Skip to content

Commit

Permalink
added detector plane resampling
Browse files Browse the repository at this point in the history
  • Loading branch information
gvarnavi committed Jan 8, 2024
1 parent faef19e commit c9156dc
Show file tree
Hide file tree
Showing 12 changed files with 274 additions and 72 deletions.
4 changes: 3 additions & 1 deletion py4DSTEM/preprocess/preprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,9 @@ def resample_data_diffraction(
resampling_factor = np.array(output_size) / np.array(datacube.shape[-2:])

resampling_factor = np.concatenate(((1, 1), resampling_factor))
datacube.data = zoom(datacube.data, resampling_factor, order=1)
datacube.data = zoom(
datacube.data, resampling_factor, order=1, mode="grid-wrap", grid_mode=True
)
datacube.calibration.set_Q_pixel_size(
datacube.calibration.get_Q_pixel_size() / resampling_factor[2]
)
Expand Down
31 changes: 23 additions & 8 deletions py4DSTEM/process/phase/magnetic_ptychographic_tomography.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,8 @@ def preprocess(
self,
diffraction_intensities_shape: Tuple[int, int] = None,
reshaping_method: str = "fourier",
probe_roi_shape: Tuple[int, int] = None,
padded_diffraction_intensities_shape: Tuple[int, int] = None,
region_of_interest_shape: Tuple[int, int] = None,
dp_mask: np.ndarray = None,
fit_function: str = "plane",
plot_probe_overlaps: bool = True,
Expand Down Expand Up @@ -265,9 +266,12 @@ def preprocess(
If None, no resampling of diffraction intenstities is performed
reshaping_method: str, optional
Method to use for reshaping, either 'bin, 'bilinear', or 'fourier' (default)
probe_roi_shape, (int,int), optional
padded_diffraction_intensities_shape: (int,int), optional
Padded diffraction intensities shape.
If None, no padding is performed
region_of_interest_shape: (int,int), optional
If not None, explicitly sets region_of_interest_shape and resamples exit_waves
at the diffraction plane to allow comparison with experimental data
dp_mask: ndarray, optional
Mask for datacube intensities (Qx,Qy)
fit_function: str, optional
Expand Down Expand Up @@ -308,7 +312,9 @@ def preprocess(
# set additional metadata
self._diffraction_intensities_shape = diffraction_intensities_shape
self._reshaping_method = reshaping_method
self._probe_roi_shape = probe_roi_shape
self._padded_diffraction_intensities_shape = (
padded_diffraction_intensities_shape
)
self._dp_mask = dp_mask

if self._datacube is None:
Expand Down Expand Up @@ -350,11 +356,20 @@ def preprocess(
roi_shape = self._datacube[0].Qshape
if diffraction_intensities_shape is not None:
roi_shape = diffraction_intensities_shape
if probe_roi_shape is not None:
roi_shape = tuple(max(q, s) for q, s in zip(roi_shape, probe_roi_shape))
if padded_diffraction_intensities_shape is not None:
roi_shape = tuple(
max(q, s)
for q, s in zip(roi_shape, padded_diffraction_intensities_shape)
)

self._amplitudes = xp.empty((self._num_diffraction_patterns,) + roi_shape)
self._region_of_interest_shape = np.array(roi_shape)

if region_of_interest_shape is not None:
self._resample_exit_waves = True
self._region_of_interest_shape = np.array(region_of_interest_shape)
else:
self._resample_exit_waves = False
self._region_of_interest_shape = np.array(self._amplitudes.shape[-2:])

# TO-DO: generalize this
if force_com_shifts is None:
Expand All @@ -381,7 +396,7 @@ def preprocess(
self._datacube[index],
diffraction_intensities_shape=self._diffraction_intensities_shape,
reshaping_method=self._reshaping_method,
probe_roi_shape=self._probe_roi_shape,
padded_diffraction_intensities_shape=self._padded_diffraction_intensities_shape,
vacuum_probe_intensity=self._vacuum_probe_intensity,
dp_mask=self._dp_mask,
com_shifts=force_com_shifts[index],
Expand All @@ -397,7 +412,7 @@ def preprocess(
self._datacube[index],
diffraction_intensities_shape=self._diffraction_intensities_shape,
reshaping_method=self._reshaping_method,
probe_roi_shape=self._probe_roi_shape,
padded_diffraction_intensities_shape=self._padded_diffraction_intensities_shape,
vacuum_probe_intensity=None,
dp_mask=None,
com_shifts=force_com_shifts[index],
Expand Down
33 changes: 24 additions & 9 deletions py4DSTEM/process/phase/magnetic_ptychography.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ def preprocess(
self,
diffraction_intensities_shape: Tuple[int, int] = None,
reshaping_method: str = "fourier",
probe_roi_shape: Tuple[int, int] = None,
padded_diffraction_intensities_shape: Tuple[int, int] = None,
region_of_interest_shape: Tuple[int, int] = None,
dp_mask: np.ndarray = None,
fit_function: str = "plane",
plot_rotation: bool = True,
Expand Down Expand Up @@ -244,10 +245,13 @@ def preprocess(
Pixel dimensions (Qx',Qy') of the resampled diffraction intensities
If None, no resampling of diffraction intenstities is performed
reshaping_method: str, optional
Method to use for reshaping, either 'bin', 'bilinear', or 'fourier' (default)
probe_roi_shape, (int,int), optional
Method to use for reshaping, either 'bin, 'bilinear', or 'fourier' (default)
padded_diffraction_intensities_shape: (int,int), optional
Padded diffraction intensities shape.
If None, no padding is performed
region_of_interest_shape: (int,int), optional
If not None, explicitly sets region_of_interest_shape and resamples exit_waves
at the diffraction plane to allow comparison with experimental data
dp_mask: ndarray, optional
Mask for datacube intensities (Qx,Qy)
fit_function: str, optional
Expand Down Expand Up @@ -291,7 +295,9 @@ def preprocess(
# set additional metadata
self._diffraction_intensities_shape = diffraction_intensities_shape
self._reshaping_method = reshaping_method
self._probe_roi_shape = probe_roi_shape
self._padded_diffraction_intensities_shape = (
padded_diffraction_intensities_shape
)
self._dp_mask = dp_mask

if self._datacube is None:
Expand Down Expand Up @@ -374,11 +380,20 @@ def preprocess(
roi_shape = self._datacube[0].Qshape
if diffraction_intensities_shape is not None:
roi_shape = diffraction_intensities_shape
if probe_roi_shape is not None:
roi_shape = tuple(max(q, s) for q, s in zip(roi_shape, probe_roi_shape))
if padded_diffraction_intensities_shape is not None:
roi_shape = tuple(
max(q, s)
for q, s in zip(roi_shape, padded_diffraction_intensities_shape)
)

self._amplitudes = xp.empty((self._num_diffraction_patterns,) + roi_shape)
self._region_of_interest_shape = np.array(roi_shape)

if region_of_interest_shape is not None:
self._resample_exit_waves = True
self._region_of_interest_shape = np.array(region_of_interest_shape)
else:
self._resample_exit_waves = False
self._region_of_interest_shape = np.array(self._amplitudes.shape[-2:])

# TO-DO: generalize this
if force_com_shifts is None:
Expand Down Expand Up @@ -408,7 +423,7 @@ def preprocess(
self._datacube[index],
diffraction_intensities_shape=self._diffraction_intensities_shape,
reshaping_method=self._reshaping_method,
probe_roi_shape=self._probe_roi_shape,
padded_diffraction_intensities_shape=self._padded_diffraction_intensities_shape,
vacuum_probe_intensity=self._vacuum_probe_intensity,
dp_mask=self._dp_mask,
com_shifts=force_com_shifts[index],
Expand All @@ -424,7 +439,7 @@ def preprocess(
self._datacube[index],
diffraction_intensities_shape=self._diffraction_intensities_shape,
reshaping_method=self._reshaping_method,
probe_roi_shape=self._probe_roi_shape,
padded_diffraction_intensities_shape=self._padded_diffraction_intensities_shape,
vacuum_probe_intensity=None,
dp_mask=None,
com_shifts=force_com_shifts[index],
Expand Down
22 changes: 17 additions & 5 deletions py4DSTEM/process/phase/mixedstate_multislice_ptychography.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,8 @@ def preprocess(
self,
diffraction_intensities_shape: Tuple[int, int] = None,
reshaping_method: str = "fourier",
probe_roi_shape: Tuple[int, int] = None,
padded_diffraction_intensities_shape: Tuple[int, int] = None,
region_of_interest_shape: Tuple[int, int] = None,
dp_mask: np.ndarray = None,
fit_function: str = "plane",
plot_center_of_mass: str = "default",
Expand Down Expand Up @@ -314,9 +315,12 @@ def preprocess(
If None, no resampling of diffraction intenstities is performed
reshaping_method: str, optional
Method to use for reshaping, either 'bin, 'bilinear', or 'fourier' (default)
probe_roi_shape, (int,int), optional
padded_diffraction_intensities_shape: (int,int), optional
Padded diffraction intensities shape.
If None, no padding is performed
region_of_interest_shape: (int,int), optional
If not None, explicitly sets region_of_interest_shape and resamples exit_waves
at the diffraction plane to allow comparison with experimental data
dp_mask: ndarray, optional
Mask for datacube intensities (Qx,Qy)
fit_function: str, optional
Expand Down Expand Up @@ -363,7 +367,9 @@ def preprocess(
# set additional metadata
self._diffraction_intensities_shape = diffraction_intensities_shape
self._reshaping_method = reshaping_method
self._probe_roi_shape = probe_roi_shape
self._padded_diffraction_intensities_shape = (
padded_diffraction_intensities_shape
)
self._dp_mask = dp_mask

if self._datacube is None:
Expand All @@ -387,7 +393,7 @@ def preprocess(
self._datacube,
diffraction_intensities_shape=self._diffraction_intensities_shape,
reshaping_method=self._reshaping_method,
probe_roi_shape=self._probe_roi_shape,
padded_diffraction_intensities_shape=self._padded_diffraction_intensities_shape,
vacuum_probe_intensity=self._vacuum_probe_intensity,
dp_mask=self._dp_mask,
com_shifts=force_com_shifts,
Expand Down Expand Up @@ -460,7 +466,13 @@ def preprocess(

# explicitly delete namespace
self._num_diffraction_patterns = self._amplitudes.shape[0]
self._region_of_interest_shape = np.array(self._amplitudes.shape[-2:])

if region_of_interest_shape is not None:
self._resample_exit_waves = True
self._region_of_interest_shape = np.array(region_of_interest_shape)
else:
self._resample_exit_waves = False
self._region_of_interest_shape = np.array(self._amplitudes.shape[-2:])
del self._intensities

# initialize probe positions
Expand Down
17 changes: 13 additions & 4 deletions py4DSTEM/process/phase/mixedstate_ptychography.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ def preprocess(
self,
diffraction_intensities_shape: Tuple[int, int] = None,
reshaping_method: str = "fourier",
probe_roi_shape: Tuple[int, int] = None,
padded_diffraction_intensities_shape: Tuple[int, int] = None,
region_of_interest_shape: Tuple[int, int] = None,
dp_mask: np.ndarray = None,
fit_function: str = "plane",
plot_center_of_mass: str = "default",
Expand Down Expand Up @@ -304,7 +305,9 @@ def preprocess(
# set additional metadata
self._diffraction_intensities_shape = diffraction_intensities_shape
self._reshaping_method = reshaping_method
self._probe_roi_shape = probe_roi_shape
self._padded_diffraction_intensities_shape = (
padded_diffraction_intensities_shape
)
self._dp_mask = dp_mask

if self._datacube is None:
Expand All @@ -328,7 +331,7 @@ def preprocess(
self._datacube,
diffraction_intensities_shape=self._diffraction_intensities_shape,
reshaping_method=self._reshaping_method,
probe_roi_shape=self._probe_roi_shape,
padded_diffraction_intensities_shape=self._padded_diffraction_intensities_shape,
vacuum_probe_intensity=self._vacuum_probe_intensity,
dp_mask=self._dp_mask,
com_shifts=force_com_shifts,
Expand Down Expand Up @@ -401,7 +404,13 @@ def preprocess(

# explicitly delete namespace
self._num_diffraction_patterns = self._amplitudes.shape[0]
self._region_of_interest_shape = np.array(self._amplitudes.shape[-2:])

if region_of_interest_shape is not None:
self._resample_exit_waves = True
self._region_of_interest_shape = np.array(region_of_interest_shape)
else:
self._resample_exit_waves = False
self._region_of_interest_shape = np.array(self._amplitudes.shape[-2:])
del self._intensities

# initialize probe positions
Expand Down
22 changes: 17 additions & 5 deletions py4DSTEM/process/phase/multislice_ptychography.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,8 @@ def preprocess(
self,
diffraction_intensities_shape: Tuple[int, int] = None,
reshaping_method: str = "fourier",
probe_roi_shape: Tuple[int, int] = None,
padded_diffraction_intensities_shape: Tuple[int, int] = None,
region_of_interest_shape: Tuple[int, int] = None,
dp_mask: np.ndarray = None,
fit_function: str = "plane",
plot_center_of_mass: str = "default",
Expand Down Expand Up @@ -289,9 +290,12 @@ def preprocess(
If None, no resampling of diffraction intenstities is performed
reshaping_method: str, optional
Method to use for reshaping, either 'bin, 'bilinear', or 'fourier' (default)
probe_roi_shape, (int,int), optional
padded_diffraction_intensities_shape: (int,int), optional
Padded diffraction intensities shape.
If None, no padding is performed
region_of_interest_shape: (int,int), optional
If not None, explicitly sets region_of_interest_shape and resamples exit_waves
at the diffraction plane to allow comparison with experimental data
dp_mask: ndarray, optional
Mask for datacube intensities (Qx,Qy)
fit_function: str, optional
Expand Down Expand Up @@ -338,7 +342,9 @@ def preprocess(
# set additional metadata
self._diffraction_intensities_shape = diffraction_intensities_shape
self._reshaping_method = reshaping_method
self._probe_roi_shape = probe_roi_shape
self._padded_diffraction_intensities_shape = (
padded_diffraction_intensities_shape
)
self._dp_mask = dp_mask

if self._datacube is None:
Expand All @@ -362,7 +368,7 @@ def preprocess(
self._datacube,
diffraction_intensities_shape=self._diffraction_intensities_shape,
reshaping_method=self._reshaping_method,
probe_roi_shape=self._probe_roi_shape,
padded_diffraction_intensities_shape=self._padded_diffraction_intensities_shape,
vacuum_probe_intensity=self._vacuum_probe_intensity,
dp_mask=self._dp_mask,
com_shifts=force_com_shifts,
Expand Down Expand Up @@ -435,7 +441,13 @@ def preprocess(

# explicitly delete namespace
self._num_diffraction_patterns = self._amplitudes.shape[0]
self._region_of_interest_shape = np.array(self._amplitudes.shape[-2:])

if region_of_interest_shape is not None:
self._resample_exit_waves = True
self._region_of_interest_shape = np.array(region_of_interest_shape)
else:
self._resample_exit_waves = False
self._region_of_interest_shape = np.array(self._amplitudes.shape[-2:])
del self._intensities

# initialize probe positions
Expand Down
21 changes: 9 additions & 12 deletions py4DSTEM/process/phase/phase_base_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def _preprocess_datacube_and_vacuum_probe(
datacube,
diffraction_intensities_shape=None,
reshaping_method="fourier",
probe_roi_shape=None,
padded_diffraction_intensities_shape=None,
vacuum_probe_intensity=None,
dp_mask=None,
com_shifts=None,
Expand All @@ -153,13 +153,10 @@ def _preprocess_datacube_and_vacuum_probe(
Note this does not affect the maximum scattering wavevector (Qx*dkx,Qy*dky) = (Sx*dkx',Sy*dky'),
and thus the real-space sampling stays fixed.
The real space sampling, (dx, dy), combined with the resampled diffraction_intensities_shape,
sets the real-space probe region of interest (ROI) extent (dx*Sx, dy*Sy).
Occasionally, one may also want to specify a larger probe ROI extent, e.g when the probe
does not comfortably fit without self-ovelap artifacts, or when the scan step sizes are much
smaller than the real-space sampling (dx,dy). This can be achieved by specifying a
probe_roi_shape, which is larger than diffraction_intensities_shape, which will result in
zero-padding of the diffraction intensities.
Additionally, one may wish to zero-pad the diffraction intensity data. Note this does not increase
the information or resolution, but might be beneficial in a limited number of cases, e.g. when the
scan step sizes are much smaller than the real-space sampling (dx,dy). This can be achieved by specifying
a padded_diffraction_intensities_shape which is larger than diffraction_intensities_shape.
Parameters
----------
Expand All @@ -170,7 +167,7 @@ def _preprocess_datacube_and_vacuum_probe(
If None, no resamping is performed
reshaping method: str, optional
Reshaping method to use, one of 'bin', 'bilinear' or 'fourier' (default)
probe_roi_shape, (int,int), optional
padded_diffraction_intensities_shape, (int,int), optional
Padded diffraction intensities shape.
If None, no padding is performed
vacuum_probe_intensity, np.ndarray, optional
Expand Down Expand Up @@ -284,10 +281,10 @@ def _preprocess_datacube_and_vacuum_probe(
)
)

if probe_roi_shape is not None:
if padded_diffraction_intensities_shape is not None:
Qx, Qy = datacube.shape[-2:]
Sx, Sy = probe_roi_shape
datacube = datacube.pad_Q(output_size=probe_roi_shape)
Sx, Sy = padded_diffraction_intensities_shape
datacube = datacube.pad_Q(output_size=padded_diffraction_intensities_shape)

if vacuum_probe_intensity is not None or dp_mask is not None:
pad_kx = Sx - Qx
Expand Down
Loading

0 comments on commit c9156dc

Please sign in to comment.