1
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2026-05-10 00:32:10 +02:00

Compare commits

...

4 Commits

15 changed files with 293 additions and 42 deletions
+9 -2
View File
@@ -248,11 +248,11 @@ class BECWaveform(RPCBase):
""" """
@rpc_call @rpc_call
def apply_config(self, config: "dict | WidgetConfig", replot_last_scan: "bool" = False): def apply_config(self, config: "dict | SubplotConfig", replot_last_scan: "bool" = False):
""" """
Apply the configuration to the 1D waveform widget. Apply the configuration to the 1D waveform widget.
Args: Args:
config(dict|WidgetConfig): Configuration settings. config(dict|SubplotConfig): Configuration settings.
replot_last_scan(bool, optional): If True, replot the last scan. Defaults to False. replot_last_scan(bool, optional): If True, replot the last scan. Defaults to False.
""" """
@@ -614,6 +614,13 @@ class BECFigure(RPCBase, BECFigureClientMixin):
Clear all widgets from the figure and reset to default state Clear all widgets from the figure and reset to default state
""" """
@property
@rpc_call
def containers(self) -> "dict":
"""
None
"""
class BECCurve(RPCBase): class BECCurve(RPCBase):
@property @property
+35 -11
View File
@@ -1,10 +1,12 @@
import inspect import inspect
from typing import Literal
from bec_lib import MessageEndpoints, messages from bec_lib import MessageEndpoints, messages
from qtpy.QtCore import QTimer from qtpy.QtCore import QTimer
from bec_widgets.utils import BECDispatcher from bec_widgets.utils import BECDispatcher
from bec_widgets.utils.bec_connector import BECConnector from bec_widgets.utils.bec_connector import BECConnector
from bec_widgets.widgets.dock.dock_area import BECDockArea
from bec_widgets.widgets.figure import BECFigure from bec_widgets.widgets.figure import BECFigure
from bec_widgets.widgets.plots import BECCurve, BECImageShow, BECWaveform from bec_widgets.widgets.plots import BECCurve, BECImageShow, BECWaveform
@@ -12,12 +14,18 @@ from bec_widgets.widgets.plots import BECCurve, BECImageShow, BECWaveform
class BECWidgetsCLIServer: class BECWidgetsCLIServer:
WIDGETS = [BECWaveform, BECFigure, BECCurve, BECImageShow] WIDGETS = [BECWaveform, BECFigure, BECCurve, BECImageShow]
def __init__(self, gui_id: str = None, dispatcher: BECDispatcher = None, client=None) -> None: def __init__(
self,
gui_id: str = None,
dispatcher: BECDispatcher = None,
client=None,
gui_class: BECFigure | BECDockArea = BECFigure,
) -> None:
self.dispatcher = BECDispatcher() if dispatcher is None else dispatcher self.dispatcher = BECDispatcher() if dispatcher is None else dispatcher
self.client = self.dispatcher.client if client is None else client self.client = self.dispatcher.client if client is None else client
self.client.start() self.client.start()
self.gui_id = gui_id self.gui_id = gui_id
self.fig = BECFigure(gui_id=self.gui_id) self.gui = gui_class(gui_id=self.gui_id)
self.dispatcher.connect_slot( self.dispatcher.connect_slot(
self.on_rpc_update, MessageEndpoints.gui_instructions(self.gui_id) self.on_rpc_update, MessageEndpoints.gui_instructions(self.gui_id)
@@ -53,14 +61,14 @@ class BECWidgetsCLIServer:
def get_object_from_config(self, config: dict): def get_object_from_config(self, config: dict):
gui_id = config.get("gui_id") gui_id = config.get("gui_id")
# check if the object is the figure # check if the object is the figure
if gui_id == self.fig.gui_id: if gui_id == self.gui.gui_id:
return self.fig return self.gui
# check if the object is a widget # check if the object is a widget
if gui_id in self.fig._widgets: if gui_id in self.gui.containers:
obj = self.fig._widgets[config["gui_id"]] obj = self.gui.containers[config["gui_id"]]
return obj return obj
if self.fig._widgets: if self.gui.containers:
for widget in self.fig._widgets.values(): for widget in self.gui.containers.values():
item = widget.find_widget_by_id(gui_id) item = widget.find_widget_by_id(gui_id)
if item: if item:
return item return item
@@ -123,13 +131,29 @@ if __name__ == "__main__": # pragma: no cover
parser = argparse.ArgumentParser(description="BEC Widgets CLI Server") parser = argparse.ArgumentParser(description="BEC Widgets CLI Server")
parser.add_argument("--id", type=str, help="The id of the server") parser.add_argument("--id", type=str, help="The id of the server")
parser.add_argument(
"--gui_class",
type=str,
help="Name of the gui class to be rendered. Possible values: \n- BECFigure\n- BECDockArea",
)
args = parser.parse_args() args = parser.parse_args()
server = BECWidgetsCLIServer(gui_id=args.id) if args.gui_class == "BECFigure":
# server = BECWidgetsCLIServer(gui_id="test") gui_class = BECFigure
elif args.gui_class == "BECDockArea":
gui_class = BECDockArea
else:
print(
"Please specify a valid gui_class to run. Use -h for help."
"\n Starting with default gui_class BECFigure."
)
gui_class = BECFigure
fig = server.fig # server = BECWidgetsCLIServer(gui_id=args.id, gui_class=gui_class)
server = BECWidgetsCLIServer(gui_id="test", gui_class=gui_class)
fig = server.gui
win.setCentralWidget(fig) win.setCentralWidget(fig)
win.show() win.show()
@@ -2,13 +2,16 @@ import os
import numpy as np import numpy as np
import pyqtgraph as pg import pyqtgraph as pg
from pyqtgraph.Qt import uic from PyQt6.QtCore import QSize
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import QMainWindow
from pyqtgraph.Qt import QtWidgets, uic
from qtconsole.inprocess import QtInProcessKernelManager from qtconsole.inprocess import QtInProcessKernelManager
from qtconsole.rich_jupyter_widget import RichJupyterWidget from qtconsole.rich_jupyter_widget import RichJupyterWidget
from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget
from bec_widgets.utils import BECDispatcher from bec_widgets.utils import BECDispatcher
from bec_widgets.widgets import BECFigure from bec_widgets.widgets import BECDockArea, BECFigure
class JupyterConsoleWidget(RichJupyterWidget): # pragma: no cover: class JupyterConsoleWidget(RichJupyterWidget): # pragma: no cover:
@@ -47,9 +50,14 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
self.console.kernel_manager.kernel.shell.push( self.console.kernel_manager.kernel.shell.push(
{ {
"fig": self.figure, "fig": self.figure,
"dock": self.dock,
"w1": self.w1, "w1": self.w1,
"w2": self.w2, "w2": self.w2,
"w3": self.w3, "w3": self.w3,
"d1": self.d1,
"d2": self.d2,
"d3": self.d3,
"label_2": self.label_2,
"bec": self.figure.client, "bec": self.figure.client,
"scans": self.figure.client.scans, "scans": self.figure.client.scans,
"dev": self.figure.client.device_manager.devices, "dev": self.figure.client.device_manager.devices,
@@ -62,9 +70,16 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
self.figure = BECFigure(parent=self, gui_id="remote") # Create a new BECDeviceMonitor self.figure = BECFigure(parent=self, gui_id="remote") # Create a new BECDeviceMonitor
self.glw_1_layout.addWidget(self.figure) # Add BECDeviceMonitor to the layout self.glw_1_layout.addWidget(self.figure) # Add BECDeviceMonitor to the layout
self.dock_layout = QVBoxLayout(self.dock_placeholder)
self.dock = BECDockArea(gui_id="remote")
self.dock_layout.addWidget(self.dock)
# add stuff to figure # add stuff to figure
self._init_figure() self._init_figure()
# init dock for testing
self._init_dock()
self.console_layout = QVBoxLayout(self.widget_console) self.console_layout = QVBoxLayout(self.widget_console)
self.console = JupyterConsoleWidget() self.console = JupyterConsoleWidget()
self.console_layout.addWidget(self.console) self.console_layout.addWidget(self.console)
@@ -86,6 +101,19 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
self.w1.add_curve_scan("samx", "samy", "bpm3a", pen_style="dash") self.w1.add_curve_scan("samx", "samy", "bpm3a", pen_style="dash")
self.c1 = self.w1.get_config() self.c1 = self.w1.get_config()
def _init_dock(self):
self.button_1 = QtWidgets.QPushButton("Button 1 ")
self.label_1 = QtWidgets.QLabel("some scan info label with useful information")
self.label_2 = QtWidgets.QLabel("label which is added separately")
self.d1 = self.dock.add_dock(widget=self.button_1, position="left")
self.d2 = self.dock.add_dock(widget=self.label_1, position="right")
self.d3 = self.dock.plot(x_name="samx", y_name="bpm4d")
self.d4 = self.dock.image(monitor="eiger")
self.d4.set_vrange(0, 100)
if __name__ == "__main__": # pragma: no cover if __name__ == "__main__": # pragma: no cover
import sys import sys
@@ -96,6 +124,10 @@ if __name__ == "__main__": # pragma: no cover
app = QApplication(sys.argv) app = QApplication(sys.argv)
app.setApplicationName("Jupyter Console") app.setApplicationName("Jupyter Console")
app.setApplicationDisplayName("Jupyter Console")
icon = QIcon()
icon.addFile("terminal_icon.png", size=QSize(48, 48))
app.setWindowIcon(icon)
win = JupyterConsoleWindow() win = JupyterConsoleWindow()
win.show() win.show()
@@ -13,13 +13,37 @@
<property name="windowTitle"> <property name="windowTitle">
<string>Plotting Console</string> <string>Plotting Console</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout_4">
<item> <item>
<widget class="QSplitter" name="splitter"> <widget class="QSplitter" name="splitter">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<widget class="QWidget" name="glw" native="true"/> <widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab_1">
<attribute name="title">
<string>BECDock</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="dock_placeholder" native="true"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>BECFigure</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QWidget" name="glw" native="true"/>
</item>
</layout>
</widget>
</widget>
<widget class="QWidget" name="widget_console" native="true"/> <widget class="QWidget" name="widget_console" native="true"/>
</widget> </widget>
</item> </item>
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

+50
View File
@@ -0,0 +1,50 @@
from typing import Literal, Optional
from pydantic import Field
from pyqtgraph.dockarea import Dock
from qtpy.QtWidgets import QWidget
from bec_widgets.utils import BECConnector, ConnectionConfig, WidgetContainerUtils
class DockConfig(ConnectionConfig):
widgets: dict[str, ConnectionConfig] = Field({}, description="The widgets in the dock.")
position: Literal["bottom", "top", "left", "right", "above", "below"] = Field(
"bottom", description="The position of the dock."
)
parent_dock_area: Optional[str] = Field(
None, description="The GUI ID of parent dock area of the dock."
)
class BECDock(BECConnector, Dock):
def __init__(
self,
parent: Optional[QWidget] = None,
parent_dock_area: Optional["BECDockArea"] = None,
config: Optional[
DockConfig
] = None, # TODO ATM connection config -> will be changed when I will know what I want to use there
name: Optional[str] = None,
client=None,
gui_id: Optional[str] = None,
**kwargs,
) -> None:
if config is None:
config = DockConfig(
widget_class=self.__class__.__name__, parent_dock_area=parent_dock_area.gui_id
)
else:
if isinstance(config, dict):
config = DockConfig(**config)
self.config = config
super().__init__(client=client, config=config, gui_id=gui_id)
Dock.__init__(self, name=name, **kwargs)
self.parent_dock_area = parent_dock_area
self.sigClosed.connect(self._remove_from_dock_area)
def _remove_from_dock_area(self):
"""Remove this dock from the DockArea it lives inside."""
self.parent_dock_area.docks.pop(self.name())
+107
View File
@@ -0,0 +1,107 @@
from collections import defaultdict
from typing import Literal, Optional
import pyqtgraph as pg
from pydantic import Field
from pyqtgraph.dockarea.DockArea import Dock, DockArea
from qtpy.QtWidgets import QWidget
from bec_widgets.utils import BECConnector, ConnectionConfig, WidgetContainerUtils
from bec_widgets.widgets import BECFigure, BECMotorMap, BECWaveform
from bec_widgets.widgets.plots import BECImageShow
from .dock import BECDock, DockConfig
class DockAreaConfig(ConnectionConfig):
docks: dict[str, DockConfig] = Field({}, description="The docks in the dock area.")
class BECDockArea(BECConnector, DockArea):
USER_ACCESS = ["figure", "plot", "image", "motor_map", "add_dock", "remove_dock_by_id", "clear"]
def __init__(
self,
parent: Optional[QWidget] = None,
config: Optional[DockAreaConfig] = None,
client=None,
gui_id: Optional[str] = None,
) -> None:
if config is None:
config = DockAreaConfig(widget_class=self.__class__.__name__)
else:
if isinstance(config, dict):
config = DockAreaConfig(**config)
self.config = config
super().__init__(client=client, config=config, gui_id=gui_id)
DockArea.__init__(self, parent=parent)
self._last_state = None # TODO not sure if this will ever work
def figure(self, name: str = None) -> BECFigure:
figure = BECFigure(gui_id="remote")
self.add_dock(name=name, widget=figure, prefix="figure")
return figure
def plot(
self,
x_name: str = None,
y_name: str = None,
name: str = None,
) -> BECWaveform:
figure = BECFigure(gui_id="remote")
self.add_dock(name=name, widget=figure, prefix="plot")
plot = figure.plot(x_name, y_name)
return plot
def image(self, monitor: str = "eiger", name: str = None) -> BECImageShow:
figure = BECFigure(gui_id="remote")
self.add_dock(name=name, widget=figure, prefix="image")
image = figure.image(monitor)
return image
def motor_map(self, x_name: str = None, y_name: str = None, name: str = None) -> BECMotorMap:
figure = BECFigure(gui_id="remote")
self.add_dock(name=name, widget=figure, prefix="motor_map")
motor_map = figure.motor_map(x_name, y_name)
return motor_map
def add_dock(
self,
name: str = None,
widget: QWidget = None,
position: Literal["bottom", "top", "left", "right", "above", "below"] = None,
relative_to: Optional[BECDock] = None, # TODO implement relative_to
prefix: str = "dock",
) -> BECDock:
if name is None:
name = WidgetContainerUtils.generate_unique_widget_id(
container=self.docks, prefix=prefix
)
if name in set(self.docks.keys()):
raise ValueError(f"Dock with name {name} already exists.")
if position is None:
position = "bottom"
dock = BECDock(name=name, parent_dock_area=self, closable=True)
dock.config.position = position
self.config.docks[name] = dock.config
self.addDock(dock, position)
if widget is not None:
dock.addWidget(widget)
return dock
def remove_dock_by_id(self, dock_id: str):
if dock_id in self.docks:
dock_to_remove = self.docks[dock_id]
dock_to_remove.close()
else:
raise ValueError(f"Dock with id {dock_id} does not exist.")
+12 -3
View File
@@ -20,8 +20,8 @@ from bec_widgets.widgets.plots import (
BECMotorMap, BECMotorMap,
BECPlotBase, BECPlotBase,
BECWaveform, BECWaveform,
SubplotConfig,
Waveform1DConfig, Waveform1DConfig,
WidgetConfig,
) )
from bec_widgets.widgets.plots.image import ImageConfig from bec_widgets.widgets.plots.image import ImageConfig
from bec_widgets.widgets.plots.motor_map import MotorMapConfig from bec_widgets.widgets.plots.motor_map import MotorMapConfig
@@ -33,7 +33,7 @@ class FigureConfig(ConnectionConfig):
theme: Literal["dark", "light"] = Field("dark", description="The theme of the figure widget.") theme: Literal["dark", "light"] = Field("dark", description="The theme of the figure widget.")
num_cols: int = Field(1, description="The number of columns in the figure widget.") num_cols: int = Field(1, description="The number of columns in the figure widget.")
num_rows: int = Field(1, description="The number of rows in the figure widget.") num_rows: int = Field(1, description="The number of rows in the figure widget.")
widgets: dict[str, WidgetConfig] = Field( widgets: dict[str, SubplotConfig] = Field(
{}, description="The list of widgets to be added to the figure widget." {}, description="The list of widgets to be added to the figure widget."
) )
@@ -43,7 +43,7 @@ class WidgetHandler:
def __init__(self): def __init__(self):
self.widget_factory = { self.widget_factory = {
"PlotBase": (BECPlotBase, WidgetConfig), "PlotBase": (BECPlotBase, SubplotConfig),
"Waveform1D": (BECWaveform, Waveform1DConfig), "Waveform1D": (BECWaveform, Waveform1DConfig),
"ImShow": (BECImageShow, ImageConfig), "ImShow": (BECImageShow, ImageConfig),
"MotorMap": (BECMotorMap, MotorMapConfig), "MotorMap": (BECMotorMap, MotorMapConfig),
@@ -110,6 +110,7 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
"change_layout", "change_layout",
"change_theme", "change_theme",
"clear_all", "clear_all",
"containers",
] ]
clean_signal = pyqtSignal() clean_signal = pyqtSignal()
@@ -160,6 +161,14 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
def widgets(self, value: dict): def widgets(self, value: dict):
self._widgets = value self._widgets = value
@property
def containers(self) -> dict:
return self._widgets
@containers.setter
def containers(self, value: dict):
self._widgets = value
def add_plot( def add_plot(
self, self,
x_name: str = None, x_name: str = None,
+1 -1
View File
@@ -1,4 +1,4 @@
from .image import BECImageItem, BECImageShow, ImageItemConfig from .image import BECImageItem, BECImageShow, ImageItemConfig
from .motor_map import BECMotorMap, MotorMapConfig from .motor_map import BECMotorMap, MotorMapConfig
from .plot_base import AxisConfig, BECPlotBase, WidgetConfig from .plot_base import AxisConfig, BECPlotBase, SubplotConfig
from .waveform import BECCurve, BECWaveform, Waveform1DConfig from .waveform import BECCurve, BECWaveform, Waveform1DConfig
+5 -7
View File
@@ -14,7 +14,7 @@ from qtpy.QtWidgets import QWidget
from bec_widgets.utils import BECConnector, ConnectionConfig, EntryValidator from bec_widgets.utils import BECConnector, ConnectionConfig, EntryValidator
from .plot_base import BECPlotBase, WidgetConfig from .plot_base import BECPlotBase, SubplotConfig
class ProcessingConfig(BaseModel): class ProcessingConfig(BaseModel):
@@ -50,7 +50,7 @@ class ImageItemConfig(ConnectionConfig):
) )
class ImageConfig(WidgetConfig): class ImageConfig(SubplotConfig):
images: dict[str, ImageItemConfig] = Field( images: dict[str, ImageItemConfig] = Field(
{}, {},
description="The configuration of the images. The key is the name of the image (source).", description="The configuration of the images. The key is the name of the image (source).",
@@ -358,7 +358,7 @@ class BECImageShow(BECPlotBase):
thread.start() thread.start()
def find_widget_by_id(self, item_id: str) -> BECImageItem: def find_widget_by_id(self, item_id: str) -> BECImageItem: # todo can be done in mixin
""" """
Find the widget by its gui_id. Find the widget by its gui_id.
Args: Args:
@@ -390,11 +390,11 @@ class BECImageShow(BECPlotBase):
if result is not None: if result is not None:
return result return result
def apply_config(self, config: dict | WidgetConfig): def apply_config(self, config: dict | SubplotConfig):
""" """
Apply the configuration to the 1D waveform widget. Apply the configuration to the 1D waveform widget.
Args: Args:
config(dict|WidgetConfig): Configuration settings. config(dict|SubplotConfig): Configuration settings.
replot_last_scan(bool, optional): If True, replot the last scan. Defaults to False. replot_last_scan(bool, optional): If True, replot the last scan. Defaults to False.
""" """
if isinstance(config, dict): if isinstance(config, dict):
@@ -719,10 +719,8 @@ class BECImageShow(BECPlotBase):
processing_config = image_to_update.config.processing processing_config = image_to_update.config.processing
self.processor.set_config(processing_config) self.processor.set_config(processing_config)
if self.use_threading: if self.use_threading:
print("using threaded version")
self._create_thread_worker(device, data) self._create_thread_worker(device, data)
else: else:
print("using NON-threaded version")
data = self.processor.process_image(data) data = self.processor.process_image(data)
self.update_image(device, data) self.update_image(device, data)
+2 -2
View File
@@ -13,11 +13,11 @@ from qtpy.QtCore import Slot as pyqtSlot
from qtpy.QtWidgets import QWidget from qtpy.QtWidgets import QWidget
from bec_widgets.utils import EntryValidator from bec_widgets.utils import EntryValidator
from bec_widgets.widgets.plots.plot_base import BECPlotBase, WidgetConfig from bec_widgets.widgets.plots.plot_base import BECPlotBase, SubplotConfig
from bec_widgets.widgets.plots.waveform import Signal, SignalData from bec_widgets.widgets.plots.waveform import Signal, SignalData
class MotorMapConfig(WidgetConfig): class MotorMapConfig(SubplotConfig):
signals: Optional[Signal] = Field(None, description="Signals of the motor map") signals: Optional[Signal] = Field(None, description="Signals of the motor map")
color_map: Optional[str] = Field( color_map: Optional[str] = Field(
"Greys", description="Color scheme of the motor position gradient." "Greys", description="Color scheme of the motor position gradient."
+3 -3
View File
@@ -22,7 +22,7 @@ class AxisConfig(BaseModel):
y_grid: bool = Field(False, description="Show grid on the y-axis.") y_grid: bool = Field(False, description="Show grid on the y-axis.")
class WidgetConfig(ConnectionConfig): class SubplotConfig(ConnectionConfig):
parent_id: Optional[str] = Field(None, description="The parent figure of the plot.") parent_id: Optional[str] = Field(None, description="The parent figure of the plot.")
# Coordinates in the figure # Coordinates in the figure
@@ -56,12 +56,12 @@ class BECPlotBase(BECConnector, pg.GraphicsLayout):
self, self,
parent: Optional[QWidget] = None, # TODO decide if needed for this class parent: Optional[QWidget] = None, # TODO decide if needed for this class
parent_figure=None, parent_figure=None,
config: Optional[WidgetConfig] = None, config: Optional[SubplotConfig] = None,
client=None, client=None,
gui_id: Optional[str] = None, gui_id: Optional[str] = None,
): ):
if config is None: if config is None:
config = WidgetConfig(widget_class=self.__class__.__name__) config = SubplotConfig(widget_class=self.__class__.__name__)
super().__init__(client=client, config=config, gui_id=gui_id) super().__init__(client=client, config=config, gui_id=gui_id)
pg.GraphicsLayout.__init__(self, parent) pg.GraphicsLayout.__init__(self, parent)
+4 -4
View File
@@ -15,7 +15,7 @@ from qtpy.QtCore import Slot as pyqtSlot
from qtpy.QtWidgets import QWidget from qtpy.QtWidgets import QWidget
from bec_widgets.utils import BECConnector, Colors, ConnectionConfig, EntryValidator from bec_widgets.utils import BECConnector, Colors, ConnectionConfig, EntryValidator
from bec_widgets.widgets.plots.plot_base import BECPlotBase, WidgetConfig from bec_widgets.widgets.plots.plot_base import BECPlotBase, SubplotConfig
class SignalData(BaseModel): class SignalData(BaseModel):
@@ -53,7 +53,7 @@ class CurveConfig(ConnectionConfig):
colormap: Optional[str] = Field("plasma", description="The colormap of the curves z gradient.") colormap: Optional[str] = Field("plasma", description="The colormap of the curves z gradient.")
class Waveform1DConfig(WidgetConfig): class Waveform1DConfig(SubplotConfig):
color_palette: Literal["plasma", "viridis", "inferno", "magma"] = Field( color_palette: Literal["plasma", "viridis", "inferno", "magma"] = Field(
"plasma", description="The color palette of the figure widget." "plasma", description="The color palette of the figure widget."
) # TODO can be extended to all colormaps from current pyqtgraph session ) # TODO can be extended to all colormaps from current pyqtgraph session
@@ -299,11 +299,11 @@ class BECWaveform(BECPlotBase):
if curve.gui_id == item_id: if curve.gui_id == item_id:
return curve return curve
def apply_config(self, config: dict | WidgetConfig, replot_last_scan: bool = False): def apply_config(self, config: dict | SubplotConfig, replot_last_scan: bool = False):
""" """
Apply the configuration to the 1D waveform widget. Apply the configuration to the 1D waveform widget.
Args: Args:
config(dict|WidgetConfig): Configuration settings. config(dict|SubplotConfig): Configuration settings.
replot_last_scan(bool, optional): If True, replot the last scan. Defaults to False. replot_last_scan(bool, optional): If True, replot the last scan. Defaults to False.
""" """
if isinstance(config, dict): if isinstance(config, dict):
+5 -5
View File
@@ -11,8 +11,8 @@ from bec_widgets.utils import BECDispatcher
def rpc_server(qtbot, bec_client_lib, threads_check): def rpc_server(qtbot, bec_client_lib, threads_check):
dispatcher = BECDispatcher(client=bec_client_lib) # Has to init singleton with fixture client dispatcher = BECDispatcher(client=bec_client_lib) # Has to init singleton with fixture client
server = BECWidgetsCLIServer(gui_id="id_test") server = BECWidgetsCLIServer(gui_id="id_test")
qtbot.addWidget(server.fig) qtbot.addWidget(server.gui)
qtbot.waitExposed(server.fig) qtbot.waitExposed(server.gui)
qtbot.wait(1000) # 1s long to wait until gui is ready qtbot.wait(1000) # 1s long to wait until gui is ready
yield server yield server
dispatcher.disconnect_all() dispatcher.disconnect_all()
@@ -23,7 +23,7 @@ def rpc_server(qtbot, bec_client_lib, threads_check):
def test_rpc_waveform1d_custom_curve(rpc_server, qtbot): def test_rpc_waveform1d_custom_curve(rpc_server, qtbot):
fig = BECFigure(rpc_server.gui_id) fig = BECFigure(rpc_server.gui_id)
fig_server = rpc_server.fig fig_server = rpc_server.gui
ax = fig.add_plot() ax = fig.add_plot()
curve = ax.add_curve_custom([1, 2, 3], [1, 2, 3]) curve = ax.add_curve_custom([1, 2, 3], [1, 2, 3])
@@ -37,7 +37,7 @@ def test_rpc_waveform1d_custom_curve(rpc_server, qtbot):
def test_rpc_plotting_shortcuts_init_configs(rpc_server, qtbot): def test_rpc_plotting_shortcuts_init_configs(rpc_server, qtbot):
fig = BECFigure(rpc_server.gui_id) fig = BECFigure(rpc_server.gui_id)
fig_server = rpc_server.fig fig_server = rpc_server.gui
plt = fig.plot("samx", "bpm4i") plt = fig.plot("samx", "bpm4i")
im = fig.image("eiger") im = fig.image("eiger")
@@ -151,7 +151,7 @@ def test_rpc_image(rpc_server, qtbot):
def test_rpc_motor_map(rpc_server, qtbot): def test_rpc_motor_map(rpc_server, qtbot):
fig = BECFigure(rpc_server.gui_id) fig = BECFigure(rpc_server.gui_id)
fig_server = rpc_server.fig fig_server = rpc_server.gui
motor_map = fig.motor_map("samx", "samy") motor_map = fig.motor_map("samx", "samy")