diff --git a/docs/user-guide/tof/dream.ipynb b/docs/user-guide/tof/dream.ipynb index 62e125ad..3ea29af8 100644 --- a/docs/user-guide/tof/dream.ipynb +++ b/docs/user-guide/tof/dream.ipynb @@ -24,7 +24,7 @@ "import plopp as pp\n", "import scipp as sc\n", "from scippneutron.chopper import DiskChopper\n", - "from ess.reduce.nexus.types import AnyRun, DetectorData, SampleRun\n", + "from ess.reduce.nexus.types import AnyRun, RawDetector, SampleRun\n", "from ess.reduce.time_of_flight import *" ] }, @@ -300,10 +300,10 @@ "source": [ "wf = GenericTofWorkflow(run_types=[SampleRun], monitor_types=[])\n", "\n", - "wf[DetectorData[SampleRun]] = raw_data\n", + "wf[RawDetector[SampleRun]] = raw_data\n", "wf[DetectorLtotal[SampleRun]] = Ltotal\n", "\n", - "wf.visualize(DetectorTofData[SampleRun])" + "wf.visualize(TofDetector[SampleRun])" ] }, { @@ -436,7 +436,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "id": "30", "metadata": {}, @@ -457,7 +456,7 @@ "wf[TimeOfFlightLookupTable] = table\n", "\n", "# Compute time-of-flight of neutron events\n", - "tofs = wf.compute(DetectorTofData[SampleRun])\n", + "tofs = wf.compute(TofDetector[SampleRun])\n", "tofs" ] }, @@ -616,11 +615,11 @@ "outputs": [], "source": [ "# Update workflow\n", - "wf[DetectorData[SampleRun]] = raw_data\n", + "wf[RawDetector[SampleRun]] = raw_data\n", "wf[DetectorLtotal[SampleRun]] = Ltotal\n", "\n", "# Compute tofs and wavelengths\n", - "tofs = wf.compute(DetectorTofData[SampleRun])\n", + "tofs = wf.compute(TofDetector[SampleRun])\n", "wav_wfm = tofs.transform_coords(\"wavelength\", graph=graph)\n", "\n", "# Compare in plot\n", @@ -795,13 +794,13 @@ "metadata": {}, "outputs": [], "source": [ - "wf[DetectorData[SampleRun]] = ess_beamline.get_monitor(\"detector\")[0]\n", + "wf[RawDetector[SampleRun]] = ess_beamline.get_monitor(\"detector\")[0]\n", "wf[DetectorLtotal[SampleRun]] = Ltotal\n", "\n", "wf[TimeOfFlightLookupTable] = table\n", "\n", "# Compute time-of-flight\n", - "tofs = wf.compute(DetectorTofData[SampleRun])\n", + "tofs = wf.compute(TofDetector[SampleRun])\n", "# Compute wavelength\n", "wav_wfm = tofs.transform_coords(\"wavelength\", graph=graph)\n", "\n", @@ -823,17 +822,6 @@ "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3" } }, "nbformat": 4, diff --git a/docs/user-guide/tof/frame-unwrapping.ipynb b/docs/user-guide/tof/frame-unwrapping.ipynb index c2369ad5..43f58116 100644 --- a/docs/user-guide/tof/frame-unwrapping.ipynb +++ b/docs/user-guide/tof/frame-unwrapping.ipynb @@ -1,7 +1,6 @@ { "cells": [ { - "attachments": {}, "cell_type": "markdown", "id": "0", "metadata": {}, @@ -32,7 +31,7 @@ "import plopp as pp\n", "import scipp as sc\n", "from scippneutron.chopper import DiskChopper\n", - "from ess.reduce.nexus.types import AnyRun, DetectorData, SampleRun\n", + "from ess.reduce.nexus.types import AnyRun, RawDetector, SampleRun\n", "from ess.reduce.time_of_flight import *\n", "import tof\n", "\n", @@ -161,10 +160,10 @@ "source": [ "wf = GenericTofWorkflow(run_types=[SampleRun], monitor_types=[])\n", "\n", - "wf[DetectorData[SampleRun]] = nxevent_data\n", + "wf[RawDetector[SampleRun]] = nxevent_data\n", "wf[DetectorLtotal[SampleRun]] = nxevent_data.coords[\"Ltotal\"]\n", "\n", - "wf.visualize(DetectorTofData[SampleRun])" + "wf.visualize(TofDetector[SampleRun])" ] }, { @@ -271,7 +270,7 @@ "wf[TimeOfFlightLookupTable] = table\n", "\n", "# Compute neutron tofs\n", - "tofs = wf.compute(DetectorTofData[SampleRun])\n", + "tofs = wf.compute(TofDetector[SampleRun])\n", "\n", "tof_hist = tofs.hist(tof=sc.scalar(500.0, unit=\"us\"))\n", "pp.plot({det.name: tof_hist[\"detector_number\", i] for i, det in enumerate(detectors)})" @@ -456,11 +455,11 @@ "# Reduction workflow\n", "wf = GenericTofWorkflow(run_types=[SampleRun], monitor_types=[])\n", "nxevent_data = results.to_nxevent_data()\n", - "wf[DetectorData[SampleRun]] = nxevent_data\n", + "wf[RawDetector[SampleRun]] = nxevent_data\n", "wf[DetectorLtotal[SampleRun]] = nxevent_data.coords[\"Ltotal\"]\n", "wf[TimeOfFlightLookupTable] = table\n", "\n", - "tofs = wf.compute(DetectorTofData[SampleRun])\n", + "tofs = wf.compute(TofDetector[SampleRun])\n", "\n", "tof_hist = tofs.hist(tof=sc.scalar(500.0, unit=\"us\"))\n", "pp.plot({det.name: tof_hist[\"detector_number\", i] for i, det in enumerate(detectors)})" @@ -500,24 +499,7 @@ ] } ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3" - } - }, + "metadata": {}, "nbformat": 4, "nbformat_minor": 5 } diff --git a/docs/user-guide/tof/wfm.ipynb b/docs/user-guide/tof/wfm.ipynb index 99fd8909..e6eb7000 100644 --- a/docs/user-guide/tof/wfm.ipynb +++ b/docs/user-guide/tof/wfm.ipynb @@ -25,7 +25,7 @@ "import plopp as pp\n", "import scipp as sc\n", "from scippneutron.chopper import DiskChopper\n", - "from ess.reduce.nexus.types import AnyRun, DetectorData, SampleRun\n", + "from ess.reduce.nexus.types import AnyRun, RawDetector, SampleRun\n", "from ess.reduce.time_of_flight import *" ] }, @@ -321,10 +321,10 @@ "source": [ "wf = GenericTofWorkflow(run_types=[SampleRun], monitor_types=[])\n", "\n", - "wf[DetectorData[SampleRun]] = raw_data\n", + "wf[RawDetector[SampleRun]] = raw_data\n", "wf[DetectorLtotal[SampleRun]] = Ltotal\n", "\n", - "wf.visualize(DetectorTofData[SampleRun])" + "wf.visualize(TofDetector[SampleRun])" ] }, { @@ -442,7 +442,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "id": "27", "metadata": {}, @@ -466,7 +465,7 @@ "source": [ "wf[TimeOfFlightLookupTable] = table\n", "\n", - "tofs = wf.compute(DetectorTofData[SampleRun])\n", + "tofs = wf.compute(TofDetector[SampleRun])\n", "tofs" ] }, @@ -549,24 +548,7 @@ ] } ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3" - } - }, + "metadata": {}, "nbformat": 4, "nbformat_minor": 5 } diff --git a/src/ess/reduce/live/raw.py b/src/ess/reduce/live/raw.py index 7c48ef31..ef3c0624 100644 --- a/src/ess/reduce/live/raw.py +++ b/src/ess/reduce/live/raw.py @@ -29,7 +29,7 @@ import scippnexus as snx from ess.reduce.nexus.types import ( - CalibratedDetector, + EmptyDetector, Filename, NeXusComponent, NeXusDetectorName, @@ -305,7 +305,7 @@ def transform_weights( @staticmethod def from_detector_and_histogrammer( - detector: CalibratedDetector[SampleRun], + detector: EmptyDetector[SampleRun], window: RollingDetectorViewWindow, projection: Histogrammer, ) -> RollingDetectorView: @@ -320,10 +320,10 @@ def from_detector_and_histogrammer( def from_detector_with_projection( projection: Callable[[sc.DataArray], sc.DataArray] | None, ) -> Callable[ - [CalibratedDetector[SampleRun], RollingDetectorViewWindow], RollingDetectorView + [EmptyDetector[SampleRun], RollingDetectorViewWindow], RollingDetectorView ]: def factory( - detector: CalibratedDetector[SampleRun], + detector: EmptyDetector[SampleRun], window: RollingDetectorViewWindow, ) -> RollingDetectorView: """Helper for constructing via a Sciline workflow.""" @@ -591,7 +591,7 @@ def gaussian_position_noise(sigma: PositionNoiseSigma) -> PositionNoise: def position_with_noisy_replicas( *, - detector: CalibratedDetector[SampleRun], + detector: EmptyDetector[SampleRun], position_noise: PositionNoise, replicas: PositionNoiseReplicaCount, ) -> CalibratedPositionWithNoisyReplicas: diff --git a/src/ess/reduce/nexus/types.py b/src/ess/reduce/nexus/types.py index 911d0718..05dcbb62 100644 --- a/src/ess/reduce/nexus/types.py +++ b/src/ess/reduce/nexus/types.py @@ -199,25 +199,19 @@ class MonitorPositionOffset( """Offset for the monitor position, added to base position.""" -class CalibratedDetector(sciline.Scope[RunType, sc.DataArray], sc.DataArray): - """Calibrated data from a detector.""" +class EmptyDetector(sciline.Scope[RunType, sc.DataArray], sc.DataArray): + """Detector without neutron data.""" -class CalibratedBeamline(sciline.Scope[RunType, sc.DataArray], sc.DataArray): - """Calibrated beamline with detector and other components.""" +class EmptyMonitor(sciline.Scope[RunType, MonitorType, sc.DataArray], sc.DataArray): + """Monitor without neutron data.""" -class CalibratedMonitor( - sciline.Scope[RunType, MonitorType, sc.DataArray], sc.DataArray -): - """Calibrated data from a monitor.""" - - -class DetectorData(sciline.Scope[RunType, sc.DataArray], sc.DataArray): +class RawDetector(sciline.Scope[RunType, sc.DataArray], sc.DataArray): """Calibrated detector merged with neutron event or histogram data.""" -class MonitorData(sciline.Scope[RunType, MonitorType, sc.DataArray], sc.DataArray): +class RawMonitor(sciline.Scope[RunType, MonitorType, sc.DataArray], sc.DataArray): """Calibrated monitor merged with neutron event or histogram data.""" diff --git a/src/ess/reduce/nexus/workflow.py b/src/ess/reduce/nexus/workflow.py index 86e4fdd1..80057f5a 100644 --- a/src/ess/reduce/nexus/workflow.py +++ b/src/ess/reduce/nexus/workflow.py @@ -20,17 +20,14 @@ COMPONENT_CONSTRAINTS, AllNeXusComponents, Beamline, - CalibratedBeamline, - CalibratedDetector, - CalibratedMonitor, Component, DetectorBankSizes, - DetectorData, DetectorPositionOffset, + EmptyDetector, + EmptyMonitor, Filename, GravityVector, Measurement, - MonitorData, MonitorPositionOffset, MonitorType, NeXusAllComponentLocationSpec, @@ -46,6 +43,8 @@ Position, PreopenNeXusFile, RawChoppers, + RawDetector, + RawMonitor, RunType, TimeInterval, UniqueComponent, @@ -360,13 +359,11 @@ def get_calibrated_detector( # all. offset: DetectorPositionOffset[RunType], bank_sizes: DetectorBankSizes, -) -> CalibratedDetector[RunType]: +) -> EmptyDetector[RunType]: """ Extract the data array corresponding to a detector's signal field. - The returned data array includes coords and masks pertaining directly to the - signal values array, but not additional information about the detector. The - data array is reshaped to the logical detector shape, which by folding the data + The data array is reshaped to the logical detector shape, by folding the data array along the detector_number dimension. Parameters @@ -395,50 +392,15 @@ def get_calibrated_detector( else: transform_value = transform.value position = transform_value * offsets - return CalibratedDetector[RunType]( + return EmptyDetector[RunType]( da.assign_coords(position=position + offset.to(unit=position.unit)) ) -def assemble_beamline( - detector: CalibratedDetector[RunType], - source_position: Position[snx.NXsource, RunType], - sample_position: Position[snx.NXsample, RunType], - gravity: GravityVector, -) -> CalibratedBeamline[RunType]: - """ - Add beamline information (gravity vector, source- and sample-position) to detector. - - This is performed separately and after :py:func:`get_calibrated_detector` to avoid - as false dependency of, e.g., the reshaped detector numbers on the sample position. - The latter can change during a run, e.g., for a rotating sample. The detector - numbers might be used, e.g., to mask certain detector pixels, and should not depend - on the sample position. - - Parameters - ---------- - detector: - NeXus detector group. - source_position: - Position of the neutron source. - sample_position: - Position of the sample. - gravity: - Gravity vector. - """ - return CalibratedBeamline[RunType]( - detector.assign_coords( - source_position=source_position, - sample_position=sample_position, - gravity=gravity, - ) - ) - - def assemble_detector_data( - detector: CalibratedBeamline[RunType], + detector: EmptyDetector[RunType], event_data: NeXusData[snx.NXdetector, RunType], -) -> DetectorData[RunType]: +) -> RawDetector[RunType]: """ Assemble a detector data array with event data. @@ -454,7 +416,7 @@ def assemble_detector_data( grouped = nexus.group_event_data( event_data=event_data, detector_number=detector.coords['detector_number'] ) - return DetectorData[RunType]( + return RawDetector[RunType]( _add_variances(grouped) .assign_coords(detector.coords) .assign_masks(detector.masks) @@ -465,7 +427,7 @@ def get_calibrated_monitor( monitor: NeXusComponent[MonitorType, RunType], offset: MonitorPositionOffset[RunType, MonitorType], source_position: Position[snx.NXsource, RunType], -) -> CalibratedMonitor[RunType, MonitorType]: +) -> EmptyMonitor[RunType, MonitorType]: """ Extract the data array corresponding to a monitor's signal field. @@ -482,7 +444,7 @@ def get_calibrated_monitor( Position of the neutron source. """ monitor = nexus.compute_component_position(monitor) - return CalibratedMonitor[RunType, MonitorType]( + return EmptyMonitor[RunType, MonitorType]( nexus.extract_signal_data_array(monitor).assign_coords( position=monitor['position'] + offset.to(unit=monitor['position'].unit), source_position=source_position, @@ -491,9 +453,9 @@ def get_calibrated_monitor( def assemble_monitor_data( - monitor: CalibratedMonitor[RunType, MonitorType], + monitor: EmptyMonitor[RunType, MonitorType], data: NeXusData[MonitorType, RunType], -) -> MonitorData[RunType, MonitorType]: +) -> RawMonitor[RunType, MonitorType]: """ Assemble a monitor data array with event data. @@ -507,7 +469,7 @@ def assemble_monitor_data( Data array with neutron counts. """ da = data.assign_coords(monitor.coords).assign_masks(monitor.masks) - return MonitorData[RunType, MonitorType](_add_variances(da)) + return RawMonitor[RunType, MonitorType](_add_variances(da)) def parse_disk_choppers( @@ -655,7 +617,6 @@ def load_measurement_metadata_from_nexus( no_detector_position_offset, load_nexus_sample, get_calibrated_detector, - assemble_beamline, assemble_detector_data, ) diff --git a/src/ess/reduce/time_of_flight/__init__.py b/src/ess/reduce/time_of_flight/__init__.py index b64bba50..fa5374f9 100644 --- a/src/ess/reduce/time_of_flight/__init__.py +++ b/src/ess/reduce/time_of_flight/__init__.py @@ -24,25 +24,23 @@ ) from .types import ( DetectorLtotal, - DetectorTofData, MonitorLtotal, - MonitorTofData, PulseStrideOffset, TimeOfFlightLookupTable, TimeOfFlightLookupTableFilename, + TofDetector, + TofMonitor, ) from .workflow import GenericTofWorkflow __all__ = [ "DetectorLtotal", - "DetectorTofData", "DiskChoppers", "DistanceResolution", "GenericTofWorkflow", "LookupTableRelativeErrorThreshold", "LtotalRange", "MonitorLtotal", - "MonitorTofData", "NumberOfSimulatedNeutrons", "PulsePeriod", "PulseStride", @@ -53,7 +51,9 @@ "TimeOfFlightLookupTable", "TimeOfFlightLookupTableFilename", "TimeResolution", + "TofDetector", "TofLookupTableWorkflow", + "TofMonitor", "providers", "simulate_chopper_cascade_using_tof", ] diff --git a/src/ess/reduce/time_of_flight/eto_to_tof.py b/src/ess/reduce/time_of_flight/eto_to_tof.py index b0bacc06..1d81da9b 100644 --- a/src/ess/reduce/time_of_flight/eto_to_tof.py +++ b/src/ess/reduce/time_of_flight/eto_to_tof.py @@ -12,6 +12,7 @@ import numpy as np import scipp as sc import scippneutron as scn +import scippnexus as snx from scippneutron._utils import elem_unit try: @@ -20,21 +21,23 @@ from .interpolator_scipy import Interpolator as InterpolatorImpl from ..nexus.types import ( - CalibratedBeamline, - CalibratedMonitor, - DetectorData, - MonitorData, + EmptyDetector, + EmptyMonitor, + GravityVector, MonitorType, + Position, + RawDetector, + RawMonitor, RunType, ) from .resample import rebin_strictly_increasing from .types import ( DetectorLtotal, - DetectorTofData, MonitorLtotal, - MonitorTofData, PulseStrideOffset, TimeOfFlightLookupTable, + TofDetector, + TofMonitor, ) @@ -271,30 +274,42 @@ def _time_of_flight_data_events( def detector_ltotal_from_straight_line_approximation( - detector_beamline: CalibratedBeamline[RunType], + detector: EmptyDetector[RunType], + source_position: Position[snx.NXsource, RunType], + sample_position: Position[snx.NXsample, RunType], + gravity: GravityVector, ) -> DetectorLtotal[RunType]: - """ - Compute Ltotal for the detector pixels. + """Compute Ltotal for the detector pixels. + This is a naive straight-line approximation to Ltotal based on basic component positions. Parameters ---------- - detector_beamline: - Beamline data for the detector that contains the positions necessary to compute - the straight-line approximation to Ltotal (source, sample, and detector - positions). + detector: + Data array with detector positions. + source_position: + Position of the neutron source. + sample_position: + Position of the sample. + gravity: + Gravity vector. """ - graph = scn.conversion.graph.beamline.beamline(scatter=True) + graph = { + **scn.conversion.graph.beamline.beamline(scatter=True), + 'source_position': lambda: source_position, + 'sample_position': lambda: sample_position, + 'gravity': lambda: gravity, + } return DetectorLtotal[RunType]( - detector_beamline.transform_coords( + detector.transform_coords( "Ltotal", graph=graph, keep_intermediate=False ).coords["Ltotal"] ) def monitor_ltotal_from_straight_line_approximation( - monitor_beamline: CalibratedMonitor[RunType, MonitorType], + monitor_beamline: EmptyMonitor[RunType, MonitorType], ) -> MonitorLtotal[RunType, MonitorType]: """ Compute Ltotal for the monitor. @@ -334,11 +349,11 @@ def _compute_tof_data( def detector_time_of_flight_data( - detector_data: DetectorData[RunType], + detector_data: RawDetector[RunType], lookup: TimeOfFlightLookupTable, ltotal: DetectorLtotal[RunType], pulse_stride_offset: PulseStrideOffset, -) -> DetectorTofData[RunType]: +) -> TofDetector[RunType]: """ Convert the time-of-arrival data to time-of-flight data using a lookup table. The output data will have a time-of-flight coordinate. @@ -357,7 +372,7 @@ def detector_time_of_flight_data( When pulse-skipping, the offset of the first pulse in the stride. This is typically zero but can be a small integer < pulse_stride. """ - return DetectorTofData[RunType]( + return TofDetector[RunType]( _compute_tof_data( da=detector_data, lookup=lookup, @@ -368,11 +383,11 @@ def detector_time_of_flight_data( def monitor_time_of_flight_data( - monitor_data: MonitorData[RunType, MonitorType], + monitor_data: RawMonitor[RunType, MonitorType], lookup: TimeOfFlightLookupTable, ltotal: MonitorLtotal[RunType, MonitorType], pulse_stride_offset: PulseStrideOffset, -) -> MonitorTofData[RunType, MonitorType]: +) -> TofMonitor[RunType, MonitorType]: """ Convert the time-of-arrival data to time-of-flight data using a lookup table. The output data will have a time-of-flight coordinate. @@ -391,7 +406,7 @@ def monitor_time_of_flight_data( When pulse-skipping, the offset of the first pulse in the stride. This is typically zero but can be a small integer < pulse_stride. """ - return MonitorTofData[RunType, MonitorType]( + return TofMonitor[RunType, MonitorType]( _compute_tof_data( da=monitor_data, lookup=lookup, diff --git a/src/ess/reduce/time_of_flight/types.py b/src/ess/reduce/time_of_flight/types.py index 71bd0944..fc94f679 100644 --- a/src/ess/reduce/time_of_flight/types.py +++ b/src/ess/reduce/time_of_flight/types.py @@ -33,9 +33,9 @@ class MonitorLtotal(sl.Scope[RunType, MonitorType, sc.Variable], sc.Variable): """Total path length of neutrons from source to monitor.""" -class DetectorTofData(sl.Scope[RunType, sc.DataArray], sc.DataArray): +class TofDetector(sl.Scope[RunType, sc.DataArray], sc.DataArray): """Detector data with time-of-flight coordinate.""" -class MonitorTofData(sl.Scope[RunType, MonitorType, sc.DataArray], sc.DataArray): +class TofMonitor(sl.Scope[RunType, MonitorType, sc.DataArray], sc.DataArray): """Monitor data with time-of-flight coordinate.""" diff --git a/tests/nexus/workflow_test.py b/tests/nexus/workflow_test.py index 55ddd775..826eb38f 100644 --- a/tests/nexus/workflow_test.py +++ b/tests/nexus/workflow_test.py @@ -12,20 +12,20 @@ from ess.reduce.nexus.types import ( BackgroundRun, Beamline, - DetectorData, EmptyBeamRun, Filename, FrameMonitor0, FrameMonitor1, FrameMonitor2, Measurement, - MonitorData, MonitorType, NeXusComponentLocationSpec, NeXusName, NeXusTransformation, PreopenNeXusFile, RawChoppers, + RawDetector, + RawMonitor, RunType, SampleRun, TimeInterval, @@ -333,9 +333,9 @@ def test_get_calibrated_detector_forwards_masks( @pytest.fixture -def calibrated_detector() -> workflow.CalibratedDetector[SampleRun]: +def calibrated_detector() -> workflow.EmptyDetector[SampleRun]: detector_number = sc.arange('detector_number', 6, unit=None) - return workflow.CalibratedDetector[SampleRun]( + return workflow.EmptyDetector[SampleRun]( sc.DataArray( sc.empty_like(detector_number), coords={ @@ -446,8 +446,8 @@ def test_get_calibrated_monitor_subtracts_offset_from_position( @pytest.fixture -def calibrated_monitor() -> workflow.CalibratedMonitor[SampleRun, FrameMonitor1]: - return workflow.CalibratedMonitor[SampleRun, FrameMonitor1]( +def calibrated_monitor() -> workflow.EmptyMonitor[SampleRun, FrameMonitor1]: + return workflow.EmptyMonitor[SampleRun, FrameMonitor1]( sc.DataArray( sc.scalar(0), coords={'position': sc.vector([1.0, 2.0, 3.0], unit='m')}, @@ -553,7 +553,7 @@ def test_load_event_monitor_workflow(loki_tutorial_sample_run_60250: Path) -> No wf = LoadMonitorWorkflow(run_types=[SampleRun], monitor_types=[FrameMonitor1]) wf[Filename[SampleRun]] = loki_tutorial_sample_run_60250 wf[NeXusName[FrameMonitor1]] = 'monitor_1' - da = wf.compute(MonitorData[SampleRun, FrameMonitor1]) + da = wf.compute(RawMonitor[SampleRun, FrameMonitor1]) assert 'position' in da.coords assert 'source_position' in da.coords assert da.bins is not None @@ -565,7 +565,7 @@ def test_load_histogram_monitor_workflow(dream_coda_test_file: Path) -> None: wf = LoadMonitorWorkflow(run_types=[SampleRun], monitor_types=[FrameMonitor1]) wf[Filename[SampleRun]] = dream_coda_test_file wf[NeXusName[FrameMonitor1]] = 'monitor_bunker' - da = wf.compute(MonitorData[SampleRun, FrameMonitor1]) + da = wf.compute(RawMonitor[SampleRun, FrameMonitor1]) assert 'position' in da.coords assert 'source_position' in da.coords assert da.bins is None @@ -579,10 +579,8 @@ def test_load_detector_workflow(loki_tutorial_sample_run_60250: Path) -> None: wf = LoadDetectorWorkflow(run_types=[SampleRun], monitor_types=[]) wf[Filename[SampleRun]] = loki_tutorial_sample_run_60250 wf[NeXusName[snx.NXdetector]] = 'larmor_detector' - da = wf.compute(DetectorData[SampleRun]) + da = wf.compute(RawDetector[SampleRun]) assert 'position' in da.coords - assert 'sample_position' in da.coords - assert 'source_position' in da.coords assert da.bins is not None assert da.dims == ('detector_number',) @@ -596,13 +594,11 @@ def test_generic_nexus_workflow( wf[NeXusName[FrameMonitor1]] = 'monitor_1' wf[NeXusName[snx.NXdetector]] = 'larmor_detector' wf[PreopenNeXusFile] = preopen - da = wf.compute(DetectorData[SampleRun]) + da = wf.compute(RawDetector[SampleRun]) assert 'position' in da.coords - assert 'sample_position' in da.coords - assert 'source_position' in da.coords assert da.bins is not None assert da.dims == ('detector_number',) - da = wf.compute(MonitorData[SampleRun, FrameMonitor1]) + da = wf.compute(RawMonitor[SampleRun, FrameMonitor1]) assert 'position' in da.coords assert 'source_position' in da.coords assert da.bins is not None @@ -663,14 +659,14 @@ def test_generic_nexus_workflow_includes_only_given_run_and_monitor_types() -> N graph = wf.underlying_graph # Check some examples to avoid relying entirely on complicated loops below. - assert DetectorData[SampleRun] in graph - assert DetectorData[BackgroundRun] not in graph - assert MonitorData[SampleRun, FrameMonitor1] in graph - assert MonitorData[SampleRun, FrameMonitor2] not in graph - assert MonitorData[SampleRun, FrameMonitor0] in graph - assert MonitorData[BackgroundRun, FrameMonitor0] not in graph - assert MonitorData[BackgroundRun, FrameMonitor1] not in graph - assert MonitorData[BackgroundRun, FrameMonitor2] not in graph + assert RawDetector[SampleRun] in graph + assert RawDetector[BackgroundRun] not in graph + assert RawMonitor[SampleRun, FrameMonitor1] in graph + assert RawMonitor[SampleRun, FrameMonitor2] not in graph + assert RawMonitor[SampleRun, FrameMonitor0] in graph + assert RawMonitor[BackgroundRun, FrameMonitor0] not in graph + assert RawMonitor[BackgroundRun, FrameMonitor1] not in graph + assert RawMonitor[BackgroundRun, FrameMonitor2] not in graph assert RawChoppers[SampleRun] in graph assert RawChoppers[BackgroundRun] not in graph @@ -705,14 +701,14 @@ def test_generic_nexus_workflow_includes_only_given_run_types() -> None: graph = wf.underlying_graph # Check some examples to avoid relying entirely on complicated loops below. - assert DetectorData[EmptyBeamRun] in graph - assert DetectorData[SampleRun] not in graph - assert MonitorData[EmptyBeamRun, FrameMonitor1] in graph - assert MonitorData[EmptyBeamRun, FrameMonitor2] in graph - assert MonitorData[EmptyBeamRun, FrameMonitor0] in graph - assert MonitorData[SampleRun, FrameMonitor1] not in graph - assert MonitorData[SampleRun, FrameMonitor2] not in graph - assert MonitorData[SampleRun, FrameMonitor0] not in graph + assert RawDetector[EmptyBeamRun] in graph + assert RawDetector[SampleRun] not in graph + assert RawMonitor[EmptyBeamRun, FrameMonitor1] in graph + assert RawMonitor[EmptyBeamRun, FrameMonitor2] in graph + assert RawMonitor[EmptyBeamRun, FrameMonitor0] in graph + assert RawMonitor[SampleRun, FrameMonitor1] not in graph + assert RawMonitor[SampleRun, FrameMonitor2] not in graph + assert RawMonitor[SampleRun, FrameMonitor0] not in graph assert RawChoppers[EmptyBeamRun] in graph assert RawChoppers[SampleRun] not in graph @@ -729,16 +725,16 @@ def test_generic_nexus_workflow_includes_only_given_monitor_types() -> None: graph = wf.underlying_graph # Check some examples to avoid relying entirely on complicated loops below. - assert DetectorData[SampleRun] in graph - assert DetectorData[BackgroundRun] in graph - assert MonitorData[SampleRun, TransmissionMonitor] in graph - assert MonitorData[SampleRun, FrameMonitor1] in graph - assert MonitorData[SampleRun, FrameMonitor2] not in graph - assert MonitorData[SampleRun, FrameMonitor0] not in graph - assert MonitorData[BackgroundRun, TransmissionMonitor] in graph - assert MonitorData[BackgroundRun, FrameMonitor1] in graph - assert MonitorData[BackgroundRun, FrameMonitor2] not in graph - assert MonitorData[BackgroundRun, FrameMonitor0] not in graph + assert RawDetector[SampleRun] in graph + assert RawDetector[BackgroundRun] in graph + assert RawMonitor[SampleRun, TransmissionMonitor] in graph + assert RawMonitor[SampleRun, FrameMonitor1] in graph + assert RawMonitor[SampleRun, FrameMonitor2] not in graph + assert RawMonitor[SampleRun, FrameMonitor0] not in graph + assert RawMonitor[BackgroundRun, TransmissionMonitor] in graph + assert RawMonitor[BackgroundRun, FrameMonitor1] in graph + assert RawMonitor[BackgroundRun, FrameMonitor2] not in graph + assert RawMonitor[BackgroundRun, FrameMonitor0] not in graph assert RawChoppers[SampleRun] in graph assert RawChoppers[BackgroundRun] in graph diff --git a/tests/time_of_flight/unwrap_test.py b/tests/time_of_flight/unwrap_test.py index 4e9cc3c1..94d75e01 100644 --- a/tests/time_of_flight/unwrap_test.py +++ b/tests/time_of_flight/unwrap_test.py @@ -8,7 +8,7 @@ from scippneutron.conversion.graph.tof import elastic as elastic_graph from ess.reduce import time_of_flight -from ess.reduce.nexus.types import AnyRun, DetectorData, SampleRun +from ess.reduce.nexus.types import AnyRun, RawDetector, SampleRun from ess.reduce.time_of_flight import GenericTofWorkflow, TofLookupTableWorkflow, fakes sl = pytest.importorskip("sciline") @@ -62,7 +62,7 @@ def _make_workflow_event_mode( mon, ref = beamline.get_monitor("detector") pl = GenericTofWorkflow(run_types=[SampleRun], monitor_types=[]) - pl[DetectorData[SampleRun]] = mon + pl[RawDetector[SampleRun]] = mon pl[time_of_flight.DetectorLtotal[SampleRun]] = distance pl[time_of_flight.PulseStrideOffset] = pulse_stride_offset @@ -93,7 +93,7 @@ def _make_workflow_histogram_mode(dim, distance, choppers, lut_workflow, seed): ).rename(event_time_offset=dim) pl = GenericTofWorkflow(run_types=[SampleRun], monitor_types=[]) - pl[DetectorData[SampleRun]] = mon + pl[RawDetector[SampleRun]] = mon pl[time_of_flight.DetectorLtotal[SampleRun]] = distance lut_wf = lut_workflow.copy() @@ -161,7 +161,7 @@ def test_unwrap_with_no_choppers() -> None: error_threshold=1.0, ) - tofs = pl.compute(time_of_flight.DetectorTofData[SampleRun]) + tofs = pl.compute(time_of_flight.TofDetector[SampleRun]) _validate_result_events( tofs=tofs, ref=ref, percentile=96, diff_threshold=1.0, rtol=0.02 @@ -184,7 +184,7 @@ def test_standard_unwrap(dist, lut_workflow_psc_choppers) -> None: error_threshold=0.1, ) - tofs = pl.compute(time_of_flight.DetectorTofData[SampleRun]) + tofs = pl.compute(time_of_flight.TofDetector[SampleRun]) _validate_result_events( tofs=tofs, ref=ref, percentile=100, diff_threshold=0.02, rtol=0.05 @@ -206,7 +206,7 @@ def test_standard_unwrap_histogram_mode(dist, dim, lut_workflow_psc_choppers) -> seed=37, ) - tofs = pl.compute(time_of_flight.DetectorTofData[SampleRun]) + tofs = pl.compute(time_of_flight.TofDetector[SampleRun]) _validate_result_histogram_mode( tofs=tofs, ref=ref, percentile=96, diff_threshold=0.4, rtol=0.05 @@ -225,7 +225,7 @@ def test_pulse_skipping_unwrap(dist, lut_workflow_pulse_skipping) -> None: error_threshold=0.1, ) - tofs = pl.compute(time_of_flight.DetectorTofData[SampleRun]) + tofs = pl.compute(time_of_flight.TofDetector[SampleRun]) _validate_result_events( tofs=tofs, ref=ref, percentile=100, diff_threshold=0.1, rtol=0.05 @@ -249,7 +249,7 @@ def test_pulse_skipping_unwrap_180_phase_shift() -> None: error_threshold=0.1, ) - tofs = pl.compute(time_of_flight.DetectorTofData[SampleRun]) + tofs = pl.compute(time_of_flight.TofDetector[SampleRun]) _validate_result_events( tofs=tofs, ref=ref, percentile=100, diff_threshold=0.1, rtol=0.05 @@ -269,7 +269,7 @@ def test_pulse_skipping_stride_offset_guess_gives_expected_result( error_threshold=0.1, ) - tofs = pl.compute(time_of_flight.DetectorTofData[SampleRun]) + tofs = pl.compute(time_of_flight.TofDetector[SampleRun]) _validate_result_events( tofs=tofs, ref=ref, percentile=100, diff_threshold=0.1, rtol=0.05 @@ -302,7 +302,7 @@ def test_pulse_skipping_unwrap_when_all_neutrons_arrive_after_second_pulse() -> error_threshold=0.1, ) - tofs = pl.compute(time_of_flight.DetectorTofData[SampleRun]) + tofs = pl.compute(time_of_flight.TofDetector[SampleRun]) _validate_result_events( tofs=tofs, ref=ref, percentile=100, diff_threshold=0.1, rtol=0.05 @@ -332,7 +332,7 @@ def test_pulse_skipping_unwrap_when_first_half_of_first_pulse_is_missing() -> No # Skip first pulse = half of the first frame a = mon.group('event_time_zero')['event_time_zero', 1:] a.bins.coords['event_time_zero'] = sc.bins_like(a, a.coords['event_time_zero']) - pl[DetectorData[SampleRun]] = a.bins.concat('event_time_zero') + pl[RawDetector[SampleRun]] = a.bins.concat('event_time_zero') pl[time_of_flight.DetectorLtotal[SampleRun]] = distance pl[time_of_flight.TimeOfFlightLookupTable] = lut_wf.compute( @@ -340,7 +340,7 @@ def test_pulse_skipping_unwrap_when_first_half_of_first_pulse_is_missing() -> No ) pl[time_of_flight.PulseStrideOffset] = 1 # Start the stride at the second pulse - tofs = pl.compute(time_of_flight.DetectorTofData[SampleRun]) + tofs = pl.compute(time_of_flight.TofDetector[SampleRun]) # Convert to wavelength graph = {**beamline_graph(scatter=False), **elastic_graph("tof")} @@ -373,7 +373,7 @@ def test_pulse_skipping_unwrap_when_first_half_of_first_pulse_is_missing() -> No # Make sure that we have not lost too many events (we lose some because they may be # given a NaN tof from the lookup). assert sc.isclose( - pl.compute(DetectorData[SampleRun]).data.nansum(), + pl.compute(RawDetector[SampleRun]).data.nansum(), tofs.data.nansum(), rtol=sc.scalar(1.0e-3), ) @@ -396,7 +396,7 @@ def test_pulse_skipping_stride_3() -> None: error_threshold=0.1, ) - tofs = pl.compute(time_of_flight.DetectorTofData[SampleRun]) + tofs = pl.compute(time_of_flight.TofDetector[SampleRun]) _validate_result_events( tofs=tofs, ref=ref, percentile=100, diff_threshold=0.1, rtol=0.05 @@ -412,7 +412,7 @@ def test_pulse_skipping_unwrap_histogram_mode(lut_workflow_pulse_skipping) -> No seed=9, ) - tofs = pl.compute(time_of_flight.DetectorTofData[SampleRun]) + tofs = pl.compute(time_of_flight.TofDetector[SampleRun]) _validate_result_histogram_mode( tofs=tofs, ref=ref, percentile=96, diff_threshold=0.4, rtol=0.05 @@ -430,13 +430,13 @@ def test_unwrap_int(dtype, lut_workflow_psc_choppers) -> None: error_threshold=0.1, ) - mon = pl.compute(DetectorData[SampleRun]).copy() + mon = pl.compute(RawDetector[SampleRun]).copy() mon.bins.coords["event_time_offset"] = mon.bins.coords["event_time_offset"].to( dtype=dtype, unit="ns" ) - pl[DetectorData[SampleRun]] = mon + pl[RawDetector[SampleRun]] = mon - tofs = pl.compute(time_of_flight.DetectorTofData[SampleRun]) + tofs = pl.compute(time_of_flight.TofDetector[SampleRun]) _validate_result_events( tofs=tofs, ref=ref, percentile=100, diff_threshold=0.02, rtol=0.05 diff --git a/tests/time_of_flight/wfm_test.py b/tests/time_of_flight/wfm_test.py index 04e196b6..c7c347c4 100644 --- a/tests/time_of_flight/wfm_test.py +++ b/tests/time_of_flight/wfm_test.py @@ -9,7 +9,7 @@ from scippneutron.conversion.graph.tof import elastic as elastic_graph from ess.reduce import time_of_flight -from ess.reduce.nexus.types import AnyRun, DetectorData, SampleRun +from ess.reduce.nexus.types import AnyRun, RawDetector, SampleRun from ess.reduce.time_of_flight import GenericTofWorkflow, TofLookupTableWorkflow, fakes sl = pytest.importorskip("sciline") @@ -130,7 +130,7 @@ def setup_workflow( error_threshold: float = 0.1, ) -> sl.Pipeline: pl = GenericTofWorkflow(run_types=[SampleRun], monitor_types=[]) - pl[DetectorData[SampleRun]] = raw_data + pl[RawDetector[SampleRun]] = raw_data pl[time_of_flight.DetectorLtotal[SampleRun]] = ltotal lut_wf = lut_workflow.copy() @@ -194,7 +194,7 @@ def test_dream_wfm( raw_data=raw, ltotal=ltotal, lut_workflow=lut_workflow_dream_choppers ) - tofs = pl.compute(time_of_flight.DetectorTofData[SampleRun]) + tofs = pl.compute(time_of_flight.TofDetector[SampleRun]) # Convert to wavelength graph = {**beamline_graph(scatter=False), **elastic_graph("tof")} @@ -281,7 +281,7 @@ def test_dream_wfm_with_subframe_time_overlap( error_threshold=0.01, ) - tofs = pl.compute(time_of_flight.DetectorTofData[SampleRun]) + tofs = pl.compute(time_of_flight.TofDetector[SampleRun]) # Convert to wavelength graph = {**beamline_graph(scatter=False), **elastic_graph("tof")} @@ -464,7 +464,7 @@ def test_v20_compute_wavelengths_from_wfm( raw_data=raw, ltotal=ltotal, lut_workflow=lut_workflow_v20_choppers ) - tofs = pl.compute(time_of_flight.DetectorTofData[SampleRun]) + tofs = pl.compute(time_of_flight.TofDetector[SampleRun]) # Convert to wavelength graph = {**beamline_graph(scatter=False), **elastic_graph("tof")} diff --git a/tests/time_of_flight/workflow_test.py b/tests/time_of_flight/workflow_test.py index 4187db8a..2f6ad0aa 100644 --- a/tests/time_of_flight/workflow_test.py +++ b/tests/time_of_flight/workflow_test.py @@ -10,10 +10,11 @@ from ess.reduce import time_of_flight from ess.reduce.nexus.types import ( AnyRun, - CalibratedBeamline, - DetectorData, DiskChoppers, + EmptyDetector, NeXusData, + Position, + RawDetector, SampleRun, ) from ess.reduce.time_of_flight import ( @@ -77,17 +78,20 @@ def test_GenericTofWorkflow_with_tof_lut_from_tof_simulation( calibrated_beamline: sc.DataArray, nexus_data: sc.DataArray ): wf = GenericTofWorkflow(run_types=[SampleRun], monitor_types=[]) - wf[CalibratedBeamline[SampleRun]] = calibrated_beamline + wf[EmptyDetector[SampleRun]] = calibrated_beamline wf[NeXusData[snx.NXdetector, SampleRun]] = nexus_data + # Unused because calibrated_beamline contains Ltotal but needed by wf structure + wf[Position[snx.NXsample, SampleRun]] = sc.vector([1e10, 1e10, 1e10], unit='m') + wf[Position[snx.NXsource, SampleRun]] = sc.vector([1e10, 1e10, 1e10], unit='m') # Should be able to compute DetectorData without chopper and simulation params # This contains event_time_offset (time-of-arrival). - _ = wf.compute(DetectorData[SampleRun]) + _ = wf.compute(RawDetector[SampleRun]) # By default, the workflow tries to load the LUT from file with pytest.raises(sciline.UnsatisfiedRequirement): _ = wf.compute(time_of_flight.TimeOfFlightLookupTable) with pytest.raises(sciline.UnsatisfiedRequirement): - _ = wf.compute(time_of_flight.DetectorTofData[SampleRun]) + _ = wf.compute(time_of_flight.TofDetector[SampleRun]) lut_wf = TofLookupTableWorkflow() lut_wf[DiskChoppers[AnyRun]] = fakes.psc_choppers() @@ -101,7 +105,7 @@ def test_GenericTofWorkflow_with_tof_lut_from_tof_simulation( wf[time_of_flight.TimeOfFlightLookupTable] = table # Should now be able to compute DetectorData with chopper and simulation params - detector = wf.compute(time_of_flight.DetectorTofData[SampleRun]) + detector = wf.compute(time_of_flight.TofDetector[SampleRun]) assert 'tof' in detector.bins.coords @@ -122,14 +126,17 @@ def test_GenericTofWorkflow_with_tof_lut_from_file( lut.save_hdf5(filename=tmp_path / "lut.h5") wf = GenericTofWorkflow(run_types=[SampleRun], monitor_types=[]) - wf[CalibratedBeamline[SampleRun]] = calibrated_beamline + wf[EmptyDetector[SampleRun]] = calibrated_beamline wf[NeXusData[snx.NXdetector, SampleRun]] = nexus_data wf[time_of_flight.TimeOfFlightLookupTableFilename] = ( tmp_path / "lut.h5" ).as_posix() + # Unused because calibrated_beamline contains Ltotal but needed by wf structure + wf[Position[snx.NXsample, SampleRun]] = sc.vector([1e10, 1e10, 1e10], unit='m') + wf[Position[snx.NXsource, SampleRun]] = sc.vector([1e10, 1e10, 1e10], unit='m') loaded_lut = wf.compute(time_of_flight.TimeOfFlightLookupTable) assert_identical(lut, loaded_lut) - detector = wf.compute(time_of_flight.DetectorTofData[SampleRun]) + detector = wf.compute(time_of_flight.TofDetector[SampleRun]) assert 'tof' in detector.bins.coords