【思维导图】脑机接口MNE工具箱中关于epoch的基础知识点

整理自【脑机接口社区】的几篇文章:

  1. (2)-MNE中数据结构Epoch及其创建方法
  2. (3)-MNE中数据结构Epoch及其用法简介Python-EEG工具库MNE中文教程
  3. (14)-Epoch对象中的元数据(metadata)
  4. (15)-Epochs数据可视化
  5. (16)-脑电数据的Epoching处理
    【思维导图】脑机接口MNE工具箱中关于epoch的基础知识点_第1张图片
    【思维导图】脑机接口MNE工具箱中关于epoch的基础知识点_第2张图片
(3)-数据结构Epoch及其创建方法
	epochs 定义
		 从连续的脑电图信号中提取一些特定时间窗口的信号,这些时间窗口可以称作为epochs.
		由于EEG是连续收集的,要分析脑电事件相关的电位时,需要将信号"切分"成时间片段,这些时间片段被锁定到某个事件(例如刺激)中的时间片段。
	举个例子
		 假设我们有一个长度为60s的信号x,采样频率为1 Hz.
			脑电信号的矩阵表示为1x60矩阵,
		如果将信号划分成一些2s的信号,则将有30个peoch(信号中每2s就是一个epoch)
	在MNE中,Epoch对象是一种把连续型数据作为时间段集合的表示方法,
		 形状为(n_events,n_channels,n_times)的数组形式:
	创建Epochs对象方式有三种:
		(1)通过Raw对象和事件事件点(event times)
		 (2)通过读取.fif文件数据生成Epoch对象
			a. 读取fif文件创建Epoch对象
				 1)读取fif文件,构建raw对象;
					raw_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw.fif'
				 2)创建event对象;
					event_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw-eve.fif'
					event_id, tmin, tmax = 1, -0.2, 0.5
						为什么event id = 1
					events = mne.read_events(event_fname)
				 3)创建epoch对象;
					epochs = mne.Epochs(raw, events, event_id, tmin, tmax, proj=True,
                    picks=picks, baseline=(None, 0), preload=True,
                    reject=dict(grad=4000e-13, mag=4e-12, eog=150e-6))
						mne.Epochs
					b.查看epoch对象
						print(epochs.events[:3])
							[[27977     0     2]
 [28771     0     1]
 [29652     0     2]]
						print(epochs.event_id)
							{'Auditory/Left': 1, 'Auditory/Right': 2}
				 4)对epoch进行叠加平均得到evoked对象;
					evoked = epochs.average()
					evoked.plot(time_unit='s')
plt.show() 
				 5)绘制evoked。
		 (3)通过mne.EpochsArray从头创建Epoch对象

【思维导图】脑机接口MNE工具箱中关于epoch的基础知识点_第3张图片

a. 读取fif文件创建Epoch对象
	 1)读取fif文件,构建raw对象;
		raw_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw.fif'
	 2)创建event对象;
		event_id, tmin, tmax = 1, -0.2, 0.5
			为什么event id = 1
		events = mne.read_events(event_fname)
			event_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw-eve.fif'
	 3)创建epoch对象;
		epochs = mne.Epochs(raw, events, event_id, tmin, tmax, proj=True,
                    picks=picks, baseline=(None, 0), preload=True,
                    reject=dict(grad=4000e-13, mag=4e-12, eog=150e-6))
			mne.Epochs
		b.查看epoch对象
			print(epochs.events[:3])
				[[27977     0     2]
 [28771     0     1]
 [29652     0     2]]
				打印前三个
			print(epochs.event_id)
				{'Auditory/Left': 1, 'Auditory/Right': 2}
	 4)对epoch进行叠加平均得到evoked对象;
		evoked = epochs.average()
			叠加平均
		evoked.plot(time_unit='s')
plt.show() 
	 5)绘制evoked。

【思维导图】脑机接口MNE工具箱中关于epoch的基础知识点_第4张图片
【思维导图】脑机接口MNE工具箱中关于epoch的基础知识点_第5张图片

脑机接口MNE工具箱epoch基础知识点
	(3)-数据结构Epoch及其创建方法
		epochs 定义
			 从连续的脑电图信号中提取一些特定时间窗口的信号,这些时间窗口可以称作为epochs.
			由于EEG是连续收集的,要分析脑电事件相关的电位时,需要将信号"切分"成时间片段,这些时间片段被锁定到某个事件(例如刺激)中的时间片段。
		举个例子
			 假设我们有一个长度为60s的信号x,采样频率为1 Hz.
				脑电信号的矩阵表示为1x60矩阵,
			如果将信号划分成一些2s的信号,则将有30个peoch(信号中每2s就是一个epoch)
		在MNE中,Epoch对象是一种把连续型数据作为时间段集合的表示方法,
			 形状为(n_events,n_channels,n_times)的数组形式:
				(n_events,n_channels,n_times)
		创建Epochs对象方式有三种:
			(1)通过Raw对象和事件事件点(event times)
			 (2)通过读取.fif文件数据生成Epoch对象
				a. 读取fif文件创建Epoch对象
					 1)读取fif文件,构建raw对象;
						raw_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw.fif'
					 2)创建event对象;
						event_id, tmin, tmax = 1, -0.2, 0.5
							为什么event id = 1
						events = mne.read_events(event_fname)
							event_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw-eve.fif'
					 3)创建epoch对象;
						epochs = mne.Epochs(raw, events, event_id, tmin, tmax, proj=True,
                    picks=picks, baseline=(None, 0), preload=True,
                    reject=dict(grad=4000e-13, mag=4e-12, eog=150e-6))
							mne.Epochs
						b.查看epoch对象
							print(epochs.events[:3])
								[[27977     0     2]
 [28771     0     1]
 [29652     0     2]]
								打印前三个
							print(epochs.event_id)
								{'Auditory/Left': 1, 'Auditory/Right': 2}
					 4)对epoch进行叠加平均得到evoked对象;
						evoked = epochs.average()
							叠加平均
						evoked.plot(time_unit='s')
plt.show() 
					 5)绘制evoked。
			 (3)通过mne.EpochsArray从头创建Epoch对象
	(14)-Epoch对象中的元数据(metadata)
		有时候使用mne的metadata属性来存储相关数据特别有用,metadata使用pandas.DataFrame来封装数据。
			其中每一行对应一个epoch,
			每一列对应一个epoch的元数据属性。
				列必须包含字符串、整数或浮点数。
		案例
			#导入工具
				import mne
				import numpy as np
				import matplotlib.pyplot as plt
			#加载数据
				path = mne.datasets.kiloword.data_path() + '/kword_metadata-epo.fif'
					从上面打印的信息可以知道该数据集中有960个样本数据。
				epochs = mne.read_epochs(path)
				epochs.metadata[:10]
					# 元数据以panda.DataFrame的形式存储数据
						# 获取前10条记录
							print(epochs.metadata.head(10))
					我们可以使用该元数据属性来选择epoch的子集。
						这使用了Pandas中的pandas.DataFrame.query()方法。
							任何有效的查询字符串都将起作用。
			"""
注意,传统的epoch子选择仍然有效。
传统的选择epoch的MNE方法将取代丰富的元数据查询。
"""
				epochs['cent'].average().plot(show=False, time_unit='s')
plt.show()
			下面,我们将绘制两个图进行比较:
				av1 = epochs['Concreteness < 5 and WordFrequency < 2'].average()
av2 = epochs['Concreteness > 5 and WordFrequency > 2'].average()
joint_kwargs = dict(ts_args=dict(time_unit='s'),
                    topomap_args=dict(time_unit='s'))
av1.plot_joint(show=False, **joint_kwargs)av2.plot_joint(show=False, **joint_kwargs)
plt.show()
					子主题 1
					子主题 2
					Concreteness < 5 and WordFrequency < 2
			words = ['film', 'cent', 'shot', 'cold', 'main']
epochs['WORD in {}'.format(words)].plot_image(show=False)

				plt.show()
			下面将展示一个更复杂的示例,该示例利用每个epoch的元数据。
				我们将在元数据对象中创建一个新列,并使用它生成许多试验子集的平均值。
					metadata = epochs.metadatais
_concrete = metadata["Concreteness"] > metadata["Concreteness"].median()
metadata["is_concrete"] = np.where(is_concrete, 'Concrete', 'Abstract')
is_long = metadata["NumberOfLetters"] > 5
metadata["is_long"] = np.where(is_long, 'Long', 'Short')
epochs.metadata = metadata
				"""
现在我们可以快速提取(并绘制)数据的子集。
例如,看按单词长度和具体程度划分的单词:
"""
					query = "is_long == '{0}' & is_concrete == '{1}'"evokeds = dict()
