# LabOne Q:
from laboneq.simple import *
# pretty printing
from pprint import pprint
Device Descriptor¶
descriptor = """\
instruments:
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
"""
Device Calibration¶
def calibrate_devices(device_setup):
device_setup.logical_signal_groups["q0"].logical_signals[
"drive_line"
].calibration = SignalCalibration(
oscillator=Oscillator(
uid="drive_q0_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[
"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],
),
)
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[
"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],
),
)
device_setup.logical_signal_groups["q1"].logical_signals[
"acquire_line"
].oscillator = Oscillator(
uid="acquire_q1_osc", frequency=1e8, modulation_type=ModulationType.SOFTWARE
)
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)
Experiment Definition¶
# Create Resonator Spectroscopy example experiment
exp = Experiment(
uid="Resonator Spectroscopy",
signals=[ExperimentSignal("q0_measure"), ExperimentSignal("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.delay(
signal="q0_measure",
time=1e-6,
) # KNOWN ISSUE: Need to wait for 1us to prevent QA holdoff error
Session instantiation¶
session = Session(device_setup=device_setup)
session.connect(do_emulation=True)
Experiment compilation¶
compiled_experiment = session.compile(experiment=exp)
Compiled experiment can also be retrieved from the session at any time, once available:
compiled_experiment = session.compiled_experiment
Experiment execution¶
Returns a reference to the results object obtained by running this experiment
my_results = session.run(compiled_experiment)
Result Handling¶
Results are available after executing an experiment:
Get a results object¶
containing all relevant data from the last execution
results = session.results
Note: This results object contains a reference of the data stored in the session and care has to be taken when using this to not affect the results in the session.
results_copy = session.get_results()
Note: To obtain a copy of the results contained within the session, use the get_results method instead
device_setup = results.device_setup
device_calibration = results.device_calibration
experiment = results.experiment
experiment_calibration = results.experiment_calibration
signal_map = results.signal_map
compiled_experiment = results.compiled_experiment
acquired_results = results.acquired_results
Compiled Experiment¶
recipe = compiled_experiment.recipe
src = compiled_experiment.src
waves = compiled_experiment.waves
Acquired Results¶
The structure of the acquired results will change. For now, it is just adapted to the current controller implementation.
pprint(acquired_results)
Convenience getters on Results object¶
Get acquired results for a given buffer (handle):
acquired_data = results.get_data("h")
# 1D -> one axis only
axis_grid = results.get_axis("h")[0]
axis_name = results.get_axis_name("h")[0]
Serialization¶
Save the entire session as executed above:
session.save("my_session.json")
Save individual data entities from the session:
session.save_device_setup("my_device_setup.json")
session.save_experiment("my_experiment.json")
session.save_compiled_experiment("my_compiled_experiment.json")
session.save_device_calibration("my_device_calibration.json")
session.save_experiment_calibration("my_experiment_calibration.json")
session.save_signal_map("my_signal_map.json")
session.save_results("my_results.json")
Load serialized session into a new session:
new_session = Session.load("my_session.json")
Connect and rerun the loaded session:
new_session.connect(do_emulation=True)
new_results = new_session.run()
Load individual data entities into the session:
session.load_device_setup("my_device_setup.json")
session.load_experiment("my_experiment.json")
session.load_compiled_experiment("my_compiled_experiment.json")
session.load_device_calibration("my_device_calibration.json")
session.load_experiment_calibration("my_experiment_calibration.json")
session.load_signal_map("my_signal_map.json")
Load data entities separately:
my_device_setup = DeviceSetup.load("my_device_setup.json")
my_experiment = Experiment.load("my_experiment.json")
compiled_experiment = CompiledExperiment.load("my_compiled_experiment.json")
my_device_calibration = Calibration.load("my_device_calibration.json")
my_experiment_calibration = Calibration.load("my_experiment_calibration.json")
my_results = Results.load("my_results.json")
# Signal Maps can only be loaded on and applied to an existing Experiment:
my_experiment.load_signal_map("my_signal_map.json")
print(my_device_setup)
Plotting¶
Plotting the acquired results:
import matplotlib.pyplot as plt
import numpy as np
plt.plot(axis_grid, np.absolute(acquired_data))
plt.xlabel(axis_name)
Plotting device output signals:
from laboneq.simulator.output_simulator import OutputSimulator
simulator = OutputSimulator(compiled_experiment)
qb = device_setup.logical_signal_groups["q0"].logical_signals
measure_iq_port = qb["measure_line"].physical_channel
acquire_port = qb["acquire_line"].physical_channel
snippet_measure = simulator.get_snippet(measure_iq_port, start=0, output_length=1e-5)
snippet_acquire = simulator.get_snippet(acquire_port, start=0, output_length=1e-5)
fig, ax = plt.subplots(3, 1, figsize=(5, 5), sharex=True)
fig.subplots_adjust(hspace=0.4)
time = snippet_measure.time
ax[0].plot(time, snippet_measure.wave.real)
ax[0].set_ylabel("Amplitude")
ax[0].set_title("Readout pulse I")
ax[1].plot(time, snippet_measure.wave.imag)
ax[1].set_ylabel("Amplitude")
ax[1].set_title("Readout pulse Q")
time = snippet_acquire.time
ax[2].plot(time, snippet_acquire.wave.real)
ax[2].set_title("QA trigger")