class VNA_Pwr_Lyzer(VNA_Lyzer):
    base_name="vna_pwr_lyzer"

    pwr=Array().tag(unit="dBm", label="Power", sub=True)

    pwr_ind=Int()

    frq_ind=Int()

    yok_ind=Int()

    swp_type=Enum("pwr_first", "yoko_first")

    def _default_read_data(self):
        return read_data

    #def _observe_pwr_ind(self, change):
    #    reset_property(self, "Magcom")

    @tag_property(sub=True)
    def Magcom(self):
        if self.filter_type=="None":
            Magcom=self.MagcomData
        elif self.filter_type=="Fit":
            return self.MagAbsFit
        else:
            Magcom=self.MagcomFilt[self.indices, :, :]
        if self.bgsub_type=="Complex":
            return self.bgsub(Magcom)
        return Magcom[:, :, self.pwr_ind]

#array([[self.fft_filter_full(m, n, Magcom) for n in range(len(self.yoko))] for m in range(len(self.pwr))]).transpose()

    @private_property
    def MagcomFilt(self):
        if self.filt.filter_type=="FIR":
            return array([[self.filt.fir_filter(self.MagcomData[:,n,m]) for n in self.flat_flux_indices] for m in range(len(self.pwr))]).transpose()
        return array([[self.filt.fft_filter(self.MagcomData[:,n,m]) for n in self.flat_flux_indices]  for m in range(len(self.pwr))]).transpose()

    @tag_property( sub=True)
    def MagAbsFilt_sq(self):
        return absolute(self.MagcomFilt[:, :, self.pwr_ind])**2

    @private_property
    def fit_params(self):
        if self.fitter.fit_params is None:
            self.fitter.full_fit(x=self.flux_axis[self.flat_flux_indices], y=self.MagAbsFilt_sq, indices=self.flat_indices, gamma=self.fitter.gamma)
            if self.calc_p_guess:
                self.fitter.make_p_guess(self.flux_axis[self.flat_flux_indices], y=self.MagAbsFilt_sq, indices=self.flat_indices, gamma=self.fitter.gamma)
        return self.fitter.fit_params

    @private_property
    def MagAbsFit(self):
        return sqrt(self.fitter.reconstruct_fit(self.flux_axis[self.flat_flux_indices], self.fit_params))
class Coil_Lyzer(TA88_Lyzer):
    current = Array().tag(unit="V", plot=True, label="Current", sub=True)
Exemple #3
0
class Sat_Qubit(Qubit):
    atten = Float(83.0)
    phi_arr = Array()
    pwr_arr = Array()

    def _default_phi_arr(self):
        return linspace(0.2, 0.3, 101)

    def _default_pwr_arr(self):
        return linspace(-50.0, 0, 31)

    gamma = Float(38.0e6)
    gamma_el = Float(0.750e6)
    gamma_phi = Float(0.0)

    T = Float(0.03)
    N_dim = Int(8)

    fd = Float(4.5e9)

    N_gamma = SProperty()

    @N_gamma.getter
    def _get_N_gamma(self, fd, T):
        return 1.0 / (exp(h * fd / (k * T)) - 1.0)

    @private_property
    def a_op(self):
        return destroy(self.N_dim)

    @private_property
    def a_dag(self):
        return self.a_op.dag()

    @private_property
    def tdiag(self):
        return Qobj(diag(range(0, 2 * self.N_dim,
                               2)))  #dephasing operator, tdiag

    c_ops = SProperty().tag(sub=True)

    @c_ops.getter
    def _get_c_ops(self, gamma, N_gamma, a_op, a_dag, tdiag, gamma_phi):
        rate1 = gamma * (1 + N_gamma)
        rate2 = gamma * N_gamma
        return [sqrt(rate1) * a_op, sqrt(rate2) * a_dag, gamma_phi * tdiag]

    @private_property
    def nvec(self):
        return arange(self.N_dim)

    @private_property
    def fdvec(self):
        return self.nvec * self.fd

    @private_property
    def Ecvec(self):
        return -self.Ec * (6.0 * self.nvec**2 + 6.0 * self.nvec + 3.0) / 12.0

    @private_property
    def pwr_lin(self):
        pwr_fridge = self.pwr_arr - self.atten
        return 0.001 * 10**(pwr_fridge / 10.0)

    @private_property
    def Omega_arr(self):
        pwr_fridge = self.pwr_arr - self.atten
        return sqrt(0.001 * 10**(pwr_fridge / 10.0) /
                    (h * a.fd)) * sqrt(2 * self.gamma_el)

    @private_property
    def value_grid(self):
        value_grid = array(meshgrid(self.phi_arr, self.Omega_arr))
        return zip(value_grid[0, :, :].flatten(),
                   value_grid[1, :, :].flatten())

    funcer = Callable()
    #    @private_property
    #    def funcer(self):
    #        def find_expect2(vg): #phi=0.1, Omega_vec=3.0):
    #            phi, Omega=vg#.shape
    #            Omega_vec=-0.5j*(Omega*a.a_dag - conj(Omega)*a.a_op)
    #
    #            Ej = a.Ejmax*absolute(cos(pi*phi)) #Josephson energy as function of Phi.
    #
    #            wTvec = (-Ej + sqrt(8.0*Ej*a.Ec)*(a.nvec+0.5)+a.Ecvec)/h #\omega_m
    #
    #            wT = wTvec-a.fdvec #rotating frame of gate drive \omega_m-m*\omega_\gate
    #            transmon_levels = Qobj(diag(wT[range(a.N_dim)]))
    #            H=transmon_levels +Omega_vec #- 0.5j*(Omega_true*adag - conj(Omega_true)*a)
    #            final_state = steadystate(H, a.c_ops) #solve master equation
    #
    #            return expect( a.a_op, final_state) #expectation value of relaxation operator
    #            #Omega=\alpha\sqrt{2\Gamma_10} where |\alpha|^2=phonon flux=number of phonons per second
    #            #Omega=2\alpha\sqrt{\gamma} where |\alpha|^2=phonon flux=number of phonons per second
    #
    #        return find_expect

    @private_property
    def fexpt(self):
        fexpt = parallel_map(self.funcer, self.value_grid, progress_bar=True)
        return reshape(fexpt, (len(self.pwr_arr), len(self.phi_arr)))
