Пример #1
0
def transmission_vs_frequency_explicit(center, span, suffix=None):
    @MakeMeasurementFunction([
        DataParameter(
            name='frequency' + str(suffix),
            unit='Hz',
            paramtype='array',
            # yes independent, but pysweep will not recognize it as such
            independent=2),
        DataParameter(
            name='amplitude' + str(suffix),
            unit='',
            paramtype='array',
            # explicitely tell that this parameter depends on
            # the corresponding frequency parameter
            extra_dependencies=['frequency' + str(suffix)]),
        DataParameter(
            name='phase' + str(suffix),
            unit='rad',
            paramtype='array',
            # explicitely tell that this parameter depends on
            # the corresponding frequency parameter
            extra_dependencies=['frequency' + str(suffix)])
    ])
    def transmission_vs_frequency_measurement_function(d):
        station = d['STATION']
        station.vna.S21.center(center)
        station.vna.S21.span(span)
        return return_vna_trace(d)

    # return a measurement function
    return transmission_vs_frequency_measurement_function
Пример #2
0
def measure_SNR_CW(suffix='', **kwargs):
    """Pysweep VNA measurement function that measures the mean, std and SNR in dB at a single 1 frequency point. 

    Args:
        suffix (int): suffix added to the DataParameters.
        setup_vna (boolean): whether to use the current VNA settings or pass new ones via kwargs.
        kwargs: see `setup_CW_sweep`.

    Returns:
    Pysweep measurement function
    """
    @MakeMeasurementFunction([
        DataParameter(name="signal" + str(suffix), unit="dB"),
        DataParameter(name="noise" + str(suffix), unit="dB"),
        DataParameter(name="SNR" + str(suffix), unit="dB"),
    ])
    def measurement_function(d):
        vna_data = measure_cw_sweep(**kwargs)(d)
        I = vna_data[1]
        Q = vna_data[2]
        S = I + 1j * Q
        lin_mean = np.abs(S.mean())
        lin_std = np.abs(S.std())

        return [
            20 * np.log10(lin_mean),
            20 * np.log10(lin_std),
            20 * np.log10(lin_mean / lin_std),
        ]

    return measurement_function
Пример #3
0
def measure_single_averaged_IQpoint(controller,
                                    time_bin,
                                    integration_time,
                                    channel=0,
                                    **kw):
    """
    Under development! If you end up wanting to use this, be aware that it is buggy/that it still needs to be finished.
    Arno can help.
    """
    @MakeMeasurementFunction([
        DataParameter("amplitude", "", "array"),
        DataParameter("phase", "rad", "array"),
    ])
    def return_alazar_point(d):
        # setup_single_averaged_IQpoint(controller, time_bin, integration_time, setup_awg=True,
        #                           verbose=True, allocated_buffers=None)

        station = d["STATION"]
        data = controller.acquisition()
        data = np.squeeze(data)[..., 0].mean()
        mag, phase = np.abs(data), np.angle(data, deg=False)

        return [mag, phase]

    return return_alazar_point
Пример #4
0
    def measure_magnet_components_sph(self):
        """ Measure the x, y, z component of the magnet, convert to spherical using the 
        ISO 80000-2:2009 physics convention for the (r, theta, phi) <--> (x, y, z) definition 
        and return as list. 
        output: [r, theta, phi] 
        r (float): magentic field strength, unit: T
        theta (float): inclination angle, unit: degrees, 0 <= theta <= 180
        phi (float): the azimuth (in plane) angle, unit: degrees, range: 0 <= phi < 360
        """
        @MakeMeasurementFunction([
            DataParameter(name="r", unit="T"),
            DataParameter(name="theta", unit="deg"),
            DataParameter(name="phi", unit="deg"),
        ])
        def measurement_function(d):
            x = self.magnet.x_measured(
            ) + 1e-9  # avoiding dividing by true zero
            y = self.magnet.y_measured() + 1e-9
            z = self.magnet.z_measured() + 1e-9

            r_meas = np.sqrt(x**2 + y**2 + z**2)
            phi_meas = np.arctan2(y, x) / np.pi * 180
            if phi_meas < 0:
                phi_meas += 360
            theta_meas = np.arccos(z / r_meas) / np.pi * 180

            return [r_meas, theta_meas, phi_meas]

        return measurement_function
Пример #5
0
def measure_soft_time_avg_spec(controller,
                               sweep_param,
                               sweep_vals,
                               integration_time,
                               exp_name=None,
                               channel=0,
                               **kw):
    """
    Under development! If you end up wanting to use this, be aware that it is buggy/that it still needs to be finished.
    Arno can help.
    """
    @MakeMeasurementFunction([
        DataParameter("frequency", "Hz", "array", True),
        DataParameter("amplitude", "", "array"),
        DataParameter("phase", "rad", "array"),
    ])
    def return_alazar_trace(d):
        setup_triggered_softsweep(controller,
                                  sweep_param,
                                  sweep_vals,
                                  integration_time,
                                  setup_awg=True,
                                  verbose=True,
                                  **kw)
        station = d["STATION"]
        freqs = sweep_vals

        data = np.squeeze(controller.acquisition())[..., channel]
        mag, phase = np.abs(data), np.angle(data, deg=False)

        return [freqs, mag, phase]

    return return_alazar_trace
