0
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2025-07-13 19:21:50 +02:00

fix: correct coordinates for cursor table

This commit is contained in:
wyzula-jan
2023-08-15 14:01:23 +02:00
parent 98e711f4d0
commit ce54daf754
4 changed files with 240 additions and 94 deletions

View File

@ -42,15 +42,9 @@ class BasicPlot(QtWidgets.QWidget):
current_path = os.path.dirname(__file__)
uic.loadUi(os.path.join(current_path, "line_plot.ui"), self)
self.splitter_H.setSizes([1, 1])
self._idle_time = 100
self.title = ""
self.label_bottom = ""
self.label_left = ""
self.producer = RedisConnector(["localhost:6379"]).producer()
self.scan_motors = []
self.y_value_list = y_value_list
self.previous_y_value_list = None
self.plotter_data_x = []
@ -58,15 +52,6 @@ class BasicPlot(QtWidgets.QWidget):
self.plotter_scan_id = None
##########################
# Buttons
##########################
self.init_ui()
self.hook_crosshair()
self.pushButton_generate.clicked.connect(self.generate_data)
self._current_proj = None
self._current_metadata_ep = "px_stream/projection_{}/metadata"
@ -75,6 +60,21 @@ class BasicPlot(QtWidgets.QWidget):
self.data_retriever = threading.Thread(target=self.on_projection, daemon=True)
self.data_retriever.start()
# self.comboBox.currentIndexChanged.connect(lambda : print(f'current comboText: {self.comboBox.currentText()}'))
# self.comboBox.currentIndexChanged.connect(lambda: print(f'current comboIndex: {self.comboBox.currentIndex()}'))
#
# self.doubleSpinBox.valueChanged.connect(lambda : print('Spin Changed'))
# self.splitterH_main.setSizes([1, 1])
##########################
# UI
##########################
self.init_ui()
self.init_curves()
self.hook_crosshair()
self.pushButton_generate.clicked.connect(self.generate_data)
def init_ui(self):
"""Setup all ui elements"""
##########################
@ -89,16 +89,16 @@ class BasicPlot(QtWidgets.QWidget):
# ROI selector - so far from [-1,1] #TODO update to scale with xrange
self.roi_selector = pg.LinearRegionItem([-1, 1])
# self.glw_plot.nextRow() #TODO update of cursor
# self.label_plot_moved = pg.LabelItem(justify="center")
# self.glw_plot.addItem(self.label_plot_moved)
# self.label_plot_moved.setText("Actual coordinates (X, Y)")
#
# # Label for coordinates clicked
# self.glw_plot.nextRow()
# self.label_plot_clicked = pg.LabelItem(justify="center")
# self.glw_plot.addItem(self.label_plot_clicked)
# self.label_plot_clicked.setText("Clicked coordinates (X, Y)")
self.glw_plot.nextRow() # TODO update of cursor
self.label_plot_moved = pg.LabelItem(justify="center")
self.glw_plot.addItem(self.label_plot_moved)
self.label_plot_moved.setText("Actual coordinates (X, Y)")
# Label for coordinates clicked
self.glw_plot.nextRow()
self.label_plot_clicked = pg.LabelItem(justify="center")
self.glw_plot.addItem(self.label_plot_clicked)
self.label_plot_clicked.setText("Clicked coordinates (X, Y)")
# 1D PlotItem
self.glw_plot.nextRow()
@ -107,9 +107,47 @@ class BasicPlot(QtWidgets.QWidget):
self.glw_plot.addItem(self.plot)
self.plot.addLegend()
# check if roi selector is in the plot
if self.roi_selector not in self.plot.items:
self.plot.addItem(self.roi_selector)
##########################
# 2D Plot
##########################
# Label for coordinates moved
self.label_image_moved = pg.LabelItem(justify="center")
self.glw_image.addItem(self.label_image_moved)
self.label_image_moved.setText("Actual coordinates (X, Y)")
# Label for coordinates clicked
self.glw_image.nextRow()
self.label_image_clicked = pg.LabelItem(justify="center")
self.glw_image.addItem(self.label_image_clicked)
self.label_image_clicked.setText("Clicked coordinates (X, Y)")
# TODO try to lock aspect ratio with view
# # Create a window
# win = pg.GraphicsLayoutWidget()
# win.show()
#
# # Create a ViewBox
# view = win.addViewBox()
#
# # Lock the aspect ratio
# view.setAspectLocked(True)
# # Create an ImageItem
# image_item = pg.ImageItem(np.random.random((100, 100)))
#
# # Add the ImageItem to the ViewBox
# view.addItem(image_item)
# 2D ImageItem
self.glw_image.nextRow()
self.plot_image = pg.PlotItem()
self.glw_image.addItem(self.plot_image)
def init_curves(self):
# init of 1D plot
self.plot.clear()
self.curves = []
self.pens = []
@ -128,31 +166,36 @@ class BasicPlot(QtWidgets.QWidget):
self.pens.append(pen)
self.brushs.append(brush)
##########################
# 2D Plot
##########################
# check if roi selector is in the plot
if self.roi_selector not in self.plot.items:
self.plot.addItem(self.roi_selector)
# Label for coordinates moved
self.label_image_moved = pg.LabelItem(justify="center")
self.glw_image.addItem(self.label_image_moved)
self.label_image_moved.setText("Actual coordinates (X, Y)")
# init of 2D plot
self.plot_image.clear()
# Label for coordinates clicked
self.glw_image.nextRow()
self.label_image_clicked = pg.LabelItem(justify="center")
self.glw_image.addItem(self.label_image_clicked)
self.label_image_clicked.setText("Clicked coordinates (X, Y)")
# 2D ImageItem
self.glw_image.nextRow()
self.plot_image = pg.PlotItem()
self.img = pg.ImageItem()
self.glw_image.addItem(self.plot_image)
self.plot_image.addItem(self.img)
def hook_crosshair(self):
# hooking signals
self.hook_crosshair()
self.init_table()
def splitter_sizes(self):
...
# self.crosshair_plot = Crosshair(self.plot, precision=2)
def hook_crosshair(self):
self.crosshair_1d = Crosshair(self.plot, precision=4)
self.crosshair_1d.coordinatesChanged1D.connect(
lambda x, y: self.label_plot_moved.setText(f"Moved : ({x}, {y})")
)
self.crosshair_1d.coordinatesClicked1D.connect(
lambda x, y: self.label_plot_clicked.setText(f"Moved : ({x}, {y})")
)
self.crosshair_1d.coordinatesChanged1D.connect(
lambda x, y: self.update_table(table_widget=self.cursor_table, x=x, y_values=y)
)
self.crosshair_2D = Crosshair(self.plot_image)
@ -170,21 +213,21 @@ class BasicPlot(QtWidgets.QWidget):
def gauss(x, mu, sigma):
return (1 / (sigma * np.sqrt(2 * np.pi))) * np.exp(-0.5 * ((x - mu) / sigma) ** 2)
mu = 0 # mean
sigma = 1 # standard deviation
self.plotter_data_x = np.linspace(0, 10, 1000)
self.plotter_data_y = [
gauss(self.plotter_data_x, mu, sigma),
gauss(self.plotter_data_x, 1, 1),
gauss(self.plotter_data_x, 1.5, 3),
np.sin(self.plotter_data_x),
np.cos(self.plotter_data_x),
np.sin(2 * self.plotter_data_x),
] # List of y-values for multiple curves
self.y_value_list = ["gauss"] # ["Sine"]#, "Cosine", "Sine2x"]
self.y_value_list = ["Gauss (1,1)", "Gauss (1.5,3)"] # ["Sine"]#, "Cosine", "Sine2x"]
# Curves
color_list = ["#384c6b", "#e28a2b", "#5E3023", "#e41a1c", "#984e83", "#4daf4a"]
self.init_curves()
for ii in range(len(self.y_value_list)):
self.curves[ii].setData(self.plotter_data_x, self.plotter_data_y[ii])
@ -208,11 +251,22 @@ class BasicPlot(QtWidgets.QWidget):
self.producer.set_and_publish("px_stream/gui_event", msg=msg)
self.roi_signal.emit(region)
def init_table(self):
# Init number of rows in table according to n of devices
self.cursor_table.setRowCount(len(self.y_value_list))
# self.table.setHorizontalHeaderLabels(["(X, Y) - Moved", "(X, Y) - Clicked"]) #TODO can be dynamic
self.cursor_table.setVerticalHeaderLabels(self.y_value_list)
self.cursor_table.resizeColumnsToContents()
def update_table(self, table_widget, x, y_values):
for i, y in enumerate(y_values):
table_widget.setItem(i, 1, QTableWidgetItem(str(x)))
table_widget.setItem(i, 2, QTableWidgetItem(str(y)))
table_widget.resizeColumnsToContents()
def update(self):
"""Update the plot with the new data."""
print("updated")
# check if QTable was initialised and if list of devices was changed
# if self.y_value_list != self.previous_y_value_list:
# self.setup_cursor_table()
@ -307,7 +361,6 @@ class BasicPlot(QtWidgets.QWidget):
@pyqtSlot(dict, dict)
def on_dap_update(self, data: dict, metadata: dict):
self.img.setImage(data["z"])
# time.sleep(0,1)
@pyqtSlot(dict)
def new_proj(self, data):
@ -337,6 +390,7 @@ if __name__ == "__main__":
default=["gauss_bpm"],
)
# default = ["gauss_bpm", "bpm4i", "bpm5i", "bpm6i", "xert"],
# dispatcher = bec_dispatcher
value = parser.parse_args()
print(f"Plotting signals for: {', '.join(value.signals)}")
client = bec_dispatcher.client
@ -347,6 +401,8 @@ if __name__ == "__main__":
# bec_dispatcher.connect(plot)
bec_dispatcher.connect_proj_id(plot.new_proj)
bec_dispatcher.connect_dap_slot(plot.on_dap_update, "px_dap_worker")
plot.roi_signal.connect(lambda x: print(f"signal from ROI {x}"))
plot.roi_signal.connect(lambda x: bec_dispatcher.getStuff(x))
plot.show()
# client.callbacks.register("scan_segment", plot, sync=False)
app.exec_()

View File

@ -13,24 +13,17 @@
<property name="windowTitle">
<string>Line Plot</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="pushButton_generate">
<property name="text">
<string>Generate 1D and 2D data without stream</string>
</property>
</widget>
</item>
<item>
<widget class="QSplitter" name="splitter_H">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QSplitter" name="splitter_plot">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="orientation">
@ -39,30 +32,112 @@
<widget class="GraphicsLayoutWidget" name="glw_plot"/>
<widget class="GraphicsLayoutWidget" name="glw_image"/>
</widget>
<widget class="QTableWidget" name="cursor_table">
<property name="textElideMode">
<enum>Qt::ElideMiddle</enum>
</property>
<column>
<property name="text">
<string>Display</string>
</property>
</column>
<column>
<property name="text">
<string>Device</string>
</property>
</column>
<column>
<property name="text">
<string>X</string>
</property>
</column>
<column>
<property name="text">
<string>Y</string>
</property>
</column>
<widget class="QWidget" name="">
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,1,1,15">
<item>
<widget class="QPushButton" name="pushButton_generate">
<property name="text">
<string>Generate 1D and 2D data without stream</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>1st angle of azimutal segment (deg)</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<double>360.000000000000000</double>
</property>
<property name="singleStep">
<double>0.250000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>f1amp</string>
</property>
</item>
<item>
<property name="text">
<string>f2amp</string>
</property>
</item>
<item>
<property name="text">
<string>f2 phase</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Precision</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox_precision">
<property name="value">
<number>4</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTableWidget" name="cursor_table">
<property name="textElideMode">
<enum>Qt::ElideMiddle</enum>
</property>
<column>
<property name="text">
<string>Display</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>
</item>

