def vec2scalA(self, At, Ar, alpha=1.0): """ vec2scalA(self,At,Ar,alpha=1.0): At = transmitter antenna Ar = receiver antenna Calculate ScalChannel by combining the propagation channel VectChannel with realistic antennas transfer function alpha : normalization factor """ Ftt, Ftp = At.Fsynth3(self.rang[:, 0], self.rang[:, 1]) Frt, Frp = Ar.Fsynth3(self.rang[:, 0], self.rang[:, 1]) Ftt = Ftt.transpose() Ftp = Ftp.transpose() Frt = Frt.transpose() Frp = Frp.transpose() Ftt = bs.FUsignal(At.fa, Ftt * alpha) Ftp = bs.FUsignal(At.fa, Ftp * alpha) Frt = bs.FUsignal(Ar.fa, Frt * alpha) Frp = bs.FUsignal(Ar.fa, Frp * alpha) scalch = ScalChannel(self, Ftt, Ftp, Frt, Frp) return(scalch)
def VCg2VCl(VCg, Tt, Tr): """ global reference frame to local reference frame Parameters ---------- VCg : VectChannel global Tt : Tx rotation matrix Tr : Rx rotation matrix Returns ------- VCl : VectChannel (local) """ import copy VCl = copy.deepcopy(VCg) freq = VCl.freq Rt, tangl = BTB_tx(VCg.tang, Tt) Rr, rangl = BTB_rx(VCg.rang, Tr) VCl.tang = tangl VCl.rang = rangl uf = np.ones(VCg.nfreq) r0 = np.outer(Rr[0, 0, :], uf) r1 = np.outer(Rr[0, 1, :], uf) # print "shape r0 = ",np.shape(r0) # print "shape VCg.Ctt.y = ",np.shape(VCg.Ctt.y) # print "shape r1 = ",np.shape(r1) # print "shape VCg.Cpt.y = ",np.shape(VCg.Cpt.y) t00 = r0 * VCg.Ctt.y + r1 * VCg.Cpt.y t01 = r0 * VCg.Ctp.y + r1 * VCg.Cpp.y r0 = np.outer(Rr[1, 0, :], uf) r1 = np.pouter(Rr[1, 1, :], uf) t10 = r0 * VCg.Ctt.y + r1 * VCg.Cpt.y t11 = r0 * VCg.Ctp.y + r1 * VCg.Cpp.y r0 = np.outer(Rt[0, 0, :], uf) r1 = np.outer(Rt[1, 0, :], uf) Cttl = t00 * r0 + t01 * r1 Cptl = t10 * r0 + t11 * r1 r0 = np.outer(Rt[0, 1, :], uf) r1 = np.outer(Rt[1, 1, :], uf) Ctpl = t00 * r0 + t01 * r1 Cppl = t10 * r0 + t11 * r1 VCl.Ctt = bs.FUsignal(freq, Cttl) VCl.Ctp = bs.FUsignal(freq, Ctpl) VCl.Cpt = bs.FUsignal(freq, Cptl) VCl.Cpp = bs.FUsignal(freq, Cppl) return VCl
def __init__(self, d, fmin=2, fmax=11, Nf=180): self.tauk = np.array([d / 0.3]) freq = np.linspace(fmin, fmax, Nf) c1 = 1.0 / d * np.ones(len(freq)) c2 = zeros(len(freq)) c1.reshape(1, Nf) c2.reshape(1, Nf) self.freq = freq self.Ctt = bs.FUsignal(freq, c1) self.Ctp = bs.FUsignal(freq, c2) self.Cpt = bs.FUsignal(freq, c2) self.Cpp = bs.FUsignal(freq, c1) self.tang = array([0]) self.rang = array([0]) self.nray = 1
def eval(self): u""" evaluate waveform The :math:`\lambda/4*\pi` factor which is necessary to get the proper budget link ( from the Friis formula) is introduced in this function. """ if self['typ'] == 'generic': [st, sf] = self.ip_generic() #elif self['typ'] == 'mbofdm': # [st,sf]=self.mbofdm() elif self['typ'] == 'W1compensate': [st, sf] = self.fromfile() elif self['typ'] == 'W1offset': [st, sf] = self.fromfile2() else: logging.critical('waveform typ not recognized, check your config \ file') self.st = st self.sf = sf self.f = self.sf.x ygamma = -1j * 0.3 / (4 * np.pi * self.f) self.gamm = bs.FUsignal(x=self.f, y=ygamma) self.sfg = self.sf * self.gamm self.sfgh = self.sfg.symH(0) self.stgh = self.sfgh.ifft(1)
def vec2scal(self): """ calculate scalChannel from VectChannel and antenna Returns ------- slach : ScalChannel """ freq = self.freq sh = np.shape(self.Ctt.y) Ftt = bs.FUsignal(freq, np.ones(sh)) Ftp = bs.FUsignal(freq, np.zeros(sh)) Frt = bs.FUsignal(freq, np.ones(sh)) Frp = bs.FUsignal(freq, np.zeros(sh)) scalch = ScalChannel(self, Ftt, Ftp, Frt, Frp) return(scalch)
def freqz(self,**kwargs): """ freqz : evaluation of filter transfer function The function evaluates an FUsignal Parameters ---------- display : boolean True fsGHz : float if set to 0 (relative frequency) """ defaults = {'display':True, 'fsGHz':0} for k in defaults: if k not in kwargs: kwargs[k]=defaults[k] (w,h) = si.freqz(self.b,self.a) if kwargs['fsGHz']!=0: fNGHz = kwargs['fsGHz']/2. self.H = bs.FUsignal(w*fNGHz/np.pi,h) xlabel = 'Frequency (GHz)' else: self.H = bs.FUsignal(w/np.pi,h) xlabel = 'Relative frequency' if kwargs['display']: if 'fig' not in kwargs: fig = plt.figure() else: fig = kwargs['fig'] ax1 = fig.add_subplot(211) self.H.plot(typ=['l20'],xlabels=[xlabel],fig=fig,ax=ax1) plt.grid() ax2 = fig.add_subplot(212) self.H.plot(typ=['d'],xlabels=[xlabel],fig=fig,ax=ax2) plt.grid()
def eval(self): """ evaluate waveform The lambda/4*pi factor which is necessary to get the proper budget link ( from the fris formula) is introduced in this function. """ if self.parameters['type'] == 'generic': [st,sf]=self.ip_generic() if self.parameters['type'] == 'mbofdm': [st,sf]=self.mbofdm() if self.parameters['type'] == 'file': [st,sf]=self.fromfile() self.st = st self.sf = sf self.f = self.sf.x ygamma = -1j*0.3/(4*np.pi*self.f) self.gamm = bs.FUsignal(self.f,ygamma) self.sfg = self.sf*self.gamm self.sfgh = self.sfg.symH(0) self.stgh = self.sfgh.ifft(1)
def eval(self, fGHz=np.array([2.4])): """docstring for eval""" print 'Rays evaluation' self.I.eval(fGHz) B = self.B.eval(fGHz) B0 = self.B0.eval(fGHz) # Ct : f x r x 2 x 2 Ct = np.zeros((self.I.nf, self.nray, 2, 2), dtype=complex) # delays : ,r self.delays = np.zeros((self.nray)) # dis : ,r self.dis = np.zeros((self.nray)) #nf : number of frequency point nf = self.I.nf aod = np.empty((2, self.nray)) aoa = np.empty((2, self.nray)) # loop on interaction blocks for l in self: # l stands for the number of interactions r = self[l]['nbrays'] # reshape in order to have a 1D list of index # reshape ray index rrl = self[l]['rays'].reshape(r * l, order='F') # get the corresponding evaluated interactions A = self.I.I[:, rrl, :, :].reshape(self.I.nf, r, l, 2, 2, order='F') Bl = B[:, rrl, :, :].reshape(self.I.nf, r, l, 2, 2, order='F') B0l = B0[:, self[l]['rayidx'], :, :] alpha = self.I.alpha[rrl].reshape(r, l, order='F') gamma = self.I.gamma[rrl].reshape(r, l, order='F') si0 = self.I.si0[rrl].reshape(r, l, order='F') sout = self.I.sout[rrl].reshape(r, l, order='F') aoa[:, self[l]['rayidx']] = self[l]['aoa'] aod[:, self[l]['rayidx']] = self[l]['aod'] try: del Z except: pass ## loop on all the interactions of ray with l interactions for i in range(0, l): ############################################ ## # Divergence factor D ### not yet implementented ############################################ # if i == 0: # D0=1./si0[:,1] # rho1=si0[:,1]*alpha[:,i] # rho2=si0[:,1]*alpha[:,i]*gamma[:,i] # D=np.sqrt( # ( (rho1 ) / (rho1 + sout[:,i]) ) # *( (rho2) / (rho2 + sout[:,i]))) # D=D*D0 # rho1=rho1+(sout[:,i]*alpha[:,i]) # rho2=rho2+(sout[:,i]*alpha[:,i]*gamma[:,i]) ## gerer le loss # if np.isnan(D).any(): # p=np.nonzero(np.isnan(D))[0] # D[p]=1./sout[p,1] # else : # D=np.sqrt( # ( (rho1 ) / (rho1 + sout[:,i]) ) # *( (rho2) / (rho2 + sout[:,i]))) # rho1=rho1+(sout[:,i]*alpha[:,i]) # rho2=rho2+(sout[:,i]*alpha[:,i]*gamma[:,i]) ############################################ # A0 (X dot Y) # | | | # v v v ########################## ## B # I # B # I # B # ########################## # \_____/ \______/ # | | # Atmp(i) Atmp(i+1) # # Z=Atmp(i) dot Atmp(i+1) X = A[:, :, i, :, :] Y = Bl[:, :, i, :, :] ## Dot product interaction X Basis Atmp = np.sum(X[..., :, :, np.newaxis] * Y[..., np.newaxis, :, :], axis=-2) #*D[np.newaxis,:,np.newaxis,np.newaxis] if i == 0: ## First Baspdis added A0 = B0l[:, :, :, :] Z = np.sum(A0[..., :, :, np.newaxis] * Atmp[..., np.newaxis, :, :], axis=-2) else: # dot product previous interaction with latest Z = np.sum(Z[..., :, :, np.newaxis] * Atmp[..., np.newaxis, :, :], axis=-2) # fill the C tilde Ct[:, self[l]['rayidx'], :, :] = Z[:, :, :, :] # delay computation: self[l]['dis'] = self.I.si0[self[l]['rays'][0, :]] + np.sum( self.I.sout[self[l]['rays']], axis=0) # Power losses due to distances # will be removed once the divergence factor will be implemented Ct[:, self[l]['rayidx'], :, :] = Ct[:, self[l]['rayidx'], :, :] * 1. / ( self[l]['dis'][np.newaxis, :, np.newaxis, np.newaxis]) self.delays[self[l]['rayidx']] = self[l]['dis'] / 0.3 self.dis[self[l]['rayidx']] = self[l]['dis'] # To be corrected in a future version Ct = np.swapaxes(Ct, 1, 0) c11 = Ct[:, :, 0, 0] c12 = Ct[:, :, 0, 1] c21 = Ct[:, :, 1, 0] c22 = Ct[:, :, 1, 1] Cn = Ctilde() Cn.Cpp = bs.FUsignal(self.I.fGHz, c11) Cn.Ctp = bs.FUsignal(self.I.fGHz, c12) Cn.Cpt = bs.FUsignal(self.I.fGHz, c21) Cn.Ctt = bs.FUsignal(self.I.fGHz, c22) Cn.nfreq = self.I.nf Cn.nray = self.nray Cn.tauk = self.delays Cn.fGHz = self.I.fGHz # r x 2 Cn.tang = aod.T # r x 2 Cn.rang = aoa.T # add aoa and aod return (Cn)
freq = Gt.I.f nfreq = Gt.I.nf nray = np.array(([Gt.nray])) Cr = np.swapaxes(Gt.Ctilde, 1, 0) #Cr=Gt.Ctilde.reshape(nray, nfreq,2,2) #Cr=np.transpose(Gt.Ctilde,(1,0,2,3)) c11 = Cr[:, :, 0, 0] c12 = Cr[:, :, 0, 1] c21 = Cr[:, :, 1, 0] c22 = Cr[:, :, 1, 1] Cn = Ctilde() Cn.Cpp = bs.FUsignal(freq, c11) Cn.Ctp = bs.FUsignal(freq, c12) Cn.Cpt = bs.FUsignal(freq, c21) Cn.Ctt = bs.FUsignal(freq, c22) Cn.nfreq = Gt.I.nf Cn.nray = Gt.nray Cn.tauk = Gt.delays r = 0 plotray(r) ### RECIPROCITY TEST #S2 = Simul() ## loading a layout #filestr = 'defstr'
def load(self, filefield, transpose=False): """ load a Ctilde from a .field file Load the three files .tauk .tang .rang which contain respectively delay , angle of departure , angle of arrival. Parameters ---------- filefield : string transpose : boolean default False Examples -------- >>> from pylayers.antprop.channel import * >>> from pylayers.simul.simulem import * >>> S=Simul() >>> S.load('default.ini') >>> C =Ctilde() >>> C.load(pyu.getlong(S.dtud[1][1],'output')) """ filetauk = filefield.replace('.field', '.tauk') filetang = filefield.replace('.field', '.tang') filerang = filefield.replace('.field', '.rang') try: fo = open(filefield, "rb") except: raise NameError( "file "+ filefield+ " is unreachable") # decode filename (*.field file obtained from evalfield simulation) nray = stru.unpack('i', fo.read(4))[0] print "nray : ", nray nfreq = stru.unpack('i', fo.read(4))[0] print "nfreq : ", nfreq if nfreq == 0: print " Error : incorrect number of frequency points in .field" self.fail = True return n = nray * nfreq buf = fo.read() fo.close() CMat = np.ndarray(shape=(n,8),buffer=buf) c11 = CMat[:, 0] + CMat[:, 1]*1j c12 = CMat[:, 2] + CMat[:, 3]*1j c21 = CMat[:, 4] + CMat[:, 5]*1j c22 = CMat[:, 6] + CMat[:, 7]*1j c11 = c11.reshape(nray, nfreq) c12 = c12.reshape(nray, nfreq) c21 = c21.reshape(nray, nfreq) c22 = c22.reshape(nray, nfreq) if transpose: c11 = c11.transpose() c12 = c12.transpose() c21 = c21.transpose() c22 = c22.transpose() # # Temporary freq --> read filefreq # freq = np.linspace(2, 11, nfreq) self.Ctt = bs.FUsignal(freq, c11) self.Ctp = bs.FUsignal(freq, c12) self.Cpt = bs.FUsignal(freq, c21) self.Cpp = bs.FUsignal(freq, c22) self.nfreq = nfreq self.nray = nray try: fo = open(filetauk, "rb") except: self.fail = True print "file ", filetauk, " is unreachable" # decode filetauk if not self.fail: nray_tauk = stru.unpack('i', fo.read(4))[0] print "nb rays in .tauk file: ", nray_tauk buf = fo.read() fo.close() nray = len(buf) / 8 print "nb rays 2: ", nray self.tauk = np.ndarray(shape=nray, buffer=buf) if nray_tauk != nray: print nray_tauk - nray self.tauk = self.tauk # decode the angular files (.tang and .rang) try: fo = open(filetang, "rb") except: self.fail = True print "file ", filetang, " is unreachable" if not self.fail: nray_tang = stru.unpack('i', fo.read(4))[0] buf = fo.read() fo.close() # coorectif Bug evalfield tmp = np.ndarray(shape=(nray_tang, 2), buffer=buf) self.tang = tmp[0:nray, :] try: fo = open(filerang, "rb") except: self.fail = True print "file ", filerang, " is unreachable" if not self.fail: nray_rang = stru.unpack('i', fo.read(4))[0] buf = fo.read() fo.close() # coorectif Bug evalfield tmp = np.ndarray(shape=(nray_rang, 2), buffer=buf) self.rang = tmp[0:nray, :]
def prop2tran(self,a='theta',b='theta'): """ transform propagation channel into transmission channel Parameters ---------- a : string or antenna array polarization antenna a ( 'theta' | 'phi' | 'ant' ) : string or antenna array polarization antenna b ( 'theta' | 'phi' | 'ant' ) 0 : theta 1 : phi Returns ------- H : Tchannel(bs.FUDAsignal) """ freq = self.freq nfreq = self.nfreq nray = self.nray sh = np.shape(self.Ctt.y) if type(a)==str: Fat = np.zeros(nray*nfreq).reshape((nray,nfreq)) Fap = np.zeros(nray*nfreq).reshape((nray,nfreq)) if a=='theta': Fat = np.ones((nray,nfreq)) if a=='phi': Fap = np.ones((nray,nfreq)) Fat = bs.FUsignal(self.freq,Fat) Fap = bs.FUsignal(self.freq,Fap) else: Fat , Fap = a.Fsynth3(self.rang[:, 0],self.rang[:,1]) Fat = Fat.transpose() Fap = Fap.transpose() Fat = bs.FUsignal(a.fa,Fat) Fap = bs.FUsignal(a.fa,Fap) if type(b)==str: Fbt = np.zeros(nray*nfreq).reshape((nray,nfreq)) Fbp = np.zeros(nray*nfreq).reshape((nray,nfreq)) if b=='theta': Fbt = np.ones((nray,nfreq)) if b=='phi': Fbp = np.ones((nray,nfreq)) Fbt = bs.FUsignal(self.freq,Fbt) Fbp = bs.FUsignal(self.freq,Fbp) else: Fbt , Fbp = b.Fsynth3(self.rang[:, 0],self.rang[:,1]) # (nray,nfeq) needed Fbt = Fbt.transpose() Fbp = Fbp.transpose() Fbt = bs.FUsignal(b.fa,Fbt) Fbp = bs.FUsignal(b.fa,Fbp) #pdb.set_trace() t1 = self.Ctt * Fat + self.Cpt * Fap t2 = self.Ctp * Fat + self.Cpp * Fap alpha = t1 * Fbt + t2 * Fbp H = Tchannel(alpha.x,alpha.y,self.tauk,self.tang,self.rang) return(H)