ROOT logo
// @(#)root/roostats:$Id: HypoTestResult.cxx 39934 2011-06-24 09:15:34Z 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 39934 2011-06-24 09:15:34Z 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),
   fBackgroundIsAlt(kFALSE)
{
   // 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),
   fBackgroundIsAlt(kFALSE)
{
   // 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, fNullPValueError, kTRUE);
   UpdatePValue(fAltDistr, fAlternatePValue, fAlternatePValueError, kFALSE);
}


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

   UpdatePValue(fNullDistr, fNullPValue, fNullPValueError, kTRUE);
   UpdatePValue(fAltDistr, fAlternatePValue, fAlternatePValueError, kFALSE);
}
//____________________________________________________________________
void HypoTestResult::SetPValueIsRightTail(Bool_t pr) {
   fPValueIsRightTail = pr;

   UpdatePValue(fNullDistr, fNullPValue, fNullPValueError, kTRUE);
   UpdatePValue(fAltDistr, fAlternatePValue, fAlternatePValueError, kFALSE);
}

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

Double_t HypoTestResult::NullPValueError() const {
   // compute error on Null pvalue 
   return fNullPValueError; 
}

//____________________________________________________________________
Double_t HypoTestResult::CLbError() const {
   // compute CLb error
   // Clb =  1 - NullPValue() 
   // must use opposite condition that routine above
   return fBackgroundIsAlt ? fAlternatePValueError : fNullPValueError;
}

//____________________________________________________________________
Double_t HypoTestResult::CLsplusbError() const {
   return fBackgroundIsAlt ? fNullPValueError : fAlternatePValueError;
}


//____________________________________________________________________
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 ) return numeric_limits<double>::infinity();

   double cl_b_err2 = pow(CLbError(),2);
   double cl_sb_err2 = pow(CLsplusbError(),2);

   return TMath::Sqrt(cl_sb_err2 + cl_b_err2 * pow(CLs(),2))/CLb();
}



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

   if(IsNaN(fTestStatisticData)) return;
   if(!distr) return;

   /* Got to be careful for discrete distributions:
    * To get the right behaviour for limits, the p-value must 
    * include the value of fTestStatistic both for Alt and Null cases
    */
   if(fPValueIsRightTail) {
      pvalue = distr->IntegralAndError(perror, fTestStatisticData, RooNumber::infinity(), kTRUE,
                                       kTRUE , kTRUE );   // always closed interval [ fTestStatistic, inf ] 

   }else{
      pvalue = distr->IntegralAndError(perror, -RooNumber::infinity(), fTestStatisticData, kTRUE,
                                       kTRUE,  kTRUE  ); // // always closed  [ -inf, fTestStatistic ]
   }
}

 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