for concreteness in ("Concrete", "Abstract"):
    for length in ("Long", "Short"):
        subset = epochs[query.format(length, concreteness)]
        evokeds["/".join((concreteness, length))] = list(subset.iter_evoked())
				# 为了进行实际的可视化,下面存储了许多共享参数。
					style_plot = dict(
    colors={"Long": "Crimson", "Short": "Cornflowerblue"},
    linestyles={"Concrete": "-", "Abstract": ":"},
    split_legend=True, 
   ci=.68, 
   show_sensors='lower right',
    legend='lower left',
    truncate_yaxis="auto",
    picks=epochs.ch_names.index("Pz"),)fig, ax = plt.subplots(figsize=(6, 4))
					共享参数。
				#绘制诱发响应
					mne.viz.plot_compare_evokeds(evokeds, axes=ax, **style_plot)
plt.show()
				下面比较不同字母长度(字母个数)单词所得到的诱发响应。
					比较长度为4、5、6、7或8个字母的单词:
						letters = epochs.metadata["NumberOfLetters"].unique().astype(int).astype(str)evokeds = dict()
for n_letters in letters:
    evokeds[n_letters] = epochs["NumberOfLetters == " + n_letters].average()
style_plot["colors"] = {n_letters: int(n_letters)
                        for n_letters in letters}style_plot["cmap"] = ("# of Letters", "viridis_r")
del style_plot['linestyles']
fig, ax = plt.subplots(figsize=(6, 4))
mne.viz.plot_compare_evokeds(evokeds, axes=ax, **style_plot)
plt.show()
				最后,对于字母的具体性与连续长度之间的相互作用:
					evokeds = dict()
query = "is_concrete == '{0}' & NumberOfLetters == {1}"
for concreteness in ("Concrete", "Abstract"):
    for n_letters in letters:
        subset = epochs[query.format(concreteness, n_letters)]
        evokeds["/".join((concreteness, n_letters))] = subset.average()
style_plot["linestyles"] = {"Concrete": "-", "Abstract": ":"}
fig, ax = plt.subplots(figsize=(6, 4))
mne.viz.plot_compare_evokeds(evokeds, axes=ax, **style_plot)
plt.show()
	(15)-Epochs数据可视化
		高级matplotlib函数
			所有方法均返回matplotlib图形实例的句柄。
		mne.Epochs.plot()提供了一个交互式浏览器,
			当与关键字block = True结合使用时,允许手动拒绝。
			这将阻止脚本执行,直到关闭浏览器窗口。
		# 加载工具包
			import os.path as op
			import mne
			import matplotlib.pyplot as plt
		# 加载数据
			"""加载数据,如果本地无该数据,则从网络中下载"""
				data_path = op.join(mne.datasets.sample.data_path(), 'MEG', 'sample')
				raw = mne.io.read_raw_fif(    op.join(data_path, 'sample_audvis_filt-0-40_raw.fif'), preload=True)
			# 设置
				event IDevent_id = {'auditory/left': 1, 'auditory/right': 2, 'visual/left': 3,'visual/right': 4, 'smiley': 5, 'button': 32}
events = mne.find_events(raw)
epochs = mne.Epochs(raw, events, event_id=event_id, tmin=-0.2, tmax=.5,
                    preload=True)
del raw
		# 绘制
			epochsepochs.plot(block=True)
