bec-widgets 0.53.2__py3-none-any.whl → 0.54.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 (67) hide show
  1. CHANGELOG.md +24 -25
  2. PKG-INFO +1 -1
  3. bec_widgets/cli/client.py +13 -13
  4. bec_widgets/cli/client_utils.py +0 -4
  5. bec_widgets/cli/generate_cli.py +7 -5
  6. bec_widgets/cli/server.py +5 -7
  7. bec_widgets/examples/jupyter_console/jupyter_console_window.py +7 -3
  8. bec_widgets/examples/motor_movement/motor_control_compilations.py +17 -16
  9. bec_widgets/widgets/__init__.py +0 -10
  10. bec_widgets/widgets/figure/figure.py +40 -23
  11. bec_widgets/widgets/figure/plots/__init__.py +0 -0
  12. bec_widgets/widgets/figure/plots/image/__init__.py +0 -0
  13. bec_widgets/widgets/{plots → figure/plots/image}/image.py +6 -416
  14. bec_widgets/widgets/figure/plots/image/image_item.py +277 -0
  15. bec_widgets/widgets/figure/plots/image/image_processor.py +152 -0
  16. bec_widgets/widgets/figure/plots/motor_map/__init__.py +0 -0
  17. bec_widgets/widgets/{plots → figure/plots/motor_map}/motor_map.py +2 -2
  18. bec_widgets/widgets/figure/plots/waveform/__init__.py +0 -0
  19. bec_widgets/widgets/{plots → figure/plots/waveform}/waveform.py +9 -222
  20. bec_widgets/widgets/figure/plots/waveform/waveform_curve.py +227 -0
  21. bec_widgets/widgets/motor_control/__init__.py +0 -7
  22. bec_widgets/widgets/motor_control/motor_control.py +2 -948
  23. bec_widgets/widgets/motor_control/motor_table/__init__.py +0 -0
  24. bec_widgets/widgets/motor_control/motor_table/motor_table.py +483 -0
  25. bec_widgets/widgets/motor_control/movement_absolute/__init__.py +0 -0
  26. bec_widgets/widgets/motor_control/movement_absolute/movement_absolute.py +157 -0
  27. bec_widgets/widgets/motor_control/movement_relative/__init__.py +0 -0
  28. bec_widgets/widgets/motor_control/movement_relative/movement_relative.py +227 -0
  29. bec_widgets/widgets/motor_control/selection/__init__.py +0 -0
  30. bec_widgets/widgets/motor_control/selection/selection.py +110 -0
  31. {bec_widgets-0.53.2.dist-info → bec_widgets-0.54.0.dist-info}/METADATA +1 -1
  32. {bec_widgets-0.53.2.dist-info → bec_widgets-0.54.0.dist-info}/RECORD +51 -52
  33. docs/requirements.txt +1 -0
  34. pyproject.toml +1 -1
  35. tests/end-2-end/test_bec_dock_rpc_e2e.py +1 -1
  36. tests/end-2-end/test_bec_figure_rpc_e2e.py +4 -4
  37. tests/end-2-end/test_rpc_register_e2e.py +1 -1
  38. tests/unit_tests/test_bec_dock.py +1 -1
  39. tests/unit_tests/test_bec_figure.py +6 -4
  40. tests/unit_tests/test_bec_motor_map.py +2 -3
  41. tests/unit_tests/test_motor_control.py +6 -5
  42. tests/unit_tests/test_waveform1d.py +13 -1
  43. bec_widgets/validation/__init__.py +0 -2
  44. bec_widgets/validation/monitor_config_validator.py +0 -258
  45. bec_widgets/widgets/monitor/__init__.py +0 -1
  46. bec_widgets/widgets/monitor/config_dialog.py +0 -574
  47. bec_widgets/widgets/monitor/config_dialog.ui +0 -210
  48. bec_widgets/widgets/monitor/example_configs/config_device.yaml +0 -60
  49. bec_widgets/widgets/monitor/example_configs/config_scans.yaml +0 -92
  50. bec_widgets/widgets/monitor/monitor.py +0 -845
  51. bec_widgets/widgets/monitor/tab_template.ui +0 -180
  52. bec_widgets/widgets/motor_map/__init__.py +0 -1
  53. bec_widgets/widgets/motor_map/motor_map.py +0 -594
  54. bec_widgets/widgets/plots/__init__.py +0 -4
  55. tests/unit_tests/test_bec_monitor.py +0 -220
  56. tests/unit_tests/test_config_dialog.py +0 -178
  57. tests/unit_tests/test_motor_map.py +0 -171
  58. tests/unit_tests/test_validator_errors.py +0 -110
  59. /bec_widgets/{cli → assets}/bec_widgets_icon.png +0 -0
  60. /bec_widgets/{examples/jupyter_console → assets}/terminal_icon.png +0 -0
  61. /bec_widgets/widgets/{plots → figure/plots}/plot_base.py +0 -0
  62. /bec_widgets/widgets/motor_control/{motor_control_table.ui → motor_table/motor_table.ui} +0 -0
  63. /bec_widgets/widgets/motor_control/{motor_control_absolute.ui → movement_absolute/movement_absolute.ui} +0 -0
  64. /bec_widgets/widgets/motor_control/{motor_control_relative.ui → movement_relative/movement_relative.ui} +0 -0
  65. /bec_widgets/widgets/motor_control/{motor_control_selection.ui → selection/selection.ui} +0 -0
  66. {bec_widgets-0.53.2.dist-info → bec_widgets-0.54.0.dist-info}/WHEEL +0 -0
  67. {bec_widgets-0.53.2.dist-info → bec_widgets-0.54.0.dist-info}/licenses/LICENSE +0 -0
