def test_eda_clean(): sampling_rate = 1000 eda = nk.eda_simulate(duration=30, sampling_rate=sampling_rate, scr_number=6, noise=0.01, drift=0.01, random_state=42) clean = nk.eda_clean(eda, sampling_rate=sampling_rate) assert len(clean) == len(eda) # Comparison to biosppy (https://github.com/PIA-Group/BioSPPy/blob/master/biosppy/signals/eda.py) eda_biosppy = nk.eda_clean(eda, sampling_rate=sampling_rate, method="biosppy") original, _, _ = biosppy.tools.filter_signal(signal=eda, ftype='butter', band='lowpass', order=4, frequency=5, sampling_rate=sampling_rate) original, _ = biosppy.tools.smoother(signal=original, kernel='boxzen', size=int(0.75 * sampling_rate), mirror=True) # pd.DataFrame({"our":eda_biosppy, "biosppy":original}).plot() assert np.allclose((eda_biosppy - original).mean(), 0, atol=1e-5)
def extract_eda_features(eda: List[float], sampling_rate) -> pd.DataFrame: # eda = MinMaxScaler().fit_transform(np.array(eda).reshape(-1, 1)).ravel() HIGHCUT_FREQUENCY = 5 # defaults as BioSPPy nyquist_freq = 2 * HIGHCUT_FREQUENCY / sampling_rate # Normalize frequency to Nyquist Frequency (Fs/2) if 0 < nyquist_freq < 1: eda = nk.eda_clean(eda, sampling_rate=sampling_rate, method='biosppy') eda_decomposed = nk.eda_phasic(eda, sampling_rate=sampling_rate) scr_peaks, info = nk.eda_peaks(eda_decomposed['EDA_Phasic'], sampling_rate=sampling_rate) signals = pd.DataFrame({"EDA_Raw": eda}) signals = pd.concat([signals, eda_decomposed, scr_peaks], axis=1) return signals
def eda_process(raw_signal, exper, path=None): """ 皮电信号处理,输入未处理的皮电信号,输出scr监测后的图像。 :param raw_signal: 未处理的皮电信号 :param exper: 第几次实验 :param path: 文件保存的地址 :return: 无 """ # 降采样 downsize_rate = 100 down_size = 2000 / downsize_rate # raw_signal = np.loadtxt(filepath) raw_signal = raw_signal[::int(down_size)] # sampling_rate = int(2000 / down_size) # plt.plot(raw_signal) # plt.show() # 带通滤波与平滑处理 eda_cleaned = nk.eda_clean(raw_signal, sampling_rate=downsize_rate, method="biosppy") # 相位成分提取 # eda = nk.eda_phasic(eda_cleaned, sampling_rate=sampling_rate, method='median') # eda_phasic = eda["EDA_Phasic"].values # plt.plot(eda_phasic) # plt.show() # 微分与卷积处理 info = nk.eda_findpeaks(eda_cleaned, sampling_rate=downsize_rate, method="qz") features = [info["SCR_Onsets"], info["SCR_Offsets"], info['SCR_Peaks'], info['eda_phasic_diffandsmoothed']] # 时间轴 length = len(eda_cleaned) T = (length - 1) / downsize_rate ts = np.linspace(0, T, length, endpoint=True) # 绘图 # bplt.plot_eda_qz(ts=ts, raw=raw_signal, filtered=eda_cleaned, onsets=features[0], # offsets=features[1], peaks=features[2], eda_phasic_diffandsmoothed=features[3], show=True, # path=filepath, stimulus=False) # 保存文件名 # scr监测与绘图输出保存 if path is not None: plot_scr_v2(ts=ts, sampling_rate=downsize_rate, filtered=eda_cleaned, onsets=features[0], offsets=features[1], exper=exper, show=False, path=path) else: plot_scr_v2(ts=ts, sampling_rate=downsize_rate, filtered=eda_cleaned, onsets=features[0], offsets=features[1], exper=exper, show=False)
def standardized_eda_process(eda_signal, sampling_rate, method="neurokit"): eda_cleaned = nk.eda_clean(eda_signal, sampling_rate=sampling_rate, method=method) eda_cleaned_standardized = nk.standardize( eda_cleaned) # only change to eda_process eda_decomposed = nk.eda_phasic(eda_cleaned_standardized, sampling_rate=sampling_rate) peak_signal, info = nk.eda_peaks(eda_decomposed["EDA_Phasic"].values, sampling_rate=sampling_rate, method=method, amplitude_min=0.1) signals = pd.DataFrame({ "EDA_Raw": eda_signal, "EDA_Clean": eda_cleaned, "EDA_Standardized": eda_cleaned_standardized }) signals = pd.concat([signals, eda_decomposed, peak_signal], axis=1) return signals, info