diff --git a/docs/examples/zoom.ipynb b/docs/examples/zoom.ipynb index 9e466c03..80d021e7 100644 --- a/docs/examples/zoom.ipynb +++ b/docs/examples/zoom.ipynb @@ -22,7 +22,7 @@ "There are a few things that are not yet handled:\n", "\n", "- TOF or wavelength masks\n", - "- Position corrections from user file" + "- Position corrections from user file (not automatically, have manual sample and detector bank offsets)" ] }, { @@ -69,6 +69,8 @@ " sans.isis.CalibrationFilename: '192tubeCalibration_11-02-2019_r5_10lines.nxs',\n", " sans.isis.Filename[sans.types.SampleRun]: 'ZOOM00034786.nxs',\n", " sans.isis.Filename[sans.types.EmptyBeamRun]: 'ZOOM00034787.nxs',\n", + " sans.isis.SampleOffset: sc.vector([0.0, 0.0, 0.11], unit='m'),\n", + " sans.isis.DetectorBankOffset: sc.vector([0.0, 0.0, 0.5], unit='m'),\n", "}\n", "masks = [\n", " 'andru_test.xml',\n", @@ -270,7 +272,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.10.12" } }, "nbformat": 4, diff --git a/src/esssans/isis/__init__.py b/src/esssans/isis/__init__.py index 3ec01ca4..fd868c9d 100644 --- a/src/esssans/isis/__init__.py +++ b/src/esssans/isis/__init__.py @@ -9,6 +9,11 @@ sans2d_tube_detector_pixel_shape, ) from . import io, masking +from .components import ( + DetectorBankOffset, + SampleOffset, + apply_component_user_offsets_to_raw_data, +) from .io import CalibrationFilename, DataFolder, Filename, PixelMaskFilename from .masking import PixelMask from .visualization import plot_flat_detector_xy @@ -19,6 +24,7 @@ get_monitor, lab_frame_transform, sans2d_tube_detector_pixel_shape, + apply_component_user_offsets_to_raw_data, ) + io.providers + masking.providers @@ -32,11 +38,14 @@ __all__ = [ 'CalibrationFilename', 'DataFolder', + 'DetectorBankOffset', 'Filename', + 'apply_component_user_offsets_to_raw_data', 'io', 'masking', 'PixelMask', 'PixelMaskFilename', 'providers', + 'SampleOffset', 'plot_flat_detector_xy', ] diff --git a/src/esssans/isis/components.py b/src/esssans/isis/components.py new file mode 100644 index 00000000..dfcd5277 --- /dev/null +++ b/src/esssans/isis/components.py @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright (c) 2024 Scipp contributors (https://github.com/scipp) +from typing import NewType + +import sciline +import scipp as sc + +from ..types import RawData, RunType + + +class RawDataWithComponentUserOffsets( + sciline.Scope[RunType, sc.DataArray], sc.DataArray +): + """Raw data with applied user configuration for component positions.""" + + +SampleOffset = NewType('SampleOffset', sc.Variable) +DetectorBankOffset = NewType('DetectorBankOffset', sc.Variable) + + +def apply_component_user_offsets_to_raw_data( + data: RawData[RunType], + sample_offset: SampleOffset, + detector_bank_offset: DetectorBankOffset, +) -> RawDataWithComponentUserOffsets[RunType]: + """Apply user configuration to raw data. + + Parameters + ---------- + data: + Raw data. + sample_offset: + Sample offset. + detector_bank_offset: + Detector bank offset. + """ + data = data.copy(deep=False) + sample_pos = data.coords['sample_position'] + data.coords['sample_position'] = sample_pos + sample_offset.to( + unit=sample_pos.unit, copy=False + ) + pos = data.coords['position'] + data.coords['position'] = pos + detector_bank_offset.to(unit=pos.unit, copy=False) + return RawDataWithComponentUserOffsets[RunType](data) diff --git a/src/esssans/isis/masking.py b/src/esssans/isis/masking.py index 96c49cec..2d4f27ab 100644 --- a/src/esssans/isis/masking.py +++ b/src/esssans/isis/masking.py @@ -7,6 +7,7 @@ import scipp as sc from ..types import MaskedData, RawData, RunType, SampleRun +from .components import RawDataWithComponentUserOffsets from .io import MaskedDetectorIDs PixelMask = NewType('PixelMask', sc.Variable) @@ -18,7 +19,7 @@ def to_pixel_mask(data: RawData[SampleRun], masked: MaskedDetectorIDs) -> PixelM Parameters ---------- data: - Raw data. + Raw data, defining the detector IDs. masked: The masked detector IDs. """ @@ -29,14 +30,19 @@ def to_pixel_mask(data: RawData[SampleRun], masked: MaskedDetectorIDs) -> PixelM def apply_pixel_masks( - data: RawData[RunType], masks: sciline.Series[str, PixelMask] + data: RawDataWithComponentUserOffsets[RunType], + masks: sciline.Series[str, PixelMask], ) -> MaskedData[RunType]: """Apply pixel-specific masks to raw data. + This depends on the configured raw data (which has been configured with component + positions) since in principle we might apply pixel masks based on the component + positions. Currently the only masks are based on detector IDs. + Parameters ---------- data: - Raw data. + Raw data with configured component positions. masks: A series of masks. """