UI updates

This commit is contained in:
Ayzen
2026-04-01 20:21:16 +03:00
parent 4abc95c372
commit 669205d8f8
43 changed files with 2055 additions and 973 deletions
@@ -12,12 +12,22 @@ from python_app.gui.runtime.history import record_result_history, remove_last_al
class AppWindowSnapshotMixin:
"""Saves runtime data snapshots and maintains ring-reader freshness."""
@staticmethod
def _snapshot_config_profile_path(snapshot_dir: Path) -> Path:
"""Return companion config-profile path inside a saved snapshot directory."""
return snapshot_dir / "config_profile.json"
@staticmethod
def _vna_json_config_profile_path(output_root: Path, output_stem: str) -> Path:
"""Return companion config-profile path for one VNA-history JSON export batch."""
return output_root / f"{output_stem}_config_profile.json"
def _save_snapshot(self) -> None:
"""Save runtime snapshot in numpy-directory format."""
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")
self._show_error("No runtime data is available for save", details=self._runtime_history_details())
return
try:
@@ -32,6 +42,19 @@ class AppWindowSnapshotMixin:
list(self._result_history),
last_n,
)
config_profile_path = self._snapshot_config_profile_path(snapshot_dir)
try:
self._write_gui_profile_to_path(config_profile_path, allow_overwrite=False)
except Exception as exc: # noqa: BLE001
self._show_error(
"Snapshot data was saved, but the adjacent config profile could not be written",
details=(
f"snapshot_dir={snapshot_dir}\n"
f"config_profile_path={config_profile_path}\n\n"
f"{self._exception_details(exc)}"
),
)
return
self._log(
f"Saved numpy snapshot: {snapshot_dir} "
f"(raw={summary.get('raw_count', 0)}, "
@@ -43,55 +66,77 @@ class AppWindowSnapshotMixin:
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})"
f"requested_last_n={last_n}, "
f"config_profile={config_profile_path})"
)
except Exception as exc: # noqa: BLE001
self._show_error(f"Failed to save snapshot: {exc}")
self._show_exception("Failed to save snapshot", exc)
def _save_vna_history_json(self) -> None:
"""Save runtime history as vna_system-compatible JSON file."""
"""Save one VNA-history JSON per available combo in runtime history."""
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")
self._show_error("No runtime data is available for save", details=self._runtime_history_details())
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())
channel = self._vna_json_channel.currentText()
channel = "s21"
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_paths, summary = self._store.save_runtime_vna_history_json_batch(
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,
channel=channel,
primary_stage="preprocessed",
)
output_stem = str(summary.get("output_stem", "")).strip()
if not output_stem:
raise RuntimeError("VNA history JSON export did not report output_stem for config companion save")
config_profile_path = self._vna_json_config_profile_path(output_root, output_stem)
try:
self._write_gui_profile_to_path(config_profile_path, allow_overwrite=False)
except Exception as exc: # noqa: BLE001
exported_preview = "\n".join(str(path) for path in output_paths[:8])
if len(output_paths) > 8:
exported_preview += "\n..."
self._show_error(
"VNA history JSON files were saved, but the adjacent config profile could not be written",
details=(
f"output_root={output_root}\n"
f"config_profile_path={config_profile_path}\n"
f"saved_json_files={len(output_paths)}\n"
f"{exported_preview}\n\n"
f"{self._exception_details(exc)}"
),
)
return
combos = summary.get("combos", [])
combo_preview = ", ".join(f"in{input_pos}/out{output_pos}" for input_pos, output_pos in combos[:6])
if len(combos) > 6:
combo_preview += ", ..."
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"Saved VNA history JSON batch: files={len(output_paths)} "
f"(combos={summary.get('combo_count', 0)}"
f"{', ' + combo_preview if combo_preview else ''}, "
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"channel={channel}, "
f"requested_last_n={last_n})"
f"requested_last_n={last_n}, "
f"config_profile={config_profile_path})"
)
except Exception as exc: # noqa: BLE001
self._show_error(f"Failed to save VNA history JSON: {exc}")
self._show_exception("Failed to save VNA history JSON", exc)
def _remove_last_runtime_history(self) -> None:
"""Remove the newest runtime measurement from all stages and processor replay state."""
@@ -104,7 +149,10 @@ class AppWindowSnapshotMixin:
def _apply_runtime_history_deletion(self, *, remove_last_only: bool) -> None:
"""Apply destructive runtime-history deletion across readers, caches, and processor replay state."""
if self._capture_session is not None:
self._show_error("Cannot modify runtime history during active capture sequence")
self._show_error(
"Cannot modify runtime history during active capture sequence",
details=f"{self._capture_state_details()}\n\n{self._runtime_history_details()}",
)
return
resume_acquisition = self._supervisor.is_running()
@@ -161,7 +209,7 @@ class AppWindowSnapshotMixin:
if resume_acquisition:
self._start_run()
except Exception as exc: # noqa: BLE001
self._show_error(f"Failed to {error_action}: {exc}")
self._show_exception(f"Failed to {error_action}", exc)
def _browse_save_path(self) -> None:
"""Open directory picker for snapshot output path."""
@@ -238,7 +286,7 @@ class AppWindowSnapshotMixin:
continue
break
except Exception as exc: # noqa: BLE001
self._log(f"Snapshot drain warning: {exc}")
self._log_exception("Snapshot drain warning", exc, level="WARN")
def _drop_pending_ring_payloads(self, *, include_results: bool = True) -> None:
"""Drop unread payloads from active readers."""