bec-widgets 0.44.4__py3-none-any.whl → 0.45.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/client.py +105 -5
- bec_widgets/cli/client_utils.py +4 -4
- bec_widgets/cli/generate_cli.py +6 -4
- bec_widgets/cli/server.py +2 -3
- bec_widgets/examples/__init__.py +1 -1
- bec_widgets/examples/eiger_plot/eiger_plot.py +3 -11
- bec_widgets/examples/mca_readout/mca_plot.py +21 -24
- bec_widgets/examples/mca_readout/mca_sim.py +7 -12
- bec_widgets/examples/motor_movement/__init__.py +1 -1
- bec_widgets/examples/motor_movement/motor_control_compilations.py +3 -8
- bec_widgets/examples/motor_movement/motor_controller.ui +1 -1
- bec_widgets/examples/motor_movement/motor_example.py +13 -14
- bec_widgets/examples/stream_plot/stream_plot.py +5 -4
- bec_widgets/utils/__init__.py +5 -5
- bec_widgets/utils/bec_connector.py +1 -1
- bec_widgets/utils/bec_dispatcher.py +1 -2
- bec_widgets/utils/bec_table.py +1 -1
- bec_widgets/utils/crosshair.py +2 -1
- bec_widgets/utils/validator_delegate.py +1 -1
- bec_widgets/utils/widget_io.py +6 -6
- bec_widgets/utils/yaml_dialog.py +1 -0
- bec_widgets/validation/monitor_config_validator.py +6 -6
- bec_widgets/widgets/__init__.py +7 -8
- bec_widgets/widgets/editor/editor.py +6 -14
- bec_widgets/widgets/figure/__init__.py +1 -1
- bec_widgets/widgets/figure/figure.py +74 -4
- bec_widgets/widgets/monitor/__init__.py +0 -1
- bec_widgets/widgets/monitor/config_dialog.py +7 -8
- bec_widgets/widgets/monitor/monitor.py +16 -26
- bec_widgets/widgets/monitor_scatter_2D/monitor_scatter_2D.py +11 -19
- bec_widgets/widgets/motor_control/__init__.py +2 -2
- bec_widgets/widgets/motor_control/motor_control.py +11 -10
- bec_widgets/widgets/motor_map/motor_map.py +2 -3
- bec_widgets/widgets/plots/__init__.py +4 -3
- bec_widgets/widgets/plots/image.py +7 -6
- bec_widgets/widgets/plots/motor_map.py +423 -0
- bec_widgets/widgets/plots/plot_base.py +1 -2
- bec_widgets/widgets/plots/waveform1d.py +24 -23
- bec_widgets/widgets/scan_control/scan_control.py +12 -12
- bec_widgets/widgets/toolbar/toolbar.py +2 -4
- {bec_widgets-0.44.4.dist-info → bec_widgets-0.45.0.dist-info}/METADATA +2 -1
- bec_widgets-0.45.0.dist-info/RECORD +98 -0
- tests/client_mocks.py +76 -30
- tests/conftest.py +2 -1
- tests/test_bec_connector.py +2 -1
- tests/test_bec_dispatcher.py +3 -4
- tests/test_bec_figure.py +14 -2
- tests/test_bec_monitor.py +7 -76
- tests/test_bec_monitor_scatter2D.py +8 -32
- tests/test_bec_motor_map.py +125 -0
- tests/test_config_dialog.py +4 -66
- tests/test_editor.py +2 -4
- tests/test_eiger_plot.py +2 -0
- tests/test_generate_cli_client.py +4 -2
- tests/test_motor_control.py +25 -92
- tests/test_motor_map.py +10 -66
- tests/test_plot_base.py +1 -0
- tests/test_scan_control.py +1 -1
- tests/test_stream_plot.py +2 -2
- tests/test_validator_errors.py +5 -4
- tests/test_waveform1d.py +31 -12
- tests/test_widget_io.py +1 -8
- tests/test_yaml_dialog.py +2 -1
- bec_widgets-0.44.4.dist-info/RECORD +0 -96
- {bec_widgets-0.44.4.dist-info → bec_widgets-0.45.0.dist-info}/LICENSE +0 -0
- {bec_widgets-0.44.4.dist-info → bec_widgets-0.45.0.dist-info}/WHEEL +0 -0
- {bec_widgets-0.44.4.dist-info → bec_widgets-0.45.0.dist-info}/top_level.txt +0 -0
bec_widgets/cli/client.py
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# This file was automatically generated by generate_cli.py
|
2
2
|
|
3
|
-
from bec_widgets.cli.client_utils import rpc_call, RPCBase, BECFigureClientMixin
|
4
3
|
from typing import Literal, Optional, overload
|
5
4
|
|
5
|
+
from bec_widgets.cli.client_utils import BECFigureClientMixin, RPCBase, rpc_call
|
6
|
+
|
6
7
|
|
7
8
|
class BECPlotBase(RPCBase):
|
8
9
|
@rpc_call
|
@@ -194,12 +195,12 @@ class BECWaveform1D(RPCBase):
|
|
194
195
|
"""
|
195
196
|
|
196
197
|
@rpc_call
|
197
|
-
def scan_history(self, scan_index: "int" = None,
|
198
|
+
def scan_history(self, scan_index: "int" = None, scan_id: "str" = None):
|
198
199
|
"""
|
199
200
|
Update the scan curves with the data from the scan storage.
|
200
|
-
Provide only one of
|
201
|
+
Provide only one of scan_id or scan_index.
|
201
202
|
Args:
|
202
|
-
|
203
|
+
scan_id(str, optional): ScanID of the scan to be updated. Defaults to None.
|
203
204
|
scan_index(int, optional): Index of the scan to be updated. Defaults to None.
|
204
205
|
"""
|
205
206
|
|
@@ -449,12 +450,35 @@ class BECFigure(RPCBase, BECFigureClientMixin):
|
|
449
450
|
row(int): The row coordinate of the widget in the figure. If not provided, the next empty row will be used.
|
450
451
|
col(int): The column coordinate of the widget in the figure. If not provided, the next empty column will be used.
|
451
452
|
config(dict): Additional configuration for the widget.
|
452
|
-
**axis_kwargs:
|
453
|
+
**axis_kwargs: Additional axis properties to set on the widget after creation.
|
453
454
|
|
454
455
|
Returns:
|
455
456
|
BECImageShow: The image widget.
|
456
457
|
"""
|
457
458
|
|
459
|
+
@rpc_call
|
460
|
+
def add_motor_map(
|
461
|
+
self,
|
462
|
+
motor_x: "str" = None,
|
463
|
+
motor_y: "str" = None,
|
464
|
+
row: "int" = None,
|
465
|
+
col: "int" = None,
|
466
|
+
config=None,
|
467
|
+
**axis_kwargs
|
468
|
+
) -> "BECMotorMap":
|
469
|
+
"""
|
470
|
+
Args:
|
471
|
+
motor_x(str): The name of the motor for the X axis.
|
472
|
+
motor_y(str): The name of the motor for the Y axis.
|
473
|
+
row(int): The row coordinate of the widget in the figure. If not provided, the next empty row will be used.
|
474
|
+
col(int): The column coordinate of the widget in the figure. If not provided, the next empty column will be used.
|
475
|
+
config(dict): Additional configuration for the widget.
|
476
|
+
**axis_kwargs:
|
477
|
+
|
478
|
+
Returns:
|
479
|
+
BECMotorMap: The motor map widget.
|
480
|
+
"""
|
481
|
+
|
458
482
|
@rpc_call
|
459
483
|
def plot(
|
460
484
|
self,
|
@@ -511,6 +535,21 @@ class BECFigure(RPCBase, BECFigureClientMixin):
|
|
511
535
|
BECImageShow: The image widget.
|
512
536
|
"""
|
513
537
|
|
538
|
+
@rpc_call
|
539
|
+
def motor_map(
|
540
|
+
self, motor_x: "str" = None, motor_y: "str" = None, **axis_kwargs
|
541
|
+
) -> "BECMotorMap":
|
542
|
+
"""
|
543
|
+
Add a motor map to the figure. Always access the first motor map widget in the figure.
|
544
|
+
Args:
|
545
|
+
motor_x(str): The name of the motor for the X axis.
|
546
|
+
motor_y(str): The name of the motor for the Y axis.
|
547
|
+
**axis_kwargs: Additional axis properties to set on the widget after creation.
|
548
|
+
|
549
|
+
Returns:
|
550
|
+
BECMotorMap: The motor map widget.
|
551
|
+
"""
|
552
|
+
|
514
553
|
@rpc_call
|
515
554
|
def remove(
|
516
555
|
self,
|
@@ -1090,3 +1129,64 @@ class BECImageItem(RPCBase):
|
|
1090
1129
|
Returns:
|
1091
1130
|
dict: The configuration of the plot widget.
|
1092
1131
|
"""
|
1132
|
+
|
1133
|
+
|
1134
|
+
class BECMotorMap(RPCBase):
|
1135
|
+
@rpc_call
|
1136
|
+
def change_motors(
|
1137
|
+
self,
|
1138
|
+
motor_x: "str",
|
1139
|
+
motor_y: "str",
|
1140
|
+
motor_x_entry: "str" = None,
|
1141
|
+
motor_y_entry: "str" = None,
|
1142
|
+
validate_bec: "bool" = True,
|
1143
|
+
) -> "None":
|
1144
|
+
"""
|
1145
|
+
Change the active motors for the plot.
|
1146
|
+
Args:
|
1147
|
+
motor_x(str): Motor name for the X axis.
|
1148
|
+
motor_y(str): Motor name for the Y axis.
|
1149
|
+
motor_x_entry(str): Motor entry for the X axis.
|
1150
|
+
motor_y_entry(str): Motor entry for the Y axis.
|
1151
|
+
validate_bec(bool, optional): If True, validate the signal with BEC. Defaults to True.
|
1152
|
+
"""
|
1153
|
+
|
1154
|
+
@rpc_call
|
1155
|
+
def set_max_points(self, max_points: "int") -> "None":
|
1156
|
+
"""
|
1157
|
+
Set the maximum number of points to display.
|
1158
|
+
Args:
|
1159
|
+
max_points(int): Maximum number of points to display.
|
1160
|
+
"""
|
1161
|
+
|
1162
|
+
@rpc_call
|
1163
|
+
def set_precision(self, precision: "int") -> "None":
|
1164
|
+
"""
|
1165
|
+
Set the decimal precision of the motor position.
|
1166
|
+
Args:
|
1167
|
+
precision(int): Decimal precision of the motor position.
|
1168
|
+
"""
|
1169
|
+
|
1170
|
+
@rpc_call
|
1171
|
+
def set_num_dim_points(self, num_dim_points: "int") -> "None":
|
1172
|
+
"""
|
1173
|
+
Set the number of dim points for the motor map.
|
1174
|
+
Args:
|
1175
|
+
num_dim_points(int): Number of dim points.
|
1176
|
+
"""
|
1177
|
+
|
1178
|
+
@rpc_call
|
1179
|
+
def set_background_value(self, background_value: "int") -> "None":
|
1180
|
+
"""
|
1181
|
+
Set the background value of the motor map.
|
1182
|
+
Args:
|
1183
|
+
background_value(int): Background value of the motor map.
|
1184
|
+
"""
|
1185
|
+
|
1186
|
+
@rpc_call
|
1187
|
+
def set_scatter_size(self, scatter_size: "int") -> "None":
|
1188
|
+
"""
|
1189
|
+
Set the scatter size of the motor map plot.
|
1190
|
+
Args:
|
1191
|
+
scatter_size(int): Size of the scatter points.
|
1192
|
+
"""
|
bec_widgets/cli/client_utils.py
CHANGED
@@ -8,12 +8,12 @@ import uuid
|
|
8
8
|
from functools import wraps
|
9
9
|
from typing import TYPE_CHECKING
|
10
10
|
|
11
|
-
from qtpy.QtCore import QCoreApplication
|
12
|
-
|
13
|
-
import bec_widgets.cli.client as client
|
14
11
|
from bec_lib import MessageEndpoints, messages
|
15
12
|
from bec_lib.connector import MessageObject
|
16
13
|
from bec_lib.device import DeviceBase
|
14
|
+
from qtpy.QtCore import QCoreApplication
|
15
|
+
|
16
|
+
import bec_widgets.cli.client as client
|
17
17
|
from bec_widgets.utils.bec_dispatcher import BECDispatcher
|
18
18
|
|
19
19
|
if TYPE_CHECKING:
|
@@ -59,7 +59,7 @@ def update_script(figure: BECFigure, msg):
|
|
59
59
|
"""
|
60
60
|
info = msg.info
|
61
61
|
status = msg.status
|
62
|
-
scan_id = msg.
|
62
|
+
scan_id = msg.scan_id
|
63
63
|
scan_number = info.get("scan_number", 0)
|
64
64
|
scan_name = info.get("scan_name", "Unknown")
|
65
65
|
scan_report_devices = info.get("scan_report_devices", [])
|
bec_widgets/cli/generate_cli.py
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# pylint: disable=missing-module-docstring
|
2
2
|
from __future__ import annotations
|
3
|
+
|
3
4
|
import inspect
|
4
|
-
import black
|
5
5
|
import sys
|
6
6
|
|
7
|
+
import black
|
7
8
|
|
8
9
|
if sys.version_info >= (3, 11):
|
9
10
|
from typing import get_overloads
|
@@ -106,11 +107,11 @@ class {class_name}(RPCBase):"""
|
|
106
107
|
if __name__ == "__main__": # pragma: no cover
|
107
108
|
import os
|
108
109
|
|
110
|
+
from bec_widgets.utils import BECConnector
|
109
111
|
from bec_widgets.widgets.figure import BECFigure
|
110
|
-
from bec_widgets.widgets.plots import BECPlotBase, BECWaveform1D
|
111
|
-
from bec_widgets.widgets.plots.waveform1d import BECCurve
|
112
|
+
from bec_widgets.widgets.plots import BECImageShow, BECMotorMap, BECPlotBase, BECWaveform1D
|
112
113
|
from bec_widgets.widgets.plots.image import BECImageItem
|
113
|
-
from bec_widgets.
|
114
|
+
from bec_widgets.widgets.plots.waveform1d import BECCurve
|
114
115
|
|
115
116
|
current_path = os.path.dirname(__file__)
|
116
117
|
client_path = os.path.join(current_path, "client.py")
|
@@ -122,6 +123,7 @@ if __name__ == "__main__": # pragma: no cover
|
|
122
123
|
BECImageShow,
|
123
124
|
BECConnector,
|
124
125
|
BECImageItem,
|
126
|
+
BECMotorMap,
|
125
127
|
]
|
126
128
|
generator = ClientGenerator()
|
127
129
|
generator.generate_client(clss)
|
bec_widgets/cli/server.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
import inspect
|
2
2
|
|
3
|
+
from bec_lib import MessageEndpoints, messages
|
3
4
|
from qtpy.QtCore import QTimer
|
4
5
|
|
5
|
-
from bec_lib import MessageEndpoints, messages
|
6
6
|
from bec_widgets.utils import BECDispatcher
|
7
7
|
from bec_widgets.utils.bec_connector import BECConnector
|
8
8
|
from bec_widgets.widgets.figure import BECFigure
|
@@ -115,8 +115,7 @@ if __name__ == "__main__": # pragma: no cover
|
|
115
115
|
import argparse
|
116
116
|
import sys
|
117
117
|
|
118
|
-
from qtpy.QtWidgets import QApplication
|
119
|
-
from qtpy.QtWidgets import QMainWindow
|
118
|
+
from qtpy.QtWidgets import QApplication, QMainWindow
|
120
119
|
|
121
120
|
app = QApplication(sys.argv)
|
122
121
|
app.setApplicationName("BEC Figure")
|
bec_widgets/examples/__init__.py
CHANGED
@@ -6,20 +6,11 @@ import h5py
|
|
6
6
|
import numpy as np
|
7
7
|
import pyqtgraph as pg
|
8
8
|
import zmq
|
9
|
+
from pyqtgraph.Qt import uic
|
9
10
|
from qtpy.QtCore import Signal as pyqtSignal
|
10
11
|
from qtpy.QtCore import Slot as pyqtSlot
|
11
12
|
from qtpy.QtGui import QKeySequence
|
12
|
-
from qtpy.QtWidgets import
|
13
|
-
QWidget,
|
14
|
-
QFileDialog,
|
15
|
-
QShortcut,
|
16
|
-
QDialog,
|
17
|
-
QVBoxLayout,
|
18
|
-
QLabel,
|
19
|
-
QFrame,
|
20
|
-
)
|
21
|
-
from pyqtgraph.Qt import uic
|
22
|
-
|
13
|
+
from qtpy.QtWidgets import QDialog, QFileDialog, QFrame, QLabel, QShortcut, QVBoxLayout, QWidget
|
23
14
|
|
24
15
|
# from scipy.stats import multivariate_normal
|
25
16
|
|
@@ -307,6 +298,7 @@ class EigerPlot(QWidget):
|
|
307
298
|
|
308
299
|
if __name__ == "__main__":
|
309
300
|
import sys
|
301
|
+
|
310
302
|
from qtpy.QtWidgets import QApplication
|
311
303
|
|
312
304
|
app = QApplication(sys.argv)
|
@@ -1,19 +1,15 @@
|
|
1
1
|
# import simulation_progress as SP
|
2
2
|
import numpy as np
|
3
3
|
import pyqtgraph as pg
|
4
|
-
from qtpy.QtCore import Signal as pyqtSignal, Slot as pyqtSlot
|
5
|
-
from qtpy.QtWidgets import (
|
6
|
-
QApplication,
|
7
|
-
QVBoxLayout,
|
8
|
-
QWidget,
|
9
|
-
)
|
10
|
-
|
11
4
|
from bec_lib import MessageEndpoints, messages
|
5
|
+
from qtpy.QtCore import Signal as pyqtSignal
|
6
|
+
from qtpy.QtCore import Slot as pyqtSlot
|
7
|
+
from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget
|
12
8
|
|
13
9
|
|
14
10
|
class StreamApp(QWidget):
|
15
11
|
update_signal = pyqtSignal()
|
16
|
-
|
12
|
+
new_scan_id = pyqtSignal(str)
|
17
13
|
|
18
14
|
def __init__(self, device, sub_device):
|
19
15
|
super().__init__()
|
@@ -23,7 +19,7 @@ class StreamApp(QWidget):
|
|
23
19
|
self.setWindowTitle("MCA readout")
|
24
20
|
|
25
21
|
self.data = None
|
26
|
-
self.
|
22
|
+
self.scan_id = None
|
27
23
|
self.stream_consumer = None
|
28
24
|
|
29
25
|
self.device = device
|
@@ -33,7 +29,7 @@ class StreamApp(QWidget):
|
|
33
29
|
|
34
30
|
# self.start_device_consumer(self.device) # for simulation
|
35
31
|
|
36
|
-
self.
|
32
|
+
self.new_scan_id.connect(self.create_new_stream_consumer)
|
37
33
|
self.update_signal.connect(self.plot_new)
|
38
34
|
|
39
35
|
def init_ui(self):
|
@@ -64,17 +60,17 @@ class StreamApp(QWidget):
|
|
64
60
|
# self.glw.addItem(self.hist)
|
65
61
|
|
66
62
|
@pyqtSlot(str)
|
67
|
-
def create_new_stream_consumer(self,
|
68
|
-
print(f"Creating new stream consumer for
|
63
|
+
def create_new_stream_consumer(self, scan_id: str):
|
64
|
+
print(f"Creating new stream consumer for scan_id: {scan_id}")
|
69
65
|
|
70
|
-
self.connect_stream_consumer(
|
66
|
+
self.connect_stream_consumer(scan_id, self.device)
|
71
67
|
|
72
|
-
def connect_stream_consumer(self,
|
68
|
+
def connect_stream_consumer(self, scan_id, device):
|
73
69
|
if self.stream_consumer is not None:
|
74
70
|
self.stream_consumer.shutdown()
|
75
71
|
|
76
72
|
self.stream_consumer = connector.stream_consumer(
|
77
|
-
topics=MessageEndpoints.device_async_readback(
|
73
|
+
topics=MessageEndpoints.device_async_readback(scan_id=scan_id, device=device),
|
78
74
|
cb=self._streamer_cb,
|
79
75
|
parent=self,
|
80
76
|
)
|
@@ -125,24 +121,25 @@ class StreamApp(QWidget):
|
|
125
121
|
|
126
122
|
msgDEV = msg.value
|
127
123
|
|
128
|
-
|
124
|
+
current_scan_id = msgDEV.content["scan_id"]
|
129
125
|
|
130
|
-
if parent.
|
131
|
-
parent.
|
132
|
-
parent.
|
133
|
-
print(f"New
|
126
|
+
if parent.scan_id is None:
|
127
|
+
parent.scan_id = current_scan_id
|
128
|
+
parent.new_scan_id.emit(current_scan_id)
|
129
|
+
print(f"New scan_id: {current_scan_id}")
|
134
130
|
|
135
|
-
if
|
136
|
-
parent.
|
131
|
+
if current_scan_id != parent.scan_id:
|
132
|
+
parent.scan_id = current_scan_id
|
137
133
|
# parent.data = None
|
138
134
|
# parent.imageItem.clear()
|
139
|
-
parent.
|
135
|
+
parent.new_scan_id.emit(current_scan_id)
|
140
136
|
|
141
|
-
print(f"New
|
137
|
+
print(f"New scan_id: {current_scan_id}")
|
142
138
|
|
143
139
|
|
144
140
|
if __name__ == "__main__":
|
145
141
|
import argparse
|
142
|
+
|
146
143
|
from bec_lib import RedisConnector
|
147
144
|
|
148
145
|
parser = argparse.ArgumentParser(description="Stream App.")
|
@@ -1,31 +1,26 @@
|
|
1
|
-
from bec_lib import messages, MessageEndpoints, RedisConnector
|
2
1
|
import time
|
3
2
|
|
3
|
+
from bec_lib import MessageEndpoints, RedisConnector, messages
|
4
|
+
|
4
5
|
connector = RedisConnector("localhost:6379")
|
5
6
|
producer = connector.producer()
|
6
7
|
metadata = {}
|
7
8
|
|
8
|
-
|
9
|
+
scan_id = "ScanID1"
|
9
10
|
|
10
11
|
metadata.update(
|
11
|
-
{
|
12
|
-
"scanID": scanID, # this will be different for each scan
|
13
|
-
"async_update": "append",
|
14
|
-
}
|
12
|
+
{"scan_id": scan_id, "async_update": "append"} # this will be different for each scan
|
15
13
|
)
|
16
14
|
for ii in range(20):
|
17
15
|
data = {"mca1": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "mca2": [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]}
|
18
|
-
msg = messages.DeviceMessage(
|
19
|
-
signals=data,
|
20
|
-
metadata=metadata,
|
21
|
-
).dumps()
|
16
|
+
msg = messages.DeviceMessage(signals=data, metadata=metadata).dumps()
|
22
17
|
|
23
18
|
# producer.send(topic=MessageEndpoints.device_status(device="mca"), msg=msg)
|
24
19
|
|
25
20
|
producer.xadd(
|
26
21
|
topic=MessageEndpoints.device_async_readback(
|
27
|
-
|
28
|
-
), #
|
22
|
+
scan_id=scan_id, device="mca"
|
23
|
+
), # scan_id will be different for each scan
|
29
24
|
msg={"data": msg}, # TODO should be msg_dict
|
30
25
|
expire=1800,
|
31
26
|
)
|
@@ -1,22 +1,17 @@
|
|
1
1
|
# pylint: disable = no-name-in-module,missing-class-docstring, missing-module-docstring
|
2
2
|
|
3
3
|
import qdarktheme
|
4
|
-
from qtpy.QtWidgets import QApplication
|
5
|
-
from qtpy.QtWidgets import QVBoxLayout
|
6
|
-
from qtpy.QtWidgets import (
|
7
|
-
QWidget,
|
8
|
-
QSplitter,
|
9
|
-
)
|
10
4
|
from qtpy.QtCore import Qt
|
5
|
+
from qtpy.QtWidgets import QApplication, QSplitter, QVBoxLayout, QWidget
|
11
6
|
|
12
7
|
from bec_widgets.utils.bec_dispatcher import BECDispatcher
|
13
8
|
from bec_widgets.widgets import (
|
14
9
|
MotorControlAbsolute,
|
15
10
|
MotorControlRelative,
|
16
11
|
MotorControlSelection,
|
17
|
-
MotorThread,
|
18
|
-
MotorMap,
|
19
12
|
MotorCoordinateTable,
|
13
|
+
MotorMap,
|
14
|
+
MotorThread,
|
20
15
|
)
|
21
16
|
|
22
17
|
CONFIG_DEFAULT = {
|
@@ -5,29 +5,28 @@ from functools import partial
|
|
5
5
|
|
6
6
|
import numpy as np
|
7
7
|
import pyqtgraph as pg
|
8
|
+
from bec_lib import MessageEndpoints, messages
|
9
|
+
from pyqtgraph.Qt import QtCore, QtWidgets, uic
|
8
10
|
from qtpy import QtGui
|
9
|
-
from qtpy.QtCore import
|
10
|
-
from qtpy.QtCore import Signal as pyqtSignal
|
11
|
-
from qtpy.
|
12
|
-
from qtpy.QtGui import QKeySequence
|
11
|
+
from qtpy.QtCore import Qt, QThread
|
12
|
+
from qtpy.QtCore import Signal as pyqtSignal
|
13
|
+
from qtpy.QtCore import Slot as pyqtSlot
|
14
|
+
from qtpy.QtGui import QDoubleValidator, QKeySequence
|
13
15
|
from qtpy.QtWidgets import (
|
14
16
|
QApplication,
|
15
|
-
QWidget,
|
16
|
-
QFileDialog,
|
17
17
|
QDialog,
|
18
|
-
|
18
|
+
QFileDialog,
|
19
|
+
QFrame,
|
19
20
|
QLabel,
|
21
|
+
QMessageBox,
|
20
22
|
QPushButton,
|
21
|
-
|
23
|
+
QShortcut,
|
24
|
+
QVBoxLayout,
|
25
|
+
QWidget,
|
22
26
|
)
|
23
|
-
from qtpy.QtWidgets import QMessageBox
|
24
|
-
from qtpy.QtWidgets import QShortcut
|
25
|
-
from pyqtgraph.Qt import QtWidgets, uic, QtCore
|
26
27
|
|
27
|
-
from bec_lib import MessageEndpoints, messages
|
28
28
|
from bec_widgets.utils import DoubleValidationDelegate
|
29
29
|
|
30
|
-
|
31
30
|
# TODO - General features
|
32
31
|
# - put motor status (moving, stopped, etc)
|
33
32
|
# - add mouse interactions with the plot -> click to select coordinates, double click to move?
|
@@ -1306,9 +1305,9 @@ class MotorControl(QThread):
|
|
1306
1305
|
|
1307
1306
|
|
1308
1307
|
if __name__ == "__main__":
|
1309
|
-
import yaml
|
1310
1308
|
import argparse
|
1311
1309
|
|
1310
|
+
import yaml
|
1312
1311
|
from bec_lib import BECClient, ServiceConfig
|
1313
1312
|
|
1314
1313
|
parser = argparse.ArgumentParser(description="Motor App")
|
@@ -5,14 +5,15 @@ import time
|
|
5
5
|
import numpy as np
|
6
6
|
import pyqtgraph
|
7
7
|
import pyqtgraph as pg
|
8
|
-
from bec_lib import
|
8
|
+
from bec_lib import MessageEndpoints, messages
|
9
9
|
from bec_lib.redis_connector import RedisConnector
|
10
|
-
from qtpy.QtCore import Slot as pyqtSlot
|
11
|
-
from qtpy.QtWidgets import QTableWidgetItem
|
12
10
|
from pyqtgraph import mkBrush, mkPen
|
13
11
|
from pyqtgraph.Qt import QtCore, QtWidgets, uic
|
14
12
|
from pyqtgraph.Qt.QtCore import pyqtSignal
|
15
|
-
from
|
13
|
+
from qtpy.QtCore import Slot as pyqtSlot
|
14
|
+
from qtpy.QtWidgets import QTableWidgetItem
|
15
|
+
|
16
|
+
from bec_widgets.utils import Colors, Crosshair
|
16
17
|
from bec_widgets.utils.bec_dispatcher import BECDispatcher
|
17
18
|
|
18
19
|
|
bec_widgets/utils/__init__.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
from .crosshair import Crosshair
|
2
|
-
from .colors import Colors
|
3
|
-
from .validator_delegate import DoubleValidationDelegate
|
4
|
-
from .bec_table import BECTable
|
5
1
|
from .bec_connector import BECConnector, ConnectionConfig
|
6
2
|
from .bec_dispatcher import BECDispatcher
|
7
|
-
from .
|
3
|
+
from .bec_table import BECTable
|
4
|
+
from .colors import Colors
|
5
|
+
from .crosshair import Crosshair
|
8
6
|
from .entry_validator import EntryValidator
|
7
|
+
from .rpc_decorator import register_rpc_methods, rpc_public
|
8
|
+
from .validator_delegate import DoubleValidationDelegate
|
@@ -8,11 +8,10 @@ from typing import Union
|
|
8
8
|
|
9
9
|
import redis
|
10
10
|
from bec_lib import BECClient, ServiceConfig
|
11
|
+
from bec_lib.endpoints import EndpointInfo
|
11
12
|
from qtpy.QtCore import QObject
|
12
13
|
from qtpy.QtCore import Signal as pyqtSignal
|
13
14
|
|
14
|
-
from bec_lib.endpoints import EndpointInfo
|
15
|
-
|
16
15
|
# Adding a new pyqt signal requires a class factory, as they must be part of the class definition
|
17
16
|
# and cannot be dynamically added as class attributes after the class has been defined.
|
18
17
|
_signal_class_factory = (
|
bec_widgets/utils/bec_table.py
CHANGED
bec_widgets/utils/crosshair.py
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# from qtpy.QtWidgets import QStyledItemDelegate, QLineEdit
|
3
3
|
|
4
4
|
from qtpy.QtGui import QDoubleValidator
|
5
|
-
from qtpy.QtWidgets import
|
5
|
+
from qtpy.QtWidgets import QLineEdit, QStyledItemDelegate
|
6
6
|
|
7
7
|
|
8
8
|
class DoubleValidationDelegate(QStyledItemDelegate):
|
bec_widgets/utils/widget_io.py
CHANGED
@@ -3,16 +3,16 @@ from abc import ABC, abstractmethod
|
|
3
3
|
|
4
4
|
from qtpy.QtWidgets import (
|
5
5
|
QApplication,
|
6
|
-
|
7
|
-
QLineEdit,
|
6
|
+
QCheckBox,
|
8
7
|
QComboBox,
|
9
|
-
QTableWidget,
|
10
|
-
QSpinBox,
|
11
8
|
QDoubleSpinBox,
|
9
|
+
QLabel,
|
10
|
+
QLineEdit,
|
11
|
+
QSpinBox,
|
12
|
+
QTableWidget,
|
12
13
|
QTableWidgetItem,
|
13
14
|
QVBoxLayout,
|
14
|
-
|
15
|
-
QLabel,
|
15
|
+
QWidget,
|
16
16
|
)
|
17
17
|
|
18
18
|
|
bec_widgets/utils/yaml_dialog.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
from typing import Optional, Union
|
1
|
+
from typing import Literal, Optional, Union
|
2
2
|
|
3
|
-
from pydantic import BaseModel, Field, field_validator, model_validator
|
3
|
+
from pydantic import BaseModel, Field, ValidationError, field_validator, model_validator
|
4
4
|
from pydantic_core import PydanticCustomError
|
5
5
|
|
6
6
|
|
@@ -92,12 +92,12 @@ class SourceHistoryValidator(BaseModel):
|
|
92
92
|
"""History source validator
|
93
93
|
Attributes:
|
94
94
|
type (str): type of source - history
|
95
|
-
|
95
|
+
scan_id (str): Scan ID for history source.
|
96
96
|
signals (list): Signal for the source.
|
97
97
|
"""
|
98
98
|
|
99
99
|
type: Literal["history"]
|
100
|
-
|
100
|
+
scan_id: str # TODO can be validated if it is a valid scan_id
|
101
101
|
signals: AxisSignal
|
102
102
|
|
103
103
|
|
@@ -131,12 +131,12 @@ class Source(BaseModel): # TODO decide if it should stay for general Source val
|
|
131
131
|
General source validation, includes all Optional arguments of all other sources.
|
132
132
|
Attributes:
|
133
133
|
type (list): type of source (scan_segment, history)
|
134
|
-
|
134
|
+
scan_id (Optional[str]): Scan ID for history source.
|
135
135
|
signals (Optional[AxisSignal]): Signal for the source.
|
136
136
|
"""
|
137
137
|
|
138
138
|
type: Literal["scan_segment", "history", "redis"]
|
139
|
-
|
139
|
+
scan_id: Optional[str] = None
|
140
140
|
signals: Optional[dict] = None
|
141
141
|
|
142
142
|
|