Source code for kidsproc.kidsmodel.simulator

#! /usr/bin/env python
import numpy as np
# from astropy import units as u
from astropy.modeling.mappings import Identity
from astropy.modeling import fix_inputs
from . import (
        # ResonanceCircleComplex,
        ResonanceCircleInv,
        ResonanceCircleComplex,
        ResonanceCircleComplexInv,
        ResonanceCircleSweepComplex,
        ResonanceCircleProbeComplex,
        ReadoutIQToComplex,
        OpticalDetune,
        # InstrumentalDetune,
        ResonanceCircleQrInv
        )
from astropy import log


[docs]class KidsSimulator(object): """Class that make simulated kids data.""" def __init__(self, fr=None, Qr=None, background=None, responsivity=None): self._Qr = Qr self._fr = fr self._background = background self._responsivity = responsivity # make models m_r = ResonanceCircleQrInv() m_x = Identity(1) m_p_probe = OpticalDetune( background=self._background, responsivity=self._responsivity) m_iq = (ReadoutIQToComplex() | ResonanceCircleComplex()) self._x_sweep = fix_inputs((m_r & m_x) | m_iq, { 'Qr': self._Qr }) self._f_sweep = ResonanceCircleSweepComplex(fr=self._fr, Qr=self._Qr) self._x_probe = self._x_sweep self._f_probe = ResonanceCircleProbeComplex() self._Qr2r = m_r self._p2x = m_p_probe self._p_probe = (m_r & m_p_probe) | m_iq self._iq2rx = ResonanceCircleInv() self._iq2rxcomplex = ResonanceCircleComplexInv() self._rx2iqcomplex = ResonanceCircleComplex() m_info = ['summary of kids simulator models:', ] sep = '-*' * 40 m_info.append(f"{sep}\nx sweep:\n{self._x_sweep}") m_info.append(f"{sep}\nf sweep:\n{self._f_sweep}") m_info.append(f"{sep}\nx probe:\n{self._x_probe}") m_info.append(f"{sep}\nf_probe:\n{self._f_probe}") m_info.append(f"{sep}\np_probe:\n{self._p_probe}") m_info.append(f"{sep}") log.info('\n'.join(m_info)) @property def fwhm_x(self): """Return the resonance FWHM in unit of x.""" return 1. / self._Qr @property def fwhm_f(self): """Return the resonance FWHM in unit of Hz.""" return self.fwhm_x * self._fr
[docs] def sweep_x(self, n_steps=None, n_fwhms=None, xlim=None): """Return a resonance circle sweep.""" if n_fwhms is None and xlim is None: raise ValueError("n_fwhms or xlim is required.") if xlim is None: xlim = (-0.5 * n_fwhms * self.fwhm_x, 0.5 * n_fwhms * self.fwhm_x) # get grid xs = np.linspace(*xlim, n_steps) iqs = self._x_sweep(xs) return xs, iqs
[docs] def probe_p(self, pwrs): """Return detector response for given optical power.""" # self._p2x.background = background # self._p2x.responsivity = responsivity rs = np.full(pwrs.shape, self._Qr2r(self._Qr)) xs = self._p2x(pwrs) iqs = self._x_probe(xs) return rs, xs, iqs
[docs] def solve_x(self, *args): """Return x for given detector response.""" if len(args) == 1: # complex return self._iq2rxcomplex(args[0]) return self._iq2rx(*args)