本文是在阅读博主zhoudapeng01的文章Python 中MNE库去伪迹(ICA)_zhoudapeng01的博客-CSDN博客_ica mne后做的一个翻译工作。
主要介绍的还是ICA,需要了解的前置知识为MNE库和PCA(实际上知道概念就行)
# -*- coding: utf-8 -*-
"""
.. _tut-artifact-ica:
利用ICA去除伪迹
============================
本教程涵盖了独立分量分析 (ICA) 的基础知识,并展示了如何使用 ICA 进行去除伪迹;
一个扩展示例说明了眼部和心跳伪影的修复。 有关 ICA 的概念背景,请参阅 scikit-learn 教程。
.. contents:: Page contents
:local:
:depth: 2
我们一如既往地导入必要的 Python 模块并加载一些“示例数据 ”。
由于 ICA 的计算量很大,我们还将数据裁剪为 60 秒;
为了避免重复导入 mne.preprocessing ,我们将直接从该子模块导入一些函数和类:
"""
import os
import mne
from mne.preprocessing import (ICA, create_eog_epochs, create_ecg_epochs,
corrmap)
# 获取data数据的文件夹名
sample_data_folder = mne.datasets.sample.data_path()
sample_data_raw_file = os.path.join(sample_data_folder, 'MEG', 'sample',
'sample_audvis_raw.fif')
# 创建raw对象
raw = mne.io.read_raw_fif(sample_data_raw_file)
# 数据裁剪为60s
raw.crop(tmax=60.)
###############################################################################
# .. note::
# 在应用 ICA(或其他任何去除伪迹策略)之前,请务必观察数据中的伪迹,以确保选择正确的去除工具。
# 有时,正确的方法就是不用这些工具——如果伪迹足够小,您甚至可能不需要修复它们以获得良好的分析结果
# 因为此时已经可以直接在源数据上获得良好的分析结果了
# 有关检测和可视化各种类型的伪迹的指南,请参阅 :ref:`tut-artifact-overview`。
#
# 什么是ICA ?
# ^^^^^^^^^^^^
#
# 独立分量(或者叫成分)分析 (ICA) 是一种从一组记录中估计独立源信号的技术,其中源信号以未知的比率混合在一起。
# 一个常见的例子是“盲源分离”的问题:
# 3 个乐器在同一个房间里演奏,3 个麦克风记录表演(每个麦克风拾取所有 3 个乐器,但电平不同)
# 你能以某种方式“解混”由 3 个麦克风记录的信号,
# 以便最终得到一个单独的“录音”,录音中每个乐器的声音被分隔起来
#
# 不难看出这种类比如何适用于 EEG/MEG 分析:
# 有许多“麦克风”(传感器通道)同时记录许多“乐器”(眨眼、心跳、大脑不同区域的活动、咬紧下巴的肌肉活动) 或吞咽等)。
# 只要这些各种源信号在统计上是独立且非高斯分布的,通常可以使用 ICA 分离源,然后在排除不需要的源后重新构建传感器信号。
#
#
# ICA in MNE-Python
# ~~~~~~~~~~~~~~~~~
#
# .. sidebar:: ICA and 降维
#
# 如果你想执行 ICA 时 *不要* 降维(除了 n_components 中给出的独立成分(IC)的数量,以及你在
# ICA.exclude 中指定的任何后续排除 IC),
# 通过设置``max_pca_components=None`` 和 ``n_pca_components=None``(这些是默认值)来实现。
#
# 但是,如果您 *要* 降低维度,请考虑以下示例:
# 如果您有 300 个传感器通道并且设置了“max_pca_components=200”、“n_components=50”和
# “n_pca_components=None”,
# 那么 PCA 步骤产生 200 个 PC,前 50 个 PC 被发送到 ICA 算法(产生 50 个 IC),
# 在重建期间:方法:`~mne.preprocessing.ICA.apply` 将使用 50 个 IC 加上编号为 51-200 的 PC
# (完整的 PCA 残差)。
# 如果改为指定 ``n_pca_components=120``,则 :方法:`~mne.preprocessing.ICA.apply`
# 将使用 50 个 IC 加上 PCA 残差中的前 70 个 PC(编号 51-120)进行重构。
#
# **如果您以前一直在使用 EEGLAB** 的 ``runica()`` 并且正在寻找其
# ``'pca', n`` 选项的等效项以在 ICA 步骤之前通过 PCA 降低维度,
# 请设置 ` `max_pca_components=n`,同时将 ``n_components`` 和 ``n_pca_components``
# 保留为默认值(即 ``None``)。
#
# MNE-Python 实现了三种不同的 ICA 算法:“fastica”(默认)、“picard”和“infomax”。
# FastICA 和 Infomax 都得到了相当广泛的使用;
# Picard 是一种较新的(2017 年)算法,预计收敛速度比 FastICA 和 Infomax 更快,
# 并且在源不完全独立的情况下比其他算法更稳健,这通常发生在真实的 EEG/MEG 数据中。
# 有关详细信息,请参阅 [1]_。
#
# MNE-Python中的ICA接口类似于
# `scikit-learn`_: 一些通用参数在创建如下类时被指定
# :class:`~mne.preprocessing.ICA` object, 然后
# :class:`~mne.preprocessing.ICA` object 使用其自身的如下方法来拟合数据
# :meth:`~mne.preprocessing.ICA.fit` method. 拟合的结果被添加到如下
# :class:`~mne.preprocessing.ICA` object 作为属性, 使用一个下划线作为结尾 (``_``),
# 比如 ``ica.mixing_matrix_`` 和``ica.unmixing_matrix_``.
# 拟合后,你想要移除的ICA component(s)必须被选中, 然后ICA拟合必须被应用到如下
# :class:`~mne.io.Raw` or :class:`~mne.Epochs` object 通过使用
# :class:`~mne.preprocessing.ICA` object的 :方法:`~mne.preprocessing.ICA.apply`
# 方法。
#
# 正如通常使用 ICA 所做的那样,在执行 ICA 分解之前,首先将数据缩放到单位方差并使用主成分分析 (PCA) 进行白化。
# 您可以在这一步通过指定“max_pca_components”来强制进行可选的降维。
# 从保留的主成分 (PC) 中,第一个“n_components”然后被传递给 ICA 算法
# (“n_components”可能是要使用的整数个成分,或者使用的成分应该捕获的解释方差的一部分 )。
#
# 在可视化独立组件 (IC) 并排除任何要修复的捕获伪迹后,可以使用
# ~mne.preprocessing.ICA 对象的:meth:`~mne.preprocessing.ICA.apply` 方法重建传感器信号。
# 默认情况下,信号重建使用所有 IC(减去 ``ICA.exclude`` 中列出的任何 IC)
# 加上所有未包含在 ICA 分解中的 PC(即“PCA 残差”)。
# 如果你想减少重建阶段使用的成分数量,它由 ``n_pca_components`` 参数控制(这反过来会降低数据的秩;
# 默认情况下,``n_pca_components = max_pca_components`` 不会导致额外的降维)。
# 下图总结了拟合和重建过程以及控制各个阶段维数的参数:
#
# .. graphviz:: ../../_static/diagrams/ica.dot
# :alt: Diagram of ICA procedure in MNE-Python
# :align: left
#
# 有关详细信息,请参阅:class:`~mne.preprocessing.ICA` 文档的注释部分。
# 接下来,我们将通过一个扩展示例更详细地说明这些步骤中的每一个。
#
# Example: EOG and ECG 伪迹去除
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#
# 可视化伪迹
# ~~~~~~~~~~~~~~~~~~~~~~~~~
#
# 让我们从可视化我们想要修复的伪迹开始。
# 在这个数据集中,它们足够大,可以在原始数据中轻松看到:
# 选择一些清晰显示心跳和眨眼的导联
regexp = r'(MEG [12][45][123]1|EEG 00.)'
# 使用正则表达式选择频道。artifact_picks返回 ch_names 中好的导联的索引。
artifact_picks = mne.pick_channels_regexp(raw.ch_names, regexp=regexp)
# 可视化这些导联的数据
raw.plot(order=artifact_picks, n_channels=len(artifact_picks))
###############################################################################
# 我们可以使用 :func:`~mne.preprocessing.create_eog_epochs`
# 来总结眼部伪影如何在每个通道类型中表现出来,
# 就像我们在 :ref:`tut-artifact-overview` 教程中所做的那样:
# evoke主要用于存储实验期间的平均数据
eog_evoked = create_eog_epochs(raw).average()
# 基线校正
eog_evoked.apply_baseline(baseline=(None, -0.2))
# 可视化平均诱发
eog_evoked.plot_joint()
###############################################################################
# 现在我们将对心跳伪迹做同样的事情
# 使用:func:`~mne.preprocessing.create_ecg_epochs`:
ecg_evoked = create_ecg_epochs(raw).average()
ecg_evoked.apply_baseline(baseline=(None, -0.2))
ecg_evoked.plot_joint()
###############################################################################
# 滤波以去除低频漂移
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# 在我们运行 ICA 之前,一个重要的步骤是过滤数据以消除低频漂移,以消除其对 ICA 拟合质量产生的负面影响。
# 缓慢漂移会造成一些问题,因为它们降低了假定为独立来源的独立性(例如,在缓慢向上漂移期间,
# 神经、心跳、眨眼和其他肌肉来源都倾向于具有更高的值),使得算法更难找到准确的解决方案。
# 建议使用截止频率为 1 Hz 的高通滤波器。
# 但是,由于滤波是线性运算,从滤波后的信号中找到的 ICA 解可以应用于未滤波的信号(有关更多信息,请参阅 [2]_),
# 因此我们将保留一份未滤波的 :class:`~ mne.io.Raw` 对象,以便我们稍后可以将 ICA 解决方案应用于它。
# 复制一份数据以进行滤波
filt_raw = raw.copy()
# 滤除1Hz以下的数据
filt_raw.load_data().filter(l_freq=1., h_freq=None)
###############################################################################
# 拟合并绘制 ICA 解
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# .. sidebar:: 忽略时间域
#
# 在 MNE-Python 中实现的 ICA 算法是跨通道来查找patterns的,但忽略时域(的连续性)。
# 这意味着您可以在不连续的 :class:`~mne.Epochs` 或 :class:`~mne.Evoked` 对象
# (不仅仅是连续的 :class:`~mne.io.Raw` 对象)上计算 ICA,
# 或者通过将“decim”参数传递给“ICA.fit()”,只使用每个数据集中的第 N 个样本。
#
# 现在我们已准备好设置和拟合 ICA。
# 由于我们知道(通过观察我们的原始数据)EOG(眼电图) 和 ECG(心电图) 伪影相当强,
# 我们预计这些伪影将在 ICA 之前发生的 PCA 分解的前几个维度中被捕获。
# 因此,我们可能不需要大量components来很好地分离伪迹(尽管通常最好包含更多components以获得更准确的解决方案)。
# 作为第一个猜测,我们将使用 n_components=15 运行 ICA(仅使用前 15 个 PCA components来计算 ICA 分解)
# ——考虑到我们的数据有超过 300 个通道,这是一个非常小的数字,但它具有快速运行的优势,
# 我们将能够轻松判断它是否有效(因为我们已经知道 EOG / ECG 伪迹应该是什么样子)。
#
# ICA 拟合不是确定性的(例如,components可能在不同的run中符号不同,或者在返回中的顺序不同),
# 因此我们还将指定一个“随机种子”,以便每次由我们的 Web 服务器构建本教程时我们都会得到相同的结果。
# 选取前15个components,设定随机种子为固定数
ica = ICA(n_components=15, random_state=97)
# 对滤波过的raw进行ICA
ica.fit(filt_raw)
###############################################################################
# 我们可以传递给:meth:`~mne.preprocessing.ICA.fit` 方法的一些可选参数包括 ``decim``
# (在计算 IC 时仅使用每第 N 个样本,这可以提高相当多的速度) 和 ``reject``
# (用于为每种通道类型提供最大可接受峰峰值幅度的拒绝字典,就像我们在 :ref:`tut-overview`
# 教程中创建epoch数据时使用的那样)。
# 现在我们可以检查 IC 以查看它们捕获的内容。
# :meth:`~mne.preprocessing.ICA.plot_sources` 将显示 IC 的时间序列。
# 请注意,在调用:方法:`~mne.preprocessing.ICA.plot_sources` 时,
# 我们可以使用原始的、未过滤的:class:`~mne.io.Raw` 对象:
# 原始raw中data数据提取
raw.load_data()
# 使用拟合过的ICA显示IC的时间序列
ica.plot_sources(raw)
###############################################################################
# 在这里我们可以很清楚地看到第一个component(``ICA000``)很好地捕获了 EOG 信号,
# 而第二个component(``ICA001``)看起来很像`心跳`_(更多 有关视觉识别独立组件的信息,
# `this EEGLAB tutorial`_ 是一个很好的资源)。
# 我们还可以使用:方法:`~mne.preprocessing.ICA.plot_components`来可视化每个组件的头皮场分布。
# 这些是基于 ICA 分解矩阵中的值进行插值的:
# sphinx_gallery_thumbnail_number = 9
# 画出这15个ICA的脑电图
ica.plot_components()
###############################################################################
# .. note::
#
# :meth:`~mne.preprocessing.ICA.plot_components`(绘制每个组件的头皮场拓扑图)
# 有一个可选的“inst”参数,它接受一个实例:class:`~mne.io.Raw`或:类:`~mne.Epochs`。
# 传递“inst”使头皮拓扑图具有交互性:单击一个将打开该组件的诊断窗口(见下文)。
#
# 在上面的图中,我们能很明显看到哪些 IC 正在捕获我们的 EOG 和 ECG 伪迹,
# 但是为了确定,还可以使用其他方法将它们可视化。
# 首先,我们可以绘制原始信号与重构信号的叠加图,其中不包括包含伪迹的 IC,使用
# :方法:`~mne.preprocessing.ICA.plot_overlay`:
# 眼动
ica.plot_overlay(raw, exclude=[0], picks='eeg')
# 心电
ica.plot_overlay(raw, exclude=[1], picks='mag')
###############################################################################
# 我们还可以绘制每个 IC 的一些诊断信息
# :meth:`~mne.preprocessing.ICA.plot_properties`:
# 属性包括脑电拓扑图、epoch图像、ERP/ERF、功率谱和epoch方差。
ica.plot_properties(raw, picks=[0, 1])
###############################################################################
# 在其余部分中,我们将研究在重建传感器信号之前选择要排除哪些 IC 的不同方法。
#
#
# 手动选择 ICA 组件
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# 一旦我们确定要排除哪些components,我们可以通过设置 ``ica.exclude`` 属性手动指定。
# 与标记坏频道类似,仅设置 ``ica.exclude`` 不会立即执行任何操作
# (它只是将排除的 IC 添加到列表中,以便稍后在需要时使用)。
# 一旦设置了排除项,即使没有传递 ``exclude`` 参数,
# 像 :meth:`~mne.preprocessing.ICA.plot_overlay` 这样的 ICA 方法也会排除这些components,
# 被排除的components列表将会在使用 mne.preprocessing.ICA.save 和 mne.preprocessing.read_ica 时保留。
# 根据上面的图所选择的要排除的components
ica.exclude = [0, 1]
###############################################################################
# 既然已经设置了排除项,我们可以使用:meth:`~mne.preprocessing.ICA.apply`
# 方法重建去除伪影的传感器信号(请记住,我们将 *已过滤* 数据中的 ICA 解决方案应用于原始 *未过滤* 信号)。
# 将原始原始数据与重建数据一起绘制,可以看到心跳和眨眼伪影已得到修复。
# ica.apply() 会在原始raw对象进行更改,因此想要不更改源raw,在此就创建一个copy:
reconst_raw = raw.copy()
# 应用ica到reconst_raw上
ica.apply(reconst_raw)
# 没有去除伪迹
raw.plot(order=artifact_picks, n_channels=len(artifact_picks))
# 去除了伪迹
reconst_raw.plot(order=artifact_picks, n_channels=len(artifact_picks))
# 删除copy的raw
del reconst_raw
###############################################################################
# 使用 EOG 通道选择 ICA components
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# 查看图表并手动选择要排除的 IC 似乎很容易,但在处理数十或数百个受试者时,
# 这可能成为分析流程中一个乏味且限速的步骤。
# 一种替代方法是使用专用 EOG 或 ECG 传感器作为“模式”来检查 IC,
# 并自动标记排除与 EOG/ECG 模式匹配的任何 IC。
# 在这里,我们将使用:meth:`~mne.preprocessing.ICA.find_bads_eog`
# 自动找到最匹配 EOG 信号的 IC,然后使用:meth:`~mne.preprocessing.ICA.plot_scores`
# 以及我们的其他绘图功能以查看它选择了哪些 IC。 我们首先将 ica.exclude 重置为空列表:
ica.exclude = []
# 找出与 EOG 模式匹配的 IC
eog_indices, eog_scores = ica.find_bads_eog(raw)
# 设置ica的exclude属性
ica.exclude = eog_indices
# ICA component "EOG match"的分数条形图
ica.plot_scores(eog_scores)
# 给出诊断信息图
ica.plot_properties(raw, picks=eog_indices)
# 绘制应用于原始数据的 IC,突出显示 EOG 匹配
ica.plot_sources(raw)
# 绘制应用于平均 EOG epoch 的 IC,突出显示 EOG 匹配
ica.plot_sources(eog_evoked)
###############################################################################
# 请注意,上面我们在原始 :class:`~mne.io.Raw` 实例和 :class:`~mne.Evoked`
# 实例上都使用了提取 EOG 伪影的方法。
# 这可以是另一种确认 :meth:`~mne.preprocessing.ICA.find_bads_eog` 已识别正确components的方法。
#
#
# 使用模拟通道选择 ICA 组件
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# 如果你没有 EOG 通道,:meth:`~mne.preprocessing.ICA.find_bads_eog` 有一个 ``ch_name`` 参数,
# 你可以使用它作为 EOG 的代理。
# 您可以使用单个通道,或从额叶 EEG 传感器创建双极参考,并将其用作虚拟 EOG 通道。
# 然而,这有一个风险:你必须保证额叶 EEG 通道只反映 EOG,而不是前额叶皮层中的大脑动态
# (或者说你不能在意那些前额叶信号)。
#
# 对于ECG,更简单:meth:`~mne.preprocessing.ICA.find_bads_ecg`
# 可以使用磁力计通道或梯度计通道的跨通道平均来构建虚拟ECG通道,所以如果你有MEG通道通常不需要通过特定的频道名称。
# :meth:`~mne.preprocessing.ICA.find_bads_ecg` 的 ``method`` 参数也有两个选项:
# ``'ctps'``(交叉试验阶段统计 [3]_)和 ``'correlation' ``(数据和心电图通道之间的皮尔逊相关性)。
# 首先将 ica.exclude 重置为空列表
ica.exclude = []
# 找出与 ECG 模式匹配的 IC
ecg_indices, ecg_scores = ica.find_bads_ecg(raw, method='correlation')
# 设置ica的exclude属性
ica.exclude = ecg_indices
# ICA component "ECG match"的分数条形图
ica.plot_scores(ecg_scores)
# 给出诊断信息图
ica.plot_properties(raw, picks=ecg_indices)
# 绘制应用于原始数据的 IC,突出显示 ECG 匹配
ica.plot_sources(raw)
# 绘制应用于平均 ECG epoch 的 IC,突出显示 ECG 匹配
ica.plot_sources(ecg_evoked)
###############################################################################
# 这些图的最后一个ica.plot_sources(ecg_evoked)特别有用:
# 它向我们展示了心跳伪迹显示在了 *两个* IC里,而我们只捕获了其中一个。
# 事实上,如果我们仔细观察:meth:`~mne.preprocessing.ICA.plot_sources`的输出
# (在线,可以右键→“查看图像”放大),看起来“ICA014”具有与“ICA001”同相的弱周期性分量。
# 使用更多components重新运行 ICA 以查看第二个心跳伪迹是否能更好地解决可能是值得的:
# 这次用 30 个components拟合 ICA
new_ica = ICA(n_components=30, random_state=97)
new_ica.fit(filt_raw)
# 找出与ECG模式匹配的 IC
ecg_indices, ecg_scores = new_ica.find_bads_ecg(raw, method='correlation')
new_ica.exclude = ecg_indices
# ICA component "ECG match"的分数条形图
new_ica.plot_scores(ecg_scores)
# 给出诊断信息图
new_ica.plot_properties(raw, picks=ecg_indices)
# 绘制应用于原始数据的 IC,突出显示 ECG 匹配
new_ica.plot_sources(raw)
# 绘制应用于平均 ECG epoch 的 IC,突出显示 ECG 匹配
new_ica.plot_sources(ecg_evoked)
###############################################################################
# 现在的效果好了很多。 现在我们已经捕获了反映心跳伪影的两个 IC
# (因此,我们得到了两个诊断图:每个 IC 对应一个反映心跳的图)。
# 这证明了在接受它们之前检查自动获取伪迹components方法的结果的价值,
# 例如:meth:`~mne.preprocessing.ICA.find_bads_ecg`。
# 在进行下一步之前清理内存
del raw, filt_raw, ica, new_ica
###############################################################################
# 使用模板匹配来选择 IC 中的components
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# 在处理多个被试时,也可以手动挑选出一个被试的 IC 作为exclusion,
# 然后使用该components作为 *模板* 来选择要从其他主题的数据中排除哪些 IC,
# 使用:func:`mne.preprocessing.corrmap` [4]_
# :func:`~mne.preprocessing.corrmap` 背后的想法是,伪迹模式在各个主题之间足够相似,
# 因此可以通过将每个 ICA solutions 中的 IC 与通用模板相关联来识别相应的 IC,并选择相关强度最高的 IC 。
# :func:`~mne.preprocessing.corrmap` 接受一个 ICA solutions 列表和一个 ``template`` 参数,
# 该参数指定哪个 ICA 对象和其中的哪个组件用作模板。
#
# 由于我们的示例数据集仅包含来自一个被试的数据,因此我们将使用具有多个被试的不同数据集:
# EEGBCI 数据集 [5]_ [6]_。
# 数据集有 109 个主题,我们只需从前 4 个主题中的每个主题下载一次运行(左/右手运动任务):
mapping = {
'Fc5.': 'FC5', 'Fc3.': 'FC3', 'Fc1.': 'FC1', 'Fcz.': 'FCz', 'Fc2.': 'FC2',
'Fc4.': 'FC4', 'Fc6.': 'FC6', 'C5..': 'C5', 'C3..': 'C3', 'C1..': 'C1',
'Cz..': 'Cz', 'C2..': 'C2', 'C4..': 'C4', 'C6..': 'C6', 'Cp5.': 'CP5',
'Cp3.': 'CP3', 'Cp1.': 'CP1', 'Cpz.': 'CPz', 'Cp2.': 'CP2', 'Cp4.': 'CP4',
'Cp6.': 'CP6', 'Fp1.': 'Fp1', 'Fpz.': 'Fpz', 'Fp2.': 'Fp2', 'Af7.': 'AF7',
'Af3.': 'AF3', 'Afz.': 'AFz', 'Af4.': 'AF4', 'Af8.': 'AF8', 'F7..': 'F7',
'F5..': 'F5', 'F3..': 'F3', 'F1..': 'F1', 'Fz..': 'Fz', 'F2..': 'F2',
'F4..': 'F4', 'F6..': 'F6', 'F8..': 'F8', 'Ft7.': 'FT7', 'Ft8.': 'FT8',
'T7..': 'T7', 'T8..': 'T8', 'T9..': 'T9', 'T10.': 'T10', 'Tp7.': 'TP7',
'Tp8.': 'TP8', 'P7..': 'P7', 'P5..': 'P5', 'P3..': 'P3', 'P1..': 'P1',
'Pz..': 'Pz', 'P2..': 'P2', 'P4..': 'P4', 'P6..': 'P6', 'P8..': 'P8',
'Po7.': 'PO7', 'Po3.': 'PO3', 'Poz.': 'POz', 'Po4.': 'PO4', 'Po8.': 'PO8',
'O1..': 'O1', 'Oz..': 'Oz', 'O2..': 'O2', 'Iz..': 'Iz'
}
raws = list()
icas = list()
# 读取4个被试的第3个数据集到raw,然后将raw添加到raws中
for subj in range(4):
# EEGBCI 被试的下标是从1开始的; run 3 是一个左右手运动任务的二分类数据集
fname = mne.datasets.eegbci.load_data(subj + 1, runs=[3])[0]
# 根据文件名读取相应的数据集到raw中
raw = mne.io.read_raw_edf(fname)
# 去除导联名中的 '.' ,同时进行大小写转换。之后就可以设置montage(导联排布)
raw.rename_channels(mapping)
# 设置为国际1005标准
raw.set_montage('standard_1005')
# 拟合ICA
ica = ICA(n_components=30, random_state=97)
ica.fit(raw)
# 添加raw和ICA到相应的列表中
raws.append(raw)
icas.append(ica)
###############################################################################
# 然后使用 :func:`~mne.preprocessing.corrmap`:
# 使用第一个被试作为模板; 使用 Fpz 作为 EOG 的代理
raw = raws[0]
ica = icas[0]
# 获得以Fpz作为参考模板,与EOG匹配的IC的下标和分数
eog_inds, eog_scores = ica.find_bads_eog(raw, ch_name='Fpz')
# 通过相关图查找跨被试的相似独立分量。
corrmap(icas, template=(0, eog_inds[0]))
###############################################################################
# 第一个图显示了模板图,而第二个图显示了被认为与模板“匹配”的所有映射(包括模板本身)。 四个被试只有三个匹配;
# 注意输出消息“No maps selected for subject [1], consider a more liberal threshold
# (没有为被试 1 选择map,考虑更宽松的阈值)”。
# 默认情况下,阈值是通过尝试多个值自动设置的; 这里它可能选择了一个太高的阈值。
# 让我们看一下每个被试的 ICA 源:
for index, (ica, raw) in enumerate(zip(icas, raws)):
fig = ica.plot_sources(raw)
fig.suptitle('Subject {}'.format(index))
###############################################################################
# 请注意,被试 1 *确实* 似乎有一个 IC 看起来像是反映了眨眼伪影(组件 ``ICA000``)。
# 另请注意,被试 3 似乎有 *两个* components反映了眼部伪影(``ICA000`` 和 ``ICA002``),
# 但只有一个被:func:`~mne.preprocessing.corrmap` 捕获。
# 让我们尝试手动设置阈值:
corrmap(icas, template=(0, eog_inds[0]), threshold=0.9)
###############################################################################
# 现在我们得到的信息是“每个被试至少检测到 1 个 IC”(这很好)。
# 基于这一点,我们将重新运行:func:`~mne.preprocessing.corrmap`,
# 参数为``label=blink, show=False`` 以 *标记* 每个对象捕获眨眼伪影的 IC(不会再次绘制它们)。
corrmap(icas, template=(0, eog_inds[0]), threshold=0.9, label='blink',
plot=False)
print([ica.labels_ for ica in icas])
###############################################################################
# 请注意,第一个被试在索引 0 处有 3 个不同的 IC 标签:
# “eog/0/Fpz”、“eog”和“blink”。
# 前两个是由 :meth:`~mne.preprocessing.ICA.find_bads_eog` 添加的;
# 最后一个则是调用:func:`~mne.preprocessing.corrmap` 添加了“blink”标签。
# 另请注意,每个受试者至少有一个标记为“blink”的 IC 索引,
# 受试者 3 有两个标记为“blink”的components(0 和 2)(与上面的 IC 源图一致)。
# :class:`~mne.preprocessing.ICA` 对象的 ``labels_`` 属性也可以手动编辑以使用自定义标签注释 IC。
# 它们在绘图时也会派上用场:
icas[3].plot_components(picks=icas[3].labels_['blink'])
icas[3].exclude = icas[3].labels_['blink']
icas[3].plot_sources(raws[3])
###############################################################################
# 作为最后一条note, 可以使用如下的方法来提取数字化的ICs
# :meth:`~mne.preprocessing.ICA.get_components` 是属于
# :class:`~mne.preprocessing.ICA` 对象的方法. 这将会返回一个可以传递给如下函数的numpy数组
# :func:`~mne.preprocessing.corrmap` 而不是我们之前传递的元组 :class:`tuple` of
# ``(subject_index, component_index)``, 它们产生的结果是相同的:
template_eog_component = icas[0].get_components()[:, eog_inds[0]]
corrmap(icas, template=template_eog_component, threshold=0.9)
print(template_eog_component)
###############################################################################
# 使用 IC 的这种数字表示来获得特定的伪迹模式的一个优点是,它可以被保存并用作模板,以便进行未来的模板匹配任务使用
# 通过函数:func:`~mne.preprocessing.corrmap` 来实现,而无需加载或重新计算最初产生模板的 ICA 解决方案。
# 换句话说,当模板是 NumPy 数组时,包含模板的 :class:`~mne.preprocessing.ICA`
# 对象不需要在提供给 :func:`~mne.preprocessing.corrmap 的 ICA 列表中`。
#
#
# References
# ^^^^^^^^^^
#
# .. [1] Ablin P, Cardoso J, Gramfort A (2018). Faster Independent Component
# Analysis by Preconditioning With Hessian Approximations. *IEEE
# Transactions on Signal Processing* 66:4040–4049.
# https://doi.org/10.1109/TSP.2018.2844203
#
# .. [2] Winkler I, Debener S, Müller K-R, Tangermann M (2015). On the
# influence of high-pass filtering on ICA-based artifact reduction in
# EEG-ERP. Proceedings of EMBC-2015, 4101–4105.
# https://doi.org/10.1109/EMBC.2015.7319296
#
# .. [3] Dammers J, Schiek M, Boers F, Silex C, Zvyagintsev M, Pietrzyk U,
# Mathiak K (2008). Integration of amplitude and phase statistics for
# complete artifact removal in independent components of neuromagnetic
# recordings. *IEEE Transactions on Biomedical Engineering*
# 55(10):2353–2362. https://doi.org/10.1109/TBME.2008.926677
#
# .. [4] Viola FC, Thorne J, Edmonds B, Schneider T, Eichele T, Debener S
# (2009). Semi-automatic identification of independent components
# representing EEG artifact. *Clinical Neurophysiology* 120(5):868–877.
# https://doi.org/10.1016/j.clinph.2009.01.015
#
# .. [5] Schalk G, McFarland DJ, Hinterberger T, Birbaumer N, Wolpaw JR (2004).
# BCI2000: A General-Purpose Brain-Computer Interface (BCI) System.
# *IEEE Transactions on Biomedical Engineering* 51(6):1034-1043.
# https://doi.org/10.1109/TBME.2004.827072
#
# .. [6] Goldberger AL, Amaral LAN, Glass L, Hausdorff JM, Ivanov PCh, Mark RG,
# Mietus JE, Moody GB, Peng C-K, Stanley HE (2000). PhysioBank,
# PhysioToolkit, and PhysioNet: Components of a New Research Resource
# for Complex Physiologic Signals. *Circulation* 101(23):e215-e220.
# https://doi.org/10.1161/01.CIR.101.23.e215
#
#
# .. LINKS
#
# .. _`blind source separation`:
# https://en.wikipedia.org/wiki/Signal_separation
# .. _`statistically independent`:
# https://en.wikipedia.org/wiki/Independence_(probability_theory)
# .. _`scikit-learn`: https://scikit-learn.org
# .. _`random seed`: https://en.wikipedia.org/wiki/Random_seed
# .. _`regular expression`: https://www.regular-expressions.info/
# .. _`qrs`: https://en.wikipedia.org/wiki/QRS_complex
# .. _`this EEGLAB tutorial`: https://labeling.ucsd.edu/tutorial/labels