From f878e87ad545e0fe68292030d9f06dee693e0da2 Mon Sep 17 00:00:00 2001 From: wyzula-jan Date: Fri, 14 Mar 2025 18:05:46 +0100 Subject: [PATCH] refactor(motor_map_widget): BECMotorMapWidget removed --- bec_widgets/cli/client.py | 89 ------- .../jupyter_console/jupyter_console_window.py | 23 +- .../widgets/containers/dock/dock_area.py | 8 +- bec_widgets/widgets/plots/image/__init__.py | 0 .../widgets/plots/motor_map/__init__.py | 0 .../motor_map/bec_motor_map_widget.pyproject | 1 - .../motor_map/bec_motor_map_widget_plugin.py | 56 ----- .../motor_map/motor_map_dialog/__init__.py | 0 .../motor_map_dialog/motor_map_settings.py | 56 ----- .../motor_map_dialog/motor_map_settings.ui | 108 -------- .../plots/motor_map/motor_map_widget.py | 234 ------------------ .../register_bec_motor_map_widget.py | 17 -- tests/unit_tests/test_bec_dock.py | 7 +- tests/unit_tests/test_motor_map_widget.py | 193 --------------- 14 files changed, 13 insertions(+), 779 deletions(-) delete mode 100644 bec_widgets/widgets/plots/image/__init__.py delete mode 100644 bec_widgets/widgets/plots/motor_map/__init__.py delete mode 100644 bec_widgets/widgets/plots/motor_map/bec_motor_map_widget.pyproject delete mode 100644 bec_widgets/widgets/plots/motor_map/bec_motor_map_widget_plugin.py delete mode 100644 bec_widgets/widgets/plots/motor_map/motor_map_dialog/__init__.py delete mode 100644 bec_widgets/widgets/plots/motor_map/motor_map_dialog/motor_map_settings.py delete mode 100644 bec_widgets/widgets/plots/motor_map/motor_map_dialog/motor_map_settings.ui delete mode 100644 bec_widgets/widgets/plots/motor_map/motor_map_widget.py delete mode 100644 bec_widgets/widgets/plots/motor_map/register_bec_motor_map_widget.py delete mode 100644 tests/unit_tests/test_motor_map_widget.py diff --git a/bec_widgets/cli/client.py b/bec_widgets/cli/client.py index efde94b3..7040dc71 100644 --- a/bec_widgets/cli/client.py +++ b/bec_widgets/cli/client.py @@ -18,7 +18,6 @@ class Widgets(str, enum.Enum): AbortButton = "AbortButton" BECColorMapWidget = "BECColorMapWidget" BECDockArea = "BECDockArea" - BECMotorMapWidget = "BECMotorMapWidget" BECMultiWaveformWidget = "BECMultiWaveformWidget" BECProgressBar = "BECProgressBar" BECQueue = "BECQueue" @@ -1316,94 +1315,6 @@ class BECMotorMap(RPCBase): """ -class BECMotorMapWidget(RPCBase): - @rpc_call - def change_motors( - self, - motor_x: "str", - motor_y: "str", - motor_x_entry: "str" = None, - motor_y_entry: "str" = None, - validate_bec: "bool" = True, - ) -> "None": - """ - Change the active motors for the plot. - - Args: - motor_x(str): Motor name for the X axis. - motor_y(str): Motor name for the Y axis. - motor_x_entry(str): Motor entry for the X axis. - motor_y_entry(str): Motor entry for the Y axis. - validate_bec(bool, optional): If True, validate the signal with BEC. Defaults to True. - """ - - @rpc_call - def set_max_points(self, max_points: "int") -> "None": - """ - Set the maximum number of points to display on the motor map. - - Args: - max_points(int): Maximum number of points to display. - """ - - @rpc_call - def set_precision(self, precision: "int") -> "None": - """ - Set the precision of the motor map. - - Args: - precision(int): Precision to set. - """ - - @rpc_call - def set_num_dim_points(self, num_dim_points: "int") -> "None": - """ - Set the number of points to display on the motor map. - - Args: - num_dim_points(int): Number of points to display. - """ - - @rpc_call - def set_background_value(self, background_value: "int") -> "None": - """ - Set the background value of the motor map. - - Args: - background_value(int): Background value of the motor map. - """ - - @rpc_call - def set_scatter_size(self, scatter_size: "int") -> "None": - """ - Set the scatter size of the motor map. - - Args: - scatter_size(int): Scatter size of the motor map. - """ - - @rpc_call - def get_data(self) -> "dict": - """ - Get the data of the motor map. - - Returns: - dict: Data of the motor map. - """ - - @rpc_call - def reset_history(self) -> "None": - """ - Reset the history of the motor map. - """ - - @rpc_call - def export(self): - """ - Show the export dialog for the motor map. - """ - - class BECMultiWaveform(RPCBase): @property @rpc_call diff --git a/bec_widgets/examples/jupyter_console/jupyter_console_window.py b/bec_widgets/examples/jupyter_console/jupyter_console_window.py index c001f086..d4837d0c 100644 --- a/bec_widgets/examples/jupyter_console/jupyter_console_window.py +++ b/bec_widgets/examples/jupyter_console/jupyter_console_window.py @@ -21,6 +21,7 @@ from bec_widgets.widgets.containers.figure import BECFigure from bec_widgets.widgets.containers.layout_manager.layout_manager import LayoutManagerWidget from bec_widgets.widgets.editors.jupyter_console.jupyter_console import BECJupyterConsole from bec_widgets.widgets.plots_next_gen.image.image import Image +from bec_widgets.widgets.plots_next_gen.motor_map.motor_map import MotorMap from bec_widgets.widgets.plots_next_gen.plot_base import PlotBase from bec_widgets.widgets.plots_next_gen.scatter_waveform.scatter_waveform import ScatterWaveform from bec_widgets.widgets.plots_next_gen.waveform.waveform import Waveform @@ -53,11 +54,9 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover: "w8": self.w8, "w9": self.w9, "w10": self.w10, - "d0": self.d0, "im": self.im, "mi": self.mi, "mm": self.mm, - "mw": self.mw, "lm": self.lm, "btn1": self.btn1, "btn2": self.btn2, @@ -146,15 +145,19 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover: tab_widget.addTab(seventh_tab, "Scatter Waveform") tab_widget.setCurrentIndex(6) + eighth_tab = QWidget() + eighth_tab_layout = QVBoxLayout(eighth_tab) + self.mm = MotorMap() + eighth_tab_layout.addWidget(self.mm) + tab_widget.addTab(eighth_tab, "Motor Map") + tab_widget.setCurrentIndex(7) + # add stuff to the new Waveform widget self._init_waveform() # add stuff to figure self._init_figure() - # init dock for testing - self._init_dock() - self.setWindowTitle("Jupyter Console Window") def _init_waveform(self): @@ -219,16 +222,6 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover: col=2, ) - def _init_dock(self): - - self.d0 = self.dock.new(name="dock_0") - self.mm = self.d0.new("BECMotorMapWidget") - self.mm.change_motors("samx", "samy") - - self.mw = None # self.wf.multi_waveform(monitor="waveform") # , config=config) - - self.dock.save_state() - def closeEvent(self, event): """Override to handle things when main window is closed.""" self.dock.cleanup() diff --git a/bec_widgets/widgets/containers/dock/dock_area.py b/bec_widgets/widgets/containers/dock/dock_area.py index 74bbbbaf..60ddc641 100644 --- a/bec_widgets/widgets/containers/dock/dock_area.py +++ b/bec_widgets/widgets/containers/dock/dock_area.py @@ -25,9 +25,9 @@ from bec_widgets.widgets.containers.dock.dock import BECDock, DockConfig from bec_widgets.widgets.control.device_control.positioner_box import PositionerBox from bec_widgets.widgets.control.scan_control.scan_control import ScanControl from bec_widgets.widgets.editors.vscode.vscode import VSCodeEditor -from bec_widgets.widgets.plots.motor_map.motor_map_widget import BECMotorMapWidget from bec_widgets.widgets.plots.multi_waveform.multi_waveform_widget import BECMultiWaveformWidget from bec_widgets.widgets.plots_next_gen.image.image import Image +from bec_widgets.widgets.plots_next_gen.motor_map.motor_map import MotorMap from bec_widgets.widgets.plots_next_gen.scatter_waveform.scatter_waveform import ScatterWaveform from bec_widgets.widgets.plots_next_gen.waveform.waveform import Waveform from bec_widgets.widgets.progress.ring_progress_bar.ring_progress_bar import RingProgressBar @@ -111,9 +111,7 @@ class BECDockArea(BECWidget, QWidget): icon_name=Image.ICON_NAME, tooltip="Add Image", filled=True ), "motor_map": MaterialIconAction( - icon_name=BECMotorMapWidget.ICON_NAME, - tooltip="Add Motor Map", - filled=True, + icon_name=MotorMap.ICON_NAME, tooltip="Add Motor Map", filled=True ), }, ), @@ -192,7 +190,7 @@ class BECDockArea(BECWidget, QWidget): lambda: self._create_widget_from_toolbar(widget_name="Image") ) self.toolbar.widgets["menu_plots"].widgets["motor_map"].triggered.connect( - lambda: self._create_widget_from_toolbar(widget_name="BECMotorMapWidget") + lambda: self._create_widget_from_toolbar(widget_name="MotorMap") ) # Menu Devices diff --git a/bec_widgets/widgets/plots/image/__init__.py b/bec_widgets/widgets/plots/image/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/bec_widgets/widgets/plots/motor_map/__init__.py b/bec_widgets/widgets/plots/motor_map/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/bec_widgets/widgets/plots/motor_map/bec_motor_map_widget.pyproject b/bec_widgets/widgets/plots/motor_map/bec_motor_map_widget.pyproject deleted file mode 100644 index ceca50a1..00000000 --- a/bec_widgets/widgets/plots/motor_map/bec_motor_map_widget.pyproject +++ /dev/null @@ -1 +0,0 @@ -{'files': ['motor_map_widget.py','motor_map_widget_plugin.py']} \ No newline at end of file diff --git a/bec_widgets/widgets/plots/motor_map/bec_motor_map_widget_plugin.py b/bec_widgets/widgets/plots/motor_map/bec_motor_map_widget_plugin.py deleted file mode 100644 index e2a38f48..00000000 --- a/bec_widgets/widgets/plots/motor_map/bec_motor_map_widget_plugin.py +++ /dev/null @@ -1,56 +0,0 @@ -import os - -from qtpy.QtDesigner import QDesignerCustomWidgetInterface - -import bec_widgets -from bec_widgets.utils.bec_designer import designer_material_icon -from bec_widgets.widgets.plots.motor_map.motor_map_widget import BECMotorMapWidget - -DOM_XML = """ - - - - -""" - -MODULE_PATH = os.path.dirname(bec_widgets.__file__) - - -class BECMotorMapWidgetPlugin(QDesignerCustomWidgetInterface): # pragma: no cover - def __init__(self): - super().__init__() - self._form_editor = None - - def createWidget(self, parent): - t = BECMotorMapWidget(parent) - return t - - def domXml(self): - return DOM_XML - - def group(self): - return "BEC Plots" - - def icon(self): - return designer_material_icon(BECMotorMapWidget.ICON_NAME) - - def includeFile(self): - return "bec_motor_map_widget" - - def initialize(self, form_editor): - self._form_editor = form_editor - - def isContainer(self): - return False - - def isInitialized(self): - return self._form_editor is not None - - def name(self): - return "BECMotorMapWidget" - - def toolTip(self): - return "BECMotorMapWidget" - - def whatsThis(self): - return self.toolTip() diff --git a/bec_widgets/widgets/plots/motor_map/motor_map_dialog/__init__.py b/bec_widgets/widgets/plots/motor_map/motor_map_dialog/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/bec_widgets/widgets/plots/motor_map/motor_map_dialog/motor_map_settings.py b/bec_widgets/widgets/plots/motor_map/motor_map_dialog/motor_map_settings.py deleted file mode 100644 index 0724687c..00000000 --- a/bec_widgets/widgets/plots/motor_map/motor_map_dialog/motor_map_settings.py +++ /dev/null @@ -1,56 +0,0 @@ -import os - -from qtpy.QtWidgets import QVBoxLayout - -from bec_widgets.qt_utils.error_popups import SafeSlot as Slot -from bec_widgets.qt_utils.settings_dialog import SettingWidget -from bec_widgets.utils import UILoader -from bec_widgets.utils.widget_io import WidgetIO - - -class MotorMapSettings(SettingWidget): - def __init__(self, parent=None, *args, **kwargs): - super().__init__(parent, *args, **kwargs) - current_path = os.path.dirname(__file__) - - self.ui = UILoader(self).loader(os.path.join(current_path, "motor_map_settings.ui")) - - self.layout = QVBoxLayout(self) - self.layout.addWidget(self.ui) - - @Slot(dict) - def display_current_settings(self, config: dict): - WidgetIO.set_value(self.ui.max_points, config["max_points"]) - WidgetIO.set_value(self.ui.trace_dim, config["num_dim_points"]) - WidgetIO.set_value(self.ui.precision, config["precision"]) - WidgetIO.set_value(self.ui.scatter_size, config["scatter_size"]) - background_intensity = int((config["background_value"] / 255) * 100) - WidgetIO.set_value(self.ui.background_value, background_intensity) - color = config["color"] - self.ui.color.set_color(color) - - @Slot() - def accept_changes(self): - max_points = WidgetIO.get_value(self.ui.max_points) - num_dim_points = WidgetIO.get_value(self.ui.trace_dim) - precision = WidgetIO.get_value(self.ui.precision) - scatter_size = WidgetIO.get_value(self.ui.scatter_size) - background_intensity = int(WidgetIO.get_value(self.ui.background_value) * 0.01 * 255) - color = self.ui.color.get_color("RGBA") - - if self.target_widget is not None: - self.target_widget.set_max_points(max_points) - self.target_widget.set_num_dim_points(num_dim_points) - self.target_widget.set_precision(precision) - self.target_widget.set_scatter_size(scatter_size) - self.target_widget.set_background_value(background_intensity) - self.target_widget.set_color(color) - - def cleanup(self): - self.ui.color.cleanup() - self.ui.color.close() - self.ui.color.deleteLater() - - def closeEvent(self, event): - self.cleanup() - super().closeEvent(event) diff --git a/bec_widgets/widgets/plots/motor_map/motor_map_dialog/motor_map_settings.ui b/bec_widgets/widgets/plots/motor_map/motor_map_dialog/motor_map_settings.ui deleted file mode 100644 index cb36feda..00000000 --- a/bec_widgets/widgets/plots/motor_map/motor_map_dialog/motor_map_settings.ui +++ /dev/null @@ -1,108 +0,0 @@ - - - Form - - - - 0 - 0 - 243 - 233 - - - - Form - - - - - - 20 - - - - - - - Trace Dim - - - - - - - Precision - - - - - - - Background Intensity - - - - - - - 15 - - - - - - - 100 - - - - - - - Max Points - - - - - - - Scatter Size - - - - - - - 10000 - - - - - - - 1000 - - - - - - - Color - - - - - - - - - - - ColorButton - QPushButton -
color_button
-
-
- - -
diff --git a/bec_widgets/widgets/plots/motor_map/motor_map_widget.py b/bec_widgets/widgets/plots/motor_map/motor_map_widget.py deleted file mode 100644 index d8456f06..00000000 --- a/bec_widgets/widgets/plots/motor_map/motor_map_widget.py +++ /dev/null @@ -1,234 +0,0 @@ -from __future__ import annotations - -import sys - -from qtpy.QtWidgets import QVBoxLayout, QWidget - -from bec_widgets.qt_utils.settings_dialog import SettingsDialog -from bec_widgets.qt_utils.toolbar import DeviceSelectionAction, MaterialIconAction, ModularToolBar -from bec_widgets.utils.bec_widget import BECWidget -from bec_widgets.widgets.containers.figure import BECFigure -from bec_widgets.widgets.containers.figure.plots.motor_map.motor_map import MotorMapConfig -from bec_widgets.widgets.control.device_input.base_classes.device_input_base import BECDeviceFilter -from bec_widgets.widgets.control.device_input.device_combobox.device_combobox import DeviceComboBox -from bec_widgets.widgets.plots.motor_map.motor_map_dialog.motor_map_settings import MotorMapSettings - - -class BECMotorMapWidget(BECWidget, QWidget): - PLUGIN = True - ICON_NAME = "my_location" - USER_ACCESS = [ - "change_motors", - "set_max_points", - "set_precision", - "set_num_dim_points", - "set_background_value", - "set_scatter_size", - "get_data", - "reset_history", - "export", - ] - - def __init__( - self, - parent: QWidget | None = None, - config: MotorMapConfig | None = None, - client=None, - gui_id: str | None = None, - **kwargs, - ) -> None: - if config is None: - config = MotorMapConfig(widget_class=self.__class__.__name__) - else: - if isinstance(config, dict): - config = MotorMapConfig(**config) - super().__init__(client=client, gui_id=gui_id, **kwargs) - QWidget.__init__(self, parent) - - self.layout = QVBoxLayout(self) - self.layout.setSpacing(0) - self.layout.setContentsMargins(0, 0, 0, 0) - - self.fig = BECFigure() - self.toolbar = ModularToolBar( - actions={ - "motor_x": DeviceSelectionAction( - "Motor X:", DeviceComboBox(device_filter=[BECDeviceFilter.POSITIONER]) - ), - "motor_y": DeviceSelectionAction( - "Motor Y:", DeviceComboBox(device_filter=[BECDeviceFilter.POSITIONER]) - ), - "connect": MaterialIconAction(icon_name="link", tooltip="Connect Motors"), - "history": MaterialIconAction(icon_name="history", tooltip="Reset Trace History"), - "config": MaterialIconAction( - icon_name="settings", tooltip="Open Configuration Dialog" - ), - }, - target_widget=self, - ) - - self.layout.addWidget(self.toolbar) - self.layout.addWidget(self.fig) - - self.map = self.fig.motor_map() - self.map.apply_config(config) - - self._hook_actions() - - self.config = config - - def _hook_actions(self): - self.toolbar.widgets["connect"].action.triggered.connect(self._action_motors) - self.toolbar.widgets["config"].action.triggered.connect(self.show_settings) - self.toolbar.widgets["history"].action.triggered.connect(self.reset_history) - - if self.map.motor_x is None and self.map.motor_y is None: - self._enable_actions(False) - - def _enable_actions(self, enable: bool): - self.toolbar.widgets["config"].action.setEnabled(enable) - self.toolbar.widgets["history"].action.setEnabled(enable) - - def _action_motors(self): - toolbar_x = self.toolbar.widgets["motor_x"].device_combobox - toolbar_y = self.toolbar.widgets["motor_y"].device_combobox - motor_x = toolbar_x.currentText() - motor_y = toolbar_y.currentText() - self.change_motors(motor_x, motor_y, None, None, True) - toolbar_x.setStyleSheet("QComboBox {{ background-color: " "; }}") - toolbar_y.setStyleSheet("QComboBox {{ background-color: " "; }}") - - def show_settings(self) -> None: - dialog = SettingsDialog( - self, settings_widget=MotorMapSettings(), window_title="Motor Map Settings" - ) - dialog.exec() - - ################################### - # User Access Methods from MotorMap - ################################### - - def change_motors( - self, - motor_x: str, - motor_y: str, - motor_x_entry: str = None, - motor_y_entry: str = None, - validate_bec: bool = True, - ) -> None: - """ - Change the active motors for the plot. - - Args: - motor_x(str): Motor name for the X axis. - motor_y(str): Motor name for the Y axis. - motor_x_entry(str): Motor entry for the X axis. - motor_y_entry(str): Motor entry for the Y axis. - validate_bec(bool, optional): If True, validate the signal with BEC. Defaults to True. - """ - self.map.change_motors(motor_x, motor_y, motor_x_entry, motor_y_entry, validate_bec) - if self.map.motor_x is not None and self.map.motor_y is not None: - self._enable_actions(True) - toolbar_x = self.toolbar.widgets["motor_x"].device_combobox - toolbar_y = self.toolbar.widgets["motor_y"].device_combobox - - if toolbar_x.currentText() != motor_x: - toolbar_x.setCurrentText(motor_x) - toolbar_x.setStyleSheet("QComboBox {{ background-color: " "; }}") - if toolbar_y.currentText() != motor_y: - toolbar_y.setCurrentText(motor_y) - toolbar_y.setStyleSheet("QComboBox {{ background-color: " "; }}") - - def get_data(self) -> dict: - """ - Get the data of the motor map. - - Returns: - dict: Data of the motor map. - """ - return self.map.get_data() - - def reset_history(self) -> None: - """ - Reset the history of the motor map. - """ - self.map.reset_history() - - def set_color(self, color: str | tuple): - """ - Set the color of the motor map. - - Args: - color(str, tuple): Color to set. - """ - self.map.set_color(color) - - def set_max_points(self, max_points: int) -> None: - """ - Set the maximum number of points to display on the motor map. - - Args: - max_points(int): Maximum number of points to display. - """ - self.map.set_max_points(max_points) - - def set_precision(self, precision: int) -> None: - """ - Set the precision of the motor map. - - Args: - precision(int): Precision to set. - """ - self.map.set_precision(precision) - - def set_num_dim_points(self, num_dim_points: int) -> None: - """ - Set the number of points to display on the motor map. - - Args: - num_dim_points(int): Number of points to display. - """ - self.map.set_num_dim_points(num_dim_points) - - def set_background_value(self, background_value: int) -> None: - """ - Set the background value of the motor map. - - Args: - background_value(int): Background value of the motor map. - """ - self.map.set_background_value(background_value) - - def set_scatter_size(self, scatter_size: int) -> None: - """ - Set the scatter size of the motor map. - - Args: - scatter_size(int): Scatter size of the motor map. - """ - self.map.set_scatter_size(scatter_size) - - def export(self): - """ - Show the export dialog for the motor map. - """ - self.map.export() - - def cleanup(self): - self.fig.cleanup() - self.toolbar.widgets["motor_x"].device_combobox.cleanup() - self.toolbar.widgets["motor_y"].device_combobox.cleanup() - return super().cleanup() - - -def main(): # pragma: no cover - from qtpy.QtWidgets import QApplication - - app = QApplication(sys.argv) - widget = BECMotorMapWidget() - widget.show() - sys.exit(app.exec_()) - - -if __name__ == "__main__": # pragma: no cover - main() diff --git a/bec_widgets/widgets/plots/motor_map/register_bec_motor_map_widget.py b/bec_widgets/widgets/plots/motor_map/register_bec_motor_map_widget.py deleted file mode 100644 index 88bf7a7a..00000000 --- a/bec_widgets/widgets/plots/motor_map/register_bec_motor_map_widget.py +++ /dev/null @@ -1,17 +0,0 @@ -def main(): # pragma: no cover - from qtpy import PYSIDE6 - - if not PYSIDE6: - print("PYSIDE6 is not available in the environment. Cannot patch designer.") - return - from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection - - from bec_widgets.widgets.plots.motor_map.bec_motor_map_widget_plugin import ( - BECMotorMapWidgetPlugin, - ) - - QPyDesignerCustomWidgetCollection.addCustomWidget(BECMotorMapWidgetPlugin()) - - -if __name__ == "__main__": # pragma: no cover - main() diff --git a/tests/unit_tests/test_bec_dock.py b/tests/unit_tests/test_bec_dock.py index 0551df63..c175db79 100644 --- a/tests/unit_tests/test_bec_dock.py +++ b/tests/unit_tests/test_bec_dock.py @@ -135,11 +135,8 @@ def test_toolbar_add_plot_image(bec_dock_area): def test_toolbar_add_plot_motor_map(bec_dock_area): bec_dock_area.toolbar.widgets["menu_plots"].widgets["motor_map"].trigger() - assert "BECMotorMapWidget_0" in bec_dock_area.panels - assert ( - bec_dock_area.panels["BECMotorMapWidget_0"].widgets[0].config.widget_class - == "BECMotorMapWidget" - ) + assert "MotorMap_0" in bec_dock_area.panels + assert bec_dock_area.panels["MotorMap_0"].widgets[0].config.widget_class == "MotorMap" def test_toolbar_add_multi_waveform(bec_dock_area): diff --git a/tests/unit_tests/test_motor_map_widget.py b/tests/unit_tests/test_motor_map_widget.py deleted file mode 100644 index 23bc549f..00000000 --- a/tests/unit_tests/test_motor_map_widget.py +++ /dev/null @@ -1,193 +0,0 @@ -from unittest.mock import MagicMock, patch - -import pytest - -from bec_widgets.widgets.control.device_input.base_classes.device_input_base import BECDeviceFilter -from bec_widgets.widgets.plots.motor_map.motor_map_dialog.motor_map_settings import MotorMapSettings -from bec_widgets.widgets.plots.motor_map.motor_map_widget import BECMotorMapWidget - -from .client_mocks import mocked_client - - -@pytest.fixture -def motor_map_widget(qtbot, mocked_client): - widget = BECMotorMapWidget(client=mocked_client()) - widget.toolbar.widgets["motor_x"].device_combobox.set_device_filter(BECDeviceFilter.POSITIONER) - widget.toolbar.widgets["motor_y"].device_combobox.set_device_filter(BECDeviceFilter.POSITIONER) - qtbot.addWidget(widget) - qtbot.waitExposed(widget) - yield widget - - -@pytest.fixture -def mock_motor_map(motor_map_widget): - motor_map_mock = MagicMock() - motor_map_widget.map = motor_map_mock - return motor_map_mock - - -def test_motor_map_widget_init(motor_map_widget): - assert motor_map_widget is not None - assert motor_map_widget.client is not None - assert isinstance(motor_map_widget, BECMotorMapWidget) - assert motor_map_widget.config.widget_class == "BECMotorMapWidget" - - # check initial state of toolbar actions - assert motor_map_widget.toolbar.widgets["connect"].action.isEnabled() == True - assert motor_map_widget.toolbar.widgets["config"].action.isEnabled() == False - assert motor_map_widget.toolbar.widgets["history"].action.isEnabled() == False - assert motor_map_widget.toolbar.widgets["motor_x"].device_combobox.config.device_filter == [ - BECDeviceFilter.POSITIONER - ] - assert motor_map_widget.toolbar.widgets["motor_y"].device_combobox.config.device_filter == [ - BECDeviceFilter.POSITIONER - ] - assert motor_map_widget.map.motor_x is None - assert motor_map_widget.map.motor_y is None - - -################################### -# Toolbar Actions -################################### - - -def test_motor_map_widget_change_motors_enable_toolbar(motor_map_widget): - motor_map_widget.change_motors("samx", "samy") - assert motor_map_widget.map.motor_x == "samx" - assert motor_map_widget.map.motor_y == "samy" - assert motor_map_widget.toolbar.widgets["motor_x"].device_combobox.currentText() == "samx" - assert motor_map_widget.toolbar.widgets["motor_y"].device_combobox.currentText() == "samy" - assert motor_map_widget.toolbar.widgets["config"].action.isEnabled() == True - assert motor_map_widget.toolbar.widgets["history"].action.isEnabled() == True - - -################################### -# Wrapper methods for MotorMap -################################### - - -def test_change_motors(motor_map_widget, mock_motor_map): - motor_map_widget.change_motors("motor_x", "motor_y", "motor_x_entry", "motor_y_entry", True) - mock_motor_map.change_motors.assert_called_once_with( - "motor_x", "motor_y", "motor_x_entry", "motor_y_entry", True - ) - - -def test_get_data(motor_map_widget, mock_motor_map): - motor_map_widget.get_data() - mock_motor_map.get_data.assert_called_once() - - -def test_reset_history(motor_map_widget, mock_motor_map): - motor_map_widget.reset_history() - mock_motor_map.reset_history.assert_called_once() - - -def test_set_color(motor_map_widget, mock_motor_map): - motor_map_widget.set_color("blue") - mock_motor_map.set_color.assert_called_once_with("blue") - - -def test_set_max_points(motor_map_widget, mock_motor_map): - motor_map_widget.set_max_points(100) - mock_motor_map.set_max_points.assert_called_once_with(100) - - -def test_set_precision(motor_map_widget, mock_motor_map): - motor_map_widget.set_precision(2) - mock_motor_map.set_precision.assert_called_once_with(2) - - -def test_set_num_dim_points(motor_map_widget, mock_motor_map): - motor_map_widget.set_num_dim_points(50) - mock_motor_map.set_num_dim_points.assert_called_once_with(50) - - -def test_set_background_value(motor_map_widget, mock_motor_map): - motor_map_widget.set_background_value(128) - mock_motor_map.set_background_value.assert_called_once_with(128) - - -def test_set_scatter_size(motor_map_widget, mock_motor_map): - motor_map_widget.set_scatter_size(10) - mock_motor_map.set_scatter_size.assert_called_once_with(10) - - -################################### -# MotorMap Dialog -################################### - - -def test_motor_map_widget_clicked(motor_map_widget, qtbot): - motor_map_widget.toolbar.widgets["motor_x"].device_combobox.setCurrentText("samx") - motor_map_widget.toolbar.widgets["motor_y"].device_combobox.setCurrentText("samy") - motor_map_widget.toolbar.widgets["connect"].action.trigger() - - qtbot.wait(200) - - assert motor_map_widget.map.motor_x == "samx" - assert motor_map_widget.map.motor_y == "samy" - assert motor_map_widget.toolbar.widgets["config"].action.isEnabled() == True - assert motor_map_widget.toolbar.widgets["history"].action.isEnabled() == True - - -@pytest.fixture -def motor_map_settings(qtbot): - widget = MotorMapSettings() - qtbot.addWidget(widget) - qtbot.waitExposed(widget) - yield widget - - -def test_display_current_settings(motor_map_settings): - config = { - "max_points": 100, - "num_dim_points": 50, - "precision": 2, - "scatter_size": 10, - "background_value": 128, - "color": (255, 0, 0, 255), - } - - with patch("bec_widgets.utils.widget_io.WidgetIO.set_value") as mock_set_value: - with patch.object(motor_map_settings.ui.color, "set_color") as mock_set_color: - motor_map_settings.display_current_settings(config) - mock_set_value.assert_any_call(motor_map_settings.ui.max_points, config["max_points"]) - mock_set_value.assert_any_call( - motor_map_settings.ui.trace_dim, config["num_dim_points"] - ) - mock_set_value.assert_any_call(motor_map_settings.ui.precision, config["precision"]) - mock_set_value.assert_any_call( - motor_map_settings.ui.scatter_size, config["scatter_size"] - ) - mock_set_value.assert_any_call( - motor_map_settings.ui.background_value, 50 - ) # 128/255*100 = 50 - mock_set_color.assert_called_once_with(config["color"]) - - -def test_accept_changes(motor_map_settings): - with patch( - "bec_widgets.utils.widget_io.WidgetIO.get_value", side_effect=[100, 50, 2, 10, 50] - ) as mock_get_value: - with patch.object( - motor_map_settings.ui.color, "get_color", return_value=(255, 0, 0, 255) - ) as mock_get_color: - mock_target_widget = MagicMock() - motor_map_settings.set_target_widget(mock_target_widget) - - motor_map_settings.accept_changes() - - mock_get_value.assert_any_call(motor_map_settings.ui.max_points) - mock_get_value.assert_any_call(motor_map_settings.ui.trace_dim) - mock_get_value.assert_any_call(motor_map_settings.ui.precision) - mock_get_value.assert_any_call(motor_map_settings.ui.scatter_size) - mock_get_value.assert_any_call(motor_map_settings.ui.background_value) - mock_get_color.assert_called_once() - - mock_target_widget.set_max_points.assert_called_once_with(100) - mock_target_widget.set_num_dim_points.assert_called_once_with(50) - mock_target_widget.set_precision.assert_called_once_with(2) - mock_target_widget.set_scatter_size.assert_called_once_with(10) - mock_target_widget.set_background_value.assert_called_once_with(127) - mock_target_widget.set_color.assert_called_once_with((255, 0, 0, 255))