diff --git a/examples/CCLight_example/qisa_test_assembly/UHFQC_ro_example_code_word_0.qisa b/examples/CCLight_example/qisa_test_assembly/UHFQC_ro_example_code_word_0.qisa new file mode 100644 index 0000000000..ae10b6e84d --- /dev/null +++ b/examples/CCLight_example/qisa_test_assembly/UHFQC_ro_example_code_word_0.qisa @@ -0,0 +1,20 @@ +SMIS s0, { 0 } +SMIS s1, { 1 } +SMIS s2, { 2 } +SMIS s3, { 3 } +SMIS s4, { 4 } +SMIS s5, { 5 } +SMIS s6, { 6 } +SMIS s7, {0, 1, 2, 3, 4, 5} +SMIS s11, {0, 2, 3, 5, 6} +LDI r4, 150 +LDI r3, 2 +SUB r3, r4, r3 +Loop: + bs 2 CW_01 s6 + qwait 70 + bs 1 MeasZ s0 + qwait 500 + BR always, loop + NOP + NOP diff --git a/examples/CCLight_example/qisa_test_assembly/UHFQC_ro_example_code_word_0_2.qisa b/examples/CCLight_example/qisa_test_assembly/UHFQC_ro_example_code_word_0_2.qisa new file mode 100644 index 0000000000..52beeb9c22 --- /dev/null +++ b/examples/CCLight_example/qisa_test_assembly/UHFQC_ro_example_code_word_0_2.qisa @@ -0,0 +1,22 @@ +SMIS s0, { 0 } +SMIS s1, { 1 } +SMIS s2, { 2 } +SMIS s3, { 3 } +SMIS s4, { 4 } +SMIS s5, { 5 } +SMIS s6, { 6 } +SMIS s7, {0, 1, 2, 3, 4, 5} +SMIS s11, {0, 2, 3, 5, 6} +LDI r4, 150 +LDI r3, 2 +SUB r3, r4, r3 +Loop: + bs 2 CW_01 s6 + qwait 70 + bs 1 MeasZ s0 + qwait 500 + bs 1 MeasZ s2 + qwait 500 + BR always, loop + NOP + NOP diff --git a/examples/CCLight_example/qisa_test_assembly/UHFQC_ro_example_code_word_2.qisa b/examples/CCLight_example/qisa_test_assembly/UHFQC_ro_example_code_word_2.qisa new file mode 100644 index 0000000000..3a0e300019 --- /dev/null +++ b/examples/CCLight_example/qisa_test_assembly/UHFQC_ro_example_code_word_2.qisa @@ -0,0 +1,20 @@ +SMIS s0, { 0 } +SMIS s1, { 1 } +SMIS s2, { 2 } +SMIS s3, { 3 } +SMIS s4, { 4 } +SMIS s5, { 5 } +SMIS s6, { 6 } +SMIS s7, {0, 1, 2, 3, 4, 5} +SMIS s11, {0, 2, 3, 5, 6} +LDI r4, 150 +LDI r3, 2 +SUB r3, r4, r3 +Loop: + bs 2 CW_01 s6 + qwait 70 + bs 1 MeasZ s2 + qwait 500 + BR always, loop + NOP + NOP diff --git a/experiments.db b/experiments.db new file mode 100644 index 0000000000..7efc315fcf Binary files /dev/null and b/experiments.db differ diff --git a/pycqed/analysis/PSD/standard_arches_psd.py b/pycqed/analysis/PSD/standard_arches_psd.py index 91ef78ad94..48ccd6b1af 100644 --- a/pycqed/analysis/PSD/standard_arches_psd.py +++ b/pycqed/analysis/PSD/standard_arches_psd.py @@ -2,353 +2,16 @@ import lmfit from matplotlib import pyplot as plt import os +############################################################################################## +# These functions are VERY deprecated! Use the 'coherence_analysis from analysis_v2 instead! # +############################################################################################## -def PSD_Analysis(table, freq_resonator=None, Qc=None, chi_shift=None, path=None): - """ - Requires a table as input: - Row | Content - --------+-------- - 1 | dac - 2 | frequency - 3 | T1 - 4 | T2 star - 5 | T2 echo - 6 | Exclusion mask (True where data is to be excluded) +def PSD_Analysis(table, freq_resonator=None, Qc=None, chi_shift=None, path=None, plot: bool = True, verbose: bool = True): + raise DeprecationWarning("This function is VERY deprecated! Use the 'coherence_analysis from analysis_v2 instead!") - Generates 7 plots: - > T1, T2, Echo vs flux - > T1, T2, Echo vs frequency - > T1, T2, Echo vs flux sensitivity - - > ratio Ramsey/Echo vs flux - > ratio Ramsey/Echo vs frequency - > ratio Ramsey/Echo vs flux sensitivity - - > Dephasing rates Ramsey and Echo vs flux sensitivity - - If properties of resonator are provided (freq_resonator, Qc, chi_shift), - it also calculates the number of noise photons. - - """ - dac, freq, T1, Tramsey, Techo, exclusion_mask = table - exclusion_mask = np.array(exclusion_mask, dtype=bool) - - # Extract the dac arcs required for getting the sensitivities - fit_result_arch = fit_frequencies(dac, freq) - - # convert dac in flux as unit of Phi_0 - flux = (dac-fit_result_arch.best_values['offset'])\ - / fit_result_arch.best_values['dac0'] - - # calculate the derivative vs flux - sensitivity_angular = partial_omega_over_flux( - flux, fit_result_arch.best_values['Ec'], - fit_result_arch.best_values['Ej']) - sensitivity = sensitivity_angular/(2*np.pi) - - # Pure dephasing times - # Calculate pure dephasings - Gamma_1 = 1.0/T1[~exclusion_mask] - Gamma_ramsey = 1.0/Tramsey[~exclusion_mask] - Gamma_echo = 1.0/Techo[~exclusion_mask] - - Gamma_phi_ramsey = Gamma_ramsey - Gamma_1/2.0 - Gamma_phi_echo = Gamma_echo - Gamma_1/2.0 - - plot_coherence_times(flux, freq, sensitivity, - T1, Tramsey, Techo, path) - plot_ratios(flux, freq, sensitivity, - Gamma_phi_ramsey, Gamma_phi_echo, path) - - fit_res_gammas = fit_gammas(sensitivity, Gamma_phi_ramsey, Gamma_phi_echo) - - intercept = fit_res_gammas.params['intercept'].value - slope_ramsey = fit_res_gammas.params['slope_ramsey'].value - slope_echo = fit_res_gammas.params['slope_echo'].value - - plot_gamma_fit(sensitivity, Gamma_phi_ramsey, Gamma_phi_echo, - slope_ramsey, slope_echo, intercept, path) - - # after fitting gammas - # from flux noise - # Martinis PRA 2003 - sqrtA_rams = slope_ramsey/(np.pi*np.sqrt(30)) - sqrtA_echo = slope_echo/(np.pi*np.sqrt(1.386)) - - - print('Amplitude echo PSD = (%s u\Phi_0)^2' % (sqrtA_echo/1e-6)) - print('Amplitude rams PSD = (%s u\Phi_0)^2' % (sqrtA_rams/1e-6)) - - # from white noise - # using Eq 5 in Nat. Comm. 7,12964 (The flux qubit revisited to enhance - # coherence and reproducability) - if not ((freq_resonator is None) and (Qc is None) and (chi_shift is None)): - n_avg = calculate_n_avg(freq_resonator, Qc, chi_shift, intercept) - print('Estimated residual photon number: %s' % n_avg) - else: - n_avg = np.nan - - return (sqrtA_echo/1e-6), n_avg - -def calculate_n_avg(freq_resonator, Qc, chi_shift, intercept): - """ - Returns the avg photon of white noise,assuming photon shot noise from the RO hanger. - """ - k_r = 2*np.pi*freq_resonator/Qc - eta = k_r**2/(k_r**2 + 4*chi_shift**2) - n_avg = intercept*k_r/(4*chi_shift**2*eta) - return n_avg def prepare_input_table(dac, frequency, T1, T2_star, T2_echo, T1_mask=None, T2_star_mask=None, T2_echo_mask=None): - """ - Returns a table ready for PSD_Analysis input - If sizes are different, it adds nans on the end. - """ - assert(len(dac) == len(frequency)) - assert(len(dac) == len(T1)) - assert(len(dac) == len(T2_star)) - assert(len(dac) == len(T2_echo)) - - - if T1_mask is None: - T1_mask = np.zeros(len(T1), dtype=bool) - if T2_star_mask is None: - T2_star_mask = np.zeros(len(T2_star), dtype=bool) - if T2_echo_mask is None: - T2_echo_mask = np.zeros(len(T2_echo), dtype=bool) - - assert(len(T1) == len(T1_mask)) - assert(len(T2_star) == len(T2_star_mask)) - assert(len(T2_echo) == len(T2_echo_mask)) - - table = np.ones((6, len(dac))) - table = table * np.nan - table[0, :] = dac - table[1, :len(frequency)] = frequency - table[2, :len(T1)] = T1 - table[3, :len(T2_star)] = T2_star - table[4, :len(T2_echo)] = T2_echo - table[5, :len(T1_mask)] = np.logical_or(np.logical_or(T1_mask, - T2_star_mask), - T2_echo_mask) - - return table - - -def arch(dac, Ec, Ej, offset, dac0): - ''' - Function for frequency vs flux (in dac) for the transmon - - Input: - - dac: voltage used in the DAC to generate the flux - - Ec (Hz): Charging energy of the transmon in Hz - - Ej (Hz): Josephson energy of the transmon in Hz - - offset: voltage offset of the arch (same unit of the dac) - - dac0: dac value to generate 1 Phi_0 (same unit of the dac) - - Note: the Phi_0 (periodicity) dac0 - ''' - model = np.sqrt(8*Ec*Ej*np.abs(np.cos((np.pi*(dac-offset))/dac0)))-Ec - - return model - -# define the model (from the function) used to fit data -arch_model = lmfit.Model(arch) - - -# derivative of arch vs flux (in unit of Phi0) -# this is the sensitivity to flux noise -def partial_omega_over_flux(flux, Ec, Ej): - ''' - Note: flux is in unit of Phi0 - Ej and Ec are in Hz - - Output: angular frequency over Phi_0 - ''' - model = -np.sign(np.cos(np.pi*flux)) * (np.pi**2)*np.sqrt(8*Ec*Ej) * \ - np.sin(np.pi*flux) / np.sqrt(np.abs(np.cos(np.pi*flux))) - return model - - -def fit_frequencies(dac, freq): - arch_model.set_param_hint('Ec', value=250e6, min=200e6, max=300e6) - arch_model.set_param_hint('Ej', value=18e9, min=0) - arch_model.set_param_hint('offset', value=0) - arch_model.set_param_hint('dac0', value=2000, min=0) - - arch_model.make_params() - - fit_result_arch = arch_model.fit(freq, dac=dac) - return fit_result_arch - -def plot_coherence_times_freq(flux, freq, sensitivity, - T1, Tramsey, Techo, path, - figname='Coherence_times.PNG'): - f, ax = plt.subplots() - - ax.plot(freq/1e9, T1/1e-6, 'o', color='C3', label='$T_1$') - ax.plot(freq/1e9, Tramsey/1e-6, 'o', color='C2', label='$T_2^*$') - ax.plot(freq/1e9, Techo/1e-6, 'o', color='C0', label='$T_2$') - ax.set_title('$T_1$, $T_2^*$, $T_2$ vs frequency') - ax.set_xlabel('Frequency (GHz)') - ax.legend(loc=0) - - - f.tight_layout() - if path is not None: - savename = os.path.abspath(os.path.join(path, figname)) - f.savefig(savename, format='PNG', dpi=450) - -def plot_coherence_times(flux, freq, sensitivity, - T1, Tramsey, Techo, path, - figname='Coherence_times.PNG'): - # font = {'size': 16} - # matplotlib.rc('font', **font) - - # f, ax = plt.subplots(1, 3, figsize=[18, 6], sharey=True) - - f, ax = plt.subplots(1, 3, figsize=(18, 5), sharey=True) - - ax[0].plot(flux/1e-3, T1/1e-6, 'o', color='C3', label='$T_1$') - ax[0].plot(flux/1e-3, Tramsey/1e-6, 'o', color='C2', label='$T_2^*$') - ax[0].plot(flux/1e-3, Techo/1e-6, 'o', color='C0', label='$T_2$') - ax[0].set_title('$T_1$, $T_2^*$, $T_2$ vs flux', size=16) - ax[0].set_ylabel('Coherence time ($\mu$s)', size=16) - ax[0].set_xlabel('Flux (m$\Phi_0$)', size=16) - - ax[1].plot(freq/1e9, T1/1e-6, 'o', color='C3', label='$T_1$') - ax[1].plot(freq/1e9, Tramsey/1e-6, 'o', color='C2', label='$T_2^*$') - ax[1].plot(freq/1e9, Techo/1e-6, 'o', color='C0', label='$T_2$') - ax[1].set_title('$T_1$, $T_2^*$, $T_2$ vs frequency', size=16) - ax[1].set_xlabel('Frequency (GHz)', size=16) - ax[1].legend(loc=0) - - ax[2].plot(np.abs(sensitivity)/1e9, T1/1e-6, 'o', color='C3', label='$T_1$') - ax[2].plot(np.abs(sensitivity)/1e9, Tramsey/1e-6, - 'o', color='C2', label='$T_2^*$') - ax[2].plot( - np.abs(sensitivity)/1e9, Techo/1e-6, 'o', color='C0', label='$T_2$') - ax[2].set_title('$T_1$, $T_2^*$, $T_2$ vs sensitivity', size=16) - ax[2].set_xlabel(r'$|\partial\nu/\partial\Phi|$ (GHz/$\Phi_0$)', size=16) - - f.tight_layout() - if path is not None: - savename = os.path.abspath(os.path.join(path, figname)) - f.savefig(savename, format='PNG', dpi=450) - - - -def plot_ratios(flux, freq, sensitivity, - Gamma_phi_ramsey, Gamma_phi_echo, path, - figname='Gamma_ratios.PNG'): - # Pure dephaning times - - f, ax = plt.subplots(1, 3, figsize=(18, 5), sharey=True) - ratio_gamma = Gamma_phi_ramsey/Gamma_phi_echo - - ax[0].plot(flux/1e-3, ratio_gamma, 'o', color='C0') - ax[0].set_title('$T_\phi^{\mathrm{Echo}}/T_\phi^{\mathrm{Ramsey}}$ vs flux', size=16) - ax[0].set_ylabel('Ratio', size=16) - ax[0].set_xlabel('Flux (m$\Phi_0$)', size=16) - - ax[1].plot(freq/1e9, ratio_gamma, 'o', color='C0') - ax[1].set_title('$T_\phi^{\mathrm{Echo}}/T_\phi^{\mathrm{Ramsey}}$ vs frequency', size=16) - ax[1].set_xlabel('Frequency (GHz)', size=16) - - ax[2].plot(np.abs(sensitivity)/1e9, ratio_gamma, 'o', color='C0') - ax[2].set_title('$T_\phi^{\mathrm{Echo}}/T_\phi^{\mathrm{Ramsey}}$ vs sensitivity', size=16) - ax[2].set_xlabel(r'$|\partial\nu/\partial\Phi|$ (GHz/$\Phi_0$)', size=16) - - f.tight_layout() - - if path is not None: - savename = os.path.abspath(os.path.join(path, figname)) - f.savefig(savename, format='PNG', dpi=450) - - -def residual_Gamma(pars_dict, sensitivity, Gamma_phi_ramsey, Gamma_phi_echo): - slope_ramsey = pars_dict['slope_ramsey'] - slope_echo = pars_dict['slope_echo'] - intercept = pars_dict['intercept'] - - gamma_values_ramsey = slope_ramsey*np.abs(sensitivity) + intercept - residual_ramsey = Gamma_phi_ramsey - gamma_values_ramsey - - gamma_values_echo = slope_echo*np.abs(sensitivity) + intercept - residual_echo = Gamma_phi_echo - gamma_values_echo - - return np.concatenate((residual_ramsey, residual_echo)) - - -def super_residual(p): - data = residual_Gamma(p) - # print(type(data)) - return data.astype(float) - - -def fit_gammas(sensitivity, Gamma_phi_ramsey, Gamma_phi_echo, verbose=0): - # create a parametrrer set for the initial guess - p = lmfit.Parameters() - p.add('slope_ramsey', value=100.0, vary=True) - p.add('slope_echo', value=100.0, vary=True) - p.add('intercept', value=100.0, vary=True) - - # mi = lmfit.minimize(super_residual, p) - wrap_residual = lambda p: residual_Gamma(p, - sensitivity=sensitivity, - Gamma_phi_ramsey=Gamma_phi_ramsey, - Gamma_phi_echo=Gamma_phi_echo) - fit_result_gammas = lmfit.minimize(wrap_residual, p) - verbose = 1 - if verbose > 0: - lmfit.printfuncs.report_fit(fit_result_gammas.params) - return fit_result_gammas - - -def plot_gamma_fit(sensitivity, Gamma_phi_ramsey, Gamma_phi_echo, - slope_ramsey, slope_echo, intercept, path, - f=None, ax=None, - figname='Gamma_Fit.PNG'): - if f is None: - f, ax = plt.subplots() - - ax.plot(np.abs(sensitivity)/1e9, Gamma_phi_ramsey, - 'o', color='C2', label='$\Gamma_{\phi,\mathrm{Ramsey}}$') - ax.plot(np.abs(sensitivity)/1e9, slope_ramsey * - np.abs(sensitivity)+intercept, color='C2') - - ax.plot(np.abs(sensitivity)/1e9, Gamma_phi_echo, - 'o', color='C0', label='$\Gamma_{\phi,\mathrm{Echo}}$') - ax.plot(np.abs(sensitivity)/1e9, slope_echo * - np.abs(sensitivity)+intercept, color='C0') - - ax.legend(loc=0) - # ax.set_title('Pure dephasing vs flux sensitivity') - ax.set_title('Previous cooldown') - ax.set_xlabel(r'$|\partial f/\partial\Phi|$ (GHz/$\Phi_0$)') - ax.set_ylabel('$\Gamma_{\phi}$ (1/s)') - f.tight_layout() - ax.set_ylim(0, np.max(Gamma_phi_ramsey)*1.05) - if path is not None: - savename = os.path.abspath(os.path.join(path, figname)) - f.savefig(savename, format='PNG', dpi=450) - - -""" -Test code -# print the result of the fit and plot data -print('Offset = %s mV' % (fit_result_arch.best_values['offset'])) -print('Dac/Phi_0 = %s mV' % (fit_result_arch.best_values['dac0'])) -print('Ec = %s MHz' % (fit_result_arch.best_values['Ec']/1e6)) -print('Ej = %s GHz' % (fit_result_arch.best_values['Ej']/1e9)) - -plt.plot(dac, freq/1e9, 'o', label='data') -plt.plot(dac, fit_result_arch.best_fit/1e9, color='C3', label='best fit') -plt.legend(loc=0) -plt.title('Full arch QR3') -plt.ylabel('Freq (GHz)') -plt.xlabel('Dac (mV)') -""" + raise DeprecationWarning("This function is VERY deprecated! Use the 'coherence_analysis from analysis_v2 instead!") \ No newline at end of file diff --git a/pycqed/analysis/analysis_toolbox.py b/pycqed/analysis/analysis_toolbox.py index 85dab9b5d1..18e7898231 100644 --- a/pycqed/analysis/analysis_toolbox.py +++ b/pycqed/analysis/analysis_toolbox.py @@ -22,6 +22,7 @@ from .tools.plotting import * import colorsys as colors from matplotlib import cm +from pycqed.analysis import composite_analysis as RA from matplotlib.colors import LogNorm @@ -1412,6 +1413,9 @@ def calculate_rotation_matrix(delta_I, delta_Q): def normalize_TD_data(data, data_zero, data_one): + """ + Normalizes measured data to refernce signals for zero and one + """ return (data - data_zero) / (data_one - data_zero) diff --git a/pycqed/analysis/fitting_models.py b/pycqed/analysis/fitting_models.py index 1ce559a3ed..3bc7584062 100644 --- a/pycqed/analysis/fitting_models.py +++ b/pycqed/analysis/fitting_models.py @@ -3,13 +3,15 @@ from scipy.special import erfc import lmfit import logging + + ################################# # Fitting Functions Library # ################################# def RandomizedBenchmarkingDecay(numCliff, Amplitude, p, offset): - val = Amplitude * (p**numCliff) + offset + val = Amplitude * (p ** numCliff) + offset return val @@ -17,8 +19,8 @@ def DoubleExpDampOscFunc(t, tau_1, tau_2, freq_1, freq_2, phase_1, phase_2, amp_1, amp_2, osc_offset): - cos_1 = amp_1 * (np.cos(2*np.pi*freq_1*t+phase_1)) * np.exp(-(t/tau_1)) - cos_2 = amp_2 * (np.cos(2*np.pi*freq_2*t+phase_2)) * np.exp(-(t/tau_2)) + cos_1 = amp_1 * (np.cos(2 * np.pi * freq_1 * t + phase_1)) * np.exp(-(t / tau_1)) + cos_2 = amp_2 * (np.cos(2 * np.pi * freq_2 * t + phase_2)) * np.exp(-(t / tau_2)) return cos_1 + cos_2 + osc_offset @@ -33,22 +35,22 @@ def double_RandomizedBenchmarkingDecay(numCliff, p, offset, pick invert to be 1 or 0 """ # Inverting clifford curve - val_inv = (1-offset) * (p**numCliff) + offset + val_inv = (1 - offset) * (p ** numCliff) + offset # flipping clifford curve - val_flip = -offset * (p**numCliff) + offset + val_flip = -offset * (p ** numCliff) + offset # Using invert as a boolean but not using if statement to allow for # arrays to be input in the function - val = (1-invert) * val_flip + invert*val_inv + val = (1 - invert) * val_flip + invert * val_inv return val def LorentzFunc(f, amplitude, center, sigma): - val = amplitude/np.pi * (sigma / ((f-center)**2 + sigma**2)) + val = amplitude / np.pi * (sigma / ((f - center) ** 2 + sigma ** 2)) return val def Lorentzian(f, A, offset, f0, kappa): - val = offset + A/np.pi * (kappa / ((f-f0)**2 + kappa**2)) + val = offset + A / np.pi * (kappa / ((f - f0) ** 2 + kappa ** 2)) return val @@ -82,8 +84,8 @@ def TwinLorentzFunc(f, A_gf_over_2, A, f0_gf_over_2, f0, transition background (float): background offset """ - val = (A_gf_over_2/np.pi * (kappa_gf_over_2 / ((f-f0_gf_over_2)**2 + kappa_gf_over_2**2)) + - A/np.pi * (kappa / ((f-f0)**2 + kappa**2)) + background) + val = (A_gf_over_2 / np.pi * (kappa_gf_over_2 / ((f - f0_gf_over_2) ** 2 + kappa_gf_over_2 ** 2)) + + A / np.pi * (kappa / ((f - f0) ** 2 + kappa ** 2)) + background) return val @@ -107,15 +109,31 @@ def Qubit_dac_to_freq(dac_voltage, f_max, E_c, if dac_flux_coefficient is not None: logging.warning('"dac_flux_coefficient" deprecated. Please use the ' 'physically meaningful "V_per_phi0" instead.') - V_per_phi0 = np.pi/dac_flux_coefficient + V_per_phi0 = np.pi / dac_flux_coefficient qubit_freq = (f_max + E_c) * ( - asymmetry**2 + (1 - asymmetry**2) * - np.cos(np.pi / V_per_phi0 * - (dac_voltage - dac_sweet_spot))**2)**0.25 - E_c + asymmetry ** 2 + (1 - asymmetry ** 2) * + np.cos(np.pi / V_per_phi0 * + (dac_voltage - dac_sweet_spot)) ** 2) ** 0.25 - E_c return qubit_freq +def Resonator_dac_to_freq(dac_voltage, f_max_qubit, f_0_res, + E_c, dac_sweet_spot, + coupling, V_per_phi0=None, + dac_flux_coefficient=None, + asymmetry=0): + qubit_freq = Qubit_dac_to_freq(dac_voltage=dac_voltage, f_max=f_max_qubit, E_c=E_c, + dac_sweet_spot=dac_sweet_spot, V_per_phi0=V_per_phi0, + dac_flux_coefficient=dac_flux_coefficient, + asymmetry=asymmetry) + delta_qr = (qubit_freq - f_0_res) + lamb_shift = (coupling ** 2 / delta_qr) + resonator_freq = f_0_res - lamb_shift + + return resonator_freq + + def Qubit_dac_to_detun(dac_voltage, f_max, E_c, dac_sweet_spot, V_per_phi0, asymmetry=0): ''' @@ -158,13 +176,13 @@ def Qubit_freq_to_dac(frequency, f_max, E_c, # dac_term = np.arccos(((frequency+E_c)/((f_max+E_c) * asymm_term))**2) dac_term = np.arccos(np.sqrt( - (((frequency + E_c) / (f_max + E_c))**4 - asymmetry**2) / - (1 - asymmetry**2))) + (((frequency + E_c) / (f_max + E_c)) ** 4 - asymmetry ** 2) / + (1 - asymmetry ** 2))) if dac_flux_coefficient is not None: logging.warning('"dac_flux_coefficient" deprecated. Please use the ' 'physically meaningful "V_per_phi0" instead.') - V_per_phi0 = np.pi/dac_flux_coefficient + V_per_phi0 = np.pi / dac_flux_coefficient if branch == 'positive': dac_voltage = dac_term * V_per_phi0 / np.pi + dac_sweet_spot @@ -178,16 +196,16 @@ def Qubit_freq_to_dac(frequency, f_max, E_c, def Qubit_dac_sensitivity(dac_voltage, f_max: float, E_c: float, dac_sweet_spot: float, V_per_phi0: float, - asymmetry: float=0): + asymmetry: float = 0): ''' Derivative of the qubit detuning vs dac at dac_voltage. The returned quantity is "dfreq/dPhi (dac_voltage)" ''' cos_term = np.cos(np.pi / V_per_phi0 * (dac_voltage - dac_sweet_spot)) sin_term = np.sin(np.pi / V_per_phi0 * (dac_voltage - dac_sweet_spot)) - return ((f_max + E_c)*(1 - asymmetry**2) * np.pi / (2 * V_per_phi0) * - cos_term * sin_term * (asymmetry**2 + (1 - asymmetry**2) * - cos_term**2)**(-0.75)) + return ((f_max + E_c) * (1 - asymmetry ** 2) * np.pi / (2 * V_per_phi0) * + cos_term * sin_term * (asymmetry ** 2 + (1 - asymmetry ** 2) * + cos_term ** 2) ** (-0.75)) def QubitFreqDac(dac_voltage, f_max, E_c, @@ -200,8 +218,8 @@ def QubitFreqDac(dac_voltage, f_max, E_c, def QubitFreqFlux(flux, f_max, E_c, flux_zero, dac_offset=0): 'The cosine Arc model for calibrated flux.' - calculated_frequency = (f_max + E_c)*np.sqrt(np.abs( - np.cos(np.pi*(flux-dac_offset)/flux_zero))) - E_c + calculated_frequency = (f_max + E_c) * np.sqrt(np.abs( + np.cos(np.pi * (flux - dac_offset) / flux_zero))) - E_c return calculated_frequency @@ -214,17 +232,19 @@ def CosFunc(t, amplitude, frequency, phase, offset): phase in rad offset a.u. ''' - return amplitude*np.cos(2*np.pi*frequency*t + phase)+offset + return amplitude * np.cos(2 * np.pi * frequency * t + phase) + offset def ExpDecayFunc(t, tau, amplitude, offset, n): - return amplitude*np.exp(-(t/tau)**n)+offset + return amplitude * np.exp(-(t / tau) ** n) + offset + def idle_error_rate_exp_decay(N, N1, N2, A, offset): """ exponential decay consisting of two components """ - return A *np.exp(-N/N1-(N/N2)**2) + offset + return A * np.exp(-N / N1 - (N / N2) ** 2) + offset + def gain_corr_ExpDecayFunc(t, tau, amp, gc): """ @@ -233,7 +253,7 @@ def gain_corr_ExpDecayFunc(t, tau, amp, gc): the distortions. """ - y = gc*(1+amp*np.exp(-t/tau)) + y = gc * (1 + amp * np.exp(-t / tau)) return y @@ -243,21 +263,20 @@ def gain_corr_double_ExpDecayFunc(t, tau_A, tau_B, amp_A, amp_B, gc): Includes a "gain correction" parameter that is ignored when correcting the distortions. """ - y = gc*(1+amp_A*np.exp(-t/tau_A)+ amp_B*np.exp(-t/tau_B)) + y = gc * (1 + amp_A * np.exp(-t / tau_A) + amp_B * np.exp(-t / tau_B)) return y - def ExpDampOscFunc(t, tau, n, frequency, phase, amplitude, oscillation_offset, exponential_offset): - return amplitude*np.exp(-(t/tau)**n)*(np.cos( - 2*np.pi*frequency*t+phase)+oscillation_offset) + exponential_offset + return amplitude * np.exp(-(t / tau) ** n) * (np.cos( + 2 * np.pi * frequency * t + phase) + oscillation_offset) + exponential_offset def GaussExpDampOscFunc(t, tau, tau_2, frequency, phase, amplitude, oscillation_offset, exponential_offset): - return amplitude*np.exp(-(t/tau_2)**2 - (t/tau))*(np.cos( - 2*np.pi*frequency*t+phase)+oscillation_offset) + exponential_offset + return amplitude * np.exp(-(t / tau_2) ** 2 - (t / tau)) * (np.cos( + 2 * np.pi * frequency * t + phase) + oscillation_offset) + exponential_offset def ExpDampDblOscFunc(t, tau, n, freq_1, freq_2, phase_1, phase_2, @@ -266,13 +285,13 @@ def ExpDampDblOscFunc(t, tau, n, freq_1, freq_2, phase_1, phase_2, ''' Exponential decay with double cosine modulation ''' - exp_decay = np.exp(-(t/tau)**n) + exp_decay = np.exp(-(t / tau) ** n) cos_1 = (np.cos( - 2*np.pi*freq_1*t+phase_1)+osc_offset_1) + 2 * np.pi * freq_1 * t + phase_1) + osc_offset_1) cos_2 = (np.cos( - 2*np.pi*freq_2*t+phase_2)+osc_offset_2) + 2 * np.pi * freq_2 * t + phase_2) + osc_offset_2) - return amp_1*exp_decay*cos_1 + amp_2*exp_decay*cos_2 + exponential_offset + return amp_1 * exp_decay * cos_1 + amp_2 * exp_decay * cos_2 + exponential_offset def HangerFuncAmplitude(f, f0, Q, Qe, A, theta): @@ -288,7 +307,7 @@ def HangerFuncAmplitude(f, f0, Q, Qe, A, theta): f is in Hz f0 is in GHz ''' - return abs(A*(1.-Q/Qe*np.exp(1.j*theta)/(1.+2.j*Q*(f/1.e9-f0)/f0))) + return abs(A * (1. - Q / Qe * np.exp(1.j * theta) / (1. + 2.j * Q * (f / 1.e9 - f0) / f0))) def HangerFuncComplex(f, pars): @@ -310,8 +329,8 @@ def HangerFuncComplex(f, pars): phi_v = pars['phi_v'] phi_0 = pars['phi_0'] - S21 = A*(1-Q/Qe*np.exp(1j*theta)/(1+2.j*Q*(f/1.e9-f0)/f0)) * \ - np.exp(1j*(phi_v*f+phi_0)) + S21 = A * (1 - Q / Qe * np.exp(1j * theta) / (1 + 2.j * Q * (f / 1.e9 - f0) / f0)) * \ + np.exp(1j * (phi_v * f + phi_0)) return S21 @@ -320,50 +339,50 @@ def PolyBgHangerFuncAmplitude(f, f0, Q, Qe, A, theta, poly_coeffs): # This is the function for a hanger (lambda/4 resonator) which takes into # account a possible polynomial background # NOT DEBUGGED - return np.abs((1.+np.polyval(poly_coeffs, (f/1.e9-f0)/f0)) * + return np.abs((1. + np.polyval(poly_coeffs, (f / 1.e9 - f0) / f0)) * HangerFuncAmplitude(f, f0, Q, Qe, A, theta)) def SlopedHangerFuncAmplitude(f, f0, Q, Qe, A, theta, slope): # This is the function for a hanger (lambda/4 resonator) which takes into # account a possible slope df - return np.abs((1.+slope*(f/1.e9-f0)/f0) * + return np.abs((1. + slope * (f / 1.e9 - f0) / f0) * HangerFuncAmplitude(f, f0, Q, Qe, A, theta)) def SlopedHangerFuncComplex(f, f0, Q, Qe, A, theta, phi_v, phi_0, slope): # This is the function for a hanger (lambda/4 resonator) which takes into # account a possible slope df - return (1.+slope*(f/1.e9-f0)/f0)*np.exp(1.j*(phi_v*f+phi_0-phi_v*f[0])) * \ - HangerFuncComplex(f, f0, Q, Qe, A, theta) + return (1. + slope * (f / 1.e9 - f0) / f0) * np.exp(1.j * (phi_v * f + phi_0 - phi_v * f[0])) * \ + HangerFuncComplex(f, f0, Q, Qe, A, theta) def linear_with_offset(x, a, b): ''' A linear signal with a fixed offset. ''' - return a*x + b + return a * x + b def linear_with_background(x, a, b): ''' A linear signal with a fixed background. ''' - return np.sqrt((a*x)**2 + b**2) + return np.sqrt((a * x) ** 2 + b ** 2) def linear_with_background_and_offset(x, a, b, c): ''' A linear signal with a fixed background. ''' - return np.sqrt((a*x)**2 + b**2)+c + return np.sqrt((a * x) ** 2 + b ** 2) + c def gaussianCDF(x, amplitude, mu, sigma): """ CDF of gaussian is P(X<=x) = .5 erfc((mu-x)/(sqrt(2)sig)) """ - return 0.5 * amplitude * erfc((mu - x) / (np.sqrt(2)*sigma)) + return 0.5 * amplitude * erfc((mu - x) / (np.sqrt(2) * sigma)) def double_gaussianCDF(x, A_amplitude, A_mu, A_sigma, @@ -377,6 +396,37 @@ def double_gaussianCDF(x, A_amplitude, A_mu, A_sigma, CDF_B = gaussianCDF(x, amplitude=B_amplitude, mu=B_mu, sigma=B_sigma) return CDF_A + CDF_B +def ro_gauss(x, A_center, B_center, A_sigma, B_sigma, A_amplitude, + B_amplitude, A_spurious, B_spurious): + ''' + Two double-gaussians with sigma and mu/center of the residuals equal to the + according state. + ''' + gauss = lmfit.lineshapes.gaussian + A_gauss = gauss(x=x[0], center=A_center, sigma=A_sigma, amplitude=A_amplitude) + B_gauss = gauss(x=x[1], center=B_center, sigma=B_sigma, amplitude=B_amplitude) + gauss0 = ((1-A_spurious)*A_gauss + A_spurious*B_gauss) + gauss1 = ((1-B_spurious)*B_gauss + B_spurious*A_gauss) + return [gauss0, gauss1] + + +def ro_CDF(x, A_center, B_center, A_sigma, B_sigma, A_amplitude, + B_amplitude, A_spurious, B_spurious): + cdf = gaussianCDF + A_gauss = cdf(x=x[0], mu=A_center, sigma=A_sigma, amplitude=A_amplitude) + B_gauss = cdf(x=x[1], mu=B_center, sigma=B_sigma, amplitude=B_amplitude) + gauss0 = ((1-A_spurious)*A_gauss + A_spurious*B_gauss) + gauss1 = ((1-B_spurious)*B_gauss + B_spurious*A_gauss) + return [gauss0, gauss1] + + +def ro_CDF_discr(x, A_center, B_center, A_sigma, B_sigma, A_amplitude, + B_amplitude, A_spurious, B_spurious): + #A_amplitude /= 1-A_spurious + #B_amplitude /= 1-B_spurious + return ro_CDF(x, A_center, B_center, A_sigma, B_sigma, A_amplitude, + B_amplitude, A_spurious=0, B_spurious=0) + def gaussian_2D(x, y, amplitude=1, center_x=0, center_y=0, @@ -385,23 +435,23 @@ def gaussian_2D(x, y, amplitude=1, A 2D gaussian function. if you want to use this for fitting you need to flatten your data first. ''' - gaus = lmfit.lineshapes.gaussian - val = (gaus(x, amplitude, center_x, sigma_x) * - gaus(y, amplitude, center_y, sigma_y)) + gauss = lmfit.lineshapes.gaussian + val = (gauss(x, amplitude, center_x, sigma_x) * + gauss(y, amplitude, center_y, sigma_y)) return val def DoubleExpDecayFunc(t, tau1, tau2, amp1, amp2, offset, n): return (offset + - amp1 * np.exp(-(t / tau1)**n) + - amp2 * np.exp(-(t / tau2)**n)) + amp1 * np.exp(-(t / tau1) ** n) + + amp2 * np.exp(-(t / tau2) ** n)) def TripleExpDecayFunc(t, tau1, tau2, tau3, amp1, amp2, amp3, offset, n): return (offset + - amp1*np.exp(-(t/tau1)**n) + - amp2*np.exp(-(t/tau2)**n) + - amp3*np.exp(-(t/tau3)**n)) + amp1 * np.exp(-(t / tau1) ** n) + + amp2 * np.exp(-(t / tau2) ** n) + + amp3 * np.exp(-(t / tau3) ** n)) def avoided_crossing_mediated_coupling(flux, f_bus, f_center1, f_center2, @@ -423,7 +473,7 @@ def avoided_crossing_mediated_coupling(flux, f_bus, f_center1, f_center2, """ if type(flux_state) == int: - flux_state = [flux_state]*len(flux) + flux_state = [flux_state] * len(flux) frequencies = np.zeros([len(flux), 2]) for kk, dac in enumerate(flux): @@ -454,7 +504,7 @@ def avoided_crossing_direct_coupling(flux, f_center1, f_center2, """ if type(flux_state) == int: - flux_state = [flux_state]*len(flux) + flux_state = [flux_state] * len(flux) frequencies = np.zeros([len(flux), 2]) for kk, dac in enumerate(flux): @@ -485,7 +535,7 @@ def residual_complex_fcn(pars, cmp_fcn, x, y): ''' cmp_values = cmp_fcn(x, pars) - res = cmp_values-y + res = cmp_values - y res = np.append(res.real, res.imag) return res @@ -501,7 +551,7 @@ def exp_dec_guess(model, data, t): offs_guess = data[np.argmax(t)] amp_guess = data[np.argmin(t)] - offs_guess # guess tau by looking for value closest to 1/e - tau_guess = t[np.argmin(abs((amp_guess*(1/np.e) + offs_guess)-data))] + tau_guess = t[np.argmin(abs((amp_guess * (1 / np.e) + offs_guess) - data))] model.set_param_hint('amplitude', value=amp_guess) model.set_param_hint('tau', value=tau_guess) @@ -512,6 +562,114 @@ def exp_dec_guess(model, data, t): return params +def group_consecutives(vals, step=1): + """Return list of consecutive lists of numbers from vals (number list).""" + run = [] + result = [run] + expect = None + for v in vals: + if (v == expect) or (expect is None): + run.append(v) + else: + run = [v] + result.append(run) + expect = v + step + return result + + +def arc_guess(freq, dac, dd=0.1): + ''' + Expects the dac values to be sorted! + :param freq: + :param dac: + :param dd: + :return: + ''' + p = round(max(dd * len(dac), 1)) + f_small = np.average(np.sort(freq)[:p]) + np.std(np.sort(freq)[:p]) + f_big = np.average(np.sort(freq)[-p:]) - np.std(np.sort(freq)[-p:]) + #print(f_small * 1e-9, f_big * 1e-9) + + fmax = np.max(freq) + fmin = np.min(freq) + + dacs_ss = np.where(freq >= f_big)[0] + dacs_as = np.where(freq <= f_small)[0] + + dacs_ss_groups = group_consecutives(vals=dacs_ss, step=1) + dacs_as_groups = group_consecutives(vals=dacs_as, step=1) + + dacs_ss_single = [] + for g in dacs_ss_groups: + ind = g[np.argmax(freq[g])] + # ind = int(round(np.average(g))) + dacs_ss_single.append(ind) + + dac_ss_group_index = np.argmin(np.abs(dac[dacs_ss_single])) + dac_ss_index = dacs_ss_single[dac_ss_group_index] + min_left = 0 + min_right = len(dac) - 1 + dacs_as_single = [] + for g in dacs_as_groups: + if 0 in g: + ind = 0 + elif len(dac) - 1 in g: + ind = len(dac) - 1 + else: + ind = int(round(np.average(g))) + + if ind < dac_ss_index: + min_left = max(ind, min_left) + elif ind > dac_ss_index: + min_right = min(ind, min_right) + dacs_as_single.append(ind) + # print('maxs', dacs_ss_single) + # print('mins', dacs_as_single) + arc_len = (dac[min_right] - dac[min_left]) + + # print('%d to %d = %.5f' % (min_left, min_right, arc_len)) + if min_left == 0 or min_right == len(dac) - 1: + arc_len *= 2 + elif len(dacs_ss_groups) > 1: + arc_len = np.average(dac[dacs_ss_single[1:]] - dac[dacs_ss_single[:-1]]) + + return fmax, fmin, dac[dac_ss_index], arc_len + + +def Resonator_dac_arch_guess(model, freq, dac_voltage, f_max_qubit: float = None, E_c: float = None): + fmax, fmin, dac_ss, period = arc_guess(freq=freq, dac=dac_voltage) + coup_guess = 15e6 + + # todo make better f_res guess + f_res = np.mean(freq) # - (coup_guess ** 2 / (f_max_qubit - fmax)) + f_max_qubit_vary = f_max_qubit is None + f_max_qubit = f_max_qubit or f_res - 500e6 + + model.set_param_hint('f_0_res', value=f_res, min=f_res / 2, max=2 * f_res) + model.set_param_hint('f_max_qubit', value=f_max_qubit, min=3e9, max=8.5e9, vary=f_max_qubit_vary) + model.set_param_hint('dac_sweet_spot', value=dac_ss, min=(dac_ss - 0.005) / 2, max=2 * (dac_ss + 0.005)) + model.set_param_hint('V_per_phi0', value=period, min=(period - 0.005) / 3, max=5 * (period + 0.005)) + model.set_param_hint('asymmetry', value=0, max=1, min=-1) + model.set_param_hint('coupling', value=coup_guess, min=1e6, max=80e6) + E_c = E_c or 260e6 + model.set_param_hint('E_c', value=E_c, min=50e6, max=400e6) + + params = model.make_params() + return params + + +def Qubit_dac_arch_guess(model, freq, dac_voltage): + fmax, fmin, dac_ss, period = arc_guess(freq=freq, dac=dac_voltage) + model.set_param_hint('f_max', value=fmax, min=0.7 * fmax, max=1.3 * fmax) + model.set_param_hint('dac_sweet_spot', value=dac_ss, min=(dac_ss - 0.005) / 2, max=2 * (dac_ss + 0.005)) + model.set_param_hint('V_per_phi0', value=period, min=(period - 0.005) / 3, max=5 * (period + 0.005)) + model.set_param_hint('asymmetry', value=0, max=1, min=-1) + model.set_param_hint('E_c', value=260e6, min=50e6, max=400e6) + + params = model.make_params() + return params + + def idle_err_rate_guess(model, data, N): ''' Assumes exponential decay in estimating the parameters @@ -519,15 +677,14 @@ def idle_err_rate_guess(model, data, N): amp_guess = 0.5 offset = np.mean(data) N1 = np.mean(N) - N2= np.mean(N) + N2 = np.mean(N) params = model.make_params(A=amp_guess, - N1 = N1, - N2 = N2, + N1=N1, + N2=N2, offset=offset) return params - def fft_freq_phase_guess(data, t): ''' Guess for a cosine fit using FFT, only works for evenly spaced points @@ -535,14 +692,14 @@ def fft_freq_phase_guess(data, t): # Freq guess ! only valid with uniform sampling # Only first half of array is used, because the second half contains the # negative frequecy components, and we want a positive frequency. - w = np.fft.fft(data)[:len(data)//2] - f = np.fft.fftfreq(len(data), t[1]-t[0])[:len(w)] + w = np.fft.fft(data)[:len(data) // 2] + f = np.fft.fftfreq(len(data), t[1] - t[0])[:len(w)] w[0] = 0 # Removes DC component from fourier transform # Use absolute value of complex valued spectrum abs_w = np.abs(w) freq_guess = abs(f[abs_w == max(abs_w)][0]) - ph_guess = 2*np.pi-(2*np.pi*t[data == max(data)]*freq_guess)[0] + ph_guess = 2 * np.pi - (2 * np.pi * t[data == max(data)] * freq_guess)[0] # the condition data == max(data) can have several solutions # (for example when discretization is visible) # to prevent errors we pick the first solution @@ -557,7 +714,7 @@ def Cos_guess(model, data, t, **kwargs): model, model.__class__) """ - amp_guess = abs(max(data)-min(data))/2 # amp is positive by convention + amp_guess = abs(max(data) - min(data)) / 2 # amp is positive by convention offs_guess = np.mean(data) freq_guess, ph_guess = fft_freq_phase_guess(data, t) @@ -580,11 +737,11 @@ def exp_damp_osc_guess(model, data, t): The guess for the exponential is simpler as it sets the exponent (n) at 1 and the tau at 2/3 of the total range """ - amp_guess = abs(max(data)-min(data))/2 # amp is positive by convention + amp_guess = abs(max(data) - min(data)) / 2 # amp is positive by convention freq_guess, ph_guess = fft_freq_phase_guess(data, t) osc_offs_guess = 0 - tau_guess = 2/3*max(t) + tau_guess = 2 / 3 * max(t) exp_offs_guess = np.mean(data) n_guess = 1 @@ -602,10 +759,10 @@ def Cos_amp_phase_guess(model, data, f, t): ''' Guess for a cosine fit with fixed frequency f. ''' - amp_guess = abs(max(data)-min(data))/2 # amp is positive by convention + amp_guess = abs(max(data) - min(data)) / 2 # amp is positive by convention offs_guess = np.mean(data) - ph_guess = (-2*np.pi*t[data == max(data)]*f)[0] + ph_guess = (-2 * np.pi * t[data == max(data)] * f)[0] # the condition data == max(data) can have several solutions # (for example when discretization is visible) # to prevent errors we pick the first solution @@ -636,18 +793,32 @@ def gauss_2D_guess(model, data, x, y): Note: possibly not compatible if the model uses prefixes. ''' + dx = x[1:]-x[:-1] + dy = y[1:]-y[:-1] + sums = np.sum(((data[:-1,:-1]*dx).transpose()*dy)) + amp = np.sqrt(sums) data_grid = data.reshape(-1, len(np.unique(x))) x_proj_data = np.mean(data_grid, axis=0) y_proj_data = np.mean(data_grid, axis=1) - - x_guess = lmfit.models.GaussianModel().guess(x_proj_data, np.unique(x)) - y_guess = lmfit.models.GaussianModel().guess(y_proj_data, np.unique(y)) - - params = model.make_params(amplitude=1, - center_x=x_guess['center'].value, - center_y=y_guess['center'].value, - sigma_x=x_guess['sigma'].value, - sigma_y=y_guess['sigma'].value) + x.sort() + y.sort() + xm = lmfit.models.GaussianModel() + ym = lmfit.models.GaussianModel() + x_guess = xm.guess(data=x_proj_data, x=np.unique(x)) + x_res = xm.fit(data=x_proj_data, x=np.unique(x), params=x_guess) + y_guess = ym.guess(data=y_proj_data, x=np.unique(y)) + y_res = ym.fit(data=y_proj_data, x=np.unique(y), params=y_guess) + + x_guess = x_res.params + y_guess = y_res.params + model.set_param_hint('amplitude', value=amp, min=0.9*amp, max=1.1*amp, + vary=True) + model.set_param_hint('sigma_x', value=x_guess['sigma'].value, min=0, + vary=True) + model.set_param_hint('sigma_y', value=y_guess['sigma'].value, min=0, + vary=True) + params = model.make_params(center_x=x_guess['center'].value, + center_y=y_guess['center'].value,) return params @@ -658,7 +829,6 @@ def double_gauss_2D_guess(model, data, x, y): Assumptions on input data * input is a flattened version of a 2D grid. - * total surface under the gaussians sums up to 1. Note: possibly not compatible if the model uses prefixes. Note 2: see also gauss_2D_guess() for some notes on how to improve this function. @@ -703,15 +873,15 @@ def double_gauss_guess(model, data, x=None, **kwargs): if x is None: x = np.arange(len(data)) cdf = np.cumsum(data) - norm_cdf = cdf/cdf[-1] + norm_cdf = cdf / cdf[-1] par_dict = {'A_center': x[(np.abs(norm_cdf - 0.25)).argmin()], 'B_center': x[(np.abs(norm_cdf - 0.75)).argmin()], - 'A_sigma': (x[(np.abs(norm_cdf - 0.25 - .33/2)).argmin()] - - x[(np.abs(norm_cdf - 0.25 + .33/2)).argmin()]), - 'B_sigma': (x[(np.abs(norm_cdf - 0.75 - .33/2)).argmin()] - - x[(np.abs(norm_cdf - 0.75 + .33/2)).argmin()])} + 'A_sigma': (x[(np.abs(norm_cdf - 0.25 - .33 / 2)).argmin()] - + x[(np.abs(norm_cdf - 0.25 + .33 / 2)).argmin()]), + 'B_sigma': (x[(np.abs(norm_cdf - 0.75 - .33 / 2)).argmin()] - + x[(np.abs(norm_cdf - 0.75 + .33 / 2)).argmin()])} - amp = max(data)*(par_dict['A_sigma'] + par_dict['B_sigma'])/2. + amp = max(data) * (par_dict['A_sigma'] + par_dict['B_sigma']) / 2. if model is not None: # Specify explicitly because not all pars are set to those from the par # dict @@ -726,18 +896,66 @@ def double_gauss_guess(model, data, x=None, **kwargs): else: return par_dict +def ro_double_gauss_guess(model, data, x, fixed_p01 = False, fixed_p10 = False): + # An initial guess is done on the binned data with single gaussians + # to constrain the fit params and avoid fitting noise if + # e.g., mmt. ind. rel. is very low + gmod0 = lmfit.models.GaussianModel() + guess0 = gmod0.guess(data=data[0], x=x[0]) + gmod1 = lmfit.models.GaussianModel() + guess1 = gmod1.guess(data=data[1], x=x[1]) + + + model.set_param_hint( + 'A_center', vary=True, value=guess0['center'].value, + min=guess0['center'] - 2 * guess0['sigma'], + max=guess0['center'] + 2 * guess0['sigma']) + model.set_param_hint( + 'B_center', vary=True, value=guess1['center'].value, + min=guess1['center'] - 2 * guess1['sigma'], + max=guess1['center'] + 2 * guess1['sigma']) + model.set_param_hint('A_sigma', value=guess0['sigma'].value, vary=True) + model.set_param_hint('B_sigma', value=guess1['sigma'].value, vary=True) + + # Amplitudes + intarea0 = sum_int(x=x[0], y=data[0])[-1] + intarea1 = sum_int(x=x[1], y=data[1])[-1] + model.set_param_hint('A_amplitude', value=intarea0, vary=False) + model.set_param_hint('B_amplitude', value=intarea1, vary=False) + model.set_param_hint('SNR', expr='abs(A_center-B_center)*2/(A_sigma+B_sigma)', + vary=False) + + # Spurious excitement + f = np.sqrt(2*np.pi) + amp0 = 0.99 * np.max(data[0]) * guess0['sigma'] * f + amp1 = 0.99 * np.max(data[1]) * guess1['sigma'] * f + spurious0 = max(1-(amp0/intarea0), 1e-3) + spurious1 = max(1-(amp1/intarea1), 1e-3) + p01 = fixed_p01 if fixed_p01 is not False else spurious0 + p10 = fixed_p10 if fixed_p10 is not False else spurious1 + model.set_param_hint('A_spurious', value=p01, min=0, max=1, + vary=fixed_p01 is False) + model.set_param_hint('B_spurious', value=p10, min=0, max=1, + vary=fixed_p10 is False) + + return model.make_params() + + +def sum_int(x,y): + return np.cumsum(y[:-1]*(x[1:]-x[:-1])) + ################################# # User defined Models # ################################# # NOTE: it is actually better to instantiate the model within your analysis # file, this prevents the model params having a memory. -# A valid reason to define it here would be if you want to add a guess function +# A valid reason to define it here would beexp_dec_guess if you want to add a guess function CosModel = lmfit.Model(CosFunc) CosModel.guess = Cos_guess ExpDecayModel = lmfit.Model(ExpDecayFunc) TripleExpDecayModel = lmfit.Model(TripleExpDecayFunc) -ExpDecayModel.guess = exp_dec_guess +ExpDecayModel.guess = exp_dec_guess # todo: fix ExpDampOscModel = lmfit.Model(ExpDampOscFunc) GaussExpDampOscModel = lmfit.Model(GaussExpDampOscFunc) ExpDampDblOscModel = lmfit.Model(ExpDampDblOscFunc) @@ -770,7 +988,7 @@ def double_gauss_guess(model, data, x=None, **kwargs): LorentzModel = lmfit.Model(lmfit.models.lorentzian) Lorentz_w_background_Model = lmfit.models.LorentzianModel() + \ - lmfit.models.LinearModel() + lmfit.models.LinearModel() PolyBgHangerAmplitudeModel = (HangerAmplitudeModel * lmfit.models.PolynomialModel(degree=7)) @@ -805,34 +1023,33 @@ def plot_fitres2D_heatmap(fit_res, x, y, axs=None, cmap='viridis'): axs[2].set_title('initial guess') return axs - # Before defining a new model, take a look at the built in models in lmfit. # From http://lmfit.github.io/lmfit-py/builtin_models.html # Built-in Fitting Models in the models module # Peak-like models - # GaussianModel - # LorentzianModel - # VoigtModel - # PseudoVoigtModel - # Pearson7Model - # StudentsTModel - # BreitWignerModel - # LognormalModel - # DampedOcsillatorModel - # ExponentialGaussianModel - # SkewedGaussianModel - # DonaichModel +# GaussianModel +# LorentzianModel +# VoigtModel +# PseudoVoigtModel +# Pearson7Model +# StudentsTModel +# BreitWignerModel +# LognormalModel +# DampedOcsillatorModel +# ExponentialGaussianModel +# SkewedGaussianModel +# DonaichModel # Linear and Polynomial Models - # ConstantModel - # LinearModel - # QuadraticModel - # ParabolicModel - # PolynomialModel +# ConstantModel +# LinearModel +# QuadraticModel +# ParabolicModel +# PolynomialModel # Step-like models - # StepModel - # RectangleModel +# StepModel +# RectangleModel # Exponential and Power law models - # ExponentialModel - # PowerLawModel +# ExponentialModel +# PowerLawModel diff --git a/pycqed/analysis/measurement_analysis.py b/pycqed/analysis/measurement_analysis.py index 98ccf9f690..7655b6c9f3 100644 --- a/pycqed/analysis/measurement_analysis.py +++ b/pycqed/analysis/measurement_analysis.py @@ -20,6 +20,7 @@ from pycqed.analysis.tools import data_manipulation as dm_tools import imp import math + try: import pygsti except ImportError as e: @@ -56,7 +57,6 @@ else: raise - imp.reload(dm_tools) @@ -83,26 +83,26 @@ def __init__(self, TwoD=False, folder=None, auto=True, self.run_default_analysis(TwoD=TwoD, **kw) def set_plot_parameter_values(self, **kw): - #dpi for plots + # dpi for plots self.dpi = kw.pop('dpi', 300) - #font sizes + # font sizes self.font_size = kw.pop('font_size', 11) - #line widths connecting data points + # line widths connecting data points self.line_width = kw.pop('line_width', 2) - #lw of axes and text boxes + # lw of axes and text boxes self.axes_line_width = kw.pop('axes_line_width', 0.5) - #tick lengths + # tick lengths self.tick_length = kw.pop('tick_length', 4) - #tick line widths + # tick line widths self.tick_width = kw.pop('tick_width', 0.5) - #marker size for data points + # marker size for data points self.marker_size = kw.pop('marker_size', None) - #marker size for special points like + # marker size for special points like self.marker_size_special = kw.pop('marker_size_special', 8) - #peak freq., Rabi pi and pi/2 amplitudes + # peak freq., Rabi pi and pi/2 amplitudes self.box_props = kw.pop('box_props', dict(boxstyle='Square', facecolor='white', - alpha=0.8, lw=self.axes_line_width) ) + alpha=0.8, lw=self.axes_line_width)) self.tick_color = kw.get('tick_color', 'k') # tick label color get's updated in savefig @@ -114,7 +114,6 @@ def set_plot_parameter_values(self, **kw): "axes.labelcolor": self.axes_labelcolor, } plt.rcParams.update(params) - def load_hdf5data(self, folder=None, file_only=False, **kw): if folder is None: folder = self.folder @@ -128,9 +127,9 @@ def load_hdf5data(self, folder=None, file_only=False, **kw): self.g = self.data_file['Experimental Data'] self.measurementstring = os.path.split(folder)[1] self.timestamp = os.path.split(os.path.split(folder)[0])[1] \ - + '/' + self.measurementstring[:6] + + '/' + self.measurementstring[:6] self.timestamp_string = os.path.split(os.path.split(folder)[0])[1] \ - + '_' + self.measurementstring[:6] + + '_' + self.measurementstring[:6] self.measurementstring = self.measurementstring[7:] self.default_plot_title = self.measurementstring return self.data_file @@ -140,11 +139,11 @@ def finish(self, close_file=True, **kw): self.data_file.close() def analysis_h5data(self, name='analysis'): - if not os.path.exists(os.path.join(self.folder, name+'.hdf5')): + if not os.path.exists(os.path.join(self.folder, name + '.hdf5')): mode = 'w' else: mode = 'r+' - return h5py.File(os.path.join(self.folder, name+'.hdf5'), mode) + return h5py.File(os.path.join(self.folder, name + '.hdf5'), mode) def default_fig(self, **kw): figsize = kw.pop('figsize', None) @@ -185,10 +184,10 @@ def save_fig(self, fig, figname=None, xlabel='x', if xlabel == 'x': xlabel = self.sweep_name - figname = (self.measurementstring+'_'+ylabel + - '_vs_'+xlabel+'.'+plot_format) + figname = (self.measurementstring + '_' + ylabel + + '_vs_' + xlabel + '.' + plot_format) else: - figname = (figname+'.' + plot_format) + figname = (figname + '.' + plot_format) self.savename = os.path.abspath(os.path.join( self.folder, figname)) if fig_tight: @@ -245,11 +244,11 @@ def setup_figures_and_axes(self, main_figs=1): if val_len == 4: if self.no_of_columns == 2: self.figarray, self.axarray = plt.subplots( - val_len, 1, figsize=(3.375, 2.25**len(self.value_names)), + val_len, 1, figsize=(3.375, 2.25 ** len(self.value_names)), dpi=self.dpi) else: self.figarray, self.axarray = plt.subplots( - val_len, 1, figsize=(7, 4*len(self.value_names)), + val_len, 1, figsize=(7, 4 * len(self.value_names)), dpi=self.dpi) # val_len, 1, figsize=(min(8*len(self.value_names), 11), # 4*len(self.value_names))) @@ -257,13 +256,13 @@ def setup_figures_and_axes(self, main_figs=1): if self.no_of_columns == 2: self.figarray, self.axarray = plt.subplots( max(len(self.value_names), 1), 1, - figsize=(3.375, 2.25*len(self.value_names)), dpi=self.dpi) + figsize=(3.375, 2.25 * len(self.value_names)), dpi=self.dpi) # max(len(self.value_names), 1), 1, # figsize=(8, 4*len(self.value_names))) else: self.figarray, self.axarray = plt.subplots( max(len(self.value_names), 1), 1, - figsize=(7, 4*len(self.value_names)), dpi=self.dpi) + figsize=(7, 4 * len(self.value_names)), dpi=self.dpi) # max(len(self.value_names), 1), 1, # figsize=(8, 4*len(self.value_names))) @@ -354,9 +353,9 @@ def save_fitted_parameters(self, fit_res, var_name, save_peaks=False, # fit_res.fit_report() + \ # '\n'+'*'*80 + '\n\n' fit_grp.attrs['Fit Report'] = \ - '\n'+'*'*80+'\n' + \ + '\n' + '*' * 80 + '\n' + \ lmfit.fit_report(fit_res) + \ - '\n'+'*'*80 + '\n\n' + '\n' + '*' * 80 + '\n\n' fit_grp.attrs.create(name='chisqr', data=fit_res.chisqr) fit_grp.attrs.create(name='var_name', data=var_name.encode('utf-8')) @@ -397,8 +396,8 @@ def save_fitted_parameters(self, fit_res, var_name, save_peaks=False, if weights is not None: mean = np.mean(fit_res.data) std = np.std(fit_res.data) - weight = ((fit_res.data - mean)/std)**weights - weighted_chisqr = np.sum(weight*(fit_res.data-fit_res.best_fit)**2) + weight = ((fit_res.data - mean) / std) ** weights + weighted_chisqr = np.sum(weight * (fit_res.data - fit_res.best_fit) ** 2) fit_grp.attrs.create(name='weighted_chisqr', data=weighted_chisqr) def save_computed_parameters(self, computed_params, var_name): @@ -436,7 +435,7 @@ def save_computed_parameters(self, computed_params, var_name): except: # if it already exists overwrite existing par_group = fit_grp[par_name] par_group.attrs.create(name=par_name, data=par_val) - #par_dict = vars(par_val) + # par_dict = vars(par_val) else: fit_grp.attrs.create(name=par_name, data=par_val) @@ -452,24 +451,24 @@ def run_default_analysis(self, TwoD=False, close_file=True, if len(self.value_names) == 4: if self.no_of_columns == 2: fig, axs = plt.subplots( - nrows=int(len(self.value_names)/2), ncols=2, - figsize=(3.375, 2.25*len(self.value_names)), + nrows=int(len(self.value_names) / 2), ncols=2, + figsize=(3.375, 2.25 * len(self.value_names)), dpi=self.dpi) else: fig, axs = plt.subplots( nrows=len(self.value_names), ncols=1, - figsize=(7, 4*len(self.value_names)), dpi=self.dpi) + figsize=(7, 4 * len(self.value_names)), dpi=self.dpi) else: if self.no_of_columns == 2: fig, axs = plt.subplots(max(len(self.value_names), 1), 1, figsize=(3.375, - 2.25*len(self.value_names)), + 2.25 * len(self.value_names)), dpi=self.dpi) else: fig, axs = plt.subplots(max(len(self.value_names), 1), 1, figsize=( - 7, 4*len(self.value_names)), + 7, 4 * len(self.value_names)), dpi=self.dpi) # Add all the sweeps to the plot 1 by 1 # indices are determined by it's shape/number of sweeps @@ -479,7 +478,7 @@ def run_default_analysis(self, TwoD=False, close_file=True, elif self.no_of_columns == 1: ax = axs[i] elif self.no_of_columns == 2: - ax = axs[i//2, i % 2] + ax = axs[i // 2, i % 2] else: ax = axs[i] # If not 2 or 4 just gives a list of plots if i != 0: @@ -513,25 +512,25 @@ def run_default_analysis(self, TwoD=False, close_file=True, if len(self.value_names) == 4: if self.no_of_columns == 2: - fig, axs = plt.subplots(int(len(self.value_names)/2), 2, + fig, axs = plt.subplots(int(len(self.value_names) / 2), 2, figsize=(3.375, - 2.25*len(self.value_names)), + 2.25 * len(self.value_names)), dpi=self.dpi) else: fig, axs = plt.subplots(max(len(self.value_names)), 1, figsize=(7, - 4*len(self.value_names)), + 4 * len(self.value_names)), dpi=self.dpi) else: if self.no_of_columns == 2: fig, axs = plt.subplots(max(len(self.value_names), 1), 1, figsize=(3.375, - 2.25*len(self.value_names)), + 2.25 * len(self.value_names)), dpi=self.dpi) else: fig, axs = plt.subplots(max(len(self.value_names), 1), 1, figsize=(7, - 4*len(self.value_names)), + 4 * len(self.value_names)), dpi=self.dpi) for i in range(len(self.value_names)): @@ -540,7 +539,7 @@ def run_default_analysis(self, TwoD=False, close_file=True, elif len(self.value_names) == 2: ax = axs[i % 2] elif len(self.value_names) == 4: - ax = axs[i//2, i % 2] + ax = axs[i // 2, i % 2] else: ax = axs[i] # If not 2 or 4 just gives a list of plots @@ -621,8 +620,8 @@ def get_naming_and_values(self): self.measured_values.append( self.get_values(self.value_names[i])) self.ylabels.append(str( - self.value_names[i] + '('+value_units[i]+')')) - self.xlabel = str(self.sweep_name + '('+self.sweep_unit+')') + self.value_names[i] + '(' + value_units[i] + ')')) + self.xlabel = str(self.sweep_name + '(' + self.sweep_unit + ')') elif datasaving_format == 'Version 2': @@ -643,22 +642,23 @@ def get_naming_and_values(self): self.sweep_points = self.data[0:len(self.parameter_names), :] self.measured_values = self.data[-len(self.value_names):, :] - self.xlabel = self.parameter_names[0] + ' (' + \ - self.parameter_units[0] + ')' - self.parameter_labels = [a+' (' + b + ')' for a, b in zip( - self.parameter_names, - self.parameter_units)] + self.xlabel = self.parameter_names[0] + ' (' + \ + self.parameter_units[0] + ')' + self.parameter_labels = [a + ' (' + b + ')' for a, b in zip( + self.parameter_names, + self.parameter_units)] - self.ylabels = [a+' (' + b + ')' for a, b in zip(self.value_names, - self.value_units)] + self.ylabels = [a + ' (' + b + ')' for a, b in zip(self.value_names, + self.value_units)] if 'optimization_result' in self.g: self.optimization_result = OrderedDict({ 'generation': self.g['optimization_result'][:, 0], - 'evals': self.g['optimization_result'][:, 1], - 'xfavorite': self.g['optimization_result'][:, 2:2+len(self.parameter_names)], - 'stds': self.g['optimization_result'][:, 2+len(self.parameter_names):2+2*len(self.parameter_names)], - 'fbest': self.g['optimization_result'][:, -len(self.parameter_names)-1], + 'evals': self.g['optimization_result'][:, 1], + 'xfavorite': self.g['optimization_result'][:, 2:2 + len(self.parameter_names)], + 'stds': self.g['optimization_result'][:, + 2 + len(self.parameter_names):2 + 2 * len(self.parameter_names)], + 'fbest': self.g['optimization_result'][:, -len(self.parameter_names) - 1], 'xbest': self.g['optimization_result'][:, -len(self.parameter_names):]}) else: raise ValueError('datasaving_format "%s " not recognized' @@ -729,7 +729,7 @@ def plot_results_vs_sweepparam(self, x, y, fig, ax, show=False, marker='-o', if save: if log: # litle hack to only change savename if logarithmic - self.save_fig(fig, xlabel=xlabel, ylabel=(ylabel+'_log'), **kw) + self.save_fig(fig, xlabel=xlabel, ylabel=(ylabel + '_log'), **kw) else: self.save_fig(fig, xlabel=xlabel, ylabel=ylabel, **kw) return @@ -778,7 +778,7 @@ def plot_dB_from_linear(self, x, lin_amp, fig, ax, show=False, marker='.', **kw) ax.set_title(self.plot_title) ax.set_xlabel(xlabel) ax.set_ylabel(ylabel) - y_dB = 20*np.log10(lin_amp) + y_dB = 20 * np.log10(lin_amp) ax.plot(x, y_dB, marker) if show: plt.show() @@ -818,9 +818,9 @@ def get_naming_and_values_2D(self): self.measured_values.append( self.get_values(self.value_names[i])) self.zlabels.append(str( - self.value_names[i] + '('+value_units[i]+')')) - self.xlabel = str(self.sweep_name + '('+self.sweep_unit+')') - self.ylabel = str(self.sweep_name_2D + '('+self.sweep_unit_2D+')') + self.value_names[i] + '(' + value_units[i] + ')')) + self.xlabel = str(self.sweep_name + '(' + self.sweep_unit + ')') + self.ylabel = str(self.sweep_name_2D + '(' + self.sweep_unit_2D + ')') elif datasaving_format == 'Version 2': @@ -841,10 +841,10 @@ def get_naming_and_values_2D(self): # Adding np.nan for prematurely interupted experiments nr_missing_values = 0 - if len(x)%cols != 0: - nr_missing_values = cols - len(x)%cols - x = np.append(x, np.zeros(nr_missing_values)+np.nan) - y = np.append(y, np.zeros(nr_missing_values)+np.nan) + if len(x) % cols != 0: + nr_missing_values = cols - len(x) % cols + x = np.append(x, np.zeros(nr_missing_values) + np.nan) + y = np.append(y, np.zeros(nr_missing_values) + np.nan) # X,Y,Z can be put in colormap directly self.X = x.reshape(-1, cols) @@ -854,30 +854,30 @@ def get_naming_and_values_2D(self): if len(self.value_names) == 1: z = self.data[2] - z = np.append(z, np.zeros(nr_missing_values)+np.nan) + z = np.append(z, np.zeros(nr_missing_values) + np.nan) self.Z = z.reshape(-1, cols) self.measured_values = [self.Z.T] else: self.Z = [] self.measured_values = [] for i in range(len(self.value_names)): - z = self.data[2+i] - z = np.append(z, np.zeros(nr_missing_values)+np.nan) + z = self.data[2 + i] + z = np.append(z, np.zeros(nr_missing_values) + np.nan) Z = z.reshape(-1, cols) self.Z.append(Z) self.measured_values.append(Z.T) - self.xlabel = self.parameter_names[0] + ' (' + \ - self.parameter_units[0] + ')' - self.ylabel = self.parameter_names[1] + ' (' + \ - self.parameter_units[1] + ')' + self.xlabel = self.parameter_names[0] + ' (' + \ + self.parameter_units[0] + ')' + self.ylabel = self.parameter_names[1] + ' (' + \ + self.parameter_units[1] + ')' - self.parameter_labels = [a+' (' + b + ')' for a, b in zip( - self.parameter_names, - self.parameter_units)] + self.parameter_labels = [a + ' (' + b + ')' for a, b in zip( + self.parameter_names, + self.parameter_units)] - self.zlabels = [a+' (' + b + ')' for a, b in zip(self.value_names, - self.value_units)] + self.zlabels = [a + ' (' + b + ')' for a, b in zip(self.value_names, + self.value_units)] else: raise ValueError('datasaving_format "%s " not recognized' @@ -898,13 +898,13 @@ def get_best_fit_results(self, peak=False, weighted=False): i = np.where(self.value_names == var)[0] # relies # on looping order # of get_naming and variables, not the most robust way - norm_chisq = chisqr/np.std(self.measured_values[i]) + norm_chisq = chisqr / np.std(self.measured_values[i]) normalized_chisquares[key] = norm_chisq if peak: try: if ('dip' in item['Peaks'].attrs) or \ - ('peak' in item['Peaks'].attrs): + ('peak' in item['Peaks'].attrs): haspeak_lst += [key] except: pass @@ -943,8 +943,8 @@ def make_figures(self, **kw): ax.plot(self.sweep_points[0][-1], self.sweep_points[1][-1], 'o', markersize=5, c='w') plot_title = kw.pop('plot_title', textwrap.fill( - self.timestamp_string + '_' + - self.measurementstring, 40)) + self.timestamp_string + '_' + + self.measurementstring, 40)) ax.set_title(plot_title) set_xlabel(ax, self.parameter_names[0], self.parameter_units[0]) set_ylabel(ax, self.parameter_names[1], self.parameter_units[1]) @@ -956,7 +956,7 @@ class OptimizationAnalysis(MeasurementAnalysis): def run_default_analysis(self, close_file=True, show=False, plot_all=False, **kw): self.get_naming_and_values() try: - optimization_method = self.data_file['Instrument settings']\ + optimization_method = self.data_file['Instrument settings'] \ ['MC'].attrs['optimization_method'] except: optimization_method = 'Numerical' @@ -966,12 +966,12 @@ def run_default_analysis(self, close_file=True, show=False, plot_all=False, **kw break base_figname = optimization_method + ' optimization of ' + \ - self.value_names[i] + self.value_names[i] # Optimizable value vs n figure fig1_type = '%s vs n' % self.value_names[i] figname1 = base_figname + '\n' + fig1_type savename1 = self.timestamp_string + '_' + base_figname + '_' + \ - fig1_type + fig1_type fig1, ax = self.default_ax() ax.plot(self.measured_values[i], marker='o') # assumes only one value exists because it is an optimization @@ -1001,11 +1001,11 @@ def run_default_analysis(self, close_file=True, show=False, plot_all=False, **kw # Parameters vs n figure fig2, axarray = plt.subplots(len(self.parameter_names), 1, figsize=(8, - 4*len(self.parameter_names))) + 4 * len(self.parameter_names))) fig2_type = 'parameters vs n' figname2 = base_figname + '\n' + fig2_type savename2 = self.timestamp_string + '_' + base_figname + '_' + \ - fig2_type + fig2_type if len(self.parameter_names) != 1: axarray[0].set_title(self.timestamp_string + ' ' + figname2) @@ -1024,11 +1024,11 @@ def run_default_analysis(self, close_file=True, show=False, plot_all=False, **kw # Optimizable value vs paramter fig3, axarray = plt.subplots(len(self.parameter_names), 1, figsize=(8, - 4*len(self.parameter_names))) + 4 * len(self.parameter_names))) fig3_type = '%s vs parameters' % self.value_names[0] figname3 = base_figname + '\n' + fig3_type savename3 = self.timestamp_string + '_' + base_figname + '_' + \ - fig3_type + fig3_type cm = plt.cm.get_cmap('RdYlBu') if len(self.parameter_names) != 1: @@ -1098,7 +1098,6 @@ def run_default_analysis(self, close_file=True, show=False, plot_all=False, **kw class TD_Analysis(MeasurementAnalysis): - ''' Parent class for Time Domain (TD) analysis. Contains functions for rotating and normalizing data based on calibration coordinates. @@ -1198,11 +1197,11 @@ def run_default_analysis(self, close_main_fig=True, show=False, **kw): - save_fig = kw.pop('save_fig',True) - close_file = kw.pop('close_file',True) + save_fig = kw.pop('save_fig', True) + close_file = kw.pop('close_file', True) super().run_default_analysis(show=show, - close_file=close_file, **kw) + close_file=close_file, **kw) self.add_analysis_datagroup_to_file() @@ -1267,15 +1266,15 @@ def normalize_data_to_calibration_points(self, values, calsteps, # both are I pulses if verbose: print('Only I calibration point') - cal_zero_points = list(range(NoPts-int(calsteps),NoPts)) + cal_zero_points = list(range(NoPts - int(calsteps), NoPts)) cal_one_points = None elif calsteps == 4: if verbose: print('I and X180 calibration points') # first two cal points are I pulses, last two are X180 pulses - cal_zero_points = list(range(NoPts-int(calsteps), - int(NoPts-int(calsteps)/2))) - cal_one_points = list(range(int(NoPts-int(calsteps)/2), NoPts)) + cal_zero_points = list(range(NoPts - int(calsteps), + int(NoPts - int(calsteps) / 2))) + cal_one_points = list(range(int(NoPts - int(calsteps) / 2), NoPts)) elif (calsteps == 6) and last_ge_pulse: # oscillations between |g>-|f> # use the I cal points (data[-6] and data[-5]) and @@ -1283,9 +1282,9 @@ def normalize_data_to_calibration_points(self, values, calsteps, if verbose: print('Oscillations between |g> - |f>') print('I and X180_ef calibration points') - cal_zero_points = list(range(NoPts-int(calsteps), - NoPts-int(2*calsteps/3))) - cal_one_points = list(range(NoPts-int(calsteps/3), NoPts)) + cal_zero_points = list(range(NoPts - int(calsteps), + NoPts - int(2 * calsteps / 3))) + cal_one_points = list(range(NoPts - int(calsteps / 3), NoPts)) elif (calsteps == 6) and (not last_ge_pulse): # oscillations between |e>-|f> # use the X180 cal points (data[-4] and data[-3]) @@ -1293,9 +1292,9 @@ def normalize_data_to_calibration_points(self, values, calsteps, if verbose: print('Oscillations between |e> - |f>') print('X180 and X180_ef calibration points') - cal_zero_points = list(range(NoPts- int(2*calsteps/3), - NoPts-int(calsteps/3))) - cal_one_points = list(range(NoPts-int(calsteps/3), NoPts)) + cal_zero_points = list(range(NoPts - int(2 * calsteps / 3), + NoPts - int(calsteps / 3))) + cal_one_points = list(range(NoPts - int(calsteps / 3), NoPts)) else: # assume no cal points were used @@ -1314,9 +1313,9 @@ def normalize_data_to_calibration_points(self, values, calsteps, ' for 0 cal_points. Setting NoCalPoints to 4.') self.NoCalPoints = 4 calsteps = 4 - cal_zero_points = list(range(NoPts-int(self.NoCalPoints), - int(NoPts-int(self.NoCalPoints)/2))) - cal_one_points = list(range(int(NoPts-int(self.NoCalPoints)/2), NoPts)) + cal_zero_points = list(range(NoPts - int(self.NoCalPoints), + int(NoPts - int(self.NoCalPoints) / 2))) + cal_one_points = list(range(int(NoPts - int(self.NoCalPoints) / 2), NoPts)) self.corr_data = a_tools.normalize_data_v3( self.measured_values[0], cal_zero_points, cal_one_points) else: @@ -1385,17 +1384,17 @@ def __init__(self, cost_function=0, NoCalPoints=4, center_point=31, make_fig=Tru super(chevron_optimization_v1, self).__init__(**kw) def run_default_analysis(self, - close_main_fig=True, **kw): + close_main_fig=True, **kw): super(chevron_optimization_v1, self).run_default_analysis(**kw) sweep_points_wocal = self.sweep_points[:-4] measured_values_wocal = self.measured_values[0][:-4] output_fft = np.real_if_close(np.fft.rfft(measured_values_wocal)) ax_fft = np.fft.rfftfreq(len(measured_values_wocal), - d=sweep_points_wocal[1]-sweep_points_wocal[0]) + d=sweep_points_wocal[1] - sweep_points_wocal[0]) order_mask = np.argsort(ax_fft) y = output_fft[order_mask] - y = y/np.sum(np.abs(y)) + y = y / np.sum(np.abs(y)) u = np.where(np.arange(len(y)) == 0, 0, y) array_peaks = a_tools.peak_finder(np.arange(len(np.abs(y))), @@ -1405,7 +1404,7 @@ def run_default_analysis(self, self.period = 0. self.cost_value = 100. else: - self.period = 1./ax_fft[order_mask][array_peaks['peak_idx']] + self.period = 1. / ax_fft[order_mask][array_peaks['peak_idx']] if self.period == np.inf: self.period = 0. if self.cost_function == 0: @@ -1415,22 +1414,22 @@ def run_default_analysis(self, measured_values_wocal) def get_cost_value(self, x, y): - num_periods = np.floor(x[-1]/self.period) + num_periods = np.floor(x[-1] / self.period) if num_periods == np.inf: num_periods = 0 # sum of mins sum_min = 0. for i in range(int(num_periods)): - sum_min += np.interp((i+0.5)*self.period, x, y) + sum_min += np.interp((i + 0.5) * self.period, x, y) # print(sum_min) # sum of maxs sum_max = 0. for i in range(int(num_periods)): - sum_max += 1.-np.interp(i*self.period, x, y) + sum_max += 1. - np.interp(i * self.period, x, y) # print(sum_max) - return sum_max+sum_min + return sum_max + sum_min class chevron_optimization_v2(TD_Analysis): @@ -1441,23 +1440,23 @@ def __init__(self, NoCalPoints=4, center_point=31, make_fig=True, super(chevron_optimization_v2, self).__init__(**kw) def run_default_analysis(self, - close_main_fig=True, **kw): + close_main_fig=True, **kw): super(chevron_optimization_v2, self).run_default_analysis(**kw) measured_values = a_tools.normalize_data_v3(self.measured_values[0]) - self.cost_value_1, self.period = self.sum_cost(self.sweep_points*1e9, + self.cost_value_1, self.period = self.sum_cost(self.sweep_points * 1e9, measured_values) - self.cost_value_2 = self.swap_cost(self.sweep_points*1e9, + self.cost_value_2 = self.swap_cost(self.sweep_points * 1e9, measured_values) self.cost_value = [self.cost_value_1, self.cost_value_2] fig, ax = plt.subplots(1, figsize=(8, 6)) - min_idx, max_idx = self.return_max_min(self.sweep_points*1e9, + min_idx, max_idx = self.return_max_min(self.sweep_points * 1e9, measured_values, 1) - ax.plot(self.sweep_points*1e9, measured_values, 'b-') - ax.plot(self.sweep_points[min_idx]*1e9, measured_values[min_idx], 'r*') - ax.plot(self.sweep_points[max_idx]*1e9, measured_values[max_idx], 'g*') - ax.plot(self.period*0.5, self.cost_value_2, 'b*', label='SWAP cost') + ax.plot(self.sweep_points * 1e9, measured_values, 'b-') + ax.plot(self.sweep_points[min_idx] * 1e9, measured_values[min_idx], 'r*') + ax.plot(self.sweep_points[max_idx] * 1e9, measured_values[max_idx], 'g*') + ax.plot(self.period * 0.5, self.cost_value_2, 'b*', label='SWAP cost') ax.set_ylim(-0.05, 1.05) ax.text(35, 0.05, r'%.3f' % (self.cost_value_1), color='red') ax.xaxis.label.set_fontsize(13) @@ -1472,18 +1471,18 @@ def run_default_analysis(self, def analysis_on_fig(self, ax): measured_values = a_tools.normalize_data_v3(self.measured_values[0]) - self.cost_value_1, self.period = self.sum_cost(self.sweep_points*1e9, + self.cost_value_1, self.period = self.sum_cost(self.sweep_points * 1e9, measured_values) - self.cost_value_2 = self.swap_cost(self.sweep_points*1e9, + self.cost_value_2 = self.swap_cost(self.sweep_points * 1e9, measured_values) self.cost_value = [self.cost_value_1, self.cost_value_2] - min_idx, max_idx = self.return_max_min(self.sweep_points*1e9, + min_idx, max_idx = self.return_max_min(self.sweep_points * 1e9, measured_values, 1) - ax.plot(self.sweep_points*1e9, measured_values, 'b-') - ax.plot(self.sweep_points[min_idx]*1e9, measured_values[min_idx], 'r*') - ax.plot(self.sweep_points[max_idx]*1e9, measured_values[max_idx], 'g*') - ax.plot(self.period*0.5, self.cost_value_2, 'b*', label='SWAP cost') + ax.plot(self.sweep_points * 1e9, measured_values, 'b-') + ax.plot(self.sweep_points[min_idx] * 1e9, measured_values[min_idx], 'r*') + ax.plot(self.sweep_points[max_idx] * 1e9, measured_values[max_idx], 'g*') + ax.plot(self.period * 0.5, self.cost_value_2, 'b*', label='SWAP cost') ax.set_ylim(-0.05, 1.05) ax.text(35, 0.05, r'%.3f' % (self.cost_value_1), color='red') ax.xaxis.label.set_fontsize(13) @@ -1505,24 +1504,24 @@ def get_period(self, min_array, max_array): diff = sorted_vec[1:] - sorted_vec[:-1] avg = np.mean(diff) std = np.std(diff) - diff_filtered = np.where(np.abs(diff-avg) < std, diff, np.nan) + diff_filtered = np.where(np.abs(diff - avg) < std, diff, np.nan) diff_filtered = diff_filtered[~np.isnan(diff_filtered)] - # diff_filtered = diff - return 2.*np.mean(diff_filtered), np.std(diff_filtered) + # diff_filtered = diff + return 2. * np.mean(diff_filtered), np.std(diff_filtered) def spec_power(self, data_x, data_y): x_points = data_x[:-4] y_points = data_y[:-4] min_idx, max_idx = self.return_max_min(data_x, data_y, 1) period, st = self.get_period(data_x[min_idx], data_x[max_idx]) - f = 1./period + f = 1. / period output_fft = np.real_if_close(np.fft.rfft(y_points)) ax_fft = np.fft.rfftfreq(len(y_points), - d=x_points[1]-x_points[0]) + d=x_points[1] - x_points[0]) order_mask = np.argsort(ax_fft) y = output_fft[order_mask] - y = y/np.sum(np.abs(y)) + y = y / np.sum(np.abs(y)) return -np.interp(f, ax_fft, np.abs(y)) def sum_cost(self, data_x, data_y): @@ -1530,27 +1529,26 @@ def sum_cost(self, data_x, data_y): y_points = data_y[:-4] min_idx, max_idx = self.return_max_min(data_x, data_y, 4) period, st = self.get_period(data_x[min_idx], data_x[max_idx]) - num_periods = np.floor(x_points[-1]/period) + num_periods = np.floor(x_points[-1] / period) sum_min = 0. for i in range(int(num_periods)): - sum_min += np.interp((i+0.5)*period, x_points, y_points) + sum_min += np.interp((i + 0.5) * period, x_points, y_points) sum_max = 0. for i in range(int(num_periods)): - sum_max += 1.-np.interp(i*period, x_points, y_points) + sum_max += 1. - np.interp(i * period, x_points, y_points) - return sum_max+sum_min, period + return sum_max + sum_min, period def swap_cost(self, data_x, data_y): x_points = data_x[:-4] y_points = data_y[:-4] min_idx, max_idx = self.return_max_min(data_x, data_y, 4) period, st = self.get_period(data_x[min_idx], data_x[max_idx]) - return np.interp(period*0.5, x_points, y_points) + return np.interp(period * 0.5, x_points, y_points) class Rabi_Analysis(TD_Analysis): - """ Analysis script for a Rabi measurement: if not separate_fits: @@ -1619,7 +1617,7 @@ def __init__(self, label='Rabi', qb_name=None, NoCalPoints=0, **kw): def fit_data(self, print_fit_results=True, verbose=False, separate_fits=False): - self.fit_res = ['']*self.nr_quadratures #for legacy reasons + self.fit_res = [''] * self.nr_quadratures # for legacy reasons if not separate_fits: @@ -1627,30 +1625,30 @@ def fit_data(self, print_fit_results=True, verbose=False, separate_fits=False): # Find guess values # Frequency guess fft_of_data = np.fft.fft(self.normalized_data_points, norm='ortho') - power_spectrum = np.abs(fft_of_data)**2 + power_spectrum = np.abs(fft_of_data) ** 2 index_of_fourier_maximum = np.argmax( - power_spectrum[1:len(fft_of_data)//2])+1 + power_spectrum[1:len(fft_of_data) // 2]) + 1 - top_x_val=np.take(self.sweep_points, - np.argmax(self.normalized_data_points)) - bottom_x_val=np.take(self.sweep_points, - np.argmin(self.normalized_data_points)) + top_x_val = np.take(self.sweep_points, + np.argmax(self.normalized_data_points)) + bottom_x_val = np.take(self.sweep_points, + np.argmin(self.normalized_data_points)) if index_of_fourier_maximum == 1: if verbose: print('Initial guesses obtained by assuming the data trace ' 'is between one half and one period of the cosine.') - freq_guess = 1.0/(2.0*np.abs(bottom_x_val-top_x_val)) + freq_guess = 1.0 / (2.0 * np.abs(bottom_x_val - top_x_val)) else: if verbose: print('Initial guesses obtained from fft of data.') - fft_scale = 1.0/(self.sweep_points[-1]- - self.sweep_points[0]) - freq_guess = fft_scale*index_of_fourier_maximum + fft_scale = 1.0 / (self.sweep_points[-1] - + self.sweep_points[0]) + freq_guess = fft_scale * index_of_fourier_maximum # Amplitude guess - diff = 0.5*(max(self.normalized_data_points) - - min(self.normalized_data_points)) + diff = 0.5 * (max(self.normalized_data_points) - + min(self.normalized_data_points)) amp_guess = -diff # phase guess --> NOT NEEDED because in cal pts calibration we make sure @@ -1660,19 +1658,19 @@ def fit_data(self, print_fit_results=True, verbose=False, separate_fits=False): # phase_guess=-phase_guess # Offset guess - if np.abs( np.abs(min(self.normalized_data_points)) - - np.abs(max(self.normalized_data_points)) ) < 3: - offset_guess=(min(self.normalized_data_points)+ - max(self.normalized_data_points))/2 - elif np.abs(min(self.normalized_data_points))>\ + if np.abs(np.abs(min(self.normalized_data_points)) - + np.abs(max(self.normalized_data_points))) < 3: + offset_guess = (min(self.normalized_data_points) + + max(self.normalized_data_points)) / 2 + elif np.abs(min(self.normalized_data_points)) > \ np.abs(max(self.normalized_data_points)): - offset_guess=(min(self.normalized_data_points)- - max(self.normalized_data_points))/2 + offset_guess = (min(self.normalized_data_points) - + max(self.normalized_data_points)) / 2 else: - offset_guess=(max(self.normalized_data_points)- - min(self.normalized_data_points))/2 + offset_guess = (max(self.normalized_data_points) - + min(self.normalized_data_points)) / 2 - #Set up fit parameters and perform fit + # Set up fit parameters and perform fit cos_mod.set_param_hint('amplitude', value=amp_guess, vary=False) @@ -1682,8 +1680,8 @@ def fit_data(self, print_fit_results=True, verbose=False, separate_fits=False): cos_mod.set_param_hint('frequency', value=freq_guess, vary=True, - min=(1/(100 *self.sweep_pts_wo_cal_pts[-1])), - max=(20/self.sweep_pts_wo_cal_pts[-1])) + min=(1 / (100 * self.sweep_pts_wo_cal_pts[-1])), + max=(20 / self.sweep_pts_wo_cal_pts[-1])) cos_mod.set_param_hint('offset', value=offset_guess, vary=True) @@ -1697,15 +1695,15 @@ def fit_data(self, print_fit_results=True, verbose=False, separate_fits=False): init_data_diff = np.abs(self.fit_result.init_fit[0] - self.normalized_data_points[0]) - if (self.fit_result.chisqr > .35) or (init_data_diff>offset_guess): + if (self.fit_result.chisqr > .35) or (init_data_diff > offset_guess): logging.warning('Fit did not converge, varying phase.') fit_res_lst = [] - for phase_estimate in np.linspace(0, 2*np.pi, 8): + for phase_estimate in np.linspace(0, 2 * np.pi, 8): cos_mod.set_param_hint('phase', - value=phase_estimate, - vary=True) + value=phase_estimate, + vary=True) self.params = cos_mod.make_params() fit_res_lst += [cos_mod.fit( data=self.normalized_data_points, @@ -1715,7 +1713,7 @@ def fit_data(self, print_fit_results=True, verbose=False, separate_fits=False): chisqr_lst = [fit_res.chisqr for fit_res in fit_res_lst] self.fit_result = fit_res_lst[np.argmin(chisqr_lst)] - for i in range(self.nr_quadratures): #for legacy reasons + for i in range(self.nr_quadratures): # for legacy reasons self.fit_res[i] = self.fit_result try: @@ -1726,7 +1724,7 @@ def fit_data(self, print_fit_results=True, verbose=False, separate_fits=False): logging.warning(e) if print_fit_results: - print(self.fit_result.fit_report()) + print(self.fit_result.fit_report()) else: model = fit_mods.lmfit.Model(fit_mods.CosFunc) @@ -1735,8 +1733,8 @@ def fit_data(self, print_fit_results=True, verbose=False, separate_fits=False): # easier to do just one fit we stick to that. # We make an initial guess of the Rabi period using both # quadratures - data = np.sqrt(self.measured_values[0]**2 + - self.measured_values[1]**2) + data = np.sqrt(self.measured_values[0] ** 2 + + self.measured_values[1] ** 2) params = fit_mods.Cos_guess(model, data=data, t=self.sweep_points) fitRes = model.fit( @@ -1766,7 +1764,6 @@ def fit_data(self, print_fit_results=True, verbose=False, separate_fits=False): for fit_res in self.fit_res: print(fit_res.fit_report()) - def run_default_analysis(self, show=False, close_file=False, **kw): @@ -1776,13 +1773,12 @@ def run_default_analysis(self, show=False, save_fig=False, **kw) show_guess = kw.get('show_guess', False) - plot_amplitudes = kw.get('plot_amplitudes',True) - plot_errorbars = kw.get('plot_errorbars',False) - print_fit_results = kw.get('print_fit_results',False) + plot_amplitudes = kw.get('plot_amplitudes', True) + plot_errorbars = kw.get('plot_errorbars', False) + print_fit_results = kw.get('print_fit_results', False) separate_fits = kw.get('separate_fits', False) - self.nr_quadratures = len(self.ylabels) #for legacy reasons - + self.nr_quadratures = len(self.ylabels) # for legacy reasons # Create new sweep points without cal pts variable. Needed here because # we may have 0 cal pts, so writing self.sweep_points[:-self.NoCalPoints] # will give an error if self.NoCalPoints==0. @@ -1791,7 +1787,7 @@ def run_default_analysis(self, show=False, self.sweep_pts_wo_cal_pts = \ self.sweep_pts_wo_cal_pts[:-self.NoCalPoints] - #get the fit results (lmfit.ModelResult) and save them + # get the fit results (lmfit.ModelResult) and save them self.fit_data(print_fit_results, separate_fits=separate_fits) # if not separate_fits, get the computed pi and piHalf amplitudes @@ -1801,7 +1797,7 @@ def run_default_analysis(self, show=False, self.save_computed_parameters(self.rabi_amplitudes, var_name=self.value_names[0]) - #Plot results + # Plot results if self.make_fig: self.make_figures(show=show, show_guess=show_guess, plot_amplitudes=plot_amplitudes, @@ -1826,46 +1822,46 @@ def make_figures(self, show=False, show_guess=False, plot_amplitudes=True, if self.for_ef: pi_pulse_old = float(instr_set[self.qb_name].attrs['amp180_ef']) pi_half_pulse_old = \ - pi_pulse_old*float(instr_set[self.qb_name].attrs['amp90_scale_ef']) + pi_pulse_old * float(instr_set[self.qb_name].attrs['amp90_scale_ef']) else: pi_pulse_old = float(instr_set[self.qb_name].attrs['amp180']) pi_half_pulse_old = \ - pi_pulse_old*float(instr_set[self.qb_name].attrs['amp90_scale']) + pi_pulse_old * float(instr_set[self.qb_name].attrs['amp90_scale']) old_vals = '\n $\pi-Amp_{old}$ = %.3g ' % (pi_pulse_old) + \ - self.parameter_units[0]+ \ - '\n$\pi/2-Amp_{old}$ = %.3g '% (pi_half_pulse_old) + \ - self.parameter_units[0] + self.parameter_units[0] + \ + '\n$\pi/2-Amp_{old}$ = %.3g ' % (pi_half_pulse_old) + \ + self.parameter_units[0] except(TypeError, KeyError, ValueError): logging.warning('qb_name is None. Default value qb_name="qb" is ' 'used. Old parameter values will not be retrieved.') old_vals = '' - textstr = (' $\pi-Amp$ = %.3g ' % (pi_pulse)+self.parameter_units[0]+ - ' $\pm$ (%.3g) '% (self.rabi_amplitudes['piPulse_std'])+ - self.parameter_units[0]+ - '\n$\pi/2-Amp$ = %.3g '% (pi_half_pulse)+ - self.parameter_units[0]+ - ' $\pm$ (%.3g) '% (self.rabi_amplitudes['piHalfPulse_std'])+ - self.parameter_units[0]+ old_vals) + textstr = (' $\pi-Amp$ = %.3g ' % (pi_pulse) + self.parameter_units[0] + + ' $\pm$ (%.3g) ' % (self.rabi_amplitudes['piPulse_std']) + + self.parameter_units[0] + + '\n$\pi/2-Amp$ = %.3g ' % (pi_half_pulse) + + self.parameter_units[0] + + ' $\pm$ (%.3g) ' % (self.rabi_amplitudes['piHalfPulse_std']) + + self.parameter_units[0] + old_vals) - self.fig.text(0.5,0,textstr, - transform=self.ax.transAxes, fontsize=self.font_size, - verticalalignment='top', - horizontalalignment='center',bbox=self.box_props) + self.fig.text(0.5, 0, textstr, + transform=self.ax.transAxes, fontsize=self.font_size, + verticalalignment='top', + horizontalalignment='center', bbox=self.box_props) # Used for plotting the fit (line 1776) best_vals = self.fit_result.best_values cos_fit_func = lambda a: fit_mods.CosFunc(a, - amplitude=best_vals['amplitude'], - frequency=best_vals['frequency'], - phase=best_vals['phase'], - offset=best_vals['offset']) + amplitude=best_vals['amplitude'], + frequency=best_vals['frequency'], + phase=best_vals['phase'], + offset=best_vals['offset']) # Plot error bars if plot_errorbars: a_tools.plot_errorbars(self.sweep_pts_wo_cal_pts, self.normalized_data_points, - ax=self.ax,only_bars=True, + ax=self.ax, only_bars=True, linewidth=self.axes_line_width, marker='none', markersize=self.marker_size) @@ -1873,52 +1869,51 @@ def make_figures(self, show=False, show_guess=False, plot_amplitudes=True, # Plot with initial guess if show_guess: self.ax.plot(self.sweep_pts_wo_cal_pts, - self.fit_result.init_fit, 'k--', linewidth=self.line_width) + self.fit_result.init_fit, 'k--', linewidth=self.line_width) # Plot the calculated pi and pi/2 amplitudes if plot_amplitudes: - piPulse_fit = cos_fit_func(pi_pulse) piHalfPulse_fit = cos_fit_func(pi_half_pulse) # Plot 2 horizontal lines for piAmpl and piHalfAmpl self.ax.plot([min(self.sweep_points), max(self.sweep_points)], - [piPulse_fit, piPulse_fit], 'k--', - linewidth=self.axes_line_width) + [piPulse_fit, piPulse_fit], 'k--', + linewidth=self.axes_line_width) self.ax.plot([min(self.sweep_points), max(self.sweep_points)], - [piHalfPulse_fit, piHalfPulse_fit], 'k--', - linewidth=self.axes_line_width) + [piHalfPulse_fit, piHalfPulse_fit], 'k--', + linewidth=self.axes_line_width) # Plot two points for the pi and piHalf pulses self.ax.plot(pi_pulse, piPulse_fit, 'ro', - markersize=self.marker_size_special) + markersize=self.marker_size_special) self.ax.plot(pi_half_pulse, piHalfPulse_fit, 'ro', - markersize=self.marker_size_special) + markersize=self.marker_size_special) # Plot with best fit results x = np.linspace(self.sweep_points[0], self.sweep_pts_wo_cal_pts[-1], - len(self.sweep_points)*100) + len(self.sweep_points) * 100) y = cos_fit_func(x) self.ax.plot(x, y, 'r-', linewidth=self.line_width) - #display figure + # display figure if show: plt.show() - - #save figure - self.save_fig(self.fig, figname=self.measurementstring+'_Rabi_fit', + self.ax.set_ylabel('V_homodyne (a.u)') + # save figure + self.save_fig(self.fig, figname=self.measurementstring + '_Rabi_fit', **kw) else: if self.nr_quadratures == 2: self.figure, self.axs = plt.subplots(self.nr_quadratures, 1, - figsize=(5, 6)) + figsize=(5, 6)) else: self.figure, ax = plt.subplots(self.nr_quadratures, 1, - figsize=(5, 6)) + figsize=(5, 6)) self.axs = [ax] # to ensure it is a list of axes, as figure making relies on this x_fine = np.linspace(min(self.sweep_points), max(self.sweep_points), @@ -1944,15 +1939,15 @@ def make_figures(self, show=False, show_guess=False, plot_amplitudes=True, # adding the fitted amp180 if 'period' in self.fit_res[i].params.keys(): label = 'amp180 = {:.3e}'.format( - abs(self.fit_res[i].params['period'].value)/2) + abs(self.fit_res[i].params['period'].value) / 2) else: label = 'amp180 = {:.3e}'.format( abs(self.fit_res[i].params['x0'].value)) self.axs[i].plot(x_fine, fine_fit, label=label) ymin = min(self.measured_values[i]) ymax = max(self.measured_values[i]) - yspan = ymax-ymin - self.axs[i].set_ylim(ymin-0.23*yspan, 0.05*yspan+ymax) + yspan = ymax - ymin + self.axs[i].set_ylim(ymin - 0.23 * yspan, 0.05 * yspan + ymax) self.axs[i].legend(frameon=False, loc='lower left') if show_guess: @@ -1961,15 +1956,15 @@ def make_figures(self, show=False, show_guess=False, plot_amplitudes=True, self.axs[i].plot(x_fine, fine_fit, label='guess') self.axs[i].legend(loc='best') - #display figure + # display figure if show: plt.show() self.save_fig(self.figure, fig_tight=False, **kw) - def get_amplitudes(self,**kw): + def get_amplitudes(self, **kw): - #Extract the best fitted frequency and phase. + # Extract the best fitted frequency and phase. freq_fit = self.fit_result.best_values['frequency'] phase_fit = self.fit_result.best_values['phase'] @@ -1986,96 +1981,96 @@ def get_amplitudes(self,**kw): # If phase_fit<1, the piHalf amplitude<0. if phase_fit < 1: logging.info('The data could not be fitted correctly. ' - 'The fitted phase "%s" <1, which gives ' - 'negative piHalf ' - 'amplitude.' %phase_fit) + 'The fitted phase "%s" <1, which gives ' + 'negative piHalf ' + 'amplitude.' % phase_fit) stepsize = self.sweep_points[1] - self.sweep_points[0] - #Nyquist: wavelength>2*stepsize - if (freq_fit) > 2*stepsize: + # Nyquist: wavelength>2*stepsize + if (freq_fit) > 2 * stepsize: logging.info('The data could not be fitted correctly. The ' - 'frequency "%s" is too high.' %freq_fit) + 'frequency "%s" is too high.' % freq_fit) - #Extract pi and pi/2 amplitudes from best fit values + # Extract pi and pi/2 amplitudes from best fit values if phase_fit == 0: - piPulse = 1/(2*freq_fit) - piHalfPulse = 1/(4*freq_fit) - piPulse_std = freq_std/freq_fit - piHalfPulse_std = freq_std/freq_fit + piPulse = 1 / (2 * freq_fit) + piHalfPulse = 1 / (4 * freq_fit) + piPulse_std = freq_std / freq_fit + piHalfPulse_std = freq_std / freq_fit else: n = np.arange(-2, 3, 0.5) - piPulse_vals = (2*n*np.pi+np.pi-phase_fit)/(2*np.pi*freq_fit) - piHalfPulse_vals = (2*n*np.pi+np.pi/2-phase_fit)/(2*np.pi*freq_fit) + piPulse_vals = (2 * n * np.pi + np.pi - phase_fit) / (2 * np.pi * freq_fit) + piHalfPulse_vals = (2 * n * np.pi + np.pi / 2 - phase_fit) / (2 * np.pi * freq_fit) try: piHalfPulse = np.min(np.take(piHalfPulse_vals, - np.where(piHalfPulse_vals>=0))) + np.where(piHalfPulse_vals >= 0))) except ValueError: piHalfPulse = np.asarray([]) try: if piHalfPulse.size != 0: piPulse = np.min(np.take( - piPulse_vals, np.where(piPulse_vals>=piHalfPulse))) + piPulse_vals, np.where(piPulse_vals >= piHalfPulse))) else: piPulse = np.min(np.take(piPulse_vals, - np.where(piPulse_vals>=0.001))) + np.where(piPulse_vals >= 0.001))) except ValueError: piPulse = np.asarray([]) - if piPulse.size==0 or piPulse>max(self.sweep_points): - i=0 - while (piPulse_vals[i] max(self.sweep_points): + i = 0 + while (piPulse_vals[i] < min(self.sweep_points) and + i < piPulse_vals.size): + i += 1 piPulse = piPulse_vals[i] - if piHalfPulse.size==0 or piHalfPulse>max(self.sweep_points): - i=0 - while (piHalfPulse_vals[i] max(self.sweep_points): + i = 0 + while (piHalfPulse_vals[i] < min(self.sweep_points) and + i < piHalfPulse_vals.size): + i += 1 piHalfPulse = piHalfPulse_vals[i] # piPulse = 1/(2*freq_fit) - phase_fit/(2*np.pi*freq_fit) # piHalfPulse = 1/(4*freq_fit) - phase_fit/(2*np.pi*freq_fit) - #Calculate std. deviation for pi and pi/2 amplitudes based on error + # Calculate std. deviation for pi and pi/2 amplitudes based on error # propagation theory - #(http://ugastro.berkeley.edu/infrared09/PDF-2009/statistics1.pdf) - #Errors were assumed to be uncorrelated. + # (http://ugastro.berkeley.edu/infrared09/PDF-2009/statistics1.pdf) + # Errors were assumed to be uncorrelated. - #extract cov(phase,freq) + # extract cov(phase,freq) freq_idx = self.fit_result.var_names.index('frequency') phase_idx = self.fit_result.var_names.index('phase') if self.fit_result.covar is not None: - cov_freq_phase = self.fit_result.covar[freq_idx,phase_idx] + cov_freq_phase = self.fit_result.covar[freq_idx, phase_idx] else: - cov_freq_phase=0 + cov_freq_phase = 0 - piPulse_std = piPulse*np.sqrt( (2*np.pi*freq_std/freq_fit)**2 + - (phase_std/phase_fit)**2 - -cov_freq_phase/ - (np.pi*freq_fit*phase_fit) ) - piHalfPulse_std = np.sqrt( (piPulse_std)**2 + - (freq_std/freq_fit)**2 ) + piPulse_std = piPulse * np.sqrt((2 * np.pi * freq_std / freq_fit) ** 2 + + (phase_std / phase_fit) ** 2 + - cov_freq_phase / + (np.pi * freq_fit * phase_fit)) + piHalfPulse_std = np.sqrt((piPulse_std) ** 2 + + (freq_std / freq_fit) ** 2) if kw.get('print_parameters', False): - print('\u03C0'+'-Pulse Amplitude = {:.6} '.format(piPulse)+ - '('+self.parameter_units[-1]+')'+'\t'+ - '\u03C0'+'-Pulse Stddev = {:.6} '.format(piPulse_std)+ - '('+self.parameter_units[-1]+')'+'\n'+ - '\u03C0'+'/2-Pulse Amplitude = {:.6} '.format(piHalfPulse)+ - '('+self.parameter_units[-1]+')'+'\t'+ - '\u03C0'+'/2-Pulse Stddev = {:.6} '.format(piHalfPulse_std)+ - '('+self.parameter_units[-1]+')') - - #return as dict for ease of use with "save_computed_parameters" - self.rabi_amplitudes = {'piPulse':piPulse, - 'piPulse_std':piPulse_std, - 'piHalfPulse':piHalfPulse, - 'piHalfPulse_std':piHalfPulse_std} + print('\u03C0' + '-Pulse Amplitude = {:.6} '.format(piPulse) + + '(' + self.parameter_units[-1] + ')' + '\t' + + '\u03C0' + '-Pulse Stddev = {:.6} '.format(piPulse_std) + + '(' + self.parameter_units[-1] + ')' + '\n' + + '\u03C0' + '/2-Pulse Amplitude = {:.6} '.format(piHalfPulse) + + '(' + self.parameter_units[-1] + ')' + '\t' + + '\u03C0' + '/2-Pulse Stddev = {:.6} '.format(piHalfPulse_std) + + '(' + self.parameter_units[-1] + ')') + + # return as dict for ease of use with "save_computed_parameters" + self.rabi_amplitudes = {'piPulse': piPulse, + 'piPulse_std': piPulse_std, + 'piHalfPulse': piHalfPulse, + 'piHalfPulse_std': piHalfPulse_std} else: logging.warning("Fitted frequency is zero. The pi-pulse and " "pi/2-pulse will not be computed.") @@ -2084,19 +2079,19 @@ def get_amplitudes(self,**kw): def get_measured_amp180(self): # Retrieve amp180 value from data file # The "Analysis" group might contain the "Corrected data" dataset - #fit_grps = list(self.data_file['Analysis'].keys()) - #fitted_pars_0 = self.data_file['Analysis'][fit_grps[0]] + # fit_grps = list(self.data_file['Analysis'].keys()) + # fitted_pars_0 = self.data_file['Analysis'][fit_grps[0]] a = self.data_file['Analysis'] fit_grps = [i for i in a.values() if isinstance(i, h5py.Group)] fitted_pars_0 = fit_grps[0] - amp180 = fitted_pars_0['period'].attrs['value']/2 + amp180 = fitted_pars_0['period'].attrs['value'] / 2 # If there are two quadratures, return the amplitude with the smallest # errorbar if len(fit_grps) == 2: fitted_pars_1 = fit_grps[1] if (fitted_pars_1['period'].attrs['stderr'] < fitted_pars_0['period'].attrs['stderr']): - amp180 = fitted_pars_1['period'].attrs['value']/2 + amp180 = fitted_pars_1['period'].attrs['value'] / 2 return amp180 @@ -2108,13 +2103,13 @@ def __init__(self, NoCalPoints=4, center_point=31, make_fig=True, super(TD_UHFQC, self).__init__(**kw) def run_default_analysis(self, - close_main_fig=True, **kw): + close_main_fig=True, **kw): super(TD_UHFQC, self).run_default_analysis(**kw) measured_values = a_tools.normalize_data_v3(self.measured_values[0]) fig, ax = plt.subplots(1, figsize=(8, 6)) - ax.plot(self.sweep_points*1e9, measured_values, '-o') + ax.plot(self.sweep_points * 1e9, measured_values, '-o') ax.set_ylim(-0.05, 1.05) ax.xaxis.label.set_fontsize(13) ax.yaxis.label.set_fontsize(13) @@ -2163,8 +2158,8 @@ def make_figures(self, **kw): x_fine = np.linspace(min(self.sweep_points), max(self.sweep_points), 1000) plot_title = kw.pop('plot_title', textwrap.fill( - self.timestamp_string + '_' + - self.measurementstring, 40)) + self.timestamp_string + '_' + + self.measurementstring, 40)) self.plot_results_vs_sweepparam(x=self.sweep_points, y=self.corr_data, fig=self.fig, ax=self.ax, @@ -2179,8 +2174,8 @@ def make_figures(self, **kw): scale_factor, unit = SI_prefix_and_scale_factor( self.fit_res.params['tau'].value, self.parameter_units[0]) textstr = '$T_2$={:.3g}$\pm$({:.3g}) {} '.format( - self.fit_res.params['tau'].value*scale_factor, - self.fit_res.params['tau'].stderr*scale_factor, + self.fit_res.params['tau'].value * scale_factor, + self.fit_res.params['tau'].stderr * scale_factor, unit) if show_guess: self.ax.plot(x_fine, self.fit_res.eval( @@ -2252,9 +2247,9 @@ def run_default_analysis(self, close_file=True, **kw): self.measured_values[1][-1]]) self.measured_values[0][:] = ( - self.measured_values[0] - cal_0I)/(cal_1I-cal_0I) + self.measured_values[0] - cal_0I) / (cal_1I - cal_0I) self.measured_values[1][:] = ( - self.measured_values[1] - cal_0Q)/(cal_1Q-cal_0Q) + self.measured_values[1] - cal_0Q) / (cal_1Q - cal_0Q) self.sort_data() @@ -2282,15 +2277,15 @@ def sort_data(self): self.x_exc = self.x_exc[:-2] def calculate_cost_func(self, **kw): - num_points = len(self.sweep_points)-4 + num_points = len(self.sweep_points) - 4 - id_dat_swp = self.measured_values[1][:num_points//2] - ex_dat_swp = self.measured_values[1][num_points//2:-4] + id_dat_swp = self.measured_values[1][:num_points // 2] + ex_dat_swp = self.measured_values[1][num_points // 2:-4] - id_dat_cp = self.measured_values[0][:num_points//2] - ex_dat_cp = self.measured_values[0][num_points//2:-4] + id_dat_cp = self.measured_values[0][:num_points // 2] + ex_dat_cp = self.measured_values[0][num_points // 2:-4] - maximum_difference = max((id_dat_cp-ex_dat_cp)) + maximum_difference = max((id_dat_cp - ex_dat_cp)) # I think the labels are wrong in excited and identity but the value # we get is correct missing_swap_pop = np.mean(ex_dat_swp - id_dat_swp) @@ -2300,14 +2295,14 @@ def make_figures(self, **kw): # calculate fitted curves x_points_fit = np.linspace(self.x_idx[0], self.x_idx[-1], 50) fit_idx = self.fit_result['idx_amp'] \ - * np.cos(2*np.pi * self.fit_result['idx_freq'] - * x_points_fit + self.fit_result['idx_phase']) \ - + self.fit_result['idx_offset'] + * np.cos(2 * np.pi * self.fit_result['idx_freq'] + * x_points_fit + self.fit_result['idx_phase']) \ + + self.fit_result['idx_offset'] fit_exc = self.fit_result['exc_amp'] \ - * np.cos(2*np.pi * self.fit_result['exc_freq'] - * x_points_fit + self.fit_result['exc_phase']) \ - + self.fit_result['exc_offset'] + * np.cos(2 * np.pi * self.fit_result['exc_freq'] + * x_points_fit + self.fit_result['exc_phase']) \ + + self.fit_result['exc_offset'] self.fig, self.axs = plt.subplots(2, 1, figsize=(5, 6)) for i in [0, 1]: @@ -2317,8 +2312,8 @@ def make_figures(self, **kw): label='excitation') if i == self.oscillating_qubit: plot_title = kw.pop('plot_title', textwrap.fill( - self.timestamp_string + '_' + - self.measurementstring, 40)) + self.timestamp_string + '_' + + self.measurementstring, 40)) self.axs[i].plot(x_points_fit, fit_idx, '-') self.axs[i].plot(x_points_fit, fit_exc, '-') self.axs[i].legend() @@ -2333,14 +2328,14 @@ def fit_data(self, **kw): # Frequency is known, because we sweep the phase of the second pihalf # pulse in a Ramsey-type experiment. model = lmfit.Model((lambda t, amplitude, phase, offset: - amplitude*np.cos(2*np.pi*t/360.0 + phase)+offset)) + amplitude * np.cos(2 * np.pi * t / 360.0 + phase) + offset)) self.fit_result = {} # Fit case with no excitation first guess_params = fit_mods.Cos_amp_phase_guess( model, data=self.y_idx[self.oscillating_qubit], - f=1.0/360.0, t=self.x_idx) + f=1.0 / 360.0, t=self.x_idx) fit_res = model.fit( data=self.y_idx[self.oscillating_qubit], t=self.x_idx, @@ -2354,13 +2349,13 @@ def fit_data(self, **kw): guess_params = fit_mods.Cos_amp_phase_guess( model, data=self.y_exc[self.oscillating_qubit], - f=1.0/360.0, t=self.x_exc) + f=1.0 / 360.0, t=self.x_exc) fit_res = model.fit( data=self.y_exc[self.oscillating_qubit], t=self.x_exc, params=guess_params) self.fit_result['exc_amp'] = fit_res.values['amplitude'] - self.fit_result['exc_freq'] = 1.0/360.0 + self.fit_result['exc_freq'] = 1.0 / 360.0 self.fit_result['exc_phase'] = fit_res.values['phase'] self.fit_result['exc_offset'] = fit_res.values['offset'] @@ -2368,7 +2363,6 @@ def fit_data(self, **kw): class Motzoi_XY_analysis(TD_Analysis): - ''' Analysis for the Motzoi XY sequence (Xy-Yx) Extracts the alternating datapoints and then fits two polynomials. @@ -2387,8 +2381,8 @@ def run_default_analysis(self, close_file=True, close_main_fig=True, **kw): if self.cal_points is None: if len(self.measured_values) == 2: - self.corr_data = (self.measured_values[0]**2 + - self.measured_values[1]**2) + self.corr_data = (self.measured_values[0] ** 2 + + self.measured_values[1] ** 2) else: self.corr_data = self.measured_values[0] @@ -2420,8 +2414,8 @@ def make_figures(self, **kw): x_fine = np.linspace(min(self.sweep_points), max(self.sweep_points), 1000) plot_title = kw.pop('plot_title', textwrap.fill( - self.timestamp_string + '_' + - self.measurementstring, 40)) + self.timestamp_string + '_' + + self.measurementstring, 40)) self.ax.set_title(plot_title) self.ax.ticklabel_format(useOffset=False) @@ -2479,13 +2473,13 @@ def calculate_optimal_motzoi(self): b_vals0 = self.fit_res[0].best_values b_vals1 = self.fit_res[1].best_values x1, x2 = a_tools.solve_quadratic_equation( - b_vals1['a']-b_vals0['a'], b_vals1['b']-b_vals0['b'], - b_vals1['c']-b_vals0['c']) + b_vals1['a'] - b_vals0['a'], b_vals1['b'] - b_vals0['b'], + b_vals1['c'] - b_vals0['c']) self.optimal_motzoi = min(x1, x2, key=lambda x: abs(x)) return self.optimal_motzoi -class QScale_Analysis(TD_Analysis): +class QScale_Analysis(TD_Analysis): ''' Analysis for a DRAG pulse calibration measurement as described in Baur, M. PhD Thesis(2012): measurement sequence ( (xX)-(xY)-(xmY) ). @@ -2581,7 +2575,7 @@ def run_default_analysis(self, close_file=False, if kw.pop('save_fig', True): self.save_fig(fig, - figname=self.measurementstring+'_Qscale_fit', **kw) + figname=self.measurementstring + '_Qscale_fit', **kw) if close_file: self.data_file.close() @@ -2620,9 +2614,9 @@ def make_figures(self, fig=None, ax=None, **kw): ylabel = r'$F$ $\left(|e \rangle \right) (arb. units)$' fig.text(0.5, 0, textstr, fontsize=self.font_size, - transform=ax.transAxes, - verticalalignment='top', - horizontalalignment='center', bbox=self.box_props) + transform=ax.transAxes, + verticalalignment='top', + horizontalalignment='center', bbox=self.box_props) self.plot_results_vs_sweepparam(self.sweep_points_xX, self.corr_data_xX, fig, ax, @@ -2641,38 +2635,38 @@ def make_figures(self, fig=None, ax=None, **kw): ticks_around=True, xlabel=r'$q_{scales}$', ylabel=ylabel) - ax.legend(loc='best', prop={'size': self.font_size}) - #c = ['b', 'g', 'r'] + ax.legend(loc='best', prop={'size': self.font_size}) + # c = ['b', 'g', 'r'] c = ['g', 'r'] if hasattr(self, 'fit_res'): # for i in range(len(self.fit_res)): for i in range(len(c)): - fine_fit = self.fit_res[i+1].model.func( - x_fine, **self.fit_res[i+1].best_values) + fine_fit = self.fit_res[i + 1].model.func( + x_fine, **self.fit_res[i + 1].best_values) # if i == 0: # fine_fit = self.fit_res[i+1].best_values['c'] * \ # np.ones(x_fine.size) ax.plot(x_fine, fine_fit, c=c[i], linewidth=self.axes_line_width, label='fit') if show_guess: - fine_fit = self.fit_res[i+1].model.func( - x_fine, **self.fit_res[i+1].init_values) + fine_fit = self.fit_res[i + 1].model.func( + x_fine, **self.fit_res[i + 1].init_values) if i == 0: - fine_fit = self.fit_res[i+1].best_values['c'] * \ + fine_fit = self.fit_res[i + 1].best_values['c'] * \ np.ones(x_fine.size) ax.plot(x_fine, fine_fit, c=c[i], linewidth=self.axes_line_width, - label='guess') + label='guess') # Create custom legend blue_line = mlines.Line2D([], [], color='blue', marker='o', markersize=self.marker_size, label=r'$X_{\frac{\pi}{2}}X_{\pi}$') green_line = mlines.Line2D([], [], color='green', marker='o', - markersize=self.marker_size, - label=r'$X_{\frac{\pi}{2}}Y_{\pi}$') + markersize=self.marker_size, + label=r'$X_{\frac{\pi}{2}}Y_{\pi}$') red_line = mlines.Line2D([], [], color='red', marker='o', - markersize=self.marker_size, - label=r'$X_{\frac{\pi}{2}}Y_{-\pi}$') + markersize=self.marker_size, + label=r'$X_{\frac{\pi}{2}}Y_{-\pi}$') ax.legend(handles=[blue_line, green_line, red_line], loc='upper right', prop={'size': self.font_size}) @@ -2693,9 +2687,9 @@ def fit_data(self, **kw): model_linear = lmfit.models.LinearModel() self.fit_res = ['', '', ''] - #Fit xX measurement - constant + # Fit xX measurement - constant params = model_const.guess(data=self.corr_data_xX, - x=self.sweep_points_xX) + x=self.sweep_points_xX) self.fit_res[0] = model_const.fit( data=self.corr_data_xX, x=self.sweep_points_xX, @@ -2703,9 +2697,9 @@ def fit_data(self, **kw): self.save_fitted_parameters(fit_res=self.fit_res[0], var_name='xX') - #Fit xY measurement + # Fit xY measurement params = model_linear.guess(data=self.corr_data_xY, - x=self.sweep_points_xY) + x=self.sweep_points_xY) self.fit_res[1] = model_linear.fit( data=self.corr_data_xY, x=self.sweep_points_xY, @@ -2713,9 +2707,9 @@ def fit_data(self, **kw): self.save_fitted_parameters(fit_res=self.fit_res[1], var_name='xY') - #Fit xmY measurement + # Fit xmY measurement params = model_linear.guess(data=self.corr_data_xmY, - x=self.sweep_points_xmY) + x=self.sweep_points_xmY) self.fit_res[2] = model_linear.fit( data=self.corr_data_xmY, x=self.sweep_points_xmY, @@ -2723,55 +2717,55 @@ def fit_data(self, **kw): self.save_fitted_parameters(fit_res=self.fit_res[2], var_name='xmY') - if kw.get('print_fit_results',False): - print('Fit Report - X'+'\u03C0'+'/2 X'+'\u03C0'+':\n{}\n'. - format(self.fit_res[0].fit_report())+ - 'Fit Report - X'+'\u03C0'+'/2 Y'+'\u03C0'+':\n{}\n'. - format(self.fit_res[1].fit_report())+ - 'Fit Report - X'+'\u03C0'+'/2 Y-'+'\u03C0'+':\n{}\n'. + if kw.get('print_fit_results', False): + print('Fit Report - X' + '\u03C0' + '/2 X' + '\u03C0' + ':\n{}\n'. + format(self.fit_res[0].fit_report()) + + 'Fit Report - X' + '\u03C0' + '/2 Y' + '\u03C0' + ':\n{}\n'. + format(self.fit_res[1].fit_report()) + + 'Fit Report - X' + '\u03C0' + '/2 Y-' + '\u03C0' + ':\n{}\n'. format(self.fit_res[2].fit_report())) def calculate_optimal_qscale(self, threshold=0.02, **kw): - #The best qscale parameter is the point where all 3 curves intersect. + # The best qscale parameter is the point where all 3 curves intersect. print_parameters = kw.get('print_parameters', False) b_vals0 = self.fit_res[0].best_values b_vals1 = self.fit_res[1].best_values b_vals2 = self.fit_res[2].best_values - optimal_qscale = (b_vals1['intercept']-b_vals2['intercept'])/\ - (b_vals2['slope']-b_vals1['slope']) + optimal_qscale = (b_vals1['intercept'] - b_vals2['intercept']) / \ + (b_vals2['slope'] - b_vals1['slope']) # Warning if Xpi/2Xpi line is not within +/-threshold of 0.5 - if (b_vals0['c'] > (0.5+threshold)) or (b_vals0['c']<(0.5-threshold)): + if (b_vals0['c'] > (0.5 + threshold)) or (b_vals0['c'] < (0.5 - threshold)): logging.warning('The trace from the X90-X180 pulses is NOT within ' - '+/-%s of the expected value of 0.5.'%threshold) + '+/-%s of the expected value of 0.5.' % threshold) # Warning if optimal_qscale is not within +/-threshold of 0.5 - optimal_qscale_pop = optimal_qscale*b_vals2['slope']+b_vals2['intercept'] - if (optimal_qscale_pop > (0.5+threshold)) or \ - (optimal_qscale_pop<(0.5-threshold)): + optimal_qscale_pop = optimal_qscale * b_vals2['slope'] + b_vals2['intercept'] + if (optimal_qscale_pop > (0.5 + threshold)) or \ + (optimal_qscale_pop < (0.5 - threshold)): logging.warning('The optimal qscale found gives a population that is ' 'NOT within +/-%s of the expected value of 0.5.' - %threshold) + % threshold) - #Calculate standard deviation - #(http://ugastro.berkeley.edu/infrared09/PDF-2009/statistics1.pdf) + # Calculate standard deviation + # (http://ugastro.berkeley.edu/infrared09/PDF-2009/statistics1.pdf) b1_idx = self.fit_res[1].var_names.index('intercept') m1_idx = self.fit_res[1].var_names.index('slope') b2_idx = self.fit_res[2].var_names.index('intercept') m2_idx = self.fit_res[2].var_names.index('slope') if self.fit_res[1].covar is not None: - cov_b1_m1 = self.fit_res[1].covar[b1_idx,m1_idx] + cov_b1_m1 = self.fit_res[1].covar[b1_idx, m1_idx] else: cov_b1_m1 = 0 if self.fit_res[2].covar is not None: - cov_b2_m2 = self.fit_res[2].covar[b2_idx,m2_idx] + cov_b2_m2 = self.fit_res[2].covar[b2_idx, m2_idx] else: cov_b2_m2 = 0 - cov_qscale_squared = (- cov_b1_m1 - cov_b2_m2)**2 + cov_qscale_squared = (- cov_b1_m1 - cov_b2_m2) ** 2 intercept_diff_mean = self.fit_res[1].params['intercept'].value - \ self.fit_res[2].params['intercept'].value @@ -2779,39 +2773,39 @@ def calculate_optimal_qscale(self, threshold=0.02, **kw): self.fit_res[1].params['slope'].value intercept_diff_std_squared = \ - (self.fit_res[1].params['intercept'].stderr)**2 + \ - (self.fit_res[2].params['intercept'].stderr)**2 + (self.fit_res[1].params['intercept'].stderr) ** 2 + \ + (self.fit_res[2].params['intercept'].stderr) ** 2 slope_diff_std_squared = \ - (self.fit_res[2].params['slope'].stderr)**2 + \ - (self.fit_res[1].params['slope'].stderr)**2 - - sqrt_quantity = intercept_diff_std_squared/((intercept_diff_mean)**2) + \ - slope_diff_std_squared/((slope_diff_mean)**2) - \ - 2*cov_qscale_squared/(intercept_diff_mean*slope_diff_mean) - if sqrt_quantity<0: - optimal_qscale_stddev = optimal_qscale*np.sqrt( - intercept_diff_std_squared/((intercept_diff_mean)**2) + \ - slope_diff_std_squared/((slope_diff_mean)**2)) + (self.fit_res[2].params['slope'].stderr) ** 2 + \ + (self.fit_res[1].params['slope'].stderr) ** 2 + + sqrt_quantity = intercept_diff_std_squared / ((intercept_diff_mean) ** 2) + \ + slope_diff_std_squared / ((slope_diff_mean) ** 2) - \ + 2 * cov_qscale_squared / (intercept_diff_mean * slope_diff_mean) + if sqrt_quantity < 0: + optimal_qscale_stddev = optimal_qscale * np.sqrt( + intercept_diff_std_squared / ((intercept_diff_mean) ** 2) + \ + slope_diff_std_squared / ((slope_diff_mean) ** 2)) else: - optimal_qscale_stddev = optimal_qscale*np.sqrt(sqrt_quantity) + optimal_qscale_stddev = optimal_qscale * np.sqrt(sqrt_quantity) if print_parameters: print('Optimal QScale Parameter = {} \t QScale Stddev = {}'.format( optimal_qscale, optimal_qscale_stddev)) - #return as dict for use with "save_computed_parameters" - self.optimal_qscale = {'qscale':optimal_qscale, - 'qscale_std':optimal_qscale_stddev} + # return as dict for use with "save_computed_parameters" + self.optimal_qscale = {'qscale': optimal_qscale, + 'qscale_std': optimal_qscale_stddev} return self.optimal_qscale -class Rabi_Analysis_old(TD_Analysis): +class Rabi_Analysis_old(TD_Analysis): ''' This is the old Rabi analysis for the mathematica sequences of 60 points ''' - def __init__(self, label='Rabi', **kw): + def __init__(self, label='Rabi', **kw): kw['label'] = label kw['h5mode'] = 'r+' super(self.__class__, self).__init__(**kw) @@ -2829,7 +2823,7 @@ def run_default_analysis(self, print_fit_results=False, **kw): self.center_point = 0 fig, axarray = plt.subplots(2, 1, figsize=figsize) - fit_res = [None]*len(self.value_names) + fit_res = [None] * len(self.value_names) for i, name in enumerate(self.value_names): offset_estimate = np.mean(self.measured_values[i]) @@ -2838,27 +2832,27 @@ def run_default_analysis(self, print_fit_results=False, **kw): amplitude_sign = -1. else: amplitude_sign = 1. - amplitude_estimate = amplitude_sign*abs(max( - self.measured_values[i])-min(self.measured_values[i]))/2 + amplitude_estimate = amplitude_sign * abs(max( + self.measured_values[i]) - min(self.measured_values[i])) / 2 w = np.fft.fft( - self.measured_values[i][:-self.NoCalPoints]-offset_estimate) - index_of_fourier_maximum = np.argmax(np.abs(w[1:len(w)/2]))+1 - fourier_index_to_freq = 1/abs(self.sweep_points[0] - - self.sweep_points[-self.NoCalPoints]) + self.measured_values[i][:-self.NoCalPoints] - offset_estimate) + index_of_fourier_maximum = np.argmax(np.abs(w[1:len(w) / 2])) + 1 + fourier_index_to_freq = 1 / abs(self.sweep_points[0] - + self.sweep_points[-self.NoCalPoints]) if index_of_fourier_maximum < 3: print( 'Rabi period too long for fourier analysis, using single period as default guess') frequency_estimate = fourier_index_to_freq else: frequency_estimate = fourier_index_to_freq * \ - index_of_fourier_maximum + index_of_fourier_maximum # Guess for params fit_mods.CosModel.set_param_hint('amplitude', value=amplitude_estimate) fit_mods.CosModel.set_param_hint('frequency', value=frequency_estimate, - min=0, max=1/8.) + min=0, max=1 / 8.) fit_mods.CosModel.set_param_hint('offset', value=offset_estimate) fit_mods.CosModel.set_param_hint('phase', @@ -2870,7 +2864,7 @@ def run_default_analysis(self, print_fit_results=False, **kw): self.params = fit_mods.CosModel.make_params() displaced_fitting_axis = self.sweep_points[:-self.NoCalPoints] - \ - self.center_point + self.center_point fit_res[i] = fit_mods.CosModel.fit( data=self.measured_values[i][:-self.NoCalPoints], @@ -2896,28 +2890,28 @@ def run_default_analysis(self, print_fit_results=False, **kw): fit_res[i].init_fit, 'k--') x = np.linspace(min(displaced_fitting_axis), max(displaced_fitting_axis), - len(displaced_fitting_axis)*100) + len(displaced_fitting_axis) * 100) y = fit_mods.CosFunc(x, frequency=best_vals['frequency'], phase=best_vals['phase'], amplitude=best_vals['amplitude'], offset=best_vals['offset']) - axarray[i].plot(x+self.center_point, y, 'r-') + axarray[i].plot(x + self.center_point, y, 'r-') textstr = ( - ''' $f$ = %.3g $\pm$ (%.3g) - $A$ = %.3g $\pm$ (%.3g) - $\phi$ = %.3g $\pm$ (%.3g) - $a_0$ = %.3g $\pm$ (%.3g)''' % ( - fit_res[i].params['frequency'].value, - fit_res[i].params['frequency'].stderr, - fit_res[i].params['amplitude'].value, - fit_res[i].params['amplitude'].stderr, - fit_res[i].params['phase'].value, - fit_res[i].params['phase'].stderr, - fit_res[i].params['offset'].value, - fit_res[i].params['offset'].stderr)) + ''' $f$ = %.3g $\pm$ (%.3g) + $A$ = %.3g $\pm$ (%.3g) + $\phi$ = %.3g $\pm$ (%.3g) + $a_0$ = %.3g $\pm$ (%.3g)''' % ( + fit_res[i].params['frequency'].value, + fit_res[i].params['frequency'].stderr, + fit_res[i].params['amplitude'].value, + fit_res[i].params['amplitude'].stderr, + fit_res[i].params['phase'].value, + fit_res[i].params['phase'].stderr, + fit_res[i].params['offset'].value, + fit_res[i].params['offset'].stderr)) axarray[i].text(0.65, 0.95, textstr, transform=axarray[i].transAxes, @@ -2933,7 +2927,7 @@ def run_default_analysis(self, print_fit_results=False, **kw): if show_fig: plt.show() - self.save_fig(fig, figname=self.sweep_name+'Rabi_fit', **kw) + self.save_fig(fig, figname=self.sweep_name + 'Rabi_fit', **kw) if close_file: self.data_file.close() return fit_res @@ -2945,14 +2939,14 @@ def calculate_drive_scaling_factor(self, frequency): the max amplitude. ''' desired_period_in_indices = \ - (len(self.sweep_points)-self.NoCalPoints)/1.5 + (len(self.sweep_points) - self.NoCalPoints) / 1.5 sorted_swp = np.sort(self.sweep_points) # Sorting needed for when data is taken in other than ascending order step_per_index = sorted_swp[1] - sorted_swp[0] desired_period = desired_period_in_indices * step_per_index # calibration points max should be at -20 # and + 20 from the center -> period of 80 - desired_freq = 1/desired_period + desired_freq = 1 / desired_period rabi_scaling = desired_freq / frequency return rabi_scaling @@ -2991,8 +2985,14 @@ class SSRO_Analysis(MeasurementAnalysis): the optimum threshold and fidelity from cumulative histograms. ''' - def __init__(self, rotate=True, close_fig=True, channels=['I', 'Q'], - hist_log_scale: bool=True, **kw): + def __init__(self, rotate=True, close_fig=True, channels=None, + hist_log_scale: bool = True, **kw): + if channels is None: + channels = ['I', 'Q'] + + logging.warning('The use of this class is deprectated!' + + ' Use the new v2 analysis instead.') + kw['h5mode'] = 'r+' self.rotate = rotate self.channels = channels @@ -3010,11 +3010,14 @@ def run_default_analysis(self, rotate=True, channels=['I', 'Q'], no_fits=False, print_fit_results=False, + pge=None, peg=None, preselection=False, - n_bins: int=120, **kw): + n_bins: int = 120, **kw): self.add_analysis_datagroup_to_file() self.no_fits = no_fits + self.pge = pge #fixed fraction of ground state in the excited state histogram (relaxation) + self.peg = peg #fixed fraction of excited state in the ground state hitogram (residual population) self.get_naming_and_values() # plotting histograms of the raw shots on I and Q axis @@ -3027,12 +3030,12 @@ def run_default_analysis(self, rotate=True, shots_I_presel_0, shots_I_presel_1 = a_tools.zigzag( shots_I_data, sample_0, sample_1, nr_samples) shots_I_data_0, shots_I_data_1 = a_tools.zigzag( - shots_I_data, sample_0+1, sample_1+1, nr_samples) - shots_Q_data_0 = shots_I_data_0*0 - shots_Q_data_1 = shots_I_data_1*0 + shots_I_data, sample_0 + 1, sample_1 + 1, nr_samples) + shots_Q_data_0 = shots_I_data_0 * 0 + shots_Q_data_1 = shots_I_data_1 * 0 if preselection: - shots_Q_presel_0 = shots_I_presel_0*0 - shots_Q_presel_1 = shots_I_presel_1*0 + shots_Q_presel_0 = shots_I_presel_0 * 0 + shots_Q_presel_1 = shots_I_presel_1 * 0 else: # Try getting data by name first and by index otherwise @@ -3054,9 +3057,9 @@ def run_default_analysis(self, rotate=True, shots_Q_presel_0, shots_Q_presel_1 = a_tools.zigzag( shots_Q_data, sample_0, sample_1, nr_samples) shots_I_data_0, shots_I_data_1 = a_tools.zigzag( - shots_I_data, sample_0+1, sample_1+1, nr_samples) + shots_I_data, sample_0 + 1, sample_1 + 1, nr_samples) shots_Q_data_0, shots_Q_data_1 = a_tools.zigzag( - shots_Q_data, sample_0+1, sample_1+1, nr_samples) + shots_Q_data, sample_0 + 1, sample_1 + 1, nr_samples) # cutting off half data points (odd number of data points) min_len = np.min([np.size(shots_I_data_0), np.size(shots_I_data_1), @@ -3079,10 +3082,10 @@ def run_default_analysis(self, rotate=True, **kw) self.theta = theta if preselection: - shots_presel_1_rot = np.cos(theta)*shots_I_presel_1 - \ - np.sin(theta)*shots_Q_presel_1 - shots_presel_0_rot = np.cos(theta)*shots_I_presel_0 - \ - np.sin(theta)*shots_Q_presel_0 + shots_presel_1_rot = np.cos(theta) * shots_I_presel_1 - \ + np.sin(theta) * shots_Q_presel_1 + shots_presel_0_rot = np.cos(theta) * shots_I_presel_0 - \ + np.sin(theta) * shots_Q_presel_0 else: self.theta = 0 @@ -3109,17 +3112,17 @@ def run_default_analysis(self, rotate=True, except: V_th = self.V_th_a s = np.sign(np.mean(shots_I_data_1_rot - shots_I_data_0_rot)) - shots_gmask_0 = s*(V_th - shots_presel_0_rot) > 0 - shots_gmask_1 = s*(V_th - shots_presel_1_rot) > 0 + shots_gmask_0 = s * (V_th - shots_presel_0_rot) > 0 + shots_gmask_1 = s * (V_th - shots_presel_1_rot) > 0 shots_masked_0 = shots_I_data_0_rot[shots_gmask_0] shots_masked_1 = shots_I_data_1_rot[shots_gmask_1] self.total_points = np.size(shots_I_data_0_rot) + \ - np.size(shots_I_data_1_rot) + np.size(shots_I_data_1_rot) self.removed_points = self.total_points - \ - np.size(shots_masked_0) - \ - np.size(shots_masked_1) + np.size(shots_masked_0) - \ + np.size(shots_masked_1) min_len_masked = np.min([np.size(shots_masked_0), np.size(shots_masked_1)]) @@ -3161,28 +3164,28 @@ def optimize_IQ_angle(self, shots_I_1, shots_Q_1, shots_I_0, def gaussian(height, center_x, center_y, width_x, width_y): width_x = float(width_x) width_y = float(width_y) - return lambda x, y: height*np.exp(-(((center_x-x)/width_x)**2+( - (center_y-y)/width_y)**2)/2) + return lambda x, y: height * np.exp(-(((center_x - x) / width_x) ** 2 + ( + (center_y - y) / width_y) ** 2) / 2) def fitgaussian(data): params = moments(data) errorfunction = lambda p: np.ravel(gaussian(*p)(*np.indices( - data.shape))-data) + data.shape)) - data) p, success = optimize.leastsq(errorfunction, params) return p def moments(data): total = data.sum() X, Y = np.indices(data.shape) - x = (X*data).sum()/total - y = (Y*data).sum()/total + x = (X * data).sum() / total + y = (Y * data).sum() / total col = data[:, int(y)] eps = 1e-8 # To prevent division by zero - width_x = np.sqrt(abs((np.arange(col.size)-y)**2*col).sum()/( - col.sum()+eps)) + width_x = np.sqrt(abs((np.arange(col.size) - y) ** 2 * col).sum() / ( + col.sum() + eps)) row = data[int(x), :] - width_y = np.sqrt(abs((np.arange(row.size)-x)**2*row).sum()/( - row.sum()+eps)) + width_y = np.sqrt(abs((np.arange(row.size) - x) ** 2 * row).sum() / ( + row.sum() + eps)) height = data.max() return height, x, y, width_x, width_y @@ -3193,8 +3196,8 @@ def moments(data): params1 = fitgaussian(data1) fit1 = gaussian(*params1) # interpolating to find the gauss top x and y coordinates - x_lin = np.linspace(0, n_bins, n_bins+1) - y_lin = np.linspace(0, n_bins, n_bins+1) + x_lin = np.linspace(0, n_bins, n_bins + 1) + y_lin = np.linspace(0, n_bins, n_bins + 1) f_x_1 = interp1d(x_lin, xedges1, fill_value='extrapolate') x_1_max = f_x_1(params1[1]) f_y_1 = interp1d(y_lin, yedges1, fill_value='extrapolate') @@ -3207,15 +3210,15 @@ def moments(data): # following part will calculate the angle to rotate the IQ plane # All information is to be rotated to the I channel - y_diff = y_1_max-y_0_max - x_diff = x_1_max-x_0_max + y_diff = y_1_max - y_0_max + x_diff = x_1_max - x_0_max theta = -np.arctan2(y_diff, x_diff) - shots_I_1_rot = np.cos(theta)*shots_I_1 - np.sin(theta)*shots_Q_1 - shots_Q_1_rot = np.sin(theta)*shots_I_1 + np.cos(theta)*shots_Q_1 + shots_I_1_rot = np.cos(theta) * shots_I_1 - np.sin(theta) * shots_Q_1 + shots_Q_1_rot = np.sin(theta) * shots_I_1 + np.cos(theta) * shots_Q_1 - shots_I_0_rot = np.cos(theta)*shots_I_0 - np.sin(theta)*shots_Q_0 - shots_Q_0_rot = np.sin(theta)*shots_I_0 + np.cos(theta)*shots_Q_0 + shots_I_0_rot = np.cos(theta) * shots_I_0 - np.sin(theta) * shots_Q_0 + shots_Q_0_rot = np.sin(theta) * shots_I_0 + np.cos(theta) * shots_Q_0 return (theta, shots_I_1_rot, shots_I_0_rot) @@ -3236,21 +3239,21 @@ def no_fits_analysis(self, shots_I_1_rot, shots_I_0_rot, min_len, range=(min_voltage, max_voltage), density=1) cumsum_1 = np.cumsum(hist_1) - self.cumsum_1 = cumsum_1/cumsum_1[-1] # renormalizing + self.cumsum_1 = cumsum_1 / cumsum_1[-1] # renormalizing hist_0, bins = np.histogram(shots_I_0_rot, bins=1000, range=(min_voltage, max_voltage), density=1) cumsum_0 = np.cumsum(hist_0) - self.cumsum_0 = cumsum_0/cumsum_0[-1] # renormalizing + self.cumsum_0 = cumsum_0 / cumsum_0[-1] # renormalizing - cumsum_diff = (abs(self.cumsum_1-self.cumsum_0)) + cumsum_diff = (abs(self.cumsum_1 - self.cumsum_0)) cumsum_diff_list = cumsum_diff.tolist() self.index_V_th_a = int(cumsum_diff_list.index(np.max( cumsum_diff_list))) - V_th_a = bins[self.index_V_th_a]+(bins[1]-bins[0])/2 + V_th_a = bins[self.index_V_th_a] + (bins[1] - bins[0]) / 2 # adding half a bin size - F_a = 1-(1-cumsum_diff_list[self.index_V_th_a])/2 + F_a = 1 - (1 - cumsum_diff_list[self.index_V_th_a]) / 2 if plot: fig, ax = plt.subplots() @@ -3264,7 +3267,7 @@ def no_fits_analysis(self, shots_I_1_rot, shots_I_0_rot, min_len, plt.xlabel('DAQ voltage integrated (AU)', fontsize=14) plt.ylabel('Fraction', fontsize=14) - #plt.hist(SS_Q_data, bins=40,label = '0 Q') + # plt.hist(SS_Q_data, bins=40,label = '0 Q') plt.legend(loc=2) if masked: filename = 'raw-cumulative-histograms-masked' @@ -3293,9 +3296,9 @@ def s_curve_fits(self, shots_I_1_rot, shots_I_0_rot, min_len, masked=False, S_sorted_I_1 = np.sort(shots_I_1_rot) S_sorted_I_0 = np.sort(shots_I_0_rot) p_norm_I_1 = 1. * np.arange(len(S_sorted_I_1)) / \ - (len(S_sorted_I_1) - 1) + (len(S_sorted_I_1) - 1) p_norm_I_0 = 1. * np.arange(len(S_sorted_I_0)) / \ - (len(S_sorted_I_0) - 1) + (len(S_sorted_I_0) - 1) # fitting the curves with integral normal distribution def erfcc(x): @@ -3304,11 +3307,12 @@ def erfcc(x): """ z = abs(x) out = np.zeros(np.size(x)) - t = 1. / (1. + 0.5*z) - r = t * np.exp(-z*z-1.26551223+t*(1.00002368+t*(.37409196 + - t*(.09678418+t*(-.18628806+t*(.27886807 + - t*(-1.13520398+t*(1.48851587+t*(-.82215223 + - t*.17087277))))))))) + t = 1. / (1. + 0.5 * z) + r = t * np.exp(-z * z - 1.26551223 + t * (1.00002368 + t * (.37409196 + + t * (.09678418 + t * ( + -.18628806 + t * (.27886807 + + t * (-1.13520398 + t * (1.48851587 + t * (-.82215223 + + t * .17087277))))))))) if np.size(x) > 1: for k in range(np.size(x)): if (x[k] >= 0.): @@ -3319,12 +3323,12 @@ def erfcc(x): if (x > 0): out = r else: - out = 2-r + out = 2 - r return out def NormCdf(x, mu, sigma): - t = x-mu - y = 0.5*erfcc(-t/(sigma*np.sqrt(2.0))) + t = x - mu + y = 0.5 * erfcc(-t / (sigma * np.sqrt(2.0))) for k in range(np.size(x)): if y[k] > 1.0: y[k] = 1.0 @@ -3333,11 +3337,11 @@ def NormCdf(x, mu, sigma): NormCdfModel = lmfit.Model(NormCdf) def NormCdf2(x, mu0, mu1, sigma0, sigma1, frac1): - t0 = x-mu0 - t1 = x-mu1 - frac0 = 1-frac1 - y = frac1*0.5*erfcc(-t1/(sigma1*np.sqrt(2.0))) + \ - frac0*0.5*erfcc(-t0/(sigma0*np.sqrt(2.0))) + t0 = x - mu0 + t1 = x - mu1 + frac0 = 1 - frac1 + y = frac1 * 0.5 * erfcc(-t1 / (sigma1 * np.sqrt(2.0))) + \ + frac0 * 0.5 * erfcc(-t0 / (sigma0 * np.sqrt(2.0))) for k in range(np.size(x)): if y[k] > 1.0: y[k] = 1.0 @@ -3345,9 +3349,9 @@ def NormCdf2(x, mu0, mu1, sigma0, sigma1, frac1): NormCdf2Model = lmfit.Model(NormCdf2) NormCdfModel.set_param_hint('mu', value=(np.average(shots_I_0_rot) + - np.average(shots_I_1_rot))/2) + np.average(shots_I_1_rot)) / 2) NormCdfModel.set_param_hint('sigma', value=(np.std(shots_I_0_rot) + - np.std(shots_I_1_rot))/2, + np.std(shots_I_1_rot)) / 2, min=0) params = NormCdfModel.make_params() @@ -3373,7 +3377,10 @@ def NormCdf2(x, mu0, mu1, sigma0, sigma1, frac1): NormCdf2Model.set_param_hint('mu1', value=np.average(shots_I_1_rot)) NormCdf2Model.set_param_hint( 'sigma1', value=np.std(shots_I_1_rot), min=0) - NormCdf2Model.set_param_hint('frac1', value=0.9, min=0, max=1) + if self.pge==None: + NormCdf2Model.set_param_hint('frac1', value=0.9, min=0, max=1) + else: + NormCdf2Model.set_param_hint('frac1', value=1-self.pge, vary=False) # performing the double gaussfits of on 1 data params = NormCdf2Model.make_params() @@ -3396,8 +3403,12 @@ def NormCdf2(x, mu0, mu1, sigma0, sigma1, frac1): NormCdf2Model.set_param_hint('mu1', value=mu1_1, vary=False) NormCdf2Model.set_param_hint( 'sigma1', value=sigma1_1, min=0, vary=False) - NormCdf2Model.set_param_hint( - 'frac1', value=0.025, min=0, max=1, vary=True) + if self.peg==None: + NormCdf2Model.set_param_hint( + 'frac1', value=0.025, min=0, max=1, vary=True) + else: + NormCdf2Model.set_param_hint( + 'frac1', value=self.peg,vary=False) params = NormCdf2Model.make_params() fit_res_double_0 = NormCdf2Model.fit( @@ -3413,16 +3424,17 @@ def NormCdf2(x, mu0, mu1, sigma0, sigma1, frac1): frac1_0 = fit_res_double_0.params['frac1'].value def NormCdf(x, mu, sigma): - t = x-mu - y = 0.5*erfcc(-t/(sigma*np.sqrt(2.0))) + t = x - mu + y = 0.5 * erfcc(-t / (sigma * np.sqrt(2.0))) return y def NormCdfdiff(x, mu0=mu0, mu1=mu1, sigma0=sigma0, sigma1=sigma1): - y = -abs(NormCdf(x, mu0, sigma0)-NormCdf(x, mu1, sigma1)) + y = -abs(NormCdf(x, mu0, sigma0) - NormCdf(x, mu1, sigma1)) return y V_opt_single = optimize.brent(NormCdfdiff) F_single = -NormCdfdiff(x=V_opt_single) + # print 'V_opt_single', V_opt_single # print 'F_single', F_single @@ -3430,11 +3442,12 @@ def NormCdfdiff(x, mu0=mu0, mu1=mu1, sigma0=sigma0, sigma1=sigma1): # with arguments in brent optimization def NormCdfdiff(x, mu0=mu0_0, mu1=mu1_1, sigma0=sigma0_0, sigma1=sigma1_1): - y0 = -abs(NormCdf(x, mu0, sigma0)-NormCdf(x, mu1, sigma1)) + y0 = -abs(NormCdf(x, mu0, sigma0) - NormCdf(x, mu1, sigma1)) return y0 self.V_th_d = optimize.brent(NormCdfdiff) - F_d = 1-(1+NormCdfdiff(x=self.V_th_d))/2 + F_d = 1 - (1 + NormCdfdiff(x=self.V_th_d)) / 2 + # print 'F_corrected',F_corrected def NormCdfdiffDouble(x, mu0_0=mu0_0, @@ -3442,12 +3455,12 @@ def NormCdfdiffDouble(x, mu0_0=mu0_0, frac1_0=frac1_0, mu1_1=mu1_1, sigma0_1=sigma0_1, sigma1_1=sigma1_1, frac1_1=frac1_1): - distr0 = (1-frac1_0)*NormCdf(x, mu0_0, sigma0_0) + \ - (frac1_0)*NormCdf(x, mu1_1, sigma1_1) + distr0 = (1 - frac1_0) * NormCdf(x, mu0_0, sigma0_0) + \ + (frac1_0) * NormCdf(x, mu1_1, sigma1_1) - distr1 = (1-frac1_1)*NormCdf(x, mu0_0, sigma0_0) + \ - (frac1_1)*NormCdf(x, mu1_1, sigma1_1) - y = - abs(distr1-distr0) + distr1 = (1 - frac1_1) * NormCdf(x, mu0_0, sigma0_0) + \ + (frac1_1) * NormCdf(x, mu1_1, sigma1_1) + y = - abs(distr1 - distr0) return y # print "refresh" @@ -3455,9 +3468,9 @@ def NormCdfdiffDouble(x, mu0_0=mu0_0, # F_d = -NormCdfdiffDouble(x=self.V_th_d) # calculating the signal-to-noise ratio - signal = abs(mu0_0-mu1_1) - noise = (sigma0_0 + sigma1_1)/2 - SNR = signal/noise + signal = abs(mu0_0 - mu1_1) + noise = (sigma0_0 + sigma1_1) / 2 + SNR = signal / noise if plot: # plotting s-curves @@ -3514,8 +3527,8 @@ def NormCdfdiffDouble(x, mu0_0=mu0_0, # n1, bins1 = np.histogram(shots_I_1_rot, bins=int(min_len/50), # normed=1) - gdat, = pylab.plot(bins0[:-1]+0.5*(bins0[1]-bins0[0]), n0, 'C0o') - edat, = pylab.plot(bins1[:-1]+0.5*(bins1[1]-bins1[0]), n1, 'C3o') + gdat, = pylab.plot(bins0[:-1] + 0.5 * (bins0[1] - bins0[0]), n0, 'C0o') + edat, = pylab.plot(bins1[:-1] + 0.5 * (bins1[1] - bins1[0]), n1, 'C3o') # n, bins1, patches = np.hist(shots_I_1_rot, bins=int(min_len/50), # label = '1 I',histtype='step', @@ -3527,19 +3540,19 @@ def NormCdfdiffDouble(x, mu0_0=mu0_0, # add lines showing the fitted distribution # building up the histogram fits for off measurements - norm0 = (bins0[1]-bins0[0])*min_len - norm1 = (bins1[1]-bins1[0])*min_len + norm0 = (bins0[1] - bins0[0]) * min_len + norm1 = (bins1[1] - bins1[0]) * min_len - y0 = norm0*(1-frac1_0)*pylab.normpdf(bins0, mu0_0, sigma0_0) + \ - norm0*frac1_0*pylab.normpdf(bins0, mu1_0, sigma1_0) - y1_0 = norm0*frac1_0*pylab.normpdf(bins0, mu1_0, sigma1_0) - y0_0 = norm0*(1-frac1_0)*pylab.normpdf(bins0, mu0_0, sigma0_0) + y0 = norm0 * (1 - frac1_0) * pylab.normpdf(bins0, mu0_0, sigma0_0) + \ + norm0 * frac1_0 * pylab.normpdf(bins0, mu1_0, sigma1_0) + y1_0 = norm0 * frac1_0 * pylab.normpdf(bins0, mu1_0, sigma1_0) + y0_0 = norm0 * (1 - frac1_0) * pylab.normpdf(bins0, mu0_0, sigma0_0) # building up the histogram fits for on measurements - y1 = norm1*(1-frac1_1)*pylab.normpdf(bins1, mu0_1, sigma0_1) + \ - norm1*frac1_1*pylab.normpdf(bins1, mu1_1, sigma1_1) - y1_1 = norm1*frac1_1*pylab.normpdf(bins1, mu1_1, sigma1_1) - y0_1 = norm1*(1-frac1_1)*pylab.normpdf(bins1, mu0_1, sigma0_1) + y1 = norm1 * (1 - frac1_1) * pylab.normpdf(bins1, mu0_1, sigma0_1) + \ + norm1 * frac1_1 * pylab.normpdf(bins1, mu1_1, sigma1_1) + y1_1 = norm1 * frac1_1 * pylab.normpdf(bins1, mu1_1, sigma1_1) + y0_1 = norm1 * (1 - frac1_1) * pylab.normpdf(bins1, mu0_1, sigma0_1) pylab.semilogy(bins0, y0, 'C0', linewidth=1.5) pylab.semilogy(bins0, y1_0, 'C0--', linewidth=3.5) @@ -3549,7 +3562,7 @@ def NormCdfdiffDouble(x, mu0_0=mu0_0, pylab.semilogy(bins1, y0_1, 'C3--', linewidth=3.5) pylab.semilogy(bins1, y1_1, 'C3--', linewidth=3.5) pdf_max = (max(max(y0), max(y1))) - (pylab.gca()).set_ylim(pdf_max/1000, 2*pdf_max) + (pylab.gca()).set_ylim(pdf_max / 1000, 2 * pdf_max) plt.title('Histograms of {} shots, {}'.format( min_len, self.timestamp_string)) @@ -3570,9 +3583,9 @@ def NormCdfdiffDouble(x, mu0_0=mu0_0, '$F_d$ = {:.4f}'.format(F_d), 'SNR = {:.2f}'.format(SNR), '$p(e|0)$ = {:.4f}'.format(frac1_0), - '$p(g|\pi)$ = {:.4f}'.format(1-frac1_1)] + '$p(g|\pi)$ = {:.4f}'.format(1 - frac1_1)] if masked: - p_rem = self.removed_points/self.total_points + p_rem = self.removed_points / self.total_points markers += [nomarker] labels += ['$p_{{rem}}$ = {:.4f}'.format(p_rem)] lgd = plt.legend(markers, labels, bbox_to_anchor=(1.05, 1), @@ -3662,8 +3675,8 @@ def plot_2D_histograms(self, shots_I_0, shots_Q_0, shots_I_1, shots_Q_1, 1], self.value_units[1]) else: set_ylabel(axarray[0], 'Dummy axis') - #axarray[0].set_xlim(-edge, edge) - #axarray[0].set_ylim(-edge, edge) + # axarray[0].set_xlim(-edge, edge) + # axarray[0].set_ylim(-edge, edge) # plotting 2D histograms of mmts with no pulse axarray[1].set_title('2D histogram, no pi pulse') @@ -3678,14 +3691,13 @@ def plot_2D_histograms(self, shots_I_0, shots_Q_0, shots_I_1, shots_Q_1, 1], self.value_units[1]) else: set_ylabel(axarray[1], 'Dummy axis') - #axarray[1].set_xlim(-edge, edge) - #axarray[1].set_ylim(-edge, edge) + # axarray[1].set_xlim(-edge, edge) + # axarray[1].set_ylim(-edge, edge) self.save_fig(fig, figname='SSRO_Density_Plots', close_fig=self.close_fig, **kw) class SSRO_discrimination_analysis(MeasurementAnalysis): - ''' Analysis that takes IQ-shots and extracts discrimination fidelity from it by fitting 2 2D gaussians. It does not assumption on what state the @@ -3704,14 +3716,14 @@ def __init__(self, **kw): def run_default_analysis(self, plot_2D_histograms=True, current_threshold=None, theta_in=0, - n_bins: int=120, **kw): + n_bins: int = 120, **kw): self.add_analysis_datagroup_to_file() self.get_naming_and_values() I_shots = self.measured_values[0] Q_shots = self.measured_values[1] if theta_in != 0: - shots = I_shots+1j*Q_shots + shots = I_shots + 1j * Q_shots rot_shots = dm_tools.rotate_complex( shots, angle=theta_in, deg=True) I_shots = rot_shots.real @@ -3757,7 +3769,7 @@ def run_default_analysis(self, plot_2D_histograms=True, ax.set_ylim(-edge, edge) # ax.set_axis_bgcolor(plt.cm.viridis(0)) set_ylabel(axs[0], 'Q', self.value_units[1]) - #axs[0].ticklabel_format(style = 'sci', fontsize=4) + # axs[0].ticklabel_format(style = 'sci', fontsize=4) self.save_fig( fig, figname='2D-Histograms_rot_{:.1f} deg'.format(theta_in), **kw) @@ -3781,9 +3793,9 @@ def run_default_analysis(self, plot_2D_histograms=True, self.theta = np.angle(diff_vec, deg=True) self.mean_sigma = np.mean([sig_a, sig_b]) # relative separation of the gaussians in units of sigma - self.relative_separation = abs(diff_vec)/self.mean_sigma + self.relative_separation = abs(diff_vec) / self.mean_sigma # relative separation of the gaussians when projected on the I-axis - self.relative_separation_I = diff_vec.real/self.mean_sigma + self.relative_separation_I = diff_vec.real / self.mean_sigma ####################################################### # Calculating discrimanation fidelities based on erfc # @@ -3791,32 +3803,31 @@ def run_default_analysis(self, plot_2D_histograms=True, # CDF of gaussian is P(X<=x) = .5 erfc((mu-x)/(sqrt(2)sig)) # Along the optimal direction - CDF_a = .5 * math.erfc((abs(diff_vec/2)) / - (np.sqrt(2)*sig_a)) - CDF_b = .5 * math.erfc((-abs(diff_vec/2)) / - (np.sqrt(2)*sig_b)) - self.F_discr = 1-(1-abs(CDF_a - CDF_b))/2 + CDF_a = .5 * math.erfc((abs(diff_vec / 2)) / + (np.sqrt(2) * sig_a)) + CDF_b = .5 * math.erfc((-abs(diff_vec / 2)) / + (np.sqrt(2) * sig_b)) + self.F_discr = 1 - (1 - abs(CDF_a - CDF_b)) / 2 # Projected on the I-axis CDF_a = .5 * math.erfc((self.mu_a.real - self.opt_I_threshold) / - (np.sqrt(2)*sig_a)) + (np.sqrt(2) * sig_a)) CDF_b = .5 * math.erfc((self.mu_b.real - self.opt_I_threshold) / - (np.sqrt(2)*sig_b)) + (np.sqrt(2) * sig_b)) self.F_discr_I = abs(CDF_a - CDF_b) # Current threshold projected on the I-axis if current_threshold is not None: CDF_a = .5 * math.erfc((self.mu_a.real - current_threshold) / - (np.sqrt(2)*sig_a)) + (np.sqrt(2) * sig_a)) CDF_b = .5 * math.erfc((self.mu_b.real - current_threshold) / - (np.sqrt(2)*sig_b)) - self.F_discr_curr_t = 1-(1-abs(CDF_a - CDF_b))/2 + (np.sqrt(2) * sig_b)) + self.F_discr_curr_t = 1 - (1 - abs(CDF_a - CDF_b)) / 2 self.finish(**kw) class touch_n_go_SSRO_Analysis(MeasurementAnalysis): - ''' Script to analyze the single shots used for touch and go selection ''' @@ -3827,7 +3838,6 @@ def __init__(self, label='touch_n_go', **kw): super(self.__class__, self).__init__(**kw) def run_default_analysis(self, print_fit_results=False, **kw): - self.add_analysis_datagroup_to_file() # plotting histograms of the raw shots on I and Q axis @@ -3839,7 +3849,7 @@ def run_default_analysis(self, print_fit_results=False, **kw): # plotting the histograms before rotation fig, axes = plt.subplots(figsize=(10, 10)) axes.hist(shots_I_data, bins=100, label='I', histtype='step', normed=1) - #axes.hist(shots_Q_data, bins=40, label = '0 Q',histtype='step',normed=1) + # axes.hist(shots_Q_data, bins=40, label = '0 Q',histtype='step',normed=1) axes.axvline(x=threshold, ls='--', label='threshold') axes.set_title( @@ -3847,7 +3857,7 @@ def run_default_analysis(self, print_fit_results=False, **kw): plt.xlabel('DAQ voltage integrated (AU)', fontsize=14) plt.ylabel('Fraction', fontsize=14) - #plt.hist(SS_Q_data, bins=40,label = '0 Q') + # plt.hist(SS_Q_data, bins=40,label = '0 Q') plt.legend() self.save_fig(fig, figname='raw-histograms', **kw) plt.show() @@ -3856,13 +3866,12 @@ def run_default_analysis(self, print_fit_results=False, **kw): class SSRO_single_quadrature_discriminiation_analysis(MeasurementAnalysis): - ''' Analysis that fits two gaussians to a histogram of a dataset. Uses this to extract F_discr and the optimal threshold ''' - def __init__(self, weight_func: str=None, **kw): + def __init__(self, weight_func: str = None, **kw): """ Bin all acquired data into historgrams and fit two gaussians to determine the @@ -3917,10 +3926,10 @@ def fit_data(self, hist, centers): def make_figures(self, hist, centers, show_guess=False, **kw): self.fig, self.ax = plt.subplots(figsize=(5, 3)) - width = .7 * (centers[1]-centers[0]) + width = .7 * (centers[1] - centers[0]) plot_title = kw.pop('plot_title', textwrap.fill( - self.timestamp_string + '_' + - self.measurementstring, 40)) + self.timestamp_string + '_' + + self.measurementstring, 40)) x_fine = np.linspace(min(centers), max(centers), 1000) @@ -3949,7 +3958,7 @@ def make_figures(self, hist, centers, show_guess=False, **kw): self.ax.vlines(self.opt_threshold, ylim[0], ylim[1], linestyles='--', label='opt. threshold') self.ax.text(.95, .95, 'F_discr {:.2f}\nOpt.thresh. {:.2f}'.format( - self.F_discr, self.opt_threshold), + self.F_discr, self.opt_threshold), verticalalignment='top', horizontalalignment='right', transform=self.ax.transAxes) self.ax.legend() @@ -3972,21 +3981,20 @@ def calculate_discrimination_fidelity(self, fit_res): s_a = fit_res.best_values['A_sigma'] s_b = fit_res.best_values['B_sigma'] - x_fine = np.linspace(min(mu_a-4*s_a, mu_b-4*s_b), - max(mu_b+4*s_a, mu_b+4*s_b), 1000) + x_fine = np.linspace(min(mu_a - 4 * s_a, mu_b - 4 * s_b), + max(mu_b + 4 * s_a, mu_b + 4 * s_b), 1000) CDF_a = np.zeros(len(x_fine)) CDF_b = np.zeros(len(x_fine)) for i, x in enumerate(x_fine): - CDF_a[i] = .5 * erfc((mu_a-x)/(np.sqrt(2)*s_a)) - CDF_b[i] = .5 * erfc((mu_b-x)/(np.sqrt(2)*s_b)) - F_discr_conservative = np.max(abs(CDF_a-CDF_b)) - F_discr = 1-(1-F_discr_conservative)/2 - opt_threshold = x_fine[np.argmax(abs(CDF_a-CDF_b))] + CDF_a[i] = .5 * erfc((mu_a - x) / (np.sqrt(2) * s_a)) + CDF_b[i] = .5 * erfc((mu_b - x) / (np.sqrt(2) * s_b)) + F_discr_conservative = np.max(abs(CDF_a - CDF_b)) + F_discr = 1 - (1 - F_discr_conservative) / 2 + opt_threshold = x_fine[np.argmax(abs(CDF_a - CDF_b))] return F_discr, opt_threshold class T1_Analysis(TD_Analysis): - """ Most kw parameters for Rabi_Analysis are also used here. """ @@ -4004,9 +4012,9 @@ def fit_T1(self, **kw): min=0, max=2) fit_mods.ExpDecayModel.set_param_hint('tau', - value=self.sweep_points[1]*50, + value=self.sweep_points[1] * 50, min=self.sweep_points[1], - max=self.sweep_points[-1]*1000) + max=self.sweep_points[-1] * 1000) fit_mods.ExpDecayModel.set_param_hint('offset', value=0, vary=False) @@ -4016,10 +4024,10 @@ def fit_T1(self, **kw): self.params = fit_mods.ExpDecayModel.make_params() fit_res = fit_mods.ExpDecayModel.fit(data=self.normalized_data_points, - t=self.sweep_points[:-self.NoCalPoints], - params=self.params) + t=self.sweep_points[:-self.NoCalPoints], + params=self.params) - if kw.get('print_fit_results',False): + if kw.get('print_fit_results', False): print(fit_res.fit_report()) return fit_res @@ -4029,61 +4037,61 @@ def run_default_analysis(self, show=False, close_file=False, **kw): super().run_default_analysis(show=show, close_file=close_file, close_main_figure=True, - save_fig=False,**kw) + save_fig=False, **kw) show_guess = kw.get('show_guess', False) - # make_fig = kw.get('make_fig',True) + # make_fig = kw.get('make_fig',True) self.add_analysis_datagroup_to_file() - #Perform fit and save fitted parameters + # Perform fit and save fitted parameters self.fit_res = self.fit_T1(**kw) self.save_fitted_parameters(fit_res=self.fit_res, var_name='F|1>') - #Create self.T1 and self.T1_stderr and save them - self.get_measured_T1() #in seconds + # Create self.T1 and self.T1_stderr and save them + self.get_measured_T1() # in seconds self.save_computed_parameters(self.T1_dict, var_name=self.value_names[0]) - T1_micro_sec = self.T1_dict['T1']*1e6 - T1_err_micro_sec = self.T1_dict['T1_stderr']*1e6 - #Print T1 and error on screen + T1_micro_sec = self.T1_dict['T1'] * 1e6 + T1_err_micro_sec = self.T1_dict['T1_stderr'] * 1e6 + # Print T1 and error on screen if kw.get('print_parameters', False): - print('T1 = {:.5f} ('.format(T1_micro_sec)+'μs) \t ' - 'T1 StdErr = {:.5f} ('.format( - T1_err_micro_sec)+'μs)') + print('T1 = {:.5f} ('.format(T1_micro_sec) + 'μs) \t ' + 'T1 StdErr = {:.5f} ('.format( + T1_err_micro_sec) + 'μs)') - #Plot best fit and initial fit + data + # Plot best fit and initial fit + data if self.make_fig: - units = SI_prefix_and_scale_factor( val=max(abs(self.ax.get_xticks())), - unit=self.sweep_unit[0] )[1] + units = SI_prefix_and_scale_factor(val=max(abs(self.ax.get_xticks())), + unit=self.sweep_unit[0])[1] # Get old values instr_set = self.data_file['Instrument settings'] try: if self.for_ef: - T1_old = float(instr_set[self.qb_name].attrs['T1_ef'])*1e6 + T1_old = float(instr_set[self.qb_name].attrs['T1_ef']) * 1e6 else: - T1_old = float(instr_set[self.qb_name].attrs['T1'])*1e6 - old_vals = '\nold $T_1$ = {:.5f} '.format(T1_old) + units + T1_old = float(instr_set[self.qb_name].attrs['T1']) * 1e6 + old_vals = '\nold $T_1$ = {:.5f} '.format(T1_old) + units except (TypeError, KeyError, ValueError): logging.warning('qb_name is None. Old parameter values will ' 'not be retrieved.') old_vals = '' - textstr = ('$T_1$ = {:.5f} '.format(T1_micro_sec) + + textstr = ('$T_1$ = {:.5f} '.format(T1_micro_sec) + units + ' $\pm$ {:.5f} '.format(T1_err_micro_sec) + units + old_vals) self.fig.text(0.5, 0, textstr, transform=self.ax.transAxes, - fontsize=self.font_size, - verticalalignment='top', - horizontalalignment='center', - bbox=self.box_props) + fontsize=self.font_size, + verticalalignment='top', + horizontalalignment='center', + bbox=self.box_props) if show_guess: self.ax.plot(self.sweep_points[:-self.NoCalPoints], - self.fit_res.init_fit, 'k--', linewidth=self.line_width) + self.fit_res.init_fit, 'k--', linewidth=self.line_width) best_vals = self.fit_res.best_values t = np.linspace(self.sweep_points[0], @@ -4102,7 +4110,7 @@ def run_default_analysis(self, show=False, close_file=False, **kw): if show: plt.show() - self.save_fig(self.fig, figname=self.measurementstring+'_Fit', **kw) + self.save_fig(self.fig, figname=self.measurementstring + '_Fit', **kw) if close_file: self.data_file.close() @@ -4117,15 +4125,14 @@ def get_measured_T1(self): # T1 = self.fit_res.params['tau'].value # T1_stderr = self.fit_res.params['tau'].stderr - #return as dict for use with "save_computed_parameters"; units are - #seconds - self.T1_dict = {'T1':self.T1, 'T1_stderr':T1_stderr} + # return as dict for use with "save_computed_parameters"; units are + # seconds + self.T1_dict = {'T1': self.T1, 'T1_stderr': T1_stderr} return self.T1, T1_stderr class Ramsey_Analysis(TD_Analysis): - """ Now has support for one and two artificial_detuning values. If the keyword parameter "artificial_detuning" is passed as an int or a list with @@ -4137,23 +4144,23 @@ class Ramsey_Analysis(TD_Analysis): Most kw parameters for Rabi_Analysis are also used here. """ - def __init__(self, label='Ramsey', **kw): + def __init__(self, label='Ramsey', phase_sweep_only=False, **kw): kw['label'] = label kw['h5mode'] = 'r+' - - self.artificial_detuning = kw.pop('artificial_detuning',0) + self.phase_sweep_only = phase_sweep_only + self.artificial_detuning = kw.pop('artificial_detuning', 0) if self.artificial_detuning == 0: logging.warning('Artificial detuning is unknown. Defaults to %s MHz. ' 'New qubit frequency might be incorrect.' - %self.artificial_detuning) + % self.artificial_detuning) # The routines for 2 art_dets does not use the self.fig and self.ax # created in TD_Analysis for make_fig==False for TD_Analysis but # still want make_fig to decide whether two_art_dets_analysis should # make a figure self.make_fig_two_dets = kw.get('make_fig', True) - if (type(self.artificial_detuning) is list ) and \ - (len(self.artificial_detuning)>1): + if (type(self.artificial_detuning) is list) and \ + (len(self.artificial_detuning) > 1): kw['make_fig'] = False super(Ramsey_Analysis, self).__init__(**kw) @@ -4161,56 +4168,69 @@ def __init__(self, label='Ramsey', **kw): def fit_Ramsey(self, x, y, **kw): print_fit_results = kw.pop('print_fit_results',False) - damped_osc_mod = fit_mods.ExpDampOscModel + damped_osc_mod = lmfit.Model(fit_mods.ExpDampOscFunc) average = np.mean(y) ft_of_data = np.fft.fft(y) index_of_fourier_maximum = np.argmax(np.abs( - ft_of_data[1:len(ft_of_data)//2]))+1 + ft_of_data[1:len(ft_of_data) // 2])) + 1 max_ramsey_delay = x[-1] - x[0] - fft_axis_scaling = 1/(max_ramsey_delay) - freq_est = fft_axis_scaling*index_of_fourier_maximum + fft_axis_scaling = 1 / (max_ramsey_delay) + freq_est = fft_axis_scaling * index_of_fourier_maximum est_number_of_periods = index_of_fourier_maximum - - if ((average > 0.7*max(y)) or - (est_number_of_periods < 2) or - est_number_of_periods > len(ft_of_data)/2.): - print('the trace is too short to find multiple periods') - - if print_fit_results: - print('Setting frequency to 0 and ' + - 'fitting with decaying exponential.') + if self.phase_sweep_only: damped_osc_mod.set_param_hint('frequency', - value=freq_est, + value=1/360, vary=False) damped_osc_mod.set_param_hint('phase', - value=0, + value=0, vary=True) + damped_osc_mod.set_param_hint('amplitude', + value=0.5*(max(self.normalized_data_points)-min(self.normalized_data_points)), + min=0.0, max=4.0) + fixed_tau=1e9 + damped_osc_mod.set_param_hint('tau', + value=fixed_tau, vary=False) else: - damped_osc_mod.set_param_hint('frequency', - value=freq_est, - vary=True, - min=(1/(100 *x[-1])), - max=(20/x[-1])) - - if (np.average(y[:4]) > - np.average(y[4:8])): - phase_estimate = 0 - else: - phase_estimate = np.pi - damped_osc_mod.set_param_hint('phase', - value=phase_estimate, vary=True) - - amplitude_guess = 1 - damped_osc_mod.set_param_hint('amplitude', - value=amplitude_guess, - min=0.4, - max=4.0) - damped_osc_mod.set_param_hint('tau', - value=x[1]*10, - min=x[1], - max=x[1]*1000) + if ((average > 0.7*max(y)) or + (est_number_of_periods < 2) or + est_number_of_periods > len(ft_of_data)/2.): + print('the trace is too short to find multiple periods') + + if print_fit_results: + print('Setting frequency to 0 and ' + + 'fitting with decaying exponential.') + damped_osc_mod.set_param_hint('frequency', + value=freq_est, + vary=False) + damped_osc_mod.set_param_hint('phase', + value=0, + vary=False) + else: + damped_osc_mod.set_param_hint('frequency', + value=freq_est, + vary=True, + min=(1/(100 *x[-1])), + max=(20/x[-1])) + + if (np.average(y[:4]) > + np.average(y[4:8])): + phase_estimate = 0 + else: + phase_estimate = np.pi + damped_osc_mod.set_param_hint('phase', + value=phase_estimate, vary=True) + + amplitude_guess = 1 + damped_osc_mod.set_param_hint('amplitude', + value=amplitude_guess, + min=0.4, + max=4.0) + damped_osc_mod.set_param_hint('tau', + value=x[1]*10, + min=x[1], + max=x[1]*1000) damped_osc_mod.set_param_hint('exponential_offset', value=0.5, min=0.4, @@ -4226,18 +4246,23 @@ def fit_Ramsey(self, x, y, **kw): fit_res = damped_osc_mod.fit(data=y, t=x, params=self.params) - if fit_res.chisqr > .35: + if self.phase_sweep_only: + chi_sqr_bound = 0 + else: + chi_sqr_bound = 0.35 + + if fit_res.chisqr > chi_sqr_bound: logging.warning('Fit did not converge, varying phase') fit_res_lst = [] - for phase_estimate in np.linspace(0, 2*np.pi, 8): + for phase_estimate in np.linspace(0, 2 * np.pi, 8): damped_osc_mod.set_param_hint('phase', value=phase_estimate) self.params = damped_osc_mod.make_params() fit_res_lst += [damped_osc_mod.fit( - data=y, - t=x, - params=self.params)] + data=y, + t=x, + params=self.params)] chisqr_lst = [fit_res.chisqr for fit_res in fit_res_lst] fit_res = fit_res_lst[np.argmin(chisqr_lst)] @@ -4251,31 +4276,31 @@ def fit_Ramsey(self, x, y, **kw): def plot_results(self, fit_res, show_guess=False, art_det=0, fig=None, ax=None, textbox=True): - self.units = SI_prefix_and_scale_factor( val=max(abs(ax.get_xticks())), - unit=self.sweep_unit[0] )[1] #list + self.units = SI_prefix_and_scale_factor(val=max(abs(ax.get_xticks())), + unit=self.sweep_unit[0])[1] # list if isinstance(art_det, list): art_det = art_det[0] if textbox: textstr = ('$f_{qubit \_ old}$ = %.7g GHz' - % (self.qubit_freq_spec*1e-9) + - '\n$f_{qubit \_ new}$ = %.7g $\pm$ (%.5g) GHz' - % (self.qubit_frequency*1e-9, - fit_res.params['frequency'].stderr*1e-9) + + % (self.qubit_freq_spec * 1e-9) + + '\n$f_{qubit \_ new}$ = %.7g $\pm$ (%.5g) GHz' + % (self.qubit_frequency * 1e-9, + fit_res.params['frequency'].stderr * 1e-9) + '\n$\Delta f$ = %.5g $ \pm$ (%.5g) MHz' - % ((self.qubit_frequency-self.qubit_freq_spec)*1e-6, - fit_res.params['frequency'].stderr*1e-6) + + % ((self.qubit_frequency - self.qubit_freq_spec) * 1e-6, + fit_res.params['frequency'].stderr * 1e-6) + '\n$f_{Ramsey}$ = %.5g $ \pm$ (%.5g) MHz' - % (fit_res.params['frequency'].value*1e-6, - fit_res.params['frequency'].stderr*1e-6) + + % (fit_res.params['frequency'].value * 1e-6, + fit_res.params['frequency'].stderr * 1e-6) + '\n$T_2^\star$ = %.6g ' - % (fit_res.params['tau'].value*self.scale) + + % (fit_res.params['tau'].value * self.scale) + self.units + ' $\pm$ (%.6g) ' - % (fit_res.params['tau'].stderr*self.scale) + + % (fit_res.params['tau'].stderr * self.scale) + self.units + '\nartificial detuning = %.2g MHz' - % (art_det*1e-6)) + % (art_det * 1e-6)) fig.text(0.5, 0, textstr, fontsize=self.font_size, transform=ax.transAxes, @@ -4283,8 +4308,8 @@ def plot_results(self, fit_res, show_guess=False, art_det=0, horizontalalignment='center', bbox=self.box_props) x = np.linspace(self.sweep_points[0], - self.sweep_points[-self.NoCalPoints-1], - len(self.sweep_points)*100) + self.sweep_points[-self.NoCalPoints - 1], + len(self.sweep_points) * 100) if show_guess: y_init = fit_mods.ExpDampOscFunc(x, **fit_res.init_values) @@ -4299,15 +4324,14 @@ def plot_results(self, fit_res, show_guess=False, art_det=0, amplitude=best_vals['amplitude'], oscillation_offset=best_vals['oscillation_offset'], exponential_offset=best_vals['exponential_offset']) - ax.plot(x, y, 'r-',linewidth=self.line_width) - + ax.plot(x, y, 'r-', linewidth=self.line_width) def run_default_analysis(self, print_fit_results=False, close_file=False, **kw): super().run_default_analysis( close_file=close_file, - close_main_figure=True,save_fig=False,**kw) + close_main_figure=True, save_fig=False, **kw) verbose = kw.get('verbose', False) # Get old values for qubit frequency @@ -4337,7 +4361,7 @@ def run_default_analysis(self, print_fit_results=False, # artificial detuning with one value can be passed as either an int or # a list with one elements if (type(self.artificial_detuning) is list) and \ - (len(self.artificial_detuning)>1): + (len(self.artificial_detuning) > 1): if verbose: print('Performing Ramsey Analysis for 2 artificial detunings.') self.two_art_dets_analysis(**kw) @@ -4351,18 +4375,18 @@ def run_default_analysis(self, print_fit_results=False, self.save_computed_parameters(self.T2_star, var_name=self.value_names[0]) - #Print the T2_star values on screen + # Print the T2_star values on screen unit = self.parameter_units[0][-1] if kw.pop('print_parameters', False): print('New qubit frequency = {:.7f} (GHz)'.format( - self.qubit_frequency*1e-9) + + self.qubit_frequency * 1e-9) + '\t\tqubit frequency stderr = {:.7f} (MHz)'.format( - self.ramsey_freq['freq_stderr']*1e-6)+ - '\nT2* = {:.5f} '.format( - self.T2_star['T2_star']*self.scale) +'('+'μ'+unit+')'+ - '\t\tT2* stderr = {:.5f} '.format( - self.T2_star['T2_star_stderr']*self.scale) + - '('+'μ'+unit+')') + self.ramsey_freq['freq_stderr'] * 1e-6) + + '\nT2* = {:.5f} '.format( + self.T2_star['T2_star'] * self.scale) + '(' + 'μ' + unit + ')' + + '\t\tT2* stderr = {:.5f} '.format( + self.T2_star['T2_star_stderr'] * self.scale) + + '(' + 'μ' + unit + ')') if close_file: self.data_file.close() @@ -4371,7 +4395,7 @@ def run_default_analysis(self, print_fit_results=False, def one_art_det_analysis(self, **kw): - #Perform fit and save fitted parameters + # Perform fit and save fitted parameters self.fit_res = self.fit_Ramsey(x=self.sweep_points[:-self.NoCalPoints], y=self.normalized_data_points, **kw) self.save_fitted_parameters(self.fit_res, var_name=self.value_names[0]) @@ -4381,7 +4405,7 @@ def one_art_det_analysis(self, **kw): self.qubit_frequency = self.qubit_freq_spec + self.artificial_detuning \ - self.ramsey_freq['freq'] - #Extract T2 star and save it + # Extract T2 star and save it self.get_measured_T2_star(fit_res=self.fit_res, **kw) # the call above defines self.T2_star as a dict; units are seconds @@ -4390,19 +4414,19 @@ def one_art_det_analysis(self, **kw): self.detuning = self.total_detuning - self.artificial_detuning if self.make_fig: - #Plot results + # Plot results show_guess = kw.pop('show_guess', False) show = kw.pop('show', False) self.plot_results(self.fit_res, show_guess=show_guess, art_det=self.artificial_detuning, fig=self.fig, ax=self.ax) - #dispaly figure + # dispaly figure if show: plt.show() - #save figure - self.save_fig(self.fig, figname=self.measurementstring+'_Ramsey_fit', + # save figure + self.save_fig(self.fig, figname=self.measurementstring + '_Ramsey_fit', **kw) def two_art_dets_analysis(self, **kw): @@ -4414,16 +4438,16 @@ def two_art_dets_analysis(self, **kw): ramsey_data_1 = self.normalized_values[0:-self.NoCalPoints:len_art_det] ramsey_data_2 = self.normalized_values[1:-self.NoCalPoints:len_art_det] - #Perform fit + # Perform fit fit_res_1 = self.fit_Ramsey(x=sweep_pts_1, y=ramsey_data_1, **kw) fit_res_2 = self.fit_Ramsey(x=sweep_pts_2, y=ramsey_data_2, **kw) - self.save_fitted_parameters(fit_res_1, var_name=(self.value_names[0]+ - ' ' + str(self.artificial_detuning[0]*1e-6) + ' MHz')) - self.save_fitted_parameters(fit_res_2, var_name=(self.value_names[0]+ - ' ' + str(self.artificial_detuning[1]*1e-6) + ' MHz')) + self.save_fitted_parameters(fit_res_1, var_name=(self.value_names[0] + + ' ' + str(self.artificial_detuning[0] * 1e-6) + ' MHz')) + self.save_fitted_parameters(fit_res_2, var_name=(self.value_names[0] + + ' ' + str(self.artificial_detuning[1] * 1e-6) + ' MHz')) ramsey_freq_dict_1 = self.get_measured_freq(fit_res=fit_res_1, **kw) ramsey_freq_1 = ramsey_freq_dict_1['freq'] @@ -4432,20 +4456,20 @@ def two_art_dets_analysis(self, **kw): # Calculate possible detunings from real qubit frequency self.new_qb_freqs = { - '0':self.qubit_freq_spec + self.artificial_detuning[0] + ramsey_freq_1, - '1':self.qubit_freq_spec + self.artificial_detuning[0] - ramsey_freq_1, - '2':self.qubit_freq_spec + self.artificial_detuning[1] + ramsey_freq_2, - '3':self.qubit_freq_spec + self.artificial_detuning[1] - ramsey_freq_2} + '0': self.qubit_freq_spec + self.artificial_detuning[0] + ramsey_freq_1, + '1': self.qubit_freq_spec + self.artificial_detuning[0] - ramsey_freq_1, + '2': self.qubit_freq_spec + self.artificial_detuning[1] + ramsey_freq_2, + '3': self.qubit_freq_spec + self.artificial_detuning[1] - ramsey_freq_2} print('The 4 possible cases for the new qubit frequency give:') pprint(self.new_qb_freqs) # Find which ones match self.diff = {} - self.diff.update({'0':self.new_qb_freqs['0']-self.new_qb_freqs['2']}) - self.diff.update({'1':self.new_qb_freqs['1']-self.new_qb_freqs['3']}) - self.diff.update({'2':self.new_qb_freqs['1']-self.new_qb_freqs['2']}) - self.diff.update({'3':self.new_qb_freqs['0']-self.new_qb_freqs['3']}) + self.diff.update({'0': self.new_qb_freqs['0'] - self.new_qb_freqs['2']}) + self.diff.update({'1': self.new_qb_freqs['1'] - self.new_qb_freqs['3']}) + self.diff.update({'2': self.new_qb_freqs['1'] - self.new_qb_freqs['2']}) + self.diff.update({'3': self.new_qb_freqs['0'] - self.new_qb_freqs['3']}) self.correct_key = np.argmin(np.abs(list(self.diff.values()))) # Get new qubit frequency self.qubit_frequency = self.new_qb_freqs[str(self.correct_key)] @@ -4470,8 +4494,8 @@ def two_art_dets_analysis(self, **kw): self.good_ramsey_freq = ramsey_freq_2 qb_stderr = ramsey_freq_dict_2['freq_stderr'] - #Extract T2 star and save it - self.get_measured_T2_star(fit_res=self.fit_res, **kw) #defines self.T2_star as a dict; + # Extract T2 star and save it + self.get_measured_T2_star(fit_res=self.fit_res, **kw) # defines self.T2_star as a dict; # units are seconds ################ @@ -4485,17 +4509,17 @@ def two_art_dets_analysis(self, **kw): ylabel = r'$F$ $\left(|f \rangle \right) (arb. units)$' else: ylabel = r'$F$ $\left(|e \rangle \right) (arb. units)$' - if self.no_of_columns==2: - figsize=(3.375, 2.25*len_art_det) + if self.no_of_columns == 2: + figsize = (3.375, 2.25 * len_art_det) else: - figsize=(7, 4*len_art_det) + figsize = (7, 4 * len_art_det) self.fig, self.axs = plt.subplots(len_art_det, 1, figsize=figsize, dpi=self.dpi) fit_res_array = [fit_res_1, fit_res_2] - ramsey_data_dict = {'0':ramsey_data_1, - '1':ramsey_data_2} + ramsey_data_dict = {'0': ramsey_data_1, + '1': ramsey_data_2} for i in range(len_art_det): ax = self.axs[i] @@ -4512,29 +4536,29 @@ def two_art_dets_analysis(self, **kw): fig=self.fig, ax=ax, textbox=False) textstr = ('artificial detuning = %.2g MHz' - % (self.artificial_detuning[i]*1e-6) + + % (self.artificial_detuning[i] * 1e-6) + '\n$f_{Ramsey}$ = %.5g $ MHz \pm$ (%.5g) MHz' - % (fit_res_array[i].params['frequency'].value*1e-6, - fit_res_array[i].params['frequency'].stderr*1e6) + + % (fit_res_array[i].params['frequency'].value * 1e-6, + fit_res_array[i].params['frequency'].stderr * 1e6) + '\n$T_2^\star$ = %.3g ' - % (fit_res_array[i].params['tau'].value*self.scale) + + % (fit_res_array[i].params['tau'].value * self.scale) + self.units + ' $\pm$ (%.3g) ' - % (fit_res_array[i].params['tau'].stderr*self.scale) + + % (fit_res_array[i].params['tau'].stderr * self.scale) + self.units) ax.annotate(textstr, xy=(0.99, 0.98), xycoords='axes fraction', fontsize=self.font_size, bbox=self.box_props, horizontalalignment='right', verticalalignment='top') - if i==(len_art_det-1): + if i == (len_art_det - 1): textstr_main = ('$f_{qubit \_ old}$ = %.5g GHz' - % (self.qubit_freq_spec*1e-9) + + % (self.qubit_freq_spec * 1e-9) + '\n$f_{qubit \_ new}$ = %.5g $ GHz \pm$ (%.5g) GHz' - % (self.qubit_frequency*1e-9, - qb_stderr*1e-9) + + % (self.qubit_frequency * 1e-9, + qb_stderr * 1e-9) + '\n$T_2^\star$ = %.3g ' - % (self.T2_star['T2_star']*self.scale) + + % (self.T2_star['T2_star'] * self.scale) + self.units + ' $\pm$ (%.3g) ' - % (self.T2_star['T2_star_stderr']*self.scale) + + % (self.T2_star['T2_star_stderr'] * self.scale) + self.units) self.fig.text(0.5, 0, textstr_main, fontsize=self.font_size, @@ -4542,20 +4566,19 @@ def two_art_dets_analysis(self, **kw): verticalalignment='top', horizontalalignment='center', bbox=self.box_props) - #dispaly figure + # dispaly figure if show: plt.show() - #save figure - self.save_fig(self.fig, figname=self.measurementstring+'_Ramsey_fit', + # save figure + self.save_fig(self.fig, figname=self.measurementstring + '_Ramsey_fit', **kw) - def get_measured_freq(self, fit_res, **kw): freq = fit_res.params['frequency'].value freq_stderr = fit_res.params['frequency'].stderr - self.ramsey_freq = {'freq':freq, 'freq_stderr':freq_stderr} + self.ramsey_freq = {'freq': freq, 'freq_stderr': freq_stderr} return self.ramsey_freq @@ -4567,7 +4590,7 @@ def get_measured_T2_star(self, fit_res, **kw): T2 = fit_res.params['tau'].value T2_stderr = fit_res.params['tau'].stderr - self.T2_star = {'T2_star':T2, 'T2_star_stderr':T2_stderr} + self.T2_star = {'T2_star': T2, 'T2_star_stderr': T2_stderr} return self.T2_star @@ -4587,16 +4610,16 @@ def run_default_analysis(self, print_fit_results=False, **kw): fig, axarray = plt.subplots(2, 2, figsize=figsize) XpY90_data = self.measured_values[0][0::2] + \ - 1.j*self.measured_values[1][0::2] + 1.j * self.measured_values[1][0::2] YpX90_data = self.measured_values[0][1::2] + \ - 1.j*self.measured_values[1][1::2] + 1.j * self.measured_values[1][1::2] self.XpY90 = np.mean(XpY90_data) self.YpX90 = np.mean(YpX90_data) self.detuning = np.abs(self.XpY90 - self.YpX90) for i, name in enumerate(self.value_names): - ax = axarray[i/2, i % 2] + ax = axarray[i / 2, i % 2] self.plot_results_vs_sweepparam(x=self.sweep_points, y=self.measured_values[i], fig=fig, @@ -4638,7 +4661,7 @@ def run_default_analysis(self, print_fit_results=False, **kw): samples = len(transients_0[:, 0]) sampling_rate = 1 # Gsample/s - self.time = np.linspace(0, samples/sampling_rate, samples) + self.time = np.linspace(0, samples / sampling_rate, samples) if mode == 'CBox': self.plot_results_vs_sweepparam(x=self.time, y=transient_0, @@ -4661,13 +4684,13 @@ def run_default_analysis(self, print_fit_results=False, **kw): if demodulate: print('demodulating using IF = %.2f GHz' % self.IF) - dem_cos = np.cos(2*np.pi*self.IF*self.time) - dem_sin = np.sin(2*np.pi*self.IF*self.time) + dem_cos = np.cos(2 * np.pi * self.IF * self.time) + dem_sin = np.sin(2 * np.pi * self.IF * self.time) - self.demod_transient_I = dem_cos*transients_0[:, 0] + \ - dem_sin * transients_1[:, 0] - self.demod_transient_Q = -dem_sin*transients_0[:, 0] + \ - dem_cos * transients_1[:, 0] + self.demod_transient_I = dem_cos * transients_0[:, 0] + \ + dem_sin * transients_1[:, 0] + self.demod_transient_Q = -dem_sin * transients_0[:, 0] + \ + dem_cos * transients_1[:, 0] fig2, axs2 = plt.subplots(1, 1, figsize=figsize, sharex=True) axs2.plot(self.time, self.demod_transient_I, marker='.', @@ -4675,15 +4698,15 @@ def run_default_analysis(self, print_fit_results=False, **kw): axs2.plot(self.time, self.demod_transient_Q, marker='.', label='Q demodulated') axs2.legend() - self.save_fig(fig2, figname=self.measurementstring+'demod', **kw) + self.save_fig(fig2, figname=self.measurementstring + 'demod', **kw) axs2.set_xlabel('time (ns)') axs2.set_ylabel('dac voltage (V)') - self.power = self.demod_transient_I**2 + self.demod_transient_Q**2 + self.power = self.demod_transient_I ** 2 + self.demod_transient_Q ** 2 fig3, ax3 = plt.subplots(1, 1, figsize=figsize, sharex=True) ax3.plot(self.time, self.power, marker='.') ax3.set_ylabel('Power (a.u.)') - self.save_fig(fig3, figname=self.measurementstring+'Power', **kw) + self.save_fig(fig3, figname=self.measurementstring + 'Power', **kw) ax3.set_xlabel('time (ns)') self.save_fig(fig, figname=self.measurementstring, **kw) @@ -4719,10 +4742,10 @@ def sine_fit_data(): def quadratic_fit_data(): M = np.array( - [sweep_points**2, sweep_points, [1]*len(sweep_points)]) + [sweep_points ** 2, sweep_points, [1] * len(sweep_points)]) Minv = np.linalg.pinv(M) [a, b, c] = np.dot(data, Minv) - fit_data = (a*sweep_points**2 + b*sweep_points + c) + fit_data = (a * sweep_points ** 2 + b * sweep_points + c) return fit_data, (a, b, c) close_file = kw.pop('close_file', True) @@ -4751,10 +4774,10 @@ def quadratic_fit_data(): self.fit_results_quadratic = quadratic_fit_data() chisqr_sine = self.fit_results_sine.chisqr - chisqr_quadratic = np.sum((self.fit_results_quadratic[0] - data)**2) + chisqr_quadratic = np.sum((self.fit_results_quadratic[0] - data) ** 2) if (chisqr_quadratic < chisqr_sine) or \ - (data_peak_to_peak/cal_peak_to_peak < .5): + (data_peak_to_peak / cal_peak_to_peak < .5): self.fit_type = 'quadratic' self.slope = self.fit_results_quadratic[1][1] amplitude = cal_peak_to_peak / 2 @@ -4765,7 +4788,7 @@ def quadratic_fit_data(): frequency = self.fit_results_sine.params['frequency'] self.slope = 2 * np.pi * amplitude * frequency - self.drive_detuning = -1*self.slope / (2 * np.pi * abs(amplitude)) + self.drive_detuning = -1 * self.slope / (2 * np.pi * abs(amplitude)) self.drive_scaling_factor = 1. / (1. + self.drive_detuning) # Plotting @@ -4811,7 +4834,7 @@ def run_default_analysis(self, print_fit_results=False, **kw): close_file = kw.pop('close_file', True) self.add_analysis_datagroup_to_file() self.get_naming_and_values() - figsize = kw.pop('figsize', (11, 2*len(self.value_names))) + figsize = kw.pop('figsize', (11, 2 * len(self.value_names))) if self.idx is not None: idx_val = np.where(self.value_names == 'I_cal_%d' % self.idx)[0][0] else: @@ -4820,7 +4843,7 @@ def run_default_analysis(self, print_fit_results=False, **kw): except: # Kind of arbitrarily choose axis 0 idx_val = 0 - fig, axarray = plt.subplots(len(self.value_names)/2, 2, + fig, axarray = plt.subplots(len(self.value_names) / 2, 2, figsize=figsize) I_cal = self.measured_values[idx_val] @@ -4832,13 +4855,13 @@ def run_default_analysis(self, print_fit_results=False, **kw): self.distance = np.power(zero_mean - one_mean, 2) distance_error = np.sqrt( - np.power(2.*(zero_mean - one_mean)*zero_std, 2) - + np.power(2.*(one_mean - zero_mean)*one_std, 2)) - self.contrast = self.distance/distance_error + np.power(2. * (zero_mean - one_mean) * zero_std, 2) + + np.power(2. * (one_mean - zero_mean) * one_std, 2)) + self.contrast = self.distance / distance_error for i, name in enumerate(self.value_names): if len(self.value_names) == 4: - ax = axarray[i/2, i % 2] + ax = axarray[i / 2, i % 2] elif len(self.value_names) == 2: ax = axarray[i] @@ -4886,15 +4909,15 @@ def run_default_analysis(self, print_fit_results=False, **kw): linestyle='solid', color='green') ax2.text(2, zero_mean, "Zero mean", bbox=self.box_props, color='blue') ax2.text(2, one_mean, "One mean", bbox=self.box_props, color='green') - ax2.hlines((zero_mean+zero_std, zero_mean-zero_std), + ax2.hlines((zero_mean + zero_std, zero_mean - zero_std), 0, len(self.sweep_points), linestyle='dashed', color='blue') - ax2.hlines((one_mean+one_std, one_mean-one_std), + ax2.hlines((one_mean + one_std, one_mean - one_std), 0, len(self.sweep_points), linestyle='dashed', color='green') - ax2.text(2, max(I_cal)+(max(I_cal)-min(I_cal))*.04, + ax2.text(2, max(I_cal) + (max(I_cal) - min(I_cal)) * .04, "Contrast: %.2f" % self.contrast, bbox=self.box_props) self.save_fig(fig, figname=self.measurementstring, **kw) - self.save_fig(fig2, figname=self.measurementstring+'_calibrated', **kw) + self.save_fig(fig2, figname=self.measurementstring + '_calibrated', **kw) if close_file: self.data_file.close() print('Average contrast: %.2f' % self.contrast) @@ -4902,7 +4925,6 @@ def run_default_analysis(self, print_fit_results=False, **kw): class AllXY_Analysis(TD_Analysis): - ''' Performs a rotation and normalization on the data and calculates a deviation from the expected ideal data. @@ -4931,10 +4953,10 @@ def run_default_analysis(self, print_fit_results=False, self.get_naming_and_values() if len(self.measured_values[0]) == 42: - ideal_data = np.concatenate((0*np.ones(10), 0.5*np.ones(24), + ideal_data = np.concatenate((0 * np.ones(10), 0.5 * np.ones(24), np.ones(8))) else: - ideal_data = np.concatenate((0*np.ones(5), 0.5*np.ones(12), + ideal_data = np.concatenate((0 * np.ones(5), 0.5 * np.ones(12), np.ones(4))) self.rotate_and_normalize_data() self.add_dataset_to_analysisgroup('Corrected data', @@ -4965,7 +4987,7 @@ def make_figures(self, ideal_data, close_main_fig, **kw): ylabel=str( self.value_names[i]), save=False) - ax1.set_ylim(min(self.corr_data)-.1, max(self.corr_data)+.1) + ax1.set_ylim(min(self.corr_data) - .1, max(self.corr_data) + .1) if self.flip_axis: ylabel = r'$F$ $|0 \rangle$' else: @@ -5002,8 +5024,8 @@ def make_figures(self, ideal_data, close_main_fig, **kw): self.save_fig(fig1, ylabel='Amplitude (normalized)', **kw) self.save_fig(fig2, ylabel='Amplitude', **kw) -class FFC_Analysis(TD_Analysis): +class FFC_Analysis(TD_Analysis): ''' Performs a rotation and normalization on the data and calculates a deviation from the expected ideal data. @@ -5013,7 +5035,7 @@ class FFC_Analysis(TD_Analysis): 'ideal_data': np.array equal in lenght to the data ''' - def __init__(self, label='FFC', make_fig=True,zero_coord=None, one_coord=None, **kw): + def __init__(self, label='FFC', make_fig=True, zero_coord=None, one_coord=None, **kw): kw['label'] = label kw['h5mode'] = 'r+' # Read write mode, file must exist self.zero_coord = zero_coord @@ -5030,7 +5052,7 @@ def run_default_analysis(self, print_fit_results=False, self.add_analysis_datagroup_to_file() self.get_naming_and_values() - ideal_data = np.concatenate((0.5*np.ones(1), 1*np.ones(1))) + ideal_data = np.concatenate((0.5 * np.ones(1), 1 * np.ones(1))) self.rotate_and_normalize_data() self.add_dataset_to_analysisgroup('Corrected data', self.corr_data) @@ -5060,7 +5082,7 @@ def make_figures(self, ideal_data, close_main_fig, **kw): ylabel=str( self.value_names[i]), save=False) - ax1.set_ylim(min(self.corr_data)-.1, max(self.corr_data)+.1) + ax1.set_ylim(min(self.corr_data) - .1, max(self.corr_data) + .1) if self.flip_axis: ylabel = r'$F$ $|0 \rangle$' else: @@ -5091,8 +5113,8 @@ def make_figures(self, ideal_data, close_main_fig, **kw): self.save_fig(fig1, ylabel='Amplitude (normalized)', **kw) self.save_fig(fig2, ylabel='Amplitude', **kw) -class RandomizedBenchmarking_Analysis(TD_Analysis): +class RandomizedBenchmarking_Analysis(TD_Analysis): ''' Rotates and normalizes the data before doing a fit with a decaying exponential to extract the Clifford fidelity. @@ -5116,8 +5138,8 @@ def run_default_analysis(self, **kw): super().run_default_analysis(close_file=False, make_fig=False, **kw) - data = self.corr_data[:-1*(len(self.cal_points[0]*2))] - n_cl = self.sweep_points[:-1*(len(self.cal_points[0]*2))] + data = self.corr_data[:-1 * (len(self.cal_points[0] * 2))] + n_cl = self.sweep_points[:-1 * (len(self.cal_points[0] * 2))] self.fit_res = self.fit_data(data, n_cl) self.fit_results = [self.fit_res] @@ -5135,26 +5157,26 @@ def calc_T1_limited_fidelity(self, T1, pulse_delay): pulse separation is time between start of pulses ''' Np = 1.875 # Number of gates per Clifford - F_cl = (1/6*(3 + 2*np.exp(-1*pulse_delay/(2*T1)) + - np.exp(-pulse_delay/T1)))**Np - p = 2*F_cl - 1 + F_cl = (1 / 6 * (3 + 2 * np.exp(-1 * pulse_delay / (2 * T1)) + + np.exp(-pulse_delay / T1))) ** Np + p = 2 * F_cl - 1 return F_cl, p def add_textbox(self, ax, F_T1=None): - textstr = ('\t$F_{Cl}$'+' \t= {:.4g} $\pm$ ({:.4g})%'.format( - self.fit_res.params['fidelity_per_Clifford'].value*100, - self.fit_res.params['fidelity_per_Clifford'].stderr*100) + - '\n $1-F_{Cl}$'+' = {:.4g} $\pm$ ({:.4g})%'.format( - (1-self.fit_res.params['fidelity_per_Clifford'].value)*100, - (self.fit_res.params['fidelity_per_Clifford'].stderr)*100) + - '\n\tOffset\t= {:.4g} $\pm$ ({:.4g})'.format( - (self.fit_res.params['offset'].value), - (self.fit_res.params['offset'].stderr))) + textstr = ('\t$F_{Cl}$' + ' \t= {:.4g} $\pm$ ({:.4g})%'.format( + self.fit_res.params['fidelity_per_Clifford'].value * 100, + self.fit_res.params['fidelity_per_Clifford'].stderr * 100) + + '\n $1-F_{Cl}$' + ' = {:.4g} $\pm$ ({:.4g})%'.format( + (1 - self.fit_res.params['fidelity_per_Clifford'].value) * 100, + (self.fit_res.params['fidelity_per_Clifford'].stderr) * 100) + + '\n\tOffset\t= {:.4g} $\pm$ ({:.4g})'.format( + (self.fit_res.params['offset'].value), + (self.fit_res.params['offset'].stderr))) if F_T1 is not None: textstr += ('\n\t $F_{Cl}^{T_1}$ = ' + - '{:.6g}%'.format(F_T1*100)) + '{:.6g}%'.format(F_T1 * 100)) self.ax.text(0.1, 0.95, textstr, transform=self.ax.transAxes, fontsize=11, verticalalignment='top', @@ -5173,8 +5195,8 @@ def make_figures(self, close_main_fig, **kw): x = self.sweep_points[:-2] y = self.corr_data[:-2] else: - x = self.sweep_points[:-1*(len(self.cal_points[0])*2)] - y = self.corr_data[:-1*(len(self.cal_points[0])*2)] + x = self.sweep_points[:-1 * (len(self.cal_points[0]) * 2)] + y = self.corr_data[:-1 * (len(self.cal_points[0]) * 2)] self.plot_results_vs_sweepparam(x=x, y=y, @@ -5188,8 +5210,8 @@ def make_figures(self, close_main_fig, **kw): best_fit = fit_mods.RandomizedBenchmarkingDecay( x_fine, **fit_res.best_values) self.ax.plot(x_fine, best_fit, label='Fit') - self.ax.set_ylim(min(min(self.corr_data)-.1, -.1), - max(max(self.corr_data)+.1, 1.1)) + self.ax.set_ylim(min(min(self.corr_data) - .1, -.1), + max(max(self.corr_data) + .1, 1.1)) # Here we add the line corresponding to T1 limited fidelity F_T1 = None @@ -5257,14 +5279,14 @@ def run_default_analysis(self, **kw): super(RandomizedBenchmarking_Analysis, self).run_default_analysis( close_file=False, make_fig=False, **kw) - data = self.corr_data[:-1*(len(self.cal_points[0]*2))] + data = self.corr_data[:-1 * (len(self.cal_points[0] * 2))] # 1- minus all populations because we measure fidelity to 1 data_0 = 1 - data[::2] data_1 = 1 - data[1::2] # 2-state population is just whatever is missing in 0 and 1 state # assumes that 2 looks like 1 state data_2 = 1 - (data_1) - (data_0) - n_cl = self.sweep_points[:-1*(len(self.cal_points[0]*2)):2] + n_cl = self.sweep_points[:-1 * (len(self.cal_points[0] * 2)):2] self.fit_results = self.fit_data(data_0, data_1, n_cl) @@ -5283,7 +5305,7 @@ def fit_data(self, data0, data1, numCliff, show_guess=False, plot_results=False): data = np.concatenate([data0, data1]) - numCliff = 2*list(numCliff) + numCliff = 2 * list(numCliff) invert = np.concatenate([np.ones(len(data0)), np.zeros(len(data1))]) @@ -5310,14 +5332,14 @@ def fit_data(self, data0, data1, numCliff, def add_textbox(self, f, ax, F_T1=None): fr0 = self.fit_results.params textstr = ( - '$F_{\mathrm{Cl}}$'+'= {:.5g} \n\t$\pm$ ({:.2g})%'.format( - fr0['fidelity_per_Clifford'].value*100, - fr0['fidelity_per_Clifford'].stderr*100) + - '\nOffset '+'= {:.4g} \n\t$\pm$ ({:.2g})%'.format( - fr0['offset'].value*100, fr0['offset'].stderr*100)) + '$F_{\mathrm{Cl}}$' + '= {:.5g} \n\t$\pm$ ({:.2g})%'.format( + fr0['fidelity_per_Clifford'].value * 100, + fr0['fidelity_per_Clifford'].stderr * 100) + + '\nOffset ' + '= {:.4g} \n\t$\pm$ ({:.2g})%'.format( + fr0['offset'].value * 100, fr0['offset'].stderr * 100)) if F_T1 is not None: textstr += ('\n\t $F_{Cl}^{T_1}$ = ' + - '{:.5g}%'.format(F_T1*100)) + '{:.5g}%'.format(F_T1 * 100)) ax.text(0.95, 0.1, textstr, transform=f.transFigure, fontsize=11, verticalalignment='bottom', horizontalalignment='right') @@ -5328,23 +5350,23 @@ def make_figures(self, n_cl, data_0, data_1, data_2, ax.plot(n_cl, data_0, 'o', color='b', label=r'$|0\rangle$') ax.plot(n_cl, data_1, '^', color='r', label=r'$|1\rangle$') ax.plot(n_cl, data_2, 'p', color='g', label=r'$|2\rangle$') - ax.hlines(0, n_cl[0], n_cl[-1]*1.05, linestyle='--') - ax.hlines(1, n_cl[0], n_cl[-1]*1.05, linestyle='--') - ax.plot([n_cl[-1]]*4, self.corr_data[-4:], 'o', color='None') + ax.hlines(0, n_cl[0], n_cl[-1] * 1.05, linestyle='--') + ax.hlines(1, n_cl[0], n_cl[-1] * 1.05, linestyle='--') + ax.plot([n_cl[-1]] * 4, self.corr_data[-4:], 'o', color='None') ax.set_xlabel('Number of Cliffords') ax.set_ylabel('State populations') plot_title = kw.pop('plot_title', textwrap.fill( - self.timestamp_string + '_' + - self.measurementstring, 40)) + self.timestamp_string + '_' + + self.measurementstring, 40)) ax.set_title(plot_title) - ax.set_xlim(n_cl[0], n_cl[-1]*1.02) + ax.set_xlim(n_cl[0], n_cl[-1] * 1.02) ax.set_ylim(-.1, 1.1) - x_fine = np.linspace(0, self.sweep_points[-1]*1.05, 1000) + x_fine = np.linspace(0, self.sweep_points[-1] * 1.05, 1000) fit_0 = fit_mods.double_RandomizedBenchmarkingDecay( - x_fine, invert=1, ** self.fit_results.best_values) + x_fine, invert=1, **self.fit_results.best_values) fit_1 = fit_mods.double_RandomizedBenchmarkingDecay( - x_fine, invert=0, ** self.fit_results.best_values) - fit_2 = 1-fit_1-fit_0 + x_fine, invert=0, **self.fit_results.best_values) + fit_2 = 1 - fit_1 - fit_0 ax.plot(x_fine, fit_0, color='darkgray', label='fit') ax.plot(x_fine, fit_1, color='darkgray') @@ -5375,7 +5397,6 @@ def make_figures(self, n_cl, data_0, data_1, data_2, class RandomizedBench_2D_flat_Analysis(RandomizedBenchmarking_Analysis): - ''' Analysis for the specific RB sequenes used in the CBox that require doing a 2D scan in order to get enough seeds in (due to the limit of the @@ -5399,13 +5420,13 @@ def get_naming_and_values(self): class Homodyne_Analysis(MeasurementAnalysis): - def __init__(self, label='HM', custom_power_message: dict=None, **kw): + def __init__(self, label='HM', custom_power_message: dict = None, **kw): # Custome power message is used to create a message in resonator measurements # dict must be custom_power_message={'Power': -15, 'Atten': 86, 'res_len':3e-6} # Power in dBm, Atten in dB and resonator length in m kw['label'] = label kw['h5mode'] = 'r+' - kw['custom_power_message']=custom_power_message + kw['custom_power_message'] = custom_power_message super().__init__(**kw) def run_default_analysis(self, print_fit_results=False, @@ -5430,7 +5451,7 @@ def run_default_analysis(self, print_fit_results=False, ########## Fit data ########## # Fit Power to a Lorentzian - self.measured_powers = self.measured_values[0]**2 + self.measured_powers = self.measured_values[0] ** 2 min_index = np.argmin(self.measured_powers) max_index = np.argmax(self.measured_powers) @@ -5445,13 +5466,13 @@ def run_default_analysis(self, print_fit_results=False, window_len=0) # Search for peak - if self.peaks['dip'] is not None: # look for dips first + if self.peaks['dip'] is not None: # look for dips first f0 = self.peaks['dip'] amplitude_factor = -1. elif self.peaks['peak'] is not None: # then look for peaks f0 = self.peaks['peak'] amplitude_factor = 1. - else: # Otherwise take center of range + else: # Otherwise take center of range f0 = np.median(self.sweep_points) amplitude_factor = -1. logging.warning('No peaks or dips in range') @@ -5484,9 +5505,9 @@ def run_default_analysis(self, print_fit_results=False, Qe = abs(Q / abs(1 - S21min)) # Note: input to the fit function is in GHz for convenience - Model.set_param_hint('f0', value=f0*1e-9, - min=min(self.sweep_points)*1e-9, - max=max(self.sweep_points)*1e-9) + Model.set_param_hint('f0', value=f0 * 1e-9, + min=min(self.sweep_points) * 1e-9, + max=max(self.sweep_points) * 1e-9) Model.set_param_hint('A', value=amplitude_guess) Model.set_param_hint('Q', value=Q, min=1, max=50e6) Model.set_param_hint('Qe', value=Qe, min=1, max=50e6) @@ -5496,8 +5517,8 @@ def run_default_analysis(self, print_fit_results=False, Model.set_param_hint('Qi', expr='abs(1./(1./Q-1./Qe*cos(theta)))', vary=False) Model.set_param_hint('Qc', expr='Qe/cos(theta)', vary=False) - Model.set_param_hint('theta', value=0, min=-np.pi/2, - max=np.pi/2) + Model.set_param_hint('theta', value=0, min=-np.pi / 2, + max=np.pi / 2) Model.set_param_hint('slope', value=0, vary=True) self.params = Model.make_params() @@ -5522,22 +5543,22 @@ def run_default_analysis(self, print_fit_results=False, # this is the fit with a complex transmission curve WITHOUT slope data_amp = self.measured_values[0] data_angle = self.measured_values[1] - data_complex = data_amp*np.cos(data_angle)+1j*data_amp*np.sin(data_angle) - #np.add(self.measured_values[2], 1j*self.measured_values[3]) + data_complex = data_amp * np.cos(data_angle) + 1j * data_amp * np.sin(data_angle) + # np.add(self.measured_values[2], 1j*self.measured_values[3]) # Initial guesses guess_A = max(data_amp) # this has to been improved guess_Q = f0 / abs(self.min_frequency - self.max_frequency) - guess_Qe = guess_Q/(1-(max(data_amp)-min(data_amp))) + guess_Qe = guess_Q / (1 - (max(data_amp) - min(data_amp))) # phi_v # number of 2*pi phase jumps nbr_phase_jumps = (np.diff(data_angle) > 4).sum() - guess_phi_v = (2*np.pi*nbr_phase_jumps+(data_angle[0]-data_angle[-1]))/( - self.sweep_points[0] - self.sweep_points[-1]) + guess_phi_v = (2 * np.pi * nbr_phase_jumps + (data_angle[0] - data_angle[-1])) / ( + self.sweep_points[0] - self.sweep_points[-1]) # phi_0 - angle_resonance = data_angle[int(len(self.sweep_points)/2)] - phase_evolution_resonance = np.exp(1j*guess_phi_v*f0) + angle_resonance = data_angle[int(len(self.sweep_points) / 2)] + phase_evolution_resonance = np.exp(1j * guess_phi_v * f0) angle_phase_evolution = np.arctan2( np.imag(phase_evolution_resonance), np.real(phase_evolution_resonance)) guess_phi_0 = angle_resonance - angle_phase_evolution @@ -5545,13 +5566,13 @@ def run_default_analysis(self, print_fit_results=False, # prepare the parameter dictionary P = lmfit.Parameters() # (Name, Value, Vary, Min, Max, Expr) - P.add_many(('f0', f0/1e9, True, None, None, None), - ('Q', guess_Q, True, 1, 50e6, None), - ('Qe', guess_Qe, True, 1, 50e6, None), - ('A', guess_A, True, 0, None, None), - ('theta', 0, True, -np.pi/2, np.pi/2, None), - ('phi_v', guess_phi_v, True, None, None, None), - ('phi_0', guess_phi_0, True, -np.pi, np.pi, None)) + P.add_many(('f0', f0 / 1e9, True, None, None, None), + ('Q', guess_Q, True, 1, 50e6, None), + ('Qe', guess_Qe, True, 1, 50e6, None), + ('A', guess_A, True, 0, None, None), + ('theta', 0, True, -np.pi / 2, np.pi / 2, None), + ('phi_v', guess_phi_v, True, None, None, None), + ('phi_0', guess_phi_0, True, -np.pi, np.pi, None)) P.add('Qi', expr='1./(1./Q-1./Qe*cos(theta))', vary=False) P.add('Qc', expr='Qe/cos(theta)', vary=False) @@ -5564,8 +5585,8 @@ def run_default_analysis(self, print_fit_results=False, kappa_guess = 2.5e6 - amplitude_guess = amplitude_factor * np.pi*kappa_guess * abs( - max(self.measured_powers)-min(self.measured_powers)) + amplitude_guess = amplitude_factor * np.pi * kappa_guess * abs( + max(self.measured_powers) - min(self.measured_powers)) Model.set_param_hint('f0', value=f0, min=min(self.sweep_points), @@ -5591,7 +5612,7 @@ def run_default_analysis(self, print_fit_results=False, else: raise ValueError('fitting model "{}" not recognized'.format( - fitting_model)) + fitting_model)) self.fit_results = fit_res self.save_fitted_parameters(fit_res, var_name='HM') @@ -5623,7 +5644,7 @@ def run_default_analysis(self, print_fit_results=False, fig2, ax2 = self.default_ax() self.plot_results_vs_sweepparam(x=self.sweep_points, y=data_amp, fig=fig2, ax=ax2, - show=False, xlabel=self.sweep_name, + show=False, xlabel=self.sweep_name, x_unit=self.sweep_unit[0], ylabel=str('S21_mag'), y_unit=self.value_units[0]) @@ -5643,7 +5664,7 @@ def run_default_analysis(self, print_fit_results=False, instr_set = self.data_file['Instrument settings'] try: old_RO_freq = float(instr_set[self.qb_name].attrs['f_RO']) - old_vals = '\n$f_{\mathrm{old}}$ = %.5f GHz' % (old_RO_freq*scale) + old_vals = '\n$f_{\mathrm{old}}$ = %.5f GHz' % (old_RO_freq * scale) except (TypeError, KeyError, ValueError): logging.warning('qb_name is None. Old parameter values will ' 'not be retrieved.') @@ -5654,12 +5675,12 @@ def run_default_analysis(self, print_fit_results=False, textstr = '$f_{\mathrm{center}}$ = %.5f GHz $\pm$ (%.3g) GHz' % ( fit_res.params['f0'].value, fit_res.params['f0'].stderr) + '\n' \ - '$Qc$ = %.1f $\pm$ (%.1f)' % ( - fit_res.params['Qc'].value, - fit_res.params['Qc'].stderr) + '\n' \ - '$Qi$ = %.1f $\pm$ (%.1f)' % ( - fit_res.params['Qi'].value, fit_res.params['Qi'].stderr) + \ - old_vals + '$Qc$ = %.1f $\pm$ (%.1f)' % ( + fit_res.params['Qc'].value, + fit_res.params['Qc'].stderr) + '\n' \ + '$Qi$ = %.1f $\pm$ (%.1f)' % ( + fit_res.params['Qi'].value, fit_res.params['Qi'].stderr) + \ + old_vals else: ############################################################################### # Custom must be a dictionary # @@ -5671,28 +5692,30 @@ def run_default_analysis(self, print_fit_results=False, ############################################################################### custom_power = kw['custom_power_message'] - power_in_w = 10**((custom_power['Power']-custom_power['Atten'])/10)*1e-3 - mean_ph = (2*(fit_res.params['Q'].value**2)/(fit_res.params['Qc'].value*hbar*(2*pi*fit_res.params['f0'].value*1e9)**2))*power_in_w - phase_vel = 4*custom_power['res_len']*fit_res.params['f0'].value*1e9 + power_in_w = 10 ** ((custom_power['Power'] - custom_power['Atten']) / 10) * 1e-3 + mean_ph = (2 * (fit_res.params['Q'].value ** 2) / (fit_res.params['Qc'].value * hbar * ( + 2 * pi * fit_res.params['f0'].value * 1e9) ** 2)) * power_in_w + phase_vel = 4 * custom_power['res_len'] * fit_res.params['f0'].value * 1e9 textstr = '$f_{\mathrm{center}}$ = %.5f GHz $\pm$ (%.3g) GHz' % ( fit_res.params['f0'].value, fit_res.params['f0'].stderr) + '\n' \ - '$Qc$ = %.1f $\pm$ (%.1f)' % ( - fit_res.params['Qc'].value, - fit_res.params['Qc'].stderr) + '\n' \ - '$Qi$ = %.1f $\pm$ (%.1f)' % ( - fit_res.params['Qi'].value, fit_res.params['Qi'].stderr) + \ - old_vals + '\n' \ - '$< n_{\mathrm{ph} }>$ = %.1f' %(mean_ph) + '\n' \ - '$v_{\mathrm{phase}}$ = %.3e m/s' %(phase_vel) + '$Qc$ = %.1f $\pm$ (%.1f)' % ( + fit_res.params['Qc'].value, + fit_res.params['Qc'].stderr) + '\n' \ + '$Qi$ = %.1f $\pm$ (%.1f)' % ( + fit_res.params['Qi'].value, fit_res.params['Qi'].stderr) + \ + old_vals + '\n' \ + '$< n_{\mathrm{ph} }>$ = %.1f' % (mean_ph) + '\n' \ + '$v_{\mathrm{phase}}$ = %.3e m/s' % ( + phase_vel) elif fitting_model == 'lorentzian': textstr = '$f_{{\mathrm{{center}}}}$ = %.5f GHz ' \ '$\pm$ (%.3g) GHz' % ( - fit_res.params['f0'].value*scale, - fit_res.params['f0'].stderr*scale) + '\n' \ - '$Q$ = %.1f $\pm$ (%.1f)' % ( + fit_res.params['f0'].value * scale, + fit_res.params['f0'].stderr * scale) + '\n' \ + '$Q$ = %.1f $\pm$ (%.1f)' % ( fit_res.params['Q'].value, fit_res.params['Q'].stderr) + old_vals @@ -5734,7 +5757,7 @@ def run_default_analysis(self, print_fit_results=False, f0 = fit_res.params['f0'].value if 'hanger' in fitting_model: # f is expected in Hz but f0 in GHz! - ax.plot(f0*1e9, Model.func(f=f0*1e9, **fit_res.best_values), 'o', + ax.plot(f0 * 1e9, Model.func(f=f0 * 1e9, **fit_res.best_values), 'o', ms=self.marker_size_special) else: ax.plot(f0, Model.func(f=f0, **fit_res.best_values), 'o', @@ -5808,7 +5831,7 @@ def run_default_analysis(self, print_fit_results=False, window_len=11, grp.attrs.create(name='max_delay', data=self.max_delay) grp.attrs.create(name='window_length', data=window_len) - textstr = "optimal delay = {:.0f} ns".format(self.max_delay*1e9) + textstr = "optimal delay = {:.0f} ns".format(self.max_delay * 1e9) if print_results: print(textstr) @@ -5817,15 +5840,15 @@ def run_default_analysis(self, print_fit_results=False, window_len=11, ax.text(0.05, 0.95, textstr, transform=ax.transAxes, fontsize=11, verticalalignment='top', bbox=self.box_props) - self.plot_results_vs_sweepparam(x=self.sweep_points*1e9, + self.plot_results_vs_sweepparam(x=self.sweep_points * 1e9, y=self.measured_values[0], fig=fig, ax=ax, xlabel='Acquisition delay (ns)', ylabel='Signal amplitude (arb. units)', save=False) - ax.plot(self.sweep_points*1e9, self.y_smoothed, 'r-') - ax.plot((self.max_delay*1e9, self.max_delay*1e9), ax.get_ylim(), 'g-') + ax.plot(self.sweep_points * 1e9, self.y_smoothed, 'r-') + ax.plot((self.max_delay * 1e9, self.max_delay * 1e9), ax.get_ylim(), 'g-') self.save_fig(fig, xlabel='delay', ylabel='amplitude', **kw) if close_file: @@ -5849,7 +5872,7 @@ def run_default_analysis(self, print_fit_results=False, self.add_analysis_datagroup_to_file() # Fit Power to a Lorentzian - self.measured_powers = self.measured_values[0]**2 + self.measured_powers = self.measured_values[0] ** 2 min_index = np.argmin(self.measured_powers) max_index = np.argmax(self.measured_powers) @@ -5860,13 +5883,13 @@ def run_default_analysis(self, print_fit_results=False, self.peaks = a_tools.peak_finder((self.sweep_points), self.measured_values[0]) - if self.peaks['dip'] is not None: # look for dips first + if self.peaks['dip'] is not None: # look for dips first f0 = self.peaks['dip'] amplitude_factor = -1. elif self.peaks['peak'] is not None: # then look for peaks f0 = self.peaks['peak'] amplitude_factor = 1. - else: # Otherwise take center of range + else: # Otherwise take center of range f0 = np.median(self.sweep_points) amplitude_factor = -1. logging.error('No peaks or dips in range') @@ -5875,12 +5898,12 @@ def run_default_analysis(self, print_fit_results=False, def poly(x, c0, c1, c2): "line" - return c2 * x**2 + c1 * x + c0 + return c2 * x ** 2 + c1 * x + c0 def cosine(x, amplitude, frequency, phase, offset): # Naming convention, frequency should be Hz # omega is in radial freq - return amplitude*np.cos(2*np.pi*frequency*x + phase)+offset + return amplitude * np.cos(2 * np.pi * frequency * x + phase) + offset def hanger_function_amplitude(x, f0, Q, Qe, A, theta): ''' @@ -5891,15 +5914,15 @@ def hanger_function_amplitude(x, f0, Q, Qe, A, theta): In this case it may misjudge the slope Theta is the asymmetry parameter ''' - return abs(A*(1.-Q/Qe*np.exp(1.j*theta)/(1.+2.j*Q*(x-f0)/f0))) + return abs(A * (1. - Q / Qe * np.exp(1.j * theta) / (1. + 2.j * Q * (x - f0) / f0))) - HangerModel = lmfit.Model(hanger_function_amplitude)\ - + lmfit.Model(cosine) \ - + lmfit.Model(poly) + HangerModel = lmfit.Model(hanger_function_amplitude) \ + + lmfit.Model(cosine) \ + + lmfit.Model(poly) # amplitude_guess = np.pi*sigma_guess * abs( # max(self.measured_powers)-min(self.measured_powers)) - amplitude_guess = max(self.measured_powers)-min(self.measured_powers) + amplitude_guess = max(self.measured_powers) - min(self.measured_powers) S21min = min(self.measured_values[0]) # Creating parameters and estimations @@ -5915,8 +5938,8 @@ def hanger_function_amplitude(x, f0, Q, Qe, A, theta): HangerModel.set_param_hint('Qi', expr='1./(1./Q-1./Qe*cos(theta))', vary=False) HangerModel.set_param_hint('Qc', expr='Qe/cos(theta)', vary=False) - HangerModel.set_param_hint('theta', value=0, min=-np.pi/2, - max=np.pi/2) + HangerModel.set_param_hint('theta', value=0, min=-np.pi / 2, + max=np.pi / 2) HangerModel.set_param_hint('slope', value=0, vary=True) HangerModel.set_param_hint('c0', value=0, vary=False) @@ -5927,7 +5950,7 @@ def hanger_function_amplitude(x, f0, Q, Qe, A, theta): HangerModel.set_param_hint( 'frequency', value=50, min=0, max=300, vary=True) HangerModel.set_param_hint( - 'phase', value=0, min=0, max=2*np.pi, vary=True) + 'phase', value=0, min=0, max=2 * np.pi, vary=True) HangerModel.set_param_hint('offset', value=0, vary=True) self.params = HangerModel.make_params() @@ -5967,7 +5990,6 @@ def hanger_function_amplitude(x, f0, Q, Qe, A, theta): class Qubit_Spectroscopy_Analysis(MeasurementAnalysis): - """ Analysis script for a regular (ge peak/dip only) or a high power (ge and gf/2 peaks/dips) Qubit Spectroscopy: @@ -6092,25 +6114,25 @@ def fit_data(self, analyze_ef=False, **kw): key = 'dip' else: # Otherwise take center of range and raise warning f0 = np.median(self.sweep_points) - kappa_guess = 0.005*1e9 + kappa_guess = 0.005 * 1e9 logging.warning('No peaks or dips have been found. Initial ' 'frequency guess taken ' 'as median of sweep points (f_guess={}), ' 'initial linewidth ' 'guess was taken as kappa_guess={}'.format( - f0, kappa_guess)) + f0, kappa_guess)) key = 'peak' tallest_peak = f0 # the ge freq if verbose: - print('Largest '+key+' is at ', tallest_peak) + print('Largest ' + key + ' is at ', tallest_peak) if f0 == self.peaks[key]: - tallest_peak_idx = self.peaks[key+'_idx'] + tallest_peak_idx = self.peaks[key + '_idx'] if verbose: - print('Largest '+key+' idx is ', tallest_peak_idx) + print('Largest ' + key + ' idx is ', tallest_peak_idx) amplitude_guess = np.pi * kappa_guess * \ - abs(max(self.data_dist) - min(self.data_dist)) + abs(max(self.data_dist) - min(self.data_dist)) if key == 'dip': amplitude_guess = -amplitude_guess @@ -6145,13 +6167,13 @@ def fit_data(self, analyze_ef=False, **kw): # extract second highest peak -> ef transition f0, f0_gf_over_2, \ - kappa_guess, kappa_guess_ef = a_tools.find_second_peak( - sweep_pts=self.sweep_points, - data_dist_smooth=data_dist_smooth, - key=key, - peaks=self.peaks, - percentile=percentile, - verbose=verbose) + kappa_guess, kappa_guess_ef = a_tools.find_second_peak( + sweep_pts=self.sweep_points, + data_dist_smooth=data_dist_smooth, + key=key, + peaks=self.peaks, + percentile=percentile, + verbose=verbose) if f0 == 0: f0 = tallest_peak @@ -6163,11 +6185,11 @@ def fit_data(self, analyze_ef=False, **kw): kappa_guess_ef = 2.5e6 amplitude_guess = np.pi * kappa_guess * \ - abs(max(self.data_dist) - min(self.data_dist)) + abs(max(self.data_dist) - min(self.data_dist)) - amplitude_guess_ef = 0.5*np.pi * kappa_guess_ef * \ - abs(max(self.data_dist) - - min(self.data_dist)) + amplitude_guess_ef = 0.5 * np.pi * kappa_guess_ef * \ + abs(max(self.data_dist) - + min(self.data_dist)) if key == 'dip': amplitude_guess = -amplitude_guess @@ -6222,7 +6244,7 @@ def run_default_analysis(self, print_fit_results=False, analyze_ef=False, # self.marker_size_special, self.qb_name which should be defined in the # MeasurementAnalysis init. if not hasattr(self, 'font_size') and not hasattr(self, 'line_width') \ - and not hasattr(self, 'marker_size_special') \ + and not hasattr(self, 'marker_size_special') \ and not hasattr(self, 'qb_name'): try: q_idx = self.folder[-10::].index('q') @@ -6299,31 +6321,31 @@ def run_default_analysis(self, print_fit_results=False, analyze_ef=False, 'f0_gf/2={:.5f} GHz $\pm$ ({:.2f}) MHz ' \ '\nold f0_gf/2={:.5f} GHz' \ '\nkappa_gf={:.4f} MHz $\pm$ ({:.2f}) MHz'.format( - self.fit_res.params['f0'].value*scale, - self.fit_res.params['f0'].stderr/1e6, - old_freq*scale, - self.fit_res.params['kappa'].value/1e6, - self.fit_res.params['kappa'].stderr/1e6, - self.fit_res.params['f0_gf_over_2'].value*scale, - self.fit_res.params['f0_gf_over_2'].stderr/1e6, - old_freq_ef*scale, - self.fit_res.params['kappa_gf_over_2'].value/1e6, - self.fit_res.params['kappa_gf_over_2'].stderr/1e6) + self.fit_res.params['f0'].value * scale, + self.fit_res.params['f0'].stderr / 1e6, + old_freq * scale, + self.fit_res.params['kappa'].value / 1e6, + self.fit_res.params['kappa'].stderr / 1e6, + self.fit_res.params['f0_gf_over_2'].value * scale, + self.fit_res.params['f0_gf_over_2'].stderr / 1e6, + old_freq_ef * scale, + self.fit_res.params['kappa_gf_over_2'].value / 1e6, + self.fit_res.params['kappa_gf_over_2'].stderr / 1e6) except (TypeError, KeyError, ValueError): logging.warning('qb_name is None. Old parameter values will ' 'not be retrieved.') label = 'f0={:.5f} GHz $\pm$ ({:.2f}) MHz ' \ - '\nkappa0={:.4f} MHz $\pm$ ({:.2f}) MHz\n'\ + '\nkappa0={:.4f} MHz $\pm$ ({:.2f}) MHz\n' \ 'f0_gf/2={:.5f} GHz $\pm$ ({:.2f}) MHz ' \ '\nkappa_gf={:.4f} MHz $\pm$ ({:.2f}) MHz'.format( - self.fit_res.params['f0'].value*scale, - self.fit_res.params['f0'].stderr/1e6, - self.fit_res.params['kappa'].value/1e6, - self.fit_res.params['kappa'].stderr/1e6, - self.fit_res.params['f0_gf_over_2'].value*scale, - self.fit_res.params['f0_gf_over_2'].stderr/1e6, - self.fit_res.params['kappa_gf_over_2'].value/1e6, - self.fit_res.params['kappa_gf_over_2'].stderr/1e6) + self.fit_res.params['f0'].value * scale, + self.fit_res.params['f0'].stderr / 1e6, + self.fit_res.params['kappa'].value / 1e6, + self.fit_res.params['kappa'].stderr / 1e6, + self.fit_res.params['f0_gf_over_2'].value * scale, + self.fit_res.params['f0_gf_over_2'].stderr / 1e6, + self.fit_res.params['kappa_gf_over_2'].value / 1e6, + self.fit_res.params['kappa_gf_over_2'].stderr / 1e6) else: try: old_freq = float(instr_set[self.qb_name].attrs['f_qubit']) @@ -6331,20 +6353,20 @@ def run_default_analysis(self, print_fit_results=False, analyze_ef=False, label = 'f0={:.5f} GHz $\pm$ ({:.2f}) MHz ' \ '\nold f0={:.5f} GHz' \ '\nkappa0={:.4f} MHz $\pm$ ({:.2f}) MHz'.format( - self.fit_res.params['f0'].value*scale, - self.fit_res.params['f0'].stderr/1e6, - old_freq*scale, - self.fit_res.params['kappa'].value/1e6, - self.fit_res.params['kappa'].stderr/1e6) + self.fit_res.params['f0'].value * scale, + self.fit_res.params['f0'].stderr / 1e6, + old_freq * scale, + self.fit_res.params['kappa'].value / 1e6, + self.fit_res.params['kappa'].stderr / 1e6) except (TypeError, KeyError, ValueError): logging.warning('qb_name is None. Old parameter values will ' 'not be retrieved.') label = 'f0={:.5f} GHz $\pm$ ({:.2f}) MHz ' \ '\nkappa0={:.4f} MHz $\pm$ ({:.2f}) MHz'.format( - self.fit_res.params['f0'].value*scale, - self.fit_res.params['f0'].stderr/1e6, - self.fit_res.params['kappa'].value/1e6, - self.fit_res.params['kappa'].stderr/1e6) + self.fit_res.params['f0'].value * scale, + self.fit_res.params['f0'].stderr / 1e6, + self.fit_res.params['kappa'].value / 1e6, + self.fit_res.params['kappa'].stderr / 1e6) fig_dist.text(0.5, 0, label, transform=ax_dist.transAxes, fontsize=self.font_size, verticalalignment='top', @@ -6358,15 +6380,15 @@ def run_default_analysis(self, print_fit_results=False, analyze_ef=False, print('f_ge = {:.5} (GHz) \t f_ge Stderr = {:.5} (MHz) \n' 'f_gf/2 = {:.5} (GHz) \t f_gf/2 Stderr = {:.5} ' '(MHz)'.format( - self.fitted_freq*scale, - self.fit_res.params['f0'].stderr*1e-6, - self.fitted_freq_gf_over_2*scale, - self.fit_res.params['f0_gf_over_2'].stderr*1e-6)) + self.fitted_freq * scale, + self.fit_res.params['f0'].stderr * 1e-6, + self.fitted_freq_gf_over_2 * scale, + self.fit_res.params['f0_gf_over_2'].stderr * 1e-6)) else: print('f_ge = {:.5} (GHz) \t ' 'f_ge Stderr = {:.5} (MHz)'.format( - self.fitted_freq*scale, - self.fit_res.params['f0'].stderr*1e-6)) + self.fitted_freq * scale, + self.fit_res.params['f0'].stderr * 1e-6)) if show: plt.show() @@ -6391,7 +6413,6 @@ def get_linewidth_estimate(self): class Mixer_Calibration_Analysis(MeasurementAnalysis): - ''' Simple analysis that takes the minimum value measured and adds it to the analysis datagroup @@ -6485,55 +6506,55 @@ def run_default_analysis(self, **kw): label='data', fmt='ob') ax1.plot(x_fine, fitted_freqs, '--c', label='fit') ax1.legend() - ax1.set_title(self.timestamp_string+'\n' + 'Qubit Frequency') + ax1.set_title(self.timestamp_string + '\n' + 'Qubit Frequency') ax1.set_xlabel((str(self.sweep_name + ' (' + self.sweep_unit + ')'))) ax1.set_ylabel(r'$f_{qubit}$ (GHz)') ax1.grid() fig2, axarray2 = plt.subplots(2, 1, figsize=figsize) - axarray2[0].set_title(self.timestamp_string+'\n' + 'Qubit Coherence') + axarray2[0].set_title(self.timestamp_string + '\n' + 'Qubit Coherence') axarray2[0].errorbar( x=x, - y=T1*1e-3, yerr=T1_stderr*1e-3, + y=T1 * 1e-3, yerr=T1_stderr * 1e-3, fmt='o', label='$T_1$') axarray2[0].errorbar( x=x, - y=T2_echo*1e-3, yerr=T2_echo_stderr*1e-3, + y=T2_echo * 1e-3, yerr=T2_echo_stderr * 1e-3, fmt='o', label='$T_2$-echo') axarray2[0].errorbar( x=x, - y=T2_star*1e-3, yerr=T2_star_stderr*1e-3, + y=T2_star * 1e-3, yerr=T2_star_stderr * 1e-3, fmt='o', label='$T_2$-star') axarray2[0].set_xlabel(r'dac voltage') axarray2[0].set_ylabel(r'$\tau (\mu s)$ ') # axarray[0].set_xlim(-600, 700) - axarray2[0].set_ylim(0, max([max(T1*1e-3), max(T2_echo*1e-3)]) - + 3*max(T1_stderr*1e-3)) + axarray2[0].set_ylim(0, max([max(T1 * 1e-3), max(T2_echo * 1e-3)]) + + 3 * max(T1_stderr * 1e-3)) axarray2[0].legend() axarray2[0].grid() axarray2[1].errorbar( - x=qubit_freq*1e-9, - y=T1*1e-3, yerr=T1_stderr*1e-3, + x=qubit_freq * 1e-9, + y=T1 * 1e-3, yerr=T1_stderr * 1e-3, fmt='o', label='$T_1$') axarray2[1].errorbar( - x=qubit_freq*1e-9, - y=T2_echo*1e-3, yerr=T2_echo_stderr*1e-3, + x=qubit_freq * 1e-9, + y=T2_echo * 1e-3, yerr=T2_echo_stderr * 1e-3, fmt='o', label='$T_2$-echo') axarray2[1].errorbar( - x=qubit_freq*1e-9, - y=T2_star*1e-3, yerr=T2_star_stderr*1e-3, + x=qubit_freq * 1e-9, + y=T2_star * 1e-3, yerr=T2_star_stderr * 1e-3, fmt='o', label='$T_2^\star$') axarray2[1].set_xlabel(r'$f_{qubit}$ (GHz)') axarray2[1].set_ylabel(r'$\tau (\mu s)$ ') # axarray[1].set_xlim(-600, 700) - axarray2[1].set_ylim(0, max([max(T1*1e-3), max(T2_echo*1e-3)]) - + 3*max(T1_stderr*1e-3)) + axarray2[1].set_ylim(0, max([max(T1 * 1e-3), max(T2_echo * 1e-3)]) + + 3 * max(T1_stderr * 1e-3)) axarray2[1].legend(loc=2) axarray2[1].grid() fig3, axarray3 = plt.subplots(2, 1, figsize=figsize) - axarray3[0].set_title(self.timestamp+'\n' + 'AWG pulse amplitude') + axarray3[0].set_title(self.timestamp + '\n' + 'AWG pulse amplitude') axarray3[0].plot(x, AWG_Pulse_amp_ch1, 'o') axarray3[0].plot(x, AWG_Pulse_amp_ch2, 'o') axarray3[0].set_xlabel(r'dac voltage') @@ -6577,13 +6598,13 @@ def run_default_analysis(self, **kw): close_file = kw.pop('close_file', True) x = self.sweep_points x_fine = np.linspace( - self.sweep_points[0], self.sweep_points[-1], 1000)*1e-3 + self.sweep_points[0], self.sweep_points[-1], 1000) * 1e-3 self.qubit_freq = self.measured_values[2] self.qubit_freq_stderr = self.measured_values[3] - fit_res = fit_qubit_frequency(sweep_points=x*1e-3, - data=self.qubit_freq*1e9, + fit_res = fit_qubit_frequency(sweep_points=x * 1e-3, + data=self.qubit_freq * 1e9, mode=self.fit_mode, data_file=self.data_file, qubit_name=self.qubit_name, **kw) @@ -6598,16 +6619,16 @@ def run_default_analysis(self, **kw): dac_offset=fit_res.best_values['dac_offset']) fig1, ax1 = self.default_ax() - ax1.errorbar(x=x*1e-3, y=self.qubit_freq*1e9, + ax1.errorbar(x=x * 1e-3, y=self.qubit_freq * 1e9, yerr=self.qubit_freq_stderr, label='data', fmt='ob') if show_guess: - ax1.plot(x*1e-3, fit_res.init_fit, 'k--') + ax1.plot(x * 1e-3, fit_res.init_fit, 'k--') ax1.plot(x_fine, fitted_freqs, '--c', label='fit') ax1.legend() - ax1.set_title(self.timestamp+'\n' + 'Qubit Frequency') + ax1.set_title(self.timestamp + '\n' + 'Qubit Frequency') ax1.set_xlabel((str(self.sweep_name + ' (V)'))) ax1.set_ylabel(r'$f_{qubit}$ (GHz)') ax1.grid() @@ -6620,7 +6641,6 @@ def run_default_analysis(self, **kw): class TwoD_Analysis(MeasurementAnalysis): - ''' Analysis for 2D measurements. ''' @@ -6693,13 +6713,13 @@ def run_default_analysis(self, normalize=False, plot_linecuts=True, self.value_names[i]) if "xlabel" not in kw: - kw["xlabel"]=self.parameter_names[0] + kw["xlabel"] = self.parameter_names[0] if "ylabel" not in kw: - kw["ylabel"]=self.parameter_names[1] + kw["ylabel"] = self.parameter_names[1] if "xunit" not in kw: - kw["xunit"]=self.parameter_units[0] + kw["xunit"] = self.parameter_units[0] if "yunit" not in kw: - kw["yunit"]=self.parameter_units[1] + kw["yunit"] = self.parameter_units[1] a_tools.color_plot(x=self.sweep_points, y=self.sweep_points_2D, @@ -6711,8 +6731,8 @@ def run_default_analysis(self, normalize=False, plot_linecuts=True, normalize=normalize, **kw) ax.set_title(fig_title) - #set_xlabel(ax, self.parameter_names[0], self.parameter_units[0]) - #set_ylabel(ax, self.parameter_names[1], self.parameter_units[1]) + # set_xlabel(ax, self.parameter_names[0], self.parameter_units[0]) + # set_ylabel(ax, self.parameter_names[1], self.parameter_units[1]) if save_fig: self.save_fig(fig, figname=savename, **kw) @@ -6754,8 +6774,8 @@ def run_default_analysis(self, save_fig=True, ampl_min_idx = np.argmin(data_arr[phase_min_idx]) self.QI_min = self.sweep_points[ampl_min_idx] - textstr = 'Q phase of minimum = %.2f deg' % self.phase_min + '\n' + \ - 'Q/I ratio of minimum = %.2f' % self.QI_min + textstr = 'Q phase of minimum = %.2f deg' % self.phase_min + '\n' + \ + 'Q/I ratio of minimum = %.2f' % self.QI_min ax.text(0.60, 0.95, textstr, transform=ax.transAxes, @@ -6772,7 +6792,6 @@ def run_default_analysis(self, save_fig=True, class Three_Tone_Spectroscopy_Analysis(MeasurementAnalysis): - ''' Analysis for 2D measurement Three tone spectroscopy. **kwargs: @@ -6796,7 +6815,7 @@ def run_default_analysis(self, f01=None, f12=None, measured_phases = self.measured_values[1] fig1_title = self.timestamp_string + \ - self.measurementstring+'_'+'Amplitude' + self.measurementstring + '_' + 'Amplitude' a_tools.color_plot(x=self.sweep_points, y=self.sweep_points_2D, z=measured_powers.transpose(), @@ -6809,7 +6828,7 @@ def run_default_analysis(self, f01=None, f12=None, # figsize wider for colorbar fig2, ax2 = self.default_ax(figsize=(8, 5)) - fig2_title = self.timestamp_string+self.measurementstring+'_'+'Phase' + fig2_title = self.timestamp_string + self.measurementstring + '_' + 'Phase' a_tools.color_plot(x=self.sweep_points, y=self.sweep_points_2D, z=measured_phases.transpose(), @@ -6830,24 +6849,24 @@ def run_default_analysis(self, f01=None, f12=None, if f12 is not None: ax1.plot((min(self.sweep_points), max(self.sweep_points)), - (f01 + f12-min(self.sweep_points), - f01 + f12-max(self.sweep_points)), + (f01 + f12 - min(self.sweep_points), + f01 + f12 - max(self.sweep_points)), linestyle='dashed', lw=2, color=line_color, alpha=.5) ax2.plot((min(self.sweep_points), max(self.sweep_points)), - (f01 + f12-min(self.sweep_points), - f01 + f12-max(self.sweep_points)), + (f01 + f12 - min(self.sweep_points), + f01 + f12 - max(self.sweep_points)), linestyle='dashed', lw=2, color=line_color, alpha=.5) if (f01 is not None) and (f12 is not None): - anharm = f01-f12 + anharm = f01 - f12 EC, EJ = a_tools.fit_EC_EJ(f01, f12) # EC *= 1000 - textstr = 'f01 = {:.4g} GHz'.format(f01*1e-9) + '\n' + \ - 'f12 = {:.4g} GHz'.format(f12*1e-9) + '\n' + \ - 'anharm = {:.4g} MHz'.format(anharm*1e-6) + '\n' + \ - 'EC ~= {:.4g} MHz'.format(EC*1e-6) + '\n' + \ - 'EJ = {:.4g} GHz'.format(EJ*1e-9) + textstr = 'f01 = {:.4g} GHz'.format(f01 * 1e-9) + '\n' + \ + 'f12 = {:.4g} GHz'.format(f12 * 1e-9) + '\n' + \ + 'anharm = {:.4g} MHz'.format(anharm * 1e-6) + '\n' + \ + 'EC ~= {:.4g} MHz'.format(EC * 1e-6) + '\n' + \ + 'EJ = {:.4g} GHz'.format(EJ * 1e-9) ax1.text(0.95, 0.95, textstr, transform=ax1.transAxes, fontsize=11, verticalalignment='top', @@ -6892,9 +6911,9 @@ def __init__(self, label='powersweep', **kw): # def run_default_analysis(self, normalize=True, w_low_power=None, # w_high_power=None, **kw): - # super(self.__class__, self).run_default_analysis(close_file=False, - # save_fig=False, **kw) - # close_file = kw.pop('close_file', True) + # super(self.__class__, self).run_default_analysis(close_file=False, + # save_fig=False, **kw) + # close_file = kw.pop('close_file', True) def run_default_analysis(self, normalize=True, plot_Q=True, plot_f0=True, plot_linecuts=True, linecut_log=True, plot_all=False, save_fig=True, **kw): @@ -6910,7 +6929,7 @@ def run_default_analysis(self, normalize=True, plot_Q=True, plot_f0=True, plot_l for u, power in enumerate(self.sweep_points_2D): fit_res = self.fit_hanger_model( self.sweep_points, self.measured_values[0][:, u]) - self.save_fitted_parameters(fit_res, var_name='Powersweep'+str(u)) + self.save_fitted_parameters(fit_res, var_name='Powersweep' + str(u)) fits[str(power)] = fit_res self.fit_results = fits @@ -7020,7 +7039,7 @@ def fit_hanger_model(self, sweep_values, measured_values): # max(self.measured_powers)-min(self.measured_powers)) # Fit Power to a Lorentzian - measured_powers = measured_values**2 + measured_powers = measured_values ** 2 min_index = np.argmin(measured_powers) max_index = np.argmax(measured_powers) @@ -7031,22 +7050,22 @@ def fit_hanger_model(self, sweep_values, measured_values): peaks = a_tools.peak_finder((sweep_values), measured_values) - if peaks['dip'] is not None: # look for dips first + if peaks['dip'] is not None: # look for dips first f0 = peaks['dip'] amplitude_factor = -1. elif peaks['peak'] is not None: # then look for peaks f0 = peaks['peak'] amplitude_factor = 1. - else: # Otherwise take center of range + else: # Otherwise take center of range f0 = np.median(sweep_values) amplitude_factor = -1. logging.error('No peaks or dips in range') # If this error is raised, it should continue the analysis but # not use it to update the qubit object - amplitude_guess = max(measured_powers)-min(measured_powers) + amplitude_guess = max(measured_powers) - min(measured_powers) # Creating parameters and estimations - S21min = min(measured_values)/max(measured_values) + S21min = min(measured_values) / max(measured_values) Q = f0 / abs(min_frequency - max_frequency) Qe = abs(Q / abs(1 - S21min)) @@ -7060,8 +7079,8 @@ def fit_hanger_model(self, sweep_values, measured_values): HangerModel.set_param_hint('Qi', expr='1./(1./Q-1./Qe*cos(theta))', vary=False) HangerModel.set_param_hint('Qc', expr='Qe/cos(theta)', vary=False) - HangerModel.set_param_hint('theta', value=0, min=-np.pi/2, - max=np.pi/2) + HangerModel.set_param_hint('theta', value=0, min=-np.pi / 2, + max=np.pi / 2) HangerModel.set_param_hint('slope', value=0, vary=True, min=-1, max=1) params = HangerModel.make_params() @@ -7073,7 +7092,6 @@ def fit_hanger_model(self, sweep_values, measured_values): class time_trace_analysis(MeasurementAnalysis): - ''' Analysis for a binary (+1, -1) time trace returns the average length till flip @@ -7101,10 +7119,10 @@ def run_default_analysis(self, flipping_sequence=False, **kw): self.average_cycles_constant = np.mean(rsf_lst_pm) self.ax.hist(rsf_lst_mp, bins, histtype='step', normed=1, label='Avg rounds flipping = %.2f' % - np.mean(rsf_lst_mp), color='b') + np.mean(rsf_lst_mp), color='b') self.ax.hist(rsf_lst_pm, bins, histtype='step', normed=1, label='Avg rounds constant = %.2f' - % np.mean(rsf_lst_pm), color='r') + % np.mean(rsf_lst_pm), color='r') self.ax.set_yscale('log') self.ax.set_ylabel('normalized occurence') self.ax.set_xlabel('rounds') @@ -7112,7 +7130,7 @@ def run_default_analysis(self, flipping_sequence=False, **kw): self.ax.set_xlim(0, 80) self.ax.legend() self.ax.set_title( - self.timestamp_string+'\n'+self.measurementstring) + self.timestamp_string + '\n' + self.measurementstring) self.save_fig(self.fig, xlabel='rounds_flipping', ylabel='normalized occurence', **kw) return self.average_cycles_constant, self.average_cycles_flipping @@ -7121,10 +7139,10 @@ def run_default_analysis(self, flipping_sequence=False, **kw): self.mean_rnds_since_fl_pm = np.mean(rsf_lst_pm) self.ax.hist(rsf_lst_mp, bins, histtype='step', normed=1, label='Avg rounds till flip -1 to +1 = %.2f' % - np.mean(rsf_lst_mp), color='b') + np.mean(rsf_lst_mp), color='b') self.ax.hist(rsf_lst_pm, bins, histtype='step', normed=1, label='Avg rounds till flip +1 to -1 = %.2f' - % np.mean(rsf_lst_pm), color='r') + % np.mean(rsf_lst_pm), color='r') self.ax.set_yscale('log') self.ax.set_ylabel('normalized occurence') self.ax.set_xlabel('rounds till flip') @@ -7132,14 +7150,13 @@ def run_default_analysis(self, flipping_sequence=False, **kw): self.ax.set_xlim(0, 80) self.ax.legend() self.ax.set_title( - self.timestamp_string+'\n'+self.measurementstring) + self.timestamp_string + '\n' + self.measurementstring) self.save_fig(self.fig, xlabel='rounds_till_flip', ylabel='normalized occurence', **kw) return self.mean_rnds_since_fl_pm, self.mean_rnds_since_fl_mp class time_trace_analysis_initialized(MeasurementAnalysis): - ''' Analysis for a binary (+1, -1) time trace returns the average length till flip @@ -7154,7 +7171,7 @@ def run_default_analysis(self, flipping_sequence=False, **kw): rtf = [dm_tools.count_rounds_to_error(ser) for ser in self.Z] self.mean_rtf = np.nanmean(rtf) self.std_rtf = np.nanstd(rtf) - self.std_err_rtf = self.std_rtf/np.sqrt(len(self.sweep_points_2D)) + self.std_err_rtf = self.std_rtf / np.sqrt(len(self.sweep_points_2D)) if kw.pop('make_fig', True): self.fig, self.ax = plt.subplots(1, 1, figsize=(13, 6)) @@ -7162,14 +7179,14 @@ def run_default_analysis(self, flipping_sequence=False, **kw): hist, bins = np.histogram(rtf, bins=bins, density=True) self.ax.plot(bins[1:], hist, drawstyle='steps', label='Mean rounds till failure = %.2f' - % self.mean_rtf) + % self.mean_rtf) self.ax.set_yscale('log') self.ax.set_ylabel('normalized occurence') self.ax.set_xlabel('Rounds to failure') self.ax.set_ylim(1e-4, 1) self.ax.set_xlim(0, 100) self.ax.legend() - self.ax.set_title(self.timestamp_string+'\n' + + self.ax.set_title(self.timestamp_string + '\n' + self.measurementstring) self.save_fig(self.fig, xlabel='Rounds to failure', ylabel='normalized occurence', **kw) @@ -7178,7 +7195,6 @@ def run_default_analysis(self, flipping_sequence=False, **kw): class rounds_to_failure_analysis(MeasurementAnalysis): - ''' Analysis for a binary (+1, -1) time trace returns the average rounds to surprise/failure. @@ -7198,16 +7214,16 @@ def run_default_analysis(self, flipping_sequence=False, **kw): rtf, term_cond = list(zip(*rtf_c)) self.mean_rtf = np.nanmean(rtf) self.std_rtf = np.nanstd(rtf) - self.std_err_rtf = self.std_rtf/np.sqrt(len(self.sweep_points_2D)) + self.std_err_rtf = self.std_rtf / np.sqrt(len(self.sweep_points_2D)) term_cts = Counter(term_cond) # note that we only take 1 derivative and this is not equal to the # notion of detection events as in Kelly et al. terminated_by_flip = float(term_cts['single event']) terminated_by_RO_err = float(term_cts['double event']) total_cts = terminated_by_RO_err + terminated_by_flip + \ - term_cts['unknown'] - self.flip_err_frac = terminated_by_flip/total_cts*100. - self.RO_err_frac = terminated_by_RO_err/total_cts*100. + term_cts['unknown'] + self.flip_err_frac = terminated_by_flip / total_cts * 100. + self.RO_err_frac = terminated_by_RO_err / total_cts * 100. if kw.pop('make_fig', True): self.fig, self.ax = plt.subplots(1, 1, figsize=(13, 6)) @@ -7224,7 +7240,7 @@ def run_default_analysis(self, flipping_sequence=False, **kw): self.ax.set_ylim(1e-4, 1) self.ax.set_xlim(0, 200) self.ax.legend() - self.ax.set_title(self.timestamp_string+'\n' + + self.ax.set_title(self.timestamp_string + '\n' + self.measurementstring) self.save_fig(self.fig, xlabel='Rounds to failure', ylabel='normalized occurence', **kw) @@ -7233,12 +7249,11 @@ def run_default_analysis(self, flipping_sequence=False, **kw): class butterfly_analysis(MeasurementAnalysis): - ''' Extracts the coefficients for the post-measurement butterfly ''' - def __init__(self, auto=True, label='Butterfly', close_file=True, + def __init__(self, auto=True, label='Butterfly', close_file=True, timestamp=None, threshold=None, threshold_init=None, @@ -7264,7 +7279,7 @@ def __init__(self, auto=True, label='Butterfly', close_file=True, I_shots = self.measured_values[0] Q_shots = self.measured_values[1] - shots = I_shots+1j*Q_shots + shots = I_shots + 1j * Q_shots rot_shots = dm_tools.rotate_complex( shots, angle=theta_in, deg=True) I_shots = rot_shots.real @@ -7280,7 +7295,7 @@ def __init__(self, auto=True, label='Butterfly', close_file=True, # different input states shots = np.size(self.data) shots_per_mmt = np.floor_divide(shots, 6) - shots_used = shots_per_mmt*6 + shots_used = shots_per_mmt * 6 m0_on = self.data[3:shots_used:6] m1_on = self.data[4:shots_used:6] m2_on = self.data[5:shots_used:6] @@ -7311,7 +7326,7 @@ def __init__(self, auto=True, label='Butterfly', close_file=True, self.data_rel = self.data_rel_post fraction = (np.size(self.data_exc) + - np.size(self.data_exc))*3/shots_used/2 + np.size(self.data_exc)) * 3 / shots_used / 2 else: m0_on = self.data[2::4] @@ -7352,21 +7367,21 @@ def bar_plot_raw_probabilities(self): for i in range(nr_msmts): # Convert pauli eigenvalues to probability of excitation # +1 -> 0 and -1 -> 1 - m_off[i] = -(np.mean(data_exc[:, i])-1)/2 - m_on[i] = -(np.mean(data_rel[:, i])-1)/2 + m_off[i] = -(np.mean(data_exc[:, i]) - 1) / 2 + m_on[i] = -(np.mean(data_rel[:, i]) - 1) / 2 f, ax = plt.subplots() ax.set_ylim(0, 1) w = .4 ax.hlines(0.5, -.5, 5, linestyles='--') - bar0 = ax.bar(np.arange(nr_msmts)+w/2, m_off, width=w, color='C0', + bar0 = ax.bar(np.arange(nr_msmts) + w / 2, m_off, width=w, color='C0', label='No $\pi$-pulse') - bar1 = ax.bar(np.arange(nr_msmts)-w/2, m_on, width=w, color='C3', + bar1 = ax.bar(np.arange(nr_msmts) - w / 2, m_on, width=w, color='C3', label='$\pi$-pulse') pl_tools.autolabel_barplot(ax, bar0) pl_tools.autolabel_barplot(ax, bar1) - ax.set_xlim(-.5, nr_msmts-.5) + ax.set_xlim(-.5, nr_msmts - .5) ax.set_xticks([0, 1, 2]) set_ylabel(ax, 'P (|1>)') ax.legend() @@ -7375,11 +7390,11 @@ def bar_plot_raw_probabilities(self): ax.set_title(figname) savename = os.path.abspath(os.path.join( - self.folder, figname+'.png')) + self.folder, figname + '.png')) print(savename) f.savefig(savename, dpi=300, format='png') - def run_default_analysis(self, verbose=False, **kw): + def run_default_analysis(self, verbose=False, **kw): self.exc_coeffs = dm_tools.butterfly_data_binning(Z=self.data_exc, initial_state=0) self.rel_coeffs = dm_tools.butterfly_data_binning(Z=self.data_rel, @@ -7387,10 +7402,10 @@ def run_default_analysis(self, verbose=False, **kw): self.butterfly_coeffs = dm_tools.butterfly_matrix_inversion( self.exc_coeffs, self.rel_coeffs) # eps,declaration,output_input - F_a_butterfly = (1-(self.butterfly_coeffs.get('eps00_1') + - self.butterfly_coeffs.get('eps01_1') + - self.butterfly_coeffs.get('eps10_0') + - self.butterfly_coeffs.get('eps11_0'))/2) + F_a_butterfly = (1 - (self.butterfly_coeffs.get('eps00_1') + + self.butterfly_coeffs.get('eps01_1') + + self.butterfly_coeffs.get('eps10_0') + + self.butterfly_coeffs.get('eps11_0')) / 2) mmt_ind_rel = (self.butterfly_coeffs.get('eps00_1') + self.butterfly_coeffs.get('eps10_1')) @@ -7424,7 +7439,7 @@ def make_data_tables(self): savename = os.path.abspath(os.path.join( self.folder, figname1)) - data_to_table_png(data=data_raw_p, filename=savename+'.png', + data_to_table_png(data=data_raw_p, filename=savename + '.png', title=figname1) figname2 = 'inferred states' @@ -7436,7 +7451,7 @@ def make_data_tables(self): ['eps1_1', '{:.4f}'.format(self.rel_coeffs['eps1_1'])]] savename = os.path.abspath(os.path.join( self.folder, figname2)) - data_to_table_png(data=data_inf, filename=savename+'.png', + data_to_table_png(data=data_inf, filename=savename + '.png', title=figname2) bf = self.butterfly_coeffs @@ -7452,19 +7467,19 @@ def make_data_tables(self): ['eps11_1', '{:.4f}'.format(bf['eps11_1'])]] savename = os.path.abspath(os.path.join( self.folder, figname3)) - data_to_table_png(data=data, filename=savename+'.png', + data_to_table_png(data=data, filename=savename + '.png', title=figname3) figname4 = 'Derived quantities' data = [['Measurement induced excitations', '{:.4f}'.format(bf['mmt_ind_exc'])], ['Measurement induced relaxation', - '{:.4f}'.format(bf['mmt_ind_rel'])], + '{:.4f}'.format(bf['mmt_ind_rel'])], ['Readout fidelity', - '{:.4f}'.format(bf['F_a_butterfly'])]] + '{:.4f}'.format(bf['F_a_butterfly'])]] savename = os.path.abspath(os.path.join( self.folder, figname4)) - data_to_table_png(data=data, filename=savename+'.png', + data_to_table_png(data=data, filename=savename + '.png', title=figname4) @@ -7484,6 +7499,17 @@ def fit_qubit_frequency(sweep_points, data, mode='dac', that value. If a qubit name and a hdf5 data file is specified it uses values from the data_file. NB! This function could be cleaned up a bit. + + :param sweep_points: + :param data: + :param mode: + :param vary_E_c: + :param vary_f_max: + :param vary_dac_flux_coeff: + :param vary_dac_sweet_spot: + :param data_file: + :param kw: + :return: ''' qubit_name = kw.pop('qubit_name', None) @@ -7533,6 +7559,7 @@ def fit_qubit_frequency(sweep_points, data, mode='dac', fit_res = Qubit_freq_mod.fit(data=data, flux=sweep_points) return fit_res + # Ramiro's routines @@ -7542,7 +7569,7 @@ def __init__(self, auto=True, label='', timestamp=None): if timestamp is None: self.folder = a_tools.latest_data('Chevron') splitted = self.folder.split('\\') - self.scan_start = splitted[-2]+'_'+splitted[-1][:6] + self.scan_start = splitted[-2] + '_' + splitted[-1][:6] self.scan_stop = self.scan_start else: self.scan_start = timestamp @@ -7565,10 +7592,10 @@ def analysis(self): x, y, z = self.reshape_data(chevron_scan.TD_dict['sweep_points'][0], chevron_scan.TD_dict['I'][0]) plot_times = y - plot_step = plot_times[1]-plot_times[0] + plot_step = plot_times[1] - plot_times[0] plot_x = x - x_step = plot_x[1]-plot_x[0] + x_step = plot_x[1] - plot_x[0] result = z @@ -7584,9 +7611,9 @@ def analysis(self): ax.set_ylabel(r'Time (ns)') ax.set_title('%s: Chevron scan' % self.scan_start) # ax.set_xlim(xmin, xmax) - ax.set_ylim(plot_x.min()-x_step/2., plot_x.max()+x_step/2.) + ax.set_ylim(plot_x.min() - x_step / 2., plot_x.max() + x_step / 2.) ax.set_xlim( - plot_times.min()-plot_step/2., plot_times.max()+plot_step/2.) + plot_times.min() - plot_step / 2., plot_times.max() + plot_step / 2.) # ax.set_xlim(plot_times.min()-plot_step/2.,plot_times.max()+plot_step/2.) # ax.set_xlim(0,50) # print('Bounce %d ns amp=%.3f; Pole %d ns amp=%.3f'%(list_values[iter_idx,0], @@ -7597,7 +7624,7 @@ def analysis(self): cax = ax_divider.append_axes('right', size='10%', pad='5%') cbar = plt.colorbar(out['cmap'], cax=cax) cbar.set_ticks( - np.arange(fig_clim[0], 1.01*fig_clim[1], (fig_clim[1]-fig_clim[0])/5.)) + np.arange(fig_clim[0], 1.01 * fig_clim[1], (fig_clim[1] - fig_clim[0]) / 5.)) cbar.set_ticklabels( [str(fig_clim[0]), '', '', '', '', str(fig_clim[1])]) cbar.set_label('Qubit excitation probability') @@ -7612,7 +7639,7 @@ def reshape_axis_2d(self, axis_array): dimx = np.sum(np.where(x == x[0], 1, 0)) dimy = len(x) // dimx # print(dimx,dimy) - if dimy*dimx < len(x): + if dimy * dimx < len(x): logging.warning.warn( 'Data was cut-off. Probably due to an interrupted scan') dimy_c = dimy + 1 @@ -7626,10 +7653,10 @@ def reshape_data(self, sweep_points, data): # print(x,y) dimx = len(x) dimy = len(y) - dim = dimx*dimy + dim = dimx * dimy if dim > len(data): dimy = dimy - 1 - return x, y[:dimy], (data[:dimx*dimy].reshape((dimy, dimx))).transpose() + return x, y[:dimy], (data[:dimx * dimy].reshape((dimy, dimx))).transpose() def save_fig(self, fig, figname=None, xlabel='x', ylabel='y', fig_tight=True, **kw): @@ -7640,9 +7667,9 @@ def save_fig(self, fig, figname=None, xlabel='x', ylabel='y', plot_formats = [plot_formats] for plot_format in plot_formats: if figname is None: - figname = (self.scan_start+'_Chevron_2D_'+'.'+plot_format) + figname = (self.scan_start + '_Chevron_2D_' + '.' + plot_format) else: - figname = (figname+'.' + plot_format) + figname = (figname + '.' + plot_format) self.savename = os.path.abspath(os.path.join( self.folder, figname)) if fig_tight: @@ -7696,9 +7723,9 @@ def run_default_analysis(self, **kw): textstr = ('$A_1$: {:.3f} \t$A_2$: {:.3f} \n'.format(A1, A2) + '$f_1$: {:.3f} MHz\t$f_2$: {:.3f} MHz \n'.format( - f1*1e-6, f2*1e-6) + - r'$\tau _1$: {:.2f} $\mu$s'.format(tau1*1e6) + - ' \t'+r'$\tau _2$: {:.2f}$\mu$s'.format(tau2*1e6)) + f1 * 1e-6, f2 * 1e-6) + + r'$\tau _1$: {:.2f} $\mu$s'.format(tau1 * 1e6) + + ' \t' + r'$\tau _2$: {:.2f}$\mu$s'.format(tau2 * 1e6)) ax.text(0.4, 0.95, textstr, transform=ax.transAxes, fontsize=11, @@ -7708,8 +7735,8 @@ def run_default_analysis(self, **kw): ax.set_ylabel(r'$F |1\rangle$') ax.set_title('%s: Double Frequency analysis' % self.timestamp) ax.set_xlabel(r'Time ($\mu s$)') - ax.plot(plot_x*1e6, y, 'o') - ax.plot(plot_x[:-4]*1e6, self.fit_plot, '-') + ax.plot(plot_x * 1e6, y, 'o') + ax.plot(plot_x[:-4] * 1e6, self.fit_plot, '-') fig.tight_layout() self.save_fig(fig, **kw) self.data_file.close() @@ -7718,24 +7745,24 @@ def run_default_analysis(self, **kw): def fit(self, sweep_values, measured_values): Double_Cos_Model = fit_mods.DoubleExpDampOscModel fourier_max_pos = a_tools.peak_finder_v2( - np.arange(1, len(sweep_values)/2, 1), - abs(np.fft.fft(measured_values))[1:len(measured_values)//2], + np.arange(1, len(sweep_values) / 2, 1), + abs(np.fft.fft(measured_values))[1:len(measured_values) // 2], window_len=1, perc=95) if len(fourier_max_pos) == 1: - freq_guess = 1./sweep_values[-1] * \ - (fourier_max_pos[0]+np.array([-1, 1])) + freq_guess = 1. / sweep_values[-1] * \ + (fourier_max_pos[0] + np.array([-1, 1])) else: - freq_guess = 1./sweep_values[-1]*fourier_max_pos + freq_guess = 1. / sweep_values[-1] * fourier_max_pos Double_Cos_Model.set_param_hint( - 'tau_1', value=.3*sweep_values[-1], vary=True) + 'tau_1', value=.3 * sweep_values[-1], vary=True) Double_Cos_Model.set_param_hint( - 'tau_2', value=.3*sweep_values[-1], vary=True) + 'tau_2', value=.3 * sweep_values[-1], vary=True) Double_Cos_Model.set_param_hint( 'freq_1', value=freq_guess[0], min=0) Double_Cos_Model.set_param_hint( 'freq_2', value=freq_guess[1], min=0) - Double_Cos_Model.set_param_hint('phase_1', value=1*np.pi/2.) - Double_Cos_Model.set_param_hint('phase_2', value=3*np.pi/2.) + Double_Cos_Model.set_param_hint('phase_1', value=1 * np.pi / 2.) + Double_Cos_Model.set_param_hint('phase_2', value=3 * np.pi / 2.) Double_Cos_Model.set_param_hint( 'amp_1', value=0.25, min=0.1, max=0.4, vary=True) Double_Cos_Model.set_param_hint( @@ -7757,9 +7784,9 @@ def save_fig(self, fig, figname='_DoubleFreq_', xlabel='x', ylabel='y', plot_formats = [plot_formats] for plot_format in plot_formats: if figname is None: - figname = (self.timestamp+figname+'.'+plot_format) + figname = (self.timestamp + figname + '.' + plot_format) else: - figname = (figname+'.' + plot_format) + figname = (figname + '.' + plot_format) self.savename = os.path.abspath(os.path.join( self.folder, figname)) if fig_tight: @@ -7787,7 +7814,7 @@ def __init__(self, auto=True, label='SWAPN', cost_func='sum', timestamp=None, st if timestamp is None: self.folder = a_tools.latest_data(label) splitted = self.folder.split('\\') - self.scan_start = splitted[-2]+'_'+splitted[-1][:6] + self.scan_start = splitted[-2] + '_' + splitted[-1][:6] self.scan_stop = self.scan_start else: self.scan_start = timestamp @@ -7816,37 +7843,37 @@ def analysis(self): if self.cost_func == 'sum': self.cost_val = np.sum( - np.power(y[:-4], np.divide(1, x[:-4])))/float(len(y[:-4])) + np.power(y[:-4], np.divide(1, x[:-4]))) / float(len(y[:-4])) elif self.cost_func == 'slope': - self.cost_val = abs(y[0]*(y[1]-y[0]))+abs(y[0]) + self.cost_val = abs(y[0] * (y[1] - y[0])) + abs(y[0]) elif self.cost_func == 'dumb-sum': - self.cost_val = (np.sum(y[:-4])/float(len(y[:-4])))-y[:-4].min() + self.cost_val = (np.sum(y[:-4]) / float(len(y[:-4]))) - y[:-4].min() elif self.cost_func == 'until-nonmono-sum': i = 0 y_fil = deepcopy(y) lastval = y_fil[0] keep_going = 1 - while(keep_going): + while (keep_going): if i > 5: - latestthreevals = (y_fil[i]+y_fil[i-1] + y_fil[i-2])/3 - threevalsbefore = (y_fil[i-3]+y_fil[i-4] + y_fil[i-5])/3 - if latestthreevals < (threevalsbefore-0.12) or i > len(y_fil)-4: + latestthreevals = (y_fil[i] + y_fil[i - 1] + y_fil[i - 2]) / 3 + threevalsbefore = (y_fil[i - 3] + y_fil[i - 4] + y_fil[i - 5]) / 3 + if latestthreevals < (threevalsbefore - 0.12) or i > len(y_fil) - 4: keep_going = 0 i += 1 - y_fil[i-1:-4] = threevalsbefore - self.cost_val = (np.sum(y_fil[:-4])/float(len(y_fil[:-4]))) + y_fil[i - 1:-4] = threevalsbefore + self.cost_val = (np.sum(y_fil[:-4]) / float(len(y_fil[:-4]))) self.single_swap_fid = y[0] fig = plt.figure() ax = fig.add_subplot(111) plot_x = x - plot_step = plot_x[1]-plot_x[0] + plot_step = plot_x[1] - plot_x[0] ax.set_xlabel(r'# Swap pulses') ax.set_ylabel(r'$F |1\rangle$') ax.set_title('%s: SWAPN sequence' % self.scan_start) - ax.set_xlim(plot_x.min()-plot_step/2., plot_x.max()+plot_step/2.) + ax.set_xlim(plot_x.min() - plot_step / 2., plot_x.max() + plot_step / 2.) ax.plot(plot_x, y, 'bo') @@ -7862,9 +7889,9 @@ def save_fig(self, fig, figname=None, xlabel='x', ylabel='y', plot_formats = [plot_formats] for plot_format in plot_formats: if figname is None: - figname = (self.scan_start+'_DoubleFreq_'+'.'+plot_format) + figname = (self.scan_start + '_DoubleFreq_' + '.' + plot_format) else: - figname = (figname+'.' + plot_format) + figname = (figname + '.' + plot_format) self.savename = os.path.abspath(os.path.join( self.folder, figname)) if fig_tight: @@ -7887,7 +7914,6 @@ def save_fig(self, fig, figname=None, xlabel='x', ylabel='y', class AvoidedCrossingAnalysis(MeasurementAnalysis): - """ Performs analysis to fit the avoided crossing """ @@ -7922,7 +7948,7 @@ def __init__(self, auto=True, filter_idx_high=filter_idx_high, filter_threshold=filter_threshold) filt_flux_low, filt_flux_high, filt_peaks_low, filt_peaks_high, \ - filter_func = filtered_dat + filter_func = filtered_dat self.f, self.ax = self.make_filtered_figure(filt_flux_low, filt_flux_high, filt_peaks_low, filt_peaks_high, filter_func, @@ -7972,13 +7998,13 @@ def filter_data(self, flux, peaks_low, peaks_high, a, x0=None, y0=None, 3. remove any data with indices specified by hand """ if a is None: - a = -1*(max(peaks_high)-min(peaks_low))/(max(flux)-min(flux)) + a = -1 * (max(peaks_high) - min(peaks_low)) / (max(flux) - min(flux)) if x0 is None: x0 = np.mean(flux) if y0 is None: y0 = np.mean(np.concatenate([peaks_low, peaks_high])) - filter_func = lambda x: a*(x-x0)+y0 + filter_func = lambda x: a * (x - x0) + y0 filter_mask_high = [True] * len(peaks_high) filter_mask_high = ~dm_tools.get_outliers(peaks_high, filter_threshold) @@ -8010,21 +8036,21 @@ def make_unfiltered_figure(self, peaks_low, peaks_high, transpose, cmap, if add_title: ax.set_title(self.timestamp_string + title) - pl_tools.flex_colormesh_plot_vs_xy(self.X[0]*1e-9, flux, self.Z[0], + pl_tools.flex_colormesh_plot_vs_xy(self.X[0] * 1e-9, flux, self.Z[0], ax=ax, transpose=transpose, cmap=cmap) - ax.plot(flux, peaks_high*1e-9, 'o', markeredgewidth=1., + ax.plot(flux, peaks_high * 1e-9, 'o', markeredgewidth=1., fillstyle='none', c='r') - ax.plot(flux, peaks_low*1e-9, 'o', markeredgewidth=1., + ax.plot(flux, peaks_low * 1e-9, 'o', markeredgewidth=1., fillstyle='none', c='orange') # self.ylabel because the axes are transposed xlabel = self.ylabel if xlabel is None else xlabel ax.set_xlabel(xlabel) ax.set_ylabel(ylabel) - ax.set_ylim(min(self.X[0]*1e-9), max(self.X[0]*1e-9)) + ax.set_ylim(min(self.X[0] * 1e-9), max(self.X[0] * 1e-9)) ax.set_xlim(min(flux), max(flux)) - f.savefig(os.path.join(self.folder, title+'.png'), format='png', + f.savefig(os.path.join(self.folder, title + '.png'), format='png', dpi=600) return f, ax @@ -8040,13 +8066,13 @@ def make_filtered_figure(self, if add_title: ax.set_title(self.timestamp_string + title) - pl_tools.flex_colormesh_plot_vs_xy(self.X[0]*1e-9, flux, self.Z[0], + pl_tools.flex_colormesh_plot_vs_xy(self.X[0] * 1e-9, flux, self.Z[0], ax=ax, transpose=transpose, cmap=cmap) - ax.plot(filt_flux_high, filt_peaks_high*1e-9, + ax.plot(filt_flux_high, filt_peaks_high * 1e-9, 'o', fillstyle='none', markeredgewidth=1., c='r', label='upper branch peaks') - ax.plot(filt_flux_low, filt_peaks_low*1e-9, + ax.plot(filt_flux_low, filt_peaks_low * 1e-9, 'o', fillstyle='none', markeredgewidth=1., c='orange', label='lower branch peaks') @@ -8054,11 +8080,11 @@ def make_filtered_figure(self, xlabel = self.ylabel if xlabel is None else xlabel ax.set_xlabel(xlabel) ax.set_ylabel(ylabel) - ax.set_ylim(min(self.X[0]*1e-9), max(self.X[0]*1e-9)) - ax.plot(flux, filter_func(flux)*1e-9, ls='--', c='w', + ax.set_ylim(min(self.X[0] * 1e-9), max(self.X[0] * 1e-9)) + ax.plot(flux, filter_func(flux) * 1e-9, ls='--', c='w', label='filter function') # ax.legend() # looks ugly, better after matplotlib update? - f.savefig(os.path.join(self.folder, title+'.png'), format='png', + f.savefig(os.path.join(self.folder, title + '.png'), format='png', dpi=600) return f, ax @@ -8074,13 +8100,13 @@ def make_fit_figure(self, if add_title: ax.set_title(self.timestamp_string + title) - pl_tools.flex_colormesh_plot_vs_xy(self.X[0]*1e-9, flux, self.Z[0], + pl_tools.flex_colormesh_plot_vs_xy(self.X[0] * 1e-9, flux, self.Z[0], ax=ax, transpose=transpose, cmap=cmap) - ax.plot(filt_flux_high, filt_peaks_high*1e-9, + ax.plot(filt_flux_high, filt_peaks_high * 1e-9, 'o', fillstyle='none', markeredgewidth=1., c='r', label='upper branch peaks') - ax.plot(filt_flux_low, filt_peaks_low*1e-9, + ax.plot(filt_flux_low, filt_peaks_low * 1e-9, 'o', fillstyle='none', markeredgewidth=1., c='orange', label='lower branch peaks') @@ -8088,22 +8114,22 @@ def make_fit_figure(self, xlabel = self.ylabel if xlabel is None else xlabel ax.set_xlabel(xlabel) ax.set_ylabel(ylabel) - ax.set_ylim(min(self.X[0]*1e-9), max(self.X[0]*1e-9)) + ax.set_ylim(min(self.X[0] * 1e-9), max(self.X[0] * 1e-9)) ax.set_xlim(min(flux), max(flux)) - ax.plot(flux, 1e-9*fit_mods.avoided_crossing_direct_coupling( + ax.plot(flux, 1e-9 * fit_mods.avoided_crossing_direct_coupling( flux, **fit_res.best_values, flux_state=False), 'r-', label='fit') - ax.plot(flux, 1e-9*fit_mods.avoided_crossing_direct_coupling( + ax.plot(flux, 1e-9 * fit_mods.avoided_crossing_direct_coupling( flux, **fit_res.best_values, flux_state=True), 'y-', label='fit') g_legend = r'{} = {:.2f}$\pm${:.2f} MHz'.format( coupling_label, - fit_res.params['g']*1e-6, fit_res.params['g'].stderr*1e-6) + fit_res.params['g'] * 1e-6, fit_res.params['g'].stderr * 1e-6) ax.text(.6, .8, g_legend, transform=ax.transAxes, color='white') # ax.legend() # looks ugly, better after matplotlib update? - f.savefig(os.path.join(self.folder, title+'.png'), format='png', + f.savefig(os.path.join(self.folder, title + '.png'), format='png', dpi=600) return f, ax @@ -8139,18 +8165,18 @@ def resized_fit_func(flux, f_center1, f_center2, c1, c2, g): if cross_flux_guess is None: cross_flux_guess = np.mean(total_flux) if f1_guess is None: - f1_guess = np.mean(total_freqs)-g_guess + f1_guess = np.mean(total_freqs) - g_guess c2_guess = 0. if f2_guess is None: # The factor *1000* is a magic number but seems to give a # reasonable guess that converges well. - c1_guess = -1*((max(total_freqs)-min(total_freqs)) / - (max(total_flux)-min(total_flux)))/1000 + c1_guess = -1 * ((max(total_freqs) - min(total_freqs)) / + (max(total_flux) - min(total_flux))) / 1000 - f2_guess = cross_flux_guess*(c1_guess-c2_guess)+f1_guess + f2_guess = cross_flux_guess * (c1_guess - c2_guess) + f1_guess else: - c1_guess = c2_guess + (f2_guess-f1_guess)/cross_flux_guess + c1_guess = c2_guess + (f2_guess - f1_guess) / cross_flux_guess av_crossing_model.set_param_hint( 'g', min=0., max=0.5e9, value=g_guess, vary=True) @@ -8234,7 +8260,7 @@ def run_special_analysis(self, make_fig=True): self.flux_amp is not None and self.V_per_phi0 is not None): self.step_response = fit_mods.Qubit_freq_to_dac( - frequency=self.f01max-self.df, + frequency=self.f01max - self.df, f_max=self.f01max, E_c=self.E_c, dac_sweet_spot=self.V_offset, @@ -8276,8 +8302,8 @@ def analyze_trace(self, I, Q, x_pts, # Filter phase and/or calculate the derivative if filter_deriv_phase: - df = self.gauss_deriv_filter(phases, filter_width, dt, pad_val=0)\ - / (2 * np.pi) + df = self.gauss_deriv_filter(phases, filter_width, dt, pad_val=0) \ + / (2 * np.pi) else: # Calculate central derivative df = np.gradient(phases, dt) / (2 * np.pi) @@ -8309,7 +8335,7 @@ def get_stepresponse(self, df, f01max, E_c, F_amp, V_per_phi0, Returns: s (array): Normalized step response in voltage space. ''' - s = (np.arccos((1 - df / (f01max + E_c))**2) * np.pi / V_per_phi0 + + s = (np.arccos((1 - df / (f01max + E_c)) ** 2) * np.pi / V_per_phi0 + V_offset) / F_amp return s @@ -8395,9 +8421,9 @@ def gauss_filter(self, data, sigma, d, nr_sigmas=4, pad_val=None): filterHalfWidth = np.ceil(nr_sigmas * sigma / d) tMaxFilter = filterHalfWidth * d # upper limit of range has + dt/10 to include endpoint - tFilter = np.arange(-tMaxFilter, tMaxFilter + d/10, step=d) + tFilter = np.arange(-tMaxFilter, tMaxFilter + d / 10, step=d) - gaussFilter = np.exp(-tFilter**2 / (2*sigma**2)) + gaussFilter = np.exp(-tFilter ** 2 / (2 * sigma ** 2)) gaussFilter /= np.sum(gaussFilter) if pad_val is None: @@ -8432,12 +8458,12 @@ def gauss_deriv_filter(self, data, sigma, d, nr_sigmas=4, pad_val=None): filterHalfWidth = np.ceil(nr_sigmas * sigma / d) tMaxFilter = filterHalfWidth * d # upper limit of range has + dt/10 to include endpoint - tFilter = np.arange(-tMaxFilter, tMaxFilter + d/10, step=d) + tFilter = np.arange(-tMaxFilter, tMaxFilter + d / 10, step=d) # First calculate normalized Gaussian, then derivative - gaussFilter = np.exp(-tFilter**2 / (2*sigma**2)) + gaussFilter = np.exp(-tFilter ** 2 / (2 * sigma ** 2)) gaussFilter /= np.sum(gaussFilter) - gaussDerivFilter = gaussFilter * (-tFilter) / (sigma**2) + gaussDerivFilter = gaussFilter * (-tFilter) / (sigma ** 2) if pad_val is None: pad_val = data[0] @@ -8464,9 +8490,9 @@ def run_dac_arc_analysis(self, make_fig=True): # Note: assumes symmetric qubit. if self.V_per_phi0 is None: self.V_per_phi0 = ( - np.pi * (self.sweep_points_2D[0] - self.V_offset) / - np.arccos(((self.f01max - df + self.E_c) / - (self.f01max + self.E_c))**2)) + np.pi * (self.sweep_points_2D[0] - self.V_offset) / + np.arccos(((self.f01max - df + self.E_c) / + (self.f01max + self.E_c)) ** 2)) # Set the demodulation frequencies based on the guess self.demod_freqs = [fit_mods.Qubit_dac_to_detun( @@ -8495,7 +8521,7 @@ def run_dac_arc_analysis(self, make_fig=True): for i in self.all_df]) self.fit_freqs, self.fit_amps = self.remove_outliers( - [len(self.sweep_points_2D)//2]) + [len(self.sweep_points_2D) // 2]) self.param_hints = { 'f_max': self.f01max, @@ -8575,7 +8601,7 @@ class GST_Analysis(TD_Analysis): pyGSTi. The actual analysis is then run using the tools from pyGSTi. ''' - def __init__(self, timestamp=None, nr_qubits: int=1, **kw): + def __init__(self, timestamp=None, nr_qubits: int = 1, **kw): ''' Args: nr_qubits (int): @@ -8629,7 +8655,7 @@ def run_default_analysis(self, **kw): else: raise NotImplementedError( 'GST analysis for {} qubits is not implemented.' - .format(self.nr_qubits)) + .format(self.nr_qubits)) # Write extracted counts to file. self.pygsti_fn = os.path.join(self.folder, 'pyGSTi_dataset.txt') @@ -8710,12 +8736,12 @@ def count_results_1Q(self): for soft_idx in range(self.soft_repetitions): # For all soft repetitions: sum up "1" counts. one_count += np.sum( - data[soft_idx, block_idx+seq_idx:block_idx+l:d], + data[soft_idx, block_idx + seq_idx:block_idx + l:d], dtype=int) zero_count = (self.hard_repetitions * self.soft_repetitions - one_count) - counts.append((self.exp_list[i+seq_idx].str, + counts.append((self.exp_list[i + seq_idx].str, zero_count, one_count)) # If the last file has a different number of experiments, count those @@ -8730,13 +8756,13 @@ def count_results_1Q(self): for soft_idx in range(self.soft_repetitions): one_count += np.sum( data[soft_idx, - block_idx+seq_idx:block_idx+l_last:d_last], + block_idx + seq_idx:block_idx + l_last:d_last], dtype=int) zero_count = (self.hard_repetitions * self.soft_repetitions - one_count) counts.append( - (self.exp_list[self.nr_hard_segs-1 + seq_idx].str, + (self.exp_list[self.nr_hard_segs - 1 + seq_idx].str, zero_count, one_count)) return counts, spam_label_order @@ -8780,8 +8806,8 @@ def count_results_2Q(self): for soft_idx in range(self.soft_repetitions): for x in range(0, l, d): - q0_bit = data_q0[soft_idx, block_idx+seq_idx+x] - q1_bit = data_q1[soft_idx, block_idx+seq_idx+x] + q0_bit = data_q0[soft_idx, block_idx + seq_idx + x] + q1_bit = data_q1[soft_idx, block_idx + seq_idx + x] if not q0_bit and not q1_bit: new_count[0] += 1 elif q0_bit and not q1_bit: @@ -8791,7 +8817,7 @@ def count_results_2Q(self): else: new_count[3] += 1 - counts.append((self.exp_list[i+seq_idx].str, *new_count)) + counts.append((self.exp_list[i + seq_idx].str, *new_count)) # If the last file has a different number of experiments, count those # separately @@ -8804,8 +8830,8 @@ def count_results_2Q(self): new_count = (0, 0, 0, 0) for soft_idx in range(self.soft_repetitions): for x in range(0, l_last, d_last): - q0_bit = data_q0[soft_idx, block_idx+seq_idx+x] - q1_bit = data_q1[soft_idx, block_idx+seq_idx+x] + q0_bit = data_q0[soft_idx, block_idx + seq_idx + x] + q1_bit = data_q1[soft_idx, block_idx + seq_idx + x] if not q0_bit and not q1_bit: new_count[0] += 1 elif q0_bit and not q1_bit: @@ -8816,7 +8842,7 @@ def count_results_2Q(self): new_count[3] += 1 counts.append( - (self.exp_list[self.nr_hard_segs-1 + seq_idx].str, + (self.exp_list[self.nr_hard_segs - 1 + seq_idx].str, *new_count)) return counts, spam_label_order @@ -8824,7 +8850,7 @@ def count_results_2Q(self): class CZ_1Q_phase_analysis(TD_Analysis): - def __init__(self, use_diff: bool=True, meas_vals_idx: int=0, **kw): + def __init__(self, use_diff: bool = True, meas_vals_idx: int = 0, **kw): self.use_diff = use_diff self.meas_vals_idx = meas_vals_idx super().__init__(rotate_and_normalize=False, cal_points=False, **kw) @@ -8897,152 +8923,12 @@ def make_figures(self, **kw): self.save_fig(fig, **kw) -def DAC_scan_analysis_and_plot(scan_start, scan_stop, dac, feed, dac_prefix='',perc=99.6, factor=1, smooth_window_len=31,smoothing=True, - overwrite_old=False, fig_format='png', verbose=False, peak_fitting_sample_n=0, plotsize=None, temperature_plots=True, current_multiplier=1): - plotsize = plotsize or (4,10) - date_folder = scan_stop.split('_')[0] - time_folder = scan_stop.split('_')[1] - out_path = a_tools.datadir+"/%s/%s_analysis_2D_Plots"%(date_folder,time_folder) - try: - os.mkdir(out_path) - except: - if not overwrite_old: - raise FileExistsError("Output folder exists. Either move old folder or pass option overwrite_old=True") - - pdict={'amp':'all_data', - 'frequencies':'sweep_points', - 'dac':'fluxcurrent.'+dac, - } - - opt_dict = {'scan_label':dac_prefix+dac, - 'exact_label_match':True} - - nparams = ['amp', - 'frequencies', - 'dac', - ] - - if temperature_plots: - nparams.append('T_mc') - nparams.append('T_cp') - pdict['T_mc'] = 'Fridge monitor.T_MClo' - pdict['T_cp'] = 'Fridge monitor.T_CP' - - - #retrieve data - spec_scans = ca.quick_analysis(t_start=scan_start, t_stop=scan_stop, options_dict=opt_dict, - params_dict_TD=pdict, numeric_params=nparams) - #sort data - dac_values_unsorted = spec_scans.TD_dict['dac'] - sorted_indices = dac_values_unsorted.argsort() - dac_values=np.array(dac_values_unsorted[sorted_indices], dtype=float)*current_multiplier - amplitude_values=np.array(spec_scans.TD_dict['amp'][sorted_indices,feed], dtype=float) - frequency_values=np.array(spec_scans.TD_dict['frequencies'][sorted_indices], dtype=float) - - if temperature_plots: - T_mc=np.array(spec_scans.TD_dict['T_mc'][sorted_indices], dtype=float) - T_cp=np.array(spec_scans.TD_dict['T_cp'][sorted_indices], dtype=float) - #Plot the smoothed and fitted data - p = dac_values>=0 - n = dac_values<=0 - scale = floor(2*max(T_cp)/max(T_mc))/2 - plt.title('Temperatures, feedline %d, %s %s'%(feed,dac_prefix, dac)) - if n is not None and len(n) > 0: - plt.plot(-dac_values[n]*1e3, T_mc[n]*1e3, label='Mixing Chamber (negative current)') - plt.plot(-dac_values[n]*1e3, T_cp[n]*1e3/10, label='Cold Plate/%d (negative)'%scale) - if p is not None and len(p) > 0: - plt.plot(dac_values[p]*1e3, T_mc[p]*1e3, label='Mixing Chamber (positive)') - plt.plot(dac_values[p]*1e3, T_cp[p]*1e3/10, label='Cold Plate/10 (positive)') - plt.xlabel(r'Flux bias current, I (mA)') - plt.ylabel('Temperature (mK)') - plt.legend() - plt.ylim(0,40) - plt.savefig(out_path+"/temperatures-feed_%d_%s%s.%s"%(feed,dac_prefix,dac,fig_format)) - if verbose: - plt.show() - plt.close() +def DAC_scan_analysis_and_plot(**kwargs): + raise DeprecationWarning('Use FluxFrequency from analysis_v2.dac_scan_analysis instead.') - smoothed_amplitude_values = np.zeros_like(amplitude_values) - peak_frequencies = np.zeros_like(amplitude_values[:,0], dtype=object) - peak_amplitudes = np.zeros_like(amplitude_values[:,0], dtype=object) - Qis = np.zeros_like(amplitude_values[:,0], dtype=float) - - #Smooth data and find peeks - for i, dac_value in enumerate(dac_values): - # try: - # a = Homodyne_Analysis(label='-D4_dac_channel_%s_%.3f'%(dac, dac_value), close_fig=True, show=False) - # Qis[i] = a.fit_results.params['Qi'] - # except: - # pass - peaks_x, peaks_z,smoothed_z=a_tools.peak_finder_v3(frequency_values[i], amplitude_values[i], smoothing=smoothing, perc=perc, window_len=smooth_window_len,factor=factor) - #save peaks and smoothed data - smoothed_amplitude_values[i,:] = smoothed_z - peak_frequencies[i] = peaks_x - peak_amplitudes[i] = peaks_z - - # plt.title('Qi, feedline %d, %s %s'%(feed,dac_prefix, dac)) - # plt.plot(dac_values*1e3, Qis) - # plt.xlabel(r'Flux bias current, I (mA)') - # plt.ylabel('Quality Factor (-)') - # plt.savefig(out_path+"/Qis-feed_%d_%s%s.%s"%(feed,dac_prefix,dac,fig_format)) - # if verbose: - # plt.show() - # plt.close() - - #Plot parameters - spec_scans.plot_dicts['arches'] = {'plotfn': spec_scans.plot_colorx, - 'xvals': dac_values*1e3, - 'yvals': frequency_values*1e-9, - 'zvals': smoothed_amplitude_values.transpose(), - 'title': 'transmission, feedline {} '.format(feed)+dac_prefix+dac+'_'+scan_stop, - 'xlabel': r'Flux bias current, I (mA)', - 'ylabel': r'Frequency (GHz)', - 'zlabel': 'Homodyne amplitude (mV)', - 'zrange': [smoothed_amplitude_values.min(), smoothed_amplitude_values.max()], - 'plotsize': (8,8), - 'cmap':'YlGn_r', - } - - #Plot the smoothed and fitted data - plt.title('Peak finder sample, feedline %d, %s %s'%(feed, dac_prefix, dac)) - plt.plot(frequency_values[peak_fitting_sample_n]*1e-9, amplitude_values[peak_fitting_sample_n], label='Raw Data') - plt.plot(frequency_values[peak_fitting_sample_n]*1e-9, smoothed_amplitude_values[peak_fitting_sample_n], label='Smoothed Data') - for i,peak in enumerate(peak_frequencies[peak_fitting_sample_n]): - if verbose: - print("%.6f GHz" % (peak*1e-9)) - plt.scatter(peak*1e-9,peak_amplitudes[peak_fitting_sample_n][i]) - plt.xlabel('Frequency (GHz)') - plt.ylabel('Homodyne amplitude (mV)') - plt.legend() - plt.savefig(out_path+"/peaks-feed_%d_%s%s.%s"%(feed,dac_prefix,dac,fig_format)) - if verbose: - plt.show() - plt.close() +def time_domain_DAC_scan_analysis_and_plot(**kwargs): + raise DeprecationWarning('Use FluxFrequency from analysis_v2.dac_scan_analysis instead.') - fig = plt.figure(figsize=plotsize) - ax = fig.add_subplot(111) - spec_scans.axs['arches'] = ax - spec_scans.plot() - peaks_container=[] - - txt_file = out_path+'/peaks-feed_%d_%s%s.txt'%(feed,dac_prefix, dac) - f=open(txt_file, 'w+') - - for i, dac_value in enumerate(dac_values): - line = ','.join(str(x) for x in peak_frequencies[i]) - f.write('['+line + ']\n') - #print(dac_value,line) - for peak in peak_frequencies[i]: - ax.scatter(dac_value*1e3, peak*1e-9, color='b', s=9) - f.close() - - ax.xaxis.label.set_fontsize(10) - ax.yaxis.label.set_fontsize(10) - ax.title.set_fontsize(10) - if verbose: - plt.show() - fig.savefig(out_path+"/2D_plot-feed_%d_%s%s.%s"%(feed,dac_prefix,dac,fig_format)) - plt.close() def Input_average_analysis(IF, fig_format='png', alpha=1, phi=0, I_o=0, Q_o=0, predistort=True, plot=True, timestamp_ground=None, @@ -9057,81 +8943,82 @@ def Input_average_analysis(IF, fig_format='png', alpha=1, phi=0, I_o=0, Q_o=0, # MHz modulation offset_calibration_samples = 720 - x = data_file.sweep_points/1.8 + x = data_file.sweep_points / 1.8 offset_I = np.mean(data_file.measured_values[ - 0][-offset_calibration_samples:]) + 0][-offset_calibration_samples:]) offset_Q = np.mean(data_file.measured_values[ - 1][-offset_calibration_samples:]) + 1][-offset_calibration_samples:]) print('offset I {}, offset Q {}'.format(offset_I, offset_Q)) - y1 = data_file.measured_values[0]-offset_I - y2 = data_file.measured_values[1]-offset_Q + y1 = data_file.measured_values[0] - offset_I + y2 = data_file.measured_values[1] - offset_Q I0, Q0 = SSB_demod(y1, y2, alpha=alpha, phi=phi, I_o=I_o, Q_o=Q_o, IF=IF, predistort=predistort) - power0 = (I0**2+Q0**2)/50 + power0 = (I0 ** 2 + Q0 ** 2) / 50 data_file = MeasurementAnalysis( label='_1', auto=True, TwoD=False, close_fig=True, plot=True, timestamp=timestamp_excited) temp = data_file.load_hdf5data() data_file.get_naming_and_values() - x = data_file.sweep_points/1.8 + x = data_file.sweep_points / 1.8 offset_I = np.mean(data_file.measured_values[ - 0][-offset_calibration_samples:]) + 0][-offset_calibration_samples:]) offset_Q = np.mean(data_file.measured_values[ - 1][-offset_calibration_samples:]) - y1 = data_file.measured_values[0]-offset_I - y2 = data_file.measured_values[1]-offset_Q - I1, Q1 = SSB_demod(y1, y2, alpha=alpha, phi=phi, I_o=I_o, - Q_o=Q_o, IF=IF, predistort=predistort) - power1 = (I1**2+Q1**2)/50 - - amps = np.sqrt((I1-I0)**2+(Q1-Q0)**2) + 1][-offset_calibration_samples:]) + y1 = data_file.measured_values[0] - offset_I + y2 = data_file.measured_values[1] - offset_Q + I1, Q1 = SSB_demod(y1, y2, alpha=alpha, phi=phi, I_o=I_o, + Q_o=Q_o, IF=IF, predistort=predistort) + power1 = (I1 ** 2 + Q1 ** 2) / 50 + + amps = np.sqrt((I1 - I0) ** 2 + (Q1 - Q0) ** 2) amp_max = np.max(amps) # defining weight functions for postrotation - weight_I = (I1-I0)/amp_max - weight_Q = (Q1-Q0)/amp_max + weight_I = (I1 - I0) / amp_max + weight_Q = (Q1 - Q0) / amp_max if post_rotation_angle == None: arg_max = np.argmax(amps) post_rotation_angle = np.arctan2( - weight_I[arg_max], weight_Q[arg_max])-np.pi/2 - #print('found post_rotation angle {}'.format(post_rotation_angle)) + weight_I[arg_max], weight_Q[arg_max]) - np.pi / 2 + # print('found post_rotation angle {}'.format(post_rotation_angle)) else: - post_rotation_angle = 2*np.pi*post_rotation_angle/360 - I0rot = np.cos(post_rotation_angle)*I0 - np.sin(post_rotation_angle)*Q0 - Q0rot = np.sin(post_rotation_angle)*I0 + np.cos(post_rotation_angle)*Q0 - I1rot = np.cos(post_rotation_angle)*I1 - np.sin(post_rotation_angle)*Q1 - Q1rot = np.sin(post_rotation_angle)*I1 + np.cos(post_rotation_angle)*Q1 + post_rotation_angle = 2 * np.pi * post_rotation_angle / 360 + I0rot = np.cos(post_rotation_angle) * I0 - np.sin(post_rotation_angle) * Q0 + Q0rot = np.sin(post_rotation_angle) * I0 + np.cos(post_rotation_angle) * Q0 + I1rot = np.cos(post_rotation_angle) * I1 - np.sin(post_rotation_angle) * Q1 + Q1rot = np.sin(post_rotation_angle) * I1 + np.cos(post_rotation_angle) * Q1 I0 = I0rot Q0 = Q0rot I1 = I1rot Q1 = Q1rot # redefining weight functions after rotation - weight_I = (I1-I0)/amp_max - weight_Q = (Q1-Q0)/amp_max + weight_I = (I1 - I0) / amp_max + weight_Q = (Q1 - Q0) / amp_max - edge = 1.05*max(max(np.sqrt(I0**2+Q0**2)), max(np.sqrt(I1**2+Q1**2))) + edge = 1.05 * max(max(np.sqrt(I0 ** 2 + Q0 ** 2)), max(np.sqrt(I1 ** 2 + Q1 ** 2))) def rms(x): - return np.sqrt(x.dot(x)/x.size) + return np.sqrt(x.dot(x) / x.size) if optimization_window != None: optimization_start = optimization_window[0] optimization_stop = optimization_window[-1] - start_sample = int(optimization_start*1.8e9) - stop_sample = int(optimization_stop*1.8e9) + start_sample = int(optimization_start * 1.8e9) + stop_sample = int(optimization_stop * 1.8e9) shift_w = 0e-9 - start_sample_w = int((optimization_start-shift_w)*1.8e9) - stop_sample_w = int((optimization_stop-shift_w)*1.8e9) + start_sample_w = int((optimization_start - shift_w) * 1.8e9) + stop_sample_w = int((optimization_stop - shift_w) * 1.8e9) depletion_cost_d = np.mean(rms(I0[start_sample:stop_sample]) + rms(Q0[start_sample:stop_sample]) + rms(I1[start_sample:stop_sample]) + rms(Q1[start_sample:stop_sample])) - depletion_cost_w = 10*np.mean(rms(I0[start_sample_w:stop_sample_w]-I1[start_sample_w:stop_sample_w]) + - rms(Q0[start_sample_w:stop_sample_w]-Q1[start_sample_w:stop_sample_w])) # +abs(np.mean(Q0[start_sample:stop_sample]))+abs(np.mean(I1[start_sample:stop_sample]))+abs(np.mean(Q1[start_sample:stop_sample])) - depletion_cost = depletion_cost_d+depletion_cost_w - #print('total {} direct {} weights {}'.format(1000*depletion_cost, 1000*depletion_cost_d, 1000*depletion_cost_w)) + depletion_cost_w = 10 * np.mean(rms(I0[start_sample_w:stop_sample_w] - I1[start_sample_w:stop_sample_w]) + + rms(Q0[start_sample_w:stop_sample_w] - Q1[ + start_sample_w:stop_sample_w])) # +abs(np.mean(Q0[start_sample:stop_sample]))+abs(np.mean(I1[start_sample:stop_sample]))+abs(np.mean(Q1[start_sample:stop_sample])) + depletion_cost = depletion_cost_d + depletion_cost_w + # print('total {} direct {} weights {}'.format(1000*depletion_cost, 1000*depletion_cost_d, 1000*depletion_cost_w)) else: depletion_cost = 0 @@ -9146,14 +9033,14 @@ def rms(x): plt.ylabel('Demodulated voltage (V)') if optimization_window != None: - plt.axvline(optimization_start*1e9, linestyle='--', + plt.axvline(optimization_start * 1e9, linestyle='--', color='k', label='depletion optimization window') - plt.axvline(optimization_stop*1e9, linestyle='--', color='k') + plt.axvline(optimization_stop * 1e9, linestyle='--', color='k') ax.set_xlim(0, 1500) plt.legend() - plt.savefig(data_file.folder+'\\' + - 'transients_I_demodulated.'+fig_format, format=fig_format) + plt.savefig(data_file.folder + '\\' + + 'transients_I_demodulated.' + fig_format, format=fig_format) plt.close() fig, ax = plt.subplots() @@ -9164,28 +9051,28 @@ def rms(x): plt.xlabel('time (ns)') plt.ylabel('Demodulated Q') if optimization_window != None: - plt.axvline(optimization_start*1e9, linestyle='--', + plt.axvline(optimization_start * 1e9, linestyle='--', color='k', label='depletion optimization window') - plt.axvline(optimization_stop*1e9, linestyle='--', color='k') + plt.axvline(optimization_stop * 1e9, linestyle='--', color='k') ax.set_xlim(0, 1500) plt.legend() - plt.savefig(data_file.folder+'\\' + - 'transients_Q_demodulated.'+fig_format, format=fig_format) + plt.savefig(data_file.folder + '\\' + + 'transients_Q_demodulated.' + fig_format, format=fig_format) plt.close() fig, ax = plt.subplots() - plt.plot(x, power0*1e6, label='ground', lw=4) - plt.plot(x, power1*1e6, label='excited', lw=4) + plt.plot(x, power0 * 1e6, label='ground', lw=4) + plt.plot(x, power1 * 1e6, label='excited', lw=4) if optimization_window != None: - plt.axvline(optimization_start*1e9, linestyle='--', + plt.axvline(optimization_start * 1e9, linestyle='--', color='k', label='depletion optimization window') - plt.axvline(optimization_stop*1e9, linestyle='--', color='k') + plt.axvline(optimization_stop * 1e9, linestyle='--', color='k') ax.set_xlim(0, 1500) plt.title('Signal power (uW)') plt.ylabel('Signal power (uW)') - plt.savefig(data_file.folder+'\\'+'transients_power.' + + plt.savefig(data_file.folder + '\\' + 'transients_power.' + fig_format, format=fig_format) plt.close() @@ -9196,54 +9083,54 @@ def rms(x): A1I = I1 A1Q = Q1 Fs = 1.8e9 - f_axis, PSD0I = func.PSD(A0I, 1/Fs) - f_axis, PSD1I = func.PSD(A1I, 1/Fs) - f_axis, PSD0Q = func.PSD(A0Q, 1/Fs) - f_axis, PSD1Q = func.PSD(A1Q, 1/Fs) + f_axis, PSD0I = func.PSD(A0I, 1 / Fs) + f_axis, PSD1I = func.PSD(A1I, 1 / Fs) + f_axis, PSD0Q = func.PSD(A0Q, 1 / Fs) + f_axis, PSD1Q = func.PSD(A1Q, 1 / Fs) - f_axis_o, PSD0I_o = func.PSD(A0I[-1024:], 1/Fs) - f_axis_o, PSD1I_o = func.PSD(A1I[-1024:], 1/Fs) - f_axis_o, PSD0Q_o = func.PSD(A0Q[-1024:], 1/Fs) - f_axis_o, PSD1Q_o = func.PSD(A1Q[-1024:], 1/Fs) + f_axis_o, PSD0I_o = func.PSD(A0I[-1024:], 1 / Fs) + f_axis_o, PSD1I_o = func.PSD(A1I[-1024:], 1 / Fs) + f_axis_o, PSD0Q_o = func.PSD(A0Q[-1024:], 1 / Fs) + f_axis_o, PSD1Q_o = func.PSD(A1Q[-1024:], 1 / Fs) - n_spurious = int(round(2*len(A0I)*abs(IF)/Fs)) + n_spurious = int(round(2 * len(A0I) * abs(IF) / Fs)) f_spurious = f_axis[n_spurious] - n_offset = int(round(len(A0I[-1024:])*abs(IF)/Fs)) + n_offset = int(round(len(A0I[-1024:]) * abs(IF) / Fs)) f_offset = f_axis_o[n_offset] - #print('f_spurious', f_spurious) - #print('f_offset', f_offset) - #print(len(A0I), len(A0I[-1024:])) + # print('f_spurious', f_spurious) + # print('f_offset', f_offset) + # print(len(A0I), len(A0I[-1024:])) samples = 7 cost_skew = 0 cost_offset = 0 for i in range(samples): - n_s = int(n_spurious-samples/2+i) - n_o = int(n_offset-samples/2+i) + n_s = int(n_spurious - samples / 2 + i) + n_o = int(n_offset - samples / 2 + i) cost_skew = cost_skew + \ - np.abs(PSD0I[n_s])+np.abs(PSD1I[n_s]) + \ - np.abs(PSD0Q[n_s])+np.abs(PSD1Q[n_s]) + np.abs(PSD0I[n_s]) + np.abs(PSD1I[n_s]) + \ + np.abs(PSD0Q[n_s]) + np.abs(PSD1Q[n_s]) cost_offset = cost_offset + \ - np.abs(PSD0I_o[n_o])+np.abs(PSD1I_o[n_o]) + \ - np.abs(PSD0Q_o[n_o])+np.abs(PSD1Q_o[n_o]) + np.abs(PSD0I_o[n_o]) + np.abs(PSD1I_o[n_o]) + \ + np.abs(PSD0Q_o[n_o]) + np.abs(PSD1Q_o[n_o]) -# print('freq',f_axis[n]) -# print('cost_skew', cost_skew) + # print('freq',f_axis[n]) + # print('cost_skew', cost_skew) if plot: fig, ax = plt.subplots(2) ax[0].set_xlim(0, 0.4) # plotting the spectrum - ax[0].plot(f_axis*1e-9, abs(PSD0I), label='ground I') + ax[0].plot(f_axis * 1e-9, abs(PSD0I), label='ground I') # plotting the spectrum - ax[0].plot(f_axis*1e-9, abs(PSD1I), label='excited I') + ax[0].plot(f_axis * 1e-9, abs(PSD1I), label='excited I') ax[1].set_xlim(0, 0.4) # plotting the spectrum - ax[1].plot(f_axis*1e-9, abs(PSD0Q), label='ground Q') + ax[1].plot(f_axis * 1e-9, abs(PSD0Q), label='ground Q') # plotting the spectrum - ax[1].plot(f_axis*1e-9, abs(PSD1Q), label='excited Q') + ax[1].plot(f_axis * 1e-9, abs(PSD1Q), label='excited Q') ax[1].set_xlabel('Freq (GHz)') ax[0].set_ylabel('|PSD|') ax[0].set_yscale('log') @@ -9253,20 +9140,20 @@ def rms(x): ax[1].legend() ax[0].set_title('PSD') - plt.savefig(data_file.folder+'\\'+'PSD.'+fig_format, format=fig_format) + plt.savefig(data_file.folder + '\\' + 'PSD.' + fig_format, format=fig_format) plt.close() fig, ax = plt.subplots(2) ax[0].set_xlim(0, 0.4) # plotting the spectrum - ax[0].plot(f_axis_o*1e-9, abs(PSD0I_o), label='ground I') + ax[0].plot(f_axis_o * 1e-9, abs(PSD0I_o), label='ground I') # plotting the spectrum - ax[0].plot(f_axis_o*1e-9, abs(PSD1I_o), label='excited I') + ax[0].plot(f_axis_o * 1e-9, abs(PSD1I_o), label='excited I') ax[1].set_xlim(0, 0.4) # plotting the spectrum - ax[1].plot(f_axis_o*1e-9, abs(PSD0Q_o), label='ground Q') + ax[1].plot(f_axis_o * 1e-9, abs(PSD0Q_o), label='ground Q') # plotting the spectrum - ax[1].plot(f_axis_o*1e-9, abs(PSD1Q_o), label='excited Q') + ax[1].plot(f_axis_o * 1e-9, abs(PSD1Q_o), label='excited Q') ax[1].set_xlabel('Freq (GHz)') ax[0].set_ylabel('|PSD|') ax[0].set_yscale('log') @@ -9276,7 +9163,7 @@ def rms(x): ax[1].legend() ax[0].set_title('PSD last quarter') - plt.savefig(data_file.folder+'\\'+'PSD_last_quarter.' + + plt.savefig(data_file.folder + '\\' + 'PSD_last_quarter.' + fig_format, format=fig_format) plt.close() @@ -9287,10 +9174,10 @@ def rms(x): ax.set_xlim(-edge, edge) plt.legend(frameon=False) plt.title('IQ trajectory alpha{} phi{}_'.format( - alpha, phi)+data_file.timestamp_string) + alpha, phi) + data_file.timestamp_string) plt.xlabel('I (V)') plt.ylabel('Q (V)') - plt.savefig(data_file.folder+'\\'+'IQ_trajectory.' + + plt.savefig(data_file.folder + '\\' + 'IQ_trajectory.' + fig_format, format=fig_format) plt.close() @@ -9302,25 +9189,25 @@ def rms(x): plt.title('IQ trajectory weights') plt.xlabel('weight I') plt.ylabel('weight Q') - plt.savefig(data_file.folder+'\\'+'IQ_trajectory_weights') + plt.savefig(data_file.folder + '\\' + 'IQ_trajectory_weights') plt.close() - time = np.linspace(0, len(weight_I)/1.8, len(weight_I)) + time = np.linspace(0, len(weight_I) / 1.8, len(weight_I)) fig, ax = plt.subplots() plt.plot(time, weight_I, label='weight I') plt.plot(time, weight_Q, label='weight Q') if optimization_window != None: - plt.axvline((optimization_start-shift_w)*1e9, linestyle='--', + plt.axvline((optimization_start - shift_w) * 1e9, linestyle='--', color='k', label='depletion optimization window') - plt.axvline((optimization_stop-shift_w)*1e9, linestyle='--', color='k') + plt.axvline((optimization_stop - shift_w) * 1e9, linestyle='--', color='k') plt.legend() plt.xlabel('time (ns)') plt.ylabel('Integration weight (V)') - plt.title('weight functions_'+data_file.timestamp_string) + plt.title('weight functions_' + data_file.timestamp_string) plt.axhline(0, linestyle='--') - edge = 1.05*max(max(abs(weight_I)), max(abs(weight_Q))) + edge = 1.05 * max(max(abs(weight_I)), max(abs(weight_Q))) - plt.savefig(data_file.folder+'\\'+'weight_functions.' + + plt.savefig(data_file.folder + '\\' + 'weight_functions.' + fig_format, format=fig_format) plt.close() @@ -9330,6 +9217,7 @@ def rms(x): 'depletion_cost': depletion_cost, 'x': x, 'y1': y1, 'y2': y2, 'I0': I0, 'Q0': Q0, 'I1': I1, 'Q1': Q1} + # analysis functions @@ -9338,17 +9226,17 @@ def SSB_demod(Ivals, Qvals, alpha=1, phi=0, I_o=0, Q_o=0, IF=10e6, predistort=Tr # ((1, np.tan(phi*2*np.pi/360)), # (0, 1/alpha * 1/np.cos(phi*2*np.pi/360)))) predistortion_matrix = np.array( - ((1, -alpha*np.sin(phi*2*np.pi/360)), - (0, alpha*np.cos(phi*2*np.pi/360)))) + ((1, -alpha * np.sin(phi * 2 * np.pi / 360)), + (0, alpha * np.cos(phi * 2 * np.pi / 360)))) trace_length = len(Ivals) - tbase = np.arange(0, trace_length/1.8e9, 1/1.8e9) + tbase = np.arange(0, trace_length / 1.8e9, 1 / 1.8e9) if predistort: - Ivals = Ivals-I_o - Qvals = Qvals-Q_o + Ivals = Ivals - I_o + Qvals = Qvals - Q_o [Ivals, Qvals] = np.dot(predistortion_matrix, [Ivals, Qvals]) - cosI = np.array(np.cos(2*np.pi*IF*tbase)) - sinI = np.array(np.sin(2*np.pi*IF*tbase)) - I = np.multiply(Ivals, cosI)-np.multiply(Qvals, sinI) - Q = np.multiply(Ivals, sinI)+np.multiply(Qvals, cosI) + cosI = np.array(np.cos(2 * np.pi * IF * tbase)) + sinI = np.array(np.sin(2 * np.pi * IF * tbase)) + I = np.multiply(Ivals, cosI) - np.multiply(Qvals, sinI) + Q = np.multiply(Ivals, sinI) + np.multiply(Qvals, cosI) return I, Q diff --git a/pycqed/analysis/tools/cryoscope_tools.py b/pycqed/analysis/tools/cryoscope_tools.py index 043235825c..03a6104209 100644 --- a/pycqed/analysis/tools/cryoscope_tools.py +++ b/pycqed/analysis/tools/cryoscope_tools.py @@ -4,11 +4,12 @@ Dec 2017 Edited by Adriaan Rol """ - +from typing import Union import numpy as np import matplotlib.pyplot as plt import matplotlib.ticker -from pycqed.analysis.tools.plotting import (set_xlabel, set_ylabel) +from pycqed.analysis.tools.plotting import (set_xlabel, set_ylabel, + flex_colormesh_plot_vs_xy) import scipy.signal as ss import scipy.optimize as so @@ -49,9 +50,10 @@ def normalize_sincos( def fft_based_freq_guess_complex(y): """ - guess the shape of a sinusoidal complex signal y (in multiples of sampling rate), - by selecting the peak in the fft. - return guess (f, ph, off, amp) for the model y = amp*exp(2pi i f t + ph) + off. + guess the shape of a sinusoidal complex signal y (in multiples of + sampling rate), by selecting the peak in the fft. + return guess (f, ph, off, amp) for the model + y = amp*exp(2pi i f t + ph) + off. """ fft = np.fft.fft(y)[1:len(y)] freq_guess_idx = np.argmax(np.abs(fft)) @@ -81,17 +83,20 @@ def __init__( analyse a cryoscope measurement. time: array of times (lengths of Z pulse) - complex_data: measured data, combine x- and y- results in a complex number + complex_data: measured data, combine x- and y- results in a + complex number norm_window_size: window size used for normalizing sine and cosine demod_freq: frequency for demodulation. Is guessed if None. - derivative_window_length, derivative_order: parameters of the sovgol filter used for extracting frequency. + derivative_window_length, derivative_order: parameters of the sovgol + filter used for extracting frequency. Needs some playing around sometimes. - demod_smooth: when the demodulated signal should be smoothed before taking derivative, set this to - a tuple (window_length, order), again parametrizing a sovgol filter. + demod_smooth: when the demodulated signal should be smoothed before + taking derivative, set this to a tuple (window_length, order), + again parametrizing a sovgol filter. """ self.time = time @@ -113,7 +118,8 @@ def __init__( if self.demod_freq is None: self.demod_freq = - \ - fft_based_freq_guess_complex(self.norm_data)[0] * self.sampling_rate + fft_based_freq_guess_complex(self.norm_data)[ + 0] * self.sampling_rate self.demod_data = np.exp( 2 * np.pi * 1j * self.time * self.demod_freq) * self.norm_data @@ -131,8 +137,9 @@ def __init__( # extract frequency by a lowpass-derivative filter. - # use a savitzky golay filter: it take sliding window of length `window_length`, - # fits a polynomial, returns derivative at middle point + # use a savitzky golay filter: it take sliding window of length + # `window_length`, fits a polynomial, returns derivative at + # middle point self.detuning = ss.savgol_filter( self.phase / ( 2 * np.pi), @@ -141,7 +148,6 @@ def __init__( deriv=1) * self.sampling_rate self.real_detuning = self.get_real_detuning(self.nyquist_order) - def get_real_detuning(self, nyquist_order=None): if nyquist_order is None: nyquist_order = self.nyquist_order @@ -161,38 +167,44 @@ def get_amplitudes(self): else: raise NotImplementedError('Add a "freq_to_amp" method.') + def plot_short_time_fft(self, ax=None, + title='Short time Fourier Transform', + window_size=100, **kw): - def plot_short_time_fft(self, window_size=100): + if ax is None: + ax = plt.gca() + ax.set_title(title) - f, t, Zxx = ss.stft(self.norm_data, fs=self.sampling_rate, nperseg=window_size, + f, t, Zxx = ss.stft(self.norm_data, fs=self.sampling_rate, + nperseg=window_size, noverlap=0.95 * window_size, return_onesided=False) m = np.argsort(f) - - ax = plt.gca() - ax.pcolormesh(self.time[0] + t, f[m], np.abs(Zxx)[m, :]) - ax.set_title('Short time Fourier Transform') ax.set_ylabel('Frequency') ax.set_xlabel('Time') + formatter = matplotlib.ticker.EngFormatter(unit='s') ax.xaxis.set_major_formatter(formatter) formatter = matplotlib.ticker.EngFormatter(unit='Hz') ax.yaxis.set_major_formatter(formatter) - def plot_raw_data(self, style=".-"): - ax = plt.gca() - ax.set_title("Raw cryoscope data") + def plot_raw_data(self, ax=None, title="Raw cryoscope data", + style=".-", **kw): + if ax is None: + ax = plt.gca() + ax.set_title(title) ax.plot(self.time, self.data.real, style, label="Re", color="C0") ax.plot(self.time, self.data.imag, style, label="Im", color="C1") ax.legend() - ax.set_xlabel("Time") - ax.set_ylabel("Amplitude") - formatter = matplotlib.ticker.EngFormatter(unit='s') - ax.xaxis.set_major_formatter(formatter) + set_xlabel(ax, 'Time', 's') + set_ylabel(ax, "Amplitude", 'a.u.') + + def plot_normalized_data(self, ax=None, title='Normalized cryoscope data', + style=".-", **kw): + if ax is None: + ax = plt.gca() + ax.set_title(title) - def plot_normalized_data(self, style=".-"): - ax = plt.gca() - ax.set_title("Normalized cryoscope data") ax.plot( self.time, self.norm_data.real, @@ -206,9 +218,12 @@ def plot_normalized_data(self, style=".-"): formatter = matplotlib.ticker.EngFormatter(unit='s') ax.xaxis.set_major_formatter(formatter) - def plot_demodulated_data(self, style=".-"): - ax = plt.gca() - ax.set_title("Demodulated cryoscope data") + def plot_demodulated_data(self, ax=None, + title='Demodulated cryoscope data', + style=".-", **kw): + if ax is None: + ax = plt.gca() + ax.set_title(title) ax.plot( self.time, self.demod_data.real, @@ -227,52 +242,64 @@ def plot_demodulated_data(self, style=".-"): formatter = matplotlib.ticker.EngFormatter(unit='s') ax.xaxis.set_major_formatter(formatter) - def plot_normalized_data_circle(self): - plt.title("Normalized cryoscope data") - plt.xlabel("Re") - plt.ylabel("Im") - plt.plot(self.norm_data.real, self.norm_data.imag, ".") + def plot_normalized_data_circle(self, ax=None, + title='Normalized cryoscope data', **kw): + if ax is None: + ax = plt.gca() + ax.set_title(title) + ax.set_xlabel("Re") + ax.set_ylabel("Im") + ax.plot(self.norm_data.real, self.norm_data.imag, ".") - def plot_phase(self, wrap=False): - ax = plt.gca() - plt.title("Cryoscope demodulated phase") + def plot_phase(self, ax=None, title="Cryoscope demodulated phase", + wrap=False, **kw): + if ax is None: + ax = plt.gca() + ax.set_title(title) if wrap: - plt.plot(self.time, self.phase % (2 * np.pi), ".", color="C0") + ax.plot(self.time, self.phase % (2 * np.pi), ".", color="C0") else: - plt.plot(self.time, self.phase, ".", label="Im", color="C0") + ax.plot(self.time, self.phase, ".", label="Im", color="C0") set_xlabel(ax, 'Time', 's') set_ylabel(ax, 'Phase', 'deg') - - def plot_detuning(self): - ax = plt.gca() - plt.title("Detuning from demodulation frequency") - plt.plot(self.time, self.detuning, ".-", color="C0") + def plot_detuning(self, ax=None, + title="Detuning from demodulation frequency", **kw): + if ax is None: + ax = plt.gca() + ax.set_title(title) + ax.plot(self.time, self.detuning, ".-", color="C0") set_xlabel(ax, 'Time', 's') set_ylabel(ax, 'Frequency', 'Hz') - def plot_frequency(self, nyquists=None, style=".-", show_demod_freq=True): - ax = plt.gca() - plt.title("Detuning frequency") + def plot_frequency(self, ax=None, title='Detuning frequency', + nyquists=None, style=".-", show_demod_freq=True, **kw): + if ax is None: + ax = plt.gca() + ax.set_title(title) if nyquists is None: nyquists = [self.nyquist_order] for n in nyquists: if show_demod_freq: - plt.axhline(-self.demod_freq + self.sampling_rate*n, linestyle='--', c='grey') + ax.axhline(-self.demod_freq + self.sampling_rate * + n, linestyle='--', c='grey') real_detuning = self.get_real_detuning(n) ax.plot(self.time, real_detuning, style) set_xlabel(ax, 'Time', 's') set_ylabel(ax, 'Frequency', 'Hz') - def plot_amplitude(self, nyquists=None, style=".-"): - ax = plt.gca() - plt.title("Cryoscope amplitude") + def plot_amplitude(self, ax=None, title='Cryoscope amplitude', + nyquists=None, style=".-", **kw): + if ax is None: + ax = plt.gca() + ax.set_title(title) amp = self.get_amplitudes() ax.plot(self.time, amp, style) set_xlabel(ax, 'Time', 's') set_ylabel(ax, 'Amplitude', 'V') + def sincos_model_real_imag(times, freq, phase): r, i = np.cos(2 * np.pi * @@ -293,12 +320,15 @@ class DacArchAnalysis: supersampled signals, after constructing the arc, fits a polynomial in order to facilitate interpolation. """ + def __init__( self, times, amps, data, + exclusion_indices=[], poly_fit_order=2, + nyquist_calc='auto', invert_frequency_sign=False, plot_fits=False): """ @@ -307,23 +337,28 @@ def __init__( times: array of pulse lengths amps: array of pulse amplitudes - data: 2D array of measurement results (size of len(times x amps)). Complex numbers containing x- and y- values + data: 2D array of measurement results (size of len(times x amps)). + Complex numbers containing x- and y- values poly_fit_order: order of model used for fitting the dac-arch - invert_frequency_sign: boolean. might be useful if x and y are interchanged in measurement + invert_frequency_sign: boolean. might be useful if x and y are + interchanged in measurement plot_fits: plots how the fit is going, for display. """ self.data = data self.times = times - self.amps = amps + self.amps = np.array(amps) self.poly_fit_order = poly_fit_order self.sampling_rate = 1 / (self.times[1] - self.times[0]) self.freqs = [] + self.excl_amps = [] + self.excl_freqs = [] + self.exclusion_indices = exclusion_indices self.norm_data = [] @@ -354,33 +389,53 @@ def __init__( self.freqs.append(fit[0]) self.freqs = np.array(self.freqs) - - self.nyquist = np.cumsum(self.freqs[1:] < self.freqs[:-1]) - self.nyquist = np.hstack(([0], self.nyquist)) + if nyquist_calc == 'auto': + self.nyquist = np.cumsum(self.freqs[1:] < self.freqs[:-1]) + self.nyquist = np.hstack(([0], self.nyquist)) + elif nyquist_calc == 'disabled': + self.nyquist = np.zeros(len(self.freqs)) + else: + raise NotImplementedError() + # FIXME: proper support for auto nyquist with + # a proper nyquist should be extracte self.freqs = self.freqs + self.nyquist * self.sampling_rate if invert_frequency_sign: self.freqs = -self.freqs - self.poly_fit = np.polyfit(self.amps, self.freqs, self.poly_fit_order) + # Exclude data from excludion indices + self.filt_freqs = np.delete(self.freqs, self.exclusion_indices) + self.filt_amps = np.delete(self.amps, self.exclusion_indices) + self.excl_freqs = self.freqs[self.exclusion_indices] + self.excl_amps = self.amps[self.exclusion_indices] + + self.poly_fit = np.polyfit(self.filt_amps, self.filt_freqs, + self.poly_fit_order) self._inv_interpolation = None def amp_to_freq(self, amp): """ - Find the frequency that corresponds to a given amplitude by evaluating the fit to the extracted data. + Find the frequency that corresponds to a given amplitude by + evaluating the fit to the extracted data. """ return np.polyval(self.poly_fit, amp) - def freq_to_amp(self, freq, kind='interpolate'): + def freq_to_amp(self, freq, kind='root_parabola', **kw): """ - Find the amplitude that corresponds to a given frequency, by numerically inverting the fit. + Find the amplitude that corresponds to a given frequency, by + numerically inverting the fit. freq: The frequency or set of frequencies. kind: Which technique to use: - "interpolate": Uses numerical interpolation to find the inverse. Only works if freq is in the range of measured dac values. - "root": Finds the inverse of the model numerical. Slow, but can extrapolate. + "interpolate": Uses numerical interpolation to find the inverse. + Only works if freq is in the range of measured dac values. + "root": Finds the inverse of the model numerical. Slow, but can + extrapolate. + + **kw : get passed on to methods that implement the different "kind" + of calculations. """ if kind == 'interpolate': @@ -401,11 +456,48 @@ def freq_to_amp(self, freq, kind='interpolate'): if kind == 'root': return np.vectorize(self._freq_to_amp_root)(freq) + if kind == 'root_parabola': + # return self._freq_to_amp_root_parabola(freq, **kw) + return freq_to_amp_root_parabola(freq=freq, + poly_coeffs=self.poly_fit, **kw) + raise ValueError("`kind` not understood") + # def _freq_to_amp_root_parabola(self, freq, positive_branch=True): + # """ + # Converts freq in Hz to amplitude. + + # Requires "poly_fit" to be set to the polynomial values + # extracted from the cryoscope flux arc. + + # Assumes a parabola to find the roots but should also work for a higher + # order polynomial, except that it will pick the wrong branch. + + # N.B. this method assumes that the polycoeffs are with respect to the + # amplitude in units of V. + # """ + + # # recursive allows dealing with an array of freqs + # if isinstance(freq, (list, np.ndarray)): + # return np.array([self._freq_to_amp_root_parabola( + # f, positive_branch=positive_branch) for f in freq]) + + # p = np.poly1d(self.poly_fit) + # sols = (p-freq).roots + + # # sols returns 2 solutions (for a 2nd order polynomial) + # if positive_branch: + # sol = np.max(sols) + # else: + # sol = np.min(sols) + + # # imaginary part is ignored, instead sticking to closest real value + # return np.real(sol) + def _freq_to_amp_root(self, freq): """ - Find the amplitude corresponding to a given frequency by numerically inverting the fit. + Find the amplitude corresponding to a given frequency by numerically + inverting the fit. """ poly = np.array(self.poly_fit) @@ -428,13 +520,18 @@ def plot_freqs(self, ax=None, title='', **kw): if ax is None: ax = plt.gca() ax.set_title(title) - ax.plot(self.amps, self.freqs, ".-") - set_xlabel(ax, "Amplitude") #a.u. - set_ylabel(ax, 'Detuning', 'Hz') - aa = np.linspace(min(self.amps), max(self.amps), 50) + amps_sorted = [x for x, _ in sorted( + zip(self.filt_amps, self.filt_freqs))] + freqs_sorted = [y for _, y in sorted( + zip(self.filt_amps, self.filt_freqs))] - ax.plot(aa, np.polyval(self.poly_fit, aa)) + ax.plot(amps_sorted, freqs_sorted, ".-") + ax.scatter(self.excl_amps, self.excl_freqs, marker='x', color='C3') + aa = np.linspace(min(self.amps), max(self.amps), 50) + ax.plot(aa, np.polyval(self.poly_fit, aa), label='fit') + set_xlabel(ax, "Amplitude", 'V') + set_ylabel(ax, 'Detuning', 'Hz') def plot_ffts(self, ax=None, title='', nyquist_unwrap=False, **kw): if ax is None: @@ -446,20 +543,52 @@ def plot_ffts(self, ax=None, title='', nyquist_unwrap=False, **kw): freqs = np.arange(len(ffts[0])) * self.sampling_rate / len(ffts[0]) - def shift_helper(x): - diff = np.diff(x) / 2 - diff = np.hstack((diff[0], diff, -diff[-1])) - xshift = np.hstack((x, x[-1])) - diff - return xshift + flex_colormesh_plot_vs_xy(xvals=np.array(self.amps), yvals=freqs, + zvals=np.abs(ffts).T, + ax=ax) - aa, ff = np.meshgrid(shift_helper(self.amps), shift_helper(freqs)) + ax.scatter(self.filt_amps, self.filt_freqs % self.sampling_rate, color="C1", + facecolors='none', label='Dominant freqs.') + + ax.scatter(self.excl_amps, self.excl_freqs % self.sampling_rate, + color="C3", + marker='x') + aa = np.linspace(min(self.amps), max(self.amps), 300) - plt.pcolormesh(aa, ff, np.abs(ffts).T) - set_xlabel(ax, "Amplitude", 'V') #a.u. + ax.plot(aa, np.polyval(self.poly_fit, aa) % self.sampling_rate, "r", + label='fit') + set_xlabel(ax, "Amplitude", 'V') # a.u. set_ylabel(ax, 'Detuning', 'Hz') + ax.legend() - ax.scatter(self.amps, self.freqs % self.sampling_rate, color="C1") - aa = np.linspace(min(self.amps), max(self.amps), 300) +def freq_to_amp_root_parabola(freq, poly_coeffs, positive_branch=True): + """ + Converts freq in Hz to amplitude in V. + + Requires "poly_coeffs" to be set to the polynomial values + extracted from the cryoscope flux arc. + + Assumes a parabola to find the roots but should also work for a higher + order polynomial, except that it will pick the wrong branch. + + N.B. this method assumes that the polycoeffs are with respect to the + amplitude in units of V. + """ + # recursive allows dealing with an array of freqs + if isinstance(freq, (list, np.ndarray)): + return np.array([freq_to_amp_root_parabola( + freq=f, poly_coeffs=poly_coeffs, + positive_branch=positive_branch) for f in freq]) + + p = np.poly1d(poly_coeffs) + sols = (p-freq).roots + + # sols returns 2 solutions (for a 2nd order polynomial) + if positive_branch: + sol = np.max(sols) + else: + sol = np.min(sols) - ax.plot(aa, np.polyval(self.poly_fit, aa) % self.sampling_rate, ".r") + # imaginary part is ignored, instead sticking to closest real value + return np.real(sol) diff --git a/pycqed/analysis/tools/plotting.py b/pycqed/analysis/tools/plotting.py index 531cbc5dc8..7735375648 100644 --- a/pycqed/analysis/tools/plotting.py +++ b/pycqed/analysis/tools/plotting.py @@ -286,6 +286,10 @@ def flex_colormesh_plot_vs_xy(xvals, yvals, zvals, ax=None, (len(yvals), len(xvals)). """ + xvals = np.array(xvals) + yvals = np.array(yvals) + + # First, we need to sort the data as otherwise we get odd plotting # artefacts. An example is e.g., plotting a fourier transform sorted_x_arguments = xvals.argsort() @@ -320,7 +324,7 @@ def flex_colormesh_plot_vs_xy(xvals, yvals, zvals, ax=None, # various plot options # define colormap - cmap = plt.get_cmap(kw.pop('cmap', 'CMRmap')) + cmap = plt.get_cmap(kw.pop('cmap', 'viridis')) clim = kw.pop('clim', [None, None]) # normalized plot if normalize: diff --git a/pycqed/analysis_v2/VQE_EVC.py b/pycqed/analysis_v2/VQE_EVC.py new file mode 100644 index 0000000000..7139837b44 --- /dev/null +++ b/pycqed/analysis_v2/VQE_EVC.py @@ -0,0 +1,957 @@ +import time +import numpy as np +from pycqed.analysis import analysis_toolbox as a_tools +import pycqed.analysis_v2.base_analysis as ba +# import dataprep for tomography module +# import tomography module +# using the data prep module of analysis V2 +# from pycqed.analysis_v2 import tomography_dataprep as dataprep +from pycqed.analysis import measurement_analysis as ma +try: + import qutip as qt +except ImportError as e: + pass + # logging.warning('Could not import qutip, tomo code will not work') + +def reshape_block(shots_data, segments_per_block=16, block_size=4092, mode='truncate'): + """ + inputs: shots_data 1D array of dimension N + organizes data in blocks of dimension block_size. + num of blocks is N/block_size + """ + N = len(shots_data) + # Data dimension needs to be an integer multiple of block_size + assert(N%block_size==0) + num_blocks = N//block_size + full_segments = block_size//segments_per_block + orfan_segments = block_size % segments_per_block + missing_segments = segments_per_block - orfan_segments +# print(N,num_blocks,full_segments,orfan_segments,missing_segments) + reshaped_data = shots_data.reshape((num_blocks,block_size)) + if mode.lower()=='truncate': + truncate_idx = full_segments*segments_per_block + return reshaped_data[:,:truncate_idx] + elif mode.lower()=='padd': + padd_dim = (full_segments+1)*segments_per_block + return_block = np.nan*np.ones((num_blocks,padd_dim)) + return_block[:,:block_size] = reshaped_data + return return_block + else: + raise ValueError('Mode not understood. Needs to be truncate or padd') + +def all_repetitions(shots_data,segments_per_block=16): + flat_dim = shots_data.shape[0]*shots_data.shape[1] + # Data dimension needs to divide the segments_per_block + assert(flat_dim%segments_per_block==0) + num_blocks = flat_dim // segments_per_block + block_data = shots_data.reshape((num_blocks,segments_per_block)) + return block_data + +def get_segments_average(shots_data, segments_per_block=16, block_size=4092, mode='truncate', average=True): + reshaped_data = reshape_block(shots_data=shots_data, + segments_per_block=segments_per_block, + block_size=block_size, + mode=mode) + all_reps = all_repetitions(shots_data=reshaped_data, + segments_per_block=segments_per_block) + if average: + return np.mean(all_reps,axis=0) + else: + return all_reps + + + +class ExpectationValueCalculation: + + def __init__(self, auto=True, label='', timestamp=None, + fig_format='png', + q0_label='q0', + q1_label='q1', close_fig=True, **kw): + self.label = label + self.timestamp = timestamp + self.fig_format = fig_format + # q0 == D2 + self.q0_label = q0_label + # q1 == A + self.q1_label = q1_label + self.n_states = 2 ** 2 + self.ma_obj = ma.MeasurementAnalysis(auto=False, label=label, + timestamp=timestamp) + self.ma_obj.get_naming_and_values() + # self.get_naming_and_values() + # hard coded number of segments for a 2 qubit state tomography + # constraint imposed by UHFLI + self.nr_segments = 16 + # self.exp_name = os.path.split(self.folder)[-1][7:] + + avg_h1 = self.ma_obj.measured_values[0] + avg_h2 = self.ma_obj.measured_values[1] + avg_h12 = self.ma_obj.measured_values[2] + + # Binning all the points required for the tomo + h1_00 = np.mean(avg_h1[8:10]) + h1_01 = np.mean(avg_h1[10:12]) + h1_10 = np.mean(avg_h1[12:14]) + h1_11 = np.mean(avg_h1[14:]) + + h2_00 = np.mean(avg_h2[8:10]) + h2_01 = np.mean(avg_h2[10:12]) + h2_10 = np.mean(avg_h2[12:14]) + h2_11 = np.mean(avg_h2[14:]) + + h12_00 = np.mean(avg_h12[8:10]) + h12_01 = np.mean(avg_h12[10:12]) + h12_10 = np.mean(avg_h12[12:14]) + h12_11 = np.mean(avg_h12[14:]) + + self.measurements_tomo = ( + np.array([avg_h1[0:8], avg_h2[0:8], + avg_h12[0:8]])).flatten() + # print(self.measurements_tomo) + # print(len(self.measurements_tomo)) + + # 108 x 1 + # get the calibration points by averaging over the five measurements + # taken knowing the initial state we put in + self.measurements_cal = np.array( + [h1_00, h1_01, h1_10, h1_11, + h2_00, h2_01, h2_10, h2_11, + h12_00, h12_01, h12_10, h12_11]) + # print(len(self.measurements_cal)) + + + # print(self.measurements_cal) + + def _calibrate_betas(self): + """ + calculates betas from calibration points for the initial measurement + operator + + Betas are ordered by B0 -> II B1 -> IZ etc(binary counting) + <0|Z|0> = 1, <1|Z|1> = -1 + + Keyword arguments: + measurements_cal --- array(2 ** n_qubits) should be ordered + correctly (00, 01, 10, 11) for 2 qubits + """ + cal_matrix = np.zeros((self.n_states, self.n_states)) + # get the coefficient matrix for the betas + for i in range(self.n_states): + for j in range(self.n_states): + # perform bitwise AND and count the resulting 1s + cal_matrix[i, j] = (-1)**(bin((i & j)).count("1")) + # invert solve the simple system of equations + # print(cal_matrix) + # print(np.linalg.inv(cal_matrix)) + betas = np.zeros(12) + # print(self.measurements_cal[0:4]) + betas[0:4] = np.dot(np.linalg.inv(cal_matrix), self.measurements_cal[0:4]) + # print(cal_matrix) + # print(np.linalg.inv(cal_matrix)) + # print(self.measurements_cal[0:4]) + # print(betas[0:4]) + betas[4:8] = np.dot(np.linalg.inv(cal_matrix), self.measurements_cal[4:8]) + # print(betas[4:8]) + betas[8:] = np.dot(np.linalg.inv(cal_matrix), self.measurements_cal[8:12]) + # print(betas[8:]) + + return betas + + def expectation_value_calculation_IdenZ(self): + + betas = self._calibrate_betas() + #inverting the unprimed beta matrix + #up is unprimed + self.betas = betas + # print(self.betas[0:4], self.betas[4:8], self.betas[8:]) + beta_0_up =self.betas[0] + + beta_1_up =self.betas[1] + beta_2_up =self.betas[2] + beta_3_up =self.betas[3] + + + beta_matrix_up = np.array([[beta_0_up,beta_1_up,beta_2_up,beta_3_up], + [beta_0_up,-1*beta_1_up,beta_2_up,-1*beta_3_up], + [beta_0_up,beta_1_up,-1*beta_2_up,-1*beta_3_up], + [beta_0_up,-1*beta_1_up,-1*beta_2_up,beta_3_up]]) + + #assuming 0:4 are + # expect_value_IdenZ_up = np.dot(np.linalg.inv(beta_matrix_up), self.measurements_tomo[1:4]) + + expect_value_IdenZ_up = np.dot(np.linalg.inv(beta_matrix_up), self.measurements_tomo[0:4]) + + #inverting the primed beta matrix + #p is primed + beta_0_p =self.betas[4] + beta_1_p =self.betas[5] + beta_2_p =self.betas[6] + beta_3_p =self.betas[7] + + beta_matrix_p = np.array([[beta_0_p,beta_1_p,beta_2_p,beta_3_p], + [beta_0_p,-1*beta_1_p,beta_2_p,-1*beta_3_p], + [beta_0_p,beta_1_p,-1*beta_2_p,-1*beta_3_p], + [beta_0_p,-1*beta_1_p,-1*beta_2_p,beta_3_p]]) + # beta_matrix_p = np.array([[-1*beta_1_p,beta_2_p,-1*beta_3_p], + # [beta_1_p,-1*beta_2_p,-1*beta_3_p], + # [-1*beta_1_p,-1*beta_2_p,beta_3_p]]) + #assuming 0:4 are + expect_value_IdenZ_p = np.dot(np.linalg.inv(beta_matrix_p), self.measurements_tomo[8:12]) + # expect_value_IdenZ_p = np.dot(np.linalg.inv(beta_matrix_p), self.measurements_tomo[1:4]) + + #inverting the unprimed beta matrix + #up is unprimed + beta_0_pp =self.betas[8] + beta_1_pp =self.betas[9] + beta_2_pp =self.betas[10] + beta_3_pp =self.betas[11] + + beta_matrix_pp = np.array([[beta_0_pp,beta_1_pp,beta_2_pp,beta_3_pp], + [beta_0_pp,-1*beta_1_pp,beta_2_pp,-1*beta_3_pp], + [beta_0_pp,beta_1_pp,-1*beta_2_pp,-1*beta_3_pp], + [beta_0_pp,-1*beta_1_pp,-1*beta_2_pp,beta_3_pp]]) + # beta_matrix_pp = np.array([[-1*beta_1_pp,beta_2_pp,-1*beta_3_pp], + # [beta_1_pp,-1*beta_2_pp,-1*beta_3_pp], + # [-1*beta_1_pp,-1*beta_2_pp,beta_3_pp]]) + #assuming 0:4 are + expect_value_IdenZ_pp = np.dot(np.linalg.inv(beta_matrix_pp), self.measurements_tomo[16:20]) + # expect_value_IdenZ_pp = np.dot(np.linalg.inv(beta_matrix_p), self.measurements_tomo[1:4]) + + #take the mean of calculated expectation values of II, IZ, ZI, ZZ + #for three different beta vectors + + expect_value_IdenZ = np.mean( np.array([expect_value_IdenZ_up, + expect_value_IdenZ_p, + expect_value_IdenZ_pp]), + axis=0 ) + + print(expect_value_IdenZ_up) + + print(expect_value_IdenZ_p) + + print(expect_value_IdenZ_pp) + return expect_value_IdenZ + + def expectation_value_calculation_XX(self): + + + expect_value_XX_up = ((self.measurements_tomo[4] + self.measurements_tomo[5]) -2*self.betas[0])/2*self.betas[3] + expect_value_XX_p = ((self.measurements_tomo[12] + self.measurements_tomo[13])-2*self.betas[4])/2*self.betas[7] + expect_value_XX_pp = ((self.measurements_tomo[20] + self.measurements_tomo[21]) - 2*self.betas[8])/2*self.betas[11] + expectation_value_XX = (expect_value_XX_up + expect_value_XX_p + expect_value_XX_pp)/3 + # print(expect_value_XX_up, expect_value_XX_p, expect_value_XX_pp) + return expectation_value_XX + + def expectation_value_calculation_YY(self): + + + expect_value_YY_up = ((self.measurements_tomo[6] + self.measurements_tomo[7]) -2*self.betas[0])/2*self.betas[3] + expect_value_YY_p = ((self.measurements_tomo[14] + self.measurements_tomo[15])-2*self.betas[4])/2*self.betas[7] + expect_value_YY_pp = ((self.measurements_tomo[22] + self.measurements_tomo[23]) - 2*self.betas[8])/2*self.betas[11] + # print(expect_value_YY_up, expect_value_YY_p, expect_value_YY_pp) + expectation_value_YY = (expect_value_YY_up + expect_value_YY_p + expect_value_YY_pp)/3 + + return expectation_value_YY + + def execute_expectation_value_calculation(self): + + expect_values = np.zeros(6) + expect_values[0:4] = self.expectation_value_calculation_IdenZ() + # print(self.expectation_value_calculation_IdenZ()) + expect_values[4] = self.expectation_value_calculation_XX() + # print(self.expectation_value_calculation_XX()) + expect_values[5] = self.expectation_value_calculation_YY() + # print(self.expectation_value_calculation_YY()) + return expect_values, self.betas + + +class ExpectationValueCalculation2: + + def __init__(self, auto=True, label='', timestamp=None, + fig_format='png', + q0_label='q0', + q1_label='q1', close_fig=True, **kw): + self.label = label + self.timestamp = timestamp + self.fig_format = fig_format + # q0 == D2 + self.q0_label = q0_label + # q1 == A + self.q1_label = q1_label + self.n_states = 2 ** 2 + self.ma_obj = ma.MeasurementAnalysis(auto=False, label=label, + timestamp=timestamp) + self.ma_obj.get_naming_and_values() + # self.get_naming_and_values() + # hard coded number of segments for a 2 qubit state tomography + # constraint imposed by UHFLI + self.nr_segments = 16 + # self.exp_name = os.path.split(self.folder)[-1][7:] + + avg_h1 = self.ma_obj.measured_values[0] + avg_h2 = self.ma_obj.measured_values[1] + avg_h12 = self.ma_obj.measured_values[2] + h1_00 = np.mean(avg_h1[8:10]) + h1_01 = np.mean(avg_h1[10:12]) + h1_10 = np.mean(avg_h1[12:14]) + h1_11 = np.mean(avg_h1[14:]) + + h2_00 = np.mean(avg_h2[8:10]) + h2_01 = np.mean(avg_h2[10:12]) + h2_10 = np.mean(avg_h2[12:14]) + h2_11 = np.mean(avg_h2[14:]) + + h12_00 = np.mean(avg_h12[8:10]) + h12_01 = np.mean(avg_h12[10:12]) + h12_10 = np.mean(avg_h12[12:14]) + h12_11 = np.mean(avg_h12[14:]) + self.measurements_tomo = ( + np.array([avg_h1[0:8], avg_h2[0:8], + avg_h12[0:8]])).flatten() + # print(self.measurements_tomo) + # print(len(self.measurements_tomo)) + + # 108 x 1 + # get the calibration points by averaging over the five measurements + # taken knowing the initial state we put in + self.measurements_cal = np.array( + [h1_00, h1_01, h1_10, h1_11, + h2_00, h2_01, h2_10, h2_11, + h12_00, h12_01, h12_10, h12_11]) + + def _calibrate_betas(self): + """ + calculates betas from calibration points for the initial measurement + operator + + Betas are ordered by B0 -> II B1 -> IZ etc(binary counting) + <0|Z|0> = 1, <1|Z|1> = -1 + + Keyword arguments: + measurements_cal --- array(2 ** n_qubits) should be ordered + correctly (00, 01, 10, 11) for 2 qubits + """ + cal_matrix = np.zeros((self.n_states, self.n_states)) + # get the coefficient matrix for the betas + for i in range(self.n_states): + for j in range(self.n_states): + # perform bitwise AND and count the resulting 1s + cal_matrix[i, j] = (-1)**(bin((i & j)).count("1")) + # invert solve the simple system of equations + # print(cal_matrix) + # print(np.linalg.inv(cal_matrix)) + betas = np.zeros(12) + # print(self.measurements_cal[0:4]) + betas[0:4] = np.dot(np.linalg.inv(cal_matrix), + self.measurements_cal[0:4]) + self.betas_up = betas[0:4] + betas[4:8] = np.dot(np.linalg.inv(cal_matrix), + self.measurements_cal[4:8]) + self.betas_p = betas[4:8] + betas[8:] = np.dot(np.linalg.inv(cal_matrix), + self.measurements_cal[8:12]) + self.betas_pp = betas[8:] + return betas + + def assemble_M_matrix_single_block(self, beta_array): + M_matrix_single_block_row_1 = np.array([beta_array[0], beta_array[1], + beta_array[2], beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_2 = np.array([beta_array[0], + -1*beta_array[1], + beta_array[2], + -1*beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_3 = np.array([beta_array[0], + beta_array[1], + -1*beta_array[2], + -1*beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_4 = np.array([beta_array[0], + -1*beta_array[1], + -1*beta_array[2], + beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_5 = np.array([beta_array[0], + 0, 0, 0, -beta_array[1], + -beta_array[2], + beta_array[3], 0, 0, 0]) + M_matrix_single_block_row_6 = np.array([beta_array[0], 0, 0, 0, + beta_array[1], + beta_array[2], + beta_array[3], + 0, 0, 0]) + M_matrix_single_block_row_7 = np.array([beta_array[0], 0, 0, + 0, 0, 0, 0, beta_array[1], + beta_array[2], + beta_array[3]]) + M_matrix_single_block_row_8 = np.array([beta_array[0], 0, 0, 0, 0, + 0, 0, -beta_array[1], + -beta_array[2], + beta_array[3]]) + M_matrix_single_block = np.vstack((M_matrix_single_block_row_1, + M_matrix_single_block_row_2, + M_matrix_single_block_row_3, + M_matrix_single_block_row_4, + M_matrix_single_block_row_5, + M_matrix_single_block_row_6, + M_matrix_single_block_row_7, + M_matrix_single_block_row_8)) + M_matrix_single_block = M_matrix_single_block.reshape(8, 10) + return M_matrix_single_block + + def assemble_M_matrix(self): + Block1 = self.assemble_M_matrix_single_block(self.betas_up) + Block2 = self.assemble_M_matrix_single_block(self.betas_p) + Block3 = self.assemble_M_matrix_single_block(self.betas_pp) + self.M_matrix = np.vstack((Block1, Block2, Block3)).reshape(24, 10) + return self.M_matrix + + def invert_M_matrix(self): + self.inverse_matrix = np.linalg.pinv(self.M_matrix) + return self.inverse_matrix + + def execute_error_signalling(self, ev): + II = (ev[0] - ev[3])/(1 - ev[3]) + IZ = (ev[1] - ev[2])/(1 - ev[3]) + ZI = (ev[1] - ev[2])/(1 - ev[3]) + ZZ = (ev[3] - ev[0])/(1 - ev[3]) + XX = (ev[4] + ev[5])/(1 - ev[3]) + YY = (ev[4] + ev[5])/(1 - ev[3]) + ev_error_signalling = np.array([II, IZ, ZI, ZZ, XX, YY]) + return ev_error_signalling + + def execute_expectation_value_calculation(self): + # assemble matrix that connects RO with terms + self._calibrate_betas() + self.assemble_M_matrix() + self.invert_M_matrix() + # use it to get terms back from RO + rescaled_measurements_tomo = self.measurements_tomo + self.expect_values = np.dot(self.inverse_matrix, + rescaled_measurements_tomo) + expect_values_VQE = np.array([self.expect_values[0], + self.expect_values[1], + self.expect_values[2], + self.expect_values[3], + self.expect_values[6], + self.expect_values[9]]) + return expect_values_VQE + + def execute_expectation_value_calculation_traceone(self): + # assemble matrix that connects RO with terms + self._calibrate_betas() + self.assemble_M_matrix() + self.inverse_matrix = np.linalg.pinv(self.M_matrix[:, 1:]) + # use it to get terms back from RO + rescaled_measurements_tomo = self.measurements_tomo + self.expect_values = np.dot(self.inverse_matrix, + rescaled_measurements_tomo) + expect_values_VQE = np.array([1, + self.expect_values[0], + self.expect_values[1], + self.expect_values[2], + self.expect_values[5], + self.expect_values[8]]) + return expect_values_VQE + + def execute_expectation_value_calculation_T1signaling(self): + # assemble matrix that connects RO with terms + self._calibrate_betas() + self.assemble_M_matrix() + self.inverse_matrix = np.linalg.pinv(self.M_matrix[:, 1:]) + # use it to get terms back from RO + rescaled_measurements_tomo = self.measurements_tomo + self.expect_values = np.dot(self.inverse_matrix, + rescaled_measurements_tomo) + expect_values_VQE = np.array([1, + self.expect_values[0], + self.expect_values[1], + self.expect_values[2], + self.expect_values[5], + self.expect_values[8]]) + expect_values_VQE = self.execute_error_signalling(expect_values_VQE) + return expect_values_VQE + + +class ExpectationValueCalculation3_shots: + + def __init__(self, auto=True, label='', timestamp=None, + fig_format='png', + q0_label='q0', + q1_label='q1', close_fig=True, **kw): + self.label = label + self.timestamp = timestamp + self.fig_format = fig_format + # q0 == D2 + self.q0_label = q0_label + # q1 == A + self.q1_label = q1_label + self.n_states = 2 ** 2 + self.ma_obj = ma.MeasurementAnalysis(auto=False, label=label, + timestamp=timestamp) + self.ma_obj.get_naming_and_values() + # self.get_naming_and_values() + # hard coded number of segments for a 2 qubit state tomography + # constraint imposed by UHFLI + self.nr_segments = 16 + shots_I_q0 = get_segments_average(self.ma_obj.measured_values[0], + segments_per_block=16, + block_size=4094, + average=False) + shots_I_q1 = get_segments_average(self.ma_obj.measured_values[1], + segments_per_block=16, + block_size=4094, + average=False) + + shots_I_q0q1 = np.multiply(shots_I_q0/(np.max(shots_I_q0)-np.min(shots_I_q0)),shots_I_q1/(np.max(shots_I_q1)-np.min(shots_I_q1))) + + avg_h1 = np.mean(shots_I_q0,axis=0) + avg_h2 = np.mean(shots_I_q1,axis=0) + avg_h12 = np.mean(shots_I_q0q1,axis=0) + + h1_00 = np.mean(avg_h1[8:10]) + h1_01 = np.mean(avg_h1[10:12]) + h1_10 = np.mean(avg_h1[12:14]) + h1_11 = np.mean(avg_h1[14:]) + + h2_00 = np.mean(avg_h2[8:10]) + h2_01 = np.mean(avg_h2[10:12]) + h2_10 = np.mean(avg_h2[12:14]) + h2_11 = np.mean(avg_h2[14:]) + + h12_00 = np.mean(avg_h12[8:10]) + h12_01 = np.mean(avg_h12[10:12]) + h12_10 = np.mean(avg_h12[12:14]) + h12_11 = np.mean(avg_h12[14:]) + mean_h1 = (h1_00+h1_10+h1_01+h1_11)/4 + mean_h2 = (h2_00+h2_01+h2_10+h2_11)/4 + mean_h12 = (h12_00+h12_11+h12_01+h12_10)/4 + + #subtract beta 0 from all measurements + #rescale them + avg_h1 -= mean_h1 + avg_h2 -= mean_h2 + avg_h12 -= mean_h12 + + scale_h1 = (h1_00+h1_10-h1_01-h1_11)/4 + scale_h2 = (h2_00+h2_01-h2_10-h2_11)/4 + scale_h12 = (h12_00+h12_11-h12_01-h12_10)/4 + + avg_h1 = (avg_h1)/scale_h1 + avg_h2 = (avg_h2)/scale_h2 + avg_h12 = (avg_h12)/scale_h12 + #The averages have been redefined so redefine the cal terms + h1_00 = np.mean(avg_h1[8:10]) + h1_01 = np.mean(avg_h1[10:12]) + h1_10 = np.mean(avg_h1[12:14]) + h1_11 = np.mean(avg_h1[14:]) + + h2_00 = np.mean(avg_h2[8:10]) + h2_01 = np.mean(avg_h2[10:12]) + h2_10 = np.mean(avg_h2[12:14]) + h2_11 = np.mean(avg_h2[14:]) + + h12_00 = np.mean(avg_h12[8:10]) + h12_01 = np.mean(avg_h12[10:12]) + h12_10 = np.mean(avg_h12[12:14]) + h12_11 = np.mean(avg_h12[14:]) + + self.measurements_tomo = ( + np.array([avg_h1[0:8], avg_h2[0:8], + avg_h12[0:8]])).flatten() + # print(self.measurements_tomo) + # print(len(self.measurements_tomo)) + + # 108 x 1 + # get the calibration points by averaging over the five measurements + # taken knowing the initial state we put in + self.measurements_cal = np.array( + [h1_00, h1_01, h1_10, h1_11, + h2_00, h2_01, h2_10, h2_11, + h12_00, h12_01, h12_10, h12_11]) + + def _calibrate_betas(self): + """ + calculates betas from calibration points for the initial measurement + operator + + Betas are ordered by B0 -> II B1 -> IZ etc(binary counting) + <0|Z|0> = 1, <1|Z|1> = -1 + + Keyword arguments: + measurements_cal --- array(2 ** n_qubits) should be ordered + correctly (00, 01, 10, 11) for 2 qubits + """ + cal_matrix = np.zeros((self.n_states, self.n_states)) + # get the coefficient matrix for the betas + for i in range(self.n_states): + for j in range(self.n_states): + # perform bitwise AND and count the resulting 1s + cal_matrix[i, j] = (-1)**(bin((i & j)).count("1")) + # invert solve the simple system of equations + # print(cal_matrix) + # print(np.linalg.inv(cal_matrix)) + betas = np.zeros(12) + + betas[0:4] = np.dot(np.linalg.inv(cal_matrix), + self.measurements_cal[0:4]) + self.betas_up = betas[0:4] + betas[4:8] = np.dot(np.linalg.inv(cal_matrix), + self.measurements_cal[4:8]) + self.betas_p = betas[4:8] + betas[8:] = np.dot(np.linalg.inv(cal_matrix), + self.measurements_cal[8:12]) + + self.betas_pp = betas[8:] + return betas + + def assemble_M_matrix_single_block(self, beta_array): + # II IZ ZI ZZ IX XI XX IY YI YY + M_matrix_single_block_row_1 = np.array([beta_array[0], beta_array[1], + beta_array[2], beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_2 = np.array([beta_array[0], + -1*beta_array[1], + beta_array[2], + -1*beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_3 = np.array([beta_array[0], + beta_array[1], + -1*beta_array[2], + -1*beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_4 = np.array([beta_array[0], + -1*beta_array[1], + -1*beta_array[2], + beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_5 = np.array([beta_array[0], # 36 + 0, 0, 0, -1*beta_array[1], + -1*beta_array[2], + beta_array[3], 0, 0, 0]) + M_matrix_single_block_row_6 = np.array([beta_array[0], 0, 0, 0, # 29 + beta_array[1], + beta_array[2], + beta_array[3], + 0, 0, 0]) + M_matrix_single_block_row_7 = np.array([beta_array[0], 0, 0, + 0, 0, 0, 0, beta_array[1], + beta_array[2], + beta_array[3]]) + M_matrix_single_block_row_8 = np.array([beta_array[0], 0, 0, 0, 0, + 0, 0, -1*beta_array[1], + -1*beta_array[2], + beta_array[3]]) + M_matrix_single_block = np.vstack((M_matrix_single_block_row_1, + M_matrix_single_block_row_2, + M_matrix_single_block_row_3, + M_matrix_single_block_row_4, + M_matrix_single_block_row_5, + M_matrix_single_block_row_6, + M_matrix_single_block_row_7, + M_matrix_single_block_row_8)) + M_matrix_single_block = M_matrix_single_block.reshape(8, 10) + return M_matrix_single_block + + def assemble_M_matrix(self): + Block1 = self.assemble_M_matrix_single_block(self.betas_up) + Block2 = self.assemble_M_matrix_single_block(self.betas_p) + Block3 = self.assemble_M_matrix_single_block(self.betas_pp) + self.M_matrix = np.vstack((Block1, Block2, Block3)).reshape(24, 10) + return self.M_matrix + + def invert_M_matrix(self): + self.inverse_matrix = np.linalg.pinv(self.M_matrix) + return self.inverse_matrix + + def execute_error_signalling(self, ev): + II = (ev[0] - ev[3])/(1 - ev[3]) + IZ = (ev[1] - ev[2])/(1 - ev[3]) + ZI = (ev[2] - ev[1])/(1 - ev[3]) + ZZ = (ev[3] - ev[0])/(1 - ev[3]) + XX = (ev[4] + ev[5])/(1 - ev[3]) + YY = (ev[5] + ev[4])/(1 - ev[3]) + ev_error_signalling = np.array([II, IZ, ZI, ZZ, XX, YY]) + return ev_error_signalling + + def execute_expectation_value_calculation(self): + # assemble matrix that connects RO with terms + self._calibrate_betas() + self.assemble_M_matrix() + self.invert_M_matrix() + # use it to get terms back from RO + rescaled_measurements_tomo = self.measurements_tomo + self.expect_values = np.dot(self.inverse_matrix, + rescaled_measurements_tomo) + print(self.expect_values) + expect_values_VQE = np.array([1, + self.expect_values[1], + self.expect_values[2], + self.expect_values[3], + self.expect_values[6], + self.expect_values[9]]) + self.expect_values = expect_values_VQE + return expect_values_VQE + + def execute_expectation_value_calculation_traceone(self): + # assemble matrix that connects RO with terms + self._calibrate_betas() + self.assemble_M_matrix() + self.inverse_matrix = np.linalg.pinv(self.M_matrix[:, 1:]) + # use it to get terms back from RO + beta_0_vec = np.repeat([self.betas_up[0], + self.betas_p[0], + self.betas_pp[0]], 8) + rescaled_measurements_tomo = self.measurements_tomo - beta_0_vec + self.expect_values = np.dot(self.inverse_matrix, + rescaled_measurements_tomo) + expect_values_VQE = np.array([1, + self.expect_values[0], + self.expect_values[1], + self.expect_values[2], + self.expect_values[5], + self.expect_values[8]]) + self.expect_values = expect_values_VQE + print(self.expect_values) + return expect_values_VQE + + def execute_expectation_value_calculation_T1signaling(self): + # assemble matrix that connects RO with terms + self._calibrate_betas() + self.assemble_M_matrix() + self.invert_M_matrix() + # use it to get terms back from RO + rescaled_measurements_tomo = self.measurements_tomo + self.expect_values = np.dot(self.inverse_matrix, + rescaled_measurements_tomo) + expect_values_VQE = np.array([self.expect_values[0], + self.expect_values[1], + self.expect_values[2], + self.expect_values[3], + self.expect_values[6], + self.expect_values[9]]) + expect_values_VQE = self.execute_error_signalling(expect_values_VQE) + self.expect_values = expect_values_VQE + return expect_values_VQE + + + + +class ExpectationValueCalculation2_shots: + + def __init__(self, auto=True, label='', timestamp=None, + fig_format='png', + q0_label='q0', + q1_label='q1', close_fig=True, **kw): + self.label = label + self.timestamp = timestamp + self.fig_format = fig_format + # q0 == D2 + self.q0_label = q0_label + # q1 == A + self.q1_label = q1_label + self.n_states = 2 ** 2 + self.ma_obj = ma.MeasurementAnalysis(auto=False, label=label, + timestamp=timestamp) + self.ma_obj.get_naming_and_values() + # self.get_naming_and_values() + # hard coded number of segments for a 2 qubit state tomography + # constraint imposed by UHFLI + self.nr_segments = 16 + # self.exp_name = os.path.split(self.folder)[-1][7:] + shots_I_q0 = get_segments_average(self.ma_obj.measured_values[0], + segments_per_block=16, + block_size=4094, + average=False) + shots_I_q1 = get_segments_average(self.ma_obj.measured_values[1], + segments_per_block=16, + block_size=4094, + average=False) + + shots_I_q0q1 = np.multiply(shots_I_q0/(np.max(shots_I_q0)-np.min(shots_I_q0)),shots_I_q1/(np.max(shots_I_q1)-np.min(shots_I_q1))) + + avg_h1 = np.mean(shots_I_q0,axis=0) + avg_h2 = np.mean(shots_I_q1,axis=0) + avg_h12 = np.mean(shots_I_q0q1,axis=0) + h1_00 = np.mean(avg_h1[8:10]) + h1_01 = np.mean(avg_h1[10:12]) + h1_10 = np.mean(avg_h1[12:14]) + h1_11 = np.mean(avg_h1[14:]) + + h2_00 = np.mean(avg_h2[8:10]) + h2_01 = np.mean(avg_h2[10:12]) + h2_10 = np.mean(avg_h2[12:14]) + h2_11 = np.mean(avg_h2[14:]) + + h12_00 = np.mean(avg_h12[8:10]) + h12_01 = np.mean(avg_h12[10:12]) + h12_10 = np.mean(avg_h12[12:14]) + h12_11 = np.mean(avg_h12[14:]) + self.measurements_tomo = ( + np.array([avg_h1[0:8], avg_h2[0:8], + avg_h12[0:8]])).flatten() + # print(self.measurements_tomo) + # print(len(self.measurements_tomo)) + + # 108 x 1 + # get the calibration points by averaging over the five measurements + # taken knowing the initial state we put in + self.measurements_cal = np.array( + [h1_00, h1_01, h1_10, h1_11, + h2_00, h2_01, h2_10, h2_11, + h12_00, h12_01, h12_10, h12_11]) + + def _calibrate_betas(self): + """ + calculates betas from calibration points for the initial measurement + operator + + Betas are ordered by B0 -> II B1 -> IZ etc(binary counting) + <0|Z|0> = 1, <1|Z|1> = -1 + + Keyword arguments: + measurements_cal --- array(2 ** n_qubits) should be ordered + correctly (00, 01, 10, 11) for 2 qubits + """ + cal_matrix = np.zeros((self.n_states, self.n_states)) + # get the coefficient matrix for the betas + for i in range(self.n_states): + for j in range(self.n_states): + # perform bitwise AND and count the resulting 1s + cal_matrix[i, j] = (-1)**(bin((i & j)).count("1")) + # invert solve the simple system of equations + # print(cal_matrix) + # print(np.linalg.inv(cal_matrix)) + betas = np.zeros(12) + # print(self.measurements_cal[0:4]) + betas[0:4] = np.dot(np.linalg.inv(cal_matrix), + self.measurements_cal[0:4]) + self.betas_up = betas[0:4] + betas[4:8] = np.dot(np.linalg.inv(cal_matrix), + self.measurements_cal[4:8]) + self.betas_p = betas[4:8] + betas[8:] = np.dot(np.linalg.inv(cal_matrix), + self.measurements_cal[8:12]) + self.betas_pp = betas[8:] + return betas + + def assemble_M_matrix_single_block(self, beta_array): + M_matrix_single_block_row_1 = np.array([beta_array[0], beta_array[1], + beta_array[2], beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_2 = np.array([beta_array[0], + -1*beta_array[1], + beta_array[2], + -1*beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_3 = np.array([beta_array[0], + beta_array[1], + -1*beta_array[2], + -1*beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_4 = np.array([beta_array[0], + -1*beta_array[1], + -1*beta_array[2], + beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_5 = np.array([beta_array[0], + 0, 0, 0, -beta_array[1], + -beta_array[2], + beta_array[3], 0, 0, 0]) + M_matrix_single_block_row_6 = np.array([beta_array[0], 0, 0, 0, + beta_array[1], + beta_array[2], + beta_array[3], + 0, 0, 0]) + M_matrix_single_block_row_7 = np.array([beta_array[0], 0, 0, + 0, 0, 0, 0, beta_array[1], + beta_array[2], + beta_array[3]]) + M_matrix_single_block_row_8 = np.array([beta_array[0], 0, 0, 0, 0, + 0, 0, -beta_array[1], + -beta_array[2], + beta_array[3]]) + M_matrix_single_block = np.vstack((M_matrix_single_block_row_1, + M_matrix_single_block_row_2, + M_matrix_single_block_row_3, + M_matrix_single_block_row_4, + M_matrix_single_block_row_5, + M_matrix_single_block_row_6, + M_matrix_single_block_row_7, + M_matrix_single_block_row_8)) + M_matrix_single_block = M_matrix_single_block.reshape(8, 10) + return M_matrix_single_block + + def assemble_M_matrix(self): + Block1 = self.assemble_M_matrix_single_block(self.betas_up) + Block2 = self.assemble_M_matrix_single_block(self.betas_p) + Block3 = self.assemble_M_matrix_single_block(self.betas_pp) + self.M_matrix = np.vstack((Block1, Block2, Block3)).reshape(24, 10) + return self.M_matrix + + def invert_M_matrix(self): + self.inverse_matrix = np.linalg.pinv(self.M_matrix) + return self.inverse_matrix + + def execute_error_signalling(self, ev): + II = (ev[0] - ev[3])/(1 - ev[3]) + IZ = (ev[1] - ev[2])/(1 - ev[3]) + ZI = (ev[1] - ev[2])/(1 - ev[3]) + ZZ = (ev[3] - ev[0])/(1 - ev[3]) + XX = (ev[4] + ev[5])/(1 - ev[3]) + YY = (ev[4] + ev[5])/(1 - ev[3]) + ev_error_signalling = np.array([II, IZ, ZI, ZZ, XX, YY]) + return ev_error_signalling + + def execute_expectation_value_calculation(self): + # assemble matrix that connects RO with terms + self._calibrate_betas() + self.assemble_M_matrix() + self.invert_M_matrix() + # use it to get terms back from RO + rescaled_measurements_tomo = self.measurements_tomo + self.expect_values = np.dot(self.inverse_matrix, + rescaled_measurements_tomo) + expect_values_VQE = np.array([self.expect_values[0], + self.expect_values[1], + self.expect_values[2], + self.expect_values[3], + self.expect_values[6], + self.expect_values[9]]) + return expect_values_VQE + + def execute_expectation_value_calculation_traceone(self): + # assemble matrix that connects RO with terms + self._calibrate_betas() + self.assemble_M_matrix() + self.inverse_matrix = np.linalg.pinv(self.M_matrix[:, 1:]) + # use it to get terms back from RO + rescaled_measurements_tomo = self.measurements_tomo + self.expect_values = np.dot(self.inverse_matrix, + rescaled_measurements_tomo) + expect_values_VQE = np.array([1, + self.expect_values[0], + self.expect_values[1], + self.expect_values[2], + self.expect_values[5], + self.expect_values[8]]) + return expect_values_VQE + + def execute_expectation_value_calculation_T1signaling(self): + # assemble matrix that connects RO with terms + self._calibrate_betas() + self.assemble_M_matrix() + self.inverse_matrix = np.linalg.pinv(self.M_matrix[:, 1:]) + # use it to get terms back from RO + rescaled_measurements_tomo = self.measurements_tomo + self.expect_values = np.dot(self.inverse_matrix, + rescaled_measurements_tomo) + expect_values_VQE = np.array([1, + self.expect_values[0], + self.expect_values[1], + self.expect_values[2], + self.expect_values[5], + self.expect_values[8]]) + expect_values_VQE = self.execute_error_signalling(expect_values_VQE) + return expect_values_VQE diff --git a/pycqed/analysis_v2/VQE_EVC_2.py b/pycqed/analysis_v2/VQE_EVC_2.py new file mode 100644 index 0000000000..9560d8ce47 --- /dev/null +++ b/pycqed/analysis_v2/VQE_EVC_2.py @@ -0,0 +1,505 @@ +import time +import numpy as np +from pycqed.analysis import analysis_toolbox as a_tools +import pycqed.analysis_v2.base_analysis as ba +# import dataprep for tomography module +# import tomography module +# using the data prep module of analysis V2 +# from pycqed.analysis_v2 import tomography_dataprep as dataprep +from pycqed.analysis import measurement_analysis as ma +try: + import qutip as qt +except ImportError as e: + pass + # logging.warning('Could not import qutip, tomo code will not work') + +def reshape_block(shots_data, segments_per_block=16, block_size=4092, mode='truncate'): + """ + inputs: shots_data 1D array of dimension N + organizes data in blocks of dimension block_size. + num of blocks is N/block_size + """ + N = len(shots_data) + # Data dimension needs to be an integer multiple of block_size + assert(N%block_size==0) + num_blocks = N//block_size + full_segments = block_size//segments_per_block + orfan_segments = block_size % segments_per_block + missing_segments = segments_per_block - orfan_segments +# print(N,num_blocks,full_segments,orfan_segments,missing_segments) + reshaped_data = shots_data.reshape((num_blocks,block_size)) + if mode.lower()=='truncate': + truncate_idx = full_segments*segments_per_block + return reshaped_data[:,:truncate_idx] + elif mode.lower()=='padd': + padd_dim = (full_segments+1)*segments_per_block + return_block = np.nan*np.ones((num_blocks,padd_dim)) + return_block[:,:block_size] = reshaped_data + return return_block + else: + raise ValueError('Mode not understood. Needs to be truncate or padd') + +def all_repetitions(shots_data,segments_per_block=16): + flat_dim = shots_data.shape[0]*shots_data.shape[1] + # Data dimension needs to divide the segments_per_block + assert(flat_dim%segments_per_block==0) + num_blocks = flat_dim // segments_per_block + block_data = shots_data.reshape((num_blocks,segments_per_block)) + return block_data + +def get_segments_average(shots_data, segments_per_block=16, block_size=4092, mode='truncate', average=True): + reshaped_data = reshape_block(shots_data=shots_data, + segments_per_block=segments_per_block, + block_size=block_size, + mode=mode) + all_reps = all_repetitions(shots_data=reshaped_data, + segments_per_block=segments_per_block) + if average: + return np.mean(all_reps,axis=0) + else: + return all_reps + + +class ExpectationValueCalculation_mmt_computer: + + def __init__(self, auto=True, label='', timestamp=None, + fig_format='png', + q0_label='q0', + q1_label='q1', close_fig=True, **kw): + self.label = label + self.timestamp = timestamp + self.fig_format = fig_format + # q0 == D2 + self.q0_label = q0_label + # q1 == A + self.q1_label = q1_label + self.n_states = 2 ** 2 + self.ma_obj = ma.MeasurementAnalysis(auto=False, label=label, + timestamp=timestamp) + self.ma_obj.get_naming_and_values() + # self.get_naming_and_values() + # hard coded number of segments for a 2 qubit state tomography + # constraint imposed by UHFLI + self.nr_segments = 16 + # self.exp_name = os.path.split(self.folder)[-1][7:] + + avg_h1 = self.ma_obj.measured_values[0] + avg_h2 = self.ma_obj.measured_values[1] + avg_h12 = self.ma_obj.measured_values[2] + h1_00 = np.mean(avg_h1[36:36+7]) + h1_01 = np.mean(avg_h1[43:43+7]) + h1_10 = np.mean(avg_h1[50:50+7]) + h1_11 = np.mean(avg_h1[57:]) + + h2_00 = np.mean(avg_h2[36:36+7]) + h2_01 = np.mean(avg_h2[43:43+7]) + h2_10 = np.mean(avg_h2[50:50+7]) + h2_11 = np.mean(avg_h2[57:]) + + h12_00 = np.mean(avg_h12[36:36+7]) + h12_01 = np.mean(avg_h12[43:43+7]) + h12_10 = np.mean(avg_h12[50:50+7]) + h12_11 = np.mean(avg_h12[57:]) + + measurement_channel_1 = np.array([avg_h1[0], avg_h1[1], avg_h1[7], + avg_h1[8], avg_h1[14], avg_h1[21], + avg_h1[28], avg_h1[35]]) + measurement_channel_2 = np.array([avg_h2[0], avg_h2[1], avg_h2[7], avg_h2[8], + avg_h2[14], avg_h2[21], avg_h2[28], avg_h2[35]]) + measurement_channel_3 = np.array([avg_h12[0], avg_h12[1], avg_h12[7], + avg_h12[8], avg_h12[14], avg_h12[21], + avg_h12[28],avg_h12[35]]) + self.measurements_tomo = np.array([measurement_channel_1, + measurement_channel_2, + measurement_channel_3]).flatten() + # print(self.measurements_tomo) + # print(len(self.measurements_tomo)) + + # 108 x 1 + # get the calibration points by averaging over the five measurements + # taken knowing the initial state we put in + self.measurements_cal = np.array( + [h1_00, h1_01, h1_10, h1_11, + h2_00, h2_01, h2_10, h2_11, + h12_00, h12_01, h12_10, h12_11]) + + def _calibrate_betas(self): + """ + calculates betas from calibration points for the initial measurement + operator + + Betas are ordered by B0 -> II B1 -> IZ etc(binary counting) + <0|Z|0> = 1, <1|Z|1> = -1 + + Keyword arguments: + measurements_cal --- array(2 ** n_qubits) should be ordered + correctly (00, 01, 10, 11) for 2 qubits + """ + cal_matrix = np.zeros((self.n_states, self.n_states)) + # get the coefficient matrix for the betas + for i in range(self.n_states): + for j in range(self.n_states): + # perform bitwise AND and count the resulting 1s + cal_matrix[i, j] = (-1)**(bin((i & j)).count("1")) + # invert solve the simple system of equations + # print(cal_matrix) + # print(np.linalg.inv(cal_matrix)) + betas = np.zeros(12) + # print(self.measurements_cal[0:4]) + betas[0:4] = np.dot(np.linalg.inv(cal_matrix), + self.measurements_cal[0:4]) + self.betas_up = betas[0:4] + betas[4:8] = np.dot(np.linalg.inv(cal_matrix), + self.measurements_cal[4:8]) + self.betas_p = betas[4:8] + betas[8:] = np.dot(np.linalg.inv(cal_matrix), + self.measurements_cal[8:12]) + self.betas_pp = betas[8:] + return betas + + def assemble_M_matrix_single_block(self, beta_array): + M_matrix_single_block_row_1 = np.array([beta_array[0], beta_array[1], + beta_array[2], beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_2 = np.array([beta_array[0], + -1*beta_array[1], + beta_array[2], + -1*beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_3 = np.array([beta_array[0], + beta_array[1], + -1*beta_array[2], + -1*beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_4 = np.array([beta_array[0], + -1*beta_array[1], + -1*beta_array[2], + beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_5 = np.array([beta_array[0], + 0, 0, 0, -beta_array[1], + -beta_array[2], + beta_array[3], 0, 0, 0]) + M_matrix_single_block_row_6 = np.array([beta_array[0], 0, 0, 0, + beta_array[1], + beta_array[2], + beta_array[3], + 0, 0, 0]) + M_matrix_single_block_row_7 = np.array([beta_array[0], 0, 0, + 0, 0, 0, 0, beta_array[1], + beta_array[2], + beta_array[3]]) + M_matrix_single_block_row_8 = np.array([beta_array[0], 0, 0, 0, 0, + 0, 0, -beta_array[1], + -beta_array[2], + beta_array[3]]) + M_matrix_single_block = np.vstack((M_matrix_single_block_row_1, + M_matrix_single_block_row_2, + M_matrix_single_block_row_3, + M_matrix_single_block_row_4, + M_matrix_single_block_row_5, + M_matrix_single_block_row_6, + M_matrix_single_block_row_7, + M_matrix_single_block_row_8)) + M_matrix_single_block = M_matrix_single_block.reshape(8, 10) + return M_matrix_single_block + + def assemble_M_matrix(self): + Block1 = self.assemble_M_matrix_single_block(self.betas_up) + Block2 = self.assemble_M_matrix_single_block(self.betas_p) + Block3 = self.assemble_M_matrix_single_block(self.betas_pp) + self.M_matrix = np.vstack((Block1, Block2, Block3)).reshape(24, 10) + return self.M_matrix + + def invert_M_matrix(self): + self.inverse_matrix = np.linalg.pinv(self.M_matrix) + return self.inverse_matrix + + def execute_error_signalling(self, ev): + II = (ev[0] - ev[3])/(1 - ev[3]) + IZ = (ev[1] - ev[2])/(1 - ev[3]) + ZI = (ev[1] - ev[2])/(1 - ev[3]) + ZZ = (ev[3] - ev[0])/(1 - ev[3]) + XX = (ev[4] + ev[5])/(1 - ev[3]) + YY = (ev[4] + ev[5])/(1 - ev[3]) + ev_error_signalling = np.array([II, IZ, ZI, ZZ, XX, YY]) + return ev_error_signalling + + def execute_expectation_value_calculation(self): + # assemble matrix that connects RO with terms + self._calibrate_betas() + self.assemble_M_matrix() + self.invert_M_matrix() + # use it to get terms back from RO + rescaled_measurements_tomo = self.measurements_tomo + self.expect_values = np.dot(self.inverse_matrix, + rescaled_measurements_tomo) + expect_values_VQE = np.array([self.expect_values[0], + self.expect_values[1], + self.expect_values[2], + self.expect_values[3], + self.expect_values[6], + self.expect_values[9]]) + return expect_values_VQE + + def execute_expectation_value_calculation_traceone(self): + # assemble matrix that connects RO with terms + self._calibrate_betas() + self.assemble_M_matrix() + self.inverse_matrix = np.linalg.pinv(self.M_matrix[:, 1:]) + # use it to get terms back from RO + rescaled_measurements_tomo = self.measurements_tomo + self.expect_values = np.dot(self.inverse_matrix, + rescaled_measurements_tomo) + expect_values_VQE = np.array([1, + self.expect_values[0], + self.expect_values[1], + self.expect_values[2], + self.expect_values[5], + self.expect_values[8]]) + return expect_values_VQE + + def execute_expectation_value_calculation_T1signaling(self): + # assemble matrix that connects RO with terms + self._calibrate_betas() + self.assemble_M_matrix() + self.inverse_matrix = np.linalg.pinv(self.M_matrix[:, 1:]) + # use it to get terms back from RO + rescaled_measurements_tomo = self.measurements_tomo + self.expect_values = np.dot(self.inverse_matrix, + rescaled_measurements_tomo) + expect_values_VQE = np.array([1, + self.expect_values[0], + self.expect_values[1], + self.expect_values[2], + self.expect_values[5], + self.expect_values[8]]) + expect_values_VQE = self.execute_error_signalling(expect_values_VQE) + return expect_values_VQE + + +class ExpectationValueCalculation: + + def __init__(self, auto=True, label='', timestamp=None, + fig_format='png', + q0_label='q0', + q1_label='q1', close_fig=True, **kw): + self.label = label + self.timestamp = timestamp + self.fig_format = fig_format + # q0 == D2 + self.q0_label = q0_label + # q1 == A + self.q1_label = q1_label + self.n_states = 2 ** 2 + self.ma_obj = ma.MeasurementAnalysis(auto=False, label=label, + timestamp=timestamp) + self.ma_obj.get_naming_and_values() + # self.get_naming_and_values() + # hard coded number of segments for a 2 qubit state tomography + # constraint imposed by UHFLI + # self.nr_segments = 16 + # self.exp_name = os.path.split(self.folder)[-1][7:] + + avg_h1 = self.ma_obj.measured_values[0] + avg_h2 = self.ma_obj.measured_values[1] + avg_h12 = self.ma_obj.measured_values[2] + + #this should be implemented with a flag + #but + h1_00 = np.mean(avg_h1[36:36+7]) + h1_01 = np.mean(avg_h1[43:43+7]) + h1_10 = np.mean(avg_h1[50:50+7]) + h1_11 = np.mean(avg_h1[57:]) + + h2_00 = np.mean(avg_h2[36:36+7]) + h2_01 = np.mean(avg_h2[43:43+7]) + h2_10 = np.mean(avg_h2[50:50+7]) + h2_11 = np.mean(avg_h2[57:]) + + h12_00 = np.mean(avg_h12[36:36+7]) + h12_01 = np.mean(avg_h12[43:43+7]) + h12_10 = np.mean(avg_h12[50:50+7]) + h12_11 = np.mean(avg_h12[57:]) + + + mean_h1 = (h1_00+h1_10+h1_01+h1_11)/4 + mean_h2 = (h2_00+h2_01+h2_10+h2_11)/4 + mean_h12 = (h12_00+h12_11+h12_01+h12_10)/4 + + #subtract beta 0 from all measurements + #rescale them + avg_h1 -= mean_h1 + avg_h2 -= mean_h2 + avg_h12 -= mean_h12 + + scale_h1 = (h1_00+h1_10-h1_01-h1_11)/4 + scale_h2 = (h2_00+h2_01-h2_10-h2_11)/4 + scale_h12 = (h12_00+h12_11-h12_01-h12_10)/4 + + avg_h1 = (avg_h1)/scale_h1 + avg_h2 = (avg_h2)/scale_h2 + avg_h12 = (avg_h12)/scale_h12 + #The averages have been redefined so redefine the cal terms + h1_00 = np.mean(avg_h1[36:36+7]) + h1_01 = np.mean(avg_h1[43:43+7]) + h1_10 = np.mean(avg_h1[50:50+7]) + h1_11 = np.mean(avg_h1[57:]) + + h2_00 = np.mean(avg_h2[36:36+7]) + h2_01 = np.mean(avg_h2[43:43+7]) + h2_10 = np.mean(avg_h2[50:50+7]) + h2_11 = np.mean(avg_h2[57:]) + + h12_00 = np.mean(avg_h12[36:36+7]) + h12_01 = np.mean(avg_h12[43:43+7]) + h12_10 = np.mean(avg_h12[50:50+7]) + h12_11 = np.mean(avg_h12[57:]) + + measurement_channel_1 = np.array([avg_h1[0],avg_h1[1],avg_h1[7],avg_h1[8],avg_h1[14],avg_h1[21],avg_h1[28],avg_h1[35]]) + measurement_channel_2 = np.array([avg_h2[0],avg_h2[1],avg_h2[7],avg_h2[8],avg_h2[14],avg_h2[21],avg_h2[28],avg_h2[35]]) + measurement_channel_3 = np.array([avg_h12[0],avg_h12[1],avg_h12[7],avg_h12[8],avg_h12[14],avg_h12[21],avg_h12[28],avg_h12[35]]) + self.measurements_tomo = np.array([measurement_channel_1,measurement_channel_2,measurement_channel_3]).flatten() + + # print(self.measurements_tomo) + # print(len(self.measurements_tomo)) + + # 108 x 1 + # get the calibration points by averaging over the five measurements + # taken knowing the initial state we put in + self.measurements_cal=np.array([h1_00, h1_01, h1_10, h1_11, h2_00, h2_01, h2_10, h2_11, h12_00, h12_01, h12_10, h12_11]) + + def _calibrate_betas(self): + """ + calculates betas from calibration points for the initial measurement + operator + + Betas are ordered by B0 -> II B1 -> IZ etc(binary counting) + <0|Z|0> = 1, <1|Z|1> = -1 + + Keyword arguments: + measurements_cal --- array(2 ** n_qubits) should be ordered + correctly (00, 01, 10, 11) for 2 qubits + """ + cal_matrix = np.zeros((self.n_states, self.n_states)) + # get the coefficient matrix for the betas + for i in range(self.n_states): + for j in range(self.n_states): + # perform bitwise AND and count the resulting 1s + cal_matrix[i, j] = (-1)**(bin((i & j)).count("1")) + # invert solve the simple system of equations + # print(cal_matrix) + # print(np.linalg.inv(cal_matrix)) + self.betas = np.zeros(12) + # print(self.measurements_cal[0:4]) + self.betas[0:4] = np.dot(np.linalg.inv(cal_matrix), + self.measurements_cal[0:4]) + self.betas_up = self.betas[0:4] + self.betas[4:8] = np.dot(np.linalg.inv(cal_matrix), + self.measurements_cal[4:8]) + self.betas_p = self.betas[4:8] + self.betas[8:] = np.dot(np.linalg.inv(cal_matrix), + self.measurements_cal[8:12]) + self.betas_pp = self.betas[8:] + return self.betas + + def assemble_M_matrix_single_block(self, beta_array): + M_matrix_single_block_row_1 = np.array([beta_array[1], + beta_array[2], beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_2 = np.array([-1*beta_array[1], + beta_array[2], + -1*beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_3 = np.array([beta_array[1], + -1*beta_array[2], + -1*beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_4 = np.array([-1*beta_array[1], + -1*beta_array[2], + beta_array[3], + 0, 0, 0, 0, 0, 0]) + M_matrix_single_block_row_5 = np.array([0, 0, 0, -beta_array[1], + -beta_array[2], + beta_array[3], 0, 0, 0]) + M_matrix_single_block_row_6 = np.array([0, 0, 0, + beta_array[1], + beta_array[2], + beta_array[3], + 0, 0, 0]) + M_matrix_single_block_row_7 = np.array([0, 0, + 0, 0, 0, 0, beta_array[1], + beta_array[2], + beta_array[3]]) + M_matrix_single_block_row_8 = np.array([0, 0, 0, 0, + 0, 0, -beta_array[1], + -beta_array[2], + beta_array[3]]) + M_matrix_single_block = np.vstack((M_matrix_single_block_row_1, + M_matrix_single_block_row_2, + M_matrix_single_block_row_3, + M_matrix_single_block_row_4, + M_matrix_single_block_row_5, + M_matrix_single_block_row_6, + M_matrix_single_block_row_7, + M_matrix_single_block_row_8)) + M_matrix_single_block = M_matrix_single_block.reshape(8, 9) + return M_matrix_single_block + + def assemble_M_matrix(self): + Block1 = self.assemble_M_matrix_single_block(self.betas_up) + Block2 = self.assemble_M_matrix_single_block(self.betas_p) + Block3 = self.assemble_M_matrix_single_block(self.betas_pp) + self.M_matrix = np.vstack((Block1, Block2, Block3)).reshape(24, 9) + + return self.M_matrix + + def invert_M_matrix(self): + self.inverse_matrix = np.linalg.pinv(self.M_matrix) + return self.inverse_matrix + + def execute_error_signalling(self, ev): + II = (ev[0] - ev[3])/(1 - ev[3]) + IZ = (ev[1] - ev[2])/(1 - ev[3]) + ZI = (ev[1] - ev[2])/(1 - ev[3]) + ZZ = (ev[3] - ev[0])/(1 - ev[3]) + XX = (ev[4] + ev[5])/(1 - ev[3]) + YY = (ev[4] + ev[5])/(1 - ev[3]) + ev_error_signalling = np.array([II, IZ, ZI, ZZ, XX, YY]) + return ev_error_signalling + + def execute_expectation_value_calculation_traceone(self): + # assemble matrix that connects RO with terms + self._calibrate_betas() + self.assemble_M_matrix() + self.inverse_matrix = np.linalg.pinv(self.M_matrix) + + # use it to get terms back from RO + rescaled_measurements_tomo = self.measurements_tomo + self.expect_values = np.dot(self.inverse_matrix, + rescaled_measurements_tomo) + expect_values_VQE = np.array([1, + self.expect_values[0], + self.expect_values[1], + self.expect_values[2], + self.expect_values[5], + self.expect_values[8]]) + return expect_values_VQE + + def execute_expectation_value_calculation_T1signaling(self): + # assemble matrix that connects RO with terms + self._calibrate_betas() + self.assemble_M_matrix() + self.inverse_matrix = np.linalg.pinv(self.M_matrix[:, 1:]) + # use it to get terms back from RO + rescaled_measurements_tomo = self.measurements_tomo + self.expect_values = np.dot(self.inverse_matrix, + rescaled_measurements_tomo) + expect_values_VQE = np.array([1, + self.expect_values[0], + self.expect_values[1], + self.expect_values[2], + self.expect_values[5], + self.expect_values[8]]) + expect_values_VQE = self.execute_error_signalling(expect_values_VQE) + return expect_values_VQE \ No newline at end of file diff --git a/pycqed/analysis_v2/VQE_cost_functions.py b/pycqed/analysis_v2/VQE_cost_functions.py new file mode 100644 index 0000000000..d8ee346ed0 --- /dev/null +++ b/pycqed/analysis_v2/VQE_cost_functions.py @@ -0,0 +1,46 @@ +import numpy as np +import sys +sys.path.append('D:/repository/PycQED_py3') + + +class VQE_cost_functions(object): + + def __init__(self, + path_file, + expect_values): + """ + Class is instantiated with the hydrogen data path file and measured expectation values. + The expectation values are in the following order II, IZ, ZI, ZZ, XX, YY + + """ + self.path_file = path_file + self.hydrogen_data = np.loadtxt(self.path_file, unpack=False) + self.interatomic_distances = self.hydrogen_data[:, 0] + self.weight_of_pauli_terms = self.hydrogen_data[:, 1:7] + self.expect_values = expect_values + + def cost_function_bare_VQE(self, distance_index): + cost_func_bare = np.dot( + self.expect_values, self.weight_of_pauli_terms[distance_index, :]) + return cost_func_bare + + def get_pauli_ops(self): + X = np.array([[0, 1], [1, 0]]) + Y = np.array([[0, -1j], [1j, 0]]) + Z = np.array([[1, 0], [0, -1]]) + I = np.identity(2) + II = np.kron(I, I) + IZ = np.kron(I, Z) + ZI = np.kron(Z, I) + ZZ = np.kron(Z, Z) + XX = np.kron(X, X) + YY = np.kron(Y, Y) + return II, IZ, ZI, ZZ, XX, YY + + def get_hamiltonian(self, distance_index): + terms = self.get_pauli_ops() + gs = self.weight_of_pauli_terms[distance_index, :] + ham = np.zeros((4,4), dtype=np.complex128) + for i,g in enumerate(gs): + ham += g*terms[i] + return ham \ No newline at end of file diff --git a/pycqed/analysis_v2/base_analysis.py b/pycqed/analysis_v2/base_analysis.py index 7b1afb7e71..08e811d181 100644 --- a/pycqed/analysis_v2/base_analysis.py +++ b/pycqed/analysis_v2/base_analysis.py @@ -1,11 +1,12 @@ """ File containing the BaseDataAnalyis class. """ +from inspect import signature import os import numpy as np import copy from collections import OrderedDict - +from inspect import signature import numbers from matplotlib import pyplot as plt from pycqed.analysis import analysis_toolbox as a_tools @@ -21,6 +22,8 @@ import lmfit import h5py from pycqed.measurement.hdf5_data import write_dict_to_hdf5 +import copy + class BaseDataAnalysis(object): """ @@ -45,14 +48,22 @@ class BaseDataAnalysis(object): self.prepare_plots() # specify default plots if not self.extract_only: self.plot(key_list='auto') # make the plots + """ - def __init__(self, t_start: str=None, t_stop: str=None, - label: str='', - data_file_path: str=None, - close_figs: bool=True, - options_dict: dict=None, extract_only: bool=False, - do_fitting: bool=False): + fit_res = None + ''' + Dictionary containing fitting objects + ''' + fit_dict = None + ''' + Dictionary containing fitting results + ''' + + def __init__(self, t_start: str = None, t_stop: str = None, + label: str = '', data_file_path: str = None, + close_figs: bool = True, options_dict: dict = None, + extract_only: bool = False, do_fitting: bool = False): ''' This is the __init__ of the abstract base class. It is intended to be called at the start of the init of the child @@ -66,6 +77,7 @@ def __init__(self, t_start: str=None, t_stop: str=None, - specify options specific to that analysis - call self.run_analysis + This method sets several attributes of the analysis class. These include assigning the arguments of this function to attributes. Other arguments that get created are @@ -79,17 +91,39 @@ def __init__(self, t_start: str=None, t_stop: str=None, There are several ways to specify where the data should be loaded from. - data_file_path: directly give the file path of a data file that - should be loaded. - t_start, t_stop: give a range of timestamps in where data is - loaded from. Filtering options can be given through the - options dictionary. If t_stop is omitted, the extraction - routine looks for the data with time stamp t_start. - none of the above: look for the last data which matches the + + none of the below parameters: look for the last data which matches the filtering options from the options dictionary. - Note: data_file_path has priority, i.e. if this argument is given - time stamps are ignored. + + :param t_start, t_stop: give a range of timestamps in where data is + loaded from. Filtering options can be given + through the options dictionary. If t_stop is + omitted, the extraction routine looks for + the data with time stamp t_start. + :param label: Only process datasets with this label. + :param data_file_path: directly give the file path of a data file that + should be loaded. Note: data_file_path has + priority, i.e. if this argument is given time + stamps are ignored. + :param close_figs: Close the figure (do not display) + :param options_dict: available options are: + -'presentation_mode' + -'tight_fig' + -'plot_init' + -'save_figs' + -'close_figs' + -'verbose' + -'auto-keys' + -'twoD' + -'ma_type' + -'scan_label' + -'do_individual_traces' + -'filter_no_analysis' + -'exact_label_match' + :param extract_only: Should we also do the plots? + :param do_fitting: Should the run_fitting method be executed? ''' + # todo: what exactly does this flag do? May 2018 (Adriaan/Rene) self.single_timestamp = False # initialize an empty dict to store results of analysis self.proc_data_dict = OrderedDict() @@ -177,19 +211,18 @@ def run_analysis(self): This function is at the core of all analysis and defines the flow. This function is typically called after the __init__. """ - self.extract_data() # extract data specified in params dict - self.process_data() # binning, filtering etc + self.extract_data() # extract data specified in params dict + self.process_data() # binning, filtering etc if self.do_fitting: - self.prepare_fitting() # set up fit_dicts - self.run_fitting() # fitting to models + self.prepare_fitting() # set up fit_dicts + self.run_fitting() # fitting to models self.save_fit_results() self.analyze_fit_results() # analyzing the results of the fits - self.prepare_plots() # specify default plots + self.prepare_plots() # specify default plots if not self.extract_only: self.plot(key_list='auto') # make the plots - if self.options_dict.get('save_figs', False): self.save_figures(close_figs=self.options_dict.get('close_figs', False)) @@ -218,9 +251,6 @@ def get_timestamps(self): label=self.labels, exact_label_match=self.exact_label_match) - if self.verbose: - print(len(self.timestamps), type(self.timestamps[0])) - if len(np.ravel(self.timestamps)) < 1: raise ValueError( "No timestamps in range! Check the labels and other filters.") @@ -322,7 +352,6 @@ def extract_data_json(self): # self.raw_data_dict.items()] self.raw_data_dict['timestamps'] = [self.t_start] - def process_data(self): """ process_data: overloaded in child classes, @@ -344,38 +373,48 @@ def analyze_fit_results(self): """ pass - def save_figures(self, savedir: str=None, savebase: str =None, - tag_tstamp: bool=True, - fmt: str ='png', key_list: list='auto', - close_figs: bool=True): + def save_figures(self, savedir: str = None, savebase: str = None, + tag_tstamp: bool = True, + fmt: str = 'png', key_list: list = 'auto', + close_figs: bool = True): if savedir is None: savedir = self.raw_data_dict.get('folder', '') if isinstance(savedir, list): savedir = savedir[0] + if savebase is None: savebase = '' if tag_tstamp: - tstag = '_'+self.raw_data_dict['timestamps'][0] + tstag = '_' + self.raw_data_dict['timestamps'][0] else: tstag = '' if key_list == 'auto' or key_list is None: key_list = self.figs.keys() + + try: + os.mkdir(savedir) + except FileExistsError: + pass + + if self.verbose: + print('Saving figures to %s' % savedir) + for key in key_list: if self.presentation_mode: - savename = os.path.join(savedir, savebase+key+tstag+'presentation'+'.'+fmt) + savename = os.path.join(savedir, savebase + key + tstag + 'presentation' + '.' + fmt) self.figs[key].savefig(savename, bbox_inches='tight', fmt=fmt) - savename = os.path.join(savedir, savebase+key+tstag+'presentation'+'.svg') + savename = os.path.join(savedir, savebase + key + tstag + 'presentation' + '.svg') self.figs[key].savefig(savename, bbox_inches='tight', fmt='svg') else: - savename = os.path.join(savedir, savebase+key+tstag+'.'+fmt) + savename = os.path.join(savedir, savebase + key + tstag + '.' + fmt) self.figs[key].savefig(savename, bbox_inches='tight', fmt=fmt) if close_figs: plt.close(self.figs[key]) - def save_data(self, savedir: str=None, savebase: str=None, - tag_tstamp: bool=True, - fmt: str='json', key_list='auto'): + def save_data(self, savedir: str = None, savebase: str = None, + tag_tstamp: bool = True, + fmt: str = 'json', key_list='auto'): ''' Saves the data from self.raw_data_dict to file. @@ -404,7 +443,7 @@ def save_data(self, savedir: str=None, savebase: str=None, if savebase is None: savebase = '' if tag_tstamp: - tstag = '_'+self.raw_data_dict['timestamps'][0] + tstag = '_' + self.raw_data_dict['timestamps'][0] else: tstag = '' @@ -415,7 +454,14 @@ def save_data(self, savedir: str=None, savebase: str=None, for k in key_list: save_dict[k] = self.raw_data_dict[k] + try: + os.mkdir(savedir) + except FileExistsError: + pass + filepath = os.path.join(savedir, savebase + tstag + '.' + fmt) + if self.verbose: + print('Saving raw data to %s' % filepath) with open(filepath, 'w') as file: json.dump(save_dict, file, cls=NumpyJsonEncoder, indent=4) print('Data saved to "{}".'.format(filepath)) @@ -435,6 +481,7 @@ def run_fitting(self): for key, fit_dict in self.fit_dicts.items(): guess_dict = fit_dict.get('guess_dict', None) guess_pars = fit_dict.get('guess_pars', None) + guessfn_pars = fit_dict.get('guessfn_pars', {}) fit_yvals = fit_dict['fit_yvals'] fit_xvals = fit_dict['fit_xvals'] @@ -443,14 +490,14 @@ def run_fitting(self): fit_fn = fit_dict.get('fit_fn', None) model = fit_dict.get('model', lmfit.Model(fit_fn)) fit_guess_fn = fit_dict.get('fit_guess_fn', None) - if fit_guess_fn is None: + if fit_guess_fn is None and fit_dict.get('fit_guess', True): fit_guess_fn = model.guess if guess_pars is None: if fit_guess_fn is not None: # a fit function should return lmfit parameter objects # but can also work by returning a dictionary of guesses - guess_pars = fit_guess_fn(**fit_yvals, **fit_xvals) + guess_pars = fit_guess_fn(**fit_yvals, **fit_xvals, **guessfn_pars) if not isinstance(guess_pars, lmfit.Parameters): for gd_key, val in list(guess_pars.items()): model.set_param_hint(gd_key, **val) @@ -464,13 +511,12 @@ def run_fitting(self): # A guess can also be specified as a dictionary. # additionally this can be used to overwrite values # from the guess functions. - else: + elif guess_dict is not None: for key, val in list(guess_dict.items()): model.set_param_hint(key, **val) guess_pars = model.make_params() - - fit_dict['fit_res'] = model.fit( - params=guess_pars, **fit_xvals, **fit_yvals) + fit_dict['fit_res'] = model.fit(**fit_xvals, **fit_yvals, + params=guess_pars) self.fit_res[key] = fit_dict['fit_res'] @@ -480,16 +526,27 @@ def save_fit_results(self): """ # Check weather there is any data to save - if self.fit_res is not None and self.fit_res: - fn = a_tools.measurement_filename(a_tools.get_folder(self.timestamps[0])) - with h5py.File(fn, 'r+') as data_file: + if hasattr(self, 'fit_res') and self.fit_res is not None: + fn = self.options_dict.get('analysis_result_file', False) + if fn == False: + fn = a_tools.measurement_filename(a_tools.get_folder(self.timestamps[0])) + + try: + os.mkdir(os.path.dirname(fn)) + except FileExistsError: + pass + + if self.verbose: + print('Saving fitting results to %s' % fn) + + with h5py.File(fn, 'a') as data_file: try: analysis_group = data_file.create_group('Analysis') except ValueError: # If the analysis group already exists. analysis_group = data_file['Analysis'] - # Iterate over all the fit result dicts + # Iterate over all the fit result dicts as not to overwrite old/other analysis for fr_key, fit_res in self.fit_res.items(): try: fr_group = analysis_group.create_group(fr_key) @@ -499,10 +556,36 @@ def save_fit_results(self): del analysis_group[fr_key] fr_group = analysis_group.create_group(fr_key) - # TODO: convert the params object to a simple dict - # write_dict_to_hdf5(fit_res.params, entry_point=fr_group) - write_dict_to_hdf5(fit_res.best_values, entry_point=fr_group) - + d = self._convert_dict_rec(copy.deepcopy(fit_res)) + write_dict_to_hdf5(d, entry_point=fr_group) + + @staticmethod + def _convert_dict_rec(obj): + try: + # is iterable? + for k in obj: + obj[k] = BaseDataAnalysis._convert_dict_rec(obj[k]) + except TypeError: + if isinstance(obj, lmfit.model.ModelResult): + obj = BaseDataAnalysis._flatten_lmfit_modelresult(obj) + else: + obj = str(obj) + return obj + + @staticmethod + def _flatten_lmfit_modelresult(model): + assert type(model) is lmfit.model.ModelResult + dic = OrderedDict() + dic['success'] = model.success + dic['message'] = model.message + dic['params'] = {} + for param_name in model.params: + dic['params'][param_name] = {} + param = model.params[param_name] + for k in param.__dict__: + if not k.startswith('_') and k not in ['from_internal', ]: + dic['params'][param_name][k] = getattr(param, k) + return dic def plot(self, key_list=None, axs_dict=None, presentation_mode=None, no_label=False): @@ -538,7 +621,8 @@ def plot(self, key_list=None, axs_dict=None, pdict.get('numplotsy', 1), pdict.get('numplotsx', 1), sharex=pdict.get('sharex', False), sharey=pdict.get('sharey', False), - figsize=pdict.get('plotsize', None) #plotsize None uses .rc_default of matplotlib + figsize=pdict.get('plotsize', None) + # plotsize None uses .rc_default of matplotlib ) # transparent background around axes for presenting data @@ -549,9 +633,6 @@ def plot(self, key_list=None, axs_dict=None, else: for key in key_list: pdict = self.plot_dicts[key] - - plot_id_y = pdict.get('plot_id_y', None) - plot_id_x = pdict.get('plot_id_x', None) plot_touching = pdict.get('touching', False) if type(pdict['plotfn']) is str: @@ -561,15 +642,24 @@ def plot(self, key_list=None, axs_dict=None, # used to ensure axes are touching if plot_touching: - self.axs[pdict['ax_id']].figure.subplots_adjust(wspace=0, hspace=0) - - # ensures the argument convention is preserved - if hasattr(self, plotfn.__name__): - plotfn(pdict, axs=self.axs[pdict['ax_id']]) - else: + self.axs[pdict['ax_id']].figure.subplots_adjust(wspace=0, + hspace=0) + + # Check if pdict is one of the accepted arguments, these are + # the plotting functions in the analysis base class. + if 'pdict' in signature(plotfn).parameters: + plotfn(pdict=pdict, axs=self.axs[pdict['ax_id']]) + + # most normal plot functions also work, it is required + # that these accept an "ax" argument to plot on and **kwargs + # the pdict is passed in as kwargs to such a function + elif 'ax' in signature(plotfn).parameters: # Calling the function passing along anything # defined in the specific plot dict as kwargs plotfn(ax=self.axs[pdict['ax_id']], **pdict) + else: + raise ValueError( + '"{}" is not a valid plot function'.format(plotfn)) self.format_datetime_xaxes(key_list) self.add_to_plots(key_list=key_list) @@ -614,15 +704,15 @@ def plot_bar(self, pdict, axs): do_legend = pdict.get('do_legend', False) plot_touching = pdict.get('touching', False) - plot_xwidth = (plot_xedges[1:]-plot_xedges[:-1]) + plot_xwidth = (plot_xedges[1:] - plot_xedges[:-1]) # center is left edge + widht /2 - plot_centers = plot_xedges[:-1] + plot_xwidth/2 + plot_centers = plot_xedges[:-1] + plot_xwidth / 2 if plot_multiple: p_out = [] for ii, this_yvals in enumerate(plot_yvals): p_out.append(pfunc(plot_centers, this_yvals, width=plot_xwidth, - color=gco(ii, len(plot_yvals)-1), + color=gco(ii, len(plot_yvals) - 1), label='%s%s' % (dataset_desc, dataset_label[ii]), **plot_barkws)) @@ -666,6 +756,19 @@ def plot_line(self, pdict, axs): Takes either an x and y array or a list of x and y arrays. Detection happens based on types of the data """ + + # if a y or xerr is specified, used the errorbar-function + plot_linekws = pdict.get('line_kws', {}) + xerr = pdict.get('xerr', None) + yerr = pdict.get('yerr', None) + if xerr is not None or yerr is not None: + pdict['func'] = pdict.get('func', 'errorbar') + if yerr is not None: + plot_linekws['yerr'] = plot_linekws.get('yerr', yerr) + if xerr is not None: + plot_linekws['xerr'] = plot_linekws.get('xerr', xerr) + + pdict['line_kws'] = plot_linekws pfunc = getattr(axs, pdict.get('func', 'plot')) plot_xvals = pdict['xvals'] plot_yvals = pdict['yvals'] @@ -676,7 +779,8 @@ def plot_line(self, pdict, axs): plot_title = pdict.get('title', None) plot_xrange = pdict.get('xrange', None) plot_yrange = pdict.get('yrange', None) - plot_linekws = pdict.get('line_kws', {}) + if pdict.get('color', False): + plot_linekws['color'] = pdict.get('color') # plot_multiple = pdict.get('multiple', False) plot_linestyle = pdict.get('linestyle', '-') @@ -694,8 +798,8 @@ def plot_line(self, pdict, axs): plot_multiple = False else: plot_multiple = True - assert(len(plot_xvals) == len(plot_yvals)) - assert(len(plot_xvals[0]) == len(plot_yvals[0])) + assert (len(plot_xvals) == len(plot_yvals)) + assert (len(plot_xvals[0]) == len(plot_yvals[0])) if plot_multiple: p_out = [] @@ -772,25 +876,25 @@ def plot_yslices(self, pdict, axs): plot_xrange = pdict.get('xrange', None) plot_yrange = pdict.get('yrange', None) - plot_xvals_step = plot_xvals[1]-plot_xvals[0] + plot_xvals_step = plot_xvals[1] - plot_xvals[0] for ii, idx in enumerate(slice_idxs): if len(slice_idxs) == 1: pfunc(plot_xvals, plot_yvals[idx], '-bo', label='%s = %.2f %s' % ( - slice_label, plot_slicevals[idx], slice_units)) + slice_label, plot_slicevals[idx], slice_units)) else: - if ii == 0 or ii == len(slice_idxs)-1: + if ii == 0 or ii == len(slice_idxs) - 1: pfunc(plot_xvals, plot_yvals[idx], '-o', - color=gco(ii, len(slice_idxs)-1), + color=gco(ii, len(slice_idxs) - 1), label='%s = %.2f %s' % ( - slice_label, plot_slicevals[idx], slice_units)) + slice_label, plot_slicevals[idx], slice_units)) else: pfunc(plot_xvals, plot_yvals[idx], '-o', - color=gco(ii, len(slice_idxs)-1)) + color=gco(ii, len(slice_idxs) - 1)) if plot_xrange is None: - xmin, xmax = np.min(plot_xvals)-plot_xvals_step / \ - 2., np.max(plot_xvals)+plot_xvals_step/2. + xmin, xmax = np.min(plot_xvals) - plot_xvals_step / \ + 2., np.max(plot_xvals) + plot_xvals_step / 2. else: xmin, xmax = plot_xrange axs.set_xlim(xmin, xmax) @@ -905,7 +1009,7 @@ def plot_color2D(self, pfunc, pdict, axs): plot_normalize = pdict.get('normalize', False) plot_logzscale = pdict.get('logzscale', False) if plot_logzscale: - plot_zvals = np.log10(pdict['zvals']/plot_logzscale) + plot_zvals = np.log10(pdict['zvals'] / plot_logzscale) else: plot_zvals = pdict['zvals'] @@ -913,10 +1017,10 @@ def plot_color2D(self, pfunc, pdict, axs): plot_xvals_step = 0 plot_yvals_step = 0 else: - plot_xvals_step = (abs(np.max(plot_xvals)-np.min(plot_xvals))/ - len(plot_xvals)) - plot_yvals_step = (abs(np.max(plot_yvals)-np.min(plot_yvals))/ - len(plot_yvals)) + plot_xvals_step = (abs(np.max(plot_xvals) - np.min(plot_xvals)) / + len(plot_xvals)) + plot_yvals_step = (abs(self._globalmax(plot_yvals) - self._globalmin(plot_yvals)) / + len(plot_yvals)) # plot_yvals_step = plot_yvals[1]-plot_yvals[0] if plot_zrange is not None: @@ -961,13 +1065,13 @@ def plot_color2D(self, pfunc, pdict, axs): if plot_xrange is None: if plot_xwidth is not None: - xmin, xmax = min([min(xvals)-plot_xwidth[tt]/2 + xmin, xmax = min([min(xvals) - plot_xwidth[tt] / 2 for tt, xvals in enumerate(plot_xvals)]), \ - max([max(xvals)+plot_xwidth[tt]/2 - for tt, xvals in enumerate(plot_xvals)]) + max([max(xvals) + plot_xwidth[tt] / 2 + for tt, xvals in enumerate(plot_xvals)]) else: - xmin = np.min(plot_xvals) - plot_xvals_step/2 - xmax = np.max(plot_xvals) + plot_xvals_step/2 + xmin = np.min(plot_xvals) - plot_xvals_step / 2 + xmax = np.max(plot_xvals) + plot_xvals_step / 2 else: xmin, xmax = plot_xrange if plot_transpose: @@ -988,8 +1092,8 @@ def plot_color2D(self, pfunc, pdict, axs): ymin = min(ymin_list) ymax = max(ymax_list) else: - ymin = np.min(plot_yvals) - plot_yvals_step / 2. - ymax = np.max(plot_yvals) + plot_yvals_step/2. + ymin = self._globalmin(plot_yvals) - plot_yvals_step / 2. + ymax = self._globalmax(plot_yvals) + plot_yvals_step / 2. else: ymin, ymax = plot_yrange if plot_transpose: @@ -1010,7 +1114,7 @@ def label_color2D(self, pdict, axs): plot_xunit = pdict['xunit'] plot_ylabel = pdict['ylabel'] plot_yunit = pdict['yunit'] - plot_title = pdict['title'] + plot_title = pdict.get('title', None) if plot_transpose: # transpose switches X and Y set_xlabel(axs, plot_ylabel, plot_yunit) @@ -1140,3 +1244,123 @@ def plot_matplot_ax_method(self, pdict, axs): """ pfunc = getattr(axs, pdict.get('func')) pfunc(**pdict['plot_kws']) + + @staticmethod + def _sort_by_axis0(arr, sorted_indices, type=None): + ''' + Sorts the array (possibly a list of unequally long lists) by a list of indicies + :param arr: array (possibly a list of unequally long lists) + :param sorted_indices: list of indicies + :param type: the datatype of the contained values + :return: Sorted array + ''' + if type is None: + return [np.array(arr[i]) for i in sorted_indices] + else: + return [np.array(arr[i], dtype=type) for i in sorted_indices] + + @staticmethod + def _globalmin(array): + ''' + Gives the global minimum of an array (possibly a list of unequally long lists) + :param array: array (possibly a list of unequally long lists) + :return: Global minimum + ''' + return np.min([np.min(v) for v in array]) + + @staticmethod + def _globalmax(array): + ''' + Gives the global maximum of an array (possibly a list of unequally long lists) + :param array: array (possibly a list of unequally long lists) + :return: Global maximum + ''' + return np.max([np.max(v) for v in array]) + + def plot_vlines_auto(self, pdict, axs): + xs = pdict.get('xdata') + for i,x in enumerate(xs): + d = {} + for k in pdict: + lk = k[:-1] + #if lk in signature(axs.axvline).parameters: + if k not in ['xdata', 'plotfn', 'ax_id', 'do_legend']: + try: + d[lk] = pdict[k][i] + except: + pass + axs.axvline(x=x, **d) + + +def plot_scatter_errorbar(self, ax_id, xdata, ydata, xerr=None, yerr=None, pdict=None): + pdict = pdict or {} + + pds = { + 'ax_id': ax_id, + 'plotfn': self.plot_line, + 'zorder': 10, + 'xvals': xdata, + 'yvals': ydata, + 'marker': 'x', + 'linestyle': 'None', + 'yerr': yerr, + 'xerr': xerr, + } + + if xerr is not None or yerr is not None: + pds['func'] = 'errorbar' + pds['marker'] = None + pds['line_kws'] = {'fmt': 'none'} + if pdict.get('marker', False): + pds['line_kws'] = {'fmt': pdict['marker']} + else: + ys = 0 if yerr is None else np.min(yerr) / np.max(ydata) + xs = 0 if xerr is None else np.min(xerr) / np.max(xdata) + if ys < 1e-2 and xs < 1e-2: + pds['line_kws'] = {'fmt': 'o'} + else: + pds['func'] = 'scatter' + + pds = _merge_dict_rec(pds, pdict) + + return pds + + +def plot_scatter_errorbar_fit(self, ax_id, xdata, ydata, fitfunc, xerr=None, yerr=None, fitextra=0.1, + fitpoints=1000, pdict_scatter=None, pdict_fit=None): + pdict_fit = pdict_fit or {} + pds = plot_scatter_errorbar(self=self, ax_id=ax_id, xdata=xdata, ydata=ydata, xerr=xerr, yerr=yerr, + pdict=pdict_scatter) + + mi, ma = np.min(xdata), np.max(xdata) + ex = (ma - mi) * fitextra + xdata_fit = np.linspace(mi - ex, ma + ex, fitpoints) + ydata_fit = fitfunc(xdata_fit) + + pdf = { + 'ax_id': ax_id, + 'zorder': 5, + 'plotfn': self.plot_line, + 'xvals': xdata_fit, + 'yvals': ydata_fit, + 'linestyle': '-', + 'marker': '', + } + + pdf = _merge_dict_rec(pdf, pdict_fit) + + return pds, pdf + + +def _merge_dict_rec(dict_a: dict, dict_b: dict): + for k in dict_a: + if k in dict_b: + if dict_a[k] is dict or dict_b[k] is dict: + a = dict_a[k] or {} + dict_a[k] = _merge_dict_rec(a, dict_b[k]) + else: + dict_a[k] = dict_b[k] + for k in dict_b: + if k not in dict_a: + dict_a[k] = dict_b[k] + return dict_a diff --git a/pycqed/analysis_v2/coherence_analysis.py b/pycqed/analysis_v2/coherence_analysis.py new file mode 100644 index 0000000000..384abd30a9 --- /dev/null +++ b/pycqed/analysis_v2/coherence_analysis.py @@ -0,0 +1,864 @@ +''' +Hacked together by Rene Vollmer +''' + +import datetime +import pycqed.analysis_v2.base_analysis as ba +from pycqed.analysis_v2.base_analysis import plot_scatter_errorbar_fit, plot_scatter_errorbar + +import numpy as np +import lmfit + +from pycqed.analysis import analysis_toolbox as a_tools + + +class CoherenceTimesAnalysisSingle(ba.BaseDataAnalysis): + # todo docstring + def __init__(self, t_start: str = None, t_stop: str = None, + label: str = '', + options_dict: dict = None, extract_only: bool = False, auto: bool = True, + close_figs: bool = True, do_fitting: bool = True, + tau_key='Analysis.Fitted Params F|1>.tau.value', + tau_std_key='Analysis.Fitted Params F|1>.tau.stderr', + plot_versus_dac=True, + dac_key='Instrument settings.fluxcurrent.Q', + plot_versus_frequency=True, + frequency_key='Instrument settings.Q.freq_qubit', + ): + ''' + Plots and Analyses the coherence time (e.g. T1, T2 OR T2*) of one measurement series. + + :param t_start: start time of scan as a string of format YYYYMMDD_HHmmss + :param t_stop: end time of scan as a string of format YYYYMMDD_HHmmss + :param label: the label that was used to name the measurements (only necessary if non-relevant measurements are in the time range) + :param options_dict: Available options are the ones from the base_analysis and: + - (todo) + :param auto: Execute all steps automatically + :param close_figs: Close the figure (do not display) + :param extract_only: Should we also do the plots? + :param do_fitting: Should the run_fitting method be executed? + :param tau_key: key for the tau (time) fit result, e.g. 'Analysis.Fitted Params F|1>.tau.value' + :param tau_std_key: key for the tau (time) standard deviation fit result, + e.g. 'Analysis.Fitted Params F|1>.tau.stderr' + :param plot_versus_dac: Extract and plot dac value? + E.g. set False if you did not vary the dac for this measurement. + :param dac_key: key for the dac current values, e.g. 'Instrument settings.fluxcurrent.Q' + :param plot_versus_frequency: Extract and plot frequency value? + E.g. set False if you did not use the Qubit object. + :param frequency_key: key for the dac current values, e.g. 'Instrument settings.Q.freq_qubit' + ''' + super().__init__(t_start=t_start, t_stop=t_stop, + label=label, + options_dict=options_dict, + do_fitting=do_fitting, + close_figs=close_figs, + extract_only=extract_only) + # self.single_timestamp = False + self.params_dict = {'tau': tau_key, + 'tau_stderr': tau_std_key, + } + self.numeric_params = ['tau', 'tau_stderr'] + + self.plot_versus_dac = plot_versus_dac + if plot_versus_dac: + self.params_dict['dac'] = dac_key + + self.plot_versus_frequency = plot_versus_frequency + if plot_versus_frequency: + self.params_dict['qfreq'] = frequency_key + + self.numeric_params = [] + + if auto: + self.run_analysis() + + def extract_data(self): + # load data + super().extract_data() + tau = np.array(self.raw_data_dict['tau'], dtype=float) + tau_std = np.array(self.raw_data_dict['tau_stderr'], dtype=float) + # sort data + + if self.plot_versus_dac: + dacs = np.array(self.raw_data_dict['dac'], dtype=float) + sorted_indices = dacs.argsort() + self.raw_data_dict['dac_sorted'] = dacs[sorted_indices] + self.raw_data_dict['dac_sorted_tau'] = tau[sorted_indices] + self.raw_data_dict['dac_sorted_tau_stderr'] = tau_std[sorted_indices] + if self.plot_versus_frequency: + freqs = np.array(self.raw_data_dict['qfreq'], dtype=float) + self.raw_data_dict['dac_sorted_freq'] = freqs[sorted_indices] + + if self.plot_versus_frequency: + freqs = np.array(self.raw_data_dict['qfreq'], dtype=float) + sorted_indices = freqs.argsort() + self.raw_data_dict['freq_sorted'] = freqs[sorted_indices] + self.raw_data_dict['freq_sorted_tau'] = tau[sorted_indices] + self.raw_data_dict['freq_sorted_tau_stderr'] = tau_std[sorted_indices] + if self.plot_versus_dac: + freqs = np.array(self.raw_data_dict['dac'], dtype=float) + self.raw_data_dict['freq_sorted_dac'] = freqs[sorted_indices] + + def run_fitting(self): + # This is not the proper way to do this! + # TODO: move this to prepare_fitting + if hasattr(self, 'raw_data_dict'): + self.fit_res = {} + if self.plot_versus_dac and self.plot_versus_frequency: + dac = self.raw_data_dict['dac_sorted'] + freq = self.raw_data_dict['dac_sorted_freq'] + # dac = self.raw_data_dict['freq_sorted_dac'] + # freq = self.raw_data_dict['freq_sorted'] + # Extract the dac arcs required for getting the sensitivities + fit_object = fit_frequencies(dac=dac, freq=freq) + self.fit_res['dac_arc_object'] = fit_object + self.fit_res['dac_arc_fitfct'] = lambda x: fit_object.model.eval(fit_object.params, dac=x) + + # convert dac in flux as unit of Phi_0 + flux = (dac - fit_object.best_values['offset']) / fit_object.best_values['dac0'] + self.fit_res['flux_values'] = flux + + # calculate the derivative vs flux + sensitivity_angular = partial_omega_over_flux(flux, fit_object.best_values['Ec'], + fit_object.best_values['Ej']) + self.fit_res['Ec'] = fit_object.best_values['Ec'] + self.fit_res['Ej'] = fit_object.best_values['Ej'] + self.fit_res['sensitivity_values'] = sensitivity_angular / (2 * np.pi) + if self.verbose: + # todo: print EC and EJ + pass + else: + print('Warning: first run extract_data!') + + def save_fit_results(self): + # todo: if you want to save some results to a hdf5, do it here + pass + + def prepare_plots(self): + if not ("time_stability" in self.plot_dicts): + self._prepare_plot(ax_id='time_stability', xvals=self.raw_data_dict['datetime'], + yvals=self.raw_data_dict['tau'], yerr=self.raw_data_dict['tau_stderr'], + xlabel='Time in Delft', xunit=None) + if self.plot_versus_frequency: + self._prepare_plot(ax_id='freq_relation', xvals=self.raw_data_dict['freq_sorted'], + yvals=self.raw_data_dict['freq_sorted_tau'], + yerr=self.raw_data_dict['freq_sorted_tau_stderr'], + xlabel='Qubit Frequency', xunit='Hz') + + if self.plot_versus_dac: + # dac vs frequency (with fit if possible) + plot_dict = { + 'xlabel': 'DAC Current', 'xunit': 'A', + 'ylabel': 'Qubit Frequency', 'yunit': 'Hz', + } + if hasattr(self, 'fit_res'): + pds, pdf = plot_scatter_errorbar_fit(self=self, ax_id='dac_freq_relation', + xdata=self.raw_data_dict['dac_sorted'], + ydata=self.raw_data_dict['dac_sorted_freq'], + fitfunc=self.fit_res['dac_arc_fitfct'], + pdict_scatter=plot_dict, pdict_fit=plot_dict) + self.plot_dicts["dac_freq_relation_scatter"] = pds + self.plot_dicts["dac_freq_relation_fit"] = pdf + else: + pds = plot_scatter_errorbar(self=self, ax_id='dac_freq_relation', + xdata=self.raw_data_dict['dac_sorted'], + ydata=self.raw_data_dict['dac_sorted_freq'], + pdict=plot_dict) + self.plot_dicts["dac_freq_relation"] = pds + + # coherence time vs dac + self._prepare_plot(ax_id="dac_relation", xvals=self.raw_data_dict['dac_sorted'], + yvals=self.raw_data_dict['dac_sorted_tau'], + yerr=self.raw_data_dict['dac_sorted_tau_stderr'], + xlabel='DAC Value', xunit='A') + + if hasattr(self, 'fit_res'): + if 'sensitivity_values' in self.fit_res: + # sensitivity vs tau + self._prepare_plot(ax_id="sensitivity_relation", + xvals=self.fit_res['sensitivity_values'] * 1e-9, + yvals=self.raw_data_dict['dac_sorted_tau'], + yerr=self.raw_data_dict['dac_sorted_tau_stderr'], + xlabel=r'Sensitivity $|\partial\nu/\partial\Phi|$', + xunit=r'GHz/$\Phi_0$') + if 'flux_values' in self.fit_res: + # flux vs tau + self._prepare_plot(ax_id="flux_relation", + xvals=self.fit_res['flux_values'], + yvals=self.raw_data_dict['dac_sorted_tau'], + yerr=self.raw_data_dict['dac_sorted_tau_stderr'], + xlabel='Flux Value', xunit='$\Phi_0$') + + def _prepare_plot(self, ax_id, xvals, yvals, xlabel, xunit, yerr=None): + plot_dict = { + 'xlabel': xlabel, + 'xunit': xunit, + 'ylabel': 'Coherence', + 'yrange': (0, 1.1 * np.max(yvals)), + 'yunit': 's', + # 'marker': 'x', + # 'setlabel': setlabel, + # 'legend_title': legend_title, + # 'title': (self.raw_data_dict['timestamps'][0]+' - ' + + # self.raw_data_dict['timestamps'][-1] + '\n' + + # self.raw_data_dict['measurementstring'][0]), + # 'do_legend': do_legend, + # 'legend_pos': 'upper right' + } + + self.plot_dicts[ax_id] = plot_scatter_errorbar(self=self, ax_id=ax_id, xdata=xvals, ydata=yvals, + xerr=None, yerr=yerr, pdict=plot_dict) + + +class CoherenceTimesAnalysis(ba.BaseDataAnalysis): + T1 = 't1' + T2 = 't2' # e.g. echo + T2_star = 't2s' # e.g. ramsey + + def __init__(self, dac_instr_names: list, qubit_instr_names: list, + t_start: str = None, t_stop: str = None, + label: str = '', labels=None, + options_dict: dict = None, extract_only: bool = False, + auto: bool = True, + tau_keys: dict = None, + tau_std_keys: dict = None, + plot_versus_dac: bool = True, + dac_key_pattern: str = 'Instrument settings.fluxcurrent.{DAC}', + plot_versus_frequency: bool = True, + frequency_key_pattern: str = 'Instrument settings.{Q}.freq_qubit', + res_freq: list = None, res_Qc: list = None, chi_shift: list = None, + do_fitting: bool = True, close_figs: bool = True, + ): + ''' + Plots and Analyses the coherence times (i.e. T1, T2 OR T2*) of one or several measurements. + + :param t_start: + :param t_stop: + :param label: + :param options_dict: + :param auto: + :param close_figs: Close the figure (do not display) + :param extract_only: + :param do_fitting: + :param tau_key: + :param tau_std_key: key for the tau (time) standard deviation fit result, + e.g. 'Analysis.Fitted Params F|1>.tau.stderr' + :param plot_versus_dac: Extract and plot dac value? + E.g. set False if you did not vary the dac for this measurement. + :param dac_key: + :param plot_versus_frequency: Extract and plot frequency value? + E.g. set False if you did not use the Qubit object. + :param frequency_key: + + + :param dac_instr_names: + :param qubit_instr_names: + :param t_start: start time of scan as a string of format YYYYMMDD_HHmmss + :param t_stop: end time of scan as a string of format YYYYMMDD_HHmmss + :param labels: a dict of the labels that were used to name the measurements (only necessary if non-relevant measurements are in the time range) + :param options_dict: Available options are the ones from the base_analysis and: + - (todo) + :param extract_only: Should we also do the plots? + :param auto: Execute all steps automatically + :param tau_keys: dict of keys for the tau (time) fit results, + e.g. {CoherenceTimesAnalysis.T1 : 'Analysis.Fitted Params F|1>.tau.value', ...} + :param tau_std_keys: dict of keys for the tau standard deviation (time) fit results, + e.g. {CoherenceTimesAnalysis.T1 : 'Analysis.Fitted Params F|1>.tau.stderr', ...} + :param plot_versus_dac: Extract and plot dac value? + E.g. set False if you did not vary the dac for this measurement. + :param dac_key_pattern: key pattern for the dac current values, e.g. 'Instrument settings.fluxcurrent.{DAC}' + use {Q} to replace by qubit_instr_names and {DAC} to replace by dac_instr_names. + :param plot_versus_frequency: Extract and plot frequency value? + E.g. set False if you did not use the Qubit object. + :param frequency_key_pattern: keys for the dac current values, e.g. 'Instrument settings.{Q}.freq_qubit' + use {Q} to replace by qubit_instr_names and {DAC} to replace by dac_instr_names. + :param res_freq: Frequency of the resonator + :param res_Qc: Quality factor of the resonator + :param chi_shift: Qubit-induced dispersive shift + :param do_fitting: Should the run_fitting method be executed? + :param close_figs: Close the figure (do not display) + ''' + + if dac_instr_names is str: + dac_instr_names = [dac_instr_names, ] + if qubit_instr_names is str: + qubit_instr_names = [qubit_instr_names, ] + + ## Check data and apply default values + assert (len(qubit_instr_names) == len(dac_instr_names)) + if plot_versus_dac: + assert (len(qubit_instr_names) == len(dac_instr_names)) + if res_Qc or res_freq or chi_shift: + assert (len(qubit_instr_names) == len(res_Qc)) + assert (len(qubit_instr_names) == len(res_freq)) + assert (len(qubit_instr_names) == len(chi_shift)) + + # Find the keys for the coherence times and their errors + # todo merge instead of overwrite! + tau_keys = tau_keys or { + self.T1: 'Analysis.Fitted Params F|1>.tau.value', + self.T2: 'Analysis.Fitted Params corr_data.tau.value', + self.T2_star: 'Analysis.Fitted Params raw w0.tau.value', + } + tau_std_keys = tau_std_keys or { + self.T1: 'Analysis.Fitted Params F|1>.tau.stderr', + self.T2: 'Analysis.Fitted Params corr_data.tau.stderr', + self.T2_star: 'Analysis.Fitted Params raw w0.tau.stderr', + } + + if len(qubit_instr_names) == 1: + s = '' + else: + s = '_{Q}' + + labels = labels or { + self.T1: '_T1' + s, + self.T2: '_echo' + s, + self.T2_star: '_ramsey' + s, + } + + assert (len(tau_keys) == len(labels)) + assert (len(tau_keys) == len(tau_std_keys)) + assert (len(tau_keys) >= 3) + + req = (self.T1, self.T2, self.T2_star) + if not all(k in tau_keys for k in req): + raise KeyError("You need to at least specify ", req, " for parameters tau_keys.") + if not all(k in tau_std_keys for k in req): + raise KeyError("You need to at least specify ", req, " for parameters tau_std_keys.") + if not all(k in labels for k in req): + raise KeyError("You need to at least specify ", req, " for parameters labels.") + + # Call abstract init + super().__init__(t_start=t_start, t_stop=t_stop, + label=label, + options_dict=options_dict, + do_fitting=do_fitting, + extract_only=extract_only, + close_figs=close_figs) + + # Save some data for later use + self.raw_data_dict = {} + self.fit_res = {} + self.res_Qc = res_Qc + self.res_freq = res_freq + self.chi_shift = chi_shift + self.qubit_names = qubit_instr_names + + # Find the dac and frequency keys + self.dac_keys = [] if plot_versus_dac else None + self.freq_keys = [] if plot_versus_frequency else None + for i, dac_instr_name in enumerate(dac_instr_names): + qubit_instr_name = qubit_instr_names[i] + if plot_versus_dac: + dac_key = self._parse(dac=dac_instr_name, qubit=qubit_instr_name, pattern=dac_key_pattern) + self.dac_keys.append(dac_key) + if plot_versus_frequency: + freq_key = self._parse(dac=dac_instr_name, qubit=qubit_instr_name, pattern=frequency_key_pattern) + self.freq_keys.append(freq_key) + + # Create all slave objects + self.all_analysis = {} + for i, dac_instr_name in enumerate(dac_instr_names): + qubit = self.qubit_names[i] + dac_key = self.dac_keys[i] if plot_versus_dac else None + freq_key = self.freq_keys[i] if plot_versus_frequency else None + self.all_analysis[self.qubit_names[i]] = {} + for typ in tau_keys: + tau_key = tau_keys[typ] + tau_std_key = tau_std_keys[typ] + + self.all_analysis[qubit][typ] = CoherenceTimesAnalysisSingle( + t_start=t_start, t_stop=t_stop, + label=self._parse(dac=dac_instr_name, qubit=qubit, pattern=labels[typ]), + auto=False, extract_only=True, + tau_key=tau_key, + tau_std_key=tau_std_key, + plot_versus_dac=plot_versus_dac, + dac_key=dac_key, + plot_versus_frequency=plot_versus_frequency, + frequency_key=freq_key, + options_dict=options_dict, + close_figs=close_figs, + ) + + if auto: + self.run_analysis() + + @staticmethod + def _parse(qubit, dac, pattern): + key = pattern.replace('{DAC}', dac) + key = key.replace('{Q}', qubit) + return key + + def extract_data(self): + youngest = None + for qubit in self.all_analysis: + + self.raw_data_dict[qubit] = {} + for typ in self.all_analysis[qubit]: + a = self.all_analysis[qubit][typ] + a.extract_data() + self.raw_data_dict[qubit][typ] = a.raw_data_dict + tmp_y = self.max_time(a.raw_data_dict["datetime"]) + if not youngest or youngest < tmp_y: + youngest = tmp_y + + youngest += datetime.timedelta(seconds=1) + + self.raw_data_dict['datetime'] = [youngest] + self.raw_data_dict['timestamps'] = [youngest.strftime("%Y%m%d_%H%M%S")] + self.timestamps = [youngest] + folder = a_tools.datadir + '/%s_coherence_analysis' % (youngest.strftime("%Y%m%d/%H%M%S")) + self.raw_data_dict['folder'] = [folder] + + @staticmethod + def max_time(times): + youngest = None + for tmp in times: + if not youngest or youngest < tmp: + youngest = tmp + return youngest + + @staticmethod + def _put_data_into_scheme(scheme, scheme_mess, other_mess): + scheme = list(scheme) + other = [None] * len(scheme) + for i, o in enumerate(other_mess): + j = scheme.index(float(scheme_mess[i])) + other[j] = o + return other + + def process_data(self): + for qubit in self.all_analysis: + self.proc_data_dict[qubit] = {} + qo = self.all_analysis[qubit] + + # collect all dac values + all_dac = np.array([]) + for typ in qo: + a = self.all_analysis[qubit][typ] + all_dac = np.append(all_dac, np.array(a.raw_data_dict['dac'], dtype=float)) + all_dac = np.unique(all_dac) + all_dac.sort() + self.proc_data_dict[qubit]['all_dac'] = all_dac + + # Sort the measurement data (taus) into the dac values + qubit_mask = np.array([True] * len(all_dac), dtype=bool) + for typ in qo: + a = self.all_analysis[qubit][typ] + d = self.raw_data_dict[qubit][typ] + self.proc_data_dict[qubit][typ] = {} + + sorted_taus = self._put_data_into_scheme(scheme=all_dac, scheme_mess=d['dac'], + other_mess=d['tau']) + sorted_taus = np.array(sorted_taus) + self.proc_data_dict[qubit][typ]['all_dac_sorted_tau'] = sorted_taus + mask = (sorted_taus == None) + self.proc_data_dict[qubit][typ]['all_dac_sorted_tau_mask'] = mask + qubit_mask = (qubit_mask * 1 + mask * 1) == 2 + + self.proc_data_dict[qubit]['all_mask'] = qubit_mask + + # Calculate gamma = 1/Tau where appropriate + for typ in qo: + sorted_taus = self.proc_data_dict[qubit][typ]['all_dac_sorted_tau'] + self.proc_data_dict[qubit][typ]['all_dac_sorted_gamma'] = 1.0 / sorted_taus[~qubit_mask] + + gamma_1 = self.proc_data_dict[qubit][self.T1]['all_dac_sorted_gamma'] + gamma_ramsey = self.proc_data_dict[qubit][self.T2_star]['all_dac_sorted_gamma'] + gamma_echo = self.proc_data_dict[qubit][self.T2]['all_dac_sorted_gamma'] + gamma_phi_ramsey = (gamma_ramsey - gamma_1 / 2.0) + gamma_phi_echo = (gamma_echo - gamma_1 / 2.0) + self.proc_data_dict[qubit]['gamma_phi_ramsey'] = gamma_phi_ramsey + self.proc_data_dict[qubit]['gamma_phi_echo'] = gamma_phi_echo + + def run_fitting(self): + # This is not the proper way to do this! + # TODO: move this to prepare_fitting + if self.freq_keys and self.dac_keys: + for qubit in self.all_analysis: + self.fit_res[qubit] = {} + if self.verbose: + print("Fitting qubit: %s" % qubit) + + all_dac = self.proc_data_dict[qubit]['all_dac'] + for typ in self.all_analysis[qubit]: + self.fit_res[qubit][typ] = {} + a = self.all_analysis[qubit][typ] + # Sort the flux and sensitivity data + if self.freq_keys and self.dac_keys: + # sort the data by dac (just in case some samples are missing) + a.run_fitting() + self.fit_res[qubit][typ] = a.fit_res + + sorted_sens = self._put_data_into_scheme(scheme=all_dac, scheme_mess=a.raw_data_dict['dac'], + other_mess=a.fit_res['sensitivity_values']) + sorted_flux = self._put_data_into_scheme(scheme=all_dac, scheme_mess=a.raw_data_dict['dac'], + other_mess=a.fit_res['flux_values']) + sorted_sens = np.array(sorted_sens, dtype=float) + sorted_flux = np.array(sorted_flux, dtype=float) + self.fit_res[qubit][typ]['sorted_sensitivity'] = sorted_sens + self.fit_res[qubit][typ]['sorted_flux'] = sorted_flux + + # these should all be the same for all types, so chose one (here T1) + self.fit_res[qubit]['sorted_flux'] = self.fit_res[qubit][self.T1]['sorted_flux'] + self.fit_res[qubit]['sorted_sensitivity'] = self.fit_res[qubit][self.T1][ + 'sorted_sensitivity'] + + # Make the PSD fit, if we have enough data + exclusion_mask = self.proc_data_dict[qubit]['all_mask'] + masked_dac = all_dac[~exclusion_mask] + if len(masked_dac) > 4: + # Fit gamma vs sensitivity + sensitivity = self.fit_res[qubit]['sorted_sensitivity'] + gamma_phi_ramsey = self.proc_data_dict[qubit]['gamma_phi_ramsey'] + gamma_phi_echo = self.proc_data_dict[qubit]['gamma_phi_echo'] + fit_res_gammas = fit_gammas(sensitivity=sensitivity, Gamma_phi_ramsey=gamma_phi_ramsey, + Gamma_phi_echo=gamma_phi_echo, verbose=self.verbose) + self.fit_res[qubit]['fit_res'] = fit_res_gammas + intercept = fit_res_gammas.params['intercept'].value + slope_ramsey = fit_res_gammas.params['slope_ramsey'].value + slope_echo = fit_res_gammas.params['slope_echo'].value + + # after fitting gammas + # from flux noise + # Martinis PRA 2003 + sqrtA_rams = slope_ramsey / (np.pi * np.sqrt(30)) + sqrtA_echo = slope_echo / (np.pi * np.sqrt(1.386)) + + if self.verbose: + print('Amplitude echo PSD = (%s u\Phi_0)^2' % (sqrtA_echo / 1e-6)) + print('Amplitude rams PSD = (%s u\Phi_0)^2' % (sqrtA_rams / 1e-6)) + + chi = self.chi_shift[qubit] if self.chi_shift else None + res_freq = self.res_freq[qubit] if self.res_freq else None + res_Qc = self.res_Qc[qubit] if self.res_Qc else None + + # from white noise + # using Eq 5 in Nat. Comm. 7,12964 (The flux qubit revisited to enhance + # coherence and reproducability) + if not ((res_freq is None) and (res_Qc is None) and (chi is None)): + n_avg = calculate_n_avg(res_freq, res_Qc, chi, intercept) + self.fit_res[qubit]['avg_noise_photons'] = n_avg + if self.verbose: + print('Estimated residual photon number: %s' % n_avg) + + self.fit_res[qubit]['gamma_intercept'] = intercept + self.fit_res[qubit]['gamma_slope_ramsey'] = slope_ramsey + self.fit_res[qubit]['gamma_slope_echo'] = slope_echo + self.fit_res[qubit]['gamma_phi_ramsey_f'] = lambda x: slope_ramsey * x * 1e9 + intercept + self.fit_res[qubit]['gamma_phi_echo_f'] = lambda x: slope_echo * x * 1e9 + intercept + self.fit_res[qubit]['sqrtA_echo'] = (sqrtA_echo / 1e-6) + self.fit_res[qubit]['fit_res'] = fit_res_gammas + + self.fit_res[qubit]['gamma_intercept_std'] = fit_res_gammas.params['intercept'].stderr + self.fit_res[qubit]['gamma_slope_ramsey_std'] = fit_res_gammas.params['slope_ramsey'].stderr + self.fit_res[qubit]['gamma_slope_echo_std'] = fit_res_gammas.params['slope_echo'].stderr + + + else: + # fixme: make this a proper warning + print( + 'Found %d dac values. I need at least 4 dac values to run the PSD analysis.' % len(masked_dac)) + else: + # fixme: make this a proper warning + print('You have to enable plot_versus_frequency and plot_versus_dac to execute the PSD analysis.') + + def save_fit_results(self): + # todo: if you want to save some results to a hdf5, do it here + pass + + def prepare_plots(self): + # prepare axis + cr_all_base = "coherence_ratios" + ct_all_base = 'coherence_times' + cg_all_base = 'coherence_gamma' + # f, axs = plt.subplots(1, 3, figsize=(18, 5), sharey=True) + # self.figs[cg_base] = f + # self.plot_dicts[cg_base] = {} + # self.axs[cg_base + "_flux"] = axs[0] + # self.axs[cg_base + "_frequency"] = axs[1] + # self.axs[cg_base + "_sensitivity"] = axs[2] + + self.plot_dicts = {} + for qubit in self.all_analysis: + # if the analysis was succesful + cm = self.options_dict.get('current_multiplier', 1) + + dat = self.raw_data_dict[qubit] + if hasattr(self, 'fit_res'): + sensitivity = self.fit_res[qubit]['sorted_sensitivity'] + flux = self.fit_res[qubit]['sorted_flux'] + + # freq = self.fit_res[qubit][self.T1]['qfreq'] + gamma_phi_echo = self.proc_data_dict[qubit]['gamma_phi_echo'] + gamma_phi_echo_f = self.fit_res[qubit]['gamma_phi_echo_f'] + gamma_phi_ramsey = self.proc_data_dict[qubit]['gamma_phi_ramsey'] + gamma_phi_ramsey_f = self.fit_res[qubit]['gamma_phi_ramsey_f'] + + ############ + # coherence_gamma + pdict_scatter = { + 'xlabel': r'Sensitivity $|\partial\nu/\partial\Phi|$', + 'xunit': r'GHz/$\Phi_0$', + 'ylabel': r'$\Gamma_{\phi}$', + 'yunit': r'$s^{-1}$', + 'setlabel': '$\Gamma_{\phi,\mathrm{Ramsey}}$', + } + pdict_fit = {} + cg_base = qubit + "_" + cg_all_base + pds, pdf = plot_scatter_errorbar_fit(self=self, ax_id=cg_base, xdata=np.abs(sensitivity) * 1e-9, + ydata=gamma_phi_ramsey, fitfunc=gamma_phi_ramsey_f, + xerr=None, yerr=None, fitextra=0.1, fitpoints=1000, + pdict_scatter=pdict_scatter, pdict_fit=pdict_fit) + self.plot_dicts[cg_base + '_ramsey_fit'] = pdf + self.plot_dicts[cg_base + '_ramsey_scatter'] = pds + + pds, pdf = plot_scatter_errorbar_fit(self=self, ax_id=cg_base, xdata=np.abs(sensitivity) * 1e-9, + ydata=gamma_phi_echo, fitfunc=gamma_phi_echo_f, + xerr=None, yerr=None, fitextra=0.1, fitpoints=1000, + pdict_scatter=pdict_scatter, pdict_fit=pdict_fit) + self.plot_dicts[cg_base + '_echo_fit'] = pdf + self.plot_dicts[cg_base + '_echo_scatter'] = pds + + if self.options_dict.get('print_fit_result_plot', True): + dac_fit_text = '$\Gamma = %.5f(\pm %.5f)$\n' % ( + self.fit_res[qubit]['gamma_intercept'], self.fit_res[qubit]['gamma_intercept_std']) + # dac_fit_text += '$\Gamma/2 \pi = %.2f(\pm %.3f)$ MHz\n' % (self.fit_res[qubit]['gamma_intercept'], self.fit_res[qubit]['gamma_intercept_std']) + # dac_fit_text += '$\Gamma/2 \pi = %.2f(\pm %.3f)$ MHz\n' % (self.fit_res[qubit]['gamma_intercept'], self.fit_res[qubit]['gamma_intercept_std']) + + self.fit_res[qubit]['gamma_slope_ramsey_std'] + self.fit_res[qubit]['gamma_slope_echo_std'] + + self.plot_dicts[cg_base + '_text_msg'] = { + 'ax_id': cg_base, + # 'ypos': 0.15, + 'plotfn': self.plot_text, + 'box_props': 'fancy', + 'text_string': dac_fit_text, + } + + ############ + # coherence_ratios + cr_base = qubit + '_' + cr_all_base + ratio_gamma = (gamma_phi_ramsey / gamma_phi_echo) + + pdict_scatter = { + 'xlabel': 'Flux', + 'xunit': 'm$\Phi_0$', + 'ylabel': '$T_\phi^{\mathrm{Echo}}/T_\phi^{\mathrm{Ramsey}}$', + } + pds = plot_scatter_errorbar(self=self, ax_id=cr_all_base + '_flux', + xdata=flux * 1e3, + ydata=ratio_gamma, + xerr=None, yerr=None, + pdict=pdict_scatter) + self.plot_dicts[cr_base + '_flux'] = pds + + pdict_scatter = { + 'xlabel': r'Sensitivity $|\partial\nu/\partial\Phi|$', + 'xunit': r'GHz/$\Phi_0$', + 'ylabel': '$T_\phi^{\mathrm{Echo}}/T_\phi^{\mathrm{Ramsey}}$', + } + pds = plot_scatter_errorbar(self=self, ax_id=cr_all_base + '_sensitivity', + xdata=np.abs(sensitivity) * 1e-9, + ydata=ratio_gamma, + xerr=None, yerr=None, + pdict=pdict_scatter) + self.plot_dicts[cr_base + '_sensitivity'] = pds + + ############ + # coherence_times + ct_base = qubit + '_' + ct_all_base + + plot_types = ['time_stability', 'freq_relation', 'dac_relation', 'flux_relation', 'sensitivity_relation', ] + ymax = [0] * len(plot_types) + ymin = [0] * len(plot_types) + markers = ('x', 'o', '+') + for typi, typ in enumerate(self.all_analysis[qubit]): + a = self.all_analysis[qubit][typ] + a.prepare_plots() + label = '%s_%s' % (qubit, typ) + for pti, plot_type in enumerate(plot_types): # 'dac_freq_relation + + if plot_type in ['freq_relation', ]: + if self.freq_keys: + plot = True + else: + plot = False + elif plot_type in ['dac_relation', ]: + if self.dac_keys: + plot = True + else: + plot = False + elif plot_type in ['flux_relation', 'sensitivity_relation', + 'dac_freq_relation']: + if self.freq_keys and self.dac_keys: + plot = True + else: + plot = False + else: + plot = True + + if plot: + if a.plot_dicts[plot_type]['yrange']: + ymin[pti] = min(ymin[pti], a.plot_dicts[plot_type]['yrange'][0]) + ymax[pti] = max(ymax[pti], a.plot_dicts[plot_type]['yrange'][1]) + + key = ct_base + '_' + plot_type + '_' + typ + self.plot_dicts[key] = a.plot_dicts[plot_type] + self.plot_dicts[key]['ax_id'] = ct_base + '_' + plot_type + self.plot_dicts[key]['setlabel'] = label + self.plot_dicts[key]['do_legend'] = True + self.plot_dicts[key]['yrange'] = None + # self.plot_dicts[key]['xrange'] = None + self.plot_dicts[key]['marker'] = markers[typi % len(markers)] + if self.plot_dicts[key]['func'] == 'errorbar': + self.plot_dicts[key]['line_kws'] = {'fmt': markers[typi % len(markers)]} + + if 'analysis' in dat and dat['analysis']: + if self.dac_keys and self.freq_keys: + pdict_scatter = { + 'xlabel': r'Sensitivity $|\partial\nu/\partial\Phi|$', + 'xunit': 'm$\Phi_0$', + 'ylabel': '$T_\phi^{\mathrm{Echo}}/T_\phi^{\mathrm{Ramsey}}$', + 'setlabel': label + } + pds = plot_scatter_errorbar(self=self, ax_id=ct_base + '_flux_gamma_relation', + xdata=flux * 1e3, + ydata=dat['analysis'][typ], + xerr=None, yerr=None, + pdict=pdict_scatter) + self.plot_dicts[ct_base + '_flux_gamma_relation_' + typ] = pds + for pti, plot_type in enumerate(plot_types): + key = ct_base + '_' + plot_type + '_' + typ + if key in self.plot_dicts: + self.plot_dicts[key]['yrange'] = [ymin[pti], ymax[pti]] + # self.raw_data_dict[qubit][typ] = a.raw_data_dict + + +def calculate_n_avg(freq_resonator, Qc, chi_shift, intercept): + """ + Returns the avg photon of white noise,assuming photon shot noise from the RO hanger. + """ + k_r = 2 * np.pi * freq_resonator / Qc + eta = k_r ** 2 / (k_r ** 2 + 4 * chi_shift ** 2) + n_avg = intercept * k_r / (4 * chi_shift ** 2 * eta) + return n_avg + + +def prepare_input_table(dac: list, frequency: list, T1: list, T2_star: list, T2_echo: list, + T1_mask: list = None, T2_star_mask: list = None, T2_echo_mask: list = None): + """ + Returns a table ready for PSD_Analysis input + If sizes are different, it adds nans on the end. + """ + assert (len(dac) == len(frequency)) + assert (len(dac) == len(T1)) + assert (len(dac) == len(T2_star)) + assert (len(dac) == len(T2_echo)) + + if T1_mask is None: + T1_mask = np.zeros(len(T1), dtype=bool) + if T2_star_mask is None: + T2_star_mask = np.zeros(len(T2_star), dtype=bool) + if T2_echo_mask is None: + T2_echo_mask = np.zeros(len(T2_echo), dtype=bool) + + assert (len(T1) == len(T1_mask)) + assert (len(T2_star) == len(T2_star_mask)) + assert (len(T2_echo) == len(T2_echo_mask)) + + table = np.ones((6, len(dac))) + table = table * np.nan + table[0, :] = dac + table[1, :len(frequency)] = frequency + table[2, :len(T1)] = T1 + table[3, :len(T2_star)] = T2_star + table[4, :len(T2_echo)] = T2_echo + table[5, :len(T1_mask)] = np.logical_or(np.logical_or(T1_mask, + T2_star_mask), + T2_echo_mask) + + return table + + +def arch(dac, Ec, Ej, offset, dac0): + ''' + Function for frequency vs flux (in dac) for the transmon + + Input: + - dac: voltage used in the DAC to generate the flux + - Ec (Hz): Charging energy of the transmon in Hz + - Ej (Hz): Josephson energy of the transmon in Hz + - offset: voltage offset of the arch (same unit of the dac) + - dac0: dac value to generate 1 Phi_0 (same unit of the dac) + + Note: the Phi_0 (periodicity) dac0 + ''' + d = np.abs(np.cos((np.pi * (dac - offset)) / dac0)) + model = np.sqrt(8 * Ec * Ej * d) - Ec + + return model + + +# define the model (from the function above) used to fit data +arch_model = lmfit.Model(arch) + + +# derivative of arch vs flux (in unit of Phi0) +# this is the sensitivity to flux noise +def partial_omega_over_flux(flux, Ec, Ej): + ''' + Note: flux is in unit of Phi0 + Ej and Ec are in Hz + + Output: angular frequency over Phi_0 + ''' + model = -np.sign(np.cos(np.pi * flux)) * (np.pi ** 2) * np.sqrt(8 * Ec * Ej) * \ + np.sin(np.pi * flux) / np.sqrt(np.abs(np.cos(np.pi * flux))) + return model + + +def fit_frequencies(dac, freq): + arch_model.set_param_hint('Ec', value=260e6, min=100e6, max=350e6) + arch_model.set_param_hint('Ej', value=19e9, min=0.1e9, max=30e9) + arch_model.set_param_hint('offset', value=0, min=-0.05, max=0.05) + arch_model.set_param_hint('dac0', value=0.1, min=0) + + arch_model.make_params() + + fit_result_arch = arch_model.fit(freq, dac=dac) + return fit_result_arch + + +def residual_Gamma(pars_dict, sensitivity, Gamma_phi_ramsey, Gamma_phi_echo): + slope_ramsey = pars_dict['slope_ramsey'] + slope_echo = pars_dict['slope_echo'] + intercept = pars_dict['intercept'] + + gamma_values_ramsey = slope_ramsey * np.abs(sensitivity) + intercept + residual_ramsey = Gamma_phi_ramsey - gamma_values_ramsey + + gamma_values_echo = slope_echo * np.abs(sensitivity) + intercept + residual_echo = Gamma_phi_echo - gamma_values_echo + + return np.concatenate((residual_ramsey, residual_echo)) + + +def fit_gammas(sensitivity, Gamma_phi_ramsey, Gamma_phi_echo, verbose: bool = False): + # create a parametrrer set for the initial guess + p = lmfit.Parameters() + p.add('slope_ramsey', value=100.0, vary=True) + p.add('slope_echo', value=100.0, vary=True) + p.add('intercept', value=100.0, vary=True) + + wrap_residual = lambda p: residual_Gamma(p, + sensitivity=sensitivity, + Gamma_phi_ramsey=Gamma_phi_ramsey, + Gamma_phi_echo=Gamma_phi_echo) + fit_result_gammas = lmfit.minimize(wrap_residual, p) + if verbose: + lmfit.printfuncs.report_fit(fit_result_gammas.params) + return fit_result_gammas diff --git a/pycqed/analysis_v2/cross_dephasing_analysis.py b/pycqed/analysis_v2/cross_dephasing_analysis.py new file mode 100644 index 0000000000..f62d762ab7 --- /dev/null +++ b/pycqed/analysis_v2/cross_dephasing_analysis.py @@ -0,0 +1,260 @@ +''' +Toolset to analyse measurement-induced Dephasing of qubits + +Hacked together by Rene Vollmer +''' + +import pycqed +from pycqed.analysis_v2.quantum_efficiency_analysis import RamseyAnalysisSweep +import pycqed.analysis_v2.base_analysis as ba +import numpy as np +from collections import OrderedDict +import copy +import datetime +import os +from pycqed.analysis import analysis_toolbox as a_tools + +import numpy as np +import matplotlib.pyplot as plt +import numpy.ma +from mpl_toolkits.axes_grid1.inset_locator import inset_axes + + +class CrossDephasingAnalysis(ba.BaseDataAnalysis): + ''' + Analyses measurement-induced Dephasing of qubits + ''' + + def __init__(self, qubit_labels: list, + t_start: str = None, t_stop: str = None, + label_pattern: str = 'ro_amp_sweep_ramsey_trgt_{TQ}_measured_{RQ}', + options_dict: dict = None, + extract_only: bool = False, auto: bool = True, + close_figs: bool = True, do_fitting: bool = True): + + super().__init__(t_start=t_start, t_stop=t_stop, + label=label_pattern, + options_dict=options_dict, + do_fitting=do_fitting, + close_figs=close_figs, + extract_only=extract_only) + + self.label_pattern = label_pattern + self.qubit_labels = qubit_labels + self.ra = np.array([[None] * len(qubit_labels)] * len(qubit_labels)) + d = copy.deepcopy(self.options_dict) + d['save_figs'] = False + for i, tq in enumerate(qubit_labels): + for j, rq in enumerate(qubit_labels): + label = label_pattern.replace('{TQ}', tq).replace('{RQ}', rq) + self.ra[i, j] = RamseyAnalysisSweep( + t_start=t_start, + t_stop=t_stop, + label=label, options_dict=d, + auto=False, extract_only=True) + + if auto: + self.run_analysis() + + def extract_data(self): + ts = [] + for i, tq in enumerate(self.qubit_labels): + for j, rq in enumerate(self.qubit_labels): + ra = self.ra[i, j] + ra.extract_data() + ts.append(np.max(ra.raw_data_dict['datetime'])) + + youngest = np.max(ts) + youngest += datetime.timedelta(seconds=1) + + self.raw_data_dict = OrderedDict() + self.raw_data_dict['datetime'] = [youngest] + self.raw_data_dict['timestamps'] = [youngest.strftime("%Y%m%d_%H%M%S")] + self.timestamps = [youngest.strftime("%Y%m%d_%H%M%S")] + + f = '%s_measurement_cross_dephasing_analysis' % (youngest.strftime("%H%M%S")) + d = '%s' % (youngest.strftime("%Y%m%d")) + folder = os.path.join(a_tools.datadir, d, f) + self.raw_data_dict['folder'] = [folder] + self.options_dict['analysis_result_file'] = os.path.join(folder, f + '.hdf5') + + def run_fitting(self): + qubit_labels = self.qubit_labels + self.fit_dicts = OrderedDict() + self.fit_res = OrderedDict() + self.fit_dicts['sigmas'] = np.array( + [[None] * len(qubit_labels)] * len(qubit_labels), dtype=float) + self.fit_dicts['sigmas_norm'] = np.array( + [[None] * len(qubit_labels)] * len(qubit_labels), dtype=float) + self.fit_dicts['deph_norm'] = np.array( + [[None] * len(qubit_labels)] * len(qubit_labels), dtype=float) + self.fit_res['coherence_fit'] = np.array( + [[None] * len(qubit_labels)] * len(qubit_labels), dtype=object) + + for i, tq in enumerate(qubit_labels): + for j, rq in enumerate(qubit_labels): + ra = self.ra[i, j] + ra.run_analysis() + self.fit_res['coherence_fit'] = ra.fit_res['coherence_fit'] + self.fit_dicts['sigmas'][i, j] = ra.fit_dicts['coherence_fit']['sigma'] + self.fit_dicts['sigmas_norm'][i,:] = self.fit_dicts['sigmas'][i,:] / self.fit_dicts['sigmas'][i, i] + self.fit_dicts['deph_norm'][i,:] = self.fit_dicts['sigmas'][i, i] / self.fit_dicts['sigmas'][i,:] + + def prepare_plots(self): + self.plot_dicts['sigmas'] = { + 'plotfn': self.plot_labeled_2d, + 'title': '', # todo + 'yvals': self.qubit_labels, 'ylabel': 'Targeted Qubit', 'yunit': '', + 'xvals': self.qubit_labels, 'xlabel': 'Dephased Qubit', 'xunit': '', + 'zvals': self.fit_dicts['sigmas'], + 'zlabel': r'Ramsey Gauss width $\sigma$', + #'plotsize': self.options_dict.get('plotsize', None), + 'cmap': self.options_dict.get('cmap', 'YlGn_r'), + } + self.plot_dicts['sigmas_norm'] = { + 'plotfn': self.plot_labeled_2d, + 'title': 'Normalized by targetted Qubit', # todo + 'yvals': self.qubit_labels, 'ylabel': 'Targeted Qubit', 'yunit': '', + 'xvals': self.qubit_labels, 'xlabel': 'Dephased Qubit', 'xunit': '', + 'zvals': self.fit_dicts['sigmas_norm'], + 'zlabel': r'Normalized Ramsey Gauss width $\sigma$', + 'plotsize': self.options_dict.get('plotsize', None), + 'cmap': self.options_dict.get('cmap', 'YlGn_r'), + } + self.plot_dicts['deph_norm'] = { + 'plotfn': self.plot_norm_matrix, + 'title': 'Normalized by targetted Qubit', # todo + 'yvals': self.qubit_labels, 'ylabel': 'Targeted Qubit', 'yunit': '', + 'xvals': self.qubit_labels, 'xlabel': 'Dephased Qubit', 'xunit': '', + 'zvals': self.fit_dicts['deph_norm'], + 'zlabel': r'Normalized Inverse Ramsey Gauss width $\sigma^{-1}$', + 'plotsize': self.options_dict.get('plotsize', None), + 'cmap': self.options_dict.get('cmap', 'YlGn_r'), + } + + for i, tq in enumerate(self.qubit_labels): + for j, rq in enumerate(self.qubit_labels): + ra = self.ra[i, j] + label = self.label_pattern.replace('{TQ}', tq) + label = label.replace('{RQ}', rq) + for p in ra.plot_dicts: + self.plot_dicts[p+label] = ra.plot_dicts[p] + self.plot_dicts[p+label]['ax_id'] = self.plot_dicts[p+label].get('ax_id', '')+label + self.plot_dicts[p+label]['title'] = self.plot_dicts[p+label].get('title', 'Coherence ')+label + + def plot_labeled_2d(self, pdict, axs): + xl = pdict.get('xvals') + yl = pdict.get('yvals') + z = pdict.get('zvals') + + xn = np.array(range(len(xl)))+0.5 + yn = np.array(range(len(yl)))+0.5 + pdict['xvals'] = xn + pdict['yvals'] = -yn + pdict['zrange'] = (0, np.max(z)) + + self.plot_colorxy(pdict=pdict, axs=axs) + + axs.yaxis.set_ticklabels(yl) + axs.yaxis.set_ticks(-yn) + axs.xaxis.set_ticklabels(xl) + axs.xaxis.set_ticks(xn) + + axs.cbar.set_label(pdict.get('zlabel', '')) + + def plot_norm_matrix(self, pdict, axs): + fig = axs.figure + xl = pdict.get('xvals') + yl = pdict.get('yvals') + z = pdict.get('zvals') + + xn = np.array(range(len(xl))) + yn = np.array(range(len(yl))) + + diag_matrix = np.zeros_like(z, dtype=bool) + for i in range(len(diag_matrix)): + diag_matrix[i, i] = True + + off_diagonal = numpy.ma.masked_array(z, diag_matrix) + diagonal = numpy.ma.masked_array(z, diag_matrix == False) + + # axins1 = inset_axes(parent_axes=axs, + # width="4%", # width = 10% of parent_bbox width + # height="45%", # height : 50% + # loc=2, + # bbox_to_anchor=(1.03, 0., 1, 1), + # bbox_transform=axs.transAxes, + # borderpad=0, + # ) + + pa = axs.imshow(diagonal, cmap='Reds', vmax=1, vmin=0.95) + #cba = fig.colorbar(pa, cax=axins1) + + axins2 = inset_axes(parent_axes=axs, + width="4%", # width = 10% of parent_bbox width + height="100%", # height : 50% + loc=3, + bbox_to_anchor=(1.03, 0., 1, 1), + bbox_transform=axs.transAxes, + borderpad=0, + ) + + pb = axs.imshow(off_diagonal, cmap='Blues', + vmin=0, vmax=max(np.max(off_diagonal),0.01)) + cbb = fig.colorbar(pb, cax=axins2) + + axs.yaxis.set_ticklabels(yl) + axs.yaxis.set_ticks(yn) + axs.xaxis.set_ticklabels(xl) + axs.xaxis.set_ticks(xn) + + #axs.cbar.set_label(pdict.get('zlabel', '')) + + def plot_double_matrix(self, pdict, axs): + fig = axs.figure + xl = pdict.get('xvals') + yl = pdict.get('yvals') + z = pdict.get('zvals') + + xn = np.array(range(len(xl))) + yn = np.array(range(len(yl))) + + diag_matrix = np.zeros_like(z, dtype=bool) + for i in range(len(diag_matrix)): + diag_matrix[i, i] = True + + off_diagonal = numpy.ma.masked_array(z, diag_matrix) + diagonal = numpy.ma.masked_array(z, diag_matrix == False) + + axins1 = inset_axes(parent_axes=axs, + width="4%", # width = 10% of parent_bbox width + height="45%", # height : 50% + loc=2, + bbox_to_anchor=(1.03, 0., 1, 1), + bbox_transform=axs.transAxes, + borderpad=0, + ) + + pa = axs.imshow(diagonal, cmap='Reds', vmax=1, + vmin=min(np.min(diagonal), 0.99)) + cba = fig.colorbar(pa, cax=axins1) + + axins2 = inset_axes(parent_axes=axs, + width="4%", # width = 10% of parent_bbox width + height="100%", # height : 50% + loc=3, + bbox_to_anchor=(1.03, 0., 1, 1), + bbox_transform=axs.transAxes, + borderpad=0, + ) + + pb = axs.imshow(off_diagonal, cmap='Blues_r', + vmin=0, vmax=max(np.max(off_diagonal),0.01)) + cbb = fig.colorbar(pb, cax=axins2) + + axs.yaxis.set_ticklabels(yl) + axs.yaxis.set_ticks(yn) + axs.xaxis.set_ticklabels(xl) + axs.xaxis.set_ticks(xn) + + #axs.cbar.set_label(pdict.get('zlabel', '')) diff --git a/pycqed/analysis_v2/cryo_scope_analysis.py b/pycqed/analysis_v2/cryo_scope_analysis.py index 87d2285e29..3953922cad 100644 --- a/pycqed/analysis_v2/cryo_scope_analysis.py +++ b/pycqed/analysis_v2/cryo_scope_analysis.py @@ -1,19 +1,16 @@ import matplotlib.pyplot as plt -import lmfit +from typing import Union +from copy import deepcopy from pycqed.analysis import analysis_toolbox as a_tools from collections import OrderedDict from pycqed.analysis import measurement_analysis as ma_old from pycqed.analysis.tools import cryoscope_tools as ct import pycqed.analysis_v2.base_analysis as ba -import pycqed.measurement.waveform_control_CC.waveform as wf -import pycqed.analysis.fitting_models as fit_mods import numpy as np -from numpy.fft import fft, ifft, fftfreq from scipy.stats import sem from pycqed.analysis.tools.plotting import set_xlabel, set_ylabel - class RamZFluxArc(ba.BaseDataAnalysis): """ Analysis for the 2D scan that is used to calibrate the FluxArc. @@ -27,20 +24,41 @@ class RamZFluxArc(ba.BaseDataAnalysis): def __init__(self, t_start: str, t_stop: str, label='arc', options_dict: dict=None, + ch_amp_key: str='Snapshot/instruments/AWG8_8005' + '/parameters/awgs_0_outputs_1_amplitude', + ch_range_key: str='Snapshot/instruments/AWG8_8005' + '/parameters/sigouts_0_range', + waveform_amp_key: str='Snapshot/instruments/FL_LutMan_QR' + '/parameters/sq_amp', + close_figs=True, + nyquist_calc: str= 'auto', + exclusion_indices: list=None, + ch_idx_cos: int=0, + ch_idx_sin: int=1, f_demod: float=0, demodulate: bool=False, auto=True): if options_dict is None: options_dict = dict() + + self.ch_amp_key = ch_amp_key + # ch_range_keycan also be set to `None`, then the value will + # default to 1 (no rescaling) + self.ch_range_key = ch_range_key + self.waveform_amp_key = waveform_amp_key + self.exclusion_indices = exclusion_indices + self.exclusion_indices = exclusion_indices \ + if exclusion_indices is not None else [] + self.nyquist_calc = nyquist_calc + self.ch_idx_cos = ch_idx_cos + self.ch_idx_sin = ch_idx_sin + super().__init__(t_start=t_start, t_stop=t_stop, label=label, - options_dict=options_dict) + options_dict=options_dict, close_figs=close_figs) if auto: self.run_analysis() def extract_data(self): """ Custom data extraction for this specific experiment. - - Overwrite this method if you wnat to - """ self.timestamps = a_tools.get_timestamps_in_range( self.t_start, self.t_stop, @@ -48,9 +66,6 @@ def extract_data(self): self.raw_data_dict = OrderedDict() - # FIXME: this is hardcoded and should be an argument in options dict - amp_key = 'Snapshot/instruments/AWG8_8005/parameters/awgs_0_outputs_1_amplitude' - self.raw_data_dict['amps'] = [] self.raw_data_dict['data'] = [] @@ -58,8 +73,17 @@ def extract_data(self): a = ma_old.MeasurementAnalysis( timestamp=t, auto=False, close_file=False) a.get_naming_and_values() - amp = a.data_file[amp_key].attrs['value'] - data = a.measured_values[2] + 1j * a.measured_values[3] + + ch_amp = a.data_file[self.ch_amp_key].attrs['value'] + if self.ch_range_key is None: + ch_range = 2 # corresponds to a scale factor of 1 + else: + ch_range = a.data_file[self.ch_range_key].attrs['value'] + waveform_amp = a.data_file[self.waveform_amp_key].attrs['value'] + amp = ch_amp*ch_range/2*waveform_amp + # amp = ch_amp + data = a.measured_values[self.ch_idx_cos] + 1j * \ + a.measured_values[self.ch_idx_sin] # hacky but required for data saving self.raw_data_dict['folder'] = a.folder self.raw_data_dict['amps'].append(amp) @@ -74,10 +98,13 @@ def process_data(self): self.raw_data_dict['times'], self.raw_data_dict['amps'], self.raw_data_dict['data'], - poly_fit_order=3, plot_fits=False) + exclusion_indices=self.exclusion_indices, + nyquist_calc=self.nyquist_calc, + poly_fit_order=2, plot_fits=False) self.proc_data_dict['dac_arc_ana'] = self.dac_arc_ana + self.proc_data_dict['poly_coeffs'] = self.dac_arc_ana.poly_fit - # this is the infamous dac arc conversion method + # this is the dac arc conversion method # we would like this to be directly accessible self.freq_to_amp = self.dac_arc_ana.freq_to_amp self.amp_to_freq = self.dac_arc_ana.amp_to_freq @@ -85,11 +112,13 @@ def process_data(self): def prepare_plots(self): self.plot_dicts['freqs'] = { 'plotfn': self.dac_arc_ana.plot_freqs, - 'title': "Cryoscope arc \n"+self.timestamps[0]+' - '+self.timestamps[-1]} + 'title': "Cryoscope arc \n" + + self.timestamps[0]+' - ' + self.timestamps[-1]} self.plot_dicts['FluxArc'] = { 'plotfn': self.dac_arc_ana.plot_ffts, - 'title': "Cryoscope arc \n"+self.timestamps[0]+' - '+self.timestamps[-1]} + 'title': "Cryoscope arc \n" + + self.timestamps[0]+' - '+self.timestamps[-1]} class Cryoscope_Analysis(ba.BaseDataAnalysis): @@ -97,60 +126,106 @@ class Cryoscope_Analysis(ba.BaseDataAnalysis): Cryoscope analysis. Requires a function to convert frequency to amp for the final step of the analysis. """ - def __init__(self, t_start: str, t_stop: str, - freq_to_amp, - label='cryoscope', - derivative_window_length: float=15e-9, - norm_window_size: int=31, - nyquist_order: int =0, - options_dict: dict=None, - auto=True): + + def __init__( + self, t_start: str, + t_stop: str =None, + label='cryoscope', + derivative_window_length: float=5e-9, + norm_window_size: int=31, + nyquist_order: int =0, + ch_amp_key: str='Snapshot/instruments/AWG8_8005' + '/parameters/awgs_0_outputs_1_amplitude', + ch_range_key: str='Snapshot/instruments/AWG8_8005' + '/parameters/sigouts_0_range', + polycoeffs_freq_conv: Union[list, str] = + 'Snapshot/instruments/FL_LutMan_QR/parameters/polycoeffs_freq_conv/value', + ch_idx_cos: int=0, + ch_idx_sin: int=1, + input_wf_key: str=None, + options_dict: dict=None, + close_figs: bool=True, + auto=True): + """ + Cryoscope analysis for an arbitrary waveform. + """ if options_dict is None: options_dict = dict() - super().__init__(t_start=t_start, t_stop=t_stop, label=label, - options_dict=options_dict) - if auto: - self.run_analysis() - self.freq_to_amp = freq_to_amp + self.polycoeffs_freq_conv = polycoeffs_freq_conv + + self.ch_amp_key = ch_amp_key + # ch_range_keycan also be set to `None`, then the value will + # default to 1 (no rescaling) + self.ch_range_key = ch_range_key + self.derivative_window_length = derivative_window_length self.norm_window_size = norm_window_size self.nyquist_order = nyquist_order + self.ch_idx_cos = ch_idx_cos + self.ch_idx_sin = ch_idx_sin + + super().__init__( + t_start=t_start, t_stop=t_stop, label=label, + options_dict=options_dict, close_figs=close_figs) + if auto: + self.run_analysis() + + def amp_to_freq(self, amp): + return np.polyval(self.polycoeffs_freq_conv, amp) + + def freq_to_amp(self, freq, positive_branch=True): + return ct.freq_to_amp_root_parabola(freq, + poly_coeffs=self.polycoeffs_freq_conv, + positive_branch=positive_branch) + def extract_data(self): """ Custom data extraction for this specific experiment. - """ - # timestamps in range so that multiple datasets can be averaged together self.timestamps = a_tools.get_timestamps_in_range( self.t_start, self.t_stop, label=self.labels) - + self.timestamp = self.timestamps[0] self.raw_data_dict = OrderedDict() - # FIXME: this is hardcoded and should be an argument in options dict - amp_key = 'Snapshot/instruments/AWG8_8005/parameters/awgs_0_outputs_1_amplitude' + self.raw_data_dict['amps'] = [] + self.raw_data_dict['data'] = [] - data = [] - for t in self.timestamps: - a = ma_old.MeasurementAnalysis( - timestamp=t, auto=False, close_file=False) - a.get_naming_and_values() - amp = a.data_file[amp_key].attrs['value'] - data = a.measured_values[0] + 1j * a.measured_values[1] - # hacky but required for data saving - self.raw_data_dict['folder'] = a.folder - self.raw_data_dict['amp'] = amp # Should be the same for all - data.append(data) - a.finish() + a = ma_old.MeasurementAnalysis( + timestamp=self.timestamp, auto=False, close_file=False) + a.get_naming_and_values() + + ch_amp = a.data_file[self.ch_amp_key].attrs['value'] + if self.ch_range_key is None: + ch_range = 2 # corresponds to a scale factor of 1 + else: + ch_range = a.data_file[self.ch_range_key].attrs['value'] + amp = ch_amp*ch_range/2 + # amp = ch_amp + + # read conversion polynomial from the datafile if not provided as input + if isinstance(self.polycoeffs_freq_conv, str): + self.polycoeffs_freq_conv = np.array( + a.data_file[self.polycoeffs_freq_conv]) + print(np.array(self.polycoeffs_freq_conv)) + + self.raw_data_dict['data'] = a.measured_values[self.ch_idx_cos] + 1j * \ + a.measured_values[self.ch_idx_sin] + + # hacky but required for data saving + self.raw_data_dict['folder'] = a.folder + self.raw_data_dict['amps'].append(amp) + a.finish() - self.raw_data_dict['data'] = np.mean(data) # axis= 0 or 1? self.raw_data_dict['times'] = a.sweep_points self.raw_data_dict['timestamps'] = self.timestamps def process_data(self): - self.proc_data_dict['derivative_window_length'] = self.derivative_window_length + self.proc_data_dict = deepcopy(self.raw_data_dict) + self.proc_data_dict['derivative_window_length'] = \ + self.derivative_window_length self.proc_data_dict['norm_window_size'] = self.norm_window_size self.proc_data_dict['nyquist_order'] = self.nyquist_order @@ -163,22 +238,35 @@ def process_data(self): self.ca.freq_to_amp = self.freq_to_amp self.ca.nyquist_order = self.nyquist_order - def prepare_plots(self): - self.plot_dicts['freqs'] = { - 'plotfn': self.dac_arc_ana.plot_freqs, - 'title': "Cryoscope arc \n"+self.timestamps[0]+' - '+self.timestamps[-1]} + # pass + self.plot_dicts['raw_data'] = { + 'plotfn': self.ca.plot_raw_data, + 'title': self.timestamp+'\nRaw cryoscope data'} + + self.plot_dicts['demod_data'] = { + 'plotfn': self.ca.plot_demodulated_data, + 'title': self.timestamp+'\nDemodulated data'} + self.plot_dicts['norm_data_circ'] = { + 'plotfn': self.ca.plot_normalized_data_circle, + 'title': self.timestamp+'\nNormalized cryoscope data'} - # self.plot_dicts['freqs'] = { - # 'plotfn': self.dac_arc_ana.plot_freqs, - # 'title': "Cryoscope arc \n"+self.timestamps[0]+' - '+self.timestamps[-1]} + self.plot_dicts['demod_phase'] = { + 'plotfn': self.ca.plot_phase, + 'title': self.timestamp+'\nDemodulated phase'} - # self.plot_dicts['FluxArc'] = { - # 'plotfn': self.dac_arc_ana.plot_ffts, - # 'title': "Cryoscope arc \n"+self.timestamps[0]+' - '+self.timestamps[-1]} + self.plot_dicts['frequency_detuning'] = { + 'plotfn': self.ca.plot_frequency, + 'title': self.timestamp+'\nDetuning frequency'} + self.plot_dicts['cryoscope_amplitude'] = { + 'plotfn': self.ca.plot_amplitude, + 'title': self.timestamp+'\nCryoscope amplitude'} + self.plot_dicts['short_time_fft'] = { + 'plotfn': self.ca.plot_short_time_fft, + 'title': self.timestamp+'\nShort time Fourier Transform'} class SlidingPulses_Analysis(ba.BaseDataAnalysis): @@ -296,14 +384,14 @@ def make_phase_plot(t, phase, phase_err, title, ylim=None, ax=None, **kw): label=r'$\pm$5 deg', linewidth=0.5) ax.axhline(mean_phase_tail-5, ls='--', c='grey', linewidth=0.5) ax.legend() - if ylim == None: + if ylim is None: ax.set_ylim(mean_phase_tail-60, mean_phase_tail+40) else: ax.set_ylim(ylim[0], ylim[1]) def make_amp_err_plot(t, amp, timestamp, ax=None, **kw): - if ax == None: + if ax is None: f, ax = plt.subplots() mean_amp = np.nanmean(amp[len(amp)//2]) diff --git a/pycqed/analysis_v2/dac_scan_analysis.py b/pycqed/analysis_v2/dac_scan_analysis.py new file mode 100644 index 0000000000..ab019c8592 --- /dev/null +++ b/pycqed/analysis_v2/dac_scan_analysis.py @@ -0,0 +1,344 @@ +''' +Hacked together by Rene Vollmer +''' +import datetime + +import pycqed.analysis_v2.base_analysis as ba +import numpy as np +from pycqed.analysis import analysis_toolbox as a_tools +from pycqed.analysis.fitting_models import Qubit_dac_to_freq, Resonator_dac_to_freq, Qubit_dac_arch_guess, \ + Resonator_dac_arch_guess +import lmfit +from copy import deepcopy + + +class FluxFrequency(ba.BaseDataAnalysis): + + def __init__(self, t_start: str = None, t_stop: str = None, + label: str = '', + auto: bool = True, + data_file_path: str = None, + close_figs: bool = True, + options_dict: dict = None, extract_only: bool = False, + do_fitting: bool = True, + is_spectroscopy: bool = True, + extract_fitparams: bool = True, + temp_keys: dict = None, + ): + super().__init__(t_start=t_start, t_stop=t_stop, + label=label, + data_file_path=data_file_path, + options_dict=options_dict, + do_fitting=do_fitting, + close_figs=close_figs, + extract_only=extract_only) + + self.params_dict = {'freq_label': self.options_dict.get('sweep_name_key', 'sweep_name'), + 'freq_unit': self.options_dict.get('sweep_unit_key', 'sweep_unit'), + 'measurementstring': 'measurementstring', + 'freq': self.options_dict.get('sweep_points_key', 'sweep_points'), + 'amp': self.options_dict.get('amp_key', 'amp'), + 'phase': self.options_dict.get('phase_key', 'phase'), + 'dac': self.options_dict.get('dac_key', 'Instrument settings.fluxcurrent.Q'), + } + self.numeric_params = ['freq', 'amp', 'phase', 'dac'] + + self.is_spectroscopy = is_spectroscopy + self.extract_fitparams = extract_fitparams + if extract_fitparams: + if is_spectroscopy: + default_key = 'Fitted Params distance.f0.value' + else: + default_key = 'Fitted Params HM.f0.value' + + p = self.options_dict.get('fitparams_key', default_key) + self.params_dict['fitparams'] = p + self.numeric_params.append('fitparams') + + self.temp_keys = temp_keys + self.temperature_plots = False if temp_keys is None else len(temp_keys) >= 1 + if self.temperature_plots: + for temp_key in temp_keys: + self.params_dict[temp_key] = temp_keys[temp_key] + self.numeric_params.append(temp_key) + + if auto: + self.run_analysis() + + def process_data(self): + # sort data + self.proc_data_dict = {} + dac_values_unsorted = np.array(self.raw_data_dict['dac']) + sorted_indices = dac_values_unsorted.argsort() + self.proc_data_dict['dac_values'] = dac_values_unsorted[sorted_indices] + + temp = { + 'amp': 'amplitude_values', + 'phase': 'phase_values', + 'freq': 'frequency_values' + } + for k in temp: + self.proc_data_dict[temp[k]] = self._sort_by_axis0(self.raw_data_dict[k], sorted_indices) + self.proc_data_dict['datetime'] = [self.raw_data_dict['datetime'][i] for i in sorted_indices] + # Do we have negative angles? + negative_angles = self._globalmin(self.proc_data_dict['phase_values']) < 0 + if negative_angles: + tpi = np.pi + else: + tpi = 2 * np.pi + angle_type_deg_guess = np.max([np.max(np.abs(i)) for i in self.proc_data_dict['phase_values']]) > tpi + + if self.options_dict.get('phase_in_rad', False): + deg_factor = 1 + if angle_type_deg_guess: + print('Warning: Assuming degrees as unit for Phase, but it does not seem to be in radians, ' + + 'consider changing the phase_in_rad entry in the options dict accordingly') + else: + deg_factor = np.pi / 180 + if not angle_type_deg_guess: + print('Warning: Assuming degrees as unit for Phase, but it might not be - ' + + 'consider changing the phase_in_rad entry in the options dict accordingly') + + rad = [i * deg_factor for i in self.proc_data_dict['phase_values']] + real = [self.proc_data_dict['amplitude_values'][j] * np.cos(i) for j, i in enumerate(rad)] + imag = [self.proc_data_dict['amplitude_values'][j] * np.sin(i) for j, i in enumerate(rad)] + self.proc_data_dict['distance_values'] = [a_tools.calculate_distance_ground_state( + data_real=real[i], data_imag=imag[i], percentile=self.options_dict.get('s21_percentile', 70), + normalize=self.options_dict.get('s21_normalize_per_dac', False)) for i, v in + enumerate(self.proc_data_dict['dac_values'])] + + if self.options_dict.get('s21_normalize_global', True): + self.proc_data_dict['distance_values'] = [temp / np.max(temp) for temp in + self.proc_data_dict['distance_values']] + + if self.extract_fitparams: + corr_f = self.options_dict.get('fitparams_corr_fact', 1) + self.proc_data_dict['fit_frequencies'] = self.raw_data_dict['fitparams'][sorted_indices] * corr_f + + if self.temperature_plots: + for k in self.temp_keys: + self.proc_data_dict[k] = np.array(self.raw_data_dict[k][sorted_indices], dtype=float) + + # Smooth data and find peeks + smooth = self.options_dict.get('smoothing', False) + freqs = self.proc_data_dict['frequency_values'] + for k in ['amplitude_values', 'phase_values', 'distance_values']: + self.proc_data_dict[k + '_smooth'] = {} + for i, dac_value in enumerate(self.proc_data_dict['dac_values']): + peaks_x, peaks_z, smoothed_z = a_tools.peak_finder_v3(freqs[i], + self.proc_data_dict[k][i], + smoothing=smooth, + perc=self.options_dict.get('peak_perc', 99), + window_len=self.options_dict.get( + 'smoothing_win_len', + False), + factor=self.options_dict.get('data_factor', 1)) + self.proc_data_dict[k + '_smooth'][i] = smoothed_z + + # Fixme: save peaks + + def run_fitting(self): + # This is not the proper way to do this! + # TODO: move this to prepare_fitting + self.fit_dicts = {} + self.fit_result = {} + + dac_vals = self.proc_data_dict['dac_values'] + freq_vals = self.proc_data_dict['fit_frequencies'] + + f_q = self.options_dict.get('qubit_freq', None) + ext = f_q is not None + if self.is_spectroscopy: + fitmod = lmfit.Model(Qubit_dac_to_freq) + fitmod.guess = Qubit_dac_arch_guess.__get__(fitmod, fitmod.__class__) + fitmod.guess(freq=freq_vals, dac_voltage=dac_vals) + else: + if f_q is None and self.verbose: + print('Specify qubit_freq in the options_dict to obtain a better fit!') + # Todo: provide alternative fit? + fitmod = lmfit.Model(Resonator_dac_to_freq) + fitmod.guess = Resonator_dac_arch_guess.__get__(fitmod, fitmod.__class__) + fitmod.guess(freq=freq_vals, dac_voltage=dac_vals, f_max_qubit=f_q) + + fit_result = fitmod.fit(freq_vals, dac_voltage=dac_vals) + + self.fit_result['dac_arc'] = fit_result + EC = fit_result.params['E_c'] + if self.is_spectroscopy: + f0 = fit_result.params['f_max'] + else: + f0 = fit_result.params['f_max_qubit'] + + self.fit_dicts['E_C'] = EC.value + self.fit_dicts['E_J'] = (f0.value ** 2 + 2 * EC.value * f0.value + EC.value ** 2) / (8 * EC.value) + self.fit_dicts['f_sweet_spot'] = f0.value + self.fit_dicts['dac_sweet_spot'] = fit_result.params['dac_sweet_spot'].value + self.fit_dicts['dac_per_phi0'] = fit_result.params['V_per_phi0'].value + self.fit_dicts['asymmetry'] = fit_result.params['asymmetry'].value + + self.fit_dicts['E_C_std'] = EC.stderr + self.fit_dicts['E_J_std'] = -1 # (f0 ** 2 + 2 * EC * f0 + EC ** 2) / (8 * EC) + self.fit_dicts['f_sweet_spot_std'] = f0.stderr + self.fit_dicts['dac_sweet_spot_std'] = fit_result.params['dac_sweet_spot'].stderr + self.fit_dicts['dac_per_phi0_std'] = fit_result.params['V_per_phi0'].stderr + self.fit_dicts['asymmetry_std'] = fit_result.params['asymmetry'].stderr + + if not self.is_spectroscopy: + g = fit_result.params['coupling'] + fr = fit_result.params['f_0_res'] + self.fit_dicts['coupling'] = g.value + self.fit_dicts['coupling_std'] = g.stderr + self.fit_dicts['f_0_res'] = fr.value + self.fit_dicts['f_0_res_std'] = fr.stderr + + def prepare_plots(self): + plot_vs_flux = self.options_dict.get('plot_vs_flux', False) + custom_multiplier = self.options_dict.get('current_multiplier', 1) + fitted = hasattr(self, 'fit_result') and 'dac_arc' in self.fit_result + plot_vs_flux = plot_vs_flux and fitted and (custom_multiplier == 1) + + flux_factor = 1 + if plot_vs_flux: + flux_factor = self.fit_result['dac_arc'].params['V_per_phi0'] + + if plot_vs_flux: + cm = flux_factor + else: + cm = custom_multiplier + + current_label = 'Flux bias current, I' + current_unit = 'A' + if plot_vs_flux: + current_label = 'Flux' + current_unit = r'$\Phi_0$' + + x = self.proc_data_dict['dac_values'] * cm + y = self.proc_data_dict['frequency_values'] + + if self.is_spectroscopy: + s = 'Spectroscopy' + else: + s = 'Resonator' + + twoDPlot = {'plotfn': self.plot_colorx, + 'zorder': 0, + 'xvals': x, + 'yvals': y, + 'title': 'Flux Current ' + s + ' Sweep', + 'xlabel': current_label, + 'xunit': current_unit, + 'ylabel': r'Frequency', + 'yunit': 'Hz', + # 'zrange': [smoothed_amplitude_values.min(), smoothed_amplitude_values.max()], + # 'xrange': [self._globalmin(x), self._globalmax(x)], + # 'yrange': [self._globalmin(y), self._globalmax(y)], + 'plotsize': self.options_dict.get('plotsize', None), + 'cmap': self.options_dict.get('cmap', 'YlGn_r'), + 'plot_transpose': self.options_dict.get('plot_transpose', False), + } + + scatter = { + 'plotfn': self.plot_line, + 'zorder': 5, + 'xvals': self.proc_data_dict['dac_values'], + 'yvals': self.proc_data_dict['fit_frequencies'], + 'marker': 'x', + 'linestyle': 'None', + } + + if self.do_fitting: + fit_result = self.fit_result['dac_arc'] + fit = { + 'plotfn': self.plot_fit, + 'zorder': 10, + 'fit_res': fit_result, + 'xvals': self.proc_data_dict['dac_values'] * cm, + 'yvals': self.proc_data_dict['fit_frequencies'], + 'marker': '', + 'linestyle': '-', + } + + ext = self.options_dict.get('qubit_freq', None) is not None + for ax in ['amplitude', 'phase', 'distance']: + z = self.proc_data_dict['%s_values' % ax] + td = deepcopy(twoDPlot) + td['zvals'] = z + unit = ' (a.u.)' + if ax == 'phase': + if self.options_dict.get('phase_in_rad', False): + unit = ' (rad.)' + else: + unit = ' (deg.)' + elif ax == 'distance': + if self.options_dict.get('s21_normalize_global', False): + unit = ' (norm.)' + td['zlabel'] = ax + unit + td['ax_id'] = ax + self.plot_dicts[ax] = td + + if self.options_dict.get('show_fitted_peaks', True): + sc = deepcopy(scatter) + sc['ax_id'] = ax + self.plot_dicts[ax + '_scatter'] = sc + + if self.do_fitting: + f = deepcopy(fit) + f['ax_id'] = ax + self.plot_dicts[ax + '_fit'] = f + + if hasattr(self, 'fit_dicts') and self.options_dict.get('print_fit_result_plot', True): + dac_fit_text = '' + # if ext or self.is_spectroscopy: + dac_fit_text += '$E_C/2 \pi = %.2f(\pm %.3f)$ MHz\n' % ( + self.fit_dicts['E_C'] * 1e-6, self.fit_dicts['E_C_std'] * 1e-6) + dac_fit_text += '$E_J/\hbar = %.2f$ GHz\n' % ( + self.fit_dicts['E_J'] * 1e-9) # , self.fit_dicts['E_J_std'] * 1e-9 + dac_fit_text += '$\omega_{ss}/2 \pi = %.2f(\pm %.3f)$ GHz\n' % ( + self.fit_dicts['f_sweet_spot'] * 1e-9, self.fit_dicts['f_sweet_spot_std'] * 1e-9) + dac_fit_text += '$I_{ss}/2 \pi = %.2f(\pm %.3f)$ mA\n' % ( + self.fit_dicts['dac_sweet_spot'] * custom_multiplier * 1e3, + self.fit_dicts['dac_sweet_spot_std'] * custom_multiplier * 1e3) + dac_fit_text += '$I/\Phi_0 = %.2f(\pm %.3f)$ mA/$\Phi_0$' % ( + self.fit_dicts['dac_per_phi0'] * custom_multiplier * 1e3, + self.fit_dicts['dac_per_phi0_std'] * custom_multiplier * 1e3) + + if not self.is_spectroscopy: + dac_fit_text += '\n$g/2 \pi = %.2f(\pm %.3f)$ MHz\n' % ( + self.fit_dicts['coupling'] * 1e-6, self.fit_dicts['coupling_std'] * 1e-6) + dac_fit_text += '$\omega_{r,0}/2 \pi = %.2f(\pm %.3f)$ GHz' % ( + self.fit_dicts['f_0_res'] * 1e-9, self.fit_dicts['f_0_res_std'] * 1e-9) + self.plot_dicts['text_msg_' + ax] = { + 'ax_id': ax, + # 'ypos': 0.15, + 'plotfn': self.plot_text, + 'box_props': 'fancy', + 'text_string': dac_fit_text, + } + + # Now plot temperatures + if self.temperature_plots: + for k in self.temp_keys: + temp_dict = { + 'plotfn': self.plot_line, + 'xvals': x, + 'yvals': self.proc_data_dict[k], + 'title': 'Fridge Temperature during Flux Current Sweep', + 'xlabel': r'Flux bias current, I', + 'xunit': 'A', + 'ylabel': r'Temperature', + 'yunit': 'K', + 'marker': 'x', + 'linestyle': '-', + 'do_legend': True, + 'setlabel': k, + } + t = deepcopy(temp_dict) + t['ax_id'] = 'temperature_dac_relation' + self.plot_dicts['temperature_' + k + '_dac_relation'] = t + + t = deepcopy(temp_dict) + t['xvals'] = self.proc_data_dict['datetime'] + t['ax_id'] = 'temperature_time_relation' + t['xlabel'] = r'Time in Delft' + t['xunit'] = '' + self.plot_dicts['temperature_' + k + '_time_relation'] = t \ No newline at end of file diff --git a/pycqed/analysis_v2/measurement_analysis.py b/pycqed/analysis_v2/measurement_analysis.py index 71edff0af2..b6eee2cc20 100644 --- a/pycqed/analysis_v2/measurement_analysis.py +++ b/pycqed/analysis_v2/measurement_analysis.py @@ -7,23 +7,32 @@ # This snippet ensures all submodules get reloaded properly from importlib import reload import pycqed.analysis_v2.base_analysis as ba +reload(ba) import pycqed.analysis_v2.simple_analysis as sa +reload(sa) import pycqed.analysis_v2.timedomain_analysis as ta +reload(ta) import pycqed.analysis_v2.readout_analysis as ra +reload(ra) import pycqed.analysis_v2.syndrome_analysis as synda +reload(sa) # only one of these two files should exist in the end import pycqed.analysis_v2.cryo_scope_analysis as csa +reload(csa) import pycqed.analysis_v2.distortions_analysis as da import pycqed.analysis_v2.optimization_analysis as oa - -reload(ba) +reload(da) +import pycqed.analysis_v2.coherence_analysis as cs +reload(cs) +import pycqed.analysis_v2.spectroscopy_analysis as sa reload(sa) -reload(synda) -reload(ta) +import pycqed.analysis_v2.dac_scan_analysis as da reload(da) -reload(ra) -reload(csa) -reload(oa) +import pycqed.analysis_v2.quantum_efficiency_analysis as qea +reload(qea) +import pycqed.analysis_v2.cross_dephasing_analysis as cda +reload(cda) + from pycqed.analysis_v2.base_analysis import * from pycqed.analysis_v2.simple_analysis import ( @@ -38,8 +47,15 @@ Single_Qubit_RoundsToEvent_Analysis, One_Qubit_Paritycheck_Analysis) -from pycqed.analysis_v2.cryo_scope_analysis import RamZFluxArc, SlidingPulses_Analysis +from pycqed.analysis_v2.cryo_scope_analysis import RamZFluxArc, \ + SlidingPulses_Analysis, Cryoscope_Analysis from pycqed.analysis_v2.distortions_analysis import Scope_Trace_analysis from pycqed.analysis_v2.optimization_analysis import OptimizationAnalysis from pycqed.analysis_v2.timing_cal_analysis import Timing_Cal_Flux_Coarse + +from pycqed.analysis_v2.coherence_analysis import CoherenceTimesAnalysis, CoherenceTimesAnalysisSingle +from pycqed.analysis_v2.spectroscopy_analysis import Spectroscopy, ResonatorSpectroscopy, VNA_analysis, complex_spectroscopy +from pycqed.analysis_v2.dac_scan_analysis import FluxFrequency +from pycqed.analysis_v2.quantum_efficiency_analysis import QuantumEfficiencyAnalysis, RamseyAnalysisSingleScans, RamseyAnalysisSweep, SSROAnalysisSingleScans, SSROAnalysisSweep, QuantumEfficiencyAnalysisTWPA +from pycqed.analysis_v2.cross_dephasing_analysis import CrossDephasingAnalysis \ No newline at end of file diff --git a/pycqed/analysis_v2/quantum_efficiency_analysis.py b/pycqed/analysis_v2/quantum_efficiency_analysis.py new file mode 100644 index 0000000000..24d45d40e7 --- /dev/null +++ b/pycqed/analysis_v2/quantum_efficiency_analysis.py @@ -0,0 +1,783 @@ +''' +Collection of classes to analyse Quantum efficiency measurements. +General procedure is: + - find factor 'a' of the quadratic scaling of the Single-Shot-Readout as a function of scaling_amp (see SSROAnalysis class) + - find sigma from the Gaussian fit of the Ramsey as a function of scaling_amp (see RamseyAnalysis class) + - Calculate eta = a * sigma**2 / 2 (see QuantumEfficiencyAnalysis class) +For details, see https://arxiv.org/abs/1711.05336 + +Lastly, the QuantumEfficiencyAnalysisTWPA class allows for analysing the efficiency +as a function of TWPA power and frequency. + +Hacked together by Rene Vollmer +''' + +import datetime +import pycqed.analysis_v2.base_analysis as ba +from pycqed.analysis_v2.base_analysis import plot_scatter_errorbar_fit, plot_scatter_errorbar + +import numpy as np +import lmfit +import os + +from pycqed.analysis import analysis_toolbox as a_tools +from collections import OrderedDict + +import copy +from pycqed.analysis.measurement_analysis import MeasurementAnalysis + + +class QuantumEfficiencyAnalysisTWPA(ba.BaseDataAnalysis): + ''' + Analyses Quantum efficiency measurements as a function of TWPA Pump frequency and power. + ''' + + def __init__(self, t_start: str = None, t_stop: str = None, + label_ramsey: str = '_Ramsey', + label_ssro: str = '_SSRO', label: str = '', + options_dict: dict = None, + extract_only: bool = False, auto: bool = True, + close_figs: bool = True, do_fitting: bool = True, + twpa_pump_freq_key: str = 'Instrument settings.TWPA_Pump.frequency', + twpa_pump_power_key: str = 'Instrument settings.TWPA_Pump.power', + use_prefit: bool = False): + ''' + + :param t_start: start time of scan as a string of format YYYYMMDD_HHmmss + :param t_stop: end time of scan as a string of format YYYYMMDD_HHmmss + :param options_dict: Available options are the ones from the base_analysis and: + - individual_plots : plot all the individual fits? + - cmap : colormap for 2D plots + - plotsize : plotsize for 2D plots + - (todo) + :param auto: Execute all steps automatically + :param close_figs: Close the figure (do not display) + :param extract_only: Should we also do the plots? + :param do_fitting: Should the run_fitting method be executed? + :param label_ramsey: the label that was used to name the ramsey measurements + :param label_ssro: the label that was used to name the SSRO measurements + :param label: (Optional) common label that was used to name all measurements + :param twpa_pump_freq_key: key for the TWPA Pump Frequency, e.g. 'Instrument settings.TWPA_Pump.frequency' + :param twpa_pump_power_key: key for the TWPA Pump Power, e.g. 'Instrument settings.TWPA_Pump.power' + ''' + super().__init__(t_start=t_start, t_stop=t_stop, + label=label, + options_dict=options_dict, + do_fitting=do_fitting, + close_figs=close_figs, + extract_only=extract_only) + self.use_prefit = use_prefit + self.label_ramsey = label_ramsey + self.label_ssro = label_ssro + + self.params_dict = {'TWPA_freq': twpa_pump_freq_key, + 'TWPA_power': twpa_pump_power_key} + + self.numeric_params = ['TWPA_freq', 'TWPA_power'] + if use_prefit: + self.params_dict['a'] = 'Analysis.coherence_analysis.a' + self.params_dict['a_std'] = 'Analysis.coherence_analysis.a_std' + self.params_dict['sigma'] = 'Analysis.coherence_analysis.sigma' + self.params_dict['sigma_std'] = 'Analysis.coherence_analysis.sigma_std' + self.params_dict['eta'] = 'Analysis.coherence_analysis.eta' + self.params_dict['u_eta'] = 'Analysis.coherence_analysis.u_eta' + self.numeric_params.append('a') + self.numeric_params.append('a_std') + self.numeric_params.append('sigma') + self.numeric_params.append('sigma_std') + self.numeric_params.append('eta') + self.numeric_params.append('u_eta') + + if auto: + self.run_analysis() + + def extract_data(self): + super().extract_data() + # Sort data by frequencies and power + self.proc_data_dict = {} + twpa_freqs_unsorted = np.array(self.raw_data_dict['TWPA_freq'], dtype=float) + twpa_freqs = np.unique(twpa_freqs_unsorted) + twpa_freqs.sort() + twpa_powers_unsorted = np.array(self.raw_data_dict['TWPA_power'], dtype=float) + twpa_powers = np.unique(twpa_powers_unsorted) + twpa_powers.sort() + + self.proc_data_dict['TWPA_freqs'] = twpa_freqs + self.proc_data_dict['TWPA_powers'] = twpa_powers + if self.verbose: + print('Found %d twpa freqs and %d amplitudes' % (len(twpa_freqs), len(twpa_powers))) + print(twpa_freqs, twpa_powers) + + dates = np.array([[None] * len(twpa_powers)] * len(twpa_freqs)) + # date_limits = np.array([[(None, None)] * len(twpa_powers)] * len(twpa_freqs)) + datetimes = np.array(self.raw_data_dict['datetime'], dtype=datetime.datetime) + for i, twpa_freq in enumerate(twpa_freqs): + freq_indices = np.where(twpa_freqs_unsorted == twpa_freq) + for j, twpa_power in enumerate(twpa_powers): + power_indices = np.where(twpa_powers_unsorted == twpa_power) + indices = np.array(np.intersect1d(freq_indices, power_indices), dtype=int) + if self.use_prefit: + if len(indices) > 1: + print("Warning: more than one efficiency value found for freq %.3f and power %.3f"%(twpa_freq*1e-9,twpa_power)) + elif len(indices) == 1: + print("Warning:no efficiency value found for freq %.3f and power %.3f"%(twpa_freq*1e-9,twpa_power)) + dates = indices[0] + + else: + dts = datetimes[indices] + dates[i, j] = dts + # date_limits[i, j][0] = np.min(dts) + # date_limits[i, j][1] = np.max(dts) + + if self.use_prefit: + self.proc_data_dict['sorted_indices'] = np.array(dates, dtype=int) + else: + self.proc_data_dict['sorted_datetimes'] = dates + # self.proc_data_dict['sorted_date_limits'] = date_limits + + def process_data(self): + twpa_freqs = self.proc_data_dict['TWPA_freqs'] + twpa_powers = self.proc_data_dict['TWPA_powers'] + dates = self.proc_data_dict['sorted_datetimes'] + sorted_indices = self.proc_data_dict['sorted_indices'] + # date_limits = self.proc_data_dict['sorted_date_limits'] + + eta = np.array([[None] * len(twpa_powers)] * len(twpa_freqs), dtype=float) + u_eta = np.array([[None] * len(twpa_powers)] * len(twpa_freqs), dtype=float) + sigma = np.array([[None] * len(twpa_powers)] * len(twpa_freqs), dtype=float) + u_sigma = np.array([[None] * len(twpa_powers)] * len(twpa_freqs), dtype=float) + a = np.array([[None] * len(twpa_powers)] * len(twpa_freqs), dtype=float) + u_a = np.array([[None] * len(twpa_powers)] * len(twpa_freqs), dtype=float) + + + objects = np.array([[None] * len(twpa_powers)] * len(twpa_freqs), dtype=QuantumEfficiencyAnalysis) + d = copy.deepcopy(self.options_dict) + d['save_figs'] = False + for i, freq in enumerate(twpa_freqs): + for j, power in enumerate(twpa_powers): + if self.use_prefit: + index = sorted_indices[i, j] + a[i, j] = self.raw_data_dict['a'][index] + u_a[i, j] = self.raw_data_dict['a_std'][index] + sigma[i, j] = self.raw_data_dict['sigma'][index] + u_sigma[i, j] = self.raw_data_dict['sigma_std'][index] + eta[i, j] = self.raw_data_dict['eta'][index] + u_eta[i, j] = self.raw_data_dict['u_eta'][index] + else: + t_start = [d.strftime("%Y%m%d_%H%M%S") for d in dates[i, j]] # date_limits[i, j][0] + t_stop = None # date_limits[i, j][1] + # print(t_start, t_stop) + qea = QuantumEfficiencyAnalysis(t_start=t_start, t_stop=t_stop, label_ramsey=self.label_ramsey, + label_ssro=self.label_ssro, options_dict=d, auto=False, + extract_only=True) + qea.run_analysis() + + a[i, j] = qea.fit_dicts['a'] + u_a[i, j] = qea.fit_dicts['a_std'] + + sigma[i, j] = qea.fit_dicts['sigma'] + u_sigma[i, j] = qea.fit_dicts['sigma_std'] + + eta[i, j] = qea.fit_dicts['eta'] + u_eta[i, j] = qea.fit_dicts['u_eta'] + + objects[i, j] = qea + + if not self.use_prefit: + self.proc_data_dict['analysis_objects'] = objects + + self.proc_data_dict['as'] = a + self.proc_data_dict['as_std'] = u_a + self.proc_data_dict['sigmas'] = sigma + self.proc_data_dict['sigmas_std'] = u_sigma + self.proc_data_dict['etas'] = eta + self.proc_data_dict['etas_std'] = u_eta + + self.proc_data_dict['as'] = a + self.proc_data_dict['as_std'] = u_a + self.proc_data_dict['sigmas'] = sigma + self.proc_data_dict['sigmas_std'] = u_sigma + self.proc_data_dict['etas'] = eta + self.proc_data_dict['etas_std'] = u_eta + + def prepare_plots(self): + twpa_powers = self.proc_data_dict['TWPA_powers'] + twpa_freqs = self.proc_data_dict['TWPA_freqs'] + + # Quantum Efficiency + self.plot_dicts['quantum_eff'] = { + 'plotfn': self.plot_colorxy, + 'title': '', # todo + 'yvals': twpa_powers, 'ylabel': r'TWPA Power', 'yunit': 'dBm', + 'xvals': twpa_freqs, 'xlabel': 'TWPA Frequency', 'xunit': 'Hz', + 'zvals': self.proc_data_dict['etas'].transpose() * 100, + 'zlabel': r'Quantum efficiency $\eta$ (%)', + 'plotsize': self.options_dict.get('plotsize', None), + 'cmap': self.options_dict.get('cmap', 'YlGn_r'), + } + self.plot_dicts['quantum_eff_vari'] = { + 'plotfn': self.plot_colorxy, + 'title': '', # todo + 'yvals': twpa_powers, 'ylabel': r'TWPA Power', 'yunit': 'dBm', + 'xvals': twpa_freqs, 'xlabel': 'TWPA Frequency', 'xunit': 'Hz', + 'zvals': self.proc_data_dict['etas_std'].transpose(), + 'zlabel': r'Quantum efficiency Deviation $\delta \eta$', + 'plotsize': self.options_dict.get('plotsize', None), + 'cmap': self.options_dict.get('cmap', 'YlGn_r'), + } + + # SSRO Slope + self.plot_dicts['ssro_slope'] = { + 'plotfn': self.plot_colorxy, + 'title': '', # todo + 'yvals': twpa_powers, 'ylabel': r'TWPA Power', 'yunit': 'dBm', + 'xvals': twpa_freqs, 'xlabel': 'TWPA Frequency', 'xunit': 'Hz', + 'zvals': self.proc_data_dict['as'].transpose(), + 'zlabel': r'SSRO slope $a$', + 'plotsize': self.options_dict.get('plotsize', None), + 'cmap': self.options_dict.get('cmap', 'YlGn_r'), + } + self.plot_dicts['ssro_slope_vari'] = { + 'plotfn': self.plot_colorxy, + 'title': '', # todo + 'yvals': twpa_powers, 'ylabel': r'TWPA Power', 'yunit': 'dBm', + 'xvals': twpa_freqs, 'xlabel': 'TWPA Frequency', 'xunit': 'Hz', + 'zvals': self.proc_data_dict['as_std'].transpose(), + 'zlabel': r'SSRO slope variance $\delta a$', + 'plotsize': self.options_dict.get('plotsize', None), + 'cmap': self.options_dict.get('cmap', 'YlGn_r'), + } + + # Ramsey Gauss Width + self.plot_dicts['ramsey_gauss_width'] = { + 'plotfn': self.plot_colorxy, + 'title': '', # todo + 'yvals': twpa_powers, 'ylabel': r'TWPA Power', 'yunit': 'dBm', + 'xvals': twpa_freqs, 'xlabel': 'TWPA Frequency', 'xunit': 'Hz', + 'zvals': self.proc_data_dict['sigmas'].transpose(), + 'zlabel': r'Ramsey Gauss width $\sigma$', + 'plotsize': self.options_dict.get('plotsize', None), + 'cmap': self.options_dict.get('cmap', 'YlGn_r'), + } + self.plot_dicts['ramsey_gauss_width_vari'] = { + 'plotfn': self.plot_colorxy, + 'title': '', # todo + 'yvals': twpa_powers, 'ylabel': r'TWPA Power', 'yunit': 'dBm', + 'xvals': twpa_freqs, 'xlabel': 'TWPA Frequency', 'xunit': 'Hz', + 'zvals': self.proc_data_dict['sigmas_std'].transpose(), + 'zlabel': r'Ramsey Gauss width variance $\delta\sigma$', + 'plotsize': self.options_dict.get('plotsize', None), + 'cmap': self.options_dict.get('cmap', 'YlGn_r'), + } + + if self.options_dict.get('individual_plots', False): + # todo: add 1D plot from QuantumEfficiencyAnalysis + for i, twpa_freq in enumerate(twpa_freqs): + for j, twpa_power in enumerate(twpa_powers): + pre = 'freq_%.3f-power_%.3f-' % (twpa_freq, twpa_power) + obj = self.proc_data_dict['analysis_objects'][i, j] + for k in ['amp_vs_Ramsey_coherence', 'amp_vs_Ramsey_fit', ]: + self.plot_dicts[pre + k] = obj.ra.plot_dicts[k] + self.plot_dicts[pre + k]['ax_id'] = pre + 'snr_analysis' + for k in ['amp_vs_SNR_fit', 'amp_vs_SNR_scatter', ]: + self.plot_dicts[pre + k] = obj.ssro.plot_dicts[k] + self.plot_dicts[pre + k]['ax_id'] = pre + 'snr_analysis' + + +class QuantumEfficiencyAnalysis(ba.BaseDataAnalysis): + ''' + Analyses one set of Quantum efficiency measurements + ''' + + def __init__(self, t_start: str = None, t_stop: str = None, + label_ramsey: str = '_Ramsey', + label_ssro: str = '_SSRO', + options_dict: dict = None, + extract_only: bool = False, auto: bool = True, + close_figs: bool = True, do_fitting: bool = True, + use_sweeps: bool = True): + ''' + + :param t_start: start time of scan as a string of format YYYYMMDD_HHmmss + :param t_stop: end time of scan as a string of format YYYYMMDD_HHmmss + :param options_dict: Available options are the ones from the base_analysis and: + - individual_plots : plot all the individual fits? + - cmap : colormap for 2D plots + - plotsize : plotsize for 2D plots + - (todo) + :param auto: Execute all steps automatically + :param close_figs: Close the figure (do not display) + :param extract_only: Should we also do the plots? + :param do_fitting: Should the run_fitting method be executed? + :param label_ramsey: the label that was used to name the ramsey measurements + :param label_ssro: the label that was used to name the SSRO measurements + :param use_sweeps: + ''' + super().__init__(t_start=t_start, t_stop=t_stop, + options_dict=options_dict, + do_fitting=do_fitting, + close_figs=close_figs, + extract_only=extract_only, + ) + d = copy.deepcopy(self.options_dict) + d['save_figs'] = False + + if use_sweeps: + self.ra = RamseyAnalysisSweep(t_start=t_start, t_stop=t_stop, + label=label_ramsey, + options_dict=d, auto=False, + extract_only=True) + self.ssro = SSROAnalysisSweep(t_start=t_start, t_stop=t_stop, + label=label_ssro, + options_dict=d, auto=False, + extract_only=True) + else: + self.ra = RamseyAnalysisSingleScans(t_start=t_start, t_stop=t_stop, + label=label_ramsey, + options_dict=d, auto=False, + extract_only=True) + self.ssro = SSROAnalysisSingleScans(t_start=t_start, t_stop=t_stop, + label=label_ssro, + options_dict=d, auto=False, + extract_only=True) + + if auto: + self.run_analysis() + + def extract_data(self): + self.raw_data_dict = OrderedDict() + + self.ra.extract_data() + self.ssro.extract_data() + + youngest = max(np.max(np.array(self.ra.raw_data_dict['datetime'], dtype=datetime.datetime)), + np.max(np.array(self.ssro.raw_data_dict['datetime'], dtype=datetime.datetime))) + + youngest += datetime.timedelta(seconds=1) + + self.raw_data_dict['datetime'] = [youngest] + self.raw_data_dict['timestamps'] = [youngest.strftime("%Y%m%d_%H%M%S")] + self.timestamps = [youngest.strftime("%Y%m%d_%H%M%S")] + + f = '%s_quantum_efficiency_analysis' % (youngest.strftime("%H%M%S")) + d = '%s' % (youngest.strftime("%Y%m%d")) + folder = os.path.join(a_tools.datadir, d, f) + self.raw_data_dict['folder'] = [folder] + self.options_dict['analysis_result_file'] = os.path.join(folder, f + '.hdf5') + + + def run_fitting(self): + self.ra.run_analysis() + self.ssro.run_analysis() + + self.fit_dicts = OrderedDict() + self.fit_dicts['sigma'] = self.ra.fit_dicts['coherence_fit']['sigma'] + self.fit_dicts['sigma_std'] = self.ra.fit_dicts['coherence_fit']['sigma_std'] + # self.raw_data_dict['scale'] = self.ra.fit_dicts['coherence_fit']['scale'] + self.fit_dicts['a'] = self.ssro.fit_dicts['snr_fit']['a'] + self.fit_dicts['a_std'] = self.ssro.fit_dicts['snr_fit']['a_std'] + + sigma = self.fit_dicts['sigma'] + u_sigma = self.fit_dicts['sigma_std'] + a = self.fit_dicts['a'] + u_a = self.fit_dicts['a_std'] + + eta = a * sigma ** 2 / 2 + u_eta = (u_a / a + 2 * u_sigma / sigma) * eta + + if self.verbose: + print('eta = %.4f +- %.4f' % (eta, u_eta)) + + self.fit_dicts['eta'] = eta + self.fit_dicts['u_eta'] = u_eta + + #For saving + self.fit_res = OrderedDict() + self.fit_res['quantum_efficiency'] = OrderedDict() + self.fit_res['quantum_efficiency']['eta'] = eta + self.fit_res['quantum_efficiency']['u_eta'] = u_eta + self.fit_res['quantum_efficiency']['sigma'] = sigma + self.fit_res['quantum_efficiency']['sigma_std'] = u_sigma + self.fit_res['quantum_efficiency']['a'] = a + self.fit_res['quantum_efficiency']['a_std'] = u_a + + # todo: Reformat data for saving in hdf5 file + # self.fit_res['etas'] = { + # {power: self.proc_data_dict['etas'][i, j] for j, power in self.raw_data_dict['TWPA_freq_ramesy']} + # for i, freq in self.raw_data_dict['TWPA_power_ramesy'] + # } + # self.fit_res['u_etas'] = { + # {power: self.proc_data_dict['u_etas'][i, j] for j, power in self.raw_data_dict['TWPA_freq_ramesy']} + # for i, freq in self.raw_data_dict['TWPA_power_ramesy'] + # } + + def prepare_plots(self): + # self.ra.plot_dicts['amp_vs_Ramsey_fit'] + # self.ra.plot_dicts['amp_vs_Ramsey_Phase'] + # self.ra.plot_dicts['amp_vs_Ramsey_coherence'] + + # self.ssro.plot_dicts['amp_vs_SNR_fit'] + # self.ssro.plot_dicts['amp_vs_SNR_scatter'] + # self.ssro.plot_dicts['amp_vs_Fa'] + # self.ssro.plot_dicts['amp_vs_Fd'] + self.ra.prepare_plots() + for d in self.ra.plot_dicts: + self.plot_dicts[d] = self.ra.plot_dicts[d] + self.ssro.prepare_plots() + for d in self.ssro.plot_dicts: + self.plot_dicts[d] = self.ssro.plot_dicts[d] + + if self.options_dict.get('subplots', True): + for k in ['amp_vs_Ramsey_coherence', 'amp_vs_Ramsey_fit', 'amp_vs_SNR_fit', 'amp_vs_SNR_scatter']: + self.plot_dicts[k]['ax_id'] = 'snr_analysis' + self.plot_dicts[k]['ylabel'] = 'SNR, coherence' + self.plot_dicts[k]['yunit'] = '(-)' + self.plot_dicts[k]['title'] = r'$\eta = (%.4f \pm %.4f)$ %%' % ( + 100 * self.fit_dicts['eta'], 100 * self.fit_dicts['u_eta']) + + self.plot_dicts['amp_vs_Ramsey_fit']['color'] = 'red' + self.plot_dicts['amp_vs_Ramsey_coherence']['color'] = 'red' + self.plot_dicts['amp_vs_SNR_fit']['color'] = 'blue' + self.plot_dicts['amp_vs_SNR_scatter']['color'] = 'blue' + + self.plot_dicts['amp_vs_Ramsey_coherence']['marker'] = 'o' + self.plot_dicts['amp_vs_SNR_scatter']['marker'] = 'o' + + self.plot_dicts['amp_vs_SNR_fit']['do_legend'] = True + self.plot_dicts['amp_vs_Ramsey_fit']['do_legend'] = True + + +class RamseyAnalysis(ba.BaseDataAnalysis): + + def process_data(self): + # Remove None entries + dephasing = self.raw_data_dict['dephasing'] + amps = self.raw_data_dict['scaling_amp'] + mask = np.intersect1d(np.where(dephasing != None), np.where(amps != None)) + + self.proc_data_dict['scaling_amp'] = amps[mask] + self.proc_data_dict['coherence'] = dephasing[mask] + self.proc_data_dict['phase'] = self.raw_data_dict['phase'][mask] + + def run_fitting(self): + self.fit_res = OrderedDict() + coherence = self.proc_data_dict['coherence'] + scaling_amp = self.proc_data_dict['scaling_amp'] + + def gaussian(x, sigma, scale): + return scale * np.exp(-(x) ** 2 / (2 * sigma ** 2)) + + gmodel = lmfit.models.Model(gaussian) + gmodel.set_param_hint('sigma', value=0.07, min=-5, max=5) + gmodel.set_param_hint('scale', value=np.max(coherence)) # , min=0.1, max=100) + para = gmodel.make_params() + coherence_fit = gmodel.fit(coherence, x=scaling_amp, **para) + self.fit_res['coherence_fit'] = coherence_fit + self.fit_dicts['coherence_fit'] = OrderedDict() + self.fit_dicts['coherence_fit']['sigma'] = coherence_fit.params['sigma'].value + self.fit_dicts['coherence_fit']['sigma_std'] = coherence_fit.params['sigma'].stderr + self.fit_dicts['coherence_fit']['scale'] = coherence_fit.params['scale'].value + self.fit_dicts['coherence_fit']['scale_std'] = coherence_fit.params['scale'].stderr + + def prepare_plots(self): + name = '' + fit_text = "$\sigma = %.3f \pm %.3f$"%(self.fit_dicts['coherence_fit']['sigma'], + self.fit_dicts['coherence_fit']['sigma_std']) + self.plot_dicts['text_msg_' + name + 'amp_vs_Ramsey'] = { + 'ax_id':name + 'amp_vs_Ramsey', + # 'ypos': 0.15, + 'plotfn': self.plot_text, + 'box_props': 'fancy', + 'text_string': fit_text, + } + self.plot_dicts[name + 'amp_vs_Ramsey_fit'] = { + 'plotfn': self.plot_fit, + 'ax_id': name + 'amp_vs_Ramsey', + 'zorder': 5, + 'fit_res': self.fit_res['coherence_fit'], + 'xvals': self.proc_data_dict['scaling_amp'], + 'marker': '', + 'linestyle': '-', + 'ylabel': r'Coherence, $\left| \rho_{01} \right|$', + 'yunit': '', + 'xlabel': 'scaling amplitude', + 'xunit': 'rel. amp.', + 'setlabel': 'ramsey coherence fit', + } + self.plot_dicts[name + 'amp_vs_Ramsey_coherence'] = { + 'plotfn': self.plot_line, + 'ax_id': name + 'amp_vs_Ramsey', + 'zorder': 0, + 'xvals': self.proc_data_dict['scaling_amp'], + 'yvals': self.proc_data_dict['coherence'], + 'marker': 'x', + 'linestyle': '', + 'setlabel': 'ramsey coherence data', + } + self.plot_dicts[name + 'amp_vs_Ramsey_Phase'] = { + 'plotfn': self.plot_line, + 'xvals': self.proc_data_dict['scaling_amp'], + 'yvals': self.proc_data_dict['phase'], + 'marker': 'x', + 'linestyle': '', + 'ylabel': 'Phase', + 'yunit': 'deg.', + 'xlabel': 'scaling amplitude', + 'xunit': 'rel. amp.', + 'setlabel': 'ramsey phase data', + } + + +class RamseyAnalysisSweep(RamseyAnalysis): + def __init__(self, t_start: str = None, t_stop: str = None, + label: str = '_ro_amp_sweep_ramsey', + options_dict: dict = None, extract_only: bool = False, + auto: bool = True, close_figs: bool = True, + do_fitting: bool = True): + super().__init__(t_start=t_start, t_stop=t_start, + label=label, + options_dict=options_dict, + do_fitting=do_fitting, + close_figs=close_figs, + extract_only=extract_only, + ) + self.single_timestamp = True + ts = a_tools.get_timestamps_in_range(timestamp_start=t_start, + timestamp_end=t_stop, label=label, + exact_label_match=True) + if self.verbose: + print('RamseyAnalysisSweep', ts) + assert(len(ts) == 1) + self.timestamp = ts[0] + + if auto: + self.run_analysis() + + def extract_data(self): + self.raw_data_dict = OrderedDict() + data_file = MeasurementAnalysis(label=self.labels[0], + timestamp=self.timestamp, + auto=True, TwoD=False) + + dateobj = a_tools.datetime_from_timestamp(self.timestamp) + self.timestamps = [self.timestamp] + self.raw_data_dict['timestamps'] = [self.timestamp] + self.raw_data_dict['datetime'] = np.array([dateobj], dtype=datetime.datetime) + + temp = data_file.load_hdf5data() + data_file.get_naming_and_values() + self.raw_data_dict['scaling_amp'] = data_file.sweep_points + self.raw_data_dict['dephasing'] = np.array(data_file.measured_values[0], dtype=float) + self.raw_data_dict['phase'] = np.array(data_file.measured_values[1], dtype=float) + self.raw_data_dict['folder'] = data_file.folder + + +class RamseyAnalysisSingleScans(RamseyAnalysis): + + def __init__(self, t_start: str = None, t_stop: str = None, label: str = '_Ramsey', + options_dict: dict = None, extract_only: bool = False, auto: bool = True, + close_figs: bool = True, do_fitting: bool = True): + super().__init__(t_start=t_start, t_stop=t_stop, + label=label, + options_dict=options_dict, + do_fitting=do_fitting, + close_figs=close_figs, + extract_only=extract_only + ) + sa = self.options_dict.get('scaling_amp_key_ramsey', 'Instrument settings.RO_lutman.M_amp_R0') + rak = self.options_dict.get('ramsey_amplitude_key', 'Analysis.Fitted Params lin_trans w0.amplitude.value') + rap = self.options_dict.get('ramsey_phase_key', 'Analysis.Fitted Params lin_trans w0.phase.value') + self.params_dict = {'scaling_amp': sa, + 'dephasing': rak, + 'phase': rap, + } + self.numeric_params = ['scaling_amp', 'dephasing', 'phase'] + + if auto: + self.run_analysis() + + def extract_data(self): + # Load data + super().extract_data() + #todo: we need an option to remove outliers and the reference point + + # Set output paths + youngest = np.max(self.raw_data_dict['datetime']) + youngest += datetime.timedelta(seconds=1) + + f = '%s_amp_sweep_ramsey' % (youngest.strftime("%H%M%S")) + d = '%s' % (youngest.strftime("%Y%m%d")) + folder = os.path.join(a_tools.datadir, d, f) + self.raw_data_dict['folder'] = [folder] + self.options_dict['analysis_result_file'] = os.path.join(folder, f + '.hdf5') + + +class SSROAnalysis(ba.BaseDataAnalysis): + def process_data(self): + + # Remove None entries + snr = np.array(self.raw_data_dict['SNR'], dtype=float) + amps = np.array(self.raw_data_dict['scaling_amp'], dtype=float) + mask = np.intersect1d(np.where(snr != None), np.where(amps != None)) + self.proc_data_dict['scaling_amp'] = amps[mask] + self.proc_data_dict['SNR'] = snr[mask] + self.proc_data_dict['F_a'] = np.array(self.raw_data_dict['F_a'], dtype=float)[mask] + self.proc_data_dict['F_d'] = np.array(self.raw_data_dict['F_d'], dtype=float)[mask] + + def run_fitting(self): + self.fit_res = OrderedDict() + SNR = self.proc_data_dict['SNR'] + amps = self.proc_data_dict['scaling_amp'] + + def line(x, a): + return np.sqrt(a) * x + + gmodel = lmfit.models.Model(line) + gmodel.set_param_hint('a', value=1, min=1e-5, max=100) + para = gmodel.make_params() + snr_fit = gmodel.fit(SNR, x=amps, **para) + self.fit_res['snr_fit'] = snr_fit + + self.fit_dicts['snr_fit'] = OrderedDict() + self.fit_dicts['snr_fit']['a'] = snr_fit.params['a'].value + self.fit_dicts['snr_fit']['a_std'] = snr_fit.params['a'].stderr + + def prepare_plots(self): + name = '' + self.plot_dicts[name + 'amp_vs_SNR_fit'] = { + 'plotfn': self.plot_fit, + 'ax_id': name + 'amp_vs_SNR', + 'zorder': 5, + 'fit_res': self.fit_res['snr_fit'], + 'xvals': self.proc_data_dict['scaling_amp'], + 'marker': '', + 'linestyle': '-', + 'setlabel': 'SNR fit', + 'do_legend': True, + } + self.plot_dicts[name + 'amp_vs_SNR_scatter'] = { + 'plotfn': self.plot_line, + 'ax_id': name + 'amp_vs_SNR', + 'zorder': 0, + 'xvals': self.proc_data_dict['scaling_amp'], + 'xlabel': 'scaling amplitude', + 'xunit': 'rel. amp.', + 'yvals': self.proc_data_dict['SNR'], + 'ylabel': 'SNR', + 'yunit': '-', + 'marker': 'x', + 'linestyle': '', + 'setlabel': 'SNR data', + 'do_legend': True, + } + self.plot_dicts[name + 'amp_vs_Fa'] = { + 'plotfn': self.plot_line, + 'zorder': 0, + 'ax_id': name + 'amp_vs_F', + 'xvals': self.proc_data_dict['scaling_amp'], + 'yvals': self.proc_data_dict['F_a'], + 'marker': 'x', + 'linestyle': '', + 'setlabel': '$F_a$ data', + 'do_legend': True, + } + self.plot_dicts[name + 'amp_vs_Fd'] = { + 'plotfn': self.plot_line, + 'zorder': 1, + 'ax_id': name + 'amp_vs_F', + 'xvals': self.proc_data_dict['scaling_amp'], + 'yvals': self.proc_data_dict['F_d'], + 'marker': 'x', + 'linestyle': '', + 'ylabel': 'Fidelity', + 'yunit': '-', + 'xlabel': 'scaling amplitude', + 'xunit': 'rel. amp.', + 'setlabel': '$F_d$ data', + 'do_legend': True, + } + + +class SSROAnalysisSweep(SSROAnalysis): + def __init__(self, t_start: str = None, t_stop: str = None, + label: str = '_ro_amp_sweep_SNR', + options_dict: dict = None, extract_only: bool = False, auto: bool = True, + close_figs: bool = True, do_fitting: bool = True): + super().__init__(t_start=t_start, t_stop=t_start, + label=label, + options_dict=options_dict, + do_fitting=do_fitting, + close_figs=close_figs, + extract_only=extract_only, + ) + self.single_timestamp = True + + ts = a_tools.get_timestamps_in_range(timestamp_start=t_start, + timestamp_end=t_stop, label=label, + exact_label_match=True) + if self.verbose: + print('SSROAnalysisSweep', ts) + assert(len(ts) == 1) + self.timestamp = ts[0] + + if auto: + self.run_analysis() + + def extract_data(self): + self.raw_data_dict = OrderedDict() + data_file = MeasurementAnalysis(timestamp=self.timestamp, + auto=True, TwoD=False) + + dateobj = a_tools.datetime_from_timestamp(self.timestamp) + self.timestamps = [self.timestamp] + self.raw_data_dict['timestamps'] = [self.timestamp] + self.raw_data_dict['datetime'] = np.array([dateobj], dtype=datetime.datetime) + + temp = data_file.load_hdf5data() + data_file.get_naming_and_values() + self.raw_data_dict['scaling_amp'] = data_file.sweep_points + self.raw_data_dict['SNR'] = np.array(data_file.measured_values[0], dtype=float) + self.raw_data_dict['F_d'] = np.array(data_file.measured_values[1], dtype=float) + self.raw_data_dict['F_a'] = np.array(data_file.measured_values[2], dtype=float) + self.raw_data_dict['folder'] = data_file.folder + + +class SSROAnalysisSingleScans(SSROAnalysis): + + def __init__(self, t_start: str = None, t_stop: str = None, label: str = '_SSRO', + options_dict: dict = None, extract_only: bool = False, auto: bool = True, + close_figs: bool = True, do_fitting: bool = True): + super().__init__(t_start=t_start, t_stop=t_stop, + label=label, + options_dict=options_dict, + do_fitting=do_fitting, + close_figs=close_figs, + extract_only=extract_only, + ) + + sa = self.options_dict.get('scaling_amp_key_ssro', 'Instrument settings.RO_lutman.M_amp_R0') + + self.params_dict = {'scaling_amp': sa, + 'SNR': 'Analysis.SSRO_Fidelity.SNR', + 'F_a': 'Analysis.SSRO_Fidelity.F_a', + 'F_d': 'Analysis.SSRO_Fidelity.F_d', + } + self.numeric_params = ['scaling_amp', 'SNR', 'F_a', 'F_d'] + + if auto: + self.run_analysis() + + def extract_data(self): + # Load data + super().extract_data() + + #todo: we need an option to remove outliers and the reference point + + # Set output paths + youngest = np.max(self.raw_data_dict['datetime']) + youngest += datetime.timedelta(seconds=1) + f = '%s_amp_sweep_SNR_optimized' % (youngest.strftime("%H%M%S")) + d = '%s' % (youngest.strftime("%Y%m%d")) + folder = os.path.join(a_tools.datadir, d, f) + self.raw_data_dict['folder'] = [folder] + self.options_dict['analysis_result_file'] = os.path.join(folder, f + '.hdf5') diff --git a/pycqed/analysis_v2/readout_analysis.py b/pycqed/analysis_v2/readout_analysis.py index e92632eabd..12bd57911f 100644 --- a/pycqed/analysis_v2/readout_analysis.py +++ b/pycqed/analysis_v2/readout_analysis.py @@ -3,14 +3,19 @@ This includes - readout discrimination analysis - single shot readout analysis - - multiplexed readout analysis + - multiplexed readout analysis (to be updated!) + +Originally written by Adriaan, updated/rewritten by Rene May 2018 """ import itertools +from copy import deepcopy + import matplotlib.pyplot as plt import lmfit from collections import OrderedDict import numpy as np import pycqed.analysis.fitting_models as fit_mods +from pycqed.analysis.fitting_models import ro_gauss, ro_CDF, ro_CDF_discr, gaussian_2D, gauss_2D_guess, gaussianCDF, ro_double_gauss_guess import pycqed.analysis.analysis_toolbox as a_tools import pycqed.analysis_v2.base_analysis as ba from scipy.optimize import minimize @@ -23,16 +28,33 @@ class Singleshot_Readout_Analysis(ba.BaseDataAnalysis): def __init__(self, t_start: str=None, t_stop: str=None, - label: str='', + label: str='', do_fitting: bool = True, data_file_path: str=None, - options_dict: dict=None, extract_only: bool=False, - do_fitting: bool=True, auto=True): + options_dict: dict=None, auto=True, **kw): + ''' + options dict options: + 'fixed_p10' fixes p(e|g) (do not vary in fit) + 'fixed_p01' : fixes p(g|pi) (do not vary in fit) + 'auto_rotation_angle' : (bool) automatically find the I/Q mixing angle + 'rotation_angle' : manually define the I/Q mixing angle (ignored if auto_rotation_angle is set to True) + 'nr_bins' : number of bins to use for the histograms + 'post_select' : + 'post_select_threshold' : + 'nr_samples' : amount of different samples (e.g. ground and excited = 2) + 'sample_0' : index of first sample (ground-state) + 'sample_1' : index of second sample (first excited-state) + 'max_datapoints' : maximum amount of datapoints for culumative fit + 'log_hist' : use log scale for the y-axis of the 1D histograms + 'verbose' : see BaseDataAnalysis + 'presentation_mode' : see BaseDataAnalysis + see BaseDataAnalysis for more. + ''' super().__init__(t_start=t_start, t_stop=t_stop, - label=label, + label=label, do_fitting=do_fitting, data_file_path=data_file_path, options_dict=options_dict, - extract_only=extract_only, do_fitting=do_fitting) - self.single_timestamp = False + **kw) + self.single_timestamp = True self.params_dict = { 'measurementstring': 'measurementstring', 'measured_values': 'measured_values', @@ -40,6 +62,11 @@ def __init__(self, t_start: str=None, t_stop: str=None, 'value_units': 'value_units'} self.numeric_params = [] + + # Determine the default for auto_rotation_angle + man_angle = self.options_dict.get('rotation_angle', False) is False + self.options_dict['auto_rotation_angle'] = self.options_dict.get('auto_rotation_angle', man_angle) + if auto: self.run_analysis() @@ -47,7 +74,6 @@ def process_data(self): """ Responsible for creating the histograms based on the raw data """ - # Determine the shape of the data to extract wheter to rotate or not post_select = self.options_dict.get('post_select', False) post_select_threshold = self.options_dict.get( 'post_select_threshold', 0) @@ -56,163 +82,229 @@ def process_data(self): sample_1 = self.options_dict.get('sample_1', 1) nr_bins = self.options_dict.get('nr_bins', 100) - nr_expts = self.raw_data_dict['nr_experiments'] - self.proc_data_dict['shots_0'] = [''] * nr_expts - self.proc_data_dict['shots_1'] = [''] * nr_expts - self.proc_data_dict['nr_shots'] = [0] * nr_expts - ###################################################### # Separating data into shots for 0 and shots for 1 # ###################################################### - - for i, meas_val in enumerate(self.raw_data_dict['measured_values']): - dat = meas_val[0] # hardcoded for 1 channel for now + meas_val = self.raw_data_dict['measured_values'] + unit = self.raw_data_dict['value_units'][0] + # loop through channels + shots = np.zeros((2, len(meas_val),), dtype=np.ndarray) + for j, dat in enumerate(meas_val): + assert unit == self.raw_data_dict['value_units'][j], 'The channels have been measured using different units. This is not supported yet.' sh_0, sh_1 = get_shots_zero_one( dat, post_select=post_select, nr_samples=nr_samples, post_select_threshold=post_select_threshold, sample_0=sample_0, sample_1=sample_1) - min_sh = np.min(sh_0) - max_sh = np.max(sh_1) - self.proc_data_dict['shots_0'][i] = sh_0 - self.proc_data_dict['shots_1'][i] = sh_1 - self.proc_data_dict['nr_shots'][i] = len(sh_0) + shots[0, j] = sh_0 + shots[1, j] = sh_1 + #shots = np.array(shots, dtype=float) + + # Do we have two quadratures? + if len(meas_val) == 2: + ######################################################## + # + ######################################################## + data_range_x = (np.min([np.min(b) for b in shots[:, 0]]), + np.max([np.max(b) for b in shots[:, 0]])) + data_range_y = (np.min([np.min(b) for b in shots[:, 1]]), + np.max([np.max(b) for b in shots[:, 1]])) + data_range_xy = (data_range_x, data_range_y) + nr_bins_2D = self.options_dict.get('nr_bins_2D', 6*np.sqrt(nr_bins)) + H0, xedges, yedges = np.histogram2d(x=shots[0, 0], + y=shots[0, 1], + bins=nr_bins_2D, + range=data_range_xy) + H1, xedges, yedges = np.histogram2d(x=shots[1, 0], + y=shots[1, 1], + bins=nr_bins_2D, + range=data_range_xy) + binsize_x = xedges[1] - xedges[0] + binsize_y = yedges[1] - yedges[0] + bin_centers_x = xedges[:-1] + binsize_x + bin_centers_y = yedges[:-1] + binsize_y + self.proc_data_dict['2D_histogram_x'] = bin_centers_x + self.proc_data_dict['2D_histogram_y'] = bin_centers_y + self.proc_data_dict['2D_histogram_z'] = [H0, H1] + + # Find and apply the effective/rotated integrated voltage + angle = self.options_dict.get('rotation_angle', 0) + auto_angle = self.options_dict.get('auto_rotation_angle', True) + if auto_angle: + ########################################## + # Determining the rotation of the data # + ########################################## + gauss2D_model_0 = lmfit.Model(gaussian_2D, + independent_vars=['x', 'y']) + gauss2D_model_1 = lmfit.Model(gaussian_2D, + independent_vars=['x', 'y']) + guess0 = gauss_2D_guess(model=gauss2D_model_0, data=H0.transpose(), + x=bin_centers_x, y=bin_centers_y) + guess1 = gauss_2D_guess(model=gauss2D_model_1, data=H1.transpose(), + x=bin_centers_x, y=bin_centers_y) + + x2d = np.array([bin_centers_x]*len(bin_centers_y)) + y2d = np.array([bin_centers_y]*len(bin_centers_x)).transpose() + fitres0 = gauss2D_model_0.fit(data=H0.transpose(), x=x2d, y=y2d, + **guess0) + fitres1 = gauss2D_model_1.fit(data=H1.transpose(), x=x2d, y=y2d, + **guess1) + + fr0 = fitres0.best_values + fr1 = fitres1.best_values + x0 = fr0['center_x'] + x1 = fr1['center_x'] + y0 = fr0['center_y'] + y1 = fr1['center_y'] + + self.proc_data_dict['IQ_pos'] = [[x0, x1], [y0, y1]] + dx = x1 - x0 + dy = y1 - y0 + mid = [x0 + dx/2, y0 + dy/2] + angle = np.arctan2(dy, dx) + else: + mid = [0, 0] + + if self.verbose: + ang_deg = (angle*180/np.pi) + print('Mixing I/Q channels with %.3f degrees '%ang_deg + + #'around point (%.2f, %.2f)%s'%(mid[0], mid[1], unit) + + ' to obtain effective voltage.') + + self.proc_data_dict['raw_offset'] = [*mid, angle] + # create matrix + rot_mat = [[+np.cos(-angle), -np.sin(-angle)], + [+np.sin(-angle), +np.cos(-angle)]] + # rotate data accordingly + eff_sh = np.zeros(len(shots[0]), dtype=np.ndarray) + eff_sh[0] = np.dot(rot_mat[0], shots[0])# - mid + eff_sh[1] = np.dot(rot_mat[0], shots[1])# - mid + else: + # If we have only one quadrature, use that (doh!) + eff_sh = shots[:, 0] + + self.proc_data_dict['all_channel_int_voltages'] = shots + self.proc_data_dict['shots_xlabel'] = 'Effective integrated Voltage'#self.raw_data_dict['value_names'][0] + self.proc_data_dict['shots_xunit'] = unit + self.proc_data_dict['eff_int_voltages'] = eff_sh + self.proc_data_dict['nr_shots'] = [len(eff_sh[0]), len(eff_sh[1])] + sh_min = min(np.min(eff_sh[0]), np.min(eff_sh[1])) + sh_max = max(np.max(eff_sh[0]), np.max(eff_sh[1])) + data_range = (sh_min, sh_max) + + eff_sh_sort = np.sort(list(eff_sh), axis=1) + x0, n0 = np.unique(eff_sh_sort[0], return_counts=True) + cumsum0 = np.cumsum(n0) + x1, n1 = np.unique(eff_sh_sort[1], return_counts=True) + cumsum1 = np.cumsum(n1) + + self.proc_data_dict['cumsum_x'] = [x0, x1] + self.proc_data_dict['cumsum_y'] = [cumsum0, cumsum1] + + all_x = np.unique(np.sort(np.concatenate((x0, x1)))) + md = self.options_dict.get('max_datapoints', 1000) + if len(all_x) > md: + all_x = np.linspace(*data_range, md) + ecumsum0 = np.interp(x=all_x, xp=x0, fp=cumsum0, left=0) + necumsum0 = ecumsum0/np.max(ecumsum0) + ecumsum1 = np.interp(x=all_x, xp=x1, fp=cumsum1, left=0) + necumsum1 = ecumsum1/np.max(ecumsum1) + + self.proc_data_dict['cumsum_x_ds'] = all_x + self.proc_data_dict['cumsum_y_ds'] = [ecumsum0, ecumsum1] + self.proc_data_dict['cumsum_y_ds_n'] = [necumsum0, necumsum1] ################################## # Binning data into histograms # ################################## - self.proc_data_dict['hist_0'] = np.histogram( - self.proc_data_dict['shots_0'][0], bins=nr_bins, - range=(min_sh, max_sh)) - # range given to ensure both use histograms use same bins - self.proc_data_dict['hist_1'] = np.histogram( - self.proc_data_dict['shots_1'][0], bins=nr_bins, - range=(min_sh, max_sh)) - - self.proc_data_dict['bin_centers'] = ( - self.proc_data_dict['hist_0'][1][:-1] + - self.proc_data_dict['hist_0'][1][1:]) / 2 - self.proc_data_dict['binsize'] = (self.proc_data_dict['hist_0'][1][1] - - self.proc_data_dict['hist_0'][1][0]) - ########################## - # Cumulative histograms # - ########################## - - # the cumulative histograms are normalized to ensure the right - # fidelities can be calculated - self.proc_data_dict['cumhist_0'] = np.cumsum( - self.proc_data_dict['hist_0'][0])/( - np.sum(self.proc_data_dict['hist_0'][0])) - self.proc_data_dict['cumhist_1'] = np.cumsum( - self.proc_data_dict['hist_1'][0])/( - np.sum(self.proc_data_dict['hist_1'][0])) - - self.proc_data_dict['shots_xlabel'] = \ - self.raw_data_dict['value_names'][0][0] - self.proc_data_dict['shots_xunit'] = \ - self.raw_data_dict['value_units'][0][0] - - ########################################################### - # Threshold and fidelity based on cumulative histograms # - ########################################################### + h0, bin_edges = np.histogram(eff_sh[0], bins=nr_bins, + range=data_range) + h1, bin_edges = np.histogram(eff_sh[1], bins=nr_bins, + range=data_range) + self.proc_data_dict['hist'] = [h0, h1] + binsize = (bin_edges[1] - bin_edges[0]) + self.proc_data_dict['bin_edges'] = bin_edges + self.proc_data_dict['bin_centers'] = bin_edges[:-1]+binsize + self.proc_data_dict['binsize'] = binsize + + ####################################################### + # Threshold and fidelity based on culmulative counts # + ####################################################### # Average assignment fidelity: F_ass = (P01 - P10 )/2 # where Pxy equals probability to measure x when starting in y - F_vs_th = (1-(1-abs(self.proc_data_dict['cumhist_1'] - - self.proc_data_dict['cumhist_0']))/2) - opt_idx = np.argmax(F_vs_th) + F_vs_th = (1-(1-abs(necumsum0 - necumsum1))/2) + opt_idxs = np.argwhere(F_vs_th == np.amax(F_vs_th)) + opt_idx = int(round(np.average(opt_idxs))) self.proc_data_dict['F_assignment_raw'] = F_vs_th[opt_idx] - self.proc_data_dict['threshold_raw'] = \ - self.proc_data_dict['bin_centers'][opt_idx] + self.proc_data_dict['threshold_raw'] = all_x[opt_idx] + def prepare_fitting(self): self.fit_dicts = OrderedDict() - # An initial guess is done on the single guassians to constrain - # the fit params and avoid fitting noise if - # e.g., mmt. ind. rel. is very low - gmod0 = lmfit.models.GaussianModel() - guess0 = gmod0.guess(data=self.proc_data_dict['hist_0'][0], - x=self.proc_data_dict['bin_centers']) - gmod1 = lmfit.models.GaussianModel() - guess1 = gmod1.guess(data=self.proc_data_dict['hist_1'][0], - x=self.proc_data_dict['bin_centers']) - - DoubleGaussMod_0 = (lmfit.models.GaussianModel(prefix='A_') + - lmfit.models.GaussianModel(prefix='B_')) - DoubleGaussMod_0.set_param_hint( - 'A_center', - value=guess0['center'], - min=guess0['center']-2*guess0['sigma'], - max=guess0['center']+2*guess0['sigma']) - DoubleGaussMod_0.set_param_hint( - 'B_center', - value=guess1['center'], - min=guess1['center']-2*guess1['sigma'], - max=guess1['center']+2*guess1['sigma']) - # This way of assigning makes the guess function a method of the - # model (ensures model/self is passed as first argument. - DoubleGaussMod_0.guess = fit_mods.double_gauss_guess.__get__( - DoubleGaussMod_0, DoubleGaussMod_0.__class__) - - # Two instances of the model are required to avoid - # memory interference between the two fits - DoubleGaussMod_1 = (lmfit.models.GaussianModel(prefix='A_') + - lmfit.models.GaussianModel(prefix='B_')) - DoubleGaussMod_1.set_param_hint( - 'A_center', - value=guess0['center'], - min=guess0['center']-2*guess0['sigma'], - max=guess0['center']+2*guess0['sigma']) - DoubleGaussMod_1.set_param_hint( - 'B_center', - value=guess1['center'], - min=guess1['center']-2*guess1['sigma'], - max=guess1['center']+2*guess1['sigma']) - DoubleGaussMod_1.guess = fit_mods.double_gauss_guess.__get__( - DoubleGaussMod_1, DoubleGaussMod_1.__class__) - - self.fit_dicts['shots_0'] = { - 'model': DoubleGaussMod_0, - # 'fit_guess_fn': DoubleGaussMod_0.guess, - 'fit_xvals': {'x': self.proc_data_dict['bin_centers']}, - 'fit_yvals': {'data': self.proc_data_dict['hist_0'][0]}} - - self.fit_dicts['shots_1'] = { - 'model': DoubleGaussMod_1, - # 'fit_guess_fn': DoubleGaussMod_1.guess, - 'fit_xvals': {'x': self.proc_data_dict['bin_centers']}, - 'fit_yvals': {'data': self.proc_data_dict['hist_1'][0]}} + bin_x = self.proc_data_dict['bin_centers'] + bin_xs = [bin_x, bin_x] + bin_ys = self.proc_data_dict['hist'] + m = lmfit.model.Model(ro_gauss) + m.guess = ro_double_gauss_guess.__get__(m, m.__class__) + params = m.guess(x=bin_xs, data=bin_ys, + fixed_p01=self.options_dict.get('fixed_p01', False), + fixed_p10=self.options_dict.get('fixed_p10', False)) + res = m.fit(x=bin_xs, data=bin_ys, params=params) + + self.fit_dicts['shots_all_hist'] = { + 'model': m, + 'fit_xvals': {'x': bin_xs}, + 'fit_yvals': {'data': bin_ys}, + 'guessfn_pars': {'fixed_p01': self.options_dict.get('fixed_p01', False), + 'fixed_p10': self.options_dict.get('fixed_p10', False)}, + } + + m_cul = lmfit.model.Model(ro_CDF) + cdf_xs = self.proc_data_dict['cumsum_x_ds'] + cdf_xs = [np.array(cdf_xs), np.array(cdf_xs)] + cdf_ys = self.proc_data_dict['cumsum_y_ds'] + cdf_ys = [np.array(cdf_ys[0]), np.array(cdf_ys[1])] + #cul_res = m_cul.fit(x=cdf_xs, data=cdf_ys, params=res.params) + cum_params = res.params + cum_params['A_amplitude'].value = np.max(cdf_ys[0]) + cum_params['A_amplitude'].vary = False + cum_params['B_amplitude'].value = np.max(cdf_ys[1]) + cum_params['A_amplitude'].vary = False + self.fit_dicts['shots_all'] = { + 'model': m_cul, + 'fit_xvals': {'x': cdf_xs}, + 'fit_yvals': {'data': cdf_ys}, + 'guess_pars': cum_params, + } + def analyze_fit_results(self): # Create a CDF based on the fit functions of both fits. - fr_0 = self.fit_res['shots_0'] - fr_1 = self.fit_res['shots_1'] - bv0 = fr_0.best_values - bv1 = fr_1.best_values - norm_factor = 1/(self.proc_data_dict['binsize'] * - self.proc_data_dict['nr_shots'][0]) + fr = self.fit_res['shots_all'] + bv = fr.best_values + + bvn = deepcopy(bv) + bvn['A_amplitude'] = 1 + bvn['B_amplitude'] = 1 + def CDF(x): + return ro_CDF(x=x, **bvn) def CDF_0(x): - return fit_mods.double_gaussianCDF( - x, A_amplitude=bv0['A_amplitude']*norm_factor, - A_sigma=bv0['A_sigma'], A_mu=bv0['A_center'], - B_amplitude=bv0['B_amplitude']*norm_factor, - B_sigma=bv0['B_sigma'], B_mu=bv0['B_center']) + return CDF(x=[x, x])[0] def CDF_1(x): - return fit_mods.double_gaussianCDF( - x, A_amplitude=bv1['A_amplitude']*norm_factor, - A_sigma=bv1['A_sigma'], A_mu=bv1['A_center'], - B_amplitude=bv1['B_amplitude']*norm_factor, - B_sigma=bv1['B_sigma'], B_mu=bv1['B_center']) + return CDF(x=[x, x])[1] def infid_vs_th(x): - return (1-abs(CDF_0(x) - CDF_1(x)))/2 + cdf = ro_CDF(x=[x, x], **bvn) + return (1-np.abs(cdf[0] - cdf[1]))/2 self._CDF_0 = CDF_0 self._CDF_1 = CDF_1 self._infid_vs_th = infid_vs_th - opt_fid = minimize(infid_vs_th, (bv0['A_center']+bv0['B_center'])/2) + thr_guess = (3*bv['B_center'] - bv['A_center'])/2 + opt_fid = minimize(infid_vs_th, thr_guess) # for some reason the fit sometimes returns a list of values if isinstance(opt_fid['fun'], float): @@ -227,243 +319,417 @@ def infid_vs_th(x): ########################################### # Extracting the discrimination fidelity # ########################################### - if bv0['A_amplitude'] > bv0['B_amplitude']: - mu_0 = bv0['A_center'] - sigma_0 = bv0['A_sigma'] - # under the assumption of perfect gates and no mmt induced exc. - self.proc_data_dict['residual_excitation'] = \ - norm_factor * bv0['B_amplitude'] - else: - mu_0 = bv0['B_center'] - sigma_0 = bv0['B_sigma'] - # under the assumption of perfect gates and no mmt induced exc. - self.proc_data_dict['residual_excitation'] = \ - norm_factor * bv0['A_amplitude'] - - if bv1['A_amplitude'] > bv1['B_amplitude']: - mu_1 = bv1['A_center'] - sigma_1 = bv1['A_sigma'] - # under the assumption of perfect gates and no mmt induced exc. - self.proc_data_dict['measurement_induced_relaxation'] = \ - norm_factor * bv1['B_amplitude'] - - else: - mu_1 = bv1['B_center'] - sigma_1 = bv1['B_sigma'] - # under the assumption of perfect gates and no mmt induced exc. - self.proc_data_dict['measurement_induced_relaxation'] = \ - norm_factor * bv1['A_amplitude'] def CDF_0_discr(x): - return fit_mods.gaussianCDF(x, 1, mu=mu_0, sigma=sigma_0) + return gaussianCDF(x, amplitude=1, + mu=bv['A_center'], sigma=bv['A_sigma']) def CDF_1_discr(x): - return fit_mods.gaussianCDF(x, 1, mu=mu_1, sigma=sigma_1) + return gaussianCDF(x, amplitude=1, + mu=bv['B_center'], sigma=bv['B_sigma']) def disc_infid_vs_th(x): - return (1-abs(CDF_0_discr(x) - CDF_1_discr(x)))/2 + cdf0 = gaussianCDF(x, amplitude=1, mu=bv['A_center'], + sigma=bv['A_sigma']) + cdf1 = gaussianCDF(x, amplitude=1, mu=bv['B_center'], + sigma=bv['B_sigma']) + return (1-np.abs(cdf0 - cdf1))/2 self._CDF_0_discr = CDF_0_discr self._CDF_1_discr = CDF_1_discr self._disc_infid_vs_th = disc_infid_vs_th - opt_fid = minimize(disc_infid_vs_th, (mu_0 + mu_1)/2) + opt_fid_discr = minimize(disc_infid_vs_th, thr_guess) # for some reason the fit sometimes returns a list of values - if isinstance(opt_fid['fun'], float): - self.proc_data_dict['F_discr'] = (1-opt_fid['fun']) + if isinstance(opt_fid_discr['fun'], float): + self.proc_data_dict['F_discr'] = (1-opt_fid_discr['fun']) else: - self.proc_data_dict['F_discr'] = (1-opt_fid['fun'])[0] + self.proc_data_dict['F_discr'] = (1-opt_fid_discr['fun'])[0] + + self.proc_data_dict['threshold_discr'] = opt_fid_discr['x'][0] - self.proc_data_dict['threshold_discr'] = opt_fid['x'][0] + fr = self.fit_res['shots_all'] + bv = fr.params + self.proc_data_dict['residual_excitation'] = bv['B_spurious'].value + self.proc_data_dict['measurement_induced_relaxation'] = bv['A_spurious'].value def prepare_plots(self): - # N.B. If the log option is used we should manually set the - # yscale to go from .5 to the current max as otherwise the fits - # mess up the log plots. + # Did we load two voltage components (shall we do 2D plots?) + two_dim_data = len(self.proc_data_dict['all_channel_int_voltages'][0]) == 2 + + eff_voltage_label = self.proc_data_dict['shots_xlabel'] + eff_voltage_unit = self.proc_data_dict['shots_xunit'] + x_volt_label = self.raw_data_dict['value_names'][0] + x_volt_unit = self.raw_data_dict['value_units'][0] + if two_dim_data: + y_volt_label = self.raw_data_dict['value_names'][1] + y_volt_unit = self.raw_data_dict['value_units'][1] + z_hist_label = 'Counts' + label_0 = '|g> prep.' + label_1 = '|e> prep.' + title = ('\n' + self.timestamps[0] + ' - "' + + self.raw_data_dict['measurementstring'] + '"') + + + #### 1D histograms log_hist = self.options_dict.get('log_hist', False) - - # The histograms - self.plot_dicts['1D_histogram'] = { + bin_x = self.proc_data_dict['bin_edges'] + bin_y = self.proc_data_dict['hist'] + self.plot_dicts['hist_0'] = { + 'title': 'Binned Shot Counts' + title, + 'ax_id' : '1D_histogram', 'plotfn': self.plot_bar, - 'xvals': self.proc_data_dict['hist_0'][1], - 'yvals': self.proc_data_dict['hist_0'][0], + 'xvals': bin_x, + 'yvals': bin_y[0], + 'xwidth' : self.proc_data_dict['binsize'], 'bar_kws': {'log': log_hist, 'alpha': .4, 'facecolor': 'C0', 'edgecolor': 'C0'}, - 'setlabel': 'Shots 0', - 'xlabel': self.proc_data_dict['shots_xlabel'], - 'xunit': self.proc_data_dict['shots_xunit'], - 'ylabel': 'Counts', - 'title': (self.timestamps[0] + ' \n' + - self.raw_data_dict['measurementstring'][0])} + 'setlabel': label_0, + 'xlabel': eff_voltage_label, + 'xunit': eff_voltage_unit, + 'ylabel': z_hist_label, + } + self.plot_dicts['hist_1'] = { 'ax_id': '1D_histogram', 'plotfn': self.plot_bar, - 'xvals': self.proc_data_dict['hist_1'][1], - 'yvals': self.proc_data_dict['hist_1'][0], - 'bar_kws': {'log': log_hist, 'alpha': .4, 'facecolor': 'C3', + 'xvals': bin_x, + 'yvals': bin_y[1], + 'xwidth' : self.proc_data_dict['binsize'], + 'bar_kws': {'log': log_hist, 'alpha': .3, 'facecolor': 'C3', 'edgecolor': 'C3'}, - 'setlabel': 'Shots 1', 'do_legend': True, - 'xlabel': self.proc_data_dict['shots_xlabel'], - 'xunit': self.proc_data_dict['shots_xunit'], - 'ylabel': 'Counts'} + 'setlabel': label_1, + 'do_legend': True, + 'xlabel': eff_voltage_label, + 'xunit': eff_voltage_unit, + 'ylabel': z_hist_label, + } + if log_hist: + self.plot_dicts['hist_0']['yrange'] = (0.5, 1.5*np.max(bin_y[0])) + self.plot_dicts['hist_1']['yrange'] = (0.5, 1.5*np.max(bin_y[1])) + + #### CDF + cdf_xs = self.proc_data_dict['cumsum_x'] + cdf_ys = self.proc_data_dict['cumsum_y'] + cdf_ys[0] = cdf_ys[0]/np.max(cdf_ys[0]) + cdf_ys[1] = cdf_ys[1]/np.max(cdf_ys[1]) + xra = (bin_x[0], bin_x[-1]) + + self.plot_dicts['cdf_shots_0'] = { + 'title': 'Culmulative Shot Counts (no binning)' + title, + 'ax_id': 'cdf', + 'plotfn': self.plot_line, + 'xvals': cdf_xs[0], + 'yvals': cdf_ys[0], + 'setlabel': label_0, + 'xrange': xra, + 'line_kws': {'color': 'C0', 'alpha': 0.3}, + 'marker': '', + 'xlabel': eff_voltage_label, + 'xunit': eff_voltage_unit, + 'ylabel': 'Culmulative Counts', + 'yunit': 'norm.', + 'do_legend': True, + } + self.plot_dicts['cdf_shots_1'] = { + 'ax_id': 'cdf', + 'plotfn': self.plot_line, + 'xvals': cdf_xs[1], + 'yvals': cdf_ys[1], + 'setlabel': label_1, + 'line_kws': {'color': 'C3', 'alpha': 0.3}, + 'marker': '', + 'xlabel': eff_voltage_label, + 'xunit': eff_voltage_unit, + 'ylabel': 'Culmulative Counts', + 'yunit': 'norm.', + 'do_legend': True, + } + + ### Vlines for thresholds + th_raw = self.proc_data_dict['threshold_raw'] + threshs = [th_raw,] + if self.do_fitting: + threshs.append(self.proc_data_dict['threshold_fit']) + threshs.append(self.proc_data_dict['threshold_discr']) + + for ax in ['1D_histogram', 'cdf']: + self.plot_dicts[ax+'_vlines_thresh'] = { + 'ax_id': ax, + 'plotfn': self.plot_vlines_auto, + 'xdata': threshs, + 'linestyles': ['--', '-.', ':'], + 'labels': ['$th_{raw}$', '$th_{fit}$', '$th_{d}$'], + 'colors': ['0.3', '0.5', '0.2'], + 'do_legend': True, + } + + #### 2D Histograms + if two_dim_data: + iq_centers = None + if 'IQ_pos' in self.proc_data_dict and self.proc_data_dict['IQ_pos'] is not None: + iq_centers = self.proc_data_dict['IQ_pos'] + peak_marker_2D = { + 'plotfn': self.plot_line, + 'xvals': iq_centers[1], + 'yvals': iq_centers[0], + 'xlabel': x_volt_label, + 'xunit': x_volt_unit, + 'ylabel': y_volt_label, + 'yunit': y_volt_unit, + 'marker': 'x', + 'linestyle': '', + 'color': 'black', + #'line_kws': {'markersize': 1, 'color': 'black', 'alpha': 1}, + 'setlabel': 'Peaks', + 'do_legend': True, + } + peak_marker_2D_rot = deepcopy(peak_marker_2D) + peak_marker_2D_rot['xvals'] = iq_centers[0] + peak_marker_2D_rot['yvals'] = iq_centers[1] + + self.plot_dicts['2D_histogram_0'] = { + 'title': 'Raw '+label_0+' Binned Shot Counts' + title, + 'ax_id': '2D_histogram_0', + 'plotfn': self.plot_colorxy, + 'xvals': self.proc_data_dict['2D_histogram_y'], + 'yvals': self.proc_data_dict['2D_histogram_x'], + 'zvals': self.proc_data_dict['2D_histogram_z'][0], + 'xlabel': x_volt_label, + 'xunit': x_volt_unit, + 'ylabel': y_volt_label, + 'yunit': y_volt_unit, + 'zlabel': z_hist_label, + 'zunit': '-', + 'cmap': 'Blues', + } + if iq_centers is not None: + dp = deepcopy(peak_marker_2D) + dp['ax_id'] = '2D_histogram_0' + self.plot_dicts['2D_histogram_0_marker'] = dp + + self.plot_dicts['2D_histogram_1'] = { + 'title': 'Raw '+label_1+' Binned Shot Counts' + title, + 'ax_id': '2D_histogram_1', + 'plotfn': self.plot_colorxy, + 'xvals': self.proc_data_dict['2D_histogram_y'], + 'yvals': self.proc_data_dict['2D_histogram_x'], + 'zvals': self.proc_data_dict['2D_histogram_z'][1], + 'xlabel': x_volt_label, + 'xunit': x_volt_unit, + 'ylabel': y_volt_label, + 'yunit': y_volt_unit, + 'zlabel': z_hist_label, + 'zunit': '-', + 'cmap': 'Reds', + } + if iq_centers is not None: + dp = deepcopy(peak_marker_2D) + dp['ax_id'] = '2D_histogram_1' + self.plot_dicts['2D_histogram_1_marker'] = dp + + #### Scatter Shots + volts = self.proc_data_dict['all_channel_int_voltages'] + vxr = [np.min([np.min(a) for a in volts[:][1]]), + np.max([np.max(a) for a in volts[:][1]])] + vyr = [np.min([np.min(a) for a in volts[:][0]]), + np.max([np.max(a) for a in volts[:][0]])] + self.plot_dicts['2D_shots_0'] = { + 'title': 'Raw Shots' + title, + 'ax_id': '2D_shots', + 'plotfn': self.plot_line, + 'xvals': volts[0][1], + 'yvals': volts[0][0], + #'range': [vxr, vyr], + #'xrange': vxr, + #'yrange': vyr, + 'xlabel': x_volt_label, + 'xunit': x_volt_unit, + 'ylabel': y_volt_label, + 'yunit': y_volt_unit, + 'zlabel': z_hist_label, + 'marker': 'o', + 'linestyle': '', + 'color': 'C0', + 'line_kws': {'markersize': 0.25, 'color': 'C0', 'alpha': 0.5}, + 'setlabel': label_0, + 'do_legend': True, + } + self.plot_dicts['2D_shots_1'] = { + 'ax_id': '2D_shots', + 'plotfn': self.plot_line, + 'xvals': volts[1][1], + 'yvals': volts[1][0], + #'range': [vxr, vyr], + #'xrange': vxr, + #'yrange': vyr, + 'xlabel': x_volt_label, + 'xunit': x_volt_unit, + 'ylabel': y_volt_label, + 'yunit': y_volt_unit, + 'zlabel': z_hist_label, + 'marker': 'o', + 'linestyle': '', + 'color': 'C3', + 'line_kws': {'markersize': 0.25, 'color': 'C3', 'alpha': 0.5}, + 'setlabel': label_1, + 'do_legend': True, + } + if iq_centers is not None: + dp = deepcopy(peak_marker_2D) + dp['ax_id'] = '2D_shots' + self.plot_dicts['2D_shots_marker'] = dp # The cumulative histograms - self.plot_dicts['cum_histogram'] = { - 'plotfn': self.plot_bar, - 'xvals': self.proc_data_dict['hist_0'][1], - 'yvals': self.proc_data_dict['cumhist_0'], - 'bar_kws': {'log': False, 'alpha': .4, 'facecolor': 'C0', - 'edgecolor': 'C0'}, - 'setlabel': 'Shots 0', - 'xlabel': self.proc_data_dict['shots_xlabel'], - 'xunit': self.proc_data_dict['shots_xunit'], - 'ylabel': 'Counts', - 'title': 'Cumulative Histograms' + '\n'+self.timestamps[0]} - self.plot_dicts['cumhist_1'] = { - 'ax_id': 'cum_histogram', - 'plotfn': self.plot_bar, - 'xvals': self.proc_data_dict['hist_1'][1], - 'yvals': self.proc_data_dict['cumhist_1'], - 'bar_kws': {'log': False, 'alpha': .4, 'facecolor': 'C3', - 'edgecolor': 'C3'}, - 'setlabel': 'Shots 1', 'do_legend': True, - 'xlabel': self.proc_data_dict['shots_xlabel'], - 'xunit': self.proc_data_dict['shots_xunit'], - 'ylabel': 'Counts'} - ##################################### # Adding the fits to the figures # ##################################### if self.do_fitting: - self.plot_dicts['fit_shots_0'] = { + #todo: add seperate fits for residual and main gaussians + x = np.linspace(bin_x[0], bin_x[-1], 150) + para_hist_tmp = self.fit_res['shots_all_hist'].best_values + para_cdf = self.fit_res['shots_all'].best_values + para_hist = para_cdf + para_hist['A_amplitude'] = para_hist_tmp['A_amplitude'] + para_hist['B_amplitude'] = para_hist_tmp['B_amplitude'] + + ro_g = ro_gauss(x=[x, x], **para_hist) + self.plot_dicts['new_fit_shots_0'] = { 'ax_id': '1D_histogram', - 'plotfn': self.plot_fit, - 'fit_res': self.fit_dicts['shots_0']['fit_res'], - 'plot_init': self.options_dict['plot_init'], - 'setlabel': 'Fit shots 0', + 'plotfn': self.plot_line, + 'xvals': x, + 'yvals': ro_g[0], + 'setlabel': 'Fit '+label_0, 'line_kws': {'color': 'C0'}, - 'do_legend': True} - self.plot_dicts['fit_shots_1'] = { + 'marker': '', + 'do_legend': True, + } + self.plot_dicts['new_fit_shots_1'] = { 'ax_id': '1D_histogram', - 'plotfn': self.plot_fit, - 'fit_res': self.fit_dicts['shots_1']['fit_res'], - 'plot_init': self.options_dict['plot_init'], - 'setlabel': 'Fit shots 1', + 'plotfn': self.plot_line, + 'xvals': x, + 'yvals': ro_g[1], + 'marker': '', + 'setlabel': 'Fit '+label_1, 'line_kws': {'color': 'C3'}, - 'do_legend': True} + 'do_legend': True, + } - x = np.linspace(self.proc_data_dict['bin_centers'][0], - self.proc_data_dict['bin_centers'][-1], 100) self.plot_dicts['cdf_fit_shots_0'] = { - 'ax_id': 'cum_histogram', + 'ax_id': 'cdf', 'plotfn': self.plot_line, 'xvals': x, 'yvals': self._CDF_0(x), - 'setlabel': 'Fit shots 0', - 'line_kws': {'color': 'C0'}, + 'setlabel': 'Fit '+label_0, + 'line_kws': {'color': 'C0', 'alpha': 0.8}, + 'linestyle': ':', 'marker': '', - 'do_legend': True} + 'do_legend': True, + } self.plot_dicts['cdf_fit_shots_1'] = { - 'ax_id': 'cum_histogram', + 'ax_id': 'cdf', 'plotfn': self.plot_line, 'xvals': x, 'yvals': self._CDF_1(x), 'marker': '', - 'setlabel': 'Fit shots 1', - 'line_kws': {'color': 'C3'}, - 'do_legend': True} - - ########################################### - # Thresholds and fidelity information # - ########################################### - + 'linestyle': ':', + 'setlabel': 'Fit '+label_1, + 'line_kws': {'color': 'C3', 'alpha': 0.8}, + 'do_legend': True, + } + + ########################################## + # Add textbox (eg.g Thresholds, fidelity # + # information, number of shots etc) # + ########################################## if not self.presentation_mode: - max_cnts = np.max([np.max(self.proc_data_dict['hist_0'][0]), - np.max(self.proc_data_dict['hist_1'][0])]) - + fit_text = 'Thresholds:' + fit_text += '\nName | Level | Fidelity' thr, th_unit = SI_val_to_msg_str( self.proc_data_dict['threshold_raw'], - self.proc_data_dict['shots_xunit'], return_type=float) - + eff_voltage_unit, return_type=float) raw_th_msg = ( - 'Raw threshold: {:.2f} {}\n'.format( - thr, th_unit) + - r'$F_{A}$-raw: ' + - r'{:.3f}'.format( - self.proc_data_dict['F_assignment_raw'])) - self.plot_dicts['cumhist_threshold'] = { - 'ax_id': '1D_histogram', - 'plotfn': self.plot_vlines, - 'x': self.proc_data_dict['threshold_raw'], - 'ymin': 0, - 'ymax': max_cnts*1.05, - 'colors': '.3', - 'linestyles': 'dashed', - 'line_kws': {'linewidth': .8}, - 'setlabel': raw_th_msg, - 'do_legend': True} + '\n>raw | ' + + '{:.2f} {} | '.format(thr, th_unit) + + '{:.1f}%'.format( + self.proc_data_dict['F_assignment_raw']*100)) + + fit_text += raw_th_msg + if self.do_fitting: thr, th_unit = SI_val_to_msg_str( self.proc_data_dict['threshold_fit'], - self.proc_data_dict['shots_xunit'], return_type=float) + eff_voltage_unit, return_type=float) fit_th_msg = ( - 'Fit threshold: {:.2f} {}\n'.format( - thr, th_unit) + - r'$F_{A}$-fit: ' + - r'{:.3f}'.format(self.proc_data_dict['F_assignment_fit'])) - - self.plot_dicts['fit_threshold'] = { - 'ax_id': '1D_histogram', - 'plotfn': self.plot_vlines, - 'x': self.proc_data_dict['threshold_fit'], - 'ymin': 0, - 'ymax': max_cnts*1.05, - 'colors': '.4', - 'linestyles': 'dotted', - 'line_kws': {'linewidth': .8}, - 'setlabel': fit_th_msg, - 'do_legend': True} + '\n>fit | ' + + '{:.2f} {} | '.format(thr, th_unit) + + '{:.1f}%'.format( + self.proc_data_dict['F_assignment_fit']*100)) + fit_text += fit_th_msg thr, th_unit = SI_val_to_msg_str( self.proc_data_dict['threshold_discr'], - self.proc_data_dict['shots_xunit'], return_type=float) + eff_voltage_unit, return_type=float) fit_th_msg = ( - 'Discr. threshold: {:.2f} {}\n'.format( - thr, th_unit) + - r'$F_{D}$: ' + - ' {:.3f}'.format(self.proc_data_dict['F_discr'])) - self.plot_dicts['discr_threshold'] = { - 'ax_id': '1D_histogram', - 'plotfn': self.plot_vlines, - 'x': self.proc_data_dict['threshold_discr'], - 'ymin': 0, - 'ymax': max_cnts*1.05, - 'colors': '.3', - 'linestyles': '-.', - 'line_kws': {'linewidth': .8}, - 'setlabel': fit_th_msg, - 'do_legend': True} - - # To add text only to the legend I create some "fake" data - rel_exc_str = ('Mmt. Ind. Rel.: {:.1f}%\n'.format( - self.proc_data_dict['measurement_induced_relaxation']*100) + - 'Residual Exc.: {:.1f}%'.format( - self.proc_data_dict['residual_excitation']*100)) - self.plot_dicts['rel_exc_msg'] = { - 'ax_id': '1D_histogram', - 'plotfn': self.plot_line, - 'xvals': [self.proc_data_dict['threshold_discr']], - 'yvals': [max_cnts/2], - 'line_kws': {'alpha': 0}, - 'setlabel': rel_exc_str, - 'do_legend': True} - + '\n>dis | ' + + '{:.2f} {} | '.format(thr, th_unit) + + '{:.1f}%'.format( + self.proc_data_dict['F_discr']*100)) + fit_text += fit_th_msg + snr = self.fit_res['shots_all'].params['SNR'] + fit_text += '\nSNR (fit) = ${:.3f}\\pm{:.3f}$'.format(snr.value, snr.stderr) + + fr = self.fit_res['shots_all'] + bv = fr.params + a_sp = bv['A_spurious'] + fit_text += '\n\nSpurious Excitations:' + fit_text += '\n$p(e|0) = {:.3f}$'.format(a_sp.value) + if self.options_dict.get('fixed_p01', True) == True: + fit_text += '$\\pm{:.3f}$'.format(a_sp.stderr) + else: + fit_text += ' (fixed)' + + b_sp = bv['B_spurious'] + fit_text += ' \n$p(g|\\pi) = {:.3f}$'.format(b_sp.value) + if self.options_dict.get('fixed_p10', True) == True: + fit_text += '$\\pm{:.3f}$'.format(b_sp.stderr) + else: + fit_text += ' (fixed)' + + if two_dim_data: + offs = self.proc_data_dict['raw_offset'] + #fit_text += '\nOffset from raw:\n' + #fit_text += '({:.3f},{:.3f}) {},\n'.format(offs[0], offs[1], eff_voltage_unit) + fit_text += '\n\nRotated by ${:.1f}^\\circ$'.format((offs[2]*180/np.pi)%180) + auto_rot = self.options_dict.get('auto_rotation_angle', True) + fit_text += '(auto)' if auto_rot else '(man.)' + else: + fit_text += '\n\n(Single quadrature data)' + + fit_text += '\n\nTotal shots: %d+%d'%(*self.proc_data_dict['nr_shots'],) + + for ax in ['cdf', '1D_histogram']: + self.plot_dicts['text_msg_' + ax] = { + 'ax_id': ax, + # 'ypos': 0.15, + 'xpos' : 1.05, + 'horizontalalignment' : 'left', + 'plotfn': self.plot_text, + 'box_props': 'fancy', + 'text_string': fit_text, + } class Multiplexed_Readout_Analysis(ba.BaseDataAnalysis): """ For two qubits, to make an n-qubit mux readout experiment. we should vectorize this analysis + + TODO: This needs to be rewritten/debugged! + Suggestion: + Use N*(N-1)/2 instances of Singleshot_Readout_Analysis, + run them without saving the plots and then merge together the + plot_dicts as in the cross_dephasing_analysis. """ def __init__(self, t_start: str=None, t_stop: str=None, @@ -524,7 +790,6 @@ def process_data(self): self.proc_data_dict['ch_names'] = self.raw_data_dict['value_names'][0] for ch_name, shots in self.raw_data_dict['measured_values_ord_dict'].items(): - # print(ch_name) self.proc_data_dict[ch_name] = shots[0] # only 1 dataset self.proc_data_dict[ch_name + ' all'] = self.proc_data_dict[ch_name] @@ -544,9 +809,9 @@ def process_data(self): # No post selection implemented yet self.proc_data_dict['{} {}'.format(ch_name, comb)] = \ self.proc_data_dict[ch_name][i::number_of_experiments] - ################################## - # Binning data into histograms # - ################################## + ##################################### + # Binning data into 1D histograms # + ##################################### hist_name = 'hist {} {}'.format( ch_name, comb) self.proc_data_dict[hist_name] = np.histogram( @@ -796,3 +1061,4 @@ def make_mux_ssro_histogram(data_dict, ch_name, title=None, ax=None, **kw): if title is not None: ax.set_title(title) + diff --git a/pycqed/analysis_v2/spectroscopy_analysis.py b/pycqed/analysis_v2/spectroscopy_analysis.py index 4a81a7fa13..3c96aaabbf 100644 --- a/pycqed/analysis_v2/spectroscopy_analysis.py +++ b/pycqed/analysis_v2/spectroscopy_analysis.py @@ -18,13 +18,16 @@ class Spectroscopy(ba.BaseDataAnalysis): - def __init__(self, t_start, - options_dict=None, - t_stop=None, - extract_only=False, - auto=True, - do_fitting=False): - super(Spectroscopy, self).__init__(t_start, t_stop=t_stop, + + def __init__(self, t_start: str, + t_stop: str = None, + options_dict: dict = None, + label: str = None, + extract_only: bool = False, + auto: bool = True, + do_fitting: bool = False): + super(Spectroscopy, self).__init__(t_start=t_start, t_stop=t_stop, + label=label, options_dict=options_dict, extract_only=extract_only, do_fitting=do_fitting) @@ -35,6 +38,7 @@ def __init__(self, t_start, 'freq': 'sweep_points', 'amp': 'amp', 'phase': 'phase'} + self.options_dict.get('xwidth', None) # {'xlabel': 'sweep_name', # 'xunit': 'sweep_unit', @@ -45,7 +49,7 @@ def __init__(self, t_start, # 'measured_values': 'measured_values'} if self.extract_fitparams: - self.params_dict.update({'fitparams': 'fit_params'}) + self.params_dict.update({'fitparams': self.options_dict.get('fitparams_key', 'fit_params')}) self.numeric_params = ['freq', 'amp', 'phase'] if 'qubit_label' in self.options_dict: @@ -136,9 +140,7 @@ def prepare_plots(self): 'plotsize': plotsize } else: - plotcbar = self.options_dict.get('colorbar', False) - plot_fn = self.plot_colorx # (self, pdict, axs) - self.plot_dicts['amp'] = {'plotfn': plot_fn, + self.plot_dicts['amp'] = {'plotfn': self.plot_colorx, 'xvals': proc_data_dict['plot_xvals'], 'xwidth': proc_data_dict['plot_xwidth'], 'yvals': proc_data_dict['plot_frequency'], @@ -150,7 +152,13 @@ def prepare_plots(self): 'yrange': proc_data_dict['freq_range'], 'zrange': proc_data_dict['amp_range'], 'plotsize': plotsize, - 'plotcbar': plotcbar + 'plotcbar': self.options_dict.get('colorbar', False), + } + + self.plot_dicts['amp'] = {'plotfn': self.plot_colorx, + 'xvals': proc_data_dict['plot_xvals'], + 'yvals': proc_data_dict['plot_frequency'], + 'zvals': proc_data_dict['plot_amp'], } def plot_for_presentation(self, key_list=None, no_label=False): @@ -160,7 +168,7 @@ def plot_for_presentation(self, key_list=None, no_label=False): pdict = self.plot_dicts[key] if key == 'amp': if pdict['plotfn'] == self.plot_line: - ymin, ymax = 0, 1.2*np.max(np.ravel(pdict['yvals'])) + ymin, ymax = 0, 1.2 * np.max(np.ravel(pdict['yvals'])) self.axs[key].set_ylim(ymin, ymax) self.axs[key].set_ylabel('Transmission amplitude (V rms)') @@ -202,8 +210,7 @@ def process_data(self): self.proc_data_dict['amp_label'] = 'Transmission amplitude (V rms)' self.proc_data_dict['phase_label'] = 'Transmission phase (degrees)' if len(self.raw_data_dict['timestamps']) == 1: - self.proc_data_dict['plot_phase'] = np.unwrap( - np.pi/180.*self.proc_data_dict['plot_phase'])*180/np.pi + self.proc_data_dict['plot_phase'] = np.unwrap(np.pi / 180. * self.proc_data_dict['plot_phase']) * 180 / np.pi self.proc_data_dict['plot_xlabel'] = 'Readout Frequency (Hz)' else: pass @@ -218,8 +225,7 @@ def process_data(self): self.proc_data_dict['real_label'] = 'Real{S21} (V rms)' self.proc_data_dict['imag_label'] = 'Imag{S21} (V rms)' if len(self.raw_data_dict['timestamps']) == 1: - self.proc_data_dict['plot_phase'] = np.unwrap( - np.pi/180.*self.proc_data_dict['plot_phase'])*180/np.pi + self.proc_data_dict['plot_phase'] = np.unwrap(np.pi / 180. * self.proc_data_dict['plot_phase']) * 180 / np.pi self.proc_data_dict['plot_xlabel'] = 'Frequency (Hz)' else: pass @@ -400,8 +406,7 @@ def process_data(self): self.proc_data_dict['amp_label'] = 'Transmission amplitude (V rms)' self.proc_data_dict['phase_label'] = 'Transmission phase (degrees)' if len(self.raw_data_dict['timestamps']) == 1: - self.proc_data_dict['plot_phase'] = np.unwrap( - np.pi/180.*self.proc_data_dict['plot_phase'])*180/np.pi + self.proc_data_dict['plot_phase'] = np.unwrap(np.pi / 180. * self.proc_data_dict['plot_phase']) * 180 / np.pi self.proc_data_dict['plot_xlabel'] = 'Readout Frequency (Hz)' else: pass @@ -453,7 +458,7 @@ def prepare_fitting(self): 'fit_yvals': [{'data': np.squeeze(tt)} for tt in self.plot_amp], 'fit_xvals': np.squeeze([{'f': tt[0]} for tt in self.plot_frequency])} - def do_subtract_background(self, thres=None, back_dict=None,): + def do_subtract_background(self, thres=None, back_dict=None, ): if len(self.raw_data_dict['timestamps']) == 1: pass else: @@ -470,10 +475,11 @@ def do_subtract_background(self, thres=None, back_dict=None,): guess_dict = SlopedHangerFuncAmplitudeGuess(y, x) Q = guess_dict['Q']['value'] f0 = guess_dict['f0']['value'] - df = 2*f0/Q - fmin = f0-df - fmax = f0+df - indices = np.logical_or(x < fmin*1e9, x > fmax*1e9) + df = 2 * f0 / Q + fmin = f0 - df + fmax = f0 + df + indices = np.logical_or(x < fmin * 1e9, x > fmax * 1e9) + x_filtered.append(x[indices]) y_filtered.append(y[indices]) self.background = pd.concat([pd.Series(y_filtered[tt], index=x_filtered[tt]) @@ -483,7 +489,7 @@ def do_subtract_background(self, thres=None, back_dict=None,): amp = background_vals[:, 1] # thres = 0.0065 indices = amp < thres - freq = freq[indices]*1e-9 + freq = freq[indices] * 1e-9 amp = amp[indices] fit_fn = double_cos_linear_offset model = lmfit.Model(fit_fn) @@ -501,8 +507,7 @@ def do_subtract_background(self, thres=None, back_dict=None,): self.background_fit = fit_res for tt in range(len(self.raw_data_dict['timestamps'])): - divide_vals = fit_fn(np.squeeze(self.plot_frequency)[ - tt]*1e-9, **fit_res.best_values) + divide_vals = fit_fn(np.squeeze(self.plot_frequency)[tt] * 1e-9, **fit_res.best_values) self.plot_amp[tt] = np.array( [np.array([np.divide(np.squeeze(self.plot_amp[tt]), divide_vals)])]).transpose() @@ -515,17 +520,19 @@ def plot_fitting(self): fit_results = fit_dict['fit_res'] ax = self.axs['amp'] if len(self.raw_data_dict['timestamps']) == 1: - ax.plot(list(fit_dict['fit_xvals'].values())[ - 0], fit_results.best_fit, 'r-', linewidth=1.5) - textstr = 'f0 = %.5f $\pm$ %.1g GHz' % (fit_results.params['f0'].value, fit_results.params['f0'].stderr) + '\n' \ - 'Q = %.4g $\pm$ %.0g' % (fit_results.params['Q'].value, fit_results.params['Q'].stderr) + '\n' \ - 'Qc = %.4g $\pm$ %.0g' % (fit_results.params['Qc'].value, fit_results.params['Qc'].stderr) + '\n' \ - 'Qi = %.4g $\pm$ %.0g' % ( - fit_results.params['Qi'].value, fit_results.params['Qi'].stderr) + ax.plot(list(fit_dict['fit_xvals'].values())[0], fit_results.best_fit, 'r-', linewidth=1.5) + textstr = 'f0 = %.5f $\pm$ %.1g GHz' % ( + fit_results.params['f0'].value, fit_results.params['f0'].stderr) + '\n' \ + 'Q = %.4g $\pm$ %.0g' % ( + fit_results.params['Q'].value, fit_results.params['Q'].stderr) + '\n' \ + 'Qc = %.4g $\pm$ %.0g' % ( + fit_results.params['Qc'].value, fit_results.params['Qc'].stderr) + '\n' \ + 'Qi = %.4g $\pm$ %.0g' % ( + fit_results.params['Qi'].value, fit_results.params['Qi'].stderr) box_props = dict(boxstyle='Square', facecolor='white', alpha=0.8) self.box_props = {key: val for key, - val in box_props.items()} + val in box_props.items()} self.box_props.update({'linewidth': 0}) self.box_props['alpha'] = 0. ax.text(0.03, 0.95, textstr, transform=ax.transAxes, diff --git a/pycqed/init/config/setup_dict.py b/pycqed/init/config/setup_dict.py index 942e8348c0..5ed5c49f77 100644 --- a/pycqed/init/config/setup_dict.py +++ b/pycqed/init/config/setup_dict.py @@ -11,7 +11,7 @@ '203050745808564': 'La_Ducati_Jr', '57277341811788': 'Simulation_PC', '272774795670508': 'Nathans_Laptop', - '46390847630': 'tud276606_FPGA_PC', + '46390847630': 'Aprilia_Jr', '198690273946987': 'Bart_Laptop', '167746772205643': 'NuovaFerrari', '167746772714689': 'Xiang_PC', @@ -25,7 +25,7 @@ '215977245830009': 'LaVespa', } -data_dir_dict = {'tud276606_FPGA_PC': 'D:\Experiments/CBox_Testing/Data', +data_dir_dict = {'Aprilia_Jr': '\\TUD278336', 'CDickel_Desktop': 'D:\Experiments/ExperimentName/Data', 'Sjoerd_laptop': 'D:\data', 'Malay_Laptop':'D:\Tomo datasets', @@ -41,7 +41,8 @@ 'La_Ducati': 'D:\Experiments/Simultaneous_Driving/Data', 'La_Ducati_Jr': 'D:\Experiments/1611_Starmon/Data', 'Simulation_PC': 'D:\Experiments/testSingleShotFidelityAnalysis/Data', - 'Ramiro_Desktop': r'D:\\Repositories\\PhD_RS\\data_local', + # 'Ramiro_Desktop': r'D:\\PhD_RS\\data_local', + 'Ramiro_Desktop': r'\\TUD277449\Experiments\1801_QECVQE\Data', # 'Ramiro_Desktop': r'\\131.180.82.81\\Experiments\\1702_Starmon\\data', # 'Ramiro_Desktop': r'\\131.180.82.81\\data', # 'Ramiro_Desktop': r'\\131.180.82.190\\Experiments\\1611_Starmon\\Data', diff --git a/pycqed/instrument_drivers/meta_instrument/LutMans/base_lutman.py b/pycqed/instrument_drivers/meta_instrument/LutMans/base_lutman.py index 3459216c21..400752862f 100644 --- a/pycqed/instrument_drivers/meta_instrument/LutMans/base_lutman.py +++ b/pycqed/instrument_drivers/meta_instrument/LutMans/base_lutman.py @@ -149,7 +149,7 @@ def render_wave(self, wave_name, show=True, time_units='lut_index', marker='o', label='chQ') ax.legend() if self._voltage_min is not None: - ax.set_axis_bgcolor('gray') + ax.set_facecolor('gray') ax.axhspan(self._voltage_min, self._voltage_max, facecolor='w', linewidth=0) ax.set_ylim(self._voltage_min*1.1, self._voltage_max*1.1) diff --git a/pycqed/instrument_drivers/meta_instrument/LutMans/flux_lutman.py b/pycqed/instrument_drivers/meta_instrument/LutMans/flux_lutman.py index 62d2f92bb1..164bd4059a 100644 --- a/pycqed/instrument_drivers/meta_instrument/LutMans/flux_lutman.py +++ b/pycqed/instrument_drivers/meta_instrument/LutMans/flux_lutman.py @@ -1,6 +1,7 @@ from .base_lutman import Base_LutMan import numpy as np import logging +from copy import copy from qcodes.instrument.parameter import ManualParameter, InstrumentRefParameter from qcodes.utils import validators as vals from pycqed.instrument_drivers.pq_parameters import NP_NANs @@ -15,7 +16,7 @@ class Base_Flux_LutMan(Base_LutMan): # this default lutman is if a flux pulse can be done with only one # other qubit. this needs to be expanded if there are more qubits # to interact with. - _def_lm = ['i', 'cz_z', 'square', 'park', 'multi_cz'] + _def_lm = ['i', 'cz_z', 'square', 'park', 'multi_cz', 'custom_wf'] def render_wave(self, wave_name, show=True, time_units='s', reload_pulses: bool=True, render_distorted_wave: bool=True, @@ -81,7 +82,8 @@ def _add_cfg_parameters(self): ' where sc is the desired scaling factor that includes the sq_amp ' 'used and the range of the AWG (5 in amp mode).', vals=vals.Arrays(), - initial_value=np.array([0, 0, 0]), + # initial value is chosen to not raise errors + initial_value=np.array([2e9, 0, 0]), parameter_class=ManualParameter) self.add_parameter('cfg_operating_mode', @@ -121,7 +123,7 @@ def _add_cfg_parameters(self): self.add_parameter('cfg_max_wf_length', parameter_class=ManualParameter, - initial_value=100e-6, + initial_value=10e-6, unit='s', vals=vals.Numbers(0, 100e-6)) def amp_to_detuning(self, amp): @@ -176,6 +178,9 @@ def get_dac_val_to_amp_scalefactor(self): Returns the scale factor to transform an amplitude in 'dac value' to an amplitude in 'V'. + "dac_value" refers to the value between -1 and +1 that is set in a + waveform. + N.B. the implementation is specific to this type of AWG """ AWG = self.AWG.get_instr() @@ -187,6 +192,7 @@ def get_dac_val_to_amp_scalefactor(self): channel_amp = AWG.get('awgs_{}_outputs_{}_amplitude'.format( awg_nr, ch_pair)) + # channel range of 5 corresponds to -2.5V to +2.5V channel_range_pp = AWG.get('sigouts_{}_range'.format(awg_ch)) # direct_mode = AWG.get('sigouts_{}_direct'.format(awg_ch)) scale_factor = channel_amp*(channel_range_pp/2) @@ -209,6 +215,14 @@ def set_default_lutmap(self): def _add_waveform_parameters(self): """ Adds the parameters required to generate the standard waveforms + + The following prefixes are used for waveform parameters + sq + cz + czd + mcz + custom + """ self.add_parameter('sq_amp', initial_value=.5, # units is part of the total range of AWG8 @@ -263,10 +277,16 @@ def _add_waveform_parameters(self): parameter_class=ManualParameter) self.add_parameter('cz_freq_01_max', vals=vals.Numbers(), + # initial value is chosen to not raise errors + initial_value=6e9, unit='Hz', parameter_class=ManualParameter) self.add_parameter('cz_J2', vals=vals.Numbers(), unit='Hz', + # initial value is chosen to not raise errors + initial_value=15e6, parameter_class=ManualParameter) self.add_parameter('cz_freq_interaction', vals=vals.Numbers(), + # initial value is chosen to not raise errors + initial_value=5e9, unit='Hz', parameter_class=ManualParameter) @@ -307,6 +327,27 @@ def _add_waveform_parameters(self): parameter_class=ManualParameter, vals=vals.Numbers(min_value=0)) + self.add_parameter( + 'custom_wf', + initial_value=np.array([]), + label='Custom waveform', + docstring=('Specifies a custom waveform, note that ' + '`custom_wf_length` is used to cut of the waveform if' + 'it is set.'), + parameter_class=ManualParameter, + vals=vals.Arrays()) + self.add_parameter( + 'custom_wf_length', + unit='s', + label='Custom waveform length', + initial_value=np.inf, + docstring=('Used to determine at what sample the custom waveform ' + 'is forced to zero. This is used to facilitate easy ' + 'cryoscope measurements of custom waveforms.'), + parameter_class=ManualParameter, + vals=vals.Numbers(min_value=0)) + + def generate_standard_waveforms(self): """ Generates all the standard waveforms and populates self._wave_dict @@ -320,7 +361,7 @@ def generate_standard_waveforms(self): self._wave_dict['cz'] = self._gen_cz() self._wave_dict['cz_z'] = self._gen_cz_z(regenerate_cz=False) self._wave_dict['idle_z'] = self._gen_idle_z() - + self._wave_dict['custom_wf'] = self._gen_custom_wf() self._wave_dict['multi_square'] = self._gen_multi_square( regenerate_square=False) # multi_cz is used because there is no real-time flux correction yet @@ -498,6 +539,16 @@ def _gen_multi_cz(self, regenerate_cz=True): # CZ with phase correction return waveform + def _gen_custom_wf(self): + base_wf = copy(self.custom_wf()) + + if self.custom_wf_length() != np.inf: + # cuts of the waveform at a certain length by setting + # all subsequent samples to 0. + max_sample = int(self.custom_wf_length()*self.sampling_rate()) + base_wf[max_sample:] = 0 + return base_wf + def _gen_composite_wf(self, primitive_waveform_name: str, time_tuples: list): """ @@ -597,10 +648,11 @@ def load_waveform_onto_AWG_lookuptable(self, waveform_name: str, self._wave_dict_dist[waveform_name] = waveform self.AWG.get_instr().set(codeword, waveform) - def load_composite_waveform_onto_AWG_lookuptable(self, - primitive_waveform_name: str, - time_tuples: list, - codeword: int): + def load_composite_waveform_onto_AWG_lookuptable( + self, + primitive_waveform_name: str, + time_tuples: list, + codeword: int): """ Creates a composite waveform based on time_tuples extracted from a qisa file. @@ -701,7 +753,27 @@ def distort_waveform(self, waveform): self.sampling_rate())) return distorted_waveform - def plot_flux_arc(self, ax=None, show=True): + def plot_cz_trajectory(self, ax=None, show=True): + """ + Plots the cz trajectory in frequency space. + """ + if ax is None: + f, ax = plt.subplots() + extra_samples = 10 + nr_plot_samples = int((self.cz_length()+self.cz_phase_corr_length()) * + self.sampling_rate() + extra_samples) + dac_amps = self._wave_dict['cz_z'][:nr_plot_samples] + samples = np.arange(len(dac_amps)) + amps = dac_amps*self.get_dac_val_to_amp_scalefactor() + deltas = self.amp_to_detuning(amps) + freqs = self.cz_freq_01_max()-deltas + ax.scatter(amps, freqs, c=samples, label='CZ trajectory') + if show: + plt.show() + return ax + + def plot_flux_arc(self, ax=None, show=True, + plot_cz_trajectory=False): """ Plots the flux arc as used in the lutman based on the polynomial coefficients @@ -729,8 +801,9 @@ def plot_flux_arc(self, ax=None, show=True): color='C1', alpha=0.25) title = ('Calibration visualization\n{}\nchannel {}'.format( - self.AWG(), self.cfg_awg_channel())) - + self.AWG(), self.cfg_awg_channel())) + if plot_cz_trajectory: + self.plot_cz_trajectory(ax=ax, show=False) leg = ax.legend(title=title, loc=(1.05, .7)) leg._legend_box.align = 'center' set_xlabel(ax, 'AWG amplitude', 'V') @@ -787,7 +860,6 @@ def load_waveform_onto_AWG_lookuptable(self, waveform_name: str, self.AWG.get_instr().set(codeword, waveform) self.AWG.get_instr().start() - def distort_waveform(self, waveform): """ Modifies the ideal waveform to correct for distortions and correct @@ -835,4 +907,18 @@ def convolve_kernel(self, kernel_list, length_samples=None): :max(len(k), int(length_samples))] if length_samples is not None: return kernels[:int(length_samples)] - return kernels \ No newline at end of file + return kernels + + def get_dac_val_to_amp_scalefactor(self): + """ + Returns the scale factor to transform an amplitude in 'dac value' to an + amplitude in 'V'. + + N.B. the implementation is specific to this type of AWG (QWG) + """ + AWG = self.AWG.get_instr() + awg_ch = self.cfg_awg_channel() + + channel_amp = AWG.get('ch{}_amp'.format(awg_ch)) + scale_factor = channel_amp + return scale_factor diff --git a/pycqed/instrument_drivers/meta_instrument/LutMans/mw_lutman.py b/pycqed/instrument_drivers/meta_instrument/LutMans/mw_lutman.py index ac648d0377..9ef8b2b5df 100644 --- a/pycqed/instrument_drivers/meta_instrument/LutMans/mw_lutman.py +++ b/pycqed/instrument_drivers/meta_instrument/LutMans/mw_lutman.py @@ -4,7 +4,6 @@ from qcodes.utils import validators as vals from pycqed.measurement.waveform_control_CC import waveform as wf - class Base_MW_LutMan(Base_LutMan): _def_lm = ['I', 'rX180', 'rY180', 'rX90', 'rY90', 'rXm90', 'rYm90', 'rPhi90', 'spec'] @@ -291,7 +290,7 @@ def _get_channel_amp(self): awg_nr = (awg_ch-1)//2 ch_pair = (awg_ch-1) % 2 vals.append( - AWG.get('awgs_{}_outputs_{}_amplitude'.format(awg_nr, awg_ch))) + AWG.get('awgs_{}_outputs_{}_amplitude'.format(awg_nr, ch_pair))) assert vals[0] == vals[1] return vals[0] @@ -377,7 +376,7 @@ def _get_channel_amp(self): awg_nr = (awg_ch-1)//2 ch_pair = (awg_ch-1) % 2 vals.append( - AWG.get('awgs_{}_outputs_{}_amplitude'.format(awg_nr, awg_ch))) + AWG.get('awgs_{}_outputs_{}_amplitude'.format(awg_nr, ch_pair))) assert vals[0] == vals[1] == vals[2] == vals[3] return vals[0] @@ -416,13 +415,6 @@ def apply_mixer_predistortion_corrections(self, wave_dict): class QWG_MW_LutMan_VQE(QWG_MW_LutMan): - """ - WORK ONGOING: - 4. define the waveforms accordingly to the VQE lutmap. - (use parameters from _add_waveform_parameters.) - - """ - def __init__(self, name, **kw): """ Waveform allocation strategy for VQE. @@ -472,8 +464,8 @@ def __init__(self, name, **kw): 'rXm90', 'rYm90', 'rPhi90'] self.set_default_lutmap() - self._vqe_lm = ['I', 'X180t', 'Y180t', 'X90t', 'Xm90t', - 'Y90t', 'Y90t', 'Y180'] + self._vqe_lm = ['I', 'X180c', 'Y180c', 'X90c', 'Xm90c', + 'Y90c', 'Y90c', 'rY180'] def set_VQE_lutmap(self): """ @@ -497,10 +489,7 @@ def _add_waveform_parameters(self): parameter_class=ManualParameter, initial_value=0) # parameters related to phase compilation - self.add_parameter('phi1', unit='rad', vals=vals.Numbers(0, 2*np.pi), - parameter_class=ManualParameter, - initial_value=0) - self.add_parameter('phi2', unit='rad', vals=vals.Numbers(0, 2*np.pi), + self.add_parameter('phi', unit='rad', vals=vals.Numbers(0, 2*np.pi), parameter_class=ManualParameter, initial_value=0) @@ -517,14 +506,45 @@ def generate_standard_waveforms(self): else: f_modulation = 0 - # """ - # This pulses still need to be cross-checked. - # """ - # self._wave_dict['cX180_phi'] = self.wf_func( - # amp=self.mw_amp180(), sigma_length=self.mw_gauss_width(), - # f_modulation=f_modulation, - # sampling_rate=self.sampling_rate(), phase=0, - # motzoi=self.mw_motzoi()) + self._wave_dict['X180c'] = self.wf_func( + amp=self.mw_amp180(), sigma_length=self.mw_gauss_width(), + f_modulation=f_modulation, + sampling_rate=self.sampling_rate(), phase=self.phi(), + motzoi=self.mw_motzoi()) + self._wave_dict['rY180'] = self.wf_func( + amp=self.mw_amp180(), sigma_length=self.mw_gauss_width(), + f_modulation=f_modulation, + sampling_rate=self.sampling_rate(), phase=90, + motzoi=self.mw_motzoi()) + self._wave_dict['rY180c'] = self.wf_func( + amp=self.mw_amp180(), sigma_length=self.mw_gauss_width(), + f_modulation=f_modulation, + sampling_rate=self.sampling_rate(), phase=90+self.phi(), + motzoi=self.mw_motzoi()) + self._wave_dict['rX90c'] = self.wf_func( + amp=self.mw_amp180()*self.mw_amp90_scale(), + sigma_length=self.mw_gauss_width(), + f_modulation=f_modulation, + sampling_rate=self.sampling_rate(), phase=self.phi(), + motzoi=self.mw_motzoi()) + self._wave_dict['rY90c'] = self.wf_func( + amp=self.mw_amp180()*self.mw_amp90_scale(), + sigma_length=self.mw_gauss_width(), + f_modulation=f_modulation, + sampling_rate=self.sampling_rate(), phase=90+self.phi(), + motzoi=self.mw_motzoi()) + self._wave_dict['rXm90c'] = self.wf_func( + amp=-1*self.mw_amp180()*self.mw_amp90_scale(), + sigma_length=self.mw_gauss_width(), + f_modulation=f_modulation, + sampling_rate=self.sampling_rate(), phase=self.phi(), + motzoi=self.mw_motzoi()) + self._wave_dict['rYm90c'] = self.wf_func( + amp=-1*self.mw_amp180()*self.mw_amp90_scale(), + sigma_length=self.mw_gauss_width(), + f_modulation=f_modulation, + sampling_rate=self.sampling_rate(), phase=90+self.phi(), + motzoi=self.mw_motzoi()) if self.mixer_apply_predistortion_matrix(): self._wave_dict = self.apply_mixer_predistortion_corrections( diff --git a/pycqed/instrument_drivers/meta_instrument/LutMans/ro_lutman.py b/pycqed/instrument_drivers/meta_instrument/LutMans/ro_lutman.py index 82ad4a05ef..cd29662544 100644 --- a/pycqed/instrument_drivers/meta_instrument/LutMans/ro_lutman.py +++ b/pycqed/instrument_drivers/meta_instrument/LutMans/ro_lutman.py @@ -8,10 +8,20 @@ class Base_RO_LutMan(Base_LutMan): - def __init__(self, name, num_res: int=1, **kw): + def __init__(self, name, num_res=2, feedline_number: int=0,**kw): if num_res > 9: raise ValueError('At most 9 resonators can be read out.') self._num_res = num_res + self._feedline_number = feedline_number + if self._feedline_number==0: + self._resonator_codeword_bit_mapping=[0,2,3,5,6] + elif self._feedline_number==1: + self._resonator_codeword_bit_mapping=[1,4] + else: + raise NotImplementedError( + 'hardcoded for feedline 0 and 1 of Surface-7') + #capping the resonator bit mapping in case a limited number of resonators is used + self._resonator_codeword_bit_mapping = self._resonator_codeword_bit_mapping[:self._num_res] super().__init__(name, **kw) def _add_waveform_parameters(self): @@ -20,6 +30,14 @@ def _add_waveform_parameters(self): vals=vals.Bool(), parameter_class=ManualParameter, initial_value=False) + self.add_parameter('gaussian_convolution', + vals=vals.Bool(), + parameter_class=ManualParameter, + initial_value=False) + self.add_parameter('gaussian_convolution_sigma', vals=vals.Numbers(), + parameter_class=ManualParameter, + initial_value=5.0e-9, + unit='s') self.add_parameter('mixer_alpha', vals=vals.Numbers(), parameter_class=ManualParameter, initial_value=1.0) @@ -33,19 +51,24 @@ def _add_waveform_parameters(self): comb_msg = ( 'Resonator combinations specifies which pulses are uploaded to' 'the device. Given as a list of lists:' - 'e.g. [[0], [1], [0, 1]] specifies that pulses for readout' - 'of resonator 0, 1, and a pulse for mux readout on both should be' + 'e.g. [[0], [2], [0, 2]] specifies that pulses for readout' + 'of resonator 0, 2, and a pulse for mux readout on both should be' 'uploaded.') self.add_parameter('resonator_combinations', vals=vals.Lists(), parameter_class=ManualParameter, docstring=comb_msg, - initial_value=[[0]]) + initial_value=[[0], [2], [0, 2]]) self.add_parameter('pulse_type', vals=vals.Enum( - 'M_up_down_down', 'M_square'), + 'M_up_down_down', 'M_simple', 'M_up_down_down_final'), + parameter_class=ManualParameter, + docstring='defines sequence of segments of the pulse', + initial_value='M_simple') + self.add_parameter('pulse_primitive_shape', vals=vals.Enum( + 'square', 'gaussian'), parameter_class=ManualParameter, - docstring=comb_msg, - initial_value='M_square') - for res in range(self._num_res): + docstring='defines the shape of the segments of the pulse', + initial_value='square') + for res in self._resonator_codeword_bit_mapping: self.add_parameter('M_modulation_R{}'.format(res), vals=vals.Numbers(), unit='Hz', parameter_class=ManualParameter, @@ -53,11 +76,23 @@ def _add_waveform_parameters(self): self.add_parameter('M_length_R{}'.format(res), unit='s', vals=vals.Numbers(1e-9, 8000e-9), parameter_class=ManualParameter, - initial_value=300e-9) + initial_value=2000e-9) self.add_parameter('M_amp_R{}'.format(res), unit='V', vals=vals.Numbers(0, 1), parameter_class=ManualParameter, initial_value=0.1) + self.add_parameter('M_final_amp_R{}'.format(res), unit='V', + vals=vals.Numbers(0, 1), + parameter_class=ManualParameter, + initial_value=0.1) + self.add_parameter('M_final_length_R{}'.format(res), unit='s', + vals=vals.Numbers(1e-9, 8000e-9), + parameter_class=ManualParameter, + initial_value=1000e-9) + self.add_parameter('M_final_delay_R{}'.format(res), unit='s', + vals=vals.Numbers(1e-9, 8000e-9), + parameter_class=ManualParameter, + initial_value=200e-9) self.add_parameter('M_phi_R{}'.format(res), unit='deg', parameter_class=ManualParameter, initial_value=0.0) @@ -84,53 +119,121 @@ def _add_waveform_parameters(self): parameter_class=ManualParameter, initial_value=180.0) + def add_pulse(self, amplitude: float, length: float, phase: float, + delay: float=0): + kw = {} + if self.pulse_primitive_shape() == 'square': + shape_function = wf.block_pulse + kw['length'] = length + elif self.pulse_primitive_shape() == 'gaussian': + shape_function = wf.gauss_pulse + nr_sigma = 4 + kw['sigma_length'] = length/nr_sigma + kw['nr_sigma'] = nr_sigma + else: + raise NotImplementedError('Primitive pulse shape ' + + self.pulse_primitive_shape() + + ' not implemented.') + + M = shape_function(amp=amplitude, + sampling_rate=self.get('sampling_rate'), + delay=delay, + phase=phase, **kw) + return M + def generate_standard_waveforms(self): """ """ # Only generate the combinations required/specified in the LutMap # RO pulses + sampling_rate = self.get('sampling_rate') + + # Prepare gauss pulse for convolution (if desired) + if self.gaussian_convolution(): + if self.pulse_primitive_shape() != 'square': + print("Warning: recommend to set pulse_primitive_shape to " + + "'square' when using gaussian_convolution.") + sigma = self.gaussian_convolution_sigma() + def norm_gauss(x, mu, sigma): + n = 1/(sigma*np.sqrt(2*np.pi)) + return n*np.exp((-((x-mu)/sigma)**2)/2) + + gauss_length = 6*sigma# in units of time + hgsl = int(gauss_length*sampling_rate/2)# half no. of samples + gauss_sample_length = hgsl*2# no. of samples + gauss_samples = np.arange(0, gauss_sample_length, 1)/sampling_rate + norm_gauss_p = norm_gauss(x=gauss_samples, + mu=gauss_length/2, sigma=sigma) + else: + gauss_length = 0 + + # Prepare pulses for all resonators self._wave_dict = {} - for res in range(self._num_res): - M = wf.block_pulse(self.get('M_amp_R{}'.format(res)), - self.get('M_length_R{}'.format(res)), # ns - sampling_rate=self.get('sampling_rate'), + for res in self._resonator_codeword_bit_mapping: + res_wave_dict = {} + # 1. Generate Pulse envelopes + ## Simple pulse + up_len = self.get('M_length_R{}'.format(res))-gauss_length + M = self.add_pulse(self.get('M_amp_R{}'.format(res)), up_len, delay=0, phase=self.get('M_phi_R{}'.format(res))) - Mod_M = wf.mod_pulse(M[0], M[1], - f_modulation=self.get( - 'M_modulation_R{}'.format(res)), - sampling_rate=self.get('sampling_rate')) - - # 3-step RO pulse with ramp-up and double depletion - M_down0 = wf.block_pulse(self.get('M_down_amp0_R{}'.format(res)), - self.get( - 'M_down_length0_R{}'.format(res)), # ns - sampling_rate=self.get('sampling_rate'), + res_wave_dict['M_simple_R{}'.format(res)] = M + + ## 3-step RO pulse with ramp-up and double depletion + up_len = self.get('M_length_R{}'.format(res))-gauss_length/2 + M_up = self.add_pulse(self.get('M_amp_R{}'.format(res)), + up_len, delay=0, + phase=self.get('M_phi_R{}'.format(res))) + M_down0 = self.add_pulse(self.get('M_down_amp0_R{}'.format(res)), + self.get('M_down_length0_R{}'.format(res)), # ns delay=0, phase=self.get('M_down_phi0_R{}'.format(res))) - M_down1 = wf.block_pulse(self.get('M_down_amp1_R{}'.format(res)), - self.get( - 'M_down_length1_R{}'.format(res)), # ns - sampling_rate=self.get('sampling_rate'), - delay=0, + down1_len = self.get('M_down_length1_R{}'.format(res))-gauss_length/2 + M_down1 = self.add_pulse(self.get('M_down_amp1_R{}'.format(res)), + down1_len, delay=0, phase=self.get('M_down_phi1_R{}'.format(res))) - # concatenating up, down, down depletion - M_up_down_down = (np.concatenate((M[0], M_down0[0], M_down1[0])), - np.concatenate((M[1], M_down0[1], M_down1[1]))) - Mod_M_up_down_down = wf.mod_pulse(M_up_down_down[0], M_up_down_down[1], - f_modulation=self.get( - 'M_modulation_R{}'.format(res)), - sampling_rate=self.sampling_rate()) - self._wave_dict.update({'M_square_R{}'.format(res): Mod_M, - 'M_up_down_down_R{}'.format(res): Mod_M_up_down_down}) - - if self.mixer_apply_predistortion_matrix(): - M = wf.mixer_predistortion_matrix( - self.mixer_alpha(), self.mixer_phi()) - for key, val in self._wave_dict.items(): - self._wave_dict[key] = np.dot(M, val) + M_up_down_down = (np.concatenate((M_up[0], M_down0[0], M_down1[0])), + np.concatenate((M_up[1], M_down0[1], M_down1[1]))) + res_wave_dict['M_up_down_down_R{}'.format(res)] = M_up_down_down + + ## pulse with up, down, down depletion with an additional final + ## strong measurement at some delay + M_final = self.add_pulse(self.get('M_final_amp_R{}'.format(res)), + self.get('M_final_length_R{}'.format(res)), # ns + delay=self.get('M_final_delay_R{}'.format(res)), + phase=self.get('M_phi_R{}'.format(res))) + + M_up_down_down_final = (np.concatenate((M_up_down_down[0], M_final[0])), + np.concatenate((M_up_down_down[1], M_final[1]))) + res_wave_dict['M_up_down_down_final_R{}'.format(res)] = M_up_down_down_final + + # 2. convolve with gaussian (if desired) + if self.gaussian_convolution(): + for key, val in res_wave_dict.items(): + M_conv0 = np.convolve(val[0], norm_gauss_p) + M_conv1 = np.convolve(val[1], norm_gauss_p) + #M_conv0 = M_conv0[hgsl: -hgsl+1] + #M_conv1 = M_conv1[hgsl: -hgsl+1] + res_wave_dict[key] = (M_conv0/sampling_rate, M_conv1/sampling_rate) + + # 3. modulation with base frequency + for key, val in res_wave_dict.items(): + res_wave_dict[key] = wf.mod_pulse(pulse_I=val[0], pulse_Q=val[1], + f_modulation=self.get('M_modulation_R{}'.format(res)), + sampling_rate=self.get('sampling_rate')) + + # 4. apply mixer predistortion + if self.mixer_apply_predistortion_matrix(): + Mat = wf.mixer_predistortion_matrix( + self.mixer_alpha(), self.mixer_phi()) + for key, val in res_wave_dict.items(): + res_wave_dict[key] = np.dot(Mat, val) + + # 5. Add to global dict + self._wave_dict.update(**res_wave_dict) + return self._wave_dict @@ -148,9 +251,6 @@ def __init__(self, name, num_res: int=1, **kw): self._voltage_max = 1.0-1.0/2**13 self.sampling_rate(1.8e9) - self.add_parameter('hardcode_cases', vals=vals.Lists(), - parameter_class=ManualParameter, - initial_value=[]) def set_default_lutmap(self): @@ -181,7 +281,6 @@ def load_single_pulse_sequence_onto_UHFQC(self, pulse_name, def load_DIO_triggered_sequence_onto_UHFQC(self, regenerate_waveforms=True, - hardcode_cases=None, timeout=5): ''' Load a single pulse to the lookuptable, it uses the lut_mapping to @@ -194,13 +293,6 @@ def load_DIO_triggered_sequence_onto_UHFQC(self, ''' resonator_combinations = self.resonator_combinations() - # TODO: automatically assign right codeword for resonator combinations - # 1. convert each combination to binary to extract the expected CW - # 2. create a list of these binary numbers or put the combinations in - # a dict with these numbers as keys. - # 3. When uploading, ensure that the pulses are loaded to the right - # number as specified in 2. - pulse_type = self.pulse_type() if regenerate_waveforms: wave_dict = self.generate_standard_waveforms() @@ -230,8 +322,7 @@ def load_DIO_triggered_sequence_onto_UHFQC(self, I_waves[i], wave_dict[wavename][0]) Q_waves[i] = add_waves_different_length( Q_waves[i], wave_dict[wavename][1]) - - cases[i] += 2**resonator + cases[i] += 2**self._resonator_codeword_bit_mapping.index(resonator) # clipping the waveform I_waves[i] = np.clip(I_waves[i], @@ -239,9 +330,6 @@ def load_DIO_triggered_sequence_onto_UHFQC(self, Q_waves[i] = np.clip(Q_waves[i], self._voltage_min, self._voltage_max) - if self.hardcode_cases() != []: - cases = self.hardcode_cases() - self.AWG.get_instr().awg_sequence_acquisition_and_DIO_triggered_pulse( I_waves, Q_waves, cases, self.acquisition_delay(), timeout=timeout) diff --git a/pycqed/instrument_drivers/meta_instrument/device_object.py b/pycqed/instrument_drivers/meta_instrument/device_object.py index a4d64b1012..3dd84c69cc 100644 --- a/pycqed/instrument_drivers/meta_instrument/device_object.py +++ b/pycqed/instrument_drivers/meta_instrument/device_object.py @@ -136,10 +136,13 @@ def prepare_for_timedomain(self): q1.prepare_for_timedomain() q0.prepare_for_timedomain() RO_LMM.acquisition_delay(q0.RO_acq_marker_delay()) + #aligining the acquisition delays according to q0, important for optimal + #weight calibrations + q0.RO_acq_marker_delay(q1.RO_acq_marker_delay()) # Generate multiplexed pulse - multiplexed_wave = [[q0.RO_LutMan(), 'M_square'], - [q1.RO_LutMan(), 'M_square']] + multiplexed_wave = [[q0.RO_LutMan(), 'M_simple'], + [q1.RO_LutMan(), 'M_simple']] RO_LMM.generate_multiplexed_pulse(multiplexed_wave) RO_LMM.load_pulse_onto_AWG_lookuptable('Multiplexed_pulse') diff --git a/pycqed/instrument_drivers/meta_instrument/device_object_CCL.py b/pycqed/instrument_drivers/meta_instrument/device_object_CCL.py index 7550424370..f0390836e3 100644 --- a/pycqed/instrument_drivers/meta_instrument/device_object_CCL.py +++ b/pycqed/instrument_drivers/meta_instrument/device_object_CCL.py @@ -11,6 +11,8 @@ from pycqed.analysis import measurement_analysis as ma from pycqed.analysis_v2 import measurement_analysis as ma2 import networkx as nx +import datetime + try: from pycqed.measurement.openql_experiments import single_qubit_oql as sqo @@ -204,16 +206,20 @@ def prepare_fluxing(self): # fl_lutman.load_waveforms_onto_awg_lookuptable() fl_lutman.load_waveforms_onto_AWG_lookuptable() awg = fl_lutman.AWG.get_instr() - # awg.upload_codeword_program(awgs=[0]) - - awg_hack_program_cz = """ - while (1) { - waitDIOTrigger(); - playWave("dev8005_wave_ch1_cw001", "dev8005_wave_ch2_cw001"); - } - """ - awg.configure_awg_from_string(0, awg_hack_program_cz) - awg.configure_codeword_protocol() + if awg.__class__.__name__ == 'QuTech_AWG_Module': + using_QWG = True + else: + using_QWG = False + if not using_QWG: + # awg.upload_codeword_program(awgs=[0]) + awg_hack_program_cz = """ + while (1) { + waitDIOTrigger(); + playWave("dev8005_wave_ch1_cw001", "dev8005_wave_ch2_cw001"); + } + """ + awg.configure_awg_from_string(0, awg_hack_program_cz) + awg.configure_codeword_protocol() awg.start() @@ -237,7 +243,8 @@ def _prep_ro_setup_qubits(self): qb.ro_acq_weight_type(self.ro_acq_weight_type()) qb.ro_acq_integration_length(self.ro_acq_integration_length()) qb.ro_acq_digitized(self.ro_acq_digitized()) - qb.ro_acq_delay(self.ro_acq_delay()) + # hardcoded because UHFLI is not stable for arbitrary values + qb.ro_acq_input_average_length(4096/1.8e9) acq_device = qb.instr_acquisition() @@ -255,6 +262,8 @@ def _prep_ro_setup_qubits(self): # set RO modulation to use common LO frequency qb.ro_freq_mod(qb.ro_freq() - self.ro_lo_freq()) + qb._prep_ro_pulse(upload=False) + qb._prep_ro_pulse(upload=True) def _prep_ro_integration_weights(self): """ @@ -455,7 +464,7 @@ def _prep_ro_pulses(self): ro_lm = qb.instr_LutMan_RO.get_instr() lutmans_to_configure[ro_lm.name] = ro_lm - res_nr = qb.ro_pulse_res_nr() + res_nr = qb.cfg_qubit_nr()() # extend the list of combinations to be set for the lutman @@ -556,7 +565,7 @@ def prepare_for_timedomain(self): qb._prep_td_sources() qb._prep_mw_pulses() - self._prep_td_configure_VSM() + # self._prep_td_configure_VSM() ######################################################## # Measurement methods @@ -574,6 +583,7 @@ def measure_conditional_oscillation(self, q0: str, q1: str, """ if prepare_for_timedomain: self.prepare_for_timedomain() + if MC is None: MC = self.instr_MC.get_instr() assert q0 in self.qubits() @@ -680,7 +690,7 @@ def measure_two_qubit_SSRO(self, nr_shots: int=4088*4, prepare_for_timedomain: bool =True, result_logging_mode='lin_trans', - initialize: bool=True, + initialize: bool=False, analyze=True, MC=None): if prepare_for_timedomain: @@ -732,6 +742,104 @@ def measure_two_qubit_SSRO(self, a = ma2.Multiplexed_Readout_Analysis() return a + def measure_msmt_induced_dephasing_matrix(self, qubits: list, + analyze=True, MC=None, + prepare_for_timedomain=True, + n_amps_rel: int=None, + verbose=True, + get_quantum_eff: bool=False): + ''' + Measures the msmt induced dephasing for readout the readout of qubits + i on qubit j. Additionally measures the SNR as a function of amplitude + for the diagonal elements to obtain the quantum efficiency. + In order to use this: make sure that + - all readout_and_depletion pulses are of equal total length + - the cc light to has the readout time configured equal to the + measurement and depletion time + 60 ns buffer + + fixme: not sure if the weight function assignment is working correctly. + + the qubit objects will use SSB for the ramsey measurements. + ''' + lpatt = '_trgt_{TQ}_measured_{RQ}' + if prepare_for_timedomain: + #for q in qubits: + # q.prepare_for_timedomain() + self.prepare_for_timedomain() + + old_suffixes = [q.msmt_suffix for q in qubits] #Save old qubit suffixes + old_suffix = self.msmt_suffix + + # Save the start-time of the experiment for analysis + start = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") + + # Loop over all target and measurement qubits + target_qubits = qubits[:] + measured_qubits = qubits[:] + for target_qubit in target_qubits: + for measured_qubit in measured_qubits: + # Set measurement label suffix + s = lpatt.replace('{TQ}', target_qubit.name) + s = s.replace('{RQ}', measured_qubit.name) + measured_qubit.msmt_suffix = s + target_qubit.msmt_suffix = s + + #Print label + if verbose: + print(s) + + # Slight differences if diagonal element + if target_qubit == measured_qubit: + amps_rel = np.linspace(0, 1, n_amps_rel) + mqp = None + list_target_qubits = None + else: + t_amp_max = max(target_qubit.ro_pulse_down_amp0(), + target_qubit.ro_pulse_down_amp1(), + target_qubit.ro_pulse_amp()) + amp_max = max(t_amp_max, measured_qubit.ro_pulse_amp()) + amps_rel = np.linspace(0, 0.99/(amp_max), n_amps_rel) + mqp = self.cfg_openql_platform_fn() + list_target_qubits = [target_qubit,] + + # If a diagonal element, consider doing the full quantum + # efficiency matrix. + if target_qubit == measured_qubit and get_quantum_eff: + res = measured_qubit.measure_quantum_efficiency( + verbose=verbose, + amps_rel=amps_rel) + else: + res = measured_qubit.measure_msmt_induced_dephasing_sweeping_amps( + verbose=verbose, + amps_rel=amps_rel, + cross_target_qubits=list_target_qubits, + multi_qubit_platf_cfg=mqp, + analyze=True + ) + # Print the result of the measurement + if verbose: + print(res) + + # Save the end-time of the experiment + stop = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") + + #reset the msmt_suffix'es + for qi, q in enumerate(qubits): + q.msmt_suffix = old_suffixes[qi] + self.msmt_suffix = old_suffix + + # Run the analysis for this experiment + if analyze: + options_dict = { + 'verbose': True, + } + qarr = [q.name for q in qubits] + labelpatt = 'ro_amp_sweep_ramsey'+lpatt + ca = ma2.CrossDephasingAnalysis(t_start=start, t_stop=stop, + label_pattern=labelpatt, + qubit_labels=qarr, + options_dict=options_dict) + def measure_chevron(self, q0: str, q_spec: str, amps, lengths, prepare_for_timedomain=True, MC=None, @@ -755,33 +863,44 @@ def measure_chevron(self, q0: str, q_spec: str, q0idx = self.find_instrument(q0).cfg_qubit_nr() q_specidx = self.find_instrument(q_spec).cfg_qubit_nr() - # buffer times are hardcoded for now FIXME! - p = mqo.Chevron(q0idx, q_specidx, buffer_time=100e-9, - buffer_time2=1750e-9, - platf_cfg=self.cfg_openql_platform_fn()) - self.instr_CC.get_instr().eqasm_program(p.filename) - self.instr_CC.get_instr().start() - fl_lutman = self.find_instrument(q0).instr_LutMan_Flux.get_instr() + if waveform_name == 'square': + length_par = fl_lutman.sq_length + elif waveform_name == 'cz_z': + length_par = fl_lutman.cz_length, + else: + raise ValueError('Waveform shape not understood') + awg = fl_lutman.AWG.get_instr() - awg_ch = fl_lutman.cfg_awg_channel()-1 # -1 is to account for starting at 1 - ch_pair = awg_ch % 2 - awg_nr = awg_ch//2 + using_QWG = (awg.__class__.__name__ == 'QuTech_AWG_Module') - amp_par = awg.parameters['awgs_{}_outputs_{}_amplitude'.format( - awg_nr, ch_pair)] + if using_QWG: + awg_ch = fl_lutman.cfg_awg_channel() + amp_par = awg.parameters['ch{}_amp'.format(awg_ch)] + sw = swf.FLsweep_QWG(fl_lutman, length_par, + realtime_loading=False, + waveform_name=waveform_name) + flux_cw = 0 - if waveform_name == 'square': - sw = swf.FLsweep(fl_lutman, fl_lutman.sq_length, - realtime_loading=False, - waveform_name=waveform_name) - elif waveform_name == 'cz_z': - sw = swf.FLsweep(fl_lutman, fl_lutman.cz_length, + else: + awg_ch = fl_lutman.cfg_awg_channel()-1 # -1 is to account for starting at 1 + ch_pair = awg_ch % 2 + awg_nr = awg_ch//2 + + amp_par = awg.parameters['awgs_{}_outputs_{}_amplitude'.format( + awg_nr, ch_pair)] + sw = swf.FLsweep(fl_lutman, length_par, realtime_loading=False, waveform_name=waveform_name) - else: - raise ValueError() + flux_cw = 2 + # buffer times are hardcoded for now FIXME! + p = mqo.Chevron(q0idx, q_specidx, buffer_time=100e-9, + buffer_time2=200e-9, + flux_cw=flux_cw, + platf_cfg=self.cfg_openql_platform_fn()) + self.instr_CC.get_instr().eqasm_program(p.filename) + self.instr_CC.get_instr().start() d = self.get_correlation_detector(single_int_avg=True, seg_per_point=1) @@ -798,7 +917,35 @@ def measure_chevron(self, q0: str, q_spec: str, def measure_cryoscope(self, q0: str, times, MC=None, experiment_name='Cryoscope', + waveform_name: str='square', + max_delay: float='auto', prepare_for_timedomain: bool=True): + """ + Performs a cryoscope experiment to measure the shape of a flux pulse. + + Args: + q0 (str) : + name of the target qubit + + times (array): + array of measurment times + + experiment_name (str): + used to label the experiment + + waveform_name (str {"square", "custom_wf"}) : + defines the name of the waveform used in the + cryoscope. Valid values are either "square" or "custom_wf" + + max_delay {float, "auto"} : + determines the delay in the delay in the pusle sequence + if set to "auto" this is automatically set to the largest + pulse duration for the cryoscope. + + prepare_for_timedomain (bool): + calls self.prepare_for_timedomain on start + """ + if prepare_for_timedomain: self.prepare_for_timedomain() if MC is None: @@ -807,16 +954,27 @@ def measure_cryoscope(self, q0: str, times, assert q0 in self.qubits() q0idx = self.find_instrument(q0).cfg_qubit_nr() + if max_delay == 'auto': + max_delay = np.max(times) + 40e-9 p = mqo.Cryoscope(q0idx, buffer_time1=20e-9, - buffer_time2=2000e-9, + buffer_time2=max_delay, platf_cfg=self.cfg_openql_platform_fn()) self.instr_CC.get_instr().eqasm_program(p.filename) self.instr_CC.get_instr().start() fl_lutman = self.find_instrument(q0).instr_LutMan_Flux.get_instr() - sw = swf.FLsweep(fl_lutman, fl_lutman.sq_length, - realtime_loading=True, - waveform_name='square') + + if waveform_name == 'square': + sw = swf.FLsweep(fl_lutman, fl_lutman.sq_length, + realtime_loading=True, + waveform_name='square') + elif waveform_name == 'custom_wf': + sw = swf.FLsweep(fl_lutman, fl_lutman.custom_wf_length, + realtime_loading=True, + waveform_name='custom_wf') + else: + raise ValueError('waveform_name "{}" should be either ' + '"square" or "custom_wf"'.format(waveform_name)) MC.set_sweep_function(sw) MC.set_sweep_points(times) d = self.get_int_avg_det(values_per_point=2, @@ -862,7 +1020,7 @@ def calibrate_mux_RO(self, q1.calibrate_optimal_weights( analyze=True, verify=verify_optimal_weights) - self.measure_two_qubit_SSRO(q0.name, q1.name, + self.measure_two_qubit_SSRO([q1.name, q0.name], result_logging_mode='lin_trans') res_dict = mra.two_qubit_ssro_fidelity( @@ -876,7 +1034,9 @@ def calibrate_mux_RO(self, UHFQC.quex_trans_offset_weightfunction_1(V_offset_cor[1]) # Does not work because axes are not normalized - UHFQC.upload_transformation_matrix(res_dict['mu_matrix_inv']) + matrix_normalized = res_dict['mu_matrix_inv'] + matrix_rescaled = matrix_normalized/abs(matrix_normalized).max() + UHFQC.upload_transformation_matrix(matrix_rescaled) # a = self.check_mux_RO(update=update, update_threshold=update_threshold) return True @@ -1012,8 +1172,6 @@ def create_dep_graph(self): dag.add_node(self.name + ' mw-ro timing') dag.add_edge(self.name + ' mw-ro timing', 'AWG8 MW-staircase') - - dag.add_node(self.name + ' mw-vsm timing') dag.add_edge(self.name + ' mw-vsm timing', self.name + ' mw-ro timing') diff --git a/pycqed/instrument_drivers/meta_instrument/qubit_objects/CCL_Transmon.py b/pycqed/instrument_drivers/meta_instrument/qubit_objects/CCL_Transmon.py index 68be82e7a3..b2cc97315f 100644 --- a/pycqed/instrument_drivers/meta_instrument/qubit_objects/CCL_Transmon.py +++ b/pycqed/instrument_drivers/meta_instrument/qubit_objects/CCL_Transmon.py @@ -4,9 +4,11 @@ from autodepgraph.graph_v2 import AutoDepGraph_DAG try: from pycqed.measurement.openql_experiments import single_qubit_oql as sqo + import pycqed.measurement.openql_experiments.multi_qubit_oql as mqo except ImportError: logging.warning('Could not import OpenQL') sqo = None + mqo = None from pycqed.utilities.general import gen_sweep_pts from .qubit_object import Qubit @@ -24,7 +26,7 @@ import cma from pycqed.measurement.optimization import nelder_mead - +import datetime class CCLight_Transmon(Qubit): @@ -110,14 +112,8 @@ def add_ro_parameters(self): parameter_class=ManualParameter) # RO pulse parameters - self.add_parameter('ro_pulse_res_nr', - label='Resonator number', docstring=( - 'Resonator number used in lutman for' - ' uploading to the correct UHFQC codeword.'), - initial_value=0, vals=vals.Ints(0, 9), - parameter_class=ManualParameter) - self.add_parameter('ro_pulse_type', initial_value='square', - vals=vals.Enum('gated', 'square', 'up_down_down'), + self.add_parameter('ro_pulse_type', initial_value='simple', + vals=vals.Enum('gated', 'simple', 'up_down_down','up_down_down_final'), parameter_class=ManualParameter) # Mixer offsets correction, RO pulse @@ -178,12 +174,12 @@ def add_ro_parameters(self): 'ro_acq_weight_chI', initial_value=0, docstring=( 'Determines the I-channel for integration. When the' ' ro_acq_weight_type is optimal only this channel will ' - 'affect the result.'), vals=vals.Ints(0, 5), + 'affect the result.'), vals=vals.Ints(0, 9), parameter_class=ManualParameter) self.add_parameter( 'ro_acq_weight_chQ', initial_value=1, docstring=( 'Determines the Q-channel for integration.'), - vals=vals.Ints(0, 5), parameter_class=ManualParameter) + vals=vals.Ints(0, 9), parameter_class=ManualParameter) self.add_parameter('ro_acq_weight_func_I', vals=vals.Arrays(), @@ -212,7 +208,8 @@ def add_ro_parameters(self): docstring=('The measurement time in input averaging.')) self.add_parameter('ro_acq_integration_length', initial_value=500e-9, - vals=vals.Numbers(min_value=0, max_value=4096/1.8e9), + vals=vals.Numbers( + min_value=0, max_value=4096/1.8e9), parameter_class=ManualParameter) self.add_parameter('ro_acq_averages', initial_value=1024, @@ -495,10 +492,7 @@ def add_config_parameters(self): self.add_parameter( 'cfg_qubit_nr', label='Qubit number', vals=vals.Ints(0, 7), parameter_class=ManualParameter, initial_value=0, - docstring='The qubit number is used in the OpenQL compiler. ' - 'Beware that a similar parameter (ro_pulse_res_nr) exists that is' - ' used for uploading to the right Lookuptable. These params are ' - 'oten but not always identical (e.g., multiple feedlines). ') + docstring='The qubit number is used in the OpenQL compiler. ') self.add_parameter('cfg_qubit_freq_calc_method', initial_value='latest', @@ -518,13 +512,13 @@ def add_config_parameters(self): # TODO: add docstring (Oct 2017) self.add_parameter('cfg_prepare_ro_awg', vals=vals.Bool(), docstring=('If False disables uploading pusles ' - 'to AWG8 and UHFQC'), + 'to UHFQC'), initial_value=True, parameter_class=ManualParameter) self.add_parameter('cfg_prepare_mw_awg', vals=vals.Bool(), docstring=('If False disables uploading pusles ' - 'to AWG8 and UHFQC'), + 'to AWG8'), initial_value=True, parameter_class=ManualParameter) self.add_parameter('cfg_with_vsm', vals=vals.Bool(), @@ -539,6 +533,10 @@ def add_config_parameters(self): 'or a str (channel name) when using an SPI rack.'), initial_value=1, parameter_class=ManualParameter) + self.add_parameter('cfg_spec_mode', vals=vals.Bool(), + docstring=('Used to activate spec mode in measurements'), + initial_value=False, + parameter_class=ManualParameter) def add_generic_qubit_parameters(self): self.add_parameter('E_c', unit='Hz', @@ -562,7 +560,7 @@ def add_generic_qubit_parameters(self): label='Qubit frequency', unit='Hz', parameter_class=ManualParameter) self.add_parameter('freq_max', - label='mwubit sweet spot frequency', unit='Hz', + label='qubit sweet spot frequency', unit='Hz', parameter_class=ManualParameter) self.add_parameter('freq_res', label='Resonator frequency', unit='Hz', @@ -712,13 +710,12 @@ def _prep_ro_sources(self): LO.on() LO.power(self.ro_pow_LO()) - def _prep_ro_pulse(self): + def _prep_ro_pulse(self, upload=True): """ Sets the appropriate parameters in the RO LutMan and uploads the desired wave. Relevant parameters are: ro_pulse_type ("up_down_down", "square") - ro_pulse_res_nr ro_freq_mod ro_acq_delay @@ -751,7 +748,7 @@ def _prep_ro_pulse(self): ro_lm = self.instr_LutMan_RO.get_instr() ro_lm.AWG(self.instr_acquisition()) - idx = self.ro_pulse_res_nr() + idx = self.cfg_qubit_nr() # These parameters affect all resonators ro_lm.set('pulse_type', 'M_' + self.ro_pulse_type()) ro_lm.set('mixer_alpha', @@ -780,7 +777,8 @@ def _prep_ro_pulse(self): self.ro_pulse_down_phi1()) ro_lm.acquisition_delay(self.ro_acq_delay()) - ro_lm.load_DIO_triggered_sequence_onto_UHFQC() + if upload: + ro_lm.load_DIO_triggered_sequence_onto_UHFQC() UHFQC.sigouts_0_offset(self.ro_pulse_mixer_offs_I()) UHFQC.sigouts_1_offset(self.ro_pulse_mixer_offs_Q()) @@ -837,7 +835,7 @@ def prepare_for_timedomain(self): self._prep_td_sources() self._prep_mw_pulses() if self.cfg_with_vsm(): - self._prep_td_configure_VSM() + self._prep_td_configure_VSM() def _prep_td_sources(self): self.instr_spec_source.get_instr().off() @@ -849,43 +847,79 @@ def _prep_td_sources(self): self.instr_LO_mw.get_instr().power.set(self.mw_pow_td_source.get()) def _prep_mw_pulses(self): - MW_LutMan = self.instr_LutMan_MW.get_instr() - - # QWG lutman has hardcoded channels. - if hasattr(MW_LutMan, 'channel_GI'): - # 4-channels are used for VSM based AWG's. - MW_LutMan.channel_GI(0+self.mw_awg_ch()) - MW_LutMan.channel_GQ(1+self.mw_awg_ch()) - MW_LutMan.channel_DI(2+self.mw_awg_ch()) - MW_LutMan.channel_DQ(3+self.mw_awg_ch()) - # updating the lutmap is required to make sure channels are correct - MW_LutMan.set_default_lutmap() - - # Pulse pars + # 1. Gets instruments and prepares cases + MW_LutMan = self.instr_LutMan_MW.get_instr() + AWG = MW_LutMan.AWG.get_instr() + do_prepare = self.cfg_prepare_mw_awg() + using_QWG = (AWG.__class__.__name__ == 'QuTech_AWG_Module') + using_VSM = self.cfg_with_vsm() + + # 2. Prepares map and parameters for waveforms + # (except pi-pulse amp, which depends on VSM usage) + MW_LutMan.set_default_lutmap() + MW_LutMan.mw_amp90_scale(self.mw_amp90_scale()) + MW_LutMan.mw_gauss_width(self.mw_gauss_width()) + MW_LutMan.mw_motzoi(self.mw_motzoi()) + MW_LutMan.mw_modulation(self.mw_freq_mod()) + MW_LutMan.spec_amp(self.spec_amp()) + + # 3. Does case-dependent things: + # mixers offset+skewness + # pi-pulse amplitude + if using_VSM: + # case with VSM (both QWG and AWG8) MW_LutMan.mw_amp180(self.mw_amp180()) - MW_LutMan.mw_amp90_scale(self.mw_amp90_scale()) - MW_LutMan.mw_gauss_width(self.mw_gauss_width()) - MW_LutMan.mw_motzoi(self.mw_motzoi()) - MW_LutMan.mw_modulation(self.mw_freq_mod()) - - MW_LutMan.spec_amp(self.spec_amp()) - - # Mixer params MW_LutMan.G_mixer_phi(self.mw_G_mixer_phi()) MW_LutMan.G_mixer_alpha(self.mw_G_mixer_alpha()) MW_LutMan.D_mixer_phi(self.mw_D_mixer_phi()) MW_LutMan.D_mixer_alpha(self.mw_D_mixer_alpha()) - if self.cfg_prepare_mw_awg(): - MW_LutMan.load_waveforms_onto_AWG_lookuptable() - AWG = MW_LutMan.AWG.get_instr() - if AWG.__class__.__name__ == 'QuTech_AWG_Module': + MW_LutMan.channel_GI(0+self.mw_awg_ch()) + MW_LutMan.channel_GQ(1+self.mw_awg_ch()) + MW_LutMan.channel_DI(2+self.mw_awg_ch()) + MW_LutMan.channel_DQ(3+self.mw_awg_ch()) + + if using_QWG: # N.B. This part is QWG specific - AWG.ch1_offset(self.mw_mixer_offs_GI()) - AWG.ch2_offset(self.mw_mixer_offs_GQ()) - AWG.ch3_offset(self.mw_mixer_offs_DI()) - AWG.ch4_offset(self.mw_mixer_offs_DQ()) + if hasattr(MW_LutMan, 'channel_GI'): + # 4-channels are used for VSM based AWG's. + AWG.ch1_offset(self.mw_mixer_offs_GI()) + AWG.ch2_offset(self.mw_mixer_offs_GQ()) + AWG.ch3_offset(self.mw_mixer_offs_DI()) + AWG.ch4_offset(self.mw_mixer_offs_DQ()) + else: # using_AWG8 + # N.B. This part is AWG8 specific + AWG.set('sigouts_{}_offset'.format(self.mw_awg_ch()-1), + self.mw_mixer_offs_GI()) + AWG.set('sigouts_{}_offset'.format(self.mw_awg_ch()+0), + self.mw_mixer_offs_GQ()) + AWG.set('sigouts_{}_offset'.format(self.mw_awg_ch()+1), + self.mw_mixer_offs_DI()) + AWG.set('sigouts_{}_offset'.format(self.mw_awg_ch()+2), + self.mw_mixer_offs_DQ()) + else: + if using_QWG: + MW_LutMan.mw_amp180(1) + # case without VSM and with QWG + if ((self.mw_G_mixer_phi() != self.mw_D_mixer_phi()) + or (self.mw_G_mixer_alpha() != self.mw_D_mixer_alpha())): + logging.warning('CCL_Transmon {}; _prep_mw_pulses: ' + 'no VSM detected, using mixer parameters' + ' from gaussian channel.'.format(self.name)) + MW_LutMan.mixer_phi(self.mw_G_mixer_phi()) + MW_LutMan.mixer_alpha(self.mw_G_mixer_alpha()) + AWG.set('ch{}_offset'.format(MW_LutMan.channel_I()), + self.mw_mixer_offs_GI()) + AWG.set('ch{}_offset'.format(MW_LutMan.channel_Q()), + self.mw_mixer_offs_GQ()) + MW_LutMan.channel_amp(self.mw_amp180()) else: + # case with VSM (both QWG and AWG8) + MW_LutMan.mw_amp180(self.mw_amp180()) + MW_LutMan.G_mixer_phi(self.mw_G_mixer_phi()) + MW_LutMan.G_mixer_alpha(self.mw_G_mixer_alpha()) + MW_LutMan.D_mixer_phi(self.mw_D_mixer_phi()) + MW_LutMan.D_mixer_alpha(self.mw_D_mixer_alpha()) # N.B. This part is AWG8 specific AWG.set('sigouts_{}_offset'.format(self.mw_awg_ch()-1), self.mw_mixer_offs_GI()) @@ -954,7 +988,11 @@ def calibrate_motzoi(self, MC=None, verbose=True, update=True): """ Calibrates the motzoi VSM attenauation prameter """ - motzois = gen_sweep_pts(center=30e3, span=30e3, num=31) + using_VSM = self.cfg_with_vsm() + if using_VSM: + motzois = gen_sweep_pts(center=30e3, span=30e3, num=31) + else: + motzois = gen_sweep_pts(center=0, span=.3, num=31) # large range a = self.measure_motzoi(MC=MC, motzoi_atts=motzois, analyze=True) @@ -965,9 +1003,12 @@ def calibrate_motzoi(self, MC=None, verbose=True, update=True): 'outside of measured span, aborting') return False if update: - if verbose: - print('Setting motzoi to {:.3f}'.format(opt_motzoi)) - self.mw_vsm_D_att(opt_motzoi) + if using_VSM: + if verbose: + print('Setting motzoi to {:.3f}'.format(opt_motzoi)) + self.mw_vsm_D_att(opt_motzoi) + else: + self.mw_motzoi(opt_motzoi) return opt_motzoi def calibrate_mixer_offsets_drive(self, update: bool =True)-> bool: @@ -979,71 +1020,98 @@ def calibrate_mixer_offsets_drive(self, update: bool =True)-> bool: ''' # turn relevant channels on + + using_VSM = self.cfg_with_vsm() MW_LutMan = self.instr_LutMan_MW.get_instr() AWG = MW_LutMan.AWG.get_instr() + using_QWG = (AWG.__class__.__name__ == 'QuTech_AWG_Module') - if AWG.__class__.__name__ == 'QuTech_AWG_Module': - chGI_par = AWG.parameters['ch1_offset'] - chGQ_par = AWG.parameters['ch2_offset'] - chDI_par = AWG.parameters['ch3_offset'] - chDQ_par = AWG.parameters['ch4_offset'] - - else: - # This part is AWG8 specific and wont work with a QWG - awg_ch = self.mw_awg_ch() - AWG.stop() - AWG.set('sigouts_{}_on'.format(awg_ch-1), 1) - AWG.set('sigouts_{}_on'.format(awg_ch+0), 1) - AWG.set('sigouts_{}_on'.format(awg_ch+1), 1) - AWG.set('sigouts_{}_on'.format(awg_ch+2), 1) - - chGI_par = AWG.parameters['sigouts_{}_offset'.format(awg_ch-1)] - chGQ_par = AWG.parameters['sigouts_{}_offset'.format(awg_ch+0)] - chDI_par = AWG.parameters['sigouts_{}_offset'.format(awg_ch+1)] - chDQ_par = AWG.parameters['sigouts_{}_offset'.format(awg_ch+2)] - # End of AWG8 specific part - offset_pars = [chGI_par, chGQ_par, chDI_par, chDQ_par] - - VSM = self.instr_VSM.get_instr() + if using_VSM: + if AWG.__class__.__name__ == 'QuTech_AWG_Module': + chGI_par = AWG.parameters['ch1_offset'] + chGQ_par = AWG.parameters['ch2_offset'] + chDI_par = AWG.parameters['ch3_offset'] + chDQ_par = AWG.parameters['ch4_offset'] - ch_in = self.mw_vsm_ch_in() - mod_out = self.mw_vsm_mod_out() - # module 8 is hardcoded for use mixer calls (signal hound) - VSM.set('mod8_marker_source'.format(ch_in), 'int') - VSM.set('mod8_ch{}_marker_state'.format(ch_in), 'on') + else: + # This part is AWG8 specific and wont work with a QWG + awg_ch = self.mw_awg_ch() + AWG.stop() + AWG.set('sigouts_{}_on'.format(awg_ch-1), 1) + AWG.set('sigouts_{}_on'.format(awg_ch+0), 1) + AWG.set('sigouts_{}_on'.format(awg_ch+1), 1) + AWG.set('sigouts_{}_on'.format(awg_ch+2), 1) + + chGI_par = AWG.parameters['sigouts_{}_offset'.format(awg_ch-1)] + chGQ_par = AWG.parameters['sigouts_{}_offset'.format(awg_ch+0)] + chDI_par = AWG.parameters['sigouts_{}_offset'.format(awg_ch+1)] + chDQ_par = AWG.parameters['sigouts_{}_offset'.format(awg_ch+2)] + # End of AWG8 specific part + offset_pars = [chGI_par, chGQ_par, chDI_par, chDQ_par] - ##### - # This snippet is the 4 parameter joint optimization - ##### + VSM = self.instr_VSM.get_instr() - # return True + ch_in = self.mw_vsm_ch_in() + mod_out = self.mw_vsm_mod_out() + # module 8 is hardcoded for use mixer calls (signal hound) + VSM.set('mod8_marker_source'.format(ch_in), 'int') + VSM.set('mod8_ch{}_marker_state'.format(ch_in), 'on') + + ##### + # This snippet is the 4 parameter joint optimization + ##### + + # return True + + # Calibrate Gaussian component mixer + # the use of modula 8 for mixer calibrations is hardcoded. + VSM.set('mod8_ch{}_gaussian_att_raw'.format(ch_in), 50000) + VSM.set('mod8_ch{}_derivative_att_raw'.format(ch_in), 0) + offset_I, offset_Q = mixer_carrier_cancellation( + SH=self.instr_SH.get_instr(), + source=self.instr_LO_mw.get_instr(), + MC=self.instr_MC.get_instr(), + chI_par=chGI_par, chQ_par=chGQ_par) + if update: + self.mw_mixer_offs_GI(offset_I) + self.mw_mixer_offs_GQ(offset_Q) + + # Calibrate Derivative component mixer + VSM.set('mod8_ch{}_gaussian_att_raw'.format(ch_in), 0) + VSM.set('mod8_ch{}_derivative_att_raw'.format(ch_in), 50000) + + offset_I, offset_Q = mixer_carrier_cancellation( + SH=self.instr_SH.get_instr(), + source=self.instr_LO_mw.get_instr(), + MC=self.instr_MC.get_instr(), + chI_par=chDI_par, + chQ_par=chDQ_par) + if update: + self.mw_mixer_offs_DI(offset_I) + self.mw_mixer_offs_DQ(offset_Q) - # Calibrate Gaussian component mixer - #the use of modula 8 for mixer calibrations is hardcoded. - VSM.set('mod8_ch{}_gaussian_att_raw'.format(ch_in), 50000) - VSM.set('mod8_ch{}_derivative_att_raw'.format(ch_in), 0) - offset_I, offset_Q = mixer_carrier_cancellation( - SH=self.instr_SH.get_instr(), - source=self.instr_LO_mw.get_instr(), - MC=self.instr_MC.get_instr(), - chI_par=chGI_par, chQ_par=chGQ_par) - if update: - self.mw_mixer_offs_GI(offset_I) - self.mw_mixer_offs_GQ(offset_Q) + else: + if using_QWG: + QWG_MW = self.instr_LutMan_MW.get_instr().AWG.get_instr() + chI = self.instr_LutMan_MW.get_instr().channel_I() + chQ = self.instr_LutMan_MW.get_instr().channel_Q() + chI_par = QWG_MW.parameters['ch%s_offset' % chI] + chQ_par = QWG_MW.parameters['ch%s_offset' % chQ] + + offset_I, offset_Q = mixer_carrier_cancellation( + SH=self.instr_SH.get_instr(), + source=self.instr_LO_mw.get_instr(), + MC=self.instr_MC.get_instr(), + chI_par=chI_par, + chQ_par=chQ_par) + if update: + self.mw_mixer_offs_GI(offset_I) + self.mw_mixer_offs_GQ(offset_Q) - # Calibrate Derivative component mixer - VSM.set('mod8_ch{}_gaussian_att_raw'.format(ch_in), 0) - VSM.set('mod8_ch{}_derivative_att_raw'.format(ch_in), 50000) + else: + raise NotImplementedError( + 'VSM-less case not implemented without QWG.') - offset_I, offset_Q = mixer_carrier_cancellation( - SH=self.instr_SH.get_instr(), - source=self.instr_LO_mw.get_instr(), - MC=self.instr_MC.get_instr(), - chI_par=chDI_par, - chQ_par=chDQ_par) - if update: - self.mw_mixer_offs_DI(offset_I) - self.mw_mixer_offs_DQ(offset_Q) return True def calibrate_mixer_skewness_RO(self, update=True): @@ -1053,6 +1121,7 @@ def calibrate_mixer_skewness_RO(self, update=True): ''' # using the restless tuning sequence + self.prepare_for_timedomain() p = sqo.randomized_benchmarking( self.cfg_qubit_nr(), self.cfg_openql_platform_fn(), nr_cliffords=[1], @@ -1061,11 +1130,11 @@ def calibrate_mixer_skewness_RO(self, update=True): self.instr_CC.get_instr().start() LutMan = self.instr_LutMan_RO.get_instr() - LutMan.apply_mixer_predistortion_matrix(True) + LutMan.mixer_apply_predistortion_matrix(True) MC = self.instr_MC.get_instr() - S1 = swf.lutman_par( + S1 = swf.lutman_par_UHFQC_dig_trig( LutMan, LutMan.mixer_alpha, single=False, run=True) - S2 = swf.lutman_par( + S2 = swf.lutman_par_UHFQC_dig_trig( LutMan, LutMan.mixer_phi, single=False, run=True) detector = det.Signal_Hound_fixed_frequency( @@ -1117,9 +1186,13 @@ def calibrate_mixer_offsets_RO(self, update: bool=True) -> bool: def measure_heterodyne_spectroscopy(self, freqs, MC=None, analyze=True, close_fig=True): + UHFQC=self.instr_acquisition.get_instr() self.prepare_for_continuous_wave() if MC is None: MC = self.instr_MC.get_instr() + # Starting specmode if set in config + if self.cfg_spec_mode(): + UHFQC.spec_mode_on(IF=self.ro_freq_mod(), ro_amp=self.ro_pulse_amp()) # Snippet here to create and upload the CCL instructions CCL = self.instr_CC.get_instr() CCL.stop() @@ -1136,6 +1209,10 @@ def measure_heterodyne_spectroscopy(self, freqs, MC=None, self.int_avg_det_single._set_real_imag(False) MC.set_detector_function(self.int_avg_det_single) MC.run(name='Resonator_scan'+self.msmt_suffix) + # Stopping specmode + if self.cfg_spec_mode(): + UHFQC.spec_mode_off() + self._prep_ro_pulse(upload=True) if analyze: ma.Homodyne_Analysis(label=self.msmt_suffix, close_fig=close_fig) @@ -1159,7 +1236,7 @@ def measure_resonator_power(self, freqs, powers, MC=None, ro_lm = self.instr_LutMan_RO.get_instr() m_amp_par = ro_lm.parameters[ - 'M_amp_R{}'.format(self.ro_pulse_res_nr())] + 'M_amp_R{}'.format(self.cfg_qubit_nr())] s2 = swf.lutman_par_dB_attenuation_UHFQC_dig_trig( LutMan=ro_lm, LutMan_parameter=m_amp_par) MC.set_sweep_function_2D(s2) @@ -1171,7 +1248,7 @@ def measure_resonator_power(self, freqs, powers, MC=None, ma.TwoD_Analysis(label='Resonator_power_scan', close_fig=close_fig) def measure_resonator_frequency_dac_scan(self, freqs, dac_values, MC=None, - analyze: bool =True, close_fig: bool=True): + analyze: bool =True, close_fig: bool=True): self.prepare_for_continuous_wave() if MC is None: MC = self.instr_MC.get_instr() @@ -1205,8 +1282,8 @@ def measure_resonator_frequency_dac_scan(self, freqs, dac_values, MC=None, ma.TwoD_Analysis(label='Resonator_dac_scan', close_fig=close_fig) def measure_qubit_frequency_dac_scan(self, freqs, dac_values, - pulsed=True, MC=None, - analyze=True, close_fig=True): + pulsed=True, MC=None, + analyze=True, close_fig=True): if not pulsed: logging.warning('CCL transmon can only perform ' 'pulsed spectrocsopy') @@ -1278,7 +1355,9 @@ def measure_ssro(self, MC=None, analyze: bool=True, nr_shots: int=4092*4, post_select: bool = False, post_select_threshold: float =None, update: bool=True, - verbose: bool=True): + verbose: bool=True, + SNR_detector: bool=False, + cal_residual_excitation: bool=False): old_RO_digit = self.ro_acq_digitized() self.ro_acq_digitized(False) # docstring from parent class @@ -1316,39 +1395,48 @@ def measure_ssro(self, MC=None, analyze: bool=True, nr_shots: int=4092*4, 'SSRO{}'.format(self.msmt_suffix)) MC.live_plot_enabled(old_plot_setting) if analyze: - if len(d.value_names) == 1: - - if post_select_threshold == None: - post_select_threshold = self.ro_acq_threshold() - a = ma2.Singleshot_Readout_Analysis( - t_start=None, t_stop=None, - label='SSRO', - options_dict={'post_select': post_select, - 'nr_samples': 2+2*post_select, - 'post_select_threshold': post_select_threshold}, - extract_only=no_figs) - if update_threshold: - # UHFQC threshold is wrong, the magic number is a - # dirty hack. This works. we don't know why. - magic_scale_factor = 1 # 0.655 - self.ro_acq_threshold(a.proc_data_dict['threshold_raw'] * - magic_scale_factor) - if update: - self.F_ssro(a.proc_data_dict['F_assignment_raw']) - self.F_discr(a.proc_data_dict['F_discr']) - if verbose: - print('Avg. Assignement fidelity: \t{:.4f}\n'.format( - a.proc_data_dict['F_assignment_raw']) + - 'Avg. Discrimination fidelity: \t{:.4f}'.format( - a.proc_data_dict['F_discr'])) - return (a.proc_data_dict['F_assignment_raw'], - a.proc_data_dict['F_discr']) + if SNR_detector: + if cal_residual_excitation: + a=ma.SSRO_Analysis(rotate=True, label='SSRO', no_fits=False, close_fig=True, peg=None, pge=None, timestamp=None, channels=d.value_names) + self.peg=a.frac1_0 + self.pge=1-a.frac1_1 + else: + a=ma.SSRO_Analysis(rotate=True, label='SSRO', no_fits=False, close_fig=True, peg=self.peg, pge=self.pge, channels=d.value_names) + return {'SNR':a.SNR, 'F_d':a.F_d, 'F_a':a.F_a} + else: + if len(d.value_names) == 1: + if post_select_threshold == None: + post_select_threshold = self.ro_acq_threshold() + a = ma2.Singleshot_Readout_Analysis( + t_start=None, t_stop=None, + label='SSRO', + options_dict={'post_select': post_select, + 'nr_samples': 2+2*post_select, + 'post_select_threshold': post_select_threshold}, + extract_only=no_figs) + if update_threshold: + # UHFQC threshold is wrong, the magic number is a + # dirty hack. This works. we don't know why. + magic_scale_factor = 1 # 0.655 + self.ro_acq_threshold(a.proc_data_dict['threshold_raw'] * + magic_scale_factor) + if update: + self.F_ssro(a.proc_data_dict['F_assignment_raw']) + self.F_discr(a.proc_data_dict['F_discr']) + if verbose: + print('Avg. Assignement fidelity: \t{:.4f}\n'.format( + a.proc_data_dict['F_assignment_raw']) + + 'Avg. Discrimination fidelity: \t{:.4f}'.format( + a.proc_data_dict['F_discr'])) + return (a.proc_data_dict['F_assignment_raw'], + a.proc_data_dict['F_discr']) + else: + a = ma.SSRO_Analysis(label='SSRO', + channels=d.value_names, + no_fits=no_figs, rotate=True) + return a.F_a, a.F_d - a = ma.SSRO_Analysis(label='SSRO', - channels=d.value_names, - no_fits=no_figs, rotate=True) - return a.F_a, a.F_d def measure_transients(self, MC=None, analyze: bool=True, cases=('off', 'on'), @@ -1409,12 +1497,14 @@ def measure_transients(self, MC=None, analyze: bool=True, def calibrate_optimal_weights(self, MC=None, verify: bool=True, analyze: bool=True, update: bool=True, - no_figs: bool=False)->bool: + no_figs: bool=False, + update_threshold: bool=True)->bool: if MC is None: MC = self.instr_MC.get_instr() # Ensure that enough averages are used to get accurate weights old_avg = self.ro_acq_averages() + self.ro_acq_averages(2**15) transients = self.measure_transients(MC=MC, analyze=analyze, depletion_analysis=False) @@ -1424,8 +1514,8 @@ def calibrate_optimal_weights(self, MC=None, verify: bool=True, self.ro_acq_averages(old_avg) # Calculate optimal weights - optimized_weights_I = -(transients[1][0] - transients[0][0]) - optimized_weights_Q = -(transients[1][1] - transients[0][1]) + optimized_weights_I = (transients[1][0] - transients[0][0]) + optimized_weights_Q = (transients[1][1] - transients[0][1]) # joint rescaling to +/-1 Volt maxI = np.max(np.abs(optimized_weights_I)) maxQ = np.max(np.abs(optimized_weights_Q)) @@ -1436,7 +1526,6 @@ def calibrate_optimal_weights(self, MC=None, verify: bool=True, weight_scale_factor*optimized_weights_I) optimized_weights_Q = np.array( weight_scale_factor*optimized_weights_Q) - self.ro_acq_averages(old_avg) if update: self.ro_acq_weight_func_I(optimized_weights_I) @@ -1444,7 +1533,7 @@ def calibrate_optimal_weights(self, MC=None, verify: bool=True, self.ro_acq_weight_type('optimal') if verify: - self.measure_ssro(no_figs=no_figs) + self.measure_ssro(no_figs=no_figs, update_threshold=update_threshold) return True def measure_rabi(self, MC=None, atts=np.linspace(0, 65535, 31), @@ -1476,21 +1565,22 @@ def measure_rabi_vsm(self, MC=None, atts=np.linspace(0, 65535, 31), mod_out = self.mw_vsm_mod_out() ch_in = self.mw_vsm_ch_in() if all_modules: - mod_sweep=[] - for i in range(8): - VSM.set('mod{}_ch{}_marker_state'.format(i+1, ch_in),'on') - G_par=VSM.parameters['mod{}_ch{}_gaussian_att_raw'.format( - i+1, ch_in)] - D_par=VSM.parameters['mod{}_ch{}_derivative_att_raw'.format( - i+1, ch_in)] - mod_sweep.append(swf.two_par_joint_sweep(G_par, D_par, preserve_ratio=False)) - s=swf.multi_sweep_function(sweep_functions=mod_sweep) + mod_sweep = [] + for i in range(8): + VSM.set('mod{}_ch{}_marker_state'.format(i+1, ch_in), 'on') + G_par = VSM.parameters['mod{}_ch{}_gaussian_att_raw'.format( + i+1, ch_in)] + D_par = VSM.parameters['mod{}_ch{}_derivative_att_raw'.format( + i+1, ch_in)] + mod_sweep.append(swf.two_par_joint_sweep( + G_par, D_par, preserve_ratio=False)) + s = swf.multi_sweep_function(sweep_functions=mod_sweep) else: - G_par = VSM.parameters['mod{}_ch{}_gaussian_att_raw'.format( - mod_out, ch_in)] - D_par = VSM.parameters['mod{}_ch{}_derivative_att_raw'.format( - mod_out, ch_in)] - s = swf.two_par_joint_sweep(G_par, D_par, preserve_ratio=True) + G_par = VSM.parameters['mod{}_ch{}_gaussian_att_raw'.format( + mod_out, ch_in)] + D_par = VSM.parameters['mod{}_ch{}_derivative_att_raw'.format( + mod_out, ch_in)] + s = swf.two_par_joint_sweep(G_par, D_par, preserve_ratio=True) self.instr_CC.get_instr().eqasm_program(p.filename) MC.set_sweep_function(s) MC.set_sweep_points(atts) @@ -1502,8 +1592,11 @@ def measure_rabi_vsm(self, MC=None, atts=np.linspace(0, 65535, 31), return True def measure_rabi_channel_amp(self, MC=None, amps=np.linspace(0, 1, 31), - analyze=True, close_fig=True, real_imag=True, - prepare_for_timedomain=True, update_mw_lutman=False): + analyze=True, close_fig=True, real_imag=True, + prepare_for_timedomain=True, update_mw_lutman=False): + MW_LutMan = self.instr_LutMan_MW.get_instr() + using_QWG = (MW_LutMan.AWG.get_instr( + ).__class__.__name__ == 'QuTech_AWG_Module') if MC is None: MC = self.instr_MC.get_instr() if prepare_for_timedomain: @@ -1514,8 +1607,6 @@ def measure_rabi_channel_amp(self, MC=None, amps=np.linspace(0, 1, 31), platf_cfg=self.cfg_openql_platform_fn()) self.instr_CC.get_instr().eqasm_program(p.filename) - MW_LutMan = self.instr_LutMan_MW.get_instr() - s = MW_LutMan.channel_amp MC.set_sweep_function(s) MC.set_sweep_points(amps) @@ -1525,8 +1616,10 @@ def measure_rabi_channel_amp(self, MC=None, amps=np.linspace(0, 1, 31), MC.run(name='rabi_'+self.msmt_suffix) ma.MeasurementAnalysis() if update_mw_lutman: - a=ma.Rabi_Analysis(label='rabi') - MW_LutMan.channel_amp(a.rabi_amplitudes['piPulse']) + a = ma.Rabi_Analysis(label='rabi') + MW_LutMan.channel_amp(a.rabi_amplitudes['piPulse']) + if using_QWG: + self.mw_amp180(a.rabi_amplitudes['piPulse']) return True def measure_allxy(self, MC=None, @@ -1553,8 +1646,6 @@ def measure_allxy(self, MC=None, a = ma.AllXY_Analysis(close_main_fig=close_fig) return a.deviation_total - - def calibrate_mw_gates_restless( self, MC=None, parameter_list: list = ['G_att', 'D_att', 'freq'], @@ -1574,7 +1665,6 @@ def calibrate_mw_gates_restless( prepare_for_timedomain=prepare_for_timedomain, method='restless') - def calibrate_mw_gates_rb( self, MC=None, parameter_list: list = ['G_att', 'D_att', 'freq'], @@ -1592,7 +1682,7 @@ def calibrate_mw_gates_rb( method = self.cfg_rb_calibrate_method() if method == 'restless': restless = True - else: # ORBIT + else: # ORBIT restless = False if MC is None: @@ -1971,22 +2061,75 @@ def measure_ramsey(self, times=None, MC=None, self.mw_freq_mod.get() + artificial_detuning) p = sqo.Ramsey(times, qubit_idx=self.cfg_qubit_nr(), - platf_cfg=self.cfg_openql_platform_fn()) + platf_cfg=self.cfg_openql_platform_fn()) s = swf.OpenQL_Sweep(openql_program=p, - CCL=self.instr_CC.get_instr(), - parameter_name='Time', unit='s') - d = self.int_avg_det + CCL=self.instr_CC.get_instr(), + parameter_name='Time', unit='s') MC.set_sweep_function(s) MC.set_sweep_points(times) + + d = self.int_avg_det MC.set_detector_function(d) MC.run('Ramsey'+label+self.msmt_suffix) - a = ma.Ramsey_Analysis(auto=True, close_fig=True, - freq_qubit=freq_qubit, - artificial_detuning=artificial_detuning) - if update: - # dict containing val and stderr - self.T2_star(a.T2_star['T2_star']) - return a.T2_star + if analyze: + a = ma.Ramsey_Analysis(auto=True, close_fig=True, + freq_qubit=freq_qubit, + artificial_detuning=artificial_detuning) + if update: + self.T2_star(a.T2_star['T2_star']) + return a.T2_star + + def measure_msmt_induced_dephasing_ramsey(self, MC=None, + label: str='', verbose:bool = True, + analyze=True, close_fig=True, update=True, + cross_target_qubits=None, multi_qubit_platf_cfg=None): + # docstring from parent class + # N.B. this is a good example for a generic timedomain experiment using + # the CCL transmon. + if MC is None: + MC = self.instr_MC.get_instr() + if cross_target_qubits is None: + platf_cfg = self.cfg_openql_platform_fn() + else: + platf_cfg = multi_qubit_platf_cfg + + self.prepare_for_timedomain() + angles = np.arange(0, 421, 20) + if cross_target_qubits is None: + qubits = [self.cfg_qubit_nr()] + else: + qubits = [] + for cross_target_qubit in cross_target_qubits: + qubits.append(cross_target_qubit.cfg_qubit_nr()) + qubits.append(self.cfg_qubit_nr()) + + p = mqo.Ramsey_msmt_induced_dephasing(qubits=qubits, angles=angles, + platf_cfg=platf_cfg) + s = swf.OpenQL_Sweep(openql_program=p, + CCL=self.instr_CC.get_instr(), + parameter_name='angle', unit='degree') + MC.set_sweep_function(s) + MC.set_sweep_points(angles) + d = self.int_avg_det + MC.set_detector_function(d) + MC.run('Ramsey'+label+self.msmt_suffix) + if analyze: + a = ma.Ramsey_Analysis(auto=True, close_fig=True, + freq_qubit=self.freq_qubit(), + artificial_detuning=0, #fixme + phase_sweep_only=True) + res = { + 'coherence': a.fit_res.params['amplitude'].value, + 'phase': (a.fit_res.params['phase'].value)*360/(2*np.pi)% 360 + } + if verbose: + print('> ramsey analyse', res) + return res + #else: + # return {'coherence': -1, + # 'phase' : -1} + + def measure_echo(self, times=None, MC=None, analyze=True, close_fig=True, update=True): @@ -2058,7 +2201,6 @@ def measure_flipping(self, number_of_flips=np.arange(20), equator=True, self.prepare_for_timedomain() p = sqo.flipping(number_of_flips=nf, equator=equator, qubit_idx=self.cfg_qubit_nr(), - parameter_name='Number of pi-pulses', unit='#', platf_cfg=self.cfg_openql_platform_fn()) s = swf.OpenQL_Sweep(openql_program=p, @@ -2073,9 +2215,14 @@ def measure_flipping(self, number_of_flips=np.arange(20), equator=True, options_dict={'scan_label': 'flipping'}) return a - def measure_motzoi(self, motzoi_atts=np.linspace(0, 50e3, 31), + def measure_motzoi(self, motzoi_atts=None, prepare_for_timedomain: bool=True, MC=None, analyze=True, close_fig=True): + using_VSM = self.cfg_with_vsm() + MW_LutMan = self.instr_LutMan_MW.get_instr() + AWG = MW_LutMan.AWG.get_instr() + using_QWG = (AWG.__class__.__name__ == 'QuTech_AWG_Module') + if MC is None: MC = self.instr_MC.get_instr() if prepare_for_timedomain: @@ -2089,18 +2236,29 @@ def measure_motzoi(self, motzoi_atts=np.linspace(0, 50e3, 31), values_per_point_suffex=['yX', 'xY'], always_prepare=True) - VSM = self.instr_VSM.get_instr() - mod_out = self.mw_vsm_mod_out() - ch_in = self.mw_vsm_ch_in() - D_par = VSM.parameters['mod{}_ch{}_derivative_att_raw'.format( - mod_out, ch_in)] + if using_VSM: + if motzoi_atts is None: + motzoi_atts = np.linspace(0, 50e3, 31) + mod_out = self.mw_vsm_mod_out() + ch_in = self.mw_vsm_ch_in() + D_par = VSM.parameters['mod{}_ch{}_derivative_att_raw'.format( + mod_out, ch_in)] + swf_func = D_par + else: + if using_QWG: + if motzoi_atts is None: + motzoi_atts = np.linspace(-.3, .3, 31) + swf_func = swf.QWG_lutman_par(LutMan=MW_LutMan, + LutMan_parameter=MW_LutMan.mw_motzoi) + else: + raise NotImplementedError( + 'VSM-less case not implemented without QWG.') - MC.set_sweep_function(D_par) + MC.set_sweep_function(swf_func) MC.set_sweep_points(motzoi_atts) MC.set_detector_function(d) MC.run('Motzoi_XY'+self.msmt_suffix) - if analyze: if self.ro_acq_weight_type() == 'optimal': a = ma2.Intersect_Analysis( @@ -2171,7 +2329,6 @@ def measure_randomized_benchmarking(self, nr_cliffords=2**np.arange(12), self.F_RB(a.fit_res.params['fidelity_per_Clifford'].value) return a.fit_res.params['fidelity_per_Clifford'].value - def create_dep_graph(self): dag = AutoDepGraph_DAG(name=self.name+' DAG') @@ -2204,7 +2361,6 @@ def create_dep_graph(self): dag.add_node(self.name + ' ro pulse-acq window timing') - dag.add_node(self.name + ' readout coarse', check_function=self.name + '.measure_ssro') @@ -2269,3 +2425,181 @@ def create_dep_graph(self): self.name+' single qubit gates fine') self._dag = dag return dag + + #functions for quantum efficiency measurements and crossdephasing measurements + def measure_msmt_induced_dephasing_sweeping_amps(self, amps_rel=None, + nested_MC=None, cross_target_qubits=None, + multi_qubit_platf_cfg=None, analyze=False, + verbose: bool=True): + waveform_name = 'up_down_down_final' + + if nested_MC is None: + nested_MC = self.instr_nested_MC.get_instr() + + if cross_target_qubits is None or (len(cross_target_qubits) == 1 and self.name == cross_target_qubits[0]): + cross_target_qubits = None + + if cross_target_qubits is None: + # Only measure on a single Qubit + cfg_qubit_nrs = [self.cfg_qubit_nr()] + optimization_M_amps = [self.ro_pulse_amp()] + optimization_M_amp_down0s = [self.ro_pulse_down_amp0()] + optimization_M_amp_down1s = [self.ro_pulse_down_amp1()] + readout_pulse_length = self.ro_pulse_length() + readout_pulse_length += self.ro_pulse_down_length0() + readout_pulse_length += self.ro_pulse_down_length1() + amps_rel = np.linspace(0, 0.5, 11) if amps_rel is None else amps_rel + else: + cfg_qubit_nrs = [] + optimization_M_amps = [] + optimization_M_amp_down0s = [] + optimization_M_amp_down1s = [] + readout_pulse_lengths = [] + for cross_target_qubit in cross_target_qubits: + cfg_qubit_nrs.append(cross_target_qubit.cfg_qubit_nr()) + optimization_M_amps.append(cross_target_qubit.ro_pulse_amp()) + optimization_M_amp_down0s.append(cross_target_qubit.ro_pulse_down_amp0()) + optimization_M_amp_down1s.append(cross_target_qubit.ro_pulse_down_amp1()) + ro_len = cross_target_qubit.ro_pulse_length() + ro_len += cross_target_qubit.ro_pulse_down_length0() + ro_len += cross_target_qubit.ro_pulse_down_length1() + readout_pulse_lengths.append(ro_len) + readout_pulse_length = np.max(readout_pulse_lengths) + + old_waveform_name = self.ro_pulse_type() + self.ro_pulse_type(waveform_name) + RO_lutman = self.instr_LutMan_RO.get_instr() + RO_lutman.set('M_final_amp_R{}'.format(self.cfg_qubit_nr()), self.ro_pulse_amp()) + old_delay = self.ro_acq_delay() + + d = RO_lutman.get('M_final_delay_R{}'.format(self.cfg_qubit_nr())) + self.ro_acq_delay(old_delay + readout_pulse_length +d) + self.ro_acq_integration_length(readout_pulse_length+100e-9) + self.ro_acq_weight_type('SSB') + self.prepare_for_timedomain() + old_ro_prepare_state = self.cfg_prepare_ro_awg() + self.cfg_prepare_ro_awg(False) + + sweep_function = swf.lutman_par_depletion_pulse_global_scaling( + LutMan=RO_lutman, + resonator_numbers=cfg_qubit_nrs, + optimization_M_amps=optimization_M_amps, + optimization_M_amp_down0s=optimization_M_amp_down0s, + optimization_M_amp_down1s=optimization_M_amp_down1s, + upload=True + ) + d = det.Function_Detector( + self.measure_msmt_induced_dephasing_ramsey, + msmt_kw={ + 'cross_target_qubits': cross_target_qubits, + 'multi_qubit_platf_cfg': multi_qubit_platf_cfg, + 'analyze': True, + }, + result_keys=['coherence', 'phase'] + ) + + nested_MC.set_sweep_function(sweep_function) + nested_MC.set_sweep_points(amps_rel) + nested_MC.set_detector_function(d) + + label = 'ro_amp_sweep_ramsey' + self.msmt_suffix + nested_MC.run(label) + + # Reset qubit objects parameters tp previous settings + self.ro_pulse_type(old_waveform_name) + self.cfg_prepare_ro_awg(old_ro_prepare_state) + self.ro_acq_delay(old_delay) + + if analyze: + res = ma.MeasurementAnalysis(label=label, plot_all=False, auto=True) + return res + + + def measure_SNR_sweeping_amps(self, amps_rel, nr_shots=2*4094, + nested_MC=None, analyze=True): + if nested_MC is None: + nested_MC = self.instr_nested_MC.get_instr() + self.prepare_for_timedomain() + RO_lutman = self.instr_LutMan_RO.get_instr() + old_ro_prepare_state = self.cfg_prepare_ro_awg() + self.cfg_prepare_ro_awg(False) + + sweep_function = swf.lutman_par_depletion_pulse_global_scaling( + LutMan=RO_lutman, + resonator_numbers=[self.cfg_qubit_nr()], + optimization_M_amps=[self.ro_pulse_amp()], + optimization_M_amp_down0s=[self.ro_pulse_down_amp0()], + optimization_M_amp_down1s=[self.ro_pulse_down_amp1()], + upload=True + ) + d = det.Function_Detector( + self.measure_ssro, + msmt_kw={ + 'nr_shots': nr_shots, + 'analyze': True, 'SNR_detector': True, + 'cal_residual_excitation': False, + }, + result_keys=['SNR', 'F_d', 'F_a'] + ) + + nested_MC.set_sweep_function(sweep_function) + nested_MC.set_sweep_points(amps_rel) + nested_MC.set_detector_function(d) + label = 'ro_amp_sweep_SNR' + self.msmt_suffix + nested_MC.run(label) + + self.cfg_prepare_ro_awg(old_ro_prepare_state) + + if analyze: + ma.MeasurementAnalysis(label=label, plot_all=False, auto=True) + + def measure_quantum_efficiency(self, amps_rel = None, nr_shots=2*4094, + analyze=True, verbose=True): + # requires the cc light to have the readout time configured equal + # to the measurement and depletion time + 60 ns buffer + # it requires an optimized depletion pulse + amps_rel = np.linspace(0,0.5,11) if amps_rel is None else amps_rel + self.cfg_prepare_ro_awg(True) + + start_time = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") + + self.measure_msmt_induced_dephasing_sweeping_amps(amps_rel=amps_rel, + analyze=False) + readout_pulse_length = self.ro_pulse_length() + readout_pulse_length += self.ro_pulse_down_length0() + readout_pulse_length += self.ro_pulse_down_length1() + self.ro_acq_integration_length(readout_pulse_length+100e-9) + + # calibrate optimal weights + self.calibrate_optimal_weights(verify=False) + + # calibrate residual excitation and relaxation at high power + self.measure_ssro(cal_residual_excitation=True, SNR_detector=True, + nr_shots=nr_shots, update_threshold=False) + self.measure_SNR_sweeping_amps(amps_rel=amps_rel, analyze=False) + + end_time = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") + + # set the pulse back to optimal depletion + self.ro_pulse_type('up_down_down') + + if analyze: + options_dict = { + 'individual_plots': True, + 'verbose': verbose, + } + qea = ma2.QuantumEfficiencyAnalysis(t_start=start_time, + t_stop=end_time, + use_sweeps=True, + options_dict=options_dict, + label_ramsey='_ro_amp_sweep_ramsey'+self.msmt_suffix, + label_ssro='_ro_amp_sweep_SNR'+self.msmt_suffix) + + qea.run_analysis() + eta = qea.fit_dicts['eta'] + u_eta = qea.fit_dicts['u_eta'] + + return {'eta': eta, 'u_eta': u_eta, + 't_start': start_time, 't_stop': end_time} + else: + return {} diff --git a/pycqed/instrument_drivers/physical_instruments/QuTech_AWG_Module.py b/pycqed/instrument_drivers/physical_instruments/QuTech_AWG_Module.py index 3cceeda35b..0f11cdbf07 100644 --- a/pycqed/instrument_drivers/physical_instruments/QuTech_AWG_Module.py +++ b/pycqed/instrument_drivers/physical_instruments/QuTech_AWG_Module.py @@ -136,6 +136,7 @@ def add_parameters(self): dac_temperature_cmd = 'STATus:DAC{}:TEMperature'.format(ch) gain_adjust_cmd = 'DAC{}:GAIn:DRIFt:ADJust'.format(ch) dac_digital_value_cmd = 'DAC{}:DIGitalvalue'.format(ch) + # Set channel first to ensure sensible sorting of pars # Compatibility: 5014, QWG self.add_parameter('ch{}_state'.format(ch), @@ -178,7 +179,6 @@ def add_parameters(self): docstring='Reads the temperature of a DAC.\n' \ +'Temperature measurement interval is 10 seconds\n' \ +'Return:\n float with temperature in Celsius') - self.add_parameter('output{}_voltage'.format(ch), unit='V', label=('Channel {} voltage output').format(ch), diff --git a/pycqed/instrument_drivers/physical_instruments/QuTech_CCL.py b/pycqed/instrument_drivers/physical_instruments/QuTech_CCL.py index 5305a7ccd9..f69d472217 100644 --- a/pycqed/instrument_drivers/physical_instruments/QuTech_CCL.py +++ b/pycqed/instrument_drivers/physical_instruments/QuTech_CCL.py @@ -298,6 +298,8 @@ def get_idn(self): except Exception as e: logging.warn('Error: failed to retrive IDN from CC-Light.', str(e)) + self.version_info["Driver Version"] = self.driver_version + return self.version_info def print_readable_idn(self): diff --git a/pycqed/instrument_drivers/physical_instruments/ZurichInstruments/UHFQuantumController.py b/pycqed/instrument_drivers/physical_instruments/ZurichInstruments/UHFQuantumController.py index 0e90541480..6282510458 100644 --- a/pycqed/instrument_drivers/physical_instruments/ZurichInstruments/UHFQuantumController.py +++ b/pycqed/instrument_drivers/physical_instruments/ZurichInstruments/UHFQuantumController.py @@ -33,7 +33,8 @@ class UHFQC(Instrument): """ def __init__(self, name, device='auto', interface='USB', - address='127.0.0.1', port=8004, DIO=True,**kw): + address='127.0.0.1', port=8004, DIO=True, + nr_integration_channels=9,**kw): ''' Input arguments: name: (str) name of the instrument @@ -44,7 +45,7 @@ def __init__(self, name, device='auto', interface='USB', # #suggestion W vlothuizen t0 = time.time() super().__init__(name, **kw) - + self.nr_integration_channels = nr_integration_channels self.DIO=DIO self._daq = zi.ziDAQServer(address, int(port), 5) # self._daq.setDebugLevel(5) @@ -164,7 +165,7 @@ def __init__(self, name, device='auto', interface='USB', # storing an offset correction parameter for all weight functions, # this allows normalized calibration when performing cross-talk suppressed # readout - for i in range(5): + for i in range(self.nr_integration_channels): self.add_parameter("quex_trans_offset_weightfunction_{}".format(i), unit='', # unit is adc value label='RO normalization offset', @@ -231,9 +232,9 @@ def load_default_settings(self): self.awgs_0_dio_valid_index(16) self.awgs_0_dio_valid_polarity(2) # high polarity - - - + # setting the output channels to 50 ohm + self.sigouts_0_imp50(True) + self.sigouts_1_imp50(True) # We probably need to adjust some delays here... #self.awgs_0_dio_delay_index(31) @@ -241,17 +242,17 @@ def load_default_settings(self): # No rotation on the output of the weighted integration unit, i.e. take # real part of result - for i in range(0, 4): - eval('self.quex_rot_{0}_real(1.0)'.format(i)) - eval('self.quex_rot_{0}_imag(0.0)'.format(i)) + for i in range(0, self.nr_integration_channels): + self.set('quex_rot_{0}_real'.format(i), 1.0) + self.set('quex_rot_{0}_imag'.format(i), 0.0) # No cross-coupling in the matrix multiplication (identity matrix) - for i in range(0, 4): - for j in range(0, 4): + for i in range(0, self.nr_integration_channels): + for j in range(0,): if i == j: - eval('self.quex_trans_{0}_col_{1}_real(1)'.format(i, j)) + self.set('quex_trans_{0}_col_{1}_real'.format(i, j),1) else: - eval('self.quex_trans_{0}_col_{1}_real(0)'.format(i, j)) + self.set('quex_trans_{0}_col_{1}_real'.format(i, j),0) # Configure the result logger to not do any averaging self.quex_rl_length(pow(2, LOG2_AVG_CNT)-1) @@ -679,6 +680,7 @@ def prepare_SSB_weight_and_rotation(self, IF, """ trace_length = 4096 tbase = np.arange(0, trace_length/1.8e9, 1/1.8e9) + print(len(tbase)) cosI = np.array(np.cos(2*np.pi*IF*tbase)) sinI = np.array(np.sin(2*np.pi*IF*tbase)) self.set('quex_wint_weights_{}_real'.format(weight_function_I), @@ -798,7 +800,7 @@ def awg_sequence_acquisition_and_DIO_triggered_pulse( 'const TRIGGER1 = 0x000001;\n' + 'const WINT_TRIG = 0x000010;\n' + 'const IAVG_TRIG = 0x000020;\n' + - 'const WINT_EN = 0x1f0000;\n' + + 'const WINT_EN = 0x1ff0000;\n' + 'const DIO_VALID = 0x00010000;\n' + 'setTrigger(WINT_EN);\n' + 'var loop_cnt = getUserReg(0);\n' + @@ -889,7 +891,7 @@ def awg_sequence_acquisition_and_pulse(self, Iwave, Qwave, acquisition_delay, di const TRIGGER1 = 0x000001; const WINT_TRIG = 0x000010; const IAVG_TRIG = 0x000020; -const WINT_EN = 0x1f0000; +const WINT_EN = 0x1ff0000; setTrigger(WINT_EN); var loop_cnt = getUserReg(0); var wait_delay = getUserReg(2); @@ -954,7 +956,7 @@ def awg_sequence_acquisition(self): const TRIGGER1 = 0x000001; const WINT_TRIG = 0x000010; const IAVG_TRIG = 0x000020; -const WINT_EN = 0x1f0000; +const WINT_EN = 0x1ff0000; setTrigger(WINT_EN); var loop_cnt = getUserReg(0); var RO_TRIG; @@ -988,26 +990,87 @@ def awg_sequence_acquisition_and_pulse_SSB( coswave = RO_amp*np.cos(2*np.pi*array*f_RO_mod/f_sampling) Iwave = (coswave+sinwave)/np.sqrt(2) Qwave = (coswave-sinwave)/np.sqrt(2) - # Iwave, Qwave = PG.mod_pulse(np.ones(samples), np.zeros(samples), f=f_RO_mod, phase=0, sampling_rate=f_sampling) self.awg_sequence_acquisition_and_pulse( Iwave, Qwave, acquisition_delay, dig_trigger=dig_trigger) def upload_transformation_matrix(self, matrix): for i in range(np.shape(matrix)[0]): # looping over the rows for j in range(np.shape(matrix)[1]): # looping over the colums - eval( - 'self.quex_trans_{}_col_{}_real(matrix[{}][{}])'.format(j, i, i, j)) + self.set('quex_trans_{}_col_{}_real'.format(j, i), matrix[i][j]) - def download_transformation_matrix(self, nr_rows=4, nr_cols=4): + def download_transformation_matrix(self, nr_rows=None, nr_cols=None): + if not nr_rows or not nr_cols: + nr_rows = self.nr_integration_channels + nr_cols = self.nr_integration_channels matrix = np.zeros([nr_rows, nr_cols]) for i in range(np.shape(matrix)[0]): # looping over the rows for j in range(np.shape(matrix)[1]): # looping over the colums - matrix[i][j] = ( - eval('self.quex_trans_{}_col_{}_real()'.format(j, i))) - # print(value) - # matrix[i,j]=value + matrix[i][j] = self.get('quex_trans_{}_col_{}_real'.format(j, i)) return matrix + + def spec_mode_on(self, acq_length=1/1500, IF=20e6, ro_amp=0.1): + awg_code = """ +const TRIGGER1 = 0x000001; +const WINT_TRIG = 0x000010; +const IAVG_TRIG = 0x000020; +const WINT_EN = 0x1f0000; +setTrigger(WINT_EN); +var loop_cnt = getUserReg(0); + +const Fsample = 1.8e9; +const triggerdelay = {}; //seconds +repeat(loop_cnt) {{ +setTrigger(WINT_EN + WINT_TRIG + TRIGGER1); +wait(5); +setTrigger(WINT_EN); +wait(triggerdelay*Fsample/8 - 5); +}} +wait(1000); +setTrigger(0); + """.format(acq_length) + #setting the internal oscillator to the IF + self.oscs_0_freq(IF) + #setting the integration path to use the oscillator instead of integration functions + self.quex_wint_mode(1) + #just below the + self.quex_wint_length(int(acq_length*0.99*1.8e9)) + #uploading the sequence + self.awg_string(awg_code) + # setting the integration rotation to single sideband + self.quex_rot_0_real(1) + self.quex_rot_0_imag(1) + self.quex_rot_1_real(1) + self.quex_rot_1_imag(-1) + # setting the mixer deskewing to identity + self.quex_deskew_0_col_0(1) + self.quex_deskew_1_col_0(0) + self.quex_deskew_0_col_1(0) + self.quex_deskew_1_col_1(1) + + self.sigouts_0_enables_3(1) + self.sigouts_1_enables_7(1) + # setting + self.sigouts_1_amplitudes_7(ro_amp)#magic scale factor + self.sigouts_0_amplitudes_3(ro_amp) + + def spec_mode_off(self): + # Resetting To regular Mode + # changing int length + self.quex_wint_mode(0) + # Default settings copied + self.quex_rot_0_imag(0) + self.quex_rot_0_real(1) + self.quex_rot_1_imag(0) + self.quex_rot_1_real(1) + # setting to DSB by default + self.quex_deskew_0_col_0(1) + self.quex_deskew_1_col_0(0) + self.quex_deskew_0_col_1(0) + self.quex_deskew_1_col_1(1) + #switching off the modulation tone + self.sigouts_0_enables_3(0) + self.sigouts_1_enables_7(0) class ziShellError(Exception): """Base class for exceptions in this module.""" diff --git a/pycqed/instrument_drivers/physical_instruments/ZurichInstruments/zi_parameter_files/d_node_pars.txt b/pycqed/instrument_drivers/physical_instruments/ZurichInstruments/zi_parameter_files/d_node_pars.txt index 0be0a72618..be6f275f53 100644 --- a/pycqed/instrument_drivers/physical_instruments/ZurichInstruments/zi_parameter_files/d_node_pars.txt +++ b/pycqed/instrument_drivers/physical_instruments/ZurichInstruments/zi_parameter_files/d_node_pars.txt @@ -1,4 +1,8 @@ -[ +[ + [ + "system/fpgarevision", + "float" + ], [ "awgs/0/sequencer/program", "vector_g" @@ -112,73 +116,122 @@ "float" ], [ - "quex/wint/weights/3/real", - "vector_gs" + "quex/iavg/data/0", + "vector_g" ], [ "quex/iavg/data/1", "vector_g" ], [ - "quex/wint/weights/1/real", - "vector_gs" + "quex/rl/data/0", + "vector_g" + ], + [ + "quex/rl/data/1", + "vector_g" + ], + [ + "quex/rl/data/2", + "vector_g" ], [ "quex/rl/data/3", "vector_g" ], + [ + "quex/rl/data/4", + "vector_g" + ], + [ + "quex/rl/data/5", + "vector_g" + ], + [ + "quex/rl/data/6", + "vector_g" + ], + [ + "quex/rl/data/7", + "vector_g" + ], + [ + "quex/rl/data/8", + "vector_g" + ], + [ + "quex/wint/weights/0/real", + "vector_gs" + ], + [ + "quex/wint/weights/1/real", + "vector_gs" + ], [ "quex/wint/weights/2/real", "vector_gs" ], [ - "quex/iavg/data/0", - "vector_g" + "quex/wint/weights/3/real", + "vector_gs" ], [ - "quex/wint/weights/2/imag", + "quex/wint/weights/4/real", "vector_gs" ], [ - "quex/wint/weights/3/imag", + "quex/wint/weights/5/real", "vector_gs" ], [ - "quex/rl/data/4", - "vector_g" + "quex/wint/weights/6/real", + "vector_gs" + ], + [ + "quex/wint/weights/7/real", + "vector_gs" + ], + [ + "quex/wint/weights/8/real", + "vector_gs" ], [ "quex/wint/weights/0/imag", "vector_gs" ], [ - "quex/wint/weights/4/imag", + "quex/wint/weights/1/imag", "vector_gs" ], [ - "quex/rl/data/2", - "vector_g" + "quex/wint/weights/2/imag", + "vector_gs" ], [ - "quex/wint/weights/0/real", + "quex/wint/weights/3/imag", "vector_gs" ], [ - "quex/rl/data/0", - "vector_g" + "quex/wint/weights/4/imag", + "vector_gs" ], [ - "quex/wint/weights/1/imag", + "quex/wint/weights/5/imag", "vector_gs" ], [ - "quex/wint/weights/4/real", + "quex/wint/weights/6/imag", "vector_gs" ], [ - "quex/rl/data/1", - "vector_g" + "quex/wint/weights/7/imag", + "vector_gs" + ], + [ + "quex/wint/weights/8/imag", + "vector_gs" ], + [ "dios/0/input", "vector_s" diff --git a/pycqed/instrument_drivers/physical_instruments/ZurichInstruments/zi_parameter_files/s_node_pars.txt b/pycqed/instrument_drivers/physical_instruments/ZurichInstruments/zi_parameter_files/s_node_pars.txt index 47cd8719f7..876b4b6b53 100644 --- a/pycqed/instrument_drivers/physical_instruments/ZurichInstruments/zi_parameter_files/s_node_pars.txt +++ b/pycqed/instrument_drivers/physical_instruments/ZurichInstruments/zi_parameter_files/s_node_pars.txt @@ -665,6 +665,54 @@ 0, 4 ], + [ + "quex/corr/5/mode", + "bool", + 0, + 1 + ], + [ + "quex/corr/5/source", + "int_8bit", + 0, + 4 + ], + [ + "quex/corr/6/mode", + "bool", + 0, + 1 + ], + [ + "quex/corr/6/source", + "int_8bit", + 0, + 4 + ], + [ + "quex/corr/7/mode", + "bool", + 0, + 1 + ], + [ + "quex/corr/7/source", + "int_8bit", + 0, + 4 + ], + [ + "quex/corr/8/mode", + "bool", + 0, + 1 + ], + [ + "quex/corr/8/source", + "int_8bit", + 0, + 4 + ], [ "quex/rot/0/imag", "float", @@ -672,389 +720,1199 @@ 2.0 ], [ - "quex/rot/0/real", + "quex/rot/0/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/rot/1/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/rot/1/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/rot/2/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/rot/2/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/rot/3/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/rot/3/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/rot/4/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/rot/4/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/rot/5/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/rot/5/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/rot/6/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/rot/6/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/rot/7/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/rot/7/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/rot/8/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/rot/8/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/thres/0/level", + "float", + -32.0, + 32.0 + ], + [ + "quex/thres/1/level", + "float", + -32.0, + 32.0 + ], + [ + "quex/thres/2/level", + "float", + -32.0, + 32.0 + ], + [ + "quex/thres/3/level", + "float", + -32.0, + 32.0 + ], + [ + "quex/thres/4/level", + "float", + -32.0, + 32.0 + ], + [ + "quex/thres/5/level", + "float", + -32.0, + 32.0 + ], + [ + "quex/thres/6/level", + "float", + -32.0, + 32.0 + ], + [ + "quex/thres/7/level", + "float", + -32.0, + 32.0 + ], + [ + "quex/thres/8/level", + "float", + -32.0, + 32.0 + ], + + + + + [ + "quex/trans/0/col/0/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/0/col/1/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/0/col/2/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/0/col/3/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/0/col/4/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/0/col/5/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/0/col/6/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/0/col/7/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/0/col/8/imag", + "float", + -2.0, + 2.0 + ], + + + + [ + "quex/trans/1/col/0/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/1/col/1/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/1/col/2/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/1/col/3/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/1/col/4/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/1/col/5/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/1/col/6/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/1/col/7/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/1/col/8/imag", + "float", + -2.0, + 2.0 + ], + + + + + [ + "quex/trans/2/col/0/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/2/col/1/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/2/col/2/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/2/col/3/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/2/col/4/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/2/col/5/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/2/col/6/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/2/col/7/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/2/col/8/imag", + "float", + -2.0, + 2.0 + ], + + + + + [ + "quex/trans/3/col/0/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/3/col/1/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/3/col/2/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/3/col/3/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/3/col/4/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/3/col/5/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/3/col/6/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/3/col/7/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/3/col/8/imag", + "float", + -2.0, + 2.0 + ], + + + + + [ + "quex/trans/4/col/0/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/4/col/1/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/4/col/2/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/4/col/3/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/4/col/4/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/4/col/5/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/4/col/6/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/4/col/7/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/4/col/8/imag", + "float", + -2.0, + 2.0 + ], + + + + + [ + "quex/trans/5/col/0/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/5/col/1/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/5/col/2/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/5/col/3/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/5/col/4/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/5/col/5/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/5/col/6/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/5/col/7/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/5/col/8/imag", + "float", + -2.0, + 2.0 + ], + + + + + [ + "quex/trans/6/col/0/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/6/col/1/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/6/col/2/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/6/col/3/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/6/col/4/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/6/col/5/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/6/col/6/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/6/col/7/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/6/col/8/imag", + "float", + -2.0, + 2.0 + ], + + + + + [ + "quex/trans/7/col/0/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/7/col/1/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/7/col/2/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/7/col/3/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/7/col/4/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/7/col/5/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/7/col/6/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/7/col/7/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/7/col/8/imag", + "float", + -2.0, + 2.0 + ], + + + + + [ + "quex/trans/8/col/0/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/8/col/1/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/8/col/2/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/8/col/3/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/8/col/4/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/8/col/5/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/8/col/6/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/8/col/7/imag", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/8/col/8/imag", "float", -2.0, 2.0 ], + + + [ - "quex/rot/1/imag", + "quex/trans/0/col/0/real", "float", -2.0, 2.0 ], - [ - "quex/rot/1/real", + [ + "quex/trans/0/col/1/real", "float", -2.0, 2.0 ], - [ - "quex/rot/2/imag", + [ + "quex/trans/0/col/2/real", "float", -2.0, 2.0 ], - [ - "quex/rot/2/real", + [ + "quex/trans/0/col/3/real", "float", -2.0, 2.0 ], - [ - "quex/rot/3/imag", + [ + "quex/trans/0/col/4/real", "float", -2.0, 2.0 ], - [ - "quex/rot/3/real", + [ + "quex/trans/0/col/5/real", "float", -2.0, 2.0 ], - [ - "quex/rot/4/imag", + [ + "quex/trans/0/col/6/real", "float", -2.0, 2.0 ], - [ - "quex/rot/4/real", + [ + "quex/trans/0/col/7/real", "float", -2.0, 2.0 ], - [ - "quex/thres/0/level", + [ + "quex/trans/0/col/8/real", "float", - -32.0, - 32.0 + -2.0, + 2.0 ], + + + [ - "quex/thres/1/level", + "quex/trans/1/col/0/real", "float", - -32.0, - 32.0 + -2.0, + 2.0 ], - [ - "quex/thres/2/level", + [ + "quex/trans/1/col/1/real", "float", - -32.0, - 32.0 + -2.0, + 2.0 ], - [ - "quex/thres/3/level", + [ + "quex/trans/1/col/2/real", "float", - -32.0, - 32.0 + -2.0, + 2.0 ], - [ - "quex/thres/4/level", + [ + "quex/trans/1/col/3/real", "float", - -32.0, - 32.0 + -2.0, + 2.0 ], - [ - "quex/trans/0/col/0/imag", + [ + "quex/trans/1/col/4/real", "float", -2.0, 2.0 ], - [ - "quex/trans/0/col/0/real", + [ + "quex/trans/1/col/5/real", "float", -2.0, 2.0 ], - [ - "quex/trans/0/col/1/imag", + [ + "quex/trans/1/col/6/real", "float", -2.0, 2.0 ], - [ - "quex/trans/0/col/1/real", + [ + "quex/trans/1/col/7/real", "float", -2.0, 2.0 ], - [ - "quex/trans/0/col/2/imag", + [ + "quex/trans/1/col/8/real", "float", -2.0, 2.0 ], + + + + [ - "quex/trans/0/col/2/real", + "quex/trans/2/col/0/real", "float", -2.0, 2.0 ], - [ - "quex/trans/0/col/3/imag", + [ + "quex/trans/2/col/1/real", "float", -2.0, 2.0 ], - [ - "quex/trans/0/col/3/real", + [ + "quex/trans/2/col/2/real", "float", -2.0, 2.0 ], - [ - "quex/trans/0/col/4/imag", + [ + "quex/trans/2/col/3/real", "float", -2.0, 2.0 ], - [ - "quex/trans/0/col/4/real", + [ + "quex/trans/2/col/4/real", "float", -2.0, 2.0 ], - [ - "quex/trans/1/col/0/imag", + [ + "quex/trans/2/col/5/real", "float", -2.0, 2.0 ], - [ - "quex/trans/1/col/0/real", + [ + "quex/trans/2/col/6/real", "float", -2.0, 2.0 ], - [ - "quex/trans/1/col/1/imag", + [ + "quex/trans/2/col/7/real", "float", -2.0, 2.0 ], - [ - "quex/trans/1/col/1/real", + [ + "quex/trans/2/col/8/real", "float", -2.0, 2.0 ], + + + [ - "quex/trans/1/col/2/imag", + "quex/trans/3/col/0/real", "float", -2.0, 2.0 ], - [ - "quex/trans/1/col/2/real", + [ + "quex/trans/3/col/1/real", "float", -2.0, 2.0 ], - [ - "quex/trans/1/col/3/imag", + [ + "quex/trans/3/col/2/real", "float", -2.0, 2.0 ], - [ - "quex/trans/1/col/3/real", + [ + "quex/trans/3/col/3/real", "float", -2.0, 2.0 ], - [ - "quex/trans/1/col/4/imag", + [ + "quex/trans/3/col/4/real", "float", -2.0, 2.0 ], - [ - "quex/trans/1/col/4/real", + [ + "quex/trans/3/col/5/real", "float", -2.0, 2.0 ], - [ - "quex/trans/2/col/0/imag", + [ + "quex/trans/3/col/6/real", "float", -2.0, 2.0 ], - [ - "quex/trans/2/col/0/real", + [ + "quex/trans/3/col/7/real", "float", -2.0, 2.0 ], - [ - "quex/trans/2/col/1/imag", + [ + "quex/trans/3/col/8/real", "float", -2.0, 2.0 ], + + + [ - "quex/trans/2/col/1/real", + "quex/trans/4/col/0/real", "float", -2.0, 2.0 ], - [ - "quex/trans/2/col/2/imag", + [ + "quex/trans/4/col/1/real", "float", -2.0, 2.0 ], - [ - "quex/trans/2/col/2/real", + [ + "quex/trans/4/col/2/real", "float", -2.0, 2.0 ], - [ - "quex/trans/2/col/3/imag", + [ + "quex/trans/4/col/3/real", "float", -2.0, 2.0 ], - [ - "quex/trans/2/col/3/real", + [ + "quex/trans/4/col/4/real", "float", -2.0, 2.0 ], - [ - "quex/trans/2/col/4/imag", + [ + "quex/trans/4/col/5/real", "float", -2.0, 2.0 ], - [ - "quex/trans/2/col/4/real", + [ + "quex/trans/4/col/6/real", "float", -2.0, 2.0 ], - [ - "quex/trans/3/col/0/imag", + [ + "quex/trans/4/col/7/real", "float", -2.0, 2.0 ], - [ - "quex/trans/3/col/0/real", + [ + "quex/trans/4/col/8/real", "float", -2.0, 2.0 ], + + + [ - "quex/trans/3/col/1/imag", + "quex/trans/5/col/0/real", "float", -2.0, 2.0 ], - [ - "quex/trans/3/col/1/real", + [ + "quex/trans/5/col/1/real", "float", -2.0, 2.0 ], - [ - "quex/trans/3/col/2/imag", + [ + "quex/trans/5/col/2/real", "float", -2.0, 2.0 ], - [ - "quex/trans/3/col/2/real", + [ + "quex/trans/5/col/3/real", "float", -2.0, 2.0 ], - [ - "quex/trans/3/col/3/imag", + [ + "quex/trans/5/col/4/real", "float", -2.0, 2.0 ], - [ - "quex/trans/3/col/3/real", + [ + "quex/trans/5/col/5/real", "float", -2.0, 2.0 ], - [ - "quex/trans/3/col/4/imag", + [ + "quex/trans/5/col/6/real", "float", -2.0, 2.0 ], - [ - "quex/trans/3/col/4/real", + [ + "quex/trans/5/col/7/real", "float", -2.0, 2.0 ], - [ - "quex/trans/4/col/0/imag", + [ + "quex/trans/5/col/8/real", "float", -2.0, 2.0 ], + + + [ - "quex/trans/4/col/0/real", + "quex/trans/6/col/0/real", "float", -2.0, 2.0 ], - [ - "quex/trans/4/col/1/imag", + [ + "quex/trans/6/col/1/real", "float", -2.0, 2.0 ], - [ - "quex/trans/4/col/1/real", + [ + "quex/trans/6/col/2/real", "float", -2.0, 2.0 ], - [ - "quex/trans/4/col/2/imag", + [ + "quex/trans/6/col/3/real", "float", -2.0, 2.0 ], - [ - "quex/trans/4/col/2/real", + [ + "quex/trans/6/col/4/real", "float", -2.0, 2.0 ], - [ - "quex/trans/4/col/3/imag", + [ + "quex/trans/6/col/5/real", "float", -2.0, 2.0 ], - [ - "quex/trans/4/col/3/real", + [ + "quex/trans/6/col/6/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/6/col/7/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/6/col/8/real", "float", -2.0, 2.0 ], + + + [ - "quex/trans/4/col/4/imag", + "quex/trans/7/col/0/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/7/col/1/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/7/col/2/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/7/col/3/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/7/col/4/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/7/col/5/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/7/col/6/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/7/col/7/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/7/col/8/real", "float", -2.0, 2.0 ], + + + [ - "quex/trans/4/col/4/real", + "quex/trans/8/col/0/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/8/col/1/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/8/col/2/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/8/col/3/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/8/col/4/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/8/col/5/real", "float", -2.0, 2.0 ], + [ + "quex/trans/8/col/6/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/8/col/7/real", + "float", + -2.0, + 2.0 + ], + [ + "quex/trans/8/col/8/real", + "float", + -2.0, + 2.0 + ], + + + [ "quex/wint/delay", "int", @@ -1103,6 +1961,30 @@ 0, 1 ], + [ + "quex/wint/source/5", + "bool", + 0, + 1 + ], + [ + "quex/wint/source/6", + "bool", + 0, + 1 + ], + [ + "quex/wint/source/7", + "bool", + 0, + 1 + ], + [ + "quex/wint/source/8", + "bool", + 0, + 1 + ], [ "dios/0/decimation", "int_64", diff --git a/pycqed/instrument_drivers/physical_instruments/_CCL/ccl_param_nodes.json b/pycqed/instrument_drivers/physical_instruments/_CCL/ccl_param_nodes.json index de3b00e6ec..9ecb246859 100644 --- a/pycqed/instrument_drivers/physical_instruments/_CCL/ccl_param_nodes.json +++ b/pycqed/instrument_drivers/physical_instruments/_CCL/ccl_param_nodes.json @@ -44,7 +44,6 @@ "label": "Number Append Points", "name": "num_append_pts", "set_cmd": "QUTech:NumAppendPts {}", - "unit": "2.5 ns per point", "vals": { "range": [ 0, @@ -54,9 +53,9 @@ } }, { - "docstring": "This parameter determines the extra output delay introduced for the DIO1 channel. It controls UHFQC1 to perform measurements on qubits 0, 2, 3, 5, and 6. The unit is 20ns.", + "docstring": "This parameter determines the extra output delay introduced for the DIO1 channel. The unit is 20ns.", "get_cmd": "QUTech:DioDelayONE?", - "label": "Output Delay of DIO1, measuring qubit 0, 2, 3, 5 6", + "label": "Output Delay of DIO1", "name": "dio1_out_delay", "set_cmd": "QUTech:DioDelayONE {}", "unit": "20 ns", @@ -69,9 +68,9 @@ } }, { - "docstring": "This parameter determines the extra output delay introduced for the DIO1 channel. It controls UHFQC1 to perform measurements on qubits 1 and 4. The unit is 20ns.", + "docstring": "This parameter determines the extra output delay introduced for the DIO2 channel. The unit is 20ns.", "get_cmd": "QUTech:DioDelayTWO?", - "label": "Output Delay of DIO2, measuring qubit 1, 4", + "label": "Output Delay of DIO2", "name": "dio2_out_delay", "set_cmd": "QUTech:DioDelayTWO {}", "unit": "20 ns", @@ -84,9 +83,9 @@ } }, { - "docstring": "This parameter determines the extra output delay introduced for the DIO3 channel. It controls AWG8 to perform flux control on all 7 qubits. The unit is 20ns.", + "docstring": "This parameter determines the extra output delay introduced for the DIO3 channel. The unit is 20ns.", "get_cmd": "QUTech:DioDelayTHRee?", - "label": "Output Delay of DIO3, flux control all 7 qubits", + "label": "Output Delay of DIO3", "name": "dio3_out_delay", "set_cmd": "QUTech:DioDelayTHRee {}", "unit": "20 ns", @@ -99,9 +98,9 @@ } }, { - "docstring": "This parameter determines the extra output delay introduced for the DIO4 channel. It contains two microwave channels, which control qubits (0, 1) and (2, 3, 4), respectively. The unit is 20ns.", + "docstring": "This parameter determines the extra output delay introduced for the DIO4 channel. The unit is 20ns.", "get_cmd": "QUTech:DioDelayFOUr?", - "label": "Output Delay of DIO4, microwave 1 (qubit 0, 1) and microwave 2 (qubit 2, 3, 4)", + "label": "Output Delay of DIO4", "name": "dio4_out_delay", "set_cmd": "QUTech:DioDelayFOUr {}", "unit": "20 ns", @@ -134,7 +133,6 @@ "label": "VSM Channel 0 delay", "name": "vsm_channel_delay0", "set_cmd": "QUTech:VSMChannelDelay0 {}", - "unit": "2.5 ns", "vals": { "range": [ 0, @@ -149,7 +147,6 @@ "label": "VSM Channel 1 delay", "name": "vsm_channel_delay1", "set_cmd": "QUTech:VSMChannelDelay1 {}", - "unit": "2.5 ns", "vals": { "range": [ 0, @@ -164,7 +161,6 @@ "label": "VSM Channel 2 delay", "name": "vsm_channel_delay2", "set_cmd": "QUTech:VSMChannelDelay2 {}", - "unit": "2.5 ns", "vals": { "range": [ 0, @@ -179,7 +175,6 @@ "label": "VSM Channel 3 delay", "name": "vsm_channel_delay3", "set_cmd": "QUTech:VSMChannelDelay3 {}", - "unit": "2.5 ns", "vals": { "range": [ 0, @@ -194,7 +189,6 @@ "label": "VSM Channel 4 delay", "name": "vsm_channel_delay4", "set_cmd": "QUTech:VSMChannelDelay4 {}", - "unit": "2.5 ns", "vals": { "range": [ 0, @@ -209,7 +203,6 @@ "label": "VSM Channel 5 delay", "name": "vsm_channel_delay5", "set_cmd": "QUTech:VSMChannelDelay5 {}", - "unit": "2.5 ns", "vals": { "range": [ 0, @@ -224,7 +217,6 @@ "label": "VSM Channel 6 delay", "name": "vsm_channel_delay6", "set_cmd": "QUTech:VSMChannelDelay6 {}", - "unit": "2.5 ns", "vals": { "range": [ 0, @@ -239,7 +231,6 @@ "label": "VSM Channel 7 delay", "name": "vsm_channel_delay7", "set_cmd": "QUTech:VSMChannelDelay7 {}", - "unit": "2.5 ns", "vals": { "range": [ 0, @@ -254,7 +245,6 @@ "label": "VSM Channel 8 delay", "name": "vsm_channel_delay8", "set_cmd": "QUTech:VSMChannelDelay8 {}", - "unit": "2.5 ns", "vals": { "range": [ 0, @@ -269,7 +259,6 @@ "label": "VSM Channel 9 delay", "name": "vsm_channel_delay9", "set_cmd": "QUTech:VSMChannelDelay9 {}", - "unit": "2.5 ns", "vals": { "range": [ 0, @@ -284,7 +273,6 @@ "label": "VSM Channel 10 delay", "name": "vsm_channel_delay10", "set_cmd": "QUTech:VSMChannelDelay10 {}", - "unit": "2.5 ns", "vals": { "range": [ 0, @@ -299,7 +287,6 @@ "label": "VSM Channel 11 delay", "name": "vsm_channel_delay11", "set_cmd": "QUTech:VSMChannelDelay11 {}", - "unit": "2.5 ns", "vals": { "range": [ 0, @@ -314,7 +301,6 @@ "label": "VSM Channel 12 delay", "name": "vsm_channel_delay12", "set_cmd": "QUTech:VSMChannelDelay12 {}", - "unit": "2.5 ns", "vals": { "range": [ 0, @@ -329,7 +315,6 @@ "label": "VSM Channel 13 delay", "name": "vsm_channel_delay13", "set_cmd": "QUTech:VSMChannelDelay13 {}", - "unit": "2.5 ns", "vals": { "range": [ 0, @@ -344,7 +329,6 @@ "label": "VSM Channel 14 delay", "name": "vsm_channel_delay14", "set_cmd": "QUTech:VSMChannelDelay14 {}", - "unit": "2.5 ns", "vals": { "range": [ 0, @@ -359,7 +343,6 @@ "label": "VSM Channel 15 delay", "name": "vsm_channel_delay15", "set_cmd": "QUTech:VSMChannelDelay15 {}", - "unit": "2.5 ns", "vals": { "range": [ 0, @@ -370,14 +353,14 @@ } ], "version": { - "Embedded Software Build Time": "19/03/2018-12:05:58", - "Embedded Software Version": "0.2.2", - "Firmware Build Time": "23/01/2018-16:25:20", + "Embedded Software Build Time": "18/12/2017-09:12:28", + "Embedded Software Version": "0.2.0", + "Firmware Build Time": "18/12/2017-15:54:16", "Kernel Module Build Time": "18/12/2017-00:56:35", "Kernel Module Version": "0.2.0", - "firmware": "0.5.2", + "firmware": "99.5.1", "model": "CCL1", - "serial": "CCLight2", + "serial": "00000001", "vendor": "QuTech" } } \ No newline at end of file diff --git a/pycqed/measurement/detector_functions.py b/pycqed/measurement/detector_functions.py index 21e683395e..75664b57c8 100644 --- a/pycqed/measurement/detector_functions.py +++ b/pycqed/measurement/detector_functions.py @@ -1136,6 +1136,37 @@ def finish(self, **kw): self.SH.abort() +class Signal_Hound_sweeped_frequency(Hard_Detector): + + def __init__(self, signal_hound, Navg=1, delay=0.1, + **kw): + super().__init__() + self.name = 'SignalHound_fixed_frequency' + self.value_names = ['Power'] + self.value_units = ['dBm'] + self.delay = delay + self.SH = signal_hound + self.Navg = Navg + + def acquire_data_point(self, **kw): + frequency=self.swp.pop() + self.SH.set('frequency', frequency) + self.SH.prepare_for_measurement() + time.sleep(self.delay) + return self.SH.get_power_at_freq(Navg=self.Navg) + + def get_values(self): + return([self.acquire_data_point()]) + + + def prepare(self, sweep_points): + self.swp=list(sweep_points) + #self.SH.prepare_for_measurement() + + def finish(self, **kw): + self.SH.abort() + + class SH_mixer_skewness_det(Soft_Detector): ''' @@ -1983,10 +2014,11 @@ def prepare(self, sweep_points): # The averaging-count is used to specify how many times the AWG program # should run self.UHFQC.awgs_0_single(1) - self.UHFQC.awgs_0_userregs_0(self.nr_shots) - self.UHFQC.awgs_0_userregs_1(0) # 0 for rl, 1 for iavg (input avg) - # The AWG program uses userregs/0 to define the number of iterations + self.UHFQC.awgs_0_userregs_0(self.nr_shots) # The AWG program uses + # userregs/0 to define the number of iterations # in the loop + self.UHFQC.awgs_0_userregs_1(0) # 0 for rl, 1 for iavg (input avg) + self.UHFQC.quex_rl_length(self.nr_shots) self.UHFQC.quex_rl_avgcnt(0) # log2(1) for single shot readout diff --git a/pycqed/measurement/openql_experiments/clifford_rb_oql.py b/pycqed/measurement/openql_experiments/clifford_rb_oql.py index 6672936c12..a99fb56574 100644 --- a/pycqed/measurement/openql_experiments/clifford_rb_oql.py +++ b/pycqed/measurement/openql_experiments/clifford_rb_oql.py @@ -17,7 +17,7 @@ add_two_q_cal_points from pycqed.measurement.randomized_benchmarking import randomized_benchmarking as rb -from pycqed.measurement.openql_experiments import openql_experiments as oqh +from pycqed.measurement.openql_experiments import openql_helpers as oqh from pycqed.measurement.randomized_benchmarking.two_qubit_clifford_group \ import SingleQubitClifford, TwoQubitClifford base_qasm_path = join(dirname(__file__), 'qasm_files') @@ -181,9 +181,12 @@ def randomized_benchmarking(qubits: list, platf_cfg: str, if cal_points: if number_of_qubits == 1: - p = add_single_qubit_cal_points(p, platf=platf, qubit_idx=qubits[0]) + p = add_single_qubit_cal_points(p, platf=platf, + qubit_idx=qubits[0]) elif number_of_qubits == 2: - p = add_two_q_cal_points(p, platf=platf, q0=qubits[0], q1=qubits[1]) + p = add_two_q_cal_points(p, platf=platf, + q0=qubits[0], + q1=qubits[1]) with suppress_stdout(): p.compile(verbose=False) diff --git a/pycqed/measurement/openql_experiments/multi_qubit_oql.py b/pycqed/measurement/openql_experiments/multi_qubit_oql.py index bef0ed26eb..8b651ab69d 100644 --- a/pycqed/measurement/openql_experiments/multi_qubit_oql.py +++ b/pycqed/measurement/openql_experiments/multi_qubit_oql.py @@ -4,6 +4,8 @@ import openql.openql as ql from pycqed.utilities.general import suppress_stdout from openql.openql import Program, Kernel, Platform +from pycqed.measurement.openql_experiments import single_qubit_oql as sqo + base_qasm_path = join(dirname(__file__), 'qasm_files') output_dir = join(dirname(__file__), 'output') @@ -132,6 +134,50 @@ def multi_qubit_off_on(qubits: list, initialize: bool, return p +def Ramsey_msmt_induced_dephasing(qubits: list, angles: list, platf_cfg: str): + """ + Ramsey sequence that varies azimuthal phase instead of time. Works for a single + qubit or multiple qubits. The coherence of the LSQ is measured, while the whole list + of qubits is measured. + Writes output files to the directory specified in openql. + Output directory is set as an attribute to the program for convenience. + + note: executes the measurement between gates to measure the measurement induced dephasing + + Input pars: + qubits: list specifying the targeted qubit MSQ, and the qubit of which the coherence + is measured LSQ. + angles: the list of angles for each Ramsey element + platf_cfg: filename of the platform config file + Returns: + p: OpenQL Program object containing + + """ + platf = Platform('OpenQL_Platform', platf_cfg) + p = Program(pname="Ramsey_msmt_induced_dephasing", nqubits=platf.get_qubit_number(), + p=platf) + + for i, angle in enumerate(angles[:-4]): + cw_idx = angle//20 + 9 + k = Kernel("Ramsey_azi_"+str(angle), p=platf) + for qubit in qubits: + k.prepz(qubit) + k.gate('rx90', qubits[-1]) + for qubit in qubits: + k.measure(qubit) + k.gate('cw_{:02}'.format(cw_idx), qubits[-1]) + p.add_kernel(k) + + # adding the calibration points + sqo.add_single_qubit_cal_points(p, platf=platf, qubit_idx=qubits[-1]) + + with suppress_stdout(): + p.compile(verbose=False) + # attribute get's added to program to help finding the output files + p.output_dir = ql.get_output_dir() + p.filename = join(p.output_dir, p.name + '.qisa') + return p + def two_qubit_off_on(q0: int, q1: int, platf_cfg: str): ''' @@ -154,7 +200,7 @@ def two_qubit_off_on(q0: int, q1: int, platf_cfg: str): return p -def two_qubit_tomo_cardinal(cardinal: int, q0: int, q1: int, platf_cfg: str): +def two_qubit_tomo_cardinal(q0: int, q1: int, cardinal: int, platf_cfg: str): ''' Cardinal tomography for two qubits. Args: @@ -195,7 +241,7 @@ def two_qubit_tomo_cardinal(cardinal: int, q0: int, q1: int, platf_cfg: str): # every calibration point is repeated 7 times. This is copied from the # script for Tektronix driven qubits. I do not know if this repetition # is important or even necessary here. - p = add_two_q_cal_points(p, platf=platf, q0=0, q1=1, reps_per_cal_pt=7) + p = add_two_q_cal_points(p, platf=platf, q0=q1, q1=q0, reps_per_cal_pt=7) with suppress_stdout(): p.compile() # attribute is added to program to help finding the output files @@ -505,7 +551,7 @@ def Chevron_hack(qubit_idx: int, qubit_idx_spec, def Chevron(qubit_idx: int, qubit_idx_spec: int, - buffer_time, buffer_time2, platf_cfg: str): + buffer_time, buffer_time2, flux_cw: int, platf_cfg: str): """ Writes output files to the directory specified in openql. Output directory is set as an attribute to the program for convenience. @@ -527,13 +573,15 @@ def Chevron(qubit_idx: int, qubit_idx_spec: int, buffer_nanoseconds = int(round(buffer_time/1e-9)) buffer_nanoseconds2 = int(round(buffer_time2/1e-9)) + if flux_cw is None: + flux_cw = 2 k = Kernel("Chevron", p=platf) k.prepz(qubit_idx) k.gate('rx90', qubit_idx_spec) k.gate('rx180', qubit_idx) k.gate("wait", [qubit_idx], buffer_nanoseconds) - k.gate('fl_cw_02', 2, 0) + k.gate('fl_cw_{:02}'.format(flux_cw), 2, 0) k.gate('wait', [qubit_idx], buffer_nanoseconds2) k.gate('rx180', qubit_idx) k.measure(qubit_idx) @@ -1254,3 +1302,159 @@ def add_two_q_cal_points(p, platf, q0: int, q1: int, p.add_kernel(k) return p + + +def Chevron_first_manifold(qubit_idx: int, qubit_idx_spec: int, + buffer_time, buffer_time2, flux_cw: int, platf_cfg: str): + """ + Writes output files to the directory specified in openql. + Output directory is set as an attribute to the program for convenience. + + Input pars: + qubit_idx: int specifying the target qubit (starting at 0) + qubit_idx_spec: int specifying the spectator qubit + buffer_time : + buffer_time2 : + + platf_cfg: filename of the platform config file + Returns: + p: OpenQL Program object containing + + """ + platf = Platform('OpenQL_Platform', platf_cfg) + p = Program(pname="Chevron", nqubits=platf.get_qubit_number(), + p=platf) + + buffer_nanoseconds = int(round(buffer_time/1e-9)) + buffer_nanoseconds2 = int(round(buffer_time2/1e-9)) + if flux_cw is None: + flux_cw = 2 + + k = Kernel("Chevron", p=platf) + k.prepz(qubit_idx) + k.gate('rx180', qubit_idx) + k.gate("wait", [qubit_idx], buffer_nanoseconds) + k.gate('fl_cw_{:02}'.format(flux_cw), 2, 0) + k.gate('wait', [qubit_idx], buffer_nanoseconds2) + k.measure(qubit_idx) + k.measure(qubit_idx_spec) + k.gate("wait", [qubit_idx, qubit_idx_spec], 0) + p.add_kernel(k) + + with suppress_stdout(): + p.compile() + # attribute get's added to program to help finding the output files + p.output_dir = ql.get_output_dir() + p.filename = join(p.output_dir, p.name + '.qisa') + return p + + +def partial_tomography_cardinal(q0: int, q1: int, cardinal: int, platf_cfg: str, + precompiled_flux: bool=True, + cal_points: bool=True, second_CZ_delay: int=260, + CZ_duration: int=260, + add_echo_pulses: bool=False): + """ + Tomography sequence for Grover's algorithm. + + cardinal: int denoting cardinal state prepared. + """ + + if not precompiled_flux: + raise NotImplementedError('Currently only precompiled flux pulses ' + 'are supported.') + + platf = Platform('OpenQL_Platform', platf_cfg) + p = Program(pname="partial_tomography_cardinal_seq", + nqubits=platf.get_qubit_number(), p=platf) + + cardinal_gates = ['i', 'rx180', 'ry90', 'rym90', 'rx90', 'rxm90'] + + if (cardinal>35 or cardinal<0): + raise ValueError('cardinal must be in [0, 35]') + + idx_p0 = cardinal % 6 + idx_p1 = ((cardinal - idx_p0)//6) % 6 + #cardinal_gates[] + #k.gate(string_of_the_gate, integer_from_qubit) + tomo_gates = [('i','i'),('i','rx180'),('rx180','i'),('rx180','rx180'), + ('ry90','ry90'),('rym90','rym90'),('rx90','rx90'),('rxm90','rxm90')] + + for gates in tomo_gates: + #strings denoting the gates + SP0 = cardinal_gates[idx_p0] + SP1 = cardinal_gates[idx_p1] + t_q0 = gates[1] + t_q1 = gates[0] + k = Kernel('PT_{}_tomo_{}_{}'.format(cardinal, idx_p0, idx_p1), + p=platf) + + k.prepz(q0) + k.prepz(q1) + + # Cardinal state preparation + k.gate(SP0, q0) + k.gate(SP1, q1) + # tomo pulses + #to be taken from list of tuples + k.gate(t_q1, q0) + k.gate(t_q0, q1) + + k.measure(q0) + k.measure(q1) + k.gate('wait', [2, 0], 0) + p.add_kernel(k) + + p = add_two_q_cal_points(p, platf=platf, q0=q0, q1=q1, reps_per_cal_pt=2) + with suppress_stdout(): + p.compile() + + p.output_dir = ql.get_output_dir() + p.filename = join(p.output_dir, p.name + '.qisa') + return p + + +def two_qubit_VQE(q0: int, q1: int, platf_cfg: str): + ''' + VQE tomography for two qubits. + Args: + cardinal (int) : index of prep gate + q0, q1 (int) : target qubits for the sequence + ''' + tomo_pulses = ['i', 'rx180', 'ry90', 'rym90', 'rx90', 'rxm90'] + tomo_list_q0 = tomo_pulses + tomo_list_q1 = tomo_pulses + + platf = Platform('OpenQL_Platform', platf_cfg) + p = Program(pname="VQE_full_tomo", + nqubits=platf.get_qubit_number(), p=platf) + + # Tomography pulses + i = 0 + for p_q1 in tomo_list_q1: + for p_q0 in tomo_list_q0: + i += 1 + kernel_name = '{}_{}_{}'.format(i, p_q0, p_q1) + k = Kernel(kernel_name, p=platf) + k.prepz(q0) + k.prepz(q1) + k.gate('ry180', q0) #Y180 gate without compilation + k.gate('i', q0) #Y180 gate without compilation + k.gate("wait", [q1], 40) + k.gate('fl_cw_02', 2, 0) + k.gate("wait", [q1], 40) + k.gate(p_q0, q0) #compiled z gate+pre_rotation + k.gate(p_q1, q1) #pre_rotation + k.measure(q0) + k.measure(q1) + p.add_kernel(k) + # every calibration point is repeated 7 times. This is copied from the + # script for Tektronix driven qubits. I do not know if this repetition + # is important or even necessary here. + p = add_two_q_cal_points(p, platf=platf, q0=q1, q1=q0, reps_per_cal_pt=7) + with suppress_stdout(): + p.compile() + # attribute is added to program to help finding the output files + p.output_dir = ql.get_output_dir() + p.filename = join(p.output_dir, p.name + '.qisa') + return p \ No newline at end of file diff --git a/pycqed/measurement/openql_experiments/output/cs.txt b/pycqed/measurement/openql_experiments/output/cs.txt index ba39bcdbf8..bff9cc8c3a 100644 --- a/pycqed/measurement/openql_experiments/output/cs.txt +++ b/pycqed/measurement/openql_experiments/output/cs.txt @@ -1,5 +1,14 @@ Condition OpTypeLeft CW_Left OpTypeRight CW_Right 0: 0 0 0 0 0 + 48: 2 1 0 0 0 + 55: 2 1 7 0 0 + 49: 2 1 1 0 0 + 51: 2 1 3 0 0 + 53: 2 1 5 0 0 + 50: 2 1 2 0 0 + 52: 2 1 4 0 0 + 54: 2 1 6 0 0 + 56: 2 1 8 0 0 40: 1 1 0 0 0 47: 1 1 7 0 0 41: 1 1 1 0 0 @@ -8,7 +17,6 @@ 42: 1 1 2 0 0 44: 1 1 4 0 0 46: 1 1 6 0 0 - 48: 1 1 8 0 0 8: 0 1 0 0 0 9: 0 1 1 0 0 10: 0 1 2 0 0 @@ -50,4 +58,4 @@ 134: 0 2 6 2 6 135: 0 2 7 2 7 4: 0 3 0 0 0 - 2: 0 1 0 0 0 + 2: 0 0 0 0 0 diff --git a/pycqed/measurement/openql_experiments/output/qisa_opcodes.qmap b/pycqed/measurement/openql_experiments/output/qisa_opcodes.qmap index b44499b531..4b565fa4d9 100644 --- a/pycqed/measurement/openql_experiments/output/qisa_opcodes.qmap +++ b/pycqed/measurement/openql_experiments/output/qisa_opcodes.qmap @@ -22,15 +22,23 @@ def_opcode["qwaitr"] = 0x38 # quantum instructions (double instruction format) # no arguments def_q_arg_none["qnop"] = 0x00 -def_q_arg_st["C_cw_00"] = 0x28 -def_q_arg_st["C_cw_07"] = 0x2f -def_q_arg_st["C_cw_01"] = 0x29 -def_q_arg_st["C_cw_03"] = 0x2b -def_q_arg_st["C_cw_05"] = 0x2d -def_q_arg_st["C_cw_02"] = 0x2a -def_q_arg_st["C_cw_04"] = 0x2c -def_q_arg_st["C_cw_06"] = 0x2e -def_q_arg_st["C_cw_08"] = 0x30 +def_q_arg_st["C0_cw_00"] = 0x30 +def_q_arg_st["C0_cw_07"] = 0x37 +def_q_arg_st["C0_cw_01"] = 0x31 +def_q_arg_st["C0_cw_03"] = 0x33 +def_q_arg_st["C0_cw_05"] = 0x35 +def_q_arg_st["C0_cw_02"] = 0x32 +def_q_arg_st["C0_cw_04"] = 0x34 +def_q_arg_st["C0_cw_06"] = 0x36 +def_q_arg_st["C0_cw_08"] = 0x38 +def_q_arg_st["C1_cw_00"] = 0x28 +def_q_arg_st["C1_cw_07"] = 0x2f +def_q_arg_st["C1_cw_01"] = 0x29 +def_q_arg_st["C1_cw_03"] = 0x2b +def_q_arg_st["C1_cw_05"] = 0x2d +def_q_arg_st["C1_cw_02"] = 0x2a +def_q_arg_st["C1_cw_04"] = 0x2c +def_q_arg_st["C1_cw_06"] = 0x2e def_q_arg_st["cw_00"] = 0x8 def_q_arg_st["cw_01"] = 0x9 def_q_arg_st["cw_02"] = 0xa diff --git a/pycqed/measurement/sweep_functions.py b/pycqed/measurement/sweep_functions.py index 3d4141aff2..5cc2b7e5b5 100644 --- a/pycqed/measurement/sweep_functions.py +++ b/pycqed/measurement/sweep_functions.py @@ -710,11 +710,11 @@ def __init__(self, LutMan, LutMan_parameter, **kw): self.LutMan_parameter = LutMan_parameter def set_parameter(self, val): - self.LutMan.QWG.get_instr().stop() + self.LutMan.AWG.get_instr().stop() self.LutMan_parameter.set(val) - self.LutMan.load_pulses_onto_AWG_lookuptable(regenerate_pulses=True) - self.LutMan.QWG.get_instr().start() - self.LutMan.QWG.get_instr().getOperationComplete() + self.LutMan.load_waveforms_onto_AWG_lookuptable(regenerate_waveforms=True) + self.LutMan.AWG.get_instr().start() + self.LutMan.AWG.get_instr().getOperationComplete() class QWG_flux_amp(Soft_Sweep): @@ -907,6 +907,49 @@ def set_parameter(self, val): self.LutMan.AWG.get_instr().acquisition_arm(single=self.single) +class lutman_par_depletion_pulse_global_scaling(Soft_Sweep): + def __init__(self, LutMan, resonator_numbers, optimization_M_amps, + optimization_M_amp_down0s, optimization_M_amp_down1s, + upload=True, **kw): + # sweeps the readout-and depletion pules of the listed resonators. + # sets the remaining readout and depletion pulses to 0 amplitude. + + self.set_kw() + self.name= 'depletion_pulse_sweeper' + self.parameter_name = 'relative_depletion_pulse_scaling_amp' + self.unit = 'a.u.' + self.sweep_control = 'soft' + self.LutMan = LutMan + self.optimization_M_amps = optimization_M_amps + self.optimization_M_amp_down0s = optimization_M_amp_down0s + self.optimization_M_amp_down1s = optimization_M_amp_down1s + self.resonator_numbers = resonator_numbers + self.upload=upload + + def set_parameter(self, val): + ''' + Set the parameter(s) to be swept. Differs per sweep function + Sweeping the amplitudes of the readout-and-depletion-pulses in the list + relative to the initially optimized amplitude. + Sets the remaining depletion pulses to zero. + ''' + for resonator_number in self.LutMan._resonator_codeword_bit_mapping: + if resonator_number in self.resonator_numbers: + i = self.resonator_numbers.index(resonator_number) + self.LutMan.set('M_amp_R{}'.format(resonator_number), + val*self.optimization_M_amps[i]) + self.LutMan.set('M_down_amp0_R{}'.format(resonator_number), + val*self.optimization_M_amp_down0s[i]) + self.LutMan.set('M_down_amp1_R{}'.format(resonator_number), + val*self.optimization_M_amp_down1s[i]) + else: + self.LutMan.set('M_amp_R{}'.format(resonator_number), 0) + self.LutMan.set('M_down_amp0_R{}'.format(resonator_number), 0) + self.LutMan.set('M_down_amp1_R{}'.format(resonator_number), 0) + if self.upload: + self.LutMan.load_DIO_triggered_sequence_onto_UHFQC(regenerate_waveforms=True) + + class lutman_par_dB_attenuation_UHFQC_dig_trig(Soft_Sweep): def __init__(self, LutMan, LutMan_parameter, run=False, **kw): self.set_kw() @@ -945,6 +988,7 @@ def set_parameter(self, val): self.LutMan.load_DIO_triggered_sequence_onto_UHFQC() if self.run: self.LutMan.AWG.get_instr().acquisition_arm(single=self.single) + class UHFQC_pulse_dB_attenuation(Soft_Sweep): def __init__(self, UHFQC, IF, dig_trigger=True,**kw): @@ -1046,6 +1090,12 @@ def prepare(self): playWave("dev8005_wave_ch1_cw004", "dev8005_wave_ch2_cw004"); } """ + awg_hack_program_custom_wf = """ + while (1) { + waitDIOTrigger(); + playWave("dev8005_wave_ch1_cw004", "dev8005_wave_ch2_cw004"); + } + """ awg = self.lm.AWG.get_instr() self.lm.load_waveform_onto_AWG_lookuptable( self.waveform_name, regenerate_waveforms=True) @@ -1053,6 +1103,9 @@ def prepare(self): awg.configure_awg_from_string(0, awg_hack_program_multi_cz) elif 'z' in self.waveform_name: awg.configure_awg_from_string(0, awg_hack_program_cz) + elif 'custom' in self.waveform_name: + awg.configure_awg_from_string(0, awg_hack_program_custom_wf) + else: awg.configure_awg_from_string(0, awg_hack_program) @@ -1092,3 +1145,35 @@ def set_parameter(self, val): awg.configure_awg_from_string(0, awg_hack_program) awg.configure_codeword_protocol() awg.start() + + +class FLsweep_QWG(Soft_Sweep): + """ + Special sweep function for QWG flux pulses. + """ + def __init__(self, lm, par, waveform_name, realtime_loading=True, + other_waveform=None, **kw): + super().__init__(**kw) + self.lm = lm + self.par = par + self.waveform_name = waveform_name + self.parameter_name = par.name + self.unit = par.unit + self.name = par.name + self.realtime_loading = realtime_loading + self.other_waveform = other_waveform + + def prepare(self): + awg = self.lm.AWG.get_instr() + awg.stop() + self.lm.load_waveform_onto_AWG_lookuptable( + self.waveform_name, regenerate_waveforms=True) + awg.start() + + def set_parameter(self, val): + self.par(val) + awg = self.lm.AWG.get_instr() + awg.stop() + self.lm.load_waveform_onto_AWG_lookuptable( + self.waveform_name, regenerate_waveforms=True) + awg.start() diff --git a/pycqed/measurement/waveform_control_CC/amsterdam_waveforms.py b/pycqed/measurement/waveform_control_CC/amsterdam_waveforms.py new file mode 100644 index 0000000000..2cd645fd31 --- /dev/null +++ b/pycqed/measurement/waveform_control_CC/amsterdam_waveforms.py @@ -0,0 +1,79 @@ +""" +This module contains the functions to make the basic waveforms to construct +a Delft/Amsterdam houses pattern. + +This is used in the quantum efficiency paper and as a showcase for the +cryoscope. +""" + +import numpy as np + +# Amsterdam houses functions +def ams_sc(unitlength, ams_sc_base, ams_sc_step): + """ + staircase shaped house + """ + ams_sc = ams_sc_base * np.ones(13*unitlength) +\ + np.concatenate([ + 0*np.ones(unitlength), ams_sc_step*np.ones(unitlength), + 2*ams_sc_step*np.ones(unitlength), 3 * + ams_sc_step*np.ones(unitlength), + 4*ams_sc_step*np.ones(unitlength), 5 * + ams_sc_step*np.ones(unitlength), + 6*ams_sc_step*np.ones(unitlength), 5 * + ams_sc_step*np.ones(unitlength), + 4*ams_sc_step*np.ones(unitlength), 3 * + ams_sc_step*np.ones(unitlength), + 2*ams_sc_step*np.ones(unitlength), ams_sc_step*np.ones(unitlength), + 0.0*np.ones(unitlength)]) + return ams_sc + +def ams_clock(unitlength, ams_clock_base, ams_clock_delta): + ams_clock = ams_clock_base*np.ones(8*unitlength) +\ + np.concatenate([ + np.linspace(0, ams_clock_delta, + unitlength), ams_clock_delta*np.ones(6*unitlength), + np.linspace(ams_clock_delta, 0, unitlength)]) + return ams_clock + + +def ams_bottle(unitlength, ams_bottle_base, ams_bottle_delta): + ams_bottle = ams_bottle_base * np.ones(8*unitlength) +\ + np.concatenate([ + np.linspace(0, ams_bottle_delta, 3*unitlength)**4 / + ams_bottle_delta**3, + ams_bottle_delta*np.ones(2*unitlength), + np.linspace(ams_bottle_delta, 0, 3*unitlength)**4/ams_bottle_delta**3]) + return ams_bottle + + +def ams_bottle2(unitlength, ams_bottle_base, ams_bottle_delta): + """ + Quite steep bottle (based on second order polynomial) + """ + ams_bottle = ams_bottle_base * np.ones(7*unitlength) + np.concatenate([ + np.linspace(0, ams_bottle_delta, 3*unitlength)**2/ams_bottle_delta**1, + ams_bottle_delta*np.ones(1*unitlength), + np.linspace(ams_bottle_delta, 0, 3*unitlength)**2/ams_bottle_delta**1]) + return ams_bottle + + +def ams_bottle3(unitlength, ams_bottle_base, ams_bottle_delta): + """ + Normal triangular rooftop + """ + ams_bottle = ams_bottle_base * np.ones(13*unitlength) + np.concatenate([ + np.linspace(0, ams_bottle_delta, 6.5*unitlength), + np.linspace(ams_bottle_delta, 0, 6.5*unitlength)]) + return ams_bottle + + +def ams_midup(unitlength, ams_midup_base, ams_midup_delta): + ams_midup = ams_midup_base * np.ones(9*unitlength) + np.concatenate([ + 0*np.ones(3*unitlength), + ams_midup_delta * np.ones(3*unitlength)+-0.03 * + np.linspace(-unitlength, unitlength, 3*unitlength)**2/unitlength**2, + 0*np.ones(3*unitlength)]) + return ams_midup + + diff --git a/pycqed/measurement/waveform_control_CC/waveform.py b/pycqed/measurement/waveform_control_CC/waveform.py index 0933579355..8ed33f6451 100644 --- a/pycqed/measurement/waveform_control_CC/waveform.py +++ b/pycqed/measurement/waveform_control_CC/waveform.py @@ -389,17 +389,17 @@ def martinis_flux_pulse(length: float, lambda_2: float, lambda_3: float, # Return in the specified units if return_unit == 'theta': # Theta is returned in radians here - return interp_wave + return np.nan_to_num(interp_wave) # Convert to detuning from f_interaction delta_f_wave = 2 * J2 / np.tan(interp_wave) if return_unit == 'eps': - return delta_f_wave + return np.nan_to_num(delta_f_wave) # Convert to parametrization of f_01 f_01_wave = delta_f_wave + f_interaction if return_unit == 'f01': - return f_01_wave + return np.nan_to_num(f_01_wave) # Convert to voltage voltage_wave = Qubit_freq_to_dac( diff --git a/pycqed/tests/analysis_v2/test_coherence_analysis.py b/pycqed/tests/analysis_v2/test_coherence_analysis.py new file mode 100644 index 0000000000..404b559cb9 --- /dev/null +++ b/pycqed/tests/analysis_v2/test_coherence_analysis.py @@ -0,0 +1,65 @@ +''' +Hacked together by Rene Vollmer +''' + +import unittest +import numpy as np +import pycqed as pq +import os +from pycqed.analysis_v2 import measurement_analysis as ma + +tau_keys = { + ma.CoherenceTimesAnalysis.T1: 'Analysis.Fitted Params F|1>.tau.value', + ma.CoherenceTimesAnalysis.T2: 'Analysis.Fitted Params corr_data.tau.value', + ma.CoherenceTimesAnalysis.T2_star: 'Analysis.Fitted Params raw w0.tau.value', +} +tau_std_keys = { + ma.CoherenceTimesAnalysis.T1: 'Analysis.Fitted Params F|1>.tau.stderr', + ma.CoherenceTimesAnalysis.T2: 'Analysis.Fitted Params corr_data.tau.stderr', + ma.CoherenceTimesAnalysis.T2_star: 'Analysis.Fitted Params raw w0.tau.stderr', +} +labels = { + ma.CoherenceTimesAnalysis.T1: '_T1-VFC_res1_dac_channel_VFCQ6_', + ma.CoherenceTimesAnalysis.T2: '_echo-VFC_res1_dac_channel_VFCQ6_', + ma.CoherenceTimesAnalysis.T2_star: '_Ramsey-VFC_res1_dac_channel_VFCQ6_', +} + +dac = 'VFCQ6' +qubit = 'Q2' +t_start = '20180412_190000' +t_stop = '20180412_210000' + + +class Test_Cryoscope_analysis(unittest.TestCase): + + @classmethod + def setUpClass(self): + self.datadir = os.path.join(pq.__path__[0], 'tests', 'test_data') + ma.a_tools.datadir = self.datadir + + def test_CoherenceTimesAnalysisSingle(self): + key = ma.CoherenceTimesAnalysis.T2_star + + a = ma.CoherenceTimesAnalysisSingle(t_start=t_start, t_stop=t_stop, label=labels[key], + auto=True, extract_only=False, + tau_key=tau_keys[key], tau_std_key=tau_std_keys[key], + plot_versus_dac=True, dac_key='Instrument settings.fluxcurrent.' + dac, + plot_versus_frequency=True, + frequency_key='Instrument settings.' + qubit + '.freq_qubit') + + #np.testing.assert_('dac_arc_fitfct' in a.fit_res.keys()) + #np.testing.assert_('flux_values' in a.fit_res.keys()) + #np.testing.assert_('Ec' in a.fit_res.keys()) + #np.testing.assert_('Ej' in a.fit_res.keys()) + #np.testing.assert_('sensitivity_values' in a.fit_res.keys()) + + def test_CoherenceTimesAnalysis(self): + b = ma.CoherenceTimesAnalysis(dac_instr_names=[dac], qubit_instr_names=[qubit], + t_start=t_start, t_stop=t_stop, labels=labels, + tau_keys=tau_keys, tau_std_keys=tau_std_keys, + plot_versus_dac=True, + dac_key_pattern='Instrument settings.fluxcurrent.{DAC}', + plot_versus_frequency=True, + frequency_key_pattern='Instrument settings.{Q}.freq_qubit', + auto=True, extract_only=False, close_figs=False, options_dict={'verbose': False}) + diff --git a/pycqed/tests/analysis_v2/test_cryoscope_analysis.py b/pycqed/tests/analysis_v2/test_cryoscope_analysis.py index 55ccbe2ef7..403cb75c45 100644 --- a/pycqed/tests/analysis_v2/test_cryoscope_analysis.py +++ b/pycqed/tests/analysis_v2/test_cryoscope_analysis.py @@ -12,19 +12,44 @@ def setUpClass(self): self.datadir = os.path.join(pq.__path__[0], 'tests', 'test_data') ma.a_tools.datadir = self.datadir + def test_Cryoscope_Analysis(self): + a = ma.Cryoscope_Analysis( + t_start='20180423_114715', + polycoeffs_freq_conv='Snapshot/instruments/FL_LutMan_QR/parameters/polycoeffs_freq_conv/value', + derivative_window_length=2e-9) + + expected_figs = {'raw_data', 'demod_data', 'norm_data_circ', + 'demod_phase', 'frequency_detuning', + 'cryoscope_amplitude', 'short_time_fft'} + self.assertTrue(expected_figs.issubset(set(a.figs.keys()))) + self.assertTrue(expected_figs.issubset(set(a.axs.keys()))) + # Does not actually check for the content + def test_RamZFluxArc(self): - a = ma.RamZFluxArc(t_start='20180205_105633', t_stop='20180205_120210') + a = ma.RamZFluxArc(t_start='20180205_105633', t_stop='20180205_120210', + ch_idx_cos=2, ch_idx_sin=3) + poly_coeffs = a.proc_data_dict['poly_coeffs'] # test dac arc conversion # For this to work all other parts have to work - amps = a.freq_to_amp([.5e9, .6e9, .8e9]) - exp_amps = np.array([0.5357841, 0.58333725, 0.66727005]) - np.testing.assert_array_almost_equal(amps, exp_amps, decimal=2) + amps = np.linspace(.1, 1, 21) + freqs = a.amp_to_freq(amps) + + rec_amps = a.freq_to_amp(freqs, kind='interpolate') + np.testing.assert_array_almost_equal(amps, rec_amps, decimal=2) + rec_amps = a.freq_to_amp(freqs, kind='root') + np.testing.assert_array_almost_equal(amps, rec_amps, decimal=2) + rec_amps = a.freq_to_amp(freqs, kind='root_parabola') + np.testing.assert_array_almost_equal(amps, rec_amps, decimal=2) + + np.testing.assert_array_almost_equal(amps, rec_amps, decimal=2) - freqs = a.amp_to_freq([.3, .4, .5]) - exp_freqs = np.array( - [1.46405902e+08, 2.67461142e+08, 4.31098670e+08]) - np.testing.assert_array_almost_equal(freqs, exp_freqs, decimal=-7) + poly_coeffs = a.proc_data_dict['poly_coeffs'] + exp_poly_coeffs = np.array( + [1.36263320e+09, -2.23862128e+08, 3.87339064e+07]) + print(poly_coeffs) + np.testing.assert_array_almost_equal(poly_coeffs, exp_poly_coeffs, + decimal=-7) def test_sliding_pulses_analysis(self): @@ -43,7 +68,8 @@ def test_sliding_pulses_analysis(self): # a reference curve is needed to convert to amps da = ma.RamZFluxArc(t_start='20180205_105633', - t_stop='20180205_120210') + t_stop='20180205_120210', + ch_idx_cos=2, ch_idx_sin=3) a = ma.SlidingPulses_Analysis( t_start='20180221_195729', freq_to_amp=da.freq_to_amp, amp_to_freq=da.amp_to_freq) diff --git a/pycqed/tests/analysis_v2/test_dac_scan_analysis.py b/pycqed/tests/analysis_v2/test_dac_scan_analysis.py new file mode 100644 index 0000000000..c57d8cea2d --- /dev/null +++ b/pycqed/tests/analysis_v2/test_dac_scan_analysis.py @@ -0,0 +1,50 @@ +''' +Hacked together by Rene Vollmer +''' + +import unittest +import numpy as np +import pycqed as pq +import os +from pycqed.analysis_v2 import measurement_analysis as ma + +dac = 'VFCQ6' +qubit = 'Q2' +t_start = '20180414_121500' +t_stop = '20180414_141000' + + +class Test_DAC_scan_analysis(unittest.TestCase): + + @classmethod + def setUpClass(self): + self.datadir = os.path.join(pq.__path__[0], 'tests', 'test_data') + ma.a_tools.datadir = self.datadir + + def test_FluxFrequency_Qubit(self): + dic = { + 'fitparams_key': 'Fitted Params distance.f0.value', + 's21_normalize_per_dac': True, + 's21_normalize_global': True, 's21_percentile': 70, + 'verbose': True, + 'dac_key': 'Instrument settings.fluxcurrent.' + dac, + } + d = ma.FluxFrequency(t_start=t_start, t_stop=t_stop, label='_spectroscopy', + options_dict=dic, is_spectroscopy=True, temp_keys={'T_mc': 'Fridge monitor.T_MC'}, + auto=True, do_fitting=True, close_figs=False) + + # todo: test fit results, loaded and processed data + + def test_FluxFrequency_Resonator(self): + dic = { + 'fitparams_key': 'Fitted Params HM.f0.value', + 'fitparams_corr_fact': 1e9, + 'qubit_freq': 6.95e9, + 'verbose': True, + 'dac_key': 'Instrument settings.fluxcurrent.' + dac, + } + d = ma.FluxFrequency(t_start=t_start, t_stop=t_stop, label='_Resonator', + options_dict=dic, is_spectroscopy=False, extract_fitparams=True, + auto=True, do_fitting=True, close_figs=False) + + # todo: test fit results, loaded and processed data diff --git a/pycqed/tests/analysis_v2/test_readout_analysis.py b/pycqed/tests/analysis_v2/test_readout_analysis.py index d015b40ce7..e5b9ccd463 100644 --- a/pycqed/tests/analysis_v2/test_readout_analysis.py +++ b/pycqed/tests/analysis_v2/test_readout_analysis.py @@ -5,6 +5,60 @@ from pycqed.analysis_v2 import measurement_analysis as ma from pycqed.analysis_v2 import readout_analysis as ra +# Add test: 20180508\182642 - 183214 +class Test_SSRO_auto_angle(unittest.TestCase): + + @classmethod + def setUpClass(self): + self.datadir = os.path.join(pq.__path__[0], 'tests', 'test_data') + ma.a_tools.datadir = self.datadir + + def test_angles(self): + tp = 2*np.pi + ro_amp_high_factor = 0.1 + ts = '20180508_182642' + te = '20180508_183214' + for angle in np.arange(0, 360, 30): + options_dict = { + 'verbose': True, + 'rotation_angle': angle*np.pi/180, + 'auto_rotation_angle': True, + 'fixed_p01': 0, + 'fixed_p10': 0, + 'nr_bins': 100, + } + label = 'SSRO_%d_%.2f' % (angle,ro_amp_high_factor*100) + aut = ma.Singleshot_Readout_Analysis(t_start=ts, t_stop=te, + label=label, + extract_only=True, + do_fitting=True, + options_dict=options_dict) + aut_angle = aut.proc_data_dict['raw_offset'][2] + aut_angle = aut_angle % tp + aut_snr = aut.fit_res['shots_all'].params['SNR'].value + + options_dict['auto_rotation_angle'] = False + opt = ma.Singleshot_Readout_Analysis(t_start=ts, t_stop=te, + label=label, + extract_only=True, + do_fitting=True, + options_dict=options_dict) + opt_angle = opt.proc_data_dict['raw_offset'][2] + opt_angle = opt_angle % tp + opt_snr = opt.fit_res['shots_all'].params['SNR'].value + da = min(abs(aut_angle-opt_angle), + abs(aut_angle-opt_angle+2*np.pi), + abs(aut_angle-opt_angle-2*np.pi)) + + # Check if the angle was found within a few degrees + self.assertLess(da*180/np.pi, 9) + + # Check if the SNRs roughly make sense + self.assertLess(aut_snr, 1.1) + self.assertLess(opt_snr, 1.1) + self.assertGreater(aut_snr, 0.55) + self.assertGreater(opt_snr, 0.55) + class Test_SSRO_discrimination_analysis(unittest.TestCase): @@ -41,16 +95,13 @@ def test_SSRO_analysis_basic_1D_wrong_peak_selected(self): t_stop = t_start a = ma.Singleshot_Readout_Analysis(t_start=t_start, t_stop=t_stop, extract_only=True) - np.testing.assert_almost_equal(a.proc_data_dict['threshold_raw'], - -3.30, decimal=2) + self.assertBetween(a.proc_data_dict['threshold_raw'], -3.3, -3.2) np.testing.assert_almost_equal(a.proc_data_dict['F_assignment_raw'], - 0.944, decimal=3) - np.testing.assert_almost_equal(a.proc_data_dict['threshold_fit'], - -3.25, decimal=2) + 0.944, decimal=2) + self.assertBetween(a.proc_data_dict['threshold_fit'], -3.3, -3.2) np.testing.assert_almost_equal(a.proc_data_dict['F_assignment_fit'], 0.944, decimal=2) - np.testing.assert_almost_equal(a.proc_data_dict['threshold_discr'], - -3.2, decimal=1) + self.assertBetween(a.proc_data_dict['threshold_discr'], -3.3, -3.2) np.testing.assert_almost_equal(a.proc_data_dict['F_discr'], 0.99, decimal=2) @@ -61,17 +112,16 @@ def test_SSRO_analysis_basic_1D_misfit(self): t_stop = t_start a = ma.Singleshot_Readout_Analysis(t_start=t_start, t_stop=t_stop, extract_only=True) - np.testing.assert_almost_equal(a.proc_data_dict['threshold_raw'], - -.95, decimal=2) + self.assertBetween(a.proc_data_dict['threshold_raw'], -1, -0.7) np.testing.assert_almost_equal(a.proc_data_dict['F_assignment_raw'], - 0.949, decimal=3) - self.assertBetween(a.proc_data_dict['threshold_fit'], -1, -.9) + 0.949, decimal=2) + self.assertBetween(a.proc_data_dict['threshold_fit'], -1, -.7) np.testing.assert_almost_equal(a.proc_data_dict['F_assignment_fit'], 0.945, decimal=2) self.assertBetween(a.proc_data_dict['threshold_discr'], -1, -.7) np.testing.assert_almost_equal(a.proc_data_dict['F_discr'], 1.000, decimal=2) - self.assertLess(a.proc_data_dict['residual_excitation'], 0.02) + self.assertLess(a.proc_data_dict['residual_excitation'], 0.09) np.testing.assert_almost_equal( a.proc_data_dict['measurement_induced_relaxation'], 0.1, decimal=1) diff --git a/pycqed/tests/dev_qubit_objs/test_qubit_objects.py b/pycqed/tests/dev_qubit_objs/test_qubit_objects.py index ec245efe15..d1ee08adbf 100644 --- a/pycqed/tests/dev_qubit_objs/test_qubit_objects.py +++ b/pycqed/tests/dev_qubit_objs/test_qubit_objects.py @@ -73,7 +73,7 @@ def setUpClass(self): self.AWG8_VSM_MW_LutMan.mw_modulation(100e6) self.AWG8_VSM_MW_LutMan.sampling_rate(2.4e9) - self.ro_lutman = UHFQC_RO_LutMan('RO_lutman', num_res=5) + self.ro_lutman = UHFQC_RO_LutMan('RO_lutman', num_res=5, feedline_number=0) self.ro_lutman.AWG(self.UHFQC.name) # Assign instruments @@ -224,7 +224,6 @@ def test_prep_ro_MW_sources(self): @unittest.skipIf(Dummy_VSM_not_fixed, 'Dummy_VSM_not_fixed') def test_prep_ro_pulses(self): - self.CCL_qubit.ro_pulse_res_nr(3) self.CCL_qubit.ro_pulse_mixer_alpha(1.1) self.CCL_qubit.ro_pulse_mixer_phi(4) self.CCL_qubit.ro_pulse_length(312e-9) @@ -238,9 +237,9 @@ def test_prep_ro_pulses(self): self.assertEqual(self.ro_lutman.mixer_phi(), 4) self.assertEqual(self.ro_lutman.mixer_alpha(), 1.1) - self.assertEqual(self.ro_lutman.M_length_R3(), 312e-9) - self.assertEqual(self.ro_lutman.M_down_length0_R3(), 23e-9) - self.assertEqual(self.ro_lutman.M_down_amp0_R3(), .1) + self.assertEqual(self.ro_lutman.M_length_R0(), 312e-9) + self.assertEqual(self.ro_lutman.M_down_length0_R0(), 23e-9) + self.assertEqual(self.ro_lutman.M_down_amp0_R0(), .1) self.assertEqual(self.UHFQC.sigouts_0_offset(), .01) self.assertEqual(self.UHFQC.sigouts_1_offset(), .02) diff --git a/pycqed/tests/test_LutMans.py b/pycqed/tests/test_LutMans.py index 108f6904e3..6ffb933afd 100644 --- a/pycqed/tests/test_LutMans.py +++ b/pycqed/tests/test_LutMans.py @@ -8,6 +8,7 @@ from pycqed.instrument_drivers.meta_instrument.LutMans.base_lutman import \ get_redundant_codewords + class Test_MW_LutMan(unittest.TestCase): @classmethod @@ -207,10 +208,10 @@ def test_amp_to_dac_val_conversions(self): self.fluxlutman.cfg_awg_channel(1) def test_plot_flux_arc(self): - self.fluxlutman.plot_flux_arc(show=False) + self.fluxlutman.plot_flux_arc(show=False, plot_cz_trajectory=True) - def test_generate_standard_flux_waveforms(self): - self.fluxlutman.generate_standard_waveforms() + def test_plot_cz_trajectory(self): + self.fluxlutman.plot_cz_trajectory(show=False) def test_standard_cz_waveform(self): self.fluxlutman.czd_double_sided(False) @@ -299,7 +300,6 @@ def test_freq_amp_conversions(self): recovered_amp = self.fluxlutman.detuning_to_amp(-5e9) self.assertAlmostEqual(recovered_amp, 0.082696256708720065) - # Test negative branch of parabola test_amps = np.linspace(-0.1, -.5, 11) freqs = self.fluxlutman.amp_to_detuning(test_amps) @@ -307,7 +307,33 @@ def test_freq_amp_conversions(self): freqs, positive_branch=False) np.testing.assert_array_almost_equal(test_amps, recovered_amps) + def test_custom_wf(self): + self.fluxlutman.generate_standard_waveforms() + np.testing.assert_array_almost_equal( + self.fluxlutman._wave_dict['custom_wf'], + np.array([])) + # Tests if the custom wf is part of the default lutmap + self.fluxlutman.load_waveforms_onto_AWG_lookuptable() + self.assertIn('custom_wf', self.fluxlutman._wave_dict_dist) + + x = np.arange(200) + y = np.cos(x)/20 + self.fluxlutman.custom_wf(y) + self.fluxlutman.generate_standard_waveforms() + np.testing.assert_array_almost_equal( + self.fluxlutman._wave_dict['custom_wf'], y) + + self.fluxlutman.custom_wf_length(30e-9) + self.fluxlutman.generate_standard_waveforms() + y_cut = np.cos(x)/20 + cut_sample = 72 # 30ns * 2.4GSps + y_cut[cut_sample:] = 0 + np.testing.assert_array_almost_equal( + self.fluxlutman._wave_dict['custom_wf'], y_cut) + # base waveform is not changed + np.testing.assert_array_almost_equal( + self.fluxlutman.custom_wf(), y) def test_generate_standard_flux_waveforms(self): self.fluxlutman.generate_standard_waveforms() @@ -318,7 +344,6 @@ def test_upload_and_distort(self): def test_generate_composite(self): self.fluxlutman.generate_standard_waveforms() - empty_flux_tuples = [] gen_wf = self.fluxlutman._gen_composite_wf('cz_z', time_tuples=[]) exp_wf = np.zeros(12000) # 5us *2.4GSps np.testing.assert_array_almost_equal(gen_wf, exp_wf) @@ -377,22 +402,23 @@ def tearDownClass(self): except KeyError: pass + class Test_LutMan_Utils(unittest.TestCase): def test_get_redundant_codewords(self): target_cw = 5 red_cws_A = get_redundant_codewords(target_cw, 4, 0) for cw in red_cws_A: print(bin(cw)) - self.assertEqual(cw&15, target_cw) + self.assertEqual(cw & 15, target_cw) self.assertEqual(len(red_cws_A), 2**4) - red_cws_B = get_redundant_codewords(target_cw, 4, 4) for cw in red_cws_B: print(bin(cw)) - self.assertEqual((cw&(256-16))>>4, target_cw) + self.assertEqual((cw & (256-16)) >> 4, target_cw) self.assertEqual(len(red_cws_B), 2**4) + def dict_contained_in(subset, superset): if subset.items() <= superset.items(): return True diff --git a/pycqed/tests/test_amsterdam_waveforms.py b/pycqed/tests/test_amsterdam_waveforms.py new file mode 100644 index 0000000000..fed9196026 --- /dev/null +++ b/pycqed/tests/test_amsterdam_waveforms.py @@ -0,0 +1,216 @@ +import numpy as np +import unittest +import warnings +from pycqed.measurement.waveform_control_CC import amsterdam_waveforms as awf + + +class Test_Amsterdam_Waveforms(unittest.TestCase): + + def test_amsterdam_waveform(self): + unitlength = 10 + rescaling = 0.7 + roofScale = 0.5 + + ams_sc_base = 0.47 * rescaling + ams_sc_step = 0.07 * rescaling * roofScale + ams_sc = awf.ams_sc( + unitlength, ams_sc_base, ams_sc_step) + + ams_bottle_base = 0.55 * rescaling + ams_bottle_delta = 0.3 * rescaling * roofScale + ams_bottle = awf.ams_bottle(unitlength, ams_bottle_base, + ams_bottle_delta) + + ams_midup_base = 0.63 * rescaling + ams_midup_delta = 0.25 * rescaling * roofScale + ams_midup = awf.ams_midup(unitlength, ams_midup_base, + ams_midup_delta) + + ams_bottle_base3 = 0.5 * rescaling + ams_bottle_delta3 = 0.1 * rescaling * roofScale + ams_bottle3 = awf.ams_bottle3(unitlength, + ams_bottle_base3, ams_bottle_delta3) + + ams_bottle_base2 = 0.58 * rescaling + ams_bottle_delta2 = 0.3 * rescaling * roofScale + ams_bottle2 = awf.ams_bottle2(unitlength, + ams_bottle_base2, ams_bottle_delta2) + + amsterdam_wf = np.concatenate([ + np.zeros(10), + ams_sc, + ams_bottle, + ams_midup, + ams_bottle3, + ams_bottle2, + np.zeros(10)]) + + expected_wf = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.329, 0.329, + 0.329, + 0.329, 0.329, 0.329, 0.329, 0.329, 0.329, 0.329, + 0.3535, + 0.3535, 0.3535, 0.3535, 0.3535, 0.3535, 0.3535, + 0.3535, + 0.3535, 0.3535, 0.378, 0.378, 0.378, 0.378, 0.378, + 0.378, + 0.378, 0.378, 0.378, 0.378, 0.4025, 0.4025, 0.4025, + 0.4025, + 0.4025, 0.4025, 0.4025, 0.4025, 0.4025, 0.4025, + 0.427, + 0.427, 0.427, 0.427, 0.427, 0.427, 0.427, 0.427, + 0.427, + 0.427, 0.4515, 0.4515, 0.4515, 0.4515, 0.4515, + 0.4515, + 0.4515, 0.4515, 0.4515, 0.4515, 0.476, 0.476, 0.476, + 0.476, + 0.476, 0.476, 0.476, 0.476, 0.476, 0.476, 0.4515, + 0.4515, + 0.4515, 0.4515, 0.4515, 0.4515, 0.4515, 0.4515, + 0.4515, + 0.4515, 0.427, 0.427, 0.427, 0.427, 0.427, 0.427, + 0.427, + 0.427, 0.427, 0.427, 0.4025, 0.4025, 0.4025, 0.4025, + 0.4025, + 0.4025, 0.4025, 0.4025, 0.4025, 0.4025, 0.378, + 0.378, + 0.378, 0.378, 0.378, 0.378, 0.378, 0.378, 0.378, + 0.378, + 0.3535, 0.3535, 0.3535, 0.3535, 0.3535, 0.3535, + 0.3535, + 0.3535, 0.3535, 0.3535, 0.329, 0.329, 0.329, 0.329, + 0.329, + 0.329, 0.329, 0.329, 0.329, 0.329, 0.385, + 0.38500015, + 0.38500238, 0.38501202, 0.385038, 0.38509278, + 0.3851924, + 0.38535644, 0.38560808, 0.38597402, 0.38648456, + 0.38717354, + 0.38807838, 0.38924005, 0.39070308, 0.39251558, + 0.3947292, + 0.39739918, 0.4005843, 0.40434691, 0.40875294, + 0.41387184, + 0.41977667, 0.42654403, 0.43425409, 0.44299057, + 0.45284076, + 0.46389552, 0.47624928, 0.49, 0.49, 0.49, 0.49, 0.49, + 0.49, + 0.49, 0.49, 0.49, 0.49, 0.49, 0.49, 0.49, 0.49, 0.49, + 0.49, + 0.49, 0.49, 0.49, 0.49, 0.49, 0.49, 0.47624928, + 0.46389552, + 0.45284076, 0.44299057, 0.43425409, 0.42654403, + 0.41977667, + 0.41387184, 0.40875294, 0.40434691, 0.4005843, + 0.39739918, + 0.3947292, 0.39251558, 0.39070308, 0.38924005, + 0.38807838, + 0.38717354, 0.38648456, 0.38597402, 0.38560808, + 0.38535644, + 0.3851924, 0.38509278, 0.385038, 0.38501202, + 0.38500238, + 0.38500015, 0.385, 0.441, 0.441, 0.441, 0.441, 0.441, + 0.441, + 0.441, 0.441, 0.441, 0.441, 0.441, 0.441, 0.441, + 0.441, + 0.441, 0.441, 0.441, 0.441, 0.441, 0.441, 0.441, + 0.441, + 0.441, 0.441, 0.441, 0.441, 0.441, 0.441, 0.441, + 0.441, + 0.4985, 0.50249524, 0.50620511, 0.50962961, + 0.51276873, + 0.51562247, 0.51819084, 0.52047384, 0.52247146, + 0.52418371, + 0.52561058, 0.52675208, 0.5276082, 0.52817895, + 0.52846433, + 0.52846433, 0.52817895, 0.5276082, 0.52675208, + 0.52561058, + 0.52418371, 0.52247146, 0.52047384, 0.51819084, + 0.51562247, + 0.51276873, 0.50962961, 0.50620511, 0.50249524, + 0.4985, + 0.441, 0.441, 0.441, 0.441, 0.441, 0.441, 0.441, + 0.441, + 0.441, 0.441, 0.441, 0.441, 0.441, 0.441, 0.441, + 0.441, + 0.441, 0.441, 0.441, 0.441, 0.441, 0.441, 0.441, + 0.441, + 0.441, 0.441, 0.441, 0.441, 0.441, 0.441, 0.35, + 0.35054687, + 0.35109375, 0.35164062, 0.3521875, 0.35273437, + 0.35328125, + 0.35382812, 0.354375, 0.35492187, 0.35546875, + 0.35601563, + 0.3565625, 0.35710937, 0.35765625, 0.35820312, + 0.35875, + 0.35929687, 0.35984375, 0.36039062, 0.3609375, + 0.36148437, + 0.36203125, 0.36257812, 0.363125, 0.36367187, + 0.36421875, + 0.36476562, 0.3653125, 0.36585937, 0.36640625, + 0.36695312, + 0.3675, 0.36804687, 0.36859375, 0.36914062, + 0.3696875, + 0.37023438, 0.37078125, 0.37132812, 0.371875, + 0.37242187, + 0.37296875, 0.37351562, 0.3740625, 0.37460937, + 0.37515625, + 0.37570312, 0.37625, 0.37679687, 0.37734375, + 0.37789062, + 0.3784375, 0.37898437, 0.37953125, 0.38007812, + 0.380625, + 0.38117187, 0.38171875, 0.38226562, 0.3828125, + 0.38335937, + 0.38390625, 0.38445312, 0.385, 0.385, + 0.38445312, + 0.38390625, 0.38335937, 0.3828125, 0.38226562, + 0.38171875, + 0.38117187, 0.380625, 0.38007812, 0.37953125, + 0.37898437, + 0.3784375, 0.37789062, 0.37734375, 0.37679687, + 0.37625, + 0.37570312, 0.37515625, 0.37460937, 0.3740625, + 0.37351562, + 0.37296875, 0.37242187, 0.371875, 0.37132812, + 0.37078125, + 0.37023438, 0.3696875, 0.36914062, 0.36859375, + 0.36804687, + 0.3675, 0.36695312, 0.36640625, 0.36585937, + 0.3653125, + 0.36476562, 0.36421875, 0.36367187, 0.363125, + 0.36257812, + 0.36203125, 0.36148437, 0.3609375, 0.36039062, + 0.35984375, + 0.35929687, 0.35875, 0.35820312, 0.35765625, + 0.35710937, + 0.3565625, 0.35601563, 0.35546875, 0.35492187, + 0.354375, + 0.35382812, 0.35328125, 0.35273437, 0.3521875, + 0.35164062, + 0.35109375, 0.35054687, 0.35, 0.406, 0.40612485, + 0.40649941, + 0.40712366, 0.40799762, 0.40912128, 0.41049465, + 0.41211772, + 0.41399049, 0.41611296, 0.41848514, 0.42110702, + 0.4239786, + 0.42709988, 0.43047087, 0.43409156, 0.43796195, + 0.44208205, + 0.44645184, 0.45107134, 0.45594055, 0.46105945, + 0.46642806, + 0.47204637, 0.47791439, 0.4840321, 0.49039952, + 0.49701665, + 0.50388347, 0.511, 0.511, 0.511, 0.511, 0.511, 0.511, + 0.511, + 0.511, 0.511, 0.511, 0.511, 0.511, 0.50388347, + 0.49701665, + 0.49039952, 0.4840321, 0.47791439, 0.47204637, + 0.46642806, + 0.46105945, 0.45594055, 0.45107134, 0.44645184, + 0.44208205, + 0.43796195, 0.43409156, 0.43047087, 0.42709988, + 0.4239786, + 0.42110702, 0.41848514, 0.41611296, 0.41399049, + 0.41211772, + 0.41049465, 0.40912128, 0.40799762, 0.40712366, + 0.40649941, 0.40612485, 0.406, 0., 0., 0., 0., + 0., 0., 0., 0., 0., 0.] + + np.testing.assert_array_almost_equal(amsterdam_wf, expected_wf) diff --git a/pycqed/tests/test_data/20161214/120000_dummy_Butterfly/120000_dummy_Butterfly.hdf5 b/pycqed/tests/test_data/20161214/120000_dummy_Butterfly/120000_dummy_Butterfly.hdf5 index 66c0f10970..beeab35028 100644 Binary files a/pycqed/tests/test_data/20161214/120000_dummy_Butterfly/120000_dummy_Butterfly.hdf5 and b/pycqed/tests/test_data/20161214/120000_dummy_Butterfly/120000_dummy_Butterfly.hdf5 differ diff --git a/pycqed/tests/test_data/20170120/001151_Dummy_Tomo_31_QL_QR_/001151_Dummy_Tomo_31_QL_QR_.hdf5 b/pycqed/tests/test_data/20170120/001151_Dummy_Tomo_31_QL_QR_/001151_Dummy_Tomo_31_QL_QR_.hdf5 index a279e999c8..e655e0ec5a 100755 Binary files a/pycqed/tests/test_data/20170120/001151_Dummy_Tomo_31_QL_QR_/001151_Dummy_Tomo_31_QL_QR_.hdf5 and b/pycqed/tests/test_data/20170120/001151_Dummy_Tomo_31_QL_QR_/001151_Dummy_Tomo_31_QL_QR_.hdf5 differ diff --git a/pycqed/tests/test_data/20170201/122018_Ramsey_AncT/122018_Ramsey_AncT.hdf5 b/pycqed/tests/test_data/20170201/122018_Ramsey_AncT/122018_Ramsey_AncT.hdf5 index 898d7bec99..10280457c6 100644 Binary files a/pycqed/tests/test_data/20170201/122018_Ramsey_AncT/122018_Ramsey_AncT.hdf5 and b/pycqed/tests/test_data/20170201/122018_Ramsey_AncT/122018_Ramsey_AncT.hdf5 differ diff --git a/pycqed/tests/test_data/20170227/115026_resonator_scan_qubit/115026_resonator_scan_qubit.hdf5 b/pycqed/tests/test_data/20170227/115026_resonator_scan_qubit/115026_resonator_scan_qubit.hdf5 index 101d0b38bf..9b904cab35 100644 Binary files a/pycqed/tests/test_data/20170227/115026_resonator_scan_qubit/115026_resonator_scan_qubit.hdf5 and b/pycqed/tests/test_data/20170227/115026_resonator_scan_qubit/115026_resonator_scan_qubit.hdf5 differ diff --git a/pycqed/tests/test_data/20170227/115118_acquisition_delay_scan_qubit/115118_acquisition_delay_scan_qubit.hdf5 b/pycqed/tests/test_data/20170227/115118_acquisition_delay_scan_qubit/115118_acquisition_delay_scan_qubit.hdf5 index 689ba7bdc3..e47404c538 100644 Binary files a/pycqed/tests/test_data/20170227/115118_acquisition_delay_scan_qubit/115118_acquisition_delay_scan_qubit.hdf5 and b/pycqed/tests/test_data/20170227/115118_acquisition_delay_scan_qubit/115118_acquisition_delay_scan_qubit.hdf5 differ diff --git a/pycqed/tests/test_data/20170412/183928_Rabi-n1_q9/183928_Rabi-n1_q9.hdf5 b/pycqed/tests/test_data/20170412/183928_Rabi-n1_q9/183928_Rabi-n1_q9.hdf5 index 7fd5fbe646..79943d6277 100644 Binary files a/pycqed/tests/test_data/20170412/183928_Rabi-n1_q9/183928_Rabi-n1_q9.hdf5 and b/pycqed/tests/test_data/20170412/183928_Rabi-n1_q9/183928_Rabi-n1_q9.hdf5 differ diff --git a/pycqed/tests/test_data/20170412/185618_Rabi-n1_q9/185618_Rabi-n1_q9.hdf5 b/pycqed/tests/test_data/20170412/185618_Rabi-n1_q9/185618_Rabi-n1_q9.hdf5 index 18b96c7f87..ced751d941 100644 Binary files a/pycqed/tests/test_data/20170412/185618_Rabi-n1_q9/185618_Rabi-n1_q9.hdf5 and b/pycqed/tests/test_data/20170412/185618_Rabi-n1_q9/185618_Rabi-n1_q9.hdf5 differ diff --git a/pycqed/tests/test_data/20170413/134244_Rabi-n1_q9/134244_Rabi-n1_q9.hdf5 b/pycqed/tests/test_data/20170413/134244_Rabi-n1_q9/134244_Rabi-n1_q9.hdf5 index de9754e7ad..11b986eddb 100644 Binary files a/pycqed/tests/test_data/20170413/134244_Rabi-n1_q9/134244_Rabi-n1_q9.hdf5 and b/pycqed/tests/test_data/20170413/134244_Rabi-n1_q9/134244_Rabi-n1_q9.hdf5 differ diff --git a/pycqed/tests/test_data/20170606/162250_SSRO_QL_QR/162250_SSRO_QL_QR.hdf5 b/pycqed/tests/test_data/20170606/162250_SSRO_QL_QR/162250_SSRO_QL_QR.hdf5 index 0ca4f82a2a..f69fc32a7d 100644 Binary files a/pycqed/tests/test_data/20170606/162250_SSRO_QL_QR/162250_SSRO_QL_QR.hdf5 and b/pycqed/tests/test_data/20170606/162250_SSRO_QL_QR/162250_SSRO_QL_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170607/145645_Ramsey_10pulse_sep_QR/145645_Ramsey_10pulse_sep_QR.hdf5 b/pycqed/tests/test_data/20170607/145645_Ramsey_10pulse_sep_QR/145645_Ramsey_10pulse_sep_QR.hdf5 index 8cd7c42a94..6aa617efa4 100644 Binary files a/pycqed/tests/test_data/20170607/145645_Ramsey_10pulse_sep_QR/145645_Ramsey_10pulse_sep_QR.hdf5 and b/pycqed/tests/test_data/20170607/145645_Ramsey_10pulse_sep_QR/145645_Ramsey_10pulse_sep_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170607/152324_T1_QL/152324_T1_QL.hdf5 b/pycqed/tests/test_data/20170607/152324_T1_QL/152324_T1_QL.hdf5 index eef899eb6b..1f1f872f43 100644 Binary files a/pycqed/tests/test_data/20170607/152324_T1_QL/152324_T1_QL.hdf5 and b/pycqed/tests/test_data/20170607/152324_T1_QL/152324_T1_QL.hdf5 differ diff --git a/pycqed/tests/test_data/20170607/160504_Rabi-n1_QR/160504_Rabi-n1_QR.hdf5 b/pycqed/tests/test_data/20170607/160504_Rabi-n1_QR/160504_Rabi-n1_QR.hdf5 index 9e381aeea3..fe38b7c9b2 100644 Binary files a/pycqed/tests/test_data/20170607/160504_Rabi-n1_QR/160504_Rabi-n1_QR.hdf5 and b/pycqed/tests/test_data/20170607/160504_Rabi-n1_QR/160504_Rabi-n1_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170607/161234_Motzoi_XY_QR/161234_Motzoi_XY_QR.hdf5 b/pycqed/tests/test_data/20170607/161234_Motzoi_XY_QR/161234_Motzoi_XY_QR.hdf5 index 3edd6009da..69d613b307 100644 Binary files a/pycqed/tests/test_data/20170607/161234_Motzoi_XY_QR/161234_Motzoi_XY_QR.hdf5 and b/pycqed/tests/test_data/20170607/161234_Motzoi_XY_QR/161234_Motzoi_XY_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170607/161456_AllXY_QR/161456_AllXY_QR.hdf5 b/pycqed/tests/test_data/20170607/161456_AllXY_QR/161456_AllXY_QR.hdf5 index 68018a9aef..e44757d63c 100644 Binary files a/pycqed/tests/test_data/20170607/161456_AllXY_QR/161456_AllXY_QR.hdf5 and b/pycqed/tests/test_data/20170607/161456_AllXY_QR/161456_AllXY_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170607/210555_Motzoi_XY_QR/210555_Motzoi_XY_QR.hdf5 b/pycqed/tests/test_data/20170607/210555_Motzoi_XY_QR/210555_Motzoi_XY_QR.hdf5 index 02a38accb3..c35a013ceb 100644 Binary files a/pycqed/tests/test_data/20170607/210555_Motzoi_XY_QR/210555_Motzoi_XY_QR.hdf5 and b/pycqed/tests/test_data/20170607/210555_Motzoi_XY_QR/210555_Motzoi_XY_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170607/210655_RB_100seeds_QR/210655_RB_100seeds_QR.hdf5 b/pycqed/tests/test_data/20170607/210655_RB_100seeds_QR/210655_RB_100seeds_QR.hdf5 index 8cb33723a7..54fc6734ac 100644 Binary files a/pycqed/tests/test_data/20170607/210655_RB_100seeds_QR/210655_RB_100seeds_QR.hdf5 and b/pycqed/tests/test_data/20170607/210655_RB_100seeds_QR/210655_RB_100seeds_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170607/211144_Ramsey_QR/211144_Ramsey_QR.hdf5 b/pycqed/tests/test_data/20170607/211144_Ramsey_QR/211144_Ramsey_QR.hdf5 index 82b9ac7a1f..00488ca91a 100644 Binary files a/pycqed/tests/test_data/20170607/211144_Ramsey_QR/211144_Ramsey_QR.hdf5 and b/pycqed/tests/test_data/20170607/211144_Ramsey_QR/211144_Ramsey_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170607/211203_Rabi-n1_QR/211203_Rabi-n1_QR.hdf5 b/pycqed/tests/test_data/20170607/211203_Rabi-n1_QR/211203_Rabi-n1_QR.hdf5 index 2f0b9cceb5..d3a365ee50 100644 Binary files a/pycqed/tests/test_data/20170607/211203_Rabi-n1_QR/211203_Rabi-n1_QR.hdf5 and b/pycqed/tests/test_data/20170607/211203_Rabi-n1_QR/211203_Rabi-n1_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170607/211611_echo_QR/211611_echo_QR.hdf5 b/pycqed/tests/test_data/20170607/211611_echo_QR/211611_echo_QR.hdf5 index a2fc536399..b941d17a09 100644 Binary files a/pycqed/tests/test_data/20170607/211611_echo_QR/211611_echo_QR.hdf5 and b/pycqed/tests/test_data/20170607/211611_echo_QR/211611_echo_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170607/211630_AllXY_QR/211630_AllXY_QR.hdf5 b/pycqed/tests/test_data/20170607/211630_AllXY_QR/211630_AllXY_QR.hdf5 index 5e9d20a580..83da4b2a03 100644 Binary files a/pycqed/tests/test_data/20170607/211630_AllXY_QR/211630_AllXY_QR.hdf5 and b/pycqed/tests/test_data/20170607/211630_AllXY_QR/211630_AllXY_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170716/134634_SSRO_QR/134634_SSRO_QR.hdf5 b/pycqed/tests/test_data/20170716/134634_SSRO_QR/134634_SSRO_QR.hdf5 index 9a57e98454..22a3223450 100644 Binary files a/pycqed/tests/test_data/20170716/134634_SSRO_QR/134634_SSRO_QR.hdf5 and b/pycqed/tests/test_data/20170716/134634_SSRO_QR/134634_SSRO_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170716/144742_Butterfly_QR_initialize_True/144742_Butterfly_QR_initialize_True.hdf5 b/pycqed/tests/test_data/20170716/144742_Butterfly_QR_initialize_True/144742_Butterfly_QR_initialize_True.hdf5 index f65210d96e..9204a97a10 100644 Binary files a/pycqed/tests/test_data/20170716/144742_Butterfly_QR_initialize_True/144742_Butterfly_QR_initialize_True.hdf5 and b/pycqed/tests/test_data/20170716/144742_Butterfly_QR_initialize_True/144742_Butterfly_QR_initialize_True.hdf5 differ diff --git a/pycqed/tests/test_data/20170726/164507_flipping_sequence_rancoarse_fact0.80_QR/164507_flipping_sequence_rancoarse_fact0.80_QR.hdf5 b/pycqed/tests/test_data/20170726/164507_flipping_sequence_rancoarse_fact0.80_QR/164507_flipping_sequence_rancoarse_fact0.80_QR.hdf5 index 9acc18d4c4..7bb211c21c 100644 Binary files a/pycqed/tests/test_data/20170726/164507_flipping_sequence_rancoarse_fact0.80_QR/164507_flipping_sequence_rancoarse_fact0.80_QR.hdf5 and b/pycqed/tests/test_data/20170726/164507_flipping_sequence_rancoarse_fact0.80_QR/164507_flipping_sequence_rancoarse_fact0.80_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170726/164536_flipping_sequence_rancoarse_fact0.90_QR/164536_flipping_sequence_rancoarse_fact0.90_QR.hdf5 b/pycqed/tests/test_data/20170726/164536_flipping_sequence_rancoarse_fact0.90_QR/164536_flipping_sequence_rancoarse_fact0.90_QR.hdf5 index 80284a8934..24833cca6b 100644 Binary files a/pycqed/tests/test_data/20170726/164536_flipping_sequence_rancoarse_fact0.90_QR/164536_flipping_sequence_rancoarse_fact0.90_QR.hdf5 and b/pycqed/tests/test_data/20170726/164536_flipping_sequence_rancoarse_fact0.90_QR/164536_flipping_sequence_rancoarse_fact0.90_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170726/164550_flipping_sequence_ranfine_fact0.90_QR/164550_flipping_sequence_ranfine_fact0.90_QR.hdf5 b/pycqed/tests/test_data/20170726/164550_flipping_sequence_ranfine_fact0.90_QR/164550_flipping_sequence_ranfine_fact0.90_QR.hdf5 index af194f1877..fffa063b26 100644 Binary files a/pycqed/tests/test_data/20170726/164550_flipping_sequence_ranfine_fact0.90_QR/164550_flipping_sequence_ranfine_fact0.90_QR.hdf5 and b/pycqed/tests/test_data/20170726/164550_flipping_sequence_ranfine_fact0.90_QR/164550_flipping_sequence_ranfine_fact0.90_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170726/164605_flipping_sequence_rancoarse_fact0.95_QR/164605_flipping_sequence_rancoarse_fact0.95_QR.hdf5 b/pycqed/tests/test_data/20170726/164605_flipping_sequence_rancoarse_fact0.95_QR/164605_flipping_sequence_rancoarse_fact0.95_QR.hdf5 index 9ce2edc726..5f7a3096c2 100644 Binary files a/pycqed/tests/test_data/20170726/164605_flipping_sequence_rancoarse_fact0.95_QR/164605_flipping_sequence_rancoarse_fact0.95_QR.hdf5 and b/pycqed/tests/test_data/20170726/164605_flipping_sequence_rancoarse_fact0.95_QR/164605_flipping_sequence_rancoarse_fact0.95_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170726/164619_flipping_sequence_ranfine_fact0.95_QR/164619_flipping_sequence_ranfine_fact0.95_QR.hdf5 b/pycqed/tests/test_data/20170726/164619_flipping_sequence_ranfine_fact0.95_QR/164619_flipping_sequence_ranfine_fact0.95_QR.hdf5 index 7564d9b191..1e34e4f6d5 100644 Binary files a/pycqed/tests/test_data/20170726/164619_flipping_sequence_ranfine_fact0.95_QR/164619_flipping_sequence_ranfine_fact0.95_QR.hdf5 and b/pycqed/tests/test_data/20170726/164619_flipping_sequence_ranfine_fact0.95_QR/164619_flipping_sequence_ranfine_fact0.95_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170726/164635_flipping_sequence_rancoarse_fact0.99_QR/164635_flipping_sequence_rancoarse_fact0.99_QR.hdf5 b/pycqed/tests/test_data/20170726/164635_flipping_sequence_rancoarse_fact0.99_QR/164635_flipping_sequence_rancoarse_fact0.99_QR.hdf5 index a2b6e9929a..a5b409f741 100644 Binary files a/pycqed/tests/test_data/20170726/164635_flipping_sequence_rancoarse_fact0.99_QR/164635_flipping_sequence_rancoarse_fact0.99_QR.hdf5 and b/pycqed/tests/test_data/20170726/164635_flipping_sequence_rancoarse_fact0.99_QR/164635_flipping_sequence_rancoarse_fact0.99_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170726/164649_flipping_sequence_ranfine_fact0.99_QR/164649_flipping_sequence_ranfine_fact0.99_QR.hdf5 b/pycqed/tests/test_data/20170726/164649_flipping_sequence_ranfine_fact0.99_QR/164649_flipping_sequence_ranfine_fact0.99_QR.hdf5 index 50a28fada9..a41abcac42 100644 Binary files a/pycqed/tests/test_data/20170726/164649_flipping_sequence_ranfine_fact0.99_QR/164649_flipping_sequence_ranfine_fact0.99_QR.hdf5 and b/pycqed/tests/test_data/20170726/164649_flipping_sequence_ranfine_fact0.99_QR/164649_flipping_sequence_ranfine_fact0.99_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170726/164704_flipping_sequence_rancoarse_fact1.00_QR/164704_flipping_sequence_rancoarse_fact1.00_QR.hdf5 b/pycqed/tests/test_data/20170726/164704_flipping_sequence_rancoarse_fact1.00_QR/164704_flipping_sequence_rancoarse_fact1.00_QR.hdf5 index 2d6fe5c953..c1a4db2b15 100644 Binary files a/pycqed/tests/test_data/20170726/164704_flipping_sequence_rancoarse_fact1.00_QR/164704_flipping_sequence_rancoarse_fact1.00_QR.hdf5 and b/pycqed/tests/test_data/20170726/164704_flipping_sequence_rancoarse_fact1.00_QR/164704_flipping_sequence_rancoarse_fact1.00_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170726/164718_flipping_sequence_ranfine_fact1.00_QR/164718_flipping_sequence_ranfine_fact1.00_QR.hdf5 b/pycqed/tests/test_data/20170726/164718_flipping_sequence_ranfine_fact1.00_QR/164718_flipping_sequence_ranfine_fact1.00_QR.hdf5 index c75572085e..d01cf307f0 100644 Binary files a/pycqed/tests/test_data/20170726/164718_flipping_sequence_ranfine_fact1.00_QR/164718_flipping_sequence_ranfine_fact1.00_QR.hdf5 and b/pycqed/tests/test_data/20170726/164718_flipping_sequence_ranfine_fact1.00_QR/164718_flipping_sequence_ranfine_fact1.00_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170726/164733_flipping_sequence_rancoarse_fact1.01_QR/164733_flipping_sequence_rancoarse_fact1.01_QR.hdf5 b/pycqed/tests/test_data/20170726/164733_flipping_sequence_rancoarse_fact1.01_QR/164733_flipping_sequence_rancoarse_fact1.01_QR.hdf5 index 97c1e3562c..a41c4fde52 100644 Binary files a/pycqed/tests/test_data/20170726/164733_flipping_sequence_rancoarse_fact1.01_QR/164733_flipping_sequence_rancoarse_fact1.01_QR.hdf5 and b/pycqed/tests/test_data/20170726/164733_flipping_sequence_rancoarse_fact1.01_QR/164733_flipping_sequence_rancoarse_fact1.01_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170726/164747_flipping_sequence_ranfine_fact1.01_QR/164747_flipping_sequence_ranfine_fact1.01_QR.hdf5 b/pycqed/tests/test_data/20170726/164747_flipping_sequence_ranfine_fact1.01_QR/164747_flipping_sequence_ranfine_fact1.01_QR.hdf5 index f5aff8eebc..313981219d 100644 Binary files a/pycqed/tests/test_data/20170726/164747_flipping_sequence_ranfine_fact1.01_QR/164747_flipping_sequence_ranfine_fact1.01_QR.hdf5 and b/pycqed/tests/test_data/20170726/164747_flipping_sequence_ranfine_fact1.01_QR/164747_flipping_sequence_ranfine_fact1.01_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170726/164802_flipping_sequence_rancoarse_fact1.05_QR/164802_flipping_sequence_rancoarse_fact1.05_QR.hdf5 b/pycqed/tests/test_data/20170726/164802_flipping_sequence_rancoarse_fact1.05_QR/164802_flipping_sequence_rancoarse_fact1.05_QR.hdf5 index 0920ddd17b..27efc349fe 100644 Binary files a/pycqed/tests/test_data/20170726/164802_flipping_sequence_rancoarse_fact1.05_QR/164802_flipping_sequence_rancoarse_fact1.05_QR.hdf5 and b/pycqed/tests/test_data/20170726/164802_flipping_sequence_rancoarse_fact1.05_QR/164802_flipping_sequence_rancoarse_fact1.05_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170726/164816_flipping_sequence_ranfine_fact1.05_QR/164816_flipping_sequence_ranfine_fact1.05_QR.hdf5 b/pycqed/tests/test_data/20170726/164816_flipping_sequence_ranfine_fact1.05_QR/164816_flipping_sequence_ranfine_fact1.05_QR.hdf5 index 7b52e79208..83a7c7e35a 100644 Binary files a/pycqed/tests/test_data/20170726/164816_flipping_sequence_ranfine_fact1.05_QR/164816_flipping_sequence_ranfine_fact1.05_QR.hdf5 and b/pycqed/tests/test_data/20170726/164816_flipping_sequence_ranfine_fact1.05_QR/164816_flipping_sequence_ranfine_fact1.05_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170726/164831_flipping_sequence_rancoarse_fact1.10_QR/164831_flipping_sequence_rancoarse_fact1.10_QR.hdf5 b/pycqed/tests/test_data/20170726/164831_flipping_sequence_rancoarse_fact1.10_QR/164831_flipping_sequence_rancoarse_fact1.10_QR.hdf5 index 50f069fd9f..ab4ca25570 100644 Binary files a/pycqed/tests/test_data/20170726/164831_flipping_sequence_rancoarse_fact1.10_QR/164831_flipping_sequence_rancoarse_fact1.10_QR.hdf5 and b/pycqed/tests/test_data/20170726/164831_flipping_sequence_rancoarse_fact1.10_QR/164831_flipping_sequence_rancoarse_fact1.10_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170726/164845_flipping_sequence_ranfine_fact1.10_QR/164845_flipping_sequence_ranfine_fact1.10_QR.hdf5 b/pycqed/tests/test_data/20170726/164845_flipping_sequence_ranfine_fact1.10_QR/164845_flipping_sequence_ranfine_fact1.10_QR.hdf5 index 3bc65c47b6..3ec3c51691 100644 Binary files a/pycqed/tests/test_data/20170726/164845_flipping_sequence_ranfine_fact1.10_QR/164845_flipping_sequence_ranfine_fact1.10_QR.hdf5 and b/pycqed/tests/test_data/20170726/164845_flipping_sequence_ranfine_fact1.10_QR/164845_flipping_sequence_ranfine_fact1.10_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170726/164901_flipping_sequence_rancoarse_fact1.20_QR/164901_flipping_sequence_rancoarse_fact1.20_QR.hdf5 b/pycqed/tests/test_data/20170726/164901_flipping_sequence_rancoarse_fact1.20_QR/164901_flipping_sequence_rancoarse_fact1.20_QR.hdf5 index 4bc6ce52bf..3ef2061551 100644 Binary files a/pycqed/tests/test_data/20170726/164901_flipping_sequence_rancoarse_fact1.20_QR/164901_flipping_sequence_rancoarse_fact1.20_QR.hdf5 and b/pycqed/tests/test_data/20170726/164901_flipping_sequence_rancoarse_fact1.20_QR/164901_flipping_sequence_rancoarse_fact1.20_QR.hdf5 differ diff --git a/pycqed/tests/test_data/20170929/120456_resonator_spec_qubit/120456_resonator_spec_qubit.hdf5 b/pycqed/tests/test_data/20170929/120456_resonator_spec_qubit/120456_resonator_spec_qubit.hdf5 index 41e1a408d0..138b8bcd24 100644 Binary files a/pycqed/tests/test_data/20170929/120456_resonator_spec_qubit/120456_resonator_spec_qubit.hdf5 and b/pycqed/tests/test_data/20170929/120456_resonator_spec_qubit/120456_resonator_spec_qubit.hdf5 differ diff --git a/pycqed/tests/test_data/20170929/144754_spectroscopy_qb2/144754_spectroscopy_qb2.hdf5 b/pycqed/tests/test_data/20170929/144754_spectroscopy_qb2/144754_spectroscopy_qb2.hdf5 index 83b15a6903..920fbae2de 100644 Binary files a/pycqed/tests/test_data/20170929/144754_spectroscopy_qb2/144754_spectroscopy_qb2.hdf5 and b/pycqed/tests/test_data/20170929/144754_spectroscopy_qb2/144754_spectroscopy_qb2.hdf5 differ diff --git a/pycqed/tests/test_data/20170929/165005_QScale_qb6/165005_QScale_qb6.hdf5 b/pycqed/tests/test_data/20170929/165005_QScale_qb6/165005_QScale_qb6.hdf5 index bda453a7a8..dc3617fbe5 100644 Binary files a/pycqed/tests/test_data/20170929/165005_QScale_qb6/165005_QScale_qb6.hdf5 and b/pycqed/tests/test_data/20170929/165005_QScale_qb6/165005_QScale_qb6.hdf5 differ diff --git a/pycqed/tests/test_data/20170929/174145_resonator_spec_qubit/174145_resonator_spec_qubit.hdf5 b/pycqed/tests/test_data/20170929/174145_resonator_spec_qubit/174145_resonator_spec_qubit.hdf5 index 14b515ab6c..dd4d17f862 100644 Binary files a/pycqed/tests/test_data/20170929/174145_resonator_spec_qubit/174145_resonator_spec_qubit.hdf5 and b/pycqed/tests/test_data/20170929/174145_resonator_spec_qubit/174145_resonator_spec_qubit.hdf5 differ diff --git a/pycqed/tests/test_data/20170929/175516_spectroscopy_qb2/175516_spectroscopy_qb2.hdf5 b/pycqed/tests/test_data/20170929/175516_spectroscopy_qb2/175516_spectroscopy_qb2.hdf5 index b9581945ff..7ddf1a33dd 100644 Binary files a/pycqed/tests/test_data/20170929/175516_spectroscopy_qb2/175516_spectroscopy_qb2.hdf5 and b/pycqed/tests/test_data/20170929/175516_spectroscopy_qb2/175516_spectroscopy_qb2.hdf5 differ diff --git a/pycqed/tests/test_data/20170929/205730_QScale_qb6/205730_QScale_qb6.hdf5 b/pycqed/tests/test_data/20170929/205730_QScale_qb6/205730_QScale_qb6.hdf5 index a5a723f86f..d12c6dc099 100644 Binary files a/pycqed/tests/test_data/20170929/205730_QScale_qb6/205730_QScale_qb6.hdf5 and b/pycqed/tests/test_data/20170929/205730_QScale_qb6/205730_QScale_qb6.hdf5 differ diff --git a/pycqed/tests/test_data/20171016/135112_Measure_SSRO_QL/135112_Measure_SSRO_QL.hdf5 b/pycqed/tests/test_data/20171016/135112_Measure_SSRO_QL/135112_Measure_SSRO_QL.hdf5 index 3f5d549ff0..19fc0d8825 100644 Binary files a/pycqed/tests/test_data/20171016/135112_Measure_SSRO_QL/135112_Measure_SSRO_QL.hdf5 and b/pycqed/tests/test_data/20171016/135112_Measure_SSRO_QL/135112_Measure_SSRO_QL.hdf5 differ diff --git a/pycqed/tests/test_data/20171016/171715_Measure_SSRO_QL/171715_Measure_SSRO_QL.hdf5 b/pycqed/tests/test_data/20171016/171715_Measure_SSRO_QL/171715_Measure_SSRO_QL.hdf5 index 7bf7b42759..0f29a6b8df 100644 Binary files a/pycqed/tests/test_data/20171016/171715_Measure_SSRO_QL/171715_Measure_SSRO_QL.hdf5 and b/pycqed/tests/test_data/20171016/171715_Measure_SSRO_QL/171715_Measure_SSRO_QL.hdf5 differ diff --git a/pycqed/tests/test_data/20171016/181021_Measure_SSRO_QL/181021_Measure_SSRO_QL.hdf5 b/pycqed/tests/test_data/20171016/181021_Measure_SSRO_QL/181021_Measure_SSRO_QL.hdf5 index a022755d7f..cf5bd53dc5 100644 Binary files a/pycqed/tests/test_data/20171016/181021_Measure_SSRO_QL/181021_Measure_SSRO_QL.hdf5 and b/pycqed/tests/test_data/20171016/181021_Measure_SSRO_QL/181021_Measure_SSRO_QL.hdf5 differ diff --git a/pycqed/tests/test_data/20171126/180251_QR_phase/180251_QR_phase.hdf5 b/pycqed/tests/test_data/20171126/180251_QR_phase/180251_QR_phase.hdf5 index f34a30a2f8..e23a50f294 100644 Binary files a/pycqed/tests/test_data/20171126/180251_QR_phase/180251_QR_phase.hdf5 and b/pycqed/tests/test_data/20171126/180251_QR_phase/180251_QR_phase.hdf5 differ diff --git a/pycqed/tests/test_data/20171126/181327_QL_phase/181327_QL_phase.hdf5 b/pycqed/tests/test_data/20171126/181327_QL_phase/181327_QL_phase.hdf5 index e921a0d8ef..25e7efc96d 100644 Binary files a/pycqed/tests/test_data/20171126/181327_QL_phase/181327_QL_phase.hdf5 and b/pycqed/tests/test_data/20171126/181327_QL_phase/181327_QL_phase.hdf5 differ diff --git a/pycqed/tests/test_data/20180130/191229_conditional_oscillation_device/191229_conditional_oscillation_device.hdf5 b/pycqed/tests/test_data/20180130/191229_conditional_oscillation_device/191229_conditional_oscillation_device.hdf5 index 9bd657a4ce..a2810df47f 100644 Binary files a/pycqed/tests/test_data/20180130/191229_conditional_oscillation_device/191229_conditional_oscillation_device.hdf5 and b/pycqed/tests/test_data/20180130/191229_conditional_oscillation_device/191229_conditional_oscillation_device.hdf5 differ diff --git a/pycqed/tests/test_data/20180210/181633_idle_error_rates_QL/181633_idle_error_rates_QL.hdf5 b/pycqed/tests/test_data/20180210/181633_idle_error_rates_QL/181633_idle_error_rates_QL.hdf5 index da6d251aaa..4d71f0c2df 100644 Binary files a/pycqed/tests/test_data/20180210/181633_idle_error_rates_QL/181633_idle_error_rates_QL.hdf5 and b/pycqed/tests/test_data/20180210/181633_idle_error_rates_QL/181633_idle_error_rates_QL.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/194743_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.0015/194743_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.0015.hdf5 b/pycqed/tests/test_data/20180412/194743_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.0015/194743_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.0015.hdf5 new file mode 100644 index 0000000000..490fab29c0 Binary files /dev/null and b/pycqed/tests/test_data/20180412/194743_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.0015/194743_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.0015.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/194804_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.0015/194804_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.0015.hdf5 b/pycqed/tests/test_data/20180412/194804_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.0015/194804_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.0015.hdf5 new file mode 100644 index 0000000000..73467ad413 Binary files /dev/null and b/pycqed/tests/test_data/20180412/194804_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.0015/194804_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.0015.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/194922_rabi_-VFC_res1_dac_channel_VFCQ6_-0.0015/194922_rabi_-VFC_res1_dac_channel_VFCQ6_-0.0015.hdf5 b/pycqed/tests/test_data/20180412/194922_rabi_-VFC_res1_dac_channel_VFCQ6_-0.0015/194922_rabi_-VFC_res1_dac_channel_VFCQ6_-0.0015.hdf5 new file mode 100644 index 0000000000..2649dc42a9 Binary files /dev/null and b/pycqed/tests/test_data/20180412/194922_rabi_-VFC_res1_dac_channel_VFCQ6_-0.0015/194922_rabi_-VFC_res1_dac_channel_VFCQ6_-0.0015.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/194942_T1-VFC_res1_dac_channel_VFCQ6_-0.0015/194942_T1-VFC_res1_dac_channel_VFCQ6_-0.0015.hdf5 b/pycqed/tests/test_data/20180412/194942_T1-VFC_res1_dac_channel_VFCQ6_-0.0015/194942_T1-VFC_res1_dac_channel_VFCQ6_-0.0015.hdf5 new file mode 100644 index 0000000000..7a0798a479 Binary files /dev/null and b/pycqed/tests/test_data/20180412/194942_T1-VFC_res1_dac_channel_VFCQ6_-0.0015/194942_T1-VFC_res1_dac_channel_VFCQ6_-0.0015.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195005_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.0015/195005_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.0015.hdf5 b/pycqed/tests/test_data/20180412/195005_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.0015/195005_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.0015.hdf5 new file mode 100644 index 0000000000..363ea54f06 Binary files /dev/null and b/pycqed/tests/test_data/20180412/195005_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.0015/195005_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.0015.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195032_echo-VFC_res1_dac_channel_VFCQ6_-0.0015/195032_echo-VFC_res1_dac_channel_VFCQ6_-0.0015.hdf5 b/pycqed/tests/test_data/20180412/195032_echo-VFC_res1_dac_channel_VFCQ6_-0.0015/195032_echo-VFC_res1_dac_channel_VFCQ6_-0.0015.hdf5 new file mode 100644 index 0000000000..acd5edf774 Binary files /dev/null and b/pycqed/tests/test_data/20180412/195032_echo-VFC_res1_dac_channel_VFCQ6_-0.0015/195032_echo-VFC_res1_dac_channel_VFCQ6_-0.0015.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195100_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.00115/195100_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.00115.hdf5 b/pycqed/tests/test_data/20180412/195100_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.00115/195100_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.00115.hdf5 new file mode 100644 index 0000000000..6d5f3c964d Binary files /dev/null and b/pycqed/tests/test_data/20180412/195100_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.00115/195100_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.00115.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195121_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.00115/195121_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.00115.hdf5 b/pycqed/tests/test_data/20180412/195121_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.00115/195121_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.00115.hdf5 new file mode 100644 index 0000000000..8df597dc38 Binary files /dev/null and b/pycqed/tests/test_data/20180412/195121_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.00115/195121_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.00115.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195240_rabi_-VFC_res1_dac_channel_VFCQ6_-0.00115/195240_rabi_-VFC_res1_dac_channel_VFCQ6_-0.00115.hdf5 b/pycqed/tests/test_data/20180412/195240_rabi_-VFC_res1_dac_channel_VFCQ6_-0.00115/195240_rabi_-VFC_res1_dac_channel_VFCQ6_-0.00115.hdf5 new file mode 100644 index 0000000000..f3a8ac82e6 Binary files /dev/null and b/pycqed/tests/test_data/20180412/195240_rabi_-VFC_res1_dac_channel_VFCQ6_-0.00115/195240_rabi_-VFC_res1_dac_channel_VFCQ6_-0.00115.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195300_T1-VFC_res1_dac_channel_VFCQ6_-0.00115/195300_T1-VFC_res1_dac_channel_VFCQ6_-0.00115.hdf5 b/pycqed/tests/test_data/20180412/195300_T1-VFC_res1_dac_channel_VFCQ6_-0.00115/195300_T1-VFC_res1_dac_channel_VFCQ6_-0.00115.hdf5 new file mode 100644 index 0000000000..7d4db7825f Binary files /dev/null and b/pycqed/tests/test_data/20180412/195300_T1-VFC_res1_dac_channel_VFCQ6_-0.00115/195300_T1-VFC_res1_dac_channel_VFCQ6_-0.00115.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195323_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.00115/195323_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.00115.hdf5 b/pycqed/tests/test_data/20180412/195323_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.00115/195323_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.00115.hdf5 new file mode 100644 index 0000000000..a3e7507e7f Binary files /dev/null and b/pycqed/tests/test_data/20180412/195323_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.00115/195323_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.00115.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195350_echo-VFC_res1_dac_channel_VFCQ6_-0.00115/195350_echo-VFC_res1_dac_channel_VFCQ6_-0.00115.hdf5 b/pycqed/tests/test_data/20180412/195350_echo-VFC_res1_dac_channel_VFCQ6_-0.00115/195350_echo-VFC_res1_dac_channel_VFCQ6_-0.00115.hdf5 new file mode 100644 index 0000000000..fb80b54e3c Binary files /dev/null and b/pycqed/tests/test_data/20180412/195350_echo-VFC_res1_dac_channel_VFCQ6_-0.00115/195350_echo-VFC_res1_dac_channel_VFCQ6_-0.00115.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195418_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001/195418_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001.hdf5 b/pycqed/tests/test_data/20180412/195418_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001/195418_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001.hdf5 new file mode 100644 index 0000000000..e553f8a164 Binary files /dev/null and b/pycqed/tests/test_data/20180412/195418_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001/195418_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195439_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001/195439_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001.hdf5 b/pycqed/tests/test_data/20180412/195439_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001/195439_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001.hdf5 new file mode 100644 index 0000000000..7d90fd52cf Binary files /dev/null and b/pycqed/tests/test_data/20180412/195439_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001/195439_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195558_rabi_-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001/195558_rabi_-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001.hdf5 b/pycqed/tests/test_data/20180412/195558_rabi_-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001/195558_rabi_-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001.hdf5 new file mode 100644 index 0000000000..ebc7575583 Binary files /dev/null and b/pycqed/tests/test_data/20180412/195558_rabi_-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001/195558_rabi_-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195618_T1-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001/195618_T1-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001.hdf5 b/pycqed/tests/test_data/20180412/195618_T1-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001/195618_T1-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001.hdf5 new file mode 100644 index 0000000000..b6277a8ab2 Binary files /dev/null and b/pycqed/tests/test_data/20180412/195618_T1-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001/195618_T1-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195641_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001/195641_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001.hdf5 b/pycqed/tests/test_data/20180412/195641_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001/195641_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001.hdf5 new file mode 100644 index 0000000000..6d7c0349ef Binary files /dev/null and b/pycqed/tests/test_data/20180412/195641_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001/195641_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195708_echo-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001/195708_echo-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001.hdf5 b/pycqed/tests/test_data/20180412/195708_echo-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001/195708_echo-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001.hdf5 new file mode 100644 index 0000000000..102c674b43 Binary files /dev/null and b/pycqed/tests/test_data/20180412/195708_echo-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001/195708_echo-VFC_res1_dac_channel_VFCQ6_-0.0008000000000000001.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195736_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003/195736_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003.hdf5 b/pycqed/tests/test_data/20180412/195736_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003/195736_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003.hdf5 new file mode 100644 index 0000000000..7c208fb279 Binary files /dev/null and b/pycqed/tests/test_data/20180412/195736_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003/195736_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195758_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003/195758_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003.hdf5 b/pycqed/tests/test_data/20180412/195758_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003/195758_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003.hdf5 new file mode 100644 index 0000000000..973a859b2b Binary files /dev/null and b/pycqed/tests/test_data/20180412/195758_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003/195758_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195917_rabi_-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003/195917_rabi_-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003.hdf5 b/pycqed/tests/test_data/20180412/195917_rabi_-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003/195917_rabi_-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003.hdf5 new file mode 100644 index 0000000000..403956882b Binary files /dev/null and b/pycqed/tests/test_data/20180412/195917_rabi_-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003/195917_rabi_-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195937_T1-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003/195937_T1-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003.hdf5 b/pycqed/tests/test_data/20180412/195937_T1-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003/195937_T1-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003.hdf5 new file mode 100644 index 0000000000..603fc35da9 Binary files /dev/null and b/pycqed/tests/test_data/20180412/195937_T1-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003/195937_T1-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/195959_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003/195959_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003.hdf5 b/pycqed/tests/test_data/20180412/195959_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003/195959_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003.hdf5 new file mode 100644 index 0000000000..25df7cefe1 Binary files /dev/null and b/pycqed/tests/test_data/20180412/195959_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003/195959_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/200027_echo-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003/200027_echo-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003.hdf5 b/pycqed/tests/test_data/20180412/200027_echo-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003/200027_echo-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003.hdf5 new file mode 100644 index 0000000000..e494072cc7 Binary files /dev/null and b/pycqed/tests/test_data/20180412/200027_echo-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003/200027_echo-VFC_res1_dac_channel_VFCQ6_-0.0004500000000000003.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/200054_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026/200054_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026.hdf5 b/pycqed/tests/test_data/20180412/200054_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026/200054_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026.hdf5 new file mode 100644 index 0000000000..c8be8e1a5a Binary files /dev/null and b/pycqed/tests/test_data/20180412/200054_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026/200054_Resonator_scan-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/200117_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026/200117_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026.hdf5 b/pycqed/tests/test_data/20180412/200117_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026/200117_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026.hdf5 new file mode 100644 index 0000000000..b4571e2b22 Binary files /dev/null and b/pycqed/tests/test_data/20180412/200117_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026/200117_spectroscopy_-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/200235_rabi_-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026/200235_rabi_-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026.hdf5 b/pycqed/tests/test_data/20180412/200235_rabi_-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026/200235_rabi_-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026.hdf5 new file mode 100644 index 0000000000..a84cb9a5cd Binary files /dev/null and b/pycqed/tests/test_data/20180412/200235_rabi_-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026/200235_rabi_-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/200255_T1-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026/200255_T1-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026.hdf5 b/pycqed/tests/test_data/20180412/200255_T1-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026/200255_T1-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026.hdf5 new file mode 100644 index 0000000000..90554ccb7d Binary files /dev/null and b/pycqed/tests/test_data/20180412/200255_T1-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026/200255_T1-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/200317_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026/200317_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026.hdf5 b/pycqed/tests/test_data/20180412/200317_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026/200317_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026.hdf5 new file mode 100644 index 0000000000..f2dd08ccc1 Binary files /dev/null and b/pycqed/tests/test_data/20180412/200317_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026/200317_Ramsey-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/200345_echo-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026/200345_echo-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026.hdf5 b/pycqed/tests/test_data/20180412/200345_echo-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026/200345_echo-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026.hdf5 new file mode 100644 index 0000000000..0ca4d5442e Binary files /dev/null and b/pycqed/tests/test_data/20180412/200345_echo-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026/200345_echo-VFC_res1_dac_channel_VFCQ6_-0.00010000000000000026.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/200412_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998/200412_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998.hdf5 b/pycqed/tests/test_data/20180412/200412_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998/200412_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998.hdf5 new file mode 100644 index 0000000000..5a5023c6e3 Binary files /dev/null and b/pycqed/tests/test_data/20180412/200412_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998/200412_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/200434_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998/200434_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998.hdf5 b/pycqed/tests/test_data/20180412/200434_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998/200434_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998.hdf5 new file mode 100644 index 0000000000..678688edc8 Binary files /dev/null and b/pycqed/tests/test_data/20180412/200434_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998/200434_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/200553_rabi_-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998/200553_rabi_-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998.hdf5 b/pycqed/tests/test_data/20180412/200553_rabi_-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998/200553_rabi_-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998.hdf5 new file mode 100644 index 0000000000..86d7097c1b Binary files /dev/null and b/pycqed/tests/test_data/20180412/200553_rabi_-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998/200553_rabi_-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/200612_T1-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998/200612_T1-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998.hdf5 b/pycqed/tests/test_data/20180412/200612_T1-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998/200612_T1-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998.hdf5 new file mode 100644 index 0000000000..f9cdfccb8a Binary files /dev/null and b/pycqed/tests/test_data/20180412/200612_T1-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998/200612_T1-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/200635_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998/200635_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998.hdf5 b/pycqed/tests/test_data/20180412/200635_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998/200635_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998.hdf5 new file mode 100644 index 0000000000..89ebb63dda Binary files /dev/null and b/pycqed/tests/test_data/20180412/200635_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998/200635_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/200703_echo-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998/200703_echo-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998.hdf5 b/pycqed/tests/test_data/20180412/200703_echo-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998/200703_echo-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998.hdf5 new file mode 100644 index 0000000000..d0d5b30800 Binary files /dev/null and b/pycqed/tests/test_data/20180412/200703_echo-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998/200703_echo-VFC_res1_dac_channel_VFCQ6_0.0002499999999999998.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/200730_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994/200730_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994.hdf5 b/pycqed/tests/test_data/20180412/200730_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994/200730_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994.hdf5 new file mode 100644 index 0000000000..ddbafd71c6 Binary files /dev/null and b/pycqed/tests/test_data/20180412/200730_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994/200730_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/200752_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994/200752_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994.hdf5 b/pycqed/tests/test_data/20180412/200752_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994/200752_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994.hdf5 new file mode 100644 index 0000000000..dfdf77e7b2 Binary files /dev/null and b/pycqed/tests/test_data/20180412/200752_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994/200752_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/200912_rabi_-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994/200912_rabi_-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994.hdf5 b/pycqed/tests/test_data/20180412/200912_rabi_-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994/200912_rabi_-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994.hdf5 new file mode 100644 index 0000000000..69eec38dba Binary files /dev/null and b/pycqed/tests/test_data/20180412/200912_rabi_-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994/200912_rabi_-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/200931_T1-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994/200931_T1-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994.hdf5 b/pycqed/tests/test_data/20180412/200931_T1-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994/200931_T1-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994.hdf5 new file mode 100644 index 0000000000..0ed212a501 Binary files /dev/null and b/pycqed/tests/test_data/20180412/200931_T1-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994/200931_T1-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/200954_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994/200954_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994.hdf5 b/pycqed/tests/test_data/20180412/200954_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994/200954_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994.hdf5 new file mode 100644 index 0000000000..861ad75d22 Binary files /dev/null and b/pycqed/tests/test_data/20180412/200954_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994/200954_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/201021_echo-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994/201021_echo-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994.hdf5 b/pycqed/tests/test_data/20180412/201021_echo-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994/201021_echo-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994.hdf5 new file mode 100644 index 0000000000..0d9b87d4e6 Binary files /dev/null and b/pycqed/tests/test_data/20180412/201021_echo-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994/201021_echo-VFC_res1_dac_channel_VFCQ6_0.0005999999999999994.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/201049_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995/201049_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995.hdf5 b/pycqed/tests/test_data/20180412/201049_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995/201049_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995.hdf5 new file mode 100644 index 0000000000..ee5d979663 Binary files /dev/null and b/pycqed/tests/test_data/20180412/201049_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995/201049_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/201110_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995/201110_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995.hdf5 b/pycqed/tests/test_data/20180412/201110_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995/201110_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995.hdf5 new file mode 100644 index 0000000000..55055bb3a2 Binary files /dev/null and b/pycqed/tests/test_data/20180412/201110_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995/201110_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/201229_rabi_-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995/201229_rabi_-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995.hdf5 b/pycqed/tests/test_data/20180412/201229_rabi_-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995/201229_rabi_-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995.hdf5 new file mode 100644 index 0000000000..c511c817d1 Binary files /dev/null and b/pycqed/tests/test_data/20180412/201229_rabi_-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995/201229_rabi_-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/201249_T1-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995/201249_T1-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995.hdf5 b/pycqed/tests/test_data/20180412/201249_T1-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995/201249_T1-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995.hdf5 new file mode 100644 index 0000000000..52144f61f6 Binary files /dev/null and b/pycqed/tests/test_data/20180412/201249_T1-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995/201249_T1-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/201312_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995/201312_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995.hdf5 b/pycqed/tests/test_data/20180412/201312_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995/201312_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995.hdf5 new file mode 100644 index 0000000000..90f5e2fac6 Binary files /dev/null and b/pycqed/tests/test_data/20180412/201312_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995/201312_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/201339_echo-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995/201339_echo-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995.hdf5 b/pycqed/tests/test_data/20180412/201339_echo-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995/201339_echo-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995.hdf5 new file mode 100644 index 0000000000..99e79af813 Binary files /dev/null and b/pycqed/tests/test_data/20180412/201339_echo-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995/201339_echo-VFC_res1_dac_channel_VFCQ6_0.0009499999999999995.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/201406_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995/201406_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995.hdf5 b/pycqed/tests/test_data/20180412/201406_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995/201406_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995.hdf5 new file mode 100644 index 0000000000..f28b8451df Binary files /dev/null and b/pycqed/tests/test_data/20180412/201406_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995/201406_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/201428_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995/201428_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995.hdf5 b/pycqed/tests/test_data/20180412/201428_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995/201428_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995.hdf5 new file mode 100644 index 0000000000..dbe88cb630 Binary files /dev/null and b/pycqed/tests/test_data/20180412/201428_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995/201428_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/201547_rabi_-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995/201547_rabi_-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995.hdf5 b/pycqed/tests/test_data/20180412/201547_rabi_-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995/201547_rabi_-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995.hdf5 new file mode 100644 index 0000000000..e420107ee4 Binary files /dev/null and b/pycqed/tests/test_data/20180412/201547_rabi_-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995/201547_rabi_-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/201608_T1-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995/201608_T1-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995.hdf5 b/pycqed/tests/test_data/20180412/201608_T1-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995/201608_T1-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995.hdf5 new file mode 100644 index 0000000000..e45c050562 Binary files /dev/null and b/pycqed/tests/test_data/20180412/201608_T1-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995/201608_T1-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/201630_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995/201630_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995.hdf5 b/pycqed/tests/test_data/20180412/201630_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995/201630_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995.hdf5 new file mode 100644 index 0000000000..eeabe12159 Binary files /dev/null and b/pycqed/tests/test_data/20180412/201630_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995/201630_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/201658_echo-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995/201658_echo-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995.hdf5 b/pycqed/tests/test_data/20180412/201658_echo-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995/201658_echo-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995.hdf5 new file mode 100644 index 0000000000..b32ef5e370 Binary files /dev/null and b/pycqed/tests/test_data/20180412/201658_echo-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995/201658_echo-VFC_res1_dac_channel_VFCQ6_0.0012999999999999995.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/201725_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996/201725_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996.hdf5 b/pycqed/tests/test_data/20180412/201725_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996/201725_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996.hdf5 new file mode 100644 index 0000000000..e0ad41fe0c Binary files /dev/null and b/pycqed/tests/test_data/20180412/201725_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996/201725_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/201747_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996/201747_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996.hdf5 b/pycqed/tests/test_data/20180412/201747_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996/201747_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996.hdf5 new file mode 100644 index 0000000000..ef470606c4 Binary files /dev/null and b/pycqed/tests/test_data/20180412/201747_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996/201747_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/201906_rabi_-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996/201906_rabi_-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996.hdf5 b/pycqed/tests/test_data/20180412/201906_rabi_-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996/201906_rabi_-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996.hdf5 new file mode 100644 index 0000000000..e33a0e0e7a Binary files /dev/null and b/pycqed/tests/test_data/20180412/201906_rabi_-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996/201906_rabi_-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/201925_T1-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996/201925_T1-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996.hdf5 b/pycqed/tests/test_data/20180412/201925_T1-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996/201925_T1-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996.hdf5 new file mode 100644 index 0000000000..7d1ff804d5 Binary files /dev/null and b/pycqed/tests/test_data/20180412/201925_T1-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996/201925_T1-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/201948_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996/201948_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996.hdf5 b/pycqed/tests/test_data/20180412/201948_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996/201948_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996.hdf5 new file mode 100644 index 0000000000..11d7f9d405 Binary files /dev/null and b/pycqed/tests/test_data/20180412/201948_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996/201948_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/202015_echo-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996/202015_echo-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996.hdf5 b/pycqed/tests/test_data/20180412/202015_echo-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996/202015_echo-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996.hdf5 new file mode 100644 index 0000000000..862f0ac825 Binary files /dev/null and b/pycqed/tests/test_data/20180412/202015_echo-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996/202015_echo-VFC_res1_dac_channel_VFCQ6_0.0016499999999999996.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/202043_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996/202043_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996.hdf5 b/pycqed/tests/test_data/20180412/202043_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996/202043_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996.hdf5 new file mode 100644 index 0000000000..446bc01976 Binary files /dev/null and b/pycqed/tests/test_data/20180412/202043_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996/202043_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/202105_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996/202105_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996.hdf5 b/pycqed/tests/test_data/20180412/202105_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996/202105_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996.hdf5 new file mode 100644 index 0000000000..ae5572d9ce Binary files /dev/null and b/pycqed/tests/test_data/20180412/202105_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996/202105_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/202223_rabi_-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996/202223_rabi_-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996.hdf5 b/pycqed/tests/test_data/20180412/202223_rabi_-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996/202223_rabi_-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996.hdf5 new file mode 100644 index 0000000000..11cff85c3e Binary files /dev/null and b/pycqed/tests/test_data/20180412/202223_rabi_-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996/202223_rabi_-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/202243_T1-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996/202243_T1-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996.hdf5 b/pycqed/tests/test_data/20180412/202243_T1-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996/202243_T1-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996.hdf5 new file mode 100644 index 0000000000..abfeff5399 Binary files /dev/null and b/pycqed/tests/test_data/20180412/202243_T1-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996/202243_T1-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/202305_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996/202305_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996.hdf5 b/pycqed/tests/test_data/20180412/202305_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996/202305_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996.hdf5 new file mode 100644 index 0000000000..bcb9b8d01c Binary files /dev/null and b/pycqed/tests/test_data/20180412/202305_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996/202305_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/202333_echo-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996/202333_echo-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996.hdf5 b/pycqed/tests/test_data/20180412/202333_echo-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996/202333_echo-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996.hdf5 new file mode 100644 index 0000000000..4f00433c77 Binary files /dev/null and b/pycqed/tests/test_data/20180412/202333_echo-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996/202333_echo-VFC_res1_dac_channel_VFCQ6_0.0019999999999999996.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/202400_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992/202400_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992.hdf5 b/pycqed/tests/test_data/20180412/202400_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992/202400_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992.hdf5 new file mode 100644 index 0000000000..863f085708 Binary files /dev/null and b/pycqed/tests/test_data/20180412/202400_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992/202400_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/202422_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992/202422_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992.hdf5 b/pycqed/tests/test_data/20180412/202422_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992/202422_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992.hdf5 new file mode 100644 index 0000000000..691c05369d Binary files /dev/null and b/pycqed/tests/test_data/20180412/202422_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992/202422_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/202541_rabi_-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992/202541_rabi_-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992.hdf5 b/pycqed/tests/test_data/20180412/202541_rabi_-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992/202541_rabi_-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992.hdf5 new file mode 100644 index 0000000000..a97f7f75ee Binary files /dev/null and b/pycqed/tests/test_data/20180412/202541_rabi_-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992/202541_rabi_-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/202601_T1-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992/202601_T1-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992.hdf5 b/pycqed/tests/test_data/20180412/202601_T1-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992/202601_T1-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992.hdf5 new file mode 100644 index 0000000000..978a89e0fa Binary files /dev/null and b/pycqed/tests/test_data/20180412/202601_T1-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992/202601_T1-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/202624_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992/202624_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992.hdf5 b/pycqed/tests/test_data/20180412/202624_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992/202624_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992.hdf5 new file mode 100644 index 0000000000..226b43cfa7 Binary files /dev/null and b/pycqed/tests/test_data/20180412/202624_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992/202624_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/202651_echo-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992/202651_echo-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992.hdf5 b/pycqed/tests/test_data/20180412/202651_echo-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992/202651_echo-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992.hdf5 new file mode 100644 index 0000000000..855555c8f2 Binary files /dev/null and b/pycqed/tests/test_data/20180412/202651_echo-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992/202651_echo-VFC_res1_dac_channel_VFCQ6_0.0023499999999999992.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/202719_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.002699999999999999/202719_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.002699999999999999.hdf5 b/pycqed/tests/test_data/20180412/202719_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.002699999999999999/202719_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.002699999999999999.hdf5 new file mode 100644 index 0000000000..879ea9e7f0 Binary files /dev/null and b/pycqed/tests/test_data/20180412/202719_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.002699999999999999/202719_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.002699999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/202741_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.002699999999999999/202741_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.002699999999999999.hdf5 b/pycqed/tests/test_data/20180412/202741_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.002699999999999999/202741_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.002699999999999999.hdf5 new file mode 100644 index 0000000000..0b8e21c5ca Binary files /dev/null and b/pycqed/tests/test_data/20180412/202741_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.002699999999999999/202741_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.002699999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/202859_rabi_-VFC_res1_dac_channel_VFCQ6_0.002699999999999999/202859_rabi_-VFC_res1_dac_channel_VFCQ6_0.002699999999999999.hdf5 b/pycqed/tests/test_data/20180412/202859_rabi_-VFC_res1_dac_channel_VFCQ6_0.002699999999999999/202859_rabi_-VFC_res1_dac_channel_VFCQ6_0.002699999999999999.hdf5 new file mode 100644 index 0000000000..3c73660cc3 Binary files /dev/null and b/pycqed/tests/test_data/20180412/202859_rabi_-VFC_res1_dac_channel_VFCQ6_0.002699999999999999/202859_rabi_-VFC_res1_dac_channel_VFCQ6_0.002699999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/202918_T1-VFC_res1_dac_channel_VFCQ6_0.002699999999999999/202918_T1-VFC_res1_dac_channel_VFCQ6_0.002699999999999999.hdf5 b/pycqed/tests/test_data/20180412/202918_T1-VFC_res1_dac_channel_VFCQ6_0.002699999999999999/202918_T1-VFC_res1_dac_channel_VFCQ6_0.002699999999999999.hdf5 new file mode 100644 index 0000000000..a0e1b5ec8a Binary files /dev/null and b/pycqed/tests/test_data/20180412/202918_T1-VFC_res1_dac_channel_VFCQ6_0.002699999999999999/202918_T1-VFC_res1_dac_channel_VFCQ6_0.002699999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/202941_Ramsey-VFC_res1_dac_channel_VFCQ6_0.002699999999999999/202941_Ramsey-VFC_res1_dac_channel_VFCQ6_0.002699999999999999.hdf5 b/pycqed/tests/test_data/20180412/202941_Ramsey-VFC_res1_dac_channel_VFCQ6_0.002699999999999999/202941_Ramsey-VFC_res1_dac_channel_VFCQ6_0.002699999999999999.hdf5 new file mode 100644 index 0000000000..29921f25ec Binary files /dev/null and b/pycqed/tests/test_data/20180412/202941_Ramsey-VFC_res1_dac_channel_VFCQ6_0.002699999999999999/202941_Ramsey-VFC_res1_dac_channel_VFCQ6_0.002699999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/203009_echo-VFC_res1_dac_channel_VFCQ6_0.002699999999999999/203009_echo-VFC_res1_dac_channel_VFCQ6_0.002699999999999999.hdf5 b/pycqed/tests/test_data/20180412/203009_echo-VFC_res1_dac_channel_VFCQ6_0.002699999999999999/203009_echo-VFC_res1_dac_channel_VFCQ6_0.002699999999999999.hdf5 new file mode 100644 index 0000000000..a1c2c236c7 Binary files /dev/null and b/pycqed/tests/test_data/20180412/203009_echo-VFC_res1_dac_channel_VFCQ6_0.002699999999999999/203009_echo-VFC_res1_dac_channel_VFCQ6_0.002699999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/203037_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993/203037_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993.hdf5 b/pycqed/tests/test_data/20180412/203037_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993/203037_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993.hdf5 new file mode 100644 index 0000000000..4901635fec Binary files /dev/null and b/pycqed/tests/test_data/20180412/203037_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993/203037_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/203059_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993/203059_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993.hdf5 b/pycqed/tests/test_data/20180412/203059_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993/203059_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993.hdf5 new file mode 100644 index 0000000000..6f1f700b1b Binary files /dev/null and b/pycqed/tests/test_data/20180412/203059_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993/203059_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/203218_rabi_-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993/203218_rabi_-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993.hdf5 b/pycqed/tests/test_data/20180412/203218_rabi_-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993/203218_rabi_-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993.hdf5 new file mode 100644 index 0000000000..8ec3adeb29 Binary files /dev/null and b/pycqed/tests/test_data/20180412/203218_rabi_-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993/203218_rabi_-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/203237_T1-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993/203237_T1-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993.hdf5 b/pycqed/tests/test_data/20180412/203237_T1-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993/203237_T1-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993.hdf5 new file mode 100644 index 0000000000..65feb04ca0 Binary files /dev/null and b/pycqed/tests/test_data/20180412/203237_T1-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993/203237_T1-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/203301_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993/203301_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993.hdf5 b/pycqed/tests/test_data/20180412/203301_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993/203301_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993.hdf5 new file mode 100644 index 0000000000..e9d3ad79f5 Binary files /dev/null and b/pycqed/tests/test_data/20180412/203301_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993/203301_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/203328_echo-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993/203328_echo-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993.hdf5 b/pycqed/tests/test_data/20180412/203328_echo-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993/203328_echo-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993.hdf5 new file mode 100644 index 0000000000..56b194c5ed Binary files /dev/null and b/pycqed/tests/test_data/20180412/203328_echo-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993/203328_echo-VFC_res1_dac_channel_VFCQ6_0.0030499999999999993.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/203356_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.003399999999999999/203356_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.003399999999999999.hdf5 b/pycqed/tests/test_data/20180412/203356_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.003399999999999999/203356_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.003399999999999999.hdf5 new file mode 100644 index 0000000000..fa1a023dda Binary files /dev/null and b/pycqed/tests/test_data/20180412/203356_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.003399999999999999/203356_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.003399999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/203417_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.003399999999999999/203417_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.003399999999999999.hdf5 b/pycqed/tests/test_data/20180412/203417_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.003399999999999999/203417_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.003399999999999999.hdf5 new file mode 100644 index 0000000000..c54ee7671b Binary files /dev/null and b/pycqed/tests/test_data/20180412/203417_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.003399999999999999/203417_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.003399999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/203536_rabi_-VFC_res1_dac_channel_VFCQ6_0.003399999999999999/203536_rabi_-VFC_res1_dac_channel_VFCQ6_0.003399999999999999.hdf5 b/pycqed/tests/test_data/20180412/203536_rabi_-VFC_res1_dac_channel_VFCQ6_0.003399999999999999/203536_rabi_-VFC_res1_dac_channel_VFCQ6_0.003399999999999999.hdf5 new file mode 100644 index 0000000000..32c22b3404 Binary files /dev/null and b/pycqed/tests/test_data/20180412/203536_rabi_-VFC_res1_dac_channel_VFCQ6_0.003399999999999999/203536_rabi_-VFC_res1_dac_channel_VFCQ6_0.003399999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/203555_T1-VFC_res1_dac_channel_VFCQ6_0.003399999999999999/203555_T1-VFC_res1_dac_channel_VFCQ6_0.003399999999999999.hdf5 b/pycqed/tests/test_data/20180412/203555_T1-VFC_res1_dac_channel_VFCQ6_0.003399999999999999/203555_T1-VFC_res1_dac_channel_VFCQ6_0.003399999999999999.hdf5 new file mode 100644 index 0000000000..40f7c1a978 Binary files /dev/null and b/pycqed/tests/test_data/20180412/203555_T1-VFC_res1_dac_channel_VFCQ6_0.003399999999999999/203555_T1-VFC_res1_dac_channel_VFCQ6_0.003399999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/203618_Ramsey-VFC_res1_dac_channel_VFCQ6_0.003399999999999999/203618_Ramsey-VFC_res1_dac_channel_VFCQ6_0.003399999999999999.hdf5 b/pycqed/tests/test_data/20180412/203618_Ramsey-VFC_res1_dac_channel_VFCQ6_0.003399999999999999/203618_Ramsey-VFC_res1_dac_channel_VFCQ6_0.003399999999999999.hdf5 new file mode 100644 index 0000000000..42fae8d414 Binary files /dev/null and b/pycqed/tests/test_data/20180412/203618_Ramsey-VFC_res1_dac_channel_VFCQ6_0.003399999999999999/203618_Ramsey-VFC_res1_dac_channel_VFCQ6_0.003399999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/203645_echo-VFC_res1_dac_channel_VFCQ6_0.003399999999999999/203645_echo-VFC_res1_dac_channel_VFCQ6_0.003399999999999999.hdf5 b/pycqed/tests/test_data/20180412/203645_echo-VFC_res1_dac_channel_VFCQ6_0.003399999999999999/203645_echo-VFC_res1_dac_channel_VFCQ6_0.003399999999999999.hdf5 new file mode 100644 index 0000000000..c1fd0f11e8 Binary files /dev/null and b/pycqed/tests/test_data/20180412/203645_echo-VFC_res1_dac_channel_VFCQ6_0.003399999999999999/203645_echo-VFC_res1_dac_channel_VFCQ6_0.003399999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/203713_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994/203713_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994.hdf5 b/pycqed/tests/test_data/20180412/203713_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994/203713_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994.hdf5 new file mode 100644 index 0000000000..2994b7271a Binary files /dev/null and b/pycqed/tests/test_data/20180412/203713_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994/203713_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/203735_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994/203735_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994.hdf5 b/pycqed/tests/test_data/20180412/203735_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994/203735_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994.hdf5 new file mode 100644 index 0000000000..4d3918a8d7 Binary files /dev/null and b/pycqed/tests/test_data/20180412/203735_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994/203735_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/203854_rabi_-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994/203854_rabi_-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994.hdf5 b/pycqed/tests/test_data/20180412/203854_rabi_-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994/203854_rabi_-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994.hdf5 new file mode 100644 index 0000000000..e8057ad670 Binary files /dev/null and b/pycqed/tests/test_data/20180412/203854_rabi_-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994/203854_rabi_-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/203914_T1-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994/203914_T1-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994.hdf5 b/pycqed/tests/test_data/20180412/203914_T1-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994/203914_T1-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994.hdf5 new file mode 100644 index 0000000000..992b55b3a5 Binary files /dev/null and b/pycqed/tests/test_data/20180412/203914_T1-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994/203914_T1-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/203936_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994/203936_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994.hdf5 b/pycqed/tests/test_data/20180412/203936_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994/203936_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994.hdf5 new file mode 100644 index 0000000000..b33221d987 Binary files /dev/null and b/pycqed/tests/test_data/20180412/203936_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994/203936_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/204004_echo-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994/204004_echo-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994.hdf5 b/pycqed/tests/test_data/20180412/204004_echo-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994/204004_echo-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994.hdf5 new file mode 100644 index 0000000000..bc2d2df561 Binary files /dev/null and b/pycqed/tests/test_data/20180412/204004_echo-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994/204004_echo-VFC_res1_dac_channel_VFCQ6_0.0037499999999999994.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/204031_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995/204031_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995.hdf5 b/pycqed/tests/test_data/20180412/204031_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995/204031_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995.hdf5 new file mode 100644 index 0000000000..70e24a8c32 Binary files /dev/null and b/pycqed/tests/test_data/20180412/204031_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995/204031_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/204053_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995/204053_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995.hdf5 b/pycqed/tests/test_data/20180412/204053_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995/204053_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995.hdf5 new file mode 100644 index 0000000000..203f14e0ba Binary files /dev/null and b/pycqed/tests/test_data/20180412/204053_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995/204053_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/204212_rabi_-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995/204212_rabi_-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995.hdf5 b/pycqed/tests/test_data/20180412/204212_rabi_-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995/204212_rabi_-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995.hdf5 new file mode 100644 index 0000000000..b3d3573bd7 Binary files /dev/null and b/pycqed/tests/test_data/20180412/204212_rabi_-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995/204212_rabi_-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/204233_T1-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995/204233_T1-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995.hdf5 b/pycqed/tests/test_data/20180412/204233_T1-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995/204233_T1-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995.hdf5 new file mode 100644 index 0000000000..51d9e6761f Binary files /dev/null and b/pycqed/tests/test_data/20180412/204233_T1-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995/204233_T1-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/204257_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995/204257_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995.hdf5 b/pycqed/tests/test_data/20180412/204257_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995/204257_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995.hdf5 new file mode 100644 index 0000000000..6d3334fd83 Binary files /dev/null and b/pycqed/tests/test_data/20180412/204257_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995/204257_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/204325_echo-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995/204325_echo-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995.hdf5 b/pycqed/tests/test_data/20180412/204325_echo-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995/204325_echo-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995.hdf5 new file mode 100644 index 0000000000..6fb2abd0b7 Binary files /dev/null and b/pycqed/tests/test_data/20180412/204325_echo-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995/204325_echo-VFC_res1_dac_channel_VFCQ6_0.0040999999999999995.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/204353_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.004449999999999999/204353_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.004449999999999999.hdf5 b/pycqed/tests/test_data/20180412/204353_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.004449999999999999/204353_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.004449999999999999.hdf5 new file mode 100644 index 0000000000..b26390d6c0 Binary files /dev/null and b/pycqed/tests/test_data/20180412/204353_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.004449999999999999/204353_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.004449999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/204416_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.004449999999999999/204416_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.004449999999999999.hdf5 b/pycqed/tests/test_data/20180412/204416_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.004449999999999999/204416_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.004449999999999999.hdf5 new file mode 100644 index 0000000000..de9b5a02ec Binary files /dev/null and b/pycqed/tests/test_data/20180412/204416_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.004449999999999999/204416_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.004449999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/204535_rabi_-VFC_res1_dac_channel_VFCQ6_0.004449999999999999/204535_rabi_-VFC_res1_dac_channel_VFCQ6_0.004449999999999999.hdf5 b/pycqed/tests/test_data/20180412/204535_rabi_-VFC_res1_dac_channel_VFCQ6_0.004449999999999999/204535_rabi_-VFC_res1_dac_channel_VFCQ6_0.004449999999999999.hdf5 new file mode 100644 index 0000000000..46fdbbbb73 Binary files /dev/null and b/pycqed/tests/test_data/20180412/204535_rabi_-VFC_res1_dac_channel_VFCQ6_0.004449999999999999/204535_rabi_-VFC_res1_dac_channel_VFCQ6_0.004449999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/204558_T1-VFC_res1_dac_channel_VFCQ6_0.004449999999999999/204558_T1-VFC_res1_dac_channel_VFCQ6_0.004449999999999999.hdf5 b/pycqed/tests/test_data/20180412/204558_T1-VFC_res1_dac_channel_VFCQ6_0.004449999999999999/204558_T1-VFC_res1_dac_channel_VFCQ6_0.004449999999999999.hdf5 new file mode 100644 index 0000000000..4eca44047e Binary files /dev/null and b/pycqed/tests/test_data/20180412/204558_T1-VFC_res1_dac_channel_VFCQ6_0.004449999999999999/204558_T1-VFC_res1_dac_channel_VFCQ6_0.004449999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/204622_Ramsey-VFC_res1_dac_channel_VFCQ6_0.004449999999999999/204622_Ramsey-VFC_res1_dac_channel_VFCQ6_0.004449999999999999.hdf5 b/pycqed/tests/test_data/20180412/204622_Ramsey-VFC_res1_dac_channel_VFCQ6_0.004449999999999999/204622_Ramsey-VFC_res1_dac_channel_VFCQ6_0.004449999999999999.hdf5 new file mode 100644 index 0000000000..8d209b5c29 Binary files /dev/null and b/pycqed/tests/test_data/20180412/204622_Ramsey-VFC_res1_dac_channel_VFCQ6_0.004449999999999999/204622_Ramsey-VFC_res1_dac_channel_VFCQ6_0.004449999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/204650_echo-VFC_res1_dac_channel_VFCQ6_0.004449999999999999/204650_echo-VFC_res1_dac_channel_VFCQ6_0.004449999999999999.hdf5 b/pycqed/tests/test_data/20180412/204650_echo-VFC_res1_dac_channel_VFCQ6_0.004449999999999999/204650_echo-VFC_res1_dac_channel_VFCQ6_0.004449999999999999.hdf5 new file mode 100644 index 0000000000..dfd351dc96 Binary files /dev/null and b/pycqed/tests/test_data/20180412/204650_echo-VFC_res1_dac_channel_VFCQ6_0.004449999999999999/204650_echo-VFC_res1_dac_channel_VFCQ6_0.004449999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/204718_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.004799999999999999/204718_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.004799999999999999.hdf5 b/pycqed/tests/test_data/20180412/204718_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.004799999999999999/204718_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.004799999999999999.hdf5 new file mode 100644 index 0000000000..ec8c21c517 Binary files /dev/null and b/pycqed/tests/test_data/20180412/204718_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.004799999999999999/204718_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.004799999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/204739_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.004799999999999999/204739_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.004799999999999999.hdf5 b/pycqed/tests/test_data/20180412/204739_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.004799999999999999/204739_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.004799999999999999.hdf5 new file mode 100644 index 0000000000..0f27ed945d Binary files /dev/null and b/pycqed/tests/test_data/20180412/204739_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.004799999999999999/204739_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.004799999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/204858_rabi_-VFC_res1_dac_channel_VFCQ6_0.004799999999999999/204858_rabi_-VFC_res1_dac_channel_VFCQ6_0.004799999999999999.hdf5 b/pycqed/tests/test_data/20180412/204858_rabi_-VFC_res1_dac_channel_VFCQ6_0.004799999999999999/204858_rabi_-VFC_res1_dac_channel_VFCQ6_0.004799999999999999.hdf5 new file mode 100644 index 0000000000..0ea6330309 Binary files /dev/null and b/pycqed/tests/test_data/20180412/204858_rabi_-VFC_res1_dac_channel_VFCQ6_0.004799999999999999/204858_rabi_-VFC_res1_dac_channel_VFCQ6_0.004799999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/204918_T1-VFC_res1_dac_channel_VFCQ6_0.004799999999999999/204918_T1-VFC_res1_dac_channel_VFCQ6_0.004799999999999999.hdf5 b/pycqed/tests/test_data/20180412/204918_T1-VFC_res1_dac_channel_VFCQ6_0.004799999999999999/204918_T1-VFC_res1_dac_channel_VFCQ6_0.004799999999999999.hdf5 new file mode 100644 index 0000000000..9b7af740a0 Binary files /dev/null and b/pycqed/tests/test_data/20180412/204918_T1-VFC_res1_dac_channel_VFCQ6_0.004799999999999999/204918_T1-VFC_res1_dac_channel_VFCQ6_0.004799999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/204941_Ramsey-VFC_res1_dac_channel_VFCQ6_0.004799999999999999/204941_Ramsey-VFC_res1_dac_channel_VFCQ6_0.004799999999999999.hdf5 b/pycqed/tests/test_data/20180412/204941_Ramsey-VFC_res1_dac_channel_VFCQ6_0.004799999999999999/204941_Ramsey-VFC_res1_dac_channel_VFCQ6_0.004799999999999999.hdf5 new file mode 100644 index 0000000000..694076f655 Binary files /dev/null and b/pycqed/tests/test_data/20180412/204941_Ramsey-VFC_res1_dac_channel_VFCQ6_0.004799999999999999/204941_Ramsey-VFC_res1_dac_channel_VFCQ6_0.004799999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/205008_echo-VFC_res1_dac_channel_VFCQ6_0.004799999999999999/205008_echo-VFC_res1_dac_channel_VFCQ6_0.004799999999999999.hdf5 b/pycqed/tests/test_data/20180412/205008_echo-VFC_res1_dac_channel_VFCQ6_0.004799999999999999/205008_echo-VFC_res1_dac_channel_VFCQ6_0.004799999999999999.hdf5 new file mode 100644 index 0000000000..c1d8d52449 Binary files /dev/null and b/pycqed/tests/test_data/20180412/205008_echo-VFC_res1_dac_channel_VFCQ6_0.004799999999999999/205008_echo-VFC_res1_dac_channel_VFCQ6_0.004799999999999999.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/205036_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.005149999999999998/205036_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.005149999999999998.hdf5 b/pycqed/tests/test_data/20180412/205036_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.005149999999999998/205036_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.005149999999999998.hdf5 new file mode 100644 index 0000000000..237833c573 Binary files /dev/null and b/pycqed/tests/test_data/20180412/205036_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.005149999999999998/205036_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.005149999999999998.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/205057_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.005149999999999998/205057_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.005149999999999998.hdf5 b/pycqed/tests/test_data/20180412/205057_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.005149999999999998/205057_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.005149999999999998.hdf5 new file mode 100644 index 0000000000..a0aab9209c Binary files /dev/null and b/pycqed/tests/test_data/20180412/205057_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.005149999999999998/205057_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.005149999999999998.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/205216_rabi_-VFC_res1_dac_channel_VFCQ6_0.005149999999999998/205216_rabi_-VFC_res1_dac_channel_VFCQ6_0.005149999999999998.hdf5 b/pycqed/tests/test_data/20180412/205216_rabi_-VFC_res1_dac_channel_VFCQ6_0.005149999999999998/205216_rabi_-VFC_res1_dac_channel_VFCQ6_0.005149999999999998.hdf5 new file mode 100644 index 0000000000..57a076bc06 Binary files /dev/null and b/pycqed/tests/test_data/20180412/205216_rabi_-VFC_res1_dac_channel_VFCQ6_0.005149999999999998/205216_rabi_-VFC_res1_dac_channel_VFCQ6_0.005149999999999998.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/205237_T1-VFC_res1_dac_channel_VFCQ6_0.005149999999999998/205237_T1-VFC_res1_dac_channel_VFCQ6_0.005149999999999998.hdf5 b/pycqed/tests/test_data/20180412/205237_T1-VFC_res1_dac_channel_VFCQ6_0.005149999999999998/205237_T1-VFC_res1_dac_channel_VFCQ6_0.005149999999999998.hdf5 new file mode 100644 index 0000000000..ab0002e2d6 Binary files /dev/null and b/pycqed/tests/test_data/20180412/205237_T1-VFC_res1_dac_channel_VFCQ6_0.005149999999999998/205237_T1-VFC_res1_dac_channel_VFCQ6_0.005149999999999998.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/205300_Ramsey-VFC_res1_dac_channel_VFCQ6_0.005149999999999998/205300_Ramsey-VFC_res1_dac_channel_VFCQ6_0.005149999999999998.hdf5 b/pycqed/tests/test_data/20180412/205300_Ramsey-VFC_res1_dac_channel_VFCQ6_0.005149999999999998/205300_Ramsey-VFC_res1_dac_channel_VFCQ6_0.005149999999999998.hdf5 new file mode 100644 index 0000000000..2be3858550 Binary files /dev/null and b/pycqed/tests/test_data/20180412/205300_Ramsey-VFC_res1_dac_channel_VFCQ6_0.005149999999999998/205300_Ramsey-VFC_res1_dac_channel_VFCQ6_0.005149999999999998.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/205328_echo-VFC_res1_dac_channel_VFCQ6_0.005149999999999998/205328_echo-VFC_res1_dac_channel_VFCQ6_0.005149999999999998.hdf5 b/pycqed/tests/test_data/20180412/205328_echo-VFC_res1_dac_channel_VFCQ6_0.005149999999999998/205328_echo-VFC_res1_dac_channel_VFCQ6_0.005149999999999998.hdf5 new file mode 100644 index 0000000000..a6ecef891e Binary files /dev/null and b/pycqed/tests/test_data/20180412/205328_echo-VFC_res1_dac_channel_VFCQ6_0.005149999999999998/205328_echo-VFC_res1_dac_channel_VFCQ6_0.005149999999999998.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/205356_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0055/205356_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0055.hdf5 b/pycqed/tests/test_data/20180412/205356_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0055/205356_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0055.hdf5 new file mode 100644 index 0000000000..cf57cde864 Binary files /dev/null and b/pycqed/tests/test_data/20180412/205356_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0055/205356_Resonator_scan-VFC_res1_dac_channel_VFCQ6_0.0055.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/205418_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0055/205418_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0055.hdf5 b/pycqed/tests/test_data/20180412/205418_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0055/205418_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0055.hdf5 new file mode 100644 index 0000000000..268bbccf8c Binary files /dev/null and b/pycqed/tests/test_data/20180412/205418_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0055/205418_spectroscopy_-VFC_res1_dac_channel_VFCQ6_0.0055.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/205536_rabi_-VFC_res1_dac_channel_VFCQ6_0.0055/205536_rabi_-VFC_res1_dac_channel_VFCQ6_0.0055.hdf5 b/pycqed/tests/test_data/20180412/205536_rabi_-VFC_res1_dac_channel_VFCQ6_0.0055/205536_rabi_-VFC_res1_dac_channel_VFCQ6_0.0055.hdf5 new file mode 100644 index 0000000000..698fbbd794 Binary files /dev/null and b/pycqed/tests/test_data/20180412/205536_rabi_-VFC_res1_dac_channel_VFCQ6_0.0055/205536_rabi_-VFC_res1_dac_channel_VFCQ6_0.0055.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/205556_T1-VFC_res1_dac_channel_VFCQ6_0.0055/205556_T1-VFC_res1_dac_channel_VFCQ6_0.0055.hdf5 b/pycqed/tests/test_data/20180412/205556_T1-VFC_res1_dac_channel_VFCQ6_0.0055/205556_T1-VFC_res1_dac_channel_VFCQ6_0.0055.hdf5 new file mode 100644 index 0000000000..51bbb9b698 Binary files /dev/null and b/pycqed/tests/test_data/20180412/205556_T1-VFC_res1_dac_channel_VFCQ6_0.0055/205556_T1-VFC_res1_dac_channel_VFCQ6_0.0055.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/205619_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0055/205619_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0055.hdf5 b/pycqed/tests/test_data/20180412/205619_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0055/205619_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0055.hdf5 new file mode 100644 index 0000000000..99bf38702e Binary files /dev/null and b/pycqed/tests/test_data/20180412/205619_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0055/205619_Ramsey-VFC_res1_dac_channel_VFCQ6_0.0055.hdf5 differ diff --git a/pycqed/tests/test_data/20180412/205647_echo-VFC_res1_dac_channel_VFCQ6_0.0055/205647_echo-VFC_res1_dac_channel_VFCQ6_0.0055.hdf5 b/pycqed/tests/test_data/20180412/205647_echo-VFC_res1_dac_channel_VFCQ6_0.0055/205647_echo-VFC_res1_dac_channel_VFCQ6_0.0055.hdf5 new file mode 100644 index 0000000000..69f1b116ac Binary files /dev/null and b/pycqed/tests/test_data/20180412/205647_echo-VFC_res1_dac_channel_VFCQ6_0.0055/205647_echo-VFC_res1_dac_channel_VFCQ6_0.0055.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/121600_Resonator_scan-VFC_res3_init_/121600_Resonator_scan-VFC_res3_init_.hdf5 b/pycqed/tests/test_data/20180414/121600_Resonator_scan-VFC_res3_init_/121600_Resonator_scan-VFC_res3_init_.hdf5 new file mode 100755 index 0000000000..7d63402933 Binary files /dev/null and b/pycqed/tests/test_data/20180414/121600_Resonator_scan-VFC_res3_init_/121600_Resonator_scan-VFC_res3_init_.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/121728_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-50.0/121728_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-50.0.hdf5 b/pycqed/tests/test_data/20180414/121728_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-50.0/121728_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-50.0.hdf5 new file mode 100755 index 0000000000..d7901f54d3 Binary files /dev/null and b/pycqed/tests/test_data/20180414/121728_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-50.0/121728_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-50.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/121912_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-50.0/121912_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-50.0.hdf5 b/pycqed/tests/test_data/20180414/121912_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-50.0/121912_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-50.0.hdf5 new file mode 100755 index 0000000000..0a2e69e6ed Binary files /dev/null and b/pycqed/tests/test_data/20180414/121912_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-50.0/121912_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-50.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/122058_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-50.0/122058_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-50.0.hdf5 b/pycqed/tests/test_data/20180414/122058_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-50.0/122058_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-50.0.hdf5 new file mode 100755 index 0000000000..9c4c6ef848 Binary files /dev/null and b/pycqed/tests/test_data/20180414/122058_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-50.0/122058_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-50.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/122115_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-50.0/122115_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-50.0.hdf5 b/pycqed/tests/test_data/20180414/122115_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-50.0/122115_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-50.0.hdf5 new file mode 100755 index 0000000000..0892a09727 Binary files /dev/null and b/pycqed/tests/test_data/20180414/122115_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-50.0/122115_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-50.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/122259_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-48.0/122259_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-48.0.hdf5 b/pycqed/tests/test_data/20180414/122259_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-48.0/122259_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-48.0.hdf5 new file mode 100755 index 0000000000..1e007cac5a Binary files /dev/null and b/pycqed/tests/test_data/20180414/122259_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-48.0/122259_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-48.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/122317_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-48.0/122317_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-48.0.hdf5 b/pycqed/tests/test_data/20180414/122317_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-48.0/122317_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-48.0.hdf5 new file mode 100755 index 0000000000..40c919cc8f Binary files /dev/null and b/pycqed/tests/test_data/20180414/122317_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-48.0/122317_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-48.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/122502_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-46.0/122502_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-46.0.hdf5 b/pycqed/tests/test_data/20180414/122502_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-46.0/122502_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-46.0.hdf5 new file mode 100755 index 0000000000..b2c60d59aa Binary files /dev/null and b/pycqed/tests/test_data/20180414/122502_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-46.0/122502_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-46.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/122519_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-46.0/122519_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-46.0.hdf5 b/pycqed/tests/test_data/20180414/122519_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-46.0/122519_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-46.0.hdf5 new file mode 100755 index 0000000000..ee84fa56b0 Binary files /dev/null and b/pycqed/tests/test_data/20180414/122519_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-46.0/122519_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-46.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/122703_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-44.0/122703_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-44.0.hdf5 b/pycqed/tests/test_data/20180414/122703_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-44.0/122703_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-44.0.hdf5 new file mode 100755 index 0000000000..d7cc299a5f Binary files /dev/null and b/pycqed/tests/test_data/20180414/122703_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-44.0/122703_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-44.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/122720_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-44.0/122720_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-44.0.hdf5 b/pycqed/tests/test_data/20180414/122720_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-44.0/122720_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-44.0.hdf5 new file mode 100755 index 0000000000..187821ae33 Binary files /dev/null and b/pycqed/tests/test_data/20180414/122720_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-44.0/122720_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-44.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/122903_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-42.0/122903_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-42.0.hdf5 b/pycqed/tests/test_data/20180414/122903_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-42.0/122903_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-42.0.hdf5 new file mode 100755 index 0000000000..bc756959b0 Binary files /dev/null and b/pycqed/tests/test_data/20180414/122903_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-42.0/122903_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-42.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/122920_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-42.0/122920_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-42.0.hdf5 b/pycqed/tests/test_data/20180414/122920_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-42.0/122920_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-42.0.hdf5 new file mode 100755 index 0000000000..ecad19d70a Binary files /dev/null and b/pycqed/tests/test_data/20180414/122920_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-42.0/122920_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-42.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/123103_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-40.0/123103_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-40.0.hdf5 b/pycqed/tests/test_data/20180414/123103_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-40.0/123103_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-40.0.hdf5 new file mode 100755 index 0000000000..7606d5e650 Binary files /dev/null and b/pycqed/tests/test_data/20180414/123103_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-40.0/123103_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-40.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/123120_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-40.0/123120_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-40.0.hdf5 b/pycqed/tests/test_data/20180414/123120_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-40.0/123120_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-40.0.hdf5 new file mode 100755 index 0000000000..b3437675a0 Binary files /dev/null and b/pycqed/tests/test_data/20180414/123120_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-40.0/123120_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-40.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/123303_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-38.0/123303_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-38.0.hdf5 b/pycqed/tests/test_data/20180414/123303_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-38.0/123303_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-38.0.hdf5 new file mode 100755 index 0000000000..4325d8e0b3 Binary files /dev/null and b/pycqed/tests/test_data/20180414/123303_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-38.0/123303_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-38.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/123320_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-38.0/123320_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-38.0.hdf5 b/pycqed/tests/test_data/20180414/123320_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-38.0/123320_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-38.0.hdf5 new file mode 100755 index 0000000000..5fe15df1c6 Binary files /dev/null and b/pycqed/tests/test_data/20180414/123320_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-38.0/123320_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-38.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/123502_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-36.0/123502_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-36.0.hdf5 b/pycqed/tests/test_data/20180414/123502_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-36.0/123502_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-36.0.hdf5 new file mode 100755 index 0000000000..990259f138 Binary files /dev/null and b/pycqed/tests/test_data/20180414/123502_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-36.0/123502_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-36.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/123519_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-36.0/123519_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-36.0.hdf5 b/pycqed/tests/test_data/20180414/123519_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-36.0/123519_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-36.0.hdf5 new file mode 100755 index 0000000000..409372fc74 Binary files /dev/null and b/pycqed/tests/test_data/20180414/123519_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-36.0/123519_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-36.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/123702_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-34.0/123702_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-34.0.hdf5 b/pycqed/tests/test_data/20180414/123702_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-34.0/123702_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-34.0.hdf5 new file mode 100755 index 0000000000..fb0bb935d8 Binary files /dev/null and b/pycqed/tests/test_data/20180414/123702_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-34.0/123702_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-34.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/123720_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-34.0/123720_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-34.0.hdf5 b/pycqed/tests/test_data/20180414/123720_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-34.0/123720_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-34.0.hdf5 new file mode 100755 index 0000000000..ec6a33e1bb Binary files /dev/null and b/pycqed/tests/test_data/20180414/123720_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-34.0/123720_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-34.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/123903_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-32.0/123903_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-32.0.hdf5 b/pycqed/tests/test_data/20180414/123903_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-32.0/123903_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-32.0.hdf5 new file mode 100755 index 0000000000..b29588448e Binary files /dev/null and b/pycqed/tests/test_data/20180414/123903_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-32.0/123903_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-32.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/123920_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-32.0/123920_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-32.0.hdf5 b/pycqed/tests/test_data/20180414/123920_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-32.0/123920_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-32.0.hdf5 new file mode 100755 index 0000000000..0cf66dc19e Binary files /dev/null and b/pycqed/tests/test_data/20180414/123920_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-32.0/123920_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-32.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/124103_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-30.0/124103_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-30.0.hdf5 b/pycqed/tests/test_data/20180414/124103_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-30.0/124103_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-30.0.hdf5 new file mode 100755 index 0000000000..b1e7b1dd3b Binary files /dev/null and b/pycqed/tests/test_data/20180414/124103_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-30.0/124103_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-30.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/124120_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-30.0/124120_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-30.0.hdf5 b/pycqed/tests/test_data/20180414/124120_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-30.0/124120_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-30.0.hdf5 new file mode 100755 index 0000000000..a9d7a25d55 Binary files /dev/null and b/pycqed/tests/test_data/20180414/124120_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-30.0/124120_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-30.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/124302_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-28.0/124302_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-28.0.hdf5 b/pycqed/tests/test_data/20180414/124302_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-28.0/124302_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-28.0.hdf5 new file mode 100755 index 0000000000..8622471307 Binary files /dev/null and b/pycqed/tests/test_data/20180414/124302_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-28.0/124302_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-28.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/124320_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-28.0/124320_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-28.0.hdf5 b/pycqed/tests/test_data/20180414/124320_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-28.0/124320_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-28.0.hdf5 new file mode 100755 index 0000000000..7b72b47653 Binary files /dev/null and b/pycqed/tests/test_data/20180414/124320_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-28.0/124320_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-28.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/124509_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-26.0/124509_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-26.0.hdf5 b/pycqed/tests/test_data/20180414/124509_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-26.0/124509_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-26.0.hdf5 new file mode 100755 index 0000000000..0501a4c7a4 Binary files /dev/null and b/pycqed/tests/test_data/20180414/124509_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-26.0/124509_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-26.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/124528_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-26.0/124528_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-26.0.hdf5 b/pycqed/tests/test_data/20180414/124528_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-26.0/124528_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-26.0.hdf5 new file mode 100755 index 0000000000..6087dd4eac Binary files /dev/null and b/pycqed/tests/test_data/20180414/124528_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-26.0/124528_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-26.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/124718_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-24.0/124718_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-24.0.hdf5 b/pycqed/tests/test_data/20180414/124718_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-24.0/124718_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-24.0.hdf5 new file mode 100755 index 0000000000..d1e845c8b7 Binary files /dev/null and b/pycqed/tests/test_data/20180414/124718_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-24.0/124718_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-24.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/124734_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-24.0/124734_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-24.0.hdf5 b/pycqed/tests/test_data/20180414/124734_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-24.0/124734_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-24.0.hdf5 new file mode 100755 index 0000000000..a45405eb86 Binary files /dev/null and b/pycqed/tests/test_data/20180414/124734_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-24.0/124734_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-24.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/124917_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-22.0/124917_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-22.0.hdf5 b/pycqed/tests/test_data/20180414/124917_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-22.0/124917_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-22.0.hdf5 new file mode 100755 index 0000000000..7183732ab7 Binary files /dev/null and b/pycqed/tests/test_data/20180414/124917_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-22.0/124917_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-22.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/124935_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-22.0/124935_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-22.0.hdf5 b/pycqed/tests/test_data/20180414/124935_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-22.0/124935_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-22.0.hdf5 new file mode 100755 index 0000000000..a3ac114561 Binary files /dev/null and b/pycqed/tests/test_data/20180414/124935_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-22.0/124935_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-22.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/125118_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-20.0/125118_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-20.0.hdf5 b/pycqed/tests/test_data/20180414/125118_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-20.0/125118_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-20.0.hdf5 new file mode 100755 index 0000000000..3c09e73afe Binary files /dev/null and b/pycqed/tests/test_data/20180414/125118_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-20.0/125118_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-20.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/125135_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-20.0/125135_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-20.0.hdf5 b/pycqed/tests/test_data/20180414/125135_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-20.0/125135_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-20.0.hdf5 new file mode 100755 index 0000000000..0344563ad5 Binary files /dev/null and b/pycqed/tests/test_data/20180414/125135_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-20.0/125135_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-20.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/125320_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-18.0/125320_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-18.0.hdf5 b/pycqed/tests/test_data/20180414/125320_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-18.0/125320_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-18.0.hdf5 new file mode 100755 index 0000000000..3f443fff7a Binary files /dev/null and b/pycqed/tests/test_data/20180414/125320_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-18.0/125320_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-18.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/125337_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-18.0/125337_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-18.0.hdf5 b/pycqed/tests/test_data/20180414/125337_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-18.0/125337_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-18.0.hdf5 new file mode 100755 index 0000000000..d3d7d1c4a6 Binary files /dev/null and b/pycqed/tests/test_data/20180414/125337_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-18.0/125337_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-18.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/125523_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-16.0/125523_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-16.0.hdf5 b/pycqed/tests/test_data/20180414/125523_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-16.0/125523_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-16.0.hdf5 new file mode 100755 index 0000000000..a31bdc62d7 Binary files /dev/null and b/pycqed/tests/test_data/20180414/125523_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-16.0/125523_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-16.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/125540_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-16.0/125540_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-16.0.hdf5 b/pycqed/tests/test_data/20180414/125540_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-16.0/125540_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-16.0.hdf5 new file mode 100755 index 0000000000..ac4dc63d8b Binary files /dev/null and b/pycqed/tests/test_data/20180414/125540_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-16.0/125540_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-16.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/125724_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-14.0/125724_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-14.0.hdf5 b/pycqed/tests/test_data/20180414/125724_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-14.0/125724_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-14.0.hdf5 new file mode 100755 index 0000000000..34a7d85026 Binary files /dev/null and b/pycqed/tests/test_data/20180414/125724_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-14.0/125724_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-14.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/125744_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-14.0/125744_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-14.0.hdf5 b/pycqed/tests/test_data/20180414/125744_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-14.0/125744_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-14.0.hdf5 new file mode 100755 index 0000000000..43b88d0ab7 Binary files /dev/null and b/pycqed/tests/test_data/20180414/125744_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-14.0/125744_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-14.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/125927_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-12.0/125927_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-12.0.hdf5 b/pycqed/tests/test_data/20180414/125927_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-12.0/125927_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-12.0.hdf5 new file mode 100755 index 0000000000..36ae4292f3 Binary files /dev/null and b/pycqed/tests/test_data/20180414/125927_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-12.0/125927_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-12.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/125945_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-12.0/125945_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-12.0.hdf5 b/pycqed/tests/test_data/20180414/125945_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-12.0/125945_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-12.0.hdf5 new file mode 100755 index 0000000000..312a0a17b4 Binary files /dev/null and b/pycqed/tests/test_data/20180414/125945_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-12.0/125945_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-12.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/130127_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-10.0/130127_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-10.0.hdf5 b/pycqed/tests/test_data/20180414/130127_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-10.0/130127_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-10.0.hdf5 new file mode 100755 index 0000000000..964b4eb621 Binary files /dev/null and b/pycqed/tests/test_data/20180414/130127_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-10.0/130127_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-10.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/130147_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-10.0/130147_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-10.0.hdf5 b/pycqed/tests/test_data/20180414/130147_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-10.0/130147_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-10.0.hdf5 new file mode 100755 index 0000000000..8efda0a634 Binary files /dev/null and b/pycqed/tests/test_data/20180414/130147_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-10.0/130147_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-10.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/130329_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-8.0/130329_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-8.0.hdf5 b/pycqed/tests/test_data/20180414/130329_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-8.0/130329_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-8.0.hdf5 new file mode 100755 index 0000000000..07190a8186 Binary files /dev/null and b/pycqed/tests/test_data/20180414/130329_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-8.0/130329_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-8.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/130347_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-8.0/130347_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-8.0.hdf5 b/pycqed/tests/test_data/20180414/130347_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-8.0/130347_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-8.0.hdf5 new file mode 100755 index 0000000000..5124ba923d Binary files /dev/null and b/pycqed/tests/test_data/20180414/130347_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-8.0/130347_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-8.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/130531_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-6.0/130531_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-6.0.hdf5 b/pycqed/tests/test_data/20180414/130531_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-6.0/130531_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-6.0.hdf5 new file mode 100755 index 0000000000..a1e174fef4 Binary files /dev/null and b/pycqed/tests/test_data/20180414/130531_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-6.0/130531_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-6.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/130548_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-6.0/130548_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-6.0.hdf5 b/pycqed/tests/test_data/20180414/130548_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-6.0/130548_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-6.0.hdf5 new file mode 100755 index 0000000000..aa1d5a38c0 Binary files /dev/null and b/pycqed/tests/test_data/20180414/130548_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-6.0/130548_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-6.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/130731_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-4.0/130731_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-4.0.hdf5 b/pycqed/tests/test_data/20180414/130731_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-4.0/130731_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-4.0.hdf5 new file mode 100755 index 0000000000..9d7a8eeedd Binary files /dev/null and b/pycqed/tests/test_data/20180414/130731_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-4.0/130731_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-4.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/130748_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-4.0/130748_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-4.0.hdf5 b/pycqed/tests/test_data/20180414/130748_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-4.0/130748_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-4.0.hdf5 new file mode 100755 index 0000000000..eb1ccb74a0 Binary files /dev/null and b/pycqed/tests/test_data/20180414/130748_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-4.0/130748_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-4.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/130930_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-2.0/130930_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-2.0.hdf5 b/pycqed/tests/test_data/20180414/130930_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-2.0/130930_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-2.0.hdf5 new file mode 100755 index 0000000000..3785b5190d Binary files /dev/null and b/pycqed/tests/test_data/20180414/130930_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-2.0/130930_Resonator_scan-VFC_res3_dac_channel_VFCQ6_-2.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/130947_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-2.0/130947_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-2.0.hdf5 b/pycqed/tests/test_data/20180414/130947_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-2.0/130947_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-2.0.hdf5 new file mode 100755 index 0000000000..91f2a8ee95 Binary files /dev/null and b/pycqed/tests/test_data/20180414/130947_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-2.0/130947_spectroscopy_-VFC_res3_dac_channel_VFCQ6_-2.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/131132_Resonator_scan-VFC_res3_dac_channel_VFCQ6_0.0/131132_Resonator_scan-VFC_res3_dac_channel_VFCQ6_0.0.hdf5 b/pycqed/tests/test_data/20180414/131132_Resonator_scan-VFC_res3_dac_channel_VFCQ6_0.0/131132_Resonator_scan-VFC_res3_dac_channel_VFCQ6_0.0.hdf5 new file mode 100755 index 0000000000..fc53490903 Binary files /dev/null and b/pycqed/tests/test_data/20180414/131132_Resonator_scan-VFC_res3_dac_channel_VFCQ6_0.0/131132_Resonator_scan-VFC_res3_dac_channel_VFCQ6_0.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/131149_spectroscopy_-VFC_res3_dac_channel_VFCQ6_0.0/131149_spectroscopy_-VFC_res3_dac_channel_VFCQ6_0.0.hdf5 b/pycqed/tests/test_data/20180414/131149_spectroscopy_-VFC_res3_dac_channel_VFCQ6_0.0/131149_spectroscopy_-VFC_res3_dac_channel_VFCQ6_0.0.hdf5 new file mode 100755 index 0000000000..afca4879c3 Binary files /dev/null and b/pycqed/tests/test_data/20180414/131149_spectroscopy_-VFC_res3_dac_channel_VFCQ6_0.0/131149_spectroscopy_-VFC_res3_dac_channel_VFCQ6_0.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/131333_Resonator_scan-VFC_res3_dac_channel_VFCQ6_2.0/131333_Resonator_scan-VFC_res3_dac_channel_VFCQ6_2.0.hdf5 b/pycqed/tests/test_data/20180414/131333_Resonator_scan-VFC_res3_dac_channel_VFCQ6_2.0/131333_Resonator_scan-VFC_res3_dac_channel_VFCQ6_2.0.hdf5 new file mode 100755 index 0000000000..a9a0448540 Binary files /dev/null and b/pycqed/tests/test_data/20180414/131333_Resonator_scan-VFC_res3_dac_channel_VFCQ6_2.0/131333_Resonator_scan-VFC_res3_dac_channel_VFCQ6_2.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/131353_spectroscopy_-VFC_res3_dac_channel_VFCQ6_2.0/131353_spectroscopy_-VFC_res3_dac_channel_VFCQ6_2.0.hdf5 b/pycqed/tests/test_data/20180414/131353_spectroscopy_-VFC_res3_dac_channel_VFCQ6_2.0/131353_spectroscopy_-VFC_res3_dac_channel_VFCQ6_2.0.hdf5 new file mode 100755 index 0000000000..bfe0299ec8 Binary files /dev/null and b/pycqed/tests/test_data/20180414/131353_spectroscopy_-VFC_res3_dac_channel_VFCQ6_2.0/131353_spectroscopy_-VFC_res3_dac_channel_VFCQ6_2.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/131537_Resonator_scan-VFC_res3_dac_channel_VFCQ6_4.0/131537_Resonator_scan-VFC_res3_dac_channel_VFCQ6_4.0.hdf5 b/pycqed/tests/test_data/20180414/131537_Resonator_scan-VFC_res3_dac_channel_VFCQ6_4.0/131537_Resonator_scan-VFC_res3_dac_channel_VFCQ6_4.0.hdf5 new file mode 100755 index 0000000000..02d8735426 Binary files /dev/null and b/pycqed/tests/test_data/20180414/131537_Resonator_scan-VFC_res3_dac_channel_VFCQ6_4.0/131537_Resonator_scan-VFC_res3_dac_channel_VFCQ6_4.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/131559_spectroscopy_-VFC_res3_dac_channel_VFCQ6_4.0/131559_spectroscopy_-VFC_res3_dac_channel_VFCQ6_4.0.hdf5 b/pycqed/tests/test_data/20180414/131559_spectroscopy_-VFC_res3_dac_channel_VFCQ6_4.0/131559_spectroscopy_-VFC_res3_dac_channel_VFCQ6_4.0.hdf5 new file mode 100755 index 0000000000..8a772ac475 Binary files /dev/null and b/pycqed/tests/test_data/20180414/131559_spectroscopy_-VFC_res3_dac_channel_VFCQ6_4.0/131559_spectroscopy_-VFC_res3_dac_channel_VFCQ6_4.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/133613_Resonator_scan-VFC_res3_dac_channel_VFCQ6_6.0/133613_Resonator_scan-VFC_res3_dac_channel_VFCQ6_6.0.hdf5 b/pycqed/tests/test_data/20180414/133613_Resonator_scan-VFC_res3_dac_channel_VFCQ6_6.0/133613_Resonator_scan-VFC_res3_dac_channel_VFCQ6_6.0.hdf5 new file mode 100755 index 0000000000..5b0ca85014 Binary files /dev/null and b/pycqed/tests/test_data/20180414/133613_Resonator_scan-VFC_res3_dac_channel_VFCQ6_6.0/133613_Resonator_scan-VFC_res3_dac_channel_VFCQ6_6.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/133630_spectroscopy_-VFC_res3_dac_channel_VFCQ6_6.0/133630_spectroscopy_-VFC_res3_dac_channel_VFCQ6_6.0.hdf5 b/pycqed/tests/test_data/20180414/133630_spectroscopy_-VFC_res3_dac_channel_VFCQ6_6.0/133630_spectroscopy_-VFC_res3_dac_channel_VFCQ6_6.0.hdf5 new file mode 100755 index 0000000000..ca69d434a1 Binary files /dev/null and b/pycqed/tests/test_data/20180414/133630_spectroscopy_-VFC_res3_dac_channel_VFCQ6_6.0/133630_spectroscopy_-VFC_res3_dac_channel_VFCQ6_6.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/133813_Resonator_scan-VFC_res3_dac_channel_VFCQ6_8.0/133813_Resonator_scan-VFC_res3_dac_channel_VFCQ6_8.0.hdf5 b/pycqed/tests/test_data/20180414/133813_Resonator_scan-VFC_res3_dac_channel_VFCQ6_8.0/133813_Resonator_scan-VFC_res3_dac_channel_VFCQ6_8.0.hdf5 new file mode 100755 index 0000000000..72a0845ef5 Binary files /dev/null and b/pycqed/tests/test_data/20180414/133813_Resonator_scan-VFC_res3_dac_channel_VFCQ6_8.0/133813_Resonator_scan-VFC_res3_dac_channel_VFCQ6_8.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/133830_spectroscopy_-VFC_res3_dac_channel_VFCQ6_8.0/133830_spectroscopy_-VFC_res3_dac_channel_VFCQ6_8.0.hdf5 b/pycqed/tests/test_data/20180414/133830_spectroscopy_-VFC_res3_dac_channel_VFCQ6_8.0/133830_spectroscopy_-VFC_res3_dac_channel_VFCQ6_8.0.hdf5 new file mode 100755 index 0000000000..bc27f83ca5 Binary files /dev/null and b/pycqed/tests/test_data/20180414/133830_spectroscopy_-VFC_res3_dac_channel_VFCQ6_8.0/133830_spectroscopy_-VFC_res3_dac_channel_VFCQ6_8.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/134012_Resonator_scan-VFC_res3_dac_channel_VFCQ6_10.0/134012_Resonator_scan-VFC_res3_dac_channel_VFCQ6_10.0.hdf5 b/pycqed/tests/test_data/20180414/134012_Resonator_scan-VFC_res3_dac_channel_VFCQ6_10.0/134012_Resonator_scan-VFC_res3_dac_channel_VFCQ6_10.0.hdf5 new file mode 100755 index 0000000000..d0102f1af2 Binary files /dev/null and b/pycqed/tests/test_data/20180414/134012_Resonator_scan-VFC_res3_dac_channel_VFCQ6_10.0/134012_Resonator_scan-VFC_res3_dac_channel_VFCQ6_10.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/134029_spectroscopy_-VFC_res3_dac_channel_VFCQ6_10.0/134029_spectroscopy_-VFC_res3_dac_channel_VFCQ6_10.0.hdf5 b/pycqed/tests/test_data/20180414/134029_spectroscopy_-VFC_res3_dac_channel_VFCQ6_10.0/134029_spectroscopy_-VFC_res3_dac_channel_VFCQ6_10.0.hdf5 new file mode 100755 index 0000000000..dbf1b18578 Binary files /dev/null and b/pycqed/tests/test_data/20180414/134029_spectroscopy_-VFC_res3_dac_channel_VFCQ6_10.0/134029_spectroscopy_-VFC_res3_dac_channel_VFCQ6_10.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/134211_Resonator_scan-VFC_res3_dac_channel_VFCQ6_12.0/134211_Resonator_scan-VFC_res3_dac_channel_VFCQ6_12.0.hdf5 b/pycqed/tests/test_data/20180414/134211_Resonator_scan-VFC_res3_dac_channel_VFCQ6_12.0/134211_Resonator_scan-VFC_res3_dac_channel_VFCQ6_12.0.hdf5 new file mode 100755 index 0000000000..40960ffae9 Binary files /dev/null and b/pycqed/tests/test_data/20180414/134211_Resonator_scan-VFC_res3_dac_channel_VFCQ6_12.0/134211_Resonator_scan-VFC_res3_dac_channel_VFCQ6_12.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/134228_spectroscopy_-VFC_res3_dac_channel_VFCQ6_12.0/134228_spectroscopy_-VFC_res3_dac_channel_VFCQ6_12.0.hdf5 b/pycqed/tests/test_data/20180414/134228_spectroscopy_-VFC_res3_dac_channel_VFCQ6_12.0/134228_spectroscopy_-VFC_res3_dac_channel_VFCQ6_12.0.hdf5 new file mode 100755 index 0000000000..0e5f64742a Binary files /dev/null and b/pycqed/tests/test_data/20180414/134228_spectroscopy_-VFC_res3_dac_channel_VFCQ6_12.0/134228_spectroscopy_-VFC_res3_dac_channel_VFCQ6_12.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/134410_Resonator_scan-VFC_res3_dac_channel_VFCQ6_14.0/134410_Resonator_scan-VFC_res3_dac_channel_VFCQ6_14.0.hdf5 b/pycqed/tests/test_data/20180414/134410_Resonator_scan-VFC_res3_dac_channel_VFCQ6_14.0/134410_Resonator_scan-VFC_res3_dac_channel_VFCQ6_14.0.hdf5 new file mode 100755 index 0000000000..0d648e6e10 Binary files /dev/null and b/pycqed/tests/test_data/20180414/134410_Resonator_scan-VFC_res3_dac_channel_VFCQ6_14.0/134410_Resonator_scan-VFC_res3_dac_channel_VFCQ6_14.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/134427_spectroscopy_-VFC_res3_dac_channel_VFCQ6_14.0/134427_spectroscopy_-VFC_res3_dac_channel_VFCQ6_14.0.hdf5 b/pycqed/tests/test_data/20180414/134427_spectroscopy_-VFC_res3_dac_channel_VFCQ6_14.0/134427_spectroscopy_-VFC_res3_dac_channel_VFCQ6_14.0.hdf5 new file mode 100755 index 0000000000..42cf164cad Binary files /dev/null and b/pycqed/tests/test_data/20180414/134427_spectroscopy_-VFC_res3_dac_channel_VFCQ6_14.0/134427_spectroscopy_-VFC_res3_dac_channel_VFCQ6_14.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/134609_Resonator_scan-VFC_res3_dac_channel_VFCQ6_16.0/134609_Resonator_scan-VFC_res3_dac_channel_VFCQ6_16.0.hdf5 b/pycqed/tests/test_data/20180414/134609_Resonator_scan-VFC_res3_dac_channel_VFCQ6_16.0/134609_Resonator_scan-VFC_res3_dac_channel_VFCQ6_16.0.hdf5 new file mode 100755 index 0000000000..721134b035 Binary files /dev/null and b/pycqed/tests/test_data/20180414/134609_Resonator_scan-VFC_res3_dac_channel_VFCQ6_16.0/134609_Resonator_scan-VFC_res3_dac_channel_VFCQ6_16.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/134627_spectroscopy_-VFC_res3_dac_channel_VFCQ6_16.0/134627_spectroscopy_-VFC_res3_dac_channel_VFCQ6_16.0.hdf5 b/pycqed/tests/test_data/20180414/134627_spectroscopy_-VFC_res3_dac_channel_VFCQ6_16.0/134627_spectroscopy_-VFC_res3_dac_channel_VFCQ6_16.0.hdf5 new file mode 100755 index 0000000000..916129cfb2 Binary files /dev/null and b/pycqed/tests/test_data/20180414/134627_spectroscopy_-VFC_res3_dac_channel_VFCQ6_16.0/134627_spectroscopy_-VFC_res3_dac_channel_VFCQ6_16.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/134810_Resonator_scan-VFC_res3_dac_channel_VFCQ6_18.0/134810_Resonator_scan-VFC_res3_dac_channel_VFCQ6_18.0.hdf5 b/pycqed/tests/test_data/20180414/134810_Resonator_scan-VFC_res3_dac_channel_VFCQ6_18.0/134810_Resonator_scan-VFC_res3_dac_channel_VFCQ6_18.0.hdf5 new file mode 100755 index 0000000000..873ef3080e Binary files /dev/null and b/pycqed/tests/test_data/20180414/134810_Resonator_scan-VFC_res3_dac_channel_VFCQ6_18.0/134810_Resonator_scan-VFC_res3_dac_channel_VFCQ6_18.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/134827_spectroscopy_-VFC_res3_dac_channel_VFCQ6_18.0/134827_spectroscopy_-VFC_res3_dac_channel_VFCQ6_18.0.hdf5 b/pycqed/tests/test_data/20180414/134827_spectroscopy_-VFC_res3_dac_channel_VFCQ6_18.0/134827_spectroscopy_-VFC_res3_dac_channel_VFCQ6_18.0.hdf5 new file mode 100755 index 0000000000..13a671e269 Binary files /dev/null and b/pycqed/tests/test_data/20180414/134827_spectroscopy_-VFC_res3_dac_channel_VFCQ6_18.0/134827_spectroscopy_-VFC_res3_dac_channel_VFCQ6_18.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/135009_Resonator_scan-VFC_res3_dac_channel_VFCQ6_20.0/135009_Resonator_scan-VFC_res3_dac_channel_VFCQ6_20.0.hdf5 b/pycqed/tests/test_data/20180414/135009_Resonator_scan-VFC_res3_dac_channel_VFCQ6_20.0/135009_Resonator_scan-VFC_res3_dac_channel_VFCQ6_20.0.hdf5 new file mode 100755 index 0000000000..26aebfea0a Binary files /dev/null and b/pycqed/tests/test_data/20180414/135009_Resonator_scan-VFC_res3_dac_channel_VFCQ6_20.0/135009_Resonator_scan-VFC_res3_dac_channel_VFCQ6_20.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/135027_spectroscopy_-VFC_res3_dac_channel_VFCQ6_20.0/135027_spectroscopy_-VFC_res3_dac_channel_VFCQ6_20.0.hdf5 b/pycqed/tests/test_data/20180414/135027_spectroscopy_-VFC_res3_dac_channel_VFCQ6_20.0/135027_spectroscopy_-VFC_res3_dac_channel_VFCQ6_20.0.hdf5 new file mode 100755 index 0000000000..ac5d57c34f Binary files /dev/null and b/pycqed/tests/test_data/20180414/135027_spectroscopy_-VFC_res3_dac_channel_VFCQ6_20.0/135027_spectroscopy_-VFC_res3_dac_channel_VFCQ6_20.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/135209_Resonator_scan-VFC_res3_dac_channel_VFCQ6_22.0/135209_Resonator_scan-VFC_res3_dac_channel_VFCQ6_22.0.hdf5 b/pycqed/tests/test_data/20180414/135209_Resonator_scan-VFC_res3_dac_channel_VFCQ6_22.0/135209_Resonator_scan-VFC_res3_dac_channel_VFCQ6_22.0.hdf5 new file mode 100755 index 0000000000..43b9d2aea3 Binary files /dev/null and b/pycqed/tests/test_data/20180414/135209_Resonator_scan-VFC_res3_dac_channel_VFCQ6_22.0/135209_Resonator_scan-VFC_res3_dac_channel_VFCQ6_22.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/135227_spectroscopy_-VFC_res3_dac_channel_VFCQ6_22.0/135227_spectroscopy_-VFC_res3_dac_channel_VFCQ6_22.0.hdf5 b/pycqed/tests/test_data/20180414/135227_spectroscopy_-VFC_res3_dac_channel_VFCQ6_22.0/135227_spectroscopy_-VFC_res3_dac_channel_VFCQ6_22.0.hdf5 new file mode 100755 index 0000000000..2b5dab19a5 Binary files /dev/null and b/pycqed/tests/test_data/20180414/135227_spectroscopy_-VFC_res3_dac_channel_VFCQ6_22.0/135227_spectroscopy_-VFC_res3_dac_channel_VFCQ6_22.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/135414_Resonator_scan-VFC_res3_dac_channel_VFCQ6_24.0/135414_Resonator_scan-VFC_res3_dac_channel_VFCQ6_24.0.hdf5 b/pycqed/tests/test_data/20180414/135414_Resonator_scan-VFC_res3_dac_channel_VFCQ6_24.0/135414_Resonator_scan-VFC_res3_dac_channel_VFCQ6_24.0.hdf5 new file mode 100755 index 0000000000..d79fb6390a Binary files /dev/null and b/pycqed/tests/test_data/20180414/135414_Resonator_scan-VFC_res3_dac_channel_VFCQ6_24.0/135414_Resonator_scan-VFC_res3_dac_channel_VFCQ6_24.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/135431_spectroscopy_-VFC_res3_dac_channel_VFCQ6_24.0/135431_spectroscopy_-VFC_res3_dac_channel_VFCQ6_24.0.hdf5 b/pycqed/tests/test_data/20180414/135431_spectroscopy_-VFC_res3_dac_channel_VFCQ6_24.0/135431_spectroscopy_-VFC_res3_dac_channel_VFCQ6_24.0.hdf5 new file mode 100755 index 0000000000..5af3ed1b09 Binary files /dev/null and b/pycqed/tests/test_data/20180414/135431_spectroscopy_-VFC_res3_dac_channel_VFCQ6_24.0/135431_spectroscopy_-VFC_res3_dac_channel_VFCQ6_24.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/135614_Resonator_scan-VFC_res3_dac_channel_VFCQ6_26.0/135614_Resonator_scan-VFC_res3_dac_channel_VFCQ6_26.0.hdf5 b/pycqed/tests/test_data/20180414/135614_Resonator_scan-VFC_res3_dac_channel_VFCQ6_26.0/135614_Resonator_scan-VFC_res3_dac_channel_VFCQ6_26.0.hdf5 new file mode 100755 index 0000000000..d2bf8fae12 Binary files /dev/null and b/pycqed/tests/test_data/20180414/135614_Resonator_scan-VFC_res3_dac_channel_VFCQ6_26.0/135614_Resonator_scan-VFC_res3_dac_channel_VFCQ6_26.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/135632_spectroscopy_-VFC_res3_dac_channel_VFCQ6_26.0/135632_spectroscopy_-VFC_res3_dac_channel_VFCQ6_26.0.hdf5 b/pycqed/tests/test_data/20180414/135632_spectroscopy_-VFC_res3_dac_channel_VFCQ6_26.0/135632_spectroscopy_-VFC_res3_dac_channel_VFCQ6_26.0.hdf5 new file mode 100755 index 0000000000..2859e73331 Binary files /dev/null and b/pycqed/tests/test_data/20180414/135632_spectroscopy_-VFC_res3_dac_channel_VFCQ6_26.0/135632_spectroscopy_-VFC_res3_dac_channel_VFCQ6_26.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/135815_Resonator_scan-VFC_res3_dac_channel_VFCQ6_28.0/135815_Resonator_scan-VFC_res3_dac_channel_VFCQ6_28.0.hdf5 b/pycqed/tests/test_data/20180414/135815_Resonator_scan-VFC_res3_dac_channel_VFCQ6_28.0/135815_Resonator_scan-VFC_res3_dac_channel_VFCQ6_28.0.hdf5 new file mode 100755 index 0000000000..8c56ab2364 Binary files /dev/null and b/pycqed/tests/test_data/20180414/135815_Resonator_scan-VFC_res3_dac_channel_VFCQ6_28.0/135815_Resonator_scan-VFC_res3_dac_channel_VFCQ6_28.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/135832_spectroscopy_-VFC_res3_dac_channel_VFCQ6_28.0/135832_spectroscopy_-VFC_res3_dac_channel_VFCQ6_28.0.hdf5 b/pycqed/tests/test_data/20180414/135832_spectroscopy_-VFC_res3_dac_channel_VFCQ6_28.0/135832_spectroscopy_-VFC_res3_dac_channel_VFCQ6_28.0.hdf5 new file mode 100755 index 0000000000..840b067b68 Binary files /dev/null and b/pycqed/tests/test_data/20180414/135832_spectroscopy_-VFC_res3_dac_channel_VFCQ6_28.0/135832_spectroscopy_-VFC_res3_dac_channel_VFCQ6_28.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/140014_Resonator_scan-VFC_res3_dac_channel_VFCQ6_30.0/140014_Resonator_scan-VFC_res3_dac_channel_VFCQ6_30.0.hdf5 b/pycqed/tests/test_data/20180414/140014_Resonator_scan-VFC_res3_dac_channel_VFCQ6_30.0/140014_Resonator_scan-VFC_res3_dac_channel_VFCQ6_30.0.hdf5 new file mode 100755 index 0000000000..30bb836e63 Binary files /dev/null and b/pycqed/tests/test_data/20180414/140014_Resonator_scan-VFC_res3_dac_channel_VFCQ6_30.0/140014_Resonator_scan-VFC_res3_dac_channel_VFCQ6_30.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/140031_spectroscopy_-VFC_res3_dac_channel_VFCQ6_30.0/140031_spectroscopy_-VFC_res3_dac_channel_VFCQ6_30.0.hdf5 b/pycqed/tests/test_data/20180414/140031_spectroscopy_-VFC_res3_dac_channel_VFCQ6_30.0/140031_spectroscopy_-VFC_res3_dac_channel_VFCQ6_30.0.hdf5 new file mode 100755 index 0000000000..affb981db9 Binary files /dev/null and b/pycqed/tests/test_data/20180414/140031_spectroscopy_-VFC_res3_dac_channel_VFCQ6_30.0/140031_spectroscopy_-VFC_res3_dac_channel_VFCQ6_30.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/140213_Resonator_scan-VFC_res3_dac_channel_VFCQ6_32.0/140213_Resonator_scan-VFC_res3_dac_channel_VFCQ6_32.0.hdf5 b/pycqed/tests/test_data/20180414/140213_Resonator_scan-VFC_res3_dac_channel_VFCQ6_32.0/140213_Resonator_scan-VFC_res3_dac_channel_VFCQ6_32.0.hdf5 new file mode 100755 index 0000000000..b82f101474 Binary files /dev/null and b/pycqed/tests/test_data/20180414/140213_Resonator_scan-VFC_res3_dac_channel_VFCQ6_32.0/140213_Resonator_scan-VFC_res3_dac_channel_VFCQ6_32.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/140232_spectroscopy_-VFC_res3_dac_channel_VFCQ6_32.0/140232_spectroscopy_-VFC_res3_dac_channel_VFCQ6_32.0.hdf5 b/pycqed/tests/test_data/20180414/140232_spectroscopy_-VFC_res3_dac_channel_VFCQ6_32.0/140232_spectroscopy_-VFC_res3_dac_channel_VFCQ6_32.0.hdf5 new file mode 100755 index 0000000000..96764de6fb Binary files /dev/null and b/pycqed/tests/test_data/20180414/140232_spectroscopy_-VFC_res3_dac_channel_VFCQ6_32.0/140232_spectroscopy_-VFC_res3_dac_channel_VFCQ6_32.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/140414_Resonator_scan-VFC_res3_dac_channel_VFCQ6_34.0/140414_Resonator_scan-VFC_res3_dac_channel_VFCQ6_34.0.hdf5 b/pycqed/tests/test_data/20180414/140414_Resonator_scan-VFC_res3_dac_channel_VFCQ6_34.0/140414_Resonator_scan-VFC_res3_dac_channel_VFCQ6_34.0.hdf5 new file mode 100755 index 0000000000..48541449fc Binary files /dev/null and b/pycqed/tests/test_data/20180414/140414_Resonator_scan-VFC_res3_dac_channel_VFCQ6_34.0/140414_Resonator_scan-VFC_res3_dac_channel_VFCQ6_34.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/140431_spectroscopy_-VFC_res3_dac_channel_VFCQ6_34.0/140431_spectroscopy_-VFC_res3_dac_channel_VFCQ6_34.0.hdf5 b/pycqed/tests/test_data/20180414/140431_spectroscopy_-VFC_res3_dac_channel_VFCQ6_34.0/140431_spectroscopy_-VFC_res3_dac_channel_VFCQ6_34.0.hdf5 new file mode 100755 index 0000000000..2c5f39d523 Binary files /dev/null and b/pycqed/tests/test_data/20180414/140431_spectroscopy_-VFC_res3_dac_channel_VFCQ6_34.0/140431_spectroscopy_-VFC_res3_dac_channel_VFCQ6_34.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/140613_Resonator_scan-VFC_res3_dac_channel_VFCQ6_36.0/140613_Resonator_scan-VFC_res3_dac_channel_VFCQ6_36.0.hdf5 b/pycqed/tests/test_data/20180414/140613_Resonator_scan-VFC_res3_dac_channel_VFCQ6_36.0/140613_Resonator_scan-VFC_res3_dac_channel_VFCQ6_36.0.hdf5 new file mode 100755 index 0000000000..eb465c986a Binary files /dev/null and b/pycqed/tests/test_data/20180414/140613_Resonator_scan-VFC_res3_dac_channel_VFCQ6_36.0/140613_Resonator_scan-VFC_res3_dac_channel_VFCQ6_36.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/140630_spectroscopy_-VFC_res3_dac_channel_VFCQ6_36.0/140630_spectroscopy_-VFC_res3_dac_channel_VFCQ6_36.0.hdf5 b/pycqed/tests/test_data/20180414/140630_spectroscopy_-VFC_res3_dac_channel_VFCQ6_36.0/140630_spectroscopy_-VFC_res3_dac_channel_VFCQ6_36.0.hdf5 new file mode 100755 index 0000000000..571a403235 Binary files /dev/null and b/pycqed/tests/test_data/20180414/140630_spectroscopy_-VFC_res3_dac_channel_VFCQ6_36.0/140630_spectroscopy_-VFC_res3_dac_channel_VFCQ6_36.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/140812_Resonator_scan-VFC_res3_dac_channel_VFCQ6_38.0/140812_Resonator_scan-VFC_res3_dac_channel_VFCQ6_38.0.hdf5 b/pycqed/tests/test_data/20180414/140812_Resonator_scan-VFC_res3_dac_channel_VFCQ6_38.0/140812_Resonator_scan-VFC_res3_dac_channel_VFCQ6_38.0.hdf5 new file mode 100755 index 0000000000..44214307c0 Binary files /dev/null and b/pycqed/tests/test_data/20180414/140812_Resonator_scan-VFC_res3_dac_channel_VFCQ6_38.0/140812_Resonator_scan-VFC_res3_dac_channel_VFCQ6_38.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/140829_spectroscopy_-VFC_res3_dac_channel_VFCQ6_38.0/140829_spectroscopy_-VFC_res3_dac_channel_VFCQ6_38.0.hdf5 b/pycqed/tests/test_data/20180414/140829_spectroscopy_-VFC_res3_dac_channel_VFCQ6_38.0/140829_spectroscopy_-VFC_res3_dac_channel_VFCQ6_38.0.hdf5 new file mode 100755 index 0000000000..7776b990f0 Binary files /dev/null and b/pycqed/tests/test_data/20180414/140829_spectroscopy_-VFC_res3_dac_channel_VFCQ6_38.0/140829_spectroscopy_-VFC_res3_dac_channel_VFCQ6_38.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/141011_Resonator_scan-VFC_res3_dac_channel_VFCQ6_40.0/141011_Resonator_scan-VFC_res3_dac_channel_VFCQ6_40.0.hdf5 b/pycqed/tests/test_data/20180414/141011_Resonator_scan-VFC_res3_dac_channel_VFCQ6_40.0/141011_Resonator_scan-VFC_res3_dac_channel_VFCQ6_40.0.hdf5 new file mode 100755 index 0000000000..5914343a16 Binary files /dev/null and b/pycqed/tests/test_data/20180414/141011_Resonator_scan-VFC_res3_dac_channel_VFCQ6_40.0/141011_Resonator_scan-VFC_res3_dac_channel_VFCQ6_40.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/141028_spectroscopy_-VFC_res3_dac_channel_VFCQ6_40.0/141028_spectroscopy_-VFC_res3_dac_channel_VFCQ6_40.0.hdf5 b/pycqed/tests/test_data/20180414/141028_spectroscopy_-VFC_res3_dac_channel_VFCQ6_40.0/141028_spectroscopy_-VFC_res3_dac_channel_VFCQ6_40.0.hdf5 new file mode 100755 index 0000000000..2a9d68f22b Binary files /dev/null and b/pycqed/tests/test_data/20180414/141028_spectroscopy_-VFC_res3_dac_channel_VFCQ6_40.0/141028_spectroscopy_-VFC_res3_dac_channel_VFCQ6_40.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/141210_Resonator_scan-VFC_res3_dac_channel_VFCQ6_42.0/141210_Resonator_scan-VFC_res3_dac_channel_VFCQ6_42.0.hdf5 b/pycqed/tests/test_data/20180414/141210_Resonator_scan-VFC_res3_dac_channel_VFCQ6_42.0/141210_Resonator_scan-VFC_res3_dac_channel_VFCQ6_42.0.hdf5 new file mode 100755 index 0000000000..847d1d96b5 Binary files /dev/null and b/pycqed/tests/test_data/20180414/141210_Resonator_scan-VFC_res3_dac_channel_VFCQ6_42.0/141210_Resonator_scan-VFC_res3_dac_channel_VFCQ6_42.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/141227_spectroscopy_-VFC_res3_dac_channel_VFCQ6_42.0/141227_spectroscopy_-VFC_res3_dac_channel_VFCQ6_42.0.hdf5 b/pycqed/tests/test_data/20180414/141227_spectroscopy_-VFC_res3_dac_channel_VFCQ6_42.0/141227_spectroscopy_-VFC_res3_dac_channel_VFCQ6_42.0.hdf5 new file mode 100755 index 0000000000..075fc95471 Binary files /dev/null and b/pycqed/tests/test_data/20180414/141227_spectroscopy_-VFC_res3_dac_channel_VFCQ6_42.0/141227_spectroscopy_-VFC_res3_dac_channel_VFCQ6_42.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/141409_Resonator_scan-VFC_res3_dac_channel_VFCQ6_44.0/141409_Resonator_scan-VFC_res3_dac_channel_VFCQ6_44.0.hdf5 b/pycqed/tests/test_data/20180414/141409_Resonator_scan-VFC_res3_dac_channel_VFCQ6_44.0/141409_Resonator_scan-VFC_res3_dac_channel_VFCQ6_44.0.hdf5 new file mode 100755 index 0000000000..254ce06671 Binary files /dev/null and b/pycqed/tests/test_data/20180414/141409_Resonator_scan-VFC_res3_dac_channel_VFCQ6_44.0/141409_Resonator_scan-VFC_res3_dac_channel_VFCQ6_44.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/141426_spectroscopy_-VFC_res3_dac_channel_VFCQ6_44.0/141426_spectroscopy_-VFC_res3_dac_channel_VFCQ6_44.0.hdf5 b/pycqed/tests/test_data/20180414/141426_spectroscopy_-VFC_res3_dac_channel_VFCQ6_44.0/141426_spectroscopy_-VFC_res3_dac_channel_VFCQ6_44.0.hdf5 new file mode 100755 index 0000000000..88b40d2773 Binary files /dev/null and b/pycqed/tests/test_data/20180414/141426_spectroscopy_-VFC_res3_dac_channel_VFCQ6_44.0/141426_spectroscopy_-VFC_res3_dac_channel_VFCQ6_44.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/141608_Resonator_scan-VFC_res3_dac_channel_VFCQ6_46.0/141608_Resonator_scan-VFC_res3_dac_channel_VFCQ6_46.0.hdf5 b/pycqed/tests/test_data/20180414/141608_Resonator_scan-VFC_res3_dac_channel_VFCQ6_46.0/141608_Resonator_scan-VFC_res3_dac_channel_VFCQ6_46.0.hdf5 new file mode 100755 index 0000000000..c4ba82b3fb Binary files /dev/null and b/pycqed/tests/test_data/20180414/141608_Resonator_scan-VFC_res3_dac_channel_VFCQ6_46.0/141608_Resonator_scan-VFC_res3_dac_channel_VFCQ6_46.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/141625_spectroscopy_-VFC_res3_dac_channel_VFCQ6_46.0/141625_spectroscopy_-VFC_res3_dac_channel_VFCQ6_46.0.hdf5 b/pycqed/tests/test_data/20180414/141625_spectroscopy_-VFC_res3_dac_channel_VFCQ6_46.0/141625_spectroscopy_-VFC_res3_dac_channel_VFCQ6_46.0.hdf5 new file mode 100755 index 0000000000..7ffe6b6f6b Binary files /dev/null and b/pycqed/tests/test_data/20180414/141625_spectroscopy_-VFC_res3_dac_channel_VFCQ6_46.0/141625_spectroscopy_-VFC_res3_dac_channel_VFCQ6_46.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/141807_Resonator_scan-VFC_res3_dac_channel_VFCQ6_48.0/141807_Resonator_scan-VFC_res3_dac_channel_VFCQ6_48.0.hdf5 b/pycqed/tests/test_data/20180414/141807_Resonator_scan-VFC_res3_dac_channel_VFCQ6_48.0/141807_Resonator_scan-VFC_res3_dac_channel_VFCQ6_48.0.hdf5 new file mode 100755 index 0000000000..3d36dc5a6d Binary files /dev/null and b/pycqed/tests/test_data/20180414/141807_Resonator_scan-VFC_res3_dac_channel_VFCQ6_48.0/141807_Resonator_scan-VFC_res3_dac_channel_VFCQ6_48.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180414/141824_spectroscopy_-VFC_res3_dac_channel_VFCQ6_48.0/141824_spectroscopy_-VFC_res3_dac_channel_VFCQ6_48.0.hdf5 b/pycqed/tests/test_data/20180414/141824_spectroscopy_-VFC_res3_dac_channel_VFCQ6_48.0/141824_spectroscopy_-VFC_res3_dac_channel_VFCQ6_48.0.hdf5 new file mode 100755 index 0000000000..9fe9d014d9 Binary files /dev/null and b/pycqed/tests/test_data/20180414/141824_spectroscopy_-VFC_res3_dac_channel_VFCQ6_48.0/141824_spectroscopy_-VFC_res3_dac_channel_VFCQ6_48.0.hdf5 differ diff --git a/pycqed/tests/test_data/20180423/114715_cryoscope_Delft_houses/114715_cryoscope_Delft_houses.hdf5 b/pycqed/tests/test_data/20180423/114715_cryoscope_Delft_houses/114715_cryoscope_Delft_houses.hdf5 new file mode 100644 index 0000000000..1da52f4396 Binary files /dev/null and b/pycqed/tests/test_data/20180423/114715_cryoscope_Delft_houses/114715_cryoscope_Delft_houses.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/182642_SSRO_0_10.00/182642_SSRO_0_10.00.hdf5 b/pycqed/tests/test_data/20180508/182642_SSRO_0_10.00/182642_SSRO_0_10.00.hdf5 new file mode 100644 index 0000000000..b9572c68d3 Binary files /dev/null and b/pycqed/tests/test_data/20180508/182642_SSRO_0_10.00/182642_SSRO_0_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/182657_SSRO_15_10.00/182657_SSRO_15_10.00.hdf5 b/pycqed/tests/test_data/20180508/182657_SSRO_15_10.00/182657_SSRO_15_10.00.hdf5 new file mode 100644 index 0000000000..3f689ae6f4 Binary files /dev/null and b/pycqed/tests/test_data/20180508/182657_SSRO_15_10.00/182657_SSRO_15_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/182711_SSRO_30_10.00/182711_SSRO_30_10.00.hdf5 b/pycqed/tests/test_data/20180508/182711_SSRO_30_10.00/182711_SSRO_30_10.00.hdf5 new file mode 100644 index 0000000000..c5de82f3a0 Binary files /dev/null and b/pycqed/tests/test_data/20180508/182711_SSRO_30_10.00/182711_SSRO_30_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/182726_SSRO_45_10.00/182726_SSRO_45_10.00.hdf5 b/pycqed/tests/test_data/20180508/182726_SSRO_45_10.00/182726_SSRO_45_10.00.hdf5 new file mode 100644 index 0000000000..a84964a158 Binary files /dev/null and b/pycqed/tests/test_data/20180508/182726_SSRO_45_10.00/182726_SSRO_45_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/182740_SSRO_60_10.00/182740_SSRO_60_10.00.hdf5 b/pycqed/tests/test_data/20180508/182740_SSRO_60_10.00/182740_SSRO_60_10.00.hdf5 new file mode 100644 index 0000000000..0ffa21a274 Binary files /dev/null and b/pycqed/tests/test_data/20180508/182740_SSRO_60_10.00/182740_SSRO_60_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/182755_SSRO_75_10.00/182755_SSRO_75_10.00.hdf5 b/pycqed/tests/test_data/20180508/182755_SSRO_75_10.00/182755_SSRO_75_10.00.hdf5 new file mode 100644 index 0000000000..f8b13596cd Binary files /dev/null and b/pycqed/tests/test_data/20180508/182755_SSRO_75_10.00/182755_SSRO_75_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/182809_SSRO_90_10.00/182809_SSRO_90_10.00.hdf5 b/pycqed/tests/test_data/20180508/182809_SSRO_90_10.00/182809_SSRO_90_10.00.hdf5 new file mode 100644 index 0000000000..e2ab28466b Binary files /dev/null and b/pycqed/tests/test_data/20180508/182809_SSRO_90_10.00/182809_SSRO_90_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/182823_SSRO_105_10.00/182823_SSRO_105_10.00.hdf5 b/pycqed/tests/test_data/20180508/182823_SSRO_105_10.00/182823_SSRO_105_10.00.hdf5 new file mode 100644 index 0000000000..0b73f41574 Binary files /dev/null and b/pycqed/tests/test_data/20180508/182823_SSRO_105_10.00/182823_SSRO_105_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/182838_SSRO_120_10.00/182838_SSRO_120_10.00.hdf5 b/pycqed/tests/test_data/20180508/182838_SSRO_120_10.00/182838_SSRO_120_10.00.hdf5 new file mode 100644 index 0000000000..d7e9066233 Binary files /dev/null and b/pycqed/tests/test_data/20180508/182838_SSRO_120_10.00/182838_SSRO_120_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/182852_SSRO_135_10.00/182852_SSRO_135_10.00.hdf5 b/pycqed/tests/test_data/20180508/182852_SSRO_135_10.00/182852_SSRO_135_10.00.hdf5 new file mode 100644 index 0000000000..37ff09bf4e Binary files /dev/null and b/pycqed/tests/test_data/20180508/182852_SSRO_135_10.00/182852_SSRO_135_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/182906_SSRO_150_10.00/182906_SSRO_150_10.00.hdf5 b/pycqed/tests/test_data/20180508/182906_SSRO_150_10.00/182906_SSRO_150_10.00.hdf5 new file mode 100644 index 0000000000..4037695e0e Binary files /dev/null and b/pycqed/tests/test_data/20180508/182906_SSRO_150_10.00/182906_SSRO_150_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/182921_SSRO_165_10.00/182921_SSRO_165_10.00.hdf5 b/pycqed/tests/test_data/20180508/182921_SSRO_165_10.00/182921_SSRO_165_10.00.hdf5 new file mode 100644 index 0000000000..d7c896fe35 Binary files /dev/null and b/pycqed/tests/test_data/20180508/182921_SSRO_165_10.00/182921_SSRO_165_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/182935_SSRO_180_10.00/182935_SSRO_180_10.00.hdf5 b/pycqed/tests/test_data/20180508/182935_SSRO_180_10.00/182935_SSRO_180_10.00.hdf5 new file mode 100644 index 0000000000..5c0e27f5a6 Binary files /dev/null and b/pycqed/tests/test_data/20180508/182935_SSRO_180_10.00/182935_SSRO_180_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/182950_SSRO_195_10.00/182950_SSRO_195_10.00.hdf5 b/pycqed/tests/test_data/20180508/182950_SSRO_195_10.00/182950_SSRO_195_10.00.hdf5 new file mode 100644 index 0000000000..fe87b19acb Binary files /dev/null and b/pycqed/tests/test_data/20180508/182950_SSRO_195_10.00/182950_SSRO_195_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/183005_SSRO_210_10.00/183005_SSRO_210_10.00.hdf5 b/pycqed/tests/test_data/20180508/183005_SSRO_210_10.00/183005_SSRO_210_10.00.hdf5 new file mode 100644 index 0000000000..748a34a11b Binary files /dev/null and b/pycqed/tests/test_data/20180508/183005_SSRO_210_10.00/183005_SSRO_210_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/183019_SSRO_225_10.00/183019_SSRO_225_10.00.hdf5 b/pycqed/tests/test_data/20180508/183019_SSRO_225_10.00/183019_SSRO_225_10.00.hdf5 new file mode 100644 index 0000000000..b5ef45ec8e Binary files /dev/null and b/pycqed/tests/test_data/20180508/183019_SSRO_225_10.00/183019_SSRO_225_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/183034_SSRO_240_10.00/183034_SSRO_240_10.00.hdf5 b/pycqed/tests/test_data/20180508/183034_SSRO_240_10.00/183034_SSRO_240_10.00.hdf5 new file mode 100644 index 0000000000..349f0f8642 Binary files /dev/null and b/pycqed/tests/test_data/20180508/183034_SSRO_240_10.00/183034_SSRO_240_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/183048_SSRO_255_10.00/183048_SSRO_255_10.00.hdf5 b/pycqed/tests/test_data/20180508/183048_SSRO_255_10.00/183048_SSRO_255_10.00.hdf5 new file mode 100644 index 0000000000..fe237b26a4 Binary files /dev/null and b/pycqed/tests/test_data/20180508/183048_SSRO_255_10.00/183048_SSRO_255_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/183102_SSRO_270_10.00/183102_SSRO_270_10.00.hdf5 b/pycqed/tests/test_data/20180508/183102_SSRO_270_10.00/183102_SSRO_270_10.00.hdf5 new file mode 100644 index 0000000000..8e1b706152 Binary files /dev/null and b/pycqed/tests/test_data/20180508/183102_SSRO_270_10.00/183102_SSRO_270_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/183117_SSRO_285_10.00/183117_SSRO_285_10.00.hdf5 b/pycqed/tests/test_data/20180508/183117_SSRO_285_10.00/183117_SSRO_285_10.00.hdf5 new file mode 100644 index 0000000000..efcd7a4970 Binary files /dev/null and b/pycqed/tests/test_data/20180508/183117_SSRO_285_10.00/183117_SSRO_285_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/183131_SSRO_300_10.00/183131_SSRO_300_10.00.hdf5 b/pycqed/tests/test_data/20180508/183131_SSRO_300_10.00/183131_SSRO_300_10.00.hdf5 new file mode 100644 index 0000000000..be2c6af4eb Binary files /dev/null and b/pycqed/tests/test_data/20180508/183131_SSRO_300_10.00/183131_SSRO_300_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/183146_SSRO_315_10.00/183146_SSRO_315_10.00.hdf5 b/pycqed/tests/test_data/20180508/183146_SSRO_315_10.00/183146_SSRO_315_10.00.hdf5 new file mode 100644 index 0000000000..c94254d8ad Binary files /dev/null and b/pycqed/tests/test_data/20180508/183146_SSRO_315_10.00/183146_SSRO_315_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/183200_SSRO_330_10.00/183200_SSRO_330_10.00.hdf5 b/pycqed/tests/test_data/20180508/183200_SSRO_330_10.00/183200_SSRO_330_10.00.hdf5 new file mode 100644 index 0000000000..b8dc473039 Binary files /dev/null and b/pycqed/tests/test_data/20180508/183200_SSRO_330_10.00/183200_SSRO_330_10.00.hdf5 differ diff --git a/pycqed/tests/test_data/20180508/183214_SSRO_345_10.00/183214_SSRO_345_10.00.hdf5 b/pycqed/tests/test_data/20180508/183214_SSRO_345_10.00/183214_SSRO_345_10.00.hdf5 new file mode 100644 index 0000000000..5f553ed63b Binary files /dev/null and b/pycqed/tests/test_data/20180508/183214_SSRO_345_10.00/183214_SSRO_345_10.00.hdf5 differ