chaotic_pfc.comms.channel

channel.py

Transmission-channel models sitting between the chaotic transmitter and the receiver.

Six channels are provided:

All accept the transmitted signal s as a 1-D array and return the received signal r of the same length. The FIR channel additionally returns its filter coefficients so they can be overlaid on the PSD plots produced by chaotic_pfc.plotting.

Functions

awgn(sig, snr_db[, rng])

Add white Gaussian noise to sig for a given SNR in dB.

channel_impulsive(sig, snr_db[, ...])

AWGN channel with Middleton Class-A impulsive noise.

channel_multipath(sig, snr_db[, delays, ...])

Multipath channel with configurable tap delays and gains.

fir_channel(s[, cutoff, num_taps, window])

Transmit s through a symmetric FIR low-pass channel.

ideal_channel(s)

Transmit s through a noiseless, distortion-free channel.

chaotic_pfc.comms.channel.ideal_channel(s)[source]

Transmit s through a noiseless, distortion-free channel.

This is literally a copy of the input. It is still defined as a function (rather than aliased to numpy.ndarray.copy) so that the receiver-side code can always call ideal_channel(s) consistently regardless of the channel configuration chosen by the caller.

Parameters:

s (ndarray[tuple[Any, ...], dtype[_ScalarT]]) – Transmitted signal, shape (N,).

Returns:

  • ndarray, shape (N,) – An independent copy of s. Mutating the output does not affect the input.

  • Implements (Channel.)

Return type:

ndarray[tuple[Any, …], dtype[_ScalarT]]

chaotic_pfc.comms.channel.fir_channel(s, cutoff=0.99, num_taps=201, window='hamming')[source]

Transmit s through a symmetric FIR low-pass channel.

The channel is built with scipy.signal.firwin() using pass_zero=True (true low-pass) and unit sampling frequency normalisation (fs=2.0). The DC gain of the resulting filter is normalised to 1.0.

Parameters:
  • s (ndarray[tuple[Any, ...], dtype[_ScalarT]]) – Transmitted signal, shape (N,).

  • cutoff (float) – Normalised cutoff frequency ω_c / π (0, 1). Defaults to 0.99 — i.e. the channel passes almost everything, mimicking a very lightly band-limited link.

  • num_taps (int) – Length of the FIR filter in samples. Must be a positive integer.

  • window (str) – Window function passed through to firwin. Any name accepted by scipy.signal.get_window() is valid — common choices are "hamming", "hann", "blackman".

Returns:

  • r (ndarray, shape (N,)) – Received signal, s filtered through the FIR coefficients.

  • h (ndarray, shape (num_taps,)) – Filter coefficients, useful for overlaying the channel response on PSD plots.

Return type:

tuple[ndarray[tuple[Any, …], dtype[_ScalarT]], ndarray[tuple[Any, …], dtype[_ScalarT]]]

Notes

Unlike ideal_channel(), this function returns the filter taps alongside the filtered signal. It therefore does not satisfy Channel (which expects a single NDArray return).

chaotic_pfc.comms.channel.awgn(sig, snr_db, rng=None)[source]

Add white Gaussian noise to sig for a given SNR in dB.

The noise power is E[|sig|²] / 10^(SNR/10), so a higher SNR means less noise.

Parameters:
  • sig (ndarray[tuple[Any, ...], dtype[_ScalarT]]) – Signal samples, shape (N,).

  • snr_db (float) – Signal-to-noise ratio in dB. snr_db gives the original signal; snr_db = 0 gives equal-power noise.

  • rng (Generator | None) – NumPy Generator. None (default) creates a fresh default_rng() with no fixed seed, so results are not reproducible across calls. Pass a seeded generator for deterministic noise.

Returns:

Signal with additive white Gaussian noise.

Return type:

ndarray, shape (N,)

Notes

The SNR is defined as \(E[|s|^2] / 10^{SNR/10}\) [Haykin01].

References

[Haykin01]
  1. Haykin. “Communication Systems.” 4th ed., Wiley, 2001.

chaotic_pfc.comms.channel.channel_impulsive(sig, snr_db, prob_impulse=0.01, amp_factor=10.0, rng=None)[source]

AWGN channel with Middleton Class-A impulsive noise.

A fraction prob_impulse of samples receive an additional impulse of randomised sign and amplitude amp_factor × std(sig) on top of the AWGN background.

Parameters:
  • sig (ndarray[tuple[Any, ...], dtype[_ScalarT]]) – Signal samples, shape (N,).

  • snr_db (float) – Background AWGN signal-to-noise ratio in dB.

  • prob_impulse (float) – Probability a sample is hit by an impulse (e.g. 0.01 = 1 %).

  • amp_factor (float) – Impulse amplitude in multiples of the signal std.

  • rng (Generator | None) – Random generator. None creates a fresh default_rng().

Returns:

Signal with AWGN + Middleton Class-A impulsive noise.

Return type:

ndarray, shape (N,)

chaotic_pfc.comms.channel.channel_multipath(sig, snr_db, delays=None, gains=None, rng=None)[source]

Multipath channel with configurable tap delays and gains.

Simulates a frequency-selective channel by summing delayed copies of the input. Output power is normalised to the input power, then AWGN is added at the requested SNR.

Parameters:
  • sig (ndarray[tuple[Any, ...], dtype[_ScalarT]]) – Signal samples, shape (N,).

  • snr_db (float) – AWGN signal-to-noise ratio after multipath combining, in dB.

  • delays (list[int] | None) – Delay of each path in samples (default: [0, 3, 7, 15]).

  • gains (list[float] | None) – Attenuation per path (default: [1.0, 0.6, 0.4, 0.2]).

  • rng (Generator | None) – Random generator. None creates a fresh default_rng().

Returns:

Multipath-combined signal with AWGN.

Return type:

ndarray, shape (N,)