Пример #6
0
def measure_PSD_averaged(averages=1, suffix='', **kwargs):
    """Pysweep VNA measurement function that returns the average of the PSD of the I and Q quadratures. 
    Uses a rolling average, so at most two traces exist in the memory simultaneously. Averages can thus be large without memory issues.
    Mainly to be used as a diagnostic tool; `frequency` is based on `times` which might not be entirely correct.
    To be implemented: make averaging optional. 

    Args:
        averages (int): number of averages to be performed.
        suffix (int): suffix added to the DataParameters.
        setup_vna (boolean): whether to use the current VNA settings or pass new ones via kwargs.
        kwargs: see `setup_CW_sweep`.

    Returns:
    Pysweep measurement function
    """
    @MakeMeasurementFunction([
        DataParameter(
            name="frequency" + str(suffix),
            unit="s",
            paramtype="array",
            independent=2,
        ),
        DataParameter(
            name="PSD" + str(suffix),
            unit="",
            paramtype="array",
            extra_dependencies=["frequency" + str(suffix)],
        ),
    ])
    def measurement_function(d):
        station = d["STATION"]
        if bool(kwargs):
            # while this seems redundant as measure_cw_sweep can also recognise if there are kwargs
            # we put the setting up here outside the for loop to save time as cw_sweeps can be very short
            setup_CW_sweep(station=station, **kwargs)

        bw = station.vna.S21.bandwidth()
        sweep_time = station.vna.S21.sweep_time()
        npts = station.vna.S21.npts()
        times = np.linspace(1 / bw, sweep_time, npts)
        n = times.size
        step = np.diff(times)[0]
        fftfreq = np.fft.fftfreq(n, d=step)

        for ii in range(int(averages)):
            vna_data = measure_cw_sweep()(d)
            I = vna_data[1]
            Q = vna_data[2]
            fft_y = np.abs(np.fft.fft((Q - np.mean(Q)) + 1j *
                                      (I - np.mean(I))))**2

            if ii == 0:
                fft_array = fft_y
            else:
                fft_array = (fft_array * (ii) + fft_y) / (ii + 1)

        return [fftfreq, fft_array]

    return measurement_function
Пример #7
0
def measure_cw_sweep(suffix='', **kwargs):
    """Pysweep VNA measurement function that returns a CW trace, either given the currently
    set VNA parameters or for a custom set of parameters specified via kwargs when setup_vna=true.
    By setting suffix one can measure several frequencies
    versus a parameter in the same measurement without the parameter names interfering.
    Note that it is not entirely clear to what degree `times` is accurate!

    Args:
        suffix (int): suffix added to the DataParameters.
        kwargs: see `setup_CW_sweep`.


    Returns:
    Pysweep measurement function
    """
    @MakeMeasurementFunction([
        DataParameter(
            name="time" + str(suffix),
            unit="s",
            paramtype="array",
            independent=2,
        ),
        DataParameter(
            name="I" + str(suffix),
            unit="",
            paramtype="array",
            extra_dependencies=["time" + str(suffix)],
        ),
        DataParameter(
            name="Q" + str(suffix),
            unit="",
            paramtype="array",
            extra_dependencies=["time" + str(suffix)],
        ),
    ])
    def measurement_function(d):
        station = d["STATION"]
        if bool(
                kwargs
        ):  # checks if there are kwargs, otherwise we can skip setting up the VNA
            setup_CW_sweep(station=station, **kwargs)

        bw = station.vna.S21.bandwidth()
        sweep_time = station.vna.S21.sweep_time()
        npts = station.vna.S21.npts()
        times = np.linspace(1 / bw, sweep_time, npts)

        if not station.vna.rf_power():
            station.vna.rf_on()

        vna_data = station.vna.S21.trace_fixed_frequency()
        station.vna.rf_off()

        return [times, vna_data[0], vna_data[1]]

    return measurement_function
