compile_erpimage() - Extracts relevant data from multiple data sets for creating ERPimages. ERPimages are produced by the function plot_erpimageMK.m. Usage: >> compile_erpimage(setfiles,varargin) Required Input: gui_infiles_or_tmplt - ['gui', a cell array of strings, or a string template] If 'gui', a GUI is created that allows you to select which set files to import (this is probably the easiest way to import files). If a cell array of of strings, each element of the cell array should contain the filename of an EEGLAB set file (e.g., {'visodbl01.set','visodbl02.set'}. Otherwise, this input should be a filename template (i.e., a string with # where the subject number should be--'visodbl#.set'). If you provide a template, you must use the option 'sub_ids' (see below) to specify the ID numbers of each subject. Include the files' path unless the files are in the current working directory. Optional Inputs: 'bins' = [integer vector] Bins to extract trials from {default: use all bins} 'chans' = [string | cell array] Name of the electrode (e.g., 'MiCe') or a cell array of electrode names that you want to image. {default: use all electrodes} 'sub_ids' = [integer vector] A set of integers specifying the subject ID numbers to include in the grand average. Only necessary if a filename template is given as the input to gui_infiles_or_tmplt. Leading 0's are not necessary for ID numbers less than 10 (e.g., If 7 is a sub_id and visodbl#.set the template, the function will look for visodbl07.set AND visodbl7.set). 'bsln_wind' = [pair of integers] The time window (in units of milliseconds) that will be used to baseline each trial of EEG. The mean voltage in the time window will be removed from the entire EEG epoch. If the data have already been baselined and ICA artifact correction was NOT applied, you won't need to re-baseline the data. {default: no additional baselining will be done} 'out_fname' = [string] The name of the Matlab file in which the ERPimage data will be stored. If not specified, the data will be stored in global variables that plot_erpimageMK.m can use. By convention, you should give the file the extension .eim and include the files' path, unless the files are in the current working directory. {default: store data as global variables} '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 verblevel not already specified} 3 - stuff that might help you debug (show all reports) Outputs: If specified, function saves data for creating ERPimages in a Matlab file. Otherwise, function stores the data in the following global variables: chan_data, chans, chanlocs, ep_info, ep_times, bindesc, & srate Example: >> setfile_tplate='/usr/local/matlab-toolboxes/matlabmk/demo_files/rtm#y.set'; >> chans={'MiPf','MiCe','MiOc','LLOc','RLOc'}; >> compile_erpimage(setfile_tplate,'sub_ids',1:4,'chans',chans, ... 'bins',[127 133 142 157],'out_fname','demo.eim'); >> plot_erpimageMK('MiCe','rtmsec','in_fname','demo.eim','avewidth',4,'fig_id',1); Notes: -This function assumes that if two electrodes in two different setfiles have the same name (e.g., 'MiCe'), then they are homologous. Congruency of electrode coordinates is not checked. Some electrodes in the 26 and 59 electrode caps have the same names but are not in homologous positions. Author: David Groppe Kutaslab, 8/2009
0001 % compile_erpimage() - Extracts relevant data from multiple data sets for 0002 % creating ERPimages. ERPimages are produced by the 0003 % function plot_erpimageMK.m. 0004 % 0005 % Usage: 0006 % >> compile_erpimage(setfiles,varargin) 0007 % 0008 % Required Input: 0009 % gui_infiles_or_tmplt - ['gui', a cell array of strings, or a string template] 0010 % If 'gui', a GUI is created that allows you to select 0011 % which set files to import (this is probably the 0012 % easiest way to import files). If a cell array of 0013 % of strings, each element of the cell array should 0014 % contain the filename of an EEGLAB set file (e.g., 0015 % {'visodbl01.set','visodbl02.set'}. Otherwise, this 0016 % input should be a filename template (i.e., a string with 0017 % # where the subject number should be--'visodbl#.set'). 0018 % If you provide a template, you must use the option 0019 % 'sub_ids' (see below) to specify the ID numbers of 0020 % each subject. Include the files' path unless the files 0021 % are in the current working directory. 0022 % 0023 % 0024 % Optional Inputs: 0025 % 'bins' = [integer vector] Bins to extract trials from {default: 0026 % use all bins} 0027 % 'chans' = [string | cell array] Name of the electrode (e.g., 0028 % 'MiCe') or a cell array of electrode names that you 0029 % want to image. {default: use all electrodes} 0030 % 'sub_ids' = [integer vector] A set of integers specifying the 0031 % subject ID numbers to include in the grand average. 0032 % Only necessary if a filename template is given as 0033 % the input to gui_infiles_or_tmplt. Leading 0's are not 0034 % necessary for ID numbers less than 10 (e.g., If 7 is a 0035 % sub_id and visodbl#.set the template, the function will 0036 % look for visodbl07.set AND visodbl7.set). 0037 % 'bsln_wind' = [pair of integers] The time window (in units of 0038 % milliseconds) that will be used to baseline each trial 0039 % of EEG. The mean voltage in the time window will be 0040 % removed from the entire EEG epoch. If the data have 0041 % already been baselined and ICA artifact correction was NOT 0042 % applied, you won't need to re-baseline the data. {default: 0043 % no additional baselining will be done} 0044 % 'out_fname' = [string] The name of the Matlab file in which the 0045 % ERPimage data will be stored. If not specified, 0046 % the data will be stored in global variables that 0047 % plot_erpimageMK.m can use. By convention, you 0048 % should give the file the extension .eim and include 0049 % the files' path, unless the files are in the 0050 % current working directory. {default: store data as 0051 % global variables} 0052 % 'verblevel' = an integer specifiying the amount of information you 0053 % want functions to provide about what they are doing 0054 % during runtime. 0055 % Options are: 0056 % 0 - quiet, only show errors, warnings, and EEGLAB 0057 % reports 0058 % 1 - stuff anyone should probably know 0059 % 2 - stuff you should know the first time you start 0060 % working with a data set {default value if 0061 % verblevel not already specified} 0062 % 3 - stuff that might help you debug (show all 0063 % reports) 0064 % 0065 % Outputs: 0066 % If specified, function saves data for creating ERPimages in a Matlab file. 0067 % Otherwise, function stores the data in the following global variables: 0068 % chan_data, chans, chanlocs, ep_info, ep_times, bindesc, & srate 0069 % 0070 % 0071 % Example: 0072 % >> setfile_tplate='/usr/local/matlab-toolboxes/matlabmk/demo_files/rtm#y.set'; 0073 % >> chans={'MiPf','MiCe','MiOc','LLOc','RLOc'}; 0074 % >> compile_erpimage(setfile_tplate,'sub_ids',1:4,'chans',chans, ... 0075 % 'bins',[127 133 142 157],'out_fname','demo.eim'); 0076 % >> plot_erpimageMK('MiCe','rtmsec','in_fname','demo.eim','avewidth',4,'fig_id',1); 0077 % 0078 % Notes: 0079 % -This function assumes that if two electrodes in two different setfiles 0080 % have the same name (e.g., 'MiCe'), then they are homologous. Congruency 0081 % of electrode coordinates is not checked. Some electrodes in the 26 and 0082 % 59 electrode caps have the same names but are not in homologous 0083 % positions. 0084 % 0085 % Author: 0086 % David Groppe 0087 % Kutaslab, 8/2009 0088 % 0089 0090 %%%%%%%%%%%%%%%% REVISION LOG %%%%%%%%%%%%%%%%% 0091 % 0092 % 08/21/09 Tidied up (e.g., temp_epoch information for the set currently in memory 0093 % no longer needs to be stored) -DG 0094 % 0095 % 2/1/2010-remove_art_ics.m replaced by remove_artifact_ics.m. Help 0096 % documentation extended to cover all optional input arguments. -DG 0097 % 0098 0099 function compile_erpimage(gui_infiles_or_tmplt,varargin) 0100 0101 global VERBLEVEL 0102 global chan_data; 0103 global chans; 0104 global chanlocs; 0105 global ep_info; 0106 global ep_times; 0107 global bindesc; 0108 global srate; 0109 global rtbins; 0110 global rtmsec; 0111 global eim_bins 0112 0113 %Input Parser 0114 p=inputParser; 0115 %Note: the order of the required arguments needs to match precisely their 0116 %order in the function definition (which is also the order used by p.parse 0117 %below) 0118 p.addRequired('gui_infiles_or_tmplt',@(x) ischar(x) || iscell(x)); 0119 p.addParamValue('bins',[],@isnumeric); 0120 p.addParamValue('chans',[],@(x) ischar(x) | iscell(x)); 0121 p.addParamValue('sub_ids',[],@isnumeric); 0122 p.addParamValue('out_fname',[],@ischar); 0123 p.addParamValue('verblevel',[],@(x) x>=0); 0124 p.addParamValue('bsln_wind',[],@(x) isvector(x) && (length(x)==2)); 0125 0126 p.parse(gui_infiles_or_tmplt,varargin{:}); 0127 0128 if isempty(VERBLEVEL) && isempty(p.Results.verblevel) 0129 VERBLEVEL=2; 0130 elseif ~isempty(p.Results.verblevel) 0131 VERBLEVEL=p.Results.verblevel; 0132 end 0133 0134 %Do NOT store data in global variables 0135 if ~isempty(p.Results.out_fname) 0136 clear global chan_data; 0137 clear global chans; 0138 clear global chanlocs; 0139 clear global ep_info; 0140 clear global ep_times; 0141 clear global bindesc; 0142 clear global srate; 0143 clear global rtbins; 0144 clear global rtmsec; 0145 clear global eim_bins; 0146 end 0147 0148 %Note, if chans is empty, use all of them (done in main loop below) 0149 if ischar(p.Results.chans) 0150 n_chan=1; 0151 chans{1}=p.Results.chans; %make it a cell array 0152 chan_data=cell(1,n_chan); 0153 elseif iscell(p.Results.chans) 0154 n_chan=length(p.Results.chans); 0155 chans=p.Results.chans; 0156 chan_data=cell(1,n_chan); 0157 end 0158 0159 0160 %% Get *.set fileames 0161 sfiles=get_set_infiles(gui_infiles_or_tmplt,p.Results.sub_ids); 0162 0163 0164 if isempty(p.Results.bins), 0165 VerbReport('Grabbing data from all bins in setfiles.',2,VERBLEVEL); 0166 end 0167 0168 0169 %%%%%%%%%%%%%%%%%%%% File Loop %%%%%%%%%%%%%%%%%%%%%%%%% 0170 clear ep_info; %the epoch information from all sets 0171 rtmsec=[]; %the rts from all sets 0172 rtbins=[]; %the bin numbers that rtmsec correspond to (same event can have different RTs for different bins) 0173 chanlocs=[]; %the channel location info for all sets 0174 grand_ep_ct=0; 0175 global EEG; %necessary for rm_artifact_ics (below) 0176 0177 for a=1:length(sfiles), 0178 %Note, pop_loadset displays message about what file is being loaded 0179 EEG=pop_loadset(sfiles{a}); 0180 0181 %Check for artifact ICs and remove them if there 0182 %[EEG, ICs_removed]=remove_art_ics(EEG,p.Results.bsln_wind,VERBLEVEL); ??old code 0183 ICs_removed=remove_artifact_ics(p.Results.bsln_wind,VERBLEVEL); 0184 0185 %Baseline EEG (unless already baselined by remove_art_ics 0186 %if ~isempty(p.Results.bsln_wind) && ~ICs_removed, ?? old code 0187 if ~isempty(p.Results.bsln_wind) && isempty(ICs_removed), 0188 EEG=baseline_EEG(EEG,p.Results.bsln_wind,VERBLEVEL); 0189 end 0190 0191 %%%%% Make sure new set is consistent with already loaded sets %%%%%% 0192 %Get/check times (in ms) for all time points 0193 if ~exist('ep_times','var') 0194 ep_times=EEG.times; 0195 elseif isempty(ep_times) 0196 ep_times=EEG.times; 0197 else 0198 if (length(ep_times)==length(EEG.times)), 0199 if max(abs(ep_times-EEG.times)) 0200 error('EEG.times in set %s does not match that of other sets.\n', ... 0201 sfiles{a}); 0202 end 0203 else 0204 error('EEG.times in set %s does not match that of other sets.\n', ... 0205 sfiles{a}); 0206 end 0207 end 0208 0209 %Get/check sampling rate 0210 if ~exist('srate','var') 0211 srate=EEG.srate; 0212 elseif isempty(srate) 0213 srate=EEG.srate; 0214 else 0215 if (srate~=EEG.srate), 0216 error('EEG.srate in set %s does not match that of other sets.\n', ... 0217 sfiles{a}); 0218 end 0219 end 0220 0221 %See if reaction time info is attached to set 0222 fldnames=fieldnames(EEG); 0223 rtmsec_attached=0; 0224 rtbins_attached=0; 0225 for d=1:length(fldnames), 0226 if strcmpi(fldnames{d},'rtmsec') 0227 rtmsec_attached=1; 0228 elseif strcmpi(fldnames{d},'rtbins') 0229 rtbins_attached=1; 0230 end 0231 end 0232 rts_attached=rtbins_attached*rtmsec_attached; 0233 if ~isempty(rtmsec) && ~(rts_attached), 0234 error(['File %s does not have reaction time information, ' ... 0235 'but the other files you loaded do.\n'],sfiles{a}); 0236 end 0237 0238 %Get/check bin descriptors 0239 if ~exist('bindesc','var') 0240 bindesc=EEG.bindesc; 0241 elseif isempty(bindesc) 0242 bindesc=EEG.bindesc; 0243 else 0244 if length(bindesc)==length(EEG.bindesc) 0245 for b=1:length(bindesc), 0246 if ~strcmpi(bindesc{b},EEG.bindesc{b}), 0247 error('EEG.bindesc in set %s does not match that of other sets.\n', ... 0248 sfiles{a}); 0249 end 0250 end 0251 else 0252 error('EEG.bindesc in set %s does not match that of other sets.\n', ... 0253 sfiles{a}); 0254 end 0255 end 0256 0257 no_chans=0; 0258 if ~exist('chanlocs','var'), 0259 no_chans=1; 0260 elseif isempty(chanlocs), 0261 no_chans=1; 0262 end 0263 if no_chans, 0264 chanlocs=EEG.chanlocs; 0265 %if chans not specified by user, use all of them 0266 if isempty(p.Results.chans) 0267 n_chan=length(chanlocs); 0268 chan_data=cell(1,n_chan); 0269 for c=1:n_chan, 0270 chans{c}=EEG.chanlocs(c).labels; 0271 end 0272 end 0273 end 0274 0275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0276 % Find epochs that fall into desired bins 0277 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0278 %Note, I'm sure you could speed this up by first converting the bin 0279 %identifiers in EEG.epoch.eventtype from strings (e.g., 'bin1') to 0280 %integers (e.g., 1) 0281 0282 %Initialize variables tracking information about the current set 0283 use_ep_this_set=[]; 0284 temp_ep_ct=0; %this variable counts how many epochs have been grabbed from JUST THE CURRENT SET 0285 0286 if isempty(p.Results.bins), 0287 %use all bins 0288 for d=1:length(EEG.epoch), 0289 %Grab this epoch? loop 0290 for j=1:length(EEG.epoch(d).eventtype), %check this epoch's types 0291 if strcmpi(EEG.epoch(d).eventtype{j}(1:3),'bin') %is this type a bin? 0292 use_ep_this_set=[use_ep_this_set d]; 0293 temp_ep_ct=temp_ep_ct+1; 0294 0295 EEG.epoch(d).sourcefile=sfiles{a}; %create new field to keep 0296 %track of what file each epoch came from 0297 grand_ep_ct=grand_ep_ct+1; 0298 ep_info(grand_ep_ct)=EEG.epoch(d); 0299 if rts_attached, 0300 rtbins{grand_ep_ct}=EEG.rtbins{d}; 0301 rtmsec{grand_ep_ct}=EEG.rtmsec{d}; 0302 end 0303 break; %leave j loop 0304 end 0305 end 0306 end 0307 else 0308 %use specified bins 0309 for d=1:length(EEG.epoch), 0310 %Grab this epoch? loop 0311 grabbed=0; 0312 for j=1:length(EEG.epoch(d).eventtype), %check this epoch's types 0313 for k=p.Results.bins, 0314 if strcmpi(EEG.epoch(d).eventtype{j},['bin' int2str(k)]), 0315 use_ep_this_set=[use_ep_this_set d]; 0316 temp_ep_ct=temp_ep_ct+1; 0317 0318 EEG.epoch(d).sourcefile=sfiles{a}; %create new field to keep 0319 %track of what file each epoch came from 0320 grand_ep_ct=grand_ep_ct+1; 0321 ep_info(grand_ep_ct)=EEG.epoch(d); 0322 if rts_attached, 0323 rtbins{grand_ep_ct}=EEG.rtbins{d}; 0324 rtmsec{grand_ep_ct}=EEG.rtmsec{d}; 0325 end 0326 grabbed=1; 0327 break; %leave k loop 0328 end 0329 end 0330 if grabbed, 0331 break; %leave j loop 0332 end 0333 end 0334 end 0335 end 0336 0337 %Check to make sure no epochs have been included more than once. This 0338 %should never happen. 0339 if length(use_ep_this_set)~=length(unique(use_ep_this_set)), 0340 error(['The same trial of data has been grabbed more than once and will distort' ... 0341 ' the ERPimage.']); 0342 end 0343 0344 %Make sure this file is contributing some data to the pool 0345 if isempty(use_ep_this_set), 0346 watchit(sprintf('File %s has no trials for the bins you are trying to analyze.\n', ... 0347 sfiles{a})); 0348 else 0349 for c=1:n_chan, 0350 %find channel id 0351 n_loc=length(chanlocs); 0352 chan_id=[]; 0353 for d=1:n_loc, 0354 if strcmpi(chanlocs(d).labels,chans{c}), 0355 chan_id=d; 0356 break; %break out of d loop; 0357 end 0358 end 0359 0360 if ~isempty(chan_id) 0361 %concatenate data 0362 chan_data{c}=[chan_data{c} squeeze(EEG.data(chan_id,:,use_ep_this_set))]; 0363 else 0364 watchit(sprintf('File: %s does not have electrode: %s\n',sfiles{a}, ... 0365 chans{c})); 0366 end 0367 end 0368 end 0369 end 0370 0371 %record bins that were loaded 0372 if ~isempty(p.Results.bins) 0373 eim_bins=p.Results.bins; 0374 else 0375 eim_bins=zeros(1,length(bindesc)); 0376 for a=1:length(bindesc) 0377 if ~isempty(bindesc{a}) 0378 eim_bins(a)=1; 0379 end 0380 end 0381 eim_bins=find(eim_bins); 0382 end 0383 0384 if ~isempty(p.Results.out_fname) 0385 VerbReport(sprintf('Saving data to %s.',p.Results.out_fname),2,VERBLEVEL); 0386 save(p.Results.out_fname,'chans','chan_data','ep_info','chanlocs', ... 0387 'ep_times','sfiles','bindesc','srate','rtbins','rtmsec','eim_bins'); 0388 else %make variables global for other functions to use 0389 VerbReport('Putting data in global variables.',2,VERBLEVEL); 0390 end 0391