Source code for qupulse.pulses.interpolation
"""This module defines strategies for interpolation between points in a pulse table or similar.
Classes:
- InterpolationStrategy: Interface for interpolation strategies.
- LinearInterpolationStrategy: Interpolates linearly between two points.
- HoldInterpolationStrategy: Interpolates by holding the first point's value.
- JumpInterpolationStrategy: Interpolates by holding the second point's value.
"""
from abc import ABCMeta, abstractmethod
from typing import Any, Tuple
import numpy as np
from qupulse.expressions import ExpressionScalar
__all__ = ["InterpolationStrategy", "HoldInterpolationStrategy",
"JumpInterpolationStrategy", "LinearInterpolationStrategy"]
[docs]class InterpolationStrategy(metaclass=ABCMeta):
"""Defines a strategy to interpolate values between two points."""
@abstractmethod
def __call__(self,
start: Tuple[float, float],
end: Tuple[float, float],
times: np.ndarray) -> np.ndarray:
"""Return a sequence of voltage values for the time slot between the start and the
end point (given as (time, value) pairs) according to the interpolation strategy.
Args:
start ((float, float)): The start point of the interpolation as (time, value) pair.
end ((float, float)): The end point of the interpolation as (time, value) pair.
times (numpy.ndarray): An array of sample times for which values will be computed. All
values in this array must lie within the boundaries defined by start and end.
Returns:
A numpy.ndarray containing the interpolated values.
"""
@property
@abstractmethod
def integral(self) -> ExpressionScalar:
"""Returns the symbolic integral of this interpolation strategy using (v0,t0) and (v1,t1)
to represent start and end point."""
@property
@abstractmethod
def expression(self) -> ExpressionScalar:
"""Returns a symbolic expression of the interpolation strategy using (v0,t0) and (v1, t1)
to represent start and end point and t as free variable. Note that the expression is only valid for values of t
between t0 and t1."""
@abstractmethod
def __repr__(self) -> str:
"""String representation of the Interpolation Strategy Class"""
def __eq__(self, other: Any) -> bool:
# Interpolations are the same, if their type is the same
return type(self) == type(other)
def __ne__(self, other: Any) -> bool:
return not self.__eq__(other)
def __hash__(self) -> int:
return hash(self.__repr__())
[docs]class LinearInterpolationStrategy(InterpolationStrategy):
"""An InterpolationStrategy that interpolates linearly between two points."""
def __call__(self,
start: Tuple[float, float],
end: Tuple[float, float],
times: np.ndarray) -> np.ndarray:
m = (end[1] - start[1])/(end[0] - start[0])
return m * (times - start[0]) + start[1]
@property
def integral(self) -> ExpressionScalar:
return ExpressionScalar('(t1-t0) * (v0 + v1) / 2')
@property
def expression(self) -> ExpressionScalar:
return ExpressionScalar('v0 + (v1-v0) * (t-t0)/(t1-t0)')
def __str__(self) -> str:
return 'linear'
def __repr__(self) -> str:
return "<Linear Interpolation>"
[docs]class HoldInterpolationStrategy(InterpolationStrategy):
"""An InterpolationStrategy that interpolates by holding the value of the start point for the
entire intermediate space."""
def __call__(self,
start: Tuple[float, float],
end: Tuple[float, float],
times: np.ndarray) -> np.ndarray:
if np.any(times < start[0]) or np.any(times > end[0]):
raise ValueError(
"Time Value for interpolation out of bounds. Must be between {0} and {1}.".format(
start[0], end[0]
)
)
return np.full_like(times, fill_value=start[1], dtype=float)
@property
def integral(self) -> ExpressionScalar:
return ExpressionScalar('v0*(t1-t0)')
@property
def expression(self) -> ExpressionScalar:
return ExpressionScalar('v0')
def __str__(self) -> str:
return 'hold'
def __repr__(self) -> str:
return "<Hold Interpolation>"
[docs]class JumpInterpolationStrategy(InterpolationStrategy):
"""An InterpolationStrategy that interpolates by holding the value of the end point for the
entire intermediate space."""
def __call__(self,
start: Tuple[float, float],
end: Tuple[float, float],
times: np.ndarray) -> np.ndarray:
if np.any(times < start[0]) or np.any(times > end[0]):
raise ValueError(
"Time Value for interpolation out of bounds. Must be between {0} and {1}.".format(
start[0], end[0]
)
)
return np.full_like(times, fill_value=end[1], dtype=float)
@property
def integral(self) -> ExpressionScalar:
return ExpressionScalar('v1*(t1-t0)')
@property
def expression(self) -> ExpressionScalar:
return ExpressionScalar('v1')
def __str__(self) -> str:
return 'jump'
def __repr__(self) -> str:
return "<Jump Interpolation>"