Esempio n. 1
0
def generate_symbols_for_eq(method, M, dtype):
    #TODO: investigate if it makes sense to include the calculations of constants inside the methods
    if method in ["cma"]:
        return np.atleast_2d(_cal_Rconstant(M) + 0j).astype(dtype)
    if method in ["sgncma"]:
        return np.atleast_2d(_cal_Rconstant(M) + 0j).astype(dtype)
    if method in ["mcma"]:
        return np.atleast_2d(_cal_Rconstant_complex(M)).astype(dtype)
    if method in ["rde"]:
        p = generate_partition_codes_radius(M)
        return np.atleast_2d(p+0j).astype(dtype)
    if method in ["mrde"]:
        p = generate_partition_codes_complex(M)
        return  np.atleast_2d(p).astype(dtype)
    if method in ["sbd"]:
        symbols = np.atleast_2d(cal_symbols_qam(M)/np.sqrt(cal_scaling_factor_qam(M))).astype(dtype)
        return symbols
    if method in ["mddma"]:
        symbols = np.atleast_2d(cal_symbols_qam(M)/np.sqrt(cal_scaling_factor_qam(M))).astype(dtype)
        return  symbols
    if method in ["dd"]:
        symbols = np.atleast_2d(cal_symbols_qam(M)/np.sqrt(cal_scaling_factor_qam(M))).astype(dtype)
        return symbols
    if method in ["sgncma_real"]:
        return np.repeat([np.atleast_1d(_cal_Rconstant_complex(M).real.astype(dtype))], 2, axis=0)
    if method in ["cma_real"]:
        return np.repeat([np.atleast_1d(_cal_Rconstant_complex(M).real.astype(dtype))], 2, axis=0)
    if method in ["dd_real"]:
        symbols = cal_symbols_qam(M)/np.sqrt(cal_scaling_factor_qam(M))
        symbols_out = np.vstack([symbols.real, symbols.imag]).astype(dtype)
        return symbols_out
    if method in ["dd_data_real", "sbd_data"]:
        raise ValueError("%s is a data-aided method and needs the symbols to be passed"%method)
    raise ValueError("%s is unknown method"%method)
Esempio n. 2
0
def _select_errorfct(method, M, symbols, dtype, **kwargs):
    #TODO: investigate if it makes sense to include the calculations of constants inside the methods
    if method in ["mcma"]:
        return ErrorFctMCMA(_cal_Rconstant_complex(M))
    elif method in ["cma"]:
        return ErrorFctCMA(_cal_Rconstant(M))
    elif method in ["rde"]:
        p, c = generate_partition_codes_radius(M)
        return ErrorFctRDE(p, c)
    elif method in ["mrde"]:
        p, c = generate_partition_codes_complex(M)
        return ErrorFctMRDE(p, c)
    elif method in ["sca"]:
        return ErrorFctSCA(_cal_Rsca(M))
    elif method in ["cme"]:
        if symbols is None:
            syms = cal_symbols_qam(M) / np.sqrt(cal_scaling_factor_qam(M))
            syms = syms.astype(dtype)
        else:
            syms = symbols
        d = np.min(
            abs(np.diff(np.unique(syms.real)))
        )  # should be fixed to consider different spacing between real and imag
        R = _cal_Rconstant(M)
        r2 = np.mean(abs(syms)**2)
        r4 = np.mean(abs(syms)**4)
        A = r4 / r2
        bb = np.max(abs(syms * abs(syms)**2 - A))
        try:
            beta = kwargs['beta']
        except:
            r2 = np.mean(abs(syms)**2)
            r4 = np.mean(abs(syms)**4)
            A = r4 / r2
            beta = np.max(abs(syms * abs(syms)**2 - A)) / 2
        return ErrorFctCME(R, d, beta)
    elif method in ['sbd']:
        if symbols is None:
            return ErrorFctSBD(
                (cal_symbols_qam(M) /
                 np.sqrt(cal_scaling_factor_qam(M))).astype(dtype))
        else:
            return ErrorFctSBD(symbols)
    elif method in ['mddma']:
        return ErrorFctMDDMA(
            (cal_symbols_qam(M) /
             np.sqrt(cal_scaling_factor_qam(M))).astype(dtype))
    elif method in ['dd']:
        return ErrorFctDD((cal_symbols_qam(M) /
                           np.sqrt(cal_scaling_factor_qam(M))).astype(dtype))
    else:
        raise ValueError("%s is unknown method" % method)
