See also

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

banner

Charge Stability Diagram#

Tutorial Objective#

The charge stability diagram provides a map of the stable electron configurations in a double quantum dot system as a function of gate voltages. By simultaneously sweeping two gate electrodes that tune the electrochemical potentials of the dots, and monitoring the response with a nearby charge sensor, one obtains a characteristic pattern of polygonal regions. Each region corresponds to a distinct charge occupation, while the boundaries mark transitions where electrons tunnel into or out of the dots. The geometry of these patterns reveals the interplay of Coulomb interactions, tunnel couplings, and gate lever arms, and serves as a key diagnostic for tuning and characterizing coupled quantum dot devices. For further information, see Hanson.2007.

Imports

[1]:
from __future__ import annotations

from dependencies.analysis_utils import ChargeStabilityDiagramAnalysis
from dependencies.simulated_data import get_charge_stability_diagram_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")
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).

QRM (Module 4):

  • \(\text{O}^{1}\) and \(\text{I}^{1}\): Charge sensor (cs0) resonator probe and readout connection.

Charge Stability Diagram - Schedule & Measurement#

We define a measurement sequence for mapping out a charge stability diagram.

This schedule performs a 2D sweep over two plunger gate voltages applied to target_element_1 and target_element_2. For each amplitude pair, gate voltage pulses are applied simultaneously, and a charge sensor measurement is used to detect transitions in the charge configuration of the system.

We define all variables for the experiment schedule in one location for ease of access and modification.

[4]:
repetitions = 100
pulse_duration = 100e-8
target_element_1 = qubit_0
target_element_2 = qubit_1
sensor = sensor_0
num_amp1 = 50
num_amp2 = 50
[5]:
charge_stability_schedule = Schedule("2-parameter sweep")

ref_op = None
with (
    charge_stability_schedule.loop(arange(0, repetitions, 1, DType.NUMBER)),
    charge_stability_schedule.loop(
        linspace(
            start=0.0,
            stop=0.5,
            num=num_amp1,
            dtype=DType.AMPLITUDE,
        )
    ) as amp1,
    charge_stability_schedule.loop(
        linspace(start=0.0, stop=0.75, num=num_amp2, dtype=DType.AMPLITUDE)
    ) as amp2,
):
    ref_op = charge_stability_schedule.add(
        SquarePulse(
            amp=amp1,
            duration=pulse_duration,
            port=target_element_1.ports.gate,
        ),
        ref_op=ref_op,
    )
    charge_stability_schedule.add(
        SquarePulse(
            amp=amp2,
            duration=pulse_duration,
            port=target_element_2.ports.gate,
        ),
        ref_op=ref_op,
        ref_pt="start",
    )
    charge_stability_schedule.add(
        Measure(
            sensor.name,
            gate_pulse_amp=0.5,
            coords={"port1_amplitude": amp1, "port2_amplitude": amp2},
        ),
        ref_op=ref_op,
        ref_pt="start",
    )
/tmp/ipykernel_4133/3251067471.py:19: FutureWarning: amp is deprecated as an argument to SquarePulse and will be removed in qblox-scheduler >= 2.0; use amplitude instead.
  SquarePulse(
/tmp/ipykernel_4133/3251067471.py:27: 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.

Note that this schedule can be adapted to perform a concurrent sweep of any two output ports by changing the sweep objects (with the exception of ChargeSensor elements).

[6]:
charge_stability_ds = hw_agent.run(charge_stability_schedule)
charge_stability_ds
[6]:
<xarray.Dataset> Size: 120kB
Dimensions:            (acq_index_0: 2500)
Coordinates:
  * acq_index_0        (acq_index_0) int64 20kB 0 1 2 3 ... 2496 2497 2498 2499
    loop_repetition_0  (acq_index_0) float64 20kB 0.0 1.0 ... 2.499e+03
    port1_amplitude    (acq_index_0) float64 20kB 0.0 0.0 0.0 ... 0.5 0.5 0.5
    port2_amplitude    (acq_index_0) float64 20kB 0.0 0.01531 ... 0.7347 0.75
Data variables:
    0                  (acq_index_0) complex128 40kB (nan+nanj) ... (nan+nanj)
Attributes:
    tuid:     20260415-120501-058-8b9e19

Analysis#

[7]:
if cluster.is_dummy:
    charge_stability_ds[0].data = get_charge_stability_diagram_data(
        [(1, 0), (2, 0)], [(0, 0)], num_amp1, num_amp2
    )
[8]:
analysis = ChargeStabilityDiagramAnalysis(charge_stability_ds)
analysis.display_figs_mpl()
../../../_images/applications_spin_spin_005_ChargeStabilityDiagram_19_0.png
../../../_images/applications_spin_spin_005_ChargeStabilityDiagram_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-05-01_UTC.json'