function handle = topoplot(data,varargin)
% topoplot() -  plot a topographic map of an EEG or MEG field as a 2-D
%               circular view (looking down at the top of the head)
%               using cointerpolation on a fine cartesian grid.
% Usage:
%         >>  topoplot(cfg, datavector);
%         >>  topoplot(datavector,'Key1','Value1','Key2','Value2'...)
%         >>  topoplot(cfg,X,Y,datavector,Labels) (OLDSTYLE, no further documentation)
% Inputs:
%     datavector  = vector of values at the corresponding locations.
%     cfg         = configuration structure containing the (optional) parameters
% OR
% The Key-Value pairs contain the (optional) parameters. Every cfg field can also
% be specified using the fieldname as a key in the key-value pairs.
%
% Compulsory fields/parameters:
% cfg.layout          = 'layoutfile.lay' (specify the layoutfile here).
%                         (if the OLDSTYLE syntax is used, cfg.layout is NOT used)
%
% Optional Parameters & Values
%
% cfg.colormap        = any sized colormap
% cfg.interplimits    = 'electrodes' to furthest electrode
%                       'head' (default) to edge of head
% cfg.gridscale       = 67 (default) scaling grid size
% cfg.maplimits       = 'absmax' (default) +/- the absolute-max
%                       'maxmin' scale to data range
%                       [clim1,clim2] user-defined lo/hi
% cfg.style           = 'straight' colormap only
%                       'contour' contour lines only
%                       'both' (default) both colormap and contour lines
%                       'fill' constant color between lines
%                       'blank' just head and electrodes
% cfg.numcontour      = 6 (default) number of contour lines
% cfg.shading         = 'flat' (default),'interp'
% cfg.interpolation   = 'linear','cubic','nearest','v4' (default) see griddata
% cfg.headcolor       = [0,0,0] (default) Color of head cartoon
% cfg.hlinewidth      = 2 (default) Linewidth of the drawn head, nose and ears			
% cfg.contcolor       = [0 0 0] (default)	Contourline color
%
% cfg.electrodes      = 'on'(default),'off','labels','numbers','highlights' or 'dotnum'
% cfg.emarker         = 'o' (default), Marker symbol			
% cfg.ecolor          = [0 0 0] (default), Marker color (black)		
% cfg.emarkersize     = 2 (default), Marker size		
% cfg.efontsize       = the DefaultAxesFontSize (default),
%                         Marker fontsize if cfg.electrodes='numbers' or 'labels'
%
% cfg.highlight       = 'off' (default) or the electrodenumbers you want to highlight
% cfg.hlmarker        = 'o' (default)  Highlight marker symbol
% cfg.hlcolor         = [0 0 0] (default) Highlight marker color (black)
% cfg.hlmarkersize    = 6 (default) Highlight marker size
% cfg.hllinewidth     = 3 (default) Highlight marker linewidth
%
% Note: topoplot() only works when map limits are >= the max and min
%                             interpolated data values.
%
% Note: topoplot() will ignore any electrode with a position outside
%                             the head (radius > 0.5)


% 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')

% Copyright (C) Andy Spydell, Colin Humphries & Arnaud Delorme
% CNL / Salk Institute, Aug, 1996
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

% New implementation by Geerten Kramer (2005), based on versions of
% Ole Jensen and JanMathijs Schoffelen

% $Log: topoplot.m,v $
% Revision 1.4  2005/11/09 16:25:49  geekra
% Cleaned up tab characters in documentation.
%
% Revision 1.3  2005/11/08 18:58:52  geekra
% Complete new implementation. But it is completely backwards compatible with
% the old version in /fieldtrip/private/.
% - Added new commandline key-value possibilities.
% - Added new highlighting options.
% - Updated the documentation.
%


Narg=nargin;
if(Narg<2)
	error('At least 2 input argument are allowed');
end;
N=length(varargin);
if(N==1)
	OldStyleSyntax=0;
	if(isstruct(data)&&isnumeric(varargin{1}))
		cfg=data;
		data=varargin{1};
	else
		errmsg=['\n'];
		errmsg=[errmsg,'When only two inputarguments are supplied, the following syntax\n'];
		errmsg=[errmsg,'should be used:\n'];
		errmsg=[errmsg,'[handle]=topoplot(cfg,datavector);\n'];
		errmsg=[errmsg,'Which is not the case.\n'];
		error(sprintf(errmsg));
	end;
