added tmp reference capture
This commit is contained in:
@@ -14,9 +14,13 @@ from python_app.workflows.multi_radar_capture_workflow import (
|
|||||||
MultiRadarSequentialCaptureSession,
|
MultiRadarSequentialCaptureSession,
|
||||||
)
|
)
|
||||||
from python_app.workflows.radar_config_variants import scan_radar_config_variants
|
from python_app.workflows.radar_config_variants import scan_radar_config_variants
|
||||||
|
from python_app.workflows.reference_workflow import capture_reference_set
|
||||||
from python_app.workflows.sequential_capture_workflow import SequentialCaptureSession
|
from python_app.workflows.sequential_capture_workflow import SequentialCaptureSession
|
||||||
|
|
||||||
|
|
||||||
|
TMP_REFERENCE_SET_NAME = "tmp_reference"
|
||||||
|
|
||||||
|
|
||||||
class AppWindowPreprocessMixin:
|
class AppWindowPreprocessMixin:
|
||||||
"""Handles preprocess set management and sequential capture workflows."""
|
"""Handles preprocess set management and sequential capture workflows."""
|
||||||
|
|
||||||
@@ -103,6 +107,63 @@ class AppWindowPreprocessMixin:
|
|||||||
dialog.raise_()
|
dialog.raise_()
|
||||||
dialog.activateWindow()
|
dialog.activateWindow()
|
||||||
|
|
||||||
|
def _capture_tmp_reference(self) -> None:
|
||||||
|
"""Capture, save, and select a temporary S21 reference with current sweep settings."""
|
||||||
|
if self._capture_session is not None:
|
||||||
|
self._show_error(
|
||||||
|
"Cannot capture tmp reference during active capture sequence",
|
||||||
|
details=self._capture_state_details(),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
pipeline_was_running = self._supervisor.is_running()
|
||||||
|
pipeline_was_paused = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
if pipeline_was_running:
|
||||||
|
self._log("Pipeline paused for tmp reference capture")
|
||||||
|
self._stop_run()
|
||||||
|
pipeline_was_paused = True
|
||||||
|
|
||||||
|
config = self._build_config()
|
||||||
|
radar_key = self._radar_key(config)
|
||||||
|
self._log(
|
||||||
|
"Tmp S21 Reference capture started: "
|
||||||
|
f"set={TMP_REFERENCE_SET_NAME}, radar_key={radar_key}"
|
||||||
|
)
|
||||||
|
|
||||||
|
radar_key, collection = capture_reference_set(config, TMP_REFERENCE_SET_NAME, self._store)
|
||||||
|
self._selected_preprocess_sets["s21_reference"] = TMP_REFERENCE_SET_NAME
|
||||||
|
self._selected_preprocess_radar_key = radar_key
|
||||||
|
self._processor_run_signature = None
|
||||||
|
self._history_run_signature = None
|
||||||
|
if self._supervisor.is_processor_running():
|
||||||
|
self._stop_all_processes()
|
||||||
|
self._reset_runtime_history()
|
||||||
|
self._refresh_preprocess_summary_labels()
|
||||||
|
if collection.traces:
|
||||||
|
self._draw_single_trace(
|
||||||
|
collection.traces[-1],
|
||||||
|
title="Tmp S21 Reference last trace",
|
||||||
|
channel="s21",
|
||||||
|
)
|
||||||
|
if self._preprocess_dialog is not None:
|
||||||
|
self._refresh_sets()
|
||||||
|
self._preprocess_dialog.set_status(
|
||||||
|
f"S21 Reference set saved: {TMP_REFERENCE_SET_NAME} ({len(collection.traces)} traces)"
|
||||||
|
)
|
||||||
|
|
||||||
|
self._log(
|
||||||
|
"Tmp S21 Reference captured and selected: "
|
||||||
|
f"set={TMP_REFERENCE_SET_NAME}, key={radar_key}, traces={len(collection.traces)}; "
|
||||||
|
"runtime history reset"
|
||||||
|
)
|
||||||
|
except Exception as exc: # noqa: BLE001
|
||||||
|
self._show_exception("Failed to capture tmp reference", exc)
|
||||||
|
finally:
|
||||||
|
if pipeline_was_paused:
|
||||||
|
self._start_run()
|
||||||
|
|
||||||
def _ensure_preprocess_dialog(self) -> PreprocessDialog:
|
def _ensure_preprocess_dialog(self) -> PreprocessDialog:
|
||||||
"""Create preprocessing dialog lazily and wire its signals once."""
|
"""Create preprocessing dialog lazily and wire its signals once."""
|
||||||
if self._preprocess_dialog is not None:
|
if self._preprocess_dialog is not None:
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ def build_data_actions_group(owner) -> QGroupBox:
|
|||||||
remove_last_button = QPushButton("Remove Last Measurement")
|
remove_last_button = QPushButton("Remove Last Measurement")
|
||||||
remove_last_button.clicked.connect(owner._remove_last_runtime_history)
|
remove_last_button.clicked.connect(owner._remove_last_runtime_history)
|
||||||
remove_last_button.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
|
remove_last_button.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
|
||||||
|
capture_tmp_reference_button = QPushButton("Capture Tmp Reference")
|
||||||
|
capture_tmp_reference_button.clicked.connect(owner._capture_tmp_reference)
|
||||||
|
capture_tmp_reference_button.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
|
||||||
owner._save_count = QSpinBox()
|
owner._save_count = QSpinBox()
|
||||||
owner._save_count.setMinimum(1)
|
owner._save_count.setMinimum(1)
|
||||||
owner._save_count.setMaximum(10_000)
|
owner._save_count.setMaximum(10_000)
|
||||||
@@ -41,7 +44,8 @@ def build_data_actions_group(owner) -> QGroupBox:
|
|||||||
button_grid.setVerticalSpacing(8)
|
button_grid.setVerticalSpacing(8)
|
||||||
button_grid.addWidget(save_button, 0, 0)
|
button_grid.addWidget(save_button, 0, 0)
|
||||||
button_grid.addWidget(save_vna_json_button, 0, 1)
|
button_grid.addWidget(save_vna_json_button, 0, 1)
|
||||||
button_grid.addWidget(remove_last_button, 1, 0, 1, 2)
|
button_grid.addWidget(remove_last_button, 1, 0)
|
||||||
|
button_grid.addWidget(capture_tmp_reference_button, 1, 1)
|
||||||
button_grid.setColumnStretch(0, 1)
|
button_grid.setColumnStretch(0, 1)
|
||||||
button_grid.setColumnStretch(1, 1)
|
button_grid.setColumnStretch(1, 1)
|
||||||
layout.addLayout(button_grid)
|
layout.addLayout(button_grid)
|
||||||
|
|||||||
@@ -2,13 +2,10 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import time
|
from python_app.models.dataset_model import SweepCollection
|
||||||
|
|
||||||
from python_app.hardware_full.single_radar_service import create_single_radar_service
|
|
||||||
from python_app.hardware_full.switch_service import SwitchService
|
|
||||||
from python_app.models.dataset_model import ComboKey, SweepCollection, TraceData
|
|
||||||
from python_app.models.run_config_model import RunConfigModel
|
from python_app.models.run_config_model import RunConfigModel
|
||||||
from python_app.storage.npz_store import NpzStore, radar_key_from_config
|
from python_app.storage.npz_store import NpzStore
|
||||||
|
from python_app.workflows.sequential_capture_workflow import SequentialCaptureSession
|
||||||
|
|
||||||
|
|
||||||
def capture_calibration_set(
|
def capture_calibration_set(
|
||||||
@@ -24,66 +21,11 @@ def capture_calibration_set(
|
|||||||
"and captured explicitly."
|
"and captured explicitly."
|
||||||
)
|
)
|
||||||
|
|
||||||
combos = RunConfigModel.build_full_combos(config.input_switch.positions, config.output_switch.positions)
|
session = SequentialCaptureSession(config=config, kind="s21_calibration", set_name=set_name)
|
||||||
|
|
||||||
radar = create_single_radar_service(config)
|
|
||||||
input_switch = SwitchService(
|
|
||||||
name=config.input_switch.name,
|
|
||||||
positions=config.input_switch.positions,
|
|
||||||
mode=config.input_switch.driver_mode,
|
|
||||||
driver=config.input_switch.driver,
|
|
||||||
gpio_chip=config.input_switch.gpio_chip,
|
|
||||||
pin_a=config.input_switch.pin_a,
|
|
||||||
pin_b=config.input_switch.pin_b,
|
|
||||||
invert_logic=config.input_switch.invert_logic,
|
|
||||||
)
|
|
||||||
output_switch = SwitchService(
|
|
||||||
name=config.output_switch.name,
|
|
||||||
positions=config.output_switch.positions,
|
|
||||||
mode=config.output_switch.driver_mode,
|
|
||||||
driver=config.output_switch.driver,
|
|
||||||
gpio_chip=config.output_switch.gpio_chip,
|
|
||||||
pin_a=config.output_switch.pin_a,
|
|
||||||
pin_b=config.output_switch.pin_b,
|
|
||||||
invert_logic=config.output_switch.invert_logic,
|
|
||||||
)
|
|
||||||
|
|
||||||
traces: list[TraceData] = []
|
|
||||||
try:
|
try:
|
||||||
radar.open()
|
session.open()
|
||||||
radar.configure(config.radar.sweep)
|
while not session.is_complete():
|
||||||
input_switch.open()
|
session.capture_current_combo()
|
||||||
output_switch.open()
|
return session.finalize(store)
|
||||||
|
|
||||||
for combo in combos:
|
|
||||||
output_switch.switch_to(combo.output)
|
|
||||||
input_switch.switch_to(combo.input)
|
|
||||||
if config.runtime.settling_ms > 0:
|
|
||||||
time.sleep(config.runtime.settling_ms / 1000.0)
|
|
||||||
|
|
||||||
sweep = radar.acquire()
|
|
||||||
traces.append(
|
|
||||||
TraceData(
|
|
||||||
combo=ComboKey(input_pos=combo.input, output_pos=combo.output),
|
|
||||||
frequency_hz=sweep.x,
|
|
||||||
s11=sweep.trace("s11"),
|
|
||||||
s21=sweep.trace("s21"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
finally:
|
finally:
|
||||||
output_switch.close()
|
session.close()
|
||||||
input_switch.close()
|
|
||||||
radar.close()
|
|
||||||
|
|
||||||
collection = SweepCollection(collection_id=1, monotonic_ns=time.monotonic_ns(), traces=traces)
|
|
||||||
radar_key = radar_key_from_config(
|
|
||||||
model_name=config.radar.model,
|
|
||||||
serial=config.radar.serial,
|
|
||||||
sweep_start_hz=config.radar.sweep.start_hz,
|
|
||||||
sweep_stop_hz=config.radar.sweep.stop_hz,
|
|
||||||
sweep_points=config.radar.sweep.points,
|
|
||||||
ifbw_hz=config.radar.sweep.if_bandwidth_hz,
|
|
||||||
power_dbm=config.radar.sweep.power_dbm,
|
|
||||||
)
|
|
||||||
store.save_set("s21_calibration", radar_key, set_name, collection)
|
|
||||||
return radar_key, collection
|
|
||||||
|
|||||||
@@ -2,14 +2,10 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import time
|
from python_app.models.dataset_model import SweepCollection
|
||||||
|
|
||||||
from python_app.hardware_full.multi_device_service import MultiDeviceLibreVnaService
|
|
||||||
from python_app.hardware_full.single_radar_service import create_single_radar_service
|
|
||||||
from python_app.hardware_full.switch_service import SwitchService
|
|
||||||
from python_app.models.dataset_model import ComboKey, SweepCollection, TraceData
|
|
||||||
from python_app.models.run_config_model import RunConfigModel
|
from python_app.models.run_config_model import RunConfigModel
|
||||||
from python_app.storage.npz_store import NpzStore, radar_key_from_config
|
from python_app.storage.npz_store import NpzStore
|
||||||
|
from python_app.workflows.sequential_capture_workflow import SequentialCaptureSession
|
||||||
|
|
||||||
|
|
||||||
def capture_reference_set(
|
def capture_reference_set(
|
||||||
@@ -18,94 +14,11 @@ def capture_reference_set(
|
|||||||
store: NpzStore,
|
store: NpzStore,
|
||||||
) -> tuple[str, SweepCollection]:
|
) -> tuple[str, SweepCollection]:
|
||||||
"""Capture all switch combinations and persist them as reference set."""
|
"""Capture all switch combinations and persist them as reference set."""
|
||||||
if config.is_multi_device:
|
session = SequentialCaptureSession(config=config, kind="s21_reference", set_name=set_name)
|
||||||
radar = MultiDeviceLibreVnaService(
|
|
||||||
master_serial=config.radar.serial,
|
|
||||||
slave_serials=list(config.radar.multi_device.slave_serials),
|
|
||||||
force_external_reference=config.radar.multi_device.force_external_reference,
|
|
||||||
recovery_attempts=config.radar.multi_device.recovery_attempts,
|
|
||||||
backend_mode=config.radar.driver_mode,
|
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
radar.open()
|
session.open()
|
||||||
radar.configure(config.radar.sweep)
|
while not session.is_complete():
|
||||||
collection = radar.acquire_collection(collection_id=1)
|
session.capture_current_combo()
|
||||||
|
return session.finalize(store)
|
||||||
finally:
|
finally:
|
||||||
radar.close()
|
session.close()
|
||||||
|
|
||||||
radar_key = radar_key_from_config(
|
|
||||||
model_name=config.radar.model,
|
|
||||||
serial=config.radar.serial,
|
|
||||||
sweep_start_hz=config.radar.sweep.start_hz,
|
|
||||||
sweep_stop_hz=config.radar.sweep.stop_hz,
|
|
||||||
sweep_points=config.radar.sweep.points,
|
|
||||||
ifbw_hz=config.radar.sweep.if_bandwidth_hz,
|
|
||||||
power_dbm=config.radar.sweep.power_dbm,
|
|
||||||
extra_serials=config.radar.multi_device.slave_serials,
|
|
||||||
)
|
|
||||||
store.save_set("s21_reference", radar_key, set_name, collection)
|
|
||||||
return radar_key, collection
|
|
||||||
|
|
||||||
combos = RunConfigModel.build_full_combos(config.input_switch.positions, config.output_switch.positions)
|
|
||||||
|
|
||||||
radar = create_single_radar_service(config)
|
|
||||||
input_switch = SwitchService(
|
|
||||||
name=config.input_switch.name,
|
|
||||||
positions=config.input_switch.positions,
|
|
||||||
mode=config.input_switch.driver_mode,
|
|
||||||
driver=config.input_switch.driver,
|
|
||||||
gpio_chip=config.input_switch.gpio_chip,
|
|
||||||
pin_a=config.input_switch.pin_a,
|
|
||||||
pin_b=config.input_switch.pin_b,
|
|
||||||
invert_logic=config.input_switch.invert_logic,
|
|
||||||
)
|
|
||||||
output_switch = SwitchService(
|
|
||||||
name=config.output_switch.name,
|
|
||||||
positions=config.output_switch.positions,
|
|
||||||
mode=config.output_switch.driver_mode,
|
|
||||||
driver=config.output_switch.driver,
|
|
||||||
gpio_chip=config.output_switch.gpio_chip,
|
|
||||||
pin_a=config.output_switch.pin_a,
|
|
||||||
pin_b=config.output_switch.pin_b,
|
|
||||||
invert_logic=config.output_switch.invert_logic,
|
|
||||||
)
|
|
||||||
|
|
||||||
traces: list[TraceData] = []
|
|
||||||
try:
|
|
||||||
radar.open()
|
|
||||||
radar.configure(config.radar.sweep)
|
|
||||||
input_switch.open()
|
|
||||||
output_switch.open()
|
|
||||||
|
|
||||||
for combo in combos:
|
|
||||||
output_switch.switch_to(combo.output)
|
|
||||||
input_switch.switch_to(combo.input)
|
|
||||||
if config.runtime.settling_ms > 0:
|
|
||||||
time.sleep(config.runtime.settling_ms / 1000.0)
|
|
||||||
|
|
||||||
sweep = radar.acquire()
|
|
||||||
traces.append(
|
|
||||||
TraceData(
|
|
||||||
combo=ComboKey(input_pos=combo.input, output_pos=combo.output),
|
|
||||||
frequency_hz=sweep.x,
|
|
||||||
s11=sweep.trace("s11"),
|
|
||||||
s21=sweep.trace("s21"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
finally:
|
|
||||||
output_switch.close()
|
|
||||||
input_switch.close()
|
|
||||||
radar.close()
|
|
||||||
|
|
||||||
collection = SweepCollection(collection_id=1, monotonic_ns=time.monotonic_ns(), traces=traces)
|
|
||||||
radar_key = radar_key_from_config(
|
|
||||||
model_name=config.radar.model,
|
|
||||||
serial=config.radar.serial,
|
|
||||||
sweep_start_hz=config.radar.sweep.start_hz,
|
|
||||||
sweep_stop_hz=config.radar.sweep.stop_hz,
|
|
||||||
sweep_points=config.radar.sweep.points,
|
|
||||||
ifbw_hz=config.radar.sweep.if_bandwidth_hz,
|
|
||||||
power_dbm=config.radar.sweep.power_dbm,
|
|
||||||
)
|
|
||||||
store.save_set("s21_reference", radar_key, set_name, collection)
|
|
||||||
return radar_key, collection
|
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
смотри сейчас будем добавлять в проект поддержку еще одного девайса в качестве радара. Когда будешь читать код смотри если есть файлы длинее чем 1300 строк то надо бы будет их грамотно разбить. В целом пиши код как мастер профессионал лучший в мире и самый опытный разработчик, пиши красивейший код, максимально читаемый, грамотный и понятный. Очень внимательнно смотри чтобы не было фолбеков, если в коде уже сейчас видишь какие то фолбеки то скажи где они и что делают, скорее всего будем удалять их в дальнейшем. И когда писать сейчас будешь то не создавай лишнего кода типа фолбеков изза отсутвтивия зависимостей и так далее, лишний код это плохо. объем в идеале уменьшать надо проекта.
|
||||||
|
|
||||||
|
Давай постепенно будем добавлять поддержку нового типа радара в код, для начала - сбор данных свипов. По пути /home/europa/Documents/kamil_adc
|
||||||
Reference in New Issue
Block a user