def smooth(data, window_type='hann', filter_width=11, sigma=2, plot_on=1): """ Smooth 1d data with moving window (uses filtfilt to have zero phase distortion) Wrapper for scipy.signal.filtfilt To do: consider replacing with sosfiltfilt Inputs: data: numpy array window_type ('hann'): string ('boxcar', 'gaussian', 'hann', 'bartlett', 'blackman') filter_width (11): int (wider is more smooth) odd is ideal sigma (2.): scalar std deviation only used for gaussian plot_on (1): int determines plotting. 0 none, 1 plot signal, 2: also plot filter Outputs data_smoothed: signal after being smoothed filter_window: the window used for smoothing Notes: Uses gustaffson's method to handle edge artifacts Currently accepted window_type options: hann (default) - cosine bump filter_width is only param blackman - more narrowly peaked bump than hann boxcar - flat-top of length filter_width bartlett - triangle gaussian - sigma determines width """ if window_type == 'boxcar': filter_window = windows.boxcar(filter_width) elif window_type == 'hann': filter_window = windows.hann(filter_width) elif window_type == 'bartlett': filter_window = windows.bartlett(filter_width) elif window_type == 'blackman': filter_window = windows.blackman(filter_width) elif window_type == 'gaussian': filter_window = windows.gaussian(filter_width, sigma) filter_window = filter_window / np.sum(filter_window) data_smoothed = signal.filtfilt(filter_window, 1, data, method="gust") # pad if plot_on: if plot_on > 1: plt.plot(filter_window) plt.title(f'{window_type} filter') plt.figure('signal', figsize=(10, 5)) plt.plot(data, color=(0.7, 0.7, 0.7), label='noisy signal', linewidth=1) plt.plot(data_smoothed, color='r', label='smoothed signal') plt.xlim(0, len(data_smoothed)) plt.xlabel('sample') plt.grid(True) plt.legend() return data_smoothed, filter_window
def bartlett(dataset, **kwargs): r""" Calculate Bartlett apodization (triangular window with end points at zero). For multidimensional NDDataset, the apodization is by default performed on the last dimension. The data in the last dimension MUST be time-domain or dimensionless, otherwise an error is raised. The Bartlett window is defined as .. math:: w(n) = \frac{2}{M-1} (\frac{M-1}{2} - |n - \frac{M-1}{2}|) where M is the number of point of the input dataset. Parameters ---------- dataset : Dataset Input dataset. **kwargs Additional keyword parameters (see Other Parameters). Returns ------- apodized Dataset. apod_arr The apodization array only if 'retapod' is True. Other Parameters ---------------- dim : str or int, keyword parameter, optional, default='x' Specify on which dimension to apply the apodization method. If `dim` is specified as an integer it is equivalent to the usual `axis` numpy parameter. inv : bool, keyword parameter, optional, default=False True for inverse apodization. rev : bool, keyword parameter, optional, default=False True to reverse the apodization before applying it to the data. inplace : bool, keyword parameter, optional, default=False True if we make the transform inplace. If False, the function return a new dataset. retapod : bool, keyword parameter, optional, default=False True to return the apodization array along with the apodized object. See Also -------- triang : A triangular window that does not touch zero at the ends. """ x = dataset return x * windows.bartlett(len(x), sym=True)
def get_fft_window(window_type, window_length): # Generate the window with the right number of points window = None if window_type == "Bartlett": window = windows.bartlett(window_length) if window_type == "Blackman": window = windows.blackman(window_length) if window_type == "Blackman Harris": window = windows.blackmanharris(window_length) if window_type == "Flat Top": window = windows.flattop(window_length) if window_type == "Hamming": window = windows.hamming(window_length) if window_type == "Hanning": window = windows.hann(window_length) # If no window matched, use a rectangular window if window is None: window = np.ones(window_length) # Return the window return window
def test_basic(self): assert_allclose(windows.bartlett(6), [0, 0.4, 0.8, 0.8, 0.4, 0]) assert_allclose(windows.bartlett(7), [0, 1/3, 2/3, 1.0, 2/3, 1/3, 0]) assert_allclose(windows.bartlett(6, False), [0, 1/3, 2/3, 1.0, 2/3, 1/3])
def testbench(): #Parametros del muestreo fs = 1024 N = 1024 #Enciendo el generador de funciones generador = gen.signal_generator(fs,N) #Genero el tono x1 fd = 0.5*(fs/N) fd = 0 A1 = 1 f1 = int(np.round(N/4)) + fd p1 = 0 (t,x1) = generador.sinewave(A1,f1,p1) #Genero el tono x2 K1 = 40 K2 = np.power(10,-K1/20) A2 = A1*K2 f2 = int(np.round(N/4)) + int(10) p2 = 0 (t,x2) = generador.sinewave(A2,f2,p2) #Genero el la funcion bitonal x = x1 + x2 plt.figure() plt.title('Funcion bitonal') plt.plot(t,x) plt.xlabel('t[s]') plt.ylabel('x(t)[s]') plt.grid() #Genera la ventana w = win.bartlett(N) w = np.reshape(w,(N,1)) #Grafica la ventana plt.figure() plt.plot(t,w) plt.title('Ventana') plt.ylabel('w(t)[V]') plt.xlabel('t[s]') plt.grid() #Genera la secuencia bitonal ventaneada x = x*w #Grafica la secuencia ventaneada # plt.figure() # plt.plot(t,xw) # plt.title('Secuencia ventaneada') # plt.ylabel('x(t)[V]') # plt.xlabel('t[s]') #Enciendo el analizador de espectro analizador = sa.spectrum_analyzer(fs,N,"fft") # # #Grafico el espectro de la ventana # # analizador.module_phase(w) #Grafico el espectro de la funcion bitonal sin ventanear analizador.module_phase(x)
def pre_processing(self): """ Complete various pre-processing steps for encoded protein sequences before doing any of the DSP-related functions or transformations. Zero-pad the sequences, remove any +/- infinity or NAN values, get the approximate protein spectra and window function parameter names. Parameters ---------- :self (PyDSP object): instance of PyDSP class. Returns ------- None """ #zero-pad encoded sequences so they are all the same length self.protein_seqs = zero_padding(self.protein_seqs) #get shape parameters of proteins seqs self.num_seqs = self.protein_seqs.shape[0] self.signal_len = self.protein_seqs.shape[1] #replace any positive or negative infinity or NAN values with 0 self.protein_seqs[self.protein_seqs == -np.inf] = 0 self.protein_seqs[self.protein_seqs == np.inf] = 0 self.protein_seqs[self.protein_seqs == np.nan] = 0 #replace any NAN's with 0's #self.protein_seqs.fillna(0, inplace=True) self.protein_seqs = np.nan_to_num(self.protein_seqs) #initialise zeros array to store all protein spectra self.fft_power = np.zeros((self.num_seqs, self.signal_len)) self.fft_real = np.zeros((self.num_seqs, self.signal_len)) self.fft_imag = np.zeros((self.num_seqs, self.signal_len)) self.fft_abs = np.zeros((self.num_seqs, self.signal_len)) #list of accepted spectra, window functions and filters all_spectra = ['power', 'absolute', 'real', 'imaginary'] all_windows = [ 'hamming', 'blackman', 'blackmanharris', 'gaussian', 'bartlett', 'kaiser', 'barthann', 'bohman', 'chebwin', 'cosine', 'exponential' 'flattop', 'hann', 'boxcar', 'hanning', 'nuttall', 'parzen', 'triang', 'tukey' ] all_filters = [ 'savgol', 'medfilt', 'symiirorder1', 'lfilter', 'hilbert' ] #set required input parameters, raise error if spectrum is none if self.spectrum == None: raise ValueError( 'Invalid input Spectrum type ({}) not available in valid spectra: {}' .format(self.spectrum, all_spectra)) else: #get closest correct spectra from user input, if no close match then raise error spectra_matches = (get_close_matches(self.spectrum, all_spectra, cutoff=0.4)) if spectra_matches == []: raise ValueError( 'Invalid input Spectrum type ({}) not available in valid spectra: {}' .format(self.spectrum, all_spectra)) else: self.spectra = spectra_matches[0] #closest match in array if self.window_type == None: self.window = 1 #window = 1 is the same as applying no window else: #get closest correct window function from user input window_matches = (get_close_matches(self.window, all_windows, cutoff=0.4)) #check if sym=True or sym=False #get window function specified by window input parameter, if no match then window = 1 if window_matches != []: if window_matches[0] == 'hamming': self.window = hamming(self.signal_len, sym=True) self.window_type = "hamming" elif window_matches[0] == "blackman": self.window = blackman(self.signal_len, sym=True) self.window = "blackman" elif window_matches[0] == "blackmanharris": self.window = blackmanharris(self.signal_len, sym=True) #** self.window_type = "blackmanharris" elif window_matches[0] == "bartlett": self.window = bartlett(self.signal_len, sym=True) self.window_type = "bartlett" elif window_matches[0] == "gaussian": self.window = gaussian(self.signal_len, std=7, sym=True) self.window_type = "gaussian" elif window_matches[0] == "kaiser": self.window = kaiser(self.signal_len, beta=14, sym=True) self.window_type = "kaiser" elif window_matches[0] == "hanning": self.window = hanning(self.signal_len, sym=True) self.window_type = "hanning" elif window_matches[0] == "barthann": self.window = barthann(self.signal_len, sym=True) self.window_type = "barthann" elif window_matches[0] == "bohman": self.window = bohman(self.signal_len, sym=True) self.window_type = "bohman" elif window_matches[0] == "chebwin": self.window = chebwin(self.signal_len, sym=True) self.window_type = "chebwin" elif window_matches[0] == "cosine": self.window = cosine(self.signal_len, sym=True) self.window_type = "cosine" elif window_matches[0] == "exponential": self.window = exponential(self.signal_len, sym=True) self.window_type = "exponential" elif window_matches[0] == "flattop": self.window = flattop(self.signal_len, sym=True) self.window_type = "flattop" elif window_matches[0] == "boxcar": self.window = boxcar(self.signal_len, sym=True) self.window_type = "boxcar" elif window_matches[0] == "nuttall": self.window = nuttall(self.signal_len, sym=True) self.window_type = "nuttall" elif window_matches[0] == "parzen": self.window = parzen(self.signal_len, sym=True) self.window_type = "parzen" elif window_matches[0] == "triang": self.window = triang(self.signal_len, sym=True) self.window_type = "triang" elif window_matches[0] == "tukey": self.window = tukey(self.signal_len, sym=True) self.window_type = "tukey" else: self.window = 1 #window = 1 is the same as applying no window #calculate convolution from protein sequences if self.convolution is not None: if self.window is not None: self.convoled_seqs = signal.convolve( self.protein_seqs, self.window, mode='same') / sum( self.window) if self.filter != None: #get closest correct filter from user input filter_matches = (get_close_matches(self.filter, all_filters, cutoff=0.4)) #set filter attribute according to approximate user input if filter_matches != []: if filter_matches[0] == 'savgol': self.filter = savgol_filter(self.signal_len, self.signal_len) elif filter_matches[0] == 'medfilt': self.filter = medfilt(self.signal_len) elif filter_matches[0] == 'symiirorder1': self.filter = symiirorder1(self.signal_len, c0=1, z1=1) elif filter_matches[0] == 'lfilter': self.filter = lfilter(self.signal_len) elif filter_matches[0] == 'hilbert': self.filter = hilbert(self.signal_len) else: self.filter = "" #no filter