elseif(N==3)
	OldStyleSyntax=1;
	if((isstruct(data)||isempty(data))...
			&&isnumeric(varargin{1})&&isnumeric(varargin{2})&&isnumeric(varargin{3}))
		cfg=data;	
		X=varargin{1};	
		Y=varargin{2};
		data=varargin{3};
	else
		errmsg=['\n'];
		errmsg=[errmsg,'When four inputarguments are supplied, the following syntax\n'];
		errmsg=[errmsg,'should be used:\n'];
		errmsg=[errmsg,'[handle]=topoplot(cfg,X,Y,datavector);\n'];
		errmsg=[errmsg,'Which is not the case.\n'];
		error(sprintf(errmsg));
	end;
elseif(N==4)
	if((isstruct(data)||isempty(data))&&isnumeric(varargin{1})&&isnumeric(varargin{2})...
					&&isnumeric(varargin{3})&&iscell(varargin{4}))
		OldStyleSyntax=1;
		cfg=data;
		X=varargin{1};	
		Y=varargin{2};
		data=varargin{3};
		labels=varargin{4};
	elseif(ischar(varargin{1})&&ischar(varargin{3})&&isnumeric(data))
		OldStyleSyntax=0;
		cfg=keyval2cfg(varargin);
	else
		errmsg=['\n'];
		errmsg=[errmsg,'When five inputarguments are supplied, one of the following syntaxes\n'];
		errmsg=[errmsg,'should be used:\n'];
		errmsg=[errmsg,'[handle]=topoplot(cfg,X,Y,datavector,Labels);\n'];
		errmsg=[errmsg,'or:\n'];
		errmsg=[errmsg,'[handle]=topoplot(datavector,Key1,Value1,Key2,Value2);\n'];
		errmsg=[errmsg,'Neither is the case.\n'];
		error(sprintf(errmsg));
	end;	

else
	OldStyleSyntax=0;
	if(rem(N,2))
		error('Varargin must be an even set of key-value pairs or one cfg structure');
	end;
	checkifstring=[];
	for(i=1:2:N)
		checkifstring=[checkifstring,ischar(varargin{i})];
	end;
	if(~all(checkifstring))
		error('All keys must be strings!');
	else
		cfg=keyval2cfg(varargin);
	end
end;

if(~isfield(cfg,'maxchans'))		cfg.maxchans = 256;			end;
if(~isfield(cfg,'maplimits'))		cfg.maplimits = 'absmax';	end; % absmax, maxmin, [values]
if(~isfield(cfg,'interplimits'))	cfg.interplimits ='head';	end; % head, electrodes
if(~isfield(cfg,'grid_scale'))		cfg.grid_scale = 67;		end; % 67 in original
if(~isfield(cfg,'contournum'))		cfg.contournum = 6;			end;
if(~isfield(cfg,'style'))			cfg.style = 'both';			end; % both,straight,fill,contour,blank
if(~isfield(cfg,'hcolor'))			cfg.hcolor = [0 0 0];		end;
if(~isfield(cfg,'contcolor'))		cfg.contcolor = [0 0 0];	end;
if(~isfield(cfg,'hlinewidth'))		cfg.hlinewidth = 2;			end;
if(~isfield(cfg,'shading'))			cfg.shading = 'flat';		end; % flat or interp
if(~isfield(cfg,'interpolation'))	cfg.interpolation = 'v4';	end;
if(~isfield(cfg,'layout'))
	if(~OldStyleSyntax)
		error('Specify at least the field or key "layout".');
	end;
end;

if(~isfield(cfg,'electrodes'))		cfg.electrodes = 'on';		end; % on,off,label,numbers or highlights
if(~isfield(cfg,'showlabels')) % for compatibility with OLDSTYLE
	cfg.showlabels = '';
else
	cfg.electrodes = '';
end;
if(~isfield(cfg,'emarker'))			cfg.emarker = 'o';			end;
if(~isfield(cfg,'ecolor'))			cfg.ecolor = [0 0 0];		end;
if(~isfield(cfg,'emarkersize'))		cfg.emarkersize = 2;		end;
if(~isfield(cfg,'efsize'))			cfg.efsize = get(0,'DefaultAxesFontSize');end;

if(~isfield(cfg,'highlight'))		cfg.highlight = 'off';		end; % 'off' or the electrodenumbers.
if(~isfield(cfg,'hlmarker'))		cfg.hlmarker = 'o';			end;
if(~isfield(cfg,'hlcolor'))			cfg.hlcolor = [0 0 0];		end;
if(~isfield(cfg,'hlmarkersize'))	cfg.hlmarkersize = 6;		end;
if(~isfield(cfg,'hllinewidth'))		cfg.hllinewidth = 3;		end;
% if(~isfield(cfg,'contournum'))		cfg.contournum = 6;			end;
% if(~isfield(cfg,'contournum'))		cfg.contournum = 6;			end;
% if(~isfield(cfg,'contournum'))		cfg.contournum = 6;			end;
% if(~isfield(cfg,'contournum'))		cfg.contournum = 6;			end;
% if(~isfield(cfg,'contournum'))		cfg.contournum = 6;			end;
% if(~isfield(cfg,'contournum'))		cfg.contournum = 6;			end;

if(isfield(cfg,'colormap'))
	if(size(cfg.colormap,2)~=3)
		error('topoplot(): Colormap must be a n x 3 matrix');
	end
	colormap(cfg.colormap);
end;
if(isfield(cfg,'headlimits'))
	cfg.interplimits=cfg.headlimits;
	cfg=rmfield(cfg,'headlimits');
	if(~isstr(cfg.interplimits))
		error('topoplot(): interplimits value must be a string')
	end
	cfg.interplimits = lower(cfg.interplimits);
	if(~strcmp(cfg.interplimits,'electrodes') & ~strcmp(cfg.interplimits,'head'))
		error('topoplot(): Incorrect value for interplimits')
	end
end;	
if(isfield(cfg,'gridscale'))
	cfg.grid_scale = cfg.gridscale;
	cfg=rmfield(cfg,'gridscale');
end;
if(isfield(cfg,'interpolate'))
	cfg.interpolation = lower(cfg.interpolate);
	cfg=rmfield(cfg,'interpolate');
end;
if(isfield(cfg,'numcontour'))
	cfg.contournum = cfg.numcontour;
	cfg=rmfield(cfg,'numcontour');
end;
if(isfield(cfg,'electrod'))
	cfg.electrodes = lower(cfg.electrod);
	cfg=rmfield(cfg,'electrod');
end;
if(isfield(cfg,'headcolor'))
	cfg.hcolor = cfg.headcolor;
	cfg=rmfield(cfg,'headcolor');
end;
if(isfield(cfg,'electcolor'))
	cfg.ecolor = cfg.electcolor;
	cfg=rmfield(cfg,'electcolor');
end;
if(isfield(cfg,'emsize'))
	cfg.emarkersize = cfg.emsize;
	cfg=rmfield(cfg,'emsize');
end;
if(isfield(cfg,'efontsize'))
	cfg.efsize = cfg.efontsize;
	cfg=rmfield(cfg,'efontsize');
end;
if(isfield(cfg,'shading'))
	cfg.shading = lower(cfg.shading);
	if(~any(strcmp(cfg.shading,{'flat','interp'})))
		error('Invalid Shading Parameter')
	end
end
if(isfield(cfg,'zlim'))
	cfg.maplimits = cfg.zlim;
	cfg=rmfield(cfg,'zlim');
end;

[r,c] = size(data);
if(r>1&&c>1),
  error('topoplot(): data should be a single vector\n');
end

if(~OldStyleSyntax)
	[chNum,X,Y,Width,Height,labels] = textread(cfg.layout,'%f %f %f %f %f %s');

	if(length(data)~=length(X))
		if(length(data)~=length(X)-2)
			error('topoplot(): data vector must be the same size as layout-file')
		else
			X=X(1:end-2);
			Y=Y(1:end-2);
			labels=labels(1:end-2);
		end;
	end
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*X;                               % convert degrees to rads
Rd = Y;
%ii = find(Rd <= 0.5); % interpolate on-head channels only
%Th = Th(ii);
%Rd = Rd(ii);
%data = data(ii);


[x,y] = pol2cart(Th,Rd);



%X = X - (-5.55);
X = X - (max(X)-min(X))/2;
Y = Y - (max(Y)-min(Y))/2;


y = 0.9*((X-min(X))/(max(X)-min(X))-0.5);
x = 0.9*((Y-min(Y))/(max(Y)-min(Y))-0.5);

rmax = .5;

ha = gca;
cla
hold on

if ~strcmp(cfg.style,'blank')
	% find limits for interpolation
	if strcmp(cfg.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,cfg.grid_scale);   % x-axis description (row vector)
	yi = linspace(ymin,ymax,cfg.grid_scale);   % y-axis description (row vector)

	[Xi,Yi,Zi] = griddata(y,x,data,yi',xi,cfg.interpolation); % Interpolate data
	% [Xi,Yi,Zi] = griddata(y,x,data,yi',xi,'invdist'); % Interpolate data

	% 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(cfg.maplimits)
		if strcmp(cfg.maplimits,'absmax')
			amin = -max(max(abs(Zi)));
			amax = max(max(abs(Zi)));
		elseif strcmp(cfg.maplimits,'maxmin')
			amin = min(min(Zi));
			amax = max(max(Zi));
		end
	else
		amin = cfg.maplimits(1);
		amax = cfg.maplimits(2);
	end
	delta = xi(2)-xi(1); % length of grid entry

	% Draw topoplot on head
	if strcmp(cfg.style,'contour')
		contour(Xi,Yi,Zi,cfg.contournum,'k');
	elseif strcmp(cfg.style,'both')
		surface(Xi-delta/2,Yi-delta/2,zeros(size(Zi)),Zi,'EdgeColor','none',...
		'FaceColor',cfg.shading);
		contour(Xi,Yi,Zi,cfg.contournum,'k');
	elseif strcmp(cfg.style,'straight')
		surface(Xi-delta/2,Yi-delta/2,zeros(size(Zi)),Zi,'EdgeColor','none',...
		'FaceColor',cfg.shading);
	elseif strcmp(cfg.style,'fill')
		contourf(Xi,Yi,Zi,cfg.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 Electrodes
if(strcmp(cfg.electrodes,'on')||strcmp(cfg.showlabels,'markers'))
	if(ischar(cfg.highlight))
		hp2 = plot(y,x,cfg.emarker,'Color',cfg.ecolor,'markersize',cfg.emarkersize);
	elseif(isnumeric(cfg.highlight))
		normal = setdiff(1:length(X),cfg.highlight);
		hp2 = plot(y(normal),x(normal),cfg.emarker,'Color',cfg.ecolor,'markersize',cfg.emarkersize);
		hp2 = plot(y(cfg.highlight),x(cfg.highlight),cfg.hlmarker,'Color',cfg.hlcolor...
								,'markersize',cfg.hlmarkersize,'linewidth',cfg.hllinewidth);
	else
		error('Unknown highlight type');
	end;
elseif(any(strcmp(cfg.electrodes,{'highlights','highlight'})))
	if(isnumeric(cfg.highlight))
		hp2 = plot(y(cfg.highlight),x(cfg.highlight),cfg.hlmarker,'Color',cfg.hlcolor...
								,'markersize',cfg.hlmarkersize,'linewidth',cfg.hllinewidth);
	else
		error('Unknown highlight type');
	end;
elseif(strcmp(cfg.electrodes,'labels')||strcmp(cfg.showlabels,'yes'))
	for(i=1:size(labels,1))
		text(y(i),x(i),labels(i,:),'HorizontalAlignment','center',...
		'VerticalAlignment','middle','Color',cfg.ecolor,...
		'FontSize',cfg.efsize)
	end
elseif(strcmp(cfg.electrodes,'numbers')||strcmp(cfg.showlabels,'numbers'))
	for i = 1:size(labels,1)
		text(y(i),x(i),int2str(i),'HorizontalAlignment','center',...
		'VerticalAlignment','middle','Color',cfg.ecolor,...
		'FontSize',cfg.efsize)
	end
elseif(strcmp(cfg.electrodes,'dotnum'))
	for i = 1:size(labels,1)
		text(y(i),x(i),int2str(i),'HorizontalAlignment','left',...
		'VerticalAlignment','bottom','Color',cfg.ecolor,...
		'FontSize',cfg.efsize)
	end
	if(ischar(cfg.highlight))
		hp2 = plot(y,x,cfg.emarker,'Color',cfg.ecolor,'markersize',cfg.emarkersize);
	elseif(isnumeric(cfg.highlight))
		normal = setdiff(1:length(X),cfg.highlight);
		hp2 = plot(y(normal),x(normal),cfg.emarker,'Color',cfg.ecolor,'markersize',cfg.emarkersize);
		hp2 = plot(y(cfg.highlight),x(cfg.highlight),cfg.hlmarker,'Color',cfg.hlcolor...
								,'markersize',cfg.hlmarkersize,'linewidth',cfg.hllinewidth);
	else
		error('Unknown highlight type');
	end;
end

% Plot Head, Ears, Nose
plot(cos(l).*rmax,sin(l).*rmax,...
    'color',cfg.hcolor,'Linestyle','-','LineWidth',cfg.hlinewidth);
plot([.18*rmax;0;-.18*rmax],[base;tip;base],...
    'Color',cfg.hcolor,'LineWidth',cfg.hlinewidth);

plot(EarX,EarY,'color',cfg.hcolor,'LineWidth',cfg.hlinewidth)
plot(-EarX,EarY,'color',cfg.hcolor,'LineWidth',cfg.hlinewidth)

hold off
axis off

