Beispiel #1
0
    def _detect_resonator(self, plot=True):
        """
        Finds frequency of the resonator visible on the VNA screen
        """
        vna = self._vna
        tries_number = 3
        for i in range(0, tries_number):
            vna.avg_clear(); vna.prepare_for_stb(); vna.sweep_single(); vna.wait_for_stb()
            frequencies, sdata = vna.get_frequencies(), vna.get_sdata()
            scan_range = frequencies[-1]-frequencies[0]

            port = circuit.notch_port(frequencies, sdata)
            port.autofit()
            fit_min_idx = argmin(abs(port.z_data_sim))

            estimated_frequency = frequencies[argmin(abs(sdata))]
            estimated_amplitude = min(abs(sdata))

            fit_frequency = frequencies[fit_min_idx]
            fit_amplitude = min(abs(port.z_data_sim))

            if abs(fit_frequency-estimated_frequency)<0.1*scan_range and \
                abs(fit_amplitude-estimated_amplitude)<5*estimated_amplitude:
                # Success!
                break
            else:
                # print(estimated_amplitude, fit_amplitude, estimated_frequency, fit_frequency)
                print("\rFit was inaccurate, retrying", end = "")

        if plot:
            port.plotall()

        return fit_frequency, fit_amplitude, angle(port.z_data_sim)[fit_min_idx]
Beispiel #2
0
def test_fit(f_data, z_data, fit_results, test):
    port1 = circuit.notch_port()
    port1.add_data(f_data, z_data)
    results = slf.fit(port1)
    assert fit_results[0] == pytest.approx(
        results[4], abs=0.02 * results[4]) and fit_results[1] == pytest.approx(
            results[5], 0.02 * results[5]), test
def test_fit(f_data, z_data, fit_results, test):
    port1 = circuit.notch_port()
    port1.add_data(f_data, z_data)
    delay, results = fitting_tool.fit(port1)
    assert fit_results[0] == pytest.approx(results[4],abs=0.02*results[4])\
           and fit_results[1] == pytest.approx(results[5],0.02*results[5])\
           and fit_results[2] == pytest.approx(delay, 0.02*delay), test
def detect_resonator(pna, type="AMP"):
    """
	Finds a resonator on the screen
	"""

    freq = 1
    if type == "AMP":
        Y = 20 * np.log10(abs(pna.get_sdata()))
        idx = np.where(Y == np.min(Y))[0][0]
        freq = pna.get_frequencies()[idx]
        amp = (Y[idx])
        return freq, amp
    elif type == "PHAS":
        Y = np.diff(np.unwrap(np.angle(pna.get_sdata())))
        idx = np.where(Y == np.max(Y))[0][0]
        freq = pna.get_frequencies()[idx]
        phas_derivative = Y[idx]
        return freq, phas_derivative
    elif type == "FIT":
        port = circuit.notch_port(pna.get_frequencies(), pna.get_sdata())
        port.autofit()
        # port.plotall()
        # print(port.fitresults)
        return pna.get_frequencies()[np.argmin(abs(
            port.z_data_sim))], 20 * np.log10(min(abs(port.z_data_sim)))
    def __init__(self, frequencies, s_data, plot=True, fast=False):

        self._freqs = frequencies
        self._s_data = s_data
        self._plot = plot
        self._port = notch_port(frequencies, s_data)
        # self._s_data_filtered = (savgol_filter(real(self._s_data), 21, 2)\
        #                         + 1j*savgol_filter(imag(self._s_data), 21, 2))
        # self._filtered_port = notch_port(frequencies, self._s_data_filtered)
        self._fast = fast
