selcal/scripts/filters.py

62 lines
1.9 KiB
Python

import numpy as np
from scipy.signal import butter, lfilter, decimate
def anti_alias(data, sample_rate, max_frequency, order=5):
FILTER_HEADROOM = 1.2
nyquist_rate = 2 * max_frequency
downsample_factor = 1
if sample_rate > nyquist_rate:
filtered_data = lowpass_filter(
data,
max_frequency * FILTER_HEADROOM,
sample_rate,
order
)
downsample_factor = int(sample_rate / nyquist_rate)
filtered_data = decimate(filtered_data, downsample_factor)
sample_rate = sample_rate // downsample_factor
else:
filtered_data = data
return filtered_data, sample_rate, downsample_factor
def smoothing_filter(data, window_size=256, mode='same'):
window = np.ones(window_size) / window_size
return np.convolve(data, window, mode=mode)
# Stolen from selcald
def note(freq, length, amp=1.0, rate=44100):
if freq == 0:
data = np.zeros(int(length * rate))
else:
t = np.linspace(0, length, int(length * rate))
data = np.sin(2 * np.pi * freq * t) * amp
return data
# These originally came from https://scipy.github.io/old-wiki/pages/Cookbook/ButterworthBandpass,
# but they've been copied around the internet so many times that ChatGPT now produces them verbatim.
def butter_bandpass(lowcut, highcut, fs, order=5):
nyquist = 0.5 * fs
low = lowcut / nyquist
high = highcut / nyquist
b, a = butter(order, [low, high], btype='band')
return b, a
def bandpass_filter(data, lowcut, highcut, fs, order=5):
b, a = butter_bandpass(lowcut, highcut, fs, order=order)
y = lfilter(b, a, data)
return y
def butter_lowpass(cutoff, fs, order=5):
nyquist = 0.5 * fs
normal_cutoff = cutoff / nyquist
b, a = butter(order, normal_cutoff, btype='low', analog=False)
return b, a
def lowpass_filter(data, cutoff, fs, order=5):
b, a = butter_lowpass(cutoff, fs, order=order)
y = lfilter(b, a, data)
return y