#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)
{
}
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)
{
}
HypoTestResult::~HypoTestResult()
{
}
void HypoTestResult::Append(const HypoTestResult* other) {
if(fNullDistr)
fNullDistr->Add(other->GetNullDistribution());
else
fNullDistr = other->GetNullDistribution();
if(fAltDistr)
fAltDistr->Add(other->GetAltDistribution());
else
fAltDistr = other->GetAltDistribution();
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();
for(size_t i=0; i < entries; i++) {
if( (GetPValueIsRightTail() && values[i] > fTestStatisticData) ||
(!GetPValueIsRightTail() && values[i] < fTestStatisticData)
) {
squares += pow(weights[i], 2);
}
}
squares /= entries;
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();
for(size_t i=0; i < entries; i++) {
if( (GetPValueIsRightTail() && values[i] < fTestStatisticData) ||
(!GetPValueIsRightTail() && values[i] > fTestStatisticData)
) {
squares += pow(weights[i], 2);
}
}
squares /= entries;
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();
for(size_t i=0; i < entries; i++) {
if( (GetPValueIsRightTail() && values[i] < fTestStatisticData) ||
(!GetPValueIsRightTail() && values[i] > fTestStatisticData)
) {
squares += pow(weights[i], 2);
}
}
squares /= entries;
return sqrt( (squares - pow(CLsplusb(),2)) / entries );
}
Double_t HypoTestResult::CLsError() const {
// #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);
}
void HypoTestResult::UpdatePValue(const SamplingDistribution* distr, Double_t *pvalue, Bool_t pIsRightTail) {
if(IsNaN(fTestStatisticData)) return;
if(distr) {
if(pIsRightTail)
*pvalue = distr->Integral(fTestStatisticData, RooNumber::infinity());
else
*pvalue = distr->Integral(-RooNumber::infinity(), fTestStatisticData);
}
}