Skip to content

Sweep Program API

Import paths

from qm.qua import (
    declare_with_stream,
    NativeIterable,
    NativeIterableRange,
    QuaIterable,
    QuaIterableRange,
    QuaProduct,
    QuaZip,
)

Automatic streaming

qm.qua.declare_with_stream

declare_with_stream(
    t: type[NumberT],
    stream_name: str,
    value: Optional[NumberT] = None,
    auto_buffer: bool = True,
    average_axes: Optional[list[str]] = None,
) -> DirectStreamSource[NumberT]

Declare a QUA variable that is automatically saved to a result stream.

The returned object can be used anywhere the declared QUA variable can be used, including assignments and measurement processes. During stream_processing, the saved values are emitted to stream_name.

When auto_buffer=True, buffering is derived from the enclosing named QUA loops. Native iterables are not buffered; their current values are appended to the saved stream name instead. When no averaging is requested, the outermost buffered QUA axis is left unbuffered so live plotting can consume the stream progressively, and the generated stream-processing step stores the result with save_all(). When average_axes is provided, the named axes are reduced during generated stream processing and the final averaged result is stored with save().

PARAMETER DESCRIPTION
t

Type of the declared variable, for example fixed, int, or bool.

TYPE: type[NumberT]

stream_name

Base name of the result stream.

TYPE: str

value

Optional initial value for the declared variable.

TYPE: Optional[NumberT] DEFAULT: None

auto_buffer

If True, derive buffering from the enclosing named QUA loops. When no averaging is requested, the first buffered QUA axis is left unbuffered for live plotting. Defaults to True.

TYPE: bool DEFAULT: True

average_axes

Names of QUA loop axes to average when auto_buffer=True. When provided, the generated stream processing stores the reduced result with save(); otherwise it stores the stream with save_all(). Defaults to None.

TYPE: Optional[list[str]] DEFAULT: None

RETURNS DESCRIPTION
DirectStreamSource[NumberT]

A stream-backed QUA variable.

RAISES DESCRIPTION
QmQuaException

If average_axes is provided while auto_buffer is False, if average_axes refers to a native iterator, if non-averaged QUA loop scopes appear before an averaged axis, or if auto-buffering is used inside loops without names or known sizes.

Example
shots = QuaIterableRange("shots", 100)

with program() as prog:
    for shot in shots:
        I = declare_with_stream(fixed, "I", auto_buffer=True)
        Q = declare_with_stream(fixed, "Q", auto_buffer=True)
        measure(
            "readout",
            "rr",
            demod.full("cos", I),
            demod.full("sin", Q),
        )

Iterator helpers

NativeIterable

NativeIterable(
    name: str,
    array: NativeArrayType,
    *,
    metadata: Optional[MetaDataType] = None
)

Python-side iterable over explicit values.

Use this helper for loops that choose Python values such as element names, labels, or configuration variants. No QUA variable is declared; the yielded value is a Python value.

Use NativeIterable instead of a plain Python iterator when the Python-side axis should still participate in Sweep Program composition. The iterable name is preserved, so the axis can be combined inside QuaProduct or QuaZip, and its current value can be reflected in generated stream names by declare_with_stream.

Example
with program() as prog:
    for element in NativeIterable("element", ["q1", "q2"]):
        play("x180", element)

This is equivalent to:

with program() as prog:
    for element in ["q1", "q2"]:
        play("x180", element)

values property

values: NativeArrayType

Return the Python values represented by this iterable.

NativeIterableRange

NativeIterableRange(
    name: str,
    stop: int,
    *,
    metadata: Optional[MetaDataType] = None
)
NativeIterableRange(
    name: str,
    start: Number,
    stop: Number,
    step: Number = 1,
    *,
    metadata: Optional[MetaDataType] = None
)
NativeIterableRange(
    name: str,
    *args: Number,
    metadata: Optional[MetaDataType] = None
)

Python-side range iterator.

Use this helper for sweep dimensions that should stay in Python, for example when choosing configuration variants or element names around QUA code. No QUA variable is declared; the yielded value is a Python value.

Use NativeIterableRange instead of a plain Python iterator when the Python-side axis should still participate in Sweep Program composition. The iterable name is preserved, so the axis can be combined inside QuaProduct or QuaZip, and its current value can be reflected in generated stream names by declare_with_stream.

NativeIterableRange(name, stop) behaves like range(stop). NativeIterableRange(name, start, stop, step) behaves like range(start, stop, step) for integers and like numpy.arange(start, stop, step) for floats. stop is exclusive.

Example
with program() as prog:
    for amp_scale in NativeIterableRange("amp_scale", 0.1, 1.0, 0.05):
        play("pulse" * amp(amp_scale), "element")

This is equivalent to:

with program() as prog:
    for amp_scale in np.arange(0.1, 1.0, 0.05):
        play("pulse" * amp(amp_scale), "element")

values property

values: NativeArrayType

Return the Python values represented by this iterable.

QuaIterable