Exemple #4
0
class Lyzer(LyzerBase):
    base_name="lyzer"

    frequency=Array().tag(unit="GHz", plot=True, label="Frequency", sub=True)
    yoko=Array().tag(unit="V", plot=True, label="Yoko", sub=True)
    #pwr=Array().tag(unit="V", plot=True, label="Yoko", sub=True)
    #frq2=Array().tag(unit="V", plot=True, label="Yoko", sub=True)
    Magcom=Array().tag(sub=True)
    probe_pwr=Float().tag(label="Probe power", read_only=True, display_unit="dBm/mW")

    on_res_ind=Int()
    start_ind=Int()
    stop_ind=Int()
    filt_center=Int()
    filt_halfwidth=Int()
    indices=List()
    port_name=Unicode('S21')
    VNA_name=Unicode("RS VNA")

    @tag_property()
    def filt_start_ind(self):
        return self.filt_center-self.filt_halfwidth+1

    @tag_property()
    def filt_end_ind(self):
        return self.filt_center+self.filt_halfwidth#-1

    fit_func=Callable(lorentzian).tag(private=True)
    read_data=Callable(read_data).tag(sub=True)

    fit_type=Enum("fq", "yoko")

    @tag_property(plot=True, sub=True)
    def fq(self):
        return self.qdt._get_fq(Ej=self.Ej, Ec=self.qdt.Ec)

    @tag_property(sub=True)
    def ls_f(self):
        #return array([f-self.qdt._get_Lamb_shift(f=f) for f in self.frequency])
        return array([sqrt(f*(f-2*self.qdt._get_Lamb_shift(f=f))) for f in self.frequency])

    @tag_property(sub=True)
    def voltage_from_flux_par(self):
        Ej=self.qdt._get_Ej_get_fq(fq=self.ls_f)
        flux_d_flux0=self.qdt._get_flux_over_flux0_get_Ej(Ej=Ej)
        #flux_d_flux0=arccos(Ej/Ejmax)#-pi/2
        #flux_d_flux0=append(flux_d_flux0, -arccos(Ej/Ejmax))
        #flux_d_flux0=append(flux_d_flux0, -arccos(Ej/Ejmax)+pi)
        #flux_d_flux0=append(flux_d_flux0, arccos(Ej/Ejmax)-pi)
        return self.qdt._get_voltage(flux_over_flux0=flux_d_flux0, offset=self.offset, flux_factor=self.flux_factor)


    @tag_property(sub=True)
    def voltage_from_flux_par2(self):
        Ej=self.qdt._get_Ej_get_fq(fq=self.ls_f)
        fdf0=self.qdt._get_flux_over_flux0_get_Ej(Ej=Ej)
        flux_d_flux0=append(fdf0, -fdf0)
        flux_d_flux0=append(flux_d_flux0, -fdf0+pi)
        flux_d_flux0=append(flux_d_flux0, fdf0-pi)
        freq=append(self.frequency, self.frequency)
        freq=append(freq, freq)
        return freq, self.qdt._get_voltage(flux_over_flux0=flux_d_flux0, offset=self.offset, flux_factor=self.flux_factor)

    @tag_property(sub=True)
    def ls_flux_par(self):
        return self.qdt._get_ls_flux_parabola(voltage=self.yoko, offset=self.offset, flux_factor=self.flux_factor)

    @tag_property(plot=True, sub=True)
    def Ej(self):
        return self.qdt._get_Ej(Ejmax=self.qdt.Ejmax, flux_over_flux0=self.flux_over_flux0)

    @tag_property(sub=True)
    def flux_over_flux0(self):
        return self.qdt._get_flux_over_flux0(voltage=self.yoko, offset=self.offset, flux_factor=self.flux_factor)


    def _default_indices(self):
        return range(len(self.frequency))
        #return [range(81, 120+1), range(137, 260+1), range(269, 320+1), range(411, 449+1)]#, [490]]#, [186]]

    def fft_filter(self, n):
        myifft=fft.ifft(self.Magcom[:,n])
        myifft[self.filt_end_ind:-self.filt_end_ind]=0.0
        if self.filt_start_ind!=0:
            myifft[:self.filt_start_ind]=0.0
            myifft[-self.filt_start_ind:]=0.0
        return fft.fft(myifft)

    @tag_property(plot=True, sub=True)
    def MagdB(self):
        return 10.0*log10(self.MagAbs)

    @tag_property(plot=True, sub=True)
    def MagAbs(self):
        return absolute(self.Magcom)

    @tag_property(plot=True, sub=True)
    def MagAbsFilt(self):
        return absolute(self.MagcomFilt)#.transpose()-absolute(self.MagcomFilt[:,0])).transpose()

    @tag_property(plot=True, sub=True)
    def MagdBFilt(self):
        return 10.0*log10(self.MagAbsFilt)

    @tag_property(plot=True, sub=True)
    def MagcomFilt(self):
        #return array([fft_filter4(self.Magcom[:,n], self.filt_center) for n in range(len(self.yoko))]).transpose()
        return array([fft_filter3(self.Magcom[:,n], self.filt_start_ind, self.filt_end_ind) for n in range(len(self.yoko))]).transpose()

    @tag_property(sub=True)
    def MagAbsFit(self):
        if self.fit_type=="yoko":
            return sqrt(array([self.fit_func(self.yoko, fp) for fp in self.fit_params]))
        return sqrt(array([self.fit_func(self.fq, fp) for fp in self.fit_params]))

    @tag_property(sub=True)
    def MagdBFit(self):
        return 10*log10(self.MagAbsFit)

    @tag_property(sub=True)
    def fit_params(self):
        return self.full_fano_fit(self.fq)

    @plots
    def widths_plot(self, pl=None):
        scatter(self.frequency[self.indices]/1e9, absolute([fp[0] for fp in self.fit_params]), plotter=pl)
        line(self.frequency/1e9, self.qdt._get_coupling(self.frequency), plotter=pl, color="red")
        return pl

    @plots
    def center_plot(self, pl=None):
        line(self.frequency[self.indices]/1e9, array([fp[1] for fp in self.fit_params]), plotter=pl)
        line(self.frequency/1e9, self.ls_f, plotter=pl, color="red", linewidth=1.0)
        return pl

    @plots
    def heights_plot(self, pl=None):
        pl, pf=line(self.frequency[self.indices]/1e9, array([fp[3]-fp[2] for fp in self.fit_params]))
        return pl

    @plots
    def background_plot(self, pl=None):
        pl, pf=line(self.frequency[self.indices]/1e9, array([fp[2]+fp[3] for fp in self.fit_params]))
        line(self.frequency[self.indices]/1e9, self.MagAbsFilt_sq[self.indices,0], plotter=pl, color="red")
        return pl


    def magabs_colormesh(self):
        pl, pf=colormesh(self.yoko, self.frequency/1e9, self.MagAbs, plotter="magabs_{}".format(self.name))
        pl.set_ylim(min(self.frequency/1e9), max(self.frequency/1e9))
        pl.set_xlim(min(self.yoko), max(self.yoko))
        pl.xlabel="Yoko (V)"
        pl.ylabel="Frequency (GHz)"
        return pl

    def ifft_plot(self):
        p, pf=line(absolute(fft.ifft(self.Magcom[:,self.on_res_ind])), plotter="ifft_{}".format(self.name),
               plot_name="onres_{}".format(self.on_res_ind),label="i {}".format(self.on_res_ind), color="red")
        line(absolute(fft.ifft(self.Magcom[:,self.start_ind])), plotter=p, linewidth=1.0,
             plot_name="strt {}".format(self.start_ind), label="i {}".format(self.start_ind))
        line(absolute(fft.ifft(self.Magcom[:,self.stop_ind])), plotter=p, linewidth=1.0,
             plot_name="stop {}".format(self.stop_ind), label="i {}".format(self.stop_ind))
        return p

    def hann_ifft_plot(self):
        on_res=log10(absolute(hann_ifft(self.Magcom[:,self.on_res_ind])))
        strt=log10(absolute(hann_ifft(self.Magcom[:,self.start_ind])))
        stop=log10(absolute(hann_ifft(self.Magcom[:,self.stop_ind])))

        p, pf=line(on_res, plotter="hann_ifft_{}".format(self.name), color="red",
               plot_name="onres_{}".format(self.on_res_ind),label="i {}".format(self.on_res_ind))
        line(strt, plotter=p, linewidth=1.0,
             plot_name="strt {}".format(self.start_ind), label="i {}".format(self.start_ind))
        line(stop, plotter=p, linewidth=1.0,
             plot_name="stop {}".format(self.stop_ind), label="i {}".format(self.stop_ind))

        filt=filt_prep(len(on_res), self.filt_start_ind, self.filt_end_ind)
        top=max([amax(on_res), amax(strt), amax(stop)])
        line(filt*top, plotter=p, color="green")

        return p

    def filt_compare(self, ind):
        p, pf=line(self.frequency, self.MagdB[:, ind], label="MagAbs (unfiltered)", plotter="filtcomp_{}".format(self.name))
        line(self.frequency, self.MagdBFilt[:, ind], label="MagAbs (filtered)", plotter=p)

    @plots
    def ls_magabsfilt_colormesh(self, pl=None):
        colormesh(self.flux_over_flux0[10:-10], self.ls_f[10:-10]/1e9,
                        self.MagAbsFilt[10:-10, 10:-10], plotter=pl)#"magabsfilt_{}".format(self.name))
        return pl

    @plots
    def magabsfilt_colormesh(self, pl=None, xlabel="$\Phi/\Phi_0$", ylabel="Frequency (GHz)"):
        colormesh(self.flux_over_flux0[10:-10], self.frequency[10:-10]/1e9,
                        self.MagAbsFilt[10:-10, 10:-10], #plot_name="magabsfiltf_{}".format(self.name),
                        plotter=pl, xlabel=xlabel, ylabel=ylabel)
        return pl

    @plots
    def ls_magabsfit_colormesh(self, pl=None, xlabel="$\Phi/\Phi_0$", ylabel="Frequency (GHz)"):
        colormesh(self.flux_over_flux0[10:-10], self.ls_f[self.indices][10:-10]/1e9,
                        self.MagAbsFit[10:-10, 10:-10], plotter=pl, xlabel=xlabel, ylabel=ylabel)
    @plots
    def magabsfit_colormesh(self, pl=None, xlabel="$\Phi/\Phi_0$", ylabel="Frequency (GHz)"):
        colormesh(self.flux_over_flux0[10:-10], self.frequency[self.indices][10:-10]/1e9,
                        self.MagAbsFit[10:-10, 10:-10], plotter=pl, xlabel=xlabel, ylabel=ylabel)

    @plots
    def flux_line(self, pl=None, xlabel="$\Phi/\Phi_0$", ylabel="Frequency (GHz)"):
        xmin, xmax, ymin, ymax=pl.x_min, pl.x_max, pl.y_min, pl.y_max
        line(self.flux_over_flux0[10:-10], self.fq[10:-10]/1e9, plotter=pl, xlabel=xlabel, ylabel=ylabel)
        pl.x_min, pl.x_max, pl.y_min, pl.y_max=xmin, xmax, ymin, ymax
        pl.xlabel="$\Phi/\Phi_0$"
        pl.ylabel="Frequency (GHz)"
        return pl

    def magphasefilt_colormesh(self):
        phase=angle(self.Magcom[10:-10, 10:-10])
        #phasefilt=array([unwrap(phase[:,n], discont=5.5) for n in range(phase.shape[1])])
        phase=(phase.transpose()-phase[:,0]).transpose()
        phasefilt=unwrap(phase, discont=1.5, axis=1)
        #phasefilt=phasefilt-phasefilt[0, :]
        pl, pf=colormesh(self.flux_over_flux0[10:-10], self.frequency[10:-10]/1e9,
                         phasefilt, plotter="magphasefilt_{}".format(self.name))
        #print self.voltage_from_flux_par2[0].shape,self.voltage_from_flux_par2[1].shape
        #line(self.voltage_from_flux_par2[0]/1e9, self.voltage_from_flux_par2[1], plotter=p)
        #print max(self.voltage_from_flux_par), min(self.voltage_from_flux_par)
        pl.xlabel="Yoko (V)"
        pl.ylabel="Frequency (GHz)"
        return pl

    def magabsfilt2_colormesh(self):
        p, pf=colormesh(self.frequency[10:-10]/1e9, self.yoko[10:-10],
                        self.MagAbsFilt.transpose()[10:-10, 10:-10], plotter="magabsfilt2_{}".format(self.name))
        print self.voltage_from_flux_par2[0].shape,self.voltage_from_flux_par2[1].shape
        line(self.voltage_from_flux_par2[0]/1e9, self.voltage_from_flux_par2[1], plotter=p)
        #print max(self.voltage_from_flux_par), min(self.voltage_from_flux_par)
        p.xlabel="Yoko (V)"
        p.ylabel="Frequency (GHz)"
        return p

    def magdBfilt_colormesh(self):
        return colormesh(self.yoko, self.frequency/1e9, self.MagdBFilt, plotter="magdBfilt_{}".format(self.name),
                    xlabel="Yoko (V)", ylabel="Frequency (GHz)")

    def magdBfiltbgsub_colormesh(self):
        return colormesh(self.yoko, self.frequency/1e9, (self.MagdBFilt.transpose()-self.MagdBFilt[:, self.start_ind]).transpose(),
                         plotter="magdBfiltbgsub_{}".format(self.name), xlabel="Yoko (V)", ylabel="Frequency (GHz)")

    @tag_property(plot=True, sub=True)
    def MagAbsFilt_sq(self):
        return (self.MagAbsFilt)**2

    def full_fano_fit(self, fq):
        log_debug("started fano fitting")
        fit_params=[self.fano_fit(n, fq)  for n in self.indices]
        #fit_params=array(zip(*fit_params))
        log_debug("ended fano fitting")
        return fit_params

    def full_fano_fit2(self):
        MagAbsFilt_sq=self.MagAbsFilt**2
        return full_fano_fit(self.fit_func, self.p_guess, MagAbsFilt_sq, self.fq, indices=self.indices)

        #fit_params=[full_fano_fit(self.fit_func, self.p_guess, MagAbsFilt_sq[n, :], self.fq) for n in self.indices]
        #fit_params=array(zip(*fit_params))
        #return fit_params

    def full_fano_fit3(self):
        MagAbsFilt_sq=self.MagAbsFilt**2
        return full_fit(lorentzian2, self.p_guess, MagAbsFilt_sq, self.fq, indices=self.indices)

    def plot_widths(self, plotter=None):
        fit_params=self.full_fano_fit()
        scatter(fit_params[0, :], absolute(fit_params[1, :]), color="red", label=self.name, plot_name="widths_{}".format(self.name), plotter=plotter)

    def resid_func(self, p, y, x):
        """residuals of fitting function"""
        return y-self.fit_func(x, p)

    def fano_fit(self, n, fq):
        dat=self.MagAbsFilt_sq[n, :]
        datamax=max(dat)
        datamin=min(dat)
        if self.fit_type=="yoko":
            p_guess=[0.2, self.yoko[self.on_res_ind], datamax-datamin, dat[0]]
            pbest= leastsq(self.resid_func, p_guess, args=(dat, self.yoko), full_output=1)
        else:
            p_guess=[self.qdt._get_coupling(self.frequency[n]), self.ls_f[n], datamax-datamin, dat[0]]
            pbest= leastsq(self.resid_func, p_guess, args=(dat, fq), full_output=1)
        best_parameters = pbest[0]
        return (best_parameters[0], best_parameters[1], best_parameters[2], best_parameters[3])
