Home > matlabmk > tfdr_specGRP.m

tfdr_specGRP

PURPOSE ^

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

SYNOPSIS ^

function [specGRP, p_values, data_t, crit_t]=tfdr_specGRP(specGRP_or_fname,bin,varargin)

DESCRIPTION ^

 tfdr_specGRP() - Tests the null hypothesis that the grand average voltage
             of a between-subject difference in power spectra is mu
             (usually 0) using t-tests based and one of various Benjamini
             algorithms for control of the false discovery rate.  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 tfdr_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, p_values, data_t, crit_t]=tfdr_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}
   q             - A number between 0 and 1 specifying the family-wise
                   q level of the test. q is the upper bound on the 
                   expected proportion of rejected null hypotheses that are
                   false rejections (i.e., the FDR). {default: 0.05}
   method        - ['bh', 'by', or 'bky'] The procedure used to control
                   the FDR. 'bh' is the classic Benjamini & Hochberg (1995)
                   procedure, which is guaranteed to control FDR when the 
                   tests are independent or positively dependent (e.g., 
                   positively correlated Gaussians). 'by' is a much more
                   conservative version of 'bh' that always controls FDR
                   (regardless of the dependency structure of the tests--
                   Benjamini & Yekutieli, 2001). 'bky' is a "two-stage"
                   version of 'bh' that is more powerful than 'bh' when a 
                   lot of the null hypotheses are false (Benjamini, Krieger, &
                   Yekutieli, 2006).  'bky' is guaranteed to control FDR when the
                   tests are independent and tends to be slightly less
                   powerful than 'bh' when few or no null hypothese are
                   false.
   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, 
                   false discovery rate, 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 t-tests are completed 
                   and added to it. User will first be prompted to verify 
                   file name and path. {default: 'yes'}

 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 
                   t-tests and the test parameters. 
   p_values      - A two-dimensional matrix (channel x frequency) of the
                   p-values of each comparison (no correction for multiple
                   comparisons).
   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".


 References:
   Benjamini, Y., & Hochberg, Y. (1995). Controlling the false discovery 
 rate: A practical and powerful approach to multiple testing. Journal of 
 the Royal Statistical Society. Series B (Methodological), 57(1), 289-300.

   Benjamini, Y., Krieger, A. M., & Yekutieli, D. (2006). Adaptive linear 
 step-up procedures that control the false discovery rate. Biometrika, 
 93(3), 491-507. 

   Benjamini, Y., & Yekutieli, D. (2001). The control of the false 
 discovery rate in multiple testing under dependency. The Annals of 
 Statistics, 29(4), 1165-1188. 



 Author:
 David Groppe
 Kutaslab, 12/2010

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 % tfdr_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 t-tests based and one of various Benjamini
0004 %             algorithms for control of the false discovery rate.  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 tfdr_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, p_values, data_t, crit_t]=tfdr_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 %   q             - A number between 0 and 1 specifying the family-wise
0041 %                   q level of the test. q is the upper bound on the
0042 %                   expected proportion of rejected null hypotheses that are
0043 %                   false rejections (i.e., the FDR). {default: 0.05}
0044 %   method        - ['bh', 'by', or 'bky'] The procedure used to control
0045 %                   the FDR. 'bh' is the classic Benjamini & Hochberg (1995)
0046 %                   procedure, which is guaranteed to control FDR when the
0047 %                   tests are independent or positively dependent (e.g.,
0048 %                   positively correlated Gaussians). 'by' is a much more
0049 %                   conservative version of 'bh' that always controls FDR
0050 %                   (regardless of the dependency structure of the tests--
0051 %                   Benjamini & Yekutieli, 2001). 'bky' is a "two-stage"
0052 %                   version of 'bh' that is more powerful than 'bh' when a
0053 %                   lot of the null hypotheses are false (Benjamini, Krieger, &
0054 %                   Yekutieli, 2006).  'bky' is guaranteed to control FDR when the
0055 %                   tests are independent and tends to be slightly less
0056 %                   powerful than 'bh' when few or no null hypothese are
0057 %                   false.
0058 %   freq_band     - 2D matrix of pairs of frequency values specifying the
0059 %                   beginning and end of one or more frequency bands in Hz
0060 %                   (e.g., [3 8; 8 12]).  Every single frequency in
0061 %                   the frequency band will be individually tested (i.e.,
0062 %                   maximal temporal resolution) if mean_band option is
0063 %                   NOT used. Note, boundaries of frequency band(s) may not
0064 %                   exactly correspond to desired frequency band boundaries
0065 %                   because of temporal digitization (i.e., you only have
0066 %                   samples every so many Hz). {default: 0 Hz to the
0067 %                   Nyquist frequency}
0068 %   freq_block_dur- [integers] A number or numbers (in Hz) specifying a
0069 %                   duration of frequency blocks in which the frequency
0070 %                   windows specified by freq_band will be divided.  For
0071 %                   example, if freq_band=[0 40] and freq_block_dur=10,
0072 %                   the 0 to 40 Hz frequency band will be sub-divided into
0073 %                   10 Hz bands (i.e., freq_band will equal something like
0074 %                   [0 9; 10 19; 20 29; 30 39]--depending on your frequency
0075 %                   resolution).  This is an easy way to break up larger
0076 %                   frequency bands of interest into smaller bands for
0077 %                   mean band analysis (if the 'mean_band' option is set to
0078 %                   'yes').  If you specify multiple frequency bands with
0079 %                   'freq_band', you can break them up using durations of
0080 %                   different lengths.  For example, if freq_band=[0 10;
0081 %                   40 90] and freq_block_dur=[5 10], the first frequency
0082 %                   band (0 to 10 Hz) will be broken up into 5 Hz
0083 %                   bands and the second band (40 to 90 Hz) will be
0084 %                   broken up into 10 Hz bands. {default: not used}
0085 %   mean_band     - ['yes' or 'no'] If 'yes', the permutation test will be
0086 %                   performed on the mean power within each frequency band
0087 %                   specified by freq_band.  This sacrifices frequency
0088 %                   resolution to increase test power by reducing the number
0089 %                   of comparisons.  If 'no', every single frequency within
0090 %                   freq_band's frequency bands will be tested individually.
0091 %                   {default: 'no'}
0092 %   null_mean     - [number] The mean of the null hypothesis (in units of
0093 %                   microvolts). {default: 0}
0094 %   exclude_chans - A cell array of channel labels to exclude from the
0095 %                   permutation test (e.g., {'A2','lle','rhe'}).  This option
0096 %                   sacrifices spatial resolution to increase test power by
0097 %                   reducing the number of comparisons. Use headinfo_spec.m to see
0098 %                   the channel labels stored in the specGRP variable. You cannot
0099 %                   use both this option and 'include_chans' (below).{default:
0100 %                   not used, all channels included in test}
0101 %   include_chans - A cell array of channel labels to use in the permutation
0102 %                   test (e.g., {'A2','lle','rhe'}).  All other channels will
0103 %                   be ignored. This option sacrifices spatial resolution to
0104 %                   increase test power by reducing the number of comparisons.
0105 %                   Use headinfo_spec.m to see the channel labels stored in the specGRP
0106 %                   variable. You cannot use both this option and
0107 %                   'exclude_chans' (above). {default: not used, all channels
0108 %                   included in test}
0109 %   verblevel     - An integer specifiying the amount of information you want
0110 %                   this function to provide about what it is doing during runtime.
0111 %                    Options are:
0112 %                      0 - quiet, only show errors, warnings, and EEGLAB reports
0113 %                      1 - stuff anyone should probably know
0114 %                      2 - stuff you should know the first time you start working
0115 %                          with a data set {default value}
0116 %                      3 - stuff that might help you debug (show all
0117 %                          reports)
0118 %   plot_gui      - ['yes' or 'no'] If 'yes', a GUI is created for
0119 %                   visualizing the results of the permutation test using the
0120 %                   function gui_pow.m. The GUI vizualizes the grand average
0121 %                   ERPs in each bin via various stats (e.g., t-scores), shows
0122 %                   topographies at individual frequencies, and illustrates
0123 %                   which electrodes significantly differ from the null
0124 %                   hypothesis.  This option does not work if mean_band
0125 %                   option is set to 'yes.' This GUI can be reproduced using
0126 %                   the function gui_pow.m. {default: 'yes'}
0127 %   plot_raster   - ['yes' or 'no'] If 'yes', a two-dimensional (frequency x channel)
0128 %                   binary "raster" diagram is created to illustrate the
0129 %                   results of the permutation test.  Significant negative and
0130 %                   positive deviations from the null hypothesis are shown
0131 %                   as black and white rectangles respectively. Non-
0132 %                   significant comparisons are shown as gray rectangles.
0133 %                   Clicking on the rectangles will show you the
0134 %                   corresponding frequency and channel label for that
0135 %                   rectangle. This figure can be reproduced with the
0136 %                   function sig_raster.m. {default: 'yes'}
0137 %   plot_mn_topo  - ['yes' or 'no'] If 'yes', the topographies of the mean
0138 %                   voltages/effects in each frequency band is produced.  More
0139 %                   specifically, two figures are produced: one showing the
0140 %                   topographies in decibel power the other in t-scores. Significant/
0141 %                   nonsignificant comparisons are shown as white/black
0142 %                   electrodes. Clicking on electrodes will show the
0143 %                   electrode's name.  This figure can be reproduced with
0144 %                   the function sig_topo.m.  This option has NO effect if
0145 %                   mean_band option is set to 'no'. {default: 'yes'}
0146 %   output_file   - A string indicating the name of a space delimited text
0147 %                   file to produce containing the p-values of all comparisons
0148 %                   and the details of the test (e.g., number of permutations,
0149 %                   false discovery rate, etc...). If mean_band option is
0150 %                   set to 'yes,' t-scores of each comparison are also
0151 %                   included since you cannot derive them from the t-scores
0152 %                   at each frequency/electrode in a simple way. When
0153 %                   importing this file into a spreadsheet be sure NOT to count
0154 %                   consecutive spaces as multiple delimiters. {default: none}
0155 %   save_specGRP  - ['yes' or 'no'] If 'yes', the specGRP variable will be
0156 %                   saved to disk after the t-tests are completed
0157 %                   and added to it. User will first be prompted to verify
0158 %                   file name and path. {default: 'yes'}
0159 %
0160 % Outputs:
0161 %   specGRP       - specGRP structure variable.  This is the same as
0162 %                   the input specGRP variable with one addition: the
0163 %                   field specGRP.t_tests will contain the results of the
0164 %                   t-tests and the test parameters.
0165 %   p_values      - A two-dimensional matrix (channel x frequency) of the
0166 %                   p-values of each comparison (no correction for multiple
0167 %                   comparisons).
0168 %   data_t        - A two-dimensional matrix (channel x frequency) of the
0169 %                   t-scores of each comparison.
0170 %   crit_t        - The critical t-score(s) for the test.  Any t-scores
0171 %                   that are more extreme than the critical t-score(s)
0172 %                   significantly deviate from 0.
0173 %
0174 %   Note also that a great deal of information about the test is displayed
0175 %   in the MATLAB command window.  You can easiy record of all this
0176 %   information to a text file using the MATLAB command "diary."
0177 %
0178 % Global Variables:
0179 %   VERBLEVEL = MATLABmk level of verbosity (i.e., tells functions how much
0180 %               to report about what they're doing during runtime) set by
0181 %               the optional function argument 'verblevel'
0182 %
0183 % Notes:
0184 % -To add a bin that is the difference in spectral power between two groups
0185 % to a specGRP variable, use the function "bin_op_specGRP".
0186 %
0187 %
0188 % References:
0189 %   Benjamini, Y., & Hochberg, Y. (1995). Controlling the false discovery
0190 % rate: A practical and powerful approach to multiple testing. Journal of
0191 % the Royal Statistical Society. Series B (Methodological), 57(1), 289-300.
0192 %
0193 %   Benjamini, Y., Krieger, A. M., & Yekutieli, D. (2006). Adaptive linear
0194 % step-up procedures that control the false discovery rate. Biometrika,
0195 % 93(3), 491-507.
0196 %
0197 %   Benjamini, Y., & Yekutieli, D. (2001). The control of the false
0198 % discovery rate in multiple testing under dependency. The Annals of
0199 % Statistics, 29(4), 1165-1188.
0200 %
0201 %
0202 %
0203 % Author:
0204 % David Groppe
0205 % Kutaslab, 12/2010
0206 
0207 %%%%%%%%%%%%%%%% REVISION LOG %%%%%%%%%%%%%%%%%
0208 % ?/?/2010-??
0209 %
0210 
0211 function [specGRP, p_values, data_t, crit_t]=tfdr_specGRP(specGRP_or_fname,bin,varargin)
0212 
0213 global VERBLEVEL;
0214 
0215 p=inputParser;
0216 p.addRequired('specGRP_or_fname',@(x) ischar(x) || isstruct(x));
0217 p.addRequired('bin',@(x) isnumeric(x) && (length(x)==1) && (x>0));
0218 p.addParamValue('tail',0,@(x) isnumeric(x) && (length(x)==1));
0219 p.addParamValue('q',0.05,@(x) isnumeric(x) && (x>0) && (x<1));
0220 p.addParamValue('method','bh',@(x) strcmpi(x,'bh') || strcmpi(x,'by') || strcmpi(x,'bky'));
0221 p.addParamValue('freq_band',[],@(x) isnumeric(x) && (size(x,2)==2)); 
0222 p.addParamValue('freq_block_dur',[],@isnumeric);
0223 p.addParamValue('mean_band','no',@(x) ischar(x) && (strcmpi(x,'yes') || strcmpi(x,'no')));
0224 p.addParamValue('null_mean',0,@(x) isnumeric(x) && (length(x)==1));
0225 p.addParamValue('verblevel',[],@(x) isnumeric(x) && (length(x)==1));
0226 p.addParamValue('exclude_chans',[],@(x) ischar(x) || iscell(x));
0227 p.addParamValue('include_chans',[],@(x) ischar(x) || iscell(x));
0228 p.addParamValue('plot_gui','yes',@(x) ischar(x) && (strcmpi(x,'yes') || strcmpi(x,'no')));
0229 p.addParamValue('plot_raster','yes',@(x) ischar(x) && (strcmpi(x,'yes') || strcmpi(x,'no')));
0230 p.addParamValue('plot_mn_topo',[],@(x) ischar(x) && (strcmpi(x,'yes') || strcmpi(x,'no')));
0231 p.addParamValue('output_file',[],@ischar);
0232 p.addParamValue('save_specGRP','yes',@(x) ischar(x) && (strcmpi(x,'yes') || strcmpi(x,'no')));
0233 
0234 p.parse(specGRP_or_fname,bin,varargin{:});
0235 
0236 
0237 if isempty(p.Results.verblevel),
0238     if isempty(VERBLEVEL),
0239         VERBLEVEL=2;
0240     end
0241 else
0242    VERBLEVEL=p.Results.verblevel; 
0243 end
0244     
0245 mean_band=str2bool(p.Results.mean_band);
0246 
0247 %Load specGRP struct
0248 if ischar(specGRP_or_fname),
0249     fprintf('Loading specGRP struct from file %s.\n',specGRP_or_fname);
0250     load(specGRP_or_fname,'-MAT');
0251 else
0252     specGRP=specGRP_or_fname;
0253     clear specGRP_or_fname;
0254 end
0255 [n_chan, n_pt, n_bin]=size(specGRP.grands_pow_dB);
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 & q level
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 
0497 %Compute the t-tests
0498 if strcmpi(specGRP.bin_info(bin).op,'(A+B)/n'),
0499     %one sample t-test
0500     VerbReport('Performing one sample/repeated measures t-tests.',1,VERBLEVEL);
0501     powAB=zeros(length(use_chans),size(powA,2),n_subA+n_subB);
0502     powAB(:,:,1:n_subA)=powA-p.Results.null_mean;
0503     powAB(:,:,(n_subA+1):(n_subA+n_subB))=powB-p.Results.null_mean;
0504     [p_values, data_t]=fast_t1(powAB,p.Results.tail,VERBLEVEL);
0505 else
0506     %independent samples t-test
0507     VerbReport('Performing independent samples t-tests.',1,VERBLEVEL);
0508     [p_values, data_t]=fast_t2(powA-p.Results.null_mean,powB,p.Results.tail,VERBLEVEL);
0509 end
0510 %Perform FDR control
0511 switch lower(p.Results.method)
0512     case 'bh'
0513         VerbReport('FDR control procedure: Benjamini & Hochberg (independent or positive dependency)',1,VERBLEVEL);
0514         [h_rej, crit_p]=fdr_bh(p_values,p.Results.q,'pdep','no');
0515     case 'by'
0516         VerbReport('FDR control procedure: Benjamini & Yekutieli (arbitrary dependency)',1,VERBLEVEL);
0517         [h_rej, crit_p]=fdr_bh(p_values,p.Results.q,'dep','no');
0518     case 'bky'
0519         VerbReport('FDR control procedure: Benjamini, Krieger, & Yekutieli (two-stage)',1,VERBLEVEL);
0520         [h_rej, crit_p]=fdr_bky(p_values,p.Results.q,'no');
0521 end
0522 
0523 sig_tpts=find(sum(h_rej));
0524 if isempty(sig_tpts),
0525     if p.Results.tail==0,
0526         crit_t=[NaN NaN];
0527     else
0528         crit_t=NaN;
0529     end
0530     fprintf('Power spectra are NOT significantly different from zero (q=%f) at any frequency/window analyzed.\n', ...
0531         p.Results.q);
0532     %fprintf('All p-values>=%f\n',min(min(p_values))); ?? add FDR-corrected
0533     %p-values someday?
0534 else
0535     crit_t=min(abs(data_t(crit_p==p_values)));
0536     if p.Results.tail<0,
0537         crit_t=-crit_t;
0538     elseif p.Results.tail==0,
0539         crit_t=[-crit_t crit_t];
0540     end
0541     
0542     %Command line summary of results
0543     VerbReport(['Critical t-score(s):' num2str(crit_t)],1,VERBLEVEL);
0544     if p.Results.tail
0545         %one-tailed test
0546         tw_alpha=1-cdf('t',max(abs(crit_t)),df);
0547     else
0548         %two-tailed test
0549         tw_alpha=2-cdf('t',max(crit_t),df)-cdf('t',-min(crit_t),df);
0550     end
0551     VerbReport(sprintf('That corresponds to a test-wise alpha level of %f.',tw_alpha),1,VERBLEVEL);
0552     VerbReport(sprintf('Bonferroni test-wise alpha would be %f.',p.Results.q/(size(p_values,1)* ...
0553         size(p_values,2))),1,VERBLEVEL);
0554   
0555     fprintf('Significant differences from zero (in order of earliest to latest):\n');
0556     %max_sig_p=0; ?? report FDR corrected p-values someday?
0557     %frequency bands instead of individual frequencies
0558     for t=sig_tpts,
0559         if mean_band
0560             fprintf('%d to %d Hz, electrode(s): ',specGRP.freqs(use_frq_ids{t}(1)), ...
0561                 specGRP.freqs(use_frq_ids{t}(end)));
0562         else
0563             fprintf('%d Hz, electrode(s): ',specGRP.freqs(use_frq_ids(t)));
0564         end
0565         sig_elec=find(p_values(:,t)<p.Results.q);
0566         ct=0;
0567         for c=sig_elec',
0568             ct=ct+1;
0569             % if p_values(c,t)>max_sig_p, ?? report FDR corrected p-values someday?
0570             %  max_sig_p=p_values(c,t);
0571             % end
0572             if ct==length(sig_elec),
0573                 fprintf('%s.\n',specGRP.chanlocs(use_chans(c)).labels);
0574             else
0575                 fprintf('%s, ',specGRP.chanlocs(use_chans(c)).labels);
0576             end
0577         end
0578     end
0579     %fprintf('All significant p-values<=%f\n',max_sig_p); ?? add FDR-corrected
0580     %p-values someday?
0581 end
0582 
0583 %Add t-test results to specGRP struct
0584 n_t_tests=length(specGRP.t_tests);
0585 neo_test=n_t_tests+1;
0586 specGRP.t_tests(neo_test).bin=bin;
0587 specGRP.t_tests(neo_test).freq_band=freq_band;
0588 specGRP.t_tests(neo_test).used_freq_ids=use_frq_ids;
0589 n_use_chans=length(use_chans);
0590 include_chans=cell(1,n_use_chans);
0591 for a=1:n_use_chans,
0592    include_chans{a}=specGRP.chanlocs(use_chans(a)).labels; 
0593 end
0594 specGRP.t_tests(neo_test).include_chans=include_chans;
0595 specGRP.t_tests(neo_test).used_chan_ids=use_chans;
0596 specGRP.t_tests(neo_test).mult_comp_method=p.Results.method;
0597 specGRP.t_tests(neo_test).n_perm=NaN;
0598 specGRP.t_tests(neo_test).desired_alphaORq=p.Results.q;
0599 specGRP.t_tests(neo_test).estimated_alpha=NaN;
0600 specGRP.t_tests(neo_test).null_mean=p.Results.null_mean;
0601 if mean_band,
0602     specGRP.t_tests(neo_test).data_t=data_t;
0603     specGRP.t_tests(neo_test).mean_band='yes';
0604 else
0605     specGRP.t_tests(neo_test).data_t='See specGRP.grands_pow_dB_t';
0606     specGRP.t_tests(neo_test).mean_band='no';
0607 end
0608 specGRP.t_tests(neo_test).crit_t=crit_t;
0609 specGRP.t_tests(neo_test).df=df;
0610 specGRP.t_tests(neo_test).adj_pval=NaN; % ?? make FDR adjusted p-vals someday?
0611 specGRP.t_tests(neo_test).fdr_rej=h_rej;
0612 specGRP.t_tests(neo_test).seed_state=NaN;
0613 
0614 if strcmpi(p.Results.plot_raster,'yes'),
0615     sig_raster(specGRP,neo_test,'verblevel',0);
0616 end
0617 
0618 if mean_band,
0619     if strcmpi(p.Results.plot_mn_topo,'yes') || isempty(p.Results.plot_mn_topo),
0620         sig_topo(specGRP,neo_test,'units','t','verblevel',0); %t-score topographies
0621         sig_topo(specGRP,neo_test,'units','dB','verblevel',0); %10*log10((uV^2)/Hz) topographies
0622     end
0623 else
0624     %plot_pvals(specGRP,p.Results.alpha,use_chans,use_frq_ids,prm_pval,bin);
0625     %%improve plot_pvals and make an option ??
0626     if strcmpi(p.Results.plot_gui,'yes'),
0627         gui_pow('initialize','specGND_or_specGRP',specGRP,'t_test',neo_test,'stat','t', ...
0628             'verblevel',1);
0629     end
0630 end
0631 
0632 if ~isempty(p.Results.output_file)
0633     [fid msg]=fopen(p.Results.output_file,'w');
0634     if fid==-1,
0635         error('Cannot create file %s for writing.  According to fopen.m: %s.', ...
0636             p.Results.file,msg);
0637     else
0638         %Write header column of frequencies
0639         % Leave first column blank for channel labels
0640         if mean_band,
0641             for t=1:n_band
0642                 fprintf(fid,' %d-%d',specGRP.freqs(use_frq_ids{t}(1)), ...
0643                     specGRP.freqs(use_frq_ids{t}(end)));
0644             end
0645 
0646             %write a couple spaces and then write header for t-scores
0647             fprintf(fid,'  ');
0648             for t=1:n_band
0649                 fprintf(fid,' %d-%d',specGRP.freqs(use_frq_ids{t}(1)), ...
0650                     specGRP.freqs(use_frq_ids{t}(end)));
0651             end
0652         else
0653             for t=use_frq_ids,
0654                 fprintf(fid,' %d',specGRP.freqs(t));
0655             end
0656         end
0657         fprintf(fid,' Hz\n');
0658         
0659         % Write channel labels and p-values
0660         chan_ct=0;
0661         for c=use_chans,
0662             chan_ct=chan_ct+1;
0663             fprintf(fid,'%s',specGRP.chanlocs(c).labels);
0664             for t=1:length(use_tpts),
0665                 fprintf(fid,' %f',p_values(chan_ct,t)); % ?? make FDR adjusted p-values someday?
0666             end
0667             fprintf(fid,' p-value');
0668             
0669             if mean_band,
0670                 %write a couple spaces and then write t-scores if mean amp
0671                 %in frequency bands used
0672                 fprintf(fid,' ');
0673                 for t=1:n_band
0674                     fprintf(fid,' %f',data_t(chan_ct,t));
0675                 end
0676                 fprintf(fid,' t-score \n');
0677             else
0678                 fprintf(fid,'\n');
0679             end
0680         end
0681         
0682         % Write t-test details
0683         fprintf(fid,'Experiment: %s\n',specGRP.exp_desc);
0684         fprintf(fid,'Test_of_null_hypothesis_that_Bin_%d_equals_%d\n',bin,p.Results.null_mean);
0685         fprintf(fid,'#_of_frequency_bands: %d\n',n_band);
0686         fprintf(fid,'FDR_method: %s\n',p.Results.method);
0687         fprintf(fid,'Tail_of_test: ');
0688         if ~p.Results.tail,
0689             fprintf(fid,'Two_tailed\n');
0690             fprintf(fid,'Critical_t_scores: %f %f\n',crit_t(1),crit_t(2));
0691         elseif p.Results.tail>0
0692             fprintf(fid,'Upper_tailed\n');
0693             fprintf(fid,'Critical_t_score: %f\n',crit_t(1));
0694         else
0695             fprintf(fid,'Lower_tailed\n');
0696             fprintf(fid,'Critical_t_score: %f\n',crit_t(1));
0697         end
0698         fprintf(fid,'Critical_p-value: %f\n',crit_p);
0699         fprintf(fid,'Total_#_of_significant_differences: %d\n',sum(sum(h_rej)));
0700         fprintf(fid,'Estimated_upper_bound_on_expected_#_of_false_discoveries: %.1f\n',sum(sum(h_rej))*p.Results.q);
0701         fprintf(fid,'Degrees_of_freedom: %d\n',df);
0702         fprintf(fid,'q_level: %f\n',p.Results.q);
0703         for grp=[grpA grpB],
0704             % # of participants and filenames
0705             if grp==grpA,
0706                 use_subs=use_subsA;
0707                 fprintf(fid,'specGRP_fname_GroupA: %s\n',specGRP.specGND_fnames{grp});
0708                 fprintf(fid,'#_of_participants_GroupA: %d\n',n_subA);
0709                 fprintf(fid,'Participant_names_GroupA: \n');
0710             else
0711                 use_subs=use_subsB;
0712                 fprintf(fid,'specGRP_fname_GroupB: %s\n',specGRP.specGND_fnames{grp});
0713                 fprintf(fid,'#_of_participants_GroupB: %d\n',n_subB);
0714                 fprintf(fid,'Participant_names_GroupB: \n');
0715             end
0716             for s=1:length(use_subs),
0717                 fprintf(fid,'%s\n',specGRP.indiv_subnames{grp}{use_subs(s)});
0718             end
0719         end
0720     end
0721     fclose(fid);
0722 end
0723 
0724 if ~strcmpi(p.Results.save_specGRP,'no'),
0725     specGRP=save_erps(specGRP);
0726 end
0727 
0728 
0729 %
0730 %% %%%%%%%%%%%%%%%%%%%%% function str2bool() %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0731 %
0732 function bool=str2bool(str)
0733 %function bool=str2bool(str)
0734 
0735 if ischar(str),
0736     if strcmpi(str,'yes') || strcmpi(str,'y')
0737         bool=1;
0738     else
0739         bool=0;
0740     end
0741 else
0742    bool=str; 
0743 end
0744

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