Problem
BIFROST's geometry models the real neutron source as an NXmoderator (~162 m upstream) and reserves NXsource for accelerator/production metadata that is explicitly pinned at the origin (depends_on='.', empty transformations) — coinciding with the sample. This matches essreduce's own ProductionInfo docstring ("its position is not relevant for data reduction").
essreduce, however, keys the source position off the unique NXsource component. For BIFROST that resolves to the origin-pinned accelerator group, not the moderator. Any reduction path that consumes Position[NXsource, RunType] therefore silently measures distances from the origin (i.e. the sample) for BIFROST.
Where it currently bites / is worked around
The chopper-cascade wavelength-LUT workflow hit this as a hard failure (chopper distance came out negative, since the choppers sit "behind" an origin source). It is worked around in wavelength_lut_workflow._moderator_source_position: resolve the source from NXmoderator when present, else fall back to NXsource.
That fix is local to the LUT workflow only. The same trap is latent anywhere else source position matters — most notably a detector Ltotal computation. BIFROST's detector reduction is currently TOA-based, so it does not exercise the source position today, but the moment it (or any other instrument adopting the NXmoderator convention) uses an essreduce TOF/Ltotal path, it will silently compute from the sample with no error.
Possible directions
- Centralise the moderator-preferring source resolution so every workflow shares it, rather than the one-off in the LUT workflow.
- Or push it upstream into essreduce: prefer
NXmoderator for the source position when present, treating NXsource as production metadata.
Whichever way, the goal is convention-agnostic behaviour: works whether the source is labelled NXsource (e.g. LOKI) or NXmoderator (BIFROST), since the convention is not expected to be uniform across instruments.
Context: surfaced while reviving the BIFROST chopper-cascade work (bifrost-choppers). Related to the geometry-file issues tracked in #962.
Problem
BIFROST's geometry models the real neutron source as an
NXmoderator(~162 m upstream) and reservesNXsourcefor accelerator/production metadata that is explicitly pinned at the origin (depends_on='.', empty transformations) — coinciding with the sample. This matches essreduce's ownProductionInfodocstring ("its position is not relevant for data reduction").essreduce, however, keys the source position off the unique
NXsourcecomponent. For BIFROST that resolves to the origin-pinned accelerator group, not the moderator. Any reduction path that consumesPosition[NXsource, RunType]therefore silently measures distances from the origin (i.e. the sample) for BIFROST.Where it currently bites / is worked around
The chopper-cascade wavelength-LUT workflow hit this as a hard failure (chopper distance came out negative, since the choppers sit "behind" an origin source). It is worked around in
wavelength_lut_workflow._moderator_source_position: resolve the source fromNXmoderatorwhen present, else fall back toNXsource.That fix is local to the LUT workflow only. The same trap is latent anywhere else source position matters — most notably a detector
Ltotalcomputation. BIFROST's detector reduction is currently TOA-based, so it does not exercise the source position today, but the moment it (or any other instrument adopting theNXmoderatorconvention) uses an essreduce TOF/Ltotalpath, it will silently compute from the sample with no error.Possible directions
NXmoderatorfor the source position when present, treatingNXsourceas production metadata.Whichever way, the goal is convention-agnostic behaviour: works whether the source is labelled
NXsource(e.g. LOKI) orNXmoderator(BIFROST), since the convention is not expected to be uniform across instruments.Context: surfaced while reviving the BIFROST chopper-cascade work (
bifrost-choppers). Related to the geometry-file issues tracked in #962.