def NqpfromQi(S21data, uselowtempapprox=True, lbd0=0.092, kb=86.17, N0=1.72e4, kbTD=37312.0): '''Calculates the number of quasiparticles from the measured temperature dependence of Qi. Returns temperatures in K, along with the calculated quasiparticle numbers. If uselowtempapprox, the complex impedence is calculated directly with a low temperature approximation, else it\'s calculated with the cinduct function in kidcalc (slow).''' ak_ = ak(S21data) hw = S21data[:, 5] * 2 * np.pi * 6.582e-4 * 1e-6 d = S21data[0, 25] kbTc = S21data[0, 21] * kb kbT = S21data[:, 1] * kb D0 = 1.76 * kbTc if uselowtempapprox: beta_ = beta(lbd0, d, D0, D0, kbT[0]) def minfunc(kbT, s2s1, hw, D0): xi = hw / (2 * kbT) return np.abs(np.pi/4*((np.exp(D0/kbT)-2*np.exp(-xi)*i0(xi))/\ (np.sinh(xi)*k0(xi)))-s2s1) Nqp = np.zeros(len(kbT)) for i in range(len(kbT)): s2s1 = S21data[i, 4] * (ak_ * beta_) / 2 res = minisc(minfunc, args=(s2s1, hw[i], D0), bounds=(0, kbTc), method='bounded') kbTeff = res.x Nqp[i] = S21data[0, 14] * nqp(kbTeff, D0, N0) return kbT / kb, Nqp else: def minfunc(kbT, s2s1, hw, N0, kbTc, kbTD): D_ = D(kbT, N0, kbTc, kbTD) s1, s2 = cinduct(hw, D_, kbT) return np.abs(s2s1 - s2 / s1) Nqp = np.zeros(len(kbT)) for i in range(len(kbT)): D_0 = D(kbT[i], N0, kbTc, kbTD) beta_ = beta(lbd0, d, D_0, D0, kbT[i]) s2s1 = S21data[i, 4] * (ak_ * beta_) / 2 res = minisc(minfunc, args=(s2s1, hw[i], N0, kbTc, kbTD), bounds=(0, kbTc), method='bounded') kbTeff = res.x D_ = D(kbTeff, N0, kbTc, kbTD) Nqp[i] = S21data[0, 14] * nqp(kbTeff, D_, N0) return kbT / kb, Nqp
def NqpfromQi(S21data, uselowtempapprox=True, SC=SuperCond.Al()): """Calculates the number of quasiparticles from the measured temperature dependence of Qi. Returns temperatures in K, along with the calculated quasiparticle numbers. If uselowtempapprox, the complex impedence is calculated directly with a low temperature approximation, else it\'s calculated with the cinduct function in kidcalc (slow).""" ak_ = ak(S21data) hw = S21data[:, 5] * const.Plack / const.e * 1e6 kbT = S21data[:, 1] * const.Boltzmann / const.e * 1e6 if uselowtempapprox: beta_ = kidcalc.beta(kbT[0], SC.D0, SuperCond.Sheet(SC, d=S21data[0, 25])) def minfunc(kbT, s2s1, hw, D0): xi = hw / (2 * kbT) return np.abs(np.pi / 4 * ((np.exp(D0 / kbT) - 2 * np.exp(-xi) * i0(xi)) / (np.sinh(xi) * k0(xi))) - s2s1) Nqp = np.zeros(len(kbT)) for i in range(len(kbT)): s2s1 = S21data[i, 4] * (ak_ * beta_) / 2 res = minisc( minfunc, args=(s2s1, hw[i], SC.D0), bounds=(0, SC.kbTc), method="bounded", ) kbTeff = res.x Nqp[i] = S21data[0, 14] * kidcalc.nqp(kbTeff, SC.D0, SC) return kbT / (const.Boltzmann / const.e * 1e6), Nqp else: def minfunc(kbT, s2s1, hw, SC): D_ = kidcalc.D(kbT, SC) s1, s2 = kidcalc.cinduct(hw, D_, kbT) return np.abs(s2s1 - s2 / s1) Nqp = np.zeros(len(kbT)) for i in range(len(kbT)): D_0 = kidcalc.D(kbT[i], SC) beta_ = kidcalc.beta(kbT[i], D_0, SuperCond.Sheet(SC, d=S21data[0, 25])) s2s1 = S21data[i, 4] * (ak_ * beta_) / 2 res = minisc(minfunc, args=(s2s1, hw[i], SC), bounds=(0, SC.kbTc), method="bounded") kbTeff = res.x D_ = kidcalc.D(kbTeff, SC) Nqp[i] = S21data[0, 14] * kidcalc.nqp(kbTeff, D_, SC) return kbT / (const.Boltzmann / const.e * 1e6), Nqp
def calc_params(self, e, nrTraps, t1, t2, xi, eta, P, kbT): D = kidcalc.D(kbT, self.SC) c = nrTraps / self.V / (2 * self.SC.N0 * D) NT = kidcalc.nqp(kbT, D, self.SC) * self.V R = (2 * D / self.SC.kbTc)**3 / (4 * D * self.SC.N0 * self.SC.t0) Rstar = R / (1 + self.tesc / self.SC.tpb) Rtstar = xi / (t1 * self.SC.N0 * D) * (1 + e / D) Gd = (np.sqrt(np.pi) / 4 * (kbT / D)**(3 / 2) * np.exp(-(D - e) / kbT) * (1 / t1 * (3 + 2 * ((D - e) / kbT)) * kbT / D + 4 / t2 * (1 + (D - e) / kbT))) Gt = (2 * c / t2 * (1 - e / D) * (1 / (np.exp( (D - e) / kbT) - 1) + 1) * (1 - 1 / (np.exp(e / kbT) + 1))) GB = 1 / self.SC.tpb Ges = 1 / self.tesc NTw = R * NT**2 / (2 * self.V * GB) return [ R, self.V, GB, Gt, Gd, Rtstar, Ges, NTw, eta, P, D, ], NT, Rstar
def calc_params(self, Gt, Gd, eta, P, kbT): D = kidcalc.D(kbT, self.N0, self.kbTc, self.kbTD) NT = kidcalc.nqp(kbT, D, self.N0) * self.V R = (2 * D / self.kbTc)**3 / (4 * D * self.N0 * self.t0) Rstar = R / (1 + self.tesc / self.tpb) Ges = 1 / self.tesc GB = 1 / self.tpb NTw = R * NT**2 / (2 * self.V * GB) return [R, self.V, GB, Gt, Gd, Ges, NTw, eta, P, D], NT, Rstar
def calc_params(self, e, nrTraps, t1, xi, kbT): D = kidcalc.D(kbT, self.N0, self.kbTc, self.kbTD) c = (nrTraps / self.V / (2 * self.N0 * D)) NT = kidcalc.nqp(kbT, D, self.N0) * self.V NtT = self.V * 2 * self.N0 * D * c / kidcalc.f(e, kbT) R = (2 * D / self.kbTc)**3 / (4 * D * self.N0 * self.t0) Rstar = R / (1 + self.tesc / self.tpb) Rtstar = xi * (1 + e / D) / (t1 * self.N0 * D) return [Rstar, self.V, NT, NtT, Rtstar]
def calc_params(self, e, nrTraps, Gt, Gd, xi, kbT): D = kidcalc.D(kbT, self.SC) c = nrTraps / self.V / (2 * self.SC.N0 * D) NT = kidcalc.nqp(kbT, D, self.SC.N0) * self.V NtT = self.V * 2 * self.SC.N0 * D * c * kidcalc.f(e, kbT) R = (2 * D / self.SC.kbTc)**3 / (4 * D * self.SC.N0 * self.SC.t0) Rstar = R / (1 + self.tesc / self.SC.tpb) Rtstar = R * xi return [Rstar, self.V, NT, NtT, Gt, Gd, Rtstar]
def calc_params(self, e, nrTraps, t1, t2, xi, kbT): D = kidcalc.D(kbT, self.SC) c = nrTraps / self.V / (2 * self.SC.N0 * D) NT = kidcalc.nqp(kbT, D, self.SC) * self.V NtT = self.V * 2 * self.SC.N0 * D * c * kidcalc.f(e, kbT) R = (2 * D / self.SC.kbTc)**3 / (4 * D * self.SC.N0 * self.SC.t0) Rstar = R / (1 + self.tesc / self.SC.tpb) Rtstar = xi / (t1 * self.SC.N0 * D) * (1 + e / D) Gd = (np.sqrt(np.pi) / 4 * (kbT / D)**(3 / 2) * np.exp(-(D - e) / kbT) * (1 / t1 * (3 + 2 * ((D - e) / kbT)) * kbT / D + 4 / t2 * (1 + (D - e) / kbT))) Gt = (2 * c / t2 * (1 - e / D) * (1 / (np.exp( (D - e) / kbT) - 1) + 1) * (1 - 1 / (np.exp(e / kbT) + 1))) return [Rstar, self.V, NT, NtT, Gt, Gd, Rtstar]
def calc_params(self, e, nrTraps, t1, t2, eta, P, kbT): D = kidcalc.D(kbT, self.SCvol.SC) NT = kidcalc.nqp(kbT, D, self.SCvol.SC) * self.SCvol.SC.V R = (2 * D / self.SCvol.SC.kbTc)**3 / (4 * D * self.SCvol.SC.N0 * self.SCvol.SC.t0) Rstar = R / (1 + self.SCvol.SC.tesc / self.SCvol.SC.tpb) Ges = 1 / self.SCvol.SC.tesc GB = 1 / self.SCvol.SC.tpb NwT = R * NT**2 / (2 * self.SCvol.SC.V * GB) Nqp0 = np.sqrt(self.SCvol.SC.V * ((1 + GB / Ges) * eta * P / D + 2 * GB * NwT) / R) kbTeff = kidcalc.kbTeff(Nqp0, self.SCvol.SC) Gd = (np.sqrt(np.pi) / 4 * (kbTeff / D)**(3 / 2) * np.exp(-(D - e) / kbTeff) * (1 / t1 * (3 + 2 * ((D - e) / kbTeff)) * kbTeff / D + 4 / t2 * (1 + (D - e) / kbTeff))) Gt = (2 * (nrTraps / self.SCvol.SC.V / (2 * self.SCvol.SC.N0 * D)) / t2 * (1 - e / D) * (1 / (np.exp((D - e) / kbTeff) - 1) + 1) * (1 - 1 / (np.exp(e / kbTeff) + 1))) return [R, self.SCvol.SC.V, GB, Gt, Gd, Ges, NwT, eta, P, D], NT, Rstar
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 Nqp_0(self): return self.V * kidcalc.nqp(self.kbT, self.D_0, self.SC)
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])