ROOT logo
// @(#)root/roostats:$Id: HypoTestResult.cxx 36602 2010-11-11 16:52:13Z moneta $
// Author: Kyle Cranmer, Lorenzo Moneta, Gregory Schott, Wouter Verkerke, Sven Kreiss
/*************************************************************************
 * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

/*****************************************************************************
 * Project: RooStats
 * Package: RooFit/RooStats  
 * @(#)root/roofit/roostats:$Id: HypoTestResult.cxx 36602 2010-11-11 16:52:13Z moneta $
 * Authors:                     
 *   Kyle Cranmer, Lorenzo Moneta, Gregory Schott, Wouter Verkerke, Sven Kreiss
 *
 *****************************************************************************/



//_________________________________________________
/*
BEGIN_HTML
<p>
HypoTestResult is a base class for results from hypothesis tests.
Any tool inheriting from HypoTestCalculator can return a HypoTestResult.
As such, it stores a p-value for the null-hypothesis (eg. background-only) 
and an alternate hypothesis (eg. signal+background).  
The p-values can also be transformed into confidence levels (CLb, CLsplusb) in a trivial way.
The ratio of the CLsplusb to CLb is often called CLs, and is considered useful, though it is 
not a probability.
Finally, the p-value of the null can be transformed into a number of equivalent Gaussian sigma using the 
Significance method.
END_HTML
*/
//

#include "RooStats/HypoTestResult.h"
#include "RooAbsReal.h"

#ifndef RooStats_RooStatsUtils
#include "RooStats/RooStatsUtils.h"
#endif

#include <limits>
#define NaN numeric_limits<float>::quiet_NaN()
#define IsNaN(a) isnan(a)

ClassImp(RooStats::HypoTestResult) ;

using namespace RooStats;

//____________________________________________________________________
HypoTestResult::HypoTestResult(const char* name) : 
   TNamed(name,name),
   fNullPValue(NaN), fAlternatePValue(NaN),
   fTestStatisticData(NaN),
   fNullDistr(NULL), fAltDistr(NULL),
   fPValueIsRightTail(kTRUE)
{
   // Default constructor
}


//____________________________________________________________________
HypoTestResult::HypoTestResult(const char* name, Double_t nullp, Double_t altp) :
   TNamed(name,name),
   fNullPValue(nullp), fAlternatePValue(altp),
   fTestStatisticData(NaN),
   fNullDistr(NULL), fAltDistr(NULL),
   fPValueIsRightTail(kTRUE)
{
   // Alternate constructor
}


//____________________________________________________________________
HypoTestResult::~HypoTestResult()
{
   // Destructor

}


void HypoTestResult::Append(const HypoTestResult* other) {
   // Add additional toy-MC experiments to the current results.
   // Use the data test statistics of the added object if it is not already
   // set (otherwise, ignore the new one).

   if(fNullDistr)
      fNullDistr->Add(other->GetNullDistribution());
   else
      fNullDistr = other->GetNullDistribution();

   if(fAltDistr)
      fAltDistr->Add(other->GetAltDistribution());
   else
      fAltDistr = other->GetAltDistribution();

   // if no data is present use the other HypoTestResult's data
   if(IsNaN(fTestStatisticData)) fTestStatisticData = other->GetTestStatisticData();

   UpdatePValue(fNullDistr, &fNullPValue, fPValueIsRightTail);
   UpdatePValue(fAltDistr, &fAlternatePValue, !fPValueIsRightTail);
}


//____________________________________________________________________
void HypoTestResult::SetAltDistribution(SamplingDistribution *alt) {
   fAltDistr = alt;
   UpdatePValue(fAltDistr, &fAlternatePValue, !fPValueIsRightTail);
}
//____________________________________________________________________
void HypoTestResult::SetNullDistribution(SamplingDistribution *null) {
   fNullDistr = null;
   UpdatePValue(fNullDistr, &fNullPValue, fPValueIsRightTail);
}
//____________________________________________________________________
void HypoTestResult::SetTestStatisticData(const Double_t tsd) {
   fTestStatisticData = tsd;

   UpdatePValue(fNullDistr, &fNullPValue, fPValueIsRightTail);
   UpdatePValue(fAltDistr, &fAlternatePValue, !fPValueIsRightTail);
}
//____________________________________________________________________
void HypoTestResult::SetPValueIsRightTail(Bool_t pr) {
   fPValueIsRightTail = pr;

   UpdatePValue(fNullDistr, &fNullPValue, fPValueIsRightTail);
   UpdatePValue(fAltDistr, &fAlternatePValue, !fPValueIsRightTail);
}

