ECG/PPG峰值检测出现ValueError:不允许负维度的问题求助
问题
编写了beat_detect函数,通过signal.find_peaks检测ECG信号的R波峰值,再提取ECG峰值前后55个点范围内的PPG信号片段。批量处理多名被试的多组数据时,程序会随机在部分数据处中断,抛出错误:ValueError: negative dimensions are not allowed。
已排查确认出错数据中ECG峰值均正常检测到,但更换文件后错误仍会随机出现。函数代码如下:
def beat_detect (ECG, PPG_red_interp, PPG_ir_interp, PPG_red2_interp, PPG_ir2_interp): ecg_peaks = signal.find_peaks(ECG, height=np.mean(ECG)+2*np.std(ECG), prominence=np.mean(ECG)+np.std(ECG)) ecg_beats = np.zeros((len(ecg_peaks[0]) - 2, 110)) ppg_red_beats = np.zeros((len(ecg_peaks[0]) - 2, 110)) ppg_ir_beats = np.zeros((len(ecg_peaks[0]) - 2, 110)) ppg_red2_beats = np.zeros((len(ecg_peaks[0]) - 2, 110)) ppg_ir2_beats = np.zeros((len(ecg_peaks[0]) - 2, 110)) for i in range(1, len(ecg_peaks[0])-1): ecg_beats[i-1] = ECG[ecg_peaks[0][i]-55:ecg_peaks[0][i]+55] ppg_red_beats[i-1] = PPG_red_interp[ecg_peaks[0][i]-55:ecg_peaks[0][i]+55] ppg_ir_beats[i-1] = PPG_ir_interp[ecg_peaks[0][i]-55:ecg_peaks[0][i]+55] ppg_red2_beats[i-1] = PPG_red2_interp[ecg_peaks[0][i]-55:ecg_peaks[0][i]+55] ppg_ir2_beats[i-1] = PPG_ir_interp[ecg_peaks[0][i]-55:ecg_peaks[0][i]+55] return ecg_peaks, ecg_beats, ppg_red_beats, ppg_ir_beats, ppg_red2_beats, ppg_ir2_beats
问题原因分析
数组初始化的负数维度问题:代码直接用
len(ecg_peaks[0]) - 2作为结果数组的第一维度。如果某组数据中检测到的ECG峰值数量≤2(比如刚好2个或1个),这个计算结果会≤0,初始化np.zeros((负数, 110))时就会触发negative dimensions are not allowed错误。这种情况容易随机出现在数据量较短、R波数量少的样本中。切片边界越界隐患:当ECG峰值位置距离信号起始端不足55个点(
ecg_peaks[0][i]-55 < 0),或距离末端不足55个点(ecg_peaks[0][i]+55 > 信号长度),此时切片长度会不等于110,赋值到固定长度的数组时会引发维度不匹配,也可能间接触发类似异常。
解决方案
1. 增加峰值数量校验
在初始化数组前,先检查ECG峰值数量是否满足处理要求(至少3个),不满足时返回合理的空值或提示,避免初始化负数维度数组。
2. 处理切片边界问题
对切片的起始和结束索引做边界限制,确保切片在信号数组的有效范围内,同时保证切片长度为110(不足时补零)。
修改后的代码
import numpy as np from scipy import signal def beat_detect(ECG, PPG_red_interp, PPG_ir_interp, PPG_red2_interp, PPG_ir2_interp): ecg_peaks = signal.find_peaks(ECG, height=np.mean(ECG)+2*np.std(ECG), prominence=np.mean(ECG)+np.std(ECG)) peak_count = len(ecg_peaks[0]) # 校验峰值数量,至少需要3个才能处理中间的峰值 if peak_count < 3: # 返回空数组或根据需求返回其他默认值 return ( ecg_peaks, np.array([]), np.array([]), np.array([]), np.array([]), np.array([]) ) # 初始化结果数组 ecg_beats = np.zeros((peak_count - 2, 110)) ppg_red_beats = np.zeros((peak_count - 2, 110)) ppg_ir_beats = np.zeros((peak_count - 2, 110)) ppg_red2_beats = np.zeros((peak_count - 2, 110)) ppg_ir2_beats = np.zeros((peak_count - 2, 110)) # 获取各信号的长度,用于边界判断 ecg_len = len(ECG) ppg_red_len = len(PPG_red_interp) ppg_ir_len = len(PPG_ir_interp) ppg_red2_len = len(PPG_red2_interp) ppg_ir2_len = len(PPG_ir2_interp) for i in range(1, peak_count - 1): peak_pos = ecg_peaks[0][i] # 计算切片的起始和结束索引,做边界限制 start = max(0, peak_pos - 55) end = start + 110 # 处理ECG信号切片 if end > ecg_len: # 末端不足时,取到末尾后补零 ecg_slice = np.pad(ECG[start:], (0, 110 - (ecg_len - start)), mode='constant') else: ecg_slice = ECG[start:end] ecg_beats[i-1] = ecg_slice # 处理PPG_red信号切片 if end > ppg_red_len: ppg_red_slice = np.pad(PPG_red_interp[start:], (0, 110 - (ppg_red_len - start)), mode='constant') else: ppg_red_slice = PPG_red_interp[start:end] ppg_red_beats[i-1] = ppg_red_slice # 处理PPG_ir信号切片 if end > ppg_ir_len: ppg_ir_slice = np.pad(PPG_ir_interp[start:], (0, 110 - (ppg_ir_len - start)), mode='constant') else: ppg_ir_slice = PPG_ir_interp[start:end] ppg_ir_beats[i-1] = ppg_ir_slice # 处理PPG_red2信号切片 if end > ppg_red2_len: ppg_red2_slice = np.pad(PPG_red2_interp[start:], (0, 110 - (ppg_red2_len - start)), mode='constant') else: ppg_red2_slice = PPG_red2_interp[start:end] ppg_red2_beats[i-1] = ppg_red2_slice # 处理PPG_ir2信号切片 if end > ppg_ir2_len: ppg_ir2_slice = np.pad(PPG_ir2_interp[start:], (0, 110 - (ppg_ir2_len - start)), mode='constant') else: ppg_ir2_slice = PPG_ir2_interp[start:end] ppg_ir2_beats[i-1] = ppg_ir2_slice return ecg_peaks, ecg_beats, ppg_red_beats, ppg_ir_beats, ppg_red2_beats, ppg_ir2_beats
内容的提问来源于stack exchange,提问作者Kcodx
相关产品推荐
相关产品推荐