Exemple #5
0
class Sat_Qubit(Qubit):
    atten = Float(83.0)
    phi_arr = Array()
    pwr_arr = Array()
    frq_arr = Array()

    do_ls = Bool(True)
    harm_osc = Bool(False)

    Np = Int(9)
    f0 = Float(5.30001e9)

    def _default_phi_arr(self):
        return linspace(0.35, 0.4, 2 * 150) * pi

    def _default_pwr_arr(self):
        return linspace(-50.0, 0, 31)

    def _default_frq_arr(self):
        return linspace(3.5e9, 7.5e9, 51)

    gamma = Float(38.0e6)
    gamma_el = Float(0.750e6)
    gamma_phi = Float(0.0)

    T = Float(0.03)
    N_dim = Int(8)

    fd = Float(4.5e9)

    Zc = Float(50.0)

    Ic = Float(112.0e-9)

    def _get_fTvec(self, phi, gamma, Delta, fd, Psaw):
        C = self.Ct * (1.0 + 2.0 * Delta / fd) + self.Cc
        Ec = e**2 / (2 * C)
        Ecvec = -Ec * (6.0 * self.nvec**2 + 6.0 * self.nvec + 3.0) / 12.0

        Isq = 0.0 * 4.0 * gamma * 2.0 * (self.Cc + self.Ct) * Psaw * 1  #+0.0j
        if Isq < self.Ic**2:
            Ej = self.Ejmax * absolute(cos(phi)) * sqrt(
                1.0 - Isq / self.Ic**2)  #Josephson energy as function of Phi.
        else:
            Ej = 0.0  #print sqrt(Isq)
        if self.harm_osc:
            return sqrt(8.0 * Ej * Ec) * (self.nvec + 0.5) / h
        return (-Ej + sqrt(8.0 * Ej * Ec) *
                (self.nvec + 0.5) + Ecvec) / h  #\omega_m
        #return 0.0*(-Ej + 1.0*sqrt(8.0*Ej*self.Ec)*(self.nvec+0.5)+self.Ecvec)/h #\omega_m

    def _get_X(self, f, f0, Np):
        return Np * pi * (f - f0) / f0

    def _get_GammaDelta(self, gamma, fd, f0, Np):
        if not self.do_ls:
            return gamma, 0.0
        X = self._get_X(f=fd, f0=f0, Np=Np)
        Delta = gamma * (sin(2 * X) - 2 * X) / (2 * X**2)
        Gamma = gamma * (sin(X) / X)**2
        return Gamma, Delta

    Gamma_C = SProperty()

    @Gamma_C.getter
    def _get_Gamma_C(self, fd, Cc, Ct, Zc):
        return 2 * pi * (Zc * Cc**2 * fd**2) / (4 * (Cc + Ct))

    N_gamma = SProperty()

    @N_gamma.getter
    def _get_N_gamma(self, fd, T):
        return 1.0 / (exp(h * fd / (k * T)) - 1.0)

    @private_property
    def a_op(self):
        return destroy(self.N_dim)

    @private_property
    def a_dag(self):
        return self.a_op.dag()

    @private_property
    def tdiag(self):
        return Qobj(diag(range(0, 2 * self.N_dim,
                               2)))  #dephasing operator, tdiag

    c_ops = SProperty().tag(sub=True)

    @c_ops.getter
    def _get_c_ops(self, gamma, N_gamma, a_op, a_dag, tdiag, gamma_phi):
        rate1 = gamma * (1 + N_gamma)
        rate2 = gamma * N_gamma
        return [sqrt(rate1) * a_op, sqrt(rate2) * a_dag, gamma_phi * tdiag]

    @private_property
    def nvec(self):
        return arange(self.N_dim)

    @private_property
    def fdvec(self):
        return self.nvec * self.fd

    @private_property
    def Ecvec(self):
        return -self.Ec * (6.0 * self.nvec**2 + 6.0 * self.nvec + 3.0) / 12.0

    @private_property
    def pwr_lin(self):
        pwr_fridge = self.pwr_arr - self.atten
        return 0.001 * 10**(pwr_fridge / 10.0)

    @private_property
    def Omega_arr(self):
        return sqrt(self.pwr_lin / h * 2.0)
        #pwr_fridge=self.pwr_arr-self.atten
        #return sqrt(0.001*10**(pwr_fridge/10.0)/(h*a.fd))*sqrt(2*self.gamma_el)

    @private_property
    def value_grid(self):
        value_grid = array(meshgrid(self.phi_arr, self.frq_arr))
        #value_grid=array(meshgrid(self.phi_arr, self.Omega_arr))
        return zip(value_grid[0, :, :].flatten(),
                   value_grid[1, :, :].flatten())

    funcer = Callable()
    funcer2 = Callable()

    @private_property
    def value_grid2(self):
        value_grid = array(meshgrid(self.phi_arr, self.pwr_arr))
        return zip(value_grid[0, :, :].flatten(),
                   value_grid[1, :, :].flatten())

    power_plot = Bool(True)
    acoustic_plot = Bool(True)

    @private_property
    def fexpt(self):
        self.power_plot = False
        fexpt = parallel_map(self.funcer, self.value_grid, progress_bar=True)
        return reshape(fexpt, (len(self.frq_arr), len(self.phi_arr)))

    @private_property
    def fexpt2(self):
        self.power_plot = True
        fexpt = parallel_map(self.funcer, self.value_grid2, progress_bar=True)
        #print shape(self.value_grid2)
        #print self.pwr_arr.shape
        #print self.phi_arr.shape
        #print shape(fexpt)
        return reshape(fexpt, (len(self.pwr_arr), len(self.phi_arr)))

    def find_expect(self, vg, pwr, fd):
        if self.power_plot:
            phi, pwr = vg
        else:
            phi, fd = vg
        pwr_fridge = pwr - self.atten
        lin_pwr = 0.001 * 10**(pwr_fridge / 10.0)
        Omega = sqrt(lin_pwr / h * 2.0)

        gamma, Delta = self._get_GammaDelta(fd=fd,
                                            f0=self.f0,
                                            Np=self.Np,
                                            gamma=self.gamma)
        g_el = self._get_Gamma_C(fd=fd)
        wTvec = self._get_fTvec(phi=phi,
                                gamma=gamma,
                                Delta=Delta,
                                fd=fd,
                                Psaw=lin_pwr)

        if self.acoustic_plot:
            Om = Omega * sqrt(gamma / fd)
        else:
            Om = Omega * sqrt(g_el / fd)
        wT = wTvec - fd * self.nvec  #rotating frame of gate drive \omega_m-m*\omega_\gate
        transmon_levels = Qobj(diag(wT[range(self.N_dim)]))
        rate1 = (gamma + g_el) * (1.0 + self.N_gamma)
        rate2 = (gamma + g_el) * self.N_gamma
        c_ops = [sqrt(rate1) * self.a_op,
                 sqrt(rate2) * self.a_dag
                 ]  #, sqrt(rate3)*self.a_op, sqrt(rate4)*self.a_dag]
        Omega_vec = -0.5j * (Om * self.a_dag - conj(Om) * self.a_op)
        H = transmon_levels + Omega_vec
        final_state = steadystate(H, c_ops)  #solve master equation
        fexpt = expect(self.a_op,
                       final_state)  #expectation value of relaxation operator
        #return fexpt
        if self.acoustic_plot:
            return 1.0 * gamma / Om * fexpt
        else:
            return 1.0 * sqrt(g_el * gamma) / Om * fexpt
