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

feat: setting map according to motor limits

This commit is contained in:
wyzula-jan
2023-08-18 17:06:37 +02:00
parent e6952a6d13
commit 512e698e26
2 changed files with 297 additions and 46 deletions

View File

@ -6,33 +6,74 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>800</width> <width>1289</width>
<height>266</height> <height>596</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Motor Controller</string> <string>Motor Controller</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<item> <item>
<widget class="QLabel" name="label_status"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="text"> <item>
<string>Motor Position</string> <widget class="QLabel" name="label_status">
</property> <property name="text">
<property name="alignment"> <string>Motor Position</string>
<set>Qt::AlignCenter</set> </property>
</property> <property name="alignment">
</widget> <set>Qt::AlignCenter</set>
</item> </property>
<item> </widget>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1,1"> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="pushButton_2">
<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> <item>
<widget class="GraphicsLayoutWidget" name="glw"> <widget class="GraphicsLayoutWidget" name="glw">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="1,10,10">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>General</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Decimal precision</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox"/>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QGroupBox" name="motorControl"> <widget class="QGroupBox" name="motorControl">
<property name="title"> <property name="title">
@ -92,7 +133,7 @@
<item> <item>
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="groupBox">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>true</bool>
</property> </property>
<property name="title"> <property name="title">
<string>Motor Limits</string> <string>Motor Limits</string>
@ -120,13 +161,34 @@
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="2" column="1">
<widget class="QSpinBox" name="spinBox_samxN"/> <widget class="QSpinBox" name="spinBox_x_min">
<property name="minimum">
<number>-1000</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
</widget>
</item> </item>
<item row="1" column="2"> <item row="1" column="2">
<widget class="QSpinBox" name="spinBox_samyP"/> <widget class="QSpinBox" name="spinBox_y_max">
<property name="minimum">
<number>-1000</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
</widget>
</item> </item>
<item row="2" column="3"> <item row="2" column="3">
<widget class="QSpinBox" name="spinBox_samxP"/> <widget class="QSpinBox" name="spinBox_x_max">
<property name="minimum">
<number>-1000</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
</widget>
</item> </item>
<item row="1" column="3"> <item row="1" column="3">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
@ -136,12 +198,12 @@
</widget> </widget>
</item> </item>
<item row="3" column="2"> <item row="3" column="2">
<widget class="QSpinBox" name="spinBox_samyN"/> <widget class="QSpinBox" name="spinBox_y_min">
</item> <property name="minimum">
<item row="2" column="2"> <number>-1000</number>
<widget class="QPushButton" name="pushButton"> </property>
<property name="text"> <property name="maximum">
<string>Update</string> <number>1000</number>
</property> </property>
</widget> </widget>
</item> </item>
@ -150,6 +212,94 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Saved</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QPushButton" name="pushButton_4">
<property name="text">
<string>Go to selected</string>
</property>
</widget>
</item>
<item>
<widget class="QTableWidget" name="tableWidget">
<column>
<property name="text">
<string>Show</string>
</property>
</column>
<column>
<property name="text">
<string>X</string>
</property>
</column>
<column>
<property name="text">
<string>Y</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Queue</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="pushButton_5">
<property name="text">
<string>Reset Queue</string>
</property>
</widget>
</item>
<item>
<widget class="QTableWidget" name="tableWidget_2">
<column>
<property name="text">
<string>queueID</string>
</property>
</column>
<column>
<property name="text">
<string>scanID</string>
</property>
</column>
<column>
<property name="text">
<string>is_scan</string>
</property>
</column>
<column>
<property name="text">
<string>type</string>
</property>
</column>
<column>
<property name="text">
<string>scan_number</string>
</property>
</column>
<column>
<property name="text">
<string>IQ status</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<customwidgets> <customwidgets>

View File

