Logo ROOT   6.18/05
Reference Guide
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. This class does not (yet) do any smart handling of integrals,
25i.e. all integrals of the product are handled numerically
26**/
27
28
29#include "RooFit.h"
30
31#include "Riostream.h"
32#include "RooAddition.h"
33#include "RooProduct.h"
34#include "RooAbsReal.h"
35#include "RooErrorHandler.h"
36#include "RooArgSet.h"
37#include "RooNameReg.h"
38#include "RooNLLVar.h"
39#include "RooChi2Var.h"
40#include "RooMsgService.h"
41
42#include <algorithm>
43#include <cmath>
44
45using namespace std;
46
48;
49
50
51////////////////////////////////////////////////////////////////////////////////
52/// Empty constructor
54 : _setIter( _set.createIterator() )
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 , _setIter( _set.createIterator() ) // yes, _setIter is defined _after_ _set ;-)
71 , _cacheMgr(this,10)
72{
73 std::unique_ptr<TIterator> inputIter( sumSet.createIterator() );
74 RooAbsArg* comp ;
75 while((comp = (RooAbsArg*)inputIter->Next())) {
76 if (!dynamic_cast<RooAbsReal*>(comp)) {
77 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: component " << comp->GetName()
78 << " is not of type RooAbsReal" << endl ;
80 }
81 _set.add(*comp) ;
82 if (takeOwnership) _ownedList.addOwned(*comp) ;
83 }
84
85}
86
87
88
89////////////////////////////////////////////////////////////////////////////////
90/// Constructor with two sets of RooAbsReals.
91///
92/// The sum of pair-wise products of elements in the sets will be computed:
93/// \f[
94/// A = \sum_i \mathrm{Set1}[i] * \mathrm{Set2}[i]
95/// \f]
96///
97/// \param[in] name Name of the PDF
98/// \param[in] title Title
99/// \param[in] sumSet1 Left-hand element of the pair-wise products
100/// \param[in] sumSet2 Right-hand element of the pair-wise products
101/// \param[in] takeOwnership If true, the RooAddition object will take ownership of the arguments in the `sumSets`
102///
103
104
105RooAddition::RooAddition(const char* name, const char* title, const RooArgList& sumSet1, const RooArgList& sumSet2, Bool_t takeOwnership)
106 : RooAbsReal(name, title)
107 , _set("!set","set of components",this)
108 , _setIter( _set.createIterator() ) // yes, _setIter is defined _after_ _set ;-)
109 , _cacheMgr(this,10)
110{
111 if (sumSet1.getSize() != sumSet2.getSize()) {
112 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: input lists should be of equal length" << endl ;
114 }
115
116 std::unique_ptr<TIterator> inputIter1( sumSet1.createIterator() );
117 std::unique_ptr<TIterator> inputIter2( sumSet2.createIterator() );
118 RooAbsArg *comp1(0),*comp2(0) ;
119 while((comp1 = (RooAbsArg*)inputIter1->Next())) {
120 if (!dynamic_cast<RooAbsReal*>(comp1)) {
121 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: component " << comp1->GetName()
122 << " in first list is not of type RooAbsReal" << endl ;
124 }
125 comp2 = (RooAbsArg*)inputIter2->Next();
126 if (!dynamic_cast<RooAbsReal*>(comp2)) {
127 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: component " << comp2->GetName()
128 << " in first list is not of type RooAbsReal" << endl ;
130 }
131 // TODO: add flag to RooProduct c'tor to make it assume ownership...
132 TString _name(name);
133 _name.Append( "_[");
134 _name.Append(comp1->GetName());
135 _name.Append( "_x_");
136 _name.Append(comp2->GetName());
137 _name.Append( "]");
138 RooProduct *prod = new RooProduct( _name, _name , RooArgSet(*comp1, *comp2) /*, takeOwnership */ ) ;
139 _set.add(*prod);
140 _ownedList.addOwned(*prod) ;
141 if (takeOwnership) {
142 _ownedList.addOwned(*comp1) ;
143 _ownedList.addOwned(*comp2) ;
144 }
145 }
146}
147
148
149
150////////////////////////////////////////////////////////////////////////////////
151/// Copy constructor
152
153RooAddition::RooAddition(const RooAddition& other, const char* name)
154 : RooAbsReal(other, name)
155 , _set("!set",this,other._set)
156 , _setIter( _set.createIterator() ) // yes, _setIter is defined _after_ _set ;-)
157 , _cacheMgr(other._cacheMgr,this)
158{
159 // Member _ownedList is intentionally not copy-constructed -- ownership is not transferred
160}
161
162
163////////////////////////////////////////////////////////////////////////////////
164
166{ // Destructor
167 delete _setIter ;
168}
169
170////////////////////////////////////////////////////////////////////////////////
171/// Calculate and return current value of self
172
174{
175 Double_t sum(0);
176 const RooArgSet* nset = _set.nset() ;
177
178// cout << "RooAddition::eval sum = " ;
179
180 for (const auto arg : _set) {
181 const auto comp = static_cast<RooAbsReal*>(arg);
182 const Double_t tmp = comp->getVal(nset);
183// cout << tmp << " " ;
184 sum += tmp ;
185 }
186// cout << " = " << sum << endl ;
187 return sum ;
188}
189
190
191////////////////////////////////////////////////////////////////////////////////
192/// Return the default error level for MINUIT error analysis
193/// If the addition contains one or more RooNLLVars and
194/// no RooChi2Vars, return the defaultErrorLevel() of
195/// RooNLLVar. If the addition contains one ore more RooChi2Vars
196/// and no RooNLLVars, return the defaultErrorLevel() of
197/// RooChi2Var. If the addition contains neither or both
198/// issue a warning message and return a value of 1
199
201{
202 RooAbsReal* nllArg(0) ;
203 RooAbsReal* chi2Arg(0) ;
204
205 RooAbsArg* arg ;
206
207 RooArgSet* comps = getComponents() ;
208 TIterator* iter = comps->createIterator() ;
209 while((arg=(RooAbsArg*)iter->Next())) {
210 if (dynamic_cast<RooNLLVar*>(arg)) {
211 nllArg = (RooAbsReal*)arg ;
212 }
213 if (dynamic_cast<RooChi2Var*>(arg)) {
214 chi2Arg = (RooAbsReal*)arg ;
215 }
216 }
217 delete iter ;
218 delete comps ;
219
220 if (nllArg && !chi2Arg) {
221 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName()
222 << ") Summation contains a RooNLLVar, using its error level" << endl ;
223 return nllArg->defaultErrorLevel() ;
224 } else if (chi2Arg && !nllArg) {
225 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName()
226 << ") Summation contains a RooChi2Var, using its error level" << endl ;
227 return chi2Arg->defaultErrorLevel() ;
228 } else if (!nllArg && !chi2Arg) {
229 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName() << ") WARNING: "
230 << "Summation contains neither RooNLLVar nor RooChi2Var server, using default level of 1.0" << endl ;
231 } else {
232 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName() << ") WARNING: "
233 << "Summation contains BOTH RooNLLVar and RooChi2Var server, using default level of 1.0" << endl ;
234 }
235
236 return 1.0 ;
237}
238
239
240////////////////////////////////////////////////////////////////////////////////
241
243{
244 _setIter->Reset() ;
245
246 RooAbsReal* arg;
247 while((arg=(RooAbsReal*)_setIter->Next())) {
248 arg->enableOffsetting(flag) ;
249 }
250}
251
252
253
254////////////////////////////////////////////////////////////////////////////////
255
257{
258 _setIter->Reset() ;
259
260 RooAbsReal* arg;
261 while((arg=(RooAbsReal*)_setIter->Next())) {
262 arg->setData(data,cloneData) ;
263 }
264 return kTRUE ;
265}
266
267
268
269////////////////////////////////////////////////////////////////////////////////
270
271void RooAddition::printMetaArgs(ostream& os) const
272{
273 _setIter->Reset() ;
274
276 RooAbsArg* arg;
277 while((arg=(RooAbsArg*)_setIter->Next())) {
278 if (!first) { os << " + " ;
279 } else { first = kFALSE ;
280 }
281 os << arg->GetName() ;
282 }
283 os << " " ;
284}
285
286////////////////////////////////////////////////////////////////////////////////
287
288Int_t RooAddition::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName) const
289{
290 // we always do things ourselves -- actually, always delegate further down the line ;-)
291 analVars.add(allVars);
292
293 // check if we already have integrals for this combination of factors
294 Int_t sterileIndex(-1);
295 CacheElem* cache = (CacheElem*) _cacheMgr.getObj(&analVars,&analVars,&sterileIndex,RooNameReg::ptr(rangeName));
296 if (cache!=0) {
297 Int_t code = _cacheMgr.lastIndex();
298 return code+1;
299 }
300
301 // we don't, so we make it right here....
302 cache = new CacheElem;
303 _setIter->Reset();
304 RooAbsReal *arg(0);
305 while( (arg=(RooAbsReal*)_setIter->Next())!=0 ) { // checked in c'tor that this will work...
306 RooAbsReal *I = arg->createIntegral(analVars,rangeName);
307 cache->_I.addOwned(*I);
308 }
309
310 Int_t code = _cacheMgr.setObj(&analVars,&analVars,(RooAbsCacheElement*)cache,RooNameReg::ptr(rangeName));
311 return 1+code;
312}
313
314////////////////////////////////////////////////////////////////////////////////
315/// Calculate integral internally from appropriate integral cache
316
317Double_t RooAddition::analyticalIntegral(Int_t code, const char* rangeName) const
318{
319 // note: rangeName implicit encoded in code: see _cacheMgr.setObj in getPartIntList...
320 CacheElem *cache = (CacheElem*) _cacheMgr.getObjByIndex(code-1);
321 if (cache==0) {
322 // cache got sterilized, trigger repopulation of this slot, then try again...
323 std::unique_ptr<RooArgSet> vars( getParameters(RooArgSet()) );
324 std::unique_ptr<RooArgSet> iset( _cacheMgr.nameSet2ByIndex(code-1)->select(*vars) );
326 Int_t code2 = getAnalyticalIntegral(*iset,dummy,rangeName);
327 assert(code==code2); // must have revived the right (sterilized) slot...
328 return analyticalIntegral(code2,rangeName);
329 }
330 assert(cache!=0);
331
332 // loop over cache, and sum...
333 std::unique_ptr<TIterator> iter( cache->_I.createIterator() );
334 RooAbsReal *I;
335 double result(0);
336 while ( ( I=(RooAbsReal*)iter->Next() ) != 0 ) result += I->getVal();
337 return result;
338
339}
340
341
342
343////////////////////////////////////////////////////////////////////////////////
344
345std::list<Double_t>* RooAddition::binBoundaries(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const
346{
347 std::list<Double_t>* sumBinB = 0 ;
348 Bool_t needClean(kFALSE) ;
349
350 RooFIter iter = _set.fwdIterator() ;
351 RooAbsReal* func ;
352 // Loop over components pdf
353 while((func=(RooAbsReal*)iter.next())) {
354
355 std::list<Double_t>* funcBinB = func->binBoundaries(obs,xlo,xhi) ;
356
357 // Process hint
358 if (funcBinB) {
359 if (!sumBinB) {
360 // If this is the first hint, then just save it
361 sumBinB = funcBinB ;
362 } else {
363
364 std::list<Double_t>* newSumBinB = new std::list<Double_t>(sumBinB->size()+funcBinB->size()) ;
365
366 // Merge hints into temporary array
367 merge(funcBinB->begin(),funcBinB->end(),sumBinB->begin(),sumBinB->end(),newSumBinB->begin()) ;
368
369 // Copy merged array without duplicates to new sumBinBArrau
370 delete sumBinB ;
371 delete funcBinB ;
372 sumBinB = newSumBinB ;
373 needClean = kTRUE ;
374 }
375 }
376 }
377
378 // Remove consecutive duplicates
379 if (needClean) {
380 std::list<Double_t>::iterator new_end = unique(sumBinB->begin(),sumBinB->end()) ;
381 sumBinB->erase(new_end,sumBinB->end()) ;
382 }
383
384 return sumBinB ;
385}
386
387
388//_____________________________________________________________________________B
390{
391 // If all components that depend on obs are binned that so is the product
392
393 RooFIter iter = _set.fwdIterator() ;
394 RooAbsReal* func ;
395 while((func=(RooAbsReal*)iter.next())) {
396 if (func->dependsOn(obs) && !func->isBinnedDistribution(obs)) {
397 return kFALSE ;
398 }
399 }
400
401 return kTRUE ;
402}
403
404
405
406
407////////////////////////////////////////////////////////////////////////////////
408
409std::list<Double_t>* RooAddition::plotSamplingHint(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const
410{
411 std::list<Double_t>* sumHint = 0 ;
412 Bool_t needClean(kFALSE) ;
413
414 RooFIter iter = _set.fwdIterator() ;
415 RooAbsReal* func ;
416 // Loop over components pdf
417 while((func=(RooAbsReal*)iter.next())) {
418
419 std::list<Double_t>* funcHint = func->plotSamplingHint(obs,xlo,xhi) ;
420
421 // Process hint
422 if (funcHint) {
423 if (!sumHint) {
424
425 // If this is the first hint, then just save it
426 sumHint = funcHint ;
427
428 } else {
429
430 std::list<Double_t>* newSumHint = new std::list<Double_t>(sumHint->size()+funcHint->size()) ;
431
432 // Merge hints into temporary array
433 merge(funcHint->begin(),funcHint->end(),sumHint->begin(),sumHint->end(),newSumHint->begin()) ;
434
435 // Copy merged array without duplicates to new sumHintArrau
436 delete sumHint ;
437 sumHint = newSumHint ;
438 needClean = kTRUE ;
439 }
440 }
441 }
442
443 // Remove consecutive duplicates
444 if (needClean) {
445 std::list<Double_t>::iterator new_end = unique(sumHint->begin(),sumHint->end()) ;
446 sumHint->erase(new_end,sumHint->end()) ;
447 }
448
449 return sumHint ;
450}
451
452
453
454////////////////////////////////////////////////////////////////////////////////
455/// Return list of all RooAbsArgs in cache element
456
458{
459 RooArgList ret(_I) ;
460 return ret ;
461}
462
464{
465 // Destructor
466}
467
468
static RooMathCoreReg dummy
#define coutI(a)
Definition: RooMsgService.h:31
#define coutE(a)
Definition: RooMsgService.h:34
int Int_t
Definition: RtypesCore.h:41
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
double Double_t
Definition: RtypesCore.h:55
const Bool_t kTRUE
Definition: RtypesCore.h:87
#define ClassImp(name)
Definition: Rtypes.h:365
char name[80]
Definition: TGX11.cxx:109
RooAbsArg is the common abstract base class for objects that represent a value (of arbitrary type) an...
Definition: RooAbsArg.h:70
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.
Definition: RooAbsArg.cxx:729
friend class RooArgSet
Definition: RooAbsArg.h:516
RooArgSet * getParameters(const RooAbsData *data, Bool_t stripDisconnected=kTRUE) const
Create a list of leaf nodes in the arg tree starting with ourself as top node that don't match any of...
Definition: RooAbsArg.cxx:543
RooArgSet * getComponents() const
Definition: RooAbsArg.cxx:673
RooAbsCacheElement is the abstract base class for objects to be stored in RooAbsCache cache manager o...
RooFIter fwdIterator() const R__SUGGEST_ALTERNATIVE("begin()
One-time forward iterator.
Int_t getSize() const
virtual Bool_t addOwned(RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
TIterator * createIterator(Bool_t dir=kIterForward) const R__SUGGEST_ALTERNATIVE("begin()
TIterator-style iteration over contained elements.
RooAbsData is the common abstract base class for binned and unbinned datasets.
Definition: RooAbsData.h:37
const RooArgSet * nset() const
Definition: RooAbsProxy.h:46
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:53
virtual Double_t defaultErrorLevel() const
Definition: RooAbsReal.h:207
virtual std::list< Double_t > * plotSamplingHint(RooAbsRealLValue &, Double_t, Double_t) const
Definition: RooAbsReal.h:297
virtual std::list< Double_t > * binBoundaries(RooAbsRealLValue &, Double_t, Double_t) const
Definition: RooAbsReal.h:296
Double_t getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition: RooAbsReal.h:81
virtual void enableOffsetting(Bool_t)
Definition: RooAbsReal.h:325
virtual Bool_t setData(RooAbsData &, Bool_t=kTRUE)
Definition: RooAbsReal.h:323
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 ...
Definition: RooAbsReal.cxx:531
virtual Bool_t isBinnedDistribution(const RooArgSet &) const
Definition: RooAbsReal.h:295
Iterator over set.
Definition: RooAddition.h:65
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:26
void printMetaArgs(std::ostream &os) const
virtual std::list< Double_t > * plotSamplingHint(RooAbsRealLValue &, Double_t, Double_t) const
TIterator * _setIter
Definition: RooAddition.h:63
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
RooArgList _ownedList
Definition: RooAddition.h:61
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:62
Double_t evaluate() const
Calculate and return current value of self.
virtual ~RooAddition()
RooAddition()
Empty constructor.
Definition: RooAddition.cxx:53
RooObjCacheManager _cacheMgr
Definition: RooAddition.h:72
virtual std::list< Double_t > * binBoundaries(RooAbsRealLValue &, Double_t, Double_t) const
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:21
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgSet.h:28
virtual Bool_t add(const RooAbsCollection &col, Bool_t silent=kFALSE)
Add a collection of arguments to this collection by calling add() for each element in the source coll...
Definition: RooArgSet.h:88
T * getObj(const RooArgSet *nset, Int_t *sterileIndex=0, const TNamed *isetRangeName=0)
const RooNameSet * nameSet2ByIndex(Int_t index) const
T * getObjByIndex(Int_t index) const
Int_t lastIndex() const
Int_t setObj(const RooArgSet *nset, T *obj, const TNamed *isetRangeName=0)
Class RooChi2Var implements a simple chi^2 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.
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Reimplementation of standard RooArgList::add()
Class RooNLLVar implements a a -log(likelihood) calculation from a dataset and a PDF.
Definition: RooNLLVar.h:26
static const TNamed * ptr(const char *stringPtr)
Return a unique TNamed pointer for given C++ string.
Definition: RooNameReg.cxx:104
RooArgSet * select(const RooArgSet &list) const
Construct a RooArgSet of objects in input 'list' whose names match to those in the internal name list...
Definition: RooNameSet.cxx:187
A RooProduct represents the product of a given set of RooAbsReal objects.
Definition: RooProduct.h:32
Iterator abstract base class.
Definition: TIterator.h:30
virtual void Reset()=0
virtual TObject * Next()=0
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Basic string class.
Definition: TString.h:131
TString & Append(const char *cs)
Definition: TString.h:559
#define I(x, y, z)
@ InputArguments
Definition: RooGlobalFunc.h:58
Definition: first.py:1
static long int sum(long int i)
Definition: Factory.cxx:2258