diff --git a/.gitignore b/.gitignore index 1179d4ca..6e8f7ed2 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,6 @@ *.vscode *.venv logs_tensorboard -*.hdf5 -*.lock .python-version .DS_Store .idea @@ -18,4 +16,9 @@ site/ .cache/mkdocs-jupyter/ # misc -notes/ \ No newline at end of file +notes/ + +# files +*.hdf5 +*.png +*.lock \ No newline at end of file diff --git a/PtyLab/Engines/BaseEngine.py b/PtyLab/Engines/BaseEngine.py index 93634afc..dbc58df7 100644 --- a/PtyLab/Engines/BaseEngine.py +++ b/PtyLab/Engines/BaseEngine.py @@ -6,6 +6,7 @@ from PtyLab import Operators from PtyLab.ExperimentalData.ExperimentalData import ExperimentalData +from PtyLab.Monitor.frame import MonitorFrame from PtyLab.Monitor.Monitor import Monitor from PtyLab.Params.Params import Params from PtyLab.Reconstruction.Reconstruction import Reconstruction @@ -143,10 +144,28 @@ def __init__( self.experimentalData = experimentalData self.params = params self.monitor = monitor - self.monitor.reconstruction = reconstruction # share reconstruction state with monitor # datalogger self.logger = logging.getLogger("BaseEngine") + # messages already shown by _logOnce + self._loggedOnce = set() + + def _logOnce(self, message, *args): + """ + Log a message at INFO the first time, and at DEBUG on every repeat. + + For steps that run every iteration (e.g. probe COM stabilization), so the + output says once that the step is active instead of once per iteration. + + Args: + message (str): + Logging format string; also identifies the message. + *args: + Arguments for the format string. + """ + level = logging.DEBUG if message in self._loggedOnce else logging.INFO + self._loggedOnce.add(message) + self.logger.log(level, message, *args) def _prepareReconstruction(self): """ @@ -332,7 +351,7 @@ def _initialProbePowerCorrection(self): in frame $j$. The correction preserves the probe shape and phase while placing its total power on the scale of the experimental data, reducing large amplitude corrections at the beginning of reconstruction. - + """ if self.params.probePowerCorrectionSwitch: self.reconstruction.probe = ( @@ -399,6 +418,10 @@ def _setObjectProbeROI(self, update=False): """ Set the object and probe regions of interest used for monitoring. + The regions are stored on the engine as ``objectROI`` and ``probeROI`` + and handed to the monitor in each `MonitorFrame`. ``objectROI`` also + sets the reference region of ``params.objectContrastSwitch``. + The object ROI is derived from the scan-position extent and probe size, scaled by ``monitor.objectZoom``. The probe ROI is centered on the probe grid and derived from the entrance pupil diameter and @@ -412,9 +435,9 @@ def _setObjectProbeROI(self, update=False): If True, recompute existing ROIs. Otherwise, ROIs are only created when they are not already defined. Defaults to False. """ - if not hasattr(self.monitor, "objectROI") or update: + if getattr(self, "objectROI", None) is None or update: if self.monitor.objectZoom == "full" or self.monitor.objectZoom is None: - self.monitor.objectROI = [ + self.objectROI = [ slice(None, None, None), slice(None, None, None), ] @@ -436,7 +459,7 @@ def _setObjectProbeROI(self, update=False): / 2 ).astype(int) - # self.monitor.objectROI = [ + # self.objectROI = [ # slice( # max(0, yc - ry // 2), min(self.reconstruction.No, yc + ry // 2) # ), @@ -444,7 +467,7 @@ def _setObjectProbeROI(self, update=False): # max(0, xc - rx // 2), min(self.reconstruction.No, xc + rx // 2) # ), # ] - self.monitor.objectROI = [ + self.objectROI = [ slice( max(0, xc - rx // 2), min(self.reconstruction.No, xc + rx // 2) ), @@ -453,16 +476,16 @@ def _setObjectProbeROI(self, update=False): ), ] - if not hasattr(self.monitor, "probeROI") or update: + if getattr(self, "probeROI", None) is None or update: if self.monitor.probeZoom == "full" or self.monitor.probeZoom is None: - self.monitor.probeROI = [slice(None, None), slice(None, None)] + self.probeROI = [slice(None, None), slice(None, None)] else: r = int( self.experimentalData.entrancePupilDiameter / self.reconstruction.dxp / self.monitor.probeZoom ) - self.monitor.probeROI = [ + self.probeROI = [ slice( max(0, self.reconstruction.Np // 2 - r), min(self.reconstruction.Np, self.reconstruction.Np // 2 + r), @@ -476,35 +499,30 @@ def _setObjectProbeROI(self, update=False): def _showInitialGuesses(self): """ Display the initial object and probe estimates in the reconstruction monitor. - - The object and probe are cropped to the monitoring regions defined by - ``objectROI`` and ``probeROI`` before being passed to the monitor together - with the current reconstruction error, propagation distance, mode purities, - and scan positions. """ self.monitor.initializeMonitors() - objectEstimate = np.squeeze( - self.reconstruction.object[ - ..., self.monitor.objectROI[0], self.monitor.objectROI[1] - ] - ) - probeEstimate = np.squeeze( - self.reconstruction.probe[ - ..., self.monitor.probeROI[0], self.monitor.probeROI[1] - ] - ) + self.monitor.update(self._monitorFrame()) - self.monitor.updateObjectProbeErrorMonitor( - error=self.reconstruction.error, - object_estimate=objectEstimate, - probe_estimate=probeEstimate, - zo=self.reconstruction.zo, - purity_probe=self.reconstruction.purityProbe, - purity_object=self.reconstruction.purityObject, - encoder_positions=self.reconstruction.positions, - ) + def _monitorFrame(self, **fields): + """ + Snapshot of the current reconstruction state for the monitor. - # self.monitor.updateObjectProbeErrorMonitor() + Args: + **fields: + Further `MonitorFrame` fields, e.g. the encoder positions or the + diffraction intensities. + + Returns: + MonitorFrame: + Frame holding references to the live object and probe, with the + engine's display regions ``objectROI`` and ``probeROI``. + """ + return MonitorFrame.from_reconstruction( + self.reconstruction, + object_roi=self.objectROI, + probe_roi=self.probeROI, + **fields, + ) def _checkMISC(self): """ @@ -625,7 +643,7 @@ def _checkFFT(self): if self.experimentalData.PSD is not None: self.experimentalData.PSD = np.fft.fftshift( self.experimentalData.PSD, axes=(-1, -2) - ) + ) self.params.fftshiftFlag = 0 def _move_data_to_gpu(self): @@ -974,7 +992,6 @@ def _match_dtypes_real(self): name, value.astype(self.dtype_real, copy=False), ) - def object2detector(self, esw=None): """ @@ -1065,12 +1082,12 @@ def getBeamWidth(self): \mathrm{FWHM}_x = 2\sqrt{2\ln 2}\sigma_x $$ - The same calculation is applied along $y$. + The same calculation is applied along $y$. Returns: tuple: ``(beamWidthY, beamWidthX)`` in meters. - + Notes: For non-Gaussian probe profiles, the returned values should be interpreted as second-moment @@ -1194,7 +1211,7 @@ def getOverlap(self, ind1, ind2): self.reconstruction.areaOverlap = np.mean( abs( np.sum( - abs(Q)**2 * np.exp(-1.0j * 2 * np.pi * (Fx * sx + Fy * sy)), + abs(Q) ** 2 * np.exp(-1.0j * 2 * np.pi * (Fx * sx + Fy * sy)), axis=(-1, -2), ) ) @@ -1587,8 +1604,9 @@ def showReconstruction(self, loop): For Fourier ptychography, the object is transformed to real space before visualization. When the monitor verbosity is set to ``"high"``, the - current measured and estimated diffraction intensities, reconstruction - error, and estimated scan overlap are also displayed. + current measured and estimated diffraction intensities and the estimated + scan overlap are also sent, and the last iteration prints a summary of + the final error and overlap. If object dumping is enabled, the current reconstructed object is written to disk for each iteration. @@ -1597,92 +1615,49 @@ def showReconstruction(self, loop): loop (int): Current reconstruction iteration. """ - if np.mod(loop, self.monitor.figureUpdateFrequency) == 0: - if self.experimentalData.operationMode == "FPM": - object_estimate = np.squeeze( - asNumpyArray( - fft2c(self.reconstruction.object)[ - ..., self.monitor.objectROI[0], self.monitor.objectROI[1] - ] - ) - ) - probe_estimate = np.squeeze( - asNumpyArray( - self.reconstruction.probe[ - ..., self.monitor.probeROI[0], self.monitor.probeROI[1] - ] - ) - ) - else: - object_estimate = np.squeeze( - asNumpyArray( - self.reconstruction.object[ - ..., self.monitor.objectROI[0], self.monitor.objectROI[1] - ] - ) - ) - probe_estimate = np.squeeze( - asNumpyArray( - self.reconstruction.probe[ - ..., self.monitor.probeROI[0], self.monitor.probeROI[1] - ] - ) - ) - self.monitor.updateObjectProbeErrorMonitor( - error=self.reconstruction.error, - object_estimate=object_estimate, - probe_estimate=probe_estimate, - zo=self.reconstruction.zo, - purity_probe=self.reconstruction.purityProbe, - purity_object=self.reconstruction.purityObject, - encoder_positions=self.reconstruction.positions, + if self.monitor.verboseLevel == "high" and loop == self.numIterations - 1: + # one summary at the end of the run, not one per monitor update + self.getOverlap(0, 1) + self.pbar.write("") + self.pbar.write("final iteration: %i" % loop) + self.pbar.write("error: %.1f" % self.reconstruction.error[-1]) + self.pbar.write( + "estimated linear overlap: %.1f %%" + % (100 * self.reconstruction.linearOverlap) ) - - self.monitor.writeEngineName(repr(type(self))) - - self.monitor.update_encoder( - corrected_positions=self.reconstruction.encoder_corrected, - original_positions=self.experimentalData.encoder, + self.pbar.write( + "estimated area overlap: %.1f %%" + % (100 * self.reconstruction.areaOverlap) ) - self.monitor.updateBeamWidth(*self.getBeamWidth()) - - # self.monitor.visualize_probe_engine(self.reconstruction.probe_storage) + if np.mod(loop, self.monitor.figureUpdateFrequency) == 0: + fields = { + "engine_name": repr(type(self)), + "encoder_original": self.experimentalData.encoder, + "encoder_corrected": self.reconstruction.encoder_corrected, + "beam_width": self.getBeamWidth(), + } if self.monitor.verboseLevel == "high": + Iestimated = asNumpyArray(self.reconstruction.Iestimated) + Imeasured = asNumpyArray(self.reconstruction.Imeasured) if self.params.fftshiftSwitch: - Iestimated = np.fft.fftshift( - asNumpyArray(self.reconstruction.Iestimated) - ) - Imeasured = np.fft.fftshift( - asNumpyArray(self.reconstruction.Imeasured) - ) - else: - Iestimated = asNumpyArray(self.reconstruction.Iestimated) - Imeasured = asNumpyArray(self.reconstruction.Imeasured) - - self.monitor.updateDiffractionDataMonitor( - Iestimated=Iestimated, Imeasured=Imeasured - ) + # the engine works on fftshifted detector frames; shift back + # so the zero frequency is in the centre of the image + Iestimated = np.fft.fftshift(Iestimated) + Imeasured = np.fft.fftshift(Imeasured) + # sets reconstruction.areaOverlap and .linearOverlap self.getOverlap(0, 1) - self.pbar.write("") - self.pbar.write("iteration: %i" % loop) - self.pbar.write("error: %.1f" % self.reconstruction.error[-1]) - self.pbar.write( - "estimated linear overlap: %.1f %%" - % (100 * self.reconstruction.linearOverlap) - ) - self.pbar.write( - "estimated area overlap: %.1f %%" - % (100 * self.reconstruction.areaOverlap) + fields.update( + I_estimated=Iestimated, + I_measured=Imeasured, + area_overlap=self.reconstruction.areaOverlap, + linear_overlap=self.reconstruction.linearOverlap, ) - self.monitor.update_overlap( - self.reconstruction.areaOverlap, self.reconstruction.linearOverlap - ) - # self.pbar.write('coherence structure:') + self.monitor.update(self._monitorFrame(**fields)) if self.params.positionCorrectionSwitch: # show reconstruction @@ -1940,6 +1915,7 @@ def position_update_to_change_in_z(self, loop): This method is used together with position correction and is called periodically when `map_position_to_z_change` is enabled. """ + self._logOnce("Updating zo from the scale of the corrected positions") X0 = self.reconstruction.encoder_corrected Y0 = self.experimentalData.encoder msqdisplacement = np.linalg.norm(1e6 * X0 - 1e6 * Y0) @@ -1954,16 +1930,18 @@ def position_update_to_change_in_z(self, loop): # target distance implied by the scale change of the positions target_z = self.reconstruction.zo / factor step = target_z - self.reconstruction.zo - self.logger.info(f"Naive estimate of new z: {target_z:.3f}, stepsize {step:.3f}") + self.logger.debug( + f"Naive estimate of new z: {target_z:.3f}, stepsize {step:.3f}" + ) if abs(step) < 2e-5: # same skip threshold as before (it used 5 * step < 1e-4) - self.logger.info("Skipping update as step is too small") + self.logger.debug("Skipping update as step is too small") return # damped update: move a fraction of the way toward the target each call damping = 0.2 z_new = self.reconstruction.zo + damping * step - self.logger.info(f"Loop: {loop} step: {step}") - self.logger.info( + self.logger.debug(f"Loop: {loop} step: {step}") + self.logger.debug( f"old z: {self.reconstruction.zo:.3f}\n new z calculated: {z_new:.3f}\n diff: {self.reconstruction.zo - z_new}\n" ) # scale the coordinates accordingly @@ -1980,7 +1958,7 @@ def position_update_to_change_in_z(self, loop): ) self.reconstruction.encoder_corrected = new_encoder - self.logger.info( + self.logger.debug( f"Mean square displacement: before: {msqdisplacement:.3f} after: {msqdisplacement_a:.3f}" ) @@ -2020,10 +1998,12 @@ def positionCorrectionUpdate(self): The method updates `reconstruction.encoder_corrected` in place and is called when position correction is enabled. """ - + # fit the scaling out, to put in the z if len(self.reconstruction.error) > self.startAtIteration: - self.logger.info("Updating positions") + self._logOnce( + "Position correction: updating scan positions every iteration" + ) # update positions if self.experimentalData.operationMode == "FPM": @@ -2056,7 +2036,7 @@ def positionCorrectionUpdate(self): ) self.reconstruction.encoder_corrected = new_encoder - self.logger.info( + self.logger.debug( f"Average update size: {abs(self.D).mean():.2f} pixels" ) @@ -2186,7 +2166,7 @@ def applyConstraints(self, loop): * np.mean( abs( self.reconstruction.object[ - ..., self.monitor.objectROI[0], self.monitor.objectROI[1] + ..., self.objectROI[0], self.objectROI[1] ] ) ) @@ -2241,6 +2221,11 @@ def applyConstraints(self, loop): merit, AOI_image, allmerits = self.reconstruction.TV_autofocus( self.params, loop=loop ) + if merit is not None: # None on iterations where autofocus is skipped + self._logOnce( + "TV autofocus: updating zo every %d iterations", + self.params.TV_autofocus_run_every, + ) self.monitor.update_focusing_metric( merit, AOI_image, @@ -2437,7 +2422,7 @@ def comStabilization(self): For multislice reconstruction, the last probe slice is used to estimate the center. """ - self.logger.info("Doing probe com stabilization") + self._logOnce("Doing probe com stabilization every iteration") xp = getArrayModule(self.reconstruction.probe) # calculate center of mass of the probe (for multislice cases, the probe for the last slice is used) P2 = xp.sum( @@ -2524,9 +2509,7 @@ def modulusEnforcedProbe(self): self.object2detector() if self.params.FourierMaskSwitch: - self.reconstruction.ESW = ( - self.reconstruction.ESW - * xp.sqrt( + self.reconstruction.ESW = self.reconstruction.ESW * xp.sqrt( self.experimentalData.emptyBeam / ( 1e-10 @@ -2535,9 +2518,8 @@ def modulusEnforcedProbe(self): axis=(0, 1, 2, 3), ) ) - ) - * self.experimentalData.W - + self.reconstruction.ESW * (1 - self.experimentalData.W) + ) * self.experimentalData.W + self.reconstruction.ESW * ( + 1 - self.experimentalData.W ) else: self.reconstruction.ESW = self.reconstruction.ESW * np.sqrt( @@ -2649,10 +2631,10 @@ def objectPatchUpdate_TV(self, objectPatch: np.ndarray, DELTA: np.ndarray): regularization term. """ - #xp = getArrayModule(objectPatch) - #frac = self.reconstruction.probe.conj() / xp.max( + # xp = getArrayModule(objectPatch) + # frac = self.reconstruction.probe.conj() / xp.max( # xp.sum(xp.abs(self.reconstruction.probe) ** 2, axis=(0, 1, 2, 3)) - #) + # ) # gradient = xp.gradient(objectPatch, axis=(4, 5)) # @@ -2660,7 +2642,7 @@ def objectPatchUpdate_TV(self, objectPatch: np.ndarray, DELTA: np.ndarray): # norm = (gradient[0] + gradient[1]) ** 2 # temp = [gradient[0] / xp.sqrt(norm + epsilon), gradient[1] / xp.sqrt(norm + epsilon)] # TV_update = divergence(temp) - + TV_update = grad_TV(objectPatch, epsilon=1e-2) updated_object = self.objectPatchUpdate(objectPatch, DELTA) diff --git a/PtyLab/Engines/OPR.py b/PtyLab/Engines/OPR.py index 6562cc98..6a2cd7af 100644 --- a/PtyLab/Engines/OPR.py +++ b/PtyLab/Engines/OPR.py @@ -12,7 +12,7 @@ import logging import sys -import tqdm +from tqdm.auto import trange # widget bar in Jupyter, text bar in a terminal from PtyLab.Engines.BaseEngine import BaseEngine from PtyLab.ExperimentalData.ExperimentalData import ExperimentalData @@ -26,7 +26,6 @@ class OPR(BaseEngine): - def __init__( self, reconstruction: Reconstruction, @@ -79,9 +78,7 @@ def reconstruct(self): ) # actual reconstruction ePIE_engine - self.pbar = tqdm.trange( - self.numIterations, desc="OPR", file=sys.stdout, leave=True - ) + self.pbar = trange(self.numIterations, desc="OPR", file=sys.stdout, leave=True) for loop in self.pbar: self.it = loop # set position order @@ -205,8 +202,13 @@ def _orthogonalizeIncoherentModes_batched(self): # stays bounded regardless of frame count; the batched call is already # wide enough at a few dozen frames to hide launch overhead. elements_per_frame = nModes * n * n - chunk = int(max(1, self._orthogonalization_chunk_bytes // - (elements_per_frame * stack.dtype.itemsize))) + chunk = int( + max( + 1, + self._orthogonalization_chunk_bytes + // (elements_per_frame * stack.dtype.itemsize), + ) + ) flat = stack[0, 0, :, 0, :, :, :].reshape(nModes, n * n, nFrames) for start in range(0, nFrames, chunk): diff --git a/PtyLab/Engines/aPIE.py b/PtyLab/Engines/aPIE.py index 5c8fe6c5..e9ec117e 100644 --- a/PtyLab/Engines/aPIE.py +++ b/PtyLab/Engines/aPIE.py @@ -1,9 +1,9 @@ from typing import Any import numpy as np -import tqdm from matplotlib import pyplot as plt from scipy.interpolate import interp2d +from tqdm.auto import trange # widget bar in Jupyter, text bar in a terminal from PtyLab.utils.visualisation import hsvplot @@ -83,9 +83,7 @@ def doReconstruction(self): self.thetaSearchRadiusMax, self.thetaSearchRadiusMin, self.numIterations ) - self.pbar = tqdm.trange( - self.numIterations, desc="aPIE", file=sys.stdout, leave=True - ) + self.pbar = trange(self.numIterations, desc="aPIE", file=sys.stdout, leave=True) for loop in self.pbar: # save theta search history self.reconstruction.thetaHistory = np.append( diff --git a/PtyLab/Engines/e3PIE.py b/PtyLab/Engines/e3PIE.py index 8ad7a567..ae05de3e 100644 --- a/PtyLab/Engines/e3PIE.py +++ b/PtyLab/Engines/e3PIE.py @@ -1,6 +1,6 @@ import numpy as np -import tqdm from matplotlib import pyplot as plt +from tqdm.auto import trange # widget bar in Jupyter, text bar in a terminal try: import cupy as cp @@ -25,7 +25,6 @@ class e3PIE(BaseEngine): - def __init__( self, reconstruction: Reconstruction, @@ -76,7 +75,7 @@ def reconstruct(self): # get module xp = getArrayModule(self.reconstruction.object) - self.pbar = tqdm.trange( + self.pbar = trange( self.numIterations, desc="e3PIE", file=sys.stdout, leave=True ) @@ -123,7 +122,6 @@ def reconstruct(self): ] # update object slice for loopTemp in range(self.reconstruction.nslice - 1): - sliceLoop = self.reconstruction.nslice - 1 - loopTemp # temp_delta = self.reconstruction.esw[..., sliceLoop, sy, sx] @@ -137,7 +135,7 @@ def reconstruct(self): ) ) # eswTemp update (here probe incident on last slice) - beth = 0.9 # todo, why need beth, not betaProbe, changable? + beth = 0.9 # todo, why need beth, not betaProbe, changable? self.reconstruction.probe[:, :, :, sliceLoop, ...] = ( self.probeUpdate( objectPatch[:, :, :, sliceLoop, ...], diff --git a/PtyLab/Engines/ePIE.py b/PtyLab/Engines/ePIE.py index 2a047940..11eba2cb 100644 --- a/PtyLab/Engines/ePIE.py +++ b/PtyLab/Engines/ePIE.py @@ -2,8 +2,8 @@ import sys import numpy as np -import tqdm from matplotlib import pyplot as plt +from tqdm.auto import trange # widget bar in Jupyter, text bar in a terminal from PtyLab.Engines.BaseEngine import BaseEngine from PtyLab.ExperimentalData.ExperimentalData import ExperimentalData @@ -66,6 +66,7 @@ class ePIE(BaseEngine): imaging," Ultramicroscopy 109, 1256-1262 (2009). https://doi.org/10.1016/j.ultramic.2009.05.012 """ + def __init__( self, reconstruction: Reconstruction, @@ -169,8 +170,9 @@ def reconstruct_stepwise(self, experimentalData: ExperimentalData = None): probe estimate is updated sequentially across all scan positions. After all scan positions in an iteration have been processed, - `getErrorMetrics()` evaluates the reconstruction error and - `applyConstraints()` applies the enabled reconstruction constraints. + `getErrorMetrics()` evaluates the reconstruction error, + `applyConstraints()` applies the enabled reconstruction constraints and + `showReconstruction()` updates the monitor. The method yields after every scan-position update, allowing custom code to be interleaved with the reconstruction. @@ -190,9 +192,7 @@ def reconstruct_stepwise(self, experimentalData: ExperimentalData = None): self._prepareReconstruction() # actual reconstruction ePIE_engine - self.pbar = tqdm.trange( - self.numIterations, desc="ePIE", file=sys.stdout, leave=True - ) + self.pbar = trange(self.numIterations, desc="ePIE", file=sys.stdout, leave=True) for loop in self.pbar: # set position order self.setPositionOrder() @@ -234,10 +234,10 @@ def reconstruct_stepwise(self, experimentalData: ExperimentalData = None): object_patch = self.objectPatchUpdate(objectPatch, DELTA) self.reconstruction.object[..., sy, sx] = object_patch - - #self.reconstruction.object[..., sy, sx] = self.objectPatchUpdate( + + # self.reconstruction.object[..., sy, sx] = self.objectPatchUpdate( # objectPatch, DELTA - #) + # ) # probe update self.reconstruction.probe = self.probeUpdate(objectPatch, DELTA) @@ -255,8 +255,8 @@ def reconstruct_stepwise(self, experimentalData: ExperimentalData = None): # apply Constraints self.applyConstraints(loop) - # show reconstruction - # self.showReconstruction(loop) + # update the monitor, as every other engine does after the constraints + self.showReconstruction(loop) if self.params.gpuFlag: self.logger.info("switch to cpu") diff --git a/PtyLab/Engines/mPIE.py b/PtyLab/Engines/mPIE.py index b677a321..ea06a06c 100644 --- a/PtyLab/Engines/mPIE.py +++ b/PtyLab/Engines/mPIE.py @@ -13,7 +13,7 @@ import sys import warnings -import tqdm +from tqdm.auto import tqdm, trange # widget bar in Jupyter, text bar in a terminal from PtyLab.Engines.BaseEngine import BaseEngine from PtyLab.ExperimentalData.ExperimentalData import ExperimentalData @@ -98,6 +98,7 @@ class mPIE(BaseEngine): Baseline ePIE reconstruction without rPIE regularization or momentum acceleration. """ + def __init__( self, reconstruction: Reconstruction, @@ -127,7 +128,7 @@ def __init__( 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") @@ -200,7 +201,9 @@ def initializeReconstructionParams(self): self.reconstruction.probeWindow = np.abs(self.reconstruction.probe) - def reconstruct(self, experimentalData=None, reconstruction=None, vis_after_each_iteration=None): + def reconstruct( + self, experimentalData=None, reconstruction=None, vis_after_each_iteration=None + ): r""" Run the mPIE reconstruction to completion. @@ -273,13 +276,11 @@ def reconstruct(self, experimentalData=None, reconstruction=None, vis_after_each self.reconstruction.objectBuffer = self.reconstruction.object.copy() self.reconstruction.probeBuffer = self.reconstruction.probe.copy() # actual reconstruction MPIE_engine - self.pbar = tqdm.trange( - self.numIterations, desc="mPIE", file=sys.stdout, leave=True - ) + self.pbar = trange(self.numIterations, desc="mPIE", file=sys.stdout, leave=True) for loop in self.pbar: # set position order self.setPositionOrder() - self.pbar_pos = tqdm.tqdm( + self.pbar_pos = tqdm( self.positionIndices, leave=False, desc="ptychogram", file=sys.stdout ) for positionLoop, positionIndex in enumerate(self.pbar_pos): @@ -329,9 +330,7 @@ def reconstruct(self, experimentalData=None, reconstruction=None, vis_after_each # self.reconstruction.push_probe_update(self.reconstruction.probe, positionIndex, self.experimentalData.ptychogram.shape[0]) if self.params.positionCorrectionSwitch: - self.positionCorrection( - objectPatch, positionIndex, sy, sx - ) + self.positionCorrection(objectPatch, positionIndex, sy, sx) # self.pbar_pos.write(f'Corr: {shifter[0]*1e6:.2f} um x {shifter[1]*1e6:.2f} um') # momentum updates @@ -610,4 +609,4 @@ def stepM(self): @stepM.setter def stepM(self, value): - self.frictionM = value \ No newline at end of file + self.frictionM = value diff --git a/PtyLab/Engines/mqNewton.py b/PtyLab/Engines/mqNewton.py index 3de798de..d130f236 100644 --- a/PtyLab/Engines/mqNewton.py +++ b/PtyLab/Engines/mqNewton.py @@ -12,7 +12,7 @@ import logging import sys -import tqdm +from tqdm.auto import trange # widget bar in Jupyter, text bar in a terminal from PtyLab.Engines.BaseEngine import BaseEngine from PtyLab.ExperimentalData.ExperimentalData import ExperimentalData @@ -85,7 +85,7 @@ def reconstruct(self, experimentalData: ExperimentalData = None): self._prepareReconstruction() self.initializeAdaptiveMomentum() - self.pbar = tqdm.trange( + self.pbar = trange( self.numIterations, desc="mqNewton", file=sys.stdout, leave=True ) for loop in self.pbar: diff --git a/PtyLab/Engines/multiPIE.py b/PtyLab/Engines/multiPIE.py index 3136abb7..0857131a 100644 --- a/PtyLab/Engines/multiPIE.py +++ b/PtyLab/Engines/multiPIE.py @@ -12,7 +12,7 @@ import logging import sys -import tqdm +from tqdm.auto import trange # widget bar in Jupyter, text bar in a terminal from PtyLab.Engines.BaseEngine import BaseEngine from PtyLab.ExperimentalData.ExperimentalData import ExperimentalData @@ -68,7 +68,7 @@ def initializeReconstructionParams(self): def reconstruct(self): self._prepareReconstruction() - self.pbar = tqdm.trange( + self.pbar = trange( self.numIterations, desc="multiPIE", file=sys.stdout, leave=True ) diff --git a/PtyLab/Engines/qNewton.py b/PtyLab/Engines/qNewton.py index 6a742412..4b441766 100644 --- a/PtyLab/Engines/qNewton.py +++ b/PtyLab/Engines/qNewton.py @@ -12,7 +12,7 @@ import logging import sys -import tqdm +from tqdm.auto import trange # widget bar in Jupyter, text bar in a terminal from PtyLab.Engines.BaseEngine import BaseEngine from PtyLab.ExperimentalData.ExperimentalData import ExperimentalData @@ -57,7 +57,7 @@ def reconstruct(self, experimentalData: ExperimentalData = None): self.experimentalData = experimentalData self._prepareReconstruction() - self.pbar = tqdm.trange( + self.pbar = trange( self.numIterations, desc="qNewton", file=sys.stdout, leave=True ) for loop in self.pbar: diff --git a/PtyLab/Engines/zPIE.py b/PtyLab/Engines/zPIE.py index 9c9a1a99..34a3a5e8 100644 --- a/PtyLab/Engines/zPIE.py +++ b/PtyLab/Engines/zPIE.py @@ -1,6 +1,6 @@ import numpy as np -import tqdm from matplotlib import pyplot as plt +from tqdm.auto import trange # widget bar in Jupyter, text bar in a terminal try: import cupy as cp @@ -112,7 +112,7 @@ def reconstruct(self, experimentalData=None, reconstruction=None): X, Y = xp.meshgrid(xp.arange(-n // 2, n // 2), xp.arange(-n // 2, n // 2)) w = xp.exp(-((xp.sqrt(X**2 + Y**2) / self.reconstruction.Np) ** 4)) - self.pbar = tqdm.trange( + self.pbar = trange( self.numIterations, desc="zPIE", file=sys.stdout, leave=True ) # in order to change description to the tqdm progress bar for loop in self.pbar: diff --git a/PtyLab/Monitor/Monitor.py b/PtyLab/Monitor/Monitor.py index 7ebc027e..35330a7a 100644 --- a/PtyLab/Monitor/Monitor.py +++ b/PtyLab/Monitor/Monitor.py @@ -1,102 +1,151 @@ import warnings from pathlib import Path +from typing import Literal import numpy as np from PtyLab.utils.visualisation import complex2rgb, setColorMap -from .Plots import DiffractionDataPlot, ObjectProbeErrorPlot, is_inline +from .frame import MonitorFrame +from .Plots import ( + DiffractionDataPlot, + ObjectProbeErrorPlot, + ParameterHistoryPlot, + is_inline, +) +# allowed values of the Monitor settings; type hints only, values are not checked +ObjectPlot = Literal["complex", "abs", "angle"] +VerboseLevel = Literal["low", "high"] -class AbstractMonitor(object): - """ - This monitor implements all the basic features that you have to override for a custom monitor. - Alternatively, you can instantiate this class to create a monitor that does not do anything and therefore, - will not take time to run. +def tracked_values(frame: MonitorFrame) -> dict: + """Scalars besides object and probe that an engine may change, in display units. - """ + Quantities the frame does not carry (`None`) or that are undefined for this + reconstruction (purity of a single mode) are left out. - def initializeMonitors(self): - """ - This code is run after __init__, use it to build a.k.a. GUI elements. + Args: + frame (MonitorFrame): Current reconstruction state. - :return: Nothing - """ + Returns: + dict[str, dict[str, float]]: Panel title -> line label -> value. + """ + values = {} + if frame.zo is not None: + values["zo [mm]"] = {"zo": 1e3 * float(frame.zo)} + if frame.theta is not None: + values["theta [deg]"] = {"theta": float(frame.theta)} + purity = {} + if frame.nosm > 1: + purity["object"] = 100 * float(frame.purity_object) + if frame.npsm > 1: + purity["probe"] = 100 * float(frame.purity_probe) + if purity: + values["purity [%]"] = purity + return values + + +class AbstractMonitor: + """Base class of the reconstruction monitors; on its own it shows nothing. + + The engines call `update` with one `MonitorFrame` per update. A custom monitor + can either override `update` and read the frame directly, or override the + per-quantity hooks below (`updateObjectProbeErrorMonitor`, `update_encoder`, + ...), which the default `update` calls. Every hook is a no-op here, so a + subclass only implements the ones it uses. + """ - pass + def update(self, frame: MonitorFrame): + """Show one snapshot of the reconstruction. - def update_focusing_metric(self, TV_value, AOI_image, metric_name, allmerits=None): - """ - Show the total variation of the object estimate inside the area of interest. - :param TV_value: Value of TV - :return: - """ - pass + The default forwards the frame to the per-quantity hooks, so monitors + written against those hooks keep working. Fields the engine left empty + (`None`) are skipped. - def writeEngineName(self, name): + Args: + frame (MonitorFrame): Current reconstruction state. """ - Save the engine name for this particular iteration. - - :param name: Name of the engine that is used for this iteration. + self.updateObjectProbeErrorMonitor( + error=frame.error, + object_estimate=frame.object_view(), + probe_estimate=frame.probe_view(), + zo=frame.zo, + purity_probe=frame.purity_probe, + purity_object=frame.purity_object, + encoder_positions=frame.positions, + ) + if frame.engine_name is not None: + self.writeEngineName(frame.engine_name) + if frame.encoder_original is not None: + self.update_encoder( + corrected_positions=frame.encoder_corrected, + original_positions=frame.encoder_original, + ) + if frame.beam_width is not None: + self.updateBeamWidth(*frame.beam_width) + if frame.I_estimated is not None: + self.updateDiffractionDataMonitor( + Iestimated=frame.I_estimated, Imeasured=frame.I_measured + ) + if frame.area_overlap is not None: + self.update_overlap(frame.area_overlap, frame.linear_overlap) - :return: - """ - pass + def initializeMonitors(self): + """Create the figures or other outputs; the engine calls it before the first update.""" - def visualize_probe_engine(self, estimate): - """ - For nonlinear imaging only. Return the electric field of the probe. - """ - pass + def saveFigures(self, fileName="recent", dpi=150): + """Save the monitor figures as PNG files. This monitor has none. - def updatePlot( - self, - object_estimate: np.ndarray, - probe_estimate: np.ndarray, - zo=None, - encoder_positions=None, - ): + Returns: + list[Path]: Empty, as nothing is saved. """ - Update the visualisation of both probe and and object estimate. - - Please note, that only the part that is defined by probeZoom and objectZoom is uploaded. + return [] - #TODO: Change that, upload the entire image and make the monitor decide which parts to show. + def describe_parameters(self, params): + """Record the reconstruction parameters, e.g. as text in a log. - :param object_estimate: Array with the object estimate. - :param probe_estimate: Array with the probe estimate. - :return: + Args: + params (Params): Parameters of the reconstruction. """ - pass - def getOverlap(self, *args, **kwargs): + def update_focusing_metric(self, TV_value, AOI_image, metric_name, allmerits=None): + """Show the result of one TV autofocus step. + + Args: + TV_value (float): Focus metric at the current distance. + AOI_image (np.ndarray): Propagated field in the area of interest. + metric_name (str): Name of the focus metric, e.g. `"TV"`. + allmerits (np.ndarray, optional): Focus metric at every distance that + was tried. Defaults to None. """ - Get the overlap between subsequent probes. - Todo(dbs660): Move this. + def writeEngineName(self, name): + """Record which engine produced the current update. - :param args: - :param kwargs: - :return: + Args: + name (str): Engine name. """ - # TODO: remove this from here, it should go in some utils - pass - - def update_positions(self, *args, **kwargs): - """Update the position information.""" - pass def update_encoder(self, corrected_positions, original_positions, *args, **kwargs): - """Update the image of the encoder positions.""" - pass + """Show the scan positions before and after position correction. + + Args: + corrected_positions (np.ndarray): Corrected encoder positions in m. + original_positions (np.ndarray): Measured encoder positions in m. + """ def update_overlap(self, overlap_area, linear_overlap): - pass + """Show the estimated probe overlap between neighbouring scan positions. + + Args: + overlap_area (float): Area overlap, between 0 and 1. + linear_overlap (float): Linear overlap, between 0 and 1. + """ def updateObjectProbeErrorMonitor( self, - error: float, + error, object_estimate: np.ndarray, probe_estimate: np.ndarray, zo=None, @@ -104,234 +153,232 @@ def updateObjectProbeErrorMonitor( purity_object=None, encoder_positions=None, ): - """ - Update the Object and Probe error monitor, and any associated metrics. - - :param error: Value of the loss for the current iteration. - :param object_estimate: Current object estimate - :param probe_estimate: Current probe estimate - :param zo: Sample-detector distance - :param purity_probe: purity of the probe - :param purity_object: purity of the object - :return: + """Show the object and probe estimates and the error metric. + + Args: + error (array-like): Error metric of every iteration so far. + object_estimate (np.ndarray): Object inside the display region. + probe_estimate (np.ndarray): Probe inside the display region. + zo (float, optional): Sample-detector distance in m. Defaults to None. + purity_probe (float, optional): Probe purity. Defaults to None. + purity_object (float, optional): Object purity. Defaults to None. + encoder_positions (np.ndarray, optional): Scan positions in object + pixels. Defaults to None. """ - pass + def updateBeamWidth(self, beamwidth_y, beamwidth_x): + """Show the probe width. - def updateBeamWidth(self, beamwidth_x, beamwidth_y): + Args: + beamwidth_y (float): FWHM along y in m. + beamwidth_x (float): FWHM along x in m. """ - Update the beam width in X and Y - - Parameters - ---------- - beamwidth_x: beamwidth x in meter - beamwidth_y: beamwidth y in meter - - Returns - ------- - - """ - pass def updateDiffractionDataMonitor(self, Iestimated, Imeasured): - """ - Update the diffraction data estimate at the current iteration. + """Show the estimated and measured intensity at the last scan position. - :param Iestimated: Estimated intensity at the current position - :param Imeasured: Measured intensity at the current position - :return: + Args: + Iestimated (np.ndarray): Estimated detector intensity. + Imeasured (np.ndarray): Measured detector intensity. """ - pass - class Monitor(AbstractMonitor): - """ - Monitor contains two submonitors: ObjectProbeErrorPlot (object,probe,error) and DiffractionDataPlot (diffraction - intensity estimate and measurement) + """Live matplotlib monitor, in GUI windows or in Jupyter cell outputs. + + Shows up to three figures: + + - object, probe and error metric (`ObjectProbeErrorPlot`), always + - estimated vs measured intensity (`DiffractionDataPlot`), for + `verboseLevel = "high"` + - zo, theta, purity and scan positions (`ParameterHistoryPlot`), once the + engine changes one of them and while `showParameterHistory` is True + + Attributes: + figureUpdateFrequency (int): Update the figures every this many iterations. + verboseLevel (str): `"low"`, or `"high"` to add the diffraction figure. + objectPlot (str): `"complex"`, `"abs"` or `"angle"`. + objectZoom (float or None): Shrinks the shown object region around the + scanned area; `None` or `"full"` shows the whole object. + probeZoom (float or None): Same for the probe, around the pupil size. + objectPlotContrast (float): Brightness scaling of the complex object plot. + probePlotContrast (float): Brightness scaling of the complex probe plot. + showParameterHistory (bool): Whether to show the third figure. + screenshot_directory (str or None): If set, the first figure is saved + there after every update as `frame_.png`. """ def __init__(self): # settings for visualization self._figureUpdateFrequency = 1 - self.objectPlot = "complex" - self._verboseLevel = "low" + self.objectPlot: ObjectPlot = "complex" + self._verboseLevel: VerboseLevel = "low" self.objectZoom = 1 self.probeZoom = 1 self.objectPlotContrast = 1 self.probePlotContrast = 1 - self.reconstruction = None self.cmapDiffraction = setColorMap() self.defaultMonitor = None self.screenshot_directory = None self.diffractionDataMonitor = None + # zo, theta, purity and scan positions in a third window, shown only + # for the quantities the engine actually changes + self.showParameterHistory = True + self.parameterHistoryMonitor = None @property - def figureUpdateFrequency(self): + def figureUpdateFrequency(self) -> int: return self._figureUpdateFrequency @figureUpdateFrequency.setter - def figureUpdateFrequency(self, value): + def figureUpdateFrequency(self, value: int): self._figureUpdateFrequency = value if is_inline() and self.figureUpdateFrequency < 5: - warnings.simplefilter("always", UserWarning) warnings.warn( - "For faster update of the reconstruction plot, set `monitor.figureUpdateFrequency = 5` or higher." + "For faster update of the reconstruction plot, set `monitor.figureUpdateFrequency = 5` or higher.", + stacklevel=2, ) @property - def verboseLevel(self): + def verboseLevel(self) -> VerboseLevel: return self._verboseLevel @verboseLevel.setter - def verboseLevel(self, value): + def verboseLevel(self, value: VerboseLevel): self._verboseLevel = value if is_inline() and self._verboseLevel == "high": - warnings.simplefilter("always", UserWarning) warnings.warn( "For diffraction data plot, preferably use an interactive matplotlib backend or" - ' set `monitor.verboseLevel = "low"`. ' + ' set `monitor.verboseLevel = "low"`. ', + stacklevel=2, ) def initializeMonitors(self): - """ - Create the figure and axes etc. - :return: - """ - # only initialize if it hasn't been done + """Create the figures; a figure that already exists is reused.""" if self.defaultMonitor is None: self.defaultMonitor = ObjectProbeErrorPlot() if self.verboseLevel == "high": self.diffractionDataMonitor = DiffractionDataPlot() - @property - def objectPixelSize(self): - """Pixel size of the object estimate that is plotted.""" - if self.reconstruction.data.operationMode == "FPM": - return self.reconstruction.dxo_fpm - return self.reconstruction.dxo + if self.showParameterHistory and self.parameterHistoryMonitor is None: + # creates no figure yet; that happens once a quantity changes + self.parameterHistoryMonitor = ParameterHistoryPlot() - @property - def probePixelSize(self): - """Axis step of the probe panel.""" - if self.reconstruction.data.operationMode == "FPM": - return self.reconstruction.dfp - return self.reconstruction.dxp - - @property - def probeAxisUnit(self): - """Unit of the probe panel axes: a length for CPM, a spatial frequency for FPM.""" - if self.reconstruction.data.operationMode == "FPM": - return "1/um" - return "mm" - - @property - def probeLabel(self): - """Title of the probe panel. FPM estimates a pupil instead of a probe.""" - if self.reconstruction.data.operationMode == "FPM": - return "Pupil estimate" - return "Probe estimate" + def update(self, frame: MonitorFrame): + """Draw the object, probe and error panels, plus the diffraction data when shown. - def updateObjectProbeErrorMonitor( - self, - error, - object_estimate, - probe_estimate, - zo=None, - purity_probe=None, - purity_object=None, - encoder_positions=None, - ): - """ - update the probe object plots - :param object_estimate: - :return: + Args: + frame (MonitorFrame): Current reconstruction state. """ - self.defaultMonitor.updateError(error) # self.reconstruction.error) - # print(f"Object plot: {self.objectPlot}") - self.defaultMonitor.updateObject( - object_estimate, - self.reconstruction, + plot = self.defaultMonitor + plot.updateError(frame.error) + plot.updateObject( + frame.object_view(), objectPlot=self.objectPlot, - pixelSize=self.objectPixelSize, + pixelSize=frame.object_pixel_size, axisUnit="mm", amplitudeScalingFactor=self.objectPlotContrast, + # purity is only defined for mixed states + purity=frame.purity_object if frame.nosm > 1 else None, ) - self.defaultMonitor.updateProbe( - probe_estimate, - self.reconstruction, - pixelSize=self.probePixelSize, - axisUnit=self.probeAxisUnit, - label=self.probeLabel, + plot.updateProbe( + frame.probe_view(), + pixelSize=frame.probe_pixel_size, + axisUnit=frame.probe_axis_unit, + label=frame.probe_label, amplitudeScalingFactor=self.probePlotContrast, + purity=frame.purity_probe if frame.npsm > 1 else None, ) - self.defaultMonitor.update_z(zo) - self.defaultMonitor.drawNow() + plot.drawNow() if self.screenshot_directory is not None: - self.defaultMonitor.figure.savefig( - Path(self.screenshot_directory) / f"frame_{len(error)}.png" + plot.figure.savefig( + Path(self.screenshot_directory) / f"frame_{frame.iteration}.png" ) - def describe_parameters(self, *args, **kwargs): - pass - - def updateDiffractionDataMonitor(self, Iestimated, Imeasured): - """ - update the diffraction plots + # the diffraction figure only exists for verboseLevel "high", and the + # engine only fills the intensities then + if self.diffractionDataMonitor is not None and frame.I_estimated is not None: + self.diffractionDataMonitor.update_view( + frame.I_estimated, frame.I_measured, cmap=self.cmapDiffraction + ) + self.diffractionDataMonitor.drawNow() + + if self.parameterHistoryMonitor is not None: + history = self.parameterHistoryMonitor + history.record(frame.iteration, tracked_values(frame)) + if frame.encoder_corrected is not None: + history.record_positions( + frame.encoder_original, frame.encoder_corrected + ) + history.draw() + + def saveFigures(self, fileName="recent", dpi=150): + """Save the current monitor figures as PNG files. + + Call it after `engine.reconstruct()` to keep the final state, or let + `reconstruction.saveResults(fileName, snapshot=monitor)` call it next to + the HDF5 file. Each figure that exists is written as + `_
.png`: + + - `reconstruction`: object, probe and error metric + - `diffraction`: estimated vs measured intensity (`verboseLevel = "high"`) + - `history`: zo, theta, purity and scan positions, if any of them changed + + Args: + fileName (str or Path, optional): Path prefix of the PNG files; missing + parent directories are created. Defaults to `"recent"`. + dpi (int, optional): Resolution of the PNG files. Defaults to 150. + + Returns: + list[Path]: The files written. """ - - self.diffractionDataMonitor.update_view( - Iestimated, Imeasured, cmap=self.cmapDiffraction - ) - # self.diffractionDataMonitor.updateIestimated(Iestimated, cmap=self.cmapDiffraction) - # self.diffractionDataMonitor.updateImeasured(Imeasured, cmap=self.cmapDiffraction) - self.diffractionDataMonitor.drawNow() - - -class DummyMonitor(object): - """Monitor without any visualisation so it won't consume any time""" + figures = { + "reconstruction": self.defaultMonitor, + "diffraction": self.diffractionDataMonitor, + "history": self.parameterHistoryMonitor, + } + prefix = Path(fileName) + prefix.parent.mkdir(parents=True, exist_ok=True) + saved = [] + for name, plot in figures.items(): + # a plot object can exist without a figure, e.g. the history window + # before any quantity changed + if plot is None or getattr(plot, "figure", None) is None: + continue + path = prefix.with_name(f"{prefix.name}_{name}.png") + plot.figure.savefig(path, dpi=dpi, bbox_inches="tight") + saved.append(path) + return saved + + +class DummyMonitor(AbstractMonitor): + """Monitor that shows nothing, for runs where plotting would only cost time. + + Inherits every no-op hook from `AbstractMonitor`, so any hook an engine calls + (e.g. `update_focusing_metric` when `params.TV_autofocus` is on) exists here too. + """ objectZoom = 1 probeZoom = 1 - # remains from mPIE + # the engines only call the monitor every `figureUpdateFrequency` iterations figureUpdateFrequency = 1000000 verboseLevel = "low" - def update_encoder(self, *args, **kwargs): - pass - - def updateBeamWidth(self, *args, **kwargs): - pass - - - - def updatePlot(self, object_estimate, probe_estimate): - pass - - def getOverlap(self, ind1, ind2, probePixelsize): - pass - - def initializeVisualisation(self): - pass - - def initializeMonitors(self): - pass - - def updateObjectProbeErrorMonitor(self, *args, **kwargs): - pass - - def updateDiffractionDataMonitor(self, *args, **kwargs): - pass - - def writeEngineName(self, *args, **kwargs): + def update(self, frame): + # the default would crop and copy object and probe to the CPU for nothing pass class NapariMonitor(DummyMonitor): + """Shows the object, probe and diffraction data as layers in a napari viewer. + + Needs napari, which is not a PtyLab dependency. + """ def initializeVisualisation(self): + """Open the viewer and create its image layers.""" # currently a hacky way for this class, these napari implementations must # later be moved an optional sub-package. try: @@ -343,8 +390,14 @@ def initializeVisualisation(self): msg = "Install napari to access this `NapariMonitor` implementation" raise ImportError(msg) - self.viewer.add_image(name="object estimate", data=np.random.rand(100, 100)) - self.viewer.add_image(name="probe estimate", data=np.random.rand(100, 100)) + # object and probe are shown as complex2rgb images, so these layers must be + # RGB from the start: napari fixes a layer's `rgb` flag when it is created + self.viewer.add_image( + name="object estimate", data=np.zeros((100, 100, 3)), rgb=True + ) + self.viewer.add_image( + name="probe estimate", data=np.zeros((100, 100, 3)), rgb=True + ) self.Iestimated = self.viewer.add_image( name="I estimated", data=np.random.rand(100, 100) @@ -366,25 +419,25 @@ def add_ptychogram(self, experimentalData): def update_probe_image(self, new_probe): RGB_probe = complex2rgb(new_probe) - self.viewer.layers["probe_estimate"].data = RGB_probe + self.viewer.layers["probe estimate"].data = RGB_probe def update_object_image(self, object_estimate): RGB_object = complex2rgb(object_estimate) self.viewer.layers["object estimate"].data = RGB_object - def updatePlot(self, object_estimate, probe_estimate): + def updatePlot( + self, object_estimate, probe_estimate, zo=None, encoder_positions=None + ): self.update_probe_image(probe_estimate) self.update_object_image(object_estimate) + def updateObjectProbeErrorMonitor( + self, error, object_estimate, probe_estimate, *args, **kwargs + ): + # this is the hook `BaseEngine.showReconstruction` calls; without it the + # viewer never receives the estimates + self.updatePlot(object_estimate, probe_estimate) + def updateDiffractionDataMonitor(self, Iestimated, Imeasured): self.Iestimated.data = Iestimated self.Imeasured.data = Imeasured - - def update_positions(self, *args, **kwargs): - """ - Update the positions. USeful for position correction. - :param args: - :param kwargs: - :return: - """ - pass diff --git a/PtyLab/Monitor/Plots.py b/PtyLab/Monitor/Plots.py index d487d046..d4ac51bf 100644 --- a/PtyLab/Monitor/Plots.py +++ b/PtyLab/Monitor/Plots.py @@ -1,9 +1,10 @@ -import warnings +import math import matplotlib as mpl import numpy as np -from IPython.display import clear_output, display +from IPython.display import display from matplotlib import pyplot as plt +from matplotlib import ticker from matplotlib.image import AxesImage from mpl_toolkits.axes_grid1 import make_axes_locatable @@ -12,92 +13,135 @@ def is_inline(): - """Default IPython (jupyter notebook) backend""" - return True if "inline" in mpl.get_backend().lower() else False + """Whether matplotlib draws inline, as in a Jupyter notebook. + Returns: + bool: True for an inline backend, False for a GUI or file backend. + """ + return "inline" in mpl.get_backend().lower() -class ObjectProbeErrorPlot(object): - def __init__(self, figNum=1): - """Create a monitor. - In principle, to use this method all you have to do is initialize the monitor and then call +class _LiveFigure: + """Drawing logic shared by the monitor figures. - updateObject, updateProbe, updateErrorMetric and drawnow to ensure that something is drawn immediately. + In a script the figure lives in its own GUI window that is redrawn in place. + In Jupyter (inline backend) the figure is shown once through a display handle, + and every later draw replaces that output, so the rest of the cell output + (prints, progress bar, other figures) stays untouched. + """ - For example usage, see test_matplot_monitor.py. + def _attach_figure(self, figure) -> None: + self.figure = figure + self.canvas = figure.canvas + self.display_handle = None + self.firstrun = True + if is_inline(): + # the display handle shows this figure; detach it from pyplot so the + # inline backend does not draw it a second time at the end of the cell + plt.close(figure) - """ - self.figNum = figNum - self._createFigure() + def drawNowScript(self): + """Redraw the figure window, reopening it if it was closed.""" + if self.firstrun or not plt.fignum_exists(self.figNum): + self.figure.show() + self.firstrun = False + self.canvas.draw_idle() + self.canvas.flush_events() + + def drawNowIpython(self): + """Show the figure on the first call, then update that same output.""" + if self.display_handle is None: + self.display_handle = display(self.figure, display_id=True) + else: + self.display_handle.update(self.figure) + self.firstrun = False + + def drawNow(self): + """Draw the figure, in a notebook output or in its window.""" + if is_inline(): + self.drawNowIpython() + else: + self.drawNowScript() - # Get a reference to the figure canvas - self.canvas = self.figure.canvas - self.display_id = None - def update_z(self, *args, **kwargs): - """Update the sample-detector distance. Does nothing at the moment.""" - pass +class ObjectProbeErrorPlot(_LiveFigure): + """Figure with the object estimate, the probe estimate and the error metric. - def _createFigure(self) -> None: - """ - Create the figure. - :return: - """ + Call `updateObject`, `updateProbe` and `updateError` with the current state, + then `drawNow` to show it. The first round of updates creates the images; later + ones only replace their data. - plt.ion() - self.figure, axes = plt.subplot_mosaic( - """Ape""", - num=self.figNum, - figsize=(10, 3), - empty_sentinel=" ", - constrained_layout=False, - ) + Args: + figNum (int, optional): pyplot figure number. Defaults to 1. + """ + + def __init__(self, figNum=1): + self.figNum = figNum + self._createFigure() + + def _createFigure(self) -> None: + """Create the figure with an object, a probe and an error-metric panel.""" + # interactive mode only matters for GUI windows; leave notebook sessions alone + if not is_inline(): + plt.ion() + # a new monitor must not draw on top of an old figure with the same number; + # the size is set separately because pyplot ignores figsize for a reused one + self.figure = plt.figure(num=self.figNum, clear=True) + self.figure.set_size_inches(10, 3) + axes = self.figure.subplot_mosaic("""Ape""", empty_sentinel=" ") self.ax_object = axes["A"] self.ax_probe = axes["p"] - # self.ax_probe_ff = axes["P"] self.ax_error_metric = axes["e"] - # self.ax_probe_ff.set_title("FF probe") - self.ax_probe.set_title("Probe") - # self.ax_object = axes[0][0] - # self.ax_probe = axes[0][1] - # self.ax_error_metric = axes[0][2] - # self.ax_object.set_title - self.txt_purityProbe = self.ax_probe.set_title("Probe estimate") self.txt_purityObject = self.ax_object.set_title("Object estimate") - self.ax_error_metric.set_title("Error metric") - self.ax_error_metric.grid(True) - self.ax_error_metric.grid( - animated=True, which="minor", color="#999999", linestyle="-", alpha=0.2 - ) - self.ax_error_metric.set_xlabel("iterations") - self.ax_error_metric.set_ylabel("error") - self.ax_error_metric.set_xscale("log") - self.ax_error_metric.set_yscale("log") - self.ax_error_metric.axis("image") + self.txt_purityProbe = self.ax_probe.set_title("Probe estimate") + + ax = self.ax_error_metric + ax.set_title("Error metric") + ax.set_xlabel("iterations") + ax.set_ylabel("error") + ax.set_xscale("log") + ax.set_yscale("log") + # plain tick labels (2, 3, 20) instead of 2x10^0, which overlap on a short + # axis; LogFormatter still thins out the minor labels over many decades + for axis in (ax.xaxis, ax.yaxis): + axis.set_major_formatter(ticker.LogFormatter()) + axis.set_minor_formatter(ticker.LogFormatter(labelOnlyBase=False)) + ax.grid(True, which="major", alpha=0.4) + ax.grid(True, which="minor", alpha=0.15) self.figure.tight_layout() - self.firstrun = True + self._attach_figure(self.figure) def updateObject( self, object_estimate, - optimizable, objectPlot, amplitudeScalingFactor=1, + purity=None, **kwargs, ): + """Show the object estimate. + + Args: + object_estimate (np.ndarray): Object, `(Ny, Nx)` or a stack of modes, + which are tiled side by side. + objectPlot (str): `"complex"` (phase as hue, amplitude as brightness), + `"abs"` or `"angle"`. + amplitudeScalingFactor (float, optional): Brightness scaling of the + complex plot. Defaults to 1. + purity (float, optional): Object purity, shown in the title; `None` for + a single object mode. Defaults to None. + **kwargs: Passed to `complexPlot` on the first call, e.g. `pixelSize` + and `axisUnit`. + """ OE = modeTile(object_estimate, normalize=True) if objectPlot == "complex": OE = complex2rgb(OE, amplitudeScalingFactor=amplitudeScalingFactor) - elif objectPlot == "abs": - # original - # OE = OE / abs(OE).max() - # better + # normalise to mean + std rather than the maximum, so a few hot pixels + # do not darken the whole image AOE = abs(OE) - OE = OE / (AOE.mean() + np.std(AOE)) - # OE = OE / abs(OE.max()) - OE = abs(OE) + OE = abs(OE / (AOE.mean() + np.std(AOE))) elif objectPlot == "angle": OE = np.angle(OE) @@ -108,15 +152,14 @@ def updateObject( self.im_object = self.ax_object.imshow(OE, interpolation=None) divider = make_axes_locatable(self.ax_object) cax = divider.append_axes("right", size="5%", pad=0.1) - self.objectCbar = plt.colorbar( + self.objectCbar = self.figure.colorbar( self.im_object, ax=self.ax_object, cax=cax ) else: self.im_object.set_data(OE) - if optimizable.nosm > 1: + if purity is not None: self.txt_purityObject.set_text( - "Object estimate\nPurity: %i" % (100 * optimizable.purityObject) - + "%" + f"Object estimate\nPurity: {int(100 * purity)}%" ) self.im_object.autoscale() @@ -124,17 +167,24 @@ def updateObject( def updateProbe( self, probe_estimate, - optimizable, amplitudeScalingFactor=1, label="Probe estimate", + purity=None, **kwargs, ): - - # from PtyLab.Operators.Operators import fft2c - # - # probe_estimate_ff = fft2c(probe_estimate) - # PE_ff = complex2rgb(modeTile(probe_estimate_ff, normalize=True)) - + """Show the probe (or, for FPM, pupil) estimate as a complex plot. + + Args: + probe_estimate (np.ndarray): Probe, `(Ny, Nx)` or a stack of modes, + which are tiled side by side. + amplitudeScalingFactor (float, optional): Brightness scaling of the + complex plot. Defaults to 1. + label (str, optional): Panel title. Defaults to `"Probe estimate"`. + purity (float, optional): Probe purity, shown in the title; `None` for + a single probe mode. Defaults to None. + **kwargs: Passed to `complexPlot` on the first call, e.g. `pixelSize` + and `axisUnit`. + """ PE = complex2rgb( modeTile(probe_estimate, normalize=True), amplitudeScalingFactor=amplitudeScalingFactor, @@ -143,198 +193,224 @@ def updateProbe( if self.firstrun: self.im_probe = complexPlot(PE, ax=self.ax_probe, **kwargs) self.txt_purityProbe = self.ax_probe.set_title(label) - # self.im_probe_ff = complexPlot(PE_ff, self.ax_probe_ff, **kwargs) else: self.im_probe.set_data(PE) - # self.im_probe_ff.set_data(PE_ff) - if ( - optimizable.npsm > 1 - and optimizable.purityProbe == optimizable.purityProbe - ): - self.txt_purityProbe.set_text( - "%s\nPurity: %.2f" % (label, 100 * optimizable.purityProbe) + "%" - ) + # purity is NaN until it is first computed + if purity is not None and not math.isnan(float(purity)): + self.txt_purityProbe.set_text(f"{label}\nPurity: {100 * purity:.2f}%") self.im_probe.autoscale() - def updateError(self, error_estimate: np.ndarray) -> None: - """ - Update the error estimate plot. - :param error_estimate: - :return: - """ + def updateError(self, error_estimate) -> None: + """Plot the error metric of every iteration so far on log-log axes. - if self.firstrun: - self.error_metric_plot = self.ax_error_metric.plot( - error_estimate, "o-", mfc="none" - )[0] - else: - if len(error_estimate) > 1 and error_estimate[-1] == error_estimate[-1]: - self.error_metric_plot.set_data( - np.arange(len(error_estimate)) + 1, error_estimate - ) - self.ax_error_metric.set_xlim(1, len(error_estimate)) - self.ax_error_metric.set_ylim( - np.min(error_estimate), np.max(error_estimate) - ) - data_aspect = np.log( - np.max(error_estimate) / np.min(error_estimate) - ) / np.log(len(error_estimate)) - self.ax_error_metric.set_aspect(1 / data_aspect) - self.ax_error_metric.set_title( - f"Error metric (it {len(error_estimate)})" - ) - - def drawNowScript(self): + Args: + error_estimate (array-like): One error value per completed iteration. """ - Forces the image to be drawn - :return: - """ - if self.firstrun: - self.figure.show() - self.firstrun = False + error = np.asarray(gpuUtils.asNumpyArray(error_estimate), dtype=float) + # iterations count from 1, as 0 cannot be shown on a log axis + iterations = np.arange(1, len(error) + 1) - # Reopen the figure if the window is closed - if not plt.fignum_exists(self.figNum): - self.figure.show() - - self.canvas.draw_idle() - self.canvas.flush_events() - - def drawNowIpython(self): if self.firstrun: - self.display_id = display(self.figure, display_id=True) - self.firstrun = False - else: - clear_output(wait=True) - self.display_id = display( - self.figure, display_id=self.display_id.display_id + (self.error_metric_plot,) = self.ax_error_metric.plot( + iterations, error, "o-", mfc="none" ) - self.canvas.draw_idle() - self.canvas.flush_events() - - def drawNow(self): - if is_inline(): - self.drawNowIpython() else: - self.drawNowScript() + self.error_metric_plot.set_data(iterations, error) + if len(error) > 0: + ax = self.ax_error_metric + # rescale to the data; the log axes ignore non-positive and NaN values + ax.relim() + ax.autoscale_view() + ax.set_title(f"Error metric (it {len(error)})") -class DiffractionDataPlot(object): - def __init__(self, figNum=2): - """Create a monitor. - In principle, to use this method all you have to do is initialize the monitor and then call +class DiffractionDataPlot(_LiveFigure): + r"""Figure with the estimated and measured diffraction intensity, side by side. - updateImeasured, updateIestimated and drawnow to ensure that something is drawn immediately. + Both are shown as $\log_{10}(I + 1)$, with the colour limits of the measured + intensity applied to the estimate so the two can be compared directly. - For example usage, see test_matplot_monitor.py. + Args: + figNum (int, optional): pyplot figure number. Defaults to 2. + """ - """ + def __init__(self, figNum=2): self.figNum = figNum self._createFigure() - # Get a reference to the figure canvas - self.canvas = self.figure.canvas - self.display_id = None # Added attribute - def _createFigure(self) -> None: - """ - Create the figure. - :return: - """ - - # add an axis for the object - plt.ion() - self.figure, axes = plt.subplots( - 1, 2, num=self.figNum, squeeze=False, clear=True, figsize=(8, 3) - ) + """Create the figure with an estimated and a measured intensity panel.""" + # interactive mode only matters for GUI windows; leave notebook sessions alone + if not is_inline(): + plt.ion() + # see ObjectProbeErrorPlot._createFigure for why size is set separately + self.figure = plt.figure(num=self.figNum, clear=True) + self.figure.set_size_inches(8, 3) + axes = self.figure.subplots(1, 2, squeeze=False) self.ax_Iestimated = axes[0][0] self.ax_Imeasured = axes[0][1] self.ax_Iestimated.set_title("Estimated intensity") self.ax_Imeasured.set_title("Measured intensity") self.figure.tight_layout() - self.firstrun = True + self._attach_figure(self.figure) def updateIestimated(self, Iestimate, cmap="gray", **kwargs): - # move it to CPU if it's on the GPU - Iestimate = gpuUtils.asNumpyArray(Iestimate) + """Show the estimated intensity; its colour limits are set by `update_view`. + Args: + Iestimate (np.ndarray): Estimated detector intensity, CPU or GPU. + cmap (str or Colormap, optional): Colour map. Defaults to `"gray"`. + """ + Iestimate = gpuUtils.asNumpyArray(Iestimate) if self.firstrun: - self.im_Iestimated: AxesImage = self.ax_Iestimated.imshow( np.log10(np.squeeze(Iestimate + 1)), cmap=cmap, interpolation=None ) - divider = make_axes_locatable(self.ax_Iestimated) cax = divider.append_axes("right", size="5%", pad=0.1) - self.IestimatedCbar = plt.colorbar( + self.IestimatedCbar = self.figure.colorbar( self.im_Iestimated, ax=self.ax_Iestimated, cax=cax ) - # scale it according to I measured - else: self.im_Iestimated.set_data(np.log10(np.squeeze(Iestimate + 1))) - # self.im_Iestimated.autoscale() - # self.im_Iestimated.set_ def updateImeasured(self, Imeasured, cmap="gray", **kwargs): + """Show the measured intensity, with colour limits fitted to it. + + Args: + Imeasured (np.ndarray): Measured detector intensity, CPU or GPU. + cmap (str or Colormap, optional): Colour map. Defaults to `"gray"`. + """ Imeasured = gpuUtils.asNumpyArray(Imeasured) if self.firstrun: self.im_Imeasured: AxesImage = self.ax_Imeasured.imshow( np.log10(np.squeeze(Imeasured + 1)), cmap=cmap, interpolation=None ) - divider = make_axes_locatable(self.ax_Imeasured) cax = divider.append_axes("right", size="5%", pad=0.1) - self.ImeasuredCbar = plt.colorbar( + self.ImeasuredCbar = self.figure.colorbar( self.im_Imeasured, ax=self.ax_Imeasured, cax=cax ) - else: self.im_Imeasured.set_data(np.log10(np.squeeze(Imeasured + 1))) self.im_Imeasured.autoscale() - def drawNowScript(self): - """ - Forces the image to be drawn - :return: + def update_view(self, Iestimated, Imeasured, cmap): + """Show both intensities with the colour limits of the measured one. + + Args: + Iestimated (np.ndarray): Estimated detector intensity. + Imeasured (np.ndarray): Measured detector intensity. + cmap (str or Colormap): Colour map of both panels. """ - if self.firstrun: - self.figure.show() - self.firstrun = False + self.updateImeasured(Imeasured, cmap=cmap) + self.updateIestimated(Iestimated, cmap=cmap) + self.im_Iestimated.set_clim(*self.im_Imeasured.get_clim()) - # Reopen the figure if the window is closed - if not plt.fignum_exists(self.figNum): - self.figure.show() - self.canvas.draw_idle() - self.canvas.flush_events() +class ParameterHistoryPlot(_LiveFigure): + """Traces of the quantities an engine changes besides object and probe. - def drawNowIpython(self): - if self.firstrun: - self.display_id = display(self.figure, display_id=True) - self.firstrun = False - else: - clear_output(wait=True) - self.display_id = display( - self.figure, display_id=self.display_id.display_id - ) - self.canvas.draw_idle() - self.canvas.flush_events() + Each update records one value per line, grouped into panels (e.g. the panel + "purity [%]" with lines "object" and "probe"). A panel is only drawn once one of + its lines has changed from its first value, so quantities the engine never + touches (a fixed zo, a single-mode purity) stay hidden. The scan-position + panel appears once position correction has moved a position. - def drawNow(self): - if is_inline(): - self.drawNowIpython() - else: - self.drawNowScript() + The figure is created on the first draw that has something to show, so no + window opens for a reconstruction that changes nothing. + """ - def update_view(self, Iestimated, Imeasured, cmap): - """Update the I measured and I estimated and make sure that the colormaps have the same limits""" - self.updateImeasured(Imeasured, cmap=cmap) - self.updateIestimated(Iestimated, cmap=cmap) - self._equalize_contrast() + def __init__(self, figNum=3): + self.figNum = figNum + self.figure = None + # panel title -> line label -> ([iterations], [values]) + self.history = {} + # (measured, corrected) positions in m, only kept once they differ + self.positions = None + + def record(self, iteration, values): + """Append one value per line. + + Args: + iteration (int): Iteration the values belong to. + values (dict[str, dict[str, float]]): Panel title -> line label -> value. + """ + for panel, lines in values.items(): + for label, value in lines.items(): + its, vals = self.history.setdefault(panel, {}).setdefault( + label, ([], []) + ) + its.append(iteration) + vals.append(value) + + def record_positions(self, measured, corrected): + """Keep the scan positions if position correction has moved any of them.""" + measured = gpuUtils.asNumpyArray(measured) + corrected = gpuUtils.asNumpyArray(corrected) + if not np.array_equal(measured, corrected): + # corrected is edited in place by the engine, so keep a copy + self.positions = (measured, corrected.copy()) + + def active_panels(self): + """Titles of the panels whose values have changed, in recording order.""" + return [ + panel + for panel, lines in self.history.items() + if any( + not np.allclose(vals, vals[0], rtol=1e-6, atol=0) + for _, vals in lines.values() + ) + ] + + def draw(self): + """Redraw every active panel; does nothing while no panel is active.""" + panels = self.active_panels() + n = len(panels) + (self.positions is not None) + if n == 0: + return + + if self.figure is None: + # interactive mode only matters for GUI windows + if not is_inline(): + plt.ion() + self._attach_figure(plt.figure(num=self.figNum, clear=True)) + else: + # the number of panels can grow, so rebuild the axes on every draw; + # a handful of line plots is cheap next to the object/probe images + self.figure.clf() + self.figure.set_size_inches(3.2 * n, 3, forward=True) + + axes = np.atleast_1d(self.figure.subplots(1, n)) + for ax, panel in zip(axes, panels): + for label, (its, vals) in self.history[panel].items(): + ax.plot(its, vals, ".-", label=label) + ax.set_title(panel) + ax.set_xlabel("iterations") + # show absolute values (49.99 mm), not an offset plus tiny ticks + ax.ticklabel_format(axis="y", useOffset=False) + ax.grid(True, alpha=0.3) + if len(self.history[panel]) > 1: + ax.legend(fontsize="small") + + if self.positions is not None: + measured, corrected = self.positions + ax = axes[-1] + # encoder positions are (y, x) in m; plot x horizontally, in mm + ax.plot( + measured[:, 1] * 1e3, + measured[:, 0] * 1e3, + "o", + mfc="none", + label="measured", + ) + ax.plot( + corrected[:, 1] * 1e3, corrected[:, 0] * 1e3, ".", label="corrected" + ) + ax.set_title("scan positions [mm]") + ax.set_aspect("equal", adjustable="datalim") + ax.legend(fontsize="small") - def _equalize_contrast(self): - """Adopt the contrast limits from the measured data and apply them to the predicted""" - clims = self.im_Imeasured.get_clim() - self.im_Iestimated.set_clim(*clims) + self.figure.tight_layout() + self.drawNow() diff --git a/PtyLab/Monitor/TensorboardMonitor.py b/PtyLab/Monitor/TensorboardMonitor.py index fb9dc316..bdc767b2 100644 --- a/PtyLab/Monitor/TensorboardMonitor.py +++ b/PtyLab/Monitor/TensorboardMonitor.py @@ -23,7 +23,7 @@ from PtyLab.Monitor.Monitor import AbstractMonitor from PtyLab.utils.gpuUtils import asNumpyArray from PtyLab.utils.utils import fft2c -from PtyLab.utils.visualisation import complex2rgb, complex2rgb_vectorized +from PtyLab.utils.visualisation import complex2rgb_vectorized def center_angle(object_estimate): @@ -65,7 +65,7 @@ class TensorboardMonitor(AbstractMonitor): downsample_everything = 1 def __init__(self, logdir="./logs_tensorboard", name=None): - super(AbstractMonitor).__init__() + super().__init__() # if true, all phases are centered in such a way that the average phase in the center of any RGB plot is zero. self.center_phases = True if name is None: @@ -110,7 +110,6 @@ def visualize_probe_engine(self, engine): engine.get_fundamental(), center_phase=self.center_phases ) self.__safe_upload_image("original probe", np.squeeze(RGB_image), self.i) - pass def updateObjectProbeErrorMonitor( self, @@ -222,9 +221,6 @@ def update_encoder( :param scaling: :return: """ - # convert the positions to mm - corrected_positions = corrected_positions - original_positions = original_positions # set them to mean 0 corrected_positions = corrected_positions - corrected_positions.mean( axis=0, keepdims=True @@ -237,9 +233,7 @@ def update_encoder( import matplotlib.pyplot as plt # make a fov that makes sense - scale_0 = 1.1 - if scaling > scale_0: - scale_0 = scaling + scale_0 = max(1.1, scaling) position_range = ( np.min(original_positions.flatten()), @@ -270,8 +264,7 @@ def update_encoder( # plot the original one everywhere - for name, ax in axes.items(): - ax: plt.Axes = ax + for ax in axes.values(): ax.scatter( original_positions[:, 0], original_positions[:, 1], @@ -375,13 +368,9 @@ def _update_object_estimate( if highres: I_object = abs(object_estimate**2) - std_obj = I_object.std() - mean_obj = I_object.mean() - min_int = 0 # mean_obj - 2 * std_obj - # max_int = np.min((mean_obj + 2 * std_obj, I_object.max())) + min_int = 0 N = I_object.shape[-1] roi = slice(N // 2 - N // 5, N // 2 + N // 5) - # max_int = I_object[...,roi,roi].max() from scipy import ndimage max_int = ndimage.gaussian_filter(I_object, 3)[..., roi, roi].max() @@ -416,7 +405,7 @@ def _update_object_estimate( if zo is not None: plt.title(f"z = {zo * 1e3:.3f} mm") plt.savefig(f"intensities/{self.i}.png") - plt.savefig(f"intensities/AAA.png") + plt.savefig("intensities/AAA.png") def _update_probe_estimate(self, probe_estimate, highres=True): # first, convert it to images @@ -498,9 +487,8 @@ def __safe_upload_image(self, name, data, step, max_outputs=3, description=None) ) def __safe_upload_scalar(self, name, data, step, description=None): - if isinstance(data, list): - if data == []: - return # initialization, not required for tensorboard, ignore it + if isinstance(data, list) and data == []: + return # initialization, not required for tensorboard, ignore it data = asNumpyArray(data) try: # only take the last one in case of a list @@ -539,7 +527,7 @@ def update_purities(self, probe_purity, object_purity): self._update_probe_purity(probe_purity) def describe_parameters(self, params: Params): - text = "\n".join(["%s: %s" % (k, d) for (k, d) in params.__dict__.items()]) + text = "\n".join([f"{k}: {d}" for (k, d) in params.__dict__.items()]) with self.writer.as_default(): tfs.text( "summary parameters", text, step=self.i, description="initial settings" diff --git a/PtyLab/Monitor/frame.py b/PtyLab/Monitor/frame.py new file mode 100644 index 00000000..4c6c15e1 --- /dev/null +++ b/PtyLab/Monitor/frame.py @@ -0,0 +1,164 @@ +from dataclasses import dataclass +from typing import Any + +import numpy as np + +from PtyLab.utils.gpuUtils import asNumpyArray +from PtyLab.utils.utils import fft2c + +FULL_ROI = (slice(None), slice(None)) + + +def panel_geometry(reconstruction) -> dict: + """Axis steps, units and labels of the object and probe panels. + + FPM reconstructs the object spectrum and a pupil, so the panels use the FPM + object sampling `dxo_fpm` and the pupil-plane step `dfp` (a spatial frequency) + instead of `dxo` and `dxp`. + + Args: + reconstruction (Reconstruction): Reconstruction whose sampling is shown. + + Returns: + dict: The `MonitorFrame` fields `object_pixel_size`, `probe_pixel_size`, + `probe_axis_unit` and `probe_label`. + """ + if reconstruction.data.operationMode == "FPM": + return { + "object_pixel_size": reconstruction.dxo_fpm, + "probe_pixel_size": reconstruction.dfp, + "probe_axis_unit": "1/um", + "probe_label": "Pupil estimate", + } + return { + "object_pixel_size": reconstruction.dxo, + "probe_pixel_size": reconstruction.dxp, + "probe_axis_unit": "mm", + "probe_label": "Probe estimate", + } + + +@dataclass +class MonitorFrame: + """One snapshot of the reconstruction state, handed to a monitor. + + The engine builds one frame per monitor update and passes it to + `AbstractMonitor.update`. The monitor decides what to show from it. + + The array fields are references to the live reconstruction arrays (CPU or GPU), + not copies, so building a frame is cheap even when the monitor ignores it. They + are only valid during the `update` call; a monitor that keeps data for later + must copy it, e.g. through `object_view` and `probe_view`. + + Attributes: + error (np.ndarray): Error metric of every iteration so far. + object (Any): `reconstruction.object`. For FPM this is the object spectrum; + `object_view` transforms it to real space. + probe (Any): `reconstruction.probe` (the pupil for FPM). + operation_mode (str): `"CPM"` or `"FPM"`. + object_roi (tuple[slice, slice]): Region of the object to display. + probe_roi (tuple[slice, slice]): Region of the probe to display. + object_pixel_size (float): Axis step of the object panel in meters. + probe_pixel_size (float): Axis step of the probe panel, in meters for CPM + and in 1/m for FPM. + probe_axis_unit (str): Unit of the probe panel axes. + probe_label (str): Title of the probe panel. + nosm (int): Number of object state mixtures. + npsm (int): Number of probe state mixtures. + purity_object (Any): Object purity, meaningful only when `nosm > 1`. + purity_probe (Any): Probe purity, meaningful only when `npsm > 1`. + zo (Any): Sample-detector distance in meters. + theta (Any): Reflection angle in degrees (aPIE), `None` if not used. + positions (np.ndarray | None): Scan positions in object pixels. + engine_name (str | None): Name of the engine that produced the frame. + encoder_original (np.ndarray | None): Measured encoder positions. + encoder_corrected (np.ndarray | None): Encoder positions after position + correction. + beam_width (tuple[float, float] | None): `(y, x)` probe FWHM in meters. + I_estimated (np.ndarray | None): Estimated detector intensity at the + last scan position, only filled for `verboseLevel == "high"`. + I_measured (np.ndarray | None): Measured detector intensity at the same + position. + area_overlap (float | None): Estimated probe area overlap. + linear_overlap (float | None): Estimated probe linear overlap. + """ + + error: np.ndarray + object: Any + probe: Any + operation_mode: str = "CPM" + object_roi: tuple = FULL_ROI + probe_roi: tuple = FULL_ROI + object_pixel_size: float = 1.0 + probe_pixel_size: float = 1.0 + probe_axis_unit: str = "mm" + probe_label: str = "Probe estimate" + nosm: int = 1 + npsm: int = 1 + purity_object: Any = None + purity_probe: Any = None + zo: Any = None + theta: Any = None + positions: np.ndarray | None = None + engine_name: str | None = None + encoder_original: np.ndarray | None = None + encoder_corrected: np.ndarray | None = None + beam_width: tuple | None = None + I_estimated: np.ndarray | None = None + I_measured: np.ndarray | None = None + area_overlap: float | None = None + linear_overlap: float | None = None + + @classmethod + def from_reconstruction(cls, reconstruction, **fields) -> "MonitorFrame": + """Fill the fields that follow from the reconstruction state. + + The panel sampling comes from `panel_geometry`. The engine must have + initialised `reconstruction.error` first. + + Args: + reconstruction (Reconstruction): Current reconstruction state. + **fields: Further `MonitorFrame` fields (ROIs, engine name, encoder, + beam width, diffraction data, overlaps), passed through unchanged. + + Returns: + MonitorFrame: The snapshot. + """ + return cls( + error=reconstruction.error, + object=reconstruction.object, + probe=reconstruction.probe, + operation_mode=reconstruction.data.operationMode, + **panel_geometry(reconstruction), + nosm=reconstruction.nosm, + npsm=reconstruction.npsm, + purity_object=reconstruction.purityObject, + purity_probe=reconstruction.purityProbe, + zo=reconstruction.zo, + theta=reconstruction.theta, + positions=reconstruction.positions, + **fields, + ) + + @property + def iteration(self) -> int: + """Number of completed iterations.""" + return len(self.error) + + def object_view(self) -> np.ndarray: + """Real-space object inside `object_roi`, as a squeezed NumPy array. + + Leading singleton axes of the 6D array `(nlambda, nosm, 1, nslice, No, No)` + are dropped, so a single-mode object comes back as `(Ny, Nx)`. + """ + # FPM stores the object spectrum; the monitor shows its fft2c, as it always has + obj = fft2c(self.object) if self.operation_mode == "FPM" else self.object + # crop before moving to the CPU so only the displayed region is copied + return np.squeeze( + asNumpyArray(obj[..., self.object_roi[0], self.object_roi[1]]) + ) + + def probe_view(self) -> np.ndarray: + """Probe inside `probe_roi`, as a squeezed NumPy array.""" + probe = self.probe[..., self.probe_roi[0], self.probe_roi[1]] + return np.squeeze(asNumpyArray(probe)) diff --git a/PtyLab/Reconstruction/Reconstruction.py b/PtyLab/Reconstruction/Reconstruction.py index 9fc8f271..656da89b 100644 --- a/PtyLab/Reconstruction/Reconstruction.py +++ b/PtyLab/Reconstruction/Reconstruction.py @@ -1,21 +1,23 @@ +import logging import time -import numpy as np -from PtyLab.ExperimentalData.ExperimentalData import ExperimentalData from copy import copy -import logging +from pathlib import Path + import h5py +import numpy as np -# logging.basicConfig(level=logging.DEBUG) -from PtyLab.Regularizers import metric_at, TV +from PtyLab import Params +from PtyLab.ExperimentalData.ExperimentalData import ExperimentalData -from PtyLab.utils.initializationFunctions import initialProbeOrObject +# logging.basicConfig(level=logging.DEBUG) +from PtyLab.Regularizers import TV, metric_at from PtyLab.utils.gpuUtils import ( + asNumpyArray, + getArrayModule, transfer_fields_to_cpu, transfer_fields_to_gpu, - getArrayModule, ) -from PtyLab import Params -from PtyLab.utils.gpuUtils import asNumpyArray +from PtyLab.utils.initializationFunctions import initialProbeOrObject def calculate_pixel_positions(encoder_corrected, dxo, No, Np, asint): @@ -371,14 +373,16 @@ def zo(self, new_value): self.logger.debug(f"Changing sample-detector distance to {new_value}") self.dxp = self.wavelength * self._zo / self.Ld elif self.data.operationMode == "FPM": - self.logger.debug(f"Changing illumination-to-sample distance to {new_value}") - self.zled = self._zo - + self.logger.debug( + f"Changing illumination-to-sample distance to {new_value}" + ) + self.zled = self._zo + def computeParameters(self): """ Compute reconstruction geometry and mode-dependent default parameters. - For CPM, missing probe and spectral parameters are initialized from the current reconstruction geometry. + For CPM, missing probe and spectral parameters are initialized from the current reconstruction geometry. For FPM, the sample-plane sampling and pupil geometry are derived from the microscope magnification and numerical aperture. @@ -428,12 +432,14 @@ def computeParameters(self): ) # set object pixel numbers - if not hasattr(self, 'No'): + if not hasattr(self, "No"): self.No = ( self.Np * 2**2 ) # unimportant but leave it here as it's required for self.positions # we need space for the probe as well, on both sides that would be half the probe - range_pixels = np.max(self.positions, axis=0) - np.min(self.positions, axis=0) + range_pixels = np.max(self.positions, axis=0) - np.min( + self.positions, axis=0 + ) # print(range_pixels) range_pixels = np.max(range_pixels) + self.Np * 2 if range_pixels % 2 == 1: @@ -485,17 +491,25 @@ def make_alignment_plot(self, saveit=False): ax = axes["alignment"] ax.scatter( - p_old[:, 1], p_old[:, 0], marker="s", s=12, c="gold", - edgecolors="k", linewidths=0.3, label="original", + p_old[:, 1], + p_old[:, 0], + marker="s", + s=12, + c="gold", + edgecolors="k", + linewidths=0.3, + label="original", ) ax.scatter(p_new[:, 1], p_new[:, 0], marker="o", s=12, c="red", label="new") ax.set_aspect("equal") ax.invert_yaxis() # row 0 at the top, as in the reconstructed image ax.set_xlabel("column [px]") ax.set_ylabel("row [px]") - ax.set_title(f'alignment (updated {time.strftime("%Y%h%d, %H:%M:%S")})') + ax.set_title(f"alignment (updated {time.strftime('%Y%h%d, %H:%M:%S')})") # legend below the axes so it never hides scan points - ax.legend(loc="upper center", bbox_to_anchor=(0.5, -0.15), ncol=2, frameon=False) + ax.legend( + loc="upper center", bbox_to_anchor=(0.5, -0.15), ncol=2, frameon=False + ) if "focus" in axes: # defocus estimate per iteration ax = axes["focus"] @@ -515,7 +529,11 @@ def make_alignment_plot(self, saveit=False): ax = axes["merit"] ax.plot(self.dz * 1e3, np.array(self.merit), "o", ms=3, label="original") ax.plot( - -self.dz * 1e3, np.array(self.merit), "s", ms=3, color="red", + -self.dz * 1e3, + np.array(self.merit), + "s", + ms=3, + color="red", label="mirrored", ) ax.set_xlabel("Defocus [mm]") @@ -532,7 +550,7 @@ def make_alignment_plot(self, saveit=False): fig.savefig(output, dpi=100) t1 = time.time() - print(f"Alignment display took {t1-t0} secs") + print(f"Alignment display took {t1 - t0} secs") return fig return p @@ -609,7 +627,7 @@ def initializeObjectProbe(self, force=True): force (bool, optional): Forwarded to the object and probe initialization methods. Defaults to True. - """ + """ # initialize object and probe self.initializeObject(force=force) self.initializeProbe(force=force) @@ -658,17 +676,21 @@ def initializeObject(self, type_of_init=None, force=True): self.No, self.No, ) - if self.initialObject == 'recon': + if self.initialObject == "recon": # Load the object from an existing reconstruction. Confusing filename, but it contains both object and probe. - self.initialGuessObject = self.loadResults(self.initialProbe_filename, datatype='object') + self.initialGuessObject = self.loadResults( + self.initialProbe_filename, datatype="object" + ) else: - self.initialGuessObject = initialProbeOrObject(self.shape_O, self.initialObject, self, self.logger).astype(np.complex64) + self.initialGuessObject = initialProbeOrObject( + self.shape_O, self.initialObject, self, self.logger + ).astype(np.complex64) # self.initialGuessObject *= 1e-2 @staticmethod - def loadResults(fileName, datatype='probe'): - ''' + def loadResults(fileName, datatype="probe"): + """ Load an object or probe from a saved PtyLab reconstruction. Args: @@ -682,7 +704,7 @@ def loadResults(fileName, datatype='probe'): Returns: np.ndarray: Copy of the requested reconstruction dataset. - ''' + """ with h5py.File(fileName) as archive: data = np.copy(np.array(archive[datatype])) return data @@ -724,8 +746,10 @@ def initializeProbe(self, force=False): int(self.Np), ) - if self.initialProbe == 'recon': - self.initialGuessProbe = self.loadResults(self.initialProbe_filename, datatype='probe') + if self.initialProbe == "recon": + self.initialGuessProbe = self.loadResults( + self.initialProbe_filename, datatype="probe" + ) else: if force: self.initialGuessProbe = None @@ -777,7 +801,7 @@ def load_object(self, filename): self.object = obj else: raise RuntimeError( - f'Shape of saved object cannot be extended to shape of required object. File: {archive["object"].shape}. Need: {self.shape_O}' + f"Shape of saved object cannot be extended to shape of required object. File: {archive['object'].shape}. Need: {self.shape_O}" ) def load_probe(self, filename, expand_npsm=False, center_phase=False): @@ -813,19 +837,18 @@ def load_probe(self, filename, expand_npsm=False, center_phase=False): probe = np.array(archive["probe"]) N_probe_read = probe.shape[-1] # roughly extract the center - ss = slice(np.clip(N_probe_read//2-self.Np//2, 0, None), np.clip(N_probe_read//2-self.Np//2+int(self.Np), 0, N_probe_read)) - probe = probe[ - : self.nlambda, - :1, - : self.npsm, - : self.nslice, - ss,ss - ] + ss = slice( + np.clip(N_probe_read // 2 - self.Np // 2, 0, None), + np.clip( + N_probe_read // 2 - self.Np // 2 + int(self.Np), 0, N_probe_read + ), + ) + probe = probe[: self.nlambda, :1, : self.npsm, : self.nslice, ss, ss] if np.all(np.array(probe.shape) == np.array(self.shape_P)): self.probe = probe else: raise RuntimeError( - f'Shape of saved probe cannot be extended to shape of required probe. File: {archive["probe"].shape}. Need: {self.shape_P}' + f"Shape of saved probe cannot be extended to shape of required probe. File: {archive['probe'].shape}. Need: {self.shape_P}" ) if center_phase: self._center_probe_angle() @@ -837,10 +860,13 @@ def _center_probe_angle(self): The offset is estimated from the first probe mode and corrected by applying a compensating phase factor. """ - from skimage.registration import phase_cross_correlation from scipy.ndimage import fourier_shift + from skimage.registration import phase_cross_correlation + p0 = np.squeeze(self.probe)[0] - shift = phase_cross_correlation(p0, 0 * p0 + 1, normalization=None, space='fourier')[0] + shift = phase_cross_correlation( + p0, 0 * p0 + 1, normalization=None, space="fourier" + )[0] phexp = np.fft.fftshift(fourier_shift(0 * p0 + 1j, -shift / 2)) self.probe *= phexp @@ -865,7 +891,6 @@ def load(self, filename): adapt or validate the loaded object and probe shapes. """ with h5py.File(filename, "r") as archive: - self.probe = np.array(archive["probe"]) self.object = np.array(archive["object"]) self.error = np.array(archive["error"]) @@ -877,7 +902,7 @@ def load(self, filename): if "theta" in archive.keys(): self.theta = np.array(archive["theta"]) - def saveResults(self, fileName="recent", type="all", squeeze=False): + def saveResults(self, fileName="recent", type="all", squeeze=False, snapshot=None): """ Save reconstruction results to an HDF5 file. @@ -895,6 +920,13 @@ def saveResults(self, fileName="recent", type="all", squeeze=False): or probe. This option does not affect ``type="all"``. Defaults to False. + snapshot (AbstractMonitor, optional): + Monitor whose current figures are saved as PNG files next to the + HDF5 file, via ``snapshot.saveFigures``. The PNG names reuse + ``fileName`` without its ``.hdf5``/``.h5`` extension, e.g. + ``run.hdf5`` gives ``run_reconstruction.png``. Defaults to None, + which saves no figures. + Raises: NotImplementedError: If an unsupported save type is requested. @@ -926,22 +958,22 @@ def saveResults(self, fileName="recent", type="all", squeeze=False): hf.create_dataset("dxp", data=self.dxp, dtype="f") hf.create_dataset("purityProbe", data=self.purityProbe, dtype="f") hf.create_dataset("purityObject", data=self.purityObject, dtype="f") - hf.create_dataset('I object', data=abs(self.object), dtype='f') - hf.create_dataset('I probe', data=abs(self.probe), dtype='f') - hf.create_dataset('encoder_corrected', data=self.encoder_corrected) + hf.create_dataset("I object", data=abs(self.object), dtype="f") + hf.create_dataset("I probe", data=abs(self.probe), dtype="f") + hf.create_dataset("encoder_corrected", data=self.encoder_corrected) if hasattr(self, "theta"): if self.theta != None: hf.create_dataset("theta", data=self.theta, dtype="f") if self.data.operationMode == "FPM": - hf = h5py.File(fileName, "w") - hf.create_dataset("probe", data=self.probe, dtype="complex64") - hf.create_dataset("object", data=self.object, dtype="complex64") - hf.create_dataset("error", data=self.error, dtype="f") - hf.create_dataset("zled", data=self.zled, dtype="f") - hf.create_dataset("wavelength", data=self.wavelength, dtype="f") - hf.create_dataset("dxp", data=self.dxp, dtype="f") + with h5py.File(fileName, "w") as hf: + hf.create_dataset("probe", data=self.probe, dtype="complex64") + hf.create_dataset("object", data=self.object, dtype="complex64") + hf.create_dataset("error", data=self.error, dtype="f") + hf.create_dataset("zled", data=self.zled, dtype="f") + hf.create_dataset("wavelength", data=self.wavelength, dtype="f") + hf.create_dataset("dxp", data=self.dxp, dtype="f") elif type == "probe": with h5py.File(fileName, "w") as hf: hf.create_dataset( @@ -953,10 +985,21 @@ def saveResults(self, fileName="recent", type="all", squeeze=False): "object", data=squeezefun(self.object), dtype="complex64" ) elif type == "probe_stack": - hf = h5py.File(fileName + '_probe_stack.hdf5', 'w') - hf.create_dataset('probe_stack', data=self.probe_stack.get(), dtype='complex64') + with h5py.File(fileName + "_probe_stack.hdf5", "w") as hf: + hf.create_dataset( + "probe_stack", data=self.probe_stack.get(), dtype="complex64" + ) print("The reconstruction results (%s) have been saved" % type) + if snapshot is not None: + # "results/run.hdf5" -> "results/run_reconstruction.png", ...; other + # suffixes are kept, as they may be part of the name ("run.v2") + prefix = Path(fileName) + if prefix.suffix.lower() in (".hdf5", ".h5"): + prefix = prefix.with_suffix("") + for path in snapshot.saveFigures(prefix): + print("Saved monitor figure %s" % path) + # detector coordinates @property def Nd(self): @@ -1033,8 +1076,7 @@ def Lo(self): @property def dxo_fpm(self): - """Real-space object pixel size for FPM. - """ + """Real-space object pixel size for FPM.""" return self.dxp * self.Np / self.No @property @@ -1141,30 +1183,30 @@ def describe_reconstruction(self): str: Formatted reconstruction summary. """ - minmax_tv = '' + minmax_tv = "" try: - minmax_tv = f'(min: {self.params.TV_autofocus_min_z*1e3}, max: {self.params.TV_autofocus_max_z*1e3}.)' - except TypeError: # one of them is none + minmax_tv = f"(min: {self.params.TV_autofocus_min_z * 1e3}, max: {self.params.TV_autofocus_max_z * 1e3}.)" + except TypeError: # one of them is none pass info = f""" Experimental data: - Ptychogram shape: {self.data.ptychogram.shape} - Ptychogram size[px]: {self.data.Nd} - - Ptychogram size: {self.data.Ld*1e3} mm - - Pixel pitch: {self.data.dxd*1e6} um - - Scan size: {1e3*(self.data.encoder.max(axis=0) - self.data.encoder.min(axis=0))} mm + - Ptychogram size: {self.data.Ld * 1e3} mm + - Pixel pitch: {self.data.dxd * 1e6} um + - Scan size: {1e3 * (self.data.encoder.max(axis=0) - self.data.encoder.min(axis=0))} mm Reconstruction: - number of pixels: {self.No} - - Pixel pitch: {self.dxo*1e6} um - - Field of view: {self.Lo*1e3} mm - - Scan size in pixels: {self.positions.max(axis=0)- self.positions.min(axis=0)} + - Pixel pitch: {self.dxo * 1e6} um + - Field of view: {self.Lo * 1e3} mm + - Scan size in pixels: {self.positions.max(axis=0) - self.positions.min(axis=0)} - Propagation distance: {self.zo * 1e3} mm {minmax_tv} - - Probe FoV: {self.Lp*1e3} mm + - Probe FoV: {self.Lp * 1e3} mm Derived parameters: - NA detector: {self.NAd} - - Depth of field: {self.DoF*1e6} um + - Depth of field: {self.DoF * 1e6} um """ self.logger.info(info) @@ -1191,7 +1233,6 @@ def Q2(self): raise NotImplementedError("Q2 is no longer available") def TV_autofocus(self, params: Params, loop): - """ Perform one autofocus update by optimizing a propagated-field metric. @@ -1290,15 +1331,19 @@ def TV_autofocus(self, params: Params, loop): ) self.zo -= delta_z end_time = time.time() - self.logger.info( - f"TV autofocus took {end_time-start_time} seconds, and moved focus by {-delta_z*1e6} micron" + self.logger.debug( + f"TV autofocus took {end_time - start_time} seconds, and moved focus by {-delta_z * 1e6} micron" ) - indices = [nplanes//2, np.argmax(merit)] + indices = [nplanes // 2, np.argmax(merit)] OEs = OEs[indices] - phexp = OEs.sum((-2,-1), keepdims=True).conj() + phexp = OEs.sum((-2, -1), keepdims=True).conj() phexp = phexp / abs(phexp) OEs *= phexp - return merit[nplanes//2] / asNumpyArray(abs(self.object[..., sy, sx]).mean()), np.hstack(OEs), (scores, self.zo) + return ( + merit[nplanes // 2] / asNumpyArray(abs(self.object[..., sy, sx]).mean()), + np.hstack(OEs), + (scores, self.zo), + ) def reset_TV_autofocus(self): """ diff --git a/PtyLab/utils/visualisation.py b/PtyLab/utils/visualisation.py index 7c94a2e2..3eabcac4 100644 --- a/PtyLab/utils/visualisation.py +++ b/PtyLab/utils/visualisation.py @@ -155,7 +155,10 @@ def complexPlot(rgb, ax=None, pixelSize=1, axisUnit="pixel"): norm = mpl.colors.Normalize(vmin=-np.pi, vmax=np.pi) scalar_mappable = mpl.cm.ScalarMappable(norm=norm, cmap=mpl.cm.hsv) scalar_mappable.set_array([]) - cbar = plt.colorbar(scalar_mappable, ax=ax, cax=cax, ticks=[-np.pi, 0, np.pi]) + # colorbar on the axes' own figure, not pyplot's current one + cbar = ax.figure.colorbar( + scalar_mappable, ax=ax, cax=cax, ticks=[-np.pi, 0, np.pi] + ) cbar.ax.set_yticklabels([r"$-\pi$", "0", r"$\pi$"]) return im diff --git a/example_scripts/exampleMonitorGUI.py b/example_scripts/exampleMonitorGUI.py new file mode 100644 index 00000000..97507251 --- /dev/null +++ b/example_scripts/exampleMonitorGUI.py @@ -0,0 +1,114 @@ +""" +Live reconstruction monitor, in GUI windows or in Jupyter cells. To mainly explore the +monitor visualization options + +Runs a short mPIE reconstruction and shows the default `Monitor`: object, probe and +error metric; the estimated vs measured diffraction intensity; and the history of +the other quantities the engine changes (zo, purities, scan positions). + +As a script, the monitor opens its own windows, which stay open after the run +until you close them: + + $ python example_scripts/exampleMonitorGUI.py [--file ] [--iterations 20] + [--autofocus] [--position-correction] [--modes 3] + +Cell by cell (`# %%`, e.g. "Run Cell" in VS Code), the figures appear as cell +outputs and update in place. Change the settings by editing `args` in the +settings cell; re-running the reconstruction cell continues from the current +estimate. + +The flags switch on reconstruction features that change those quantities, so +their panels appear in the history window. +""" + +# %% Imports +import argparse +import sys +from pathlib import Path + +import matplotlib.pyplot as plt + +import PtyLab +from PtyLab import Engines +from PtyLab.io import getExampleDataFolder +from PtyLab.Monitor.Plots import is_inline + +# %% Settings +# allow_abbrev=False: the Jupyter kernel's own `--f=.json` must not be +# read as an abbreviation of `--file` +parser = argparse.ArgumentParser(description="Live monitor preview", allow_abbrev=False) +parser.add_argument("--file", type=str, default=f"{getExampleDataFolder()}/simu.hdf5") +parser.add_argument("--iterations", type=int, default=20) +parser.add_argument("--autofocus", action="store_true", help="TV autofocus: zo changes") +parser.add_argument( + "--position-correction", + action="store_true", + help="position correction: scan positions change", +) +parser.add_argument( + "--modes", + type=int, + default=1, + help="number of probe modes; >1 with orthogonalization changes the purity", +) +# parse_known_args ignores the arguments a Jupyter kernel is started with +args, _ = parser.parse_known_args() + +# when running cell by cell, override here, e.g. +# args.autofocus = True +# args.modes = 3 + +# a script needs a GUI backend to open windows; matplotlib falls back to a +# non-interactive one (e.g. Agg) when there is no display +backend = plt.get_backend().lower() +if not is_inline() and backend in ("agg", "pdf", "ps", "svg", "cairo", "template"): + sys.exit( + f"matplotlib backend is '{backend}', which cannot open a window. " + "Run this on a machine with a display, or set MPLBACKEND=QtAgg / TkAgg." + ) + +# %% Data and parameters +experimentalData, reconstruction, params, monitor, _ = PtyLab.easyInitialize( + args.file, operationMode="CPM" +) +params.gpuSwitch = False +params.comStabilizationSwitch = True + +if args.autofocus: + params.TV_autofocus = True + params.TV_autofocus_run_every = 1 # update zo every iteration +if args.position_correction: + params.positionCorrectionSwitch = True +if args.modes > 1: + reconstruction.npsm = args.modes + # the purity is only recomputed when the modes are orthogonalized + params.orthogonalizationSwitch = True + params.orthogonalizationFrequency = 1 + +monitor.figureUpdateFrequency = 1 # redraw after every iteration +monitor.verboseLevel = "high" # also show the diffraction intensities +monitor.objectPlot = "complex" # complex | abs | angle +monitor.showParameterHistory = True # third figure: zo, purity, scan positions + +reconstruction.initializeObjectProbe() + +# mPIE calls showReconstruction every iteration (ePIE currently does not) +engine = Engines.mPIE(reconstruction, experimentalData, params, monitor) +engine.numIterations = args.iterations +if args.position_correction: + engine.startAtIteration = 1 # position correction is off before this iteration + +# %% Reconstruct (re-run to continue from the current estimate) +engine.reconstruct() + +# %% Save the reconstruction plus a PNG of every monitor figure +# results/monitor.hdf5, results/monitor_reconstruction.png, ... +Path("results").mkdir(exist_ok=True) +reconstruction.saveResults("results/monitor.hdf5", snapshot=monitor) + +# %% Keep the windows open (script only) +if not is_inline(): + # the monitor runs in interactive mode; switch it off so show() blocks and + # the windows stay open after the reconstruction finishes + plt.ioff() + plt.show() diff --git a/jupyter_tutorials/jupyter_tutorials_tutorial_CPM_sim.ipynb b/jupyter_tutorials/jupyter_tutorials_tutorial_CPM_sim.ipynb index 97a4686c..fa73c2a9 100644 --- a/jupyter_tutorials/jupyter_tutorials_tutorial_CPM_sim.ipynb +++ b/jupyter_tutorials/jupyter_tutorials_tutorial_CPM_sim.ipynb @@ -338,7 +338,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -351,7 +351,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "69f1776d350a4300993be78a06578b64", + "model_id": "76887b665771485fa1175360f286446d", "version_major": 2, "version_minor": 0 }, @@ -393,7 +393,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -444,7 +444,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "/mnt/home/shantanu/projects/PtyLab.py/PtyLab/Monitor/Monitor.py:178: UserWarning: For faster update of the reconstruction plot, set `monitor.figureUpdateFrequency = 5` or higher.\n", + "/mnt/home/shantanu/projects/PtyLab.py/PtyLab/Monitor/Monitor.py:262: UserWarning: For faster update of the reconstruction plot, set `monitor.figureUpdateFrequency = 5` or higher.\n", " warnings.warn(\n" ] } @@ -540,22 +540,1444 @@ "execution_count": 17, "metadata": {}, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:mPIE:Successfully created mPIE engine\n", + "INFO:mPIE:Wavelength attribute: 6.328e-07\n" + ] + }, + { + "data": { + "image/png": "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uaUhzurVq/mXf/kX5s2bR7lcZt999+WrX/3qpMv/rW99i4MOOojW1lZ6e3s59dRTWbVqVSLO/fffz2te8xrmz59PS0sLixcv5tRTT2XTpk3A+ON21l64pUuX8vKXv5ybb76Zgw8+mNbWVvbff39uvvlmAH784x+7OeKggw7i7rvvTpTnnnvu4U1vehO77747LS0tzJ8/n3/5l39h48aNLs6FF17IBz7wAQB22203Vy6/HJOpe44cObYv/PXT5ZdfzrJlyyiXy/z1r391/nP++te/8rrXvY6enh5e8IIXAJpQf/zjH3fxly5dyoc//OGG9Y4dX6677jo3voxnnvvCF76Q/fbbj3vuuYejjz6atrY2li9fzo9+9CMAfv3rX3PYYYfR2trKXnvtxQ033NCQxkTj8ERrTFuGO++8k6OOOoq2tja3Ps3aszw2NsaFF17InnvuSUtLCwsWLODVr341Dz744Lht/5Of/IRSqcRRRx2VCE+P00uXLuXee+/l17/+tSvrRPumlyxZQhBMTAF/9KMfEYYhZ511lgtraWnhzDPP5LbbbnNj8NDQEL/85S85/fTTHVEGTaw7Ojr4wQ9+kEj3oIMOore3l2uvvXbCMjwVkGuWpxn/8z//w9KlSznyyCMz7x911FEsXbqUn/70pw33TjnlFJYuXcrFF1/M7bffzuc//3kGBgb45je/2TS/kZERjj76aFavXs3b3vY2dtllF2699VbOO+88nnzyycR+2zPPPJOvf/3rvPSlL+Utb3kL9Xqd3/zmN9x+++0cfPDBXH311bzlLW/h0EMPdT+kZcuWNc1bSskrX/lKfvvb33LWWWex99578+c//5nPfe5z/OMf/3B76O69915e/vKX8+xnP5uPfexjlMtlHnjgAX73u98BsPfee/Oxj32M888/n7POOsu13RFHHDFuW3/729+mWq3yrne9i/7+fj7zmc9wyimn8KIXvYibb76ZD33oQzzwwAN84Qtf4P3vf39i8Pz6179OR0cH55xzDh0dHfzqV7/i/PPPZ2hoiEsuuQSAj3zkI2zatInHH3+cz33ucwB0dHRMqe45cuTYcbCLk76+PhdWr9c57rjjeMELXsCll15KW1sbSile+cpXctNNN3HmmWdy4IEHct111/GBD3yA1atXu9+3xa9//Wu+//3v8+53v5tyucwXv/hFjj/+eO644w4ntV+7di3Pe97znEOwOXPm8POf/5wzzzyToaEh3vve945b9k9+8pP8v//3/zjllFN4y1vewvr16/nCF77AUUcdxd13382sWbOoVqscd9xxVCoV3vWudzF//nxWr17N//7v/zI4OEh3d/eUx22ABx54gNe97nW87W1v4/TTT+fSSy/lFa94BVdeeSUf/vCHeec73wnAxRdfzCmnnMLf//53txD75S9/yUMPPcSb3/xm5s+fz7333stVV13Fvffey+23344Qgle/+tX84x//4Lvf/S6f+9znmD17NoATIE+m7jly5Jg6Nm3a1OAsVgiRGCMBvva1rzE2NsZZZ51FuVymt7fX3Tv55JPZY489+NSnPuWEiW95y1v4xje+wUknncT73vc+fv/733PxxRfzt7/9jf/6r/9KpP33v/+d0047jbe97W289a1vZa+99hq3zAMDA7z85S/n1FNP5eSTT+aKK67g1FNP5dvf/jbvfe97efvb387rXvc6LrnkEk466SRWrVpFZ2cnMLlxeDJrzI0bN/LSl76UU089ldNPP5158+ZlljWKIl7+8pdz4403cuqpp/Ke97yHzZs388tf/pK//OUv4469t956K/vtt9+E1pKXX34573rXu+jo6OAjH/kIQNPyTBV33303e+65Z4IAAxx66KEA/PGPf2TJkiX8+c9/pl6vN1gplEolDjzwwAYhKsBzn/tct65/ymNajcBnOAYHBxWgXvWqV40b75WvfKUC1NDQkFIq3rP8yle+MhHvne98pwLUn/70Jxe26667JvamffzjH1ft7e3qH//4R+LZc889V4VhqB577DGllFK/+tWvFKDe/e53N5TH32MwlT3LV199tQqCoGGfw5VXXqkA9bvf/U4ppdTnPve5Cfdkj7ef5IwzzkjsG3744YcVoObMmaMGBwdd+HnnnacAdcABB6harebCTzvtNFUqlRL7nkdGRhryedvb3qba2toS8ZrtWZ5s3XPkyLHtsPvxbrjhBrV+/Xq1atUq9b3vfU/19fWp1tZW9fjjjyul9FgBqHPPPTfx/E9+8hMFqE984hOJ8JNOOkkJIdQDDzzgwgAFqD/84Q8u7NFHH1UtLS3qn//5n13YmWeeqRYsWKA2bNiQSPPUU09V3d3dmWOMxSOPPKLCMFSf/OQnE+F//vOfVaFQcOF33323AtQPf/jDcdun2bht283fN7zrrrsqQN16660u7LrrrlOAam1tVY8++qgL/9KXvqQAddNNN7mwrHp997vfVYC65ZZbXFizPcuTrXuOHDkmD/tbz7rK5bKLZ9dPXV1dat26dYk07Fr0tNNOS4T/8Y9/VIB6y1vekgh///vfrwD1q1/9yoXZ8eUXv/jFpMp99NFHK0B95zvfcWH33XefAlQQBOr222934Xac8teJkx2Hx1tj2jJceeWVmff8/b9f/epXFaAuu+yyhrgT7dddvHixes1rXtMQnjVOT3XPso/xnt13333Vi170oobwe++9N9EGP/zhDxvGdIuTTz5ZzZ8/vyH8rLPOUq2trVtV5p2N3Ax7GrF582YAJ/FqBnt/aGgoEb5ixYrE93e9610A/OxnP2ua1g9/+EOOPPJIenp62LBhg7uOPfZYoihypoPXXHMNQgguuOCChjSEEBPUrHnee++9N8961rMSeVvTyJtuugnAaQmuvfbaBtPwbcHJJ59Md3e3+37YYYcBcPrpp1MoFBLh1WqV1atXuzB//8zmzZvZsGEDRx55JCMjI9x3330T5j3ZuufIkWP74dhjj2XOnDksWbKEU089lY6ODv7rv/6LRYsWJeK94x3vSHz/2c9+RhiGvPvd706Ev+9970Mpxc9//vNE+OGHH85BBx3kvu+yyy686lWv4rrrriOKIpRSXHPNNbziFa9AKZUYA4477jg2bdrEXXfd1bQeP/7xj5FScsoppySenT9/PnvssYcbP+z4dt111zEyMjL1BmuCffbZh8MPP9x9t2Pni170InbZZZeG8IceesiF+WPn2NgYGzZs4HnPex7AuHW2mGzdc+TIMXWsXLmSX/7yl4krPb4BvOY1r2nYKmjx9re/PfHdrkHPOeecRPj73vc+gAZLyd12243jjjtu0mXu6Ojg1FNPdd/32msvZs2axd577+3GIGgcj7Z1HPZRLpd585vfPGG8a665htmzZ7v1uY+J1tIbN26kp6dnUuXZURgdHc30fdTS0uLu+3+bxbX3ffT09DA6Orpd56odhdwMexphSbAlzc3QjFTvscceie/Lli0jCIJxz167//77ueeee5oOeuvWrQO0ueLChQsTpjbbivvvv5+//e1vE+b92te+lq985Su85S1v4dxzz+XFL34xr371qznppJMmtceiGfxFHcQLyyVLlmSGDwwMuLB7772Xj370o/zqV79qEFrYvYDjYbJ1z5Ejx/bDypUr2XPPPSkUCsybN4+99tqrYQwpFAosXrw4Efboo4+ycOHChjF37733dvd9pMdigD333JORkRHWr19PEAQMDg5y1VVXcdVVV2WWdbwx4P7770cplZkPxE4Nd9ttN8455xwuu+wyvv3tb3PkkUfyyle+ktNPPz0hKJwqtmXs7O/v56KLLuJ73/teQx0nO3ZOpu45cuSYOg499NBJOfjabbfdJn3v0UcfJQgCli9fngifP38+s2bNahg/x0s7C4sXL24gmt3d3ROOR+vXr9+mcdjHokWLJuXM68EHH2SvvfZKKGSmAtXER8bOQmtra6ZfHesfyQpD7d9mcbMcttm6ba0CbmciJ8vTiO7ubhYsWMA999wzbrx77rmHRYsWNewZSGMyHU5KyT/90z/xwQ9+MPP+nnvuOWEaWwspJfvvvz+XXXZZ5n070LW2tnLLLbdw00038dOf/pRf/OIXfP/73+dFL3oR119//VZ7AWz2XLNw+0MeHBzk6KOPpquri4997GMsW7aMlpYW7rrrLj70oQ9NSvs92brnyJFj+2EyC8FyubxNQrjJwI4Rp59+OmeccUZmnGc/+9njPi+E4Oc//3nmeGV9IwB89rOf5U1vehPXXnst119/Pe9+97udX4u0UGCy2NqxE7RvjVtvvZUPfOADHHjggXR0dCCl5Pjjj5/02DnZuufIkWPHYDzv1M3uTZYETdXz9daOR9s6DvvYGd66+/r6EoLH6cCCBQsSVpYWTz75JAALFy508fzwdFwbz8fAwABtbW1PC8/nOVmeZrz85S/ny1/+Mr/97W+dF0Efv/nNb3jkkUd429ve1nDv/vvvT0jkHnjgAaSUCQ/MaSxbtowtW7Zw7LHHjluuZcuWcd1119Hf3z+udnkqEqFly5bxpz/9iRe/+MUTPhcEAS9+8Yt58YtfzGWXXcanPvUpPvKRj3DTTTdx7LHH7lRJ1M0338zGjRv58Y9/nPBKaD3q+mhWrqnUPUeOHNOLXXfdlRtuuIHNmzcntMt2y8Wuu+6aiH///fc3pPGPf/yDtrY2Z03S2dlJFEUTjr1ZWLZsGUopdtttt0kJNPfff3/2339/PvrRj3Lrrbfy/Oc/nyuvvJJPfOITwM6T5A8MDHDjjTdy0UUXcf7557vwrPYab+ycSt1z5Mgxvdh1112RUnL//fc7axzQzrUGBwcbxs+dhTlz5kx6HN5eY+SyZcv4/e9/T61Wm7IVzLOe9azMdWYWdtSYfuCBB3LTTTcxNDSUUNj9/ve/d/cB9ttvPwqFAn/4wx845ZRTXLxqtcof//jHRJjFww8/nOgfT2Xke5anGR/4wAdobW3lbW97W+IoDdDma29/+9tpa2tzx2r4WLlyZeL7F77wBUCfm9cMp5xyCrfddhvXXXddw73BwUHq9Tqg96copbjooosa4vlag/b2dgYHB5tXMJX36tWr+fKXv9xwb3R0lOHhYYCGY5sg/kFaEw97jt9k894WWGmlX+9qtcoXv/jFhrjt7e2ZpoWTrXuOHDmmHy972cuIooj/+I//SIR/7nOfQwjRMMbedtttib1uq1at4tprr+UlL3mJOxPzNa95Dddccw1/+ctfGvJbv379uOV59atfTRiGXHTRRQ1meUopN3cMDQ25Mdxi//33JwiChHncVMbtbUHW2AkkTl3wywSNY/pk654jR46nBl72spcBjb9za1l3wgkn7OwiAUxpHN5ea8zXvOY1bNiwoWEugYlNrA8//HD+8pe/TOp40R01pp900klEUZQwW69UKnzta1/jsMMOc1aR3d3dHHvssXzrW99KbC29+uqr2bJlCyeffHJD2nfdddeEp9g8VZBrlqcZe+yxB9/4xjd4/etfz/7778+ZZ57JbrvtxiOPPMJ//ud/smHDBr773e9mupd/+OGHeeUrX8nxxx/Pbbfdxre+9S1e97rXccABBzTN7wMf+AD//d//zctf/nLe9KY3cdBBBzE8PMyf//xnfvSjH/HII48we/ZsjjnmGN7whjfw+c9/nvvvv9+ZzP3mN7/hmGOO4eyzzwb0WWk33HADl112GQsXLmS33XZLOFjw8YY3vIEf/OAHvP3tb+emm27i+c9/PlEUcd999/GDH/zAnbP3sY99jFtuuYUTTjiBXXfdlXXr1vHFL36RxYsXO+37smXLmDVrFldeeSWdnZ20t7dz2GGHTXnvy2RwxBFH0NPTwxlnnMG73/1uhBBcffXVmQPdQQcdxPe//33OOeccDjnkEDo6OnjFK14x6brnyJFj+vGKV7yCY445ho985CM88sgjHHDAAVx//fVce+21vPe9720Yj/fbbz+OO+64xNFRQELY+G//9m/cdNNNHHbYYbz1rW9ln332ob+/n7vuuosbbrghU0hosWzZMj7xiU9w3nnn8cgjj3DiiSfS2dnJww8/zH/9139x1lln8f73v59f/epXnH322Zx88snsueee1Ot1rr76ardItJjKuL0t6Orq4qijjuIzn/kMtVqNRYsWcf3112dqS6yDtI985COceuqpFItFXvGKV0y67jly5Jg6fv7zn2c6KT3iiCPYfffdtyrNAw44gDPOOIOrrrrKbWO74447+MY3vsGJJ57IMcccs63F3mpMdhzeXmvMN77xjXzzm9/knHPO4Y477uDII49keHiYG264gXe+85286lWvavrsq171Kj7+8Y/z61//mpe85CXj5nPQQQdxxRVX8IlPfILly5czd+5c50A2C7fccotz6Lt+/XqGh4ed5dFRRx3lrCgPO+wwTj75ZM477zzWrVvH8uXL+cY3vuE4io9PfvKTHHHEERx99NGcddZZPP7443z2s5/lJS95Cccff3wi7p133kl/f/+49X9KYec53s4xHu655x512mmnqQULFqhisajmz5+vTjvtNPXnP/+5Ia511//Xv/5VnXTSSaqzs1P19PSos88+W42Ojibipo+OUkqpzZs3q/POO08tX75clUolNXv2bHXEEUeoSy+9VFWrVRevXq+rSy65RD3rWc9SpVJJzZkzR730pS9Vd955p4tz3333qaOOOkq1trYqYMJjpKrVqvr0pz+t9t13X1Uul1VPT4866KCD1EUXXaQ2bdqklFLqxhtvVK961avUwoULValUUgsXLlSnnXZaw3FX1157rdpnn31UoVBIuPhvdnTUJZdcknj+pptuyjxmxbrl/7//+z8X9rvf/U4973nPU62trWrhwoXqgx/8oDuWwD8mZcuWLep1r3udmjVrlgIS5ZhM3XPkyLHtyPoNZ+GMM85Q7e3tmfc2b96s/vVf/1UtXLhQFYtFtccee6hLLrmk4bgPQK1YsUJ961vfUnvssYcql8vqOc95TmJcsFi7dq1asWKFWrJkiRvnX/ziF6urrrpqUvW65ppr1Ate8ALV3t6u2tvb1bOe9Sy1YsUK9fe//10ppdRDDz2k/uVf/kUtW7ZMtbS0qN7eXnXMMceoG264IZFOs3G72dFRJ5xwQkNZbL19ZI21jz/+uPrnf/5nNWvWLNXd3a1OPvlk9cQTTyhAXXDBBYnnP/7xj6tFixapIAga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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "24af49edb12c40ed987dc94459d7aca3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "mPIE: 0%| | 0/100 [00:00" + "ptychogram: 0%| | 0/100 [00:00(...)` call in the engine sources.""" + pattern = re.compile(r"self\.monitor\.([A-Za-z_]\w*)\s*\(") + return sorted( + { + name + for f in ENGINES_DIR.rglob("*.py") + for name in pattern.findall(f.read_text()) + } + ) + + +@pytest.mark.parametrize("hook", engine_monitor_hooks()) +def test_dummy_monitor_has_every_engine_hook(hook): + assert callable(getattr(DummyMonitor(), hook, None)) + + +@pytest.mark.parametrize("engine_name", ["ePIE", "mPIE", "qNewton", "mqNewton"]) +def test_engine_runs_with_dummy_monitor_and_autofocus(generate_simu_hdf5, engine_name): + data = ExperimentalData(str(generate_simu_hdf5), operationMode="CPM") + params = Params() + params.gpuSwitch = False + # autofocus calls monitor.update_focusing_metric, which DummyMonitor once lacked + params.TV_autofocus = True + params.TV_autofocus_run_every = 1 + reconstruction = Reconstruction(data, params) + reconstruction.initializeObjectProbe() + + engine = getattr(Engines, engine_name)(reconstruction, data, params, DummyMonitor()) + engine.numIterations = 2 + engine.reconstruct() + + assert len(reconstruction.error) == 2 diff --git a/tests/Monitor/test_matplotlib_monitor.py b/tests/Monitor/test_matplotlib_monitor.py index 6fe8d577..8da69c5f 100644 --- a/tests/Monitor/test_matplotlib_monitor.py +++ b/tests/Monitor/test_matplotlib_monitor.py @@ -1,11 +1,12 @@ -import pytest import numpy as np -from PtyLab.Monitor.Plots import ObjectProbeErrorPlot +import pytest + from PtyLab.Engines.BaseEngine import BaseEngine -from PtyLab.Reconstruction.Reconstruction import Reconstruction from PtyLab.ExperimentalData.ExperimentalData import ExperimentalData -from PtyLab.Params.Params import Params from PtyLab.Monitor.Monitor import Monitor +from PtyLab.Monitor.Plots import ObjectProbeErrorPlot +from PtyLab.Params.Params import Params +from PtyLab.Reconstruction.Reconstruction import Reconstruction @pytest.mark.skip(reason="Visual test - requires manual inspection") @@ -21,7 +22,7 @@ def test_live_update(self): error_metrics = [] for k in range(100): error_metrics.append(np.random.rand()) - self.monitor.updateObject(np.random.rand(100, 100)) + self.monitor.updateObject(np.random.rand(100, 100), objectPlot="abs") self.monitor.updateError(error_metrics) self.monitor.drawNow() @@ -35,7 +36,9 @@ def setup(self): self.monitor = Monitor() self.optimizable = Reconstruction(self.experimentalData, self.params) self.optimizable.initializeObjectProbe() - self.BR = BaseEngine(self.optimizable, self.experimentalData, self.params, self.monitor) + self.BR = BaseEngine( + self.optimizable, self.experimentalData, self.params, self.monitor + ) def test_show_reconstruction(self): self.BR.reconstruction.initializeObjectProbe() diff --git a/tests/Monitor/test_monitor_frame.py b/tests/Monitor/test_monitor_frame.py new file mode 100644 index 00000000..22603070 --- /dev/null +++ b/tests/Monitor/test_monitor_frame.py @@ -0,0 +1,181 @@ +"""MonitorFrame contents and how monitors consume it.""" + +import matplotlib + +matplotlib.use("Agg") + +import numpy as np +import pytest +from numpy.testing import assert_allclose + +from PtyLab import Engines +from PtyLab.ExperimentalData.ExperimentalData import ExperimentalData +from PtyLab.Monitor.frame import MonitorFrame +from PtyLab.Monitor.Monitor import AbstractMonitor, DummyMonitor, Monitor +from PtyLab.Params.Params import Params +from PtyLab.Reconstruction.Reconstruction import Reconstruction +from PtyLab.utils.utils import fft2c + + +def _record(name): + """A monitor hook that stores its arguments under `name`.""" + + def hook(self, *args, **kwargs): + self.calls.setdefault(name, []).append((args, kwargs)) + + return hook + + +class RecordingMonitor(AbstractMonitor): + """Uses the default `update`, and records what reaches each hook.""" + + figureUpdateFrequency = 1 + verboseLevel = "high" + objectZoom = 1 + probeZoom = 1 + + def __init__(self): + self.calls = {} + + updateObjectProbeErrorMonitor = _record("updateObjectProbeErrorMonitor") + writeEngineName = _record("writeEngineName") + update_encoder = _record("update_encoder") + updateBeamWidth = _record("updateBeamWidth") + updateDiffractionDataMonitor = _record("updateDiffractionDataMonitor") + update_overlap = _record("update_overlap") + + +def six_d(rng, n): + """Random complex array in the 6D layout (nlambda, nosm, npsm, nslice, Ny, Nx).""" + return rng.random((1, 1, 1, 1, n, n)) + 1j * rng.random((1, 1, 1, 1, n, n)) + + +def test_views_crop_to_the_roi_and_drop_singleton_axes(): + rng = np.random.default_rng(0) + obj, probe = six_d(rng, 16), six_d(rng, 8) + frame = MonitorFrame( + error=np.array([1.0]), + object=obj, + probe=probe, + object_roi=(slice(2, 10), slice(4, 12)), + probe_roi=(slice(1, 5), slice(1, 5)), + ) + + assert_allclose(frame.object_view(), obj[0, 0, 0, 0, 2:10, 4:12]) + assert_allclose(frame.probe_view(), probe[0, 0, 0, 0, 1:5, 1:5]) + + +def test_fpm_object_view_shows_the_transformed_spectrum(): + rng = np.random.default_rng(1) + spectrum = six_d(rng, 16) + frame = MonitorFrame( + error=np.array([]), object=spectrum, probe=six_d(rng, 8), operation_mode="FPM" + ) + + assert_allclose(frame.object_view(), np.squeeze(fft2c(spectrum))) + + +def test_default_update_forwards_to_hooks_and_skips_empty_fields(): + rng = np.random.default_rng(2) + monitor = RecordingMonitor() + frame = MonitorFrame( + error=np.array([3.0, 2.0]), + object=six_d(rng, 8), + probe=six_d(rng, 8), + zo=0.05, + engine_name="mPIE", + beam_width=(1e-4, 2e-4), + ) + + monitor.update(frame) + + ((_, kwargs),) = monitor.calls["updateObjectProbeErrorMonitor"] + assert_allclose(kwargs["object_estimate"], frame.object_view()) + assert kwargs["zo"] == 0.05 + assert monitor.calls["writeEngineName"] == [(("mPIE",), {})] + assert monitor.calls["updateBeamWidth"] == [((1e-4, 2e-4), {})] + # no encoder, intensities or overlaps in the frame, so those hooks stay quiet + assert set(monitor.calls) == { + "updateObjectProbeErrorMonitor", + "writeEngineName", + "updateBeamWidth", + } + + +def test_dummy_monitor_never_reads_the_arrays(): + # object=None would fail in object_view, so this passes only if it is skipped + DummyMonitor().update(MonitorFrame(error=np.array([]), object=None, probe=None)) + + +def run_mpie(monitor, iterations=2): + data = ExperimentalData("example_data/simu.hdf5", operationMode="CPM") + params = Params() + params.gpuSwitch = False + reconstruction = Reconstruction(data, params) + reconstruction.initializeObjectProbe() + engine = Engines.mPIE(reconstruction, data, params, monitor) + engine.numIterations = iterations + engine.reconstruct() + return engine, reconstruction + + +@pytest.mark.usefixtures("generate_simu_hdf5") +def test_engine_sends_full_frames_to_a_hook_based_monitor(): + monitor = RecordingMonitor() + engine, reconstruction = run_mpie(monitor) + + # one call for the initial guess plus one per iteration + assert len(monitor.calls["updateObjectProbeErrorMonitor"]) == 3 + # the initial-guess frame has no engine extras, every iteration frame does + for hook in ("writeEngineName", "update_encoder", "updateBeamWidth"): + assert len(monitor.calls[hook]) == 2, hook + # verboseLevel "high" adds the diffraction data and the overlaps + assert len(monitor.calls["updateDiffractionDataMonitor"]) == 2 + assert len(monitor.calls["update_overlap"]) == 2 + + # the object reaching the hook is the engine's ROI crop, as before the frame existed + (_, kwargs) = monitor.calls["updateObjectProbeErrorMonitor"][-1] + roi = engine.objectROI + assert_allclose( + kwargs["object_estimate"], + np.squeeze(reconstruction.object[..., roi[0], roi[1]]), + ) + + +@pytest.mark.usefixtures("generate_simu_hdf5") +def test_matplotlib_monitor_draws_every_iteration(): + monitor = Monitor() + monitor.figureUpdateFrequency = 1 + monitor.verboseLevel = "high" + run_mpie(monitor, iterations=3) + + error_axis = monitor.defaultMonitor.ax_error_metric + assert error_axis.get_title() == "Error metric (it 3)" + assert monitor.diffractionDataMonitor.im_Iestimated is not None + + +@pytest.mark.usefixtures("generate_simu_hdf5") +def test_save_figures_writes_one_png_per_existing_window(tmp_path): + monitor = Monitor() + monitor.verboseLevel = "high" + run_mpie(monitor) + + saved = monitor.saveFigures(tmp_path / "out" / "run") + + # no history window: plain mPIE changes none of zo, theta, purity, positions + assert [p.name for p in saved] == ["run_reconstruction.png", "run_diffraction.png"] + assert all(p.stat().st_size > 0 for p in saved) + assert DummyMonitor().saveFigures(tmp_path / "dummy") == [] + + +@pytest.mark.usefixtures("generate_simu_hdf5") +def test_save_results_with_snapshot_writes_hdf5_and_figures(tmp_path): + monitor = Monitor() + _, reconstruction = run_mpie(monitor) + + reconstruction.saveResults(str(tmp_path / "run.hdf5"), snapshot=monitor) + + assert sorted(p.name for p in tmp_path.iterdir()) == [ + "run.hdf5", + "run_reconstruction.png", + ] diff --git a/tests/Monitor/test_parameter_history.py b/tests/Monitor/test_parameter_history.py new file mode 100644 index 00000000..c30aff31 --- /dev/null +++ b/tests/Monitor/test_parameter_history.py @@ -0,0 +1,91 @@ +"""The parameter-history window shows only the quantities an engine changes.""" + +import matplotlib + +matplotlib.use("Agg") + +import numpy as np +import pytest + +from PtyLab import Engines +from PtyLab.ExperimentalData.ExperimentalData import ExperimentalData +from PtyLab.Monitor.frame import MonitorFrame +from PtyLab.Monitor.Monitor import Monitor, tracked_values +from PtyLab.Monitor.Plots import ParameterHistoryPlot +from PtyLab.Params.Params import Params +from PtyLab.Reconstruction.Reconstruction import Reconstruction + + +def test_tracked_values_in_display_units_and_without_undefined_purity(): + frame = MonitorFrame( + error=np.array([]), + object=None, + probe=None, + zo=0.05, + beam_width=(2e-4, 1e-4), # (y, x); not plotted + area_overlap=0.8, # not plotted + linear_overlap=0.6, + npsm=3, + purity_probe=0.8, + purity_object=1.0, # single object mode: undefined, must be left out + ) + + assert tracked_values(frame) == { + "zo [mm]": {"zo": 50.0}, + "purity [%]": {"probe": 80.0}, + } + + +def test_constant_quantities_open_no_window(): + plot = ParameterHistoryPlot() + for it in range(3): + plot.record(it, {"zo [mm]": {"zo": 50.0}}) + plot.draw() + + assert plot.active_panels() == [] + assert plot.figure is None + + +def test_a_changed_quantity_gets_a_panel(): + plot = ParameterHistoryPlot() + for it, zo in enumerate([50.0, 50.0, 49.9]): + plot.record(it, {"zo [mm]": {"zo": zo}, "theta [deg]": {"theta": 45.0}}) + plot.draw() + + assert plot.active_panels() == ["zo [mm]"] + assert [ax.get_title() for ax in plot.figure.axes] == ["zo [mm]"] + + +def test_positions_kept_only_once_moved_and_copied(): + plot = ParameterHistoryPlot() + measured = np.zeros((4, 2)) + corrected = measured.copy() + + plot.record_positions(measured, corrected) + assert plot.positions is None + + corrected[0] = 1e-6 + plot.record_positions(measured, corrected) + corrected[1] = 5e-6 # the engine edits in place; the stored copy must not follow + assert plot.positions[1][1, 0] == 0 + + +@pytest.mark.usefixtures("generate_simu_hdf5") +@pytest.mark.parametrize("autofocus", [False, True]) +def test_zo_panel_appears_only_when_autofocus_moves_zo(autofocus): + data = ExperimentalData("example_data/simu.hdf5", operationMode="CPM") + params = Params() + params.gpuSwitch = False + params.TV_autofocus = autofocus + params.TV_autofocus_run_every = 1 + reconstruction = Reconstruction(data, params) + reconstruction.initializeObjectProbe() + monitor = Monitor() + monitor.figureUpdateFrequency = 1 + + engine = Engines.mPIE(reconstruction, data, params, monitor) + engine.numIterations = 3 + engine.reconstruct() + + panels = monitor.parameterHistoryMonitor.active_panels() + assert ("zo [mm]" in panels) == autofocus diff --git a/tests/Reconstruction/test_fpm_sampling.py b/tests/Reconstruction/test_fpm_sampling.py index 1e2008cf..5bf6ef01 100644 --- a/tests/Reconstruction/test_fpm_sampling.py +++ b/tests/Reconstruction/test_fpm_sampling.py @@ -4,7 +4,7 @@ from numpy.testing import assert_allclose from PtyLab.ExperimentalData.ExperimentalData import ExperimentalData -from PtyLab.Monitor.Monitor import Monitor +from PtyLab.Monitor.frame import panel_geometry from PtyLab.Params.Params import Params from PtyLab.Reconstruction.Reconstruction import Reconstruction from PtyLab.utils.visualisation import plotExtent @@ -50,13 +50,12 @@ def test_fpm_object_sampling_preserves_field_of_view(fpm_reconstruction): def test_monitor_plots_fpm_object_with_fpm_pixel_size(fpm_reconstruction): - monitor = Monitor() - monitor.reconstruction = fpm_reconstruction + panels = panel_geometry(fpm_reconstruction) - assert_allclose(monitor.objectPixelSize, fpm_reconstruction.dxo_fpm) + assert_allclose(panels["object_pixel_size"], fpm_reconstruction.dxo_fpm) # the plotted extent is the field of view of the raw images, not No * dxo assert_allclose( - fpm_reconstruction.No * monitor.objectPixelSize, + fpm_reconstruction.No * panels["object_pixel_size"], fpm_reconstruction.Np * fpm_reconstruction.dxp, ) @@ -65,10 +64,9 @@ def test_monitor_plots_cpm_object_with_dxo(generate_simu_hdf5): data = ExperimentalData("example:simulation_cpm") reconstruction = Reconstruction(data, Params()) - monitor = Monitor() - monitor.reconstruction = reconstruction + panels = panel_geometry(reconstruction) - assert_allclose(monitor.objectPixelSize, reconstruction.dxo) + assert_allclose(panels["object_pixel_size"], reconstruction.dxo) def test_fpm_pupil_sampling_matches_the_numerical_aperture(fpm_reconstruction): @@ -85,16 +83,15 @@ def test_fpm_pupil_sampling_matches_the_numerical_aperture(fpm_reconstruction): def test_monitor_plots_fpm_pupil_in_reciprocal_units(fpm_reconstruction): """For FPM the probe panel shows the pupil, which lives in Fourier space.""" - monitor = Monitor() - monitor.reconstruction = fpm_reconstruction + panels = panel_geometry(fpm_reconstruction) - assert monitor.probeLabel == "Pupil estimate" - assert monitor.probeAxisUnit == "1/um" - assert_allclose(monitor.probePixelSize, fpm_reconstruction.dfp) + assert panels["probe_label"] == "Pupil estimate" + assert panels["probe_axis_unit"] == "1/um" + assert_allclose(panels["probe_pixel_size"], fpm_reconstruction.dfp) # the axis spans the bandwidth the low-resolution grid can carry, 1 / dxp assert_allclose( - fpm_reconstruction.Np * monitor.probePixelSize, 1 / fpm_reconstruction.dxp + fpm_reconstruction.Np * panels["probe_pixel_size"], 1 / fpm_reconstruction.dxp ) @@ -103,12 +100,11 @@ def test_monitor_probe_panel_unchanged_for_cpm(generate_simu_hdf5): data = ExperimentalData("example:simulation_cpm") reconstruction = Reconstruction(data, Params()) - monitor = Monitor() - monitor.reconstruction = reconstruction + panels = panel_geometry(reconstruction) - assert monitor.probeLabel == "Probe estimate" - assert monitor.probeAxisUnit == "mm" - assert_allclose(monitor.probePixelSize, reconstruction.dxp) + assert panels["probe_label"] == "Probe estimate" + assert panels["probe_axis_unit"] == "mm" + assert_allclose(panels["probe_pixel_size"], reconstruction.dxp) def test_only_reciprocal_axes_are_centred_on_zero(generate_simu_hdf5):