eeg_tools.bandpass_filter

eeg_tools.bandpass_filter(signal, locut, hicut, srate, offset=None, passdB=1.0, stopdB=30.0, ftype='IIR', verbose=True)[source]

Band-/Low-/High-pass filter a 1D/2D input signal

Parameters:

signal : NumPy 1d/2darray

Input signal to be filtered. For 2d arrays it is assumed that signal has shape M-by-N, where M is the number of 1d signals (e.g., channels), and N is the number of samples (measurements etc.).

locut : float

Lower cutoff frequency in Hz. If locut is None then high-pass filtering is performed.

hicut : float

Upper cutoff frequency in Hz. If hicut is None then low-pass filtering is performed.

srate : float

Sampling rate of the signal in Hz.

offset : float

Offset frequency in Hz. The frequency shift used to calculate the stopband (see Notes for details). By default, the offset is a fraction of low-/high-cut frequencies.

passdB : float

Maximal frequency loss in the passband (in dB). For ftype = FIR (see below) passdB has to be equals stopdB.

stopdB : float

Minimal frequency attentuation in the stopband (in dB). For ftype = FIR (see below) passdB has to be equals stopdB.

ftype : str

Type of filter to be used (either IIR = infinite impulse response filter, or FIR = finite impulse response filter).

verbose : bool

Boolean flag to decide whether status messages are printed or not.

Returns:

filtered : NumPy 1d/2darray

Filtered version of input signal.

See also

scipy.signal.buttord
routine used to calculate optimal filter order
scipy.signal.butter
routine used to construct Butterworth filter based on output of buttord.
scipy.signal.lfilter
filters the input signal using calculated Butterworth filter design

Notes

This routine uses a Butterworth filter (for ftype = ‘IIR’) or a Kaiser filter (for ftype = ‘FIR’) to low-/high-/bandpass the input signal. Based on the user’s input the optimal (i.e., lowest) order of the filter is calculated. Note that depending on the choice of cutoff frequencies and values of passdB and stopdB the computed filter coefficients might be very large/low causing numerical instability in the filtering routine. The code assumes you know what you’re doing and does not try to guess whether the combination of cutoff-frequencies, offset and attenuation/amplification values applied to the input signal makes sense.

By default the offset frequency is computed as fraction of the input frequencies, i.e., for low-/high-pass filters the offset is 0.5*cutoff-frequency, for band-pass filters the offset is calculated as 0.5 times the width of the pass-band. The following skteches illustrate the filter’s operating modes

Amplification 
(dB)
/ \
||            Low-pass
|| ---------------------+
||                      |\
||                      | \
||                      |  +---------
||               PASS   |OS|   STOP
|| 
++===================================> Frequency (Hz)

Amplification 
(dB)
/\
||            High-pass
||           +------------------------
||          /|       
||         / |       
|| -------+  |       
|| STOP   |OS|   PASS  
|| 
++===================================> Frequency (Hz)

Amplification 
(dB)
/\
||            Band-pass
||           +----------+
||          /|          |\
||         / |          | \
|| -------+  |          |  +---------
|| STOP   |OS|   PASS   |OS|   STOP
||
++===================================> Frequency (Hz)

Where STOP = stop-band, OS = offset, PASS = pass-band.

Examples

We construct an artifical signal which we want to low-/high-/band-pass filter.

>>> import numpy as np
>>> srate = 5000 # Sampling rate in Hz
>>> T = 0.05
>>> nsamples = T*srate
>>> t = np.linspace(0,T,nsamples,endpoint=False)
>>> a = 0.02
>>> f0 = 600.0
>>> signal = 0.1 * np.sin(2 * np.pi * 1.2 * np.sqrt(t))
>>> signal += 0.01 * np.cos(2 * np.pi * 312 * t + 0.1)
>>> signal += a * np.cos(2 * np.pi * f0 * t + .11)
>>> signal += 0.03 * np.cos(2 * np.pi * 2000 * t)

First, we low-pass filter the signal using the default IIR Butterworth filter (all examples given below can be repeated using the FIR Kaiser filter by additionally providing the keyword argument ftype=’FIR’). As cutoff frequency we choose 50Hz, with an offset of 10Hz. That means frequencies [0-50] Hz “survive”, frequencies in the band [50-60] Hz are gradually attenuated, all frequencies >60Hz are maximally attenuated.

>>> filtered = bandpass_filter(signal,50,None,5000,offset=10)

Now, construct a high-pass filter that removes all frequencies below 500Hz, using the default offset of 0.5*`hicut` (see Notes for details).

>>> filtered = bandpass_filter(signal,None,500,5000)

Finally, we band-pass filter the signal, so that only frequency components between 500Hz and 1250Hz remain

>>> filtered = bandpass_filter(signal,500,1250,5000)

Note that ill-chosen values for the offset (e.g., very steep slopes, from the stop- to the pass-band, see Notes for a sketch) and/or attenuation/amplification dB’s may lead to very large/small filter coefficients that may cause erratic results due to numerical instability.