0
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2025-07-14 03:31:50 +02:00

feat: new GUI

This commit is contained in:
wyzula-jan
2023-08-25 11:36:49 +02:00
parent 3c0e5955d4
commit 0226188079
2 changed files with 498 additions and 288 deletions

View File

@ -6,288 +6,268 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1289</width> <width>1115</width>
<height>596</height> <height>506</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Motor Controller</string> <string>Motor Controller</string>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout" stretch="7,1,7">
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout"> <widget class="GraphicsLayoutWidget" name="glw">
<item> <property name="enabled">
<layout class="QHBoxLayout" name="horizontalLayout"> <bool>true</bool>
<item> </property>
<widget class="QPushButton" name="pushButton_2"> </widget>
<property name="text">
<string>Go</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_3">
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="GraphicsLayoutWidget" name="glw">
<property name="enabled">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item> </item>
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="1,10,10"> <widget class="QFrame" name="Controls">
<item> <property name="minimumSize">
<widget class="QGroupBox" name="groupBox_2"> <size>
<property name="title"> <width>221</width>
<string>General</string> <height>471</height>
</property> </size>
<layout class="QGridLayout" name="gridLayout_4"> </property>
<item row="0" column="0"> <layout class="QVBoxLayout" name="verticalLayout_6">
<widget class="QLabel" name="label_5"> <item>
<property name="text"> <widget class="QGroupBox" name="motorSelection">
<string>Decimal precision</string> <property name="title">
</property> <string>Motor Selection</string>
</widget> </property>
</item> <layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="1"> <item row="2" column="0">
<widget class="QSpinBox" name="spinBox"/> <widget class="QLabel" name="label_8">
</item> <property name="text">
<item row="1" column="0"> <string>Motor Y</string>
<widget class="QLabel" name="label_8"> </property>
<property name="text"> </widget>
<string>Speed</string> </item>
</property> <item row="1" column="0">
</widget> <widget class="QLabel" name="label_5">
</item> <property name="text">
<item row="1" column="1"> <string>Motor X</string>
<widget class="QDoubleSpinBox" name="doubleSpinBox_speed"/> </property>
</item> </widget>
</layout> </item>
</widget> <item row="1" column="1">
</item> <widget class="QComboBox" name="comboBox"/>
<item> </item>
<widget class="QGroupBox" name="motorControl"> <item row="2" column="1">
<property name="title"> <widget class="QComboBox" name="comboBox_2"/>
<string>Motor Controls</string> </item>
</property> </layout>
<layout class="QVBoxLayout" name="verticalLayout_5"> </widget>
<item> </item>
<widget class="QCheckBox" name="checkBox_enableArrows"> <item>
<property name="text"> <spacer name="verticalSpacer_3">
<string>Move with arrow keys</string> <property name="orientation">
</property> <enum>Qt::Vertical</enum>
</widget> </property>
</item> <property name="sizeHint" stdset="0">
<item> <size>
<layout class="QGridLayout" name="gridLayout"> <width>20</width>
<item row="0" column="1"> <height>18</height>
<widget class="QToolButton" name="toolButton_up"> </size>
<property name="text"> </property>
<string>...</string> </spacer>
</property> </item>
<property name="arrowType"> <item>
<enum>Qt::UpArrow</enum> <widget class="QGroupBox" name="motorControl">
</property> <property name="title">
</widget> <string>Motor Relative</string>
</item> </property>
<item row="1" column="0"> <layout class="QVBoxLayout" name="verticalLayout_5">
<widget class="QToolButton" name="toolButton_left"> <item>
<property name="text"> <widget class="QCheckBox" name="checkBox_enableArrows">
<string>...</string> <property name="text">
</property> <string>Move with arrow keys</string>
<property name="arrowType"> </property>
<enum>Qt::LeftArrow</enum> </widget>
</property> </item>
</widget> <item>
</item> <layout class="QGridLayout" name="gridLayout">
<item row="1" column="1"> <property name="sizeConstraint">
<widget class="QSpinBox" name="spinBox_step"> <enum>QLayout::SetDefaultConstraint</enum>
<property name="value"> </property>
<number>5</number> <item row="1" column="2" alignment="Qt::AlignHCenter|Qt::AlignVCenter">
</property> <widget class="QToolButton" name="toolButton_up">
</widget> <property name="text">
</item> <string>...</string>
<item row="1" column="2"> </property>
<widget class="QToolButton" name="toolButton_right"> <property name="arrowType">
<property name="text"> <enum>Qt::UpArrow</enum>
<string>...</string> </property>
</property> </widget>
<property name="arrowType"> </item>
<enum>Qt::RightArrow</enum> <item row="2" column="4">
</property> <spacer name="horizontalSpacer_2">
</widget> <property name="orientation">
</item> <enum>Qt::Horizontal</enum>
<item row="2" column="1"> </property>
<widget class="QToolButton" name="toolButton_down"> <property name="sizeHint" stdset="0">
<property name="text"> <size>
<string>...</string> <width>40</width>
</property> <height>20</height>
<property name="arrowType"> </size>
<enum>Qt::DownArrow</enum> </property>
</property> </spacer>
</widget> </item>
</item> <item row="2" column="2" alignment="Qt::AlignHCenter|Qt::AlignVCenter">
</layout> <widget class="QSpinBox" name="spinBox_step">
</item> <property name="value">
<item> <number>5</number>
<layout class="QGridLayout" name="gridLayout_3"> </property>
<item row="0" column="1"> </widget>
<widget class="QLabel" name="label_6"> </item>
<property name="text"> <item row="3" column="2" alignment="Qt::AlignHCenter|Qt::AlignVCenter">
<string>X</string> <widget class="QToolButton" name="toolButton_down">
</property> <property name="text">
<property name="alignment"> <string>...</string>
<set>Qt::AlignCenter</set> </property>
</property> <property name="arrowType">
</widget> <enum>Qt::DownArrow</enum>
</item> </property>
<item row="0" column="2"> </widget>
<widget class="QLabel" name="label_7"> </item>
<property name="text"> <item row="2" column="1">
<string>Y</string> <widget class="QToolButton" name="toolButton_left">
</property> <property name="text">
<property name="alignment"> <string>...</string>
<set>Qt::AlignCenter</set> </property>
</property> <property name="arrowType">
</widget> <enum>Qt::LeftArrow</enum>
</item> </property>
<item row="1" column="0"> </widget>
<widget class="QPushButton" name="pushButton_go_absolute"> </item>
<property name="text"> <item row="0" column="2">
<string>Go</string> <spacer name="verticalSpacer">
</property> <property name="orientation">
</widget> <enum>Qt::Vertical</enum>
</item> </property>
<item row="1" column="1"> <property name="sizeHint" stdset="0">
<widget class="QSpinBox" name="spinBox_absolute_x"/> <size>
</item> <width>20</width>
<item row="1" column="2"> <height>40</height>
<widget class="QSpinBox" name="spinBox_absolute_y"/> </size>
</item> </property>
</layout> </spacer>
</item> </item>
<item> <item row="2" column="3">
<widget class="QPushButton" name="pushButton_stop"> <widget class="QToolButton" name="toolButton_right">
<property name="text"> <property name="text">
<string>Stop Movement</string> <string>...</string>
</property> </property>
</widget> <property name="arrowType">
</item> <enum>Qt::RightArrow</enum>
</layout> </property>
</widget> </widget>
</item> </item>
<item> <item row="2" column="0">
<widget class="QGroupBox" name="groupBox"> <spacer name="horizontalSpacer">
<property name="enabled"> <property name="orientation">
<bool>true</bool> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="title"> <property name="sizeHint" stdset="0">
<string>Motor Limits</string> <size>
</property> <width>40</width>
<layout class="QGridLayout" name="gridLayout_2"> <height>20</height>
<item row="3" column="1"> </size>
<widget class="QSpinBox" name="spinBox_x_min"> </property>
<property name="minimum"> </spacer>
<number>-1000</number> </item>
</property> <item row="4" column="2">
<property name="maximum"> <spacer name="verticalSpacer_2">
<number>1000</number> <property name="orientation">
</property> <enum>Qt::Vertical</enum>
<property name="value"> </property>
<number>-100</number> <property name="sizeHint" stdset="0">
</property> <size>
</widget> <width>20</width>
</item> <height>40</height>
<item row="2" column="2"> </size>
<widget class="QSpinBox" name="spinBox_y_max"> </property>
<property name="minimum"> </spacer>
<number>-1000</number> </item>
</property> </layout>
<property name="maximum"> </item>
<number>1000</number> </layout>
</property> </widget>
<property name="value"> </item>
<number>100</number> <item>
</property> <spacer name="verticalSpacer_4">
</widget> <property name="orientation">
</item> <enum>Qt::Vertical</enum>
<item row="5" column="2"> </property>
<widget class="QLabel" name="label_2"> <property name="sizeHint" stdset="0">
<property name="text"> <size>
<string>- samy</string> <width>20</width>
</property> <height>13</height>
</widget> </size>
</item> </property>
<item row="3" column="3"> </spacer>
<widget class="QSpinBox" name="spinBox_x_max"> </item>
<property name="minimum"> <item>
<number>-1000</number> <widget class="QGroupBox" name="groupBox">
</property> <property name="title">
<property name="maximum"> <string>Move Absolute</string>
<number>1000</number> </property>
</property> <layout class="QVBoxLayout" name="verticalLayout">
<property name="value"> <item>
<number>100</number> <layout class="QGridLayout" name="gridLayout_3">
</property> <item row="0" column="1">
</widget> <widget class="QLabel" name="label_6">
</item> <property name="text">
<item row="1" column="2"> <string>X</string>
<widget class="QLabel" name="label"> </property>
<property name="text"> <property name="alignment">
<string>+ samy</string> <set>Qt::AlignCenter</set>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="3"> <item row="0" column="2">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_7">
<property name="text"> <property name="text">
<string>+ samx</string> <string>Y</string>
</property> </property>
</widget> <property name="alignment">
</item> <set>Qt::AlignCenter</set>
<item row="2" column="1"> </property>
<widget class="QLabel" name="label_4"> </widget>
<property name="text"> </item>
<string>- samx</string> <item row="1" column="0">
</property> <widget class="QPushButton" name="pushButton_go_absolute">
</widget> <property name="text">
</item> <string>Go</string>
<item row="4" column="2"> </property>
<widget class="QSpinBox" name="spinBox_y_min"> </widget>
<property name="minimum"> </item>
<number>-1000</number> <item row="1" column="1">
</property> <widget class="QSpinBox" name="spinBox_absolute_x"/>
<property name="maximum"> </item>
<number>1000</number> <item row="1" column="2">
</property> <widget class="QSpinBox" name="spinBox_absolute_y"/>
<property name="value"> </item>
<number>-100</number> </layout>
</property> </item>
</widget> <item>
</item> <widget class="QPushButton" name="pushButton_stop">
<item row="3" column="2"> <property name="text">
<widget class="QPushButton" name="pushButton_updateLimits"> <string>Stop Movement</string>
<property name="text"> </property>
<string>Update</string> </widget>
</property> </item>
</widget> </layout>
</item> </widget>
</layout> </item>
</widget> </layout>
</item> </widget>
</layout>
</item> </item>
<item> <item>
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabWidget_tables">
<property name="enabled">
<bool>true</bool>
</property>
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>0</number>
</property> </property>
@ -327,6 +307,209 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>Settings</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QGroupBox" name="motorConfig">
<property name="title">
<string>Motor Limits</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="3" column="1">
<widget class="QSpinBox" name="spinBox_y_min">
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="minimum">
<number>-1000</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>-100</number>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="pushButton_updateLimits">
<property name="text">
<string>Update</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="spinBox_x_max">
<property name="minimum">
<number>-1000</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_Y_max">
<property name="text">
<string>+ Y</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBox_y_max">
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="minimum">
<number>-1000</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QSpinBox" name="spinBox_x_min">
<property name="minimum">
<number>-1000</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>-100</number>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_Y_min">
<property name="text">
<string>- Y</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_X_min">
<property name="text">
<string>- X</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_X_max">
<property name="text">
<string>+ X</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Motor config</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="4" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox"/>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBox"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Tolerance</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Update Frequency</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="spinBox_2"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Decimal Precision</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="spinBox_3"/>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_9">
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Speed</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Y</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>X = Y</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QSpinBox" name="spinBox_4"/>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="spinBox_5"/>
</item>
<item row="3" column="2">
<widget class="QSpinBox" name="spinBox_6"/>
</item>
<item row="4" column="2">
<widget class="QDoubleSpinBox" name="doubleSpinBox_2"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2"> <widget class="QWidget" name="tab_2">
<attribute name="title"> <attribute name="title">
<string>Queue</string> <string>Queue</string>
@ -334,6 +517,9 @@
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<widget class="QPushButton" name="pushButton_5"> <widget class="QPushButton" name="pushButton_5">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text"> <property name="text">
<string>Reset Queue</string> <string>Reset Queue</string>
</property> </property>
@ -341,6 +527,9 @@
</item> </item>
<item> <item>
<widget class="QTableWidget" name="tableWidget_2"> <widget class="QTableWidget" name="tableWidget_2">
<property name="enabled">
<bool>false</bool>
</property>
<column> <column>
<property name="text"> <property name="text">
<string>queueID</string> <string>queueID</string>

