本教程描述了events的表示方式以及如何使用events数组对数据进行选择。
像往常一样,我们将首先导入:

1
2
3
4
5
6
7
8
9
10
11
12
import os

import numpy as np

import mne

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 = mne.io.read_raw_fif(sample_data_raw_file, verbose=False)
raw.crop(tmax=60).load_data()

Reading 0 … 36037 = 0.000 … 60.000 secs…

之前我们已经描述了从raw对象获取events数组的不同方法。由于示例数据集包括在stim通道sti014上记录的实验事件,因此我们将通过使用mne.find_events()解析来自该通道的事件开始本教程:

1
events = mne.find_events(raw, stim_channel="STI 014")

86 events found on stim channel STI 014
Event IDs: [ 1 2 3 4 5 32]

读写events数据

events数组是NumPy数组对象,因此可以使用NumPy.save()将它们作为二进制.npy文件保存到磁盘。然而,MNE-Python提供了方便的函数mne.read_events()mne.write_events(),用于文本文件(常见的文件扩展名是.eve、.lst和.txt)或二进制文件读写events数组。

1
2
3
4
5
sample_data_events_file = os.path.join(
sample_data_folder, "MEG", "sample", "sample_audvis_raw-eve.fif"
)
events_from_file = mne.read_events(sample_data_events_file)
assert np.array_equal(events, events_from_file[: len(events)])

将events数组写入磁盘时,按照惯例,MNE-Python期望事件文件具有.eve扩展名,或者具有以-eve或_eve结尾的文件名,如果不遵守此惯例将发出警告。

对events进行再选择和合并

find_events()告诉我们找到的事件数量,以及存在的唯一整数事件id:

1
mne.find_events(raw, stim_channel="STI 014")

86 events found on stim channel STI 014
Event IDs: [ 1 2 3 4 5 32]

如果对其中一些事件不感兴趣,可以使用mne.pick_events()轻松地对事件进行再选择,该函数具有参数includeexclude。(就像pick_events一样,read_events也一样)例如,在示例数据中,Event ID 32可以排除为:

1
events_no_button = mne.pick_events(events, exclude=32)

也可以使用mne.merge_events()组合两个事件id;下面的示例将事件id 1、2和3合并为一个标记为1的事件:

1
2
merged_events = mne.merge_events(events, [1, 2, 3], 1)
print(np.unique(merged_events[:, -1]))

[ 1 4 5 32]

如果只是想汇总试验类型进行分析,则不需要合并事件。下一节将介绍MNE-Python如何使用events字典将事件id映射到更具描述性的标签字符串。

将事件id映射到标签字符串

events的整数ID是根据直流电压脉冲幅度分配的。跟踪哪个ID对应于哪个实验条件比较麻烦,而且在分析期间通常需要将实验条件合并。你可能还记得,对于示例数据集,整数ID到标签的映射在入门教程的这个表中给出。这里,我们简单地将该映射复制为一个事件字典:

1
2
3
4
5
6
7
8
event_dict = {
"auditory/left": 1,
"auditory/right": 2,
"visual/left": 3,
"visual/right": 4,
"smiley": 5,
"buttonpress": 32,
}

像这样的events字典在从连续数据中提取epochs时使用,得到的epoch对象允许通过请求描述字符串来访问。例如,如果我们想合并所有听觉试验,而不是使用merge_events()函数合并事件id 1和2,我们可以利用event_dict的键包含由/字符分隔的多个描述:请求'auditory'将选择所有具有事件id 1和2的epoch;请求'left'将选择所有事件id为1和3的epoch。以后的教程会反复用到这个方法

绘制events

events字典的另一个用途是绘制events,它可以作为一种很有用的检查,确保事件信号被正确地发送到STIM通道,并且MNE-Python已经成功地找到了它们。函数mne.viz.plot_events()将绘制每个事件与其样本数的关系,如果提供采样频率,它将以秒为单位绘制它们与时间的关系。它也可以用first_samp参数来解释Neuromag系统中样本数和样本索引之间的偏移。如果提供了events字典,它将用于生成图例:

1
2
3
fig = mne.viz.plot_events(
events, sfreq=raw.info["sfreq"], first_samp=raw.first_samp, event_id=event_dict
)

image.png

把raw数据和events一起画出来

在raw数据绘图时传递events参数即可:

1
2
3
4
5
6
7
raw.plot(
events=events,
start=5,
duration=10,
color="gray",
event_color={1: "r", 2: "g", 3: "b", 4: "m", 5: "y", 32: "k"},
)

image.png

创建等间隔的events数组

对于分析静息态的实验,raw记录中可能不包括任何events。在这种情况下,可以使用mne.make_fixed_length_events()生成等距时间的events数组:

1
new_events = mne.make_fixed_length_events(raw, start=5, stop=50, duration=2.0)

默认情况下,所有事件都将被赋予整数Event ID为1,但您可以使用id参数进行更改。也可以指定overlap持续时间——也就是说,如果你最终想要2.5秒长的epoch,但你想要它们重叠0.5秒,你可以在调用make_fixed_length_events()时指定duration=2.5, overlap=0.5,这将产生与duration=2, overlap=0相同的事件间隔。