Experiment Reference¶
This notebook is intended as a reference to see how parts of a LabOne Q experiment can be built.
Imports, device setup, and example experiment¶
You'll start by importing LabOne Q, defining your descriptor, providing a calibration, and creating a device setup.
In [ ]:
Copied!
# LabOne Q:
from laboneq.simple import *
# LabOne Q:
from laboneq.simple import *
In [ ]:
Copied!
descriptor = """\
instrument_list:
HDAWG:
- address: DEV1001
uid: device_hdawg
UHFQA:
- address: DEV2001
uid: device_uhfqa
PQSC:
- address: DEV3001
uid: device_pqsc
connections:
device_hdawg:
- iq_signal: q0/drive_line
ports: [SIGOUTS/0, SIGOUTS/1]
- iq_signal: q1/drive_line
ports: [SIGOUTS/2, SIGOUTS/3]
- rf_signal: q0/flux_line
ports: [SIGOUTS/4]
- rf_signal: q1/flux_line
ports: [SIGOUTS/5]
- to: device_uhfqa
port: DIOS/0
device_uhfqa:
- iq_signal: q0/measure_line
ports: [SIGOUTS/0, SIGOUTS/1]
- acquire_signal: q0/acquire_line
- iq_signal: q1/measure_line
ports: [SIGOUTS/0, SIGOUTS/1]
- acquire_signal: q1/acquire_line
device_pqsc:
- to: device_hdawg
port: ZSYNCS/0
"""
descriptor = """\
instrument_list:
HDAWG:
- address: DEV1001
uid: device_hdawg
UHFQA:
- address: DEV2001
uid: device_uhfqa
PQSC:
- address: DEV3001
uid: device_pqsc
connections:
device_hdawg:
- iq_signal: q0/drive_line
ports: [SIGOUTS/0, SIGOUTS/1]
- iq_signal: q1/drive_line
ports: [SIGOUTS/2, SIGOUTS/3]
- rf_signal: q0/flux_line
ports: [SIGOUTS/4]
- rf_signal: q1/flux_line
ports: [SIGOUTS/5]
- to: device_uhfqa
port: DIOS/0
device_uhfqa:
- iq_signal: q0/measure_line
ports: [SIGOUTS/0, SIGOUTS/1]
- acquire_signal: q0/acquire_line
- iq_signal: q1/measure_line
ports: [SIGOUTS/0, SIGOUTS/1]
- acquire_signal: q1/acquire_line
device_pqsc:
- to: device_hdawg
port: ZSYNCS/0
"""
In [ ]:
Copied!
def calibrate_devices(device_setup):
device_setup.logical_signal_groups["q0"].logical_signals[
"drive_line"
].calibration = SignalCalibration(
oscillator=Oscillator(
uid="drive_osc", frequency=1e8, modulation_type=ModulationType.HARDWARE
),
mixer_calibration=MixerCalibration(
voltage_offsets=[0.02, 0.01],
correction_matrix=[
[1.0, 0.0],
[0.0, 1.0],
],
),
)
device_setup.logical_signal_groups["q0"].logical_signals[
"flux_line"
].oscillator = Oscillator(
uid="flux_q0_osc", frequency=1e8, modulation_type=ModulationType.HARDWARE
)
device_setup.logical_signal_groups["q0"].logical_signals[
"measure_line"
].calibration = SignalCalibration(
oscillator=Oscillator(
uid="measure_q0_osc", frequency=1e8, modulation_type=ModulationType.SOFTWARE
),
mixer_calibration=MixerCalibration(
voltage_offsets=[0.02, 0.01],
correction_matrix=[
[1.0, 0.0],
[0.0, 1.0],
],
),
)
device_setup.logical_signal_groups["q0"].logical_signals[
"acquire_line"
].oscillator = Oscillator(
uid="acquire_q0_osc", frequency=1e8, modulation_type=ModulationType.SOFTWARE
)
device_setup.logical_signal_groups["q1"].logical_signals[
"drive_line"
].calibration = SignalCalibration(
oscillator=Oscillator(
uid="drive_q1_osc", frequency=1e8, modulation_type=ModulationType.HARDWARE
),
mixer_calibration=MixerCalibration(
voltage_offsets=[0.02, 0.01],
correction_matrix=[
[1.0, 0.0],
[0.0, 1.0],
],
),
)
device_setup.logical_signal_groups["q1"].logical_signals[
"flux_line"
].oscillator = Oscillator(
uid="flux_q1_osc", frequency=1e8, modulation_type=ModulationType.HARDWARE
)
device_setup.logical_signal_groups["q1"].logical_signals[
"measure_line"
].calibration = SignalCalibration(
oscillator=Oscillator(
uid="measure_q1_osc", frequency=1e8, modulation_type=ModulationType.SOFTWARE
),
mixer_calibration=MixerCalibration(
voltage_offsets=[0.02, 0.01],
correction_matrix=[
[1.0, 0.0],
[0.0, 1.0],
],
),
)
device_setup.logical_signal_groups["q1"].logical_signals[
"acquire_line"
].oscillator = Oscillator(
uid="acquire_q1_osc", frequency=1e8, modulation_type=ModulationType.SOFTWARE
)
def calibrate_devices(device_setup):
device_setup.logical_signal_groups["q0"].logical_signals[
"drive_line"
].calibration = SignalCalibration(
oscillator=Oscillator(
uid="drive_osc", frequency=1e8, modulation_type=ModulationType.HARDWARE
),
mixer_calibration=MixerCalibration(
voltage_offsets=[0.02, 0.01],
correction_matrix=[
[1.0, 0.0],
[0.0, 1.0],
],
),
)
device_setup.logical_signal_groups["q0"].logical_signals[
"flux_line"
].oscillator = Oscillator(
uid="flux_q0_osc", frequency=1e8, modulation_type=ModulationType.HARDWARE
)
device_setup.logical_signal_groups["q0"].logical_signals[
"measure_line"
].calibration = SignalCalibration(
oscillator=Oscillator(
uid="measure_q0_osc", frequency=1e8, modulation_type=ModulationType.SOFTWARE
),
mixer_calibration=MixerCalibration(
voltage_offsets=[0.02, 0.01],
correction_matrix=[
[1.0, 0.0],
[0.0, 1.0],
],
),
)
device_setup.logical_signal_groups["q0"].logical_signals[
"acquire_line"
].oscillator = Oscillator(
uid="acquire_q0_osc", frequency=1e8, modulation_type=ModulationType.SOFTWARE
)
device_setup.logical_signal_groups["q1"].logical_signals[
"drive_line"
].calibration = SignalCalibration(
oscillator=Oscillator(
uid="drive_q1_osc", frequency=1e8, modulation_type=ModulationType.HARDWARE
),
mixer_calibration=MixerCalibration(
voltage_offsets=[0.02, 0.01],
correction_matrix=[
[1.0, 0.0],
[0.0, 1.0],
],
),
)
device_setup.logical_signal_groups["q1"].logical_signals[
"flux_line"
].oscillator = Oscillator(
uid="flux_q1_osc", frequency=1e8, modulation_type=ModulationType.HARDWARE
)
device_setup.logical_signal_groups["q1"].logical_signals[
"measure_line"
].calibration = SignalCalibration(
oscillator=Oscillator(
uid="measure_q1_osc", frequency=1e8, modulation_type=ModulationType.SOFTWARE
),
mixer_calibration=MixerCalibration(
voltage_offsets=[0.02, 0.01],
correction_matrix=[
[1.0, 0.0],
[0.0, 1.0],
],
),
)
device_setup.logical_signal_groups["q1"].logical_signals[
"acquire_line"
].oscillator = Oscillator(
uid="acquire_q1_osc", frequency=1e8, modulation_type=ModulationType.SOFTWARE
)
In [ ]:
Copied!
device_setup = DeviceSetup.from_descriptor(
descriptor,
server_host="111.22.33.44",
server_port="8004",
setup_name="ZI_QCCS",
)
calibrate_devices(device_setup)
device_setup = DeviceSetup.from_descriptor(
descriptor,
server_host="111.22.33.44",
server_port="8004",
setup_name="ZI_QCCS",
)
calibrate_devices(device_setup)
Example experiment¶
After creating your device setup, you can run an example experiment, e.g., this resonator spectroscopy.
In [ ]:
Copied!
# Create Resonator Spectroscopy example experiment
exp = Experiment(
uid="Resonator Spectroscopy",
signals=[ExperimentSignal(uid="q0_measure"), ExperimentSignal(uid="q0_acquire")],
)
# Connect experiment signals to logical signals
exp.map_signal(
"q0_measure",
device_setup.logical_signal_groups["q0"].logical_signals["measure_line"],
)
exp.map_signal(
"q0_acquire",
device_setup.logical_signal_groups["q0"].logical_signals["acquire_line"],
)
start = -100e6
stop = 100e6
count = 20
average_exponent = 10 # used for 2^n averages, n=average_exponent, maximum: n = 17
sweep_parameter = LinearSweepParameter(
uid="sweep_param", start=start, stop=stop, count=count
)
device_setup.logical_signal_groups["q0"].logical_signals[
"measure_line"
].oscillator.frequency = sweep_parameter
device_setup.logical_signal_groups["q0"].logical_signals[
"measure_line"
].oscillator.modulation_type = ModulationType.HARDWARE
with exp.sweep(uid="sweep", parameter=sweep_parameter):
with exp.acquire_loop_rt(
uid="avg",
count=pow(2, average_exponent),
averaging_mode=AveragingMode.SEQUENTIAL,
acquisition_type=AcquisitionType.SPECTROSCOPY,
):
with exp.section(uid="spectroscopy"):
exp.play(
signal="q0_measure",
pulse=pulse_library.const(length=1e-6, amplitude=1.0),
)
exp.acquire(
signal="q0_acquire",
handle="h",
length=1e-6,
)
with exp.section(uid="relax"):
exp.play(
signal="q0_measure",
pulse=pulse_library.const(length=1e-6, amplitude=0.0),
) # KNOWN ISSUE: Need to wait for 1us to prevent QA holdoff error
# Create Resonator Spectroscopy example experiment
exp = Experiment(
uid="Resonator Spectroscopy",
signals=[ExperimentSignal(uid="q0_measure"), ExperimentSignal(uid="q0_acquire")],
)
# Connect experiment signals to logical signals
exp.map_signal(
"q0_measure",
device_setup.logical_signal_groups["q0"].logical_signals["measure_line"],
)
exp.map_signal(
"q0_acquire",
device_setup.logical_signal_groups["q0"].logical_signals["acquire_line"],
)
start = -100e6
stop = 100e6
count = 20
average_exponent = 10 # used for 2^n averages, n=average_exponent, maximum: n = 17
sweep_parameter = LinearSweepParameter(
uid="sweep_param", start=start, stop=stop, count=count
)
device_setup.logical_signal_groups["q0"].logical_signals[
"measure_line"
].oscillator.frequency = sweep_parameter
device_setup.logical_signal_groups["q0"].logical_signals[
"measure_line"
].oscillator.modulation_type = ModulationType.HARDWARE
with exp.sweep(uid="sweep", parameter=sweep_parameter):
with exp.acquire_loop_rt(
uid="avg",
count=pow(2, average_exponent),
averaging_mode=AveragingMode.SEQUENTIAL,
acquisition_type=AcquisitionType.SPECTROSCOPY,
):
with exp.section(uid="spectroscopy"):
exp.play(
signal="q0_measure",
pulse=pulse_library.const(length=1e-6, amplitude=1.0),
)
exp.acquire(
signal="q0_acquire",
handle="h",
length=1e-6,
)
with exp.section(uid="relax"):
exp.play(
signal="q0_measure",
pulse=pulse_library.const(length=1e-6, amplitude=0.0),
) # KNOWN ISSUE: Need to wait for 1us to prevent QA holdoff error
In [ ]:
Copied!
session = Session(device_setup=device_setup)
session.connect(do_emulation=True)
my_results = session.run(exp)
session = Session(device_setup=device_setup)
session.connect(do_emulation=True)
my_results = session.run(exp)
Experiment Instantiation¶
You'll now create an experiment from scratch, going through each step.
In [ ]:
Copied!
exp = Experiment()
exp = Experiment(uid="MyExperiment")
exp = Experiment(
uid="MyExperiment",
signals=[ExperimentSignal(uid="q0_measure"), ExperimentSignal(uid="q0_acquire")],
)
exp = Experiment()
exp = Experiment(uid="MyExperiment")
exp = Experiment(
uid="MyExperiment",
signals=[ExperimentSignal(uid="q0_measure"), ExperimentSignal(uid="q0_acquire")],
)
In [ ]:
Copied!
exp.add_signal(uid="q0_drive")
exp.add_signal(uid="q0_drive")
In [ ]:
Copied!
exp.experiment_signals_uids()
exp.experiment_signals_uids()
In [ ]:
Copied!
exp.is_experiment_signal("q0_drive")
exp.is_experiment_signal("q0_drive")
In [ ]:
Copied!
exp.map_signal(
"q0_drive", device_setup.logical_signal_groups["q0"].logical_signals["drive_line"]
)
exp.map_signal(
"q0_measure",
device_setup.logical_signal_groups["q0"].logical_signals["measure_line"],
)
exp.map_signal(
"q0_acquire",
device_setup.logical_signal_groups["q0"].logical_signals["acquire_line"],
)
exp.map_signal(
"q0_drive", device_setup.logical_signal_groups["q0"].logical_signals["drive_line"]
)
exp.map_signal(
"q0_measure",
device_setup.logical_signal_groups["q0"].logical_signals["measure_line"],
)
exp.map_signal(
"q0_acquire",
device_setup.logical_signal_groups["q0"].logical_signals["acquire_line"],
)
In [ ]:
Copied!
exp.signal_mapping_status
exp.signal_mapping_status
Sections¶
Simple Section¶
In [ ]:
Copied!
with exp.section(uid="qubit_excitation"):
# e.g. play pulses here
pass
# with exp.section(uid="qubit_excitation"): # Nest one section in another and inherit exec_type from parent section
# e.g. play pulses here
# pass
with exp.section(uid="qubit_excitation"):
# e.g. play pulses here
pass
# with exp.section(uid="qubit_excitation"): # Nest one section in another and inherit exec_type from parent section
# e.g. play pulses here
# pass
Access Current Section¶
In [ ]:
Copied!
def play_x90_on_drive(section):
section.play(
signal="q0_drive",
pulse=pulse_library.gaussian(uid="x90", length=100e-9, amplitude=1.0),
)
with exp.section(uid="prepare") as s:
play_x90_on_drive(s)
with exp.section(uid="conclude") as s:
play_x90_on_drive(s)
def play_x90_on_drive(section):
section.play(
signal="q0_drive",
pulse=pulse_library.gaussian(uid="x90", length=100e-9, amplitude=1.0),
)
with exp.section(uid="prepare") as s:
play_x90_on_drive(s)
with exp.section(uid="conclude") as s:
play_x90_on_drive(s)
Sweep Section¶
In [ ]:
Copied!
# 1D sweep with one parameter
sweep_parameter_1 = LinearSweepParameter(
uid="lin_sweep_1", start=0.0, stop=1.0, count=10, axis_name="Amplitude"
)
with exp.sweep(uid="single_sweep", parameter=sweep_parameter_1):
pass
# 1D sweep with one parameter
sweep_parameter_1 = LinearSweepParameter(
uid="lin_sweep_1", start=0.0, stop=1.0, count=10, axis_name="Amplitude"
)
with exp.sweep(uid="single_sweep", parameter=sweep_parameter_1):
pass
In [ ]:
Copied!
# 2D sweep with two parameters
sweep_parameter_1 = LinearSweepParameter(
uid="lin_sweep_1", start=0.0, stop=1.0, count=10, axis_name="Amplitude"
)
sweep_parameter_2 = LinearSweepParameter(
uid="lin_sweep_2", start=1e6, stop=1e9, count=20, axis_name="Frequency"
)
with exp.sweep(uid="sweep_first_d", parameter=sweep_parameter_1):
with exp.sweep(uid="sweep_second_d", parameter=sweep_parameter_2):
pass
# 2D sweep with two parameters
sweep_parameter_1 = LinearSweepParameter(
uid="lin_sweep_1", start=0.0, stop=1.0, count=10, axis_name="Amplitude"
)
sweep_parameter_2 = LinearSweepParameter(
uid="lin_sweep_2", start=1e6, stop=1e9, count=20, axis_name="Frequency"
)
with exp.sweep(uid="sweep_first_d", parameter=sweep_parameter_1):
with exp.sweep(uid="sweep_second_d", parameter=sweep_parameter_2):
pass
In [ ]:
Copied!
# 1D sweep with multiple parameter in pararallel
sweep_parameter_1 = LinearSweepParameter(
uid="lin_sweep_1", start=0.0, stop=1.0, count=10, axis_name="Amplitude"
)
sweep_parameter_2 = LinearSweepParameter(
uid="lin_sweep_2", start=1e6, stop=1e9, count=10, axis_name="Frequency"
)
with exp.sweep(uid="multi_sweep", parameter=[sweep_parameter_1, sweep_parameter_2]):
pass
# 1D sweep with multiple parameter in pararallel
sweep_parameter_1 = LinearSweepParameter(
uid="lin_sweep_1", start=0.0, stop=1.0, count=10, axis_name="Amplitude"
)
sweep_parameter_2 = LinearSweepParameter(
uid="lin_sweep_2", start=1e6, stop=1e9, count=10, axis_name="Frequency"
)
with exp.sweep(uid="multi_sweep", parameter=[sweep_parameter_1, sweep_parameter_2]):
pass
Averaging Acquire Loop in real time¶
In [ ]:
Copied!
with exp.acquire_loop_rt(
uid="acquire_loop_rt",
count=20,
averaging_mode=AveragingMode.SEQUENTIAL,
acquisition_type=AcquisitionType.INTEGRATION,
repetition_mode=RepetitionMode.CONSTANT,
repetition_time=1e-06,
):
pass
with exp.acquire_loop_rt(
uid="acquire_loop_rt",
count=20,
averaging_mode=AveragingMode.SEQUENTIAL,
acquisition_type=AcquisitionType.INTEGRATION,
repetition_mode=RepetitionMode.CONSTANT,
repetition_time=1e-06,
):
pass
Operations in near time¶
Callback Function¶
In [ ]:
Copied!
# exp.call()
# exp.call()
Set node parameter in Zurich Instruments devices¶
Note: setting nodes can lead to uncontrolled behavior. It is preferable to sweep such nodes using the calibration in a near-time sweep.
In [ ]:
Copied!
# exp.set_node(path='', value=value)
# exp.set_node(path='', value=value)
Operations in real time¶
Play Pulses¶
In [ ]:
Copied!
with exp.section(uid="drive"):
exp.play(
signal="q0_drive",
pulse=pulse_library.gaussian(uid="x90", length=100e-9, amplitude=1.0),
)
with exp.section(uid="drive"):
exp.play(
signal="q0_drive",
pulse=pulse_library.gaussian(uid="x90", length=100e-9, amplitude=1.0),
)
Acquire Signals¶
In [ ]:
Copied!
acquisition_pulse = pulse_library.const(length=1e-6, amplitude=1.0)
qubit1_kernel = pulse_library.const(length=1e-6, amplitude=1.0)
with exp.acquire_loop_rt(
uid="ac",
count=1,
acquisition_type=AcquisitionType.INTEGRATION,
):
exp.acquire(signal="q0_acquire", handle="handle1", kernel=qubit1_kernel)
exp.acquire(
signal="q1_acquire", handle="handle2", kernel=qubit1_kernel
) # Would this overwrite result_buffer?
exp.acquire(
signal="q1_acquire", handle="handle3", kernel=qubit1_kernel
) # Add Acquire() meta-info e.g. "kernel" to the handle?
# my_results = results.get(result_buffer="handle")
acquisition_pulse = pulse_library.const(length=1e-6, amplitude=1.0)
qubit1_kernel = pulse_library.const(length=1e-6, amplitude=1.0)
with exp.acquire_loop_rt(
uid="ac",
count=1,
acquisition_type=AcquisitionType.INTEGRATION,
):
exp.acquire(signal="q0_acquire", handle="handle1", kernel=qubit1_kernel)
exp.acquire(
signal="q1_acquire", handle="handle2", kernel=qubit1_kernel
) # Would this overwrite result_buffer?
exp.acquire(
signal="q1_acquire", handle="handle3", kernel=qubit1_kernel
) # Add Acquire() meta-info e.g. "kernel" to the handle?
# my_results = results.get(result_buffer="handle")
Delay¶
In [ ]:
Copied!
with exp.section(uid="delay"):
exp.delay(signal="q0_drive", time=1e-03)
with exp.section(uid="delay"):
exp.delay(signal="q0_drive", time=1e-03)
Signal Reservation¶
In [ ]:
Copied!
with exp.section(uid="reserve"):
exp.reserve("q0_drive")
with exp.section(uid="reserve"):
exp.reserve("q0_drive")
In [ ]:
Copied!