def transmissionfit(f_data,z_data,fr,Qr): #not tested ''' phasefit enhanced by circlefit method ''' xc, yc, r0 = rt.fit_circle(z_data) zc = np.complex(xc,yc) fitparams = rt.phase_fit_nooffset(f_data,rt.center(z_data,zc),Qr,fr) Qr, fr = fitparams[0] results = {"Qr":Qr,"fr":fr} p = fr, Qr chi_square, cov = rt.get_cov(rt.residuals_transm_ideal,f_data,z_data,p) if cov!=None: errors = [np.sqrt(cov[i][i]) for i in range(len(cov))] results.update({"fr_err":errors[0],"Qr_err":errors[1],"chi_square":chi_square}) return results
def do_calibration(f_data,z_data,ignoreslope=True,guessdelay=True): ''' performs an automated calibration and tries to determine the prefactors a, alpha, delay fr, Qr, and a possible slope are extra information, which can be used as start parameters for subsequent fits see also "do_normalization" the calibration procedure works for transmission line resonators as well ''' delay, params = get_delay(f_data,z_data,ignoreslope=ignoreslope,guess=guessdelay) z_data = (z_data-params[1]*(f_data-params[4]))*np.exp(2.*1j*np.pi*delay*f_data) xc, yc, r0 = rt.fit_circle(z_data) zc = np.complex(xc,yc) fitparams = rt.phase_fit(f_data,rt.center(z_data,zc),0.,np.absolute(params[5]),params[4]) theta, Qr, fr = fitparams beta = rt.periodic_boundary(theta+np.pi,np.pi) offrespoint = np.complex((xc+r0*np.cos(beta)),(yc+r0*np.sin(beta))) alpha = np.angle(offrespoint) a = np.absolute(offrespoint) return delay, a, alpha, fr, Qr, params[1], params[4]
def circlefit(f_data,z_data,fr=None,Qr=None,refine_results=False,calc_errors=True): ''' performs a circle fit on a frequency vs. complex resonator scattering data set Data has to be normalized!! INPUT: f_data,z_data: input data (frequency, complex S21 data) OUTPUT: outpus a dictionary {key:value} consisting of the fit values, errors and status information about the fit values: {"phi0":phi0, "Qr":Qr, "absolute(Qc)":absQc, "Qi": Qi, "electronic_delay":delay, "complexQc":complQc, "resonance_freq":fr, "prefactor_a":a, "prefactor_alpha":alpha} errors: {"phi0_err":phi0_err, "Qr_err":Qr_err, "absolute(Qc)_err":absQc_err, "Qi_err": Qi_err, "electronic_delay_err":delay_err, "resonance_freq_err":fr_err, "prefactor_a_err":a_err, "prefactor_alpha_err":alpha_err} for details, see: [1] (not diameter corrected) Jiansong Gao, "The Physics of Superconducting Microwave Resonators" (PhD Thesis), Appendix E, California Institute of Technology, (2008) [2] (diameter corrected) M. S. Khalil, et. al., J. Appl. Phys. 111, 054510 (2012) [3] (fitting techniques) N. CHERNOV AND C. LESORT, "Least Squares Fitting of Circles", Journal of Mathematical Imaging and Vision 23, 239, (2005) [4] (further fitting techniques) P. J. Petersan, S. M. Anlage, J. Appl. Phys, 84, 3392 (1998) the program fits the circle with the algebraic technique described in [3], the rest of the fitting is done with the scipy.optimize least square fitting toolbox also, check out [5] S. Probst et al. "Efficient and reliable analysis of noisy complex scatterung resonator data for superconducting quantum circuits" (in preparation) ''' if fr==None: fr=f_data[np.argmin(np.absolute(z_data))] if Qr==None: Qr=1e6 xc, yc, r0 = rt.fit_circle(z_data,refine_results=refine_results) phi0 = -np.arcsin(yc/r0) theta0 = rt.periodic_boundary(phi0+np.pi,np.pi) z_data_corr = rt.center(z_data,np.complex(xc,yc)) theta0, Qr, fr = rt.phase_fit(f_data,z_data_corr,theta0,Qr,fr) #print "Qr from phasefit is: " + str(Qr) absQc = Qr/(2.*r0) complQc = absQc*np.exp(1j*((-1.)*phi0)) Qc = 1./(1./complQc).real # here, taking the real part of (1/complQc) from diameter correction method Qi_dia_corr = 1./(1./Qr-1./Qc) Qi_no_corr = 1./(1./Qr-1./absQc) results = {"Qi_dia_corr":Qi_dia_corr,"Qi_no_corr":Qi_no_corr,"absQc":absQc,"Qc_dia_corr":Qc,"Qr":Qr,"fr":fr,"theta0":theta0,"phi0":phi0} #calculation of the error p = [fr,absQc,Qr,phi0] #chi_square, errors = rt.get_errors(rt.residuals_notch_ideal,f_data,z_data,p) if calc_errors==True: chi_square, cov = rt.get_cov_fast(f_data,z_data,p) #chi_square, cov = rt.get_cov(rt.residuals_notch_ideal,f_data,z_data,p) if cov!=None: errors = np.sqrt(np.diagonal(cov)) fr_err,absQc_err,Qr_err,phi0_err = errors #calc Qi with error prop (sum the squares of the variances and covariaces) dQr = 1./((1./Qr-1./absQc)**2*Qr**2) dabsQc = - 1./((1./Qr-1./absQc)**2*absQc**2) Qi_no_corr_err = np.sqrt((dQr**2*cov[2][2]) + (dabsQc**2*cov[1][1])+(2*dQr*dabsQc*cov[2][1])) #with correlations #calc Qi dia corr with error prop dQr = 1/((1/Qr-np.cos(phi0)/absQc)**2 *Qr**2) dabsQc = -np.cos(phi0)/((1/Qr-np.cos(phi0)/absQc)**2 *absQc**2) dphi0 = -np.sin(phi0)/((1/Qr-np.cos(phi0)/absQc)**2 *absQc) ##err1 = ( (dQr*cov[2][2])**2 + (dabsQc*cov[1][1])**2 + (dphi0*cov[3][3])**2 ) err1 = ( (dQr**2*cov[2][2]) + (dabsQc**2*cov[1][1]) + (dphi0**2*cov[3][3]) ) err2 = ( dQr*dabsQc*cov[2][1] + dQr*dphi0*cov[2][3] + dabsQc*dphi0*cov[1][3] ) Qi_dia_corr_err = np.sqrt(err1+2*err2) # including correlations errors = {"phi0_err":phi0_err, "Qr_err":Qr_err, "absQc_err":absQc_err, "fr_err":fr_err,"chi_square":chi_square,"Qi_no_corr_err":Qi_no_corr_err,"Qi_dia_corr_err": Qi_dia_corr_err} results.update( errors ) else: print "WARNING: Error calculation failed!" else: #just calc chisquared: fun2 = lambda x: rt.residuals_notch_ideal(x,f_data,z_data)**2 chi_square = 1./float(len(f_data)-len(p)) * (fun2(p)).sum() errors = {"chi_square":chi_square} results.update(errors) return results