Skip to main content

MultiplicativeBaselineModel

Struct MultiplicativeBaselineModel 

Source
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).

§Placement differs on the exact resolved-count route

“Outermost” describes the TRANSMISSION routes, where the model lives in the measured bins and B(E) corrects the measured sample/open-beam ratio: y(E) = B(E)·[Anorm·T + additive background].

The exact separate-arm count route has two distinct axes (true-energy quadrature vs detector-time bins), so it places B on the TRUE-ENERGY sample arm, BEFORE the detector response, and applies the Anorm/ABC wrapper afterwards on the measured bins: Anorm·R[Φ·B·T]/R[Φ] + background. That ordering is deliberate — a sample-side multiplicative correction is a property of the sample arm, and applying it after the ratio would make it a detector-space term instead — but it means B is NOT the outermost factor there, and a fitted baseline / baseline_e_ref_ev is not directly comparable across the two routes: on the transmission routes E is the measured bin energy, on the exact count route it is the true quadrature energy. Note b0 remains degenerate with Anorm on both (the response is linear), which is why the free-Anorm rejection applies to both.

§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>

Source

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.

Source

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>

Source§

fn evaluate(&self, params: &[f64]) -> Result<Vec<f64>, FittingError>

Evaluate the model for the given parameters. Read more
Source§

fn analytical_jacobian( &self, params: &[f64], free_param_indices: &[usize], y_current: &[f64], ) -> Option<FlatMatrix>

Optionally provide an analytical Jacobian. Read more
Source§

impl<M: FitModel> ForwardModel for MultiplicativeBaselineModel<M>

Source§

fn predict(&self, params: &[f64]) -> Result<Vec<f64>, FittingError>

Predict model output for the given parameter vector. Read more
Source§

fn jacobian( &self, params: &[f64], free_param_indices: &[usize], y_current: &[f64], ) -> Option<Vec<Vec<f64>>>

Analytical Jacobian (column-major layout). Read more
Source§

fn n_data(&self) -> usize

Number of data points in the model output.
Source§

fn n_params(&self) -> usize

Number of parameters (total, including fixed).

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> ByRef<T> for T

§

fn by_ref(&self) -> &T

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T, U> Imply<T> for U
where T: ?Sized, U: ?Sized,