@@ -11,14 +11,15 @@ from bec_widgets.examples import (
11
11
  MotorControlPanelAbsolute,
12
12
  MotorControlPanelRelative,
13
13
  )
14
- from bec_widgets.widgets import (
14
+ from bec_widgets.widgets.motor_control.motor_control import MotorActions, MotorThread
15
+ from bec_widgets.widgets.motor_control.motor_table.motor_table import MotorCoordinateTable
16
+ from bec_widgets.widgets.motor_control.movement_absolute.movement_absolute import (
15
17
  MotorControlAbsolute,
18
+ )
19
+ from bec_widgets.widgets.motor_control.movement_relative.movement_relative import (
16
20
  MotorControlRelative,
17
- MotorControlSelection,
18
- MotorCoordinateTable,
19
- MotorThread,
20
21
  )
21
- from bec_widgets.widgets.motor_control.motor_control import MotorActions
22
+ from bec_widgets.widgets.motor_control.selection.selection import MotorControlSelection
22
23
 
23
24
  from .client_mocks import mocked_client
24
25
 
@@ -4,7 +4,7 @@ from unittest.mock import MagicMock
4
4
  import numpy as np
5
5
  import pytest
6
6
 
7
- from bec_widgets.widgets.plots.waveform import CurveConfig, Signal, SignalData
7
+ from bec_widgets.widgets.figure.plots.waveform.waveform_curve import CurveConfig, Signal, SignalData
8
8
 
9
9
  from .client_mocks import mocked_client
10
10
  from .test_bec_figure import bec_figure
@@ -304,6 +304,18 @@ def test_set_custom_curve_data(bec_figure, qtbot):
304
304
  assert np.array_equal(y_new, [7, 8, 9])
305
305
 
306
306
 
307
+ def test_custom_data_2D_array(bec_figure, qtbot):
308
+
309
+ data = np.random.rand(10, 2)
310
+
311
+ plt = bec_figure.plot(data)
312
+
313
+ x, y = plt.curves[0].get_data()
314
+
315
+ assert np.array_equal(x, data[:, 0])
316
+ assert np.array_equal(y, data[:, 1])
317
+
318
+
307
319
  def test_get_all_data(bec_figure):
308
320
  w1 = bec_figure.add_plot()
309
321
 
@@ -1,2 +0,0 @@
1
- # from .monitor_config import validate_monitor_config, ValidationError
2
- from .monitor_config_validator import MonitorConfigValidator
@@ -1,258 +0,0 @@
1
- from typing import Literal, Optional, Union
2
-
3
- from pydantic import BaseModel, Field, ValidationError, field_validator, model_validator
4
- from pydantic_core import PydanticCustomError
5
-
6
-
7
- class Signal(BaseModel):
8
- """
9
- Represents a signal in a plot configuration.
10
-
11
- Args:
12
- name (str): The name of the signal.
13
- entry (Optional[str]): The entry point of the signal, optional.
14
- """
15
-
16
- name: str
17
- entry: Optional[str] = Field(None, validate_default=True)
18
-
19
- @model_validator(mode="before")
20
- @classmethod
21
- def validate_fields(cls, values):
22
- """Validate the fields of the model.
23
- First validate the 'name' field, then validate the 'entry' field.
24
-
25
- Args:
26
- values (dict): The values to be validated."""
27
- devices = MonitorConfigValidator.devices
28
-
29
- # Validate 'name'
30
- name = values.get("name")
31
-
32
- # Check if device name provided
33
- if name is None:
34
- raise PydanticCustomError(
35
- "no_device_name", "Device name must be provided", {"wrong_value": name}
36
- )
37
- # Check if device exists in BEC
38
- if name not in devices:
39
- raise PydanticCustomError(
40
- "no_device_bec",
41
- 'Device "{wrong_value}" not found in current BEC session',
42
- {"wrong_value": name},
43
- )
44
-
45
- device = devices[name] # get the device to check if it has signals
46
-
47
- # Get device description
48
- description = device.describe()
49
-
50
- # Validate 'entry'
51
- entry = values.get("entry")
52
-
53
- # Set entry based on hints if not provided
54
- if entry is None:
55
- entry = next(iter(device._hints), name) if hasattr(device, "_hints") else name
56
- if entry not in description:
57
- raise PydanticCustomError(
58
- "no_entry_for_device",
59
- 'Entry "{wrong_value}" not found in device "{device_name}" signals',
60
- {"wrong_value": entry, "device_name": name},
61
- )
62
-
63
- values["entry"] = entry
64
- return values
65
-
66
-
67
- class AxisSignal(BaseModel):
68
- """
69
- Configuration signal axis for a single plot.
70
- Attributes:
71
- x (list): Signal for the X axis.
72
- y (list): Signals for the Y axis.
73
- """
74
-
75
- x: list[Signal] = Field(default_factory=list)
76
- y: list[Signal] = Field(default_factory=list)
77
-
78
- @field_validator("x")
79
- @classmethod
80
- def validate_x_signals(cls, v):
81
- """Ensure that there is only one signal for x-axis."""
82
- if len(v) != 1:
83
- raise PydanticCustomError(
84
- "x_axis_multiple_signals",
85
- 'There must be exactly one signal for x axis. Number of x signals: "{wrong_value}"',
86
- {"wrong_value": v},
87
- )
88
-
89
- return v
90
-
91
-
92
- class SourceHistoryValidator(BaseModel):
93
- """History source validator
94
- Attributes:
95
- type (str): type of source - history
96
- scan_id (str): Scan ID for history source.
97
- signals (list): Signal for the source.
98
- """
99
-
100
- type: Literal["history"]
101
- scan_id: str # TODO can be validated if it is a valid scan_id
102
- signals: AxisSignal
103
-
104
-
105
- class SourceSegmentValidator(BaseModel):
106
- """Scan Segment source validator
107
- Attributes:
108
- type (str): type of source - scan_segment
109
- signals (AxisSignal): Signal for the source.
110
- """
111
-
112
- type: Literal["scan_segment"]
113
- signals: AxisSignal
114
-
115
-
116
- class SourceRedisValidator(BaseModel):
117
- """Scan Segment source validator
118
- Attributes:
119
- type (str): type of source - scan_segment
120
- endpoint (str): Endpoint reference in redis.
121
- update (str): Update type.
122
- """
123
-
124
- type: Literal["redis"]
125
- endpoint: str
126
- update: str
127
- signals: dict
128
-
129
-
130
- class Source(BaseModel): # TODO decide if it should stay for general Source validation
131
- """
132
- General source validation, includes all Optional arguments of all other sources.
133
- Attributes:
134
- type (list): type of source (scan_segment, history)
135
- scan_id (Optional[str]): Scan ID for history source.
136
- signals (Optional[AxisSignal]): Signal for the source.
137
- """
138
-
139
- type: Literal["scan_segment", "history", "redis"]
140
- scan_id: Optional[str] = None
141
- signals: Optional[dict] = None
142
-
143
-
144
- class PlotConfig(BaseModel):
145
- """
146
- Configuration for a single plot.
147
-
148
- Attributes:
149
- plot_name (Optional[str]): Name of the plot.
150
- x_label (Optional[str]): The label for the x-axis.
151
- y_label (Optional[str]): The label for the y-axis.
152
- sources (list): A list of sources to be plotted on this axis.
153
- """
154
-
155
- plot_name: Optional[str] = None
156
- x_label: Optional[str] = None
157
- y_label: Optional[str] = None
158
- sources: list = Field(default_factory=list)
159
-
160
- @field_validator("sources")
161
- @classmethod
162
- def validate_sources(cls, values):
163
- """Validate the sources of the plot configuration, based on the type of source."""
164
- validated_sources = []
165
- for source in values:
166
- # Check if source type is supported
167
- Source(**source)
168
- source_type = source.get("type", None)
169
-
170
- # Validate source based on type
171
- if source_type == "scan_segment":
172
- validated_sources.append(SourceSegmentValidator(**source))
173
- elif source_type == "history":
174
- validated_sources.append(SourceHistoryValidator(**source))
175
- elif source_type == "redis":
176
- validated_sources.append(SourceRedisValidator(**source))
177
- return validated_sources
178
-
179
-
180
- class PlotSettings(BaseModel):
181
- """
182
- Global settings for plotting affecting mostly visuals.
183
-
184
- Attributes:
185
- background_color (str): Color of the plot background. Default is black.
186
- axis_width (Optional[int]): Width of the plot axes. Default is 2.
187
- axis_color (Optional[str]): Color of the plot axes. Default is None.
188
- num_columns (int): Number of columns in the plot layout. Default is 1.
189
- colormap (str): Colormap to be used. Default is magma.
190
- scan_types (bool): Indicates if the configuration is for different scan types. Default is False.
191
- """
192
-
193
- background_color: Literal["black", "white"] = "black"
194
- axis_width: Optional[int] = 2
195
- axis_color: Optional[str] = None
196
- num_columns: Optional[int] = 1
197
- colormap: Optional[str] = "magma"
198
- scan_types: Optional[bool] = False
199
-
200
-
201
- class DeviceMonitorConfig(BaseModel):
202
- """
203
- Configuration model for the device monitor mode.
204
-
205
- Attributes:
206
- plot_settings (PlotSettings): Global settings for plotting.
207
- plot_data (list[PlotConfig]): List of plot configurations.
208
- """
209
-
210
- plot_settings: PlotSettings
211
- plot_data: list[PlotConfig]
212
-
213
-
214
- class ScanModeConfig(BaseModel):
215
- """
216
- Configuration model for scan mode.
217
-
218
- Attributes:
219
- plot_settings (PlotSettings): Global settings for plotting.
220
- plot_data (dict[str, list[PlotConfig]]): Dictionary of plot configurations,
221
- keyed by scan type.
222
- """
223
-
224
- plot_settings: PlotSettings
225
- plot_data: dict[str, list[PlotConfig]]
226
-
227
-
228
- class MonitorConfigValidator:
229
- """Validates the configuration data for the BECMonitor."""
230
-
231
- devices = None
232
-
233
- def __init__(self, devices):
234
- # self.device_manager = device_manager
235
- MonitorConfigValidator.devices = devices
236
-
237
- def validate_monitor_config(
238
- self, config_data: dict
239
- ) -> Union[DeviceMonitorConfig, ScanModeConfig]:
240
- """
241
- Validates the configuration data based on the provided schema.
242
-
243
- Args:
244
- config_data (dict): Configuration data to be validated.
245
-
246
- Returns:
247
- Union[DeviceMonitorConfig, ScanModeConfig]: Validated configuration object.
248
-
249
- Raises:
250
- ValidationError: If the configuration data does not conform to the schema.
251
- """
252
- config_type = config_data.get("plot_settings", {}).get("scan_types", False)
253
- if config_type:
254
- validated_config = ScanModeConfig(**config_data)
255
- else:
256
- validated_config = DeviceMonitorConfig(**config_data)
257
-
258
- return validated_config
@@ -1 +0,0 @@
1
- from .monitor import BECMonitor