Python-EEG工具库MNE
一、环境配置
安装MNE-python
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import mne from mne.datasets import sample import matplotlib.pyplot as plt
fname = 'F:/data/MNE-sample-data/MEG/sample/sample_audvis_raw.fif'
""" 如果上述给定的地址中存在该文件,则直接加载本地文件, 如果不存在则在网上下载改数据 """ raw = mne.io.read_raw_fif(fname)
""" 案例: 获取10-20秒内的良好的MEG数据
# 根据type来选择 那些良好的MEG信号(良好的MEG信号,通过设置exclude="bads") channel, 结果为 channels所对应的的索引 """
picks = mne.pick_types(raw.info, meg=True, exclude='bads') t_idx = raw.time_as_index([10., 20.]) data, times = raw[picks, t_idx[0]:t_idx[1]] plt.plot(times,data.T) plt.title("Sample channels") plt.show()
|

二、MNE中数据结构Raw及其用法简介
Raw对象主要用来存储连续型数据,核心数据为n_channels和times,也包含Info对象。
1、打开raw数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import mne from mne.datasets import sample import matplotlib.pyplot as plt
fname = data_path + '/MEG/sample/sample_audvis_raw.fif'
""" 如果上述给定的地址中存在该文件,则直接加载本地文件, 如果不存在则在网上下载改数据 """ raw = mne.io.read_raw_fif(fname)
|
1 2 3 4 5 6 7 8 9
| data, times = raw[picks, time_slice]
data,times=raw[:] data,times=raw[:,:]
|
2、sfreq:采样频率
1 2 3 4 5 6 7 8 9 10
| """ sfreq:采样频率
raw返回所选信道以及时间段内的数据和时间点, 分别赋值给data以及times(即raw对象返回的是两个array) """ sfreq=raw.info['sfreq'] data,times=raw[:5,int(sfreq*1):int(sfreq*3)] plt.plot(times,data.T) plt.title("Sample channels")
|

3、绘制各通道的功率谱密度
1 2
| raw.plot_psd() plt.show()
|

4、绘制SSP矢量图
1 2
| raw.plot_projs_topomap() plt.show()
|

5、绘制通道频谱图作为topography
1 2
| raw.plot_psd_topo() plt.show()
|

6、绘制电极位置
1 2
| raw.plot_sensors() plt.show()
|

三、MNE从头创建Raw对象
1、简单介绍
在实际过程中,有时需要从头构建数据来创建Raw对象。
方式:通过mne.io.RawArray
类来手动创建Raw
注:使用mne.io.RawArray创建Raw对象时,其构造函数只接受矩阵和info对象。
数据对应的单位:
V: eeg, eog, seeg, emg, ecg, bio, ecog
T: mag
T/m: grad
M: hbo, hbr
Am: dipole
AU: misc
构建一个Raw对象时,需要准备两种数据,一种是data数据,一种是Info数据,
data数据是一个二维数据,形状为(n_channels,n_times)
2、包装数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| """ 生成一个大小为5x1000的二维随机数据 其中5代表5个通道,1000代表times """ data = np.random.randn(5,1000)
""" 创建info结构, 内容包括:通道名称和通道类型 设置采样频率为:sfreq=100 """ info = mne.create_info( ch_names=['MEG1','MEG2','EEG1','EEG2','EOG'], ch_types=['grad','grad','eeg','eeg','eog'], sfreq=100 )
custom_raw = mne.io.RawArray(data,info)
|
3、对图形进行缩放
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| """ 对图形进行缩放
对于实际的EEG / MEG数据,应使用不同的比例因子。 对通道eeg、grad,eog的数据进行2倍缩小 """
scalings = {'eeg':2,'grad':2,'eog':2}
custom_raw.plot(n_channels=5, scalings=scalings, title='Data from arrays', show=True, block=True) plt.show()
|

