def reGrid(self,noise_dT=3,noise_avg=3): self.tPumpSkew,self.dTskew=Skew(self.tTHz,self.tPump,self.dT,noise_dT) self.dTSkewFFT=np_rfft(self.dTskew,axis=1) self.tPumpSkew,self.avgSkew=Skew(self.tTHz,self.tPump, self.avg,noise_avg) self.avgSkewFFT=np_rfft(self.avgSkew,axis=1) return
def fourier_integral_midpoint(integrand, a, b, N): """ approximates int_a^b dx integrand(x) by the riemann sum with N terms and the most simplest uniform midpoint weights """ #log.debug("integrate over [{:.3e},{:.3e}] using {} points".format(a,b,N)) delta_x = (b-a)/N delta_k = 2*np.pi/(b-a) yl = integrand(np.linspace(a+delta_x/2, b+delta_x/2, N, endpoint=False)) fft_vals = np_rfft(yl) tau = np.arange(len(fft_vals))*delta_k #log.debug("yields d_x={:.3e}, d_k={:.3e} kmax={:.3e}".format(delta_x, delta_k, tau[-1])) return tau, delta_x*np.exp(-1j*tau*(a+delta_x/2))*fft_vals
def fourier_integral_simps(integrand, a, b, N): """ approximates int_a^b dx integrand(x) by the riemann sum with N terms using simpson integration scheme """ delta_x = (b - a) / (N - 1) delta_k = 2 * np.pi / N / delta_x l = np.arange(0, N) yl = integrand(a + l * delta_x) yl = get_fourier_integral_simps_weighted_values(yl) fft_vals = np_rfft(yl) tau = np.arange(len(fft_vals)) * delta_k return tau, delta_x * np.exp(-1j * tau * a) * fft_vals
def fourier_integral_midpoint(integrand, a, b, N): """ approximates int_a^b dx integrand(x) by the riemann sum with N terms and the most simplest uniform midpoint weights """ #log.debug("integrate over [{:.3e},{:.3e}] using {} points".format(a,b,N)) delta_x = (b - a) / N delta_k = 2 * np.pi / (b - a) yl = integrand( np.linspace(a + delta_x / 2, b + delta_x / 2, N, endpoint=False)) fft_vals = np_rfft(yl) tau = np.arange(len(fft_vals)) * delta_k #log.debug("yields d_x={:.3e}, d_k={:.3e} kmax={:.3e}".format(delta_x, delta_k, tau[-1])) return tau, delta_x * np.exp(-1j * tau * (a + delta_x / 2)) * fft_vals
def fourier_integral_simps(integrand, a, b, N): """ approximates int_a^b dx integrand(x) by the riemann sum with N terms using simpson integration scheme """ delta_x = (b-a)/(N-1) delta_k = 2*np.pi/N/delta_x l = np.arange(0, N) yl = integrand(a + l*delta_x) yl = get_fourier_integral_simps_weighted_values(yl) fft_vals = np_rfft(yl) tau = np.arange(len(fft_vals))*delta_k return tau, delta_x*np.exp(-1j*tau*a)*fft_vals
def deConvolve(self,G_w,noise_dT=3,noise_avg=3,fMax=2.4): self.reGrid(noise_dT=noise_dT,noise_avg=noise_avg) self.tPumpDeconv=np_arange(np_amin(self.tPump),np_amax(self.tPump), self.tTHz[1]-self.tTHz[0]) loc=np_amin(np_where(self.f >= fMax)) for i in range(self.tPumpSkew.size): self.dTSkewFFT[i,:loc]=self.dTSkewFFT[i,:loc]/G_w[:loc] self.avgSkewFFT[i,:loc]=self.avgSkewFFT[i,:loc]/G_w[:loc] self.dTskew=np_irfft(self.dTSkewFFT,axis=1) self.avgSkewFFT=np_irfft(self.avgSkewFFT,axis=1) self.dTdeconv=unSkew(self.tTHz,self.tPump,self.tPumpSkew,self.dTskew) self.avgDeconv=unSkew(self.tTHz,self.tPump ,self.tPumpSkew,self.avgSkewFFT) self.refDeconv=self.avgDeconv-self.dTdeconv self.pumpDeconv=self.avgDeconv+self.dTdeconv self.refFFTdeconv=np_rfft(self.refDeconv,axis=1) self.pumpFFTdeconv=np_rfft(self.pumpDeconv,axis=1) self.transDeconv=self.pumpFFTdeconv/self.refFFTdeconv return
def __init__(self,label='data',folder=False, tPump=False,tTHz=False, ref=False,pump=False,tmax=False,tmin=False, fmax=False,fmin=False): if folder: self.tPump=np_loadtxt(folder+'/tPump.dat') self.tTHz=np_loadtxt(folder+'/tTHz.dat') self.ref=np_loadtxt(folder+'/ref.dat') self.pump=np_loadtxt(folder+'/pump.dat') self.avg=(self.ref+self.pump)/2 if type(tPump)!=bool: self.tPump=tPump; self.tTHz=tTHz; self.dT=self.pump-self.ref self.refFFT=np_rfft(self.ref,axis=1) self.pumpFFT=np_rfft(self.pump,axis=1) self.trans=self.pumpFFT/self.refFFT self.f=np_rfftfreq(self.tTHz.size,self.tTHz[1]-self.tTHz[0]) self.fX,self.fY=np_meshgrid(self.f,self.tPump) return
def rfft(metAry, n=None, axes=-1): """ RFFT function wraper for numpy.fft to be used on metaArray objects, returns scaled metaArray object. """ nyquist = len(metAry) * 0.5 / (metAry.get_range(axes, 'end') - metAry.get_range(axes, 'begin')) fary = metaArray(np_rfft(metAry.data, n, axes)) fary.set_range(0, 'begin', 0) fary.set_range(0, 'end', nyquist) fary.set_range(0, 'unit', 'Hz') fary.set_range(0, 'label', 'Frequency') fary['unit'] = '' fary['label'] = 'Amplitude' try: fary['name'] = 'FFT{ ' + metAry['name'] + ' }' except TypeError: fary['name'] = 'FFT{ }' return fary
def stfft(metAry, tres=100, fres=None, window='blackmanharris', \ fmin=None, fmax=None, mag=True, debug=False): """ Simple implementation of short time fast Fourier transform on metaArray object. metAry Input metaArray tres Temporal resolution fres Frequency resolution window Window function or None fmin Cut-off frequency for the return data, default to the 0 fmax Cut-off frequency for the return data, default to the Nyquist mag The default is to return the abs() value, return complex array if false Each window will overlap 50% with its immediate neighbours. e.g.: |_____________________________________________| | | 1 | 3 | 5 | 7 | 9 | 11| 13| 15| 17| 19| 21| | 0 | 2 | 4 | 6 | 8 | 10| 12| 14| 16| 18| 20| | """ f1 = fmax # Length of the (short) time window l = int(round(2 * len(metAry) / float(tres))) # List of (short) time window starting points winlst = linspace(0, len(metAry) - l, tres).round().astype(int) # Native RFFT frequency resolution to Nyquist lfres = int(floor(l/2.0)+1) Nyquist = 0.5 * len(metAry) / (metAry.get_range(0, 'end') - metAry.get_range(0, 'begin')) # RFFT len, use native resolution by default n = None # Generate the (short) time window function if window is None: win = 1 else: win = get_window(window, l) # Decide where to slice the rfft output as a ratio to Nyquist # Make fmax < 1 or None if fmax is not None: if fmax < Nyquist: fmax = fmax / Nyquist elif fmax >= Nyquist: fmax = None if debug: print("*** Warning, spec frequency range beyond Nyquist limit") # Check whether padding is needed # If fres is not specified, use the native resolution if fres is None: if fmax is None: # No freq limit, use native resolution fres = lfres else: # Still on native resolution, but truncated to fmax fres = int(round(fmax * lfres)) else: # fres is specified if fmax is not None: # freq limit specified, work out global freq resolution gfres = int(round(fres / fmax)) else: # No freq limit, global freq resolution is same as fres gfres = fres # Global freq resolution is greater than native freq resolution # Need padding for rfft if gfres > lfres: n = (gfres - 1) * 2 elif gfres < lfres: # No need for padding, but throwing away freq resolution for nothing if debug: print("*** Warning, frequency resolution is artificially limited") # else gfres = lfres, no need for padding, native fres is just right # Convert fmax to array length if specified if fmax is not None: # If rfft is padded if n is not None: fmax = int(round(int(floor(n/2.0)+1) * fmax)) else: # Otherwise just truncate from native output fmax = int(round(lfres * fmax)) if debug: src_len = len(metAry.data[:l]*win) rfft_len = len(np_rfft(metAry.data[:l]*win, n=n)) print("*** l: " + str(l)) print("*** lfres: " + str(lfres)) print("*** Nyquist: " + str(Nyquist)) print("*** n: " + str(n)) print("*** fmax: " + str(fmax)) print("*** fres: " + str(fres)) print("*** src_len: " + str(src_len)) print("*** rfft_len: " + str(rfft_len)) if mag: # Construct a place holder of the 2D time-freq output tfary = zeros((tres, fres)).astype(float) for i in range(len(winlst)): t = winlst[i] # Where the (short) time window starts # Do the rfft to length n, and slice to fmax, then take abs() tfary[i] = spline_resize(abs(np_rfft(metAry.data[t:t+l]*win, n=n)[:fmax]), fres) else: # Construct a place holder of the 2D time-freq output tfary = zeros((tres,fres)).astype(complex) for i in range(len(winlst)): t = winlst[i] # Do the rfft to length n, and slice to fmax tfary[i] = spline_resize(np_rfft(metAry.data[t:t+l]*win, n=n)[:fmax], fres) tfary = metaArray(tfary) try: tfary['name'] = 'STFFT{ ' + metAry['name'] + ' }' except: tfary['name'] = 'STFFT{ }' tfary['unit'] = metAry['unit'] tfary['label'] = metAry['label'] # Per axis definitions tfary.set_range(0, 'begin', metAry.get_range(0, 'begin')) tfary.set_range(0, 'end', metAry.get_range(0, 'end')) tfary.set_range(0, 'unit', metAry.get_range(0, 'unit')) tfary.set_range(0, 'label', metAry.get_range(0, 'label')) tfary.set_range(1, 'begin', 0) if f1 is None: tfary.set_range(1, 'end', Nyquist) else: tfary.set_range(1, 'end', f1) tfary.set_range(1, 'unit', 'Hz') tfary.set_range(1, 'label', 'Frequency') return tfary