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.

Updated on: 2026-03-27T15:54:52+05:30

2K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements