Channels#

class AWGN(*, snr_dB: float | None = None, sigma2: float | None = None, seed: int | None = None, name: str = 'awgn')[source]#

Additive white Gaussian noise channel.

Signal Model#

\[y[n] = x[n] + b[n], \qquad b[n] \sim \mathcal{CN}\left(0, \sigma^2\right)\]

When parameterized by snr_dB, the variance is derived from the measured input power \(P_x = \mathbb{E}\left[|x[n]|^2\right]\):

\[\sigma^2 = P_x \, 10^{-\mathrm{SNR_{dB}}/10}\]

For real-valued inputs, a real Gaussian noise of variance \(\sigma^2\) is applied instead of a circular complex one.

Axes: element-wise – applied pointwise, shape-agnostic. One caveat under a batch (D51): with snr_dB= the signal power is measured over the whole input, batch rows included, so rows of unequal power share one variance rather than each receiving the requested SNR; sigma2= is batch-neutral.

param snr_dB:

Signal-to-noise ratio \(\mathrm{SNR_{dB}}\) in decibels, relative to the measured input power. Mutually exclusive with sigma2.

type snr_dB:

float, keyword-only

param sigma2:

Absolute noise variance \(\sigma^2\). Mutually exclusive with snr_dB.

type sigma2:

float, keyword-only

param seed:

Local RNG seed.

type seed:

int, optional, keyword-only

param name:

Name of the channel instance. Default is "awgn".

type name:

str, optional, keyword-only

sigma2_#

Variance actually applied. Estimated from the input power when parameterized by snr_dB (data-dependent, hence the trailing underscore); equal to sigma2 otherwise.

Type:

float

References

J. G. Proakis, M. Salehi, Digital Communications, 5th ed., McGraw-Hill, 2008, Section 4.2.

Examples

>>> x = np.zeros(10_000, dtype=complex)
>>> y = AWGN(sigma2=0.01, seed=42)(x)
>>> print(round(float(np.var(y)), 3))
0.01
class FlatMIMOChannel(H: ndarray | None = None, *, extend: bool = True, name: str = 'mimo_channel')[source]#

Flat (frequency-non-selective) MIMO channel.

Signal Model#

\[\mathbf{y}[n] = \mathbf{H} \, \mathbf{x}[n] + \mathbf{b}[n]\]

where \(\mathbf{H}\) is the channel matrix of size \(N_r \times N_t\), \(\mathbf{x}[n]\) the \(N_t \times 1\) transmitted vector and \(\mathbf{b}[n]\) the additive noise, contributed by chaining a separate element-wise AWGN block (this class applies only the noiseless product).

Axes: declared axis – expects (..., ant, N) with antennas on axis -2, validated against \(N_t\). H may be a stack of channels (K, N_r, N_t): against X of shape (K, N_t, N) channel \(k\) is applied to frame \(k\) – one independent draw per trial, the batch contract of D51 for a channel whose realization is configured rather than drawn per call.

param H:

Channel matrix \(\mathbf{H}\) of shape (N_r, N_t).

type H:

np.ndarray, optional

param extend:

Unused for a flat channel (inherited). Default is True.

type extend:

bool, keyword-only

param name:

Name of the processor. Default is "mimo_channel".

type name:

str, optional, keyword-only

raises ShapeError:

If the antenna axis of the input does not match \(N_t\).

References

D. Tse and P. Viswanath, Fundamentals of Wireless Communication, Cambridge University Press, 2005, Chapter 7.

Examples

>>> H = np.array([[1.0, 0.0], [0.0, 2.0]])
>>> x = np.array([[1.0, 1.0], [1.0, -1.0]])
>>> FlatMIMOChannel(H)(x)
array([[ 1.,  1.],
       [ 2., -2.]])
class SelectiveMIMOChannel(H: ndarray | None = None, *, extend: bool = True, name: str = 'mimo_channel')[source]#

Frequency-selective (multi-tap) MIMO channel.

Signal Model#

\[\mathbf{y}[n] = \sum_{l=0}^{L-1} \mathbf{H}[l] \, \mathbf{x}[n-l] + \mathbf{b}[n]\]

where \(\mathbf{H}[l]\) is the channel matrix of size \(N_r \times N_t\) of the \(l\)-th of \(L\) taps, \(\mathbf{x}[n]\) the \(N_t \times 1\) transmitted vector and \(\mathbf{b}[n]\) the additive noise, contributed by chaining a separate element-wise AWGN block (this class applies only the noiseless convolution).

Axes: declared axis – expects (ant, N) with antennas on axis -2, validated against \(N_t\).

param H:

Stacked channel matrices \(\mathbf{H}[l]\) of shape (L, N_r, N_t).

type H:

np.ndarray, optional

param extend:

If True, the output holds the full convolution (N + L - 1 samples); if False, it is truncated to N samples. Default is True.

type extend:

bool, keyword-only

param name:

Name of the processor. Default is "mimo_channel".

type name:

str, optional, keyword-only

raises ShapeError:

If the antenna axis of the input does not match \(N_t\).

References

D. Tse and P. Viswanath, Fundamentals of Wireless Communication, Cambridge University Press, 2005, Chapter 7.

Examples

>>> H = np.array([[[1.0]], [[0.5]]])
>>> x = np.array([[1.0, 0.0, 0.0]])
>>> SelectiveMIMOChannel(H)(x)
array([[1. +0.j, 0.5+0.j, 0. +0.j, 0. +0.j]])