QuaIterable(
    name: str,
    array: QuaIterableArrayInputInt,
    *,
    metadata: Optional[MetaDataType] = None
)
QuaIterable(
    name: str,
    array: QuaIterableArrayInputFloat,
    *,
    metadata: Optional[MetaDataType] = None
)
QuaIterable(
    name: str,
    array: QuaIterableArrayInput,
    *,
    metadata: Optional[MetaDataType] = None
)

QUA-side iterable over an explicit sequence of numeric values.

Use this helper when a sweep axis should execute on the QOP rather than in Python.

If the values are uniformly spaced, the iterator may be optimized to a for_ loop. Otherwise it is compiled as a for_each_ loop.

Integer sequences produce integer QUA variables. Any non-integer values are converted to float.

The yielded value is a QUA variable, not a Python scalar.

Example
with program() as prog:
    for amp_scale in QuaIterable("amp_scale", np.linspace(0.1, 0.6, 10)):
        play("pulse" * amp(amp_scale), "element")

This is equivalent to:

with program() as prog:
    amp_scale = declare(fixed)
    with for_each_(amp_scale, np.linspace(0.1, 0.6, 10)):
        play("pulse" * amp(amp_scale), "element")

values property

values: QuaIterableArrayType[T]

Return the Python values represented by this iterable.

is_stream_averaged

is_stream_averaged(stream_name: str) -> bool

Check if stream is averaged on this iterable

QuaIterableRange

QuaIterableRange(
    name: str,
    stop: int,
    *,
    metadata: Optional[MetaDataType] = None
)
QuaIterableRange(
    name: str,
    start: int,
    stop: int,
    step: int = 1,
    *,
    metadata: Optional[MetaDataType] = None
)
QuaIterableRange(
    name: str,
    start: Number,
    stop: Number,
    step: Number = 1,
    *,
    metadata: Optional[MetaDataType] = None
)
QuaIterableRange(
    name: str,
    /,
    *args: Number,
    metadata: Optional[MetaDataType] = None,
)

QUA-side range iterator.

Use this helper when a sweep axis should execute on the QOP as a for_ loop rather than in Python.

QuaIterableRange(name, stop) behaves like range(stop). QuaIterableRange(name, start, stop, step) behaves like range(start, stop, step) for integers and like numpy.arange(start, stop, step) for floats. stop is exclusive.

The yielded value is a QUA variable, not a Python scalar.

For floating-point ranges, the internal stop value may be adjusted slightly to avoid fixed-point boundary issues in the generated loop.

Example
with program() as prog:
    for amp_scale in QuaIterableRange("amp_scale", 0.1, 1.0, 0.05):
        play("pulse" * amp(amp_scale), "element")

This is equivalent to:

with program() as prog:
    amp_scale = declare(fixed)
    with for_(amp_scale, 0.1, amp_scale < 1.0, amp_scale + 0.05):
        play("pulse" * amp(amp_scale), "element")

values property

values: QuaIterableArrayType[T]

Return the Python values represented by this iterable.

QuaProduct

QuaProduct(iterables: List[IterableBase[Any]])

Combine iterables into nested loops, similarly to Python's itertools.product.

QuaProduct expands a sequence of iterable helpers into nested loops. The first iterable becomes the outermost loop and the last iterable becomes the innermost loop, so reordering the list changes the loop nesting order.

A product can mix QUA iterables and native iterables. The yielded value is a named tuple whose field names match the iterable names.

Note

Use QuaProduct as the outer combinator. Do not pass a QuaProduct instance into another iterable helper such as QuaZip.

Example
with program() as prog:
    for args in QuaProduct(
        [
            QuaIterableRange("shot", 100),
            NativeIterable("element", ["q1", "q2"]),
            QuaZip(
                [
                    QuaIterable("amp", [0.2, 0.5, 0.8]),
                    QuaIterable("tau", [16, 32, 64]),
                ],
                name="drive",
            ),
        ]
    ):
        play("x90" * amp(args.drive.amp), args.element)
        wait(args.drive.tau)

QuaZip

QuaZip(
    iterables: Sequence[IterableBase[Any]],
    name: Optional[str] = None,
)

Combine iterables position-by-position, similarly to Python's built-in zip.

QuaZip advances multiple iterables together and yields one named tuple per position.

It can zip either QUA iterables or native iterables, but not both in the same call. When zipping QUA iterables, the zip is compiled as a single for_each_ loop. When zipping native iterables, iteration happens in Python and stops at the shortest iterable.

Note

Provide iterables with matching lengths so that the zipped values represent the same sweep positions.

Example
with program() as prog:
    for pair in QuaZip(
        [
            QuaIterable("amp", [0.2, 0.5, 0.8]),
            QuaIterable("tau", [16, 32, 64]),
        ]
    ):
        play("x90" * amp(pair.amp), "q1")
        wait(pair.tau)

values property

values: MultiIteratorsValuesType

Return the underlying values of the zipped iterables.

For usage examples and behavior details, see the Sweep Program guide.