Source code for ess.spectroscopy.indirect.time_of_flight

# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2025 Scipp contributors (https://github.com/scipp)

"""Utilities for computing real neutron time-of-flight for indirect geometry."""

from collections.abc import Iterable

import sciline
import scippnexus as snx

from ess.reduce import unwrap as reduce_unwrap
from ess.reduce.unwrap.types import DetectorLtotal

from ..types import (
    DataAtSample,
    ErrorLimitedLookupTable,
    LookupTable,
    LookupTableRelativeErrorThreshold,
    MonitorCoordTransformGraph,
    MonitorLtotal,
    MonitorType,
    NeXusDetectorName,
    PulseStrideOffset,
    RawDetector,
    RawMonitor,
    RunType,
    WavelengthDetector,
    WavelengthMonitor,
)


[docs] def TofWorkflow( *, run_types: Iterable[sciline.typing.Key], monitor_types: Iterable[sciline.typing.Key], ) -> sciline.Pipeline: workflow = reduce_unwrap.GenericUnwrapWorkflow( run_types=run_types, monitor_types=monitor_types, ) for provider in providers: workflow.insert(provider) return workflow
[docs] def detector_wavelength_data( sample_data: DataAtSample[RunType], lookup: ErrorLimitedLookupTable[snx.NXdetector], pulse_stride_offset: PulseStrideOffset, ) -> WavelengthDetector[RunType]: """ Convert the time-of-arrival data to wavelength data using a lookup table. The output data will have a wavelength coordinate. This is a wrapper around :func:`ess.reduce.unwrap.detector_wavelength_data` for indirect geometry spectrometers. """ result = reduce_unwrap.to_wavelength.detector_wavelength_data( detector_data=RawDetector[RunType](sample_data), lookup=lookup, ltotal=DetectorLtotal(sample_data.coords['L1']), pulse_stride_offset=pulse_stride_offset, ) # This is the incident wavelength at the sample. result.bins.coords['incident_wavelength'] = result.bins.coords.pop('wavelength') del result.bins.coords['event_time_zero'] return result
[docs] def monitor_wavelength_data( monitor_data: RawMonitor[RunType, MonitorType], lookup: ErrorLimitedLookupTable[MonitorType], ltotal: MonitorLtotal[RunType, MonitorType], pulse_stride_offset: PulseStrideOffset, ) -> WavelengthMonitor[RunType, MonitorType]: """ Convert the time-of-arrival data to wavelength data using a lookup table. The output data will have a wavelength coordinate. This is a wrapper around :func:`ess.reduce.unwrap.monitor_wavelength_data` for indirect geometry spectrometers. """ result = reduce_unwrap.to_wavelength.monitor_wavelength_data( monitor_data=monitor_data.rename(t='tof'), lookup=lookup, ltotal=ltotal, pulse_stride_offset=pulse_stride_offset, ) result = result.rename(wavelength='incident_wavelength') return result
[docs] def compute_monitor_ltotal( monitor_data: RawMonitor[RunType, MonitorType], coord_transform_graph: MonitorCoordTransformGraph, ) -> MonitorLtotal[RunType, MonitorType]: """Compute the path length from the source to the monitor.""" return MonitorLtotal[RunType, MonitorType]( monitor_data.transform_coords( 'Ltotal', graph=coord_transform_graph, keep_intermediate=False, keep_aliases=False, rename_dims=False, ).coords['Ltotal'] )
[docs] def mask_large_uncertainty_in_lut_detector( table: LookupTable, error_threshold: LookupTableRelativeErrorThreshold, ) -> ErrorLimitedLookupTable[snx.NXdetector]: """ Mask regions in the wavelength lookup table with large uncertainty using NaNs. The threshold is looked up under the key ``'detector'``. The same threshold is applied to all triplets. Parameters ---------- table: Lookup table with wavelength as a function of distance and time-of-arrival. error_threshold: Threshold for the relative standard deviation (coefficient of variation) of the projected wavelength above which values are masked. See also -------- essreduce.unwrap.mask_large_uncertainty_in_lut: The underlying implementation. """ from ess.reduce.unwrap.to_wavelength import ( mask_large_uncertainty_in_lut_detector, ) return ErrorLimitedLookupTable[snx.NXdetector]( mask_large_uncertainty_in_lut_detector( table=table, error_threshold=error_threshold, detector_name=NeXusDetectorName('detector'), ) )
providers = ( compute_monitor_ltotal, detector_wavelength_data, mask_large_uncertainty_in_lut_detector, monitor_wavelength_data, ) """Providers for wavelength calculation on indirect geometry spectrometers. The providers here override the default providers of :class:`ess.reduce.unwrap.GenericUnwrapWorkflow` to customize the workflow for indirect geometry spectrometers. """