spec_topo() - Plots scalp topographies of spectral power averaged across time and frequencies. Data are taken from TFR or tfrGND variables and a single bin or the difference between bins. Topographies follow EEGLAB conventions (rather than FieldTrip conventions) and individual electrodes can be highlighted with white markers. Usage: >> spec_topo(spec_var_or_fname,bin,time_wind,freq_band,varargin) Required Inputs: spec_var_or_fname - A TFR or tfrGND structure variable or the filename of such a variable that has been saved to disk. If you specifiy a filename be sure to include the file's path, unless the file is in the current working directory. bin - [string] Indicates the number of the bin or the bin difference you wish to plot. For example, if you wish to plot the spectrograms for Bin 1, enter '1' or 1. If you want to plot the spectrograms for Bin 1 minus those from Bin 2, enter '1=2'. time_wind - n by 2 matrix of times (in milliseconds) indicating the starting and stopping points of n time windows to average over. If n>1, a topography will be created for each time window (i.e., n topographies). Also note that if n>1, either one or n pairs of values must be input for the freq_band variable. If n pairs of time_wind values are input and only 1 pair for freq_band values are input, the topographies will represent the mean power in the same frequency band in the n time windows. freq_band - n by 2 matrix of frequencies (in Hz) indicating the starting and stopping points of n frequency bands to average over. If n>1, a topography will be created for each frequency band (i.e., n topographies). Also note that if n>1, either one or n pairs of values must be input for the time_wind variable. If n pairs of freq_band values are input and only 1 pair for time_wind values are input, the topographies will represent the mean power in the same time window for the n frequency bands. Optional Inputs: 'maplimits' - ['maxmin' or 'absmax'] If 'maxmin', topography color scale will range from the lowest value in each topography to the highest value in each topography. If 'absmax', topography color scale will range from -1*the greatest absolute value of each topography to the greatest absolute value of each topograhy. Note if 'one_scale' option input is used, the color scale is based on the full set of topographies. 'one_scale' - [1 or 0] If 1, all topographies are plot using a single color scale. If 0, each topography gets its own color scale. {default: 0} 'units' - ['raw' or 'dB'] If 'raw' topographies will be processed in units of (uV^2)/Hz). If 'dB' spectral power will be shown in decibels (10*log10((uV^2)/Hz)). Note, using a relative baseline for raw data produces unitless values. {default: whatever units data are already stored in} 'bsln_wind' - [start_time end_time] Temporal boundaries of baseline window (in units of ms). {default: keep baseline window the same as it currently is} 'bsln_type' - ['absolute' or 'relative'] Type of baseline normalization. If 'absolute', the mean power in the baseline window is subtracted from the rest of the time points. If 'relative', the mean power in the baseline window is divided from the rest of the time points. {default: keep baseline type the same as it currently is}. 'fig_id' - [integer] The index # of the MATLAB figure in which the diagram will be produced. Useful for overwriting old figures. {default: lowest unused index} 'sub_id' - [integer] The number of the subject whose individual data you wish to plot from a tfrGND variable. If not specified and a tfrGND variable was input, grand average data will be plot. If a TFR variable was input, 'sub_id' will have no effect. {default: not specified} 'title_on' - [1 or 0] If 1, a title indicating the bin(s) # and bin descriptor(s) will be added to the figure. If 0, no title will be added. {default: 1} 'sig_chans' - [string or cell array of strings] Names of channel(s) to highlight with white marker(s) (e.g., 'MiCe' or {'MiCe','MiPa'}). Useful for indicating channels with significant effects. {default: none} '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) Global Variable: 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' Notes: -The printed/exported figure will have the same dimensions as the figure on the display. Thus you can undo figure clutter by re-sizing it. -You need data at least three channels to interpolate a scalp topography. -It may not be possible to use the exact time windows or frequency bands specified by the user due to the limited temporal and frequency resolution of the TFR or tfrGND variable. This function will try to match the time windows and frequency bands as closely as possible, but they may differ slightly from the specified ranges. Examples: -Plotting mean spectrogram power in 8 to 12 Hz frequency band from 400 to 600 ms. Data taken from Bin 1 a single participant's TFR variable: >>spec_topo(TFR,1,[400 600],[8 12]); -Plotting mean difference in spectrogram power in 8 to 12 Hz frequency band from 400 to 600 ms and 700 to 1000 ms. The difference is between Bin 2 and Bin 1 and data are taken from grand averages in a tfrGND variable: >>spec_topo(tfrGND,'2-1',[400 600; 700 1000],[8 12]); -Plotting mean difference in spectrogram power in 8 to 12 Hz and 40 to 80 Hz frequency band from 400 to 600 ms ms. The difference is between Bin 2 and Bin 1 and data are taken from a single participant's TFR variable. In addition, channels MiCe and MiPa will be marked in white. >>spec_topo(TFR,'2-1',[400 600],[8 12; 40 80],,'sig_chans',{'MiCe','MiPa'}); -Plotting mean spectrogram power in 8 to 12 Hz frequency band from 400 to 600 ms and 40 to 80 Hz from 700 to 1000 ms. Data taken from grand averages in a tfrGND variable: >>spec_topo(tfrGND,1,[400 600; 700 1000],[8 12; 40 80]); Author: David Groppe Kutaslab, 4/2011
0001 % spec_topo() - Plots scalp topographies of spectral power averaged across 0002 % time and frequencies. Data are taken from TFR or tfrGND 0003 % variables and a single bin or the difference between bins. 0004 % Topographies follow EEGLAB conventions (rather than 0005 % FieldTrip conventions) and individual electrodes can be 0006 % highlighted with white markers. 0007 % 0008 % Usage: 0009 % >> spec_topo(spec_var_or_fname,bin,time_wind,freq_band,varargin) 0010 % 0011 % Required Inputs: 0012 % spec_var_or_fname - A TFR or tfrGND structure variable or the 0013 % filename of such a variable that has 0014 % been saved to disk. If you specifiy a filename be 0015 % sure to include the file's path, unless the file is 0016 % in the current working directory. 0017 % bin - [string] Indicates the number of the bin or the bin 0018 % difference you wish to plot. For example, if you 0019 % wish to plot the spectrograms for Bin 1, enter '1' 0020 % or 1. If you want to plot the spectrograms for Bin 1 0021 % minus those from Bin 2, enter '1=2'. 0022 % time_wind - n by 2 matrix of times (in milliseconds) indicating 0023 % the starting and stopping points of n time windows 0024 % to average over. If n>1, a topography will be 0025 % created for each time window (i.e., n topographies). 0026 % Also note that if n>1, either one or n pairs of 0027 % values must be input for the freq_band variable. If 0028 % n pairs of time_wind values are input and only 1 0029 % pair for freq_band values are input, the 0030 % topographies will represent the mean power in the 0031 % same frequency band in the n time windows. 0032 % freq_band - n by 2 matrix of frequencies (in Hz) indicating 0033 % the starting and stopping points of n frequency bands 0034 % to average over. If n>1, a topography will be 0035 % created for each frequency band (i.e., n topographies). 0036 % Also note that if n>1, either one or n pairs of 0037 % values must be input for the time_wind variable. If 0038 % n pairs of freq_band values are input and only 1 0039 % pair for time_wind values are input, the 0040 % topographies will represent the mean power in the 0041 % same time window for the n frequency bands. 0042 % 0043 % Optional Inputs: 0044 % 'maplimits' - ['maxmin' or 'absmax'] If 'maxmin', topography color 0045 % scale will range from the lowest value in each 0046 % topography to the highest value in each topography. 0047 % If 'absmax', topography color scale will range from 0048 % -1*the greatest absolute value of each topography to 0049 % the greatest absolute value of each topograhy. Note 0050 % if 'one_scale' option input is used, the color scale 0051 % is based on the full set of topographies. 0052 % 'one_scale' - [1 or 0] If 1, all topographies are plot using a 0053 % single color scale. If 0, each topography gets its 0054 % own color scale. {default: 0} 0055 % 'units' - ['raw' or 'dB'] If 'raw' topographies will be 0056 % processed in units of (uV^2)/Hz). If 'dB' spectral 0057 % power will be shown in decibels 0058 % (10*log10((uV^2)/Hz)). Note, using a relative 0059 % baseline for raw data produces unitless values. 0060 % {default: whatever units data are already stored in} 0061 % 'bsln_wind' - [start_time end_time] Temporal boundaries of baseline 0062 % window (in units of ms). {default: keep baseline 0063 % window the same as it currently is} 0064 % 'bsln_type' - ['absolute' or 'relative'] Type of baseline 0065 % normalization. If 'absolute', the mean power in the 0066 % baseline window is subtracted from the rest of the time 0067 % points. If 'relative', the mean power in the baseline 0068 % window is divided from the rest of the time points. 0069 % {default: keep baseline type the same as it 0070 % currently is}. 0071 % 'fig_id' - [integer] The index # of the MATLAB figure in which 0072 % the diagram will be produced. Useful for overwriting 0073 % old figures. {default: lowest unused index} 0074 % 'sub_id' - [integer] The number of the subject whose individual 0075 % data you wish to plot from a tfrGND variable. If not 0076 % specified and a tfrGND variable was input, grand 0077 % average data will be plot. If a TFR variable was 0078 % input, 'sub_id' will have no effect. {default: not 0079 % specified} 0080 % 'title_on' - [1 or 0] If 1, a title indicating the bin(s) # and bin 0081 % descriptor(s) will be added to the figure. If 0, no 0082 % title will be added. {default: 1} 0083 % 'sig_chans' - [string or cell array of strings] Names of channel(s) 0084 % to highlight with white marker(s) (e.g., 'MiCe' or 0085 % {'MiCe','MiPa'}). Useful for indicating channels with 0086 % significant effects. {default: none} 0087 % 'verblevel' - An integer specifiying the amount of information you want 0088 % this function to provide about what it is doing during runtime. 0089 % Options are: 0090 % 0 - quiet, only show errors, warnings, and EEGLAB reports 0091 % 1 - stuff anyone should probably know 0092 % 2 - stuff you should know the first time you start working 0093 % with a data set {default value} 0094 % 3 - stuff that might help you debug (show all 0095 % reports) 0096 % 0097 % Global Variable: 0098 % VERBLEVEL - MATLABmk level of verbosity (i.e., tells functions how 0099 % much to report about what they're doing during runtime) 0100 % set by the optional function argument 'verblevel' 0101 % 0102 % Notes: 0103 % -The printed/exported figure will have the same dimensions as the figure 0104 % on the display. Thus you can undo figure clutter by re-sizing it. 0105 % 0106 % -You need data at least three channels to interpolate a scalp topography. 0107 % 0108 % -It may not be possible to use the exact time windows or frequency 0109 % bands specified by the user due to the limited temporal and frequency 0110 % resolution of the TFR or tfrGND variable. This function will try to 0111 % match the time windows and frequency bands as closely as possible, but 0112 % they may differ slightly from the specified ranges. 0113 % 0114 % Examples: 0115 % -Plotting mean spectrogram power in 8 to 12 Hz frequency band from 400 to 0116 % 600 ms. Data taken from Bin 1 a single participant's TFR variable: 0117 % >>spec_topo(TFR,1,[400 600],[8 12]); 0118 % 0119 % -Plotting mean difference in spectrogram power in 8 to 12 Hz frequency 0120 % band from 400 to 600 ms and 700 to 1000 ms. The difference is between 0121 % Bin 2 and Bin 1 and data are taken from grand averages in a tfrGND 0122 % variable: 0123 % >>spec_topo(tfrGND,'2-1',[400 600; 700 1000],[8 12]); 0124 % 0125 % -Plotting mean difference in spectrogram power in 8 to 12 Hz and 40 to 0126 % 80 Hz frequency band from 400 to 600 ms ms. The difference is between 0127 % Bin 2 and Bin 1 and data are taken from a single participant's TFR 0128 % variable. In addition, channels MiCe and MiPa will be marked in white. 0129 % >>spec_topo(TFR,'2-1',[400 600],[8 12; 40 80],,'sig_chans',{'MiCe','MiPa'}); 0130 % 0131 % -Plotting mean spectrogram power in 8 to 12 Hz frequency band from 400 to 0132 % 600 ms and 40 to 80 Hz from 700 to 1000 ms. Data taken from grand averages 0133 % in a tfrGND variable: 0134 % >>spec_topo(tfrGND,1,[400 600; 700 1000],[8 12; 40 80]); 0135 % 0136 % 0137 % Author: 0138 % David Groppe 0139 % Kutaslab, 4/2011 0140 0141 %%%%%%%%%%%%%%%% REVISION LOG %%%%%%%%%%%%%%%%% 0142 % ??/??/20??-?? 0143 0144 %%%%%%%%%%%%%%%% FUTURE WORK %%%%%%%%%%%%%%%%% 0145 % -add test_id option to plot the results of specific tests? 0146 % -make it possible to show differences in units of t-scores? 0147 % -add option to include/exclude chans? 0148 % -use verblevel more? right now it's used once 0149 % -make it possible for user to specifiy numeric arguments for maplimits? 0150 0151 function spec_topo(spec_var_or_fname,bin,time_wind,freq_band,varargin) 0152 0153 p=inputParser; 0154 p.addRequired('spec_var_or_fname',@(x) ischar(x) || isstruct(x)); 0155 p.addRequired('bin',@(x) ischar(x) || isnumeric(x)); %char allows bin differences (e.g., "1-2") 0156 p.addRequired('time_wind',@(x) isnumeric(x)); 0157 p.addRequired('freq_band',@(x) isnumeric(x)); 0158 p.addParamValue('maplimits',[],@(x) (strcmpi(x,'absmax') || strcmpi(x,'maxmin'))); 0159 p.addParamValue('units',[],@(x) strcmpi(x,'dB') || strcmpi(x,'raw')); 0160 p.addParamValue('bsln_wind',[],@(x) isnumeric(x) && length(x)==2); 0161 p.addParamValue('bsln_type',[],@(x) strcmpi(x,'relative') || strcmpi(x,'absolute')); 0162 p.addParamValue('fig_id',[],@(x) isnumeric(x) && (length(x)==1)); 0163 p.addParamValue('sub_id',[],@(x) isnumeric(x) && (length(x)==1) && (x>0)); 0164 p.addParamValue('title_on',1,@(x) isnumeric(x) && (length(x)==1)); 0165 p.addParamValue('one_scale',0,@(x) isnumeric(x) && (length(x)==1)); 0166 p.addParamValue('verblevel',[],@(x) isnumeric(x) && (length(x)==1)); 0167 p.addParamValue('sig_chans',[],@(x) ischar(x) || iscell(x)); 0168 0169 p.parse(spec_var_or_fname,bin,time_wind,freq_band,varargin{:}); 0170 0171 % Manage VERBLEVEL 0172 if isempty(p.Results.verblevel), 0173 VERBLEVEL=2; %not global, just local 0174 else 0175 VERBLEVEL=p.Results.verblevel; 0176 end 0177 0178 %Load TFR or tfrGND struct 0179 if ischar(spec_var_or_fname), 0180 fprintf('Loading TFR or tfrGND struct variable from file %s.\n',spec_var_or_fname); 0181 load(spec_var_or_fname,'-MAT'); 0182 if ~exist('TFR','var') && ~exist('tfrGND','var') 0183 error('File %s does not contain a TFR or tfrGND variable.',spec_var_or_fname); 0184 end 0185 if exist('TFR','var'), 0186 spec_var=TFR; %for simplicity TFR variables are re-named spec_var 0187 clear TFR; 0188 elseif exist('tfrGND','var'), 0189 spec_var=tfrGND; %for simplicity tfrGND variables are re-named spec_var 0190 clear tfrGND; 0191 end 0192 VerbReport(sprintf('Experiment: %s',spec_var.exp_name),2,VERBLEVEL); 0193 else 0194 spec_var=spec_var_or_fname; %for simplicity TFR and tfrGND variables are re-named spec_var 0195 clear spec_var_or_fname; 0196 end 0197 0198 grand=isfield(spec_var,'grands'); %1 if spec_var includes grand average data (e.g., spec_var is a tfrGND variable) 0199 0200 %make sure EEGLAB and FieldTrip channel labels are the same 0201 label_compat(spec_var,grand); 0202 0203 if isempty(p.Results.sig_chans), 0204 sig_chans=[]; 0205 else 0206 if ischar(p.Results.sig_chans), 0207 sig_chan_labels{1}=p.Results.sig_chans; 0208 else 0209 sig_chan_labels=p.Results.sig_chans; 0210 end 0211 n_sig_chan=length(sig_chan_labels); 0212 n_chan=length(spec_var.chanlocs); 0213 sig_chans=zeros(1,n_sig_chan); 0214 for s=1:n_sig_chan, 0215 found=0; 0216 for c=1:n_chan, 0217 if strcmpi(spec_var.chanlocs(c).labels,sig_chan_labels{s}), 0218 sig_chans(s)=c; 0219 found=1; 0220 break; 0221 end 0222 end 0223 if ~found, 0224 error('There are no channels called %s in this TFR/tfrGND variable.',sig_chan_labels{s}); 0225 end 0226 end 0227 end 0228 0229 %Figure out how many topos to plot 0230 n_wind=size(time_wind,1); 0231 n_band=size(freq_band,1); 0232 if n_wind==1, 0233 n_topos=n_band; 0234 if n_band>1, 0235 time_wind=repmat(time_wind,n_band,1); 0236 n_wind=n_band; 0237 end 0238 elseif n_band==1, 0239 n_topos=n_wind; 0240 if n_wind>1, 0241 freq_band=repmat(freq_band,n_wind,1); 0242 n_band=n_wind; 0243 end 0244 elseif n_wind==n_band, 0245 n_topos=n_band; 0246 else 0247 error('The number of time windows needs to equal the number of frequency bands or you need to use either a single time window OR frequency band.'); 0248 end 0249 wdth=floor(sqrt(n_topos)); 0250 ht=ceil(n_topos/wdth); 0251 0252 % Copy baseline options into variables that can be overwritten 0253 bsln_wind=p.Results.bsln_wind; 0254 bsln_type=p.Results.bsln_type; 0255 units=p.Results.units; 0256 0257 %See if user has requested the difference between conditions 0258 plot_bins=p.Results.bin; 0259 neg_id=find(plot_bins=='-'); 0260 n_bins=length(spec_var.bindesc); 0261 if ismember('-',plot_bins), 0262 bin1=str2double(plot_bins(1:(neg_id-1))); 0263 bin2=str2double(plot_bins((neg_id+1):end)); 0264 %make sure bins exist 0265 if isempty(bin1) || isempty(bin2), 0266 error('%s is not a valid bin request.',plot_bins); 0267 elseif bin1>n_bins, 0268 error('You only have %d bins in this TFR/tfrGND variable but you requested Bin %d.',n_bins,bin1); 0269 elseif bin2>n_bins, 0270 error('You only have %d bins in this TFR/tfrGND variable but you requested Bin %d.',n_bins,bin2); 0271 end 0272 0273 %take of baseline and unit transformation (if requested) 0274 [spec_var, bsln_type, bsln_wind, units]=bsln_stuff(spec_var,bsln_type,bsln_wind,units,[bin1 bin2],grand); 0275 0276 dif=1; 0277 %Store data to be visualized in powspctrm 0278 prefix=[spec_var.bindesc{bin1} '-' spec_var.bindesc{bin2}]; 0279 if grand, 0280 %tfrGND variable 0281 if isempty(p.Results.sub_id), 0282 %grand average spectrograms 0283 powspctrm=spec_var.grands{bin1}-spec_var.grands{bin2}; 0284 suffix=['(Bin ' int2str(bin1) '-' int2str(bin2) ', Grand)']; 0285 else 0286 %plot spectrogram for an individual subjec 0287 powspctrm=squeeze(spec_var.indiv{bin1}(p.Results.sub_id,:,:,:))- ... 0288 squeeze(spec_var.indiv{bin2}(p.Results.sub_id,:,:,:)); 0289 suffix=['(Bin ' int2str(bin1) '-' int2str(bin2) ', Sub ' int2str(p.Results.sub_id) ')']; 0290 end 0291 else 0292 %TFR variable 0293 powspctrm=spec_var.bins{bin1}.powspctrm-spec_var.bins{bin2}.powspctrm; 0294 suffix=['(Bin ' int2str(bin1) '-' int2str(bin2) ')']; 0295 end 0296 else 0297 %Plot data from a single bin 0298 if ischar(plot_bins) 0299 bin=str2double(plot_bins); 0300 else 0301 bin=plot_bins; 0302 end 0303 if isempty(bin), 0304 error('%s is not a valid bin request.',plot_bins); 0305 end 0306 %make sure bin exists 0307 if bin>n_bins, 0308 error('You only have %d bins in this tfrGND variable but you requested Bin %d.',n_bins,bin); 0309 end 0310 0311 %baseline and unit transformation (if requested) 0312 [spec_var, bsln_type, bsln_wind, units]=bsln_stuff(spec_var,bsln_type,bsln_wind,units,bin,grand); 0313 0314 dif=0; 0315 %Store data to be visualized in powspctrm 0316 prefix=spec_var.bindesc{bin}; 0317 if grand, 0318 %tfrGND variable 0319 if isempty(p.Results.sub_id), 0320 %plot grand average spectrograms 0321 powspctrm=spec_var.grands{bin}; 0322 suffix=['(Bin ' int2str(bin) ', Grand)']; 0323 else 0324 %plot spectrogram for an individual subject 0325 powspctrm=squeeze(spec_var.indiv{bin}(p.Results.sub_id,:,:,:)); 0326 suffix=['(Bin ' int2str(bin) ', Sub ' int2str(p.Results.sub_id) ')']; 0327 end 0328 else 0329 %TFR variable 0330 powspctrm=spec_var.bins{bin}.powspctrm; 0331 suffix=['(Bin ' int2str(bin) ')']; 0332 end 0333 end 0334 if strcmpi(bsln_type,'relative'), 0335 units='% change'; 0336 end 0337 0338 chans=1:length(spec_var.chanlocs); 0339 if length(chans)<3, 0340 watchit('sig_topo.m cannot plot scalp topographies with less than 3 electrodes.'); 0341 return 0342 end 0343 if isempty(p.Results.fig_id) 0344 fig_h=figure; 0345 else 0346 fig_h=figure(p.Results.fig_id); clf; 0347 end 0348 0349 set(fig_h,'name',[prefix ' ' suffix],'paperpositionmode','auto'); 0350 %setting paperpositionmode to 'auto' means that if the figure is manually 0351 %resized, the printed version of the figure will reflect whatever the 0352 %shown size was (at the time of printing) 0353 0354 0355 %Figure out topography colorscale limits 0356 gnrl_maplimits=p.Results.maplimits; 0357 if isempty(gnrl_maplimits), 0358 %use default maplimits 0359 if strcmpi(bsln_type,'none'), 0360 if dif, 0361 gnrl_maplimits='absmax'; 0362 else 0363 %topography is of non-baselined power values, thus the smallest 0364 %possible value is 0 and it doesn't make sense to use maxmin 0365 gnrl_maplimits='maxmin'; 0366 end 0367 elseif strcmpi(bsln_type,'relative') && ~dif, 0368 gnrl_maplimits='maxmin'; 0369 else 0370 gnrl_maplimits='absmax'; 0371 end 0372 end 0373 0374 0375 %Compute mean voltage or spectral power in each time window 0376 mns=zeros(length(chans),n_topos); 0377 freq_lims=zeros(n_topos,2); 0378 time_lims=zeros(n_topos,2); 0379 for w=1:n_topos, 0380 %get time point and frequency IDs 0381 if grand, 0382 %grand average spec_var 0383 0384 %Time Points 0385 start_id=find_tpt(time_wind(w,1)/1000,spec_var.ftrip.time); %convert from ms to sec 0386 end_id=find_tpt(time_wind(w,2)/1000,spec_var.ftrip.time); %convert from ms to sec 0387 used_tpts=start_id:end_id; 0388 0389 if isempty(used_tpts), 0390 error('The time window of %g to %g exceeds the time range of this TFR/tfrGND variable.', ... 0391 time_wind(w,1),time_wind(w,1)); 0392 end 0393 time_lims(w,:)=spec_var.ftrip.time([start_id end_id]); 0394 0395 %Frequencies 0396 start_id=find_tpt(freq_band(w,1),spec_var.ftrip.freq); 0397 end_id=find_tpt(freq_band(w,2),spec_var.ftrip.freq); 0398 used_freqs=start_id:end_id; 0399 0400 if isempty(used_tpts), 0401 error('The frequency band of %g to %g exceeds the frequency range of this TFR/tfrGND variable.', ... 0402 freq_band(w,1),freq_band(w,1)); 0403 end 0404 freq_lims(w,:)=spec_var.ftrip.freq([start_id end_id]); 0405 0406 mns(:,w)=mean(mean(powspctrm(:,used_freqs,used_tpts),3),2); 0407 else 0408 %individual participant spec_var 0409 0410 %Time Points (use time points from Bin 1; all bins should have the 0411 %same time points) 0412 start_id=find_tpt(time_wind(w,1)/1000,spec_var.bins{1}.time); %convert from ms to sec 0413 end_id=find_tpt(time_wind(w,2)/1000,spec_var.bins{1}.time); %convert from ms to sec 0414 used_tpts=start_id:end_id; 0415 0416 if isempty(used_tpts), 0417 error('The time window of %g to %g exceeds the time range of this TFR/tfrGND variable.', ... 0418 time_wind(w,1),time_wind(w,1)); 0419 end 0420 time_lims(w,:)=spec_var.bins{1}.time([start_id end_id]); 0421 0422 0423 %Frequencies (use frequencies from Bin 1; all bins should have the 0424 %same frequencies) 0425 start_id=find_tpt(freq_band(w,1),spec_var.bins{1}.freq); 0426 end_id=find_tpt(freq_band(w,2),spec_var.bins{1}.freq); 0427 used_freqs=start_id:end_id; 0428 0429 if isempty(used_tpts), 0430 error('The frequency band of %g to %g exceeds the frequency range of this TFR/tfrGND variable.', ... 0431 freq_band(w,1),freq_band(w,1)); 0432 end 0433 freq_lims(w,:)=spec_var.bins{1}.freq([start_id end_id]); 0434 0435 mns(:,w)=mean(mean(powspctrm(:,used_freqs,used_tpts),3),2); 0436 end 0437 end 0438 if p.Results.one_scale<=0, 0439 one_scale=0; 0440 maplimits=gnrl_maplimits; 0441 else 0442 one_scale=1; 0443 if strcmpi(gnrl_maplimits,'absmax') 0444 mx=max(max(abs(mns))); 0445 maplimits=[-1 1]*mx; 0446 else 0447 %must be maxmin 0448 mx=max(max(mns)); 0449 mn=min(min(mns)); 0450 maplimits=[mn mx]; 0451 end 0452 end 0453 0454 0455 for a=1:n_topos, 0456 subplot(ht,wdth,a); 0457 0458 mn=mns(:,a); 0459 topoplotMK(mn,spec_var.chanlocs(chans),'emarker2',{sig_chans,'o',[1 1 1],4}, ... 0460 'maplimits',maplimits); 0461 0462 %hh=title(sprintf('%d-%d ms, %g-%g Hz',time_wind(a,1),time_wind(a,2), ... 0463 % freq_band(a,1),freq_band(a,2))); %times & freqs based on specified 0464 % times & freqs 0465 hh=title(sprintf('%g-%g ms, %g-%g Hz',time_lims(a,1)*1000,time_lims(a,2)*1000, ... 0466 freq_lims(a,1),freq_lims(a,2))); %times & freqs based on actual times & freqs 0467 %time limits are converted from seconds to ms 0468 0469 if ~one_scale, 0470 hcb=colorbar; 0471 hy=ylabel(hcb,units); 0472 if ~strcmpi(units,'% change') 0473 if strcmpi(gnrl_maplimits,'absmax') 0474 %color scale will be centered at 0 0475 colorscale_range=range(get(hcb,'YLim')); 0476 y_offset=.005*colorscale_range; %old y_offset was .03 0477 if strcmpi(units,'raw') 0478 set(hy,'rotation',0,'verticalalignment','middle','position',[5.3+n_topos*.2 y_offset 1.0001]); 0479 else 0480 %dB units 0481 set(hy,'rotation',0,'verticalalignment','middle','position',[4.9+n_topos*.2 y_offset 1.0001]); 0482 end 0483 else 0484 %maplimits must be maxmin 0485 colorscale_center=median(get(hcb,'ytick')); 0486 colorscale_range=range(get(hcb,'YLim')); 0487 if strcmpi(units,'raw') 0488 y_offset=.0058*colorscale_range; 0489 set(hy,'rotation',0,'verticalalignment','middle','position',[6.9+n_topos*.2 colorscale_center+y_offset 1.0001]); 0490 else 0491 %dB units 0492 y_offset=.0021*colorscale_range; 0493 set(hy,'rotation',0,'verticalalignment','middle','position',[6.9+n_topos*.2 colorscale_center+y_offset 1.0001]); 0494 end 0495 end 0496 end 0497 end 0498 end 0499 0500 if one_scale, 0501 hcb=cbar_nudge('vert',0,maplimits); 0502 hy=ylabel(hcb,units); 0503 set(hy,'rotation',0,'verticalalignment','middle'); 0504 end 0505 0506 % Plot title of entire figure 0507 if p.Results.title_on, 0508 h=textsc([prefix ' ' suffix],'title'); 0509 set(h,'fontsize',14,'fontweight','bold'); 0510 end 0511 %%%%%%%%%%%%%%%%%%%%%%%%% End of Main Function %%%%%%%%%%%%%%%%%%%%%%%%% 0512 0513 0514 0515 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0516 %% cbar_nudge (plots colorbar slightly to left of cbar.m 0517 % search for "DG change" to find the line I edited 0518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0519 function [handle]=cbar_nudge(arg,colors,minmax, grad) 0520 0521 if nargin < 2 0522 colors = 0; 0523 end 0524 posscale = 'off'; 0525 if nargin < 1 0526 arg = 'vert'; 0527 ax = []; 0528 else 0529 if isempty(arg) 0530 arg = 0; 0531 end 0532 if arg(1) == 0 0533 ax = []; 0534 arg = 'vert'; 0535 elseif strcmpi(arg, 'pos') 0536 ax = []; 0537 arg = 'vert'; 0538 posscale = 'on'; 0539 else 0540 if isstr(arg) 0541 ax = []; 0542 else 0543 ax = arg; 0544 arg = []; 0545 end 0546 end 0547 end 0548 0549 if nargin>2 0550 if size(minmax,1) ~= 1 | size(minmax,2) ~= 2 0551 help cbar 0552 fprintf('cbar() : minmax arg must be [min,max]\n'); 0553 return 0554 end 0555 end 0556 if nargin < 4 0557 grad = 5; 0558 end; 0559 0560 0561 %%%%%%%%%%%%%%%%%%%%%%%%%%% 0562 % Choose colorbar position 0563 %%%%%%%%%%%%%%%%%%%%%%%%%%% 0564 0565 if (length(colors) == 1) & (colors == 0) 0566 t = caxis; 0567 else 0568 t = [0 1]; 0569 end 0570 if ~isempty(arg) 0571 if strcmp(arg,'vert') 0572 cax = gca; 0573 pos = get(cax,'Position'); 0574 stripe = 0.04; 0575 edge = 0.01; 0576 space = -.02; 0577 0578 set(cax,'Position',[pos(1) pos(2) pos(3) pos(4)]) 0579 rect = [pos(1)+pos(3)+space pos(2) stripe*pos(3) pos(4)]; 0580 ax = axes('Position', rect); 0581 elseif strcmp(arg,'horiz') 0582 cax = gca; 0583 pos = get(cax,'Position'); 0584 stripe = 0.075; 0585 space = .1; 0586 set(cax,'Position',... 0587 [pos(1) pos(2)+(stripe+space)*pos(4) pos(3) (1-stripe-space)*pos(4)]) 0588 rect = [pos(1) pos(2) pos(3) stripe*pos(4)]; 0589 ax = axes('Position', rect); 0590 end 0591 else 0592 pos = get(ax,'Position'); 0593 if pos(3) > pos(4) 0594 arg = 'horiz'; 0595 else 0596 arg = 'vert'; 0597 end 0598 end 0599 0600 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0601 % Draw colorbar using image() 0602 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0603 0604 map = colormap; 0605 n = size(map,1); 0606 0607 if length(colors) == 1 0608 if strcmp(arg,'vert') 0609 if strcmpi(posscale, 'on') 0610 image([0 1],[0 t(2)],[ceil(n/2):n-colors]'); 0611 else 0612 image([0 1],t,[1:n-colors]'); 0613 end; 0614 set(ax,'xticklabelmode','manual') 0615 set(ax,'xticklabel',[],'YAxisLocation','right') 0616 0617 else 0618 image(t,[0 1],[1:n-colors]); 0619 set(ax,'yticklabelmode','manual') 0620 set(ax,'yticklabel',[],'YAxisLocation','right') 0621 end 0622 set(ax,'Ydir','normal','YAxisLocation','right') 0623 0624 else % length > 1 0625 0626 if max(colors) > n 0627 error('Color vector excedes size of colormap') 0628 end 0629 if strcmp(arg,'vert') 0630 image([0 1],t,[colors]'); 0631 set(ax,'xticklabelmode','manual') 0632 set(ax,'xticklabel',[]) 0633 else 0634 image([0 1],t,[colors]); 0635 set(ax,'yticklabelmode','manual') 0636 set(ax,'yticklabel',[],'YAxisLocation','right') 0637 end 0638 set(ax,'Ydir','normal','YAxisLocation','right') 0639 end 0640 0641 %%%%%%%%%%%%%%%%%%%%%%%%% 0642 % Adjust cbar ticklabels 0643 %%%%%%%%%%%%%%%%%%%%%%%%% 0644 0645 if nargin > 2 0646 if strcmp(arg,'vert') 0647 Cax = get(ax,'Ylim'); 0648 else 0649 Cax = get(ax,'Xlim'); 0650 end; 0651 CBTicks = [Cax(1):(Cax(2)-Cax(1))/(grad-1):Cax(2)]; % caxis tick positions 0652 CBLabels = [minmax(1):(minmax(2)-minmax(1))/(grad-1):minmax(2)]; % tick labels 0653 0654 dec = floor(log10(max(abs(minmax)))); % decade of largest abs value 0655 CBLabels = ([minmax]* [ linspace(1,0, grad);linspace(0, 1, grad)]); 0656 if dec<1 0657 CBLabels = round(CBLabels*10^(1-dec))*10^(dec-1); 0658 elseif dec == 1 0659 CBLabels = round(CBLabels*10^(2-dec))*10^(dec-2); 0660 else 0661 CBLabels = round(CBLabels); 0662 end 0663 0664 if strcmp(arg,'vert') 0665 set(ax,'Ytick',CBTicks); 0666 set(ax,'Yticklabel',CBLabels); 0667 else 0668 set(ax,'Xtick',CBTicks); 0669 set(ax,'Xticklabel',CBLabels); 0670 end 0671 end 0672 handle = ax; 0673 0674 %%%%%%%%%%%%%%%%%% 0675 % Adjust cbar tag 0676 %%%%%%%%%%%%%%%%%% 0677 0678 set(ax,'tag','cbar') 0679 0680 0681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0682 function label_compat(spec_var,grand) 0683 %function label_compat(spec_var,grand) 0684 %Checks to make sure EEGLAB and FieldTrip channel labels are the same. 0685 %EEGLAB channel information is what's used for plotting topographies. 0686 0687 n_chan_eeglab=length(spec_var.chanlocs); 0688 if grand, 0689 %Grand average MATLABmk/FieldTrip spectral variable 0690 n_chan_ftrip=length(spec_var.ftrip.label); 0691 0692 %make sure # of channels are the same 0693 if n_chan_ftrip~=n_chan_eeglab, 0694 error('There are EEGLAB coordinates for %d channels but FieldTrip coordinates for %d channels.', ... 0695 n_chan_eeglab,n_chan_ftrip); 0696 end 0697 0698 %make sure channel labels are the same 0699 for a=1:n_chan_eeglab, 0700 if ~strcmpi(spec_var.ftrip.label{a},spec_var.chanlocs(a).labels), 0701 error('EEGLAB and FieldTrip channel labels are incompatible. Channel %d is %s for EEGLAB and %s for FieldTrip.', ... 0702 a,spec_var.chanlocs(a).labels,spec_var.ftrip.label{a}); 0703 end 0704 end 0705 else 0706 %Individual participant MATLABmk/FieldTrip spectral variable 0707 n_chan_ftrip=length(spec_var.bins{1}.label); 0708 0709 %make sure # of channels are the same 0710 if n_chan_ftrip~=n_chan_eeglab, 0711 error('There are EEGLAB coordinates for %d channels but FieldTrip coordinates for %d channels.', ... 0712 n_chan_eeglab,n_chan_ftrip); 0713 end 0714 0715 %make sure channel labels are the same 0716 for a=1:n_chan_eeglab, 0717 if ~strcmpi(spec_var.bins{1}.label{a},spec_var.chanlocs(a).labels), 0718 error('EEGLAB and FieldTrip channel labels are incompatible. Channel %d is %s for EEGLAB and %s for FieldTrip.', ... 0719 a,spec_var.chanlocs(a).labels,spec_var.ftrip.label{a}); 0720 end 0721 end 0722 end 0723 0724 0725 %%%%%%%%%%%%%%%%% 0726 function [spec_var, bsln_type, bsln_wind, units]=bsln_stuff(spec_var,bsln_type,bsln_wind,units,bins,grand) 0727 %function [spec_var, bsln_type, bsln_wind, units]=bsln_stuff(spec_var,bsln_type,bsln_wind,units,bins,grand) 0728 0729 % Transform spectrograms to dB or re-baseline (if requested) 0730 if isempty(bsln_wind), 0731 bsln_wind=spec_var.bsln_wind; 0732 end 0733 if isempty(bsln_type), 0734 bsln_type=spec_var.bsln_type; 0735 end 0736 if isempty(units), 0737 units=spec_var.units; 0738 end 0739 if ~strcmpi(units,spec_var.units) || ... 0740 ~isequal(bsln_wind,spec_var.bsln_wind) || ... 0741 ~strcmpi(bsln_type,spec_var.bsln_type) 0742 if grand, 0743 spec_var=baseline_tfrGND(spec_var,units,bsln_wind,bsln_type,bins); 0744 else 0745 spec_var=baseline_TFR(spec_var,units,bsln_wind,bsln_type,bins); 0746 end 0747 end 0748