def init_KID( Chipnum, KIDnum, Pread, Tbath, Teffmethod="GR", wvl=None, S21=False, SC_class=SC.Al ): """This returns an KID object, with the parameters initialized by measurements on a physical KID. The effective temperature is set with an lifetime measurement, either from GR noise (GR) or pulse (pulse)""" TDparam = io.get_grTDparam(Chipnum) S21data = io.get_S21data(Chipnum, KIDnum, Pread) Qc = S21data[0, 3] hw0 = S21data[0, 5] * const.Planck / const.e * 1e12 * 1e-6 kbT0 = const.Boltzmann / const.e * 1e6 * S21data[0, 1] SC_inst = SC.init_SC(Chipnum, KIDnum, Pread, SC_class=SC_class) ak1 = calc.ak(S21data, SC_inst) if Teffmethod == "GR": Temp = io.get_grTemp(TDparam, KIDnum, Pread) taut = np.zeros(len(Temp)) for i in range(len(Temp)): freq, SPR = io.get_grdata(TDparam, KIDnum, Pread, Temp[i]) taut[i] = calc.tau(freq, SPR)[0] tauspl = interpolate.splrep(Temp[~np.isnan(taut)], taut[~np.isnan(taut)]) tau1 = interpolate.splev(Tbath, tauspl) kbT = kidcalc.kbTbeff(tau1, SC_inst) elif Teffmethod == "pulse": peakdata_ph, peakdata_amp = io.get_pulsedata(Chipnum, KIDnum, Pread, Tbath, wvl) tau1 = calc.tau_pulse(peakdata_ph) kbT = kidcalc.kbTbeff(tau1, SC_inst) elif Teffmethod == "Tbath": kbT = Tbath * 1e-3 * const.Boltzmann / const.e * 1e6 if S21: return S21KID(S21data, Qc=Qc, hw0=hw0, kbT0=kbT0, kbT=kbT, ak=ak1, SC=SC_inst) else: return KID(Qc=Qc, hw0=hw0, kbT0=kbT0, kbT=kbT, ak=ak1, SC=SC_inst)
def rej_pulses(data, nrsgm=6, nrseg=32, sfreq=50e3, smoothdata=False, plot=False): '''Pulse rejection algorithm. It devides the time stream into segments and rejects segments based on a threshold. Based on PdV's pulse rejection algorithm. Arguments: data -- the time stream to be analyzed nrsgm -- number of times the minimal standard deviation to use as threshold (default 6) nrseg -- number of segments to divide the time stream in (default 32) sfreq -- sample frequency (default 50 kHz), only needed when plot or smoothdata. smoothdata -- boolean to determine to smooth the timestream first. If True, the lifetime is estimated on a Lorenzian fit on the non-rejected full time stream and given to the smooth function. if the fit fails, the lifetime is set to 1 µs. plot -- boolean to plot time stream with rejection indication. Returns: The splitted input data and a list of booleans which segments are rejected.''' if smoothdata: #estimate lifetime via initial PSD and Lorentzian fit. freq, PSD = welch(data, sfreq, 'hamming', nperseg=.5 * sfreq) tau, tauerr = calc.tau(freq, 10 * np.log10(PSD)) if tauerr / tau >= .1: tau = 1 warnings.warn('Could not estimate lifetime from PSD, 1 µs is used') tau *= 1e-6 #convert to seconds smdata = smooth(data, tau, sfreq) else: smdata = data corrdata = subtr_offset(smdata) spdata = np.array(np.array_split(corrdata, nrseg)) thrshld = nrsgm * spdata.std(1).min() reject = np.abs(spdata).max(1) > thrshld if plot: fig, ax = plt.subplots() t0 = 0 for ind in range(nrseg): ax.plot((t0 + np.arange(len(spdata[ind]))) / sfreq, spdata[ind], color='b', alpha=.5 if reject[ind] else 1) t0 += len(spdata[ind]) ax.plot(np.arange(len(data)) / sfreq, thrshld * np.ones(len(data)), 'r', label=f'{nrsgm}$\sigma_{{min}}$-threshold') ax.plot( np.arange(len(data)) / sfreq, -1 * thrshld * np.ones(len(data)), 'r') ax.legend() ax.set_xlabel('Time (s)') plt.show() plt.close() return np.array(np.array_split(data, nrseg)), reject
def calc_ltnlvl(self, Tmin, Tmax, *args, lvlcal=1, points=20, plotspec=False, plotnumrates=False, PSDs='NN'): tau = np.full(points, np.nan) tauerr = np.full(points, np.nan) lvl = np.full(points, np.nan) lvlerr = np.full(points, np.nan) Temp = np.linspace(Tmin, Tmax, points) cmap = matplotlib.cm.get_cmap('viridis') norm = matplotlib.colors.Normalize(vmin=Temp.min(), vmax=Temp.max()) for i in range(len(Temp)): if plotnumrates: freq, swdB, nums, rates = self.calc_spec(*args, Temp[i] * self.kb, lvlcal=lvlcal, retnumrates=True, PSDs=PSDs) plt.figure('Nums') numcol = ['b', 'g', 'r', 'c', 'm', 'y', 'k'] for val in nums.values(): plt.plot(Temp[i], val, numcol.pop(0) + '.') plt.figure('Rates') ratecol = ['b', 'g', 'r', 'c', 'm', 'y', 'k'] for val in rates.values(): plt.plot(Temp[i], val, ratecol.pop(0) + '.') else: freq, swdB = self.calc_spec(*args, Temp[i] * self.kb, lvlcal=lvlcal, PSDs=PSDs) tau[i], tauerr[i], lvl[i], lvlerr[i] = calc.tau(freq, swdB, startf=1e0, stopf=1e5, plot=False, retfnl=True) if plotspec: plt.figure('Spectra') plt.plot(freq, swdB, color=cmap(norm(Temp[i]))) if plotspec: plt.figure('Spectra') plt.xscale('log') plt.ylabel('Noise level (dBc/Hz)') plt.xlabel('Frequency (Hz)') clb = plt.colorbar( matplotlib.cm.ScalarMappable(norm=norm, cmap=cmap)) clb.ax.set_title('T (K)') if plotnumrates: plt.figure('Nums') plt.title('Numbers') plt.yscale('log') plt.xlabel('Temperature (K)') plt.ylabel('Number') plt.legend(list(nums.keys())) plt.figure('Rates') plt.title('Rates') plt.yscale('log') plt.legend(list(rates.keys())) plt.ylabel(r'Rate ($\mu s^{-1}$)') plt.xlabel('Temperature (K)') return Temp, tau, tauerr, lvl, lvlerr
def Nqp( Chipnum, KIDnum, pltPread="all", spec="cross", startstopf=(None, None), delampNoise=False, del1fNoise=False, del1fnNoise=False, Tminmax=None, relerrthrs=0.3, pltThrm=True, pltNqpQi=False, splitT=0, pltNqptau=False, SCvol=None, SCkwargs={}, nqpaxis=True, fig=None, ax=None, label=None, color=None, fmt="-o", ): """Plots the number of quasiparticle calculated from the noise levels and lifetimes from PSDs. options similar to options in ltnlvl. pltThrm -- also plot thermal line (needs constants) pltNqpQi -- plot Nqp from Qi as well (needs constants) splitT -- makes NqpQi line dashed below this T pltNqptau -- plot Nqp from lifetime only (need constants) nqpaxis -- also shows density on right axis.""" TDparam = io.get_grTDparam(Chipnum) if ax is None: fig, ax = plt.subplots() Preadar = _selectPread(pltPread, io.get_grPread(TDparam, KIDnum)) if Preadar.size > 1: cmap = matplotlib.cm.get_cmap("plasma") norm = matplotlib.colors.Normalize(-1.05 * Preadar.max(), -0.95 * Preadar.min()) clb = fig.colorbar(matplotlib.cm.ScalarMappable(norm=norm, cmap=cmap), ax=ax) clb.ax.set_title(r"$P_{read}$ (dBm)") if SCvol is None: SCvol = SuperCond.init_SCvol(Chipnum, KIDnum, set_tesc=pltNqptau, **SCkwargs) for Pread in Preadar: S21data = io.get_S21data(Chipnum, KIDnum, Pread) Respspl = calc.Respspl(Chipnum, KIDnum, Pread, var=spec) Temp = io.get_grTemp(TDparam, KIDnum, Pread) if Tminmax is not None: if Tminmax[0] is not None: Temp = Temp[Temp > Tminmax[0]] if Tminmax[1] is not None: Temp = Temp[Temp < Tminmax[1]] Nqp, Nqperr, taut = np.zeros((3, len(Temp))) for i in range(len(Temp)): freq, SPR = io.get_grdata(TDparam, KIDnum, Pread, Temp[i], spec=spec) if delampNoise: freq, SPR = filters.del_ampNoise(freq, SPR) if del1fNoise: freq, SPR = filters.del_1fNoise(freq, SPR) if del1fnNoise: freq, SPR = filters.del_1fnNoise(freq, SPR) taut[i], tauterr, lvl, lvlerr = calc.tau(freq, SPR, retfnl=True, startf=startstopf[0], stopf=startstopf[1]) lvl = lvl / interpolate.splev(Temp[i] * 1e-3, Respspl)**2 lvlerr = lvlerr / interpolate.splev(Temp[i] * 1e-3, Respspl)**2 Nqp[i] = lvl / (4 * taut[i] * 1e-6) Nqperr[i] = np.sqrt((lvlerr / (4 * taut[i] * 1e-6))**2 + (-lvl * tauterr * 1e-6 / (4 * (taut[i] * 1e-6)**2))**2) mask = ~np.isnan(Nqp) mask[mask] = Nqperr[mask] / Nqp[mask] <= relerrthrs if color is None: if Preadar.size > 1: color = cmap(norm(-1 * Pread)) elif pltPread == "min": color = "purple" elif pltPread == "max": color = "gold" dataline = ax.errorbar( Temp[mask], Nqp[mask], yerr=Nqperr[mask], color=color, fmt=fmt, mec="k", capsize=2.0, label=label, ) if pltNqptau: Nqp_ = SCvol.V * kidcalc.nqpfromtau(taut, SCvol) (tauline, ) = ax.plot( Temp[mask], Nqp_[mask], color=color, zorder=len(ax.lines) + 1, label="$\\tau_{qp}^*$", ) if pltNqpQi: Preadar = io.get_S21Pread(Chipnum, KIDnum) for Pread in Preadar: S21data = io.get_S21data(Chipnum, KIDnum, Pread) T, Nqp = calc.NqpfromQi(S21data, SC=SCvol.SC) mask = np.logical_and(T * 1e3 > ax.get_xlim()[0], T * 1e3 < ax.get_xlim()[1]) totalT = T[mask] totalNqp = Nqp[mask] if len(Preadar) == 1: color = "g" else: color = cmap(norm(closestPread)) (Qline, ) = ax.plot( totalT[totalT > splitT] * 1e3, totalNqp[totalT > splitT], linestyle="-", color=color, zorder=len(ax.lines) + 1, label="$Q_i$", ) ax.plot( totalT[totalT < splitT] * 1e3, totalNqp[totalT < splitT], linestyle="--", color=color, zorder=len(ax.lines) + 1, ) if pltThrm: T = np.linspace(*ax.get_xlim(), 100) NqpT = np.zeros(100) for i in range(len(T)): D_ = kidcalc.D(const.Boltzmann / const.e * 1e6 * T[i] * 1e-3, SCvol.SC) NqpT[i] = SCvol.V * kidcalc.nqp( const.Boltzmann / const.e * 1e6 * T[i] * 1e-3, D_, SCvol.SC) (Thline, ) = ax.plot(T, NqpT, color="k", zorder=len(ax.lines) + 1, label="Thermal $N_{qp}$") handles, labels = ax.get_legend_handles_labels() by_label = dict(zip(labels, handles)) ax.legend(by_label.values(), by_label.keys()) ax.set_ylabel("$N_{qp}$") ax.set_xlabel("Temperature (mK)") ax.set_yscale("log") if nqpaxis: def nqptoNqp(x): return x * SCvol.V def Nqptonqp(x): return x / SCvol.V ax2 = ax.secondary_yaxis("right", functions=(Nqptonqp, nqptoNqp)) ax2.set_ylabel("$n_{qp}$ ($\\mu m^{-3}$)") if Preadar.size > 1: l, b, w, h = clb.ax.get_position().bounds clb.ax.set_position([l + 0.12, b, w, h])
def ltnlvl( Chipnum, KIDlist=None, pltPread="all", spec="cross", Tminmax=None, startstopf=(None, None), lvlcomp="", pltTTc=False, delampNoise=False, del1fNoise=False, del1fnNoise=False, suboffres=False, relerrthrs=0.1, pltKIDsep=True, pltthlvl=False, pltkaplan=False, pltthmlvl=False, plttres=False, plttscat=False, fig=None, ax12=None, color="Pread", pltclrbar=True, fmt="-o", label=None, SCvol=None, SCkwargs={}, showfit=False, savefig=False, ): """Plots the results from a Lorentzian fit to the PSDs of multiple KIDs, read powers and temperatures. Two axes: 0: lifetimes 1: noise levels, both with temperature on the x-axis. The color can be specified and is Pread by default. Options: startstopf -- defines the fitting window lvlcomp -- defines how the levels are compensated. Use Resp for responsivity compensation. (will be moved in the future) del{}Noise -- filter spectrum before fitting. relerrthrs -- only plot fits with a relative error threshold in lifetime less than this. pltKIDsep -- if True, different KIDs get a new figure. pltthlvl -- expected noise level is plotted as dashed line pltkaplan -- a kaplan fit (tesc as parameter) is plotted in the lifetime axis. pltthmfnl -- a noise level from the fitted lifetime and theoretical Nqp is plotted as well plttres -- the resonator ring time is plotted in the lifetime axis. ... multiple figure handling options ... ... options for the tesc deteremination ... showfit -- the fits are displayed in numerous new figures, for manual checking.""" def _make_fig(): fig, axs = plt.subplots(1, 2, figsize=(8, 3)) return fig, axs def _get_cmap(**kwargs): if color == "Pread": cmap = matplotlib.cm.get_cmap("plasma") norm = matplotlib.colors.Normalize(-1.05 * kwargs["Preadar"].max(), -0.95 * kwargs["Preadar"].min()) if pltclrbar: clb = fig.colorbar( matplotlib.cm.ScalarMappable(norm=norm, cmap=cmap)) clb.ax.set_title(r"$P_{read}$ (dBm)") elif color == "Pint": cmap = matplotlib.cm.get_cmap("plasma") norm = matplotlib.colors.Normalize(kwargs["Pintar"].min() * 1.05, kwargs["Pintar"].max() * 0.95) if pltclrbar: clb = fig.colorbar( matplotlib.cm.ScalarMappable(norm=norm, cmap=cmap)) clb.ax.set_title(r"$P_{int}$ (dBm)") elif color == "V": cmap = matplotlib.cm.get_cmap("cividis") norm = matplotlib.colors.Normalize( np.array(list(Vdict.values())).min(), np.array(list(Vdict.values())).max(), ) if pltclrbar: clb = fig.colorbar( matplotlib.cm.ScalarMappable(norm=norm, cmap=cmap)) clb.ax.set_title(r"Al Vol. ($\mu m^3$)") elif color == "KIDnum": cmap = matplotlib.cm.get_cmap("Paired") norm = matplotlib.colors.Normalize( np.array(KIDlist).min(), np.array(KIDlist).max()) if pltclrbar: clb = fig.colorbar( matplotlib.cm.ScalarMappable(norm=norm, cmap=cmap)) clb.ax.set_title("KID nr.") else: raise ValueError( "{} is not a valid variable as color".format(color)) return cmap, norm TDparam = io.get_grTDparam(Chipnum) if suboffres: TDparamoffres = io.get_grTDparam(Chipnum, offres=True) if KIDlist is None: KIDlist = io.get_grKIDs(TDparam) elif type(KIDlist) is int: KIDlist = [KIDlist] if color == "Pint": Pintdict = io.get_Pintdict(Chipnum) if not pltKIDsep: if ax12 is None: fig, axs = _make_fig() else: axs = ax12 if color == "Pint": Pintar = np.array([Pintdict[k] for k in KIDlist]) cmap, norm = _get_cmap(Pintar=Pintar) elif color == "V": Vdict = io.get_Vdict(Chipnum) cmap, norm = _get_cmap(Vdict=Vdict) elif color == "Pread": Preaddict = io.get_Preaddict(Chipnum) Preadar = np.array([Preaddict[k] for k in KIDlist]) cmap, norm = _get_cmap(Preadar=Preadar) elif color == "KIDnum": cmap, norm = _get_cmap(KIDlist=KIDlist) for KIDnum in KIDlist: Preadar = _selectPread(pltPread, io.get_grPread(TDparam, KIDnum)) if pltKIDsep: if ax12 is None: fig, axs = _make_fig() else: axs = ax12 if len(KIDlist) > 1: fig.suptitle(f"KID{KIDnum}") if color == "Pread": cmap, norm = _get_cmap(Preadar=Preadar) elif color == "Pint": cmap, norm = _get_cmap(Pintar=np.array(Pintdict[KIDnum])) if lvlcomp != "" or pltkaplan or pltthmlvl or pltthlvl or pltTTc: if SCvol is None: SCvol = SuperCond.init_SCvol(Chipnum, KIDnum, **SCkwargs) else: SCvol = SuperCond.Vol(SuperCond.Al(), np.nan, np.nan) for Pread in Preadar: Temp = np.trim_zeros(io.get_grTemp(TDparam, KIDnum, Pread)) lvlcompspl = calc.NLcomp(Chipnum, KIDnum, Pread, SCvol=SCvol, method=lvlcomp, var=spec) if suboffres: Temp = np.intersect1d( Temp, io.get_grTemp(TDparamoffres, KIDnum, Pread)) if Tminmax is not None: if Tminmax[0] is not None: Temp = Temp[Temp > Tminmax[0]] if Tminmax[1] is not None: Temp = Temp[Temp < Tminmax[1]] taut = np.zeros((len(Temp))) tauterr = np.zeros((len(Temp))) lvl = np.zeros((len(Temp))) lvlerr = np.zeros((len(Temp))) for i in range(len(Temp)): freq, SPR = io.get_grdata(TDparam, KIDnum, Pread, Temp[i], spec) if suboffres: orfreq, orSPR = io.get_grdata(TDparamoffres, KIDnum, Pread, Temp[i], spec) freq, SPR = filters.subtr_spec(freq, SPR, orfreq, orSPR) if delampNoise: freq, SPR = filters.del_ampNoise(freq, SPR) if del1fNoise: freq, SPR = filters.del_1fNoise(freq, SPR) if del1fnNoise: freq, SPR = filters.del_1fnNoise(freq, SPR) if showfit: print("{}, KID{}, -{} dBm, T={}, {}".format( Chipnum, KIDnum, Pread, Temp[i], spec)) taut[i], tauterr[i], lvl[i], lvlerr[i] = calc.tau( freq, SPR, plot=showfit, retfnl=True, startf=startstopf[0], stopf=startstopf[1], ) if showfit: print(tauterr[i] / taut[i]) lvl[i] = lvl[i] / interpolate.splev(Temp[i] * 1e-3, lvlcompspl) lvlerr[i] = lvlerr[i] / interpolate.splev( Temp[i] * 1e-3, lvlcompspl) # Deleting bad fits and plotting: mask = ~np.isnan(taut) mask[mask] = tauterr[mask] / taut[mask] <= relerrthrs if color == "Pread": clr = cmap(norm(-1 * Pread)) elif color == "Pint": clr = cmap(norm(Pint)) elif color == "V": clr = cmap(norm(Vdict[KIDnum])) elif color == "KIDnum": clr = cmap(norm(KIDnum)) else: clr = color if pltTTc: Temp = Temp / (SCvol.SC.kbTc / (const.Boltzmann / const.e * 1e6) * 1e3) axs[0].errorbar( Temp[mask], taut[mask], yerr=tauterr[mask], fmt=fmt, capsize=3.0, color=clr, mec="k", label=label if Pread == Preadar[-1] else "", ) axs[1].errorbar( Temp[mask], 10 * np.log10(lvl[mask]), yerr=10 * np.log10((lvlerr[mask] + lvl[mask]) / lvl[mask]), fmt=fmt, capsize=3.0, color=clr, mec="k", label=label if Pread == Preadar[-1] else "", ) if pltthlvl: if Tminmax is not None and not pltTTc: Tstartstop = Tminmax else: Tstartstop = (Temp[mask].min(), Temp[mask].max()) Ttemp = np.linspace(*Tstartstop, 100) if pltTTc: Ttemp = Ttemp * (SCvol.SC.kbTc / (const.Boltzmann / const.e * 1e6) * 1e3) explvl = (interpolate.splev( Ttemp * 1e-3, calc.Respspl(Chipnum, KIDnum, Pread, var=spec))**2) explvl *= (4 * SCvol.SC.t0 * 1e-6 * SCvol.V * SCvol.SC.N0 * (SCvol.SC.kbTc)**3 / (2 * (SCvol.SC.D0)**2) * (1 + SCvol.tesc / SCvol.SC.tpb) / 2) explvl /= interpolate.splev(Ttemp * 1e-3, lvlcompspl) if pltTTc: Ttemp = Ttemp / (SCvol.SC.kbTc / (const.Boltzmann / const.e * 1e6) * 1e3) (thlvlplot, ) = axs[1].plot( Ttemp, 10 * np.log10(explvl), color=clr, linestyle="--", linewidth=2.0, ) axs[1].legend((thlvlplot, ), (r"Expected noise level", )) if pltkaplan and Temp[mask].size != 0: if Tminmax is not None and not pltTTc: Tstartstop = Tminmax else: Tstartstop = (Temp[mask].min(), Temp[mask].max()) T = np.linspace(*Tstartstop, 100) if pltTTc: T = T * (SCvol.SC.kbTc / (const.Boltzmann / const.e * 1e6)) else: T = T * 1e-3 taukaplan = kidcalc.tau_kaplan(T, SCvol) if pltTTc: T = T / (SCvol.SC.kbTc / (const.Boltzmann / const.e * 1e6)) else: T = T * 1e3 axs[0].plot( T, taukaplan, color=clr, linestyle="--", linewidth=2.0, label="Kaplan, $\\tau_{qp}$", ) if plttscat: if Tminmax is not None: Tstartstop = Tminmax else: Tstartstop = (Temp[mask].min(), Temp[mask].max()) T = np.linspace(*Tstartstop, 100) if pltTTc: T = T * (SCvol.SC.kbTc / (const.Boltzmann / const.e * 1e6)) else: T = T * 1e-3 tscat = SCvol.SC.t0 / ( 2.277 * (SCvol.SC.kbTc / (2 * SCvol.SC.D0))**0.5 * (T / (SCvol.SC.kbTc / (const.Boltzmann / const.e * 1e6)))**(7 / 2)) if pltTTc: T = T / (SCvol.SC.kbTc / (const.Boltzmann / const.e * 1e6)) else: T = T * 1e3 axs[0].plot( T, tscat, color=clr, linestyle="-.", linewidth=2.0, label="Kaplan, $\\tau_s$", ) if pltthmlvl: try: if pltTTc: Temp = Temp * (SCvol.SC.kbTc / (const.Boltzmann / const.e * 1e6) * 1e3) tauspl = interpolate.splrep(Temp[mask], taut[mask], s=0) T = np.linspace(Temp[mask].min(), Temp[mask].max(), 100) Nqp = np.zeros(len(T)) for i in range(len(T)): Nqp[i] = SCvol.V * kidcalc.nqp( T[i] * 1e-3 * const.Boltzmann / const.e * 1e6, SCvol.D0, SCvol.SC, ) thmfnl = ( 4 * interpolate.splev(T, tauspl) * 1e-6 * Nqp * interpolate.splev( T * 1e-3, calc.Respspl(Chipnum, KIDnum, Pread, var=spec))**2) thmfnl /= interpolate.splev(T * 1e-3, lvlcompspl) if pltTTc: T = T / (SCvol.SC.kbTc / (const.Boltzmann / const.e * 1e6) * 1e3) (thmfnlplot, ) = axs[1].plot( T, 10 * np.log10(thmfnl), color=clr, linestyle="--", linewidth=3.0, ) axs[1].legend( (thmfnlplot, ), ("Thermal Noise Level \n with measured $\\tau_{qp}^*$", ), ) except: warnings.warn( "Could not make Thermal Noise Level, {},KID{},-{} dBm,{}" .format(Chipnum, KIDnum, Pread, spec)) if plttres: S21data = io.get_S21data(Chipnum, KIDnum, Pread) (tresline, ) = axs[0].plot( S21data[:, 1] / S21data[0, 21] if pltTTc else S21data[:, 1] * 1e3, S21data[:, 2] / (np.pi * S21data[:, 5]) * 1e6, color=clr, linestyle=":", ) axs[0].legend((tresline, ), ("$\\tau_{res}$", )) axs[0].set_yscale("log") for i in range(2): if pltTTc: axs[i].set_xlabel("$T/T_c$") else: axs[i].set_xlabel("Temperature (mK)") axs[0].set_ylabel(r"$\tau_{qp}^*$ (µs)") if lvlcomp == "Resp": axs[1].set_ylabel(r"Noise Level/$\mathcal{R}^2(T)$ (dB/Hz)") elif lvlcomp == "RespV": axs[1].set_ylabel(r"Noise Level/$(\mathcal{R}^2(T)V)$ (dB/Hz)") elif lvlcomp == "RespVtescTc": axs[1].set_ylabel(r"Noise Level/$(\mathcal{R}^2(T)\chi)$ (dB/Hz)") elif lvlcomp == "": axs[1].set_ylabel(r"Noise Level (dB/Hz)") elif lvlcomp == "RespLowT": axs[1].set_ylabel(r"Noise Level/$\mathcal{R}^2(T=50 mK)$ (dB/Hz)") else: axs[1].set_ylabel(r"comp. Noise Level (dB/Hz)") plt.tight_layout() if savefig: plt.savefig("GR_{}_KID{}_{}.pdf".format(Chipnum, KIDnum, spec)) plt.close() if ax12 is None: return fig, axs
def calc_ltnlvl(self, Tmin, Tmax, *args, lvlcal=1, points=20, plotspec=False, plotnumrates=False, PSDs="NN"): tau = np.full(points, np.nan) tauerr = np.full(points, np.nan) lvl = np.full(points, np.nan) lvlerr = np.full(points, np.nan) Temp = np.linspace(Tmin, Tmax, points) cmap = matplotlib.cm.get_cmap("viridis") norm = matplotlib.colors.Normalize(vmin=Temp.min(), vmax=Temp.max()) for i in range(len(Temp)): if plotnumrates: freq, swdB, nums, rates = self.calc_spec( *args, Temp[i] * const.Boltzmann / const.e * 1e6, lvlcal=lvlcal, retnumrates=True, PSDs=PSDs) plt.figure("Nums") numcol = ["b", "g", "r", "c", "m", "y", "k"] for val in nums.values(): plt.plot(Temp[i], val, numcol.pop(0) + ".") plt.figure("Rates") ratecol = ["b", "g", "r", "c", "m", "y", "k"] for val in rates.values(): plt.plot(Temp[i], val, ratecol.pop(0) + ".") else: freq, swdB = self.calc_spec(*args, Temp[i] * const.Boltzmann / const.e * 1e6, lvlcal=lvlcal, PSDs=PSDs) tau[i], tauerr[i], lvl[i], lvlerr[i] = calc.tau(freq, swdB, startf=1e0, stopf=1e5, plot=False, retfnl=True) if plotspec: plt.figure("Spectra") plt.plot(freq, swdB, color=cmap(norm(Temp[i]))) if plotspec: plt.figure("Spectra") plt.xscale("log") plt.ylabel("Noise level (dBc/Hz)") plt.xlabel("Frequency (Hz)") clb = plt.colorbar( matplotlib.cm.ScalarMappable(norm=norm, cmap=cmap)) clb.ax.set_title("T (K)") if plotnumrates: plt.figure("Nums") plt.title("Numbers") plt.yscale("log") plt.xlabel("Temperature (K)") plt.ylabel("Number") plt.legend(list(nums.keys())) plt.figure("Rates") plt.title("Rates") plt.yscale("log") plt.legend(list(rates.keys())) plt.ylabel(r"Rate ($\mu s^{-1}$)") plt.xlabel("Temperature (K)") return Temp, tau, tauerr, lvl, lvlerr
def Nqp(Chipnum, KIDnum, pltPread='all', spec='cross', startstopf=(None, None), delampNoise=False, del1fNoise=False, del1fnNoise=False, Tmax=500, relerrthrs=.3, pltThrm=True, pltNqpQi=False, splitT=0, pltNqptau=False, tescPread='max', nqpaxis=True, fig=None, ax=None, label=None, clr=None, N0=1.72e4, kbTD=37312.0, kb=86.17): '''Plots the number of quasiparticle calculated from the noise levels and lifetimes from PSDs. options similar to options in ltnlvl. TODO: delete double code in ltnlvl and Nqp pltThrm -- also plot thermal line (needs constants) pltNqpQi -- plot Nqp from Qi as well (needs constants) splitT -- makes NqpQi line dashed below this T pltNqptau -- plot Nqp from lifetime only (need constants) nqpaxis -- also shows density on right axis. ''' TDparam = io.get_grTDparam(Chipnum) if ax is None or fig is None: fig, ax = plt.subplots() Preadar = _selectPread(pltPread, io.get_grPread(TDparam, KIDnum)) if Preadar.size > 1: cmap = matplotlib.cm.get_cmap('plasma') norm = matplotlib.colors.Normalize(-1.05 * Preadar.max(), -.95 * Preadar.min()) clb = fig.colorbar(matplotlib.cm.ScalarMappable(norm=norm, cmap=cmap), ax=ax) clb.ax.set_title(r'$P_{read}$ (dBm)') for Pread in Preadar: S21data = io.get_S21data(Chipnum, KIDnum, Pread) if spec == 'cross': Respspl = interpolate.splrep(S21data[:, 1] * 1e3, np.sqrt(S21data[:, 10] * S21data[:, 18]), s=0) elif spec == 'amp': Respspl = interpolate.splrep(S21data[:, 1] * 1e3, S21data[:, 18], s=0) elif spec == 'phase': Respspl = interpolate.splrep(S21data[:, 1] * 1e3, S21data[:, 10], s=0) Temp = io.get_grTemp(TDparam, KIDnum, Pread) Temp = Temp[Temp < Tmax] Nqp, Nqperr, taut = np.zeros((3, len(Temp))) for i in range(len(Temp)): freq, SPR = io.get_grdata(TDparam, KIDnum, Pread, Temp[i], spec=spec) if delampNoise: freq, SPR = filters.del_ampNoise(freq, SPR) if del1fNoise: freq, SPR = filters.del_1fNoise(freq, SPR) if del1fnNoise: freq, SPR = filters.del_1fnNoise(freq, SPR) taut[i],tauterr,lvl,lvlerr = \ calc.tau(freq,SPR,retfnl = True, startf=startstopf[0],stopf=startstopf[1]) lvl = lvl / interpolate.splev(Temp[i], Respspl)**2 lvlerr = lvlerr / interpolate.splev(Temp[i], Respspl)**2 Nqp[i] = lvl / (4 * taut[i] * 1e-6) Nqperr[i] = np.sqrt((lvlerr/(4*taut[i]*1e-6))**2+\ (-lvl*tauterr*1e-6/(4*(taut[i]*1e-6)**2))**2) mask = ~np.isnan(Nqp) mask[mask] = Nqperr[mask] / Nqp[mask] <= relerrthrs if Preadar.size > 1: clr = cmap(norm(-1 * Pread)) elif pltPread == 'min': clr = 'purple' elif pltPread == 'max': clr = 'gold' dataline = ax.errorbar(Temp[mask], Nqp[mask], yerr=Nqperr[mask], color=clr, marker='o', mec='k', capsize=2., label=label) if pltNqptau: tesc = calc.tesc(Chipnum, KIDnum, Pread=tescPread) Nqp_ = S21data[0, 14] * kidcalc.nqpfromtau(taut, tesc, kb * S21data[0, 21]) tauline, = ax.plot(Temp[mask], Nqp_[mask], color=clr, zorder=len(ax.lines) + 1, label='$\\tau_{qp}^*$') if pltNqpQi: Preadar = io.get_S21Pread(Chipnum, KIDnum) for Pread in Preadar: S21data = io.get_S21data(Chipnum, KIDnum, Pread) T, Nqp = calc.NqpfromQi(S21data) mask = np.logical_and(T * 1e3 > ax.get_xlim()[0], T * 1e3 < ax.get_xlim()[1]) totalT = T[mask] totalNqp = Nqp[mask] if len(Preadar) == 1: clr = 'g' else: clr = cmap(norm(closestPread)) Qline, = ax.plot(totalT[totalT > splitT] * 1e3, totalNqp[totalT > splitT], linestyle='-', color=clr, zorder=len(ax.lines) + 1, label='$Q_i$') ax.plot(totalT[totalT < splitT] * 1e3, totalNqp[totalT < splitT], linestyle='--', color=clr, zorder=len(ax.lines) + 1) if pltThrm: T = np.linspace(*ax.get_xlim(), 100) NqpT = np.zeros(100) for i in range(len(T)): D_ = kidcalc.D(kb * T[i] * 1e-3, N0, kb * S21data[0, 21], kbTD) NqpT[i] = S21data[0, 14] * kidcalc.nqp(kb * T[i] * 1e-3, D_, N0) Thline, = ax.plot(T, NqpT, color='k', zorder=len(ax.lines) + 1, label='Thermal $N_{qp}$') handles, labels = ax.get_legend_handles_labels() by_label = dict(zip(labels, handles)) ax.legend(by_label.values(), by_label.keys()) ax.set_ylabel('$N_{qp}$') ax.set_xlabel('Temperature (mK)') ax.set_yscale('log') if nqpaxis: def nqptoNqp(x): return x * S21data[0, 14] def Nqptonqp(x): return x / S21data[0, 14] ax2 = ax.secondary_yaxis('right', functions=(Nqptonqp, nqptoNqp)) ax2.set_ylabel('$n_{qp}$ ($\\mu m^{-3}$)') if Preadar.size > 1: l, b, w, h = clb.ax.get_position().bounds clb.ax.set_position([l + .12, b, w, h])
def ltnlvl(Chipnum, KIDlist=None, pltPread='all', spec='cross', Tminmax=None, startstopf=(None, None), decades=3, minfreq=1e2, lvlcomp='', delampNoise=False, del1fNoise=False, del1fnNoise=False, suboffres=False, relerrthrs=.2, pltKIDsep=True, pltthlvl=False, pltkaplan=False, pltthmfnl=False, plttres=False, fig=None, ax12=None, color='Pread', pltclrbar=True, fmt='-o', label=None, defaulttesc=0, tescPread='max', tescpltkaplan=False, tescTminmax=(300, 400), showfit=False, savefig=False): '''Plots the results from a Lorentzian fit to the PSDs of multiple KIDs, read powers and temperatures. Two axes: 0: lifetimes 1: noise levels, both with temperature on the x-axis. The color can be specified and is Pread by default. Options: startstopf -- defines the fitting window decades,minfreq -- fitting options, see kidata.calc.tau method lvlcomp -- defines how the levels are compensated. Use Resp for responsivity compensation. (will be moved in the future) del{}Noise -- filter options {amp,1f,1fn} spectrum before fitting, see kidata.filters module. relerrthrs -- only plot fits with a relative error threshold in lifetime less than this. pltKIDsep -- if True, different KIDs get a new figure. pltthlvl -- expected noise level is plotted as dashed line pltkaplan -- a kaplan fit (tesc as parameter) is plotted in the lifetime axis. pltthmfnl -- a noise level from the fitted lifetime and theoretical Nqp is plotted as well plttres -- the resonator ring time is plotted in the lifetime axis. ... multiple figure handling options ... ... options for the tesc deteremination ... showfit -- the fits are displayed in numerous new figures, for manual checking.''' def _make_fig(): fig, axs = plt.subplots(1, 2, figsize=(8, 3)) return fig, axs def _get_cmap(**kwargs): if color == 'Pread': cmap = matplotlib.cm.get_cmap('plasma') norm = matplotlib.colors.Normalize(-1.05 * kwargs['Preadar'].max(), -.95 * kwargs['Preadar'].min()) clb = fig.colorbar( matplotlib.cm.ScalarMappable(norm=norm, cmap=cmap)) clb.ax.set_title(r'$P_{read}$ (dBm)') elif color == 'Pint': cmap = matplotlib.cm.get_cmap('plasma') norm = matplotlib.colors.Normalize(kwargs['Pintar'].min() * 1.05, kwargs['Pintar'].max() * .95) clb = fig.colorbar( matplotlib.cm.ScalarMappable(norm=norm, cmap=cmap)) clb.ax.set_title(r'$P_{int}$ (dBm)') elif color == 'V': cmap = matplotlib.cm.get_cmap('cividis') norm = matplotlib.colors.Normalize( np.array(list(Vdict.values())).min(), np.array(list(Vdict.values())).max()) clb = fig.colorbar( matplotlib.cm.ScalarMappable(norm=norm, cmap=cmap)) clb.ax.set_title(r'Al Vol. ($\mu m^3$)') elif color == 'KIDnum': cmap = matplotlib.cm.get_cmap('Paired') norm = matplotlib.colors.Normalize( np.array(KIDlist).min(), np.array(KIDlist).max()) clb = fig.colorbar( matplotlib.cm.ScalarMappable(norm=norm, cmap=cmap)) clb.ax.set_title('KID nr.') else: raise ValueError( '{} is not a valid variable as color'.format(color)) return cmap, norm TDparam = io.get_grTDparam(Chipnum) if suboffres: TDparamoffres = io.get_grTDparam(Chipnum, offres=True) if KIDlist is None: KIDlist = io.get_grKIDs(TDparam) elif type(KIDlist) is int: KIDlist = [KIDlist] if color == 'Pint': Pintdict = io.get_Pintdict(Chipnum) if not pltKIDsep: if ax12 is None: fig, axs = _make_fig() else: axs = ax12 if color == 'Pint': Pintar = np.array([Pintdict[k] for k in KIDlist]) cmap, norm = _get_cmap(Pintar=Pintar) elif color == 'V': Vdict = io.get_Vdict(Chipnum) cmap, norm = _get_cmap(Vdict=Vdict) elif color == 'Pread': Preaddict = io.get_Preaddict(Chipnum) Preadar = np.array([Preaddict[k] for k in KIDlist]) cmap, norm = _get_cmap(Preadar=Preadar) elif color == 'KIDnum': cmap, norm = _get_cmap(KIDlist=KIDlist) for KIDnum in KIDlist: Preadar = _selectPread(pltPread, io.get_grPread(TDparam, KIDnum)) if pltKIDsep: if ax12 is None: fig, axs = _make_fig() else: axs = ax12 if len(KIDlist) > 1: fig.suptitle(f'KID{KIDnum}') if color == 'Pread': cmap, norm = _get_cmap(Preadar=Preadar) elif color == 'Pint': cmap, norm = _get_cmap(Pintar=np.array(Pintdict[KIDnum])) if pltthlvl or 'tesc' in lvlcomp or pltkaplan: tesc_ = calc.tesc(Chipnum, KIDnum, defaulttesc=defaulttesc, minTemp=tescTminmax[0], maxTemp=tescTminmax[1], relerrthrs=relerrthrs, Pread=tescPread, pltkaplan=tescpltkaplan) for Pread in Preadar: Temp = np.trim_zeros(io.get_grTemp(TDparam, KIDnum, Pread)) if lvlcomp != '': S21data = io.get_S21data(Chipnum, KIDnum, Pread) if 'ak' in lvlcomp: akin = calc.ak(S21data) V = S21data[0, 14] if spec == 'cross': Respspl = interpolate.splrep(S21data[:, 1] * 1e3, np.sqrt(S21data[:, 10] * S21data[:, 18]), s=0) elif spec == 'amp': Respspl = interpolate.splrep(S21data[:, 1] * 1e3, S21data[:, 18], s=0) elif spec == 'phase': Respspl = interpolate.splrep(S21data[:, 1] * 1e3, S21data[:, 10], s=0) if lvlcomp == 'QakV': sqrtlvlcompspl = interpolate.splrep(S21data[:, 1] * 1e3, S21data[:, 2] * akin / V, s=0) elif lvlcomp == 'QaksqrtV': sqrtlvlcompspl = interpolate.splrep(S21data[:, 1] * 1e3, S21data[:, 2] * akin / np.sqrt(V), s=0) elif lvlcomp == 'QaksqrtVtesc': sqrtlvlcompspl = interpolate.splrep( S21data[:,1]*1e3, S21data[:,2]*akin/np.sqrt(V*\ (1+tesc_/.28e-3)),s=0) elif lvlcomp == 'QaksqrtVtescTc': sqrtlvlcompspl = interpolate.splrep( S21data[:,1]*1e3, S21data[:,2]*akin/np.sqrt(V*\ (1+tesc_/.28e-3)*\ (86.17*S21data[0,21])**3/\ (S21data[0,15]/1.6e-19*1e6)**2),s=0) elif lvlcomp == 'Resp': sqrtlvlcompspl = Respspl elif lvlcomp == 'RespPulse': pulsePreadar = io.get_pulsePread(Chipnum, KIDnum) pulsePreadselect = pulsePreadar[np.abs(pulsePreadar - Pread).argmin()] pulseTemp = io.get_pulseTemp(Chipnum, KIDnum, pulsePreadselect).min() pulsewvl = io.get_pulsewvl(Chipnum, KIDnum, pulsePreadselect, pulseTemp).min() phasepulse, amppulse = io.get_pulsedata( Chipnum, KIDnum, pulsePreadselect, pulseTemp, pulsewvl) phtau = calc.tau_pulse(phasepulse) amptau = calc.tau_pulse(amppulse) assert np.abs( 1 - phtau / amptau ) < .1, 'Amp and Phase lifetimes differ by more than 10%' dAdTheta = -1 * (amppulse / phasepulse )[600:int(600 + 2 * phtau)].mean() if spec == 'cross': Respspl = interpolate.splrep( S21data[:, 1] * 1e3, np.sqrt(S21data[:, 10]**2 * dAdTheta), s=0) elif spec == 'amp': Respspl = interpolate.splrep(S21data[:, 1] * 1e3, S21data[:, 10] * dAdTheta, s=0) elif spec == 'phase': Respspl = interpolate.splrep(S21data[:, 1] * 1e3, S21data[:, 10], s=0) sqrtlvlcompspl = Respspl elif lvlcomp == 'RespPint': Pint = 10**(-Pread / 10) * S21data[:, 2]**2 / ( S21data[:, 3] * np.pi) Pint /= Pint[0] sqrtlvlcompspl = interpolate.splrep( S21data[:, 1] * 1e3, interpolate.splev(S21data[:, 1] * 1e3, Respspl) / Pint**(1 / 4), s=0) elif lvlcomp == 'RespV': sqrtlvlcompspl = interpolate.splrep( S21data[:, 1] * 1e3, interpolate.splev(S21data[:, 1] * 1e3, Respspl) * np.sqrt(V), s=0) elif lvlcomp == 'RespVtescTc': kbTc = 86.17 * S21data[0, 21] sqrtlvlcompspl = interpolate.splrep( S21data[:,1]*1e3, interpolate.splev(S21data[:,1]*1e3, Respspl)*\ np.sqrt(V*(1+tesc_/.28e-3)*\ (kbTc)**3/\ (kidcalc.D(86.17*S21data[:,1],1.72e4,kbTc,37312.))**2),s=0) elif lvlcomp == 'RespLowT': sqrtlvlcompspl = interpolate.splrep( S21data[:,1]*1e3,np.ones(len(S21data[:,1]))*\ interpolate.splev(S21data[0,1]*1e3,Respspl)) else: raise ValueError( '{} is an invalid compensation method'.format(lvlcomp)) Pint = 10 * np.log10(10**(-1 * Pread / 10) * S21data[0, 2]**2 / S21data[0, 3] / np.pi) else: sqrtlvlcompspl = interpolate.splrep(Temp, np.ones(len(Temp))) if suboffres: Temp = np.intersect1d( Temp, io.get_grTemp(TDparamoffres, KIDnum, Pread)) if Tminmax != None: if Tminmax[0] != None: Temp = Temp[Temp > Tminmax[0]] if Tminmax[1] != None: Temp = Temp[Temp < Tminmax[1]] taut = np.zeros((len(Temp))) tauterr = np.zeros((len(Temp))) lvl = np.zeros((len(Temp))) lvlerr = np.zeros((len(Temp))) for i in range(len(Temp)): freq, SPR = io.get_grdata(TDparam, KIDnum, Pread, Temp[i], spec) if suboffres: orfreq, orSPR = io.get_grdata(TDparamoffres, KIDnum, Pread, Temp[i], spec) freq, SPR = filters.subtr_spec(freq, SPR, orfreq, orSPR) if delampNoise: freq, SPR = filters.del_ampNoise(freq, SPR) if del1fNoise: freq, SPR = filters.del_1fNoise(freq, SPR) if del1fnNoise: freq, SPR = filters.del_1fnNoise(freq, SPR) if showfit: print('{}, KID{}, -{} dBm, T={}, {}'.format( Chipnum, KIDnum, Pread, Temp[i], spec)) taut[i],tauterr[i],lvl[i],lvlerr[i] = \ calc.tau(freq,SPR,plot=showfit,retfnl=True, startf=startstopf[0],stopf=startstopf[1], decades=decades,minfreq=minfreq) if showfit: print(tauterr[i] / taut[i]) lvl[i] = lvl[i] / interpolate.splev(Temp[i], sqrtlvlcompspl)**2 lvlerr[i] = lvlerr[i] / interpolate.splev( Temp[i], sqrtlvlcompspl)**2 #Deleting bad fits and plotting: mask = ~np.isnan(taut) mask[mask] = tauterr[mask] / taut[mask] <= relerrthrs if color == 'Pread': clr = cmap(norm(-1 * Pread)) elif color == 'Pint': clr = cmap(norm(Pint)) elif color == 'V': clr = cmap(norm(Vdict[KIDnum])) elif color == 'KIDnum': clr = cmap(norm(KIDnum)) else: clr = color axs[0].errorbar(Temp[mask], taut[mask], yerr=tauterr[mask], fmt=fmt, capsize=3., color=clr, mec='k', label=label if Pread == Preadar[-1] else '') axs[1].errorbar(Temp[mask], 10 * np.log10(lvl[mask]), yerr=10 * np.log10( (lvlerr[mask] + lvl[mask]) / lvl[mask]), fmt=fmt, capsize=3., color=clr, mec='k', label=label if Pread == Preadar[-1] else '') if pltthlvl: if Tminmax is not None: Tstartstop = Tminmax else: Tstartstop = (Temp[mask].min(), Temp[mask].max()) Ttemp = np.linspace(*Tstartstop, 100) explvl = interpolate.splev(Ttemp, Respspl)**2 explvl *= 4*.44e-6*S21data[0,14]*1.72e4*(86.17*S21data[0,21])**3/\ (2*(S21data[0,15]/1.602e-19*1e6)**2)*(1+tesc_/.28e-3)/2 explvl /= interpolate.splev(Ttemp, sqrtlvlcompspl)**2 thlvlplot, = axs[1].plot(Ttemp, 10 * np.log10(explvl), color=clr, linestyle='--', linewidth=2.) axs[1].legend((thlvlplot, ), (r'Expected noise level', )) if pltkaplan and Temp[mask].size != 0 and Pread == Preadar.max(): if Tminmax is not None: Tstartstop = Tminmax else: Tstartstop = (Temp[mask].min(), Temp[mask].max()) T = np.linspace(*Tstartstop, 100) * 1e-3 taukaplan = kidcalc.tau_kaplan(T, tesc=tesc_, kbTc=86.17 * S21data[0, 21]) kaplanfit, = axs[0].plot(T * 1e3, taukaplan, color=clr, linestyle='--', linewidth=2.) axs[0].legend((kaplanfit, ), ('Kaplan', )) if pltthmfnl: try: tauspl = interpolate.splrep(Temp[mask], taut[mask], s=0) T = np.linspace(Temp[mask].min(), Temp[mask].max(), 100) Nqp = np.zeros(len(T)) for i in range(len(T)): Nqp[i] = V * nqp(T[i] * 86.17 * 1e-3, S21data[0, 15] / 1.602e-19 * 1e6, 1.72e4) thmfnl = 4*interpolate.splev(T,tauspl)*1e-6*\ Nqp*interpolate.splev(T,Respspl)**2 thmfnl /= interpolate.splev(T, sqrtlvlcompspl)**2 thmfnlplot, = axs[1].plot(T, 10 * np.log10(thmfnl), color=clr, linestyle='--', linewidth=3.) axs[1].legend( (thmfnlplot, ), ('Thermal Noise Level \n with measured $\\tau_{qp}^*$', )) except: warnings.warn( 'Could not make Thermal Noise Level, {},KID{},-{} dBm,{}' .format(Chipnum, KIDnum, Pread, spec)) if plttres: tresline, = axs[0].plot(S21data[:, 1] * 1e3, S21data[:, 2] / (np.pi * S21data[:, 5]) * 1e6, color=clr, linestyle=':') axs[0].legend((tresline, ), ('$\\tau_{res}$', )) axs[0].set_yscale('log') for i in range(2): axs[i].set_xlabel('Temperature (mK)') axs[0].set_ylabel(r'$\tau_{qp}^*$ (µs)') if lvlcomp == 'Resp': axs[1].set_ylabel(r'Noise Level/$\mathcal{R}^2(T)$ (dB/Hz)') elif lvlcomp == 'RespV': axs[1].set_ylabel(r'Noise Level/$(\mathcal{R}^2(T)V)$ (dB/Hz)') elif lvlcomp == 'RespVtescTc': axs[1].set_ylabel(r'Noise Level/$(\mathcal{R}^2(T)\chi)$ (dB/Hz)') elif lvlcomp == '': axs[1].set_ylabel(r'Noise Level (dB/Hz)') elif lvlcomp == 'RespLowT': axs[1].set_ylabel(r'Noise Level/$\mathcal{R}^2(T=50 mK)$ (dB/Hz)') else: axs[1].set_ylabel(r'comp. Noise Level (dB/Hz)') plt.tight_layout() if savefig: plt.savefig('GR_{}_KID{}_{}.pdf'.format(Chipnum, KIDnum, spec)) plt.close() if ax12 is None: return fig, axs