This cookbook recipe demonstrates the use of scipy.signal.butter to create a bandpass Butterworth filter. scipy.signal.freqz is used to compute the frequency response, and scipy.signal.lfilter is used to apply the filter to a signal. (This code was originally given in an answer to a question at stackoverflow.com.)

```   1
2 from scipy.signal import butter, lfilter
3
4
5 def butter_bandpass(lowcut, highcut, fs, order=5):
6     nyq = 0.5 * fs
7     low = lowcut / nyq
8     high = highcut / nyq
9     b, a = butter(order, [low, high], btype='band')
10     return b, a
11
12
13 def butter_bandpass_filter(data, lowcut, highcut, fs, order=5):
14     b, a = butter_bandpass(lowcut, highcut, fs, order=order)
15     y = lfilter(b, a, data)
16     return y
17
18
19 if __name__ == "__main__":
20     import numpy as np
21     import matplotlib.pyplot as plt
22     from scipy.signal import freqz
23
24     # Sample rate and desired cutoff frequencies (in Hz).
25     fs = 5000.0
26     lowcut = 500.0
27     highcut = 1250.0
28
29     # Plot the frequency response for a few different orders.
30     plt.figure(1)
31     plt.clf()
32     for order in [3, 6, 9]:
33         b, a = butter_bandpass(lowcut, highcut, fs, order=order)
34         w, h = freqz(b, a, worN=2000)
35         plt.plot((fs * 0.5 / np.pi) * w, abs(h), label="order = %d" % order)
36
37     plt.plot([0, 0.5 * fs], [np.sqrt(0.5), np.sqrt(0.5)],
38              '--', label='sqrt(0.5)')
39     plt.xlabel('Frequency (Hz)')
40     plt.ylabel('Gain')
41     plt.grid(True)
42     plt.legend(loc='best')
43
44     # Filter a noisy signal.
45     T = 0.05
46     nsamples = T * fs
47     t = np.linspace(0, T, nsamples, endpoint=False)
48     a = 0.02
49     f0 = 600.0
50     x = 0.1 * np.sin(2 * np.pi * 1.2 * np.sqrt(t))
51     x += 0.01 * np.cos(2 * np.pi * 312 * t + 0.1)
52     x += a * np.cos(2 * np.pi * f0 * t + .11)
53     x += 0.03 * np.cos(2 * np.pi * 2000 * t)
54     plt.figure(2)
55     plt.clf()
56     plt.plot(t, x, label='Noisy signal')
57
58     y = butter_bandpass_filter(x, lowcut, highcut, fs, order=6)
59     plt.plot(t, y, label='Filtered signal (%g Hz)' % f0)
60     plt.xlabel('time (seconds)')
61     plt.hlines([-a, a], 0, T, linestyles='--')
62     plt.grid(True)
63     plt.axis('tight')
64     plt.legend(loc='upper left')
65
66     plt.show()
```

The plots generated by the above code:

Cookbook/ButterworthBandpass (last edited 2012-09-03 15:45:46 by WarrenWeckesser)