plt.show()
				顶部的数字表示epoch的事件id。
					事件id?
				底部的数字是各个epoch的运行编号。
		因为这里没有进行人为的伪影校正或剔除,所以有一些epoch数据被眨眼和扫视污染。
			例如,epoch 1似乎被眨眼污染了(滚动到底部查看EOG通道)。
			单击浏览器窗口的顶部可以将这个epoch标记为剔除。
				单击时,epoch应该变为红色。
					这意味着当浏览器窗口关闭时,它将被删除。
		通过将events关键字传递给epochs绘图仪,可以在epoched数据上绘制事件标记。
			这些事件被绘制为竖线,它们遵循与mvc.viz.plot_events()相同的着色方案。
				由于颜色相同,事件绘图仪也可以作为epochs绘图仪事件的图例。
				也可以通过event_colors关键字传递自己的颜色。
				颜色
			在这里,我们可以绘制看到笑脸和按下按钮之间的反应时间(事件32)。
			在传递事件时,默认情况下,底部的epoch编号是关闭的,以避免重叠。
				你可以通过设置对话框通过按o键重新打开它。
		# 绘制
			 eventsevents = mne.pick_events(events, include=[5, 32])
				mne.viz.plot_events(events)
			# 绘制smiley的epochs
				epochs['smiley'].plot(events=events)
				plt.show()
			为了一眼就可以看到所有的epoch,可以使用函数mne.epoch.plot_image()将各个通道绘制为图像。
				 它可以显示信号在所有时间点上的振幅,加上激活的平均(诱发响应)。 
					显式地将交互式colorbar设置为on
						(默认情况下也是on,以使用除topo绘图以外的colorbar来绘制函数)。
					在交互模式下,可以通过鼠标滚动和上下箭头键来缩放和改变颜色图。
						也可以用鼠标左右拖动颜色栏。
						按下空格键则会重置比例。
				epochs.plot_image(278,
                  cmap='interactive',
                  sigma=1.,
                  vmin=-250, vmax=250)
					No baseline correction applied
Not setting metadata
0 projection items activated
0 bad epochs dropped
				这里还可以通过计算全局字段功率(或其他聚合方法)来概述所有通道。
					但是,以这种方式组合多个通道类型(例如MEG和EEG)是不明智的,
					因此,如果未指定特定的通道选择,默认情况下plot_image()方法将为每个通道类型生成单独的图形。
						epochs.plot_image(combine='gfp', sigma=2., cmap="YlGnBu_r")
						为每个通道类型生成单独的图形。
				mne.epoch.plot_image()
			这里还可以使用一些函数来绘制按通道排列成通道阵列形状的信息。
				图像绘制时默认情况下使用自动缩放,但是有噪声的通道和不同的通道类型会导致缩放有点小。
				epochs.plot_topo_image(vmin=-250,
                       vmax=250,
                       title='ERF images',
                       sigma=2.,
                       fig_facecolor='w',
                       font_color='k')
	(16)-脑电数据的Epoching处理
		首先,读入原始样本数据:
			data_path = mne.datasets.sample.data_path()
fname = op.join(data_path, 'MEG', 'sample', 'sample_audvis_raw.fif')
raw = mne.io.read_raw_fif(fname)
		# 设置EEG 平均参考
			raw.set_eeg_reference('average', projection=True)
		要创建时间锁定的epochs,首先需要一组包含有关时间信息的事件。
			这里使用刺激通道来定义事件。
				order = np.arange(raw.info['nchan'])
					注意底部的STI 014频道。
						触发通道用于将所有事件合并到单个通道中。
							触发通道
					从上图上可以看到在整个记录中有几个振幅不同的脉冲。
						这些脉冲对应于在采集过程中呈现给受试者的不同刺激。
							脉冲的值为1、2、3、4、5和32。
			"""交换两个通道的绘图顺序,以将触发通道显示为第十个通道。"""
				order[9] = 312
order[312] = 9  
raw.plot(n_channels=10, order=order, block=True)
plt.show()
				要从原始数据创建事件列表,MNE中只需调用一个专门用于此目的的函数。
				由于事件列表只是一个numpy数组,所以也可以手动创建一个。
				如果是从外部源(如单独的事件文件)创建事件,则应注意将事件与原始数据正确对齐。
					events = mne.find_events(raw)
print('Found %s events, first five:' % len(events))
print(events[:5])
			时间锁定的epochs
		"""绘制事件以了解范例为图例指定颜色和event_id字典。"""
			event_id = {'Auditory/Left': 1, 'Auditory/Right': 2,
            'Visual/Left': 3, 'Visual/Right': 4,
            'smiley': 5, 'button': 32}
color = {1: 'green', 2: 'yellow', 3: 'red', 4: 'c', 5: 'black', 32: 'blue'}

mne.viz.plot_events(events, raw.info['sfreq'], raw.first_samp, color=color,
                    event_id=event_id)
plt.show()
				320 events found
				Event IDs: [ 1  2  3  4  5 32]
