bec-widgets 0.94.6__py3-none-any.whl → 0.95.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.
- CHANGELOG.md +36 -40
- PKG-INFO +1 -1
- bec_widgets/cli/client.py +19 -0
- bec_widgets/cli/client_utils.py +1 -0
- bec_widgets/cli/server.py +5 -5
- bec_widgets/widgets/device_browser/__init__.py +0 -0
- bec_widgets/widgets/device_browser/device_browser.py +107 -0
- bec_widgets/widgets/device_browser/device_browser.pyproject +1 -0
- bec_widgets/widgets/device_browser/device_browser.ui +44 -0
- bec_widgets/widgets/device_browser/device_browser_plugin.py +54 -0
- bec_widgets/widgets/device_browser/device_item/__init__.py +1 -0
- bec_widgets/widgets/device_browser/device_item/device_item.py +53 -0
- bec_widgets/widgets/device_browser/register_device_browser.py +15 -0
- {bec_widgets-0.94.6.dist-info → bec_widgets-0.95.0.dist-info}/METADATA +1 -1
- {bec_widgets-0.94.6.dist-info → bec_widgets-0.95.0.dist-info}/RECORD +75 -35
- docs/_static/custom.css +10 -10
- docs/assets/widget_screenshots/buttons.png +0 -0
- docs/assets/widget_screenshots/device_box.png +0 -0
- docs/assets/widget_screenshots/device_browser.png +0 -0
- docs/assets/widget_screenshots/device_inputs.png +0 -0
- docs/assets/widget_screenshots/dock_area.png +0 -0
- docs/assets/widget_screenshots/figure.png +0 -0
- docs/assets/widget_screenshots/image_widget.png +0 -0
- docs/assets/widget_screenshots/motor_map_widget.png +0 -0
- docs/assets/widget_screenshots/position_indicator.png +0 -0
- docs/assets/widget_screenshots/queue.png +0 -0
- docs/assets/widget_screenshots/ring_progress_bar.png +0 -0
- docs/assets/widget_screenshots/scan_controller.png +0 -0
- docs/assets/widget_screenshots/spinner.gif +0 -0
- docs/assets/widget_screenshots/status_box.png +0 -0
- docs/assets/widget_screenshots/text_box.png +0 -0
- docs/assets/widget_screenshots/toggle.png +0 -0
- docs/assets/widget_screenshots/waveform_widget.png +0 -0
- docs/assets/widget_screenshots/website.png +0 -0
- docs/conf.py +1 -0
- docs/developer/developer.md +2 -0
- docs/index.md +4 -0
- docs/requirements.txt +1 -0
- docs/user/user.md +4 -0
- docs/user/widgets/bec_figure/bec_figure.md +105 -0
- docs/user/widgets/bec_status_box/bec_status_box.md +38 -0
- docs/user/widgets/buttons/buttons.md +50 -0
- docs/user/widgets/device_browser/device_browser.md +36 -0
- docs/user/widgets/device_browser/device_browser.png +0 -0
- docs/user/widgets/device_input/device_input.md +100 -0
- docs/user/widgets/dock_area/BECDockArea.png +0 -0
- docs/user/widgets/dock_area/bec_dock_area.md +107 -0
- docs/user/widgets/image/image_widget.md +84 -0
- docs/user/widgets/motor_map/motor_map.md +80 -0
- docs/user/widgets/position_indicator/position_indicator.md +76 -0
- docs/user/widgets/positioner_box/positioner_box.md +63 -0
- docs/user/widgets/progress_bar/ring_progress_bar.md +103 -0
- docs/user/widgets/queue/queue.md +41 -0
- docs/user/widgets/scan_control/scan_control.md +46 -0
- docs/user/widgets/spinner/spinner.md +75 -0
- docs/user/widgets/text_box/text_box.md +74 -0
- docs/user/widgets/toggle/toggle.md +66 -0
- docs/user/widgets/waveform/waveform_widget.md +132 -0
- docs/user/widgets/website/website.md +69 -0
- docs/user/widgets/widgets.md +212 -12
- pyproject.toml +1 -1
- tests/unit_tests/client_mocks.py +14 -0
- tests/unit_tests/test_device_browser.py +83 -0
- docs/user/widgets/bec_figure.md +0 -146
- docs/user/widgets/bec_status_box.md +0 -30
- docs/user/widgets/buttons.md +0 -37
- docs/user/widgets/ring_progress_bar.md +0 -54
- docs/user/widgets/scan_control.md +0 -35
- docs/user/widgets/text_box.md +0 -33
- docs/user/widgets/website.md +0 -21
- {bec_widgets-0.94.6.dist-info → bec_widgets-0.95.0.dist-info}/WHEEL +0 -0
- {bec_widgets-0.94.6.dist-info → bec_widgets-0.95.0.dist-info}/entry_points.txt +0 -0
- {bec_widgets-0.94.6.dist-info → bec_widgets-0.95.0.dist-info}/licenses/LICENSE +0 -0
- /docs/user/widgets/{BECFigure.png → bec_figure/BECFigure.png} +0 -0
- /docs/user/widgets/{bec_status_box.gif → bec_status_box/bec_status_box.gif} +0 -0
- /docs/user/widgets/{image_plot.gif → image/image_plot.gif} +0 -0
- /docs/user/widgets/{motor.gif → motor_map/motor.gif} +0 -0
- /docs/user/widgets/{progress_bar.gif → progress_bar/progress_bar.gif} +0 -0
- /docs/user/widgets/{scan_control.gif → scan_control/scan_control.gif} +0 -0
- /docs/user/widgets/{bec_figure_dap.gif → waveform/bec_figure_dap.gif} +0 -0
- /docs/user/widgets/{scatter_2D.gif → waveform/scatter_2D.gif} +0 -0
- /docs/user/widgets/{w1D.gif → waveform/w1D.gif} +0 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
(user.widgets.toggle)=
|
2
|
+
|
3
|
+
# Toggle Switch Widget
|
4
|
+
|
5
|
+
````{tab} Overview
|
6
|
+
|
7
|
+
The [`Toggle Switch`](/api_reference/_autosummary/bec_widgets.cli.client.ToggleSwitch) widget provides a simple, customizable toggle switch that can be used to represent binary states (e.g., on/off, true/false) within a GUI. This widget is designed to be used directly in code or added through `QtDesigner`, making it versatile for various applications where a user-friendly switch is needed.
|
8
|
+
|
9
|
+
## Key Features:
|
10
|
+
- **Binary State Representation**: Represents a simple on/off state with a smooth toggle animation.
|
11
|
+
- **Customizable Appearance**: Allows customization of track and thumb colors for both active and inactive states.
|
12
|
+
- **Smooth Animation**: Includes a smooth animation when toggling between states, enhancing user interaction.
|
13
|
+
- **QtDesigner Integration**: Can be added directly through `QtDesigner` or instantiated in code.
|
14
|
+
|
15
|
+
````
|
16
|
+
|
17
|
+
````{tab} Examples
|
18
|
+
|
19
|
+
The `Toggle Switch` widget can be integrated within a GUI application either through direct code instantiation or by using `QtDesigner`. Below are examples demonstrating how to create and customize the `Toggle Switch` widget.
|
20
|
+
|
21
|
+
## Example 1 - Creating a Toggle Switch in Code
|
22
|
+
|
23
|
+
In this example, we demonstrate how to create a `ToggleSwitch` widget in code and customize its appearance.
|
24
|
+
|
25
|
+
```python
|
26
|
+
from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget
|
27
|
+
from bec_widgets.widgets.toggle_switch import ToggleSwitch
|
28
|
+
|
29
|
+
class MyGui(QWidget):
|
30
|
+
def __init__(self):
|
31
|
+
super().__init__()
|
32
|
+
self.setLayout(QVBoxLayout(self)) # Initialize the layout for the widget
|
33
|
+
|
34
|
+
# Create and add the ToggleSwitch to the layout
|
35
|
+
self.toggle_switch = ToggleSwitch()
|
36
|
+
self.layout().addWidget(self.toggle_switch)
|
37
|
+
|
38
|
+
# Example of how this custom GUI might be used:
|
39
|
+
app = QApplication([])
|
40
|
+
my_gui = MyGui()
|
41
|
+
my_gui.show()
|
42
|
+
app.exec_()
|
43
|
+
```
|
44
|
+
|
45
|
+
## Example 2 - Customizing the Toggle Switch Appearance
|
46
|
+
|
47
|
+
The `ToggleSwitch` widget allows you to customize its appearance by changing the track and thumb colors for both active and inactive states. Below is an example of how to set these properties.
|
48
|
+
|
49
|
+
```python
|
50
|
+
# Set the active and inactive track and thumb colors
|
51
|
+
self.toggle_switch.active_track_color = QColor(0, 122, 204) # Active state track color (blue)
|
52
|
+
self.toggle_switch.inactive_track_color = QColor(200, 200, 200) # Inactive state track color (grey)
|
53
|
+
self.toggle_switch.active_thumb_color = QColor(255, 255, 255) # Active state thumb color (white)
|
54
|
+
self.toggle_switch.inactive_thumb_color = QColor(255, 255, 255) # Inactive state thumb color (white)
|
55
|
+
```
|
56
|
+
|
57
|
+
## Example 3 - Integrating the Toggle Switch in QtDesigner
|
58
|
+
|
59
|
+
The `ToggleSwitch` can be added as a custom widget in `QtDesigner`. Once integrated, you can configure its properties through the designer's property editor. After adding the widget to a form in QtDesigner, you can manipulate it in your PyQt/PySide application:
|
60
|
+
|
61
|
+
```python
|
62
|
+
# For instance:
|
63
|
+
self.toggle_switch.setChecked(True)
|
64
|
+
```
|
65
|
+
|
66
|
+
````
|
@@ -0,0 +1,132 @@
|
|
1
|
+
(user.widgets.waveform_widget)=
|
2
|
+
|
3
|
+
# Waveform Widget
|
4
|
+
|
5
|
+
````{tab} Overview
|
6
|
+
|
7
|
+
The Waveform Widget is used to display 1D detector signals. The widget is directly integrated with the `BEC` framework and can display real-time data from detectors loaded in the current `BEC` session as well as custom data from users.
|
8
|
+
|
9
|
+
## Key Features:
|
10
|
+
- **Flexible Integration**: The widget can be integrated into both [`BECFigure`](user.widgets.bec_figure) and [`BECDockArea`](user.widgets.bec_dock_area), or used as an individual component in your application through `BECDesigner`.
|
11
|
+
- **Data Visualization**: Real-time plotting of positioner versus detector values from the BEC session, as well as static plotting of custom data.
|
12
|
+
- **Real-time Data Processing**: Add real-time Data Processing Pipeline (DAP) to the real-time acquisition.
|
13
|
+
- **Data Export**: Export data to CSV, H5, and other formats.
|
14
|
+
- **Customizable Visual Elements**: Customize visual elements such as line color and style.
|
15
|
+
- **Interactive Controls**: Interactive controls for zooming and panning through the data.
|
16
|
+
|
17
|
+

