"""Display controls retain measurements and redraw the same source timeline.""" import numpy as np import pytest from orisys_app_shared.force.session import SessionSample, SessionStore from orisys_app_shared.force.source import StoreCurveSource from orisys_studio.ui.force_plots import ForcePlotsPanel def _store(*, partial=False): store = SessionStore() for index in range(21): raw = float(index + 100) shear = float("nan") if partial else raw / 100 store.append(SessionSample( frame_id=index, t_rel_s=float(index), fn_raw=raw, fx_raw=-raw, fy_raw=raw, fn_n=raw / 100, fx_n=shear, fy_n=shear, fn_raw_processed=raw, fx_raw_processed=-raw, fy_raw_processed=raw, fn_n_processed=raw / 100, fx_n_processed=shear, fy_n_processed=shear, )) return store def _curve(panel, axis=0): x, y = panel.curves[axis].getData() if x is None: return np.empty(0), np.empty(0) return np.asarray(x, dtype=float), np.asarray(y, dtype=float) @pytest.mark.parametrize("browse", [False, True]) def test_y_limit_settings_keep_trace_window_cursor_and_store(make_window, browse): window = make_window(units="raw", plot_window_sec=4.0) store = _store() window.force_plots.set_store(store) if browse: window.force_plots.set_window(5.0, 12.0) window.force_plots.set_cursor(8.0) before = tuple(array.copy() for array in _curve(window.force_plots)) x_range = window.force_plots.plots[0].viewRange()[0] # No acquisition tick follows: an idle or paused view must redraw immediately. window.display_ctl.apply_plot_settings({"fn_raw_max": 2000.0}) for actual, expected in zip(_curve(window.force_plots), before): np.testing.assert_array_equal(actual, expected) assert window.force_plots.plots[0].viewRange()[0] == pytest.approx(x_range) assert window.force_plots.cursor_time() == 8.0 assert len(store.visible(0.0, 20.0).times) == 21 @pytest.mark.parametrize("kind", ["memory", "disk", "analysis"]) def test_window_and_unit_changes_preserve_partial_axes_and_session_time(qt_app, kind): store = _store(partial=True) panel = ForcePlotsPanel() try: source = StoreCurveSource(store) source.kind = kind panel.set_curve_source(source) for unit in ("N", "raw", "N"): panel.set_units(unit) for seconds in (4.0, 8.0, 8.0): panel.set_window_sec(seconds) x, y = _curve(panel) assert len(x) > 1 assert x[-1] == 20.0 assert x[0] == 20.0 - seconds assert y[-1] == pytest.approx(1.2 if unit == "N" else 120.0) assert panel.plots[0].viewRange()[0][1] == pytest.approx(20.0) if unit == "N": assert np.isnan(_curve(panel, 1)[1]).all() assert np.isnan(_curve(panel, 2)[1]).all() assert len(store.visible(0.0, 20.0).times) == 21 finally: panel.close() panel.deleteLater() def test_back_to_latest_reloads_the_live_tail_without_duplicate_samples(qt_app): panel = ForcePlotsPanel() try: panel.set_store(_store()) for _ in range(2): panel.set_window(2.0, 7.0) panel.follow_latest() x, y = _curve(panel) np.testing.assert_array_equal(x, np.arange(16.0, 21.0)) np.testing.assert_array_equal(y, np.arange(116.0, 121.0)) panel.reset() assert _curve(panel)[0].size == 0 finally: panel.close() panel.deleteLater() def test_auto_y_range_keeps_replayed_data_visible_after_unit_switch(qt_app): panel = ForcePlotsPanel() try: panel.set_store(_store()) panel.show_all() panel.set_axis_limits( fn_min=0, fn_max=20, shear_max=20, fn_raw_min=0, fn_raw_max=0, shear_raw_max=0, ) panel.set_units("N") panel.set_units("raw") qt_app.processEvents() x, y = _curve(panel) assert x.size == 21 low, high = panel.plots[0].viewRange()[1] assert low <= y.min() <= y.max() <= high finally: panel.close() panel.deleteLater()