四、MNE中数据结构Epoch
从连续的脑电图信号中提取一些特定时间窗口的信号,这些时间窗口可以称作为epochs
.
1、创建Epochs对象方式有三种:
- (1)通过Raw对象和事件事件点(event times)-
- (2)通过读取.fif文件数据生成Epoch对象
- (3)通过mne.EpochsArray从头创建Epoch对象
2、读取fif文件创建Epoch对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| 步骤: 1)读取fif文件,构建raw对象; 2)创建event对象; 3)创建epoch对象; 4)对epoch进行叠加平均得到evoked对象; 5)绘制evoked。
import mne from mne import io from mne.datasets import sample
data_path = sample.data_path()
raw_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw.fif' event_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw-eve.fif' event_id, tmin, tmax = 1, -0.2, 0.5
raw = io.read_raw_fif(raw_fname)
events = mne.read_events(event_fname)
""" 挑选通道:EEG + MEG - bad channels """ raw.info['bads'] += ['MEG 2443', 'EEG 053'] picks = mne.pick_types(raw.info, meg=True, eeg=False, stim=True, eog=True, exclude='bads')
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)) """ 对epochs数据进行求平均获取诱发响应 """ evoked = epochs.average()
evoked.plot(time_unit='s') plt.show()
|
3、从头创建Epoch对象
Epochs对象是一种将连续数据表示为时间段集合的方法
方式:利用mne.EpochsArray
创建Epochs对象,创建时直接构建numpy数组即可,数组的形状必须是(n_epochs, n_chans, n_times)
数据对应的单位:
- V: eeg, eog, seeg, emg, ecg, bio, ecog
- T: mag
- T/m: grad
- M: hbo, hbr
- Am: dipole
- AU: misc
第一步:构建数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 第一步:构建数据
构建一个大小为10x5x200的三维数组,数组中数据是随机数; 第一维数据表示:10 epochs 第二维数据表示:5 channels 第三维数据表示:2 seconds per epoch
sfreq = 100 data = np.random.randn(10, 5, sfreq * 2)
info = mne.create_info( ch_names=['MEG1', 'MEG2', 'EEG1', 'EEG2', 'EOG'], ch_types=['grad', 'grad', 'eeg', 'eeg', 'eog'], sfreq=sfreq )
|
第二步:构建events
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 在创建Epochs对象时,必须提供一个"events"数组,
事件(event)描述的是某一种波形(症状)的起始点,其为一个三元组,形状为(n_events,3): 第一列元素以整数来描述的事件起始采样点; 第二列元素对应的是当前事件来源的刺激通道(stimulus channel)的先前值(previous value),该值大多数情况是0; 第三列元素表示的是该event的id。
events = np.array([ [0, 0, 1], [1, 0, 2], [2, 0, 1], [3, 0, 2], [4, 0, 1], [5, 0, 2], [6, 0, 1], [7, 0, 2], [8, 0, 1], [9, 0, 2], ])
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 设置事件的id
如果是dict,则以后可以使用这些键访问关联的事件。示例:dict(听觉=1,视觉=3) 如果是int,将创建一个id为string的dict。 如果是列表,则使用列表中指定ID的所有事件。 如果没有,则所有事件都将与一起使用,并使用与事件id整数对应的字符串整数名称创建dict。
event_id = dict(smiling=1, frowning=2) """ tmin:event开始前的时间,如果未指定,则默认为0 """
tmin = -0.1
|
第三步:创建epochs对象
1 2 3 4 5 6 7
| """ 利用mne.EpochsArray创建epochs对象 """ custom_epochs = mne.EpochsArray(data, info, events, tmin, event_id) print(custom_epochs)
_ = custom_epochs['smiling'].average().plot(time_unit='s')
|

4、查看epoch对象
epochs对象类似于mne.io.Raw对象,也具有info属性和event属性。
可以通过下面两种方式来查看epoch内的event相关信息
1 2 3 4 5 6 7 8 9
| print(epochs.events[:3]) print(epochs.event_id)
print(epochs[1:5]) print(epochs['Auditory/Right'])
print(epochs['Right']) print(epochs['Right', 'Left'])
|
5、epoch平均叠加
通过调用mne.Epochs.average()
方法可返回Evoked对象,average()方法可以通过参数指定需要的信道。
1 2 3 4 5 6 7 8
| ev_right = epochs['Right'].average() ev_left = epochs['Left'].average()
f, axs = plt.subplots(3, 2, figsize=(10, 5)) _ = f.suptitle('Left / Right auditory', fontsize=20) _ = ev_left.plot(axes=axs[:, 0], show=False, time_unit='s') _ = ev_right.plot(axes=axs[:, 1], show=False, time_unit='s') plt.tight_layout()
|

有时候使用mne
的metadata
属性来存储相关数据特别有用,metadata使用pandas.DataFrame
来封装数据。其中每一行对应一个epoch,每一列对应一个epoch的元数据属性。列必须包含字符串、整数或浮点数。
7、Epochs数据可视化
mne.Epochs.plot()
提供了一个交互式浏览器,当与关键字block = True
结合使用时,允许手动拒绝。这将阻止脚本执行,直到关闭浏览器窗口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| """ 加载数据,如果本地无该数据, 则从网络中下载 """ 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_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)
|
1 2 3
| epochs.plot(block=True) plt.show()
|

顶部的数字表示epoch的事件id。底部的数字是各个epoch的运行编号。
五、Evoked结构
Evoked potential(EP)诱发电位或诱发反应是指在出现诸如闪光或纯音之类的刺激后,从人类或其他动物的神经系统,特别是大脑的特定部分记录的特定模式的电位。不同形式和类型的刺激会产生不同类型的电位。
诱发电位振幅往往较低,从小于1微伏到数微伏不等,而脑电图为数十微伏,肌电图为毫伏,心电图通常接近20毫伏。为了在EEG、ECG、EMG等生物信号和环境噪声的背景下解决这些低幅度电位,通常需要对信号进行平均。信号被时间锁定在刺激上,大部分噪声是随机产生的,这样就可以通过对重复响应来平均掉噪声。
诱发电位(Evoked)结构主要用于存储实验期间的平均数据,在MNE中,创建Evoked对象通常使用mne.Epochs.average()
来平均epochs数据来实现。