You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

问题原因分析

  1. 数组初始化的负数维度问题:代码直接用len(ecg_peaks[0]) - 2作为结果数组的第一维度。如果某组数据中检测到的ECG峰值数量≤2(比如刚好2个或1个),这个计算结果会≤0,初始化np.zeros((负数, 110))时就会触发negative dimensions are not allowed错误。这种情况容易随机出现在数据量较短、R波数量少的样本中。

  2. 切片边界越界隐患:当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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 10:55:17