Skip to content

qoolqit.waveforms

waveforms

Composable, time-bounded scalar waveforms for pulse-level quantum control.

Modules:

  • base_waveforms

    Base classes for scalar time-bounded waveforms and their sequential composition.

  • utils
  • waveforms

    Concrete waveform implementations.

Classes:

BlackmanWaveform(duration: float, area: float)

A Blackman window of a specified duration and area under the curve.

Implements the positive Blackman window shaped waveform blackman(t) = A(0.42 - 0.5cos(αt) + 0.08cos(2αt)) A = area/(0.42duration) α = 2π/duration

See: https://en.wikipedia.org/wiki/Window_function#:~:text=Blackman%20window

Parameters:

  • duration

    (float) –

    The waveform duration.

  • area

    (float) –

    The integral of the waveform.

Example
blackman_wf = BlackmanWaveform(100.0, area=3.14)

Methods:

  • __rmul__

    Rescale this waveform by a scalar (right-hand multiplication).

  • __rshift__

    Returns a new CompositeWaveform composed of this waveform and another.

Attributes:

  • duration (float) –

    Returns the duration of the waveform.

  • params (dict[str, float | ndarray]) –

    Dictionary of parameters used by the waveform.

Source code in qoolqit/waveforms/waveforms.py
def __init__(self, duration: float, area: float) -> None:
    """Initializes a new BlackmanWaveform."""
    super().__init__(duration, area=area)

duration: float property

Returns the duration of the waveform.

params: dict[str, float | np.ndarray] property

Dictionary of parameters used by the waveform.

__rmul__(other: float) -> Waveform

Rescale this waveform by a scalar (right-hand multiplication).

Source code in qoolqit/waveforms/base_waveforms.py
def __rmul__(self, other: float) -> Waveform:
    """Rescale this waveform by a scalar (right-hand multiplication)."""
    return self.__mul__(other)

__rshift__(other: Waveform) -> CompositeWaveform

Returns a new CompositeWaveform composed of this waveform and another.

Source code in qoolqit/waveforms/base_waveforms.py
def __rshift__(self, other: Waveform) -> CompositeWaveform:
    """Returns a new CompositeWaveform composed of this waveform and another."""
    if isinstance(other, Waveform):
        if isinstance(other, CompositeWaveform):
            return CompositeWaveform(self, *other._waveforms)
        return CompositeWaveform(self, other)
    else:
        raise NotImplementedError(f"Composing with object of type {type(other)} not supported.")

CompositeWaveform(*waveforms: Waveform)

A concatenation of waveforms played sequentially.

Waveforms are joined in the given order, each starting where the previous one ends, and the composition can be used as a single waveform.

Attributes:

  • waveforms (list[Waveform]) –

    a list of waveforms in the composition.

  • durations (list[float]) –

    a list of durations of each individual waveform.

  • times (list[float]) –

    a list of times when each individual waveform starts.

Parameters:

  • waveforms

    (Waveform, default: () ) –

    an iterator over waveforms.

Raises:

  • TypeError

    if any argument is not an instance of Waveform.

  • ValueError

    if no waveforms are provided.

Methods:

  • __rmul__

    Rescale this waveform by a scalar (right-hand multiplication).

  • max

    Get the maximum value of the waveform.

  • min

    Get the minimum value of the waveform.

Source code in qoolqit/waveforms/base_waveforms.py
def __init__(self, *waveforms: Waveform) -> None:
    """Initializes the CompositeWaveform.

    Arguments:
        waveforms: an iterator over waveforms.

    Raises:
        TypeError: if any argument is not an instance of Waveform.
        ValueError: if no waveforms are provided.
    """
    if not all(isinstance(wf, Waveform) for wf in waveforms):
        raise TypeError("All arguments must be instances of Waveform.")
    if not waveforms:
        raise ValueError("At least one Waveform must be provided.")

    self._waveforms = []
    for wf in waveforms:
        if isinstance(wf, CompositeWaveform):
            self._waveforms += wf.waveforms
        else:
            self._waveforms.append(wf)

    super().__init__(sum(self.durations))

duration: float property

Returns the duration of the waveform.

durations: list[float] property

Returns the list of durations of each individual waveform.

n_waveforms: int property

Returns the number of waveforms.

params: dict[str, float | np.ndarray] property

Dictionary of parameters used by the waveform.

times: list[float] property

Returns the list of times when each individual waveform starts.

waveforms: list[Waveform] property

Returns a list of the individual waveforms.

__rmul__(other: float) -> Waveform

