Skip to content

komm.APSKModulation

Amplitude- and phase-shift keying (APSK) modulation. It is a complex modulation scheme in which the constellation is the union (concatenation) of component PSK constellations, called rings. More precisely, consider $K$ rings $\mathbf{X}_k$, for $k \in [0 : K)$, where the $k$-th ring has order $M_k$, amplitude $A_k$, and phase offset $\phi_k$. The $i$-th constellation symbol of the $k$-th ring is given by $$ x_{k,i} = A_k \exp \left( \mathrm{j} \frac{2 \pi i}{M_k} \right) \exp(\mathrm{j} \phi_k), \quad k \in [0 : K), \quad i \in [0 : M_k). $$ The resulting APSK constellation is therefore given by $$ \mathbf{X} = \begin{bmatrix} \mathbf{X}_0 \\ \vdots \\ \mathbf{X}_{K-1} \end{bmatrix}, $$ which has order $M = M_0 + M_1 + \cdots + M_{K-1}$. The order $M_k$ of each ring need not be a power of $2$; however, the order $M$ of the constructed APSK modulation must be.

Parameters:

  • orders (tuple[int, ...])

    A $K$-tuple with the orders $M_k$ of each ring, for $k \in [0 : K)$. The sum $M_0 + M_1 + \cdots + M_{K-1}$ must be a power of $2$.

  • amplitudes (tuple[float, ...])

    A $K$-tuple with the amplitudes $A_k$ of each ring, for $k \in [0 : K)$.

  • phase_offsets (float | tuple[float, ...])

    A $K$-tuple with the phase offsets $\phi_k$ of each ring, for $k \in [0 : K)$. If specified as a single float $\phi$, then it is assumed that $\phi_k = \phi$ for all $k \in [0 : K)$. The default value is 0.0.

  • labeling (Literal['natural'] | ArrayLike)

    The binary labeling of the modulation. Can be specified either as a 2D-array of integers (see base class for details), or as a string. In the latter case, the string must be equal to 'natural'. The default value is 'natural'.

Examples:

  1. The $8$-APSK modulation with $(M_0, M_1) = (4, 4)$, $(A_0, A_1) = (1, 2)$, and $(\phi_0, \phi_1) = (0, 0)$ is depicted below.

    (4,4)-APSK modulation.

    >>> apsk = komm.APSKModulation(orders=(4, 4), amplitudes=(1.0, 2.0))
    >>> apsk.constellation.round(3)
    array([ 1.+0.j,  0.+1.j, -1.+0.j, -0.-1.j,
            2.+0.j,  0.+2.j, -2.+0.j, -0.-2.j])
    
  2. The $16$-APSK modulation with $(M_0, M_1) = (8, 8)$, $(A_0, A_1) = (1, 2)$, and $(\phi_0, \phi_1) = (0, \pi/8)$ is depicted below.

    (8,8)-APSK modulation.

    >>> apsk = komm.APSKModulation(
    ...     orders=(8, 8),
    ...     amplitudes=(1.0, 2.0),
    ...     phase_offsets=(0.0, np.pi/8)
    ... )
    >>> apsk.constellation.round(3)
    array([ 1.   +0.j   ,  0.707+0.707j,  0.   +1.j   , -0.707+0.707j,
           -1.   +0.j   , -0.707-0.707j, -0.   -1.j   ,  0.707-0.707j,
            1.848+0.765j,  0.765+1.848j, -0.765+1.848j, -1.848+0.765j,
           -1.848-0.765j, -0.765-1.848j,  0.765-1.848j,  1.848-0.765j])
    
  3. The $16$-APSK modulation with $(M_0, M_1) = (4, 12)$, $(A_0, A_1) = (\sqrt{2}, 3)$, and $(\phi_0, \phi_1) = (\pi/4, 0)$ is depicted below.

    (4,12)-APSK modulation.

    >>> apsk = komm.APSKModulation(
    ...     orders=(4, 12),
    ...     amplitudes=(np.sqrt(2), 3.0),
    ...     phase_offsets=(np.pi/4, 0.0)
    ... )
    >>> apsk.constellation.round(3)
    array([ 1.   +1.j   , -1.   +1.j   , -1.   -1.j   ,  1.   -1.j   ,
            3.   +0.j   ,  2.598+1.5j  ,  1.5  +2.598j,  0.   +3.j   ,
           -1.5  +2.598j, -2.598+1.5j  , -3.   +0.j   , -2.598-1.5j  ,
           -1.5  -2.598j, -0.   -3.j   ,  1.5  -2.598j,  2.598-1.5j  ])
    

constellation NDArray[complexfloating] cached property

The constellation $\mathbf{X}$ of the modulation.

Examples:

