ROOT logo
// @(#)root/roostats:$Id$
// Author: Kyle Cranmer, Sven Kreiss   23/05/10
/*************************************************************************
 * 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.             *
 *************************************************************************/

/**
Same purpose as HybridCalculatorOriginal, but different implementation.

This is the "generic" version that works with any TestStatSampler. The
HybridCalculator derives from this class but explicitly uses the
ToyMCSampler as its TestStatSampler.
*/

#include "RooStats/HybridCalculatorGeneric.h"
#include "RooStats/HybridPlot.h"

#include "RooStats/ToyMCSampler.h"
#include "RooStats/RatioOfProfiledLikelihoodsTestStat.h"

#include "RooAddPdf.h"


ClassImp(RooStats::HybridCalculatorGeneric)

using namespace RooStats;


//___________________________________
HybridCalculatorGeneric::HybridCalculatorGeneric(
                                     const RooAbsData &data,
                                     const ModelConfig &altModel,
                                     const ModelConfig &nullModel,
                                     TestStatSampler *sampler
                                     ) :
   fAltModel(&altModel),
   fNullModel(&nullModel),
   fData(&data),
   fPriorNuisanceNull(0),
   fPriorNuisanceAlt(0),
   fTestStatSampler(sampler),
   fDefaultSampler(0),
   fDefaultTestStat(0)
{
   // Constructor. When test stat sampler is not provided
   // uses ToyMCSampler and RatioOfProfiledLikelihoodsTestStat
   // and nToys = 1000.
   // User can : GetTestStatSampler()->SetNToys( # )
   if(!sampler){
      fDefaultTestStat
         = new RatioOfProfiledLikelihoodsTestStat(*nullModel.GetPdf(),
                                                  *altModel.GetPdf(),
                                                  altModel.GetSnapshot());

      fDefaultSampler = new ToyMCSampler(*fDefaultTestStat, 1000);
      fTestStatSampler = fDefaultSampler;
   }
}

//_____________________________________________________________
void HybridCalculatorGeneric::SetupSampler(const ModelConfig& model) const {
   // common setup for both models
   fNullModel->LoadSnapshot();
   fTestStatSampler->SetObservables(*fNullModel->GetObservables());
   fTestStatSampler->SetParametersForTestStat(*fNullModel->GetParametersOfInterest());

   // for this model
   model.LoadSnapshot();
   fTestStatSampler->SetSamplingDistName(model.GetName());
   fTestStatSampler->SetPdf(*model.GetPdf());
   fTestStatSampler->SetGlobalObservables(*model.GetGlobalObservables());
   fTestStatSampler->SetNuisanceParameters(*model.GetNuisanceParameters());

   if( (&model == fNullModel) && fPriorNuisanceNull){
     // Setup Priors for ad hoc Hybrid
     fTestStatSampler->SetPriorNuisance(fPriorNuisanceNull);
   } else if( (&model == fAltModel) && fPriorNuisanceAlt){
     // Setup Priors for ad hoc Hybrid
     fTestStatSampler->SetPriorNuisance(fPriorNuisanceAlt);
   } else if(model.GetNuisanceParameters()==NULL ||
             model.GetNuisanceParameters()->getSize()==0){
     oocoutI((TObject*)0,InputArguments)
       << "No nuisance parameters specified and no prior forced, reduces to simple hypothesis testing with no uncertainty" << endl;
   } else{
     // TODO principled case:
     // must create posterior from Model.PriorPdf and Model.Pdf

     // Note, we do not want to use "prior" for nuisance parameters:
     // fTestStatSampler->SetPriorNuisance(const_cast<RooAbsPdf*>(model.GetPriorPdf()));

     oocoutE((TObject*)0,InputArguments)  << "infering posterior from ModelConfig is not yet implemented" << endl;
   }
}

//____________________________________________________
HybridCalculatorGeneric::~HybridCalculatorGeneric()  {
   //  if(fPriorNuisanceNull) delete fPriorNuisanceNull;
   //  if(fPriorNuisanceAlt)  delete fPriorNuisanceAlt;
   if(fDefaultSampler)    delete fDefaultSampler;
   if(fDefaultTestStat)   delete fDefaultTestStat;
}

