82 lines
2.6 KiB
Python
82 lines
2.6 KiB
Python
"""Frequency-axis calibration helpers."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Mapping
|
|
|
|
import numpy as np
|
|
|
|
from rfg_adc_plotter.constants import SWEEP_FREQ_MAX_GHZ, SWEEP_FREQ_MIN_GHZ
|
|
from rfg_adc_plotter.types import SweepData
|
|
|
|
|
|
def recalculate_calibration_c(
|
|
base_coeffs: np.ndarray,
|
|
f_min: float = SWEEP_FREQ_MIN_GHZ,
|
|
f_max: float = SWEEP_FREQ_MAX_GHZ,
|
|
) -> np.ndarray:
|
|
"""Recalculate coefficients while preserving sweep edges."""
|
|
coeffs = np.asarray(base_coeffs, dtype=np.float64).reshape(-1)
|
|
if coeffs.size < 3:
|
|
out = np.zeros((3,), dtype=np.float64)
|
|
out[: coeffs.size] = coeffs
|
|
coeffs = out
|
|
c0, c1, c2 = float(coeffs[0]), float(coeffs[1]), float(coeffs[2])
|
|
x0 = float(f_min)
|
|
x1 = float(f_max)
|
|
y0 = c0 + c1 * x0 + c2 * (x0 ** 2)
|
|
y1 = c0 + c1 * x1 + c2 * (x1 ** 2)
|
|
if not (np.isfinite(y0) and np.isfinite(y1)) or y1 == y0:
|
|
return np.asarray([c0, c1, c2], dtype=np.float64)
|
|
scale = (x1 - x0) / (y1 - y0)
|
|
shift = x0 - scale * y0
|
|
return np.asarray(
|
|
[
|
|
shift + scale * c0,
|
|
scale * c1,
|
|
scale * c2,
|
|
],
|
|
dtype=np.float64,
|
|
)
|
|
|
|
|
|
CALIBRATION_C_BASE = np.asarray([0.0, 1.0, 0.025], dtype=np.float64)
|
|
CALIBRATION_C = recalculate_calibration_c(CALIBRATION_C_BASE)
|
|
|
|
|
|
def get_calibration_base() -> np.ndarray:
|
|
return np.asarray(CALIBRATION_C_BASE, dtype=np.float64).copy()
|
|
|
|
|
|
def get_calibration_coeffs() -> np.ndarray:
|
|
return np.asarray(CALIBRATION_C, dtype=np.float64).copy()
|
|
|
|
|
|
def set_calibration_base_value(index: int, value: float) -> np.ndarray:
|
|
"""Update one base coefficient and recalculate the working coefficients."""
|
|
global CALIBRATION_C
|
|
CALIBRATION_C_BASE[int(index)] = float(value)
|
|
CALIBRATION_C = recalculate_calibration_c(CALIBRATION_C_BASE)
|
|
return get_calibration_coeffs()
|
|
|
|
|
|
def calibrate_freqs(sweep: Mapping[str, Any]) -> SweepData:
|
|
"""Return a sweep copy with calibrated and resampled frequency axis."""
|
|
freqs = np.asarray(sweep["F"], dtype=np.float64).copy()
|
|
values = np.asarray(sweep["I"], dtype=np.float64).copy()
|
|
coeffs = np.asarray(CALIBRATION_C, dtype=np.float64)
|
|
if freqs.size > 0:
|
|
freqs = coeffs[0] + coeffs[1] * freqs + coeffs[2] * (freqs * freqs)
|
|
|
|
if freqs.size >= 2:
|
|
freqs_cal = np.linspace(float(freqs[0]), float(freqs[-1]), freqs.size, dtype=np.float64)
|
|
values_cal = np.interp(freqs_cal, freqs, values).astype(np.float64)
|
|
else:
|
|
freqs_cal = freqs.copy()
|
|
values_cal = values.copy()
|
|
|
|
return {
|
|
"F": freqs_cal,
|
|
"I": values_cal,
|
|
}
|