tfrs2tfrGND() - Creates a fieldtrip compatible MATLABmk tfrGND struct variable from MATLABmk *.tfr files. The tfrGND variable contains mean spectrograms per bin for each subject and the grand average spectrograms. Usage: >> tfrGND=tfrs2tfrGND(gui_infiles_or_tmplt,varargin); Required Inputs: 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 tfr 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 a tfr file (e.g., {'visodbl01.tfr','visodbl02.tfr'}. Otherwise, this input should be a filename template (i.e., a string with # where the subject number should be--'visodbl#.tfr'). 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. Note, tfr files are produced by set2tfr.m. Optional Inputs: 'use_bins' - [integer vector] A set of integers specifying which bins to import into MATLAB. If not specified, all bins will be imported. Note, if you import only a subset of bins, the bin numberings will start at 1 and run to the number you've imported (i.e., they may differ from the bin numbers in the set files. {default: import all bins} '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. 'units' - ['dB' or 'raw'] If 'dB' spectral power will be in units of decibels, 10*log10(uV^2/Hz). If 'raw' spectral power will be in units of uV^2/Hz. {default: whatever the units were when the tfrGND variable was first created} 'bsln_type' - The type of baseline used to normalize each participant's data. Default is to use whatever baseline type was used when the TFR variablea were first created. Options are: 'relative' - Power at each time point is divided by the mean power in the baseline window. 'absolute' - The mean power in the baseline window is subtracted from the power at each time point. 'bsln_wind' - [min max] Time window (in ms) used to baseline the spectrograms {default: whatever baseline window was originally used with the TFR variables} 'out_fname' - [string] Filename to save TFR variable to. If empty (i.e., not specified), the TFR variable will NOT be saved to disk but will be returned to the MATLAB workspace. If no file extension is given '.tfr' will be added to the filename. {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} 3 - stuff that might help you debug (show all reports) Output: tfrGND - Contains the mean spectrograms per bin for each subject, the grand average spectrograms, and associated information (e.g., channel locations, source files) in a fieldtrip compatible format. Global Variables: VERBLEVEL - MATLABmk 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' Author: David Groppe Kutaslab, 1/2011
0001 % tfrs2tfrGND() - Creates a fieldtrip compatible MATLABmk tfrGND struct variable 0002 % from MATLABmk *.tfr files. The tfrGND variable contains mean 0003 % spectrograms per bin for each subject and the grand 0004 % average spectrograms. 0005 % 0006 % Usage: 0007 % >> tfrGND=tfrs2tfrGND(gui_infiles_or_tmplt,varargin); 0008 % 0009 % Required Inputs: 0010 % gui_infiles_or_tmplt - ['gui', a cell array of strings, or a string template] 0011 % If 'gui', a GUI is created that allows you to select 0012 % which tfr files to import (this is probably the 0013 % easiest way to import files). If a cell array of 0014 % of strings, each element of the cell array should 0015 % contain the filename of a tfr file (e.g., 0016 % {'visodbl01.tfr','visodbl02.tfr'}. Otherwise, this 0017 % input should be a filename template (i.e., a string with 0018 % # where the subject number should be--'visodbl#.tfr'). 0019 % If you provide a template, you must use the option 0020 % 'sub_ids' (see below) to specify the ID numbers of 0021 % each subject. Include the files' path unless the files 0022 % are in the current working directory. Note, tfr 0023 % files are produced by set2tfr.m. 0024 % 0025 % 0026 % Optional Inputs: 0027 % 'use_bins' - [integer vector] A set of integers specifying which 0028 % bins to import into MATLAB. If not specified, all 0029 % bins will be imported. Note, if you import only a 0030 % subset of bins, the bin numberings will start at 1 0031 % and run to the number you've imported (i.e., they may 0032 % differ from the bin numbers in the set files. 0033 % {default: import all bins} 0034 % 'sub_ids' - [integer vector] A set of integers specifying the 0035 % subject ID numbers to include in the grand average. 0036 % Only necessary if a filename template is given as 0037 % the input to gui_infiles_or_tmplt. 0038 % 'units' - ['dB' or 'raw'] If 'dB' spectral power will be in units 0039 % of decibels, 10*log10(uV^2/Hz). If 'raw' spectral 0040 % power will be in units of uV^2/Hz. {default: whatever 0041 % the units were when the tfrGND variable was first 0042 % created} 0043 % 'bsln_type' - The type of baseline used to normalize each 0044 % participant's data. Default is to use whatever baseline 0045 % type was used when the TFR variablea were first 0046 % created. Options are: 0047 % 'relative' - Power at each time point is divided by 0048 % the mean power in the baseline window. 0049 % 'absolute' - The mean power in the baseline window 0050 % is subtracted from the power at each 0051 % time point. 0052 % 'bsln_wind' - [min max] Time window (in ms) used to baseline the 0053 % spectrograms {default: whatever baseline window was 0054 % originally used with the TFR variables} 0055 % 'out_fname' - [string] Filename to save TFR variable to. If empty 0056 % (i.e., not specified), the TFR variable will NOT be 0057 % saved to disk but will be returned to the MATLAB 0058 % workspace. If no file extension is given '.tfr' will 0059 % be added to the filename. {default: not specified} 0060 % 'verblevel' - An integer specifiying the amount of information you want 0061 % this function to provide about what it is doing during runtime. 0062 % Options are: 0063 % 0 - quiet, only show errors, warnings, and EEGLAB reports 0064 % 1 - stuff anyone should probably know 0065 % 2 - stuff you should know the first time you start working 0066 % with a data set {default value} 0067 % 3 - stuff that might help you debug (show all 0068 % reports) 0069 % 0070 % Output: 0071 % tfrGND - Contains the mean spectrograms per bin for each subject, 0072 % the grand average spectrograms, and associated 0073 % information (e.g., channel locations, source files) 0074 % in a fieldtrip compatible format. 0075 % 0076 % Global Variables: 0077 % VERBLEVEL - MATLABmk level of verbosity (i.e., tells 0078 % functions how much to report about what they're doing during 0079 % runtime) set by the optional function argument 'verblevel' 0080 % 0081 % Author: 0082 % David Groppe 0083 % Kutaslab, 1/2011 0084 0085 %%%%%%%%%%%%%%%% Revision History %%%%%%%%%%%%%%%%% 0086 % 0087 0088 %%%%%%%%%%%%%%%% Future Work %%%%%%%%%%%%%%%%% 0089 %make exclude/include chans an option ?? 0090 % 0091 % stuff i could add to tfrGND struct ?? 0092 % * indiv_subnames:<-The codenames of each subject 0093 % * indiv_traits: <-A field where you could store traits of individual subjects (e.g., age, working memory span) 0094 % * indiv_bin_ct: <-The number of trials each participant contributed to each bin. 0095 % * indiv_bin_raw_ct: <-A field specific to Kutaslab data that can be 0096 % ignored by non-Kutaslab users. 0097 % * indiv_art_ics: <-The numeric indices of independent components 0098 % removed from each set file before using them to compute ERPs 0099 % * history: <-A record of commands applied to the tfrGND variable 0100 0101 0102 %note fieldtrip function for computing grandaverages is 0103 %ft_freqgrandaverages.m 0104 0105 0106 function tfrGND=tfrs2tfrGND(gui_infiles_or_tmplt,varargin) 0107 0108 p=inputParser; 0109 p.addRequired('gui_infiles_or_tmplt',@(x) ischar(x) || iscell(x)); 0110 p.addParamValue('use_bins',[],@isnumeric); 0111 %p.addParamValue('freq_limits',[],@(x) isnumeric(x) && length(x)==2); %?? make this simply a vector of frequencies of interest first? 0112 %p.addParamValue('time_limits',[],@(x) isnumeric(x) && length(x)==2); ?? 0113 p.addParamValue('out_fname',[],@ischar); 0114 %p.addParamValue('exclude_chans',[],@(x) ischar(x) || iscell(x)); ?? 0115 %p.addParamValue('include_chans',[],@(x) ischar(x) || iscell(x)); ?? 0116 p.addParamValue('verblevel',[],@(x) isnumeric(x) && (length(x)==1)); 0117 p.addParamValue('sub_ids',[],@isnumeric); 0118 p.addParamValue('units',[],@(x) strcmpi(x,'dB') || strcmpi(x,'raw')); 0119 p.addParamValue('bsln_wind',[],@(x) isnumeric(x) && length(x)==2); 0120 p.addParamValue('bsln_type',[],@(x) strcmpi(x,'relative') || strcmpi(x,'absolute')); 0121 %add time_limits & freq_limits as an option ?? 0122 0123 p.parse(gui_infiles_or_tmplt,varargin{:}); 0124 0125 %% Select files for loading 0126 if strcmpi(gui_infiles_or_tmplt,'GUI'), 0127 loading=1; 0128 infiles=[]; 0129 while loading, 0130 [neofname, inpath]=uigetfile({'*.tfr','*.tfr files'; ... 0131 '*.*','All Files (*.*)'},'MATLABmk tfr Files to Import','MultiSelect','on'); 0132 if ischar(neofname), 0133 clear infname; 0134 infname{1}=neofname; %make it a cell array for consistent syntax below 0135 else 0136 infname=neofname; 0137 end 0138 if ~inpath, 0139 if isempty(infiles), 0140 fprintf('File selection cancelled. Aborting tfrs2tfrGND.\n'); 0141 tfrGND=[]; 0142 return; 0143 else 0144 loading=0; 0145 end 0146 else 0147 if isempty(infiles), 0148 infiles=cell(1,length(infname)); %preallocate mem 0149 for a=1:length(infname), 0150 infiles{a}=[inpath infname{a}]; 0151 end 0152 else 0153 n_files=length(infiles); 0154 ct=0; 0155 for a=(n_files+1):(n_files+length(infname)), 0156 ct=ct+1; 0157 infiles{a}=[inpath infname{ct}]; 0158 end 0159 end 0160 % trigger GUI to see if user wants to load more 0161 resp=questdlg('Do you want to load more files?',... 0162 'tfrs2tfrGND','Yes','No','Yes'); 0163 if strcmpi(resp,'No'), 0164 loading=0; 0165 end 0166 end 0167 end 0168 elseif iscell(p.Results.gui_infiles_or_tmplt) 0169 infiles=p.Results.gui_infiles_or_tmplt; 0170 else 0171 if isempty(p.Results.sub_ids) 0172 error('If gui_infiles_or_tmplt is a string filename template, you must specify the subject numbers with the argument ''sub_ids''.'); 0173 elseif ~ismember('#',p.Results.gui_infiles_or_tmplt), 0174 error('The filename template %s needs to contain a # to indicate where the subject numbers go (e.g., odbl#.nrm).', ... 0175 p.Results.gui_infiles_or_tmplt); 0176 else 0177 lb_id=find(p.Results.gui_infiles_or_tmplt=='#'); 0178 prefix=p.Results.gui_infiles_or_tmplt(1:(lb_id(1)-1)); %indexing lb_id by 1 in case there are multiple pound signs 0179 postfix=p.Results.gui_infiles_or_tmplt((lb_id(1)+1):end); 0180 n_infiles=length(p.Results.sub_ids); 0181 infiles=cell(1,n_infiles); 0182 for s=1:n_infiles, 0183 no_pad=[prefix num2str(p.Results.sub_ids(s)) postfix]; 0184 if p.Results.sub_ids(s)<10, 0185 padded=[prefix num2str(p.Results.sub_ids(s),'%.2d') postfix]; 0186 [sP wP]=unix(['ls ' padded]); %if sp==0, then the file exists, need wP argument so that it isn't automatically displayed in command window 0187 [sNP wNP]=unix(['ls ' no_pad]); %Need wP argument so that it isn't automatically displayed in command window 0188 if ~sP 0189 if ~sNP, 0190 error('You have a file named %s and one named %s. I don''t know which one to load!\n', ... 0191 padded,no_pad); 0192 else 0193 infiles{s}=padded; 0194 end 0195 else 0196 infiles{s}=no_pad; 0197 end 0198 else 0199 infiles{s}=no_pad; 0200 end 0201 end 0202 end 0203 end 0204 0205 %Get rid of any redundant input files 0206 tfr_fnames=unique(infiles); 0207 n_subs=length(tfr_fnames); 0208 0209 for sub=1:n_subs, 0210 fprintf('Loading data from file: %s\n',tfr_fnames{sub}); 0211 load(tfr_fnames{sub},'-MAT'); 0212 if sub==1, 0213 n_bins=length(TFR.bindesc); 0214 if isempty(p.Results.use_bins), 0215 use_bins=1:n_bins; 0216 else 0217 use_bins=p.Results.use_bins; 0218 if max(use_bins)>n_bins, 0219 error('This file only has %d bins, but you requested importing bin %d.\n', ... 0220 n_bins,max(use_bins)); 0221 end 0222 end 0223 n_use_bins=length(use_bins); 0224 0225 n_chans=length(TFR.bins{1}.label); 0226 n_freqs=length(TFR.bins{1}.freq); 0227 n_tpts=length(TFR.bins{1}.time); 0228 0229 %Initialize tfrGND variable 0230 tfrGND.filename=[]; 0231 tfrGND.filepath=[]; 0232 tfrGND.exp_name=TFR.exp_name; 0233 tfrGND.tfr_fnames=tfr_fnames; 0234 tfrGND.grands=cell(1,n_use_bins); 0235 tfrGND.indiv=cell(1,n_use_bins); 0236 tfrGND.ftrip=TFR.bins{1}; %fieldtrip template into which we can plug whatever 0237 %power spectrum we want when we need to use fieldtrip functions 0238 tfrGND.ftrip.powspctrm=[]; %erase whatever data were there to lessen variable size a bit 0239 tfrGND.bindesc=TFR.bindesc; 0240 tfrGND.bsln_wind=TFR.bsln_wind; 0241 tfrGND.bsln_type=TFR.bsln_type; 0242 tfrGND.units=TFR.units; 0243 tfrGND.chanlocs=TFR.chanlocs; 0244 0245 for b=1:n_use_bins, 0246 tfrGND.indiv{b}=zeros(n_subs,n_chans,n_freqs,n_tpts); 0247 tfrGND.indiv{b}(sub,:,:,:)=TFR.bins{b}.powspctrm; 0248 tfrGND.grands{b}=TFR.bins{b}.powspctrm./n_subs; %running sum computes grand average 0249 0250 % ?? should check to make sure a participant contributes trials 0251 % to a bin before averaging? 0252 end 0253 0254 tfrGND.saved='no'; 0255 tfrGND.stats=[]; 0256 else 0257 %Check for consistency with previously loaded files 0258 if ~isequal(tfrGND.bindesc,TFR.bindesc), 0259 error('File %s has a different bin descriptor than file %s.', ... 0260 tfr_fnames{sub},tfr_fnames{1}); 0261 end 0262 if ~isequal(tfrGND.exp_name,TFR.exp_name), 0263 watchit(sprintf('File %s has a different bin descriptor than file %s.\n Using %s.\n', ... 0264 tfr_fnames{sub},tfr_fnames{1},tfrGND.exp_name)); 0265 end 0266 if ~isequal(tfrGND.ftrip.elec,TFR.bins{1}.elec), 0267 error('File %s has different electrode info than file %s.', ... 0268 tfr_fnames{sub},tfr_fnames{1}); 0269 end 0270 if ~isequal(tfrGND.ftrip.time,TFR.bins{1}.time), 0271 error('File %s has different time points than file %s.', ... 0272 tfr_fnames{sub},tfr_fnames{1}); 0273 end 0274 if ~isequal(tfrGND.ftrip.freq,TFR.bins{1}.freq), 0275 error('File %s has different frequencies than file %s.', ... 0276 tfr_fnames{sub},tfr_fnames{1}); 0277 end 0278 0279 if ~isequal(tfrGND.bsln_wind,TFR.bsln_wind), 0280 error('File %s has a different baseline window than file %s.', ... 0281 tfr_fnames{sub},tfr_fnames{1}); 0282 end 0283 0284 if ~isequal(tfrGND.bsln_type,TFR.bsln_type), 0285 error('File %s has a different baseline type than file %s.', ... 0286 tfr_fnames{sub},tfr_fnames{1}); 0287 end 0288 0289 if ~isequal(tfrGND.units,TFR.units), 0290 if strcmpi(tfrGND.units,'dB'), 0291 error('Data in file %s are NOT in units of dB but those in file %s are.', ... 0292 tfr_fnames{sub},tfr_fnames{1}); 0293 else 0294 error('Data in file %s are in units of dB but those in file %s are NOT.', ... 0295 tfr_fnames{sub},tfr_fnames{1}); 0296 end 0297 end 0298 0299 if ~isequal(tfrGND.chanlocs,TFR.chanlocs), 0300 error('File %s has a different TFR.chanlocs information than file %s.', ... 0301 tfr_fnames{sub},tfr_fnames{1}); 0302 end 0303 0304 for b=1:n_use_bins, 0305 tfrGND.indiv{b}(sub,:,:,:)=TFR.bins{b}.powspctrm; 0306 tfrGND.grands{b}=tfrGND.grands{b}+TFR.bins{b}.powspctrm./n_subs; %running sum computes grand average 0307 end 0308 end 0309 0310 %clear big variable to make way for new big variable 0311 clear TFR 0312 end 0313 0314 %% Transform spectrograms to dB or re-baseline (if requested) 0315 bsln_wind=p.Results.bsln_wind; 0316 bsln_type=p.Results.bsln_type; 0317 units=p.Results.units; 0318 if isempty(bsln_wind), 0319 bsln_wind=tfrGND.bsln_wind; 0320 end 0321 if isempty(bsln_type), 0322 bsln_type=tfrGND.bsln_type; 0323 end 0324 if isempty(units), 0325 units=tfrGND.units; 0326 end 0327 if ~strcmpi(units,tfrGND.units) || ... 0328 ~isequal(bsln_wind,tfrGND.bsln_wind) || ... 0329 ~strcmpi(bsln_type,tfrGND.bsln_type) 0330 tfrGND=baseline_tfrGND(tfrGND,units,bsln_wind,bsln_type); 0331 end 0332 0333 0334 %% Save tfrGND variable 0335 if isempty(p.Results.out_fname), 0336 %Create GUI 0337 [jname, jpath]=uiputfile({'*.tfrGND','*.tfrGND files'; ... 0338 '*','All files'},'Save tfrGND variable as:','untitled.tfrGND'); 0339 if ~jpath, 0340 fprintf('Output filename selection cancelled. tfrGND variable NOT saved to disk.\n'); 0341 else 0342 %test to make sure file can be created 0343 isW=isWriteable([jpath jname]); 0344 if isW, 0345 tfrGND=save_matmk(tfrGND,jname,jpath,1); % 1 means that user won't be asked again about saving file 0346 else 0347 fprintf('tfrGND file could not be saved, but should still exist in MATLAB workspace.'); 0348 end 0349 end 0350 elseif ~strcmpi(p.Results.out_fname,'no save'), 0351 [jpath, jname]=pathNname(p.Results.out_fname); 0352 %Add .tfrGND extension if no extension given 0353 if ~ismember('.',jname), 0354 jname=[jname '.tfrGND']; 0355 end 0356 tfrGND=save_matmk(tfrGND,jname,jpath); 0357 end 0358 0359 0360 %%%%%%% END OF MAIN FUNCTION %%%%%%% 0361 0362 0363 function isW = isWriteable(inFile) 0364 % Function checks to make sure "inFile" can be written to disk. "inFile" is 0365 % not modified by the function. 0366 % 0367 % Author: Tom Urbach 0368 % 0369 0370 isW = 0; 0371 [fid, message] = fopen(inFile,'a+'); 0372 if (fid ~= -1) 0373 isW = 1; 0374 fclose(fid); 0375 else 0376 fprintf('Error opening %s: %s\n', inFile, message); 0377 end 0378