Source code for edges_analysis.calibration.s11
"""Corrections for S11 measurements."""
from __future__ import annotations
import attr
import numpy as np
from astropy import units as u
from edges_cal import modelling as mdl
from edges_cal import types as tp
from edges_cal.s11 import (
InternalSwitch,
LoadPlusSwitchS11,
LoadS11,
StandardsReadings,
VNAReading,
)
from edges_cal.tools import FrequencyRange
from hickleable import hickleable
from typing import Sequence
[docs]
@hickleable()
@attr.s
class AntennaS11(LoadS11):
_complex_model_type_default = mdl.ComplexRealImagModel
_default_nterms = 10
_model_type_default = mdl.Polynomial
model_delay: tp.Time = attr.ib(170 * u.ns)
[docs]
@classmethod
def from_s1p_files(
cls,
files: Sequence[tp.PathLike],
internal_switch: InternalSwitch,
f_low: float = 0 * u.MHz,
f_high: float = np.inf * u.MHz,
**kwargs,
) -> AntennaS11:
"""Generate from a list of four S1P files."""
files = sorted(files)
assert len(files) == 4
standards = StandardsReadings(
*[VNAReading.from_s1p(fl, f_low=f_low, f_high=f_high) for fl in files[:3]]
)
external = VNAReading.from_s1p(files[-1], f_low=f_low, f_high=f_high)
# Note that here the
load_s11 = (
LoadPlusSwitchS11(
standards=standards,
external_match=external,
load_name="antenna",
),
)
return cls.from_load_and_internal_switch(
load_s11=load_s11, internal_switch=internal_switch, **kwargs
)
[docs]
@classmethod
def from_single_file(
cls,
path,
internal_switch: InternalSwitch,
f_low: float = 0 * u.MHz,
f_high: float = np.inf * u.MHz,
**kwargs,
):
"""Generate from a single pre-calibrated file."""
if path.endswith(".csv"):
delimiter = ","
else:
delimiter = " "
f_orig, gamma_real, gamma_imag = np.loadtxt(
path,
skiprows=1,
delimiter=delimiter,
unpack=True,
comments=["BEGIN", "END", "#"],
)
return cls(
raw_s11=gamma_real + 1j * gamma_imag,
freq=FrequencyRange(f_orig * u.Hz, f_low=f_low, f_high=f_high),
internal_switch=internal_switch,
**kwargs,
)