Neural phase for a scan series#
Fit a model on a representative counting scan. Reuse its frozen weights for later scans of the same field. Each scan supplies its own diffraction data; previous images guide registration, not the current neural phase. This workflow uses CUDA. No pretrained specimen model or simulated training data is required.
Train and check one scan#
Start with a calibrated counting dataset. The everyday notebook, kept in the private spectra repository, includes the optical fit, staged training and direct/neural phase comparison.
from quantem.gpu import DirectPtycho
with DirectPtycho(reference_scan) as ptycho:
optics = ptycho.aberrations(show=False)
model = ptycho.train_neural_phase(optics)
scores = model.score(ptycho, optics, partition="detector")
Default training uses complementary bright-field detector blocks on one
scan patch, then selects the staged U-Net, annular readout and bounded heads
on a separate patch. model.show() displays selection curves. The detector
score above evaluates a third unused patch in both directions, conditional
on shared optics and the measured annular guide. Lower error means better
prediction under this linear model; it does not alone establish resolution.
model.save("phase-model.pt") optionally writes the fitted model for another
session. The current session can reuse model directly. The previous
electron-half recipe remains available with recipe="count_split", steps=60, seed=42; score(partition="electron") retains its three-way comparison.
The advanced notebook, in the same private repository, covers damping, probe
phase and measured-pattern exploration.
The public fitting method is DirectPtycho.aberrations(). Older examples used
find_aberrations() or fit_aberrations(), which are no longer public methods.
Saved fit files are direct-aberrations.npz and .json. The native Swift
entry point is DirectPtychoModelFit.findAberrations.
Reuse the model#
model = DirectPtycho.load_neural_phase("phase-model.pt")
with DirectPtycho(reference_scan) as ptycho:
fit = ptycho.aberrations(show=False)
series = ptycho.series(fit=fit, method="phase", neural_model=model,
max_frames=2, show=False)
series.add(completed_scan)
reconstruction = series.latest
reconstruction.show()
Pass a resident acquisition or its file path to add. A receiver can use
process=series.add; it owns the input through the call. A sequence of files
can go straight into ptycho.series(paths, ...), as in the
multiple-scan notebook. By
default, each scan refits defocus and twofold astigmatism at fixed higher-order
optics. These fits never retrain the network. Use refit="none" for a
fixed-optics comparison.
reconstruction.phaseis the phase-only direct solution in radians.neural_phaseadds the frozen, measurement-conditioned correction.complex_phaseandamplitudeare available when"complex"was requested.reconstruction.annular_countsis the measured virtual-detector image on the native scan grid.annulus_mradrecords the inclusive inner and exclusive outer angles. The calibrated center, row and column angular sampling and detector validity mask determine which pixels contribute.reconstruction.aberrationsis a copy of the aberration coefficients applied to that scan.displacement_Ais the measured (row, column) shift relative to the first scan.placedtells whether registration accepted it for the combined image.
series.latest is None before the first scan. An unrequested image is
None. A rejected scan still has its individual images. Hold the returned
snapshot to keep those GPU arrays after a rolling window advances. The series
keeps only the latest annular image. reconstruction.show() pairs that
scan’s phase and annular counts with separate contrast and calibrated scale bars.
series.show() compares images combined over accepted scans.
Check what the annular detector contributes#
The default displayed band is model.annulus_mrad. To compare network on
and off, use the same reference fit, specimen and band. Here scan is one
measured acquisition; both series use the same optical refit policy.
with DirectPtycho(reference_scan) as ptycho:
fit = ptycho.aberrations(show=False)
control = ptycho.series([scan], fit=fit, method="phase",
annulus_mrad=model.annulus_mrad, show=False)
learned = ptycho.series([scan], fit=fit, method="phase",
neural_model=model, show=False)
control.latest.show() # direct phase + measured annular counts
learned.latest.show() # neural phase + the same measured counts
You can inspect another band by passing annulus_mrad=(inner, outer) on a
neural series. Only the measured view changes; the learned guide still uses
the checkpoint’s angles. With neither a model nor angles, no annular image
is requested. This control tests the total effect of refinement. Isolating the
guide’s contribution requires fitting matched models with and without it.
What the correction can support#
The U-Net proposes a residual from normalized direct phase. A separate learned readout uses phase features and annular intensities. Both proposals are filtered by the current scan’s diffraction equations. A bounded final Fourier update uses the remaining mismatch and tapers to zero between 1 and 1.5 Å⁻¹. This taper applies only to the final update. Annular brightness can help locate scattering contrast; it does not establish chemistry, improved resolution or layer separation.
Version-one checkpoints require uniform detector weighting, phase damping 0.03 and a 1 Å⁻¹ smoothness scale. Loading verifies the schema; applying the model checks voltage, convergence semiangle, phase sampling and upsample. The saved record includes the seed, training and validation patches, history and selected step. Series provenance includes the checkpoint SHA-256. Use a region supported by the regularized direct solver if a full field exceeds its resident limit.