bec-widgets 0.44.4__py3-none-any.whl → 0.45.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.
- bec_widgets/cli/client.py +105 -5
- bec_widgets/cli/client_utils.py +4 -4
- bec_widgets/cli/generate_cli.py +6 -4
- bec_widgets/cli/server.py +2 -3
- bec_widgets/examples/__init__.py +1 -1
- bec_widgets/examples/eiger_plot/eiger_plot.py +3 -11
- bec_widgets/examples/mca_readout/mca_plot.py +21 -24
- bec_widgets/examples/mca_readout/mca_sim.py +7 -12
- bec_widgets/examples/motor_movement/__init__.py +1 -1
- bec_widgets/examples/motor_movement/motor_control_compilations.py +3 -8
- bec_widgets/examples/motor_movement/motor_controller.ui +1 -1
- bec_widgets/examples/motor_movement/motor_example.py +13 -14
- bec_widgets/examples/stream_plot/stream_plot.py +5 -4
- bec_widgets/utils/__init__.py +5 -5
- bec_widgets/utils/bec_connector.py +1 -1
- bec_widgets/utils/bec_dispatcher.py +1 -2
- bec_widgets/utils/bec_table.py +1 -1
- bec_widgets/utils/crosshair.py +2 -1
- bec_widgets/utils/validator_delegate.py +1 -1
- bec_widgets/utils/widget_io.py +6 -6
- bec_widgets/utils/yaml_dialog.py +1 -0
- bec_widgets/validation/monitor_config_validator.py +6 -6
- bec_widgets/widgets/__init__.py +7 -8
- bec_widgets/widgets/editor/editor.py +6 -14
- bec_widgets/widgets/figure/__init__.py +1 -1
- bec_widgets/widgets/figure/figure.py +74 -4
- bec_widgets/widgets/monitor/__init__.py +0 -1
- bec_widgets/widgets/monitor/config_dialog.py +7 -8
- bec_widgets/widgets/monitor/monitor.py +16 -26
- bec_widgets/widgets/monitor_scatter_2D/monitor_scatter_2D.py +11 -19
- bec_widgets/widgets/motor_control/__init__.py +2 -2
- bec_widgets/widgets/motor_control/motor_control.py +11 -10
- bec_widgets/widgets/motor_map/motor_map.py +2 -3
- bec_widgets/widgets/plots/__init__.py +4 -3
- bec_widgets/widgets/plots/image.py +7 -6
- bec_widgets/widgets/plots/motor_map.py +423 -0
- bec_widgets/widgets/plots/plot_base.py +1 -2
- bec_widgets/widgets/plots/waveform1d.py +24 -23
- bec_widgets/widgets/scan_control/scan_control.py +12 -12
- bec_widgets/widgets/toolbar/toolbar.py +2 -4
- {bec_widgets-0.44.4.dist-info → bec_widgets-0.45.0.dist-info}/METADATA +2 -1
- bec_widgets-0.45.0.dist-info/RECORD +98 -0
- tests/client_mocks.py +76 -30
- tests/conftest.py +2 -1
- tests/test_bec_connector.py +2 -1
- tests/test_bec_dispatcher.py +3 -4
- tests/test_bec_figure.py +14 -2
- tests/test_bec_monitor.py +7 -76
- tests/test_bec_monitor_scatter2D.py +8 -32
- tests/test_bec_motor_map.py +125 -0
- tests/test_config_dialog.py +4 -66
- tests/test_editor.py +2 -4
- tests/test_eiger_plot.py +2 -0
- tests/test_generate_cli_client.py +4 -2
- tests/test_motor_control.py +25 -92
- tests/test_motor_map.py +10 -66
- tests/test_plot_base.py +1 -0
- tests/test_scan_control.py +1 -1
- tests/test_stream_plot.py +2 -2
- tests/test_validator_errors.py +5 -4
- tests/test_waveform1d.py +31 -12
- tests/test_widget_io.py +1 -8
- tests/test_yaml_dialog.py +2 -1
- bec_widgets-0.44.4.dist-info/RECORD +0 -96
- {bec_widgets-0.44.4.dist-info → bec_widgets-0.45.0.dist-info}/LICENSE +0 -0
- {bec_widgets-0.44.4.dist-info → bec_widgets-0.45.0.dist-info}/WHEEL +0 -0
- {bec_widgets-0.44.4.dist-info → bec_widgets-0.45.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,98 @@
|
|
1
|
+
bec_widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
bec_widgets/cli/__init__.py,sha256=yFyAmDteCcndbReunhnrfDib6JujQ7-BKWeVvuU0Ylw,30
|
3
|
+
bec_widgets/cli/client.py,sha256=J3yvhteGky9XHXMoyN0am75uAE4qeo7Oj_dZbdtMHRM,37300
|
4
|
+
bec_widgets/cli/client_utils.py,sha256=8tVOmAMo5x0tUywTfivvCt8n0tJoT5WzoCa3GtsZ-qE,9694
|
5
|
+
bec_widgets/cli/generate_cli.py,sha256=QqTacqaG3zYi-Zmun62j-4Tv-Az5rDbvFXA2ESFjWZ0,4010
|
6
|
+
bec_widgets/cli/server.py,sha256=4552dbbdJlalIllQGJFR3AsN0iLl5Qs23BAeqQiof0s,4721
|
7
|
+
bec_widgets/examples/__init__.py,sha256=WWQ0cu7m8sA4Ehy-DWdTIqSISjaHsbxhsNmNrMnhDZU,202
|
8
|
+
bec_widgets/examples/eiger_plot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
+
bec_widgets/examples/eiger_plot/eiger_plot.py,sha256=Uxl2Usf8jEzaX7AT8zVqa1x8ZIEgI1HmazSlb-tRFWE,10359
|
10
|
+
bec_widgets/examples/eiger_plot/eiger_plot.ui,sha256=grHfnO3OG_lelJhdRsnA0badCvRdDunPrIMIyNQ5N-w,5809
|
11
|
+
bec_widgets/examples/mca_readout/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
|
+
bec_widgets/examples/mca_readout/mca_plot.py,sha256=do7mSK_nzHtojRiMi8JoN_Rckg9yfjYYWz2S_Nl3xbE,5079
|
13
|
+
bec_widgets/examples/mca_readout/mca_sim.py,sha256=Dv_yYJ-uCmfMTBX0l-yVZqn-UHpfo8L3jNZ-JOPtzHk,867
|
14
|
+
bec_widgets/examples/motor_movement/__init__.py,sha256=LzPJkxLAxOsZCbXR-fRCPmeYobp7Yqds6tDxW4W1gSw,214
|
15
|
+
bec_widgets/examples/motor_movement/config_example.yaml,sha256=YT8Bl3ViTaP03cX9X8kIgWnkoxaQOFqS-oRrclGS2hc,356
|
16
|
+
bec_widgets/examples/motor_movement/csax_bec_config.yaml,sha256=cqhzwfIhFgHfCt90oVW3no8aVlWg7V42t4iiJCnydSw,146
|
17
|
+
bec_widgets/examples/motor_movement/csaxs_config.yaml,sha256=poNndp-1ptdnriIJ_RTnbAimFlOJ45VdxfkclGEQlgc,344
|
18
|
+
bec_widgets/examples/motor_movement/motor_control_compilations.py,sha256=HIDauBIkNmKB8oCuGy_toNkIYxsdBCEniK2zj6vZFVg,8979
|
19
|
+
bec_widgets/examples/motor_movement/motor_controller.ui,sha256=83XX6NGILwntoUIghvzWnMuGf80O8khK3SduVKTAEFM,29105
|
20
|
+
bec_widgets/examples/motor_movement/motor_example.py,sha256=_0S_VnksFhwb3WM3dQuI9BUrn8UYzXJg5q6ayPCsaoI,53414
|
21
|
+
bec_widgets/examples/stream_plot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
|
+
bec_widgets/examples/stream_plot/line_plot.ui,sha256=rgNfhOXu1AcWF0P6wnOlmJKDjS-VIoduVrREvmzJQR8,4626
|
23
|
+
bec_widgets/examples/stream_plot/stream_plot.py,sha256=ZzvJm4T--oxmAGj4IeDWsNuBrWq_MyY04vI_OFJYs4A,12184
|
24
|
+
bec_widgets/simulations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
|
+
bec_widgets/utils/__init__.py,sha256=-szVMxtb6Aoz5_e6Py652ExbGnmSVjd0w6ULBvumguk,353
|
26
|
+
bec_widgets/utils/bec_connector.py,sha256=h4GGoaPSsdBolG5n8uCVWILHTe46NckTQqdBHBPlRaE,3652
|
27
|
+
bec_widgets/utils/bec_dispatcher.py,sha256=nzocqIcVzJpWP5hTnAx0l-M6Wm7pU2sfW5KmQrMVbu0,7365
|
28
|
+
bec_widgets/utils/bec_table.py,sha256=Xy5qM343K8EvEpB4g_129b63yo1wdEvEY3wqxB_p_Iw,716
|
29
|
+
bec_widgets/utils/colors.py,sha256=JsLxzkxbw-I8GIuvnIKyiM83n0edhyMG2Fa4Ffm62ww,2392
|
30
|
+
bec_widgets/utils/crosshair.py,sha256=5gG4G6jjtp6Bd1Y5EySHP2EkmtR4mYdxLCgVtx9fokE,9406
|
31
|
+
bec_widgets/utils/ctrl_c.py,sha256=NMJlPDZcuqMUGykyhuZY5Ibed4yRI1K_uh16z2MmlXQ,1198
|
32
|
+
bec_widgets/utils/entry_validator.py,sha256=nPdu87Ry9Vka2QVbOLW4YbLJwEWpRYypNl7hlXaMaHM,614
|
33
|
+
bec_widgets/utils/rpc_decorator.py,sha256=pIvtqySQLnuS7l2Ti_UAe4WX7CRivZnsE5ZdKAihxh0,479
|
34
|
+
bec_widgets/utils/validator_delegate.py,sha256=Emj1WF6W8Ke1ruBWUfmHdVJpmOSPezuOt4zvQTay_44,442
|
35
|
+
bec_widgets/utils/widget_io.py,sha256=JKl508VnqQSxcaHqKaoBQ1TWSOm3pXhxQGx7iF_pRA0,10875
|
36
|
+
bec_widgets/utils/yaml_dialog.py,sha256=soZI8BOjlqYGfYDga70MEvkxJTsktq4y7B3uog2cSik,1851
|
37
|
+
bec_widgets/validation/__init__.py,sha256=ismd1bU5FhFb0zFPwNKuq7oT48G4Y2GfaMZOdNKUtGk,132
|
38
|
+
bec_widgets/validation/monitor_config_validator.py,sha256=M9p8K_nvxicnqJB4X7j90R377WHYVH4wMCtSXsRI51M,8150
|
39
|
+
bec_widgets/widgets/__init__.py,sha256=QNCuDcg0o3uvGbf74qXeFjEsgIzOeEcd1hoWabJ4tKQ,437
|
40
|
+
bec_widgets/widgets/editor/__init__.py,sha256=5mBdFYi_IpygCz81kbLEZUWhd1b6oqiO3nASejuV_ug,30
|
41
|
+
bec_widgets/widgets/editor/editor.py,sha256=pIIYLPqqqhXqT11Xj10cyGEiy-ieNGE4ZujN5lf0e68,15110
|
42
|
+
bec_widgets/widgets/figure/__init__.py,sha256=3hGx_KOV7QHCYAV06aNuUgKq4QIYCjUTad-DrwkUaBM,44
|
43
|
+
bec_widgets/widgets/figure/figure.py,sha256=-3SJu93gE73ttrfxD9NGPRmgvaZjH0jOX_7ovhrHXck,32454
|
44
|
+
bec_widgets/widgets/figure/figure_debug_minimal.ui,sha256=GodXBvBvs5QAUsHbo3pcxR4o51Tvce4DTqpTluk3hOs,742
|
45
|
+
bec_widgets/widgets/monitor/__init__.py,sha256=afXuZcBOxNAuYdCkIQXX5J60R5A3Q_86lNEW2vpFtPI,32
|
46
|
+
bec_widgets/widgets/monitor/config_dialog.py,sha256=Z1a4WRIVlfEGdwC-QG25kba2EHCZWi5J843tBVZlWiI,20275
|
47
|
+
bec_widgets/widgets/monitor/config_dialog.ui,sha256=ISMcF7CLTAMXhfZh2Yv5yezzAjMtb9fxY1pmX4B_jCg,5932
|
48
|
+
bec_widgets/widgets/monitor/monitor.py,sha256=ET5O48kqRlwd8_jCMCrp8QwnL8LvoNgb5nQmVw36pKg,30219
|
49
|
+
bec_widgets/widgets/monitor/tab_template.ui,sha256=JVB5fkzVhTjxMn9EdZCXsnfzBkeZpFMdTRuqTNSDSSo,4904
|
50
|
+
bec_widgets/widgets/monitor_scatter_2D/__init__.py,sha256=hgiRKV5PBdesYLFbLmYb-qfqNTIGwzpdQFvkLi6-qnE,52
|
51
|
+
bec_widgets/widgets/monitor_scatter_2D/monitor_scatter_2D.py,sha256=AKx3SUKxbyUxpXAHG5T-_horr02coKHbcMQppRZ_eEY,13108
|
52
|
+
bec_widgets/widgets/motor_control/__init__.py,sha256=_4-G9AKcEnOyS6qVE26meRw3grEohNeMzACNMU5Sig0,153
|
53
|
+
bec_widgets/widgets/motor_control/motor_control.py,sha256=sfH_uGes4B3mOFPP9BYVMtqMSCFD5fWJNQwNxV06288,42458
|
54
|
+
bec_widgets/widgets/motor_control/motor_control_absolute.ui,sha256=nR3p6oevAkIBTLW5wM_zYOVWsCAUgeMZdRm10Q77COE,4126
|
55
|
+
bec_widgets/widgets/motor_control/motor_control_relative.ui,sha256=PulNJNiws7TRAxHM2snNyvlmQ0tRShdArHmtaC85h4U,8684
|
56
|
+
bec_widgets/widgets/motor_control/motor_control_selection.ui,sha256=vXXpvNWuL6xyHhW7Lx1zmVFX-95Z5AXGlhKQD2HmM1A,1779
|
57
|
+
bec_widgets/widgets/motor_control/motor_control_table.ui,sha256=t6aRKiSmutMfp0AyupavbCs0cal-FANEnlKQiPzC9PQ,2792
|
58
|
+
bec_widgets/widgets/motor_map/__init__.py,sha256=K3c-3A_LbxK0UJ0_bV3opL-wGLTwBLendsJXsg8GAqE,32
|
59
|
+
bec_widgets/widgets/motor_map/motor_map.py,sha256=A7VOs8RAiXaLZF4_oxOYJX5BwMhRvir0k0u5eEPFtLc,21909
|
60
|
+
bec_widgets/widgets/plots/__init__.py,sha256=ncGc6re47T9Bq75RQrPrk2rX2V89QZWRFOwZjmvkQPw,241
|
61
|
+
bec_widgets/widgets/plots/image.py,sha256=Ty-8etIYBQl1MJLcuwCtlLUcAuXbxBq4RLDikbTL34c,31748
|
62
|
+
bec_widgets/widgets/plots/motor_map.py,sha256=yBqVvLgEQhiIpQyvmsoTUToEyLblVmS2sTST7N8hNQA,15115
|
63
|
+
bec_widgets/widgets/plots/plot_base.py,sha256=tF0oamgCVIXFrfD8jnMVTltkzYLLSQ0Dq9HAG57Ji3E,8446
|
64
|
+
bec_widgets/widgets/plots/waveform1d.py,sha256=RbI5dQlbAaC4A1WuQLS1DWpk5UjeELpaUEvHkFvZAbA,25631
|
65
|
+
bec_widgets/widgets/scan_control/__init__.py,sha256=IOfHl15vxb_uC6KN62-PeUzbBha_vQyqkkXbJ2HU674,38
|
66
|
+
bec_widgets/widgets/scan_control/scan_control.py,sha256=tbO9tbVynRvs4VCxTZ4ZFBDTVAojIr-zkl70vuHbWgw,17116
|
67
|
+
bec_widgets/widgets/toolbar/__init__.py,sha256=d-TP4_cr_VbpwreMM4ePnfZ5YXsEPQ45ibEf75nuGoE,36
|
68
|
+
bec_widgets/widgets/toolbar/toolbar.py,sha256=sxz7rbc8XNPS6n2WMObF4-2PqdYfPxVtsOZEGV6mqa0,5124
|
69
|
+
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
70
|
+
tests/client_mocks.py,sha256=925yW3vFnS8h6ym_4kpgX299WGVeObkGneuiXNWRE7s,3596
|
71
|
+
tests/conftest.py,sha256=wMFVnerrLZjpi-OnPf7Ugah_DCb51QD1WWcbR4e_M6k,1055
|
72
|
+
tests/test_bec_connector.py,sha256=f2XXGGw3NoZLIUrDuZuEWwF_ttOYmmquCgUrV5XkIOY,1951
|
73
|
+
tests/test_bec_dispatcher.py,sha256=vWQGdUyMvssrOyiVxdsOpErOh4awX_NSQWvKSBoRfAI,9223
|
74
|
+
tests/test_bec_figure.py,sha256=-2KYedk32pCsXNmAN0OFUrQT101YV3rrSL0ET3KXjjA,7464
|
75
|
+
tests/test_bec_monitor.py,sha256=mN7gBY7oXY6j65zzihpy8r-FvwVoCQlie3F6SoVq0mo,7042
|
76
|
+
tests/test_bec_monitor_scatter2D.py,sha256=UYs0pe9uBX7GpFVkhxw-Hx_MwTz7NKMtWIBqONTZ1JI,5797
|
77
|
+
tests/test_bec_motor_map.py,sha256=5D-xPQQ731Q6wsEzAmqJqoy_FpHtlK1siwqql8sJ0p0,4613
|
78
|
+
tests/test_config_dialog.py,sha256=5uNGcpvrx8qDdMwFCTXr8HMzFZF4rFi-ZHoDpMxGMf8,6955
|
79
|
+
tests/test_crosshair.py,sha256=d7fX-ymboZPALNqqiAj86PZ96llmGZ_3jf0yjVP0S94,5039
|
80
|
+
tests/test_editor.py,sha256=TED5k1xFJHRZ4KDAg2VxSRu_hMJnra-lbAmVwsDicsM,6784
|
81
|
+
tests/test_eiger_plot.py,sha256=bWnKBQid0YcLMQeBLy6ojb4ZpwTG-rFVT0kMg9Y08p8,4427
|
82
|
+
tests/test_generate_cli_client.py,sha256=BdpTZMNUFOBJa2e-rme9AJUoXfueYyLiUCOpGi3SNvc,2400
|
83
|
+
tests/test_motor_control.py,sha256=jdTG35z3jOL9XCAIDNIGfdv60vcwGLHa3KJjKqJkoZw,20322
|
84
|
+
tests/test_motor_map.py,sha256=UEjmtIYI2mxq9BUeopqoqNNy7UiPJEts9h45ufsFcrA,5979
|
85
|
+
tests/test_plot_base.py,sha256=bOdlgAxh9oKk5PwiQ_MSFmzr44uJ61Tlg242RCIhl5c,2610
|
86
|
+
tests/test_scan_control.py,sha256=e6_YpyxcayK35jXBSfxinGNL_8G-jcrWap25eg3z4QI,7560
|
87
|
+
tests/test_stream_plot.py,sha256=LNCYIj9CafremGaz-DwDktCRJRrjgfOdVewCUwwZE5s,5843
|
88
|
+
tests/test_validator_errors.py,sha256=NFxyv0TIOXeZKZRRUBfVQ7bpunwY4KkG95yTUdQmvns,3532
|
89
|
+
tests/test_waveform1d.py,sha256=GzlQTAjbg35mMKhopLCiHy3fIx0ld6WTr46ZuMTeSTE,13644
|
90
|
+
tests/test_widget_io.py,sha256=FeL3ZYSBQnRt6jxj8VGYw1cmcicRQyHKleahw7XIyR0,3475
|
91
|
+
tests/test_yaml_dialog.py,sha256=HNrqferkdg02-9ieOhhI2mr2Qvt7GrYgXmQ061YCTbg,5794
|
92
|
+
tests/test_msgs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
93
|
+
tests/test_msgs/available_scans_message.py,sha256=m_z97hIrjHXXMa2Ex-UvsPmTxOYXfjxyJaGkIY6StTY,46532
|
94
|
+
bec_widgets-0.45.0.dist-info/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
|
95
|
+
bec_widgets-0.45.0.dist-info/METADATA,sha256=9EPs7EAqxS-MNM5INN1K7kdqlawrd_oeyHwDhotp5wI,3714
|
96
|
+
bec_widgets-0.45.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
97
|
+
bec_widgets-0.45.0.dist-info/top_level.txt,sha256=EXCwhJYmXmd1DjYYL3hrGsddX-97IwYSiIHrf27FFVk,18
|
98
|
+
bec_widgets-0.45.0.dist-info/RECORD,,
|
tests/client_mocks.py
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# pylint: disable = no-name-in-module,missing-class-docstring, missing-module-docstring
|
2
|
+
from unittest.mock import MagicMock, patch
|
2
3
|
|
3
4
|
import pytest
|
4
|
-
from
|
5
|
+
from bec_lib.device import Positioner
|
6
|
+
from bec_lib.devicemanager import DeviceContainer
|
5
7
|
|
6
8
|
|
7
9
|
class FakeDevice:
|
@@ -11,7 +13,7 @@ class FakeDevice:
|
|
11
13
|
self.name = name
|
12
14
|
self.enabled = enabled
|
13
15
|
self.signals = {self.name: {"value": 1.0}}
|
14
|
-
self.description = {self.name: {"source": self.name}}
|
16
|
+
self.description = {self.name: {"source": self.name, "dtype": "number", "shape": []}}
|
15
17
|
|
16
18
|
def __contains__(self, item):
|
17
19
|
return item == self.name
|
@@ -37,41 +39,85 @@ class FakeDevice:
|
|
37
39
|
return self.description
|
38
40
|
|
39
41
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
42
|
+
class FakePositioner(FakeDevice):
|
43
|
+
def __init__(self, name, enabled=True, limits=None, read_value=1.0):
|
44
|
+
super().__init__(name, enabled)
|
45
|
+
self.limits = limits if limits is not None else [0, 0]
|
46
|
+
self.read_value = read_value
|
47
|
+
|
48
|
+
def set_read_value(self, value):
|
49
|
+
self.read_value = value
|
50
|
+
|
51
|
+
def read(self):
|
52
|
+
return {self.name: {"value": self.read_value}}
|
53
|
+
|
54
|
+
def set_limits(self, limits):
|
55
|
+
self.limits = limits
|
56
|
+
|
57
|
+
def move(self, value, relative=False):
|
58
|
+
"""Simulates moving the device to a new position."""
|
59
|
+
if relative:
|
60
|
+
self.read_value += value
|
61
|
+
else:
|
62
|
+
self.read_value = value
|
63
|
+
# Respect the limits
|
64
|
+
self.read_value = max(min(self.read_value, self.limits[1]), self.limits[0])
|
65
|
+
|
66
|
+
@property
|
67
|
+
def readback(self):
|
68
|
+
return MagicMock(get=MagicMock(return_value=self.read_value))
|
69
|
+
|
70
|
+
|
71
|
+
class DMMock:
|
72
|
+
def __init__(self):
|
73
|
+
self.devices = DeviceContainer()
|
74
|
+
|
75
|
+
def add_devives(self, devices: list):
|
76
|
+
for device in devices:
|
77
|
+
self.devices[device.name] = device
|
78
|
+
|
79
|
+
|
80
|
+
DEVICES = [
|
81
|
+
FakePositioner("samx", limits=[-10, 10], read_value=2.0),
|
82
|
+
FakePositioner("samy", limits=[-5, 5], read_value=3.0),
|
83
|
+
FakePositioner("aptrx", limits=None, read_value=4.0),
|
84
|
+
FakePositioner("aptry", limits=None, read_value=5.0),
|
85
|
+
FakeDevice("gauss_bpm"),
|
86
|
+
FakeDevice("gauss_adc1"),
|
87
|
+
FakeDevice("gauss_adc2"),
|
88
|
+
FakeDevice("gauss_adc3"),
|
89
|
+
FakeDevice("bpm4i"),
|
90
|
+
FakeDevice("bpm3a"),
|
91
|
+
FakeDevice("bpm3i"),
|
92
|
+
]
|
47
93
|
|
48
94
|
|
49
95
|
@pytest.fixture(scope="function")
|
50
96
|
def mocked_client():
|
51
|
-
# Create a dictionary of mocked devices
|
52
|
-
device_names = [
|
53
|
-
"samx",
|
54
|
-
"samy",
|
55
|
-
"gauss_bpm",
|
56
|
-
"gauss_adc1",
|
57
|
-
"gauss_adc2",
|
58
|
-
"gauss_adc3",
|
59
|
-
"bpm4i",
|
60
|
-
"bpm3a",
|
61
|
-
"bpm3i",
|
62
|
-
]
|
63
|
-
mocked_devices = {name: get_mocked_device(name) for name in device_names}
|
64
|
-
|
65
97
|
# Create a MagicMock object
|
66
98
|
client = MagicMock()
|
67
99
|
|
68
100
|
# Mock the device_manager.devices attribute
|
69
|
-
client.device_manager
|
70
|
-
client.device_manager.
|
71
|
-
|
101
|
+
client.device_manager = DMMock()
|
102
|
+
client.device_manager.add_devives(DEVICES)
|
103
|
+
|
104
|
+
def mock_mv(*args, relative=False):
|
105
|
+
# Extracting motor and value pairs
|
106
|
+
for i in range(0, len(args), 2):
|
107
|
+
motor = args[i]
|
108
|
+
value = args[i + 1]
|
109
|
+
motor.move(value, relative=relative)
|
110
|
+
return MagicMock(wait=MagicMock())
|
111
|
+
|
112
|
+
client.scans = MagicMock(mv=mock_mv)
|
113
|
+
|
114
|
+
# Ensure isinstance check for Positioner passes
|
115
|
+
original_isinstance = isinstance
|
72
116
|
|
73
|
-
|
74
|
-
|
75
|
-
|
117
|
+
def isinstance_mock(obj, class_info):
|
118
|
+
if class_info == Positioner and isinstance(obj, FakePositioner):
|
119
|
+
return True
|
120
|
+
return original_isinstance(obj, class_info)
|
76
121
|
|
77
|
-
|
122
|
+
with patch("builtins.isinstance", new=isinstance_mock):
|
123
|
+
yield client
|
tests/conftest.py
CHANGED
tests/test_bec_connector.py
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# pylint: disable = no-name-in-module,missing-class-docstring, missing-module-docstring
|
2
2
|
import pytest
|
3
3
|
|
4
|
-
from .client_mocks import mocked_client
|
5
4
|
from bec_widgets.utils import BECConnector, ConnectionConfig
|
6
5
|
|
6
|
+
from .client_mocks import mocked_client
|
7
|
+
|
7
8
|
|
8
9
|
@pytest.fixture
|
9
10
|
def bec_connector(mocked_client):
|
tests/test_bec_dispatcher.py
CHANGED
@@ -2,11 +2,10 @@
|
|
2
2
|
from unittest.mock import Mock
|
3
3
|
|
4
4
|
import pytest
|
5
|
-
from bec_lib.messages import ScanMessage
|
6
5
|
from bec_lib.connector import MessageObject
|
6
|
+
from bec_lib.messages import ScanMessage
|
7
7
|
|
8
|
-
|
9
|
-
msg = MessageObject(topic="", value=ScanMessage(point_id=0, scanID=0, data={}))
|
8
|
+
msg = MessageObject(topic="", value=ScanMessage(point_id=0, scan_id=0, data={}))
|
10
9
|
|
11
10
|
|
12
11
|
@pytest.fixture(name="consumer")
|
@@ -206,7 +205,7 @@ def test_connect_one_slot_multiple_topics_single_callback(bec_dispatcher, consum
|
|
206
205
|
# Simulate messages being published on each topic
|
207
206
|
for topic in topics:
|
208
207
|
msg_with_topic = MessageObject(
|
209
|
-
topic=topic, value=ScanMessage(point_id=0,
|
208
|
+
topic=topic, value=ScanMessage(point_id=0, scan_id=0, data={})
|
210
209
|
)
|
211
210
|
consumer.register.call_args.kwargs["cb"](msg_with_topic)
|
212
211
|
|
tests/test_bec_figure.py
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
# pylint: disable=missing-function-docstring, missing-module-docstring, unused-import
|
2
2
|
import os
|
3
|
+
from unittest.mock import MagicMock
|
3
4
|
|
4
5
|
import numpy as np
|
5
6
|
import pytest
|
6
|
-
|
7
|
+
|
8
|
+
from bec_widgets.widgets import BECFigure, BECMotorMap, BECWaveform1D
|
9
|
+
from bec_widgets.widgets.plots import BECImageShow
|
7
10
|
|
8
11
|
from .client_mocks import mocked_client
|
9
|
-
from bec_widgets.widgets import BECFigure
|
10
12
|
|
11
13
|
|
12
14
|
@pytest.fixture
|
@@ -65,6 +67,16 @@ def test_bec_figure_add_remove_plot(bec_figure):
|
|
65
67
|
assert bec_figure._widgets["widget_2"].config.widget_class == "BECWaveform1D"
|
66
68
|
|
67
69
|
|
70
|
+
def test_add_different_types_of_widgets(bec_figure):
|
71
|
+
plt = bec_figure.plot("samx", "bpm4i")
|
72
|
+
im = bec_figure.image("eiger")
|
73
|
+
motor_map = bec_figure.motor_map("samx", "samy")
|
74
|
+
|
75
|
+
assert plt.__class__ == BECWaveform1D
|
76
|
+
assert im.__class__ == BECImageShow
|
77
|
+
assert motor_map.__class__ == BECMotorMap
|
78
|
+
|
79
|
+
|
68
80
|
def test_access_widgets_access_errors(bec_figure):
|
69
81
|
bec_figure.add_plot(row=0, col=0)
|
70
82
|
|
tests/test_bec_monitor.py
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
# pylint: disable = no-name-in-module,missing-class-docstring, missing-module-docstring
|
2
2
|
import os
|
3
|
-
import
|
3
|
+
from unittest.mock import MagicMock
|
4
4
|
|
5
5
|
import pytest
|
6
|
-
|
6
|
+
import yaml
|
7
7
|
|
8
8
|
from bec_widgets.widgets import BECMonitor
|
9
9
|
|
10
|
+
from .client_mocks import mocked_client
|
11
|
+
|
10
12
|
|
11
13
|
def load_test_config(config_name):
|
12
14
|
"""Helper function to load config from yaml file."""
|
@@ -16,69 +18,6 @@ def load_test_config(config_name):
|
|
16
18
|
return config
|
17
19
|
|
18
20
|
|
19
|
-
class FakeDevice:
|
20
|
-
"""Fake minimal positioner class for testing."""
|
21
|
-
|
22
|
-
def __init__(self, name, enabled=True):
|
23
|
-
self.name = name
|
24
|
-
self.enabled = enabled
|
25
|
-
self.signals = {self.name: {"value": 1.0}}
|
26
|
-
self.description = {self.name: {"source": self.name}}
|
27
|
-
|
28
|
-
def __contains__(self, item):
|
29
|
-
return item == self.name
|
30
|
-
|
31
|
-
@property
|
32
|
-
def _hints(self):
|
33
|
-
return [self.name]
|
34
|
-
|
35
|
-
def set_value(self, fake_value: float = 1.0) -> None:
|
36
|
-
"""
|
37
|
-
Setup fake value for device readout
|
38
|
-
Args:
|
39
|
-
fake_value(float): Desired fake value
|
40
|
-
"""
|
41
|
-
self.signals[self.name]["value"] = fake_value
|
42
|
-
|
43
|
-
def describe(self) -> dict:
|
44
|
-
"""
|
45
|
-
Get the description of the device
|
46
|
-
Returns:
|
47
|
-
dict: Description of the device
|
48
|
-
"""
|
49
|
-
return self.description
|
50
|
-
|
51
|
-
|
52
|
-
def get_mocked_device(device_name: str):
|
53
|
-
"""
|
54
|
-
Helper function to mock the devices
|
55
|
-
Args:
|
56
|
-
device_name(str): Name of the device to mock
|
57
|
-
"""
|
58
|
-
return FakeDevice(name=device_name, enabled=True)
|
59
|
-
|
60
|
-
|
61
|
-
@pytest.fixture(scope="function")
|
62
|
-
def mocked_client():
|
63
|
-
# Create a dictionary of mocked devices
|
64
|
-
device_names = ["samx", "gauss_bpm", "gauss_adc1", "gauss_adc2", "gauss_adc3", "bpm4i"]
|
65
|
-
mocked_devices = {name: get_mocked_device(name) for name in device_names}
|
66
|
-
|
67
|
-
# Create a MagicMock object
|
68
|
-
client = MagicMock()
|
69
|
-
|
70
|
-
# Mock the device_manager.devices attribute
|
71
|
-
client.device_manager.devices = MagicMock()
|
72
|
-
client.device_manager.devices.__getitem__.side_effect = lambda x: mocked_devices.get(x)
|
73
|
-
client.device_manager.devices.__contains__.side_effect = lambda x: x in mocked_devices
|
74
|
-
|
75
|
-
# Set each device as an attribute of the mock
|
76
|
-
for name, device in mocked_devices.items():
|
77
|
-
setattr(client.device_manager.devices, name, device)
|
78
|
-
|
79
|
-
return client
|
80
|
-
|
81
|
-
|
82
21
|
@pytest.fixture(scope="function")
|
83
22
|
def monitor(bec_dispatcher, qtbot, mocked_client):
|
84
23
|
# client = MagicMock()
|
@@ -126,12 +65,7 @@ def test_on_config_update(monitor, config_initial, config_update):
|
|
126
65
|
@pytest.mark.parametrize(
|
127
66
|
"config_name, expected_num_columns, expected_plot_names, expected_coordinates",
|
128
67
|
[
|
129
|
-
(
|
130
|
-
"config_device",
|
131
|
-
1,
|
132
|
-
["BPM4i plots vs samx", "Gauss plots vs samx"],
|
133
|
-
[(0, 0), (1, 0)],
|
134
|
-
),
|
68
|
+
("config_device", 1, ["BPM4i plots vs samx", "Gauss plots vs samx"], [(0, 0), (1, 0)]),
|
135
69
|
(
|
136
70
|
"config_scan",
|
137
71
|
3,
|
@@ -186,7 +120,7 @@ msg_1 = {
|
|
186
120
|
"gauss_adc1": {"gauss_adc1": {"value": 8}},
|
187
121
|
"gauss_adc2": {"gauss_adc2": {"value": 9}},
|
188
122
|
},
|
189
|
-
"
|
123
|
+
"scan_id": 1,
|
190
124
|
}
|
191
125
|
metadata_grid = {"scan_name": "grid_scan"}
|
192
126
|
metadata_line = {"scan_name": "line_scan"}
|
@@ -195,7 +129,7 @@ metadata_line = {"scan_name": "line_scan"}
|
|
195
129
|
@pytest.mark.parametrize(
|
196
130
|
"config_name, msg, metadata, expected_data",
|
197
131
|
[
|
198
|
-
# case: msg does not have '
|
132
|
+
# case: msg does not have 'scan_id'
|
199
133
|
(
|
200
134
|
"config_device",
|
201
135
|
{"data": {}},
|
@@ -271,9 +205,6 @@ def test_on_scan_segment(monitor, config_name, msg, metadata, expected_data):
|
|
271
205
|
config = load_test_config(config_name)
|
272
206
|
monitor.on_config_update(config)
|
273
207
|
|
274
|
-
# Get hints
|
275
|
-
monitor.dev.__getitem__.side_effect = mock_getitem
|
276
|
-
|
277
208
|
# Mock scan_storage.find_scan_by_ID
|
278
209
|
mock_scan_data = MagicMock()
|
279
210
|
mock_scan_data.data = {
|
@@ -1,17 +1,14 @@
|
|
1
1
|
# pylint: disable=missing-module-docstring, missing-function-docstring
|
2
2
|
from collections import defaultdict
|
3
|
+
from unittest.mock import MagicMock
|
3
4
|
|
4
5
|
import pytest
|
5
|
-
from unittest.mock import MagicMock
|
6
6
|
from qtpy import QtGui
|
7
7
|
|
8
8
|
from bec_widgets.widgets import BECMonitor2DScatter
|
9
9
|
|
10
10
|
CONFIG_DEFAULT = {
|
11
|
-
"plot_settings": {
|
12
|
-
"colormap": "CET-L4",
|
13
|
-
"num_columns": 1,
|
14
|
-
},
|
11
|
+
"plot_settings": {"colormap": "CET-L4", "num_columns": 1},
|
15
12
|
"waveform2D": [
|
16
13
|
{
|
17
14
|
"plot_name": "Waveform 2D Scatter (1)",
|
@@ -37,10 +34,7 @@ CONFIG_DEFAULT = {
|
|
37
34
|
}
|
38
35
|
|
39
36
|
CONFIG_ONE_PLOT = {
|
40
|
-
"plot_settings": {
|
41
|
-
"colormap": "CET-L4",
|
42
|
-
"num_columns": 1,
|
43
|
-
},
|
37
|
+
"plot_settings": {"colormap": "CET-L4", "num_columns": 1},
|
44
38
|
"waveform2D": [
|
45
39
|
{
|
46
40
|
"plot_name": "Waveform 2D Scatter (1)",
|
@@ -51,7 +45,7 @@ CONFIG_ONE_PLOT = {
|
|
51
45
|
"y": [{"name": "aptry", "entry": "aptry"}],
|
52
46
|
"z": [{"name": "gauss_bpm", "entry": "gauss_bpm"}],
|
53
47
|
},
|
54
|
-
}
|
48
|
+
}
|
55
49
|
],
|
56
50
|
}
|
57
51
|
|
@@ -65,13 +59,7 @@ def monitor_2Dscatter(qtbot):
|
|
65
59
|
yield widget
|
66
60
|
|
67
61
|
|
68
|
-
@pytest.mark.parametrize(
|
69
|
-
"config, number_of_plots",
|
70
|
-
[
|
71
|
-
(CONFIG_DEFAULT, 2),
|
72
|
-
(CONFIG_ONE_PLOT, 1),
|
73
|
-
],
|
74
|
-
)
|
62
|
+
@pytest.mark.parametrize("config, number_of_plots", [(CONFIG_DEFAULT, 2), (CONFIG_ONE_PLOT, 1)])
|
75
63
|
def test_initialization(monitor_2Dscatter, config, number_of_plots):
|
76
64
|
config_load = config
|
77
65
|
monitor_2Dscatter.on_config_update(config_load)
|
@@ -81,13 +69,7 @@ def test_initialization(monitor_2Dscatter, config, number_of_plots):
|
|
81
69
|
assert len(monitor_2Dscatter.plot_data) == number_of_plots
|
82
70
|
|
83
71
|
|
84
|
-
@pytest.mark.parametrize(
|
85
|
-
"config ",
|
86
|
-
[
|
87
|
-
(CONFIG_DEFAULT),
|
88
|
-
(CONFIG_ONE_PLOT),
|
89
|
-
],
|
90
|
-
)
|
72
|
+
@pytest.mark.parametrize("config ", [(CONFIG_DEFAULT), (CONFIG_ONE_PLOT)])
|
91
73
|
def test_database_initialization(monitor_2Dscatter, config):
|
92
74
|
monitor_2Dscatter.on_config_update(config)
|
93
75
|
# Check if the database is a defaultdict
|
@@ -108,13 +90,7 @@ def test_database_initialization(monitor_2Dscatter, config):
|
|
108
90
|
assert isinstance(monitor_2Dscatter.database[plot_name][axis][signal_name], list)
|
109
91
|
|
110
92
|
|
111
|
-
@pytest.mark.parametrize(
|
112
|
-
"config ",
|
113
|
-
[
|
114
|
-
(CONFIG_DEFAULT),
|
115
|
-
(CONFIG_ONE_PLOT),
|
116
|
-
],
|
117
|
-
)
|
93
|
+
@pytest.mark.parametrize("config ", [(CONFIG_DEFAULT), (CONFIG_ONE_PLOT)])
|
118
94
|
def test_ui_initialization(monitor_2Dscatter, config):
|
119
95
|
monitor_2Dscatter.on_config_update(config)
|
120
96
|
assert len(monitor_2Dscatter.plots) == len(config["waveform2D"])
|
@@ -133,7 +109,7 @@ def simulate_scan_data(monitor, x_value, y_value, z_value):
|
|
133
109
|
"samy": {"samy": {"value": y_value}},
|
134
110
|
"gauss_bpm": {"gauss_bpm": {"value": z_value}},
|
135
111
|
},
|
136
|
-
"
|
112
|
+
"scan_id": 1,
|
137
113
|
}
|
138
114
|
monitor.on_scan_segment(msg, {})
|
139
115
|
|
@@ -0,0 +1,125 @@
|
|
1
|
+
import pytest
|
2
|
+
|
3
|
+
from bec_widgets.widgets import BECMotorMap
|
4
|
+
from bec_widgets.widgets.plots.motor_map import MotorMapConfig
|
5
|
+
from bec_widgets.widgets.plots.waveform1d import Signal, SignalData
|
6
|
+
|
7
|
+
from .client_mocks import mocked_client
|
8
|
+
|
9
|
+
|
10
|
+
@pytest.fixture(scope="function")
|
11
|
+
def bec_motor_map(qtbot, mocked_client):
|
12
|
+
widget = BECMotorMap(client=mocked_client, gui_id="BECMotorMap_test")
|
13
|
+
# qtbot.addWidget(widget)
|
14
|
+
# qtbot.waitExposed(widget)
|
15
|
+
yield widget
|
16
|
+
|
17
|
+
|
18
|
+
def test_motor_map_init(bec_motor_map):
|
19
|
+
default_config = MotorMapConfig(widget_class="BECMotorMap", gui_id="BECMotorMap_test")
|
20
|
+
|
21
|
+
assert bec_motor_map.config == default_config
|
22
|
+
|
23
|
+
|
24
|
+
def test_motor_map_change_motors(bec_motor_map):
|
25
|
+
bec_motor_map.change_motors("samx", "samy")
|
26
|
+
|
27
|
+
assert bec_motor_map.config.signals.x == SignalData(name="samx", entry="samx", limits=[-10, 10])
|
28
|
+
assert bec_motor_map.config.signals.y == SignalData(name="samy", entry="samy", limits=[-5, 5])
|
29
|
+
|
30
|
+
|
31
|
+
def test_motor_map_get_limits(bec_motor_map):
|
32
|
+
expected_limits = {
|
33
|
+
"samx": [-10, 10],
|
34
|
+
"samy": [-5, 5],
|
35
|
+
}
|
36
|
+
|
37
|
+
for motor_name, expected_limit in expected_limits.items():
|
38
|
+
actual_limit = bec_motor_map._get_motor_limit(motor_name)
|
39
|
+
assert actual_limit == expected_limit
|
40
|
+
|
41
|
+
|
42
|
+
def test_motor_map_get_init_position(bec_motor_map):
|
43
|
+
bec_motor_map.set_precision(2)
|
44
|
+
|
45
|
+
motor_map_dev = bec_motor_map.client.device_manager.devices
|
46
|
+
|
47
|
+
expected_positions = {
|
48
|
+
("samx", "samx"): motor_map_dev["samx"].read()["samx"]["value"],
|
49
|
+
("samy", "samy"): motor_map_dev["samy"].read()["samy"]["value"],
|
50
|
+
("aptrx", "aptrx"): motor_map_dev["aptrx"].read()["aptrx"]["value"],
|
51
|
+
("aptry", "aptry"): motor_map_dev["aptry"].read()["aptry"]["value"],
|
52
|
+
}
|
53
|
+
|
54
|
+
for (motor_name, entry), expected_position in expected_positions.items():
|
55
|
+
actual_position = bec_motor_map._get_motor_init_position(motor_name, entry, 2)
|
56
|
+
assert actual_position == expected_position
|
57
|
+
|
58
|
+
|
59
|
+
def test_motor_movement_updates_position_and_database(bec_motor_map):
|
60
|
+
motor_map_dev = bec_motor_map.client.device_manager.devices
|
61
|
+
|
62
|
+
init_positions = {
|
63
|
+
"samx": [motor_map_dev["samx"].read()["samx"]["value"]],
|
64
|
+
"samy": [motor_map_dev["samy"].read()["samy"]["value"]],
|
65
|
+
}
|
66
|
+
|
67
|
+
bec_motor_map.change_motors("samx", "samy")
|
68
|
+
|
69
|
+
assert bec_motor_map.database_buffer["x"] == init_positions["samx"]
|
70
|
+
assert bec_motor_map.database_buffer["y"] == init_positions["samy"]
|
71
|
+
|
72
|
+
# Simulate motor movement for 'samx' only
|
73
|
+
new_position_samx = 4.0
|
74
|
+
bec_motor_map.on_device_readback({"signals": {"samx": {"value": new_position_samx}}})
|
75
|
+
|
76
|
+
init_positions["samx"].append(new_position_samx)
|
77
|
+
init_positions["samy"].append(init_positions["samy"][-1])
|
78
|
+
# Verify database update for 'samx'
|
79
|
+
assert bec_motor_map.database_buffer["x"] == init_positions["samx"]
|
80
|
+
|
81
|
+
# Verify 'samy' retains its last known position
|
82
|
+
assert bec_motor_map.database_buffer["y"] == init_positions["samy"]
|
83
|
+
|
84
|
+
|
85
|
+
def test_scatter_plot_rendering(bec_motor_map):
|
86
|
+
motor_map_dev = bec_motor_map.client.device_manager.devices
|
87
|
+
|
88
|
+
init_positions = {
|
89
|
+
"samx": [motor_map_dev["samx"].read()["samx"]["value"]],
|
90
|
+
"samy": [motor_map_dev["samy"].read()["samy"]["value"]],
|
91
|
+
}
|
92
|
+
|
93
|
+
bec_motor_map.change_motors("samx", "samy")
|
94
|
+
|
95
|
+
# Simulate motor movement for 'samx' only
|
96
|
+
new_position_samx = 4.0
|
97
|
+
bec_motor_map.on_device_readback({"signals": {"samx": {"value": new_position_samx}}})
|
98
|
+
bec_motor_map._update_plot()
|
99
|
+
|
100
|
+
# Get the scatter plot item
|
101
|
+
scatter_plot_item = bec_motor_map.plot_components["scatter"]
|
102
|
+
|
103
|
+
# Check the scatter plot item properties
|
104
|
+
assert len(scatter_plot_item.data) > 0, "Scatter plot data is empty"
|
105
|
+
x_data = scatter_plot_item.data["x"]
|
106
|
+
y_data = scatter_plot_item.data["y"]
|
107
|
+
assert x_data[-1] == new_position_samx, "Scatter plot X data not updated correctly"
|
108
|
+
assert (
|
109
|
+
y_data[-1] == init_positions["samy"][-1]
|
110
|
+
), "Scatter plot Y data should retain last known position"
|
111
|
+
|
112
|
+
|
113
|
+
def test_plot_visualization_consistency(bec_motor_map):
|
114
|
+
bec_motor_map.change_motors("samx", "samy")
|
115
|
+
# Simulate updating the plot with new data
|
116
|
+
bec_motor_map.on_device_readback({"signals": {"samx": {"value": 5}}})
|
117
|
+
bec_motor_map.on_device_readback({"signals": {"samy": {"value": 9}}})
|
118
|
+
bec_motor_map._update_plot()
|
119
|
+
|
120
|
+
scatter_plot_item = bec_motor_map.plot_components["scatter"]
|
121
|
+
|
122
|
+
# Check if the scatter plot reflects the new data correctly
|
123
|
+
assert (
|
124
|
+
scatter_plot_item.data["x"][-1] == 5 and scatter_plot_item.data["y"][-1] == 9
|
125
|
+
), "Plot not updated correctly with new data"
|