Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooProduct.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 * GR, Gerhard Raven, VU Amsterdan, graven@nikhef.nl *
8 * *
9 * Copyright (c) 2000-2007, 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 RooProduct.cxx
19\class RooProduct
20\ingroup Roofitcore
21
22A RooProduct represents the product of a given set of RooAbsReal objects.
23
24**/
25
26
27#include <cmath>
28#include <memory>
29
30#include "RooProduct.h"
31#include "RooNameReg.h"
32#include "RooAbsReal.h"
33#include "RooAbsCategory.h"
34#include "RooErrorHandler.h"
35#include "RooMsgService.h"
36#include "RooTrace.h"
37
38using namespace std ;
39
41;
42
43class RooProduct::ProdMap : public std::vector<std::pair<RooArgSet*,RooArgList*> > {} ;
44
45// Namespace with helper functions that have STL stuff that we don't want to expose to CINT
46namespace {
47 typedef RooProduct::ProdMap::iterator RPPMIter ;
48 std::pair<RPPMIter,RPPMIter> findOverlap2nd(RPPMIter i, RPPMIter end) ;
49 void dump_map(ostream& os, RPPMIter i, RPPMIter end) ;
50}
51
52
53
54////////////////////////////////////////////////////////////////////////////////
55/// Default constructor
56
58{
60}
61
62
63
64////////////////////////////////////////////////////////////////////////////////
65/// Destructor
66
68{
70}
71
72
73
74////////////////////////////////////////////////////////////////////////////////
75/// Construct function representing the product of functions in prodSet
76
77RooProduct::RooProduct(const char* name, const char* title, const RooArgList& prodSet) :
78 RooAbsReal(name, title),
79 _compRSet("!compRSet","Set of real product components",this),
80 _compCSet("!compCSet","Set of category product components",this),
81 _cacheMgr(this,10)
82{
83 for (auto comp : prodSet) {
84 if (dynamic_cast<RooAbsReal*>(comp)) {
85 _compRSet.add(*comp) ;
86 } else if (dynamic_cast<RooAbsCategory*>(comp)) {
87 _compCSet.add(*comp) ;
88 } else {
89 coutE(InputArguments) << "RooProduct::ctor(" << GetName() << ") ERROR: component " << comp->GetName()
90 << " is not of type RooAbsReal or RooAbsCategory" << endl ;
92 }
93 }
95}
96
97
98
99////////////////////////////////////////////////////////////////////////////////
100/// Copy constructor
101
102RooProduct::RooProduct(const RooProduct& other, const char* name) :
103 RooAbsReal(other, name),
104 _compRSet("!compRSet",this,other._compRSet),
105 _compCSet("!compCSet",this,other._compCSet),
106 _cacheMgr(other._cacheMgr,this)
107{
109}
110
111
112
113////////////////////////////////////////////////////////////////////////////////
114/// Force internal handling of integration of given observable if any
115/// of the product terms depend on it.
116
118{
119 // Force internal handling of integration of given observable if any
120 // of the product terms depend on it.
121
122 RooFIter compRIter = _compRSet.fwdIterator() ;
123 RooAbsReal* rcomp ;
124 Bool_t depends(kFALSE);
125 while((rcomp=(RooAbsReal*)compRIter.next())&&!depends) {
126 depends = rcomp->dependsOn(dep);
127 }
128 return depends ;
129}
130
131
132
133////////////////////////////////////////////////////////////////////////////////
134/// Group observables into subsets in which the product factorizes
135/// and that can thus be integrated separately
136
137RooProduct::ProdMap* RooProduct::groupProductTerms(const RooArgSet& allVars) const
138{
139 ProdMap* map = new ProdMap ;
140
141 // Do we have any terms which do not depend on the
142 // on the variables we integrate over?
143 RooAbsReal* rcomp ;
144 RooFIter compRIter = _compRSet.fwdIterator() ;
145 RooArgList *indep = new RooArgList();
146 while((rcomp=(RooAbsReal*) compRIter.next())) {
147 if( !rcomp->dependsOn(allVars) ) indep->add(*rcomp);
148 }
149 if (indep->getSize()!=0) {
150 map->push_back( std::make_pair(new RooArgSet(),indep) );
151 } else {
152 delete indep;
153 }
154
155 // Map observables -> functions ; start with individual observables
156 RooFIter allVarsIter = allVars.fwdIterator() ;
157 RooAbsReal* var ;
158 while((var=(RooAbsReal*)allVarsIter.next())) {
159 RooArgSet *vars = new RooArgSet(); vars->add(*var);
160 RooArgList *comps = new RooArgList();
161 RooAbsReal* rcomp2 ;
162
163 compRIter = _compRSet.fwdIterator() ;
164 while((rcomp2=(RooAbsReal*) compRIter.next())) {
165 if( rcomp2->dependsOn(*var) ) comps->add(*rcomp2);
166 }
167 map->push_back( std::make_pair(vars,comps) );
168 }
169
170 // Merge groups with overlapping dependents
171 Bool_t overlap;
172 do {
173 std::pair<ProdMap::iterator,ProdMap::iterator> i = findOverlap2nd(map->begin(),map->end());
174 overlap = (i.first!=i.second);
175 if (overlap) {
176 i.first->first->add(*i.second->first);
177
178 // In the merging step, make sure not to duplicate
179 RooFIter it = i.second->second->fwdIterator() ;
180 RooAbsArg* targ ;
181 while ((targ = it.next())) {
182 if (!i.first->second->find(*targ)) {
183 i.first->second->add(*targ) ;
184 }
185 }
186 //i.first->second->add(*i.second->second);
187
188 delete i.second->first;
189 delete i.second->second;
190 map->erase(i.second);
191 }
192 } while (overlap);
193
194 // check that we have all variables to be integrated over on the LHS
195 // of the map, and all terms in the product do appear on the RHS
196 int nVar=0; int nFunc=0;
197 for (ProdMap::iterator i = map->begin();i!=map->end();++i) {
198 nVar+=i->first->getSize();
199 nFunc+=i->second->getSize();
200 }
201 assert(nVar==allVars.getSize());
202 assert(nFunc==_compRSet.getSize());
203 return map;
204}
205
206
207
208////////////////////////////////////////////////////////////////////////////////
209/// Return list of (partial) integrals whose product defines the integral of this
210/// RooProduct over the observables in iset in range isetRange. If no such list
211/// exists, create it now and store it in the cache for future use.
212
213Int_t RooProduct::getPartIntList(const RooArgSet* iset, const char *isetRange) const
214{
215
216 // check if we already have integrals for this combination of factors
217 Int_t sterileIndex(-1);
218 CacheElem* cache = (CacheElem*) _cacheMgr.getObj(iset,iset,&sterileIndex,RooNameReg::ptr(isetRange));
219 if (cache!=0) {
220 Int_t code = _cacheMgr.lastIndex();
221 return code;
222 }
223
224 ProdMap* map = groupProductTerms(*iset);
225
226 cxcoutD(Integration) << "RooProduct::getPartIntList(" << GetName() << ") groupProductTerms returned map" ;
227 if (dologD(Integration)) {
228 dump_map(ccoutD(Integration),map->begin(),map->end());
229 ccoutD(Integration) << endl;
230 }
231
232 // did we find any factorizable terms?
233 if (map->size()<2) {
234
235 for (ProdMap::iterator iter = map->begin() ; iter != map->end() ; ++iter) {
236 delete iter->first ;
237 delete iter->second ;
238 }
239
240 delete map ;
241 return -1; // RRI caller will zero analVars if return code = 0....
242 }
243 cache = new CacheElem();
244
245 for (ProdMap::const_iterator i = map->begin();i!=map->end();++i) {
246 RooAbsReal *term(0);
247 if (i->second->getSize()>1) { // create a RooProd for this subexpression
248 const char *name = makeFPName("SUBPROD_",*i->second);
249 term = new RooProduct(name,name,*i->second);
250 cache->_ownedList.addOwned(*term);
251 cxcoutD(Integration) << "RooProduct::getPartIntList(" << GetName() << ") created subexpression " << term->GetName() << endl;
252 } else {
253 assert(i->second->getSize()==1);
254 RooFIter j = i->second->fwdIterator();
255 term = (RooAbsReal*)j.next();
256 }
257 assert(term!=0);
258 if (i->first->getSize()==0) { // check whether we need to integrate over this term or not...
259 cache->_prodList.add(*term);
260 cxcoutD(Integration) << "RooProduct::getPartIntList(" << GetName() << ") adding simple factor " << term->GetName() << endl;
261 } else {
262 RooAbsReal *integral = term->createIntegral(*i->first,isetRange);
263 cache->_prodList.add(*integral);
264 cache->_ownedList.addOwned(*integral);
265 cxcoutD(Integration) << "RooProduct::getPartIntList(" << GetName() << ") adding integral for " << term->GetName() << " : " << integral->GetName() << endl;
266 }
267 }
268 // add current set-up to cache, and return index..
269 Int_t code = _cacheMgr.setObj(iset,iset,(RooAbsCacheElement*)cache,RooNameReg::ptr(isetRange));
270
271 cxcoutD(Integration) << "RooProduct::getPartIntList(" << GetName() << ") created list " << cache->_prodList << " with code " << code+1 << endl
272 << " for iset=" << *iset << " @" << iset << " range: " << (isetRange?isetRange:"<none>") << endl ;
273
274 for (ProdMap::iterator iter = map->begin() ; iter != map->end() ; ++iter) {
275 delete iter->first ;
276 delete iter->second ;
277 }
278 delete map ;
279 return code;
280}
281
282
283////////////////////////////////////////////////////////////////////////////////
284/// Declare that we handle all integrations internally
285
287 const RooArgSet* /*normSet*/,
288 const char* rangeName) const
289{
290 if (_forceNumInt) return 0 ;
291
292 // Declare that we can analytically integrate all requested observables
293 // (basically, we will take care of the problem, and delegate where required)
294 //assert(normSet==0);
295 assert(analVars.getSize()==0);
296 analVars.add(allVars) ;
297 Int_t code = getPartIntList(&analVars,rangeName)+1;
298 return code ;
299}
300
301
302////////////////////////////////////////////////////////////////////////////////
303/// Calculate integral internally from appropriate partial integral cache
304
305Double_t RooProduct::analyticalIntegral(Int_t code, const char* rangeName) const
306{
307 // note: rangeName implicit encoded in code: see _cacheMgr.setObj in getPartIntList...
308 CacheElem *cache = (CacheElem*) _cacheMgr.getObjByIndex(code-1);
309 if (cache==0) {
310 // cache got sterilized, trigger repopulation of this slot, then try again...
311 std::unique_ptr<RooArgSet> vars( getParameters(RooArgSet()) );
312 std::unique_ptr<RooArgSet> iset( _cacheMgr.nameSet2ByIndex(code-1)->select(*vars) );
313 Int_t code2 = getPartIntList(iset.get(),rangeName)+1;
314 assert(code==code2); // must have revived the right (sterilized) slot...
315 return analyticalIntegral(code2,rangeName);
316 }
317 assert(cache!=0);
318
319 return calculate(cache->_prodList);
320}
321
322
323////////////////////////////////////////////////////////////////////////////////
324/// Calculate and return product of partial terms in partIntList
325
327{
328 RooAbsReal *term(0);
329 Double_t val=1;
330 RooFIter i = partIntList.fwdIterator() ;
331 while((term=(RooAbsReal*)i.next())) {
332 double x = term->getVal();
333 val*= x;
334 }
335 return val;
336}
337
338
339////////////////////////////////////////////////////////////////////////////////
340/// Construct automatic name for internal product terms
341
342const char* RooProduct::makeFPName(const char *pfx,const RooArgSet& terms) const
343{
344 static TString pname;
345 pname = pfx;
346 RooFIter i = terms.fwdIterator();
347 RooAbsArg *arg;
349 while((arg=(RooAbsArg*)i.next())) {
350 if (first) { first=kFALSE;}
351 else pname.Append("_X_");
352 pname.Append(arg->GetName());
353 }
354 return pname.Data();
355}
356
357
358
359////////////////////////////////////////////////////////////////////////////////
360/// Evaluate product of input functions
361
363{
364 Double_t prod(1) ;
365
366 const RooArgSet* nset = _compRSet.nset() ;
367 for (const auto item : _compRSet) {
368 auto rcomp = static_cast<const RooAbsReal*>(item);
369
370 prod *= rcomp->getVal(nset) ;
371 }
372
373 for (const auto item : _compCSet) {
374 auto ccomp = static_cast<const RooAbsCategory*>(item);
375
376 prod *= ccomp->getCurrentIndex() ;
377 }
378
379 return prod ;
380}
381
382
383
384////////////////////////////////////////////////////////////////////////////////
385/// Forward the plot sampling hint from the p.d.f. that defines the observable obs
386
387std::list<Double_t>* RooProduct::binBoundaries(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const
388{
389 for (const auto item : _compRSet) {
390 auto func = static_cast<const RooAbsReal*>(item);
391
392 list<Double_t>* binb = func->binBoundaries(obs,xlo,xhi) ;
393 if (binb) {
394 return binb ;
395 }
396 }
397
398 return 0 ;
399}
400
401
402//_____________________________________________________________________________B
404{
405 // If all components that depend on obs are binned that so is the product
406
407 for (const auto item : _compRSet) {
408 auto func = static_cast<const RooAbsReal*>(item);
409
410 if (func->dependsOn(obs) && !func->isBinnedDistribution(obs)) {
411 return kFALSE ;
412 }
413 }
414
415 return kTRUE ;
416}
417
418
419
420////////////////////////////////////////////////////////////////////////////////
421/// Forward the plot sampling hint from the p.d.f. that defines the observable obs
422
423std::list<Double_t>* RooProduct::plotSamplingHint(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const
424{
425 for (const auto item : _compRSet) {
426 auto func = static_cast<const RooAbsReal*>(item);
427
428 list<Double_t>* hint = func->plotSamplingHint(obs,xlo,xhi) ;
429 if (hint) {
430 return hint ;
431 }
432 }
433
434 return 0 ;
435}
436
437
438
439////////////////////////////////////////////////////////////////////////////////
440/// Destructor
441
443{
444}
445
446
447////////////////////////////////////////////////////////////////////////////////
448/// Return list of all RooAbsArgs in cache element
449
451{
452 RooArgList ret(_ownedList) ;
453 return ret ;
454}
455
456
457
458
459////////////////////////////////////////////////////////////////////////////////
460/// Label OK'ed components of a RooProduct with cache-and-track
461
463{
464 RooArgSet comp(components()) ;
465 for (const auto parg : comp) {
466 if (parg->isDerived()) {
467 if (parg->canNodeBeCached()==Always) {
468 trackNodes.add(*parg) ;
469 //cout << "tracking node RooProduct component " << parg->IsA()->GetName() << "::" << parg->GetName() << endl ;
470 }
471 }
472 }
473}
474
475
476
477
478
479////////////////////////////////////////////////////////////////////////////////
480/// Customized printing of arguments of a RooProduct to more intuitively reflect the contents of the
481/// product operator construction
482
483void RooProduct::printMetaArgs(ostream& os) const
484{
486
487 for (const auto rcomp : _compRSet) {
488 if (!first) { os << " * " ; } else { first = kFALSE ; }
489 os << rcomp->GetName() ;
490 }
491
492 for (const auto item : _compCSet) {
493 auto ccomp = static_cast<const RooAbsCategory*>(item);
494
495 if (!first) { os << " * " ; } else { first = kFALSE ; }
496 os << ccomp->GetName() ;
497 }
498
499 os << " " ;
500}
501
502
503
504
505
506namespace {
507
508std::pair<RPPMIter,RPPMIter> findOverlap2nd(RPPMIter i, RPPMIter end)
509{
510 // Utility function finding pairs of overlapping input functions
511 for (; i!=end; ++i) for ( RPPMIter j(i+1); j!=end; ++j) {
512 if (i->second->overlaps(*j->second)) {
513 return std::make_pair(i,j);
514 }
515 }
516 return std::make_pair(end,end);
517}
518
519
520void dump_map(ostream& os, RPPMIter i, RPPMIter end)
521{
522 // Utility dump function for debugging
524 os << " [ " ;
525 for(; i!=end;++i) {
526 if (first) { first=kFALSE; }
527 else { os << " , " ; }
528 os << *(i->first) << " -> " << *(i->second) ;
529 }
530 os << " ] " ;
531}
532
533}
534
535
536
537
#define cxcoutD(a)
#define dologD(a)
#define coutE(a)
#define ccoutD(a)
#define TRACE_DESTROY
Definition RooTrace.h:24
#define TRACE_CREATE
Definition RooTrace.h:23
const Bool_t kFALSE
Definition RtypesCore.h:92
bool Bool_t
Definition RtypesCore.h:63
const Bool_t kTRUE
Definition RtypesCore.h:91
#define ClassImp(name)
Definition Rtypes.h:364
char name[80]
Definition TGX11.cxx:110
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition RooAbsArg.h:72
Bool_t dependsOn(const RooAbsCollection &serverList, const RooAbsArg *ignoreArg=0, Bool_t valueOnly=kFALSE) const
Test whether we depend on (ie, are served by) any object in the specified collection.
friend class RooArgSet
Definition RooAbsArg.h:606
RooArgSet * getParameters(const RooAbsData *data, bool stripDisconnected=true) const
Create a list of leaf nodes in the arg tree starting with ourself as top node that don't match any of...
RooAbsCacheElement is the abstract base class for objects to be stored in RooAbsCache cache manager o...
RooAbsCategory is the base class for objects that represent a discrete value with a finite number of ...
Int_t getSize() const
virtual Bool_t addOwned(RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
RooFIter fwdIterator() const
One-time forward iterator.
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
RooAbsArg * first() const
const RooArgSet * nset() const
Definition RooAbsProxy.h:45
RooAbsRealLValue is the common abstract base class for objects that represent a real value that may a...
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition RooAbsReal.h:61
Bool_t _forceNumInt
Definition RooAbsReal.h:478
virtual std::list< Double_t > * binBoundaries(RooAbsRealLValue &obs, Double_t xlo, Double_t xhi) const
Retrieve bin boundaries if this distribution is binned in obs.
Double_t getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:91
RooAbsReal * createIntegral(const RooArgSet &iset, const RooCmdArg &arg1, const RooCmdArg &arg2=RooCmdArg::none(), const RooCmdArg &arg3=RooCmdArg::none(), const RooCmdArg &arg4=RooCmdArg::none(), const RooCmdArg &arg5=RooCmdArg::none(), const RooCmdArg &arg6=RooCmdArg::none(), const RooCmdArg &arg7=RooCmdArg::none(), const RooCmdArg &arg8=RooCmdArg::none()) const
Create an object that represents the integral of the function over one or more observables listed in ...
virtual std::list< Double_t > * plotSamplingHint(RooAbsRealLValue &obs, Double_t xlo, Double_t xhi) const
Interface for returning an optional hint for initial sampling points when constructing a curve projec...
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:21
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:29
Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE) override
Add element to non-owning set.
T * getObj(const RooArgSet *nset, Int_t *sterileIndex=0, const TNamed *isetRangeName=0)
const RooNameSet * nameSet2ByIndex(Int_t index) const
Retrieve RooNameSet associated with slot at given index.
T * getObjByIndex(Int_t index) const
Retrieve payload object by slot index.
Int_t lastIndex() const
Int_t setObj(const RooArgSet *nset, T *obj, const TNamed *isetRangeName=0)
static void softAbort()
A one-time forward iterator working on RooLinkedList or RooAbsCollection.
RooAbsArg * next()
Return next element or nullptr if at end.
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE) override
Reimplementation of standard RooArgList::add()
static const TNamed * ptr(const char *stringPtr)
Return a unique TNamed pointer for given C++ string.
RooArgSet * select(const RooArgSet &list) const
Construct a RooArgSet of objects in input 'list' whose names match to those in the internal name list...
virtual ~CacheElem()
Destructor.
RooArgList _ownedList
Definition RooProduct.h:69
virtual RooArgList containedArgs(Action)
Return list of all RooAbsArgs in cache element.
A RooProduct represents the product of a given set of RooAbsReal objects.
Definition RooProduct.h:29
void printMetaArgs(std::ostream &os) const
Customized printing of arguments of a RooProduct to more intuitively reflect the contents of the prod...
virtual std::list< Double_t > * plotSamplingHint(RooAbsRealLValue &, Double_t, Double_t) const
Forward the plot sampling hint from the p.d.f. that defines the observable obs
RooListProxy _compRSet
Definition RooProduct.h:61
virtual ~RooProduct()
Destructor.
ProdMap * groupProductTerms(const RooArgSet &) const
Group observables into subsets in which the product factorizes and that can thus be integrated separa...
Double_t calculate(const RooArgList &partIntList) const
Calculate and return product of partial terms in partIntList.
Double_t evaluate() const
Evaluate product of input functions.
virtual Int_t getAnalyticalIntegralWN(RooArgSet &allVars, RooArgSet &analVars, const RooArgSet *normSet, const char *rangeName=0) const
Declare that we handle all integrations internally.
virtual std::list< Double_t > * binBoundaries(RooAbsRealLValue &, Double_t, Double_t) const
Forward the plot sampling hint from the p.d.f. that defines the observable obs
const char * makeFPName(const char *pfx, const RooArgSet &terms) const
Construct automatic name for internal product terms.
virtual Bool_t forceAnalyticalInt(const RooAbsArg &dep) const
Force internal handling of integration of given observable if any of the product terms depend on it.
virtual Double_t analyticalIntegral(Int_t code, const char *rangeName=0) const
Calculate integral internally from appropriate partial integral cache.
RooProduct()
Default constructor.
RooObjCacheManager _cacheMgr
Definition RooProduct.h:72
Int_t getPartIntList(const RooArgSet *iset, const char *rangeName=0) const
Return list of (partial) integrals whose product defines the integral of this RooProduct over the obs...
virtual void setCacheAndTrackHints(RooArgSet &)
Label OK'ed components of a RooProduct with cache-and-track.
RooListProxy _compCSet
Definition RooProduct.h:62
virtual Bool_t isBinnedDistribution(const RooArgSet &obs) const
Tests if the distribution is binned. Unless overridden by derived classes, this always returns false.
RooArgList components()
Definition RooProduct.h:44
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
Basic string class.
Definition TString.h:136
const char * Data() const
Definition TString.h:369
TString & Append(const char *cs)
Definition TString.h:564
Double_t x[n]
Definition legend1.C:17
Definition first.py:1