Пример #8
0
def measure_linear_sweep(suffix='', **kwargs):
    """Pysweep VNA measurement function that returns an S21 trace, either given the currently
    set VNA parameters or for a custom set of parameters specified via kwargs.
    By setting suffix one can measure the response of several resonances
    versus a parameter in the same measurement without the parameter names interfering.

    Args:
        suffix (int): suffix added to the DataParameters.
        kwargs: see `setup_linear_sweep`.


    Returns:
    Pysweep measurement function
    """
    @MakeMeasurementFunction([
        DataParameter(
            name="frequency" + str(suffix),
            unit="Hz",
            paramtype="array",
            independent=2,
        ),
        DataParameter(
            name="amplitude" + str(suffix),
            unit="",
            paramtype="array",
            extra_dependencies=["frequency" + str(suffix)],
        ),
        DataParameter(
            name="phase" + str(suffix),
            unit="rad",
            paramtype="array",
            extra_dependencies=["frequency" + str(suffix)],
        ),
    ])
    def measurement_function(d):
        station = d["STATION"]
        if bool(
                kwargs
        ):  # checks if there are kwargs, otherwise we can skip setting up the VNA
            setup_linear_sweep(station=station, **kwargs)

        freqs = np.linspace(station.vna.S21.start(), station.vna.S21.stop(),
                            station.vna.S21.npts())

        if not station.vna.rf_power():
            station.vna.rf_on()

        vna_data = station.vna.S21.trace_mag_phase()
        station.vna.rf_off()

        return [freqs, vna_data[0], vna_data[1]]

    return measurement_function
Пример #9
0
    def measure_magnet_components(self):
        """ Measure the x, y, z component of the magnet and return as list
        output: [x, y, z]
        """
        @MakeMeasurementFunction([
            DataParameter(name="x", unit="T"),
            DataParameter(name="y", unit="T"),
            DataParameter(name="z", unit="T"),
        ])
        def measurement_function(d):
            x_meas = self.magnet.x_measured()
            y_meas = self.magnet.y_measured()
            z_meas = self.magnet.z_measured()
            return [x_meas, y_meas, z_meas]

        return measurement_function
Пример #10
0
def measure_QPP(controller,
                acq_time,
                navg,
                SR=250e6,
                setup_awg=True,
                hetsrc_power=None,
                hetsrc_freq=None,
                **kw):
    @MakeMeasurementFunction([
        DataParameter("timestamp", "s", "array", False),
    ])
    def return_alazar_trace(d):

        setup_QPP(controller, acq_time, navg, SR=SR, setup_awg=setup_awg, **kw)

        station = d["STATION"]

        station = d["STATION"]

        station.awg.start()

        if hetsrc_power is not None:
            station.hetsrc.RF.power(hetsrc_power)

        if hetsrc_freq == 'dict':
            station.hetsrc.frequency(d["f0"])
        elif hetsrc_freq == None:
            pass
        else:
            station.hetsrc.frequency(hetsrc_freq)

        station.qubsrc.modulation_rf('OFF')
        station.qubsrc.output_rf('ON')
        station.RF.on()
        station.RF.pulsemod_source('EXT')
        station.RF.pulsemod_state('OFF')
        station.RF.ref_LO_out('LO')
        station.LO.on()

        station.alazar.clear_buffers()
        data = np.squeeze(controller.acquisition())[..., 0]
        time.sleep(0.1)

        station.awg.stop()
        station.qubsrc.output_rf('OFF')
        station.RF.off()
        station.RF.ref_LO_out('OFF')
        station.LO.off()

        timestamp = int(time.time() * 1e6)
        datasaver_run_id = d["DATASAVER"].datasaver._dataset.run_id
        data_folder_path = str(qcodes.config.core.db_location)[:-3] + "\\"
        Path(data_folder_path).mkdir(parents=True, exist_ok=True)
        np.save(
            data_folder_path + "ID_" + f"{datasaver_run_id}_IQ_{timestamp:d}",
            [controller.demod_tvals, data])

        return [timestamp]

    return return_alazar_trace
Пример #11
0
def measure_adaptive_linear_sweep(suffix='', **kwargs):
    """Pysweep VNA measurement function that measures S21 in a window around a
    frequency f0 as be updated through functions such as `measure_resonance_frequency`.
    This is helpful when measuring S21 versus parameters that change the resonance frequency;
    one can first coarsely determine where the resonance is and then finely measure around it.
    Typically one would provide kwargs such as span and npts.

    Args:
    suffix (int): suffix added to the DataParameters.
    kwargs: see `setup_linear_sweep`.


    Returns:
    Pysweep measurement function

    """
    @MakeMeasurementFunction([
        DataParameter(
            name="frequency" + str(suffix),
            unit="Hz",
            paramtype="array",
            independent=2,
        ),
        DataParameter(
            name="amplitude" + str(suffix),
            unit="",
            paramtype="array",
            extra_dependencies=["frequency" + str(suffix)],
        ),
        DataParameter(
            name="phase" + str(suffix),
            unit="rad",
            paramtype="array",
            extra_dependencies=["frequency" + str(suffix)],
        ),
    ])
    def measurement_function(d):
        data = measure_linear_sweep(suffix=suffix, center=d["f0"], **kwargs)(d)
        return [data[0], data[1], data[2]]

    return measurement_function
