lima2.client 3.1a0__tar.gz → 3.1.2__tar.gz
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.
- {lima2_client-3.1a0/src/lima2_client.egg-info → lima2_client-3.1.2}/PKG-INFO +2 -2
- {lima2_client-3.1a0 → lima2_client-3.1.2}/pyproject.toml +1 -1
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/client.py +27 -1
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/detector.py +16 -2
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/state_machine.py +3 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/master_file/generate.py +53 -2
- {lima2_client-3.1a0 → lima2_client-3.1.2/src/lima2_client.egg-info}/PKG-INFO +2 -2
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2_client.egg-info/requires.txt +1 -1
- {lima2_client-3.1a0 → lima2_client-3.1.2}/LICENSE +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/README.md +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/setup.cfg +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/finite_state_machine/__init__.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/finite_state_machine/draw_state_diagram.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/finite_state_machine/examples/__init__.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/finite_state_machine/examples/async_github_pull_request.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/finite_state_machine/examples/async_turnstile.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/finite_state_machine/examples/boolean_field.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/finite_state_machine/examples/github_pull_request.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/finite_state_machine/examples/turnstile.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/finite_state_machine/exceptions.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/finite_state_machine/state_machine.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/__init__.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/convert.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/devencoded/__init__.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/devencoded/dense_frame.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/devencoded/exception.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/devencoded/smx_sparse_frame.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/devencoded/sparse_frame.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/devencoded/structured_array.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/pipeline.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/pipelines/__init__.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/pipelines/failing.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/pipelines/legacy.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/pipelines/smx.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/pipelines/xpcs.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/progress_counter.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/py.typed +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/shell.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/topology.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/client/utils.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/master_file/py.typed +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/server/__init__.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/server/control.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/server/receiver.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2/server/timer.py +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2_client.egg-info/SOURCES.txt +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2_client.egg-info/dependency_links.txt +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2_client.egg-info/entry_points.txt +0 -0
- {lima2_client-3.1a0 → lima2_client-3.1.2}/src/lima2_client.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lima2-client
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.1.2
|
|
4
4
|
Summary: Python client library for Lima2 detector
|
|
5
5
|
Author: BCU (ESRF)
|
|
6
6
|
License: Copyright (c) 2020-2024 Beamline Control Unit, ESRF
|
|
@@ -24,7 +24,7 @@ Requires-Dist: gevent
|
|
|
24
24
|
Requires-Dist: jsonschema
|
|
25
25
|
Requires-Dist: jsonschema-default
|
|
26
26
|
Requires-Dist: beartype
|
|
27
|
-
Requires-Dist: numpy
|
|
27
|
+
Requires-Dist: numpy<2.3
|
|
28
28
|
Requires-Dist: pyyaml
|
|
29
29
|
Requires-Dist: typing-extensions
|
|
30
30
|
Requires-Dist: h5py
|
|
@@ -89,6 +89,22 @@ class Client:
|
|
|
89
89
|
{saving channel name: list of tasks}.
|
|
90
90
|
"""
|
|
91
91
|
|
|
92
|
+
def cleanup(self):
|
|
93
|
+
"""Unregister all state loggers and tango event handlers.
|
|
94
|
+
|
|
95
|
+
This method serves only in specific cases where event handlers must for
|
|
96
|
+
some reason be unregistered. In a normal use case, a Client is
|
|
97
|
+
instantiated once per Lima2 instance, and no cleanup is necessary.
|
|
98
|
+
|
|
99
|
+
NOTE: After this call, the Client instance should no longer be used.
|
|
100
|
+
"""
|
|
101
|
+
self._detector.unregister_events()
|
|
102
|
+
self._detector = None
|
|
103
|
+
|
|
104
|
+
for pipeline in self.__pipelines.values():
|
|
105
|
+
pipeline.unregister_events()
|
|
106
|
+
self.__pipelines.clear()
|
|
107
|
+
|
|
92
108
|
@classmethod
|
|
93
109
|
def from_yaml(
|
|
94
110
|
cls,
|
|
@@ -167,6 +183,15 @@ class Client:
|
|
|
167
183
|
) -> None:
|
|
168
184
|
"""Prepare acquisition with a given uuid and set of params."""
|
|
169
185
|
|
|
186
|
+
# Check parameters required for master file generation
|
|
187
|
+
checked_params = mfg.check_generation(
|
|
188
|
+
ctrl_params=ctrl_params,
|
|
189
|
+
recv_params=acq_params,
|
|
190
|
+
proc_params=proc_params,
|
|
191
|
+
topology_kind=self.topology_kind,
|
|
192
|
+
)
|
|
193
|
+
ctrl_params, acq_params, proc_params = checked_params
|
|
194
|
+
|
|
170
195
|
# Adjust params for distributed acquisition
|
|
171
196
|
ctl, acq, proc = topology.distribute_acq(
|
|
172
197
|
ctl_params=ctrl_params,
|
|
@@ -209,6 +234,7 @@ class Client:
|
|
|
209
234
|
ctrl_params=ctl,
|
|
210
235
|
recv_params=acq[0],
|
|
211
236
|
proc_params=proc[0],
|
|
237
|
+
topology_kind=self.topology_kind,
|
|
212
238
|
)
|
|
213
239
|
|
|
214
240
|
@docstring_from(Detector.start_acq)
|
|
@@ -364,7 +390,7 @@ class Client:
|
|
|
364
390
|
|
|
365
391
|
cleared = []
|
|
366
392
|
for uuid in receiver.pipelines:
|
|
367
|
-
if uuid != str(current):
|
|
393
|
+
if uuid != str(current) and all(self.pipeline(UUID(uuid)).is_finished):
|
|
368
394
|
logger.debug(
|
|
369
395
|
f"Erasing pipeline {uuid} from recv {receiver.dev_name()}"
|
|
370
396
|
)
|
|
@@ -73,6 +73,7 @@ class Detector:
|
|
|
73
73
|
|
|
74
74
|
self.__ctrl = ctrl_dev
|
|
75
75
|
self.__recvs = list(recv_devs)
|
|
76
|
+
self._state_event_ids: dict[tango.DeviceProxy, int] = {}
|
|
76
77
|
|
|
77
78
|
self.ping()
|
|
78
79
|
|
|
@@ -100,6 +101,17 @@ class Detector:
|
|
|
100
101
|
d.set_green_mode(tango.GreenMode.Gevent)
|
|
101
102
|
d.set_timeout_millis(timeout * 1000)
|
|
102
103
|
|
|
104
|
+
def unregister_events(self):
|
|
105
|
+
"""Unregister all state loggers and tango event handlers.
|
|
106
|
+
|
|
107
|
+
This method serves only in specific cases where event handlers must for
|
|
108
|
+
some reason be unregistered. In a normal use case, a Client is
|
|
109
|
+
instantiated once per Lima2 instance, and no cleanup is necessary.
|
|
110
|
+
"""
|
|
111
|
+
for device, event_id in self._state_event_ids.items():
|
|
112
|
+
device.unsubscribe_event(event_id)
|
|
113
|
+
self._state_event_ids.clear()
|
|
114
|
+
|
|
103
115
|
@contextlib.contextmanager
|
|
104
116
|
def _locked_fsm(self) -> Iterator[fsm.StateMachine]:
|
|
105
117
|
self.__fsm_lock.acquire()
|
|
@@ -633,12 +645,14 @@ class Detector:
|
|
|
633
645
|
finally:
|
|
634
646
|
_logger.info(f"Current state: {fsm.state}")
|
|
635
647
|
|
|
636
|
-
|
|
637
|
-
dev.subscribe_event(
|
|
648
|
+
self._state_event_ids = {
|
|
649
|
+
dev: dev.subscribe_event(
|
|
638
650
|
"acq_state",
|
|
639
651
|
tango.EventType.CHANGE_EVENT,
|
|
640
652
|
on_acq_state_change,
|
|
641
653
|
)
|
|
654
|
+
for dev in self.devs
|
|
655
|
+
}
|
|
642
656
|
|
|
643
657
|
def _register_on_end_acq_handlers(self):
|
|
644
658
|
"""Register an "end of acquisition" callback on each receiver.
|
|
@@ -239,6 +239,9 @@ class StateMachine(fsm.StateMachine):
|
|
|
239
239
|
if logger in self.__loggers:
|
|
240
240
|
self.__loggers.remove(logger)
|
|
241
241
|
|
|
242
|
+
def clear_transition_loggers(self):
|
|
243
|
+
self.__loggers.clear()
|
|
244
|
+
|
|
242
245
|
def on_state_change(self, state):
|
|
243
246
|
_logger.debug(f"on_state_change {state}")
|
|
244
247
|
futures = []
|
|
@@ -27,6 +27,7 @@ import gevent
|
|
|
27
27
|
import gevent.event
|
|
28
28
|
|
|
29
29
|
from lima2.client.pipeline import FrameType, Pipeline
|
|
30
|
+
from lima2.client.topology import TopologyKind
|
|
30
31
|
|
|
31
32
|
logger = logging.getLogger(__name__)
|
|
32
33
|
|
|
@@ -66,12 +67,54 @@ class MasterFileTask:
|
|
|
66
67
|
self.task.join()
|
|
67
68
|
|
|
68
69
|
|
|
70
|
+
def check_generation(
|
|
71
|
+
ctrl_params: dict,
|
|
72
|
+
recv_params: dict,
|
|
73
|
+
proc_params: dict,
|
|
74
|
+
topology_kind: TopologyKind,
|
|
75
|
+
) -> list[dict]:
|
|
76
|
+
"""Check the parameters to be sent to prepare to ensure master file info"""
|
|
77
|
+
|
|
78
|
+
# group all active saving subsystems
|
|
79
|
+
active_saving_params: list[dict] = []
|
|
80
|
+
|
|
81
|
+
# first check receiver raw saving or SDK saving
|
|
82
|
+
for params in [recv_params, ctrl_params]:
|
|
83
|
+
if "saving" in params and params["saving"]["enabled"]:
|
|
84
|
+
active_saving_params.append(params["saving"])
|
|
85
|
+
break
|
|
86
|
+
|
|
87
|
+
# then check the saving streams of the current pipeline
|
|
88
|
+
for source, params in proc_params.items():
|
|
89
|
+
# Skip other subsystems
|
|
90
|
+
if not source.startswith("saving"):
|
|
91
|
+
continue
|
|
92
|
+
# Skip source if channel is disabled
|
|
93
|
+
if params["enabled"]:
|
|
94
|
+
active_saving_params.append(params)
|
|
95
|
+
|
|
96
|
+
need_frame_lut = topology_kind == TopologyKind.UNEVEN
|
|
97
|
+
|
|
98
|
+
# include detector frame_idx dataset in HDF5 files
|
|
99
|
+
for saving_params in active_saving_params:
|
|
100
|
+
if need_frame_lut and "include_frame_idx" in saving_params:
|
|
101
|
+
saving_params["include_frame_idx"] = True
|
|
102
|
+
|
|
103
|
+
# allow retreiving recv-det-frame-idx mapping
|
|
104
|
+
if need_frame_lut and "frame_idx_enabled" in proc_params:
|
|
105
|
+
logger.debug("Enabling frame_idx generation")
|
|
106
|
+
proc_params["frame_idx_enabled"] = True
|
|
107
|
+
|
|
108
|
+
return ctrl_params, recv_params, proc_params
|
|
109
|
+
|
|
110
|
+
|
|
69
111
|
def enable_generation(
|
|
70
112
|
pipeline: Pipeline,
|
|
71
113
|
num_frames: int,
|
|
72
114
|
ctrl_params: dict,
|
|
73
115
|
recv_params: dict,
|
|
74
116
|
proc_params: dict,
|
|
117
|
+
topology_kind: TopologyKind,
|
|
75
118
|
rr_offset: int = 0,
|
|
76
119
|
lut_source: LUTSource = LUTSource.AUTO,
|
|
77
120
|
) -> dict[str, MasterFileTask]:
|
|
@@ -144,6 +187,11 @@ def enable_generation(
|
|
|
144
187
|
proc_params=proc_params,
|
|
145
188
|
)
|
|
146
189
|
|
|
190
|
+
need_frame_lut = topology_kind == TopologyKind.UNEVEN
|
|
191
|
+
|
|
192
|
+
# Check strict Round-Robin only when needed
|
|
193
|
+
check_strict_rr = topology_kind == TopologyKind.ROUND_ROBIN
|
|
194
|
+
|
|
147
195
|
for source, frame_info, saving_params, cnt_name in active_saving_params:
|
|
148
196
|
base_path = saving_params["base_path"]
|
|
149
197
|
filename_prefix = saving_params["filename_prefix"]
|
|
@@ -171,10 +219,12 @@ def enable_generation(
|
|
|
171
219
|
this_lut_source = LUTSource.ROUND_ROBIN
|
|
172
220
|
if this_lut_source is None:
|
|
173
221
|
raise ValueError(f"Cannot satisfy {lut_source=}: {file_lut=}, {recv_lut=}")
|
|
222
|
+
elif this_lut_source == LUTSource.ROUND_ROBIN and need_frame_lut:
|
|
223
|
+
raise ValueError(f"Cannot use {this_lut_source} with {topology_kind}")
|
|
174
224
|
|
|
175
225
|
logger.info(
|
|
176
226
|
f"Master file (channel={source}) will be generated "
|
|
177
|
-
f"at {master_file_path}..."
|
|
227
|
+
f"at {master_file_path} [{this_lut_source}]..."
|
|
178
228
|
)
|
|
179
229
|
|
|
180
230
|
if frame_info is not None:
|
|
@@ -201,6 +251,7 @@ def enable_generation(
|
|
|
201
251
|
end_event=end_event,
|
|
202
252
|
cnt_name=cnt_name,
|
|
203
253
|
config=config,
|
|
254
|
+
check_strict_rr=check_strict_rr,
|
|
204
255
|
)
|
|
205
256
|
|
|
206
257
|
lut_sources = [s["lut_source"] for s in generate_params.values()]
|
|
@@ -260,7 +311,7 @@ class MasterFileGeneration:
|
|
|
260
311
|
end_event: Optional[gevent.event.Event] = None
|
|
261
312
|
cnt_name: Optional[str] = None
|
|
262
313
|
config: Optional[dict] = None
|
|
263
|
-
check_strict_rr: bool =
|
|
314
|
+
check_strict_rr: bool = False
|
|
264
315
|
|
|
265
316
|
def __init__(self, params: Params):
|
|
266
317
|
self._p = params
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lima2-client
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.1.2
|
|
4
4
|
Summary: Python client library for Lima2 detector
|
|
5
5
|
Author: BCU (ESRF)
|
|
6
6
|
License: Copyright (c) 2020-2024 Beamline Control Unit, ESRF
|
|
@@ -24,7 +24,7 @@ Requires-Dist: gevent
|
|
|
24
24
|
Requires-Dist: jsonschema
|
|
25
25
|
Requires-Dist: jsonschema-default
|
|
26
26
|
Requires-Dist: beartype
|
|
27
|
-
Requires-Dist: numpy
|
|
27
|
+
Requires-Dist: numpy<2.3
|
|
28
28
|
Requires-Dist: pyyaml
|
|
29
29
|
Requires-Dist: typing-extensions
|
|
30
30
|
Requires-Dist: h5py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lima2_client-3.1a0 → lima2_client-3.1.2}/src/finite_state_machine/examples/async_turnstile.py
RENAMED
|
File without changes
|
{lima2_client-3.1a0 → lima2_client-3.1.2}/src/finite_state_machine/examples/boolean_field.py
RENAMED
|
File without changes
|
{lima2_client-3.1a0 → lima2_client-3.1.2}/src/finite_state_machine/examples/github_pull_request.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|