Propagation delay¶
This notebook shows you how to perform a propagation delay experiment. You'll sweep the delay of the qantum analyzer integration and then find the maximum result.
0. LabOne Q Imports¶
You'll begin by importing laboneq.simple
and some extra helper functions to run the examples.
import time
from pathlib import Path
# Helpers:
from laboneq.contrib.example_helpers.generate_device_setup import (
generate_device_setup_qubits,
)
from laboneq.contrib.example_helpers.plotting.plot_helpers import plot_results
# LabOne Q:
from laboneq.simple import *
1. Device Setup¶
Below, you'll create a device setup and choose to run this notebook in emulated mode or directly on the control hardware, by specifying use_emulation = True/False
respectively.
If you run on your hardware, you need to generate a device setup first, please have a look at our device setup tutorial for how to do this in general. Here, we use a helper functions to generate the device setup and a set up qubit objects with pre-defined parameters.
# specify the number of qubits you want to use
number_of_qubits = 6
# generate the device setup and the qubit objects using a helper function
device_setup, qubits = generate_device_setup_qubits(
number_qubits=number_of_qubits,
pqsc=[{"serial": "DEV10001"}],
hdawg=[
{
"serial": "DEV8001",
"zsync": 0,
"number_of_channels": 8,
"options": None,
}
],
shfqc=[
{
"serial": "DEV12001",
"zsync": 1,
"number_of_channels": 6,
"readout_multiplex": 6,
"options": None,
}
],
include_flux_lines=True,
server_host="localhost",
setup_name=f"my_{number_of_qubits}_tunable_qubit_setup",
)
# use emulation mode - no connection to instruments
use_emulation = True
# create and connect to a session
session = Session(device_setup=device_setup)
session.connect(do_emulation=use_emulation)
2. Experiment Parameters¶
Now you'll define the frequency sweep parameters and pulse to use in your experiment.
delay_sweep = LinearSweepParameter(
uid="delay_sweep_param", start=0, stop=1.0e-6, count=21
)
# define number of averages
# used for 2^num_averages, maximum: num_averages = 17
num_averages = 4
# readout pulse parameters and definition
envelope_duration = 2.048e-6
envelope_rise_fall_time = 0.05e-6
readout_pulse = pulse_library.gaussian_square(
uid="readout_pulse", length=envelope_duration, amplitude=0.9
)
3. Experiment Definition¶
You'll now create a function to generate your propagation delay experiment. In this experiment, you'll pass the delay_sweep
defined previously as an argument to the near-time sweep section. Within the real-time acquisition section, you'll set use INTEGRATION
as your acquisition type, and you'll create a section containing a play
and an acquire
command.
# function that defines a resonator spectroscopy experiment, and takes the frequency sweep as a parameter
def propagation_delay(readout_pulse, delay_sweep):
# Create resonator spectroscopy experiment - uses only readout drive and signal acquisition
exp_prop_delay = Experiment(
uid="Propagation Delay Measurement",
signals=[
ExperimentSignal("measure"),
ExperimentSignal("acquire"),
],
)
## define experimental sequence
# outer loop - vary drive frequency
with exp_prop_delay.sweep(uid="del_sweep", parameter=delay_sweep):
with exp_prop_delay.acquire_loop_rt(
uid="shots",
count=2**num_averages,
acquisition_type=AcquisitionType.INTEGRATION,
):
# readout pulse and data acquisition
with exp_prop_delay.section(uid="spectroscopy"):
# play resonator excitation pulse
exp_prop_delay.play(signal="measure", pulse=readout_pulse)
# resonator signal readout
exp_prop_delay.acquire(
signal="acquire", handle="res_prop_delay", kernel=readout_pulse
)
# relax time after readout - for signal processing and qubit relaxation to ground state
with exp_prop_delay.section(uid="relax", length=1e-6):
exp_prop_delay.reserve(signal="measure")
cal = Calibration()
cal["acquire"] = SignalCalibration(port_delay=delay_sweep)
exp_prop_delay.set_calibration(cal)
return exp_prop_delay
3.1 Signal Map¶
Before running the experiment, you'll define and set the mapping between the experimental and logical lines.
# signal maps for a qubit - maps the logical signal of the device setup to the experimental signals of the experiment
def res_spec_map(qubit):
signal_map = {
"measure": device_setup.logical_signal_groups[f"{qubit}"].logical_signals[
"measure"
],
"acquire": device_setup.logical_signal_groups[f"{qubit}"].logical_signals[
"acquire"
],
}
return signal_map
# pass sweep and pulse to experiment and apply signal map
exp_prop_delay = propagation_delay(readout_pulse, delay_sweep)
exp_prop_delay.set_signal_map(res_spec_map("q0"))
3.2 Compile and Generate Pulse Sheet¶
Now, you'll compile the experiment and generate a pulse sheet.
# compile the experiment on the open instrument session
compiled_prop_delay = session.compile(exp_prop_delay)
Path("Pulse_Sheets").mkdir(parents=True, exist_ok=True)
# generate a pulse sheet to inspect experiment before runtime
show_pulse_sheet("Pulse_Sheets/Propagation_Delay", compiled_prop_delay)
3.3 Run, Save, and Plot Results¶
Finally, you'll run the experiment, save, and plot the results.
# run the compiled experiemnt
prop_delay_results = session.run(compiled_prop_delay)
timestamp = time.strftime("%Y%m%dT%H%M%S")
Path("Results").mkdir(parents=True, exist_ok=True)
save(prop_delay_results, f"Results/{timestamp}_prop_delay_results.json")
print(f"File saved as Results/{timestamp}_prop_delay_results.json")
plot_results(prop_delay_results, phase=True)