Пример #12
0
def measure_cw_point(suffix='', **kwargs):
    """Pysweep VNA measurement function that returns an averaged CW point, either given the currently
    set VNA parameters or for a custom set of parameters specified via kwargs when setup_vna=true.
    By setting suffix one can measure several frequencies
    versus a parameter in the same measurement without the parameter names interfering.

    Args:
        suffix (int): suffix added to the DataParameters.
        setup_vna (boolean): whether to use the current VNA settings or pass new ones via kwargs.
        kwargs: see `setup_CW_sweep`.


    Returns:
    Pysweep measurement function
    """
    @MakeMeasurementFunction([
        DataParameter(name="amplitude" + str(suffix), unit=""),
        DataParameter(name="phase" + str(suffix), unit="rad")
    ])
    def measurement_function(d):
        station = d["STATION"]
        if bool(
                kwargs
        ):  # checks if there are kwargs, otherwise we can skip setting up the VNA
            setup_CW_sweep(station=station, **kwargs)

        if not station.vna.rf_power():
            station.vna.rf_on()

        data = list(station.vna.S21.point_fixed_frequency_mag_phase())

        station.vna.rf_off()

        return data

    return measurement_function
Пример #13
0
def measure_resonance_frequency(peak_finder,
                                save_trace=False,
                                suffix='',
                                **kwargs):
    """Pysweep VNA measurement function that can estimate a resonance frequency `f0`. 
    frequency. Can choose to save the trace or only the resonance frequency.

    peak_finder: Function that finds a peak from VNA output. See for example general_tools -> peak_finding.py
    save_trace (boolean): whether to save the full VNA trace and the determined f0 or only f0.
    suffix (int): suffix added to the DataParameters.
    kwargs: see `setup_linear_sweep`.

    Returns:
    Pysweep measurement function

    """
    def measurement_function(d):
        freqs, mag, phase = measure_linear_sweep(suffix=suffix, **kwargs)(d)

        m0 = peak_finder(freqs, mag)
        if m0 == None:
            raise Exception(
                "Failed to find a resonance."
            )  # needs work, can implement alternative strategies
        d["f0"] = m0

        if save_trace == True:
            return [freqs, mag, phase, m0]
        else:
            return [m0]

    if save_trace == True:
        return MeasurementFunction(measurement_function, [
            DataParameter(
                name="frequency" + str(suffix),
                unit="Hz",
                paramtype="array",
                independent=2,
            ),
            DataParameter(
                name="amplitude" + str(suffix),
                unit="",
                paramtype="array",
                extra_dependencies=["frequency" + str(suffix)],
            ),
            DataParameter(
                name="phase" + str(suffix),
                unit="rad",
                paramtype="array",
                extra_dependencies=["frequency" + str(suffix)],
            ),
            DataParameter(
                name="resonance_frequency" + str(suffix),
                unit="Hz",
                paramtype="numeric",
            ),
        ])
    else:
        return MeasurementFunction(measurement_function, [
            DataParameter(
                name="resonance_frequency" + str(suffix),
                unit="Hz",
                paramtype="numeric",
            ),
        ])
