topoplotFast.m 66 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610
  1. % topoplot() - plot a topographic map of a scalp data field in a 2-D circular view
  2. % (looking down at the top of the head) using interpolation on a fine
  3. % cartesian grid. Can also show specified channnel location(s), or return
  4. % an interpolated value at an arbitrary scalp location (see 'noplot').
  5. % By default, channel locations below head center (arc_length 0.5) are
  6. % shown in a 'skirt' outside the cartoon head (see 'plotrad' and 'headrad'
  7. % options below). Nose is at top of plot; left is left; right is right.
  8. % Using option 'plotgrid', the plot may be one or more rectangular grids.
  9. % Usage:
  10. % >> topoplot(datavector, EEG.chanlocs); % plot a map using an EEG chanlocs structure
  11. % >> topoplot(datavector, 'my_chan.locs'); % read a channel locations file and plot a map
  12. % >> topoplot('example'); % give an example of an electrode location file
  13. % >> [h grid_or_val plotrad_or_grid, xmesh, ymesh]= ...
  14. % topoplot(datavector, chan_locs, 'Input1','Value1', ...);
  15. % Required Inputs:
  16. % datavector - single vector of channel values. Else, if a vector of selected subset
  17. % (int) channel numbers -> mark their location(s) using 'style' 'blank'.
  18. % chan_locs - name of an EEG electrode position file (>> topoplot example).
  19. % Else, an EEG.chanlocs structure (>> help readlocs or >> topoplot example)
  20. % Optional inputs:
  21. % 'maplimits' - 'absmax' -> scale map colors to +/- the absolute-max (makes green 0);
  22. % 'maxmin' -> scale colors to the data range (makes green mid-range);
  23. % [lo.hi] -> use user-definined lo/hi limits
  24. % {default: 'absmax'}
  25. % 'style' - 'map' -> plot colored map only
  26. % 'contour' -> plot contour lines only
  27. % 'both' -> plot both colored map and contour lines
  28. % 'fill' -> plot constant color between contour lines
  29. % 'blank' -> plot electrode locations only {default: 'both'}
  30. % 'electrodes' - 'on','off','labels','numbers','ptslabels','ptsnumbers'. To set the 'pts'
  31. % marker,,see 'Plot detail options' below. {default: 'on' -> mark electrode
  32. % locations with points ('.') unless more than 64 channels, then 'off'}.
  33. % 'plotchans' - [vector] channel numbers (indices) to use in making the head plot.
  34. % {default: [] -> plot all chans}
  35. % 'chantype' - cell array of channel type(s) to plot. Will also accept a single quoted
  36. % string type. Channel type for channel k is field EEG.chanlocs(k).type.
  37. % If present, overrides 'plotchans' and also 'chaninfo' with field
  38. % 'chantype'. Ex. 'EEG' or {'EEG','EOG'} {default: all, or 'plotchans' arg}
  39. % 'plotgrid' - [channels] Plot channel data in one or more rectangular grids, as
  40. % specified by [channels], a position matrix of channel numbers defining
  41. % the topographic locations of the channels in the grid. Zero values are
  42. % given the figure background color; negative integers, the color of the
  43. % polarity-reversed channel values. Ex: >> figure; ...
  44. % >> topoplot(values,'chanlocs','plotgrid',[11 12 0; 13 14 15]);
  45. % % Plot a (2,3) grid of data values from channels 11-15 with one empty
  46. % grid cell (top right) {default: no grid plot}
  47. % 'nosedir' - ['+X'|'-X'|'+Y'|'-Y'] direction of nose {default: '+X'}
  48. % 'chaninfo' - [struct] optional structure containing fields 'nosedir', 'plotrad'
  49. % and/or 'chantype'. See these (separate) field definitions above, below.
  50. % {default: nosedir +X, plotrad 0.5, all channels}
  51. % 'plotrad' - [0.15<=float<=1.0] plotting radius = max channel arc_length to plot.
  52. % See >> topoplot example. If plotrad > 0.5, chans with arc_length > 0.5
  53. % (i.e. below ears-eyes) are plotted in a circular 'skirt' outside the
  54. % cartoon head. See 'intrad' below. {default: max(max(chanlocs.radius),0.5);
  55. % If the chanlocs structure includes a field chanlocs.plotrad, its value
  56. % is used by default}.
  57. % 'headrad' - [0.15<=float<=1.0] drawing radius (arc_length) for the cartoon head.
  58. % NOTE: Only headrad = 0.5 is anatomically correct! 0 -> don't draw head;
  59. % 'rim' -> show cartoon head at outer edge of the plot {default: 0.5}
  60. % 'intrad' - [0.15<=float<=1.0] radius of the scalp map interpolation area (square or
  61. % disk, see 'intsquare' below). Interpolate electrodes in this area and use
  62. % this limit to define boundaries of the scalp map interpolated data matrix
  63. % {default: max channel location radius}
  64. % 'intsquare' - ['on'|'off'] 'on' -> Interpolate values at electrodes located in the whole
  65. % square containing the (radius intrad) interpolation disk; 'off' -> Interpolate
  66. % values from electrodes shown in the interpolation disk only {default: 'on'}.
  67. % 'conv' - ['on'|'off'] Show map interpolation only out to the convext hull of
  68. % the electrode locations to minimize extrapolation. {default: 'off'}
  69. % 'noplot' - ['on'|'off'|[rad theta]] do not plot (but return interpolated data).
  70. % Else, if [rad theta] are coordinates of a (possibly missing) channel,
  71. % returns interpolated value for channel location. For more info,
  72. % see >> topoplot 'example' {default: 'off'}
  73. % 'verbose' - ['on'|'off'] comment on operations on command line {default: 'on'}.
  74. %
  75. % Plot detail options:
  76. % 'drawaxis' - ['on'|'off'] draw axis on the top left corner.
  77. % 'emarker' - Matlab marker char | {markerchar color size linewidth} char, else cell array
  78. % specifying the electrode 'pts' marker. Ex: {'s','r',32,1} -> 32-point solid
  79. % red square. {default: {'.','k',[],1} where marker size ([]) depends on the number
  80. % of channels plotted}.
  81. % 'emarker2' - {markchans}|{markchans marker color size linewidth} cell array specifying
  82. % an alternate marker for specified 'plotchans'. Ex: {[3 17],'s','g'}
  83. % {default: none, or if {markchans} only are specified, then {markchans,'o','r',10,1}}
  84. % 'hcolor' - color of the cartoon head. Use 'hcolor','none' to plot no head. {default: 'k' = black}
  85. % 'shading' - 'flat','interp' {default: 'flat'}
  86. % 'numcontour' - number of contour lines {default: 6}
  87. % 'contourvals' - values for contour {default: same as input values}
  88. % 'pmask' - values for masking topoplot. Array of zeros and 1 of the same size as the input
  89. % value array {default: []}
  90. % 'color' - color of the contours {default: dark grey}
  91. % 'whitebk ' - ('on'|'off') make the background color white (e.g., to print empty plotgrid channels)
  92. % {default: 'off'}
  93. % 'gridscale' - [int > 32] size (nrows) of interpolated scalp map data matrix {default: 67}
  94. % 'colormap' - (n,3) any size colormap {default: existing colormap}
  95. % 'circgrid' - [int > 100] number of elements (angles) in head and border circles {201}
  96. %
  97. % Dipole plotting options:
  98. % 'dipole' - [xi yi xe ye ze] plot dipole on the top of the scalp map
  99. % from coordinate (xi,yi) to coordinates (xe,ye,ze) (dipole head
  100. % model has radius 1). If several rows, plot one dipole per row.
  101. % Coordinates returned by dipplot() may be used. Can accept
  102. % an EEG.dipfit.model structure (See >> help dipplot).
  103. % Ex: ,'dipole',EEG.dipfit.model(17) % Plot dipole(s) for comp. 17.
  104. % 'dipnorm' - ['on'|'off'] normalize dipole length {default: 'on'}.
  105. % 'diporient' - [-1|1] invert dipole orientation {default: 1}.
  106. % 'diplen' - [real] scale dipole length {default: 1}.
  107. % 'dipscale' - [real] scale dipole size {default: 1}.
  108. % 'dipsphere' - [real] size of the dipole sphere. {default: 85 mm}.
  109. % 'dipcolor' - [color] dipole color as Matlab code code or [r g b] vector
  110. % {default: 'k' = black}.
  111. % Outputs:
  112. % h - handle of the colored surface. If no surface is plotted,
  113. % return "gca", the handle of the current plot.
  114. % grid_or_val - [matrix] the interpolated data image (with off-head points = NaN).
  115. % Else, single interpolated value at the specified 'noplot' arg channel
  116. % location ([rad theta]), if any.
  117. % plotrad_or_grid - IF grid image returned above, then the 'plotrad' radius of the grid.
  118. % Else, the grid image
  119. % xmesh, ymesh - x and y values of the returned grid (above)
  120. %
  121. % Chan_locs format:
  122. % See >> topoplot 'example'
  123. %
  124. % Examples:
  125. %
  126. % To plot channel locations only:
  127. % >> figure; topoplot([],EEG.chanlocs,'style','blank','electrodes','labelpoint','chaninfo',EEG.chaninfo);
  128. %
  129. % Notes: - To change the plot map masking ring to a new figure background color,
  130. % >> set(findobj(gca,'type','patch'),'facecolor',get(gcf,'color'))
  131. % - Topoplots may be rotated. From the commandline >> view([deg 90]) {default: [0 90])
  132. %
  133. % Authors: Andy Spydell, Colin Humphries, Arnaud Delorme & Scott Makeig
  134. % CNL / Salk Institute, 8/1996-/10/2001; SCCN/INC/UCSD, Nov. 2001 -
  135. %
  136. % See also: timtopo(), envtopo()
  137. % Deprecated options:
  138. % 'shrink' - ['on'|'off'|'force'|factor] Deprecated. 'on' -> If max channel arc_length
  139. % > 0.5, shrink electrode coordinates towards vertex to plot all channels
  140. % by making max arc_length 0.5. 'force' -> Normalize arc_length
  141. % so the channel max is 0.5. factor -> Apply a specified shrink
  142. % factor (range (0,1) = shrink fraction). {default: 'off'}
  143. % 'electcolor' {'k'} ... electrode marking details and their {defaults}.
  144. % 'emarker' {'.'}|'emarkersize' {14}|'emarkersizemark' {40}|'efontsize' {var} -
  145. % electrode marking details and their {defaults}.
  146. % 'ecolor' - color of the electrode markers {default: 'k' = black}
  147. % 'interplimits' - ['electrodes'|'head'] 'electrodes'-> interpolate the electrode grid;
  148. % 'head'-> interpolate the whole disk {default: 'head'}.
  149. % Unimplemented future options:
  150. % Copyright (C) Colin Humphries & Scott Makeig, CNL / Salk Institute, Aug, 1996
  151. %
  152. % This program is free software; you can redistribute it and/or modify
  153. % it under the terms of the GNU General Public License as published by
  154. % the Free Software Foundation; either version 2 of the License, or
  155. % (at your option) any later version.
  156. %
  157. % This program is distributed in the hope that it will be useful,
  158. % but WITHOUT ANY WARRANTY; without even the implied warranty of
  159. % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  160. % GNU General Public License for more details.
  161. %
  162. % You should have received a copy of the GNU General Public License
  163. % along with this program; if not, write to the Free Software
  164. % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  165. % Topoplot Version 2.1
  166. % Early development history:
  167. % Begun by Andy Spydell and Scott Makeig, NHRC, 7-23-96
  168. % 8-96 Revised by Colin Humphries, CNL / Salk Institute, La Jolla CA
  169. % -changed surf command to imagesc (faster)
  170. % -can now handle arbitrary scaling of electrode distances
  171. % -can now handle non integer angles in chan_locs
  172. % 4-4-97 Revised again by Colin Humphries, reformatted by SM
  173. % -added parameters
  174. % -changed chan_locs format
  175. % 2-26-98 Revised by Colin
  176. % -changed image back to surface command
  177. % -added fill and blank styles
  178. % -removed extra background colormap entry (now use any colormap)
  179. % -added parameters for electrode colors and labels
  180. % -now each topoplot axes use the caxis command again.
  181. % -removed OUTPUT parameter
  182. % 3-11-98 changed default emarkersize, improve help msg -sm
  183. % 5-24-01 made default emarkersize vary with number of channels -sm
  184. % 01-25-02 reformated help & license, added link -ad
  185. % 03-15-02 added readlocs and the use of eloc input structure -ad
  186. % 03-25-02 added 'labelpoint' options and allow Values=[] -ad &sm
  187. % 03-25-02 added details to "Unknown parameter" warning -sm & ad
  188. function [handle,Zi,grid,Xi,Yi] = topoplotFast(Values,loc_file,varargin)
  189. %
  190. %%%%%%%%%%%%%%%%%%%%%%%% Set defaults %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  191. %
  192. icadefs % read defaults MAXTOPOPLOTCHANS and DEFAULT_ELOC and BACKCOLOR
  193. if ~exist('BACKCOLOR') % if icadefs.m does not define BACKCOLOR
  194. BACKCOLOR = [.93 .96 1]; % EEGLAB standard
  195. end
  196. whitebk = 'off'; % by default, make gridplot background color = EEGLAB screen background color
  197. plotgrid = 'off';
  198. plotchans = [];
  199. noplot = 'off';
  200. handle = [];
  201. Zi = [];
  202. chanval = NaN;
  203. rmax = 0.5; % actual head radius - Don't change this!
  204. INTERPLIMITS = 'head'; % head, electrodes
  205. INTSQUARE = 'on'; % default, interpolate electrodes located though the whole square containing
  206. % the plotting disk
  207. default_intrad = 1; % indicator for (no) specified intrad
  208. MAPLIMITS = 'absmax'; % absmax, maxmin, [values]
  209. GRID_SCALE = 67; % plot map on a 67X67 grid
  210. CIRCGRID = 201; % number of angles to use in drawing circles
  211. AXHEADFAC = 1.3; % head to axes scaling factor
  212. CONTOURNUM = 6; % number of contour levels to plot
  213. STYLE = 'both'; % default 'style': both,straight,fill,contour,blank
  214. HEADCOLOR = [0 0 0]; % default head color (black)
  215. CCOLOR = [0.2 0.2 0.2]; % default contour color
  216. ELECTRODES = []; % default 'electrodes': on|off|label - set below
  217. MAXDEFAULTSHOWLOCS = 64;% if more channels than this, don't show electrode locations by default
  218. EMARKER = '.'; % mark electrode locations with small disks
  219. ECOLOR = [0 0 0]; % default electrode color = black
  220. EMARKERSIZE = []; % default depends on number of electrodes, set in code
  221. EMARKERLINEWIDTH = 1; % default edge linewidth for emarkers
  222. EMARKERSIZE1CHAN = 20; % default selected channel location marker size
  223. EMARKERCOLOR1CHAN = 'red'; % selected channel location marker color
  224. EMARKER2CHANS = []; % mark subset of electrode locations with small disks
  225. EMARKER2 = 'o'; % mark subset of electrode locations with small disks
  226. EMARKER2COLOR = 'r'; % mark subset of electrode locations with small disks
  227. EMARKERSIZE2 = 10; % default selected channel location marker size
  228. EMARKER2LINEWIDTH = 1;
  229. EFSIZE = get(0,'DefaultAxesFontSize'); % use current default fontsize for electrode labels
  230. HLINEWIDTH = 1.7; % default linewidth for head, nose, ears
  231. BLANKINGRINGWIDTH = .035;% width of the blanking ring
  232. HEADRINGWIDTH = .007;% width of the cartoon head ring
  233. SHADING = 'flat'; % default 'shading': flat|interp
  234. shrinkfactor = []; % shrink mode (dprecated)
  235. intrad = []; % default interpolation square is to outermost electrode (<=1.0)
  236. plotrad = []; % plotting radius ([] = auto, based on outermost channel location)
  237. headrad = []; % default plotting radius for cartoon head is 0.5
  238. squeezefac = 1.0;
  239. MINPLOTRAD = 0.15; % can't make a topoplot with smaller plotrad (contours fail)
  240. VERBOSE = 'off';
  241. MASKSURF = 'off';
  242. CONVHULL = 'off'; % dont mask outside the electrodes convex hull
  243. DRAWAXIS = 'off';
  244. CHOOSECHANTYPE = 0;
  245. ContourVals = Values;
  246. PMASKFLAG = 0;
  247. %%%%%% Dipole defaults %%%%%%%%%%%%
  248. DIPOLE = [];
  249. DIPNORM = 'on';
  250. DIPSPHERE = 85;
  251. DIPLEN = 1;
  252. DIPSCALE = 1;
  253. DIPORIENT = 1;
  254. DIPCOLOR = [0 0 0];
  255. NOSEDIR = '+X';
  256. CHANINFO = [];
  257. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  258. %
  259. %%%%%%%%%%%%%%%%%%%%%%% Handle arguments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  260. %
  261. if nargin< 1
  262. help topoplot;
  263. return
  264. end
  265. % calling topoplot from Fieldtrip
  266. % -------------------------------
  267. fieldtrip = 0;
  268. if nargin < 2, loc_file = []; end;
  269. if isstruct(Values) | ~isstruct(loc_file), fieldtrip == 1; end;
  270. if isstr(loc_file), if exist(loc_file) ~= 2, fieldtrip == 1; end; end;
  271. if fieldtrip
  272. disp('Calling topoplot from Fieldtrip');
  273. dir1 = which('topoplot'); dir1 = fileparts(dir1);
  274. dir2 = which('electrodenormalize'); dir2 = fileparts(dir2);
  275. addpath(dir2);
  276. try,
  277. topoplot(Values, loc_file, varargin{:});
  278. catch,
  279. end;
  280. addpath(dir1);
  281. return;
  282. end;
  283. nargs = nargin;
  284. if nargs == 1
  285. if isstr(Values)
  286. if any(strcmp(lower(Values),{'example','demo'}))
  287. fprintf(['This is an example of an electrode location file,\n',...
  288. 'an ascii file consisting of the following four columns:\n',...
  289. ' channel_number degrees arc_length channel_name\n\n',...
  290. 'Example:\n',...
  291. ' 1 -18 .352 Fp1 \n',...
  292. ' 2 18 .352 Fp2 \n',...
  293. ' 5 -90 .181 C3 \n',...
  294. ' 6 90 .181 C4 \n',...
  295. ' 7 -90 .500 A1 \n',...
  296. ' 8 90 .500 A2 \n',...
  297. ' 9 -142 .231 P3 \n',...
  298. '10 142 .231 P4 \n',...
  299. '11 0 .181 Fz \n',...
  300. '12 0 0 Cz \n',...
  301. '13 180 .181 Pz \n\n',...
  302. ...
  303. 'In topoplot() coordinates, 0 deg. points to the nose, positive\n',...
  304. 'angles point to the right hemisphere, and negative to the left.\n',...
  305. 'The model head sphere has a circumference of 2; the vertex\n',...
  306. '(Cz) has arc_length 0. Locations with arc_length > 0.5 are below\n',...
  307. 'head center and are plotted outside the head cartoon.\n'....
  308. 'Option plotrad controls how much of this lower-head "skirt" is shown.\n',...
  309. 'Option headrad controls if and where the cartoon head will be drawn.\n',...
  310. 'Option intrad controls how many channels will be included in the interpolation.\n',...
  311. ])
  312. return
  313. end
  314. end
  315. end
  316. if nargs < 2
  317. loc_file = DEFAULT_ELOC;
  318. if ~exist(loc_file)
  319. fprintf('default locations file "%s" not found - specify chan_locs in topoplot() call.\n',loc_file)
  320. error(' ')
  321. end
  322. end
  323. if isempty(loc_file)
  324. loc_file = 0;
  325. end
  326. if isnumeric(loc_file) & loc_file == 0
  327. loc_file = DEFAULT_ELOC;
  328. end
  329. if nargs > 2
  330. if ~(round(nargs/2) == nargs/2)
  331. error('Odd number of input arguments??')
  332. end
  333. for i = 1:2:length(varargin)
  334. Param = varargin{i};
  335. Value = varargin{i+1};
  336. if ~isstr(Param)
  337. error('Flag arguments must be strings')
  338. end
  339. Param = lower(Param);
  340. switch Param
  341. case 'conv'
  342. CONVHULL = lower(Value);
  343. if ~strcmp(CONVHULL,'on') & ~strcmp(CONVHULL,'off')
  344. error('Value of ''conv'' must be ''on'' or ''off''.');
  345. end
  346. case 'colormap'
  347. if size(Value,2)~=3
  348. error('Colormap must be a n x 3 matrix')
  349. end
  350. colormap(Value)
  351. case 'intsquare'
  352. INTSQUARE = lower(Value);
  353. if ~strcmp(INTSQUARE,'on') & ~strcmp(INTSQUARE,'off')
  354. error('Value of ''intsquare'' must be ''on'' or ''off''.');
  355. end
  356. case {'interplimits','headlimits'}
  357. if ~isstr(Value)
  358. error('''interplimits'' value must be a string')
  359. end
  360. Value = lower(Value);
  361. if ~strcmp(Value,'electrodes') & ~strcmp(Value,'head')
  362. error('Incorrect value for interplimits')
  363. end
  364. INTERPLIMITS = Value;
  365. case 'verbose'
  366. VERBOSE = Value;
  367. case 'nosedir'
  368. NOSEDIR = Value;
  369. if isempty(strmatch(lower(NOSEDIR), { '+x', '-x', '+y', '-y' }))
  370. error('Invalid nose direction');
  371. end;
  372. case 'chaninfo'
  373. CHANINFO = Value;
  374. if isfield(CHANINFO, 'nosedir'), NOSEDIR = CHANINFO.nosedir; end;
  375. if isfield(CHANINFO, 'shrink' ), shrinkfactor = CHANINFO.shrink; end;
  376. if isfield(CHANINFO, 'plotrad') & isempty(plotrad), plotrad = CHANINFO.plotrad; end;
  377. if isfield(CHANINFO, 'chantype')
  378. chantype = CHANINFO.chantype;
  379. if ischar(chantype), chantype = cellstr(chantype); end
  380. CHOOSECHANTYPE = 1;
  381. end
  382. case 'chantype'
  383. chantype = Value;
  384. CHOOSECHANTYPE = 1;
  385. if ischar(chantype), chantype = cellstr(chantype); end
  386. if ~iscell(chantype), error('chantype must be cell array. e.g. {''EEG'', ''EOG''}'); end
  387. case 'drawaxis'
  388. DRAWAXIS = Value;
  389. case 'maplimits'
  390. MAPLIMITS = Value;
  391. case 'masksurf'
  392. MASKSURF = Value;
  393. case 'circgrid'
  394. CIRCGRID = Value;
  395. if isstr(CIRCGRID) | CIRCGRID<100
  396. error('''circgrid'' value must be an int > 100');
  397. end
  398. case 'style'
  399. STYLE = lower(Value);
  400. case 'numcontour'
  401. CONTOURNUM = Value;
  402. case 'electrodes'
  403. ELECTRODES = lower(Value);
  404. if strcmpi(ELECTRODES,'pointlabels') | strcmpi(ELECTRODES,'ptslabels') ...
  405. | strcmpi(ELECTRODES,'labelspts') | strcmpi(ELECTRODES,'ptlabels') ...
  406. | strcmpi(ELECTRODES,'labelpts')
  407. ELECTRODES = 'labelpoint'; % backwards compatability
  408. elseif strcmpi(ELECTRODES,'pointnumbers') | strcmpi(ELECTRODES,'ptsnumbers') ...
  409. | strcmpi(ELECTRODES,'numberspts') | strcmpi(ELECTRODES,'ptnumbers') ...
  410. | strcmpi(ELECTRODES,'numberpts') | strcmpi(ELECTRODES,'ptsnums') ...
  411. | strcmpi(ELECTRODES,'numspts')
  412. ELECTRODES = 'numpoint'; % backwards compatability
  413. elseif strcmpi(ELECTRODES,'nums')
  414. ELECTRODES = 'numbers'; % backwards compatability
  415. elseif strcmpi(ELECTRODES,'pts')
  416. ELECTRODES = 'on'; % backwards compatability
  417. elseif ~strcmp(ELECTRODES,'off') ...
  418. & ~strcmpi(ELECTRODES,'on') ...
  419. & ~strcmp(ELECTRODES,'labels') ...
  420. & ~strcmpi(ELECTRODES,'numbers') ...
  421. & ~strcmpi(ELECTRODES,'labelpoint') ...
  422. & ~strcmpi(ELECTRODES,'numpoint')
  423. error('Unknown value for keyword ''electrodes''');
  424. end
  425. case 'dipole'
  426. DIPOLE = Value;
  427. case 'dipsphere'
  428. DIPSPHERE = Value;
  429. case 'dipnorm'
  430. DIPNORM = Value;
  431. case 'diplen'
  432. DIPLEN = Value;
  433. case 'dipscale'
  434. DIPSCALE = Value;
  435. case 'contourvals'
  436. ContourVals = Value;
  437. case 'pmask'
  438. ContourVals = Value;
  439. PMASKFLAG = 1;
  440. case 'diporient'
  441. DIPORIENT = Value;
  442. case 'dipcolor'
  443. DIPCOLOR = Value;
  444. case 'emarker'
  445. if ischar(Value)
  446. EMARKER = Value;
  447. elseif ~iscell(Value) | length(Value) > 4
  448. error('''emarker'' argument must be a cell array {marker color size linewidth}')
  449. else
  450. EMARKER = Value{1};
  451. end
  452. if length(Value) > 1
  453. ECOLOR = Value{2};
  454. end
  455. if length(Value) > 2
  456. EMARKERSIZE2 = Value{3};
  457. end
  458. if length(Value) > 3
  459. EMARKERLINEWIDTH = Value{4};
  460. end
  461. case 'emarker2'
  462. if ~iscell(Value) | length(Value) > 5
  463. error('''emarker2'' argument must be a cell array {chans marker color size linewidth}')
  464. end
  465. EMARKER2CHANS = abs(Value{1}); % ignore channels < 0
  466. if length(Value) > 1
  467. EMARKER2 = Value{2};
  468. end
  469. if length(Value) > 2
  470. EMARKER2COLOR = Value{3};
  471. end
  472. if length(Value) > 3
  473. EMARKERSIZE2 = Value{4};
  474. end
  475. if length(Value) > 4
  476. EMARKER2LINEWIDTH = Value{5};
  477. end
  478. case 'shrink'
  479. shrinkfactor = Value;
  480. case 'intrad'
  481. intrad = Value;
  482. if isstr(intrad) | (intrad < MINPLOTRAD | intrad > 1)
  483. error('intrad argument should be a number between 0.15 and 1.0');
  484. end
  485. case 'plotrad'
  486. plotrad = Value;
  487. if isstr(plotrad) | (plotrad < MINPLOTRAD | plotrad > 1)
  488. error('plotrad argument should be a number between 0.15 and 1.0');
  489. end
  490. case 'headrad'
  491. headrad = Value;
  492. if isstr(headrad) & ( strcmpi(headrad,'off') | strcmpi(headrad,'none') )
  493. headrad = 0; % undocumented 'no head' alternatives
  494. end
  495. if isempty(headrad) % [] -> none also
  496. headrad = 0;
  497. end
  498. if ~isstr(headrad)
  499. if ~(headrad==0) & (headrad < MINPLOTRAD | headrad>1)
  500. error('bad value for headrad');
  501. end
  502. elseif ~strcmpi(headrad,'rim')
  503. error('bad value for headrad');
  504. end
  505. case {'headcolor','hcolor'}
  506. HEADCOLOR = Value;
  507. case {'contourcolor','ccolor'}
  508. CCOLOR = Value;
  509. case {'electcolor','ecolor'}
  510. ECOLOR = Value;
  511. case {'emarkersize','emsize'}
  512. EMARKERSIZE = Value;
  513. case {'emarkersize1chan','emarkersizemark'}
  514. EMARKERSIZE1CHAN= Value;
  515. case {'efontsize','efsize'}
  516. EFSIZE = Value;
  517. case 'shading'
  518. SHADING = lower(Value);
  519. if ~any(strcmp(SHADING,{'flat','interp'}))
  520. error('Invalid shading parameter')
  521. end
  522. case 'noplot'
  523. noplot = Value;
  524. if ~isstr(noplot)
  525. if length(noplot) ~= 2
  526. error('''noplot'' location should be [radius, angle]')
  527. else
  528. chanrad = noplot(1);
  529. chantheta = noplot(2);
  530. noplot = 'on';
  531. end
  532. end
  533. case 'gridscale'
  534. GRID_SCALE = Value;
  535. if isstr(GRID_SCALE) | GRID_SCALE ~= round(GRID_SCALE) | GRID_SCALE < 32
  536. error('''gridscale'' value must be integer > 32.');
  537. end
  538. case {'plotgrid','gridplot'}
  539. plotgrid = 'on';
  540. gridchans = Value;
  541. case 'plotchans'
  542. plotchans = Value(:);
  543. if find(plotchans<=0)
  544. error('''plotchans'' values must be > 0');
  545. end
  546. % if max(abs(plotchans))>max(Values) | max(abs(plotchans))>length(Values) -sm ???
  547. case {'whitebk','whiteback','forprint'}
  548. whitebk = Value;
  549. otherwise
  550. error(['Unknown input parameter ''' Param ''' ???'])
  551. end
  552. end
  553. end
  554. if strcmpi(whitebk, 'on')
  555. BACKCOLOR = [ 1 1 1 ];
  556. end;
  557. cmap = jet(64);
  558. cmaplen = size(cmap,1);
  559. %ELECTRODES = 'off';
  560. GRID_SCALE = 32;
  561. STYLE='map';
  562. if strcmp(STYLE,'blank') % else if Values holds numbers of channels to mark
  563. if length(Values) < length(loc_file)
  564. ContourVals = zeros(1,length(loc_file));
  565. ContourVals(Values) = 1;
  566. Values = ContourVals;
  567. end;
  568. end;
  569. %
  570. %%%%%%%%%%%%%%%%%%%%%%%%%%% test args for plotting an electrode grid %%%%%%%%%%%%%%%%%%%%%%
  571. %
  572. if strcmp(plotgrid,'on')
  573. STYLE = 'grid';
  574. gchans = sort(find(abs(gridchans(:))>0));
  575. % if setdiff(gchans,unique(gchans))
  576. % fprintf('topoplot() warning: ''plotgrid'' channel matrix has duplicate channels\n');
  577. % end
  578. if ~isempty(plotchans)
  579. if intersect(gchans,abs(plotchans))
  580. fprintf('topoplot() warning: ''plotgrid'' and ''plotchans'' have channels in common\n');
  581. end
  582. end
  583. end
  584. %
  585. %%%%%%%%%%%%%%%%%%%%%%%%%%% misc arg tests %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  586. %
  587. if isempty(ELECTRODES) % if electrode labeling not specified
  588. if length(Values) > MAXDEFAULTSHOWLOCS % if more channels than default max
  589. ELECTRODES = 'off'; % don't show electrodes
  590. else % else if fewer chans,
  591. ELECTRODES = 'on'; % do
  592. end
  593. end
  594. if isempty(Values)
  595. STYLE = 'blank';
  596. end
  597. [r,c] = size(Values);
  598. if r>1 & c>1,
  599. error('input data must be a single vector');
  600. end
  601. Values = Values(:); % make Values a column vector
  602. ContourVals = ContourVals(:); % values for contour
  603. if ~isempty(intrad) & ~isempty(plotrad) & intrad < plotrad
  604. error('intrad must be >= plotrad');
  605. end
  606. if ~strcmpi(STYLE,'grid') % if not plot grid only
  607. %
  608. %%%%%%%%%%%%%%%%%%%% Read the channel location information %%%%%%%%%%%%%%%%%%%%%%%%
  609. %
  610. if isstr(loc_file)
  611. [tmpeloc labels Th Rd indices] = readlocs( loc_file);
  612. elseif isstruct(loc_file) % a locs struct
  613. [tmpeloc labels Th Rd indices] = readlocs( loc_file );
  614. % Note: Th and Rd correspond to indices channels-with-coordinates only
  615. else
  616. error('loc_file must be a EEG.locs struct or locs filename');
  617. end
  618. Th = pi/180*Th; % convert degrees to radians
  619. allchansind = 1:length(Th);
  620. if ~isempty(plotchans)
  621. if max(plotchans) > length(Th)
  622. error('''plotchans'' values must be <= max channel index');
  623. end
  624. end
  625. %
  626. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% channels to plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  627. %
  628. if ~isempty(plotchans)
  629. plotchans = intersect(plotchans, indices);
  630. end;
  631. if ~isempty(Values) & ~strcmpi( STYLE, 'blank') & isempty(plotchans)
  632. plotchans = indices;
  633. end
  634. if isempty(plotchans) & strcmpi( STYLE, 'blank')
  635. plotchans = indices;
  636. end
  637. %
  638. %%%%%%%%%%%%%%%%%%%%%%%%%%% filter for channel type(s), if specified %%%%%%%%%%%%%%%%%%%%%
  639. %
  640. if CHOOSECHANTYPE,
  641. newplotchans = eeg_chantype(loc_file,chantype);
  642. plotchans = intersect(newplotchans, plotchans);
  643. end
  644. %
  645. %%%%%%%%%%%%%%%%%%%%%%%%%%% filter channels used for components %%%%%%%%%%%%%%%%%%%%%
  646. %
  647. if isfield(CHANINFO, 'icachansind') & ~isempty(Values) & length(Values) ~= length(tmpeloc)
  648. % test if ICA component
  649. % ---------------------
  650. if length(CHANINFO.icachansind) == length(Values)
  651. % if only a subset of channels are to be plotted
  652. % and ICA components also use a subject of channel
  653. % we must find the new indices for these channels
  654. plotchans = intersect(CHANINFO.icachansind, plotchans);
  655. tmpvals = zeros(1, length(tmpeloc));
  656. tmpvals(CHANINFO.icachansind) = Values;
  657. Values = tmpvals;
  658. tmpvals = zeros(1, length(tmpeloc));
  659. tmpvals(CHANINFO.icachansind) = ContourVals;
  660. ContourVals = tmpvals;
  661. end;
  662. end;
  663. %
  664. %%%%%%%%%%%%%%%%%%% last channel is reference? %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  665. %
  666. if length(tmpeloc) == length(Values) + 1 % remove last channel if necessary
  667. % (common reference channel)
  668. if plotchans(end) == length(tmpeloc)
  669. plotchans(end) = [];
  670. end;
  671. end;
  672. %
  673. %%%%%%%%%%%%%%%%%%% remove infinite and NaN values %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  674. %
  675. if length(Values) > 1
  676. inds = union(find(isnan(Values)), find(isinf(Values))); % NaN and Inf values
  677. plotchans = setdiff(plotchans, inds);
  678. end;
  679. if strcmp(plotgrid,'on')
  680. plotchans = setxor(plotchans,gchans); % remove grid chans from head plotchans
  681. end
  682. [x,y] = pol2cart(Th,Rd); % transform electrode locations from polar to cartesian coordinates
  683. plotchans = abs(plotchans); % reverse indicated channel polarities
  684. allchansind = allchansind(plotchans);
  685. Th = Th(plotchans);
  686. Rd = Rd(plotchans);
  687. x = x(plotchans);
  688. y = y(plotchans);
  689. labels = labels(plotchans); % remove labels for electrodes without locations
  690. labels = strvcat(labels); % make a label string matrix
  691. if ~isempty(Values) & length(Values) > 1
  692. Values = Values(plotchans);
  693. ContourVals = ContourVals(plotchans);
  694. end;
  695. %
  696. %%%%%%%%%%%%%%%%%% Read plotting radius from chanlocs %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  697. %
  698. if isempty(plotrad) & isfield(tmpeloc, 'plotrad'),
  699. plotrad = tmpeloc(1).plotrad;
  700. if isstr(plotrad) % plotrad shouldn't be a string
  701. plotrad = str2num(plotrad) % just checking
  702. end
  703. if plotrad < MINPLOTRAD | plotrad > 1.0
  704. fprintf('Bad value (%g) for plotrad.\n',plotrad);
  705. error(' ');
  706. end
  707. if strcmpi(VERBOSE,'on') & ~isempty(plotrad)
  708. fprintf('Plotting radius plotrad (%g) set from EEG.chanlocs.\n',plotrad);
  709. end
  710. end;
  711. if isempty(plotrad)
  712. plotrad = min(1.0,max(Rd)*1.02); % default: just outside the outermost electrode location
  713. plotrad = max(plotrad,0.5); % default: plot out to the 0.5 head boundary
  714. end % don't plot channels with Rd > 1 (below head)
  715. if isempty(intrad)
  716. default_intrad = 1; % indicator for (no) specified intrad
  717. intrad = min(1.0,max(Rd)*1.02); % default: just outside the outermost electrode location
  718. else
  719. default_intrad = 0; % indicator for (no) specified intrad
  720. if plotrad > intrad
  721. plotrad = intrad;
  722. end
  723. end % don't interpolate channels with Rd > 1 (below head)
  724. if isstr(plotrad) | plotrad < MINPLOTRAD | plotrad > 1.0
  725. error('plotrad must be between 0.15 and 1.0');
  726. end
  727. %
  728. %%%%%%%%%%%%%%%%%%%%%%% Set radius of head cartoon %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  729. %
  730. if isempty(headrad) % never set -> defaults
  731. if plotrad >= rmax
  732. headrad = rmax; % (anatomically correct)
  733. else % if plotrad < rmax
  734. headrad = 0; % don't plot head
  735. if strcmpi(VERBOSE, 'on')
  736. fprintf('topoplot(): not plotting cartoon head since plotrad (%5.4g) < 0.5\n',...
  737. plotrad);
  738. end
  739. end
  740. elseif strcmpi(headrad,'rim') % force plotting at rim of map
  741. headrad = plotrad;
  742. end
  743. %
  744. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Shrink mode %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  745. %
  746. if ~isempty(shrinkfactor) | isfield(tmpeloc, 'shrink'),
  747. if isempty(shrinkfactor) & isfield(tmpeloc, 'shrink'),
  748. shrinkfactor = tmpeloc(1).shrink;
  749. if strcmpi(VERBOSE,'on')
  750. if isstr(shrinkfactor)
  751. fprintf('Automatically shrinking coordinates to lie above the head perimter.\n');
  752. else
  753. fprintf('Automatically shrinking coordinates by %3.2f\n', shrinkfactor);
  754. end;
  755. end
  756. end;
  757. if isstr(shrinkfactor)
  758. if strcmpi(shrinkfactor, 'on') | strcmpi(shrinkfactor, 'force') | strcmpi(shrinkfactor, 'auto')
  759. if abs(headrad-rmax) > 1e-2
  760. fprintf(' NOTE -> the head cartoon will NOT accurately indicate the actual electrode locations\n');
  761. end
  762. if strcmpi(VERBOSE,'on')
  763. fprintf(' Shrink flag -> plotting cartoon head at plotrad\n');
  764. end
  765. headrad = plotrad; % plot head around outer electrodes, no matter if 0.5 or not
  766. end
  767. else % apply shrinkfactor
  768. plotrad = rmax/(1-shrinkfactor);
  769. headrad = plotrad; % make deprecated 'shrink' mode plot
  770. if strcmpi(VERBOSE,'on')
  771. fprintf(' %g%% shrink applied.');
  772. if abs(headrad-rmax) > 1e-2
  773. fprintf(' Warning: With this "shrink" setting, the cartoon head will NOT be anatomically correct.\n');
  774. else
  775. fprintf('\n');
  776. end
  777. end
  778. end
  779. end; % if shrink
  780. %
  781. %%%%%%%%%%%%%%%%% Issue warning if headrad ~= rmax %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  782. %
  783. if headrad ~= 0.5 & strcmpi(VERBOSE, 'on')
  784. fprintf(' NB: Plotting map using ''plotrad'' %-4.3g,',plotrad);
  785. fprintf( ' ''headrad'' %-4.3g\n',headrad);
  786. fprintf('Warning: The plotting radius of the cartoon head is NOT anatomically correct (0.5).\n')
  787. end
  788. %
  789. %%%%%%%%%%%%%%%%%%%%% Find plotting channels %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  790. %
  791. pltchans = find(Rd <= plotrad); % plot channels inside plotting circle
  792. if strcmpi(INTSQUARE,'on') % interpolate channels in the radius intrad square
  793. intchans = find(x <= intrad & y <= intrad); % interpolate and plot channels inside interpolation square
  794. else
  795. intchans = find(Rd <= intrad); % interpolate channels in the radius intrad circle only
  796. end
  797. %
  798. %%%%%%%%%%%%%%%%%%%%% Eliminate channels not plotted %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  799. %
  800. allx = x;
  801. ally = y;
  802. intchans; % interpolate using only the 'intchans' channels
  803. pltchans; % plot using only indicated 'plotchans' channels
  804. if length(pltchans) < length(Rd) & strcmpi(VERBOSE, 'on')
  805. fprintf('Interpolating %d and plotting %d of the %d scalp electrodes.\n', ...
  806. length(intchans),length(pltchans),length(Rd));
  807. end;
  808. % fprintf('topoplot(): plotting %d channels\n',length(pltchans));
  809. if ~isempty(EMARKER2CHANS)
  810. if strcmpi(STYLE,'blank')
  811. error('emarker2 not defined for style ''blank'' - use marking channel numbers in place of data');
  812. else % mark1chans and mark2chans are subsets of pltchans for markers 1 and 2
  813. [tmp1 mark1chans tmp2] = setxor(pltchans,EMARKER2CHANS);
  814. [tmp3 tmp4 mark2chans] = intersect(EMARKER2CHANS,pltchans);
  815. end
  816. end
  817. if ~isempty(Values)
  818. if length(Values) == length(Th) % if as many map Values as channel locs
  819. intValues = Values(intchans);
  820. intContourVals = ContourVals(intchans);
  821. Values = Values(pltchans);
  822. ContourVals = ContourVals(pltchans);
  823. end;
  824. end; % now channel parameters and values all refer to plotting channels only
  825. allchansind = allchansind(pltchans);
  826. intTh = Th(intchans); % eliminate channels outside the interpolation area
  827. intRd = Rd(intchans);
  828. intx = x(intchans);
  829. inty = y(intchans);
  830. Th = Th(pltchans); % eliminate channels outside the plotting area
  831. Rd = Rd(pltchans);
  832. x = x(pltchans);
  833. y = y(pltchans);
  834. labels= labels(pltchans,:);
  835. %
  836. %%%%%%%%%%%%%%% Squeeze channel locations to <= rmax %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  837. %
  838. squeezefac = rmax/plotrad;
  839. intRd = intRd*squeezefac; % squeeze electrode arc_lengths towards the vertex
  840. Rd = Rd*squeezefac; % squeeze electrode arc_lengths towards the vertex
  841. % to plot all inside the head cartoon
  842. intx = intx*squeezefac;
  843. inty = inty*squeezefac;
  844. x = x*squeezefac;
  845. y = y*squeezefac;
  846. allx = allx*squeezefac;
  847. ally = ally*squeezefac;
  848. % Note: Now outermost channel will be plotted just inside rmax
  849. else % if strcmpi(STYLE,'grid')
  850. intx = rmax; inty=rmax;
  851. end % if ~strcmpi(STYLE,'grid')
  852. %
  853. %%%%%%%%%%%%%%%% rotate channels based on chaninfo %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  854. %
  855. if strcmpi(lower(NOSEDIR), '+x')
  856. rotate = 0;
  857. else
  858. if strcmpi(lower(NOSEDIR), '+y')
  859. rotate = 3*pi/2;
  860. elseif strcmpi(lower(NOSEDIR), '-x')
  861. rotate = pi;
  862. else rotate = pi/2;
  863. end;
  864. allcoords = (inty + intx*sqrt(-1))*exp(sqrt(-1)*rotate);
  865. intx = imag(allcoords);
  866. inty = real(allcoords);
  867. allcoords = (ally + allx*sqrt(-1))*exp(sqrt(-1)*rotate);
  868. allx = imag(allcoords);
  869. ally = real(allcoords);
  870. allcoords = (y + x*sqrt(-1))*exp(sqrt(-1)*rotate);
  871. x = imag(allcoords);
  872. y = real(allcoords);
  873. end;
  874. %
  875. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Make the plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  876. %
  877. if ~strcmpi(STYLE,'blank') % if draw interpolated scalp map
  878. if ~strcmpi(STYLE,'grid') % not a rectangular channel grid
  879. %
  880. %%%%%%%%%%%%%%%% Find limits for interpolation %%%%%%%%%%%%%%%%%%%%%%%%%%%%
  881. %
  882. if default_intrad % if no specified intrad
  883. if strcmpi(INTERPLIMITS,'head') % intrad is 'head'
  884. xmin = min(-rmax,min(intx)); xmax = max(rmax,max(intx));
  885. ymin = min(-rmax,min(inty)); ymax = max(rmax,max(inty));
  886. else % INTERPLIMITS = rectangle containing electrodes -- DEPRECATED OPTION!
  887. xmin = max(-rmax,min(intx)); xmax = min(rmax,max(intx));
  888. ymin = max(-rmax,min(inty)); ymax = min(rmax,max(inty));
  889. end
  890. else % some other intrad specified
  891. xmin = -intrad*squeezefac; xmax = intrad*squeezefac; % use the specified intrad value
  892. ymin = -intrad*squeezefac; ymax = intrad*squeezefac;
  893. end
  894. %
  895. %%%%%%%%%%%%%%%%%%%%%%% Interpolate scalp map data %%%%%%%%%%%%%%%%%%%%%%%%
  896. %
  897. xi = linspace(xmin,xmax,GRID_SCALE); % x-axis description (row vector)
  898. yi = linspace(ymin,ymax,GRID_SCALE); % y-axis description (row vector)
  899. [Xi,Yi,Zi] = griddata(double(inty),double(intx),double(intValues),double(yi)',double(xi),'v4'); % interpolate data
  900. % [Xi,Yi,ZiC] = griddata(double(inty),double(intx),double(intContourVals),double(yi)',double(xi),'v4'); % interpolate data
  901. %
  902. %%%%%%%%%%%%%%%%%%%%%%% Mask out data outside the head %%%%%%%%%%%%%%%%%%%%%
  903. %
  904. mask = (sqrt(Xi.^2 + Yi.^2) <= rmax); % mask outside the plotting circle
  905. ii = find(mask == 0);
  906. Zi(ii) = NaN; % mask non-plotting voxels with NaNs
  907. % ZiC(ii) = NaN; % mask non-plotting voxels with NaNs
  908. grid = plotrad; % unless 'noplot', then 3rd output arg is plotrad
  909. %
  910. %%%%%%%%%% Return interpolated value at designated scalp location %%%%%%%%%%
  911. %
  912. if exist('chanrad') % optional first argument to 'noplot'
  913. chantheta = (chantheta/360)*2*pi;
  914. chancoords = round(ceil(GRID_SCALE/2)+GRID_SCALE/2*2*chanrad*[cos(-chantheta),...
  915. -sin(-chantheta)]);
  916. if chancoords(1)<1 ...
  917. | chancoords(1) > GRID_SCALE ...
  918. | chancoords(2)<1 ...
  919. | chancoords(2)>GRID_SCALE
  920. error('designated ''noplot'' channel out of bounds')
  921. else
  922. chanval = Zi(chancoords(1),chancoords(2));
  923. grid = Zi;
  924. Zi = chanval; % return interpolated value instead of Zi
  925. end
  926. end
  927. %
  928. %%%%%%%%%%%%%%%%%%%%%%%%%% Return interpolated image only %%%%%%%%%%%%%%%%%
  929. %
  930. if strcmpi(noplot, 'on')
  931. if strcmpi(VERBOSE,'on')
  932. fprintf('topoplot(): no plot requested.\n')
  933. end
  934. return;
  935. end
  936. %
  937. %%%%%%%%%%%%%%%%%%%%%%% Calculate colormap limits %%%%%%%%%%%%%%%%%%%%%%%%%%
  938. %
  939. if isstr(MAPLIMITS)
  940. if strcmp(MAPLIMITS,'absmax')
  941. amax = max(max(abs(Zi)));
  942. amin = -amax;
  943. elseif strcmp(MAPLIMITS,'maxmin') | strcmp(MAPLIMITS,'minmax')
  944. amin = min(min(Zi));
  945. amax = max(max(Zi));
  946. else
  947. error('unknown ''maplimits'' value.');
  948. end
  949. elseif length(MAPLIMITS) == 2
  950. amin = MAPLIMITS(1);
  951. amax = MAPLIMITS(2);
  952. else
  953. error('unknown ''maplimits'' value');
  954. end
  955. delta = xi(2)-xi(1); % length of grid entry
  956. end % if ~strcmpi(STYLE,'grid')
  957. %
  958. %%%%%%%%%%%%%%%%%%%%%%%%%% Scale the axes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  959. %
  960. %cla % clear current axis
  961. hold on
  962. h = gca; % uses current axes
  963. % instead of default larger AXHEADFAC
  964. if squeezefac<0.92 & plotrad-headrad > 0.05 % (size of head in axes)
  965. AXHEADFAC = 1.05; % do not leave room for external ears if head cartoon
  966. % shrunk enough by the 'skirt' option
  967. end
  968. set(gca,'Xlim',[-rmax rmax]*AXHEADFAC,'Ylim',[-rmax rmax]*AXHEADFAC);
  969. % specify size of head axes in gca
  970. unsh = (GRID_SCALE+1)/GRID_SCALE; % un-shrink the effects of 'interp' SHADING
  971. %
  972. %%%%%%%%%%%%%%%%%%%%%%%% Plot grid only %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  973. %
  974. if strcmpi(STYLE,'grid') % plot grid only
  975. %
  976. % The goal below is to make the grid cells square - not yet achieved in all cases? -sm
  977. %
  978. g1 = size(gridchans,1);
  979. g2 = size(gridchans,2);
  980. gmax = max([g1 g2]);
  981. Xi = linspace(-rmax*g2/gmax,rmax*g2/gmax,g1+1);
  982. Xi = Xi+rmax/g1; Xi = Xi(1:end-1);
  983. Yi = linspace(-rmax*g1/gmax,rmax*g1/gmax,g2+1);
  984. Yi = Yi+rmax/g2; Yi = Yi(1:end-1); Yi = Yi(end:-1:1); % by trial and error!
  985. %
  986. %%%%%%%%%%% collect the gridchans values %%%%%%%%%%%%%%%%%%%%%%%%%%%
  987. %
  988. gridvalues = zeros(size(gridchans));
  989. for j=1:size(gridchans,1)
  990. for k=1:size(gridchans,2)
  991. gc = gridchans(j,k);
  992. if gc > 0
  993. gridvalues(j,k) = Values(gc);
  994. elseif gc < 0
  995. gridvalues(j,k) = -Values(gc);
  996. else
  997. gridvalues(j,k) = nan; % not-a-number = no value
  998. end
  999. end
  1000. end
  1001. %
  1002. %%%%%%%%%%% reset color limits for grid plot %%%%%%%%%%%%%%%%%%%%%%%%%
  1003. %
  1004. if isstr(MAPLIMITS)
  1005. if strcmp(MAPLIMITS,'maxmin') | strcmp(MAPLIMITS,'minmax')
  1006. amin = min(min(gridvalues(~isnan(gridvalues))));
  1007. amax = max(max(gridvalues(~isnan(gridvalues))));
  1008. elseif strcmp(MAPLIMITS,'absmax')
  1009. % 11/21/2005 Toby edit
  1010. % This should now work as specified. Before it only crashed (using
  1011. % "plotgrid" and "maplimits>absmax" options).
  1012. amax = max(max(abs(gridvalues(~isnan(gridvalues)))));
  1013. amin = -amax;
  1014. %amin = -max(max(abs([amin amax])));
  1015. %amax = max(max(abs([amin amax])));
  1016. else
  1017. error('unknown ''maplimits'' value');
  1018. end
  1019. elseif length(MAPLIMITS) == 2
  1020. amin = MAPLIMITS(1);
  1021. amax = MAPLIMITS(2);
  1022. else
  1023. error('unknown ''maplimits'' value');
  1024. end
  1025. %
  1026. %%%%%%%%%% explicitly compute grid colors, allowing BACKCOLOR %%%%%%
  1027. %
  1028. gridvalues = 1+floor(cmaplen*(gridvalues-amin)/(amax-amin));
  1029. gridvalues(find(gridvalues == cmaplen+1)) = cmaplen;
  1030. gridcolors = zeros([size(gridvalues),3]);
  1031. for j=1:size(gridchans,1)
  1032. for k=1:size(gridchans,2)
  1033. if ~isnan(gridvalues(j,k))
  1034. gridcolors(j,k,:) = cmap(gridvalues(j,k),:);
  1035. else
  1036. if strcmpi(whitebk,'off')
  1037. gridcolors(j,k,:) = BACKCOLOR; % gridchans == 0 -> background color
  1038. % This allows the plot to show 'space' between separate sub-grids or strips
  1039. else % 'on'
  1040. gridcolors(j,k,:) = [1 1 1]; BACKCOLOR; % gridchans == 0 -> white for printing
  1041. end
  1042. end
  1043. end
  1044. end
  1045. %
  1046. %%%%%%%%%% draw the gridplot image %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1047. %
  1048. handle=imagesc(Xi,Yi,gridcolors); % plot grid with explicit colors
  1049. axis square
  1050. %
  1051. %%%%%%%%%%%%%%%%%%%%%%%% Plot map contours only %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1052. %
  1053. % elseif strcmp(STYLE,'contour') % plot surface contours only
  1054. % [cls chs] = contour(Xi,Yi,ZiC,CONTOURNUM,'k');
  1055. % % for h=chs, set(h,'color',CCOLOR); end
  1056. % %
  1057. % %%%%%%%%%%%%%%%%%%%%%%%% Else plot map and contours %%%%%%%%%%%%%%%%%%%%%%%%%
  1058. % %
  1059. % elseif strcmp(STYLE,'both') % plot interpolated surface and surface contours
  1060. % if strcmp(SHADING,'interp')
  1061. % tmph = surface(Xi*unsh,Yi*unsh,zeros(size(Zi))-0.1,Zi,...
  1062. % 'EdgeColor','none','FaceColor',SHADING);
  1063. % else % SHADING == 'flat'
  1064. % tmph = surface(Xi-delta/2,Yi-delta/2,zeros(size(Zi))-0.1,Zi,...
  1065. % 'EdgeColor','none','FaceColor',SHADING);
  1066. % end
  1067. % if strcmpi(MASKSURF, 'on')
  1068. % set(tmph, 'visible', 'off');
  1069. % handle = tmph;
  1070. % end;
  1071. %
  1072. % warning off;
  1073. % if ~PMASKFLAG
  1074. % [cls chs] = contour(Xi,Yi,ZiC,CONTOURNUM,'k');
  1075. % else
  1076. % ZiC(find(ZiC > 0.5 )) = NaN;
  1077. % [cls chs] = contourf(Xi,Yi,ZiC,0,'k');
  1078. % subh = get(chs, 'children');
  1079. % for indsubh = 1:length(subh)
  1080. % numfaces = size(get(subh(indsubh), 'XData'),1);
  1081. % set(subh(indsubh), 'FaceVertexCData', ones(numfaces,3), 'Cdatamapping', 'direct', 'facealpha', 0.5, 'linewidth', 2);
  1082. % end;
  1083. % end;
  1084. % for h=chs, set(h,'color',CCOLOR); end
  1085. % warning on;
  1086. %
  1087. %%%%%%%%%%%%%%%%%%%%%%%% Else plot map only %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1088. %
  1089. elseif strcmp(STYLE,'straight') | strcmp(STYLE,'map') % 'straight' was former arg
  1090. if strcmp(SHADING,'interp') % 'interp' mode is shifted somehow... but how?
  1091. tmph = surface(Xi*unsh,Yi*unsh,zeros(size(Zi)),Zi,'EdgeColor','none',...
  1092. 'FaceColor',SHADING);
  1093. else
  1094. tmph = surface(Xi-delta/2,Yi-delta/2,zeros(size(Zi)),Zi,'EdgeColor','none',...
  1095. 'FaceColor',SHADING);
  1096. end
  1097. if strcmpi(MASKSURF, 'on')
  1098. set(tmph, 'visible', 'off');
  1099. handle = tmph;
  1100. end;
  1101. %
  1102. %%%%%%%%%%%%%%%%%% Else fill contours with uniform colors %%%%%%%%%%%%%%%%%%
  1103. %
  1104. elseif strcmp(STYLE,'fill')
  1105. [cls chs] = contourf(Xi,Yi,Zi,CONTOURNUM,'k');
  1106. % for h=chs, set(h,'color',CCOLOR); end
  1107. % <- 'not line objects.' Why does 'both' work above???
  1108. else
  1109. error('Invalid style')
  1110. end
  1111. %
  1112. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Set color axis %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1113. %
  1114. caxis([amin amax]); % set coloraxis
  1115. colormap(jet(100))
  1116. else % if STYLE 'blank'
  1117. %
  1118. %%%%%%%%%%%%%%%%%%%%%%% Draw blank head %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1119. %
  1120. if strcmpi(noplot, 'on')
  1121. if strcmpi(VERBOSE,'on')
  1122. fprintf('topoplot(): no plot requested.\n')
  1123. end
  1124. return;
  1125. end
  1126. %cla
  1127. hold on
  1128. set(gca,'Xlim',[-rmax rmax]*AXHEADFAC,'Ylim',[-rmax rmax]*AXHEADFAC)
  1129. % pos = get(gca,'position');
  1130. % fprintf('Current axes size %g,%g\n',pos(3),pos(4));
  1131. if strcmp(ELECTRODES,'labelpoint') | strcmp(ELECTRODES,'numpoint')
  1132. text(-0.6,-0.6, ...
  1133. [ int2str(length(Rd)) ' of ' int2str(length(tmpeloc)) ' electrode locations shown']);
  1134. text(-0.6,-0.7, [ 'Click on electrodes to toggle name/number']);
  1135. tl = title('Channel locations');
  1136. set(tl, 'fontweight', 'bold');
  1137. end;
  1138. end % STYLE 'blank'
  1139. if exist('handle') ~= 1
  1140. handle = gca;
  1141. end;
  1142. if ~strcmpi(STYLE,'grid') % if not plot grid only
  1143. %
  1144. %%%%%%%%%%%%%%%%%%% Plot filled ring to mask jagged grid boundary %%%%%%%%%%%%%%%%%%%%%%%%%%%
  1145. %
  1146. hwidth = HEADRINGWIDTH; % width of head ring
  1147. hin = squeezefac*headrad*(1- hwidth/2); % inner head ring radius
  1148. if strcmp(SHADING,'interp')
  1149. rwidth = BLANKINGRINGWIDTH*1.3; % width of blanking outer ring
  1150. else
  1151. rwidth = BLANKINGRINGWIDTH; % width of blanking outer ring
  1152. end
  1153. rin = rmax*(1-rwidth/2); % inner ring radius
  1154. if hin>rin
  1155. rin = hin; % dont blank inside the head ring
  1156. end
  1157. if strcmp(CONVHULL,'on') %%%%%%%%% mask outside the convex hull of the electrodes %%%%%%%%%
  1158. cnv = convhull(allx,ally);
  1159. cnvfac = round(CIRCGRID/length(cnv)); % spline interpolate the convex hull
  1160. if cnvfac < 1, cnvfac=1; end;
  1161. CIRCGRID = cnvfac*length(cnv);
  1162. startangle = atan2(allx(cnv(1)),ally(cnv(1)));
  1163. circ = linspace(0+startangle,2*pi+startangle,CIRCGRID);
  1164. rx = sin(circ);
  1165. ry = cos(circ);
  1166. allx = allx(:)'; % make x (elec locations; + to nose) a row vector
  1167. ally = ally(:)'; % make y (elec locations, + to r? ear) a row vector
  1168. erad = sqrt(allx(cnv).^2+ally(cnv).^2); % convert to polar coordinates
  1169. eang = atan2(allx(cnv),ally(cnv));
  1170. eang = unwrap(eang);
  1171. eradi =spline(linspace(0,1,3*length(cnv)), [erad erad erad], ...
  1172. linspace(0,1,3*length(cnv)*cnvfac));
  1173. eangi =spline(linspace(0,1,3*length(cnv)), [eang+2*pi eang eang-2*pi], ...
  1174. linspace(0,1,3*length(cnv)*cnvfac));
  1175. xx = eradi.*sin(eangi); % convert back to rect coordinates
  1176. yy = eradi.*cos(eangi);
  1177. yy = yy(CIRCGRID+1:2*CIRCGRID);
  1178. xx = xx(CIRCGRID+1:2*CIRCGRID);
  1179. eangi = eangi(CIRCGRID+1:2*CIRCGRID);
  1180. eradi = eradi(CIRCGRID+1:2*CIRCGRID);
  1181. xx = xx*1.02; yy = yy*1.02; % extend spline outside electrode marks
  1182. splrad = sqrt(xx.^2+yy.^2); % arc radius of spline points (yy,xx)
  1183. oob = find(splrad >= rin); % enforce an upper bound on xx,yy
  1184. xx(oob) = rin*xx(oob)./splrad(oob); % max radius = rin
  1185. yy(oob) = rin*yy(oob)./splrad(oob); % max radius = rin
  1186. splrad = sqrt(xx.^2+yy.^2); % arc radius of spline points (yy,xx)
  1187. oob = find(splrad < hin); % don't let splrad be inside the head cartoon
  1188. xx(oob) = hin*xx(oob)./splrad(oob); % min radius = hin
  1189. yy(oob) = hin*yy(oob)./splrad(oob); % min radius = hin
  1190. ringy = [[ry(:)' ry(1) ]*(rin+rwidth) yy yy(1)];
  1191. ringx = [[rx(:)' rx(1) ]*(rin+rwidth) xx xx(1)];
  1192. ringh2= patch(ringy,ringx,ones(size(ringy)),BACKCOLOR,'edgecolor','none'); hold on
  1193. % plot(ry*rmax,rx*rmax,'b') % debugging line
  1194. else %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% mask the jagged border around rmax %%%%%%%%%%%%%%%5%%%%%%
  1195. circ = linspace(0,2*pi,CIRCGRID);
  1196. rx = sin(circ);
  1197. ry = cos(circ);
  1198. ringx = [[rx(:)' rx(1) ]*(rin+rwidth) [rx(:)' rx(1)]*rin];
  1199. ringy = [[ry(:)' ry(1) ]*(rin+rwidth) [ry(:)' ry(1)]*rin];
  1200. if ~strcmpi(STYLE,'blank')
  1201. ringh= patch(ringx,ringy,0.01*ones(size(ringx)),BACKCOLOR,'edgecolor','none'); hold on
  1202. end
  1203. % plot(ry*rmax,rx*rmax,'b') % debugging line
  1204. end
  1205. %f1= fill(rin*[rx rX],rin*[ry rY],BACKCOLOR,'edgecolor',BACKCOLOR); hold on
  1206. %f2= fill(rin*[rx rX*(1+rwidth)],rin*[ry rY*(1+rwidth)],BACKCOLOR,'edgecolor',BACKCOLOR);
  1207. % Former line-style border smoothing - width did not scale with plot
  1208. % brdr=plot(1.015*cos(circ).*rmax,1.015*sin(circ).*rmax,... % old line-based method
  1209. % 'color',HEADCOLOR,'Linestyle','-','LineWidth',HLINEWIDTH); % plot skirt outline
  1210. % set(brdr,'color',BACKCOLOR,'linewidth',HLINEWIDTH + 4); % hide the disk edge jaggies
  1211. %
  1212. %%%%%%%%%%%%%%%%%%%%%%%%% Plot cartoon head, ears, nose %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1213. %
  1214. if headrad > 0 % if cartoon head to be plotted
  1215. %
  1216. %%%%%%%%%%%%%%%%%%% Plot head outline %%%%%%%%%%%%%%%%%%%%%%%%%%%
  1217. %
  1218. headx = [[rx(:)' rx(1) ]*(hin+hwidth) [rx(:)' rx(1)]*hin];
  1219. heady = [[ry(:)' ry(1) ]*(hin+hwidth) [ry(:)' ry(1)]*hin];
  1220. if ~isstr(HEADCOLOR) | ~strcmpi(HEADCOLOR,'none')
  1221. ringh= patch(headx,heady,ones(size(headx)),HEADCOLOR,'edgecolor',HEADCOLOR); hold on
  1222. end
  1223. % rx = sin(circ); rX = rx(end:-1:1);
  1224. % ry = cos(circ); rY = ry(end:-1:1);
  1225. % for k=2:2:CIRCGRID
  1226. % rx(k) = rx(k)*(1+hwidth);
  1227. % ry(k) = ry(k)*(1+hwidth);
  1228. % end
  1229. % f3= fill(hin*[rx rX],hin*[ry rY],HEADCOLOR,'edgecolor',HEADCOLOR); hold on
  1230. % f4= fill(hin*[rx rX*(1+hwidth)],hin*[ry rY*(1+hwidth)],HEADCOLOR,'edgecolor',HEADCOLOR);
  1231. % Former line-style head
  1232. % plot(cos(circ).*squeezefac*headrad,sin(circ).*squeezefac*headrad,...
  1233. % 'color',HEADCOLOR,'Linestyle','-','LineWidth',HLINEWIDTH); % plot head outline
  1234. %
  1235. %%%%%%%%%%%%%%%%%%% Plot ears and nose %%%%%%%%%%%%%%%%%%%%%%%%%%%
  1236. %
  1237. base = rmax-.0046;
  1238. basex = 0.18*rmax; % nose width
  1239. tip = 1.15*rmax;
  1240. tiphw = .04*rmax; % nose tip half width
  1241. tipr = .01*rmax; % nose tip rounding
  1242. q = .04; % ear lengthening
  1243. EarX = [.497-.005 .510 .518 .5299 .5419 .54 .547 .532 .510 .489-.005]; % rmax = 0.5
  1244. EarY = [q+.0555 q+.0775 q+.0783 q+.0746 q+.0555 -.0055 -.0932 -.1313 -.1384 -.1199];
  1245. sf = headrad/plotrad; % squeeze the model ears and nose
  1246. % by this factor
  1247. if ~isstr(HEADCOLOR) | ~strcmpi(HEADCOLOR,'none')
  1248. plot3([basex;tiphw;0;-tiphw;-basex]*sf,[base;tip-tipr;tip;tip-tipr;base]*sf,...
  1249. 2*ones(size([basex;tiphw;0;-tiphw;-basex])),...
  1250. 'Color',HEADCOLOR,'LineWidth',HLINEWIDTH); % plot nose
  1251. plot3(EarX*sf,EarY*sf,2*ones(size(EarX)),'color',HEADCOLOR,'LineWidth',HLINEWIDTH) % plot left ear
  1252. plot3(-EarX*sf,EarY*sf,2*ones(size(EarY)),'color',HEADCOLOR,'LineWidth',HLINEWIDTH) % plot right ear
  1253. end
  1254. end
  1255. %
  1256. % %%%%%%%%%%%%%%%%%%% Show electrode information %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1257. %
  1258. plotax = gca;
  1259. axis square % make plotax square
  1260. axis off
  1261. pos = get(gca,'position');
  1262. xlm = get(gca,'xlim');
  1263. ylm = get(gca,'ylim');
  1264. % textax = axes('position',pos,'xlim',xlm,'ylim',ylm); % make new axes so clicking numbers <-> labels
  1265. % will work inside head cartoon patch
  1266. % axes(textax);
  1267. axis square % make textax square
  1268. pos = get(gca,'position');
  1269. set(plotax,'position',pos);
  1270. xlm = get(gca,'xlim');
  1271. set(plotax,'xlim',xlm);
  1272. ylm = get(gca,'ylim');
  1273. set(plotax,'ylim',ylm); % copy position and axis limits again
  1274. axis equal;
  1275. set(gca, 'xlim', [-0.525 0.525]); set(plotax, 'xlim', [-0.525 0.525]);
  1276. set(gca, 'ylim', [-0.525 0.525]); set(plotax, 'ylim', [-0.525 0.525]);
  1277. %get(textax,'pos') % test if equal!
  1278. %get(plotax,'pos')
  1279. %get(textax,'xlim')
  1280. %get(plotax,'xlim')
  1281. %get(textax,'ylim')
  1282. %get(plotax,'ylim')
  1283. if isempty(EMARKERSIZE)
  1284. EMARKERSIZE = 10;
  1285. if length(y)>=160
  1286. EMARKERSIZE = 3;
  1287. elseif length(y)>=128
  1288. EMARKERSIZE = 3;
  1289. elseif length(y)>=100
  1290. EMARKERSIZE = 3;
  1291. elseif length(y)>=80
  1292. EMARKERSIZE = 4;
  1293. elseif length(y)>=64
  1294. EMARKERSIZE = 5;
  1295. elseif length(y)>=48
  1296. EMARKERSIZE = 6;
  1297. elseif length(y)>=32
  1298. EMARKERSIZE = 8;
  1299. end
  1300. end
  1301. %
  1302. %%%%%%%%%%%%%%%%%%%%%%%% Mark electrode locations only %%%%%%%%%%%%%%%%%%%%%%%%%%
  1303. %
  1304. ELECTRODE_HEIGHT = 2.1; % z value for plotting electrode information (above the surf)
  1305. if strcmp(ELECTRODES,'on') % plot electrodes as spots
  1306. if isempty(EMARKER2CHANS)
  1307. hp2 = plot3(y,x,ones(size(x))*ELECTRODE_HEIGHT,...
  1308. EMARKER,'Color',ECOLOR,'markersize',EMARKERSIZE,'linewidth',EMARKERLINEWIDTH);
  1309. else % plot markers for normal chans and EMARKER2CHANS separately
  1310. hp2 = plot3(y(mark1chans),x(mark1chans),ones(size((mark1chans)))*ELECTRODE_HEIGHT,...
  1311. EMARKER,'Color',ECOLOR,'markersize',EMARKERSIZE,'linewidth',EMARKERLINEWIDTH);
  1312. hp2b = plot3(y(mark2chans),x(mark2chans),ones(size((mark2chans)))*ELECTRODE_HEIGHT,...
  1313. EMARKER2,'Color',EMARKER2COLOR,'markerfacecolor',EMARKER2COLOR,'linewidth',EMARKER2LINEWIDTH,'markersize',EMARKERSIZE2);
  1314. end
  1315. %
  1316. %%%%%%%%%%%%%%%%%%%%%%%% Print electrode labels only %%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1317. %
  1318. elseif strcmp(ELECTRODES,'labels') % print electrode names (labels)
  1319. for i = 1:size(labels,1)
  1320. text(double(y(i)),double(x(i)),...
  1321. ELECTRODE_HEIGHT,labels(i,:),'HorizontalAlignment','center',...
  1322. 'VerticalAlignment','middle','Color',ECOLOR,...
  1323. 'FontSize',EFSIZE)
  1324. end
  1325. %
  1326. %%%%%%%%%%%%%%%%%%%%%%%% Mark electrode locations plus labels %%%%%%%%%%%%%%%%%%%
  1327. %
  1328. elseif strcmp(ELECTRODES,'labelpoint')
  1329. if isempty(EMARKER2CHANS)
  1330. hp2 = plot3(y,x,ones(size(x))*ELECTRODE_HEIGHT,...
  1331. EMARKER,'Color',ECOLOR,'markersize',EMARKERSIZE,'linewidth',EMARKERLINEWIDTH);
  1332. else
  1333. hp2 = plot3(y(mark1chans),x(mark1chans),ones(size((mark1chans)))*ELECTRODE_HEIGHT,...
  1334. EMARKER,'Color',ECOLOR,'markersize',EMARKERSIZE,'linewidth',EMARKERLINEWIDTH);
  1335. hp2b = plot3(y(mark2chans),x(mark2chans),ones(size((mark2chans)))*ELECTRODE_HEIGHT,...
  1336. EMARKER2,'Color',EMARKER2COLOR,'markerfacecolor',EMARKER2COLOR,'linewidth',EMARKER2LINEWIDTH,'markersize',EMARKERSIZE2);
  1337. end
  1338. for i = 1:size(labels,1)
  1339. hh(i) = text(double(y(i)+0.01),double(x(i)),...
  1340. ELECTRODE_HEIGHT,labels(i,:),'HorizontalAlignment','left',...
  1341. 'VerticalAlignment','middle','Color', ECOLOR,'userdata', num2str(allchansind(i)), ...
  1342. 'FontSize',EFSIZE, 'buttondownfcn', ...
  1343. ['tmpstr = get(gco, ''userdata'');'...
  1344. 'set(gco, ''userdata'', get(gco, ''string''));' ...
  1345. 'set(gco, ''string'', tmpstr); clear tmpstr;'] );
  1346. end
  1347. %
  1348. %%%%%%%%%%%%%%%%%%%%%%% Mark electrode locations plus numbers %%%%%%%%%%%%%%%%%%%
  1349. %
  1350. elseif strcmp(ELECTRODES,'numpoint')
  1351. if isempty(EMARKER2CHANS)
  1352. hp2 = plot3(y,x,ones(size(x))*ELECTRODE_HEIGHT,...
  1353. EMARKER,'Color',ECOLOR,'markersize',EMARKERSIZE,'linewidth',EMARKERLINEWIDTH);
  1354. else
  1355. hp2 = plot3(y(mark1chans),x(mark1chans),ones(size((mark1chans)))*ELECTRODE_HEIGHT,...
  1356. EMARKER,'Color',ECOLOR,'markersize',EMARKERSIZE,'linewidth',EMARKERLINEWIDTH);
  1357. hp2b = plot3(y(mark2chans),x(mark2chans),ones(size((mark2chans)))*ELECTRODE_HEIGHT,...
  1358. EMARKER2,'Color',EMARKER2COLOR,'markerfacecolor',EMARKER2COLOR,'linewidth',EMARKER2LINEWIDTH,'markersize',EMARKERSIZE2);
  1359. end
  1360. for i = 1:size(labels,1)
  1361. hh(i) = text(double(y(i)+0.01),double(x(i)),...
  1362. ELECTRODE_HEIGHT,num2str(allchansind(i)),'HorizontalAlignment','left',...
  1363. 'VerticalAlignment','middle','Color', ECOLOR,'userdata', labels(i,:) , ...
  1364. 'FontSize',EFSIZE, 'buttondownfcn', ...
  1365. ['tmpstr = get(gco, ''userdata'');'...
  1366. 'set(gco, ''userdata'', get(gco, ''string''));' ...
  1367. 'set(gco, ''string'', tmpstr); clear tmpstr;'] );
  1368. end
  1369. %
  1370. %%%%%%%%%%%%%%%%%%%%%% Print electrode numbers only %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1371. %
  1372. elseif strcmp(ELECTRODES,'numbers')
  1373. for i = 1:size(labels,1)
  1374. text(double(y(i)),double(x(i)),...
  1375. ELECTRODE_HEIGHT,int2str(allchansind(i)),'HorizontalAlignment','center',...
  1376. 'VerticalAlignment','middle','Color',ECOLOR,...
  1377. 'FontSize',EFSIZE)
  1378. end
  1379. %
  1380. %%%%%%%%%%%%%%%%%%%%%% Mark emarker2 electrodes only %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1381. %
  1382. elseif strcmp(ELECTRODES,'off') & ~isempty(EMARKER2CHANS)
  1383. hp2b = plot3(y(mark2chans),x(mark2chans),ones(size((mark2chans)))*ELECTRODE_HEIGHT,...
  1384. EMARKER2,'Color',EMARKER2COLOR,'markerfacecolor',EMARKER2COLOR,'linewidth',EMARKER2LINEWIDTH,'markersize',EMARKERSIZE2);
  1385. end
  1386. %
  1387. %%%%%%%% Mark specified electrode locations with red filled disks %%%%%%%%%%%%%%%%%%%%%%
  1388. %
  1389. try,
  1390. if strcmpi(STYLE,'blank') % if mark-selected-channel-locations mode
  1391. for kk = 1:length(1:length(x))
  1392. if Values(kk) == 3
  1393. hp2 = plot3(y(kk),x(kk),ELECTRODE_HEIGHT,EMARKER,'Color', [0 0 0], 'markersize', EMARKERSIZE1CHAN);
  1394. elseif Values(kk) == 2
  1395. hp2 = plot3(y(kk),x(kk),ELECTRODE_HEIGHT,EMARKER,'Color', [0.5 0 0], 'markersize', EMARKERSIZE1CHAN);
  1396. elseif Values(kk) == 1
  1397. hp2 = plot3(y(kk),x(kk),ELECTRODE_HEIGHT,EMARKER,'Color', [1 0 0], 'markersize', EMARKERSIZE1CHAN);
  1398. elseif strcmpi(ELECTRODES,'on')
  1399. hp2 = plot3(y(kk),x(kk),ELECTRODE_HEIGHT,EMARKER,'Color', ECOLOR, 'markersize', EMARKERSIZE);
  1400. end
  1401. end
  1402. end
  1403. catch, end;
  1404. %
  1405. %%%%%%%%%%%%%%%%%%%%%%%%%%% Plot dipole(s) on the scalp map %%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1406. %
  1407. if ~isempty(DIPOLE)
  1408. hold on;
  1409. tmp = DIPOLE;
  1410. if isstruct(DIPOLE)
  1411. if ~isfield(tmp,'posxyz')
  1412. error('dipole structure is not an EEG.dipfit.model')
  1413. end
  1414. DIPOLE = []; % Note: invert x and y from dipplot usage
  1415. DIPOLE(:,1) = -tmp.posxyz(:,2)/DIPSPHERE; % -y -> x
  1416. DIPOLE(:,2) = tmp.posxyz(:,1)/DIPSPHERE; % x -> y
  1417. DIPOLE(:,3) = -tmp.momxyz(:,2);
  1418. DIPOLE(:,4) = tmp.momxyz(:,1);
  1419. else
  1420. DIPOLE(:,1) = -tmp(:,2); % same for vector input
  1421. DIPOLE(:,2) = tmp(:,1);
  1422. DIPOLE(:,3) = -tmp(:,4);
  1423. DIPOLE(:,4) = tmp(:,3);
  1424. end;
  1425. for index = 1:size(DIPOLE,1)
  1426. if ~any(DIPOLE(index,:))
  1427. DIPOLE(index,:) = [];
  1428. end
  1429. end;
  1430. DIPOLE(:,1:4) = DIPOLE(:,1:4)*rmax*(rmax/plotrad); % scale radius from 1 -> rmax (0.5)
  1431. DIPOLE(:,3:end) = (DIPOLE(:,3:end))*rmax/100000*(rmax/plotrad);
  1432. if strcmpi(DIPNORM, 'on')
  1433. for index = 1:size(DIPOLE,1)
  1434. DIPOLE(index,3:4) = DIPOLE(index,3:4)/norm(DIPOLE(index,3:end))*0.2;
  1435. end;
  1436. end;
  1437. DIPOLE(:, 3:4) = DIPORIENT*DIPOLE(:, 3:4)*DIPLEN;
  1438. PLOT_DIPOLE=1;
  1439. if sum(DIPOLE(1,3:4).^2) <= 0.00001
  1440. if strcmpi(VERBOSE,'on')
  1441. fprintf('Note: dipole is length 0 - not plotted\n')
  1442. end
  1443. PLOT_DIPOLE = 0;
  1444. end
  1445. if 0 % sum(DIPOLE(1,1:2).^2) > plotrad
  1446. if strcmpi(VERBOSE,'on')
  1447. fprintf('Note: dipole is outside plotting area - not plotted\n')
  1448. end
  1449. PLOT_DIPOLE = 0;
  1450. end
  1451. if PLOT_DIPOLE
  1452. for index = 1:size(DIPOLE,1)
  1453. hh = plot( DIPOLE(index, 1), DIPOLE(index, 2), '.');
  1454. set(hh, 'color', DIPCOLOR, 'markersize', DIPSCALE*30);
  1455. hh = line( [DIPOLE(index, 1) DIPOLE(index, 1)+DIPOLE(index, 3)]', ...
  1456. [DIPOLE(index, 2) DIPOLE(index, 2)+DIPOLE(index, 4)]',[10 10]);
  1457. set(hh, 'color', DIPCOLOR, 'linewidth', DIPSCALE*30/7);
  1458. end;
  1459. end;
  1460. end;
  1461. end % if ~ 'gridplot'
  1462. %
  1463. %%%%%%%%%%%%% Plot axis orientation %%%%%%%%%%%%%%%%%%%%
  1464. %
  1465. if strcmpi(DRAWAXIS, 'on')
  1466. axes('position', [0 0.85 0.08 0.1]);
  1467. axis off;
  1468. coordend1 = sqrt(-1)*3;
  1469. coordend2 = -3;
  1470. coordend1 = coordend1*exp(sqrt(-1)*rotate);
  1471. coordend2 = coordend2*exp(sqrt(-1)*rotate);
  1472. line([5 5+round(real(coordend1))]', [5 5+round(imag(coordend1))]', 'color', 'k');
  1473. line([5 5+round(real(coordend2))]', [5 5+round(imag(coordend2))]', 'color', 'k');
  1474. if round(real(coordend2))<0
  1475. text( 5+round(real(coordend2))*1.2, 5+round(imag(coordend2))*1.2-2, '+Y');
  1476. else text( 5+round(real(coordend2))*1.2, 5+round(imag(coordend2))*1.2, '+Y');
  1477. end;
  1478. if round(real(coordend1))<0
  1479. text( 5+round(real(coordend1))*1.2, 5+round(imag(coordend1))*1.2+1.5, '+X');
  1480. else text( 5+round(real(coordend1))*1.2, 5+round(imag(coordend1))*1.2, '+X');
  1481. end;
  1482. set(gca, 'xlim', [0 10], 'ylim', [0 10]);
  1483. end;
  1484. %
  1485. %%%%%%%%%%%%% Set EEGLAB background color to match head border %%%%%%%%%%%%%%%%%%%%%%%%
  1486. %
  1487. try,
  1488. icadefs;
  1489. set(gcf, 'color', BACKCOLOR);
  1490. catch,
  1491. end;
  1492. hold off
  1493. axis off
  1494. % set(get(h,'children'),'hittest','off')
  1495. set(get(h,'children'),'buttonDownFcn',get(h,'buttonDownFcn'))
  1496. return