bec-widgets 0.78.0__py3-none-any.whl → 0.79.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.
Files changed (28) hide show
  1. CHANGELOG.md +26 -28
  2. PKG-INFO +1 -1
  3. bec_widgets/cli/client.py +90 -0
  4. bec_widgets/utils/ui_loader.py +30 -7
  5. bec_widgets/utils/widget_io.py +25 -2
  6. bec_widgets/widgets/figure/plots/axis_settings.py +61 -0
  7. bec_widgets/widgets/figure/plots/axis_settings.ui +249 -0
  8. bec_widgets/widgets/figure/plots/motor_map/motor_map.py +18 -5
  9. bec_widgets/widgets/motor_map/__init__.py +0 -0
  10. bec_widgets/widgets/motor_map/assets/connection.svg +4 -0
  11. bec_widgets/widgets/motor_map/assets/history.svg +4 -0
  12. bec_widgets/widgets/motor_map/assets/motor_map.png +0 -0
  13. bec_widgets/widgets/motor_map/assets/settings.svg +4 -0
  14. bec_widgets/widgets/motor_map/bec_motor_map_widget.pyproject +1 -0
  15. bec_widgets/widgets/motor_map/bec_motor_map_widget_plugin.py +55 -0
  16. bec_widgets/widgets/motor_map/motor_map_dialog/__init__.py +0 -0
  17. bec_widgets/widgets/motor_map/motor_map_dialog/motor_map_settings.py +73 -0
  18. bec_widgets/widgets/motor_map/motor_map_dialog/motor_map_settings.ui +108 -0
  19. bec_widgets/widgets/motor_map/motor_map_dialog/motor_map_toolbar.py +59 -0
  20. bec_widgets/widgets/motor_map/motor_map_widget.py +235 -0
  21. bec_widgets/widgets/motor_map/register_bec_motor_map_widget.py +15 -0
  22. bec_widgets/widgets/toolbar/toolbar.py +43 -103
  23. {bec_widgets-0.78.0.dist-info → bec_widgets-0.79.0.dist-info}/METADATA +1 -1
  24. {bec_widgets-0.78.0.dist-info → bec_widgets-0.79.0.dist-info}/RECORD +28 -13
  25. pyproject.toml +1 -1
  26. {bec_widgets-0.78.0.dist-info → bec_widgets-0.79.0.dist-info}/WHEEL +0 -0
  27. {bec_widgets-0.78.0.dist-info → bec_widgets-0.79.0.dist-info}/entry_points.txt +0 -0
  28. {bec_widgets-0.78.0.dist-info → bec_widgets-0.79.0.dist-info}/licenses/LICENSE +0 -0
CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v0.79.0 (2024-07-03)
4
+
5
+ ### Feature
6
+
7
+ * feat(motor_map_widget): standalone MotorMap Widget with toolbar + plugin ([`6e75642`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/6e756420907d7093557e945bc92bc4cfc0138d07))
8
+
9
+ * feat(motor_map): method to reset history trace ([`5960918`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/5960918137dd41cdeb94e50f8abc4f169cf45c11))
10
+
11
+ ### Fix
12
+
13
+ * fix(toolbar): change default color to black to match BECFigure theme ([`b8774e0`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/b8774e0b0bc43dcd00f94f42539a778e507ca27d))
14
+
15
+ * fix(motor_map): fixed bug with residual trace after changing motors ([`aaa0d10`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/aaa0d1003d2e94b45bafe4f700852c2c05288aea))
16
+
17
+ * fix(widget_io): widget handler adjusted for spinboxes and comboboxes ([`3dc0532`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/3dc0532df05b6ec0a2522107fa0b1e210ce7d91b))
18
+
19
+ ### Refactor
20
+
21
+ * refactor(toolbar): cleanup and adjusted colors ([`96863ad`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/96863adf53c15112645d20eb6200733617801c6d))
22
+
23
+ ## v0.78.1 (2024-07-02)
24
+
25
+ ### Fix
26
+
27
+ * fix(ui_loader): ui loader is compatible with bec plugins ([`b787759`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/b787759f44486dc7af2c03811efb156041e4b6cb))
28
+
3
29
  ## v0.78.0 (2024-07-02)
4
30
 
5
31
  ### Feature
