data science/signal processing
Filters
꼰대코더
2025. 10. 16. 00:04
Low Pass Filter
import numpy as np
import scipy.signal
import scipy.io.wavfile
import matplotlib.pyplot as plt
def lowpass(data: np.ndarray, cutoff: float, sample_rate: float, poles: int = 5):
sos = scipy.signal.butter(poles, cutoff, 'lowpass', fs=sample_rate, output='sos')
filtered_data = scipy.signal.sosfiltfilt(sos, data)
return filtered_data
# Load sample data from a WAV file
sample_rate, data = scipy.io.wavfile.read('ecg.wav')
times = np.arange(len(data))/sample_rate
# Apply a 50 Hz low-pass filter to the original data
filtered = lowpass(data, 50, sample_rate)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 3), sharex=True, sharey=True)
ax1.plot(times, data)
ax1.set_title("Original Signal")
ax1.margins(0, .1)
ax1.grid(alpha=.5, ls='--')
ax2.plot(times, filtered)
ax2.set_title("Low-Pass Filter (50 Hz)")
ax2.grid(alpha=.5, ls='--')
plt.tight_layout()
plt.show()

High Pass Filter
import numpy as np
import scipy.signal
import scipy.io.wavfile
import matplotlib.pyplot as plt
def highpass(data: np.ndarray, cutoff: float, sample_rate: float, poles: int = 5):
sos = scipy.signal.butter(poles, cutoff, 'highpass', fs=sample_rate, output='sos')
filtered_data = scipy.signal.sosfiltfilt(sos, data)
return filtered_data
# Load sample data from a WAV file
sample_rate, data = scipy.io.wavfile.read('ecg.wav')
times = np.arange(len(data))/sample_rate
# Apply a 20 Hz high-pass filter to the original data
filtered = highpass(data, 20, sample_rate)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 3), sharex=True, sharey=True)
ax1.plot(times, data)
ax1.set_title("Original Signal")
ax1.margins(0, .1)
ax1.grid(alpha=.5, ls='--')
ax2.plot(times, filtered)
ax2.set_title("High-Pass Filter (20 Hz)")
ax2.grid(alpha=.5, ls='--')
plt.tight_layout()
plt.show()

Band Pass Filter
import numpy as np
import scipy.signal
import scipy.io.wavfile
import matplotlib.pyplot as plt
def bandpass(data: np.ndarray, edges: list[float], sample_rate: float, poles: int = 5):
sos = scipy.signal.butter(poles, edges, 'bandpass', fs=sample_rate, output='sos')
filtered_data = scipy.signal.sosfiltfilt(sos, data)
return filtered_data
# Load sample data from a WAV file
sample_rate, data = scipy.io.wavfile.read('ecg.wav')
times = np.arange(len(data))/sample_rate
# Apply a 10-50 Hz high-pass filter to the original data
filtered = bandpass(data, [10, 50], sample_rate)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 3), sharex=True, sharey=True)
ax1.plot(times, data)
ax1.set_title("Original Signal")
ax1.margins(0, .1)
ax1.grid(alpha=.5, ls='--')
ax2.plot(times, filtered)
ax2.set_title("Band-Pass Filter (10-50 Hz)")
ax2.grid(alpha=.5, ls='--')
plt.tight_layout()
plt.show()

Low Pass Cutoff with different Frequencies
import numpy as np
import scipy.signal
import scipy.io.wavfile
import matplotlib.pyplot as plt
# Load sample data from a WAV file
sample_rate, data = scipy.io.wavfile.read('ecg.wav')
times = np.arange(len(data))/sample_rate
# Plot the original signal
plt.plot(times, data, '.-', alpha=.5, label="original signal")
# Plot the signal low-pass filtered using different cutoffs
for cutoff in [10, 20, 30, 50]:
sos = scipy.signal.butter(5, cutoff, 'lowpass', fs=sample_rate, output='sos')
filtered = scipy.signal.sosfiltfilt(sos, data)
plt.plot(times, filtered, label=f"low-pass {cutoff} Hz")
plt.legend()
plt.grid(alpha=.5, ls='--')
plt.axis([0.35, 0.5, None, None])
plt.show()

Filter using Convolution
import numpy as np
import scipy.io.wavfile
import matplotlib.pyplot as plt
# Load sample data from a WAV file
sample_rate, data = scipy.io.wavfile.read('ecg.wav')
times = np.arange(len(data))/sample_rate
# create a Hanning kernel 1/50th of a second wide
kernel_width_seconds = 1.0/50
kernel_size_points = int(kernel_width_seconds * sample_rate)
kernel = np.hanning(kernel_size_points)
# normalize the kernel
kernel = kernel / kernel.sum()
# Create a filtered signal by convolving the kernel with the original data
filtered = np.convolve(kernel, data, mode='valid')
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(10, 3))
ax1.plot(np.arange(len(kernel))/sample_rate, kernel, '.-')
ax1.set_title("Kernel (1/50 sec wide)")
ax1.grid(alpha=.5, ls='--')
ax2.plot(np.arange(len(data))/sample_rate, data)
ax2.set_title("Original Signal")
ax2.margins(0, .1)
ax2.grid(alpha=.5, ls='--')
ax3.plot(np.arange(len(filtered))/sample_rate, filtered)
ax3.set_title("Convolved Signal")
ax3.margins(0, .1)
ax3.grid(alpha=.5, ls='--')
plt.tight_layout()
plt.show()
