bec-widgets 0.99.8__py3-none-any.whl → 0.99.9__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 (155) hide show
  1. CHANGELOG.md +6 -6
  2. PKG-INFO +1 -1
  3. {bec_widgets-0.99.8.dist-info → bec_widgets-0.99.9.dist-info}/METADATA +1 -1
  4. {bec_widgets-0.99.8.dist-info → bec_widgets-0.99.9.dist-info}/RECORD +8 -155
  5. pyproject.toml +6 -1
  6. docs/Makefile +0 -20
  7. docs/_static/custom.css +0 -170
  8. docs/_templates/custom-class-template.rst +0 -34
  9. docs/_templates/custom-module-template.rst +0 -66
  10. docs/api_reference/api_reference.md +0 -12
  11. docs/assets/apps_48dp.svg +0 -1
  12. docs/assets/display_settings_48dp.svg +0 -1
  13. docs/assets/index_api.svg +0 -97
  14. docs/assets/index_contribute.svg +0 -76
  15. docs/assets/index_getting_started.svg +0 -66
  16. docs/assets/index_user_guide.svg +0 -67
  17. docs/assets/rocket_launch_48dp.svg +0 -1
  18. docs/assets/widget_screenshots/buttons.png +0 -0
  19. docs/assets/widget_screenshots/device_box.png +0 -0
  20. docs/assets/widget_screenshots/device_browser.png +0 -0
  21. docs/assets/widget_screenshots/device_inputs.png +0 -0
  22. docs/assets/widget_screenshots/dock_area.png +0 -0
  23. docs/assets/widget_screenshots/figure.png +0 -0
  24. docs/assets/widget_screenshots/image_widget.png +0 -0
  25. docs/assets/widget_screenshots/motor_map_widget.png +0 -0
  26. docs/assets/widget_screenshots/position_indicator.png +0 -0
  27. docs/assets/widget_screenshots/queue.png +0 -0
  28. docs/assets/widget_screenshots/ring_progress_bar.png +0 -0
  29. docs/assets/widget_screenshots/scan_controller.png +0 -0
  30. docs/assets/widget_screenshots/spinner.gif +0 -0
  31. docs/assets/widget_screenshots/status_box.png +0 -0
  32. docs/assets/widget_screenshots/text_box.png +0 -0
  33. docs/assets/widget_screenshots/toggle.png +0 -0
  34. docs/assets/widget_screenshots/waveform_widget.png +0 -0
  35. docs/assets/widget_screenshots/website.png +0 -0
  36. docs/conf.py +0 -82
  37. docs/developer/developer.md +0 -52
  38. docs/developer/introduction/concepts.md +0 -14
  39. docs/developer/introduction/contributing.md +0 -28
  40. docs/developer/introduction/introduction.md +0 -16
  41. docs/developer/introduction/useful_links.md +0 -23
  42. docs/developer/widget_development/bec_dispatcher.md +0 -143
  43. docs/developer/widget_development/widget_base_class.md +0 -171
  44. docs/developer/widget_development/widget_development.md +0 -14
  45. docs/index.md +0 -74
  46. docs/introduction/introduction.md +0 -18
  47. docs/make.bat +0 -35
  48. docs/requirements.txt +0 -12
  49. docs/user/api_reference/api_reference.md +0 -11
  50. docs/user/applications/applications.md +0 -10
  51. docs/user/customisation.md +0 -123
  52. docs/user/getting_started/BECDockArea.png +0 -0
  53. docs/user/getting_started/auto_updates.md +0 -82
  54. docs/user/getting_started/getting_started.md +0 -15
  55. docs/user/getting_started/gui_complex_gui.gif +0 -0
  56. docs/user/getting_started/installation.md +0 -33
  57. docs/user/getting_started/quick_start.md +0 -110
  58. docs/user/getting_started/video_tutorials.md +0 -17
  59. docs/user/user.md +0 -71
  60. docs/user/widgets/bec_figure/BECFigure.png +0 -0
  61. docs/user/widgets/bec_figure/bec_figure.md +0 -105
  62. docs/user/widgets/bec_status_box/bec_status_box.gif +0 -0
  63. docs/user/widgets/bec_status_box/bec_status_box.md +0 -38
  64. docs/user/widgets/buttons/buttons.md +0 -90
  65. docs/user/widgets/buttons/dark_mode_disabled.png +0 -0
  66. docs/user/widgets/buttons/dark_mode_enabled.png +0 -0
  67. docs/user/widgets/device_browser/device_browser.md +0 -36
  68. docs/user/widgets/device_browser/device_browser.png +0 -0
  69. docs/user/widgets/device_input/device_input.md +0 -100
  70. docs/user/widgets/dock_area/BECDockArea.png +0 -0
  71. docs/user/widgets/dock_area/bec_dock_area.md +0 -109
  72. docs/user/widgets/image/image_plot.gif +0 -0
  73. docs/user/widgets/image/image_widget.md +0 -84
  74. docs/user/widgets/motor_map/motor.gif +0 -0
  75. docs/user/widgets/motor_map/motor_map.md +0 -80
  76. docs/user/widgets/position_indicator/position_indicator.md +0 -69
  77. docs/user/widgets/positioner_box/positioner_box.md +0 -63
  78. docs/user/widgets/progress_bar/progress_bar.gif +0 -0
  79. docs/user/widgets/progress_bar/ring_progress_bar.md +0 -103
  80. docs/user/widgets/queue/queue.md +0 -41
  81. docs/user/widgets/scan_control/hide_scan_control.png +0 -0
  82. docs/user/widgets/scan_control/scan_control.gif +0 -0
  83. docs/user/widgets/scan_control/scan_control.md +0 -54
  84. docs/user/widgets/spinner/spinner.md +0 -68
  85. docs/user/widgets/text_box/text_box.md +0 -74
  86. docs/user/widgets/toggle/toggle.md +0 -66
  87. docs/user/widgets/waveform/bec_figure_dap.gif +0 -0
  88. docs/user/widgets/waveform/scatter_2D.gif +0 -0
  89. docs/user/widgets/waveform/w1D.gif +0 -0
  90. docs/user/widgets/waveform/waveform_widget.md +0 -132
  91. docs/user/widgets/website/website.md +0 -69
  92. docs/user/widgets/widgets.md +0 -220
  93. tests/__init__.py +0 -0
  94. tests/end-2-end/__init__.py +0 -0
  95. tests/end-2-end/conftest.py +0 -53
  96. tests/end-2-end/test_bec_dock_rpc_e2e.py +0 -298
  97. tests/end-2-end/test_bec_figure_rpc_e2e.py +0 -212
  98. tests/end-2-end/test_rpc_register_e2e.py +0 -40
  99. tests/end-2-end/test_scan_control_e2e.py +0 -71
  100. tests/references/SpinnerWidget/SpinnerWidget_darwin.png +0 -0
  101. tests/references/SpinnerWidget/SpinnerWidget_linux.png +0 -0
  102. tests/references/SpinnerWidget/SpinnerWidget_started_darwin.png +0 -0
  103. tests/references/SpinnerWidget/SpinnerWidget_started_linux.png +0 -0
  104. tests/unit_tests/__init__.py +0 -0
  105. tests/unit_tests/client_mocks.py +0 -189
  106. tests/unit_tests/conftest.py +0 -64
  107. tests/unit_tests/test_bec_connector.py +0 -80
  108. tests/unit_tests/test_bec_dispatcher.py +0 -119
  109. tests/unit_tests/test_bec_dock.py +0 -155
  110. tests/unit_tests/test_bec_figure.py +0 -270
  111. tests/unit_tests/test_bec_image.py +0 -63
  112. tests/unit_tests/test_bec_image_widget.py +0 -217
  113. tests/unit_tests/test_bec_motor_map.py +0 -282
  114. tests/unit_tests/test_bec_queue.py +0 -111
  115. tests/unit_tests/test_bec_status_box.py +0 -123
  116. tests/unit_tests/test_client_utils.py +0 -76
  117. tests/unit_tests/test_color_map_selector.py +0 -42
  118. tests/unit_tests/test_color_validation.py +0 -75
  119. tests/unit_tests/test_configs/config_device.yaml +0 -33
  120. tests/unit_tests/test_configs/config_device_no_entry.yaml +0 -27
  121. tests/unit_tests/test_configs/config_scan.yaml +0 -82
  122. tests/unit_tests/test_crosshair.py +0 -143
  123. tests/unit_tests/test_dark_mode_button.py +0 -70
  124. tests/unit_tests/test_device_browser.py +0 -83
  125. tests/unit_tests/test_device_input_base.py +0 -76
  126. tests/unit_tests/test_device_input_widgets.py +0 -178
  127. tests/unit_tests/test_error_utils.py +0 -63
  128. tests/unit_tests/test_generate_cli_client.py +0 -123
  129. tests/unit_tests/test_generate_plugin.py +0 -155
  130. tests/unit_tests/test_motor_map_widget.py +0 -194
  131. tests/unit_tests/test_msgs/__init__.py +0 -0
  132. tests/unit_tests/test_msgs/available_scans_message.py +0 -989
  133. tests/unit_tests/test_plot_base.py +0 -95
  134. tests/unit_tests/test_plugin_utils.py +0 -13
  135. tests/unit_tests/test_positioner_box.py +0 -130
  136. tests/unit_tests/test_ring_progress_bar.py +0 -337
  137. tests/unit_tests/test_rpc_register.py +0 -52
  138. tests/unit_tests/test_rpc_server.py +0 -42
  139. tests/unit_tests/test_rpc_widget_handler.py +0 -7
  140. tests/unit_tests/test_scan_control.py +0 -324
  141. tests/unit_tests/test_scan_control_group_box.py +0 -160
  142. tests/unit_tests/test_setting_dialog.py +0 -96
  143. tests/unit_tests/test_spinner.py +0 -31
  144. tests/unit_tests/test_stop_button.py +0 -27
  145. tests/unit_tests/test_text_box_widget.py +0 -54
  146. tests/unit_tests/test_toggle.py +0 -38
  147. tests/unit_tests/test_vscode_widget.py +0 -75
  148. tests/unit_tests/test_waveform1d.py +0 -712
  149. tests/unit_tests/test_waveform_widget.py +0 -462
  150. tests/unit_tests/test_website_widget.py +0 -25
  151. tests/unit_tests/test_widget_io.py +0 -90
  152. tests/unit_tests/test_yaml_dialog.py +0 -163
  153. {bec_widgets-0.99.8.dist-info → bec_widgets-0.99.9.dist-info}/WHEEL +0 -0
  154. {bec_widgets-0.99.8.dist-info → bec_widgets-0.99.9.dist-info}/entry_points.txt +0 -0
  155. {bec_widgets-0.99.8.dist-info → bec_widgets-0.99.9.dist-info}/licenses/LICENSE +0 -0
@@ -1,270 +0,0 @@
1
- # pylint: disable=missing-function-docstring, missing-module-docstring, unused-import
2
-
3
- import numpy as np
4
- import pytest
5
-
6
- from bec_widgets.widgets.figure import BECFigure
7
- from bec_widgets.widgets.figure.plots.image.image import BECImageShow
8
- from bec_widgets.widgets.figure.plots.motor_map.motor_map import BECMotorMap
9
- from bec_widgets.widgets.figure.plots.waveform.waveform import BECWaveform
10
-
11
- from .client_mocks import mocked_client
12
- from .conftest import create_widget
13
-
14
-
15
- def test_bec_figure_init(qtbot, mocked_client):
16
- bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
17
- assert bec_figure is not None
18
- assert bec_figure.client is not None
19
- assert isinstance(bec_figure, BECFigure)
20
- assert bec_figure.config.widget_class == "BECFigure"
21
-
22
-
23
- def test_bec_figure_init_with_config(mocked_client):
24
- config = {"widget_class": "BECFigure", "gui_id": "test_gui_id", "theme": "dark"}
25
- widget = BECFigure(client=mocked_client, config=config)
26
- assert widget.config.gui_id == "test_gui_id"
27
- assert widget.config.theme == "dark"
28
-
29
-
30
- def test_bec_figure_add_remove_plot(qtbot, mocked_client):
31
- bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
32
- initial_count = len(bec_figure._widgets)
33
-
34
- # Adding 3 widgets - 2 WaveformBase and 1 PlotBase
35
- w0 = bec_figure.plot(new=True)
36
- w1 = bec_figure.plot(new=True)
37
- w2 = bec_figure.add_widget(widget_type="BECPlotBase")
38
-
39
- # Check if the widgets were added
40
- assert len(bec_figure._widgets) == initial_count + 3
41
- assert w0.gui_id in bec_figure._widgets
42
- assert w1.gui_id in bec_figure._widgets
43
- assert w2.gui_id in bec_figure._widgets
44
- assert bec_figure._widgets[w0.gui_id].config.widget_class == "BECWaveform"
45
- assert bec_figure._widgets[w1.gui_id].config.widget_class == "BECWaveform"
46
- assert bec_figure._widgets[w2.gui_id].config.widget_class == "BECPlotBase"
47
-
48
- # Check accessing positions by the grid in figure
49
- assert bec_figure[0, 0] == w0
50
- assert bec_figure[1, 0] == w1
51
- assert bec_figure[2, 0] == w2
52
-
53
- # Removing 1 widget
54
- bec_figure.remove(widget_id=w0.gui_id)
55
- assert len(bec_figure._widgets) == initial_count + 2
56
- assert w0.gui_id not in bec_figure._widgets
57
- assert w2.gui_id in bec_figure._widgets
58
- assert bec_figure._widgets[w1.gui_id].config.widget_class == "BECWaveform"
59
-
60
-
61
- def test_add_different_types_of_widgets(qtbot, mocked_client):
62
- bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
63
- plt = bec_figure.plot(x_name="samx", y_name="bpm4i")
64
- im = bec_figure.image("eiger")
65
- motor_map = bec_figure.motor_map("samx", "samy")
66
-
67
- assert plt.__class__ == BECWaveform
68
- assert im.__class__ == BECImageShow
69
- assert motor_map.__class__ == BECMotorMap
70
-
71
-
72
- def test_access_widgets_access_errors(qtbot, mocked_client):
73
- bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
74
- bec_figure.plot(row=0, col=0)
75
-
76
- # access widget by non-existent coordinates
77
- with pytest.raises(ValueError) as excinfo:
78
- bec_figure[0, 2]
79
- assert "No widget at coordinates (0, 2)" in str(excinfo.value)
80
-
81
- # access widget by non-existent widget_id
82
- with pytest.raises(KeyError) as excinfo:
83
- bec_figure["non_existent_widget"]
84
- assert "Widget with id 'non_existent_widget' not found" in str(excinfo.value)
85
-
86
- # access widget by wrong type
87
- with pytest.raises(TypeError) as excinfo:
88
- bec_figure[1.2]
89
- assert (
90
- "Key must be a string (widget id) or a tuple of two integers (grid coordinates)"
91
- in str(excinfo.value)
92
- )
93
-
94
-
95
- def test_add_plot_to_occupied_position(qtbot, mocked_client):
96
- bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
97
- bec_figure.plot(row=0, col=0)
98
-
99
- with pytest.raises(ValueError) as excinfo:
100
- bec_figure.plot(row=0, col=0, new=True)
101
- assert "Position at row 0 and column 0 is already occupied." in str(excinfo.value)
102
-
103
-
104
- def test_remove_plots(qtbot, mocked_client):
105
- bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
106
- w1 = bec_figure.plot(row=0, col=0)
107
- w2 = bec_figure.plot(row=0, col=1)
108
- w3 = bec_figure.plot(row=1, col=0)
109
- w4 = bec_figure.plot(row=1, col=1)
110
-
111
- assert bec_figure[0, 0] == w1
112
- assert bec_figure[0, 1] == w2
113
- assert bec_figure[1, 0] == w3
114
- assert bec_figure[1, 1] == w4
115
-
116
- # remove by coordinates
117
- bec_figure[0, 0].remove()
118
- assert w1.gui_id not in bec_figure._widgets
119
-
120
- # remove by widget_id
121
- bec_figure.remove(widget_id=w2.gui_id)
122
- assert w2.gui_id not in bec_figure._widgets
123
-
124
- # remove by widget object
125
- w3.remove()
126
- assert w3.gui_id not in bec_figure._widgets
127
-
128
- # check the remaining widget 4
129
- assert bec_figure[0, 0] == w4
130
- assert bec_figure[w4.gui_id] == w4
131
- assert w4.gui_id in bec_figure._widgets
132
- assert len(bec_figure._widgets) == 1
133
-
134
-
135
- def test_remove_plots_by_coordinates_ints(qtbot, mocked_client):
136
- bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
137
- w1 = bec_figure.plot(row=0, col=0)
138
- w2 = bec_figure.plot(row=0, col=1)
139
-
140
- bec_figure.remove(row=0, col=0)
141
- assert w1.gui_id not in bec_figure._widgets
142
- assert w2.gui_id in bec_figure._widgets
143
- assert bec_figure[0, 0] == w2
144
- assert len(bec_figure._widgets) == 1
145
-
146
-
147
- def test_remove_plots_by_coordinates_tuple(qtbot, mocked_client):
148
- bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
149
- w1 = bec_figure.plot(row=0, col=0)
150
- w2 = bec_figure.plot(row=0, col=1)
151
-
152
- bec_figure.remove(coordinates=(0, 0))
153
- assert w1.gui_id not in bec_figure._widgets
154
- assert w2.gui_id in bec_figure._widgets
155
- assert bec_figure[0, 0] == w2
156
- assert len(bec_figure._widgets) == 1
157
-
158
-
159
- def test_remove_plot_by_id_error(qtbot, mocked_client):
160
- bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
161
- bec_figure.plot()
162
-
163
- with pytest.raises(ValueError) as excinfo:
164
- bec_figure.remove(widget_id="non_existent_widget")
165
- assert "Widget with ID 'non_existent_widget' does not exist." in str(excinfo.value)
166
-
167
-
168
- def test_remove_plot_by_coordinates_error(qtbot, mocked_client):
169
- bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
170
- bec_figure.plot(row=0, col=0)
171
-
172
- with pytest.raises(ValueError) as excinfo:
173
- bec_figure.remove(0, 1)
174
- assert "No widget at coordinates (0, 1)" in str(excinfo.value)
175
-
176
-
177
- def test_remove_plot_by_providing_nothing(qtbot, mocked_client):
178
- bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
179
- bec_figure.plot(row=0, col=0)
180
-
181
- with pytest.raises(ValueError) as excinfo:
182
- bec_figure.remove()
183
- assert "Must provide either widget_id or coordinates for removal." in str(excinfo.value)
184
-
185
-
186
- # def test_change_theme(bec_figure): #TODO do no work at python 3.12
187
- # bec_figure.change_theme("dark")
188
- # assert bec_figure.config.theme == "dark"
189
- # assert bec_figure.backgroundBrush().color().name() == "#000000"
190
- # bec_figure.change_theme("light")
191
- # assert bec_figure.config.theme == "light"
192
- # assert bec_figure.backgroundBrush().color().name() == "#ffffff"
193
- # bec_figure.change_theme("dark")
194
- # assert bec_figure.config.theme == "dark"
195
- # assert bec_figure.backgroundBrush().color().name() == "#000000"
196
-
197
-
198
- def test_change_layout(qtbot, mocked_client):
199
- bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
200
- w1 = bec_figure.plot(row=0, col=0)
201
- w2 = bec_figure.plot(row=0, col=1)
202
- w3 = bec_figure.plot(row=1, col=0)
203
- w4 = bec_figure.plot(row=1, col=1)
204
-
205
- bec_figure.change_layout(max_columns=1)
206
-
207
- assert np.shape(bec_figure.grid) == (4, 1)
208
- assert bec_figure[0, 0] == w1
209
- assert bec_figure[1, 0] == w2
210
- assert bec_figure[2, 0] == w3
211
- assert bec_figure[3, 0] == w4
212
-
213
- bec_figure.change_layout(max_rows=1)
214
-
215
- assert np.shape(bec_figure.grid) == (1, 4)
216
- assert bec_figure[0, 0] == w1
217
- assert bec_figure[0, 1] == w2
218
- assert bec_figure[0, 2] == w3
219
- assert bec_figure[0, 3] == w4
220
-
221
-
222
- def test_clear_all(qtbot, mocked_client):
223
- bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
224
- bec_figure.plot(row=0, col=0)
225
- bec_figure.plot(row=0, col=1)
226
- bec_figure.plot(row=1, col=0)
227
- bec_figure.plot(row=1, col=1)
228
-
229
- bec_figure.clear_all()
230
-
231
- assert len(bec_figure._widgets) == 0
232
- assert np.shape(bec_figure.grid) == (0,)
233
-
234
-
235
- def test_shortcuts(qtbot, mocked_client):
236
- bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
237
- plt = bec_figure.plot(x_name="samx", y_name="bpm4i")
238
- im = bec_figure.image("eiger")
239
- motor_map = bec_figure.motor_map("samx", "samy")
240
-
241
- assert plt.config.widget_class == "BECWaveform"
242
- assert plt.__class__ == BECWaveform
243
- assert im.config.widget_class == "BECImageShow"
244
- assert im.__class__ == BECImageShow
245
- assert motor_map.config.widget_class == "BECMotorMap"
246
- assert motor_map.__class__ == BECMotorMap
247
-
248
-
249
- def test_plot_access_factory(qtbot, mocked_client):
250
- bec_figure = create_widget(qtbot, BECFigure, client=mocked_client)
251
- plt_00 = bec_figure.plot(x_name="samx", y_name="bpm4i")
252
- plt_01 = bec_figure.plot(x_name="samx", y_name="bpm4i", row=0, col=1)
253
- plt_10 = bec_figure.plot(new=True)
254
-
255
- assert bec_figure.widget_list[0] == plt_00
256
- assert bec_figure.widget_list[1] == plt_01
257
- assert bec_figure.widget_list[2] == plt_10
258
- assert bec_figure.axes(row=0, col=0) == plt_00
259
- assert bec_figure.axes(row=0, col=1) == plt_01
260
- assert bec_figure.axes(row=1, col=0) == plt_10
261
-
262
- assert len(plt_00.curves) == 1
263
- assert len(plt_01.curves) == 1
264
- assert len(plt_10.curves) == 0
265
-
266
- # update plt_00
267
- bec_figure.plot(x_name="samx", y_name="bpm3a")
268
- bec_figure.plot(x=[1, 2, 3], y=[1, 2, 3], row=0, col=0)
269
-
270
- assert len(plt_00.curves) == 3
@@ -1,63 +0,0 @@
1
- # pylint: disable=missing-function-docstring, missing-module-docstring, unused-import
2
- from unittest import mock
3
-
4
- import numpy as np
5
- import pytest
6
- from bec_lib import messages
7
- from qtpy.QtGui import QFontInfo
8
-
9
- from bec_widgets.widgets.figure import BECFigure
10
-
11
- from .client_mocks import mocked_client
12
- from .conftest import create_widget
13
-
14
-
15
- @pytest.fixture
16
- def bec_image_show(bec_figure):
17
- yield bec_figure.image("eiger")
18
-
19
-
20
- def test_on_image_update(qtbot, mocked_client):
21
- bec_image_show = create_widget(qtbot, BECFigure, client=mocked_client).image("eiger")
22
- data = np.random.rand(100, 100)
23
- msg = messages.DeviceMonitor2DMessage(device="eiger", data=data, metadata={"scan_id": "12345"})
24
- bec_image_show.on_image_update(msg.content, msg.metadata)
25
- img = bec_image_show.images[0]
26
- assert np.array_equal(img.get_data(), data)
27
-
28
-
29
- def test_autorange_on_image_update(qtbot, mocked_client):
30
- bec_image_show = create_widget(qtbot, BECFigure, client=mocked_client).image("eiger")
31
- # Check if autorange mode "mean" works, should be default
32
- data = np.random.rand(100, 100)
33
- msg = messages.DeviceMonitor2DMessage(device="eiger", data=data, metadata={"scan_id": "12345"})
34
- bec_image_show.on_image_update(msg.content, msg.metadata)
35
- img = bec_image_show.images[0]
36
- assert np.array_equal(img.get_data(), data)
37
- vmin = max(np.mean(data) - 2 * np.std(data), 0)
38
- vmax = np.mean(data) + 2 * np.std(data)
39
- assert np.isclose(img.color_bar.getLevels(), (vmin, vmax), rtol=(1e-5, 1e-5)).all()
40
- # Test general update with autorange True, mode "max"
41
- bec_image_show.set_autorange_mode("max")
42
- bec_image_show.on_image_update(msg.content, msg.metadata)
43
- img = bec_image_show.images[0]
44
- vmin = np.min(data)
45
- vmax = np.max(data)
46
- assert np.array_equal(img.get_data(), data)
47
- assert np.isclose(img.color_bar.getLevels(), (vmin, vmax), rtol=(1e-5, 1e-5)).all()
48
- # Change the input data, and switch to autorange False, colormap levels should stay untouched
49
- data *= 100
50
- msg = messages.DeviceMonitor2DMessage(device="eiger", data=data, metadata={"scan_id": "12345"})
51
- bec_image_show.set_autorange(False)
52
- bec_image_show.on_image_update(msg.content, msg.metadata)
53
- img = bec_image_show.images[0]
54
- assert np.array_equal(img.get_data(), data)
55
- assert np.isclose(img.color_bar.getLevels(), (vmin, vmax), rtol=(1e-3, 1e-3)).all()
56
- # Reactivate autorange, should now scale the new data
57
- bec_image_show.set_autorange(True)
58
- bec_image_show.set_autorange_mode("mean")
59
- bec_image_show.on_image_update(msg.content, msg.metadata)
60
- img = bec_image_show.images[0]
61
- vmin = max(np.mean(data) - 2 * np.std(data), 0)
62
- vmax = np.mean(data) + 2 * np.std(data)
63
- assert np.isclose(img.color_bar.getLevels(), (vmin, vmax), rtol=(1e-5, 1e-5)).all()
@@ -1,217 +0,0 @@
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
-
19
-
20
- @pytest.fixture
21
- def mock_image(image_widget):
22
- image_mock = MagicMock()
23
- image_widget._image = image_mock
24
- return image_mock
25
-
26
-
27
- def test_image_widget_init(image_widget):
28
- assert image_widget is not None
29
- assert image_widget.client is not None
30
- assert isinstance(image_widget, BECImageWidget)
31
- assert image_widget.config.widget_class == "BECImageWidget"
32
- assert image_widget._image is not None
33
-
34
- assert (
35
- image_widget.toolbar.widgets["monitor"].device_combobox.config.device_filter == "FakeDevice"
36
- )
37
- assert image_widget.toolbar.widgets["drag_mode"].action.isChecked() == True
38
- assert image_widget.toolbar.widgets["rectangle_mode"].action.isChecked() == False
39
- assert image_widget.toolbar.widgets["auto_range"].action.isChecked() == False
40
- assert image_widget.toolbar.widgets["auto_range_image"].action.isChecked() == True
41
- assert image_widget.toolbar.widgets["FFT"].action.isChecked() == False
42
- assert image_widget.toolbar.widgets["transpose"].action.isChecked() == False
43
- assert image_widget.toolbar.widgets["log"].action.isChecked() == False
44
-
45
-
46
- ###################################
47
- # Toolbar Actions
48
- ###################################
49
- def test_toolbar_connect_action(image_widget, mock_image, qtbot):
50
- combo = image_widget.toolbar.widgets["monitor"].device_combobox
51
- combo.setCurrentText("eiger")
52
- qtbot.wait(200)
53
- assert combo.currentText() == "eiger"
54
- action = image_widget.toolbar.widgets["connect"].action
55
- action.trigger()
56
- image_widget._image.image.assert_called_once_with(
57
- monitor="eiger",
58
- color_map="magma",
59
- color_bar="full",
60
- downsample=True,
61
- opacity=1.0,
62
- vrange=None,
63
- )
64
-
65
-
66
- def test_image_toolbar_drag_mode_action_triggered(image_widget, qtbot):
67
- action_drag = image_widget.toolbar.widgets["drag_mode"].action
68
- action_rectangle = image_widget.toolbar.widgets["rectangle_mode"].action
69
- action_drag.trigger()
70
- assert action_drag.isChecked() == True
71
- assert action_rectangle.isChecked() == False
72
-
73
-
74
- def test_image_toolbar_rectangle_mode_action_triggered(image_widget, qtbot):
75
- action_drag = image_widget.toolbar.widgets["drag_mode"].action
76
- action_rectangle = image_widget.toolbar.widgets["rectangle_mode"].action
77
- action_rectangle.trigger()
78
- assert action_drag.isChecked() == False
79
- assert action_rectangle.isChecked() == True
80
-
81
-
82
- def test_image_toolbar_auto_range(image_widget, mock_image):
83
- action = image_widget.toolbar.widgets["auto_range"].action
84
- action.trigger()
85
- image_widget._image.set_auto_range.assert_called_once_with(True, "xy")
86
-
87
-
88
- def test_image_toolbar_enable_mouse_pan_mode(qtbot, image_widget):
89
- action_drag = image_widget.toolbar.widgets["drag_mode"].action
90
- action_rectangle = image_widget.toolbar.widgets["rectangle_mode"].action
91
-
92
- mock_view_box = MagicMock()
93
- image_widget._image.plot_item.getViewBox = MagicMock(return_value=mock_view_box)
94
-
95
- image_widget.enable_mouse_pan_mode()
96
-
97
- assert action_drag.isChecked() == True
98
- assert action_rectangle.isChecked() == False
99
- mock_view_box.setMouseMode.assert_called_once_with(pg.ViewBox.PanMode)
100
-
101
-
102
- def test_image_toolbar_auto_range_image(image_widget, mock_image):
103
- action = image_widget.toolbar.widgets["auto_range_image"].action
104
- action.trigger()
105
- assert action.isChecked() == False
106
- image_widget._image.set_autorange.assert_called_once_with(False)
107
-
108
-
109
- def test_image_toolbar_FFT(image_widget, mock_image):
110
- action = image_widget.toolbar.widgets["FFT"].action
111
- action.trigger()
112
- assert action.isChecked() == True
113
- image_widget._image.set_fft.assert_called_once_with(True, None)
114
-
115
-
116
- def test_image_toolbar_log(image_widget, mock_image):
117
- action = image_widget.toolbar.widgets["log"].action
118
- action.trigger()
119
- assert action.isChecked() == True
120
- image_widget._image.set_log.assert_called_once_with(True, None)
121
-
122
-
123
- def test_image_toggle_transpose(image_widget, mock_image):
124
- action = image_widget.toolbar.widgets["transpose"].action
125
- action.trigger()
126
- assert action.isChecked() == True
127
- image_widget._image.set_transpose.assert_called_once_with(True, None)
128
-
129
-
130
- def test_image_toolbar_rotation(image_widget, mock_image):
131
- action_left = image_widget.toolbar.widgets["rotate_left"].action
132
- action_right = image_widget.toolbar.widgets["rotate_right"].action
133
-
134
- action_left.trigger()
135
- image_widget._image.set_rotation(1, None)
136
- action_right.trigger()
137
- image_widget._image.set_rotation(2, None)
138
-
139
- action_right.trigger()
140
- image_widget._image.set_rotation(1, None)
141
-
142
-
143
- ###################################
144
- # Wrapper methods for ImageShow
145
- ###################################
146
-
147
-
148
- def test_image_set_image(image_widget, mock_image):
149
- image_widget.image(monitor="image")
150
- image_widget._image.image.assert_called_once_with(
151
- monitor="image",
152
- color_map="magma",
153
- color_bar="full",
154
- downsample=True,
155
- opacity=1.0,
156
- vrange=None,
157
- )
158
-
159
-
160
- def test_image_vrange(image_widget, mock_image):
161
- image_widget.set_vrange(0, 1)
162
- image_widget._image.set_vrange.assert_called_once_with(0, 1, None)
163
-
164
-
165
- def test_image_set_color_map(image_widget, mock_image):
166
- image_widget.set_color_map("viridis")
167
- image_widget._image.set_color_map.assert_called_once_with("viridis", None)
168
-
169
-
170
- def test_image_widget_set_title(image_widget, mock_image):
171
- image_widget.set_title("Title Label")
172
- image_widget._image.set_title.assert_called_once_with("Title Label")
173
-
174
-
175
- def test_image_widget_set_x_label(image_widget, mock_image):
176
- image_widget.set_x_label("X Label")
177
- image_widget._image.set_x_label.assert_called_once_with("X Label")
178
-
179
-
180
- def test_image_widget_set_y_label(image_widget, mock_image):
181
- image_widget.set_y_label("Y Label")
182
- image_widget._image.set_y_label.assert_called_once_with("Y Label")
183
-
184
-
185
- def test_image_widget_set_x_scale(image_widget, mock_image):
186
- image_widget.set_x_scale("linear")
187
- image_widget._image.set_x_scale.assert_called_once_with("linear")
188
-
189
-
190
- def test_image_widget_set_y_scale(image_widget, mock_image):
191
- image_widget.set_y_scale("log")
192
- image_widget._image.set_y_scale.assert_called_once_with("log")
193
-
194
-
195
- def test_image_widget_set_x_lim(image_widget, mock_image):
196
- image_widget.set_x_lim((0, 10))
197
- image_widget._image.set_x_lim.assert_called_once_with((0, 10))
198
-
199
-
200
- def test_image_widget_set_y_lim(image_widget, mock_image):
201
- image_widget.set_y_lim((0, 10))
202
- image_widget._image.set_y_lim.assert_called_once_with((0, 10))
203
-
204
-
205
- def test_image_widget_set_grid(image_widget, mock_image):
206
- image_widget.set_grid(True, False)
207
- image_widget._image.set_grid.assert_called_once_with(True, False)
208
-
209
-
210
- def test_image_widget_lock_aspect_ratio(image_widget, mock_image):
211
- image_widget.lock_aspect_ratio(True)
212
- image_widget._image.lock_aspect_ratio.assert_called_once_with(True)
213
-
214
-
215
- def test_image_widget_export(image_widget, mock_image):
216
- image_widget.export()
217
- image_widget._image.export.assert_called_once()