希尔伯特变换幅值包络无法在带通滤波后的脑电信号上绘制
EEG信号带通滤波后希尔伯特变换全为NaN的问题
问题描述
对脑电(EEG)信号执行带通滤波后,应用希尔伯特变换并取绝对值获取瞬时功率时出现异常:带通滤波后的信号显示正常,原始信号的希尔伯特变换结果也正常,但带通滤波信号经希尔伯特变换后得到的数组全为nan+nanj,无法正常显示结果。
可复现代码
import numpy as np from neurodsp.filt import filter_signal from scipy import signal import matplotlib.pyplot as plt Fs = 1024 LBP, HBP = 1, 100 Chan1 = np.loadtxt('SampleData') Chan1_BP = filter_signal(Chan1, Fs, 'bandpass', (LBP,HBP)) # 原始信号希尔伯特变换正常 analytical_signal = signal.hilbert(Chan1) amplitude_envelope = np.abs(analytical_signal) # 验证带通滤波信号正常 fig0 = plt.figure(figsize=(10, 8)) plt.plot(Chan1) plt.plot(Chan1_BP) fig1 = plt.figure(figsize=(10, 8)) plt.plot(Chan1) plt.plot(amplitude_envelope) # 带通滤波信号希尔伯特变换出现问题 analytical_signal = signal.hilbert(Chan1_BP) amplitude_envelope = np.abs(analytical_signal) fig2 = plt.figure(figsize=(10, 8)) plt.plot(Chan1_BP) plt.plot(amplitude_envelope)
原因分析与解决方案
核心原因
neurodsp.filt.filter_signal函数在滤波过程中,会因边界效应在信号首尾生成NaN值;而scipy.signal.hilbert处理包含NaN的数组时,会直接返回全NaN的复数数组。
解决方法
方法1:清理滤波后的NaN值
先检查并移除滤波信号中的无效NaN段:
# 定位有效信号区间 valid_mask = ~np.isnan(Chan1_BP) Chan1_BP_clean = Chan1_BP[valid_mask] # 重新执行希尔伯特变换 analytical_signal = signal.hilbert(Chan1_BP_clean) amplitude_envelope = np.abs(analytical_signal)
之后绘图时注意对应有效区间的时间轴即可。
方法2:修改滤波参数避免生成NaN
若使用的neurodsp版本支持,调用filter_signal时添加remove_edges=False参数,关闭边缘截断逻辑:
Chan1_BP = filter_signal(Chan1, Fs, 'bandpass', (LBP,HBP), remove_edges=False)
此方法可保留完整信号长度,但需注意边缘的滤波误差,若对边缘精度要求高,可后续手动处理边缘值。
方法3:预处理信号减少边界效应
对原始信号先做边缘填充(如镜像填充、零填充),再执行滤波:
# 镜像填充信号边缘,长度为滤波器阶数的一半(示例) from scipy.signal import firwin order = int(3 * Fs / LBP) # 估算滤波器阶数 Chan1_padded = np.pad(Chan1, order//2, mode='reflect') # 对填充后的信号滤波 Chan1_BP_padded = filter_signal(Chan1_padded, Fs, 'bandpass', (LBP,HBP)) # 截断回原始信号长度 Chan1_BP = Chan1_BP_padded[order//2 : -order//2] # 再执行希尔伯特变换 analytical_signal = signal.hilbert(Chan1_BP) amplitude_envelope = np.abs(analytical_signal)
内容的提问来源于stack exchange,提问作者Andrew M
相关产品推荐
相关产品推荐

