Skip to content
Closed
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
4 changes: 2 additions & 2 deletions PtyLab/Engines/BaseEngine.py
Original file line number Diff line number Diff line change
Expand Up @@ -1577,7 +1577,7 @@ def decompressionProjection(self, positionIndex):
axis=-2,
)

def showReconstruction(self, loop):
def showReconstruction(self, loop, force=False):
"""
Update reconstruction monitoring and optional iteration output.

Expand All @@ -1597,7 +1597,7 @@ def showReconstruction(self, loop):
loop (int):
Current reconstruction iteration.
"""
if np.mod(loop, self.monitor.figureUpdateFrequency) == 0:
if force or np.mod(loop, self.monitor.figureUpdateFrequency) == 0:
if self.experimentalData.operationMode == "FPM":
object_estimate = np.squeeze(
asNumpyArray(
Expand Down
12 changes: 12 additions & 0 deletions PtyLab/Engines/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"OPR",
"qNewton",
"zPIE",
"purityPIE",
]
from .e3PIE import e3PIE
from .ePIE import ePIE
Expand All @@ -25,3 +26,14 @@
from .OPR import OPR
from .qNewton import qNewton
from .zPIE import zPIE
from .purityPIE import purityPIE


import warnings

warnings.warn(
"`pcPIE` is deprecated. Use `mPIE` with "
"`params.positionCorrectionSwitch = True` instead.",
DeprecationWarning,
stacklevel=2,
)
88 changes: 82 additions & 6 deletions PtyLab/Engines/aPIE.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,46 @@


class aPIE(BaseEngine):
"""
aPIE: angle correction PIE: ePIE combined with Luus-Jaakola algorithm (the latter for angle correction) + momentum
r"""
Angle-corrected ptychographic iterative engine (aPIE).

`aPIE` extends the standard PIE reconstruction by jointly refining the
object, probe, and detector tilt angle. The angular correction is based on
a Luus-Jaakola-type stochastic search combined with momentum
acceleration.[^debeurs2022]

The detector tilt is described by the angle `reconstruction.theta`. For
each reconstruction iteration, two candidate angles are evaluated: the
current angle and a randomly perturbed angle within the current search
radius. The diffraction data are transformed into the corresponding
detector coordinates for each candidate, followed by a standard PIE
object/probe reconstruction.

The candidate producing the lower reconstruction error is retained. The
angular update is then combined with a momentum term according to

$$
\theta_{\mathrm{mom}}^{(k+1)} = f\,\Delta\theta_k + \gamma\,\theta_{\mathrm{mom}}^{(k)}
$$

where `f = feedback`, `\gamma = aPIEfriction`, and `\Delta\theta_k` is the
accepted angular change.

The angular search radius is gradually reduced from
`thetaSearchRadiusMax` to `thetaSearchRadiusMin` over the reconstruction
iterations, allowing coarse angular exploration at the beginning and
progressively finer correction toward convergence.

The evolution of the estimated detector angle is stored in
`reconstruction.thetaHistory`.

Angle correction requires an initial value of `reconstruction.theta`.

[^debeurs2022]: A. de Beurs, L. Loetgering, M. Herczog,
M. Du, K. S. E. Eikema, and S. Witte,
"aPIE: an angle calibration algorithm for reflection ptychography,"
Opt. Lett. 47, 1949-1952 (2022).
https://doi.org/10.1364/OL.453655
"""

def __init__(
Expand All @@ -41,8 +79,6 @@ def __init__(
params: Params,
monitor: Monitor,
):
# This contains reconstruction parameters that are specific to the reconstruction
# but not necessarily to aPIE reconstruction
super().__init__(reconstruction, experimentalData, params, monitor)
self.logger = logging.getLogger("aPIE")
self.logger.info("Sucesfully created aPIE aPIE_engine")
Expand All @@ -51,8 +87,20 @@ def __init__(

def initializeReconstructionParams(self):
"""
Set parameters that are specific to the ePIE settings.
:return:
Initialize parameters specific to the aPIE reconstruction.

This method sets the object and probe update strengths, angular momentum
parameters, reconstruction length, and angular search-radius limits. It
also initializes the detector-angle momentum and history if they are not
already present.

A copy of the original ptychogram is stored in
`self.ptychogramUntransformed` for repeated angle-dependent coordinate
transformations during reconstruction.

Raises:
ValueError:
If `reconstruction.theta` has not been initialized.
"""
self.betaProbe = 0.25
self.betaObject = 0.25
Expand All @@ -74,6 +122,34 @@ def initializeReconstructionParams(self):
raise ValueError("theta value is not given")

def doReconstruction(self):
"""
Run the aPIE reconstruction with iterative detector-angle correction.

The reconstruction starts from the current detector angle
`reconstruction.theta` and gradually reduces the angular search radius
from `thetaSearchRadiusMax` to `thetaSearchRadiusMin` over the requested
number of iterations.

At each iteration, two candidate detector angles are evaluated: the
current angle and a randomly perturbed angle within the current search
radius, both including the accumulated angular momentum.

For each candidate angle, the original ptychogram is transformed into the
corresponding detector coordinates. A standard PIE reconstruction is then
performed over all scan positions, including object and probe updates,
constraint application, and reconstruction-error evaluation.

The candidate producing the lower reconstruction error is retained. The
accepted angular change is used to update `reconstruction.thetaMomentum`,
which contributes to the candidate angles in the following iteration.

The accepted detector angle is appended to
`reconstruction.thetaHistory`, and the reconstruction monitor is updated
throughout the optimization.

If GPU acceleration is enabled, the reconstruction data are returned to
CPU memory after completion.
"""
self._prepareReconstruction()

xp = getArrayModule(self.reconstruction.object)
Expand Down
15 changes: 0 additions & 15 deletions PtyLab/Engines/ePIE.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,21 +73,6 @@ def __init__(
params: Params,
monitor: Monitor,
):
"""
Initialize the ePIE reconstruction engine.

Args:
reconstruction (Reconstruction):
Reconstruction state containing the current object, probe, and
geometry.
experimentalData (ExperimentalData):
Experimental diffraction data and acquisition parameters.
params (Params):
Shared reconstruction parameters and constraint settings.
monitor (Monitor):
Monitor used for reconstruction visualization and progress
reporting.
"""
super().__init__(reconstruction, experimentalData, params, monitor)
self.logger = logging.getLogger("ePIE")
self.logger.info("Sucesfully created ePIE ePIE_engine")
Expand Down
25 changes: 1 addition & 24 deletions PtyLab/Engines/mPIE.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,29 +105,6 @@ def __init__(
params: Params,
monitor: Monitor,
):
"""
Initialize the mPIE reconstruction engine.

Shared reconstruction state is initialized through `BaseEngine`, followed
by the mPIE-specific reconstruction parameters and momentum buffers.

Momentum acceleration is enabled through
`params.momentumAcceleration`, allowing shared BaseEngine operations such
as modal orthogonalization to keep the corresponding momentum and buffer
arrays consistent with the reconstructed object and probe.

Args:
reconstruction (Reconstruction):
Reconstruction state containing the current object, probe, and
geometry.
experimentalData (ExperimentalData):
Experimental diffraction data and acquisition parameters.
params (Params):
Shared reconstruction parameters and constraint settings.
monitor (Monitor):
Monitor used for reconstruction visualization and progress
reporting.
"""
super().__init__(reconstruction, experimentalData, params, monitor)
self.logger = logging.getLogger("mPIE")
self.logger.info("Successfully created mPIE engine")
Expand Down Expand Up @@ -564,7 +541,7 @@ def probeUpdate(self, objectPatch: np.ndarray, DELTA: np.ndarray, weight: float)

class pcPIE(mPIE):
"""
Backward-compatible wrapper for :class:`mPIE`.
Backward-compatible wrapper for `mPIE`.

Position correction is now provided by `mPIE` through
`params.positionCorrectionSwitch`. This class is retained only for
Expand Down
Loading
Loading