def __init__( self, Qc=2e4, hw0=5 * 0.6582 * 2 * np.pi, kbT0=0.2 * 86.17, kbT=0.2 * 86.17, ak=0.0268, SCvol=SC.Vol(SC.Al(), .05, 15.), ): """Attributes are defined here. hw0 and kbT0 give the resonance frequency at temperature T0, both in µeV, from which we linearize to calculate the new resonance frequencies.""" self.SC = SCvol.SC self.d = SCvol.d self.V = SCvol.V self.tesc = SCvol.tesc self.Qc = Qc # - self.hw0 = hw0 # µeV self.kbT0 = kbT0 # µeV self.kbT = kbT # µeV self.ak = ak # - self.epb = 0.6 - 0.4 * np.exp(-self.tesc / self.SC.tpb) # arbitary,
def spec( Chipnum, KIDlist=None, pltPread="all", spec="all", lvlcomp="", SCvol=None, SCkwargs={}, clbar=True, cmap=None, norm=None, del1fNoise=False, delampNoise=False, del1fnNoise=False, suboffres=False, plttres=False, Tminmax=(0, 500), ax12=None, xlim=(None, None), ylim=(None, None), ): """Plots PSDs of multiple KIDs, read powers and temperatures (indicated by color). Every KID has a new figure, which is returned if only one KID is plotted. lvlcomp specifies how the noise levels should be compensated (will be a different function in the future). Use Resp to divide by responsivity and obtain quasiparticle fluctuations. Use Resptres to compensate for the factor (1+(omega*taures)^2) and get the quasiparticle fluctuations. plttres will plot arrow at the frequencies corresponding to the resonator ring time.""" 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 spec == "all": specs = ["cross", "amp", "phase"] elif type(spec) == list: specs = spec else: raise ValueError("Invalid Spectrum Selection") for KIDnum in KIDlist: if lvlcomp != "": if SCvol is None: SCvol = SuperCond.init_SCvol(Chipnum, KIDnum, **SCkwargs) else: SCvol = SuperCond.Vol(SuperCond.Al(), np.nan, np.nan) Preadar = _selectPread(pltPread, io.get_grPread(TDparam, KIDnum)) if ax12 is None: fig, axs = plt.subplots( len(Preadar), len(specs), figsize=(4 * len(specs), 4 * len(Preadar)), sharex=True, sharey=True, squeeze=False, ) fig.suptitle(f"{Chipnum}, KID{KIDnum}") else: axs = ax12 for ax1, Pread in zip(range(len(Preadar)), Preadar): axs[ax1, 0].set_ylabel("PSD (dBc/Hz)") Temp = io.get_grTemp(TDparam, KIDnum, Pread) if suboffres: Temp = np.intersect1d( Temp, io.get_grTemp(TDparamoffres, KIDnum, Pread)) Temp = Temp[np.logical_and(Temp < Tminmax[1], Temp > Tminmax[0])] if cmap is None or norm is None: cmap = matplotlib.cm.get_cmap("viridis") norm = matplotlib.colors.Normalize(Temp.min(), Temp.max()) if clbar: clb = plt.colorbar(matplotlib.cm.ScalarMappable(norm=norm, cmap=cmap), ax=axs[ax1, -1]) clb.ax.set_title("T (mK)") if plttres: S21data = io.get_S21data(Chipnum, KIDnum, Pread) for i in range(len(Temp)): for (ax2, spec) in zip(range(len(specs)), specs): lvlcompspl = calc.NLcomp(Chipnum, KIDnum, Pread, SCvol=SCvol, method=lvlcomp, var=spec) freq, SPR = io.get_grdata(TDparam, KIDnum, Pread, Temp[i], spec=spec) if suboffres: orfreq, orSPR = io.get_grdata(TDparamoffres, KIDnum, Pread, Temp[i], spec=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) SPR[SPR == -140] = np.nan SPR[SPR == -np.inf] = np.nan SPR = 10 * np.log10(10**(SPR / 10) / interpolate.splev( Temp[i] * 1e-3, lvlcompspl)) axs[ax1, ax2].plot(freq, SPR, color=cmap(norm(Temp[i]))) axs[ax1, ax2].set_xscale("log") axs[ax1, ax2].set_title(spec + ", -{} dBm".format(Pread)) axs[-1, ax2].set_xlabel("Freq. (Hz)") if plttres: Tind = np.abs(S21data[:, 1] - Temp[i] * 1e-3).argmin() fres = S21data[Tind, 5] / (2 * S21data[Tind, 2]) axs[ax1, ax2].annotate("", (fres, 1), (fres, 1.25), arrowprops=dict(arrowstyle="simple", color=cmap( norm(Temp[i])), ec="k"), annotation_clip=False, xycoords=('data', 'axes fraction')) axs[0, 0].set_xlim(*xlim) axs[0, 0].set_ylim(*ylim) # plt.tight_layout() if ax12 is None and len(KIDlist) == 1: return fig, axs
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