Я хочу убрать тренд сигнала с помощью полосового фильтра. Я использовал фильтр Баттерворта с FL = 0,1 Гц и FH = 20 Гц в Python, но после применения этого полосового фильтра я заметил большой всплеск в начале сигнала без тренда. к чему этот шип? и как убрать этот шип в питоне?
скачать "data1.csv" можно по этой ссылке.
from scipy.signal import butter, lfilter
from numpy import genfromtxt
import numpy as np
import matplotlib.pyplot as plt
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 = lfilter(b, a, data)
return y
BP_without_NaN = genfromtxt('data1.csv', delimiter=',')
framerate=1024
# detrending [0.1Hz 20Hz]
OMW = butter_bandpass_filter(data = BP_without_NaN, lowcut = 0.1, highcut = 20 , fs = framerate, order = 3)
# plot OMW
time = np.linspace(0, len(OMW)/framerate ,len(OMW))
plt.plot(time, OMW)
plt.show()
При применении фильтра Баттерворта (или любого другого БИХ-фильтра) каждая выходная выборка вычисляется на основе предыдущих выходных выборок.
y[n] = b0 * x[n] + b1 * x[n-1] + ... + bk * x[n-k]
- a1 * y[n-1] + ... + ak * y[n-k]
Это создает проблему для того, как запустить фильтр в начале сигнала, поскольку еще не были вычислены выходные выборки. Типичный способ справиться с этим - предположить, что все выходные данные в отрицательные моменты времени n < 0 равны нулю, или, что то же самое, концептуально экстраполировать входные данные как нулевые. Этот подход с нулевой инициализацией — это то, что scipy.signal.lfilter делает по умолчанию.
Однако такой подход не всегда удобен. Если входной сигнал не начинается близко к нулю, то экстраполяция нулей вносит в сигнал искусственный скачок или разрыв скачка, а выходной сигнал начинается с нежелательного переходного процесса, реакции фильтра на этот искусственный скачок.
Глядя на ваши связанные данные, входные данные начинаются с нескольких сотен выборок, равных 154. Это объясняет большой всплеск в начале вашего графика. В основном вы можете удалить всплеск, изменив инициализацию фильтра. Используйте scipy.signal.lfilter_zi для вычисления начальных условий для lfilter для установившегося состояния переходной характеристики со значением 154:
zi = lfilter_zi(b, a) * data[0]
Затем используйте его с lfilter как y, _ = lfilter(b, a, data, zi=zi)
. Вот что я получаю с этим изменением:
Добро пожаловать в СО! Что вы пробовали до сих пор / пожалуйста, добавьте минимальный, полный и проверяемый пример вашего кода, чтобы мы могли вам помочь!