mirror of
https://github.com/bec-project/bec_widgets.git
synced 2026-03-06 17:02:50 +01:00
718 lines
24 KiB
Python
718 lines
24 KiB
Python
from __future__ import annotations
|
|
|
|
import sys
|
|
from typing import Literal
|
|
|
|
import numpy as np
|
|
import pyqtgraph as pg
|
|
from bec_lib.logger import bec_logger
|
|
from qtpy.QtCore import Property, Signal, Slot
|
|
from qtpy.QtWidgets import QVBoxLayout, QWidget
|
|
|
|
from bec_widgets.qt_utils.error_popups import SafeSlot, WarningPopupUtility
|
|
from bec_widgets.qt_utils.settings_dialog import SettingsDialog
|
|
from bec_widgets.qt_utils.toolbar import MaterialIconAction, ModularToolBar, SeparatorAction
|
|
from bec_widgets.utils.bec_widget import BECWidget
|
|
from bec_widgets.widgets.figure import BECFigure
|
|
from bec_widgets.widgets.figure.plots.axis_settings import AxisSettings
|
|
from bec_widgets.widgets.figure.plots.waveform.waveform import Waveform1DConfig
|
|
from bec_widgets.widgets.figure.plots.waveform.waveform_curve import BECCurve
|
|
from bec_widgets.widgets.waveform.waveform_popups.curve_dialog.curve_dialog import CurveSettings
|
|
from bec_widgets.widgets.waveform.waveform_popups.dap_summary_dialog.dap_summary_dialog import (
|
|
FitSummaryWidget,
|
|
)
|
|
|
|
try:
|
|
import pandas as pd
|
|
except ImportError:
|
|
pd = None
|
|
|
|
logger = bec_logger.logger
|
|
|
|
|
|
class BECWaveformWidget(BECWidget, QWidget):
|
|
ICON_NAME = "show_chart"
|
|
USER_ACCESS = [
|
|
"curves",
|
|
"plot",
|
|
"add_dap",
|
|
"get_dap_params",
|
|
"remove_curve",
|
|
"scan_history",
|
|
"get_all_data",
|
|
"set",
|
|
"set_x",
|
|
"set_title",
|
|
"set_x_label",
|
|
"set_y_label",
|
|
"set_x_scale",
|
|
"set_y_scale",
|
|
"set_x_lim",
|
|
"set_y_lim",
|
|
"set_legend_label_size",
|
|
"set_auto_range",
|
|
"set_grid",
|
|
"lock_aspect_ratio",
|
|
"export",
|
|
"export_to_matplotlib",
|
|
"toggle_roi",
|
|
"select_roi",
|
|
]
|
|
scan_signal_update = Signal()
|
|
async_signal_update = Signal()
|
|
dap_summary_update = Signal(dict, dict)
|
|
dap_params_update = Signal(dict, dict)
|
|
autorange_signal = Signal()
|
|
new_scan = Signal()
|
|
crosshair_position_changed = Signal(tuple)
|
|
crosshair_position_changed_string = Signal(str)
|
|
crosshair_position_clicked = Signal(tuple)
|
|
crosshair_position_clicked_string = Signal(str)
|
|
crosshair_coordinates_changed = Signal(tuple)
|
|
crosshair_coordinates_changed_string = Signal(str)
|
|
crosshair_coordinates_clicked = Signal(tuple)
|
|
crosshair_coordinates_clicked_string = Signal(str)
|
|
roi_changed = Signal(tuple)
|
|
roi_active = Signal(bool)
|
|
|
|
def __init__(
|
|
self,
|
|
parent: QWidget | None = None,
|
|
config: Waveform1DConfig | dict = None,
|
|
client=None,
|
|
gui_id: str | None = None,
|
|
) -> None:
|
|
if config is None:
|
|
config = Waveform1DConfig(widget_class=self.__class__.__name__)
|
|
else:
|
|
if isinstance(config, dict):
|
|
config = Waveform1DConfig(**config)
|
|
super().__init__(client=client, gui_id=gui_id)
|
|
QWidget.__init__(self, parent)
|
|
|
|
self.layout = QVBoxLayout(self)
|
|
self.layout.setSpacing(0)
|
|
self.layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
self.fig = BECFigure()
|
|
self.toolbar = ModularToolBar(
|
|
actions={
|
|
"save": MaterialIconAction(icon_name="save", tooltip="Open Export Dialog"),
|
|
"matplotlib": MaterialIconAction(
|
|
icon_name="photo_library", tooltip="Open Matplotlib Plot"
|
|
),
|
|
"separator_1": SeparatorAction(),
|
|
"drag_mode": MaterialIconAction(
|
|
icon_name="drag_pan", tooltip="Drag Mouse Mode", checkable=True
|
|
),
|
|
"rectangle_mode": MaterialIconAction(
|
|
icon_name="frame_inspect", tooltip="Rectangle Zoom Mode", checkable=True
|
|
),
|
|
"auto_range": MaterialIconAction(
|
|
icon_name="open_in_full", tooltip="Autorange Plot"
|
|
),
|
|
"separator_2": SeparatorAction(),
|
|
"curves": MaterialIconAction(
|
|
icon_name="timeline", tooltip="Open Curves Configuration"
|
|
),
|
|
"fit_params": MaterialIconAction(
|
|
icon_name="monitoring", tooltip="Open Fitting Parameters"
|
|
),
|
|
"axis_settings": MaterialIconAction(
|
|
icon_name="settings", tooltip="Open Configuration Dialog"
|
|
),
|
|
"crosshair": MaterialIconAction(
|
|
icon_name="point_scan", tooltip="Show Crosshair", checkable=True
|
|
),
|
|
"roi_select": MaterialIconAction(
|
|
icon_name="align_justify_space_between",
|
|
tooltip="Add ROI region for DAP",
|
|
checkable=True,
|
|
),
|
|
},
|
|
target_widget=self,
|
|
)
|
|
|
|
self.layout.addWidget(self.toolbar)
|
|
self.layout.addWidget(self.fig)
|
|
|
|
self.warning_util = WarningPopupUtility(self)
|
|
|
|
self.waveform = self.fig.plot()
|
|
self.waveform.apply_config(config)
|
|
|
|
self.config = config
|
|
self._clear_curves_on_plot_update = False
|
|
|
|
self.hook_waveform_signals()
|
|
self._hook_actions()
|
|
|
|
def hook_waveform_signals(self):
|
|
self.waveform.scan_signal_update.connect(self.scan_signal_update)
|
|
self.waveform.async_signal_update.connect(self.async_signal_update)
|
|
self.waveform.dap_params_update.connect(self.dap_params_update)
|
|
self.waveform.dap_summary_update.connect(self.dap_summary_update)
|
|
self.waveform.autorange_signal.connect(self.autorange_signal)
|
|
self.waveform.new_scan.connect(self.new_scan)
|
|
self.waveform.crosshair_coordinates_changed.connect(self.crosshair_coordinates_changed)
|
|
self.waveform.crosshair_coordinates_clicked.connect(self.crosshair_coordinates_clicked)
|
|
self.waveform.crosshair_coordinates_changed.connect(
|
|
self._emit_crosshair_coordinates_changed_string
|
|
)
|
|
self.waveform.crosshair_coordinates_clicked.connect(
|
|
self._emit_crosshair_coordinates_clicked_string
|
|
)
|
|
self.waveform.crosshair_position_changed.connect(self.crosshair_position_changed)
|
|
self.waveform.crosshair_position_clicked.connect(self.crosshair_position_clicked)
|
|
self.waveform.crosshair_position_changed.connect(
|
|
self._emit_crosshair_position_changed_string
|
|
)
|
|
self.waveform.crosshair_position_clicked.connect(
|
|
self._emit_crosshair_position_clicked_string
|
|
)
|
|
self.waveform.roi_changed.connect(self.roi_changed)
|
|
self.waveform.roi_active.connect(self.roi_active)
|
|
|
|
def _hook_actions(self):
|
|
self.toolbar.widgets["save"].action.triggered.connect(self.export)
|
|
self.toolbar.widgets["matplotlib"].action.triggered.connect(self.export_to_matplotlib)
|
|
self.toolbar.widgets["drag_mode"].action.triggered.connect(self.enable_mouse_pan_mode)
|
|
self.toolbar.widgets["rectangle_mode"].action.triggered.connect(
|
|
self.enable_mouse_rectangle_mode
|
|
)
|
|
self.toolbar.widgets["auto_range"].action.triggered.connect(self._auto_range_from_toolbar)
|
|
self.toolbar.widgets["curves"].action.triggered.connect(self.show_curve_settings)
|
|
self.toolbar.widgets["fit_params"].action.triggered.connect(self.show_fit_summary_dialog)
|
|
self.toolbar.widgets["axis_settings"].action.triggered.connect(self.show_axis_settings)
|
|
self.toolbar.widgets["crosshair"].action.triggered.connect(self.waveform.toggle_crosshair)
|
|
self.toolbar.widgets["roi_select"].action.toggled.connect(self.waveform.toggle_roi)
|
|
# self.toolbar.widgets["import"].action.triggered.connect(
|
|
# lambda: self.load_config(path=None, gui=True)
|
|
# )
|
|
# self.toolbar.widgets["export"].action.triggered.connect(
|
|
# lambda: self.save_config(path=None, gui=True)
|
|
# )
|
|
|
|
@Slot(bool)
|
|
def toogle_roi_select(self, checked: bool):
|
|
"""Toggle the linear region selector.
|
|
|
|
Args:
|
|
checked(bool): If True, enable the linear region selector.
|
|
"""
|
|
self.toolbar.widgets["roi_select"].action.setChecked(checked)
|
|
|
|
@Property(bool)
|
|
def clear_curves_on_plot_update(self) -> bool:
|
|
"""If True, clear curves on plot update."""
|
|
return self._clear_curves_on_plot_update
|
|
|
|
@clear_curves_on_plot_update.setter
|
|
def clear_curves_on_plot_update(self, value: bool):
|
|
"""Set the clear curves on plot update property.
|
|
|
|
Args:
|
|
value(bool): If True, clear curves on plot update.
|
|
"""
|
|
self._clear_curves_on_plot_update = value
|
|
|
|
@SafeSlot(tuple)
|
|
def _emit_crosshair_coordinates_changed_string(self, coordinates):
|
|
self.crosshair_coordinates_changed_string.emit(str(coordinates))
|
|
|
|
@SafeSlot(tuple)
|
|
def _emit_crosshair_coordinates_clicked_string(self, coordinates):
|
|
self.crosshair_coordinates_clicked_string.emit(str(coordinates))
|
|
|
|
@SafeSlot(tuple)
|
|
def _emit_crosshair_position_changed_string(self, position):
|
|
self.crosshair_position_changed_string.emit(str(position))
|
|
|
|
@SafeSlot(tuple)
|
|
def _emit_crosshair_position_clicked_string(self, position):
|
|
self.crosshair_position_clicked_string.emit(str(position))
|
|
|
|
###################################
|
|
# Dialog Windows
|
|
###################################
|
|
def show_axis_settings(self):
|
|
dialog = SettingsDialog(
|
|
self,
|
|
settings_widget=AxisSettings(),
|
|
window_title="Axis Settings",
|
|
config=self._config_dict["axis"],
|
|
)
|
|
dialog.exec()
|
|
|
|
def show_curve_settings(self):
|
|
dialog = SettingsDialog(
|
|
self,
|
|
settings_widget=CurveSettings(),
|
|
window_title="Curve Settings",
|
|
config=self.waveform._curves_data,
|
|
)
|
|
dialog.resize(800, 600)
|
|
dialog.exec()
|
|
|
|
def show_fit_summary_dialog(self):
|
|
dialog = FitSummaryWidget(target_widget=self)
|
|
dialog.resize(800, 600)
|
|
dialog.exec()
|
|
|
|
###################################
|
|
# User Access Methods from Waveform
|
|
###################################
|
|
@property
|
|
def curves(self) -> list[BECCurve]:
|
|
"""
|
|
Get the curves of the plot widget as a list
|
|
Returns:
|
|
list: List of curves.
|
|
"""
|
|
return self.waveform._curves
|
|
|
|
@curves.setter
|
|
def curves(self, value: list[BECCurve]):
|
|
self.waveform._curves = value
|
|
|
|
def get_curve(self, identifier) -> BECCurve:
|
|
"""
|
|
Get the curve by its index or ID.
|
|
|
|
Args:
|
|
identifier(int|str): Identifier of the curve. Can be either an integer (index) or a string (curve_id).
|
|
|
|
Returns:
|
|
BECCurve: The curve object.
|
|
"""
|
|
return self.waveform.get_curve(identifier)
|
|
|
|
def set_colormap(self, colormap: str):
|
|
"""
|
|
Set the colormap of the plot widget.
|
|
|
|
Args:
|
|
colormap(str, optional): Scale the colors of curves to colormap. If None, use the default color palette.
|
|
"""
|
|
self.waveform.set_colormap(colormap)
|
|
|
|
@Slot(str, str) # Slot for x_name, x_entry
|
|
@SafeSlot(str, popup_error=True) # Slot for x_name and
|
|
def set_x(self, x_name: str, x_entry: str | None = None):
|
|
"""
|
|
Change the x axis of the plot widget.
|
|
|
|
Args:
|
|
x_name(str): Name of the x signal.
|
|
- "best_effort": Use the best effort signal.
|
|
- "timestamp": Use the timestamp signal.
|
|
- "index": Use the index signal.
|
|
- Custom signal name of device from BEC.
|
|
x_entry(str): Entry of the x signal.
|
|
"""
|
|
self.waveform.set_x(x_name, x_entry)
|
|
|
|
@Slot(str) # Slot for y_name
|
|
@SafeSlot(popup_error=True)
|
|
def plot(
|
|
self,
|
|
arg1: list | np.ndarray | str | None = None,
|
|
x: list | np.ndarray | None = None,
|
|
y: list | np.ndarray | None = None,
|
|
x_name: str | None = None,
|
|
y_name: str | None = None,
|
|
z_name: str | None = None,
|
|
x_entry: str | None = None,
|
|
y_entry: str | None = None,
|
|
z_entry: str | None = None,
|
|
color: str | None = None,
|
|
color_map_z: str | None = "magma",
|
|
label: str | None = None,
|
|
validate: bool = True,
|
|
dap: str | None = None, # TODO add dap custom curve wrapper
|
|
**kwargs,
|
|
) -> BECCurve:
|
|
"""
|
|
Plot a curve to the plot widget.
|
|
Args:
|
|
arg1(list | np.ndarray | str | None): First argument which can be x data(list | np.ndarray), y data(list | np.ndarray), or y_name(str).
|
|
x(list | np.ndarray): Custom x data to plot.
|
|
y(list | np.ndarray): Custom y data to plot.
|
|
x_name(str): The name of the device for the x-axis.
|
|
y_name(str): The name of the device for the y-axis.
|
|
z_name(str): The name of the device for the z-axis.
|
|
x_entry(str): The name of the entry for the x-axis.
|
|
y_entry(str): The name of the entry for the y-axis.
|
|
z_entry(str): The name of the entry for the z-axis.
|
|
color(str): The color of the curve.
|
|
color_map_z(str): The color map to use for the z-axis.
|
|
label(str): The label of the curve.
|
|
validate(bool): If True, validate the device names and entries.
|
|
dap(str): The dap model to use for the curve. If not specified, none will be added.
|
|
|
|
Returns:
|
|
BECCurve: The curve object.
|
|
"""
|
|
if self.clear_curves_on_plot_update is True:
|
|
self.waveform.clear_source(source="scan_segment")
|
|
return self.waveform.plot(
|
|
arg1=arg1,
|
|
x=x,
|
|
y=y,
|
|
x_name=x_name,
|
|
y_name=y_name,
|
|
z_name=z_name,
|
|
x_entry=x_entry,
|
|
y_entry=y_entry,
|
|
z_entry=z_entry,
|
|
color=color,
|
|
color_map_z=color_map_z,
|
|
label=label,
|
|
validate=validate,
|
|
dap=dap,
|
|
**kwargs,
|
|
)
|
|
|
|
@Slot(
|
|
str, str, str, str, str, str, bool
|
|
) # Slot for x_name, y_name, x_entry, y_entry, color, validate_bec
|
|
@SafeSlot(str, str, str, popup_error=True)
|
|
def add_dap(
|
|
self,
|
|
x_name: str,
|
|
y_name: str,
|
|
dap: str,
|
|
x_entry: str | None = None,
|
|
y_entry: str | None = None,
|
|
color: str | None = None,
|
|
validate_bec: bool = True,
|
|
**kwargs,
|
|
) -> BECCurve:
|
|
"""
|
|
Add LMFIT dap model curve to the plot widget.
|
|
|
|
Args:
|
|
x_name(str): Name of the x signal.
|
|
x_entry(str): Entry of the x signal.
|
|
y_name(str): Name of the y signal.
|
|
y_entry(str): Entry of the y signal.
|
|
color(str, optional): Color of the curve. Defaults to None.
|
|
dap(str): The dap model to use for the curve.
|
|
validate_bec(bool, optional): If True, validate the signal with BEC. Defaults to True.
|
|
**kwargs: Additional keyword arguments for the curve configuration.
|
|
|
|
Returns:
|
|
BECCurve: The curve object.
|
|
"""
|
|
if self.clear_curves_on_plot_update is True:
|
|
self.waveform.clear_source(source="DAP")
|
|
return self.waveform.add_dap(
|
|
x_name=x_name,
|
|
y_name=y_name,
|
|
x_entry=x_entry,
|
|
y_entry=y_entry,
|
|
color=color,
|
|
dap=dap,
|
|
validate_bec=validate_bec,
|
|
**kwargs,
|
|
)
|
|
|
|
def get_dap_params(self) -> dict:
|
|
"""
|
|
Get the DAP parameters of all DAP curves.
|
|
|
|
Returns:
|
|
dict: DAP parameters of all DAP curves.
|
|
"""
|
|
|
|
return self.waveform.get_dap_params()
|
|
|
|
def get_dap_summary(self) -> dict:
|
|
"""
|
|
Get the DAP summary of all DAP curves.
|
|
|
|
Returns:
|
|
dict: DAP summary of all DAP curves.
|
|
"""
|
|
return self.waveform.get_dap_summary()
|
|
|
|
def remove_curve(self, *identifiers):
|
|
"""
|
|
Remove a curve from the plot widget.
|
|
|
|
Args:
|
|
*identifiers: Identifier of the curve to be removed. Can be either an integer (index) or a string (curve_id).
|
|
"""
|
|
self.waveform.remove_curve(*identifiers)
|
|
|
|
def scan_history(self, scan_index: int = None, scan_id: str = None):
|
|
"""
|
|
Update the scan curves with the data from the scan storage.
|
|
Provide only one of scan_id or scan_index.
|
|
|
|
Args:
|
|
scan_id(str, optional): ScanID of the scan to be updated. Defaults to None.
|
|
scan_index(int, optional): Index of the scan to be updated. Defaults to None.
|
|
"""
|
|
self.waveform.scan_history(scan_index, scan_id)
|
|
|
|
def get_all_data(self, output: Literal["dict", "pandas"] = "dict") -> dict | pd.DataFrame:
|
|
"""
|
|
Extract all curve data into a dictionary or a pandas DataFrame.
|
|
|
|
Args:
|
|
output (Literal["dict", "pandas"]): Format of the output data.
|
|
|
|
Returns:
|
|
dict | pd.DataFrame: Data of all curves in the specified format.
|
|
"""
|
|
try:
|
|
import pandas as pd
|
|
except ImportError:
|
|
pd = None
|
|
if output == "pandas":
|
|
logger.warning(
|
|
"Pandas is not installed. "
|
|
"Please install pandas using 'pip install pandas'."
|
|
"Output will be dictionary instead."
|
|
)
|
|
output = "dict"
|
|
return self.waveform.get_all_data(output)
|
|
|
|
###################################
|
|
# User Access Methods from Plotbase
|
|
###################################
|
|
|
|
def set(self, **kwargs):
|
|
"""
|
|
Set the properties of the plot widget.
|
|
|
|
Args:
|
|
**kwargs: Keyword arguments for the properties to be set.
|
|
|
|
Possible properties:
|
|
- title: str
|
|
- x_label: str
|
|
- y_label: str
|
|
- x_scale: Literal["linear", "log"]
|
|
- y_scale: Literal["linear", "log"]
|
|
- x_lim: tuple
|
|
- y_lim: tuple
|
|
- legend_label_size: int
|
|
"""
|
|
self.waveform.set(**kwargs)
|
|
|
|
def set_title(self, title: str):
|
|
"""
|
|
Set the title of the plot widget.
|
|
|
|
Args:
|
|
title(str): Title of the plot.
|
|
"""
|
|
self.waveform.set_title(title)
|
|
|
|
def set_x_label(self, x_label: str):
|
|
"""
|
|
Set the x-axis label of the plot widget.
|
|
|
|
Args:
|
|
x_label(str): Label of the x-axis.
|
|
"""
|
|
self.waveform.set_x_label(x_label)
|
|
|
|
def set_y_label(self, y_label: str):
|
|
"""
|
|
Set the y-axis label of the plot widget.
|
|
|
|
Args:
|
|
y_label(str): Label of the y-axis.
|
|
"""
|
|
self.waveform.set_y_label(y_label)
|
|
|
|
def set_x_scale(self, x_scale: Literal["linear", "log"]):
|
|
"""
|
|
Set the scale of the x-axis of the plot widget.
|
|
|
|
Args:
|
|
x_scale(Literal["linear", "log"]): Scale of the x-axis.
|
|
"""
|
|
self.waveform.set_x_scale(x_scale)
|
|
|
|
def set_y_scale(self, y_scale: Literal["linear", "log"]):
|
|
"""
|
|
Set the scale of the y-axis of the plot widget.
|
|
|
|
Args:
|
|
y_scale(Literal["linear", "log"]): Scale of the y-axis.
|
|
"""
|
|
self.waveform.set_y_scale(y_scale)
|
|
|
|
def set_x_lim(self, x_lim: tuple):
|
|
"""
|
|
Set the limits of the x-axis of the plot widget.
|
|
|
|
Args:
|
|
x_lim(tuple): Limits of the x-axis.
|
|
"""
|
|
self.waveform.set_x_lim(x_lim)
|
|
|
|
def set_y_lim(self, y_lim: tuple):
|
|
"""
|
|
Set the limits of the y-axis of the plot widget.
|
|
|
|
Args:
|
|
y_lim(tuple): Limits of the y-axis.
|
|
"""
|
|
self.waveform.set_y_lim(y_lim)
|
|
|
|
def set_legend_label_size(self, legend_label_size: int):
|
|
"""
|
|
Set the size of the legend labels of the plot widget.
|
|
|
|
Args:
|
|
legend_label_size(int): Size of the legend labels.
|
|
"""
|
|
self.waveform.set_legend_label_size(legend_label_size)
|
|
|
|
def set_auto_range(self, enabled: bool, axis: str = "xy"):
|
|
"""
|
|
Set the auto range of the plot widget.
|
|
|
|
Args:
|
|
enabled(bool): If True, enable the auto range.
|
|
axis(str, optional): The axis to enable the auto range.
|
|
- "xy": Enable auto range for both x and y axis.
|
|
- "x": Enable auto range for x axis.
|
|
- "y": Enable auto range for y axis.
|
|
"""
|
|
self.waveform.set_auto_range(enabled, axis)
|
|
|
|
def toggle_roi(self, checked: bool):
|
|
"""Toggle the linear region selector.
|
|
|
|
Args:
|
|
checked(bool): If True, enable the linear region selector.
|
|
"""
|
|
self.waveform.toggle_roi(checked)
|
|
|
|
def select_roi(self, region: tuple):
|
|
"""
|
|
Set the region of interest of the plot widget.
|
|
|
|
Args:
|
|
region(tuple): Region of interest.
|
|
"""
|
|
self.waveform.select_roi(region)
|
|
|
|
@SafeSlot()
|
|
def _auto_range_from_toolbar(self):
|
|
"""
|
|
Set the auto range of the plot widget from the toolbar.
|
|
"""
|
|
self.waveform.set_auto_range(True, "xy")
|
|
|
|
def set_grid(self, x_grid: bool, y_grid: bool):
|
|
"""
|
|
Set the grid visibility of the plot widget.
|
|
|
|
Args:
|
|
x_grid(bool): Visibility of the x-axis grid.
|
|
y_grid(bool): Visibility of the y-axis grid.
|
|
"""
|
|
self.waveform.set_grid(x_grid, y_grid)
|
|
|
|
def set_outer_axes(self, show: bool):
|
|
"""
|
|
Set the outer axes visibility of the plot widget.
|
|
|
|
Args:
|
|
show(bool): Visibility of the outer axes.
|
|
"""
|
|
self.waveform.set_outer_axes(show)
|
|
|
|
def lock_aspect_ratio(self, lock: bool):
|
|
"""
|
|
Lock the aspect ratio of the plot widget.
|
|
|
|
Args:
|
|
lock(bool): Lock the aspect ratio.
|
|
"""
|
|
self.waveform.lock_aspect_ratio(lock)
|
|
|
|
@SafeSlot()
|
|
def enable_mouse_rectangle_mode(self):
|
|
self.toolbar.widgets["rectangle_mode"].action.setChecked(True)
|
|
self.toolbar.widgets["drag_mode"].action.setChecked(False)
|
|
self.waveform.plot_item.getViewBox().setMouseMode(pg.ViewBox.RectMode)
|
|
|
|
@SafeSlot()
|
|
def enable_mouse_pan_mode(self):
|
|
self.toolbar.widgets["drag_mode"].action.setChecked(True)
|
|
self.toolbar.widgets["rectangle_mode"].action.setChecked(False)
|
|
self.waveform.plot_item.getViewBox().setMouseMode(pg.ViewBox.PanMode)
|
|
|
|
def export(self):
|
|
"""
|
|
Show the export dialog for the plot widget.
|
|
"""
|
|
self.waveform.export()
|
|
|
|
def export_to_matplotlib(self):
|
|
"""
|
|
Export the plot widget to Matplotlib.
|
|
"""
|
|
try:
|
|
import matplotlib as mpl
|
|
except ImportError:
|
|
self.warning_util.show_warning(
|
|
title="Matplotlib not installed",
|
|
message="Matplotlib is required for this feature.",
|
|
detailed_text="Please install matplotlib in your Python environment by using 'pip install matplotlib'.",
|
|
)
|
|
return
|
|
self.waveform.export_to_matplotlib()
|
|
|
|
#######################################
|
|
# User Access Methods from BECConnector
|
|
######################################
|
|
def load_config(self, path: str | None = None, gui: bool = False):
|
|
"""
|
|
Load the configuration of the widget from YAML.
|
|
|
|
Args:
|
|
path(str): Path to the configuration file for non-GUI dialog mode.
|
|
gui(bool): If True, use the GUI dialog to load the configuration file.
|
|
"""
|
|
self.fig.load_config(path=path, gui=gui)
|
|
|
|
def save_config(self, path: str | None = None, gui: bool = False):
|
|
"""
|
|
Save the configuration of the widget to YAML.
|
|
|
|
Args:
|
|
path(str): Path to save the configuration file for non-GUI dialog mode.
|
|
gui(bool): If True, use the GUI dialog to save the configuration file.
|
|
"""
|
|
self.fig.save_config(path=path, gui=gui)
|
|
|
|
def cleanup(self):
|
|
self.fig.cleanup()
|
|
return super().cleanup()
|
|
|
|
|
|
def main(): # pragma: no cover
|
|
from qtpy.QtWidgets import QApplication
|
|
|
|
app = QApplication(sys.argv)
|
|
widget = BECWaveformWidget()
|
|
widget.plot(x_name="samx", y_name="bpm4i")
|
|
widget.plot(y_name="bpm3i")
|
|
widget.plot(y_name="bpm4a")
|
|
widget.plot(y_name="bpm5i")
|
|
widget.show()
|
|
sys.exit(app.exec_())
|
|
|
|
|
|
if __name__ == "__main__": # pragma: no cover
|
|
main()
|