subject: fix calibration cancel, unit mixing, FN clamping, export/apply and depth scale

This commit is contained in:
ykcheungab
2026-09-13 12:35:05 +08:00
parent db228b6f57
commit f501fa93f3
9 changed files with 725 additions and 78 deletions
+151 -1
View File
@@ -4,6 +4,7 @@ from __future__ import annotations
import pytest
import ui_check
from tests.conftest import visible_descendants
RESOLUTIONS = ((1280, 720), (1600, 900), (1920, 1080))
@@ -196,7 +197,7 @@ def test_toolbar_run_button_is_labelled(make_window):
window = _show(make_window(), (1400, 880))
label = window.toolbar.btn_run.text()
assert label.strip()
assert label != "▶"
assert label != "â–¶"
window.toolbar.set_run_checked(True)
assert window.toolbar.btn_run.text() != label
@@ -279,3 +280,152 @@ def test_force_plots_render_demo_data(make_window):
QApplication.processEvents()
assert window.force_plots.history.sample_count > 0
assert all(label.text() for label in window.force_plots.value_labels)
# --------------------------------------------------------------- record channel
def _running_window(make_window):
"""A window in the ``running`` phase whose worker never opens a device.
The Qt timer is stopped deliberately: these tests drive the display path by
calling ``_on_run_tick`` themselves, and a concurrent 16 ms timer would race
the assertions (and outlive the window on teardown).
"""
window = _show(make_window(sensor_type="box", source_mode="camera"), (1440, 880))
stuck = ui_check._StuckWorker()
window._ensure_workers = lambda: None
window._box_worker = stuck
window._finger_worker = stuck
window._start_run()
window._run_timer.stop()
window._set_phase("running")
return window, stuck
def _finish(window, stuck):
window._stop_run(reason="user_stop")
stuck.release()
def test_record_channel_does_not_depend_on_the_ui_timer(make_window):
window, stuck = _running_window(make_window)
for index in range(90):
stuck.emit(ui_check._fake_packet(index))
assert window.session_store.count == 90, "samples were lost without a UI tick"
_finish(window, stuck)
def test_invalid_samples_are_excluded_not_zeroed(make_window):
import math
window, stuck = _running_window(make_window)
for index in range(9):
stuck.emit(ui_check._fake_packet(index))
stuck.emit(ui_check._fake_packet(99, valid=False, reason="read failed"))
slice_ = window.session_store.data()
assert slice_.valid.tolist()[-1] is False
assert math.isnan(slice_.raw[-1][0]), "a failed readout became a number"
assert sum(1 for _ in window.session_store.iter_valid("raw")) == 9
_finish(window, stuck)
def test_calibration_sampling_survives_a_hidden_panel(make_window):
window, stuck = _running_window(make_window)
window._show_cal = False
window._apply_panel_visibility()
assert not window.cal_panel.isVisible()
window.cal_recorder.start(channel="fn", reference_load_n=2.0, duration_s=1.0)
for index in range(40):
stuck.emit(ui_check._fake_packet(index))
point = window.cal_recorder.finish_now()
assert point is not None
assert point.n_valid == 40, "hiding the panel stopped the sampling"
assert point.status == "ok"
_finish(window, stuck)
def test_record_button_stays_a_cancel_affordance(make_window):
from orisys_app_shared.i18n import t
window, stuck = _running_window(make_window)
window.cal_panel.set_running(True)
window.cal_panel._on_record_clicked()
assert window.cal_panel._recording
assert window.cal_panel.btn_record.isEnabled(), "the recording cannot be stopped"
assert window.cal_panel.btn_record.text() == t("cal.recording_stop")
window.cal_panel._on_record_clicked()
assert not window.cal_panel._recording
_finish(window, stuck)
def test_unit_switch_rebuilds_from_the_session_store(make_window):
import math
window, stuck = _running_window(make_window)
window.toolbar.units_combo.setCurrentIndex(1) # raw
window.force_plots.reset()
for index in range(60):
stuck.emit(ui_check._fake_packet(index))
window._on_run_tick()
state = window.force_plots.history.state()
assert float(state.values[:, 0].max()) > 5.0, "raw values were not plotted"
window.toolbar.units_combo.setCurrentIndex(0) # newton
assert window.force_plots._unit == "N"
newtons = window.force_plots.history.state().values[:, 0]
finite = [v for v in newtons if math.isfinite(v)]
assert finite and max(finite) < 5.0, "the buffer still held raw values in N mode"
_finish(window, stuck)
def test_history_keeps_negative_fn(make_window):
window, stuck = _running_window(make_window)
window.force_plots.set_fixed_newton(True)
for index in range(20):
window.force_plots.push(index / 30.0, -2.5, 0.0, 0.0, unit="N")
window.force_plots.push(1.0, -3.0, 0.0, 0.0, unit="N")
state = window.force_plots.history.state()
assert float(state.values[:, 0].min()) < 0.0, (
"negative FN was clamped before entering the buffer"
)
_finish(window, stuck)
def test_depth_view_reports_missing_data_and_fixes_its_scale(make_window):
import numpy as np
window, stuck = _running_window(make_window)
window.arrow_panel.set_view_mode("depth")
window._last_rendered_view_mode = None
stuck.emit(ui_check._fake_packet(0, depth=None))
window._on_run_tick()
from orisys_app_shared.i18n import t
assert window.arrow_panel.image_label.text() == t("panels.depth_unavailable"), (
"a missing depth map silently fell back to the processed frame"
)
window._last_rendered_view_mode = None
stuck.emit(ui_check._fake_packet(1, depth=np.linspace(0.0, 1.0, 64).reshape(8, 8)))
window._on_run_tick()
latched = window.arrow_panel.depth_scale_label.text()
assert latched
window._last_rendered_view_mode = None
stuck.emit(ui_check._fake_packet(2, depth=np.linspace(0.0, 9.0, 64).reshape(8, 8)))
window._on_run_tick()
assert window.arrow_panel.depth_scale_label.text() == latched, (
"the depth colour scale re-fitted on every frame"
)
_finish(window, stuck)