//____________________________________________________
HypoTestResult* HybridCalculatorGeneric::GetHypoTest() const {

   // several possibilities:
   // no prior nuisance given and no nuisance parameters: ok
   // no prior nuisance given but nuisance parameters: error
   // prior nuisance given for some nuisance parameters:
   //   - nuisance parameters are constant, so they don't float in test statistic
   //   - nuisance parameters are floating, so they do float in test statistic

   // TODO skreiss: really necessary?
   const_cast<ModelConfig*>(fNullModel)->GuessObsAndNuisance(*fData);
   const_cast<ModelConfig*>(fAltModel)->GuessObsAndNuisance(*fData);

   if( (fNullModel->GetNuisanceParameters()
        && fNullModel->GetNuisanceParameters()->getSize()>0
        && !fPriorNuisanceNull)
     || (fAltModel->GetNuisanceParameters()
         && fAltModel->GetNuisanceParameters()->getSize()>0
         && !fPriorNuisanceAlt)
       ){
     oocoutE((TObject*)0,InputArguments)  << "Must ForceNuisancePdf, inferring posterior from ModelConfig is not yet implemented" << endl;
     return 0;
   }

   if(   (!fNullModel->GetNuisanceParameters() && fPriorNuisanceNull)
      || (!fAltModel->GetNuisanceParameters()  && fPriorNuisanceAlt)
      || (fNullModel->GetNuisanceParameters()  && fNullModel->GetNuisanceParameters()->getSize()==0 && fPriorNuisanceNull)
       || (fAltModel->GetNuisanceParameters()  && fAltModel->GetNuisanceParameters()->getSize()>0   && !fPriorNuisanceAlt)
       ){
     oocoutE((TObject*)0,InputArguments)  << "Nuisance PDF specified, but the pdf doesn't know which parameters are the nuisance parameters.  Must set nuisance parameters in the ModelConfig" << endl;
     return 0;
   }


   // get a big list of all variables for convenient switching
   RooArgSet *nullParams = fNullModel->GetPdf()->getParameters(*fData);
   RooArgSet *altParams = fAltModel->GetPdf()->getParameters(*fData);
   // save all parameters so we can set them back to what they were
   RooArgSet *bothParams = fNullModel->GetPdf()->getParameters(*fData);
   bothParams->add(*altParams,false);
   RooArgSet *saveAll = (RooArgSet*) bothParams->snapshot();


   // evaluate test statistic on data
   RooArgSet nullP(*fNullModel->GetSnapshot());
   double obsTestStat = fTestStatSampler->EvaluateTestStatistic(*const_cast<RooAbsData*>(fData), nullP);
   oocoutP((TObject*)0,Generation) << "Test Statistic on data: " << obsTestStat << endl;

   // Generate sampling distribution for null
   SetupSampler(*fNullModel);
   if(PreNullHook(obsTestStat) != 0) {
      oocoutE((TObject*)0,Generation) << "PreNullHook did not return 0." << endl;
   }
   RooArgSet poiNull(*fNullModel->GetParametersOfInterest());
   SamplingDistribution* samp_null = fTestStatSampler->GetSamplingDistribution(poiNull);

   // set parameters back
   *bothParams = *saveAll;

   // Generate sampling distribution for alternate
   SetupSampler(*fAltModel);
   if(PreAltHook(obsTestStat) != 0) {
      oocoutE((TObject*)0,Generation) << "PreAltHook did not return 0." << endl;
   }
   RooArgSet poiAlt(*fAltModel->GetParametersOfInterest());
   SamplingDistribution* samp_alt = fTestStatSampler->GetSamplingDistribution(poiAlt);


   string resultname = "HybridCalculator_result";
   HypoTestResult* res = new HypoTestResult(resultname.c_str());
   res->SetPValueIsRightTail(fTestStatSampler->GetTestStatistic()->PValueIsRightTail());
   res->SetTestStatisticData(obsTestStat);
   res->SetAltDistribution(samp_alt);
   res->SetNullDistribution(samp_null);

   *bothParams = *saveAll;
   delete bothParams;
   delete saveAll;
   delete altParams;
   delete nullParams;

   return res;
}




 HybridCalculatorGeneric.cxx:1
 HybridCalculatorGeneric.cxx:2
 HybridCalculatorGeneric.cxx:3
 HybridCalculatorGeneric.cxx:4
 HybridCalculatorGeneric.cxx:5
 HybridCalculatorGeneric.cxx:6
 HybridCalculatorGeneric.cxx:7
 HybridCalculatorGeneric.cxx:8
 HybridCalculatorGeneric.cxx:9
 HybridCalculatorGeneric.cxx:10
 HybridCalculatorGeneric.cxx:11
 HybridCalculatorGeneric.cxx:12
 HybridCalculatorGeneric.cxx:13
 HybridCalculatorGeneric.cxx:14
 HybridCalculatorGeneric.cxx:15
 HybridCalculatorGeneric.cxx:16
 HybridCalculatorGeneric.cxx:17
 HybridCalculatorGeneric.cxx:18
 HybridCalculatorGeneric.cxx:19
 HybridCalculatorGeneric.cxx:20
 HybridCalculatorGeneric.cxx:21
 HybridCalculatorGeneric.cxx:22
 HybridCalculatorGeneric.cxx:23
 HybridCalculatorGeneric.cxx:24
 HybridCalculatorGeneric.cxx:25
 HybridCalculatorGeneric.cxx:26
 HybridCalculatorGeneric.cxx:27
 HybridCalculatorGeneric.cxx:28
 HybridCalculatorGeneric.cxx:29
 HybridCalculatorGeneric.cxx:30
 HybridCalculatorGeneric.cxx:31
 HybridCalculatorGeneric.cxx:32
 HybridCalculatorGeneric.cxx:33
 HybridCalculatorGeneric.cxx:34
 HybridCalculatorGeneric.cxx:35
 HybridCalculatorGeneric.cxx:36
 HybridCalculatorGeneric.cxx:37
 HybridCalculatorGeneric.cxx:38
 HybridCalculatorGeneric.cxx:39
 HybridCalculatorGeneric.cxx:40
 HybridCalculatorGeneric.cxx:41
 HybridCalculatorGeneric.cxx:42
 HybridCalculatorGeneric.cxx:43
 HybridCalculatorGeneric.cxx:44
 HybridCalculatorGeneric.cxx:45
 HybridCalculatorGeneric.cxx:46
 HybridCalculatorGeneric.cxx:47
 HybridCalculatorGeneric.cxx:48
 HybridCalculatorGeneric.cxx:49
 HybridCalculatorGeneric.cxx:50
 HybridCalculatorGeneric.cxx:51
 HybridCalculatorGeneric.cxx:52
 HybridCalculatorGeneric.cxx:53
 HybridCalculatorGeneric.cxx:54
 HybridCalculatorGeneric.cxx:55
 HybridCalculatorGeneric.cxx:56
 HybridCalculatorGeneric.cxx:57
 HybridCalculatorGeneric.cxx:58
 HybridCalculatorGeneric.cxx:59
 HybridCalculatorGeneric.cxx:60
 HybridCalculatorGeneric.cxx:61
 HybridCalculatorGeneric.cxx:62
 HybridCalculatorGeneric.cxx:63
 HybridCalculatorGeneric.cxx:64
 HybridCalculatorGeneric.cxx:65
 HybridCalculatorGeneric.cxx:66
 HybridCalculatorGeneric.cxx:67
 HybridCalculatorGeneric.cxx:68
 HybridCalculatorGeneric.cxx:69
 HybridCalculatorGeneric.cxx:70
 HybridCalculatorGeneric.cxx:71
 HybridCalculatorGeneric.cxx:72
 HybridCalculatorGeneric.cxx:73
 HybridCalculatorGeneric.cxx:74
 HybridCalculatorGeneric.cxx:75
 HybridCalculatorGeneric.cxx:76
 HybridCalculatorGeneric.cxx:77
 HybridCalculatorGeneric.cxx:78
 HybridCalculatorGeneric.cxx:79
 HybridCalculatorGeneric.cxx:80
 HybridCalculatorGeneric.cxx:81
 HybridCalculatorGeneric.cxx:82
 HybridCalculatorGeneric.cxx:83
 HybridCalculatorGeneric.cxx:84
 HybridCalculatorGeneric.cxx:85
 HybridCalculatorGeneric.cxx:86
 HybridCalculatorGeneric.cxx:87
 HybridCalculatorGeneric.cxx:88
 HybridCalculatorGeneric.cxx:89
 HybridCalculatorGeneric.cxx:90
 HybridCalculatorGeneric.cxx:91
 HybridCalculatorGeneric.cxx:92
 HybridCalculatorGeneric.cxx:93
 HybridCalculatorGeneric.cxx:94
 HybridCalculatorGeneric.cxx:95
 HybridCalculatorGeneric.cxx:96
 HybridCalculatorGeneric.cxx:97
 HybridCalculatorGeneric.cxx:98
 HybridCalculatorGeneric.cxx:99
 HybridCalculatorGeneric.cxx:100
 HybridCalculatorGeneric.cxx:101
 HybridCalculatorGeneric.cxx:102
 HybridCalculatorGeneric.cxx:103
 HybridCalculatorGeneric.cxx:104
 HybridCalculatorGeneric.cxx:105
 HybridCalculatorGeneric.cxx:106
 HybridCalculatorGeneric.cxx:107
 HybridCalculatorGeneric.cxx:108
 HybridCalculatorGeneric.cxx:109
 HybridCalculatorGeneric.cxx:110
 HybridCalculatorGeneric.cxx:111
 HybridCalculatorGeneric.cxx:112
 HybridCalculatorGeneric.cxx:113
 HybridCalculatorGeneric.cxx:114
 HybridCalculatorGeneric.cxx:115
 HybridCalculatorGeneric.cxx:116
 HybridCalculatorGeneric.cxx:117
 HybridCalculatorGeneric.cxx:118
 HybridCalculatorGeneric.cxx:119
 HybridCalculatorGeneric.cxx:120
 HybridCalculatorGeneric.cxx:121
 HybridCalculatorGeneric.cxx:122
 HybridCalculatorGeneric.cxx:123
 HybridCalculatorGeneric.cxx:124
 HybridCalculatorGeneric.cxx:125
 HybridCalculatorGeneric.cxx:126
 HybridCalculatorGeneric.cxx:127
 HybridCalculatorGeneric.cxx:128
 HybridCalculatorGeneric.cxx:129
 HybridCalculatorGeneric.cxx:130
 HybridCalculatorGeneric.cxx:131
 HybridCalculatorGeneric.cxx:132
 HybridCalculatorGeneric.cxx:133
 HybridCalculatorGeneric.cxx:134
 HybridCalculatorGeneric.cxx:135
 HybridCalculatorGeneric.cxx:136
 HybridCalculatorGeneric.cxx:137
 HybridCalculatorGeneric.cxx:138
 HybridCalculatorGeneric.cxx:139
 HybridCalculatorGeneric.cxx:140
 HybridCalculatorGeneric.cxx:141
 HybridCalculatorGeneric.cxx:142
 HybridCalculatorGeneric.cxx:143
 HybridCalculatorGeneric.cxx:144
 HybridCalculatorGeneric.cxx:145
 HybridCalculatorGeneric.cxx:146
 HybridCalculatorGeneric.cxx:147
 HybridCalculatorGeneric.cxx:148
 HybridCalculatorGeneric.cxx:149
 HybridCalculatorGeneric.cxx:150
 HybridCalculatorGeneric.cxx:151
 HybridCalculatorGeneric.cxx:152
 HybridCalculatorGeneric.cxx:153
 HybridCalculatorGeneric.cxx:154
 HybridCalculatorGeneric.cxx:155
 HybridCalculatorGeneric.cxx:156
 HybridCalculatorGeneric.cxx:157
 HybridCalculatorGeneric.cxx:158
 HybridCalculatorGeneric.cxx:159
 HybridCalculatorGeneric.cxx:160
 HybridCalculatorGeneric.cxx:161
 HybridCalculatorGeneric.cxx:162
 HybridCalculatorGeneric.cxx:163
 HybridCalculatorGeneric.cxx:164
 HybridCalculatorGeneric.cxx:165
 HybridCalculatorGeneric.cxx:166
 HybridCalculatorGeneric.cxx:167
 HybridCalculatorGeneric.cxx:168
 HybridCalculatorGeneric.cxx:169
 HybridCalculatorGeneric.cxx:170
 HybridCalculatorGeneric.cxx:171
 HybridCalculatorGeneric.cxx:172
 HybridCalculatorGeneric.cxx:173
 HybridCalculatorGeneric.cxx:174
 HybridCalculatorGeneric.cxx:175
 HybridCalculatorGeneric.cxx:176
 HybridCalculatorGeneric.cxx:177
 HybridCalculatorGeneric.cxx:178
 HybridCalculatorGeneric.cxx:179
 HybridCalculatorGeneric.cxx:180
 HybridCalculatorGeneric.cxx:181
 HybridCalculatorGeneric.cxx:182
 HybridCalculatorGeneric.cxx:183
 HybridCalculatorGeneric.cxx:184
 HybridCalculatorGeneric.cxx:185
 HybridCalculatorGeneric.cxx:186
 HybridCalculatorGeneric.cxx:187
 HybridCalculatorGeneric.cxx:188
 HybridCalculatorGeneric.cxx:189
 HybridCalculatorGeneric.cxx:190
 HybridCalculatorGeneric.cxx:191
 HybridCalculatorGeneric.cxx:192
 HybridCalculatorGeneric.cxx:193
 HybridCalculatorGeneric.cxx:194