//____________________________________________________________________
Bool_t HypoTestResult::HasTestStatisticData(void) const {
   return !IsNaN(fTestStatisticData);
}

Double_t HypoTestResult::NullPValueError() const {
   if(!fNullDistr  ||  !HasTestStatisticData()) return 0.0;

   double squares = 0.0;
   vector<Double_t> values = fNullDistr->GetSamplingDistribution();
   vector<Double_t> weights = fNullDistr->GetSampleWeights();
   size_t entries = values.size();


   // weights
   for(size_t i=0; i < entries; i++) {
      if( (GetPValueIsRightTail()  &&  values[i] > fTestStatisticData) ||
          (!GetPValueIsRightTail()  &&  values[i] < fTestStatisticData)
      ) {
         squares += pow(weights[i], 2);
      }
   }
   squares /= entries;

   //cout << "NullPValue Binomial error: " << TMath::Sqrt(NullPValue() * (1. - NullPValue()) / entries) << endl;
   return sqrt( (squares - pow(NullPValue(),2)) / entries );
}

//____________________________________________________________________
Double_t HypoTestResult::CLbError() const {
   if(!fNullDistr  ||  !HasTestStatisticData()) return 0.0;

   double squares = 0.0;
   vector<Double_t> values = fNullDistr->GetSamplingDistribution();
   vector<Double_t> weights = fNullDistr->GetSampleWeights();
   size_t entries = values.size();


   // weights
   for(size_t i=0; i < entries; i++) {
      if( (GetPValueIsRightTail()  &&  values[i] < fTestStatisticData) ||
          (!GetPValueIsRightTail()  &&  values[i] > fTestStatisticData)
      ) {
         squares += pow(weights[i], 2);
      }
   }
   squares /= entries;

   //cout << "CLb Binomial error: " << TMath::Sqrt(CLb() * (1. - CLb()) / entries) << endl;
   return sqrt( (squares - pow(CLb(),2)) / entries );
}

//____________________________________________________________________
Double_t HypoTestResult::CLsplusbError() const {
   if(!fAltDistr  ||  !HasTestStatisticData()) return 0.0;

   double squares = 0.0;
   vector<Double_t> values = fAltDistr->GetSamplingDistribution();
   vector<Double_t> weights = fAltDistr->GetSampleWeights();
   size_t entries = values.size();


   // weights
   for(size_t i=0; i < entries; i++) {
      if( (GetPValueIsRightTail()  &&  values[i] < fTestStatisticData) ||
          (!GetPValueIsRightTail()  &&  values[i] > fTestStatisticData)
      ) {
         squares += pow(weights[i], 2);
      }
   }
   squares /= entries;

   //cout << "CLs+b Binomial error: " << TMath::Sqrt(CLsplusb() * (1. - CLsplusb()) / entries) << endl;
   return sqrt( (squares - pow(CLsplusb(),2)) / entries );
}


//____________________________________________________________________
Double_t HypoTestResult::CLsError() const {
   // Returns an estimate of the error on CLs through combination of the
   // errors on CLb and CLsplusb:
   // BEGIN_LATEX
   // #sigma_{CL_s} = CL_s
   // #sqrt{#left( #frac{#sigma_{CL_{s+b}}}{CL_{s+b}} #right)^2 + #left( #frac{#sigma_{CL_{b}}}{CL_{b}} #right)^2}
   // END_LATEX

   if(!fAltDistr || !fNullDistr) return 0.0;

   unsigned const int n_b = fNullDistr->GetSamplingDistribution().size();
   unsigned const int n_sb = fAltDistr->GetSamplingDistribution().size();

   if (CLb() == 0 || CLsplusb() == 0) return 0.0;

   double cl_b_err = (1. - CLb()) / (n_b * CLb());
   double cl_sb_err = (1. - CLsplusb()) / (n_sb * CLsplusb());

   return CLs() * TMath::Sqrt(cl_b_err + cl_sb_err);
}



