ERP学习笔记-频域分析之小波变换fieldtrip

**频域分析:**在不同的频率下数据的情况

**注意:**本脚本使用的是fieldtrip-20170830,不要轻易更改版本,可能会报错

修改后代码可以根据Cond_all自动运行每个不同条件的数据,并保存为struct格式

第一步:条件设置

Matlab 复制代码
%定义每个条件的marker信息
Cond_all = {'B1(S57)','onlygo-go-cue';'B2(S77)','onlygo-go-go';'B3(S41)','uninf-go-cue';'B4(S61)','uninf-go-go'}';

第二步:将数据转换为fieldtrip可以分析的格式

基础代码
Matlab 复制代码
%% Transform data
%定义数据所在的路径
data_root = 'E:\data';
%筛选路径下所有set格式的文件
filenames = dir([data_root, filesep, '*.set']);
%提取文件的个数信息
subj_num = length(filenames);
%创建空胞元以储存后续信息
all_EEG = cell(subj_num,1);%所有的
all_EEG_B1 = cell(subj_num,1);%条件B1
all_EEG_B2 = cell(subj_num,1);%条件B2
all_EEG_B3 = cell(subj_num,1);
%对于每个被试
for i = 1:subj_num
    %拼接数据的绝对路径
    fn = [data_root, filesep, filenames(i).name];
    %导入subj_num被试的数据
    EEG = pop_loadset(fn);
    %分别提取B1 B2 B3条件的数据
    %对应eeglab中条件的mark形式,以及关注的时间段
    %如果读取的数据没有进行基线校正,这里需要进行基线校正
    EEG_B1 = pop_epoch(EEG, {'B1(S11)'},[-0.5 3]);
    EEG_B2 = pop_epoch(EEG, {'B2(S12)'},[-0.5 3]);
    EEG_B3 = pop_epoch(EEG, {'B3(S13)'},[-0.5 3]);
    %分别储存所有数据 B1 B2 B3条件的数据
    all_EEG{i} = EEG;
    all_EEG_B1{i} = EEG_B1;
    all_EEG_B2{i} = EEG_B2;
    all_EEG_B3{i} = EEG_B3;
end
%保存数据为mat文件
save('all_EEG.mat','all_EEG');
save('all_EEG_B1.mat','all_EEG_B1');
save('all_EEG_B2.mat','all_EEG_B2');
save('all_EEG_B3.mat','all_EEG_B3');
%% eeglab 2 fieldtrip
%创建空胞元以储存后续信息
all_data = cell(subj_num,1);
all_data_B1 = cell(subj_num,1);
all_data_B2 = cell(subj_num,1);
all_data_B3 = cell(subj_num,1);
%对于每个被试
for i=1:subj_num
    %对第i个被试进行数据格式转化
    all_data{i} = eeglab2fieldtrip(all_EEG{i}, 'preprocessing');
    all_data_B1{i} = eeglab2fieldtrip(all_EEG_B1{i}, 'preprocessing');
    all_data_B2{i} = eeglab2fieldtrip(all_EEG_B2{i}, 'preprocessing');
    all_data_B3{i} = eeglab2fieldtrip(all_EEG_B3{i}, 'preprocessing');
end
%保存数据为mat文件
save('data_transformed.mat','all_data','all_data_B1','all_data_B2','all_data_B3');
修改后代码
Matlab 复制代码
%% Transform data
%% 基础设置
%epochs的开始时间
time_start = -0.5;%%%%%%需修改
%epochs的结束时间
time_end = 1;%%%%%%需修改
%epochs的时间段
time_epoch = [time_start time_end];
%基线校正的时间段
time_baseline = [time_start*1000 0];
%定义数据所在的路径
data_root = path_re_ref;%%%%%%需修改
%筛选路径下所有set格式的文件
filenames = dir([data_root, filesep, '*.set']);
%提取文件的个数信息
subj_num = length(filenames);
%% 创建空胞元以储存后续信息,自动根据Cond_all生成
% 提取第一列的所有B编号
b_names = Cond_all(1,:);
% 创建结构体来存储所有EEG数据
all_EEG = struct();
data_transf = struct();
% all_EEG.all = cell(subj_num, 1);
% 循环创建cell数组
for i = 1:length(b_names)
    % 使用正则表达式提取B编号(如B3、B4、B10等)
    b_match{i} = regexp(b_names{i}, 'B\d+', 'match');
    field_name = char(b_match{i});  % 直接使用匹配到的B编号
    all_EEG.(field_name) = cell(subj_num, 1);%保存初始数据
    data_transf.(field_name) = cell(subj_num, 1);%保存eeglab 2 fieldtrip后数据
end
%% 读取eeglab中的数据,分条件保存到all_EEG中,并转换数据保存到data_transf中
%对于每个被试
for nsub = 1:subj_num
    %拼接数据的绝对路径
    fn = [data_root, filesep, filenames(nsub).name];
    %导入subj_num被试的数据
    EEG = pop_loadset(fn);
    % all_EEG.all{nsub} = EEG;
    %遍历每个条件,分别提取B1 B2 B3条件的数据
    %对应eeglab中条件的mark形式,以及关注的时间段
    %如果读取的数据没有进行基线校正,这里需要进行基线校正
    for i = 1:length(b_match)
        b_name = char(b_match{i});  % 如 'B3', 'B4'
        b_epoch_name = b_names{i};  % 如 'B3(S41)', 'B4(S61)'
        % 处理EEG数据
        EEG_temp = pop_epoch(EEG, {b_epoch_name}, time_epoch);
        EEG_temp = pop_rmbase(EEG_temp, time_baseline, []);
        % eeglab 2 fieldtrip
        data_temp = eeglab2fieldtrip(EEG_temp, 'preprocessing');
        % 存储到结构体
        all_EEG.(b_name){nsub} = EEG_temp;
        data_transf.(b_name){nsub} = data_temp;
    end
end
%保存数据为mat文件
save('all_EEG.mat','all_EEG');
save('data_transf.mat','data_transf');

第三步:进行小波变换和基线校正

基础代码
Matlab 复制代码
%%
load('data_transformed.mat')
%提取被试的数量
subj_num = length(all_data);
%创建空胞元以保存后续信息
all_data_tf = cell(subj_num,1);
all_data_tf_B1 = cell(subj_num,1);
all_data_tf_B2 = cell(subj_num,1);
all_data_tf_B3 = cell(subj_num,1);
cfg = [];
cfg.method     = 'wavelet';
cfg.keeptrials =  'no';
cfg.output     = 'pow';
cfg.foi        = 3:1:40;%关注频段
% cfg.width      = 7;
cfg.width      = linspace(3,7,length(cfg.foi));
cfg.toi        = -0.5:0.001:1;	%关注时间段
cfg.pad = 'nextpow2';% more efficient FFT computation than the default 'maxperlen'
%对于每一个被试
for  i = 1:subj_num
    %根据cfg中的指定参数,对data进行时频变换
    %dimord与powspctrm中的内容是对应的
    all_data_tf{i} = ft_freqanalysis(cfg,all_data{i});
    all_data_tf_B1{i} = ft_freqanalysis(cfg,all_data_B1{i});
    all_data_tf_B2{i} = ft_freqanalysis(cfg,all_data_B2{i});
    all_data_tf_B3{i} = ft_freqanalysis(cfg,all_data_B3{i});
end
save('data_tf.mat','all_data_tf','all_data_tf_B1','all_data_tf_B2','all_data_tf_B3');

基线校正,以all_data_tf为例

Matlab 复制代码
%% 以all_data_tf为例
load('data_tf.mat')
%% 基线校正
load data_tf.mat
cfg = [];
cfg.baseline = [-0.5 0];%需要根据自己的数据修改
cfg.baselinetype =  'relchange';
cfg.parameter = 'powspctrm';
for i = 1:length(all_data_tf)
    all_data_baseline_tf{1,i} = ft_freqbaseline(cfg, all_data_tf{1,i});
end
save('data_tf_baseline.mat','all_data_baseline_tf');
修改后代码
Matlab 复制代码
%% 小波变换
load('data_transf.mat')
%% 提取被试的数量
% 获取结构体的所有字段名
fields = fieldnames(data_transf);
first_field_data = data_transf.(fields{1});
subj_num = size(first_field_data, 1);
%% 创建空胞元以保存后续信息
data_TFR = struct();
data_TFR_baseline = struct();
% 提取第一列的所有B编号
b_names = Cond_all(1,:);
% 循环创建cell数组
for i = 1:length(b_names)
    % 使用正则表达式提取B编号(如B3、B4、B10等)
    b_match{i} = regexp(b_names{i}, 'B\d+', 'match');
    field_name = char(b_match{i});  % 直接使用匹配到的B编号
    data_TFR.(field_name) = cell(subj_num, 1);%保存小波变换后数据
    data_TFR_baseline.(field_name) = cell(subj_num, 1);%保存基线校正后的数据
end
%% 时频变换和基线校正
cfg = [];
cfg.method     = 'wavelet';
cfg.keeptrials =  'no';
cfg.output     = 'pow';
cfg.foi        = 3:1:40;%关注频段
% cfg.width      = 7;
cfg.width      = linspace(3,7,length(cfg.foi));
cfg.toi        = -0.5:0.001:1;	%关注时间段
cfg.pad = 'nextpow2';% more efficient FFT computation than the default 'maxperlen'
%基线校正
cfg.baseline = [-0.5 0];%%%%%%需修改
cfg.baselinetype =  'relchange';
cfg.parameter = 'powspctrm';
%对于每一个被试
for  nsub = 1:subj_num
    %根据cfg中的指定参数,对data进行时频变换
    %dimord与powspctrm中的内容是对应的
    for i = 1:length(b_match)
        b_name = char(b_match{i});  % 如 'B3', 'B4'
        data_TFR.(b_name){nsub} = ft_freqanalysis(cfg,data_transf.(b_name){nsub});%时频变换
        data_TFR_baseline.(b_name){nsub} = ft_freqbaseline(cfg,data_TFR.(b_name){nsub});%基线校正
    end
end
save('data_TFR.mat','data_TFR');
save('data_TFR_baseline.mat','data_TFR_baseline');

第四步:画图

基础代码

以all_data_tf为例

Matlab 复制代码
%% 画图
load data_tf_baseline.mat
cfg = [];
cfg.channel = 'all';
%进行时频维度的组水平叠加平均
group_data_tf = ft_freqgrandaverage(cfg,all_data_tf{:});
%% 绘制所有通道的时频图,按照通道位置摆放
cfg = [];
%定义通道排布系统
cfg.layout = 'EEG1005.lay';
%是否可以界面交互
cfg.interactive = 'yes';
%是否绘制头轮廓
cfg.showoutline = 'yes';
%绘图
ft_multiplotTFR(cfg,group_data_tf);
%% 绘制单幅时频图,按照通道
cfg = [];
%定义通道排布系统
cfg.layout = 'EEG1005.lay';
%选择的通道
%如果cfg.channel中定义了多个通道,则是绘制这多个通道的均值
%cfg.channel = {'Cz','Fz'};
%如果像绘制单个通道的时频图,则
cfg.channel = 'Cz';
%绘图
ft_multiplotTFR(cfg,group_data_tf);
%% 绘制特定时频域下的地形图
cfg = [];
%定义通道排布系统
cfg.layout = 'EEG1005.lay';
%感兴趣的时间段
cfg.xlim = [0.08 0.42];
%感兴趣频率段
cfg.ylim = [8 13];
%定义colorbar
cfg.zlim = [-5.21e+06 5.21e+06];
%绘图
ft_multiplotTFR(cfg,group_data_tf);
相关推荐
QiZhang | UESTC1 小时前
学习日记day40
学习
大江东去浪淘尽千古风流人物2 小时前
【MSCKF】UpdaterHelper 学习备注
学习
hmbbcsm2 小时前
python学习之路(十三)[闭包,装饰器,函数式编程,生成器]
学习
眠晚晚3 小时前
漏洞发现笔记分享
笔记·web安全·网络安全
云半S一3 小时前
春招准备之Redis篇
数据库·经验分享·redis·笔记·缓存
丝斯20114 小时前
AI学习笔记整理(26)—— 计算机视觉之目标追踪‌
人工智能·笔记·学习
('-')4 小时前
《从根上理解MySQL是怎样运行的》第二十五章笔记
数据库·笔记·mysql
m0_689618284 小时前
会“变形”的软3D电磁结构,让4D电子、柔性机器人迎来新可能
笔记·学习·机器人
雍凉明月夜4 小时前
c++ 精学笔记记录Ⅰ
开发语言·c++·笔记