非官方中文翻译 本页译自 MNE-Python 官方文档: 查看英文原文 ↗。 文档版权归 MNE Developers 所有(BSD-3-Clause)。

典型 M/EEG 工作流#

概述#

本节介绍典型的 MEG/EEG 工作流程,最终涵盖到源重建。该流程在 Workflow of the MNE software 一节中作了概括。下文中的引用指向 Python 函数和对象。

MNE Workflow Flowchart
MNE 软件的工作流程#

预处理#

建议采用以下 MEG 和 EEG 数据预处理步骤:

  • 必须识别 MEG 和 EEG 数据中的坏通道,参见标记坏通道一节。

  • 需要将数据滤波到所需的通带。

  • 应抑制伪迹(例如使用 ICA 或 SSP)。

标记坏通道#

有时某些 MEG 或 EEG 通道会因各种原因无法正常工作。应当把这些通道标记为坏通道,从而将其排除在分析之外,例如:

>>> raw.info['bads'] = ['MEG2443']

尤其当某个通道完全没有信号(平坦)时,务必将其排除在分析之外,因为其噪声估计会低得不切实际,从而使电流估计计算给平坦通道上的零信号赋予很大权重,最终结果实际上会消失殆尽。排除噪声较大的通道同样重要,因为在使用信号空间投影或 EEG 平均电极参考时,这些通道可能会影响其他通道。噪声较大的坏通道还可能引发不必要的 epoch 剔除,从而对平均和噪声协方差矩阵估计产生不利影响。

识别坏通道的推荐方法有:

  • 在数据采集过程中观察数据质量,并将发现的异常通道记录到测量记录表中。

  • 查看在线平均数据,检查各通道的状态。

  • 在关闭伪迹剔除、SSP/ICA 以及 EEG 平均电极参考计算的情况下,计算初步的离线平均数据,并检查各通道的状态。

  • 在未启用 SSP/ICA 的情况下,使用 mne.io.Raw.plot() 查看原始数据并识别坏通道。

注意

强烈建议在原始数据文件中识别并标记坏通道。如果原始数据文件中已包含坏通道标记,这些选择会自动传递到平均文件、噪声协方差矩阵、正向解文件和逆算子分解中。

伪迹抑制#

SSP#

信号空间投影(Signal-Space Projection,SSP)是在软件层面抑制外部干扰的一种方法。与许多其他噪声消除方法不同,SSP 不需要额外的参考传感器来记录干扰场。相反,SSP 依赖于这样一个事实:大脑内源产生的磁场分布与外部噪声源产生的磁场分布在空间分布上存在足够大的差异。此外,该方法还隐含地假设由显著外部噪声模式所张成的线性空间具有较低的维数。

基于 SSP 的伪迹剔除通常使用 mne.preprocessing.compute_proj_ecg() 和 mne.preprocessing.compute_proj_eog() 方法完成,更多信息参见 投影器与投影背景知识 和 使用 SSP 修复伪迹。

ICA#

许多 M/EEG 信号(包括生物伪迹)反映的是非高斯过程。因此,基于 PCA 的伪迹剔除在分离信号与噪声源方面可能表现较差。

基于 ICA 的伪迹剔除使用 mne.preprocessing.ICA 类完成,更多信息参见独立成分分析(ICA)一节。

分段与诱发数据#

原始数据的分段通过事件(events)完成,事件为每个数据片段定义了 t=0。使用 mne.find_events() 可以提取打标到采集软件中的事件时间:

>>> events = mne.find_events(raw)

如有必要,随后可以修改、扩展或更改 events 数组。如果原始触发码和触发时间对于所关注的分析是正确的,则可以使用以下代码为第一种事件类型(1)构建 mne.Epochs:

>>> reject = dict(grad=4000e-13, mag=4e-12, eog=150e-6)
>>> epochs = mne.Epochs(raw, events, event_id=1, tmin=-0.2, tmax=0.5,
>>>                     proj=True, picks=picks, baseline=(None, 0),
>>>                     preload=True, reject=reject)

注意

剔除阈值(通过 reject 参数设置)的单位分别为:梯度计为 T/m,磁强计为 T,EEG 和 EOG 通道为 V。

使用标注剔除数据段#

mne.Epochs 的 reject 关键字用于基于峰峰值阈值剔除坏 epoch。也可以通过用标注(annotations)标记原始数据的某些片段来剔除坏数据段。更多内容参见 剔除坏数据段与中断 和 mne.Annotations。

