From 1d1c600a325acf9bc5c32052687d562c9964b2b1 Mon Sep 17 00:00:00 2001 From: maclariz Date: Fri, 6 Jun 2025 16:42:45 +0100 Subject: [PATCH] Update DDF v10 A small update to increase efficiency of calculation for multi-aperture arrays --- .../process/diffraction/digital_dark_field.py | 48 +++++++------------ 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/py4DSTEM/process/diffraction/digital_dark_field.py b/py4DSTEM/process/diffraction/digital_dark_field.py index cbf2778f4..9add55e08 100644 --- a/py4DSTEM/process/diffraction/digital_dark_field.py +++ b/py4DSTEM/process/diffraction/digital_dark_field.py @@ -423,30 +423,6 @@ def pointlist_to_array( return points_array -def pointlist_differences(aperture_position, points_array): - """ - calculates Euclidean distances between a specific aperture position - and a whole list of detected points for a dataset - - Parameters - ---------- - aperture_position: tuple - 2-element vector of the diffraction space shape of a position of an aperture - points_array: numpy array - as produced by pointlist_to_array and defined in docstring for that function - - Returns - ---------- - diff: numpy array - the Euclidean distances as a 1D numpy array - """ - subtractor = np.array( - [[aperture_position[0], aperture_position[1]] * points_array.shape[0]] - ).reshape((points_array.shape[0], 2)) - diff = ((points_array[:, :2] - subtractor) ** 2).sum(axis=1) ** 0.5 - return diff - - def DDFimage(points_array, aperture_positions, Rshape=None, tol=1): """ Calculates a Digital Dark Field image from a list of detected diffraction peak positions in a points_array and a list of aperture_positions, within a defined matching tolerance @@ -478,19 +454,27 @@ def DDFimage(points_array, aperture_positions, Rshape=None, tol=1): ) image = np.zeros(Rshape) + for aperture_index in tqdmnd(len(aperture_positions)): + # Pick one of the aperture positions aperture_position = aperture_positions[aperture_index] - intensities = np.vstack( + # Calculate vector differences + differences = points_array[:, :2] - aperture_position + # Calculate normalised distances + diffnorm = (differences**2).sum(axis=1) ** 0.5 + # Append these norms to the ends of each row for each spot + intensities = np.hstack( ( - points_array[:, 2:5].T, - pointlist_differences(aperture_position, points_array), + points_array[:, 2:5], + diffnorm[:, np.newaxis], ) - ).T + ) + # Delete all spots for which the norm is larger than tolerance intensities2 = np.delete(intensities, np.where(intensities[:, 3] > tol), axis=0) - for row in range(intensities2[:, 0].shape[0]): - image[ - intensities2[row, 1].astype(int), intensities2[row, 2].astype(int) - ] += intensities2[row, 0] + # Update the image with the remaining intensities sliced by the Rx and Ry positions + image[ + intensities2[:, 1].astype(int), intensities2[:, 2].astype(int) + ] += intensities2[:, 0] return image