sbjct_info2set() - Imports information about a subject into the epochs of an EEGLAB .set file from a text file. The new information (e.g., age, sex) is added to the EEG.event and EEG.epoch fields of the EEG struct variable. Usage: >> sbjct_info2set(in_setfile,sbjct_infofile,sbjct_id,out_setfile,forcewrite,verblevel) Required Inputs: in_setfile = [string] the name of the source EEGLAB .set file (include the file's pathname unless it is in the current working directory). sbjct_infofile = [string] a space or tab delimited text file containing additional numeric information about the subject who generated the data in 'in_setfile'. The first row of the file is a header line with a one word description of each column in the file. Each row below the headerline corresponds to a different experimental subject. The first column of the file specifies the subject ID (it can be a number or a string). Additional columns specificy information about the subject (e.g., age, sex). This information can be numeric or a string. sbjct_id = a number or string that identifies the subject who produced the data in 'in_setfile.' The contents of 'sbjct_id' should match the contents of exactly one cell in the first column of the file specified by 'sbjct_infofile' (matching is NOT case sensitive). Optional Inputs: out_setfile = [string] the name of the EEGLAB .set file that will be written to (include the file's pathname unless it is in the current working directory) {default: same as in_setfile} forcewrite = ['on' | 'off'] If 'on', the function will automatically overwrite any pre-existing event information in the .set file that contradicts the event information in sbjct_infofile. If 'off,' the user will be asked whether or not to overwrite any such pre-existing information. {default: 'off'} 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: Function outputs nothing in Matlab. It simply writes/overwites a .set file to disk. Example: >> in_fname='/homes/dgroppe/SANDBOX/PRSENT/prsent41.set'; >> sbjct_infofile='/homes/dgroppe/SANDBOX/PRSENT/prsent_sbjctinfo.txt'; >> evcode_info2set(in_fname,sbjct_infofile,'temp.set'); Additional Notes: Don't use parenthesis in column header names. Matlab interprets the name as a function call. Use NaN to fill cells for codes that don't have a value for a particular column Author: David Groppe Kutaslab, 10/2009
0001 function sbjct_info2set(in_setfile,sbjct_infofile,sbjct_id,out_setfile,forcewrite,verblevel) 0002 % 0003 % sbjct_info2set() - Imports information about a subject into the epochs 0004 % of an EEGLAB .set file from a text file. 0005 % The new information (e.g., age, sex) is added to the 0006 % EEG.event and EEG.epoch fields of the EEG struct 0007 % variable. 0008 % 0009 % Usage: 0010 % >> sbjct_info2set(in_setfile,sbjct_infofile,sbjct_id,out_setfile,forcewrite,verblevel) 0011 % 0012 % 0013 % Required Inputs: 0014 % in_setfile = [string] the name of the source EEGLAB .set file 0015 % (include the file's pathname unless it is in the 0016 % current working directory). 0017 % 0018 % sbjct_infofile = [string] a space or tab delimited text file 0019 % containing additional numeric information 0020 % about the subject who generated the data in 0021 % 'in_setfile'. The first row of the file is a 0022 % header line with a one word description of each 0023 % column in the file. Each row below the headerline 0024 % corresponds to a different experimental subject. 0025 % The first column of the file specifies the subject 0026 % ID (it can be a number or a string). Additional columns 0027 % specificy information about the subject (e.g., 0028 % age, sex). This information can be numeric or a 0029 % string. 0030 % 0031 % sbjct_id = a number or string that identifies the subject 0032 % who produced the data in 'in_setfile.' The contents 0033 % of 'sbjct_id' should match the contents of exactly 0034 % one cell in the first column of the file specified by 0035 % 'sbjct_infofile' (matching is NOT case sensitive). 0036 % 0037 % Optional Inputs: 0038 % out_setfile = [string] the name of the EEGLAB .set file that will 0039 % be written to (include the file's pathname unless 0040 % it is in the current working directory) {default: 0041 % same as in_setfile} 0042 % 0043 % forcewrite = ['on' | 'off'] If 'on', the function will 0044 % automatically overwrite any pre-existing event 0045 % information in the .set file that contradicts the 0046 % event information in sbjct_infofile. If 'off,' the 0047 % user will be asked whether or not to overwrite any 0048 % such pre-existing information. {default: 'off'} 0049 % 0050 % verblevel = an integer specifiying the amount of information you 0051 % want functions to provide about what they are doing 0052 % during runtime. 0053 % Options are: 0054 % 0 - quiet, only show errors, warnings, and EEGLAB 0055 % reports 0056 % 1 - stuff anyone should probably know 0057 % 2 - stuff you should know the first time you start 0058 % working with a data set {default value if 0059 % verblevel not already specified} 0060 % 3 - stuff that might help you debug (show all 0061 % reports) 0062 % 0063 % Outputs: 0064 % Function outputs nothing in Matlab. It simply writes/overwites a .set 0065 % file to disk. 0066 % 0067 % 0068 % Example: 0069 % >> in_fname='/homes/dgroppe/SANDBOX/PRSENT/prsent41.set'; 0070 % >> sbjct_infofile='/homes/dgroppe/SANDBOX/PRSENT/prsent_sbjctinfo.txt'; 0071 % >> evcode_info2set(in_fname,sbjct_infofile,'temp.set'); 0072 % 0073 % 0074 % Additional Notes: 0075 % 0076 % Don't use parenthesis in column header names. Matlab interprets 0077 % the name as a function call. 0078 % 0079 % Use NaN to fill cells for codes that don't have a value for a 0080 % particular column 0081 % 0082 % Author: 0083 % David Groppe 0084 % Kutaslab, 10/2009 0085 % 0086 0087 global VERBLEVEL 0088 0089 %Check Inputs 0090 if nargin<3, 0091 error('Function sbjct_info2set.m requires at least three arguments.\n'); 0092 end 0093 0094 if ~ischar(in_setfile), 0095 error('Argument in_setfile needs to be a string that specifies an EEGLAB .set file.'); 0096 end 0097 0098 if ~ischar(sbjct_infofile), 0099 error('Argument sbjct_infofile needs to be a string that specifies a text file.'); 0100 end 0101 0102 if isnumeric(sbjct_id), 0103 sbjct_id=num2str(sbjct_id); 0104 end 0105 0106 if nargin<4, 0107 out_setfile=in_setfile; %default: output file same as input file 0108 VerbReport('New set file will overwrite old set file (default behavior).', ... 0109 2, VERBLEVEL); 0110 else 0111 if ~ischar(out_setfile), 0112 error('Argument out_setfile needs to be a string that specifies an EEGLAB .set file.'); 0113 end 0114 end 0115 0116 if nargin<5, 0117 forcewrite='off'; 0118 elseif (~strcmpi(forcewrite,'on') && ~strcmpi(forcewrite,'off')) 0119 error('Argument "forcewrite" needs to be set to ''on'' or ''off''.'); 0120 end 0121 0122 if nargin<6 0123 if isempty(VERBLEVEL), 0124 VERBLEVEL=2; %default 0125 end 0126 else 0127 VERBLEVEL=verblevel; 0128 end 0129 0130 0131 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0132 % LOAD .set FILE 0133 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0134 EEG=pop_loadset(in_setfile); 0135 0136 0137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0138 % LOAD INFORMATION ABOUT EACH CLASS OF EXPERIMENTAL EVENT (e.g. TARGETS vs. STANDARDS) FROM A TEXT FILE 0139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0140 VerbReport(sprintf('Getting additional information about subject from %s', ... 0141 sbjct_infofile), 1, VERBLEVEL); 0142 [sub_fid, message]=fopen(sbjct_infofile,'r'); 0143 if (sub_fid==-1), 0144 fprintf('*************** ERROR ******************\n'); 0145 fprintf('Cannot open file %s.\n',sbjct_infofile); 0146 fprintf('According to fopen: %s.\n',message); 0147 error('Aborting import of additional subject information.'); 0148 else 0149 %read column headers 0150 txtline = fgetl(sub_fid); 0151 if (txtline==-1), 0152 fprintf('*************** ERROR ******************\n'); 0153 fprintf('File %s is empty.\n',sub_fid); 0154 error('Aborting import of additional subject information.'); 0155 else 0156 0157 %Parse column header 0158 clear sub_col_hdrs; 0159 col_ct=1; 0160 [sub_col_hdrs{col_ct}, rmndr]=strtok(txtline); 0161 fprintf('Subject ID column is: %s\n',sub_col_hdrs{col_ct}); 0162 while ~isempty(rmndr) && charleft(rmndr), 0163 col_ct=col_ct+1; 0164 [sub_col_hdrs{col_ct}, rmndr]=strtok(rmndr); 0165 fprintf('Column %d is: %s\n',col_ct,sub_col_hdrs{col_ct}); 0166 end 0167 n_col=col_ct; 0168 0169 %Read rows (information per subject) 0170 row_ct=1; 0171 found_flag=0; 0172 while ~feof(sub_fid) 0173 txtline = fgetl(sub_fid); 0174 [neo_val, txtline]=strtok(txtline); 0175 if strcmpi(neo_val,sbjct_id), 0176 if found_flag, 0177 error('File %s had multiple rows for subject %s. It should only have one.',sbjct_infofile,sbjct_id); 0178 else 0179 found_flag=1; 0180 col_ct=1; 0181 file_sub_info=cell(1,n_col-1); 0182 while ~isempty(txtline) && charleft(txtline), 0183 [neo_val, txtline]=strtok(txtline); 0184 file_sub_info{col_ct}=neo_val; %novel info is a string 0185 %Note, subjects that do not have a value for that 0186 %column should be represented as NaN 0187 col_ct=col_ct+1; 0188 end 0189 end 0190 end 0191 row_ct=row_ct+1; 0192 end 0193 end 0194 fclose(sub_fid); 0195 end 0196 if ~found_flag, 0197 error('Subject %s not found in file %s. Import of subject information aborted.', ... 0198 sbjct_id,sbjct_infofile); 0199 end 0200 0201 0202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0203 % ADD NEW EPOCH INFORMATION TO EEG STRUCT 0204 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0205 0206 fldnames=fieldnames(EEG.epoch); 0207 %for each new column (assume first column is Subject ID) 0208 for a=2:length(sub_col_hdrs), 0209 doit=1; 0210 %check to make sure column does not already exist 0211 for b=1:length(fldnames), 0212 if strcmpi(['event' sub_col_hdrs{a}],fldnames{b}), 0213 if ~strcmpi(forcewrite,'on') 0214 %ask user if s/he wants to overwrite 0215 fprintf('Field %s already exists in %s.\n',sub_col_hdrs{a},EEG.filename); 0216 erayz=input('Do you want to overwrite existing field? ("y" or "n"): ','s'); 0217 while ~strcmpi(erayz,'y') && ~strcmpi(erayz,'n') 0218 erayz=input('Please enter the single letter "y" or "n": ','s'); 0219 end 0220 else 0221 erayz='y'; 0222 end 0223 if strcmpi(erayz,'n') 0224 fprintf('NOT overwriting EEG.%s.\n',fldnames{b}); 0225 doit=0; 0226 break; 0227 else 0228 fprintf('OVERWRITING EEG.%s.\n',fldnames{b}); 0229 EEG.epoch=rmfield(EEG.epoch,fldnames{b}); 0230 EEG.event=rmfield(EEG.event,fldnames{b}(6:end)); %starting at 6 ignores 'event' 0231 break; 0232 end 0233 end 0234 end 0235 0236 %write new event info to struct 0237 if doit, 0238 if isempty(str2num(file_sub_info{a-1})), 0239 str=1; %string 0240 else 0241 str=0; %numeric 0242 end 0243 0244 %add to EEG.epoch 0245 for c=1:length(EEG.epoch), 0246 if str, 0247 cmd=['EEG.epoch(' int2str(c) ').event' sub_col_hdrs{a} '=''' file_sub_info{a-1} ''';']; 0248 else 0249 cmd=['EEG.epoch(' int2str(c) ').event' sub_col_hdrs{a} '=' file_sub_info{a-1} ';']; 0250 end 0251 eval(cmd); 0252 end 0253 0254 %add to EEG.event 0255 for c=1:length(EEG.event), 0256 if str, 0257 cmd=['EEG.event(' int2str(c) ').' sub_col_hdrs{a} '=''' file_sub_info{a-1} ''';'];%string 0258 else 0259 cmd=['EEG.event(' int2str(c) ').' sub_col_hdrs{a} '=' file_sub_info{a-1} ';'];%numeric 0260 end 0261 eval(cmd); 0262 end 0263 end 0264 end 0265 0266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0267 % SAVE .set FILE 0268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0269 0270 [fpath, fname]=pathNname(out_setfile); 0271 EEG=pop_saveset(EEG,'filepath',fpath,'filename',fname); 0272 0273 end 0274 0275 0276 function yesno=charleft(str) 0277 0278 0279 yesno=0; 0280 for x=1:length(str), 0281 if (str(x)~=32) && (str(x)~=13) 0282 %32=space, 13=carriage return 0283 yesno=1; 0284 break; 0285 end 0286 end 0287 0288 0289 end