See also
A Jupyter notebook version of this tutorial can be downloaded here.

04b : Coulomb Diamonds#
Tutorial Objective#
In this tutorial, we provide an example of a Coulomb diamond measurement where we apply a voltage bias between the source and drain leads of charge sensor and measure the current flowing through the device as a function of both the bias voltage amplitude and the gate voltage amplitude. This reveals regions of Coulomb blockade where current flow is suppressed, which manifest as diamond-shaped features in the measurement data.
Imports
[1]:
from __future__ import annotations
import rich # noqa:F401
from qblox_scheduler import HardwareAgent, Schedule
from qblox_scheduler.operations import (
Measure,
SquarePulse,
)
from qblox_scheduler.operations.expressions import DType
from qblox_scheduler.operations.loop_domains import arange, linspace
Hardware/Device Configuration Files#
We use JSON files in order to set the configurations for different parts of the whole system.
Hardware configuration
The hardware configuration file contains the cluster IP and the type of modules in that specific cluster (by cluster slot). Options such as the output attenuations, mixer corrections or LO frequencies can be fixed inside this file and the cluster will adapt to these settings when initialized. Hardware connectivities are also described here: Each module’s output is directly connected to the corresponding device port on the chip, allowing the software to address device elements directly and eliminating an extra layer of complexity for the user.
Device configuration
The device configuration file defines each quantum element and its associated properties. In this case, the basic spin elements are qubits, whilst the charge sensor element is a sensor and edges can be defined as barriers between the dots. As can be observed in this file, each element contains several key properties that can be pre-set in the file, or from within the Jupyter notebook (e.g. sensor.measure.pulse_amp(0.5)). Please have a quick look through these properties and change them as suited to your device, if needed. Some of the typically important properties are: acq_delay, integration_time, and clock_freqs. You may also adjust the default pulse amplitudes and pulse durations for a given element here, or may define additional elements as needed.
Hardware configuration
The hardware configuration file contains the cluster IP and the type of modules in that specific cluster (by cluster slot). Options such as the output attenuations, mixer corrections or LO frequencies can be fixed inside this file and the cluster will adapt to these settings when initialized. Hardware connectivities are also described here: Each module’s output is directly connected to the corresponding device port on the chip, allowing the software to address device elements directly and eliminating an extra layer of complexity for the user.
Device configuration
The device configuration file defines each quantum element and its associated properties. In this case, the basic spin elements are qubits, whilst the charge sensor element is a sensor and edges can be defined as barriers between the dots. As can be observed in this file, each element contains several key properties that can be pre-set in the file, or from within the Jupyter notebook (e.g. sensor.measure.pulse_amp(0.5)). Please have a quick look through these properties and change them as suited to your device, if needed. Some of the typically important properties are: acq_delay, integration_time, and clock_freqs. You may also adjust the default pulse amplitudes and pulse durations for a given element here, or may define additional elements as needed.
Using the information specified in these files, we set the hardware and device configurations which determines the connectivity of our system.
[2]:
hw_config_path = "dependencies/configs/tuning_spin_coupled_pair_hardware_config.json"
device_path = "dependencies/configs/spin_with_psb_device_config_2q.yaml"
Experimental Setup#
To run the tutorial, you will need a quantum device consists of a double quantum dot array (q0 and q1), with a charge sensor (cs0) connected to reflectometry readout. The DC voltages of the quantum device also need to be properly tuned. For example, reservoir gates need to be ramped up for the accumulation devices. The charge sensor can be a quantum dot, quantum point contact (QPC), or single electron transistor (SET).
The HardwareAgent() is the main object for Qblox experiments. It provides an interface to define the quantum device, set up hardware connectivity, run experiments, and receive results.
[3]:
hw_agent = HardwareAgent(hw_config_path, device_path)
hw_agent.connect_clusters()
# Device name string should be defined as specified in the hardware configuration file
sensor_0 = hw_agent.quantum_device.get_element("cs0")
source_drain_bias = hw_agent.quantum_device.get_element("ohmic0")
qubit_0 = hw_agent.quantum_device.get_element("q0")
qubit_1 = hw_agent.quantum_device.get_element("q1")
/builds/0/.venv/lib/python3.10/site-packages/qblox_scheduler/qblox/hardware_agent.py:460: UserWarning: cluster0: Trying to instantiate cluster with ip 'None'.Creating a dummy cluster.
warnings.warn(
As can be observed from the defined quantum devices and the hardware connectivies of these elements, the relevant modules and connections for this tutorial are:
QCM (Module 2):
\(\text{O}^{1}\): Gate connection line for qubit 0 (
q0).\(\text{O}^{2}\): Gate connection line for qubit 1 (
q1).\(\text{O}^{4}\): Source drain bias connection for the charge sensor leads (
ohmic0).
QRM (Module 4):
\(\text{O}^{1}\) and \(\text{I}^{1}\): Charge sensor (
cs0) resonator probe and readout connection.
Coulomb Diamonds - Schedule & Measurement#
We create a schedule for measuring Coulomb diamonds via 2D amplitude sweeps.
This schedule performs a nested sweep: sourcedrain_amp parameter is applied to the ohmic contact (typically setting the source-drain bias), while sensor_amp parameter is applied to the charge sensor gate. For each pair of amplitudes, a gate pulse is applied to the ohmic contact and a charge measurement is performed via the sensor.
Note: The pulse duration (pulse_duration) must be longer than the duration of the Measure() gate. Otherwise, operation overlap may occur.
We define all variables for the experiment schedule in one location for ease of access and modification.
[4]:
repetitions = 5
pulse_duration = 800e-9
ohmic_target = source_drain_bias
sensor = sensor_0
[5]:
coulomb_diamonds_schedule = Schedule("schedule")
with (
coulomb_diamonds_schedule.loop(arange(0, repetitions, 1, DType.NUMBER)),
coulomb_diamonds_schedule.loop(
linspace(
start=0.0,
stop=0.5,
num=4,
dtype=DType.AMPLITUDE,
)
) as sourcedrain_amp,
coulomb_diamonds_schedule.loop(
linspace(start=0.0, stop=0.75, num=5, dtype=DType.AMPLITUDE)
) as sensor_amp,
):
ref_op = coulomb_diamonds_schedule.add(
SquarePulse(
amp=sourcedrain_amp,
duration=pulse_duration,
port=ohmic_target.ports.gate,
)
)
coulomb_diamonds_schedule.add(
Measure(
sensor.name,
gate_pulse_amp=sensor_amp,
pulse_duration=pulse_duration,
coords={"ohmic_amp": sourcedrain_amp, "sensor_plunger_amp": sensor_amp},
),
ref_op=ref_op,
ref_pt="start",
)
Now, we will run the schedule. See the documentation on the QRM Module and Readout Sequencers for information on how the signal is processed upon acquisition.
Before running this schedule, please make sure that the measurement pulse amplitude, duration, acquisition delay and integration time parameters are adjusted to your needs in the device configuration file. These will be defined via the sensor device (in this case, named cs0) since the measurement is performed via this quantum device.
Note that this schedule can be adapted to perform a sweep of the gate connection of any quantum device element via changing the target element.
[6]:
coulomb_diamonds_ds = hw_agent.run(coulomb_diamonds_schedule)
coulomb_diamonds_ds
[6]:
<xarray.Dataset> Size: 960B
Dimensions: (acq_index_0: 20)
Coordinates:
* acq_index_0 (acq_index_0) int64 160B 0 1 2 3 4 5 ... 15 16 17 18 19
ohmic_amp (acq_index_0) float64 160B 0.0 0.0 0.0 ... 0.5 0.5 0.5
loop_repetition_0 (acq_index_0) float64 160B 0.0 1.0 2.0 ... 18.0 19.0
sensor_plunger_amp (acq_index_0) float64 160B 0.0 0.1875 ... 0.5625 0.75
Data variables:
0 (acq_index_0) complex128 320B (nan+nanj) ... (nan+nanj)
Attributes:
tuid: 20251030-003717-465-4d8751You may plot the pulse diagram of a schedule for verification.
[7]:
hw_agent.compile(coulomb_diamonds_schedule).plot_pulse_diagram()
[7]:
(<Figure size 1000x621 with 1 Axes>,
<Axes: title={'center': 'schedule schedule 4 repeated 1 times'}, xlabel='Time [μs]', ylabel='$\\dfrac{V}{V_{max}}$'>)
The quantum device settings can be saved after every experiment for allowing later reference into experiment settings.
[8]:
hw_agent.quantum_device.to_json_file("./dependencies/configs", add_timestamp=True)
[8]:
'./dependencies/configs/spin_with_psb_device_config_2025-10-30_00-37-18_UTC.json'