// private
//____________________________________________________________________
void HypoTestResult::UpdatePValue(const SamplingDistribution* distr, Double_t *pvalue, Bool_t pIsRightTail) {
   // updates the pvalue if sufficient data is available

   if(IsNaN(fTestStatisticData)) return;

   if(distr) {
      if(pIsRightTail)
         *pvalue = distr->Integral(fTestStatisticData, RooNumber::infinity());
      else
         *pvalue = distr->Integral(-RooNumber::infinity(), fTestStatisticData);
   }
}

 HypoTestResult.cxx:1
 HypoTestResult.cxx:2
 HypoTestResult.cxx:3
 HypoTestResult.cxx:4
 HypoTestResult.cxx:5
 HypoTestResult.cxx:6
 HypoTestResult.cxx:7
 HypoTestResult.cxx:8
 HypoTestResult.cxx:9
 HypoTestResult.cxx:10
 HypoTestResult.cxx:11
 HypoTestResult.cxx:12
 HypoTestResult.cxx:13
 HypoTestResult.cxx:14
 HypoTestResult.cxx:15
 HypoTestResult.cxx:16
 HypoTestResult.cxx:17
 HypoTestResult.cxx:18
 HypoTestResult.cxx:19
 HypoTestResult.cxx:20
 HypoTestResult.cxx:21
 HypoTestResult.cxx:22
 HypoTestResult.cxx:23
 HypoTestResult.cxx:24
 HypoTestResult.cxx:25
 HypoTestResult.cxx:26
 HypoTestResult.cxx:27
 HypoTestResult.cxx:28
 HypoTestResult.cxx:29
 HypoTestResult.cxx:30
 HypoTestResult.cxx:31
 HypoTestResult.cxx:32
 HypoTestResult.cxx:33
 HypoTestResult.cxx:34
 HypoTestResult.cxx:35
 HypoTestResult.cxx:36
 HypoTestResult.cxx:37
 HypoTestResult.cxx:38
 HypoTestResult.cxx:39
 HypoTestResult.cxx:40
 HypoTestResult.cxx:41
 HypoTestResult.cxx:42
 HypoTestResult.cxx:43
 HypoTestResult.cxx:44
 HypoTestResult.cxx:45
 HypoTestResult.cxx:46
 HypoTestResult.cxx:47
 HypoTestResult.cxx:48
 HypoTestResult.cxx:49
 HypoTestResult.cxx:50
 HypoTestResult.cxx:51
 HypoTestResult.cxx:52
 HypoTestResult.cxx:53
 HypoTestResult.cxx:54
 HypoTestResult.cxx:55
 HypoTestResult.cxx:56
 HypoTestResult.cxx:57
 HypoTestResult.cxx:58
 HypoTestResult.cxx:59
 HypoTestResult.cxx:60
 HypoTestResult.cxx:61
 HypoTestResult.cxx:62
 HypoTestResult.cxx:63
 HypoTestResult.cxx:64
 HypoTestResult.cxx:65
 HypoTestResult.cxx:66
 HypoTestResult.cxx:67
 HypoTestResult.cxx:68
 HypoTestResult.cxx:69
 HypoTestResult.cxx:70
 HypoTestResult.cxx:71
 HypoTestResult.cxx:72
 HypoTestResult.cxx:73
 HypoTestResult.cxx:74
 HypoTestResult.cxx:75
 HypoTestResult.cxx:76
 HypoTestResult.cxx:77
 HypoTestResult.cxx:78
 HypoTestResult.cxx:79
 HypoTestResult.cxx:80
 HypoTestResult.cxx:81
 HypoTestResult.cxx:82
 HypoTestResult.cxx:83
 HypoTestResult.cxx:84
 HypoTestResult.cxx:85
 HypoTestResult.cxx:86
 HypoTestResult.cxx:87
 HypoTestResult.cxx:88
 HypoTestResult.cxx:89
 HypoTestResult.cxx:90
 HypoTestResult.cxx:91
 HypoTestResult.cxx:92
 HypoTestResult.cxx:93
 HypoTestResult.cxx:94
 HypoTestResult.cxx:95
 HypoTestResult.cxx:96
 HypoTestResult.cxx:97
 HypoTestResult.cxx:98
 HypoTestResult.cxx:99
 HypoTestResult.cxx:100
 HypoTestResult.cxx:101
 HypoTestResult.cxx:102
 HypoTestResult.cxx:103
 HypoTestResult.cxx:104
 HypoTestResult.cxx:105
 HypoTestResult.cxx:106
 HypoTestResult.cxx:107
 HypoTestResult.cxx:108
 HypoTestResult.cxx:109
 HypoTestResult.cxx:110
 HypoTestResult.cxx:111
 HypoTestResult.cxx:112
 HypoTestResult.cxx:113
 HypoTestResult.cxx:114
 HypoTestResult.cxx:115
 HypoTestResult.cxx:116
 HypoTestResult.cxx:117
 HypoTestResult.cxx:118
 HypoTestResult.cxx:119
 HypoTestResult.cxx:120
 HypoTestResult.cxx:121
 HypoTestResult.cxx:122
 HypoTestResult.cxx:123
 HypoTestResult.cxx:124
 HypoTestResult.cxx:125
 HypoTestResult.cxx:126
 HypoTestResult.cxx:127
 HypoTestResult.cxx:128
 HypoTestResult.cxx:129
 HypoTestResult.cxx:130
 HypoTestResult.cxx:131
 HypoTestResult.cxx:132
 HypoTestResult.cxx:133
 HypoTestResult.cxx:134
 HypoTestResult.cxx:135
 HypoTestResult.cxx:136
 HypoTestResult.cxx:137
 HypoTestResult.cxx:138
 HypoTestResult.cxx:139
 HypoTestResult.cxx:140
 HypoTestResult.cxx:141
 HypoTestResult.cxx:142
 HypoTestResult.cxx:143
 HypoTestResult.cxx:144
 HypoTestResult.cxx:145
 HypoTestResult.cxx:146
 HypoTestResult.cxx:147
 HypoTestResult.cxx:148
 HypoTestResult.cxx:149
 HypoTestResult.cxx:150
 HypoTestResult.cxx:151
 HypoTestResult.cxx:152
 HypoTestResult.cxx:153
 HypoTestResult.cxx:154
 HypoTestResult.cxx:155
 HypoTestResult.cxx:156
 HypoTestResult.cxx:157
 HypoTestResult.cxx:158
 HypoTestResult.cxx:159
 HypoTestResult.cxx:160
 HypoTestResult.cxx:161
 HypoTestResult.cxx:162
 HypoTestResult.cxx:163
 HypoTestResult.cxx:164
 HypoTestResult.cxx:165
 HypoTestResult.cxx:166
 HypoTestResult.cxx:167
 HypoTestResult.cxx:168
 HypoTestResult.cxx:169
 HypoTestResult.cxx:170
 HypoTestResult.cxx:171
 HypoTestResult.cxx:172
 HypoTestResult.cxx:173
 HypoTestResult.cxx:174
 HypoTestResult.cxx:175
 HypoTestResult.cxx:176
 HypoTestResult.cxx:177
 HypoTestResult.cxx:178
 HypoTestResult.cxx:179
 HypoTestResult.cxx:180
 HypoTestResult.cxx:181
 HypoTestResult.cxx:182
 HypoTestResult.cxx:183
 HypoTestResult.cxx:184
 HypoTestResult.cxx:185
 HypoTestResult.cxx:186
 HypoTestResult.cxx:187
 HypoTestResult.cxx:188
 HypoTestResult.cxx:189
 HypoTestResult.cxx:190
 HypoTestResult.cxx:191
 HypoTestResult.cxx:192
 HypoTestResult.cxx:193
 HypoTestResult.cxx:194
 HypoTestResult.cxx:195
 HypoTestResult.cxx:196
 HypoTestResult.cxx:197
 HypoTestResult.cxx:198
 HypoTestResult.cxx:199
 HypoTestResult.cxx:200
 HypoTestResult.cxx:201
 HypoTestResult.cxx:202
 HypoTestResult.cxx:203
 HypoTestResult.cxx:204
 HypoTestResult.cxx:205
 HypoTestResult.cxx:206
 HypoTestResult.cxx:207
 HypoTestResult.cxx:208
 HypoTestResult.cxx:209
 HypoTestResult.cxx:210
 HypoTestResult.cxx:211
 HypoTestResult.cxx:212
 HypoTestResult.cxx:213
 HypoTestResult.cxx:214
 HypoTestResult.cxx:215
 HypoTestResult.cxx:216
 HypoTestResult.cxx:217
 HypoTestResult.cxx:218
 HypoTestResult.cxx:219
 HypoTestResult.cxx:220
 HypoTestResult.cxx:221
 HypoTestResult.cxx:222
 HypoTestResult.cxx:223
 HypoTestResult.cxx:224
 HypoTestResult.cxx:225
 HypoTestResult.cxx:226
 HypoTestResult.cxx:227
 HypoTestResult.cxx:228
 HypoTestResult.cxx:229
 HypoTestResult.cxx:230
 HypoTestResult.cxx:231
 HypoTestResult.cxx:232
 HypoTestResult.cxx:233
 HypoTestResult.cxx:234
 HypoTestResult.cxx:235
 HypoTestResult.cxx:236
 HypoTestResult.cxx:237
 HypoTestResult.cxx:238
 HypoTestResult.cxx:239
 HypoTestResult.cxx:240
 HypoTestResult.cxx:241
 HypoTestResult.cxx:242
 HypoTestResult.cxx:243
 HypoTestResult.cxx:244
 HypoTestResult.cxx:245
 HypoTestResult.cxx:246
 HypoTestResult.cxx:247
 HypoTestResult.cxx:248
 HypoTestResult.cxx:249