essreduce 25.2.4__py3-none-any.whl → 25.2.5__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/nexus/_nexus_loader.py +9 -4
- ess/reduce/streaming.py +56 -3
- {essreduce-25.2.4.dist-info → essreduce-25.2.5.dist-info}/METADATA +1 -1
- {essreduce-25.2.4.dist-info → essreduce-25.2.5.dist-info}/RECORD +8 -8
- {essreduce-25.2.4.dist-info → essreduce-25.2.5.dist-info}/WHEEL +1 -1
- {essreduce-25.2.4.dist-info → essreduce-25.2.5.dist-info}/LICENSE +0 -0
- {essreduce-25.2.4.dist-info → essreduce-25.2.5.dist-info}/entry_points.txt +0 -0
- {essreduce-25.2.4.dist-info → essreduce-25.2.5.dist-info}/top_level.txt +0 -0
|
@@ -180,10 +180,15 @@ def _attempt_to_open_without_locking(
|
|
|
180
180
|
# HDF5 tracks file locking flags internally within a single process.
|
|
181
181
|
# If the same file is opened multiple times, we can get a flag mismatch.
|
|
182
182
|
# We can try opening without locking, maybe this matches the original flags.
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
183
|
+
error_message = err.args[0]
|
|
184
|
+
if isinstance(error_message, str):
|
|
185
|
+
if "file locking flag values don't match" in error_message:
|
|
186
|
+
return True
|
|
187
|
+
if (
|
|
188
|
+
"file locking 'ignore disabled locks' flag values don't match"
|
|
189
|
+
in error_message
|
|
190
|
+
):
|
|
191
|
+
return True
|
|
187
192
|
return False
|
|
188
193
|
|
|
189
194
|
|
ess/reduce/streaming.py
CHANGED
|
@@ -68,7 +68,18 @@ class Accumulator(ABC, Generic[T]):
|
|
|
68
68
|
def _do_push(self, value: T) -> None: ...
|
|
69
69
|
|
|
70
70
|
@property
|
|
71
|
-
|
|
71
|
+
def is_empty(self) -> bool:
|
|
72
|
+
"""
|
|
73
|
+
Check if the accumulator is empty.
|
|
74
|
+
|
|
75
|
+
Returns
|
|
76
|
+
-------
|
|
77
|
+
:
|
|
78
|
+
True if the accumulator is empty, False otherwise.
|
|
79
|
+
"""
|
|
80
|
+
return False
|
|
81
|
+
|
|
82
|
+
@property
|
|
72
83
|
def value(self) -> T:
|
|
73
84
|
"""
|
|
74
85
|
Get the accumulated value.
|
|
@@ -77,6 +88,24 @@ class Accumulator(ABC, Generic[T]):
|
|
|
77
88
|
-------
|
|
78
89
|
:
|
|
79
90
|
Accumulated value.
|
|
91
|
+
|
|
92
|
+
Raises
|
|
93
|
+
------
|
|
94
|
+
ValueError
|
|
95
|
+
If the accumulator is empty.
|
|
96
|
+
"""
|
|
97
|
+
if self.is_empty:
|
|
98
|
+
raise ValueError("Cannot get value from empty accumulator")
|
|
99
|
+
return self._get_value()
|
|
100
|
+
|
|
101
|
+
@abstractmethod
|
|
102
|
+
def _get_value(self) -> T:
|
|
103
|
+
"""Return the accumulated value, assuming it exists."""
|
|
104
|
+
|
|
105
|
+
@abstractmethod
|
|
106
|
+
def clear(self) -> None:
|
|
107
|
+
"""
|
|
108
|
+
Clear the accumulator, resetting it to its initial state.
|
|
80
109
|
"""
|
|
81
110
|
|
|
82
111
|
|
|
@@ -92,7 +121,10 @@ class EternalAccumulator(Accumulator[T]):
|
|
|
92
121
|
self._value: T | None = None
|
|
93
122
|
|
|
94
123
|
@property
|
|
95
|
-
def
|
|
124
|
+
def is_empty(self) -> bool:
|
|
125
|
+
return self._value is None
|
|
126
|
+
|
|
127
|
+
def _get_value(self) -> T:
|
|
96
128
|
return deepcopy(self._value)
|
|
97
129
|
|
|
98
130
|
def _do_push(self, value: T) -> None:
|
|
@@ -101,6 +133,10 @@ class EternalAccumulator(Accumulator[T]):
|
|
|
101
133
|
else:
|
|
102
134
|
self._value += value
|
|
103
135
|
|
|
136
|
+
def clear(self) -> None:
|
|
137
|
+
"""Clear the accumulated value."""
|
|
138
|
+
self._value = None
|
|
139
|
+
|
|
104
140
|
|
|
105
141
|
class RollingAccumulator(Accumulator[T]):
|
|
106
142
|
"""
|
|
@@ -121,7 +157,10 @@ class RollingAccumulator(Accumulator[T]):
|
|
|
121
157
|
self._values: list[T] = []
|
|
122
158
|
|
|
123
159
|
@property
|
|
124
|
-
def
|
|
160
|
+
def is_empty(self) -> bool:
|
|
161
|
+
return len(self._values) == 0
|
|
162
|
+
|
|
163
|
+
def _get_value(self) -> T:
|
|
125
164
|
# Naive and potentially slow implementation if values and/or window are large!
|
|
126
165
|
return sc.reduce(self._values).sum()
|
|
127
166
|
|
|
@@ -130,6 +169,10 @@ class RollingAccumulator(Accumulator[T]):
|
|
|
130
169
|
if len(self._values) > self._window:
|
|
131
170
|
self._values.pop(0)
|
|
132
171
|
|
|
172
|
+
def clear(self) -> None:
|
|
173
|
+
"""Clear the accumulated values."""
|
|
174
|
+
self._values = []
|
|
175
|
+
|
|
133
176
|
|
|
134
177
|
class StreamProcessor:
|
|
135
178
|
"""
|
|
@@ -299,6 +342,16 @@ class StreamProcessor:
|
|
|
299
342
|
self._finalize_workflow[key] = self._accumulators[key].value
|
|
300
343
|
return self._finalize_workflow.compute(self._target_keys)
|
|
301
344
|
|
|
345
|
+
def clear(self) -> None:
|
|
346
|
+
"""
|
|
347
|
+
Clear all accumulators, resetting them to their initial state.
|
|
348
|
+
|
|
349
|
+
This is useful for restarting a streaming computation without
|
|
350
|
+
creating a new StreamProcessor instance.
|
|
351
|
+
"""
|
|
352
|
+
for accumulator in self._accumulators.values():
|
|
353
|
+
accumulator.clear()
|
|
354
|
+
|
|
302
355
|
|
|
303
356
|
def _find_descendants(
|
|
304
357
|
workflow: sciline.Pipeline, keys: tuple[sciline.typing.Key, ...]
|
|
@@ -3,7 +3,7 @@ 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=XNUr5Vg8lufBqjTjjzd0nfiRR2f70zkTixXkG_O26Bk,11687
|
|
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
|
|
@@ -12,7 +12,7 @@ ess/reduce/live/raw.py,sha256=pzXsPZQERtUm5tabTXjxd-XHH4WDDP13TTBG0lGPcqg,25262
|
|
|
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
|
|
15
|
-
ess/reduce/nexus/_nexus_loader.py,sha256=
|
|
15
|
+
ess/reduce/nexus/_nexus_loader.py,sha256=NpBTBjWLKSnW0B1EarFdt2QxV0X7QBQLk2dSJq2ZuOw,19847
|
|
16
16
|
ess/reduce/nexus/json_generator.py,sha256=ME2Xn8L7Oi3uHJk9ZZdCRQTRX-OV_wh9-DJn07Alplk,2529
|
|
17
17
|
ess/reduce/nexus/json_nexus.py,sha256=QrVc0p424nZ5dHX9gebAJppTw6lGZq9404P_OFl1giA,10282
|
|
18
18
|
ess/reduce/nexus/types.py,sha256=15XcHbNbOfnAYjWXzzKyYDVNyNixRnP0hJ-Q2duwMWE,9896
|
|
@@ -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.2.
|
|
40
|
-
essreduce-25.2.
|
|
41
|
-
essreduce-25.2.
|
|
42
|
-
essreduce-25.2.
|
|
43
|
-
essreduce-25.2.
|
|
44
|
-
essreduce-25.2.
|
|
39
|
+
essreduce-25.2.5.dist-info/LICENSE,sha256=nVEiume4Qj6jMYfSRjHTM2jtJ4FGu0g-5Sdh7osfEYw,1553
|
|
40
|
+
essreduce-25.2.5.dist-info/METADATA,sha256=ri1OfgsTeyU-LR2NMBoAB5zJXLCRAl72qkND7TbOf5M,3708
|
|
41
|
+
essreduce-25.2.5.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
|
|
42
|
+
essreduce-25.2.5.dist-info/entry_points.txt,sha256=PMZOIYzCifHMTe4pK3HbhxUwxjFaZizYlLD0td4Isb0,66
|
|
43
|
+
essreduce-25.2.5.dist-info/top_level.txt,sha256=0JxTCgMKPLKtp14wb1-RKisQPQWX7i96innZNvHBr-s,4
|
|
44
|
+
essreduce-25.2.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|