Widgets for air removal from amplitude projections.
Inherits navigation, mask drawing, I/O, and display from
PhaseTracker. Overrides the correction methods to apply
rmair() followed by a logarithm
instead of phase-ramp removal.
Attach a PolygonSelector to the main image axes for mask drawing.
Left-click to add vertices; click the first vertex again (or press
Enter in matplotlib ≥ 3.7) to close and finalise the polygon.
Then click add mask (or another mask button) to apply it.
The selector is drawn directly on ax1 — no separate figure is
opened. Any previously unfinished selector is discarded first.
Play through all projections from the current index.
Click stop (or press the stop button) to halt the animation at
the current frame.
Each frame is rendered synchronously so the animation is actually
visible. draw_idle() (used by update()) schedules an
async repaint that never fires inside a tight Python loop; we
force a synchronous draw() + flush_events() after each
frame to push the data to the screen. flush_events() also
pumps the GUI event queue so the stop button callback can fire
mid-loop.
Notebook mode (requires %matplotlibwidget) — the
function returns immediately; interact with the GUI in the
cell output, then access results in the next cell:
tracker=gui_plotamp(stack_objs,**params)# ── next cell ──stack_ampcorr=tracker.X1.copy()
Notebook mode (requires %matplotlibwidget) — the
function returns immediately; interact with the GUI in the
cell output, then access results in the next cell:
tracker=gui_plotphase(stack_objs,**params)# ── next cell ──stack_phasecorr=tracker.X1.copy()
Interactively draw one or more polygon regions on image and return
a cumulative boolean mask.
Opens a figure with the image and two buttons:
Add region — commits the current polygon to the mask; a
permanent dashed outline marks it; you can immediately draw the
next polygon.
Finish — closes the figure (any in-progress polygon with ≥ 3
vertices is committed automatically).
Draw each polygon by left-clicking vertices directly on the image.
The polygon closes visually once you have ≥ 3 points. Click
Add region to store it, then draw the next one. No Enter key or
precise “click first vertex to close” is needed.
This is the lightweight notebook alternative to the full
gui_plotphase() / gui_plotamp() GUI (which is better
suited to terminal use).
Important
Jupyter notebook — two-cell workflow.make_air_mask returns immediately (non-blocking) so that the
figure widget can be displayed. Do not put painter.mask
access in the same cell — the cell will have finished executing
before you interact with the figure, and the mask will be empty.
Always use two separate cells:
# Cell 1 — show the figure and drawpainter=make_air_mask(stack[0],vmin=-1.6,vmax=1.6)# Cell 2 — run AFTER clicking Finish in the figure aboveair_mask=painter.mask.copy()
Terminal / IPython — works with any backend; blocks until the
figure is closed.
JupyterLab — requires %matplotlibwidget
(pipinstallipympl). Put it as the first cell of your
notebook and restart the kernel.
Classic Jupyter Notebook — %matplotlibwidget (preferred)
or %matplotlibnotebook (built-in, no install).
``%matplotlib inline`` — not interactive; a
UserWarning explains how to switch.
param image:
2-D image to display (e.g. one slice from the projection stack).
type image:
array_like, shape (ny, nx)
param cmap:
Colourmap name. Default 'gray'.
type cmap:
str, optional
param vmin:
Colormap limits.
type vmin:
float or None, optional
param vmax:
Colormap limits.
type vmax:
float or None, optional
param figsize:
Figure size (width,height) in inches. Default (8,7).
type figsize:
tuple of float, optional
returns:
painter – Object whose .mask attribute (ndarray of bool, shape
(ny,nx)) is the union of all added regions.
.n_regions counts how many polygons were added.
rtype:
_MaskPainter
Examples
Terminal / IPython (single cell, blocks until Finish is clicked):
fromtoupy.restorationimportmake_air_mask,rmphaserampimportnumpyasnppainter=make_air_mask(stack[0],vmin=-1.6,vmax=1.6)air_mask=painter.mask.copy()# available immediately after returncorrected=np.stack([np.angle(rmphaseramp(np.exp(1j*proj),weight=air_mask,zero_air_phase=True))forprojinstack])
JupyterLab (%matplotlibwidget + pipinstallipympl once,
two separate cells):
# ── Cell 1 ── draw the mask (returns immediately)painter=make_air_mask(stack[0],vmin=-1.6,vmax=1.6)# ── Cell 2 ── run after clicking Finish in the figure aboveair_mask=painter.mask.copy()
Interactively choose the region of interest for derivative computation.
Opens a GUI figure showing the first projection with the current ROI
(from params) overlaid in red. Click two corners to redefine the
rectangle, then click Confirm.
Pure FFT symmetric-difference filter. Applied directly via
scipy.fft.fft() — no ShiftFunc overhead. Supports
the symmetric and n_cpus parameters.
"spline", "linear"
Sub-pixel shift via ShiftFunc
(always symmetric ±0.5 px). symmetric and n_cpus are
ignored for these methods.
symmetric (bool, optional) – Only used when shift_method="fourier". If True (default),
applies a symmetric ±½-pixel difference (filter
2i·sin(πf)). If False, applies a forward 1-pixel
difference (filter exp(2πif)−1).
n_cpus (int, optional) – Number of threads passed to scipy.fft.fft().
Only used when shift_method="fourier".
-1 (default) uses all available cores.
Returns:
diffimg – Derivative image (same shape as input_array).
Remove residual per-projection phase offsets from a stack of projections.
After rmphaseramp(), individual projections may still carry
small projection-to-projection phase variations that appear as
vertical stripes in sinograms. This function corrects them in a
second pass using the sinogram itself:
Rows that are consistently air at all angles have low phase
variance across the stack (object rows vary strongly with angle).
Otsu thresholding on the per-row standard-deviation separates
air rows (low std) from object rows (high std) automatically.
For each projection the residual offset is the circular mean phase
over the detected air rows; this is subtracted so that all
projections share the same air phase reference.
Parameters:
stack (array_like, shape (nprojs, nr, nc)) –
Stack of ramp-corrected projections. Accepted types:
complex — direct output of rmphaseramp(). The
function returns a complex array; extract the phase sinogram
with np.angle(normalized).
real (float) — phase values already extracted via
np.angle(). The function returns a float array of the same
dtype; use it directly as the sinogram.
Warning
Do not pass np.real(rmphaseramp(...)). That gives
the real part of the complex projection (amplitude·cosφ),
not the phase. Use np.angle(rmphaseramp(...)) or pass
the complex array directly.
border (int, optional) – Number of pixels to exclude from each edge — should match the
border value used in rmphaseramp(). Default 0.
Returns:
normalized (ndarray, shape (nprojs, nr, nc)) – Stack with per-projection offsets removed. Same dtype as
stack (complex if complex in, float if float in).
offsets (ndarray, float, shape (nprojs,)) – Per-projection phase offsets that were subtracted (radians).
Relative to the stack circular mean, so they sum to approximately
zero.
Examples
Option A — complex stack (direct output of rmphaseramp):
Remove the linear phase ramp from a complex ptychographic image.
Parameters:
image (array_like) – Input complex image.
mask (array_like of bool, optional) – Boolean array marking the air/vacuum region (True = air).
If None, air is detected automatically via Otsu thresholding.
weight (str, optional) – Only used when mask=None. Passed to rmphaseramp().
Default 'auto'.
Remove the linear phase ramp from a complex ptychographic image.
This is the single entry point for all phase-ramp correction tasks,
including the role previously filled by rmlinearphase(). Pass a
boolean mask as weight together with zero_air_phase=True to
replicate the old rmlinearphase(image,mask=mask) call exactly.
Parameters:
a (array_like) – Input complex 2-D image.
weight ({None, 'median', 'abs', 'auto'} or array_like, optional) –
Strategy for estimating the ramp slope.
None / 'median'
Global median phase gradient. Robust to object
contamination as long as air covers more than 50 % of the
image.
'abs'
Amplitude-weighted mean gradient (original Ptypy behaviour).
'auto'
Automatically detect the air region from the amplitude image
using Otsu thresholding (air = high amplitude). Reliable even
when the air region is small, provided amplitude contrast
between air and object is detectable.
array_like (boolean or float)
Custom mask / weight array (same shape as a). A
boolean or 0/1 integer array is treated as a binary air mask:
ramp slope is estimated via the median within the mask, and
zero_air_phase=True uses the circular mean over those
pixels to zero the air phase. A continuous float array uses a
modulus-weighted mean instead.
Replacingrmlinearphase()with a mask:
rmlinearphase(image,mask=mask)
→ rmphaseramp(image,weight=mask,zero_air_phase=True)
return_phaseramp (bool, optional) – If True, also return the total correction phasor p.
Default False.
n_iter (int, optional) – Number of self-consistent refinement iterations. Only active
when weight is None / 'median' (no prior mask
supplied). After the first correction, pixels whose corrected
phase is close to zero are identified as air and used to refine
the ramp estimate. Default 1 (single pass, no refinement).
If True, apply a global phase offset after ramp removal so
that the mean phase over the air/vacuum region is exactly zero.
The air phase offset is estimated by two strategies, chosen
automatically:
Circular mean (used when weight='auto' or a binary mask
is supplied): the already-computed air mask is reused. Fast
and precise when the mask correctly identifies the air region.
Phase histogram mode (fallback for weight=None/'median'/'abs'): finds the dominant peak in the interior phase
histogram via a two-step smoothed + raw argmax + parabolic
interpolation. Robust even without an explicit mask, and
tolerant of bright reconstruction artefacts inside the image
border.
Default False.
border (int, optional) – Number of pixels to exclude from each edge before computing
the Otsu threshold, gradient estimation, and phase-offset
correction. In ptychography, scan positions at the image
boundary often lack proper overlap, producing strong noise
artefacts that corrupt the ramp estimate. Set this to
approximately (beam diameter) / (scan step) pixels to remove
these artefacts entirely. Default 0 (no exclusion).
Returns:
out (ndarray, complex) – Ramp-corrected image.
p (ndarray, complex) – Total correction phasor (only returned when
return_phaseramp=True).
A GUI figure opens showing the first projection overlaid with
phase-residue locations (red dots). Click three points in order:
Top-left corner of the rectangular unwrap region.
Bottom-right corner of the unwrap region.
A pixel in air / vacuum (must be inside the rectangle).
Then click Confirm to accept, or Reset to start over.
Parameters:
stack_array (ndarray) – A 3-dimensional array containing the stack of projections
to be unwrapped.
threshold (int, optional) – Threshold for the number of acceptable phase residues. (Default = 5000)
parallel (bool, optional) – If True, multiprocessing is used for residue computation.
(Default = False)
ncores (int, optional) – Number of cores for parallel computation. (Default = 1)
Returns:
Terminal mode – (rx,ry,airpix) — ranges and air-pixel tuple, ready to use.
Jupyter mode (two-cell workflow) – picker — _RegionPicker instance. Access
picker.rx, picker.ry, picker.airpix in the next
cell after clicking Confirm.
stack_array (ndarray) – A 3-dimensional array containing the stack of projections
from which to calculate the phase residues.
threshold (int, optional) – Maximum number of acceptable phase residues per projection.
Projections with more residues than threshold are flagged
as problematic. Default 5000.
Returns:
resmap (ndarray) – 2-D phase residue accumulation map (sum of absolute residue maps
across all projections).
posres (tuple of ndarray) – Indices (yres,xres) of pixels where resmap>=1.
nres (int) – Total number of residues found in the last processed projection.
Calculate the map of residues on the stack using parallel processing.
Parameters:
stack_array (ndarray) – A 3-dimensional array containing the stack of projections
from which to calculate the phase residues.
threshold (int, optional) – Maximum number of acceptable phase residues per projection.
Projections with more residues than threshold are flagged
as problematic. Default 1000.
ncores (int, optional) – Number of CPU cores for parallel computation.
Default 2.
Reliability-guided BFS. Computes a per-pixel reliability from
second-order phase differences and processes pixel edges in
decreasing reliability order via a priority queue. Generally
the most robust choice for noisy data.
Reference: M. A. Herraez, D. R. Burton, M. J. Lalor, and
M. A. Gdeisat, “Fast two-dimensional phase-unwrapping algorithm
based on sorting by reliability”, Applied Optics 41(35), 2002.
"goldstein"
Branch-cut algorithm. Locates phase residues, pairs them with a
greedy nearest-neighbour strategy, draws L-shaped branch cuts,
then unwraps via BFS flood fill from the image centre. Falls
back to Flynn’s method when no residues are found.
Reference: R. M. Goldstein, H. A. Zebker, and C. L. Werner,
“Satellite radar interferometry: Two-dimensional phase
unwrapping”, Radio Science 23(4), 1988.
"flynn"
Row-integration + median row correction. Integrates wrapped
horizontal differences row by row, then corrects accumulated
row-to-row offsets using a median estimator. O(N) complexity,
fastest but least robust to noise.
Reference: T. J. Flynn, “Two-dimensional phase unwrapping with
minimum weighted discontinuity”, Journal of the Optical Society
of America A 14(10), 1997.
"wls"
DCT-based unweighted least-squares (Ghiglia & Romero, 1994).
Solves the 2-D Poisson equation whose right-hand side is the
divergence of the wrapped phase gradients, using a DCT-II
transform (Neumann boundary conditions). Globally optimal under
a flat weight model; O(N log N) complexity. More robust than
the greedy methods for densely wrapped, smooth phase fields.
Reference: D. C. Ghiglia and L. A. Romero, “Robust two-dimensional
weighted and unweighted phase unwrapping that uses fast transforms
and iterative methods”, J. Opt. Soc. Am. A 11(1), 107-117 (1994).
"snaphu"
Statistical-cost network-flow algorithm (Chen & Zebker, 2001).
Regarded as the gold standard for 2-D phase unwrapping. The
per-pixel reliability map is used as a coherence estimate.
Requires the optional package snaphu-py
(pipinstallsnaphu).
Reference: C. W. Chen and H. A. Zebker, “Two-dimensional phase
unwrapping with use of statistical models for cost functions in
nonlinear optimization”, J. Opt. Soc. Am. A 18(2), 338-351 (2001).
verbose (bool, optional) – Only used when method='snaphu'. If False (default) SNAPHU’s
extensive C-level log is suppressed and replaced by a single line.
Set to True to see the full SNAPHU output.
Returns:
unwrapped – Float64 unwrapped phase array, same shape as phase.
Return type:
ndarray
Raises:
ValueError – If method is not one of the recognised algorithm names.
ImportError – If method='snaphu' and snaphu-py is not installed.
stack_phasecorr (ndarray) – A 3-dimensional array containing the stack of projections to be unwrapped
rx (tuple or list of ints) – Limits of the are to be unwrapped in x and y
ry (tuple or list of ints) – Limits of the are to be unwrapped in x and y
airpix (tuple or list of ints) – Position of pixel in the air/vacuum area
**params –
Dictionary of additional parameters.
vminfloat or None
Minimum value for the gray level at each display.
vmaxfloat or None
Maximum value for the gray level at each display.
unwrap_methodstr, optional
Phase unwrapping algorithm to use. One of "herraez"
(default), "goldstein", "flynn", "wls", or
"snaphu". See unwrap_phase_2d() for details.
"snaphu" requires the optional package snaphu-py
(pipinstallsnaphu).
parallelbool, optional
If True, use parallel processing. Default True.
n_cpusint, optional
Number of CPU cores for parallel computation. Pass -1
to use all available cores. Default -1.
Returns:
stack_unwrap – A 3-dimensional array containing the stack of unwrapped projections
Return type:
ndarray
Notes
Five algorithms are available. The default is the reliability-guided
algorithm by Herraez et al. [2]. For the best robustness use
"wls" (no extra dependency) or "snaphu" (requires
pipinstallsnaphu).
phase (float or array_like) – The value or signal to wrapped.
endpoint (bool, optional) – If endpoint=False, the scalar value or array is wrapped
to [-pi, pi), whereas if endpoint=True, it is wrapped to (-pi, pi].
The default value is endpoint=True