pub struct UnifiedFitConfig { /* private fields */ }Expand description
Unified fit configuration for all data types and solvers.
Carries both transmission and counts background configs, and uses
SolverConfig (which embeds solver-specific tuning).
Implementations§
Source§impl UnifiedFitConfig
impl UnifiedFitConfig
Sourcepub fn new(
energies: Vec<f64>,
resonance_data: Vec<ResonanceData>,
isotope_names: Vec<String>,
temperature_k: f64,
resolution: Option<ResolutionFunction>,
initial_densities: Vec<f64>,
) -> Result<Self, FitConfigError>
pub fn new( energies: Vec<f64>, resonance_data: Vec<ResonanceData>, isotope_names: Vec<String>, temperature_k: f64, resolution: Option<ResolutionFunction>, initial_densities: Vec<f64>, ) -> Result<Self, FitConfigError>
Construct a new config with validation.
Sourcepub fn with_tzero_jacobian_method(
self,
method: Option<EnergyScaleJacobianMethod>,
) -> Self
pub fn with_tzero_jacobian_method( self, method: Option<EnergyScaleJacobianMethod>, ) -> Self
Override the method used for the t0 / L_scale Jacobian columns
in EnergyScaleTransmissionModel. None (default) defers to
the model’s own default selection via
EnergyScaleJacobianMethod::from_env: PartialGal since issue
#489 unless overridden by NEREIDS_TZERO_JACOBIAN.
Sourcepub fn with_energy_scale_seed(self, enabled: bool) -> Self
pub fn with_energy_scale_seed(self, enabled: bool) -> Self
Enable/disable the resonance peak-match (t0, L_scale) seed that
normally runs before an energy-scale fit (default true). Callers
that supply their own, stronger alignment anchor — calibrate_energy
(issue #634) — disable it: the seed’s dip detector mislocates
saturated flat-bottom dips and its in-bounds least-squares result
would overwrite the anchor.
pub fn with_solver(self, solver: SolverConfig) -> Self
pub fn with_fit_temperature(self, v: bool) -> Self
pub fn with_compute_covariance(self, v: bool) -> Self
Sourcepub fn with_scale_by_chi2(self, v: bool) -> Self
pub fn with_scale_by_chi2(self, v: bool) -> Self
Enable χ²-scaled uncertainties (issue #638).
When true, inflate the reported covariance-only σ by sqrt of the
goodness-of-fit-per-dof that the same result reports, turning the
inverse-Fisher lower bound into a goodness-of-fit-scaled estimate.
Self-consistent on every path:
- Transmission (LM and Poisson-KL):
σ → σ·√(χ²/ν)using the Gaussianreduced_chi_squared. The LM path applies this unconditionally (Numerical Recipes §15.6), so the flag is a no-op there; the Poisson-KL path applies it on opt-in (the raw inverse-Fisher bound is the default). - Counts (joint-Poisson):
σ → σ·√(D/ν)using the conditional-binomialdeviance_per_dof(a genuine count-statistics GOF), on opt-in.
It never scales by a Poisson deviance on transmission fractions (which would be a pseudo-Poisson statistic, not a valid reduced-χ²). Off by default, so existing results are unchanged.
Sourcepub fn with_energy_scale(
self,
t0_init_us: f64,
l_scale_init: f64,
flight_path_m: f64,
) -> Self
pub fn with_energy_scale( self, t0_init_us: f64, l_scale_init: f64, flight_path_m: f64, ) -> Self
Enable energy-scale fitting (SAMMY TZERO equivalent).
Adds t₀ (μs) and L_scale (dimensionless) as fit parameters. These adjust the energy axis during fitting to correct for flight-path and timing-offset uncertainties.
Sourcepub fn with_fit_energy_range(
self,
range: Option<(f64, f64)>,
) -> Result<Self, FitConfigError>
pub fn with_fit_energy_range( self, range: Option<(f64, f64)>, ) -> Result<Self, FitConfigError>
Restrict the fit cost function to bins inside [min_eV, max_eV]
(SAMMY EMIN/EMAX equivalent). The configured energies grid is
expected to extend by ~5×FWHM beyond [min, max] on each side
(the GUI / pre-processing layer handles this); the LM and
joint-Poisson cost paths mask residuals outside [min, max] to
zero so resonance broadening at the boundaries is correct.
None (default) = full grid, no masking.
Validates the range up-front so non-finite or reversed bounds (which would silently produce an empty active-bin mask and a deceptive fit) are rejected at config-build time rather than surfacing as a downstream solver error.
pub fn with_transmission_background(self, bg: BackgroundConfig) -> Self
Sourcepub fn with_multiplicative_baseline(
self,
bl: MultiplicativeBaselineConfig,
) -> Self
pub fn with_multiplicative_baseline( self, bl: MultiplicativeBaselineConfig, ) -> Self
Enable the bounded multiplicative polynomial baseline (issue #635):
y(E) = (b0 + b1·z + b2·z²) · T_model(E), z = ln(E/E_ref).
See MultiplicativeBaselineConfig. Validated at fit dispatch by
validate_multiplicative_baseline (inits within bounds, B(E) > 0
at the initial point, and no free Anorm alongside — b0 and
Anorm are degenerate normalizations).
pub fn with_counts_background(self, bg: CountsBackgroundConfig) -> Self
Sourcepub fn with_counts_enable_polish(self, v: Option<bool>) -> Self
pub fn with_counts_enable_polish(self, v: Option<bool>) -> Self
Override the Nelder-Mead polish flag for the counts-KL dispatch.
Some(true) forces polish on, Some(false) forces it off, None
(the default) lets the dispatcher pick (polish on for single-spectrum,
off for spatial maps).
pub fn with_precomputed_cross_sections(self, xs: Arc<Vec<Vec<f64>>>) -> Self
Sourcepub fn with_precomputed_work_cross_sections(
self,
xs: Arc<Vec<Vec<f64>>>,
layout: Arc<WorkingGridLayout>,
) -> Self
pub fn with_precomputed_work_cross_sections( self, xs: Arc<Vec<Vec<f64>>>, layout: Arc<WorkingGridLayout>, ) -> Self
Attach the working-grid Doppler-broadened σ + its layout for the fixed-calibration / fixed-temperature precomputed path (issue #608).
When set, build_transmission_model builds a
PrecomputedTransmissionModel whose σ live on the working grid and
whose evaluate / analytical_jacobian apply resolution on the working
grid and extract the data points last — matching forward_model. The
data-grid precomputed_cross_sections must still be set (for the
surrogate-plan builders and shape validation); for tabulated / no
resolution the working grid equals the data grid and this is left
None.
The σ + layout are not validated here (this is an infallible builder
setter); shape/consistency are checked once up front in
validate_precomputed_cross_sections, which every public entry point
(fit_spectrum_typed, fit_transmission_poisson, spatial_map_typed)
calls before any forward-model build or per-pixel loop — mirroring how
Self::with_precomputed_cross_sections is validated.
pub fn with_precomputed_base_xs(self, xs: Arc<Vec<Vec<f64>>>) -> Self
Sourcepub fn with_precomputed_resolution_plan(self, plan: Arc<ResolutionPlan>) -> Self
pub fn with_precomputed_resolution_plan(self, plan: Arc<ResolutionPlan>) -> Self
Attach a prebuilt resolution plan for the config’s energy grid.
The caller (typically spatial_map_typed) must ensure that
plan.target_energies() equals self.energies(), otherwise
the fit-model layer will return either a length-mismatch
error or ResolutionError::PlanGridMismatch (for a different
same-length grid) on the first broadening call.
Sourcepub fn with_precomputed_sparse_cubature_plan(
self,
plan: Arc<SparseEmpiricalCubaturePlan>,
) -> Self
pub fn with_precomputed_sparse_cubature_plan( self, plan: Arc<SparseEmpiricalCubaturePlan>, ) -> Self
Attach a prebuilt sparse empirical cubature plan for the config’s energy grid + isotope set (see epic #472).
The plan is advisory — the fit model falls back to the exact
ResolutionPlan path when any of these guards fire:
plan.target_energies() != self.energies()(grid mismatch).plan.k() != n_density_params(isotope-set mismatch).self.fit_temperature == true(σ changes → atoms stale).self.fit_energy_scale == true(grid changes → plan stale).n_density_params == 1(the scalar fast-path is handled separately — see thek == 1dispatch).
Callers (typically spatial_map_typed) are responsible for
ensuring the plan was built against compatible sigmas /
training_densities / jacobian_anchor; the fit model cannot
re-check those at dispatch time.
Sourcepub fn with_precomputed_sparse_scalar_plan(
self,
plan: Arc<ScalarSurrogatePlan>,
) -> Self
pub fn with_precomputed_sparse_scalar_plan( self, plan: Arc<ScalarSurrogatePlan>, ) -> Self
Attach a prebuilt scalar (k = 1) surrogate plan. Same
invalidation discipline as the cubature: the plan is cleared on
with_groups / with_precomputed_cross_sections /
with_precomputed_base_xs, so a stale σ cannot silently
dispatch.
Sourcepub fn with_groups(
self,
groups: &[(&IsotopeGroup, &[ResonanceData])],
initial_densities: Vec<f64>,
) -> Result<Self, FitConfigError>
pub fn with_groups( self, groups: &[(&IsotopeGroup, &[ResonanceData])], initial_densities: Vec<f64>, ) -> Result<Self, FitConfigError>
Configure isotope groups with ratio constraints.
Each group binds multiple isotopes to one fitted density parameter.
groups is a slice of (IsotopeGroup, member_resonance_data) pairs.
initial_densities must have one entry per group.
Replaces the existing per-isotope configuration with the expanded group mapping (flattened resonance_data + density_indices + density_ratios).
§Errors
FitConfigError::DensityFreezeBeforeGroups if a density-freeze mask
(issue #633) was already set — grouping redefines the density
parameters, so the pre-group mask no longer applies. Configure the
freeze after grouping. (Erroring rather than silently clearing the
mask keeps a mis-ordered builder chain from producing an unexpectedly
unfrozen fit.)
Sourcepub fn precomputed_sparse_cubature_plan(
&self,
) -> Option<&Arc<SparseEmpiricalCubaturePlan>>
pub fn precomputed_sparse_cubature_plan( &self, ) -> Option<&Arc<SparseEmpiricalCubaturePlan>>
Caller-attached sparse empirical cubature plan, if any.
spatial_map_typed reads this so a pre-existing plan is
preserved instead of being clobbered by the local rebuild
pathway.
Sourcepub fn precomputed_sparse_scalar_plan(
&self,
) -> Option<&Arc<ScalarSurrogatePlan>>
pub fn precomputed_sparse_scalar_plan( &self, ) -> Option<&Arc<ScalarSurrogatePlan>>
Caller-attached scalar (k = 1) surrogate plan, if any.
pub fn energies(&self) -> &[f64]
pub fn resonance_data(&self) -> &[ResonanceData]
pub fn isotope_names(&self) -> &[String]
pub fn temperature_k(&self) -> f64
pub fn resolution(&self) -> Option<&ResolutionFunction>
pub fn initial_densities(&self) -> &[f64]
pub fn solver(&self) -> &SolverConfig
pub fn fit_temperature(&self) -> bool
pub fn transmission_background(&self) -> Option<&BackgroundConfig>
Sourcepub fn multiplicative_baseline(&self) -> Option<&MultiplicativeBaselineConfig>
pub fn multiplicative_baseline(&self) -> Option<&MultiplicativeBaselineConfig>
The configured multiplicative baseline (issue #635), if any.
pub fn counts_background(&self) -> Option<&CountsBackgroundConfig>
Sourcepub fn counts_enable_polish(&self) -> Option<bool>
pub fn counts_enable_polish(&self) -> Option<bool>
Counts-KL polish override (see Self::with_counts_enable_polish).
Sourcepub fn fit_energy_scale(&self) -> bool
pub fn fit_energy_scale(&self) -> bool
Whether SAMMY TZERO energy-scale calibration is enabled
(see Self::with_energy_scale).
Sourcepub fn scale_by_chi2(&self) -> bool
pub fn scale_by_chi2(&self) -> bool
Whether χ²-scaled uncertainties are enabled
(see Self::with_scale_by_chi2).
Sourcepub fn flight_path_m(&self) -> f64
pub fn flight_path_m(&self) -> f64
Nominal flight path (m) configured via Self::with_energy_scale.
Sourcepub fn fit_energy_range(&self) -> Option<(f64, f64)>
pub fn fit_energy_range(&self) -> Option<(f64, f64)>
User-specified fit-energy-range restriction (SAMMY EMIN/EMAX
equivalent), or None for full-grid fitting.
See Self::with_fit_energy_range.
Sourcepub fn baseline_reference_energy(&self) -> f64
pub fn baseline_reference_energy(&self) -> f64
Baseline log-basis reference energy over the ACTIVE fit window
(issue #648). Every baseline construction site must use this rather
than baseline_reference_energy(self.energies()): with a
fit_energy_range set, the full-grid midpoint sits thousands of eV
away from the window and the baseline silently absorbs temperature
broadening. Folds the fit_energy_range mask in one place so no
call site can reintroduce the full-grid bug.
pub fn precomputed_cross_sections(&self) -> Option<&Arc<Vec<Vec<f64>>>>
Sourcepub fn n_density_params(&self) -> usize
pub fn n_density_params(&self) -> usize
Number of density parameters (one per group or per isotope).
Sourcepub fn with_fix_densities(self, fix: bool) -> Self
pub fn with_fix_densities(self, fix: bool) -> Self
Freeze (or unfreeze) all density parameters at their initial values (issue #633). The standard resonance-thermometry recipe: the areal density is known from a calibration foil, so only temperature (and/or the energy scale / baseline) is fitted.
with_fix_densities(true) sets an all-fixed mask;
with_fix_densities(false) clears any mask back to all-free.
Applies to every fitter and to spatial_map_typed.
Call this after Self::with_groups — grouping redefines the
density parameters, so Self::with_groups rejects a freeze mask set
before it (FitConfigError::DensityFreezeBeforeGroups).
Sourcepub fn with_density_free(self, free: Vec<bool>) -> Result<Self, FitConfigError>
pub fn with_density_free(self, free: Vec<bool>) -> Result<Self, FitConfigError>
Per-density-parameter free/fixed mask (SAMMY-style selective
freezing): free[i] == false freezes density parameter i at its
initial value. Length must equal Self::n_density_params — one
entry per isotope for ungrouped fits, one per group for grouped
fits.
Call this after Self::with_groups — grouping redefines the
density parameters, so Self::with_groups rejects a freeze mask set
before it (FitConfigError::DensityFreezeBeforeGroups).
§Errors
FitConfigError::DensityCountMismatch if free.len() differs
from the density-parameter count.
Trait Implementations§
Source§impl Clone for UnifiedFitConfig
impl Clone for UnifiedFitConfig
Source§fn clone(&self) -> UnifiedFitConfig
fn clone(&self) -> UnifiedFitConfig
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for UnifiedFitConfig
impl RefUnwindSafe for UnifiedFitConfig
impl Send for UnifiedFitConfig
impl Sync for UnifiedFitConfig
impl Unpin for UnifiedFitConfig
impl UnsafeUnpin for UnifiedFitConfig
impl UnwindSafe for UnifiedFitConfig
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more