diff --git a/bec_widgets/cli/client.py b/bec_widgets/cli/client.py
index b052e742..773d5b44 100644
--- a/bec_widgets/cli/client.py
+++ b/bec_widgets/cli/client.py
@@ -19,6 +19,7 @@ class Widgets(str, enum.Enum):
BECMotorMapWidget = "BECMotorMapWidget"
BECQueue = "BECQueue"
BECStatusBox = "BECStatusBox"
+ BECWaveformWidget = "BECWaveformWidget"
DeviceBox = "DeviceBox"
DeviceComboBox = "DeviceComboBox"
DeviceLineEdit = "DeviceLineEdit"
@@ -27,7 +28,6 @@ class Widgets(str, enum.Enum):
StopButton = "StopButton"
TextBox = "TextBox"
VSCodeEditor = "VSCodeEditor"
- BECWaveformWidget = "BECWaveformWidget"
WebsiteWidget = "WebsiteWidget"
@@ -469,8 +469,9 @@ class BECFigure(RPCBase):
@rpc_call
def plot(
self,
- x: "list | np.ndarray | None" = None,
+ arg1: "list | np.ndarray | str | None" = None,
y: "list | np.ndarray | None" = None,
+ x: "list | np.ndarray | None" = None,
x_name: "str | None" = None,
y_name: "str | None" = None,
z_name: "str | None" = None,
@@ -492,8 +493,9 @@ class BECFigure(RPCBase):
Add a 1D waveform plot to the figure. Always access the first waveform widget in the figure.
Args:
- x(list | np.ndarray): Custom x data to plot.
+ arg1(list | np.ndarray | str | None): First argument which can be x data, y data, or y_name.
y(list | np.ndarray): Custom y data to plot.
+ x(list | np.ndarray): Custom x 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.
@@ -1498,8 +1500,9 @@ class BECWaveform(RPCBase):
@rpc_call
def plot(
self,
- x: "list | np.ndarray | None" = None,
+ arg1: "list | np.ndarray | str | None" = None,
y: "list | np.ndarray | None" = None,
+ x: "list | np.ndarray | None" = None,
x_name: "str | None" = None,
y_name: "str | None" = None,
z_name: "str | None" = None,
@@ -1511,13 +1514,20 @@ class BECWaveform(RPCBase):
label: "str | None" = None,
validate: "bool" = True,
dap: "str | None" = None,
+ **kwargs,
) -> "BECCurve":
"""
Plot a curve to the plot widget.
+
Args:
- x(list | np.ndarray): Custom x data to plot.
+ arg1(list | np.ndarray | str | None): First argument which can be x data, y data, or y_name.
y(list | np.ndarray): Custom y data to plot.
- x_name(str): The name of the device for the x-axis.
+ x(list | np.ndarray): Custom y data to plot.
+ 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.
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.
@@ -1527,7 +1537,7 @@ class BECWaveform(RPCBase):
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.
+ dap(str): The dap model to use for the curve, only available for sync devices. If not specified, none will be added.
Returns:
BECCurve: The curve object.
@@ -1536,12 +1546,13 @@ class BECWaveform(RPCBase):
@rpc_call
def add_dap(
self,
- x_name: "str",
- y_name: "str",
+ x_name: "str | None" = None,
+ y_name: "str | None" = None,
x_entry: "Optional[str]" = None,
y_entry: "Optional[str]" = None,
color: "Optional[str]" = None,
dap: "str" = "GaussianModel",
+ validate_bec: "bool" = True,
**kwargs,
) -> "BECCurve":
"""
@@ -1556,12 +1567,27 @@ class BECWaveform(RPCBase):
color_map_z(str): The color map to use for the z-axis.
label(str, optional): Label 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.
"""
+ @rpc_call
+ 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.
+ """
+
@rpc_call
def get_dap_params(self) -> "dict":
"""
@@ -1746,6 +1772,12 @@ class BECWaveform(RPCBase):
Remove the plot widget from the figure.
"""
+ @rpc_call
+ def clear_all(self):
+ """
+ None
+ """
+
@rpc_call
def set_legend_label_size(self, size: "int" = None):
"""
@@ -1756,24 +1788,6 @@ class BECWaveform(RPCBase):
"""
-class DeviceBox(RPCBase):
- @property
- @rpc_call
- def _config_dict(self) -> "dict":
- """
- Get the configuration of the widget.
-
- Returns:
- dict: The configuration of the widget.
- """
-
- @rpc_call
- def _get_all_rpc(self) -> "dict":
- """
- Get all registered RPC objects.
- """
-
-
class BECWaveformWidget(RPCBase):
@property
@rpc_call
@@ -1800,6 +1814,7 @@ class BECWaveformWidget(RPCBase):
label: "str | None" = None,
validate: "bool" = True,
dap: "str | None" = None,
+ **kwargs,
) -> "BECCurve":
"""
Plot a curve to the plot widget.
@@ -2003,6 +2018,24 @@ class BECWaveformWidget(RPCBase):
"""
+class DeviceBox(RPCBase):
+ @property
+ @rpc_call
+ def _config_dict(self) -> "dict":
+ """
+ Get the configuration of the widget.
+
+ Returns:
+ dict: The configuration of the widget.
+ """
+
+ @rpc_call
+ def _get_all_rpc(self) -> "dict":
+ """
+ Get all registered RPC objects.
+ """
+
+
class DeviceComboBox(RPCBase):
@property
@rpc_call
diff --git a/bec_widgets/widgets/waveform/waveform_toolbar/curve_dialog/curve_dialog.py b/bec_widgets/widgets/waveform/waveform_toolbar/curve_dialog/curve_dialog.py
index d8b98a51..71990343 100644
--- a/bec_widgets/widgets/waveform/waveform_toolbar/curve_dialog/curve_dialog.py
+++ b/bec_widgets/widgets/waveform/waveform_toolbar/curve_dialog/curve_dialog.py
@@ -29,18 +29,42 @@ class CurveSettings(SettingWidget):
self.layout.addWidget(self.ui)
self.ui.add_curve.clicked.connect(self.add_curve)
+ self.ui.x_mode.currentIndexChanged.connect(self.set_x_mode)
@Slot(dict)
def display_current_settings(self, config: dict | BaseModel):
curves = config["scan_segment"]
- first_label, first_curve = next(iter(curves.items()))
- self.ui.x_name.setText(first_curve.config.signals.x.name)
- self.ui.x_entry.setText(first_curve.config.signals.x.entry)
+
+ # set mode of x axis box
+ x_name = self.target_widget.waveform._x_axis_mode["name"]
+ x_entry = self.target_widget.waveform._x_axis_mode["entry"]
+ self._setup_x_box(x_name, x_entry)
+
for label, curve in curves.items():
row_count = self.ui.scan_table.rowCount()
self.ui.scan_table.insertRow(row_count)
ScanRow(table_widget=self.ui.scan_table, row=row_count, config=curve.config)
+ def _setup_x_box(self, name, entry):
+ if name in ["index", "timestamp", "best_effort"]:
+ self.ui.x_mode.setCurrentText(name)
+ self.set_x_mode()
+ else:
+ self.ui.x_mode.setCurrentText("device")
+ self.set_x_mode()
+ self.ui.x_name.setText(name)
+ self.ui.x_entry.setText(entry)
+
+ @Slot()
+ def set_x_mode(self):
+ x_mode = self.ui.x_mode.currentText()
+ if x_mode in ["index", "timestamp", "best_effort"]:
+ self.ui.x_name.setEnabled(False)
+ self.ui.x_entry.setEnabled(False)
+ else:
+ self.ui.x_name.setEnabled(True)
+ self.ui.x_entry.setEnabled(True)
+
@Slot()
def accept_changes(self):
self.accept_scan_curve_changes()
@@ -52,8 +76,17 @@ class CurveSettings(SettingWidget):
self.get_curve_params()
def get_curve_params(self):
- x_name = self.ui.x_name.text()
- x_entry = self.ui.x_entry.text()
+ x_mode = self.ui.x_mode.currentText()
+
+ if x_mode in ["index", "timestamp", "best_effort"]:
+ x_name = x_mode
+ x_entry = x_mode
+ else:
+ x_name = self.ui.x_name.text()
+ x_entry = self.ui.x_entry.text()
+
+ self.target_widget.set_x(x_name=x_name, x_entry=x_entry)
+
for row in range(self.ui.scan_table.rowCount()):
y_name = self.ui.scan_table.cellWidget(row, 0).text()
y_entry = self.ui.scan_table.cellWidget(row, 1).text()
@@ -62,8 +95,6 @@ class CurveSettings(SettingWidget):
width = self.ui.scan_table.cellWidget(row, 4).value()
symbol_size = self.ui.scan_table.cellWidget(row, 5).value()
self.target_widget.plot(
- x_name=x_name,
- x_entry=x_entry,
y_name=y_name,
y_entry=y_entry,
color=color,
diff --git a/bec_widgets/widgets/waveform/waveform_toolbar/curve_dialog/curve_dialog.ui b/bec_widgets/widgets/waveform/waveform_toolbar/curve_dialog/curve_dialog.ui
index 32df4fa1..437169d5 100644
--- a/bec_widgets/widgets/waveform/waveform_toolbar/curve_dialog/curve_dialog.ui
+++ b/bec_widgets/widgets/waveform/waveform_toolbar/curve_dialog/curve_dialog.ui
@@ -31,7 +31,67 @@
X Axis
-
+
+ -
+
+
+ X Axis Mode
+
+
+
+ -
+
+
-
+
+ best_effort
+
+
+ -
+
+ device
+
+
+ -
+
+ index
+
+
+ -
+
+ timestamp
+
+
+
+
+ -
+
+
+ Qt::Orientation::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ QFrame::Shadow::Sunken
+
+
+ 1
+
+
+ 0
+
+
+ Qt::Orientation::Vertical
+
+
+
-
diff --git a/bec_widgets/widgets/waveform/waveform_widget.py b/bec_widgets/widgets/waveform/waveform_widget.py
index f59f639d..dac4b99c 100644
--- a/bec_widgets/widgets/waveform/waveform_widget.py
+++ b/bec_widgets/widgets/waveform/waveform_widget.py
@@ -124,7 +124,9 @@ class BECWaveformWidget(BECConnector, QWidget):
dialog.resize(800, 600)
dialog.exec()
- def _check_if_scans_have_same_x(self, enabled=True, x_name_to_check: str = None) -> bool:
+ def _check_if_scans_have_same_x(
+ self, enabled=True, x_name_to_check: str = None
+ ) -> bool: # TODO probably not needed anymore
"""
Check if all scans have the same x-axis.
@@ -173,6 +175,20 @@ class BECWaveformWidget(BECConnector, QWidget):
"""
return self.waveform.get_curve(identifier)
+ 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)
+
def plot(
self,
x: list | np.ndarray | None = None,
@@ -210,7 +226,7 @@ class BECWaveformWidget(BECConnector, QWidget):
Returns:
BECCurve: The curve object.
"""
- self._check_if_scans_have_same_x(enabled=True, x_name_to_check=x_name)
+ # self._check_if_scans_have_same_x(enabled=True, x_name_to_check=x_name)
return self.waveform.plot(
x=x,
y=y,