Skip to navigation

Device Configuration

Think of device configuration as your lab notebook for defining a quantum device. Instead of hardcoding voltages and channel numbers in your Python scripts, you describe your device topology once in a YAML file. This makes it easy to work with different devices, share configurations with collaborators, and keep your experimental code clean.

Your First Device Configuration

Let’s configure a simple single quantum dot device. Create a file called device.yaml:

name: "My Billion Qubit Device"
gates:
PLUNGER:
type: PLUNGER
control_channel: 1
v_lower_bound: -2.0
v_upper_bound: 0.0
BARRIER:
type: BARRIER
control_channel: 2
v_lower_bound: -1.5
v_upper_bound: 0.0
contacts:
SOURCE:
type: SOURCE
measure_channel: 1
control_channel: 3
v_lower_bound: -0.01
v_upper_bound: 0.01
DRAIN:
type: DRAIN
measure_channel: 2
control_channel: 4
v_lower_bound: -0.01
v_upper_bound: 0.01
gpios:
VSS:
type: INPUT
control_channel: 5
v_lower_bound: 0
v_upper_bound: 3.3
VDD:
type: INPUT
control_channel: 6
v_lower_bound: -3.3
v_upper_bound: 0
instruments:
- name: qdac
type: GENERAL
driver: qdac2
ip_addr: 192.168.1.100
slew_rate: 0.5
routines:
- name: pinchoff_sweep
parameters:
gate: BARRIER
v_start: -1.5
v_stop: 0.0
n_points: 100
contact: DRAIN

Now you can control your device using gate names instead of channel numbers:

from stanza.utils import device_from_yaml
from stanza.models import PadType
device = device_from_yaml("device.yaml")
# Set voltages using descriptive names
device.jump({"PLUNGER": -1.2, "BARRIER": -0.8})
# Measure current
current = device.measure("DRAIN")
# Zero all gates and contacts (default)
device.zero(PadType.ALL)
# Zero only gates
device.zero(PadType.GATE)
# Zero only contacts
device.zero(PadType.CONTACT)
# Zero only GPIO pads
device.zero(PadType.GPIO)

Understanding Gates

Gates control the electrostatic landscape of your device. Stanza supports four gate types:

  • PLUNGER: Controls charge occupation in quantum dots
  • BARRIER: Controls tunnel coupling between regions
  • RESERVOIR: Connects to electron reservoirs
  • SCREEN: Provides electrostatic screening

Example: Double Quantum Dot

Here’s how you might configure a double quantum dot device:

gates:
# Plunger gates control chemical potential
LEFT_PLUNGER:
type: PLUNGER
control_channel: 1
v_lower_bound: -2.0
v_upper_bound: 0.0
RIGHT_PLUNGER:
type: PLUNGER
control_channel: 2
v_lower_bound: -2.0
v_upper_bound: 0.0
# Barrier gates control tunnel coupling
LEFT_BARRIER:
type: BARRIER
control_channel: 3
v_lower_bound: -1.5
v_upper_bound: 0.0
CENTER_BARRIER:
type: BARRIER
control_channel: 4
v_lower_bound: -1.5
v_upper_bound: 0.0
RIGHT_BARRIER:
type: BARRIER
control_channel: 5
v_lower_bound: -1.5
v_upper_bound: 0.0

The voltage bounds act as safety limits - if your code tries to exceed them, Stanza raises an error before touching the hardware.

Working with Gate Groups

Filter gates by type for common operations:

# Get all plunger gates
plungers = device.get_gates_by_type("PLUNGER")
# ["LEFT_PLUNGER", "RIGHT_PLUNGER"]
# Sweep all barriers together
barriers = device.get_gates_by_type("BARRIER")
voltages = [-1.5, -1.0, -0.5, 0.0]
device.sweep_nd(barriers, voltages, contact="DRAIN")

Example: Measurement-Only Contact

For contacts that only measure without voltage control:

contacts:
LEFT_RESERVOIR:
type: SOURCE
measure_channel: 1
control_channel: 6
v_lower_bound: -0.01
v_upper_bound: 0.01
RIGHT_RESERVOIR:
type: DRAIN
measure_channel: 2
control_channel: 7
v_lower_bound: -0.01
v_upper_bound: 0.01
SENSOR_DRAIN:
type: DRAIN
measure_channel: 3 # No voltage control needed

Use measurement-only contacts for fast current measurements during sweeps:

import numpy as np
# Sweep and measure at sensor
voltages = np.linspace(-2.0, 0.0, 100)
v_data, i_data = device.sweep_1d(
"LEFT_PLUNGER",
voltages.tolist(),
"SENSOR_DRAIN"
)

Contacts: Where You Measure

Contacts are where current flows in and out of your device. Stanza supports SOURCE and DRAIN contact types for DC transport measurements.

Example: DC Transport with Bias

Configure contacts that can both measure current and apply bias voltage:

contacts:
LEFT_RESERVOIR:
type: SOURCE
measure_channel: 1
control_channel: 6
v_lower_bound: -0.01 # 10 mV bias range
v_upper_bound: 0.01
RIGHT_RESERVOIR:
type: DRAIN
measure_channel: 2
control_channel: 7
v_lower_bound: -0.01
v_upper_bound: 0.01

Sweep bias voltage to measure Coulomb diamonds:

# Apply 10 mV bias
device.jump({"LEFT_RESERVOIR": 0.005, "RIGHT_RESERVOIR": -0.005})
# Measure conductance
current = device.measure("RIGHT_RESERVOIR")
conductance = current / 0.010

GPIOs: Pins for digital inputs and outputs

GPIOS (General Purpose Input/Output) are digital pins for sending and receiving signals from external components.

Example: Setting VSS and VDD

If your device has an external component, such as an LED or a multiplexer, you can configure the positive supply voltage (VDD) and the drain (VSS) with the following configuration:

gpios:
VSS:
type: INPUT
control_channel: 5
v_lower_bound: 0
v_upper_bound: 3.3
VDD:
type: INPUT
control_channel: 6
v_lower_bound: -3.3
v_upper_bound: 0

Connecting to Hardware

Instruments bridge your device configuration and actual hardware. The most common setup uses a QDAC-II for voltage control and current measurement.

Example: Simple Setup

Use a single QDAC-II for everything:

instruments:
- name: qdac
type: GENERAL # Both control and measurement
driver: qdac2
ip_addr: 192.168.1.100
slew_rate: 0.5 # V/s
measurement_duration: 10e-3 # 10 ms
sample_time: 100e-6 # 100 μs

Example: Separate Control and Measurement

For more flexibility, split control and measurement:

instruments:
# QDAC for voltage control
- name: qdac-control
type: CONTROL
driver: qdac2
ip_addr: 192.168.1.100
slew_rate: 0.5
# QDAC for DC current measurement
- name: qdac-measure
type: MEASUREMENT
driver: qdac2
ip_addr: 192.168.1.100
measurement_duration: 10e-3
sample_time: 100e-6
current_range: "LOW" # For pA-nA currents

The device automatically routes operations to the appropriate instrument based on control/measure channels.

Testing Without Hardware

Enable simulation mode for developing routines before hardware access:

instruments:
- name: qdac-sim
type: GENERAL
driver: qdac2
ip_addr: 127.0.0.1
is_simulation: true
sim_file: "./sim_config.yaml"

Pre-configuring Routine Parameters

The routines section lets you pre-configure parameters for common measurements:

routines:
- name: barrier_sweep
parameters:
gate: LEFT_BARRIER
v_start: -1.5
v_stop: 0.0
n_points: 100
contact: DRAIN
- name: charge_stability
parameters:
gate_x: LEFT_PLUNGER
gate_y: RIGHT_PLUNGER
v_x_start: -2.0
v_x_stop: -0.5
v_y_start: -2.0
v_y_stop: -0.5
n_points_x: 100
n_points_y: 100
contact: DRAIN

Run routines without repeating parameters:

