Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooAddition.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 RooAddition.cxx
19\class RooAddition
20\ingroup Roofitcore
21
22RooAddition calculates the sum of a set of RooAbsReal terms, or
23when constructed with two sets, it sums the product of the terms
24in the two sets.
25**/
26
27
28#include "RooFit.h"
29
30#include "Riostream.h"
31#include "RooAddition.h"
32#include "RooProduct.h"
33#include "RooAbsReal.h"
34#include "RooErrorHandler.h"
35#include "RooArgSet.h"
36#include "RooNameReg.h"
37#include "RooNLLVar.h"
38#include "RooNLLVarNew.h"
39#include "RooChi2Var.h"
40#include "RooMsgService.h"
41#include "RooBatchCompute.h"
42
43#include <algorithm>
44#include <cmath>
45
46using namespace std;
47
49;
50
51
52////////////////////////////////////////////////////////////////////////////////
53/// Empty constructor
54RooAddition::RooAddition() : _cacheMgr(this,10)
55{
56}
57
58
59
60////////////////////////////////////////////////////////////////////////////////
61/// Constructor with a single set consisting of RooAbsReal.
62/// \param[in] name Name of the PDF
63/// \param[in] title Title
64/// \param[in] sumSet The value of the function will be the sum of the values in this set
65/// \param[in] takeOwnership If true, the RooAddition object will take ownership of the arguments in `sumSet`
66
67RooAddition::RooAddition(const char* name, const char* title, const RooArgList& sumSet, Bool_t takeOwnership)
68 : RooAbsReal(name, title)
69 , _set("!set","set of components",this)
70 , _cacheMgr(this,10)
71{
72 for (const auto comp : sumSet) {
73 if (!dynamic_cast<RooAbsReal*>(comp)) {
74 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: component " << comp->GetName()
75 << " is not of type RooAbsReal" << endl ;
77 }
78 _set.add(*comp) ;
79 if (takeOwnership) _ownedList.addOwned(*comp) ;
80 }
81
82}
83
84
85
86////////////////////////////////////////////////////////////////////////////////
87/// Constructor with two sets of RooAbsReals.
88///
89/// The sum of pair-wise products of elements in the sets will be computed:
90/// \f[
91/// A = \sum_i \mathrm{Set1}[i] * \mathrm{Set2}[i]
92/// \f]
93///
94/// \param[in] name Name of the PDF
95/// \param[in] title Title
96/// \param[in] sumSet1 Left-hand element of the pair-wise products
97/// \param[in] sumSet2 Right-hand element of the pair-wise products
98/// \param[in] takeOwnership If true, the RooAddition object will take ownership of the arguments in the `sumSets`
99///
100RooAddition::RooAddition(const char* name, const char* title, const RooArgList& sumSet1, const RooArgList& sumSet2, Bool_t takeOwnership)
101 : RooAbsReal(name, title)
102 , _set("!set","set of components",this)
103 , _cacheMgr(this,10)
104{
105 if (sumSet1.getSize() != sumSet2.getSize()) {
106 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: input lists should be of equal length" << endl ;
108 }
109
110 for (unsigned int i = 0; i < sumSet1.size(); ++i) {
111 const auto comp1 = &sumSet1[i];
112 const auto comp2 = &sumSet2[i];
113
114 if (!dynamic_cast<RooAbsReal*>(comp1)) {
115 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: component " << comp1->GetName()
116 << " in first list is not of type RooAbsReal" << endl ;
118 }
119
120 if (!dynamic_cast<RooAbsReal*>(comp2)) {
121 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: component " << comp2->GetName()
122 << " in first list is not of type RooAbsReal" << endl ;
124 }
125 // TODO: add flag to RooProduct c'tor to make it assume ownership...
126 TString _name(name);
127 _name.Append( "_[");
128 _name.Append(comp1->GetName());
129 _name.Append( "_x_");
130 _name.Append(comp2->GetName());
131 _name.Append( "]");
132 RooProduct *prod = new RooProduct( _name, _name , RooArgSet(*comp1, *comp2) /*, takeOwnership */ ) ;
133 _set.add(*prod);
134 _ownedList.addOwned(*prod) ;
135 if (takeOwnership) {
136 _ownedList.addOwned(*comp1) ;
137 _ownedList.addOwned(*comp2) ;
138 }
139 }
140}
141
142
143
144////////////////////////////////////////////////////////////////////////////////
145/// Copy constructor
146
147RooAddition::RooAddition(const RooAddition& other, const char* name)
148 : RooAbsReal(other, name)
149 , _set("!set",this,other._set)
150 , _cacheMgr(other._cacheMgr,this)
151{
152 // Member _ownedList is intentionally not copy-constructed -- ownership is not transferred
153}
154
155
156////////////////////////////////////////////////////////////////////////////////
157
159{ // Destructor
160
161}
162
163////////////////////////////////////////////////////////////////////////////////
164/// Calculate and return current value of self
165
167{
168 Double_t sum(0);
169 const RooArgSet* nset = _set.nset() ;
170
171// cout << "RooAddition::eval sum = " ;
172
173 for (const auto arg : _set) {
174 const auto comp = static_cast<RooAbsReal*>(arg);
175 const Double_t tmp = comp->getVal(nset);
176// cout << tmp << " " ;
177 sum += tmp ;
178 }
179// cout << " = " << sum << endl ;
180 return sum ;
181}
182
183
184////////////////////////////////////////////////////////////////////////////////
185/// Compute addition of PDFs in batches.
186void RooAddition::computeBatch(cudaStream_t* stream, double* output, size_t nEvents, RooFit::Detail::DataMap const& dataMap) const
187{
190 pdfs.reserve(_set.size());
191 coefs.reserve(_set.size());
192 for (const auto arg : _set)
193 {
194 pdfs.push_back(dataMap.at(arg));
195 coefs.push_back(1.0);
196 }
198 dispatch->compute(stream, RooBatchCompute::AddPdf, output, nEvents, pdfs, coefs);
199}
200
201
202////////////////////////////////////////////////////////////////////////////////
203/// Return the default error level for MINUIT error analysis
204/// If the addition contains one or more RooNLLVars and
205/// no RooChi2Vars, return the defaultErrorLevel() of
206/// RooNLLVar. If the addition contains one ore more RooChi2Vars
207/// and no RooNLLVars, return the defaultErrorLevel() of
208/// RooChi2Var. If the addition contains neither or both
209/// issue a warning message and return a value of 1
210
212{
213 RooAbsReal* nllArg(0) ;
214 RooAbsReal* chi2Arg(0) ;
215
216 RooAbsArg* arg ;
217
218 RooArgSet* comps = getComponents() ;
219 TIterator* iter = comps->createIterator() ;
220 while((arg=(RooAbsArg*)iter->Next())) {
221 if (dynamic_cast<RooNLLVar*>(arg) || dynamic_cast<ROOT::Experimental::RooNLLVarNew*>(arg)) {
222 nllArg = (RooAbsReal*)arg ;
223 }
224 if (dynamic_cast<RooChi2Var*>(arg)) {
225 chi2Arg = (RooAbsReal*)arg ;
226 }
227 }
228 delete iter ;
229 delete comps ;
230
231 if (nllArg && !chi2Arg) {
232 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName()
233 << ") Summation contains a RooNLLVar, using its error level" << endl ;
234 return nllArg->defaultErrorLevel() ;
235 } else if (chi2Arg && !nllArg) {
236 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName()
237 << ") Summation contains a RooChi2Var, using its error level" << endl ;
238 return chi2Arg->defaultErrorLevel() ;
239 } else if (!nllArg && !chi2Arg) {
240 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName() << ") WARNING: "
241 << "Summation contains neither RooNLLVar nor RooChi2Var server, using default level of 1.0" << endl ;
242 } else {
243 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName() << ") WARNING: "
244 << "Summation contains BOTH RooNLLVar and RooChi2Var server, using default level of 1.0" << endl ;
245 }
246
247 return 1.0 ;
248}
249
250
251////////////////////////////////////////////////////////////////////////////////
252
254{
255 for (auto arg : _set) {
256 static_cast<RooAbsReal*>(arg)->enableOffsetting(flag) ;
257 }
258}
259
260
261
262////////////////////////////////////////////////////////////////////////////////
263
265{
266 for (const auto arg : _set) {
267 static_cast<RooAbsReal*>(arg)->setData(data,cloneData) ;
268 }
269 return kTRUE ;
270}
271
272
273
274////////////////////////////////////////////////////////////////////////////////
275
276void RooAddition::printMetaArgs(ostream& os) const
277{
279 for (const auto arg : _set) {
280 if (!first) {
281 os << " + " ;
282 } else {
283 first = kFALSE ;
284 }
285 os << arg->GetName() ;
286 }
287 os << " " ;
288}
289
290////////////////////////////////////////////////////////////////////////////////
291
292Int_t RooAddition::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName) const
293{
294 // we always do things ourselves -- actually, always delegate further down the line ;-)
295 analVars.add(allVars);
296
297 // check if we already have integrals for this combination of factors
298 Int_t sterileIndex(-1);
299 CacheElem* cache = (CacheElem*) _cacheMgr.getObj(&analVars,&analVars,&sterileIndex,RooNameReg::ptr(rangeName));
300 if (cache!=0) {
301 Int_t code = _cacheMgr.lastIndex();
302 return code+1;
303 }
304
305 // we don't, so we make it right here....
306 cache = new CacheElem;
307 for (const auto arg : _set) {// checked in c'tor that this will work...
308 RooAbsReal *I = static_cast<const RooAbsReal*>(arg)->createIntegral(analVars,rangeName);
309 cache->_I.addOwned(*I);
310 }
311
312 Int_t code = _cacheMgr.setObj(&analVars,&analVars,(RooAbsCacheElement*)cache,RooNameReg::ptr(rangeName));
313 return 1+code;
314}
315
316////////////////////////////////////////////////////////////////////////////////
317/// Calculate integral internally from appropriate integral cache
318
319Double_t RooAddition::analyticalIntegral(Int_t code, const char* rangeName) const
320{
321 // note: rangeName implicit encoded in code: see _cacheMgr.setObj in getPartIntList...
322 CacheElem *cache = (CacheElem*) _cacheMgr.getObjByIndex(code-1);
323 if (cache==0) {
324 // cache got sterilized, trigger repopulation of this slot, then try again...
325 std::unique_ptr<RooArgSet> vars( getParameters(RooArgSet()) );
326 RooArgSet iset = _cacheMgr.selectFromSet2(*vars, code-1);
327 RooArgSet dummy;
328 Int_t code2 = getAnalyticalIntegral(iset,dummy,rangeName);
329 assert(code==code2); // must have revived the right (sterilized) slot...
330 return analyticalIntegral(code2,rangeName);
331 }
332 assert(cache!=0);
333
334 // loop over cache, and sum...
335 double result(0);
336 for (auto I : cache->_I) {
337 result += static_cast<const RooAbsReal*>(I)->getVal();
338 }
339 return result;
340
341}
342
343
344
345////////////////////////////////////////////////////////////////////////////////
346
347std::list<Double_t>* RooAddition::binBoundaries(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const
348{
349 std::list<Double_t>* sumBinB = 0 ;
350 Bool_t needClean(kFALSE) ;
351
352 RooFIter iter = _set.fwdIterator() ;
353 RooAbsReal* func ;
354 // Loop over components pdf
355 while((func=(RooAbsReal*)iter.next())) {
356
357 std::list<Double_t>* funcBinB = func->binBoundaries(obs,xlo,xhi) ;
358
359 // Process hint
360 if (funcBinB) {
361 if (!sumBinB) {
362 // If this is the first hint, then just save it
363 sumBinB = funcBinB ;
364 } else {
365
366 std::list<Double_t>* newSumBinB = new std::list<Double_t>(sumBinB->size()+funcBinB->size()) ;
367
368 // Merge hints into temporary array
369 merge(funcBinB->begin(),funcBinB->end(),sumBinB->begin(),sumBinB->end(),newSumBinB->begin()) ;
370
371 // Copy merged array without duplicates to new sumBinBArrau
372 delete sumBinB ;
373 delete funcBinB ;
374 sumBinB = newSumBinB ;
375 needClean = kTRUE ;
376 }
377 }
378 }
379
380 // Remove consecutive duplicates
381 if (needClean) {
382 std::list<Double_t>::iterator new_end = unique(sumBinB->begin(),sumBinB->end()) ;
383 sumBinB->erase(new_end,sumBinB->end()) ;
384 }
385
386 return sumBinB ;
387}
388
389
390//_____________________________________________________________________________B
392{
393 // If all components that depend on obs are binned that so is the product
394
395 RooFIter iter = _set.fwdIterator() ;
396 RooAbsReal* func ;
397 while((func=(RooAbsReal*)iter.next())) {
398 if (func->dependsOn(obs) && !func->isBinnedDistribution(obs)) {
399 return kFALSE ;
400 }
401 }
402
403 return kTRUE ;
404}
405
406
407
408
409////////////////////////////////////////////////////////////////////////////////
410
411std::list<Double_t>* RooAddition::plotSamplingHint(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const
412{
413 std::list<Double_t>* sumHint = 0 ;
414 Bool_t needClean(kFALSE) ;
415
416 RooFIter iter = _set.fwdIterator() ;
417 RooAbsReal* func ;
418 // Loop over components pdf
419 while((func=(RooAbsReal*)iter.next())) {
420
421 std::list<Double_t>* funcHint = func->plotSamplingHint(obs,xlo,xhi) ;
422
423 // Process hint
424 if (funcHint) {
425 if (!sumHint) {
426
427 // If this is the first hint, then just save it
428 sumHint = funcHint ;
429
430 } else {
431
432 std::list<Double_t>* newSumHint = new std::list<Double_t>(sumHint->size()+funcHint->size()) ;
433
434 // Merge hints into temporary array
435 merge(funcHint->begin(),funcHint->end(),sumHint->begin(),sumHint->end(),newSumHint->begin()) ;
436
437 // Copy merged array without duplicates to new sumHintArrau
438 delete sumHint ;
439 sumHint = newSumHint ;
440 needClean = kTRUE ;
441 }
442 }
443 }
444
445 // Remove consecutive duplicates
446 if (needClean) {
447 std::list<Double_t>::iterator new_end = unique(sumHint->begin(),sumHint->end()) ;
448 sumHint->erase(new_end,sumHint->end()) ;
449 }
450
451 return sumHint ;
452}
453
454
455
456////////////////////////////////////////////////////////////////////////////////
457/// Return list of all RooAbsArgs in cache element
458
460{
461 RooArgList ret(_I) ;
462 return ret ;
463}
464
466{
467 // Destructor
468}
469
470
#define coutI(a)
#define coutE(a)
const Bool_t kFALSE
Definition RtypesCore.h:101
const Bool_t kTRUE
Definition RtypesCore.h:100
#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:69
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:642
RooArgSet * getComponents() const
Create a RooArgSet with all components (branch nodes) of the expression tree headed by this object.
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...
Int_t getSize() const
RooFIter fwdIterator() const
One-time forward iterator.
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
virtual Bool_t addOwned(RooAbsArg &var, Bool_t silent=kFALSE)
Add an argument and transfer the ownership to the collection.
Storage_t::size_type size() const
const char * GetName() const
Returns name of object.
TIterator * createIterator(Bool_t dir=kIterForward) const
TIterator-style iteration over contained elements.
RooAbsData is the common abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:82
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:64
virtual Double_t defaultErrorLevel() const
Definition RooAbsReal.h:256
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 > * 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:94
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...
virtual Bool_t isBinnedDistribution(const RooArgSet &) const
Tests if the distribution is binned. Unless overridden by derived classes, this always returns false.
Definition RooAbsReal.h:345
virtual RooArgList containedArgs(Action)
Return list of all RooAbsArgs in cache element.
RooAddition calculates the sum of a set of RooAbsReal terms, or when constructed with two sets,...
Definition RooAddition.h:27
void printMetaArgs(std::ostream &os) const
virtual std::list< Double_t > * plotSamplingHint(RooAbsRealLValue &, Double_t, Double_t) const
Interface for returning an optional hint for initial sampling points when constructing a curve projec...
Int_t getAnalyticalIntegral(RooArgSet &allVars, RooArgSet &numVars, const char *rangeName=0) const
Interface function getAnalyticalIntergral advertises the analytical integrals that are supported.
Bool_t isBinnedDistribution(const RooArgSet &obs) const
Tests if the distribution is binned. Unless overridden by derived classes, this always returns false.
RooArgList _ownedList
Definition RooAddition.h:64
virtual void enableOffsetting(Bool_t)
Double_t analyticalIntegral(Int_t code, const char *rangeName=0) const
Calculate integral internally from appropriate integral cache.
RooListProxy _set
Definition RooAddition.h:65
Double_t evaluate() const
The cache manager.
virtual ~RooAddition()
RooAddition()
Empty constructor.
RooObjCacheManager _cacheMgr
Definition RooAddition.h:74
virtual std::list< Double_t > * binBoundaries(RooAbsRealLValue &, Double_t, Double_t) const
Retrieve bin boundaries if this distribution is binned in obs.
void computeBatch(cudaStream_t *, double *output, size_t nEvents, RooFit::Detail::DataMap const &) const
Compute addition of PDFs in batches.
Bool_t setData(RooAbsData &data, Bool_t cloneData=kTRUE)
virtual Double_t defaultErrorLevel() const
Return the default error level for MINUIT error analysis If the addition contains one or more RooNLLV...
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:35
virtual void compute(cudaStream_t *, Computer, RestrictArr, size_t, const VarVector &, const ArgVector &={})=0
T * getObj(const RooArgSet *nset, Int_t *sterileIndex=0, const TNamed *isetRangeName=0)
T * getObjByIndex(Int_t index) const
Retrieve payload object by slot index.
RooArgSet selectFromSet2(RooArgSet const &argSet, int index) const
Create RooArgSet contatining the objects that are both in the cached set 2.
Int_t lastIndex() const
Int_t setObj(const RooArgSet *nset, T *obj, const TNamed *isetRangeName=0)
RooChi2Var implements a simple calculation from a binned dataset and a PDF.
Definition RooChi2Var.h:25
static void softAbort()
A one-time forward iterator working on RooLinkedList or RooAbsCollection.
RooAbsArg * next()
Return next element or nullptr if at end.
auto & at(RooAbsArg const *arg, RooAbsArg const *=nullptr)
Definition DataMap.h:88
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE) override
Reimplementation of standard RooArgList::add()
Class RooNLLVar implements a -log(likelihood) calculation from a dataset and a PDF.
Definition RooNLLVar.h:30
static const TNamed * ptr(const char *stringPtr)
Return a unique TNamed pointer for given C++ string.
A RooProduct represents the product of a given set of RooAbsReal objects.
Definition RooProduct.h:29
Iterator abstract base class.
Definition TIterator.h:30
virtual TObject * Next()=0
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
Basic string class.
Definition TString.h:136
TString & Append(const char *cs)
Definition TString.h:564
#define I(x, y, z)
std::vector< RooSpan< const double > > VarVector
R__EXTERN RooBatchComputeInterface * dispatchCUDA
R__EXTERN RooBatchComputeInterface * dispatchCPU
This dispatch pointer points to an implementation of the compute library, provided one has been loade...
std::vector< double > ArgVector
Definition first.py:1
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2345
static void output(int code)
Definition gifencode.c:226