From 512e698e26d9eef05b4f430475ccc268b68ad632 Mon Sep 17 00:00:00 2001
From: wyzula-jan <133381102+wyzula-jan@users.noreply.github.com>
Date: Fri, 18 Aug 2023 17:06:37 +0200
Subject: [PATCH] feat: setting map according to motor limits
---
.../motor_movement/motor_controller.ui | 200 +++++++++++++++---
.../examples/motor_movement/motor_example.py | 143 +++++++++++--
2 files changed, 297 insertions(+), 46 deletions(-)
diff --git a/bec_widgets/examples/motor_movement/motor_controller.ui b/bec_widgets/examples/motor_movement/motor_controller.ui
index ba2dc0da..13cc96c5 100644
--- a/bec_widgets/examples/motor_movement/motor_controller.ui
+++ b/bec_widgets/examples/motor_movement/motor_controller.ui
@@ -6,33 +6,74 @@
0
0
- 800
- 266
+ 1289
+ 596
Motor Controller
-
+
-
-
-
- Motor Position
-
-
- Qt::AlignCenter
-
-
-
- -
-
+
+
-
+
+
+ Motor Position
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
-
+
+
+ Go
+
+
+
+ -
+
+
+ Save
+
+
+
+
+
-
- false
+ true
+
+
+ -
+
+
-
+
+
+ General
+
+
+
-
+
+
+ Decimal precision
+
+
+
+ -
+
+
+
+
+
-
@@ -92,7 +133,7 @@
-
- false
+ true
Motor Limits
@@ -120,13 +161,34 @@
-
-
+
+
+ -1000
+
+
+ 1000
+
+
-
-
+
+
+ -1000
+
+
+ 1000
+
+
-
-
+
+
+ -1000
+
+
+ 1000
+
+
-
@@ -136,12 +198,12 @@
-
-
-
- -
-
-
- Update
+
+
+ -1000
+
+
+ 1000
@@ -150,6 +212,94 @@
+ -
+
+
+ 0
+
+
+
+ Saved
+
+
+
-
+
+
+ Go to selected
+
+
+
+ -
+
+
+
+ Show
+
+
+
+
+ X
+
+
+
+
+ Y
+
+
+
+
+
+
+
+
+ Queue
+
+
+ -
+
+
+ Reset Queue
+
+
+
+ -
+
+
+
+ queueID
+
+
+
+
+ scanID
+
+
+
+
+ is_scan
+
+
+
+
+ type
+
+
+
+
+ scan_number
+
+
+
+
+ IQ status
+
+
+
+
+
+
+
+
diff --git a/bec_widgets/examples/motor_movement/motor_example.py b/bec_widgets/examples/motor_movement/motor_example.py
index 27eaaf73..491c50c5 100644
--- a/bec_widgets/examples/motor_movement/motor_example.py
+++ b/bec_widgets/examples/motor_movement/motor_example.py
@@ -1,6 +1,7 @@
import os
import numpy as np
+from PyQt5 import QtGui
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QApplication, QWidget
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)
# 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()
def init_ui(self):
@@ -31,13 +39,17 @@ class MotorApp(QWidget):
self.image_map = pg.ImageItem()
self.plot_map.addItem(self.image_map)
- self.image_map_data = np.zeros((100, 100), dtype=np.float32)
- x, y = self.get_xy() # Assuming get_xy returns the motor position
- self.update_image_map(x, y)
- self.image_map.setImage(self.image_map_data.T) # Set the image
+ # self.image_map_data = np.zeros((100, 100), dtype=np.float32)
+ # x, y = self.get_xy() # Assuming get_xy returns the motor position
+ # self.update_image_map(x, y)
+ # self.image_map.setImage(self.image_map_data.T) # Set the image
+
+ # self.init_motor_map()
+
##########################
# Signals
##########################
+
# Buttons - Motor Movement
self.toolButton_right.clicked.connect(
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())
)
+ # 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
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:
- 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()
self.motor_position.emit(motor_position)
@@ -83,22 +200,6 @@ class MotorApp(QWidget):
y = dev.samy.position()
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__":
from bec_widgets.bec_dispatcher import bec_dispatcher