Skip to main content

Library to tune up the WACQT quantum computers

Project description

Tergite Tuner

CI

A Python library that tunes up the WACQT quantum computers.

This is a stripped down fork of the tergite-autocalibration project that was developed jointly by Chalmers Next Labs (CNL) and the Quantum Technology department of Chalmers University of Technology.

It is meant to be used as a library that one can install in their project while tergite-autocalibration is meant to be used more interactively with CLI, GUI to browse datasets, and charts for more manual oversight of the tuneup.

It contains a calibration runner, a collection of calibration schedules, and a collection of post-processing and analysis routines. It is developed and tested on the WACQT quantum computers at Chalmers Next Labs quantum testbed and Chalmers University of Technology.

This project is developed by a core group of collaborators. Chalmers Next Labs AB (CNL) takes on the role of managing and maintaining this project.

Note: The Tergite stack is developed on a separate version control system and mirrored on GitHub. If you are reading this on GitHub, then you are looking at a mirror.

This project owes its very existence to the tireless work of the authors and contributors of tergite-autocalibration.

Quick Start

Requirements

  • Python ≥ 3.12 but < 3.13 (a fresh conda or venv environment is fine).
  • A reachable redis server. The default URL is redis://127.0.0.1:6379/0; override via the REDIS_URL env var or the redis_url keyword argument when calling the public API.
redis-server

Installation

pip install tergite-tuner

Copy the example environment file and edit it as needed.

The .env file controls the cluster IP, redis URL, target node, qubits/couplers under calibration, and so on.

Every field on SessionContextcan be set in the .env (in upper case), or passed as a keyword argument to the public API of the entry point functions.

On top of having a .env file, more configuration files maybe required. (See .example.env file for more details)

The contents of each of these files can as well be passed to the entry functions as python objects e.g.

from tergite_tuner import tune_device
from tergite_tuner.config.types import (
    DeviceConfig, 
    ClusterConfig, 
    SpiConfig, 
    NodeConfig,
)

_, results = tune_device(
    device_config=DeviceConfig(
        name = "matthias",
        resonator={
            "all": {"attenuation": 10},
            "q01": { "VNA_frequency": 6433000000.0 },
            "q02":{ "VNA_frequency": 6290000000.0 },
        },
        # ...
    ), 
    node_config=NodeConfig.model_validate(
        {
            "qubit_spectroscopy_vs_current": {
                "all": {
                    "spec.spec_duration": 6e-6,
                    "reset.duration": 200e-6,
                },
            }
        }
    ), 
    spi_config=SpiConfig.model_validate({
        "q11_q12": {
            "spi_module_number": 1,
            "dac_name": "dac0",
            "edge_group": 1,
        },        
        "q12_q13": {
            "spi_module_number": 2,
            "dac_name": "dac1",
            "edge_group": 2,
        }
    }),                
    cluster_config=ClusterConfig.model_validate({
      "config_type": "quantify_scheduler.backends.qblox_backend.QbloxHardwareCompilationConfig",
      "hardware_description": {
        "clusterA": {
          "instrument_type": "Cluster",
          "ref": "internal",
          "modules": {
            "1": {
              "instrument_type": "QCM_RF"
            },
          }
        }
      },
      # ...
    })
)

Customization of Nodes

It is also possible to pass in your own implementation of the Nodes as long as they are inherited from the base nodes BaseNode, QubitNode, CouplerNode etc.

You can also change the order in which the nodes run or even choose to skip some of them by supplying your own ignored_nodes: tuple[NodeEnum, ...] = ... and node_dag_edges: tuple[tuple[NodeEnum, NodeEnum], ...] as args to the entry point functions.

from tergite_tuner.lib.base.node import QubitNode, BaseNode, CouplerNode
from tergite_tuner import tune_device, NodeEnum


class CustomQubitNode(QubitNode):
    ...


class CustomDeviceNode(BaseNode):
    def precompile(self, samplespace): ...

    @classmethod
    def persist_qois(cls, session: "SessionContext", node_name: str): ...


class CustomCouplerNode(QubitNode):
    ...


_, results = tune_device(
    node_cls_map={
        NodeEnum.QUBIT_01_SPECTROSCOPY: CustomQubitNode,
        NodeEnum.COUPLER_ANTICROSSING: CustomCouplerNode,
    },
    node_dag_edges=(
        (NodeEnum.PUNCHOUT, NodeEnum.TOF,),
        (NodeEnum.QUBIT_01_SPECTROSCOPY, NodeEnum.COUPLER_ANTICROSSING),
    ),
    ignored_nodes=(NodeEnum.PUNCHOUT,)
)

Public API

The library exposes the following entry points from tergite_tuner.__init__:

from tergite_tuner import (
    tune_device,
    reanalyse,
    generate_calib_seed_file,
    run_node,
    read_result,
)

Run the full calibration pipeline

from tergite_tuner import tune_device, read_result
from tergite_tuner.lib.nodes import NodeEnum

# Use a .env file as the only source of configuration
_, results = tune_device(env_file=".env")

