mirror of
https://github.com/bec-project/bec_widgets.git
synced 2025-07-13 19:21:50 +02:00
feat: add first draft for alignment_1d GUI
This commit is contained in:
225
bec_widgets/applications/alignment/alignment_1d/alignment_1d.py
Normal file
225
bec_widgets/applications/alignment/alignment_1d/alignment_1d.py
Normal file
@ -0,0 +1,225 @@
|
||||
""" This module contains the GUI for the 1D alignment application.
|
||||
#TODO at this stage it is a preliminary version of the GUI, which will be added to the main branch although it is not yet fully functional.
|
||||
It is a work in progress and will be updated in the future.
|
||||
"""
|
||||
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
from bec_lib.device import Positioner, Signal
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from qtpy.QtCore import Signal as pyqtSignal
|
||||
from qtpy.QtWidgets import QCheckBox, QDoubleSpinBox, QSpinBox, QVBoxLayout, QWidget
|
||||
|
||||
from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
|
||||
from bec_widgets.qt_utils.toolbar import WidgetAction
|
||||
from bec_widgets.utils import UILoader
|
||||
from bec_widgets.utils.bec_widget import BECWidget
|
||||
from bec_widgets.widgets.bec_progressbar.bec_progressbar import BECProgressBar
|
||||
from bec_widgets.widgets.device_line_edit.device_line_edit import DeviceLineEdit
|
||||
from bec_widgets.widgets.lmfit_dialog.lmfit_dialog import LMFitDialog
|
||||
from bec_widgets.widgets.positioner_box.positioner_control_line import PositionerControlLine
|
||||
from bec_widgets.widgets.toggle.toggle import ToggleSwitch
|
||||
from bec_widgets.widgets.waveform.waveform_widget import BECWaveformWidget
|
||||
|
||||
|
||||
class Alignment1D(BECWidget, QWidget):
|
||||
"""GUI for 1D alignment"""
|
||||
|
||||
motion_is_active = pyqtSignal(bool)
|
||||
|
||||
def __init__(
|
||||
self, parent: Optional[QWidget] = None, client=None, gui_id: Optional[str] = None
|
||||
) -> None:
|
||||
"""Initialise the widget
|
||||
|
||||
Args:
|
||||
parent: Parent widget.
|
||||
config: Configuration of the widget.
|
||||
client: BEC client object.
|
||||
gui_id: GUI ID.
|
||||
"""
|
||||
super().__init__(client=client, gui_id=gui_id)
|
||||
QWidget.__init__(self, parent)
|
||||
self.get_bec_shortcuts()
|
||||
self.ui_file = "alignment_1d.ui"
|
||||
self.ui = None
|
||||
self.progress_bar = None
|
||||
self.waveform = None
|
||||
self.init_ui()
|
||||
|
||||
def init_ui(self):
|
||||
"""Initialise the UI from QT Designer file"""
|
||||
|
||||
current_path = os.path.dirname(__file__)
|
||||
self.ui = UILoader(self).loader(os.path.join(current_path, self.ui_file))
|
||||
layout = QVBoxLayout(self)
|
||||
layout.addWidget(self.ui)
|
||||
self.setLayout(layout)
|
||||
self.waveform = self.ui.findChild(BECWaveformWidget, "bec_waveform_widget")
|
||||
# Customize the plotting widget
|
||||
self._customise_bec_waveform_widget()
|
||||
# Setup filters for comboboxes
|
||||
self._setup_motor_combobox()
|
||||
self._setup_signal_combobox()
|
||||
# Setup arrow item
|
||||
self._setup_arrow_item()
|
||||
# Setup Scan Control
|
||||
self._setup_scan_control()
|
||||
# Setup progress bar
|
||||
self._setup_progress_bar()
|
||||
# Add actions buttons
|
||||
self._add_action_buttons()
|
||||
# Hook scaninfo updates
|
||||
self.bec_dispatcher.connect_slot(self._scan_status_callback, MessageEndpoints.scan_status())
|
||||
|
||||
##############################
|
||||
############ SLOTS ###########
|
||||
##############################
|
||||
|
||||
@Slot(dict, dict)
|
||||
def _scan_status_callback(self, content: dict, metadata: dict) -> None:
|
||||
"""This slot allows to enable/disable the UI critical components when a scan is running"""
|
||||
if content["status"] in ["running", "open"]:
|
||||
self.motion_is_active.emit(True)
|
||||
self._enable_ui(False)
|
||||
elif content["status"] in ["aborted", "halted", "closed"]:
|
||||
self.motion_is_active.emit(False)
|
||||
self._enable_ui(True)
|
||||
|
||||
@Slot(float)
|
||||
def move_to_center(self, pos: float) -> None:
|
||||
"""Move the selected motor to the center"""
|
||||
motor = self.ui.device_combobox.currentText()
|
||||
self.dev[motor].move(float(pos), relative=False)
|
||||
|
||||
@Slot()
|
||||
def _reset_progress_bar(self) -> None:
|
||||
"""Reset the progress bar"""
|
||||
self.progress_bar.set_value(0)
|
||||
self.progress_bar.set_minimum(0)
|
||||
|
||||
@Slot(dict, dict)
|
||||
def _update_progress_bar(self, content: dict, metadata: dict) -> None:
|
||||
"""Hook to update the progress bar
|
||||
|
||||
Args:
|
||||
content: Content of the scan progress message.
|
||||
metadata: Metadata of the message.
|
||||
"""
|
||||
if content["max_value"] == 0:
|
||||
self.progress_bar.set_value(0)
|
||||
return
|
||||
self.progress_bar.set_maximum(content["max_value"])
|
||||
self.progress_bar.set_value(content["value"])
|
||||
|
||||
##############################
|
||||
######## END OF SLOTS ########
|
||||
##############################
|
||||
|
||||
def _enable_ui(self, enable: bool) -> None:
|
||||
"""Enable or disable the UI components"""
|
||||
# Device selection comboboxes
|
||||
self.ui.device_combobox.setEnabled(enable)
|
||||
self.ui.device_combobox_2.setEnabled(enable)
|
||||
self.ui.dap_combo_box.setEnabled(enable)
|
||||
# Scan button
|
||||
self.ui.scan_button.setEnabled(enable)
|
||||
# Positioner control line
|
||||
# pylint: disable=protected-access
|
||||
self.ui.positioner_control_line._toogle_enable_buttons(enable)
|
||||
# Send report to scilog
|
||||
self.ui.button_send_summary_scilog.setEnabled(enable)
|
||||
# Disable move to buttons in LMFitDialog
|
||||
self.ui.findChild(LMFitDialog).set_enable_move_to_buttons(enable)
|
||||
|
||||
def _add_action_buttons(self) -> None:
|
||||
"""Add action buttons for the Action Control"""
|
||||
fit_dialog = self.ui.findChild(LMFitDialog)
|
||||
fit_dialog.update_activated_button_list(["center", "center1", "center2"])
|
||||
fit_dialog.move_to_position.connect(self.move_to_center)
|
||||
|
||||
def _customise_bec_waveform_widget(self) -> None:
|
||||
"""Customise the BEC Waveform Widget, i.e. hide toolbar buttons except roi selection"""
|
||||
for button in self.waveform.toolbar.widgets.values():
|
||||
if getattr(button, "action", None) is not None:
|
||||
button.action.setVisible(False)
|
||||
self.waveform.toolbar.widgets["roi_select"].action.setVisible(True)
|
||||
toggle_switch = self.ui.findChild(ToggleSwitch, "toggle_switch")
|
||||
scan_control = self.ui.scan_control
|
||||
self.waveform.toolbar.populate_toolbar(
|
||||
{
|
||||
"label": WidgetAction(label="Enable DAP ROI", widget=toggle_switch),
|
||||
"scan_control": WidgetAction(widget=scan_control),
|
||||
},
|
||||
self.waveform,
|
||||
)
|
||||
|
||||
def _setup_arrow_item(self) -> None:
|
||||
"""Setup the arrow item"""
|
||||
self.waveform.waveform.motor_pos_tick.add_to_plot()
|
||||
positioner_line = self.ui.findChild(PositionerControlLine)
|
||||
positioner_line.position_update.connect(self.waveform.waveform.motor_pos_tick.set_position)
|
||||
try:
|
||||
pos = float(positioner_line.ui.readback.text())
|
||||
except ValueError:
|
||||
pos = 0
|
||||
self.waveform.waveform.motor_pos_tick.set_position(pos)
|
||||
|
||||
def _setup_motor_combobox(self) -> None:
|
||||
"""Setup motor selection"""
|
||||
# FIXME after changing the filtering in the combobox
|
||||
motors = [name for name in self.dev if isinstance(self.dev.get(name), Positioner)]
|
||||
self.ui.device_combobox.setCurrentText(motors[0])
|
||||
self.ui.device_combobox.set_device_filter("Positioner")
|
||||
|
||||
def _setup_signal_combobox(self) -> None:
|
||||
"""Setup signal selection"""
|
||||
# FIXME after changing the filtering in the combobox
|
||||
signals = [name for name in self.dev if isinstance(self.dev.get(name), Signal)]
|
||||
self.ui.device_combobox_2.setCurrentText(signals[0])
|
||||
self.ui.device_combobox_2.set_device_filter("Signal")
|
||||
|
||||
def _setup_scan_control(self) -> None:
|
||||
"""Setup scan control, connect spin and check boxes to the scan_control widget"""
|
||||
device_line_edit = self.ui.scan_control.arg_box.findChild(DeviceLineEdit)
|
||||
self.ui.device_combobox.currentTextChanged.connect(device_line_edit.setText)
|
||||
device_line_edit.setText(self.ui.device_combobox.currentText())
|
||||
spin_boxes = self.ui.scan_control.arg_box.findChildren(QDoubleSpinBox)
|
||||
start = self.ui.findChild(QDoubleSpinBox, "linescan_start")
|
||||
start.valueChanged.connect(spin_boxes[0].setValue)
|
||||
stop = self.ui.findChild(QDoubleSpinBox, "linescan_stop")
|
||||
stop.valueChanged.connect(spin_boxes[1].setValue)
|
||||
step = self.ui.findChild(QSpinBox, "linescan_step")
|
||||
step.valueChanged.connect(
|
||||
self.ui.scan_control.kwarg_boxes[0].findChildren(QSpinBox)[0].setValue
|
||||
)
|
||||
exp_time = self.ui.findChild(QDoubleSpinBox, "linescan_exp_time")
|
||||
exp_time.valueChanged.connect(
|
||||
self.ui.scan_control.kwarg_boxes[1].findChildren(QDoubleSpinBox)[0].setValue
|
||||
)
|
||||
relative = self.ui.findChild(QCheckBox, "linescan_relative")
|
||||
relative.toggled.connect(
|
||||
self.ui.scan_control.kwarg_boxes[0].findChildren(QCheckBox)[0].setChecked
|
||||
)
|
||||
|
||||
def _setup_progress_bar(self) -> None:
|
||||
"""Setup progress bar"""
|
||||
# FIXME once the BECScanProgressBar is implemented
|
||||
self.progress_bar = self.ui.findChild(BECProgressBar, "bec_progress_bar")
|
||||
self.progress_bar.set_value(0)
|
||||
self.ui.bec_waveform_widget.new_scan.connect(self._reset_progress_bar)
|
||||
self.bec_dispatcher.connect_slot(
|
||||
self._update_progress_bar, MessageEndpoints.scan_progress()
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
from qtpy.QtWidgets import QApplication
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
window = Alignment1D()
|
||||
window.show()
|
||||
sys.exit(app.exec_())
|
779
bec_widgets/applications/alignment/alignment_1d/alignment_1d.ui
Normal file
779
bec_widgets/applications/alignment/alignment_1d/alignment_1d.ui
Normal file
@ -0,0 +1,779 @@
|
||||
<?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>1578</width>
|
||||
<height>962</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Alignment Control</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6" stretch="0,1,2">
|
||||
<property name="leftMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="ScanControl" name="scan_control">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="current_scan" stdset="0">
|
||||
<string>line_scan</string>
|
||||
</property>
|
||||
<property name="hide_arg_box" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="hide_kwarg_boxes" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="hide_scan_remember_toggle" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="hide_scan_control_buttons" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="hide_bundle_buttons" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="hide_args_group" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="hide_kwargs_group" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="control_layout" stretch="0,0,0,0">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="device_box">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>95</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>95</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>15</pointsize>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Devices</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0" columnstretch="0,0,0">
|
||||
<property name="leftMargin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="font">
|
||||
<font/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>LMFit Model</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="DeviceComboBox" name="device_combobox_2"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Motor</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="DeviceComboBox" name="device_combobox"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="font">
|
||||
<font/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Monitor</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="DapComboBox" name="dap_combo_box"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="scan_box">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>191</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>191</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>15</pointsize>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>LineScan</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3" rowstretch="0,0,0,0,0" columnstretch="0,0,0">
|
||||
<property name="leftMargin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="font">
|
||||
<font>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Relative</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QDoubleSpinBox" name="linescan_exp_time">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-10000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QSpinBox" name="linescan_step_2">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10000000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="3">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="scan_button">
|
||||
<property name="text">
|
||||
<string>Run Scan</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="AbortButton" name="abort_button"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="font">
|
||||
<font>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="font">
|
||||
<font>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Exposure Time</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="font">
|
||||
<font>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Steps</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="font">
|
||||
<font>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stop</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="font">
|
||||
<font>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Burst at each point</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="linescan_stop">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-10000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QDoubleSpinBox" name="linescan_start">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-10000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QSpinBox" name="linescan_step">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10000000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="linescan_relative">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="motor_tweak_box">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>201</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>201</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>15</pointsize>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Motor Tweak</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="PositionerControlLine" name="positioner_control_line">
|
||||
<property name="hide_device_selection" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="action_box">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>85</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>85</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>15</pointsize>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Utils</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="button_send_summary_scilog">
|
||||
<property name="text">
|
||||
<string>Send summary to SciLog</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="plotting_layout" stretch="7,0,2">
|
||||
<item>
|
||||
<widget class="BECWaveformWidget" name="bec_waveform_widget">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="clear_curves_on_plot_update" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ToggleSwitch" name="toggle_switch">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>3</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Activate linear region select for LMFit</string>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LayoutDirection::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="checked" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="fit_dialog_layout" stretch="4">
|
||||
<item>
|
||||
<widget class="LMFitDialog" name="lm_fit_dialog">
|
||||
<property name="always_show_latest" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="hide_curve_selection" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="hide_summary" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Logbook</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="WebsiteWidget" name="website_widget">
|
||||
<property name="url" stdset="0">
|
||||
<string>https://scilog.psi.ch/login</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="1,4">
|
||||
<item>
|
||||
<widget class="StopButton" name="stop_button"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="BECProgressBar" name="bec_progress_bar"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>DapComboBox</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>dap_combo_box</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>StopButton</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>stop_button</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>WebsiteWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>website_widget</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ScanControl</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>scan_control</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ToggleSwitch</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>toggle_switch</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>PositionerBox</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>positioner_box</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>PositionerControlLine</class>
|
||||
<extends>PositionerBox</extends>
|
||||
<header>positioner_control_line</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>BECProgressBar</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>bec_progress_bar</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>BECWaveformWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>bec_waveform_widget</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>DeviceComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>device_combobox</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>LMFitDialog</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>lm_fit_dialog</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>AbortButton</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>abort_button</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>tabWidget</tabstop>
|
||||
<tabstop>device_combobox</tabstop>
|
||||
<tabstop>device_combobox_2</tabstop>
|
||||
<tabstop>linescan_start</tabstop>
|
||||
<tabstop>linescan_stop</tabstop>
|
||||
<tabstop>linescan_step</tabstop>
|
||||
<tabstop>linescan_relative</tabstop>
|
||||
<tabstop>linescan_exp_time</tabstop>
|
||||
<tabstop>linescan_step_2</tabstop>
|
||||
<tabstop>scan_button</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>device_combobox</sender>
|
||||
<signal>currentTextChanged(QString)</signal>
|
||||
<receiver>dap_combo_box</receiver>
|
||||
<slot>select_x_axis(QString)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>214</x>
|
||||
<y>130</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>629</x>
|
||||
<y>130</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>device_combobox_2</sender>
|
||||
<signal>currentTextChanged(QString)</signal>
|
||||
<receiver>dap_combo_box</receiver>
|
||||
<slot>select_y_axis(QString)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>388</x>
|
||||
<y>130</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>629</x>
|
||||
<y>130</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>dap_combo_box</sender>
|
||||
<signal>new_dap_config(QString,QString,QString)</signal>
|
||||
<receiver>bec_waveform_widget</receiver>
|
||||
<slot>add_dap(QString,QString,QString)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>629</x>
|
||||
<y>130</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>1099</x>
|
||||
<y>221</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>device_combobox</sender>
|
||||
<signal>currentTextChanged(QString)</signal>
|
||||
<receiver>positioner_control_line</receiver>
|
||||
<slot>set_positioner(QString)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>214</x>
|
||||
<y>130</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>174</x>
|
||||
<y>550</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>scan_button</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>scan_control</receiver>
|
||||
<slot>run_scan()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>332</x>
|
||||
<y>336</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>28</x>
|
||||
<y>319</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>device_combobox_2</sender>
|
||||
<signal>currentTextChanged(QString)</signal>
|
||||
<receiver>bec_waveform_widget</receiver>
|
||||
<slot>plot(QString)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>388</x>
|
||||
<y>130</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>1099</x>
|
||||
<y>201</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>device_combobox</sender>
|
||||
<signal>currentTextChanged(QString)</signal>
|
||||
<receiver>bec_waveform_widget</receiver>
|
||||
<slot>set_x(QString)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>214</x>
|
||||
<y>130</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>1099</x>
|
||||
<y>258</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>toggle_switch</sender>
|
||||
<signal>enabled(bool)</signal>
|
||||
<receiver>bec_waveform_widget</receiver>
|
||||
<slot>toogle_roi_select(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>691</x>
|
||||
<y>536</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>1099</x>
|
||||
<y>96</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>bec_waveform_widget</sender>
|
||||
<signal>dap_summary_update(QVariantMap,QVariantMap)</signal>
|
||||
<receiver>lm_fit_dialog</receiver>
|
||||
<slot>update_summary_tree(QVariantMap,QVariantMap)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>1099</x>
|
||||
<y>258</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>1098</x>
|
||||
<y>668</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
151
bec_widgets/utils/plot_indicator_items.py
Normal file
151
bec_widgets/utils/plot_indicator_items.py
Normal file
@ -0,0 +1,151 @@
|
||||
"""Module to create an arrow item for a pyqtgraph plot"""
|
||||
|
||||
import pyqtgraph as pg
|
||||
from qtpy.QtCore import QObject, Qt, Signal, Slot
|
||||
|
||||
from bec_widgets.utils.colors import get_accent_colors
|
||||
|
||||
|
||||
class BECIndicatorItem(QObject):
|
||||
|
||||
def __init__(self, plot_item: pg.PlotItem = None, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
self.accent_colors = get_accent_colors()
|
||||
self.plot_item = plot_item
|
||||
|
||||
def add_to_plot(self) -> None:
|
||||
"""Add the item to the plot"""
|
||||
raise NotImplementedError("Method add_to_plot not implemented")
|
||||
|
||||
def remove_from_plot(self) -> None:
|
||||
"""Remove the item from the plot"""
|
||||
raise NotImplementedError("Method remove_from_plot not implemented")
|
||||
|
||||
def set_position(self, pos: tuple[float, float] | float) -> None:
|
||||
"""Set the position of the item"""
|
||||
raise NotImplementedError("Method set_position not implemented")
|
||||
|
||||
def cleanup(self) -> None:
|
||||
"""Cleanup the item"""
|
||||
self.remove_from_plot()
|
||||
self.deleteLater()
|
||||
|
||||
|
||||
class BECTickItem(BECIndicatorItem):
|
||||
"""Class to create a tick item which can be added to a pyqtgraph plot.
|
||||
The tick item will be added to the layout of the plot item and can be used to indicate
|
||||
a position"""
|
||||
|
||||
position_changed = Signal(float)
|
||||
position_changed_str = Signal(str)
|
||||
|
||||
def __init__(self, plot_item: pg.PlotItem = None, parent=None):
|
||||
super().__init__(plot_item=plot_item, parent=parent)
|
||||
self.tick_item = pg.TickSliderItem(allowAdd=False, allowRemove=False)
|
||||
self.tick = None
|
||||
self._tick_pos = 0
|
||||
self._range = [0, 1]
|
||||
|
||||
@Slot(float)
|
||||
def set_position(self, pos: float) -> None:
|
||||
"""Set the position of the tick item
|
||||
|
||||
Args:
|
||||
pos (float): The position of the tick item.
|
||||
"""
|
||||
self._tick_pos = pos
|
||||
self.update_range(self.plot_item.vb, self._range)
|
||||
|
||||
def update_range(self, vb, viewRange) -> None:
|
||||
"""Update the range of the tick item
|
||||
|
||||
Args:
|
||||
vb (pg.ViewBox): The view box.
|
||||
viewRange (tuple): The view range.
|
||||
"""
|
||||
origin = self.tick_item.tickSize / 2.0
|
||||
length = self.tick_item.length
|
||||
|
||||
lengthIncludingPadding = length + self.tick_item.tickSize + 2
|
||||
|
||||
self._range = viewRange
|
||||
|
||||
tickValueIncludingPadding = (self._tick_pos - viewRange[0]) / (viewRange[1] - viewRange[0])
|
||||
tickValue = (tickValueIncludingPadding * lengthIncludingPadding - origin) / length
|
||||
self.tick_item.setTickValue(self.tick, tickValue)
|
||||
self.position_changed.emit(self._tick_pos)
|
||||
self.position_changed_str.emit(str(self._tick_pos))
|
||||
|
||||
def add_to_plot(self):
|
||||
"""Add the tick item to the view box or plot item."""
|
||||
if self.plot_item is not None:
|
||||
self.plot_item.layout.addItem(self.tick_item, 4, 1)
|
||||
self.tick = self.tick_item.addTick(0, movable=False, color=self.accent_colors.highlight)
|
||||
self.plot_item.vb.sigXRangeChanged.connect(self.update_range)
|
||||
|
||||
def remove_from_plot(self):
|
||||
"""Remove the tick item from the view box or plot item."""
|
||||
if self.plot_item is not None:
|
||||
self.plot_item.layout.removeItem(self.tick_item)
|
||||
|
||||
|
||||
class BECArrowItem(BECIndicatorItem):
|
||||
"""Class to create an arrow item which can be added to a pyqtgraph plot.
|
||||
It can be either added directly to a view box or a plot item.
|
||||
To add the arrow item to a view box or plot item, use the add_to_plot method.
|
||||
|
||||
Args:
|
||||
view_box (pg.ViewBox | pg.PlotItem): The view box or plot item to which the arrow item should be added.
|
||||
parent (QObject): The parent object.
|
||||
|
||||
Signals:
|
||||
position_changed (tuple[float, float]): Signal emitted when the position of the arrow item has changed.
|
||||
position_changed_str (tuple[str, str]): Signal emitted when the position of the arrow item has changed.
|
||||
"""
|
||||
|
||||
# Signal to emit if the position of the arrow item has changed
|
||||
position_changed = Signal(tuple)
|
||||
position_changed_str = Signal(tuple)
|
||||
|
||||
def __init__(self, plot_item: pg.PlotItem = None, parent=None):
|
||||
super().__init__(plot_item=plot_item, parent=parent)
|
||||
self.arrow_item = pg.ArrowItem()
|
||||
|
||||
@Slot(dict)
|
||||
def set_style(self, style: dict) -> None:
|
||||
"""Set the style of the arrow item
|
||||
|
||||
Args:
|
||||
style (dict): The style of the arrow item. Dictionary with key,
|
||||
value pairs which are accepted from the pg.ArrowItem.setStyle method.
|
||||
"""
|
||||
self.arrow_item.setStyle(**style)
|
||||
|
||||
@Slot(tuple)
|
||||
def set_position(self, pos: tuple[float, float]) -> None:
|
||||
"""Set the position of the arrow item
|
||||
|
||||
Args:
|
||||
pos (tuple): The position of the arrow item as a tuple (x, y).
|
||||
"""
|
||||
pos_x = pos[0]
|
||||
pos_y = pos[1]
|
||||
self.arrow_item.setPos(pos_x, pos_y)
|
||||
self.position_changed.emit((pos_x, pos_y))
|
||||
self.position_changed_str.emit((str(pos_x), str(pos_y)))
|
||||
|
||||
def add_to_plot(self):
|
||||
"""Add the arrow item to the view box or plot item."""
|
||||
self.arrow_item.setStyle(
|
||||
angle=-90,
|
||||
pen=pg.mkPen(self.accent_colors.emergency, width=1),
|
||||
brush=pg.mkBrush(self.accent_colors.highlight),
|
||||
headLen=20,
|
||||
)
|
||||
if self.plot_item is not None:
|
||||
self.plot_item.addItem(self.arrow_item)
|
||||
|
||||
def remove_from_plot(self):
|
||||
"""Remove the arrow item from the view box or plot item."""
|
||||
if self.plot_item is not None:
|
||||
self.plot_item.removeItem(self.arrow_item)
|
@ -12,6 +12,7 @@ from qtpy.QtWidgets import QApplication, QWidget
|
||||
|
||||
from bec_widgets.utils import BECConnector, ConnectionConfig
|
||||
from bec_widgets.utils.crosshair import Crosshair
|
||||
from bec_widgets.utils.plot_indicator_items import BECArrowItem, BECTickItem
|
||||
|
||||
logger = bec_logger.logger
|
||||
|
||||
@ -105,6 +106,8 @@ class BECPlotBase(BECConnector, pg.GraphicsLayout):
|
||||
|
||||
self.add_legend()
|
||||
self.crosshair = None
|
||||
self.motor_pos_tick = BECTickItem(parent=self, plot_item=self.plot_item)
|
||||
self.arrow_item = BECArrowItem(parent=self, plot_item=self.plot_item)
|
||||
self._connect_to_theme_change()
|
||||
|
||||
def _connect_to_theme_change(self):
|
||||
@ -428,6 +431,8 @@ class BECPlotBase(BECConnector, pg.GraphicsLayout):
|
||||
def cleanup_pyqtgraph(self):
|
||||
"""Cleanup pyqtgraph items."""
|
||||
self.unhook_crosshair()
|
||||
self.motor_pos_tick.cleanup()
|
||||
self.arrow_item.cleanup()
|
||||
item = self.plot_item
|
||||
item.vb.menu.close()
|
||||
item.vb.menu.deleteLater()
|
||||
|
@ -33,6 +33,8 @@ class PositionerBox(BECWidget, QWidget):
|
||||
ICON_NAME = "switch_right"
|
||||
USER_ACCESS = ["set_positioner"]
|
||||
device_changed = Signal(str, str)
|
||||
# Signal emitted to inform listeners about a position update
|
||||
position_update = Signal(float)
|
||||
|
||||
def __init__(self, parent=None, device: Positioner = None, **kwargs):
|
||||
"""Initialize the PositionerBox widget.
|
||||
@ -245,6 +247,7 @@ class PositionerBox(BECWidget, QWidget):
|
||||
|
||||
if readback_val is not None:
|
||||
self.ui.readback.setText(f"{readback_val:.{precision}f}")
|
||||
self.position_update.emit(readback_val)
|
||||
|
||||
if setpoint_val is not None:
|
||||
self.ui.setpoint.setText(f"{setpoint_val:.{precision}f}")
|
||||
|
90
tests/unit_tests/test_utils_plot_indicators.py
Normal file
90
tests/unit_tests/test_utils_plot_indicators.py
Normal file
@ -0,0 +1,90 @@
|
||||
import pyqtgraph as pg
|
||||
import pytest
|
||||
from bec_qthemes._main import AccentColors
|
||||
|
||||
from bec_widgets.utils.plot_indicator_items import BECArrowItem, BECTickItem
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def arrow_item():
|
||||
"""Fixture for the BECArrowItem class"""
|
||||
item = BECArrowItem(plot_item=pg.PlotItem())
|
||||
yield item
|
||||
|
||||
|
||||
def test_arrow_item_add_to_plot(arrow_item):
|
||||
"""Test the add_to_plot method"""
|
||||
assert arrow_item.plot_item is not None
|
||||
assert arrow_item.plot_item.items == []
|
||||
arrow_item.accent_colors = AccentColors(theme="dark")
|
||||
arrow_item.add_to_plot()
|
||||
assert arrow_item.plot_item.items == [arrow_item.arrow_item]
|
||||
|
||||
|
||||
def test_arrow_item_remove_to_plot(arrow_item):
|
||||
"""Test the remove_from_plot method"""
|
||||
arrow_item.accent_colors = AccentColors(theme="dark")
|
||||
arrow_item.add_to_plot()
|
||||
assert arrow_item.plot_item.items == [arrow_item.arrow_item]
|
||||
arrow_item.remove_from_plot()
|
||||
assert arrow_item.plot_item.items == []
|
||||
|
||||
|
||||
def test_arrow_item_set_position(arrow_item):
|
||||
"""Test the set_position method"""
|
||||
container = []
|
||||
|
||||
def signal_callback(tup: tuple):
|
||||
container.append(tup)
|
||||
|
||||
arrow_item.accent_colors = AccentColors(theme="dark")
|
||||
arrow_item.add_to_plot()
|
||||
arrow_item.position_changed.connect(signal_callback)
|
||||
arrow_item.set_position(pos=(1, 1))
|
||||
assert arrow_item.arrow_item.pos().toTuple() == (1, 1)
|
||||
arrow_item.set_position(pos=(2, 2))
|
||||
assert arrow_item.arrow_item.pos().toTuple() == (2, 2)
|
||||
assert container == [(1, 1), (2, 2)]
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def tick_item():
|
||||
"""Fixture for the BECArrowItem class"""
|
||||
item = BECTickItem(plot_item=pg.PlotItem())
|
||||
yield item
|
||||
|
||||
|
||||
def test_tick_item_add_to_plot(tick_item):
|
||||
"""Test the add_to_plot method"""
|
||||
assert tick_item.plot_item is not None
|
||||
assert tick_item.plot_item.items == []
|
||||
tick_item.accent_colors = AccentColors(theme="dark")
|
||||
tick_item.add_to_plot()
|
||||
assert tick_item.plot_item.layout.itemAt(4, 1) == tick_item.tick_item
|
||||
|
||||
|
||||
def test_tick_item_remove_to_plot(tick_item):
|
||||
"""Test the remove_from_plot method"""
|
||||
tick_item.accent_colors = AccentColors(theme="dark")
|
||||
tick_item.add_to_plot()
|
||||
assert tick_item.plot_item.layout.itemAt(4, 1) == tick_item.tick_item
|
||||
tick_item.remove_from_plot()
|
||||
assert tick_item.plot_item.layout.itemAt(4, 1) is None
|
||||
|
||||
|
||||
def test_tick_item_set_position(tick_item):
|
||||
"""Test the set_position method"""
|
||||
container = []
|
||||
|
||||
def signal_callback(val: float):
|
||||
container.append(val)
|
||||
|
||||
tick_item.accent_colors = AccentColors(theme="dark")
|
||||
tick_item.add_to_plot()
|
||||
tick_item.position_changed.connect(signal_callback)
|
||||
|
||||
tick_item.set_position(pos=1)
|
||||
assert tick_item._tick_pos == 1
|
||||
tick_item.set_position(pos=2)
|
||||
assert tick_item._tick_pos == 2
|
||||
assert container == [1.0, 2.0]
|
Reference in New Issue
Block a user