def Resample(S, ns, nr, p, rate): w_s = rfftfreq(ns, 1.0/rate) d_s = 1.*rate / ns w_r = rfftfreq(nr, 1.0/rate) d_r = 1.*rate / nr i_wfloor = (np.floor(w_r[1:]/p / d_s) - 1).astype(np.int) i_wceil = (np.ceil(w_r[1:]/p / d_s) - 1).astype(np.int) w_floor = w_s[1+i_wfloor] w_ceil = w_s[1+i_wceil] a_floor0, a_ceil0 = (w_r[1:]/p - w_floor), (w_ceil - w_r[1:]/p) # Some freqs may be exact matches, e.g. if nr == 2*ns, every other one. exact = (a_floor0 == 0.0) & (a_ceil0 == 0.0) # Ignore the DC Component and any exact matches in the interpolation. R = np.hstack((np.array([S[0]]), np.zeros(w_r.size-1))) R[1:][exact] = S[1+i_wfloor[exact]] # The rest: interpolate mag/phase from the nearest sampled frequencies. absS, angS = np.abs(S[1:]), np.angle(S[1:]) intrp = ~exact # Basic floor/ceil linear interpolation ... i_fl, i_cl = i_wfloor[intrp], i_wceil[intrp] afl0, acl0 = a_floor0[intrp], a_ceil0[intrp] afl = 1.0 - afl0 / (afl0 + acl0) acl = 1.0 - acl0 / (afl0 + acl0) absR = afl * absS[i_fl] + acl * absS[i_cl] angR = afl * angS[i_fl] + acl * angS[i_cl] R[1:][intrp] = absR * np.exp(1j * angR) assert R.size == w_r.size, (R.size, w_r.size, S.size, ns, nr) return R
def test_definition(self): x = [0, 1, 2, 3, 4] assert_array_almost_equal(9*fft.rfftfreq(9), x) assert_array_almost_equal(9*pi*fft.rfftfreq(9, pi), x) x = [0, 1, 2, 3, 4, 5] assert_array_almost_equal(10*fft.rfftfreq(10), x) assert_array_almost_equal(10*pi*fft.rfftfreq(10, pi), x)
def test_definition(self): x = [0, 1, 2, 3, 4] assert_array_almost_equal(9 * fft.rfftfreq(9), x) assert_array_almost_equal(9 * pi * fft.rfftfreq(9, pi), x) x = [0, 1, 2, 3, 4, 5] assert_array_almost_equal(10 * fft.rfftfreq(10), x) assert_array_almost_equal(10 * pi * fft.rfftfreq(10, pi), x)
def mode_wavenumber_mnp(XC,YFC,XR,YFR,XZ,YFZ): ''' XR length along the radius YFR tangental component of the field along the radius curve XC length along the circle YFC tangental component of the field along the circle curve XZ length along the line parallel to the z-axis YFZ tangental component of the field along the line curve ''' #FIND M rpc=1 my=YFC nmy=np.reshape(np.repeat(np.reshape(my,(1,len(my))),rpc,axis=0),rpc*len(my)) #print("MY_LEN=%d,NMY_LEN=%d"%(len(my),len(nmy))) N=len(nmy) fft_y=fft.rfft(my,n=my.size) abs_y=np.abs(fft_y) freqs = fft.rfftfreq(my.size, d=1./len(my)) M_NUM = freqs[np.argmax(abs_y)] #寻找N_零点个数 nzeros=0 ntps=len(XR) #total points for i in range (ntps-1): if YFR[i]*YFR[i+1]<0: nzeros+=1 elif YFR[i]==0: nzeros+=1 #M=0 曲线无0点 N_NUM=1 if M_NUM==0 and nzeros==0: N_NUM=1 else: N_NUM=nzeros #寻找P_零点个数? 周期个数? m2=np.abs(np.mean(YFZ))**2 if YFZ[0]*YFZ[-1]>0 and YFZ[0]*YFZ[-1]/m2>0.9: P_NUM=0 else: rpc=1 my=np.concatenate([-YFZ,YFZ]) nmy=np.reshape(np.repeat(np.reshape(my,(1,len(my))),rpc,axis=0),rpc*len(my)) #print("MY_LEN=%d,NMY_LEN=%d"%(len(my),len(nmy))) fft_y=fft.rfft(my,n=my.size) abs_y=np.abs(fft_y) freqs = fft.rfftfreq(my.size, d=1./len(my)) P_NUM = freqs[np.argmax(abs_y)] return M_NUM,N_NUM,P_NUM
def complex_local_wavenumbers(self): """Returns local wavenumbers of complex space""" return (fftfreq(self.N[0], 1. / self.N[0]).astype(self.float), fftfreq(self.N[1], 1. / self.N[1])[self.complex_local_slice()[1]].astype( self.float), rfftfreq(self.N[2], 1. / self.N[2]).astype(self.float))
def __init__(self, sound, win_dur, win_overlap=0.5, win_func=hanning): sig_len = len(sound) data = sound.data fs = sound.fs win_len = floor(fs * win_dur) adv_len = floor(win_len * (1 - win_overlap)) n_wins = floor((len(sound) - win_len) / adv_len) window = win_func(win_len) spec_len = win_len // 2 + 1 stft = np.zeros((spec_len, n_wins), dtype=np.complex) for win_idx in range(n_wins): beg_idx = win_idx * adv_len end_idx = beg_idx + win_len curr_data = window * data[beg_idx:end_idx] stft[:, win_idx] = rfft(curr_data) self.t = np.linspace(0, sig_len / fs, n_wins) self.f = fs * rfftfreq(win_len) self.stft = stft self.mag_stft = np.abs(self.stft) log_mag_stft = 10 * np.log10(self.mag_stft) log_mag_stft[log_mag_stft == -np.inf] = np.min( log_mag_stft[log_mag_stft != -np.inf]) self.log_mag_stft = log_mag_stft self.fs = fs self.sig_len = sig_len self.win_len = win_len self.adv_len = adv_len self.n_wins = n_wins self.window = window
def rfftfreqs(shape: Sequence[int], spacings: Optional[Sequence[float]] = None) -> Tuple[np.ndarray]: """ The Discrete Real Fourier Transform sample frequencies for each axis. Parameters ---------- shape : Sequence[int] Axes length. spacings : Sequence[scalar], optional Sample spacings (inverse of the sampling rates). Defaults to 1. Returns ------- freqs : Tuple[np.ndarray] Arrays of frequencies. See Also -------- numpy.fft.fftfreq : for all axes except last. numpy.fft.rfftfreq : for last axis. """ if spacings is None: spacings = (1., ) * len(shape) freqs = fftfreqs(shape[:-1], spacings[:-1]) freqs += (fft.rfftfreq(shape[-1], spacings[-1]), ) return freqs
def __init__(self, lenChunk, rate, data): print('Building FFT Stereo chunks...') self._lenChunk = lenChunk self._rate = rate #Duration of a sample = lenSample (in seconds) lenSample = 1 / rate leftData, rightData = data[:, 0], data[:, 1] #number of chunks: nbChunks = int(len(leftData) / (lenChunk * rate)) lChunksNotAveraged = array_split(leftData, nbChunks) rChunksNotAveraged = array_split(rightData, nbChunks) # #Computes FFT lChunksNotAveraged = array(list(map(fft.rfft, lChunksNotAveraged))) rChunksNotAveraged = array(list(map(fft.rfft, rChunksNotAveraged))) self._nbSamples = [ len(lChunksNotAveraged[i]) for i in range(len(lChunksNotAveraged)) ] self._freqs = [ fft.rfftfreq(2 * self._nbSamples[i] - 1, lenSample) for i in range(len(lChunksNotAveraged)) ] self._lChunks = lChunksNotAveraged self._rChunks = rChunksNotAveraged #### print('...Done')
def foldpsd(psd, fs): """ Return the one-sided version of the inputted two-sided psd. Parameters ---------- psd : ndarray A two-sided psd to be converted to one-sided fs : float The sample rate used for the psd Returns ------- f : ndarray The frequencies corresponding to the outputted one-sided psd psd_folded : ndarray The one-sided (folded over) psd corresponding to the inputted two-sided psd """ psd_folded = np.copy(psd[:len(psd) // 2 + 1]) psd_folded[1:len(psd) // 2 + (len(psd)) % 2] *= 2.0 f = rfftfreq(len(psd), d=1.0 / fs) return f, psd_folded
def create_output_signal(self, freq=1000, level=-3, sig_type='sine'): '''Creates the array for global out_sig. Should eventually handle multiple signal types. Currently this only builds sine waves that are periodic in our buffer size. It finds the closest frequency to the specified frequency. takes inputs: freq: frequency in Hz. level: signal level in dB. sig_type: Currently only supports sine waves. ''' if self.out_enable: retoggle = True self.toggle_out() else: retoggle = False freq_array = fft.rfftfreq(n=self.args.buff_size, d=(1 / self.args.sample_rate)) mag_array = np.zeros_like(freq_array) closest_freq_index = np.searchsorted(freq_array, freq) mag_array[closest_freq_index] = ((10 ** (level / 20) * self.args.buff_size / 2)) self.out_sig = np.fft.irfft(a=mag_array, n=self.args.buff_size) if retoggle: self.toggle_out() return (freq_array[closest_freq_index], level, sig_type)
def stftbins(x, Nwin, Nfft=None, d=1.0): import numpy.fft as fft """ Time and frequency bins corresponding to short-time Fourier transform. Call this with the same arguments as `stft`, plus one extra argument: `d` sample spacing, to get the time and frequency axes that the output of `stft` correspond to. Parameters ---------- x : array_like same as `stft` Nwin : int same as `stft` Nfft : int, optional same as `stft` d : float, optional Sample spacing of `x` (or 1 / sample frequency), units of seconds. Default: 1.0. Returns ------- t : ndarray Array of length `len(x) // Nwin`, in units of seconds, corresponding to the first dimension (height) of the output of `stft`. f : ndarray Array of length `Nfft`, in units of Hertz, corresponding to the second dimension (width) of the output of `stft`. """ Nfft = Nfft or Nwin Nwindows = x.size // Nwin t = np.arange(Nwindows) * (Nwin * d) f = fft.rfftfreq(Nfft, d) return t, f
def beam_spectrum_freq_generation(self, n_sampling_fft = None): """ Frequency array of the beam spectrum """ if n_sampling_fft is None: n_sampling_fft = len(self.profile_array) self._beam_spectrum_freq = fft.rfftfreq(n_sampling_fft, self.bin_size)
def spectrum(data, dt=1, IsReal=False): """Calculate normalized spectrum s(f) and power spectrum w(f), for a given time series of signal ``data``. For real ``data``, The corresponding power spectrum :math:`w(f)= 2|s(f)|^2`. The coefficient 2 is because input signal is assumed real and the power for positive and negative frequencies are symmetric. So the power spectrum w(f) is specified only for positive f's :param data: The signal data in *time* domain :type data: 1d array of complex (or float if ``IsReal`` is ``True``) :param dt: (Optional) time step size of ``data``. Default to be 1. :type time: float :param bool IsReal: specify the type of ``data``. If ``True``, float data type is expected for ``data``, and :method:`np.fft.rfft` will be used to carry out FFT on ``data``. Default to be ``False``. :return: tuple containing spectrum s, power spectrum w, and frequency labels f. :rtype: (ndarray of complex, ndarray of float, ndarray of float) """ if (IsReal): assert (isinstance(data[0], (np.float, np.float128, np.float32, np.float16)) ) #real data is assumed to be stored in float type n = len(data) s = rfft(data) / n w = 2 * s * np.conj(s) f = rfftfreq(n, dt) return (s, w, f) else: assert (isinstance(data[0], (np.complex, np.complex256, np.complex64))) n = len(data) s = fft(data) / n w = s * np.conj(s) f = fftfreq(n, dt) return (s, w, f)
def bandpass_gaussian(data, dt, period, alpha): """ Bandpassing real data (in array *data*) with a Gaussian filter centered at *period* whose width is controlled by *alpha*: exp[-alpha * ((f-f0)/f0)**2], with f the frequency and f0 = 1 / *period*. *dt* is the sampling interval of the data. @type data: L{numpy.ndarray} @type dt: float @type period: float @type alpha: float @rtype: L{numpy.ndarray} """ # Fourier transform fft_data = rfft(data) # aray of frequencies freq = rfftfreq(len(data), d=dt) # bandpassing data f0 = 1.0 / period fft_data *= np.exp(-alpha * ((freq - f0) / f0)**2) # back to time domain return irfft(fft_data, n=len(data))
def apply_notches(X, notches, rate, fft=True): if fft: fs = rfftfreq(X.shape[-1], 1. / rate) delta = 1. fd = rfft(X) else: nyquist = rate / 2. n_taps = 1001 gain = [1, 1, 0, 0, 1, 1] for notch in notches: if fft: window_mask = np.logical_and(fs > notch - delta, fs < notch + delta) window_size = window_mask.sum() window = np.hamming(window_size) fd[:, window_mask] = (fd[:, window_mask] * (1. - window)[np.newaxis, :]) else: freq = np.array([ 0, notch - 1, notch - .5, notch + .5, notch + 1, nyquist ]) / nyquist filt = firwin2(n_taps, freq, gain) X = filtfilt(filt, np.array([1]), X) if fft: X = irfft(fd) return X
def stft(signal, window=128, step=65): """ Perform a shoft-time fourier transform with a Hann window https://en.wikipedia.org/wiki/Short-time_Fourier_transform Paramters --------- signal : <numpy.ndarray> array of shape length n_points of a single-channel signal window : int number of samples per window step : int stride of window, determines overlap Returns --------- time,frequency,stft : <numpy.ndarray>,<numpy.ndarray>,<numpy.ndarray> time and frequency mesh aligned with stft spectorgram assuming 44100Hz sampling rate --------- """ signal -= signal.mean() freq = rfftfreq(window, d=1 / 44100.0) # construct hann windows windows, time = overlap(signal, window, step) windows *= 0.54 - 0.46 * cos(2 * pi * arange(window) / (window - 1)) # return rfft along window axis return time, freq, rfft(windows).T
def gen_features3(x_raw,feat_divisions=[1e4,6e4,1.2e5,1.6e5,2e5,2.3e5,3e5],sample_freq = 4e6): """ Helper function to generate simple statistical features and fft amplitudes from a 150,000 row 'acoustic data' segment. x_raw is the input acoustic_data pandas series feat_divisions is the ranges of frequencies in Hz to store fourier coefficients for. sample_freq is the sampling frequency of the provided data. The default is 4MHz. returns the converted features and the names of the names of the features. """ feature_names = ['mean', 'std', 'max', 'min', 'skew', 'kurtosis'] feature_names += ["fft_[{:},{:}]Hz".format(int(i),int(j)) for (i,j) in zip(feat_divisions,feat_divisions[1:])] features = [x_raw.mean(), x_raw.std(), x_raw.max(), x_raw.min(), x_raw.skew(), x_raw.kurtosis(), ] freq = rfftfreq(len(x_raw),d=1/sample_freq) fft = np.abs(rfft(x_raw)) for i,j in zip(feat_divisions,feat_divisions[1:]): start = np.argmax(freq>i) stop = np.argmax(freq>j) features.append(np.max(fft[start:stop])) return features, feature_names
def init_plot(self): x = fft.rfftfreq(self.CHUNK_SIZE) * self.SAMPLE_RATE x_max = x[-1] self.init_y = linspace(0, x_max, len(x)) y = self.init_y source = ColumnDataSource(data=dict(x=x, y=y)) # TODO: range and size (toolbar), maybe could be user settings plot = Figure(plot_height=400, plot_width=800, title="freq anal", tools="crosshair,pan,reset,resize,save,wheel_zoom", x_range=[0, x_max], y_range=[0, 15]) rad = x_max / float(len(x)) data = plot.circle('x', 'y', source=source, line_color=None, radius=rad) self.data_source = data.data_source # TODO: maybe not the best place curdoc().add_root(plot)
def dfmap_fft(df, indep_var='Time'): if df is not None: df = df new_df = {} n = len(df[indep_var]) a, b = df[indep_var][0], df[indep_var][n-1] for key in df: if key == indep_var: continue new_df[key] = rfft(df[key]) new_df[key] = list(map(np.absolute, new_df[key])) new_df[key] = list(map(lambda x: 2*x/n, new_df[key])) # avg time between samples # assumes uniform sampling dt = (b-a) / n #dt = (b-a).total_seconds() / n # get list of frequencies from the fft # new_df['Freq'] = fftfreq(len(self.df[key]), dt) new_df['Freq'] = rfftfreq(n, dt) # new_df = pandas.DataFrame.from_dict(new_df)#.sort_values('Freq') #new_df = new_df[abs(new_df.Freq) > 0.4] return new_df
def periodogramfft(d, time, data): from scipy.signal import hann, periodogram import numpy.fft as fft print "d=", d pidx, pv, tidx, tv = peaks.turning_points(data, minidx=0) tts = time[pidx] rspl = UnivariateSpline(time, data, k=4, s=0) t0 = tts[1] tf = tts[d + 1] dt = time[1] - time[0] twin = np.arange(t0, tf, dt) N = len(twin) fs = 1 / dt #twin1 = np.arange(t0, tts[3], dt) #Nfft = len(twin1) #fs = N/(tf-t0) Nfft = 100000 rwin = rspl(twin) rwin = rwin - np.mean(rwin) hwin = hann(len(twin)) rwin = rwin * hwin #f, pgram = periodogram(hwin, fs=fs, nfft=Nfft) fftout = fft.rfft(rwin, 50 * len(rwin)) fftfreq = fft.rfftfreq(50 * len(rwin), dt) print len(fftout) print len(fftfreq) return 2 * np.pi * fftfreq, np.abs(fftout)
def power_spectrum(da, dim=None): '''calculate the power spectrum of the given DataArray''' if not isinstance(da, xr.DataArray): da = xr.DataArray(da) if dim is None: dim = da.dims[-1] # xarray-version rfft da_f = xr.apply_ufunc(rfft, da, input_core_dims=[[dim]], output_core_dims=[['freq']], kwargs={'axis': -1}) # power spectrum ps = da_f.real**2 + da_f.imag**2 ps.name = 'power' # frequency coordinate ps['freq'] = xr.DataArray(rfftfreq(da[dim].size), dims='freq', attrs={'units': 'units: sample freq'}) return ps
def low_pass_filter(signal, lp_frq, dt=0.005, time=None, zero_pad=True): """ Function to low-pass filter a signal in the frequency domain, by setting all fourier terms larger than `lp_freq` to 0. :param signal: 1d list-like object with the input signal. :param lp_frq: Low-pass cut-off frequency. :param dt: float object with the timestep. Defaults to 0.005s. Only used if `time` is `None`. :param time: 1d list-like object with the input signal. Default to None. :param zero_pad: Boolean. If `True`, the signal is padded with zeros of length `2*len(signal)`. This should be used if the input is non-repetitive. IF `False`, the input is not zero-padded. Hence, the fft assumes that the signal repeats. :return: 1D ndarray with the low-pass filtered signal. """ if time is not None: dt = time[1] - time[0] if zero_pad: n = 3 * len(signal) else: n = len(signal) frq = rfftfreq(n, d=dt) signal_fft = rfft(signal, n=n) lp_fft = signal_fft * (frq <= lp_frq) lp_signal = irfft(lp_fft, n)[:len(signal)] return lp_signal
def get_Period(dds_t, tsamp): N = np.int(nearest_power_of_2(dds_t.size)) print('Padding ', dds_t.size, 'length array with ', N-dds_t.size, 'zeros.') DDS_T = np.abs(ft.rfft(dds_t-dds_t.mean(), N)) nu = ft.rfftfreq(N, tsamp) zoom = 1 while zoom == 1: pl.plot(nu, DDS_T) pl.xlabel('Frequency [Hz]') pl.ylabel('Flux') click = input('Ready to click ? :') if click == 'y': pl.title('Click on peak for F0') F0 = pl.ginput(1) zoom = 0 break else: continue F0 = F0[0][0] P0 = 1.0 / F0 pl.close() pl.plot(nu, DDS_T) pl.xlim(0.0, 12.5*F0) pl.xlabel('Frequency [Hz]') pl.ylabel('Flux') pl.title('First 12 harmonics') pl.savefig('First-12-harmonics.eps') pl.savefig('First-12-harmonics.png') return P0, F0
def ds_to_cs_to_fits(data, P, BW, filename): ntime,nchan=data.shape new_ntime=nearest_power_of_2(data.shape[0]) new_nchan = nearest_power_of_2(data.shape[1]) print(new_ntime, 'X', new_nchan, ' 2D FFT in progress...') cs=ft.fftshift(ft.rfft2(data, [new_ntime, new_nchan]),axes=0) print('FFT shift...') realCS=np.real(cs) imagCS=np.imag(cs) CS=np.zeros([2,cs.shape[0], cs.shape[1]]) CS[0,:]=realCS CS[1,:]=imagCS tau = ft.rfftfreq(new_nchan,np.abs(BW)/nchan) fD=ft.fftshift(ft.fftfreq(new_ntime,P))*1e3 hdu = f.PrimaryHDU(CS) hdu.header['CTYPE1'] ='DELAY - MICROSEC' hdu.header['CTYPE2'] ='DOPPLER FREQUENCY - MILLIHERTZ' hdu.header['CTYPE3'] ='REAL-IMAG' hdu.header['CRVAL1'] = tau[0] hdu.header['CRVAL2'] = fD[0] hdu.header['CRVAL3'] = 0 hdu.header['CDELT1'] = tau[1]-tau[0] hdu.header['CDELT2'] = fD[1]-fD[0] hdu.header['CDELT3'] = 0 hdu.header['CRPIX1'] = 0 hdu.header['CRPIX2'] = 0 hdu.header['CRPIX3'] = 0 hdu.header['CROTA1'] = 0.0 hdu.header['CROTA2'] = 0.0 hdu.header['CROTA3'] = 0.0 hdu.header['BSCALE'] = 1.0 update_fits_header(hdu) hdu.header['INT_TIME']=P*ntime hdu.writeto(filename) return fD, tau, cs
def __init__(self, refFile='ref.txt', sampFile='samp.txt', tFile='t.txt', delta=1, l=0.4, c=0.299796): 'load data files' self.refT0 = np.loadtxt(refFile) self.sampT0 = np.loadtxt(sampFile) self.sampT = np.copy(self.sampT0) self.t = np.loadtxt(tFile) 'transforms' self.f0 = fft.rfftfreq(self.t.size, self.t[1] - self.t[0]) self.w0 = 2 * np.pi * self.f0 self.refF0 = fft.rfft(self.refT0) self.sampF0 = fft.rfft(self.sampT0) self.f = self.f0 self.w = self.w0 self.refF = self.refF0 self.sampF = self.sampF0 'experimental transfer function' self.transE = self.sampF0 / self.refF0 'constants' self.nAir = np.ones(self.f.size) self.l = l self.delta = delta self.c = c return
def trimTime(self, tMin=-10, tMax=25, delta='undefined'): if tMin > np.amin(self.t): loc1 = np.amin(np.where(self.t > tMin)) else: loc1 = 0 if tMax < np.amax(self.t): loc2 = np.amin(np.where(self.t > tMax)) else: loc2 = self.t.size self.refT0 = self.refT0[loc1:loc2] self.sampT0 = self.sampT0[loc1:loc2] self.sampT = np.copy(self.sampT0) self.t = self.t[loc1:loc2] self.f0 = fft.rfftfreq(self.t.size, self.t[1] - self.t[0]) self.w0 = 2 * np.pi * self.f0 self.refF0 = fft.rfft(self.refT0) self.sampF0 = fft.rfft(self.sampT0) self.f = self.f0 self.w = self.w0 self.refF = self.refF0 self.sampF = self.sampF0 self.transExp = self.sampF0 / self.refF0 self.nAir = np.ones(self.f.size) if delta != 'undefined': self.delta = delta return
def FFT(signal, NFFT=None, timeName='time', norm=None, freqName='frequency', real=True): """ Automatically take the real or complex FFT of an xarray.DataArray You must supply the name of the frequency axis. Assumes that time is in seconds, and returns frequency in kHz. """ timeAxisNum = signal.get_axis_num(timeName) timeAxisData = getattr(signal, timeName).data dt = (timeAxisData[-1] - timeAxisData[0]) / (len(timeAxisData) - 1) if NFFT is None: NFFT = len(timeAxisData) if real: freq = rfftfreq(NFFT, dt) * 1e-3 signalFFT = rfft(signal.data, n=NFFT, axis=timeAxisNum, norm=norm) else: freq = fftshift(fftfreq(NFFT, dt)) * 1e-3 signalFFT = fftshift(fft(signal.data, n=NFFT, axis=timeAxisNum, norm=norm), axes=timeAxisNum) #pack things back into a dataarray name = signal.name coords = dict(signal.coords.items()) coords.pop(timeName) coords[freqName] = freq olddims = signal.dims newdims = olddims[0:timeAxisNum] + (freqName, ) + olddims[timeAxisNum + 1:] return xr.DataArray(signalFFT, coords=coords, name=name, dims=newdims)
def compute_ensemble_fft(x_,u_data_): sample_size = size(u_data_[1,:]); aver_size = size(u_data_[:,1]); if sample_size%2==0: normalize_factor = (sample_size/2.)+1. elif sample_size%2==1: normalize_factor = (sample_size+1.)/2. sample_rate = 1/sample_size; k_freq = fft.rfftfreq(sample_size, sample_rate); #u_x = fft.irfft(fft.rfft(u_data_[0,:]),size(x_)) #print('x: ',size(x_),', u_x: ', size(u_x)) #pyplot.figure() #pyplot.plot(x_,u_x,'--r',x_,u_data_[0,:],'-k') #pyplot.show() u_amp = abs(fft.rfft(u_data_[0,:])) for i in range(1,aver_size): u_amp += abs(fft.rfft(u_data_[i,:])) u_amp = u_amp / (aver_size*normalize_factor) KEnerg = 0.5 * u_amp**2.0 return k_freq, u_amp, KEnerg
def test_run_copy_of_notebook_code(): np.random.seed(123) Fs = 100 # sampling frequency in Hz Ts = 1 / Fs # sampling interval in s N = 1024 # number of samples time = arange(0, N * Ts, Ts) # time instants noise_std = 0.1 # signal noise standard deviation # time domain signal x = (sin(2 * pi * Fs / 10 * time) + sin(2 * pi * Fs / 5 * time) + random.randn(len(time)) * noise_std) # Apply DFT with propagation of uncertainties X, UX = GUM_DFT(x, noise_std**2) f = fft.rfftfreq(N, Ts) # frequency values figure() plot(time, x) xlim(time[0], time[-1]) xlabel("time / s", fontsize=18) ylabel("signal amplitude / au", fontsize=18) figure() subplot(211) errorbar(f, X[:len(f)], sqrt(UX[:len(f)])) ylabel("real part", fontsize=18) xticks([]) subplot(212) errorbar(f, X[len(f):], sqrt(UX[len(f):])) ylabel("imaginary part", fontsize=18) xlabel("frequency / Hz", fontsize=18) subplots_adjust(hspace=0.05)
def bandpass_gaussian(data, dt, period, alpha): """ Bandpassing real data (in array *data*) with a Gaussian filter centered at *period* whose width is controlled by *alpha*: exp[-alpha * ((f-f0)/f0)**2], with f the frequency and f0 = 1 / *period*. *dt* is the sampling interval of the data. @type data: L{numpy.ndarray} @type dt: float @type period: float @type alpha: float @rtype: L{numpy.ndarray} """ # Fourier transform fft_data = rfft(data) # aray of frequencies freq = rfftfreq(len(data), d=dt) # bandpassing data f0 = 1.0 / period fft_data *= np.exp(-alpha * ((freq - f0) / f0) ** 2) # back to time domain return irfft(fft_data, n=len(data))
def get_rfft(signal, dt=0.005, time=None, zero_pad=True, zero_N=5): """ Function to return the real absolute fft and frequencies of a given signal. :param signal: 1d list-like object with the input signal. :param dt: float object with the timestep. Defaults to 0.005s. Only used if `time` is `None`. :param time: 1d list-like object with the input signal. Default to None. :param zero_pad: Boolean. If `True`, the signal is padded with zeros of length `2*len(signal)`. This should be used if the input is non-repetitive. IF `False`, the input is not zero-padded. Hence, the fft assumes that the signal repeats. :param zero_N: float. If `zero_pad` is True, then the total length of the signal input to the FFT is zero_N * len(signal). The extra signal content is all zeros. :return: - frq - 1d ndarray with frequencies. - signal_fft - 1d ndarray with absolute fft values. """ if time is not None: dt = time[1] - time[0] if zero_pad: extra = np.ones((zero_N - 1) * len(signal)) * signal[-1] # )np.linspace( # signal[-1], signal[0], (zero_N-1)*len(signal) # ) signal = np.append(signal, extra) n = zero_N * len(signal) else: n = len(signal) frq = rfftfreq(n, d=dt) signal_fft = np.abs(rfft(signal, n=n)) return frq, signal_fft
def make_residual_func(samples, indices, **params): 'closure for residual func' fft_size = 2 while fft_size < indices[-1]: fft_size *= 2 freqs = rfftfreq(fft_size, 5) ind_from = int(round(1 / (params['t_max'] * freqs[1]))) ind_to = ind_from + params['n_harm'] def make_series(x): 'Calculates time series from parameterized spectrum' nonlocal freqs, ind_from, ind_to, params spectrum = zeros_like(freqs, 'complex') sign_x0 = 0 if x[0] == 0.5 else abs(x[0] - 0.5) / (x[0] - 0.5) spectrum[0] = rect(sign_x0 * exp(params['scale'][0] * abs(x[0] - 0.5)), 0) for i in range(ind_from, ind_to): spectrum[i] = rect( exp(params['scale'][1] * x[1] + params['slope'] * log(freqs[i])), params['scale'][2] * x[2 + i - ind_from]) return irfft(spectrum) def residual_func(x): 'calculates sum of squared residuals' nonlocal samples, indices series = make_series(x) sum_err = 0 for position, ind in enumerate(indices): sum_err += (series[ind] - samples[position])**2 return sum_err return make_series, residual_func
def test_rfftfreq_2(self): n_points = 10000 try: res = bm.rfftfreq(n_points) except AttributeError as e: self.skipTest('Not compiled with FFTW') np.testing.assert_almost_equal(res, fft.rfftfreq(n_points), 8)
def compute_pk_raw(delta_lambda_or_log_lambda, delta, linear_binning=False): """Computes the raw power spectrum Args: delta_lambda_or_log_lambda: float Variation of (the logarithm of) the wavelength between two pixels delta: array of floats Mean transmission fluctuation (delta field) linear_binning: if set then inputs need to be in AA, outputs will be 1/AA else inputs will be in log(AA) and outputs in s/km Returns: The following variables k: the Fourier modes the Power Spectrum is measured on pk: the Power Spectrum """ if linear_binning: # spectral length in AA length_lambda = (delta_lambda_or_log_lambda * len(delta)) else: # spectral length in km/s length_lambda = (delta_lambda_or_log_lambda * constants.SPEED_LIGHT * np.log(10.) * len(delta)) # make 1D FFT num_pixels = len(delta) fft_delta = rfft(delta) # compute power spectrum pk = (fft_delta.real**2 + fft_delta.imag**2) * length_lambda / num_pixels**2 k = 2 * np.pi * rfftfreq(num_pixels, length_lambda / num_pixels) return k, pk
def decompose(self,l_edges,keep_fourier=False): """ Decomposes the shear map into its E and B modes components and returns the respective power spectral densities at the specified multipole moments :param l_edges: Multipole bin edges :type l_edges: array :param keep_fourier: If set to True, holds the Fourier transforms of the E and B mode maps into the E and B attributes of the ShearMap instance :type keep_fourier: bool. :returns: :returns: tuple -- (l -- array,P_EE,P_BB,P_EB -- arrays) = (multipole moments, EE,BB power spectra and EB cross power) >>> test_map = ShearMap.load("shear.fit",format=load_fits_default_shear) >>> l_edges = np.arange(300.0,5000.0,200.0) >>> l,EE,BB,EB = test_map.decompose(l_edges) """ #Perform Fourier transforms ft_data1 = rfft2(self.data[0]) ft_data2 = rfft2(self.data[1]) #Compute frequencies lx = rfftfreq(ft_data1.shape[0]) ly = fftfreq(ft_data1.shape[0]) #Safety check assert len(lx)==ft_data1.shape[1] assert len(ly)==ft_data1.shape[0] #Compute sines and cosines of rotation angles l_squared = lx[np.newaxis,:]**2 + ly[:,np.newaxis]**2 l_squared[0,0] = 1.0 sin_2_phi = 2.0 * lx[np.newaxis,:] * ly[:,np.newaxis] / l_squared cos_2_phi = (lx[np.newaxis,:]**2 - ly[:,np.newaxis]**2) / l_squared #Compute E and B components ft_E = cos_2_phi * ft_data1 + sin_2_phi * ft_data2 ft_B = -1.0 * sin_2_phi * ft_data1 + cos_2_phi * ft_data2 ft_E[0,0] = 0.0 ft_B[0,0] = 0.0 assert ft_E.shape == ft_B.shape assert ft_E.shape == ft_data1.shape #Compute and return power spectra l = 0.5*(l_edges[:-1] + l_edges[1:]) P_EE = _topology.rfft2_azimuthal(ft_E,ft_E,self.side_angle.to(deg).value,l_edges) P_BB = _topology.rfft2_azimuthal(ft_B,ft_B,self.side_angle.to(deg).value,l_edges) P_EB = _topology.rfft2_azimuthal(ft_E,ft_B,self.side_angle.to(deg).value,l_edges) if keep_fourier: self.fourier_E = ft_E self.fourier_B = ft_B return l,P_EE,P_BB,P_EB
def freqz_fos(b, a, order, nfft, plotfun=None): impulse = _create_impulse(nfft) response, states = fosfilter(b, a, order, impulse) freqresponse = rfft(np.real(response)) frequencies = rfftfreq(nfft) if plotfun: plotfun(frequencies, freqresponse) return freqresponse, frequencies, response
def fourier_analysis(data, ptree=None): time = data['time'] current = data['current'] voltage = data['voltage'] # inspect data n = len(time) # normalization factor for fft assert len(current) == n assert len(voltage) == n d = time[1] - time[0] # inverse of the sampling rate # check sampling spacing is the same everywhere for i in range(n - 1): assert isclose(time[i + 1] - time[i], d, atol=1e-10, rtol=1e-10) # truncate signals if ptree: steps_per_cycle = ptree.get_int('steps_per_cycle') cycles = ptree.get_int('cycles') ignore_cycles = ptree.get_int('ignore_cycles') assert cycles > ignore_cycles assert n == cycles * steps_per_cycle time = time[ignore_cycles * steps_per_cycle:] current = current[ignore_cycles * steps_per_cycle:] voltage = voltage[ignore_cycles * steps_per_cycle:] else: time = time[int(n / 2):] current = current[int(n / 2):] voltage = voltage[int(n / 2):] n = len(time) assert len(current) == n assert len(voltage) == n if not _is_power_of_two(n): warn( "(cycles-ignore_cycles)*steps_per_cycles is not a " "power of 2 (most efficient for the fourier analysis)", RuntimeWarning) # perform the actual fourrier analaysis fft_current = fft.rfft(current) / n fft_voltage = fft.rfft(voltage) / n fft_frequency = fft.rfftfreq(n, d) # find the excited harmonics if ptree: harmonics = array(ptree.get_array_int('harmonics')) peak_indices = harmonics * (cycles - ignore_cycles) else: mx, mn = peakdet(absolute(fft_voltage), mean(absolute(fft_current))) peak_indices = int(mx[:, 0]) mx, mn = peakdet(absolute(fft_voltage), mean(absolute(fft_current))) assert peak_indices == mx[:, 0] frequency = fft_frequency[peak_indices] impedance = fft_voltage[peak_indices] / fft_current[peak_indices] return [frequency, impedance]
def fromEBmodes(cls,fourier_E,fourier_B,angle=3.14*deg): """ This class method allows to build a shear map specifying its E and B mode components :param fourier_E: E mode of the shear map in fourier space :type fourier_E: numpy 2D array, must be of type np.complex128 and must have a shape that is appropriate for a real fourier transform, i.e. (N,N/2 + 1); N should be a power of 2 :param fourier_B: B mode of the shear map in fourier space :type fourier_B: numpy 2D array, must be of type np.complex128 and must have a shape that is appropriate for a real fourier transform, i.e. (N,N/2 + 1); N should be a power of 2 :param angle: Side angle of the real space map in degrees :type angle: float. :returns: the corresponding ShearMap instance :raises: AssertionErrors for inappropriate inputs """ assert fourier_E.dtype == np.complex128 and fourier_B.dtype == np.complex128 assert fourier_E.shape[1] == fourier_E.shape[0]/2 + 1 assert fourier_B.shape[1] == fourier_B.shape[0]/2 + 1 assert fourier_E.shape == fourier_B.shape #Compute frequencies lx = rfftfreq(fourier_E.shape[0]) ly = fftfreq(fourier_E.shape[0]) #Safety check assert len(lx)==fourier_E.shape[1] assert len(ly)==fourier_E.shape[0] #Compute sines and cosines of rotation angles l_squared = lx[np.newaxis,:]**2 + ly[:,np.newaxis]**2 l_squared[0,0] = 1.0 sin_2_phi = 2.0 * lx[np.newaxis,:] * ly[:,np.newaxis] / l_squared cos_2_phi = (lx[np.newaxis,:]**2 - ly[:,np.newaxis]**2) / l_squared sin_2_phi[0,0] = 0.0 cos_2_phi[0,0] = 0.0 #Invert E/B modes and find the components of the shear ft_data1 = cos_2_phi * fourier_E - sin_2_phi * fourier_B ft_data2 = sin_2_phi * fourier_E + cos_2_phi * fourier_B #Invert Fourier transforms data1 = irfft2(ft_data1) data2 = irfft2(ft_data2) #Instantiate new shear map class new = cls(np.array([data1,data2]),angle) setattr(new,"fourier_E",fourier_E) setattr(new,"fourier_B",fourier_B) return new
def main(input_val): currency_pairs = ["BTC_USD_", "LTC_USD_", "LTC_BTC_", "DRK_BTC_", "DOGE_BTC_", "DRK_LTC_", "DOGE_LTC_"] file_list_uber = [] for pair in currency_pairs: file_list_uber.append(pair + "full_ubersampled.csv") for file in file_list_uber: uber_csv = open(file, 'r') csv_read = csv.DictReader(uber_csv, delimiter=',', quoting=csv.QUOTE_NONNUMERIC) csv_list = [] for row in csv_read: csv_list.append({'price':float(row['price']), 'tmsp':int(row['tmsp'])}) first_tmsp = int(csv_list[0]['tmsp']) last_tmsp = int(csv_list[-1]['tmsp']) delta_tmsp = int(last_tmsp - first_tmsp) uber_len = len(csv_list) uber_price_array = np.zeros(uber_len, dtype='float') for i in range(0,uber_len,1): uber_price_array[i] = csv_list[i]['price'] uber_fft = fft.rfft(uber_price_array) uber_fft_imag = np.imag(uber_fft) uber_fft_real = np.real(uber_fft) uber_fft_mag = np.sqrt((uber_fft_real * uber_fft_real) + (uber_fft_imag * uber_fft_imag)) uber_fft_bins = fft.rfftfreq(uber_len, d=100) uber_csv.close() field_names = ['freq_bin', 'magnitude'] fft_csv_name = file[0:-4] + "_fft.csv" fft_csv = open(fft_csv_name, 'w', newline = '') csvwriter = csv.DictWriter(fft_csv, delimiter=',',fieldnames=field_names, quoting=csv.QUOTE_NONNUMERIC) csvwriter.writeheader() #csvwriter.writerows(full_conditioned) for i in range(0,len(uber_fft_real),1): dict_d = {'freq_bin':uber_fft_bins[i], 'magnitude':uber_fft_mag[i]} csvwriter.writerow(dict_d) fft_csv.close()
def getSTFT(signal, sample_spacing=1, slidingWindowSize=20, stepSize=10) : """ Get short-time fourier transform with slidingWindowSize=20 (number of sample in window) and stepSize=10 (number of samle to sample from window to another) """ segmentedSignal=segmentSignal(signal,slidingWindowSize,stepSize) segmentedSignalSTFT=[] for segment in segmentedSignal : segmentedSignalSTFT.append(rfft(segment)) spectrogram=np.array(segmentedSignalSTFT) t=np.array([stepSize*i for i in xrange(len(segmentedSignal))]) f=np.array(rfftfreq(slidingWindowSize,d=sample_spacing)) return t,f,spectrogram
def __init__(self, args): self.args = args # Determine the frequencies the dfft calculates at. self.freq = fft.rfftfreq(n=args.fft_size, d=(1 / args.sample_rate)) # Setup the display: self.fig = plt.figure() self.ax = plt.axes(xlim=args.xlims, ylim=args.ylims) self.ax.set_xscale('log', basex=10) self.line, = self.ax.plot([], []) plt.ion()
def freq_analyze(data, noise, dt): plt.figure() plt.plot(data) plt.title('data to analyze') plt.figure() plt.title('noise to analyze') plt.plot(noise) data_FFT=rfft(data) data_freqs=rfftfreq(len(data), dt) noise_FFT=rfft(noise) noise_freqs=rfftfreq(len(noise), dt) plt.figure() plt.plot(data_freqs, data_FFT, label='data FFT') plt.plot(noise_freqs, noise_FFT, label='noise FFT') plt.title('FFT of noise and data') plt.yscale('log') plt.show()
def __init__(self, **kwargs): super(SpectralFrameWidget, self).__init__() # default parameters if not specified for name, val in self.defaults.items(): setattr(self, name, kwargs.get(name, val)) self.setLabel('left', 'Amplitude', units='dB') self.setLabel('bottom', text='Frequency', units='kHz') self.getPlotItem().setRange(yRange=[-50, 40]) self.spectrum_curve = self.plot([]) self.freqs = rfftfreq(self.nfft) * self.fs / 1000.0 self.frame_size = get_frame_size(self.fs, self.frame_size_ms) self.window = np.hamming(self.frame_size)
def simpleSpecs(t, sig, amponly=False): ''' Creates simple amplitude and phase spectrums of real functions using numpy.fft; phase is in degrees :param t: time (1D numpy array) :param sig: signal (1D numpy array) :param amponly: outputs only the amplitude spectrum (bool) :return: frequency (1D numpy array), A(f), phi(f) ''' n = sig.size fouSig = fft.rfft(sig) / n # DFT of the signal normalized sample_int = t[n-1] - t[n-2] # sample interval fouFrq = fft.rfftfreq(n, d=sample_int) fouAmp = sqrt(real(fouSig)**2 + imag(fouSig)**2) fouPhi = angle(fouSig, deg=True) if amponly is True: return fouFrq, fouAmp else: return fouFrq, fouAmp, fouPhi
def init_plot(self): x = fft.rfftfreq(self.CHUNK_SIZE)*self.SAMPLE_RATE x_max = x[-1] self.init_y = linspace(0, x_max, len(x)) y = self.init_y source = ColumnDataSource(data=dict(x=x, y=y)) # TODO: range and size (toolbar), maybe could be user settings plot = Figure(plot_height=400, plot_width=800, title="freq anal", tools="crosshair,pan,reset,resize,save,wheel_zoom", x_range=[0, x_max], y_range=[0, 15]) rad = x_max/float(len(x)) data = plot.circle('x', 'y', source=source, line_color=None, radius=rad) self.data_source = data.data_source # TODO: maybe not the best place curdoc().add_root(plot)
def testResample(): s, rate = ReadAndConvert(os.path.join('testdata', 'foo_s80_p95.wav')) s = scipy.signal.resample(s, 4*len(s)) rate = 4*rate ConvertAndWrite(s, rate, os.path.join('testout', 'foo_resampled.wav')) s = s[0 : 15*2048] nfft, nskip = 1024, 512 Sws = STFT(s, nfft, nskip) nrfft, nrskip = 4096, 2048 target_pitch = 880. #440.0 * 2 ** (7.0 / 12) Rws = [] for nw, Sw in enumerate(Sws): freqs = rfftfreq(nfft, 1.0/rate) epitch = EstimatePitch(Sw, rate) if epitch == 0.0: p = 1 else: p = target_pitch / epitch print '%d: epitch=%f p=%f' % (nw, epitch, p) PlotPitches(np.abs(Sw), rate, name='testResampleFrame%dInMag' % nw, title='Spectrum of input frame %d (%f)' % (nw, epitch)) PlotPitches(np.angle(Sw), rate, name='testResampleFrame%dInPhase' % nw, title='Phase of input frame %d' % nw) Rw = Resample(Sw, nfft, nrfft, p, rate) Rws.append(Rw) erpitch = EstimatePitch(Rw, rate) PlotPitches(np.abs(Rw), rate, name='testResampleFrame%dOutMag' % nw, title='Spectrum of output frame %d (%f)' % (nw, erpitch)) PlotPitches(np.angle(Rw), rate, name='testResampleFrame%dOutPhase' % nw, title='Phase of output frame %d' % nw) r = STIFT(Rws, nrfft, nrskip) r = scipy.signal.resample(r, int(np.floor(r.size/2))) rate = rate/2 ConvertAndWrite( r, rate, os.path.join('testout', 'testResample.wav'))
def real_to_fourier(f, x, y, z): # Check that real-space grid spacing is all equal if not (_is_evenly_spaced(x) and _is_evenly_spaced(y) and _is_evenly_spaced(z)): raise ValueError('Sample points in real space are not evenly spaced.') dx = x[1]-x[0] # Grid spacing dy = y[1]-y[0] dz = z[1]-z[0] ftrans = ft.rfftn(f) # Wavenumber arrays kx = 2*np.pi * ft.fftfreq(x.size, d=dx) ky = 2*np.pi * ft.fftfreq(y.size, d=dy) kz = 2*np.pi * ft.rfftfreq(z.size, d=dz) # Only last axis is halved in length when using numpy.fft.rfftn() # Normalize (convert DFT to continuous FT) ftrans *= dx*dy*dz return ftrans, kx, ky, kz
def PlotPSD(self): colors = ['r'] dt = self.Dt Ry = self.measurements[0][0] mean = np.average(Ry) val = np.array( [v - mean for v in Ry] ) freq = fft.rfftfreq(len(val), dt) tr = fft.rfft(val) tr_vect = [np.real(i) for i in tr] psd = [(np.real(i)**2 + np.imag(i)**2)**0.5 for i in tr] plt.clf() plt.figure("psd") plt.plot(freq[1:],tr_vect[1:],colors[0]) plt.xlim(0, 10.0) plt.xlabel(r"$Frequency \, (Hz)$") plt.ylabel(r"$PSD$") plt.savefig("psd.eps")
def fft(self, nfft=None): """Compute the one-dimensional discrete Fourier transform of this `TimeSeries`. Parameters ---------- nfft : `int`, optional length of the desired Fourier transform. Input will be cropped or padded to match the desired length. If nfft is not given, the length of the `TimeSeries` will be used Returns ------- out : :class:`~gwpy.spectrum.Spectrum` the normalised, complex-valued FFT `Spectrum`. See Also -------- :mod:`scipy.fftpack` for the definition of the DFT and conventions used. Notes ----- This method, in constrast to the :meth:`numpy.fft.rfft` method it calls, applies the necessary normalisation such that the amplitude of the output :class:`~gwpy.spectrum.Spectrum` is correct. """ from ..spectrum import Spectrum if nfft is None: nfft = self.size dft = npfft.rfft(self.value, n=nfft) / nfft dft[1:] *= 2.0 new = Spectrum(dft, epoch=self.epoch, channel=self.channel, unit=self.unit) new.frequencies = npfft.rfftfreq(self.size, d=self.dx.value) return new
def _fourierMap(self,power_func,**kwargs): #Assert the shape of the blueprint, to tune the right size for the fourier transform lpix = 360.0/self.side_angle.to(deg).value lx = rfftfreq(self.shape[0]) * self.shape[0] * lpix ly = fftfreq(self.shape[0]) * self.shape[0] * lpix #Compute the multipole moment of each FFT pixel l = np.sqrt(lx[np.newaxis,:]**2 + ly[:,np.newaxis]**2) #Compute the power spectrum at each l and check that it is positive if isinstance(power_func,np.ndarray): #Check for correct shape assert power_func.shape[0] == 2,"If you want an interpolated power spectrum you should pass a (l,Pl) array!" #Perform the interpolation ell,Pell = power_func power_interp = interpolate.interp1d(ell,Pell,**kwargs) Pl = power_interp(l) else: Pl = power_func(l,**kwargs) assert Pl[Pl>=0.0].size == Pl.size #Generate real and imaginary parts real_part = np.sqrt(0.5*Pl) * np.random.normal(loc=0.0,scale=1.0,size=l.shape) * lpix/(2.0*np.pi) imaginary_part = np.sqrt(0.5*Pl) * np.random.normal(loc=0.0,scale=1.0,size=l.shape) * lpix/(2.0*np.pi) #Get map in real space and return ft_map = (real_part + imaginary_part*1.0j) * l.shape[0]**2 ft_map[0,0] = 0.0 return ft_map
def smooth_fft(dx, spec, sigma): """Basic math for FFT convolution with a gaussian kernel. :param dx: The wavelength or velocity spacing, same units as sigma :param sigma: The width of the gaussian kernel, same units as dx :param spec: The spectrum flux vector """ # The Fourier coordinate ss = rfftfreq(len(spec), d=dx) # Make the fourier space taper; just the analytical fft of a gaussian taper = np.exp(-2 * (np.pi ** 2) * (sigma ** 2) * (ss ** 2)) ss[0] = 0.01 # hack # Fourier transform the spectrum spec_ff = np.fft.rfft(spec) # Multiply in fourier space ff_tapered = spec_ff * taper # Fourier transform back spec_conv = np.fft.irfft(ff_tapered) return spec_conv
def complex_local_wavenumbers(self): """Returns local wavenumbers of complex space""" return (fftfreq(self.N[0], 1./self.N[0]), fftfreq(self.N[1], 1./self.N[1])[self.complex_local_slice()[1]], rfftfreq(self.N[2], 1./self.N[2]))
def fftAnalysis(self,cs,profile,mode='sensitivity'): """ Fourier analysis: find main frequencies and power therein """ if cs.verbose: try: import QCUS_testing as mytest if mode == 'sensitivity': mytest._exportProfile( profile,fname='y2profile.tsv' ) else: mytest._exportProfile( profile,fname='x2profile.tsv' ) except: pass fdelta = .1 # peak should differ by more than this fraction of max ps if mode == 'sensitivity': cs.sens_basewavelength = 0. cs.sens_ylim2 = -1 # remove average component ywork = profile-np.average(profile) nx = len(ywork) x = np.array(range(nx)) ffty = np.fft.rfft(ywork) ps = np.abs(ffty)**2 integral = np.sum(ps[self.fft_skip:]) # calculate total content, but ignore zero component freqs = rfftfreq(nx) # find peaks xy_max,xy_min = wadwrapper_lib.peakdet(ps, delta=fdelta*np.max(ps[self.fft_skip:])) # returns indices for freqs # sort peaks from large to small xy_max = sorted(xy_max,key=operator.itemgetter(1)) xy_max = xy_max[::-1] # find max component which is not zero-component and represents larger than given fraction of power base_ix = 0 # index of base-frequency start_ix = 0 # index of zero-peak for i,(xi,yi) in enumerate(xy_max): if xi<=self.fft_skip: # zero-peak must be located in skip start_ix = xi if xi>self.fft_skip and base_ix<1: base_ix = xi if mode == 'sensitivity': cs.sens_basewavelength = self.pixels2mm(cs, 1./freqs[xi]) break # filter-out all non-background trend components to find extend of signal for i in range(len(ffty)): if i>(base_ix+start_ix)/2: ffty[i] = 0. # locate minimum (after zero-peak) of trend fy = np.fft.irfft(ffty) ix_max = np.argmax(fy) ix_min = ix_max+np.argmin(fy[ix_max:]) if cs.verbose: print 'max @',ix_max print 'min @',ix_min if mode == 'sensitivity': cs.sens_ylim2 = ix_min if cs.verbose: plt.figure() plt.plot(ywork) plt.plot(fy) if mode == 'sensitivity': plt.title('sensitivity,filtered') else: plt.title('uniformity,filtered') plt.figure() plt.plot(ps) if mode == 'sensitivity': plt.title('sensitivity,powerspectrum') else: plt.title('uniformity,powerspectrum') cs.hasmadeplots = True
def PlotPitches(S, rate, dirpath='testout', name='pitches', title=''): freqs = rfftfreq(S.size, 1.0/rate) plot.LinePlotHtml( dirpath, name, title, [['freq', name]] + [[f, Sk] for f, Sk in zip(freqs, S)], logx=True, xticks_at_A=True)
def EstimatePitch(S, rate): "Very simple. Maximum value of abs(spectrum)." w = np.argmax(np.abs(S)) r = rfftfreq(S.size, 1.0/rate)[w] return r
def get_period(samples, rate, plot=False): n = samples.shape[0] minfreq = 1.0 * rate / n # plot the last 10 seconds of raw data # if plot: plt.figure(0) plt.subplot(2,1,1) plt.plot(np.linspace(0,10,int(10*rate)), samples[-int(10*rate):]) plt.xlabel('time (s)') plt.ylabel('amplitude') # apply a threshold to cut out the noise # thresh = 3.0 * np.std(samples) samples = np.fabs(samples) idx = samples < thresh samples[idx] = 0.0 # fourier transform the data to identify frequencies # ... window it with a gaussian envelope to make gaussian-shaped peaks # ... these can be accurately fit with gaussian profiles to centroid # ... precise frequency # w = signal.gaussian(samples.shape[0], std=samples.shape[0]/7) f1 = rfft(samples*w) f1 = np.abs(f1) f1 = f1 / np.max(f1) freqs = rfftfreq(samples.shape[0], 1.0/rate) # look in the region between 0.5 and 10 Hz. if your clock doesn't # tick in the frequency range, you may be in trouble # lo = np.argmax(freqs > 0.5) # or just calculate from minfreq... hi = np.argmax(freqs > 10.0) f1 = f1[lo:hi] freqs = freqs[lo:hi] # arbitrary threshold here... # tmp = np.select([f1>0.5*np.max(f1)], [f1]) peaks = signal.find_peaks_cwt(tmp, np.arange(3,5)) # plot the fourier transform, along with identified peaks # if plot: plt.subplot(2,2,3) plt.plot(freqs,f1) plt.scatter(freqs[peaks],f1[peaks],s=50) plt.xlim([0,10]) plt.ylim([0,1.1]) plt.xlabel('frequency (Hz)') plt.ylabel('power') # get a crude guess to the frequency, and cut the data around it # fguess = np.min(peaks) lo = fguess-10 hi = fguess+10 f1 = f1[lo:hi] freqs = freqs[lo:hi] fguess = np.argsort(f1)[-1] # find_peaks() doesn't always get the # exact location # update frequency guess based on gaussian interpolation # (ie, fit a parabola to log(f1)) # alpha = log(f1[fguess-1]) beta = log(f1[fguess]) gamma = log(f1[fguess+1]) a = 0.5 * (alpha - 2*beta + gamma) p = 0.5 * (alpha - gamma) / (alpha - 2*beta + gamma) b = beta - a * p**2 # new plot, zoomed in on the peak, with a Gaussian fit to the profile # if plot: xs = np.arange(0,f1.shape[0],0.1) model = np.exp(a*(xs-p-fguess)**2 + b) plt.subplot(2,2,4) plt.plot(freqs,f1) plt.plot(xs*minfreq+freqs[0],model) plt.scatter(freqs[fguess],f1[fguess]) plt.scatter(minfreq*(p+fguess) + freqs[0],np.max(model), color='r') plt.ylim([0,1.1]) plt.xlim([np.min(freqs),np.max(freqs)]) plt.xlabel('frequency (Hz)') plt.ylabel('power') fguessrefined = freqs[fguess] + p * minfreq return freqs[fguess], fguessrefined
def fftp(item): """ Calculate amplitude and phase as a function of frequency Inputs ------ item - an XPadDataItem object Returns ------- amplitude, phase pair of XPadDataItem objects """ if len(item.dim) != 1: raise ValueError("fftp can only operate on 1D traces currently") # Calculate FFT data = rfft(item.data)*(1./len(item.data)) # Create a dimension dim = XPadDataDim() dim.name = "Frequency" step = (item.dim[0].data[1] - item.dim[0].data[0]) dim.data = rfftfreq(len(item.data), step) dim.units = "1/"+item.dim[0].units if item.dim[0].units in ["s", "S", "sec", "Sec", "SEC"]: dim.data /= 1000. dim.units = "kHz" # Calculate the amplitude amp = XPadDataItem() if item.name != "": amp.name = "AMP( "+item.name+" )" amp.source = item.source if item.label != "": amp.label = "AMP( "+item.label+" )" amp.units = item.units amp.data = abs(data) amp.dim = [dim] # Calculate the phase phase = XPadDataItem() if item.name != "": phase.name = "PHASE( "+item.name+" )" phase.source = item.source if item.label != "": phase.label = "PHASE( "+item.label+" )" phase.units = "Radians" phase.data = arctan2(data.real, data.imag) a = phase.data - 2*pi for i in range(1,len(phase.data)): if abs(phase.data[i-1] - a[i]) < 1.: phase.data[i] = a[i] a = phase.data + 2*pi for i in range(1,len(phase.data)): if abs(phase.data[i-1] - a[i]) < 1.: phase.data[i] = a[i] phase.dim = [dim] return amp, phase
def __init__(self, Slices, impedance_source_list, frequency_resolution_input = None, freq_res_option = 'round', n_turns_memory = 0, recalculation_impedance = False, save_individual_voltages = False): #: *Copy of the Slices object in order to access the profile info.* self.slices = Slices #: *Impedance sources inputed as a list (eg: list of BBResonators objects)* self.impedance_source_list = impedance_source_list #: *Input frequency resolution in [Hz], the beam profile sampling for the spectrum #: will be adapted according to the freq_res_option.* self.frequency_resolution_input = frequency_resolution_input #: *Number of turns to be considered as memory for induced voltage calculation.* self.n_turns_memory = n_turns_memory #: *Length of one slice.* time_resolution = (self.slices.bin_centers[1] - self.slices.bin_centers[0]) self.recalculation_impedance = recalculation_impedance if n_turns_memory==0: if self.frequency_resolution_input == None: self.n_fft_sampling = self.slices.n_slices else: self.freq_res_option = freq_res_option if self.freq_res_option is 'round': self.n_fft_sampling = next_regular(int(np.round(1/(self.frequency_resolution_input * time_resolution)))) elif self.freq_res_option is 'ceil': self.n_fft_sampling = next_regular(int(np.ceil(1/(self.frequency_resolution_input * time_resolution)))) elif self.freq_res_option is 'floor': self.n_fft_sampling = next_regular(int(np.floor(1/(self.frequency_resolution_input * time_resolution)))) else: raise RuntimeError('The input freq_res_option is not recognized') if self.n_fft_sampling < self.slices.n_slices: print 'The input frequency resolution step is too big, and the whole \ bunch is not sliced... The number of sampling points for the \ FFT is corrected in order to sample the whole bunch (and \ you might consider changing the input in order to have \ a finer resolution).' self.n_fft_sampling = next_regular(self.slices.n_slices) #: *Real frequency resolution in [Hz], according to the obtained n_fft_sampling.* self.frequency_resolution = 1 / (self.n_fft_sampling * time_resolution) #: *Frequency array of the impedance in [Hz]* self.frequency_array = rfftfreq(self.n_fft_sampling, self.slices.bin_centers[1] - self.slices.bin_centers[0]) #: *Total impedance array of all sources in* [:math:`\Omega`] self.total_impedance = 0 self.sum_impedances(self.frequency_array) self.save_individual_voltages = save_individual_voltages if self.save_individual_voltages: self.len_impedance_source_list = len(impedance_source_list) self.matrix_save_individual_impedances = np.zeros((self.len_impedance_source_list, len(self.frequency_array))) self.matrix_save_individual_voltages = np.zeros((self.len_impedance_source_list, self.slices.n_slices)) for i in self.len_impedance_source_list: self.matrix_save_individual_impedances[i,:] = impedance_source_list[i].impedance #: *Induced voltage from the sum of the wake sources in [V]* self.induced_voltage = 0 else: self.n_turns_memory = n_turns_memory self.len_array_memory = (self.n_turns_memory+1) * self.slices.n_slices self.len_array_memory_extended = (self.n_turns_memory+2) * self.slices.n_slices self.n_points_fft = next_regular(self.len_array_memory_extended) self.frequency_array_memory = rfftfreq(self.n_points_fft, time_resolution) self.total_impedance_memory = np.zeros(self.frequency_array_memory.shape) + 0j self.time_array_memory = self.slices.bin_centers for i in range(1, self.n_turns_memory+1): self.time_array_memory = np.concatenate((self.time_array_memory, self.slices.bin_centers+(self.slices.edges[-1]-self.slices.edges[0])*i)) for imped_object in self.impedance_source_list: imped_object.imped_calc(self.frequency_array_memory) self.total_impedance_memory += imped_object.impedance
def getFFT(signal, sample_spacing=1) : """ get (frequency, complex coefficient) list representing the spectrum of the signal (list of value sampled with the sample_spacing (1/sample_rate) (every 1s)) """ return zip(rfftfreq(len(signal),d=sample_spacing),rfft(signal))