improved logging
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from python_app.models.dataset_model import SweepCollection
|
||||
from python_app.models.run_config_model import RunConfigModel
|
||||
from python_app.storage.npz_store import NpzStore
|
||||
@@ -10,6 +12,8 @@ from python_app.workflows.sequential_capture_workflow import (
|
||||
SequentialCaptureSession,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def capture_calibration_set(
|
||||
config: RunConfigModel,
|
||||
@@ -19,6 +23,7 @@ def capture_calibration_set(
|
||||
median_sweep_count: int = DEFAULT_CALIBRATION_MEDIAN_SWEEP_COUNT,
|
||||
) -> tuple[str, SweepCollection]:
|
||||
"""Capture all switch combinations and persist them as calibration set."""
|
||||
logger.info("Starting one-shot calibration capture: set=%s", set_name)
|
||||
if config.is_matrix_radar:
|
||||
raise RuntimeError(
|
||||
"Matrix-radar S21 through calibration is not supported by this one-shot full-set helper. "
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
@@ -9,12 +10,19 @@ import numpy as np
|
||||
from python_app.models.dataset_model import ComboKey, SweepCollection, TraceData
|
||||
from python_app.models.run_config_model import ComboModel, RunConfigModel
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def build_kamil_adc_neutral_s21_sets(
|
||||
config: RunConfigModel,
|
||||
point_count: int,
|
||||
) -> tuple[SweepCollection, SweepCollection]:
|
||||
"""Build S21 calibration/reference collections that leave input S21 unchanged."""
|
||||
"""Build neutral S21 calibration/reference collections for the Kamil ADC radar.
|
||||
|
||||
The calibration uses unit S21 (1+0j) and the reference uses zero S21 across
|
||||
every configured combo, so applying them in the preprocessing pipeline leaves
|
||||
the input S21 unchanged. Returns the ``(calibration, reference)`` collections.
|
||||
"""
|
||||
if not config.is_kamil_adc:
|
||||
raise ValueError("Neutral Kamil ADC sets require radar.model='kamil_adc'")
|
||||
|
||||
@@ -47,6 +55,7 @@ def build_kamil_adc_neutral_s21_sets(
|
||||
s21_value=np.complex64(0.0 + 0.0j),
|
||||
monotonic_ns=now_ns,
|
||||
)
|
||||
logger.info("Built neutral Kamil ADC S21 sets: combos=%d points=%d", len(combos), points)
|
||||
return calibration, reference
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ from __future__ import annotations
|
||||
|
||||
from contextlib import suppress
|
||||
from dataclasses import dataclass
|
||||
import logging
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
@@ -23,6 +24,8 @@ from python_app.workflows.sequential_capture_workflow import (
|
||||
select_trace_for_combo,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class MultiRadarCaptureBatch:
|
||||
@@ -97,6 +100,15 @@ class MultiRadarSequentialCaptureSession:
|
||||
self._next_index = 0
|
||||
self._opened = False
|
||||
|
||||
logger.info(
|
||||
"Multi-radar capture session created: kind=%s set=%s combos=%d variants=%d matrix_radar=%s",
|
||||
self._kind,
|
||||
self._set_name,
|
||||
len(self._combos),
|
||||
len(self._radar_variants),
|
||||
self._is_matrix_radar,
|
||||
)
|
||||
|
||||
if self._is_matrix_radar:
|
||||
self._radar: MatrixRadarService = create_matrix_radar_service(base_config)
|
||||
self._input_switch = None
|
||||
@@ -148,12 +160,17 @@ class MultiRadarSequentialCaptureSession:
|
||||
self._input_switch.open()
|
||||
if self._output_switch is not None:
|
||||
self._output_switch.open()
|
||||
logger.info("Multi-radar capture session opened (kind=%s set=%s)", self._kind, self._set_name)
|
||||
except Exception:
|
||||
logger.exception(
|
||||
"Failed to open multi-radar capture session (kind=%s set=%s)", self._kind, self._set_name
|
||||
)
|
||||
self.close()
|
||||
raise
|
||||
|
||||
def close(self) -> None:
|
||||
"""Close all opened hardware resources."""
|
||||
was_open = self._opened
|
||||
with suppress(Exception):
|
||||
if self._output_switch is not None:
|
||||
self._output_switch.close()
|
||||
@@ -163,6 +180,8 @@ class MultiRadarSequentialCaptureSession:
|
||||
with suppress(Exception):
|
||||
self._radar.close()
|
||||
self._opened = False
|
||||
if was_open:
|
||||
logger.info("Multi-radar capture session closed (kind=%s set=%s)", self._kind, self._set_name)
|
||||
|
||||
def state(self) -> SequentialCaptureState:
|
||||
"""Return current progress snapshot."""
|
||||
@@ -258,6 +277,14 @@ class MultiRadarSequentialCaptureSession:
|
||||
self._next_index = len(self._combos)
|
||||
else:
|
||||
self._next_index += 1
|
||||
logger.debug(
|
||||
"Captured combo input=%d output=%d across %d variant(s) (%d/%d)",
|
||||
combo.input,
|
||||
combo.output,
|
||||
len(variant_labels),
|
||||
self._next_index,
|
||||
len(self._combos),
|
||||
)
|
||||
return batch
|
||||
|
||||
def undo_last_capture(self) -> MultiRadarCaptureBatch:
|
||||
@@ -336,6 +363,12 @@ class MultiRadarSequentialCaptureSession:
|
||||
trace_count=len(traces),
|
||||
)
|
||||
)
|
||||
logger.info(
|
||||
"Finalized multi-radar capture kind=%s set=%s into %d variant set(s)",
|
||||
self._kind,
|
||||
self._set_name,
|
||||
len(saved_sets),
|
||||
)
|
||||
return saved_sets
|
||||
|
||||
def _current_combo(self) -> ComboModel | None:
|
||||
|
||||
@@ -4,11 +4,14 @@ from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
import json
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from python_app.models.run_config_model import RunConfigModel
|
||||
from python_app.storage.npz_store import radar_key_from_config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_RADAR_SWEEP_KEYS = (
|
||||
"start_hz",
|
||||
"stop_hz",
|
||||
@@ -59,6 +62,7 @@ def scan_radar_config_variants(
|
||||
|
||||
directory = Path(normalized_path).expanduser()
|
||||
if not directory.exists():
|
||||
logger.warning("Radar config variant directory does not exist: %s", directory)
|
||||
return [], RadarConfigScanSummary(
|
||||
directory_path=str(directory),
|
||||
json_file_count=0,
|
||||
@@ -68,6 +72,7 @@ def scan_radar_config_variants(
|
||||
issues=(f"Directory does not exist: {directory}",),
|
||||
)
|
||||
if not directory.is_dir():
|
||||
logger.warning("Radar config variant path is not a directory: %s", directory)
|
||||
return [], RadarConfigScanSummary(
|
||||
directory_path=str(directory),
|
||||
json_file_count=0,
|
||||
@@ -88,16 +93,30 @@ def scan_radar_config_variants(
|
||||
variant = _load_radar_config_variant(path, base_config=base_config)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
issues.append(f"{path.name}: {type(exc).__name__}: {exc}")
|
||||
logger.warning("Skipping radar config variant %s: %s: %s", path.name, type(exc).__name__, exc)
|
||||
continue
|
||||
if variant.radar_key in seen_radar_keys:
|
||||
duplicate_variant_count += 1
|
||||
issues.append(
|
||||
f"{path.name}: duplicate radar variant key {variant.radar_key}; keeping the first matching file only"
|
||||
)
|
||||
logger.warning(
|
||||
"Skipping duplicate radar config variant %s (radar_key=%s already seen)",
|
||||
path.name,
|
||||
variant.radar_key,
|
||||
)
|
||||
continue
|
||||
seen_radar_keys.add(variant.radar_key)
|
||||
variants.append(variant)
|
||||
|
||||
logger.info(
|
||||
"Scanned radar config variants in %s: json=%d valid=%d duplicates=%d",
|
||||
directory,
|
||||
len(json_paths),
|
||||
len(variants),
|
||||
duplicate_variant_count,
|
||||
)
|
||||
|
||||
return variants, RadarConfigScanSummary(
|
||||
directory_path=str(directory),
|
||||
json_file_count=len(json_paths),
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from python_app.models.dataset_model import SweepCollection
|
||||
from python_app.models.run_config_model import RunConfigModel
|
||||
from python_app.storage.npz_store import NpzStore
|
||||
@@ -10,6 +12,8 @@ from python_app.workflows.sequential_capture_workflow import (
|
||||
SequentialCaptureSession,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def capture_reference_set(
|
||||
config: RunConfigModel,
|
||||
@@ -19,6 +23,7 @@ def capture_reference_set(
|
||||
median_sweep_count: int = DEFAULT_CALIBRATION_MEDIAN_SWEEP_COUNT,
|
||||
) -> tuple[str, SweepCollection]:
|
||||
"""Capture all switch combinations and persist them as reference set."""
|
||||
logger.info("Starting one-shot reference capture: set=%s", set_name)
|
||||
session = SequentialCaptureSession(
|
||||
config=config,
|
||||
kind="s21_reference",
|
||||
|
||||
@@ -4,6 +4,7 @@ from __future__ import annotations
|
||||
|
||||
from contextlib import suppress
|
||||
from dataclasses import dataclass
|
||||
import logging
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
@@ -15,13 +16,15 @@ from python_app.models.dataset_model import ComboKey, SweepCollection, TraceData
|
||||
from python_app.models.run_config_model import ComboModel, RunConfigModel
|
||||
from python_app.storage.npz_store import NpzStore, radar_key_from_config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
MATRIX_RADAR_MANUAL_CAPTURE_KINDS = frozenset({"s21_calibration", "s11_open", "s11_short", "s11_load"})
|
||||
DEFAULT_CALIBRATION_MEDIAN_SWEEP_COUNT = 5
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class SequentialCaptureState:
|
||||
"""Immutable view of sequential capture progress."""
|
||||
"""Snapshot of sequential capture progress for the GUI/controller."""
|
||||
|
||||
kind: str
|
||||
set_name: str
|
||||
@@ -73,6 +76,15 @@ class SequentialCaptureSession:
|
||||
self._next_index = 0
|
||||
self._opened = False
|
||||
|
||||
logger.info(
|
||||
"Sequential capture session created: kind=%s set=%s combos=%d matrix_radar=%s median_sweeps=%d",
|
||||
self._kind,
|
||||
self._set_name,
|
||||
len(self._combos),
|
||||
self._is_matrix_radar,
|
||||
self._median_sweep_count,
|
||||
)
|
||||
|
||||
if self._is_matrix_radar:
|
||||
self._radar: MatrixRadarService = create_matrix_radar_service(config)
|
||||
self._input_switch = None
|
||||
@@ -124,12 +136,15 @@ class SequentialCaptureSession:
|
||||
self._input_switch.open()
|
||||
if self._output_switch is not None:
|
||||
self._output_switch.open()
|
||||
logger.info("Sequential capture session opened (kind=%s set=%s)", self._kind, self._set_name)
|
||||
except Exception:
|
||||
logger.exception("Failed to open sequential capture session (kind=%s set=%s)", self._kind, self._set_name)
|
||||
self.close()
|
||||
raise
|
||||
|
||||
def close(self) -> None:
|
||||
"""Close all opened hardware resources."""
|
||||
was_open = self._opened
|
||||
with suppress(Exception):
|
||||
if self._output_switch is not None:
|
||||
self._output_switch.close()
|
||||
@@ -139,6 +154,8 @@ class SequentialCaptureSession:
|
||||
with suppress(Exception):
|
||||
self._radar.close()
|
||||
self._opened = False
|
||||
if was_open:
|
||||
logger.info("Sequential capture session closed (kind=%s set=%s)", self._kind, self._set_name)
|
||||
|
||||
def state(self) -> SequentialCaptureState:
|
||||
"""Return current progress snapshot."""
|
||||
@@ -174,11 +191,13 @@ class SequentialCaptureSession:
|
||||
trace = combine_traces_via_median(per_sweep_traces)
|
||||
self._traces.append(trace)
|
||||
self._next_index += 1
|
||||
logger.debug("Captured matrix combo input=%d output=%d", combo.input, combo.output)
|
||||
return trace
|
||||
|
||||
combined_collection = combine_collections_via_median(collections)
|
||||
self._traces.extend(combined_collection.traces)
|
||||
self._next_index = len(self._combos)
|
||||
logger.info("Captured full matrix combo set (%d traces)", len(combined_collection.traces))
|
||||
return combined_collection.traces[-1]
|
||||
|
||||
if self._input_switch is None or self._output_switch is None:
|
||||
@@ -202,6 +221,13 @@ class SequentialCaptureSession:
|
||||
trace = combine_traces_via_median(sweep_traces)
|
||||
self._traces.append(trace)
|
||||
self._next_index += 1
|
||||
logger.debug(
|
||||
"Captured combo input=%d output=%d (%d/%d)",
|
||||
combo.input,
|
||||
combo.output,
|
||||
self._next_index,
|
||||
len(self._combos),
|
||||
)
|
||||
return trace
|
||||
|
||||
def undo_last_capture(self) -> TraceData:
|
||||
@@ -217,6 +243,7 @@ class SequentialCaptureSession:
|
||||
removed_trace = self._traces[-1]
|
||||
self._traces.clear()
|
||||
self._next_index = 0
|
||||
logger.info("Undid matrix combo set capture (kind=%s set=%s)", self._kind, self._set_name)
|
||||
return removed_trace
|
||||
|
||||
expected_combo = self._combos[self._next_index - 1]
|
||||
@@ -228,6 +255,13 @@ class SequentialCaptureSession:
|
||||
raise RuntimeError("Capture session state is inconsistent; last trace does not match rewind combo")
|
||||
self._next_index -= 1
|
||||
self._traces.pop()
|
||||
logger.debug(
|
||||
"Undid combo capture input=%d output=%d (%d/%d remaining)",
|
||||
expected_combo.input,
|
||||
expected_combo.output,
|
||||
self._next_index,
|
||||
len(self._combos),
|
||||
)
|
||||
return removed_trace
|
||||
|
||||
def last_captured_trace(self) -> TraceData | None:
|
||||
@@ -265,6 +299,13 @@ class SequentialCaptureSession:
|
||||
extra_serials=self._config.radar_key_extra_parts() or None,
|
||||
)
|
||||
store.save_set(self._kind, radar_key, self._set_name, collection)
|
||||
logger.info(
|
||||
"Finalized capture set kind=%s set=%s radar_key=%s traces=%d",
|
||||
self._kind,
|
||||
self._set_name,
|
||||
radar_key,
|
||||
len(collection.traces),
|
||||
)
|
||||
return radar_key, collection
|
||||
|
||||
def _current_combo(self) -> ComboModel | None:
|
||||
|
||||
Reference in New Issue
Block a user