构建好 mne.Epochs 后,可以对其进行平均以获得 mne.Evoked 数据,如下所示:

>>> evoked = epochs.average()

源定位#

MNE 大量使用 FreeSurfer 的文件结构进行分析。在开始数据分析之前,建议设置环境变量 SUBJECTS_DIR(或使用 mne.set_config() 永久设置),以指定存放解剖 MRI 数据的目录。这样,许多函数就无需再传入 subjects_dir 参数。

解剖信息#

使用 FreeSurfer 重建皮层表面#

第一个处理阶段是使用 FreeSurfer 创建各种表面重建。推荐的 FreeSurfer 工作流程概括在 FreeSurfer wiki 页面中。另请参阅 FreeSurfer MRI 重建 中的相关信息。

设置源空间#

本阶段包括以下内容:

  • 在白质表面创建合适的抽稀偶极子网格。

  • 以 fif 格式创建源空间文件。

这通过 mne.setup_source_space() 和 mne.write_source_spaces() 完成。它们假定解剖 MRI 处理已按使用 FreeSurfer 重建皮层表面一节所述完成。

为创建源空间推荐的二十面体与八面体细分方案。近似的源点间距及相应的表面积按每个半球 1000 cm2 的表面积计算。#
spacing 每个半球的源点数量 源点间距 / mm 每个源点的表面积 / mm2
'oct5'

1026

9.9

97

'ico4'

2562

6.2

39

'oct6'

4098

4.9

24

'ico5'

10242

3.1

9.8

例如,要为 subject='sample' 创建网格点间距约为 5 mm 的重建几何结构,可以这样写:

>>> src = setup_source_space('sample', spacing='oct6')
>>> write_source_spaces('sample-oct6-src.fif', src)

这会创建源空间并将其写入磁盘。

Compute Source Space 说明了如何使用源空间计算正向模型。

创建 BEM 模型网格#

使用边界元模型(BEM)计算正向解,要求将分隔不同电导率区域的表面用合适的表面单元进行剖分。我们的 BEM 软件采用三角剖分。因此,BEM 计算的前提是对 MRI 数据进行分割,并对相关表面进行三角剖分。

对于 MEG 计算,采用假设颅内体积形状的单隔室 BEM 即可获得相当准确的结果。对于 EEG,标准模型包含颅内空间、颅骨和头皮。

目前尚不存在万无一失的三角剖分创建方法。可行的方法在 The Boundary Element Model (BEM) 一节中有所描述。

准备头部表面三角剖分文件#

The Boundary Element Model (BEM) 中所述的分割算法会生成 FreeSurfer 表面或文本格式的三角剖分数据。在继续创建边界元模型之前,必须存在 FreeSurfer 表面的标准文件:

  1. inner_skull.surf 包含内颅骨的三角剖分。

  2. outer_skull.surf 包含外颅骨的三角剖分。

  3. outer_skin.surf 包含头部(头皮)表面的三角剖分。

建立边界元模型#

本阶段为计算正向解设置依赖于被试的数据:

>>> model = make_bem_model('sample')
>>> write_bem_surfaces('sample-5120-5120-5120-bem.fif', model)

其中 surfaces 是一个 BEM 表面列表,其中每个表面都是通过 mne.read_surface() 读取的。该步骤还会检查输入表面是否完整、拓扑是否正确,即表面之间不相交,且表面顺序正确(外颅骨表面位于头皮之内,内颅骨表面位于外颅骨之内)。

该步骤为 BEM 各隔室赋予电导率值。对于头皮和大脑隔室,默认值为 0.3 S/m。颅骨的默认电导率小 50 倍,即 0.006 S/m。近期文献报道的颅骨电导率比值范围从 1:15 [1] 到 1:25 - 1:50 [2] [3]。MNE 的默认比值 1:50 基于 [2] 中报道的典型值,因为其方法基于 BEM 模型中 SEF/SEP 测量的比较。不同文献之间的差异可能取决于个体差异,但更重要的是取决于颅骨隔室分割的精度。

注意

如需生成单层 BEM 模型(在 C 命令行工具中为 –homog 标志),请传入只含单个电导率值的列表,例如 conductivities=[0.3]。

使用该模型,可以通过 mne.make_bem_solution() 计算 BEM 解,如下所示:

>>> bem_sol = make_bem_solution(model)
>>> write_bem_solution('sample-5120-5120-5120-bem-sol.fif', bem_sol)

BEM 设置完成后,建议使用例如 mne.viz.plot_alignment() 或 mne.Report 检查 BEM 模型网格的位置是否正确。

注意

到目前为止,所有处理阶段都只依赖于解剖(几何)信息,因此在不同的 MEG 研究中完全相同。

注意

如果使用自定义头部模型,可能需要将 ico=None 参数设为 None,并跳过表面的降采样。

对齐坐标系#

计算正向解需要了解 MEG/EEG 与 MRI 坐标系的相对位置和朝向(参见 The head and device coordinate systems 一节)。头部坐标系通过识别基准标志点来定义,因此头部坐标系的原点和朝向在一定程度上取决于操作者。因此,最安全的做法是为每个实验场次重新建立坐标变换的计算定义,即每次使用新的头部数字化数据时都重新进行。

配准结果保存在 -trans.fif 文件中。如果该文件存在,可以按照 源空间对齐与坐标框架 一节验证其正确性。如果 -trans.fif 不存在或对齐不正确,则需要使用 mne.gui.coregistration()(或其便捷的命令行等价形式 mne coreg)来生成它。

警告

这一步很重要。如果坐标系对齐不准确,后续所有处理步骤都会受到该误差的影响。因此,该步骤应由研究负责人或经过培训的技术人员完成。对 MEG/EEG 采集期间所用对齐点进行书面或拍照记录也会有所帮助。

计算正向解#

MRI 与 MEG/EEG 的对齐设置完成后,就可以借助 mne.make_forward_solution() 计算正向解,即位于皮层上的偶极子源在测量传感器和电极处产生的磁场与电位,如下所示:

>>> fwd = make_forward_solution(raw.info, fname_trans, src, bem_sol)

计算噪声协方差矩阵#

MNE 软件使用噪声协方差矩阵的估计,在计算中正确地给各通道加权。噪声协方差矩阵提供了关于场和电位模式的信息,这些模式代表了来自人体或环境的、不感兴趣的噪声源。

噪声协方差矩阵可以通过以下几种方式计算:

  • 利用离线平均过程中的单个 epoch 计算完整的噪声协方差矩阵。这是分析诱发响应的推荐方法,例如使用 mne.compute_covariance():

    >>> cov = mne.compute_covariance(epochs, method='auto')
    
  • 利用空房间数据(无被试时采集)计算完整的噪声协方差矩阵。这是分析持续自发活动的推荐方法。可以使用 mne.compute_raw_covariance() 完成:

    >>> cov = mne.compute_raw_covariance(raw_erm)
    
  • 利用被试在场时采集的一段连续原始数据计算完整的噪声协方差矩阵。这是分析癫痫活动的推荐方法。用于此目的的数据应当不含技术伪迹和所关注的癫痫活动。所用数据段的长度应至少为 20 秒。也可以使用一段较长(*> 200 s)且包含癫痫尖波的数据,前提是尖波出现不频繁,且该数据段相对于背景脑活动而言明显平稳。这同样可以使用 mne.compute_raw_covariance()。

计算逆算子#

MNE 软件并不显式计算逆算子,而是对由噪声协方差矩阵、正向计算结果和源协方差矩阵组成的矩阵进行 SVD 分解。这种方法的优点在于,在计算最终的源估计或 dSPM 时可以方便地调整正则化参数(“SNR”)。关于该方法的数学细节,请参阅 The minimum-norm current estimates 一节。

该计算阶段可以使用 mne.minimum_norm.make_inverse_operator() 完成,如下所示:

>>> inv = mne.minimum_norm.make_inverse_operator(raw.info, fwd, cov, loose=0.2)

生成源估计#

完成上述所有预处理步骤后,就可以将计算得到的逆算子应用于 MEG 和 EEG 数据,如下所示:

>>> stc = mne.minimum_norm.apply_inverse(evoked, inv, lambda2=1. / 9.)

结果可以这样查看:

>>> stc.plot()

组分析#

通过对源估计进行形变(morphing)可以方便地开展组分析,例如形变到 subject='fsaverage',如下所示:

>>> morph = mne.compute_source_morph(stc, subject_from='sample', subject_to='fsaverage')
>>> stc_fsaverage = morph.apply(stc)

更多信息参见 Morphing and averaging source estimates 一节。

参考文献#