bec-widgets 0.51.0__py3-none-any.whl → 0.52.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bec_widgets/cli/__init__.py +1 -1
- bec_widgets/cli/bec_widgets_icon.png +0 -0
- bec_widgets/cli/client.py +213 -5
- bec_widgets/cli/client_utils.py +16 -5
- bec_widgets/cli/generate_cli.py +6 -3
- bec_widgets/cli/rpc_wigdet_handler.py +26 -0
- bec_widgets/cli/server.py +34 -9
- bec_widgets/examples/jupyter_console/jupyter_console_window.py +54 -2
- bec_widgets/examples/jupyter_console/jupyter_console_window.ui +26 -2
- bec_widgets/examples/jupyter_console/terminal_icon.png +0 -0
- bec_widgets/utils/__init__.py +1 -0
- bec_widgets/utils/bec_connector.py +11 -3
- bec_widgets/utils/layout_manager.py +117 -0
- bec_widgets/widgets/__init__.py +1 -0
- bec_widgets/widgets/dock/__init__.py +2 -0
- bec_widgets/widgets/dock/dock.py +269 -0
- bec_widgets/widgets/dock/dock_area.py +220 -0
- bec_widgets/widgets/figure/figure.py +33 -16
- bec_widgets/widgets/plots/__init__.py +1 -1
- bec_widgets/widgets/plots/image.py +5 -9
- bec_widgets/widgets/plots/motor_map.py +3 -3
- bec_widgets/widgets/plots/plot_base.py +4 -3
- bec_widgets/widgets/plots/waveform.py +6 -10
- {bec_widgets-0.51.0.dist-info → bec_widgets-0.52.0.dist-info}/METADATA +1 -1
- {bec_widgets-0.51.0.dist-info → bec_widgets-0.52.0.dist-info}/RECORD +36 -28
- tests/end-2-end/conftest.py +19 -4
- tests/end-2-end/test_bec_dock_rpc_e2e.py +145 -0
- tests/end-2-end/test_bec_figure_rpc_e2e.py +17 -17
- tests/end-2-end/test_rpc_register_e2e.py +3 -3
- tests/unit_tests/test_bec_dock.py +114 -0
- tests/unit_tests/test_bec_figure.py +20 -22
- tests/unit_tests/test_generate_cli_client.py +1 -1
- tests/unit_tests/test_waveform1d.py +1 -1
- {bec_widgets-0.51.0.dist-info → bec_widgets-0.52.0.dist-info}/LICENSE +0 -0
- {bec_widgets-0.51.0.dist-info → bec_widgets-0.52.0.dist-info}/WHEEL +0 -0
- {bec_widgets-0.51.0.dist-info → bec_widgets-0.52.0.dist-info}/top_level.txt +0 -0
@@ -1,27 +1,25 @@
|
|
1
1
|
# pylint: disable = no-name-in-module,missing-module-docstring
|
2
2
|
from __future__ import annotations
|
3
3
|
|
4
|
-
import
|
5
|
-
import os
|
4
|
+
import uuid
|
6
5
|
from collections import defaultdict
|
7
|
-
from typing import Literal, Optional
|
6
|
+
from typing import Literal, Optional
|
8
7
|
|
9
8
|
import numpy as np
|
10
9
|
import pyqtgraph as pg
|
11
10
|
import qdarktheme
|
12
11
|
from pydantic import Field
|
13
|
-
from pyqtgraph.Qt import uic
|
14
12
|
from qtpy.QtCore import Signal as pyqtSignal
|
15
|
-
from qtpy.QtWidgets import
|
13
|
+
from qtpy.QtWidgets import QWidget
|
16
14
|
|
17
|
-
from bec_widgets.utils import BECConnector,
|
15
|
+
from bec_widgets.utils import BECConnector, ConnectionConfig, WidgetContainerUtils
|
18
16
|
from bec_widgets.widgets.plots import (
|
19
17
|
BECImageShow,
|
20
18
|
BECMotorMap,
|
21
19
|
BECPlotBase,
|
22
20
|
BECWaveform,
|
21
|
+
SubplotConfig,
|
23
22
|
Waveform1DConfig,
|
24
|
-
WidgetConfig,
|
25
23
|
)
|
26
24
|
from bec_widgets.widgets.plots.image import ImageConfig
|
27
25
|
from bec_widgets.widgets.plots.motor_map import MotorMapConfig
|
@@ -33,7 +31,7 @@ class FigureConfig(ConnectionConfig):
|
|
33
31
|
theme: Literal["dark", "light"] = Field("dark", description="The theme of the figure widget.")
|
34
32
|
num_cols: int = Field(1, description="The number of columns in the figure widget.")
|
35
33
|
num_rows: int = Field(1, description="The number of rows in the figure widget.")
|
36
|
-
widgets: dict[str,
|
34
|
+
widgets: dict[str, SubplotConfig] = Field(
|
37
35
|
{}, description="The list of widgets to be added to the figure widget."
|
38
36
|
)
|
39
37
|
|
@@ -43,7 +41,7 @@ class WidgetHandler:
|
|
43
41
|
|
44
42
|
def __init__(self):
|
45
43
|
self.widget_factory = {
|
46
|
-
"PlotBase": (BECPlotBase,
|
44
|
+
"PlotBase": (BECPlotBase, SubplotConfig),
|
47
45
|
"Waveform1D": (BECWaveform, Waveform1DConfig),
|
48
46
|
"ImShow": (BECImageShow, ImageConfig),
|
49
47
|
"MotorMap": (BECMotorMap, MotorMapConfig),
|
@@ -166,14 +164,29 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
|
|
166
164
|
|
167
165
|
@widget_list.setter
|
168
166
|
def widget_list(self, value: list[BECPlotBase]):
|
167
|
+
"""
|
168
|
+
Access all widget in BECFigure as a list
|
169
|
+
Returns:
|
170
|
+
list[BECPlotBase]: List of all widgets in the figure.
|
171
|
+
"""
|
169
172
|
self._axes = value
|
170
173
|
|
171
174
|
@property
|
172
175
|
def widgets(self) -> dict:
|
176
|
+
"""
|
177
|
+
All widgets within the figure with gui ids as keys.
|
178
|
+
Returns:
|
179
|
+
dict: All widgets within the figure.
|
180
|
+
"""
|
173
181
|
return self._widgets
|
174
182
|
|
175
183
|
@widgets.setter
|
176
184
|
def widgets(self, value: dict):
|
185
|
+
"""
|
186
|
+
All widgets within the figure with gui ids as keys.
|
187
|
+
Returns:
|
188
|
+
dict: All widgets within the figure.
|
189
|
+
"""
|
177
190
|
self._widgets = value
|
178
191
|
|
179
192
|
def add_plot(
|
@@ -204,7 +217,7 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
|
|
204
217
|
config(dict): Additional configuration for the widget.
|
205
218
|
**axis_kwargs(dict): Additional axis properties to set on the widget after creation.
|
206
219
|
"""
|
207
|
-
widget_id =
|
220
|
+
widget_id = str(uuid.uuid4())
|
208
221
|
waveform = self.add_widget(
|
209
222
|
widget_type="Waveform1D",
|
210
223
|
widget_id=widget_id,
|
@@ -430,7 +443,7 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
|
|
430
443
|
BECImageShow: The image widget.
|
431
444
|
"""
|
432
445
|
|
433
|
-
widget_id =
|
446
|
+
widget_id = str(uuid.uuid4())
|
434
447
|
if config is None:
|
435
448
|
config = ImageConfig(
|
436
449
|
widget_class="BECImageShow",
|
@@ -513,7 +526,7 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
|
|
513
526
|
Returns:
|
514
527
|
BECMotorMap: The motor map widget.
|
515
528
|
"""
|
516
|
-
widget_id =
|
529
|
+
widget_id = str(uuid.uuid4())
|
517
530
|
if config is None:
|
518
531
|
config = MotorMapConfig(
|
519
532
|
widget_class="BECMotorMap",
|
@@ -554,7 +567,7 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
|
|
554
567
|
**axis_kwargs(dict): Additional axis properties to set on the widget after creation.
|
555
568
|
"""
|
556
569
|
if not widget_id:
|
557
|
-
widget_id =
|
570
|
+
widget_id = str(uuid.uuid4())
|
558
571
|
if widget_id in self._widgets:
|
559
572
|
raise ValueError(f"Widget with ID '{widget_id}' already exists.")
|
560
573
|
|
@@ -767,12 +780,16 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
|
|
767
780
|
|
768
781
|
def clear_all(self):
|
769
782
|
"""Clear all widgets from the figure and reset to default state"""
|
770
|
-
for widget in self._widgets.values():
|
771
|
-
widget.
|
772
|
-
self.clear()
|
783
|
+
for widget in list(self._widgets.values()):
|
784
|
+
widget.remove()
|
785
|
+
# self.clear()
|
773
786
|
self._widgets = defaultdict(dict)
|
774
787
|
self.grid = []
|
775
788
|
theme = self.config.theme
|
776
789
|
self.config = FigureConfig(
|
777
790
|
widget_class=self.__class__.__name__, gui_id=self.gui_id, theme=theme
|
778
791
|
)
|
792
|
+
|
793
|
+
def cleanup(self):
|
794
|
+
self.clear_all()
|
795
|
+
super().cleanup()
|
@@ -1,4 +1,4 @@
|
|
1
1
|
from .image import BECImageItem, BECImageShow, ImageItemConfig
|
2
2
|
from .motor_map import BECMotorMap, MotorMapConfig
|
3
|
-
from .plot_base import AxisConfig, BECPlotBase,
|
3
|
+
from .plot_base import AxisConfig, BECPlotBase, SubplotConfig
|
4
4
|
from .waveform import BECCurve, BECWaveform, Waveform1DConfig
|
@@ -14,7 +14,7 @@ from qtpy.QtWidgets import QWidget
|
|
14
14
|
|
15
15
|
from bec_widgets.utils import BECConnector, ConnectionConfig, EntryValidator
|
16
16
|
|
17
|
-
from .plot_base import BECPlotBase,
|
17
|
+
from .plot_base import BECPlotBase, SubplotConfig
|
18
18
|
|
19
19
|
|
20
20
|
class ProcessingConfig(BaseModel):
|
@@ -50,7 +50,7 @@ class ImageItemConfig(ConnectionConfig):
|
|
50
50
|
)
|
51
51
|
|
52
52
|
|
53
|
-
class ImageConfig(
|
53
|
+
class ImageConfig(SubplotConfig):
|
54
54
|
images: dict[str, ImageItemConfig] = Field(
|
55
55
|
{},
|
56
56
|
description="The configuration of the images. The key is the name of the image (source).",
|
@@ -288,10 +288,6 @@ class BECImageItem(BECConnector, pg.ImageItem):
|
|
288
288
|
else:
|
289
289
|
raise ValueError("style should be 'simple' or 'full'")
|
290
290
|
|
291
|
-
def cleanup(self):
|
292
|
-
"""Clean up widget."""
|
293
|
-
self.rpc_register.remove_rpc(self)
|
294
|
-
|
295
291
|
|
296
292
|
class BECImageShow(BECPlotBase):
|
297
293
|
USER_ACCESS = [
|
@@ -382,11 +378,11 @@ class BECImageShow(BECPlotBase):
|
|
382
378
|
if result is not None:
|
383
379
|
return result
|
384
380
|
|
385
|
-
def apply_config(self, config: dict |
|
381
|
+
def apply_config(self, config: dict | SubplotConfig):
|
386
382
|
"""
|
387
383
|
Apply the configuration to the 1D waveform widget.
|
388
384
|
Args:
|
389
|
-
config(dict|
|
385
|
+
config(dict|SubplotConfig): Configuration settings.
|
390
386
|
replot_last_scan(bool, optional): If True, replot the last scan. Defaults to False.
|
391
387
|
"""
|
392
388
|
if isinstance(config, dict):
|
@@ -806,7 +802,7 @@ class BECImageShow(BECPlotBase):
|
|
806
802
|
for image in self.images:
|
807
803
|
image.cleanup()
|
808
804
|
|
809
|
-
|
805
|
+
super().cleanup()
|
810
806
|
|
811
807
|
|
812
808
|
class ImageProcessor:
|
@@ -13,11 +13,11 @@ from qtpy.QtCore import Slot as pyqtSlot
|
|
13
13
|
from qtpy.QtWidgets import QWidget
|
14
14
|
|
15
15
|
from bec_widgets.utils import EntryValidator
|
16
|
-
from bec_widgets.widgets.plots.plot_base import BECPlotBase,
|
16
|
+
from bec_widgets.widgets.plots.plot_base import BECPlotBase, SubplotConfig
|
17
17
|
from bec_widgets.widgets.plots.waveform import Signal, SignalData
|
18
18
|
|
19
19
|
|
20
|
-
class MotorMapConfig(
|
20
|
+
class MotorMapConfig(SubplotConfig):
|
21
21
|
signals: Optional[Signal] = Field(None, description="Signals of the motor map")
|
22
22
|
color_map: Optional[str] = Field(
|
23
23
|
"Greys", description="Color scheme of the motor position gradient."
|
@@ -425,4 +425,4 @@ class BECMotorMap(BECPlotBase):
|
|
425
425
|
def cleanup(self):
|
426
426
|
"""Cleanup the widget."""
|
427
427
|
self._disconnect_current_motors()
|
428
|
-
|
428
|
+
super().cleanup()
|
@@ -22,7 +22,7 @@ class AxisConfig(BaseModel):
|
|
22
22
|
y_grid: bool = Field(False, description="Show grid on the y-axis.")
|
23
23
|
|
24
24
|
|
25
|
-
class
|
25
|
+
class SubplotConfig(ConnectionConfig):
|
26
26
|
parent_id: Optional[str] = Field(None, description="The parent figure of the plot.")
|
27
27
|
|
28
28
|
# Coordinates in the figure
|
@@ -56,12 +56,12 @@ class BECPlotBase(BECConnector, pg.GraphicsLayout):
|
|
56
56
|
self,
|
57
57
|
parent: Optional[QWidget] = None, # TODO decide if needed for this class
|
58
58
|
parent_figure=None,
|
59
|
-
config: Optional[
|
59
|
+
config: Optional[SubplotConfig] = None,
|
60
60
|
client=None,
|
61
61
|
gui_id: Optional[str] = None,
|
62
62
|
):
|
63
63
|
if config is None:
|
64
|
-
config =
|
64
|
+
config = SubplotConfig(widget_class=self.__class__.__name__)
|
65
65
|
super().__init__(client=client, config=config, gui_id=gui_id)
|
66
66
|
pg.GraphicsLayout.__init__(self, parent)
|
67
67
|
|
@@ -248,3 +248,4 @@ class BECPlotBase(BECConnector, pg.GraphicsLayout):
|
|
248
248
|
|
249
249
|
def cleanup(self):
|
250
250
|
"""Cleanup the plot widget."""
|
251
|
+
super().cleanup()
|
@@ -15,7 +15,7 @@ from qtpy.QtCore import Slot as pyqtSlot
|
|
15
15
|
from qtpy.QtWidgets import QWidget
|
16
16
|
|
17
17
|
from bec_widgets.utils import BECConnector, Colors, ConnectionConfig, EntryValidator
|
18
|
-
from bec_widgets.widgets.plots.plot_base import BECPlotBase,
|
18
|
+
from bec_widgets.widgets.plots.plot_base import BECPlotBase, SubplotConfig
|
19
19
|
|
20
20
|
|
21
21
|
class SignalData(BaseModel):
|
@@ -53,7 +53,7 @@ class CurveConfig(ConnectionConfig):
|
|
53
53
|
colormap: Optional[str] = Field("plasma", description="The colormap of the curves z gradient.")
|
54
54
|
|
55
55
|
|
56
|
-
class Waveform1DConfig(
|
56
|
+
class Waveform1DConfig(SubplotConfig):
|
57
57
|
color_palette: Literal["plasma", "viridis", "inferno", "magma"] = Field(
|
58
58
|
"plasma", description="The color palette of the figure widget."
|
59
59
|
) # TODO can be extended to all colormaps from current pyqtgraph session
|
@@ -229,14 +229,10 @@ class BECCurve(BECConnector, pg.PlotDataItem):
|
|
229
229
|
x_data, y_data = self.getData()
|
230
230
|
return x_data, y_data
|
231
231
|
|
232
|
-
def cleanup(self):
|
233
|
-
"""Cleanup the curve."""
|
234
|
-
self.rpc_register.remove_rpc(self)
|
235
|
-
|
236
232
|
def remove(self):
|
237
233
|
"""Remove the curve from the plot."""
|
238
|
-
self.cleanup()
|
239
234
|
self.parent_item.removeItem(self)
|
235
|
+
self.cleanup()
|
240
236
|
|
241
237
|
|
242
238
|
class BECWaveform(BECPlotBase):
|
@@ -300,11 +296,11 @@ class BECWaveform(BECPlotBase):
|
|
300
296
|
self.add_legend()
|
301
297
|
self.apply_config(self.config)
|
302
298
|
|
303
|
-
def apply_config(self, config: dict |
|
299
|
+
def apply_config(self, config: dict | SubplotConfig, replot_last_scan: bool = False):
|
304
300
|
"""
|
305
301
|
Apply the configuration to the 1D waveform widget.
|
306
302
|
Args:
|
307
|
-
config(dict|
|
303
|
+
config(dict|SubplotConfig): Configuration settings.
|
308
304
|
replot_last_scan(bool, optional): If True, replot the last scan. Defaults to False.
|
309
305
|
"""
|
310
306
|
if isinstance(config, dict):
|
@@ -799,4 +795,4 @@ class BECWaveform(BECPlotBase):
|
|
799
795
|
self.bec_dispatcher.disconnect_slot(self.on_scan_segment, MessageEndpoints.scan_segment())
|
800
796
|
for curve in self.curves:
|
801
797
|
curve.cleanup()
|
802
|
-
|
798
|
+
super().cleanup()
|
@@ -1,19 +1,21 @@
|
|
1
1
|
bec_widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
bec_widgets/cli/__init__.py,sha256=
|
2
|
+
bec_widgets/cli/__init__.py,sha256=EHPu69lxYndxm6tJqwHHlktuq0hvOCaid1Nxh0jaexo,91
|
3
3
|
bec_widgets/cli/auto_updates.py,sha256=ptZeBKr13o9THc8oKLn93K_16i6G3pxzw8hZ4MUgjW4,3845
|
4
|
-
bec_widgets/cli/bec_widgets_icon.png,sha256=
|
5
|
-
bec_widgets/cli/client.py,sha256=
|
6
|
-
bec_widgets/cli/client_utils.py,sha256=
|
7
|
-
bec_widgets/cli/generate_cli.py,sha256=
|
4
|
+
bec_widgets/cli/bec_widgets_icon.png,sha256=K8dgGwIjalDh9PRHUsSQBqgdX7a00nM3igZdc20pkYM,1747017
|
5
|
+
bec_widgets/cli/client.py,sha256=yvGQ5c-i-YhNr_8G3ls0n_PGURDeCWoPSMIdCeSoRUY,45200
|
6
|
+
bec_widgets/cli/client_utils.py,sha256=jiboQwyZ78_F3s_2Ujl2XNVd_svUklRt7nZdOLpflMc,10401
|
7
|
+
bec_widgets/cli/generate_cli.py,sha256=3YJU4dYgvW27KURUwc7oyt4IvgqEEdjMVXvrwPSbSQQ,4100
|
8
8
|
bec_widgets/cli/rpc_register.py,sha256=OZOWX0IKGXqDsnrUYi0Irl_zpPS4Q_JPCV9JQfN6YYw,2212
|
9
|
-
bec_widgets/cli/
|
9
|
+
bec_widgets/cli/rpc_wigdet_handler.py,sha256=RcIUsmrMJGCKIo8iI9-wi0tOiwIlTouuEWAMx-Vu7Y8,797
|
10
|
+
bec_widgets/cli/server.py,sha256=wIDOd56ZPfnM42pOJD8NCI3Dw38Aurb9TwwTrricfvU,5773
|
10
11
|
bec_widgets/examples/__init__.py,sha256=WWQ0cu7m8sA4Ehy-DWdTIqSISjaHsbxhsNmNrMnhDZU,202
|
11
12
|
bec_widgets/examples/eiger_plot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
13
|
bec_widgets/examples/eiger_plot/eiger_plot.py,sha256=Uxl2Usf8jEzaX7AT8zVqa1x8ZIEgI1HmazSlb-tRFWE,10359
|
13
14
|
bec_widgets/examples/eiger_plot/eiger_plot.ui,sha256=grHfnO3OG_lelJhdRsnA0badCvRdDunPrIMIyNQ5N-w,5809
|
14
15
|
bec_widgets/examples/jupyter_console/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15
|
-
bec_widgets/examples/jupyter_console/jupyter_console_window.py,sha256=
|
16
|
-
bec_widgets/examples/jupyter_console/jupyter_console_window.ui,sha256=
|
16
|
+
bec_widgets/examples/jupyter_console/jupyter_console_window.py,sha256=s8ysnlktLv3932ody8pRA1mghH1QQcxLjQK1HTZ59b8,5642
|
17
|
+
bec_widgets/examples/jupyter_console/jupyter_console_window.ui,sha256=2A2mNTUMZBYygz8K4qWzrcjnNqZBMVyeHm26iLZVRWI,1473
|
18
|
+
bec_widgets/examples/jupyter_console/terminal_icon.png,sha256=bJl7Tft4Fi2uxvuXI8o14uMHnI9eAWKSU2uftXCH9ws,3889
|
17
19
|
bec_widgets/examples/mca_readout/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
20
|
bec_widgets/examples/mca_readout/mca_plot.py,sha256=do7mSK_nzHtojRiMi8JoN_Rckg9yfjYYWz2S_Nl3xbE,5079
|
19
21
|
bec_widgets/examples/mca_readout/mca_sim.py,sha256=yiX_3sOgDZIbAYA4D2BGmOgLMBWbQMOej0hSP4cQd0o,754
|
@@ -28,8 +30,8 @@ bec_widgets/examples/stream_plot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRk
|
|
28
30
|
bec_widgets/examples/stream_plot/line_plot.ui,sha256=rgNfhOXu1AcWF0P6wnOlmJKDjS-VIoduVrREvmzJQR8,4626
|
29
31
|
bec_widgets/examples/stream_plot/stream_plot.py,sha256=vHii1p9JxSyGQ_VcCjnk9SHJ41Q6Oi1GGd6swVVHLRM,12177
|
30
32
|
bec_widgets/simulations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
31
|
-
bec_widgets/utils/__init__.py,sha256=
|
32
|
-
bec_widgets/utils/bec_connector.py,sha256=
|
33
|
+
bec_widgets/utils/__init__.py,sha256=PAHNbPFnPD-XGxKBZ7ctx9WBrvm9MArkCYDNfoOxVJA,449
|
34
|
+
bec_widgets/utils/bec_connector.py,sha256=sfYscTdj3MfWL5KuUqecnPl1Lhws2DXgA_FGsQz4DuY,5178
|
33
35
|
bec_widgets/utils/bec_dispatcher.py,sha256=xJrsHJ-flLFGA-XCa6wCsMzMpRu1fAy9IcUuLh6igSo,5569
|
34
36
|
bec_widgets/utils/bec_table.py,sha256=Xy5qM343K8EvEpB4g_129b63yo1wdEvEY3wqxB_p_Iw,716
|
35
37
|
bec_widgets/utils/colors.py,sha256=JsLxzkxbw-I8GIuvnIKyiM83n0edhyMG2Fa4Ffm62ww,2392
|
@@ -37,6 +39,7 @@ bec_widgets/utils/container_utils.py,sha256=rL-ryupQ4-7Y8mKNup5aklXleOfXSd97uwXT
|
|
37
39
|
bec_widgets/utils/crosshair.py,sha256=5gG4G6jjtp6Bd1Y5EySHP2EkmtR4mYdxLCgVtx9fokE,9406
|
38
40
|
bec_widgets/utils/ctrl_c.py,sha256=NMJlPDZcuqMUGykyhuZY5Ibed4yRI1K_uh16z2MmlXQ,1198
|
39
41
|
bec_widgets/utils/entry_validator.py,sha256=88OpJqaldMjiaEk7F9rRcwPuCOTLCzXmAlSEL-_7iXU,1296
|
42
|
+
bec_widgets/utils/layout_manager.py,sha256=hSHH3DTnaM7DyjUF9ko5FVrBdeFhY6KbhteLBnujFt0,4723
|
40
43
|
bec_widgets/utils/plugin_utils.py,sha256=wi5x7VVFee0PqAcP-EqPWjYfSe-LLhaK93y6qmnbLIw,1487
|
41
44
|
bec_widgets/utils/rpc_decorator.py,sha256=pIvtqySQLnuS7l2Ti_UAe4WX7CRivZnsE5ZdKAihxh0,479
|
42
45
|
bec_widgets/utils/thread_checker.py,sha256=rDNuA3X6KQyA7JPb67mccTg0z8YkInynLAENQDQpbuE,1607
|
@@ -45,9 +48,12 @@ bec_widgets/utils/widget_io.py,sha256=JKl508VnqQSxcaHqKaoBQ1TWSOm3pXhxQGx7iF_pRA
|
|
45
48
|
bec_widgets/utils/yaml_dialog.py,sha256=soZI8BOjlqYGfYDga70MEvkxJTsktq4y7B3uog2cSik,1851
|
46
49
|
bec_widgets/validation/__init__.py,sha256=ismd1bU5FhFb0zFPwNKuq7oT48G4Y2GfaMZOdNKUtGk,132
|
47
50
|
bec_widgets/validation/monitor_config_validator.py,sha256=M9p8K_nvxicnqJB4X7j90R377WHYVH4wMCtSXsRI51M,8150
|
48
|
-
bec_widgets/widgets/__init__.py,sha256=
|
51
|
+
bec_widgets/widgets/__init__.py,sha256=NOgRDV9-uwrH1OK2JdfG5c0WcW77TSRz3PeNlGw22Lc,392
|
52
|
+
bec_widgets/widgets/dock/__init__.py,sha256=B7foHt02gnhM7mFksa7GJVwT7n0j_JvYDCt6wc6XR5g,61
|
53
|
+
bec_widgets/widgets/dock/dock.py,sha256=vnOQnOWWnd-3X07kniSW_I5l0uEHZOaWhfuqZkDGIqE,8467
|
54
|
+
bec_widgets/widgets/dock/dock_area.py,sha256=qwwjfpGCwGk7w2F5JTD3IbJQc_06vGnhBAkCT8zr-4g,7202
|
49
55
|
bec_widgets/widgets/figure/__init__.py,sha256=3hGx_KOV7QHCYAV06aNuUgKq4QIYCjUTad-DrwkUaBM,44
|
50
|
-
bec_widgets/widgets/figure/figure.py,sha256=
|
56
|
+
bec_widgets/widgets/figure/figure.py,sha256=IJXSpza5uNIsSN2TuzSE1n9ASbB7JIBYK31MnI6OHo0,28744
|
51
57
|
bec_widgets/widgets/monitor/__init__.py,sha256=afXuZcBOxNAuYdCkIQXX5J60R5A3Q_86lNEW2vpFtPI,32
|
52
58
|
bec_widgets/widgets/monitor/config_dialog.py,sha256=Z1a4WRIVlfEGdwC-QG25kba2EHCZWi5J843tBVZlWiI,20275
|
53
59
|
bec_widgets/widgets/monitor/config_dialog.ui,sha256=ISMcF7CLTAMXhfZh2Yv5yezzAjMtb9fxY1pmX4B_jCg,5932
|
@@ -61,33 +67,35 @@ bec_widgets/widgets/motor_control/motor_control_selection.ui,sha256=vXXpvNWuL6xy
|
|
61
67
|
bec_widgets/widgets/motor_control/motor_control_table.ui,sha256=t6aRKiSmutMfp0AyupavbCs0cal-FANEnlKQiPzC9PQ,2792
|
62
68
|
bec_widgets/widgets/motor_map/__init__.py,sha256=K3c-3A_LbxK0UJ0_bV3opL-wGLTwBLendsJXsg8GAqE,32
|
63
69
|
bec_widgets/widgets/motor_map/motor_map.py,sha256=vJlLWa0BXv5KMZ7UVT0q3I1I5CXgsDiXoM_ptsAsG3c,21860
|
64
|
-
bec_widgets/widgets/plots/__init__.py,sha256=
|
65
|
-
bec_widgets/widgets/plots/image.py,sha256=
|
66
|
-
bec_widgets/widgets/plots/motor_map.py,sha256=
|
67
|
-
bec_widgets/widgets/plots/plot_base.py,sha256=
|
68
|
-
bec_widgets/widgets/plots/waveform.py,sha256=
|
70
|
+
bec_widgets/widgets/plots/__init__.py,sha256=yaCWQEXiEVj3Oh9qvD3UDzY2HE2PiDKKyKINEcVeL2k,238
|
71
|
+
bec_widgets/widgets/plots/image.py,sha256=8E1aEh6x2KhOoH9S87lEDlAmqi-JDuZS4aW1PenVhaE,32393
|
72
|
+
bec_widgets/widgets/plots/motor_map.py,sha256=gnESz9ig6MMxYasuACvtd1sXDIvB2zxiYtVbtlxwwXQ,15283
|
73
|
+
bec_widgets/widgets/plots/plot_base.py,sha256=O-eitUfWGaCFF-Qtz2nOsMCjfNMF5ZYr7T-0suOU9v0,8503
|
74
|
+
bec_widgets/widgets/plots/waveform.py,sha256=n-rNB8RWMviqY7M22lxhk-p7chpuZMIkJ81F5O7Q1jk,28580
|
69
75
|
bec_widgets/widgets/scan_control/__init__.py,sha256=IOfHl15vxb_uC6KN62-PeUzbBha_vQyqkkXbJ2HU674,38
|
70
76
|
bec_widgets/widgets/scan_control/scan_control.py,sha256=tbO9tbVynRvs4VCxTZ4ZFBDTVAojIr-zkl70vuHbWgw,17116
|
71
77
|
bec_widgets/widgets/toolbar/__init__.py,sha256=d-TP4_cr_VbpwreMM4ePnfZ5YXsEPQ45ibEf75nuGoE,36
|
72
78
|
bec_widgets/widgets/toolbar/toolbar.py,sha256=sxz7rbc8XNPS6n2WMObF4-2PqdYfPxVtsOZEGV6mqa0,5124
|
73
79
|
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
74
80
|
tests/end-2-end/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
75
|
-
tests/end-2-end/conftest.py,sha256=
|
76
|
-
tests/end-2-end/
|
77
|
-
tests/end-2-end/
|
81
|
+
tests/end-2-end/conftest.py,sha256=b5Yebbj8C1-IcXq23XGbOnXF0kOZD_Po46Z-p4cBwfs,1346
|
82
|
+
tests/end-2-end/test_bec_dock_rpc_e2e.py,sha256=vfskJxQ6xQFfG6X6Ec8GOj2SoWIk8slMd43fERroaaw,4548
|
83
|
+
tests/end-2-end/test_bec_figure_rpc_e2e.py,sha256=aEpyhRYrDC3dNScsHxJfQPfuehU6Q9wGhCGkYmooAMk,5461
|
84
|
+
tests/end-2-end/test_rpc_register_e2e.py,sha256=Jrv46F-fyJa0tls1KPTeIxXQ4oUNgWkhAMwzvMQBRR8,1581
|
78
85
|
tests/unit_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
79
86
|
tests/unit_tests/client_mocks.py,sha256=LNUgI9Ccv5Ol7_pmybIhoVqZZem1RPIsTDk7ZTARNls,4128
|
80
87
|
tests/unit_tests/conftest.py,sha256=KrnktXPWmZhnKNue-xGWOLD1XGEvdz9Vf7V2eO3XQ3A,596
|
81
88
|
tests/unit_tests/test_bec_connector.py,sha256=f2XXGGw3NoZLIUrDuZuEWwF_ttOYmmquCgUrV5XkIOY,1951
|
82
89
|
tests/unit_tests/test_bec_dispatcher.py,sha256=WW-wlzSgZA_h2Qx5EMvXfMlb2i7RYbWj2Cz3S2EzsZQ,4178
|
83
|
-
tests/unit_tests/
|
90
|
+
tests/unit_tests/test_bec_dock.py,sha256=ZnHUoVQCGbikd0mM64XBL_k0Kxp0d3UqCHpcyY59emg,3596
|
91
|
+
tests/unit_tests/test_bec_figure.py,sha256=AOPJBGJIdAz80YqSiU1PosEHo-DjlmV8869HBcSHdS0,7860
|
84
92
|
tests/unit_tests/test_bec_monitor.py,sha256=mN7gBY7oXY6j65zzihpy8r-FvwVoCQlie3F6SoVq0mo,7042
|
85
93
|
tests/unit_tests/test_bec_motor_map.py,sha256=IXSfitUGxOPqmngwVNPK5nwi2QDcXWjBkGNb0dBZDxQ,4611
|
86
94
|
tests/unit_tests/test_client_utils.py,sha256=fIApd5WgnJuyIzV-hdSABn6T-aOel2Wr2xuUX4Z651A,774
|
87
95
|
tests/unit_tests/test_config_dialog.py,sha256=5uNGcpvrx8qDdMwFCTXr8HMzFZF4rFi-ZHoDpMxGMf8,6955
|
88
96
|
tests/unit_tests/test_crosshair.py,sha256=d7fX-ymboZPALNqqiAj86PZ96llmGZ_3jf0yjVP0S94,5039
|
89
97
|
tests/unit_tests/test_eiger_plot.py,sha256=bWnKBQid0YcLMQeBLy6ojb4ZpwTG-rFVT0kMg9Y08p8,4427
|
90
|
-
tests/unit_tests/test_generate_cli_client.py,sha256=
|
98
|
+
tests/unit_tests/test_generate_cli_client.py,sha256=J7CFoO67txGu_u1Mwk32EejRX204FRuvmVg_yhAr1WM,2397
|
91
99
|
tests/unit_tests/test_motor_control.py,sha256=jdTG35z3jOL9XCAIDNIGfdv60vcwGLHa3KJjKqJkoZw,20322
|
92
100
|
tests/unit_tests/test_motor_map.py,sha256=UEjmtIYI2mxq9BUeopqoqNNy7UiPJEts9h45ufsFcrA,5979
|
93
101
|
tests/unit_tests/test_plot_base.py,sha256=bOdlgAxh9oKk5PwiQ_MSFmzr44uJ61Tlg242RCIhl5c,2610
|
@@ -95,13 +103,13 @@ tests/unit_tests/test_rpc_register.py,sha256=hECjZEimd440mwRrO0rg7L3PKN7__3DgjmE
|
|
95
103
|
tests/unit_tests/test_scan_control.py,sha256=7dtGpE0g4FqUhhQeCkyJl-9o7NH3DFZJgEaqDmBYbBc,7551
|
96
104
|
tests/unit_tests/test_stream_plot.py,sha256=LNCYIj9CafremGaz-DwDktCRJRrjgfOdVewCUwwZE5s,5843
|
97
105
|
tests/unit_tests/test_validator_errors.py,sha256=NFxyv0TIOXeZKZRRUBfVQ7bpunwY4KkG95yTUdQmvns,3532
|
98
|
-
tests/unit_tests/test_waveform1d.py,sha256
|
106
|
+
tests/unit_tests/test_waveform1d.py,sha256=cBtESTQgsVQdv-Wl75eHK9D8YY-b60Z5wqtPCo9ohu0,15002
|
99
107
|
tests/unit_tests/test_widget_io.py,sha256=FeL3ZYSBQnRt6jxj8VGYw1cmcicRQyHKleahw7XIyR0,3475
|
100
108
|
tests/unit_tests/test_yaml_dialog.py,sha256=HNrqferkdg02-9ieOhhI2mr2Qvt7GrYgXmQ061YCTbg,5794
|
101
109
|
tests/unit_tests/test_msgs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
102
110
|
tests/unit_tests/test_msgs/available_scans_message.py,sha256=m_z97hIrjHXXMa2Ex-UvsPmTxOYXfjxyJaGkIY6StTY,46532
|
103
|
-
bec_widgets-0.
|
104
|
-
bec_widgets-0.
|
105
|
-
bec_widgets-0.
|
106
|
-
bec_widgets-0.
|
107
|
-
bec_widgets-0.
|
111
|
+
bec_widgets-0.52.0.dist-info/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
|
112
|
+
bec_widgets-0.52.0.dist-info/METADATA,sha256=lSrW1foR3MPKDrHbNrH-5B8Qp1oRgvkFnwrtgsFW8C4,3724
|
113
|
+
bec_widgets-0.52.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
114
|
+
bec_widgets-0.52.0.dist-info/top_level.txt,sha256=EXCwhJYmXmd1DjYYL3hrGsddX-97IwYSiIHrf27FFVk,18
|
115
|
+
bec_widgets-0.52.0.dist-info/RECORD,,
|
tests/end-2-end/conftest.py
CHANGED
@@ -3,6 +3,7 @@ import pytest
|
|
3
3
|
from bec_widgets.cli.rpc_register import RPCRegister
|
4
4
|
from bec_widgets.cli.server import BECWidgetsCLIServer
|
5
5
|
from bec_widgets.utils import BECDispatcher
|
6
|
+
from bec_widgets.widgets import BECDockArea, BECFigure
|
6
7
|
|
7
8
|
|
8
9
|
@pytest.fixture(autouse=True)
|
@@ -12,11 +13,25 @@ def rpc_register():
|
|
12
13
|
|
13
14
|
|
14
15
|
@pytest.fixture
|
15
|
-
def
|
16
|
+
def rpc_server_figure(qtbot, bec_client_lib, threads_check):
|
16
17
|
dispatcher = BECDispatcher(client=bec_client_lib) # Has to init singleton with fixture client
|
17
|
-
server = BECWidgetsCLIServer(gui_id="figure")
|
18
|
-
qtbot.addWidget(server.
|
19
|
-
qtbot.waitExposed(server.
|
18
|
+
server = BECWidgetsCLIServer(gui_id="figure", gui_class=BECFigure)
|
19
|
+
qtbot.addWidget(server.gui)
|
20
|
+
qtbot.waitExposed(server.gui)
|
21
|
+
qtbot.wait(1000) # 1s long to wait until gui is ready
|
22
|
+
yield server
|
23
|
+
dispatcher.disconnect_all()
|
24
|
+
server.client.shutdown()
|
25
|
+
server.shutdown()
|
26
|
+
dispatcher.reset_singleton()
|
27
|
+
|
28
|
+
|
29
|
+
@pytest.fixture
|
30
|
+
def rpc_server_dock(qtbot, bec_client_lib, threads_check):
|
31
|
+
dispatcher = BECDispatcher(client=bec_client_lib) # Has to init singleton with fixture client
|
32
|
+
server = BECWidgetsCLIServer(gui_id="figure", gui_class=BECDockArea)
|
33
|
+
qtbot.addWidget(server.gui)
|
34
|
+
qtbot.waitExposed(server.gui)
|
20
35
|
qtbot.wait(1000) # 1s long to wait until gui is ready
|
21
36
|
yield server
|
22
37
|
dispatcher.disconnect_all()
|
@@ -0,0 +1,145 @@
|
|
1
|
+
import numpy as np
|
2
|
+
import pytest
|
3
|
+
from bec_lib import MessageEndpoints
|
4
|
+
|
5
|
+
from bec_widgets.cli.client import BECDockArea, BECFigure, BECImageShow, BECMotorMap, BECWaveform
|
6
|
+
|
7
|
+
|
8
|
+
def test_rpc_add_dock_with_figure_e2e(rpc_server_dock, qtbot):
|
9
|
+
dock = BECDockArea(rpc_server_dock.gui_id)
|
10
|
+
dock_server = rpc_server_dock.gui
|
11
|
+
|
12
|
+
# BEC client shortcuts
|
13
|
+
client = rpc_server_dock.client
|
14
|
+
dev = client.device_manager.devices
|
15
|
+
scans = client.scans
|
16
|
+
queue = client.queue
|
17
|
+
|
18
|
+
# Create 3 docks
|
19
|
+
d0 = dock.add_dock("dock_0")
|
20
|
+
d1 = dock.add_dock("dock_1")
|
21
|
+
d2 = dock.add_dock("dock_2")
|
22
|
+
|
23
|
+
assert len(dock_server.docks) == 3
|
24
|
+
|
25
|
+
# Add 3 figures with some widgets
|
26
|
+
fig0 = d0.add_widget_bec("BECFigure")
|
27
|
+
fig1 = d1.add_widget_bec("BECFigure")
|
28
|
+
fig2 = d2.add_widget_bec("BECFigure")
|
29
|
+
|
30
|
+
assert len(dock_server.docks) == 3
|
31
|
+
assert len(dock_server.docks["dock_0"].widgets) == 1
|
32
|
+
assert len(dock_server.docks["dock_1"].widgets) == 1
|
33
|
+
assert len(dock_server.docks["dock_2"].widgets) == 1
|
34
|
+
|
35
|
+
assert fig1.__class__.__name__ == "BECFigure"
|
36
|
+
assert fig1.__class__ == BECFigure
|
37
|
+
assert fig2.__class__.__name__ == "BECFigure"
|
38
|
+
assert fig2.__class__ == BECFigure
|
39
|
+
|
40
|
+
mm = fig0.motor_map("samx", "samy")
|
41
|
+
plt = fig1.plot("samx", "bpm4i")
|
42
|
+
im = fig2.image("eiger")
|
43
|
+
|
44
|
+
assert mm.__class__.__name__ == "BECMotorMap"
|
45
|
+
assert mm.__class__ == BECMotorMap
|
46
|
+
assert plt.__class__.__name__ == "BECWaveform"
|
47
|
+
assert plt.__class__ == BECWaveform
|
48
|
+
assert im.__class__.__name__ == "BECImageShow"
|
49
|
+
assert im.__class__ == BECImageShow
|
50
|
+
|
51
|
+
assert mm.config_dict["signals"] == {
|
52
|
+
"source": "device_readback",
|
53
|
+
"x": {
|
54
|
+
"name": "samx",
|
55
|
+
"entry": "samx",
|
56
|
+
"unit": None,
|
57
|
+
"modifier": None,
|
58
|
+
"limits": [-50.0, 50.0],
|
59
|
+
},
|
60
|
+
"y": {
|
61
|
+
"name": "samy",
|
62
|
+
"entry": "samy",
|
63
|
+
"unit": None,
|
64
|
+
"modifier": None,
|
65
|
+
"limits": [-50.0, 50.0],
|
66
|
+
},
|
67
|
+
"z": None,
|
68
|
+
}
|
69
|
+
assert plt.config_dict["curves"]["bpm4i-bpm4i"]["signals"] == {
|
70
|
+
"source": "scan_segment",
|
71
|
+
"x": {"name": "samx", "entry": "samx", "unit": None, "modifier": None, "limits": None},
|
72
|
+
"y": {"name": "bpm4i", "entry": "bpm4i", "unit": None, "modifier": None, "limits": None},
|
73
|
+
"z": None,
|
74
|
+
}
|
75
|
+
assert im.config_dict["images"]["eiger"]["monitor"] == "eiger"
|
76
|
+
|
77
|
+
# check initial position of motor map
|
78
|
+
initial_pos_x = dev.samx.read()["samx"]["value"]
|
79
|
+
initial_pos_y = dev.samy.read()["samy"]["value"]
|
80
|
+
|
81
|
+
# Try to make a scan
|
82
|
+
status = scans.line_scan(dev.samx, -5, 5, steps=10, exp_time=0.05, relative=False)
|
83
|
+
|
84
|
+
# wait for scan to finish
|
85
|
+
while not status.status == "COMPLETED":
|
86
|
+
qtbot.wait(200)
|
87
|
+
|
88
|
+
# plot
|
89
|
+
plt_last_scan_data = queue.scan_storage.storage[-1].data
|
90
|
+
plt_data = plt.get_all_data()
|
91
|
+
assert plt_data["bpm4i-bpm4i"]["x"] == plt_last_scan_data["samx"]["samx"].val
|
92
|
+
assert plt_data["bpm4i-bpm4i"]["y"] == plt_last_scan_data["bpm4i"]["bpm4i"].val
|
93
|
+
|
94
|
+
# image
|
95
|
+
last_image_device = client.connector.get_last(MessageEndpoints.device_monitor("eiger"))[
|
96
|
+
"data"
|
97
|
+
].data
|
98
|
+
qtbot.wait(500)
|
99
|
+
last_image_plot = im.images[0].get_data()
|
100
|
+
np.testing.assert_equal(last_image_device, last_image_plot)
|
101
|
+
|
102
|
+
# motor map
|
103
|
+
final_pos_x = dev.samx.read()["samx"]["value"]
|
104
|
+
final_pos_y = dev.samy.read()["samy"]["value"]
|
105
|
+
|
106
|
+
# check final coordinates of motor map
|
107
|
+
motor_map_data = mm.get_data()
|
108
|
+
|
109
|
+
np.testing.assert_equal(
|
110
|
+
[motor_map_data["x"][0], motor_map_data["y"][0]], [initial_pos_x, initial_pos_y]
|
111
|
+
)
|
112
|
+
np.testing.assert_equal(
|
113
|
+
[motor_map_data["x"][-1], motor_map_data["y"][-1]], [final_pos_x, final_pos_y]
|
114
|
+
)
|
115
|
+
|
116
|
+
|
117
|
+
def test_dock_manipulations_e2e(rpc_server_dock, qtbot):
|
118
|
+
dock = BECDockArea(rpc_server_dock.gui_id)
|
119
|
+
dock_server = rpc_server_dock.gui
|
120
|
+
|
121
|
+
d0 = dock.add_dock("dock_0")
|
122
|
+
d1 = dock.add_dock("dock_1")
|
123
|
+
d2 = dock.add_dock("dock_2")
|
124
|
+
assert len(dock_server.docks) == 3
|
125
|
+
|
126
|
+
d0.detach()
|
127
|
+
dock.detach_dock("dock_2")
|
128
|
+
assert len(dock_server.docks) == 3
|
129
|
+
assert len(dock_server.tempAreas) == 2
|
130
|
+
|
131
|
+
d0.attach()
|
132
|
+
assert len(dock_server.docks) == 3
|
133
|
+
assert len(dock_server.tempAreas) == 1
|
134
|
+
|
135
|
+
d2.remove()
|
136
|
+
qtbot.wait(200)
|
137
|
+
|
138
|
+
assert len(dock_server.docks) == 2
|
139
|
+
docks_list = list(dict(dock_server.docks).keys())
|
140
|
+
assert ["dock_0", "dock_1"] == docks_list
|
141
|
+
|
142
|
+
dock.clear_all()
|
143
|
+
|
144
|
+
assert len(dock_server.docks) == 0
|
145
|
+
assert len(dock_server.tempAreas) == 0
|