Home > matlabmk > tmax_specGRP.m

tmax_specGRP

PURPOSE ^

tmax_specGRP() - Tests the null hypothesis that the grand average voltage

SYNOPSIS ^

function [specGRP, prm_pval, data_t, crit_t]=tmax_specGRP(specGRP_or_fname,bin,varargin)

DESCRIPTION ^

 tmax_specGRP() - Tests the null hypothesis that the grand average voltage
             of a between-subject difference in power spectra is mu
             (usually 0) using a permutation test based on the 
             tmax statistic (e.g., Hemmelmann et al., 2004).  This function  
             requires individual subject power spectra to be stored in a
             "specGRP" structure and outputs the test results in a number 
             of graphical and text formats. For analogous within-subject 
             comparisons use the function tmax_specGND.m. Note, when applied 
             to a bin that is the mean power spectra across two groups 
             (i.e., NOT a difference groups), a one-sample test is executed.
             

 Usage:
  >> [specGRP, prm_pval, data_t, crit_t]=tmax_specGRP(specGRP_or_fname,bin,varargin)

 Required Inputs:
   specGRP_or_fname - A specGRP structure variable or the filename of a specGRP 
                     structure that has been saved to disk.  A specGRP variable 
                     is based on specGND variables. To create a specGRP variable from 
                     specGND variables use specGNDs2specGRP.m.  See MATLABmk 
                     documentation for detailed information about the 
                     format of a specGRP variable. If you specifiy a filename be 
                     sure to include the file's path, unless the file is in 
                     the current working directory.
   bin             - [integer] The bin to contrast against the mean of the
                     null hypothesis. Use the function headinfo_spec.m to see what 
                     bins are stored in a specGRP variable.  Use the function 
                     bin_op_specGRP.m to create a difference wave between two bins 
                     whose significance you can test with this function.

 Optional Inputs:
   tail          - [1 | 0 | -1] An integer specifying the tail of the
                   hypothesis test.  "1" means upper-tailed (i.e., alternative 
                   hypothesis is that the power difference is greater 
                   than mu).  "0" means two-tailed (i.e., alternative hypothesis
                   is that the power difference is not equal to mu).  
                   "-1" means lower-tailed (i.e., alternative hypothesis
                   is that the ERP/difference wave is less than mu).
                   {default: 0}
   alpha         - A number between 0 and 1 specifying the family-wise
                   alpha level of the test. {default: 0.05}
   n_perm        - The number of permutations to use in the test.  As this
                   value increases, the test takes longer to compute and 
                   the results become more reliable.  Manly (1997) suggests 
                   using at least 1000 permutations for an alpha level of 
                   0.05 and at least 5000 permutations for an alpha level 
                   of 0.01. {default: 2500}
   freq_band     - 2D matrix of pairs of frequency values specifying the beginning 
                   and end of one or more frequency bands in Hz (e.g., 
                   [3 8; 8 12]).  Every single frequency in 
                   the frequency band will be individually tested (i.e.,
                   maximal temporal resolution) if mean_band option is
                   NOT used. Note, boundaries of frequency band(s) may not 
                   exactly correspond to desired frequency band boundaries 
                   because of temporal digitization (i.e., you only have
                   samples every so many Hz). {default: 0 Hz to the
                   Nyquist frequency}
   freq_block_dur- [integers] A number or numbers (in Hz) specifying a
                   duration of frequency blocks in which the frequency 
                   windows specified by freq_band will be divided.  For
                   example, if freq_band=[0 40] and freq_block_dur=10,
                   the 0 to 40 Hz frequency band will be sub-divided into
                   10 Hz bands (i.e., freq_band will equal something like
                   [0 9; 10 19; 20 29; 30 39]--depending on your frequency
                   resolution).  This is an easy way to break up larger 
                   frequency bands of interest into smaller bands for 
                   mean band analysis (if the 'mean_band' option is set to
                   'yes').  If you specify multiple frequency bands with
                   'freq_band', you can break them up using durations of
                   different lengths.  For example, if freq_band=[0 10;
                   40 90] and freq_block_dur=[5 10], the first frequency
                   band (0 to 10 Hz) will be broken up into 5 Hz
                   bands and the second band (40 to 90 Hz) will be
                   broken up into 10 Hz bands. {default: not used}
   mean_band     - ['yes' or 'no'] If 'yes', the permutation test will be
                   performed on the mean power within each frequency band 
                   specified by freq_band.  This sacrifices frequency 
                   resolution to increase test power by reducing the number
                   of comparisons.  If 'no', every single frequency within
                   freq_band's frequency bands will be tested individually.
                   {default: 'no'}
   null_mean     - [number] The mean of the null hypothesis (in units of 
                   microvolts). {default: 0}
   exclude_chans - A cell array of channel labels to exclude from the
                   permutation test (e.g., {'A2','lle','rhe'}).  This option 
                   sacrifices spatial resolution to increase test power by 
                   reducing the number of comparisons. Use headinfo_spec.m to see
                   the channel labels stored in the specGRP variable. You cannot
                   use both this option and 'include_chans' (below).{default: 
                   not used, all channels included in test}
   include_chans - A cell array of channel labels to use in the permutation
                   test (e.g., {'A2','lle','rhe'}).  All other channels will
                   be ignored. This option sacrifices spatial resolution to 
                   increase test power by reducing the number of comparisons.
                   Use headinfo_spec.m to see the channel labels stored in the specGRP
                   variable. You cannot use both this option and 
                   'exclude_chans' (above). {default: not used, all channels 
                   included in test}
   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)
   plot_gui      - ['yes' or 'no'] If 'yes', a GUI is created for
                   visualizing the results of the permutation test using the 
                   function gui_pow.m. The GUI vizualizes the grand average 
                   ERPs in each bin via various stats (e.g., t-scores), shows 
                   topographies at individual frequencies, and illustrates 
                   which electrodes significantly differ from the null 
                   hypothesis.  This option does not work if mean_band 
                   option is set to 'yes.' This GUI can be reproduced using
                   the function gui_pow.m. {default: 'yes'}
   plot_raster   - ['yes' or 'no'] If 'yes', a two-dimensional (frequency x channel)
                   binary "raster" diagram is created to illustrate the
                   results of the permutation test.  Significant negative and
                   positive deviations from the null hypothesis are shown
                   as black and white rectangles respectively. Non-
                   significant comparisons are shown as gray rectangles. 
                   Clicking on the rectangles will show you the 
                   corresponding frequency and channel label for that
                   rectangle. This figure can be reproduced with the 
                   function sig_raster.m. {default: 'yes'}
   plot_mn_topo  - ['yes' or 'no'] If 'yes', the topographies of the mean
                   voltages/effects in each frequency band is produced.  More
                   specifically, two figures are produced: one showing the
                   topographies in decibel power the other in t-scores. Significant/
                   nonsignificant comparisons are shown as white/black 
                   electrodes. Clicking on electrodes will show the
                   electrode's name.  This figure can be reproduced with
                   the function sig_topo.m.  This option has NO effect if
                   mean_band option is set to 'no'. {default: 'yes'}
   output_file   - A string indicating the name of a space delimited text
                   file to produce containing the p-values of all comparisons 
                   and the details of the test (e.g., number of permutations, 
                   family-wise alpha level, etc...). If mean_band option is
                   set to 'yes,' t-scores of each comparison are also 
                   included since you cannot derive them from the t-scores
                   at each frequency/electrode in a simple way. When 
                   importing this file into a spreadsheet be sure NOT to count
                   consecutive spaces as multiple delimiters. {default: none}
   save_specGRP  - ['yes' or 'no'] If 'yes', the specGRP variable will be
                   saved to disk after the permutation test is completed 
                   and added to it. User will first be prompted to verify 
                   file name and path. {default: 'yes'}
   reproduce_test- [integer] The number of the permutation test stored in
                   the specGRP variable to reproduce.  For example, if 
                   'reproduce_test' equals 2, the second t-test 
                   stored in the specGRP variable (i.e., specGRP.t_tests(2)) will 
                   be reproduced.  Reproduction is accomplished by setting
                   the random number generator used in the permutation test 
                   to the same initial state it was in when the permutation 
                   test was first applied.

 Outputs:
   specGRP       - specGRP structure variable.  This is the same as
                   the input specGRP variable with one addition: the 
                   field specGRP.t_tests will contain the results of the 
                   permutation test and the test parameters. 
   prm_pval      - A two-dimensional matrix (channel x frequency) of the
                   p-values of each comparison.
   data_t        - A two-dimensional matrix (channel x frequency) of the
                   t-scores of each comparison.
   crit_t        - The critical t-score(s) for the test.  Any t-scores
                   that are more extreme than the critical t-score(s) 
                   significantly deviate from 0.

   Note also that a great deal of information about the test is displayed 
   in the MATLAB command window.  You can easiy record of all this
   information to a text file using the MATLAB command "diary."

 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'

 Notes:
 -To add a bin that is the difference in spectral power between two groups
 to a specGRP variable, use the function "bin_op_specGRP".

 -Unlike a parametric test (e.g., an ANOVA), a discrete set of p-values
 are possible (at most the number of possible permutations).  Since the
 number of possible permutations grows rapdily with the number of
 participants, this is only issue for small sample sizes (e.g., 3
 participants in each group).  When you have such a small sample size, the
 limited number of p-values may make the test overly conservative (e.g., 
 you might be forced to use an alpha level of .0286 since it is the biggest
 possible alpha level less than .05).

 References:
   Manly, B.F.J. (1997) Randomization, bootstrap, and Monte Carlo methods in
 biology. 2nd ed. Chapmn and Hall, London.

   Hemmelmann, et al. (2004) Multivariate tests for the evaluation of
 high-dimensional EEG data. Journal of Neuroscience Methods.


 Author:
 David Groppe
 Kutaslab, 12/2010

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 % tmax_specGRP() - Tests the null hypothesis that the grand average voltage
0002 %             of a between-subject difference in power spectra is mu
0003 %             (usually 0) using a permutation test based on the
0004 %             tmax statistic (e.g., Hemmelmann et al., 2004).  This function
0005 %             requires individual subject power spectra to be stored in a
0006 %             "specGRP" structure and outputs the test results in a number
0007 %             of graphical and text formats. For analogous within-subject
0008 %             comparisons use the function tmax_specGND.m. Note, when applied
0009 %             to a bin that is the mean power spectra across two groups
0010 %             (i.e., NOT a difference groups), a one-sample test is executed.
0011 %
0012 %
0013 % Usage:
0014 %  >> [specGRP, prm_pval, data_t, crit_t]=tmax_specGRP(specGRP_or_fname,bin,varargin)
0015 %
0016 % Required Inputs:
0017 %   specGRP_or_fname - A specGRP structure variable or the filename of a specGRP
0018 %                     structure that has been saved to disk.  A specGRP variable
0019 %                     is based on specGND variables. To create a specGRP variable from
0020 %                     specGND variables use specGNDs2specGRP.m.  See MATLABmk
0021 %                     documentation for detailed information about the
0022 %                     format of a specGRP variable. If you specifiy a filename be
0023 %                     sure to include the file's path, unless the file is in
0024 %                     the current working directory.
0025 %   bin             - [integer] The bin to contrast against the mean of the
0026 %                     null hypothesis. Use the function headinfo_spec.m to see what
0027 %                     bins are stored in a specGRP variable.  Use the function
0028 %                     bin_op_specGRP.m to create a difference wave between two bins
0029 %                     whose significance you can test with this function.
0030 %
0031 % Optional Inputs:
0032 %   tail          - [1 | 0 | -1] An integer specifying the tail of the
0033 %                   hypothesis test.  "1" means upper-tailed (i.e., alternative
0034 %                   hypothesis is that the power difference is greater
0035 %                   than mu).  "0" means two-tailed (i.e., alternative hypothesis
0036 %                   is that the power difference is not equal to mu).
0037 %                   "-1" means lower-tailed (i.e., alternative hypothesis
0038 %                   is that the ERP/difference wave is less than mu).
0039 %                   {default: 0}
0040 %   alpha         - A number between 0 and 1 specifying the family-wise
0041 %                   alpha level of the test. {default: 0.05}
0042 %   n_perm        - The number of permutations to use in the test.  As this
0043 %                   value increases, the test takes longer to compute and
0044 %                   the results become more reliable.  Manly (1997) suggests
0045 %                   using at least 1000 permutations for an alpha level of
0046 %                   0.05 and at least 5000 permutations for an alpha level
0047 %                   of 0.01. {default: 2500}
0048 %   freq_band     - 2D matrix of pairs of frequency values specifying the beginning
0049 %                   and end of one or more frequency bands in Hz (e.g.,
0050 %                   [3 8; 8 12]).  Every single frequency in
0051 %                   the frequency band will be individually tested (i.e.,
0052 %                   maximal temporal resolution) if mean_band option is
0053 %                   NOT used. Note, boundaries of frequency band(s) may not
0054 %                   exactly correspond to desired frequency band boundaries
0055 %                   because of temporal digitization (i.e., you only have
0056 %                   samples every so many Hz). {default: 0 Hz to the
0057 %                   Nyquist frequency}
0058 %   freq_block_dur- [integers] A number or numbers (in Hz) specifying a
0059 %                   duration of frequency blocks in which the frequency
0060 %                   windows specified by freq_band will be divided.  For
0061 %                   example, if freq_band=[0 40] and freq_block_dur=10,
0062 %                   the 0 to 40 Hz frequency band will be sub-divided into
0063 %                   10 Hz bands (i.e., freq_band will equal something like
0064 %                   [0 9; 10 19; 20 29; 30 39]--depending on your frequency
0065 %                   resolution).  This is an easy way to break up larger
0066 %                   frequency bands of interest into smaller bands for
0067 %                   mean band analysis (if the 'mean_band' option is set to
0068 %                   'yes').  If you specify multiple frequency bands with
0069 %                   'freq_band', you can break them up using durations of
0070 %                   different lengths.  For example, if freq_band=[0 10;
0071 %                   40 90] and freq_block_dur=[5 10], the first frequency
0072 %                   band (0 to 10 Hz) will be broken up into 5 Hz
0073 %                   bands and the second band (40 to 90 Hz) will be
0074 %                   broken up into 10 Hz bands. {default: not used}
0075 %   mean_band     - ['yes' or 'no'] If 'yes', the permutation test will be
0076 %                   performed on the mean power within each frequency band
0077 %                   specified by freq_band.  This sacrifices frequency
0078 %                   resolution to increase test power by reducing the number
0079 %                   of comparisons.  If 'no', every single frequency within
0080 %                   freq_band's frequency bands will be tested individually.
0081 %                   {default: 'no'}
0082 %   null_mean     - [number] The mean of the null hypothesis (in units of
0083 %                   microvolts). {default: 0}
0084 %   exclude_chans - A cell array of channel labels to exclude from the
0085 %                   permutation test (e.g., {'A2','lle','rhe'}).  This option
0086 %                   sacrifices spatial resolution to increase test power by
0087 %                   reducing the number of comparisons. Use headinfo_spec.m to see
0088 %                   the channel labels stored in the specGRP variable. You cannot
0089 %                   use both this option and 'include_chans' (below).{default:
0090 %                   not used, all channels included in test}
0091 %   include_chans - A cell array of channel labels to use in the permutation
0092 %                   test (e.g., {'A2','lle','rhe'}).  All other channels will
0093 %                   be ignored. This option sacrifices spatial resolution to
0094 %                   increase test power by reducing the number of comparisons.
0095 %                   Use headinfo_spec.m to see the channel labels stored in the specGRP
0096 %                   variable. You cannot use both this option and
0097 %                   'exclude_chans' (above). {default: not used, all channels
0098 %                   included in test}
0099 %   verblevel     - An integer specifiying the amount of information you want
0100 %                   this function to provide about what it is doing during runtime.
0101 %                    Options are:
0102 %                      0 - quiet, only show errors, warnings, and EEGLAB reports
0103 %                      1 - stuff anyone should probably know
0104 %                      2 - stuff you should know the first time you start working
0105 %                          with a data set {default value}
0106 %                      3 - stuff that might help you debug (show all
0107 %                          reports)
0108 %   plot_gui      - ['yes' or 'no'] If 'yes', a GUI is created for
0109 %                   visualizing the results of the permutation test using the
0110 %                   function gui_pow.m. The GUI vizualizes the grand average
0111 %                   ERPs in each bin via various stats (e.g., t-scores), shows
0112 %                   topographies at individual frequencies, and illustrates
0113 %                   which electrodes significantly differ from the null
0114 %                   hypothesis.  This option does not work if mean_band
0115 %                   option is set to 'yes.' This GUI can be reproduced using
0116 %                   the function gui_pow.m. {default: 'yes'}
0117 %   plot_raster   - ['yes' or 'no'] If 'yes', a two-dimensional (frequency x channel)
0118 %                   binary "raster" diagram is created to illustrate the
0119 %                   results of the permutation test.  Significant negative and
0120 %                   positive deviations from the null hypothesis are shown
0121 %                   as black and white rectangles respectively. Non-
0122 %                   significant comparisons are shown as gray rectangles.
0123 %                   Clicking on the rectangles will show you the
0124 %                   corresponding frequency and channel label for that
0125 %                   rectangle. This figure can be reproduced with the
0126 %                   function sig_raster.m. {default: 'yes'}
0127 %   plot_mn_topo  - ['yes' or 'no'] If 'yes', the topographies of the mean
0128 %                   voltages/effects in each frequency band is produced.  More
0129 %                   specifically, two figures are produced: one showing the
0130 %                   topographies in decibel power the other in t-scores. Significant/
0131 %                   nonsignificant comparisons are shown as white/black
0132 %                   electrodes. Clicking on electrodes will show the
0133 %                   electrode's name.  This figure can be reproduced with
0134 %                   the function sig_topo.m.  This option has NO effect if
0135 %                   mean_band option is set to 'no'. {default: 'yes'}
0136 %   output_file   - A string indicating the name of a space delimited text
0137 %                   file to produce containing the p-values of all comparisons
0138 %                   and the details of the test (e.g., number of permutations,
0139 %                   family-wise alpha level, etc...). If mean_band option is
0140 %                   set to 'yes,' t-scores of each comparison are also
0141 %                   included since you cannot derive them from the t-scores
0142 %                   at each frequency/electrode in a simple way. When
0143 %                   importing this file into a spreadsheet be sure NOT to count
0144 %                   consecutive spaces as multiple delimiters. {default: none}
0145 %   save_specGRP  - ['yes' or 'no'] If 'yes', the specGRP variable will be
0146 %                   saved to disk after the permutation test is completed
0147 %                   and added to it. User will first be prompted to verify
0148 %                   file name and path. {default: 'yes'}
0149 %   reproduce_test- [integer] The number of the permutation test stored in
0150 %                   the specGRP variable to reproduce.  For example, if
0151 %                   'reproduce_test' equals 2, the second t-test
0152 %                   stored in the specGRP variable (i.e., specGRP.t_tests(2)) will
0153 %                   be reproduced.  Reproduction is accomplished by setting
0154 %                   the random number generator used in the permutation test
0155 %                   to the same initial state it was in when the permutation
0156 %                   test was first applied.
0157 %
0158 % Outputs:
0159 %   specGRP       - specGRP structure variable.  This is the same as
0160 %                   the input specGRP variable with one addition: the
0161 %                   field specGRP.t_tests will contain the results of the
0162 %                   permutation test and the test parameters.
0163 %   prm_pval      - A two-dimensional matrix (channel x frequency) of the
0164 %                   p-values of each comparison.
0165 %   data_t        - A two-dimensional matrix (channel x frequency) of the
0166 %                   t-scores of each comparison.
0167 %   crit_t        - The critical t-score(s) for the test.  Any t-scores
0168 %                   that are more extreme than the critical t-score(s)
0169 %                   significantly deviate from 0.
0170 %
0171 %   Note also that a great deal of information about the test is displayed
0172 %   in the MATLAB command window.  You can easiy record of all this
0173 %   information to a text file using the MATLAB command "diary."
0174 %
0175 % Global Variables:
0176 %   VERBLEVEL = MATLABmk level of verbosity (i.e., tells functions how much
0177 %               to report about what they're doing during runtime) set by
0178 %               the optional function argument 'verblevel'
0179 %
0180 % Notes:
0181 % -To add a bin that is the difference in spectral power between two groups
0182 % to a specGRP variable, use the function "bin_op_specGRP".
0183 %
0184 % -Unlike a parametric test (e.g., an ANOVA), a discrete set of p-values
0185 % are possible (at most the number of possible permutations).  Since the
0186 % number of possible permutations grows rapdily with the number of
0187 % participants, this is only issue for small sample sizes (e.g., 3
0188 % participants in each group).  When you have such a small sample size, the
0189 % limited number of p-values may make the test overly conservative (e.g.,
0190 % you might be forced to use an alpha level of .0286 since it is the biggest
0191 % possible alpha level less than .05).
0192 %
0193 % References:
0194 %   Manly, B.F.J. (1997) Randomization, bootstrap, and Monte Carlo methods in
0195 % biology. 2nd ed. Chapmn and Hall, London.
0196 %
0197 %   Hemmelmann, et al. (2004) Multivariate tests for the evaluation of
0198 % high-dimensional EEG data. Journal of Neuroscience Methods.
0199 %
0200 %
0201 % Author:
0202 % David Groppe
0203 % Kutaslab, 12/2010
0204 
0205 %%%%%%%%%%%%%%%% REVISION LOG %%%%%%%%%%%%%%%%%
0206 % ?/?/2010-??
0207 %
0208 
0209 function [specGRP, prm_pval, data_t, crit_t]=tmax_specGRP(specGRP_or_fname,bin,varargin)
0210 
0211 global VERBLEVEL;
0212 
0213 p=inputParser;
0214 p.addRequired('specGRP_or_fname',@(x) ischar(x) || isstruct(x));
0215 p.addRequired('bin',@(x) isnumeric(x) && (length(x)==1) && (x>0));
0216 p.addParamValue('tail',0,@(x) isnumeric(x) && (length(x)==1));
0217 p.addParamValue('alpha',0.05,@(x) isnumeric(x) && (x>0) && (x<1));
0218 p.addParamValue('freq_band',[],@(x) isnumeric(x) && (size(x,2)==2)); 
0219 p.addParamValue('freq_block_dur',[],@isnumeric);
0220 p.addParamValue('mean_band','no',@(x) ischar(x) && (strcmpi(x,'yes') || strcmpi(x,'no')));
0221 p.addParamValue('n_perm',2500,@(x) isnumeric(x) && (length(x)==1));
0222 p.addParamValue('null_mean',0,@(x) isnumeric(x) && (length(x)==1));
0223 p.addParamValue('verblevel',[],@(x) isnumeric(x) && (length(x)==1));
0224 p.addParamValue('exclude_chans',[],@(x) ischar(x) || iscell(x));
0225 p.addParamValue('include_chans',[],@(x) ischar(x) || iscell(x));
0226 p.addParamValue('plot_gui','yes',@(x) ischar(x) && (strcmpi(x,'yes') || strcmpi(x,'no')));
0227 p.addParamValue('plot_raster','yes',@(x) ischar(x) && (strcmpi(x,'yes') || strcmpi(x,'no')));
0228 p.addParamValue('plot_mn_topo',[],@(x) ischar(x) && (strcmpi(x,'yes') || strcmpi(x,'no')));
0229 p.addParamValue('output_file',[],@ischar);
0230 p.addParamValue('reproduce_test',[],@(x) isnumeric(x) && (length(x)==1));
0231 p.addParamValue('save_specGRP','yes',@(x) ischar(x) && (strcmpi(x,'yes') || strcmpi(x,'no')));
0232 
0233 p.parse(specGRP_or_fname,bin,varargin{:});
0234 
0235 
0236 if isempty(p.Results.verblevel),
0237     if isempty(VERBLEVEL),
0238         VERBLEVEL=2;
0239     end
0240 else
0241    VERBLEVEL=p.Results.verblevel; 
0242 end
0243     
0244 mean_band=str2bool(p.Results.mean_band);
0245 
0246 %Load specGRP struct
0247 if ischar(specGRP_or_fname),
0248     fprintf('Loading specGRP struct from file %s.\n',specGRP_or_fname);
0249     load(specGRP_or_fname,'-MAT');
0250 else
0251     specGRP=specGRP_or_fname;
0252     clear specGRP_or_fname;
0253 end
0254 [n_chan, n_pt, n_bin]=size(specGRP.grands_pow_dB);
0255 n_group=length(specGRP.specGND_fnames);
0256 VerbReport(sprintf('Experiment: %s',specGRP.exp_desc),2,VERBLEVEL);
0257 
0258 if (bin>n_bin),
0259     error('There is no Bin %d in this specGRP variable.',bin); 
0260 end
0261 grpA=specGRP.bin_info(bin).groupA;
0262 grpB=specGRP.bin_info(bin).groupB;
0263 
0264 
0265 %% Figure out which channels to ignore if any
0266 %But first make sure exclude & include options were not both used.
0267 if ~isempty(p.Results.include_chans) && ~isempty(p.Results.exclude_chans)
0268     error('You cannot use BOTH ''include_chans'' and ''exclude_chans'' options.');
0269 end
0270 if ischar(p.Results.exclude_chans),
0271     exclude_chans{1}=p.Results.exclude_chans;
0272 elseif isempty(p.Results.exclude_chans)
0273     exclude_chans=[];
0274 else
0275     exclude_chans=p.Results.exclude_chans;
0276 end
0277 if ischar(p.Results.include_chans),
0278     include_chans{1}=p.Results.include_chans;
0279 elseif isempty(p.Results.include_chans)
0280     include_chans=[];
0281 else
0282     include_chans=p.Results.include_chans;
0283 end
0284 
0285 % exclude and include chan options
0286 if ~isempty(exclude_chans),
0287     ignore_chans=zeros(1,length(exclude_chans)); %preallocate mem
0288     ct=0;
0289     for x=1:length(exclude_chans),
0290         found=0;
0291         for c=1:n_chan,
0292             if strcmpi(exclude_chans{x},specGRP.chanlocs(c).labels),
0293                 found=1;
0294                 ct=ct+1;
0295                 ignore_chans(ct)=c;
0296             end
0297         end
0298         if ~found,
0299             watchit(sprintf('I attempted to exclude %s.  However no such electrode was found in specGRP variable.', ...
0300                 exclude_chans{x}));
0301         end
0302     end
0303     ignore_chans=ignore_chans(1:ct);
0304     use_chans=setdiff(1:n_chan,ignore_chans);
0305 elseif ~isempty(include_chans),
0306     use_chans=zeros(1,length(include_chans)); %preallocate mem
0307     ct=0;
0308     for x=1:length(include_chans),
0309         found=0;
0310         for c=1:n_chan,
0311             if strcmpi(include_chans{x},specGRP.chanlocs(c).labels),
0312                 found=1;
0313                 ct=ct+1;
0314                 use_chans(ct)=c;
0315             end
0316         end
0317         if ~found,
0318             watchit(sprintf('I attempted to include %s.  However no such electrode was found in specGRP variable.', ...
0319                 include_chans{x}));
0320         end
0321     end
0322     use_chans=use_chans(1:ct);
0323 else
0324     use_chans=1:n_chan;
0325 end
0326 
0327 
0328 %% Find frequency ids
0329 if isempty(p.Results.freq_band),
0330     freq_band=[0 specGRP.freqs(end)]; %default frequency band
0331 else
0332     freq_band=p.Results.freq_band;
0333 end
0334 freq_band=sort(freq_band,2); %first make sure earlier of each pair of frequencies is first
0335 freq_band=sort(freq_band,1); %next sort frequency bands from earliest to latest onset
0336 n_band=size(freq_band,1);
0337 if ~isempty(p.Results.freq_block_dur),
0338     fbd=p.Results.freq_block_dur;
0339     n_block=length(fbd);
0340     if (n_block>1) && (n_block~=n_band),
0341        error('If you specify more than one frequency block duration you need to provide exactly one duration for every frequency (in this case %d).',n_band); 
0342     elseif (n_block==1) && (n_band>1),
0343         fbd=repmat(fbd,1,n_band);
0344     end
0345         
0346     f_bands=[];
0347     one_step=1000/specGRP.srate;
0348     for a=1:n_band,
0349         band_strt=freq_band(a,1);
0350         band_stop=freq_band(a,2);
0351         new_bands=[band_strt:fbd(a):band_stop];
0352         for b=1:(length(new_bands)-1),
0353             f_bands=[f_bands; new_bands(b) new_bands(b+1)-one_step];
0354         end
0355     end
0356     freq_band=f_bands;
0357     clear f_bands;
0358     n_band=size(freq_band,1);
0359 end
0360 
0361 if mean_band,
0362     use_frq_ids=cell(1,n_band);
0363 else
0364     use_frq_ids=[];
0365 end
0366 for a=1:n_band,
0367     VerbReport(sprintf('Frequency Band #%d:',a),1,VERBLEVEL);
0368     VerbReport(sprintf('Attempting to use frequency boundaries of %d to %d Hz for hypothesis test.',freq_band(a,1),freq_band(a,2)), ...
0369         1,VERBLEVEL);
0370     start_freq=find_tpt(freq_band(a,1),specGRP.freqs);
0371     end_freq=find_tpt(freq_band(a,2),specGRP.freqs);
0372     if mean_band,
0373         use_frq_ids{a}=[start_freq:end_freq];
0374     else
0375         use_frq_ids=[use_frq_ids [start_freq:end_freq]];
0376     end
0377     %replace desired frequencies with closest matches
0378     freq_band(a,1)=specGRP.freqs(start_freq);
0379     freq_band(a,2)=specGRP.freqs(end_freq);
0380     VerbReport(sprintf('Exact frequency boundaries are %d to %d Hz (that''s from frequency number %d to %d).', ...
0381         freq_band(a,1),freq_band(a,2),start_freq,end_freq),1,VERBLEVEL);
0382 end
0383 if ~mean_band,
0384     use_frq_ids=unique(use_frq_ids); %sorts frequency ids and gets rid of any redundant frequencies
0385 end
0386 
0387 
0388 %% Compile data from two groups of participants
0389 %pre-allocate memory
0390 grp_ct=0;
0391 for grp=[grpA grpB],
0392     grp_ct=grp_ct+1;
0393     if grp_ct==1,
0394         %Group A's bin
0395         ur_bin=specGRP.bin_info(bin).source_binA;
0396     else
0397         %Group B's bin
0398         ur_bin=specGRP.bin_info(bin).source_binB;
0399     end
0400     
0401     %Load specGND variable for this group
0402     load(specGRP.specGND_fnames{grp},'-MAT');
0403     VerbReport(sprintf('Loading individual participant power spectra from Bin %d (%s) of specGND variable from %s.', ...
0404         ur_bin,specGND.bindesc{ur_bin},specGRP.specGND_fnames{grp}),2,VERBLEVEL);
0405     
0406     %Check to make sure frequencies are still compatible across specGND and specGRP
0407     %variables
0408     if ~isequal(specGND.freqs,specGRP.freqs)
0409         error('The frequencies in the specGND variable from file %s are NOT the same as those in your specGRP variable.', ...
0410             specGRP.specGND_fnames{grp});
0411     end
0412     
0413     %Derive channel indexes for this specGND variable in case specGND.chanlocs differs from
0414     %specGRP.chanlocs (in order or in identity of channels)
0415     n_chan_specGND=length(specGND.chanlocs);
0416     use_chans_specGND=[];
0417     for a=use_chans,
0418         found=0;
0419         for b=1:n_chan_specGND,
0420             if strcmpi(specGRP.chanlocs(a).labels,specGND.chanlocs(b).labels),
0421                 found=1;
0422                 use_chans_specGND=[use_chans_specGND b];
0423                 break;
0424             end
0425         end
0426         if ~found,
0427             error('specGND variable in file %s is missing channel %s.',specGRP.specGND_fnames{grp},specGRP.chanlocs(a).labels);
0428         end
0429     end
0430     
0431     %Use only subs with data in relevant bin(s)
0432     use_subs=find(specGND.indiv_bin_ct(:,ur_bin));
0433     n_sub=length(use_subs);
0434     if mean_band,
0435         %Take mean amplitude in frequency band and then test
0436         if grp_ct==1,
0437             %Group A's Power Spectra
0438             n_subA=n_sub;
0439             use_subsA=use_subs;
0440             powA=zeros(length(use_chans),n_band,n_sub);
0441             for a=1:n_band,
0442                 for sub=1:n_sub,
0443                     powA(:,a,sub)=mean(specGND.indiv_pow_dB(use_chans_specGND,use_frq_ids{a},ur_bin,use_subs(sub)),2);
0444                 end
0445             end
0446         else
0447             %Group B's Power Spectra
0448             n_subB=n_sub;
0449             use_subsB=use_subs;
0450             powB=zeros(length(use_chans),n_band,n_sub);
0451             for a=1:n_band,
0452                 for sub=1:n_sub,
0453                     powB(:,a,sub)=mean(specGND.indiv_pow_dB(use_chans_specGND,use_frq_ids{a},ur_bin,use_subs(sub)),2);
0454                 end
0455             end
0456         end
0457     else
0458         %Use every single frequency in frequency band(s)
0459         if grp_ct==1,
0460             %Group A's Power Spectra
0461             n_subA=n_sub;
0462             use_subsA=use_subs;
0463             n_use_frq_ids=length(use_frq_ids);
0464             powA=zeros(length(use_chans),n_use_frq_ids,n_sub);
0465             for sub=1:n_sub,
0466                 powA(:,:,sub)=specGND.indiv_pow_dB(use_chans_specGND,use_frq_ids,ur_bin,use_subs(sub));
0467             end
0468         else
0469             %Group B's Power Spectra
0470             n_subB=n_sub;
0471             use_subsB=use_subs;
0472             n_use_frq_ids=length(use_frq_ids);
0473             powB=zeros(length(use_chans),n_use_frq_ids,n_sub);
0474             for sub=1:n_sub,
0475                 powB(:,:,sub)=specGND.indiv_pow_dB(use_chans_specGND,use_frq_ids,ur_bin,use_subs(sub));
0476             end
0477         end
0478     end
0479 end
0480 df=n_subA+n_subB-2;
0481 
0482 %% Report tail of test & alpha levels
0483 VerbReport(sprintf('Testing null hypothesis that the grand average power spectra in specGRP variable''s Bin %d (%s) have a mean of %f 10*log10((uV^2)/Hz).',bin, ...
0484     specGRP.bin_info(bin).bindesc,p.Results.null_mean),1,VERBLEVEL);
0485 if p.Results.tail==0
0486     VerbReport(sprintf('Alternative hypothesis is that the power spectra differ from %f (i.e., two-tailed test).',p.Results.null_mean), ...
0487         1,VERBLEVEL);
0488 elseif p.Results.tail<0,
0489     VerbReport(sprintf('Alternative hypothesis is that the power spectra are less than %f (i.e., lower-tailed test).',p.Results.null_mean), ...
0490         1,VERBLEVEL);
0491 else
0492     VerbReport(sprintf('Alternative hypothesis is that the power spectra are greater than %f (i.e., upper-tailed test).',p.Results.null_mean), ...
0493         1,VERBLEVEL);
0494 end
0495 
0496 %% Optionally reset random number stream to reproduce a previous test
0497 if isempty(p.Results.reproduce_test),
0498     seed_state=[];
0499 else
0500     if p.Results.reproduce_test>length(specGRP.t_tests),
0501         error('Value of argument ''reproduce_test'' is too high.  You only have %d permutation tests stored with this specGRP variable.',length(specGRP.t_tests));
0502     else
0503         if isnan(specGRP.t_tests(p.Results.reproduce_test).n_perm)
0504             error('t-test set %d is NOT a permutation test. You don''t need to seed the random number generator to reproduce it.', ...
0505                 p.Results.reproduce_test);
0506         else
0507             seed_state=specGRP.t_tests(p.Results.reproduce_test).seed_state;
0508         end
0509     end
0510 end
0511 
0512 %Compute the permutation test
0513 freq_domain=1;
0514 if strcmpi(specGRP.bin_info(bin).op,'(A+B)/n'),
0515     %one sample t-test
0516     VerbReport('Performing one sample/repeated measures t-tests.',1,VERBLEVEL);
0517     powAB=zeros(length(use_chans),size(powA,2),n_subA+n_subB);
0518     powAB(:,:,1:n_subA)=powA-p.Results.null_mean;
0519     powAB(:,:,(n_subA+1):(n_subA+n_subB))=powB-p.Results.null_mean;
0520     [prm_pval, data_t, crit_t, seed_state, est_alpha]=mxt_perm1(powAB,p.Results.n_perm,p.Results.alpha,p.Results.tail,VERBLEVEL,seed_state,freq_domain);
0521 else
0522     %independent samples t-test
0523     VerbReport('Performing independent samples t-tests.',1,VERBLEVEL);
0524     [prm_pval, data_t, crit_t, seed_state, est_alpha]=mxt_perm2(powA-p.Results.null_mean,powB,p.Results.n_perm,p.Results.alpha,p.Results.tail,VERBLEVEL,seed_state,freq_domain);
0525 end
0526 
0527 %Command line summary of results
0528 VerbReport(['Critical t-score(s):' num2str(crit_t)],1,VERBLEVEL);
0529 if p.Results.tail
0530     %one-tailed test
0531     tw_alpha=1-cdf('t',max(abs(crit_t)),df);
0532 else
0533     %two-tailed test
0534     tw_alpha=2-cdf('t',max(crit_t),df)-cdf('t',-min(crit_t),df);
0535 end
0536 VerbReport(sprintf('That corresponds to a test-wise alpha level of %f.',tw_alpha),1,VERBLEVEL);
0537 VerbReport(sprintf('Bonferroni test-wise alpha would be %f.',p.Results.alpha/(size(prm_pval,1)* ...
0538     size(prm_pval,2))),1,VERBLEVEL);
0539 sig_freq_ids=find(sum(prm_pval<p.Results.alpha));
0540 if isempty(sig_freq_ids),
0541     fprintf('Spectral power is NOT significantly different from zero (alpha=%f) at any frequency/band analyzed.\n', ...
0542         p.Results.alpha);
0543     fprintf('All p-values>=%f\n',min(min(prm_pval)));
0544 else
0545     fprintf('Significant differences from zero (in order of lowest to highest frequency):\n');
0546     max_sig_p=0;
0547     %frequency bands instead of individual frequencies
0548     for t=sig_freq_ids,
0549         if mean_band
0550             fprintf('%d to %d Hz, electrode(s): ',specGRP.freqs(use_frq_ids{t}(1)), ...
0551                 specGRP.freqs(use_frq_ids{t}(end)));
0552         else
0553             fprintf('%d Hz, electrode(s): ',specGRP.freqs(use_frq_ids(t)));
0554         end
0555         sig_elec=find(prm_pval(:,t)<p.Results.alpha);
0556         ct=0;
0557         for c=sig_elec',
0558             ct=ct+1;
0559             if prm_pval(c,t)>max_sig_p,
0560                 max_sig_p=prm_pval(c,t);
0561             end
0562             if ct==length(sig_elec),
0563                 fprintf('%s.\n',specGRP.chanlocs(use_chans(c)).labels);
0564             else
0565                 fprintf('%s, ',specGRP.chanlocs(use_chans(c)).labels);
0566             end
0567         end
0568     end
0569     fprintf('All significant p-values<=%f\n',max_sig_p);
0570 end
0571 
0572 
0573 %Add permutation results to specGRP struct
0574 n_t_tests=length(specGRP.t_tests);
0575 neo_test=n_t_tests+1;
0576 specGRP.t_tests(neo_test).bin=bin;
0577 specGRP.t_tests(neo_test).freq_band=freq_band;
0578 specGRP.t_tests(neo_test).used_freq_ids=use_frq_ids;
0579 n_use_chans=length(use_chans);
0580 include_chans=cell(1,n_use_chans);
0581 for a=1:n_use_chans,
0582    include_chans{a}=specGRP.chanlocs(use_chans(a)).labels; 
0583 end
0584 specGRP.t_tests(neo_test).include_chans=include_chans;
0585 specGRP.t_tests(neo_test).used_chan_ids=use_chans;
0586 specGRP.t_tests(neo_test).mult_comp_method='tmax perm test';
0587 specGRP.t_tests(neo_test).n_perm=p.Results.n_perm;
0588 specGRP.t_tests(neo_test).desired_alphaORq=p.Results.alpha;
0589 specGRP.t_tests(neo_test).estimated_alpha=est_alpha;
0590 specGRP.t_tests(neo_test).null_mean=p.Results.null_mean;
0591 if mean_band,
0592     specGRP.t_tests(neo_test).data_t=data_t;
0593     specGRP.t_tests(neo_test).mean_band='yes';
0594 else
0595     specGRP.t_tests(neo_test).data_t='See specGRP.grands_pow_dB_t';
0596     specGRP.t_tests(neo_test).mean_band='no';
0597 end
0598 specGRP.t_tests(neo_test).crit_t=crit_t;
0599 specGRP.t_tests(neo_test).df=df;
0600 specGRP.t_tests(neo_test).adj_pval=prm_pval;
0601 specGRP.t_tests(neo_test).fdr_rej=NaN;
0602 specGRP.t_tests(neo_test).seed_state=seed_state;
0603 
0604 
0605 if strcmpi(p.Results.plot_raster,'yes'),
0606     sig_raster(specGRP,neo_test,'verblevel',0);
0607 end
0608 
0609 if mean_band,
0610     if strcmpi(p.Results.plot_mn_topo,'yes') || isempty(p.Results.plot_mn_topo),
0611         sig_topo(specGRP,neo_test,'units','t','verblevel',0); %t-score topographies
0612         sig_topo(specGRP,neo_test,'units','dB','verblevel',0); %10*log10((uV^2)/Hz) topographies
0613     end
0614 else
0615     %plot_pvals(specGRP,p.Results.alpha,use_chans,use_frq_ids,prm_pval,bin);
0616     %%improve plot_pvals and make an option ??
0617     if strcmpi(p.Results.plot_gui,'yes'),
0618         gui_pow('initialize','specGND_or_specGRP',specGRP,'t_test',neo_test,'stat','t', ...
0619             'verblevel',1);
0620     end
0621 end
0622 
0623 if ~isempty(p.Results.output_file)
0624     [fid msg]=fopen(p.Results.output_file,'w');
0625     if fid==-1,
0626         error('Cannot create file %s for writing.  According to fopen.m: %s.', ...
0627             p.Results.file,msg);
0628     else
0629         %Write header column of frequencies
0630         % Leave first column blank for channel labels
0631         if mean_band,
0632             for t=1:n_band
0633                 fprintf(fid,' %d-%d',specGRP.freqs(use_frq_ids{t}(1)), ...
0634                     specGRP.freqs(use_frq_ids{t}(end)));
0635             end
0636             
0637             %write a couple spaces and then write header for t-scores
0638             fprintf(fid,'  ');
0639             for t=1:n_band
0640                 fprintf(fid,' %d-%d',specGRP.freqs(use_frq_ids{t}(1)), ...
0641                     specGRP.freqs(use_frq_ids{t}(end)));
0642             end
0643         else
0644             for t=use_frq_ids,
0645                 fprintf(fid,' %d',specGRP.freqs(t));
0646             end
0647         end
0648         fprintf(fid,' Hz\n');
0649         
0650         % Write channel labels and p-values
0651         chan_ct=0;
0652         for c=use_chans,
0653             chan_ct=chan_ct+1;
0654             fprintf(fid,'%s',specGRP.chanlocs(c).labels);
0655             for t=1:length(use_frq_ids),
0656                 fprintf(fid,' %f',prm_pval(chan_ct,t));
0657             end
0658             fprintf(fid,' p-value');
0659             
0660             if mean_band,
0661                 %write a couple spaces and then write t-scores if mean amp
0662                 %in frequency bands used
0663                 fprintf(fid,' ');
0664                 for t=1:n_band
0665                     fprintf(fid,' %f',data_t(chan_ct,t));
0666                 end
0667                 fprintf(fid,' t-score \n');
0668             else
0669                 fprintf(fid,'\n');
0670             end
0671         end
0672         
0673         % Write permutation test details
0674         fprintf(fid,'Experiment: %s\n',specGRP.exp_desc);
0675         fprintf(fid,'Test_of_null_hypothesis_that_Bin_%d_equals_%f\n',bin,p.Results.null_mean);
0676         fprintf(fid,'#_of_frequency_bands: %d\n',n_band);
0677         fprintf(fid,'#_of_permutations: %d\n',p.Results.n_perm);
0678         fprintf(fid,'Tail_of_test: ');
0679         if ~p.Results.tail,
0680             fprintf(fid,'Two_tailed\n');
0681             fprintf(fid,'Critical_t_scores: %f %f\n',crit_t(1),crit_t(2));
0682         elseif p.Results.tail>0
0683             fprintf(fid,'Upper_tailed\n');
0684             fprintf(fid,'Critical_t_score: %f\n',crit_t(1));
0685         else
0686             fprintf(fid,'Lower_tailed\n');
0687             fprintf(fid,'Critical_t_score: %f\n',crit_t(1));
0688         end
0689         fprintf(fid,'Degrees_of_freedom: %d\n',df);
0690         fprintf(fid,'Alpha_level: %f\n',p.Results.alpha);
0691         
0692         for grp=[grpA grpB],
0693             % # of participants and filenames
0694             if grp==grpA,
0695                 use_subs=use_subsA;
0696                 fprintf(fid,'specGND_fname_GroupA: %s\n',specGRP.specGND_fnames{grp});
0697                 fprintf(fid,'#_of_participants_GroupA: %d\n',n_subA);
0698                 fprintf(fid,'Participant_names_GroupA: \n');
0699             else
0700                 use_subs=use_subsB;
0701                 fprintf(fid,'specGND_fname_GroupB: %s\n',specGRP.specGND_fnames{grp});
0702                 fprintf(fid,'#_of_participants_GroupB: %d\n',n_subB);
0703                 fprintf(fid,'Participant_names_GroupB: \n');
0704             end
0705             for s=1:length(use_subs),
0706                 fprintf(fid,'%s\n',specGRP.indiv_subnames{grp}{use_subs(s)});
0707             end
0708         end
0709     end
0710     fclose(fid);
0711 end
0712 
0713 if ~strcmpi(p.Results.save_specGRP,'no'),
0714     specGRP=save_matmk(specGRP);
0715 end
0716 
0717 %
0718 %% %%%%%%%%%%%%%%%%%%%%% function str2bool() %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0719 %
0720 function bool=str2bool(str)
0721 %function bool=str2bool(str)
0722 
0723 if ischar(str),
0724     if strcmpi(str,'yes') || strcmpi(str,'y')
0725         bool=1;
0726     else
0727         bool=0;
0728     end
0729 else
0730    bool=str; 
0731 end
0732

Generated on Tue 10-May-2016 16:37:45 by m2html © 2005