def resonator_quality_factor_fit(measurement, sweep_parameter_values, sweep_parameter_name='power', resonator_type='notch_port', delay=None, use_calibrate=False):
	from resonator_tools import circuit
	fitresults = []
	sweep_parameter = measurement.datasets['S-parameter'].parameters[0].values
	f_data = measurement.datasets['S-parameter'].parameters[1].values
	z_data = measurement.datasets['S-parameter'].data

	if use_calibrate:
		max_power_id = np.argmax(sweep_parameter)
		if resonator_type == 'notch_port':
			fitter = circuit.notch_port(f_data = f_data, z_data_raw=z_data[max_power_id,:])
		else:
			fitter = circuit.reflection_port(f_data = f_data, z_data_raw=z_data[max_power_id,:])
		delay, amp_norm, alpha, fr, Ql, A2, frcal = \
			fitter.do_calibration(f_data, z_data[max_power_id,:],ignoreslope=True,guessdelay=False)

	for power_id, power in enumerate(sweep_parameter_values):
		try:
			if use_calibrate:
				fitter.z_data = fitter.do_normalization(fitter.f_data,z_data[power_id,:],delay,amp_norm,alpha,A2,frcal)
				fitter.fitresults = fitter.circlefit(fitter.f_data,fitter.z_data,fr,Ql,refine_results=True,calc_errors=True)
			else:
				if resonator_type == 'notch_port':
					#print ('notch_port')
					fitter = circuit.notch_port(f_data = f_data, z_data_raw=z_data[power_id,:])
				elif resonator_type == 'reflection_port':
					#print ('reflection_port')
					fitter = circuit.reflection_port(f_data = f_data, z_data_raw=z_data[power_id,:])
				#print (power_id)
				fitter.autofit(electric_delay=delay)
				#print (fitter.fitresults)
			fitter.fitresults[sweep_parameter_name] = power
			fitter.fitresults['single_photon_limit'] = fitter.get_single_photon_limit()
			fitresults.append(fitter.fitresults.copy())
			#fitter.plotall()
			#break
		except:
			pass
		#plt.figure(power_id)
		#fitter.plotall()
		#print(fitter.fitresults)
	return pd.DataFrame(fitresults)
def fit_resonator(array, fit_axis, plot_fit=False):
    """
    Takes an xarray with data variables called 'amplitude' and 'phase' and returns an xarray consisting of the original
    raw data and the resonator fit parameters as a function of the coordinate 'fit_axis' (which is one of the
    coordinates of the input xarray). Fitting is performed using the 'notch_port' class of the circle-fit routine
    provided by https://github.com/sebastianprobst/resonator_tools
    @param array: xarray with the data variables amplitude (linear units) and phase (radians), has to have the
        coordinate frequency, and at least one further coordinate
    @param fit_axis: coordinate of the xarray along which the fits should be performed
    @param plot_fit: If True shows all raw data with fits overlay
    @return: xarray consisting of the raw input data plus the complex data, the complex data produced by the fit,
        and all fit parameters with fit_axis as coordinate.
    """

    _z = array.amplitude.values * np.exp(1j * array.phase.values)
    z = DataArray(_z, name='complex', coords={fit_axis: getattr(array, fit_axis), 'frequency': array.frequency},
                  dims=[fit_axis, 'frequency'])

    array = merge([array, z])

    fitresults = np.zeros((getattr(array, fit_axis).shape[0], 15))
    fit_data = np.empty_like(array.complex.values)

    for i in range(getattr(array, fit_axis).shape[0]):

        z_dat = array.complex.isel({fit_axis: [i]}).values[0]

        res_fit = notch_port(f_data=array.frequency.values, z_data_raw=z_dat)
        res_fit.autofit()
        fitresults[i, :] = list(res_fit.fitresults.values())

        fit_data[i, :] = res_fit.z_data_sim

        if plot_fit:
            fig2, ax2 = plt.subplots(1, 1, figsize=(10, 6))
            ax2.plot(array.frequency.values, 20 * np.log10(np.abs(z_dat)))
            ax2.plot(array.frequency.values, 20 * np.log10(np.abs(res_fit.z_data_sim)), color='blue')

            ax2_2 = ax2.twinx()
            ax2_2.plot(array.frequency.values, np.angle(z_dat), color='tab:orange')
            ax2_2.plot(array.frequency.values, np.angle(res_fit.z_data_sim), color='orange')

    _fxA = []
    for i in range(fitresults.shape[1]):
        _fxA += [DataArray(fitresults[:, i], name=list(res_fit.fitresults.keys())[i],
                           coords={fit_axis: getattr(array, fit_axis).values}, dims=[fit_axis])]

    _zfitxA = DataArray(fit_data, name='complex_fit', coords={fit_axis: getattr(array, fit_axis),
                                                              'frequency': array.frequency},
                        dims=[fit_axis, 'frequency'])

    array = merge([array, *_fxA, _zfitxA])

    return array
Beispiel #8
0
def resonator_tools_notch_port(f, S):
    '''
    :param iterable_of_float f: frequencies at which the S-parameter has been sampled
    :param iterable_of_complex S: measured S-parameters
    :return x,z,parameters: fit results
    '''
    from resonator_tools import circuit

    fitter = circuit.notch_port(f, S.ravel())
    fitter.autofit()

    return f, fitter.z_data_sim, fitter.fitresults
