Rework radar system
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
"""Manual dataset export and paused deletion of retained acquisitions."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
|
||||
from python_app.models.gui_profile_schema import ProfileWriter
|
||||
from python_app.gui.controllers.pipeline_controller import PipelineController
|
||||
from python_app.gui.controllers.sections.views import PrimaryView, DataView
|
||||
from python_app.models.run_config_schema import RunConfigModel
|
||||
from python_app.storage.npz.store import NpzStore
|
||||
|
||||
|
||||
class SnapshotController:
|
||||
"""Save stage histories and hold deletion ownership through final redraw."""
|
||||
|
||||
def __init__(
|
||||
self, pipeline: PipelineController, store: NpzStore, write_profile: ProfileWriter,
|
||||
*, destination: Callable[[RunConfigModel], tuple[Path, str, str]],
|
||||
build_config: Callable[[], RunConfigModel], processing_settings: dict[int, dict],
|
||||
allowed: Callable[[bool], bool], log: Callable[[str], None],
|
||||
error: Callable[[str, Exception], None],
|
||||
) -> None:
|
||||
self.pipeline, self.store = pipeline, store
|
||||
self._write_profile, self._log, self._error = write_profile, log, error
|
||||
self._destination, self._build_config = destination, build_config
|
||||
self._settings, self._allowed = processing_settings, allowed
|
||||
|
||||
def bind_actions(self, primary: PrimaryView, data: DataView) -> None:
|
||||
primary.clear.clicked.connect(lambda: self.delete_history(remove_last=False))
|
||||
data.remove_last.clicked.connect(lambda: self.delete_history(remove_last=True))
|
||||
data.save.clicked.connect(lambda: self.save())
|
||||
data.save_json.clicked.connect(lambda: self.save(json_export=True))
|
||||
data.record.clicked.connect(lambda: self.start_recording(data.record_count.value()))
|
||||
|
||||
def start_recording(self, count: int) -> None:
|
||||
if not self._allowed(False):
|
||||
return
|
||||
try:
|
||||
config = self.pipeline.active_config if self.pipeline.running else None
|
||||
self.pipeline.recording.start(
|
||||
*self._destination(config or self._build_config()), count,
|
||||
running=self.pipeline.running, start_acquisition=self.pipeline.start,
|
||||
)
|
||||
except Exception as exc:
|
||||
self._error("Failed to start disk recording", exc)
|
||||
|
||||
def save(self, *, json_export: bool = False) -> None:
|
||||
if not self._allowed(False):
|
||||
return
|
||||
action = "VNA history JSON" if json_export else "snapshot"
|
||||
try:
|
||||
active = self.pipeline.active_config
|
||||
root, name, prefix = self._destination(active or self._build_config())
|
||||
self.pipeline.drain_snapshot()
|
||||
if self.pipeline.closing or self.pipeline.active_config is not active:
|
||||
return
|
||||
raw = list(self.pipeline.history.raw)
|
||||
preprocessed = list(self.pipeline.history.preprocessed)
|
||||
results = list(self.pipeline.history.results)
|
||||
if not (raw or preprocessed or results):
|
||||
raise ValueError("No runtime data is available for save")
|
||||
if json_export:
|
||||
paths = self.store.save_runtime_vna_history_json_batch(
|
||||
root, name, raw, preprocessed, results,
|
||||
primary_stage="preprocessed", name_prefix=prefix,
|
||||
)
|
||||
directory = paths[0].parent
|
||||
profile_path = directory / "vna_config_profile.json"
|
||||
else:
|
||||
directory = self.store.save_runtime_snapshot_numpy(
|
||||
root, name, raw, preprocessed, results,
|
||||
name_prefix=prefix, processing_settings=self._settings,
|
||||
)
|
||||
profile_path = directory / "config_profile.json"
|
||||
try:
|
||||
self._write_profile(profile_path, allow_overwrite=json_export, dataset=True)
|
||||
except Exception as exc:
|
||||
self._error(
|
||||
f"{action} data was saved in {directory}, but the adjacent config profile "
|
||||
f"could not be written: {profile_path}", exc,
|
||||
)
|
||||
return
|
||||
self._log(
|
||||
f"Saved {action}: {directory} "
|
||||
f"(raw={len(raw)}, preprocessed={len(preprocessed)}, results={len(results)})"
|
||||
)
|
||||
except Exception as exc:
|
||||
self._error(f"Failed to save {action}", exc)
|
||||
|
||||
def delete_history(self, *, remove_last: bool) -> None:
|
||||
if not self._allowed(True):
|
||||
return
|
||||
action = "remove last runtime measurement" if remove_last else "clear runtime history"
|
||||
try:
|
||||
with self.pipeline.pause() as operation:
|
||||
if not operation.valid:
|
||||
return
|
||||
self.pipeline.discard_replay()
|
||||
dropped_raw, dropped_pre, dropped_results = self.pipeline.drop_pending()
|
||||
self.pipeline.history.delete(remove_last=remove_last)
|
||||
try:
|
||||
self.pipeline.publish_live()
|
||||
finally:
|
||||
self.pipeline.plots.clear()
|
||||
self.pipeline.settle_deleted_results()
|
||||
if not operation.valid:
|
||||
return
|
||||
self.pipeline.history_changed()
|
||||
self.pipeline.plots.redraw()
|
||||
self._log(
|
||||
f"{action}: dropped raw={dropped_raw}, "
|
||||
f"preprocessed={dropped_pre}, results={dropped_results}"
|
||||
)
|
||||
except InterruptedError:
|
||||
self.pipeline.operation_cancelled()
|
||||
except Exception as exc:
|
||||
self._error(f"Failed to {action}", exc)
|
||||
Reference in New Issue
Block a user