Exemple #6
0
class VNA_Lyzer(Lyzer):
    base_name = "vna_lyzer"

    def _default_read_data(self):
        return read_data

    filter_type = Enum("None", "FFT", "FIR", "Fit")
    bgsub_type = Enum("None", "Complex", "Abs", "dB")
    flux_axis_type = Enum("yoko", "flux", "fq")
    freq_axis_type = Enum("f", "ls_f")
    time_axis_type = Enum("points", "time", "fft_points")
    calc_p_guess = Bool(False)
    show_quick_fit = Bool(True)

    def _observe_filter_type(self, change):
        if self.filter_type == "FIR":
            self.filt.filter_type = "FIR"
        elif self.filter_type == "FFT":
            self.filt.filter_type = "FFT"

    @tag_property(sub=True)
    def flux_axis(self):
        if self.flux_axis_type == "yoko":
            return self.yoko
        elif self.flux_axis_type == "flux":
            return self.flux_over_flux0 / pi
        elif self.flux_axis_type == "fq":
            return self.fq / 1e9

    @tag_property(sub=True)
    def freq_axis(self):
        if self.flux_axis_type == "ls_f":
            return self.ls_f / 1e9
        return self.frequency / 1e9

    @t_property()
    def flux_axis_label(self):
        return {
            "yoko": "Yoko (V)",
            "flux": r"$\Phi/\Phi_0$",
            "fq": "Qubit Frequency (GHz)"
        }[self.flux_axis_type]

    @t_property()
    def freq_axis_label(self):
        return {
            "f": "Frequency (GHz)",
            "ls_f": "LS Frequency (GHz)"
        }[self.freq_axis_type]

    @tag_property(sub=True)
    def time_axis(self):
        if self.time_axis_type == "time":
            return self.ifft_time / 1e-6
        elif self.time_axis_type == "points":
            return arange(len(self.frequency))
        elif self.time_axis_type == "fft_points":
            return self.filt.fftshift(arange(len(self.frequency)))

    @t_property()
    def time_axis_label(self):
        return {
            "time": "Time (us)",
            "points": "Points",
            "fft_points": "FFT Points"
        }[self.time_axis_type]

    frequency = Array().tag(unit="GHz", plot=True, label="Frequency", sub=True)
    yoko = Array().tag(unit="V", plot=True, label="Yoko", sub=True)
    MagcomData = Array().tag(sub=True, desc="raw data in compex form")
    probe_pwr = Float().tag(label="Probe power",
                            read_only=True,
                            display_unit="dBm/mW")

    on_res_ind = Int()
    start_ind = Int()
    stop_ind = Int()

    flux_indices = List()

    def _default_flux_indices(self):
        return [range(len(self.yoko))]

    @tag_property(sub=True)
    def flat_flux_indices(self):
        return [n for ind in self.flux_indices for n in ind]

    fit_indices = List()

    def _default_fit_indices(self):
        return [range(len(self.frequency))]

    @tag_property(sub=True)
    def flat_indices(self):
        return [n for ind in self.fit_indices for n in ind]

    end_skip = Int(0)

    @tag_property(sub=True)
    def indices(self):
        if self.filter_type == "Fit":
            return self.flat_indices  #[n for ind in self.fit_indices for n in ind]
        elif self.filter_type in ("FFT", "Fir"):
            return range(self.end_skip, len(self.frequency) - self.end_skip)
        return range(len(self.frequency))

    port_name = Unicode('S21')
    VNA_name = Unicode("RS VNA")

    filt = Typed(Filter, ())
    fitter = Typed(LorentzianFitter, ())

    bgsub_start_ind = Int(0)
    bgsub_stop_ind = Int(1)
    bgsub_axis = Int(1)

    @tag_property(plot=True, sub=True)
    def fq(self):
        return self.qdt._get_fq(Ej=self.Ej, Ec=self.qdt.Ec)

    @tag_property(sub=True)
    def ls_f(self):
        #return array([f-self.qdt._get_Lamb_shift(f=f) for f in self.frequency])
        return array([
            sqrt(f * (f - 2 * self.qdt._get_Lamb_shift(f=f)))
            for f in self.frequency
        ])

    @tag_property(sub=True)
    def voltage_from_flux_par(self):
        Ej = self.qdt._get_Ej_get_fq(fq=self.ls_f)
        flux_d_flux0 = self.qdt._get_flux_over_flux0_get_Ej(Ej=Ej)
        return self.qdt._get_voltage(flux_over_flux0=flux_d_flux0,
                                     offset=self.offset,
                                     flux_factor=self.flux_factor)

    def voltage_from_frequency(self, frq):
        ls_f = array(
            [sqrt(f * (f - 2 * self.qdt._get_Lamb_shift(f=f))) for f in frq])
        Ej = self.qdt._get_Ej_get_fq(fq=ls_f)
        flux_d_flux0 = self.qdt._get_flux_over_flux0_get_Ej(Ej=Ej)
        return self.qdt._get_voltage(flux_over_flux0=-flux_d_flux0 + pi,
                                     offset=self.offset,
                                     flux_factor=self.flux_factor)

    @tag_property(sub=True)
    def voltage_from_flux_par2(self):
        Ej = self.qdt._get_Ej_get_fq(fq=self.ls_f)
        fdf0 = self.qdt._get_flux_over_flux0_get_Ej(Ej=Ej)
        flux_d_flux0 = append(fdf0, -fdf0)
        flux_d_flux0 = append(flux_d_flux0, -fdf0 + pi)
        flux_d_flux0 = append(flux_d_flux0, fdf0 - pi)
        freq = append(self.frequency, self.frequency)
        freq = append(freq, freq)
        return freq, self.qdt._get_voltage(flux_over_flux0=flux_d_flux0,
                                           offset=self.offset,
                                           flux_factor=self.flux_factor)

    @tag_property(sub=True)
    def ls_flux_par(self):
        return self.qdt._get_ls_flux_parabola(voltage=self.yoko,
                                              offset=self.offset,
                                              flux_factor=self.flux_factor)

    @tag_property(plot=True, sub=True)
    def Ej(self):
        return self.qdt._get_Ej(Ejmax=self.qdt.Ejmax,
                                flux_over_flux0=self.flux_over_flux0)

    @tag_property(sub=True)
    def flux_over_flux0(self):
        return self.qdt._get_flux_over_flux0(voltage=self.yoko,
                                             offset=self.offset,
                                             flux_factor=self.flux_factor)

    @tag_property(plot=True, sub=True)
    def MagdB(self):
        if self.bgsub_type == "dB":
            return self.bgsub(10.0 * log10(absolute(self.Magcom)))
        return 10.0 * log10(self.MagAbs)

    def bgsub(self, arr):
        return bgsub2D(arr, self.bgsub_start_ind, self.bgsub_stop_ind,
                       self.bgsub_axis)

    @tag_property(plot=True, sub=True)
    def MagAbs(self):
        if self.bgsub_type == "dB":
            return 10.0**(self.MagdB / 10.0)
        magabs = absolute(self.Magcom)
        if self.bgsub_type == "Abs":
            return self.bgsub(magabs)
        return magabs

    @tag_property(plot=True, sub=True)
    def MagAbs_sq(self):
        return (self.MagAbs)**2

    @tag_property(plot=True, sub=True)
    def Phase(self):
        return angle(self.Magcom)
        return unwrap(angle(self.Magcom).transpose() -
                      angle(self.Magcom)[:, 0],
                      discont=6,
                      axis=0).transpose()
        #return ( self.bgsub(angle(self.Magcom)) + pi) % (2 * pi ) - pi
        return self.bgsub(angle(self.Magcom))

    @tag_property(sub=True)
    def Magcom(self):
        if self.filter_type == "None":
            Magcom = self.MagcomData
        elif self.filter_type == "Fit":
            Magcom = self.MagAbsFit
        else:
            Magcom = self.MagcomFilt[self.indices, :]
        if self.bgsub_type == "Complex":
            return self.bgsub(Magcom)
        return Magcom

    @tag_property(sub=True)
    def ifft_time(self):
        return self.filt.ifft_x(self.frequency)

    @private_property
    def MagcomFilt(self):
        if self.filt.filter_type == "FIR":
            return array([
                self.filt.fir_filter(self.MagcomData[:, n])
                for n in self.flat_flux_indices
            ]).transpose()
        return array([
            self.filt.fft_filter(self.MagcomData[:, n])
            for n in self.flat_flux_indices
        ]).transpose()

    @tag_property(plot=True, sub=True)
    def MagAbsFilt_sq(self):
        return absolute(self.MagcomFilt)**2

    @private_property
    def fit_params(self):
        if self.fitter.fit_params is None:
            self.fitter.full_fit(x=self.flux_axis[self.flat_flux_indices],
                                 y=self.MagAbsFilt_sq,
                                 indices=self.flat_indices,
                                 gamma=self.fitter.gamma)
            if self.calc_p_guess:
                self.fitter.make_p_guess(
                    self.flux_axis[self.flat_flux_indices],
                    y=self.MagAbsFilt_sq,
                    indices=self.flat_indices,
                    gamma=self.fitter.gamma)
        return self.fitter.fit_params

    @private_property
    def MagAbsFit(self):
        return sqrt(
            self.fitter.reconstruct_fit(self.flux_axis[self.flat_flux_indices],
                                        self.fit_params))

    def widths_plot(self, **kwargs):
        process_kwargs(self,
                       kwargs,
                       pl="widths_{0}_{1}_{2}".format(self.filter_type,
                                                      self.bgsub_type,
                                                      self.name))
        pl = scatter(self.freq_axis[self.flat_indices],
                     absolute([fp[0] for fp in self.fit_params]), **kwargs)
        if self.show_quick_fit:
            if self.flux_axis_type == "fq":
                #line(self.freq_axis[self.indices], self.qdt._get_coupling(f=self.frequency[self.indices])/1e9, plotter=pl, color="red")
                line(self.freq_axis[self.indices],
                     self.qdt._get_fFWHM(f=self.frequency[self.indices])[2] /
                     2.0 / 1e9,
                     plotter=pl,
                     color="red")
            elif self.flux_axis_type == "yoko":
                line(
                    self.freq_axis[self.indices],
                    self.qdt._get_VfFWHM(f=self.frequency[self.indices])[2] /
                    2.0,
                    pl=pl,
                    color="red"
                )  #self.voltage_from_frequency(self.qdt._get_coupling(self.frequency)), plotter=pl, color="red")
            else:
                line(
                    self.freq_axis[self.indices],
                    self.qdt._get_fluxfFWHM(f=self.frequency[self.indices])[2]
                    / 2.0,
                    pl=pl,
                    color="red"
                )  #self.voltage_from_frequency(self.qdt._get_coupling(self.frequency)), plotter=pl, color="red")
            if self.fitter.p_guess is not None:
                line(
                    self.freq_axis[self.flat_indices],
                    array([pg[0] for pg in self.fitter.p_guess]),
                    pl=pl,
                    color="green"
                )  #self.voltage_from_frequency(self.qdt._get_coupling(self.frequency)), plotter=pl, color="red")
        return pl

    def center_plot(self, **kwargs):
        process_kwargs(self,
                       kwargs,
                       pl="center_{0}_{1}_{2}".format(self.filter_type,
                                                      self.bgsub_type,
                                                      self.name))
        pl = scatter(self.freq_axis[self.flat_indices],
                     array([fp[1] for fp in self.fit_params]), **kwargs)
        if self.show_quick_fit:
            if self.flux_axis_type == "fq":
                line(self.freq_axis[self.indices],
                     self.ls_f[self.indices] / 1e9,
                     plotter=pl,
                     color="red",
                     linewidth=1.0)
            elif self.flux_axis_type == "yoko":
                line(self.freq_axis[self.indices],
                     self.qdt._get_Vfq0(f=self.frequency[self.indices]),
                     plotter=pl,
                     color="red",
                     linewidth=1.0)
            else:
                line(self.freq_axis,
                     self.qdt._get_fluxfq0(f=self.frequency),
                     plotter=pl,
                     color="red",
                     linewidth=1.0)
            if self.fitter.p_guess is not None:
                line(
                    self.freq_axis[self.indices],
                    array([pg[1] for pg in self.fitter.p_guess]),
                    pl=pl,
                    color="green",
                    linewidth=1.0
                )  #self.voltage_from_frequency(self.qdt._get_coupling(self.frequency)), plotter=pl, color="red")
        return pl

    def heights_plot(self, pl=None):
        pl = line(self.freq_axis[self.flat_indices],
                  array([fp[2] for fp in self.fit_params]),
                  pl=pl)
        if self.show_quick_fit:
            if self.fitter.p_guess is not None:
                line(
                    self.freq_axis[self.flat_indices],
                    array([pg[2] for pg in self.fitter.p_guess]),
                    pl=pl,
                    color="green",
                    linewidth=1.0
                )  #self.voltage_from_frequency(self.qdt._get_coupling(self.frequency)), plotter=pl, color="red")
        return pl

    def background_plot(self, pl=None):
        pl = line(self.freq_axis[self.flat_indices],
                  array([fp[2] + fp[3] for fp in self.fit_params]),
                  pl=pl)
        line(self.freq_axis[self.indices],
             self.MagAbsFilt_sq[self.indices, 0],
             plotter=pl,
             color="red",
             linewidth=1.0,
             alpha=0.5)
        if self.show_quick_fit:
            if self.fitter.p_guess is not None:
                line(self.freq_axis[self.flat_indices],
                     array([pg[2] + pg[3] for pg in self.fitter.p_guess]),
                     pl=pl,
                     color="green",
                     linewidth=0.5)
        return pl

    def magabs_colormesh(self, **kwargs):
        process_kwargs(self,
                       kwargs,
                       pl="magabs_{0}_{1}_{2}".format(self.filter_type,
                                                      self.bgsub_type,
                                                      self.name))
        if self.filter_type == "Fit":
            flux_axis = self.flux_axis[self.flat_flux_indices]
            freq_axis = self.freq_axis[self.indices]
            start_ind = 0
            for ind in self.fit_indices:
                pl = colormesh(flux_axis, self.freq_axis[ind],
                               self.MagAbs[start_ind:start_ind + len(ind), :],
                               **kwargs)
                start_ind += len(ind)
        elif self.filter_type == "None":
            flux_axis = self.flux_axis
            freq_axis = self.freq_axis
            pl = colormesh(self.flux_axis, self.freq_axis, self.MagAbs,
                           **kwargs)
        else:
            flux_axis = self.flux_axis[self.flat_flux_indices]
            freq_axis = self.freq_axis[self.indices]
            pl = colormesh(flux_axis, freq_axis, self.MagAbs, **kwargs)
        if isinstance(pl, tuple):
            pl, pf = pl
        else:
            pf = None
        if pl.auto_ylim:
            pl.set_ylim(min(freq_axis), max(freq_axis))
        if pl.auto_xlim:
            pl.set_xlim(min(flux_axis), max(flux_axis))
        pl.xlabel = kwargs.pop("xlabel", self.flux_axis_label)
        pl.ylabel = kwargs.pop("ylabel", self.freq_axis_label)
        if pf is None:
            return pl
        return pl, pf

    def magdB_colormesh(self, **kwargs):
        process_kwargs(self,
                       kwargs,
                       pl="magdB_{0}_{1}_{2}".format(self.filter_type,
                                                     self.bgsub_type,
                                                     self.name))
        if self.filter_type == "Fit":
            flux_axis = self.flux_axis[self.flat_flux_indices]
            freq_axis = self.freq_axis[self.indices]
            start_ind = 0
            for ind in self.fit_indices:
                pl = colormesh(flux_axis, self.freq_axis[ind],
                               self.MagdB[start_ind:start_ind + len(ind), :],
                               **kwargs)
                start_ind += len(ind)
        elif self.filter_type == "None":
            flux_axis = self.flux_axis
            freq_axis = self.freq_axis
            pl = colormesh(self.flux_axis, self.freq_axis, self.MagdB,
                           **kwargs)
        else:
            flux_axis = self.flux_axis[self.flat_flux_indices]
            freq_axis = self.freq_axis[self.indices]
            pl = colormesh(flux_axis, freq_axis, self.MagdB, **kwargs)
        if isinstance(pl, tuple):
            pl, pf = pl
        else:
            pf = None
        if pl.auto_ylim:
            pl.set_ylim(min(freq_axis), max(freq_axis))
        if pl.auto_xlim:
            pl.set_xlim(min(flux_axis), max(flux_axis))
        pl.xlabel = kwargs.pop("xlabel", self.flux_axis_label)
        pl.ylabel = kwargs.pop("ylabel", self.freq_axis_label)
        if pf is None:
            return pl
        return pl, pf

    def phase_colormesh(self, **kwargs):
        process_kwargs(self,
                       kwargs,
                       pl="phase_{0}_{1}_{2}".format(self.filter_type,
                                                     self.bgsub_type,
                                                     self.name))
        if self.filter_type == "Fit":
            start_ind = 0
            for ind in self.fit_indices:
                pl = colormesh(self.flux_axis, self.freq_axis[ind],
                               self.Phase[start_ind:start_ind + len(ind), :],
                               **kwargs)
                start_ind += len(ind)
        else:
            pl = colormesh(self.flux_axis, self.freq_axis[self.indices],
                           self.Phase, **kwargs)
        pl.set_ylim(min(self.freq_axis[self.indices]),
                    max(self.freq_axis[self.indices]))
        pl.set_xlim(min(self.flux_axis), max(self.flux_axis))
        pl.xlabel = kwargs.pop("xlabel", self.flux_axis_label)
        pl.ylabel = kwargs.pop("ylabel", self.freq_axis_label)
        return pl

    def ifft_plot(self, **kwargs):
        process_kwargs(self,
                       kwargs,
                       pl="hannifft_{0}_{1}_{2}".format(
                           self.filter_type, self.bgsub_type, self.name))
        on_res = absolute(
            self.filt.window_ifft(self.Magcom[:, self.on_res_ind]))
        strt = absolute(self.filt.window_ifft(self.Magcom[:, self.start_ind]))
        stop = absolute(self.filt.window_ifft(self.Magcom[:, self.stop_ind]))

        pl = line(self.time_axis,
                  self.filt.fftshift(on_res),
                  color="red",
                  plot_name="onres_{}".format(self.on_res_ind),
                  label="{:.4g}".format(self.flux_axis[self.on_res_ind]),
                  **kwargs)
        line(self.time_axis,
             self.filt.fftshift(strt),
             pl=pl,
             linewidth=1.0,
             color="purple",
             plot_name="strt {}".format(self.start_ind),
             label="{:.4g}".format(self.flux_axis[self.start_ind]))
        line(self.time_axis,
             self.filt.fftshift(stop),
             pl=pl,
             linewidth=1.0,
             color="blue",
             plot_name="stop {}".format(self.stop_ind),
             label="{:.4g}".format(self.flux_axis[self.stop_ind]))

        self.filt.N = len(on_res)
        filt = self.filt.freqz
        #filt=filt_prep(len(on_res), self.filt_start_ind, self.filt_end_ind)
        top = max([amax(on_res), amax(strt), amax(stop)])
        line(self.time_axis,
             filt * top,
             plotter=pl,
             color="green",
             label="wdw")
        pl.xlabel = kwargs.pop("xlabel", self.time_axis_label)
        pl.ylabel = kwargs.pop("ylabel", "Mag abs")
        return pl

    def ifft_plot_time(self, **kwargs):
        process_kwargs(self,
                       kwargs,
                       pl="hannifft{0}{1}_{2}".format(self.filter_type,
                                                      self.bgsub_type,
                                                      self.name))
        on_res = absolute(
            self.filt.window_ifft(self.MagcomData[:, self.on_res_ind]))
        strt = absolute(
            self.filt.window_ifft(self.MagcomData[:, self.start_ind]))
        stop = absolute(
            self.filt.window_ifft(self.MagcomData[:, self.stop_ind]))

        self.filt.N = len(on_res)
        pl = line(self.ifft_time / 1e-6,
                  self.filt.fftshift(on_res),
                  color="red",
                  plot_name="onres_{}".format(self.on_res_ind),
                  label="i {}".format(self.on_res_ind),
                  **kwargs)
        line(self.ifft_time / 1e-6,
             self.filt.fftshift(strt),
             pl=pl,
             linewidth=1.0,
             plot_name="strt {}".format(self.start_ind),
             label="i {}".format(self.start_ind))
        line(self.ifft_time / 1e-6,
             self.filt.fftshift(stop),
             pl=pl,
             linewidth=1.0,
             plot_name="stop {}".format(self.stop_ind),
             label="i {}".format(self.stop_ind))

        filt = self.filt.freqz
        #filt=filt_prep(len(on_res), self.filt_start_ind, self.filt_end_ind)
        top = max([amax(on_res), amax(strt), amax(stop)])
        line(self.ifft_time / 1e-6, filt * top, plotter=pl, color="green")
        pl.xlabel = kwargs.pop("xlabel", "Time (us)")
        pl.ylabel = kwargs.pop("ylabel", "Time (us)")
        return pl

    def MagdB_cs(self, pl, ind):
        pl, pf = line(self.frequency,
                      self.MagdB[:, ind],
                      label="MagAbs (unfiltered)",
                      plotter="filtcomp_{}".format(self.name))
        line(self.frequency,
             self.MagdBFilt[:, ind],
             label="MagAbs (filtered)",
             plotter=pl)
        return pl

    def filt_compare(self, ind, **kwargs):
        process_kwargs(self,
                       kwargs,
                       pl="filtcomp_{0}_{1}_{2}".format(
                           self.filter_type, self.bgsub_type, self.name))
        self.filter_type = "None"
        pl = line(self.frequency,
                  self.MagdB[:, ind],
                  label="MagAbs (unfiltered)",
                  **kwargs)
        self.filter_type = "FFT"
        line(self.frequency,
             self.MagdB[:, ind],
             label="MagAbs (filtered)",
             plotter=pl)
        return pl
