Skip to main content
Ctrl+K

comnum

  • Getting started
  • Tutorials
  • User guide
  • Gallery of classical results
  • Why the results can be trusted
  • Maturity
    • Comparisons with other libraries
    • Why comnum
    • Benchmarks against other libraries
    • Classical performance
    • API reference
  • GitHub
  • Getting started
  • Tutorials
  • User guide
  • Gallery of classical results
  • Why the results can be trusted
  • Maturity
  • Comparisons with other libraries
  • Why comnum
  • Benchmarks against other libraries
  • Classical performance
  • API reference
  • GitHub

Section Navigation

  • Foundations
    • Constellations and Gray labels
    • Bit error rate of M-QAM over AWGN
    • M-PSK over AWGN with the Python runner
    • BPSK over flat Rayleigh fading
    • Information rates of QAM
  • Coding and shaping
    • Channel coding: from convolutional codes to the finite-length limit
    • Hu, Eleftheriou & Arnold 2005, Fig. 5: a regular PEG code of length 504
    • 5G NR channel codes: LDPC and polar
    • Probabilistic shaping: the rate gain and probabilistic amplitude shaping
  • Waveforms
    • PAPR of OFDM: the CCDF and its closed forms
    • PAPR reduction techniques
    • OFDM with impairments: imperfect channel estimates and nonlinear amplifiers
    • Proakis & Salehi 2008, Sec. 3.3-2: MSK has the error rate of BPSK
    • Thompson et al. 2008, Fig. 2: the CE-OFDM phase demodulator
    • CE-OFDM receivers, spectrum and bandwidth
    • The LoRa modulation: error rates, spectrum and interference
    • Filtered multicarrier and OTFS
  • MIMO
    • MIMO detection: linear, successive cancellation and maximum likelihood
    • Transmit diversity: Alamouti and space-time block codes
    • Alamouti 1998, Fig. 4: transmit diversity against MRRC
    • Ergodic capacity of MIMO channels
    • Large MIMO: message passing (LAMA and OAMP)
    • Biguesh & Gershman 2006, Fig. 4: LS, scaled LS, relaxed MMSE and LMMSE
  • Optical
    • Chromatic dispersion and its compensation
    • Nonlinear fibre propagation and digital back-propagation
    • Häger & Pfister 2021, Fig. 5: linear equalisation and back-propagation
    • WDM nonlinearity: the GN model and digital back-propagation
    • Raman amplification: pumps, gain flattening and the hybrid link
    • Mach–Zehnder and IQ modulators
    • Optical wireless: an LED-lit room and a turbulent free-space link
  • Hardware impairments
    • Power amplifiers and digital predistortion
    • DAC and ADC: quantisation, clipping and jitter
  • Receiver DSP
    • Nyquist pulse shaping and the eye diagram
    • OFDM over multipath: channel estimation
    • OFDM synchronisation and MIMO-OFDM
    • Blind receiver: modulation recognition, SNR and symbol rate
  • Metrics and analysis
    • Analysing a link: variants, probes and signals
  • Systems and standards
    • DVB-S2: MODCODs, constellations and frame error rates
    • 5G NR: numerology, synchronisation block and reference signals
    • DVB-S: the error rate after the Viterbi decoder against Table 3
    • DVB-T: the frame and the error rate after the Viterbi decoder against Annex A
    • CCSDS: the codes of telemetry against the normal approximation
    • 5G NR PDSCH: TS 38.101-4 test 1-2 against the RAN4 alignment
  • Simulation and specifications
    • A coherent receiver as a chain of blocks
    • Wireless links as chains: diversity, OFDM channel estimation, coded modulation
    • Recorded signals: SigMF in, blind receiver out
    • Coverage of the confidence intervals of an error rate
  • Gallery of classical results
  • Simulation and specifications
  • Wireless links as chains: diversity, OFDM channel estimation, coded modulation

Note

Go to the end to download the full example code.

Wireless links as chains: diversity, OFDM channel estimation, coded modulation#

Three wireless links written as comnum.Chain objects of native blocks and run on the parallel Rust runner.

Diversity. Alamouti’s code over 2 × 2 Rayleigh fading (Alamouti 1998) collects the diversity of the four antenna pairs: its BER is that of maximal-ratio combining of four branches, 3 dB below in SNR since the power is split between the antennas. Spatial multiplexing with zero forcing doubles the rate but keeps \(n_r - n_t + 1 = 1\) branch (Winters, Salz & Gitlin 1994). The chain is that of specs/mimo_diversity.yaml; the dotted lines are the closed forms (Proakis & Salehi, eq. 13.4-15).

OFDM. Over the EVA channel of 3GPP TS 36.101 with a Doppler of 70 Hz, every subcarrier of an OFDM link is a flat Rayleigh channel: with the channel known, the BER is that of BPSK over Rayleigh fading. Estimating it from lattice pilots costs a fraction of a dB, less with LMMSE interpolation (Edfors et al. 1998) than with linear interpolation.

Coded modulation. A regular (3, 6) LDPC code of 1024 bits with 16-QAM and a random bit interleaver (BICM, Caire, Taricco & Biglieri 1998): over AWGN its waterfall is about 1.5 dB from the BICM limit; over fast Rayleigh fading the interleaved code collects the time diversity, where the BER of the coded bits only falls as \(1/\mathrm{SNR}\).

import matplotlib.pyplot as plt
import numpy as np

# the BICM chain is shared with the test that checks these curves
from _gallery_utils import SPECS, bicm_chain

import comnum
from comnum import blocks as B
from comnum.plot import BACKGROUND, BLUE, GREY, RUST


