Logo ROOT  
Reference Guide
Loading...
Searching...
No Matches
HypoTestCalculatorGeneric.cxx
Go to the documentation of this file.
1// @(#)root/roostats:$Id$
2// Author: Kyle Cranmer, Sven Kreiss 23/05/10
3/*************************************************************************
4 * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers. *
5 * All rights reserved. *
6 * *
7 * For the licensing terms see $ROOTSYS/LICENSE. *
8 * For the list of contributors see $ROOTSYS/README/CREDITS. *
9 *************************************************************************/
10
11/** \class RooStats::HypoTestCalculatorGeneric
12 \ingroup Roostats
13
14Common base class for the Hypothesis Test Calculators.
15It is not designed to use directly but via its derived classes
16
17Same purpose as HybridCalculatorOriginal, but different implementation.
18
19This is the "generic" version that works with any TestStatSampler. The
20HybridCalculator derives from this class but explicitly uses the
21ToyMCSampler as its TestStatSampler.
22
23*/
24
30
31#include "RooAddPdf.h"
32
33#include "RooRandom.h"
34
35
36
37using namespace RooStats;
38using std::endl, std::string;
39
40////////////////////////////////////////////////////////////////////////////////
41/// Constructor. When test stat sampler is not provided
42/// uses ToyMCSampler and RatioOfProfiledLikelihoodsTestStat
43/// and nToys = 1000.
44/// User can : GetTestStatSampler()->SetNToys( # )
45
47 const RooAbsData &data,
48 const ModelConfig &altModel,
49 const ModelConfig &nullModel,
50 TestStatSampler *sampler
51 ) :
52 fAltModel(&altModel),
53 fNullModel(&nullModel),
54 fData(&data),
55 fTestStatSampler(sampler),
56 fDefaultSampler(nullptr),
57 fDefaultTestStat(nullptr),
59{
60 if(!sampler){
63 *altModel.GetPdf(),
64 altModel.GetSnapshot());
65
66 auto toymcs = new ToyMCSampler(*fDefaultTestStat, 1000);
67 const bool dataIsBinned = dynamic_cast<const RooDataHist*>(fData);
68 if (dataIsBinned) {
69 // Ensure the ToyMCSampler generates toys with the same structure as the observed data.
70 // TODO: understand why this is needed only in the RooDataHist case,
71 // but results in backwards-incompatibility for RooDataSet, which
72 // manifests for example in the stressRooStats tests.
73 // See also: https://github.com/root-project/root/pull/20171
74 toymcs->SetProtoData(&data);
75 }
76 toymcs->SetGenerateBinned(dataIsBinned); // if observed is RooDataHist -> generate RooDataHist toys
77
78 fDefaultSampler = toymcs;
79 fTestStatSampler = toymcs;
80 }
81
82
83}
84
85////////////////////////////////////////////////////////////////////////////////
86/// common setup for both models
87
89 fNullModel->LoadSnapshot();
90 fTestStatSampler->SetObservables(*fNullModel->GetObservables());
91 fTestStatSampler->SetParametersForTestStat(*fNullModel->GetParametersOfInterest());
92
93 // for this model
94 model.LoadSnapshot();
95 fTestStatSampler->SetSamplingDistName(model.GetName());
96 fTestStatSampler->SetPdf(*model.GetPdf());
97 fTestStatSampler->SetNuisanceParameters(*model.GetNuisanceParameters());
98 // global observables or nuisance pdf will be set by the derived classes
99 // (e.g. Frequentist or HybridCalculator)
100}
101
102////////////////////////////////////////////////////////////////////////////////
103
108
109////////////////////////////////////////////////////////////////////////////////
110/// several possibilities:
111/// no prior nuisance given and no nuisance parameters: ok
112/// no prior nuisance given but nuisance parameters: error
113/// prior nuisance given for some nuisance parameters:
114/// - nuisance parameters are constant, so they don't float in test statistic
115/// - nuisance parameters are floating, so they do float in test statistic
116
118
119 // initial setup
120 PreHook();
121 const_cast<ModelConfig*>(fNullModel)->GuessObsAndNuisance(*fData->get());
122 const_cast<ModelConfig*>(fAltModel)->GuessObsAndNuisance(*fData->get());
123
124 std::unique_ptr<const RooArgSet> nullSnapshot {fNullModel->GetSnapshot()};
125 if(nullSnapshot == nullptr) {
126 oocoutE(nullptr,Generation) << "Null model needs a snapshot. Set using modelconfig->SetSnapshot(poi)." << std::endl;
127 return nullptr;
128 }
129
130 // CheckHook
131 if(CheckHook() != 0) {
132 oocoutE(nullptr,Generation) << "There was an error in CheckHook(). Stop." << std::endl;
133 return nullptr;
134 }
135
136 if (!fTestStatSampler || !fTestStatSampler->GetTestStatistic() ) {
137 oocoutE(nullptr,InputArguments) << "Test Statistic Sampler or Test Statistics not defined. Stop." << std::endl;
138 return nullptr;
139 }
140
141 // get a big list of all variables for convenient switching
142 std::unique_ptr<RooArgSet> altParams{fAltModel->GetPdf()->getParameters(*fData)};
143 // save all parameters so we can set them back to what they were
144 std::unique_ptr<RooArgSet> bothParams{fNullModel->GetPdf()->getParameters(*fData)};
145 bothParams->add(*altParams,false);
146 std::unique_ptr<RooArgSet> saveAll {(RooArgSet*) bothParams->snapshot()};
147
148 // check whether we have a ToyMCSampler and if so, keep a pointer to it
149 ToyMCSampler* toymcs = dynamic_cast<ToyMCSampler*>(fTestStatSampler );
150
151 // evaluate test statistic on data
152 RooArgSet nullP(*nullSnapshot);
153 double obsTestStat;
154
155 std::unique_ptr<RooArgList> allTS;
156 if( toymcs ) {
157 allTS = std::unique_ptr<RooArgList>{toymcs->EvaluateAllTestStatistics(*const_cast<RooAbsData*>(fData), nullP)};
158 if (!allTS) return nullptr;
159 //oocoutP(nullptr,Generation) << "All Test Statistics on data: " << std::endl;
160 //allTS->Print("v");
161 RooRealVar* firstTS = static_cast<RooRealVar*>(allTS->at(0));
162 obsTestStat = firstTS->getVal();
163 if (allTS->size()<=1) {
164 allTS = nullptr; // don't save
165 }
166
167 }else{
168 obsTestStat = fTestStatSampler->EvaluateTestStatistic(*const_cast<RooAbsData*>(fData), nullP);
169 }
170 oocoutP(nullptr,Generation) << "Test Statistic on data: " << obsTestStat << std::endl;
171
172 // set parameters back ... in case the evaluation of the test statistic
173 // modified something (e.g. a nuisance parameter that is not randomized
174 // must be set here)
175 bothParams->assign(*saveAll);
176
177 // If the pdf is not extended, the generation of toy datasets will fail if
178 // the number of events requested per toy is not set. In that case, we
179 // generate the same number of events as in the observed data.
180 auto setNEventsIfNeeded = [&](RooFit::ModelConfig const *modelConfig) {
181 int nEventsPerToy = toymcs->nEventsPerToy();
182 auto *pdf = modelConfig->GetPdf();
183 if (nEventsPerToy == 0 && (!pdf->canBeExtended() || pdf->expectedEvents(modelConfig->GetObservables()) <= 0)) {
184 toymcs->SetNEventsPerToy(fData->sumEntries());
185 }
186 };
187
188
189 // Generate sampling distribution for null
191 RooArgSet paramPointNull(*fNullModel->GetParametersOfInterest());
192 if(PreNullHook(&paramPointNull, obsTestStat) != 0) {
193 oocoutE(nullptr,Generation) << "PreNullHook did not return 0." << std::endl;
194 }
195 SamplingDistribution* samp_null = nullptr;
196 RooDataSet* detOut_null = nullptr;
197 if(toymcs) {
198 setNEventsIfNeeded(fNullModel);
199
200 detOut_null = toymcs->GetSamplingDistributions(paramPointNull);
201 if( detOut_null ) {
202 samp_null = new SamplingDistribution( detOut_null->GetName(), detOut_null->GetTitle(), *detOut_null );
203 if (detOut_null->get()->size()<=1) {
204 delete detOut_null;
205 detOut_null= nullptr;
206 }
207 }
208 }else samp_null = fTestStatSampler->GetSamplingDistribution(paramPointNull);
209
210 // set parameters back
211 bothParams->assign(*saveAll);
212
213 // Generate sampling distribution for alternate
215 RooArgSet paramPointAlt(*fAltModel->GetParametersOfInterest());
216 if(PreAltHook(&paramPointAlt, obsTestStat) != 0) {
217 oocoutE(nullptr,Generation) << "PreAltHook did not return 0." << std::endl;
218 }
219 SamplingDistribution* samp_alt = nullptr;
220 RooDataSet* detOut_alt = nullptr;
221 if(toymcs) {
222
223 // case of re-using same toys for every points
224 // set a given seed
225 unsigned int prevSeed = 0;
226 if (fAltToysSeed > 0) {
227 prevSeed = RooRandom::integer(std::numeric_limits<unsigned int>::max()-1)+1; // want to avoid zero value
229 }
230
231 setNEventsIfNeeded(fAltModel);
232
233 detOut_alt = toymcs->GetSamplingDistributions(paramPointAlt);
234 if( detOut_alt ) {
235 samp_alt = new SamplingDistribution( detOut_alt->GetName(), detOut_alt->GetTitle(), *detOut_alt );
236 if (detOut_alt->get()->size()<=1) {
237 delete detOut_alt;
238 detOut_alt= nullptr;
239 }
240 }
241
242 // restore the seed
243 if (prevSeed > 0) {
245 }
246
247 }else samp_alt = fTestStatSampler->GetSamplingDistribution(paramPointAlt);
248
249
250 // create result
251 string resultname = "HypoTestCalculator_result";
252 HypoTestResult* res = new HypoTestResult(resultname.c_str());
253 res->SetPValueIsRightTail(fTestStatSampler->GetTestStatistic()->PValueIsRightTail());
254 res->SetTestStatisticData(obsTestStat);
255 res->SetAltDistribution(samp_alt); // takes ownership of samp_alt
256 res->SetNullDistribution(samp_null); // takes ownership of samp_null
257 res->SetAltDetailedOutput( detOut_alt );
258 res->SetNullDetailedOutput( detOut_null );
259 res->SetAllTestStatisticsData( allTS.get() );
260
261 const RooArgSet *aset = GetFitInfo();
262 if (aset != nullptr) {
263 RooDataSet *dset = new RooDataSet("", "", *aset);
264 dset->add(*aset);
265 res->SetFitInfo( dset );
266 }
267
268 bothParams->assign(*saveAll);
269 PostHook();
270 return res;
271}
272
273////////////////////////////////////////////////////////////////////////////////
274/// to re-use same toys for alternate hypothesis
275
277 fAltToysSeed = RooRandom::integer(std::numeric_limits<unsigned int>::max()-1)+1;
278}
#define oocoutE(o, a)
#define oocoutP(o, a)
Storage_t::size_type size() const
Abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:56
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:107
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
Container class to hold N-dimensional binned data.
Definition RooDataHist.h:40
Container class to hold unbinned data.
Definition RooDataSet.h:32
const RooArgSet * get(Int_t index) const override
Return RooArgSet with coordinates of event 'index'.
void add(const RooArgSet &row, double weight, double weightError)
Add one ore more rows of data.
static UInt_t integer(UInt_t max, TRandom *generator=randomGenerator())
Return an integer uniformly distributed from [0,n-1].
Definition RooRandom.cxx:95
static TRandom * randomGenerator()
Return a pointer to a singleton random-number generator implementation.
Definition RooRandom.cxx:47
Variable that can be changed from the outside.
Definition RooRealVar.h:37
HypoTestResult * GetHypoTest() const override
inherited methods from HypoTestCalculator interface
virtual int PreNullHook(RooArgSet *, double) const
void SetupSampler(const ModelConfig &model) const
common setup for both models
virtual int PreAltHook(RooArgSet *, double) const
virtual const RooArgSet * GetFitInfo() const
void UseSameAltToys()
Set this for re-using always the same toys for alternate hypothesis in case of calls at different nul...
HypoTestCalculatorGeneric(const RooAbsData &data, const ModelConfig &altModel, const ModelConfig &nullModel, TestStatSampler *sampler=nullptr)
Constructor.
HypoTestResult is a base class for results from hypothesis tests.
void SetAltDetailedOutput(RooDataSet *d)
void SetNullDetailedOutput(RooDataSet *d)
void SetAllTestStatisticsData(const RooArgList *tsd)
void SetNullDistribution(SamplingDistribution *null)
void SetTestStatisticData(const double tsd)
void SetFitInfo(RooDataSet *d)
void SetAltDistribution(SamplingDistribution *alt)
< A class that holds configuration information for a model using a workspace as a store
Definition ModelConfig.h:34
const RooArgSet * GetSnapshot() const
get RooArgSet for parameters for a particular hypothesis (return nullptr if not existing)
RooAbsPdf * GetPdf() const
get model PDF (return nullptr if pdf has not been specified or does not exist)
TestStatistic that returns the ratio of profiled likelihoods.
This class simply holds a sampling distribution of some test statistic.
TestStatSampler is an interface class for a tools which produce RooStats SamplingDistributions.
ToyMCSampler is an implementation of the TestStatSampler interface.
virtual RooArgList * EvaluateAllTestStatistics(RooAbsData &data, const RooArgSet &poi)
Evaluate all test statistics, returning result and any detailed output.
virtual RooDataSet * GetSamplingDistributions(RooArgSet &paramPoint)
Use for serial and parallel runs.
virtual void SetNEventsPerToy(const Int_t nevents)
Forces the generation of exactly n events even for extended PDFs.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
virtual void SetSeed(ULong_t seed=0)
Set the random generator seed.
Definition TRandom.cxx:614
RooStats::ModelConfig ModelConfig
Namespace for the RooStats classes.
Definition CodegenImpl.h:66