Power sweep of resonator

Using lockin mode we perform a 2D sweep of the amplitude and frequency of the drive to the resonator.

This experiment is an extension of the previous chapter in this tutorial: Resonator spectroscopy. The full source code for this experiment is available at presto-measure/sweep_power.py. Here, we first run the experiment and fit the resonator response, then we explain the main parts of the code.

You can create a new experiment and run it on your Presto. Be sure to change the parameters of SweepPower to match your experiment and change presto_address to match the IP address of your Presto.

from sweep_power import SweepPower
import numpy as np

experiment = SweepPower(
    freq_center=6e9,
    freq_span=5e6,
    df=100e3,
    num_averages=100,
    amp_arr=np.linspace(0.1, 1, 10),
    output_port=1,
    input_port=1,
)

presto_address = "192.168.88.65"  # your Presto IP address
save_filename = experiment.run(presto_address)

Or you can also load older data:

experiment = SweepPower.load("data/sweep_power_20220211_183107.h5")

In either case, we analyze the data to get a nice plot:

experiment.analyze()
../_images/sweep_power_light.svg ../_images/sweep_power_dark.svg

If resonator_tools is available, we perform a fit to extract resonance frequency and internal and external quality factors for a slice of the data at the selected drive amplitude.

Code explanation

Here we discuss the main part of the code inside the SweepPower class: the measurement loop. The full code is available at presto-measure/sweep_power.py. See also the previous chapter of this tutorial for a more detailed breakdown of the code.

There are two nested for loops. The outer loop updates the amplitude of the resonator drive by setting it into the OutputGroup. The inner loop updates the drive frequency by reconfiguring the digital IQ mixers with Hardware.configure_mixer().

for jj, amp in enumerate(self.amp_arr):
    og.set_amplitudes(amp)
    lck.apply_settings()

    for ii, freq in enumerate(self.freq_arr):
        lck.hardware.configure_mixer(freq, in_ports=self.input_port, out_ports=self.output_port)
        lck.apply_settings()

        _d = lck.get_pixels(self.num_skip + self.num_averages, quiet=True)
        data_i = _d[self.input_port][1][:, 0]
        data_q = _d[self.input_port][2][:, 0]
        data = data_i.real + 1j * data_q.real  # using zero IF

        self.resp_arr[jj, ii] = np.mean(data[-self.num_averages :])