I am trying to port some code from MATLAB to python. The goal is to use Butterworth filter (4th order, bandpass) API and convert it to second-order sections. I get the same output between MATLAB and python for the Butterworth filter coefficients but not for zp2sos
/zpk2sos
.
Using MATLAB R2019b, python 3.7, scipy 1.6.3.
Below is MATLAB code with output:
fs = 8000;
f1 = 200;
f2 = 400;
[z,p,k] = butter(4, [f1/(fs/2) f2/(fs/2)]);
[sos,gain] = zp2sos(z,p,k);
MATLAB Output
z = 1 1 1 1 -1 -1 -1 -1
p = 0.9173+0.2885i 0.9173-0.2885i 0.8934+0.2214i 0.8934-0.2214i
0.9237+0.1704i 0.9237-0.1704i 0.9671+0.1555i 0.9671-0.1555i
k = 3.1239e-05
sos = 1.0000 2.0000 1.0000 1.0000 -1.7867 0.8471
1.0000 2.0000 1.0000 1.0000 -1.8475 0.8823
1.0000 -2.0000 1.0000 1.0000 -1.8345 0.9246
1.0000 -2.0000 1.0000 1.0000 -1.9341 0.9594
My python code looks like this:
from scipy import signal
fs = 8000
f1 = 200
f2 = 400
z, p, k = signal.butter(4, [f1/(fs/2), f2/(fs/2)], 'bandpass', output='zpk')
sos = signal.zpk2sos(z, p, k)
Python Output:
z= [ 1.+0.j 1.+0.j 1.+0.j 1.+0.j -1.+0.j -1.+0.j -1.+0.j -1.+0.j]
p = [0.967057-0.15545929j 0.92374003-0.17042575j 0.92374003+0.17042575j 0.967057+0.15545929j
0.91727345+0.28846481j 0.89335425+0.22144318j 0.89335425-0.22144318j 0.91727345-0.28846481j]
Output ordering for 'p' is different than MATLAB but all values account for. Not sure if it matters?
k = 3.123897691708261e-05
sos=
[[ 3.12389769e-05 6.24779538e-05 3.12389769e-05 1.00000000e+00 -1.78670849e+00 8.47118894e-01]
[ 1.00000000e+00 2.00000000e+00 1.00000000e+00 1.00000000e+00 -1.84748005e+00 8.82340575e-01]
[ 1.00000000e+00 -2.00000000e+00 1.00000000e+00 1.00000000e+00 -1.83454690e+00 9.24602526e-01]
[ 1.00000000e+00 -2.00000000e+00 1.00000000e+00 1.00000000e+00 -1.93411400e+00 9.59366836e-01]]
I am not sure why the first 3 coefficients in python are always different than that of MATLAB. I have tried few different inputs. Unfortunately, I do not have experience with DSP or with scipy to understand what this means or how to debug this. I cannot change the MATLAB code but need something equivalent in python. Any help is appreciated.
k
is just incorporated into the first second-order section, which is justk*[1,2,1]
. $\endgroup$