essreduce 25.2.5__py3-none-any.whl → 25.3.0__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 +34 -65
- ess/reduce/streaming.py +58 -0
- {essreduce-25.2.5.dist-info → essreduce-25.3.0.dist-info}/METADATA +1 -1
- {essreduce-25.2.5.dist-info → essreduce-25.3.0.dist-info}/RECORD +8 -8
- {essreduce-25.2.5.dist-info → essreduce-25.3.0.dist-info}/LICENSE +0 -0
- {essreduce-25.2.5.dist-info → essreduce-25.3.0.dist-info}/WHEEL +0 -0
- {essreduce-25.2.5.dist-info → essreduce-25.3.0.dist-info}/entry_points.txt +0 -0
- {essreduce-25.2.5.dist-info → essreduce-25.3.0.dist-info}/top_level.txt +0 -0
ess/reduce/live/raw.py
CHANGED
|
@@ -15,14 +15,12 @@ options:
|
|
|
15
15
|
- `'xy_plane'`: Project the data onto the x-y plane, i.e., perpendicular to the beam.
|
|
16
16
|
- `'cylinder_mantle_z'`: Project the data onto the mantle of a cylinder aligned with the
|
|
17
17
|
z-axis.
|
|
18
|
-
-
|
|
19
|
-
flatten dimensions of the data.
|
|
18
|
+
- A callable, e.g., to select and flatten dimensions of the data.
|
|
20
19
|
"""
|
|
21
20
|
|
|
22
21
|
from __future__ import annotations
|
|
23
22
|
|
|
24
23
|
from collections.abc import Callable, Sequence
|
|
25
|
-
from dataclasses import dataclass, field
|
|
26
24
|
from math import ceil
|
|
27
25
|
from typing import Literal, NewType
|
|
28
26
|
|
|
@@ -140,44 +138,6 @@ class Histogrammer:
|
|
|
140
138
|
return self._hist(replicated, coords=self._coords) / self.replicas
|
|
141
139
|
|
|
142
140
|
|
|
143
|
-
@dataclass
|
|
144
|
-
class LogicalView:
|
|
145
|
-
"""
|
|
146
|
-
Logical view of a multi-dimensional detector.
|
|
147
|
-
|
|
148
|
-
Instances can be used as a "projection" function for a detector view.
|
|
149
|
-
|
|
150
|
-
Parameters
|
|
151
|
-
----------
|
|
152
|
-
fold:
|
|
153
|
-
Dimensions to fold. This is useful is the raw data has a single dimension that
|
|
154
|
-
corresponds to multiple dimensions in the logical view.
|
|
155
|
-
transpose:
|
|
156
|
-
Dimensions to transpose. This is useful for reordering dimensions.
|
|
157
|
-
select:
|
|
158
|
-
Dimensions with associated index to select from the data. This extracts a slice
|
|
159
|
-
of the data for each given dimension.
|
|
160
|
-
flatten:
|
|
161
|
-
Dimensions to flatten.
|
|
162
|
-
"""
|
|
163
|
-
|
|
164
|
-
fold: dict[str, int] | None = None
|
|
165
|
-
transpose: tuple[str, ...] | None = None
|
|
166
|
-
select: dict[str, int] = field(default_factory=dict)
|
|
167
|
-
flatten: dict[str, list[str]] = field(default_factory=dict)
|
|
168
|
-
|
|
169
|
-
def __call__(self, da: sc.DataArray) -> sc.DataArray:
|
|
170
|
-
if self.fold is not None:
|
|
171
|
-
da = da.fold(da.dim, sizes=self.fold)
|
|
172
|
-
if self.transpose is not None:
|
|
173
|
-
da = da.transpose(self.transpose)
|
|
174
|
-
for dim, index in self.select.items():
|
|
175
|
-
da = da[dim, index]
|
|
176
|
-
for to, dims in self.flatten.items():
|
|
177
|
-
da = da.flatten(dims, to=to)
|
|
178
|
-
return da.copy()
|
|
179
|
-
|
|
180
|
-
|
|
181
141
|
class Detector:
|
|
182
142
|
def __init__(self, detector_number: sc.Variable):
|
|
183
143
|
self._data = sc.DataArray(
|
|
@@ -295,7 +255,7 @@ class RollingDetectorView(Detector):
|
|
|
295
255
|
else:
|
|
296
256
|
indices = sc.ones(sizes=self.data.sizes, dtype='int32', unit=None)
|
|
297
257
|
indices = sc.cumsum(indices, mode='exclusive')
|
|
298
|
-
if
|
|
258
|
+
if self._projection is not None:
|
|
299
259
|
indices = self._projection(indices)
|
|
300
260
|
return roi.ROIFilter(indices=indices, norm=norm)
|
|
301
261
|
|
|
@@ -357,17 +317,23 @@ class RollingDetectorView(Detector):
|
|
|
357
317
|
)
|
|
358
318
|
|
|
359
319
|
@staticmethod
|
|
360
|
-
def
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
320
|
+
def from_detector_with_projection(
|
|
321
|
+
projection: Callable[[sc.DataArray], sc.DataArray] | None,
|
|
322
|
+
) -> Callable[
|
|
323
|
+
[CalibratedDetector[SampleRun], RollingDetectorViewWindow], RollingDetectorView
|
|
324
|
+
]:
|
|
325
|
+
def factory(
|
|
326
|
+
detector: CalibratedDetector[SampleRun],
|
|
327
|
+
window: RollingDetectorViewWindow,
|
|
328
|
+
) -> RollingDetectorView:
|
|
329
|
+
"""Helper for constructing via a Sciline workflow."""
|
|
330
|
+
return RollingDetectorView(
|
|
331
|
+
detector_number=detector.coords['detector_number'],
|
|
332
|
+
window=window,
|
|
333
|
+
projection=projection,
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
return factory
|
|
371
337
|
|
|
372
338
|
@staticmethod
|
|
373
339
|
def from_nexus(
|
|
@@ -375,7 +341,9 @@ class RollingDetectorView(Detector):
|
|
|
375
341
|
*,
|
|
376
342
|
detector_name: str,
|
|
377
343
|
window: int,
|
|
378
|
-
projection: Literal['xy_plane', 'cylinder_mantle_z']
|
|
344
|
+
projection: Literal['xy_plane', 'cylinder_mantle_z']
|
|
345
|
+
| Callable[[sc.DataArray], sc.DataArray]
|
|
346
|
+
| None = None,
|
|
379
347
|
resolution: dict[str, int] | None = None,
|
|
380
348
|
pixel_noise: Literal['cylindrical'] | sc.Variable | None = None,
|
|
381
349
|
) -> RollingDetectorView:
|
|
@@ -396,10 +364,12 @@ class RollingDetectorView(Detector):
|
|
|
396
364
|
Size of the rolling window.
|
|
397
365
|
projection:
|
|
398
366
|
Projection to use for the detector data. This can be a string selecting a
|
|
399
|
-
predefined projection or a
|
|
367
|
+
predefined projection or a function that takes a DataArray and returns a
|
|
368
|
+
DataArray. The predefined projections are 'xy_plane' and
|
|
369
|
+
'cylinder_mantle_z'.
|
|
400
370
|
resolution:
|
|
401
|
-
Resolution to use for histogramming the detector data.
|
|
402
|
-
|
|
371
|
+
Resolution to use for histogramming the detector data. Only required for
|
|
372
|
+
'xy_plane' and 'cylinder_mantle_z' projections.
|
|
403
373
|
pixel_noise:
|
|
404
374
|
Noise to add to the pixel positions. This can be a scalar value to add
|
|
405
375
|
Gaussian noise to the pixel positions or the string 'cylindrical' to add
|
|
@@ -413,13 +383,7 @@ class RollingDetectorView(Detector):
|
|
|
413
383
|
noise_replica_count = 16
|
|
414
384
|
wf = GenericNeXusWorkflow(run_types=[SampleRun], monitor_types=[])
|
|
415
385
|
wf[RollingDetectorViewWindow] = window
|
|
416
|
-
if
|
|
417
|
-
wf[LogicalView] = projection
|
|
418
|
-
wf[NeXusTransformation[snx.NXdetector, SampleRun]] = NeXusTransformation[
|
|
419
|
-
snx.NXdetector, SampleRun
|
|
420
|
-
](sc.scalar(1))
|
|
421
|
-
wf.insert(RollingDetectorView.from_detector_and_logical_view)
|
|
422
|
-
elif projection == 'cylinder_mantle_z':
|
|
386
|
+
if projection == 'cylinder_mantle_z':
|
|
423
387
|
wf.insert(make_cylinder_mantle_coords)
|
|
424
388
|
wf.insert(RollingDetectorView.from_detector_and_histogrammer)
|
|
425
389
|
wf[DetectorViewResolution] = resolution
|
|
@@ -428,7 +392,12 @@ class RollingDetectorView(Detector):
|
|
|
428
392
|
wf.insert(RollingDetectorView.from_detector_and_histogrammer)
|
|
429
393
|
wf[DetectorViewResolution] = resolution
|
|
430
394
|
else:
|
|
431
|
-
|
|
395
|
+
wf[NeXusTransformation[snx.NXdetector, SampleRun]] = NeXusTransformation[
|
|
396
|
+
snx.NXdetector, SampleRun
|
|
397
|
+
](sc.scalar(1))
|
|
398
|
+
wf.insert(
|
|
399
|
+
RollingDetectorView.from_detector_with_projection(projection=projection)
|
|
400
|
+
)
|
|
432
401
|
if isinstance(pixel_noise, sc.Variable):
|
|
433
402
|
wf.insert(gaussian_position_noise)
|
|
434
403
|
wf[PositionNoiseSigma] = pixel_noise
|
ess/reduce/streaming.py
CHANGED
|
@@ -174,6 +174,64 @@ class RollingAccumulator(Accumulator[T]):
|
|
|
174
174
|
self._values = []
|
|
175
175
|
|
|
176
176
|
|
|
177
|
+
class MinAccumulator(Accumulator):
|
|
178
|
+
"""Keeps the minimum value seen so far.
|
|
179
|
+
|
|
180
|
+
Only supports scalar values.
|
|
181
|
+
"""
|
|
182
|
+
|
|
183
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
184
|
+
super().__init__(**kwargs)
|
|
185
|
+
self._cur_min: sc.Variable | None = None
|
|
186
|
+
|
|
187
|
+
def _do_push(self, value: sc.Variable) -> None:
|
|
188
|
+
if self._cur_min is None:
|
|
189
|
+
self._cur_min = value
|
|
190
|
+
else:
|
|
191
|
+
self._cur_min = min(self._cur_min, value)
|
|
192
|
+
|
|
193
|
+
@property
|
|
194
|
+
def is_empty(self) -> bool:
|
|
195
|
+
"""Check if the accumulator has collected a minimum value."""
|
|
196
|
+
return self._cur_min is None
|
|
197
|
+
|
|
198
|
+
def _get_value(self) -> Any:
|
|
199
|
+
return self._cur_min
|
|
200
|
+
|
|
201
|
+
def clear(self) -> None:
|
|
202
|
+
"""Clear the accumulated minimum value."""
|
|
203
|
+
self._cur_min = None
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
class MaxAccumulator(Accumulator):
|
|
207
|
+
"""Keeps the maximum value seen so far.
|
|
208
|
+
|
|
209
|
+
Only supports scalar values.
|
|
210
|
+
"""
|
|
211
|
+
|
|
212
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
213
|
+
super().__init__(**kwargs)
|
|
214
|
+
self._cur_max: sc.Variable | None = None
|
|
215
|
+
|
|
216
|
+
@property
|
|
217
|
+
def is_empty(self) -> bool:
|
|
218
|
+
"""Check if the accumulator has collected a maximum value."""
|
|
219
|
+
return self._cur_max is None
|
|
220
|
+
|
|
221
|
+
def _do_push(self, value: sc.Variable) -> None:
|
|
222
|
+
if self._cur_max is None:
|
|
223
|
+
self._cur_max = value
|
|
224
|
+
else:
|
|
225
|
+
self._cur_max = max(self._cur_max, value)
|
|
226
|
+
|
|
227
|
+
def _get_value(self) -> sc.Variable | None:
|
|
228
|
+
return self._cur_max
|
|
229
|
+
|
|
230
|
+
def clear(self) -> None:
|
|
231
|
+
"""Clear the accumulated maximum value."""
|
|
232
|
+
self._cur_max = None
|
|
233
|
+
|
|
234
|
+
|
|
177
235
|
class StreamProcessor:
|
|
178
236
|
"""
|
|
179
237
|
Wrap a base workflow for streaming processing of chunks.
|
|
@@ -3,12 +3,12 @@ ess/reduce/data.py,sha256=vaoeAJ6EpK1YghOiAALLdWiW17TgUnnnt0H-RGiGzXk,3756
|
|
|
3
3
|
ess/reduce/logging.py,sha256=6n8Czq4LZ3OK9ENlKsWSI1M3KvKv6_HSoUiV4__IUlU,357
|
|
4
4
|
ess/reduce/parameter.py,sha256=4sCfoKOI2HuO_Q7JLH_jAXnEOFANSn5P3NdaOBzhJxc,4635
|
|
5
5
|
ess/reduce/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
ess/reduce/streaming.py,sha256=
|
|
6
|
+
ess/reduce/streaming.py,sha256=_zFaT9vZQ4HZ1g9qbCQxetenITdqGZMPhyNNffMpGKw,13244
|
|
7
7
|
ess/reduce/ui.py,sha256=zmorAbDwX1cU3ygDT--OP58o0qU7OBcmJz03jPeYSLA,10884
|
|
8
8
|
ess/reduce/uncertainty.py,sha256=LR4O6ApB6Z-W9gC_XW0ajupl8yFG-du0eee1AX_R-gk,6990
|
|
9
9
|
ess/reduce/workflow.py,sha256=sL34T_2Cjl_8iFlegujxI9VyOUwo6erVC8pOXnfWgYw,3060
|
|
10
10
|
ess/reduce/live/__init__.py,sha256=jPQVhihRVNtEDrE20PoKkclKV2aBF1lS7cCHootgFgI,204
|
|
11
|
-
ess/reduce/live/raw.py,sha256=
|
|
11
|
+
ess/reduce/live/raw.py,sha256=hyWkDJ0WYE2TS12dVxpRUh6RkzcUJL0bVDd4JjTidi0,24217
|
|
12
12
|
ess/reduce/live/roi.py,sha256=Hs-pW98k41WU6Kl3UQ41kQawk80c2QNOQ_WNctLzDPE,3795
|
|
13
13
|
ess/reduce/live/workflow.py,sha256=bsbwvTqPhRO6mC__3b7MgU7DWwAnOvGvG-t2n22EKq8,4285
|
|
14
14
|
ess/reduce/nexus/__init__.py,sha256=59bxKkNYg8DYcSykNvH6nCa5SYchJC4SbgZEKhkNdYc,967
|
|
@@ -36,9 +36,9 @@ ess/reduce/widgets/_spinner.py,sha256=2VY4Fhfa7HMXox2O7UbofcdKsYG-AJGrsgGJB85nDX
|
|
|
36
36
|
ess/reduce/widgets/_string_widget.py,sha256=iPAdfANyXHf-nkfhgkyH6gQDklia0LebLTmwi3m-iYQ,1482
|
|
37
37
|
ess/reduce/widgets/_switchable_widget.py,sha256=fjKz99SKLhIF1BLgGVBSKKn3Lu_jYBwDYGeAjbJY3Q8,2390
|
|
38
38
|
ess/reduce/widgets/_vector_widget.py,sha256=aTaBqCFHZQhrIoX6-sSqFWCPePEW8HQt5kUio8jP1t8,1203
|
|
39
|
-
essreduce-25.
|
|
40
|
-
essreduce-25.
|
|
41
|
-
essreduce-25.
|
|
42
|
-
essreduce-25.
|
|
43
|
-
essreduce-25.
|
|
44
|
-
essreduce-25.
|
|
39
|
+
essreduce-25.3.0.dist-info/LICENSE,sha256=nVEiume4Qj6jMYfSRjHTM2jtJ4FGu0g-5Sdh7osfEYw,1553
|
|
40
|
+
essreduce-25.3.0.dist-info/METADATA,sha256=bqJ7k-jVd1zBWfYhS4mS_LFj9Ogol9Xfvrvmw4EGPjM,3708
|
|
41
|
+
essreduce-25.3.0.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
|
|
42
|
+
essreduce-25.3.0.dist-info/entry_points.txt,sha256=PMZOIYzCifHMTe4pK3HbhxUwxjFaZizYlLD0td4Isb0,66
|
|
43
|
+
essreduce-25.3.0.dist-info/top_level.txt,sha256=0JxTCgMKPLKtp14wb1-RKisQPQWX7i96innZNvHBr-s,4
|
|
44
|
+
essreduce-25.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|