Skip to content

Core concepts and conventions

Computational boundary

Experiment geometry (Optics plus illumination) compiles once into an ImagePlaneModel: transverse wave vectors, pupil samples, Fourier crop locations, subpixel sampling offsets, multiplex weights, and optional frame gains. Algorithms consume that compiled model and measurements; they do not depend on the original LED geometry. Simulation and reconstruction share the same forward model.

Reconstruction is generic over the read-only MeasurementRead trait. MeasurementStack and LazyMeasurementStack implement it directly, so the algorithm path is statically dispatched without a dataset enum or measurement trait objects. Construction, preprocessing, materialization, and cache controls remain operations on the concrete storage types.

Object, pupil, and Fourier sampling

The object is a complex field. Its magnitude is amplitude and its angle is phase. Spectra and pupils are FFT-shifted so zero frequency is at the array centre. Each illumination source selects an overlapping low-resolution crop of the high-resolution object spectrum and propagates it through the pupil. Fractional crop offsets use bilinear sampling and adjoint-weighted insertion. The zero-offset path remains a direct copy; interpolation is not treated as an invertible copy. ImagePlaneModel::new uses integer crops by default; use with_subpixel_offsets when calibrated low-level inputs include fractional source positions.

Arrays are row-major. Shapes use (height, width), indices use (row, column), and k-vectors store (kx, ky) transverse angular spatial frequencies in radians/metre. Positive kx moves toward increasing columns and positive ky toward increasing rows.

KVector values are transverse angular spatial frequencies. Direct-k and angle-based descriptions must represent propagating waves: the transverse magnitude cannot exceed 2πn/λ; component angles lie in [-π/2, π/2]; and the combined transverse direction is validated. For a planar LED at lateral position (x, y) and axial distance z, the compiled vector is k0 * (x, y) / sqrt(x² + y² + z²), where k0 = 2πn/λ. Spherical coordinates use polar angle theta from positive z and azimuth phi from positive x toward positive y.

The low-resolution Fourier spacings are dkx = 2π / (width * object-plane pixel size) and equivalently for dky. CPU FFTs normalize the forward transform by 1/N and leave the inverse unnormalized, preserving constant-object amplitude through a high-resolution crop and low-resolution inverse transform. The ideal pupil includes samples whose transverse frequency is at most 2π NA / λ. PupilAberration coefficients are direct radian weights for the documented sampled radial-polynomial terms, not normalized Zernike coefficients.

CoordinateConvention::CenteredPositiveK records these choices in compiled models.

Low-resolution frames and the reconstruction grid

Each measured intensity frame is a low-resolution image with image_shape. The recovered amplitude (or modulation) and phase are components of one complex field with the larger reconstruction_shape. The grids cover the same field of view, so increasing each linear dimension by a factor s decreases the reconstructed pixel pitch by the same factor and increases the total pixel count by approximately .

The frequently used estimate s ≈ synthetic_na / objective_na describes an ideal bandwidth ratio. Model compilation does not turn that ratio directly into an array size. It resolves the supplied illumination into k-vectors, maps their shifts onto the discrete Fourier grid, and finds enough room for all complete low-resolution crops and any fractional interpolation neighbors. This handles asymmetric, calibrated, and one-sided illumination without assuming symmetric coverage. Automatic choices preserve the low-resolution aspect ratio and isotropic high-resolution pixel sampling.

See Configure and run a reconstruction for the exact, minimum, smooth, and power-of-two selection modes.

Units and illumination ordering

Distances are metres, wavelength is metres, numerical aperture and refractive index are dimensionless, and component angles are radians unless their name explicitly includes degrees. Source order determines measurement frame order. An explicit acquisition order reorders source weights with the wave vectors. For coded illumination, source count and measured frame count differ because a frame is an incoherent intensity sum of source modes.

LED intensity weights are reordered with acquisition order and compiled into ImagePlaneModel::frame_gains, so reconstruction does not need to retain the original LEDArray. The multiplexing matrix maps each measured frame to its incoherently weighted sources. The shared forward model, simulator, and all reconstruction algorithms support those sums: projection methods apply the same measured/predicted amplitude ratio to every source mode and back-project with its normalized multiplex weight.

Illumination::Calibrated represents imported k-vectors with optional per-frame gains and multiplexing rows. Dataset subsets use it to preserve calibrated model effects without inventing LED geometry.

Callbacks and execution boundary

The runner calls callbacks at lifecycle points around reconstruction and iterations. Built-in Rust callbacks do not cross into Python. Python simulation, reconstruction, model compilation, checkpoint I/O, image-backed object loading, and diagnostic serialization release the GIL around Rust-owned work. A Python iteration callback necessarily reacquires it for the callable and therefore can affect throughput. Reconstruction calls block the invoking Python thread.

Backend scope

The current backend is CPU-only. The Rust backend traits define an integration seam for future resident/device execution, but selecting a GPU backend is not a supported task today. Diffraction-plane and multislice forward models are also not implemented.

Backends are thread-safe trait objects. Rust callers can inject one through Runner::with_backend, ReconstructionState::initialize_with_backend, or ForwardModel::with_backend; checkpoint resume and callback-requested forward diagnostics retain that choice. BackendCapabilities, typed ComplexBuffer/RealBuffer, and ResidentBackend describe preferred memory location, transfers, and resident FFT dispatch. CpuBackend uses host buffers. Reconstruction state is host-owned today, so this is an extension seam rather than GPU execution support.

Algorithm rustdoc and the focused guides document equations, approximations, implementation details, and literature references at their point of use.