Rescale this waveform by a scalar (right-hand multiplication).

Source code in qoolqit/waveforms/base_waveforms.py
def __rmul__(self, other: float) -> Waveform:
    """Rescale this waveform by a scalar (right-hand multiplication)."""
    return self.__mul__(other)

max() -> float

Get the maximum value of the waveform.

Source code in qoolqit/waveforms/base_waveforms.py
def max(self) -> float:
    """Get the maximum value of the waveform."""
    return max([wf.max() for wf in self.waveforms])

min() -> float

Get the minimum value of the waveform.

Source code in qoolqit/waveforms/base_waveforms.py
def min(self) -> float:
    """Get the minimum value of the waveform."""
    return min([wf.min() for wf in self.waveforms])

ConstantWaveform(duration: float, value: float)

A constant waveform over a given duration.

Parameters:

  • duration

    (float) –

    the total duration.

  • value

    (float) –

    the value to take during the duration.

Methods:

  • __rmul__

    Rescale this waveform by a scalar (right-hand multiplication).

  • __rshift__

    Returns a new CompositeWaveform composed of this waveform and another.

Attributes:

  • duration (float) –

    Returns the duration of the waveform.

  • params (dict[str, float | ndarray]) –

    Dictionary of parameters used by the waveform.

Source code in qoolqit/waveforms/waveforms.py
def __init__(
    self,
    duration: float,
    value: float,
) -> None:
    super().__init__(duration, value=value)

duration: float property

Returns the duration of the waveform.

params: dict[str, float | np.ndarray] property

Dictionary of parameters used by the waveform.

__rmul__(other: float) -> Waveform

Rescale this waveform by a scalar (right-hand multiplication).

Source code in qoolqit/waveforms/base_waveforms.py
def __rmul__(self, other: float) -> Waveform:
    """Rescale this waveform by a scalar (right-hand multiplication)."""
    return self.__mul__(other)

__rshift__(other: Waveform) -> CompositeWaveform

Returns a new CompositeWaveform composed of this waveform and another.

Source code in qoolqit/waveforms/base_waveforms.py
def __rshift__(self, other: Waveform) -> CompositeWaveform:
    """Returns a new CompositeWaveform composed of this waveform and another."""
    if isinstance(other, Waveform):
        if isinstance(other, CompositeWaveform):
            return CompositeWaveform(self, *other._waveforms)
        return CompositeWaveform(self, other)
    else:
        raise NotImplementedError(f"Composing with object of type {type(other)} not supported.")

DelayWaveform(duration: float, *args: float, **kwargs: float | np.ndarray)

An empty waveform.

Parameters:

  • duration

    (float) –

    the total duration of the waveform.

  • **kwargs

    (float | ndarray, default: {} ) –

    optional keyword arguments for the waveform function.

Methods:

  • __rmul__

    Rescale this waveform by a scalar (right-hand multiplication).

  • __rshift__

    Returns a new CompositeWaveform composed of this waveform and another.

Attributes:

  • duration (float) –

    Returns the duration of the waveform.

  • params (dict[str, float | ndarray]) –

    Dictionary of parameters used by the waveform.

Source code in qoolqit/waveforms/base_waveforms.py
def __init__(
    self,
    duration: float,
    *args: float,
    **kwargs: float | np.ndarray,
) -> None:
    """Initializes the Waveform.

    Args:
        duration: the total duration of the waveform.
        **kwargs: optional keyword arguments for the waveform function.
    """

    if duration <= 0:
        raise ValueError("Duration needs to be a positive non-zero value.")

    if len(args) > 0:
        raise ValueError(
            f"Extra arguments in {type(self).__name__} need to be passed as keyword arguments"
        )

    self._duration = duration
    self._params_dict = kwargs

    for key, value in kwargs.items():
        setattr(self, key, value)

duration: float property

Returns the duration of the waveform.

params: dict[str, float | np.ndarray] property

Dictionary of parameters used by the waveform.

__rmul__(other: float) -> Waveform

Rescale this waveform by a scalar (right-hand multiplication).

Source code in qoolqit/waveforms/base_waveforms.py
def __rmul__(self, other: float) -> Waveform:
    """Rescale this waveform by a scalar (right-hand multiplication)."""
    return self.__mul__(other)

__rshift__(other: Waveform) -> CompositeWaveform

Returns a new CompositeWaveform composed of this waveform and another.

