Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooGenProdProj.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
11 * *
12 * Redistribution and use in source and binary forms, *
13 * with or without modification, are permitted according to the terms *
14 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15 *****************************************************************************/
16
17/**
18\file RooGenProdProj.cxx
19\class RooGenProdProj
20\ingroup Roofitcore
21
22
23RooGenProdProj is an auxiliary class for RooProdPdf that calculates
24a general normalised projection of a product of non-factorising PDFs, e.g.
25\f[
26 P_{x,xy} = \frac{\int ( P1 * P2 * \ldots) \mathrm{d}x}{\int ( P1 * P2 * \ldots ) \mathrm{d}x \mathrm{d}y}
27\f]
28
29Partial integrals, which factorise and can be calculated, are calculated
30analytically. Remaining non-factorising observables are integrated numerically.
31**/
32
33
34#include "Riostream.h"
35#include <math.h>
36
37#include "RooGenProdProj.h"
38#include "RooAbsReal.h"
39#include "RooAbsPdf.h"
40#include "RooErrorHandler.h"
41#include "RooProduct.h"
42
43using namespace std;
44
46
47
48
49////////////////////////////////////////////////////////////////////////////////
50/// Default constructor
51
53 _compSetOwnedN(0),
54 _compSetOwnedD(0),
55 _haveD(false)
56{
57}
58
59
60////////////////////////////////////////////////////////////////////////////////
61/// Constructor for a normalization projection of the product of p.d.f.s _prodSet
62/// integrated over _intSet in range isetRangeName while normalized over _normSet
63
64RooGenProdProj::RooGenProdProj(const char *name, const char *title, const RooArgSet& _prodSet, const RooArgSet& _intSet,
65 const RooArgSet& _normSet, const char* isetRangeName, const char* normRangeName, bool doFactorize) :
66 RooAbsReal(name, title),
67 _compSetOwnedN(0),
68 _compSetOwnedD(0),
69 _compSetN("compSetN","Set of integral components owned by numerator",this,false),
70 _compSetD("compSetD","Set of integral components owned by denominator",this,false),
71 _intList("intList","List of integrals",this,true),
72 _haveD(false)
73{
74 // Set expensive object cache to that of first item in prodSet
76
77 // Create owners of components created in ctor
80
81 RooAbsReal* numerator = makeIntegral("numerator",_prodSet,_intSet,*_compSetOwnedN,isetRangeName,doFactorize) ;
82 RooAbsReal* denominator = makeIntegral("denominator",_prodSet,_normSet,*_compSetOwnedD,normRangeName,doFactorize) ;
83
84// cout << "RooGenProdPdf::ctor(" << GetName() << ") numerator = " << numerator->GetName() << endl ;
85// numerator->printComponentTree() ;
86// cout << "RooGenProdPdf::ctor(" << GetName() << ") denominator = " << denominator->GetName() << endl ;
87// denominator->printComponentTree() ;
88
89 // Copy all components in (non-owning) set proxy
92
93 _intList.add(*numerator) ;
94 if (denominator) {
95 _intList.add(*denominator) ;
96 _haveD = true ;
97 }
98}
99
100
101
102////////////////////////////////////////////////////////////////////////////////
103/// Copy constructor
104
106 RooAbsReal(other, name),
107 _compSetOwnedN(0),
108 _compSetOwnedD(0),
109 _compSetN("compSetN","Set of integral components owned by numerator",this),
110 _compSetD("compSetD","Set of integral components owned by denominator",this),
111 _intList("intList","List of integrals",this)
112{
113 // Copy constructor
116
119
120 for (RooAbsArg * arg : *_compSetOwnedN) {
121 arg->setOperMode(_operMode) ;
122 }
123 for (RooAbsArg * arg : *_compSetOwnedD) {
124 arg->setOperMode(_operMode) ;
125 }
126
127 // Fill _intList
128 _haveD = other._haveD ;
129 _intList.add(*_compSetN.find(other._intList.at(0)->GetName())) ;
130 if (other._haveD) {
131 _intList.add(*_compSetD.find(other._intList.at(1)->GetName())) ;
132 }
133}
134
135
136
137////////////////////////////////////////////////////////////////////////////////
138/// Destructor
139
141{
142 if (_compSetOwnedN) delete _compSetOwnedN ;
143 if (_compSetOwnedD) delete _compSetOwnedD ;
144}
145
146
147
148////////////////////////////////////////////////////////////////////////////////
149/// Utility function to create integral for product over certain observables.
150/// \param[in] name Name of integral to be created.
151/// \param[in] compSet All components of the product.
152/// \param[in] intSet Observables to be integrated.
153/// \param[out] saveSet All component objects needed to represent the product integral are added as owned members to saveSet.
154/// \note The set owns new components that are created for the integral.
155/// \param[in] isetRangeName Integral range.
156/// \param[in] doFactorize
157///
158/// \return A RooAbsReal object representing the requested integral. The object is owned by `saveSet`.
159///
160/// The integration is factorized into components as much as possible and done analytically as far as possible.
161RooAbsReal* RooGenProdProj::makeIntegral(const char* name, const RooArgSet& compSet, const RooArgSet& intSet,
162 RooArgSet& saveSet, const char* isetRangeName, bool doFactorize)
163{
164 RooArgSet anaIntSet, numIntSet ;
165
166 // First determine subset of observables in intSet that are factorizable
167 for (const auto arg : intSet) {
168 auto count = std::count_if(compSet.begin(), compSet.end(), [arg](const RooAbsArg* pdfAsArg){
169 auto pdf = static_cast<const RooAbsPdf*>(pdfAsArg);
170 return (pdf->dependsOn(*arg));
171 });
172
173 if (count==1) {
174 anaIntSet.add(*arg) ;
175 }
176 }
177
178 // Determine which of the factorizable integrals can be done analytically
179 RooArgSet prodSet ;
180 numIntSet.add(intSet) ;
181
182 // The idea of the RooGenProdProj is that we divide two integral objects each
183 // created with this makeIntgral() function to get the normalized integral of
184 // a product. Therefore, we don't need to normalize the numerater and
185 // denominator integrals themselves. Doing the normalization would be
186 // expensive and it would cancel out anyway. However, if we don't specify an
187 // explicit normalization integral in createIntegral(), the last-used
188 // normalization set might be used to normalize the pdf, resulting in
189 // redundant computations.
190 //
191 // For this reason, the normalization set of the integrated pdfs is fixed to
192 // an empty set in this case. Note that in RooFit, a nullptr normalization
193 // set and an empty normalization set is not equivalent. The former implies
194 // taking the last-used normalization set, and the latter means explicitly no
195 // normalization.
196 RooArgSet emptyNormSet{};
197
198 for (const auto pdfAsArg : compSet) {
199 auto pdf = static_cast<const RooAbsPdf*>(pdfAsArg);
200
201 if (doFactorize && pdf->dependsOn(anaIntSet)) {
202 RooArgSet anaSet ;
203 Int_t code = pdf->getAnalyticalIntegralWN(anaIntSet,anaSet,0,isetRangeName) ;
204 if (code!=0) {
205 // Analytical integral, create integral object
206 std::unique_ptr<RooAbsReal> pai{pdf->createIntegral(anaSet,emptyNormSet,isetRangeName)};
207 pai->setOperMode(_operMode) ;
208
209 // Add to integral to product
210 prodSet.add(*pai) ;
211
212 // Remove analytically integratable observables from numeric integration list
213 numIntSet.remove(anaSet) ;
214
215 // Declare ownership of integral
216 saveSet.addOwned(std::move(pai));
217 } else {
218 // Analytic integration of factorizable observable not possible, add straight pdf to product
219 prodSet.add(*pdf) ;
220 }
221 } else {
222 // Non-factorizable observables, add straight pdf to product
223 prodSet.add(*pdf) ;
224 }
225 }
226
227 // Create product of (partial) analytical integrals
228 TString prodName ;
229 if (isetRangeName) {
230 prodName = Form("%s_%s_Range[%s]",GetName(),name,isetRangeName) ;
231 } else {
232 prodName = Form("%s_%s",GetName(),name) ;
233 }
234
235 // Create clones of the elements in prodSet. These need to be cloned
236 // because when caching optimisation lvl 2 is activated, pre-computed
237 // values are side-loaded into the elements.
238 // Those pre-cached values already contain normalisation constants, so
239 // the integral comes out wrongly. Therefore, we create here nodes that
240 // don't participate in any caching, which are used to compute integrals.
241 RooArgSet prodSetClone;
242 prodSet.snapshot(prodSetClone, false);
243
244 auto prod = std::make_unique<RooProduct>(prodName, "product", prodSetClone);
245 prod->setExpensiveObjectCache(expensiveObjectCache()) ;
246 prod->setOperMode(_operMode) ;
247
248 // Create integral performing remaining numeric integration over (partial) analytic product
249 std::unique_ptr<RooAbsReal> integral{prod->createIntegral(numIntSet,emptyNormSet,isetRangeName)};
250 integral->setOperMode(_operMode) ;
251 auto ret = integral.get();
252
253 // Declare ownership of prodSet, product, and integral
254 saveSet.addOwned(std::move(prodSetClone));
255 saveSet.addOwned(std::move(prod));
256 saveSet.addOwned(std::move(integral)) ;
257
258
259 // Caller owners returned master integral object
260 return ret ;
261}
262
263
264
265////////////////////////////////////////////////////////////////////////////////
266/// Calculate and return value of normalization projection
267
269{
270 RooArgSet const* nset = _intList.nset();
271
272 double nom = static_cast<RooAbsReal*>(_intList.at(0))->getVal(nset);
273
274 if (!_haveD) return nom ;
275
276 double den = static_cast<RooAbsReal*>(_intList.at(1))->getVal(nset);
277
278 //cout << "RooGenProdProj::eval(" << GetName() << ") nom = " << nom << " den = " << den << endl ;
279
280 return nom / den ;
281}
282
283
284
285////////////////////////////////////////////////////////////////////////////////
286/// Intercept cache mode operation changes and propagate them to the components
287
289{
290 // WVE use cache manager here!
291
292 for(RooAbsArg * arg : *_compSetOwnedN) {
293 arg->setOperMode(_operMode) ;
294 }
295
296 for(RooAbsArg * arg : *_compSetOwnedD) {
297 arg->setOperMode(_operMode) ;
298 }
299
301 if (_haveD) _intList.at(1)->setOperMode(Auto) ; // Denominator always stays in Auto mode (normalization integral)
302}
303
304
305
306
307
308
309
#define ClassImp(name)
Definition Rtypes.h:377
char name[80]
Definition TGX11.cxx:110
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2467
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition RooAbsArg.h:74
RooExpensiveObjectCache & expensiveObjectCache() const
void setOperMode(OperMode mode, bool recurseADirty=true)
Set the operation mode of this node.
virtual void setExpensiveObjectCache(RooExpensiveObjectCache &cache)
Definition RooAbsArg.h:500
OperMode _operMode
Definition RooAbsArg.h:711
virtual bool remove(const RooAbsArg &var, bool silent=false, bool matchByNameOnly=false)
Remove the specified argument from our list.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
const_iterator end() const
RooAbsArg * first() const
virtual bool addOwned(RooAbsArg &var, bool silent=false)
Add an argument and transfer the ownership to the collection.
const_iterator begin() const
RooAbsArg * find(const char *name) const
Find object with given name in list.
const RooArgSet * nset() const
Definition RooAbsProxy.h:52
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition RooAbsReal.h:62
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:91
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:55
RooArgSet * snapshot(bool deepCopy=true) const
Use RooAbsCollection::snapshot(), but return as RooArgSet.
Definition RooArgSet.h:178
bool add(const RooAbsArg &var, bool valueServer, bool shapeServer, bool silent)
Overloaded RooCollection_t::add() method insert object into set and registers object as server to own...
RooGenProdProj is an auxiliary class for RooProdPdf that calculates a general normalised projection o...
void operModeHook() override
Intercept cache mode operation changes and propagate them to the components.
RooGenProdProj()
Default constructor.
double evaluate() const override
Calculate and return value of normalization projection.
RooAbsReal * makeIntegral(const char *name, const RooArgSet &compSet, const RooArgSet &intSet, RooArgSet &saveSet, const char *isetRangeName, bool doFactorize)
Utility function to create integral for product over certain observables.
~RooGenProdProj() override
Destructor.
RooSetProxy _compSetD
Set proxy for denominator components.
RooListProxy _intList
Master integrals representing numerator and denominator.
RooArgSet * _compSetOwnedD
Owner of denominator components.
bool _haveD
Do we have a denominator term?
RooArgSet * _compSetOwnedN
Owner of numerator components.
RooSetProxy _compSetN
Set proxy for numerator components.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
Basic string class.
Definition TString.h:139