e-f transition spectroscopy¶
In this reference notebook, you'll learn how to use LabOne Q's logical signals lines to perform spectroscopy of higher qubit levels. This functionality requires an SHFSG or SHFQC and relies on using the command table instead of playWave
commands.
0. General Imports and Definitions¶
0.1 Python Imports¶
In [ ]:
Copied!
# LabOne Q:
from laboneq.simple import *
# Helpers:
from laboneq.contrib.example_helpers.plotting.plot_helpers import plot_simulation
from laboneq.contrib.example_helpers.generate_example_datastore import (
generate_example_datastore,
get_first_named_entry,
)
# LabOne Q:
from laboneq.simple import *
# Helpers:
from laboneq.contrib.example_helpers.plotting.plot_helpers import plot_simulation
from laboneq.contrib.example_helpers.generate_example_datastore import (
generate_example_datastore,
get_first_named_entry,
)
In [ ]:
Copied!
# Build an in-memory data store with device setup and qubit parameters for the
# example notebooks
setup_db = generate_example_datastore(in_memory=True)
# Build an in-memory data store with device setup and qubit parameters for the
# example notebooks
setup_db = generate_example_datastore(in_memory=True)
1. Define Device Setup and Calibration¶
1.1 Define a Device Setup¶
We'll load a descriptor file to define our device setup and logical signal lines. We could, instead, explicitly include the descriptor here as a string and then use DeviceSetup.from_descriptor()
below. Choose the best method that works for you!
In [ ]:
Copied!
# load a calibrated device setup from the dummy database
device_setup = get_first_named_entry(db=setup_db, name="6_qubit_setup_shfqc_calibrated")
use_emulation = True
# load a calibrated device setup from the dummy database
device_setup = get_first_named_entry(db=setup_db, name="6_qubit_setup_shfqc_calibrated")
use_emulation = True
2. e-f Transition Spectroscopy¶
Sweep the pulse frequency of a qubit drive pulse to determine the frequency of the e-f transition. This assumes that a pi-pulse for the first excited state is already calibrated.
2.1 Define the Experiment¶
In [ ]:
Copied!
## define pulses
# qubit pi-pulse for first excited state
x180 = pulse_library.drag(uid="x180", length=24e-9, amplitude=0.5, sigma=0.3, beta=0.2)
# long spectroscopy pulse for e-f transition - frequency will be swept
ef_spec_pulse = pulse_library.const(uid="ef_pulse", length=10e-6, amplitude=1.0)
# readout drive pulse
readout_pulse = pulse_library.const(uid="readout_pulse", length=400e-9, amplitude=0.2)
# readout integration weights
readout_weighting_function = pulse_library.const(
uid="readout_weighting_function", length=400e-9, amplitude=0.8
)
## define pulses
# qubit pi-pulse for first excited state
x180 = pulse_library.drag(uid="x180", length=24e-9, amplitude=0.5, sigma=0.3, beta=0.2)
# long spectroscopy pulse for e-f transition - frequency will be swept
ef_spec_pulse = pulse_library.const(uid="ef_pulse", length=10e-6, amplitude=1.0)
# readout drive pulse
readout_pulse = pulse_library.const(uid="readout_pulse", length=400e-9, amplitude=0.2)
# readout integration weights
readout_weighting_function = pulse_library.const(
uid="readout_weighting_function", length=400e-9, amplitude=0.8
)
In [ ]:
Copied!
# set up sweep parameter - drive amplitude
start = 25e6
stop = 250e6
count = 25
frequency_sweep = LinearSweepParameter(
uid="frequency", start=start, stop=stop, count=count
)
# number of averages
average_exponent = 10 # used for 2^n averages, n=average_exponent, maximum: n = 17
# Create Experiment
exp_ef_spec = Experiment(
uid="e-f spectroscopy",
signals=[
ExperimentSignal("drive"),
ExperimentSignal("drive_ef"),
ExperimentSignal("measure"),
ExperimentSignal("acquire"),
],
)
## experimental pulse sequence
# outer loop - real-time, cyclic averaging in standard integration mode
with exp_ef_spec.acquire_loop_rt(
uid="shots",
count=pow(2, average_exponent),
averaging_mode=AveragingMode.CYCLIC,
acquisition_type=AcquisitionType.INTEGRATION,
):
# inner loop - real-time frequency sweep of qubit e-f drive pulse
with exp_ef_spec.sweep(uid="sweep", parameter=frequency_sweep):
# qubit excitation - pulse amplitude will be swept
with exp_ef_spec.section(
uid="qubit_excitation",
on_system_grid=True,
alignment=SectionAlignment.RIGHT,
):
exp_ef_spec.play(signal="drive", pulse=x180)
with exp_ef_spec.section(
uid="qubit_ef_excitation",
play_after="qubit_excitation",
on_system_grid=True,
alignment=SectionAlignment.RIGHT,
):
exp_ef_spec.play(signal="drive_ef", pulse=ef_spec_pulse)
# qubit readout pulse and data acquisition
with exp_ef_spec.section(uid="qubit_readout", play_after="qubit_ef_excitation"):
# play readout pulse
exp_ef_spec.play(signal="measure", pulse=readout_pulse)
# signal data acquisition
exp_ef_spec.acquire(
signal="acquire",
handle="ac_0",
kernel=readout_weighting_function,
)
# relax time after readout - for signal processing and qubit relaxation to groundstate
with exp_ef_spec.section(uid="relax"):
exp_ef_spec.delay(signal="measure", time=100e-9)
# set up sweep parameter - drive amplitude
start = 25e6
stop = 250e6
count = 25
frequency_sweep = LinearSweepParameter(
uid="frequency", start=start, stop=stop, count=count
)
# number of averages
average_exponent = 10 # used for 2^n averages, n=average_exponent, maximum: n = 17
# Create Experiment
exp_ef_spec = Experiment(
uid="e-f spectroscopy",
signals=[
ExperimentSignal("drive"),
ExperimentSignal("drive_ef"),
ExperimentSignal("measure"),
ExperimentSignal("acquire"),
],
)
## experimental pulse sequence
# outer loop - real-time, cyclic averaging in standard integration mode
with exp_ef_spec.acquire_loop_rt(
uid="shots",
count=pow(2, average_exponent),
averaging_mode=AveragingMode.CYCLIC,
acquisition_type=AcquisitionType.INTEGRATION,
):
# inner loop - real-time frequency sweep of qubit e-f drive pulse
with exp_ef_spec.sweep(uid="sweep", parameter=frequency_sweep):
# qubit excitation - pulse amplitude will be swept
with exp_ef_spec.section(
uid="qubit_excitation",
on_system_grid=True,
alignment=SectionAlignment.RIGHT,
):
exp_ef_spec.play(signal="drive", pulse=x180)
with exp_ef_spec.section(
uid="qubit_ef_excitation",
play_after="qubit_excitation",
on_system_grid=True,
alignment=SectionAlignment.RIGHT,
):
exp_ef_spec.play(signal="drive_ef", pulse=ef_spec_pulse)
# qubit readout pulse and data acquisition
with exp_ef_spec.section(uid="qubit_readout", play_after="qubit_ef_excitation"):
# play readout pulse
exp_ef_spec.play(signal="measure", pulse=readout_pulse)
# signal data acquisition
exp_ef_spec.acquire(
signal="acquire",
handle="ac_0",
kernel=readout_weighting_function,
)
# relax time after readout - for signal processing and qubit relaxation to groundstate
with exp_ef_spec.section(uid="relax"):
exp_ef_spec.delay(signal="measure", time=100e-9)
In [ ]:
Copied!
# define signal maps for qubit 0
map_q0 = {
"drive": device_setup.logical_signal_groups["q0"].logical_signals["drive_line"],
"drive_ef": device_setup.logical_signal_groups["q0"].logical_signals[
"drive_line_ef"
],
"measure": device_setup.logical_signal_groups["q0"].logical_signals["measure_line"],
"acquire": device_setup.logical_signal_groups["q0"].logical_signals["acquire_line"],
}
# ... - and qubit 1
map_q1 = {
"drive": device_setup.logical_signal_groups["q1"].logical_signals["drive_line"],
"drive_ef": device_setup.logical_signal_groups["q1"].logical_signals[
"drive_line_ef"
],
"measure": device_setup.logical_signal_groups["q1"].logical_signals["measure_line"],
"acquire": device_setup.logical_signal_groups["q1"].logical_signals["acquire_line"],
}
# define signal maps for qubit 0
map_q0 = {
"drive": device_setup.logical_signal_groups["q0"].logical_signals["drive_line"],
"drive_ef": device_setup.logical_signal_groups["q0"].logical_signals[
"drive_line_ef"
],
"measure": device_setup.logical_signal_groups["q0"].logical_signals["measure_line"],
"acquire": device_setup.logical_signal_groups["q0"].logical_signals["acquire_line"],
}
# ... - and qubit 1
map_q1 = {
"drive": device_setup.logical_signal_groups["q1"].logical_signals["drive_line"],
"drive_ef": device_setup.logical_signal_groups["q1"].logical_signals[
"drive_line_ef"
],
"measure": device_setup.logical_signal_groups["q1"].logical_signals["measure_line"],
"acquire": device_setup.logical_signal_groups["q1"].logical_signals["acquire_line"],
}
In [ ]:
Copied!
# define experiment calibration
exp_calibration = Calibration(
{
"drive_ef": SignalCalibration(
oscillator=Oscillator(
# WORKAROUND: when sweeping an oscillator on a logical line using the oscillator switching feature, need to ensure that the uid of the swept oscillator is sorted() first
uid="ef_drive_osc",
frequency=frequency_sweep,
modulation_type=ModulationType.HARDWARE,
)
)
}
)
# define experiment calibration
exp_calibration = Calibration(
{
"drive_ef": SignalCalibration(
oscillator=Oscillator(
# WORKAROUND: when sweeping an oscillator on a logical line using the oscillator switching feature, need to ensure that the uid of the swept oscillator is sorted() first
uid="ef_drive_osc",
frequency=frequency_sweep,
modulation_type=ModulationType.HARDWARE,
)
)
}
)
2.2 Run the Experiment and Plot the Measurement Results and Pulse Sequence¶
In [ ]:
Copied!
# set signal map to qubit 0
exp_ef_spec.set_signal_map(map_q0)
exp_ef_spec.set_calibration(exp_calibration)
# create and connect to session
session = Session(device_setup=device_setup)
session.connect(do_emulation=use_emulation)
# run experiment on qubit 0
compiled_exp_ef_spec = session.compile(exp_ef_spec)
ef_espec_results = session.run(compiled_exp_ef_spec)
# set signal map to qubit 0
exp_ef_spec.set_signal_map(map_q0)
exp_ef_spec.set_calibration(exp_calibration)
# create and connect to session
session = Session(device_setup=device_setup)
session.connect(do_emulation=use_emulation)
# run experiment on qubit 0
compiled_exp_ef_spec = session.compile(exp_ef_spec)
ef_espec_results = session.run(compiled_exp_ef_spec)
In [ ]:
Copied!
# show_pulse_sheet("ef_spectroscopy", compiled_exp_ef_spec)
# show_pulse_sheet("ef_spectroscopy", compiled_exp_ef_spec)
In [ ]:
Copied!
# Plot simulated output signals
plot_simulation(compiled_exp_ef_spec, 0, 0.5e-6)
# Plot simulated output signals
plot_simulation(compiled_exp_ef_spec, 0, 0.5e-6)
In [ ]:
Copied!