mirror of
https://github.com/bec-project/bec_widgets.git
synced 2025-07-14 11:41:49 +02:00
refactor(motor_map_widget): BECMotorMapWidget removed
This commit is contained in:
@ -18,7 +18,6 @@ class Widgets(str, enum.Enum):
|
|||||||
AbortButton = "AbortButton"
|
AbortButton = "AbortButton"
|
||||||
BECColorMapWidget = "BECColorMapWidget"
|
BECColorMapWidget = "BECColorMapWidget"
|
||||||
BECDockArea = "BECDockArea"
|
BECDockArea = "BECDockArea"
|
||||||
BECMotorMapWidget = "BECMotorMapWidget"
|
|
||||||
BECMultiWaveformWidget = "BECMultiWaveformWidget"
|
BECMultiWaveformWidget = "BECMultiWaveformWidget"
|
||||||
BECProgressBar = "BECProgressBar"
|
BECProgressBar = "BECProgressBar"
|
||||||
BECQueue = "BECQueue"
|
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):
|
class BECMultiWaveform(RPCBase):
|
||||||
@property
|
@property
|
||||||
@rpc_call
|
@rpc_call
|
||||||
|
@ -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.containers.layout_manager.layout_manager import LayoutManagerWidget
|
||||||
from bec_widgets.widgets.editors.jupyter_console.jupyter_console import BECJupyterConsole
|
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.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.plot_base import PlotBase
|
||||||
from bec_widgets.widgets.plots_next_gen.scatter_waveform.scatter_waveform import ScatterWaveform
|
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.plots_next_gen.waveform.waveform import Waveform
|
||||||
@ -53,11 +54,9 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
|
|||||||
"w8": self.w8,
|
"w8": self.w8,
|
||||||
"w9": self.w9,
|
"w9": self.w9,
|
||||||
"w10": self.w10,
|
"w10": self.w10,
|
||||||
"d0": self.d0,
|
|
||||||
"im": self.im,
|
"im": self.im,
|
||||||
"mi": self.mi,
|
"mi": self.mi,
|
||||||
"mm": self.mm,
|
"mm": self.mm,
|
||||||
"mw": self.mw,
|
|
||||||
"lm": self.lm,
|
"lm": self.lm,
|
||||||
"btn1": self.btn1,
|
"btn1": self.btn1,
|
||||||
"btn2": self.btn2,
|
"btn2": self.btn2,
|
||||||
@ -146,15 +145,19 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
|
|||||||
tab_widget.addTab(seventh_tab, "Scatter Waveform")
|
tab_widget.addTab(seventh_tab, "Scatter Waveform")
|
||||||
tab_widget.setCurrentIndex(6)
|
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
|
# add stuff to the new Waveform widget
|
||||||
self._init_waveform()
|
self._init_waveform()
|
||||||
|
|
||||||
# add stuff to figure
|
# add stuff to figure
|
||||||
self._init_figure()
|
self._init_figure()
|
||||||
|
|
||||||
# init dock for testing
|
|
||||||
self._init_dock()
|
|
||||||
|
|
||||||
self.setWindowTitle("Jupyter Console Window")
|
self.setWindowTitle("Jupyter Console Window")
|
||||||
|
|
||||||
def _init_waveform(self):
|
def _init_waveform(self):
|
||||||
@ -219,16 +222,6 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
|
|||||||
col=2,
|
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):
|
def closeEvent(self, event):
|
||||||
"""Override to handle things when main window is closed."""
|
"""Override to handle things when main window is closed."""
|
||||||
self.dock.cleanup()
|
self.dock.cleanup()
|
||||||
|
@ -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.device_control.positioner_box import PositionerBox
|
||||||
from bec_widgets.widgets.control.scan_control.scan_control import ScanControl
|
from bec_widgets.widgets.control.scan_control.scan_control import ScanControl
|
||||||
from bec_widgets.widgets.editors.vscode.vscode import VSCodeEditor
|
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.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.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.scatter_waveform.scatter_waveform import ScatterWaveform
|
||||||
from bec_widgets.widgets.plots_next_gen.waveform.waveform import Waveform
|
from bec_widgets.widgets.plots_next_gen.waveform.waveform import Waveform
|
||||||
from bec_widgets.widgets.progress.ring_progress_bar.ring_progress_bar import RingProgressBar
|
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
|
icon_name=Image.ICON_NAME, tooltip="Add Image", filled=True
|
||||||
),
|
),
|
||||||
"motor_map": MaterialIconAction(
|
"motor_map": MaterialIconAction(
|
||||||
icon_name=BECMotorMapWidget.ICON_NAME,
|
icon_name=MotorMap.ICON_NAME, tooltip="Add Motor Map", filled=True
|
||||||
tooltip="Add Motor Map",
|
|
||||||
filled=True,
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -192,7 +190,7 @@ class BECDockArea(BECWidget, QWidget):
|
|||||||
lambda: self._create_widget_from_toolbar(widget_name="Image")
|
lambda: self._create_widget_from_toolbar(widget_name="Image")
|
||||||
)
|
)
|
||||||
self.toolbar.widgets["menu_plots"].widgets["motor_map"].triggered.connect(
|
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
|
# Menu Devices
|
||||||
|
@ -1 +0,0 @@
|
|||||||
{'files': ['motor_map_widget.py','motor_map_widget_plugin.py']}
|
|
@ -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 = """
|
|
||||||
<ui language='c++'>
|
|
||||||
<widget class='BECMotorMapWidget' name='bec_motor_map_widget'>
|
|
||||||
</widget>
|
|
||||||
</ui>
|
|
||||||
"""
|
|
||||||
|
|
||||||
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()
|
|
@ -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)
|
|
@ -1,108 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>Form</class>
|
|
||||||
<widget class="QWidget" name="Form">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>243</width>
|
|
||||||
<height>233</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Form</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QSpinBox" name="scatter_size">
|
|
||||||
<property name="maximum">
|
|
||||||
<number>20</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="trace_label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Trace Dim</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="precision_label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Precision</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="background_label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Background Intensity</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QSpinBox" name="precision">
|
|
||||||
<property name="maximum">
|
|
||||||
<number>15</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QSpinBox" name="background_value">
|
|
||||||
<property name="maximum">
|
|
||||||
<number>100</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="max_point_label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Max Points</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="scatter_size_label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Scatter Size</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QSpinBox" name="max_points">
|
|
||||||
<property name="maximum">
|
|
||||||
<number>10000</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QSpinBox" name="trace_dim">
|
|
||||||
<property name="maximum">
|
|
||||||
<number>1000</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QLabel" name="color_label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Color</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="1">
|
|
||||||
<widget class="ColorButton" name="color"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<customwidgets>
|
|
||||||
<customwidget>
|
|
||||||
<class>ColorButton</class>
|
|
||||||
<extends>QPushButton</extends>
|
|
||||||
<header>color_button</header>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
@ -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()
|
|
@ -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()
|
|
@ -135,11 +135,8 @@ def test_toolbar_add_plot_image(bec_dock_area):
|
|||||||
|
|
||||||
def test_toolbar_add_plot_motor_map(bec_dock_area):
|
def test_toolbar_add_plot_motor_map(bec_dock_area):
|
||||||
bec_dock_area.toolbar.widgets["menu_plots"].widgets["motor_map"].trigger()
|
bec_dock_area.toolbar.widgets["menu_plots"].widgets["motor_map"].trigger()
|
||||||
assert "BECMotorMapWidget_0" in bec_dock_area.panels
|
assert "MotorMap_0" in bec_dock_area.panels
|
||||||
assert (
|
assert bec_dock_area.panels["MotorMap_0"].widgets[0].config.widget_class == "MotorMap"
|
||||||
bec_dock_area.panels["BECMotorMapWidget_0"].widgets[0].config.widget_class
|
|
||||||
== "BECMotorMapWidget"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_toolbar_add_multi_waveform(bec_dock_area):
|
def test_toolbar_add_multi_waveform(bec_dock_area):
|
||||||
|
@ -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))
|
|
Reference in New Issue
Block a user