@@ -121,31 +147,3 @@
121
147
  * fix(rpc): trigger shutdown of server when gui is terminated ([`acc1318`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/acc13183e28030e3ca9af21bb081e1eed081622b))
122
148
 
123
149
  * fix(rpc): remove of calling "close" and waiting for gui_is_alive ([`f75fc19`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/f75fc19c5b10022763252917ca473f404a25165a))
124
-
125
- ## v0.73.1 (2024-06-25)
126
-
127
- ### Fix
128
-
129
- * fix(ringprogressbar): removed hard-coded endpoint strings ([`1de3cbf`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/1de3cbf65a1832150917a7549a1bf3efdee6371a))
130
-
131
- ## v0.73.0 (2024-06-25)
132
-
133
- ### Feature
134
-
135
- * feat: add new default scaling of image_item ([`df812ea`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/df812eaad5989f2930dde41d87491868505af946))
136
-
137
- ### Test
138
-
139
- * test: add test for imageitem ([`88ecd05`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/88ecd05b95974938ef1efff40e81854baf004cb4))
140
-
141
- ## v0.72.2 (2024-06-25)
142
-
143
- ### Fix
144
-
145
- * fix(designer): fixed designer for pyenv and venv; closes #237 ([`e631fc1`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/e631fc15d8707b73d58cb64316e115a7e43961ea))
146
-
147
- ## v0.72.1 (2024-06-24)
148
-
149
- ### Fix
150
-
151
- * fix: renamed spiral progress bar to ring progress bar; closes #235 ([`e5c0087`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/e5c0087c9aed831edbe1c172746325a772a3bafa))
PKG-INFO CHANGED
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.78.0
3
+ Version: 0.79.0
4
4
  Summary: BEC Widgets
5
5
  Project-URL: Bug Tracker, https://gitlab.psi.ch/bec/bec_widgets/issues
6
6
  Project-URL: Homepage, https://gitlab.psi.ch/bec/bec_widgets
bec_widgets/cli/client.py CHANGED
@@ -18,6 +18,7 @@ class Widgets(str, enum.Enum):
18
18
  BECDock = "BECDock"
19
19
  BECDockArea = "BECDockArea"
20
20
  BECFigure = "BECFigure"
21
+ BECMotorMapWidget = "BECMotorMapWidget"
21
22
  RingProgressBar = "RingProgressBar"
22
23
  ScanControl = "ScanControl"
23
24
  TextBox = "TextBox"
@@ -1192,6 +1193,7 @@ class BECMotorMap(RPCBase):
1192
1193
  def get_data(self) -> "dict":
1193
1194
  """
1194
1195
  Get the data of the motor map.
1196
+
1195
1197
  Returns:
1196
1198
  dict: Data of the motor map.
1197
1199
  """
@@ -1202,6 +1204,94 @@ class BECMotorMap(RPCBase):
1202
1204
  Remove the plot widget from the figure.