Exemple #7
0
class Qubit(Agent):
    """Theoretical description of qubit"""
    base_name="qubit"

    Cc=Float(1e-15).tag(desc="coupling capacitance", unit="fF")

    qubit_type=Enum("transmon", "scb")

    dephasing=Float(0.0).tag(unit="GHz")
    dephasing_slope=Float(0.0)

    @private_property
    def view_window(self):
        return QubitView(agent=self)

    superconductor=Enum("Al").tag(label="material")

    def _observe_superconductor(self, change):
        if self.superconductor=="Al":
            self.Delta=Delta_Al

    Tc=Float(Tc_Al).tag(desc="Critical temperature of superconductor", unit="K", label="Critical temperature")

    Delta=SProperty().tag(label="Gap", tex_str=r"$\Delta(0)$", unit="ueV", desc="BCS superconducting gap, 200 ueV for Al",
                     reference="BCS", expression=r"$\Delta(0)=1.764 k_B T_c$")
    @Delta.getter
    def _get_Delta(self, Tc):
        """BCS theory superconducting gap"""
        return 1.764*kB*Tc

    @Delta.setter
    def _get_Tc(self, Delta):
        return Delta/(1.764*kB)

    loop_width=Float(1.0e-6).tag(desc="loop width of SQUID", unit="um", label="loop width")
    loop_height=Float(1.0e-6).tag(desc="loop height of SQUID", unit="um", label="loop height")

    loop_area=SProperty().tag(desc="Area of SQUID loop", unit="um^2", expression="$width \times height$",
                     comment="Loop width times loop height", label="loop area")
    @loop_area.getter
    def _get_loop_area(self, loop_width, loop_height):
        return loop_width*loop_height

    Ct=Float(1.3e-13).tag(desc="shunt capacitance", unit="fF", tex_str=r"$C_q$")

    Rn=Float(5.0e3).tag(desc="Normal resistance of SQUID", unit="kOhm", label="DC Junction resistance", expression=r"$R_N$")

    Ic=SProperty().tag(desc="critical current of SQUID, Ambegaokar Baratoff formula", unit="nA", label="Critical current",
             expression=r"$I_C=\pi \Delta/(2e R_N)$")
    @Ic.getter
    def _get_Ic(self, Rn, Delta):
        """Ic*Rn=pi*Delta/(2.0*e) #Ambegaokar Baratoff formula"""
        return pi*Delta/(2.0*e)/Rn

    @Ic.setter
    def _get_Rn(self, Ic, Delta):
        """Ic*Rn=pi*Delta/(2.0*e) #Ambegaokar Baratoff formula"""
        return pi*Delta/(2.0*e)/Ic


    Ejmax=SProperty().tag(desc="""Max Josephson Energy""", unit="hGHz", expression=r'$E_{Jmax}=\hbar I_C/2e$', label="Max Josephson energy")#, unit_factor=1.0e9*h)
    @Ejmax.getter
    def _get_Ejmax(self, Ic):
        """Josephson energy"""
        return hbar*Ic/(2.0*e)

    @Ejmax.setter
    def _get_Ic_get_Ejmax(self, Ejmax):
        """inverse Josephson energy"""
        return Ejmax*(2.0*e)/hbar

    Ec=SProperty().tag(desc="Charging Energy", unit="hGHz", label="Charging energy", expression=r"$E_C=e^2/2 C_t$")#, unit_factor=1.0e9*h)
    @Ec.getter
    def _get_Ec(self, Ct, Cc):
        """Charging energy"""
        return e**2/(2.0*(Ct+Cc))

    @Ec.setter
    def _get_Ct(self, Ec, Cc):
        """inverse charging energy"""
        return e**2/(2.0*Ec)-Cc

    @Ec.setter
    def _get_Ejmax_get_Ec(self, Ec, EjmaxdivEc):
        return EjmaxdivEc*Ec

    EjmaxdivEc=SProperty().tag(desc="Maximum Ej over Ec", label=r"Maximum $E_J$ over $E_C$", expression=r"$E_{Jmax}/E_C$")
    @EjmaxdivEc.getter
    def _get_EjmaxdivEc(self, Ejmax, Ec):
        return Ejmax/Ec

    Ej=SProperty().tag(unit="hGHz", label="Josephson energy", expression=r"$E_J=E_{Jmax}|\cos(\Phi/\Phi_0)|$")
    @Ej.getter
    def _get_Ej(self, Ejmax, flux_over_flux0):
        return Ejmax*absolute(cos(flux_over_flux0)) #*pi

    @Ej.setter
    def _get_flux_over_flux0_get_Ej(self, Ej, Ejmax):
        return arccos(Ej/Ejmax)#/pi

    EjdivEc=SProperty().tag(desc="Ej over Ec", label="Ej over Ec", expression=r"$E_J/E_C$")
    @EjdivEc.getter
    def _get_EjdivEc(self, Ej, Ec):
        return Ej/Ec

    fq_approx_max=SProperty().tag(unit="GHz", label="fq approx max", desc="qubit frequency using approximate transmon formula",
                  expression=r"$f_{qmax} \approx (\sqrt{8E_{Jmax} E_C}-E_C)/h$")
    @fq_approx_max.getter
    def _get_fq_approx_max(self, Ejmax, Ec):
        return self._get_fq_approx(Ej=Ejmax, Ec=Ec)

    fq_approx=SProperty().tag(unit="GHz", expression=r"$f_q \approx (\sqrt{8E_J E_C}-E_C)/h$")
    @fq_approx.getter
    def _get_fq_approx(self, Ej, Ec):
        return (sqrt(8.0*Ej*Ec)-Ec)/h

    fq_max=SProperty().tag(unit="GHz", label="fq max", expression=r"$f_{qmax}$")
    @fq_max.getter
    def _get_fq_max(self, Ejmax, Ec, qubit_type, ng, Nstates):
        return  self._get_fq(Ej=Ejmax, Ec=Ec, qubit_type=qubit_type, ng=ng, Nstates=Nstates)

    fq=SProperty().tag(desc="""Operating frequency of qubit""", unit="GHz", expression=r"$f_q$")
    @fq.getter
    def _get_fq(self, Ej, Ec, qubit_type, ng, Nstates):
        E0, E1=self._get_energy_levels(Ej=Ej, Ec=Ec, n_energy=2, qubit_type=qubit_type, ng=ng, Nstates=Nstates)
        return (E1-E0)/h

    @fq.setter
    def _get_Ej_get_fq(self, fq, Ec):
        """h*fq=sqrt(8.0*Ej*Ec) - Ec"""
        return ((h*fq+Ec)**2)/(8.0*Ec)

    L=SProperty().tag(label="Kinetic inductance of SQUID", expression=r"$L$")
    @L.getter
    def _get_L(self, fq, Ct):
        return 1.0/(Ct*(2*pi*fq)**2)

    anharm=SProperty().tag(desc="absolute anharmonicity", unit="GHz")
    @anharm.getter
    def _get_anharm(self, Ej, Ec, qubit_type, ng, Nstates):
        E0, E1, E2=self._get_energy_levels(Ej=Ej, Ec=Ec, n_energy=3, qubit_type=qubit_type, ng=ng, Nstates=Nstates)
        return (E2-E1)/h-(E1-E0)/h

    fq2=SProperty().tag(desc="""20 over 2 freq""", unit="GHz", expression = r"$f_{20}/2$")
    @fq2.getter
    def _get_fq2(self, Ej, Ec, qubit_type, ng, Nstates):
        E0, E1, E2=self._get_energy_levels(Ej=Ej, Ec=Ec, n_energy=3, qubit_type=qubit_type, ng=ng, Nstates=Nstates)
        return (E2-E0)/h/2.0

    voltage=Float().tag(unit="V", desc="Yoko voltage on coil")
    offset=Float(0.09).tag(unit="V", desc="offset of flux in volts")
    flux_factor=Float(0.195).tag(desc="converts voltage to flux")

    flux_factor_beta=Float().tag(desc="linear dependenc on magnetic field")

    flux_over_flux0=SProperty().tag(expression=r"$\Phi/\Phi_0=$(voltage-offset)fluxfactor", unit="pi")
    @flux_over_flux0.getter
    def _get_flux_over_flux0(self, voltage, offset, flux_factor, flux_factor_beta):
        return (voltage-offset)*flux_factor#/(1.0-flux_factor_beta*(voltage-offset))
        #return (voltage-offset)*flux_factor

    @flux_over_flux0.setter
    def _get_voltage(self, flux_over_flux0, offset, flux_factor, flux_factor_beta):
        #return flux_over_flux0/flux_factor*(1-flux_factor_beta/flux_factor*flux_over_flux0)+offset
        #return flux_over_flux0/flux_factor+offset+sign(flux_over_flux0)*flux_factor_beta*flux_over_flux0**2
        #return flux_over_flux0/flux_factor+offset+flux_factor_beta*flux_over_flux0**3

        return flux_over_flux0/flux_factor+offset

    flux_parabola=SProperty()
    @flux_parabola.getter
    def _get_flux_parabola(self, voltage, offset, flux_factor, Ejmax, Ec, qubit_type, ng, Nstates):
        flx_d_flx0=self._get_flux_over_flux0(voltage=voltage, offset=offset, flux_factor=flux_factor)
        qEj=self._get_Ej(Ejmax=Ejmax, flux_over_flux0=flx_d_flx0)
        return self._get_fq(Ej=qEj, Ec=Ec, qubit_type=qubit_type, ng=ng, Nstates=Nstates)#, fq2(qEj, Ec)

    #freq_arr=Array().tag(desc="array of frequencies to evaluate over")
    f=Float(4.4e9).tag(label="Operating frequency", desc="what frequency is being stimulated/measured", unit="GHz")

    flux_from_fq=SProperty().tag(sub=True)
    @flux_from_fq.getter
    def _get_flux_from_fq(self, fq, Ct, Ejmax):
        Ec=self._get_Ec(Ct=Ct)
        Ej=self._get_Ej_get_fq(fq=fq, Ec=Ec)
        return self._get_flux_over_flux0_get_Ej(Ej=Ej, Ejmax=Ejmax)

    voltage_from_flux_par=SProperty().tag(sub=True)
    @voltage_from_flux_par.getter
    def _get_voltage_from_flux_par(self, fq, Ct, Ejmax, offset, flux_factor):
        #Ec=self._get_Ec(Ct=Ct)
        #Ej=self._get_Ej_get_fq(fq=fq, Ec=Ec)
        flux_d_flux0=self._get_flux_from_fq(fq, Ct, Ejmax) #self._get_flux_over_flux0_get_Ej(Ej=Ej, Ejmax=Ejmax)
        return self._get_voltage(flux_over_flux0=flux_d_flux0, offset=offset, flux_factor=flux_factor)

    voltage_from_flux_par_many=SProperty().tag(sub=True)
    @voltage_from_flux_par_many.getter
    def _get_voltage_from_flux_par_many(self, fq, Ct, Ejmax, offset, flux_factor, flux_factor_beta):
        #Ec=self._get_Ec(Ct=Ct)
        #Ej=self._get_Ej_get_fq(fq=f, Ec=Ec)
        fdf0=self._get_flux_from_fq(fq, Ct, Ejmax) #self._get_flux_over_flux0_get_Ej(Ej=Ej, Ejmax=Ejmax)

        #fdf0=self._get_flux_over_flux0_get_Ej(Ej=Ej, Ejmax=Ejmax)
        flux_d_flux0=append(fdf0, -fdf0)
        flux_d_flux0=append(flux_d_flux0, -fdf0+pi*(1+flux_factor_beta))
        flux_d_flux0=append(flux_d_flux0, fdf0-pi*(1+flux_factor_beta))
        freq=append(fq, fq)
        freq=append(freq, freq)
        return freq/1e9, self._get_voltage(flux_over_flux0=flux_d_flux0, offset=offset, flux_factor=flux_factor)

    def detuning(self, fq_off):
        return 2.0*pi*(self.fq - fq_off)

    def transmon_energy(self, Ej, Ec, m):
        return -Ej+sqrt(8.0*Ej*Ec)*(m+0.5) - (Ec/12.0)*(6.0*m**2+6.0*m+3.0)

    transmon_energy_levels=SProperty().tag(sub=True)
    @transmon_energy_levels.getter
    def _get_transmon_energy_levels(self, Ej, Ec, n_energy):
        return [self.transmon_energy(Ej, Ec, m) for m in range(n_energy)]

    n_energy=Int(3)

    ng=Float(0.5).tag(desc="charge on gate line", log=False)
    Nstates=Int(50).tag(desc="number of states to include in mathieu approximation. More states is better approximation")
    order=Int(3)
    EkdivEc=Array().tag(unit2="Ec", sub=True)

    energy_levels=SProperty().tag(sub=True)
    @energy_levels.getter
    def _get_energy_levels(self, Ej, Ec, n_energy, qubit_type, ng, Nstates):
        if qubit_type=="scb":
            return self._get_scb_energy_levels(Ej=Ej, Ec=Ec, n_energy=n_energy, ng=ng, Nstates=Nstates)
        return self._get_transmon_energy_levels(Ej=Ej, Ec=Ec, n_energy=n_energy)

    def indiv_EkdivEc(self, EjdivEc, n_energy, ng, Nstates):
        """calculates energies assuming float values given"""
        NL=2*Nstates+1
        A=zeros((NL, NL))
        for b in range(0,NL):
            A[b, b]=4.0*(b-Nstates-ng)**2
            if b!=NL-1:
                A[b, b+1]= -EjdivEc/2.0
            if b!=0:
                A[b, b-1]= -EjdivEc/2.0
        #w,v=eig(A)
        w=eigvalsh(A)
        return w[0:n_energy]

    scb_energy_levels=SProperty().tag(sub=True)
    @scb_energy_levels.getter
    def _get_scb_energy_levels(self, Ej, Ec, n_energy, ng, Nstates):
        if isinstance(Ej, float):
            Ej=array([Ej])
        if isinstance(ng, float):
            ng=[ng]
        EjdivEc=Ej/Ec
        energies=Ec*squeeze([[self.indiv_EkdivEc(EjdivEc=ejc, n_energy=n_energy, ng=ng_s, Nstates=Nstates) for ejc in EjdivEc] for ng_s in ng])
        return [spl.transpose() for spl in split(energies.transpose(), n_energy)]

        #energies=squeeze(energies)
        NL=2*Nstates+1
        A=zeros((NL, NL))
        for b in range(0,NL):
            A[b, b]=4.0*Ec*(b-Nstates-ng)**2
            if b!=NL-1:
                A[b, b+1]= -Ej/2.0
            if b!=0:
                A[b, b-1]= -Ej/2.0
        #w,v=eig(A)
        w=eigvalsh(A)
        return w[0:n_energy]


    def update_EkdivEc(self, ng, Ec, Ej, Nstates, order):
        """calculates transmon energy level with N states (more states is better approximation)
        effectively solves the mathieu equation but for fractional inputs (which doesn't work in scipy.special.mathieu_a)"""

