基于matlab的脑电数据预处理

  • matlab
  • ERP预处理
  • 批处理

posted on 01 Mar 2019 under category EEG

上一篇文章主要讲的是ERP预处理的基本流程,如果按照上面步骤去操作的话,每个被试数据预处理的时间可能要在1个小时左右,这样工作效率就会非常低。在这篇文章中,主要解决的问题是如何运用代码进行批处理。我会给大家逐行讲解代码的含义,并且告诉大家哪些参数需要自己修改,大家可以利用私有云上提供的样本数据体验一下运用代码跑数据的乐趣。以下是完整的ERP预处理matlab代码:


%% The function of this code is to preprocess EEG data
%% Author:kangkang

clear all; close all;clc  

for sub = [1:10];

    EEG = pop_loadbv('E:\yukang\EEG数据处理\R\前测\正常\', strcat('sub',num2str(sub),'.vhdr'), [], [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]);
    EEG = eeg_checkset( EEG );

    EEG = pop_chanedit(EEG, 'lookup','E:\\Matlabtools\\eeglab12_0_2_0b\\plugins\\dipfit2.2\\standard_BESA\\standard-10-5-cap385.elp');
    EEG = eeg_checkset( EEG );

    EEG = pop_select( EEG,'nochannel',{'VEOG' 'HEOG'});
    EEG = eeg_checkset( EEG );

    EEG = pop_reref( EEG, 19);
    EEG = eeg_checkset( EEG );

    EEG = pop_eegfiltnew(EEG, [], 0.1, 33000, true, [], 1);
    EEG = eeg_checkset( EEG );

    EEG = pop_eegfiltnew(EEG, [], 40, 330, 0, [], 1);
    EEG = eeg_checkset( EEG );

    EEG = pop_epoch( EEG, {  'S 21'  'S 22'  }, [-1  2], 'epochinfo', 'yes');
    EEG = eeg_checkset( EEG );

    EEG = pop_rmbase( EEG, [-200    0]);
    EEG = eeg_checkset( EEG );

    EEG = pop_saveset( EEG, 'filename',strcat('sub',num2str(sub),'.set'),'filepath','E:\preprocesing_1\');
    EEG = eeg_checkset( EEG );

end

下面是对以上代码的逐行解释

matlab中的注释

上面代码中的前两行文字的颜色都比较浅,文字的开头都是 %%,这便是matlab的注释符号,注释符号可以出现在代码的开头,也可以出现在每行代码的后面。它的功能是对该段(行)代码提供解释,是给使用该段代码的人看的,计算机在遇到%之后会自动跳过而不执行其后的内容。

matlab中的清空命令行

正式代码的第一行,即

clear all; close all; clc

这三个命令,即clear all,close all,clc都是清空的命令,只是它们三个清空的内容都不同。clear all清空地是当前工作区的所有数据,clc清空地是当前命令行窗口的所有内容,close all清空地是当前matlab生成地所有画布(figure),如下图所示:

p1

一般在运行一段代码之前都会将matlab工作区的数据、命令行的命令和之前生成的画布全部清除掉,以免造成不必要的bug

matlab中的循环功能

正式代码中的第二行,即:

for sub = [1:10];

     ...

end

它的功能是实现被试的循环,这也是用代码进行预处理的优势所在,不用人工对每个被试进行重复的点点点。其中需要注意的是 for 和 end 必须配套使用,否则会出现语法错误。=后边的数字的含义是从1到10的整数,这个需要根据自己的实验被试的数量改动。

具体处理流程

接下来的代码就是实现预处理流程的自动化,和上一篇文章中讲到的GUI操作流程基本一致。

导入数据

p2

如上图所示,右边的pop_loadbv是eeglab内置的导入文件函数,其后括号中全部的内容都是它的参数。第一个引号中的内容是原始数据存放的路径,这个需要改成自己的路径;紧跟着后面的strcat是一个拼接字符串的函数,它的功能也就是将两个及以上的字符串给拼接成一个字符串,在这里,我想让大家看一下我的原始数据存在形式:

p3

如上图所示,我将所有被试的数据都命名成“sub + 被试编号”的形式(后面的文件格式不要改动),这样做的目的是可以让所有的数据都能进入到循环中去,所以大家在用代码跑预处理的时候要将数据进行重新命名(这里需要提醒的是,需要做一个文档将被试的编号和被试的名字对应起来,防止后面遇到数据质量问题的时候可以追踪溯源)。再回到代码中,在拼接字符串函数里面还包含一个函数num2str,它的功能是将数字类型转换成字符串类型。拼接字符串函数的后面是一个空的中括号,其实里面放的是被试的采样点数,因为每个被试的采样点数不同,所以这里就不填。最后面是电极点的编号,如果是64导的话就需要改一下了。下面这一行在每一步完成之后都会出现,这个也不用改动。

定位电极

p4

上面这一行代码的功能对应的是定位电极,不需要做出改动

删除无用电极


EEG = pop_select( EEG,'nochannel',{'VEOG' 'HEOG'});
EEG = eeg_checkset( EEG );

上面代码的功能对应着删除无用电极,大括号里面的内容是要删除的电极名称,这个可以根据需要自行删减。

重参考


EEG = pop_reref( EEG, 19);
EEG = eeg_checkset( EEG );

以上代码的功能对应重参考,用到的函数pop_reref也是eeglab的内置函数,函数里面的参数是电极点的编号,如果用双侧乳突作为参考,就要填写双侧乳突电极点对应的编号,并用中括号括起来,如果用平均参考,就直接改成一个空的中括号,即:


EEG = pop_reref( EEG, []);
EEG = eeg_checkset( EEG );

滤波


EEG = pop_eegfiltnew(EEG, [], 0.1, 33000, true, [], 1);
EEG = eeg_checkset( EEG );

EEG = pop_eegfiltnew(EEG, [], 40, 330, 0, [], 1);
EEG = eeg_checkset( EEG );

滤波的代码如上图所示,用到的函数pop_eegfiltnew同样是eeglab的内置函数,前两行是高通滤波,后两行是低通滤波,如果你要修改滤波的参数,可以修改以上代码中的0.1(高通参数)或者40(低通参数)。

分段


EEG = pop_epoch( EEG, {  'S 21'  'S 22'  }, [-1  2], 'epochinfo', 'yes');
EEG = eeg_checkset( EEG );

以上代码是的功能是分段,用到的函数是pop_epoch,参数设置中,大括号里面放置的是用作分段的Mark,中括号里面是分段的时间窗口,这些都可以根据自己的实验需求修改,参数的含义可参见上一篇文章。

基线矫正


EEG = pop_rmbase( EEG, [-200    0]);
EEG = eeg_checkset( EEG );

基线矫正用到的函数是pop_rmbase,中括号中的数字是基线矫正的时间,一般就是以刺激出现前200毫秒作为基线,故此处不用作修改。

文件保存


EEG = pop_saveset( EEG, 'filename',strcat('sub',num2str(sub),'.set'),'filepath','E:\preprocesing_1\');
EEG = eeg_checkset( EEG );

文件保存的函数是pop_saveset,其中filepath后面的路径需要改为自己存放文件的路径。

删除坏段

以上步骤是可以用机器代替我们运行的,因为所有步骤都是重复的操作。但是对于质量有问题的trail(如反应错误、头动眼漂的成分)的筛选要根据个人经验来判断,这个只能是自己一段一段的看。这里,我们需要将之前保存好的文件再次导入eeglab中,这时导入的菜单与原始数据导入的方式不同,参照如下菜单:

p5

p6

接下来的操作步骤参见上一篇文章,完成之后再将该被试的数据保存起来。

Run ICA

ICA的步骤是重复性的,可以让机器代替我们工作。参照以下代码:


clear all; close all; clc;

for sub = [1:10];

    EEG = pop_loadset('filename',strcat('sub',num2str(sub),'.set'),'filepath','E:\preprocesing_1\');
    EEG = eeg_checkset( EEG );

    EEG = pop_runica(EEG, 'extended',1,'interupt','on');
    EEG = eeg_checkset( EEG );

    EEG = pop_saveset( EEG, 'filename',strcat('sub',num2str(sub),'.set'),'filepath','E:\preprocesing_2\');
    EEG = eeg_checkset( EEG );

end

以上代码的中间一段就是Run ICA 的,前后两段分别是用来导入和储存数据的,这里需要自己更改一下自己存放数据的路径。

去除眼电等成分

和删除坏段类似,去除眼电等成分也是需要通过个人经验进行识别的,所以这一步同样只能通过手动操作,所有被试都重复一遍,具体操作常见上一篇文章,这里就不再赘述。

保存数据

ICA跑完之后,就手动点击菜单栏保存数据,这样的话,整个预处理的流程就算走完了。相较完全的GUI操作,运用代码操作可以节省不少的时间,当然前提是代码要能够运行。

其它补充

除了上面说到的内容之外,还有如下几点补充

EEG.history

当我们用GUI手动处理完一个被试的数据之后,可以尝试着在命令行窗口敲下EEG.history,可以发现之前运行的所有过程matlab都自动帮我们记录下来了,上面预处理的批处理代码就是根据EEG.history反馈的内容修改成的

插值坏导

在上一篇文章中提到过,插值坏导的步骤只能通过代码来实现,代码如下:


EEG.data(a,:,:) = mean(EEG.data9([b c d],:,:));

字母 a,b,c,d 分别代表电极对应的编号,b,c,d 电极是a电极周围的几个电极。

路径命名

这里需要提醒的是,在我们对路径命令的时候,尽量避免用中文,一些matlab版本在路径中遇到中文字符时会报错

其它重要命令

在matlab中,有些比较重要的函数,例如help,当你想要了解某个函数的用法时,可以使用它。例如,你想要了解mean函数的用法,你就可以在命令行窗口打出一下命令:


help(mean)

按回车后,matlab就会反馈出mean的用法介绍

以上就是这篇文章的所有内容,大家可以从私有云上下载样例数据进行练习。