sdr.evm(x_hat: ArrayLike, ref: ArrayLike, norm: 'average-power-ref' | 'average-power' | 'peak-power' = 'average-power-ref', output: 'rms' | 'all' | float = 'rms') float

Calculates the error-vector magnitude (EVM) of the complex symbols \(\hat{x}[k]\).

Parameters:
x_hat: ArrayLike

The complex symbols \(\hat{x}[k]\) to be measured.

ref: ArrayLike

The complex reference symbols \(x[k]\). This can be the noiseless transmitted symbols or the modulation’s symbol map.

norm: 'average-power-ref' | 'average-power' | 'peak-power' = 'average-power-ref'

The normalization source used in the EVM calculation.

  • "average-power-ref": The average power of the reference symbols \(x[k]\).

\[P_{\text{ref}} = \frac{1}{N} \sum_{k=0}^{N-1} \left| x[k] \right|^2\]

  • "average-power": The average power of the received symbols \(\hat{x}[k]\).

\[P_{\text{ref}} = \frac{1}{N} \sum_{k=0}^{N-1} \left| \hat{x}[k] \right|^2\]

  • "peak-power": The peak power of the received symbols \(\hat{x}[k]\).

\[P_{\text{ref}} = \text{max} \left| \hat{x}[k] \right|^2\]

output: 'rms' | 'all' | float = 'rms'

The output type of the EVM calculation.

  • "rms": The root-mean-square (RMS) EVM.

\[ \text{EVM}_{\text{RMS}} = 100 \sqrt{\frac{\frac{1}{N} \sum_{k=0}^{N-1} \left| \hat{x}[k] - x[k] \right|^2}{P_{\text{ref}}}} \]

  • "all": The instantaneous EVM for each symbol.

\[ \text{EVM}_{k} = 100 \sqrt{\frac{\left| \hat{x}[k] - x[k] \right|^2}{P_{\text{ref}}}} \]

  • float: The RMS EVM for the given percentile (0 - 100).

Examples

Create QPSK symbols with \(E_s/N_0\) of 20 dB.

In [1]: psk = sdr.PSK(4, phase_offset=45); \
   ...: s = np.random.randint(0, psk.order, 1000); \
   ...: x = psk.modulate(s); \
   ...: x_hat = sdr.awgn(x, 20)
   ...: 

In [2]: plt.figure(figsize=(8, 4)); \
   ...: sdr.plot.constellation(x_hat, label=r"$\hat{x}[k]$"); \
   ...: sdr.plot.symbol_map(psk.symbol_map, label=r"Reference"); \
   ...: plt.title("QPSK Constellation at 20 dB $E_s/N_0$"); \
   ...: plt.tight_layout();
   ...: 
../../_images/sdr_evm_1.png

Measure the RMS EVM, normalizing with the average power of the reference symbols. Either the symbol map or noiseless transmitted symbols may be passed.

In [3]: sdr.evm(x_hat, psk.symbol_map)
Out[3]: 64.72102795130989

In [4]: sdr.evm(x_hat, x)
Out[4]: 10.062053563628073

Measure the RMS EVM, normalizing with the average power of the received symbols.

In [5]: sdr.evm(x_hat, psk.symbol_map, norm="average-power")
Out[5]: 182.0295817233469

Measure the RMS EVM, normalizing with the peak power of the received symbols.

In [6]: sdr.evm(x_hat, psk.symbol_map, norm="peak-power")
Out[6]: 146.0684313831214

Measure the 95th percentile EVM.

In [7]: sdr.evm(x_hat, psk.symbol_map, output=95)
Out[7]: 68.8022505582809

Measure the instantaneous EVM for each symbol.

In [8]: inst_evm = sdr.evm(x_hat, psk.symbol_map, output="all")

In [9]: plt.figure(figsize=(8, 4)); \
   ...: plt.hist(inst_evm, bins=20); \
   ...: plt.xlabel("RMS EVM (%)"); \
   ...: plt.ylabel("Count"); \
   ...: plt.title("EVM Histogram"); \
   ...: plt.tight_layout();
   ...: 
../../_images/sdr_evm_2.png