超详细TMS-EEG数据处理教程(下)

文章来源于微信公众号(茗创科技),欢迎有兴趣的朋友搜索关注。


上一期的文章TMS-EEG数据处理教程(上)中详细地介绍了TMS伪影类型和预处理步骤。这期主要讲了完成数据预处理后,再进行一些(后)处理步骤,如过滤、去趋势、去均值和降采样。但要注意的是,一些分析步骤可能需要对数据进行不同的处理。例如,当查看经颅磁刺激诱发电位(TEPs)时,你可能想要滤除数据中的高频噪声,但在执行时频分析时(滤除高频噪声)是不必要的;你可能也希望对数据进行去趋势操作,但这同样不建议用于分析TEPs。

幸运的是,这些函数(例如ft_timelockanalysisft_freqanalysis)允许对输入数据进行与ft_preprocessing相同的预处理步骤。这适用于对每步分析进行单独的处理,而不必创建额外的数据结构。

这里先只对数据进行降采样,接下来会应用到不同的(后)处理步骤。降采样需要使用ft_resampledata

cfg = [];

cfg.resamplefs = 1000;cfg.detrend = 'no';

cfg.demean = 'yes'; 

% Prior to downsampling a lowpass filter is applied, demeaning avoids artifacts at the edges of your trialdata_tms_clean = ft_resampledata(cfg, data_tms_clean);

接下来先需要将数据进行保存。

save('data_tms_clean','data_tms_clean','-v7.3');

分析

我们最初的问题是预收缩是否会影响经颅磁刺激诱发电位。为了解决这个问题,接下来将比较TEP的振幅,检查TMS的响应频率,并查看全局平均场功率。

锁时平均

当前数据集中有两个条件要比较:' relax ' & ' contract '。条件在数据集中通过EEG中的标记显示出来。读取数据时,基于这些标记的试次,可以在数据结构trialinfo字段中找到每个试次属于哪个条件的信息。在这里,“放松”条件用数字1表示,“收缩”条件用数字3表示。

>> data_tms_clean.trialinfo

ans =    

 1    

 1    

 1    

 1    

 .    

 .   

 .    

 3    

 3    

 3    

 .    

 .   

 .

我们可以使用该字段中的信息分别对这两个条件执行锁时分析。trialinfo字段中的每一行都对应于数据集中的一个试次。

在计算锁时平均值时,应用基线校正(TMS发生前50ms到1ms),进行35Hz的低通滤波。

cfg = [];

cfg.preproc.demean = 'yes';

cfg.preproc.baselinewindow = [-0.05 -0.001];cfg.preproc.lpfilter = 'yes';

cfg.preproc.lpfreq = 35;

% Find all trials corresponding to the relax conditioncfg.trials = find(data_tms_clean.trialinfo==1);relax_avg = ft_timelockanalysis(cfg, data_tms_clean);

% Find all trials corresponding to the contract conditioncfg.trials = find(data_tms_clean.trialinfo==3);

contract_avg = ft_timelockanalysis(cfg, data_tms_clean);

计算两个条件的平均值之间的差,使用函数ft_math,对一个或多个数据结构执行一定数量的数学操作。

% calculate difference

cfg = [];

cfg.operation ='subtract'; % Operation to apply

cfg.parameter ='avg'; % The fieldinthe data structure towhichto apply the operation

difference_avg = ft_math(cfg, contract_avg, relax_avg);

使用ft_singleplotER绘制条件及其差异,该函数非常适合绘制和绘制比较条件

% Plot TEPsofboth conditions

cfg = [];

cfg.layout ='easycapM10'; % Specifyingthisallows you to produce topographical plotsofyour datacfg.channel ='17';

cfg.xlim = [-0.10.6];

ft_singleplotER(cfg, relax_avg, contract_avg, difference_avg);

ylabel('Amplitude (uV)');

xlabel('time (s)');

title('Relax vs Contract');

legend({'relax''contract''contract-relax'});

ft_singleplotER一个很好的特点是,如果指定一个布局,你可以在绘图窗口中选择一个时间范围,然后单击它来生成该时间点的振幅会在地形图上显示出来。你也可以使用ft_topoplotER函数来完成此步操作。

%% Plotting topographies

figure;

cfg = [];cfg.layout = 'easycapM10';

cfg.xlim = 0:0.05:0.55; % Here we've specified a vector between 0 and 0.55 seconds in steps of 0.05 seconds. A topoplot will be created for each time point specified here.

cfg.zlim = [-2 2]; % Here you can specify the limit of thevaluescorrespondingtothe colors.Ifyoudonotspecify this the limits will be estimated automaticallyforeachplot making it difficulttocompare subsequent plots.

ft_topoplotER(cfg, difference_avg);

全局平均场功率

全局平均场功率(GMFP)是Lehmann和Skandries(1979)首次提出的一种测量方法,例如,Esser等人(2006)使用该方法来表征全局EEG活动。GMFP可以用以下公式计算(来自Esser et al. (2006))。 

其中t为时间,V为channel i处的电压,K为channel数。在Esser等人(2006)中,GMFP是根据所有被试的平均水平计算的。因为这里只有一个被试的数据,所以只计算这个被试的GMFP。但如果有多个被试,那么可以在进行总平均时用相同的方法进行计算。基本上,GMFP是channel上的标准差。

FieldTrip有一个内置的函数来计算GMFP;ft_globalmeanfield,这个函数需要输入锁时数据。这里将使用与Esser等人(2006)类似的预处理。

% Create time-locked average

cfg = [];cfg.preproc.demean = 'yes';

cfg.preproc.baselinewindow = [-0.1 -.001];cfg.preproc.bpfilter = 'yes';

cfg.preproc.bpfreq = [5 100];cfg.trials = find(data_tms_clean.trialinfo==1); 

% 'relax' trialsrelax_avg = ft_timelockanalysis(cfg, data_tms_clean);

cfg.trials = find(data_tms_clean.trialinfo==3); 

% 'contract' trialscontract_avg = ft_timelockanalysis(cfg, data_tms_clean);

% GMFP calculation

cfg = [];

cfg.method = 'amplitude';

relax_gmfp = ft_globalmeanfield(cfg, relax_avg);

contract_gmfp = ft_globalmeanfield(cfg, contract_avg);

现在可以画出两个条件的GMFP。

%Plot GMFP

figure;

plot(relax_gmfp.time, relax_gmfp.avg,'b');holdon;

plot(contract_gmfp.time, contract_gmfp.avg,'r');

xlabel('time (s)');

ylabel('GMFP (uv^2)');

legend({'Relax''Contract'});

xlim([-0.10.6]);

ylim([03]);

时频分析

把信号分解成频率,然后看这些频率的功率平均值。首先使用ft_freqanalysis将信号分解成不同的频率。在做光谱分析时,重要的是在分解成不同频率之前去趋势和去均值,以避免功率谱看起来很奇怪。因此,可以使用preproc选项对数据进行去趋势和去均值。

% Calculate Induced TFRs fpor both conditions

cfg = [];

cfg.polyremoval    =1; % Removes mean and linear trend

cfg.output          ='pow'; % Output the powerspectrum

cfg.method          ='mtmconvol';cfg.taper          ='hanning';

cfg.foi            =1:50; % Our frequenciesofinterest. Now:1to50,instepsof1.

cfg.t_ftimwin      =0.3.*ones(1,numel(cfg.foi));

cfg.toi            =-0.5:0.05:1.5;

% Calculate TFRforrelax trials

cfg.trials        = find(data_tms_clean.trialinfo==1);

relax_freq        = ft_freqanalysis(cfg, data_tms_clean);

% Calculate TFRforcontracttrials

cfg.trials        = find(data_tms_clean.trialinfo==3);

contract_freq      = ft_freqanalysis(cfg, data_tms_clean);

计算条件之间的差异。通常在绘制TFRs时,指定一个基线窗口。由于这里需计算条件之间的差异,并且对基线校正后的两个条件之间的差异感兴趣,所以这里需要先从条件中删除基线。

% Remove baseline

cfg = [];

cfg.baselinetype = 'relchange'; % Calculate the change relative to the baseline ((data-baseline) / baseline). You can also use 'absolute', 'relative', or 'db'.

cfg.baseline = [-0.5 -0.3];

relax_freq_bc = ft_freqbaseline(cfg, relax_freq);

contract_freq_bc = ft_freqbaseline(cfg, contract_freq);

% Calculate the difference between both conditions

cfg = [];

cfg.operation = 'subtract';

cfg.parameter = 'powspctrm';

difference_freq = ft_math(cfg, contract_freq_bc, relax_freq_bc);

现在已经计算了两种条件的TFR及其差异,我们可以用不同的方法绘制结果。使用ft_multiplotTFR脚本以头部2D形式绘制所有TFR。

cfg = [];

cfg.xlim = [-0.1 1.0];

cfg.zlim = [-1.5 1.5];

cfg.layout = 'easycapM10';

figure;

ft_multiplotTFR(cfg, difference_freq);

此图是完全交互式的,单击并拖动以选择一个或多个channel,单击以查看所选channel的均值。还可以使用ft_singleplotTFR在单个视图中绘制单个(或多个)channel。

cfg = [];

cfg.channel ='17'; % Specify the channel to plot

cfg.xlim = [-0.11.0]; % Specify thetimerange to plot

cfg.zlim = [-33];

cfg.layout ='easycapM10';

figure;

subplot(1,3,1); % Use MATLAB's subplot function to divide plots into one figure

ft_singleplotTFR(cfg, relax_freq_bc);

ylabel('Frequency (Hz)');

xlabel('time(s)');

title('Relax');

subplot(1,3,2);

ft_singleplotTFR(cfg, contract_freq_bc);

title('Contract');

ylabel('Frequency (Hz)');

xlabel('time(s)');

subplot(1,3,3);

cfg.zlim = [-1.5 1.5];

ft_singleplotTFR(cfg, difference_freq);

title('Contract - Relax');

ylabel('Frequency (Hz)');

xlabel('time(s)');

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容