Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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
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
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
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
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 }
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
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);
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
338 bool copySnapshots, const char *mcname,
339 const char *newmcname, bool copyData) {
340 auto objects = oldWS->allGenericObjects();
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);
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
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}
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define oocoutW(o, a)
#define oocoutE(o, a)
#define NamespaceImp(name)
Definition Rtypes.h:379
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
char name[80]
Definition TGX11.cxx:110
const_iterator begin() const
const_iterator end() const
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
const RefCountList_t & servers() const
List of all servers of this object.
Definition RooAbsArg.h:149
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 RooAbsArg &var) const
Check if collection contains an argument with the same name as var.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:40
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:59
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
Container class to hold unbinned data.
Definition RooDataSet.h:34
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.)
ModelConfig is a simple class that holds configuration information specifying how a model should be u...
Definition ModelConfig.h:35
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)
Persistable container for RooFit projects.
RooRealVar * var(RooStringView name) const
Retrieve real-valued variable (RooRealVar) with given name. A null pointer is returned if not found.
A TTree is a list of TBranches.
Definition TBranch.h:93
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:139
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:2378
A TTree represents a columnar dataset.
Definition TTree.h:79
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition TTree.cxx:5287
RooCmdArg RecycleConflictNodes(bool flag=true)
const Int_t n
Definition legend1.C:16
Namespace for the RooStats classes.
Definition CodegenImpl.h:58
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