See also

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

banner

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 numpy as np
from dependencies.analysis_utils import CoulombDiamondAnalysis
from dependencies.simulated_data import get_coulomb_diamonds_data

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
/.venv/lib/python3.14/site-packages/quantify_core/utilities/general.py:13: QCoDeSDeprecationWarning: The `qcodes.utils.helpers` module is deprecated. Please consult the api documentation at https://microsoft.github.io/Qcodes/api/index.html for alternatives.
  from qcodes.utils.helpers import NumpyJSONEncoder

Hardware/Device Configuration Files#

We use configuration files in order to describe the hardware properties (e.g. cluster ip, connected modules, output ports) and quantum device properties (charge sensors, qubits, barriers and their associated properties) in one accessible location, respectively. Check the Getting Started Guide for further information.

Based on the information specified in these files, we establish the hardware and device configurations that determine the system’s connectivity.

[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#

In order to run this application example, you will need a quantum device that 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).

Hardware Setup#

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. For more information about the HardwareAgent() you can check the Core concepts of qblox-scheduler page.

[3]:
hw_agent = HardwareAgent(hw_config_path, device_path)
hw_agent.connect_clusters()
cluster = hw_agent.get_clusters()["cluster0"]

# 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")
/.venv/lib/python3.14/site-packages/qblox_scheduler/qblox/hardware_agent.py:499: 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 = 100
pulse_duration = 800e-9
ohmic_target = source_drain_bias
sensor = sensor_0
sourcedrain_amp_start = 0.0
sourcedrain_amp_end = 0.0075
num_sd_steps = 50
sensor_plunger_amp_start = 0.0
sensor_plunger_amp_end = 0.05
num_sensor_steps = 100
[5]:
coulomb_diamonds_schedule = Schedule("schedule")

with (
    coulomb_diamonds_schedule.loop(arange(0, repetitions, 1, DType.NUMBER)),
    coulomb_diamonds_schedule.loop(
        linspace(
            start=sourcedrain_amp_start,
            stop=sourcedrain_amp_end,
            num=num_sd_steps,
            dtype=DType.AMPLITUDE,
        )
    ) as sourcedrain_amp,
    coulomb_diamonds_schedule.loop(
        linspace(
            start=sensor_plunger_amp_start,
            stop=sensor_plunger_amp_end,
            num=num_sensor_steps,
            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",
    )
/tmp/ipykernel_7788/168372514.py:23: FutureWarning: amp is deprecated as an argument to SquarePulse and will be removed in qblox-scheduler >= 2.0; use amplitude instead.
  SquarePulse(

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: 240kB
Dimensions:             (acq_index_0: 5000)
Coordinates:
  * acq_index_0         (acq_index_0) int64 40kB 0 1 2 3 ... 4996 4997 4998 4999
    ohmic_amp           (acq_index_0) float64 40kB 0.0 0.0 0.0 ... 0.0075 0.0075
    loop_repetition_0   (acq_index_0) float64 40kB 0.0 1.0 ... 4.999e+03
    sensor_plunger_amp  (acq_index_0) float64 40kB 0.0 0.0005051 ... 0.05
Data variables:
    0                   (acq_index_0) complex128 80kB (nan+nanj) ... (nan+nanj)
Attributes:
    tuid:     20260415-121012-509-91c84d

Analysis#

[7]:
if cluster.is_dummy:
    coulomb_diamonds_ds[0].data = get_coulomb_diamonds_data(
        np.linspace(sensor_plunger_amp_start, sensor_plunger_amp_end, num_sensor_steps),
        np.linspace(sourcedrain_amp_start, sourcedrain_amp_end, num_sd_steps),
    )[2]
[8]:
analysis = CoulombDiamondAnalysis(coulomb_diamonds_ds)
analysis.display_figs_mpl()
../../../_images/applications_spin_spin_004b_CoulombDiamonds_19_0.png
../../../_images/applications_spin_spin_004b_CoulombDiamonds_19_1.png

The quantum device settings can be saved after every experiment for allowing later reference into experiment settings.

[9]:
hw_agent.quantum_device.to_json_file("./dependencies/configs", add_timestamp=True)
[9]:
'./dependencies/configs/spin_with_psb_device_config_2026-04-15_12-10-12_UTC.json'