from stanza.routines import RoutineRunner
from stanza.models import DeviceConfig
config = DeviceConfig.from_yaml("device.yaml")
runner = RoutineRunner(configs=[config])
# Parameters come from YAML
runner.run("barrier_sweep")
# Override parameters at runtime
runner.run("barrier_sweep", v_start=-2.0, n_points=200)

Organizing Complex Workflows

Use nested routines to organize multi-step tune-ups:

routines:
- name: full_tuneup
parameters:
threshold: 1e-9
routines:
- name: leakage_test
parameters:
gates: [LEFT_BARRIER, CENTER_BARRIER, RIGHT_BARRIER]
contact: DRAIN
- name: pinchoff_all
parameters:
gates: [LEFT_BARRIER, CENTER_BARRIER, RIGHT_BARRIER]
v_start: -1.5
v_stop: 0.0
n_points: 50
- name: charge_stability
parameters:
gate_x: LEFT_PLUNGER
gate_y: RIGHT_PLUNGER

Run the entire workflow:

# Execute all nested routines
results = runner.run_all(parent_routine="full_tuneup")

Complete Example

Here’s a full configuration for a double quantum dot device:

name: "Double Quantum Dot - Device 42"
gates:
LP:
type: PLUNGER
control_channel: 1
v_lower_bound: -3.0
v_upper_bound: 0.0
RP:
type: PLUNGER
control_channel: 2
v_lower_bound: -3.0
v_upper_bound: 0.0
LB:
type: BARRIER
control_channel: 3
v_lower_bound: -2.0
v_upper_bound: 0.0
CB:
type: BARRIER
control_channel: 4
v_lower_bound: -2.0
v_upper_bound: 0.0
RB:
type: BARRIER
control_channel: 5
v_lower_bound: -2.0
v_upper_bound: 0.0
contacts:
LEFT:
type: SOURCE
control_channel: 6
measure_channel: 1
v_lower_bound: -0.01
v_upper_bound: 0.01
RIGHT:
type: DRAIN
control_channel: 7
measure_channel: 2
v_lower_bound: -0.01
v_upper_bound: 0.01
routines:
- name: quick_pinchoff
parameters:
gate: LB
v_start: -2.0
v_stop: 0.0
n_points: 100
contact: RIGHT
- name: charge_diagram
parameters:
gate_x: LP
gate_y: RP
v_x_start: -2.5
v_x_stop: -0.5
v_y_start: -2.5
v_y_stop: -0.5
n_points_x: 150
n_points_y: 150
contact: RIGHT
instruments:
- name: qdac-control
type: CONTROL
driver: qdac2
ip_addr: 192.168.1.100
slew_rate: 0.5
- name: qdac-measure
type: MEASUREMENT
driver: qdac2
ip_addr: 192.168.1.100
measurement_duration: 10e-3
sample_time: 100e-6
current_range: "LOW"

Use it in your code:

from stanza.utils import device_from_yaml
from stanza.routines import RoutineRunner
from stanza.models import DeviceConfig
# Direct device usage
device = device_from_yaml("device.yaml")
device.jump({"LP": -1.5, "RP": -1.2})
current = device.measure("RIGHT")
# Or use with routines
config = DeviceConfig.from_yaml("device.yaml")
runner = RoutineRunner(configs=[config])
runner.run("quick_pinchoff")
runner.run("charge_diagram")

Tips and Best Practices

Use descriptive names: Names like LEFT_PLUNGER and RIGHT_BARRIER are clearer than G1 and G2.

Start with conservative voltage bounds: You can always widen them later. Better safe than sorry.

Test with simulation first: Use is_simulation: true to verify your configuration before connecting to hardware.

One config per device: Don’t try to reuse configurations across different physical devices. Channel mappings will differ.

Version control your configs: Keep them in git alongside your routines. Document what changed and why.

Comment your YAML: Future you will thank you for explaining why certain parameters were chosen.

Next Steps

  • Device Groups - Learn how to organize pads for isolated testing
  • Routines - Learn how to write measurement routines using your configured device
  • Drivers - Understand how instruments communicate with hardware
  • Data Logging - Automatically log data from your measurements