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.
Files changed (36) hide show
  1. CHANGELOG.md +30 -34
  2. PKG-INFO +1 -1
  3. bec_widgets/assets/designer_icons/image.png +0 -0
  4. bec_widgets/assets/toolbar_icons/auto_range.svg +1 -1
  5. bec_widgets/assets/toolbar_icons/compare.svg +3 -0
  6. bec_widgets/assets/toolbar_icons/fft.svg +11 -0
  7. bec_widgets/assets/toolbar_icons/image_autorange.svg +3 -0
  8. bec_widgets/assets/toolbar_icons/line_curve.svg +3 -0
  9. bec_widgets/assets/toolbar_icons/lock_aspect_ratio.svg +3 -0
  10. bec_widgets/assets/toolbar_icons/log_scale.png +0 -0
  11. bec_widgets/assets/toolbar_icons/reset_settings.svg +3 -0
  12. bec_widgets/assets/toolbar_icons/rotate_left.svg +3 -0
  13. bec_widgets/assets/toolbar_icons/rotate_right.svg +3 -0
  14. bec_widgets/assets/toolbar_icons/transform.svg +3 -0
  15. bec_widgets/cli/client.py +187 -2
  16. bec_widgets/examples/jupyter_console/jupyter_console_window.py +18 -19
  17. bec_widgets/widgets/figure/figure.py +1 -3
  18. bec_widgets/widgets/figure/plots/axis_settings.ui +86 -100
  19. bec_widgets/widgets/figure/plots/image/image.py +85 -3
  20. bec_widgets/widgets/figure/plots/image/image_item.py +14 -0
  21. bec_widgets/widgets/image/__init__.py +0 -0
  22. bec_widgets/widgets/image/bec_image_widget.pyproject +1 -0
  23. bec_widgets/widgets/image/bec_image_widget_plugin.py +59 -0
  24. bec_widgets/widgets/image/image_widget.py +475 -0
  25. bec_widgets/widgets/image/register_bec_image_widget.py +15 -0
  26. {bec_widgets-0.89.0.dist-info → bec_widgets-0.90.0.dist-info}/METADATA +1 -1
  27. {bec_widgets-0.89.0.dist-info → bec_widgets-0.90.0.dist-info}/RECORD +36 -19
  28. pyproject.toml +1 -1
  29. tests/unit_tests/client_mocks.py +9 -1
  30. tests/unit_tests/test_bec_image_widget.py +218 -0
  31. tests/unit_tests/test_device_input_base.py +1 -1
  32. tests/unit_tests/test_device_input_widgets.py +2 -0
  33. tests/unit_tests/test_waveform_widget.py +1 -1
  34. {bec_widgets-0.89.0.dist-info → bec_widgets-0.90.0.dist-info}/WHEEL +0 -0
  35. {bec_widgets-0.89.0.dist-info → bec_widgets-0.90.0.dist-info}/entry_points.txt +0 -0
  36. {bec_widgets-0.89.0.dist-info → bec_widgets-0.90.0.dist-info}/licenses/LICENSE +0 -0
@@ -89,12 +89,19 @@ class FakePositioner(FakeDevice):
89
89
 
90
90
 
91
91
  class Positioner(FakePositioner):
92
- """just placeholder for testing embeded isinstance check in DeviceCombobox"""
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 test_waveform_widget_inti(waveform_widget):
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)