Native SSB: the model-based, tilt-corrected fit#
MetalSSBKernels runs Python’s SSB.fit_aberrations on a prepared native session: the same transfer model,
objective, search and branch test, so a native app gives the Python MPS result. The app owns selection and
presentation; the shared Swift package owns count extraction, Fourier preparation, the model, the fit and saved
numerical state. Python is not needed at runtime.
|
Python |
Method |
|---|---|---|
|
|
model agreement, tilt-corrected (sample tilt and depth spread) |
|
|
model agreement, tilt and depth held at 0 |
|
|
retired (2026-10-25): saved options decode, |
Minimal workflow#
let model = try engine.jointModel(scanDetectorRotationDegrees: rotation) // the curl estimate
let fit = try SSBModelFit.findAberrations(
model: model, rotationDegrees: rotation, darkField: darkField,
scanSampling: (stepRow, stepColumn)) // both 180-degree branches
let phase = try model.reconstruct(
fit.fit.point, upsamplingFactor: calibration.ssbUpsamplingFactor()) // phase_of_mean, auto factor
SSBRotationBranches.curlRotationDegrees gives the rotation from exact centre-of-mass moments
(dpc.find_optimal_rotation); findAberrations fits it and its opposite branch with the same options, keeps
the branch whose dark-field atomic columns have positive phase (else the larger phase skewness), and measures
the standard comparison (tiltFitGain) once, for the kept branch. checkRotation: false fits the given
rotation alone. Prepare engine with the calibrated geometry and the original unsigned counts, after the
loader’s flagged-pixel median fill when the Python session applied one. Preparing the engine again invalidates
joint models; retarget moves a model to another rotation without gathering its band evidence again.
Scientific contract#
Quantity |
Contract |
|---|---|
C10, C12 |
Angstrom in the engine ( |
C10 reference |
Model midplane; not a microscope entrance-plane focus measurement |
Astigmatism angle |
Radians, wrapped to [-pi/2, pi/2) |
Tilt |
|
Depth spread |
Nonnegative Angstrom; a model depth spread, not a measured thickness |
Objective |
|
Search |
|
Fifth order |
|
Half-band check |
Default for a ±20 fit ( |
Final phase |
|
Reconstruction methods |
|
Phase |
|
Complex |
|
Regularization |
|
Caching |
The layout (frequencies, aliases, priors, weights, dose) is kept per data, factor, q0 and weighting; the normal equations per optics, rotation and layout, one per method (a complex system also serves |
Drag previews |
|
Output sampling |
Fourier-alias reconstruction at 1, 2, 3, 4 or 8x; not interpolation. |
Rotation |
Double precision; the angle is converted in double, the BF coordinates rotated in float32 as MPS |
Wavelength |
Python’s table at 80-400 kV, else the same formula |
The TPE port is checked trial by trial: on a synthetic float32 objective that both sides evaluate from the same
float32 trial rows, the 200 search trials equal Python’s (SSBAgreementSearchTests, which
scripts/ssb_agreement_gate.py also feeds with the current Python records). The Newton after the search has
exact derivatives only: on the same objective, given its analytic derivatives, the tilt and tilt=False fits reach
its known maximum, and the staged Newton reaches the one-stage Newton’s point with fewer derivative passes.
The exact-gradient fifth-order search is checked for a maximum of the Double-summed agreement on the synthetic
test scene: a small projected exact gradient, and no rise along any of the 28 coordinates
(SSBFifthOrderGradientTests). On three measured 512 x 512 acquisitions it reached a higher Double-summed
agreement than the retired finite-difference Newton (+1.2e-7 to +3.8e-7 relative) in about 1 s instead of
65-111 s; the parameters differed along the C10-C30-C50 direction, which the agreement resolves only to about
1e-3 to 1e-2 nm at float32. Measured parity (MetalSSBMeasuredParityTests, given an exported acquisition in
SSB_PARITY_FIXTURE) covers the BF disk and fitted detector sampling, the agreement at fixed parameters (1e-7
relative), the default and tilt=False fits on the model’s exact derivatives (tolerances 0.01 nm, 0.2 degrees,
0.02 mrad; the retired stencil Newton measured 1e-5 nm, 1e-4 degrees and 1e-4 mrad, not re-measured since), the
curl rotation, the branch decision and the fixed-parameter phases (correlation 0.999999998 or better at 1x and
3x).
Limits#
The joint model fits and reconstructs C10 through C56 with tilt and depth spread; an unsupported order or a repeated term is rejected.
Supported scans are square 128, 256 and 512. There is no silent binning or padding for this model.
Every fit is model-based (the agreement objective), natively and in Python.
The native engine has no detector transposition (
scan_detector_rotation_flippedis false).No absolute potential, acquisition focus sign or specimen thickness claim follows from contrast or the agreement alone.
Saved results#
MetalSSBJointSavedRun writes a phase-only .jointssb record with source identity, build identity,
calibration, ROI, parameters, rotation, output sampling, the fit (SSBBranchedFit, both branches when compared)
and a phase SHA-256. Its fit options record higherOrderLimit and checkHigherOrderConsistency, and a
fifth-order fit its higherOrderConsistency when computed; records saved before them decode
with the standard limit 2, unchecked, and none. Records carrying the retired coherence guard
(computeHigherOrderGuard, higherOrderGuard) decode and ignore it. Reopening checks source identity, shape
and checksum, then displays the exact stored phase without refitting. Records from the earlier native optimizer still decode, phase-variance fits included
(SSBObjective.phaseVariance is kept for decoding). MetalSSBSavedRun (.ssb, the retired non-model engine’s
complex object) still opens; MetalSSBEngine.phase(of:) converts its object to the phase.
Reproducible checks#
swift test -c release -Xswiftc -enable-testing --filter MetalSSBKernelsTests
PYTHONPATH=src python scripts/ssb_agreement_gate.py # the same search trials and exact-Newton fits
SSB_PARITY_FIXTURE=... SSB_PARITY_REFERENCE=... swift test -c release -Xswiftc -enable-testing \
--filter MetalSSBMeasuredParityTests # a measured acquisition, kept outside this repository
SSB_DIRECT_FIXTURE=... [SSB_DIRECT_ALL=1] swift test -c release -Xswiftc -enable-testing \
--filter SSBDirectMeasuredParityTests # ssb, phase and complex against CUDA arrays of the same optics
The joint fixtures (SSB_JOINT_REFERENCE, SSB_JOINT_CALIBRATED_REFERENCE) gate the objective (loss relative
error < 5e-5). Their phase images were of the retired mean_phase estimator; they are not compared, and
scripts/build_metal_ssb_joint_reference.py no longer writes them (nor needs an upsampling source). Missing
external fixtures are reported as skips, never passes. Keep acquisitions, screenshots and raw logs outside this
repository.
Retired native engine paths#
The engine’s own non-model SSB and the phase-variance fit were removed on 2026-10-25; native SSB is model-based
only. MetalSSBEngine keeps Fourier preparation, the joint-model bridge and the saved-run phase conversion.
Removed: MetalSSBEngine.reconstruct(aberrations:scanDetectorRotationDegrees:), phaseVariance, optimize,
MetalSSBPhaseVarianceResult, SSBOptimizer with SSBOptimizationProgress, the phase-variance branch of
SSBModelFit (and its engine: argument), SSBFit.phaseVarianceLoss, the metal-ssb-benchmark product, the
standalone tests/metal SSB harnesses and the frozen phase-variance fit trajectory. Their ssb.metal kernels
(ssb_gamma_accumulate*, ssb_finalize_fourier_sum, the chi and cross trigonometric tables, the fused 512 and
small-scan phase-loss kernels, the phase-moment and Nyquist-correction kernels and the half-plane transposes) are
deleted; ssb.metal keeps the count conversion, row FFTs, transpose, Hermitian extraction and
ssb_object_phase. These kernels were never registered (docs/performance/kernels.md), so no registered digest
changed.
Retired estimators#
mean_phase (the per-BF-pixel phase average, with its general and fused 1536-point kernels, ssb-mean-phase)
and complex_wave (the coherent sum’s amplitude at 1x, C10/C12 only) were removed on 2026-10-25 in favour of the
regularized phase and complex reconstructions. docs/performance/kernels.md keeps their last registry rows.
Python retired the same two estimators.