reject_ics_by_ftr() - Function for evaluating whether or not the features of an independent component are extreme enough for it be classified as an EEG artifact and removed from later analysis. IC features should have already been computed by the function reject_ics_by_feature and feature thresholds can be interatively chosen by the function set_ic_ftr_thresh.m. The following seven features thresholds are tested in the given order: 1. EEG.reject.thresh_blink_topo 2. EEG.reject.thresh_heart_topo 3. EEG.reject.thresh_he_topo 4. EEG.reject.thresh_ic_emg_spectra 5. EEG.reject.thresh_ic_xtrm_chan 6. EEG.reject.thresh_ic_mn_std 7. EEG.reject.thresh_ic_eog_spectra If an IC's features exceed any of these thresholds, it is given one of the following corresponding labels, which will mark it for rejection: 1. 'Blink (objective)' 2. 'Heart (objective)' 3. 'HE (objective)' 4. 'EMG (objective)'; 5. 'Bad_chan (objective)' 6. 'Xtrm_activity (objective)' 7. 'EOG (objective)' Once an IC has been found to exceed one threshold, no other thresholds are tested (like garv thresholds). Thus an IC can only be classified as one type of artifact. Note, if any changes are made to IC labels, the EEG variable will need to be saved to preserve those changes. Usage: >> EEG=reject_ics_by_ftr(EEG,verblevel,default_thresholds) Required Input: EEG - An EEGLAB EEG struct variable Optional Inputs: 'verblevel' - An integer specifiying the amount of information you want functions to provide about what they are doing during runtime. Options are: 0 - quiet, only show errors, warnings, and EEGLAB reports 1 - stuff anyone should probably know 2 - stuff you should know the first time you start working with a data set {default value if not already globally specified} 3 - stuff that might help you debug (show all reports) 'default_thresholds' - [1 | 0] If 1, the default thresholds below will be used and existing thresholds will be erased. If 0, existing thresholds are used. {Default: 0} EEG.reject.thresh_ic_xtrm_chan=.75; EEG.reject.thresh_ic_mn_std=27.3; EEG.reject.thresh_ic_emg_spectra=.62; EEG.reject.thresh_ic_eog_spectra=.99; EEG.reject.thresh_blink_topo=.92; EEG.reject.thresh_heart_topo=.77; EEG.reject.thresh_he_topo=.70; Output: EEG - An EEGLAB EEG struct variable. Same as input EEG but possibly with EEG.iclabels, EEG.reject.gcompreject, EEG.saved, and EEG.reject.thresh* fields changed. Global Variable: VERBLEVEL - level of verbosity (i.e., tells functions how much how much to report about what they're doing during runtime) set by the optional function argument 'verblevel' Author: David Groppe Kutaslab, 12/2009
0001 function EEG=reject_ics_by_ftr(EEG,verblevel,default_thresholds) 0002 % reject_ics_by_ftr() - Function for evaluating whether or not the features of an 0003 % independent component are extreme enough for it be classified as an EEG 0004 % artifact and removed from later analysis. IC features should have 0005 % already been computed by the function reject_ics_by_feature and feature 0006 % thresholds can be interatively chosen by the function set_ic_ftr_thresh.m. 0007 % The following seven features thresholds are tested in the given order: 0008 % 1. EEG.reject.thresh_blink_topo 0009 % 2. EEG.reject.thresh_heart_topo 0010 % 3. EEG.reject.thresh_he_topo 0011 % 4. EEG.reject.thresh_ic_emg_spectra 0012 % 5. EEG.reject.thresh_ic_xtrm_chan 0013 % 6. EEG.reject.thresh_ic_mn_std 0014 % 7. EEG.reject.thresh_ic_eog_spectra 0015 % 0016 % If an IC's features exceed any of these thresholds, it is given one of 0017 % the following corresponding labels, which will mark it for rejection: 0018 % 1. 'Blink (objective)' 0019 % 2. 'Heart (objective)' 0020 % 3. 'HE (objective)' 0021 % 4. 'EMG (objective)'; 0022 % 5. 'Bad_chan (objective)' 0023 % 6. 'Xtrm_activity (objective)' 0024 % 7. 'EOG (objective)' 0025 % 0026 % Once an IC has been found to exceed one threshold, no other thresholds 0027 % are tested (like garv thresholds). Thus an IC can only be classified as 0028 % one type of artifact. 0029 % Note, if any changes are made to IC labels, the EEG variable 0030 % will need to be saved to preserve those changes. 0031 % 0032 % Usage: 0033 % >> EEG=reject_ics_by_ftr(EEG,verblevel,default_thresholds) 0034 % 0035 % Required Input: 0036 % EEG - An EEGLAB EEG struct variable 0037 % 0038 % Optional Inputs: 0039 % 'verblevel' - An integer specifiying the amount of information you want 0040 % functions to provide about what they are doing during runtime. 0041 % Options are: 0042 % 0 - quiet, only show errors, warnings, and EEGLAB reports 0043 % 1 - stuff anyone should probably know 0044 % 2 - stuff you should know the first time you start working 0045 % with a data set {default value if not already globally 0046 % specified} 0047 % 3 - stuff that might help you debug (show all reports) 0048 % 'default_thresholds' - [1 | 0] If 1, the default thresholds below will be used and 0049 % existing thresholds will be erased. If 0, existing 0050 % thresholds are used. {Default: 0} 0051 % EEG.reject.thresh_ic_xtrm_chan=.75; 0052 % EEG.reject.thresh_ic_mn_std=27.3; 0053 % EEG.reject.thresh_ic_emg_spectra=.62; 0054 % EEG.reject.thresh_ic_eog_spectra=.99; 0055 % EEG.reject.thresh_blink_topo=.92; 0056 % EEG.reject.thresh_heart_topo=.77; 0057 % EEG.reject.thresh_he_topo=.70; 0058 % 0059 % 0060 % Output: 0061 % EEG - An EEGLAB EEG struct variable. Same as input EEG but possibly 0062 % with EEG.iclabels, EEG.reject.gcompreject, EEG.saved, and 0063 % EEG.reject.thresh* fields changed. 0064 % 0065 % 0066 % Global Variable: 0067 % VERBLEVEL - level of verbosity (i.e., tells functions how much 0068 % how much to report about what they're doing during 0069 % runtime) set by the optional function argument 'verblevel' 0070 % 0071 % 0072 % Author: 0073 % David Groppe 0074 % Kutaslab, 12/2009 0075 0076 global VERBLEVEL; 0077 if nargin==1, 0078 if isempty(VERBLEVEL), 0079 VERBLEVEL=2; 0080 end 0081 else 0082 VERBLEVEL=verblevel; 0083 end 0084 0085 if nargin<3, 0086 default_thresholds=0; 0087 end 0088 0089 0090 %check to make sure IC features are part of EEG struct 0091 fldnames=fieldnames(EEG); 0092 fnd=0; 0093 fnd_iclabels=0; 0094 for n=1:length(fldnames) 0095 if strcmpi(fldnames{n},'icfeatures'), 0096 fnd=1; 0097 end 0098 if strcmpi(fldnames{n},'iclabels'), 0099 fnd_iclabels=1; 0100 end 0101 end 0102 if ~fnd, 0103 error('EEG variable is missing field "EEG.icfeatures". Try running cmpt_ic_art_ftrs.m to compute IC features.'); 0104 end 0105 n_ic=size(EEG.icawinv,2); 0106 if ~fnd_iclabels, 0107 VerbReport('Adding field "iclabels" to "EEG" variable.',2,VERBLEVEL); 0108 EEG.iclabels{n_ic}=[]; 0109 end 0110 if length(EEG.iclabels)<n_ic, 0111 EEG.iclabels{n_ic}=[]; 0112 end 0113 0114 0115 if default_thresholds, 0116 %add defualt threshold levels 0117 EEG.reject.thresh_ic_xtrm_chan=.75; 0118 EEG.reject.thresh_ic_mn_std=27.3; 0119 EEG.reject.thresh_ic_emg_spectra=.62; 0120 EEG.reject.thresh_ic_eog_spectra=.99; 0121 EEG.reject.thresh_blink_topo=.92; 0122 EEG.reject.thresh_heart_topo=.77; 0123 EEG.reject.thresh_he_topo=.70; 0124 end 0125 0126 ftr_names{1}='blink_topo'; 0127 ftr_names{2}='heart_topo'; 0128 ftr_names{3}='he_topo'; 0129 ftr_names{4}='emg_spectra'; 0130 ftr_names{5}='xtrm_chan'; 0131 ftr_names{6}='mn_std'; 0132 ftr_names{7}='eog_spectra'; 0133 0134 art_labels{1}='Blink (objective)'; 0135 art_labels{2}='Heart (objective)'; 0136 art_labels{3}='HE (objective)'; 0137 art_labels{4}='EMG (objective)'; 0138 art_labels{5}='Bad_chan (objective)'; 0139 art_labels{6}='Xtrm_activity (objective)'; 0140 art_labels{7}='EOG (objective)'; 0141 0142 thresh_names{1}='thresh_blink_topo'; 0143 thresh_names{2}='thresh_heart_topo'; 0144 thresh_names{3}='thresh_he_topo'; 0145 thresh_names{4}='thresh_ic_emg_spectra'; 0146 thresh_names{5}='thresh_ic_xtrm_chan'; 0147 thresh_names{6}='thresh_ic_mn_std'; 0148 thresh_names{7}='thresh_ic_eog_spectra'; 0149 n_thresh=length(thresh_names); 0150 0151 % Grab IC feature thresholds and add NaN threshold if they are not there 0152 fldnames=fieldnames(EEG.reject); 0153 thresh=zeros(1,n_thresh)*NaN; 0154 for t=1:n_thresh, 0155 fnd=0; 0156 for nm=1:length(fldnames), 0157 if strcmpi(fldnames{nm},thresh_names{t}), 0158 fnd=1; 0159 cmd=['thresh(t)=EEG.reject.' thresh_names{t} ';']; 0160 eval(cmd); 0161 break; 0162 end 0163 end 0164 if ~fnd, 0165 %Add field with NaN value, thresh(t) should already be NaN 0166 cmd=['EEG.reject.' thresh_names{t} '=NaN;']; 0167 eval(cmd); 0168 end 0169 VerbReport(sprintf('Feature %s''s threshold is: %.3f',ftr_names{t},thresh(t)),2,VERBLEVEL); 0170 end 0171 0172 % For each IC, test each feature 0173 rej=zeros(1,n_ic); 0174 mod=0; 0175 for c=1:n_ic, 0176 for t=1:n_thresh, 0177 % if an IC exceeds a feature, reject it, give it an artifact label, and 0178 % break loop 0179 cmd=['bool=(EEG.icfeatures(c).' ftr_names{t} '>thresh(t));']; 0180 eval(cmd); 0181 if bool, 0182 rej(c)=1; 0183 VerbReport(sprintf('Reject IC %d, Feature: %s',c,ftr_names{t}),2,VERBLEVEL); 0184 EEG.reject.gcompreject(c)=1; %Make sure IC is labeled as artifact by EEGLAB 0185 if ~strcmpi(EEG.iclabels{c},art_labels{t}), 0186 EEG.iclabels{c}=art_labels{t}; 0187 mod=1; 0188 end 0189 break; 0190 end 0191 end 0192 if ~rej(c), 0193 if is_art(EEG.iclabels{c}), 0194 n_char=length(EEG.iclabels{c}); 0195 if n_char>=11, 0196 % if IC label ends in '(objective)' but it no longer passes 0197 % rejection criteria, undo label 0198 if strcmpi(EEG.iclabels{c}(n_char-10:n_char),'(objective)'), 0199 EEG.iclabels{c}=[]; 0200 EEG.reject.gcompreject(c)=0; 0201 mod=1; 0202 VerbReport(sprintf('IC %d''s features no longer exceed rejection criteria. It is no longer selected for rejection.',c),2,VERBLEVEL); 0203 end 0204 end 0205 end 0206 end 0207 end 0208 0209 % Make sure EEG.iclabels and EEG.reject gcompreject agree 0210 for c=1:n_ic, 0211 if is_art(EEG.iclabels{c}) && ~EEG.reject.gcompreject(c), 0212 VerbReport(sprintf('IC %d is labeled as an artifact (%s), but it is not marked as such in EEG.reject.gcompreject.', ... 0213 c,EEG.iclabels{c}),2,VERBLEVEL); 0214 VerbReport('Fixing EEG.reject.gcompreject to agree with label.',2,VERBLEVEL); 0215 EEG.reject.gcompreject(c)=1; 0216 mod=1; 0217 elseif ~is_art(EEG.iclabels{c}) && EEG.reject.gcompreject(c), 0218 VerbReport(sprintf('IC %d is not labeled as an artifact, but it is marked as such in EEG.reject.gcompreject.', ... 0219 c,EEG.iclabels{c}),2,VERBLEVEL); 0220 VerbReport('Fixing EEG.reject.gcompreject to agree with label.',2,VERBLEVEL); 0221 EEG.reject.gcompreject(c)=0; 0222 mod=1; 0223 end 0224 end 0225 0226 0227 % print warning about saving data set 0228 if mod, 0229 EEG.saved='no'; 0230 VerbReport('Changes were made to the rejection status and/or labels of ICs. You need to save the data set to preserve these changes.',2,VERBLEVEL); 0231 else 0232 VerbReport('No changes were made to the rejection status or labels of any ICs.',2,VERBLEVEL); 0233 end