# Or override individual SessionContext fields inline
session, results = tune_device(
    env_file=".env",
    target_node=NodeEnum.RABI_OSCILLATIONS,
    qubits=["q00", "q01"],
    couplers=["q00_q01"],
)

# you can even pass a session from before or construct it yourself with 
# SessionContext.from_env()
tune_device(session=session, refresh_session=False)

# if you disabled session-refresh, you can read all results on 
# that session at once
results = read_result(session)

tune_device constructs a SessionContext, walks the dependency DAG up to target_node, and calibrates any nodes that are not yet in spec.

Recalibrate the device

First ensure your device_config.toml has the latest device values or if you have already run the tuneup using the same redis database, the old values should still be there so have a device_config.toml without initial values.
Note that this may mean you have two device_config.toml's, one for the first run and the other for subsequent runs.
Do the same with node_config.toml.

from tergite_tuner import tune_device, NodeEnum

# Use a .env file as the only source of configuration
_, results = tune_device(env_file=".env")

# Or override individual SessionContext fields inline
session, results = tune_device(
    env_file=".env",
    target_node=NodeEnum.RABI_OSCILLATIONS,
    qubits=["q00", "q01"],
    couplers=["q00_q01"],
    is_recalibration=True,
)

# you can even pass a session from before or construct it yourself with 
# SessionContext.from_env()
_, results = tune_device(session=session, refresh_session=False)

# you could clear up all the data files after the run
_, results = tune_device(
    session=session, refresh_session=False, keep_data_files=False)

Run one node

from tergite_tuner import run_node, NodeEnum, read_result

# Use a .env file as the only source of configuration
session, results = run_node(
    env_file=".env", node=NodeEnum.QUBIT_01_SPECTROSCOPY)

# Or override individual SessionContext fields inline
_, results = run_node(
    env_file=".env",
    qubits=["q00", "q01"],
    couplers=["q00_q01"],
    node=NodeEnum.QUBIT_01_SPECTROSCOPY
)

# you can even pass a session from before or construct it yourself with 
# SessionContext.from_env()
run_node(
    node=NodeEnum.QUBIT_01_SPECTROSCOPY, session=session, refresh_session=False)

# if you disabled session-refresh, you can read all results on 
# that session at once
results = read_result(session)

# you could clear up all the data files after the run
_, results = run_node(
    session=session, refresh_session=False, keep_data_files=False)

Re-run analysis on already-recorded data

from pathlib import Path
from tergite_tuner import reanalyse

_, results = reanalyse(
    env_file=".env",
    data_dir=Path("path/to/run/folder"),
)

Generate a BCC calibration seed

from tergite_tuner import generate_calib_seed_file, SessionContext

# Reads qubits / couplers / redis_url from the .env file. 
# Creates the file as 'calibration.seed.toml' by default
generate_calib_seed_file(env_file=".env")

# Or override individual SessionContext fields inline:
generate_calib_seed_file(couplers=["q12_q13", "q56_q67"], qubits=["q12"], path="/path/to/destination/toml/file")

# Or pass in a session from somewhere else:
session = SessionContext()
generate_calib_seed_file(session)

Samples

You can find a few examples in the ./examples folder

ToDo

  • Update export to BCC to be more generic to allow any BaseModel class to be output
  • Add tests for entire calibration runs, maybe using mode=dummy
  • Add ability to add new nodes in the NodeEnum map or allow a more flexible type in the mapping

Contributing to the project

If you would like to contribute to tergite-tuner, please have a look at our contribution guidelines.

Authors

This project is a work of many contributors.

Special credit goes to the authors of this project as seen in the CREDITS file.

Change log

To view the changelog for each version, have a look at the CHANGELOG.md file.

License

When you submit code changes, your submissions are understood to be under the same Apache 2.0 License that covers the project.

Acknowledgements

This project was sponsored by:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tergite_tuner-2026.6.0rc2.tar.gz (236.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tergite_tuner-2026.6.0rc2-py3-none-any.whl (320.7 kB view details)

Uploaded Python 3

File details

Details for the file tergite_tuner-2026.6.0rc2.tar.gz.

File metadata

  • Download URL: tergite_tuner-2026.6.0rc2.tar.gz
  • Upload date:
  • Size: 236.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for tergite_tuner-2026.6.0rc2.tar.gz
Algorithm Hash digest
SHA256 f7f38eb9eb5bb2069c8f53c8489fb2d5c647110cf8e5312835533903df15263e
MD5 0a52f981d48612f786eca548f2a72465
BLAKE2b-256 d6287bc1dc2e513068863c0306ab60228c3a0dc2079f9ddbf1a16db4b325c05a

See more details on using hashes here.

File details

Details for the file tergite_tuner-2026.6.0rc2-py3-none-any.whl.

File metadata

File hashes

Hashes for tergite_tuner-2026.6.0rc2-py3-none-any.whl
Algorithm Hash digest
SHA256 73ae868dc81fa46d33785e8eb876041a4200388781abec097bbbccdfa5d2f0c5
MD5 9b220874cfb94cb38a77651c9da22667
BLAKE2b-256 df311efb2752c432b5aea5e7b2c5361653500ee99713a65a9cefeeab9c3d7ab2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page