Пример #14
0
def measure_echo(controller,
                 delays,
                 pulse_time,
                 readout_time,
                 qubsrc_power=None,
                 qubsrc_freq=None,
                 hetsrc_power=None,
                 hetsrc_freq=None,
                 navgs=500,
                 acq_time=2.56e-6,
                 setup_awg=True,
                 suffix='',
                 fit=False,
                 **kw):
    def return_alazar_trace(d):
        station = d["STATION"]
        times = delays
        if pulse_time == 'dict':
            setup_echo(controller,
                       delays,
                       d['pipulse'] / 2,
                       readout_time,
                       navgs=navgs,
                       acq_time=acq_time,
                       setup_awg=True,
                       **kw)
        else:
            setup_echo(controller,
                       delays,
                       pulse_time,
                       readout_time,
                       navgs=navgs,
                       acq_time=acq_time,
                       setup_awg=setup_awg,
                       **kw)

        if qubsrc_power is not None:
            station.qubsrc.power(qubsrc_power)
        if hetsrc_power is not None:
            station.hetsrc.RF.power(hetsrc_power)

        if qubsrc_freq == 'dict':
            station.qubsrc.frequency(d["fq"])
        elif qubsrc_freq == None:
            pass
        else:
            station.qubsrc.frequency(qubsrc_freq)

        if hetsrc_freq == 'dict':
            station.hetsrc.frequency(d["f0"])
        elif hetsrc_freq == None:
            pass
        else:
            station.hetsrc.frequency(hetsrc_freq)

        station.qubsrc.modulation_rf('ON')
        station.qubsrc.output_rf('ON')
        station.RF.on()
        station.RF.pulsemod_source('EXT')
        station.RF.pulsemod_state('ON')
        station.RF.ref_LO_out('LO')
        station.LO.on()
        station.fg.ch1.state('OFF')
        station.awg.stop()
        station.awg.start()

        data = np.squeeze(controller.acquisition())[..., 0]
        mag, phase = np.abs(data), np.angle(data, deg=False)

        station.fg.ch1.state('OFF')
        station.awg.stop()
        station.qubsrc.modulation_rf('OFF')
        station.qubsrc.output_rf('OFF')
        station.RF.off()
        station.RF.pulsemod_source('EXT')
        station.RF.pulsemod_state('OFF')
        station.RF.ref_LO_out('OFF')
        station.LO.off()
        time.sleep(0.1)

        # it is unclear which combination of off and stop and sleep is required
        # but without them the timing goes wrong

        if fit:
            # rotate IQ data
            angle = dp.IQangle(mag * np.exp(1.j * phase))
            rotated_data = dp.IQrotate(mag * np.exp(1.j * phase), angle)

            # fit T2; still needs testing for robustness
            mod = lmfit.models.ExpressionModel('off + amp * exp(-x/t1)')
            xdat = times
            ydat = np.real(rotated_data)
            params = mod.make_params(off=ydat[-1],
                                     amp=ydat[0] - ydat[-1],
                                     t1=1e-6)
            params['t1'].set(min=1e-9)
            out = mod.fit(ydat, params, x=xdat)
            T2_time = out.params['t1']

            return [times, mag, phase, T2_time]

        else:
            return [times, mag, phase]

    if fit == True:
        return MeasurementFunction(return_alazar_trace, [
            DataParameter(
                name="delay_time" + str(suffix),
                unit="s",
                paramtype="array",
                independent=2,
            ),
            DataParameter(
                name="amplitude" + str(suffix),
                unit="",
                paramtype="array",
                extra_dependencies=["delay_time" + str(suffix)],
            ),
            DataParameter(
                name="phase" + str(suffix),
                unit="rad",
                paramtype="array",
                extra_dependencies=["delay_time" + str(suffix)],
            ),
            DataParameter(
                name="T2echo" + str(suffix),
                unit="s",
                paramtype="numeric",
            ),
        ])
    else:
        return MeasurementFunction(return_alazar_trace, [
            DataParameter(
                name="delay_time" + str(suffix),
                unit="s",
                paramtype="array",
                independent=2,
            ),
            DataParameter(
                name="amplitude" + str(suffix),
                unit="",
                paramtype="array",
                extra_dependencies=["delay_time" + str(suffix)],
            ),
            DataParameter(
                name="phase" + str(suffix),
                unit="rad",
                paramtype="array",
                extra_dependencies=["delay_time" + str(suffix)],
            ),
        ])
