Python Signals
Uniformly sampled axes and signals on them, for any kind of numerical application, classical or quantum. It depends on NumPy and qiu-python-encore, and optionally on SymPy.
The quantum packages of this monorepo, e.g. qiu-quantum-computing, encode these signals in the basis states of qubit registers, and qiu-classical-simulation builds its optical elements on them.
Installation
pip install qiu-signals
Concepts
Axes
Axes come in two layers, each in its own module together with the enum it uses:
-
integer_axis.IntegerAxis(size, ordering)is a set ofsizeuniformly spaced samples labeled by integer indices. The sample at array positionkhas the indexindex[k], fixed by the axisordering(integer_axis.IndexOrdering). -
physical_axis.PhysicalAxis(size, period, ordering, domain)is anIntegerAxisplaced in a physical domain, with a spacingperiodbetween neighboring samples. The sample at array positionklies atvalues[k] = index[k] * period
The orderings of the integer indices are:
| ordering | indices for size = 4 |
indices for size = 5 |
equivalent to |
|---|---|---|---|
NATURAL |
0, 1, 2, 3 |
0, 1, 2, 3, 4 |
numpy.arange(size) |
FFT |
0, 1, -2, -1 |
0, 1, 2, -2, -1 |
numpy.fft.fftfreq(size) * size |
CENTERED |
-2, -1, 0, 1 |
-2, -1, 0, 1, 2 |
numpy.fft.fftshift of the FFT ones |
The FFT ordering is the one in which numpy.fft returns the transform of a signal, so a Fourier conjugate axis defaults to it.
The domain (physical_axis.AxisDomain) of a physical axis is POSITION, or one of its Fourier conjugates MOMENTUM, ANGULAR_WAVENUMBER and SPATIAL_FREQUENCY. The concrete physical axis classes in physical_axis fix the domain:
PositionAxis(size, delta_x, ordering)samples positions spaced bydelta_x.MomentumAxis(size, delta_p, ordering),AngularWavenumberAxis(size, delta_k, ordering)andSpatialFrequencyAxis(size, delta_f, ordering)sample the Fourier conjugate domains with the given spacing.- Their
from_position_axisconstructors create the axis conjugate to a position axis ofsizesamples spaced bydelta_x, with the spacing of the discrete Fourier transform:2 pi hbar / (size delta_x),2 pi / (size delta_x)and1 / (size delta_x)respectively (seereciprocal_period).MomentumAxis.from_position_axis(position_axis, hbar)has no default forhbar, so the units are always explicit, e.g.scipy.constants.hbarfor SI or1.0for natural units.
Signals
A signal lives on a PhysicalAxis, and comes in two forms:
signal.Signal(axis, data)is given by its sampled values:data[k]is the value ataxis.values[k], real or complex.normalized_dataholds the values scaled to unit Euclidean norm.algebraic_signal.AlgebraicSignal(axis, function)is given by an algebraic expression of the axis values, held as a vectorized function such as a lambda or a NumPy function.dataevaluates it on the axis values, calling the signal evaluates it at arbitrary values, andto_signal()returns the sampledSignal.AlgebraicSignal.from_sympy(axis, expression, symbol=None)creates it from a SymPy expression (or a string SymPy parses), keeping the symbolicexpressionand itssymbolfor inspection. It needs the optionalsympyextra,qiu-signals[sympy].PolynomialSignal(axis, alpha, power)is the algebraic signalalpha * x**power. Itseffective_alphais the coefficient in terms of the integer indices, so thatdata == effective_alpha * axis.index**power.QuadraticSignal(axis, alpha)is the polynomial signal of power 2, also called an intensity signal.
algebraic_signal.SampledSignalis the typeSignal | AlgebraicSignal, for code that only needs theaxisand the sampled valuesdataof either kind.
The SignalFunctionType aliases for the functions of algebraic signals live in algebraic_signal as well.
Arithmetic
Signals support +, -, *, /, ** and negation, elementwise, with scalars (from either side) and with signals on an equal axis (axes compare by value). Raw NumPy arrays are rejected rather than silently broadcast.
| operands | result |
|---|---|
Signal and scalar or Signal |
a Signal of the combined samples |
AlgebraicSignal and scalar or AlgebraicSignal |
an AlgebraicSignal of the composed functions, and of the composed SymPy expressions if both operands have one |
AlgebraicSignal and Signal |
a Signal, sampling the algebraic operand first |
PolynomialSignal * or / scalar |
a PolynomialSignal (or QuadraticSignal) with the scaled alpha, so effective_alpha stays available |
Usage
import numpy as np
import sympy
from qiu_signals.algebraic_signal import AlgebraicSignal, QuadraticSignal
from qiu_signals.integer_axis import IndexOrdering
from qiu_signals.physical_axis import PositionAxis, SpatialFrequencyAxis
from qiu_signals.signal import Signal
x_axis = PositionAxis(size=256, delta_x=0.1, ordering=IndexOrdering.FFT)
# an algebraic signal, from a lambda or from a symbolic expression
gaussian = AlgebraicSignal(x_axis, lambda x: np.exp(-(x**2)))
x = sympy.Symbol("x")
symbolic = AlgebraicSignal.from_sympy(x_axis, sympy.exp(-(x**2)))
assert np.allclose(gaussian.data, symbolic.data)
assert sympy.diff(symbolic.expression, x) == -2 * x * sympy.exp(-(x**2))
# the spectrum is a sampled signal on the conjugate axis, in the same ordering
f_axis = SpatialFrequencyAxis.from_position_axis(x_axis)
spectrum = Signal(f_axis, np.fft.fft(gaussian.data))
assert np.allclose(f_axis.values, np.fft.fftfreq(256, d=0.1))
# a quadratic phase profile, and its coefficient in terms of the integer indices
lens = QuadraticSignal(x_axis, alpha=-0.5)
assert np.allclose(lens.data, lens.effective_alpha * x_axis.index**2)
# arithmetic: scaled monomials stay monomials, other combinations are algebraic
phase = -0.1 * lens
assert isinstance(phase, QuadraticSignal)
beam = 2 * gaussian + symbolic
assert beam.expression is None and np.allclose(beam.data, 3 * gaussian.data)
assert (2 * symbolic + 1).expression == 2 * sympy.exp(-(x**2)) + 1
Documentation
The documentation, with the API reference from the docstrings, is built from docs/ with MkDocs and published at https://blackwild.github.io/qiu/qiu-signals/. To serve it locally, from the repository root:
uv run mkdocs serve -f packages/qiu-signals/mkdocs.yml
Tests
From the repository root:
uv run pytest packages/qiu-signals
Release files for qiu-signals 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| qiu_signals-0.1.0.tar.gz | 11.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| qiu_signals-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 27.1 kB
Release files / qiu_signals-0.1.0.tar.gz
| Download URL | qiu_signals-0.1.0.tar.gz |
|---|---|
| Size | 11.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f2d58a0a99e7e4f0ae0e9c09dfbc71ba8bae65cf515be61c57bb2cf9083b3c99
|
|
BLAKE2b-256 checksum How to use checksums |
b851d1221a1f00564294c7e703606df2f3ebc8943271def8715344e0c1925607
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / qiu_signals-0.1.0-py3-none-any.whl
| Download URL | qiu_signals-0.1.0-py3-none-any.whl |
|---|---|
| Size | 15.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
23840b9badcce4fc3f5d0420a03a35c7171b6fb73df83f7b4fbbcf522d768d6f
|
|
BLAKE2b-256 checksum How to use checksums |
264a8d7e95ac04cfa746536fec4db4d23d5432c82d17c7fe244d62cc518efada
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|