1203
1205
  """
1204
1206
 
1207
+ @rpc_call
1208
+ def reset_history(self):
1209
+ """
1210
+ Reset the history of the motor map.
1211
+ """
1212
+
1213
+
1214
+ class BECMotorMapWidget(RPCBase):
1215
+ @rpc_call
1216
+ def change_motors(
1217
+ self,
1218
+ motor_x: "str",
1219
+ motor_y: "str",
1220
+ motor_x_entry: "str" = None,
1221
+ motor_y_entry: "str" = None,
1222
+ validate_bec: "bool" = True,
1223
+ ) -> "None":
1224
+ """
1225
+ Change the active motors for the plot.
1226
+
1227
+ Args:
1228
+ motor_x(str): Motor name for the X axis.
1229
+ motor_y(str): Motor name for the Y axis.
1230
+ motor_x_entry(str): Motor entry for the X axis.
1231
+ motor_y_entry(str): Motor entry for the Y axis.
1232
+ validate_bec(bool, optional): If True, validate the signal with BEC. Defaults to True.
1233
+ """
1234
+
1235
+ @rpc_call
1236
+ def set_max_points(self, max_points: "int") -> "None":
1237
+ """
1238
+ Set the maximum number of points to display on the motor map.
1239
+
1240
+ Args:
1241
+ max_points(int): Maximum number of points to display.
1242
+ """
1243
+
1244
+ @rpc_call
1245
+ def set_precision(self, precision: "int") -> "None":
1246
+ """
1247
+ Set the precision of the motor map.
1248
+
1249
+ Args:
1250
+ precision(int): Precision to set.
1251
+ """
1252
+
1253
+ @rpc_call
1254
+ def set_num_dim_points(self, num_dim_points: "int") -> "None":
1255
+ """
1256
+ Set the number of points to display on the motor map.
1257
+
1258
+ Args:
1259
+ num_dim_points(int): Number of points to display.
1260
+ """
1261
+
1262
+ @rpc_call
1263
+ def set_background_value(self, background_value: "int") -> "None":
1264
+ """
1265
+ Set the background value of the motor map.
1266
+
1267
+ Args:
1268
+ background_value(int): Background value of the motor map.
1269
+ """
1270
+
1271
+ @rpc_call
1272
+ def set_scatter_size(self, scatter_size: "int") -> "None":
1273
+ """
1274
+ Set the scatter size of the motor map.
1275
+
1276
+ Args:
1277
+ scatter_size(int): Scatter size of the motor map.
1278
+ """
1279
+
1280
+ @rpc_call
1281
+ def get_data(self) -> "dict":
1282
+ """
1283
+ Get the data of the motor map.
1284
+
1285
+ Returns:
1286
+ dict: Data of the motor map.
1287
+ """
1288
+
1289
+ @rpc_call
1290
+ def reset_history(self) -> "None":
1291
+ """
1292
+ Reset the history of the motor map.
1293
+ """
1294
+
1205
1295
 
1206
1296
  class BECPlotBase(RPCBase):
1207
1297
  @property
@@ -1,6 +1,30 @@
1
- from qtpy import QT_VERSION
1
+ from qtpy import PYQT6, PYSIDE6, QT_VERSION
2
2
  from qtpy.QtCore import QFile, QIODevice
3
3
 
4
+ if PYSIDE6:
5
+ from PySide6.QtUiTools import QUiLoader
6
+
7
+ from bec_widgets.utils.plugin_utils import get_rpc_classes
8
+ from bec_widgets.widgets.buttons.color_button.color_button import ColorButton
9
+
10
+ class CustomUiLoader(QUiLoader):
11
+ def __init__(self, baseinstance):
12
+ super().__init__(baseinstance)
13
+ widgets = get_rpc_classes("bec_widgets").get("top_level_classes", [])
14
+
15
+ widgets.append(ColorButton)
16
+
17
+ self.custom_widgets = {widget.__name__: widget for widget in widgets}
18
+
19
+ self.baseinstance = baseinstance
20
+
21
+ def createWidget(self, class_name, parent=None, name=""):
22
+ if class_name in self.custom_widgets:
23
+ widget = self.custom_widgets[class_name](parent)
24
+ widget.setObjectName(name)
25
+ return widget
26
+ return super().createWidget(class_name, parent, name)
27
+
4
28
 
5
29
  class UILoader:
6
30
  """Universal UI loader for PyQt5, PyQt6, PySide2, and PySide6."""
@@ -14,14 +38,14 @@ class UILoader:
14
38
  self.loader = uic.loadUi
15
39
  elif QT_VERSION.startswith("6"):
16
40
  # PyQt6 or PySide6
17
- try:
18
- from PySide6.QtUiTools import QUiLoader
19
-
41
+ if PYSIDE6:
20
42
  self.loader = self.load_ui_pyside6
21
- except ImportError:
43
+ elif PYQT6:
22
44
  from PyQt6.uic import loadUi
23
45
 
24
46
  self.loader = loadUi
47
+ else:
48
+ raise ImportError("No compatible Qt bindings found.")
25
49
 
26
50
  def load_ui_pyside6(self, ui_file, parent=None):
27
51
  """
@@ -33,9 +57,8 @@ class UILoader:
33
57
  Returns:
34
58
  QWidget: The loaded widget.
