diff --git a/bec_widgets/cli/client.py b/bec_widgets/cli/client.py index 8ce75fd8..24ce5cb6 100644 --- a/bec_widgets/cli/client.py +++ b/bec_widgets/cli/client.py @@ -4554,6 +4554,15 @@ class Waveform(RPCBase): Set auto range for the y-axis. """ + @rpc_call + def auto_range(self, value: "bool" = True): + """ + On demand apply autorange to the plot item based on the visible curves. + + Args: + value(bool): If True, apply autorange to the visible curves. + """ + @property @rpc_call def x_log(self) -> "bool": diff --git a/bec_widgets/widgets/plots/plot_base.py b/bec_widgets/widgets/plots/plot_base.py index f77f0392..42acd12a 100644 --- a/bec_widgets/widgets/plots/plot_base.py +++ b/bec_widgets/widgets/plots/plot_base.py @@ -881,6 +881,38 @@ class PlotBase(BECWidget, QWidget): """ self.plot_item.enableAutoRange(y=value) + def auto_range(self, value: bool = True): + """ + On demand apply autorange to the plot item based on the visible curves. + + Args: + value(bool): If True, apply autorange to the visible curves. + """ + if not value: + self.plot_item.enableAutoRange(x=False, y=False) + return + self._apply_autorange_only_visible_curves() + + def _fetch_visible_curves(self): + """ + Fetch all visible curves from the plot item. + """ + visible_curves = [] + for curve in self.plot_item.curves: + if curve.isVisible(): + visible_curves.append(curve) + return visible_curves + + def _apply_autorange_only_visible_curves(self): + """ + Apply autorange to the plot item based on the provided curves. + + Args: + curves (list): List of curves to apply autorange to. + """ + visible_curves = self._fetch_visible_curves() + self.plot_item.autoRange(items=visible_curves if visible_curves else None) + @SafeProperty(int, doc="The font size of the legend font.") def legend_label_size(self) -> int: """ diff --git a/bec_widgets/widgets/plots/toolbar_components/mouse_interactions.py b/bec_widgets/widgets/plots/toolbar_components/mouse_interactions.py index 61a7425d..6fdab36d 100644 --- a/bec_widgets/widgets/plots/toolbar_components/mouse_interactions.py +++ b/bec_widgets/widgets/plots/toolbar_components/mouse_interactions.py @@ -165,5 +165,4 @@ class MouseInteractionConnection(BundleConnection): Enable autorange on the plot widget. """ if self.target_widget: - self.target_widget.auto_range_x = True - self.target_widget.auto_range_y = True + self.target_widget.auto_range() diff --git a/bec_widgets/widgets/plots/waveform/waveform.py b/bec_widgets/widgets/plots/waveform/waveform.py index 8dc1e35a..97be09d5 100644 --- a/bec_widgets/widgets/plots/waveform/waveform.py +++ b/bec_widgets/widgets/plots/waveform/waveform.py @@ -96,6 +96,7 @@ class Waveform(PlotBase): "auto_range_x.setter", "auto_range_y", "auto_range_y.setter", + "auto_range", "x_log", "x_log.setter", "y_log", @@ -1109,8 +1110,7 @@ class Waveform(PlotBase): self.reset() self.new_scan.emit() self.new_scan_id.emit(current_scan_id) - self.auto_range_x = True - self.auto_range_y = True + self.auto_range(True) self.old_scan_id = self.scan_id self.scan_id = current_scan_id self.scan_item = self.queue.scan_storage.find_scan_by_ID(self.scan_id) # live scan diff --git a/tests/unit_tests/test_plot_base_next_gen.py b/tests/unit_tests/test_plot_base_next_gen.py index 79d52650..c1918d65 100644 --- a/tests/unit_tests/test_plot_base_next_gen.py +++ b/tests/unit_tests/test_plot_base_next_gen.py @@ -1,3 +1,5 @@ +import numpy as np + from bec_widgets.widgets.plots.plot_base import PlotBase, UIMode from .client_mocks import mocked_client @@ -126,6 +128,31 @@ def test_auto_range_x_y(qtbot, mocked_client): assert pb.plot_item.vb.state["autoRange"][1] is False +def test_autorange_respects_visibility(qtbot, mocked_client): + """ + Autorange must consider only the curves whose .isVisible() flag is True. + """ + + pb = create_widget(qtbot, PlotBase, client=mocked_client) + + x = np.arange(10) + small = pb.plot_item.plot(x, x, pen=(255, 0, 0)) # 0‒9 + medium = pb.plot_item.plot(x, x * 10, pen=(0, 255, 0)) # 0‒90 + large = pb.plot_item.plot(x, x * 100, pen=(0, 0, 255)) # 0‒900 + + pb.auto_range(True) + qtbot.wait(200) + yspan_full = pb.plot_item.vb.viewRange()[1] + assert yspan_full[1] > 800, "Autorange must include the largest visible curve." + + # Hide the largest curve, recompute autorange, and expect the span to shrink. + large.setVisible(False) + pb.auto_range(True) + qtbot.wait(200) + yspan_reduced = pb.plot_item.vb.viewRange()[1] + assert yspan_reduced[1] < 200, "Hidden curves must be excluded from autorange." + + def test_x_log_y_log(qtbot, mocked_client): """ Test toggling log scale on x and y axes.