#        if type(ng) not in (int, float):
#            d=zeros((order, len(ng)))
#        elif type(Ec) not in (int, float):
#            d=zeros((order, len(Ec)))
#        elif type(Ej) not in (int, float):
#            d=zeros((order, len(Ej)))
        if type(ng) in (int, float):
            ng=array([ng])
        d1=[]
        d2=[]
        d3=[]
        Ej=Ej/Ec
        Ec=1.0#/4.0
        for a in ng:
            NL=2*Nstates+1
            A=zeros((NL, NL))
            for b in range(0,NL):
                A[b, b]=4.0*Ec*(b-Nstates-a)**2
                if b!=NL-1:
                    A[b, b+1]= -Ej/2.0
                if b!=0:
                    A[b, b-1]= -Ej/2.0
            #w,v=eig(A)
            w=eigvalsh(A)
            d=w[0:order]
#            d1.append(min(w))#/h*1e-9)
#            w=delete(w, w.argmin())
#            d2.append(min(w))#/h*1e-9)
#            w=delete(w, w.argmin())
#            d3.append(min(w))#/h*1e-9)

        return array([array(d1), array(d2), array(d3)]).transpose()

    def sweepEc():
        Ecarr=Ej/EjoverEc
        E01a=sqrt(8*Ej*Ecarr)-Ecarr
        data=[]
        for Ec in Ecarr:
            d1, d2, d3= EkdivEc(ng=ng, Ec=Ec, Ej=Ej, N=50)
            E12=d3[0]-d2[0]
            E01=d2[0]-d1[0]
            anharm2=(E12-E01)#/E01
            data.append(anharm2)
        Ctr=e**2/(2.0*Ecarr*h*1e9)
        return E01a, Ctr, data, d1, d2, d3
