pub struct SpectrumFitResult {Show 18 fields
pub densities: Vec<f64>,
pub uncertainties: Option<Vec<f64>>,
pub reduced_chi_squared: f64,
pub converged: bool,
pub iterations: usize,
pub temperature_k: Option<f64>,
pub temperature_k_unc: Option<f64>,
pub anorm: f64,
pub background: [f64; 3],
pub back_d: Option<f64>,
pub back_f: Option<f64>,
pub t0_us: Option<f64>,
pub l_scale: Option<f64>,
pub energy_scale_flight_path_m: Option<f64>,
pub deviance_per_dof: Option<f64>,
pub baseline: Option<[f64; 3]>,
pub baseline_e_ref_ev: Option<f64>,
pub warnings: Vec<String>,
}Expand description
Result of fitting a single spectrum.
Fields§
§densities: Vec<f64>Fitted areal densities (atoms/barn), one per isotope.
uncertainties: Option<Vec<f64>>Uncertainty on each density.
None when covariance computation was skipped.
reduced_chi_squared: f64Reduced chi-squared of the fit.
converged: boolWhether the fit converged.
iterations: usizeNumber of iterations.
temperature_k: Option<f64>Fitted temperature in Kelvin (only when fit_temperature is true).
temperature_k_unc: Option<f64>1-sigma uncertainty on the fitted temperature (from covariance matrix).
Covariance-only lower bound for the raw-count joint-Poisson path:
this is sqrt of the temperature diagonal
of the inverse curvature (Fisher) matrix at convergence. It reflects only
statistical curvature — baseline/model noise is not in the covariance —
so on real data it can underestimate the observed per-superpixel scatter
by ~3–4×. Set UnifiedFitConfig::scale_by_chi2 to inflate it by sqrt
of the deviance_per_dof this result reports, for a
goodness-of-fit-scaled estimate. The LM transmission path is
already χ²-scaled (Numerical Recipes §15.6), so the flag is a no-op there.
anorm: f64Fitted normalization scale (SAMMY Anorm). When background
fitting is disabled, the pipeline emits 1.0 (λ̂ absorbs
the scale).
background: [f64; 3]Fitted background polynomial coefficients [BackA, BackB, BackC]
for the SAMMY-style 6-term background:
bg(E) = BackA + BackB / √E + BackC · √E + BackD · exp(-BackF / √E)Both LM-transmission and counts-KL solver paths use the same
SAMMY semantics here — the legacy alpha-fitting [b0, b1, alpha_2] layout was removed when fit_counts_poisson was
retired. When background fitting is disabled, the
pipeline emits [0.0, 0.0, 0.0].
back_d: Option<f64>Fitted exponential background amplitude (SAMMY BackD).
None when the exponential tail is not fitted; Some(value)
when the LM transmission background was active with
fit_back_d=true. Mirrors Self::t0_us /
Self::l_scale semantics so the GUI overlay can
distinguish “unfit” from “fitted to zero” without an ambiguous
0.0 sentinel.
back_f: Option<f64>Fitted exponential background decay constant (SAMMY BackF).
None when the exponential tail is not fitted; Some(value)
when the LM transmission background was active with
fit_back_f=true. Paired with Self::back_d — SAMMY
requires both flags toggled together (see
validate_transmission_background).
t0_us: Option<f64>Fitted TOF offset in microseconds (SAMMY TZERO t₀).
None when energy-scale fitting is not enabled.
l_scale: Option<f64>Fitted flight-path scale factor (SAMMY TZERO L₀, dimensionless).
None when energy-scale fitting is not enabled.
energy_scale_flight_path_m: Option<f64>The nominal flight path (m) the energy-scale fit was configured
with — stored so Self::corrected_energies reproduces the
transform with the SAME flight path the fit used, closing the
caller-resupplied-mismatch channel (issue #634 review: a wrong but
positive flight path silently changes the t₀ term). None when
energy-scale fitting is not enabled.
deviance_per_dof: Option<f64>Conditional binomial deviance divided by (n − k)
(primary GOF for the counts-KL dispatch, i.e.
SolverConfig::PoissonKL on InputData::Counts or
InputData::CountsWithNuisance).
Some(D/dof) when the counts-KL (joint-Poisson) path was used;
None for the LM transmission path (which populates
reduced_chi_squared with Pearson χ² / (n−k) instead).
baseline: Option<[f64; 3]>Fitted multiplicative-baseline coefficients [b0, b1, b2] (issue
#635) for
B(E) = b0 + b1·ln(E/E_ref) + b2·ln²(E/E_ref)On the transmission routes the baseline is applied OUTERMOST:
y(E) = B(E)·[Anorm·T + additive background]. On the exact
resolved-count route the composition is domain-specific: B(E)
multiplies the true-energy sample arm BEFORE detector response,
and the Anorm/ABC normalization applies to the measured detector
bins after the separate-arm ratio (see fit_counts_joint_poisson).
None when no multiplicative baseline was configured (values that
were configured but frozen via fit_b0/b1/b2 = false still report
Some — they are part of the model that produced the fit).
baseline_e_ref_ev: Option<f64>Reference energy E_ref (eV) the baseline’s ln(E/E_ref) basis was
centered on — the geometric midpoint √(E_min·E_max) of the fit
grid, stored so consumers reconstruct B(E) with the EXACT
reference the fit used (the same resupply-mismatch channel
Self::energy_scale_flight_path_m closes for the energy scale).
None when no multiplicative baseline was configured.
warnings: Vec<String>Structured fit-configuration warnings (issue #635). Non-fatal
conditions the caller should surface to the user — currently the
degenerate normalization trio (free Anorm + free temperature +
≥1 free density), which on real VENUS data converged to T = 4471 K
with χ²/ν = 932 and no diagnostic. Empty when nothing is flagged.
A Vec<String> rather than tracing: nereids-pipeline has no
tracing dependency, and structured warnings survive across the
PyO3 / GUI boundaries.
Implementations§
Source§impl SpectrumFitResult
impl SpectrumFitResult
Sourcepub fn corrected_energies(
&self,
nominal_energies: &[f64],
) -> Option<Result<Vec<f64>, PipelineError>>
pub fn corrected_energies( &self, nominal_energies: &[f64], ) -> Option<Result<Vec<f64>, PipelineError>>
Map a nominal energy grid through the fitted SAMMY energy scale
(t0_us, l_scale) to the corrected (calibrated) energies the fit
evaluated the physics on (issue #634).
This exposes the transform the fitter used so downstream code never
has to re-derive it — replicating it by hand with a +t0 sign
(instead of the correct −t0) caused a silent +400 K temperature bias
in the field. It reuses the canonical
corrected_energy_grid
(SAMMY dat/mdat0.f90:189, −t0 convention) with the SAME flight path
the fit was configured with (stored on the result), so a mismatched
caller-supplied flight path cannot silently skew the t₀ term.
One divergence from the fit’s internal evaluation: at a DEGENERATE
t0 at/past the grid’s shortest flight time, the model clamps t0
just below the limit and keeps evaluating, while this accessor
returns Some(Err(_)) — a degenerate calibration should be
re-examined, not silently reproduced.
Returns None when energy-scale fitting was not enabled — the
corrected grid would equal the input, but None distinguishes
“not fitted” from “fitted to the identity”.
Trait Implementations§
Source§impl Clone for SpectrumFitResult
impl Clone for SpectrumFitResult
Source§fn clone(&self) -> SpectrumFitResult
fn clone(&self) -> SpectrumFitResult
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 SpectrumFitResult
impl RefUnwindSafe for SpectrumFitResult
impl Send for SpectrumFitResult
impl Sync for SpectrumFitResult
impl Unpin for SpectrumFitResult
impl UnsafeUnpin for SpectrumFitResult
impl UnwindSafe for SpectrumFitResult
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