bin_info2EEG() - Adds "bin" information to an EEGLAB EEG variable based on a "bin list file," a text file that indicates which types of events belong to which bins. See the help comments for the function read_bin_list_file.m for information on how to create a bin list file. Note, the EEG variable can contain epoched OR continuous data. Usage: >> EEG=bin_info2EEG(EEG_or_fname,blf_fname,save_fname,verblevel); Required Inputs: EEG_or_fname - EEGLAB EEG struct variable containing epochs of EEG data (i.e., not continuous EEG) or the filename of a set file that contains such an EEG struct variable. blf_fname - [string] The filename of the bin list file. Be sure to include the file's path if the file is not in the current working directory. Optional Inputs: save_fname - The filename with which you want to save the EEG variable after the bin information has been added. If not specified, the EEG variable will not be saved to disk (it will simply be returned as the output of the function). {default: not specified} verblevel - An integer specifiying the amount of information you want this function to provide about what it is 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 globally specified} 3 - stuff that might help you debug (show all reports) Output: EEG - EEGLAB EEG struct variable with bin information added. More specifically, there will be (1) an EEG.bindesc field that contains a text description of each bin, (2) events of bin types (e.g., 'bin1') will be added to the field EEG.event, and (3) if the data are epoched, bin types will be stored in EEG.epoch(#).eventtype. Global Variable: VERBLEVEL - Mass Univariate ERP Toolbox level of verbosity (i.e., tells functions how much to report about what they're doing during runtime) set by the optional function argument 'verblevel' Notes: -If bin information has already been added to an EEG variable, this function cannot add to it or overwrite it. You need to remove it and then call this function. -This function is not yet compatible with ERPLAB's conventions for storing bin information. -EEG.urevent field is not modified by this function. Thus "bin" events only are recorded in EEG.event and EEG.epoch fields. Author: David Groppe Kutaslab, 9/2010
0001 % bin_info2EEG() - Adds "bin" information to an EEGLAB EEG variable based on 0002 % a "bin list file," a text file that indicates which types 0003 % of events belong to which bins. See the help comments 0004 % for the function read_bin_list_file.m for information on 0005 % how to create a bin list file. Note, the EEG variable 0006 % can contain epoched OR continuous data. 0007 % 0008 % Usage: 0009 % >> EEG=bin_info2EEG(EEG_or_fname,blf_fname,save_fname,verblevel); 0010 % 0011 % 0012 % Required Inputs: 0013 % EEG_or_fname - EEGLAB EEG struct variable containing epochs of EEG data 0014 % (i.e., not continuous EEG) or the filename of a set file 0015 % that contains such an EEG struct variable. 0016 % 0017 % blf_fname - [string] The filename of the bin list file. Be sure to 0018 % include the file's path if the file is not in the current 0019 % working directory. 0020 % 0021 % Optional Inputs: 0022 % save_fname - The filename with which you want to save the EEG 0023 % variable after the bin information has been added. If 0024 % not specified, the EEG variable will not be saved to 0025 % disk (it will simply be returned as the output of the 0026 % function). {default: not specified} 0027 % verblevel - An integer specifiying the amount of information you want 0028 % this function to provide about what it is doing during runtime. 0029 % Options are: 0030 % 0 - quiet, only show errors, warnings, and EEGLAB reports 0031 % 1 - stuff anyone should probably know 0032 % 2 - stuff you should know the first time you start working 0033 % with a data set {default value if not globally specified} 0034 % 3 - stuff that might help you debug (show all 0035 % reports) 0036 % 0037 % Output: 0038 % EEG - EEGLAB EEG struct variable with bin information added. 0039 % More specifically, there will be (1) an EEG.bindesc 0040 % field that contains a text description of each bin, (2) 0041 % events of bin types (e.g., 'bin1') will be added to the field 0042 % EEG.event, and (3) if the data are epoched, bin types will 0043 % be stored in EEG.epoch(#).eventtype. 0044 % 0045 % Global Variable: 0046 % VERBLEVEL - Mass Univariate ERP Toolbox level of verbosity (i.e., tells 0047 % functions how much to report about what they're doing during 0048 % runtime) set by the optional function argument 'verblevel' 0049 % 0050 % Notes: 0051 % -If bin information has already been added to an EEG variable, this 0052 % function cannot add to it or overwrite it. You need to remove it and 0053 % then call this function. 0054 % 0055 % -This function is not yet compatible with ERPLAB's conventions for 0056 % storing bin information. 0057 % 0058 % -EEG.urevent field is not modified by this function. Thus "bin" events 0059 % only are recorded in EEG.event and EEG.epoch fields. 0060 % 0061 % Author: 0062 % David Groppe 0063 % Kutaslab, 9/2010 0064 0065 %%%%%%%%%%%%%%%% Revision History %%%%%%%%%%%%%%%%% 0066 % 12/10/2010-Now works on continuous data. 0067 % 0068 % 4/13/2011-Now works on EEG variables that don't have 0069 % EEG.event(x).duration fields 0070 % 0071 % 9/5/2011-New 'bin*' elements of EEG.events had the wrong bin #. Also, the 0072 % code wouldn't work if EEG.epoch(#).eventtype was numeric. These 0073 % problems have been fixed. Thanks to Haibo "Seapsy" Zhou for finding these 0074 % problems and their solutions. 0075 % 0076 % 6/25/2012-Function crashed or could copy over incorrect EEG.epoch info 0077 % (e.g. EEG.epoch(x).latency) when run on epoched data with more than one 0078 % event per epoch. Thanks to Clemens Maidhof for alerting me to this. 0079 % 0080 0081 0082 %%%%%%%%%%%%%%%% Future Work %%%%%%%%%%%%%%%%% 0083 %-Make compatible with ERPLAB 0084 0085 function EEG=bin_info2EEG(EEG_or_fname,blf_fname,save_fname,verblevel) 0086 0087 global VERBLEVEL; 0088 0089 if nargin<3 0090 save_fname=[]; 0091 end 0092 0093 if nargin<4, 0094 if isempty(VERBLEVEL), 0095 VERBLEVEL=2; 0096 end 0097 else 0098 VERBLEVEL=verblevel; 0099 end 0100 0101 if ischar(EEG_or_fname), 0102 EEG=pop_loadset(EEG_or_fname); 0103 else 0104 EEG=EEG_or_fname; 0105 clear EEG_or_fname; 0106 end 0107 0108 %Are data epoched or continuous? 0109 if length(size(EEG.data))==2 0110 continuous=1; 0111 else 0112 continuous=0; 0113 n_ep=length(EEG.epoch); 0114 end 0115 n_ev=length(EEG.event); 0116 0117 %Check for bin_information. If found, warn that it needs to be erased 0118 if isfield(EEG,'bindesc'), 0119 error('This EEG variable already has bin information added to it (i.e., there is a ''bindesc'' field). You need to remove it before using this function.'); 0120 else 0121 if continuous, 0122 for a=1:n_ev, 0123 if strcmpi(EEG.event(a).type(1:3),'bin'), 0124 error('This EEG variable already has bin information added to it (i.e., Event #%d is of type ''%s''). You need to remove it before using this function.', ... 0125 a,EEG.event(a).type); 0126 end 0127 end 0128 else 0129 for a=1:n_ep, 0130 if iscell(EEG.epoch(a).eventtype), 0131 n_type=length(EEG.epoch(a).eventtype); 0132 else 0133 %if only one event per epoch, a string is used instead 0134 %of a cell array 0135 n_type=1; 0136 end 0137 0138 for b=1:n_type, 0139 if n_type>1 0140 if (length(EEG.epoch(a).eventtype{b})>3) && strcmpi(EEG.epoch(a).eventtype{b}(1:3),'bin'), 0141 error('This EEG variable already has bin information added to it (i.e., Epoch #%d has a type of ''%s''). You need to remove it before using this function.', ... 0142 a,EEG.epoch(a).eventtype{b}); 0143 end 0144 else 0145 if (length(EEG.epoch(a).eventtype)>3) && strcmpi(EEG.epoch(a).eventtype(1:3),'bin'), 0146 error('This EEG variable already has bin information added to it (i.e., Epoch #%d has a type of ''%s''). You need to remove it before using this function.', ... 0147 a,EEG.epoch(a).eventtype); 0148 end 0149 end 0150 end 0151 end 0152 end 0153 end 0154 0155 %% Read bin information from bin list file (a text file) 0156 [bindesc, bintype]=read_bin_list_file(blf_fname,VERBLEVEL); 0157 EEG.bindesc=bindesc; 0158 n_bin=length(bindesc); 0159 0160 bin_ct=zeros(1,n_bin); 0161 0162 %% Add bin information 0163 if continuous, 0164 ev_ct=n_ev; 0165 for a=1:n_ev, 0166 for bin=1:n_bin, 0167 if ismember(EEG.event(a).type,bintype{bin}) 0168 ev_ct=ev_ct+1; 0169 EEG.event(ev_ct).latency=EEG.event(a).latency; 0170 if isfield(EEG.event(a),'duration'), 0171 %EEGLAB apparently doesn't always add a duration field 0172 EEG.event(ev_ct).duration=EEG.event(a).duration; 0173 end 0174 EEG.event(ev_ct).type=['bin' int2str(bin)]; 0175 EEG.event(ev_ct).urevent=EEG.event(a).urevent; 0176 0177 %update bin counter 0178 bin_ct(bin)=bin_ct(bin)+1; 0179 end 0180 end 0181 end 0182 else 0183 %epoched data 0184 0185 % If the EEG.epoch field contains numeric values, change them to 0186 % strings since the rest of the code expects this field to contain only 0187 % strings. 0188 num2str_flag=0; 0189 for a=1:n_ep 0190 if isnumeric(EEG.epoch(a).eventtype) 0191 temp=EEG.epoch(a).eventtype; 0192 EEG.epoch(a).eventtype=[]; 0193 for b=1:length(temp) 0194 num2str_flag=1; 0195 EEG.epoch(a).eventtype{b}=num2str(temp(b)); 0196 end 0197 end 0198 end 0199 if num2str_flag, 0200 if VERBLEVEL>=1, 0201 fprintf('EEG.epoch(#).eventtype field contained numeric values. These have been changed to strings.'); 0202 end 0203 end 0204 0205 add_ev_ct=0; 0206 for a=1:n_ep, 0207 if iscell(EEG.epoch(a).eventtype), 0208 add_ct=0; 0209 n_ep_type=length(EEG.epoch(a).eventtype); 0210 for bin=1:n_bin, 0211 if ismember(EEG.epoch(a).eventtype,bintype{bin}) 0212 %convert non cell array fields of EEG.epoch(1) into 0213 %cell arrays 0214 0215 % Note: EEG.epoch(a).event stays a vector even when 0216 % multiple events are present in an epoch 0217 0218 %Some versions of EEGLAB apparently don't have the 0219 %eventduration field or don't create it automatically 0220 if isfield(EEG.epoch(a),'eventduration') 0221 evdurflag=1; 0222 if ~iscell(EEG.epoch(a).eventduration) 0223 temp=EEG.epoch(a).eventduration; %EEG.eventduration 0224 EEG.epoch(a).eventduration=cell(1,1); 0225 EEG.epoch(a).eventduration{1}=temp; 0226 end 0227 else 0228 evdurflag=0; 0229 end 0230 0231 if ~iscell(EEG.epoch(a).eventlatency) 0232 temp=EEG.epoch(a).eventlatency; %EEG.eventlatency 0233 EEG.epoch(a).eventlatency=cell(1,1); 0234 EEG.epoch(a).eventlatency{1}=temp; 0235 end 0236 0237 if ~iscell(EEG.epoch(a).eventtype) 0238 temp=EEG.epoch(a).eventtype; %EEG.eventtype 0239 EEG.epoch(a).eventtype=cell(1,1); 0240 EEG.epoch(a).eventtype{1}=temp; 0241 end 0242 0243 if ~iscell(EEG.epoch(a).eventurevent) 0244 temp=EEG.epoch(a).eventurevent; %EEG.eventurevent 0245 EEG.epoch(a).eventurevent=cell(1,1); 0246 EEG.epoch(a).eventurevent{1}=temp; 0247 end 0248 0249 % I am not sure why the block of code below was ever 0250 % added. It appears redundant with block of code below 0251 % it. Am just commenting it out for time being. 0252 0253 %Add bin info to EEG.epoch 0254 % add_ct=add_ct+1; 0255 % add_ev_ct=add_ev_ct+1; 0256 % EEG.epoch(a).eventtype{add_ct+n_ep_type}=['bin' num2str(bin)]; 0257 % %Duplicate other information about event 0258 % if evdurflag, 0259 % EEG.epoch(a).eventduration{add_ct+n_ep_type}=EEG.epoch(a).eventduration{b}; 0260 % end 0261 % EEG.epoch(a).eventlatency{add_ct+n_ep_type}=EEG.epoch(a).eventlatency{b}; 0262 % EEG.epoch(a).event(add_ct+n_ep_type)=n_ev+add_ev_ct; 0263 % EEG.epoch(a).eventurevent{add_ct+n_ep_type}=EEG.epoch(a).eventurevent{b}; 0264 % 0265 % source_ev_id=EEG.epoch(a).event(b); 0266 % %Note, it looks like EEGLAB adds an event for a urevent everytime it occurs in an epoch 0267 % 0268 % %Add bin info to EEG.event 0269 % EEG.event(n_ev+add_ev_ct).type=['bin' num2str(bin)]; 0270 % EEG.event(n_ev+add_ev_ct).latency=EEG.event(source_ev_id).latency; 0271 % if isfield(EEG.event(source_ev_id),'duration') 0272 % %EEGLAB apparently doesn't always create this field 0273 % EEG.event(n_ev+add_ev_ct).duration=EEG.event(source_ev_id).duration; 0274 % end 0275 % EEG.event(n_ev+add_ev_ct).urevent=EEG.event(source_ev_id).urevent; 0276 % EEG.event(n_ev+add_ev_ct).epoch=a; 0277 % 0278 % if ~EEG.epoch(a).eventlatency{b} 0279 % %only update bin counter if the time locking event 0280 % %falls in the current bin 0281 % bin_ct(bin)=bin_ct(bin)+1; 0282 % end 0283 end 0284 end 0285 else 0286 %if only one event per epoch, a string is used instead 0287 %of a cell array 0288 n_ep_type=1; 0289 end 0290 0291 add_ct=0; 0292 for b=1:n_ep_type, 0293 for bin=1:n_bin, 0294 if n_ep_type>1, 0295 if ismember(EEG.epoch(a).eventtype{b},bintype{bin}) 0296 %Add bin info to EEG.epoch 0297 add_ct=add_ct+1; 0298 add_ev_ct=add_ev_ct+1; 0299 EEG.epoch(a).eventtype{add_ct+n_ep_type}=['bin' num2str(bin)]; 0300 %Duplicate other information about the event 0301 if isfield(EEG.epoch(a),'eventduration') 0302 %Some versions of EEGLAB apparently don't have the 0303 %eventduration field or don't automatically 0304 %add it 0305 EEG.epoch(a).eventduration{add_ct+n_ep_type}=EEG.epoch(a).eventduration{b}; 0306 end 0307 EEG.epoch(a).eventlatency{add_ct+n_ep_type}=EEG.epoch(a).eventlatency{b}; 0308 EEG.epoch(a).event(add_ct+n_ep_type)=n_ev+add_ev_ct; 0309 EEG.epoch(a).eventurevent{add_ct+n_ep_type}=EEG.epoch(a).eventurevent{b}; 0310 0311 source_ev_id=EEG.epoch(a).event(b); 0312 %Note, it looks like EEGLAB adds an event for a urevent everytime it occurs in an epoch 0313 0314 %Add bin info to EEG.event 0315 EEG.event(n_ev+add_ev_ct).type=['bin' num2str(bin)]; 0316 EEG.event(n_ev+add_ev_ct).latency=EEG.event(source_ev_id).latency; 0317 if isfield(EEG.event(source_ev_id),'duration'), 0318 EEG.event(n_ev+add_ev_ct).duration=EEG.event(source_ev_id).duration; 0319 end 0320 EEG.event(n_ev+add_ev_ct).urevent=EEG.event(source_ev_id).urevent; 0321 EEG.event(n_ev+add_ev_ct).epoch=a; 0322 0323 0324 if ~EEG.epoch(a).eventlatency{b} 0325 %only update bin counter if the time locking event 0326 %falls in the current bin 0327 bin_ct(bin)=bin_ct(bin)+1; 0328 end 0329 end 0330 else 0331 if ismember(EEG.epoch(a).eventtype,bintype{bin}) 0332 %convert non cell array fields of EEG.epoch(1) into 0333 %cell arrays 0334 0335 % Note: EEG.epoch(a).event stays a vector even when 0336 % multiple events are present in an epoch 0337 0338 if isfield(EEG.epoch(a),'eventduration') 0339 %Older versions of EEGLAB apparently don't have the 0340 %eventduration field 0341 evdurflag=1; 0342 if ~iscell(EEG.epoch(a).eventduration) 0343 temp=EEG.epoch(a).eventduration; %EEG.eventduration 0344 EEG.epoch(a).eventduration=cell(1,1); 0345 EEG.epoch(a).eventduration{1}=temp; 0346 end 0347 else 0348 evdurflag=0; 0349 end 0350 0351 if ~iscell(EEG.epoch(a).eventlatency) 0352 temp=EEG.epoch(a).eventlatency; %EEG.eventlatency 0353 EEG.epoch(a).eventlatency=cell(1,1); 0354 EEG.epoch(a).eventlatency{1}=temp; 0355 end 0356 0357 if ~iscell(EEG.epoch(a).eventtype) 0358 temp=EEG.epoch(a).eventtype; %EEG.eventtype 0359 EEG.epoch(a).eventtype=cell(1,1); 0360 EEG.epoch(a).eventtype{1}=temp; 0361 end 0362 0363 if ~iscell(EEG.epoch(a).eventurevent) 0364 temp=EEG.epoch(a).eventurevent; %EEG.eventurevent 0365 EEG.epoch(a).eventurevent=cell(1,1); 0366 EEG.epoch(a).eventurevent{1}=temp; 0367 end 0368 0369 %Add bin info to EEG.epoch 0370 add_ct=add_ct+1; 0371 add_ev_ct=add_ev_ct+1; 0372 EEG.epoch(a).eventtype{add_ct+n_ep_type}=['bin' num2str(bin)]; 0373 %Duplicate other information about event 0374 if evdurflag, 0375 EEG.epoch(a).eventduration{add_ct+n_ep_type}=EEG.epoch(a).eventduration{b}; 0376 end 0377 EEG.epoch(a).eventlatency{add_ct+n_ep_type}=EEG.epoch(a).eventlatency{b}; 0378 EEG.epoch(a).event(add_ct+n_ep_type)=n_ev+add_ev_ct; 0379 EEG.epoch(a).eventurevent{add_ct+n_ep_type}=EEG.epoch(a).eventurevent{b}; 0380 0381 source_ev_id=EEG.epoch(a).event(b); 0382 %Note, it looks like EEGLAB adds an event for a urevent everytime it occurs in an epoch 0383 0384 %Add bin info to EEG.event 0385 EEG.event(n_ev+add_ev_ct).type=['bin' num2str(bin)]; 0386 EEG.event(n_ev+add_ev_ct).latency=EEG.event(source_ev_id).latency; 0387 if isfield(EEG.event(source_ev_id),'duration') 0388 EEG.event(n_ev+add_ev_ct).duration=EEG.event(source_ev_id).duration; 0389 end 0390 EEG.event(n_ev+add_ev_ct).urevent=EEG.event(source_ev_id).urevent; 0391 EEG.event(n_ev+add_ev_ct).epoch=a; 0392 0393 if ~EEG.epoch(a).eventlatency{b} 0394 %only update bin counter if the time locking event 0395 %falls in the current bin 0396 bin_ct(bin)=bin_ct(bin)+1; 0397 end 0398 end 0399 end 0400 end 0401 end 0402 end 0403 end 0404 0405 %% Output summary to command line and save EEG variable 0406 if VERBLEVEL>1, 0407 fprintf('\nNumber of events per bin.\n'); 0408 for a=1:n_bin, 0409 fprintf('Bin %d (%s): %d\n',a,EEG.bindesc{a},bin_ct(a)); 0410 end 0411 end 0412 0413 if ~isempty(save_fname), 0414 if VERBLEVEL>0, 0415 fprintf('Saving EEG variable as the file: %s\n',save_fname); 0416 end 0417 [justpath, justname]=pathNname(save_fname); 0418 EEG=pop_saveset(EEG,'filename',justname,'filepath',justpath); 0419 end