def driving_signals_3d(delay, weight, sos, phaseshift, signal): """Get 3-dimensional NFC-HOA driving signals. Parameters ---------- delay : float Overall delay in seconds. weight : float Overall weight. sos : list of array_like Second-order section filters :func:`scipy.signal.sosfilt`. phaseshift : (N,) array_like Phase shift in radians. signal : (L,) array_like + float Excitation signal consisting of (mono) audio data and a sampling rate (in Hertz). A `DelayedSignal` object can also be used. Returns ------- `DelayedSignal` A tuple containing the delayed signals (in a `numpy.ndarray` with shape ``(L, N)``), followed by the sampling rate (in Hertz) and a (possibly negative) time offset (in seconds). """ data, fs, t_offset = _util.as_delayed_signal(signal) N = len(phaseshift) out = _np.tile(_np.expand_dims(_sig.sosfilt(sos[0], data), 1), (1, N)) for m in range(1, len(sos)): modal_response = _sig.sosfilt(sos[m], data)[:, _np.newaxis] out += (2 * m + 1) * modal_response * _legendre(m, _np.cos(phaseshift)) return _util.DelayedSignal(weight / 4 / _np.pi * out, fs, t_offset + delay)
def highpass(data, freq, df, corners=4, zerophase=False): """ Butterworth-Highpass Filter. Filter data removing data below certain frequency ``freq`` using ``corners`` corners. The filter uses :func:`scipy.signal.iirfilter` (for design) and :func:`scipy.signal.sosfilt` (for applying the filter). :type data: numpy.ndarray :param data: Data to filter. :param freq: Filter corner frequency. :param df: Sampling rate in Hz. :param corners: Filter corners / order. :param zerophase: If True, apply filter once forwards and once backwards. This results in twice the number of corners but zero phase shift in the resulting filtered trace. :return: Filtered data. """ fe = 0.5 * df f = freq / fe # raise for some bad scenarios if f > 1: msg = "Selected corner frequency is above Nyquist." raise ValueError(msg) z, p, k = iirfilter(corners, f, btype='highpass', ftype='butter', output='zpk') sos = zpk2sos(z, p, k) if zerophase: firstpass = sosfilt(sos, data) return sosfilt(sos, firstpass[::-1])[::-1] else: return sosfilt(sos, data)
def filter_all(self,type,overwrite=False,zerophase=True,outfile=None,**kwargs): if type == 'bandpass': sos = filter.bandpass(df=self.stats['Fs'],**kwargs) elif type == 'lowpass': sos = filter.lowpass(df=self.stats['Fs'],**kwargs) elif type == 'highpass': sos = filter.highpass(df=self.stats['Fs'],**kwargs) else: msg = 'Filter %s is not implemented, implemented filters: bandpass, highpass,lowpass' %type raise ValueError(msg) if not overwrite: # Create a new hdf5 file of the same shape newfile = self.copy_setup(newfile=outfile) else: # Call self.file newfile newfile = self#.file with click.progressbar(range(self.stats['ntraces']),label='Filtering..' ) as ind: for i in ind: # Filter each trace if zerophase: firstpass = sosfilt(sos, self.data[i,:]) # Read in any case from self.data newfile.data[i,:] = sosfilt(sos,firstpass[::-1])[::-1] # then assign to newfile, which might be self.file else: newfile.data[i,:] = sosfilt(sos,self.data[i,:]) # flush? if not overwrite: print('Processed traces written to file %s, file closed, \ reopen to read / modify.' %newfile.file.filename) newfile.file.close()
def highpass(rawData, samplFreq, highpassCutOff): #This function high passes the data with sampling frequency samplFreq with a highpass # cut off of highpassCutOff # # Usage: [highPassedData] = highpass(rawData, samplFreq, highpassCutOff) # # rawData : raw time series Data # samplFreq: sampling Frequency of Data # highpassCutOff: The high pass frequency cut off. # numberOfChannels = len(rawData) dataLength = len(rawData[0]) duration = dataLength/samplFreq halfDataLength = dataLength/2 + 1 for channelNumber in xrange(numberOfChannels): if(len(rawData[channelNumber]) != dataLength): sys.exit('Data length not consistent\n') nyquistFrequency = samplFreq/2.0 lpefOrder = 0 if(highpassCutOff>0): hpfOrder = 12 hpfZeros, hpfPoles, hpfGain = sig.butter(hpfOrder, highpassCutOff/nyquistFrequency, btype = 'highpass', output = 'zpk' ) hpfSOS = sig.zpk2sos(hpfZeros, hpfPoles, hpfGain) #magnitude response of high pass filter minimumFrequencyStep = 1.0/duration frequencies = np.arange(0, nyquistFrequency, minimumFrequencyStep) hpfArgument = np.power((frequencies / highpassCutOff), 2*hpfOrder) hpfResponse = hpfArgument/(1 + hpfArgument) highPassCutOffIndex = np.ceil(highpassCutOff/minimumFrequencyStep) highPassedData = [] for channelNumber in xrange(numberOfChannels): if(highpassCutOff>0): x = sig.sosfilt(hpfSOS, rawData[channelNumber]) x = np.flipud(x) x = sig.sosfilt(hpfSOS, x) x = np.flipud(x) else: x = rawData[channelNumber] x[0:lpefOrder] = np.zeros(lpefOrder) x[dataLength - lpefOrder:dataLength-1] = np.zeros(lpefOrder) highPassedData.append(x) highPassedData = np.asarray(highPassedData) return highPassedData
def _sosfiltfilt(sos, x, axis=-1, padtype='odd', padlen=None, method='pad', irlen=None): """Filtfilt version using Second Order sections. Code is taken from scipy.signal.filtfilt and adapted to make it work with SOS. Note that broadcasting does not work. """ from scipy.signal import sosfilt_zi from scipy.signal._arraytools import odd_ext, axis_slice, axis_reverse x = np.asarray(x) if padlen is None: edge = 0 else: edge = padlen # x's 'axis' dimension must be bigger than edge. if x.shape[axis] <= edge: raise ValueError("The length of the input vector x must be at least " "padlen, which is %d." % edge) if padtype is not None and edge > 0: # Make an extension of length `edge` at each # end of the input array. if padtype == 'even': ext = even_ext(x, edge, axis=axis) elif padtype == 'odd': ext = odd_ext(x, edge, axis=axis) else: ext = const_ext(x, edge, axis=axis) else: ext = x # Get the steady state of the filter's step response. zi = sosfilt_zi(sos) # 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) = sosfilt(sos, 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) = sosfilt(sos, 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 lowpass_cheby_2(data, freq, df, maxorder=12, ba=False, freq_passband=False): """ Cheby2-Lowpass Filter Filter data by passing data only below a certain frequency. The main purpose of this cheby2 filter is downsampling. #318 shows some plots of this filter design itself. This method will iteratively design a filter, whose pass band frequency is determined dynamically, such that the values above the stop band frequency are lower than -96dB. :type data: numpy.ndarray :param data: Data to filter. :param freq: The frequency above which signals are attenuated with 95 dB :param df: Sampling rate in Hz. :param maxorder: Maximal order of the designed cheby2 filter :param ba: If True return only the filter coefficients (b, a) instead of filtering :param freq_passband: If True return additionally to the filtered data, the iteratively determined pass band frequency :return: Filtered data. """ nyquist = df * 0.5 # rp - maximum ripple of passband, rs - attenuation of stopband rp, rs, order = 1, 96, 1e99 ws = freq / nyquist # stop band frequency wp = ws # pass band frequency # raise for some bad scenarios if ws > 1: ws = 1.0 msg = "Selected corner frequency is above Nyquist. " + \ "Setting Nyquist as high corner." warnings.warn(msg) while True: if order <= maxorder: break wp = wp * 0.99 order, wn = cheb2ord(wp, ws, rp, rs, analog=0) if ba: return cheby2(order, rs, wn, btype='low', analog=0, output='ba') z, p, k = cheby2(order, rs, wn, btype='low', analog=0, output='zpk') sos = zpk2sos(z, p, k) if freq_passband: return sosfilt(sos, data), wp * nyquist return sosfilt(sos, data)
def filter(self, freq, order=4, btype='lowpass'): ''' Bandpass filter the data using a butterworth filter Args: * freq: A scalar or length-2 sequence giving the critical frequencies (in Hz) * order: Order of the filter. * btype: {'lowpass', 'highpass', 'bandpass', 'bandstop'}, optional (default is 'lowpass') ''' # Check that headers are correct assert not self.isempty(), 'Some sac attributes are missing (e.g., npts, delta, depvar)' # Filter design if type(freq) is list: freq = np.array(freq) Wn = freq * 2. * self.delta # Normalizing frequencies sos = signal.butter(order, Wn, btype, output='sos') # Filter waveform depvar = signal.sosfilt(sos, self.depvar) self.depvar = depvar.astype('float32') # All done return
def dn(self,x,M_change = 12): """ Downsample and filter the signal """ y = signal.sosfilt(self.sos,x) y = ssd.downsample(y,M_change) return y
def decimate(self,decimation_factor,outfile,taper_width=0.005): """ Decimate the wavefield and save to a new file """ fs_old = self.stats['Fs'] freq = self.stats['Fs'] * 0.4 / float(decimation_factor) # Get filter coeff sos = filter.cheby2_lowpass(fs_old,freq) # figure out new length temp_trace = integer_decimation(self.data[0,:], decimation_factor) n = len(temp_trace) # Get taper # The default taper is very narrow, because it is expected that the traces are very long. taper = cosine_taper(self.stats['nt'],p=taper_width) # Need a new file, because the length changes. with self.copy_setup(newfile=outfile,nt=n) as newfile: for i in range(self.stats['ntraces']): temp_trace = sosfilt(sos,taper*self.data[i,:]) newfile.data[i,:] = integer_decimation(temp_trace, decimation_factor) newfile.stats['Fs'] = fs_old / float(decimation_factor)
def up(self,x,L_change = 12): """ Upsample and filter the signal """ y = L_change*ssd.upsample(x,L_change) y = signal.sosfilt(self.sos,y) return y
def plot_filter(h, title, freq, gain, show=True): if h.ndim == 2: # second-order sections sos = h n = mne.filter.estimate_ringing_samples(sos) h = np.zeros(n) h[0] = 1 h = signal.sosfilt(sos, h) H = np.ones(512, np.complex128) for section in sos: f, this_H = signal.freqz(section[:3], section[3:]) H *= this_H else: f, H = signal.freqz(h) fig, axs = plt.subplots(2) t = np.arange(len(h)) / sfreq axs[0].plot(t, h, color=blue) axs[0].set(xlim=t[[0, -1]], xlabel='Time (sec)', ylabel='Amplitude h(n)', title=title) box_off(axs[0]) f *= sfreq / (2 * np.pi) axs[1].semilogx(f, 10 * np.log10((H * H.conj()).real), color=blue, linewidth=2, zorder=4) plot_ideal(freq, gain, axs[1]) mne.viz.tight_layout() if show: plt.show()
def lfilter(self, signal): """ Filter signal with filterbank. .. note:: This function uses :func:`scipy.signal.lfilter`. """ return ( sosfilt(sos, signal) for sos in self.filters )
def downsampling(self,cfg,zerophase_antialias): # Find a frequency dependent taper width Fs0 = self.stream[0].stats.sampling_rate npts = self.stream[0].stats.npts taper_perc = 100. * Fs0 / cfg.Fs_new[-1] / npts print(npts) print(taper_perc) # Apply antialias filter for trace in self.stream: trace.taper(type='cosine',max_percentage=taper_perc) if zerophase_antialias: firstpass = sosfilt(self.anti_alias,trace.data) trace.data = sosfilt(self.anti_alias,firstpass[::-1])[::-1] else: trace.data = sosfilt(self.anti_alias,trace.data) # Decimate if possible, otherwise interpolate for Fs in cfg.Fs_new: Fs_old = self.stream[0].stats.sampling_rate dec = ( Fs_old / Fs) if dec % 1.0 == 0: self.stream.decimate(int(dec), no_filter=True, strict_length=False) if cfg.verbose: print('* decimated traces to %g Hz' %Fs, file=self.ofid) else: try: self.stream.interpolate(sampling_rate = Fs, method='lanczos') print('* interpolated traces to %g Hz' %Fs, file=self.ofid) except: self.stream.interpolate(sampling_rate = Fs) print('* interpolated trace to %g Hz' %Fs, file=self.ofid)
def bandpass(data, freqmin, freqmax, df, corners=4, zerophase=False): """ Butterworth-Bandpass Filter. Filter data from ``freqmin`` to ``freqmax`` using ``corners`` corners. The filter uses :func:`scipy.signal.iirfilter` (for design) and :func:`scipy.signal.sosfilt` (for applying the filter). :type data: numpy.ndarray :param data: Data to filter. :param freqmin: Pass band low corner frequency. :param freqmax: Pass band high corner frequency. :param df: Sampling rate in Hz. :param corners: Filter corners / order. :param zerophase: If True, apply filter once forwards and once backwards. This results in twice the filter order but zero phase shift in the resulting filtered trace. :return: Filtered data. """ fe = 0.5 * df low = freqmin / fe high = freqmax / fe # raise for some bad scenarios if high - 1.0 > -1e-6: msg = ("Selected high corner frequency ({}) of bandpass is at or " "above Nyquist ({}). Applying a high-pass instead.").format( freqmax, fe) warnings.warn(msg) return highpass(data, freq=freqmin, df=df, corners=corners, zerophase=zerophase) if low > 1: msg = "Selected low corner frequency is above Nyquist." raise ValueError(msg) z, p, k = iirfilter(corners, [low, high], btype='band', ftype='butter', output='zpk') sos = zpk2sos(z, p, k) if zerophase: firstpass = sosfilt(sos, data) return sosfilt(sos, firstpass[::-1])[::-1] else: return sosfilt(sos, data)
def band_pass_filter(data, minfreq = 0.5, maxfreq = 0.8, df = 4, corners = 4): fe = 0.5 * df low = minfreq / fe high = maxfreq / fe z, p, k = sig.iirfilter(corners, [low, high], btype='band', ftype='butter', output='zpk') sos = sig.zpk2sos(z, p, k) return sig.sosfilt(sos, data)
def ITU_R_468_weight(signal, fs): """ Return the given signal after passing through an 468-weighting filter signal : array_like Input signal fs : float Sampling frequency """ sos = ITU_R_468_weighting(fs, output='sos') return sosfilt(sos, signal)
def bandstop(data, freqmin, freqmax, df, corners=4, zerophase=False): """ Butterworth-Bandstop Filter. Filter data removing data between frequencies ``freqmin`` and ``freqmax`` using ``corners`` corners. The filter uses :func:`scipy.signal.iirfilter` (for design) and :func:`scipy.signal.sosfilt` (for applying the filter). :type data: numpy.ndarray :param data: Data to filter. :param freqmin: Stop band low corner frequency. :param freqmax: Stop band high corner frequency. :param df: Sampling rate in Hz. :param corners: Filter corners / order. :param zerophase: If True, apply filter once forwards and once backwards. This results in twice the number of corners but zero phase shift in the resulting filtered trace. :return: Filtered data. """ fe = 0.5 * df low = freqmin / fe high = freqmax / fe # raise for some bad scenarios if high > 1: high = 1.0 msg = "Selected high corner frequency is above Nyquist. " + \ "Setting Nyquist as high corner." warnings.warn(msg) if low > 1: msg = "Selected low corner frequency is above Nyquist." raise ValueError(msg) z, p, k = iirfilter(corners, [low, high], btype='bandstop', ftype='butter', output='zpk') sos = zpk2sos(z, p, k) if zerophase: firstpass = sosfilt(sos, data) return sosfilt(sos, firstpass[::-1])[::-1] else: return sosfilt(sos, data)
def filter_fn(seg): assert seg.channels == 1 nyq = 0.5 * seg.frame_rate try: freqs = [f / nyq for f in freq] except TypeError: freqs = freq / nyq sos = butter(order, freqs, btype=type, output='sos') y = sosfilt(sos, seg.get_array_of_samples()) return seg._spawn(y.astype(seg.array_type))
def calc_response(self, y_fx = None): """ (Re-)calculate filter response `self.y` from either stimulus `self.x` (float mode) or copy fixpoint response. Split response into imag. and real components `self.y_i` and `self.y_r` and set the flag `self.cmplx`. """ if self.fx_sim: # use fixpoint simulation results instead of floating results if y_fx is not None: self.y = np.array(y_fx) qstyle_widget(self.ui.but_run, "normal") else: self.y = None else: # calculate response self.y_r[n] and self.y_i[n] (for complex case) ===== self.bb = np.asarray(fb.fil[0]['ba'][0]) self.aa = np.asarray(fb.fil[0]['ba'][1]) if min(len(self.aa), len(self.bb)) < 2: logger.error('No proper filter coefficients: len(a), len(b) < 2 !') return logger.info("Coefficient area = {0}".format(np.sum(np.abs(self.bb)))) sos = np.asarray(fb.fil[0]['sos']) antiCausal = 'zpkA' in fb.fil[0] causal = not (antiCausal) if len(sos) > 0 and causal: # has second order sections and is causal y = sig.sosfilt(sos, self.x) elif antiCausal: y = sig.filtfilt(self.bb, self.aa, self.x, -1, None) else: # no second order sections or antiCausals for current filter y = sig.lfilter(self.bb, self.aa, self.x) if self.ui.stim == "StepErr": dc = sig.freqz(self.bb, self.aa, [0]) # DC response of the system y = y - abs(dc[1]) # subtract DC (final) value from response self.y = np.real_if_close(y, tol = 1e3) # tol specified in multiples of machine eps self.needs_redraw[0] = True self.needs_redraw[1] = True # Calculate imag. and real components from response self.cmplx = np.any(np.iscomplex(self.y)) if self.cmplx: self.y_i = self.y.imag self.y_r = self.y.real else: self.y_r = self.y self.y_i = None
def _sosfiltfilt(sos, x, axis=-1, padtype='odd', padlen=None): """Do SciPy sosfiltfilt.""" from scipy.signal import sosfilt, sosfilt_zi sos, n_sections = _validate_sos(sos) # `method` is "pad"... ntaps = 2 * n_sections + 1 ntaps -= min((sos[:, 2] == 0).sum(), (sos[:, 5] == 0).sum()) edge, ext = _validate_pad(padtype, padlen, x, axis, ntaps=ntaps) # These steps follow the same form as filtfilt with modifications zi = sosfilt_zi(sos) # shape (n_sections, 2) --> (n_sections, ..., 2, ...) zi_shape = [1] * x.ndim zi_shape[axis] = 2 zi.shape = [n_sections] + zi_shape x_0 = axis_slice(ext, stop=1, axis=axis) (y, zf) = sosfilt(sos, ext, axis=axis, zi=zi * x_0) y_0 = axis_slice(y, start=-1, axis=axis) (y, zf) = sosfilt(sos, axis_reverse(y, axis=axis), axis=axis, zi=zi * y_0) y = axis_reverse(y, axis=axis) if edge > 0: y = axis_slice(y, start=edge, stop=-edge, axis=axis) return y
def _make(self, subject, recording): raw = self.source.load(subject, recording, preload=True) self.log.info("Raw %s: filtering for %s/%s...", self.name, subject, recording) # filter data picks = mne.pick_types(raw.info, eeg=True, ref_meg=True) sos = self._sos(raw.info['sfreq']) for i in picks: raw._data[i] = signal.sosfilt(sos, raw._data[i]) # update info low, high = self.args[1], self.args[2] if high and raw.info['lowpass'] > high: raw.info['lowpass'] = float(high) if low and raw.info['highpass'] < low: raw.info['highpass'] = float(low) return raw
def A_weight(signal, fs): """ Return the given signal after passing through a digital A-weighting filter signal : array_like Input signal, with time as dimension fs : float Sampling frequency """ # TODO: Upsample signal high enough that filter response meets Type 0 # limits. A passes if fs >= 260 kHz, but not at typical audio sample # rates. So upsample 48 kHz by 6 times to get an accurate measurement? # TODO: Also this could just be a measurement function that doesn't # save the whole filtered waveform. sos = A_weighting(fs, output='sos') return sosfilt(sos, signal)
def highpass(signal, cutoff, fs, order=4, zero_phase=False): """Filter signal with low-pass filter. :param signal: Signal :param fs: Sample frequency :param cutoff: Cut-off frequency :param order: Filter order :param zero_phase: Prevent phase error by filtering in both directions (filtfilt) A Butterworth filter is used. Filtering is done with second-order sections. .. seealso:: :func:`scipy.signal.butter`. """ sos = butter(order, cutoff/(fs/2.0), btype='high', output='sos') if zero_phase: return _sosfiltfilt(sos, signal) else: return sosfilt(sos, signal)
def octavepass(signal, center, fs, fraction, order=8, zero_phase=True): """Filter signal with fractional-octave bandpass filter. :param signal: Signal :param center: Centerfrequency of fractional-octave band. :param fs: Sample frequency :param fraction: Fraction of fractional-octave band. :param order: Filter order :param zero_phase: Prevent phase error by filtering in both directions (filtfilt) A Butterworth filter is used. Filtering is done with second-order sections. .. seealso:: :func:`octave_filter` """ sos = octave_filter(center, fs, fraction, order) if zero_phase: return _sosfiltfilt(sos, signal) else: return sosfilt(sos, signal)
def bandpass(signal, lowcut, highcut, fs, order=8, zero_phase=False): """Filter signal with band-pass filter. :param signal: Signal :param lowcut: Lower cut-off frequency :param highcut: Upper cut-off frequency :param fs: Sample frequency :param order: Filter order :param zero_phase: Prevent phase error by filtering in both directions (filtfilt) A Butterworth filter is used. Filtering is done with second-order sections. .. seealso:: :func:`bandpass_filter` for the filter that is used. """ sos = bandpass_filter(lowcut, highcut, fs, order, output='sos') if zero_phase: return _sosfiltfilt(sos, signal) else: return sosfilt(sos, signal)
def _detect(x, fs, fmin, fmax, psd_mode): """Detects signal stimulus.""" x = x.astype(np.float64) if psd_mode: # Estimate power spectral density. f, pxx = sig.welch(x, fs, nperseg=256, noverlap=(256//2)) # Create mask. mask = (f > fmin) & (f < fmax) # Calculate stimulus. y = np.mean(pxx[mask]) else: # Design digital Butterworth filter in sos format. order, freq_nqst = 6, fs//2 sos = sig.butter(order, [fmin/freq_nqst, fmax/freq_nqst], btype='bandpass', analog=False, output='sos') # Filter signal. xf = sig.sosfilt(sos, x, axis=-1) # Calculate stimulus. y = np.mean(xf) return y
t = np.arange(Lh) / fs s2z = matchedz_zpk # s2z = bilinear_zpk # Analog filter H = np.zeros(num_w, dtype='complex') num_biquad, Gb, G = shelving_filter_parameters( biquad_per_octave=biquad_per_octave, slope=slope, BWd=BWd) sos_sdomain = low_shelving_2nd_cascade(w0, Gb, num_biquad, biquad_per_octave) zs, ps, ks = sos2zpk(sos_sdomain) # Digital filter zpk = s2z(zs * 2 * np.pi * fc, ps * 2 * np.pi * fc, ks, fs=fs) sos_zdomain = zpk2sos(*zpk) H = sosfreqz(sos_zdomain, worN=f, fs=fs)[1] h = sosfilt(sos_zdomain, xin) # Plots flim = fmin, fmax fticks = fc * 2.**np.arange(-8, 4, 2) fticklabels = ['7.8', '31.3', '125', '500', '2k', '8k'] fticks = 1000 * 2.**np.arange(-6, 6, 2) fticklabels = ['15.6', '62.5', '250', '1k', '4k', '16k'] kw = dict(c='C0', lw=2, alpha=1) fig, ax = plt.subplots(figsize=(13, 3), ncols=3, gridspec_kw={'wspace': 0.25}) # frequency response ax[0].semilogx(f, db(H), **kw) ax[1].semilogx(f, np.angle(H, deg=True), **kw)
def plot_filter(h, sfreq, freq=None, gain=None, title=None, color='#1f77b4', flim=None, fscale='log', alim=(-60, 10), show=True): """Plot properties of a filter. Parameters ---------- h : dict or ndarray An IIR dict or 1D ndarray of coefficients (for FIR filter). sfreq : float Sample rate of the data (Hz). freq : array-like or None The ideal response frequencies to plot (must be in ascending order). If None (default), do not plot the ideal response. gain : array-like or None The ideal response gains to plot. If None (default), do not plot the ideal response. title : str | None The title to use. If None (default), deteremine the title based on the type of the system. color : color object The color to use (default '#1f77b4'). flim : tuple or None If not None, the x-axis frequency limits (Hz) to use. If None, freq will be used. If None (default) and freq is None, ``(0.1, sfreq / 2.)`` will be used. fscale : str Frequency scaling to use, can be "log" (default) or "linear". alim : tuple The y-axis amplitude limits (dB) to use (default: (-60, 10)). show : bool Show figure if True (default). Returns ------- fig : matplotlib.figure.Figure The figure containing the plots. See Also -------- mne.filter.create_filter plot_ideal_filter Notes ----- .. versionadded:: 0.14 """ from scipy.signal import freqz, group_delay import matplotlib.pyplot as plt sfreq = float(sfreq) _check_fscale(fscale) flim = _get_flim(flim, fscale, freq, sfreq) if fscale == 'log': omega = np.logspace(np.log10(flim[0]), np.log10(flim[1]), 1000) else: omega = np.linspace(flim[0], flim[1], 1000) omega /= sfreq / (2 * np.pi) if isinstance(h, dict): # IIR h.ndim == 2: # second-order sections if 'sos' in h: from scipy.signal import sosfilt h = h['sos'] H = np.ones(len(omega), np.complex128) gd = np.zeros(len(omega)) for section in h: this_H = freqz(section[:3], section[3:], omega)[1] H *= this_H with warnings.catch_warnings(record=True): # singular GD gd += group_delay((section[:3], section[3:]), omega)[1] n = estimate_ringing_samples(h) delta = np.zeros(n) delta[0] = 1 h = sosfilt(h, delta) else: from scipy.signal import lfilter n = estimate_ringing_samples((h['b'], h['a'])) delta = np.zeros(n) delta[0] = 1 H = freqz(h['b'], h['a'], omega)[1] with warnings.catch_warnings(record=True): # singular GD gd = group_delay((h['b'], h['a']), omega)[1] h = lfilter(h['b'], h['a'], delta) title = 'SOS (IIR) filter' if title is None else title else: H = freqz(h, worN=omega)[1] with warnings.catch_warnings(record=True): # singular GD gd = group_delay((h, [1.]), omega)[1] title = 'FIR filter' if title is None else title gd /= sfreq fig, axes = plt.subplots(3) # eventually axes could be a parameter t = np.arange(len(h)) / sfreq f = omega * sfreq / (2 * np.pi) axes[0].plot(t, h, color=color) axes[0].set(xlim=t[[0, -1]], xlabel='Time (sec)', ylabel='Amplitude h(n)', title=title) mag = 10 * np.log10(np.maximum((H * H.conj()).real, 1e-20)) axes[1].plot(f, mag, color=color, linewidth=2, zorder=4) if freq is not None and gain is not None: plot_ideal_filter(freq, gain, axes[1], fscale=fscale, title=None, show=False) axes[1].set(ylabel='Magnitude (dB)', xlabel='', xscale=fscale) sl = slice(0 if fscale == 'linear' else 1, None, None) axes[2].plot(f[sl], gd[sl], color=color, linewidth=2, zorder=4) axes[2].set(xlim=flim, ylabel='Group delay (sec)', xlabel='Frequency (Hz)', xscale=fscale) xticks, xticklabels = _filter_ticks(flim, fscale) dlim = [0, 1.05 * gd[1:].max()] for ax, ylim, ylabel in zip(axes[1:], (alim, dlim), ('Amplitude (dB)', 'Delay (sec)')): if xticks is not None: ax.set(xticks=xticks) ax.set(xticklabels=xticklabels) ax.set(xlim=flim, ylim=ylim, xlabel='Frequency (Hz)', ylabel=ylabel) adjust_axes(axes) tight_layout() plt_show(show) return fig
def filter_ndvar(self, ndvar): axis = ndvar.get_axis('time') sos = self._sos(1. / ndvar.time.tstep) x = signal.sosfilt(sos, ndvar.x, axis) return NDVar(x, ndvar.dims, ndvar.info.copy(), ndvar.name)
8 + ntimesteps * size_of_float + 12 ) #for nt in range(ntimesteps): # values[nt] = np.fromfile(f_in,dtype=dtype_output,count=1) values = np.fromfile(f_in, dtype=dtype_output, count=ntimesteps) tr = Trace(data=values) # Filter and downsample # Since the same filter will be applied to all synthetics consistently, non-zero-phase should be okay # ToDo: Think about whether zerophase would be better # taper first #ToDo: Discuss with Andreas whether this tapering makes sense! tr.taper(type='cosine', max_percentage=0.001) tr.data = sosfilt(sos, tr.data) tr.stats.sampling_rate = fs_old tr.interpolate(fs_new) # Differentiate if output_quantity == 'VEL' or output_quantity == 'ACC': tr.differentiate() if output_quantity == 'ACC': tr.differentiate() # Remove the extra time that specfem added tr.trim(starttime=tr.stats.starttime + offset_seconds) # Set data type tr.data = tr.data.astype(dtype_output)
def filter20_to_20k(x, fs): nyq = 0.5 * fs sos = sig.butter(5, [20.0 / nyq, 20000.0 / nyq], btype="band", output="sos") return sig.sosfilt(sos, x)
sos = butter(10, [0.04, 0.16], btype="bandpass", output="sos") w, h = sosfreqz(sos, worN=8000) # Plot the magnitude and phase of the frequency response. plt.figure(figsize=(4.0, 4.0)) plt.subplot(211) plt.plot(w / np.pi, np.abs(h)) plt.grid(alpha=0.25) plt.ylabel('Gain') plt.subplot(212) plt.plot(w / np.pi, np.angle(h)) yaxis = plt.gca().yaxis yaxis.set_ticks([-np.pi, -0.5 * np.pi, 0, 0.5 * np.pi, np.pi]) yaxis.set_ticklabels([r'$-\pi$', r'$-\pi/2$', '0', r'$\pi/2$', r'$\pi$']) plt.xlabel('Normalized frequency') plt.grid(alpha=0.25) plt.ylabel('Phase') plt.tight_layout() plt.savefig("sos_bandpass_response_freq.pdf") # Plot the step response. x = np.ones(200) y = sosfilt(sos, x) plt.figure(figsize=(4.0, 2.0)) plt.plot(y) plt.grid(alpha=0.25) plt.xlabel('Sample number') plt.tight_layout() plt.savefig("sos_bandpass_response_step.pdf")
def filter_data(data, dataplot=False, filter_response_plot=False, sampling_frequency=250): #this follows the arnav process #signal processing # - hpf, notch filter (50 Hz) x 3 with harmonics, lpf #applying high pass filter - 0.5, used to remove frequencies lower than 0.5Hz filter_order = 1 # critical_frequencies = [15, 50] #in Hz critical_frequency = 1.5 # in Hz FILTER = 'highpass' #'bandpass' output = 'sos' #design butterworth bandpass filter sos = signal.butter(filter_order, critical_frequency, FILTER, fs=sampling_frequency, output=output) filtered = signal.sosfilt(sos, data) #response of the high pass filter if (filter_response_plot): b, a = signal.butter(filter_order, critical_frequency, FILTER, sampling_frequency) w, h = signal.freqz(b, a, sampling_frequency) plt.semilogx(w, 20 * np.log10(abs(h))) plt.xlabel('Frequency [radians / second]') plt.ylabel('Amplitude [dB]') plt.margins(0, 0.1) plt.grid(which='both', axis='both') cutoff_freq = [] cutoff_freq.append(critical_frequency) for freq in cutoff_freq: plt.axvline(freq, color='green') plt.show() #normalize -(normalizing to a mean amplitude of zero (still need to cross check this)) data = data - np.mean(data, axis=0) #applying notch filter notch_times = 3 notch_frequency = 50 #Hz quality_factor = 30 # -- no reason just copied. #power line noise @ 50 Hz and its harmonics. freqs = list( map( int, list( map( round, np.arange(1, sampling_frequency / (2. * notch_frequency)) * notch_frequency)))) for _ in range(notch_times): for f in reversed(freqs): #design notch filter b, a = signal.iirnotch(f, quality_factor, sampling_frequency) filtered = signal.lfilter(b, a, filtered) #response of iirnotch filter if filter_response_plot: # Frequency response freq, h = signal.freqz(b, a, fs=sampling_frequency) # Plot fig, ax = plt.subplots(2, 1, figsize=(8, 6)) ax[0].plot(freq, 20 * np.log10(abs(h)), color='blue') ax[0].set_title("Frequency Response") ax[0].set_ylabel("Amplitude (dB)", color='blue') ax[0].set_xlim([0, 100]) ax[0].set_ylim([-25, 10]) ax[0].grid() ax[1].plot(freq, np.unwrap(np.angle(h)) * 180 / np.pi, color='green') ax[1].set_ylabel("Angle (degrees)", color='green') ax[1].set_xlabel("Frequency (Hz)") ax[1].set_xlim([0, 100]) ax[1].set_yticks([-90, -60, -30, 0, 30, 60, 90]) ax[1].set_ylim([-90, 90]) ax[1].grid() plt.show() #applying lowpass filter 50 Hz filter_order = 1 # critical_frequencies = [15, 50] #in Hz for bandpass critical_frequencies = 50 # in Hz FILTER = 'lowpass' #'bandpass' output = 'sos' #design butterworth lowpass filter sos = signal.butter(filter_order, critical_frequencies, FILTER, fs=sampling_frequency, output=output) filtered = signal.sosfilt(sos, data) #response of the lowpass filter if (filter_response_plot): output = 'ba' b, a = signal.butter(filter_order, critical_frequencies, FILTER, fs=sampling_frequency, output=output) w, h = signal.freqz(b, a, fs=sampling_frequency) plt.semilogx(w, 20 * np.log10(abs(h))) plt.xlabel('Frequency [radians / second]') plt.ylabel('Amplitude [dB]') plt.margins(0, 0.1) plt.grid(which='both', axis='both') for freq in critical_frequencies: plt.axvline(freq, color='green') plt.show() #applying ricker ricker_width = 35 * sampling_frequency // 250 ricker_sigma = 4.0 * sampling_frequency / 250 #4.0... ricker = signal.ricker(ricker_width, ricker_sigma) # normalize ricker ricker = np.array(ricker, np.float32) / np.sum(np.abs(ricker)) #obtain the ricker in the data convolution = signal.convolve(filtered, ricker, mode="same") #remove the heart beat artifacts from the original signal filtered = filtered - 2 * convolution if (filter_response_plot): plt.plot(convolution) plt.show() return filtered
by = np.exp(-tspan / 0.05) cn = np.convolve(n, by) cn = cn[:len(tspan)] s = 0.1 * np.sin(2 * np.pi * tspan) + cn freq_sample = 0.5 * (1 / dt) # Sampling frequency df = 1 / tspan[-1] freq = np.arange(df, freq_sample + df, df) signal_fft = fft.fft(s) signal_fft = signal_fft[:len(freq)] signal_fft = abs(signal_fft) # Filtered signal f_c = 10 / freq_sample # cut-off frequency sos = signal.butter(5, f_c, 'lp', output='sos') signal_filtered = signal.sosfilt(sos, s) filtered_fft = fft.fft(signal_filtered) filtered_fft = filtered_fft[:len(freq)] filtered_fft = abs(filtered_fft) fig0 = plt.figure() ax0 = fig0.add_axes([0, 0, 1, 1]) ax0.plot(freq, signal_fft) ax0.plot(freq, filtered_fft) ax0.set_xlabel('Frequency (Hz)') ax0.set_ylabel('FFT') ax0.set_title('FFT for the random signal') #ax0.legend(['Original signal','Filtered signal']) ax0.grid(True) fig3, (ax31, ax32) = plt.subplots(2, 1)
Ephys = dyn_osc.Ephys # Setup our chirp pt = '906' condit = 'OffTarget' timeseries = dbo.load_BR_dict(Ephys[pt][condit]['Filename'],sec_offset=0) end_time = timeseries['Left'].shape[0]/422 if pt == '903': tidxs = np.arange(231200,329300) #DBS903 if pt == '906': tidxs = np.arange(256000,330200) #DBS903 sos_lpf = sig.butter(10,10,output='sos',fs = 422) filt_L = sig.sosfilt(sos_lpf,timeseries['Left']) #filt_L = sig.decimate(filt_L,2)[tidxs] #-211*60*8: filt_R = sig.sosfilt(sos_lpf,timeseries['Right']) #filt_R = sig.decimate(filt_R,2)[tidxs] state = np.vstack((filt_L,filt_R)) sd = np.diff(state,axis=1,append=0) #Let's take out the BL stim first from the raw timeseries window = np.arange(255583,296095) chirp = state[:,window] #plt.figure() #plt.plot(chirp.T) ## Now we get into subwindows
def filter(self, *filt): """Apply the given filter to this `TimeSeries`. All recognised filter arguments are converted either into cascading second-order sections (if scipy >= 0.16 is installed), or into the ``(numerator, denominator)`` representation before being applied to this `TimeSeries`. .. note:: All filters are presumed to be digital (Z-domain), if you have an analog ZPK (in Hertz or in rad/s) you should be using `TimeSeries.zpk` instead. .. note:: When using `scipy` < 0.16 some higher-order filters may be unstable. With `scipy` >= 0.16 higher-order filters are decomposed into second-order-sections, and so are much more stable. Parameters ---------- *filt one of: - :class:`scipy.signal.lti` - `MxN` `numpy.ndarray` of second-order-sections (`scipy` >= 0.16 only) - ``(numerator, denominator)`` polynomials - ``(zeros, poles, gain)`` - ``(A, B, C, D)`` 'state-space' representation Returns ------- result : `TimeSeries` the filtered version of the input `TimeSeries` See also -------- TimeSeries.zpk for instructions on how to filter using a ZPK with frequencies in Hertz scipy.signal.sosfilter for details on the second-order section filtering method (`scipy` >= 0.16 only) scipy.signal.lfilter for details on the filtering method Raises ------ ValueError If ``filt`` arguments cannot be interpreted properly """ sos = None # single argument given if len(filt) == 1: filt = filt[0] # detect LTI if isinstance(filt, signal.lti): filt = filt a = filt.den b = filt.num # detect SOS elif isinstance(filt, numpy.ndarray) and filt.ndim == 2: sos = filt # detect taps else: b = filt a = [1] # detect TF elif len(filt) == 2: b, a = filt elif len(filt) == 3: try: sos = signal.zpk2sos(*filt) except AttributeError: b, a = signal.zpk2tf(*filt) elif len(filt) == 4: try: zpk = signal.ss2zpk(*filt) sos = signal.zpk2sos(zpk) except AttributeError: b, a = signal.ss2tf(*filt) else: raise ValueError("Cannot interpret filter arguments. Please " "give either a signal.lti object, or a " "tuple in zpk or ba format. See " "scipy.signal docs for details.") if sos is not None: new = signal.sosfilt(sos, self, axis=0).view(self.__class__) else: new = signal.lfilter(b, a, self, axis=0).view(self.__class__) new.__dict__ = self.copy_metadata() return new
def time_sosfilt_basic(self, n_samples, order): sosfilt(self.sos, self.y)
def applyComponent(self, component): sos = self.buildFilter(component) return sp.sosfilt(sos, component)
def convertData(adr="./data/features_clear_less.dat"): print("Program started" + "\n") fout_data = open(adr, 'w') fout_labels0 = open("./data\labels_0.dat", 'w') fout_labels1 = open("./data\labels_1.dat", 'w') fout_labels2 = open("./data\labels_2.dat", 'w') fout_labels3 = open("./data\labels_3.dat", 'w') print("\n" + "Print Successful") for i in range(32): #nUser #4, 40, 32, 40, 8064 if (i % 1 == 0): if i < 10: name = '%0*d' % (2, i + 1) else: name = i + 1 fname = "./data_preprocessed_python\s" + str( name) + ".dat" #C:/Users/lumsys/AnacondaProjects/Emo/ f = open(fname, 'rb') x = pickle.load(f, encoding='latin1') print(fname) for tr in range(nTrial): # noise = np.random.normal(0,3000, size=(8064,)) start = 128 * 3 - 1 if (tr % 1 == 0): for dat in range(128 * 3, nTime): if dat != 0: if ((dat - 383) % 768 == 0): if (tr == 0 and i == 0): print(dat) for ch in [32, 33, 36, 38]: if (1 == 1): if ch == 36 or ch == 32 or ch == 33: data_fil = x['data'][tr][ch] else: data_oringin = x['data'][tr][ch] sos = signal.butter(4, 0.3, 'high', output='sos') data_fil = signal.sosfilt( sos, data_oringin) features = extract_fre_fea( data_fil[start:dat]) for fea in features: fout_data.write(str(fea) + " ") start = dat fout_labels0.write(str(x['labels'][tr][0]) + "\n") fout_labels1.write(str(x['labels'][tr][1]) + "\n") fout_labels2.write(str(x['labels'][tr][2]) + "\n") fout_labels3.write(str(x['labels'][tr][3]) + "\n") fout_data.write("\n") #个性化特征 # fout_data.write(str(tr)+ " ") # fout_data.write(str(i)+ " ") # 总 # print(x['data'][tr][39][:].shape) # for data in datas: # fout_data.write(str(data)+ " ") # fout_labels0.write(str(x['labels'][tr][0]) + "\n") # fout_labels1.write(str(x['labels'][tr][1]) + "\n") # fout_labels2.write(str(x['labels'][tr][2]) + "\n") # fout_labels3.write(str(x['labels'][tr][3]) + "\n") # fout_data.write("\n")#40个特征换行 fout_labels0.close() fout_labels1.close() fout_labels2.close() fout_labels3.close() fout_data.close() print("\n" + "Print Successful")
def plot_converging_stack(inputfile, bandpass=None, pause=0.): f = h5py.File(inputfile, 'r') plt.ion() stack = f['corr_windows'].keys()[0] stack = f['corr_windows'][stack][:] stats = f['stats'] Fs = stats.attrs['sampling_rate'] cha1 = stats.attrs['channel1'] cha2 = stats.attrs['channel2'] if bandpass is not None: sos = get_bandpass(df=Fs, freqmin=bandpass[0], freqmax=bandpass[1], corners=bandpass[2]) firstpass = sosfilt(sos, stack) stack = sosfilt(sos, firstpass[::-1])[::-1] # display a counter for stacked windows cnt = 1 max_lag = ((len(stack) - 1) / 2) / Fs lag = np.linspace(-max_lag, max_lag, len(stack)) fig = plt.figure() ax1 = fig.add_subplot(212) ax1.set_title('{}--{}'.format(cha1, cha2)) ax1.set_xlabel('Lag (s)') ax1.set_ylabel('Correlation stack') line1, = ax1.plot(lag, stack, 'k') ax2 = fig.add_subplot(211) ax2.set_ylim([np.min(stack) * 3, np.max(stack) * 3]) ax2.set_ylabel('Correlation window(s)') line2, = ax2.plot(lag, stack) text1 = ax2.set_title(str(cnt)) plt.show() for key in f['corr_windows'].keys(): cwindow = f['corr_windows'][key][:] if bandpass is not None: firstpass = sosfilt(sos, cwindow) cwindow = sosfilt(sos, firstpass[::-1])[::-1] stack += cwindow ax1.set_ylim([np.min(stack) * 1.5, np.max(stack) * 1.5]) text1.set_text(str(cnt)) line1.set_ydata(stack) line2.set_ydata(cwindow) fig.canvas.draw() cnt += 1 if pause > 0: time.sleep(pause)
def predict(request): # Get ML model storage_client = storage.Client() bucket = storage_client.get_bucket('sensordaten-d713c.appspot.com') blob = bucket.blob('ml_model/pickle_svm.sav') pickle_in = blob.download_as_string() best_svm = pickle.loads(pickle_in) print('ML Model:') print(best_svm) # Get CSV data raw_data = pd.read_csv( 'gs://sensordaten-d713c.appspot.com/file_to_process/sensordaten.csv') raw_data.columns = ['time', 'x', 'y', 'z', 'abs'] raw_data = raw_data.drop(columns=['abs']) print('Data Head of csv file:') print(raw_data.head()) # Get SPC from CSV SPC = 0.31 # TODO Read SPC from CSV f = 100 # TODO Read frequency from CSV # Process Offset start = 10 end = raw_data['time'].max() - 10 offset_data = raw_data[(raw_data['time'] >= start) & (raw_data['time'] <= end)] offset_data['time'] = offset_data['time'] - offset_data['time'].min() offset_data.index = offset_data.index - offset_data.index.min() print(offset_data.head()) # Process Filter & SPC filter_data = copy.deepcopy(offset_data) sos = signal.butter(10, (5, 30), btype='bandpass', fs=f, output='sos') for col in ['x', 'y', 'z']: filter_data[col] = signal.sosfilt(sos, offset_data[col]) filter_data[col] = filter_data[col] / (1 - SPC) # Create datatable for feature engineering max_time = int(filter_data['time'].max()) period = 10 aggregated_data = pd.DataFrame(list(range(0, max_time, period)), columns=['time']) for col in ['x', 'y', 'z']: aggregated_data[f'{col}_mean'] = np.nan aggregated_data[f'{col}_max'] = np.nan aggregated_data[f'{col}_min'] = np.nan aggregated_data[f'{col}_std'] = np.nan for timestamp in aggregated_data['time']: relevant_rows = raw_data[((raw_data['time'] >= timestamp) & (raw_data['time'] < timestamp + period))] relevant_rows.index = relevant_rows.index - relevant_rows.index.min() outlier_relevant = process_outlier_detection(relevant_rows, ['x', 'y', 'z']) for col in ['x', 'y', 'z']: aggregated_data.loc[timestamp / period, str(col) + str('_mean')] = np.mean( outlier_relevant[col]) aggregated_data.loc[timestamp / period, str(col) + str('_max')] = np.max( outlier_relevant[col]) aggregated_data.loc[timestamp / period, str(col) + str('_min')] = np.min( outlier_relevant[col]) aggregated_data.loc[timestamp / period, str(col) + str('_std')] = np.std( outlier_relevant[col]) print('Aggregated Datatable:') print(aggregated_data) # Predict underground for aggregated values predictions = best_svm.predict(aggregated_data.drop(columns=['time'])) export_pred = pd.DataFrame(predictions, columns=['prediction']) print(export_pred)
def butter_highpass(lowcut, fs, order=5): nyq = 0.5 * fs low = lowcut / nyq b, a = signal.butter(order, [low], btype='highpass') return b, a def butter_highpass_filter(data, lowcut, fs, order=5): b, a = butter_highpass(lowcut, fs, order=order) y = signal.lfilter(b, a, data) return y lc = 0.1 hc = 30 sos = signal.butter(10, lc, 'hp', fs=fs, output='sos') filtered = signal.sosfilt(sos, cz) plt.figure() plt.plot(t, filtered[0:sample_window], label='Filtered signal') plt.plot(t, sample, label='Unfiltered signal') plt.plot(t, trig_sample, label='Trigger') plt.legend(loc='best') # %% plot_freq(filtered, fs) # %% Find the spacing of events event_idxs = np.nonzero(trig)[0] print(f'Number of events: {len(event_idxs)}')
def rectified_band_pass_signals(sig, sb=2048, sh=1024): """Compute the rectified band-pass signals as per Clause 5.1.5 of ECMA-418-2:2020 Calculation of the rectified band-pass signals along the 53 critical band rates scale. Each band pass signal is segmented into time blocks according to sb and sh Parameters ---------- signal: numpy.array 'Pa', time signal values. The sampling frequency of the signal must be 48000 Hz. sb: int or list of int block size. sh: int or list of int Hop size. Returns ------- block_array_rect: list of numpy.array rectified band-pass signals """ if isinstance(sb, int): sb = sb * np.ones(53, dtype=int) elif len(sb) != 53: raise ValueError("ERROR: len(sb) shall be either 1 or 53") if isinstance(sh, int): sh = sh * np.ones(53, dtype=int) elif len(sh) != 53: raise ValueError("ERROR: len(sh) shall be either 1 or 53") # OUTER AND MIDDLE EAR FILTERING (5.1.2) sos_ear = ear_filter_design() signal_filtered = sp_signal.sosfilt(sos_ear, sig, axis=0) # AUDITORY FILTERING BANK (5.1.3) # Order of the Outer and Middle ear filter filter_order_k = 5 # Sampling frequency fs = 48000.00 # Auditory filters centre frequencies centre_freq = gen_auditory_filters_centre_freq() block_array_rect = [] for band_number in range(53): bm_mod, am_mod = gammatone(centre_freq[band_number], k=filter_order_k, fs=fs) # bm_mod, am_mod = sp_signal.gammatone(centre_freq[band_number], "fir", fs=fs) """ "scipy.signal.lfilter" instead of "scipy.signal.filtfilt" in order to maintain consistency. That process makes possible to obtain a signal "band_pass_signal" that does not line up in time with the original signal because of the non zero-phase filtering of "lfilter", but it has a more appropriate slope than filtfilt. By using filtfilt the slope is that high that filters too much the signal. """ band_pass_signal = (2.0 * (sp_signal.lfilter( bm_mod, am_mod, signal_filtered, axis=0, )).real) """SEGMENTATION OF THE SIGNAL INTO BLOCKS (5.1.4) The segmentation of the signal is done in order to obtain results for intervals of time, not for the whole duration of the signal. The reason behind this decision resides in the fact that processing the signal in its full length at one time could end up in imprecise results. By using a "for loop", we are able to decompose the signal array "band_pass_signal_hr" into blocks. "sb_array" is the block size which changes depending on the "band_number" in which we are processing the signal. "sh_array" is the step size, the time shift to the next block. """ block_array = segmentation_blocks(band_pass_signal, sb[band_number], sh[band_number], dim=1) """RECTIFICATION (5.1.5) This part acts as the activation of the auditory nerves when the basilar membrane vibrates in a certain direction. In order to rectify the signal we are using "np.clip" which establish a minimum and a maximum value for the signal. "a_min" is set to 0 float, while "a_max" is set to "None" in order to consider the positive value of the signal. """ block_array_rect.append(np.clip(block_array, a_min=0.00, a_max=None)) return block_array_rect
def lowpass_cheby_2(data, freq, df, maxorder=12, ba=False, freq_passband=False): """ Cheby2-Lowpass Filter Filter data by passing data only below a certain frequency. The main purpose of this cheby2 filter is downsampling. This method will iteratively design a filter, whose pass band frequency is determined dynamically, such that the values above the stop band frequency are lower than -96dB. Parameters ---------- data : array Data to filter. freq : float The frequency above which signals are attenuated with 95 dB. df : float Sampling rate in Hz. maxorder : int Maximal order of the designed cheby2 filter. **Default:** ``12`` ba : bool If True return only the filter coefficients (b, a) instead of filtering. **Default:** ``False`` freq_passband : bool If True return additionally to the filtered data, the iteratively determined pass band frequency. **Default:** ``False`` Returns ------- data : array Filtered data. """ nyquist = df * 0.5 # rp - maximum ripple of passband, rs - attenuation of stopband rp, rs, order = 1, 96, 1e99 ws = freq / nyquist # stop band frequency wp = ws # pass band frequency # raise for some bad scenarios if ws > 1: ws = 1.0 msg = "Selected corner frequency is above Nyquist. " + \ "Setting Nyquist as high corner." warnings.warn(msg) while True: if order <= maxorder: break wp = wp * 0.99 order, wn = cheb2ord(wp, ws, rp, rs, analog=0) if ba: return cheby2(order, rs, wn, btype='low', analog=0, output='ba') z, p, k = cheby2(order, rs, wn, btype='low', analog=0, output='zpk') sos = zpk2sos(z, p, k) if freq_passband: return sosfilt(sos, data), wp * nyquist return sosfilt(sos, data)
import scipy.signal as sg from pysndfx import AudioEffectsChain def filter_audio(y, sr=16_000, cutoff=15_000, low_cutoff=1, filter_order=5): sos = sg.butter(filter_order, [low_cutoff / sr / 2, cutoff / sr / 2], btype='band', analog=False, output='sos') filtered = sg.sosfilt(sos, y) return filtered def shelf(y, sr=16_000, gain=5, frequency=500, slope=0.5, high_frequency=7_000): afc = AudioEffectsChain() fx = afc.lowshelf(gain=gain, frequency=frequency, slope=slope)\ .highshelf(gain=-gain, frequency=high_frequency, slope=slope) y = fx(y, sample_in=sr, sample_out=sr) return y
def bandpass(d): # create filter with cutoff frequencies 5 & 5,000 sos = signal.butter(2, [5, 5000], 'bp', fs=25000, output='sos') # apply filter and return return signal.sosfilt(sos, d)
end_time = 5 order = 10 buffer_size = 200 cutoff_frequency = 10 btype = 'hp' if __name__ == '__main__': # plt.figure(dpi=1200) f = importlib.import_module('files.blueprints.butterworth.main').P(start_time, sample_spacing, buffer_size, cutoff_frequency) signal = generate_signal([1, 2, 4, 8, 16, 32, 64, 128], [0, 0, 0, 0, 1, 0, 0, 0]) noise = generate_noise(.0) t_range = np.arange(start_time, end_time, sample_spacing) output = np.zeros(len(t_range)) plt.plot(t_range, [signal(t) + noise(t) for t in t_range]) plt.show() sos = si.butter(order, cutoff_frequency, btype, fs=1 / sample_spacing, output='sos') filtered = si.sosfilt(sos, [signal(t) + noise(t) for t in t_range]) plt.plot(t_range, filtered) plt.show() # asdf = np.zeros(len(t_range)) # for i in range(len(t_range)//buffer_size): # asdf[i:buffer_size] = for i, t in enumerate(t_range): f.set_inputs([0], [signal(t) + noise(t)]) f.step(t) output[i] = f.get_outputs([0])[0] plt.plot(t_range, output) plt.show()
def high_pass_filter(x, low_cutoff=10000, sample_rate=sample_rate): nyquist = 0.5 * sample_rate norm_low_cutoff = low_cutoff / nyquist sos = butter(10, Wn=[norm_low_cutoff], btype='highpass', output='sos') filtered_sig = sosfilt(sos, x) return filtered_sig
def draw_impz(self): """ (Re-)calculate h[n] and draw the figure """ log = self.chkLog.isChecked() stim = str(self.cmbStimulus.currentText()) periodic_sig = stim in {"Sine","Rect", "Saw"} self.lblLogBottom.setVisible(log) self.ledLogBottom.setVisible(log) self.lbldB.setVisible(log) self.lblFreq.setVisible(periodic_sig) self.ledFreq.setVisible(periodic_sig) self.lblFreqUnit.setVisible(periodic_sig) # self.lblFreqUnit.setVisible(fb.fil[0]['freq_specs_unit'] == 'f_S') self.lblFreqUnit.setText(rt_label(fb.fil[0]['freq_specs_unit'])) self.load_entry() self.bb = np.asarray(fb.fil[0]['ba'][0]) self.aa = np.asarray(fb.fil[0]['ba'][1]) sos = np.asarray(fb.fil[0]['sos']) self.f_S = fb.fil[0]['f_S'] N = self.calc_n_points(abs(int(self.ledNPoints.text()))) t = np.linspace(0, N/self.f_S, N, endpoint=False) # calculate h[n] if stim == "Pulse": x = np.zeros(N) x[0] =1.0 # create dirac impulse as input signal title_str = r'Impulse Response' H_str = r'$h[n]$' elif stim == "Step": x = np.ones(N) # create step function title_str = r'Step Response' H_str = r'$h_{\epsilon}[n]$' elif stim == "StepErr": x = np.ones(N) # create step function title_str = r'Settling Error' H_str = r'$H(0) - h_{\epsilon}[n]$' elif stim in {"Sine", "Rect"}: x = np.sin(2 * np.pi * t * float(self.ledFreq.text())) if stim == "Sine": title_str = r'Response to Sine Signal' H_str = r'$h_{\sin}[n]$' else: x = np.sign(x) title_str = r'Response to Rect. Signal' H_str = r'$h_{rect}[n]$' else: x = sig.sawtooth(t * (float(self.ledFreq.text())* 2*np.pi)) title_str = r'Response to Sawtooth Signal' H_str = r'$h_{saw}[n]$' if not np.any(sos): # no second order sections for current filter h = sig.lfilter(self.bb, self.aa, x) dc = sig.freqz(self.bb, self.aa, [0]) else: # print(sos) h = sig.sosfilt(sos, x) dc = sig.freqz(self.bb, self.aa, [0]) if stim == "StepErr": h = h - abs(dc[1]) # subtract DC value from response self.cmplx = np.any(np.iscomplex(h)) if self.cmplx: h_i = h.imag h = h.real H_i_str = r'$\Im\{$' + H_str + '$\}$' H_str = r'$\Re\{$' + H_str + '$\}$' if log: bottom = float(self.ledLogBottom.text()) H_str = r'$|$ ' + H_str + '$|$ in dB' h = np.maximum(20 * np.log10(abs(h)), bottom) if self.cmplx: h_i = np.maximum(20 * np.log10(abs(h_i)), bottom) H_i_str = r'$\log$ ' + H_i_str + ' in dB' else: bottom = 0 self._init_axes() #================ Main Plotting Routine ========================= [ml, sl, bl] = self.ax_r.stem(t, h, bottom=bottom, markerfmt='bo', linefmt='r') if self.chkPltStim.isChecked(): [ms, ss, bs] = self.ax_r.stem(t, x, bottom=bottom, markerfmt='k*', linefmt='0.5') for stem in ss: stem.set_linewidth(0.5) bs.set_visible(False) # invisible bottomline expand_lim(self.ax_r, 0.02) self.ax_r.set_title(title_str) if self.cmplx: [ml_i, sl_i, bl_i] = self.ax_i.stem(t, h_i, bottom=bottom, markerfmt='rd', linefmt='b') self.ax_i.set_xlabel(fb.fil[0]['plt_tLabel']) # self.ax_r.get_xaxis().set_ticklabels([]) # removes both xticklabels # plt.setp(ax_r.get_xticklabels(), visible=False) # is shorter but imports matplotlib, set property directly instead: [label.set_visible(False) for label in self.ax_r.get_xticklabels()] self.ax_r.set_ylabel(H_str + r'$\rightarrow $') self.ax_i.set_ylabel(H_i_str + r'$\rightarrow $') else: self.ax_r.set_xlabel(fb.fil[0]['plt_tLabel']) self.ax_r.set_ylabel(H_str + r'$\rightarrow $') if self.ACTIVE_3D: # not implemented / tested yet # plotting the stems for i in range(len(t)): self.ax3d.plot([t[i], t[i]], [h[i], h[i]], [0, h_i[i]], '-', linewidth=2, color='b', alpha=.5) # plotting a circle on the top of each stem self.ax3d.plot(t, h, h_i, 'o', markersize=8, markerfacecolor='none', color='b', label='ib') self.ax3d.set_xlabel('x') self.ax3d.set_ylabel('y') self.ax3d.set_zlabel('z') self.mplwidget.redraw()
p = pyaudio.PyAudio() # start the PyAudio class stream = p.open(format=pyaudio.paInt16, channels=1, rate=RATE, input=True, frames_per_buffer=CHUNK) #uses default input device data_buffer = np.array([]) # create a numpy array holding a single read of audio data for i in range(30): #to it a few times just to see print(i) data = np.frombuffer(stream.read(CHUNK), dtype=np.int16) data_buffer = np.concatenate([data_buffer, data]) sos = signal.butter(10, 15, 'hp', fs=1000, output='sos') data_buffer = signal.sosfilt(sos, data_buffer) # close the stream gracefully stream.stop_stream() stream.close() p.terminate() np.save('ding69.npy', data_buffer) plt.plot(data_buffer) plt.show() else: data_buffer = np.load('ding69.npy')[74700:107700] np.save('ding_select_floor2_left_mic.npy', data_buffer) plt.plot(data_buffer)
def update(self, line_label, data): """ :param line_label: Label of the segmented series :param data: Replace data in the segmented series with these data :return: """ ss_info = self.segmented_series[line_label] n_in = data.shape[0] if self.plot_config['do_hp']: data, ss_info['hp_zi'] = signal.sosfilt(self.plot_config['hp_sos'], data, zi=ss_info['hp_zi']) if self.plot_config['do_ln']: pass # TODO: Line noise / comb filter if self.pya_stream: if 'chan_label' in self.audio and self.audio['chan_label']: if self.audio['chan_label'] == line_label: write_indices = ( np.arange(data.shape[0]) + self.audio['write_ix']) % self.audio['buffer'].shape[0] self.audio['buffer'][write_indices] = ( np.copy(data) * (2**15 / self.plot_config['y_range'])).astype(np.int16) self.audio['write_ix'] = ( self.audio['write_ix'] + data.shape[0]) % self.audio['buffer'].shape[0] # Assume new samples are consecutively added to old samples (i.e., no lost samples) sample_indices = np.arange(n_in, dtype=np.int32) + ss_info['last_sample_ix'] # Wrap sample indices around our plotting limit n_plot_samples = int(self.plot_config['x_range'] * self.samplingRate) sample_indices = np.int32(np.mod(sample_indices, n_plot_samples)) # If the data length is longer than one sweep then the indices will overlap. Trim to last n_plot_samples if sample_indices.size > n_plot_samples: sample_indices = sample_indices[-n_plot_samples:] data = data[-n_plot_samples:] # Go through each plotting segment and replace data with new data as needed. for pci in ss_info['plot'].dataItems: old_x, old_y = pci.getData() x_lims = [old_x[0], old_x[-1]] if self.plot_config['downsample']: x_lims[1] += (DSFAC - 1) data_bool = np.logical_and(sample_indices >= x_lims[0], sample_indices <= x_lims[-1]) if np.where(data_bool)[0].size > 0: new_x, new_y = sample_indices[data_bool], data[data_bool] if self.plot_config['downsample']: new_x = new_x[::DSFAC] - (new_x[0] % DSFAC) + (old_x[0] % DSFAC) new_y = new_y[::DSFAC] old_bool = np.in1d(old_x, new_x, assume_unique=True) new_bool = np.in1d(new_x, old_x, assume_unique=True) old_y[old_bool] = new_y[new_bool] # old_y[np.where(old_bool)[0][-1]+1:] = 0 # Uncomment to zero out the end of the last seg. pci.setData(x=old_x, y=old_y) # Store last_sample_ix for next iteration. self.segmented_series[line_label]['last_sample_ix'] = sample_indices[ -1]
def butter_bandpass_filter(self, data, lowcut, highcut, fs, order=5): sos = self.butter_bandpass(lowcut, highcut, fs, order=order) y = sosfilt(sos, data) return y
def preprocessing_proc(sos, traces): return signal.sosfilt(sos, traces)
def butter_filter(timeseries, fs, cutoffs, btype='band', order=4): #Scipy v1.2.0 nyquist = fs / 2 butter_cut = np.divide(cutoffs, nyquist) #butterworth param (digital) sos = butter(order, butter_cut, output='sos', btype=btype) return sosfilt(sos, timeseries)
def __butter_bandstop_filter(self, data, lowcut, highcut, fs, order=5): sos = self.__butter_bandstop(lowcut, highcut, fs, order=order) y = sosfilt(sos, data).astype(np.float32) return y
def run(self,output_file=None): print('Working on station pairs:') for sta in self.station_pairs: print("{}--{}".format(sta[0],sta[1])) t_0 = UTCDateTime(self.cfg.time_begin) t_end = UTCDateTime(self.cfg.time_end) win_len_seconds = self.cfg.time_window_length win_len_samples = int(round(win_len_seconds*self.sampling_rate)) min_len_samples = int(round(self.cfg.time_min_window*self.sampling_rate)) max_lag_samples = int(round(self.cfg.corr_maxlag * self.sampling_rate)) if self.cfg.bandpass is not None: fmin = self.cfg.bandpass[0] fmax = self.cfg.bandpass[1] if fmax <= fmin: msg = "Bandpass upper corner frequency must be above lower corner frequency." raise ValueError(msg) order = self.cfg.bandpass[2] sos = bandpass(freqmin=fmin,freqmax=fmax, df=self.sampling_rate,corners=order) # Time loop t = t_0 while t <= t_end - (win_len_seconds - self.delta): print(t,file=output_file) # - check endtime, if necessary, add data from 'later' file self.update_data(t, win_len_seconds) # - slice the traces if self.cfg.time_overlap == 0: windows = self.data.slice(t, t + win_len_seconds - self.delta) else: # - deepcopy is used so that processing is not applied directly on the data stream # - This is much more expensive than using non-overlapping windows, due to the copying windows = self.data.slice(t, t + win_len_seconds - self.delta).copy() # - Apply preprocessing for w in windows: if self.cfg.bandpass is not None: w_temp = sosfilt(sos,w.data) w.data = sosfilt(sos,w_temp[::-1])[::-1] if self.cfg.cap_glitch: cap(w,self.cfg.cap_thresh) if self.cfg.whiten: whiten(w,self.cfg.white_freqmin, self.cfg.white_freqmax, self.cfg.white_taper_samples) if self.cfg.onebit: w.data = np.sign(w.data) if self.cfg.ram_norm: ram_norm(w,self.cfg.ram_window,self.cfg.ram_prefilt) # - station pair loop for sp_i in range(len(self.station_pairs)): pair = self.station_pairs[sp_i] # - select traces [net1, sta1] = pair[0].split('.') [net2, sta2] = pair[1].split('.') str1 = windows.select(network=net1, station=sta1) str2 = windows.select(network=net2, station=sta2) # - if horizontal components are involved, copy and rotate if any([i in self.cfg.corr_tensorcomponents for i in horizontals]): str1, str2 = self.rotate(str1,str2,self.baz1[sp_i],self.baz2[sp_i]) # - channel loop for cpair in self.channel_pairs[sp_i]: cpair = [re.sub('E$','T',str) for str in cpair] cpair = [re.sub('N$','R',str) for str in cpair] cp_name = '{}--{}'.format(*cpair) print(cp_name,file=output_file) loc1, cha1 = cpair[0].split('.')[2:4] loc2, cha2 = cpair[1].split('.')[2:4] try: tr1 = str1.select(location=loc1,channel=cha1)[0] tr2 = str2.select(location=loc2,channel=cha2)[0] except IndexError: print("Channel not found",file=output_file) continue # - check minimum length requirement # - Quite often not fulfilled due to data gaps if tr1.stats.npts < min_len_samples: print("Trace length < min samples\n",file=output_file) continue if tr2.stats.npts < min_len_samples: print("Trace length < min samples\n",file=output_file) continue if True in np.isnan(tr1.data): print("Trace contains nan\n",file=output_file) continue if True in np.isnan(tr2.data): print("Trace contains nan\n",file=output_file) continue if True in np.isinf(tr1.data): print("Trace contains inf\n",file=output_file) continue if True in np.isinf(tr2.data): print("Trace contains inf\n",file=output_file) continue # - correlate correlation = cross_covar(tr1.data,tr2.data, max_lag_samples,self.cfg.corr_normalize)[0] # - add to stack if len(correlation) == 2 * max_lag_samples + 1: self._correlations[cp_name]._add_corr(correlation,t) else: print('Empty window or all values zero in window.', file=output_file) # - update time t += self.cfg.time_window_length - self.cfg.time_overlap # - Write results for corr in self._correlations.values(): corr.write_stack(output_format=self.cfg.format_output) print('Finished a correlation block.')
def butterFilter(data, cuttof, filter_order=20, filter_type='low', plot=False): """Apply Butterworth filter.""" DEBUG = False # DEBUG = True # nyquist frequency nyq = 0.5 * Global.simul_frequency # adjsut cuttof frequency if isinstance(cuttof, list): cuttof_nyq = [] cuttof_nyq[0] = cuttof[0] / nyq cuttof_nyq[1] = cuttof[1] / nyq else: cuttof_nyq = cuttof / nyq # data time frame number_points = len(data) time_frame = number_points * Global.time_step number_samples = int(Global.simul_frequency * time_frame) t = np.linspace(0, time_frame, number_samples, False) if DEBUG: # For testing f0 = 10e6 f1 = 40e6 data = np.sin(2 * np.pi * f0 * t) + np.sin(2 * np.pi * f1 * t) # data = np.sin(2*np.pi*f0*t) if plot: fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True) ax1.plot(t, data) ax1.set_title('Time domain signal') ax1.grid() # Create filter sos = signal.butter(filter_order, cuttof_nyq, btype=filter_type, output='sos') # yf = fftpack.fft(data) # xf = np.linspace(0.0, 1.0/(2.0*time_frame), int(number_samples/2)) # fig, ax = plt.subplots() # ax.plot(xf, 2.0/number_samples * np.abs(yf[:number_samples//2])) # plt.show() # filtered signal filtered = signal.sosfilt(sos, data) # get filter frequency and absolute value w, h = signal.sosfreqz(sos, worN=number_points) if plot: ax2.plot(t, filtered) ax2.set_title('Filtered signal.') # ax2.axis([0, 1, -2, 2]) ax2.set_xlabel('Time [seconds]') plt.tight_layout() ax2.grid() plt.show() plt.semilogx((Global.simul_frequency * 0.5 / np.pi) * w, 20 * np.log10(abs(h))) plt.title('Butterworth filter frequency response') plt.xlabel('Frequency [radians / second]') plt.ylabel('Amplitude [dB]') plt.margins(0, 0.1) plt.grid(which='both', axis='both') plt.axvline(cuttof, color='green') # cutoff frequency # plt.grid() plt.show() # plotBode(data, time_frame, number_samples, cuttof, data2=filtered) plotBode(data, t, number_samples, cuttof, data2=filtered) return filtered
def butter_lowpass_filter(data, cutoff, fs, order=5): sos = butter_lowpass(cutoff, fs, order=order) y = signal.sosfilt(sos, data) return y
def butter_bandpass_filter(data, lowcut, highcut, fs, order=5): z, p, k = butter_bandpass(lowcut, highcut, fs, order=order) convert = zpk2sos(z, p, k) y = sosfilt(convert, data) return y