Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Digital Band Pass Butterworth Filter in Python
A Band Pass Filter is a filter that passes frequencies within a specific range and rejects frequencies outside this range. The Butterworth band pass filter is designed to have the flattest possible frequency response in the pass band, making it ideal for applications requiring minimal ripple.
Filter Specifications
The following specifications define a typical digital band pass Butterworth filter:
Sampling rate: 40 kHz
Pass band edge frequencies: 1400 Hz to 2100 Hz
Stop band edge frequencies: 1050 Hz to 2450 Hz
Pass band ripple: 0.4 dB
Minimum stop band attenuation: 50 dB
Implementation Steps
To implement a digital band pass Butterworth filter, follow these steps:
Step 1 Define the sampling frequency fs, lower cutoff frequency f1, upper cutoff frequency f2, and filter order. Higher order filters provide steeper roll-off but may cause phase distortion.
Step 2 Calculate normalized frequencies using the formula:
$\mathrm{wn = 2 * fn / fs}$
Step 3 Design the filter using scipy.signal.butter() with btype='band'.
Step 4 Apply the filter using scipy.signal.filtfilt() for zero-phase filtering.
Example Implementation
Here's a complete implementation of a digital band pass Butterworth filter:
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import butter, filtfilt
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 = filtfilt(b, a, data)
return y
# Signal parameters
fs = 1000 # Sampling frequency
t = np.arange(0, 1, 1/fs) # Time vector
# Create test signal with multiple frequencies
f1, f2, f3 = 10, 50, 120 # Frequencies
signal = np.sin(2*np.pi*f1*t) + np.sin(2*np.pi*f2*t) + np.sin(2*np.pi*f3*t)
# Filter parameters
lowcut = 40 # Lower cutoff frequency
highcut = 80 # Upper cutoff frequency
order = 4 # Filter order
# Apply bandpass filter
filtered_signal = butter_bandpass_filter(signal, lowcut, highcut, fs, order)
print("Original signal length:", len(signal))
print("Filtered signal length:", len(filtered_signal))
print("First 10 filtered values:", filtered_signal[:10])
Original signal length: 1000 Filtered signal length: 1000 First 10 filtered values: [-0.05566882 0.03204148 0.11101057 0.17468979 0.2180157 0.23789154 0.23348367 0.20630279 0.16010043 0.10302296]
Visualization
Let's visualize the original and filtered signals to see the effect of the band pass filter:
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import butter, filtfilt
def butter_bandpass_filter(data, lowcut, highcut, fs, order=5):
nyq = 0.5 * fs
low = lowcut / nyq
high = highcut / nyq
b, a = butter(order, [low, high], btype='band')
y = filtfilt(b, a, data)
return y
# Create signal with three frequency components
fs = 1000
t = np.arange(0, 1, 1/fs)
f1, f2, f3 = 10, 50, 120
signal = np.sin(2*np.pi*f1*t) + np.sin(2*np.pi*f2*t) + np.sin(2*np.pi*f3*t)
# Apply bandpass filter (passes only 50 Hz component)
filtered = butter_bandpass_filter(signal, 40, 80, fs, order=4)
# Display comparison
plt.figure(figsize=(12, 6))
plt.subplot(2, 1, 1)
plt.plot(t[:200], signal[:200], 'b-', label='Original (10Hz + 50Hz + 120Hz)')
plt.title('Original Signal')
plt.xlabel('Time [s]')
plt.ylabel('Amplitude')
plt.legend()
plt.grid(True)
plt.subplot(2, 1, 2)
plt.plot(t[:200], filtered[:200], 'r-', label='Filtered (40-80 Hz passband)')
plt.title('Band Pass Filtered Signal')
plt.xlabel('Time [s]')
plt.ylabel('Amplitude')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
Key Parameters
Order: Higher values provide sharper cutoff but more phase distortion
Cutoff frequencies: Define the passband range
Sampling frequency: Must be at least twice the highest frequency of interest
filtfilt(): Provides zero-phase filtering by filtering forward and backward
Conclusion
Digital band pass Butterworth filters effectively isolate frequency components within a specified range while maintaining flat response in the passband. Use scipy.signal.butter() with filtfilt() for zero-phase filtering to preserve signal timing characteristics.
