Source code for Constellations.ReshapedQAMConstellation

# This file is part of NFDMLab.
#
# NFDMLab is free software; you can redistribute it and/or
# modify it under the terms of the version 2 of the GNU General
# Public License as published by the Free Software Foundation.
#
# NFDMLab is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with NFDMLab; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
# Contributors:
# Sander Wahls (TU Delft) 2018
# Shrinivas Chimmalgi (TU Delft) 2018

import numpy as np
import scipy.integrate as integrate
import warnings

from Constellations import QAMConstellation

[docs]class ReshapedQAMConstellation(QAMConstellation): """Reshaped quadrature amplitude modulation (QAM) constellation (implements BaseConstellation). The goal of the reshaping procedure is to fit the average (normalized) energy of the generated pulses to a desired value Ed. For details, see Gui et al., Opt. Express 26(21), 2018. """
[docs] def __init__(self, m, n, b0_fun, Ed, bnds): """Constructor for a reshaped m x n QAM constellation. Parameters ---------- m : int n : int b0_fun : function Carrier waveform. The function should maps any input vector of the type numpy.array(float), which represents a vector of nonlinear frequencies xi, to a output vector of the type numpy.array(complex), which represents the values of the carrier waveform at these xi. Ed : float Desired average energy of the generated pulses (with respect to normalized units). Should be positive. bnds : numpy.array(float) Vector with two entries [a,b], which are used as initial bounds in the bisection produdure based on which the constellation is reshaped. It should be 0<a<b. """ super().__init__(m, n) alphabet0 = self.alphabet / np.max(np.abs(self.alphabet)) niter = 35 abs_vals = np.unique(np.abs(alphabet0)) M = np.size(alphabet0) K = np.size(abs_vals) for k in range(0, K): Ek_target = Ed*M*abs_vals[k]**2/(np.linalg.norm(alphabet0)**2) lb = bnds[0] ub = bnds[1] for iter in range(0, niter): Ak = 0.5*(lb + ub) with warnings.catch_warnings(): warnings.simplefilter("ignore") I = integrate.quad(lambda xi: -np.log(1 - Ak*(abs_vals[k]**2)*(np.abs(b0_fun(xi))**2)), -np.inf, np.inf) Ek = I[0]/np.pi if Ek<Ek_target: lb = Ak else: ub = Ak if Ek<0.95*Ek_target: raise ValueError('scale_modulation failed - try to increase upper bound') Ak = lb idx = np.abs(alphabet0) == abs_vals[k] self._alphabet[idx] = np.sqrt(Ak)*alphabet0[idx] self._name = "Reshaped %d-QAM Constellation" % self.size()