Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bandpass butterworth filter frequencies in scipy

I'm designing a bandpass filter in scipy following the cookbook. However, if I decrecrease the filtering frequencies too much I end up with garbage at high order filters. What am I doing wrong?

from scipy.signal import butter, lfilter

def butter_bandpass(lowcut, highcut, fs, order=5):
    nyq = 0.5 * fs
    low = lowcut / nyq
    high = highcut / nyq
    b, a = butter(order, [low, high], btype='band')
    return b, a

if __name__ == "__main__":
    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.signal import freqz  
    # Sample rate and desired cutoff frequencies (in Hz).
    fs = 25
    # Plot the frequency response for a few different orders.
    plt.figure(1)
    plt.clf()
    for order in [1, 3, 5, 6, 9]:
        b, a = butter_bandpass(0.5, 4, fs, order=order)
        w, h = freqz(b, a, worN=2000)#np.logspace(-4, 3, 2000))
        plt.semilogx((fs * 0.5 / np.pi) * w, abs(h), label="order = %d" % order)  
    plt.xlabel('Frequency (Hz)')
    plt.ylabel('Gain')
    plt.grid(True)
    plt.legend(loc='best')

    plt.figure(2)
    plt.clf()
    for order in [1, 3, 5, 6, 9]:
        b, a = butter_bandpass(0.05, 0.4, fs, order=order)
        w, h = freqz(b, a, worN=2000)#np.logspace(-4, 3, 2000))
        plt.semilogx((fs * 0.5 / np.pi) * w, abs(h), label="order = %d" % order)  
    plt.xlabel('Frequency (Hz)')
    plt.ylabel('Gain')
    plt.grid(True)
    plt.legend(loc='best')

    plt.show()

fs = 25, low = 0.5, high = 4fs = 25, low = 0.05, high = 0.4

Update: the issue was discussed and apparently solved on Scipy 0.14. However, the plot still looks really bad after Scipy update. What's wrong?

After Scipy 0.14, even worse

like image 453
Fra Avatar asked Feb 18 '14 18:02

Fra


People also ask

What is the frequency response of Butterworth filter?

The frequency response of the Butterworth filter is maximally flat (i.e. has no ripples) in the passband and rolls off towards zero in the stopband. When viewed on a logarithmic Bode plot, the response slopes off linearly towards negative infinity.

Is Butterworth filter a bandpass filter?

The Butterworth and Chebyshev Type II filters have flat passbands and wide transition bands. The Chebyshev Type I and elliptic filters roll off faster but have passband ripple. The frequency input to the Chebyshev Type II design function sets the beginning of the stopband rather than the end of the passband.

How do you apply a bandpass filter in Python?

To generate the filter coefficients for a bandpass filter, give butter() the filter order, the cutoff frequencies Wn=[lowcut, highcut] , the sampling rate fs (expressed in the same units as the cutoff frequencies) and the band type btype="band" .

What is the cut off frequency of Butterworth filter with a pass band gain?

Third-order Butterworth Low Pass Filter and finally our circuit of the third-order low pass Butterworth Filter with a cut-off corner frequency of 284 rads/s or 45.2Hz, a maximum pass band gain of 0.5dB and a minimum stop band gain of 20dB is constructed as follows.


1 Answers

  1. Don't use b, a = butter for high-order filters, whether in Matlab or SciPy or Octave. Transfer function format has numerical stability problems, because some of the coefficients are very large while others are very small. This is why we changed the filter design functions to use zpk format internally. To see the benefits of this, you need to use z, p, k = butter(output='zpk') and then work with poles and zeros instead of numerator and denominator.
  2. Don't do high-order digital filters in a single stage. This is a bad idea no matter what software or hardware you're implementing them on. Typically it's best to break them up into second-order sections. In Matlab, you can use zp2sos to generate these automatically. In SciPy, you can use sos = butter(output='sos') and then filter using sosfilt() or sosfiltfilt(). This is the recommended way to filter for most applications.
like image 90
endolith Avatar answered Sep 17 '22 11:09

endolith