From 3ec7b0bc425c2a20094c3d96237ed7df8fa19818 Mon Sep 17 00:00:00 2001 From: Colin Date: Fri, 27 Oct 2023 13:47:28 -0700 Subject: [PATCH 1/8] Fixing scale bar being plotted as slightly too long --- py4DSTEM/visualize/overlay.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/py4DSTEM/visualize/overlay.py b/py4DSTEM/visualize/overlay.py index 8421dd35b..3bec9eaee 100644 --- a/py4DSTEM/visualize/overlay.py +++ b/py4DSTEM/visualize/overlay.py @@ -832,7 +832,14 @@ def add_scalebar(ax, d): labelpos_y = y0 # Add line - ax.plot((yi, yf), (xi, xf), lw=width, color=color, alpha=alpha) + ax.plot( + (yi, yf), + (xi, xf), + color=color, + alpha=alpha, + lw=width, + solid_capstyle = 'butt', + ) # Add label if label: From 77762d4f1386e49327640361fbf49fdd2324479e Mon Sep 17 00:00:00 2001 From: Colin Date: Fri, 27 Oct 2023 13:53:03 -0700 Subject: [PATCH 2/8] Add option to skip calculating correlation array in crystal.orientation_plot() --- py4DSTEM/process/diffraction/crystal_ACOM.py | 129 +++++++++---------- 1 file changed, 64 insertions(+), 65 deletions(-) diff --git a/py4DSTEM/process/diffraction/crystal_ACOM.py b/py4DSTEM/process/diffraction/crystal_ACOM.py index 5722f3f38..78aa577ea 100644 --- a/py4DSTEM/process/diffraction/crystal_ACOM.py +++ b/py4DSTEM/process/diffraction/crystal_ACOM.py @@ -29,6 +29,7 @@ def orientation_plan( corr_kernel_size: float = 0.08, radial_power: float = 1.0, intensity_power: float = 0.25, # New default intensity power scaling + calculate_correlation_array = True, tol_peak_delete=None, tol_distance: float = 0.01, fiber_axis=None, @@ -61,6 +62,8 @@ def orientation_plan( corr_kernel_size (float): Correlation kernel size length in Angstroms radial_power (float): Power for scaling the correlation intensity as a function of the peak radius intensity_power (float): Power for scaling the correlation intensity as a function of the peak intensity + calculate_correlation_array (bool): Set to false to skip calculating the correlation array. + This is useful when we only want the angular range / rotation matrices. tol_peak_delete (float): Distance to delete peaks for multiple matches. Default is kernel_size * 0.5 tol_distance (float): Distance tolerance for radial shell assignment [1/Angstroms] @@ -598,21 +601,6 @@ def orientation_plan( # init storage arrays self.orientation_rotation_angles = np.zeros((self.orientation_num_zones, 3)) self.orientation_rotation_matrices = np.zeros((self.orientation_num_zones, 3, 3)) - self.orientation_ref = np.zeros( - ( - self.orientation_num_zones, - np.size(self.orientation_shell_radii), - self.orientation_in_plane_steps, - ), - dtype="float", - ) - # self.orientation_ref_1D = np.zeros( - # ( - # self.orientation_num_zones, - # np.size(self.orientation_shell_radii), - # ), - # dtype="float", - # ) # If possible, Get symmetry operations for this spacegroup, store in matrix form if self.pymatgen_available: @@ -697,65 +685,76 @@ def orientation_plan( k0 = np.array([0.0, 0.0, -1.0 / self.wavelength]) n = np.array([0.0, 0.0, -1.0]) - for a0 in tqdmnd( - np.arange(self.orientation_num_zones), - desc="Orientation plan", - unit=" zone axes", - disable=not progress_bar, - ): - # reciprocal lattice spots and excitation errors - g = self.orientation_rotation_matrices[a0, :, :].T @ self.g_vec_all - sg = self.excitation_errors(g) - - # Keep only points that will contribute to this orientation plan slice - keep = np.abs(sg) < self.orientation_kernel_size - - # in-plane rotation angle - phi = np.arctan2(g[1, :], g[0, :]) - - # Loop over all peaks - for a1 in np.arange(self.g_vec_all.shape[1]): - ind_radial = self.orientation_shell_index[a1] + if calculate_correlation_array: + # initialize empty correlation array + self.orientation_ref = np.zeros( + ( + self.orientation_num_zones, + np.size(self.orientation_shell_radii), + self.orientation_in_plane_steps, + ), + dtype="float", + ) - if keep[a1] and ind_radial >= 0: - # 2D orientation plan - self.orientation_ref[a0, ind_radial, :] += ( - np.power(self.orientation_shell_radii[ind_radial], radial_power) - * np.power(self.struct_factors_int[a1], intensity_power) - * np.maximum( - 1 - - np.sqrt( - sg[a1] ** 2 - + ( - ( - np.mod( - self.orientation_gamma - phi[a1] + np.pi, - 2 * np.pi, + for a0 in tqdmnd( + np.arange(self.orientation_num_zones), + desc="Orientation plan", + unit=" zone axes", + disable=not progress_bar, + ): + # reciprocal lattice spots and excitation errors + g = self.orientation_rotation_matrices[a0, :, :].T @ self.g_vec_all + sg = self.excitation_errors(g) + + # Keep only points that will contribute to this orientation plan slice + keep = np.abs(sg) < self.orientation_kernel_size + + # in-plane rotation angle + phi = np.arctan2(g[1, :], g[0, :]) + + # Loop over all peaks + for a1 in np.arange(self.g_vec_all.shape[1]): + ind_radial = self.orientation_shell_index[a1] + + if keep[a1] and ind_radial >= 0: + # 2D orientation plan + self.orientation_ref[a0, ind_radial, :] += ( + np.power(self.orientation_shell_radii[ind_radial], radial_power) + * np.power(self.struct_factors_int[a1], intensity_power) + * np.maximum( + 1 + - np.sqrt( + sg[a1] ** 2 + + ( + ( + np.mod( + self.orientation_gamma - phi[a1] + np.pi, + 2 * np.pi, + ) + - np.pi ) - - np.pi + * self.orientation_shell_radii[ind_radial] ) - * self.orientation_shell_radii[ind_radial] + ** 2 ) - ** 2 + / self.orientation_kernel_size, + 0, ) - / self.orientation_kernel_size, - 0, ) - ) - orientation_ref_norm = np.sqrt(np.sum(self.orientation_ref[a0, :, :] ** 2)) - if orientation_ref_norm > 0: - self.orientation_ref[a0, :, :] /= orientation_ref_norm + orientation_ref_norm = np.sqrt(np.sum(self.orientation_ref[a0, :, :] ** 2)) + if orientation_ref_norm > 0: + self.orientation_ref[a0, :, :] /= orientation_ref_norm - # Maximum value - self.orientation_ref_max = np.max(np.real(self.orientation_ref)) + # Maximum value + self.orientation_ref_max = np.max(np.real(self.orientation_ref)) - # Fourier domain along angular axis - if self.CUDA: - self.orientation_ref = cp.asarray(self.orientation_ref) - self.orientation_ref = cp.conj(cp.fft.fft(self.orientation_ref)) - else: - self.orientation_ref = np.conj(np.fft.fft(self.orientation_ref)) + # Fourier domain along angular axis + if self.CUDA: + self.orientation_ref = cp.asarray(self.orientation_ref) + self.orientation_ref = cp.conj(cp.fft.fft(self.orientation_ref)) + else: + self.orientation_ref = np.conj(np.fft.fft(self.orientation_ref)) def match_orientations( From 0c84848e9f1152e0441a4aa228cbb7bfdd1ea4fa Mon Sep 17 00:00:00 2001 From: Colin Date: Fri, 27 Oct 2023 13:54:39 -0700 Subject: [PATCH 3/8] Black formatting --- py4DSTEM/process/diffraction/crystal_ACOM.py | 2 +- py4DSTEM/visualize/overlay.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/py4DSTEM/process/diffraction/crystal_ACOM.py b/py4DSTEM/process/diffraction/crystal_ACOM.py index 78aa577ea..60c284263 100644 --- a/py4DSTEM/process/diffraction/crystal_ACOM.py +++ b/py4DSTEM/process/diffraction/crystal_ACOM.py @@ -29,7 +29,7 @@ def orientation_plan( corr_kernel_size: float = 0.08, radial_power: float = 1.0, intensity_power: float = 0.25, # New default intensity power scaling - calculate_correlation_array = True, + calculate_correlation_array=True, tol_peak_delete=None, tol_distance: float = 0.01, fiber_axis=None, diff --git a/py4DSTEM/visualize/overlay.py b/py4DSTEM/visualize/overlay.py index 3bec9eaee..32baff443 100644 --- a/py4DSTEM/visualize/overlay.py +++ b/py4DSTEM/visualize/overlay.py @@ -833,12 +833,12 @@ def add_scalebar(ax, d): # Add line ax.plot( - (yi, yf), - (xi, xf), - color=color, + (yi, yf), + (xi, xf), + color=color, alpha=alpha, lw=width, - solid_capstyle = 'butt', + solid_capstyle="butt", ) # Add label From 958642e25a56b84a28e4b6390c5550948794a747 Mon Sep 17 00:00:00 2001 From: alex-rakowski Date: Fri, 27 Oct 2023 15:05:18 -0700 Subject: [PATCH 4/8] adding assert statement --- py4DSTEM/process/diffraction/crystal_ACOM.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/py4DSTEM/process/diffraction/crystal_ACOM.py b/py4DSTEM/process/diffraction/crystal_ACOM.py index 60c284263..0c01dc70d 100644 --- a/py4DSTEM/process/diffraction/crystal_ACOM.py +++ b/py4DSTEM/process/diffraction/crystal_ACOM.py @@ -900,9 +900,13 @@ def match_single_pattern( Orientation class containing all outputs fig, ax: handles Figure handles for the plotting output - """ + """ + + # adding assert statement for checking self.orientation_ref is present + assert hasattr( + self, "orientation_ref" + ), "orientation_plan must be run with 'calculate_correlation_array=True'" - # init orientation output orientation = Orientation(num_matches=num_matches_return) if bragg_peaks.data.shape[0] < min_number_peaks: return orientation From 329034299cb3f676233a9117d343d3238afaa611 Mon Sep 17 00:00:00 2001 From: alex-rakowski Date: Fri, 27 Oct 2023 15:09:17 -0700 Subject: [PATCH 5/8] black --- py4DSTEM/process/diffraction/crystal_ACOM.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py4DSTEM/process/diffraction/crystal_ACOM.py b/py4DSTEM/process/diffraction/crystal_ACOM.py index 0c01dc70d..cba68d8fb 100644 --- a/py4DSTEM/process/diffraction/crystal_ACOM.py +++ b/py4DSTEM/process/diffraction/crystal_ACOM.py @@ -900,7 +900,7 @@ def match_single_pattern( Orientation class containing all outputs fig, ax: handles Figure handles for the plotting output - """ + """ # adding assert statement for checking self.orientation_ref is present assert hasattr( From a23839e5ca0c9c21d3802f9df302b12dd7d5522e Mon Sep 17 00:00:00 2001 From: alex-rakowski Date: Mon, 30 Oct 2023 10:56:33 -0700 Subject: [PATCH 6/8] changing assert to warning --- py4DSTEM/process/diffraction/crystal_ACOM.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/py4DSTEM/process/diffraction/crystal_ACOM.py b/py4DSTEM/process/diffraction/crystal_ACOM.py index cba68d8fb..0dcf5dad0 100644 --- a/py4DSTEM/process/diffraction/crystal_ACOM.py +++ b/py4DSTEM/process/diffraction/crystal_ACOM.py @@ -903,10 +903,12 @@ def match_single_pattern( """ # adding assert statement for checking self.orientation_ref is present - assert hasattr( + # adding assert statement for checking self.orientation_ref is present + if not hasattr( self, "orientation_ref" - ), "orientation_plan must be run with 'calculate_correlation_array=True'" - + ): + raise Warning("orientation_plan must be run with 'calculate_correlation_array=True'") + orientation = Orientation(num_matches=num_matches_return) if bragg_peaks.data.shape[0] < min_number_peaks: return orientation From 7ca7edb2a4259e1d44efd8b671b4c561bb9767f6 Mon Sep 17 00:00:00 2001 From: alex-rakowski Date: Mon, 30 Oct 2023 10:57:11 -0700 Subject: [PATCH 7/8] black --- py4DSTEM/process/diffraction/crystal_ACOM.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/py4DSTEM/process/diffraction/crystal_ACOM.py b/py4DSTEM/process/diffraction/crystal_ACOM.py index 0dcf5dad0..650fe0583 100644 --- a/py4DSTEM/process/diffraction/crystal_ACOM.py +++ b/py4DSTEM/process/diffraction/crystal_ACOM.py @@ -903,12 +903,12 @@ def match_single_pattern( """ # adding assert statement for checking self.orientation_ref is present - # adding assert statement for checking self.orientation_ref is present - if not hasattr( - self, "orientation_ref" - ): - raise Warning("orientation_plan must be run with 'calculate_correlation_array=True'") - + # adding assert statement for checking self.orientation_ref is present + if not hasattr(self, "orientation_ref"): + raise Warning( + "orientation_plan must be run with 'calculate_correlation_array=True'" + ) + orientation = Orientation(num_matches=num_matches_return) if bragg_peaks.data.shape[0] < min_number_peaks: return orientation From 7bd2ceb7bdc4296038ed74917653f8487a8f60d4 Mon Sep 17 00:00:00 2001 From: Steven Zeltmann Date: Mon, 30 Oct 2023 16:55:35 -0400 Subject: [PATCH 8/8] change Warning to ValueError --- py4DSTEM/process/diffraction/crystal_ACOM.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py4DSTEM/process/diffraction/crystal_ACOM.py b/py4DSTEM/process/diffraction/crystal_ACOM.py index 650fe0583..49be73b99 100644 --- a/py4DSTEM/process/diffraction/crystal_ACOM.py +++ b/py4DSTEM/process/diffraction/crystal_ACOM.py @@ -905,7 +905,7 @@ def match_single_pattern( # adding assert statement for checking self.orientation_ref is present # adding assert statement for checking self.orientation_ref is present if not hasattr(self, "orientation_ref"): - raise Warning( + raise ValueError( "orientation_plan must be run with 'calculate_correlation_array=True'" )