Expand description
Instrument-resolution calibration.
Fits the instrument-resolution parameters of a chosen model family to a
known-(ρ, T) calibrant, holding the sample density and temperature FIXED.
This is the calibrate step of the standard calibrate→pin→fit procedure:
characterize the beamline resolution once on a known standard, pin it, then
fit unknown samples (crate::transmission_model / the typed fitters).
Mechanism: an outer crate::nelder_mead optimizer over the few resolution
parameters; each evaluation builds a ResolutionFunction from the
parameter vector, runs the existing forward_model at the fixed
SampleParams, and returns χ²/dof after analytically fitting a
normalization (anorm) and optional low-order baseline (so a baseline offset
does not leak into the resolution). Calibration is once-per-experiment, so a
derivative-free outer loop — not LM resolution-Jacobians — is the right tool;
this mirrors the established outer-loop pattern in
crate::joint_poisson’s polish stage.
Families (ResolutionFamily):
- Gaussian — fit
(Δt, ΔL). - UdrCorr — fit a shape-preserving width correction
s(E)=s0·(E/Eref)^pon a base tabulated UDR (TabulatedResolution::width_corrected); trusts the Monte-Carlo shape, calibrates its width/energy-dependence. UDR = User-Defined Resolution, SAMMY’s term for a numerical (table-supplied) resolution function. - IkedaCarpenter — physics-complete bounded moderator fit (#642):
α(E) = e^{θ0}·√E + e^{θ1}(positive at every energy by construction),β = e^{θ2}(bounded), scalar storage fractionR = θ3 ∈ [0, 1], all folded with the SNS PSR channel triangle (CalibrationConfig::psr_fwhm_ns, default 350 ns; optionally fitted viafit_psr). Beware the β↔R ridge: asR → 0the storage term vanishes and β is unconstrained — such a fit reports"r:lower"inCalibrationResult::bounds_hitand its β carries no information.
Structs§
- Calibration
Config - Configuration for
calibrate_resolution. - Calibration
Result - Result of a resolution calibration.
Enums§
- Resolution
Family - The resolution-model family to calibrate.
Constants§
- DEFAULT_
PSR_ FWHM_ NS - Default SNS PSR (proton-storage-ring / accumulator) channel-triangle FWHM
in ns, folded into the IC family’s kernel. The SNS proton pulse is
shaped by the accumulator ring into an ~triangular ~700 ns base (FWHM ≈
350 ns) — the VENUS tabulated FTS kernel header records exactly this
(“folded triang FWHM 350 ns PSR”). SAMMY’s analog is the Gaussian-burst
FWHM
DELTAG(Manual Sec. III.C.1.a, eq. III C1 a.12) or squareBURSTwidth (Sec. III.C.2.a).pubso the Python binding’s default and the Rust default cannot drift apart. - NS_
TO_ US - Nanoseconds → microseconds (
CalibrationConfig::psr_fwhm_nsis in ns to match the FTS header convention; the kernel synthesis takes µs).pubso the Python binding’s mirroredPSR_FWHM_PIN_CEILING_UScheck converts with the identical factor. - PSR_
FWHM_ PIN_ CEILING_ US - Sanity ceiling (µs) on the configured PSR triangle FWHM: one decade above
the
PSR_FWHM_US_MAXfit bound.CalibrationConfig::psr_fwhm_nsis in NANOSECONDS (the VENUS FTS header convention: “folded triang FWHM 350 ns PSR”), and kernel-synthesis cost grows QUADRATICALLY with a wide fold’s width. The mechanism is NOT τ-step refinement — that applies only to folds FINER than the prompt design step, and a 50–350 µs fold’s FWHM/3 resolution floor is far coarser, leaving the step unchanged — it is the convolution itself: the ±FWHM fold-reach margin adds O(FWHM/step) τ-samples, each folded inconvolve_sameagainst a sampled triangle itself O(FWHM/step) long. Measured ~12 ms at 0.35 µs but ~1.3 s at 50 µs and ~28 s at 350 µs per single kernel-table synthesis at the default grid. A µs-as-ns unit slip (passing350meaning µs → interpreted as a 350 µs pin) would therefore turn a calibration into a multi-hour silent hang behind a physically fictitious fold. Any genuine width sits inside the fitted box; one decade of headroom keeps deliberate sensitivity studies possible while still catching the 1000× ns↔µs slip.0.0(fold disabled) is always accepted.pubfor parity with the Python binding’s mirrored validation. - UDR_
S0_ MAX - Upper width-scale clamp; see
UDR_S0_MIN. - UDR_
S0_ MIN - Width-scale clamp for the UDR correction (
s0 = clamp(exp(log_s0), …)).pubso the Python binding decodes the reporteds0against the same bounds the optimizer used, rather than duplicating the literals.
Functions§
- calibrate_
resolution - Calibrate the resolution parameters of
familyagainst a known-(ρ,T) calibrant. - corrected_
energy_ grid - Map an energy grid through the SAMMY energy-scale
(t0, L_scale), using the SAME convention asEnergyScaleTransmissionModel::corrected_energies: with nominaltof(E) = TOF_FACTOR·L/√E, the corrected energy isE' = (TOF_FACTOR·L·L_scale / (tof − t0))². Identity at(t0, L_scale) = (0, 1).