Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RooJeffreysPrior.cxx
Go to the documentation of this file.
1 /** \class RooJeffreysPrior
2 \ingroup Roofit
3 
4 Implementation of Jeffrey's prior. This class estimates the fisher information matrix by generating
5 a binned Asimov dataset from the supplied PDFs, fitting it, retrieving the covariance matrix and inverting
6 it. It returns the square root of the determinant of this matrix.
7 Numerical integration is used to normalise. Since each integration step requires fits to be run,
8 evaluating complicated PDFs may take long.
9 
10 Check the tutorial rs302_JeffreysPriorDemo.C for a demonstration with a simple PDF.
11 **/
12 
13 #include "RooJeffreysPrior.h"
14 
15 #include "RooAbsReal.h"
16 #include "RooAbsPdf.h"
17 #include "RooErrorHandler.h"
18 #include "RooArgSet.h"
19 #include "RooMsgService.h"
20 #include "RooFitResult.h"
21 #include "TMatrixDSym.h"
22 #include "RooDataHist.h"
23 #include "RooFitResult.h"
24 #include "RooNumIntConfig.h"
25 #include "RooRealVar.h"
26 #include "RooHelpers.h"
27 
28 using namespace std;
29 
30 ClassImp(RooJeffreysPrior);
31 
32 using namespace RooFit;
33 
34 ////////////////////////////////////////////////////////////////////////////////
35 /// Construct a new JeffreysPrior.
36 /// \param[in] name Name of this object.
37 /// \param[in] title Title (for plotting)
38 /// \param[in] nominal The PDF to base Jeffrey's prior on.
39 /// \param[in] paramSet Parameters of the PDF.
40 /// \param[in] obsSet Observables of the PDF.
41 
42 RooJeffreysPrior::RooJeffreysPrior(const char* name, const char* title,
43  RooAbsPdf& nominal,
44  const RooArgList& paramSet,
45  const RooArgList& obsSet) :
46  RooAbsPdf(name, title),
47  _nominal("nominal","nominal",this, nominal, false, false),
48  _obsSet("!obsSet","Observables",this, false, false),
49  _paramSet("!paramSet","Parameters",this),
50  _cacheMgr(this, 1, true, false)
51 {
52  for (const auto comp : obsSet) {
53  if (!dynamic_cast<RooAbsReal*>(comp)) {
54  coutE(InputArguments) << "RooJeffreysPrior::ctor(" << GetName() << ") ERROR: component " << comp->GetName()
55  << " in observable list is not of type RooAbsReal" << endl ;
56  RooErrorHandler::softAbort() ;
57  }
58  _obsSet.add(*comp) ;
59  }
60 
61  for (const auto comp : paramSet) {
62  if (!dynamic_cast<RooAbsReal*>(comp)) {
63  coutE(InputArguments) << "RooJeffreysPrior::ctor(" << GetName() << ") ERROR: component " << comp->GetName()
64  << " in parameter list is not of type RooAbsReal" << endl ;
65  RooErrorHandler::softAbort() ;
66  }
67  _paramSet.add(*comp) ;
68  }
69 
70  // use a different integrator by default.
71  if(paramSet.getSize()==1)
72  this->specialIntegratorConfig(kTRUE)->method1D().setLabel("RooAdaptiveGaussKronrodIntegrator1D") ;
73 }
74 
75 ////////////////////////////////////////////////////////////////////////////////
76 /// Copy constructor
77 
78 RooJeffreysPrior::RooJeffreysPrior(const RooJeffreysPrior& other, const char* name) :
79  RooAbsPdf(other, name),
80  _nominal("!nominal",this,other._nominal),
81  _obsSet("!obsSet",this,other._obsSet),
82  _paramSet("!paramSet",this,other._paramSet),
83  _cacheMgr(this, 1, true, false)
84 {
85 
86 }
87 
88 ////////////////////////////////////////////////////////////////////////////////
89 /// Destructor
90 
91 RooJeffreysPrior::~RooJeffreysPrior()
92 {
93 
94 }
95 
96 ////////////////////////////////////////////////////////////////////////////////
97 /// Calculate and return current value of self
98 
99 Double_t RooJeffreysPrior::evaluate() const
100 {
101  RooHelpers::LocalChangeMsgLevel msgLvlRAII(RooFit::WARNING);
102 
103 
104  CacheElem* cacheElm = (CacheElem*) _cacheMgr.getObj(nullptr);
105  if (!cacheElm) {
106  //Internally, we have to enlarge the range of fit parameters to make
107  //fits converge even if we are close to the limit of a parameter. Therefore, we clone the pdf and its
108  //observables here. If something happens to the external PDF, the cache is wiped,
109  //and we start to clone again.
110  auto& pdf = _nominal.arg();
111  RooAbsPdf* clonePdf = static_cast<RooAbsPdf*>(pdf.cloneTree());
112  auto vars = clonePdf->getParameters(_obsSet);
113  for (auto varTmp : *vars) {
114  auto& var = static_cast<RooRealVar&>(*varTmp);
115  auto range = var.getRange();
116  double span = range.second - range.first;
117  var.setRange(range.first - 0.1*span, range.second + 0.1 * span);
118  }
119 
120  cacheElm = new CacheElem;
121  cacheElm->_pdf.reset(clonePdf);
122  cacheElm->_pdfVariables.reset(vars);
123 
124  _cacheMgr.setObj(nullptr, cacheElm);
125  }
126 
127  auto& cachedPdf = *cacheElm->_pdf;
128  auto& pdfVars = *cacheElm->_pdfVariables;
129  pdfVars = _paramSet;
130 
131  std::unique_ptr<RooDataHist> data( cachedPdf.generateBinned(_obsSet,ExpectedData()) );
132  std::unique_ptr<RooFitResult> res( cachedPdf.fitTo(*data, Save(),PrintLevel(-1),Minos(false),SumW2Error(false)) );
133  TMatrixDSym cov = res->covarianceMatrix();
134  cov.Invert();
135 
136  return sqrt(cov.Determinant());
137 }
138