def test_apply_filter(dtype, benchmark): fb = 40.e9 os = 2 fs = os * fb N = 10**5 mu = 4e-4 theta = np.pi / 5.45 theta2 = np.pi / 4 t_pmd = 75e-12 M = 4 ntaps = 40 snr = 14 sig = signals.SignalQAMGrayCoded(M, N, fb=fb, nmodes=2, dtype=dtype) S = sig.resample(fs, renormalise=True, beta=0.1) S = impairments.change_snr(S, snr) SS = impairments.apply_PMD(S, theta, t_pmd) wxy, err = equalisation.equalise_signal(SS, mu, Ntaps=ntaps, method="mcma", adaptive_step=True) E1 = equalisation.apply_filter(SS, wxy, method="pyx") E2 = equalisation.apply_filter(SS, wxy, method="py") E2 = E1.recreate_from_np_array(E2) E1 = helpers.normalise_and_center(E1) E2 = helpers.normalise_and_center(E2) E1, ph = phaserec.viterbiviterbi(E1, 11) E2, ph = phaserec.viterbiviterbi(E2, 11) E1 = helpers.dump_edges(E1, 20) E2 = helpers.dump_edges(E2, 20) ser1 = E1.cal_ser().mean() ser2 = E2.cal_ser().mean() npt.assert_allclose(0, ser1, atol=3e-5) npt.assert_allclose(0, ser2, atol=3e-5)
def test_normalise(nmodes): s = signals.SignalQAMGrayCoded(64, 2**12, nmodes=nmodes) s2 = helpers.normalise_and_center(s) s3 = np.zeros(s.shape, dtype=s.dtype) for i in range(nmodes): s3[i] = helpers.normalise_and_center(s[i]) npt.assert_array_almost_equal(s2, s3)
def resample_poly(signal, fold, fnew, window=None, renormalise=False): """ Resamples a signal from an old frequency to a new. Preserves the whole data but adjusts the length of the array in the process. Parameters ---------- signal: array_like signal to be resampled fold : float Sampling frequency of the signal fnew : float New desired sampling frequency. window : array_like, optional sampling windowing function renormalise : bool, optional whether to renormalise and recenter the signal to a power of 1. Returns ------- out : array_like resampled signal of length fnew/fold*len(signal) """ signal = signal.flatten() L = len(signal) up, down = _resamplingfactors(fold, fnew) if window is None: sig_new = scisig.resample_poly(signal, up, down) else: sig_new = scisig.resample_poly(signal, up, down, window=window) if renormalise: p = np.mean(abs(signal)**2) sig_new = normalise_and_center(sig_new) * np.sqrt(p) return sig_new
def equalize_synchronize_signal(resampled_sig, mu=None, ntaps=None, method=None, adaptive_step=None, avoid_cma_sing=None): #Equalize and synchronize the signal and calculate the bit error rate if mu is None: mu = 2e-3 if ntaps is None: ntaps = 21 if method is None: method = "cma" if adaptive_step is None: adaptive_step = True if avoid_cma_sing is None: avoid_cma_sing = False wxy, err = equalisation.equalise_signal(resampled_sig, mu, Ntaps=ntaps, method=method, adaptive_step=adaptive_step, avoid_cma_sing=avoid_cma_sing) E = equalisation.apply_filter(resampled_sig, wxy) E = helpers.normalise_and_center(E) ber, errs, tx_synced = E.cal_ber( E, verbose=True ) #Synchronize the signal with the data and calculates the bit error rate return E, ber, errs, tx_synced
def test_coarse_freq_offset(self, fo, mode_offset): snr = 37 ntaps = 19 sig = signals.SignalWithPilots(64, 2**16, 1024, 32, nframes=3, nmodes=2, fb=24e9) sig2 = sig.resample(2 * sig.fb, beta=0.01, renormalise=True) sig3 = impairments.simulate_transmission(sig2, snr, freq_off=fo, modal_delay=[0, mode_offset]) sig4 = helpers.normalise_and_center(sig3) sig4 = sig4[:, 2000:] sig4.sync2frame(corr_coarse_foe=True) s1, s2 = equalisation.pilot_equaliser(sig4, [1e-3, 1e-3], ntaps, True, adaptive_stepsize=True, foe_comp=True) d, ph = phaserec.pilot_cpe(s2, nframes=1) assert np.mean(d.cal_ber()) < 1e-5
def test_apply_filter_benchmark(dtype, method, benchmark): benchmark.group = "apply filter " + str(dtype) fb = 40.e9 os = 2 fs = os * fb N = 2**17 mu = 4e-4 theta = np.pi / 5.45 theta2 = np.pi / 4 t_pmd = 75e-12 M = 4 ntaps = 40 snr = 14 sig = signals.SignalQAMGrayCoded(M, N, fb=fb, nmodes=2, dtype=dtype) S = sig.resample(fs, renormalise=True, beta=0.1) SS = impairments.change_snr(S, snr) #SS = impairments.apply_PMD(S, theta, t_pmd) wxy, err = equalisation.equalise_signal(SS, mu, Ntaps=ntaps, method="mcma", adaptive_step=True) E1 = benchmark(equalisation.apply_filter, SS, wxy, method) E1 = helpers.normalise_and_center(E1) ser = E1.cal_ser() npt.assert_allclose(0, ser, atol=3e-5)
def test_pol_rot(self, method1, method2, phi): phi = np.pi / phi fb = 40.e9 os = 2 fs = os * fb N = 2**16 beta = 0.9 mu1 = 0.1e-2 mu2 = 0.1e-2 M = 32 s = signals.SignalQAMGrayCoded(M, N, nmodes=2, fb=fb) s = s.resample(fs, beta=beta, renormalise=True) s = impairments.rotate_field(s, phi) sout, wxy, err = equalisation.dual_mode_equalisation( s, (mu1, mu2), Ntaps=5, Niter=(3, 3), methods=(method1, method2), adaptive_stepsize=(True, True)) sout = helpers.normalise_and_center(sout) ser = sout.cal_ser() #plt.plot(sout[0].real, sout[0].imag, 'r.') #plt.plot(sout[1].real, sout[1].imag, 'b.') #plt.show() if ser.mean() > 0.5: ser = sout[::-1].cal_ser() npt.assert_allclose(ser, 0)
def test_pmd(self, method1, method2): theta = np.pi / 5 dgd = 120e-12 fb = 40.e9 os = 2 fs = os * fb N = 2**16 snr = 15 beta = 0.9 mu1 = 4e-4 mu2 = 4e-4 M = 32 ntaps = 21 s = signals.SignalQAMGrayCoded(M, N, nmodes=2, fb=fb) s = s.resample(fs, beta=beta, renormalise=True) s = impairments.apply_PMD(s, theta, dgd) sout, wxy, err = equalisation.dual_mode_equalisation( s, (mu1, mu2), Ntaps=ntaps, methods=(method1, method2), adaptive_stepsize=(True, True)) sout = helpers.normalise_and_center(sout) ser = sout.cal_ser() if ser.mean() > 0.4: ser = sout[::-1].cal_ser() npt.assert_allclose(ser, 0, atol=1.01 * 2 / N) # can tolerate 1-2 errors
def test_pmd_phase_fails(self, method, phi, dgd, lw): theta = np.pi / phi fb = 40.e9 os = 2 fs = os * fb N = 2**16 snr = 15 beta = 0.3 mu = 2e-4 M = 4 ntaps = 15 s = signals.SignalQAMGrayCoded(M, N, nmodes=2, fb=fb) s = s.resample(fs, beta=beta, renormalise=True) s = impairments.apply_phase_noise(s, lw) s = impairments.apply_PMD(s, theta, dgd) wxy, err = equalisation.equalise_signal(s, mu, Ntaps=ntaps, method=method, adaptive_stepsize=False) sout = equalisation.apply_filter(s, wxy) sout, ph = phaserec.viterbiviterbi(sout, 11) sout = helpers.normalise_and_center(sout) sout = helpers.dump_edges(sout, 20) ser = sout.cal_ser() npt.assert_allclose(ser, 0)
def test_pmd_2(self, method, dgd): phi = 6.5 theta = np.pi / phi fb = 40.e9 os = 2 fs = os * fb N = 2**16 snr = 15 beta = 0.1 mu = 0.9e-3 M = 4 ntaps = 7 s = signals.SignalQAMGrayCoded(M, N, nmodes=2, fb=fb) s = s.resample(fs, beta=beta, renormalise=True) s = impairments.apply_PMD(s, theta, dgd) wxy, err = equalisation.equalise_signal(s, mu, Ntaps=ntaps, method=method, adaptive_stepsize=True, avoid_cma_sing=True) sout = equalisation.apply_filter(s, wxy) sout = helpers.normalise_and_center(sout) ser = sout.cal_ser() npt.assert_allclose(ser, 0)
def test_pmd_phase(self, method1, method2, lw): theta = np.pi / 4.5 dgd = 100e-12 fb = 40.e9 os = 2 fs = os * fb N = 2**16 snr = 15 beta = 0.9 mu1 = 2e-3 if method2 == "mddma": mu2 = 1.0e-3 else: mu2 = 2e-3 M = 32 ntaps = 21 s = signals.SignalQAMGrayCoded(M, N, nmodes=2, fb=fb) s = s.resample(fs, beta=beta, renormalise=True) s = impairments.apply_phase_noise(s, lw) s = impairments.apply_PMD(s, theta, dgd) sout, wxy, err = equalisation.dual_mode_equalisation( s, (mu1, mu2), Ntaps=ntaps, methods=(method1, method2), adaptive_stepsize=(True, True)) sout, ph = phaserec.bps(sout, M, 21) sout = helpers.normalise_and_center(sout) sout = helpers.dump_edges(sout, 50) ser = sout.cal_ser() if ser.mean() > 0.4: ser = sout[::-1].cal_ser() npt.assert_allclose(ser, 0, atol=1.01 * 3 / N) # Three wrong symbols is ok
def test_equalisation_prec(dtype, benchmark): fb = 40.e9 os = 2 fs = os * fb N = 10**5 #mu = np.float32(4e-4) mu = 4e-4 theta = np.pi / 5.45 theta2 = np.pi / 4 t_pmd = 75e-12 M = 4 ntaps = 40 snr = 14 sig = signals.SignalQAMGrayCoded(M, N, fb=fb, nmodes=2, dtype=dtype) S = sig.resample(fs, renormalise=True, beta=0.1) S = impairments.apply_phase_noise(S, 100e3) S = impairments.change_snr(S, snr) SS = impairments.apply_PMD(S, theta, t_pmd) wxy, err = benchmark(equalisation.equalise_signal, SS, mu, Ntaps=ntaps, method="mcma", adaptive_stepsize=True) E = equalisation.apply_filter(SS, wxy) E = helpers.normalise_and_center(E) E, ph = phaserec.viterbiviterbi(E, 11) E = helpers.dump_edges(E, 20) ser = E.cal_ser().mean() npt.assert_allclose(0, ser, atol=3e-5)
def test_real_valued_single_mode(self, method): s = signals.SignalQAMGrayCoded(4, 10**5, nmodes=1, fb=25e9) s2 = s.resample(s.fb*2, beta=0.1) s2 = impairments.sim_mod_response(s*0.2, dcbias=1.1) s3 = helpers.normalise_and_center(s2) s4 = impairments.change_snr(s3, 15) s5, wx, err = equalisation.equalise_signal(s4, 1e-3, Ntaps=17, method=method, adaptive_stepsize=True, apply=True) assert s5.cal_ser() < 1e5
def test_data_aided(self, modes, method, ps_sym): from qampy import helpers ntaps = 21 sig = signals.SignalQAMGrayCoded(64, 10**5, nmodes=2, fb=25e9) sig2 = sig.resample(2*sig.fb, beta=0.02) sig2 = helpers.normalise_and_center(sig2) sig2 = np.roll(sig2, ntaps//2) sig3 = impairments.simulate_transmission(sig2, dgd=150e-12, theta=np.pi/3., snr=35) sig3 = helpers.normalise_and_center(sig3) if ps_sym: symbs = sig3.symbols else: symbs = None sigout, wxy, err = equalisation.equalise_signal(sig3, 1e-3, Ntaps=ntaps, adaptive_stepsize=True, symbols=symbs, apply=True, method=method, TrSyms=20000, modes=modes) sigout = helpers.normalise_and_center(sigout) gmi = np.mean(sigout.cal_gmi(llr_minmax=True)[0]) assert gmi > 5.9
def rrcos_resample(signal, fold, fnew, Ts=None, beta=None, taps=4001, renormalise=False, fftconv=True): """ Resample a signal using a root raised cosine filter. This performs pulse shaping and resampling a the same time. The resampling is done by scipy.signal.resample_poly. This function can be quite slow. Parameters ---------- signal : array_like input time domain signal fold : float sampling frequency of the input signal fnew : float desired sampling frequency Ts : float, optional time width of the RRCOS filter (default:None makes this 1/fold) beta : float, optional filter roll off factor between (0,1] (default:None will use the default filter in poly_resample) taps : int, optional taps of the interpolation filter if taps is None we filter by zeroinsertion upsampling and multipling with the full length rrcos frequency response in the spectral domain fftconv : bool, optional filter using zero insertion upsampling/decimation and filtering using fftconvolve. I often faster for long filters and power of two signal lengths. Returns ------- sig_out : array_like resampled output signal """ if beta is None: return resample_poly(signal, fold, fnew) assert 0 < beta <= 1, "beta needs to be in interval (0,1]" if Ts is None: Ts = 1/fold up, down = _resamplingfactors(fold, fnew) fup = up*fold # for very large tap lengths it is better to filter with fftconvolve # it could be better to use default values here, but this seems to depend on pc if fftconv or taps is None: sig_new = np.zeros((up*signal.size,), dtype=signal.dtype) sig_new[::up] = signal sig_new = rrcos_pulseshaping(sig_new, fup, Ts, beta, taps) sig_new = sig_new[::down] else: t = np.linspace(0, taps, taps, endpoint=False) t -= t[(t.size-1)//2] t /= fup nqf = rrcos_time(t, beta, Ts) nqf /= nqf.max() sig_new = scisig.resample_poly(signal, up, down, window=nqf) if renormalise: p = np.mean(abs(signal)**2) sig_new = normalise_and_center(sig_new)*np.sqrt(p) return sig_new
def load_symbols_from_matlab_file(fn, M, keys, fb=10e9, fake_polmux=False, fake_pm_delay=0, normalise=True, **kwargs): """ Create a signal object from matlab file. Parameters ---------- fn : basestring Matlab filename M : int QAM order keys: list Nested list of keys (array names) in the matlab file. Depending on how the data is structured the keys can be in one of the following formats: If the symbols are given as a multi-dimensional array of complex numbers: [[ keyname ]] If the symbols are given as multi-dimensional real arrays pairs for real and imaginary part: [[ key_real, key_imag ]] If the different symbols of modes are saved in different complex arrays: [[key_mode1], ..., [key_modeN]] If the symbols are given as pairs of real arrays for each mode: [[key_mode1_real, key_mode1_imag], ... [key_modeN_real, key_modeN_imag]] fb: float, optional Symbol rate fake_polmux: boolean, optional Whether the signal uses fake polmux, thus the single dimension matlab symbol array should be duplicated fake_pm_delay: int, optional Number of symbols to delay the second dimension in the fake pol-mux normalise : boolean, optional Normalise the symbols to an average power of 1 or not. Note that if you do not normalise you need to be very careful with your signal metrics kwargs: dict Keyword arguments to pass to core.io.ndarray_from_matlab (see documentation for details) Returns ------- sig : signal_object Signal generated from the loaded symbols """ symbs = ndarray_from_matlab(fn, keys, **kwargs) if fake_polmux: symbs = np.vstack([np.roll(symbs, fake_pm_delay), symbs]) if normalise: symbs = helpers.normalise_and_center(symbs) return signals.SignalQAMGrayCoded.from_symbol_array(symbs, M, fb)
def quantize_signal(sig, nbits=6, rescale=True, re_normalize=True): """ Function so simulate limited resultion using DACs and ADCs Parameters: sig: Input signal, numpy array nbits: Quantization resultion rescale: Rescale to range p/m 1, default True re_normalize: Renormalize signal after quantization Returns: sig_out: Output quantized waveform """ # Create a 2D signal sig = np.atleast_2d(sig) npols = sig.shape[0] # Rescale to if rescale: for pol in range(npols): sig[pol] /= np.abs(sig[pol]).max() levels = np.linspace(-1, 1, 2**(nbits)) sig_out = np.zeros(sig.shape, dtype=sig.dtype) for pol in range(npols): sig_quant_re = levels[np.digitize(sig[pol].real, levels[:-1], right=False)] sig_quant_im = levels[np.digitize(sig[pol].imag, levels[:-1], right=False)] sig_out[pol] = sig_quant_re + 1j * sig_quant_im if not np.iscomplexobj(sig): sig_out = sig_out.real if re_normalize: sig_out = normalise_and_center(sig_out) return sig_out
Ncma = 10000 Nrde = N // 2 // os - int(1.5 * ntaps) #S, symbols, bits = QAM.generate_signal(N, snr, baudrate=fb, samplingrate=fs, PRBSorder=(15,23)) sig = signals.SignalQAMGrayCoded(M, N, fb=fb, nmodes=2) S = sig.resample(fs, beta=0.1, renormalise=True) S = impairments.change_snr(S, snr) SS = impairments.apply_PMD(S, theta, t_pmd) E, wx, (err, err_rde) = equalisation.dual_mode_equalisation(SS, (muCMA, muRDE), ntaps, methods=("mcma", "sbd"), adaptive=(True, True)) E = helpers.normalise_and_center(E) evm = E.cal_evm() evm_s = S[:, ::2].cal_evm() #sys.exit() plt.figure() plt.subplot(121) plt.title('Recovered MCMA/MDDMA') plt.plot(E[0].real, E[0].imag, 'r.', label=r"$EVM_x=%.1f\%%$" % (evm[0] * 100)) plt.plot(E[1].real, E[1].imag, 'g.', label=r"$EVM_y=%.1f\%%$" % (100 * evm[1])) plt.legend() plt.subplot(122) plt.title('Original') plt.plot(S[0, ::2].real, S[0, ::2].imag, 'r.',
def test_normalise_and_center(self, nmodes): s = signals.SignalQAMGrayCoded(64, 2**12, nmodes=nmodes) s2 = helpers.normalise_and_center(s) assert s.shape == s2.shape
def test_normalise_and_center(self): s = signals.SignalQAMGrayCoded(64, 2**12) s2 = helpers.normalise_and_center(s) assert type(s) is type(s2)
evm1 = np.zeros(snr.shape) evm_known = np.zeros(snr.shape) i = 0 for sr in snr: print("SNR = %2f.0 dB" % sr) signal = signals.SignalQAMGrayCoded(M, N, nmodes=1, fb=fb) signal = signal.resample(fnew=fs, beta=beta, renormalise=True) signal_s = impairments.change_snr(signal, sr) #signalx = np.atleast_2d(filtering.rrcos_pulseshaping(signal_s, beta)) wx, er = equalisation.equalise_signal(signal_s, 3e-4, Ntaps=ntaps, method="mcma", adaptive_step=True) signalafter = equalisation.apply_filter(signal_s, wx) signalafter = helpers.normalise_and_center(signalafter) evm1[i] = signal.cal_evm()[0] evm_known[i] = signalafter.cal_evm() # check to see that we can recovery timing delay #signalafter = np.roll(signalafter * 1.j**np.random.randint(0,4), np.random.randint(4, 3000)) ser[i] = signalafter.cal_ser() ber[i] = signalafter.cal_ber() i += 1 ax1.plot(snrf, theory.ber_vs_es_over_n0_qam(10**(snrf / 10), M), color=c[j], label="%d-QAM theory" % M) ax1.plot(snr, ber, color=c[j], marker=s[j], lw=0, label="%d-QAM" % M) ax2.plot(snrf, theory.ser_vs_es_over_n0_qam(10**(snrf / 10), M), color=c[j],
methods=("mcma", "sbd"), adaptive_stepsize=(True, True)) E_s, wxy_s, (err_s, err_rde_s) = equalisation.dual_mode_equalisation( SS, (muCMA, muRDE), ntaps, TrSyms=(Ncma, Nrde), methods=("mcma", "sbd"), adaptive_stepsize=(True, True)) E, wxy, (err, err_rde) = equalisation.dual_mode_equalisation( SS, (muCMA, muRDE), ntaps, TrSyms=(Ncma, Nrde), methods=("mcma", "mddma"), adaptive_stepsize=(True, True)) E = helpers.normalise_and_center(E) E_s = helpers.normalise_and_center(E_s) E_m = helpers.normalise_and_center(E_m) evm = sig[:, ::2].cal_evm() evmE = E.cal_evm() evmE_m = E_m.cal_evm() evmE_s = E_s.cal_evm() gmiE = E.cal_gmi() print(gmiE) plt.figure() plt.subplot(241) plt.title('Recovered MCMA/MDDMA') plt.hexbin(E[0].real, E[0].imag, label=r"$EVM_x=%.1f\%%$" % (evmE[0] * 100)) plt.legend() plt.subplot(242)
pilot_ins_ratio=sig_tx._pilot_ins_rat, mu=(1e-3, 1e-3), cpe_average=cpe_avg, foe_comp=True) # Calculate GMI and BER #ber_res = np.zeros(npols) #sout = signal.recreate_from_np_array(np.array(dsp_out[1])) #for l in range(npols): #gmi_res[l] = signal.cal_gmi(dsp_out[1][:])[0][0] #ber_res[l] = signal.cal_ber(np.vstackdsp_out[1][l]) #gmi_res = sout.cal_gmi()[0] #ber_res = sout.cal_ber() #dsp_out0 = dsp_out return dsp_out, dsp_out0, sig_tx, phase, phase0, signal, dsp_out2, dsp_out20, tall1, tall2 #return dsp_out, signal if __name__ == "__main__": #gmi, ber = sim_pilo print(methods)t_txrx(20) dsp, dsp1, sig, ph, ph2, sign, sig2, sig3, t1, t2 = sim_pilot_txrx( 30, laser_lw=100e3, freq_off=50e6) sigo = dsp #sigo = sign.symbols.recreate_from_np_array(dsp) sigo1 = sign.recreate_from_np_array(dsp1) sigo = helpers.normalise_and_center(sigo) sigo1 = helpers.normalise_and_center(sigo1) print(sigo.cal_gmi()) print(sigo1.cal_gmi(signal_rx=sigo1))
def sim_tx(frame, os, num_frames=5, modal_delay=None, beta=0.1, snr=None, symb_rate=24e9, freqoff=None, linewidth=None, rot_angle=None, resBits_tx=None, resBits_rx=None): """ Function to simulate transmission distortions to pilot frame """ npols = frame.shape[0] #sig = np.zeros([npols, int(num_frames*(frame[0, :]).shape[0] * os)], dtype=complex) sig = frame for l in range(npols): #curr_frame = np.tile(frame[l, :],num_frames) # Add modal delays, this can be used to emulate things like fake-pol. mux. when the frames are not aligned. if modal_delay is not None: if np.array(modal_delay).shape[0] != npols: raise ValueError( "Number of rolls has to match number of modes!") sig = np.roll(sig, modal_delay[l]) # Upsample and pulse shaping #if os > 1: # sig[l, :] = resample.rrcos_resample(curr_frame, 1, os, beta=beta, renormalise=True) # DAC if resBits_tx is not None: sig[l, :] = impairments.quantize_signal(sig[l, :], nbits=resBits_tx) # Add AWGN if snr is not None: sig[l, :] = impairments.add_awgn(sig[l, :], 10**(-snr / 20) * np.sqrt(os)) # Add FOE if freqoff is not None: sig[l, :] *= np.exp(2.j * np.pi * np.arange(len(sig[l, :])) * freqoff / (symb_rate * os)) # Add Phase Noise if linewidth is not None: sig[l, :] = impairments.apply_phase_noise(sig[l, :], linewidth, symb_rate * os) # Verfy normalization sig = helpers.normalise_and_center(sig) # Currently only implemented for DP signals. if (npols == 2) and (rot_angle is not None): sig = utils.rotate_field(sig, rot_angle) if resBits_rx is not None: for l in range(npols): sig[l, :] = impairments.quantize_signal(sig[l, :], nbits=resBits_rx) return sig
muRDE = 6e-4 Ncma = 100000 Nrde = 300000 ntaps = 51 niter = 1 symbs = io.load_symbols_from_matlab_file( "data/20GBaud_SRRC0P05_64QAM_PRBS15.mat", 64, (("X_Symbs", ), ), fb=20e9, normalise=True, fake_polmux=True) sig = io.create_signal_from_matlab( symbs, "data/OSNRLoading_IdealRxLaser_1544p91_Att_1_OSNR_38_1.mat", 50e9, (("CH1", "CH2"), ("CH3", "CH4"))) sig = sig[:, :10**6] sig = helpers.normalise_and_center(sig) sig = sig.resample(2 * symbs.fb, beta=0.05, renormalise=True) #sig = analog_frontend.comp_IQ_inbalance(sig) E, wxy, err_both = equalisation.dual_mode_equalisation( sig, (muCMA, muRDE), ntaps, Niter=(niter, niter), methods=("mcma", "sbd"), adaptive_stepsize=(True, True)) #E, wxy, err = equalisation.equalise_signal(sig, muCMA, Ntaps=33, apply=True) E = helpers.normalise_and_center(E) gmi = E.cal_gmi() print(gmi) #sys.exit()