added s11!
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
"""Dialog for calibration/reference set selection and sequential capture."""
|
||||
"""Dialog for preprocess set selection and sequential capture."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -6,6 +6,7 @@ from PyQt6.QtCore import pyqtSignal
|
||||
from PyQt6.QtWidgets import (
|
||||
QComboBox,
|
||||
QDialog,
|
||||
QFormLayout,
|
||||
QGridLayout,
|
||||
QGroupBox,
|
||||
QHBoxLayout,
|
||||
@@ -15,23 +16,24 @@ from PyQt6.QtWidgets import (
|
||||
QPushButton,
|
||||
QVBoxLayout,
|
||||
)
|
||||
import pyqtgraph as pg
|
||||
import numpy as np
|
||||
import pyqtgraph as pg
|
||||
|
||||
from python_app.models.dataset_model import TraceData
|
||||
from python_app.orchestration.preprocess_assets import (
|
||||
PREPROCESS_ASSET_KEYS,
|
||||
PREPROCESS_ASSET_SPECS,
|
||||
S11_PREPROCESS_ASSET_KEYS,
|
||||
S21_PREPROCESS_ASSET_KEYS,
|
||||
preprocess_asset_display_name,
|
||||
)
|
||||
|
||||
|
||||
class PreprocessDialog(QDialog):
|
||||
"""Standalone dialog for preprocessing capture workflows.
|
||||
|
||||
The dialog combines three concerns:
|
||||
1. Set selection (calibration/reference).
|
||||
2. Sequential capture controls for filling all N*M combinations.
|
||||
3. Quick preview of the last captured trace.
|
||||
"""
|
||||
"""Standalone dialog for preprocess set selection and capture workflows."""
|
||||
|
||||
refresh_requested = pyqtSignal()
|
||||
selection_changed = pyqtSignal(str, str)
|
||||
selection_changed = pyqtSignal()
|
||||
start_sequence_requested = pyqtSignal(str)
|
||||
capture_next_requested = pyqtSignal()
|
||||
abort_sequence_requested = pyqtSignal()
|
||||
@@ -39,13 +41,14 @@ class PreprocessDialog(QDialog):
|
||||
def __init__(self, parent=None) -> None:
|
||||
"""Initialize window metadata and compose dialog UI."""
|
||||
super().__init__(parent)
|
||||
self._set_combos: dict[str, QComboBox] = {}
|
||||
self._init_window()
|
||||
self._build_ui()
|
||||
|
||||
def _init_window(self) -> None:
|
||||
"""Set static window properties."""
|
||||
self.setWindowTitle("Preprocessing Setup")
|
||||
self.resize(1040, 760)
|
||||
self.resize(1120, 820)
|
||||
|
||||
def _build_ui(self) -> None:
|
||||
"""Build root dialog layout and all sections."""
|
||||
@@ -57,28 +60,33 @@ class PreprocessDialog(QDialog):
|
||||
|
||||
def _build_sets_group(self) -> QGroupBox:
|
||||
"""Build set-management controls used for preprocessing snapshots."""
|
||||
group = QGroupBox("Calibration / Reference Sets", self)
|
||||
layout = QGridLayout(group)
|
||||
group = QGroupBox("Preprocess Sets", self)
|
||||
layout = QVBoxLayout(group)
|
||||
|
||||
header_row = QHBoxLayout()
|
||||
self._set_name_input = QLineEdit("set_001", group)
|
||||
self._calibration_combo = QComboBox(group)
|
||||
self._reference_combo = QComboBox(group)
|
||||
|
||||
refresh_button = QPushButton("Refresh Sets", group)
|
||||
refresh_button.clicked.connect(self.refresh_requested.emit)
|
||||
header_row.addWidget(QLabel("Set name"))
|
||||
header_row.addWidget(self._set_name_input, stretch=1)
|
||||
header_row.addWidget(refresh_button)
|
||||
layout.addLayout(header_row)
|
||||
|
||||
self._calibration_combo.currentTextChanged.connect(self._emit_selection_changed)
|
||||
self._reference_combo.currentTextChanged.connect(self._emit_selection_changed)
|
||||
layout.addWidget(self._build_selector_group("S21", S21_PREPROCESS_ASSET_KEYS, group))
|
||||
layout.addWidget(self._build_selector_group("S11", S11_PREPROCESS_ASSET_KEYS, group))
|
||||
return group
|
||||
|
||||
layout.addWidget(QLabel("Set name"), 0, 0)
|
||||
layout.addWidget(self._set_name_input, 0, 1)
|
||||
layout.addWidget(refresh_button, 0, 2)
|
||||
def _build_selector_group(self, title: str, keys: tuple[str, ...], parent: QGroupBox) -> QGroupBox:
|
||||
"""Build one selector subgroup for a channel family."""
|
||||
group = QGroupBox(title, parent)
|
||||
form = QFormLayout(group)
|
||||
form.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
|
||||
|
||||
layout.addWidget(QLabel("Calibration set"), 1, 0)
|
||||
layout.addWidget(self._calibration_combo, 1, 1, 1, 2)
|
||||
|
||||
layout.addWidget(QLabel("Reference set"), 2, 0)
|
||||
layout.addWidget(self._reference_combo, 2, 1, 1, 2)
|
||||
for key in keys:
|
||||
combo = QComboBox(group)
|
||||
combo.currentTextChanged.connect(self._emit_selection_changed)
|
||||
self._set_combos[key] = combo
|
||||
form.addRow(self._asset_row_label(key), combo)
|
||||
return group
|
||||
|
||||
def _build_sequence_group(self) -> QGroupBox:
|
||||
@@ -95,8 +103,6 @@ class PreprocessDialog(QDialog):
|
||||
self._tx_antenna_label_input.setPlaceholderText("e.g. TX_A")
|
||||
self._rx_antenna_label_input.setPlaceholderText("e.g. RX_B")
|
||||
|
||||
button_row = self._build_sequence_button_row(group)
|
||||
|
||||
layout.addWidget(QLabel("Active type"), 0, 0)
|
||||
layout.addWidget(self._active_kind_label, 0, 1)
|
||||
layout.addWidget(QLabel("Progress"), 1, 0)
|
||||
@@ -107,22 +113,26 @@ class PreprocessDialog(QDialog):
|
||||
layout.addWidget(self._tx_antenna_label_input, 3, 1)
|
||||
layout.addWidget(QLabel("RX antenna label"), 4, 0)
|
||||
layout.addWidget(self._rx_antenna_label_input, 4, 1)
|
||||
layout.addLayout(button_row, 5, 0, 1, 2)
|
||||
layout.addLayout(self._build_sequence_button_grid(group), 5, 0, 1, 2)
|
||||
layout.addLayout(self._build_sequence_action_row(group), 6, 0, 1, 2)
|
||||
|
||||
self._capture_log = QPlainTextEdit(group)
|
||||
self._capture_log.setReadOnly(True)
|
||||
self._capture_log.setPlaceholderText("Capture history per combo")
|
||||
layout.addWidget(self._capture_log, 6, 0, 1, 2)
|
||||
layout.addWidget(self._capture_log, 7, 0, 1, 2)
|
||||
return group
|
||||
|
||||
def _build_sequence_button_row(self, parent: QGroupBox) -> QHBoxLayout:
|
||||
"""Build action buttons for sequence flow control."""
|
||||
start_calibration_button = QPushButton("Start Calibration Sequence", parent)
|
||||
start_calibration_button.clicked.connect(lambda: self.start_sequence_requested.emit("calibration"))
|
||||
|
||||
start_reference_button = QPushButton("Start Reference Sequence", parent)
|
||||
start_reference_button.clicked.connect(lambda: self.start_sequence_requested.emit("reference"))
|
||||
def _build_sequence_button_grid(self, parent: QGroupBox) -> QGridLayout:
|
||||
"""Build per-asset capture start buttons."""
|
||||
layout = QGridLayout()
|
||||
for index, key in enumerate(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)
|
||||
return layout
|
||||
|
||||
def _build_sequence_action_row(self, parent: QGroupBox) -> QHBoxLayout:
|
||||
"""Build capture/abort row for active sequence control."""
|
||||
self._capture_next_button = QPushButton("Capture Current Combo", parent)
|
||||
self._capture_next_button.clicked.connect(self.capture_next_requested.emit)
|
||||
self._capture_next_button.setEnabled(False)
|
||||
@@ -131,12 +141,11 @@ class PreprocessDialog(QDialog):
|
||||
self._abort_button.clicked.connect(self.abort_sequence_requested.emit)
|
||||
self._abort_button.setEnabled(False)
|
||||
|
||||
button_row = QHBoxLayout()
|
||||
button_row.addWidget(start_calibration_button)
|
||||
button_row.addWidget(start_reference_button)
|
||||
button_row.addWidget(self._capture_next_button)
|
||||
button_row.addWidget(self._abort_button)
|
||||
return button_row
|
||||
layout = QHBoxLayout()
|
||||
layout.addWidget(self._capture_next_button)
|
||||
layout.addWidget(self._abort_button)
|
||||
layout.addStretch(1)
|
||||
return layout
|
||||
|
||||
def _build_status_line(self, root_layout: QVBoxLayout) -> None:
|
||||
"""Build one-line status output for dialog operations."""
|
||||
@@ -155,13 +164,9 @@ class PreprocessDialog(QDialog):
|
||||
"""Return requested target set name."""
|
||||
return self._set_name_input.text().strip()
|
||||
|
||||
def calibration_set(self) -> str:
|
||||
"""Return currently selected calibration set."""
|
||||
return self._calibration_combo.currentText().strip()
|
||||
|
||||
def reference_set(self) -> str:
|
||||
"""Return currently selected reference set."""
|
||||
return self._reference_combo.currentText().strip()
|
||||
def selection_snapshot(self) -> dict[str, str]:
|
||||
"""Return currently selected set names keyed by preprocess asset key."""
|
||||
return {key: self._set_combos[key].currentText().strip() for key in PREPROCESS_ASSET_KEYS}
|
||||
|
||||
def antenna_labels(self) -> tuple[str, str]:
|
||||
"""Return optional TX/RX user labels used in capture logs."""
|
||||
@@ -209,7 +214,8 @@ class PreprocessDialog(QDialog):
|
||||
self._abort_button.setEnabled(False)
|
||||
return
|
||||
|
||||
self._active_kind_label.setText(kind)
|
||||
active_label = preprocess_asset_display_name(kind) if kind in PREPROCESS_ASSET_SPECS else kind
|
||||
self._active_kind_label.setText(active_label)
|
||||
self._progress_label.setText(f"{captured_count} / {total_count}")
|
||||
if next_input is None or next_output is None:
|
||||
self._combo_label.setText("<complete>")
|
||||
@@ -220,35 +226,32 @@ class PreprocessDialog(QDialog):
|
||||
self._capture_next_button.setEnabled(True)
|
||||
self._abort_button.setEnabled(True)
|
||||
|
||||
def set_calibration_sets(self, names: list[str]) -> None:
|
||||
"""Replace calibration set choices while preserving current selection when possible."""
|
||||
self._set_combo_items(self._calibration_combo, names, self.calibration_set())
|
||||
def set_available_sets(self, available_sets: dict[str, list[str]]) -> None:
|
||||
"""Replace combo-box choices for all preprocess assets."""
|
||||
for key in PREPROCESS_ASSET_KEYS:
|
||||
combo = self._set_combos[key]
|
||||
self._set_combo_items(combo, available_sets.get(key, []), combo.currentText().strip())
|
||||
|
||||
def set_reference_sets(self, names: list[str]) -> None:
|
||||
"""Replace reference set choices while preserving current selection when possible."""
|
||||
self._set_combo_items(self._reference_combo, names, self.reference_set())
|
||||
|
||||
def set_selected_sets(self, calibration_set: str, reference_set: str) -> None:
|
||||
"""Apply selected set names to both comboboxes and emit selection update."""
|
||||
if calibration_set:
|
||||
index = self._calibration_combo.findText(calibration_set)
|
||||
def set_selected_sets(self, selected_sets: dict[str, str]) -> None:
|
||||
"""Apply selected set names to all comboboxes and emit selection update."""
|
||||
for key in PREPROCESS_ASSET_KEYS:
|
||||
selected_value = selected_sets.get(key, "")
|
||||
if not selected_value:
|
||||
continue
|
||||
combo = self._set_combos[key]
|
||||
index = combo.findText(selected_value)
|
||||
if index >= 0:
|
||||
self._calibration_combo.setCurrentIndex(index)
|
||||
|
||||
if reference_set:
|
||||
index = self._reference_combo.findText(reference_set)
|
||||
if index >= 0:
|
||||
self._reference_combo.setCurrentIndex(index)
|
||||
|
||||
combo.setCurrentIndex(index)
|
||||
self._emit_selection_changed()
|
||||
|
||||
def set_status(self, message: str) -> None:
|
||||
"""Set short human-readable status line."""
|
||||
self._status_label.setText(message)
|
||||
|
||||
def draw_last_trace(self, trace: TraceData, title: str) -> None:
|
||||
"""Draw the latest captured sweep trace in dB scale."""
|
||||
magnitude_db = 20.0 * np.log10(np.maximum(np.abs(trace.s21), 1e-12))
|
||||
def draw_last_trace(self, trace: TraceData, title: str, *, channel: str) -> None:
|
||||
"""Draw the latest captured sweep trace for the requested channel in dB scale."""
|
||||
samples = trace.s11 if channel == "s11" else trace.s21
|
||||
magnitude_db = 20.0 * np.log10(np.maximum(np.abs(samples), 1e-12))
|
||||
self._preview_plot.clear()
|
||||
self._preview_plot.plot(
|
||||
trace.frequency_hz,
|
||||
@@ -261,8 +264,13 @@ class PreprocessDialog(QDialog):
|
||||
)
|
||||
|
||||
def _emit_selection_changed(self) -> None:
|
||||
"""Emit current calibration/reference selection."""
|
||||
self.selection_changed.emit(self.calibration_set(), self.reference_set())
|
||||
"""Emit current selection snapshot change."""
|
||||
self.selection_changed.emit()
|
||||
|
||||
@staticmethod
|
||||
def _asset_row_label(key: str) -> str:
|
||||
"""Return short selector label for one preprocess asset."""
|
||||
return preprocess_asset_display_name(key)
|
||||
|
||||
@staticmethod
|
||||
def _set_combo_items(combo: QComboBox, names: list[str], current_text: str) -> None:
|
||||
|
||||
Reference in New Issue
Block a user