Пример #15
0
def measure_time_rabi(controller,
                      pulse_times,
                      setup_awg=False,
                      qubsrc_power=None,
                      qubsrc_freq=None,
                      hetsrc_power=None,
                      hetsrc_freq=None,
                      suffix='',
                      fit=False,
                      T1_guess=None,
                      **kw):
    def return_alazar_trace(d):

        if setup_awg:
            setup_time_rabi(controller=controller,
                            pulse_times=pulse_times,
                            **kw)

        times = pulse_times
        station = d["STATION"]

        if qubsrc_power is not None:
            station.qubsrc.power(qubsrc_power)
        if hetsrc_power is not None:
            station.hetsrc.RF.power(hetsrc_power)

        if qubsrc_freq == 'dict':
            station.qubsrc.frequency(d["fq"])
        elif qubsrc_freq == None:
            pass
        else:
            station.qubsrc.frequency(qubsrc_freq)

        if hetsrc_freq == 'dict':
            station.hetsrc.frequency(d["f0"])
        elif hetsrc_freq == None:
            pass
        else:
            station.hetsrc.frequency(hetsrc_freq)

        station.qubsrc.modulation_rf('ON')
        station.qubsrc.output_rf('ON')
        station.RF.on()
        station.RF.pulsemod_source('EXT')
        station.RF.pulsemod_state('ON')
        station.RF.ref_LO_out('LO')
        station.LO.on()
        station.fg.ch1.state('OFF')
        station.awg.stop()
        station.awg.start()

        data = np.squeeze(controller.acquisition())[..., 0]
        mag, phase = np.abs(data), np.angle(data, deg=False)

        station.fg.ch1.state('OFF')
        station.awg.stop()
        station.qubsrc.modulation_rf('OFF')
        station.qubsrc.output_rf('OFF')
        station.RF.off()
        station.RF.pulsemod_source('EXT')
        station.RF.pulsemod_state('OFF')
        station.RF.ref_LO_out('OFF')
        station.LO.off()
        time.sleep(0.1)

        if fit:

            angle = dp.IQangle(mag * np.exp(1.j * phase))
            rotated_data = dp.IQrotate(mag * np.exp(1.j * phase), angle)
            mod = lmfit.models.ExpressionModel(
                'off + amp * exp(-x/t1) * cos(2*pi/period*x)')
            xdat = times
            ydat = np.real(rotated_data)
            period_estimate = 2 * \
                xdat[np.argmax(np.abs(savgol_filter(ydat, 15, 3)-ydat[0]))]
            off_estimate = np.mean(ydat)
            print("0.5*period_estimate = ", period_estimate * 0.5 * 1e9)
            if ydat[0] > off_estimate:
                A_estimate = np.max(ydat) - np.min(ydat)
            else:
                A_estimate = np.min(ydat) - np.max(ydat)
            if T1_guess == None:
                T1_estimate = 1.5e-6
            elif T1_guess == 'dict':
                if "t1" in list(d.keys()) and d["t1"] < 40e-6:
                    T1_estimate = d["t1"]
                else:
                    print("Not in dict")
                    T1_estimate = 1.5e-6
                print("Using T1 = {} us for the Rabi".format(1e6 *
                                                             T1_estimate))
            else:
                T1_estimate = T1_guess
            params = mod.make_params(off=off_estimate,
                                     amp=A_estimate,
                                     t1=T1_estimate,
                                     period=period_estimate)
            params['t1'].set(min=1e-9)
            params['t1'].set(max=50e-6)
            params['period'].set(min=1e-9)
            params['period'].set(max=5e-6)
            out = mod.fit(ydat, params, x=xdat)
            pipulse_time = 1 * out.params['period'].value / 2
            if pipulse_time < 10e-9:
                pipulse_time = 3 * out.params['period'].value / 2
            d['pipulse'] = pipulse_time
            d['t1'] = out.params['t1']
            print("pi_pulse = ", pipulse_time * 1e9)
            return [times, mag, phase, pipulse_time]

        else:
            return [times, mag, phase]

    if fit == True:
        return MeasurementFunction(return_alazar_trace, [
            DataParameter(
                name="pulse_time" + str(suffix),
                unit="s",
                paramtype="array",
                independent=2,
            ),
            DataParameter(
                name="amplitude" + str(suffix),
                unit="",
                paramtype="array",
                extra_dependencies=["pulse_time" + str(suffix)],
            ),
            DataParameter(
                name="phase" + str(suffix),
                unit="rad",
                paramtype="array",
                extra_dependencies=["pulse_time" + str(suffix)],
            ),
            DataParameter(
                name="pipulse_length" + str(suffix),
                unit="s",
                paramtype="numeric",
            ),
        ])
    else:
        return MeasurementFunction(return_alazar_trace, [
            DataParameter(
                name="pulse_time" + str(suffix),
                unit="s",
                paramtype="array",
                independent=2,
            ),
            DataParameter(
                name="amplitude" + str(suffix),
                unit="",
                paramtype="array",
                extra_dependencies=["pulse_time" + str(suffix)],
            ),
            DataParameter(
                name="phase" + str(suffix),
                unit="rad",
                paramtype="array",
                extra_dependencies=["pulse_time" + str(suffix)],
            ),
        ])
