essreduce 25.11.1__py3-none-any.whl → 25.11.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ess/reduce/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  import importlib.metadata
6
6
 
7
- from . import nexus, time_of_flight, uncertainty
7
+ from . import nexus, normalization, time_of_flight, uncertainty
8
8
 
9
9
  try:
10
10
  __version__ = importlib.metadata.version("essreduce")
@@ -13,4 +13,4 @@ except importlib.metadata.PackageNotFoundError:
13
13
 
14
14
  del importlib
15
15
 
16
- __all__ = ["nexus", "time_of_flight", "uncertainty"]
16
+ __all__ = ["nexus", "normalization", "time_of_flight", "uncertainty"]
@@ -20,6 +20,7 @@ from ._nexus_loader import (
20
20
  load_all_components,
21
21
  load_component,
22
22
  load_data,
23
+ load_from_path,
23
24
  open_component_group,
24
25
  open_nexus_file,
25
26
  )
@@ -33,6 +34,7 @@ __all__ = [
33
34
  'load_all_components',
34
35
  'load_component',
35
36
  'load_data',
37
+ 'load_from_path',
36
38
  'open_component_group',
37
39
  'open_nexus_file',
38
40
  'types',
@@ -8,7 +8,7 @@ from collections.abc import Generator, Mapping
8
8
  from contextlib import AbstractContextManager, contextmanager, nullcontext
9
9
  from dataclasses import dataclass
10
10
  from math import prod
11
- from typing import TypeVar, cast
11
+ from typing import Any, TypeVar, cast
12
12
 
13
13
  import scipp as sc
14
14
  import scippnexus as snx
@@ -42,6 +42,31 @@ class NoLockingIfNeededType:
42
42
  NoLockingIfNeeded = NoLockingIfNeededType()
43
43
 
44
44
 
45
+ def load_from_path(
46
+ location: NeXusLocationSpec,
47
+ definitions: Mapping | NoNewDefinitionsType = NoNewDefinitions,
48
+ ) -> Any:
49
+ """Load a field or group from a NeXus file given its location.
50
+
51
+ Parameters
52
+ ----------
53
+ location:
54
+ Location of the field within the NeXus file (filename, entry name, selection).
55
+ definitions:
56
+ Application definitions to use for the file.
57
+
58
+ Returns
59
+ -------
60
+ :
61
+ The loaded field (as a variable, data array, or raw python object) or group
62
+ (as a data group).
63
+ """
64
+ with open_nexus_file(location.filename, definitions=definitions) as f:
65
+ entry = _unique_child_group(f, snx.NXentry, location.entry_name)
66
+ item = entry[location.component_name]
67
+ return item[location.selection]
68
+
69
+
45
70
  def load_component(
46
71
  location: NeXusLocationSpec,
47
72
  *,
@@ -691,16 +691,12 @@ def LoadMonitorWorkflow(
691
691
 
692
692
 
693
693
  def LoadDetectorWorkflow(
694
- *,
695
- run_types: Iterable[sciline.typing.Key],
696
- monitor_types: Iterable[sciline.typing.Key],
694
+ *, run_types: Iterable[sciline.typing.Key]
697
695
  ) -> sciline.Pipeline:
698
696
  """Generic workflow for loading detector data from a NeXus file."""
699
697
  wf = sciline.Pipeline(
700
698
  (*_common_providers, *_detector_providers),
701
- constraints=_gather_constraints(
702
- run_types=run_types, monitor_types=monitor_types
703
- ),
699
+ constraints=_gather_constraints(run_types=run_types, monitor_types=[]),
704
700
  )
705
701
  wf[DetectorBankSizes] = DetectorBankSizes({})
706
702
  wf[PreopenNeXusFile] = PreopenNeXusFile(False)
@@ -0,0 +1,215 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+ # Copyright (c) 2025 Scipp contributors (https://github.com/scipp)
3
+ """Normalization routines for neutron data reduction."""
4
+
5
+ import functools
6
+
7
+ import scipp as sc
8
+
9
+ from .uncertainty import UncertaintyBroadcastMode, broadcast_uncertainties
10
+
11
+
12
+ def normalize_by_monitor_histogram(
13
+ detector: sc.DataArray,
14
+ *,
15
+ monitor: sc.DataArray,
16
+ uncertainty_broadcast_mode: UncertaintyBroadcastMode,
17
+ ) -> sc.DataArray:
18
+ """Normalize detector data by a normalized histogrammed monitor.
19
+
20
+ This normalization accounts for both the (wavelength) profile of the incident beam
21
+ and the integrated neutron flux, meaning measurement duration and source strength.
22
+
23
+ - For *event* detectors, the monitor values are mapped to the detector
24
+ using :func:`scipp.lookup`. That is, for detector event :math:`d_i`,
25
+ :math:`m_i` is the monitor bin value at the same coordinate.
26
+ - For *histogram* detectors, the monitor is rebinned using to the detector
27
+ binning using :func:`scipp.rebin`. Thus, detector value :math:`d_i` and
28
+ monitor value :math:`m_i` correspond to the same bin.
29
+
30
+ In both cases, let :math:`x_i` be the lower bound of monitor bin :math:`i`
31
+ and let :math:`\\Delta x_i = x_{i+1} - x_i` be the width of that bin.
32
+
33
+ The detector is normalized according to
34
+
35
+ .. math::
36
+
37
+ d_i^\\text{Norm} = \\frac{d_i}{m_i} \\Delta x_i
38
+
39
+ Parameters
40
+ ----------
41
+ detector:
42
+ Input detector data.
43
+ Must have a coordinate named ``monitor.dim``, that is, the single
44
+ dimension name of the **monitor**.
45
+ monitor:
46
+ A histogrammed monitor.
47
+ Must be one-dimensional and have a dimension coordinate, typically "wavelength".
48
+ uncertainty_broadcast_mode:
49
+ Choose how uncertainties of the monitor are broadcast to the sample data.
50
+
51
+ Returns
52
+ -------
53
+ :
54
+ ``detector`` normalized by ``monitor``.
55
+ If the monitor has masks or contains non-finite values, the output has a mask
56
+ called '_monitor_mask' constructed from the monitor masks and non-finite values.
57
+
58
+ See also
59
+ --------
60
+ normalize_by_monitor_integrated:
61
+ Normalize by an integrated monitor.
62
+ """
63
+ _check_monitor_range_contains_detector(monitor=monitor, detector=detector)
64
+
65
+ dim = monitor.dim
66
+
67
+ if detector.bins is None:
68
+ monitor = monitor.rebin({dim: detector.coords[dim]})
69
+ detector = _mask_detector_for_norm(detector=detector, monitor=monitor)
70
+ coord = monitor.coords[dim]
71
+ delta_w = sc.DataArray(coord[1:] - coord[:-1], masks=monitor.masks)
72
+ norm = broadcast_uncertainties(
73
+ monitor / delta_w, prototype=detector, mode=uncertainty_broadcast_mode
74
+ )
75
+
76
+ if detector.bins is None:
77
+ return detector / norm.rebin({dim: detector.coords[dim]})
78
+ return detector.bins / sc.lookup(norm, dim=dim)
79
+
80
+
81
+ def normalize_by_monitor_integrated(
82
+ detector: sc.DataArray,
83
+ *,
84
+ monitor: sc.DataArray,
85
+ uncertainty_broadcast_mode: UncertaintyBroadcastMode,
86
+ ) -> sc.DataArray:
87
+ """Normalize detector data by an integrated monitor.
88
+
89
+ This normalization accounts only for the integrated neutron flux,
90
+ meaning measurement duration and source strength.
91
+ It does *not* account for the (wavelength) profile of the incident beam.
92
+ For that, see :func:`normalize_by_monitor_histogram`.
93
+
94
+ Let :math:`d_i` be a detector event or the counts in a detector bin.
95
+ The normalized detector is
96
+
97
+ .. math::
98
+
99
+ d_i^\\text{Norm} = \\frac{d_i}{\\sum_j\\, m_j}
100
+
101
+ where :math:`m_j` is the monitor counts in bin :math:`j`.
102
+ Note that this is not a true integral but only a sum over monitor events.
103
+
104
+ The result depends on the range of the monitor but not its
105
+ binning within that range.
106
+
107
+ Parameters
108
+ ----------
109
+ detector:
110
+ Input detector data.
111
+ monitor:
112
+ A histogrammed monitor.
113
+ Must be one-dimensional and have a dimension coordinate, typically "wavelength".
114
+ uncertainty_broadcast_mode:
115
+ Choose how uncertainties of the monitor are broadcast to the sample data.
116
+
117
+ Returns
118
+ -------
119
+ :
120
+ `detector` normalized by a monitor.
121
+ If the monitor has masks or contains non-finite values, the output has a mask
122
+ called '_monitor_mask' constructed from the monitor masks and non-finite values.
123
+
124
+ See also
125
+ --------
126
+ normalize_by_monitor_histogram:
127
+ Normalize by a monitor histogram.
128
+ """
129
+ _check_monitor_range_contains_detector(monitor=monitor, detector=detector)
130
+ detector = _mask_detector_for_norm(detector=detector, monitor=monitor)
131
+ norm = monitor.nansum().data
132
+ norm = broadcast_uncertainties(
133
+ norm, prototype=detector, mode=uncertainty_broadcast_mode
134
+ )
135
+ return detector / norm
136
+
137
+
138
+ def _check_monitor_range_contains_detector(
139
+ *, monitor: sc.DataArray, detector: sc.DataArray
140
+ ) -> None:
141
+ dim = monitor.dim
142
+ if not monitor.coords.is_edges(dim):
143
+ raise sc.CoordError(
144
+ f"Monitor coordinate '{dim}' must be bin-edges to integrate the monitor."
145
+ )
146
+
147
+ # Prefer a bin coord over an event coord because this makes the behavior for binned
148
+ # and histogrammed data consistent. If we used an event coord, we might allow a
149
+ # monitor range that is less than the detector bins which is fine for the events,
150
+ # but would be wrong if the detector was subsequently histogrammed.
151
+ if (det_coord := detector.coords.get(dim)) is not None:
152
+ lo = det_coord[dim, :-1].nanmin()
153
+ hi = det_coord[dim, 1:].nanmax()
154
+ elif (det_coord := detector.bins.coords.get(dim)) is not None:
155
+ lo = det_coord.nanmin()
156
+ hi = det_coord.nanmax()
157
+ else:
158
+ raise sc.CoordError(
159
+ f"Missing '{dim}' coordinate in detector for monitor normalization."
160
+ )
161
+
162
+ if monitor.coords[dim].min() > lo or monitor.coords[dim].max() < hi:
163
+ raise ValueError(
164
+ f"Cannot normalize by monitor: The {dim} range of the monitor "
165
+ f"({monitor.coords[dim].min():c} to {monitor.coords[dim].max():c}) "
166
+ f"is smaller than the range of the detector ({lo:c} to {hi:c})."
167
+ )
168
+
169
+
170
+ def _mask_detector_for_norm(
171
+ *, detector: sc.DataArray, monitor: sc.DataArray
172
+ ) -> sc.DataArray:
173
+ """Mask the detector where the monitor is masked.
174
+
175
+ For performance, this applies the monitor mask to the detector bins.
176
+ This can lead to masking more events than strictly necessary if we
177
+ used an event mask.
178
+ """
179
+ dim = monitor.dim
180
+
181
+ if (monitor_mask := _monitor_mask(monitor)) is None:
182
+ return detector
183
+
184
+ if (detector_coord := detector.coords.get(monitor.dim)) is not None:
185
+ # Apply the mask to the bins or a dense detector.
186
+ # Use rebin to reshape the mask to the detector.
187
+ mask = sc.DataArray(monitor_mask, coords={dim: monitor.coords[dim]}).rebin(
188
+ {dim: detector_coord}
189
+ ).data != sc.scalar(0, unit=None)
190
+ return detector.assign_masks({"_monitor_mask": mask})
191
+
192
+ # else: Apply the mask to the events.
193
+ if dim not in detector.bins.coords:
194
+ raise sc.CoordError(
195
+ f"Detector must have coordinate '{dim}' to mask by monitor."
196
+ )
197
+ event_mask = sc.lookup(
198
+ sc.DataArray(monitor_mask, coords={dim: monitor.coords[dim]})
199
+ )[detector.bins.coords[dim]]
200
+ return detector.bins.assign_masks({"_monitor_mask": event_mask})
201
+
202
+
203
+ def _monitor_mask(monitor: sc.DataArray) -> sc.Variable | None:
204
+ """Mask nonfinite and zero monitor values and combine all masks."""
205
+ masks = list(monitor.masks.values())
206
+
207
+ finite = sc.isfinite(monitor.data)
208
+ nonzero = monitor.data != sc.scalar(0, unit=monitor.unit)
209
+ valid = finite & nonzero
210
+ if not valid.all():
211
+ masks.append(~valid)
212
+
213
+ if not masks:
214
+ return None
215
+ return functools.reduce(sc.logical_or, masks)
@@ -28,6 +28,7 @@ from .types import (
28
28
  PulseStrideOffset,
29
29
  TimeOfFlightLookupTable,
30
30
  TimeOfFlightLookupTableFilename,
31
+ ToaDetector,
31
32
  TofDetector,
32
33
  TofMonitor,
33
34
  )
@@ -51,6 +52,7 @@ __all__ = [
51
52
  "TimeOfFlightLookupTable",
52
53
  "TimeOfFlightLookupTableFilename",
53
54
  "TimeResolution",
55
+ "ToaDetector",
54
56
  "TofDetector",
55
57
  "TofLookupTableWorkflow",
56
58
  "TofMonitor",
@@ -36,6 +36,7 @@ from .types import (
36
36
  MonitorLtotal,
37
37
  PulseStrideOffset,
38
38
  TimeOfFlightLookupTable,
39
+ ToaDetector,
39
40
  TofDetector,
40
41
  TofMonitor,
41
42
  )
@@ -196,12 +197,32 @@ def _guess_pulse_stride_offset(
196
197
  return sorted(tofs, key=lambda x: sc.isnan(tofs[x]).sum())[0]
197
198
 
198
199
 
199
- def _time_of_flight_data_events(
200
+ def _prepare_tof_interpolation_inputs(
200
201
  da: sc.DataArray,
201
202
  lookup: sc.DataArray,
202
203
  ltotal: sc.Variable,
203
- pulse_stride_offset: int,
204
- ) -> sc.DataArray:
204
+ pulse_stride_offset: int | None,
205
+ ) -> dict:
206
+ """
207
+ Prepare the inputs required for the time-of-flight interpolation.
208
+ This function is used when computing the time-of-flight for event data, and for
209
+ computing the time-of-arrival for event data (as they both require guessing the
210
+ pulse_stride_offset if not provided).
211
+
212
+ Parameters
213
+ ----------
214
+ da:
215
+ Data array with event data.
216
+ lookup:
217
+ Lookup table giving time-of-flight as a function of distance and time of
218
+ arrival.
219
+ ltotal:
220
+ Total length of the flight path from the source to the detector.
221
+ pulse_stride_offset:
222
+ When pulse-skipping, the offset of the first pulse in the stride. This is
223
+ typically zero but can be a small integer < pulse_stride.
224
+ If None, a guess is made.
225
+ """
205
226
  etos = da.bins.coords["event_time_offset"].to(dtype=float, copy=False)
206
227
  eto_unit = elem_unit(etos)
207
228
 
@@ -259,12 +280,34 @@ def _time_of_flight_data_events(
259
280
  pulse_index += pulse_stride_offset
260
281
  pulse_index %= pulse_stride
261
282
 
262
- # Compute time-of-flight for all neutrons using the interpolator
263
- tofs = interp(
283
+ return {
284
+ "eto": etos,
285
+ "pulse_index": pulse_index,
286
+ "pulse_period": pulse_period,
287
+ "interp": interp,
288
+ "ltotal": ltotal,
289
+ }
290
+
291
+
292
+ def _time_of_flight_data_events(
293
+ da: sc.DataArray,
294
+ lookup: sc.DataArray,
295
+ ltotal: sc.Variable,
296
+ pulse_stride_offset: int | None,
297
+ ) -> sc.DataArray:
298
+ inputs = _prepare_tof_interpolation_inputs(
299
+ da=da,
300
+ lookup=lookup,
264
301
  ltotal=ltotal,
265
- event_time_offset=etos,
266
- pulse_index=pulse_index,
267
- pulse_period=pulse_period,
302
+ pulse_stride_offset=pulse_stride_offset,
303
+ )
304
+
305
+ # Compute time-of-flight for all neutrons using the interpolator
306
+ tofs = inputs["interp"](
307
+ ltotal=inputs["ltotal"],
308
+ event_time_offset=inputs["eto"],
309
+ pulse_index=inputs["pulse_index"],
310
+ pulse_period=inputs["pulse_period"],
268
311
  )
269
312
 
270
313
  parts = da.bins.constituents
@@ -416,6 +459,53 @@ def monitor_time_of_flight_data(
416
459
  )
417
460
 
418
461
 
462
+ def detector_time_of_arrival_data(
463
+ detector_data: RawDetector[RunType],
464
+ lookup: TimeOfFlightLookupTable,
465
+ ltotal: DetectorLtotal[RunType],
466
+ pulse_stride_offset: PulseStrideOffset,
467
+ ) -> ToaDetector[RunType]:
468
+ """
469
+ Convert the time-of-flight data to time-of-arrival data using a lookup table.
470
+ The output data will have a time-of-arrival coordinate.
471
+ The time-of-arrival is the time since the neutron was emitted from the source.
472
+ It is basically equal to event_time_offset + pulse_index * pulse_period.
473
+
474
+ Parameters
475
+ ----------
476
+ da:
477
+ Raw detector data loaded from a NeXus file, e.g., NXdetector containing
478
+ NXevent_data.
479
+ lookup:
480
+ Lookup table giving time-of-flight as a function of distance and time of
481
+ arrival.
482
+ ltotal:
483
+ Total length of the flight path from the source to the detector.
484
+ pulse_stride_offset:
485
+ When pulse-skipping, the offset of the first pulse in the stride. This is
486
+ typically zero but can be a small integer < pulse_stride.
487
+ """
488
+ if detector_data.bins is None:
489
+ raise NotImplementedError(
490
+ "Computing time-of-arrival in histogram mode is not implemented yet."
491
+ )
492
+ inputs = _prepare_tof_interpolation_inputs(
493
+ da=detector_data,
494
+ lookup=lookup,
495
+ ltotal=ltotal,
496
+ pulse_stride_offset=pulse_stride_offset,
497
+ )
498
+ parts = detector_data.bins.constituents
499
+ parts["data"] = inputs["eto"]
500
+ # The pulse index is None if pulse_stride == 1 (i.e., no pulse skipping)
501
+ if inputs["pulse_index"] is not None:
502
+ parts["data"] = parts["data"] + inputs["pulse_index"] * inputs["pulse_period"]
503
+ result = detector_data.bins.assign_coords(
504
+ toa=sc.bins(**parts, validate_indices=False)
505
+ )
506
+ return result
507
+
508
+
419
509
  def providers() -> tuple[Callable]:
420
510
  """
421
511
  Providers of the time-of-flight workflow.
@@ -425,4 +515,5 @@ def providers() -> tuple[Callable]:
425
515
  monitor_time_of_flight_data,
426
516
  detector_ltotal_from_straight_line_approximation,
427
517
  monitor_ltotal_from_straight_line_approximation,
518
+ detector_time_of_arrival_data,
428
519
  )
@@ -56,7 +56,7 @@ class FakeBeamline:
56
56
  else tof_pkg.Clockwise,
57
57
  open=ch.slit_begin,
58
58
  close=ch.slit_end,
59
- phase=abs(ch.phase),
59
+ phase=ch.phase if ch.frequency.value > 0.0 else -ch.phase,
60
60
  distance=sc.norm(ch.axle_position - source_position),
61
61
  name=name,
62
62
  )
@@ -420,7 +420,7 @@ def simulate_chopper_cascade_using_tof(
420
420
  else tof.Clockwise,
421
421
  open=ch.slit_begin,
422
422
  close=ch.slit_end,
423
- phase=abs(ch.phase),
423
+ phase=ch.phase if ch.frequency.value > 0.0 else -ch.phase,
424
424
  distance=sc.norm(
425
425
  ch.axle_position - source_position.to(unit=ch.axle_position.unit)
426
426
  ),
@@ -37,5 +37,17 @@ class TofDetector(sl.Scope[RunType, sc.DataArray], sc.DataArray):
37
37
  """Detector data with time-of-flight coordinate."""
38
38
 
39
39
 
40
+ class ToaDetector(sl.Scope[RunType, sc.DataArray], sc.DataArray):
41
+ """Detector data with time-of-arrival coordinate.
42
+
43
+ When the pulse stride is 1 (i.e., no pulse skipping), the time-of-arrival is the
44
+ same as the event_time_offset. When pulse skipping is used, the time-of-arrival is
45
+ the event_time_offset + pulse_offset * pulse_period.
46
+ This means that the time-of-arrival is basically the event_time_offset wrapped
47
+ over the frame period instead of the pulse period
48
+ (where frame_period = pulse_stride * pulse_period).
49
+ """
50
+
51
+
40
52
  class TofMonitor(sl.Scope[RunType, MonitorType, sc.DataArray], sc.DataArray):
41
53
  """Monitor data with time-of-flight coordinate."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: essreduce
3
- Version: 25.11.1
3
+ Version: 25.11.3
4
4
  Summary: Common data reduction tools for the ESS facility
5
5
  Author: Scipp contributors
6
6
  License-Expression: BSD-3-Clause
@@ -1,5 +1,6 @@
1
- ess/reduce/__init__.py,sha256=o1pWRP9YGwTukM_k-qlG6KcoXOpMb0PDVH59vod12lw,419
1
+ ess/reduce/__init__.py,sha256=9iqQ57K3stwyujDzOk30hj7WqZt1Ycnb9AVDDDmk3K0,451
2
2
  ess/reduce/logging.py,sha256=6n8Czq4LZ3OK9ENlKsWSI1M3KvKv6_HSoUiV4__IUlU,357
3
+ ess/reduce/normalization.py,sha256=B4O5W3CV_ti-zeU7tyQEAXk5pCUebZ0BG30YN2I3TyY,7844
3
4
  ess/reduce/parameter.py,sha256=4sCfoKOI2HuO_Q7JLH_jAXnEOFANSn5P3NdaOBzhJxc,4635
4
5
  ess/reduce/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
6
  ess/reduce/streaming.py,sha256=zbqxQz5dASDq4ZVyx-TdbapBXMyBttImCYz_6WOj4pg,17978
@@ -12,21 +13,21 @@ ess/reduce/live/__init__.py,sha256=jPQVhihRVNtEDrE20PoKkclKV2aBF1lS7cCHootgFgI,2
12
13
  ess/reduce/live/raw.py,sha256=d86s5fBjdf6tI_FWNMG4ZG67GCY2JADOobrinncNIjE,24367
13
14
  ess/reduce/live/roi.py,sha256=Hs-pW98k41WU6Kl3UQ41kQawk80c2QNOQ_WNctLzDPE,3795
14
15
  ess/reduce/live/workflow.py,sha256=bsbwvTqPhRO6mC__3b7MgU7DWwAnOvGvG-t2n22EKq8,4285
15
- ess/reduce/nexus/__init__.py,sha256=8TLqqALxRV5_QdCwLAjq3r6xneq6rzdh2dD7d9AXkYo,1065
16
- ess/reduce/nexus/_nexus_loader.py,sha256=8jN97CbFaSJ6XZEFzkoeAGyol8WpLTUZsHkUWu8WHsU,23136
16
+ ess/reduce/nexus/__init__.py,sha256=xXc982vZqRba4jR4z5hA2iim17Z7niw4KlS1aLFbn1Q,1107
17
+ ess/reduce/nexus/_nexus_loader.py,sha256=5J26y_t-kabj0ik0jf3OLSYda3lDLDQhvPd2_ro7Q_0,23927
17
18
  ess/reduce/nexus/json_generator.py,sha256=ME2Xn8L7Oi3uHJk9ZZdCRQTRX-OV_wh9-DJn07Alplk,2529
18
19
  ess/reduce/nexus/json_nexus.py,sha256=QrVc0p424nZ5dHX9gebAJppTw6lGZq9404P_OFl1giA,10282
19
20
  ess/reduce/nexus/types.py,sha256=g5oBBEYPH7urF1tDP0tqXtixhQN8JDpe8vmiKrPiUW0,9320
20
- ess/reduce/nexus/workflow.py,sha256=nU_YzaRJO5yUGNIHVPScJF_oEddZxaA2gChPF9mMhDQ,25031
21
+ ess/reduce/nexus/workflow.py,sha256=KRzG_flkAGNCkwDGwhTjX3h3Hi4GexMEz84trMw7HIg,24944
21
22
  ess/reduce/scripts/grow_nexus.py,sha256=hET3h06M0xlJd62E3palNLFvJMyNax2kK4XyJcOhl-I,3387
22
- ess/reduce/time_of_flight/__init__.py,sha256=Av6Pu_AKO0tF8IsWXchUXjjHps7ts2NFVnui6k3Eq-o,1425
23
- ess/reduce/time_of_flight/eto_to_tof.py,sha256=aPPQYbbz_73eq5dQCS97q02D2UUFntOfow2lWkkRyxg,14993
24
- ess/reduce/time_of_flight/fakes.py,sha256=0gtbSX3ZQilaM4ZP5dMr3fqbnhpyoVsZX2YEb8GgREE,4489
23
+ ess/reduce/time_of_flight/__init__.py,sha256=jn8x9rZ6PzyP_wK8ACd3cg9rOpDAu_IqHyTNSeKfVn0,1461
24
+ ess/reduce/time_of_flight/eto_to_tof.py,sha256=NN-UeVuFVg_WIe6ePAxN7HSxFxd-1BCrdasFB5WEfHw,18166
25
+ ess/reduce/time_of_flight/fakes.py,sha256=4viK0OsmwEHSc5bDqSNN0jdo982D-oO4phdLC6vZLng,4527
25
26
  ess/reduce/time_of_flight/interpolator_numba.py,sha256=wh2YS3j2rOu30v1Ok3xNHcwS7t8eEtZyZvbfXOCtgrQ,3835
26
27
  ess/reduce/time_of_flight/interpolator_scipy.py,sha256=_InoAPuMm2qhJKZQBAHOGRFqtvvuQ8TStoN7j_YgS4M,1853
27
- ess/reduce/time_of_flight/lut.py,sha256=bNf3EmMw86pp3lB499zvKEkCkcDlqS2eHFvyVX4bCBk,18750
28
+ ess/reduce/time_of_flight/lut.py,sha256=k8_aLQSK4kwvpOIOJgUs8J0DgromMieiKYSl7PTBC18,18788
28
29
  ess/reduce/time_of_flight/resample.py,sha256=Opmi-JA4zNH725l9VB99U4O9UlM37f5ACTCGtwBcows,3718
29
- ess/reduce/time_of_flight/types.py,sha256=VhJYLcLA_NfU-lILFNxjBkQUaC8AeNr_DJMeQuNgZOc,1302
30
+ ess/reduce/time_of_flight/types.py,sha256=xq-CjRZIzcfknqeNcUXMIZxvfK9eYmAJtXv-i4sJamE,1855
30
31
  ess/reduce/time_of_flight/workflow.py,sha256=mkgESvQ5Yt3CyAsa1iewkjBOHUqrHm5rRc1EhOQRewQ,2213
31
32
  ess/reduce/widgets/__init__.py,sha256=SoSHBv8Dc3QXV9HUvPhjSYWMwKTGYZLpsWwsShIO97Q,5325
32
33
  ess/reduce/widgets/_base.py,sha256=_wN3FOlXgx_u0c-A_3yyoIH-SdUvDENGgquh9S-h5GI,4852
@@ -40,9 +41,9 @@ ess/reduce/widgets/_spinner.py,sha256=2VY4Fhfa7HMXox2O7UbofcdKsYG-AJGrsgGJB85nDX
40
41
  ess/reduce/widgets/_string_widget.py,sha256=iPAdfANyXHf-nkfhgkyH6gQDklia0LebLTmwi3m-iYQ,1482
41
42
  ess/reduce/widgets/_switchable_widget.py,sha256=fjKz99SKLhIF1BLgGVBSKKn3Lu_jYBwDYGeAjbJY3Q8,2390
42
43
  ess/reduce/widgets/_vector_widget.py,sha256=aTaBqCFHZQhrIoX6-sSqFWCPePEW8HQt5kUio8jP1t8,1203
43
- essreduce-25.11.1.dist-info/licenses/LICENSE,sha256=nVEiume4Qj6jMYfSRjHTM2jtJ4FGu0g-5Sdh7osfEYw,1553
44
- essreduce-25.11.1.dist-info/METADATA,sha256=YJBtrUy0Gw60xZHi0TrmkBhC4XroNNC_CIEL0qRD5z8,1937
45
- essreduce-25.11.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
46
- essreduce-25.11.1.dist-info/entry_points.txt,sha256=PMZOIYzCifHMTe4pK3HbhxUwxjFaZizYlLD0td4Isb0,66
47
- essreduce-25.11.1.dist-info/top_level.txt,sha256=0JxTCgMKPLKtp14wb1-RKisQPQWX7i96innZNvHBr-s,4
48
- essreduce-25.11.1.dist-info/RECORD,,
44
+ essreduce-25.11.3.dist-info/licenses/LICENSE,sha256=nVEiume4Qj6jMYfSRjHTM2jtJ4FGu0g-5Sdh7osfEYw,1553
45
+ essreduce-25.11.3.dist-info/METADATA,sha256=RG8gLrZiQjprpTwz70dd-300cLF2jZeOEIigmwWFBOY,1937
46
+ essreduce-25.11.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
47
+ essreduce-25.11.3.dist-info/entry_points.txt,sha256=PMZOIYzCifHMTe4pK3HbhxUwxjFaZizYlLD0td4Isb0,66
48
+ essreduce-25.11.3.dist-info/top_level.txt,sha256=0JxTCgMKPLKtp14wb1-RKisQPQWX7i96innZNvHBr-s,4
49
+ essreduce-25.11.3.dist-info/RECORD,,