lima2.client 4.0.3__tar.gz → 4.0.4__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.
Files changed (129) hide show
  1. {lima2_client-4.0.3/src/lima2_client.egg-info → lima2_client-4.0.4}/PKG-INFO +1 -1
  2. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/acquisition_system.py +14 -5
  3. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/processing/pipeline.py +28 -8
  4. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/processing/reduced_data.py +4 -6
  5. {lima2_client-4.0.3 → lima2_client-4.0.4/src/lima2_client.egg-info}/PKG-INFO +1 -1
  6. lima2_client-4.0.4/src/lima2_client.egg-info/SOURCES.txt +57 -0
  7. lima2_client-4.0.3/.gitignore +0 -25
  8. lima2_client-4.0.3/.gitlab-ci.yml +0 -142
  9. lima2_client-4.0.3/conda/meta.yaml +0 -62
  10. lima2_client-4.0.3/conda/run_test.sh +0 -12
  11. lima2_client-4.0.3/docs/assets/lima2-components-and-repos.svg +0 -10
  12. lima2_client-4.0.3/docs/assets/lima2-conductor-communication-model.svg +0 -10
  13. lima2_client-4.0.3/docs/assets/lima2-conductor-modules.svg +0 -10
  14. lima2_client-4.0.3/docs/assets/logo-transparent-crop.png +0 -0
  15. lima2_client-4.0.3/docs/concepts.md +0 -59
  16. lima2_client-4.0.3/docs/contact.md +0 -8
  17. lima2_client-4.0.3/docs/dev/conductor_client.md +0 -13
  18. lima2_client-4.0.3/docs/dev/conductor_design.md +0 -192
  19. lima2_client-4.0.3/docs/dev/conductor_requirements.md +0 -43
  20. lima2_client-4.0.3/docs/dev/index.md +0 -4
  21. lima2_client-4.0.3/docs/features.md +0 -70
  22. lima2_client-4.0.3/docs/getting_started.md +0 -112
  23. lima2_client-4.0.3/docs/index.md +0 -25
  24. lima2_client-4.0.3/docs/license.md +0 -3
  25. lima2_client-4.0.3/docs/monitor.md +0 -9
  26. lima2_client-4.0.3/docs/reference/acquisition.md +0 -12
  27. lima2_client-4.0.3/docs/reference/detector.md +0 -12
  28. lima2_client-4.0.3/docs/reference/exceptions.md +0 -25
  29. lima2_client-4.0.3/docs/reference/index.md +0 -9
  30. lima2_client-4.0.3/docs/reference/pipeline.md +0 -12
  31. lima2_client-4.0.3/docs/reference/session.md +0 -12
  32. lima2_client-4.0.3/docs/release_notes.md +0 -3
  33. lima2_client-4.0.3/docs/shell.md +0 -37
  34. lima2_client-4.0.3/flake8.ini +0 -8
  35. lima2_client-4.0.3/mkdocs.yml +0 -72
  36. lima2_client-4.0.3/scripts/cleanup_processing_ds.py +0 -29
  37. lima2_client-4.0.3/src/lima2_client.egg-info/SOURCES.txt +0 -126
  38. lima2_client-4.0.3/tests/__init__.py +0 -4
  39. lima2_client-4.0.3/tests/integration/__init__.py +0 -0
  40. lima2_client-4.0.3/tests/integration/conftest.py +0 -136
  41. lima2_client-4.0.3/tests/integration/tango_db/simulator_ctl.yaml +0 -8
  42. lima2_client-4.0.3/tests/integration/tango_db/simulator_rcv1.yaml +0 -6
  43. lima2_client-4.0.3/tests/integration/tango_db/simulator_rcv2.yaml +0 -6
  44. lima2_client-4.0.3/tests/integration/test_failing.py +0 -186
  45. lima2_client-4.0.3/tests/integration/test_legacy.py +0 -159
  46. lima2_client-4.0.3/tests/unit/__init__.py +0 -4
  47. lima2_client-4.0.3/tests/unit/client/__init__.py +0 -6
  48. lima2_client-4.0.3/tests/unit/client/conftest.py +0 -73
  49. lima2_client-4.0.3/tests/unit/client/test_acquisition.py +0 -144
  50. lima2_client-4.0.3/tests/unit/client/test_detector.py +0 -40
  51. lima2_client-4.0.3/tests/unit/client/test_pipeline.py +0 -310
  52. lima2_client-4.0.3/tests/unit/client/test_session.py +0 -174
  53. lima2_client-4.0.3/tests/unit/common/__init__.py +0 -6
  54. lima2_client-4.0.3/tests/unit/common/test_dense_frame.py +0 -155
  55. lima2_client-4.0.3/tests/unit/common/test_progress_counter.py +0 -75
  56. lima2_client-4.0.3/tests/unit/common/test_smx_sparse_frame.py +0 -149
  57. lima2_client-4.0.3/tests/unit/common/test_sparse_frame.py +0 -110
  58. lima2_client-4.0.3/tests/unit/common/test_state.py +0 -63
  59. lima2_client-4.0.3/tests/unit/conductor/__init__.py +0 -6
  60. lima2_client-4.0.3/tests/unit/conductor/mock_devencoded.py +0 -53
  61. lima2_client-4.0.3/tests/unit/conductor/mock_devices.py +0 -227
  62. lima2_client-4.0.3/tests/unit/conductor/test_acquisition_system.py +0 -714
  63. lima2_client-4.0.3/tests/unit/conductor/test_master_file.py +0 -430
  64. lima2_client-4.0.3/tests/unit/conductor/test_pipeline.py +0 -877
  65. lima2_client-4.0.3/tests/unit/conductor/test_processing.py +0 -20
  66. lima2_client-4.0.3/tests/unit/conductor/test_reduced_data.py +0 -600
  67. lima2_client-4.0.3/tests/unit/conductor/test_tango_devices.py +0 -565
  68. lima2_client-4.0.3/tests/unit/conductor/test_topology.py +0 -302
  69. lima2_client-4.0.3/tests/unit/conductor/test_utils.py +0 -157
  70. lima2_client-4.0.3/tests/unit/conductor/webservice/__init__.py +0 -6
  71. lima2_client-4.0.3/tests/unit/conductor/webservice/test_acquisition.py +0 -206
  72. lima2_client-4.0.3/tests/unit/conductor/webservice/test_benchmark.py +0 -88
  73. lima2_client-4.0.3/tests/unit/conductor/webservice/test_detector.py +0 -78
  74. lima2_client-4.0.3/tests/unit/conductor/webservice/test_pipelines.py +0 -290
  75. lima2_client-4.0.3/tests/unit/conductor/webservice/test_utils.py +0 -71
  76. lima2_client-4.0.3/tests/unit/conductor/webservice/test_webapp.py +0 -117
  77. {lima2_client-4.0.3 → lima2_client-4.0.4}/LICENSE +0 -0
  78. {lima2_client-4.0.3 → lima2_client-4.0.4}/README.md +0 -0
  79. {lima2_client-4.0.3 → lima2_client-4.0.4}/pyproject.toml +0 -0
  80. {lima2_client-4.0.3 → lima2_client-4.0.4}/setup.cfg +0 -0
  81. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/client/__init__.py +0 -0
  82. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/client/exceptions.py +0 -0
  83. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/client/py.typed +0 -0
  84. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/client/services.py +0 -0
  85. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/client/session.py +0 -0
  86. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/client/shell.py +0 -0
  87. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/common/__init__.py +0 -0
  88. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/common/devencoded/__init__.py +0 -0
  89. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/common/devencoded/dense_frame.py +0 -0
  90. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/common/devencoded/exception.py +0 -0
  91. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/common/devencoded/smx_sparse_frame.py +0 -0
  92. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/common/devencoded/sparse_frame.py +0 -0
  93. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/common/devencoded/structured_array.py +0 -0
  94. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/common/exceptions.py +0 -0
  95. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/common/pipelines.py +0 -0
  96. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/common/progress_counter.py +0 -0
  97. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/common/py.typed +0 -0
  98. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/common/state.py +0 -0
  99. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/common/types.py +0 -0
  100. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/__init__.py +0 -0
  101. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/processing/__init__.py +0 -0
  102. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/processing/failing.py +0 -0
  103. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/processing/legacy.py +0 -0
  104. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/processing/master_file.py +0 -0
  105. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/processing/smx.py +0 -0
  106. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/processing/xpcs.py +0 -0
  107. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/py.typed +0 -0
  108. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/tango/__init__.py +0 -0
  109. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/tango/control.py +0 -0
  110. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/tango/processing.py +0 -0
  111. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/tango/receiver.py +0 -0
  112. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/tango/utils.py +0 -0
  113. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/topology.py +0 -0
  114. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/utils.py +0 -0
  115. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/webservice/__init__.py +0 -0
  116. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/webservice/acquisition.py +0 -0
  117. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/webservice/benchmark.py +0 -0
  118. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/webservice/benchmark_generators/__init__.py +0 -0
  119. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/webservice/benchmark_generators/rois.py +0 -0
  120. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/webservice/cli.py +0 -0
  121. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/webservice/detector.py +0 -0
  122. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/webservice/main.py +0 -0
  123. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/webservice/pipeline.py +0 -0
  124. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/webservice/utils.py +0 -0
  125. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2/conductor/webservice/webapp.py +0 -0
  126. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2_client.egg-info/dependency_links.txt +0 -0
  127. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2_client.egg-info/entry_points.txt +0 -0
  128. {lima2_client-4.0.3 → lima2_client-4.0.4}/src/lima2_client.egg-info/requires.txt +0 -0
  129. {lima2_client-4.0.3 → lima2_client-4.0.4}/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: 4.0.3
