pub fn spatial_map_typed(
input: &InputData3D<'_>,
config: &UnifiedFitConfig,
dead_pixels: Option<&Array2<bool>>,
cancel: Option<&AtomicBool>,
progress: Option<&AtomicUsize>,
) -> Result<SpatialResult, PipelineError>Expand description
Fit every pixel of a 3-D data cube and return per-pixel maps — the spatial-mapping entry point of the pipeline.
Runs the single-spectrum fitter once per (y, x) pixel of input
(shape (n_energies, height, width)), in parallel over pixels with
rayon, and assembles the results into SpatialResult: one areal
density map and uncertainty map per fitted isotope/group, the χ²
(or deviance-per-dof) map, the convergence mask, and any optional
maps the configuration enables (temperature, normalization,
background terms, t0 / flight-path scale).
§Input modes
input selects the per-pixel objective: pre-normalized
InputData3D::Transmission (+ per-bin uncertainty),
InputData3D::Counts (sample + open-beam), or
InputData3D::CountsWithNuisance (sample + flux + background
nuisance arms; counts-domain solvers only).
§Validation (all up-front, before any pixel is fitted)
- The cube’s spectral axis must match
config.energies(), the mode’s companion cubes must match the primary cube’s shape, anddead_pixels(when given) must be(height, width). - Cube values are validated on live pixels, each against its
domain — transmission finite, uncertainty finite and strictly
positive, counts/flux finite and non-negative, background finite —
so a corrupt cube fails loudly instead of producing a quietly-NaN
map. For transmission inputs
with a
fit_energy_range, the value checks are scoped to the active bins — out-of-range bins may contain NaN by design. - Known-degenerate configurations are rejected with a diagnostic
rather than letting every pixel fail into an all-NaN map:
counts + LM +
fit_energy_scale(numerically ill-conditioned per-pixel — issue #458 B3) andCountsWithNuisancewith an LM solver (requires a counts-domain solver).transmission_backgroundsettings are validated here for the same reason. (fit_energy_scaletogether withfit_temperatureis SUPPORTED since issue #634 — the energy-scale model carries a fitted temperature column.)
Per-pixel fit failures after validation are not errors: the pixel
is recorded as NaN in the maps, converged_map is false there,
and n_failed counts it.
§Cancellation and progress
cancel is polled before the sweep and at every pixel; once set,
remaining pixels are skipped and the call returns
PipelineError::Cancelled (partial results are discarded).
progress is incremented once per completed live pixel, so a UI
thread can poll it against the number of live pixels
(height × width minus the dead_pixels-masked count).
§Errors
PipelineError::ShapeMismatch for axis/shape disagreements,
PipelineError::InvalidParameter for rejected configurations and
invalid cube values, PipelineError::Transmission when the shared
cross-section / resolution-plan precompute fails (e.g. a
resolution-kernel or working-grid build error), and
PipelineError::Cancelled when cancel was set.