spatial_neighbors() - Given a set of electrode coordinates, this function returns a binary 2D matrix that indicates which electrodes are close enough to be considered neighbors. For use with cluster-based permutation tests. Usage: >>chan_hood=spatial_neighbors(chanlocs,max_dist); Required Inputs: chanlocs - An EEGLAB chanlocs structure (e.g., EEG.chanlocs from an EEG variable) max_dist - All electrodes within max_dist of another electrode are considered spatial neighbors. Max_dist is in whatever units your EEGLAB chanlocs coordinates are in. If your chanlocs coordingates are on an idealized sphere with unit radius then you can convert max_dist into centimeters by measuring the circumference of a participant's head in centimeters and using the following formulas: radius=circumference/(2*pi); radius*max_dist=max_dist in units of cm Optional Inputs: head_radius - The radius of the head in whatever units the Cartesian coordinates in chanlocs are in. This is used to convert scalar values of chan_hood into centimeters. {default: estimated from chanlocs by assuming center of head is at 0,0,0} Outputs: chan_hood - A symmetric binary matrix indicating which channels are neighbors. If chan_hood(a,b)=1, then Channel A and Channel B are nieghbors. Notes: -This function outputs an estimate of max_dist (in cm) on the command line by assuming a circumference of 56 cm and EEGLAB chanloc coordinates based on a spherical head with unit radius. It also summarizes the number of neighbors per channel using basic measures of central tendency and dispersion. -You will have more statistical power to detect effects at electrodes that have more neighbors. Thus you may have significantly less power to detect effects on the edge of the montage. Thanks to Manish Saggar for bringing this to my attention. Author: David Groppe Kutaslab, 5/2011
0001 % spatial_neighbors() - Given a set of electrode coordinates, this function 0002 % returns a binary 2D matrix that indicates which 0003 % electrodes are close enough to be considered 0004 % neighbors. For use with cluster-based permutation 0005 % tests. 0006 % 0007 % Usage: 0008 % >>chan_hood=spatial_neighbors(chanlocs,max_dist); 0009 % 0010 % Required Inputs: 0011 % chanlocs - An EEGLAB chanlocs structure (e.g., EEG.chanlocs from an EEG 0012 % variable) 0013 % max_dist - All electrodes within max_dist of another electrode are 0014 % considered spatial neighbors. Max_dist is in whatever units 0015 % your EEGLAB chanlocs coordinates are in. If your chanlocs 0016 % coordingates are on an idealized sphere with unit radius 0017 % then you can convert max_dist into centimeters by measuring 0018 % the circumference of a participant's head in centimeters and 0019 % using the following formulas: 0020 % radius=circumference/(2*pi); 0021 % radius*max_dist=max_dist in units of cm 0022 % 0023 % Optional Inputs: 0024 % head_radius - The radius of the head in whatever units the Cartesian 0025 % coordinates in chanlocs are in. This is used to 0026 % convert scalar values of chan_hood into centimeters. 0027 % {default: estimated from chanlocs by assuming center of 0028 % head is at 0,0,0} 0029 % 0030 % Outputs: 0031 % chan_hood - A symmetric binary matrix indicating which channels are 0032 % neighbors. If chan_hood(a,b)=1, then Channel A and Channel 0033 % B are nieghbors. 0034 % 0035 % Notes: 0036 % -This function outputs an estimate of max_dist (in cm) on the command line 0037 % by assuming a circumference of 56 cm and EEGLAB chanloc coordinates based 0038 % on a spherical head with unit radius. It also summarizes the number of 0039 % neighbors per channel using basic measures of central tendency and 0040 % dispersion. 0041 % -You will have more statistical power to detect effects at electrodes 0042 % that have more neighbors. Thus you may have significantly less power to 0043 % detect effects on the edge of the montage. Thanks to Manish Saggar for 0044 % bringing this to my attention. 0045 % 0046 % Author: 0047 % David Groppe 0048 % Kutaslab, 5/2011 0049 0050 %%%%% Future Work %%%%%% 0051 % -Perhaps allow max_dist to be specified in centimeters 0052 0053 function chan_hood=spatial_neighbors(chanlocs,max_dist,head_radius) 0054 0055 n_chan=length(chanlocs); 0056 0057 if nargin<3, 0058 head_radius=[]; 0059 end 0060 0061 if isempty(head_radius) 0062 fprintf('Estimating the radius of the head by assuming that the center of the head is [0,0,0] in Cartesian coordinates.\n'); 0063 dst_from_origin=zeros(1,n_chan); 0064 for a=1:n_chan, 0065 dst_from_origin(a)=sqrt(sum([chanlocs(a).X chanlocs(a).Y chanlocs(a).Z].^2)); 0066 end 0067 mn=min(dst_from_origin); 0068 mx=max(dst_from_origin); 0069 md=median(dst_from_origin); 0070 fprintf('Min/Max electrode distance from origin (in chanlocs units): %f/%f\n',mn,mx); 0071 uni=unique(dst_from_origin); 0072 if ((mx-mn)/md)>.001, 0073 fprintf('WARNING: It appears that all electrodes are NOT the same distance from the origin!!!\n'); 0074 fprintf('Your electrodes'' Cartesian coordinates either are not spherical or are not centered on [0 0 0].\n'); 0075 fprintf('This function will still work properly but its estimate of the radius of the head of will not be correct.\n'); 0076 end 0077 head_radius=median(dst_from_origin); 0078 fprintf('Radius of head (in chanlocs units) is estimated to be %f\n',head_radius); 0079 else 0080 fprintf('Using provided head radius of %f (in chanlocs units)\n',head_radius); 0081 end 0082 0083 circumference=56; %very rough estimate based on the average circumference of 10 Kutaslab participants 0084 max_dist_cm=max_dist*circumference/(2*pi*head_radius); % Radius=Circumference/(2*pi) 0085 0086 fprintf('max_dist value of %g corresponds to an approximate distance of %.2f cm (assuming\n',max_dist,max_dist_cm); 0087 fprintf(' a 56 cm great circle circumference head and that your electrode coordinates are based on an idealized\n'); 0088 fprintf(' spherical head with radius of %f).\n',head_radius); 0089 0090 chan_hood=zeros(n_chan,n_chan); 0091 n_neighbors=zeros(1,n_chan); 0092 chan_dist=zeros(1,n_chan*(n_chan-1)/2); 0093 ct=0; 0094 for c=1:n_chan, 0095 coordA=[chanlocs(c).X chanlocs(c).Y chanlocs(c).Z]; 0096 for d=c:n_chan, 0097 coordB=[chanlocs(d).X chanlocs(d).Y chanlocs(d).Z]; 0098 dstnce=sqrt(sum((coordA-coordB).^2)); 0099 if dstnce<=max_dist, 0100 chan_hood(c,d)=1; 0101 chan_hood(d,c)=1; 0102 end 0103 0104 if c~=d 0105 %don't count channels with themselves 0106 ct=ct+1; 0107 chan_dist(ct)=dstnce; 0108 end 0109 end 0110 n_neighbors(c)=sum(chan_hood(c,:))-1; 0111 end 0112 0113 fprintf('Min/Max distances between all pairs of channels (in chanlocs units): %f/%f\n', ... 0114 min(chan_dist),max(chan_dist)); 0115 fprintf('Median (semi-IQR) distance between all pairs of channels (in chanlocs units): %f (%f)\n', ... 0116 median(chan_dist),iqr(chan_dist)/2); 0117 fprintf('Mean (SD) # of neighbors per channel: %.1f (%.1f)\n',mean(n_neighbors), ... 0118 std(n_neighbors)); 0119 fprintf('Median (semi-IQR) # of neighbors per channel: %.1f (%.1f)\n',median(n_neighbors), ... 0120 iqr(n_neighbors)/2); 0121 fprintf('Min/max # of neighbors per channel: %d to %d\n',min(n_neighbors), ... 0122 max(n_neighbors));