def test_scale_invariance(self): # Regression test. There was a bug in which b was not correctly # rescaled when a[0] was nonzero. b = np.array([2, 8, 5]) a = np.array([1, 1, 8]) zi1 = lfilter_zi(b, a) zi2 = lfilter_zi(2*b, 2*a) assert_allclose(zi2, zi1, rtol=1e-12)
def next_sample(self, samples): if len(self.zi) == 0: # scale to uV range to avoid huge transient self.zi = lfilter_zi(self.b, self.a) * samples[0] y, zf = lfilter(self.b, self.a, samples, zi=self.zi) self.zi = zf return y
def filterData(self, icurr, Fs): """ Denoise an ionic current time-series and store it in self.eventData :Parameters: - `icurr` : ionic current in pA - `Fs` : original sampling frequency in Hz """ self.eventData=icurr self.Fs=Fs self.filterModel=sig.filter_design.bessel( N=self.filterOrder, Wn=(self.filterCutoff/(self.Fs/2)), btype='lowpass', analog=False, output='ba' ) # calculate the initial state of the filter and scale it with the first data point # so there is no sharp transient at the start of the data zi=sig.lfilter_zi(b=self.filterModel[0], a=self.filterModel[1])*self.eventData[0] [self.eventData, zf]=sig.lfilter( b=self.filterModel[0], a=self.filterModel[1], x=self.eventData, zi=zi )
def SignalFilter_LPFButter(signal, LPF, samplefreq, NPole=8): """Filter with Butterworth low pass, using time-causal lfilter Digitally low-pass filter a signal using a multipole Butterworth filter. Does not apply reverse filtering so that result is causal. Parameters ---------- signal : array The signal to be filtered. LPF : float The low-pass frequency of the filter (Hz) HPF : float The high-pass frequency of the filter (Hz) samplefreq : float The uniform sampling rate for the signal (in seconds) npole : int Number of poles for Butterworth filter. Positive integer. Returns ------- w : array filtered version of the input signal """ flpf = float(LPF) sf = float(samplefreq) wn = [flpf / (sf / 2.0)] b, a = spSignal.butter(NPole, wn, btype="low", output="ba") zi = spSignal.lfilter_zi(b, a) out, zo = spSignal.lfilter(b, a, signal, zi=zi * signal[0]) return np.array(out)
def filtering_ionization(ion_alt_tuple): """ Template of an ionization signal. """ template_width = 1. #s template_points = template_width * 1000 template = np.ones(int(template_points)) template[:int(template_points / 2)] = 0 freq_cut = 2. #Hz order = 2 freq_nyq = freq / 2 freq_cut_norm = freq_cut / freq_nyq b, a = sgl.butter(order, freq_cut_norm, btype='highpass') zi = sgl.lfilter_zi(b, a) ion_tot = ion_alt_tuple[-1] ion_fil_tuple = sgl.lfilter(b, a, ion_tot, zi=zi * ion_tot[0])[0] template_fil = sgl.lfilter(b, a, template, zi=zi * template[0])[0] corr = np.correlate(ion_fil_tuple, template_fil, mode='same') corr = abs(corr) return corr
def _getInititalState(b, a, alpha=1): """ --INTERNAL FUNCTION-- Get an initial filter state that corresponds to the steady state of the step response. Kwargs: b (array): Numerator coefficients. a (array): Denominator coefficients. alpha (int, float): Scaling factor. Kwrvals: zi (array): The initial filter state See Also: _getFilter _plotFilter scipy.signal.lfilter scipy.signal.lfilter_zi Notes: Example: References: .. [1] """ return alpha * ss.lfilter_zi(b, a)
def get_coeffs(fs, f0, Q, ftype, dBgain=0.0): """ this calculates coeffs and initial conditions for signal.lfilter """ b, a = biquad(fs, f0, Q, ftype, dBgain) zi = lfilter_zi(b, a) return b, a, zi
def __init__(self, b, a, storeState=True, zeroPhase=False, initOut=None): '''Initialize the object Args: b (:obj:`list`): list of 'b' constants of filter a (:obj:`list`): list of 'a' constants of filter storeState (:obj:`bool`, optional): Whether the filter state must be stored. Useful when filtering a chunked signal to avoid border effects. zeroPhase (:obj:`bool`, optional): Whether the filter has to provide zero phase error to the input i.e. no delay in the output (Note: Enabling this will disable 'storeState' and 'initOut') initOut (:obj:`list`, optional): Initial condition of the filter ''' self.__storeState = storeState self.__zeroPhase = zeroPhase self.__initOut = initOut if self.__storeState and self.__zeroPhase: self.__storeState = False if (not self.__initOut == None) and self.__zeroPhase: self.__initOut = None if self.__storeState: self.__zi = signal.lfilter_zi(b, a) if not self.__initOut == None: self.__zi = None self.__b = b self.__a = a
def filter_butter(self, data): b = signal.firwin(self.filter_win, 0.004) z = signal.lfilter_zi(b, 1) butter = zeros(data.size) for i, x in enumerate(data): butter[i], z = signal.lfilter(b, 1, [x], zi=z) return butter
def FilterAMP(df, b='none', a='none'): """Function that filters the data corresponding to amperometric experiments. Return a dataframe with the values filtered in columns called time and current.""" if b == 'none': f = 4 #order of the filter elif b != 'none': f = b if a == 'none': g = 0.05 # The denominator coefficient #vector of the filter. elif a != 'none': g = a b, a = butter(f, g) y = df['current'].values zi = lfilter_zi(b, a) z, _ = lfilter(b, a, y, zi=zi * y[0]) mid = len(df['current'].values) // 2 # Apply the filter again, to have a result filtered #at an order the same as filtfilt. z2, _ = lfilter(b, a, z, zi=zi * z[0]) # Use filtfilt to apply the filter. xfiltered = filtfilt(b, a, df['time'].values) yfiltered = filtfilt(b, a, df['current'].values) d = {'time': xfiltered, 'current': yfiltered} return pd.DataFrame(data=d)
def Filter(self, LowCorner, HighCorner, Order=3): """ Butterworth bandpass filter """ FS = 1./self.HDR['TSMP'] if HighCorner >= FS/2.: print 'Warning: High corner must be < {0:.2f} Hz'.format(FS/2.) return if LowCorner < 0.: print 'Warning: Low corner must be > 0 Hz'.format(FS/2.) return # Corner frequencies Corners = [2.*LowCorner/FS, 2.*HighCorner/FS] # Butterworth filter b, a = _sig.butter(Order, Corners, btype='band') # Filtering records for I,S in enumerate(self.CHN): # self.CHN[I] = _sig.lfilter(b, a, S) zi = _sig.lfilter_zi(b, a); self.CHN[I],_ = _sig.lfilter(b, a, S, zi=zi*S[0])
def FilterVC(df, b='none', a='none'): """Function that filters the data corresponding to cyclic voltammetry experiments. Return a dataframe with the values filtered in columns called volt and current.""" if b == 'none': f = 4 #order of the filter elif b != 'none': f = b if a == 'none': g = 0.05 # The denominator coefficient #vector of the filter. elif a != 'none': g = a b, a = butter(f, g) y = df['current'].values zi = lfilter_zi(b, a) z, _ = lfilter(b, a, y, zi=zi * y[0]) mid = len(df['volt'].values) // 2 # Apply the filter again, to have a result filtered #at an order the same as filtfilt. z2, _ = lfilter(b, a, z, zi=zi * z[0]) # Use filtfilt to apply the filter. x_f1 = filtfilt(b, a, df['volt'].values[0:mid]) y_f1 = filtfilt(b, a, df['current'].values[0:mid]) x_f2 = filtfilt(b, a, df['volt'].values[mid:]) y_f2 = filtfilt(b, a, df['current'].values[mid:]) xfiltered = np.concatenate([x_f1, x_f2]) yfiltered = np.concatenate([y_f1, y_f2]) d = {'volt': xfiltered, 'current': yfiltered} return pd.DataFrame(data=d)
def update_buffer(data_buffer, new_data, notch = False, filter_state = None): """ Title: BCI Workshop Auxiliary Tools Author: Cassani Date: May 08 2015 Availability: https://github.com/NeuroTechX/bci-workshop Updates the buffer with new data and applies butterworth filter Arguments: buffer -- array for eeg data buffer [samples][channels] new_data -- array with new data from channel [samples][channels] apply_filter -- (Boolean) when True, apply filter to buffer filter_state -- array of filtered values Returns: new_buffer -- array of updated buffer [samples][channels] """ if new_data.ndim == 1: new_data = new_data.reshape(-1, data_buffer.shape[1]) if notch: if filter_state is None: filter_state = np.tile(lfilter_zi(NOTCH_B, NOTCH_A), (data_buffer.shape[1], 1)).T new_data, filter_state = lfilter(NOTCH_B, NOTCH_A, new_data, axis=0, zi = filter_state) new_buffer = np.concatenate((data_buffer, new_data), axis=0) new_buffer = new_buffer[new_data.shape[0]:, :] return new_buffer, filter_state
def filterData(self, icurr, Fs): """ Denoise an ionic current time-series and store it in self.eventData :Parameters: - `icurr` : ionic current in pA - `Fs` : original sampling frequency in Hz """ self.eventData = icurr self.Fs = Fs self.filterModel = sig.filter_design.bessel(N=self.filterOrder, Wn=(self.filterCutoff / (self.Fs / 2)), btype='lowpass', analog=False, output='ba') # calculate the initial state of the filter and scale it with the first data point # so there is no sharp transient at the start of the data zi = sig.lfilter_zi(b=self.filterModel[0], a=self.filterModel[1]) * self.eventData[0] [self.eventData, zf] = sig.lfilter(b=self.filterModel[0], a=self.filterModel[1], x=self.eventData, zi=zi)
def __init__(self, b, a=1, channels=['ax', 'ay', 'az']): # If FIR a = 1, with IIR set A self.b = b self.a = a self.zi = signal.lfilter_zi(self.b, self.a) self.channels = channels self.axis_f_states = {key: self.zi for key in self.channels}
def getData(self): t = time.time() bsz = bsz2 = bsz3 = lfilter_zi(self.bsB, self.bsA) while (self.running): t += self.period val, val2, val3 = methods.sample() # Filter values - cascade bandstop with bandpass val, bsz = lfilter(self.bsB, self.bsA, lfilter(self.bpB, self.bpA, [val]), zi=bsz) val2, bsz2 = lfilter(self.bsB, self.bsA, lfilter(self.bpB, self.bpA, [val2]), zi=bsz2) val3, bsz3 = lfilter(self.bsB, self.bsA, lfilter(self.bpB, self.bpA, [val3]), zi=bsz3) self.buffer.append(val + 2.5) self.buffer2.append(val2 + 5) self.buffer3.append(val3 + 7.5) #SESSION RECORDING if (self.session.recording): self.session.data.append(val) self.y[:] = self.buffer self.y2[:] = self.buffer2 self.y3[:] = self.buffer3 self.curve.setData(self.x, self.y) self.curve2.setData(self.x, self.y2) self.curve3.setData(self.x, self.y3) self.app.processEvents() time.sleep(max(0, t - time.time()))
def data(self): source = self.source.data() zi = lfilter_zi(*PassFilter.butterworth(self.cutoff, self.filter_type)) while True: filtered_data, zi = self.butterworth_filter(next(source), self.cutoff, self.filter_type, zi) yield filtered_data self.state = self.source.state
def Filter(self, LowCorner, HighCorner, Order=3): """ Butterworth bandpass filter """ FS = 1. / self.HDR['TSMP'] if HighCorner >= FS / 2.: print 'Warning: High corner must be < {0:.2f} Hz'.format(FS / 2.) return if LowCorner < 0.: print 'Warning: Low corner must be > 0 Hz'.format(FS / 2.) return # Corner frequencies Corners = [2. * LowCorner / FS, 2. * HighCorner / FS] # Butterworth filter b, a = _sig.butter(Order, Corners, btype='band') # Filtering records for I, S in enumerate(self.CHN): # self.CHN[I] = _sig.lfilter(b, a, S) zi = _sig.lfilter_zi(b, a) self.CHN[I], _ = _sig.lfilter(b, a, S, zi=zi * S[0])
def SignalFilter_LPFButter(signal, LPF, samplefreq, NPole=8): """Filter with Butterworth low pass, using time-causal lfilter Digitally low-pass filter a signal using a multipole Butterworth filter. Does not apply reverse filtering so that result is causal. Parameters ---------- signal : array The signal to be filtered. LPF : float The low-pass frequency of the filter (Hz) HPF : float The high-pass frequency of the filter (Hz) samplefreq : float The uniform sampling rate for the signal (in seconds) npole : int Number of poles for Butterworth filter. Positive integer. Returns ------- w : array filtered version of the input signal """ flpf = float(LPF) sf = float(samplefreq) wn = [flpf/(sf/2.0)] b, a = spSignal.butter(NPole, wn, btype='low', output='ba') zi = spSignal.lfilter_zi(b,a) out, zo = spSignal.lfilter(b, a, signal, zi=zi*signal[0]) return(np.array(out))
def compressor(x, thresh=-24, ratio=2, attackrel=0.045, sr=44100.0, dtype=np.float32): """ simple compressor effect, code thanks to Eric Tarr @hackaudio Inputs: x: the input waveform thresh: threshold in dB ratio: compression ratio attackrel: attack & release time in seconds sr: sample rate """ attack = attackrel * sr # convert to samples fc = 1.0 / float(attack) # this is like 1/attack time b, a = scipy_signal.butter(1, fc, analog=False, output='ba') zi = scipy_signal.lfilter_zi(b, a) dB = 20. * np.log10(np.abs(x) + 1e-6) in_env, _ = scipy_signal.lfilter(b, a, dB, zi=zi * dB[0]) # input envelope calculation out_env = np.copy(in_env) # output envelope i = np.where(in_env > thresh) # compress where input env exceeds thresh out_env[i] = thresh + (in_env[i] - thresh) / ratio gain = np.power(10.0, (out_env - in_env) / 20) y = x * gain return y
def filt(self, cutoff_dt, btype='low', order=3, axis=-1, lfilter=False): """ Butterworth filter the time series Inputs: cutoff_dt - cuttoff period [seconds] btype - 'low' or 'high' or 'band' """ if self.isequal == False and self.VERBOSE: print('Warning - time series is unequally spaced.\ Use self.interp to interpolate onto an equal grid') if not btype == 'band': Wn = self.dt / cutoff_dt else: Wn = [self.dt / co for co in cutoff_dt] (b, a) = signal.butter(order, Wn, btype=btype, analog=0, output='ba') # filtfilt only likes to operate along the last axis ytmp = np.swapaxes(self.y, -1, axis) if lfilter: zi = signal.lfilter_zi(b, a) ytmp, _ = signal.lfilter(b, a, ytmp, axis=-1, zi=zi * ytmp[..., 0]) else: ytmp = signal.filtfilt(b, a, ytmp, axis=-1) return np.swapaxes(ytmp, axis, -1)
def __init__(self, Fs, CuttOffFreq, btype, Order): ''' Initialization of LowPassFilterClass Parameters ---------- :param: Fs : float Sampling Frequency of the Signal :param: CuttOffFreq : float Cutoff Frequency of the filter :param: btype : str The type of filter to be applied (lowpass, bandpass, highpass) :param: Order : int the order of the filter Returns ------- None. ''' # the cutoff frequency is normalized using the sampling frequency freqs = np.array(CuttOffFreq / 2) / (0.5 * Fs) # signal.butter function returns the numerator and denominator # polynomials of the IIR filter self.b, self.a = signal.butter( Order, freqs, btype, ) # signal lfilter_zi compute an initial state for the `lfilter` # function that corresponds to the steady state of the step response. self.zi = signal.lfilter_zi( self.b, self.a, )
def __init__(self, step_dict): # set the filter b, a cohefficients self.filter = sig.bessel(int(step_dict['order']), float(step_dict['cutoff'])) # set steady state-like step response initial condition # in order to give the right value it will need to be multiplied by the first value processed self.init = sig.lfilter_zi(self.filter[0], self.filter[1]) self.first = True
def getData(self): t = time.time() bsz = bsz2 = bsz3 = lfilter_zi(self.bsB, self.bsA) while self.running: t += self.period val, val2, val3 = methods.sample() # Filter values - cascade bandstop with bandpass val, bsz = lfilter(self.bsB, self.bsA, lfilter(self.bpB, self.bpA, [val]), zi=bsz) val2, bsz2 = lfilter(self.bsB, self.bsA, lfilter(self.bpB, self.bpA, [val2]), zi=bsz2) val3, bsz3 = lfilter(self.bsB, self.bsA, lfilter(self.bpB, self.bpA, [val3]), zi=bsz3) self.buffer.append(val + 2.5) self.buffer2.append(val2 + 5) self.buffer3.append(val3 + 7.5) # SESSION RECORDING if self.session.recording: self.session.data.append(val) self.y[:] = self.buffer self.y2[:] = self.buffer2 self.y3[:] = self.buffer3 self.curve.setData(self.x, self.y) self.curve2.setData(self.x, self.y2) self.curve3.setData(self.x, self.y3) self.app.processEvents() time.sleep(max(0, t - time.time()))
def butterworthFilter(self, fc, order, btype): ''' Applies a Butterworth filter to the signal. Side effects: the waveform will be resampled to have equally-sampled points. Args: fc (float): cutoff frequency of the filter (cf. input to signal.butter) Returns: New object containing the filtered waveform ''' uniformly_sampled = self.uniformlySample() x, y = uniformly_sampled.absc, uniformly_sampled.ordi dxes = np.diff(x) sampling_rate = 1 / dxes[0] fc = np.array(fc) b, a = signal.butter(order, fc * 2, btype, fs=sampling_rate) # construct the filter # compute initial condition such that the filtered y starts with the same value as y zi = signal.lfilter_zi(b, a) # applies the filter to the ordinate y if it is a low pass filter if btype.startswith('low'): ordi_filtered, _ = signal.lfilter(b, a, y, zi=zi * y[0]) # cheat and debias the signal prior to high pass filtering # this prevents the initial filtered signal to start from zero else: mean_y = np.mean(y) ordi_filtered, _ = signal.lfilter(b, a, y - mean_y, zi=zi * 0) uniformly_sampled.ordi = ordi_filtered return uniformly_sampled
def pre_emphasize(y, fs=16000): # approximate outer/middle hear filter # this is sampling frequency dependent b = [1, -.97] a = 1 zi = sig.lfilter_zi(b, a) return sig.lfilter(b, a, y, zi=zi)[0]
def bandlmt_wnoise(npoints=1000, mu=10, arvmean=1, time=100, freqsupport=(0, 1.5, 1.7, 3, 3.2, 4.5, 4.7, 5), ampsupport=(0.9, 1, 0.2, 0.2, 1, 0.9, 0, 0), numtabs=201, seed=None): if seed is None: seed = np.random.randint(0, int(1e6)) print('Randomly chosen seed is {}.'.format(seed)) if freqsupport[-1] > npoints / time / 2: raise FilterBandwidthExceedsSamplingBandwidthError np.random.seed(seed) freqsupport = list(freqsupport) fs = npoints / time freqsupport[-1] = fs / 2 t = np.linspace(time / npoints, time, npoints) n = np.random.randn(npoints + numtabs) coeffs = scisig.firls(numtabs, freqsupport, ampsupport, nyq=fs / 2) zi = scisig.lfilter_zi(b=coeffs, a=1) z, _ = scisig.lfilter(b=coeffs, a=1, x=n, zi=zi * n[0]) z = z[numtabs:] sig = Signal(t, z) sig *= 1 / np.mean(abs(sig.vals)) * arvmean sig += mu return sig
def lowpass(data, cutout): b, a = signal.butter(5, cutout, 'low') zi = signal.lfilter_zi(b, a) z, _ = signal.lfilter(b, a, data, zi=zi * data[0]) z2, _ = signal.lfilter(b, a, z, zi=zi * z[0]) y = signal.filtfilt(b, a, data) return y
def low_filter(sig_slice): from scipy.signal import lfilter, lfilter_zi, filtfilt, butter b, a = butter(3, 0.5) zi = lfilter_zi(b, a) z, _ = lfilter(b, a, sig_slice, zi=zi*sig_slice[0]) z2, _ = lfilter(b, a, z, zi=zi*z[0]) return(filtfilt(b, a, sig_slice))
def on_filter_echo(self): ceps = cepstrum.real_cepstrum(np.array(self.y_original)) index, result = CepstrumDialog.show_dialog(self, ceps) if result: print(index) b = np.array([1]) a = np.zeros(index + 1) a[0] = 1 a[len(a) - 1] = self.echo_alpha zi = signal.lfilter_zi(b, a) self.y_processed, _ = signal.lfilter(b, a, self.y_original, axis=0, zi=zi * self.y_original[0]) w1, h1 = signal.freqz(b, a) result = FilterResponseDialog.show_dialog(parent=self, w1=w1, h1=h1) if result: self.show_processed_data()
def __init__(self, f0, fs, Q, nb_axis=1): self.nb_axis = nb_axis # f0 = freq to be removed # fs = sampling rate (Hz) # Q = quality factor self.b, self.a = iirnotch(f0, Q, fs) # Get the filter coefficients self.z = [lfilter_zi(self.b, self.a) for _ in range(nb_axis)]
def lowpass_filter(x, RC, step): ''' Wrapper to perform low pass filtering on data x. Step is the length of time between samples in the data series. Assumes RC and step are in the same time units. ''' b, a = butter(1, 1. / (np.pi * RC / step)) return lfilter(b, a, x, zi=lfilter_zi(b, a) * x[0])[0]
def record_eeg_filtered(r_length, freq, channel_i, notch = False, filter_state=None): streams = resolve_byprop('type', 'EEG', timeout=2) inlet = StreamInlet(streams[0], max_chunklen=12) """ Records EEG data from headset Arguments: r_length -- how many seconds of data to record freq -- sample rate channel_i -- channels to keep data from Returns: data -- array of recorded data [sample, channel] """ data, timestamps = inlet.pull_chunk( timeout=r_length + 1, max_samples=int(freq * r_length)) data = np.array(data)[:, channel_i] if notch: if filter_state is None: filter_state = np.tile(lfilter_zi(NOTCH_B, NOTCH_A), (data.shape[1], 1)).T data, filter_state = lfilter(NOTCH_B, NOTCH_A, data, axis=0, zi=filter_state)
def getThreshold(self): nf = pd.DataFrame({'x': self.raw_x, 'y': self.raw_y, 'z': self.raw_z}) #nf.head() magnitude_counter = len(nf.x) # Low Pass filter the data d, c = signal.butter(4, 20, fs=self.sampled_frequency) zi = signal.lfilter_zi(d, c) #LP filter nf['x_filt'], _ = signal.lfilter(d, c, nf.x, zi=zi * nf.x.iloc[0]) nf['y_filt'], _ = signal.lfilter(d, c, nf.y, zi=zi * nf.y.iloc[0]) nf['z_filt'], _ = signal.lfilter(d, c, nf.z, zi=zi * nf.z.iloc[0]) nf['mag'] = np.sqrt( np.square(nf.x_filt) + np.square(nf.y_filt) + np.square(nf.z_filt)) bias_x = nf.x_filt.sum() / magnitude_counter bias_y = nf.y_filt.sum() / magnitude_counter bias_z = nf.z_filt.sum() / magnitude_counter bias_mag = nf.mag.sum() / magnitude_counter nf['x_zero_bias'] = nf.x_filt - bias_x nf['y_zero_bias'] = nf.y_filt - bias_y nf['z_zero_bias'] = nf.z_filt - bias_z nf['mag_zero_bias'] = nf.mag - bias_mag nf['x_sq'] = np.square(nf.x_zero_bias) nf['y_sq'] = np.square(nf.y_zero_bias) nf['z_sq'] = np.square(nf.z_zero_bias) th = np.sqrt((nf[['x_sq', 'y_sq', 'z_sq']].max()).sum()) return th
def filterSignal(sig, fType='lowpass', useFiltFilt=True, fs_Hz=1000.0, freq=100.0, order=1): """Applies lowpass or highpass filter to signal""" # CreateFilter if fType not in ['lowpass', 'highpass']: raise Exception('Invalid filter type: {}'.format(fType)) fNyquist = fs_Hz / 2.0 order = min(order, max(int(fs_Hz / freq) - 1, 1)) # limit order to avoid oscillations b, a = signal.butter(order, freq / fNyquist, fType) if not useFiltFilt: zi = signal.lfilter_zi(b, a) if len(sig.shape) > 1: if useFiltFilt: newSig = np.vstack([signal.filtfilt(b, a, sig[i]) for i in range(sig.shape[0])]) else: newSig = np.vstack([signal.lfilter(b, a, sig[i], zi=zi * sig[i, 0])[0] for i in range(sig.shape[0])]) else: if useFiltFilt: newSig = signal.filtfilt(b, a, sig) else: newSig, _ = signal.lfilter(b, a, sig, zi=zi * sig[0]) return newSig
def get_coeffs(fs, f0, Q, ftype, dBgain=0.0): """ this calculates coeffs and initial conditions for signal.lfilter to filter audio blocks """ b, a = pydsd.biquad(fs, f0, Q, ftype, dBgain) zi = signal.lfilter_zi(b, a) return b, a, zi
def __init__(self, b, a, samp) : """Coefficients (y value) and frequencies (x value) of the desired response function. The coefficients should be real valued. Frequencies should be sorted in ascending order.""" self._b = b self._a = a self._zi = s.lfilter_zi(b,a) self._samp = samp
def SignalFilter_HPFButter(signal, HPF, samplefreq, NPole = 8): flpf = float(HPF) sf = float(samplefreq) wn = [flpf/(sf/2.0)] b, a = spSignal.butter(NPole, wn, btype='high', output='ba') zi = spSignal.lfilter_zi(b,a) out, zo = spSignal.lfilter(b, a, signal, zi=zi*signal[0]) return(numpy.array(out))
def butter_bandpass_filter(data, lowcut, highcut, fs, order=5): nyq = 0.5 * fs low = lowcut / nyq high = highcut / nyq print low , high , "test" , fs b, a = butter(order, high, btype='low', analog=False) zi = lfilter_zi(b, a) y_out, zo = lfilter(b, a, data, zi=zi*data[0]) return y_out
def __init__(self, threshold_freq, order=2, design='cheby1'): """ :param threshold_freq: Threshold frequency to filter out, as a fraction of sampling freq. E.g. 0.1 """ self.b, self.a = \ butter(N=order, Wn=threshold_freq, btype='low') if design == 'butter' else \ cheby1(N=order, rp=0.1, Wn=threshold_freq, btype='low') if design == 'cheby1' else \ bad_value(design) self.filter_state = lfilter_zi(b=self.b, a=self.a)
def iirfilter(N, Wn, rp, rs, btype, ftype, target): b, a = signal.iirfilter(N, Wn, rp, rs, btype, ftype=ftype) if np.any(np.abs(np.roots(a)) > 1): raise ValueError, 'Unstable filter coefficients' zf = signal.lfilter_zi(b, a) while True: y = (yield) y, zf = signal.lfilter(b, a, y, zi=zf) target(y)
def butter_lowpass_filter(self, highcut, order=5): shift_time = int(self.fs*0.5) nyq = 0.5 * self.fs high = highcut / nyq b, a = butter(order, high, btype='low', analog=False) zi = lfilter_zi(b, a) y_out, zo = lfilter(b, a, self.sig_data2, zi=zi*self.sig_data[0]) y2 = [] for i in range(shift_time , int(self.fs * self.t) + shift_time): y2.append(y_out[i]) return y2
def step(self, node): b, a, x = node.getIn('B'), node.getIn('A'), node.getIn('X') if node.state is None: node.state = signal.lfilter_zi(b, a) result = signal.lfilter(b, a, x, zi=node.state) if node.state is None: data = result node.state = signal.lfiltic(b, a, data, x) else: data, node.state = result print(x.shape, x.dtype, data.shape, data.dtype) node.setOut('Y', data)
def __init__(self, blackboard, pattern, sample_rate=256, cutoff_freq=50, cutoff_width = 2): # TODO: Check whether only a single pattern is selected IIRFilter.__init__( self, blackboard, pattern ) # use 10 Hz notch instead self._b, self._a = make_notch( sample_rate, cutoff_freq, cutoff_width ) # create initial zi variable for filter self._zi = lfilter_zi(self._b, self._a) self._pat_extension = '/notch%d' % ( cutoff_freq )
def decimate(q, target): b, a = signal.cheby1(4, 0.05, 0.8/q) if np.any(np.abs(np.roots(a)) > 1): raise ValueError, 'Unstable filter coefficients' zf = signal.lfilter_zi(b, a) y_remainder = np.array([]) while True: y = np.r_[y_remainder, (yield)] remainder = len(y) % q if remainder != 0: y, y_remainder = y[:-remainder], y[-remainder:] else: y_remainder = np.array([]) y, zf = signal.lfilter(b, a, y, zi=zf) target(y[::q])
def __init__(self, width=5, order=3, analog=True): if width < 2.0 or not isinstance(width, int): raise ValueError('width must be an integer greater than 1.') if not isinstance(order, int): raise ValueError('order must be an integer') # find nearest odd integer self.width = int(np.ceil((width + 1) / 2) * 2 - 1) self.order = order # Use lfilter_zi to choose the initial condition of the filter. self._num, self._denom = butter(self.order, 2.0 / self.width) self._zi = lfilter_zi(self._num, self._denom)
def smoothData(xn): xn = cond # Create an order 3 lowpass butterworth filter. b, a = butter(3, 0.05) # Apply the filter to xn. Use lfilter_zi to choose the initial condition # of the filter. zi = lfilter_zi(b, a) z, _ = lfilter(b, a, xn, zi=zi*xn[0]) # Apply the filter again, to have a result filtered at an order # the same as filtfilt. z2, _ = lfilter(b, a, z, zi=zi*z[0]) # Use filtfilt to apply the filter. y = filtfilt(b, a, xn) return y
def buttersworth_smooth(signal, width=11, order=3): """Smooth the data using zero-delay buttersworth filter This code is copied from the scipy cookbook, with sytlistic improvements. http://www.scipy.org/Cookbook/FiltFilt Parameters ---------- signal : np.ndarray, ndim=1 The input signal width : float This acts very similar to the window_len in the window smoother. In the implementation, the frequency of the low-pass filter is taken to be two over this width, so it's like "half the period" of the sinusiod where the filter starts to kick in. order : int, optional The order of the filter. A small odd number is recommended. Higher order filters cutoff more quickly, but have worse numerical properties. Returns ------- output : np.ndarray, ndim=1 The smoothed signal """ if width < 2.0: return signal # first pad the signal on the ends pad = int(np.ceil((width + 1)/2)*2 - 1) # nearest odd integer padded = np.r_[signal[pad - 1: 0: -1], signal, signal[-1: -pad: -1]] #padded = np.r_[[signal[0]]*pad, signal, [signal[-1]]*pad] b, a = butter(order, 2.0 / width) # Apply the filter to the width. Use lfilter_zi to choose the # initial condition of the filter. zi = lfilter_zi(b, a) z, _ = lfilter(b, a, padded, zi=zi*padded[0]) # Apply the filter again, to have a result filtered at an order # the same as filtfilt. z2, _ = lfilter(b, a, z, zi=zi*z[0]) # Use filtfilt to apply the filter. output = filtfilt(b, a, padded) return output[(pad-1): -(pad-1)]
def test_smooth(get_fn): from scipy.signal import lfilter, lfilter_zi, filtfilt, butter pad = 5 order = 3 b, a = butter(order, 2.0 / pad) zi = lfilter_zi(b, a) signal = np.sin(np.arange(100)) padded = np.r_[signal[pad - 1: 0: -1], signal, signal[-1: -pad: -1]] z, _ = lfilter(b, a, padded, zi=zi * padded[0]) z2, _ = lfilter(b, a, z, zi=zi * z[0]) output = filtfilt(b, a, padded) test = np.loadtxt(get_fn('smooth.txt')) eq(output, test)
def update_buffer(data_buffer, new_data, notch=False, filter_state=None): """ Concatenates "new_data" into "data_buffer", and returns an array with the same size as "data_buffer" """ if new_data.ndim == 1: new_data = new_data.reshape(-1, data_buffer.shape[1]) if notch: if filter_state is None: filter_state = np.tile(lfilter_zi(NOTCH_B, NOTCH_A), (data_buffer.shape[1], 1)).T new_data, filter_state = lfilter(NOTCH_B, NOTCH_A, new_data, axis=0, zi=filter_state) new_buffer = np.concatenate((data_buffer, new_data), axis=0) new_buffer = new_buffer[new_data.shape[0]:, :] return new_buffer, filter_state
def __init__(self, blackboard, pattern, sample_rate=256, lowpass = 50 ): """ @param blackboard: blackboard instance which contains the data that must be plotted. @param pattern the pattern corresponding to the data buffer that must be filtered. Only one pattern should be selected. @param sample_rate sample rate of the data signal. Should be a positive numerical value. @param lowpass The filter's cutoff-frequency. Should be a positive numerical value. """ IIRFilter.__init__( self, blackboard, pattern ) self._b, self._a = self._make_lowpass( sample_rate, lowpass ) # create initial zi variable for filter self._zi = lfilter_zi(self._b, self._a) self._pat_extension = '/lpf%d' % ( lowpass )
def sosfilt_zi(sos): """Compute an initial state `zi` for the sosfilt function""" from scipy.signal import lfilter_zi sos = np.asarray(sos) if sos.ndim != 2 or sos.shape[1] != 6: raise ValueError('sos must be shape (n_sections, 6)') n_sections = sos.shape[0] zi = np.empty((n_sections, 2)) scale = 1.0 for section in range(n_sections): b = sos[section, :3] a = sos[section, 3:] zi[section] = scale * lfilter_zi(b, a) # If H(z) = B(z)/A(z) is this section's transfer function, then # b.sum()/a.sum() is H(1), the gain at omega=0. That's the steady # state value of this section's step response. scale *= b.sum() / a.sum() return zi
def filter_1way(b,a,in_memmap,out_memmap): X_nc = in_memmap n_s, n_ch = X_nc.shape Y_mc = out_memmap assert Y_mc.shape == (n_s,n_ch) n_out_chunk = 10000 n_in_chunk = n_out_chunk t_warmup = max(a.size,b.size)*3 pbar = ProgressBar(maxval = n_s).start() z = np.zeros((max(a.size,b.size)-1,n_ch)) for i_ch in xrange(n_ch): _,z[:,i_ch] = lfilter(b,a,X_nc[t_warmup-1::-1,i_ch],zi=lfilter_zi(b,a)) for i_in,i_out in zip(xrange(0,n_s,n_in_chunk),xrange(0,n_s,n_in_chunk)): for i_ch in xrange(n_ch): Y_mc[i_out:i_out+n_out_chunk,i_ch],z[:,i_ch] = lfilter(b,a,X_nc[i_in:i_in+n_in_chunk,i_ch],zi=z[:,i_ch]) pbar.update(i_in) pbar.finish()
def _filtfilt(b, a, x, axis=-1, padtype='odd', padlen=None): """copy of modern SciPy filtfilt without "method" or "irlen" arguments""" from scipy.signal import lfilter_zi, lfilter b = np.atleast_1d(b) a = np.atleast_1d(a) x = np.asarray(x) # method == "pad" edge, ext = _validate_pad(padtype, padlen, x, axis, ntaps=max(len(a), len(b))) # Get the steady state of the filter's step response. zi = lfilter_zi(b, a) # Reshape zi and create x0 so that zi*x0 broadcasts # to the correct value for the 'zi' keyword argument # to lfilter. zi_shape = [1] * x.ndim zi_shape[axis] = zi.size zi = np.reshape(zi, zi_shape) x0 = axis_slice(ext, stop=1, axis=axis) # Forward filter. (y, zf) = lfilter(b, a, ext, axis=axis, zi=zi * x0) # Backward filter. # Create y0 so zi*y0 broadcasts appropriately. y0 = axis_slice(y, start=-1, axis=axis) (y, zf) = lfilter(b, a, axis_reverse(y, axis=axis), axis=axis, zi=zi * y0) # Reverse y. y = axis_reverse(y, axis=axis) if edge > 0: # Slice the actual signal from the extended signal. y = axis_slice(y, start=edge, stop=-edge, axis=axis) return y
def execute(self, oat, detailedresult=False): """ Apply bandpass Butterworth filter to an OAT object """ try: from scipy.signal import butter, lfilter, lfilter_zi except: raise ImportError("scipy.signal module is required for this method") nyq = 0.5 * self.fs low = self.lowcut / nyq high = self.highcut / nyq b, a = butter(self.order, [low, high], btype=self.btype) #y = lfilter(b, a, oat.ts['data']) zi = lfilter_zi(b, a) y, zo = lfilter(b, a, oat.ts['data'], zi=zi * oat.ts['data'][0]) #copy oat and return the modified copy temp_oat = oat.copy() temp_oat.ts['data'] = y self.result['type'] = "sensor" self.result['data'] = temp_oat return self.returnResult(detailedresult)
def _filter_init(b, a, alpha=1.): """Get an initial filter state that corresponds to the steady-state of the step response. Parameters ---------- b : array Numerator coefficients. a : array Denominator coefficients. alpha : float, optional Scaling factor. Returns ------- zi : array Initial filter state. """ zi = alpha * ss.lfilter_zi(b, a) return zi
def downsample_1way(in_memmap,out_memmap,ratio=16): b,a = butter(BUTTER_ORD,1/(2*ratio),'low') X_nc = in_memmap n_s, n_ch = X_nc.shape n_s2 = n_s//ratio Y_mc = out_memmap assert Y_mc.shape == (n_s2,n_ch) n_out_chunk = 10000 n_in_chunk = n_out_chunk*ratio t_warmup = max(a.size,b.size)*3 pbar = ProgressBar(maxval = n_s).start() z = np.zeros((BUTTER_ORD,n_ch)) for i_ch in xrange(n_ch): _,z[:,i_ch] = lfilter(b,a,X_nc[t_warmup-1::-1,i_ch],zi=lfilter_zi(b,a)) for (i_in,i_out) in zip(xrange(0,n_s,n_in_chunk),xrange(0,n_s2,n_out_chunk)): for i_ch in xrange(n_ch): Low_nc,z[:,i_ch] = lfilter(b,a,X_nc[i_in:i_in+n_in_chunk,i_ch],zi=z[:,i_ch]) Y_mc[i_out:i_out+n_out_chunk,i_ch] = Low_nc[::ratio] pbar.update(i_in) pbar.finish()
def process(self, data): if self.zi is None: # initial pass, get ICs from filter coefficients zi = signal.lfilter_zi(self.b, self.a) self.zi = np.tile(zi, (data.shape[1], 1)).T else: # subsequent passes get ICs from previous input/output num_ch = data.shape[1] K = max(len(self.a)-1, len(self.b)-1) self.zi = np.zeros((K, num_ch)) # unfortunately we have to get zi channel by channel for c in range(data.shape[1]): self.zi[:, c] = signal.lfiltic( self.b, self.a, self.y_prev[-(self.overlap+1)::-1, c], self.x_prev[-(self.overlap+1)::-1, c]) out, zf = signal.lfilter( self.b, self.a, data, axis=0, zi=self.zi) self.x_prev = data self.y_prev = out return out
def test_basic(self): a = np.array([1.0, -1.0, 0.5]) b = np.array([1.0, 0.0, 2.0]) zi_expected = np.array([5.0, -1.0]) zi = lfilter_zi(b, a) assert_array_almost_equal(zi, zi_expected)
def test_tide_filter(): # import statsmodels.api as sa import wafo.spectrum.models as sm sd = 10 Sj = sm.Jonswap(Hm0=4.* sd) S = Sj.tospecdata() q = (0.1 * sd) ** 2 # variance of process noise s the car operates r = (100 * sd) ** 2 # variance of measurement error b = 0 # no system input u = 0 # no system input from scipy.signal import butter, lfilter, filtfilt, lfilter_zi freq_tide = 1. / (12 * 60 * 60) freq_wave = 1. / 10 freq_filt = freq_wave / 10 dt = 1. freq = 1. / dt fn = (freq / 2) P = 10* np.diag([1, 0.01]) R = r H = np.atleast_2d([1, 0]) F = np.atleast_2d([[0, 1], [0, 0]]) A, Q = lti_disc(F, L=None, Q=np.diag([0, q]), dt=dt) t = np.arange(0, 60 * 12, 1. / freq) w = 2 * np.pi * freq # 1 Hz tide = 100 * np.sin(freq_tide * w * t + 2 * np.pi / 4) + 100 y = tide + S.sim(len(t), dt=1. / freq)[:, 1].ravel() # lowess = sa.nonparametric.lowess # y2 = lowess(y, t, frac=0.5)[:,1] filt = Kalman(R=R, x=np.array([[tide[0]], [0]]), P=P, A=A, Q=Q, H=H, B=b) filt2 = Kalman(R=R, x=np.array([[tide[0]], [0]]), P=P, A=A, Q=Q, H=H, B=b) #y = tide + 0.5 * np.sin(freq_wave * w * t) # Butterworth filter b, a = butter(9, (freq_filt / fn), btype='low') #y2 = [lowess(y[max(i-60,0):i + 1], t[max(i-60,0):i + 1], frac=.3)[-1,1] for i in range(len(y))] #y2 = [lfilter(b, a, y[:i + 1])[i] for i in range(len(y))] #y3 = filtfilt(b, a, y[:16]).tolist() + [filtfilt(b, a, y[:i + 1])[i] for i in range(16, len(y))] #y0 = medfilt(y, 41) zi = lfilter_zi(b, a) #y2 = lfilter(b, a, y)#, zi=y[0]*zi) # standard filter y3 = filtfilt(b, a, y) # filter with phase shift correction y4 =[] y5 = [] for i, j in enumerate(y): tmp = filt(j, u=u).ravel() tmp = filt2(tmp[0], u=u).ravel() # if i==0: # print(filt.x) # print(filt2.x) y4.append(tmp[0]) y5.append(tmp[1]) y0 = medfilt(y4, 41) print(filt.P) # plot import matplotlib.pyplot as plt plt.plot(t, y, 'r.-', linewidth=2, label='raw data') #plt.plot(t, y2, 'b.-', linewidth=2, label='lowess @ %g Hz' % freq_filt) #plt.plot(t, y2, 'b.-', linewidth=2, label='filter @ %g Hz' % freq_filt) plt.plot(t, y3, 'g.-', linewidth=2, label='filtfilt @ %g Hz' % freq_filt) plt.plot(t, y4, 'k.-', linewidth=2, label='kalman') #plt.plot(t, y5, 'k.', linewidth=2, label='kalman2') plt.plot(t, tide, 'y-', linewidth=2, label='True tide') plt.legend(frameon=False, fontsize=14) plt.xlabel("Time [s]") plt.ylabel("Amplitude") plt.show('hold')