Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 108 additions & 16 deletions PtyLab/ExperimentalData/ExperimentalData.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@ class ExperimentalData:
"""
Store experimental data and geometry for a PtyLab reconstruction.

The class defines the experimental fields required for conventional
ptychography (CPM) or Fourier ptychography (FPM), loads them from an HDF5
dataset, and derives basic detector and acquisition quantities used by the
reconstruction.
The class defines the dataset fields required for conventional ptychography
(CPM) and Fourier ptychography (FPM), loads them from an HDF5 dataset, and
derives detector and dataset quantities used during reconstruction.

Args:
filename (str or Path, optional):
Expand Down Expand Up @@ -65,11 +64,32 @@ class ExperimentalData:
zo (float):
Sample-to-detector distance in meters. Available for CPM datasets.

entrancePupilDiameter (float or None):
Effective probe diameter used for probe initialization. Optional for CPM datasets, not used in FPM.

spectralDensity (np.ndarray or None):
Spectral information used for polychromatic reconstruction. Optional for CPM datasets, not used in FPM.

theta (float or None):
Sample tilt or incidence-angle parameter used for reflection-mode. Optional for CPM datasets, not used in FPM.

emptyBeam (np.ndarray or None):
Reference illumination or probe image. Optional for CPM datasets, not used in FPM.

zled (float):
LED-to-sample distance in meters. Available for FPM datasets.

magnification (float):
Microscope magnification. Available for FPM datasets.

NA (float or None):
Microscope numerical aperture optional for FPM. If not provided, it is estimated from the Fourier-space pupil diameter during reconstruction.

energyAtPos (np.ndarray):
Integrated intensity of each measurement frame.

maxProbePower (float):
Maximum integrated-amplitude scale derived from the ptychogram.

Raises:
ValueError:
Expand Down Expand Up @@ -273,8 +293,21 @@ def cropCenter(self, size):

def binData(self, binning):
'''
:param binning: Binning parameter (int, e.g. 2)
:return:
Spatially bin each diffraction pattern by averaging neighboring pixels.

Each ``binning × binning`` detector region is replaced by its mean value,
reducing both detector dimensions by the specified binning factor.

Args:
binning (int):
Integer binning factor applied along both detector dimensions.
The detector dimensions must be divisible by this value.

Notes:
This method modifies ``self.ptychogram`` in place.

The current implementation performs mean binning, so each output pixel
contains the average intensity of the corresponding input pixel block.
'''
Ndp = self.ptychogram.shape[0]
Ny = self.ptychogram.shape[1]
Expand All @@ -283,7 +316,7 @@ def binData(self, binning):
ptychogram_temp = np.copy(self.ptychogram)
self.ptychogram = np.zeros((Ndp, Ny // binning, Nx // binning))

# Loop through all dp
# Bin each diffraction pattern independently.
for i in range(Ndp):
temp = ptychogram_temp[i]
reshaped_temp = temp.reshape(Ny // binning, binning, Nx // binning, binning)
Expand All @@ -292,9 +325,40 @@ def binData(self, binning):

def setOrientation(self, orientation, force_contiguous=True):
"""
Sets the correct orientation. This function follows the ptypy convention.
Apply the detector orientation specified by the ptypy convention.

The orientation is applied to the last two dimensions of
``self.ptychogram`` using combinations of axis flips and transposition.

Args:
orientation (int or None):
Orientation code following the ptypy convention:

- ``0``: no transformation.
- ``1``: flip detector columns.
- ``2``: flip detector rows.
- ``3``: flip detector rows and columns.
- ``4``: transpose the detector dimensions.
- ``5``: transpose, then flip columns.
- ``6``: transpose, then flip rows.
- ``7``: transpose, then flip rows and columns.

If None, no transformation is applied.

If orientation is None, it won't change the current orientation.
force_contiguous (bool, optional):
If True, convert the transformed ptychogram to a contiguous
NumPy array. Defaults to True.

Raises:
TypeError:
If ``orientation`` is not an integer or None.

ValueError:
If ``orientation`` is not one of the supported values from
0 to 7.

Notes:
This method modifies ``self.ptychogram`` in place.
"""
if orientation is None: # do not update.
return
Expand Down Expand Up @@ -333,7 +397,17 @@ def setOrientation(self, orientation, force_contiguous=True):
self.ptychogram = np.ascontiguousarray(self.ptychogram)

def _setData(self):
"""
Update detector geometry and dataset-derived quantities.

This method derives detector coordinates, detector size, frame count,
per-frame integrated intensity, and the maximum probe-amplitude scale
from the current ``ptychogram`` and detector pixel size.

Notes:
This method should be called whenever the ptychogram shape or detector
sampling changes.
"""
# Set the detector coordinates
self.Nd = self.ptychogram.shape[-1]
# Detector coordinates 1D
Expand All @@ -352,7 +426,15 @@ def _setData(self):

def showPtychogram(self):
"""
show ptychogram.
Display the measured ptychogram stack on a logarithmic intensity scale.

The diffraction patterns are clipped to non-negative values, converted to
``log10(I + 1)`` for visualization, and displayed with an interactive
slider over the measurement frames.

Notes:
This method is intended for data inspection only and does not modify
``self.ptychogram``.
"""
xp = getArrayModule(self.ptychogram)
print(f"Min max ptychogram: {np.min(self.ptychogram)}, {self.ptychogram.max()}")
Expand All @@ -373,15 +455,25 @@ def _move_data_to_gpu(self):

def relative_intensity(self, index):
"""
Return the relative intensity of the ptychogram at index compared to the brightest one
Return the normalized mean intensity of a selected ptychogram frame.

The mean detector intensity is computed for each frame and
normalized.

Parameters
----------
index
Args:
index (int):
Index of the measurement frame.

Returns:
float:
Normalized mean intensity of the selected frame.

Notes:
The normalization is defined as

Returns
-------
``I_rel = I_mean / (mean(I_mean) + 2 * std(I_mean))``.

The normalized intensities are cached after the first call.
"""
if not hasattr(self, '_relative_intensity'):
self._relative_intensity = self.ptychogram.mean((-2,-1))
Expand Down
Loading
Loading