Rework radar system
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import ExitStack
|
||||
|
||||
from PyQt6.QtCore import QSignalBlocker, pyqtSignal
|
||||
from PyQt6.QtWidgets import (
|
||||
QCheckBox,
|
||||
@@ -24,12 +26,11 @@ from PyQt6.QtWidgets import (
|
||||
import numpy as np
|
||||
import pyqtgraph as pg
|
||||
|
||||
from python_app.models.gui_profile_schema import GuiPreprocessDialogStateModel
|
||||
from python_app.models.dataset_model import TraceData
|
||||
from python_app.orchestration.preprocess_assets import (
|
||||
CAPTURABLE_PREPROCESS_ASSET_KEYS,
|
||||
PREPROCESS_ASSET_SPECS,
|
||||
PREPROCESS_ASSET_NAMES,
|
||||
REQUIRED_PREPROCESS_ASSET_KEYS,
|
||||
VISIBLE_PREPROCESS_ASSET_KEYS,
|
||||
preprocess_asset_display_name,
|
||||
)
|
||||
|
||||
@@ -49,7 +50,6 @@ class PreprocessDialog(QDialog):
|
||||
finalize_sequence_requested = pyqtSignal()
|
||||
abort_sequence_requested = pyqtSignal()
|
||||
create_neutral_sets_requested = pyqtSignal()
|
||||
import_object_calibration_requested = pyqtSignal()
|
||||
create_object_calibration_requested = pyqtSignal()
|
||||
|
||||
def __init__(self, parent=None) -> None:
|
||||
@@ -113,7 +113,7 @@ class PreprocessDialog(QDialog):
|
||||
layout.addLayout(self._build_median_sweep_row(group))
|
||||
layout.addWidget(self._build_radar_config_group(group))
|
||||
|
||||
layout.addWidget(self._build_selector_group("S21", VISIBLE_PREPROCESS_ASSET_KEYS, group))
|
||||
layout.addWidget(self._build_selector_group("S21", tuple(PREPROCESS_ASSET_NAMES), group))
|
||||
return group
|
||||
|
||||
def _build_median_sweep_row(self, parent: QGroupBox) -> QHBoxLayout:
|
||||
@@ -179,13 +179,9 @@ class PreprocessDialog(QDialog):
|
||||
row = QHBoxLayout(field)
|
||||
row.setContentsMargins(0, 0, 0, 0)
|
||||
row.addWidget(combo, stretch=1)
|
||||
self._import_object_calibration_button = QPushButton("Import…", field)
|
||||
self._import_object_calibration_button.setToolTip("Import an existing cal_*.npy MIMO calibration folder.")
|
||||
self._import_object_calibration_button.clicked.connect(self.import_object_calibration_requested.emit)
|
||||
self._create_object_calibration_button = QPushButton("Create…", field)
|
||||
self._create_object_calibration_button.setToolTip("Calculate a MIMO calibration from reflector measurements.")
|
||||
self._create_object_calibration_button.clicked.connect(self.create_object_calibration_requested.emit)
|
||||
row.addWidget(self._import_object_calibration_button)
|
||||
row.addWidget(self._create_object_calibration_button)
|
||||
form.addRow(self._asset_row_label(key), field)
|
||||
return group
|
||||
@@ -218,7 +214,7 @@ class PreprocessDialog(QDialog):
|
||||
def _build_sequence_button_grid(self, parent: QGroupBox) -> QGridLayout:
|
||||
"""Build per-asset capture start buttons."""
|
||||
layout = QGridLayout()
|
||||
for index, key in enumerate(CAPTURABLE_PREPROCESS_ASSET_KEYS):
|
||||
for index, key in enumerate(REQUIRED_PREPROCESS_ASSET_KEYS):
|
||||
button = QPushButton(f"Start {preprocess_asset_display_name(key)}", parent)
|
||||
button.clicked.connect(lambda _checked=False, asset_key=key: self.start_sequence_requested.emit(asset_key))
|
||||
layout.addWidget(button, index // 2, index % 2)
|
||||
@@ -285,6 +281,19 @@ class PreprocessDialog(QDialog):
|
||||
"""Return requested target set name."""
|
||||
return self._set_name_input.text().strip()
|
||||
|
||||
def apply_settings(self, state: GuiPreprocessDialogStateModel, selected: dict[str, str], *, neutral_visible: bool) -> None:
|
||||
"""Apply profile values atomically, without emitting selection/edit signals."""
|
||||
with ExitStack() as blockers:
|
||||
for widget in (self._set_name_input, self._radar_config_dir_input,
|
||||
self._use_all_radar_configs_checkbox, *self._set_combos.values()):
|
||||
blockers.enter_context(QSignalBlocker(widget))
|
||||
self.set_set_name(state.set_name)
|
||||
self.set_radar_config_dir(state.radar_config_dir)
|
||||
self.set_use_all_radar_configs(state.use_all_radar_configs)
|
||||
self.set_median_sweep_count(state.median_sweep_count)
|
||||
self.set_selected_sets(selected, emit_signal=False)
|
||||
self.set_neutral_sets_visible(neutral_visible)
|
||||
|
||||
def set_set_name(self, value: str) -> None:
|
||||
"""Replace requested target set name."""
|
||||
self._set_name_input.setText(value)
|
||||
@@ -335,7 +344,7 @@ class PreprocessDialog(QDialog):
|
||||
|
||||
def selection_snapshot(self) -> dict[str, str]:
|
||||
"""Return currently selected set names keyed by preprocess asset key."""
|
||||
return {key: self._set_combos[key].currentData() or "" for key in VISIBLE_PREPROCESS_ASSET_KEYS}
|
||||
return {key: self._set_combos[key].currentData() or "" for key in PREPROCESS_ASSET_NAMES}
|
||||
|
||||
def clear_capture_log(self) -> None:
|
||||
"""Clear capture history text box."""
|
||||
@@ -394,7 +403,7 @@ class PreprocessDialog(QDialog):
|
||||
return
|
||||
|
||||
actions_enabled = bool(actions_enabled)
|
||||
active_label = preprocess_asset_display_name(kind) if kind in PREPROCESS_ASSET_SPECS else kind
|
||||
active_label = preprocess_asset_display_name(kind) if kind in PREPROCESS_ASSET_NAMES else kind
|
||||
self._active_kind_label.setText(active_label)
|
||||
self._progress_label.setText(f"{captured_count} / {total_count}")
|
||||
self._undo_last_button.setEnabled(bool(can_undo) and actions_enabled)
|
||||
@@ -414,14 +423,14 @@ class PreprocessDialog(QDialog):
|
||||
|
||||
def set_available_sets(self, available_sets: dict[str, list[str]]) -> None:
|
||||
"""Replace combo-box choices for all preprocess assets."""
|
||||
for key in VISIBLE_PREPROCESS_ASSET_KEYS:
|
||||
for key in PREPROCESS_ASSET_NAMES:
|
||||
combo = self._set_combos[key]
|
||||
with QSignalBlocker(combo):
|
||||
self._set_combo_items(combo, available_sets.get(key, []), combo.currentData() or "")
|
||||
|
||||
def set_selected_sets(self, selected_sets: dict[str, str], *, emit_signal: bool = True) -> None:
|
||||
"""Apply selected set names to all comboboxes and optionally emit update."""
|
||||
for key in VISIBLE_PREPROCESS_ASSET_KEYS:
|
||||
for key in PREPROCESS_ASSET_NAMES:
|
||||
selected_value = selected_sets.get(key, "")
|
||||
combo = self._set_combos[key]
|
||||
with QSignalBlocker(combo):
|
||||
@@ -451,9 +460,9 @@ class PreprocessDialog(QDialog):
|
||||
if self._preview_placeholder is not None:
|
||||
self._preview_placeholder.setText("Preview will appear after the first successful capture.")
|
||||
|
||||
def draw_last_trace(self, trace: TraceData, title: str, *, channel: str) -> None:
|
||||
def draw_last_trace(self, trace: TraceData, title: str) -> None:
|
||||
"""Draw amplitude (dB) and wrapped phase (deg, ±180) panes for the latest capture."""
|
||||
samples = trace.s11 if channel == "s11" else trace.s21
|
||||
samples = trace.s21
|
||||
magnitude_db = 20.0 * np.log10(np.maximum(np.abs(samples), 1e-12))
|
||||
phase_deg = np.degrees(np.angle(samples))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user