Пример #16
0
def measure_ramsey(controller,
                   delays,
                   pulse_time,
                   readout_time,
                   qubsrc_power=None,
                   qubsrc_freq=None,
                   hetsrc_power=None,
                   hetsrc_freq=None,
                   navgs=500,
                   acq_time=2.56e-6,
                   setup_awg=True,
                   suffix='',
                   fit=False,
                   **kw):
    def return_alazar_trace(d):
        station = d["STATION"]
        times = delays

        if pulse_time == 'dict':
            setup_ramsey(controller,
                         delays,
                         d['pipulse'] / 2,
                         readout_time,
                         navgs=navgs,
                         acq_time=acq_time,
                         setup_awg=True,
                         **kw)
        else:
            setup_ramsey(controller,
                         delays,
                         pulse_time,
                         readout_time,
                         navgs=navgs,
                         acq_time=acq_time,
                         setup_awg=setup_awg,
                         **kw)

        if qubsrc_power is not None:
            station.qubsrc.power(qubsrc_power)
        if hetsrc_power is not None:
            station.hetsrc.RF.power(hetsrc_power)

        if qubsrc_freq == 'dict':
            station.qubsrc.frequency(d["fq"])
        elif qubsrc_freq == None:
            pass
        else:
            station.qubsrc.frequency(qubsrc_freq)

        if hetsrc_freq == 'dict':
            station.hetsrc.frequency(d["f0"])
        elif hetsrc_freq == None:
            pass
        else:
            station.hetsrc.frequency(hetsrc_freq)

        station.qubsrc.modulation_rf('ON')
        station.qubsrc.output_rf('ON')
        station.RF.on()
        station.RF.pulsemod_source('EXT')
        station.RF.pulsemod_state('ON')
        station.RF.ref_LO_out('LO')
        station.LO.on()
        station.fg.ch1.state('OFF')
        station.awg.stop()
        station.awg.start()

        data = np.squeeze(controller.acquisition())[..., 0]
        mag, phase = np.abs(data), np.angle(data, deg=False)

        station.fg.ch1.state('OFF')
        station.awg.stop()
        station.qubsrc.modulation_rf('OFF')
        station.qubsrc.output_rf('OFF')
        station.RF.off()
        station.RF.pulsemod_source('EXT')
        station.RF.pulsemod_state('OFF')
        station.RF.ref_LO_out('OFF')
        station.LO.off()
        time.sleep(0.1)

        # it is unclear which combination of off and stop and sleep is required
        # but without them the timing goes wrong

        if fit:
            # rotate IQ data
            angle = dp.IQangle(mag * np.exp(1.j * phase))
            rotated_data = dp.IQrotate(mag * np.exp(1.j * phase), angle)

            # fit Rabi; still needs work because it can be off by a factor of pi in the phase depending on the sign of the first value!
            mod = lmfit.models.ExpressionModel(
                'off + amp * exp(-x/t1)*sin(2*pi/period*(x + phase))')
            xdat = times
            ydat = np.real(rotated_data)
            period_estimate = 2 * \
                xdat[np.argmax(np.abs(savgol_filter(ydat, 15, 3)-ydat[0]))]
            # period_estimate = 4*xdat[np.argmax(np.abs(xdat-xdat[0]))]
            params = mod.make_params(off=np.mean(ydat),
                                     amp=ydat[0],
                                     t1=0.15e-6,
                                     period=period_estimate,
                                     phase=0)
            params['t1'].set(min=1e-9)
            out = mod.fit(ydat, params, x=xdat)
            T2_time = out.params['t1'].value

            return [times, mag, phase, T2_time]

        else:
            return [times, mag, phase]

    if fit == True:
        return MeasurementFunction(return_alazar_trace, [
            DataParameter(
                name="delay_time" + str(suffix),
                unit="s",
                paramtype="array",
                independent=2,
            ),
            DataParameter(
                name="amplitude" + str(suffix),
                unit="",
                paramtype="array",
                extra_dependencies=["delay_time" + str(suffix)],
            ),
            DataParameter(
                name="phase" + str(suffix),
                unit="rad",
                paramtype="array",
                extra_dependencies=["delay_time" + str(suffix)],
            ),
            DataParameter(
                name="T2ramsey" + str(suffix),
                unit="s",
                paramtype="numeric",
            ),
        ])
    else:
        return MeasurementFunction(return_alazar_trace, [
            DataParameter(
                name="delay_time" + str(suffix),
                unit="s",
                paramtype="array",
                independent=2,
            ),
            DataParameter(
                name="amplitude" + str(suffix),
                unit="",
                paramtype="array",
                extra_dependencies=["delay_time" + str(suffix)],
            ),
            DataParameter(
                name="phase" + str(suffix),
                unit="rad",
                paramtype="array",
                extra_dependencies=["delay_time" + str(suffix)],
            ),
        ])
