See also
A Jupyter notebook version of this tutorial can be downloaded here
.
Fixed Frequency Transmon#
This notebook shows a typical tuneup sequence for fixed frequency transmon qubits. The notebook aims to be as compact as possible, for more details, please refer to the respective experiments.
Time of flight measurement#
Here show how to measure time of flight for your system. This is useful to calibrate the acquisition delay for subsequent experiments.
[1]:
import json
from functools import partial
from typing import Literal
import matplotlib.pyplot as plt
import numpy as np
import rich # noqa:F401
from qcodes.parameters import ManualParameter
from sklearn.metrics import ConfusionMatrixDisplay
import quantify_core.data.handling as dh
from quantify_core.analysis.readout_calibration_analysis import ReadoutCalibrationAnalysis
from quantify_core.analysis.time_of_flight_analysis import TimeOfFlightAnalysis
from quantify_scheduler import Schedule
from quantify_scheduler.backends.qblox import constants
from quantify_scheduler.device_under_test.quantum_device import QuantumDevice
from quantify_scheduler.enums import BinMode
from quantify_scheduler.gettables import ScheduleGettable
from quantify_scheduler.math import closest_number_ceil
from quantify_scheduler.operations.gate_library import Measure, Reset, Rxy, X
from quantify_scheduler.operations.pulse_library import IdlePulse
from quantify_scheduler.schedules.timedomain_schedules import ramsey_sched
from utils import initialize_hardware, run # noqa:F401
[2]:
hw_config_path = "configs/tuning_transmon_coupled_pair_hardware_config.json"
device_path = "devices/transmon_device_2q.json"
[3]:
with open(hw_config_path) as hw_cfg_json_file:
hardware_cfg = json.load(hw_cfg_json_file)
# Enter your own dataset directory here!
dh.set_datadir(dh.default_datadir())
Data will be saved in:
/root/quantify-data
[4]:
quantum_device = QuantumDevice.from_json_file(device_path)
qubit = quantum_device.get_element("q0")
quantum_device.hardware_config(hardware_cfg)
meas_ctrl, _, cluster = initialize_hardware(quantum_device, ip=None)
/builds/qblox/packages/software/qblox_instruments_docs/.venv/lib/python3.9/site-packages/quantify_scheduler/backends/types/qblox.py:1220: ValidationWarning: Setting `auto_lo_cal=on_lo_interm_freq_change` will overwrite settings `dc_offset_i=0.0` and `dc_offset_q=0.0`. To suppress this warning, do not set either `dc_offset_i` or `dc_offset_q` for this port-clock.
warnings.warn(
/builds/qblox/packages/software/qblox_instruments_docs/.venv/lib/python3.9/site-packages/quantify_scheduler/backends/types/qblox.py:1235: ValidationWarning: Setting `auto_sideband_cal=on_interm_freq_change` will overwrite settings `amp_ratio=1.0` and `phase_error=0.0`. To suppress this warning, do not set either `amp_ratio` or `phase_error` for this port-clock.
warnings.warn(
Schedule definition#
[5]:
def tof_trace_schedule(
qubit_name: str,
repetitions: int = 1,
) -> Schedule:
schedule = Schedule("Trace measurement schedule", repetitions=repetitions)
schedule.add(Measure(qubit_name, acq_protocol="Trace"))
return schedule
Measuring time of flight with trace acquisition#
[6]:
def set_readout_attenuation_hardware_config(attenuation_dB: int):
hwcfg = quantum_device.hardware_config()
output_att = hwcfg["hardware_options"]["output_att"]
output_att[f"{qubit.ports.readout()}-{qubit.name}.ro"] = attenuation_dB
quantum_device.hardware_config(hwcfg)
set_readout_attenuation_hardware_config(0)
qubit.measure.pulse_duration(300e-9)
qubit.measure.integration_time(1e-6)
qubit.measure.pulse_amp(0.1)
qubit.measure.acq_delay(4e-9)
[7]:
tof_t = ManualParameter(name="tof_t", unit="ns", label="Trace acquisition sample")
tof_t.batched = True
tof_t.batch_size = round(qubit.measure.integration_time() * constants.SAMPLING_RATE)
tof_sched_kwargs = dict(
qubit_name=qubit.name,
)
# set gettable
gettable = ScheduleGettable(
quantum_device,
schedule_function=tof_trace_schedule,
schedule_kwargs=tof_sched_kwargs,
real_imag=False,
batched=True,
)
# set measurement control
meas_ctrl.gettables(gettable)
[8]:
tof_t_setpoints = np.arange(tof_t.batch_size)
meas_ctrl.settables(tof_t)
meas_ctrl.setpoints(tof_t_setpoints)
# replace the get method for the gettable in case the cluster is a dummy
if "dummy" in str(cluster._transport):
def get_fake_tof_data():
"""Generate mock data for a time of flight measurement."""
y = (
np.heaviside(tof_t_setpoints - 200, 0.5)
- np.heaviside(tof_t_setpoints - tof_t_setpoints.size * 0.7, 0.5)
) * 30e-3
y += np.random.normal(loc=0.0, scale=1e-3, size=y.size)
return [y, np.zeros_like(y)]
gettable.get = get_fake_tof_data
tof_ds = dh.to_gridded_dataset(meas_ctrl.run("Time of flight measurement " + qubit.name))
tof_ds
Starting batched measurement...
Iterative settable(s) [outer loop(s)]:
--- (None) ---
Batched settable(s):
tof_t
Batch size limit: 1000
[8]:
<xarray.Dataset> Size: 24kB Dimensions: (x0: 1000) Coordinates: * x0 (x0) int64 8kB 0 1 2 3 4 5 6 7 ... 992 993 994 995 996 997 998 999 Data variables: y0 (x0) float64 8kB 0.001493 -0.0005849 ... 0.002208 0.0007401 y1 (x0) float64 8kB 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 Attributes: tuid: 20241113-023632-482-9d6ba1 name: Time of flight measurement q0 grid_2d: False grid_2d_uniformly_spaced: False 1d_2_settables_uniformly_spaced: False
Analysis#
[9]:
tof_analysis = TimeOfFlightAnalysis(tuid=dh.get_latest_tuid())
tof_analysis.run(playback_delay=149e-9).display_figs_mpl()
[10]:
fit_results = tof_analysis.quantities_of_interest
nco_prop_delay = fit_results["nco_prop_delay"]
measured_tof = fit_results["tof"]
qubit.measure.acq_delay(
closest_number_ceil(
measured_tof * constants.SAMPLING_RATE, constants.MIN_TIME_BETWEEN_OPERATIONS
)
/ constants.SAMPLING_RATE
)
[11]:
quantum_device.to_json_file("devices/")
[11]:
'devices/device_2q_2024-11-13_02-36-33_UTC.json'
Resonator Spectroscopy#
Here we go through resonator discovery and punchout spectroscopy for identifying the resonator and measuring it’s resonant frequency.
Resonator Spectroscopy#
[12]:
def resonator_spectroscopy_schedule(
qubit, # noqa: ANN001
freqs: np.array,
repetitions: int = 1,
) -> Schedule:
"""Schedule to sweep the resonator frequency."""
sched = Schedule("schedule", repetitions=repetitions)
for i, freq in enumerate(freqs):
sched.add(
Measure(
qubit.name,
acq_index=i,
freq=freq,
)
)
sched.add(IdlePulse(8e-9))
return sched
freqs = ManualParameter(name="freq", unit="Hz", label="Frequency")
freqs.batched = True
freqs.batch_size = 100
spec_sched_kwargs = dict(
qubit=qubit,
freqs=freqs,
)
gettable = ScheduleGettable(
quantum_device,
schedule_function=resonator_spectroscopy_schedule,
schedule_kwargs=spec_sched_kwargs,
real_imag=False,
batched=True,
)
meas_ctrl.gettables(gettable)
[13]:
quantum_device.cfg_sched_repetitions(400)
center = 7.7e9
frequency_setpoints = np.linspace(center - 20e6, center + 20e6, 300)
meas_ctrl.settables(freqs)
meas_ctrl.setpoints(frequency_setpoints)
rs_ds = meas_ctrl.run("resonator spectroscopy")
rs_ds
Starting batched measurement...
Iterative settable(s) [outer loop(s)]:
--- (None) ---
Batched settable(s):
freq
Batch size limit: 100
/builds/qblox/packages/software/qblox_instruments_docs/.venv/lib/python3.9/site-packages/quantify_scheduler/backends/types/qblox.py:1235: ValidationWarning: Setting `auto_sideband_cal=on_interm_freq_change` will overwrite settings `amp_ratio=1.0` and `phase_error=0.0`. To suppress this warning, do not set either `amp_ratio` or `phase_error` for this port-clock.
warnings.warn(
/builds/qblox/packages/software/qblox_instruments_docs/.venv/lib/python3.9/site-packages/quantify_scheduler/backends/types/qblox.py:1235: ValidationWarning: Setting `auto_sideband_cal=on_interm_freq_change` will overwrite settings `amp_ratio=1.0` and `phase_error=0.0`. To suppress this warning, do not set either `amp_ratio` or `phase_error` for this port-clock.
warnings.warn(
/builds/qblox/packages/software/qblox_instruments_docs/.venv/lib/python3.9/site-packages/quantify_scheduler/backends/types/qblox.py:1235: ValidationWarning: Setting `auto_sideband_cal=on_interm_freq_change` will overwrite settings `amp_ratio=1.0` and `phase_error=0.0`. To suppress this warning, do not set either `amp_ratio` or `phase_error` for this port-clock.
warnings.warn(
[13]:
<xarray.Dataset> Size: 7kB Dimensions: (dim_0: 300) Coordinates: x0 (dim_0) float64 2kB 7.68e+09 7.68e+09 ... 7.72e+09 7.72e+09 Dimensions without coordinates: dim_0 Data variables: y0 (dim_0) float64 2kB nan nan nan nan nan nan ... nan nan nan nan nan y1 (dim_0) float64 2kB nan nan nan nan nan nan ... nan nan nan nan nan Attributes: tuid: 20241113-023633-465-576657 name: resonator spectroscopy grid_2d: False grid_2d_uniformly_spaced: False 1d_2_settables_uniformly_spaced: False
[14]:
qubit.clock_freqs.readout(7.9e9)
Resonator punchout#
[15]:
def resonator_punchout_schedule(
qubit, # noqa: ANN001
freqs: np.array,
ro_pulse_amps: np.array,
repetitions: int = 1,
) -> Schedule:
"""Schedule to sweep the resonator frequency."""
sched = Schedule("schedule", repetitions=repetitions)
index = 0
freqs, ro_pulse_amps = np.unique(freqs), np.unique(ro_pulse_amps)
for freq in freqs:
for amp in ro_pulse_amps:
sched.add(Measure(qubit.name, acq_index=index, freq=freq, pulse_amp=amp))
sched.add(IdlePulse(8e-9))
index += 1
return sched
freqs = ManualParameter(name="freq", unit="Hz", label="Frequency")
freqs.batched = True
ro_pulse_amps = ManualParameter(name="ro_pulse_amp", unit="", label="Readout pulse amplitude")
ro_pulse_amps.batched = True
spec_sched_kwargs = dict(
qubit=qubit,
freqs=freqs,
ro_pulse_amps=ro_pulse_amps,
)
gettable = ScheduleGettable(
quantum_device,
schedule_function=resonator_punchout_schedule,
schedule_kwargs=spec_sched_kwargs,
real_imag=False,
batched=True,
)
meas_ctrl.gettables(gettable)
[16]:
quantum_device.cfg_sched_repetitions(80)
center = 7.7e9
frequency_setpoints = np.linspace(center - 20e6, center + 20e6, 100)
amplitude_setpoints = np.linspace(0, 1, 10)
meas_ctrl.settables([freqs, ro_pulse_amps])
meas_ctrl.setpoints_grid((frequency_setpoints, amplitude_setpoints))
punchout_ds = meas_ctrl.run("resonator punchout")
punchout_ds
Starting batched measurement...
Iterative settable(s) [outer loop(s)]:
--- (None) ---
Batched settable(s):
freq, ro_pulse_amp
Batch size limit: 1000
/builds/qblox/packages/software/qblox_instruments_docs/.venv/lib/python3.9/site-packages/quantify_scheduler/backends/types/qblox.py:1235: ValidationWarning: Setting `auto_sideband_cal=on_interm_freq_change` will overwrite settings `amp_ratio=1.0` and `phase_error=0.0`. To suppress this warning, do not set either `amp_ratio` or `phase_error` for this port-clock.
warnings.warn(
[16]:
<xarray.Dataset> Size: 32kB Dimensions: (dim_0: 1000) Coordinates: x0 (dim_0) float64 8kB 7.68e+09 7.68e+09 ... 7.72e+09 7.72e+09 x1 (dim_0) float64 8kB 0.0 0.0 0.0 0.0 0.0 0.0 ... 1.0 1.0 1.0 1.0 1.0 Dimensions without coordinates: dim_0 Data variables: y0 (dim_0) float64 8kB nan nan nan nan nan nan ... nan nan nan nan nan y1 (dim_0) float64 8kB nan nan nan nan nan nan ... nan nan nan nan nan Attributes: tuid: 20241113-023634-137-fd08b0 name: resonator punchout grid_2d: True grid_2d_uniformly_spaced: True 1d_2_settables_uniformly_spaced: False xlen: 100 ylen: 10
[17]:
quantum_device.to_json_file("devices/")
[17]:
'devices/device_2q_2024-11-13_02-36-35_UTC.json'
Single transmon qubit spectroscopy#
Here we will carry out qubit spectroscopy on a single transmon in order to find the \(|0\rangle \rightarrow |1\rangle\) drive frequency.
Qubit spectroscopy#
[18]:
def two_tone_spec_sched_nco(
qubit, # noqa: ANN001
spec_pulse_frequencies: np.array,
repetitions: int = 1,
) -> Schedule:
"""
Generate a batched schedule for performing fast two-tone spectroscopy.
Using the X gate to perform the frequency sweep on the qubit.
Parameters
----------
qubit
qubit that should be used.
spec_pulse_frequencies
Sample frequencies for the spectroscopy pulse in Hertz.
repetitions
The amount of times the Schedule will be repeated.
"""
sched = Schedule("two-tone", repetitions)
for acq_idx, spec_pulse_freq in enumerate(spec_pulse_frequencies):
sched.add(Reset(qubit.name))
sched.add(X(qubit.name, freq=spec_pulse_freq))
sched.add(Measure(qubit.name, acq_index=acq_idx), rel_time=200e-9)
return sched
[19]:
freqs = ManualParameter(name="freq", unit="Hz", label="Frequency")
freqs.batched = True
qubit_spec_sched_kwargs = dict(
qubit=qubit,
spec_pulse_frequencies=freqs,
)
gettable = ScheduleGettable(
quantum_device,
schedule_function=two_tone_spec_sched_nco,
schedule_kwargs=qubit_spec_sched_kwargs,
real_imag=False,
batched=True,
)
meas_ctrl.gettables(gettable)
[20]:
quantum_device.cfg_sched_repetitions(300)
center = 6.1e9
frequency_setpoints = np.linspace(center - 20e6, center + 20e6, 300)
meas_ctrl.settables(freqs)
meas_ctrl.setpoints(frequency_setpoints)
qs_ds = meas_ctrl.run("Two-tone")
qs_ds
Starting batched measurement...
Iterative settable(s) [outer loop(s)]:
--- (None) ---
Batched settable(s):
freq
Batch size limit: 300
/builds/qblox/packages/software/qblox_instruments_docs/.venv/lib/python3.9/site-packages/quantify_scheduler/backends/types/qblox.py:1235: ValidationWarning: Setting `auto_sideband_cal=on_interm_freq_change` will overwrite settings `amp_ratio=1.0` and `phase_error=0.0`. To suppress this warning, do not set either `amp_ratio` or `phase_error` for this port-clock.
warnings.warn(
[20]:
<xarray.Dataset> Size: 7kB Dimensions: (dim_0: 300) Coordinates: x0 (dim_0) float64 2kB 6.08e+09 6.08e+09 ... 6.12e+09 6.12e+09 Dimensions without coordinates: dim_0 Data variables: y0 (dim_0) float64 2kB nan nan nan nan nan nan ... nan nan nan nan nan y1 (dim_0) float64 2kB nan nan nan nan nan nan ... nan nan nan nan nan Attributes: tuid: 20241113-023635-397-20f804 name: Two-tone grid_2d: False grid_2d_uniformly_spaced: False 1d_2_settables_uniformly_spaced: False
[21]:
qubit.clock_freqs.f01(6.1e9)
[22]:
quantum_device.to_json_file("devices/")
[22]:
'devices/device_2q_2024-11-13_02-36-35_UTC.json'
Rabi Oscillations#
Here we will carry out an experiment to measure the Rabi frequency that is required to excite the qubit to \(|1\rangle\).
Rabi Oscillations#
[23]:
pulse_amps = np.linspace(-0.14, 0.14, 200)
sched = Schedule("rabi_amplitude", 400)
for acq_idx, pulse_amp in enumerate(pulse_amps):
sched.add(Reset(qubit.name))
sched.add(X(qubit.name, amp180=pulse_amp))
sched.add(Measure(qubit.name, acq_index=acq_idx), rel_time=20e-9) # wait 20ns before measuring
rabi_ds = run(schedule=sched, quantum_device=quantum_device)
rabi_ds
/builds/qblox/packages/software/qblox_instruments_docs/.venv/lib/python3.9/site-packages/quantify_scheduler/backends/types/qblox.py:1235: ValidationWarning: Setting `auto_sideband_cal=on_interm_freq_change` will overwrite settings `amp_ratio=1.0` and `phase_error=0.0`. To suppress this warning, do not set either `amp_ratio` or `phase_error` for this port-clock.
warnings.warn(
[23]:
<xarray.Dataset> Size: 5kB Dimensions: (acq_index_0: 200) Coordinates: * acq_index_0 (acq_index_0) int64 2kB 0 1 2 3 4 5 ... 194 195 196 197 198 199 Data variables: 0 (acq_index_0) complex128 3kB (nan+nanj) ... (nan+nanj)
[24]:
qubit.rxy.amp180(0.07)
[25]:
quantum_device.to_json_file("devices/")
[25]:
'devices/device_2q_2024-11-13_02-36-36_UTC.json'
T1#
Here we measure the \(T_1\) decoherence time of the qubit.
[26]:
import numpy as np
from qcodes.parameters import ManualParameter
from quantify_scheduler.gettables import ScheduleGettable
from quantify_scheduler.schedules.timedomain_schedules import t1_sched
T1#
[27]:
tau = ManualParameter(name="tau_delay", unit="s", label="Delay")
tau.batched = True
t1_sched_kwargs = {"qubit": qubit.name, "times": tau}
gettable = ScheduleGettable(
quantum_device,
schedule_function=t1_sched,
schedule_kwargs=t1_sched_kwargs,
real_imag=False,
batched=True,
)
meas_ctrl.gettables(gettable)
[28]:
delay_setpoints = np.arange(40e-9, 200e-6, 500e-9)
meas_ctrl.settables(tau)
meas_ctrl.setpoints(delay_setpoints)
quantum_device.cfg_sched_repetitions(300)
t1_ds = meas_ctrl.run("T1 experiment")
t1_ds
Starting batched measurement...
Iterative settable(s) [outer loop(s)]:
--- (None) ---
Batched settable(s):
tau_delay
Batch size limit: 400
/builds/qblox/packages/software/qblox_instruments_docs/.venv/lib/python3.9/site-packages/quantify_scheduler/backends/types/qblox.py:1235: ValidationWarning: Setting `auto_sideband_cal=on_interm_freq_change` will overwrite settings `amp_ratio=1.0` and `phase_error=0.0`. To suppress this warning, do not set either `amp_ratio` or `phase_error` for this port-clock.
warnings.warn(
[28]:
<xarray.Dataset> Size: 10kB Dimensions: (dim_0: 400) Coordinates: x0 (dim_0) float64 3kB 4e-08 5.4e-07 1.04e-06 ... 0.000199 0.0001995 Dimensions without coordinates: dim_0 Data variables: y0 (dim_0) float64 3kB nan nan nan nan nan nan ... nan nan nan nan nan y1 (dim_0) float64 3kB nan nan nan nan nan nan ... nan nan nan nan nan Attributes: tuid: 20241113-023636-259-6f8c68 name: T1 experiment grid_2d: False grid_2d_uniformly_spaced: False 1d_2_settables_uniformly_spaced: False
[29]:
quantum_device.to_json_file("devices/")
[29]:
'devices/device_2q_2024-11-13_02-36-36_UTC.json'
Ramsey Spectroscopy#
Here we demonstrate Ramsey Spectroscopy, which is used to tune the \(|0\rangle \rightarrow |1\rangle\) drive frequency more precisely. Ramsey spectroscopy is also used to find \(T_2^*\).
Ramsey oscillations#
[30]:
tau = ManualParameter(name="tau", unit="s", label="Time")
tau.batched = True
ramsey_sched_kwargs = {
"qubit": qubit.name,
"times": tau,
"artificial_detuning": 0.0,
}
gettable = ScheduleGettable(
quantum_device,
schedule_function=ramsey_sched,
schedule_kwargs=ramsey_sched_kwargs,
real_imag=False,
batched=True,
)
meas_ctrl.gettables(gettable)
[31]:
tau_setpoints = np.arange(20e-9, 4e-6, 32e-9)
meas_ctrl.settables(tau)
meas_ctrl.setpoints(tau_setpoints)
quantum_device.cfg_sched_repetitions(500)
ramsey_ds = meas_ctrl.run("ramsey")
ramsey_ds
Starting batched measurement...
Iterative settable(s) [outer loop(s)]:
--- (None) ---
Batched settable(s):
tau
Batch size limit: 125
/builds/qblox/packages/software/qblox_instruments_docs/.venv/lib/python3.9/site-packages/quantify_scheduler/backends/types/qblox.py:1235: ValidationWarning: Setting `auto_sideband_cal=on_interm_freq_change` will overwrite settings `amp_ratio=1.0` and `phase_error=0.0`. To suppress this warning, do not set either `amp_ratio` or `phase_error` for this port-clock.
warnings.warn(
/builds/qblox/packages/software/qblox_instruments_docs/.venv/lib/python3.9/site-packages/quantify_scheduler/backends/qblox/compiler_abc.py:634: RuntimeWarning: Operation is interrupting previous Pulse because it starts before the previous ends, offending operation: Pulse "Rxy(90, 0, 'q0')" (t0=0.00010002000000000001, duration=4e-08)
warnings.warn(
[31]:
<xarray.Dataset> Size: 3kB Dimensions: (dim_0: 125) Coordinates: x0 (dim_0) float64 1kB 2e-08 5.2e-08 8.4e-08 ... 3.956e-06 3.988e-06 Dimensions without coordinates: dim_0 Data variables: y0 (dim_0) float64 1kB nan nan nan nan nan nan ... nan nan nan nan nan y1 (dim_0) float64 1kB nan nan nan nan nan nan ... nan nan nan nan nan Attributes: tuid: 20241113-023636-750-341505 name: ramsey grid_2d: False grid_2d_uniformly_spaced: False 1d_2_settables_uniformly_spaced: False
[32]:
qubit.clock_freqs.f01(qubit.clock_freqs.f01() + 100e3)
[33]:
quantum_device.to_json_file("devices/")
[33]:
'devices/device_2q_2024-11-13_02-36-37_UTC.json'
Discriminated Single Shot Readout#
Here we show how to run a readout calibration experiment and fit a discriminator with a linear discriminant analysis. This experiment is sometimes called multi-state discrimination.
Schedule definition#
[34]:
def readout_calibration_sched(
qubit: str,
prepared_states: list[int],
repetitions: int = 1,
acq_protocol: Literal[
"SSBIntegrationComplex", "ThresholdedAcquisition"
] = "SSBIntegrationComplex",
) -> Schedule:
"""
Make a schedule for readout calibration.
Parameters
----------
qubit
The name of the qubit e.g., :code:`"q0"` to perform the experiment on.
prepared_states
A list of integers indicating which state to prepare the qubit in before measuring.
The ground state corresponds to 0 and the first-excited state to 1.
repetitions
The number of times the schedule will be repeated. Fixed to 1 for this schedule.
acq_protocol
The acquisition protocol used for the readout calibration. By default
"SSBIntegrationComplex", but "ThresholdedAcquisition" can be
used for verifying thresholded acquisition parameters.
Returns
-------
:
An experiment schedule.
Raises
------
NotImplementedError
If the prepared state is > 1.
"""
schedule = Schedule(f"Readout calibration {qubit}", repetitions=1)
for i, prep_state in enumerate(prepared_states):
schedule.add(Reset(qubit), label=f"Reset {i}")
if prep_state == 0:
pass
elif prep_state == 1:
schedule.add(Rxy(qubit=qubit, theta=180, phi=0))
else:
raise NotImplementedError(
"Preparing the qubit in the higher excited states is not supported yet."
)
schedule.add(
Measure(qubit, acq_index=i, bin_mode=BinMode.APPEND, acq_protocol=acq_protocol),
label=f"Measurement {i}",
)
return schedule
SSRO with single side band (SSB) integration#
[35]:
states = ManualParameter(name="states", unit="", label="Prepared state")
states.batch_size = 400
states.batched = True
readout_calibration_sched_kwargs = dict(
qubit=qubit.name, prepared_states=states, acq_protocol="SSBIntegrationComplex"
)
# set gettable
ssro_gettable = ScheduleGettable(
quantum_device,
schedule_function=readout_calibration_sched,
schedule_kwargs=readout_calibration_sched_kwargs,
real_imag=True,
batched=True,
)
# set measurement control
meas_ctrl.gettables(ssro_gettable)
[36]:
num_shots = 1000
state_setpoints = np.asarray([0, 1] * num_shots)
# replace the get method for the gettable in case the cluster is a dummy
if "dummy" in str(cluster._transport):
from fake_data import get_fake_ssro_data
ssro_gettable.get = partial(get_fake_ssro_data, num_shots=num_shots)
meas_ctrl.settables(states)
meas_ctrl.setpoints(state_setpoints)
ssro_ds = dh.to_gridded_dataset(meas_ctrl.run("Single shot readout experiment"))
ssro_ds
Starting batched measurement...
Iterative settable(s) [outer loop(s)]:
--- (None) ---
Batched settable(s):
states
Batch size limit: 400
[36]:
<xarray.Dataset> Size: 48kB Dimensions: (x0: 2000) Coordinates: * x0 (x0) int64 16kB 0 1 0 1 0 1 0 1 0 1 0 1 ... 0 1 0 1 0 1 0 1 0 1 0 1 Data variables: y0 (x0) float64 16kB 0.01177 0.0186 0.03126 ... 0.01101 0.03909 y1 (x0) float64 16kB 0.01881 0.03123 0.03309 ... 0.01339 0.0264 Attributes: tuid: 20241113-023637-072-4cdbd5 name: Single shot readout experiment grid_2d: False grid_2d_uniformly_spaced: False 1d_2_settables_uniformly_spaced: False
Fit line discriminator with linear discriminant analysis (LDA)#
[37]:
ssro_analysis = ReadoutCalibrationAnalysis(tuid=dh.get_latest_tuid())
ssro_analysis.run().display_figs_mpl()
[38]:
fit_results = ssro_analysis.fit_results["linear_discriminator"].params
acq_threshold = fit_results["acq_threshold"].value
acq_rotation = (np.rad2deg(fit_results["acq_rotation_rad"].value)) % 360
qubit.measure.acq_threshold(acq_threshold)
qubit.measure.acq_rotation(acq_rotation)
SSRO with thresholded acquisition#
[39]:
disc_ssro_gettable_kwargs = dict(
qubit=qubit.name, prepared_states=states, acq_protocol="ThresholdedAcquisition"
)
# set gettable
disc_ssro_gettable = ScheduleGettable(
quantum_device,
schedule_function=readout_calibration_sched,
schedule_kwargs=disc_ssro_gettable_kwargs,
real_imag=True,
batched=True,
)
# set measurement control
meas_ctrl.gettables(disc_ssro_gettable)
[40]:
num_shots = 10_000
state_setpoints = np.asarray([0, 1] * num_shots)
# replace the get method for the gettable in case the cluster is a dummy
if "dummy" in str(cluster._transport):
from fake_data import get_fake_binary_ssro_data
disc_ssro_gettable.get = partial(get_fake_binary_ssro_data, num_shots=num_shots)
meas_ctrl.settables(states)
meas_ctrl.setpoints(state_setpoints)
disc_ssro_ds = dh.to_gridded_dataset(meas_ctrl.run("Discriminated single shot readout experiment"))
disc_ssro_ds
Starting batched measurement...
Iterative settable(s) [outer loop(s)]:
--- (None) ---
Batched settable(s):
states
Batch size limit: 400
[40]:
<xarray.Dataset> Size: 480kB Dimensions: (x0: 20000) Coordinates: * x0 (x0) int64 160kB 0 1 0 1 0 1 0 1 0 1 0 1 ... 1 0 1 0 1 0 1 0 1 0 1 Data variables: y0 (x0) float64 160kB 0.0 1.0 0.0 1.0 0.0 1.0 ... 1.0 0.0 0.0 0.0 1.0 y1 (x0) float64 160kB nan nan nan nan nan nan ... nan nan nan nan nan Attributes: tuid: 20241113-023638-522-7a7579 name: Discriminated single shot readout exper... grid_2d: False grid_2d_uniformly_spaced: False 1d_2_settables_uniformly_spaced: False
[41]:
ConfusionMatrixDisplay.from_predictions(disc_ssro_ds.x0.data, disc_ssro_ds.y0.data)
plt.title("Confusion Matrix")
plt.xlabel("Measured State")
plt.ylabel("Prepared State")
[41]:
Text(0, 0.5, 'Prepared State')
[42]:
quantum_device.to_json_file("devices/")
[42]:
'devices/device_2q_2024-11-13_02-36-38_UTC.json'