Exemple #8
0
class Qubit(Agent):
    """Theoretical description of qubit"""
    base_name="qubit"
    #def _default_main_params(self):
    #    return ["ft", "f0", "lbda0", "a", "g", "eta", "Np", "ef", "W", "Ct",
    #            "material", "Dvv", "K2", "vf", "epsinf",
    #            "Rn", "Ic", "Ejmax", "Ej", "Ec", "EjmaxdivEc", "EjdivEc",
    #            "fq", "fq_max", "fq_max_full", "flux_over_flux0", "G_f0", "G_f",
   #             "ng", "Nstates", "EkdivEc"]

    superconductor=Enum("Al")

    def _observe_superconductor(self, change):
        if self.superconductor=="Al":
            self.Delta=Delta_Al

    Tc=Float(Tc_Al).tag(desc="Critical temperature of superconductor", unit="K")

    Delta=SProperty().tag(label="Gap", tex_str=r"$\Delta(0)$", unit="ueV", desc="Superconducting gap 200 ueV for Al",
                     reference="BCS", expression=r"$1.764 k_B T_c$")
    @Delta.getter
    def _get_Delta(self, Tc):
        """BCS theory superconducting gap"""
        return 1.764*kB*Tc

    @Delta.setter
    def _get_Tc(self, Delta):
        return Delta/(1.764*kB)

    loop_width=Float(1.0e-6).tag(desc="loop width of SQUID", unit="um", label="loop width")
    loop_height=Float(1.0e-6).tag(desc="loop height of SQUID", unit="um", label="loop height")

    loop_area=SProperty().tag(desc="Area of SQUID loop", unit="um^2", expression="$width \times height$",
                     comment="Loop width times loop height", label="loop area")
    @loop_area.getter
    def _get_loop_area(self, loop_width, loop_height):
        return loop_width*loop_height

    C=Float(1.0e-13).tag(desc="shunt capacitance", unit="fF", tex_str=r"$C_q$")

    Rn=Float(10.0e3).tag(desc="Normal resistance of SQUID", unit="kOhm", label="DC Junction resistance", tex_str=r"$R_n$")

    Ic=SProperty().tag(desc="critical current of SQUID", unit="nA", label="Critical current", tex_str=r"$I_C$")
    @Ic.getter
    def _get_Ic(self, Rn, Delta):
        """Ic*Rn=pi*Delta/(2.0*e) #Ambegaokar Baratoff formula"""
        return pi*Delta/(2.0*e)/Rn

    @Ic.setter
    def _get_Rn(self, Ic, Delta):
        """Ic*Rn=pi*Delta/(2.0*e) #Ambegaokar Baratoff formula"""
        return pi*Delta/(2.0*e)/Ic


    Ejmax=SProperty().tag(desc="""Max Josephson Energy""", unit="hGHz")#, unit_factor=1.0e9*h)
    @Ejmax.getter
    def _get_Ejmax(self, Ic):
        """Josephson energy"""
        return hbar*Ic/(2.0*e)

    @Ejmax.setter
    def _get_Ic_get_Ejmax(self, Ejmax):
        """inverse Josephson energy"""
        return Ejmax*(2.0*e)/hbar

    Ec=SProperty().tag(desc="Charging Energy", unit="hGHz")#, unit_factor=1.0e9*h)
    @Ec.getter
    def _get_Ec(self, C):
        """Charging energy"""
        return e**2/(2.0*C)

    @Ec.setter
    def _get_C(self, Ec):
        """inverse charging energy"""
        return e**2/(2.0*Ec)

    @Ec.setter
    def _get_Ejmax_get_Ec(self, Ec, EjmaxdivEc):
        return EjmaxdivEc*Ec

    EjmaxdivEc=SProperty().tag(desc="Maximum Ej over Ec")
    @EjmaxdivEc.getter
    def _get_EjmaxdivEc(self, Ejmax, Ec):
        return Ejmax/Ec

    Ej=SProperty().tag(unit="hGHz")
    @Ej.getter
    def _get_Ej(self, Ejmax, flux_over_flux0):
        return Ejmax*absolute(cos(flux_over_flux0)) #*pi

    @Ej.setter
    def _get_flux_over_flux0_get_Ej(self, Ej, Ejmax):
        return arccos(Ej/Ejmax)#/pi

    EjdivEc=SProperty().tag(desc="Ej over Ec")
    @EjdivEc.getter
    def _get_EjdivEc(self, Ej, Ec):
        return Ej/Ec

    fq_approx_max=SProperty().tag(unit="GHz", label="fq max")
    @fq_approx_max.getter
    def _get_fq_approx_max(self, Ejmax, Ec):
        return self._get_fq_approx(Ej=Ejmax, Ec=Ec)

    fq_approx=SProperty()
    @fq_approx.getter
    def _get_fq_approx(self, Ej, Ec):
        return (sqrt(8.0*Ej*Ec)-Ec)/h

    fq_max=SProperty().tag(unit="hGHz", label="fq max full")
    @fq_approx.getter
    def _get_fq_max(self, Ejmax, Ec):
        return  self._get_fq(Ej=Ejmax, Ec=Ec)

    fq=SProperty().tag(desc="""Operating frequency of qubit""", unit="GHz")
    @fq.getter
    def _get_fq(self, Ej, Ec):
        E0, E1=self._get_transmon_energy_levels(Ej=Ej, Ec=Ec, n_energy=2)
        return (E1-E0)/h

    @fq.setter
    def _get_Ej_get_fq(self, fq, Ec):
        """h*fq=sqrt(8.0*Ej*Ec) - Ec"""
        return ((h*fq+Ec)**2)/(8.0*Ec)

    L=SProperty()
    @L.getter
    def _get_L(self, fq, C):
        return 1.0/(C*(2*pi*fq)**2)

    anharm=SProperty().tag(desc="absolute anharmonicity", unit="hGHz")
    @anharm.getter
    def _get_anharm(self, Ej, Ec):
        E0, E1, E2=self._get_transmon_energy_levels(Ej=Ej, Ec=Ec, n_energy=3)
        return (E2-E1)/h-(E1-E0)/h

    fq2=SProperty().tag(desc="""20 over 2 freq""", unit="GHz")
    @fq2.getter
    def _get_fq2(self, Ej, Ec):
        E0, E1, E2=self._get_transmon_energy_levels(Ej=Ej, Ec=Ec, n_energy=3)
        return (E2-E0)/h/2.0

    voltage=Float().tag(unit="V")
    offset=Float(0.09).tag(unit="V")
    flux_factor=Float(0.195)

    flux_over_flux0=SProperty()
    @flux_over_flux0.getter
    def _get_flux_over_flux0(self, voltage, offset, flux_factor):
        return (voltage-offset)*flux_factor

    @flux_over_flux0.setter
    def _get_voltage(self, flux_over_flux0, offset, flux_factor):
        return flux_over_flux0/flux_factor+offset

    flux_parabola=SProperty()
    @flux_parabola.getter
    def _get_flux_parabola(self, voltage, offset, flux_factor, Ejmax, Ec):
        flx_d_flx0=self._get_flux_over_flux0(voltage=voltage, offset=offset, flux_factor=flux_factor)
        qEj=self._get_Ej(Ejmax=Ejmax, flux_over_flux0=flx_d_flx0)
        return self._get_fq(Ej=qEj, Ec=Ec)#, fq2(qEj, Ec)

    #freq_arr=Array().tag(desc="array of frequencies to evaluate over")
    f=Float(4.4e9).tag(desc="Operating frequency, e.g. what frequency is being stimulated/measured")
    voltage_from_flux_par=SProperty().tag(sub=True)
    @voltage_from_flux_par.getter
    def _get_voltage_from_flux_par(self, f, C, Ejmax, offset, flux_factor):
        Ec=self._get_Ec(C=C)
        Ej=self._get_Ej_get_fq(fq=f, Ec=Ec)
        flux_d_flux0=self._get_flux_over_flux0_get_Ej(Ej=Ej, Ejmax=Ejmax)
        return f/1e9, self._get_voltage(flux_over_flux0=flux_d_flux0, offset=offset, flux_factor=flux_factor)

    voltage_from_flux_par_many=SProperty().tag(sub=True)
    @voltage_from_flux_par_many.getter
    def _get_voltage_from_flux_par_many(self, f, C, Ejmax, offset, flux_factor):
        Ec=self._get_Ec(C=C)
        Ej=self._get_Ej_get_fq(fq=f, Ec=Ec)
        fdf0=self._get_flux_over_flux0_get_Ej(Ej=Ej, Ejmax=Ejmax)
        flux_d_flux0=append(fdf0, -fdf0)
        flux_d_flux0=append(flux_d_flux0, -fdf0+pi)
        flux_d_flux0=append(flux_d_flux0, fdf0-pi)
        freq=append(f, f)
        freq=append(freq, freq)
        return freq/1e9, self._get_voltage(flux_over_flux0=flux_d_flux0, offset=offset, flux_factor=flux_factor)

    def detuning(self, fq_off):
        return 2.0*pi*(self.fq - fq_off)

    def transmon_energy(self, Ej, Ec, m):
        return -Ej+sqrt(8.0*Ej*Ec)*(m+0.5) - (Ec/12.0)*(6.0*m**2+6.0*m+3.0)

    transmon_energy_levels=SProperty().tag(sub=True)
    @transmon_energy_levels.getter
    def _get_transmon_energy_levels(self, Ej, Ec, n_energy):
        #Ej=EjdivEc*Ec
        return [self.transmon_energy(Ej, Ec, m) for m in range(n_energy)]

    n_energy=Int(3)

    def indiv_EkdivEc(self, ng, Ec, Ej, Nstates, order):
        NL=2*Nstates+1
        A=zeros((NL, NL))
        for b in range(0,NL):
            A[b, b]=4.0*Ec*(b-Nstates-a)**2
            if b!=NL-1:
                A[b, b+1]= -Ej/2.0
            if b!=0:
                A[b, b-1]= -Ej/2.0
        w,v=eig(A)
        print w, v
        #for n in range(order):

    ng=Float(0.5).tag(desc="charge on gate line")
    Nstates=Int(50).tag(desc="number of states to include in mathieu approximation. More states is better approximation")
    order=Int(3)
    EkdivEc=Array().tag(unit2="Ec", sub=True)


    def update_EkdivEc(self, ng, Ec, Ej, Nstates, order):
        """calculates transmon energy level with N states (more states is better approximation)
        effectively solves the mathieu equation but for fractional inputs (which doesn't work in scipy.special.mathieu_a)"""

