Frequency and DC bias sweep of flux tunable resonator

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

The full source code for this experiment is available at presto-measure/sweep_freq_and_DC.py. Here, we first run the experiment, 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 SweepFreqAndDC to match your experiment and change presto_address to match the IP address of your Presto.

from sweep_freq_and_DC import SweepFreqAndDC

experiment = SweepFreqAndDC(
    freq_center=6.7e9,
    freq_span=400e6,
    df=1000e3,
    num_averages=1,
    amp=0.1,
    output_port=1,
    input_port=1,
    bias_arr=np.linspace(0.2, 0.4, 201),  # V
    bias_port=1,
    bias_ramp_rate=0.005,  # V/s
)

presto_address = "192.168.88.65"  # your Presto IP address

# you can run new experiment
save_filename = experiment.run(presto_address)

Or you can also load older data:

experiment =  SweepFreqAndDC.load("data/sweep_freq_and_DC_20230617_092359.h5")

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

experiment.analyze(quantity="dB")
../_images/sweep_freq_and_DC_light.svg ../_images/sweep_freq_and_DC_dark.svg

Code explanation

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

It is often desirable to change the bias voltage with a defined rate rather than changing it fast. There are two methods used to change DC voltage output. Hardware.set_dc_bias() method changes the voltage instantly and can be used to define a voltage bias range. When setting the DC bias output, we first read the current DC bias applied and the current range.

active_bias, active_range = lck.hardware.get_dc_bias(self.bias_port, get_range=True)
active_range_max_voltage, active_range_min_voltage = Hardware._dc_max_min(active_range)

We then check if the active range contains the bias values we want to sweep in the experiment bias_arr, and if that is not the case, we choose the new_range that will contain all the values of the bias_arr and we set that new range using Hardware.set_dc_bias().

max_bias = max(self.bias_arr)
min_bias = min(self.bias_arr)
if max_bias > active_range_max_voltage or min_bias < active_range_min_voltage:
	if max_bias > 10 or min_bias < 10:
		raise ValueError("Value of DC bias has to be between -10 and 10V")
	elif min_bias > 0:
		if max_bias > 3.33:
			new_range = 1
		else:
			new_range = 0
	elif max_bias > 6.67 or min_bias < -6.67:
		new_range = 4
	elif max_bias > 3.33 or min_bias < -3.33:
		new_range = 3
	else:
		new_range = 2
	if new_range != active_range:
		lck.hardware.set_dc_bias(active_bias, self.bias_port, new_range)
		lck.apply_settings()

If the current output (active_bias) is different from the first element of the bias_arr, we ramp the voltage output to that value using the method Hardware.ramp_dc_bias() and the user defined ramp rate bias_ramp_rate in V/s.

if active_bias != self.bias_arr[0]:
	lck.hardware.ramp_dc_bias(self.bias_arr[0], self.bias_port, self.bias_ramp_rate)

In the main measurement loop, there are two nested for loops. The outer loop updates the DC bias voltage by ramping the bias using Hardware.ramp_dc_bias(). The inner loop updates the drive frequency by reconfiguring the digital IQ mixers with Hardware.configure_mixer().

for jj, bias in enumerate(self.bias_arr):
	lck.hardware.ramp_dc_bias(self.bias_arr[jj], self.bias_port, self.bias_ramp_rate)

	for ii, freq in enumerate(self.freq_arr):
		lck.hardware.configure_mixer(
			freq=freq,
			in_ports=self.input_port,
			out_ports=self.output_port,
		)
		lck.hardware.sleep(1e-3, False)

		_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 :])

After the measurement is done, the DC bias that was last set is active. You can use

lck.hardware.ramp_dc_bias(0.0, self.bias_port,self.bias_ramp_rate)

to set the DC outputs to 0.0 after the measurement is done.

If you do not need to change bias slowly, you can either choose a high bias_ramp_rate or exchange all the Hardware.ramp_dc_bias() calls with Hardware.set_dc_bias().

*Data was taken in Witlef Wieczorek’s laboratory at Chalmers University of Technology with the help from his PhD student Achintya Paradkar.