some fixes again
This commit is contained in:
@@ -140,8 +140,17 @@ class AppWindow(
|
||||
try:
|
||||
value = int(raw)
|
||||
except ValueError:
|
||||
return 50
|
||||
return value if value >= 1 else 50
|
||||
value = 0
|
||||
if value >= 1:
|
||||
return value
|
||||
# A non-empty but invalid value is an operator mistake — say so instead of
|
||||
# silently swallowing it (stderr is captured by journald in headless mode).
|
||||
print(
|
||||
f"[radar] Ignoring invalid RADAR_SYSTEM_METRICS_REPORT_EVERY={raw!r}; using default 50.",
|
||||
file=sys.stderr,
|
||||
flush=True,
|
||||
)
|
||||
return 50
|
||||
|
||||
def _init_config_profile_state(self) -> None:
|
||||
"""Resolve startup profile path, load active profile, and queue fallback notices."""
|
||||
|
||||
@@ -453,6 +453,7 @@ class AppWindowConfigStateBuildersMixin:
|
||||
config.gpr,
|
||||
input_switch_positions=config.input_switch.positions,
|
||||
output_switch_positions=config.output_switch.positions,
|
||||
sweep=config.radar.sweep,
|
||||
)
|
||||
return config
|
||||
|
||||
|
||||
@@ -72,17 +72,11 @@ class AppWindowControlButtonMixin:
|
||||
Delivered as a queued signal from the watcher thread, so this executes
|
||||
on the GUI thread exactly like a click on "Capture Tmp Reference".
|
||||
"""
|
||||
# Ignore a re-entrant press: the capture flow spins the event loop (stop/
|
||||
# start run, dialogs), so a second queued press must not start a nested capture.
|
||||
if self._control_button_busy:
|
||||
self._log("GPIO control button press ignored: capture already in progress.")
|
||||
return
|
||||
self._control_button_busy = True
|
||||
try:
|
||||
self._log("GPIO control button pressed: capturing tmp reference.")
|
||||
self._capture_tmp_reference()
|
||||
finally:
|
||||
self._control_button_busy = False
|
||||
# The shared re-entrancy guard lives in _capture_tmp_reference, so this GPIO
|
||||
# trigger and the GUI "Capture Tmp Reference" button are protected by one
|
||||
# mechanism (a press during an in-progress capture is ignored there).
|
||||
self._log("GPIO control button pressed: capturing tmp reference.")
|
||||
self._capture_tmp_reference()
|
||||
|
||||
def _on_control_button_failed(self, message: str) -> None:
|
||||
"""Log an unrecoverable watcher error reported from the background thread."""
|
||||
|
||||
@@ -469,8 +469,8 @@ class AppWindowPipelineMixin:
|
||||
if collection is None:
|
||||
break
|
||||
self._pipeline_metrics.record("processing", int(collection.processing_duration_ns))
|
||||
if record_result_history(self._result_history, collection):
|
||||
latest = collection
|
||||
record_result_history(self._result_history, collection)
|
||||
latest = collection
|
||||
return latest
|
||||
|
||||
def _pump_events_during_drain(self, pause_s: float) -> None:
|
||||
|
||||
@@ -43,7 +43,9 @@ class AppWindowTracePlotMixin:
|
||||
details=f"{exc}\nExpected format: input:output,input:output",
|
||||
once_key=f"pass_through_combo_filter_invalid_{text}",
|
||||
)
|
||||
return set()
|
||||
# Fail open: an unparseable filter is ignored (all traces stay visible),
|
||||
# not turned into an empty allow-set that silently hides every trace.
|
||||
return None
|
||||
|
||||
def _configure_pass_through_magnitude_axis(self, plot: pg.PlotWidget) -> None:
|
||||
"""Apply pass-through magnitude-axis autorange or fixed Y window."""
|
||||
|
||||
@@ -117,6 +117,13 @@ class AppWindowPreprocessMixin:
|
||||
details=self._capture_state_details(),
|
||||
)
|
||||
return
|
||||
# One shared re-entrancy guard for BOTH the GUI button and the GPIO trigger:
|
||||
# this capture spins the Qt event loop (stop/start run, dialogs), so a second
|
||||
# request from either source must not start a nested capture.
|
||||
if self._control_button_busy:
|
||||
self._log("Tmp reference capture already in progress; ignoring duplicate request.")
|
||||
return
|
||||
self._control_button_busy = True
|
||||
|
||||
pipeline_was_running = self._supervisor.is_running()
|
||||
pipeline_was_paused = False
|
||||
@@ -178,6 +185,7 @@ class AppWindowPreprocessMixin:
|
||||
finally:
|
||||
if pipeline_was_paused:
|
||||
self._start_run()
|
||||
self._control_button_busy = False
|
||||
|
||||
def _ensure_preprocess_dialog(self) -> PreprocessDialog:
|
||||
"""Create preprocessing dialog lazily and wire its signals once."""
|
||||
|
||||
@@ -160,7 +160,7 @@ class AppWindowUiMixin:
|
||||
|
||||
self._status_label = QLabel("Status: idle", self._settings_panel)
|
||||
self._status_label.setObjectName("statusLabel")
|
||||
self._status_label.hide()
|
||||
right_layout.addWidget(self._status_label)
|
||||
|
||||
self._history_label = QLabel("History: raw=0, preprocessed=0, results=0", self._settings_panel)
|
||||
self._history_label.setObjectName("hintLabel")
|
||||
|
||||
@@ -25,7 +25,10 @@ def build_data_actions_group(owner) -> QGroupBox:
|
||||
save_button = QPushButton("Save Dataset")
|
||||
save_button.clicked.connect(owner._save_snapshot)
|
||||
save_button.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
|
||||
save_vna_json_button = QPushButton("Save JSON")
|
||||
save_vna_json_button = QPushButton("Save S21 JSON")
|
||||
save_vna_json_button.setToolTip(
|
||||
"Export one S21 VNA-history JSON per combo from the preprocessed stage (S11 is not included)."
|
||||
)
|
||||
save_vna_json_button.clicked.connect(owner._save_vna_history_json)
|
||||
save_vna_json_button.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
|
||||
remove_last_button = QPushButton("Remove Last Measurement")
|
||||
|
||||
@@ -15,8 +15,8 @@ THistoryCollection = TypeVar("THistoryCollection", SweepCollection, ResultCollec
|
||||
def record_result_history(
|
||||
result_history: deque[ResultCollection],
|
||||
collection: ResultCollection,
|
||||
) -> bool:
|
||||
"""Append new result or replace existing entry by stable collection key."""
|
||||
) -> None:
|
||||
"""Append a new result, or replace the existing entry with the same stable key."""
|
||||
for index in range(len(result_history) - 1, -1, -1):
|
||||
existing = result_history[index]
|
||||
if (
|
||||
@@ -24,10 +24,9 @@ def record_result_history(
|
||||
and existing.monotonic_ns == collection.monotonic_ns
|
||||
):
|
||||
result_history[index] = collection
|
||||
return True
|
||||
return
|
||||
|
||||
result_history.append(collection)
|
||||
return True
|
||||
|
||||
|
||||
def remove_last_aligned_histories(
|
||||
|
||||
Reference in New Issue
Block a user