def compute_legacy(hdf5): ''' Parse and plot data from legacy files ''' print("starting legacy function") starttime = time.time() show_plots = True zoom = 0 # samples to zoom in around frame (to look at local behavior), 0 to disable pl = 0 # static = h5py.File('ArgosCSI-96x8-2016-11-03-03-03-45_5GHz_static.hdf5', 'r') #h5py.File('logs/ArgosCSI-76x2-2017-02-07-18-25-47.hdf5','r') # static = h5py.File('trace-2020-5-26-15-27-29_1x8x3.hdf5','r') # h5py.File('logs/ArgosCSI-76x2-2017-02-07-18-25-47.hdf5','r') # env = h5py.File('logs/ArgosCSI-76x2-2017-02-07-18-25-47.hdf5','r') # mobile = h5py.File('logs/ArgosCSI-76x2-2017-02-07-18-25-47.hdf5','r') frame = 10 # frame to compute beamweights from conjdata = [] zfdata = [] # print("main checkpoint1 time expended %f" % (starttime - time.time())) for h5log in [hdf5]: # , env, mobile]: # read parameters for this measurement data samps_per_user = h5log.attrs['samples_per_user'] num_users = h5log.attrs['num_mob_ant'] timestep = h5log.attrs['frame_length'] / 20e6 noise_meas_en = h5log.attrs.get('measured_noise', 1) # compute CSI for each user and get a nice numpy array csi, iq = hdf5_lib.samps2csi( h5log['Pilot_Samples'], num_users + noise_meas_en, samps_per_user, legacy=True ) # Returns csi with Frame, User, LTS (there are 2), BS ant, Subcarrier #also, iq samples nicely chunked out, same dims, but subcarrier is sample. if zoom > 0: # zoom in too look at behavior around peak (and reduce processing time) csi = csi[frame - zoom:frame + zoom, :, :, :, :] frame = zoom # recenter the plots (otherwise it errors) noise = csi[:, -1, :, :, :] # noise is last set of data. userCSI = np.mean(csi[:, :num_users, :, :, :], 2) # don't include noise, average over both LTSs # example lts find: user = 0 # so, this is pretty ugly, but we want all the samples (not just those chunked from samps2csi), so we not only convert ints to the complex floats, but also have to figure out where to chunk the user from. lts_iq = h5log['Pilot_Samples'][frame, 0, user * samps_per_user:(user + 1) * samps_per_user, 0] * 1. + \ h5log['Pilot_Samples'][frame, 0, user * samps_per_user:(user + 1) * samps_per_user, 1] * 1j lts_iq /= 2**15 offset = lts.findLTS( lts_iq ) # Andrew wrote this, but I don't really like the way he did the convolve method... works well enough for high SNRs. offset = offset[0] + 32 print("LTS offset for user %d, frame %d: %d" % (user, frame, offset)) # compute beamweights based on the specified frame. conjbws = np.transpose(np.conj(userCSI[frame, :, :, :]), (1, 0, 2)) zfbws = np.empty( (userCSI.shape[2], userCSI.shape[1], userCSI.shape[3]), dtype='complex64') for sc in range(userCSI.shape[3]): zfbws[:, :, sc] = np.linalg.pinv(userCSI[frame, :, :, sc]) downlink = True # calculate capacity based on these weights # these return total capacity, per-user capacity, per-user/per-subcarrier capacity, SINR, single-user capacity(no inter-user interference), and SNR conj = calCapacity( userCSI, noise, conjbws, downlink=downlink ) # conjcap_total,conjcap_u,conjcap_sc,conjSINR,conjcap_su_sc,conjcap_su_u,conjSNR zf = calCapacity( userCSI, noise, zfbws, downlink=downlink ) # zfcap_total,zfcap_u,zfcap_sc,zfSINR,zfcap_su_sc,zfcap_su_u,zfSNR # print("main checkpoint2 time expended %f" % (starttime - time.time())) # plot stuff if show_plots: # Multiuser Conjugate plt.figure(1000 * pl, figsize=(50, 10)) plt.plot( np.arange(0, csi.shape[0] * timestep, timestep)[:csi.shape[0]], conj[1]) # plt.ylim([0,2]) plt.xlabel('Time (s)') plt.ylabel('Per User Capacity Conj (bps/Hz)') plt.show(block=False) # Multiuser Zeroforcing plt.figure(1000 * pl + 1, figsize=(50, 10)) plt.plot( np.arange(0, csi.shape[0] * timestep, timestep)[:csi.shape[0]], zf[1]) # plt.ylim([0,2]) plt.xlabel('Time (s)') plt.ylabel('Per User Capacity ZF (bps/Hz)') plt.show(block=False) # Single user (but show all users) plt.figure(1000 * pl + 2, figsize=(50, 10)) plt.plot( np.arange(0, csi.shape[0] * timestep, timestep)[:csi.shape[0]], conj[-2]) # plt.ylim([0,2]) plt.xlabel('Time (s)') plt.ylabel('SUBF Capacity Conj (bps/Hz)') plt.show(block=False) pl += 1 # print("main checkpoint3 time expended %f" % (starttime - time.time())) # save for exporting to matlab (prettier plots) conjdata.append(conj) zfdata.append(zf) # print("main checkpoint4 time expended %f" % (starttime - time.time())) del csi, iq # free the memory endtime = time.time() print("Total time: %f" % (endtime - starttime))
def analyze_hdf5(hdf5, frame=10, cell=0, zoom=0, pl=0): ''' Calculates and plots achievable rates from hdf5 traces ''' metadata = hdf5.metadata pilot_samples = hdf5.pilot_samples symbol_length = int(metadata['SYMBOL_LEN']) rate = float(metadata['RATE']) symbol_num = int(metadata['BS_FRAME_LEN']) timestep = symbol_length * symbol_num / rate num_cl = int(metadata['CL_NUM']) num_pilots = int(metadata['PILOT_NUM']) cp = int(metadata['CP_LEN']) prefix_len = int(metadata['PREFIX_LEN']) postfix_len = int(metadata['POSTFIX_LEN']) offset = prefix_len # compute CSI for each user and get a nice numpy array # Returns csi with Frame, User, LTS (there are 2), BS ant, Subcarrier #also, iq samples nicely chunked out, same dims, but subcarrier is sample. csi, _ = hdf5_lib.samps2csi(pilot_samples, num_pilots, symbol_length, offset=offset) csi = csi[:, cell, :, :, :, :] # zoom in too look at behavior around peak (and reduce processing time) if zoom > 0: csi = csi[frame - zoom:frame + zoom, :, :, :, :] # recenter the plots (otherwise it errors) frame = zoom noise = csi[:, -1, :, :, :] # noise is last set of data. # don't include noise, average over both LTSs userCSI = np.mean(csi[:, :num_cl, :, :, :], 2) # compute beamweights based on the specified frame. conjbws = np.transpose(np.conj(userCSI[frame, :, :, :]), (1, 0, 2)) zfbws = np.empty((userCSI.shape[2], userCSI.shape[1], userCSI.shape[3]), dtype='complex64') for sc in range(userCSI.shape[3]): zfbws[:, :, sc] = np.linalg.pinv(userCSI[frame, :, :, sc]) downlink = True # calculate capacity based on these weights # these return total capacity, per-user capacity, per-user/per-subcarrier capacity,.. # SINR, single-user capacity(no inter-user interference), and SNR # conjcap_total,conjcap_u,conjcap_sc,conjSINR,conjcap_su_sc,conjcap_su_u,conjSNR conj = calCapacity(userCSI, noise, conjbws, downlink=downlink) # zfcap_total,zfcap_u,zfcap_sc,zfSINR,zfcap_su_sc,zfcap_su_u,zfSNR zf = calCapacity(userCSI, noise, zfbws, downlink=downlink) _, demmel = calDemmel(userCSI) # plot stuff subf_conj = conj[-2] subf_zf = zf[-2] mubf_conj = conj[1] mubf_zf = zf[1] fig1, axes1 = plt.subplots(nrows=2, ncols=2, squeeze=False, figsize=(10, 8)) for j in range(2): axes1[0, 0].plot(np.arange(0, csi.shape[0] * timestep, timestep)[:csi.shape[0]], mubf_conj[:, j], label='Conj User: {}'.format(j)) for j in range(2): axes1[0, 1].plot(np.arange(0, csi.shape[0] * timestep, timestep)[:csi.shape[0]], mubf_zf[:, j], label='ZF User: {}'.format(j)) axes1[0, 0].legend(loc='upper right', ncol=1, frameon=False) axes1[0, 0].set_xlabel('Time (s)', fontsize=18) axes1[0, 0].set_ylabel('MUBF User Achievable Rate (bps/Hz)', fontsize=18) axes1[0, 1].legend(loc='upper right', ncol=1, frameon=False) axes1[0, 1].set_xlabel('Time (s)') for j in range(2): axes1[1, 0].plot(np.arange(0, csi.shape[0] * timestep, timestep)[:csi.shape[0]], subf_conj[:, j], label='Conj User: {}'.format(j)) for j in range(2): axes1[1, 1].plot(np.arange(0, csi.shape[0] * timestep, timestep)[:csi.shape[0]], subf_zf[:, j], label='ZF User: {}'.format(j)) axes1[1, 0].legend(loc='upper right', ncol=1, frameon=False) axes1[1, 0].set_xlabel('Time (s)', fontsize=18) axes1[1, 0].set_ylabel('SUBF User Achievable Rate (bps/Hz)', fontsize=18) axes1[1, 1].legend(loc='upper right', ncol=1, frameon=False) axes1[1, 1].set_xlabel('Time (s)') #axes1[1].set_ylabel('Per User Achievable Rate (bps/Hz)') # demmel number plt.figure(1000 * pl + 3, figsize=(10, 8)) plt.plot( np.arange(0, csi.shape[0] * timestep, timestep)[:csi.shape[0]], demmel[:, 7]) # plt.ylim([0,2]) plt.xlabel('Time (s)') plt.ylabel('Demmel condition number, Subcarrier 7') plt.show() pl += 1 del csi # free the memory
def verify_hdf5(hdf5, default_frame=100, ant_i=0, user_i=0, n_frm_st=0, thresh=0.001, deep_inspect=False, sub_sample=1): """ Plot data in file to verify contents. Input: default_frame: Index of frame to be plotted. Default to frame #100 """ plt.close("all") data = hdf5.data metadata = hdf5.metadata pilot_samples = hdf5.pilot_samples uplink_samples = hdf5.uplink_samples # Check which data we have available data_types_avail = [] pilots_avail = len(pilot_samples) > 0 ul_data_avail = len(uplink_samples) > 0 if pilots_avail: data_types_avail.append("PILOTS") print("PILOT Data Available") if ul_data_avail: data_types_avail.append("UL_DATA") print("Uplink Data Available") # Empty structure if not data_types_avail: raise Exception(' **** No pilots or uplink data found **** ') # Retrieve attributes symbol_length = int(metadata['SYMBOL_LEN']) num_pilots = int(metadata['PILOT_NUM']) num_cl = int(metadata['CL_NUM']) cp = int(metadata['CP_LEN']) prefix_len = int(metadata['PREFIX_LEN']) postfix_len = int(metadata['POSTFIX_LEN']) z_padding = prefix_len + postfix_len offset = int(prefix_len) fft_size = int(metadata['FFT_SIZE']) pilot_type = metadata['PILOT_SEQ_TYPE'].astype(str)[0] ofdm_pilot = np.array(metadata['OFDM_PILOT']) print( " symbol_length = {}, cp = {}, prefix_len = {}, postfix_len = {}, z_padding = {}" .format(symbol_length, cp, prefix_len, postfix_len, z_padding)) print( "******** verify_hdf5(): Calling filter_pilots and frame_sanity *********" ) n_ue = num_cl frm_plt = min(default_frame, pilot_samples.shape[0] + n_frm_st) if deep_inspect: filter_pilots_start = time.time() match_filt, k_lts, n_lts, cmpx_pilots, lts_seq_orig = hdf5_lib.filter_pilots( pilot_samples, z_padding, fft_size=fft_size, cp=cp) filter_pilots_end = time.time() frame_sanity_start = time.time() match_filt_clr, frame_map, f_st, peak_map = hdf5_lib.frame_sanity( match_filt, k_lts, n_lts, n_frm_st, frm_plt, plt_ant=ant_i, cp=cp) frame_sanity_end = time.time() print(">>>> filter_pilots time: %f \n" % (filter_pilots_end - filter_pilots_start)) print(">>>> frame_sanity time: %f \n" % (frame_sanity_end - frame_sanity_start)) # Find LTS peaks across frame n_frame = pilot_samples.shape[0] n_cell = pilot_samples.shape[1] n_ue = pilot_samples.shape[2] n_ant = pilot_samples.shape[3] seq_found = np.zeros((n_frame, n_cell, n_ue, n_ant)) num_pilots_per_sym = ((symbol_length - z_padding) // len(ofdm_pilot)) for frameIdx in range(n_frame): # Frame for cellIdx in range(n_cell): # Cell for ueIdx in range(n_ue): # UE for bsAntIdx in range(n_ant): # BS ANT I = pilot_samples[frameIdx, cellIdx, ueIdx, bsAntIdx, 0:symbol_length * 2:2] / 2**15 Q = pilot_samples[frameIdx, cellIdx, ueIdx, bsAntIdx, 1:symbol_length * 2:2] / 2**15 IQ = I + (Q * 1j) tx_pilot, lts_pks, lts_corr, pilot_thresh, best_pk = pilot_finder( IQ, pilot_type, flip=True, pilot_seq=ofdm_pilot) # Find percentage of LTS peaks within a symbol # (e.g., in a 4096-sample pilot symbol, we expect 64, 64-long sequences... assuming no CP) seq_found[frameIdx, cellIdx, ueIdx, bsAntIdx] = 100 * (lts_pks.size / num_pilots_per_sym) dbg2 = False if dbg2: fig = plt.figure(1234) ax1 = fig.add_subplot(2, 1, 1) ax1.plot(np.abs(IQ)) ax2 = fig.add_subplot(2, 1, 2) ax2.stem(np.abs(lts_corr)) ax2.scatter(np.linspace(0.0, len(lts_corr), num=1000), pilot_thresh * np.ones(1000), color='r') plt.show() # PLOTTER # Plot pilots or data or both fig, axes = plt.subplots(nrows=6, ncols=len(data_types_avail), squeeze=False, figsize=(10, 8)) for idx, ftype in enumerate(data_types_avail): if ftype == "PILOTS": axes[0, idx].set_title('PILOTS - Cell 0') samples = pilot_samples num_cl_tmp = num_pilots # number of UEs to plot data for elif ftype == "UL_DATA": axes[0, idx].set_title('UPLINK DATA - Cell 0') samples = uplink_samples num_cl_tmp = samples.shape[2] # number of UEs to plot data for # Compute CSI from IQ samples # Samps: #Frames, #Cell, #Users, #Antennas, #Samples # CSI: #Frames, #Cell, #Users, #Pilot Rep, #Antennas, #Subcarrier # For correlation use a fft size of 64 print( "*verify_hdf5(): Calling samps2csi with fft_size = {}, offset = {}, bound = cp = 0 *" .format(fft_size, offset)) csi, samps = hdf5_lib.samps2csi(samples, num_cl_tmp, symbol_length, fft_size=fft_size, offset=offset, bound=0, cp=cp, sub=sub_sample) # Correlation (Debug plot useful for checking sync) amps = np.mean(np.abs(samps[:, 0, user_i, 0, ant_i, :]), axis=1) pilot_frames = [i for i in range(len(amps)) if amps[i] > thresh] if len(pilot_frames) > 0: corr_ref_frame = pilot_frames[len(pilot_frames) // 2] else: print( "no valid frames where found. Decision threshold for amplitude was %f" % thresh) return cellCSI = csi[:, 0, :, :, :, :] # First cell userCSI = np.mean(cellCSI[:, :, :, :, :], 2) corr_total, sig_sc = calCorr( userCSI, np.transpose(np.conj(userCSI[corr_ref_frame, :, :, :]), (1, 0, 2))) # Compute CSI from IQ samples # Samps: #Frames, #Cell, #Users, #Pilot Rep, #Antennas, #Samples # CSI: #Frames, #Cell, #Users, #Pilot Rep, #Antennas, #Subcarrier # For looking at the whole picture, use a fft size of whole symbol_length as fft window (for visualization), # and no offset print( "*verify_hdf5():Calling samps2csi *AGAIN*(?) with fft_size = symbol_length, no offset*" ) csi, samps = hdf5_lib.samps2csi(samples, num_cl_tmp, symbol_length, fft_size=symbol_length, offset=0, bound=0, cp=0, sub=sub_sample) # Verify default_frame does not exceed max number of collected frames ref_frame = min(default_frame - n_frm_st, samps.shape[0]) ant_plt = ant_i user_plt = user_i # Plotter # Samps Dimensions: (Frame, Cell, User, Pilot Rep, Antenna, Sample) axes[0, idx].set_ylabel('Frame %d ant %d (Re)' % ((ref_frame + n_frm_st), ant_plt)) axes[0, idx].plot(np.real(samps[ref_frame, 0, user_plt, 0, ant_plt, :])) axes[1, idx].set_ylabel('Frame %d ant %d (Im)' % ((ref_frame + n_frm_st), ant_plt)) axes[1, idx].plot(np.imag(samps[ref_frame, 0, user_plt, 0, ant_plt, :])) axes[2, idx].set_ylabel('All Frames ant %d (Re)' % ant_plt) axes[2, idx].plot( np.real(samps[:, 0, user_plt, 0, ant_plt, :]).flatten()) axes[3, idx].set_ylabel('All Frames ant %d (Im)' % ant_plt) axes[3, idx].plot( np.imag(samps[:, 0, user_plt, 0, ant_plt, :]).flatten()) axes[4, idx].set_ylabel('Amplitude') for i in range(samps.shape[4]): axes[4, idx].plot( np.mean(np.abs(samps[:, 0, user_plt, 0, i, :]), axis=1).flatten()) axes[4, idx].set_xlabel('Sample') axes[5, idx].set_ylabel('Correlation with Frame %d' % corr_ref_frame) axes[5, idx].set_ylim([0, 1.1]) axes[5, idx].set_title('Cell %d offset %d' % (0, offset)) for u in range(num_cl_tmp): axes[5, idx].plot(corr_total[pilot_frames, u], label="user %d" % u) axes[5, idx].legend(loc='lower right', frameon=False) axes[5, idx].set_xlabel('Frame') if deep_inspect: #plots: print("Plotting the results:\n") n_cell = match_filt_clr.shape[1] n_ue = match_filt_clr.shape[2] # plot a frame: fig, axes = plt.subplots(nrows=n_cell, ncols=n_ue, squeeze=False) fig.suptitle('MF Frame # {} Antenna # {}'.format(ref_frame, ant_i)) for n_c in range(n_cell): for n_u in range(n_ue): axes[n_c, n_u].stem(match_filt_clr[ref_frame - hdf5.n_frm_st, n_c, n_u, ant_i, :]) axes[n_c, n_u].set_xlabel('Samples') axes[n_c, n_u].set_title('Cell {} UE {}'.format(n_c, n_u)) axes[n_c, n_u].grid(True) #plt.show() # plot frame_map: n_cell = frame_map.shape[1] n_ue = frame_map.shape[2] n_ant = frame_map.shape[3] # For some damm reason, if one of the subplots has all of the frames in the same state (good/bad/partial) # it chooses a random color to paint the whole subplot! # Below is some sort of remedy (will fail if SISO!): for n_c in range(n_cell): for n_u in range(n_ue): f_map = frame_map[:, n_c, n_u, :] n_gf = f_map[f_map == 1].size n_bf = f_map[f_map == -1].size n_pr = f_map[f_map == 0].size if n_gf == 0: frame_map[-1, n_c, n_u, -1] = 1 print( "No good frames! Colored the last frame of the last antenna Good for cell {} and UE {} to keep plotter happy!" .format(n_c, n_u)) if n_pr == 0: frame_map[0, n_c, n_u, -1] = 0 print( "No partial frames! Colored frame 0 of the last antenna for cell {} and UE {} Partial to keep plotter happy!" .format(n_c, n_u)) if n_bf == 0: frame_map[-1, n_c, n_u, 0] = -1 print( "No bad frames! Colored the last frame of antenna 0 Bad for cell {} and UE {} to keep plotter happy!" .format(n_c, n_u)) fig, axes = plt.subplots(nrows=n_ue, ncols=n_cell, squeeze=False) c = [] fig.suptitle('Frame Map') for n_c in range(n_cell): for n_u in range(n_ue): c.append(axes[n_u, n_c].imshow( frame_map[:, n_c, n_u, :].T, cmap=plt.cm.get_cmap('Blues', 3), interpolation='none', extent=[hdf5.n_frm_st, hdf5.n_frm_end, n_ant, 0], aspect="auto")) axes[n_u, n_c].set_title('Cell {} UE {}'.format(n_c, n_u)) axes[n_u, n_c].set_ylabel('Antenna #') axes[n_u, n_c].set_xlabel('Frame #') # Minor ticks axes[n_u, n_c].set_xticks(np.arange(hdf5.n_frm_st, hdf5.n_frm_end, 1), minor=True) axes[n_u, n_c].set_yticks(np.arange(0, n_ant, 1), minor=True) # Gridlines based on minor ticks axes[n_u, n_c].grid(which='minor', color='0.75', linestyle='-', linewidth=0.1) cbar = plt.colorbar(c[-1], ax=axes.ravel().tolist(), ticks=[-1, 0, 1], orientation='horizontal') cbar.ax.set_xticklabels( ['Bad Frame', 'Probably partial/corrupt', 'Good Frame']) #plt.show() #plot F starts for each antenna sub_fr_strt = f_st n_frame = sub_fr_strt.shape[0] # no. of captured frames n_cell = sub_fr_strt.shape[1] # no. of cells n_ue = sub_fr_strt.shape[2] # no. of UEs n_ant = sub_fr_strt.shape[3] # no. of BS antennas sf_strts = np.reshape(sub_fr_strt, (n_frame * n_cell * n_ue, n_ant)) fig, axes = plt.subplots(nrows=n_ue, ncols=n_cell, squeeze=False) fig.suptitle('Frames\' starting indices per antenna') #plot channel analysis show_plot(cmpx_pilots, lts_seq_orig, match_filt) for n_c in range(n_cell): for n_u in range(n_ue): sf_strts = sub_fr_strt[:, n_c, n_u, :] x_pl = np.arange(sf_strts.shape[0]) + hdf5.n_frm_st for j in range(n_ant): axes[n_u, n_c].plot(x_pl, sf_strts[:, j].flatten(), label='Antenna: {}'.format(j)) axes[n_u, n_c].legend(loc='lower right', ncol=8, frameon=False) axes[n_u, n_c].set_xlabel('Frame no.') axes[n_u, n_c].set_ylabel('Starting index') axes[n_u, n_c].grid(True) # PILOT MAP fig, axes = plt.subplots(nrows=n_ue, ncols=n_cell, squeeze=False) c = [] fig.suptitle( 'Pilot Map (Percentage of Detected Pilots Per Symbol) - NOTE: Might exceed 100% due to threshold' ) for n_c in range(n_cell): for n_u in range(n_ue): c.append(axes[n_u, n_c].imshow( seq_found[:, n_c, n_u, :].T, vmin=0, vmax=100, cmap='Blues', interpolation='nearest', extent=[hdf5.n_frm_st, hdf5.n_frm_end, n_ant, 0], aspect="auto")) axes[n_u, n_c].set_title('Cell {} UE {}'.format(n_c, n_u)) axes[n_u, n_c].set_ylabel('Antenna #') axes[n_u, n_c].set_xlabel('Frame #') axes[n_u, n_c].set_xticks(np.arange(hdf5.n_frm_st, hdf5.n_frm_end, 1), minor=True) axes[n_u, n_c].set_yticks(np.arange(0, n_ant, 1), minor=True) axes[n_u, n_c].grid(which='minor', color='0.75', linestyle='-', linewidth=0.05) cbar = plt.colorbar(c[-1], ax=axes.ravel().tolist(), ticks=np.linspace(0, 100, 11), orientation='horizontal') cbar.ax.set_xticklabels([ '0%', '10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', '100%' ]) # SHOW FIGURES plt.show() print( "** \tWARNING: If you attempt to plot a different frame after running this script, remember to subtract the frame_start you gave! **" ) print( ">> \tE.g.: frame no. 1763 and frame_start = 1500 --> plot(match_filter_clr[<frame 1736 - 1500>, <cell>, <ue>, ref_antenna,:])\n" ) else: plt.show()
def verify_hdf5(hdf5, default_frame=100, cell_i=0, ofdm_sym_i=0, ant_i =0, user_i=0, ul_sf_i=0, subcarrier_i=10, offset=-1, dn_calib_offset=0, up_calib_offset=0, n_frm_st=0, thresh=0.001, deep_inspect=False, sub_sample=1): """ Plot data in file to verify contents. Input: default_frame: Index of frame to be plotted. Default to frame #100 """ plt.close("all") data = hdf5.data metadata = hdf5.metadata pilot_samples = hdf5.pilot_samples uplink_samples = hdf5.uplink_samples # Check which data we have available data_types_avail = [] pilots_avail = len(pilot_samples) > 0 ul_data_avail = len(uplink_samples) > 0 if pilots_avail: data_types_avail.append("PILOTS") print("Found Pilots!") if ul_data_avail: data_types_avail.append("UL_DATA") print("Found Uplink Data") # Empty structure if not data_types_avail: raise Exception(' **** No pilots or uplink data found **** ') # Retrieve attributes symbol_length = int(metadata['SYMBOL_LEN']) num_pilots = int(metadata['PILOT_NUM']) num_cl = int(metadata['CL_NUM']) cp = int(metadata['CP_LEN']) prefix_len = int(metadata['PREFIX_LEN']) postfix_len = int(metadata['POSTFIX_LEN']) z_padding = prefix_len + postfix_len if offset < 0: # if no offset is given use prefix from HDF5 offset = int(prefix_len) fft_size = int(metadata['FFT_SIZE']) pilot_type = metadata['PILOT_SEQ_TYPE'].astype(str)[0] ofdm_pilot = np.array(metadata['OFDM_PILOT']) reciprocal_calib = np.array(metadata['RECIPROCAL_CALIB']) symbol_length_no_pad = symbol_length - z_padding num_pilots_per_sym = ((symbol_length_no_pad) // len(ofdm_pilot)) n_ue = num_cl frm_plt = min(default_frame, pilot_samples.shape[0] + n_frm_st) # Verify default_frame does not exceed max number of collected frames ref_frame = min(default_frame - n_frm_st, pilot_samples.shape[0]) print("symbol_length = {}, offset = {}, cp = {}, prefix_len = {}, postfix_len = {}, z_padding = {}, pilot_rep = {}".format(symbol_length, offset, cp, prefix_len, postfix_len, z_padding, num_pilots_per_sym)) samples = pilot_samples num_cl_tmp = num_pilots # number of UEs to plot data for samps_mat = np.reshape( samples[::sub_sample], (samples.shape[0], samples.shape[1], num_cl_tmp, samples.shape[3], symbol_length, 2)) samps = (samps_mat[:, :, :, :, :, 0] + samps_mat[:, :, :, :, :, 1]*1j)*2**-15 # Correlation (Debug plot useful for checking sync) amps = np.mean(np.abs(samps[:, 0, user_i, ant_i, :]), axis=1) pilot_frames = [i for i in range(len(amps)) if amps[i] > thresh] if len(pilot_frames) == 0: print("no valid frames where found. Decision threshold (average pilot amplitude) was %f" % thresh) return # Compute CSI from IQ samples # Samps: #Frames, #Cell, #Users, #Antennas, #Samples # CSI: #Frames, #Cell, #Users, #Pilot Rep, #Antennas, #Subcarrier # For correlation use a fft size of 64 print("*verify_hdf5(): Calling samps2csi with fft_size = {}, offset = {}, bound = {}, cp = {} *".format(fft_size, offset, z_padding, cp)) csi, _ = hdf5_lib.samps2csi(samples, num_cl_tmp, symbol_length, fft_size = fft_size, offset = offset, bound = z_padding, cp = cp, sub = sub_sample, pilot_type=pilot_type) cellCSI = csi[:, cell_i, :, :, :, :] if ofdm_sym_i >= num_pilots_per_sym: # if out of range index, do average userCSI = np.mean(cellCSI[:, :, :, :, :], 2) else: userCSI = cellCSI[:, :, ofdm_sym_i, :, :] corr_total, sig_sc = calCorr(userCSI, np.transpose(np.conj(userCSI[ref_frame, :, :, :]), (1, 0, 2) ) ) # Plotter # Plot pilots fig1, axes1 = plt.subplots(nrows=4, ncols=1, squeeze=False, figsize=(10, 8)) axes1[0, 0].set_title('Pilots IQ - Cell %d - Antenna %d - User %d'%(cell_i, ant_i, user_i)) # Samps Dimensions: (Frame, Cell, User, Pilot Rep, Antenna, Sample) axes1[0, 0].set_ylabel('Frame %d (I)' %( (ref_frame + n_frm_st)) ) axes1[0, 0].plot(np.real(samps[ref_frame, cell_i, user_i, ant_i, :])) axes1[1, 0].set_ylabel('Frame %d (Q)' %( (ref_frame + n_frm_st)) ) axes1[1, 0].plot(np.imag(samps[ref_frame, cell_i, user_i, ant_i, :])) axes1[2, 0].set_ylabel('All Frames (I)') axes1[2, 0].plot(np.real(samps[:, cell_i, user_i, ant_i, :]).flatten()) axes1[3, 0].set_ylabel('All Frames (Q)') axes1[3, 0].plot(np.imag(samps[:, cell_i, user_i, ant_i, :]).flatten()) fig2, axes2 = plt.subplots(nrows=3, ncols=1, squeeze=False, figsize=(10, 8)) axes2[0, 0].set_title('Pilot CSI Stats Across Frames- Cell %d - User %d - Subcarrier %d' % (cell_i, user_i, subcarrier_i)) axes2[0, 0].set_ylabel('Magnitude') for i in range(csi.shape[4]): axes2[0, 0].plot(np.abs(userCSI[:, user_i, i, subcarrier_i]).flatten(), label="ant %d"%i) axes2[0, 0].legend(loc='lower right', frameon=False) axes2[0, 0].set_xlabel('Frame') axes2[1, 0].set_ylabel('Phase') for i in range(csi.shape[4]): axes2[1, 0].plot(np.angle(userCSI[:, user_i, i, subcarrier_i]).flatten(), label="ant %d"%i) axes2[1, 0].legend(loc='lower right', frameon=False) axes2[1, 0].set_ylim(-np.pi, np.pi) axes2[1, 0].set_xlabel('Frame') axes2[2, 0].set_ylabel('Correlation with Frame %d' % ref_frame) axes2[2, 0].set_ylim([0, 1.1]) axes2[2, 0].set_title('Cell %d offset %d' % (0, offset)) for u in range(num_cl_tmp): axes2[2, 0].plot(corr_total[pilot_frames, u], label="user %d"%u) axes2[2, 0].legend(loc='lower right', frameon=False) axes2[2, 0].set_xlabel('Frame') if reciprocal_calib: # frame, downlink(0)-uplink(1), antennas, subcarrier csi_u, _ = hdf5_lib.samps2csi(samples, num_cl_tmp, symbol_length, fft_size = fft_size, offset = up_calib_offset, bound = z_padding, cp = cp, sub = sub_sample, pilot_type=pilot_type) csi_d, _ = hdf5_lib.samps2csi(samples, num_cl_tmp, symbol_length, fft_size = fft_size, offset = dn_calib_offset, bound = z_padding, cp = cp, sub = sub_sample, pilot_type=pilot_type) calib_corrected_csi = np.zeros(csi_d.shape, dtype='complex64') calib_corrected_csi[:, :, 0, :, :, :] = csi_d[:, :, 0, :, :, :] calib_corrected_csi[:, :, 1, :, :, :] = csi_u[:, :, 1, :, :, :] calib_corrected_csi_cell0 = calib_corrected_csi[:, 0, :, :, :, :] # TODO: add option for averaging across repeated pilots vs individual pilots #calibCSI = np.mean(calib_corrected_csi_cell0, 2) # average several csi copies calibCSI = calib_corrected_csi_cell0[:, :, 0, :, :] # take first csi calib_mat = np.divide(calibCSI[:, 0, :, :], calibCSI[:, 1, :, :]) fig3, axes3 = plt.subplots(nrows=4, ncols=1, squeeze=False, figsize=(10, 8)) axes3[0, 0].set_title('Reciprocity Calibration Factor Across Frames - Cell 0 - Subcarrier %d'%subcarrier_i) axes3[0, 0].set_ylabel('Magtinute (ant %d)' % (ant_i)) axes3[0, 0].plot(np.abs(calib_mat[:, ant_i, subcarrier_i]).flatten()) axes3[0, 0].set_xlabel('Frame') axes3[1, 0].set_ylabel('Phase (ant %d)' % (ant_i)) axes3[1, 0].plot(np.angle(calib_mat[:, ant_i, subcarrier_i]).flatten()) axes3[1, 0].set_ylim(-np.pi, np.pi) axes3[1, 0].set_xlabel('Frame') axes3[2, 0].set_ylabel('Magnitude') for i in range(calib_mat.shape[1]): axes3[2, 0].plot(np.abs(calib_mat[:, i, subcarrier_i]).flatten(), label="ant %d"%i) axes3[2, 0].set_xlabel('Frame') axes3[2, 0].legend(loc='lower right', frameon=False) axes3[3, 0].set_ylabel('Phase') for i in range(calib_mat.shape[1]): axes3[3, 0].plot(np.angle(calib_mat[:, i, subcarrier_i]).flatten(), label="ant %d"%i) axes3[3, 0].set_xlabel('Frame') axes3[3, 0].set_ylim(-np.pi, np.pi) axes3[3, 0].legend(loc='lower right', frameon=False) fig4, axes4 = plt.subplots(nrows=4, ncols=1, squeeze=False, figsize=(10, 8)) axes4[0, 0].set_title('Reciprocity Calibration Factor Across Subcarriers - Cell 0 - Frame %d'%ref_frame) axes4[0, 0].set_ylabel('Magnitude ant %d' % (ant_i)) axes4[0, 0].plot(np.abs(calib_mat[ref_frame, ant_i, :]).flatten()) axes4[0, 0].set_xlabel('Subcarrier') axes4[1, 0].set_ylabel('Phase ant %d' % (ant_i)) axes4[1, 0].plot(np.angle(calib_mat[ref_frame, ant_i, :]).flatten()) axes4[1, 0].set_ylim(-np.pi, np.pi) axes4[1, 0].set_xlabel('Subcarrier') axes4[2, 0].set_ylabel('Magnitude') for i in range(calib_mat.shape[1]): axes4[2, 0].plot(np.abs(calib_mat[ref_frame, i, :]).flatten(), label="ant %d"%i) axes4[2, 0].set_xlabel('Subcarrier') axes4[2, 0].legend(loc='lower right', frameon=False) axes4[3, 0].set_ylabel('Phase') for i in range(calib_mat.shape[1]): axes4[3, 0].plot(np.angle(calib_mat[ref_frame, i, :]).flatten(), label="ant %d"%i) axes4[3, 0].set_xlabel('Subcarrier') axes4[3, 0].set_ylim(-np.pi, np.pi) axes4[3, 0].legend(loc='lower right', frameon=False) # Plot UL data symbols if ul_data_avail: fig4, axes4 = plt.subplots(nrows=4, ncols=1, squeeze=False, figsize=(10, 8)) samples = uplink_samples num_cl_tmp = samples.shape[2] # number of UEs to plot data for # UL Samps: #Frames, #Cell, #Users, #Uplink Symbol, #Antennas, #Samples # For looking at the whole picture, use a fft size of whole symbol_length as fft window (for visualization), # and no offset #print("*verify_hdf5():Calling samps2csi *AGAIN*(?) with fft_size = symbol_length, no offset*") #_, uplink_samps = hdf5_lib.samps2csi(uplink_samples, num_cl_tmp, symbol_length, fft_size=symbol_length, offset=0, bound=0, cp=0, sub=sub_sample) samps_mat = np.reshape( samples[::sub_sample], (samples.shape[0], samples.shape[1], num_cl_tmp, samples.shape[3], symbol_length, 2)) uplink_samps = (samps_mat[:, :, :, :, :, 0] + samps_mat[:, :, :, :, :, 1]*1j)*2**-15 # Samps Dimensions: (Frame, Cell, User, Pilot Rep, Antenna, Sample) axes4[0, 0].set_title('Uplink Data IQ - Cell %d - Antenna %d - Symbol %d' % (cell_i, ant_i, ul_sf_i)) axes4[0, 0].set_ylabel('Frame %d (I)' % ref_frame) axes4[0, 0].plot(np.real(uplink_samps[ref_frame, cell_i, ul_sf_i, ant_i, :])) axes4[1, 0].set_ylabel('Frame %d (Q)' % ref_frame) axes4[1, 0].plot(np.imag(uplink_samps[ref_frame, cell_i, ul_sf_i, ant_i, :])) axes4[2, 0].set_ylabel('All Frames (I)') axes4[2, 0].plot(np.real(uplink_samps[:, cell_i, ul_sf_i, ant_i, :]).flatten()) axes4[3, 0].set_ylabel('All Frames (Q)') axes4[3, 0].plot(np.imag(uplink_samps[:, cell_i, ul_sf_i, ant_i, :]).flatten()) if deep_inspect: filter_pilots_start = time.time() match_filt, k_lts, n_lts, cmpx_pilots, lts_seq_orig = hdf5_lib.filter_pilots(pilot_samples, z_padding, fft_size = fft_size, cp = cp) filter_pilots_end = time.time() frame_sanity_start = time.time() match_filt_clr, frame_map, f_st, peak_map = hdf5_lib.frame_sanity(match_filt, k_lts, n_lts, n_frm_st, frm_plt, plt_ant=ant_i, cp = cp) frame_sanity_end = time.time() print(">>>> filter_pilots time: %f \n" % ( filter_pilots_end - filter_pilots_start) ) print(">>>> frame_sanity time: %f \n" % ( frame_sanity_end - frame_sanity_start) ) # Find LTS peaks across frame n_frame = pilot_samples.shape[0] n_cell = pilot_samples.shape[1] n_ue = pilot_samples.shape[2] n_ant = pilot_samples.shape[3] seq_found = np.zeros((n_frame, n_cell, n_ue, n_ant)) for frameIdx in range(n_frame): # Frame for cellIdx in range(n_cell): # Cell for ueIdx in range(n_ue): # UE for bsAntIdx in range(n_ant): # BS ANT I = pilot_samples[frameIdx, cellIdx, ueIdx, bsAntIdx, 0:symbol_length * 2:2] / 2 ** 15 Q = pilot_samples[frameIdx, cellIdx, ueIdx, bsAntIdx, 1:symbol_length * 2:2] / 2 ** 15 IQ = I + (Q * 1j) tx_pilot, lts_pks, lts_corr, pilot_thresh, best_pk = pilot_finder(IQ, pilot_type, flip=True, pilot_seq=ofdm_pilot) # Find percentage of LTS peaks within a symbol # (e.g., in a 4096-sample pilot symbol, we expect 64, 64-long sequences... assuming no CP) # seq_found[frameIdx, cellIdx, ueIdx, bsAntIdx] = 100 * (lts_pks.size / num_pilots_per_sym) seq_found[frameIdx, cellIdx, ueIdx, bsAntIdx] = 100 * (peak_map[frameIdx, cellIdx, ueIdx, bsAntIdx] / num_pilots_per_sym) # use matched filter analysis output dbg2 = False if dbg2: fig = plt.figure(1234) ax1 = fig.add_subplot(2, 1, 1) ax1.plot(np.abs(IQ)) ax2 = fig.add_subplot(2, 1, 2) ax2.stem(np.abs(lts_corr)) ax2.scatter(np.linspace(0.0, len(lts_corr), num=1000), pilot_thresh * np.ones(1000), color='r') plt.show() #plots: print("Plotting the results:\n") n_cell = match_filt_clr.shape[1] n_ue = match_filt_clr.shape[2] # plot a frame: fig, axes = plt.subplots(nrows=n_cell, ncols=n_ue, squeeze=False) fig.suptitle('MF Frame # {} Antenna # {}'.format(ref_frame, ant_i)) for n_c in range(n_cell): for n_u in range(n_ue): axes[n_c, n_u].stem(match_filt_clr[ref_frame - hdf5.n_frm_st, n_c, n_u, ant_i, :]) axes[n_c, n_u].set_xlabel('Samples') axes[n_c, n_u].set_title('Cell {} UE {}'.format(n_c, n_u)) axes[n_c, n_u].grid(True) #plt.show() # plot frame_map: n_cell = frame_map.shape[1] n_ue = frame_map.shape[2] n_ant = frame_map.shape[3] # For some damm reason, if one of the subplots has all of the frames in the same state (good/bad/partial) # it chooses a random color to paint the whole subplot! # Below is some sort of remedy (will fail if SISO!): for n_c in range(n_cell): for n_u in range(n_ue): f_map = frame_map[:,n_c,n_u,:] n_gf = f_map[f_map == 1].size n_bf = f_map[f_map == -1].size n_pr = f_map[f_map == 0].size if n_gf == 0: frame_map[-1,n_c,n_u,-1] = 1 print("No good frames! Colored the last frame of the last antenna Good for cell {} and UE {} to keep plotter happy!".format(n_c,n_u)) if n_pr == 0: frame_map[0,n_c,n_u,-1] = 0 print("No partial frames! Colored frame 0 of the last antenna for cell {} and UE {} Partial to keep plotter happy!".format(n_c,n_u)) if n_bf == 0: frame_map[-1,n_c,n_u,0] = -1 print("No bad frames! Colored the last frame of antenna 0 Bad for cell {} and UE {} to keep plotter happy!".format(n_c,n_u)) #plot F starts for each antenna sub_fr_strt = f_st n_frame = sub_fr_strt.shape[0] # no. of captured frames n_cell = sub_fr_strt.shape[1] # no. of cells n_ue = sub_fr_strt.shape[2] # no. of UEs n_ant = sub_fr_strt.shape[3] # no. of BS antennas sf_strts = np.reshape(sub_fr_strt, (n_frame*n_cell*n_ue,n_ant)) fig, axes = plt.subplots(nrows=n_ue, ncols=n_cell, squeeze=False) fig.suptitle('Frames\' starting indices per antenna') #plot channel analysis #show_plot(cmpx_pilots, lts_seq_orig, match_filt) for n_c in range(n_cell): for n_u in range(n_ue): sf_strts = sub_fr_strt[:,n_c,n_u,:] x_pl = np.arange(sf_strts.shape[0]) + hdf5.n_frm_st for j in range(n_ant): axes[n_u, n_c].plot(x_pl,sf_strts[:,j].flatten(), label = 'Antenna: {}'.format(j) ) axes[n_u, n_c].legend(loc='lower right', ncol=8, frameon=False) axes[n_u, n_c].set_xlabel('Frame no.') axes[n_u, n_c].set_ylabel('Starting index') axes[n_u, n_c].grid(True) # PILOT MAP fig, axes = plt.subplots(nrows=n_ue, ncols=n_cell, squeeze=False) c = [] fig.suptitle('Pilot Map (Percentage of Detected Pilots Per Symbol) - NOTE: Might exceed 100% due to threshold') for n_c in range(n_cell): for n_u in range(n_ue): c.append(axes[n_u, n_c].imshow(seq_found[:, n_c, n_u, :].T, vmin=0, vmax=100, cmap='Blues', interpolation='nearest', extent=[hdf5.n_frm_st, hdf5.n_frm_end, n_ant, 0], aspect="auto")) axes[n_u, n_c].set_title('Cell {} UE {}'.format(n_c, n_u)) axes[n_u, n_c].set_ylabel('Antenna #') axes[n_u, n_c].set_xlabel('Frame #') axes[n_u, n_c].set_xticks(np.arange(hdf5.n_frm_st, hdf5.n_frm_end, 1), minor=True) axes[n_u, n_c].set_yticks(np.arange(0, n_ant, 1), minor=True) axes[n_u, n_c].grid(which='minor', color='0.75', linestyle='-', linewidth=0.05) cbar = plt.colorbar(c[-1], ax=axes.ravel().tolist(), ticks=np.linspace(0, 100, 11), orientation='horizontal') cbar.ax.set_xticklabels(['0%', '10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', '100%']) #fig, axes = plt.subplots(nrows=n_ue, ncols=n_cell, squeeze=False) #c = [] #fig.suptitle('Frame Map') #for n_c in range(n_cell): # for n_u in range(n_ue): # c.append( axes[n_u, n_c].imshow(frame_map[:,n_c,n_u,:].T, cmap=plt.cm.get_cmap('Blues', 3), interpolation='none', # extent=[hdf5.n_frm_st,hdf5.n_frm_end, n_ant,0], aspect="auto") ) # axes[n_u, n_c].set_title('Cell {} UE {}'.format(n_c, n_u)) # axes[n_u, n_c].set_ylabel('Antenna #') # axes[n_u, n_c].set_xlabel('Frame #') # # Minor ticks # axes[n_u, n_c].set_xticks(np.arange(hdf5.n_frm_st, hdf5.n_frm_end, 1), minor=True) # axes[n_u, n_c].set_yticks(np.arange(0, n_ant, 1), minor=True) # # Gridlines based on minor ticks # axes[n_u, n_c].grid(which='minor', color='0.75', linestyle='-', linewidth=0.1) #cbar = plt.colorbar(c[-1], ax=axes.ravel().tolist(), ticks=[-1, 0, 1], orientation = 'horizontal') #cbar.ax.set_xticklabels(['Bad Frame', 'Probably partial/corrupt', 'Good Frame']) ##plt.show() # SHOW FIGURES plt.show() print("** \tWARNING: If you attempt to plot a different frame after running this script, remember to subtract the frame_start you gave! **") print(">> \tE.g.: frame no. 1763 and frame_start = 1500 --> plot(match_filter_clr[<frame 1736 - 1500>, <cell>, <ue>, ref_antenna,:])\n") else: plt.show()
def analyze_hdf5(hdf5, frame_i=10, cell_i=0, subcarrier_i=7, offset=-1, zoom=0, pl=0): ''' Calculates and plots achievable rates from hdf5 traces ''' metadata = hdf5.metadata pilot_samples = hdf5.pilot_samples noise_avail = len(hdf5.noise_samples) > 0 # TODO: noise can be estimated from null subcarriers if noise_avail: noise_samples = hdf5.noise_samples else: print('Trace-based Estimation of performance requires presense of noise samples!') print('Noise data not present. Exitting...') return symbol_length = int(metadata['SYMBOL_LEN']) rate = float(metadata['RATE']) symbol_num = int(metadata['BS_FRAME_LEN']) timestep = symbol_length*symbol_num/rate num_cl = int(metadata['CL_NUM']) num_pilots = int(metadata['PILOT_NUM']) prefix_len = int(metadata['PREFIX_LEN']) postfix_len = int(metadata['POSTFIX_LEN']) z_padding = prefix_len + postfix_len if offset < 0: # if no offset is given use prefix from HDF5 offset = int(prefix_len) fft_size = int(metadata['FFT_SIZE']) cp = int(metadata['CP_LEN']) pilot_type = metadata['PILOT_SEQ_TYPE'].astype(str)[0] nonzero_sc_size = metadata['DATA_SUBCARRIER_NUM'] num_noise_syms = noise_samples.shape[2] n_frame = pilot_samples.shape[0] n_cell = pilot_samples.shape[1] n_ue = pilot_samples.shape[2] n_ant = pilot_samples.shape[3] # compute CSI for each user and get a nice numpy array # Returns csi with Frame, Cell, User, pilot repetitions, BS ant, Subcarrier # also, iq samples nicely chunked out, same dims, but subcarrier is sample. num_cl_tmp = num_pilots csi,_ = hdf5_lib.samps2csi(pilot_samples, num_cl_tmp, symbol_length, fft_size=fft_size, offset=offset, bound=z_padding, cp=cp, sub=1, pilot_type=pilot_type, nonzero_sc_size=nonzero_sc_size) csi = csi[:, cell_i, :, :, :, :] noise,_ = hdf5_lib.samps2csi(noise_samples, num_noise_syms, symbol_length, fft_size=fft_size, offset=offset, bound=z_padding, cp=cp, sub=1, pilot_type=pilot_type, nonzero_sc_size=nonzero_sc_size) noise = noise[:, cell_i, :, :, :, :] # zoom in too look at behavior around peak (and reduce processing time) if zoom > 0: csi = csi[frame_i-zoom:frame_i+zoom, :, :, :, :] noise = noise[frame_i-zoom:frame_i+zoom, :, :, :, :] # recenter the plots (otherwise it errors) frame = zoom # don't include noise, average over all pilot repetitions userCSI = np.mean(csi, 2) noise = np.mean(noise, 2) # compute beamweights based on the specified frame. conjbws = np.transpose( np.conj(userCSI[frame_i, :, :, :]), (1, 0, 2)) zfbws = np.empty( (userCSI.shape[2], userCSI.shape[1], userCSI.shape[3]), dtype='complex64') for sc in range(userCSI.shape[3]): zfbws[:, :, sc] = np.linalg.pinv( userCSI[frame_i, :, :, sc]) downlink = True # calculate capacity based on these weights # these return total capacity, per-user capacity, per-user/per-subcarrier capacity,.. # SINR, single-user capacity(no inter-user interference), and SNR # conjcap_total,conjcap_u,conjcap_sc,conjSINR,conjcap_su_sc,conjcap_su_u,conjSNR conj = calCapacity(userCSI, noise, conjbws, downlink=downlink) # zfcap_total,zfcap_u,zfcap_sc,zfSINR,zfcap_su_sc,zfcap_su_u,zfSNR zf = calCapacity(userCSI, noise, zfbws, downlink=downlink) _, demmel = calDemmel(userCSI) # plot stuff subf_conj = conj[-2] subf_zf = zf[-2] mubf_conj = conj[1] mubf_zf = zf[1] fig1, axes1 = plt.subplots(nrows=2, ncols=2, squeeze=False, figsize=(10, 8)) axes1[0, 0].set_title('Subcarrier-Mean Spectral Efficiency Using Beamforming Weights at Frame %d'%frame_i) for j in range(num_cl_tmp): axes1[0, 0].plot(np.arange(0, csi.shape[0]*timestep, timestep)[:csi.shape[0]], mubf_conj[:,j], label = 'Conj User: {}'.format(j) ) for j in range(num_cl_tmp): axes1[0, 1].plot(np.arange(0, csi.shape[0]*timestep, timestep)[:csi.shape[0]], mubf_zf[:,j], label = 'ZF User: {}'.format(j) ) axes1[0,0].legend(loc='upper right', ncol=1, frameon=False) axes1[0,0].set_xlabel('Time (s)', fontsize=14) axes1[0,0].set_ylabel('MUBF %dx%d (bps/Hz)'%(n_ant, n_ue), fontsize=14) axes1[0,1].legend(loc='upper right', ncol=1, frameon=False) axes1[0,1].set_xlabel('Time (s)', fontsize=14) for j in range(num_cl_tmp): axes1[1, 0].plot(np.arange(0, csi.shape[0]*timestep, timestep)[:csi.shape[0]], subf_conj[:,j], label = 'Conj User: {}'.format(j) ) for j in range(num_cl_tmp): axes1[1, 1].plot(np.arange(0, csi.shape[0]*timestep, timestep)[:csi.shape[0]], subf_zf[:,j], label = 'ZF User: {}'.format(j) ) axes1[1,0].legend(loc='upper right', ncol=1, frameon=False) axes1[1,0].set_xlabel('Time (s)', fontsize=14) axes1[1,0].set_ylabel('SUBF %dx1 (bps/Hz)'%n_ant, fontsize=14) axes1[1,1].legend(loc='upper right', ncol=1, frameon=False) axes1[1,1].set_xlabel('Time (s)', fontsize=14) # demmel number plt.figure(pl+2, figsize=(10, 8)) plt.plot(np.arange(0, csi.shape[0]*timestep, timestep)[:csi.shape[0]], demmel[:, subcarrier_i]) plt.xlabel('Time (s)', fontsize=14) plt.ylabel('Condition Number', fontsize=14) plt.title('CSI Matrix Demmel condition number across time, Subcarrier %d'%subcarrier_i) #pl += 1 # SNR #snr_linear = np.mean(zf[-1], axis = -1) #snr_dB = 10 * np.log10(snr_linear) #plt.figure(pl+2, figsize=(10, 8)) #for i in range(num_cl_tmp): # plt.plot(np.arange(0, csi.shape[0]*timestep, timestep)[:csi.shape[0]], snr_dB[:, i], label = 'User: {}'.format(i)) ## plt.ylim([0,2]) #plt.xlabel('Time (s)', fontsize=14) #plt.ylabel('ZF SNR (dB)', fontsize=14) #plt.title('ZF SNR Across Frames') #plt.legend() plt.show() del csi # free the memory del noise
def verify_hdf5(hdf5, frame_i=100, cell_i=0, ofdm_sym_i=0, ant_i =0, user_i=0, ul_sf_i=0, subcarrier_i=10, offset=-1, dn_calib_offset=0, up_calib_offset=0, thresh=0.001, deep_inspect=False, corr_thresh=0.00, exclude_bs_nodes=[]): """Plot data in the hdf5 file to verify contents. Args: hdf5: An hdf5_lib object. frame_i: The index of the frame to be plotted. cell_i: The index of the hub where base station is connected. ofdm_sym_i: The index of the reference ofdm symbol in a pilot. ant_i: The index of the reference base station antenna. user_i: The index of the reference user. """ plt.close("all") # Retrieve attributes n_frm_end = hdf5.n_frm_end n_frm_st = hdf5.n_frm_st metadata = hdf5.metadata symbol_length = int(metadata['SYMBOL_LEN']) num_pilots = int(metadata['PILOT_NUM']) num_cl = int(metadata['CL_NUM']) prefix_len = int(metadata['PREFIX_LEN']) postfix_len = int(metadata['POSTFIX_LEN']) z_padding = prefix_len + postfix_len if offset < 0: # if no offset is given use prefix from HDF5 offset = int(prefix_len) fft_size = int(metadata['FFT_SIZE']) cp = int(metadata['CP_LEN']) rate = int(metadata['RATE']) pilot_type = metadata['PILOT_SEQ_TYPE'].astype(str)[0] nonzero_sc_size = metadata['DATA_SUBCARRIER_NUM'] ofdm_pilot = np.array(metadata['OFDM_PILOT']) reciprocal_calib = np.array(metadata['RECIPROCAL_CALIB']) symbol_length_no_pad = symbol_length - z_padding num_pilots_per_sym = ((symbol_length_no_pad) // len(ofdm_pilot)) n_ue = num_cl all_bs_nodes = set(range(hdf5.pilot_samples.shape[3])) plot_bs_nodes = list(all_bs_nodes - set(exclude_bs_nodes)) pilot_samples = hdf5.pilot_samples[:, :, :, plot_bs_nodes, :] ul_data_avail = len(hdf5.uplink_samples) > 0 if ul_data_avail: uplink_samples = hdf5.uplink_samples[:, :, :, plot_bs_nodes, :] noise_avail = len(hdf5.noise_samples) > 0 if noise_avail: noise_samples = hdf5.noise_samples[:, :, :, plot_bs_nodes, :] frm_plt = min(frame_i, pilot_samples.shape[0] + n_frm_st) # Verify frame_i does not exceed max number of collected frames ref_frame = min(frame_i - n_frm_st, pilot_samples.shape[0]) print("symbol_length = {}, offset = {}, cp = {}, prefix_len = {}, postfix_len = {}, z_padding = {}, pilot_rep = {}".format(symbol_length, offset, cp, prefix_len, postfix_len, z_padding, num_pilots_per_sym)) # pilot_samples dimensions: # ( #frames, #cells, #pilot subframes or cl ant sending pilots, #bs nodes or # bs ant, #samps per frame * 2 for IQ ) num_cl_tmp = num_pilots # number of UEs to plot data for num_frames = pilot_samples.shape[0] num_cells = pilot_samples.shape[1] num_bs_ants = pilot_samples.shape[3] samps_mat = np.reshape( pilot_samples, (num_frames, num_cells, num_cl_tmp, num_bs_ants, symbol_length, 2)) samps = (samps_mat[:, :, :, :, :, 0] + samps_mat[:, :, :, :, :, 1]*1j)*2**-15 # Correlation (Debug plot useful for checking sync) good_ants = [] insp_ants = [] # antennas to be inspected if ant_i > num_bs_ants - 1: insp_ants = range(samps.shape[3]) else: insp_ants = [ant_i] for i in insp_ants: amps = np.mean(np.abs(samps[:, 0, user_i, i, :]), axis=1) pilot_frames = [i for i in range(len(amps)) if amps[i] > thresh] if len(pilot_frames) > 0: good_ants = good_ants + [i] else: print("no valid frames where found in antenna %d. Decision threshold (average pilot amplitude) was %f" % (i, thresh)) if len(good_ants) == 0: print("no valid frames found in data belonging to user %d. Exitting ..." % user_i) return # Compute CSI from IQ samples # Samps: #Frames, #Cell, #Users, #Antennas, #Samples # CSI: #Frames, #Cell, #Users, #Pilot Rep, #Antennas, #Subcarrier # For correlation use a fft size of 64 print("*verify_hdf5(): Calling samps2csi with fft_size = {}, offset = {}, bound = {}, cp = {} *".format(fft_size, offset, z_padding, cp)) csi, _ = hdf5_lib.samps2csi(pilot_samples, num_cl_tmp, symbol_length, fft_size=fft_size, offset=offset, bound=z_padding, cp=cp, sub=1, pilot_type=pilot_type, nonzero_sc_size=nonzero_sc_size) cellCSI = csi[:, cell_i, :, :, :, :] if corr_thresh > 0.0: bad_nodes = find_bad_nodes(cellCSI, corr_thresh=corr_thresh, user=user_i) if bad_nodes: print(">>> Warning! List of bad nodes (1-based): {bad_nodes}". format(bad_nodes=bad_nodes)) else: print(">>> All Iris nodes are good!") if ofdm_sym_i >= num_pilots_per_sym: # if out of range index, do average userCSI = np.mean(cellCSI[:, :, :, :, :], 2) else: userCSI = cellCSI[:, :, ofdm_sym_i, :, :] corr_total, sig_sc = calCorr(userCSI, np.transpose(np.conj(userCSI[ref_frame, :, :, :]), (1, 0, 2) ) ) # Plotter # Plot pilots for i in insp_ants: fig1, axes1 = plt.subplots(nrows=2, ncols=1, squeeze=False, figsize=(10, 8)) axes1[0, 0].set_title('Pilots IQ - Cell %d - Antenna %d - User %d'%(cell_i, i, user_i)) # Samps Dimensions: (Frame, Cell, User, Pilot Rep, Antenna, Sample) axes1[0, 0].set_ylabel('Frame %d (IQ)' %( (ref_frame + n_frm_st)) ) axes1[0, 0].plot(np.real(samps[ref_frame, cell_i, user_i, i, :])) axes1[0, 0].plot(np.imag(samps[ref_frame, cell_i, user_i, i, :])) axes1[1, 0].set_ylabel('All Frames (I)') axes1[1, 0].plot(np.real(samps[:, cell_i, user_i, i, :]).flatten()) axes1[1, 0].plot(np.imag(samps[:, cell_i, user_i, i, :]).flatten()) fig2, axes2 = plt.subplots(nrows=3, ncols=1, squeeze=False, figsize=(10, 8)) axes2[0, 0].set_title('Pilot CSI Stats Across Frames- Cell %d - User %d - Subcarrier %d' % (cell_i, user_i, subcarrier_i)) axes2[0, 0].set_ylabel('Magnitude') for i in range(csi.shape[4]): axes2[0, 0].plot(np.abs(userCSI[:, user_i, i, subcarrier_i]).flatten(), label="ant %d" % plot_bs_nodes[i]) axes2[0, 0].legend(loc='lower right', frameon=False) axes2[0, 0].set_xlabel('Frame') axes2[1, 0].set_ylabel('Phase') for i in range(csi.shape[4]): axes2[1, 0].plot(np.angle(userCSI[:, user_i, i, subcarrier_i]).flatten(), label="ant %d" % plot_bs_nodes[i]) axes2[1, 0].legend(loc='lower right', frameon=False) axes2[1, 0].set_ylim(-np.pi, np.pi) axes2[1, 0].set_xlabel('Frame') axes2[2, 0].set_ylabel('Correlation with Frame %d' % ref_frame) axes2[2, 0].set_ylim([0, 1.1]) axes2[2, 0].set_title('Cell %d offset %d' % (0, offset)) for u in range(num_cl_tmp): axes2[2, 0].plot(corr_total[pilot_frames, u], label="user %d"%u) axes2[2, 0].legend(loc='lower right', frameon=False) axes2[2, 0].set_xlabel('Frame') if reciprocal_calib: # frame, downlink(0)-uplink(1), antennas, subcarrier csi_u = csi csi_d = csi if up_calib_offset != offset: csi_u,_ = hdf5_lib.samps2csi(pilot_samples, num_cl_tmp, symbol_length, fft_size=fft_size, offset=up_calib_offset, bound=z_padding, cp=cp, sub=1, pilot_type=pilot_type, nonzero_sc_size=nonzero_sc_size) if dn_calib_offset != offset: csi_d,_ = hdf5_lib.samps2csi(pilot_samples, num_cl_tmp, symbol_length, fft_size=fft_size, offset=dn_calib_offset, bound=z_padding, cp=cp, sub=1, pilot_type=pilot_type, nonzero_sc_size=nonzero_sc_size) calib_corrected_csi = np.zeros(csi_d.shape, dtype='complex64') calib_corrected_csi[:, :, 0, :, :, :] = csi_d[:, :, 0, :, :, :] calib_corrected_csi[:, :, 1, :, :, :] = csi_u[:, :, 1, :, :, :] calib_corrected_csi_cell0 = calib_corrected_csi[:, 0, :, :, :, :] # TODO: add option for averaging across repeated pilots vs individual pilots #calibCSI = np.mean(calib_corrected_csi_cell0, 2) # average several csi copies calibCSI = calib_corrected_csi_cell0[:, :, 0, :, :] # take first csi calib_mat = np.divide(calibCSI[:, 0, :, :], calibCSI[:, 1, :, :]) fig3, axes3 = plt.subplots(nrows=4, ncols=1, squeeze=False, figsize=(10, 8)) axes3[0, 0].set_title('Reciprocity Calibration Factor Across Frames - Cell 0 - Subcarrier %d' % subcarrier_i) axes3[0, 0].set_ylabel('Magtinute (ant %d)' % (ant_i)) axes3[0, 0].plot(np.abs(calib_mat[:, ant_i, subcarrier_i]).flatten(), label='') axes3[0, 0].set_xlabel('Frame') axes3[0, 0].legend(frameon=False) axes3[1, 0].set_ylabel('Phase (ant %d)' % (ant_i)) axes3[1, 0].plot(np.angle(calib_mat[:, ant_i, subcarrier_i]).flatten()) axes3[1, 0].set_ylim(-np.pi, np.pi) axes3[1, 0].set_xlabel('Frame') axes3[1, 0].legend(frameon=False) axes3[1, 0].grid() axes3[2, 0].set_ylabel('Magnitude') for i in range(calib_mat.shape[1]): axes3[2, 0].plot(np.abs(calib_mat[:, i, subcarrier_i]).flatten(), label="ant %d" % plot_bs_nodes[i]) axes3[2, 0].set_xlabel('Frame') axes3[2, 0].legend(loc='lower right', frameon=False) axes3[3, 0].set_ylabel('Phase') for i in range(calib_mat.shape[1]): axes3[3, 0].plot(np.angle(calib_mat[:, i, subcarrier_i]).flatten(), label="ant %d" % plot_bs_nodes[i]) axes3[3, 0].set_xlabel('Frame') axes3[3, 0].set_ylim(-np.pi, np.pi) axes3[3, 0].legend(loc='lower right', frameon=False) axes3[3, 0].grid() fig4, axes4 = plt.subplots(nrows=4, ncols=1, squeeze=False, figsize=(10, 8)) axes4[0, 0].set_title('Reciprocity Calibration Factor Across Subcarriers - Cell 0 - Frame %d' % ref_frame) axes4[0, 0].set_ylabel('Magnitude ant %d' % (ant_i)) axes4[0, 0].plot(np.abs(calib_mat[ref_frame, ant_i, :]).flatten()) axes4[0, 0].set_xlabel('Subcarrier') axes4[1, 0].set_ylabel('Phase ant %d' % (ant_i)) axes4[1, 0].plot(np.angle(calib_mat[ref_frame, ant_i, :]).flatten()) axes4[1, 0].set_ylim(-np.pi, np.pi) axes4[1, 0].set_xlabel('Subcarrier') axes4[2, 0].set_ylabel('Magnitude') for i in range(calib_mat.shape[1]): axes4[2, 0].plot(np.abs(calib_mat[ref_frame, i, :]).flatten(), label="ant %d" % plot_bs_nodes[i]) axes4[2, 0].set_xlabel('Subcarrier') axes4[2, 0].legend(loc='lower right', frameon=False) axes4[3, 0].set_ylabel('Phase') for i in range(calib_mat.shape[1]): axes4[3, 0].plot(np.angle(calib_mat[ref_frame, i, :]).flatten(), label="ant %d" % plot_bs_nodes[i]) axes4[3, 0].set_xlabel('Subcarrier') axes4[3, 0].set_ylim(-np.pi, np.pi) axes4[3, 0].legend(loc='lower right', frameon=False) plt.show() else: # Plot UL data symbols if ul_data_avail > 0: fig4, axes4 = plt.subplots(nrows=2, ncols=1, squeeze=False, figsize=(10, 8)) num_cl_tmp = uplink_samples.shape[2] # number of UEs to plot data for # UL Samps: #Frames, #Cell, #Users, #Uplink Symbol, #Antennas, #Samples # For looking at the whole picture, use a fft size of whole symbol_length as fft window (for visualization), # and no offset #print("*verify_hdf5():Calling samps2csi *AGAIN*(?) with fft_size = symbol_length, no offset*") #_, uplink_samps = hdf5_lib.samps2csi(uplink_samples, num_cl_tmp, symbol_length, fft_size=symbol_length, offset=0, bound=0, cp=0, sub=sub_sample) samps_mat = np.reshape( uplink_samples, (uplink_samples.shape[0], uplink_samples.shape[1], num_cl_tmp, uplink_samples.shape[3], symbol_length, 2)) uplink_samps = (samps_mat[:, :, :, :, :, 0] + samps_mat[:, :, :, :, :, 1]*1j)*2**-15 # Samps Dimensions: (Frame, Cell, User, Pilot Rep, Antenna, Sample) axes4[0, 0].set_title('Uplink Data IQ - Cell %d - Antenna %d - Symbol %d' % (cell_i, ant_i, ul_sf_i)) axes4[0, 0].set_ylabel('Frame %d (IQ)' % ref_frame) axes4[0, 0].plot(np.real(uplink_samps[ref_frame, cell_i, ul_sf_i, ant_i, :])) axes4[0, 0].plot(np.imag(uplink_samps[ref_frame, cell_i, ul_sf_i, ant_i, :])) axes4[1, 0].set_ylabel('All Frames (IQ)') axes4[1, 0].plot(np.real(uplink_samps[:, cell_i, ul_sf_i, ant_i, :]).flatten()) axes4[1, 0].plot(np.imag(uplink_samps[:, cell_i, ul_sf_i, ant_i, :]).flatten()) if deep_inspect: filter_pilots_start = time.time() match_filt, k_lts, n_lts, cmpx_pilots, lts_seq_orig = hdf5_lib.filter_pilots(pilot_samples, z_padding, fft_size = fft_size, cp = cp) filter_pilots_end = time.time() frame_sanity_start = time.time() match_filt_clr, frame_map, f_st, peak_map = hdf5_lib.frame_sanity(match_filt, k_lts, n_lts, n_frm_st, frm_plt, plt_ant=ant_i, cp = cp) frame_sanity_end = time.time() print(">>>> filter_pilots time: %f \n" % ( filter_pilots_end - filter_pilots_start) ) print(">>>> frame_sanity time: %f \n" % ( frame_sanity_end - frame_sanity_start) ) # Find LTS peaks across frame snr_start = time.time() n_frame = pilot_samples.shape[0] n_cell = pilot_samples.shape[1] n_ue = pilot_samples.shape[2] n_ant = pilot_samples.shape[3] seq_found = np.zeros((n_frame, n_cell, n_ue, n_ant)) td_pwr_dbm_noise = np.empty_like(pilot_samples[:, :, :, :, 0], dtype=float) td_pwr_dbm_signal = np.empty_like(pilot_samples[:, :, :, :, 0], dtype=float) snr = np.empty_like(pilot_samples[:, :, :, :, 0], dtype=float) for frameIdx in range(n_frame): # Frame for cellIdx in range(n_cell): # Cell for ueIdx in range(n_ue): # UE for bsAntIdx in range(n_ant): # BS ANT I = pilot_samples[frameIdx, cellIdx, ueIdx, bsAntIdx, 0:symbol_length * 2:2] / 2 ** 15 Q = pilot_samples[frameIdx, cellIdx, ueIdx, bsAntIdx, 1:symbol_length * 2:2] / 2 ** 15 IQ = I + (Q * 1j) tx_pilot, lts_pks, lts_corr, pilot_thresh, best_pk = pilot_finder(IQ, pilot_type, flip=True, pilot_seq=ofdm_pilot) # Find percentage of LTS peaks within a symbol # (e.g., in a 4096-sample pilot symbol, we expect 64, 64-long sequences... assuming no CP) # seq_found[frameIdx, cellIdx, ueIdx, bsAntIdx] = 100 * (lts_pks.size / num_pilots_per_sym) seq_found[frameIdx, cellIdx, ueIdx, bsAntIdx] = 100 * (peak_map[frameIdx, cellIdx, ueIdx, bsAntIdx] / num_pilots_per_sym) # use matched filter analysis output # Compute Power of Time Domain Signal rms = np.sqrt(np.mean(IQ * np.conj(IQ))) td_pwr_lin = np.real(rms) ** 2 td_pwr_dbm_s = 10 * np.log10(td_pwr_lin / 1e-3) td_pwr_dbm_signal[frameIdx, cellIdx, ueIdx, bsAntIdx] = td_pwr_dbm_s # Compute SNR # Noise if noise_avail: # noise_samples In = noise_samples[frameIdx, cellIdx, 0, bsAntIdx, 0:symbol_length * 2:2] / 2 ** 15 Qn = noise_samples[frameIdx, cellIdx, 0, bsAntIdx, 1:symbol_length * 2:2] / 2 ** 15 IQn = In + (Qn * 1j) # sio.savemat('test_pwr.mat', {'pilot_t': IQn}) # Compute Noise Power (Time Domain) rms = np.sqrt(np.mean(IQn * np.conj(IQn))) td_pwr_lin = np.real(rms) ** 2 td_pwr_dbm_n = 10 * np.log10(td_pwr_lin / 1e-3) td_pwr_dbm_noise[frameIdx, cellIdx, ueIdx, bsAntIdx] = td_pwr_dbm_n # SNR snr[frameIdx, cellIdx, ueIdx, bsAntIdx] = td_pwr_dbm_s - td_pwr_dbm_n dbg2 = False if dbg2: fig = plt.figure(1234) ax1 = fig.add_subplot(2, 1, 1) ax1.plot(np.abs(IQ)) ax2 = fig.add_subplot(2, 1, 2) ax2.stem(np.abs(lts_corr)) ax2.scatter(np.linspace(0.0, len(lts_corr), num=1000), pilot_thresh * np.ones(1000), color='r') plt.show() snr_end = time.time() print(">>>> compute_snr time: %f \n" % (snr_end - snr_start)) # Plots: print("Plotting the results:\n") n_cell = match_filt_clr.shape[1] n_ue = match_filt_clr.shape[2] # plot a frame: fig, axes = plt.subplots(nrows=n_cell, ncols=n_ue, squeeze=False) fig.suptitle('MF Frame # {} Antenna # {}'.format(ref_frame, ant_i)) for n_c in range(n_cell): for n_u in range(n_ue): axes[n_c, n_u].stem(match_filt_clr[ref_frame - n_frm_st, n_c, n_u, ant_i, :]) axes[n_c, n_u].set_xlabel('Samples') axes[n_c, n_u].set_title('Cell {} UE {}'.format(n_c, n_u)) axes[n_c, n_u].grid(True) # plot frame_map: n_cell = frame_map.shape[1] n_ue = frame_map.shape[2] n_ant = frame_map.shape[3] # For some damm reason, if one of the subplots has all of the frames in the same state (good/bad/partial) # it chooses a random color to paint the whole subplot! # Below is some sort of remedy (will fail if SISO!): for n_c in range(n_cell): for n_u in range(n_ue): f_map = frame_map[:,n_c,n_u,:] n_gf = f_map[f_map == 1].size n_bf = f_map[f_map == -1].size n_pr = f_map[f_map == 0].size if n_gf == 0: frame_map[-1,n_c,n_u,-1] = 1 print("No good frames! Colored the last frame of the last antenna Good for cell {} and UE {} to keep plotter happy!".format(n_c,n_u)) if n_pr == 0: frame_map[0,n_c,n_u,-1] = 0 print("No partial frames! Colored frame 0 of the last antenna for cell {} and UE {} Partial to keep plotter happy!".format(n_c,n_u)) if n_bf == 0: frame_map[-1,n_c,n_u,0] = -1 print("No bad frames! Colored the last frame of antenna 0 Bad for cell {} and UE {} to keep plotter happy!".format(n_c,n_u)) #plot F starts for each antenna sub_fr_strt = f_st n_frame = sub_fr_strt.shape[0] # no. of captured frames n_cell = sub_fr_strt.shape[1] # no. of cells n_ue = sub_fr_strt.shape[2] # no. of UEs n_ant = sub_fr_strt.shape[3] # no. of BS antennas sf_strts = np.reshape(sub_fr_strt, (n_frame*n_cell*n_ue,n_ant)) fig, axes = plt.subplots(nrows=n_ue, ncols=n_cell, squeeze=False) fig.suptitle('Frames\' starting indices per antenna') #plot channel analysis show_plot(cmpx_pilots, lts_seq_orig, match_filt, user_i, ant_i, ref_frame, n_frm_st) for n_c in range(n_cell): for n_u in range(n_ue): sf_strts = sub_fr_strt[:,n_c,n_u,:] x_pl = np.arange(sf_strts.shape[0]) + n_frm_st for j in range(n_ant): axes[n_u, n_c].plot(x_pl,sf_strts[:,j].flatten(), label = 'Antenna: {}'.format(j) ) axes[n_u, n_c].legend(loc='lower right', ncol=8, frameon=False) axes[n_u, n_c].set_xlabel('Frame no.') axes[n_u, n_c].set_ylabel('Starting index') axes[n_u, n_c].grid(True) # PILOT MAP fig, axes = plt.subplots(nrows=n_ue, ncols=n_cell, squeeze=False) c = [] fig.suptitle('Pilot Map (Percentage of Detected Pilots Per Symbol) - NOTE: Might exceed 100% due to threshold') for n_c in range(n_cell): for n_u in range(n_ue): c.append(axes[n_u, n_c].imshow(seq_found[:, n_c, n_u, :].T, vmin=0, vmax=100, cmap='Blues', interpolation='nearest', extent=[n_frm_st, n_frm_end, n_ant, 0], aspect="auto")) axes[n_u, n_c].set_title('Cell {} UE {}'.format(n_c, n_u)) axes[n_u, n_c].set_ylabel('Antenna #') axes[n_u, n_c].set_xlabel('Frame #') axes[n_u, n_c].set_xticks(np.arange(n_frm_st, n_frm_end, 1), minor=True) axes[n_u, n_c].set_yticks(np.arange(0, n_ant, 1), minor=True) axes[n_u, n_c].grid(which='minor', color='0.75', linestyle='-', linewidth=0.05) cbar = plt.colorbar(c[-1], ax=axes.ravel().tolist(), ticks=np.linspace(0, 100, 11), orientation='horizontal') cbar.ax.set_xticklabels(['0%', '10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', '100%']) fig, axes = plt.subplots(nrows=n_ue, ncols=n_cell, squeeze=False) c = [] fig.suptitle('Frame Map') for n_c in range(n_cell): for n_u in range(n_ue): c.append( axes[n_u, n_c].imshow(frame_map[:,n_c,n_u,:].T, cmap=plt.cm.get_cmap('Blues', 3), interpolation='none', extent=[n_frm_st,n_frm_end, n_ant,0], aspect="auto") ) axes[n_u, n_c].set_title('Cell {} UE {}'.format(n_c, n_u)) axes[n_u, n_c].set_ylabel('Antenna #') axes[n_u, n_c].set_xlabel('Frame #') # Minor ticks axes[n_u, n_c].set_xticks(np.arange(n_frm_st, n_frm_end, 1), minor=True) axes[n_u, n_c].set_yticks(np.arange(0, n_ant, 1), minor=True) # Gridlines based on minor ticks axes[n_u, n_c].grid(which='minor', color='0.75', linestyle='-', linewidth=0.1) cbar = plt.colorbar(c[-1], ax=axes.ravel().tolist(), ticks=[-1, 0, 1], orientation = 'horizontal') cbar.ax.set_xticklabels(['Bad Frame', 'Probably partial/corrupt', 'Good Frame']) ##plt.show() ############# # SNR MAP # ############# if noise_avail: fig, axes = plt.subplots(nrows=n_ue, ncols=n_cell, squeeze=False) c = [] fig.suptitle('SNR Map') for n_c in range(n_cell): for n_u in range(n_ue): c.append( axes[n_u, n_c].imshow(snr[:, n_c, n_u, :].T, vmin=np.min(snr), vmax=np.max(snr), cmap='Blues', interpolation='nearest', extent=[n_frm_st, n_frm_end, n_ant, 0], aspect="auto")) axes[n_u, n_c].set_title('Cell {} UE {}'.format(n_c, n_u)) axes[n_u, n_c].set_ylabel('Antenna #') axes[n_u, n_c].set_xlabel('Frame #') axes[n_u, n_c].set_xticks(np.arange(n_frm_st, n_frm_end, 1), minor=True) axes[n_u, n_c].set_yticks(np.arange(0, n_ant, 1), minor=True) axes[n_u, n_c].grid(which='minor', color='0.75', linestyle='-', linewidth=0.05) cbar = plt.colorbar(c[-1], ax=axes.ravel().tolist(), ticks=np.linspace(0, np.max(snr), 10), orientation='horizontal') plt.show() else: plt.show()