使用topoplot函数可以轻松实现在matlab的figure中绘制脑电拓扑图,但对于大量数据,如果每次都手动调用topoplot绘制单张拓扑图片,将会消耗大量时间和精力,这里手写了一个matlab脚本读取存放在excel文件中的批量数据并实现批量绘图。
1.数据源的存储结构
数据源为excel文件,excel文件内的数据截图如下:
数据基本分为三个部分:特征列,数据列和电极点列,其中:
- 特征列:代表数据的一个特征,
- 电极点列:表示测量数据所在的电极点位置
- 数据列:存储脑电强度数据
2.输入参数
算法前几行为输入参数:
参数名称 | 参数说明 |
---|---|
featurecol | 所选特征列在excel文件中的列标(数组) |
datacol | 数据列的列标(数组) |
loccol | 电极点数据在excel文件中的列标(int) |
boundlimitcol | 根据此列数据进行分组并计算每组的最大值和最小值,绘图时为同组的数据分配相同的上小限(int) |
3.输出结构
算法会根据输入的excel文件名,在源文件目录下创建一个同名文件夹(这里称之为一级目录);在此文件夹下,算法会根据数据列数组的名称,继续创建和数据列数量相同的同名文件夹,(这里称之为二级目录);最后,算法会在多个二级目录下,生成对应的脑电拓扑图,同时算法用“-”将每条数据的特征连接起来作为每个图片的文件名。输出文件的树形结构如下:
|--data.xlsx(源文件)
|--data(一级目录)
|--------数据列1(二级目录)
|---------------------文件1.png
|---------------------文件1.png
|---------------------文件1.png
|...
|---------------------文件n.png
|--------数据列2(二级目录)
...
...
算法生成的图片截图如下:
4.代码
运行此代码需要用到topoplot、chanlocsseek两个函数以及chanlocsposi.mat等文件,文件下载链接在开头,算法已更新V3.0版本请在文章开头下载!
clear all
clc
% filepath = uigetdir('*.*','请选择文件夹');%fliepath为文件夹路径</span>
featurecol=[1,3,4,5,6]; %特征列
datacol=7; %数据列
loccol=2; %电极点列
boundlimitcol=1; %限制画图上下限的列标
%调用GUI界面选择文件
% [filename1,filepath1]=uigetfile('*.xlsx','打开文件');
% filepath=strcat(filepath1,filename1);
filepath='源数据.xlsx';
[num,txt,raw]=xlsread(filepath);%读取xlsx文件
% size(raw)
%如果每列存在合并单元格的情况,则对空值进行填充
for i = 1:max([featurecol,loccol,datacol])
temp=raw{2,i};
for j = 2:size(raw,1)
if isnan(raw{j,i})
raw{j,i}=temp;
else
temp=raw{j,i};
end
end
end
%统计每个特征列值可能出现的值(读取每列数据并去重) ->colall
for i = 1:length(featurecol)
ii=featurecol(i);
colall{i,1}=unique(raw(2:size(raw,1),ii));
end
%根据boundlimitcol提供的列标,将所有数据中boundlimitcol列值相同的行划分为一组,
%计算每组的最大值和最小值,在后期绘图时相同组的数据使用相同的上小限。
alldatanum=ones(length(colall{boundlimitcol,1})*length(datacol),1);
for k1 = 2:size(raw,1)
k1;
for k2 =1:length(colall{boundlimitcol,1})
k2;
if(strcmp(raw{k1,boundlimitcol}(1,:),colall{boundlimitcol,1}(k2,:)))
for ii =1:length(datacol)
alldata(alldatanum(k2)+ii-1,k2) = raw{k1,datacol(ii)}(1,1);
alldatanum(k2)=alldatanum(k2)+1;
end
end
end
end
boundlow=min(alldata);
boundup=max(alldata);
%计算每列每个特征重复的次数
for i =1:length(colall)
featurelen(i)=1;
if i<length(colall)
for ii =i+1:length(colall)
featurelen(i)=featurelen(i)*length(colall{ii,1});
end
end
end
%遍历整个数据矩阵,穷举所有特征列可能出现的组合 ->dicttemp
for i =1:length(colall)
if i==1
circulatecount=1;
else
circulatecount=1;
for t=1:i-1
circulatecount=circulatecount*length(colall{t,1});
end
end
for ii =1:length(colall{i,1})
for iii=1:circulatecount
startnum=1+(ii-1)*featurelen(i)+(iii-1)*length(colall{i,1})*featurelen(i);
endunm=ii*featurelen(i)+(iii-1)*length(colall{i,1})*featurelen(i);
dicttemp(startnum:endunm,i)=colall{i,1}(ii);
end
end
end
%生成每张图片保存所用的文件名,每张图片用到的数据,每张图片设定的上下线信息
loccolnum=length(unique(raw(2:size(raw,1),loccol))); %电极点数目
for i =1:length(dicttemp) % dicttemp 条目
i
name='';
for ii = 1:size(dicttemp,2)
ii;
name=[name,'-',dicttemp{i,ii}];
end
dict{i,1}=name;
datavaluenum=1;
datavalue=cell(loccolnum,1+length(datacol));
for k1 = 2:size(raw,1) % raw数据
ismatch=1;
for ii =1:length(featurecol) % 所选特征数
if ~(strcmp(raw{k1,featurecol(ii)}(1,:),dicttemp{i,ii}))
ismatch=0;
break;
end
end
if ismatch==1 %若raw的k1列特征和dicttemp当前列的特征相同,则将数据列的数据放入datavalue
datavalue{datavaluenum,1}=raw{k1,loccol}(1,:);
for iii =1:length(datacol)
datavalue{datavaluenum,1+iii}=raw{k1,datacol(iii)}(1,:);
end
datavaluenum = datavaluenum+1;
end
end
dict{i,2}=datavalue; %将所有符合dicttemp i列的数据返回给添加到dict矩阵中
boundlimitcolpro=find(featurecol==boundlimitcol);%边界限制列内部下标
boundindex=find(strcmp(colall{boundlimitcolpro,1},dicttemp(i,boundlimitcolpro)));%每条数据对应的上下限的索引
for ii =1:length(datacol)%针对不同的数据列设置不同的上下限
dict{i,3+(ii-1)*2}=boundlow(1,boundindex);
dict{i,4+(ii-1)*2}=boundup(1,boundindex);
end
end
filename=filepath(1:end-5);%删除文件名的后缀名
%创建一级目录
if exist(filename,'dir')==0
mkdir(filename);
end
%创建二级目录
for i =1:length(datacol)
if exist([filename,'/',raw{1,i}(1,:)],'dir')==0
mkdir([filename,'/',raw{1,i}(1,:)]);
end
end
%调用topoplot画图
structloc=chanlocsseek(dict{1,2}(:,1));%将电极点位置数组转换成topoplot要求的矩阵结构
for i=1:length(dicttemp)
for ii = 1:length(datacol)
h_fig=figure('Visible', 'off');%
%h_fig=figure('Visible', 'off');%显示每次绘制的图片
axes = subplot(1,1,1);
bound=[dict{i,3}(1,1),dict{i,4}(1,1)];
topoplot(cell2mat(dict{i,2}(:,1+ii)),structloc,'maplimits',bound,'plotrad',0.6,'headrad',0.6,'gridscale',300)
cbar(0,0,bound);%显示颜色bar
saveas(h_fig, [filename,'/',raw{1,ii}(1,:),'/',(dict{i,1}),'-',raw{1,ii}(1,:),'.png']);%保存绘制的图片
close(h_fig); %关闭图片资源
end
end