Getting started#
Installation#
The package is on PyPI, with wheels for Linux (glibc and musl, x86-64 and ARM), macOS (Intel and Apple silicon) and Windows, for CPython 3.11 and later; NumPy is its only dependency:
pip install comnum # or: pip install "comnum[plot]", with matplotlib
From a clone, comnum is built with maturin and a Rust
toolchain (1.85 or later):
git clone https://github.com/com-rs/comnum
cd comnum
python -m venv .venv && source .venv/bin/activate
pip install maturin numpy
maturin develop --release
The development dependencies are dependency groups of pyproject.toml (pip 25.1 or
later): pip install --group test for the tests (they read the recorded outputs of
the oracles), pip install --group lint for ruff, pip install --group docs for
this documentation. The package is typed (py.typed and a stub of the extension).
Conventions#
- Arrays
Signals are 1-D
complex128arrays (array-likes are converted), bits areuint8arrays of 0 and 1, symbol indicesint64arrays. Several modes (polarisations) are 2-D arrays(modes, samples).- Randomness
There is no global generator: every function that draws takes a
comnum.Rngand advances it, so a simulation is reproducible from its seed. The generator is the one of the Rust crates — the same seed gives the same draws in Rust and in Python — andcomnum.Rng.stream()derives the independent generator of every trial of a Monte Carlo campaign.- Units and names
Physical quantities are in SI units unless the name says otherwise:
ebn0_db,esn0_db,snr_db,power_dbm,length_km,alpha_db_km,d_ps_nm_km… \(E_b/N_0\) and \(E_s/N_0\) are always distinguished by name.fsis a sampling rate,fc_hza carrier frequency,noise_vara noise variance \(E|w|^2\); MIMO matrices are(n_rx, n_tx). The tuning parameters are keyword-only (comnum.pulse_shape("rrc", 4, rolloff=0.25)).- Closed forms
The
theory_*functions and the conversions take a scalar (and return a float) or an array-like (and return an array of the same shape):comnum.theory_ber(16, np.arange(0, 12)).- Errors
Invalid parameters raise
ValueError, numerical failuresArithmeticError.- Conventions of the blocks
Gray labels, pulse grids, metrics and fibre models follow OptiCommPy, which serves as the test oracle: a user of one finds the same blocks under the same names in the other.
A first link#
16-QAM over AWGN, decided symbol by symbol, against the closed-form bit error rate:
import comnum
rng = comnum.Rng(2024)
c = comnum.Constellation("qam", 16).normalized() # Gray labels, unit energy
bits = comnum.bits(4 * 200_000, rng) # 4 bits per symbol
x = c.map_bits(bits)
y = comnum.awgn_ebn0(x, 10.0, 4, rng) # Eb/N0 = 10 dB, 4 bits/symbol
print(comnum.ber(c.demap_bits(y), bits)) # 1.80e-3
print(comnum.theory_ber(16, 10.0, "qam")) # 1.75e-3
The gallery turns such snippets into the classical curves, and the user guide shows how to run them as Monte Carlo campaigns with stopping rules and confidence intervals.