View File

@ -55,10 +55,19 @@ class Crosshair(QObject):
curves.append((item.xData, item.yData))
elif isinstance(item, pg.ImageItem): # 2D plot
return item.image, None
return curves
# if curves:
# return curves
# else:
# return None
def snap_to_data(self, x, y):
data = self.get_data()
# if data is None: #TODO hadle if data are None
# return x, y
if isinstance(data, list): # 1D plot
y_values = []
for x_data, y_data in data:
@ -92,14 +101,16 @@ class Crosshair(QObject):
pos = event[0]
if self.plot_item.vb.sceneBoundingRect().contains(pos):
mouse_point = self.plot_item.vb.mapSceneToView(pos)
self.v_line.setPos(mouse_point.x())
self.h_line.setPos(mouse_point.y())
x, y = mouse_point.x(), mouse_point.y()
if self.is_log_x:
x = 10**x
if self.is_log_y:
y = 10**y
x, y_values = self.snap_to_data(x, y)
self.v_line.setPos(mouse_point.x())
self.h_line.setPos(mouse_point.y())
if isinstance(y_values, list): # 1D plot
self.coordinatesChanged1D.emit(
round(x, self.precision), [round(y_val, self.precision) for y_val in y_values]
@ -136,6 +147,8 @@ class Crosshair(QObject):
self.marker_2d.setPos([x, y_values])
def check_log(self):
# Check if plot uses log scale
"""
Check if x or y axis is in log scale
"""
self.is_log_x = self.plot_item.ctrl.logXCheck.isChecked()
self.is_log_y = self.plot_item.ctrl.logYCheck.isChecked()

View File

@ -16,6 +16,7 @@ from crosshair import Crosshair
class ExampleApp(QWidget):
def __init__(self):
"""Example application for using the Crosshair class"""
super().__init__()
# Layout
@ -128,6 +129,7 @@ class ExampleApp(QWidget):
self.column2.addWidget(self.plot_widget_2d)
def update_table(self, table_widget, x, y_values, column):
"""Update the table with the new coordinates"""
for i, y in enumerate(y_values):
table_widget.setItem(i, column, QTableWidgetItem(f"({x}, {y})"))
table_widget.resizeColumnsToContents()