def rate(results, metric, **condition):
    """The values of a rate metric against E_b/N_0, NaN below 20 errors."""
    return results.series("ebn0_db", metric, min_count=20, **condition)[1]

Diversity of two transmit antennas over 2 × 2 Rayleigh fading.

eb = np.arange(0.0, 17.0, 2.0)
link = comnum.Chain.from_spec(SPECS / "mimo_diversity.yaml")
res = link.run(
    grid={"scheme": ["alamouti", "spatial"], "ebn0_db": list(eb)},
    stop={"min_errors": {"ber": 200}, "min_trials": 4, "max_trials": 400},
)
fig, ax = plt.subplots()
fine = np.linspace(0, 16, 81)
for scheme, branches, marker, label in [
    ("alamouti", 4, "o", "Alamouti 2 × 2"),
    ("spatial", 1, "s", "spatial multiplexing, ZF 2 × 2"),
]:
    (line,) = ax.semilogy(
        eb, rate(res, "ber", scheme=scheme), marker=marker, markeredgecolor=BACKGROUND,
        linestyle="none", label=label,
    )  # fmt: skip
    ax.semilogy(
        fine,
        comnum.theory_ber_rayleigh_mrc(fine - comnum.lin2db(2), branches=branches),
        ":",
        color=line.get_color(),
    )
ax.semilogy(
    fine,
    comnum.theory_ber_rayleigh_mrc(fine, branches=1),
    color=GREY,
    linewidth=1.2,
    label="SISO Rayleigh",
)
ax.set(
    xlabel="$E_b/N_0$ (dB)", ylabel="bit error rate", ylim=(1e-6, 0.5), xlim=(0, 16),
    title="QPSK over i.i.d. Rayleigh fading",
)  # fmt: skip
ax.legend(loc="lower left")
fig.tight_layout()
QPSK over i.i.d. Rayleigh fading

OFDM over EVA: known channel, LMMSE and linear interpolation of the pilots.

eb = np.arange(0.0, 26.0, 5.0)
lattice = {"pattern": "lattice", "freq": 3, "time": 4}
ofdm = comnum.Chain(
    tx=B.Source(constellation="QPSK", n_symbols=2400),
    ofdm=B.OfdmTx(n_fft=256, n_subcarriers=200, n_cp=18, pilots=lattice),
    channel=B.Tdl(profile="EVA", doppler_hz=70),
    noise=B.AwgnEbn0(ebn0_db=comnum.var("ebn0_db")),
    rx=B.OfdmRx(estimation=comnum.var("estimation"), detector="zf"),
)
res = ofdm.run(
    grid={"estimation": ["perfect", "lmmse", "ls"], "ebn0_db": list(eb)},
    metrics={"report": ["ber"], "scale": "none"},
    stop={"min_trials": 300, "max_trials": 300},
)
fig, ax = plt.subplots()
for est, marker, label in [
    ("perfect", "o", "known channel"),
    ("lmmse", "s", "LMMSE estimation"),
    ("ls", "D", "LS, linear interpolation"),
]:
    ax.semilogy(
        eb, rate(res, "ber", estimation=est), marker=marker, markeredgecolor=BACKGROUND,
        label=label,
    )  # fmt: skip
ax.semilogy(fine := np.linspace(0, 25, 101), comnum.theory_ber_rayleigh_mrc(fine, branches=1), ":",
            color=GREY, label="Rayleigh, closed form")  # fmt: skip
ax.set(
    xlabel="$E_b/N_0$ (dB)", ylabel="bit error rate", xlim=(0, 25),
    title="QPSK OFDM over EVA, 70 Hz Doppler",
)  # fmt: skip
ax.legend(loc="lower left")
fig.tight_layout()
QPSK OFDM over EVA, 70 Hz Doppler

BICM: an LDPC code of 1024 bits with 16-QAM over AWGN and fast Rayleigh fading: FecEncode(code, blocks=4, interleave=True), Map("16-QAM"), with fading Rayleigh(coherence_samples=1), AwgnEbn0, with fading MimoRx, Demap and FecDecode (bicm_chain).

fig, ax = plt.subplots()
for fading, eb, color, name in [
    (False, np.arange(2.0, 5.6, 0.5), BLUE, "AWGN"),
    (True, np.arange(5.0, 10.6, 0.5), RUST, "fast Rayleigh"),
]:
    res = bicm_chain(fading).run(
        grid={"ebn0_db": list(eb)},
        metrics=["ber", "coded_ber"],
        stop={"min_errors": {"coded_ber": 200}, "min_trials": 4, "max_trials": 400},
    )
    ax.semilogy(eb, rate(res, "ber"), "--", color=color, label=f"coded bits, {name}")
    ax.semilogy(
        eb, rate(res, "coded_ber"), "o-", color=color, markeredgecolor=BACKGROUND,
        label=f"decoded bits, {name}",
    )  # fmt: skip
ax.set(
    xlabel="$E_b/N_0$ (dB)", ylabel="bit error rate", ylim=(1e-6, 0.5),
    title="LDPC (1024, 512) BICM with 16-QAM",
)  # fmt: skip
ax.legend(loc="lower left")
fig.tight_layout()
LDPC (1024, 512) BICM with 16-QAM

Total running time of the script: (0 minutes 22.046 seconds)

Download Jupyter notebook: plot_02_wireless_chains.ipynb

Download Python source code: plot_02_wireless_chains.py

Download zipped: plot_02_wireless_chains.zip

Gallery generated by Sphinx-Gallery

previous

A coherent receiver as a chain of blocks

next

Recorded signals: SigMF in, blind receiver out

Show Source

© Copyright 2022-2026, Vincent Choqueuse.

Created using Sphinx 9.1.1.

Built with the PyData Sphinx Theme 0.24.0.