3
+ Version: 4.0.4
4
4
  Summary: Python client library for Lima2 detector
5
5
  Author: BCU (ESRF)
6
6
  License-Expression: MIT
@@ -16,6 +16,7 @@ import logging
16
16
  import textwrap
17
17
  import time
18
18
  import traceback
19
+ import weakref
19
20
  from typing import Any, Callable, Literal, cast
20
21
  from uuid import UUID, uuid1
21
22
 
@@ -710,24 +711,32 @@ class AcquisitionSystem:
710
711
  def register_receiver_callbacks(self) -> None:
711
712
  """Register on_state_change callback on the receiver devices"""
712
713
 
714
+ # NOTE: Using weakref in event handlers is necessary to allow the
715
+ # garbage collector to destroy the Acquisition object.
716
+ wself = weakref.ref(self)
717
+
713
718
  async def on_state_change(dev: TangoReceiver, new_state: DeviceState) -> None:
714
719
  """Handler for receiver device state changes."""
715
720
  logger.info(f"Receiver {dev.name} in new state: {new_state}")
716
721
 
722
+ self_ref = wself()
723
+ if self_ref is None:
724
+ return
725
+
717
726
  if new_state == DeviceState.FAULT:
718
727
  payload = await dev.last_error()
719
728
 
720
729
  what, info = unpack_exception(payload)
721
730
 
722
731
  logger.error(f"⁉️ FAULT state on {dev.name}. Reason: {what} ({info})")
723
- await self.update_runstate(event=RunState.ACQ_EXCEPTION)
732
+ await self_ref.update_runstate(event=RunState.ACQ_EXCEPTION)
724
733
 
725
- elif new_state == DeviceState.IDLE and self.runstate & RunState.RUNNING:
726
- self.finished_receivers.add(dev)
734
+ elif new_state == DeviceState.IDLE and self_ref.runstate & RunState.RUNNING:
735
+ self_ref.finished_receivers.add(dev)
727
736
 
728
- if self.finished_receivers == set(self.receivers):
737
+ if self_ref.finished_receivers == set(self_ref.receivers):
729
738
  logger.info("✅ All frames received")
730
- await self.update_runstate(event=RunState.ACQ_DONE)
739
+ await self_ref.update_runstate(event=RunState.ACQ_DONE)
731
740
 
732
741
  for receiver in self.receivers:
733
742
  receiver.on_state_change(functools.partial(on_state_change, receiver))
@@ -16,6 +16,7 @@ import asyncio
16
16
  import logging
17
17
  import time
18
18
  import traceback
19
+ import weakref
19
20
  from collections.abc import Callable
20
21
  from dataclasses import dataclass
21
22
  from typing import Any, AsyncIterator, Awaitable
@@ -243,6 +244,9 @@ class Pipeline:
243
244
  self.on_finished_callback = to_async(lambda _: None)
244
245
  self.on_error_callback = to_async(lambda _: None)
245
246
 
