komm.Modulation
General modulation scheme. A modulation scheme of order $M = 2^m$ is defined by a constellation $\mathbf{X}$, which is a real or complex vector of length $M$, and a binary labeling $\mathbf{Q}$, which is an $M \times m$ binary matrix whose rows are all distinct. The $i$-th element of $\mathbf{X}$, for $i \in [0:M)$, is denoted by $x_i$ and is called the $i$-th constellation symbol. The $i$-th row of $\mathbf{Q}$, for $i \in [0:M)$, is called the binary representation of the $i$-th constellation symbol.
For more details, see SA15, Sec. 2.5.
__init__
Constructor for the class.
Parameters:
-
constellation
(Array1D[float] | Array1D[complex]
) –The constellation $\mathbf{X}$ of the modulation. Must be a 1D-array containing $M$ real or complex numbers.
-
labeling
(Array2D[int]
) –The binary labeling $\mathbf{Q}$ of the modulation. Must be a 2D-array of shape $(M, m)$ where each row is a distinct binary $m$-tuple.
Examples:
The real modulation scheme depicted in the figure below has $M = 4$ and $m = 2$.
The constellation is given by $$ \mathbf{X} = \begin{bmatrix} -0.5 \\ 0.0 \\ 0.5 \\ 2.0 \end{bmatrix}, $$ and the binary labeling is given by $$ \mathbf{Q} = \begin{bmatrix} 1 & 0 \\ 1 & 1 \\ 0 & 1 \\ 0 & 0 \end{bmatrix}. $$
>>> komm.Modulation(constellation=[-0.5, 0.0, 0.5, 2.0], labeling=[[1, 0], [1, 1], [0, 1], [0, 0]])
Modulation(constellation=[-0.5, 0.0, 0.5, 2.0], labeling=[[1, 0], [1, 1], [0, 1], [0, 0]])
The complex modulation scheme depicted in the figure below has $M = 4$ and $m = 2$.
The constellation is given by $$ \mathbf{X} = \begin{bmatrix} 0 \\ -1 \\ 1 \\ \mathrm{j} \end{bmatrix}, $$ and the binary labeling is given by $$ \mathbf{Q} = \begin{bmatrix} 0 & 0 \\ 0 & 1 \\ 1 & 0 \\ 1 & 1 \end{bmatrix}. $$
>>> komm.Modulation(constellation=[0, -1, 1, 1j], labeling=[[0, 0], [0, 1], [1, 0], [1, 1]])
Modulation(constellation=[0j, (-1+0j), (1+0j), 1j], labeling=[[0, 0], [0, 1], [1, 0], [1, 1]])
constellation
property
The constellation $\mathbf{X}$ of the modulation.
Examples:
>>> mod = komm.Modulation(constellation=[-0.5, 0.0, 0.5, 2.0], labeling=[[1, 0], [1, 1], [0, 1], [0, 0]])
>>> mod.constellation
array([-0.5, 0. , 0.5, 2. ])
labeling
property
The binary labeling $\mathbf{Q}$ of the modulation.
Examples:
>>> mod = komm.Modulation(constellation=[-0.5, 0.0, 0.5, 2.0], labeling=[[1, 0], [1, 1], [0, 1], [0, 0]])
>>> mod.labeling
array([[1, 0],
[1, 1],
[0, 1],
[0, 0]])
order
property
The order $M$ of the modulation.
Examples:
>>> mod = komm.Modulation(constellation=[-0.5, 0.0, 0.5, 2.0], labeling=[[1, 0], [1, 1], [0, 1], [0, 0]])
>>> mod.order
4
bits_per_symbol
property
The number $m$ of bits per symbol of the modulation. It is given by $m = \log_2 M$, where $M$ is the order of the modulation.
Examples:
>>> mod = komm.Modulation(constellation=[-0.5, 0.0, 0.5, 2.0], labeling=[[1, 0], [1, 1], [0, 1], [0, 0]])
>>> mod.bits_per_symbol
2
energy_per_symbol
property
The average symbol energy $E_\mathrm{s}$ of the constellation. It assumes equiprobable symbols. It is given by $$ E_\mathrm{s} = \frac{1}{M} \sum_{i \in [0:M)} |x_i|^2, $$ where $|x_i|^2$ is the energy of constellation symbol $x_i$, and $M$ is the order of the modulation.
Examples:
>>> mod = komm.Modulation(constellation=[-0.5, 0.0, 0.5, 2.0], labeling=[[1, 0], [1, 1], [0, 1], [0, 0]])
>>> mod.energy_per_symbol
np.float64(1.125)
>>> mod = komm.Modulation(constellation=[0, -1, 1, 1j], labeling=[[0, 0], [0, 1], [1, 0], [1, 1]])
>>> mod.energy_per_symbol
np.float64(0.75)
energy_per_bit
property
The average bit energy $E_\mathrm{b}$ of the constellation. It assumes equiprobable symbols. It is given by $E_\mathrm{b} = E_\mathrm{s} / m$, where $E_\mathrm{s}$ is the average symbol energy, and $m$ is the number of bits per symbol of the modulation.
Examples:
>>> mod = komm.Modulation(constellation=[-0.5, 0.0, 0.5, 2.0], labeling=[[1, 0], [1, 1], [0, 1], [0, 0]])
>>> mod.energy_per_bit
np.float64(0.5625)
>>> mod = komm.Modulation(constellation=[0, -1, 1, 1j], labeling=[[0, 0], [0, 1], [1, 0], [1, 1]])
>>> mod.energy_per_bit
np.float64(0.375)
symbol_mean
property
The mean $\mu_\mathrm{s}$ of the constellation. It assumes equiprobable symbols. It is given by $$ \mu_\mathrm{s} = \frac{1}{M} \sum_{i \in [0:M)} x_i. $$
Examples:
>>> mod = komm.Modulation(constellation=[-0.5, 0.0, 0.5, 2.0], labeling=[[1, 0], [1, 1], [0, 1], [0, 0]])
>>> mod.symbol_mean
np.float64(0.5)
>>> mod = komm.Modulation(constellation=[0, -1, 1, 1j], labeling=[[0, 0], [0, 1], [1, 0], [1, 1]])
>>> mod.symbol_mean
np.complex128(0.25j)
minimum_distance
property
The minimum Euclidean distance $d_\mathrm{min}$ of the constellation. It is given by $$ d_\mathrm{min} = \min_{i, j \in [0:M), ~ i \neq j} |x_i - x_j|. $$
Examples:
>>> mod = komm.Modulation(constellation=[-0.5, 0.0, 0.5, 2.0], labeling=[[1, 0], [1, 1], [0, 1], [0, 0]])
>>> mod.minimum_distance
np.float64(0.5)
>>> mod = komm.Modulation(constellation=[0, -1, 1, 1j], labeling=[[0, 0], [0, 1], [1, 0], [1, 1]])
>>> mod.minimum_distance
np.float64(1.0)
modulate
Modulates a sequence of bits to its corresponding constellation symbols.
Parameters:
-
bits
(Array1D[int]
) –The bits to be modulated. It should be a 1D-array of integers in the set $\{ 0, 1 \}$. Its length must be a multiple of $m$.
Returns:
-
symbols
(Array1D[complex] | Array1D[float]
) –The constellation symbols corresponding to
bits
. It is a 1D-array of real or complex numbers. Its length is equal to the length ofbits
divided by $m$.
Examples:
>>> mod = komm.Modulation(constellation=[-0.5, 0.0, 0.5, 2.0], labeling=[[1, 0], [1, 1], [0, 1], [0, 0]])
>>> mod.modulate([0, 0, 1, 1, 0, 0, 1, 0])
array([ 2. , 0. , 2. , -0.5])
demodulate
Demodulates a sequence of received points to a sequence of bits.
Parameters:
-
received
(Array1D[complex] | Array1D[float]
) –The received points to be demodulated. It should be a 1D-array of real or complex numbers. It may be of any length.
-
decision_method
(str
) –The decision method to be used. It should be either
'hard'
(corresponding to hard-decision decoding) or'soft'
(corresponding to soft-decision decoding). The default value is'hard'
. -
kwargs
–Keyword arguments to be passed to the demodulator.
Returns:
-
bits_or_soft_bits
(Array1D[int] | Array1D[float]
) –The (hard or soft) bits corresponding to
received
. In the case of hard-decision decoding, it is a 1D-array of bits (integers in the set $\{ 0, 1 \}$); in the case of of soft-decision decoding, it is a 1D-array of L-values (real numbers, where positive values correspond to bit $0$ and negative values correspond to bit $1$). Its length is equal to the length ofreceived
multiplied by $m$.
Examples:
>>> mod = komm.Modulation(constellation=[-0.5, 0.0, 0.5, 2.0], labeling=[[1, 0], [1, 1], [0, 1], [0, 0]])
>>> received = [2.17, -0.06, 1.94, -0.61]
>>> mod.demodulate(received)
array([0, 0, 1, 1, 0, 0, 1, 0])
>>> mod.demodulate(received, decision_method='soft', channel_snr=100.0)
array([ 416. , 245.33333333, -27.5555556 , -16.88888889,
334.22222222, 184. , -108.44444444, 32. ])