Using Output Router and Adder (RTR) in LabOne Q¶
The Output Router and Adder (RTR) is an upgrade option for SHFSG and SHFQC that enables routing the output of an AWG sequencers to multiple output channels on the instrument front panel.
In LabOne Q this is represented as a routing between different LogicalSignals
.
In this notebook, you will learn how to configure the output router settings in LabOne Q through the SignalCalibration
setting of a LogicalSignal
or ExperimentSignal
and how to sweep these settings in an Experiment
.
Imports¶
import numpy as np
from laboneq.simple import *
from laboneq.contrib.example_helpers.plotting.plot_helpers import plot_simulation
Device Setup¶
We start by creating a device setup and adding our instruments and their connections to it. This is a new way, alternative to the descriptor, to build up your device setup and was introduced in LabOne Q 2.19. The to_signal
argument take a logical signal group / logical signal line
and connects it to a physical instrument port.
emulate = True
# Add your device setup information here
device_setup = DeviceSetup("ZI_QCCS")
device_setup.add_dataserver(host="10.22.33.44", port="8004")
device_setup.add_instruments(
SHFSG(uid="device_shfsg", address="dev12001", device_options="SHFSG8/RTR"),
HDAWG(uid="device_hdawg", address="dev8001"),
PQSC(uid="device_pqsc", address="dev10001"),
)
device_setup.add_connections(
"device_shfsg",
create_connection(to_signal="q0/drive_line", ports="SGCHANNELS/0/OUTPUT"),
create_connection(to_signal="q1/drive_line", ports="SGCHANNELS/1/OUTPUT"),
create_connection(to_signal="q2/drive_line", ports="SGCHANNELS/2/OUTPUT"),
)
device_setup.add_connections(
"device_hdawg",
create_connection(to_signal="q0/flux_line", ports="SIGOUTS/0"),
)
device_setup.add_connections(
"device_pqsc",
create_connection(to_instrument="device_hdawg", ports="ZSYNCS/0"),
create_connection(to_instrument="device_shfsg", ports="ZSYNCS/1"),
)
Configuring the Output router in the Calibration¶
Here, we use a minimal configuration to demonstrate the output router settings.
With the added_outputs
setting, the outputs of the drive line of q1 and q2 are added to the drive line for q0, scaled by their respective amplitude_scaling
and phases shifted by phase_shift
.
q0_drive = device_setup.logical_signal_groups["q0"].logical_signals["drive_line"]
q1_drive = device_setup.logical_signal_groups["q1"].logical_signals["drive_line"]
q2_drive = device_setup.logical_signal_groups["q2"].logical_signals["drive_line"]
q0_flux = device_setup.logical_signal_groups["q0"].logical_signals["flux_line"]
q0_drive.calibration = SignalCalibration(
local_oscillator=Oscillator(frequency=1e9),
added_outputs=[
OutputRoute(source=q1_drive, amplitude_scaling=0.1, phase_shift=np.pi / 4),
OutputRoute(source=q2_drive, amplitude_scaling=0.2, phase_shift=np.pi / 2),
],
)
q1_drive.calibration = SignalCalibration(
local_oscillator=Oscillator(frequency=1e9),
)
q2_drive.calibration = SignalCalibration(
local_oscillator=Oscillator(frequency=1e9),
)
# start the session
my_session = Session(device_setup=device_setup)
my_session.connect(do_emulation=emulate)
#
# print(device_setup.get_calibration())
Sweeping output router settings in an Experiment¶
The values of amplitude_scaling
and phase_shft
can be swept in a near-time loop, which can be used for calibrating crosstalk or multiplexed pulses.
Here, you will learn how to sweep these configuration settings in an experiment.
const_pulse = pulse_library.const(length=100e-9, amplitude=1)
gauss_pulse = pulse_library.gaussian(length=100e-9, amplitude=1, sigma=0.3)
def output_router_sweep(
amplitude_min=0,
amplitude_max=0.5,
phase_min=0,
phase_max=1.5 * np.pi,
count=10,
average_count=4,
):
exp = Experiment(
uid="Output Router Sweep",
signals=[
ExperimentSignal("q0_drive", map_to=q0_drive),
ExperimentSignal("q0_flux", map_to=q0_flux),
ExperimentSignal("q1_drive", map_to=q1_drive),
ExperimentSignal("q2_drive", map_to=q2_drive),
],
)
amplitude_sweep = LinearSweepParameter(
start=amplitude_min, stop=amplitude_max, count=count
)
phase_sweep = LinearSweepParameter(start=phase_min, stop=phase_max, count=count)
exp_calibration = Calibration()
exp_calibration["q0_drive"] = SignalCalibration(
added_outputs=[
OutputRoute(
source=q1_drive,
amplitude_scaling=amplitude_sweep,
phase_shift=np.pi / 4,
),
OutputRoute(
source=q2_drive, amplitude_scaling=0.2, phase_shift=phase_sweep
),
]
)
with exp.sweep(
parameter=[amplitude_sweep, phase_sweep], execution_type=ExecutionType.NEAR_TIME
):
with exp.acquire_loop_rt(count=average_count):
with exp.section(uid="simultaneous pulses"):
exp.play(signal="q0_drive", pulse=const_pulse, amplitude=0.2)
exp.play(signal="q1_drive", pulse=const_pulse, amplitude=0.5)
exp.play(signal="q2_drive", pulse=const_pulse, amplitude=0.5)
exp.play(signal="q0_flux", pulse=const_pulse, amplitude=1.0)
with exp.section(uid="gauss on q1", play_after="simultaneous pulses"):
exp.play(signal="q1_drive", pulse=gauss_pulse)
with exp.section(uid="gauss on q2", play_after="gauss on q1"):
exp.play(signal="q2_drive", pulse=gauss_pulse)
exp.play(signal="q0_flux", pulse=const_pulse, amplitude=0.5)
exp.set_calibration(exp_calibration)
return exp
my_exp = output_router_sweep()
my_cexp = my_session.compile(my_exp)
my_results = my_session.run(my_cexp)
# show the pulse sheet, including all sweep steps in real- and near-time
show_pulse_sheet(name="Output Router Sweep", compiled_experiment=my_cexp)
# show the simulated outputs - does not contain the near-time loop, only single iteration of real-time experiment
plot_simulation(my_cexp, length=1.2e-6)