Создание фильтра нижних частот в SciPy-понимание методов и блоков
Я пытаюсь фильтровать шумный сигнал сердечного ритма с помощью python. Поскольку частота сердечных сокращений никогда не должна быть около 220 ударов в минуту, я хочу отфильтровать весь шум выше 220bpm. Я преобразовал 220/минуту в 3,66666666 Герц, а затем преобразовал этот Герц в рад/С, чтобы получить 23,0383461 рад / сек.
частота дискретизации чипа, который принимает данные, составляет 30 Гц, поэтому я преобразовал это в рад/С, чтобы получить 188,495559 рад/С.
после поиска некоторых вещей в Интернете я нашел некоторые помазания для полосового фильтра, который я хотел сделать в низкочастотный. вот ссылка на полосовой код, поэтому я преобразовал его в это:
from scipy.signal import butter, lfilter
from scipy.signal import freqs
def butter_lowpass(cutOff, fs, order=5):
nyq = 0.5 * fs
normalCutoff = cutOff / nyq
b, a = butter(order, normalCutoff, btype='low', analog = True)
return b, a
def butter_lowpass_filter(data, cutOff, fs, order=4):
b, a = butter_lowpass(cutOff, fs, order=order)
y = lfilter(b, a, data)
return y
cutOff = 23.1 #cutoff frequency in rad/s
fs = 188.495559 #sampling frequency in rad/s
order = 20 #order of filter
#print sticker_data.ps1_dxdt2
y = butter_lowpass_filter(data, cutOff, fs, order)
plt.plot(y)
Я очень смущен этим, хотя, потому что я уверен, что функция масла принимает частоту среза и дискретизации в rad/s, но я, кажется, получаю странный выход. На самом деле В Гц?
во-вторых, какова цель этих двух строк:
nyq = 0.5 * fs
normalCutoff = cutOff / nyq
Я знаю что-то о нормализации но я думал, что Найквист был в 2 раза выше выборки, а не наполовину. И почему вы используете Найквиста в качестве нормализатора?
можно подробнее рассказать о том, как создавать фильтры с этими функциями?
Я построил фильтр с помощью
w, h = signal.freqs(b, a)
plt.plot(w, 20 * np.log10(abs(h)))
plt.xscale('log')
plt.title('Butterworth filter frequency response')
plt.xlabel('Frequency [radians / second]')
plt.ylabel('Amplitude [dB]')
plt.margins(0, 0.1)
plt.grid(which='both', axis='both')
plt.axvline(100, color='green') # cutoff frequency
plt.show()
и получил что явно не отключается при 23 рад / с
1 ответ:
несколько комментариев:
- The частота Найквиста - половина частоты дискретизации.
- вы работаете с регулярно отбираемыми данными, поэтому вам нужен цифровой фильтр, а не аналоговый фильтр. Это означает, что вы не должны использовать
analog=Trueв вызовеbutter, и вы должны использоватьscipy.signal.freqz(неfreqs) для генерации частотных характеристик.- одна из целей этих коротких функций полезности-позволить вам оставить все ваши частоты, выраженные В Гц. Вы не должны преобразовать в рад/сек. Как долго, как вы выражаете свои частоты с последовательным единиц, масштабирование в функции полезности заботится о нормализации для вас.
вот моя измененная версия вашего скрипта, а затем сюжет, который он генерирует.
import numpy as np from scipy.signal import butter, lfilter, freqz import matplotlib.pyplot as plt def butter_lowpass(cutoff, fs, order=5): nyq = 0.5 * fs normal_cutoff = cutoff / nyq b, a = butter(order, normal_cutoff, btype='low', analog=False) return b, a def butter_lowpass_filter(data, cutoff, fs, order=5): b, a = butter_lowpass(cutoff, fs, order=order) y = lfilter(b, a, data) return y # Filter requirements. order = 6 fs = 30.0 # sample rate, Hz cutoff = 3.667 # desired cutoff frequency of the filter, Hz # Get the filter coefficients so we can check its frequency response. b, a = butter_lowpass(cutoff, fs, order) # Plot the frequency response. w, h = freqz(b, a, worN=8000) plt.subplot(2, 1, 1) plt.plot(0.5*fs*w/np.pi, np.abs(h), 'b') plt.plot(cutoff, 0.5*np.sqrt(2), 'ko') plt.axvline(cutoff, color='k') plt.xlim(0, 0.5*fs) plt.title("Lowpass Filter Frequency Response") plt.xlabel('Frequency [Hz]') plt.grid() # Demonstrate the use of the filter. # First make some data to be filtered. T = 5.0 # seconds n = int(T * fs) # total number of samples t = np.linspace(0, T, n, endpoint=False) # "Noisy" data. We want to recover the 1.2 Hz signal from this. data = np.sin(1.2*2*np.pi*t) + 1.5*np.cos(9*2*np.pi*t) + 0.5*np.sin(12.0*2*np.pi*t) # Filter the data, and plot both the original and filtered signals. y = butter_lowpass_filter(data, cutoff, fs, order) plt.subplot(2, 1, 2) plt.plot(t, data, 'b-', label='data') plt.plot(t, y, 'g-', linewidth=2, label='filtered data') plt.xlabel('Time [sec]') plt.grid() plt.legend() plt.subplots_adjust(hspace=0.35) plt.show()

Comments