35
59
  """
36
- from PySide6.QtUiTools import QUiLoader
37
60
 
38
- loader = QUiLoader(parent)
61
+ loader = CustomUiLoader(parent)
39
62
  file = QFile(ui_file)
40
63
  if not file.open(QIODevice.ReadOnly):
41
64
  raise IOError(f"Cannot open file: {ui_file}")
@@ -44,8 +44,11 @@ class ComboBoxHandler(WidgetHandler):
44
44
  def get_value(self, widget: QComboBox) -> int:
45
45
  return widget.currentIndex()
46
46
 
47
- def set_value(self, widget: QComboBox, value: int) -> None:
48
- widget.setCurrentIndex(value)
47
+ def set_value(self, widget: QComboBox, value: int | str) -> None:
48
+ if isinstance(value, str):
49
+ value = widget.findText(value)
50
+ if isinstance(value, int):
51
+ widget.setCurrentIndex(value)
49
52
 
50
53
 
51
54
  class TableWidgetHandler(WidgetHandler):
@@ -142,6 +145,26 @@ class WidgetIO:
142
145
  elif not ignore_errors:
143
146
  raise ValueError(f"No handler for widget type: {type(widget)}")
144
147
 
148
+ @staticmethod
149
+ def check_and_adjust_limits(spin_box: QDoubleSpinBox, number: float):
150
+ """
151
+ Check if the new limits are within the current limits, if not adjust the limits.
152
+
153
+ Args:
154
+ number(float): The new value to check against the limits.
155
+ """
156
+
157
+ min_value = spin_box.minimum()
158
+ max_value = spin_box.maximum()
159
+
160
+ # Calculate the new limits
161
+ new_limit = number + 5 * number
162
+
163
+ if number < min_value:
164
+ spin_box.setMinimum(new_limit)
165
+ elif number > max_value:
166
+ spin_box.setMaximum(new_limit)
167
+
145
168
  @staticmethod
146
169
  def _find_handler(widget):
147
170
  """
@@ -0,0 +1,61 @@
1
+ import os
2
+
3
+ import qdarktheme
4
+ from qtpy.QtCore import Slot
5
+ from qtpy.QtWidgets import QVBoxLayout, QWidget
6
+
7
+ from bec_widgets.utils import UILoader
8
+ from bec_widgets.utils.widget_io import WidgetIO
9
+
10
+
11
+ class AxisSettings(QWidget):
12
+ def __init__(self, parent=None, *args, **kwargs):
13
+ super().__init__(parent=parent, *args, **kwargs)
14
+
15
+ current_path = os.path.dirname(__file__)
16
+ self.ui = UILoader().load_ui(os.path.join(current_path, "axis_settings.ui"), self)
17
+
18
+ self.layout = QVBoxLayout(self)
19
+ self.layout.addWidget(self.ui)
20
+
21
+ # Hardcoded values for best appearance
22
+ self.setMinimumHeight(280)
23
+ self.setMaximumHeight(280)
24
+ self.resize(380, 280)
25
+
26
+ @Slot(dict)
27
+ def display_current_settings(self, axis_config: dict):
28
+ # Top Box
29
+ WidgetIO.set_value(self.ui.plot_title, axis_config["title"])
30
+
31
+ # X Axis Box
32
+ WidgetIO.set_value(self.ui.x_label, axis_config["x_label"])
33
+ WidgetIO.set_value(self.ui.x_scale, axis_config["x_scale"])
34
+ WidgetIO.set_value(self.ui.x_grid, axis_config["x_grid"])
35
+ if axis_config["x_lim"] is not None:
36
+ WidgetIO.check_and_adjust_limits(self.ui.x_min, axis_config["x_lim"][0])
37
+ WidgetIO.check_and_adjust_limits(self.ui.x_max, axis_config["x_lim"][1])
38
+ WidgetIO.set_value(self.ui.x_min, axis_config["x_lim"][0])
39
+ WidgetIO.set_value(self.ui.x_max, axis_config["x_lim"][1])
40
+
41
+ # Y Axis Box
42
+ WidgetIO.set_value(self.ui.y_label, axis_config["y_label"])
43
+ WidgetIO.set_value(self.ui.y_scale, axis_config["y_scale"])
44
+ WidgetIO.set_value(self.ui.y_grid, axis_config["y_grid"])
45
+ if axis_config["y_lim"] is not None:
46
+ WidgetIO.check_and_adjust_limits(self.ui.y_min, axis_config["y_lim"][0])
47
+ WidgetIO.check_and_adjust_limits(self.ui.y_max, axis_config["y_lim"][1])
48
+ WidgetIO.set_value(self.ui.y_min, axis_config["y_lim"][0])
49
+ WidgetIO.set_value(self.ui.y_max, axis_config["y_lim"][1])
50
+
51
+
52
+ if __name__ == "__main__":
53
+ import sys
54
+
55
+ from qtpy.QtWidgets import QApplication
56
+
57
+ app = QApplication(sys.argv)
58
+ qdarktheme.setup_theme("dark")
59
+ window = AxisSettings()
60
+ window.show()
61
+ sys.exit(app.exec_())
@@ -0,0 +1,249 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ui version="4.0">
3
+ <class>Form</class>
4
+ <widget class="QWidget" name="Form">
5
+ <property name="geometry">
6
+ <rect>
7
+ <x>0</x>
8
+ <y>0</y>
9
+ <width>417</width>
10
+ <height>250</height>
11
+ </rect>
12
+ </property>
13
+ <property name="minimumSize">
14
+ <size>
15
+ <width>0</width>
16
+ <height>250</height>
17
+ </size>
18
+ </property>
19
+ <property name="maximumSize">
20
+ <size>
21
+ <width>16777215</width>
22
+ <height>278</height>
23
+ </size>
24
+ </property>
25
+ <property name="windowTitle">
26
+ <string>Form</string>
27
+ </property>
28
+ <layout class="QGridLayout" name="gridLayout">
29
+ <item row="0" column="0" colspan="3">
30
+ <layout class="QHBoxLayout" name="horizontalLayout">
31
+ <item>
32
+ <widget class="QLabel" name="plot_title_label">
33
+ <property name="text">
34
+ <string>Plot Title</string>
35
+ </property>
36
+ </widget>
37
+ </item>
38
+ <item>
39
+ <widget class="QLineEdit" name="plot_title"/>
40
+ </item>
41
+ </layout>
42
+ </item>
43
+ <item row="1" column="0" colspan="3">
44
+ <widget class="Line" name="line_H">
45
+ <property name="orientation">
46
+ <enum>Qt::Orientation::Horizontal</enum>
47
+ </property>
48
+ </widget>
49
+ </item>
50
+ <item row="2" column="0">
51
+ <widget class="QGroupBox" name="x_axis_box">
52
+ <property name="title">
53
+ <string>X Axis</string>
54
+ </property>
55
+ <layout class="QGridLayout" name="gridLayout_4">
56
+ <item row="3" column="0">
57
+ <widget class="QLabel" name="x_scale_label">
58
+ <property name="text">
59
+ <string>Scale</string>
60
+ </property>
61
+ </widget>
62
+ </item>
63
+ <item row="1" column="2">
64
+ <widget class="QDoubleSpinBox" name="x_min">
65
+ <property name="alignment">
66
+ <set>Qt::AlignmentFlag::AlignCenter</set>
67
+ </property>
68
+ <property name="minimum">
69
+ <double>-9999.000000000000000</double>
70
+ </property>
71
+ <property name="maximum">
72
+ <double>9999.000000000000000</double>
73
+ </property>
74
+ </widget>
75
+ </item>
76
+ <item row="1" column="0" colspan="2">
77
+ <widget class="QLabel" name="x_min_label">
78
+ <property name="text">
79
+ <string>Min</string>
80
+ </property>
81
+ </widget>
82
+ </item>
83
+ <item row="2" column="2">
84
+ <widget class="QDoubleSpinBox" name="x_max">
85
+ <property name="alignment">
86
+ <set>Qt::AlignmentFlag::AlignCenter</set>
87
+ </property>
88
+ <property name="minimum">
89
+ <double>-9999.000000000000000</double>
90
+ </property>
91
+ <property name="maximum">
92
+ <double>9999.000000000000000</double>
93
+ </property>
94
+ </widget>
95
+ </item>
96
+ <item row="3" column="2">
97
+ <widget class="QComboBox" name="x_scale">
98
+ <item>
99
+ <property name="text">
100
+ <string>linear</string>
101
+ </property>
102
+ </item>
103
+ <item>
104
+ <property name="text">
105
+ <string>log</string>
106
+ </property>
107
+ </item>
108
+ </widget>
109
+ </item>
110
+ <item row="2" column="0">
111
+ <widget class="QLabel" name="x_max_label">
112
+ <property name="text">
113
+ <string>Max</string>
114
+ </property>
115
+ </widget>
116
+ </item>
117
+ <item row="0" column="2">
118
+ <widget class="QLineEdit" name="x_label"/>
119
+ </item>
120
+ <item row="0" column="0">
121
+ <widget class="QLabel" name="x_label_label">
122
+ <property name="text">
123
+ <string>Label</string>
124
+ </property>
125
+ </widget>
126
+ </item>
127
+ <item row="4" column="2">
128
+ <widget class="QCheckBox" name="x_grid">
129
+ <property name="text">
130
+ <string/>
131
+ </property>
132
+ </widget>
133
+ </item>
134
+ <item row="4" column="0">
135
+ <widget class="QLabel" name="x_grid_label">
136
+ <property name="text">
137
+ <string>Grid</string>
138
+ </property>
139
+ </widget>
140
+ </item>
141
+ </layout>
142
+ </widget>
143
+ </item>
144
+ <item row="2" column="1">
145
+ <widget class="Line" name="line_V">
146
+ <property name="orientation">
147
+ <enum>Qt::Orientation::Vertical</enum>
148
+ </property>
149
+ </widget>
150
+ </item>
151
+ <item row="2" column="2">
152
+ <widget class="QGroupBox" name="y_axis_box">
153
+ <property name="title">
154
+ <string>Y Axis</string>
155
+ </property>
156
+ <layout class="QGridLayout" name="gridLayout_5">
157
+ <item row="3" column="2">
158
+ <widget class="QComboBox" name="y_scale">
159
+ <item>
160
+ <property name="text">
161
+ <string>linear</string>
162
+ </property>
163
+ </item>
164
+ <item>
165
+ <property name="text">
166
+ <string>log</string>
167
+ </property>
168
+ </item>
169
+ </widget>
170
+ </item>
171
+ <item row="2" column="2">
172
+ <widget class="QDoubleSpinBox" name="y_max">
173
+ <property name="alignment">
174
+ <set>Qt::AlignmentFlag::AlignCenter</set>
175
+ </property>
176
+ <property name="minimum">
177
+ <double>-9999.000000000000000</double>
178
+ </property>
179
+ <property name="maximum">
180
+ <double>9999.000000000000000</double>
181
+ </property>
182
+ </widget>
183
+ </item>
184
+ <item row="1" column="0" colspan="2">
185
+ <widget class="QLabel" name="y_min_label">
186
+ <property name="text">
187
+ <string>Min</string>
188
+ </property>
189
+ </widget>
190
+ </item>
191
+ <item row="1" column="2">
192
+ <widget class="QDoubleSpinBox" name="y_min">
193
+ <property name="alignment">
194
+ <set>Qt::AlignmentFlag::AlignCenter</set>
195
+ </property>
196
+ <property name="minimum">
197
+ <double>-9999.000000000000000</double>
198
+ </property>
199
+ <property name="maximum">
200
+ <double>9999.000000000000000</double>
201
+ </property>
202
+ </widget>
203
+ </item>
204
+ <item row="0" column="2">
205
+ <widget class="QLineEdit" name="y_label"/>
206
+ </item>
207
+ <item row="3" column="0">
208
+ <widget class="QLabel" name="y_scale_label">
209
+ <property name="text">
210
+ <string>Scale</string>
211
+ </property>
212
+ </widget>
213
+ </item>
214
+ <item row="0" column="0">
215
+ <widget class="QLabel" name="y_label_label">
216
+ <property name="text">
217
+ <string>Label</string>
218
+ </property>
219
+ </widget>
220
+ </item>
221
+ <item row="2" column="0">
222
+ <widget class="QLabel" name="y_max_label">
223
+ <property name="text">
224
+ <string>Max</string>
225
+ </property>
226
+ </widget>
227
+ </item>
228
+ <item row="4" column="2">
229
+ <widget class="QCheckBox" name="y_grid">
230
+ <property name="text">
231
+ <string/>
232
+ </property>
233
+ </widget>
234
+ </item>
235
+ <item row="4" column="0">
236
+ <widget class="QLabel" name="y_grid_label">
237
+ <property name="text">
238
+ <string>Grid</string>
239
+ </property>
240
+ </widget>
241
+ </item>
242
+ </layout>
243
+ </widget>
244
+ </item>
245
+ </layout>
246
+ </widget>
247
+ <resources/>
248
+ <connections/>
249
+ </ui>
@@ -10,7 +10,7 @@ from pydantic import Field, ValidationError, field_validator
10
10
  from pydantic_core import PydanticCustomError
11
11
  from qtpy import QtCore, QtGui
12
12
  from qtpy.QtCore import Signal as pyqtSignal
13
- from qtpy.QtCore import Slot as pyqtSlot
13
+ from qtpy.QtCore import Slot
14
14
  from qtpy.QtWidgets import QWidget
15
15
 
16
16
  from bec_widgets.utils import Colors, EntryValidator
@@ -24,7 +24,7 @@ class MotorMapConfig(SubplotConfig):
24
24
  (255, 255, 255, 255), description="The color of the last point of current position."
25
25
  )
26
26
  scatter_size: Optional[int] = Field(5, description="Size of the scatter points.")
27
- max_points: Optional[int] = Field(1000, description="Maximum number of points to display.")
27
+ max_points: Optional[int] = Field(5000, description="Maximum number of points to display.")
28
28
  num_dim_points: Optional[int] = Field(
29
29
  100,
30
30
  description="Number of points to dim before the color remains same for older recorded position.",
@@ -59,6 +59,7 @@ class BECMotorMap(BECPlotBase):
59
59
  "set_scatter_size",
60
60
  "get_data",
61
61
  "remove",
62
+ "reset_history",
62
63
  ]
63
64
 
64
65
  # QT Signals
@@ -120,7 +121,7 @@ class BECMotorMap(BECPlotBase):
120
121
  motor_y_entry=self.config.signals.y.entry,
