1

I am trying to apply a Butterworth filter as in this great reply How to implement band-pass Butterworth filter with Scipy.signal.butter. However, when I use the functions from there, the result seems to be the wrong way round (x(-1)):

FIGURE: applied Butterworth filter

What is wrong? (I assume this is 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


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

x=np.array(range(100))
y1=np.array([math.sin(2*3.14*xx/3) for xx in x])
y2=np.array([2*math.sin(2*3.14*xx/30) for xx in x])
y0=x*0.05
y=y1+y2+y0

lowcut=1./10000000.
highcut=1./20.

plt.figure(3)
plt.clf()

plt.plot(x, y, label='Noisy signal',lw=2.5,color='blue')
plt.plot(x,y0,ls='--',color='blue')
plt.plot(x,y1,ls='--',color='blue')
plt.plot(x,y2,ls='--',color='blue')

ysm = butter_bandpass_filter(y, lowcut, highcut, fs, order=6)

plt.plot(x, ysm, label='Filtered signal',lw=2.5,color='red')
plt.grid(True)
plt.axis('tight')
plt.legend(loc='upper left')

plt.show()
Community
  • 1
  • 1
sabine
  • 31
  • 2

1 Answers1

1

Nothing is wrong. What you are seeing is the normal phase shift created by an IIR filter.

If that phase shift is unacceptable, one option is to change this line:

y = lfilter(b, a, data)

to

y = filtfilt(b, a, data)

and add filtfilt to the names imported from scipy.signal. filtfilt applies the same filter twice, once forward and once backward, so the phase shifts "cancel". If you use filtfilt, you can lower the order of the filter because you are applying it twice.

Another option is to use a FIR filter instead of an IIR filter. Questions about the behavior of filters are probably best asked over at dsp.stackexchange.com.

Warren Weckesser
  • 110,654
  • 19
  • 194
  • 214
  • Hi Warren, thanks a lot for the swift reply! That makes sense, it seems that I need to look further into how they work. With filtfilt and order=3 the filtered signal looks in phase but shifted and rescaled (mean<-50, min<-150), I wonder if that is also expected (and how I could work around) but I will think a bit more and if I still don't understand look at stackexchange... – sabine Nov 18 '15 at 00:55