bec-widgets 0.89.0__py3-none-any.whl → 0.90.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 +30 -34
- PKG-INFO +1 -1
- bec_widgets/assets/designer_icons/image.png +0 -0
- bec_widgets/assets/toolbar_icons/auto_range.svg +1 -1
- bec_widgets/assets/toolbar_icons/compare.svg +3 -0
- bec_widgets/assets/toolbar_icons/fft.svg +11 -0
- bec_widgets/assets/toolbar_icons/image_autorange.svg +3 -0
- bec_widgets/assets/toolbar_icons/line_curve.svg +3 -0
- bec_widgets/assets/toolbar_icons/lock_aspect_ratio.svg +3 -0
- bec_widgets/assets/toolbar_icons/log_scale.png +0 -0
- bec_widgets/assets/toolbar_icons/reset_settings.svg +3 -0
- bec_widgets/assets/toolbar_icons/rotate_left.svg +3 -0
- bec_widgets/assets/toolbar_icons/rotate_right.svg +3 -0
- bec_widgets/assets/toolbar_icons/transform.svg +3 -0
- bec_widgets/cli/client.py +187 -2
- bec_widgets/examples/jupyter_console/jupyter_console_window.py +18 -19
- bec_widgets/widgets/figure/figure.py +1 -3
- bec_widgets/widgets/figure/plots/axis_settings.ui +86 -100
- bec_widgets/widgets/figure/plots/image/image.py +85 -3
- bec_widgets/widgets/figure/plots/image/image_item.py +14 -0
- bec_widgets/widgets/image/__init__.py +0 -0
- bec_widgets/widgets/image/bec_image_widget.pyproject +1 -0
- bec_widgets/widgets/image/bec_image_widget_plugin.py +59 -0
- bec_widgets/widgets/image/image_widget.py +475 -0
- bec_widgets/widgets/image/register_bec_image_widget.py +15 -0
- {bec_widgets-0.89.0.dist-info → bec_widgets-0.90.0.dist-info}/METADATA +1 -1
- {bec_widgets-0.89.0.dist-info → bec_widgets-0.90.0.dist-info}/RECORD +36 -19
- pyproject.toml +1 -1
- tests/unit_tests/client_mocks.py +9 -1
- tests/unit_tests/test_bec_image_widget.py +218 -0
- tests/unit_tests/test_device_input_base.py +1 -1
- tests/unit_tests/test_device_input_widgets.py +2 -0
- tests/unit_tests/test_waveform_widget.py +1 -1
- {bec_widgets-0.89.0.dist-info → bec_widgets-0.90.0.dist-info}/WHEEL +0 -0
- {bec_widgets-0.89.0.dist-info → bec_widgets-0.90.0.dist-info}/entry_points.txt +0 -0
- {bec_widgets-0.89.0.dist-info → bec_widgets-0.90.0.dist-info}/licenses/LICENSE +0 -0
tests/unit_tests/client_mocks.py
CHANGED
@@ -89,12 +89,19 @@ class FakePositioner(FakeDevice):
|
|
89
89
|
|
90
90
|
|
91
91
|
class Positioner(FakePositioner):
|
92
|
-
"""just placeholder for testing
|
92
|
+
"""just placeholder for testing embedded isinstance check in DeviceCombobox"""
|
93
93
|
|
94
94
|
def __init__(self, name="test", limits=None, read_value=1.0):
|
95
95
|
super().__init__(name, limits, read_value)
|
96
96
|
|
97
97
|
|
98
|
+
class Device(FakeDevice):
|
99
|
+
"""just placeholder for testing embedded isinstance check in DeviceCombobox"""
|
100
|
+
|
101
|
+
def __init__(self, name, enabled=True):
|
102
|
+
super().__init__(name, enabled)
|
103
|
+
|
104
|
+
|
98
105
|
class DMMock:
|
99
106
|
def __init__(self):
|
100
107
|
self.devices = DeviceContainer()
|
@@ -120,6 +127,7 @@ DEVICES = [
|
|
120
127
|
FakeDevice("eiger"),
|
121
128
|
FakeDevice("async_device", readout_priority=ReadoutPriority.ASYNC),
|
122
129
|
Positioner("test", limits=[-10, 10], read_value=2.0),
|
130
|
+
Device("test_device"),
|
123
131
|
]
|
124
132
|
|
125
133
|
|
@@ -0,0 +1,218 @@
|
|
1
|
+
from unittest.mock import MagicMock, patch
|
2
|
+
|
3
|
+
import pyqtgraph as pg
|
4
|
+
import pytest
|
5
|
+
|
6
|
+
from bec_widgets.widgets.image.image_widget import BECImageWidget
|
7
|
+
|
8
|
+
from .client_mocks import mocked_client
|
9
|
+
|
10
|
+
|
11
|
+
@pytest.fixture
|
12
|
+
def image_widget(qtbot, mocked_client):
|
13
|
+
widget = BECImageWidget(client=mocked_client())
|
14
|
+
widget.toolbar.widgets["monitor"].device_combobox.set_device_filter("FakeDevice")
|
15
|
+
qtbot.addWidget(widget)
|
16
|
+
qtbot.waitExposed(widget)
|
17
|
+
yield widget
|
18
|
+
widget.close()
|
19
|
+
|
20
|
+
|
21
|
+
@pytest.fixture
|
22
|
+
def mock_image(image_widget):
|
23
|
+
image_mock = MagicMock()
|
24
|
+
image_widget._image = image_mock
|
25
|
+
return image_mock
|
26
|
+
|
27
|
+
|
28
|
+
def test_image_widget_init(image_widget):
|
29
|
+
assert image_widget is not None
|
30
|
+
assert image_widget.client is not None
|
31
|
+
assert isinstance(image_widget, BECImageWidget)
|
32
|
+
assert image_widget.config.widget_class == "BECImageWidget"
|
33
|
+
assert image_widget._image is not None
|
34
|
+
|
35
|
+
assert (
|
36
|
+
image_widget.toolbar.widgets["monitor"].device_combobox.config.device_filter == "FakeDevice"
|
37
|
+
)
|
38
|
+
assert image_widget.toolbar.widgets["drag_mode"].action.isChecked() == True
|
39
|
+
assert image_widget.toolbar.widgets["rectangle_mode"].action.isChecked() == False
|
40
|
+
assert image_widget.toolbar.widgets["auto_range"].action.isChecked() == False
|
41
|
+
assert image_widget.toolbar.widgets["auto_range_image"].action.isChecked() == True
|
42
|
+
assert image_widget.toolbar.widgets["FFT"].action.isChecked() == False
|
43
|
+
assert image_widget.toolbar.widgets["transpose"].action.isChecked() == False
|
44
|
+
assert image_widget.toolbar.widgets["log"].action.isChecked() == False
|
45
|
+
|
46
|
+
|
47
|
+
###################################
|
48
|
+
# Toolbar Actions
|
49
|
+
###################################
|
50
|
+
def test_toolbar_connect_action(image_widget, mock_image, qtbot):
|
51
|
+
combo = image_widget.toolbar.widgets["monitor"].device_combobox
|
52
|
+
combo.setCurrentText("eiger")
|
53
|
+
qtbot.wait(200)
|
54
|
+
assert combo.currentText() == "eiger"
|
55
|
+
action = image_widget.toolbar.widgets["connect"].action
|
56
|
+
action.trigger()
|
57
|
+
image_widget._image.image.assert_called_once_with(
|
58
|
+
monitor="eiger",
|
59
|
+
color_map="magma",
|
60
|
+
color_bar="full",
|
61
|
+
downsample=True,
|
62
|
+
opacity=1.0,
|
63
|
+
vrange=None,
|
64
|
+
)
|
65
|
+
|
66
|
+
|
67
|
+
def test_image_toolbar_drag_mode_action_triggered(image_widget, qtbot):
|
68
|
+
action_drag = image_widget.toolbar.widgets["drag_mode"].action
|
69
|
+
action_rectangle = image_widget.toolbar.widgets["rectangle_mode"].action
|
70
|
+
action_drag.trigger()
|
71
|
+
assert action_drag.isChecked() == True
|
72
|
+
assert action_rectangle.isChecked() == False
|
73
|
+
|
74
|
+
|
75
|
+
def test_image_toolbar_rectangle_mode_action_triggered(image_widget, qtbot):
|
76
|
+
action_drag = image_widget.toolbar.widgets["drag_mode"].action
|
77
|
+
action_rectangle = image_widget.toolbar.widgets["rectangle_mode"].action
|
78
|
+
action_rectangle.trigger()
|
79
|
+
assert action_drag.isChecked() == False
|
80
|
+
assert action_rectangle.isChecked() == True
|
81
|
+
|
82
|
+
|
83
|
+
def test_image_toolbar_auto_range(image_widget, mock_image):
|
84
|
+
action = image_widget.toolbar.widgets["auto_range"].action
|
85
|
+
action.trigger()
|
86
|
+
image_widget._image.set_auto_range.assert_called_once_with(True, "xy")
|
87
|
+
|
88
|
+
|
89
|
+
def test_image_toolbar_enable_mouse_pan_mode(qtbot, image_widget):
|
90
|
+
action_drag = image_widget.toolbar.widgets["drag_mode"].action
|
91
|
+
action_rectangle = image_widget.toolbar.widgets["rectangle_mode"].action
|
92
|
+
|
93
|
+
mock_view_box = MagicMock()
|
94
|
+
image_widget._image.plot_item.getViewBox = MagicMock(return_value=mock_view_box)
|
95
|
+
|
96
|
+
image_widget.enable_mouse_pan_mode()
|
97
|
+
|
98
|
+
assert action_drag.isChecked() == True
|
99
|
+
assert action_rectangle.isChecked() == False
|
100
|
+
mock_view_box.setMouseMode.assert_called_once_with(pg.ViewBox.PanMode)
|
101
|
+
|
102
|
+
|
103
|
+
def test_image_toolbar_auto_range_image(image_widget, mock_image):
|
104
|
+
action = image_widget.toolbar.widgets["auto_range_image"].action
|
105
|
+
action.trigger()
|
106
|
+
assert action.isChecked() == False
|
107
|
+
image_widget._image.set_autorange.assert_called_once_with(False)
|
108
|
+
|
109
|
+
|
110
|
+
def test_image_toolbar_FFT(image_widget, mock_image):
|
111
|
+
action = image_widget.toolbar.widgets["FFT"].action
|
112
|
+
action.trigger()
|
113
|
+
assert action.isChecked() == True
|
114
|
+
image_widget._image.set_fft.assert_called_once_with(True, None)
|
115
|
+
|
116
|
+
|
117
|
+
def test_image_toolbar_log(image_widget, mock_image):
|
118
|
+
action = image_widget.toolbar.widgets["log"].action
|
119
|
+
action.trigger()
|
120
|
+
assert action.isChecked() == True
|
121
|
+
image_widget._image.set_log.assert_called_once_with(True, None)
|
122
|
+
|
123
|
+
|
124
|
+
def test_image_toggle_transpose(image_widget, mock_image):
|
125
|
+
action = image_widget.toolbar.widgets["transpose"].action
|
126
|
+
action.trigger()
|
127
|
+
assert action.isChecked() == True
|
128
|
+
image_widget._image.set_transpose.assert_called_once_with(True, None)
|
129
|
+
|
130
|
+
|
131
|
+
def test_image_toolbar_rotation(image_widget, mock_image):
|
132
|
+
action_left = image_widget.toolbar.widgets["rotate_left"].action
|
133
|
+
action_right = image_widget.toolbar.widgets["rotate_right"].action
|
134
|
+
|
135
|
+
action_left.trigger()
|
136
|
+
image_widget._image.set_rotation(1, None)
|
137
|
+
action_right.trigger()
|
138
|
+
image_widget._image.set_rotation(2, None)
|
139
|
+
|
140
|
+
action_right.trigger()
|
141
|
+
image_widget._image.set_rotation(1, None)
|
142
|
+
|
143
|
+
|
144
|
+
###################################
|
145
|
+
# Wrapper methods for ImageShow
|
146
|
+
###################################
|
147
|
+
|
148
|
+
|
149
|
+
def test_image_set_image(image_widget, mock_image):
|
150
|
+
image_widget.image(monitor="image")
|
151
|
+
image_widget._image.image.assert_called_once_with(
|
152
|
+
monitor="image",
|
153
|
+
color_map="magma",
|
154
|
+
color_bar="full",
|
155
|
+
downsample=True,
|
156
|
+
opacity=1.0,
|
157
|
+
vrange=None,
|
158
|
+
)
|
159
|
+
|
160
|
+
|
161
|
+
def test_image_vrange(image_widget, mock_image):
|
162
|
+
image_widget.set_vrange(0, 1)
|
163
|
+
image_widget._image.set_vrange.assert_called_once_with(0, 1, None)
|
164
|
+
|
165
|
+
|
166
|
+
def test_image_set_color_map(image_widget, mock_image):
|
167
|
+
image_widget.set_color_map("viridis")
|
168
|
+
image_widget._image.set_color_map.assert_called_once_with("viridis", None)
|
169
|
+
|
170
|
+
|
171
|
+
def test_image_widget_set_title(image_widget, mock_image):
|
172
|
+
image_widget.set_title("Title Label")
|
173
|
+
image_widget._image.set_title.assert_called_once_with("Title Label")
|
174
|
+
|
175
|
+
|
176
|
+
def test_image_widget_set_x_label(image_widget, mock_image):
|
177
|
+
image_widget.set_x_label("X Label")
|
178
|
+
image_widget._image.set_x_label.assert_called_once_with("X Label")
|
179
|
+
|
180
|
+
|
181
|
+
def test_image_widget_set_y_label(image_widget, mock_image):
|
182
|
+
image_widget.set_y_label("Y Label")
|
183
|
+
image_widget._image.set_y_label.assert_called_once_with("Y Label")
|
184
|
+
|
185
|
+
|
186
|
+
def test_image_widget_set_x_scale(image_widget, mock_image):
|
187
|
+
image_widget.set_x_scale("linear")
|
188
|
+
image_widget._image.set_x_scale.assert_called_once_with("linear")
|
189
|
+
|
190
|
+
|
191
|
+
def test_image_widget_set_y_scale(image_widget, mock_image):
|
192
|
+
image_widget.set_y_scale("log")
|
193
|
+
image_widget._image.set_y_scale.assert_called_once_with("log")
|
194
|
+
|
195
|
+
|
196
|
+
def test_image_widget_set_x_lim(image_widget, mock_image):
|
197
|
+
image_widget.set_x_lim((0, 10))
|
198
|
+
image_widget._image.set_x_lim.assert_called_once_with((0, 10))
|
199
|
+
|
200
|
+
|
201
|
+
def test_image_widget_set_y_lim(image_widget, mock_image):
|
202
|
+
image_widget.set_y_lim((0, 10))
|
203
|
+
image_widget._image.set_y_lim.assert_called_once_with((0, 10))
|
204
|
+
|
205
|
+
|
206
|
+
def test_image_widget_set_grid(image_widget, mock_image):
|
207
|
+
image_widget.set_grid(True, False)
|
208
|
+
image_widget._image.set_grid.assert_called_once_with(True, False)
|
209
|
+
|
210
|
+
|
211
|
+
def test_image_widget_lock_aspect_ratio(image_widget, mock_image):
|
212
|
+
image_widget.lock_aspect_ratio(True)
|
213
|
+
image_widget._image.lock_aspect_ratio.assert_called_once_with(True)
|
214
|
+
|
215
|
+
|
216
|
+
def test_image_widget_export(image_widget, mock_image):
|
217
|
+
image_widget.export()
|
218
|
+
image_widget._image.export.assert_called_once()
|
@@ -69,4 +69,4 @@ def test_device_input_base_get_device_list(device_input_base):
|
|
69
69
|
|
70
70
|
def test_device_input_base_get_filters(device_input_base):
|
71
71
|
filters = device_input_base.get_available_filters()
|
72
|
-
assert filters == {"FakePositioner", "FakeDevice", "Positioner"}
|
72
|
+
assert filters == {"FakePositioner", "FakeDevice", "Positioner", "Device"}
|
@@ -69,6 +69,7 @@ def test_device_input_combobox_init(device_input_combobox):
|
|
69
69
|
"eiger",
|
70
70
|
"async_device",
|
71
71
|
"test",
|
72
|
+
"test_device",
|
72
73
|
]
|
73
74
|
|
74
75
|
|
@@ -157,6 +158,7 @@ def test_device_input_line_edit_init(device_input_line_edit):
|
|
157
158
|
"eiger",
|
158
159
|
"async_device",
|
159
160
|
"test",
|
161
|
+
"test_device",
|
160
162
|
]
|
161
163
|
|
162
164
|
|
@@ -24,7 +24,7 @@ def mock_waveform(waveform_widget):
|
|
24
24
|
return waveform_mock
|
25
25
|
|
26
26
|
|
27
|
-
def
|
27
|
+
def test_waveform_widget_init(waveform_widget):
|
28
28
|
assert waveform_widget is not None
|
29
29
|
assert waveform_widget.client is not None
|
30
30
|
assert isinstance(waveform_widget, BECWaveformWidget)
|
File without changes
|
File without changes
|
File without changes
|