From 3e1708bf48bc15a25c0d01242fff28d6db868e02 Mon Sep 17 00:00:00 2001 From: appel_c Date: Tue, 18 Jul 2023 14:16:25 +0200 Subject: [PATCH] feat: add auto-computed color_list from colormaps --- bec_widgets/line_plot.py | 64 ++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 9 deletions(-) diff --git a/bec_widgets/line_plot.py b/bec_widgets/line_plot.py index a8101ea2..3ea01d5b 100644 --- a/bec_widgets/line_plot.py +++ b/bec_widgets/line_plot.py @@ -2,7 +2,7 @@ from typing import Any import numpy as np import pyqtgraph as pg -from pyqtgraph import mkPen, mkBrush +from pyqtgraph import mkPen, mkBrush, mkColor from pyqtgraph.Qt import QtCore, QtWidgets, uic from pyqtgraph.Qt.QtCore import pyqtSignal @@ -31,31 +31,37 @@ class BasicPlot(QtWidgets.QWidget): self.plotter_data_y = [] self.curves = [] self.pens = [] + self.brushs = [] self.plotter_scan_id = None # TODO to be moved to utils function plotstyles = { "symbol": "o", - "symbolSize": 12, + "symbolSize": 10, } color_list = ["#384c6b", "#e28a2b", "#5E3023", "#e41a1c", "#984e83", "#4daf4a"] + color_list = BasicPlot.golden_angle_color(colormap="viridis", num=len(self.y_value_list)) # setup plots self.plot = self.plot_window.getPlotItem() for ii in range(len(self.y_value_list)): if ii < len(color_list): pen = mkPen(color=color_list[ii], width=2, style=QtCore.Qt.DashLine) + brush = mkBrush(color=color_list[ii]) else: + color = list(np.random.choice(range(255), size=3)) pen = mkPen( - color=list(np.random.choice(range(255), size=3)), + color=color, width=2, style=QtCore.Qt.DashLine, ) - curve = pg.ScatterPlotItem(**plotstyles, pen=pen, skipFiniteCheck=True) + brush = mkBrush(color=color) + curve = pg.PlotDataItem(**plotstyles, symbolBrush=brush, pen=pen, skipFiniteCheck=True) self.plot.addItem(curve) self.curves.append(curve) self.pens.append(pen) + self.brushs.append(brush) # self.plot.plot(**plotstyles) # self.plot_data = self.plot.plot([], [], **plotstyles, pen=self.pen, title=name) @@ -86,17 +92,22 @@ class BasicPlot(QtWidgets.QWidget): closest_point = self.closest_x_y_value( mousePoint.x(), self.plotter_data_x, self.plotter_data_y[ii] ) + # TODO fix text wobble in plot, see plot when it crosses 0 + x_data = f"{closest_point[0]:.{self.precision}f}" + y_data = f"{closest_point[1]:.{self.precision}f}" + string_cap = 10 self.mouse_box_data.setText( "".join( [ self.mouse_box_data.text(), "\n", - f"", # rgba{self.pens[ii].color().getRgb() + # TODO fix different fonts for mouse cursor! + # f"", # rgba{self.pens[ii].color().getRgb() f"{y_value}", "\n", - f"X_data: {closest_point[0]:.{self.precision}f}", + f"X_data: {x_data:>string_cap}", "\n", - f"Y_data: {closest_point[1]:.{self.precision}f}

", + f"Y_data: {y_data:>string_cap}", ] ) # f"Mouse cursor\n" @@ -137,7 +148,7 @@ class BasicPlot(QtWidgets.QWidget): self.precision = client.device_manager.devices[scan_motors[0]]._info["describe"][ scan_motors[0] ]["precision"] - # TODO + # TODO after update of bec_lib, this will be new way to access data # self.precision = client.device_manager.devices[scan_motors[0]].precision x = data["data"][scan_motors[0]][scan_motors[0]]["value"] self.plotter_data_x.append(x) @@ -159,6 +170,38 @@ class BasicPlot(QtWidgets.QWidget): self.plotter_data_y.append([]) self.mouse_box_data.setText("Mouse cursor") # Crashes the Thread + @staticmethod + def golden_ratio(num: int): + # get the first num golden angles + phi = 2 * np.pi * ((1 + np.sqrt(5)) / 2) + angles = [] + for ii in range(num): + x = np.cos(ii * phi) + y = np.sin(ii * phi) + angle = np.arctan2(y, x) + angles.append(angle) + return angles + + @staticmethod + def golden_angle_color(colormap: str, num: int): + cmap = pg.colormap.get(colormap) + cmap_colors = cmap.color + if num > len(cmap_colors): + raise ValueError( + f"Number of colors requested ({num}) is greater than the number of colors in the colormap ({len(cmap_colors)})" + ) + angles = BasicPlot.golden_ratio(len(cmap_colors)) + color_selection = np.round(np.interp(angles, (-np.pi, np.pi), (0, len(cmap_colors)))) + colors = [ + mkColor(tuple((cmap_colors[int(ii)] * 255).astype(int))) for ii in color_selection[:num] + ] + return colors + + @staticmethod + def rgb_to_hex(rgb: np.ndarray) -> str: + rgb = rgb.reshape(3) + return "#{:02X}{:02X}{:02X}".format(*rgb) + if __name__ == "__main__": import argparse @@ -167,7 +210,10 @@ if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument( - "--signals", help="specify recorded signals", nargs="+", default=["gauss_bpm"] + "--signals", + help="specify recorded signals", + nargs="+", + default=["gauss_bpm", "bpm4i", "bpm5i", "bpm6i"], ) value = parser.parse_args() print(f"Plotting signals for: {', '.join(value.signals)}")