Fitting models clean - #273
Conversation
Digital Dark Field functions introduced
Restructured and some cluster support
missed import
missed import
Double import
bugfix (relics of old code)
Added the function to read pointsarrays from py4DSTEM and fixed a minor bug in cluster real space plot
|
And don't change "vector.py" in response to this. I initially changed it and then changed it back, so it looks changed but isn't. All the new stuff in in digital_dark_field_cluster.py and init.py was changed in diffraction to import the new functions into the repo |
Now writing cluster labels into the vector at L1
Complete set of functions using new img reduction method. Maybe I should also make a new method to reduce a selection to a diffraction pattern.
|
So, functions rebuilt to work with a new image reduce method in Vector and all built out to L2 clustering with two methods. The image reduce could be generalised, and an option for reducing to a diffraction pattern could also be made. |
There was a problem hiding this comment.
Hi Ian, overall looks good! I'm leaving a few comments in the files where errors would occur. A few more general things:
- We are also in the process of moving
Vectorover to being basetorch, (see #272) That will cause a problem next time you try and merge from dev, but I think an LLM should be able to adapt what you've added totorchwithout many issues. I don't think this needs to be solved now. - a lot of the things i point out in comments would be caught with a simple pre-commit. I would suggest checking out the CONTRIBUTING.md or just install and run
ruff. - as a smaller thing, please refer to PEP8 for a style guide and conventions for naming (e.g. in the
DBSCAN_L2function) - please write a few tests for DDF (or have an LLM do so for you)
| from quantem.diffraction.strain_autocorrelation import StrainMapAutocorrelation as StrainMapAutocorrelation | ||
| from quantem.diffraction.model_fitting import ModelDiffraction as ModelDiffraction No newline at end of file | ||
| from quantem.diffraction.model_fitting import ModelDiffraction as ModelDiffraction | ||
| from quantem.diffraction.digital_dark_field_cluster import * No newline at end of file |
There was a problem hiding this comment.
Please do not import * , if you want certain features elevated in the namespace please import specific items (as is done in this file)
There was a problem hiding this comment.
fair dos. Will name everything explicitly.
|
|
||
| from tqdm import tqdm | ||
|
|
||
| from sklearn.cluster import DBSCAN |
There was a problem hiding this comment.
sklearn isn't a dependency of quantem, so please guard the import with an error message saying something like "if you want to use this feature, please install scikit-learn to your environment"
There was a problem hiding this comment.
I really suggest that you consider having scikit-learn as a dependency so we can leverage the tools they have built rather than having to reinvent the wheel ourselves.
Of course, that means we might have to take torch tensors and transform to numpy to access this, but my initial attempt at getting DBSCAN written for torch didn't work well. Maybe this can be done eventually, but until then, scikit-learn is the best show on the road for clustering algorithms.
|
|
||
| from tqdm import tqdm | ||
|
|
||
| from sklearn.cluster import DBSCAN |
There was a problem hiding this comment.
sklearn isn't a dependency of quantem, so please guard the import with an error message saying something like "if you want to use this feature, please install scikit-learn to your environment"
| assert isinstance(fig, Figure) | ||
| assert isinstance(ax, Axes) |
There was a problem hiding this comment.
these lines throw an import error
| if ordering == "sequential": | ||
| cluster_list = unique_labels[1:] | ||
| elif ordering == "size": | ||
| cluster_list = L1_unique_labels[1:][np.argsort(L1_all_cluster_sizes[1:])[::-1]] |
|
|
||
| """ | ||
| assert isinstance(maskstack, np.ndarray), "the maskstack must be a numpy array" | ||
| assert maskstack.shape[-1] == pointsvector.flatten.shape[1], "the mask size does not match the Vector size" |
There was a problem hiding this comment.
should be .flatten(), and i'm not actually sure it's comparing row to row
|
|
||
| L1_unique_labels = np.unique(L1labels)[1:] | ||
|
|
||
| COMs = np.zeros_like(np.vstack((L1_unique_labels,L1_unique_labels)).T) |
There was a problem hiding this comment.
are COMs supposed to be integer valued? this will truncate sub-pixel offsets
| assert len(scaling)==len(fields), "the scalings and fields must have the same number of entries" | ||
|
|
||
| # We need to return a new Vector as it is changing length once we select only part of the data | ||
| pointsvector2 = pointsvector.copy() |
There was a problem hiding this comment.
this line isn't used
| plot_L1_clusters_kspace( | ||
| pointsvector2, | ||
| fields, | ||
| kr_max_plot=int(pointsvector2.select_fields('kx').flatten().max()*1.05) |
There was a problem hiding this comment.
is this meant to be kr not kx?
There was a problem hiding this comment.
Yes, this is intentional. It rather assumes the detector is square, which it probably is. In the rare cases where it is not (e.g. Merlin T4 in frame-based mode), kx_max > ky_max, so this sets the maximum radius used in deciding maximum axis limits to the largest k value possible +5%
| for rx in tqdm(range(Rshape[0])): | ||
| for ry in range(Rshape[1]): |
There was a problem hiding this comment.
I think there should be a way to vectorize this
What problem this PR addreseses
This creates a new set of functions in diffraction to provide Digital Dark Field imaging, both with manual selection and cluster analysis. It is all in one py file split into three parts:
All can be built out once the module has been accepted
The initial import is based on my own centre finding, which I can provide, but you may have code elsewhere in the repo that produces the desired kx and ky centre positions, in which case just adjust my function to use that result.
What should the reviewer(s) do