added json save button and remove history button. Added logging to save process
This commit is contained in:
@@ -185,6 +185,7 @@ class AppWindowConfigMixin:
|
||||
self._draw_results(self._result_history[-1])
|
||||
return
|
||||
self._plot.clear()
|
||||
self._clear_trace_plots()
|
||||
|
||||
def _on_radar_identity_changed(self, *_args) -> None:
|
||||
"""Refresh device limits when radar identity/mode changes."""
|
||||
|
||||
@@ -36,11 +36,105 @@ class AppWindowSnapshotMixin:
|
||||
f"(raw={summary.get('raw_count', 0)}, "
|
||||
f"preprocessed={summary.get('preprocessed_count', 0)}, "
|
||||
f"results={summary.get('result_count', 0)}, "
|
||||
f"mode={summary.get('selection_mode', 'unknown')})"
|
||||
f"mode={summary.get('selection_mode', 'unknown')}, "
|
||||
f"anchor={summary.get('anchor_stage', 'unknown')}, "
|
||||
f"aligned_keys={summary.get('aligned_key_count', 0)}, "
|
||||
f"raw_missing={summary.get('raw_missing_count', 0)}, "
|
||||
f"pre_missing={summary.get('preprocessed_missing_count', 0)}, "
|
||||
f"result_missing={summary.get('result_missing_count', 0)}, "
|
||||
f"requested_last_n={last_n})"
|
||||
)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
self._show_error(f"Failed to save snapshot: {exc}")
|
||||
|
||||
def _save_vna_history_json(self) -> None:
|
||||
"""Save runtime history as vna_system-compatible JSON file."""
|
||||
self._drain_runtime_rings_for_snapshot()
|
||||
|
||||
if not self._raw_history and not self._pre_history and not self._result_history:
|
||||
self._show_error("No runtime data is available for save")
|
||||
return
|
||||
|
||||
try:
|
||||
last_n = int(self._save_count.value())
|
||||
input_index = int(self._vna_json_input_index.value())
|
||||
output_index = int(self._vna_json_output_index.value())
|
||||
output_root = Path(self._save_path_input.text().strip()).expanduser()
|
||||
output_name = self._save_name_input.text().strip()
|
||||
output_path, summary = self._store.save_runtime_vna_history_json(
|
||||
output_root,
|
||||
output_name,
|
||||
list(self._raw_history),
|
||||
list(self._pre_history),
|
||||
list(self._result_history),
|
||||
last_n,
|
||||
input_index=input_index,
|
||||
output_index=output_index,
|
||||
primary_stage="preprocessed",
|
||||
)
|
||||
self._log(
|
||||
f"Saved VNA history JSON: {output_path} "
|
||||
f"(sweeps={summary.get('sweep_count', 0)}, "
|
||||
f"raw_records={summary.get('raw_record_count', 0)}, "
|
||||
f"preprocessed_records={summary.get('preprocessed_record_count', 0)}, "
|
||||
f"raw={summary.get('raw_count', 0)}, "
|
||||
f"preprocessed={summary.get('preprocessed_count', 0)}, "
|
||||
f"results={summary.get('result_count', 0)}, "
|
||||
f"mode={summary.get('selection_mode', 'unknown')}, "
|
||||
f"anchor={summary.get('anchor_stage', 'unknown')}, "
|
||||
f"input={input_index}, "
|
||||
f"output={output_index}, "
|
||||
f"requested_last_n={last_n})"
|
||||
)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
self._show_error(f"Failed to save VNA history JSON: {exc}")
|
||||
|
||||
def _clear_all_runtime_history(self) -> None:
|
||||
"""Clear all runtime histories, ring backlogs, and processor replay state."""
|
||||
if self._capture_session is not None:
|
||||
self._show_error("Cannot clear runtime history during active capture sequence")
|
||||
return
|
||||
|
||||
resume_acquisition = self._supervisor.is_running()
|
||||
dropped_raw = 0
|
||||
dropped_pre = 0
|
||||
dropped_results = 0
|
||||
|
||||
try:
|
||||
if resume_acquisition:
|
||||
self._stop_run()
|
||||
|
||||
dropped_raw = self._raw_reader.drop_all() if self._raw_reader is not None else 0
|
||||
dropped_pre = self._pre_reader.drop_all() if self._pre_reader is not None else 0
|
||||
dropped_results = self._result_reader.drop_all() if self._result_reader is not None else 0
|
||||
|
||||
self._replace_runtime_history(retained_raw=[], retained_pre=[], retained_result=[])
|
||||
self._bscan_history_floor_collection_id = 0
|
||||
self._clear_bscan_plot_history()
|
||||
|
||||
# Clear processor-side replay cache so newly rendered B-scan starts clean.
|
||||
self._write_live_processing_config(history_command="clear_all", bump_history_seq=True)
|
||||
|
||||
if self._supervisor.is_processor_running():
|
||||
self._drain_results_until_quiet(timeout_s=0.25, poll_s=0.01)
|
||||
if self._result_reader is not None:
|
||||
dropped_results += self._result_reader.drop_all()
|
||||
self._result_history.clear()
|
||||
|
||||
self._update_history_indicator()
|
||||
self._redraw_after_history_deletion()
|
||||
self._log(
|
||||
"Runtime history fully cleared: "
|
||||
f"dropped raw={dropped_raw}, "
|
||||
f"preprocessed={dropped_pre}, "
|
||||
f"results={dropped_results}"
|
||||
)
|
||||
|
||||
if resume_acquisition:
|
||||
self._start_run()
|
||||
except Exception as exc: # noqa: BLE001
|
||||
self._show_error(f"Failed to clear runtime history: {exc}")
|
||||
|
||||
def _browse_save_path(self) -> None:
|
||||
"""Open directory picker for snapshot output path."""
|
||||
selected = QFileDialog.getExistingDirectory(
|
||||
@@ -59,7 +153,7 @@ class AppWindowSnapshotMixin:
|
||||
start_raw_count = len(self._raw_history)
|
||||
start_pre_count = len(self._pre_history)
|
||||
start_result_count = len(self._result_history)
|
||||
deadline = time.monotonic() + 0.8
|
||||
deadline = time.monotonic() + 1.2
|
||||
|
||||
while True:
|
||||
progress = False
|
||||
@@ -91,13 +185,29 @@ class AppWindowSnapshotMixin:
|
||||
if progress:
|
||||
continue
|
||||
|
||||
missing_raw = self._raw_reader is not None and len(self._raw_history) == start_raw_count
|
||||
missing_pre = self._pre_reader is not None and len(self._pre_history) == start_pre_count
|
||||
got_results = len(self._result_history) > start_result_count
|
||||
raw_count = len(self._raw_history)
|
||||
pre_count = len(self._pre_history)
|
||||
result_count = len(self._result_history)
|
||||
|
||||
missing_raw = self._raw_reader is not None and raw_count == start_raw_count
|
||||
missing_pre = self._pre_reader is not None and pre_count == start_pre_count
|
||||
missing_results = self._result_reader is not None and result_count == start_result_count
|
||||
got_results = result_count > start_result_count
|
||||
got_raw_or_pre = raw_count > start_raw_count or pre_count > start_pre_count
|
||||
|
||||
if got_results and (missing_raw or missing_pre) and time.monotonic() < deadline:
|
||||
time.sleep(0.01)
|
||||
continue
|
||||
if got_raw_or_pre and missing_results and time.monotonic() < deadline:
|
||||
time.sleep(0.01)
|
||||
continue
|
||||
if (
|
||||
self._result_reader is not None
|
||||
and max(raw_count, pre_count) > result_count
|
||||
and time.monotonic() < deadline
|
||||
):
|
||||
time.sleep(0.01)
|
||||
continue
|
||||
break
|
||||
except Exception as exc: # noqa: BLE001
|
||||
self._log(f"Snapshot drain warning: {exc}")
|
||||
|
||||
@@ -16,17 +16,40 @@ def build_data_actions_group(owner) -> QGroupBox:
|
||||
|
||||
save_button = QPushButton("Save Numpy Snapshot")
|
||||
save_button.clicked.connect(owner._save_snapshot)
|
||||
save_vna_json_button = QPushButton("Save VNA History JSON")
|
||||
save_vna_json_button.clicked.connect(owner._save_vna_history_json)
|
||||
clear_history_button = QPushButton("Clear ALL Runtime History")
|
||||
clear_history_button.clicked.connect(owner._clear_all_runtime_history)
|
||||
owner._save_count = QSpinBox()
|
||||
owner._save_count.setMinimum(1)
|
||||
owner._save_count.setMaximum(10_000)
|
||||
owner._save_count.setValue(10)
|
||||
owner._vna_json_input_index = QSpinBox()
|
||||
owner._vna_json_input_index.setMinimum(0)
|
||||
owner._vna_json_input_index.setMaximum(65_535)
|
||||
owner._vna_json_input_index.setValue(0)
|
||||
owner._vna_json_output_index = QSpinBox()
|
||||
owner._vna_json_output_index.setMinimum(0)
|
||||
owner._vna_json_output_index.setMaximum(65_535)
|
||||
owner._vna_json_output_index.setValue(0)
|
||||
|
||||
save_row.addWidget(save_button)
|
||||
save_row.addWidget(save_vna_json_button)
|
||||
save_row.addWidget(clear_history_button)
|
||||
save_row.addWidget(QLabel("Last N"))
|
||||
save_row.addWidget(owner._save_count)
|
||||
save_row.addStretch(1)
|
||||
layout.addLayout(save_row)
|
||||
|
||||
json_row = QHBoxLayout()
|
||||
json_row.setSpacing(8)
|
||||
json_row.addWidget(QLabel("JSON input"))
|
||||
json_row.addWidget(owner._vna_json_input_index)
|
||||
json_row.addWidget(QLabel("output"))
|
||||
json_row.addWidget(owner._vna_json_output_index)
|
||||
json_row.addStretch(1)
|
||||
layout.addLayout(json_row)
|
||||
|
||||
path_row = QHBoxLayout()
|
||||
path_row.setSpacing(8)
|
||||
owner._save_path_input = QLineEdit(str(owner._project_root / "python_app/data/snapshots"))
|
||||
|
||||
@@ -73,7 +73,7 @@ def build_processing_group(owner) -> QGroupBox:
|
||||
|
||||
owner._bscan_max_depth_m = QDoubleSpinBox()
|
||||
owner._bscan_max_depth_m.setDecimals(1)
|
||||
owner._bscan_max_depth_m.setRange(0.1, 5.0)
|
||||
owner._bscan_max_depth_m.setRange(0.1, 20.0)
|
||||
owner._bscan_max_depth_m.setSingleStep(0.1)
|
||||
owner._bscan_max_depth_m.setValue(1.0)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user