Source code in qoolqit/waveforms/base_waveforms.py
def __rshift__(self, other: Waveform) -> CompositeWaveform:
    """Returns a new CompositeWaveform composed of this waveform and another."""
    if isinstance(other, Waveform):
        if isinstance(other, CompositeWaveform):
            return CompositeWaveform(self, *other._waveforms)
        return CompositeWaveform(self, other)
    else:
        raise NotImplementedError(f"Composing with object of type {type(other)} not supported.")

InterpolatedWaveform(duration: float, values: ArrayLike, times: ArrayLike | None = None)

A waveform created from shape-preserving interpolation of data points.

This class creates a smooth waveform by interpolating between specified data points using PCHIP (Piecewise Cubic Hermite Interpolating Polynomial) interpolation. The interpolating curve preserves the shape of the input data: bounds (avoiding under/overshooting), monotonicity, and convexity.

Uses scipy's PchipInterpolator for the interpolation.

Attributes:

  • duration (float) –

    The waveform duration.

  • values (float) –

    Array-like sequence of waveform values at the interpolation points. Must be convertible to float. These values define the amplitude of the waveform at the corresponding time points.

  • times (float) –

    Optional array-like sequence of fractional times in the range [0, 1] indicating where to place each value on the time axis. Must have the same length as values. If not provided, values are distributed evenly across the waveform duration. Default is None.

ValueError: If times contains values outside [0, 1] or if times and values have different lengths.

Example

Create a waveform with 4 points over 100ns

values = [0.0, 1.0, 0.5, 0.0] wf = InterpolatedWaveform(100, values)

Create with custom timing

times = [0.0, 0.2, 0.8, 1.0] # Non-uniform spacing wf = InterpolatedWaveform(100, values, times)

Parameters:

  • duration

    (float) –

    The total duration of the waveform. Must be positive.

  • values

    (ArrayLike) –

    Array-like sequence of waveform values at interpolation points. Can be a list, tuple, numpy array, or any sequence convertible to float.

  • times

    (ArrayLike | None, default: None ) –

    Optional array-like sequence of fractional times in [0, 1]. If provided, must have the same length as values. If None, values are evenly spaced across the duration. Default is None.

Raises:

  • ValueError

    If any value in times is outside [0, 1], or if times and values have different lengths.

Methods:

  • __rmul__

    Rescale this waveform by a scalar (right-hand multiplication).

  • __rshift__

    Returns a new CompositeWaveform composed of this waveform and another.

Source code in qoolqit/waveforms/waveforms.py
def __init__(
    self,
    duration: float,
    values: ArrayLike,
    times: ArrayLike | None = None,
):
    """Initialize an Interpolated waveform.

    Args:
        duration: The total duration of the waveform. Must be positive.
        values: Array-like sequence of waveform values at interpolation points.
            Can be a list, tuple, numpy array, or any sequence convertible to float.
        times: Optional array-like sequence of fractional times in [0, 1]. If provided,
            must have the same length as `values`. If None, values are evenly spaced
            across the duration. Default is None.

    Raises:
        ValueError: If any value in `times` is outside [0, 1], or if `times` and
            `values` have different lengths.
    """
    super().__init__(duration)
    self._values = np.array(values, dtype=float)
    if times is not None:
        self._times = np.array(times, dtype=float)
        if any([(ft < 0) or (ft > 1) for ft in self._times]):
            raise ValueError("All values in `times` must be in [0,1].")
        if len(self._times) != len(self._values):
            raise ValueError(
                "Arguments `values` and `times` must be arrays of the same length."
            )
    else:
        self._times = np.linspace(0, 1, num=len(self._values))

    self._interp_func = PchipInterpolator(duration * self._times, values)

duration: float property

Returns the duration of the waveform.

params: dict[str, float | np.ndarray] property

Dictionary of parameters used by the waveform.

__rmul__(other: float) -> Waveform

Rescale this waveform by a scalar (right-hand multiplication).

Source code in qoolqit/waveforms/base_waveforms.py
def __rmul__(self, other: float) -> Waveform:
    """Rescale this waveform by a scalar (right-hand multiplication)."""
    return self.__mul__(other)

__rshift__(other: Waveform) -> CompositeWaveform

Returns a new CompositeWaveform composed of this waveform and another.

Source code in qoolqit/waveforms/base_waveforms.py
def __rshift__(self, other: Waveform) -> CompositeWaveform:
    """Returns a new CompositeWaveform composed of this waveform and another."""
    if isinstance(other, Waveform):
        if isinstance(other, CompositeWaveform):
            return CompositeWaveform(self, *other._waveforms)
        return CompositeWaveform(self, other)
    else:
        raise NotImplementedError(f"Composing with object of type {type(other)} not supported.")

PiecewiseLinearWaveform(durations: list[float] | tuple[float, ...] | np.ndarray, values: list[float] | tuple[float, ...] | np.ndarray)

A piecewise linear waveform.

Creates a composite waveform of N ramps that linearly interpolate through the given N+1 values.

Parameters:

  • durations

    (list[float] | tuple[float, ...] | ndarray) –

    list or tuple of N duration values.

  • values

    (list[float] | tuple[float, ...] | ndarray) –

    list or tuple of N+1 waveform values.

Methods:

  • __rmul__

    Rescale this waveform by a scalar (right-hand multiplication).

  • max

    Get the maximum value of the waveform.

  • min

    Get the minimum value of the waveform.

Attributes:

  • duration (float) –

    Returns the duration of the waveform.

  • durations (list[float]) –

    Returns the list of durations of each individual waveform.

  • n_waveforms (int) –

    Returns the number of waveforms.

  • params (dict[str, float | ndarray]) –

    Dictionary of parameters used by the waveform.

  • times (list[float]) –

    Returns the list of times when each individual waveform starts.

  • waveforms (list[Waveform]) –

    Returns a list of the individual waveforms.

Source code in qoolqit/waveforms/waveforms.py
def __init__(
    self,
    durations: list[float] | tuple[float, ...] | np.ndarray,
    values: list[float] | tuple[float, ...] | np.ndarray,
) -> None:

    if len(durations) + 1 != len(values) or len(durations) == 1:
        raise ValueError(
            "A PiecewiseLinearWaveform requires N durations and N + 1 values, for N >= 2."
        )

    for duration in durations:
        if duration == 0.0:
            raise ValueError("A PiecewiseLinearWaveform interval cannot have zero duration.")

    self.values = values

    wfs = [RampWaveform(dur, values[i], values[i + 1]) for i, dur in enumerate(durations)]

    super().__init__(*wfs)

duration: float property

Returns the duration of the waveform.

durations: list[float] property

Returns the list of durations of each individual waveform.

n_waveforms: int property

Returns the number of waveforms.

params: dict[str, float | np.ndarray] property

Dictionary of parameters used by the waveform.

times: list[float] property

Returns the list of times when each individual waveform starts.

waveforms: list[Waveform] property

Returns a list of the individual waveforms.

__rmul__(other: float) -> Waveform

Rescale this waveform by a scalar (right-hand multiplication).

Source code in qoolqit/waveforms/base_waveforms.py
def __rmul__(self, other: float) -> Waveform:
    """Rescale this waveform by a scalar (right-hand multiplication)."""
    return self.__mul__(other)

max() -> float

Get the maximum value of the waveform.

Source code in qoolqit/waveforms/base_waveforms.py
def max(self) -> float:
    """Get the maximum value of the waveform."""
    return max([wf.max() for wf in self.waveforms])

min() -> float

Get the minimum value of the waveform.

Source code in qoolqit/waveforms/base_waveforms.py
def min(self) -> float:
    """Get the minimum value of the waveform."""
    return min([wf.min() for wf in self.waveforms])

RampWaveform(duration: float, initial_value: float, final_value: float)

A ramp that linearly interpolates between an initial and final value.

Parameters:

  • duration

    (float) –

    the total duration.

  • initial_value

    (float) –

    the initial value at t = 0.

  • final_value

    (float) –

    the final value at t = duration.

Methods:

  • __rmul__

    Rescale this waveform by a scalar (right-hand multiplication).

  • __rshift__

    Returns a new CompositeWaveform composed of this waveform and another.

Attributes:

  • duration (float) –

    Returns the duration of the waveform.

  • params (dict[str, float | ndarray]) –

    Dictionary of parameters used by the waveform.

Source code in qoolqit/waveforms/waveforms.py
def __init__(
    self,
    duration: float,
    initial_value: float,
    final_value: float,
) -> None:
    super().__init__(duration, initial_value=initial_value, final_value=final_value)

duration: float property

Returns the duration of the waveform.

params: dict[str, float | np.ndarray] property

Dictionary of parameters used by the waveform.

__rmul__(other: float) -> Waveform

Rescale this waveform by a scalar (right-hand multiplication).

Source code in qoolqit/waveforms/base_waveforms.py
def __rmul__(self, other: float) -> Waveform:
    """Rescale this waveform by a scalar (right-hand multiplication)."""
    return self.__mul__(other)

__rshift__(other: Waveform) -> CompositeWaveform

Returns a new CompositeWaveform composed of this waveform and another.

Source code in qoolqit/waveforms/base_waveforms.py
def __rshift__(self, other: Waveform) -> CompositeWaveform:
    """Returns a new CompositeWaveform composed of this waveform and another."""
    if isinstance(other, Waveform):
        if isinstance(other, CompositeWaveform):
            return CompositeWaveform(self, *other._waveforms)
        return CompositeWaveform(self, other)
    else:
        raise NotImplementedError(f"Composing with object of type {type(other)} not supported.")

Waveform(duration: float, *args: float, **kwargs: float | np.ndarray)

Base class for scalar time-bounded waveforms.

A waveform is a scalar function of time defined over a finite interval [0, duration]. Outside this interval, it evaluates to zero.

To define a custom waveform, subclass this class and implement: - function(t): the waveform value at time t within [0, duration]. - max(): the maximum value of the waveform. - min(): the minimum value of the waveform. - __mul__(scalar): rescale this waveform by a scalar factor. - _to_pulser(duration): conversion to a Pulser-compatible waveform.

Any additional parameters (e.g. amplitude, frequency) should be passed as keyword arguments to __init__ and are automatically stored and accessible as attributes.

Parameters:

  • duration

    (float) –

    the total duration of the waveform.

  • **kwargs

    (float | ndarray, default: {} ) –

    optional keyword arguments for the waveform function.

Methods:

  • __mul__

    Rescale this waveform by a scalar.

  • __rmul__

    Rescale this waveform by a scalar (right-hand multiplication).

  • __rshift__

    Returns a new CompositeWaveform composed of this waveform and another.

  • function

    Evaluates the waveform function at a given time t.

  • max

    Get the maximum value of the waveform.

  • min

    Get the minimum value of the waveform.

Attributes:

  • duration (float) –

    Returns the duration of the waveform.

  • params (dict[str, float | ndarray]) –

    Dictionary of parameters used by the waveform.

Source code in qoolqit/waveforms/base_waveforms.py
def __init__(
    self,
    duration: float,
    *args: float,
    **kwargs: float | np.ndarray,
) -> None:
    """Initializes the Waveform.

    Args:
        duration: the total duration of the waveform.
        **kwargs: optional keyword arguments for the waveform function.
    """

    if duration <= 0:
        raise ValueError("Duration needs to be a positive non-zero value.")

    if len(args) > 0:
        raise ValueError(
            f"Extra arguments in {type(self).__name__} need to be passed as keyword arguments"
        )

    self._duration = duration
    self._params_dict = kwargs

    for key, value in kwargs.items():
        setattr(self, key, value)

duration: float property

Returns the duration of the waveform.

params: dict[str, float | np.ndarray] property

Dictionary of parameters used by the waveform.

__mul__(other: float) -> Waveform abstractmethod

Rescale this waveform by a scalar.

Source code in qoolqit/waveforms/base_waveforms.py
@abstractmethod
def __mul__(self, other: float) -> Waveform:
    """Rescale this waveform by a scalar."""
    pass

__rmul__(other: float) -> Waveform

Rescale this waveform by a scalar (right-hand multiplication).

Source code in qoolqit/waveforms/base_waveforms.py
def __rmul__(self, other: float) -> Waveform:
    """Rescale this waveform by a scalar (right-hand multiplication)."""
    return self.__mul__(other)

__rshift__(other: Waveform) -> CompositeWaveform

Returns a new CompositeWaveform composed of this waveform and another.

Source code in qoolqit/waveforms/base_waveforms.py
def __rshift__(self, other: Waveform) -> CompositeWaveform:
    """Returns a new CompositeWaveform composed of this waveform and another."""
    if isinstance(other, Waveform):
        if isinstance(other, CompositeWaveform):
            return CompositeWaveform(self, *other._waveforms)
        return CompositeWaveform(self, other)
    else:
        raise NotImplementedError(f"Composing with object of type {type(other)} not supported.")

function(t: float) -> float abstractmethod

Evaluates the waveform function at a given time t.

Source code in qoolqit/waveforms/base_waveforms.py
@abstractmethod
def function(self, t: float) -> float:
    """Evaluates the waveform function at a given time t."""
    pass

max() -> float abstractmethod

Get the maximum value of the waveform.

Source code in qoolqit/waveforms/base_waveforms.py
@abstractmethod
def max(self) -> float:
    """Get the maximum value of the waveform."""
    pass

min() -> float abstractmethod

Get the minimum value of the waveform.

Source code in qoolqit/waveforms/base_waveforms.py
@abstractmethod
def min(self) -> float:
    """Get the minimum value of the waveform."""
    pass