From 4633a92144d841e5d0928b1aaafc6afd59dbb355 Mon Sep 17 00:00:00 2001 From: Ayzen Date: Tue, 6 Oct 2026 19:36:00 +0300 Subject: [PATCH] List saved object calibrations immediately --- .../controllers/object_calibration_controller.py | 7 ++++--- python_app/gui/controllers/preprocess_controller.py | 13 +++++++------ python_app/tests/test_object_calibration_runtime.py | 9 +++++++-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/python_app/gui/controllers/object_calibration_controller.py b/python_app/gui/controllers/object_calibration_controller.py index bbbe0f1..6fc0058 100644 --- a/python_app/gui/controllers/object_calibration_controller.py +++ b/python_app/gui/controllers/object_calibration_controller.py @@ -49,11 +49,11 @@ class ObjectCalibrationController(QObject): """Own one modeless editor, acquisition job and cancellable calculation.""" def __init__(self, parent: QWidget, store: NpzStore, build_config: Callable[[], RunConfigModel], - capture: Callable[[ObjectCalibrationDialog], ObjectSweepCapture], select_saved: Callable[[str], None], + capture: Callable[[ObjectCalibrationDialog], ObjectSweepCapture], saved: Callable[[str, bool], None], error: Callable[[str, Exception], None]) -> None: super().__init__(parent) self._parent, self._store, self._build_config = parent, store, build_config - self._start_capture, self._select_saved, self._error = capture, select_saved, error + self._start_capture, self._saved, self._error = capture, saved, error self.dialog: ObjectCalibrationDialog | None = None self.capture: ObjectSweepCapture | None = None self._closed = False @@ -157,8 +157,9 @@ class ObjectCalibrationController(QObject): validate_object_set(collection, metadata, current.to_dict(), current_key, through) except Exception as exc: status += f" Not selected for the current configuration: {exc}" + self._saved(self._save_name, False) else: - self._select_saved(self._save_name) + self._saved(self._save_name, True) status += " Applies on the next Start." self.dialog.set_status(status) logger.info("%s", status) diff --git a/python_app/gui/controllers/preprocess_controller.py b/python_app/gui/controllers/preprocess_controller.py index 5f9a744..726b946 100644 --- a/python_app/gui/controllers/preprocess_controller.py +++ b/python_app/gui/controllers/preprocess_controller.py @@ -58,7 +58,7 @@ class PreprocessController: self._capture_pause: PipelinePause | None = None self._radar_variants: list[RadarConfigVariant] = [] self.object_calibration = ObjectCalibrationController( - parent, store, build_config, self._capture_object, self._select_object, error, + parent, store, build_config, self._capture_object, self._object_saved, error, ) def bind_actions(self, primary: PrimaryView, data: DataView) -> None: @@ -529,12 +529,13 @@ class PreprocessController: provenance = capture_provenance(config.to_dict(), radar_key, through) return ObjectSweepCapture(self._pipeline, dialog, config, self.settings().median_sweep_count, provenance) - def _select_object(self, name: str) -> None: - self.selected_sets["s21_object_calibration"] = name - self.ensure_dialog().set_set_name(name) - self._summary(self.selected_sets) + def _object_saved(self, name: str, applicable: bool) -> None: + """List a new object calibration at once; select it only when it fits the current setup.""" + if applicable: + self.selected_sets["s21_object_calibration"] = name + self.ensure_dialog().set_set_name(name) + logger.info("Selected object calibration: %s", name) self._refresh_requested() - logger.info("Selected object calibration: %s", name) def invalidate_object_calibration_after_geometry_change(self) -> None: selected = self.selected_sets.get("s21_object_calibration", "") diff --git a/python_app/tests/test_object_calibration_runtime.py b/python_app/tests/test_object_calibration_runtime.py index 59d9df1..e2ae1c1 100644 --- a/python_app/tests/test_object_calibration_runtime.py +++ b/python_app/tests/test_object_calibration_runtime.py @@ -258,12 +258,14 @@ class ObjectCaptureLifecycleTest(unittest.TestCase): metadata = {"provenance": provenance, "targets": [], "diagnostics": [], "tx_output_pos": [1, 3], "rx_input_pos": [0, 2]} self.dialog.add_capture([_through()], captured.to_dict(), provenance) - for name, error in (("matching", None), ("changed", None), + for name, error in (("matching", None), ("changed", None), ("unvalidated", None), ("cancelled", InterruptedError("cancelled")), ("failed", ValueError("bad input"))): with self.subTest(outcome=name): self.config = captured.clone() if name == "changed": self.config.radar.sweep.points += 1 + if name == "unvalidated": # Same radar key, but the selected through set is gone. + self.config.preprocess.s21.calibration.set_name = "absent" self.dialog._set_name_input.setText(name) with mock.patch.object(self.dialog, "calculation_inputs", return_value=([], captured.to_dict(), {}, provenance)), \ mock.patch("python_app.workflows.mimo_calibration.compute_from_collections", @@ -284,6 +286,9 @@ class ObjectCaptureLifecycleTest(unittest.TestCase): self.assertEqual(saved_meta["provenance"], provenance) self.assertEqual(len(saved.traces), 4) expected = {"matching": "Applies on the next Start", "changed": "Not selected", - "cancelled": "cancelled", "failed": "failed"} + "unvalidated": "Not selected", "cancelled": "cancelled", "failed": "failed"} self.assertIn(expected[name], self.dialog._status_label.text()) + if name in ("matching", "unvalidated"): # Listed at once, without reopening the dialog. + combo = self.preprocess.ensure_dialog()._set_combos["s21_object_calibration"] + self.assertGreaterEqual(combo.findData(name), 0) self.error.assert_called_once()