121
122
  )
122
123
 
123
- @pyqtSlot(str, str, str, str, bool)
124
+ @Slot(str, str, str, str, bool)
124
125
  def change_motors(
125
126
  self,
126
127
  motor_x: str,
@@ -139,6 +140,8 @@ class BECMotorMap(BECPlotBase):
139
140
  motor_y_entry(str): Motor entry for the Y axis.
140
141
  validate_bec(bool, optional): If True, validate the signal with BEC. Defaults to True.
141
142
  """
143
+ self.plot_item.clear()
144
+
142
145
  motor_x_entry, motor_y_entry = self._validate_signal_entries(
143
146
  motor_x, motor_y, motor_x_entry, motor_y_entry, validate_bec
144
147
  )
@@ -164,13 +167,22 @@ class BECMotorMap(BECPlotBase):
164
167
  def get_data(self) -> dict:
165
168
  """
166
169
  Get the data of the motor map.
170
+
167
171
  Returns:
168
172
  dict: Data of the motor map.
169
173
  """
170
174
  data = {"x": self.database_buffer["x"], "y": self.database_buffer["y"]}
171
175
  return data
172
176
 
173
- def set_color(self, color: [str | tuple]):
177
+ def reset_history(self):
178
+ """
179
+ Reset the history of the motor map.
180
+ """
181
+ self.database_buffer["x"] = [self.database_buffer["x"][-1]]
182
+ self.database_buffer["y"] = [self.database_buffer["y"][-1]]
183
+ self.update_signal.emit()
184
+
185
+ def set_color(self, color: str | tuple):
174
186
  """
175
187
  Set color of the motor trace.
176
188
 
@@ -428,6 +440,7 @@ class BECMotorMap(BECPlotBase):
428
440
  print(f"The device '{motor}' does not have defined limits.")
429
441
  return None
430
442
 
443
+ @Slot()
431
444
  def _update_plot(self):
432
445
  """Update the motor map plot."""
433
446
  # If the number of points exceeds max_points, delete the oldest points
@@ -477,7 +490,7 @@ class BECMotorMap(BECPlotBase):
477
490
  f"Motor position: ({round(float(current_x),precision)}, {round(float(current_y),precision)})"
478
491
  )
479
492
 
480
- @pyqtSlot(dict)
493
+ @Slot(dict)
481
494
  def on_device_readback(self, msg: dict) -> None:
482
495
  """
483
496
  Update the motor map plot with the new motor position.