#        if type(ng) not in (int, float):
#            d=zeros((order, len(ng)))
#        elif type(Ec) not in (int, float):
#            d=zeros((order, len(Ec)))
#        elif type(Ej) not in (int, float):
#            d=zeros((order, len(Ej)))
        if type(ng) in (int, float):
            ng=array([ng])
        d1=[]
        d2=[]
        d3=[]
        Ej=Ej/Ec
        Ec=1.0#/4.0
        for a in ng:
            NL=2*Nstates+1
            A=zeros((NL, NL))
            for b in range(0,NL):
                A[b, b]=4.0*Ec*(b-Nstates-a)**2
                if b!=NL-1:
                    A[b, b+1]= -Ej/2.0
                if b!=0:
                    A[b, b-1]= -Ej/2.0
            #w,v=eig(A)
            w=eigvalsh(A)
            d=w[0:order]
#            d1.append(min(w))#/h*1e-9)
#            w=delete(w, w.argmin())
#            d2.append(min(w))#/h*1e-9)
#            w=delete(w, w.argmin())
#            d3.append(min(w))#/h*1e-9)

        return array([array(d1), array(d2), array(d3)]).transpose()

    def sweepEc():
        Ecarr=Ej/EjoverEc
        E01a=sqrt(8*Ej*Ecarr)-Ecarr
        data=[]
        for Ec in Ecarr:
            d1, d2, d3= EkdivEc(ng=ng, Ec=Ec, Ej=Ej, N=50)
            E12=d3[0]-d2[0]
            E01=d2[0]-d1[0]
            anharm2=(E12-E01)#/E01
            data.append(anharm2)
        Ctr=e**2/(2.0*Ecarr*h*1e9)
        return E01a, Ctr, data, d1, d2, d3