我想使用solve_ivp从原始PPG信号中获取二阶导数,如何将信号值输入到函数中?
我有一个原始信号的数据集(熊猫),信号振幅为“ y”值。 “ x”值或时间值是根据采样率(即1000Hz)计算得出的,它可以将“ x”值作为样本或转换为时间单位。我认为我需要使用resolve_ivp函数,但是可能有不同的方法。我已经尝试过np.gradient,但是结果与预期不符。在尝试获得二阶导数之前,我使用0.25-3Hz的Butterworth滤波器带通来获得干净的初始信号,并在一阶导数之后再次进行滤波。
以下是原始信号的链接:https://www.dropbox.com/s/4mhz3tphdzcp4e2/2_1.txt?dl=0
import neurokit as nk
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from scipy.signal import butter, lfilter, lfilter_zi
import scipy as sc
from scipy import signal
plt.rcParams['figure.figsize'] = [20, 5]
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='bandpass')
return b, a
def butter_bandpass_filter_zi(data, lowcut, highcut, fs, order=5):
b, a = butter_bandpass(lowcut, highcut, fs, order=order)
zi = lfilter_zi(b, a)
y,zo = lfilter(b, a, data, zi=zi*data[0])
return y
filename = "0_subject/2_1.txt"
data = pd.read_csv(filename, header=None, sep="\t")
data = data.transpose()
data.plot()
plt.show()
fs = 1000.0
lowcut = 0.15
highcut = 3.0
f0 = 600
T = (len(data)-1)
nsamples = len(data)
# t = np.linspace(0, T, nsamples, endpoint=False)
t = np.linspace(0, T, nsamples, endpoint=False) / fs
y = np.array(data)[:, 0]
plt.figure(2)
plt.clf()
plt.plot(t, y, label='Noisy signal')
x = butter_bandpass_filter_zi(y, lowcut, highcut, fs, order=1)
# print(x)
plt.figure(3)
plt.plot(t, x, label='Filtered signal (%g Hz)' % f0)
plt.xlabel('time (seconds)')
# plt.hlines([-a, a], 0, T, linestyles = '--')
plt.grid(True)
plt.axis('tight')
plt.legend(loc='upper left')
plt.show()
first_derivative = np.gradient(x)
first_derivative_filter = butter_bandpass_filter_zi(first_derivative, lowcut, highcut, fs, order=1)
plt.figure(4)
plt.plot(t, first_derivative_filter)
plt.show()
second_derivative = np.gradient(first_derivative_filter)
second_derivative_filter = butter_bandpass_filter_zi(first_derivative_filter, lowcut, highcut, fs, order=1)
plt.figure(5)
plt.plot(t, second_derivative_filter)
plt.show()
这是我用solve_ivp尝试过的方法,它也给出了错误的结果:
def second_der_func(t, y): return y
sol = solve_ivp(second_der_func, [t[0], len(t)-1], [x[0]])
print(sol.y[0])
plt.plot(sol.t, sol.y[0])
plt.show()
我应该得到图像上的二阶导数曲线: