pub struct MultiplicativeBaselineModel<M: FitModel> { /* private fields */ }Expand description
Bounded multiplicative polynomial baseline (issue #635):
y(E) = B(E) · T_inner(E), B(E) = b0 + b1·z + b2·z², z = ln(E / E_ref)where E_ref = √(E_min·E_max) (see baseline_reference_energy) and
T_inner is any inner FitModel — typically the bare transmission
model, or NormalizedTransmissionModel when the SAMMY additive
background is also configured (the baseline is the OUTERMOST factor).
§INTENTIONAL DEPARTURE from SAMMY
SAMMY’s modern data-reduction path applies a SCALAR normalization plus
additive backgrounds only:
T_obs = Anorm·T + BackA + BackB/√E + BackC·√E + BackD·exp(−BackF/√E)
(cro/mnrm1.f90, subroutine Norm, applied to
every data type via the/ZeroKCrossCorrections_M.f90). SAMMY’s nearest
analogue to an energy-dependent multiplicative normalization is the
DORMANT legacy power-law Anorm = Anrm(1) + Anrm(2)·E^Anrm(3)
(acs/macs4.f90:440–450, Find_Www_Yyy), which is not reachable from the
modern reconstruction path. This low-order ln-E polynomial baseline is a
NEREIDS extension motivated by the IPTS-37432 campaign (findings A3/A5):
real VENUS sample/open-beam ratios sit a few % from unity with smooth
energy dependence, and freeing the SAMMY Anorm together with temperature
and density is degenerate on such data (observed: T → 4471 K, n +76 %,
χ²/ν 932, with no warning). The bounded multiplicative form fitted
jointly with temperature at fixed density produced χ²/ν ≈ 2–8 across the
20-run campaign.
Because b0 is exactly degenerate with Anorm, the pipeline rejects a
free Anorm alongside ANY configured baseline — including a fully
frozen one (see nereids-pipeline::validate_multiplicative_baseline).
A frozen-b0 + free-Anorm combination would be well-posed, but
supporting it buys nothing (Anorm would just play b0’s role at a
rescaled value) and splits the normalization story across two knobs;
the sanctioned combination is Anorm held fixed.
§Index invariant
The baseline indices (b0_index, b1_index, b2_index) must NOT
designate a parameter the inner model reads: the analytic Jacobian
filters the baseline indices out of the inner free set, so such a
collision cannot be detected and the column would silently omit
B(E) × ∂T_inner/∂p. Aliasing AMONG the baseline indices themselves
IS supported — the Jacobian columns accumulate.
Implementations§
Source§impl<M: FitModel> MultiplicativeBaselineModel<M>
impl<M: FitModel> MultiplicativeBaselineModel<M>
Sourcepub fn new(
inner: M,
energies: &[f64],
e_ref: f64,
b0_index: usize,
b1_index: usize,
b2_index: usize,
) -> Self
pub fn new( inner: M, energies: &[f64], e_ref: f64, b0_index: usize, b1_index: usize, b2_index: usize, ) -> Self
Create the wrapper. e_ref is normally
baseline_reference_energy(energies); it is passed explicitly so
result consumers can reconstruct B(E) with the exact same reference.
Sourcepub fn with_active_mask(self, mask: Option<&[bool]>) -> Self
pub fn with_active_mask(self, mask: Option<&[bool]>) -> Self
Scope the runtime positivity guard to the given active mask
(None = all bins active, the default). See the active_mask
field doc for why masked bins must be exempt.
Trait Implementations§
Source§impl<M: FitModel> FitModel for MultiplicativeBaselineModel<M>
impl<M: FitModel> FitModel for MultiplicativeBaselineModel<M>
Source§fn evaluate(&self, params: &[f64]) -> Result<Vec<f64>, FittingError>
fn evaluate(&self, params: &[f64]) -> Result<Vec<f64>, FittingError>
Source§fn analytical_jacobian(
&self,
params: &[f64],
free_param_indices: &[usize],
y_current: &[f64],
) -> Option<FlatMatrix>
fn analytical_jacobian( &self, params: &[f64], free_param_indices: &[usize], y_current: &[f64], ) -> Option<FlatMatrix>
Source§impl<M: FitModel> ForwardModel for MultiplicativeBaselineModel<M>
impl<M: FitModel> ForwardModel for MultiplicativeBaselineModel<M>
Source§fn predict(&self, params: &[f64]) -> Result<Vec<f64>, FittingError>
fn predict(&self, params: &[f64]) -> Result<Vec<f64>, FittingError>
Auto Trait Implementations§
impl<M> Freeze for MultiplicativeBaselineModel<M>where
M: Freeze,
impl<M> RefUnwindSafe for MultiplicativeBaselineModel<M>where
M: RefUnwindSafe,
impl<M> Send for MultiplicativeBaselineModel<M>where
M: Send,
impl<M> Sync for MultiplicativeBaselineModel<M>where
M: Sync,
impl<M> Unpin for MultiplicativeBaselineModel<M>where
M: Unpin,
impl<M> UnsafeUnpin for MultiplicativeBaselineModel<M>where
M: UnsafeUnpin,
impl<M> UnwindSafe for MultiplicativeBaselineModel<M>where
M: UnwindSafe,
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
§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