步骤 18:剔心电成分
识别心电相关 ICA 成分
1. 目标
利用 ECG 通道与 ICA 成分的相关性,识别心跳伪迹成分。识别流程与步骤 17 的眼电成分识别完全一致,仅目标通道不同。
2. 何时使用 / 何时跳过
- 应当使用:研究中存在
ecg通道且 ECG 伪迹明显 - 可跳过:ECG 信号本身很干净;研究只关心短时间窗(< 1 秒)
3. 前置条件
- 已执行步骤 17:眼电成分识别已完成
- 数据中存在
ecg类型通道
4. 核心代码
Python
import mne
# ====== 方式 A:自动识别(推荐新手,默认 ctps) ======
# 注意:method 仅接受 'ctps'(默认)/'correlation',
# 'variance' 不是合法值(从未存在过)
ecg_idx, ecg_scores = ica.find_bads_ecg(
raw,
ch_name=None, # None = 自动选 ecg 通道
method='ctps', # cross-trial phase statistics(默认)
threshold='auto', # 'auto'(默认)或 float
# 注意:threshold 对两种 method 都生效:
# - 'ctps': 表示 Kuiper 检验的显著性水平;'auto' 会基于采样频率自动算
# - 'correlation': 表示 z-score 阈值
l_freq=8, # 真实默认值(注意是 8 不是 8.0,Hz)
h_freq=16, # 真实默认值(不是 30)
)
print(f"自动识别的心电成分: {ecg_idx}")
print(f"各成分分数: {ecg_scores}")
# ====== 方式 B:基于简单相关(最快) ======
ecg_idx, ecg_scores = ica.find_bads_ecg(
raw,
ch_name='ECG001', # 显式指定 ECG 通道
method='correlation',
threshold=2.0,
l_freq=8,
h_freq=16,
)
# ====== 人工核对(必做) ======
ica.plot_scores(ecg_scores, exclude=ecg_idx)
ica.plot_components(picks=ecg_idx, inst=raw)
ica.plot_sources(inst=raw, picks=ecg_idx, start=0, stop=30)
# 期望:成分时间序列呈现明显的 QRS 周期节律
# ====== 合并到 exclude 列表 ======
ica.exclude.extend(ecg_idx)
print(f"当前排除列表(含 EOG + ECG): {ica.exclude}")
5. 参数详解(真实签名)
ica.find_bads_ecg(inst, ch_name=None, threshold='auto', start=None, stop=None, l_freq=8, h_freq=16, method='ctps', reject_by_annotation=True, measure='zscore', verbose=None)
| 参数 | 含义 | 推荐值 |
|---|---|---|
ch_name |
ECG 通道 | None(自动选)/ 'ECG001' |
method |
检测方法 | 'ctps'(默认)/'correlation'('variance' 从未是合法值) |
threshold |
阈值 | 两种 method 都生效:'ctps' 表示 Kuiper 显著性水平('auto' 按 sfreq 推算);'correlation' 表示 z-score。默认 'auto' |
l_freq / h_freq |
检测 QRS 频段 | 8 / 16(真实默认,不是 8–30) |
measure |
相关性度量 | 'zscore'(默认) |
qrs_threshold |
⚠️ 不是本方法参数 | (属于 compute_proj_ecg) |
两种合法方法对比
| 方法 | 原理 | 速度 | 稳定性 |
|---|---|---|---|
ctps |
跨试验相位统计(默认) | 慢 | 高 |
correlation |
简单相关 | 快 | 中 |
⚠️
method='variance'从未是 find_bads_ecg 的合法值——传入会触发_check_option('method', ...),抛ValueError: Invalid value for the 'method' parameter...(不是 TypeError)。本教材不推荐使用任何"variance"方法。
6. 验证方法
Python
# 验证 1:候选成分数量
print(f"自动检出 ECG 成分数: {len(ecg_idx)}")
assert 0 <= len(ecg_idx) <= 3, "ECG 成分数异常"
# 验证 2:topomap 是否合理
# ECG 成分常见模式:单极强(V-lead 类似)或扩散型
for idx in ecg_idx:
ica.plot_components(picks=[idx], inst=raw)
# 验证 3:时间序列显示 QRS 节律
ica.plot_sources(inst=raw, picks=ecg_idx, start=0, stop=60)
# 期望:清晰可见周期性心跳尖峰
# 验证 4:与 ECG 通道相关性
import numpy as np
ecg_data = raw.get_data(picks='ecg')[0]
ic_data = ica.get_sources(raw).get_data()[ecg_idx[0]]
corr = np.corrcoef(ecg_data, ic_data)[0, 1]
print(f"IC{ecg_idx[0]} vs ECG 相关系数: {corr:.2f}")
# 期望:|r| > 0.2(ECG 信号较弱时)
7. 常见错误
| 错误 | 原因 | 解决方案 |
|---|---|---|
ValueError: Invalid value for the 'method' parameter... |
用了 'variance' 等非法值(_check_option 抛 ValueError,不是 TypeError) |
改用 'ctps'(默认)/'correlation' |
RuntimeError: No ECG channels found |
步骤 03 未标 ECG | 回到步骤 03 修正 |
find_bads_ecg 检出 0 成分 |
ECG 通道伪迹本身不明显 | 接受现状,跳过本步;或用 SSP(步骤 15)替代 |
method='ctps' 太慢 |
需要 epochs(计算跨试验相位) | 改用 'correlation' |
| 自动检出 vs 人工判断不一致 | 边界情况 | 永远要配合可视化人工核对 |
8. 官方来源
| 资源类型 | 链接 |
|---|---|
find_bads_ecg |
https://mne.tools/stable/generated/mne.preprocessing.ICA.html#mne.preprocessing.ICA.find_bads_ecg |
| ICA 教程 | https://mne.tools/stable/auto_tutorials/preprocessing/plot_40_artifact_correction_ica.html |
compute_proj_ecg(含 qrs_threshold) |
https://mne.tools/stable/generated/mne.preprocessing.compute_proj_ecg.html |
9. 学术引用
Shackman, A. J., et al. (2009). Identifying robust and sensitive measures for EEG cardiac artifact detection. Psychophysiology, 46(3), 593-606.