Skip to content

qiu_signals.algebraic_signal

Signals given by an algebraic expression evaluated on a physical axis.

Classes:

  • AlgebraicSignal –

    A signal given by an algebraic expression of the axis values.

  • PolynomialSignal –

    A monomial signal of the form f(x) = alpha * x^power.

  • QuadraticSignal –

    A quadratic signal of the form f(x) = alpha * x^2. Also called an intensity signal.

Attributes:

  • SignalFunctionType –

    A vectorized function, mapping an array of axis values to the signal values.

  • SampledSignal –

    A signal with sampled values on its axis, given directly or by an expression.

SignalFunctionType module-attribute

SignalFunctionType = Callable[[npt.NDArray[Any]], npt.ArrayLike]

A vectorized function, mapping an array of axis values to the signal values.

It is called once with all values as an array, e.g. axis.values, so it must act elementwise on arrays, e.g. with NumPy functions. The dtype of the array is not fixed, so that functions annotated for a specific dtype are accepted. It may return a scalar for constant signals, which is broadcast to the axis values.

SampledSignal module-attribute

SampledSignal = Signal | AlgebraicSignal

A signal with sampled values on its axis, given directly or by an expression.

Both kinds provide the axis and the sampled values data.

AlgebraicSignal

AlgebraicSignal(axis: PhysicalAxis, function: SignalFunctionType)

Bases: ArithmeticOperators

A signal given by an algebraic expression of the axis values.

The expression is held as a vectorized function, mapping an array of axis values to the array of signal values. It is either given directly, e.g. as a lambda or a NumPy function, or compiled from a SymPy expression with from_sympy, which also keeps the symbolic expression.

Algebraic signals support the arithmetic operators +, -, *, / and ** with scalars and with algebraic signals on an equal axis, composing their functions, and their SymPy expressions if both operands have one. Combined with a sampled Signal, they are sampled first, and the result is a sampled Signal.

Parameters:

  • axis (PhysicalAxis) –

    The axis the signal is evaluated on.

  • function (SignalFunctionType) –

    A function mapping an array of axis values to the array of signal values, e.g. lambda x: np.exp(-(x**2)).

Methods:

  • from_sympy –

    Create a signal from a SymPy expression in one symbol.

  • to_signal –

    Return the signal sampled on its axis.

Attributes:

  • axis (PhysicalAxis) –

    The axis the signal is evaluated on.

  • function (SignalFunctionType) –

    The vectorized function mapping axis values to signal values.

  • expression (Expr | None) –

    The SymPy expression of the signal, if it was created from one.

  • symbol (Symbol | None) –

    The SymPy symbol standing for the axis values, if created from an expression.

  • data (NDArray[number]) –

    Return the signal evaluated on the axis values.

  • size (int) –

    Return the number of samples of the signal on its axis.

Source code in packages/qiu-signals/src/qiu_signals/algebraic_signal.py
59
60
61
62
63
64
65
66
67
68
69
70
def __init__(self, axis: PhysicalAxis, function: SignalFunctionType) -> None:
    """Initialize the signal from a vectorized function.

    Args:
        axis: The axis the signal is evaluated on.
        function: A function mapping an array of axis values to the array of
            signal values, e.g. `lambda x: np.exp(-(x**2))`.
    """
    self.axis = axis
    self.function = function
    self.expression = None
    self.symbol = None

axis instance-attribute

axis: PhysicalAxis = axis

The axis the signal is evaluated on.

function instance-attribute

function: SignalFunctionType = function

The vectorized function mapping axis values to signal values.

expression instance-attribute

expression: Expr | None = None

The SymPy expression of the signal, if it was created from one.

symbol instance-attribute

symbol: Symbol | None = None

The SymPy symbol standing for the axis values, if created from an expression.

data cached property

data: NDArray[number]

Return the signal evaluated on the axis values.

size property

size: int

Return the number of samples of the signal on its axis.

from_sympy classmethod

from_sympy(axis: PhysicalAxis, expression: Expr | str, symbol: Symbol | None = None) -> AlgebraicSignal

Create a signal from a SymPy expression in one symbol.

Requires SymPy, e.g. via the sympy extra of this package.

Parameters:

  • axis (PhysicalAxis) –

    The axis the signal is evaluated on.

  • expression (Expr | str) –

    The expression of the signal, or a string SymPy can parse.

  • symbol (Symbol | None, default: None ) –

    The symbol standing for the axis values. Can be omitted if the expression has at most one free symbol.

Returns:

Raises:

  • ImportError –

    If SymPy is not installed.

  • TypeError –

    If the expression is not an algebraic SymPy expression.

  • ValueError –

    If the expression has free symbols other than symbol, or, with symbol omitted, more than one free symbol or a free symbol that is not a plain SymPy symbol.

Source code in packages/qiu-signals/src/qiu_signals/algebraic_signal.py
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
@classmethod
def from_sympy(
    cls,
    axis: PhysicalAxis,
    expression: sympy.Expr | str,
    symbol: sympy.Symbol | None = None,
) -> AlgebraicSignal:
    """Create a signal from a SymPy expression in one symbol.

    Requires SymPy, e.g. via the `sympy` extra of this package.

    Args:
        axis: The axis the signal is evaluated on.
        expression: The expression of the signal, or a string SymPy can parse.
        symbol: The symbol standing for the axis values. Can be omitted if the
            expression has at most one free symbol.

    Returns:
        The signal, evaluating the expression with NumPy.

    Raises:
        ImportError: If SymPy is not installed.
        TypeError: If the expression is not an algebraic SymPy expression.
        ValueError: If the expression has free symbols other than `symbol`, or,
            with `symbol` omitted, more than one free symbol or a free symbol
            that is not a plain SymPy symbol.
    """
    try:
        import sympy
    except ImportError as error:
        raise ImportError(
            "AlgebraicSignal.from_sympy requires SymPy, e.g. install "
            "qiu-signals[sympy]."
        ) from error

    parsed = sympy.sympify(expression)
    if not isinstance(parsed, sympy.Expr):
        raise TypeError(
            f"Expected an algebraic expression, got {parsed} of type "
            f"{type(parsed).__name__}."
        )
    free_symbols = parsed.free_symbols

    if symbol is not None:
        if free_symbols - {symbol}:
            raise ValueError(
                f"The expression {parsed} has free symbols other than {symbol}: "
                f"{sorted(map(str, free_symbols - {symbol}))}."
            )
        axis_symbol = symbol
    elif not free_symbols:
        axis_symbol = sympy.Symbol("x")
    elif len(free_symbols) > 1:
        raise ValueError(
            f"The expression {parsed} has the free symbols "
            f"{sorted(map(str, free_symbols))}; give the one standing for "
            "the axis values as `symbol`."
        )
    else:
        (free_symbol,) = free_symbols
        if not isinstance(free_symbol, sympy.Symbol):
            raise ValueError(
                f"The free symbol {free_symbol} of the expression {parsed} is "
                "not a plain symbol; give the symbol of the axis values."
            )
        axis_symbol = free_symbol

    signal = cls(axis, sympy.lambdify(axis_symbol, parsed, modules="numpy"))
    signal.expression = parsed
    signal.symbol = axis_symbol
    return signal

to_signal

to_signal() -> Signal

Return the signal sampled on its axis.

Source code in packages/qiu-signals/src/qiu_signals/algebraic_signal.py
171
172
173
def to_signal(self) -> Signal:
    """Return the signal sampled on its axis."""
    return Signal(axis=self.axis, data=self.data)

PolynomialSignal

PolynomialSignal(axis: PhysicalAxis, alpha: float, power: int)

Bases: AlgebraicSignal

A monomial signal of the form f(x) = alpha * x^power.

Attributes:

  • alpha (float) –

    The coefficient of the monomial.

  • power (int) –

    The power of the monomial.

  • effective_alpha (float) –

    Return the coefficient of the monomial in terms of the integer indices.

Source code in packages/qiu-signals/src/qiu_signals/algebraic_signal.py
237
238
239
240
241
def __init__(self, axis: PhysicalAxis, alpha: float, power: int) -> None:
    """Initialize the polynomial signal."""
    super().__init__(axis=axis, function=lambda x: alpha * x**power)
    self.alpha = alpha
    self.power = power

alpha instance-attribute

alpha: float = alpha

The coefficient of the monomial.

power instance-attribute

power: int = power

The power of the monomial.

effective_alpha property

effective_alpha: float

Return the coefficient of the monomial in terms of the integer indices.

Such that the sampled signal is effective_alpha * axis.index**power.

QuadraticSignal

QuadraticSignal(axis: PhysicalAxis, alpha: float)

Bases: PolynomialSignal

A quadratic signal of the form f(x) = alpha * x^2. Also called an intensity signal.

Source code in packages/qiu-signals/src/qiu_signals/algebraic_signal.py
268
269
270
def __init__(self, axis: PhysicalAxis, alpha: float) -> None:
    """Initialize the quadratic signal."""
    super().__init__(axis=axis, alpha=alpha, power=2)