# 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 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
recipe = compiled_experiment.recipe
src = compiled_experiment.src
waves = compiled_experiment.waves
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 the results 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
acquired_results = results.acquired_results
neartime_callback_results = results.neartime_callback_results
execution_errors = results.execution_errors
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¶
Serialising the Session class will no longer be possible from June 19th (LabOne Q version 2.55.0), when the LabOne Q serialisation framework will be removed in favour of the new serialisation framework. See our tutorial to learn more about the new LabOne Q serialisation framework and how to migrate to it.
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")