new kamil adc

This commit is contained in:
Ayzen
2026-06-11 13:02:02 +03:00
parent 21f76d7cd2
commit 9661504e51
46 changed files with 12097 additions and 1063 deletions
@@ -7,6 +7,10 @@ import time
import numpy as np
from python_app.hardware_full.kamil_adc import (
KamilAdcProcessingParams,
KamilAdcSweepProcessor,
)
from python_app.models.dataset_model import ComboKey, SweepCollection, TraceData
from python_app.models.run_config_model import ComboModel, RunConfigModel
@@ -15,33 +19,30 @@ logger = logging.getLogger(__name__)
def build_kamil_adc_neutral_s21_sets(
config: RunConfigModel,
point_count: int,
) -> tuple[SweepCollection, SweepCollection]:
"""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.
the input S21 unchanged. The frequency axis is the exact acquisition grid
(``radar.kamil_adc.band``), so neutral sets line up sample-for-sample with
live sweeps. Returns the ``(calibration, reference)`` collections.
"""
if not config.is_kamil_adc:
raise ValueError("Neutral Kamil ADC sets require radar.model='kamil_adc'")
points = int(point_count)
if points <= 0:
raise ValueError("Kamil ADC neutral set point count must be > 0")
combos = list(config.combos)
if not combos:
combos = RunConfigModel.build_full_combos(config.input_switch.positions, config.output_switch.positions)
combos = RunConfigModel.build_full_combos(
config.input_switch.positions, config.output_switch.positions
)
if not combos:
raise ValueError("Kamil ADC neutral sets require at least one switch combo")
frequency_hz = np.linspace(
float(config.radar.sweep.start_hz),
float(config.radar.sweep.stop_hz),
points,
dtype=np.float32,
)
# Single source of truth for the axis: the same grid the processor emits.
processor = KamilAdcSweepProcessor(KamilAdcProcessingParams.from_kamil_model(config.radar.kamil_adc))
frequency_hz = processor.grid_hz
now_ns = time.monotonic_ns()
calibration = _neutral_collection(
combos=combos,
@@ -55,7 +56,9 @@ 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)
logger.info(
"Built neutral Kamil ADC S21 sets: combos=%d points=%d", len(combos), int(frequency_hz.size)
)
return calibration, reference
@@ -66,17 +69,16 @@ def _neutral_collection(
s21_value: np.complex64,
monotonic_ns: int,
) -> SweepCollection:
traces = []
for combo in combos:
point_count = int(frequency_hz.size)
traces.append(
TraceData(
combo=ComboKey(input=int(combo.input), output=int(combo.output)),
frequency_hz=frequency_hz.copy(),
s11=np.zeros(point_count, dtype=np.complex64),
s21=np.full(point_count, s21_value, dtype=np.complex64),
)
point_count = int(frequency_hz.size)
traces = [
TraceData(
combo=ComboKey(input=int(combo.input), output=int(combo.output)),
frequency_hz=frequency_hz.copy(),
s11=np.zeros(point_count, dtype=np.complex64),
s21=np.full(point_count, s21_value, dtype=np.complex64),
)
for combo in combos
]
return SweepCollection(
collection_id=1,
monotonic_ns=monotonic_ns,