Esempio n. 3
0
def generate_partition_codes_complex(M):
    """
    Generate complex partitions and codes for M-QAM for MRDE based on the real and imaginary radii of the different symbols. The partitions define the boundaries between the different codes. This is used to determine on which real/imaginary radius a signal symbol should lie on. The real and imaginary parts should be used for parititioning the real and imaginary parts of the signal in MRDE.

    Parameters
    ----------
    M       : int
        M-QAM order

    Returns
    -------
    parts   : array_like
        the boundaries between the different codes for parititioning
    codes   : array_like
        the nearest symbol radius 
    """
    syms = cal_symbols_qam(M)
    scale = cal_scaling_factor_qam(M)
    syms /= np.sqrt(scale)
    syms_r = np.unique(abs(syms.real)**4 / abs(syms.real)**2)
    syms_i = np.unique(abs(syms.imag)**4 / abs(syms.imag)**2)
    codes = syms_r + 1.j * syms_i
    part_r = syms_r[:-1] + np.diff(syms_r) / 2
    part_i = syms_i[:-1] + np.diff(syms_i) / 2
    parts = part_r + 1.j * part_i
    return np.hstack([parts, codes])
Esempio n. 4
0
def _cal_Rsca(M):
    syms = cal_symbols_qam(M)
    syms /= np.sqrt(cal_scaling_factor_qam(M))
    Rd = _cal_Rdash(syms)
    return np.mean(
        (abs(syms.real + syms.imag) + abs(syms.real - syms.imag))**2 *
        Rd) / (4 * np.mean(Rd))
 def test_symbols(self, M):
     s = signals.SignalQAMGrayCoded(M, 1000, nmodes=1)
     si = np.unique(s)
     thsyms = theory.cal_symbols_qam(M) / np.sqrt(theory.cal_scaling_factor_qam(M))
     d = np.min(abs(s[0, :, np.newaxis] - thsyms), axis=1)
     assert si.shape[0] == M
     npt.assert_array_almost_equal(d, 0)
Esempio n. 6
0
 def test_reshape_symbols_DD_cmplx(self, method, M, nmodes, pass_syms):
     from qampy import theory
     from qampy.core.equalisation.equalisation import _reshape_symbols
     syms = theory.cal_symbols_qam(M)/np.sqrt(theory.cal_scaling_factor_qam(M))
     if pass_syms:
         s = _reshape_symbols(syms, method, M, np.complex128, nmodes)
     else:
         s = _reshape_symbols(None, method, M, np.complex128, nmodes)
     assert s.shape[0] == nmodes
     assert s.shape[1] == syms.shape[0]
     for i in range(nmodes):
         npt.assert_allclose(s[i], syms)
Esempio n. 7
0
 def test_reshape_symbols_DD_real(self, M, nmodes, pass_syms):
     from qampy import theory
     from qampy.core.equalisation.equalisation import _reshape_symbols
     syms = theory.cal_symbols_qam(M)/np.sqrt(theory.cal_scaling_factor_qam(M))
     if pass_syms is None:
         s = _reshape_symbols(None, "dd_real", M, np.float64, nmodes*2)
     elif pass_syms is "cmplx":
         s = _reshape_symbols(syms, "dd_real", M, np.float64, nmodes*2)
     elif pass_syms is "float":
         s = _reshape_symbols(np.array([syms.real, syms.imag]), "dd_real", M, np.float64, nmodes*2)
     assert s.shape[0] == nmodes*2
     assert s.shape[1] == syms.shape[0]
     for i in range(nmodes*2):
         if i < nmodes:
             npt.assert_allclose(s[i], syms.real)
         else:
             npt.assert_allclose(s[i], syms.imag)
Esempio n. 8
0
def generate_partition_codes_radius(M):
    """
    Generate partitions and codes for M-QAM for RDE based on the radius of the different symbols. The partitions define the boundaries between the different codes. This is used to determine on which radius a signal symbol should lie.

    Parameters
    ----------
    M       : int
        M-QAM order

    Returns
    -------
    parts   : array_like
        the boundaries between the different codes for parititioning
    codes   : array_like
        the nearest symbol radius 
    """
    syms = cal_symbols_qam(M)
    scale = cal_scaling_factor_qam(M)
    syms /= np.sqrt(scale)
    codes = np.unique(abs(syms)**4 / abs(syms)**2)
    parts = codes[:-1] + np.diff(codes) / 2
    return np.hstack([parts, codes])
Esempio n. 9
0
def _cal_gamma(M):
    """Calculate the gamma factor for SNR estimation."""
    A = abs(cal_symbols_qam(M)) / np.sqrt(cal_scaling_factor_qam(M))
    uniq, counts = np.unique(A, return_counts=True)
    return np.sum(uniq**4 * counts / M)
Esempio n. 10
0
def _cal_Rconstant_complex(M):
    syms = cal_symbols_qam(M)
    scale = cal_scaling_factor_qam(M)
    syms /= np.sqrt(scale)
    return np.mean(syms.real**4) / np.mean(syms.real**2) + 1.j * np.mean(
        syms.imag**4) / np.mean(syms.imag**2)
Esempio n. 11
0
def _cal_Rconstant(M):
    syms = cal_symbols_qam(M)
    scale = cal_scaling_factor_qam(M)
    syms /= np.sqrt(scale)
    return np.mean(abs(syms)**4) / np.mean(abs(syms)**2)