Skip to content

Commit c09c0e2

Browse files
Merge pull request #214 from scipp/isis-histogram-files
Support ISIS histogram files
2 parents e385213 + 3ffad5a commit c09c0e2

File tree

3 files changed

+80
-7
lines changed

3 files changed

+80
-7
lines changed

src/ess/isissans/__init__.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
import importlib.metadata
55

66
from . import general, io, sans2d, zoom
7-
from .general import DetectorBankOffset, MonitorOffset, SampleOffset, default_parameters
7+
from .general import (
8+
DetectorBankOffset,
9+
MonitorOffset,
10+
MonitorSpectrumNumber,
11+
SampleOffset,
12+
default_parameters,
13+
)
814
from .io import CalibrationFilename
915
from .visualization import plot_flat_detector_xy
1016

@@ -21,6 +27,7 @@
2127
'CalibrationFilename',
2228
'DetectorBankOffset',
2329
'MonitorOffset',
30+
'MonitorSpectrumNumber',
2431
'SampleOffset',
2532
'default_parameters',
2633
'io',

src/ess/isissans/general.py

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
Providers for the ISIS instruments.
55
"""
66

7-
from typing import NewType
7+
from dataclasses import dataclass
8+
from typing import Generic, NewType
89

910
import sciline
1011
import scipp as sc
@@ -45,6 +46,17 @@ class MonitorOffset(sciline.Scope[MonitorType, sc.Variable], sc.Variable):
4546
"""
4647

4748

49+
@dataclass
50+
class MonitorSpectrumNumber(Generic[MonitorType]):
51+
"""
52+
Spectrum number for monitor data.
53+
54+
This is used to identify the monitor in ISIS histogram data files.
55+
"""
56+
57+
value: int
58+
59+
4860
DetectorBankOffset = NewType('DetectorBankOffset', sc.Variable)
4961
SampleOffset = NewType('SampleOffset', sc.Variable)
5062

@@ -61,6 +73,10 @@ def default_parameters() -> dict:
6173
SampleOffset: SampleOffset(sc.vector([0, 0, 0], unit='m')),
6274
NonBackgroundWavelengthRange: None,
6375
Period: None,
76+
# Not used for event files, setting default so the workflow works. If histogram
77+
# data is used, the user should set this to the correct value.
78+
MonitorSpectrumNumber[Incident]: MonitorSpectrumNumber[Incident](-1),
79+
MonitorSpectrumNumber[Transmission]: MonitorSpectrumNumber[Transmission](-1),
6480
}
6581

6682

@@ -132,12 +148,43 @@ def get_calibrated_isis_detector(
132148

133149

134150
def get_monitor_data(
135-
dg: LoadedFileContents[RunType], nexus_name: NeXusMonitorName[MonitorType]
151+
dg: LoadedFileContents[RunType],
152+
nexus_name: NeXusMonitorName[MonitorType],
153+
spectrum_number: MonitorSpectrumNumber[MonitorType],
136154
) -> NeXusComponent[MonitorType, RunType]:
155+
"""
156+
Extract monitor data that was loaded together with detector data.
157+
158+
If the raw file is histogram data, Mantid stores this as a Workspace2D, where some
159+
or all spectra correspond to monitors.
160+
161+
Parameters
162+
----------
163+
dg:
164+
Data loaded with Mantid and converted to Scipp.
165+
nexus_name:
166+
Name of the monitor in the NeXus file, e.g. 'incident_monitor' or
167+
'transmission_monitor'. Used when raw data is an EventWorkspace, where
168+
monitors are stored in a group with this name.
169+
spectrum_number:
170+
Spectrum number of the monitor in the NeXus file, e.g., 3 for incident monitor
171+
or 4 for transmission monitor. This is used when the raw data is a
172+
Workspace2D, where the monitor data is stored in a spectrum with this number.
173+
174+
Returns
175+
-------
176+
:
177+
Monitor data extracted from the loaded file.
178+
"""
137179
# The generic NeXus workflow will try to extract 'data' from this, which is exactly
138180
# what we also have in the Mantid data. We use the generic workflow since it also
139181
# applies offsets, etc.
140-
monitor = dg['monitors'][nexus_name]['data']
182+
if 'monitors' in dg:
183+
# From EventWorkspace
184+
monitor = dg['monitors'][nexus_name]['data']
185+
else:
186+
# From Workspace2D
187+
monitor = sc.values(dg["data"]["spectrum", sc.index(spectrum_number.value)])
141188
return NeXusComponent[MonitorType, RunType](
142189
sc.DataGroup(data=monitor, position=monitor.coords['position'])
143190
)

src/ess/isissans/mantidio.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
File loading functions for ISIS data using Mantid.
55
"""
66

7+
import threading
78
from typing import NewType, NoReturn
89

910
import sciline
@@ -99,12 +100,28 @@ def from_data_workspace(
99100

100101

101102
def load_run(filename: Filename[RunType], period: Period) -> DataWorkspace[RunType]:
102-
loaded = _mantid_simpleapi.Load(
103-
Filename=str(filename), LoadMonitors=True, StoreInADS=False
104-
)
103+
# Loading many small files with Mantid is, for some reason, very slow when using
104+
# the default number of threads in the Dask threaded scheduler (1 thread worked
105+
# best, 2 is a bit slower but still fast). We can either limit that thread count,
106+
# or add a lock here, which is more specific.
107+
with load_run.lock:
108+
try:
109+
loaded = _mantid_simpleapi.Load(
110+
Filename=str(filename), LoadMonitors=True, StoreInADS=False
111+
)
112+
except TypeError:
113+
# Not loaded using LoadEventNexus, so LoadMonitor option is not available.
114+
loaded = _mantid_simpleapi.Load(Filename=str(filename), StoreInADS=False)
105115
if isinstance(loaded, _mantid_api.Workspace):
106116
# A single workspace
107117
data_ws = loaded
118+
if isinstance(data_ws, _mantid_api.WorkspaceGroup):
119+
if period is None:
120+
raise ValueError(
121+
f'Needs {Period} to be set to know what '
122+
'section of the event data to load'
123+
)
124+
data_ws = data_ws.getItem(period)
108125
else:
109126
# Separate data and monitor workspaces
110127
data_ws = loaded.OutputWorkspace
@@ -121,6 +138,8 @@ def load_run(filename: Filename[RunType], period: Period) -> DataWorkspace[RunTy
121138
return DataWorkspace[RunType](data_ws)
122139

123140

141+
load_run.lock = threading.Lock()
142+
124143
providers = (
125144
from_data_workspace,
126145
load_calibration,

0 commit comments

Comments
 (0)