Home > matlabmk > tfdrGND.m

tfdrGND

PURPOSE ^

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

SYNOPSIS ^

function [GND, p_values, data_t, crit_t, adj_p]=tfdrGND(GND_or_fname,bin,varargin)

DESCRIPTION ^

 tfdrGND() - Tests the null hypothesis that the grand average voltage
             of a bin is mu or that the grand average within-subject 
             difference between two bins is mu using one of several 
             possible false discovery rate (FDR) procedures to control for 
             mulitple comparisons (note, mu is assumed to be 0 by default).
             This function requires individual subject ERPs to 
             be stored in a "GND" structure and outputs the 
             test results in a number of graphical and text formats.  
             For analogous between-subject comparisons use the function 
             tfdrGRP.m.
             
 Usage:
  >> [GND, p_values, data_t, crit_t, adj_p]=tfdrGND(GND_or_fname,bin,varargin)

 Required Inputs:
   GND_or_fname - A GND structure variable or the filename of a 
                  GND structure that has been saved to disk.  To 
                  create a GND variable from Kutaslab ERP files (e.g.,
                  *.mas files) use avgs2GND.m.  To do the same from 
                  EEGLAB *.set files use sets2GND.m.  See Mass
                  Univariate ERP Toolbox documentation for detailed 
                  information about the format of a GND 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 a voltage of mu 
                  Use the function headinfo.m to see what bins are stored 
                  in a GND variable.  Use the function bin_dif.m to create
                  a difference wave between two bins whose significance
                  you can test with this function.

 Optional Inputs:
   tail          - [1,0, or -1] An integer specifying the tail of the
                   hypothesis test.  "1" means upper-tailed (i.e., alternative 
                   hypothesis is that the ERP/difference wave is greater 
                   than the mean of the null hypothesis).  "0" means two-
                   tailed (i.e., alternative hypothesis is that the 
                   ERP/difference wave is not equal to the mean of the null
                   hypothesis). "-1" means lower-tailed (i.e., alternative 
                   hypothesis is that the ERP/difference wave is less than
                   the mean of the null hypothesis). {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. {default: 'bh'}
   time_wind     - 2D matrix of pairs of time values specifying the beginning 
                   and end of one or more time windows in ms (e.g., 
                   [160 180; 350 550]).  Every single time point in 
                   the time window will be individually tested (i.e.,
                   maximal temporal resolution) if mean_wind option is
                   NOT used. Note, boundaries of time window(s) may not 
                   exactly correspond to desired time window boundaries 
                   because of temporal digitization (i.e., you only have
                   samples every so many ms). {default: 0 ms to the end of
                   the epoch}
   time_block_dur- [integers] A number or numbers (in milliseconds) 
                   specifying a duration of time blocks in which the time 
                   windows specified by time_wind will be divided.  For
                   example, if time_wind=[300 600] and time_block_dur=100,
                   the 300 to 600 ms time window will be sub-divided into
                   100 ms windows (i.e., time_wind will equal [300 396;
                   400 496; 500 596]).  This is an easy way to break up
                   larger time windows of interest into smaller windows
                   for mean window analysis (if mean_wind option is set to
                   'yes').  If you specify multiple time windows with
                   time_wind, you can break them up using durations of
                   different lengths.  For example, if time_wind=[150 250;
                   400 900] and time_block_dur=[25 100], the first time
                   window (150 to 250 ms) will be broken up into 25 ms
                   windows and the second window (400 to 900 ms) will be
                   broken up into 100 ms windows. {default: not used}
   mean_wind     - ['yes' or 'no'] If 'yes', the t-tests will be performed 
                   on the mean amplitude within each time window 
                   specified by time_wind.  This sacrifices temporal 
                   resolution to increase test power by reducing the number
                   of comparisons.  If 'no', every single time point within
                   time_wind's time windows will be tested individually.
                   {default: 'no'}
   null_mean     - [number] The mean of the null hypothesis (i.e., mu) in 
                   units of microvolts. {default: 0}
   exclude_chans - A cell array of channel labels to exclude from the
                   t-tests (e.g., {'A2','lle','rhe'}).  This option 
                   sacrifices spatial resolution to increase test power by 
                   reducing the number of comparisons. Use headinfo.m to see
                   the channel labels stored in the GND 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 t-tests
                   (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.m to see the channel labels stored in the GND
                   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 t-tests using the 
                   function gui_erp.m. The GUI vizualizes the grand average 
                   ERPs in each bin via various stats (uV, t-scores), shows 
                   topographies at individual time points, and illustrates 
                   which electrodes significantly differ from the null 
                   hypothesis.  This option does not work if mean_wind 
                   option is set to 'yes.' This GUI can be reproduced using
                   the function gui_erp.m. {default: 'yes'}
   plot_raster   - ['yes' or 'no'] If 'yes', a two-dimensional (time x channel)
                   binary "raster" diagram is created to illustrate the
                   results of the t-tests.  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 time 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 time window are produced.  More
                   specifically, two figures are produced: one showing the
                   topographies in uV 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_wind 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., FDR method used, 
                   family-wise q level, etc...). If mean_wind option is
                   set to 'yes,' t-scores of each comparison are also 
                   included since you cannot derive them from the t-scores
                   at each time point/electrode in a simple way. When 
                   importing this file into a spreadsheet be sure NOT to 
                   count consecutive spaces as multiple delimiters. If bh
                   or bh FDR control procedures are used, FDR adjusted 
                   p-values (also called "q-values") will be output to the 
                   text file.  If method bky is used, unadjusted p-values 
                   will be output since it is not clear how to compute FDR
                   adjusted p-values for this method. {default: none}
   save_GRP      - ['yes' or 'no'] If 'yes', the GRP variable will be
                   saved to disk after the t-tests have been completed 
                   and added to it. User will first be prompted to verify 
                   file name and path. {default: 'yes'}

 Outputs:
   GND           - GND structure variable.  This is the same as
                   the input GND variable with one addition: the 
                   field GND.t_tests will contain the results of the 
                   t-tests and the test parameters. 
   p_values      - A two-dimensional matrix (channel x time) of the
                   p-values of each comparison (no correction for multiple
                   comparisons).
   data_t        - A two-dimensional matrix (channel x time) 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.
   adj_p         - FDR corrected p-values (also called q-values). Note, 
                   FDR corrected p-values can be greater than 1. For bky 
                   procedure adj_p is NaN since it is not clear how to
                   compute adjusted p-values for this procedure.
                   

   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 = Mass Univariate ERP Toolbox 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 difference wave to a GND variable, use the function "bin_dif.m".

 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, 5/2010

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 % tfdrGND() - Tests the null hypothesis that the grand average voltage
0002 %             of a bin is mu or that the grand average within-subject
0003 %             difference between two bins is mu using one of several
0004 %             possible false discovery rate (FDR) procedures to control for
0005 %             mulitple comparisons (note, mu is assumed to be 0 by default).
0006 %             This function requires individual subject ERPs to
0007 %             be stored in a "GND" structure and outputs the
0008 %             test results in a number of graphical and text formats.
0009 %             For analogous between-subject comparisons use the function
0010 %             tfdrGRP.m.
0011 %
0012 % Usage:
0013 %  >> [GND, p_values, data_t, crit_t, adj_p]=tfdrGND(GND_or_fname,bin,varargin)
0014 %
0015 % Required Inputs:
0016 %   GND_or_fname - A GND structure variable or the filename of a
0017 %                  GND structure that has been saved to disk.  To
0018 %                  create a GND variable from Kutaslab ERP files (e.g.,
0019 %                  *.mas files) use avgs2GND.m.  To do the same from
0020 %                  EEGLAB *.set files use sets2GND.m.  See Mass
0021 %                  Univariate ERP Toolbox documentation for detailed
0022 %                  information about the format of a GND variable. If you
0023 %                  specifiy a filename be sure to include the file's path,
0024 %                  unless the file is in the current working directory.
0025 %   bin          - [integer] The bin to contrast against a voltage of mu
0026 %                  Use the function headinfo.m to see what bins are stored
0027 %                  in a GND variable.  Use the function bin_dif.m to create
0028 %                  a difference wave between two bins whose significance
0029 %                  you can test with this function.
0030 %
0031 % Optional Inputs:
0032 %   tail          - [1,0, or -1] An integer specifying the tail of the
0033 %                   hypothesis test.  "1" means upper-tailed (i.e., alternative
0034 %                   hypothesis is that the ERP/difference wave is greater
0035 %                   than the mean of the null hypothesis).  "0" means two-
0036 %                   tailed (i.e., alternative hypothesis is that the
0037 %                   ERP/difference wave is not equal to the mean of the null
0038 %                   hypothesis). "-1" means lower-tailed (i.e., alternative
0039 %                   hypothesis is that the ERP/difference wave is less than
0040 %                   the mean of the null hypothesis). {default: 0}
0041 %   q             - A number between 0 and 1 specifying the family-wise
0042 %                   q level of the test. q is the upper bound on the
0043 %                   expected proportion of rejected null hypotheses that are
0044 %                   false rejections (i.e., the FDR). {default: 0.05}
0045 %   method        - ['bh', 'by', or 'bky'] The procedure used to control
0046 %                   the FDR. 'bh' is the classic Benjamini & Hochberg (1995)
0047 %                   procedure, which is guaranteed to control FDR when the
0048 %                   tests are independent or positively dependent (e.g.,
0049 %                   positively correlated Gaussians). 'by' is a much more
0050 %                   conservative version of 'bh' that always controls FDR
0051 %                   (regardless of the dependency structure of the tests--
0052 %                   Benjamini & Yekutieli, 2001). 'bky' is a "two-stage"
0053 %                   version of 'bh' that is more powerful than 'bh' when a
0054 %                   lot of the null hypotheses are false (Benjamini, Krieger, &
0055 %                   Yekutieli, 2006).  'bky' is guaranteed to control FDR when the
0056 %                   tests are independent and tends to be slightly less
0057 %                   powerful than 'bh' when few or no null hypothese are
0058 %                   false. {default: 'bh'}
0059 %   time_wind     - 2D matrix of pairs of time values specifying the beginning
0060 %                   and end of one or more time windows in ms (e.g.,
0061 %                   [160 180; 350 550]).  Every single time point in
0062 %                   the time window will be individually tested (i.e.,
0063 %                   maximal temporal resolution) if mean_wind option is
0064 %                   NOT used. Note, boundaries of time window(s) may not
0065 %                   exactly correspond to desired time window boundaries
0066 %                   because of temporal digitization (i.e., you only have
0067 %                   samples every so many ms). {default: 0 ms to the end of
0068 %                   the epoch}
0069 %   time_block_dur- [integers] A number or numbers (in milliseconds)
0070 %                   specifying a duration of time blocks in which the time
0071 %                   windows specified by time_wind will be divided.  For
0072 %                   example, if time_wind=[300 600] and time_block_dur=100,
0073 %                   the 300 to 600 ms time window will be sub-divided into
0074 %                   100 ms windows (i.e., time_wind will equal [300 396;
0075 %                   400 496; 500 596]).  This is an easy way to break up
0076 %                   larger time windows of interest into smaller windows
0077 %                   for mean window analysis (if mean_wind option is set to
0078 %                   'yes').  If you specify multiple time windows with
0079 %                   time_wind, you can break them up using durations of
0080 %                   different lengths.  For example, if time_wind=[150 250;
0081 %                   400 900] and time_block_dur=[25 100], the first time
0082 %                   window (150 to 250 ms) will be broken up into 25 ms
0083 %                   windows and the second window (400 to 900 ms) will be
0084 %                   broken up into 100 ms windows. {default: not used}
0085 %   mean_wind     - ['yes' or 'no'] If 'yes', the t-tests will be performed
0086 %                   on the mean amplitude within each time window
0087 %                   specified by time_wind.  This sacrifices temporal
0088 %                   resolution to increase test power by reducing the number
0089 %                   of comparisons.  If 'no', every single time point within
0090 %                   time_wind's time windows will be tested individually.
0091 %                   {default: 'no'}
0092 %   null_mean     - [number] The mean of the null hypothesis (i.e., mu) in
0093 %                   units of microvolts. {default: 0}
0094 %   exclude_chans - A cell array of channel labels to exclude from the
0095 %                   t-tests (e.g., {'A2','lle','rhe'}).  This option
0096 %                   sacrifices spatial resolution to increase test power by
0097 %                   reducing the number of comparisons. Use headinfo.m to see
0098 %                   the channel labels stored in the GND 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 t-tests
0102 %                   (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.m to see the channel labels stored in the GND
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 t-tests using the
0120 %                   function gui_erp.m. The GUI vizualizes the grand average
0121 %                   ERPs in each bin via various stats (uV, t-scores), shows
0122 %                   topographies at individual time points, and illustrates
0123 %                   which electrodes significantly differ from the null
0124 %                   hypothesis.  This option does not work if mean_wind
0125 %                   option is set to 'yes.' This GUI can be reproduced using
0126 %                   the function gui_erp.m. {default: 'yes'}
0127 %   plot_raster   - ['yes' or 'no'] If 'yes', a two-dimensional (time x channel)
0128 %                   binary "raster" diagram is created to illustrate the
0129 %                   results of the t-tests.  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 time 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 time window are produced.  More
0139 %                   specifically, two figures are produced: one showing the
0140 %                   topographies in uV 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_wind 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., FDR method used,
0149 %                   family-wise q level, etc...). If mean_wind 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 time point/electrode in a simple way. When
0153 %                   importing this file into a spreadsheet be sure NOT to
0154 %                   count consecutive spaces as multiple delimiters. If bh
0155 %                   or bh FDR control procedures are used, FDR adjusted
0156 %                   p-values (also called "q-values") will be output to the
0157 %                   text file.  If method bky is used, unadjusted p-values
0158 %                   will be output since it is not clear how to compute FDR
0159 %                   adjusted p-values for this method. {default: none}
0160 %   save_GRP      - ['yes' or 'no'] If 'yes', the GRP variable will be
0161 %                   saved to disk after the t-tests have been completed
0162 %                   and added to it. User will first be prompted to verify
0163 %                   file name and path. {default: 'yes'}
0164 %
0165 % Outputs:
0166 %   GND           - GND structure variable.  This is the same as
0167 %                   the input GND variable with one addition: the
0168 %                   field GND.t_tests will contain the results of the
0169 %                   t-tests and the test parameters.
0170 %   p_values      - A two-dimensional matrix (channel x time) of the
0171 %                   p-values of each comparison (no correction for multiple
0172 %                   comparisons).
0173 %   data_t        - A two-dimensional matrix (channel x time) of the
0174 %                   t-scores of each comparison.
0175 %   crit_t        - The critical t-score(s) for the test.  Any t-scores
0176 %                   that are more extreme than the critical t-score(s)
0177 %                   significantly deviate from 0.
0178 %   adj_p         - FDR corrected p-values (also called q-values). Note,
0179 %                   FDR corrected p-values can be greater than 1. For bky
0180 %                   procedure adj_p is NaN since it is not clear how to
0181 %                   compute adjusted p-values for this procedure.
0182 %
0183 %
0184 %   Note also that a great deal of information about the test is displayed
0185 %   in the MATLAB command window.  You can easiy record of all this
0186 %   information to a text file using the MATLAB command "diary."
0187 %
0188 % Global Variables:
0189 %   VERBLEVEL = Mass Univariate ERP Toolbox level of verbosity (i.e., tells
0190 %               functions how much to report about what they're doing during
0191 %               runtime) set by the optional function argument 'verblevel'
0192 %
0193 % Notes:
0194 % -To add a difference wave to a GND variable, use the function "bin_dif.m".
0195 %
0196 % References:
0197 %   Benjamini, Y., & Hochberg, Y. (1995). Controlling the false discovery
0198 % rate: A practical and powerful approach to multiple testing. Journal of
0199 % the Royal Statistical Society. Series B (Methodological), 57(1), 289-300.
0200 %
0201 %   Benjamini, Y., Krieger, A. M., & Yekutieli, D. (2006). Adaptive linear
0202 % step-up procedures that control the false discovery rate. Biometrika,
0203 % 93(3), 491-507.
0204 %
0205 %   Benjamini, Y., & Yekutieli, D. (2001). The control of the false
0206 % discovery rate in multiple testing under dependency. The Annals of
0207 % Statistics, 29(4), 1165-1188.
0208 %
0209 % Author:
0210 % David Groppe
0211 % Kutaslab, 5/2010
0212 
0213 
0214 %%%%%%%%%%%%%%%% FUTURE WORK %%%%%%%%%%%%%%%%%
0215 %
0216 
0217 %%%%%%%%%%%%%%%% REVISION LOG %%%%%%%%%%%%%%%%%
0218 % 4/13/2011-FDR corrected p-values added for by and bh procedures. I don't
0219 % know if there's a way to compute them for bky procedure.
0220 
0221 
0222 function [GND, p_values, data_t, crit_t, adj_p]=tfdrGND(GND_or_fname,bin,varargin)
0223 
0224 global VERBLEVEL;
0225 
0226 p=inputParser;
0227 p.addRequired('GND_or_fname',@(x) ischar(x) || isstruct(x));
0228 p.addRequired('bin',@(x) isnumeric(x) && (length(x)==1) && (x>0));
0229 p.addParamValue('tail',0,@(x) isnumeric(x) && (length(x)==1));
0230 p.addParamValue('q',0.05,@(x) isnumeric(x) && (x>0) && (x<1));
0231 p.addParamValue('method','bh',@(x) strcmpi(x,'bh') || strcmpi(x,'by') || strcmpi(x,'bky'));
0232 p.addParamValue('time_wind',[],@(x) isnumeric(x) && (size(x,2)==2));
0233 p.addParamValue('time_block_dur',[],@isnumeric);
0234 p.addParamValue('mean_wind','no',@(x) ischar(x) && (strcmpi(x,'yes') || strcmpi(x,'no')));
0235 p.addParamValue('null_mean',0,@(x) isnumeric(x) && (length(x)==1));
0236 p.addParamValue('exclude_chans',[],@(x) ischar(x) || iscell(x));
0237 p.addParamValue('include_chans',[],@(x) ischar(x) || iscell(x));
0238 p.addParamValue('verblevel',[],@(x) isnumeric(x) && (length(x)==1));
0239 p.addParamValue('plot_gui','yes',@(x) ischar(x) && (strcmpi(x,'yes') || strcmpi(x,'no')));
0240 p.addParamValue('plot_raster','yes',@(x) ischar(x) && (strcmpi(x,'yes') || strcmpi(x,'no')));
0241 p.addParamValue('plot_mn_topo',[],@(x) ischar(x) && (strcmpi(x,'yes') || strcmpi(x,'no')));
0242 p.addParamValue('output_file',[],@ischar);
0243 p.addParamValue('save_GND','yes',@(x) ischar(x) && (strcmpi(x,'yes') || strcmpi(x,'no')));
0244 
0245 p.parse(GND_or_fname,bin,varargin{:});
0246 
0247 
0248 if isempty(p.Results.verblevel),
0249     if isempty(VERBLEVEL),
0250         VERBLEVEL=2;
0251     end
0252 else
0253    VERBLEVEL=p.Results.verblevel; 
0254 end
0255     
0256 mean_wind=str2bool(p.Results.mean_wind);
0257 
0258 %Load GND struct
0259 if ischar(GND_or_fname),
0260     fprintf('Loading GND struct from file %s.\n',GND_or_fname);
0261     load(GND_or_fname,'-MAT');
0262     if ~exist('GND')
0263         error('File %s does not contain a GND variable.',GND_or_fname);
0264     end
0265 else
0266     GND=GND_or_fname;
0267     clear GND_or_fname;
0268     fldnames=fieldnames(GND);
0269     if ismember('group_desc',fldnames),
0270        error('You passed a GRP variable to this function instead of a GND variable.'); 
0271     end
0272 end
0273 [n_chan, n_pt, n_bin, total_subs]=size(GND.indiv_erps);
0274 VerbReport(sprintf('Experiment: %s',GND.exp_desc),2,VERBLEVEL);
0275 
0276 if (bin>n_bin),
0277     error('There is no Bin %d in this GND variable.',bin); 
0278 end
0279 
0280 %Use only subs with data in relevant bin(s)
0281 use_subs=find(GND.indiv_bin_ct(:,p.Results.bin));
0282 n_sub=length(use_subs);
0283 VerbReport(sprintf('%d out of %d participants have data in relevant bin.',n_sub,total_subs), ...
0284     1,VERBLEVEL);
0285 
0286 
0287 %% Figure out which channels to ignore if any
0288 %But first make sure exclude & include options were not both used.
0289 if ~isempty(p.Results.include_chans) && ~isempty(p.Results.exclude_chans)
0290     error('You cannot use BOTH ''include_chans'' and ''exclude_chans'' options.');
0291 end
0292 if ischar(p.Results.exclude_chans),
0293     exclude_chans{1}=p.Results.exclude_chans;
0294 elseif isempty(p.Results.exclude_chans)
0295     exclude_chans=[];
0296 else
0297     exclude_chans=p.Results.exclude_chans;
0298 end
0299 if ischar(p.Results.include_chans),
0300     include_chans{1}=p.Results.include_chans;
0301 elseif isempty(p.Results.include_chans)
0302     include_chans=[];
0303 else
0304     include_chans=p.Results.include_chans;
0305 end
0306 
0307 % exclude and include chan options
0308 if ~isempty(exclude_chans),
0309     ignore_chans=zeros(1,length(exclude_chans)); %preallocate mem
0310     ct=0;
0311     for x=1:length(exclude_chans),
0312         found=0;
0313         for c=1:n_chan,
0314             if strcmpi(exclude_chans{x},GND.chanlocs(c).labels),
0315                 found=1;
0316                 ct=ct+1;
0317                 ignore_chans(ct)=c;
0318             end
0319         end
0320         if ~found,
0321             watchit(sprintf('I attempted to exclude %s.  However no such electrode was found in GND variable.', ...
0322                 exclude_chans{x}));
0323         end
0324     end
0325     ignore_chans=ignore_chans(1:ct);
0326     use_chans=setdiff(1:n_chan,ignore_chans);
0327 elseif ~isempty(include_chans),
0328     use_chans=zeros(1,length(include_chans)); %preallocate mem
0329     ct=0;
0330     for x=1:length(include_chans),
0331         found=0;
0332         for c=1:n_chan,
0333             if strcmpi(include_chans{x},GND.chanlocs(c).labels),
0334                 found=1;
0335                 ct=ct+1;
0336                 use_chans(ct)=c;
0337             end
0338         end
0339         if ~found,
0340             watchit(sprintf('I attempted to include %s.  However no such electrode was found in GND variable.', ...
0341                 include_chans{x}));
0342         end
0343     end
0344     use_chans=use_chans(1:ct);
0345 else
0346     use_chans=1:n_chan;
0347 end
0348 
0349 
0350 %% Find time points
0351 if isempty(p.Results.time_wind),
0352     time_wind=[0 GND.time_pts(end)]; %default time window
0353 else
0354     time_wind=p.Results.time_wind;
0355 end
0356 time_wind=sort(time_wind,2); %first make sure earlier of each pair of time points is first
0357 time_wind=sort(time_wind,1); %next sort time windows from earliest to latest onset
0358 n_wind=size(time_wind,1);
0359 if ~isempty(p.Results.time_block_dur),
0360     tbd=p.Results.time_block_dur;
0361     n_block=length(tbd);
0362     if (n_block>1) && (n_block~=n_wind),
0363        error('If you specify more than one time block duration you need to provide exactly one duration for every time window (in this case %d).',n_wind); 
0364     elseif (n_block==1) && (n_wind>1),
0365         tbd=repmat(tbd,1,n_wind);
0366     end
0367         
0368     t_winds=[];
0369     one_step=1000/GND.srate;
0370     for a=1:n_wind,
0371         wind_strt=time_wind(a,1);
0372         wind_stop=time_wind(a,2);
0373         new_winds=[wind_strt:tbd(a):wind_stop];
0374         for b=1:(length(new_winds)-1),
0375             t_winds=[t_winds; new_winds(b) new_winds(b+1)-one_step];
0376         end
0377     end
0378     time_wind=t_winds;
0379     clear t_winds;
0380     n_wind=size(time_wind,1);
0381 end
0382 
0383 if mean_wind,
0384     use_tpts=cell(1,n_wind);
0385 else
0386     use_tpts=[];
0387 end
0388 for a=1:n_wind,
0389     VerbReport(sprintf('Time Window #%d:',a),1,VERBLEVEL);
0390     VerbReport(sprintf('Attempting to use time boundaries of %d to %d ms for hypothesis test.',time_wind(a,1),time_wind(a,2)), ...
0391         1,VERBLEVEL);
0392     start_tpt=find_tpt(time_wind(a,1),GND.time_pts);
0393     end_tpt=find_tpt(time_wind(a,2),GND.time_pts);
0394     if mean_wind,
0395         use_tpts{a}=[start_tpt:end_tpt];
0396     else
0397         use_tpts=[use_tpts [start_tpt:end_tpt]];
0398     end
0399     %replace desired time points with closest matches
0400     time_wind(a,1)=GND.time_pts(start_tpt);
0401     time_wind(a,2)=GND.time_pts(end_tpt);
0402     VerbReport(sprintf('Exact window boundaries are %d to %d ms (that''s from time point %d to %d).', ...
0403         time_wind(a,1),time_wind(a,2),start_tpt,end_tpt),1,VERBLEVEL);
0404 end
0405 if ~mean_wind,
0406     use_tpts=unique(use_tpts); %sorts time points and gets rid of any redundant time points
0407 end
0408 
0409 %% Compile data
0410 if mean_wind,
0411     %Take mean amplitude in time blocks and then test
0412     erps=zeros(length(use_chans),n_wind,n_sub);
0413     for a=1:n_wind,
0414         for sub=1:n_sub,
0415             erps(:,a,sub)=mean(GND.indiv_erps(use_chans,use_tpts{a},bin,use_subs(sub)),2);
0416         end
0417     end
0418 else
0419     %Use every single time point in time window(s)
0420     n_use_tpts=length(use_tpts);
0421     erps=zeros(length(use_chans),n_use_tpts,n_sub);    
0422     for sub=1:n_sub,
0423         erps(:,:,sub)=GND.indiv_erps(use_chans,use_tpts,bin,use_subs(sub));
0424     end
0425 end
0426 
0427 
0428 %% Report tail of test & q levels
0429 VerbReport(sprintf('Testing null hypothesis that the grand average ERPs in Bin %d (%s) have a mean of %f microvolts.',bin, ...
0430     GND.bin_info(bin).bindesc,p.Results.null_mean),1,VERBLEVEL);
0431 if p.Results.tail==0
0432     VerbReport(sprintf('Alternative hypothesis is that the ERPs differ from %f (i.e., two-tailed test).',p.Results.null_mean), ...
0433         1,VERBLEVEL);
0434 elseif p.Results.tail<0,
0435     VerbReport(sprintf('Alternative hypothesis is that the ERPs are less than %f (i.e., lower-tailed test).',p.Results.null_mean), ...
0436         1,VERBLEVEL);
0437 else
0438     VerbReport(sprintf('Alternative hypothesis is that the ERPs are greater than %f (i.e., upper-tailed test).',p.Results.null_mean), ...
0439         1,VERBLEVEL);
0440 end
0441 
0442 
0443 [p_values, data_t]=fast_t1(erps-p.Results.null_mean,p.Results.tail,VERBLEVEL);
0444 switch lower(p.Results.method)
0445     case 'bh'
0446         VerbReport('FDR control procedure: Benjamini & Hochberg (independent or positive dependency)',1,VERBLEVEL);
0447         [h_rej, crit_p, adj_p]=fdr_bh(p_values,p.Results.q,'pdep','no');
0448     case 'by'
0449         VerbReport('FDR control procedure: Benjamini & Yekutieli (arbitrary dependency)',1,VERBLEVEL);
0450         [h_rej, crit_p, adj_p]=fdr_bh(p_values,p.Results.q,'dep','no');
0451     case 'bky'
0452         VerbReport('FDR control procedure: Benjamini, Krieger, & Yekutieli (two-stage)',1,VERBLEVEL);
0453         [h_rej, crit_p]=fdr_bky(p_values,p.Results.q,'no');
0454         adj_p=NaN;
0455 end
0456 
0457 sig_tpts=find(sum(h_rej));
0458 if isempty(sig_tpts),
0459     if p.Results.tail==0,
0460         crit_t=[NaN NaN];
0461     else
0462         crit_t=NaN;
0463     end    
0464     fprintf('ERPs are NOT significantly different from %f (q=%f) at any time point/window analyzed.\n', ...
0465         p.Results.null_mean,p.Results.q);
0466     if ~strcmpi(p.Results.method,'bky'),
0467         %don't have adjusted p-values for bky method
0468         fprintf('All FDR adjusted p-values>=%f\n',min(min(p_values)));
0469     end
0470 else
0471     crit_t=min(abs(data_t(crit_p==p_values)));
0472     if p.Results.tail<0,
0473         crit_t=-crit_t;
0474     elseif p.Results.tail==0,
0475         crit_t=[-crit_t crit_t];
0476     end
0477     
0478     %Command line summary of results
0479     VerbReport(['Critical t-score(s):' num2str(crit_t)],1,VERBLEVEL);
0480     if p.Results.tail
0481         %one-tailed test
0482         tw_alpha=1-cdf('t',max(abs(crit_t)),n_sub-1);
0483     else
0484         %two-tailed test
0485         tw_alpha=(1-cdf('t',max(abs(crit_t)),n_sub-1))*2;
0486     end
0487     VerbReport(sprintf('That corresponds to a test-wise alpha level of %f.',tw_alpha),1,VERBLEVEL);
0488     VerbReport(sprintf('Bonferroni test-wise alpha would be %f.',p.Results.q/numel(p_values)) ...
0489         ,1,VERBLEVEL);
0490     
0491     fprintf('Total number of significant differences: %d\n',sum(sum(h_rej)));
0492     fprintf('Estimated upper bound on expected number of false discoveries: %.1f\n',sum(sum(h_rej))*p.Results.q);
0493     fprintf('Significant differences from zero (in order of earliest to latest):\n');
0494     
0495     if ~strcmpi(p.Results.method,'bky'),
0496         %don't have adjusted p-values for bky method
0497         max_sig_p=0;
0498         min_sig_p=max(max(adj_p));
0499     end
0500     for t=sig_tpts,
0501         if mean_wind
0502             %time windows instead of time points
0503             fprintf('%d to %d ms, electrode(s): ',GND.time_pts(use_tpts{t}(1)), ...
0504                 GND.time_pts(use_tpts{t}(end)));
0505         else
0506             fprintf('%d ms, electrode(s): ',GND.time_pts(use_tpts(t)));
0507         end
0508         sig_elec=find(h_rej(:,t));
0509         ct=0;
0510         for c=sig_elec',
0511             ct=ct+1;
0512             if ~strcmpi(p.Results.method,'bky'),
0513                 %don't have adjusted p-values for bky method
0514                 if adj_p(c,t)>max_sig_p,
0515                     max_sig_p=adj_p(c,t);
0516                 end
0517                 if adj_p(c,t)<min_sig_p,
0518                     min_sig_p=adj_p(c,t);
0519                 end
0520             end
0521             if ct==length(sig_elec),
0522                 fprintf('%s.\n',GND.chanlocs(use_chans(c)).labels);
0523             else
0524                 fprintf('%s, ',GND.chanlocs(use_chans(c)).labels);
0525             end
0526         end
0527     end
0528     if ~strcmpi(p.Results.method,'bky'),
0529         fprintf('All significant corrected p-values are between %f and %f\n',max_sig_p,min_sig_p);
0530     end
0531 end
0532 
0533 
0534 %Add t-test results to GND struct
0535 n_t_tests=length(GND.t_tests);
0536 neo_test=n_t_tests+1;
0537 GND.t_tests(neo_test).bin=bin;
0538 GND.t_tests(neo_test).time_wind=time_wind;
0539 GND.t_tests(neo_test).used_tpt_ids=use_tpts;
0540 n_use_chans=length(use_chans);
0541 include_chans=cell(1,n_use_chans);
0542 for a=1:n_use_chans,
0543    include_chans{a}=GND.chanlocs(use_chans(a)).labels; 
0544 end
0545 GND.t_tests(neo_test).include_chans=include_chans;
0546 GND.t_tests(neo_test).used_chan_ids=use_chans;
0547 GND.t_tests(neo_test).mult_comp_method=p.Results.method;
0548 GND.t_tests(neo_test).n_perm=NaN;
0549 GND.t_tests(neo_test).desired_alphaORq=p.Results.q;
0550 GND.t_tests(neo_test).estimated_alpha=NaN;
0551 GND.t_tests(neo_test).null_mean=p.Results.null_mean;
0552 if mean_wind,
0553     GND.t_tests(neo_test).data_t=data_t;
0554     GND.t_tests(neo_test).mean_wind='yes';
0555 else
0556     GND.t_tests(neo_test).data_t='See GND.grands_t';
0557     GND.t_tests(neo_test).mean_wind='no';
0558 end
0559 GND.t_tests(neo_test).crit_t=crit_t;
0560 GND.t_tests(neo_test).df=length(use_subs)-1;
0561 GND.t_tests(neo_test).adj_pval=adj_p; % is NaN for BKY FDR procedure
0562 GND.t_tests(neo_test).fdr_rej=h_rej;
0563 GND.t_tests(neo_test).seed_state=NaN;
0564 GND.t_tests(neo_test).clust_info=NaN;
0565 GND.t_tests(neo_test).chan_hood=NaN;
0566 
0567 if strcmpi(p.Results.plot_raster,'yes'),
0568     sig_raster(GND,neo_test,'verblevel',0,'use_color','rgb');
0569 end
0570 
0571 if mean_wind,
0572     if strcmpi(p.Results.plot_mn_topo,'yes') || isempty(p.Results.plot_mn_topo),
0573         sig_topo(GND,neo_test,'units','t','verblevel',0); %t-score topographies
0574         sig_topo(GND,neo_test,'units','uV','verblevel',0); %microvolt topographies
0575     end
0576 else
0577     if strcmpi(p.Results.plot_gui,'yes'),
0578         gui_erp('initialize','GNDorGRP',GND,'t_test',neo_test,'stat','t','verblevel',1);
0579     end
0580 end
0581 
0582 %% Write results of test to text file if requested
0583 if ~isempty(p.Results.output_file)
0584     [fid msg]=fopen(p.Results.output_file,'w');
0585     if fid==-1,
0586         error('Cannot create file %s for writing.  According to fopen.m: %s.', ...
0587             p.Results.file,msg);
0588     else
0589         %Write header column of times
0590         % Leave first column blank for channel labels
0591         if mean_wind,
0592             for t=1:n_wind
0593                 fprintf(fid,' %d-%d',GND.time_pts(use_tpts{t}(1)), ...
0594                     GND.time_pts(use_tpts{t}(end)));
0595             end
0596             
0597             %write a couple spaces and then write header for t-scores
0598             fprintf(fid,'  ');
0599             for t=1:n_wind
0600                 fprintf(fid,' %d-%d',GND.time_pts(use_tpts{t}(1)), ...
0601                     GND.time_pts(use_tpts{t}(end)));
0602             end
0603         else
0604             for t=use_tpts,
0605                 fprintf(fid,' %d',GND.time_pts(t));
0606             end
0607         end
0608         fprintf(fid,' Milliseconds\n');
0609         
0610         % Write channel labels and p-values
0611         chan_ct=0;
0612         for c=use_chans,
0613             chan_ct=chan_ct+1;
0614             fprintf(fid,'%s',GND.chanlocs(c).labels);
0615             if strcmpi(p.Results.method,'bky'),
0616                 %print uncorrected p-values for bky method since I don't
0617                 %think there's a way to compute them
0618                 for t=1:length(use_tpts),
0619                     fprintf(fid,' %f',p_values(chan_ct,t));
0620                 end
0621                 fprintf(fid,' p-value(uncorrected)');
0622             else
0623                 for t=1:length(use_tpts),
0624                     fprintf(fid,' %f',adj_p(chan_ct,t));
0625                 end
0626                 fprintf(fid,' p-value(FDR_corrected)');
0627             end
0628             
0629             if mean_wind,
0630                 %write a couple spaces and then write t-scores if mean amp
0631                 %in time windows used
0632                 fprintf(fid,' ');
0633                 for t=1:n_wind
0634                     fprintf(fid,' %f',data_t(chan_ct,t));
0635                 end
0636                 fprintf(fid,' t-score \n');
0637             else
0638                 fprintf(fid,'\n');
0639             end
0640         end
0641         
0642         % Write t-test details
0643         fprintf(fid,'Experiment: %s\n',GND.exp_desc);
0644         fprintf(fid,'Test_of_null_hypothesis_that_Bin_%d_equals: %d\n',bin,p.Results.null_mean);
0645         fprintf(fid,'#_of_time_windows: %d\n',n_wind);
0646         fprintf(fid,'FDR_method: %s\n',p.Results.method);
0647         fprintf(fid,'Tail_of_test: ');
0648         if ~p.Results.tail,
0649             fprintf(fid,'Two_tailed\n');
0650             fprintf(fid,'Critical_t_scores: %f %f\n',crit_t(1),crit_t(2));
0651         elseif p.Results.tail>0
0652             fprintf(fid,'Upper_tailed\n');
0653             fprintf(fid,'Critical_t_score: %f\n',crit_t(1));
0654         else
0655             fprintf(fid,'Lower_tailed\n');
0656             fprintf(fid,'Critical_t_score: %f\n',crit_t(1));
0657         end
0658         fprintf(fid,'Critical_unadjusted_p-value: %f\n',crit_p);
0659         fprintf(fid,'Total_#_of_significant_differences: %d\n',sum(sum(h_rej)));
0660         fprintf(fid,'Estimated_upper_bound_on_expected_#_of_false_discoveries: %.1f\n',sum(sum(h_rej))*p.Results.q);
0661         fprintf(fid,'Degrees_of_freedom: %d\n',length(use_subs)-1);
0662         fprintf(fid,'q_level: %f\n',p.Results.q);
0663         
0664         % # of participants and filenames
0665         fprintf(fid,'#_of_participants: %d\n',length(use_subs));
0666         fprintf(fid,'Participant_names: \n');
0667         for s=1:length(use_subs),
0668             fprintf(fid,'%s\n',GND.indiv_subnames{use_subs(s)});
0669         end
0670     end
0671     fclose(fid);
0672 end
0673 
0674 if ~strcmpi(p.Results.save_GND,'no'),
0675     GND=save_erps(GND);
0676 end
0677 
0678 %
0679 %% %%%%%%%%%%%%%%%%%%%%% function str2bool() %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0680 %
0681 function bool=str2bool(str)
0682 %function bool=str2bool(str)
0683 
0684 if ischar(str),
0685     if strcmpi(str,'yes') || strcmpi(str,'y')
0686         bool=1;
0687     else
0688         bool=0;
0689     end
0690 else
0691    bool=str; 
0692 end
0693

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