I'm trying to port some MATLAB code to Python and am running into some strange behaviour. I am implementing a 5th order Butterworth bandpass filter. The sampling rate is 30 Hz.
Running MATLAB R2012b, Spyder 2.2.0 with Python 2.7, SciPy 0.12.0 on Windows 7 x64.
In MATLAB:
[b,a] = butter(5, [0.75*2/30, 5.0*2/30], 'bandpass');
y = filtfilt(b, a, input_signal)
This is the raw signal:
and the filtered signal:
and its power spectrum:
which makes sense since the normalized bandpass frequencies are 0.05 - 0.33.
I found before that SciPy's butter function does not give the same coefficients as MATLAB so I exported the filter coefficients from MATLAB to Python using hdf5write (see here: https://stackoverflow.com/questions/7117797/export-matlab-variable-to-text-for-python-usage)
In Python:
y = signal.filtfilt(b, a, input_signal, padtype = None)
and the output is:
and its power spectrum:
I used padtype = None because by default it is padtype = 'odd'. However, I've tried all the different padding options and they all look more or less the same.
I'm not entirely sure what's going wrong...any help would be greatly appreciated.
EDIT: Added graph for padtype = "odd" and b and a filter coefficients used
Signal with padtype = "odd":
Seems like there is some underlying signal so I don't think it's the impulse response although that large transient at the beginning is strange.
Python filter coefficients (5th order Butterworth filter):
passband = [0.75*2/30, 5.0*2/30]
b, a = scipy.signal.butter(5, passband, 'bandpass')
b, a are arrays of type float64.
b = array([ 5.49209388e-03, 0.00000000e+00, -2.74604694e-02,
-1.97776791e-17, 5.49209388e-02, 2.47220989e-17,
-5.49209388e-02, -1.97776791e-17, 2.74604694e-02,
0.00000000e+00, -5.49209388e-03])
a = array([ 1. , -6.52098852, 19.50384534, -35.47189804,
43.65758795, -38.07760914, 23.83047021, -10.55670367,
3.16710078, -0.58122912, 0.04945954])
MATLAB filter coefficients
b = 0.0055, 0, -0.0275, 0, 0.0549, 0, -0.0549, 0, 0.0275, 0, -0.0055
a = 1.0000, -6.5210, 19.5038, -35.4719, 43.6576, -38.0776, 23.8305,
-10.5567, 3.1671, -0.5812, 0.0495
Turns out the coefficients are about the same, I believe the issues I had before were due to the frequency being much higher (coefficients must be generated differently in MATLAB and Python).
The input signal is a list of float32, although I've tried converting to array with numpy.array and the result is the same.
EDIT: More information about padtypes and Python vs. MATLAB
Python SciPy's filtfilt function includes a parameter called padtype which indicates the type of padding extended on both sides of the signal. This padding serves to reduce transients. Odd and even are descriptors of the type of symmetry these extensions have with the endpoints (http://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.filtfilt.html).
Some illustrations of the difference in padtypes:
padtype = "even"
padtype = "odd"
padtype = None
Based on the results, it appears that MATLAB uses odd padding (which is also the default for Python):
python
output looks like the impulse response. Do you have theinput_signal
in the right orientation? (i.e. should it be transposed?). Try settingaxis=0
oraxis=1
in the call tofiltfilt
. $\endgroup$a
andb
like this. $\endgroup$b
anda
in your question. Are they formatted correctly? I suspectpadtype='odd'
is the same as Matlab, since it's the default and Matlab docs say "filtfilt minimizes start-up and ending transients by matching initial conditions", but I'm not sure. $\endgroup$