>>> apsk = komm.APSKModulation(orders=(4, 4), amplitudes=(1.0, 2.0))
>>> apsk.constellation.round(3)
array([ 1.+0.j,  0.+1.j, -1.+0.j, -0.-1.j,
        2.+0.j,  0.+2.j, -2.+0.j, -0.-2.j])

labeling NDArray[integer] cached property

The labeling $\mathbf{Q}$ of the modulation.

Examples:

>>> apsk = komm.APSKModulation(orders=(4, 4), amplitudes=(1.0, 2.0))
>>> apsk.labeling
array([[0, 0, 0],
       [0, 0, 1],
       [0, 1, 0],
       [0, 1, 1],
       [1, 0, 0],
       [1, 0, 1],
       [1, 1, 0],
       [1, 1, 1]])

inverse_labeling dict[tuple[int, ...], int] cached property

The inverse labeling of the modulation. It is a dictionary that maps each binary tuple to the corresponding constellation index.

Examples:

>>> apsk = komm.APSKModulation(orders=(4, 4), amplitudes=(1.0, 2.0))
>>> apsk.inverse_labeling
{(0, 0, 0): 0,
 (0, 0, 1): 1,
 (0, 1, 0): 2,
 (0, 1, 1): 3,
 (1, 0, 0): 4,
 (1, 0, 1): 5,
 (1, 1, 0): 6,
 (1, 1, 1): 7}

order int cached property

The order $M$ of the modulation.

Examples:

>>> apsk = komm.APSKModulation(orders=(4, 4), amplitudes=(1.0, 2.0))
>>> apsk.order
8

bits_per_symbol int cached 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:

>>> apsk = komm.APSKModulation(orders=(4, 4), amplitudes=(1.0, 2.0))
>>> apsk.bits_per_symbol
3

energy_per_symbol float cached 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)} \lVert x_i \rVert^2, $$ where $\lVert x_i \rVert^2$ is the energy of constellation symbol $x_i$, and $M$ is the order of the modulation.

Examples:

>>> apsk = komm.APSKModulation(orders=(4, 4), amplitudes=(1.0, 2.0))
>>> apsk.energy_per_symbol
2.5

energy_per_bit float cached property

The average bit energy $E_\mathrm{b}$ of the constellation. It assumes equiprobable symbols. It is given by $$ E_\mathrm{b} = \frac{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:

>>> apsk = komm.APSKModulation(orders=(4, 4), amplitudes=(1.0, 2.0))
>>> apsk.energy_per_bit
0.8333333333333334

symbol_mean complex cached 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:

>>> apsk = komm.APSKModulation(orders=(4, 4), amplitudes=(1.0, 2.0))
>>> apsk.symbol_mean
0j

minimum_distance float cached 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 } \lVert x_i - x_j \rVert. $$

Examples:

>>> apsk = komm.APSKModulation(orders=(4, 4), amplitudes=(1.0, 2.0))
>>> apsk.minimum_distance
1.0

modulate()

Modulates one or more sequences of bits to their corresponding constellation symbols.

Parameters:

  • input (ArrayLike)

    The input sequence(s). Can be either a single sequence whose length is a multiple of $m$, or a multidimensional array where the last dimension is a multiple of $m$.

Returns:

  • output (NDArray[complexfloating])

    The output sequence(s). Has the same shape as the input, with the last dimension divided by $m$.

Examples:

>>> apsk = komm.APSKModulation(orders=(4, 4), amplitudes=(1.0, 2.0))
>>> apsk.modulate([0, 0, 0, 0, 1, 1, 0, 0, 0]).round(3)
array([ 1.+0.j, -0.-1.j,  1.+0.j])

demodulate_hard()

Demodulates one or more sequences of received points to their corresponding sequences of hard bits ($\mathtt{0}$ or $\mathtt{1}$) using hard-decision decoding.

Parameters:

  • input (ArrayLike)

    The input sequence(s). Can be either a single sequence, or a multidimensional array.

Returns:

  • output (NDArray[integer])

    The output sequence(s). Has the same shape as the input, with the last dimension multiplied by $m$.

demodulate_soft()

Demodulates one or more sequences of received points to their corresponding sequences of soft bits (L-values) using soft-decision decoding. The soft bits are the log-likelihood ratios of the bits, where positive values correspond to bit $\mathtt{0}$ and negative values correspond to bit $\mathtt{1}$.

Parameters:

  • input (ArrayLike)

    The received sequence(s). Can be either a single sequence, or a multidimensional array.

  • snr (float)

    The signal-to-noise ratio (SNR) of the channel. It should be a positive real number. The default value is 1.0.

Returns:

  • output (NDArray[floating])

    The output sequence(s). Has the same shape as the input, with the last dimension multiplied by $m$.