View File

@ -11,6 +11,18 @@ from pyqtgraph.Qt import QtWidgets, uic
from bec_lib.core import MessageEndpoints, BECMessage from bec_lib.core import MessageEndpoints, BECMessage
# TODO - General features
# - setting motor speed and frequency
# - setting motor acceleration
# - updating motor precision
# - put motor selection dropdown or listwidget
# - put motor status (moving, stopped, etc)
# - remove all hardcoded references to samx and samy
# - add spinBox for motor scatter size
# - add mouse interactions with the plot -> click to select coordinates, double click to move?
# - adjust right click actions
class MotorApp(QWidget): class MotorApp(QWidget):
coordinates_updated = pyqtSignal(float, float) coordinates_updated = pyqtSignal(float, float)
@ -23,9 +35,8 @@ class MotorApp(QWidget):
# Coordinates tracking # Coordinates tracking
self.motor_positions = np.array([]) self.motor_positions = np.array([])
self.max_points = 50 # Maximum number of points to keep self.max_points = 5000 # Maximum number of points to keep
self.num_dim_points = 15 # Number of points to dim gradually self.num_dim_points = 15 # Number of points to dim gradually
self.precision = 2 # Define the decimal precision
# QThread for motor movement + signals # QThread for motor movement + signals
self.motor_thread = MotorControl() self.motor_thread = MotorControl()
@ -40,9 +51,6 @@ class MotorApp(QWidget):
print(f"Init limits: samx:{self.limit_x}, samy:{self.limit_y}") print(f"Init limits: samx:{self.limit_x}, samy:{self.limit_y}")
# self.background_map_scale = 10
# self.visited_coordinates = {}
# Initialize the image map # Initialize the image map
self.init_motor_map() self.init_motor_map()
@ -103,6 +111,14 @@ class MotorApp(QWidget):
size=2, pen=pg.mkPen(None), brush=pg.mkBrush(255, 255, 255, 255) size=2, pen=pg.mkPen(None), brush=pg.mkBrush(255, 255, 255, 255)
) )
self.plot_map.addItem(self.motor_map) self.plot_map.addItem(self.motor_map)
self.plot_map.showGrid(x=True, y=True)
##########################
# Motor General setting
##########################
# TODO make function to update precision
self.precision = 2 # self.spinBox_precision.value() # Define the decimal precision
########################## ##########################
# Motor movements signals # Motor movements signals
@ -132,6 +148,9 @@ class MotorApp(QWidget):
) )
) )
self.pushButton_go_absolute.clicked.connect(self.save_absolute_coordinates) self.pushButton_go_absolute.clicked.connect(self.save_absolute_coordinates)
self.pushButton_go_absolute.setShortcut("Ctrl+G")
self.pushButton_go_absolute.setToolTip("Ctrl+G")
self.motor_thread.move_finished.connect(lambda: self.enable_motor_controls(True)) self.motor_thread.move_finished.connect(lambda: self.enable_motor_controls(True))
# Stop Button # Stop Button
@ -158,7 +177,7 @@ class MotorApp(QWidget):
# TODO map with floats as well -> or decide system for higher precision # TODO map with floats as well -> or decide system for higher precision
self.motor_thread.coordinates_updated.connect( self.motor_thread.coordinates_updated.connect(
lambda x, y: self.update_image_map(round(x, 2), round(y, 2)) lambda x, y: self.update_image_map(round(x, self.precision), round(y, self.precision))
) )
# Coordinates table # Coordinates table
@ -294,19 +313,23 @@ class MotorControl(QThread):
move_finished = pyqtSignal() # Signal to emit when the move is finished move_finished = pyqtSignal() # Signal to emit when the move is finished
# progress_updated = pyqtSignal(int) #TODO Signal to emit progress percentage # progress_updated = pyqtSignal(int) #TODO Signal to emit progress percentage
def __init__(self, parent=None): def __init__(
self,
active_devices=["samx", "samy"],
parent=None,
):
super().__init__(parent) super().__init__(parent)
self.target_coordinates = None self.target_coordinates = None
self.running = False self.running = False
self.active_devices = active_devices
# Initialize current coordinates with the provided initial coordinates # Initialize current coordinates with the provided initial coordinates
( (
self.current_x, self.current_x,
self.current_y, self.current_y,
) = self.get_coordinates() # TODO maybe not needed, coordinates always stored in redis ) = self.get_coordinates() # TODO maybe not needed, coordinates always stored in redis
self.active_devices = ["samx", "samy"]
self.motors_consumer = client.connector.consumer( self.motors_consumer = client.connector.consumer(
topics=[ topics=[
MessageEndpoints.device_readback(self.active_devices[0]), MessageEndpoints.device_readback(self.active_devices[0]),
@ -319,13 +342,9 @@ class MotorControl(QThread):
self.motors_consumer.start() self.motors_consumer.start()
def get_coordinates(self) -> tuple: def get_coordinates(self) -> tuple:
# TODO decide if the get_coordinates and retrieve coordinates makes sense
# TODO or move also to signal/slot as in the case of limits
# TODO or move just to redis CB function
"""Get current motor position""" """Get current motor position"""
dev.samx.read(cached=True) # TODO to get last message ['value'] -> last position x = dev.samx.read(cached=True)["value"] # TODO remove hardcoded samx and samy
x = dev.samx.position() y = dev.samx.read(cached=True)["value"]
y = dev.samy.position()
return x, y return x, y
def retrieve_coordinates(self) -> tuple: def retrieve_coordinates(self) -> tuple:
@ -360,7 +379,9 @@ class MotorControl(QThread):
if current_position[0] < x_limit[0] or current_position[0] > x_limit[1]: if current_position[0] < x_limit[0] or current_position[0] > x_limit[1]:
raise ValueError("Current motor position is outside the new limits (X)") raise ValueError("Current motor position is outside the new limits (X)")
else: else:
self.update_motor_limits(dev.samx, low_limit=x_limit[0], high_limit=x_limit[1]) self.update_motor_limits(
dev.samx, low_limit=x_limit[0], high_limit=x_limit[1]
) # TODO Remove hardcoded samx and samy
if y_limit is not None: if y_limit is not None:
if current_position[1] < y_limit[0] or current_position[1] > y_limit[1]: if current_position[1] < y_limit[0] or current_position[1] > y_limit[1]: