def offAngleLoop2(file,inPulse,channel,antHeight=[]): """ the thing in doOffAngle that gets the waveform and processes it The main one was doing an fft average on top of time averaging, and I want to try without that -> Nope, doesn't help """ inPulseF,inPulseFFT = inPulse inPulseX,inPulseY = tf.genTimeSeries(inPulseF,inPulseFFT) if len(antHeight) != 0: antHeightF,antHeightFFT = antHeight antHeightX,antHeightY = tf.genTimeSeries(antHeightF,antHeightFFT) #import all the events from that file (it is stored with a ton of events in it) events = importAll(file,channel=channel) print "doOffAngle(): ",file," has number of events:",len(events) avgEventX,avgEventY = tf.correlateAndAverage(events) avgEventX *= 1e9 #also sampled too fast, so lets just do the FFT trick to downsample it again avgEventF,avgEventFFT = tf.genFFT(avgEventX,avgEventY) avgEventF = avgEventF[:1001] avgEventFFT = avgEventFFT[:1001] avgEventX,avgEventY = tf.genTimeSeries(avgEventF,avgEventFFT) #it is also too long avgEventX = avgEventX[:1000] avgEventY = avgEventY[:1000] avgEventF,avgEventFFT = tf.genFFT(avgEventX,avgEventY) if debug: print "doOffAngle(): avgEvent length: ",len(avgEventX)," dT:",avgEventX[1]-avgEventX[0] if len(antHeight) != 0: print "doOffAngle(): antHeight length: ",len(antHeightX)," dT:",antHeightX[1]-antHeightX[0] print "doOffAngle(): inPulse length: ",len(inPulseX)," dT:",inPulseX[1]-inPulseX[0] print "doOffAngle(): avgEventFFT length: ",len(avgEventF),"/",len(avgEventFFT)," dF:",avgEventF[1]-avgEventF[0] if len(antHeight) != 0: print "doOffAngle(): antHeightFFT length: ",len(antHeightF),"/",len(antHeightFFT)," dF:",antHeightF[1]-antHeightF[0] print "doOffAngle(): inPulseFFT length: ",len(inPulseF),"/",len(inPulseFFT)," dF:",inPulseF[1]-inPulseF[0] #generate the transfer function if len(antHeight) == 0: transFuncF,transFuncFFT = doChamberIdenticalTF(avgEventF,avgEventFFT,inPulseFFT) else: transFuncF,transFuncFFT = doChamberRotatedTF(avgEventF,avgEventFFT,inPulseFFT,antHeightFFT) return transFuncF,transFuncFFT
def addNoise(sigWaveX,sigWaveY,snr,showPlots=False): length = len(sigWaveX) sigWaveY /= np.std(sigWaveY) sigWaveY /= np.sqrt(length) sigWaveY *= snr noiseX = np.arange(0,length)*0.1 noiseY = makeNoise(length) #normalized to one already noiseF,noiseFFT = tf.genFFT(noiseX,noiseY) sigF,sigFFT = tf.genFFT(sigWaveX,sigWaveY) convolved = sigFFT+noiseFFT outX,outY = tf.genTimeSeries(sigF,convolved) outY /= np.std(outY) outY /= np.sqrt(length) if showPlots: fig,ax = lab.subplots(3,2) ax[0][0].plot(sigWaveX,sigWaveY,color="blue",label="signal") ax[0][0].legend() ax[2][0].plot(noiseX,noiseY,color="red",label="noise") ax[2][0].legend() ax[1][0].plot(outX,outY,color="purple",label="convolution") ax[1][0].legend() ax[0][1].plot(sigF,tf.calcLogMag(sigF,sigFFT),color="blue",label="signal") ax[0][1].legend() ax[2][1].plot(noiseF,tf.calcLogMag(noiseF,noiseFFT),color="red",label="noise") ax[2][1].set_ylim([-30,30]) ax[2][1].legend() ax[1][1].plot(sigF,tf.calcLogMag(sigF,convolved),color="purple",label="convolution") ax[1][1].set_ylim([-30,30]) ax[1][1].legend() fig.show() return outX,outY
def computeTF(inF, inFFT, outF, outFFT): """ Generating the transfer function is always the same, so it gets its own class Comparable to "deconvwnr()" in matlab (nearly identical) It has a bunch of other things you can uncomment to use, but most end up being dumb """ #then generate the transfer function! #In(f)*H(f) = Out(f) -> H(f) = Out(f)/In(f) tfFFT = np.divide(outFFT, inFFT) tfF = inF tfY = tf.fftw.irfft(tfFFT) # print tfY tfX = np.arange(0, len(tfY)) * (1. / (2. * tfF[-1])) tfF, tfFFT = tf.genFFT(tfX, tfY) return tfX, tfY, tfF, tfFFT
def HpolTransferFunctionAnalysis(pulse=False,respo=False,makeFigs=False): #import stuff if type(pulse)==bool and type(respo)==bool: print "type(pulse)" pulse = antChamberResponse(chamberRefPulse,channel=0) respo = antChamberResponse("/Volumes/BenANITA3Data/Anechoic_Chamber_New_Horn_Impulse/IdenticalAntennas/Ant2Blue_to_Ant0/HPol_Pulse/Impulse_p180Deg_t090Deg_16May2012_H.dat") #quickly making them have the same time steps pulseArgMax = np.argmax(pulse[1]) respoArgMax = np.argmax(respo[1]) offset = pulseArgMax - respoArgMax dT = (pulse[0][1] - pulse[0][0]) pulseNewT = (np.arange(0,len(pulse[0]))-pulseArgMax)*dT respoNewT = (np.arange(0,len(respo[0]))-respoArgMax)*dT #make a quick plot of that if makeFigs==True: figInWaves = lab.figure(figsize=(16,8)) axInWaves1 = figInWaves.add_subplot(111) axInWaves1.plot(pulseNewT,pulse[1],color="red",lw=1,alpha=0.6) axInWaves1.set_xlabel("Time (ns)") axInWaves1.set_ylabel("Input Pulse (V)",color="red") axInWaves1.set_title("HPol chamber input and output pulses") axInWaves2 = axInWaves1.twinx() axInWaves2.plot(respoNewT,respo[1],color="blue",lw=1,alpha=0.6) axInWaves2.set_ylabel("Recieved Pulse (V)",color="blue") axInWaves2.grid(b=True,which="major",color="white",linestyle="--") figInWaves.show() figInWaves.savefig("HpolBoresightWaveforms.png") #take the fourier transform pulseF,pulseFFT = tf.genFFT(pulseNewT,pulse) respoF,respoFFT = tf.genFFT(respoNewT,respo) #plot the log magnitude of that pulseLogMag = tf.calcLogMag(pulseF,pulseFFT) respoLogMag = tf.calcLogMag(respoF,respoFFT) if makeFigs == True: figLogMag = lab.figure(figsize=(16,8)) axLogMag1 = figLogMag.add_subplot(111) axLogMag1.plot(pulseF,pulseLogMag,color="red",lw=1,alpha=0.6) axLogMag1.set_xlabel("Frequency (GHz)") axLogMag1.set_ylabel("Input Pulse (dBm)",color="red") axLogMag1.set_title("HPol chamber input and output spectral magnitude") axLogMag2 = axLogMag1.twinx() axLogMag2.plot(respoF,respoLogMag,color="blue",lw=1,alpha=0.6) axLogMag2.set_ylabel("Recieved Pulse (dBm)",color="blue") axLogMag2.grid(b=True,which="major",color="white",linestyle="--") figLogMag.show() figLogMag.savefig("HpolBoresightMagnitudes.png") #generate a transfer function transFFT = respoFFT/pulseFFT #Also cut off the top frequencies (since there isn't any power there) cutFraction = 4 trans = tf.fftw.irfft(transFFT[:len(respo[0])/(cutFraction*2)+1]) transNewT = respoNewT[::cutFraction] #it is phase aligned at zero and I want it to start in like 10a trans = np.roll(trans,len(respo[0])/10) if makeFigs == True: figTrans = lab.figure(figsize=(16,8)) axTrans = figTrans.add_subplot(111) axTrans.plot(respoNewT[::4],trans) axTrans.set_xlabel("Time (ns)") axTrans.set_ylabel("Transfer Function (V)",color="black") axTrans.set_title("HPol Chamber Boresight Transfer Function") figTrans.show() figTrans.savefig("HpolBoresightTransferFunction.png") return transNewT,trans
def ANITA3_chamberResponse(files=-1,rotate="phi",channel=1,eventAvgs=50): #imports and generates some arrays for angle, frequency, and spectral magnitude of # correlated and averaged waveforms in a series of chamber data #the defaults are for HPol rotating in phi, but you can do others. # channel==0 is Vpol and channel==1 is Hpol (I think) if files==-1: files = localFileList_ANITA3chamberHPol() freqs = [] allFreqs = [] mags = [] allMags = [] angles = [] #params numFreqs = 25 stop = 100 #~1GHz start = 2 step = stop/float(numFreqs) sns.set_palette(sns.color_palette("husl",numFreqs)) inPulse = antChamberResponse(chamberRefPulse,channel=0) for file in files: events = importAll(file,channel=channel) print len(events) fftAvgs = len(events)/eventAvgs for fftAvgNum in range(0,fftAvgs): avgEvent = tf.correlateAndAverage(events[eventAvgs*fftAvgNum:eventAvgs*(fftAvgNum+1)]) peak = np.argmax(np.abs(avgEvent[1])) + 500 print "I'M CRAB V.v.V" procAvgEvent = processAllEvents([avgEvent],totalWidth=2000,peak=peak)[0] transFunc = HpolTransferFunctionAnalysis(pulse=inPulse,respo=procAvgEvent) #friis equation transforms to S21! (Gr*Gt)/(4*pi*R/lambda)**2 R=5.9 f,fft = tf.genFFT(transFunc[0],transFunc[1]) friis = (fft**2)/(4.*np.pi*R*f*3e8)**2 logMag = tf.calcLogMag(f,friis*1000) if freqs == []: freqs = np.ceil(f[start:stop:step]/1e6) allFreqs = np.ceil(f[start:stop]/1e6) if fftAvgNum == 0: logMagAvg = logMag/fftAvgs else: logMagAvg += logMag/fftAvgs mags.append(logMagAvg[start:stop:step]) allMags.append(logMagAvg[start:stop]) if rotate=="phi": angles.append(file.split("/")[-1].split("_")[1][1:4]) if rotate=="theta": angles.append(file.split("/")[-1].split("_")[2][1:4]) print(len(freqs)) lab.close("all") fig = lab.figure() ax = fig.add_subplot(111) for freqNum in range(0,numFreqs): curve = [] for angleNum in range(0,len(angles)): curve.append(mags[angleNum][freqNum]) curve = np.array(curve)-np.max(curve) ax.plot(angles,curve,label=freqs[freqNum]) ax.legend() fig.show() return angles,allFreqs,allMags
def offAngleLoop(file,inPulse,channel,antHeight=[]): """ Theres a loop in doOffAngle that I want to split out antHeightFFT: boresight complex antenna height for identical antennas dont set this parameter and it will treat them as identical for rotated antennas, set this to the boresight complex antenna height and it will determine the rotated height """ inPulseF,inPulseFFT = inPulse inPulseX,inPulseY = tf.genTimeSeries(inPulseF,inPulseFFT) if len(antHeight) != 0: antHeightF,antHeightFFT = antHeight antHeightX,antHeightY = tf.genTimeSeries(antHeightF,antHeightFFT) #import all the events from that file (it is stored with a ton of events in it) events = importAll(file,channel=channel) print "doOffAngle(): ",file," has number of events:",len(events) fftAvgs = len(events)/eventAvgs print "doOffAngle(): doing ",fftAvgs," fft averages" #so first I average together a bunch of events, then I average the FFTs of the transfer functions together? for fftAvgNum in range(0,fftAvgs): #get the averaged waveform avgEventX,avgEventY = tf.correlateAndAverage(events[eventAvgs*fftAvgNum:eventAvgs*(fftAvgNum+1)]) avgEventX *= 1e9 #also sampled too fast, so lets just do the FFT trick to downsample it again avgEventF,avgEventFFT = tf.genFFT(avgEventX,avgEventY) avgEventF = avgEventF[:1001] avgEventFFT = avgEventFFT[:1001] avgEventX,avgEventY = tf.genTimeSeries(avgEventF,avgEventFFT) #it is also too long avgEventX = avgEventX[:1000] avgEventY = avgEventY[:1000] print len(avgEventX),len(avgEventY) avgEventF,avgEventFFT = tf.genFFT(avgEventX,avgEventY) print len(avgEventF),len(avgEventFFT) if debug: print "doOffAngle(): avgEvent length: ",len(avgEventX)," dT:",avgEventX[1]-avgEventX[0] if len(antHeight) != 0: print "doOffAngle(): antHeight length: ",len(antHeightX)," dT:",antHeightX[1]-antHeightX[0] print "doOffAngle(): inPulse length: ",len(inPulseX)," dT:",inPulseX[1]-inPulseX[0] print "doOffAngle(): avgEventFFT length: ",len(avgEventF),"/",len(avgEventFFT)," dF:",avgEventF[1]-avgEventF[0] if len(antHeight) != 0: print "doOffAngle(): antHeightFFT length: ",len(antHeightF),"/",len(antHeightFFT)," dF:",antHeightF[1]-antHeightF[0] print "doOffAngle(): inPulseFFT length: ",len(inPulseF),"/",len(inPulseFFT)," dF:",inPulseF[1]-inPulseF[0] #find its peak (with some offset for some reason) peak = np.argmax(np.abs(avgEventY[1])) + 500 print "I'M CRAB V.v.V ",fftAvgNum #for fun #generate the transfer function if len(antHeight) == 0: transFuncF,transFuncFFT = doChamberIdenticalTF(avgEventF,avgEventFFT,inPulseFFT) else: transFuncF,transFuncFFT = doChamberRotatedTF(avgEventF,avgEventFFT,inPulseFFT,antHeightFFT) if fftAvgNum == 0: fftAvg = transFuncFFT/fftAvgs else: fftAvg += transFuncFFT/fftAvgs return transFuncF,fftAvg
def doOffAngle(pol="H"): """ April 2017 Its been awhile since I worked with this, so I'm going to write a new function so I know it is right and I don't mess up any of the old stuff just in case This uses the complex antenna height generated with doPalAnt in transferFunctionFinal, as only one antenna was rotated, so they cannot be treated as identical and a single antenna needs to be deconvolved """ #get a list of the files, which should be all the angles if pol=="H": files = localFileList_ANITA3chamberHPol() rotate="phi" channel = 1 if pol=="V": files = localFileList_ANITA3chamberVPol() rotate="theta" channel = 0 freqs = [] allFreqs = [] mags = [] allMags = [] angles = [] #params for making contour plot numFreqs = 25 stop = 100 #~1GHz start = 2 step = stop/float(numFreqs) sns.set_palette(sns.color_palette("husl",numFreqs)) #get the input pulse inPulseX,inPulseY = antChamberResponse(chamberRefPulse,channel=0) #I'm doing things in nanoseconds so lets keep doing that inPulseX *= 1e9 #also it is sampled too fast, so lets just do the FFT trick to downsample it inPulseF,inPulseFFT = tf.genFFT(inPulseX,inPulseY) inPulseF = inPulseF[:501] inPulseFFT = inPulseFFT[:501] inPulseX,inPulseY = tf.genTimeSeries(inPulseF,inPulseFFT) #get the complex antenna height from tff.doPalAnt's results #also note that I am cutting the end off so it is only 1000 points long # -> This doesn't work because the chamber measurements are shitty at low end so it messes the whole thing up palAntHeightX,palAntHeightY = np.loadtxt("/Users/brotter/benCode/impulseResponse/integratedTF/transferFunctions/antHeight_avg.txt")[:1000].T palAntHeightF,palAntHeightFFT = tf.genFFT(palAntHeightX,palAntHeightY) #grab the CHAMBER boresight and use that I guess boresight = files[4] antHeightF,antHeightFFT = offAngleLoop2(boresight,[inPulseF,inPulseFFT],channel) if debug: fig,ax = lab.subplots() ax.plot(antHeightF,tf.calcAntGain(antHeightF,antHeightFFT),label="chamber",color="red") ax.plot(palAntHeightF,tf.calcAntGain(palAntHeightF,palAntHeightFFT),label="palestine",color="blue") ax.set_xlabel("Frequency (GHz)") ax.set_ylabel("Antenna Gain (dBi)") ax.legend() fig.show() #loop over all the files for file in files: transFuncF,transFuncFFT = offAngleLoop2(file,[inPulseF,inPulseFFT],channel,antHeight=[antHeightF,antHeightFFT]) logMagAvg = tf.calcAntGain(transFuncF,transFuncFFT) mags.append(logMagAvg) allMags.append(logMagAvg) if rotate=="phi": angles.append(file.split("/")[-1].split("_")[1][1:4]) if rotate=="theta": angles.append(file.split("/")[-1].split("_")[2][1:4]) return angles,transFuncF,allMags,tf.calcAntGain(antHeightF,antHeightFFT)