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

Uploaded Python 3

File details

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

File metadata

  • Download URL: tergite_tuner-2026.6.0.tar.gz
  • Upload date:
  • Size: 236.9 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.0.tar.gz
Algorithm Hash digest
SHA256 db07dee642fedb362c075beefce5c7f4c2a4281d18d5877c1d0798e5a8709ab4
MD5 82fab7367e13be1b75db246fe5e41058
BLAKE2b-256 6be5a15ccc96aa38618c4fd7be936938ab98748ef7a5fad4737c9f8f7ab76e70

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for tergite_tuner-2026.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 33b19b082ddb93443ee3a1c9b2a4b87fc0248dfd2e0845139f43d07e5bed94cf
MD5 348a8b1ecee490baccf1aec73232d6a9
BLAKE2b-256 545d71e6c4ec137c68777e7e47a5309b1635bac7e6b1f0c75896d8b416ef72e2

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