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.0rc4.tar.gz (236.8 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.0rc4-py3-none-any.whl (320.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: tergite_tuner-2026.6.0rc4.tar.gz
  • Upload date:
  • Size: 236.8 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.0rc4.tar.gz
Algorithm Hash digest
SHA256 5bf0ec53cf78f4981a2745771484a9eedb81bf8d7c666ad8262a6e8bf7f9bef5
MD5 db2305c0aac3b433ec1457a1a486db24
BLAKE2b-256 f6e310bad23e18e28063d2bb13c8117e56d86647bcc38cb6add72860b947b0f2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for tergite_tuner-2026.6.0rc4-py3-none-any.whl
Algorithm Hash digest
SHA256 dd65e3fe4b5cba32ed96074d5ab32e53e864e31387a72fc54a2b6a9a4d005ebe
MD5 d9b7cc4efd6efd335ab9158fe0448f35
BLAKE2b-256 2304800ed04c9e01bd3be6dd1cf5b780f4b4a00db683be5b1a244379cb38ed70

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