Run a simulation¶
Compile an ImagePlaneModel, create either a complex128 object array or a
SyntheticObject, and call simulate:
truth = fpm.SyntheticObject.mixed_test_pattern(model.reconstruction_shape)
simulation = fpm.simulate(model, truth, seed=17)
With no camera or acquisition errors this is an ideal, deterministic simulation.
The result contains detector measurements, the ground_truth_object, the
true_model, and the reconstruction_model that should be paired with the
returned detector values.
Pass a CameraModel to introduce detector gain, offset, read/shot noise,
quantization, saturation, sensitivity variations, or bad pixels. Pass
IlluminationAcquisitionErrors for gain variation, missing frames, or source
permutation. Set a fixed seed whenever the workflow must be reproducible.
The Rust simulator also provides named deterministic benchmark presets and ground-truth metrics. Their precise definitions and validation policy are in Reconstruction benchmarks.
Model mismatch and detector counts¶
Represent geometric mismatch with separate concrete source descriptions:
compile the actual geometry into the model given to Simulator::new, and the
assumed geometry into the reconstruction model. IlluminationAcquisitionErrors
is limited to acquisition effects—relative frame-gain variation, failed frames,
and source permutations. Failed frames remain as dark, zero-weight frames so
frame/model indexing is retained. Fixed-sphere placement/pose and moving-arm
kinematic errors are detailed in Spherical illumination geometries.
CameraModel owns pixel sensitivity, photon/electron conversion, shot and read
noise, dark current, gain, offset, quantization, saturation, and deterministic
bad pixels. Defocus, pupil aberration, and edge apodization compile through
Optics into the model pupil; represent aberration mismatch with separate true
and reconstruction models. Illumination-angle transmission belongs in source
intensity weights, frame gains, or multiplex weights—not in the pupil.
SimulationResult retains both compiled models and acquisition configuration.
Use evaluation::evaluate_reconstruction_with_problem in Rust, or
fpm.evaluation.evaluate_reconstruction(..., problem=..., reference_model=...)
in Python, to combine masked per-frame intensity residuals with object, pupil,
and calibration comparisons. Pupil metrics remove the best global complex
scale, because object and pupil share that ambiguity.
Simulator::simulate compiles known linear camera response into the returned
reconstruction model: gains include photon conversion and electronic gain, while
background includes dark current and offset. Digitized counts can therefore be
passed directly to ReconstructionProblem; clipping, quantization, noise,
pixel-response variation, and bad pixels remain deliberate nonlinear effects or
model mismatch. A serialized SimulationConfiguration keeps
compiled_models.reconstruction_model as the strict optical model; use
reconstruction_model_for_counts() when making a problem from its saved detector
counts. Optical background belongs in both optical models; detector dark current
and electronic offset belong in CameraModel.
Synthetic objects include amplitude-only and phase-only fields, mixed patterns, resolution targets, particles, random phase, Siemens stars, and seeded biological-like phase/absorption fields. Image-backed constructors normalize grayscale values to physical amplitude and a selected phase range; empty or colour images, mismatched dimensions, and invalid phase ranges are rejected.