Clover coverage report - baseCode - 0.2.5
Coverage timestamp: Tue Apr 12 2005 11:31:58 EDT
file stats: LOC: 320   Methods: 13
NCLOC: 109   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
MetaAnalysis.java 38.9% 40.3% 38.5% 39.7%
coverage coverage
 1   
 package baseCode.math.metaanalysis;
 2   
 
 3   
 import baseCode.math.Constants;
 4   
 import cern.colt.list.DoubleArrayList;
 5   
 import cern.jet.stat.Descriptive;
 6   
 import cern.jet.stat.Probability;
 7   
 
 8   
 /**
 9   
  * Statistics for meta-analysis. Methods from Cooper and Hedges (CH); Hunter and Schmidt (HS).
 10   
  * <p>
 11   
  * In this class "conditional variance" means the variance for one data set. Unconditional means "between data set", or
 12   
  * across data set.
 13   
  * <p>
 14   
  * Copyright (c) 2004
 15   
  * </p>
 16   
  * <p>
 17   
  * Institution: Columbia University
 18   
  * </p>
 19   
  * 
 20   
  * @author Paul Pavlidis
 21   
  * @version $Id: MetaAnalysis.java,v 1.5 2005/03/21 18:01:03 pavlidis Exp $
 22   
  */
 23   
 
 24   
 public abstract class MetaAnalysis {
 25   
 
 26   
    /**
 27   
     * Fisher's method for combining p values. (Cooper and Hedges 15-8)
 28   
     * 
 29   
     * @param pvals DoubleArrayList
 30   
     * @return double
 31   
     */
 32  0
    protected double fisherCombinePvalues( DoubleArrayList pvals ) {
 33  0
       double r = 0.0;
 34  0
       for ( int i = 0, n = pvals.size(); i < n; i++ ) {
 35  0
          r += Math.log( pvals.getQuick( i ) );
 36   
       }
 37  0
       r *= -2.0;
 38  0
       return Probability.chiSquare( r, 2.0 * pvals.size() );
 39   
    }
 40   
 
 41   
    /**
 42   
     * Fisher's method for combining p values (Cooper and Hedges 15-8)
 43   
     * <p>
 44   
     * Use for p values that have already been log transformed.
 45   
     * 
 46   
     * @param pvals DoubleArrayList
 47   
     * @return double
 48   
     */
 49  0
    protected double fisherCombineLogPvalues( DoubleArrayList pvals ) {
 50  0
       double r = 0.0;
 51  0
       for ( int i = 0, n = pvals.size(); i < n; i++ ) {
 52  0
          r += pvals.getQuick( i );
 53   
       }
 54  0
       r *= -2.0;
 55  0
       return Probability.chiSquare( r, 2.0 * pvals.size() );
 56   
    }
 57   
 
 58   
    /**
 59   
     * The "Q" statistic used to test homogeneity of effect sizes. (Cooper and Hedges 18-6)
 60   
     * 
 61   
     * @param effectSizes DoubleArrayList
 62   
     * @param variances DoubleArrayList
 63   
     * @param globalMean double
 64   
     * @return double
 65   
     */
 66  24
    protected double qStatistic( DoubleArrayList effectSizes, DoubleArrayList variances, double globalMean ) {
 67   
 
 68  0
       if ( !( effectSizes.size() == variances.size() ) ) throw new IllegalArgumentException( "Unequal sizes" );
 69   
 
 70  24
       double r = 0.0;
 71  24
       for ( int i = 0, n = effectSizes.size(); i < n; i++ ) {
 72  468
          r += Math.pow( effectSizes.getQuick( i ) - globalMean, 2.0 ) / variances.getQuick( i );
 73   
       }
 74  24
       return r;
 75   
    }
 76   
 
 77   
    /**
 78   
     * Test for statistical significance of Q.
 79   
     * 
 80   
     * @param Q - computed using qStatistic
 81   
     * @param N - number of studies.
 82   
     * @see qStatistic
 83   
     * @return The upper tail chi-square probability for Q with N - degrees of freedom.
 84   
     */
 85  0
    public double qTest( double Q, double N ) {
 86  0
       return Probability.chiSquareComplemented( N - 1, Q );
 87   
    }
 88   
 
 89   
    /**
 90   
     * General formula for weighted mean of effect sizes. Cooper and Hedges 18-1, or HS pg. 100.
 91   
     * <p>
 92   
     * In HS, the weights are simply the sample sizes. For CH, the weights are 1/v for a fixed effect model. Under a
 93   
     * random effects model, we would use 1/(v + v_bs) where v_bs is the between-studies variance.
 94   
     * 
 95   
     * @param effectSizes
 96   
     * @param sampleSizes
 97   
     * @return
 98   
     */
 99  41
    protected double weightedMean( DoubleArrayList effectSizes, DoubleArrayList weights ) {
 100   
 
 101  0
       if ( !( effectSizes.size() == weights.size() ) ) throw new IllegalArgumentException( "Unequal sizes" );
 102   
 
 103  41
       double wm = 0.0;
 104  41
       for ( int i = 0; i < effectSizes.size(); i++ ) {
 105  800
          wm += weights.getQuick( i ) * effectSizes.getQuick( i );
 106   
       }
 107   
 
 108  41
       double s = Descriptive.sum( weights );
 109   
 
 110  0
       if ( s == 0.0 ) return 0.0;
 111  41
       return wm /= s;
 112   
    }
 113   
 
 114   
    /**
 115   
     * General formula for weighted mean of effect sizes including quality index scores for each value. Cooper and Hedges
 116   
     * 18-1, or HS pg. 100.
 117   
     * 
 118   
     * @param effectSizes
 119   
     * @param sampleSizes
 120   
     * @param qualityIndices
 121   
     * @return
 122   
     */
 123  0
    protected double weightedMean( DoubleArrayList effectSizes, DoubleArrayList weights, DoubleArrayList qualityIndices ) {
 124   
 
 125  0
       if ( !( effectSizes.size() == weights.size() && weights.size() == qualityIndices.size() ) )
 126  0
             throw new IllegalArgumentException( "Unequal sizes" );
 127   
 
 128  0
       double wm = 0.0;
 129  0
       for ( int i = 0; i < effectSizes.size(); i++ ) {
 130  0
          wm += weights.getQuick( i ) * effectSizes.getQuick( i ) * qualityIndices.getQuick( i );
 131   
       }
 132  0
       return wm /= ( Descriptive.sum( weights ) * Descriptive.sum( qualityIndices ) );
 133   
    }
 134   
 
 135   
    /**
 136   
     * CH 18-3. Can be used for fixed or random effects model, the variances just have to computed differently.
 137   
     * 
 138   
     * <pre>      
 139   
     *          v_dot = 1/sum_i=1&circ;k ( 1/v_i) 
 140   
     * </pre>
 141   
     * 
 142   
     * @param variances
 143   
     * @return
 144   
     */
 145  17
    protected double metaVariance( DoubleArrayList variances ) {
 146  17
       double var = 0.0;
 147  17
       for ( int i = 0; i < variances.size(); i++ ) {
 148  332
          var += 1.0 / variances.getQuick( i );
 149   
       }
 150  17
       if ( var == 0.0 ) {
 151  0
          var = Double.MIN_VALUE;
 152   
          //   throw new IllegalStateException( "Variance of zero" );
 153   
       }
 154  17
       return 1.0 / var;
 155   
    }
 156   
 
 157   
    /**
 158   
     * CH 18-3 version 2 for quality weighted. ( page 266 ) in Fixed effects model.
 159   
     * 
 160   
     * <pre>
 161   
     * 
 162   
     *  
 163   
     *   
 164   
     *    
 165   
     *     
 166   
     *      
 167   
     *       
 168   
     *          v_dot = [ sum_i=1&circ;k ( q_i &circ; 2 * w_i) ]/[ sum_i=1&circ;k  q_i * w_i ]&circ;2
 169   
     *        
 170   
     *       
 171   
     *      
 172   
     *     
 173   
     *    
 174   
     *   
 175   
     *  
 176   
     * </pre>
 177   
     * 
 178   
     * @param variances
 179   
     * @return
 180   
     */
 181  0
    protected double metaVariance( DoubleArrayList weights, DoubleArrayList qualityIndices ) {
 182  0
       double num = 0.0;
 183  0
       double denom = 0.0;
 184  0
       for ( int i = 0; i < weights.size(); i++ ) {
 185  0
          num += Math.pow( weights.getQuick( i ), 2 ) * qualityIndices.getQuick( i );
 186  0
          denom += Math.pow( weights.getQuick( i ) * qualityIndices.getQuick( i ), 2 );
 187   
       }
 188  0
       if ( denom == 0.0 ) {
 189  0
          throw new IllegalStateException( "Attempt to divide by zero." );
 190   
       }
 191  0
       return num / denom;
 192   
    }
 193   
 
 194   
    /**
 195   
     * Test statistic for H0: effectSize == 0. CH 18-5. For fixed effects model.
 196   
     * 
 197   
     * @param metaEffectSize
 198   
     * @param metaVariance
 199   
     * @return
 200   
     */
 201  0
    protected double metaZscore( double metaEffectSize, double metaVariance ) {
 202  0
       return Math.abs( metaEffectSize ) / Math.sqrt( metaVariance );
 203   
    }
 204   
 
 205   
    /**
 206   
     * CH sample variance under random effects model, equation 18-20
 207   
     * 
 208   
     * @param
 209   
     * @return
 210   
     */
 211  0
    protected double metaRESampleVariance( DoubleArrayList effectSizes ) {
 212  0
       return Descriptive.sampleVariance( effectSizes, Descriptive.mean( effectSizes ) );
 213   
    }
 214   
 
 215   
    /**
 216   
     * CH estimate of between-studies variance, equation 18-22, for random effects model.
 217   
     * 
 218   
     * @param effectSizes
 219   
     * @param variances
 220   
     * @return
 221   
     */
 222   
    //   protected double metaREVariance( DoubleArrayList effectSizes,
 223   
    //         DoubleArrayList variances ) {
 224   
    //      return Math.max( metaRESampleVariance( effectSizes )
 225   
    //            - Descriptive.mean( variances ), 0.0 );
 226   
    //   }
 227   
    /**
 228   
     * CH equation 18-23. Another estimator of the between-studies variance s<sup>2 </sup> for random effects model.
 229   
     * This is non-zero only if Q is larger than expected under the null hypothesis that the variance is zero.
 230   
     * 
 231   
     * <pre>
 232   
     * 
 233   
     *  
 234   
     *   
 235   
     *    s&circ;2 = [Q - ( k - 1 ) ] / c
 236   
     *    
 237   
     *   
 238   
     *  
 239   
     * </pre>
 240   
     * 
 241   
     * where
 242   
     * 
 243   
     * <pre>
 244   
     * 
 245   
     *  
 246   
     *   
 247   
     *    c = Max(sum_i=1&circ;k w_i - [ sum_i&circ;k w_i&circ;2 / sum_i&circ;k w_i ], 0)
 248   
     *    
 249   
     *   
 250   
     *  
 251   
     * </pre>
 252   
     * 
 253   
     * @param effectSizes
 254   
     * @param variances
 255   
     * @param weights
 256   
     * @return
 257   
     */
 258  7
    protected double metaREVariance( DoubleArrayList effectSizes, DoubleArrayList variances, DoubleArrayList weights ) {
 259   
 
 260  7
       if ( !( effectSizes.size() == weights.size() && weights.size() == variances.size() ) )
 261  0
             throw new IllegalArgumentException( "Unequal sizes" );
 262   
 
 263   
       // the weighted unconditional variance.
 264  7
       double q = qStatistic( effectSizes, variances, weightedMean( effectSizes, weights ) );
 265   
 
 266  7
       double c = Descriptive.sum( weights ) - Descriptive.sumOfSquares( weights ) / Descriptive.sum( weights );
 267  7
       return Math.max( ( q - ( effectSizes.size() - 1 ) ) / c, 0.0 );
 268   
    }
 269   
 
 270   
    /**
 271   
     * Under a random effects model, CH eqn. 18-24, we replace the conditional variance with the sum of the
 272   
     * between-sample variance and the conditional variance.
 273   
     * 
 274   
     * <pre>
 275   
     * 
 276   
     *  
 277   
     *     
 278   
     *    v_i&circ;* = sigma-hat_theta&circ;2 + v_i.
 279   
     *    
 280   
     *   
 281   
     *  
 282   
     * </pre>
 283   
     * 
 284   
     * @param variances Conditional variances
 285   
     * @param sampleVariance estimated...somehow.
 286   
     * @return
 287   
     */
 288  0
    protected DoubleArrayList metaREWeights( DoubleArrayList variances, double sampleVariance ) {
 289  0
       DoubleArrayList w = new DoubleArrayList( variances.size() );
 290   
 
 291  0
       for ( int i = 0; i < variances.size(); i++ ) {
 292  0
          if ( variances.getQuick( i ) <= 0 ) {
 293  0
             throw new IllegalStateException( "Negative or zero variance" );
 294   
          }
 295  0
          w.add( 1 / ( variances.getQuick( i ) + sampleVariance ) );
 296   
       }
 297   
 
 298  0
       return w;
 299   
    }
 300   
 
 301   
    /**
 302   
     * Weights under a fixed effects model. Simply w_i = 1/v_i. CH eqn 18-2.
 303   
     * @param variances 
 304   
     * @return
 305   
     */
 306  24
    protected DoubleArrayList metaFEWeights( DoubleArrayList variances ) {
 307  24
       DoubleArrayList w = new DoubleArrayList( variances.size() );
 308   
 
 309  24
       for ( int i = 0; i < variances.size(); i++ ) {
 310  468
          double v = variances.getQuick( i );
 311  468
          if ( v <=  Constants.SMALL) {
 312  0
             v = Constants.SMALL;
 313  0
             System.err.println( "Tiny variance    " + v );
 314   
          }
 315  468
          w.add( 1 / v );
 316   
       }
 317   
 
 318  24
       return w;
 319   
    }
 320   
 }