pub fn fit_map<'a>(
map: &MapMeasurement<'a>,
calibration: &Calibration,
) -> Result<CountsMap<'a>, PipelineError>Expand description
Fit map.material in each patch of binning×binning pixels whose
pixels not excluded all lie behind the sample, and the empty pixels not
excluded as one region with no material, as one counts fit whose regions
share the normalization, the time and room backgrounds per pixel, t0,
the flight path and the pulse: one clock, one flight path, one moderator, one proton
beam, and a detector efficiency that changes between the runs alike in
every pixel. A region’s counts are the sums over its pixels; each has its
own beam, background and gamma transmission, and its time and room
backgrounds are those per pixel times its pixels. The empty pixels pin the normalization
when their b0 is known.
Each region’s open-beam fit, which starts its beam and weights its
open-beam run, takes the time and room backgrounds’ starting numbers as
known; the map is fitted again with them at its fitted numbers, up to twenty times,
until those change the counts the open-beam fits took as known by
Σ_r Σ_k (ΔO_rk)²/O_rk at most BOUND over every region’s open-beam
bins, as fit_counts does; from the
third time on each region keeps the beam intervals its second open-beam
fit chose. A map that has not settled after twenty is unconverged.
The fit is the joint one of fit_counts,
found region by region. With the shared quantities held, each region is
fitted alone, in parallel, leaving out the bins of its material’s windows
at the shared values the steps last stopped at, first the map’s starting
ones, and gives its information and slope on them
with its own quantities and beam profiled out; their sum, with the
calibration’s prior and each measured shared quantity’s, sets a Newton
step on the shared quantities, clamped
to their bounds, with one on a bound its slope pushes out of held there.
From its second fit on, a region keeps the beam intervals of its first,
starts from its last answer, and counts in its sample run’s
overdispersion the leverage the shared quantities have on its bins, as
the joint fit does. The steps stop when their Newton decrement falls
below NEWTON_DECREMENT_TOL at fits that counted that leverage and left
out the window bins of the values they stop at; refitting the regions
with new window bins counts as a step. A
step that raises the regions’ summed deviance plus those priors’
penalty, each run weighted with the overdispersion of the step
before, or at which a fitted patch fails, is halved, up to ten times;
twenty steps, a step that cannot fall, or a failure of the empty pixels at
the smallest halving of a step or at their refit at the current values end
the map unconverged. The shared information and each region’s
information on its own quantities are inverted as information_inverse
inverts them, the shared one scaled to its diagonal before the regions’
own quantities are profiled out, with the rounding of one region’s bins:
the steps take every direction the information spans, and a quantity
along a direction it does not determine, or moving along one through the
shared quantities, has a NaN covariance. Each of the map’s regions holds
its grid’s spread to its share of the map’s counts times BOUND, so
their summed spread is within the BOUND the joint fit holds it to.
A patch whose fit fails, does not converge, or ends at a fitted
temperature of 1 K or 5000 K, at the starting shared values, at the
smallest halving of a step none of whose halvings is taken, or at a refit
at the current values, adds nothing to the shared quantities; it is fitted again after every step taken and
adds to them again once it fits. A patch left out at the end is
CountsMap::failed.
A patch has one density per isotope and one temperature: where its pixels differ, these are the uniform fit of the patch’s summed counts, which differs from the pixels’ beam-weighted means.
The map holds, for each patch, its summed counts and its fits at the current and the trial shared values, so its memory is up to several times that of the counts it is given; each region’s grid gets finer as the number of regions grows.
§Errors
Everything MapMeasurement::patches refuses;
PipelineError::InvalidParameter if a pixel is both behind the sample
and empty, a density, the temperature, the thickness variance, a
background term, the gamma transmission, the capture gammas or the
in-scatter of the sample’s patches is Value::Measured, which would
count its measurement once per patch, a term of the empty pixels’ background is
Value::Measured, the material carries resonance covariances, which a
map does not yet carry, a count of a pixel summed into a region is not a
whole non-negative number, or no patch is fitted; every refusal of
fit_counts for the material, the
backgrounds, the shared quantities and the pulse’s calibration;
PipelineError::Fitting if the pulse’s calibration has a covariance
that cannot be inverted or an eigendecomposition fails;
PipelineError::ShapeMismatch or PipelineError::InvalidParameter for
live fractions fit_counts refuses; PipelineError::FlightTimeGrid if
the grid refuses the time edges at the starting shared values.
PipelineError::InvalidParameter naming the first failing patch and its
error when no patch fits at the starting shared values, or naming the
empty pixels when their fit fails there; PipelineError::InvalidParameter
with the last patch’s reason when every patch is left out later.