简体   繁体   中英

Butterworth filter in python

I'm trying to use a Butterworth filter in Python as described in this thread with these functions:

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


def butter_bandpass_filter(data, lowcut, highcut, fs, order=5):
    b, a = butter_bandpass(lowcut, highcut, fs, order=order)
    y = lfilter(b, a, data)
    return y

The output of the FFT of my data without applying the filter gives the following plot:

在此处输入图片说明

However, after applying the filter above with:

lowcut = 1.0
highcut = 50.0
x2_Vtcr = butter_bandpass_filter(x_Vtcr, lowcut, highcut, fs, order=4)

where fs is the sampling frequency (1000 in my case) I get as FFT:

在此处输入图片说明

It looks like the filter shifts the frequency to the left and I don't get the peak where it should be. Any idea as to why this is happening?

Just in case I place where the data file (second column) . The DC is quite strong so after FFT the first element should not be included in the plot.

Thank you!

The 2 functions above seem to work fine here. This is an example of a white noise signal sampled at your fs=250 , and filtered with the two functions you mention, with a passband between 1Hz and 50 Hz as you do:

from numpy import random, arange
from numpy.fft import rfft, rfftfreq

fs = 250.
t = arange(0., 30., 1 / fs)
x_Vtcr = random.randn(len(t))

hat_x_Vtcr = rfft(x_Vtcr)
freqs = rfftfreq(x_Vtcr.size, 1 / fs)
plt.plot(freqs, abs(hat_x_Vtcr), 'b')

lowcut, highcut = 1.0, 50.0
x2_Vtcr = butter_bandpass_filter(x_Vtcr, lowcut, highcut, fs, order=4)

hat_x2_Vtcr = rfft(x2_Vtcr)
plt.plot(freqs, abs(hat_x2_Vtcr), 'r')

The resulting PSD is fine with me (red is the filtered one): 在此处输入图片说明

I guess your error is somewhere else? Please compare your code with the above snippet. You may also want to read THIS for next time.

EDIT:reply to the comment.

It does indeed work also with your data. I did:

datafile=loadtxt('V.dat')
x_Vtcr=datafile[:,1]
x_Vtcr-=x_Vtcr.mean()

and then I ran the above script, without the line on which I generate the x_Vtcr data of course. The resulting filtered output follows: 在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM