essreduce 24.12.0__py3-none-any.whl → 25.1.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/__init__.py +2 -2
- ess/reduce/live/raw.py +14 -1
- ess/reduce/nexus/_nexus_loader.py +38 -2
- ess/reduce/nexus/types.py +25 -0
- ess/reduce/time_of_flight/__init__.py +61 -0
- ess/reduce/time_of_flight/fakes.py +240 -0
- ess/reduce/time_of_flight/simulation.py +74 -0
- ess/reduce/time_of_flight/to_events.py +106 -0
- ess/reduce/time_of_flight/toa_to_tof.py +541 -0
- ess/reduce/time_of_flight/types.py +176 -0
- ess/reduce/ui.py +3 -1
- ess/reduce/widgets/__init__.py +2 -0
- ess/reduce/widgets/_base.py +85 -21
- ess/reduce/widgets/_optional_widget.py +24 -0
- ess/reduce/widgets/_spinner.py +100 -0
- ess/reduce/widgets/_switchable_widget.py +15 -0
- {essreduce-24.12.0.dist-info → essreduce-25.1.1.dist-info}/METADATA +5 -3
- essreduce-25.1.1.dist-info/RECORD +43 -0
- {essreduce-24.12.0.dist-info → essreduce-25.1.1.dist-info}/WHEEL +1 -1
- essreduce-24.12.0.dist-info/RECORD +0 -36
- {essreduce-24.12.0.dist-info → essreduce-25.1.1.dist-info}/LICENSE +0 -0
- {essreduce-24.12.0.dist-info → essreduce-25.1.1.dist-info}/entry_points.txt +0 -0
- {essreduce-24.12.0.dist-info → essreduce-25.1.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
# Copyright (c) 2025 Scipp contributors (https://github.com/scipp)
|
|
3
|
+
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import NewType
|
|
6
|
+
|
|
7
|
+
import scipp as sc
|
|
8
|
+
|
|
9
|
+
Ltotal = NewType("Ltotal", sc.Variable)
|
|
10
|
+
"""
|
|
11
|
+
Total length of the flight path from the source to the detector.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class SimulationResults:
|
|
17
|
+
"""
|
|
18
|
+
Results of a time-of-flight simulation used to create a lookup table.
|
|
19
|
+
|
|
20
|
+
The results (apart from ``distance``) should be flat lists (1d arrays) of length N
|
|
21
|
+
where N is the number of neutrons, containing the properties of the neutrons in the
|
|
22
|
+
simulation.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
time_of_arrival:
|
|
27
|
+
Time of arrival of the neutrons at the position where the events were recorded
|
|
28
|
+
(1d array of size N).
|
|
29
|
+
speed:
|
|
30
|
+
Speed of the neutrons, typically derived from the wavelength of the neutrons
|
|
31
|
+
(1d array of size N).
|
|
32
|
+
wavelength:
|
|
33
|
+
Wavelength of the neutrons (1d array of size N).
|
|
34
|
+
weight:
|
|
35
|
+
Weight/probability of the neutrons (1d array of size N).
|
|
36
|
+
distance:
|
|
37
|
+
Distance from the source to the position where the events were recorded
|
|
38
|
+
(single value; we assume all neutrons were recorded at the same position).
|
|
39
|
+
For a ``tof`` simulation, this is just the position of the detector where the
|
|
40
|
+
events are recorded. For a ``McStas`` simulation, this is the distance between
|
|
41
|
+
the source and the event monitor.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
time_of_arrival: sc.Variable
|
|
45
|
+
speed: sc.Variable
|
|
46
|
+
wavelength: sc.Variable
|
|
47
|
+
weight: sc.Variable
|
|
48
|
+
distance: sc.Variable
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclass
|
|
52
|
+
class FastestNeutron:
|
|
53
|
+
"""
|
|
54
|
+
Properties of the fastest neutron in the simulation results.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
time_of_arrival: sc.Variable
|
|
58
|
+
speed: sc.Variable
|
|
59
|
+
distance: sc.Variable
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
LtotalRange = NewType("LtotalRange", tuple[sc.Variable, sc.Variable])
|
|
63
|
+
"""
|
|
64
|
+
Range (min, max) of the total length of the flight path from the source to the detector.
|
|
65
|
+
This is used to create the lookup table to compute the neutron time-of-flight.
|
|
66
|
+
Note that the resulting table will extend slightly beyond this range, as the supplied
|
|
67
|
+
range is not necessarily a multiple of the distance resolution.
|
|
68
|
+
|
|
69
|
+
Note also that the range of total flight paths is supplied manually to the workflow
|
|
70
|
+
instead of being read from the input data, as it allows us to compute the expensive part
|
|
71
|
+
of the workflow in advance (the lookup table) and does not need to be repeated for each
|
|
72
|
+
run, or for new data coming in in the case of live data collection.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
DistanceResolution = NewType("DistanceResolution", sc.Variable)
|
|
76
|
+
"""
|
|
77
|
+
Step size of the distance axis in the lookup table.
|
|
78
|
+
Should be a single scalar value with a unit of length.
|
|
79
|
+
This is typically of the order of 1-10 cm.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
TimeOfArrivalResolution = NewType("TimeOfArrivalResolution", int | sc.Variable)
|
|
83
|
+
"""
|
|
84
|
+
Resolution of the time of arrival axis in the lookup table.
|
|
85
|
+
Can be an integer (number of bins) or a sc.Variable (bin width).
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
TimeOfFlightLookupTable = NewType("TimeOfFlightLookupTable", sc.DataArray)
|
|
89
|
+
"""
|
|
90
|
+
Lookup table giving time-of-flight as a function of distance and time of arrival.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
MaskedTimeOfFlightLookupTable = NewType("MaskedTimeOfFlightLookupTable", sc.DataArray)
|
|
94
|
+
"""
|
|
95
|
+
Lookup table giving time-of-flight as a function of distance and time of arrival, with
|
|
96
|
+
regions of large uncertainty masked out.
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
LookupTableRelativeErrorThreshold = NewType("LookupTableRelativeErrorThreshold", float)
|
|
100
|
+
|
|
101
|
+
FramePeriod = NewType("FramePeriod", sc.Variable)
|
|
102
|
+
"""
|
|
103
|
+
The period of a frame, a (small) integer multiple of the source period.
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
UnwrappedTimeOfArrival = NewType("UnwrappedTimeOfArrival", sc.Variable)
|
|
107
|
+
"""
|
|
108
|
+
Time of arrival of the neutron at the detector, unwrapped at the pulse period.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
PivotTimeAtDetector = NewType("PivotTimeAtDetector", sc.Variable)
|
|
112
|
+
"""
|
|
113
|
+
Pivot time at the detector, i.e., the time of the start of the frame at the detector.
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
UnwrappedTimeOfArrivalMinusPivotTime = NewType(
|
|
117
|
+
"UnwrappedTimeOfArrivalMinusPivotTime", sc.Variable
|
|
118
|
+
)
|
|
119
|
+
"""
|
|
120
|
+
Time of arrival of the neutron at the detector, unwrapped at the pulse period, minus
|
|
121
|
+
the start time of the frame.
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
TimeOfArrivalMinusPivotTimeModuloPeriod = NewType(
|
|
125
|
+
"TimeOfArrivalMinusPivotTimeModuloPeriod", sc.Variable
|
|
126
|
+
)
|
|
127
|
+
"""
|
|
128
|
+
Time of arrival of the neutron at the detector minus the start time of the frame,
|
|
129
|
+
modulo the frame period.
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
FrameFoldedTimeOfArrival = NewType("FrameFoldedTimeOfArrival", sc.Variable)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
PulsePeriod = NewType("PulsePeriod", sc.Variable)
|
|
136
|
+
"""
|
|
137
|
+
Period of the source pulses, i.e., time between consecutive pulse starts.
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
PulseStride = NewType("PulseStride", int)
|
|
141
|
+
"""
|
|
142
|
+
Stride of used pulses. Usually 1, but may be a small integer when pulse-skipping.
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
PulseStrideOffset = NewType("PulseStrideOffset", int)
|
|
146
|
+
"""
|
|
147
|
+
When pulse-skipping, the offset of the first pulse in the stride.
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
RawData = NewType("RawData", sc.DataArray)
|
|
151
|
+
"""
|
|
152
|
+
Raw detector data loaded from a NeXus file, e.g., NXdetector containing NXevent_data.
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
TofData = NewType("TofData", sc.DataArray)
|
|
156
|
+
"""
|
|
157
|
+
Detector data with time-of-flight coordinate.
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
ResampledTofData = NewType("ResampledTofData", sc.DataArray)
|
|
161
|
+
"""
|
|
162
|
+
Histogrammed detector data with time-of-flight coordinate, that has been resampled.
|
|
163
|
+
|
|
164
|
+
Histogrammed data that has been converted to `tof` will typically have
|
|
165
|
+
unsorted bin edges (due to either wrapping of `time_of_flight` or wavelength
|
|
166
|
+
overlap between subframes).
|
|
167
|
+
We thus resample the data to ensure that the bin edges are sorted.
|
|
168
|
+
It makes use of the ``to_events`` helper which generates a number of events in each
|
|
169
|
+
bin with a uniform distribution. The new events are then histogrammed using a set of
|
|
170
|
+
sorted bin edges to yield a new histogram with sorted bin edges.
|
|
171
|
+
|
|
172
|
+
WARNING:
|
|
173
|
+
This function is highly experimental, has limitations and should be used with
|
|
174
|
+
caution. It is a workaround to the issue that rebinning data with unsorted bin
|
|
175
|
+
edges is not supported in scipp.
|
|
176
|
+
"""
|
ess/reduce/ui.py
CHANGED
|
@@ -9,7 +9,7 @@ from IPython import display
|
|
|
9
9
|
from ipywidgets import Layout
|
|
10
10
|
|
|
11
11
|
from .parameter import Parameter
|
|
12
|
-
from .widgets import SwitchWidget, create_parameter_widget, default_layout
|
|
12
|
+
from .widgets import Spinner, SwitchWidget, create_parameter_widget, default_layout
|
|
13
13
|
from .widgets._base import get_fields, set_fields
|
|
14
14
|
from .workflow import (
|
|
15
15
|
Key,
|
|
@@ -127,7 +127,9 @@ class ResultBox(widgets.VBox):
|
|
|
127
127
|
def run_workflow(_: widgets.Button) -> None:
|
|
128
128
|
self.output.clear_output()
|
|
129
129
|
with self.output:
|
|
130
|
+
display.display(Spinner())
|
|
130
131
|
compute_result = workflow_runner()
|
|
132
|
+
display.clear_output()
|
|
131
133
|
if result_registry is not None:
|
|
132
134
|
result_registry.clear()
|
|
133
135
|
result_registry.update(compute_result)
|
ess/reduce/widgets/__init__.py
CHANGED
|
@@ -29,6 +29,7 @@ from ._bounds_widget import BoundsWidget
|
|
|
29
29
|
from ._string_widget import MultiStringWidget, StringWidget
|
|
30
30
|
from ._switchable_widget import SwitchWidget
|
|
31
31
|
from ._optional_widget import OptionalWidget
|
|
32
|
+
from ._spinner import Spinner
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
class EssWidget(Protocol):
|
|
@@ -191,4 +192,5 @@ __all__ = [
|
|
|
191
192
|
'SwitchWidget',
|
|
192
193
|
'VectorWidget',
|
|
193
194
|
'create_parameter_widget',
|
|
195
|
+
'Spinner',
|
|
194
196
|
]
|
ess/reduce/widgets/_base.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
2
2
|
# Copyright (c) 2024 Scipp contributors (https://github.com/scipp)
|
|
3
3
|
import warnings
|
|
4
|
+
from collections.abc import Iterable
|
|
4
5
|
from typing import Any, Protocol, runtime_checkable
|
|
5
6
|
|
|
6
7
|
from ipywidgets import Widget
|
|
@@ -13,6 +14,14 @@ class WidgetWithFieldsProtocol(Protocol):
|
|
|
13
14
|
def get_fields(self) -> dict[str, Any]: ...
|
|
14
15
|
|
|
15
16
|
|
|
17
|
+
def _warn_invalid_field(invalid_fields: Iterable[str]) -> None:
|
|
18
|
+
for field_name in invalid_fields:
|
|
19
|
+
warning_msg = f"Cannot set field '{field_name}'."
|
|
20
|
+
" The field does not exist in the widget."
|
|
21
|
+
"The field value will be ignored."
|
|
22
|
+
warnings.warn(warning_msg, UserWarning, stacklevel=2)
|
|
23
|
+
|
|
24
|
+
|
|
16
25
|
class WidgetWithFieldsMixin:
|
|
17
26
|
def set_fields(self, new_values: dict[str, Any]) -> None:
|
|
18
27
|
# Extract valid fields
|
|
@@ -20,11 +29,7 @@ class WidgetWithFieldsMixin:
|
|
|
20
29
|
valid_field_names = new_field_names & set(self.fields.keys())
|
|
21
30
|
# Warn for invalid fields
|
|
22
31
|
invalid_field_names = new_field_names - valid_field_names
|
|
23
|
-
|
|
24
|
-
warning_msg = f"Cannot set field '{field_name}'."
|
|
25
|
-
" The field does not exist in the widget."
|
|
26
|
-
"The field value will be ignored."
|
|
27
|
-
warnings.warn(warning_msg, UserWarning, stacklevel=1)
|
|
32
|
+
_warn_invalid_field(invalid_field_names)
|
|
28
33
|
# Set valid fields
|
|
29
34
|
for field_name in valid_field_names:
|
|
30
35
|
self.fields[field_name].value = new_values[field_name]
|
|
@@ -36,28 +41,87 @@ class WidgetWithFieldsMixin:
|
|
|
36
41
|
}
|
|
37
42
|
|
|
38
43
|
|
|
39
|
-
def
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
def set_fields(widget: Widget, new_values: dict[str, Any]) -> None:
|
|
45
|
+
"""Set the fields of a widget with the given values.
|
|
46
|
+
|
|
47
|
+
Parameters
|
|
48
|
+
----------
|
|
49
|
+
widget:
|
|
50
|
+
The widget to set the fields. It should either be an instance of
|
|
51
|
+
``WidgetWithFieldsProtocol`` or have a value property setter.
|
|
52
|
+
new_values:
|
|
53
|
+
The new values to set for the fields.
|
|
54
|
+
i.e. ``{'field_name': field_value}``
|
|
55
|
+
If the widget does not have a ``set_fields/get_fields`` method,
|
|
56
|
+
(e.g. it is not an instance of ``WidgetWithFieldsProtocol``),
|
|
57
|
+
it will try to set the value of the widget directly.
|
|
58
|
+
The value of the widget should be available in the ``new_values`` dictionary
|
|
59
|
+
with the key 'value'.
|
|
60
|
+
i.e. ``{'value': widget_value}``
|
|
61
|
+
|
|
62
|
+
Raises
|
|
63
|
+
------
|
|
64
|
+
TypeError:
|
|
65
|
+
If ``new_values`` is not a dictionary.
|
|
44
66
|
|
|
67
|
+
"""
|
|
68
|
+
if not isinstance(new_values, dict):
|
|
69
|
+
raise TypeError(f"new_values must be a dictionary, got {type(new_values)}")
|
|
45
70
|
|
|
46
|
-
def set_fields(widget: Widget, new_values: Any) -> None:
|
|
47
71
|
if isinstance(widget, WidgetWithFieldsProtocol) and isinstance(new_values, dict):
|
|
48
72
|
widget.set_fields(new_values)
|
|
49
|
-
elif _has_widget_value_setter(widget):
|
|
50
|
-
widget.value = new_values
|
|
51
73
|
else:
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
74
|
+
try:
|
|
75
|
+
# Use value property setter if ``new_values`` contains 'value'
|
|
76
|
+
if 'value' in new_values:
|
|
77
|
+
widget.value = new_values['value']
|
|
78
|
+
# Warn if there is any other fields in new_values
|
|
79
|
+
_warn_invalid_field(set(new_values.keys()) - {'value'})
|
|
80
|
+
except AttributeError as error:
|
|
81
|
+
# Checking if the widget value property has a setter in advance, i.e.
|
|
82
|
+
# ```python
|
|
83
|
+
# (widget_property := getattr(type(widget), 'value', None)) is not None
|
|
84
|
+
# and getattr(widget_property, 'fset', None) is not None
|
|
85
|
+
# ```
|
|
86
|
+
# does not work with a class that inherits Traitlets class.
|
|
87
|
+
# In those classes, even if a property has a setter,
|
|
88
|
+
# it may not have `fset` attribute.
|
|
89
|
+
# It is not really feasible to check all possible cases of value setters.
|
|
90
|
+
# Instead, we try setting the value and catch the AttributeError.
|
|
91
|
+
# to determine if the widget has a value setter.
|
|
92
|
+
warnings.warn(
|
|
93
|
+
f"Cannot set value for widget of type {type(widget)}."
|
|
94
|
+
" The new_value(s) will be ignored."
|
|
95
|
+
f" Setting value caused the following error: {error}",
|
|
96
|
+
UserWarning,
|
|
97
|
+
stacklevel=1,
|
|
98
|
+
)
|
|
58
99
|
|
|
59
100
|
|
|
60
|
-
def get_fields(widget: Widget) -> Any:
|
|
101
|
+
def get_fields(widget: Widget) -> dict[str, Any] | None:
|
|
102
|
+
"""Get the fields of a widget.
|
|
103
|
+
|
|
104
|
+
If the widget is an instance of ``WidgetWithFieldsProtocol``,
|
|
105
|
+
it will return the fields of the widget.
|
|
106
|
+
i.e. ``{'field_name': field_value}``
|
|
107
|
+
Otherwise, it will try to get the value of the widget and return a dictionary
|
|
108
|
+
with the key 'value' and the value of the widget.
|
|
109
|
+
i.e. ``{'value': widget_value}``
|
|
110
|
+
|
|
111
|
+
Parameters
|
|
112
|
+
----------
|
|
113
|
+
widget:
|
|
114
|
+
The widget to get the fields. It should either be an instance of
|
|
115
|
+
``WidgetWithFieldsProtocol`` or have a value property.
|
|
116
|
+
|
|
117
|
+
"""
|
|
61
118
|
if isinstance(widget, WidgetWithFieldsProtocol):
|
|
62
119
|
return widget.get_fields()
|
|
63
|
-
|
|
120
|
+
try:
|
|
121
|
+
return {'value': widget.value}
|
|
122
|
+
except AttributeError:
|
|
123
|
+
warnings.warn(
|
|
124
|
+
f"Cannot get value or fields for widget of type {type(widget)}.",
|
|
125
|
+
UserWarning,
|
|
126
|
+
stacklevel=1,
|
|
127
|
+
)
|
|
@@ -4,6 +4,7 @@ from typing import Any
|
|
|
4
4
|
|
|
5
5
|
from ipywidgets import HTML, HBox, Layout, RadioButtons, Widget
|
|
6
6
|
|
|
7
|
+
from ._base import get_fields, set_fields
|
|
7
8
|
from ._config import default_style
|
|
8
9
|
|
|
9
10
|
|
|
@@ -64,3 +65,26 @@ class OptionalWidget(HBox):
|
|
|
64
65
|
else:
|
|
65
66
|
self._option_box.value = self.name
|
|
66
67
|
self.wrapped.value = value
|
|
68
|
+
|
|
69
|
+
def set_fields(self, new_values: dict[str, Any]) -> None:
|
|
70
|
+
new_values = dict(new_values)
|
|
71
|
+
# Set the value of the option box
|
|
72
|
+
opted_out_flag = new_values.pop(
|
|
73
|
+
# We assume ``essreduce-opted-out`` is not used in any wrapped widget
|
|
74
|
+
'essreduce-opted-out',
|
|
75
|
+
self._option_box.value is None,
|
|
76
|
+
)
|
|
77
|
+
if not isinstance(opted_out_flag, bool):
|
|
78
|
+
raise ValueError(
|
|
79
|
+
f"Invalid value for 'essreduce-opted-out' field: {opted_out_flag}."
|
|
80
|
+
" The value should be a boolean."
|
|
81
|
+
)
|
|
82
|
+
self._option_box.value = None if opted_out_flag else self.name
|
|
83
|
+
# Set the value of the wrapped widget
|
|
84
|
+
set_fields(self.wrapped, new_values)
|
|
85
|
+
|
|
86
|
+
def get_fields(self) -> dict[str, Any] | None:
|
|
87
|
+
return {
|
|
88
|
+
**(get_fields(self.wrapped) or {}),
|
|
89
|
+
'essreduce-opted-out': self._option_box.value is None,
|
|
90
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
_spinner = '''
|
|
2
|
+
<style>
|
|
3
|
+
.lds-spinner {
|
|
4
|
+
/* change color here */
|
|
5
|
+
color: #1c4c5b
|
|
6
|
+
}
|
|
7
|
+
.lds-spinner,
|
|
8
|
+
.lds-spinner div,
|
|
9
|
+
.lds-spinner div:after {
|
|
10
|
+
box-sizing: border-box;
|
|
11
|
+
}
|
|
12
|
+
.lds-spinner {
|
|
13
|
+
color: currentColor;
|
|
14
|
+
display: inline-block;
|
|
15
|
+
position: relative;
|
|
16
|
+
width: 80px;
|
|
17
|
+
height: 80px;
|
|
18
|
+
}
|
|
19
|
+
.lds-spinner div {
|
|
20
|
+
transform-origin: 40px 40px;
|
|
21
|
+
animation: lds-spinner 1.2s linear infinite;
|
|
22
|
+
}
|
|
23
|
+
.lds-spinner div:after {
|
|
24
|
+
content: " ";
|
|
25
|
+
display: block;
|
|
26
|
+
position: absolute;
|
|
27
|
+
top: 3.2px;
|
|
28
|
+
left: 36.8px;
|
|
29
|
+
width: 6.4px;
|
|
30
|
+
height: 17.6px;
|
|
31
|
+
border-radius: 20%;
|
|
32
|
+
background: currentColor;
|
|
33
|
+
}
|
|
34
|
+
.lds-spinner div:nth-child(1) {
|
|
35
|
+
transform: rotate(0deg);
|
|
36
|
+
animation-delay: -1.1s;
|
|
37
|
+
}
|
|
38
|
+
.lds-spinner div:nth-child(2) {
|
|
39
|
+
transform: rotate(30deg);
|
|
40
|
+
animation-delay: -1s;
|
|
41
|
+
}
|
|
42
|
+
.lds-spinner div:nth-child(3) {
|
|
43
|
+
transform: rotate(60deg);
|
|
44
|
+
animation-delay: -0.9s;
|
|
45
|
+
}
|
|
46
|
+
.lds-spinner div:nth-child(4) {
|
|
47
|
+
transform: rotate(90deg);
|
|
48
|
+
animation-delay: -0.8s;
|
|
49
|
+
}
|
|
50
|
+
.lds-spinner div:nth-child(5) {
|
|
51
|
+
transform: rotate(120deg);
|
|
52
|
+
animation-delay: -0.7s;
|
|
53
|
+
}
|
|
54
|
+
.lds-spinner div:nth-child(6) {
|
|
55
|
+
transform: rotate(150deg);
|
|
56
|
+
animation-delay: -0.6s;
|
|
57
|
+
}
|
|
58
|
+
.lds-spinner div:nth-child(7) {
|
|
59
|
+
transform: rotate(180deg);
|
|
60
|
+
animation-delay: -0.5s;
|
|
61
|
+
}
|
|
62
|
+
.lds-spinner div:nth-child(8) {
|
|
63
|
+
transform: rotate(210deg);
|
|
64
|
+
animation-delay: -0.4s;
|
|
65
|
+
}
|
|
66
|
+
.lds-spinner div:nth-child(9) {
|
|
67
|
+
transform: rotate(240deg);
|
|
68
|
+
animation-delay: -0.3s;
|
|
69
|
+
}
|
|
70
|
+
.lds-spinner div:nth-child(10) {
|
|
71
|
+
transform: rotate(270deg);
|
|
72
|
+
animation-delay: -0.2s;
|
|
73
|
+
}
|
|
74
|
+
.lds-spinner div:nth-child(11) {
|
|
75
|
+
transform: rotate(300deg);
|
|
76
|
+
animation-delay: -0.1s;
|
|
77
|
+
}
|
|
78
|
+
.lds-spinner div:nth-child(12) {
|
|
79
|
+
transform: rotate(330deg);
|
|
80
|
+
animation-delay: 0s;
|
|
81
|
+
}
|
|
82
|
+
@keyframes lds-spinner {
|
|
83
|
+
0% {
|
|
84
|
+
opacity: 1;
|
|
85
|
+
}
|
|
86
|
+
100% {
|
|
87
|
+
opacity: 0;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
</style>
|
|
91
|
+
<div class="lds-spinner"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>
|
|
92
|
+
''' # noqa: E501
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class Spinner:
|
|
96
|
+
def _repr_html_(self, *args, **kwargs):
|
|
97
|
+
return _spinner
|
|
98
|
+
|
|
99
|
+
def _repr_pretty_(self, *args, **kwargs):
|
|
100
|
+
return '...in progress'
|
|
@@ -4,6 +4,7 @@ from typing import Any
|
|
|
4
4
|
|
|
5
5
|
from ipywidgets import Checkbox, HBox, Label, Stack, Widget
|
|
6
6
|
|
|
7
|
+
from ._base import get_fields, set_fields
|
|
7
8
|
from ._config import default_style
|
|
8
9
|
|
|
9
10
|
|
|
@@ -49,3 +50,17 @@ class SwitchWidget(HBox):
|
|
|
49
50
|
@value.setter
|
|
50
51
|
def value(self, value: Any) -> None:
|
|
51
52
|
self.wrapped.value = value
|
|
53
|
+
|
|
54
|
+
def set_fields(self, new_values: dict[str, Any]) -> None:
|
|
55
|
+
# Retrieve and set the enabled flag first
|
|
56
|
+
new_values = dict(new_values)
|
|
57
|
+
enabled_flag = new_values.pop('enabled', self.enabled)
|
|
58
|
+
if not isinstance(enabled_flag, bool):
|
|
59
|
+
raise ValueError(f"`enabled` must be a boolean, got {enabled_flag}")
|
|
60
|
+
self.enabled = enabled_flag
|
|
61
|
+
# Set the rest of the fields
|
|
62
|
+
set_fields(self.wrapped, new_values)
|
|
63
|
+
|
|
64
|
+
def get_fields(self) -> dict[str, Any]:
|
|
65
|
+
wrapped_fields = get_fields(self.wrapped)
|
|
66
|
+
return {'enabled': self.enabled, **(wrapped_fields or {})}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: essreduce
|
|
3
|
-
Version:
|
|
3
|
+
Version: 25.1.1
|
|
4
4
|
Summary: Common data reduction tools for the ESS facility
|
|
5
5
|
Author: Scipp contributors
|
|
6
6
|
License: BSD 3-Clause License
|
|
@@ -52,13 +52,15 @@ Requires-Python: >=3.10
|
|
|
52
52
|
Description-Content-Type: text/markdown
|
|
53
53
|
License-File: LICENSE
|
|
54
54
|
Requires-Dist: sciline>=24.06.2
|
|
55
|
-
Requires-Dist: scipp>=
|
|
55
|
+
Requires-Dist: scipp>=25.01.0
|
|
56
56
|
Requires-Dist: scippneutron>=24.11.0
|
|
57
57
|
Requires-Dist: scippnexus>=24.11.0
|
|
58
58
|
Provides-Extra: test
|
|
59
59
|
Requires-Dist: ipywidgets; extra == "test"
|
|
60
60
|
Requires-Dist: pooch; extra == "test"
|
|
61
61
|
Requires-Dist: pytest; extra == "test"
|
|
62
|
+
Requires-Dist: scipy>=1.7.0; extra == "test"
|
|
63
|
+
Requires-Dist: tof>=25.01.2; extra == "test"
|
|
62
64
|
|
|
63
65
|
[](CODE_OF_CONDUCT.md)
|
|
64
66
|
[](https://pypi.python.org/pypi/essreduce)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
ess/reduce/__init__.py,sha256=UPoVUoZ4oVwNLcAkkkCvc78hV3R8v9Q8oCxykp9WH4s,416
|
|
2
|
+
ess/reduce/data.py,sha256=vaoeAJ6EpK1YghOiAALLdWiW17TgUnnnt0H-RGiGzXk,3756
|
|
3
|
+
ess/reduce/logging.py,sha256=6n8Czq4LZ3OK9ENlKsWSI1M3KvKv6_HSoUiV4__IUlU,357
|
|
4
|
+
ess/reduce/parameter.py,sha256=4sCfoKOI2HuO_Q7JLH_jAXnEOFANSn5P3NdaOBzhJxc,4635
|
|
5
|
+
ess/reduce/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
ess/reduce/streaming.py,sha256=nEO1Xg6LbQ36F44UaVmSNe2MSWmpwz97y9tnlc-z0zA,7493
|
|
7
|
+
ess/reduce/ui.py,sha256=zmorAbDwX1cU3ygDT--OP58o0qU7OBcmJz03jPeYSLA,10884
|
|
8
|
+
ess/reduce/uncertainty.py,sha256=LR4O6ApB6Z-W9gC_XW0ajupl8yFG-du0eee1AX_R-gk,6990
|
|
9
|
+
ess/reduce/workflow.py,sha256=sL34T_2Cjl_8iFlegujxI9VyOUwo6erVC8pOXnfWgYw,3060
|
|
10
|
+
ess/reduce/live/__init__.py,sha256=jPQVhihRVNtEDrE20PoKkclKV2aBF1lS7cCHootgFgI,204
|
|
11
|
+
ess/reduce/live/raw.py,sha256=W9fv0zaRqC6PFB5DYGAI1BK-zMgX73h5JHANKu-sMl4,19438
|
|
12
|
+
ess/reduce/live/workflow.py,sha256=bsbwvTqPhRO6mC__3b7MgU7DWwAnOvGvG-t2n22EKq8,4285
|
|
13
|
+
ess/reduce/nexus/__init__.py,sha256=PxJkhlGcFRzVU4SICBhymK5_5FjM5oXPZ8YUpd0v1pE,967
|
|
14
|
+
ess/reduce/nexus/_nexus_loader.py,sha256=otc0qEjGD5K8xFLbn_RYAble34NoDhxLaazE0LAvySE,17911
|
|
15
|
+
ess/reduce/nexus/json_generator.py,sha256=ME2Xn8L7Oi3uHJk9ZZdCRQTRX-OV_wh9-DJn07Alplk,2529
|
|
16
|
+
ess/reduce/nexus/json_nexus.py,sha256=QrVc0p424nZ5dHX9gebAJppTw6lGZq9404P_OFl1giA,10282
|
|
17
|
+
ess/reduce/nexus/types.py,sha256=Az_pZtaTIlEAA4Po_YOLabez8w4HeHcr0asY3rS6BXg,9676
|
|
18
|
+
ess/reduce/nexus/workflow.py,sha256=jzdh0ubp9Mmb98a04KIeM8Xo9bpAqpnsfwFWz2VllnQ,23676
|
|
19
|
+
ess/reduce/scripts/grow_nexus.py,sha256=hET3h06M0xlJd62E3palNLFvJMyNax2kK4XyJcOhl-I,3387
|
|
20
|
+
ess/reduce/time_of_flight/__init__.py,sha256=buqd_rvHvdeO3BTZLf_rKGAFwfJgd6ixAAsxRU_-kik,1546
|
|
21
|
+
ess/reduce/time_of_flight/fakes.py,sha256=cyo6eYn0nOy3Dt1iDge7utkUrSGU-OpZ5g73-DGJsyw,7583
|
|
22
|
+
ess/reduce/time_of_flight/simulation.py,sha256=Tn4kRkXisWjA4ss4AXVshfa9gga0GFOXqtABjRru2MI,2488
|
|
23
|
+
ess/reduce/time_of_flight/to_events.py,sha256=hXTyc_o6qQc2KDurUM55Kb-5VS-VrB9lE5H_R6vAfYM,4115
|
|
24
|
+
ess/reduce/time_of_flight/toa_to_tof.py,sha256=_aQiXqO5LeeBePZcZv_f5VhkreH9NDwFQfDsbe275xI,19505
|
|
25
|
+
ess/reduce/time_of_flight/types.py,sha256=JIAvdBF61wESKoxl1vHmks_udNfT2dlrOxHKOBjFCzg,5888
|
|
26
|
+
ess/reduce/widgets/__init__.py,sha256=wk5ihxvtZHqkp2EYVtbJr1Es0lw69KQpyTSaizNgWjU,5326
|
|
27
|
+
ess/reduce/widgets/_base.py,sha256=_wN3FOlXgx_u0c-A_3yyoIH-SdUvDENGgquh9S-h5GI,4852
|
|
28
|
+
ess/reduce/widgets/_binedges_widget.py,sha256=ZCQsGjYHnJr9GFUn7NjoZc1CdsnAzm_fMzyF-fTKKVY,2785
|
|
29
|
+
ess/reduce/widgets/_bounds_widget.py,sha256=CAyswvMA49mGMl2413TKBMbuG0ULCQPEaSODq8ghiDo,1084
|
|
30
|
+
ess/reduce/widgets/_config.py,sha256=LywjxYau1hsBZ-c2W1_DQ4CRMaaai3anjA8Q8Hn0Y6Y,222
|
|
31
|
+
ess/reduce/widgets/_filename_widget.py,sha256=jlDZOvECJBBjsmfBHjhn8-ig_DQxp3C-Uy07DITs_nI,262
|
|
32
|
+
ess/reduce/widgets/_linspace_widget.py,sha256=5CWIxd-yZST3OILTHeA0Q6AMYt6FdTSs8UYvKKdmtHg,1240
|
|
33
|
+
ess/reduce/widgets/_optional_widget.py,sha256=U2chzANTtQa7IWU9vOxqCZLalRdbuK0oWhHn77V5FTM,3196
|
|
34
|
+
ess/reduce/widgets/_spinner.py,sha256=2VY4Fhfa7HMXox2O7UbofcdKsYG-AJGrsgGJB85nDX0,2081
|
|
35
|
+
ess/reduce/widgets/_string_widget.py,sha256=iPAdfANyXHf-nkfhgkyH6gQDklia0LebLTmwi3m-iYQ,1482
|
|
36
|
+
ess/reduce/widgets/_switchable_widget.py,sha256=fjKz99SKLhIF1BLgGVBSKKn3Lu_jYBwDYGeAjbJY3Q8,2390
|
|
37
|
+
ess/reduce/widgets/_vector_widget.py,sha256=aTaBqCFHZQhrIoX6-sSqFWCPePEW8HQt5kUio8jP1t8,1203
|
|
38
|
+
essreduce-25.1.1.dist-info/LICENSE,sha256=nVEiume4Qj6jMYfSRjHTM2jtJ4FGu0g-5Sdh7osfEYw,1553
|
|
39
|
+
essreduce-25.1.1.dist-info/METADATA,sha256=mjZuI2PH5ONZej_X6h-FCcEUOu70Qh8sxwaWLUL5gH0,3708
|
|
40
|
+
essreduce-25.1.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
41
|
+
essreduce-25.1.1.dist-info/entry_points.txt,sha256=PMZOIYzCifHMTe4pK3HbhxUwxjFaZizYlLD0td4Isb0,66
|
|
42
|
+
essreduce-25.1.1.dist-info/top_level.txt,sha256=0JxTCgMKPLKtp14wb1-RKisQPQWX7i96innZNvHBr-s,4
|
|
43
|
+
essreduce-25.1.1.dist-info/RECORD,,
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
ess/reduce/__init__.py,sha256=-8a2I4mbJdBgNqKxZJe0lAEQJb-lRjX1xmZvGUWCmmU,382
|
|
2
|
-
ess/reduce/data.py,sha256=vaoeAJ6EpK1YghOiAALLdWiW17TgUnnnt0H-RGiGzXk,3756
|
|
3
|
-
ess/reduce/logging.py,sha256=6n8Czq4LZ3OK9ENlKsWSI1M3KvKv6_HSoUiV4__IUlU,357
|
|
4
|
-
ess/reduce/parameter.py,sha256=4sCfoKOI2HuO_Q7JLH_jAXnEOFANSn5P3NdaOBzhJxc,4635
|
|
5
|
-
ess/reduce/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
ess/reduce/streaming.py,sha256=nEO1Xg6LbQ36F44UaVmSNe2MSWmpwz97y9tnlc-z0zA,7493
|
|
7
|
-
ess/reduce/ui.py,sha256=LHgRhcU4ghhbNLk3b64VoA-0oM6yBf4_5a1Smhenmcs,10793
|
|
8
|
-
ess/reduce/uncertainty.py,sha256=LR4O6ApB6Z-W9gC_XW0ajupl8yFG-du0eee1AX_R-gk,6990
|
|
9
|
-
ess/reduce/workflow.py,sha256=sL34T_2Cjl_8iFlegujxI9VyOUwo6erVC8pOXnfWgYw,3060
|
|
10
|
-
ess/reduce/live/__init__.py,sha256=jPQVhihRVNtEDrE20PoKkclKV2aBF1lS7cCHootgFgI,204
|
|
11
|
-
ess/reduce/live/raw.py,sha256=GQmzgh-ByqGYaiB9srRtOxmg6jQqOGNdXxL5gngGy5U,18927
|
|
12
|
-
ess/reduce/live/workflow.py,sha256=bsbwvTqPhRO6mC__3b7MgU7DWwAnOvGvG-t2n22EKq8,4285
|
|
13
|
-
ess/reduce/nexus/__init__.py,sha256=PxJkhlGcFRzVU4SICBhymK5_5FjM5oXPZ8YUpd0v1pE,967
|
|
14
|
-
ess/reduce/nexus/_nexus_loader.py,sha256=-chpzKcZGr2cXmvSYlGiKdKV591mMG-0BsBusGWTer4,16119
|
|
15
|
-
ess/reduce/nexus/json_generator.py,sha256=ME2Xn8L7Oi3uHJk9ZZdCRQTRX-OV_wh9-DJn07Alplk,2529
|
|
16
|
-
ess/reduce/nexus/json_nexus.py,sha256=QrVc0p424nZ5dHX9gebAJppTw6lGZq9404P_OFl1giA,10282
|
|
17
|
-
ess/reduce/nexus/types.py,sha256=aQMPVURUF0JaMl-82LovPxtAuqtvD150AVg17VHPyhM,8982
|
|
18
|
-
ess/reduce/nexus/workflow.py,sha256=jzdh0ubp9Mmb98a04KIeM8Xo9bpAqpnsfwFWz2VllnQ,23676
|
|
19
|
-
ess/reduce/scripts/grow_nexus.py,sha256=hET3h06M0xlJd62E3palNLFvJMyNax2kK4XyJcOhl-I,3387
|
|
20
|
-
ess/reduce/widgets/__init__.py,sha256=cjRJp4qhzCQgXZFtiZgHNmHFJVLo2Z2MozVG_LZYKlI,5281
|
|
21
|
-
ess/reduce/widgets/_base.py,sha256=0OTQsyoHXRdBs14cWtmJVqQqJcM6EIRA8dct_NQWUic,2200
|
|
22
|
-
ess/reduce/widgets/_binedges_widget.py,sha256=ZCQsGjYHnJr9GFUn7NjoZc1CdsnAzm_fMzyF-fTKKVY,2785
|
|
23
|
-
ess/reduce/widgets/_bounds_widget.py,sha256=CAyswvMA49mGMl2413TKBMbuG0ULCQPEaSODq8ghiDo,1084
|
|
24
|
-
ess/reduce/widgets/_config.py,sha256=LywjxYau1hsBZ-c2W1_DQ4CRMaaai3anjA8Q8Hn0Y6Y,222
|
|
25
|
-
ess/reduce/widgets/_filename_widget.py,sha256=jlDZOvECJBBjsmfBHjhn8-ig_DQxp3C-Uy07DITs_nI,262
|
|
26
|
-
ess/reduce/widgets/_linspace_widget.py,sha256=5CWIxd-yZST3OILTHeA0Q6AMYt6FdTSs8UYvKKdmtHg,1240
|
|
27
|
-
ess/reduce/widgets/_optional_widget.py,sha256=A7vwcVwykj7CIyHSPVh6XL5o-8Z1uJTuzha8TR09Zlc,2216
|
|
28
|
-
ess/reduce/widgets/_string_widget.py,sha256=iPAdfANyXHf-nkfhgkyH6gQDklia0LebLTmwi3m-iYQ,1482
|
|
29
|
-
ess/reduce/widgets/_switchable_widget.py,sha256=SZi65C1iShTi5Xhh7W0A7uwA-12AVaH5xmiIWOkc27o,1726
|
|
30
|
-
ess/reduce/widgets/_vector_widget.py,sha256=aTaBqCFHZQhrIoX6-sSqFWCPePEW8HQt5kUio8jP1t8,1203
|
|
31
|
-
essreduce-24.12.0.dist-info/LICENSE,sha256=nVEiume4Qj6jMYfSRjHTM2jtJ4FGu0g-5Sdh7osfEYw,1553
|
|
32
|
-
essreduce-24.12.0.dist-info/METADATA,sha256=nmgXZ0Dnz80YbVTjNuBKomMX4k7n2hyq63TGeva2B7c,3619
|
|
33
|
-
essreduce-24.12.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
34
|
-
essreduce-24.12.0.dist-info/entry_points.txt,sha256=PMZOIYzCifHMTe4pK3HbhxUwxjFaZizYlLD0td4Isb0,66
|
|
35
|
-
essreduce-24.12.0.dist-info/top_level.txt,sha256=0JxTCgMKPLKtp14wb1-RKisQPQWX7i96innZNvHBr-s,4
|
|
36
|
-
essreduce-24.12.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|