def target_filter(ac, an): sos = butter(4, 0.125, output='sos') acce = sosfiltfilt(sos, ac) angl = sosfiltfilt(sos, an) return acce, angl
def _fitFilterBandsW(self, z): # it weiths one fourth the fit in the gamma freqeucny simuProfile = [] for coefsos in self.coeFil: # filter frequency bands zFilt = sg.sosfiltfilt(coefsos, np.imag(z), axis=1, padtype='odd') zEnv = np.abs(sg.hilbert(zFilt, axis=1)) # filter envelope zEnvFilt = sg.sosfiltfilt(self.coeFilEnv, zEnv, axis=1, padtype='odd') # Correlation discarding warmup time envCo = np.corrcoef( zEnvFilt[:, int(self.tMin * self.fs):-int(self.tMin * self.fs / 2)], rowvar=True) # set to zero negative correlations envCo = np.clip(envCo, a_min=0, a_max=None) simuProfile = np.append(simuProfile, envCo[np.triu_indices(z.shape[0], 1)]) #print(simuProfile.shape) ccoef1, pval = pearsonr(simuProfile[:-4005], self.empiProfile[:-4005]) ccoefGam, pval = pearsonr(simuProfile[-4005:], self.empiProfile[-4005:]) ccoef = (3 * ccoef1 + (ccoefGam / 2)) / 4 return -1 * ccoef, envCo
def variance_explained(fit,data): band_fit = sosfiltfilt(butter(4, [1/150,1/10], 'bandpass', output='sos', fs=t_n/win), fit) band_data = sosfiltfilt(butter(4, [1/150,1/10], 'bandpass', output='sos', fs=t_n/win), data) tot_vari = np.var(band_data) resid_vari = np.var(band_data-band_fit) expl_vari = tot_vari - resid_vari return expl_vari/tot_vari
def _fitFilterBands(self, z): ccoef = [None] * self.fBands.shape[0] for idx, coefsos in enumerate(self.coeFil): # filter frequency bands zFilt = sg.sosfiltfilt(coefsos, np.imag(z), axis=1, padtype='odd') zEnv = np.abs(sg.hilbert(zFilt, axis=1)) # filter envelope zEnvFilt = sg.sosfiltfilt(self.coeFilEnv, zEnv, axis=1, padtype='odd') # Correlation discarding warmup time envCo = np.corrcoef( zEnvFilt[:, int(self.tMin * self.fs):-int(self.tMin * self.fs / 2)], rowvar=True) # set to zero negative correlations envCo = np.clip(envCo, a_min=0, a_max=None) simuProfile = envCo[np.triu_indices(z.shape[0], 1)] ccoef[idx], pval = pearsonr( simuProfile, self.empiProfile[self.edgesBand[0, idx]:self.edgesBand[1, idx]]) return -1 * np.array(ccoef)
def bandpass_data(data, *, lowcut=300, highcut=6000, fs=30000, order=3, indiv_chans=False, preprocess=False): nyq = 0.5 * fs low = lowcut / nyq high = highcut / nyq sos = signal.butter(3, [low, high], analog=False, btype='band', output='sos') if indiv_chans: print('Bandpassing individual channels') bp_data = [] for index, i in enumerate(data): st = time.time() y = signal.sosfiltfilt(sos, i) bp_data.append(y) print('Bandpassed channel %d out of %d in' % (index, len(data)), time.time() - st) bp_data = np.array(bp_data) else: bp_data = signal.sosfiltfilt(sos, data) if preprocess: print('Preproccing data') y_process = preprocess_data(bp_data) return bp_data, y_process else: return bp_data
def __iir_filtering(self): """ calc iir filter """ max_freq = 100e3 min_freq = 20e3 bin_num = 81 bandwidth = 4e3 f_emit_list = [] f_echo_right_list = [] f_echo_left_list = [] for i in range(bin_num): hz = i*1e3 sos = signal.iirfilter(N=10, Wn=[min_freq + hz - bandwidth / 2, min_freq + hz + bandwidth / 2], btype="bandpass", analog=False, ftype="butter", output="sos", fs=fs) f_emit_wave = signal.sosfiltfilt(sos, self.emit_wave, padlen=0) f_echo_wave_right = signal.sosfiltfilt( sos, self.echo_without_emit_wave[0]) f_echo_wave_left = signal.sosfiltfilt( sos, self.echo_without_emit_wave[1]) f_emit_list.append(f_emit_wave) f_echo_right_list.append(f_echo_wave_right) f_echo_left_list.append(f_echo_wave_left) return f_emit_list, f_echo_right_list, f_echo_left_list
def curve_filter(posx, posy): sos = butter(4, 0.125, output='sos') positionx = sosfiltfilt(sos, posx) positiony = sosfiltfilt(sos, posy) return positionx, positiony
def chebyBandpassFilter(data, cutoff, gstop=40, gpass=1, fs=2048.): """ Design a filter with scipy functions avoiding unstable results (when using ab output and filtfilt(), lfilter()...). Cf. ()[] Parameters ---------- data : instance of numpy.array | instance of pandas.core.DataFrame Data to be filtered. Each column will be filtered if data is a dataframe. cutoff : array-like of float Pass and stop frequencies in order: - the first element is the stop limit in the lower bound - the second element is the lower bound of the pass-band - the third element is the upper bound of the pass-band - the fourth element is the stop limit in the upper bound For instance, [0.9, 1, 45, 48] will create a band-pass filter between 1 Hz and 45 Hz. gstop : int The minimum attenuation in the stopband (dB). gpass : int The maximum loss in the passband (dB). Returns: zpk : filteredData : instance of numpy.array | instance of pandas.core.DataFrame The filtered data. """ wp = [cutoff[1] / (fs / 2), cutoff[2] / (fs / 2)] ws = [cutoff[0] / (fs / 2), cutoff[3] / (fs / 2)] z, p, k = iirdesign(wp=wp, ws=ws, gstop=gstop, gpass=gpass, ftype='cheby2', output='zpk') zpk = [z, p, k] sos = zpk2sos(z, p, k) order, Wn = cheb2ord(wp=wp, ws=ws, gstop=gstop, gpass=gpass, analog=False) print 'Creating cheby filter of order %d...' % order if (data.ndim == 2): print 'Data contain multiple columns. Apply filter on each columns.' filteredData = np.zeros(data.shape) for electrode in range(data.shape[1]): # print 'Filtering electrode %s...' % electrode filteredData[:, electrode] = sosfiltfilt(sos, data[:, electrode]) else: # Use sosfiltfilt instead of filtfilt fixed the artifacts at the beggining # of the signal filteredData = sosfiltfilt(sos, data) return zpk, filteredData
def filt_B(data_in, fs, lowcut=0, highcut=1, order=4, causal=True, axis=0): """ Butterworth filter Input ----- date_in : 1D or 2D array fs : float Sampling frequency of data_in lowcut : float Lower frequency boundary, low-pass filtering if 0 highcut : float Higher frequency boudanry; high-pass not explictly implemented order : int causal : bool If True, do forward-backward filtering (zero-phase); otherwise two-pass forward filtering (acausal signals before initial) axis : int If set to 1, force the last axis to be the time axis Return ------ data_out : shape of data_in Filtered data, with the same shape as data_in """ if highcut >= fs / 2: print( "Upper band frequency larger than Nyquist, no filtering is done!") return data_in sz = data_in.shape if len(sz) > 1 and sz[0] > sz[1] and not axis: # Make sure the time axis is the last axis data_in = data_in.T data_out = np.zeros_like(data_in) nyq = fs / 2 low = lowcut / nyq high = highcut / nyq if low == 0: # lowpass sos = butter(order, high, analog=False, btype='low', output='sos') else: # bandpass sos = butter(order, [low, high], analog=False, btype='band', output='sos') if len(sz) > 1: for i in range(data_in.shape[0]): if causal == True: data_out[i, :] = sosfilt(sos, data_in[i, :]) data_out[i, :] = sosfilt(sos, data_out[i, :]) else: data_out[i, :] = sosfiltfilt(sos, data_in[i, :]) if sz[0] > sz[1] and not axis: data_out = data_out.T else: if causal == True: data_out = sosfilt(sos, data_in) data_out = sosfilt(sos, data_out) else: data_out = sosfiltfilt(sos, data_in) return data_out
def get_stabilize_transform(self, gyro_time): # Method to bypass external orientation processing and do everything here from the raw gyro data times = gyro_time[:, 0] gyro = gyro_time[:, 1:] self.num_data_points = times.shape[0] self.gyro_sample_rate = self.num_data_points / (times[-1] - times[0]) dt = 1 / self.gyro_sample_rate traj = np.cumsum(gyro * dt, 0) smoothed_traj = np.copy(traj) # per convention x is pitch, y is yaw, and z is roll if self.get_user_option_value("pitch_smoothness") > 0: sosgyro = signal.butter( 1, 1 / self.get_user_option_value("pitch_smoothness"), "lowpass", fs=self.gyro_sample_rate, output="sos") smoothed_traj[:, 0] = signal.sosfiltfilt( sosgyro, smoothed_traj[:, 0], 0) # Filter along "vertical" time axis if self.get_user_option_value("yaw_smoothness") > 0: sosgyro = signal.butter( 1, 1 / self.get_user_option_value("yaw_smoothness"), "lowpass", fs=self.gyro_sample_rate, output="sos") smoothed_traj[:, 1] = signal.sosfiltfilt( sosgyro, smoothed_traj[:, 1], 0) # Filter along "vertical" time axis if self.get_user_option_value("roll_smoothness") > 0: sosgyro = signal.butter( 1, 1 / self.get_user_option_value("roll_smoothness"), "lowpass", fs=self.gyro_sample_rate, output="sos") smoothed_traj[:, 2] = signal.sosfiltfilt( sosgyro, smoothed_traj[:, 2], 0) # Filter along "vertical" time axis stab_rotvec = traj - smoothed_traj # How to rotate camera. From smoothed to real to counteract # convert to quaternion correction_quats = Rotation.from_rotvec(stab_rotvec).as_quat() # scalar in beginning correction_quats[:, [0, 1, 2, 3]] = correction_quats[:, [3, 0, 1, 2]] # Return timelist, quaternion list return times, correction_quats
def apply_filter(data, filt): if len(data.shape) == 1: return sosfiltfilt(filt, data) else: return np.stack([ sosfiltfilt(filt, data[:][:, 0]), sosfiltfilt(filt, data[:][:, 1]) ], axis=-1)
def filter_data(x, filter_type='butter', high_cutoff=500, sampling_freq=2e4): if filter_type == 'butter': sos = butter(N=2, Wn=high_cutoff, fs=sampling_freq, output='sos') y = sosfiltfilt(sos, x) elif filter_type == 'bessel': sos = bessel(4, high_cutoff, fs=sampling_freq, output='sos') y = sosfiltfilt(sos, x) elif filter_type == 'decimate': y = decimate(x, 10, n=4) else: y = x return y
def butter_filter(dataset, low = 4.0, high = 20.0, order = 8, btype = 'bandpass', fs = 512): """ Phase preserving filter (bandpass, lowpass or highpass) based on a butterworth filter Parameters ---------- dataset : `numpy.ndarray` input data (chans x lenght) where chan==0 is target lowcut : `float` low knee frequency highcut : `float` high knee frequency order : `int` filter order btype : `str` type of filter (bandpass, highpass, lowpass) fs : `int` sample rate Returns ------- dataset : `numpy.ndarray` filtered dataset """ # Normalize the frequencies nyq = 0.5 * fs low /= nyq high /= nyq # Make and apply filter if 'high' in btype: z, p, k = sig.butter(order, low, btype=btype, output='zpk') elif 'band' in btype: z, p, k = sig.butter(order, [low, high], btype=btype, output='zpk') elif 'low' in btype: z, p, k = sig.butter(order, high, btype=btype, output='zpk') sos = sig.zpk2sos(z, p, k) if dataset.ndim == 2: for i in range(dataset.shape[0]): dataset[i, :] = sig.sosfiltfilt(sos, dataset[i, :]) else: dataset = sig.sosfiltfilt(sos, dataset) return dataset
def filter(sig, sosfilter, stereo=True): """ same as bandstop_butter but uses second-order sections (sosfiltfilt), which have 'fewer numerical problems' """ if not stereo: return signal.sosfiltfilt(sosfilter, sig) left_channel = signal.sosfiltfilt(sosfilter, sig[:, 0]) right_channel = signal.sosfiltfilt(sosfilter, sig[:, 1]) return channels_to_stereo(left_channel, right_channel)
def connectvityBands(z, coeFil, coeFilEnv, tMin, fs): envCo = [] for coefsos in coeFil: # filter frequency bands zFilt = sg.sosfiltfilt(coefsos, np.imag(z), axis=1, padtype='odd') zEnv = np.abs(sg.hilbert(zFilt, axis=1)) # filter envelope zEnvFilt = sg.sosfiltfilt(coeFilEnv, zEnv, axis=1, padtype='odd') # Correlation discarding warmup time envCo.append( np.corrcoef(zEnvFilt[:, int(tMin * fs):-int(tMin * fs)], rowvar=True)) envCo = np.dstack(envCo) return envCo
def apply_sos_filter_to_array_with_nans(array, sos, padlen=6): try: array_filt = np.full_like(array, np.nan) ds, de = parse_array_at_nans(array) for s, e in zip(ds, de): k = array[s:e] if len(k) > padlen: k_filt = sosfiltfilt(sos, k, padlen=padlen) array_filt[s:e] = k_filt return array_filt except: array_filt = sosfiltfilt(sos, array, padlen=padlen) # raise ValueError return array_filt
def preprocess(self, pcg, ecg): # Normalise PCG pcg_mean = np.mean(pcg) pcg_std = np.std(pcg, ddof=1) pcg_norm = (pcg - pcg_mean) / pcg_std # Downsample PCG and ECG raw_mic_ds = signal.decimate(pcg_norm, 2) raw_ecg_ds = signal.decimate(ecg, 2) # Filter PCG mic_filt_hp = signal.sosfiltfilt(self.coeffs_hp, raw_mic_ds) mic_filt = signal.sosfiltfilt(self.coeffs_lp, mic_filt_hp) return mic_filt, raw_ecg_ds
def _fitFilterBands(self,z): "It only filters one frequency band: self.band" # filter frequency bands zFilt = sg.sosfiltfilt(self.coeFil[self.band], np.imag(z), axis=1, padtype='odd') zEnv = np.abs(sg.hilbert(zFilt, axis=1)) # filter envelope zEnvFilt= sg.sosfiltfilt(self.coeFilEnv, zEnv, axis=1, padtype='odd') # Correlation discarding warmup time envCo = np.corrcoef(zEnvFilt[:,int(self.tMin*self.fs):-int(self.tMin*self.fs/2)], rowvar=True) # set to zero negative correlations envCo = np.clip(envCo, a_min=0, a_max=None) # correlation per band of empirical and simulated data simuProfile = envCo[np.triu_indices(z.shape[0],1)] ccoef, pval = pearsonr(simuProfile, self.empiProfile) return -1 * ccoef
def get_normalized_data(self, poses, joints=None): df = poses.get_joint_data(joints) df_cols = joints + ([j + '_conf' for j in joints]) dfout = pd.DataFrame(columns=df_cols) for j in joints: s = (df.loc[:, (j, ['x', 'likelihood'])]).copy() s.columns = s.columns.droplevel(0) s.interpolate(inplace=True, method='linear') s.dropna(inplace=True) x = s.x #x-coord keypoint conf = s.likelihood #keypoint confidence #high pass filter sos_filt = butter(8, 0.25, 'highpass', fs=30, output='sos') x_filt = sosfiltfilt(sos_filt, x.values) x_filt = pd.Series(data=x_filt, index=x.index) x = x_filt.copy() #zscore (this is just another rescaling between -1,1 really). Optionally try removing outliers NZ = Normalizer() x_filt_z = NZ.zscore(x) x = x_filt_z.copy() #assemble keypoint + confidence dfout[j] = x dfout[j + '_conf'] = conf return dfout
def remove_tides(cube, T=T_M2): time_coord = cube.coord('time') time_units = time_coord.units target_units = cf_units.Unit( 'seconds since 1970-01-01 00:00:00-00', calendar='gregorian' ) time = time_units.convert(time_coord.points, target_units) dt = numpy.diff(time) # assert (dt.max() - dt.min()) < 1e-3, 'Uneven dt is not supported' dt = dt.min() # filter design, low-pass butterworth T0 = (2 * dt) # period of Nyquist frequency Tpass = 8 * T # period of pass frequency Gpass = 3.0 # max dB loss in pass band Tstop = 1 * T # period of stop frequency Gstop = 30.0 # min dB atennuation in stop band o, Wn = signal.buttord(T0 / Tpass, T0 / Tstop, Gpass, Gstop) if o < 0: raise Exception( 'Cannot create tidal filter. Data sampling frequency may be too low, dt=' + str(dt)) sos = signal.butter(o, Wn, output='sos') data_filtered = signal.sosfiltfilt(sos, cube.data) new_cube = cube.copy() new_cube.data = data_filtered return new_cube
def signal_preprocess_linear( ser: pd.Series, sos: np.ndarray = None, output_type: str = 'final' ) -> Union[pd.Series, Tuple[pd.Series, pd.Series, pd.Series]]: """ Method to smooth your signal with Savitzky-Golay filter (see scipy.signal.savgol_filter) Parameters ---------- """ # First, resample at uniform sampling rate the data and interpolate ser_interp = signal_resample(ser) # Setup low-pass filter from EuroNCAP criteria sos = sos or butter(5, 4, 'low', output='sos', fs=10) # Filter the data using filtfilt (filter in bidirectional) ser_filt = pd.Series(sosfiltfilt(sos, ser_interp.to_list()), index=ser_interp.index) # Last, smooth the data with Savitsky-Golay ser_smooth = pd.Series(savgol_filter(ser_filt.to_list(), window_length=5, polyorder=2), index=ser_interp.index) # return different output depending on what user asks for (useful for test) if output_type == 'all': return (ser_interp, ser_filt, ser_smooth) else: return ser_smooth
def butter_filter(data, order, cutoff): buttered = {} sos = signal.butter(order, cutoff, btype='low', analog=False, output='sos') for shot in data: # this sorts in decending order (i.e 0-10) corrected = np.array(signal.sosfiltfilt(sos, data[shot][:, 1])) buttered.update({shot: [corrected]}) return buttered
def _fitFilterBands(self,z): simuProfile = [] for coefsos in self.coeFil: # filter frequency bands zFilt = sg.sosfiltfilt(coefsos, np.imag(z), axis=1, padtype='odd') zEnv = np.abs(sg.hilbert(zFilt, axis=1)) # filter envelope zEnvFilt= sg.sosfiltfilt(self.coeFilEnv, zEnv, axis=1, padtype='odd') # Correlation discarding warmup time envCo = np.corrcoef(zEnvFilt[:,int(self.tMin*self.fs):-int(self.tMin*self.fs/2)], rowvar=True) # set to zero negative correlations envCo = np.clip(envCo, a_min=0, a_max=None) simuProfile.append(envCo[np.triu_indices(z.shape[0],1)]) #print(simuProfile.shape) #ccoef, pval = pearsonr(simuProfile, self.empiProfile) return simuProfile
def butter_bandpass_filter(data, fs=None, lowcut=None, highcut=None, order=10): """ Buterworth high, low or band pass filter. Uses scipy.signal.sosfiltfilt -- A forward-backward digital filter using cascaded second-order sections. Parameters ---------- data : array Data array fs : float Sample Rate lowcut : float Low pass frequency cutoff highcut : float High pass frequency cutoff order : int Butterworth filter order [Default = 10, i.e., 10th order Butterworth filter] Reference --------- https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.sosfiltfilt.html http://scipy-cookbook.readthedocs.io/items/ButterworthBandpass.html """ from scipy.signal import sosfiltfilt sos = butter_bandpass(fs, lowcut=lowcut, highcut=highcut, order=order) return sosfiltfilt(sos, data)
def butter_filter(data, order, cutoff): buttered = {} sos = signal.butter(order, cutoff, btype='low', analog=False, output='sos') for bias in data: corrected = np.array(signal.sosfiltfilt(sos, data[bias][:, 1])) buttered[bias] = corrected return buttered
def highpass_filter(data, order=8, in_freq=800.0, cutoff_freq=1.0): highp_freq = (cutoff_freq / (in_freq / 2)) sos = _butter_highpass(order, highp_freq) # _butter_highpass(order, highp_freq) # Perform the filtering using Scipy, expensive operation return sosfiltfilt(sos, data)
def bandblock(x, dt, flow, fupp, order=5): """ Band block filter data signal x at cut off frequencies flow and fupp, blocking harmonic content inside the frequency band [flow, fupp] Parameters ---------- x : array_like Signal dt : float Signal sampling rate (s) flow, fupp : float Blocked frequency band (Hz) order : int, optional Butterworth filter order. Default 5. Returns ------- array Filtered signal Notes ----- SciPy bandpass/bandstop filters designed with b, a are unstable and may result in erroneous filters at higher filter orders. Here we use sos (second-order sections) output of filter design instead. See Also -------- scipy.signal.butter, scipy.signal.sosfiltfilt """ nyq = 0.5 * 1. / dt # nyquist frequency normal_cutoff = (flow / nyq, fupp / nyq) # normalized cut off frequencies sos = butter(order, normal_cutoff, btype='bandstop', analog=False, output='sos') y = sosfiltfilt(sos, x) return y
def filt(data, fs, cutoff_low=None, cutoff_high=None, filt_type='low', order=5): nyq = 0.5 * fs if cutoff_low is not None: norm_cutoff_low = cutoff_low / nyq if cutoff_high is not None: norm_cutoff_high = cutoff_high / nyq if filt_type is 'low': #b, a = butter(order, norm_cutoff_high, btype='low', analog=False) sos = butter(order, norm_cutoff_high, btype='low', output='sos', analog=False) elif filt_type is 'band': # b, a = butter(order, # [norm_cutoff_low, norm_cutoff_high], # btype='band', # analog=False) sos = butter(order, [norm_cutoff_low, norm_cutoff_high], btype='band', output='sos', analog=False) #data_filt = lfilter(b, a, data) # note that the order is twice as passed since filter applied 2 directions data_filt = sosfiltfilt(sos, data) # w, h = freqz(b, a) #for showing freq response w, h = sosfreqz(sos, fs=fs, worN=2000) return data_filt, (w, h)
def bandpass(x, dt, flow, fupp, order=5): """ Band pass filter data signal x at cut off frequencies flow and fupp, blocking harmonic content outside the frequency band [flow, fupp] Parameters ---------- x : array_like Signal dt : float Signal sampling rate (s) flow, fupp : float Passing frequency band (Hz) order : int, optional Butterworth filter order. Default 5. Returns ------- array Filtered signal See Also -------- scipy.signal.butter, scipy.signal.sosfiltfilt """ nyq = 0.5 * 1. / dt # nyquist frequency normal_cutoff = (flow / nyq, fupp / nyq) # normalized cut off frequencies sos = butter(order, normal_cutoff, btype='bandpass', analog=False, output='sos') y = sosfiltfilt(sos, x) return y
def baseline_plot(x): all_axes = plt.subplots(3, 2)[1] for ri, (axes, freq) in enumerate(zip(all_axes, [0.1, 0.3, 0.5])): for ci, ax in enumerate(axes): if ci == 0: iir_hp = signal.iirfilter(4, freq / sfreq, btype='highpass', output='sos') x_hp = signal.sosfiltfilt(iir_hp, x, padlen=0) else: x_hp -= x_hp[t < 0].mean() ax.plot(t, x, color='0.5') ax.plot(t, x_hp, color='k', linestyle='--') if ri == 0: ax.set(title=('No ' if ci == 0 else '') + 'Baseline Correction') ax.set(xticks=tticks, ylim=ylim, xlim=xlim, xlabel=xlabel) ax.set_ylabel('%0.1f Hz' % freq, rotation=0, horizontalalignment='right') mne.viz.adjust_axes(axes) mne.viz.tight_layout() plt.suptitle(title) plt.show()
def lowpass_butter(fs, L, order, data, axis=-1, btype='low'): """Perform a lowpass butterworth filter on data using a forward and backward digital filter. Parameters ---------- fs : float Sampling frequency of data (example: 12 for monthly data) L : float Critical frequency for Butterworth filter. See scipy docs. order : int Order of filter. Note that filtfilt doubles the original filter order. data : numpy array 1D vector or 2D array to be filtered axis : int Axis along which filtering is performed. btype : str 'high' or 'low' pass filter Returns ------- data_filtered : numpy array Filtered data """ from scipy.signal import butter, sosfiltfilt nyq = 0.5 * fs # Nyquist frequency low = L / nyq sos = butter(order, low, btype=btype, output='sos') # Coefficients for Butterworth filter filtered = sosfiltfilt(sos, data, axis=axis) return filtered
def filter(self, order=None, gyro_cutoff=None, acc_cutoff=None, nsamp=None, method='butter'): if method == 'butter': if gyro_cutoff is not None: if len(gyro_cutoff) == 1: gyro_hi = gyro_cutoff[0] gyro = self.gyro0 elif len(gyro_cutoff) == 2: gyro_hi = gyro_cutoff[1] gyrolo = self.get_low_baseline(self.t0, self.gyro0, gyro_cutoff[0]) gyro = self.gyro0 - gyrolo else: raise ValueError('Unrecognized frequency range {}'.format(acc_cutoff)) gyro_sos = signal.butter(order, gyro_hi/(self.sampfreq/2.0), "lowpass", output='sos') self.gyro = signal.sosfiltfilt(gyro_sos, gyro, axis=0) else: self.gyro = self.gyro0 if acc_cutoff is not None: if len(acc_cutoff) == 1: acc_hi = acc_cutoff[0] acc = self.acc0 elif len(acc_cutoff) == 2: acc_hi = acc_cutoff[1] acclo = self.get_low_baseline(self.t0, self.acc0, acc_cutoff[0]) acc = self.acc0 - acclo else: raise ValueError('Unrecognized frequency range {}'.format(acc_cutoff)) acc_sos = signal.butter(order, acc_hi / (self.sampfreq / 2.0), 'lowpass', output='sos') self.acc = signal.sosfiltfilt(acc_sos, acc, axis=0) else: self.acc = self.acc0 elif method == 'running': self.gyro = np.zeros_like(self.gyro0) self.accel = np.zeros_like(self.acc0) for i in range(3): self.gyro[:, i] = np.convolve(self.gyro0[:, i], np.ones((nsamp,))/nsamp, mode='same') self.accel[:, i] = np.convolve(self.acc0[:, i], np.ones((nsamp,))/nsamp, mode='same')
def _filter_gyro(self, t, gyro): if len(self.freqrange) == 1: btype = 'lowpass' elif len(self.freqrange) == 2: btype = 'bandpass' else: raise ValueError('Unrecognized frequency range {}'.format(self.freqrange)) sos = signal.butter(self.filterorder, self.freqrange/(self.sampfreq/2.0), btype, output='sos') gyros = signal.sosfiltfilt(sos, gyro, axis=0) return gyros
# # .. note:: Notice that the group delay (which is related to the phase) of # the IIR filters below are not constant. In the FIR case, we can # design so-called linear-phase filters that have a constant group # delay, and thus compensate for the delay (making the filter # non-causal) if necessary. This cannot be done with IIR filters, as # they have a non-linear phase (non-constant group delay). As the # filter order increases, the phase distortion near and in the # transition band worsens. However, if non-causal (forward-backward) # filtering can be used, e.g. with :func:`scipy.signal.filtfilt`, # these phase issues can theoretically be mitigated. sos = signal.iirfilter(2, f_p / nyq, btype='low', ftype='butter', output='sos') plot_filter(dict(sos=sos), sfreq, freq, gain, 'Butterworth order=2', flim=flim, compensate=True) x_shallow = signal.sosfiltfilt(sos, x) del sos ############################################################################### # The falloff of this filter is not very steep. # # .. note:: Here we have made use of second-order sections (SOS) # by using :func:`scipy.signal.sosfilt` and, under the # hood, :func:`scipy.signal.zpk2sos` when passing the # ``output='sos'`` keyword argument to # :func:`scipy.signal.iirfilter`. The filter definitions # given :ref:`above <tut_filtering_basics>` use the polynomial # numerator/denominator (sometimes called "tf") form ``(b, a)``, # which are theoretically equivalent to the SOS form used here. # In practice, however, the SOS form can give much better results # due to issues with numerical precision (see
def butter_lowpass_filtfilt(data, cutoff, fs, order): sos = butter_lowpass(cutoff, fs, order) y = sosfiltfilt(sos, data) return y