Flux-dependent qubit spectroscopy Experiment¶
This notebook demonstrates how to perform qubit spectroscopy if the qubit resonance frequnecy depends on a second parameter, e.g. an external flux. We perform a 2D sweep of the amplitude of the applied external flux and the frequency of an excitation tone applied to the qubit itself.
0. General Imports and Definitions¶
0.1 Python Imports¶
In [ ]:
Copied!
# Helpers:
from laboneq.contrib.example_helpers.generate_device_setup import (
generate_device_setup_qubits,
)
from laboneq.contrib.example_helpers.plotting.plot_helpers import *
# LabOne Q:
from laboneq.simple import *
# Helpers:
from laboneq.contrib.example_helpers.generate_device_setup import (
generate_device_setup_qubits,
)
from laboneq.contrib.example_helpers.plotting.plot_helpers import *
# 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.
In [ ]:
Copied!
# specify the number of qubits you want to use
number_of_qubits = 2
# 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",
"number_of_channels": 8,
"options": None,
}
],
shfqc=[
{
"serial": "DEV12001",
"number_of_channels": 6,
"readout_multiplex": 6,
"options": None,
}
],
multiplex_drive_lines=True,
include_flux_lines=True,
server_host="localhost",
setup_name=f"my_{number_of_qubits}_tunable_qubit_setup",
)
q0, q1 = qubits[:2]
# specify the number of qubits you want to use
number_of_qubits = 2
# 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",
"number_of_channels": 8,
"options": None,
}
],
shfqc=[
{
"serial": "DEV12001",
"number_of_channels": 6,
"readout_multiplex": 6,
"options": None,
}
],
multiplex_drive_lines=True,
include_flux_lines=True,
server_host="localhost",
setup_name=f"my_{number_of_qubits}_tunable_qubit_setup",
)
q0, q1 = qubits[:2]
In [ ]:
Copied!
# 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)
# 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 Definition¶
In [ ]:
Copied!
# signal map for qubit
def map_qubit(qubit):
return {
"drive": qubit.signals["drive"],
"flux": qubit.signals["flux"],
"measure": qubit.signals["measure"],
"acquire": qubit.signals["acquire"],
}
# signal map for qubit
def map_qubit(qubit):
return {
"drive": qubit.signals["drive"],
"flux": qubit.signals["flux"],
"measure": qubit.signals["measure"],
"acquire": qubit.signals["acquire"],
}
In [ ]:
Copied!
## define pulses
# flux pulse - applied during whole experimental pulse sequence
const_flux = pulse_library.const(uid="const_flux", length=600e-9, amplitude=1.0)
# qubit drive pulse
const_iq_100ns = pulse_library.const(uid="const_iq_100ns", length=100e-9, amplitude=1.0)
# readout drive pulse
readout_pulse = pulse_library.const(uid="readout_pulse", length=400e-9, amplitude=1.0)
# readout weights for integration
readout_weighting_function = pulse_library.const(
uid="readout_weighting_function", length=400e-9, amplitude=1.0
)
## define pulses
# flux pulse - applied during whole experimental pulse sequence
const_flux = pulse_library.const(uid="const_flux", length=600e-9, amplitude=1.0)
# qubit drive pulse
const_iq_100ns = pulse_library.const(uid="const_iq_100ns", length=100e-9, amplitude=1.0)
# readout drive pulse
readout_pulse = pulse_library.const(uid="readout_pulse", length=400e-9, amplitude=1.0)
# readout weights for integration
readout_weighting_function = pulse_library.const(
uid="readout_weighting_function", length=400e-9, amplitude=1.0
)
In [ ]:
Copied!
# define sweep parameter - sweep over the frequency of a qubit excitation pulse
start = 40e6
stop = 200e6
count = 11
freq_sweep = LinearSweepParameter(
uid="qubit_frequency", start=start, stop=stop, count=count
)
# Second sweep: Amplitude of the flux pulsed
flux_count = 21
flux_sweep = LinearSweepParameter(uid="flux_qubit", start=0, stop=1, count=flux_count)
# define number of averages
average_exponent = 4 # used for 2^n averages, n=average_exponent, maximum: n = 17
# define sweep parameter - sweep over the frequency of a qubit excitation pulse
start = 40e6
stop = 200e6
count = 11
freq_sweep = LinearSweepParameter(
uid="qubit_frequency", start=start, stop=stop, count=count
)
# Second sweep: Amplitude of the flux pulsed
flux_count = 21
flux_sweep = LinearSweepParameter(uid="flux_qubit", start=0, stop=1, count=flux_count)
# define number of averages
average_exponent = 4 # used for 2^n averages, n=average_exponent, maximum: n = 17
2.1 Pulse Sequence¶
In [ ]:
Copied!
# Create Experiment - no explicit mapping to qubit lines
exp = Experiment(
uid="Qubit Flux Spectroscopy",
signals=[
ExperimentSignal("flux"),
ExperimentSignal("drive"),
ExperimentSignal("measure"),
ExperimentSignal("acquire"),
],
)
## experimental pulse sequence
with exp.acquire_loop_rt(
uid="shots",
count=pow(2, average_exponent),
averaging_mode=AveragingMode.CYCLIC,
acquisition_type=AcquisitionType.INTEGRATION,
):
with exp.sweep(uid="sweep", parameter=freq_sweep):
# inner loop - real-time, sequential averaging in standard integration mode
# inner loop - adjust flux bias to qubit
with exp.sweep(uid="flux_sweep", parameter=flux_sweep):
with exp.section(uid="flux bias"):
exp.play(signal="flux", pulse=const_flux, amplitude=flux_sweep)
# qubit excitation pulse - frequency will be swept
with exp.section(uid="qubit_excitation"):
# allow for transients to settle
exp.delay(signal="drive", time=100e-9)
# play excitation pulse
exp.play(signal="drive", pulse=const_iq_100ns)
# readout and data acquisition
with exp.section(uid="qubit_readout", play_after="qubit_excitation"):
# play readout pulse
exp.play(signal="measure", pulse=readout_pulse)
# signal data acquisition
exp.acquire(
signal="acquire",
handle="ac_0",
kernel=readout_weighting_function,
)
# relax time after readout - for signal processing and qubit relaxation to ground state
with exp.section(uid="relax", play_after="qubit_readout"):
exp.delay(signal="measure", time=1e-6)
# Create Experiment - no explicit mapping to qubit lines
exp = Experiment(
uid="Qubit Flux Spectroscopy",
signals=[
ExperimentSignal("flux"),
ExperimentSignal("drive"),
ExperimentSignal("measure"),
ExperimentSignal("acquire"),
],
)
## experimental pulse sequence
with exp.acquire_loop_rt(
uid="shots",
count=pow(2, average_exponent),
averaging_mode=AveragingMode.CYCLIC,
acquisition_type=AcquisitionType.INTEGRATION,
):
with exp.sweep(uid="sweep", parameter=freq_sweep):
# inner loop - real-time, sequential averaging in standard integration mode
# inner loop - adjust flux bias to qubit
with exp.sweep(uid="flux_sweep", parameter=flux_sweep):
with exp.section(uid="flux bias"):
exp.play(signal="flux", pulse=const_flux, amplitude=flux_sweep)
# qubit excitation pulse - frequency will be swept
with exp.section(uid="qubit_excitation"):
# allow for transients to settle
exp.delay(signal="drive", time=100e-9)
# play excitation pulse
exp.play(signal="drive", pulse=const_iq_100ns)
# readout and data acquisition
with exp.section(uid="qubit_readout", play_after="qubit_excitation"):
# play readout pulse
exp.play(signal="measure", pulse=readout_pulse)
# signal data acquisition
exp.acquire(
signal="acquire",
handle="ac_0",
kernel=readout_weighting_function,
)
# relax time after readout - for signal processing and qubit relaxation to ground state
with exp.section(uid="relax", play_after="qubit_readout"):
exp.delay(signal="measure", time=1e-6)
In [ ]:
Copied!
# define experiment calibration - sweep over qubit drive frequency
exp_calib = Calibration()
exp_calib["drive"] = SignalCalibration(
oscillator=Oscillator(
frequency=freq_sweep,
modulation_type=ModulationType.HARDWARE,
)
)
# define experiment calibration - sweep over qubit drive frequency
exp_calib = Calibration()
exp_calib["drive"] = SignalCalibration(
oscillator=Oscillator(
frequency=freq_sweep,
modulation_type=ModulationType.HARDWARE,
)
)
2.2 Run the Experiment and Plot the Measurement Results and Pulse Sequence¶
In [ ]:
Copied!
# set calibration and signal map for qubit 0
exp.set_calibration(exp_calib)
exp.set_signal_map(map_qubit(q0))
# run experiment on qubit 0
my_results = session.run(exp)
# set calibration and signal map for qubit 0
exp.set_calibration(exp_calib)
exp.set_signal_map(map_qubit(q0))
# run experiment on qubit 0
my_results = session.run(exp)
In [ ]:
Copied!
# Plot simulated output signals
plot_simulation(session.compiled_experiment, start_time=0, length=10e-6)
# Plot simulated output signals
plot_simulation(session.compiled_experiment, start_time=0, length=10e-6)
In [ ]:
Copied!
# plot measurement results
plot_result_3d(my_results, "ac_0")
# plot measurement results
plot_result_3d(my_results, "ac_0")
In [ ]:
Copied!
# use pulse sheet viewer to display the pulse sequence - only recommended for small number of averages and sweep steps to avoid performance issues
show_pulse_sheet("Qubit Flux Spectroscopy", session.compiled_experiment)
# use pulse sheet viewer to display the pulse sequence - only recommended for small number of averages and sweep steps to avoid performance issues
show_pulse_sheet("Qubit Flux Spectroscopy", session.compiled_experiment)
In [ ]:
Copied!
# set calibration and signal map for qubit 1
exp.set_calibration(exp_calib)
exp.set_signal_map(map_qubit(q1))
# run experiment on qubit 1
my_results = session.run(exp)
# set calibration and signal map for qubit 1
exp.set_calibration(exp_calib)
exp.set_signal_map(map_qubit(q1))
# run experiment on qubit 1
my_results = session.run(exp)
In [ ]:
Copied!