因论文需要,需要在脑电地形图上加入红点来标注电极,于是自己改进实现了一下新功能,加入新功能效果如下:
调用方式:
figure; plotData = rand(1,59); topoplotEEG(plotData,\'channel_locations_59ch.txt\',\'electrodes\',\'on\',\'onlymark\', [1 3 5 7 9]);
topoplotEEG代码:
% topoplot() - plot a topographic map of an EEG field as a 2-D
% circular view (looking down at the top of the head)
% using cointerpolation on a fine cartesian grid.
% Usage:
% >> topoplot(datavector,\'eloc_file\');
% >> topoplot(datavector,\'eloc_file\', \'Param1\',\'Value1\', ...)
% Inputs:
% datavector = vector of values at the corresponding locations.
% \'eloc_file\' = name of an EEG electrode position file {0 -> \'chan_file\'}
%
% Optional Parameters & Values (in any order):
% Param Value
% \'colormap\' - any sized colormap
% \'interplimits\' - \'electrodes\' to furthest electrode
% \'head\' to edge of head
% {default \'head\'}
% \'gridscale\' - scaling grid size {default 67}
% \'maplimits\' - \'absmax\' +/- the absolute-max
% \'maxmin\' scale to data range
% [clim1,clim2] user-definined lo/hi
% {default = \'absmax\'}
% \'style\' - \'straight\' colormap only
% \'contour\' contour lines only
% \'both\' both colormap and contour lines
% \'fill\' constant color between lines
% \'blank\' just head and electrodes
% {default = \'both\'}
% \'numcontour\' - number of contour lines
% {default = 6}
% \'shading\' - \'flat\',\'interp\' {default = \'flat\'}
% \'headcolor\' - Color of head cartoon {default black}
% \'electrodes\' - \'on\',\'off\',\'labels\',\'numbers\'
% \'efontsize\',\'electcolor\',\'emarker\',\'emarkersize\' - details
%
% Note: topoplot() only works when map limits are >= the max and min
% interpolated data values.
% Eloc_file format:
% chan_number degrees radius reject_level amp_gain channel_name
% (Angle-0 = Cz-to-Fz; C3-angle =-90; Radius at edge of image = 0.5)
%
% For a sample eloc file: >> topoplot(\'example\')
%
% Note: topoplot() will ignore any electrode with a position outside
% the head (radius > 0.5)
% Topoplot Version 2.1
% Begun by Andy Spydell, NHRC, 7-23-96
% 8-96 Revised by Colin Humphries, CNL / Salk Institute, La Jolla CA
% -changed surf command to imagesc (faster)
% -can now handle arbitrary scaling of electrode distances
% -can now handle non integer angles in eloc_file
% 4-4-97 Revised again by Colin Humphries, reformat by SM
% -added parameters
% -changed eloc_file format
% 2-26-98 Revised by Colin
% -changed image back to surface command
% -added fill and blank styles
% -removed extra background colormap entry (now use any colormap)
% -added parameters for electrode colors and labels
% -now each topoplot axes use the caxis command again.
% -removed OUTPUT parameter
% 3-11-98 changed default emarkersize, improve help msg -sm
function handle = topoplot(Vl,loc_file,p1,v1,p2,v2,p3,v3,p4,v4,p5,v5,p6,v6,p7,v7,p8,v8,p9,v9,p10,v10)
% User Defined Defaults:
MAXCHANS = 256;
DEFAULT_ELOC = \'eloc64.txt\';
INTERPLIMITS = \'head\'; % head, electrodes
MAPLIMITS = \'absmax\'; % absmax, maxmin, [values]
GRID_SCALE = 67;
CONTOURNUM = 6;
STYLE = \'both\'; % both,straight,fill,contour,blank
HCOLOR = [0 0 0];
ECOLOR = [0 0 0];
CONTCOLOR = [0 0 0];
ELECTROD = \'on\'; % ON OFF LABEL
EMARKERSIZE = 6;
EFSIZE = get(0,\'DefaultAxesFontSize\');
HLINEWIDTH = 2;
EMARKER = \'.\';
SHADING = \'flat\'; % flat or interp
MARKIDX = NaN;
%%%%%%%%%%%%%%%%%%%%%%%
nargs = nargin;
if nargs < 2
loc_file = DEFAULT_ELOC;
end
if nargs == 1
if isstr(Vl)
if any(strcmp(lower(Vl),{\'example\',\'demo\'}))
fprintf([\'This is an example of an electrode location file,\n\',...
\'an ascii file consisting of the following four columns:\n\',...
\' channel_number degrees arc_length channel_name\n\n\',...
\'Example:\n\',...
\' 1 -18 .352 Fp1.\n\',...
\' 2 18 .352 Fp2.\n\',...
\' 5 -90 .181 C3..\n\',...
\' 6 90 .181 C4..\n\',...
\' 7 -90 .500 A1..\n\',...
\' 8 90 .500 A2..\n\',...
\' 9 -142 .231 P3..\n\',...
\'10 142 .231 P4..\n\',...
\'11 0 .181 Fz..\n\',...
\'12 0 0 Cz..\n\',...
\'13 180 .181 Pz..\n\n\',...
\'The model head sphere has a diameter of 1.\n\',...
\'The vertex (Cz) has arc length 0. Channels with arc \n\',...
\'lengths > 0.5 are not plotted nor used for interpolation.\n\'...
\'Zero degrees is towards the nasion. Positive angles\n\',...
\'point to the right hemisphere; negative to the left.\n\',...
\'Channel names should each be four chars, padded with\n\',...
\'periods (in place of spaces).\n\'])
return
end
end
end
if isempty(loc_file)
loc_file = 0;
end
if loc_file == 0
loc_file = DEFAULT_ELOC;
end
if nargs > 2
if ~(round(nargs/2) == nargs/2)
error(\'topoplot(): Odd number of inputs?\')
end
for i = 3:2:nargs
Param = eval([\'p\',int2str((i-3)/2 +1)]);
Value = eval([\'v\',int2str((i-3)/2 +1)]);
if ~isstr(Param)
error(\'topoplot(): Parameter must be a string\')
end
Param = lower(Param);
switch lower(Param)
case \'colormap\'
if size(Value,2)~=3
error(\'topoplot(): Colormap must be a n x 3 matrix\')
end
colormap(Value)
case {\'interplimits\',\'headlimits\'}
if ~isstr(Value)
error(\'topoplot(): interplimits value must be a string\')
end
Value = lower(Value);
if ~strcmp(Value,\'electrodes\') & ~strcmp(Value,\'head\')
error(\'topoplot(): Incorrect value for interplimits\')
end
INTERPLIMITS = Value;
case \'maplimits\'
MAPLIMITS = Value;
case \'gridscale\'
GRID_SCALE = Value;
case \'style\'
STYLE = lower(Value);
case \'numcontour\'
CONTOURNUM = Value;
case \'electrodes\'
ELECTROD = lower(Value);
case \'emarker\'
EMARKER = Value;
case {\'headcolor\',\'hcolor\'}
HCOLOR = Value;
case {\'electcolor\',\'ecolor\'}
ECOLOR = Value;
case {\'emarkersize\',\'emsize\'}
EMARKERSIZE = Value;
case {\'efontsize\',\'efsize\'}
EFSIZE = Value;
case \'shading\'
SHADING = lower(Value);
if ~any(strcmp(SHADING,{\'flat\',\'interp\'}))
error(\'Invalid Shading Parameter\')
end
case \'onlymark\'
MARKIDX = Value;
otherwise
error(\'Unknown parameter.\')
end
end
end
[r,c] = size(Vl);
if r>1 & c>1,
error(\'topoplot(): data should be a single vector\n\');
end
fid = fopen(loc_file);
if fid<1,
fprintf(\'topoplot(): cannot open eloc_file (%s).\n\',loc_file);
return
end
A = fscanf(fid,\'%d %f %f %s\',[7 MAXCHANS]);
fclose(fid);
A = A\';
if length(Vl) ~= size(A,1),
fprintf(...
\'topoplot(): data vector must have the same rows (%d) as eloc_file (%d)\n\',...
length(Vl),size(A,1));
A
error(\'\');
end
labels = setstr(A(:,4:7));
idx = find(labels == \'.\'); % some labels have dots
labels(idx) = setstr(abs(\' \')*ones(size(idx))); % replace them with spaces
Th = pi/180*A(:,2); % convert degrees to radians
Rd = A(:,3);
ii = find(Rd <= 0.5); % interpolate on-head channels only
Th = Th(ii);
Rd = Rd(ii);
Vl = Vl(ii);
labels = labels(ii,:);
[x,y] = pol2cart(Th,Rd); % transform from polar to cartesian coordinates
rmax = 0.5;
ha = gca;
cla
hold on
if ~strcmp(STYLE,\'blank\')
% find limits for interpolation
if strcmp(INTERPLIMITS,\'head\')
xmin = min(-.5,min(x)); xmax = max(0.5,max(x));
ymin = min(-.5,min(y)); ymax = max(0.5,max(y));
else
xmin = max(-.5,min(x)); xmax = min(0.5,max(x));
ymin = max(-.5,min(y)); ymax = min(0.5,max(y));
end
xi = linspace(xmin,xmax,GRID_SCALE); % x-axis description (row vector)
yi = linspace(ymin,ymax,GRID_SCALE); % y-axis description (row vector)
% [Xi,Yi,Zi] = griddata(y,x,Vl,yi\',xi,\'invdist\'); % Interpolate data
[Xi,Yi,Zi] = griddata(y,x,Vl,yi\',xi,\'v4\');
% Take data within head
mask = (sqrt(Xi.^2+Yi.^2) <= rmax);
ii = find(mask == 0);
Zi(ii) = NaN;
% calculate colormap limits
m = size(colormap,1);
if isstr(MAPLIMITS)
if strcmp(MAPLIMITS,\'absmax\')
amin = -max(max(abs(Zi)));
amax = max(max(abs(Zi)));
elseif strcmp(MAPLIMITS,\'maxmin\')
amin = min(min(Zi));
amax = max(max(Zi));
end
else
amin = MAPLIMITS(1);
amax = MAPLIMITS(2);
end
delta = xi(2)-xi(1); % length of grid entry
% Draw topoplot on head
if strcmp(STYLE,\'contour\')
contour(Xi,Yi,Zi,CONTOURNUM,\'k\');
elseif strcmp(STYLE,\'both\')
if sum(isnan(MARKIDX))
surface(Xi-delta/2,Yi-delta/2,zeros(size(Zi)),Zi,\'EdgeColor\',\'none\',...
\'FaceColor\',SHADING);
% colorbar;
contour(Xi,Yi,Zi,CONTOURNUM,\'k\');
end
elseif strcmp(STYLE,\'straight\')
surface(Xi-delta/2,Yi-delta/2,zeros(size(Zi)),Zi,\'EdgeColor\',\'none\',...
\'FaceColor\',SHADING);
% colorbar
elseif strcmp(STYLE,\'fill\')
contourf(Xi,Yi,Zi,CONTOURNUM,\'k\');
else
error(\'Invalid style\')
end
caxis([amin amax]) % set coloraxis
end
set(ha,\'Xlim\',[-rmax*1.3 rmax*1.3],\'Ylim\',[-rmax*1.3 rmax*1.3])
% %%% Draw Head %%%%
l = 0:2*pi/100:2*pi;
basex = .18*rmax;
tip = rmax*1.15; base = rmax-.004;
EarX = [.497 .510 .518 .5299 .5419 .54 .547 .532 .510 .489];
EarY = [.0555 .0775 .0783 .0746 .0555 -.0055 -.0932 -.1313 -.1384 -.1199];
% Plot Head, Ears, Nose
plot(cos(l).*rmax,sin(l).*rmax,...
\'color\',HCOLOR,\'Linestyle\',\'-\',\'LineWidth\',HLINEWIDTH);
plot([.18*rmax;0;-.18*rmax],[base;tip;base],...
\'Color\',HCOLOR,\'LineWidth\',HLINEWIDTH);
plot(EarX,EarY,\'color\',HCOLOR,\'LineWidth\',HLINEWIDTH)
plot(-EarX,EarY,\'color\',HCOLOR,\'LineWidth\',HLINEWIDTH)
% Plot Electrodes
if strcmp(ELECTROD,\'on\')
if sum(isnan(MARKIDX))
hp2 = plot(y,x,EMARKER,\'Color\',ECOLOR,\'markersize\',EMARKERSIZE);
else
markedIdx = false(numel(y),1);
markedIdx(MARKIDX) = true;
hp2 = plot(y(~markedIdx),x(~markedIdx),EMARKER,\'Color\',ECOLOR,\'markersize\',EMARKERSIZE);
hp2 = plot(y(markedIdx),x(markedIdx),EMARKER,\'Color\',\'r\',\'markersize\',3*EMARKERSIZE);
end
elseif strcmp(ELECTROD,\'labels\')
for i = 1:size(labels,1)
text(y(i),x(i),labels(i,:),\'HorizontalAlignment\',\'center\',...
\'VerticalAlignment\',\'middle\',\'Color\',ECOLOR,...
\'FontSize\',EFSIZE)
end
elseif strcmp(ELECTROD,\'numbers\')
whos y x
for i = 1:size(labels,1)
text(y(i),x(i),int2str(i),\'HorizontalAlignment\',\'center\',...
\'VerticalAlignment\',\'middle\',\'Color\',ECOLOR,...
\'FontSize\',EFSIZE)
end
end
hold off
axis off