NMX Reduction Workflow#
NMX does not expect users to use python interface directly. This documentation is mostly for instrument data scientists or instrument scientists.
TL;DR#
[1]:
from ess.nmx.executables import reduction
from ess.nmx.data import get_small_nmx_nexus
from ess.nmx.configurations import (
ReductionConfig,
OutputConfig,
InputConfig,
WorkflowConfig,
TimeBinCoordinate,
)
# Build Configuration
config = ReductionConfig(
inputs=InputConfig(
input_file=[get_small_nmx_nexus().as_posix()],
detector_ids=[0, 1, 2],
),
output=OutputConfig(
output_file="scipp_output.hdf", skip_file_output=False, overwrite=True
),
workflow=WorkflowConfig(
time_bin_coordinate=TimeBinCoordinate.time_of_flight,
nbins=10,
tof_simulation_num_neutrons=1_000_000,
tof_simulation_min_wavelength=1.8,
tof_simulation_max_wavelength=3.6,
tof_simulation_seed=42,
),
)
# Run Reduction
reduction(config=config, display=display)
Downloading file 'small_nmx_nexus.hdf.zip' from 'https://public.esss.dk/groups/scipp/ess/nmx/1/small_nmx_nexus.hdf.zip' to '/home/runner/.cache/ess/nmx'.
Unzipping contents of '/home/runner/.cache/ess/nmx/small_nmx_nexus.hdf.zip' to '/home/runner/.cache/ess/nmx/small_nmx_nexus.hdf.zip.unzip'
'Input file: /home/runner/.cache/ess/nmx/small_nmx_nexus.hdf.zip.unzip/small_nmx_nexus.hdf'
'Output file: /home/runner/work/essnmx/essnmx/docs/user-guide/scipp_output.hdf'
Downloading file 'ess/ess.h5' from 'https://github.com/scipp/tof-sources/raw/refs/heads/main/1/ess/ess.h5' to '/home/runner/.cache/tof'.
/home/runner/work/essnmx/essnmx/.tox/docs/lib/python3.11/site-packages/ess/nmx/workflows.py:170: RuntimeWarning: No crystal rotation found in the Nexus file under 'entry/sample/crystal_rotation'. Returning zero rotation.
warnings.warn(
[1]:
- scippDataGroup(y_pixel_offset: 1280,
 x_pixel_offset: 1280,
 tof: 10)- detector_panel_0scippDataArray(y_pixel_offset: 1280,
 x_pixel_offset: 1280,
 tof: 10)float32counts0.0, 0.0, ..., 0.0, 0.0 - detector_panel_1scippDataArray(y_pixel_offset: 1280,
 x_pixel_offset: 1280,
 tof: 10)float32counts0.0, 0.0, ..., 0.0, 0.0 - detector_panel_2scippDataArray(y_pixel_offset: 1280,
 x_pixel_offset: 1280,
 tof: 10)float32counts0.0, 0.0, ..., 0.0, 0.0
- scippDataGroup()
- detector_panel_0essNMXDetectorMetadata()NMXDetectorMetadata(detector_name='detector_panel_0', x_pixel_size=<scipp.Variab...
- detector_panel_1essNMXDetectorMetadata()NMXDetectorMetadata(detector_name='detector_panel_1', x_pixel_size=<scipp.Variab...
- detector_panel_2essNMXDetectorMetadata()NMXDetectorMetadata(detector_name='detector_panel_2', x_pixel_size=<scipp.Variab...
- sampleessNMXSampleMetadata()NMXSampleMetadata(crystal_rotation=<scipp.Variable> () vector3 [de...
- sourceessNMXSourceMetadata()NMXSourceMetadata(source_position=<scipp.Variable> () vector3 [m...
- monitoressNMXMonitorMetadata()NMXMonitorMetadata(monitor_histogram=<scipp.DataArray> Dimensions: Sizes[tof:10,...
- lookup_tableessTimeOfFlightLookupTable()TimeOfFlightLookupTable(array=<scipp.DataArray> Dimensions: Sizes[distance:203, ...
Configuration#
essnmx provides a command line data reduction tool. The essnmx-reduce interface will reduce nexus file and save the results into NXlauetof(not exactly but very close) format for dials.
For conveniences and safety, all configuration options are wrapped in a nested pydantic model. Here is a python API you can use to build the configuration and turn it into command line arguments.
The configuration object is a pydantic model, and it thus enforces strict checks on the types of the arguments.
[2]:
from ess.nmx.configurations import (
ReductionConfig,
OutputConfig,
InputConfig,
WorkflowConfig,
TimeBinCoordinate,
to_command_arguments,
)
config = ReductionConfig(
inputs=InputConfig(
input_file=["PATH_TO_THE_NEXUS_FILE.hdf"],
detector_ids=[0, 1, 2], # Detector index to be reduced in alphabetical order.
),
output=OutputConfig(output_file="scipp_output.hdf", skip_file_output=True),
workflow=WorkflowConfig(
time_bin_coordinate=TimeBinCoordinate.time_of_flight,
nbins=10,
tof_simulation_num_neutrons=1_000_000,
tof_simulation_min_wavelength=1.8,
tof_simulation_max_wavelength=3.6,
tof_simulation_seed=42,
),
)
display(config)
print(to_command_arguments(config=config, one_line=True))
ReductionConfig(inputs=InputConfig(input_file=['PATH_TO_THE_NEXUS_FILE.hdf'], swmr=False, detector_ids=[0, 1, 2], iter_chunk=False, chunk_size_pulse=0, chunk_size_events=0), workflow=WorkflowConfig(time_bin_coordinate=<TimeBinCoordinate.time_of_flight: 'time_of_flight'>, nbins=10, min_time_bin=None, max_time_bin=None, time_bin_unit=<TimeBinUnit.ms: 'ms'>, tof_lookup_table_file_path=None, tof_simulation_num_neutrons=1000000, tof_simulation_min_wavelength=1.8, tof_simulation_max_wavelength=3.6, tof_simulation_min_ltotal=150.0, tof_simulation_max_ltotal=170.0, tof_simulation_seed=42), output=OutputConfig(verbose=False, skip_file_output=True, output_file='scipp_output.hdf', overwrite=False, compression=<Compression.BITSHUFFLE_LZ4: 'BITSHUFFLE_LZ4'>))
--input-file PATH_TO_THE_NEXUS_FILE.hdf \
--detector-ids 0 1 2 \
--chunk-size-pulse 0 \
--chunk-size-events 0 \
--time-bin-coordinate time_of_flight \
--nbins 10 \
--time-bin-unit ms \
--tof-simulation-num-neutrons 1000000 \
--tof-simulation-min-wavelength 1.8 \
--tof-simulation-max-wavelength 3.6 \
--tof-simulation-min-ltotal 150.0 \
--tof-simulation-max-ltotal 170.0 \
--tof-simulation-seed 42 \
--skip-file-output \
--output-file scipp_output.hdf \
--compression BITSHUFFLE_LZ4
Reduce Nexus File(s)#
OutputConfig has an option called skip_file_output if you want to reduce the file and use it only on the memory. Then you can use save_results function to explicitly save the results.
[3]:
from ess.nmx.executables import reduction
from ess.nmx.data import get_small_nmx_nexus
config = ReductionConfig(
inputs=InputConfig(input_file=[get_small_nmx_nexus().as_posix()]),
output=OutputConfig(skip_file_output=True),
)
results = reduction(config=config, display=display)
results
'Input file: /home/runner/.cache/ess/nmx/small_nmx_nexus.hdf.zip.unzip/small_nmx_nexus.hdf'
'Output file: /home/runner/work/essnmx/essnmx/docs/user-guide/scipp_output.h5'
/home/runner/work/essnmx/essnmx/.tox/docs/lib/python3.11/site-packages/ess/nmx/workflows.py:170: RuntimeWarning: No crystal rotation found in the Nexus file under 'entry/sample/crystal_rotation'. Returning zero rotation.
warnings.warn(
[3]:
- scippDataGroup(y_pixel_offset: 1280,
 x_pixel_offset: 1280,
 tof: 50)- detector_panel_0scippDataArray(y_pixel_offset: 1280,
 x_pixel_offset: 1280,
 tof: 50)float32counts0.0, 0.0, ..., 0.0, 0.0 - detector_panel_1scippDataArray(y_pixel_offset: 1280,
 x_pixel_offset: 1280,
 tof: 50)float32counts0.0, 0.0, ..., 0.0, 0.0 - detector_panel_2scippDataArray(y_pixel_offset: 1280,
 x_pixel_offset: 1280,
 tof: 50)float32counts0.0, 0.0, ..., 0.0, 0.0
- scippDataGroup()
- detector_panel_0essNMXDetectorMetadata()NMXDetectorMetadata(detector_name='detector_panel_0', x_pixel_size=<scipp.Variab...
- detector_panel_1essNMXDetectorMetadata()NMXDetectorMetadata(detector_name='detector_panel_1', x_pixel_size=<scipp.Variab...
- detector_panel_2essNMXDetectorMetadata()NMXDetectorMetadata(detector_name='detector_panel_2', x_pixel_size=<scipp.Variab...
- sampleessNMXSampleMetadata()NMXSampleMetadata(crystal_rotation=<scipp.Variable> () vector3 [de...
- sourceessNMXSourceMetadata()NMXSourceMetadata(source_position=<scipp.Variable> () vector3 [m...
- monitoressNMXMonitorMetadata()NMXMonitorMetadata(monitor_histogram=<scipp.DataArray> Dimensions: Sizes[tof:50,...
- lookup_tableessTimeOfFlightLookupTable()TimeOfFlightLookupTable(array=<scipp.DataArray> Dimensions: Sizes[distance:203, ...
[4]:
from ess.nmx.executables import save_results
output_config = OutputConfig(output_file="scipp_output.hdf", overwrite=True)
save_results(results=results, output_config=output_config)