@ -1,6 +1,7 @@
import os import os
import numpy as np import numpy as np
from PyQt5 import QtGui
from PyQt5.QtCore import pyqtSignal from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QApplication, QWidget from PyQt5.QtWidgets import QApplication, QWidget
from pyqtgraph.Qt import QtCore, QtWidgets, uic from pyqtgraph.Qt import QtCore, QtWidgets, uic
@ -17,7 +18,14 @@ class MotorApp(QWidget):
uic.loadUi(os.path.join(current_path, "motor_controller.ui"), self) uic.loadUi(os.path.join(current_path, "motor_controller.ui"), self)
# UI # UI
self.start_x, self.start_y = self.get_xy()
self.limit_x, self.limit_y = self.get_motor_limits(dev.samx), self.get_motor_limits(
dev.samy
)
self.label_status.setText(
f"Motor position: ({dev.samx.position():.2f}, {dev.samy.position():.2f})"
)
self.init_ui() self.init_ui()
def init_ui(self): def init_ui(self):
@ -31,13 +39,17 @@ class MotorApp(QWidget):
self.image_map = pg.ImageItem() self.image_map = pg.ImageItem()
self.plot_map.addItem(self.image_map) self.plot_map.addItem(self.image_map)
self.image_map_data = np.zeros((100, 100), dtype=np.float32) # self.image_map_data = np.zeros((100, 100), dtype=np.float32)
x, y = self.get_xy() # Assuming get_xy returns the motor position # x, y = self.get_xy() # Assuming get_xy returns the motor position
self.update_image_map(x, y) # self.update_image_map(x, y)
self.image_map.setImage(self.image_map_data.T) # Set the image # self.image_map.setImage(self.image_map_data.T) # Set the image
# self.init_motor_map()
########################## ##########################
# Signals # Signals
########################## ##########################
# Buttons - Motor Movement # Buttons - Motor Movement
self.toolButton_right.clicked.connect( self.toolButton_right.clicked.connect(
lambda: self.move_motor(dev.samx, self.spinBox_step.value()) lambda: self.move_motor(dev.samx, self.spinBox_step.value())
@ -52,6 +64,32 @@ class MotorApp(QWidget):
lambda: self.move_motor(dev.samy, -self.spinBox_step.value()) lambda: self.move_motor(dev.samy, -self.spinBox_step.value())
) )
# SpinBoxes - Motor Limits #TODO make spinboxes own limits updated, currently is [-1000, 1000]
# manually set limits before readout #TODO will be removed when spinboxes have own limits
# dev.samx.low_limit = -100
# dev.samx.high_limit = 100
# dev.samy.low_limit = -100
# dev.samy.high_limit = 100
# display initial limits
self.spinBox_x_min.setValue(self.limit_x[0])
self.spinBox_x_max.setValue(self.limit_x[1])
self.spinBox_y_min.setValue(self.limit_y[0])
self.spinBox_y_max.setValue(self.limit_y[1])
# # change limits of motors for all motors and spinboxes
self.spinBox_x_min.valueChanged.connect(
lambda x: self.update_motor_limits(dev.samx, low_limit=x)
)
self.spinBox_x_max.valueChanged.connect(
lambda x: self.update_motor_limits(dev.samx, high_limit=x)
)
self.spinBox_y_min.valueChanged.connect(
lambda x: self.update_motor_limits(dev.samy, low_limit=x)
)
self.spinBox_y_max.valueChanged.connect(
lambda x: self.update_motor_limits(dev.samy, high_limit=x)
)
# Map # Map
self.motor_position.connect(lambda x: self.update_image_map(*self.get_xy())) self.motor_position.connect(lambda x: self.update_image_map(*self.get_xy()))
@ -70,8 +108,87 @@ class MotorApp(QWidget):
) )
) )
self.init_motor_map()
def init_motor_map(self):
# Get motor limits
limit_x_min, limit_x_max = self.get_motor_limits(dev.samx)
limit_y_min, limit_y_max = self.get_motor_limits(dev.samy)
self.offset_x = limit_x_min
self.offset_y = limit_y_min
# Define the size of the image map based on the motor's limits
map_width = limit_x_max - limit_x_min + 1
map_height = limit_y_max - limit_y_min + 1
# Create an empty image map
self.background_value = 15
self.image_map_data = np.full(
(map_width, map_height), self.background_value, dtype=np.float32
)
# Set the initial position on the map
x, y = self.get_xy()
self.prev_x, self.prev_y = x, y
self.update_image_map(x, y)
# Translate and scale the image item to match the motor coordinates
self.tr = QtGui.QTransform()
self.tr.translate(limit_x_min, limit_y_min)
self.image_map.setTransform(self.tr)
self.image_map.dataTransform()
def update_image_map(self, x, y):
"""Update the image map with the new motor position"""
# Define the dimming factor
dimming_factor = 0.80
# Apply the dimming factor only to pixels above the background value
self.image_map_data[self.image_map_data > self.background_value] *= dimming_factor
# Mapping of motor coordinates to pixel coordinates
pixel_x = int(x - self.offset_x)
pixel_y = int(y - self.offset_y)
# Set the bright pixel at the new position
self.image_map_data[pixel_x, pixel_y] = 255
# Update the display
self.image_map.updateImage(self.image_map_data, levels=(0, 255))
def get_motor_limits(self, motor):
"""Get the limits of a motor"""
high_limit = motor.high_limit
low_limit = motor.low_limit
return low_limit, high_limit
def update_motor_limits(self, motor, low_limit=None, high_limit=None):
# Get current limits
current_low_limit, current_high_limit = motor.limits[0], motor.limits[1]
# Check if the low limit has changed and is not None
if low_limit is not None and low_limit != current_low_limit:
motor.low_limit = low_limit
# Check if the high limit has changed and is not None
if high_limit is not None and high_limit != current_high_limit:
motor.high_limit = high_limit
def move_motor(self, motor, value: float) -> None: def move_motor(self, motor, value: float) -> None:
scans.mv(motor, value, relative=True) try:
status = scans.mv(motor, value, relative=True)
while status.status not in ["COMPLETED", "STOPPED"]:
print(status.status)
# return status
except Exception as e:
print(e)
motor_position = motor.position() motor_position = motor.position()
self.motor_position.emit(motor_position) self.motor_position.emit(motor_position)
@ -83,22 +200,6 @@ class MotorApp(QWidget):
y = dev.samy.position() y = dev.samy.position()
return x, y return x, y
def update_image_map(self, x, y):
"""Update the image map with the new motor position"""
# Reduce the brightness of all pixels by a fixed fraction (e.g., 5%)
self.image_map_data *= 0.8
# Modify this mapping as needed
pixel_x = int(x)
pixel_y = int(y)
# Set the bright pixel at the new position
self.image_map_data[pixel_x, pixel_y] = 255
# Update the display
self.image_map.setImage(self.image_map_data)
if __name__ == "__main__": if __name__ == "__main__":
from bec_widgets.bec_dispatcher import bec_dispatcher from bec_widgets.bec_dispatcher import bec_dispatcher