Home > bioelectromagnetism > eeg_bad_channels.m

eeg_bad_channels

PURPOSE ^

eeg_bad_channels - Calculate various indices of bad voltage channels

SYNOPSIS ^

function [p] = eeg_bad_channels(p,plot)

DESCRIPTION ^

 eeg_bad_channels - Calculate various indices of bad voltage channels

 Useage: [p] = eeg_bad_channels(p,plot)
 
 Returns OK channel index in p.elec.data.OK (Nelec,1)
 
 Inputs are the eeg_toolbox p struct and a boolean 'plot'
 command to generate various plots.
 
 Some of the calculations require the variance of the
 ERP potential.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [p] = eeg_bad_channels(p,plot)
0002 
0003 % eeg_bad_channels - Calculate various indices of bad voltage channels
0004 %
0005 % Useage: [p] = eeg_bad_channels(p,plot)
0006 %
0007 % Returns OK channel index in p.elec.data.OK (Nelec,1)
0008 %
0009 % Inputs are the eeg_toolbox p struct and a boolean 'plot'
0010 % command to generate various plots.
0011 %
0012 % Some of the calculations require the variance of the
0013 % ERP potential.
0014 %
0015 %
0016 
0017 % $Revision: 1.1 $ $Date: 2004/11/12 01:32:32 $
0018 
0019 % Licence:  GNU GPL, no express or implied warranties
0020 % History:  07/2000, Darren.Weber_at_radiology.ucsf.edu
0021 %           04/2001, Darren.Weber_at_radiology.ucsf.edu
0022 %           -   modified inputs to p struct
0023 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0024 
0025 % default initialisations
0026 if ~exist('plot', 'var'), plot = 0; end
0027 
0028 if ~exist('p','var'),
0029    [p] = eeg_toolbox_defaults('create');
0030 end
0031 if isempty(p.elec.data),
0032    [p] = elec_open(p);
0033 end
0034 if isempty(p.volt.data),
0035    [p] = eeg_open(p);
0036 end
0037 
0038 % Initialise bad_channels array
0039 bad_channels = zeros(1,size(p.elec.data,1));
0040 
0041 elec = str2num(char(p.elec.data.label))';
0042 X = p.elec.data.x;
0043 Y = p.elec.data.y;
0044 Z = p.elec.data.z;
0045 n_elec = length(X);
0046 
0047 % Open output results text file
0048 [path,name,ext] = fileparts(strcat(p.volt.path, filesep, p.volt.file));
0049 outputfile = fullfile(path,strcat(name, '.', 'volt.bad'));
0050 FID = fopen(outputfile,'w');
0051 
0052 
0053 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0054 % VARIANCE
0055 % report max variance > 40 and mean variance >< (mean +/- SD mean_var)
0056 
0057 if ~isempty(p.volt.var),
0058     
0059     max_var = max(p.volt.var);
0060     extreme_maxvar = or((max_var < 1),(max_var > 40));
0061     
0062     meanvar = mean(p.volt.var);
0063     Xmeanvar = ones(size(meanvar)) .* mean(meanvar);
0064     SDmeanvar = ones(size(meanvar)) .* std(meanvar);
0065     Critmeanvar = (2 .* SDmeanvar) + Xmeanvar;
0066     extreme_meanvar = meanvar > Critmeanvar;
0067     
0068     fprintf ('\nExtreme max variance (< 1 or > 40) or mean variance (Mean + 2*StDev):\n\n');
0069     fprintf (FID,'\nExtreme max variance (< 1 or > 40) or mean variance (Mean + 2*StDev):\n\n');
0070     
0071     extreme_var = or( extreme_maxvar, extreme_meanvar );
0072     bad_channels = bad_channels + extreme_var;
0073     
0074     out = [elec(extreme_var); maxvar(extreme_var); meanvar(extreme_var)];
0075     fprintf ('elec     max    mean\n',out);
0076     fprintf ('%4d  %6.2f  %6.2f\n',out);
0077     fprintf (FID,'elec     max    mean\n',out);
0078     fprintf (FID,'%4d  %6.2f  %6.2f\n', out);
0079     
0080     if plot,
0081         figure('name','Extreme Mean Variance'); hold on
0082         plot(meanvar,'g');
0083         plot(Xmeanvar,'b');
0084         plot(Critmeanvar,'r');
0085     end
0086 else
0087     fprintf('EEG_BAD_CHANNELS: p.volt.var is empty.\n');
0088     extreme_var = zeros(1,n_elec);
0089 end
0090 
0091 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0092 % DRIFT
0093 % linear fit >> 0.0   &mean_volt_outlyers = mean(volt_outlyers');&   >= ???? xSD from mean linear fit of all elecs
0094 
0095 p = eeg_linfit(p);
0096 
0097 slope = p.volt.fitslope(1,:);
0098 
0099 mean_slope = mean(slope);
0100 std_slope = std(slope);
0101 excess_slope = or( (slope > (mean_slope + 3 * std_slope)),(slope < (mean_slope - 3 * std_slope)));
0102 
0103 %mean_int = mean(intercept);
0104 %std_int = std(intercept);
0105 %excess_intercept = or( (intercept > (mean_int + 3 * std_int)),(intercept < (mean_int - 3 * std_int)) );
0106 %poor_fit = or(excess_slope, excess_intercept);
0107 
0108 poor_fit = excess_slope;
0109 bad_channels = bad_channels + poor_fit;
0110 
0111 fprintf ('\nChannels with poor linear fit:\n\n');
0112 fprintf (FID,'\nChannels with poor linear fit:\n\n');
0113 
0114 fprintf ('mean slope = %10.4f\n\n', mean_slope);
0115 fprintf (FID,'mean slope = %10.4f\n\n', mean_slope);
0116 %fprintf ('mean intercept = %6.2f\n', mean_int);
0117 %fprintf (FID,'mean intercept = %6.2f\n', mean_int);
0118 
0119 out = [elec(poor_fit);slope(poor_fit)]; %intercept(poor_fit)];
0120 fprintf ('elec   slope\n',out);
0121 fprintf ('%4d  %10.4f\n',out);
0122 fprintf (FID,'elec   slope\n',out);
0123 fprintf (FID,'%4d  %10.4f\n', out);
0124 
0125 
0126 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0127 % CORRELATIONS & VOLTAGE VARIANCE
0128 % calculates mean correlation of elec with surrounding elecs
0129 % excludes elecs with extreme variance in surround elecs correlations
0130 
0131 % identity matrix of electrode (column) correlations
0132 COR = corrcoef(p.volt.data);
0133 
0134 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0135 % Find nearest neighbour electrodes, excluding PAN and centroid/ref
0136 % Calculate inter-electrode distances & nearest neighbour electrodes
0137 % Would be nice to use the dsearchn function, but it only returns
0138 % one nearest neighbour, rather than N neighbours.
0139 
0140 % Check if distance file already calculated (speedy option)
0141 [path,name,ext] = fileparts(strcat(p.elec.path, filesep, p.elec.file));
0142 distances_file = fullfile(path,strcat(name,'.dist.mat'));
0143 if exist(distances_file) == 2,
0144     load(distances_file);
0145 else
0146     [dist_e, dist_d] = elec_distance(elec',X,Y,Z);
0147     clear X Y Z;
0148     save(distances_file,'dist_e','dist_d');
0149 end
0150 
0151 % obtain nearest neighbour electrode labels (numbers), in NN_e
0152 [NN_e, NN_d] = elec_distance_nn(dist_e, dist_d);
0153 clear dist_e dist_d NN_d;
0154 
0155 % remove first column of NN_e because each electrodes nearest neighbour is itself.
0156 NN_e = NN_e(:,2:end);
0157 
0158 correlation = zeros(6,n_elec); % initialise nearest neighbour correlations
0159 
0160 for e = 1:n_elec
0161     nn = 0;
0162     good_nn = 0;
0163     while good_nn < 6     % Get 6 good nearest neighbour correlations
0164         nn = nn + 1;
0165         nn_elec = NN_e(e,nn);              % get nn elec number
0166         [t,r] = strtok(char(nn_elec),','); % parse nn_elec and get
0167         nn_elec = str2num(r(2:end));       % value of nn_elec as number
0168         
0169         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0170         % check nn_elec is "good" so far => avoid contaminating good
0171         % channels with correlations from bad channels
0172         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0173         
0174         if extreme_var(nn_elec) == 0
0175             good_nn = good_nn + 1;
0176             correlation(good_nn,e) = COR(nn_elec, e);
0177         end
0178     end
0179 end
0180 
0181 fprintf ('\nChannels with correlations < 0.65 :\n\n');
0182 fprintf (FID,'\nChannels with correlations < 0.65 :\n\n');
0183 
0184 mean_corr = mean(abs(correlation));
0185 
0186 neg_cor = mean_corr < 0;
0187 small_cor = mean_corr < 0.65;       % 0.65 is reasonable correlation
0188 bad_cor = or(neg_cor, small_cor);
0189 
0190 bad_channels = bad_channels + bad_cor;
0191 
0192 out = [ elec(bad_cor); mean_corr(bad_cor) ];
0193 fprintf ('elec  correlation\n');
0194 fprintf ('%4d  %11.2f\n', out);
0195 fprintf (FID,'elec  correlation\n');
0196 fprintf (FID,'%4d  %11.2f\n', out);
0197 
0198 
0199 
0200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0201 % ALL BAD CHANNELS
0202 
0203 p.elec.data.OK = (bad_channels == 0)';
0204 
0205 fprintf ('\n\nAll Bad Channels :\n\n');
0206 fprintf (FID,'\n\nAll Bad Channels :\n\n');
0207 
0208 fprintf('%4d', elec(bad_channels > 0));
0209 fprintf(FID,'%4d', elec(bad_channels > 0));
0210 
0211 fprintf ('\n\n');
0212 fprintf (FID,'\n\n');
0213 
0214 % Plot voltage/variance data
0215 if plot,
0216     time = p.volt.timeArray(:,1);
0217     figure('name','All Voltage');
0218     plot(time,p.volt.data);
0219     figure('name','Bad Voltage');
0220     plot(time,p.volt.data(:,(bad_channels > 0)) );
0221     figure('name','OK Voltage');
0222     plot(time,p.volt.data(:,(bad_channels == 0)));
0223     
0224     if ~isempty(p.volt.var),
0225         figure('name','All Variance');
0226         plot(time,p.volt.var);
0227         figure('name','Bad Variance');
0228         plot(time,p.volt.var(:, (bad_channels > 0)) );
0229         figure('name','OK Variance');
0230         plot(time,p.volt.var(:, (bad_channels == 0)));
0231     end
0232 end
0233 
0234 fclose('all');
0235 return

Generated on Mon 15-Aug-2005 15:36:19 by m2html © 2003