def equalize_pilot_sequence(rx_signal, ref_symbs, shift_fctrs, os, foe_comp=False, mu=(1e-4, 1e-4), M_pilot=4, Ntaps=45, Niter=30, adaptive_stepsize=True, methods=('cma', 'cma'), wxinit=None): """ Equalise a pilot signal using the pilot sequence, with a two step equalisation. Parameters ---------- rx_signal : array_like The received signal containing the pilots ref_symbs : array_like The reference symbols or pilot sequence shift_fctrs : array_like The indices where the pilot_sequence starts, typically this would come from the framesync. os : int Oversampling ratio foe_comp : bool, optional Whether to perform a foe inside the pilot equalisation. If yes we will first perform equalisation using methods[0], then do a pilot frequency recovery and then perform equalisation again. This can yield slightly higher performance. Currently this uses the average offset frequency of all modes. mu : tuple(float,float), optional Equalisaer steps sizes for methods[0] and methods[1] M_pilot : int, optional The QAM order of the pilots. By default we assume QPSK symbols Ntaps : int, optional The number of equalisation taps Niter : int, optional The number of iterations to do over the pilot sequence when training the filter adaptive_stepsize : bool, optional Whether to use an adapative step-size algorithm in the equaliser. Generally, you want to leave this one, because it allows for much shorter sequences. methods : tuple(string,string) The two methods to use in the equaliser wxinit : array_like, optional Filtertaps for initialisation of the filter. By default we generate typical filter taps. Returns ------- out_taps : array_like Trained filter taps foe : array_like Offset frequency. Has the same number of modes as the signal, however is a single value only. If foe_comp was false, this are simply ones. """ # Inital settings rx_signal = np.atleast_2d(rx_signal) ref_symbs = np.atleast_2d(ref_symbs) npols = rx_signal.shape[0] pilot_seq_len = ref_symbs.shape[-1] wx = wxinit if methods[0] in equalisation.REAL_VALUED: if methods[1] not in equalisation.REAL_VALUED: raise ValueError( "Using a complex and real-valued equalisation method is not supported" ) elif methods[1] in equalisation.REAL_VALUED: raise ValueError( "Using a complex and real-valued equalisation method is not supported" ) if np.unique(shift_fctrs).shape[0] > 1: syms_out = [] syms_out = np.zeros_like(ref_symbs) for i in range(npols): rx_sig_mode = rx_signal[:, shift_fctrs[i]:shift_fctrs[i] + pilot_seq_len * os + Ntaps - 1] syms_out[i], wx, err = equalisation.equalise_signal( rx_sig_mode, os, mu[0], M_pilot, wxy=wx, Ntaps=Ntaps, Niter=Niter, method=methods[0], adaptive_stepsize=adaptive_stepsize, apply=True, modes=[i]) else: rx_sig_mode = rx_signal[:, shift_fctrs[0]:shift_fctrs[0] + pilot_seq_len * os + Ntaps - 1] syms_out, wx, err = equalisation.equalise_signal( rx_sig_mode, os, mu[0], M_pilot, wxy=wxinit, Ntaps=Ntaps, Niter=Niter, method=methods[0], adaptive_stepsize=adaptive_stepsize, apply=True) # Run FOE and shift spectrum if foe_comp: foe, foePerMode, cond = pilot_based_foe(syms_out, ref_symbs) foe_all = np.ones(foePerMode.shape) * foe else: foe_all = np.zeros([npols, 1]) out_taps = wx.copy() if np.unique(shift_fctrs).shape[0] > 1: for i in range(npols): rx_sig_mode = rx_signal[:, shift_fctrs[i]:shift_fctrs[i] + pilot_seq_len * os + Ntaps - 1] if foe_comp: # it's much faster to do the foe just on the extracted part rx_sig_mode = phaserecovery.comp_freq_offset( rx_sig_mode, np.ones(foePerMode.shape) * foe, os=os) out_taps, err = equalisation.equalise_signal( rx_sig_mode, os, mu[0], M_pilot, wxy=out_taps, Ntaps=Ntaps, Niter=Niter, method=methods[0], adaptive_stepsize=adaptive_stepsize, modes=[i], symbols=ref_symbs, apply=False) out_taps, err = equalisation.equalise_signal( rx_sig_mode, os, mu[1], 4, wxy=out_taps, Ntaps=Ntaps, Niter=Niter, method=methods[1], adaptive_stepsize=adaptive_stepsize, modes=[i], symbols=ref_symbs, apply=False) else: rx_sig_mode = rx_signal[:, shift_fctrs[0]:shift_fctrs[0] + pilot_seq_len * os + Ntaps - 1] if foe_comp: rx_sig_mode = phaserecovery.comp_freq_offset( rx_sig_mode, np.ones(foePerMode.shape) * foe, os=os) out_taps, err = equalisation.equalise_signal( rx_sig_mode, os, mu[0], M_pilot, wxy=out_taps, Ntaps=Ntaps, Niter=Niter, method=methods[0], adaptive_stepsize=adaptive_stepsize, symbols=ref_symbs, apply=False) out_taps, err = equalisation.equalise_signal( rx_sig_mode, os, mu[1], M_pilot, wxy=out_taps, Niter=Niter, method=methods[1], adaptive_stepsize=adaptive_stepsize, symbols=ref_symbs, apply=False) return np.array(out_taps), foe_all
def run_pilot_receiver(rec_signal, process_frame_id=0, foe_comp=True, os=2, M=128, Numtaps=(17, 45), frame_length=2**16, method=('cma', 'cma'), pilot_seq_len=512, pilot_ins_ratio=32, Niter=(10, 30), mu=(1e-3, 1e-3), adap_step=(True, True), cpe_average=5, use_cpe_pilot_ratio=1, remove_inital_cpe_output=True, remove_phase_pilots=True): ref_symbs = rec_signal.pilot_seq nmodes = rec_signal.shape[0] # Frame sync, locate first frame shift_factor, corse_foe, mode_alignment, wx1 = pilotbased_receiver.frame_sync( rec_signal, ref_symbs, os, frame_len=frame_length, mu=mu[0], method=method[0], Ntaps=Numtaps[0], adaptive_stepsize=adap_step[0]) # Redistribute pilots according to found modes pilot_symbs = rec_signal.pilots[mode_alignment, :] ref_symbs = ref_symbs[mode_alignment, :] # taps cause offset on shift factors shift_factor = pilotbased_receiver.correct_shifts(shift_factor, Numtaps, os) # shift so that modes are offset from minimum mode minimum mode is align with the frame rec_signal = np.roll(rec_signal, -shift_factor[shift_factor >= 0].min(), axis=-1) shift_factor -= shift_factor[shift_factor >= 0].min() # Converge equalizer using the pilot sequence taps_all = [] foe_all = [] if np.all(shift_factor == 0): taps_all, foe_all = pilotbased_receiver.equalize_pilot_sequence( rec_signal, ref_symbs, os, foe_comp=foe_comp, mu=mu, Ntaps=Numtaps[1], Niter=Niter[1], adaptive_stepsize=adap_step[1], methods=method) else: for i in range(nmodes): rec_signal2 = np.roll(rec_signal, -shift_factor[i], axis=-1) taps, foePerMode = pilotbased_receiver.equalize_pilot_sequence( rec_signal2, ref_symbs, os, foe_comp=foe_comp, mu=mu, Ntaps=Numtaps[1], Niter=Niter[1], adaptive_stepsize=adap_step[1], methods=method) taps_all.append(taps[i]) foe_all.append(foePerMode[i]) if foe_comp: out_sig = phaserecovery.comp_freq_offset(rec_signal, np.array(foe_all), os=os) out_sig = rec_signal.recreate_from_np_array(out_sig) else: out_sig = rec_signal eq_mode_sig1 = pilotbased_receiver.shift_signal(out_sig, shift_factor) eq_mode_sig = equalisation.apply_filter(eq_mode_sig1, os, np.array(taps_all)) eq_mode_sig = rec_signal.recreate_from_np_array(eq_mode_sig) symbs, trace = pilotbased_receiver.pilot_based_cpe( eq_mode_sig[:, pilot_seq_len:frame_length], pilot_symbs[:, pilot_seq_len:], pilot_ins_ratio, use_pilot_ratio=use_cpe_pilot_ratio, num_average=cpe_average, remove_phase_pilots=True) #symbs = eq_mode_sig #trace = pilotbased_receiver.pilot_based_cpe2(eq_mode_sig, eq_mode_sig.pilots, #use_pilot_ratio=use_cpe_pilot_ratio, num_average=cpe_average) return np.array(symbs), trace, eq_mode_sig1, taps_all
def equalize_pilot_sequence(rx_signal, ref_symbs, shift_fctrs, os, foe_comp=False, mu=(1e-4, 1e-4), M_pilot=4, Ntaps=45, Niter=30, adaptive_stepsize=True, methods=('cma', 'cma')): # TODO fix for syncing correctly """ """ # Inital settings rx_signal = np.atleast_2d(rx_signal) ref_symbs = np.atleast_2d(ref_symbs) npols = rx_signal.shape[0] pilot_seq_len = ref_symbs.shape[-1] if np.unique(shift_fctrs).shape[0] > 1: syms_out = [] for i in range(npols): rx_sig_mode = rx_signal[:, shift_fctrs[i]:shift_fctrs[i] + pilot_seq_len * os + Ntaps - 1] syms_out_tmp, wx, err = equalisation.equalise_signal( rx_sig_mode, os, mu[0], M_pilot, Ntaps=Ntaps, Niter=Niter, method=methods[0], adaptive_stepsize=adaptive_stepsize, apply=True, selected_modes=[i]) syms_out.append(syms_out_tmp) else: rx_sig_mode = rx_signal[:, shift_fctrs[0]:shift_fctrs[0] + pilot_seq_len * os + Ntaps - 1] syms_out, wx, err = equalisation.equalise_signal( rx_sig_mode, os, mu[0], M_pilot, Ntaps=Ntaps, Niter=Niter, method=methods[0], adaptive_stepsize=adaptive_stepsize, apply=True) # Run FOE and shift spectrum if foe_comp: foe, foePerMode, cond = pilot_based_foe(syms_out, ref_symbs) rx_signal = phaserecovery.comp_freq_offset(rx_signal, np.ones(foePerMode.shape) * foe, os=os) else: foePerMode = np.zeros([npols, 1]) if np.unique(shift_fctrs).shape[0] > 1: out_taps = [] for i in range(npols): rx_sig_mode = rx_signal[:, shift_fctrs[i]:shift_fctrs[i] + pilot_seq_len * os + Ntaps - 1] tmp_taps, err = equalisation.dual_mode_equalisation( rx_sig_mode, os, mu, 4, Ntaps=Ntaps, Niter=(Niter, Niter), methods=methods, adaptive_stepsize=(adaptive_stepsize, adaptive_stepsize), selected_modes=[i], symbols=ref_symbs, apply=False) out_taps.append(tmp_taps) else: rx_sig_mode = rx_signal[:, shift_fctrs[0]:shift_fctrs[0] + pilot_seq_len * os + Ntaps - 1] out_taps, err = equalisation.dual_mode_equalisation( rx_sig_mode, os, mu, 4, Ntaps=Ntaps, Niter=(Niter, Niter), methods=methods, adaptive_stepsize=(adaptive_stepsize, adaptive_stepsize), symbols=ref_symbs, apply=False) return out_taps, foePerMode
def frame_sync(rx_signal, ref_symbs, os, frame_len=2**16, M_pilot=4, mu=1e-3, Ntaps=17, **eqargs): """ Locate the pilot sequence frame Uses a CMA-based search scheme to located the initiial pilot sequence in the long data frame. Parameters ---------- rx_signal: array_like Received Rx signal ref_symbs: array_like Pilot sequence os: int Oversampling factor frame_len: int Total frame length including pilots and payload M_pilot: int, optional QAM-order for pilot symbols mu: float, optional CMA step size Ntaps: int, optional number of taps to use in the equaliser **eqargs: arguments to be passed to equaliser Returns ------- shift_factor: array_like location of frame start index per polarization foe_corse: array_like corse frequency offset mode_sync_order: array_like Synced descrambled reference pattern order """ # If synchronization fails, then change sync_bool to 'False' sync_bool = True FRAME_SYNC_THRS = 120 # this is somewhat arbitrary but seems to work well rx_signal = np.atleast_2d(rx_signal) ref_symbs = np.atleast_2d(ref_symbs) pilot_seq_len = ref_symbs.shape[-1] nmodes = rx_signal.shape[0] assert rx_signal.shape[-1] >= ( frame_len + 2 * pilot_seq_len) * os, "Signal must be at least as long as frame" if "method" in eqargs.keys(): if eqargs["method"] in equalisation.REAL_VALUED: if np.iscomplexobj(rx_signal): raise ValueError("Equaliser method is {}, but using a real-valued equaliser in frame sync is unsupported"\ .format(eqargs["method"])) elif eqargs["method"] in equalisation.DATA_AIDED: raise ValueError("Equaliser method is {}, but using a data-aided equaliser in frame sync is unsupported"\ .format(eqargs["method"])) mode_sync_order = np.zeros(nmodes, dtype=int) not_found_modes = np.arange(0, nmodes) search_overlap = 2 # fraction of pilot_sequence to overlap search_window = pilot_seq_len * os step = search_window // search_overlap # we only need to search the length of one frame*os plus some buffer (the extra step) num_steps = (frame_len * os) // step + 1 # Now search for every mode independent shift_factor = np.zeros(nmodes, dtype=int) # Search based on equalizer error. Avoid one pilot_seq_len part in the beginning and # end to ensure that sufficient symbols can be used for the search sub_vars = np.ones((nmodes, num_steps)) * 1e2 wxys = np.zeros((num_steps, nmodes, nmodes, Ntaps), dtype=rx_signal.dtype) for i in np.arange(search_overlap, num_steps): # we avoid one step at the beginning tmp = rx_signal[:, i * step:i * step + search_window] wxy, err_out = equalisation.equalise_signal(tmp, os, mu, M_pilot, Ntaps=Ntaps, **eqargs) wxys[i] = wxy sub_vars[:, i] = np.var(err_out, axis=-1) # Lowest variance of the CMA error for each pol min_range = np.argmin(sub_vars, axis=-1) wxy = wxys[min_range] for l in range(nmodes): idx_min = min_range[l] # Extract a longer sequence to ensure that the complete pilot sequence is found longSeq = rx_signal[:, (idx_min) * step - search_window:(idx_min) * step + search_window] # Apply filter taps to the long sequence and remove coarse FO wx1 = wxy[l] symbs_out = equalisation.apply_filter(longSeq, os, wx1) foe_corse = phaserecovery.find_freq_offset(symbs_out) symbs_out = phaserecovery.comp_freq_offset(symbs_out, foe_corse) # Check for pi/2 ambiguties and verify all max_phase_rot = np.zeros(nmodes, dtype=np.float64) found_delay = np.zeros(nmodes, dtype=np.int) for ref_pol in not_found_modes: ix, dat, ii, ac = ber_functions.find_sequence_offset_complex( ref_symbs[ref_pol], symbs_out[l]) found_delay[ref_pol] = -ix max_phase_rot[ref_pol] = ac # Check for which mode found and extract the reference delay max_sync_pol = np.argmax(max_phase_rot) if max_phase_rot[max_sync_pol] < FRAME_SYNC_THRS: # warnings.warn( "Very low autocorrelation, likely the frame-sync failed") sync_bool = False mode_sync_order[l] = max_sync_pol symb_delay = found_delay[max_sync_pol] # Remove the found reference mode not_found_modes = not_found_modes[not_found_modes != max_sync_pol] # New starting sample shift_factor[l] = (idx_min) * step + os * symb_delay - search_window # Important: the shift factors are arranged in the order of the signal modes, but # the mode_sync_order specifies how the signal modes need to be rearranged to match the pilots # therefore shift factors also need to be "mode_aligned" return shift_factor, foe_corse, mode_sync_order, wx1, sync_bool
def test_comp_freq_offset(self): s = signals.SignalQAMGrayCoded(16, 2 ** 16, fb=20e9, nmodes=1) ph = np.ones(1)*1e6 s2 = cphaserecovery.comp_freq_offset(s.flatten(), ph) assert 2**16 == s2.shape[0]
def test_comp_freq_offset(self, ndim): s = signals.SignalQAMGrayCoded(16, 2 ** 16, fb=20e9, nmodes=ndim) ph = np.ones(ndim)*1e6 s2 = cphaserecovery.comp_freq_offset(s, ph) assert ndim == s2.shape[0]
def equalize_pilot_sequence(rx_signal, ref_symbs, shift_factor, os, sh = False, process_frame_id = 0, frame_length = 2**16, mu = (1e-4,1e-4), M_pilot = 4, ntaps = (25,45), Niter = (10,30), adap_step = (True,True), method=('cma','cma'),avg_foe_modes = True, do_pilot_based_foe=True,foe_symbs = None,blind_foe_payload=False): # Inital settings rx_signal = np.atleast_2d(rx_signal) ref_symbs = np.atleast_2d(ref_symbs) npols = rx_signal.shape[0] pilot_seq_len = len(ref_symbs[0,:]) eq_pilots = np.zeros([npols,pilot_seq_len],dtype = complex) tmp_pilots = np.zeros([npols,pilot_seq_len],dtype = complex) out_taps = [] # Tap update and extract the propper pilot sequuence if not((ntaps[1]-ntaps[0])%os == 0): raise ValueError("Taps for search and convergence impropper configured") tap_cor = int((ntaps[1]-ntaps[0])/2) # Run FOE and shift spectrum if not sh: # First Eq, extract pilot sequence to do FOE for l in range(npols): pilot_seq = rx_signal[:,shift_factor[l]-tap_cor:shift_factor[l]-tap_cor+pilot_seq_len*os+ntaps[1]-1] wx, err = equalisation.equalise_signal(pilot_seq, os, mu[0], M_pilot,Ntaps = ntaps[1], Niter = Niter[1], method = method[0],adaptive_stepsize = adap_step[1]) # wx, err = equalisation.equalise_signal(pilot_seq, os, mu[1], M_pilot, wxy = wx, Ntaps=ntaps[1], Niter=Niter[1], # method=method[0], adaptive_stepsize=adap_step[1]) symbs_out= equalisation.apply_filter(pilot_seq,os,wx) tmp_pilots[l,:] = symbs_out[l,:] # FOE Estimation, several options available. Default is pilot aided if do_pilot_based_foe: # Use the pilot-based FOE. Requires a pilot sequence of sufficient length if foe_symbs is None: foe, foePerMode, cond = pilot_based_foe(tmp_pilots, ref_symbs) else: num_symbs = int(foe_symbs) if num_symbs > pilot_seq_len: raise ValueError("Required number of symbols for FOE is larger than availabe sequence length. Maximum length available is %d"%pilot_seq_len) foe, foePerMode, cond = pilot_based_foe(tmp_pilots[:,:num_symbs], ref_symbs[:,:num_symbs]) # Equalize 1 frame and do blind 4:th power FFT-based estimation else: foe_est_symbs = np.zeros([npols, frame_length],dtype=complex) for l in range(npols): # If blind_foe_payload is true, use the payload for FOE estimation and not the pilot sequence. Aims at comparing blind power of 4 FOE to pilot-based if blind_foe_payload: est_sig = rx_signal[:, shift_factor[l] - tap_cor + pilot_seq_len*os:shift_factor[l] - tap_cor + frame_length * os + ntaps[1] - 1 + pilot_seq_len*os] else: est_sig = rx_signal[:,shift_factor[l]-tap_cor:shift_factor[l]-tap_cor+frame_length*os+ntaps[1]-1] est_frame = equalisation.apply_filter(est_sig,os,wx) foe_est_symbs[l,:] = est_frame[l,:] if foe_symbs is None: foePerMode = phaserecovery.find_freq_offset(foe_est_symbs) else: foePerMode = phaserecovery.find_freq_offset(foe_est_symbs[:, :foe_symbs], fft_size=foe_symbs) if avg_foe_modes: foe = np.mean(foePerMode) foePerMode = np.ones(foePerMode.shape)*foe # Apply FO-compensation sig_dc_center = phaserecovery.comp_freq_offset(rx_signal, foePerMode, os=os) else: # Signal should be DC-centered. Do nothing. sig_dc_center = rx_signal foePerMode = np.zeros([npols,1]) # First step Eq for l in range(npols): pilot_seq = sig_dc_center[:,shift_factor[l]-tap_cor:+shift_factor[l]-tap_cor+pilot_seq_len*os+ntaps[1]-1] wxy_init, err = equalisation.equalise_signal(pilot_seq, os, mu[1], 4, Ntaps = ntaps[1], Niter = Niter[1], method = method[0],adaptive_stepsize = adap_step[1]) wx, err = equalisation.equalise_signal(pilot_seq, os, mu[1], 4,wxy=wxy_init,Ntaps = ntaps[1], Niter = Niter[1], method = method[1],adaptive_stepsize = adap_step[1]) out_taps.append(wx) symbs_out = equalisation.apply_filter(pilot_seq,os,out_taps[l]) eq_pilots[l,:] = symbs_out[l,:] # Equalize using additional frames if selected for frame_id in range(0,process_frame_id+1): for l in range(npols): pilot_seq = sig_dc_center[:,frame_length*os*frame_id+shift_factor[l]-tap_cor:frame_length*os*frame_id+shift_factor[l]-tap_cor+pilot_seq_len*os+ntaps[1]-1] wx_1, err = equalisation.equalise_signal(pilot_seq, os, mu[1], 4,wxy=out_taps[l],Ntaps = ntaps[1], Niter = Niter[1], method = method[1],adaptive_stepsize = adap_step[1]) wx, err = equalisation.equalise_signal(pilot_seq, os, mu[1], 4,wxy=wx_1,Ntaps = ntaps[1], Niter = Niter[1], method = method[1],adaptive_stepsize = adap_step[1]) out_taps[l] = wx if frame_id == process_frame_id: symbs_out = equalisation.apply_filter(pilot_seq,os,out_taps[l]) eq_pilots[l,:] = symbs_out[l,:] shift_factor[l] = shift_factor[l] + process_frame_id*os*frame_length return eq_pilots, foePerMode, out_taps, shift_factor
def frame_sync(rx_signal, ref_symbs, os, frame_length = 2**16, mu = 1e-3, M_pilot = 4, ntaps = 25, Niter = 10, adap_step = True, method='cma' ,search_overlap = 2): """ Locate and extract the pilot starting frame. Uses a CMA-based search scheme to located the initiial pilot sequence in the long data frame. Input: rx_signal: Received Rx signal ref_symbs: Pilot sequence os: Oversampling frame_length: Total frame length including pilots and payload mu: CMA step size. Tuple(Search, Convergence) M_pilot: Order for pilot symbols. Should normally be QPSK and M=4 ntaps: Number of T/2-spaced taps for equalization Niter: Number of iterations for the equalizer.Tuple(Search, Convergence) adap_step: Use adaptive step size (bool). Tuple(Search, Convergence) method: Equalizer mehtods to be used. Tuple(Search, Convergence) search_overlap: Overlap of subsequences in the test Output: eq_pilots: Found pilot sequence after equalization shift_factor: New starting point for initial equalization out_taps: Taps for equalization of the whole signal foe_course: Result of blind FOE used to sync the pilot sequence. """ # Inital settings rx_signal = np.atleast_2d(rx_signal) ref_symbs = np.atleast_2d(ref_symbs) npols = rx_signal.shape[0] # Find the length of the pilot frame pilot_seq_len = len(ref_symbs[0,:]) symb_step_size = int(np.floor(pilot_seq_len * os / search_overlap)) # Adapt signal length sig_len = (np.shape(rx_signal)[1]) if (sig_len > (frame_length + (search_overlap*2 + 5)*pilot_seq_len)*os): num_steps = int(np.ceil(((frame_length + (search_overlap*2 + 5) *pilot_seq_len)*os)/symb_step_size)) else: num_steps = int(np.ceil(np.shape(rx_signal)[1] / symb_step_size)) # Now search for every mode independent shift_factor = np.zeros(npols,dtype = int) for l in range(npols): # Search based on equalizer error. Avoid certain part in the beginning and # end to ensure that sufficient symbols can be used for the search sub_var = np.ones(num_steps)*1e2 for i in np.arange(2+(search_overlap),num_steps-3-(search_overlap)): err_out = equalisation.equalise_signal(rx_signal[:,(i)*symb_step_size:(i+1+(search_overlap-1))*symb_step_size], os, mu, M_pilot,Ntaps = ntaps, Niter = Niter, method = method,adaptive_stepsize = adap_step)[1] sub_var[i] = np.var(err_out[l,int(-symb_step_size/os+ntaps):]) # Lowest variance of the CMA error minPart = np.argmin(sub_var) # Corresponding sequence shortSeq = rx_signal[:,(minPart)*symb_step_size:(minPart+1+(search_overlap-1))*symb_step_size] # Extract a longer sequence to ensure that the complete pilot sequence is found longSeq = rx_signal[:,(minPart-2-search_overlap)*symb_step_size:(minPart+3+search_overlap)*symb_step_size] # Use the first estimate to get rid of any large FO and simplify alignment wx1, err = equalisation.equalise_signal(shortSeq, os, mu, M_pilot,Ntaps = ntaps, Niter = Niter, method = method,adaptive_stepsize = adap_step) seq_foe = equalisation.apply_filter(longSeq,os,wx1) foe_corse = phaserecovery.find_freq_offset(seq_foe) # Apply filter taps to the long sequence symbs_out= equalisation.apply_filter(longSeq,os,wx1) symbs_out[l,:] = phaserecovery.comp_freq_offset(symbs_out[l, :], foe_corse[l, :]) # Check for pi/2 ambiguties max_phase_rot = np.zeros([4]) found_delay = np.zeros([4]) for k in range(4): # Find correlation for all 4 possible pi/2 rotations xcov = np.correlate(np.angle(symbs_out[l,:]*1j**k),np.angle(ref_symbs[l,:])) max_phase_rot[k] = np.max(xcov) found_delay[k] = np.argmax(xcov) # Select the best one symb_delay = int(found_delay[np.argmax(max_phase_rot)]) # New starting sample shift_factor[l] = int((minPart-4)*symb_step_size + os*symb_delay) return shift_factor, foe_corse
print(Y.shape) SS = np.vstack([X[5000:-5000],Y[5000:-5000]]) SS = SS[:,:int(2e5)] E, wxy, err_both = equalisation.dual_mode_equalisation(SS, os, M, ntaps, Niter=(5, 5), methods=("mcma", "sbd"), adaptive_stepsize=(True, True)) X = signal_quality.norm_to_s0(E[0, :], M) Y = signal_quality.norm_to_s0(E[1, :], M) E = np.vstack([X,Y]) foe = phaserecovery.find_freq_offset(E, fft_size =2 ** 10) E = phaserecovery.comp_freq_offset(E, foe) #Ec = E[:,2e4:-2e4] wx, err_both = equalisation.equalise_signal(E, 1, M, Ntaps=ntaps, Niter=4, method="sbd", adaptive_stepsize=False) Ec = equalisation.apply_filter(E, 1, wx) E = Ec print("X pol phase") Ex, phx = phaserecovery.bps(E[0], 32, QAM.symbols, 8) print("X pol phase done") print("Y pol phase") Ey, phy = phaserecovery.bps(E[1], 32, QAM.symbols, 8) print("Y pol phase done") Ec = np.vstack([Ex,Ey])