Python MNE是一种开源磁脑电图(MEG)和脑电图(EEG)分析和可视化工具。它具有很高的通用性,因为它可以应用于许多设备的数据格式。在本文中,我们将解释由MEG和EEG的MNE进行的分析过程以及最基本的教程。
执行环境
- Mac OS 10.15.3
- Python 3.6.5
- mne 0.20.4
安装
您可以使用Anaconda或pip安装它。建议在官方页面上使用Anaconda。
- 对于水蟒
1 | conda install -c conda-forge mne |
- 对于点
1 | pip install -U mne |
另外,似乎可以设置GPU,因此如果需要花费一些时间进行过滤和采样,则可能需要设置它。
1 2 3 4 5 6 | $ conda install cupy $ MNE_USE_CUDA=true python -c "import mne; mne.cuda.init_cuda(verbose=True)" Enabling CUDA with 1.55 GB available memory >>> mne.utils.set_config('MNE_USE_CUDA', 'true') # mne.io.Raw.filter()などにn_jobs='cuda'を渡す |
MEG / EEG分析教程
在本教程之后,我们将解释EEG分析的典型处理和MNE的基本数据结构。我将以简洁的方式对其进行解释,因此,如果您具有英语和EEG分析的知识,则应阅读原始页面。
分析程序
- 资料载入
- 预处理
- 事件检测
- 切入一个时代
- 时频分析
- 诱发反应的估计
模块导入
1 2 3 | import os import numpy as np import mne |
数据加载
将作为样本准备的数据加载到
mne(所有数据集的列表)中。顺便说一下,MEG和EEG每种设备都有几种文件格式,但是有一个加载这些数据的功能(支持的数据格式)
1 2 3 4 | sample_data_folder = mne.datasets.sample.data_path() sample_data_raw_file = os.path.join(sample_data_folder, 'MEG', 'sample', 'sample_audvis_filt-0-40_raw.fif') raw = mne.io.read_raw_fif(sample_data_raw_file) |
这一次,我们使用
函数
顺便说一下,在该数据的实验中,每750毫秒随机向对象显示视觉刺激和听觉刺激。另外,有时在屏幕上会显示出笑脸,而被摄对象看到它时会按下按钮。这些刺激的表现称为事件。
显示已加载的对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | print(raw) print(raw.info) # output <Raw | sample_audvis_filt-0-40_raw.fif, 376 x 41700 (277.7 s), ~3.6 MB, data not loaded> <Info | 15 non-empty values bads: 2 items (MEG 2443, EEG 053) ch_names: MEG 0113, MEG 0112, MEG 0111, MEG 0122, MEG 0123, MEG 0121, MEG ... chs: 204 GRAD, 102 MAG, 9 STIM, 60 EEG, 1 EOG custom_ref_applied: False dev_head_t: MEG device -> head transform dig: 146 items (3 Cardinal, 4 HPI, 61 EEG, 78 Extra) file_id: 4 items (dict) highpass: 0.1 Hz hpi_meas: 1 item (list) hpi_results: 1 item (list) lowpass: 40.0 Hz meas_date: 2002-12-03 19:01:10 UTC meas_id: 4 items (dict) nchan: 376 projs: PCA-v1: off, PCA-v2: off, PCA-v3: off, Average EEG reference: off sfreq: 150.2 Hz > |
在
MNE中,数据由称为Raw,Epoch和Evoked对象的对象管理。这些通过数据的时分来区分,并且Raw包含从EEG记录开始到停止的所有时间的数据,因此最好将其视为被事件分隔之前的状态。 。
显示此Raw对象的功率谱密度(PSD)和每个传感器的波形。
1 2 | raw.plot_psd(fmax=50) raw.plot(duration=5, n_channels=30) |
预处理
在EEG / MEG分析的噪声处理中,执行标准独立成分分析(ICA)。简而言之,通过将多通道信号分解为独立的分量,可以执行去除与大脑活动无关的事物(例如电源噪声和闪烁)的处理。
此处,对于364通道的信号,在分解为20个独立的分量之后,指定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # set up and fit the ICA ica = mne.preprocessing.ICA(n_components=20, random_state=97, max_iter=800) ica.fit(raw) ica.exclude = [1, 2] # details on how we picked these are omitted here ica.plot_properties(raw, picks=ica.exclude) # output Fitting ICA to data using 364 channels (please be patient, this may take a while) Inferring max_pca_components from picks Selecting by number: 20 components Fitting ICA took 2.4s. Using multitaper spectrum estimation with 7 DPSS windows 138 matching events found No baseline correction applied Not setting metadata 0 projection items activated 0 bad epochs dropped 138 matching events found No baseline correction applied Not setting metadata 0 projection items activated 0 bad epochs dropped |
为了获得去除指定独立分量的信号,请将ICA对象应用??于Raw对象。
1 2 3 | orig_raw = raw.copy() raw.load_data() ica.apply(raw) |
当显示前通道时,如以下两个图所示,消除了噪音。
1 2 3 4 5 6 7 8 9 10 11 12 13 | # show some frontal channels to clearly illustrate the artifact removal chs = ['MEG 0111', 'MEG 0121', 'MEG 0131', 'MEG 0211', 'MEG 0221', 'MEG 0231', 'MEG 0311', 'MEG 0321', 'MEG 0331', 'MEG 1511', 'MEG 1521', 'MEG 1531', 'EEG 001', 'EEG 002', 'EEG 003', 'EEG 004', 'EEG 005', 'EEG 006', 'EEG 007', 'EEG 008'] chan_idxs = [raw.ch_names.index(ch) for ch in chs] orig_raw.plot(order=chan_idxs, start=12, duration=4) raw.plot(order=chan_idxs, start=12, duration=4) # output Reading 0 ... 41699 = 0.000 ... 277.709 secs... Transforming to ICA space (20 components) Zeroing out 2 ICA components |
事件检测
此样本数据包含所谓的STIM通道,其中包含有关事件类型及其时间的数据。这次,名为
1 2 3 4 5 6 7 8 9 10 11 12 | events = mne.find_events(raw, stim_channel='STI 014') print(events[:5]) # show the first 5 # output 319 events found Event IDs: [ 1 2 3 4 5 32] [[6994 0 2] [7086 0 3] [7192 0 1] [7304 0 4] [7413 0 2]] |
<表格>
tr>
header>
<身体>
tr>
tr>
tr>
tr>
tr>
tr>
tbody>
table>
以字典类型存储事件ID和事件描述。顺便说一下,这里的键可以是任何字符串。
1 2 | event_dict = {'auditory/left': 1, 'auditory/right': 2, 'visual/left': 3, 'visual/right': 4, 'smiley': 5, 'buttonpress': 32} |
在时间轴上绘制每个事件的演示时间。先前由
1 2 | fig = mne.viz.plot_events(events, event_id=event_dict, sfreq=raw.info['sfreq'], first_samp=raw.first_samp) |
切开纪元
在MEG / EEG分析中,当调查对某种刺激的响应时,信号被分为称为历元的单位,并被视为一个数据。通过在刺激前后切出一定的部分,将其制成一个数据单元。此切割过程称为外切。原始对象在录制过程中会一直保持连接状态,但是只有一部分对刺激的响应会被剪切掉并存储在称为Epochs对象的数据类型中。
在传世中,经常执行称为阈值拒绝的过程。这意味着,如果在相关时间内包含了太大声的信号,则该部分将产生很大的噪声,并将被从数据中排除。确定排除标准。
1 2 3 4 | reject_criteria = dict(mag=4000e-15, # 4000 fT grad=4000e-13, # 4000 fT/cm eeg=150e-6, # 150 μV eog=250e-6) # 250 μV |
接下来,从Raw对象创建一个Epochs对象。
-
raw :包含信号数据的原始对象 -
events :具有时间和事件ID信息的numpy数组 -
event_id :将事件ID与它们的名称相关联的字典类型 -
tmin :削减刺激演示的秒数(在刺激演示之前加减号) -
tmax :呈现刺激以剪切数据后几秒钟 -
reject :数据排除标准
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | epochs = mne.Epochs(raw, events, event_id=event_dict, tmin=-0.2, tmax=0.5, reject=reject_criteria, preload=True) # output 319 matching events found Applying baseline correction (mode: mean) Not setting metadata Created an SSP operator (subspace dimension = 4) 4 projection items activated Loading data for 319 events and 106 original time points ... Rejecting epoch based on EOG : ['EOG 061'] Rejecting epoch based on EOG : ['EOG 061'] Rejecting epoch based on MAG : ['MEG 1711'] Rejecting epoch based on EOG : ['EOG 061'] Rejecting epoch based on EOG : ['EOG 061'] Rejecting epoch based on MAG : ['MEG 1711'] Rejecting epoch based on EEG : ['EEG 008'] Rejecting epoch based on EOG : ['EOG 061'] Rejecting epoch based on EOG : ['EOG 061'] Rejecting epoch based on EOG : ['EOG 061'] 10 bad epochs dropped |
这次似乎已排除了10个时期。
由于这次没有处理按下被摄体的按钮的定时,因此仅以视听刺激事件为对象。另外,为了防止数据的数量在条件之间偏移,通过用
1 2 3 | conds_we_care_about = ['auditory/left', 'auditory/right', 'visual/left', 'visual/right'] epochs.equalize_event_counts(conds_we_care_about) # this operates in-place |
在
1 2 3 | aud_epochs = epochs['auditory'] vis_epochs = epochs['visual'] del raw, epochs # free up memory |
在听觉数据中指定通道,并以相同的刺激提示时间显示平均波形。
1 2 3 4 5 6 7 8 9 10 11 12 13 | aud_epochs.plot_image(picks=['MEG 1332', 'EEG 021']) # output 136 matching events found No baseline correction applied Not setting metadata 0 projection items activated 0 bad epochs dropped 136 matching events found No baseline correction applied Not setting metadata 0 projection items activated 0 bad epochs dropped |
作为补充,由于可以通过Epochs对象的
1 2 3 | aud_epochs.get_data().shape (136, 376, 106) # (エポック,チャンネル,時刻) |
这同样适用于以下返回numpy数组的频率处理。
时频分析
进行时频分析以研究在MEG / EEG波形中出现刺激之前和之后的时间与频率之间的关系。在此,通过小波分析计算出对听觉刺激的反应并绘制。如彩条所示,红色越深,则该频率的幅度越大。 (更详细的示例)
1 2 3 4 5 6 7 | frequencies = np.arange(7, 30, 3) power = mne.time_frequency.tfr_morlet(aud_epochs, n_cycles=2, return_itc=False, freqs=frequencies, decim=3) power.plot(['MEG 1332']) # output No baseline correction applied |
估计诱发反应
作为MNE的数据类型,Evoked对象是Epochs对象的总和。 MEG / EEG数据具有除大脑活动以外的大量噪声,通常通过求平均值来研究条件之间的差异。
在这里,我们绘制了听觉数据和视觉数据的添加波形之间的差异。
1 2 3 4 5 | aud_evoked = aud_epochs.average() vis_evoked = vis_epochs.average() mne.viz.plot_compare_evokeds(dict(auditory=aud_evoked, visual=vis_evoked), legend='upper left', show_sensors='upper right') |
引发的对象具有进一步分析的方法。如果显示每个通道的波形,则可以看到跳动(P200)在前通道的100ms(N100)内变为负值,并在200ms左右具有正峰值。
1 | aud_evoked.plot_joint(picks='eeg') |
您还可以在头皮上显示称为地形的分布。在这里,可以看到,在头皮上观察到的具有红色正电位和蓝色负电位的脑电波如下。
1 | aud_evoked.plot_topomap(times=[0., 0.08, 0.1, 0.12, 0.2], ch_type='eeg') |
另外,要查看条件之间的差异,
1 2 | evoked_diff = mne.combine_evoked([aud_evoked, -vis_evoked], weights='equal') evoked_diff.pick_types('mag').plot_topo(color='r', legend=False) |
结论
我在这里仅介绍了基本功能,但是由于MNE官方页面上准备了许多教程和示例,所以我希望您可以将其作为进一步详细分析的第一步。
另外,由于Python具有许多用于统计和机器学习的库,我认为通过MEG / EEG机器学习进行分析将更加容易。