|
18
|
+
````
|
19
|
+
|
20
|
+
````{tab} Examples - CLI
|
21
|
+
|
22
|
+
`WaveformWidget` can be embedded in both `BECFigure` and `BECDockArea`, or used as an individual component in your application through `BECDesigner`. However, the command-line API is the same for all cases.
|
23
|
+
|
24
|
+
## Example 1 - Adding Waveform Widget to BECFigure
|
25
|
+
|
26
|
+
In this example, we will demonstrate how to add two different `WaveformWidgets` into a single `BECFigure` widget.
|
27
|
+
|
28
|
+
```python
|
29
|
+
# Add new dock with BECFigure widget
|
30
|
+
fig = gui.add_dock().add_widget('BECFigure')
|
31
|
+
|
32
|
+
# Add two WaveformWidgets to the BECFigure
|
33
|
+
plt1 = fig.plot(x_name='samx', y_name='bpm4i')
|
34
|
+
plt2 = fig.plot(x_name='samx', y_name='bpm3i')
|
35
|
+
```
|
36
|
+
|
37
|
+
## Example 2 - Adding Waveform Widget as a dock with BECDockArea
|
38
|
+
|
39
|
+
Adding `WaveformWidget` into a `BECDockArea` is similar to adding any other widget. The widget has the same API as the one in BECFigure; however, as an independent widget outside BECFigure, it has its own toolbar, allowing users to configure the widget without needing CLI commands.
|
40
|
+
|
41
|
+
```python
|
42
|
+
# Add new WaveformWidgets to the BECDockArea
|
43
|
+
plt1 = gui.add_dock().add_widget('BECWaveformWidget')
|
44
|
+
plt2 = gui.add_dock().add_widget('BECWaveformWidget')
|
45
|
+
|
46
|
+
# Add signals to the WaveformWidget
|
47
|
+
plt1.plot(x_name='samx', y_name='bpm4i')
|
48
|
+
plt2.plot(x_name='samx', y_name='bpm3i')
|
49
|
+
```
|
50
|
+
|
51
|
+
## Example 3 - Adding Waveform Widget with curves
|
52
|
+
```python
|
53
|
+
# adds a new dock, a new BECFigure and a BECWaveForm to the dock
|
54
|
+
plt = gui.add_dock().add_widget('BECFigure').plot(x_name='samx', y_name='bpm4i')
|
55
|
+
|
56
|
+
# add a second curve to the same plot
|
57
|
+
plt.plot(x_name='samx', y_name='bpm3i')
|
58
|
+
|
59
|
+
# set axis labels
|
60
|
+
plt.set_title("Gauss plots vs. samx")
|
61
|
+
plt.set_x_label("Motor X")
|
62
|
+
plt.set_y_label("Gauss Signal (A.U.")
|
63
|
+
```
|
64
|
+
|
65
|
+
```{note}
|
66
|
+
The return value of the simulated devices *bpm4i* and *bpm3i* may not be Gaussian signals, but they can be easily configured with the code snippet below. For more details, please check the documentation for the [simulation](https://bec.readthedocs.io/en/latest/developer/devices/bec_sim.html).
|
67
|
+
```
|
68
|
+
|
69
|
+
```python
|
70
|
+
# bpm4i uses GaussianModel and samx as a reference; default settings
|
71
|
+
dev.bpm4i.sim.select_sim_model("GaussianModel")
|
72
|
+
|
73
|
+
# bpm3i uses StepModel and samx as a reference; default settings
|
74
|
+
dev.bpm3i.sim.select_sim_model("StepModel")
|
75
|
+
```
|
76
|
+
## Example 4 - Adding Data Processing Pipeline Curve with LMFit Models
|
77
|
+
|
78
|
+
In addition to the scan curve, you can also add a second curve that fits the signal using a specified model from [LMFit](https://lmfit.github.io/lmfit-py/builtin_models.html). The following code snippet demonstrates how to create a 1D waveform curve with an attached DAP process, or how to add a DAP process to an existing curve using the BEC CLI. Please note that for this example, both devices were set as Gaussian signals.
|
79
|
+
|
80
|
+
```python
|
81
|
+
# Add a new dock, a new BECFigure, and a BECWaveForm to the dock with a GaussianModel DAP
|
82
|
+
plt = gui.add_dock().add_widget('BECFigure').plot(x_name='samx', y_name='bpm4i', dap="GaussianModel")
|
83
|
+
|
84
|
+
# Add a second curve to the same plot without DAP
|
85
|
+
plt.plot(x_name='samx', y_name='bpm3a')
|
86
|
+
|
87
|
+
# Add DAP to the second curve
|
88
|
+
plt.add_dap(x_name='samx', y_name='bpm3a', dap="GaussianModel")
|
89
|
+
|
90
|
+
```
|
91
|
+
|
92
|
+
To get the parameters of the fit, you need to retrieve the curve objects and call the `dap_params` property.
|
93
|
+
|
94
|
+
```python
|
95
|
+
# Get the curve object by name from the legend
|
96
|
+
dap_bpm4i = plt.get_curve("bpm4i-bpm4i-GaussianModel")
|
97
|
+
dap_bpm3a = plt.get_curve("bpm3a-bpm3a-GaussianModel")
|
98
|
+
|
99
|
+
# Get the parameters of the fit
|
100
|
+
print(dap_bpm4i.dap_params)
|
101
|
+
# Output
|
102
|
+
{'amplitude': 197.399639720862,
|
103
|
+
'center': 5.013486095404885,
|
104
|
+
'sigma': 0.9820868875739888}
|
105
|
+
|
106
|
+
print(dap_bpm3a.dap_params)
|
107
|
+
# Output
|
108
|
+
{'amplitude': 698.3072786185278,
|
109
|
+
'center': 0.9702840866173836,
|
110
|
+
'sigma': 1.97139754785518}
|
111
|
+
```
|
112
|
+
|
113
|
+

|
114
|
+
|
115
|
+
## Example 5 - 2D Waveform Scatter Plot
|
116
|
+
|
117
|
+
The 2D scatter plot widget is designed for more complex data visualization. It employs a false color map to represent a third dimension (z-axis), making it an ideal tool for visualizing multidimensional data sets.
|
118
|
+
|
119
|
+
```python
|
120
|
+
# adds a new dock, a new BECFigure and a BECWaveForm to the dock
|
121
|
+
plt = gui.add_dock().add_widget('BECFigure').add_plot(x_name='samx', y_name='samy', z_name='bpm4i')
|
122
|
+
```
|
123
|
+
|
124
|
+

|
125
|
+
|
126
|
+
````
|
127
|
+
|
128
|
+
````{tab} API
|
129
|
+
```{eval-rst}
|
130
|
+
.. include:: /api_reference/_autosummary/bec_widgets.cli.client.BECWaveform.rst
|
131
|
+
```
|
132
|
+
````
|
@@ -0,0 +1,69 @@
|
|
1
|
+
(user.widgets.website)=
|
2
|
+
|
3
|
+
# Website Widget
|
4
|
+
|
5
|
+
````{tab} Overview
|
6
|
+
|
7
|
+
The [`Website Widget`](/api_reference/_autosummary/bec_widgets.cli.client.WebsiteWidget) is a versatile tool that allows users to display websites directly within the BEC GUI. This widget is useful for embedding documentation, dashboards, or any web-based tools within the application interface. It is designed to be integrated within a [`BECDockArea`](user.widgets.bec_dock_area) or used as an individual component in your application through `QtDesigner`.
|
8
|
+
|
9
|
+
## Key Features:
|
10
|
+
- **URL Display**: Set and display any website URL within the widget.
|
11
|
+
- **Navigation Controls**: Navigate through the website’s history with back and forward controls.
|
12
|
+
- **Reload Functionality**: Reload the currently displayed website to ensure up-to-date content.
|
13
|
+
|
14
|
+
````
|
15
|
+
|
16
|
+
````{tab} Examples - CLI
|
17
|
+
|
18
|
+
The `WebsiteWidget` can be embedded within a [`BECDockArea`](user.widgets.bec_dock_area) or used as an individual component in your application through `QtDesigner`. The following examples demonstrate how to create and use the `WebsiteWidget` in different scenarios.
|
19
|
+
|
20
|
+
## Example 1 - Adding Website Widget to BECDockArea
|
21
|
+
|
22
|
+
In this example, we demonstrate how to add a `WebsiteWidget` to a `BECDockArea` and set the URL of the website to be displayed.
|
23
|
+
|
24
|
+
```python
|
25
|
+
# Add a new dock with a WebsiteWidget
|
26
|
+
web = gui.add_dock().add_widget("WebsiteWidget")
|
27
|
+
|
28
|
+
# Set the URL of the website to display
|
29
|
+
web.set_url("https://bec.readthedocs.io/en/latest/")
|
30
|
+
```
|
31
|
+
|
32
|
+
## Example 2 - Navigating within the Website Widget
|
33
|
+
|
34
|
+
The `WebsiteWidget` allows users to navigate back and forward through the website’s history. This example shows how to implement these navigation controls.
|
35
|
+
|
36
|
+
```python
|
37
|
+
# Go back in the website history
|
38
|
+
web.back()
|
39
|
+
|
40
|
+
# Go forward in the website history
|
41
|
+
web.forward()
|
42
|
+
```
|
43
|
+
|
44
|
+
## Example 3 - Reloading the Website
|
45
|
+
|
46
|
+
To ensure that the displayed website content is up-to-date, you can use the reload functionality.
|
47
|
+
|
48
|
+
```python
|
49
|
+
# Reload the current website
|
50
|
+
web.reload()
|
51
|
+
```
|
52
|
+
|
53
|
+
## Example 4 - Retrieving the Current URL
|
54
|
+
|
55
|
+
You may want to retrieve the current URL being displayed in the `WebsiteWidget`. The following example demonstrates how to access the current URL.
|
56
|
+
|
57
|
+
```python
|
58
|
+
# Get the current URL of the WebsiteWidget
|
59
|
+
current_url = web.get_url()
|
60
|
+
print(f"The current URL is: {current_url}")
|
61
|
+
```
|
62
|
+
|
63
|
+
````
|
64
|
+
|
65
|
+
````{tab} API
|
66
|
+
```{eval-rst}
|
67
|
+
.. include:: /api_reference/_autosummary/bec_widgets.cli.client.WebsiteWidget.rst
|
68
|
+
```
|
69
|
+
````
|
docs/user/widgets/widgets.md
CHANGED
@@ -1,20 +1,220 @@
|
|
1
1
|
(user.widgets)=
|
2
2
|
# Widgets
|
3
|
-
BEC Widgets includes a variety of visualization widgets designed to cater to diverse data representation needs in beamline experiments. These widgets enhance the user experience by providing intuitive and interactive data visualizations.
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
BEC Widgets offers a range of tools designed to make data visualization in beamline experiments easier and more
|
5
|
+
interactive. These widgets help users better understand their data by providing clear, intuitive displays that enhance
|
6
|
+
the overall experience.
|
7
|
+
|
8
|
+
## Widget Containers
|
9
|
+
|
10
|
+
Serves as containers to organise and display other widgets.
|
11
|
+
|
12
|
+
````{grid} 3
|
13
|
+
:gutter: 2
|
14
|
+
|
15
|
+
```{grid-item-card} BEC Dock Area
|
16
|
+
:link: user.widgets.bec_dock_area
|
17
|
+
:link-type: ref
|
18
|
+
:img-top: /assets/widget_screenshots/dock_area.png
|
19
|
+
|
20
|
+
Quickly build dynamic GUI.
|
21
|
+
|
22
|
+
```
|
23
|
+
|
24
|
+
```{grid-item-card} BEC Figure
|
25
|
+
:link: user.widgets.bec_figure
|
26
|
+
:link-type: ref
|
27
|
+
:img-top: /assets/widget_screenshots/figure.png
|
28
|
+
|
29
|
+
Display 1D and 2D data.
|
30
|
+
```
|
31
|
+
````
|
32
|
+
|
33
|
+
## Plotting Widgets
|
34
|
+
|
35
|
+
Plotting widgets are used to display data in a graphical format.
|
36
|
+
|
37
|
+
````{grid} 3
|
38
|
+
:gutter: 2
|
39
|
+
|
40
|
+
```{grid-item-card} Waveform Widget
|
41
|
+
:link: user.widgets.waveform_widget
|
42
|
+
:link-type: ref
|
43
|
+
:img-top: /assets/widget_screenshots/waveform_widget.png
|
44
|
+
|
45
|
+
Display 1D detector signals.
|
46
|
+
```
|
47
|
+
|
48
|
+
```{grid-item-card} Image Widget
|
49
|
+
:link: user.widgets.image_widget
|
50
|
+
:link-type: ref
|
51
|
+
:img-top: /assets/widget_screenshots/image_widget.png
|
52
|
+
|
53
|
+
Display signal from 2D detector.
|
54
|
+
```
|
55
|
+
|
56
|
+
```{grid-item-card} Motor Map Widget
|
57
|
+
:link: user.widgets.motor_map
|
58
|
+
:link-type: ref
|
59
|
+
:img-top: /assets/widget_screenshots/motor_map_widget.png
|
60
|
+
|
61
|
+
Track position for motors.
|
62
|
+
```
|
63
|
+
|
64
|
+
````
|
65
|
+
|
66
|
+
## Device Control Widgets
|
67
|
+
|
68
|
+
Control and monitor devices/scan in the BEC environment.
|
69
|
+
|
70
|
+
````{grid} 3
|
71
|
+
:gutter: 2
|
72
|
+
|
73
|
+
```{grid-item-card} Scan Control Widget
|
74
|
+
:link: user.widgets.scan_control
|
75
|
+
:link-type: ref
|
76
|
+
:img-top: /assets/widget_screenshots/scan_controller.png
|
77
|
+
|
78
|
+
Launch scans.
|
79
|
+
```
|
80
|
+
|
81
|
+
```{grid-item-card} Device Browser
|
82
|
+
:link: user.widgets.device_browser
|
83
|
+
:link-type: ref
|
84
|
+
:img-top: /assets/widget_screenshots/device_browser.png
|
85
|
+
|
86
|
+
Find and drag devices.
|
87
|
+
```
|
88
|
+
|
89
|
+
```{grid-item-card} Positioner Box
|
90
|
+
:link: user.widgets.positioner_box
|
91
|
+
:link-type: ref
|
92
|
+
:img-top: /assets/widget_screenshots/device_box.png
|
93
|
+
|
94
|
+
Control individual device.
|
95
|
+
```
|
10
96
|
|
11
|
-
|
12
|
-
ring_progress_bar
|
13
|
-
|
14
|
-
|
15
|
-
text_box/
|
16
|
-
bec_status_box/
|
97
|
+
```{grid-item-card} Ring Progress Bar
|
98
|
+
:link: user.widgets.ring_progress_bar
|
99
|
+
:link-type: ref
|
100
|
+
:img-top: /assets/widget_screenshots/ring_progress_bar.png
|
17
101
|
|
102
|
+
Nested progress bar.
|
18
103
|
```
|
19
104
|
|
105
|
+
````
|
106
|
+
|
107
|
+
## BEC Service Widgets
|
108
|
+
|
109
|
+
Visualise the status of BEC services.
|
110
|
+
|
111
|
+
````{grid} 3
|
112
|
+
:gutter: 2
|
113
|
+
|
114
|
+
```{grid-item-card} BEC Status Box
|
115
|
+
:link: user.widgets.bec_status_box
|
116
|
+
:link-type: ref
|
117
|
+
:img-top: /assets/widget_screenshots/status_box.png
|
118
|
+
|
119
|
+
Display status of BEC services.
|
120
|
+
```
|
121
|
+
|
122
|
+
```{grid-item-card} BEC Queue Table
|
123
|
+
:link: user.widgets.bec_queue
|
124
|
+
:link-type: ref
|
125
|
+
:img-top: /assets/widget_screenshots/queue.png
|
126
|
+
|
127
|
+
Display current scan queue.
|
128
|
+
```
|
129
|
+
````
|
130
|
+
|
131
|
+
## BEC Utility Widgets
|
132
|
+
|
133
|
+
Various utility widgets to enhance user experience.
|
134
|
+
|
135
|
+
````{grid} 3
|
136
|
+
:gutter: 2
|
137
|
+
|
138
|
+
```{grid-item-card} Service Buttons
|
139
|
+
:link: user.widgets.buttons
|
140
|
+
:link-type: ref
|
141
|
+
:img-top: /assets/widget_screenshots/buttons.png
|
142
|
+
|
143
|
+
Various service buttons.
|
144
|
+
```
|
145
|
+
|
146
|
+
```{grid-item-card} Device Input Widgets
|
147
|
+
:link: user.widgets.device_input
|
148
|
+
:link-type: ref
|
149
|
+
:img-top: /assets/widget_screenshots/device_inputs.png
|
150
|
+
|
151
|
+
Choose individual device from current session.
|
152
|
+
```
|
153
|
+
|
154
|
+
```{grid-item-card} Text Box Widget
|
155
|
+
:link: user.widgets.text_box
|
156
|
+
:link-type: ref
|
157
|
+
:img-top: /assets/widget_screenshots/text_box.png
|
158
|
+
|
159
|
+
Display custom text or HTML content.
|
160
|
+
```
|
161
|
+
|
162
|
+
```{grid-item-card} Website Widget
|
163
|
+
:link: user.widgets.website
|
164
|
+
:link-type: ref
|
165
|
+
:img-top: /assets/widget_screenshots/website.png
|
166
|
+
|
167
|
+
Display website content.
|
168
|
+
```
|
169
|
+
|
170
|
+
```{grid-item-card} Toogle Widget
|
171
|
+
:link: user.widgets.toggle
|
172
|
+
:link-type: ref
|
173
|
+
:img-top: /assets/widget_screenshots/toggle.png
|
174
|
+
|
175
|
+
Angular like toggle switch.
|
176
|
+
```
|
177
|
+
|
178
|
+
```{grid-item-card} Spinner
|
179
|
+
:link: user.widgets.spinner
|
180
|
+
:link-type: ref
|
181
|
+
:img-top: /assets/widget_screenshots/spinner.gif
|
182
|
+
|
183
|
+
Display spinner widget for loading or device movement.
|
184
|
+
```
|
185
|
+
|
186
|
+
```{grid-item-card} Position Indicator
|
187
|
+
:link: user.widgets.position_indicator
|
188
|
+
:link-type: ref
|
189
|
+
:img-top: /assets/widget_screenshots/position_indicator.png
|
190
|
+
|
191
|
+
Display position of motor withing its limits.
|
192
|
+
```
|
193
|
+
````
|
194
|
+
|
195
|
+
```{toctree}
|
196
|
+
---
|
197
|
+
maxdepth: 1
|
198
|
+
hidden: true
|
199
|
+
---
|
200
|
+
|
201
|
+
dock_area/bec_dock_area.md
|
202
|
+
bec_figure/bec_figure.md
|
203
|
+
waveform/waveform_widget.md
|
204
|
+
image/image_widget.md
|
205
|
+
motor_map/motor_map.md
|
206
|
+
scan_control/scan_control.md
|
207
|
+
progress_bar/ring_progress_bar.md
|
208
|
+
bec_status_box/bec_status_box.md
|
209
|
+
queue/queue.md
|
210
|
+
buttons/buttons.md
|
211
|
+
device_browser/device_browser.md
|
212
|
+
positioner_box/positioner_box.md
|
213
|
+
text_box/text_box.md
|
214
|
+
website/website.md
|
215
|
+
toggle/toggle.md
|
216
|
+
spinner/spinner.md
|
217
|
+
device_input/device_input.md
|
218
|
+
position_indicator/position_indicator.md
|
20
219
|
|
220
|
+
```
|
pyproject.toml
CHANGED
tests/unit_tests/client_mocks.py
CHANGED
@@ -18,6 +18,20 @@ class FakeDevice:
|
|
18
18
|
self.signals = {self.name: {"value": 1.0}}
|
19
19
|
self.description = {self.name: {"source": self.name, "dtype": "number", "shape": []}}
|
20
20
|
self.readout_priority = readout_priority
|
21
|
+
self._config = {
|
22
|
+
"readoutPriority": "baseline",
|
23
|
+
"deviceClass": "ophyd_devices.SimPositioner",
|
24
|
+
"deviceConfig": {
|
25
|
+
"delay": 1,
|
26
|
+
"limits": [-50, 50],
|
27
|
+
"tolerance": 0.01,
|
28
|
+
"update_frequency": 400,
|
29
|
+
},
|
30
|
+
"deviceTags": ["user motors"],
|
31
|
+
"enabled": enabled,
|
32
|
+
"readOnly": False,
|
33
|
+
"name": self.name,
|
34
|
+
}
|
21
35
|
|
22
36
|
def __contains__(self, item):
|
23
37
|
return item == self.name
|
@@ -0,0 +1,83 @@
|
|
1
|
+
from typing import TYPE_CHECKING
|
2
|
+
from unittest import mock
|
3
|
+
|
4
|
+
import pytest
|
5
|
+
from qtpy.QtCore import Qt
|
6
|
+
|
7
|
+
from bec_widgets.widgets.device_browser.device_browser import DeviceBrowser
|
8
|
+
|
9
|
+
from .client_mocks import mocked_client
|
10
|
+
|
11
|
+
if TYPE_CHECKING:
|
12
|
+
from qtpy.QtWidgets import QListWidgetItem
|
13
|
+
|
14
|
+
from bec_widgets.widgets.device_browser.device_item.device_item import DeviceItem
|
15
|
+
|
16
|
+
|
17
|
+
@pytest.fixture
|
18
|
+
def device_browser(qtbot, mocked_client):
|
19
|
+
dev_browser = DeviceBrowser(client=mocked_client)
|
20
|
+
qtbot.addWidget(dev_browser)
|
21
|
+
qtbot.waitExposed(dev_browser)
|
22
|
+
yield dev_browser
|
23
|
+
|
24
|
+
|
25
|
+
def test_device_browser_init_with_devices(device_browser):
|
26
|
+
"""
|
27
|
+
Test that the device browser is initialized with the correct number of devices.
|
28
|
+
"""
|
29
|
+
device_list = device_browser.ui.device_list
|
30
|
+
assert device_list.count() == len(device_browser.dev)
|
31
|
+
|
32
|
+
|
33
|
+
def test_device_browser_filtering(qtbot, device_browser):
|
34
|
+
"""
|
35
|
+
Test that the device browser is able to filter the device list.
|
36
|
+
"""
|
37
|
+
device_list = device_browser.ui.device_list
|
38
|
+
device_browser.ui.filter_input.setText("sam")
|
39
|
+
qtbot.wait(1000)
|
40
|
+
assert device_list.count() == 3
|
41
|
+
|
42
|
+
device_browser.ui.filter_input.setText("nonexistent")
|
43
|
+
qtbot.wait(1000)
|
44
|
+
assert device_list.count() == 0
|
45
|
+
|
46
|
+
device_browser.ui.filter_input.setText("")
|
47
|
+
qtbot.wait(1000)
|
48
|
+
assert device_list.count() == len(device_browser.dev)
|
49
|
+
|
50
|
+
|
51
|
+
def test_device_item_mouse_press_event(device_browser, qtbot):
|
52
|
+
"""
|
53
|
+
Test that the mousePressEvent is triggered correctly.
|
54
|
+
"""
|
55
|
+
# Simulate a left mouse press event on the device item
|
56
|
+
device_item: QListWidgetItem = device_browser.ui.device_list.itemAt(0, 0)
|
57
|
+
widget: DeviceItem = device_browser.ui.device_list.itemWidget(device_item)
|
58
|
+
qtbot.mousePress(widget.label, Qt.MouseButton.LeftButton)
|
59
|
+
|
60
|
+
|
61
|
+
def test_device_item_mouse_press_event_creates_drag(device_browser, qtbot):
|
62
|
+
"""
|
63
|
+
Test that the mousePressEvent is triggered correctly and initiates a drag.
|
64
|
+
"""
|
65
|
+
device_item: QListWidgetItem = device_browser.ui.device_list.itemAt(0, 0)
|
66
|
+
widget: DeviceItem = device_browser.ui.device_list.itemWidget(device_item)
|
67
|
+
device_name = widget.device
|
68
|
+
with mock.patch("qtpy.QtGui.QDrag.exec_") as mock_exec:
|
69
|
+
with mock.patch("qtpy.QtGui.QDrag.setMimeData") as mock_set_mimedata:
|
70
|
+
qtbot.mousePress(widget.label, Qt.MouseButton.LeftButton)
|
71
|
+
mock_set_mimedata.assert_called_once()
|
72
|
+
mock_exec.assert_called_once()
|
73
|
+
assert mock_set_mimedata.call_args[0][0].text() == device_name
|
74
|
+
|
75
|
+
|
76
|
+
def test_device_item_double_click_event(device_browser, qtbot):
|
77
|
+
"""
|
78
|
+
Test that the mouseDoubleClickEvent is triggered correctly.
|
79
|
+
"""
|
80
|
+
# Simulate a left mouse press event on the device item
|
81
|
+
device_item: QListWidgetItem = device_browser.ui.device_list.itemAt(0, 0)
|
82
|
+
widget: DeviceItem = device_browser.ui.device_list.itemWidget(device_item)
|
83
|
+
qtbot.mouseDClick(widget, Qt.LeftButton)
|