Logo ROOT  
Reference Guide
Loading...
Searching...
No Matches
RooStatsUtils.cxx
Go to the documentation of this file.
1// @(#)root/roostats:$Id$
2// Author: Kyle Cranmer 28/07/2008
3
4/*************************************************************************
5 * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include "Rtypes.h"
13
14#if !defined(R__ALPHA) && !defined(R__SOLARIS) && !defined(R__ACC) && !defined(R__FBSD)
16#endif
17
18#include "TTree.h"
19#include "TBranch.h"
20
21#include "RooArgSet.h"
22#include "RooWorkspace.h"
23#include "RooAbsPdf.h"
24#include "RooUniform.h"
25#include "RooProdPdf.h"
26#include "RooExtendPdf.h"
27#include "RooSimultaneous.h"
30
31using std::endl, std::vector;
32
33
34namespace {
35 template<class listT, class stringT> void getParameterNames(const listT* l,std::vector<stringT>& names){
36 // extract the parameter names from a list
37 if(!l) return;
38 for (auto const *obj : *l) {
39 names.push_back(obj->GetName());
40 }
41 }
42 void getArgs(RooWorkspace* ws, const std::vector<TString> names, RooArgSet& args){
43 for(const auto& p:names){
44 RooRealVar* v = ws->var(p.Data());
45 if(v){
46 args.add(*v);
47 }
48 }
49 }
50 }
51
52namespace RooStats {
53
55 static RooStatsConfig theConfig;
56 return theConfig;
57 }
58
59 double AsimovSignificance(double s, double b, double sigma_b ) {
60 // Asimov significance
61 // formula [10] and [20] from https://www.pp.rhul.ac.uk/~cowan/stat/notes/medsigNote.pdf
62 // case we have a sigma_b
63 double sb2 = sigma_b*sigma_b;
64 // formula below has a large error when sigma_b becomes zero
65 // better to use the approximation for sigma_b=0 for very small values
66 double r = sb2/b;
67 if (r > 1.E-12) {
68 double bpsb2 = b + sb2;
69 double b2 = b*b;
70 double spb = s+b;
71 double za2 = 2.*( (spb)* std::log( ( spb)*(bpsb2)/(b2+ spb*sb2) ) -
72 (b2/sb2) * std::log(1. + ( sb2 * s)/(b * bpsb2) ) );
73 return sqrt(za2);
74
75 }
76 // case when the background (b) is known
77 double za2 = 2.*( (s+b) * std::log(1. + s/b) -s );
78 return std::sqrt(za2);
79 }
80
81 void FactorizePdf(const RooArgSet &observables, RooAbsPdf &pdf, RooArgList &obsTerms, RooArgList &constraints) {
82 // utility function to factorize constraint terms from a pdf
83 // (from G. Petrucciani)
84 if (auto prod = dynamic_cast<RooProdPdf *>(&pdf)) {
85 RooArgList list(prod->pdfList());
86 for (int i = 0, n = list.size(); i < n; ++i) {
87 RooAbsPdf *pdfi = static_cast<RooAbsPdf *>(list.at(i));
88 FactorizePdf(observables, *pdfi, obsTerms, constraints);
89 }
90 } else if (dynamic_cast<RooExtendPdf *>(&pdf)) {
91 // extract underlying pdf which is extended; first server is the pdf; second server is the number of events variable
92 auto iter = pdf.servers().begin();
93 assert(iter != pdf.servers().end());
94 assert(dynamic_cast<RooAbsPdf*>(*iter));
95 FactorizePdf(observables, static_cast<RooAbsPdf&>(**iter), obsTerms, constraints);
96 } else if (auto sim = dynamic_cast<RooSimultaneous *>(&pdf)) { //|| dynamic_cast<RooSimultaneousOpt>(&pdf)) {
97 assert(sim != nullptr);
98 RooAbsCategoryLValue *cat = static_cast<RooAbsCategoryLValue *>(sim->indexCat().clone(sim->indexCat().GetName()));
99 for (int ic = 0, nc = cat->numBins((const char *)nullptr); ic < nc; ++ic) {
100 cat->setBin(ic);
101 RooAbsPdf* catPdf = sim->getPdf(cat->getCurrentLabel());
102 // it is possible that a pdf is not defined for every category
103 if (catPdf != nullptr) FactorizePdf(observables, *catPdf, obsTerms, constraints);
104 }
105 delete cat;
106 } else if (pdf.dependsOn(observables)) {
107 if (!obsTerms.contains(pdf)) obsTerms.add(pdf);
108 } else {
109 if (!constraints.contains(pdf)) constraints.add(pdf);
110 }
111 }
112
113
114 void FactorizePdf(RooStats::ModelConfig &model, RooAbsPdf &pdf, RooArgList &obsTerms, RooArgList &constraints) {
115 // utility function to factorize constraint terms from a pdf
116 // (from G. Petrucciani)
117 if (!model.GetObservables() ) {
118 oocoutE(nullptr,InputArguments) << "RooStatsUtils::FactorizePdf - invalid input model: missing observables" << std::endl;
119 return;
120 }
121 return FactorizePdf(*model.GetObservables(), pdf, obsTerms, constraints);
122 }
123
124
125 RooAbsPdf * MakeNuisancePdf(RooAbsPdf &pdf, const RooArgSet &observables, const char *name) {
126 // make a nuisance pdf by factorizing out all constraint terms in a common pdf
127 RooArgList obsTerms;
128 RooArgList constraints;
129 FactorizePdf(observables, pdf, obsTerms, constraints);
130 if(constraints.empty()) {
131 oocoutW(nullptr, Eval) << "RooStatsUtils::MakeNuisancePdf - no constraints found on nuisance parameters in the input model" << std::endl;
132 return nullptr;
133 }
134 return new RooProdPdf(name,"", constraints);
135 }
136
138 // make a nuisance pdf by factorizing out all constraint terms in a common pdf
139 if (!model.GetPdf() || !model.GetObservables() ) {
140 oocoutE(nullptr, InputArguments) << "RooStatsUtils::MakeNuisancePdf - invalid input model: missing pdf and/or observables" << std::endl;
141 return nullptr;
142 }
143 return MakeNuisancePdf(*model.GetPdf(), *model.GetObservables(), name);
144 }
145
146 RooAbsPdf * StripConstraints(RooAbsPdf &pdf, const RooArgSet &observables) {
147
148 if (auto prod = dynamic_cast<RooProdPdf *>(&pdf)) {
149
150 RooArgList list(prod->pdfList()); RooArgList newList;
151
152 for (int i = 0, n = list.size(); i < n; ++i) {
153 RooAbsPdf *pdfi = static_cast<RooAbsPdf *>(list.at(i));
154 RooAbsPdf *newPdfi = StripConstraints(*pdfi, observables);
155 if(newPdfi != nullptr) newList.add(*newPdfi);
156 }
157
158 if (newList.empty()) {
159 return nullptr; // only constraints in product
160 // return single component (no longer a product)
161 } else if (newList.size() == 1) {
162 return dynamic_cast<RooAbsPdf *>(
163 newList.at(0)->clone(TString::Format("%s_unconstrained", newList.at(0)->GetName())));
164 } else {
165 return new RooProdPdf(TString::Format("%s_unconstrained", prod->GetName()).Data(),
166 TString::Format("%s without constraints", prod->GetTitle()).Data(), newList);
167 }
168
169 } else if (dynamic_cast<RooExtendPdf*>(&pdf)) {
170
171 auto iter = pdf.servers().begin();
172 // extract underlying pdf which is extended; first server is the pdf; second server is the number of events variable
173 auto uPdf = dynamic_cast<RooAbsPdf *>(*(iter++));
174 auto extended_term = dynamic_cast<RooAbsReal *>(*(iter++));
175 assert(uPdf != nullptr);
176 assert(extended_term != nullptr);
177 assert(iter == pdf.servers().end());
178
179 RooAbsPdf *newUPdf = StripConstraints(*uPdf, observables);
180 if(newUPdf == nullptr) return nullptr; // only constraints in underlying pdf
181 else return new RooExtendPdf(TString::Format("%s_unconstrained", pdf.GetName()).Data(),
182 TString::Format("%s without constraints", pdf.GetTitle()).Data(), *newUPdf, *extended_term);
183
184 } else if (auto sim = dynamic_cast<RooSimultaneous *>(&pdf)) { //|| dynamic_cast<RooSimultaneousOpt *>(&pdf)) {
185
186 assert(sim != nullptr);
187 RooAbsCategoryLValue *cat = static_cast<RooAbsCategoryLValue *>(sim->indexCat().Clone()); assert(cat != nullptr);
188 RooArgList pdfList;
189
190 for (int ic = 0, nc = cat->numBins((const char *)nullptr); ic < nc; ++ic) {
191 cat->setBin(ic);
192 RooAbsPdf* catPdf = sim->getPdf(cat->getCurrentLabel());
193 RooAbsPdf* newPdf = nullptr;
194 // it is possible that a pdf is not defined for every category
195 if (catPdf != nullptr) newPdf = StripConstraints(*catPdf, observables);
196 if (newPdf == nullptr) { delete cat; return nullptr; } // all channels must have observables
197 pdfList.add(*newPdf);
198 }
199
200 return new RooSimultaneous(TString::Format("%s_unconstrained", sim->GetName()).Data(),
201 TString::Format("%s without constraints", sim->GetTitle()).Data(), pdfList, *cat);
202
203 } else if (pdf.dependsOn(observables)) {
204 return static_cast<RooAbsPdf *>(pdf.clone(TString::Format("%s_unconstrained", pdf.GetName()).Data()));
205 }
206
207 return nullptr; // just a constraint term
208 }
209
210 RooAbsPdf * MakeUnconstrainedPdf(RooAbsPdf &pdf, const RooArgSet &observables, const char *name) {
211 // make a clone pdf without all constraint terms in a common pdf
212 RooAbsPdf * unconstrainedPdf = StripConstraints(pdf, observables);
213 if(!unconstrainedPdf) {
214 oocoutE(nullptr, InputArguments) << "RooStats::MakeUnconstrainedPdf - invalid observable list passed (observables not found in original pdf) or invalid pdf passed (without observables)" << std::endl;
215 return nullptr;
216 }
217 if(name != nullptr) unconstrainedPdf->SetName(name);
218 return unconstrainedPdf;
219 }
220
222 // make a clone pdf without all constraint terms in a common pdf
223 if(!model.GetPdf() || !model.GetObservables()) {
224 oocoutE(nullptr, InputArguments) << "RooStatsUtils::MakeUnconstrainedPdf - invalid input model: missing pdf and/or observables" << std::endl;
225 return nullptr;
226 }
227 return MakeUnconstrainedPdf(*model.GetPdf(), *model.GetObservables(), name);
228 }
229
230 // Helper class for GetAsTTree
232 public:
233 std::map<TString, double> fVarVals;
234 double fInval;
235 TTree *fTree = nullptr;
236
237 BranchStore(const vector<TString> &params = vector<TString>(), double _inval = -999.) : fInval(_inval)
238 {
239 for (unsigned int i = 0; i < params.size(); i++)
240 fVarVals[params[i]] = _inval;
241 }
242
244 if (fTree) {
245 for(std::map<TString, double>::iterator it = fVarVals.begin();it!=fVarVals.end();++it) {
246 TBranch *br = fTree->GetBranch( it->first );
247 if (br) br->ResetAddress();
248 }
249 }
250 }
251
252 void AssignToTTree(TTree &myTree) {
253 fTree = &myTree;
254 for(std::map<TString, double>::iterator it = fVarVals.begin();it!=fVarVals.end();++it) {
255 const TString& name = it->first;
256 myTree.Branch( name, &fVarVals[name], TString::Format("%s/D", name.Data()));
257 }
258 }
259 void ResetValues() {
260 for(std::map<TString, double>::iterator it = fVarVals.begin();it!=fVarVals.end();++it) {
261 const TString& name = it->first;
263 }
264 }
265 };
266
268 if (data.numEntries() == 0) {
269 return new BranchStore;
270 }
271 vector <TString> V;
272 for (auto *rvar : dynamic_range_cast<RooRealVar *>(* data.get(0))) {
273 if (rvar == nullptr)
274 continue;
275 V.push_back(rvar->GetName());
276 if (rvar->hasAsymError()) {
277 V.push_back(TString::Format("%s_errlo", rvar->GetName()));
278 V.push_back(TString::Format("%s_errhi", rvar->GetName()));
279 }
280 else if (rvar->hasError()) {
281 V.push_back(TString::Format("%s_err", rvar->GetName()));
282 }
283 }
284 return new BranchStore(V);
285 }
286
287 void FillTree(TTree &myTree, const RooDataSet &data) {
288 BranchStore *bs = CreateBranchStore(data);
289 bs->AssignToTTree(myTree);
290
291 for(int entry = 0;entry<data.numEntries();entry++) {
292 bs->ResetValues();
293 for (auto const *rvar : dynamic_range_cast<RooRealVar *>(*data.get(entry))) {
294 if (rvar == nullptr)
295 continue;
296 bs->fVarVals[rvar->GetName()] = rvar->getValV();
297 if (rvar->hasAsymError()) {
298 bs->fVarVals[TString::Format("%s_errlo", rvar->GetName())] = rvar->getAsymErrorLo();
299 bs->fVarVals[TString::Format("%s_errhi", rvar->GetName())] = rvar->getAsymErrorHi();
300 }
301 else if (rvar->hasError()) {
302 bs->fVarVals[TString::Format("%s_err", rvar->GetName())] = rvar->getError();
303 }
304 }
305 myTree.Fill();
306 }
307
308 delete bs;
309 }
310
312 TTree* myTree = new TTree(name, desc);
313 FillTree(*myTree, data);
314 return myTree;
315 }
316
317
318 // useful function to print in one line the content of a set with their values
319 void PrintListContent(const RooArgList & l, std::ostream & os ) {
320 bool first = true;
321 os << "( ";
322 for (std::size_t i = 0; i< l.size(); ++i) {
323 if (first) {
324 first=false ;
325 } else {
326 os << ", " ;
327 }
328 l[i].printName(os);
329 os << " = ";
330 l[i].printValue(os);
331 }
332 os << ")\n";
333 }
334
335 // clone a workspace, copying all needed components and discarding all others
336 // start off with the old workspace
337 RooWorkspace* MakeReducedWorkspace(RooWorkspace *oldWS, const char *newName,
338 bool copySnapshots, const char *mcname,
339 const char *newmcname, bool copyData) {
340 auto objects = oldWS->allGenericObjects();
341 RooStats::ModelConfig *oldMC =
342 dynamic_cast<RooStats::ModelConfig *>(oldWS->obj(mcname));
343 for (auto it : objects) {
344 if (!oldMC) {
345 oldMC = dynamic_cast<RooStats::ModelConfig *>(it);
346 }
347 }
348 if (!oldMC)
349 throw std::runtime_error("unable to retrieve ModelConfig");
350
351 RooAbsPdf *origPdf = oldMC->GetPdf();
352
353 // start off with the old modelconfig
354 std::vector<TString> poilist;
355 std::vector<TString> nplist;
356 std::vector<TString> obslist;
357 std::vector<TString> globobslist;
358 RooAbsPdf *pdf = nullptr;
359 if (oldMC) {
360 pdf = oldMC->GetPdf();
361 ::getParameterNames(oldMC->GetParametersOfInterest(), poilist);
362 ::getParameterNames(oldMC->GetNuisanceParameters(), nplist);
363 ::getParameterNames(oldMC->GetObservables(), obslist);
364 ::getParameterNames(oldMC->GetGlobalObservables(), globobslist);
365 }
366 if (!pdf) {
367 if (origPdf)
368 pdf = origPdf;
369 }
370 if (!pdf) {
371 return nullptr;
372 }
373
374 // create them anew
375 RooWorkspace *newWS = new RooWorkspace(newName ? newName : oldWS->GetName());
376 newWS->autoImportClassCode(true);
377 RooStats::ModelConfig *newMC = new RooStats::ModelConfig(newmcname, newWS);
378
379 // Copy snapshots
380 if (copySnapshots) {
381 for (auto* snap : static_range_cast<RooArgSet const*>(oldWS->getSnapshots())) {
382 newWS->saveSnapshot(snap->GetName(), *snap, /*importValuesdf*/true);
383 }
384 }
385
386 newWS->import(*pdf, RooFit::RecycleConflictNodes());
387 RooAbsPdf *newPdf = newWS->pdf(pdf->GetName());
388 newMC->SetPdf(*newPdf);
389
390 if (copyData) {
391 for (auto d : oldWS->allData()) {
392 newWS->import(*d);
393 }
394 }
395
396 RooArgSet poiset;
397 ::getArgs(newWS, poilist, poiset);
398 RooArgSet npset;
399 ::getArgs(newWS, nplist, npset);
400 RooArgSet obsset;
401 ::getArgs(newWS, obslist, obsset);
402 RooArgSet globobsset;
403 ::getArgs(newWS, globobslist, globobsset);
404
405 newMC->SetParametersOfInterest(poiset);
406 newMC->SetNuisanceParameters(npset);
407 newMC->SetObservables(obsset);
408 newMC->SetGlobalObservables(globobsset);
409 newWS->import(*newMC);
410
411 return newWS;
412 }
413
414}
ROOT::R::TRInterface & r
Definition Object.C:4
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
ROOT::RRangeCast< T, true, Range_t > dynamic_range_cast(Range_t &&coll)
ROOT::RRangeCast< T, false, Range_t > static_range_cast(Range_t &&coll)
#define oocoutW(o, a)
#define oocoutE(o, a)
#define NamespaceImp(name)
Definition Rtypes.h:381
char name[80]
Definition TGX11.cxx:148
bool dependsOn(const RooAbsCollection &serverList, const RooAbsArg *ignoreArg=nullptr, bool valueOnly=false) const
Test whether we depend on (ie, are served by) any object in the specified collection.
virtual TObject * clone(const char *newname=nullptr) const =0
void SetName(const char *name) override
Set the name of the TNamed.
const RefCountList_t & servers() const
List of all servers of this object.
Definition RooAbsArg.h:145
Abstract base class for objects that represent a discrete value that can be set from the outside,...
Int_t numBins(const char *rangeName=nullptr) const override
Return the number of fit bins ( = number of types ).
void setBin(Int_t ibin, const char *rangeName=nullptr) override
Set category to i-th fit bin, which is the i-th registered state.
virtual const char * getCurrentLabel() const
Return label string of current state.
bool contains(const char *name) const
Check if collection contains an argument with a specific name.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:32
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:63
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooAbsArg * at(Int_t idx) const
Return object at given index, or nullptr if index is out of range.
Definition RooArgList.h:110
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
Container class to hold unbinned data.
Definition RooDataSet.h:32
RooExtendPdf is a wrapper around an existing PDF that adds a parameteric extended likelihood term to ...
Efficient implementation of a product of PDFs of the form.
Definition RooProdPdf.h:36
Variable that can be changed from the outside.
Definition RooRealVar.h:37
Facilitates simultaneous fitting of multiple PDFs to subsets of a given dataset.
std::map< TString, double > fVarVals
void AssignToTTree(TTree &myTree)
BranchStore(const vector< TString > &params=vector< TString >(), double _inval=-999.)
< A class that holds configuration information for a model using a workspace as a store
Definition ModelConfig.h:34
void SetParametersOfInterest(const RooArgSet &set)
Specify parameters of interest.
const RooArgSet * GetGlobalObservables() const
get RooArgSet for global observables (return nullptr if not existing)
void SetObservables(const RooArgSet &set)
Specify the observables.
const RooArgSet * GetParametersOfInterest() const
get RooArgSet containing the parameter of interest (return nullptr if not existing)
void SetPdf(const RooAbsPdf &pdf)
Set the Pdf, add to the workspace if not already there.
Definition ModelConfig.h:87
const RooArgSet * GetNuisanceParameters() const
get RooArgSet containing the nuisance parameters (return nullptr if not existing)
const RooArgSet * GetObservables() const
get RooArgSet for observables (return nullptr if not existing)
RooAbsPdf * GetPdf() const
get model PDF (return nullptr if pdf has not been specified or does not exist)
void SetNuisanceParameters(const RooArgSet &set)
Specify the nuisance parameters (parameters that are not POI).
void SetGlobalObservables(const RooArgSet &set)
Specify the global observables.
Persistable container for RooFit projects.
TObject * obj(RooStringView name) const
Return any type of object (RooAbsArg, RooAbsData or generic object) with given name).
RooAbsPdf * pdf(RooStringView name) const
Retrieve p.d.f (RooAbsPdf) with given name. A null pointer is returned if not found.
bool saveSnapshot(RooStringView, const char *paramNames)
Save snapshot of values and attributes (including "Constant") of given parameters.
std::list< RooAbsData * > allData() const
Return list of all dataset in the workspace.
RooLinkedList const & getSnapshots() const
std::list< TObject * > allGenericObjects() const
Return list of all generic objects in the workspace.
RooRealVar * var(RooStringView name) const
Retrieve real-valued variable (RooRealVar) with given name. A null pointer is returned if not found.
static void autoImportClassCode(bool flag)
If flag is true, source code of classes not the ROOT distribution is automatically imported if on obj...
bool import(const RooAbsArg &arg, const RooCmdArg &arg1={}, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={}, const RooCmdArg &arg9={})
Import a RooAbsArg object, e.g.
A TTree is a list of TBranches.
Definition TBranch.h:93
virtual void ResetAddress()
Reset the address of the branch.
Definition TBranch.cxx:2650
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
Basic string class.
Definition TString.h:138
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2385
A TTree represents a columnar dataset.
Definition TTree.h:89
virtual Int_t Fill()
Fill all branches.
Definition TTree.cxx:4653
TBranch * Branch(const char *name, T *obj, Int_t bufsize=32000, Int_t splitlevel=99)
Add a new branch, and infer the data type from the type of obj being passed.
Definition TTree.h:397
RooCmdArg RecycleConflictNodes(bool flag=true)
const Int_t n
Definition legend1.C:16
Namespace for the RooStats classes.
Definition CodegenImpl.h:66
TTree * GetAsTTree(TString name, TString desc, const RooDataSet &data)
Create a TTree with the given name and description. All RooRealVars in the RooDataSet are represented...
void FillTree(TTree &myTree, const RooDataSet &data)
BranchStore * CreateBranchStore(const RooDataSet &data)
RooAbsPdf * StripConstraints(RooAbsPdf &pdf, const RooArgSet &observables)
RooAbsPdf * MakeNuisancePdf(RooAbsPdf &pdf, const RooArgSet &observables, const char *name)
extract constraint terms from pdf
void FactorizePdf(const RooArgSet &observables, RooAbsPdf &pdf, RooArgList &obsTerms, RooArgList &constraints)
RooStatsConfig & GetGlobalRooStatsConfig()
Retrieve the config object which can be used to set flags for things like offsetting the likelihood o...
double AsimovSignificance(double s, double b, double sigma_b=0.0)
Compute the Asimov Median significance for a Poisson process with s = expected number of signal event...
RooAbsPdf * MakeUnconstrainedPdf(RooAbsPdf &pdf, const RooArgSet &observables, const char *name=nullptr)
remove constraints from pdf and return the unconstrained pdf
RooWorkspace * MakeReducedWorkspace(RooWorkspace *oldWS, const char *newName, bool copySnapshots, const char *mcname, const char *newmcname, bool copyData=true)
function that clones a workspace, copying all needed components and discarding all others
void PrintListContent(const RooArgList &l, std::ostream &os=std::cout)
useful function to print in one line the content of a set with their values
TLine l
Definition textangle.C:4