247
+ def __del__(self) -> None:
248
+ logger.debug(f"Pipeline instance {self.uuid} destroyed")
249
+
246
250
  async def connect(
247
251
  self,
248
252
  on_finished: Callable[[list[str]], Awaitable[None]],
@@ -261,6 +265,10 @@ class Pipeline:
261
265
  self.on_finished_callback = on_finished
262
266
  self.on_error_callback = on_error
263
267
 
268
+ # NOTE: Using weakref in event handlers is necessary to allow the
269
+ # garbage collector to destroy the Pipeline object.
270
+ wself = weakref.ref(self)
271
+
264
272
  async def on_device_finished(device_name: str) -> None:
265
273
  """Adds a processing device to the finished_devices set.
266
274
 
@@ -268,14 +276,19 @@ class Pipeline:
268
276
  this pipeline instance (see constructor).
269
277
  """
270
278
  logger.info(f"Processing device {device_name} is done")
271
- self.finished_devices.add(device_name)
272
279
 
273
- if self.finished_devices == set([dev.name for dev in self.devices]):
280
+ self_ref = wself()
281
+ if self_ref is None:
282
+ return
283
+
284
+ self_ref.finished_devices.add(device_name)
285
+
286
+ if self_ref.finished_devices == set([dev.name for dev in self_ref.devices]):
274
287
  try:
275
- await self.on_finished_callback(self.errors)
288
+ await self_ref.on_finished_callback(self_ref.errors)
276
289
  except Exception:
277
290
  logger.error(
278
- f"Exception raised in pipeline {self.uuid} "
291
+ f"Exception raised in pipeline {self_ref.uuid} "
279
292
  "on_finished callback:\n"
280
293
  f"{traceback.format_exc()}"
281
294
  )
@@ -285,7 +298,12 @@ class Pipeline:
285
298
  logger.warning(
286
299
  f"Error from processing device {evt.device_name}: {evt.what}."
287
300
  )
288
- self.errors.append(
301
+
302
+ self_ref = wself()
303
+ if self_ref is None:
304
+ return
305
+
306
+ self_ref.errors.append(
289
307
  format_exception(
290
308
  where=evt.device_name,
291
309
  when="while processing frames",
@@ -295,14 +313,16 @@ class Pipeline:
295
313
  )
296
314
 
297
315
  pipeline_err_evt = PipelineErrorEvent(
298
- uuid=self.uuid, error_msg=self.errors[-1], device_name=evt.device_name
316
+ uuid=self_ref.uuid,
317
+ error_msg=self_ref.errors[-1],
318
+ device_name=evt.device_name,
299
319
  )
300
320
 
301
321
  try:
302
- await self.on_error_callback(pipeline_err_evt)
322
+ await self_ref.on_error_callback(pipeline_err_evt)
303
323
  except Exception:
304
324
  logger.error(
305
- f"Exception raised in pipeline {self.uuid} "
325
+ f"Exception raised in pipeline {self_ref.uuid} "
306
326
  "on_error callback:\n"
307
327
  f"{traceback.format_exc()}"
308
328
  )
@@ -26,12 +26,7 @@ from lima2.conductor.topology import (
26
26
  LookupTable,
27
27
  ReceiverIdx,
28
28
  )
29
- from lima2.conductor.utils import (
30
- Ticker,
31
- expand,
32
- naturalsize,
33
- warn_if_hanging,
34
- )
29
+ from lima2.conductor.utils import Ticker, expand, naturalsize, warn_if_hanging
35
30
 
36
31
  logger = logging.getLogger(__name__)
37
32
 
@@ -257,6 +252,9 @@ class ReducedDataPipeline:
257
252
  self.done_event = asyncio.Event()
258
253
  """Event set when the buffer is complete with all fetched chunks."""
259
254
 
255
+ def __del__(self) -> None:
256
+ logger.debug(f"ReducedDataPipeline instance for {self.name} destroyed")
257
+
260
258
  async def lookup_chunk(
261
259
  self, rcv_idx: ReceiverIdx, from_idx: LocalIdx, chunk: npt.NDArray[Any]
262
260
  ) -> npt.NDArray[GlobalIdx]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lima2-client
3
- Version: 4.0.3
3
+ Version: 4.0.4
4
4
  Summary: Python client library for Lima2 detector
5
5
  Author: BCU (ESRF)
6
6
  License-Expression: MIT
@@ -0,0 +1,57 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/lima2/client/__init__.py
5
+ src/lima2/client/exceptions.py
6
+ src/lima2/client/py.typed
7
+ src/lima2/client/services.py
8
+ src/lima2/client/session.py
9
+ src/lima2/client/shell.py
10
+ src/lima2/common/__init__.py
11
+ src/lima2/common/exceptions.py
12
+ src/lima2/common/pipelines.py
13
+ src/lima2/common/progress_counter.py
14
+ src/lima2/common/py.typed
15
+ src/lima2/common/state.py
16
+ src/lima2/common/types.py
17
+ src/lima2/common/devencoded/__init__.py
18
+ src/lima2/common/devencoded/dense_frame.py
19
+ src/lima2/common/devencoded/exception.py
20
+ src/lima2/common/devencoded/smx_sparse_frame.py
21
+ src/lima2/common/devencoded/sparse_frame.py
22
+ src/lima2/common/devencoded/structured_array.py
23
+ src/lima2/conductor/__init__.py
24
+ src/lima2/conductor/acquisition_system.py
25
+ src/lima2/conductor/py.typed
26
+ src/lima2/conductor/topology.py
27
+ src/lima2/conductor/utils.py
28
+ src/lima2/conductor/processing/__init__.py
29
+ src/lima2/conductor/processing/failing.py
30
+ src/lima2/conductor/processing/legacy.py
31
+ src/lima2/conductor/processing/master_file.py
32
+ src/lima2/conductor/processing/pipeline.py
33
+ src/lima2/conductor/processing/reduced_data.py
34
+ src/lima2/conductor/processing/smx.py
35
+ src/lima2/conductor/processing/xpcs.py
36
+ src/lima2/conductor/tango/__init__.py
37
+ src/lima2/conductor/tango/control.py
38
+ src/lima2/conductor/tango/processing.py
39
+ src/lima2/conductor/tango/receiver.py
40
+ src/lima2/conductor/tango/utils.py
41
+ src/lima2/conductor/webservice/__init__.py
42
+ src/lima2/conductor/webservice/acquisition.py
43
+ src/lima2/conductor/webservice/benchmark.py
44
+ src/lima2/conductor/webservice/cli.py
45
+ src/lima2/conductor/webservice/detector.py
46
+ src/lima2/conductor/webservice/main.py
47
+ src/lima2/conductor/webservice/pipeline.py
48
+ src/lima2/conductor/webservice/utils.py
49
+ src/lima2/conductor/webservice/webapp.py
50
+ src/lima2/conductor/webservice/benchmark_generators/__init__.py
51
+ src/lima2/conductor/webservice/benchmark_generators/rois.py
52
+ src/lima2_client.egg-info/PKG-INFO
53
+ src/lima2_client.egg-info/SOURCES.txt
54
+ src/lima2_client.egg-info/dependency_links.txt
55
+ src/lima2_client.egg-info/entry_points.txt
56
+ src/lima2_client.egg-info/requires.txt
57
+ src/lima2_client.egg-info/top_level.txt
@@ -1,25 +0,0 @@
1
- # Byte / compiled / optimized
2
- *.py[cod]
3
- __pycache__/
4
- *.so
5
-
6
- # Distribution / packaging
7
- /dist/
8
- /build/
9
- *.egg-info/
10
- .eggs/
11
-
12
- # Unittest / coverage
13
- *.py,cover
14
- .coverage.*
15
- htmlcov/
16
- .cache/
17
- .pytest_cache/
18
-
19
- # Profiler
20
- /prof/
21
-
22
- # mypy
23
- .mypy_cache/
24
- .dmypy.json
25
- dmypy.json
@@ -1,142 +0,0 @@
1
- stages:
2
- - style
3
- - tests
4
- - build
5
- - doc
6
- - deploy
7
-
8
- black-format:
9
- stage: style
10
- script:
11
- - mamba install --yes -c conda-forge black=22.3
12
- - LC_ALL=C.UTF-8 black --check .
13
- tags:
14
- - linux
15
-
16
- flake-format:
17
- stage: style
18
- script:
19
- - mamba install --yes -c conda-forge flake8
20
- # disable dubious ownership check
21
- - git config --global --add safe.directory "*"
22
- # choose from where to diff (complete merge request or last commit otherwise)
23
- - >
24
- if [ $CI_PIPELINE_SOURCE == "merge_request_event" ]; then
25
- BASE_SHA="${CI_MERGE_REQUEST_DIFF_BASE_SHA}"
26
- else
27
- BASE_SHA=$(git rev-parse HEAD^)
28
- fi
29
- # list Added/Copied/Modified .py files since $BASE_SHA
30
- - PY_CHANGES=$(git diff $BASE_SHA --name-only --diff-filter=ACM -- "***.py")
31
- # abort if no files
32
- - >
33
- if [ -z "${PY_CHANGES}" ]; then
34
- echo "No changes."
35
- exit 0
36
- fi
37
- - flake8 --config flake8.ini $PY_CHANGES
38
- # allow failure without impacting the rest of the CI (will show an orange warning in the UI)
39
- allow_failure: true
40
- tags:
41
- - linux
42
-
43
- mypy:
44
- stage: style
45
- script:
46
- - pip install .[dev]
47
- - pip install mypy-gitlab-code-quality
48
- - mypy --no-error-summary > mypy-out.txt || true
49
- - mypy-gitlab-code-quality < mypy-out.txt > codequality.json
50
- artifacts:
51
- reports:
52
- codequality: codequality.json
53
- tags:
54
- - linux
55
- - numpy2.3+
56
-
57
- unit-test:
58
- stage: tests
59
- script:
60
- - pip install -e .[dev]
61
- - pytest --cov lima2.client --cov lima2.conductor --cov lima2.common --cov-report term --cov-report xml:coverage.xml --junitxml junit-report.xml tests/unit
62
- artifacts:
63
- paths:
64
- - junit-report.xml
65
- - coverage.xml
66
- reports:
67
- junit: junit-report.xml
68
- coverage_report:
69
- coverage_format: cobertura
70
- path: coverage.xml
71
- coverage: '/TOTAL.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/'
72
- tags:
73
- - linux
74
- - numpy2.3+
75
-
76
- build-conda:
77
- stage: build
78
- script:
79
- - conda build --output-folder=dist/conda -c esrf-bcu -c conda-forge conda
80
- artifacts:
81
- paths:
82
- - dist/conda/
83
- tags:
84
- - linux
85
-
86
- build-pypi:
87
- stage: build
88
- script:
89
- - mamba install --yes python-build
90
- - python -m build --outdir=dist/pypi .
91
- artifacts:
92
- paths:
93
- - dist/pypi/
94
- tags:
95
- - linux
96
-
97
- deploy-conda:
98
- stage: deploy
99
- environment:
100
- name: production/conda
101
- url: https://anaconda.org/esrf-bcu/lima2-client
102
- dependencies:
103
- - build-conda
104
- script:
105
- - anaconda --token=$ANACONDA_TOKEN upload --user=esrf-bcu dist/conda/**/*.tar.bz2
106
- tags:
107
- - linux
108
- only:
109
- - tags
110
-
111
- deploy-pypi:
112
- stage: deploy
113
- environment:
114
- name: production/pypi
115
- url: https://pypi.org/project/lima2.client/
116
- dependencies:
117
- - build-pypi
118
- script:
119
- - pip install twine
120
- - pip install -U packaging
121
- - twine upload dist/pypi/*
122
- tags:
123
- - linux
124
- only:
125
- - tags
126
-
127
- pages:
128
- stage: doc
129
- before_script:
130
- - pip install .[docs]
131
- script:
132
- - mkdocs build
133
- - mv site public
134
- tags:
135
- - linux
136
- - numpy2.3+
137
- artifacts:
138
- paths:
139
- - public
140
- expire_in: 7 days
141
- only:
142
- - main
@@ -1,62 +0,0 @@
1
- # Strip the 'v' from the version tag
2
- {% if GIT_DESCRIBE_TAG is defined %}
3
- {% set version = GIT_DESCRIBE_TAG[1:] %}
4
- {% else %}
5
- {% set version = "0.0.0" %}
6
- {% endif %}
7
-
8
- package:
9
- name: lima2-client
10
- version: {{ version }}
11
-
12
- source:
13
- path: ..
14
-
15
- build:
16
- number: {{ environ.get('GIT_DESCRIBE_NUMBER', 0) }}
17
- noarch: python
18
- script: "{{ PYTHON }} -m pip install . -vv"
19
- script_env:
20
- - SETUPTOOLS_SCM_PRETEND_VERSION={{ version }}
21
- entry_points:
22
- - lima2-conductor = lima2.conductor.webservice.cli:cli
23
- - lima2-shell = lima2.client.shell:app
24
-
25
- requirements:
26
- host:
27
- - python>=3.10
28
- - setuptools
29
- - setuptools_scm
30
- run:
31
- - h5py
32
- - jsonschema
33
- - jsonschema-rs
34
- - jsonschema-default
35
- - numpy
36
- - orjson
37
- - pytango
38
- - python
39
- - pyyaml
40
- - requests
41
- - starlette
42
- - typing-extensions
43
- - typer
44
- - termcolor
45
- - uvicorn[standard]
46
-
47
- test:
48
- source_files:
49
- - tests/
50
- requires:
51
- - httpx
52
- - lima2
53
- - pytest
54
- - pytest-asyncio
55
- - pytest-cov
56
- - requests-mock
57
-
58
- about:
59
- home: https://gitlab.esrf.fr/limagroup/lima2-client
60
- license: MIT
61
- license_file: LICENSE
62
- summary: A library for the unified control of 2D detectors
@@ -1,12 +0,0 @@
1
- #!/bin/bash
2
- #
3
- # Run lima2-client unit and integration tests
4
-
5
- pip check
6
-
7
- pytest tests/unit
8
-
9
- # (Only available from PyPI)
10
- pip install nosqltangodb
11
-
12
- pytest tests/integration
@@ -1,10 +0,0 @@
1
- <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 813.0464752980154 623.627757969687" width="813.0464752980154" height="623.627757969687" class="excalidraw-svg">
2
- <!-- svg-source:excalidraw -->
3
-
4
- <defs>
5
- <style class="style-fonts">
6
- @font-face { font-family: Excalifont; src: url(data:font/woff2;base64,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); }
7
- </style>
8
-
9
- </defs>
10
- <rect x="0" y="0" width="813.0464752980154" height="623.627757969687" fill="#ffffff"></rect><g stroke-linecap="round" transform="translate(439.3143650141112 399.10659746501574) rotate(0 108.00850882138684 28.721862111222435)"><path d="M14.36 0 C82.6 -2.63, 151.93 -3.46, 201.66 0 M14.36 0 C57.28 -0.68, 100.95 -0.32, 201.66 0 M201.66 0 C212.63 1.49, 215.06 4.64, 216.02 14.36 M201.66 0 C212.01 0.84, 215.2 2.76, 216.02 14.36 M216.02 14.36 C215.83 19.9, 217.86 28.98, 216.02 43.08 M216.02 14.36 C215.4 22.62, 215.29 32.81, 216.02 43.08 M216.02 43.08 C214.98 53.62, 211.14 55.73, 201.66 57.44 M216.02 43.08 C217.94 52.97, 212.58 56.12, 201.66 57.44 M201.66 57.44 C145.31 57.95, 88.4 58.63, 14.36 57.44 M201.66 57.44 C147.12 57.97, 92.19 57.91, 14.36 57.44 M14.36 57.44 C5.5 55.69, -1.49 51.72, 0 43.08 M14.36 57.44 C6.06 59.1, 0.57 50.42, 0 43.08 M0 43.08 C-0.92 36.41, 1.07 28.57, 0 14.36 M0 43.08 C0.7 35, 0.45 25.41, 0 14.36 M0 14.36 C0.71 3.36, 4.26 0.16, 14.36 0 M0 14.36 C0.59 3.2, 2.57 -2.03, 14.36 0" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-linecap="round" transform="translate(424.73906678108574 390.69777156134717) rotate(0 108.00850882138684 28.721862111222435)"><path d="M14.36 0 C56.72 4.03, 91.96 -0.94, 201.66 0 C211.63 -2.61, 218.44 5.7, 216.02 14.36 C216.18 24.61, 214.59 30.18, 216.02 43.08 C214.34 51.94, 208.03 60.73, 201.66 57.44 C149.12 59.04, 93.44 63.91, 14.36 57.44 C7.63 58.22, 2.24 55.5, 0 43.08 C0.59 31.49, 3.12 24.3, 0 14.36 C2.74 7.89, 7.3 -1.29, 14.36 0" stroke="none" stroke-width="0" fill="#ffffff"></path><path d="M14.36 0 C58.25 -1.74, 98.79 0.43, 201.66 0 M14.36 0 C62.77 0.33, 110.97 1.4, 201.66 0 M201.66 0 C210.69 -0.41, 216.1 4.93, 216.02 14.36 M201.66 0 C211.53 2, 215.45 6.58, 216.02 14.36 M216.02 14.36 C215.1 21.63, 215.25 28.5, 216.02 43.08 M216.02 14.36 C215.87 20.31, 216.48 26.12, 216.02 43.08 M216.02 43.08 C216.11 51.8, 211.82 55.73, 201.66 57.44 M216.02 43.08 C216.76 51.84, 213.5 56.23, 201.66 57.44 M201.66 57.44 C127.46 58.47, 55.46 57.99, 14.36 57.44 M201.66 57.44 C135.34 59.67, 68.15 59.5, 14.36 57.44 M14.36 57.44 C6.14 58.75, -2 54.12, 0 43.08 M14.36 57.44 C2.62 55.52, 0.85 51.71, 0 43.08 M0 43.08 C-1.38 31.98, -1.93 19.34, 0 14.36 M0 43.08 C-0.75 35.25, 0.64 28.16, 0 14.36 M0 14.36 C0.53 3.74, 5.2 -0.96, 14.36 0 M0 14.36 C2.22 5.19, 5.49 -0.57, 14.36 0" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-linecap="round" transform="translate(79.22840632566636 10) rotate(0 102.5 42.5)"><path d="M21.25 0 C77.82 -0.54, 132.76 0.2, 183.75 0 M21.25 0 C68.86 1.88, 118.67 2, 183.75 0 M183.75 0 C198.38 1.09, 204.95 8.8, 205 21.25 M183.75 0 C199.45 -1.09, 203.94 8.7, 205 21.25 M205 21.25 C204.71 28.91, 203.75 38.36, 205 63.75 M205 21.25 C204.3 35.18, 205.58 49.65, 205 63.75 M205 63.75 C206.47 78.53, 196.79 84.87, 183.75 85 M205 63.75 C206.05 79.58, 197.96 85.96, 183.75 85 M183.75 85 C136.65 87.03, 89.32 84.38, 21.25 85 M183.75 85 C129.69 85.28, 75.61 87.16, 21.25 85 M21.25 85 C6.52 84.8, 0.98 76.42, 0 63.75 M21.25 85 C4.85 85.03, -0.02 75.83, 0 63.75 M0 63.75 C-0.43 49.97, 2.05 38, 0 21.25 M0 63.75 C-0.14 50.17, 1.11 36.51, 0 21.25 M0 21.25 C1.99 5.88, 8.86 1.56, 21.25 0 M0 21.25 C-0.24 8.13, 8.32 0.16, 21.25 0" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(98.53849543699448 27.5) rotate(0 83.18991088867188 25)"><text x="83.18991088867188" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">Control software</text><text x="83.18991088867188" y="42.62" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic"></text></g><g stroke-linecap="round" transform="translate(298.47840632566636 10) rotate(0 102.5 42.5)"><path d="M21.25 0 C73.93 0.36, 126 -3.13, 183.75 0 M21.25 0 C79.67 -1.12, 140.48 -2.1, 183.75 0 M183.75 0 C198.11 1.18, 205.85 8.41, 205 21.25 M183.75 0 C199.26 -0.95, 207.17 8.98, 205 21.25 M205 21.25 C203.89 31.02, 204.96 42.04, 205 63.75 M205 21.25 C205.06 38.58, 205.3 55.83, 205 63.75 M205 63.75 C203.98 76.08, 199.09 84.41, 183.75 85 M205 63.75 C203 75.93, 199.73 83.7, 183.75 85 M183.75 85 C142.62 84.51, 101.87 84.16, 21.25 85 M183.75 85 C123.33 85.17, 62.85 83.92, 21.25 85 M21.25 85 C7.68 83.7, 0.85 76.59, 0 63.75 M21.25 85 C6.23 85.06, 1 76.85, 0 63.75 M0 63.75 C-0.17 51.31, 1.06 35.5, 0 21.25 M0 63.75 C-0.8 54.13, -0.78 44.18, 0 21.25 M0 21.25 C-0.07 8.96, 6.01 -0.69, 21.25 0 M0 21.25 C2.03 8.79, 5.13 -0.43, 21.25 0" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(329.8884786523265 27.5) rotate(0 71.08992767333984 25)"><text x="71.08992767333984" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">Monitoring app</text><text x="71.08992767333984" y="42.62" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic"></text></g><g stroke-linecap="round" transform="translate(519.7284063256664 10) rotate(0 102.5 42.5)"><path d="M21.25 0 C59.45 -0.39, 97.92 3.11, 183.75 0 M21.25 0 C81.25 1.53, 143.69 0.82, 183.75 0 M183.75 0 C198.65 -0.73, 206.45 5.49, 205 21.25 M183.75 0 C200.13 1.36, 207.11 8.95, 205 21.25 M205 21.25 C206.62 34.6, 204.76 50.14, 205 63.75 M205 21.25 C205.57 35.83, 204.95 50.63, 205 63.75 M205 63.75 C206.3 78.1, 198.75 86.23, 183.75 85 M205 63.75 C202.83 76.3, 196.96 83.97, 183.75 85 M183.75 85 C147.56 84.04, 114.82 84.46, 21.25 85 M183.75 85 C146.46 85.56, 110.06 84.32, 21.25 85 M21.25 85 C7.86 86.96, 1.61 78.84, 0 63.75 M21.25 85 C5.29 86.88, -1.68 76.67, 0 63.75 M0 63.75 C-1.8 45.36, -1.86 30.64, 0 21.25 M0 63.75 C0.75 54.69, 0.35 43.97, 0 21.25 M0 21.25 C0.37 6.06, 5.31 0.27, 21.25 0 M0 21.25 C-2.01 6.98, 6.89 -0.22, 21.25 0" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(555.6784643090648 27.5) rotate(0 66.54994201660156 25)"><text x="66.54994201660156" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">Data analysis</text><text x="66.54994201660156" y="42.62" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic"></text></g><g stroke-linecap="round" transform="translate(237.99503353381112 197.37069630929193) rotate(0 143.67781723629986 39.18485924626361)"><path d="M19.59 0 C73.45 -2.3, 125.09 -0.58, 267.76 0 M19.59 0 C97.06 -1.26, 175.5 -1.16, 267.76 0 M267.76 0 C279.71 -0.16, 286.04 6.25, 287.36 19.59 M267.76 0 C279.44 2.14, 285.51 5.42, 287.36 19.59 M287.36 19.59 C285.16 30.27, 285.55 40.54, 287.36 58.78 M287.36 19.59 C286.89 28.88, 286.55 39.48, 287.36 58.78 M287.36 58.78 C285.89 73.69, 278.86 79.86, 267.76 78.37 M287.36 58.78 C286.19 73.74, 282.49 80, 267.76 78.37 M267.76 78.37 C178.71 78.57, 90.36 77.69, 19.59 78.37 M267.76 78.37 C187.4 79.01, 107.34 79.2, 19.59 78.37 M19.59 78.37 C8.16 77.81, -0.33 70.55, 0 58.78 M19.59 78.37 C6.66 76.09, -1.46 74.04, 0 58.78 M0 58.78 C-0.01 49.19, -1.97 37.75, 0 19.59 M0 58.78 C-0.04 46.41, -0.79 33.38, 0 19.59 M0 19.59 C-1.85 7.47, 7.9 1.62, 19.59 0 M0 19.59 C-0.77 8.27, 4.71 2.03, 19.59 0" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.8" fill-opacity="0.8" transform="translate(275.4086143199156 220.17003386533986) rotate(0 106.26423645019531 16.385521690215683)"><text x="106.26423645019531" y="23.097031374528033" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="26.2168347043451px" fill="#1971c2" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">Lima2 Conductor</text></g><g stroke-linecap="round"><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(212.36512119933252 198.8579741551943) rotate(337.7795140400697 -4.993427224816088 -42.497427048625326)"><path d="M-0.83 0.77 C-2.5 -6.01, -9.52 -26.42, -10.44 -40.6 C-11.37 -54.78, -6.96 -76.77, -6.37 -84.33 M0.94 0.12 C-0.89 -6.55, -10.25 -25.21, -11.63 -39.62 C-13.01 -54.03, -8.08 -78.7, -7.32 -86.33" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(212.36512119933252 198.8579741551943) rotate(337.7795140400697 -4.993427224816088 -42.497427048625326)"><path d="M-2.61 -64.01 C-2.59 -70.7, -6.88 -76.44, -7.32 -86.33 M-2.61 -64.01 C-4.51 -71.44, -5.38 -80.5, -7.32 -86.33" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(212.36512119933252 198.8579741551943) rotate(337.7795140400697 -4.993427224816088 -42.497427048625326)"><path d="M-18.06 -66.2 C-13.95 -72.21, -14.15 -77.37, -7.32 -86.33 M-18.06 -66.2 C-14.49 -72.73, -9.86 -81.01, -7.32 -86.33" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(219.67978684693782 108.5121484260302) rotate(337.7795140400697 2.119049574325686 42.8693161974567)"><path d="M-0.45 -1.06 C-0.56 6.64, -2.3 32.64, -1.47 46.94 C-0.64 61.25, 3.44 78.19, 4.5 84.77 M1.51 1 C1.28 8.28, -3.51 31.07, -2.6 45.17 C-1.7 59.26, 5.69 79.08, 6.94 85.58" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(219.67978684693782 108.5121484260302) rotate(337.7795140400697 2.119049574325686 42.8693161974567)"><path d="M-4.61 69.26 C-3.6 72.48, 1.94 75.41, 6.94 85.58 M-4.61 69.26 C-1.72 72.18, 1.23 76.33, 6.94 85.58" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(219.67978684693782 108.5121484260302) rotate(337.7795140400697 2.119049574325686 42.8693161974567)"><path d="M8.58 65.65 C6.57 69.66, 9.06 73.42, 6.94 85.58 M8.58 65.65 C8.57 69.43, 8.62 74.37, 6.94 85.58" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(367.6784597229573 188.44379957255757) rotate(357.42796271532734 5.259413404701206 -39.04584199061077)"><path d="M0.01 0.87 C0.92 -5.73, 2.29 -25.98, 4.24 -39.24 C6.18 -52.49, 10.69 -72.35, 11.68 -78.66 M-1.44 0.29 C-0.6 -6.7, 1.07 -28.02, 3.23 -41.01 C5.39 -54, 10.35 -71.29, 11.53 -77.64" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(367.6784597229573 188.44379957255757) rotate(357.42796271532734 5.259413404701206 -39.04584199061077)"><path d="M13.89 -58.45 C14.77 -62.48, 13.96 -64.27, 11.53 -77.64 M13.89 -58.45 C12.44 -63.2, 12.9 -67.92, 11.53 -77.64" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(367.6784597229573 188.44379957255757) rotate(357.42796271532734 5.259413404701206 -39.04584199061077)"><path d="M1 -61.42 C4.47 -64.86, 6.24 -66.05, 11.53 -77.64 M1 -61.42 C2.8 -65.53, 6.51 -69.5, 11.53 -77.64" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(398.7466160790839 109.28780367957773) rotate(357.42796271532734 -8.535325631900946 39.51662451337384)"><path d="M-0.12 0.67 C-2.06 7, -8.76 25.65, -11.63 38.88 C-14.51 52.11, -16.29 73.32, -17.38 80.03 M-1.64 -0.03 C-3.64 6.38, -9.19 27.08, -11.97 40.12 C-14.75 53.16, -17.22 71.52, -18.31 78.21" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(398.7466160790839 109.28780367957773) rotate(357.42796271532734 -8.535325631900946 39.51662451337384)"><path d="M-22.23 58.69 C-19.8 66.5, -20.67 69.93, -18.31 78.21 M-22.23 58.69 C-20.75 66.37, -18.74 74.1, -18.31 78.21" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(398.7466160790839 109.28780367957773) rotate(357.42796271532734 -8.535325631900946 39.51662451337384)"><path d="M-8.76 60.74 C-10.4 67.92, -15.32 70.73, -18.31 78.21 M-8.76 60.74 C-12.43 67.65, -15.58 74.59, -18.31 78.21" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(577.8099329636148 107.66211424577801) rotate(24.0907651429369 -12.902337789406829 49.36350740028735)"><path d="M0.06 0.15 C-1.87 8.09, -6.36 31.46, -10.65 48 C-14.94 64.54, -23.24 91.09, -25.7 99.39 M-1.36 -0.81 C-3 7.23, -4.19 32.79, -8.36 49.15 C-12.54 65.52, -23.64 89.18, -26.41 97.4" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(577.8099329636148 107.66211424577801) rotate(24.0907651429369 -12.902337789406829 49.36350740028735)"><path d="M-25.72 72.41 C-25.65 80.56, -27.38 91.59, -26.41 97.4 M-25.72 72.41 C-25.41 80.56, -26.35 89.69, -26.41 97.4" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(577.8099329636148 107.66211424577801) rotate(24.0907651429369 -12.902337789406829 49.36350740028735)"><path d="M-9.82 78.7 C-15.81 84.47, -23.59 93.1, -26.41 97.4 M-9.82 78.7 C-15.18 84.49, -21.77 91.39, -26.41 97.4" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(540.7177238454382 195.29843990221218) rotate(24.0907651429369 7.271059564226391 -44.49749778353532)"><path d="M-0.81 -0.73 C1 -8.16, 8.32 -29.58, 10.94 -44.44 C13.56 -59.3, 14.2 -82.33, 14.9 -89.9 M0.96 1.51 C2.62 -6.29, 7.82 -31.12, 10.05 -46.21 C12.27 -61.3, 13.38 -81.89, 14.32 -89.06" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(540.7177238454382 195.29843990221218) rotate(24.0907651429369 7.271059564226391 -44.49749778353532)"><path d="M19.85 -67.74 C16.92 -74.11, 17.55 -80.19, 14.32 -89.06 M19.85 -67.74 C18.29 -73.05, 17.31 -76.44, 14.32 -89.06" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(540.7177238454382 195.29843990221218) rotate(24.0907651429369 7.271059564226391 -44.49749778353532)"><path d="M4.85 -69.17 C6.5 -75.01, 11.71 -80.65, 14.32 -89.06 M4.85 -69.17 C6.67 -74.05, 9.06 -77.12, 14.32 -89.06" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(581.6728507701107 157.16666666666674) rotate(0 17.884033203125 10)"><text x="0" y="14.096" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">http</text></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(406.201731471628 152.8138195923355) rotate(0 17.884033203125 10)"><text x="0" y="14.096" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">http</text></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(152.96288617876098 152.6009790772746) rotate(0 17.884033203125 10)"><text x="0" y="14.096" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">http</text></g><g stroke-linecap="round"><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(82.79642956112741 62.457336157271044) rotate(0 98.99376616004719 -0.5555555555555571)"><path d="M-0.07 0.45 C33.14 0.39, 166.23 -1.06, 199.07 -1.2 M-1.56 -0.37 C31.6 -0.16, 165.21 0.62, 198.69 0.28" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(304.4096467141818 61.0985908708827) rotate(0 97.18613325383404 0)"><path d="M0.03 0.74 C32.78 0.83, 163.11 0.35, 195.36 0.1 M-1.42 0.08 C31.37 0.43, 162.03 1.68, 194.94 1.69" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(523.7665836444044 62.72400133559759) rotate(0 97.18613325383404 0)"><path d="M-0.12 -0.93 C32.05 -1.09, 160.93 -0.44, 193.48 -0.11 M-1.65 1.19 C30.87 1.15, 162.97 1.69, 195.72 1.37" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-opacity="0.8" fill-opacity="0.8" transform="translate(139.48434199461167 70.69444444444446) rotate(0 42.24406433105469 10)"><text x="42.24406433105469" y="14.096" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="16px" fill="#1971c2" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">lima2.client</text></g><g stroke-opacity="0.8" fill-opacity="0.8" transform="translate(359.73434199461167 70.69444444444446) rotate(0 42.24406433105469 10)"><text x="42.24406433105469" y="14.096" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="16px" fill="#1971c2" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">lima2.client</text></g><g stroke-opacity="0.8" fill-opacity="0.8" transform="translate(579.9843419946117 70.69444444444446) rotate(0 42.24406433105469 10)"><text x="42.24406433105469" y="14.096" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="16px" fill="#1971c2" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">lima2.client</text></g><g stroke-opacity="0.3" fill-opacity="0.3" stroke-linecap="round" transform="translate(10 63.87881612740381) rotate(0 393.83784897167857 111.72228509323762)"><path d="M32 0 C225.23 -3.06, 417.8 -2.63, 755.68 0 M755.68 0 C777.73 -0.37, 785.76 9.35, 787.68 32 M787.68 32 C787.95 67.26, 788.87 105.2, 787.68 191.44 M787.68 191.44 C787.55 214.12, 776.35 223.67, 755.68 223.44 M755.68 223.44 C608.45 224.9, 461.27 224.85, 32 223.44 M32 223.44 C11.63 221.71, -0.53 210.84, 0 191.44 M0 191.44 C0.59 137.92, 0.08 84.56, 0 32 M0 32 C-1.31 11.18, 12.51 1.27, 32 0" stroke="#1e1e1e" stroke-width="1" fill="none" stroke-dasharray="8 8.5"></path></g><g stroke-linecap="round" transform="translate(139.1741321125411 387.11691076927184) rotate(0 108.00850882138684 28.721862111222435)"><path d="M14.36 0 C72.86 0.79, 135.18 1.59, 201.66 0 M14.36 0 C59.2 2.44, 105.88 2.76, 201.66 0 M201.66 0 C211.45 -1.84, 215.72 3.77, 216.02 14.36 M201.66 0 C209.71 1.72, 215.17 6.21, 216.02 14.36 M216.02 14.36 C217.65 22.42, 217.56 28.2, 216.02 43.08 M216.02 14.36 C215.42 24.51, 215.07 34.62, 216.02 43.08 M216.02 43.08 C215.75 53.33, 209.75 58.21, 201.66 57.44 M216.02 43.08 C215.07 54.18, 209.36 56.41, 201.66 57.44 M201.66 57.44 C131.3 56.24, 61.17 54.85, 14.36 57.44 M201.66 57.44 C129.87 57.36, 58.32 57.63, 14.36 57.44 M14.36 57.44 C6.28 58.07, -1.51 53.89, 0 43.08 M14.36 57.44 C4.5 58.55, -0.4 53.47, 0 43.08 M0 43.08 C0.94 38.41, 1.69 28.09, 0 14.36 M0 43.08 C-0.09 36.91, 0.42 28.56, 0 14.36 M0 14.36 C-1.49 5.78, 5.58 0.46, 14.36 0 M0 14.36 C0.14 6.26, 4.48 -0.81, 14.36 0" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.8" fill-opacity="0.8" transform="translate(159.78201379769746 399.4532511902786) rotate(0 87.40062713623047 16.385521690215683)"><text x="87.40062713623047" y="23.097031374528033" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="26.2168347043451px" fill="#c2255c" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">Lima2 Control</text></g><g stroke-linecap="round" transform="translate(409.6031801544824 382.2889456576785) rotate(0 108.00850882138684 28.721862111222435)"><path d="M14.36 0 C63.82 -3.94, 118.7 -3.38, 201.66 0 C212.84 -2.37, 217.18 1.53, 216.02 14.36 C215.36 24.38, 216.36 34.55, 216.02 43.08 C219.14 51.76, 214.03 56.47, 201.66 57.44 C143.47 54.47, 84.55 52.72, 14.36 57.44 C5.62 58.65, -0.76 52.13, 0 43.08 C-1.32 34.4, -2.86 24.74, 0 14.36 C-1.27 8.34, 2.89 3.26, 14.36 0" stroke="none" stroke-width="0" fill="#ffffff"></path><path d="M14.36 0 C74.66 -1.71, 132.89 1.25, 201.66 0 M14.36 0 C83.67 -0.75, 154.04 -2.44, 201.66 0 M201.66 0 C209.94 0.72, 214.42 2.82, 216.02 14.36 M201.66 0 C210.92 0.41, 213.93 2.77, 216.02 14.36 M216.02 14.36 C214.74 19.29, 214.82 27.79, 216.02 43.08 M216.02 14.36 C216.46 26.17, 215.27 35.56, 216.02 43.08 M216.02 43.08 C216.1 54.19, 211.57 56.7, 201.66 57.44 M216.02 43.08 C215.04 52.49, 211.38 58.53, 201.66 57.44 M201.66 57.44 C144.31 58.71, 83.32 57.51, 14.36 57.44 M201.66 57.44 C144.3 57.15, 86.32 57.44, 14.36 57.44 M14.36 57.44 C3 56.38, -1.85 54.47, 0 43.08 M14.36 57.44 C6.04 56.21, 1.9 50.51, 0 43.08 M0 43.08 C-0.01 35, 0.15 24.14, 0 14.36 M0 43.08 C0.32 32.4, -0.45 20.69, 0 14.36 M0 14.36 C0.19 5.36, 4.71 1.99, 14.36 0 M0 14.36 C-1.96 5.86, 4.5 -1.64, 14.36 0" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-linecap="round" transform="translate(390.5795489998619 372.8458424186258) rotate(0 108.00850882138684 28.721862111222435)"><path d="M14.36 0 C68.44 0.28, 123.11 -1.75, 201.66 0 C212.9 -3.47, 215.32 2.83, 216.02 14.36 C219.74 23.22, 219.72 31.57, 216.02 43.08 C214.62 55.28, 213.8 53.85, 201.66 57.44 C151.59 60.27, 102.39 58.84, 14.36 57.44 C5.1 56.26, -3.46 55.19, 0 43.08 C-2.07 32.14, -3.82 24.67, 0 14.36 C3.04 2.79, 4.32 -1.48, 14.36 0" stroke="none" stroke-width="0" fill="#ffffff"></path><path d="M14.36 0 C60.17 -2.02, 107.44 -0.43, 201.66 0 M14.36 0 C69.1 -1.14, 124.15 -2.22, 201.66 0 M201.66 0 C212.11 0.42, 217.32 5.28, 216.02 14.36 M201.66 0 C211.86 0.32, 217.58 7.08, 216.02 14.36 M216.02 14.36 C214.63 22.43, 216.87 30.56, 216.02 43.08 M216.02 14.36 C216.32 23.82, 215.73 31.4, 216.02 43.08 M216.02 43.08 C217.45 54.42, 210.36 56.11, 201.66 57.44 M216.02 43.08 C218.31 51.92, 210.8 55.56, 201.66 57.44 M201.66 57.44 C150.61 59.31, 101.12 58.09, 14.36 57.44 M201.66 57.44 C143.64 57.02, 86.26 56.46, 14.36 57.44 M14.36 57.44 C2.97 57.58, -0.91 52.33, 0 43.08 M14.36 57.44 C6.26 55.52, 0.11 50.46, 0 43.08 M0 43.08 C1.21 32.46, 1.29 23.32, 0 14.36 M0 43.08 C0.75 34.16, 0.55 25.08, 0 14.36 M0 14.36 C0.85 3.95, 5.42 -0.95, 14.36 0 M0 14.36 C-0.87 3.7, 5.5 -0.31, 14.36 0" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.8" fill-opacity="0.8" transform="translate(404.704818075155 385.18218283963256) rotate(0 93.88323974609375 16.385521690215683)"><text x="93.88323974609375" y="23.097031374528033" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="26.2168347043451px" fill="#c2255c" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">Lima2 Receiver</text></g><g stroke-linecap="round"><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(258.1114253707336 294.585950138414) rotate(196.4235165086758 4.105887224339256 35.99659994002985)"><path d="M-0.39 0.66 C1.07 6.27, 7.6 20.89, 8.48 32.62 C9.36 44.34, 5.34 64.44, 4.88 71.01 M1.61 -0.04 C2.95 5.76, 7.25 21.59, 7.67 33.56 C8.09 45.54, 4.33 65.22, 4.13 71.8" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(258.1114253707336 294.585950138414) rotate(196.4235165086758 4.105887224339256 35.99659994002985)"><path d="M-0.52 53.18 C1.67 58.83, 0.11 63.63, 4.13 71.8 M-0.52 53.18 C-0.08 57.37, 1.38 61.99, 4.13 71.8" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(258.1114253707336 294.585950138414) rotate(196.4235165086758 4.105887224339256 35.99659994002985)"><path d="M12.54 54.55 C11.09 59.78, 5.88 64.19, 4.13 71.8 M12.54 54.55 C10.12 58.45, 8.74 62.76, 4.13 71.8" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(275.0905361051666 370.93493677310994) rotate(196.4235165086758 -1.784867920930651 -36.93970368243015)"><path d="M0.27 -1.13 C0.49 -7.89, 1.6 -27.81, 0.95 -39.93 C0.3 -52.06, -2.58 -68.26, -3.63 -73.88 M-1.05 0.89 C-0.95 -5.81, 0.49 -26.67, 0.01 -38.91 C-0.47 -51.16, -3 -66.97, -3.94 -72.57" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(275.0905361051666 370.93493677310994) rotate(196.4235165086758 -1.784867920930651 -36.93970368243015)"><path d="M4.63 -57.11 C0.59 -61.21, -1.5 -64.07, -3.94 -72.57 M4.63 -57.11 C1.94 -61.08, -0.77 -66.13, -3.94 -72.57" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(275.0905361051666 370.93493677310994) rotate(196.4235165086758 -1.784867920930651 -36.93970368243015)"><path d="M-7.31 -55.21 C-8.17 -59.85, -7.06 -63.22, -3.94 -72.57 M-7.31 -55.21 C-6.41 -59.77, -5.54 -65.39, -3.94 -72.57" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(197.85503928078907 306.9412743110191) rotate(0 22.680038452148438 10)"><text x="0" y="14.096" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">tango</text></g><g stroke-linecap="round"><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(489.64921120383497 286.9452923253423) rotate(342.83343752515907 4.105887224339256 35.99659994002985)"><path d="M-0.9 -0.59 C0.64 5.32, 7.45 22.4, 8.37 34.65 C9.3 46.91, 5.17 66.53, 4.64 72.94 M0.83 1.71 C2.3 7.36, 7.02 21.44, 7.51 33.01 C8 44.57, 4.08 64.74, 3.75 71.1" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(489.64921120383497 286.9452923253423) rotate(342.83343752515907 4.105887224339256 35.99659994002985)"><path d="M-0.65 52.41 C-0.71 57.03, 2.71 60.72, 3.75 71.1 M-0.65 52.41 C0.69 58.51, 3.04 66.9, 3.75 71.1" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(489.64921120383497 286.9452923253423) rotate(342.83343752515907 4.105887224339256 35.99659994002985)"><path d="M12.39 53.96 C9.32 58.11, 9.72 61.45, 3.75 71.1 M12.39 53.96 C8.79 59.59, 6.19 67.39, 3.75 71.1" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(480.4503734109253 339.1804219043958) rotate(342.83343752515907 -1.7305808882549627 -24.58132036899562)"><path d="M0.07 0.41 C0.29 -1.84, 1.62 -5.61, 0.89 -13.79 C0.16 -21.97, -3.39 -42.67, -4.32 -48.65 M-0.55 0.15 C-0.38 -2.22, 1.08 -6.27, 0.4 -14.53 C-0.27 -22.8, -3.75 -43.63, -4.6 -49.45" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(480.4503734109253 339.1804219043958) rotate(342.83343752515907 -1.7305808882549627 -24.58132036899562)"><path d="M3.92 -33.96 C2.71 -37.62, 0.82 -40.72, -4.6 -49.45 M3.92 -33.96 C0.74 -39.93, -3.15 -45.86, -4.6 -49.45" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(480.4503734109253 339.1804219043958) rotate(342.83343752515907 -1.7305808882549627 -24.58132036899562)"><path d="M-8.03 -32.11 C-6.55 -36.19, -5.74 -39.71, -4.6 -49.45 M-8.03 -32.11 C-6.51 -38.74, -5.71 -45.4, -4.6 -49.45" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(420.01520378957855 303.7184812316589) rotate(0 22.680038452148438 10)"><text x="0" y="14.096" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">tango</text></g><g stroke-opacity="0.3" fill-opacity="0.3" stroke-linecap="round" transform="translate(94.78765104466208 338.97943707931074) rotate(0 308.62357299829847 77.83989466209346)"><path d="M32 0 C156.27 -0.14, 280.03 0.46, 585.25 0 M585.25 0 C608.1 -0.9, 617.56 12.34, 617.25 32 M617.25 32 C615.32 51.39, 616.33 71.38, 617.25 123.68 M617.25 123.68 C618.88 146.12, 604.97 155.97, 585.25 155.68 M585.25 155.68 C412.3 153.97, 238.69 154.06, 32 155.68 M32 155.68 C9.78 155.6, 0.38 144.96, 0 123.68 M0 123.68 C-1.34 106.86, 2.3 84.57, 0 32 M0 32 C-1.3 10.13, 10.91 0.4, 32 0" stroke="#1e1e1e" stroke-width="1" fill="none" stroke-dasharray="8 8.5"></path></g><a href="https://gitlab.esrf.fr/limagroup/lima2"><g stroke-opacity="0.3" fill-opacity="0.3" transform="translate(503.83313002839054 469.9017355785031) rotate(0 87.21615600585938 10)"><text x="174.43231201171875" y="14.096" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="end" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">(repo: limagroup/lima2)</text></g></a><a href="https://gitlab.esrf.fr/limagroup/lima2-client"><g stroke-opacity="0.3" fill-opacity="0.3" transform="translate(548.4632503034181 265.7070083558028) rotate(0 111.21620178222656 10)"><text x="222.43240356445312" y="14.096" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="end" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">(repo: limagroup/lima2-client)</text></g></a><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(719.6693843794108 332.53887903075173) rotate(0 24.469970703125 12.500000000000028)"><text x="0" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#c2255c" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">(c++)</text></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(719.9265564747731 302.53492556864836) rotate(0 41.55995941162115 12.5)"><text x="0" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1971c2" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">(python)</text></g><g stroke-opacity="0.9" fill-opacity="0.9" stroke-linecap="round" transform="translate(340.4757776338562 551.8365924043843) rotate(0 62.935446409104486 30.89558278265133)"><path d="M-0.01 -0.15 L125.93 -0.41 L125.53 61.09 L-1.6 60.57" stroke="none" stroke-width="0" fill="#ffffff"></path><path d="M0 0 C36.85 0.2, 72.95 -1.68, 125.87 0 M0 0 C36.57 0.34, 73.35 -0.67, 125.87 0 M125.87 0 C126.09 20.87, 126.61 41.13, 125.87 61.79 M125.87 0 C126.92 22.16, 126.85 43.7, 125.87 61.79 M125.87 61.79 C93.61 59.58, 60.59 60.52, 0 61.79 M125.87 61.79 C97.39 60.78, 70.14 61.8, 0 61.79 M0 61.79 C1.01 39.36, 2.26 13.36, 0 0 M0 61.79 C-0.54 41.05, 0.16 19.08, 0 0" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.9" fill-opacity="0.9" stroke-linecap="round" transform="translate(381.69657759647237 559.7907506282543) rotate(0 21.714646446488302 21.714646446488302)"><path d="M25.8 0.58 C30.23 1.16, 35.86 4.83, 38.8 8.32 C41.75 11.81, 43.59 16.96, 43.48 21.52 C43.36 26.09, 41.11 32.02, 38.1 35.69 C35.1 39.35, 29.95 42.79, 25.45 43.5 C20.95 44.22, 15.17 42.39, 11.11 39.97 C7.05 37.54, 2.75 33.34, 1.09 28.97 C-0.57 24.6, -0.53 18.18, 1.14 13.76 C2.81 9.33, 6.95 4.57, 11.11 2.4 C15.27 0.24, 23.38 0.91, 26.08 0.75 C28.78 0.59, 27.37 1.11, 27.31 1.45 M19.46 0.74 C23.69 0.19, 29.86 1.11, 33.84 3.81 C37.82 6.51, 42.01 12.46, 43.34 16.94 C44.67 21.42, 44.03 26.69, 41.82 30.68 C39.6 34.67, 34.43 38.98, 30.04 40.87 C25.64 42.76, 19.81 43.28, 15.46 42.04 C11.11 40.79, 6.6 37.11, 3.95 33.4 C1.29 29.7, -0.87 24.37, -0.46 19.82 C-0.04 15.27, 2.91 9.31, 6.41 6.09 C9.92 2.87, 18.29 1.51, 20.56 0.5 C22.83 -0.51, 20.16 -0.3, 20.02 0.03" stroke="none" stroke-width="0" fill="#ffffff"></path><path d="M18.15 -0.09 C22.49 -0.94, 29.47 1.03, 33.48 3.47 C37.49 5.91, 40.74 10.12, 42.2 14.56 C43.67 18.99, 44.02 25.72, 42.3 30.1 C40.57 34.48, 35.99 38.77, 31.85 40.84 C27.72 42.91, 22.02 43.43, 17.48 42.53 C12.93 41.64, 7.55 39.07, 4.58 35.49 C1.61 31.9, -0.57 25.8, -0.35 21.03 C-0.12 16.26, 2.6 10.38, 5.93 6.85 C9.27 3.32, 17.35 0.83, 19.67 -0.15 C21.99 -1.13, 19.9 0.5, 19.85 0.95 M25.82 0.8 C30.22 1.41, 36.12 4.55, 39.15 8.03 C42.19 11.52, 44.31 17.05, 44.04 21.71 C43.76 26.37, 40.62 32.29, 37.51 35.99 C34.41 39.69, 29.88 43.31, 25.4 43.93 C20.92 44.56, 14.71 42.32, 10.64 39.74 C6.56 37.17, 2.52 32.75, 0.96 28.49 C-0.6 24.22, -0.52 18.52, 1.26 14.15 C3.04 9.78, 7.51 4.56, 11.64 2.25 C15.77 -0.05, 23.61 0.5, 26.05 0.34 C28.49 0.18, 26.44 0.97, 26.28 1.32" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.9" fill-opacity="0.9" stroke-linecap="round" transform="translate(385.32254894113703 563.4167219729189) rotate(0 18.08867510182364 18.08867510182364)"><path d="M16.41 -0.15 C20.18 -0.51, 25.79 1.46, 29.03 3.76 C32.26 6.06, 34.96 9.99, 35.82 13.64 C36.68 17.29, 35.97 22.24, 34.19 25.67 C32.4 29.1, 28.59 32.57, 25.13 34.23 C21.66 35.89, 17.08 36.67, 13.39 35.64 C9.71 34.61, 5.24 31.2, 3.01 28.04 C0.79 24.87, -0.42 20.45, 0.07 16.63 C0.56 12.81, 3 7.88, 5.96 5.11 C8.91 2.34, 15.71 0.81, 17.79 0.03 C19.88 -0.74, 18.45 0.1, 18.46 0.47 M19.47 0.5 C23.02 0.44, 27.74 1.95, 30.39 4.46 C33.05 6.97, 35.03 11.63, 35.41 15.55 C35.78 19.46, 34.63 24.56, 32.64 27.96 C30.66 31.35, 27.19 34.9, 23.51 35.9 C19.84 36.91, 14.26 35.72, 10.59 33.98 C6.92 32.23, 3.22 28.81, 1.48 25.43 C-0.25 22.04, -0.93 17.22, 0.17 13.67 C1.27 10.12, 4.87 6.29, 8.08 4.13 C11.29 1.97, 17.63 1.21, 19.41 0.71 C21.2 0.21, 18.82 1.02, 18.81 1.12" stroke="none" stroke-width="0" fill="#1e1e1e"></path><path d="M17.17 -0.32 C20.85 -0.8, 26.08 0.98, 29.11 3.46 C32.14 5.95, 34.5 10.75, 35.36 14.58 C36.22 18.41, 36.05 23.04, 34.26 26.42 C32.48 29.8, 28.37 33.44, 24.64 34.87 C20.91 36.3, 15.59 36.16, 11.88 35 C8.16 33.84, 4.3 31.1, 2.36 27.91 C0.42 24.71, -0.32 19.73, 0.25 15.82 C0.83 11.92, 2.9 7.04, 5.82 4.46 C8.73 1.89, 15.72 1.11, 17.75 0.38 C19.78 -0.34, 18.01 -0.19, 18.01 0.13 M16.8 0.5 C20.62 -0.15, 25.53 1.27, 28.61 3.36 C31.7 5.45, 34.4 9.32, 35.31 13.05 C36.21 16.77, 35.71 22.27, 34.07 25.72 C32.42 29.16, 28.92 32.18, 25.43 33.72 C21.94 35.26, 16.74 35.9, 13.13 34.95 C9.52 34, 6.01 31.13, 3.76 28.02 C1.51 24.91, -0.68 20.04, -0.37 16.28 C-0.07 12.51, 2.81 8.12, 5.58 5.45 C8.35 2.79, 14.55 1.18, 16.25 0.3 C17.95 -0.58, 15.74 -0.1, 15.78 0.18" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-linecap="round" transform="translate(401.5867744934246 569.1876321154319) rotate(0 1.8244495495359843 1.3031782496685764)"><path d="M1.74 -0.01 C2.18 0, 2.81 0.05, 3.07 0.2 C3.33 0.36, 3.3 0.69, 3.32 0.92 C3.34 1.15, 3.32 1.3, 3.19 1.61 C3.06 1.92, 2.9 2.64, 2.55 2.8 C2.2 2.96, 1.49 2.76, 1.09 2.58 C0.69 2.4, 0.37 1.94, 0.16 1.73 C-0.05 1.52, -0.26 1.57, -0.17 1.34 C-0.08 1.11, 0.35 0.51, 0.69 0.34 C1.03 0.16, 1.68 0.36, 1.88 0.3 C2.09 0.24, 1.94 0.03, 1.94 -0.03 M1.51 0.38 C1.87 0.28, 2.97 -0.22, 3.35 -0.07 C3.73 0.07, 3.76 0.92, 3.81 1.25 C3.86 1.58, 3.82 1.78, 3.66 1.92 C3.5 2.06, 3.32 1.96, 2.85 2.1 C2.39 2.24, 1.34 2.8, 0.89 2.74 C0.43 2.69, 0.27 2.05, 0.1 1.77 C-0.07 1.5, -0.26 1.31, -0.14 1.1 C-0.02 0.88, 0.4 0.6, 0.81 0.49 C1.22 0.39, 2.13 0.58, 2.32 0.47 C2.51 0.36, 1.97 -0.13, 1.94 -0.19" stroke="none" stroke-width="0" fill="#ffffff"></path><path d="M1.87 -0.32 C2.24 -0.39, 2.44 -0.28, 2.68 -0.07 C2.91 0.15, 3.18 0.63, 3.29 0.95 C3.41 1.27, 3.51 1.56, 3.37 1.86 C3.23 2.16, 2.8 2.63, 2.48 2.74 C2.16 2.85, 1.84 2.63, 1.46 2.5 C1.08 2.37, 0.43 2.24, 0.21 1.96 C-0.02 1.69, 0.06 1.06, 0.11 0.85 C0.16 0.63, 0.18 0.78, 0.51 0.66 C0.84 0.53, 1.78 0.27, 2.06 0.11 C2.34 -0.04, 2.16 -0.31, 2.16 -0.26 M1.98 0.21 C2.38 0.29, 2.48 0.63, 2.83 0.82 C3.18 1.02, 3.99 1.24, 4.07 1.38 C4.15 1.52, 3.62 1.54, 3.31 1.68 C3 1.82, 2.62 2.09, 2.22 2.21 C1.82 2.33, 1.24 2.48, 0.9 2.4 C0.56 2.33, 0.36 2.01, 0.17 1.76 C-0.03 1.51, -0.32 1.13, -0.28 0.91 C-0.23 0.69, 0.1 0.63, 0.44 0.47 C0.79 0.3, 1.49 -0.03, 1.8 -0.09 C2.11 -0.15, 2.23 0.11, 2.31 0.1" stroke="#ffffff" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.9" fill-opacity="0.9" stroke-linecap="round" transform="translate(350.22988090300066 546.0623609770222) rotate(0 6.718197275191358 2.5593132476919322)"><path d="M0 0 C2.86 -0.1, 6.23 0.44, 13.44 0 M0 0 C3.54 -0.03, 7.58 0.24, 13.44 0 M13.44 0 C13.3 1.2, 13.42 2.7, 13.44 5.12 M13.44 0 C13.47 2.05, 13.4 3.85, 13.44 5.12 M13.44 5.12 C9.53 4.62, 5.29 4.64, 0 5.12 M13.44 5.12 C9.45 4.99, 5.07 5.11, 0 5.12 M0 5.12 C-0.15 3.01, 0.21 1.05, 0 0 M0 5.12 C-0.05 3.64, 0.03 2.09, 0 0" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.9" fill-opacity="0.9" transform="translate(475.57828552537467 568.2326503086624) rotate(0 33.76997375488281 12.5)"><text x="0" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">Camera</text></g><g stroke-linecap="round"><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(306.0781824716445 459.4276630456484) rotate(163.93583932999914 5.147015936426897 39.27351185634649)"><path d="M-0.28 -1.08 C1.6 5.66, 9 27.77, 10.18 40.91 C11.37 54.06, 7.25 71.38, 6.83 77.8 M1.78 0.97 C3.59 7.32, 8.47 26.15, 9.17 39.11 C9.88 52.07, 6.15 72.35, 6 78.72" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(306.0781824716445 459.4276630456484) rotate(163.93583932999914 5.147015936426897 39.27351185634649)"><path d="M1.25 60.12 C0.58 63.83, 4.28 67.68, 6 78.72 M1.25 60.12 C1.82 65.33, 3.58 69.09, 6 78.72" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(306.0781824716445 459.4276630456484) rotate(163.93583932999914 5.147015936426897 39.27351185634649)"><path d="M14.32 61.42 C10.92 64.82, 11.9 68.41, 6 78.72 M14.32 61.42 C11.78 66.42, 10.43 69.87, 6 78.72" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(326.3131533978724 535.01006481864) rotate(163.93583932999914 -4.006260546056183 -39.56411133130405)"><path d="M-0.11 0.61 C0.07 -5.82, 2.17 -26.55, 0.82 -39.69 C-0.54 -52.84, -6.48 -71.84, -8.25 -78.24 M-1.63 -0.11 C-1.59 -6.32, 0.98 -25.22, -0.19 -38.55 C-1.36 -51.89, -7.01 -73.2, -8.64 -80.12" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(326.3131533978724 535.01006481864) rotate(163.93583932999914 -4.006260546056183 -39.56411133130405)"><path d="M2.84 -62.91 C0.84 -67.89, -4.61 -71.28, -8.64 -80.12 M2.84 -62.91 C-1.37 -69.07, -6.56 -75.48, -8.64 -80.12" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(326.3131533978724 535.01006481864) rotate(163.93583932999914 -4.006260546056183 -39.56411133130405)"><path d="M-10.91 -59.55 C-9.08 -65.45, -10.72 -69.77, -8.64 -80.12 M-10.91 -59.55 C-9.96 -67.08, -10.01 -74.75, -8.64 -80.12" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(466.7379038509956 467.4076988123911) rotate(387.24699775313775 4.105887224339256 35.99659994002985)"><path d="M0.11 0.63 C1.25 6.25, 6.59 21.05, 7.34 32.92 C8.09 44.78, 5.14 65.28, 4.62 71.83 M-1.28 -0.09 C0.18 5.73, 8.76 21.83, 9.59 34.02 C10.43 46.21, 4.64 66.49, 3.73 73.06" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(466.7379038509956 467.4076988123911) rotate(387.24699775313775 4.105887224339256 35.99659994002985)"><path d="M0.87 54.07 C2.73 59.18, 1.37 66.68, 3.73 73.06 M0.87 54.07 C2.52 59.56, 3.28 64.33, 3.73 73.06" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(466.7379038509956 467.4076988123911) rotate(387.24699775313775 4.105887224339256 35.99659994002985)"><path d="M13.74 56.68 C11.2 60.91, 5.44 67.51, 3.73 73.06 M13.74 56.68 C11.73 61.45, 8.8 65.46, 3.73 73.06" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(464.4223394214108 534.5333926147692) rotate(387.24699775313775 -1.784867920930651 -36.93970368243015)"><path d="M-0.87 -0.83 C-0.78 -7.45, 1.41 -26.97, 0.69 -39.11 C-0.02 -51.25, -4.49 -67.91, -5.16 -73.69 M0.87 1.35 C0.78 -5.14, 0.8 -25.39, -0.39 -37.66 C-1.58 -49.93, -5.31 -66.44, -6.27 -72.27" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(464.4223394214108 534.5333926147692) rotate(387.24699775313775 -1.784867920930651 -36.93970368243015)"><path d="M2.77 -57.07 C-1.33 -62.21, -3.15 -67.51, -6.27 -72.27 M2.77 -57.07 C0.57 -62.42, -2.56 -66.79, -6.27 -72.27" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g stroke-opacity="0.7" fill-opacity="0.7" transform="translate(464.4223394214108 534.5333926147692) rotate(387.24699775313775 -1.784867920930651 -36.93970368243015)"><path d="M-9.11 -54.82 C-9.54 -60.57, -7.69 -66.56, -6.27 -72.27 M-9.11 -54.82 C-7.57 -60.89, -6.95 -65.96, -6.27 -72.27" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask></svg>