Beispiel #9
0
 def onselect(xmin, xmax):
     port = circuit.notch_port(self.freq_arr, self.resp_arr)
     port.autofit(fcrop=(xmin * 1e9, xmax * 1e9))
     sim_db = 20 * np.log10(np.abs(port.z_data_sim))
     line_fit_a.set_data(1e-9 * port.f_data, sim_db)
     line_fit_p.set_data(1e-9 * port.f_data,
                         np.angle(port.z_data_sim))
     f_min = port.f_data[np.argmin(sim_db)]
     print("----------------")
     print(f"fr = {port.fitresults['fr']}")
     print(f"Qi = {port.fitresults['Qi_dia_corr']}")
     print(f"Qc = {port.fitresults['Qc_dia_corr']}")
     print(f"Ql = {port.fitresults['Ql']}")
     print(
         f"kappa = {port.fitresults['fr'] / port.fitresults['Qc_dia_corr']}"
     )
     print(f"f_min = {f_min}")
     print("----------------")
     fig1.canvas.draw()
Beispiel #10
0
def plots2p():
    import matplotlib
    matplotlib.use('Agg')
    import matplotlib.pyplot as plt
    from io import BytesIO
    import base64

    from resonator_tools import circuit
    port1 = circuit.notch_port()
    port1.add_froms2p('c:/Users/3333.s2p',
                      3,
                      4,
                      'realimag',
                      fdata_unit=1e9,
                      delimiter=None)
    port1.autofit()
    print("Fit results:", port1.fitresults)
    port1.plotall()
    print("single photon limit:", port1.get_single_photon_limit(diacorr=True),
          "dBm")
    print("photons in reso for input -140dBm:",
          port1.get_photons_in_resonator(-140, unit='dBm', diacorr=True),
          "photons")
    print("done")

    sio = BytesIO()
    plt.savefig(sio, format='png')
    data = base64.encodebytes(sio.getvalue()).decode()

    html = '''
       <html>
           <body>
               <img src="data:image/png;base64,{}" />
           </body>
        <html>
    '''

    plt.close()
    return html.format(data)