Found 320 events, first five:
[[27977     0     2]
 [28345     0     3]
[28771     0     1]
 [29219     0     4]
 [29652     0     2]]

					如上面所示,事件列表包含三列。  
						第一列对应于样本编号,要将此转换为秒,可以将采样数除以使用的采样频率。  
						第二列是在转换时保留给触发器通道的旧值,目前没有使用。  
						第三列是触发ID(脉冲幅度)。
		这里说明一下为什么这些样本看起来与绘制的数据不一致。
			例如,第一个事件的样本编号为27977,应该转换为大约46.6秒(27977 / 600)。
				但是查看脉冲时,可以在3.6秒时看到第一个脉冲。
				这是因为Neuromag记录有一个first_samp属性,它表示系统启动和录制开始之间的偏移量。
					Neuromag记录数据的first_samp等于25800。
					这意味着使用raw.plot看到的第一个样本的样本号25800。
			一般来说,在使用时不需要担心这个偏移量,因为它在MNE函数中已经被考虑进去了,不过最好要注意这一点。
			为了确认一下,我们将事件与原始数据一起绘制。
				raw.plot(events=events, n_channels=10, order=order)
				plt.show()
				注意垂直线(事件)如何与STI 014上的脉冲很好地对齐。
					这些触发器对应于听觉和视觉刺激。
		这里定义了阈值来去除噪声。
			阈值被定义为epoch时间窗口内的峰到峰的值。
			定义为T/m表示梯度计,
			T表示磁强计,
			V表示EEG和EOG电极。
			阈值
		epochs = mne.Epochs(raw, events=events,
                    event_id=event_id, tmin=tmin,
                    tmax=tmax, baseline=baseline,
                    reject=reject, 
                   picks=('meg', 'eog'))
			baseline = (None, 0.0)
				为了得到一些有意义的结果,我们还希望将这些epochs作为基线。
					基线化计算基线期间的平均值并相应地调整数据。
					epochs构造函数默认使用从tmin到0.0秒的基线周期,作为元组的第一个元素的None指的是时间窗口的开始(本例中为-200 ms)
			reject = {'mag': 4e-12, 'eog': 200e-6}
				 # 这里只包含 MEG 和 EOG
				reject 拒绝
			tmin, tmax = -0.2, 0.5
event_id = {'Auditory/Left': 1, 'Auditory/Right': 2, 
           'Visual/Left': 3, 'Visual/Right': 4}
				首先,我们为mne.Epochs构造函数定义一些参数,tmin和tmax指的是与事件相关的偏移量,并使用epoch来封装事件前200毫秒到事件后500毫秒的数据。
			这里的event_id可以是int、int列表或dict。
				使用dict可以将这些id分配给不同的类别。
					dict
				当使用int或列表时,这个信息就会丢失。
					int
			289 matching events found
Applying baseline correction (mode: mean)
Not setting metadata
Created an SSP operator (subspace dimension = 3)
4 projection items activated
				 baseline
				SSP
		epochs.plot(block=True)
plt.show()
			下面就绘制epochs查看结果。
			顶部的数字是指ID号,从图中可以看到145个事件中有128个通过了rejection process。
				rejection process
		epochs.plot_drop_log()
plt.show()
			通过绘制drop日志,来查看为什么剔除epoch(一般被伪影等污染的epoch数据需要被剔除)。
		picks = mne.pick_types(epochs.info, meg=True, eog=True)
evoked_left = epochs['Auditory/Left'].average(picks=picks)evoked_right = epochs['Auditory/Right'].average(picks=picks)
			要获得诱发响应,只需执行epoch.average()。
				它默认只包含数据通道。
			为了便于举例,我们还使用pick来包含EOG通道。
			epochs['Auditory/Left']
				注意,这里使用了前斜杠('/')来分隔实验条件的各个因素。
		epochs_left = epochs['Left']
# ... or to select a very specific subset. 

This is the same as above:

evoked_left_again = epochs['Left/Auditory'].average(picks=picks)
			我们可以使用这些“标签”来选择例如所有左侧试验(包括视觉左侧和听觉右侧)。
		下面绘制诱发响应
			evoked_left.plot(time_unit='s')
evoked_right.plot(time_unit='s')
plt.show()

整理自【脑机接口社区】的几篇文章:

  1. (2)-MNE中数据结构Epoch及其创建方法
  2. (3)-MNE中数据结构Epoch及其用法简介Python-EEG工具库MNE中文教程
  3. (14)-Epoch对象中的元数据(metadata)
  4. (15)-Epochs数据可视化
  5. (16)-脑电数据的Epoching处理

你可能感兴趣的:(【茂森】脑机接口算法,【茂森】脑机接口宏观掌握)