Source code for qibolab.sweeper

import operator
from dataclasses import dataclass
from enum import Enum, auto
from functools import partial
from typing import Optional

import numpy.typing as npt


[docs]class Parameter(Enum): """Sweeping parameters.""" frequency = auto() amplitude = auto() duration = auto() relative_phase = auto() start = auto() attenuation = auto() gain = auto() bias = auto() lo_frequency = auto()
FREQUENCY = Parameter.frequency AMPLITUDE = Parameter.amplitude DURATION = Parameter.duration RELATIVE_PHASE = Parameter.relative_phase START = Parameter.start ATTENUATION = Parameter.attenuation GAIN = Parameter.gain BIAS = Parameter.bias
[docs]class SweeperType(Enum): """Type of the Sweeper.""" ABSOLUTE = partial(lambda x, y=None: x) FACTOR = operator.mul OFFSET = operator.add
QubitParameter = {Parameter.bias, Parameter.attenuation, Parameter.gain}
[docs]@dataclass class Sweeper: """Data structure for Sweeper object. This object is passed as an argument to the method :func:`qibolab.platforms.abstract.Platform.sweep` which enables the user to sweep a specific parameter for one or more pulses. For information on how to perform sweeps see :func:`qibolab.platforms.abstract.Platform.sweep`. Example: .. testcode:: import numpy as np from qibolab.dummy import create_dummy from qibolab.sweeper import Sweeper, Parameter from qibolab.pulses import PulseSequence from qibolab import ExecutionParameters platform = create_dummy() sequence = PulseSequence() parameter = Parameter.frequency pulse = platform.create_qubit_readout_pulse(qubit=0, start=0) sequence.add(pulse) parameter_range = np.random.randint(10, size=10) sweeper = Sweeper(parameter, parameter_range, [pulse]) platform.sweep(sequence, ExecutionParameters(), sweeper) Args: parameter (`qibolab.sweeper.Parameter`): parameter to be swept, possible choices are frequency, attenuation, amplitude, current and gain. _values (np.ndarray): sweep range. If the parameter of the sweep is a pulse parameter, if the sweeper type is not ABSOLUTE, the base value will be taken from the runcard pulse parameters. If the sweep parameter is Bias, the base value will be the sweetspot of the qubits. pulses (list) : list of `qibolab.pulses.Pulse` to be swept (optional). qubits (list): list of `qibolab.platforms.abstract.Qubit` to be swept (optional). type (SweeperType): can be ABSOLUTE (the sweeper range is swept directly), FACTOR (sweeper values are multiplied by base value), OFFSET (sweeper values are added to base value) """ parameter: Parameter values: npt.NDArray pulses: Optional[list] = None qubits: Optional[list] = None couplers: Optional[list] = None type: Optional[SweeperType] = SweeperType.ABSOLUTE def __post_init__(self): if ( self.pulses is not None and self.qubits is not None and self.couplers is not None ): raise ValueError("Cannot use a sweeper on both pulses and qubits.") if self.pulses is not None and self.parameter in QubitParameter: raise ValueError( f"Cannot sweep {self.parameter} without specifying qubits or couplers." ) if self.parameter not in QubitParameter and ( self.qubits is not None or self.couplers is not None ): raise ValueError( f"Cannot sweep {self.parameter} without specifying pulses." ) if self.pulses is None and self.qubits is None and self.couplers is None: raise ValueError( "Cannot use a sweeper without specifying pulses, qubits or couplers." )
[docs] def get_values(self, base_value): """Convert sweeper values depending on the sweeper type.""" return self.type.value(self.values, base_value)