Пример #17
0
    '''
    if max_field_strength > 1.5:
        showwarning(
            'Be aware that mu-metal shields are saturated by too large magnetic fields and will not work afterwards. '
            'Are you sure you want to go to more than 1.5 T?', ResourceWarning,
            'cqed/cqed/custom_pysweep_functions/magnet', 20)

    if np.sqrt(Bx**2 + By**2 + Bz**2) > max_field_strength:
        return bool(False)

    else:
        return bool(True)


@MakeMeasurementFunction([
    DataParameter(name='x', unit='T'),
    DataParameter(name='y', unit='T'),
    DataParameter(name='z', unit='T')
])
def measure_magnet_components(d):
    ''' Measure the x, y, z component of the magnet and return as list
    output: [x, y, z]
    '''
    station = d['STATION']
    x_meas = station.mgnt.x_measured()
    y_meas = station.mgnt.y_measured()
    z_meas = station.mgnt.z_measured()
    return [x_meas, y_meas, z_meas]


@MakeMeasurementFunction([
Пример #18
0
# Authors: Lukas Splitthoff, Lukas Gruenhaupt @TUDelft
# 04-DEC-2019
''' A set of functions to conveniently use for VNA measurements with pysweep.'''

from pysweep.core.measurementfunctions import MakeMeasurementFunction
from pysweep.databackends.base import DataParameter
import numpy as np


@MakeMeasurementFunction([
    DataParameter('frequency', 'Hz', 'array', True),
    DataParameter('amplitude', '', 'array'),
    DataParameter('phase', 'rad', 'array')
])
def return_vna_trace(d):
    """
    Pysweep VNA measurement function.
    Returns VNA frequency axis, linear amplitude and phase in radians.
    Keeps currently set VNA paramaters.
    """
    station = d['STATION']
    freqs = np.linspace(station.vna.S21.start(), station.vna.S21.stop(),
                        station.vna.S21.npts())

    if not station.vna.rf_power():
        station.vna.rf_on()

    vna_data = station.vna.S21.trace_mag_phase()

    return [freqs, vna_data[0], vna_data[1]]
Пример #19
0
def measure_qubit_frequency(frequencies,
                            suffix='',
                            save_trace=True,
                            peak_finder=None,
                            **kwargs):
    """Pysweep VNA measurement function that measures a qubit frequency `fq` and stores it in the dictionary, 
    similar to 'measure_resonance_frequency'. 

    Args:
        frequencies (array, Hz): the frequencies over which to perform the 2tone spectroscopy.
        suffix (int): suffix added to the DataParameters.
        save_trace (boolean): whether to save the full VNA trace and the determined f0 or only f0.
        peak_finder: Function that finds a peak from VNA output. See for example general_tools -> peak_finding.py
        kwargs: see `measure_2tone_sweep` and `setup_CW_sweep`.


    Returns:
    Pysweep measurement function
    """
    def measurement_function(d):
        freqs, mag, phase = measure_twotone_sweep(frequencies=frequencies,
                                                  **kwargs)(d)

        m0 = peak_finder(freqs, mag)

        if m0 == None:
            raise Exception(
                "Failed to find a resonance."
            )  # needs work, can implement alternative strategies
        d["fq"] = m0

        if save_trace == True:
            return [frequencies, mag, phase, m0]
        else:
            return [m0]

    if save_trace == True:
        return MeasurementFunction(measurement_function, [
            DataParameter(
                name="frequency" + str(suffix),
                unit="Hz",
                paramtype="array",
                independent=2,
            ),
            DataParameter(
                name="amplitude" + str(suffix),
                unit="",
                paramtype="array",
                extra_dependencies=["frequency" + str(suffix)],
            ),
            DataParameter(
                name="phase" + str(suffix),
                unit="rad",
                paramtype="array",
                extra_dependencies=["frequency" + str(suffix)],
            ),
            DataParameter(
                name="qubit_frequency" + str(suffix),
                unit="Hz",
                paramtype="numeric",
            ),
        ])
    else:
        return MeasurementFunction(measurement_function, [
            DataParameter(
                name="qubit_frequency" + str(suffix),
                unit="Hz",
                paramtype="numeric",
            ),
        ])
Пример #20
0
def measure_twotone_sweep(frequencies,
                          cw_frequency='dict',
                          qubsrc_power=None,
                          settling_time=10e-6,
                          suffix='',
                          **kwargs):
    """Pysweep VNA measurement function that creates a quasi-hardware sweep for doing two-tone spectroscopy. 
    In essence it combines doing measure_cw_point versus a sweep object of frequencies into a single measurement function.
    By creating a dedicated measurement function for this, one can easily wrap it with other functions,
    for example to do adaptive qubit spectroscopy or to find the qubit frequency and pass that on to a subsequent function.
    Think for example of measuring the Rabi frequency versus a gate voltage. 
    Perhaps this construction is not neccesary, but I could not think of a way around it. 
    Furthermore, currently the qubsrc is hardcoded. It would be better to give it as an input. But it gets a bit tricky because
    not every source has the same commands for on, off, modulation, etc. 

    Args:
        frequencies (array, Hz): the frequencies over which to perform the 2tone spectroscopy.
        cw_frequency (str, numeric): the CW frequency at which to perform the measurement.
        When this is 'dict', the value d["f0"] is used. Otherwise the input value is used.
        qubsrc_power (dBm): the power set on the qubsrc.
        settling_time (s): the waiting time after setting the qubsrc to its next point in frequencies.
        suffix (int): suffix added to the DataParameters.
        kwargs: see `setup_CW_sweep`.


    Returns:
    Pysweep measurement function
    """
    def measurement_function(d):
        station = d["STATION"]
        station.qubsrc.output_rf('ON')
        station.qubsrc.modulation_rf('OFF')

        if qubsrc_power != None:
            station.qubsrc.power(qubsrc_power)

        mag = np.zeros_like(frequencies)
        phase = np.zeros_like(frequencies)

        if cw_frequency == 'dict':
            setup_CW_sweep(station=station, cw_frequency=d["f0"], **kwargs)
        elif cw_frequency is not None or bool(kwargs):
            setup_CW_sweep(station=station,
                           cw_frequency=cw_frequency,
                           **kwargs)

        for ii in range(len(frequencies)):
            station.qubsrc.frequency(frequencies[ii])
            time.sleep(settling_time)
            data = measure_cw_point()(d)
            mag[ii] = data[0]
            phase[ii] = data[1]

        station.qubsrc.output_rf('OFF')

        return [frequencies, mag, phase]

    return MeasurementFunction(measurement_function, [
        DataParameter(
            name="frequency" + str(suffix),
            unit="Hz",
            paramtype="array",
            independent=2,
        ),
        DataParameter(
            name="amplitude" + str(suffix),
            unit="",
            paramtype="array",
            extra_dependencies=["frequency" + str(suffix)],
        ),
        DataParameter(
            name="phase" + str(suffix),
            unit="rad",
            paramtype="array",
            extra_dependencies=["frequency" + str(suffix)],
        ),
    ])