Beispiel #11
0
 def onselect(xmin, xmax):
     port = circuit.notch_port(self.freq_arr,
                               self.resp_arr[self._AMP_IDX])
     port.autofit(fcrop=(xmin * 1e9, xmax * 1e9))
     if norm:
         line_fit_a.set_data(
             1e-9 * port.f_data, 20 * np.log10(
                 np.abs(port.z_data_sim /
                        self.amp_arr[self._AMP_IDX])))
     else:
         line_fit_a.set_data(1e-9 * port.f_data,
                             20 * np.log10(np.abs(port.z_data_sim)))
     line_fit_p.set_data(1e-9 * port.f_data,
                         np.angle(port.z_data_sim))
     # print(port.fitresults)
     print("----------------")
     print(f"fr = {port.fitresults['fr']}")
     print(f"Qi = {port.fitresults['Qi_dia_corr']}")
     print(f"Qc = {port.fitresults['Qc_dia_corr']}")
     print(f"Ql = {port.fitresults['Ql']}")
     print(
         f"kappa = {port.fitresults['fr'] / port.fitresults['Qc_dia_corr']}"
     )
     print("----------------")
     # ax2.set_title(
     #     f"fr = {1e-6*fr:.0f} MHz, Ql = {Ql:.0f}, Qi = {Qi:.0f}, Qc = {Qc:.0f}, kappa = {1e-3*kappa:.0f} kHz")
     if blit:
         fig1.canvas.restore_region(self._bg)
         ax1.draw_artist(line_sel)
         ax2.draw_artist(line_a)
         ax2.draw_artist(line_fit_a)
         ax3.draw_artist(line_p)
         ax3.draw_artist(line_fit_p)
         fig1.canvas.blit(fig1.bbox)
         fig1.canvas.flush_events()
     else:
         fig1.canvas.draw()
    def analyze(self, all_plots: bool = False):
        assert self.t_arr is not None
        assert self.store_arr is not None
        assert self.readout_freq_arr is not None
        assert self.readout_if_arr is not None
        assert self.readout_nco is not None
        assert len(self.readout_freq_arr) == self.readout_freq_nr
        assert len(self.readout_if_arr) == self.readout_freq_nr

        import matplotlib.pyplot as plt
        from scipy.optimize import curve_fit
        try:
            from resonator_tools import circuit
            _has_resonator_tools = True
        except ImportError:
            _has_resonator_tools = False

        ret_fig = []

        idx = np.arange(IDX_LOW, IDX_HIGH)
        t_low = self.t_arr[IDX_LOW]
        t_high = self.t_arr[IDX_HIGH]
        nr_samples = IDX_HIGH - IDX_LOW

        if all_plots:
            # Plot raw store data for first iteration as a check
            fig1, ax1 = plt.subplots(2, 1, sharex=True, tight_layout=True)
            ax11, ax12 = ax1
            ax11.axvspan(1e9 * t_low, 1e9 * t_high, facecolor="#dfdfdf")
            ax12.axvspan(1e9 * t_low, 1e9 * t_high, facecolor="#dfdfdf")
            ax11.plot(1e9 * self.t_arr, np.abs(self.store_arr[0, 0, :]))
            ax12.plot(1e9 * self.t_arr, np.angle(self.store_arr[0, 0, :]))
            ax12.set_xlabel("Time [ns]")
            fig1.show()
            ret_fig.append(fig1)

        # Analyze
        data = self.store_arr[:, 0, idx]
        data.shape = (self.readout_freq_nr, 2, nr_samples)
        resp_I_arr = np.zeros((2, self.readout_freq_nr), np.complex128)
        resp_Q_arr = np.zeros((2, self.readout_freq_nr), np.complex128)
        dt = self.t_arr[1] - self.t_arr[0]
        t = dt * np.arange(nr_samples)
        for ii, readout_if in enumerate(self.readout_if_arr):
            cos = np.cos(2 * np.pi * readout_if * t)
            sin = np.sin(2 * np.pi * readout_if * t)
            for jj in range(2):
                data_slice = data[ii, jj, :]
                # TODO: low-pass filter the demodulated signal?
                I_real = np.sum(data_slice.real * cos) / nr_samples
                I_imag = -np.sum(data_slice.real * sin) / nr_samples
                resp_I_arr[jj, ii] = I_real + 1j * I_imag
                Q_real = np.sum(data_slice.imag * cos) / nr_samples
                Q_imag = -np.sum(data_slice.imag * sin) / nr_samples
                resp_Q_arr[jj, ii] = Q_real + 1j * Q_imag

        _, resp_H_arr = untwist_downconversion(resp_I_arr, resp_Q_arr)
        resp_dB = 20 * np.log10(np.abs(resp_H_arr))
        resp_phase = np.angle(resp_H_arr)
        # resp_phase *= -1
        resp_phase = np.unwrap(resp_phase, axis=-1)
        N = self.readout_freq_nr // 4
        idx = np.zeros(self.readout_freq_nr, bool)
        idx[:N] = True
        idx[-N:] = True
        pfit_g = np.polyfit(self.readout_freq_arr[idx], resp_phase[0, idx], 1)
        pfit_e = np.polyfit(self.readout_freq_arr[idx], resp_phase[1, idx], 1)
        pfit = 0.5 * (pfit_g + pfit_e)
        background = np.polyval(pfit, self.readout_freq_arr)
        resp_phase[0, :] -= background
        resp_phase[1, :] -= background
        separation = np.abs(resp_H_arr[1, :] - resp_H_arr[0, :])

        p0 = [
            self.readout_freq_arr[np.argmax(separation)],
            1 / self.readout_duration,
            np.max(separation),
            0.0,
        ]
        popt, pcov = curve_fit(_gaussian, self.readout_freq_arr, separation,
                               p0)

        print("----------------")
        if _has_resonator_tools:
            port_g = circuit.notch_port(
                self.readout_freq_arr,
                resp_H_arr[0, :] * np.exp(-1j * background))
            port_e = circuit.notch_port(
                self.readout_freq_arr,
                resp_H_arr[1, :] * np.exp(-1j * background))
            port_g.autofit()
            port_e.autofit()

            f_g = port_g.fitresults['fr']
            f_e = port_e.fitresults['fr']
            chi_hz = (f_e - f_g) / 2
            print(f"ω_g / 2π = {f_g * 1e-9:.6f} GHz")
            print(f"ω_e / 2π = {f_e * 1e-9:.6f} GHz")
            print(f"χ / 2π = {chi_hz * 1e-3:.2f} kHz")
        print(f"ω_opt / 2π = {popt[0] * 1e-9:.6f} GHz")
        print("----------------")

        fig2, ax2 = plt.subplots(3,
                                 1,
                                 sharex=True,
                                 tight_layout=True,
                                 figsize=(6.4, 6.4))
        ax21, ax22, ax23 = ax2

        for ax_ in ax2:
            if _has_resonator_tools:
                ax_.axvline(1e-9 * f_g, ls='--', c='tab:red', alpha=0.5)
                ax_.axvline(1e-9 * f_e, ls='--', c='tab:purple', alpha=0.5)
            ax_.axvline(1e-9 * popt[0], ls='--', c='tab:brown', alpha=0.5)

        ax21.plot(1e-9 * self.readout_freq_arr,
                  resp_dB[0, :],
                  c="tab:blue",
                  label='|g>')
        ax21.plot(1e-9 * self.readout_freq_arr,
                  resp_dB[1, :],
                  c="tab:orange",
                  label='|e>')
        ax22.plot(1e-9 * self.readout_freq_arr, resp_phase[0, :], c="tab:blue")
        ax22.plot(1e-9 * self.readout_freq_arr,
                  resp_phase[1, :],
                  c="tab:orange")
        ax23.plot(1e-9 * self.readout_freq_arr,
                  1e3 * separation,
                  c='tab:green',
                  label='||e> - |g>|')

        if _has_resonator_tools:
            ax21.plot(1e-9 * port_g.f_data,
                      20 * np.log10(np.abs(port_g.z_data_sim)),
                      c="tab:red",
                      ls='--')
            ax21.plot(1e-9 * port_e.f_data,
                      20 * np.log10(np.abs(port_e.z_data_sim)),
                      c="tab:purple",
                      ls='--')
            ax22.plot(1e-9 * port_g.f_data,
                      np.angle(port_g.z_data_sim),
                      c="tab:red",
                      ls='--')
            ax22.plot(1e-9 * port_e.f_data,
                      np.angle(port_e.z_data_sim),
                      c="tab:purple",
                      ls='--')

        ax23.plot(1e-9 * self.readout_freq_arr,
                  1e3 * _gaussian(self.readout_freq_arr, *popt),
                  c='tab:brown',
                  ls='--')

        ax21.set_ylabel("Amplitude [dBFS]")
        ax22.set_ylabel("Phase [rad]")
        ax23.set_ylabel("Separation [mFS]")
        ax2[-1].set_xlabel("Readout frequency [GHz]")
        ax21.legend(ncol=2, loc="lower right")
        ax23.legend(loc="upper right")
        fig2.show()
        ret_fig.append(fig2)

        return ret_fig
