essreduce 25.10.2__py3-none-any.whl → 25.11.1__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/live/raw.py +5 -5
- ess/reduce/nexus/types.py +25 -18
- ess/reduce/nexus/workflow.py +77 -69
- ess/reduce/time_of_flight/__init__.py +4 -4
- ess/reduce/time_of_flight/eto_to_tof.py +37 -22
- ess/reduce/time_of_flight/lut.py +2 -2
- ess/reduce/time_of_flight/types.py +2 -2
- {essreduce-25.10.2.dist-info → essreduce-25.11.1.dist-info}/METADATA +2 -2
- {essreduce-25.10.2.dist-info → essreduce-25.11.1.dist-info}/RECORD +13 -13
- {essreduce-25.10.2.dist-info → essreduce-25.11.1.dist-info}/WHEEL +0 -0
- {essreduce-25.10.2.dist-info → essreduce-25.11.1.dist-info}/entry_points.txt +0 -0
- {essreduce-25.10.2.dist-info → essreduce-25.11.1.dist-info}/licenses/LICENSE +0 -0
- {essreduce-25.10.2.dist-info → essreduce-25.11.1.dist-info}/top_level.txt +0 -0
ess/reduce/live/raw.py
CHANGED
|
@@ -29,7 +29,7 @@ import scipp as sc
|
|
|
29
29
|
import scippnexus as snx
|
|
30
30
|
|
|
31
31
|
from ess.reduce.nexus.types import (
|
|
32
|
-
|
|
32
|
+
EmptyDetector,
|
|
33
33
|
Filename,
|
|
34
34
|
NeXusComponent,
|
|
35
35
|
NeXusDetectorName,
|
|
@@ -305,7 +305,7 @@ class RollingDetectorView(Detector):
|
|
|
305
305
|
|
|
306
306
|
@staticmethod
|
|
307
307
|
def from_detector_and_histogrammer(
|
|
308
|
-
detector:
|
|
308
|
+
detector: EmptyDetector[SampleRun],
|
|
309
309
|
window: RollingDetectorViewWindow,
|
|
310
310
|
projection: Histogrammer,
|
|
311
311
|
) -> RollingDetectorView:
|
|
@@ -320,10 +320,10 @@ class RollingDetectorView(Detector):
|
|
|
320
320
|
def from_detector_with_projection(
|
|
321
321
|
projection: Callable[[sc.DataArray], sc.DataArray] | None,
|
|
322
322
|
) -> Callable[
|
|
323
|
-
[
|
|
323
|
+
[EmptyDetector[SampleRun], RollingDetectorViewWindow], RollingDetectorView
|
|
324
324
|
]:
|
|
325
325
|
def factory(
|
|
326
|
-
detector:
|
|
326
|
+
detector: EmptyDetector[SampleRun],
|
|
327
327
|
window: RollingDetectorViewWindow,
|
|
328
328
|
) -> RollingDetectorView:
|
|
329
329
|
"""Helper for constructing via a Sciline workflow."""
|
|
@@ -591,7 +591,7 @@ def gaussian_position_noise(sigma: PositionNoiseSigma) -> PositionNoise:
|
|
|
591
591
|
|
|
592
592
|
def position_with_noisy_replicas(
|
|
593
593
|
*,
|
|
594
|
-
detector:
|
|
594
|
+
detector: EmptyDetector[SampleRun],
|
|
595
595
|
position_noise: PositionNoise,
|
|
596
596
|
replicas: PositionNoiseReplicaCount,
|
|
597
597
|
) -> CalibratedPositionWithNoisyReplicas:
|
ess/reduce/nexus/types.py
CHANGED
|
@@ -40,6 +40,14 @@ PreopenNeXusFile = NewType('PreopenNeXusFile', bool)
|
|
|
40
40
|
# 1 TypeVars used to parametrize the generic parts of the workflow
|
|
41
41
|
|
|
42
42
|
# 1.1 Run types
|
|
43
|
+
|
|
44
|
+
AnyRun = NewType("AnyRun", int)
|
|
45
|
+
"""RunType that does not represent a specific measurement run.
|
|
46
|
+
|
|
47
|
+
This can be used in cases where it makes no sense to use an 'actual' run type
|
|
48
|
+
like ``SampleRun`` or ``BackgroundRun``.
|
|
49
|
+
"""
|
|
50
|
+
|
|
43
51
|
BackgroundRun = NewType('BackgroundRun', int)
|
|
44
52
|
"""Background run such as a run with only a solvent which the sample is placed in."""
|
|
45
53
|
EmptyBeamRun = NewType('EmptyBeamRun', int)
|
|
@@ -136,12 +144,17 @@ This list will be supplemented with monitor types when creating a pipeline.
|
|
|
136
144
|
UniqueComponent = TypeVar('UniqueComponent', snx.NXsample, snx.NXsource)
|
|
137
145
|
"""Components that can be identified by their type as there will only be one."""
|
|
138
146
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
147
|
+
|
|
148
|
+
class Beamline(scn_meta.Beamline, Generic[RunType]):
|
|
149
|
+
"""Beamline metadata."""
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class Measurement(scn_meta.Measurement, Generic[RunType]):
|
|
153
|
+
"""measurement metadata."""
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class Source(scn_meta.Source, Generic[RunType]):
|
|
157
|
+
"""Neutron source metadata."""
|
|
145
158
|
|
|
146
159
|
|
|
147
160
|
class NeXusName(sciline.Scope[Component, str], str):
|
|
@@ -186,25 +199,19 @@ class MonitorPositionOffset(
|
|
|
186
199
|
"""Offset for the monitor position, added to base position."""
|
|
187
200
|
|
|
188
201
|
|
|
189
|
-
class
|
|
190
|
-
"""
|
|
202
|
+
class EmptyDetector(sciline.Scope[RunType, sc.DataArray], sc.DataArray):
|
|
203
|
+
"""Detector without neutron data."""
|
|
191
204
|
|
|
192
205
|
|
|
193
|
-
class
|
|
194
|
-
"""
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
class CalibratedMonitor(
|
|
198
|
-
sciline.Scope[RunType, MonitorType, sc.DataArray], sc.DataArray
|
|
199
|
-
):
|
|
200
|
-
"""Calibrated data from a monitor."""
|
|
206
|
+
class EmptyMonitor(sciline.Scope[RunType, MonitorType, sc.DataArray], sc.DataArray):
|
|
207
|
+
"""Monitor without neutron data."""
|
|
201
208
|
|
|
202
209
|
|
|
203
|
-
class
|
|
210
|
+
class RawDetector(sciline.Scope[RunType, sc.DataArray], sc.DataArray):
|
|
204
211
|
"""Calibrated detector merged with neutron event or histogram data."""
|
|
205
212
|
|
|
206
213
|
|
|
207
|
-
class
|
|
214
|
+
class RawMonitor(sciline.Scope[RunType, MonitorType, sc.DataArray], sc.DataArray):
|
|
208
215
|
"""Calibrated monitor merged with neutron event or histogram data."""
|
|
209
216
|
|
|
210
217
|
|
ess/reduce/nexus/workflow.py
CHANGED
|
@@ -20,17 +20,14 @@ from .types import (
|
|
|
20
20
|
COMPONENT_CONSTRAINTS,
|
|
21
21
|
AllNeXusComponents,
|
|
22
22
|
Beamline,
|
|
23
|
-
CalibratedBeamline,
|
|
24
|
-
CalibratedDetector,
|
|
25
|
-
CalibratedMonitor,
|
|
26
23
|
Component,
|
|
27
24
|
DetectorBankSizes,
|
|
28
|
-
DetectorData,
|
|
29
25
|
DetectorPositionOffset,
|
|
26
|
+
EmptyDetector,
|
|
27
|
+
EmptyMonitor,
|
|
30
28
|
Filename,
|
|
31
29
|
GravityVector,
|
|
32
30
|
Measurement,
|
|
33
|
-
MonitorData,
|
|
34
31
|
MonitorPositionOffset,
|
|
35
32
|
MonitorType,
|
|
36
33
|
NeXusAllComponentLocationSpec,
|
|
@@ -46,8 +43,9 @@ from .types import (
|
|
|
46
43
|
Position,
|
|
47
44
|
PreopenNeXusFile,
|
|
48
45
|
RawChoppers,
|
|
46
|
+
RawDetector,
|
|
47
|
+
RawMonitor,
|
|
49
48
|
RunType,
|
|
50
|
-
SampleRun,
|
|
51
49
|
TimeInterval,
|
|
52
50
|
UniqueComponent,
|
|
53
51
|
)
|
|
@@ -361,13 +359,11 @@ def get_calibrated_detector(
|
|
|
361
359
|
# all.
|
|
362
360
|
offset: DetectorPositionOffset[RunType],
|
|
363
361
|
bank_sizes: DetectorBankSizes,
|
|
364
|
-
) ->
|
|
362
|
+
) -> EmptyDetector[RunType]:
|
|
365
363
|
"""
|
|
366
364
|
Extract the data array corresponding to a detector's signal field.
|
|
367
365
|
|
|
368
|
-
The
|
|
369
|
-
signal values array, but not additional information about the detector. The
|
|
370
|
-
data array is reshaped to the logical detector shape, which by folding the data
|
|
366
|
+
The data array is reshaped to the logical detector shape, by folding the data
|
|
371
367
|
array along the detector_number dimension.
|
|
372
368
|
|
|
373
369
|
Parameters
|
|
@@ -389,57 +385,26 @@ def get_calibrated_detector(
|
|
|
389
385
|
# If the NXdetector in the file is not 1-D, we want to match the order of dims.
|
|
390
386
|
# zip_pixel_offsets otherwise yields a vector with dimensions in the order given
|
|
391
387
|
# by the x/y/z offsets.
|
|
392
|
-
offsets = snx.zip_pixel_offsets(da.coords)
|
|
388
|
+
offsets = snx.zip_pixel_offsets(da.coords)
|
|
389
|
+
# Get the dims in the order of the detector data array, but filter out dims that
|
|
390
|
+
# don't exist in the offsets (e.g. the detector data may have a 'time' dimension).
|
|
391
|
+
dims = [dim for dim in da.dims if dim in offsets.dims]
|
|
392
|
+
offsets = offsets.transpose(dims).copy()
|
|
393
393
|
# We use the unit of the offsets as this is likely what the user expects.
|
|
394
394
|
if transform.value.unit is not None and transform.value.unit != '':
|
|
395
395
|
transform_value = transform.value.to(unit=offsets.unit)
|
|
396
396
|
else:
|
|
397
397
|
transform_value = transform.value
|
|
398
398
|
position = transform_value * offsets
|
|
399
|
-
return
|
|
399
|
+
return EmptyDetector[RunType](
|
|
400
400
|
da.assign_coords(position=position + offset.to(unit=position.unit))
|
|
401
401
|
)
|
|
402
402
|
|
|
403
403
|
|
|
404
|
-
def assemble_beamline(
|
|
405
|
-
detector: CalibratedDetector[RunType],
|
|
406
|
-
source_position: Position[snx.NXsource, RunType],
|
|
407
|
-
sample_position: Position[snx.NXsample, RunType],
|
|
408
|
-
gravity: GravityVector,
|
|
409
|
-
) -> CalibratedBeamline[RunType]:
|
|
410
|
-
"""
|
|
411
|
-
Add beamline information (gravity vector, source- and sample-position) to detector.
|
|
412
|
-
|
|
413
|
-
This is performed separately and after :py:func:`get_calibrated_detector` to avoid
|
|
414
|
-
as false dependency of, e.g., the reshaped detector numbers on the sample position.
|
|
415
|
-
The latter can change during a run, e.g., for a rotating sample. The detector
|
|
416
|
-
numbers might be used, e.g., to mask certain detector pixels, and should not depend
|
|
417
|
-
on the sample position.
|
|
418
|
-
|
|
419
|
-
Parameters
|
|
420
|
-
----------
|
|
421
|
-
detector:
|
|
422
|
-
NeXus detector group.
|
|
423
|
-
source_position:
|
|
424
|
-
Position of the neutron source.
|
|
425
|
-
sample_position:
|
|
426
|
-
Position of the sample.
|
|
427
|
-
gravity:
|
|
428
|
-
Gravity vector.
|
|
429
|
-
"""
|
|
430
|
-
return CalibratedBeamline[RunType](
|
|
431
|
-
detector.assign_coords(
|
|
432
|
-
source_position=source_position,
|
|
433
|
-
sample_position=sample_position,
|
|
434
|
-
gravity=gravity,
|
|
435
|
-
)
|
|
436
|
-
)
|
|
437
|
-
|
|
438
|
-
|
|
439
404
|
def assemble_detector_data(
|
|
440
|
-
detector:
|
|
441
|
-
|
|
442
|
-
) ->
|
|
405
|
+
detector: EmptyDetector[RunType],
|
|
406
|
+
neutron_data: NeXusData[snx.NXdetector, RunType],
|
|
407
|
+
) -> RawDetector[RunType]:
|
|
443
408
|
"""
|
|
444
409
|
Assemble a detector data array with event data.
|
|
445
410
|
|
|
@@ -449,14 +414,15 @@ def assemble_detector_data(
|
|
|
449
414
|
----------
|
|
450
415
|
detector:
|
|
451
416
|
Calibrated detector data array.
|
|
452
|
-
|
|
453
|
-
|
|
417
|
+
neutron_data:
|
|
418
|
+
Neutron data array (events or histogram).
|
|
454
419
|
"""
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
420
|
+
if neutron_data.bins is not None:
|
|
421
|
+
neutron_data = nexus.group_event_data(
|
|
422
|
+
event_data=neutron_data, detector_number=detector.coords['detector_number']
|
|
423
|
+
)
|
|
424
|
+
return RawDetector[RunType](
|
|
425
|
+
_add_variances(neutron_data)
|
|
460
426
|
.assign_coords(detector.coords)
|
|
461
427
|
.assign_masks(detector.masks)
|
|
462
428
|
)
|
|
@@ -466,7 +432,7 @@ def get_calibrated_monitor(
|
|
|
466
432
|
monitor: NeXusComponent[MonitorType, RunType],
|
|
467
433
|
offset: MonitorPositionOffset[RunType, MonitorType],
|
|
468
434
|
source_position: Position[snx.NXsource, RunType],
|
|
469
|
-
) ->
|
|
435
|
+
) -> EmptyMonitor[RunType, MonitorType]:
|
|
470
436
|
"""
|
|
471
437
|
Extract the data array corresponding to a monitor's signal field.
|
|
472
438
|
|
|
@@ -483,7 +449,7 @@ def get_calibrated_monitor(
|
|
|
483
449
|
Position of the neutron source.
|
|
484
450
|
"""
|
|
485
451
|
monitor = nexus.compute_component_position(monitor)
|
|
486
|
-
return
|
|
452
|
+
return EmptyMonitor[RunType, MonitorType](
|
|
487
453
|
nexus.extract_signal_data_array(monitor).assign_coords(
|
|
488
454
|
position=monitor['position'] + offset.to(unit=monitor['position'].unit),
|
|
489
455
|
source_position=source_position,
|
|
@@ -492,9 +458,9 @@ def get_calibrated_monitor(
|
|
|
492
458
|
|
|
493
459
|
|
|
494
460
|
def assemble_monitor_data(
|
|
495
|
-
monitor:
|
|
461
|
+
monitor: EmptyMonitor[RunType, MonitorType],
|
|
496
462
|
data: NeXusData[MonitorType, RunType],
|
|
497
|
-
) ->
|
|
463
|
+
) -> RawMonitor[RunType, MonitorType]:
|
|
498
464
|
"""
|
|
499
465
|
Assemble a monitor data array with event data.
|
|
500
466
|
|
|
@@ -508,7 +474,7 @@ def assemble_monitor_data(
|
|
|
508
474
|
Data array with neutron counts.
|
|
509
475
|
"""
|
|
510
476
|
da = data.assign_coords(monitor.coords).assign_masks(monitor.masks)
|
|
511
|
-
return
|
|
477
|
+
return RawMonitor[RunType, MonitorType](_add_variances(da))
|
|
512
478
|
|
|
513
479
|
|
|
514
480
|
def parse_disk_choppers(
|
|
@@ -543,6 +509,19 @@ def _drop(
|
|
|
543
509
|
}
|
|
544
510
|
|
|
545
511
|
|
|
512
|
+
class _EmptyField:
|
|
513
|
+
"""Empty field that can replace a missing detector_number in NXdetector."""
|
|
514
|
+
|
|
515
|
+
def __init__(self, sizes: dict[str, int]):
|
|
516
|
+
self.attrs = {}
|
|
517
|
+
self.sizes = sizes.copy()
|
|
518
|
+
self.dims = tuple(sizes.keys())
|
|
519
|
+
self.shape = tuple(sizes.values())
|
|
520
|
+
|
|
521
|
+
def __getitem__(self, key: Any) -> sc.Variable:
|
|
522
|
+
return sc.zeros(dims=self.dims, shape=self.shape, unit=None, dtype='int32')
|
|
523
|
+
|
|
524
|
+
|
|
546
525
|
class _StrippedDetector(snx.NXdetector):
|
|
547
526
|
"""Detector definition without large geometry or event data for ScippNexus.
|
|
548
527
|
|
|
@@ -552,8 +531,36 @@ class _StrippedDetector(snx.NXdetector):
|
|
|
552
531
|
def __init__(
|
|
553
532
|
self, attrs: dict[str, Any], children: dict[str, snx.Field | snx.Group]
|
|
554
533
|
):
|
|
555
|
-
|
|
556
|
-
|
|
534
|
+
if 'detector_number' in children:
|
|
535
|
+
data = children['detector_number']
|
|
536
|
+
else:
|
|
537
|
+
# We get the 'data' sizes before the NXdata is dropped
|
|
538
|
+
if 'data' not in children:
|
|
539
|
+
raise KeyError(
|
|
540
|
+
"StrippedDetector: Cannot determine shape of the detector. "
|
|
541
|
+
"No 'detector_number' was found, and the 'data' entry is missing."
|
|
542
|
+
)
|
|
543
|
+
if 'value' not in children['data']:
|
|
544
|
+
raise KeyError(
|
|
545
|
+
"StrippedDetector: Cannot determine shape of the detector. "
|
|
546
|
+
"The 'data' entry has no 'value'."
|
|
547
|
+
)
|
|
548
|
+
# We drop any time-related dimension from the data sizes, as they are not
|
|
549
|
+
# relevant for the detector geometry/shape.
|
|
550
|
+
data = _EmptyField(
|
|
551
|
+
sizes={
|
|
552
|
+
dim: size
|
|
553
|
+
for dim, size in children['data']['value'].sizes.items()
|
|
554
|
+
if dim not in ('time', 'frame_time')
|
|
555
|
+
}
|
|
556
|
+
)
|
|
557
|
+
|
|
558
|
+
children = _drop(
|
|
559
|
+
children, (snx.NXoff_geometry, snx.NXevent_data, snx.NXdata, snx.NXlog)
|
|
560
|
+
)
|
|
561
|
+
|
|
562
|
+
children['data'] = data
|
|
563
|
+
|
|
557
564
|
super().__init__(attrs=attrs, children=children)
|
|
558
565
|
|
|
559
566
|
|
|
@@ -567,7 +574,7 @@ class _DummyField:
|
|
|
567
574
|
self.shape = (0,)
|
|
568
575
|
|
|
569
576
|
def __getitem__(self, key: Any) -> sc.Variable:
|
|
570
|
-
return sc.
|
|
577
|
+
return sc.zeros(dims=self.dims, shape=self.shape, unit=None, dtype='int32')
|
|
571
578
|
|
|
572
579
|
|
|
573
580
|
class _StrippedMonitor(snx.NXmonitor):
|
|
@@ -606,14 +613,16 @@ def _assign_values_as_variances(var: sc.Variable) -> sc.Variable:
|
|
|
606
613
|
return var
|
|
607
614
|
|
|
608
615
|
|
|
609
|
-
def load_beamline_metadata_from_nexus(
|
|
616
|
+
def load_beamline_metadata_from_nexus(
|
|
617
|
+
file_spec: NeXusFileSpec[RunType],
|
|
618
|
+
) -> Beamline[RunType]:
|
|
610
619
|
"""Load beamline metadata from a sample NeXus file."""
|
|
611
620
|
return nexus.load_metadata(file_spec.value, Beamline)
|
|
612
621
|
|
|
613
622
|
|
|
614
623
|
def load_measurement_metadata_from_nexus(
|
|
615
|
-
file_spec: NeXusFileSpec[
|
|
616
|
-
) -> Measurement:
|
|
624
|
+
file_spec: NeXusFileSpec[RunType],
|
|
625
|
+
) -> Measurement[RunType]:
|
|
617
626
|
"""Load measurement metadata from a sample NeXus file."""
|
|
618
627
|
return nexus.load_metadata(file_spec.value, Measurement)
|
|
619
628
|
|
|
@@ -654,7 +663,6 @@ _detector_providers = (
|
|
|
654
663
|
no_detector_position_offset,
|
|
655
664
|
load_nexus_sample,
|
|
656
665
|
get_calibrated_detector,
|
|
657
|
-
assemble_beamline,
|
|
658
666
|
assemble_detector_data,
|
|
659
667
|
)
|
|
660
668
|
|
|
@@ -24,25 +24,23 @@ from .lut import (
|
|
|
24
24
|
)
|
|
25
25
|
from .types import (
|
|
26
26
|
DetectorLtotal,
|
|
27
|
-
DetectorTofData,
|
|
28
27
|
MonitorLtotal,
|
|
29
|
-
MonitorTofData,
|
|
30
28
|
PulseStrideOffset,
|
|
31
29
|
TimeOfFlightLookupTable,
|
|
32
30
|
TimeOfFlightLookupTableFilename,
|
|
31
|
+
TofDetector,
|
|
32
|
+
TofMonitor,
|
|
33
33
|
)
|
|
34
34
|
from .workflow import GenericTofWorkflow
|
|
35
35
|
|
|
36
36
|
__all__ = [
|
|
37
37
|
"DetectorLtotal",
|
|
38
|
-
"DetectorTofData",
|
|
39
38
|
"DiskChoppers",
|
|
40
39
|
"DistanceResolution",
|
|
41
40
|
"GenericTofWorkflow",
|
|
42
41
|
"LookupTableRelativeErrorThreshold",
|
|
43
42
|
"LtotalRange",
|
|
44
43
|
"MonitorLtotal",
|
|
45
|
-
"MonitorTofData",
|
|
46
44
|
"NumberOfSimulatedNeutrons",
|
|
47
45
|
"PulsePeriod",
|
|
48
46
|
"PulseStride",
|
|
@@ -53,7 +51,9 @@ __all__ = [
|
|
|
53
51
|
"TimeOfFlightLookupTable",
|
|
54
52
|
"TimeOfFlightLookupTableFilename",
|
|
55
53
|
"TimeResolution",
|
|
54
|
+
"TofDetector",
|
|
56
55
|
"TofLookupTableWorkflow",
|
|
56
|
+
"TofMonitor",
|
|
57
57
|
"providers",
|
|
58
58
|
"simulate_chopper_cascade_using_tof",
|
|
59
59
|
]
|
|
@@ -12,6 +12,7 @@ from collections.abc import Callable
|
|
|
12
12
|
import numpy as np
|
|
13
13
|
import scipp as sc
|
|
14
14
|
import scippneutron as scn
|
|
15
|
+
import scippnexus as snx
|
|
15
16
|
from scippneutron._utils import elem_unit
|
|
16
17
|
|
|
17
18
|
try:
|
|
@@ -20,21 +21,23 @@ except ImportError:
|
|
|
20
21
|
from .interpolator_scipy import Interpolator as InterpolatorImpl
|
|
21
22
|
|
|
22
23
|
from ..nexus.types import (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
MonitorData,
|
|
24
|
+
EmptyDetector,
|
|
25
|
+
EmptyMonitor,
|
|
26
|
+
GravityVector,
|
|
27
27
|
MonitorType,
|
|
28
|
+
Position,
|
|
29
|
+
RawDetector,
|
|
30
|
+
RawMonitor,
|
|
28
31
|
RunType,
|
|
29
32
|
)
|
|
30
33
|
from .resample import rebin_strictly_increasing
|
|
31
34
|
from .types import (
|
|
32
35
|
DetectorLtotal,
|
|
33
|
-
DetectorTofData,
|
|
34
36
|
MonitorLtotal,
|
|
35
|
-
MonitorTofData,
|
|
36
37
|
PulseStrideOffset,
|
|
37
38
|
TimeOfFlightLookupTable,
|
|
39
|
+
TofDetector,
|
|
40
|
+
TofMonitor,
|
|
38
41
|
)
|
|
39
42
|
|
|
40
43
|
|
|
@@ -271,30 +274,42 @@ def _time_of_flight_data_events(
|
|
|
271
274
|
|
|
272
275
|
|
|
273
276
|
def detector_ltotal_from_straight_line_approximation(
|
|
274
|
-
|
|
277
|
+
detector: EmptyDetector[RunType],
|
|
278
|
+
source_position: Position[snx.NXsource, RunType],
|
|
279
|
+
sample_position: Position[snx.NXsample, RunType],
|
|
280
|
+
gravity: GravityVector,
|
|
275
281
|
) -> DetectorLtotal[RunType]:
|
|
276
|
-
"""
|
|
277
|
-
|
|
282
|
+
"""Compute Ltotal for the detector pixels.
|
|
283
|
+
|
|
278
284
|
This is a naive straight-line approximation to Ltotal based on basic component
|
|
279
285
|
positions.
|
|
280
286
|
|
|
281
287
|
Parameters
|
|
282
288
|
----------
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
289
|
+
detector:
|
|
290
|
+
Data array with detector positions.
|
|
291
|
+
source_position:
|
|
292
|
+
Position of the neutron source.
|
|
293
|
+
sample_position:
|
|
294
|
+
Position of the sample.
|
|
295
|
+
gravity:
|
|
296
|
+
Gravity vector.
|
|
287
297
|
"""
|
|
288
|
-
graph =
|
|
298
|
+
graph = {
|
|
299
|
+
**scn.conversion.graph.beamline.beamline(scatter=True),
|
|
300
|
+
'source_position': lambda: source_position,
|
|
301
|
+
'sample_position': lambda: sample_position,
|
|
302
|
+
'gravity': lambda: gravity,
|
|
303
|
+
}
|
|
289
304
|
return DetectorLtotal[RunType](
|
|
290
|
-
|
|
305
|
+
detector.transform_coords(
|
|
291
306
|
"Ltotal", graph=graph, keep_intermediate=False
|
|
292
307
|
).coords["Ltotal"]
|
|
293
308
|
)
|
|
294
309
|
|
|
295
310
|
|
|
296
311
|
def monitor_ltotal_from_straight_line_approximation(
|
|
297
|
-
monitor_beamline:
|
|
312
|
+
monitor_beamline: EmptyMonitor[RunType, MonitorType],
|
|
298
313
|
) -> MonitorLtotal[RunType, MonitorType]:
|
|
299
314
|
"""
|
|
300
315
|
Compute Ltotal for the monitor.
|
|
@@ -334,11 +349,11 @@ def _compute_tof_data(
|
|
|
334
349
|
|
|
335
350
|
|
|
336
351
|
def detector_time_of_flight_data(
|
|
337
|
-
detector_data:
|
|
352
|
+
detector_data: RawDetector[RunType],
|
|
338
353
|
lookup: TimeOfFlightLookupTable,
|
|
339
354
|
ltotal: DetectorLtotal[RunType],
|
|
340
355
|
pulse_stride_offset: PulseStrideOffset,
|
|
341
|
-
) ->
|
|
356
|
+
) -> TofDetector[RunType]:
|
|
342
357
|
"""
|
|
343
358
|
Convert the time-of-arrival data to time-of-flight data using a lookup table.
|
|
344
359
|
The output data will have a time-of-flight coordinate.
|
|
@@ -357,7 +372,7 @@ def detector_time_of_flight_data(
|
|
|
357
372
|
When pulse-skipping, the offset of the first pulse in the stride. This is
|
|
358
373
|
typically zero but can be a small integer < pulse_stride.
|
|
359
374
|
"""
|
|
360
|
-
return
|
|
375
|
+
return TofDetector[RunType](
|
|
361
376
|
_compute_tof_data(
|
|
362
377
|
da=detector_data,
|
|
363
378
|
lookup=lookup,
|
|
@@ -368,11 +383,11 @@ def detector_time_of_flight_data(
|
|
|
368
383
|
|
|
369
384
|
|
|
370
385
|
def monitor_time_of_flight_data(
|
|
371
|
-
monitor_data:
|
|
386
|
+
monitor_data: RawMonitor[RunType, MonitorType],
|
|
372
387
|
lookup: TimeOfFlightLookupTable,
|
|
373
388
|
ltotal: MonitorLtotal[RunType, MonitorType],
|
|
374
389
|
pulse_stride_offset: PulseStrideOffset,
|
|
375
|
-
) ->
|
|
390
|
+
) -> TofMonitor[RunType, MonitorType]:
|
|
376
391
|
"""
|
|
377
392
|
Convert the time-of-arrival data to time-of-flight data using a lookup table.
|
|
378
393
|
The output data will have a time-of-flight coordinate.
|
|
@@ -391,7 +406,7 @@ def monitor_time_of_flight_data(
|
|
|
391
406
|
When pulse-skipping, the offset of the first pulse in the stride. This is
|
|
392
407
|
typically zero but can be a small integer < pulse_stride.
|
|
393
408
|
"""
|
|
394
|
-
return
|
|
409
|
+
return TofMonitor[RunType, MonitorType](
|
|
395
410
|
_compute_tof_data(
|
|
396
411
|
da=monitor_data,
|
|
397
412
|
lookup=lookup,
|
ess/reduce/time_of_flight/lut.py
CHANGED
|
@@ -12,7 +12,7 @@ import numpy as np
|
|
|
12
12
|
import sciline as sl
|
|
13
13
|
import scipp as sc
|
|
14
14
|
|
|
15
|
-
from ..nexus.types import DiskChoppers
|
|
15
|
+
from ..nexus.types import AnyRun, DiskChoppers
|
|
16
16
|
from .types import TimeOfFlightLookupTable
|
|
17
17
|
|
|
18
18
|
|
|
@@ -380,7 +380,7 @@ def make_tof_lookup_table(
|
|
|
380
380
|
|
|
381
381
|
|
|
382
382
|
def simulate_chopper_cascade_using_tof(
|
|
383
|
-
choppers: DiskChoppers,
|
|
383
|
+
choppers: DiskChoppers[AnyRun],
|
|
384
384
|
source_position: SourcePosition,
|
|
385
385
|
neutrons: NumberOfSimulatedNeutrons,
|
|
386
386
|
pulse_stride: PulseStride,
|
|
@@ -33,9 +33,9 @@ class MonitorLtotal(sl.Scope[RunType, MonitorType, sc.Variable], sc.Variable):
|
|
|
33
33
|
"""Total path length of neutrons from source to monitor."""
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
class
|
|
36
|
+
class TofDetector(sl.Scope[RunType, sc.DataArray], sc.DataArray):
|
|
37
37
|
"""Detector data with time-of-flight coordinate."""
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
class
|
|
40
|
+
class TofMonitor(sl.Scope[RunType, MonitorType, sc.DataArray], sc.DataArray):
|
|
41
41
|
"""Monitor data with time-of-flight coordinate."""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: essreduce
|
|
3
|
-
Version: 25.
|
|
3
|
+
Version: 25.11.1
|
|
4
4
|
Summary: Common data reduction tools for the ESS facility
|
|
5
5
|
Author: Scipp contributors
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -20,7 +20,7 @@ Classifier: Typing :: Typed
|
|
|
20
20
|
Requires-Python: >=3.11
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
License-File: LICENSE
|
|
23
|
-
Requires-Dist: sciline>=25.
|
|
23
|
+
Requires-Dist: sciline>=25.11.0
|
|
24
24
|
Requires-Dist: scipp>=25.04.0
|
|
25
25
|
Requires-Dist: scippneutron>=25.02.0
|
|
26
26
|
Requires-Dist: scippnexus>=25.06.0
|
|
@@ -9,24 +9,24 @@ ess/reduce/workflow.py,sha256=738-lcdgsORYfQ4A0UTk2IgnbVxC3jBdpscpaOFIpdc,3114
|
|
|
9
9
|
ess/reduce/data/__init__.py,sha256=uDtqkmKA_Zwtj6II25zntz9T812XhdCn3tktYev4uyY,486
|
|
10
10
|
ess/reduce/data/_registry.py,sha256=50qY36y5gd2i3JP0Ks6bXApGcW6l70qA6riO0m9Bz4o,11475
|
|
11
11
|
ess/reduce/live/__init__.py,sha256=jPQVhihRVNtEDrE20PoKkclKV2aBF1lS7cCHootgFgI,204
|
|
12
|
-
ess/reduce/live/raw.py,sha256=
|
|
12
|
+
ess/reduce/live/raw.py,sha256=d86s5fBjdf6tI_FWNMG4ZG67GCY2JADOobrinncNIjE,24367
|
|
13
13
|
ess/reduce/live/roi.py,sha256=Hs-pW98k41WU6Kl3UQ41kQawk80c2QNOQ_WNctLzDPE,3795
|
|
14
14
|
ess/reduce/live/workflow.py,sha256=bsbwvTqPhRO6mC__3b7MgU7DWwAnOvGvG-t2n22EKq8,4285
|
|
15
15
|
ess/reduce/nexus/__init__.py,sha256=8TLqqALxRV5_QdCwLAjq3r6xneq6rzdh2dD7d9AXkYo,1065
|
|
16
16
|
ess/reduce/nexus/_nexus_loader.py,sha256=8jN97CbFaSJ6XZEFzkoeAGyol8WpLTUZsHkUWu8WHsU,23136
|
|
17
17
|
ess/reduce/nexus/json_generator.py,sha256=ME2Xn8L7Oi3uHJk9ZZdCRQTRX-OV_wh9-DJn07Alplk,2529
|
|
18
18
|
ess/reduce/nexus/json_nexus.py,sha256=QrVc0p424nZ5dHX9gebAJppTw6lGZq9404P_OFl1giA,10282
|
|
19
|
-
ess/reduce/nexus/types.py,sha256=
|
|
20
|
-
ess/reduce/nexus/workflow.py,sha256=
|
|
19
|
+
ess/reduce/nexus/types.py,sha256=g5oBBEYPH7urF1tDP0tqXtixhQN8JDpe8vmiKrPiUW0,9320
|
|
20
|
+
ess/reduce/nexus/workflow.py,sha256=nU_YzaRJO5yUGNIHVPScJF_oEddZxaA2gChPF9mMhDQ,25031
|
|
21
21
|
ess/reduce/scripts/grow_nexus.py,sha256=hET3h06M0xlJd62E3palNLFvJMyNax2kK4XyJcOhl-I,3387
|
|
22
|
-
ess/reduce/time_of_flight/__init__.py,sha256=
|
|
23
|
-
ess/reduce/time_of_flight/eto_to_tof.py,sha256=
|
|
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
24
|
ess/reduce/time_of_flight/fakes.py,sha256=0gtbSX3ZQilaM4ZP5dMr3fqbnhpyoVsZX2YEb8GgREE,4489
|
|
25
25
|
ess/reduce/time_of_flight/interpolator_numba.py,sha256=wh2YS3j2rOu30v1Ok3xNHcwS7t8eEtZyZvbfXOCtgrQ,3835
|
|
26
26
|
ess/reduce/time_of_flight/interpolator_scipy.py,sha256=_InoAPuMm2qhJKZQBAHOGRFqtvvuQ8TStoN7j_YgS4M,1853
|
|
27
|
-
ess/reduce/time_of_flight/lut.py,sha256=
|
|
27
|
+
ess/reduce/time_of_flight/lut.py,sha256=bNf3EmMw86pp3lB499zvKEkCkcDlqS2eHFvyVX4bCBk,18750
|
|
28
28
|
ess/reduce/time_of_flight/resample.py,sha256=Opmi-JA4zNH725l9VB99U4O9UlM37f5ACTCGtwBcows,3718
|
|
29
|
-
ess/reduce/time_of_flight/types.py,sha256=
|
|
29
|
+
ess/reduce/time_of_flight/types.py,sha256=VhJYLcLA_NfU-lILFNxjBkQUaC8AeNr_DJMeQuNgZOc,1302
|
|
30
30
|
ess/reduce/time_of_flight/workflow.py,sha256=mkgESvQ5Yt3CyAsa1iewkjBOHUqrHm5rRc1EhOQRewQ,2213
|
|
31
31
|
ess/reduce/widgets/__init__.py,sha256=SoSHBv8Dc3QXV9HUvPhjSYWMwKTGYZLpsWwsShIO97Q,5325
|
|
32
32
|
ess/reduce/widgets/_base.py,sha256=_wN3FOlXgx_u0c-A_3yyoIH-SdUvDENGgquh9S-h5GI,4852
|
|
@@ -40,9 +40,9 @@ ess/reduce/widgets/_spinner.py,sha256=2VY4Fhfa7HMXox2O7UbofcdKsYG-AJGrsgGJB85nDX
|
|
|
40
40
|
ess/reduce/widgets/_string_widget.py,sha256=iPAdfANyXHf-nkfhgkyH6gQDklia0LebLTmwi3m-iYQ,1482
|
|
41
41
|
ess/reduce/widgets/_switchable_widget.py,sha256=fjKz99SKLhIF1BLgGVBSKKn3Lu_jYBwDYGeAjbJY3Q8,2390
|
|
42
42
|
ess/reduce/widgets/_vector_widget.py,sha256=aTaBqCFHZQhrIoX6-sSqFWCPePEW8HQt5kUio8jP1t8,1203
|
|
43
|
-
essreduce-25.
|
|
44
|
-
essreduce-25.
|
|
45
|
-
essreduce-25.
|
|
46
|
-
essreduce-25.
|
|
47
|
-
essreduce-25.
|
|
48
|
-
essreduce-25.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|