Beispiel #13
0
from resonator_tools import circuit

port1 = circuit.notch_port()
port1.add_froms2p('S21testdata.s2p',
                  3,
                  4,
                  'realimag',
                  fdata_unit=1e9,
                  delimiter=None)
port1.autofit()
print "Fit results:", port1.fitresults
port1.plotall()
print "single photon limit:", port1.get_single_photon_limit(
    diacorr=True), "dBm"
print "photons in reso for input -140dBm:", port1.get_photons_in_resonator(
    -140, unit='dBm', diacorr=True), "photons"
print "done"
Beispiel #14
0
 def fit_S21(self):
     from resonator_tools.circuit import notch_port
     fitter = notch_port(f_data=self.frequency.real, z_data_raw=self.S21)
     fitter.autofit()
     return fitter
 def set_data(self, frequencies, s_data):
     self._freqs = frequencies
     self._s_data = s_data
     self._port = notch_port(frequencies, s_data)
Beispiel #16
0
import matplotlib.pyplot as plt
import numpy as np
from resonator_tools import circuit
from IPython.display import display

#%%
table = pd.read_csv(r"./Projects/SFS_transmon/Simulations/res7.2_330.csv",
                    header=None,
                    skiprows=2,
                    names=[
                        "Frequency (GHz)", "RE[S11]", "IM[S11]", "RE[S12]",
                        "IM[S12]", "RE[S21]", "IM[S21]", "RE[S22]", "IM[S22]"
                    ],
                    delimiter=" ")
table.head()

#%%
port = circuit.notch_port(table["Frequency (GHz)"],
                          table["RE[S21]"] + 1j * table["IM[S21]"])
port.autofit()
port.plotall()

#%%
display(
    pd.DataFrame([port.fitresults]).applymap(lambda x: "{0:.2e}".format(x)))

#%%
port.fitresults['fr']

#%%
from resonator_tools import circuit


port1 = circuit.notch_port()
port1.add_froms2p('S21testdata.s2p',3,4,'realimag',fdata_unit=1e9,delimiter=None)
port1.autofit()
print "Fit results:", port1.fitresults
port1.plotall()
print "single photon limit:", port1.get_single_photon_limit(diacorr=True), "dBm"
print "photons in reso for input -140dBm:", port1.get_photons_in_resonator(-140,unit='dBm',diacorr=True), "photons"
print "done"