Logo ROOT   6.16/01
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 RooFIter setIter = _set.fwdIterator() ;
181 RooAbsReal* comp ;
182 while((comp=(RooAbsReal*)setIter.next())) {
183 Double_t tmp = comp->getVal(nset) ;
184// cout << tmp << " " ;
185 sum += tmp ;
186 }
187// cout << " = " << sum << endl ;
188 return sum ;
189}
190
191
192////////////////////////////////////////////////////////////////////////////////
193/// Return the default error level for MINUIT error analysis
194/// If the addition contains one or more RooNLLVars and
195/// no RooChi2Vars, return the defaultErrorLevel() of
196/// RooNLLVar. If the addition contains one ore more RooChi2Vars
197/// and no RooNLLVars, return the defaultErrorLevel() of
198/// RooChi2Var. If the addition contains neither or both
199/// issue a warning message and return a value of 1
200
202{
203 RooAbsReal* nllArg(0) ;
204 RooAbsReal* chi2Arg(0) ;
205
206 RooAbsArg* arg ;
207
208 RooArgSet* comps = getComponents() ;
209 TIterator* iter = comps->createIterator() ;
210 while((arg=(RooAbsArg*)iter->Next())) {
211 if (dynamic_cast<RooNLLVar*>(arg)) {
212 nllArg = (RooAbsReal*)arg ;
213 }
214 if (dynamic_cast<RooChi2Var*>(arg)) {
215 chi2Arg = (RooAbsReal*)arg ;
216 }
217 }
218 delete iter ;
219 delete comps ;
220
221 if (nllArg && !chi2Arg) {
222 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName()
223 << ") Summation contains a RooNLLVar, using its error level" << endl ;
224 return nllArg->defaultErrorLevel() ;
225 } else if (chi2Arg && !nllArg) {
226 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName()
227 << ") Summation contains a RooChi2Var, using its error level" << endl ;
228 return chi2Arg->defaultErrorLevel() ;
229 } else if (!nllArg && !chi2Arg) {
230 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName() << ") WARNING: "
231 << "Summation contains neither RooNLLVar nor RooChi2Var server, using default level of 1.0" << endl ;
232 } else {
233 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName() << ") WARNING: "
234 << "Summation contains BOTH RooNLLVar and RooChi2Var server, using default level of 1.0" << endl ;
235 }
236
237 return 1.0 ;
238}
239
240
241////////////////////////////////////////////////////////////////////////////////
242
244{
245 _setIter->Reset() ;
246
247 RooAbsReal* arg;
248 while((arg=(RooAbsReal*)_setIter->Next())) {
249 arg->enableOffsetting(flag) ;
250 }
251}
252
253
254
255////////////////////////////////////////////////////////////////////////////////
256
258{
259 _setIter->Reset() ;
260
261 RooAbsReal* arg;
262 while((arg=(RooAbsReal*)_setIter->Next())) {
263 arg->setData(data,cloneData) ;
264 }
265 return kTRUE ;
266}
267
268
269
270////////////////////////////////////////////////////////////////////////////////
271
272void RooAddition::printMetaArgs(ostream& os) const
273{
274 _setIter->Reset() ;
275
277 RooAbsArg* arg;
278 while((arg=(RooAbsArg*)_setIter->Next())) {
279 if (!first) { os << " + " ;
280 } else { first = kFALSE ;
281 }
282 os << arg->GetName() ;
283 }
284 os << " " ;
285}
286
287////////////////////////////////////////////////////////////////////////////////
288
289Int_t RooAddition::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName) const
290{
291 // we always do things ourselves -- actually, always delegate further down the line ;-)
292 analVars.add(allVars);
293
294 // check if we already have integrals for this combination of factors
295 Int_t sterileIndex(-1);
296 CacheElem* cache = (CacheElem*) _cacheMgr.getObj(&analVars,&analVars,&sterileIndex,RooNameReg::ptr(rangeName));
297 if (cache!=0) {
298 Int_t code = _cacheMgr.lastIndex();
299 return code+1;
300 }
301
302 // we don't, so we make it right here....
303 cache = new CacheElem;
304 _setIter->Reset();
305 RooAbsReal *arg(0);
306 while( (arg=(RooAbsReal*)_setIter->Next())!=0 ) { // checked in c'tor that this will work...
307 RooAbsReal *I = arg->createIntegral(analVars,rangeName);
308 cache->_I.addOwned(*I);
309 }
310
311 Int_t code = _cacheMgr.setObj(&analVars,&analVars,(RooAbsCacheElement*)cache,RooNameReg::ptr(rangeName));
312 return 1+code;
313}
314
315////////////////////////////////////////////////////////////////////////////////
316/// Calculate integral internally from appropriate integral cache
317
318Double_t RooAddition::analyticalIntegral(Int_t code, const char* rangeName) const
319{
320 // note: rangeName implicit encoded in code: see _cacheMgr.setObj in getPartIntList...
321 CacheElem *cache = (CacheElem*) _cacheMgr.getObjByIndex(code-1);
322 if (cache==0) {
323 // cache got sterilized, trigger repopulation of this slot, then try again...
324 std::unique_ptr<RooArgSet> vars( getParameters(RooArgSet()) );
325 std::unique_ptr<RooArgSet> iset( _cacheMgr.nameSet2ByIndex(code-1)->select(*vars) );
327 Int_t code2 = getAnalyticalIntegral(*iset,dummy,rangeName);
328 assert(code==code2); // must have revived the right (sterilized) slot...
329 return analyticalIntegral(code2,rangeName);
330 }
331 assert(cache!=0);
332
333 // loop over cache, and sum...
334 std::unique_ptr<TIterator> iter( cache->_I.createIterator() );
335 RooAbsReal *I;
336 double result(0);
337 while ( ( I=(RooAbsReal*)iter->Next() ) != 0 ) result += I->getVal();
338 return result;
339
340}
341
342
343
344////////////////////////////////////////////////////////////////////////////////
345
346std::list<Double_t>* RooAddition::binBoundaries(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const
347{
348 std::list<Double_t>* sumBinB = 0 ;
349 Bool_t needClean(kFALSE) ;
350
351 RooFIter iter = _set.fwdIterator() ;
352 RooAbsReal* func ;
353 // Loop over components pdf
354 while((func=(RooAbsReal*)iter.next())) {
355
356 std::list<Double_t>* funcBinB = func->binBoundaries(obs,xlo,xhi) ;
357
358 // Process hint
359 if (funcBinB) {
360 if (!sumBinB) {
361 // If this is the first hint, then just save it
362 sumBinB = funcBinB ;
363 } else {
364
365 std::list<Double_t>* newSumBinB = new std::list<Double_t>(sumBinB->size()+funcBinB->size()) ;
366
367 // Merge hints into temporary array
368 merge(funcBinB->begin(),funcBinB->end(),sumBinB->begin(),sumBinB->end(),newSumBinB->begin()) ;
369
370 // Copy merged array without duplicates to new sumBinBArrau
371 delete sumBinB ;
372 delete funcBinB ;
373 sumBinB = newSumBinB ;
374 needClean = kTRUE ;
375 }
376 }
377 }
378
379 // Remove consecutive duplicates
380 if (needClean) {
381 std::list<Double_t>::iterator new_end = unique(sumBinB->begin(),sumBinB->end()) ;
382 sumBinB->erase(new_end,sumBinB->end()) ;
383 }
384
385 return sumBinB ;
386}
387
388
389//_____________________________________________________________________________B
391{
392 // If all components that depend on obs are binned that so is the product
393
394 RooFIter iter = _set.fwdIterator() ;
395 RooAbsReal* func ;
396 while((func=(RooAbsReal*)iter.next())) {
397 if (func->dependsOn(obs) && !func->isBinnedDistribution(obs)) {
398 return kFALSE ;
399 }
400 }
401
402 return kTRUE ;
403}
404
405
406
407
408////////////////////////////////////////////////////////////////////////////////
409
410std::list<Double_t>* RooAddition::plotSamplingHint(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const
411{
412 std::list<Double_t>* sumHint = 0 ;
413 Bool_t needClean(kFALSE) ;
414
415 RooFIter iter = _set.fwdIterator() ;
416 RooAbsReal* func ;
417 // Loop over components pdf
418 while((func=(RooAbsReal*)iter.next())) {
419
420 std::list<Double_t>* funcHint = func->plotSamplingHint(obs,xlo,xhi) ;
421
422 // Process hint
423 if (funcHint) {
424 if (!sumHint) {
425
426 // If this is the first hint, then just save it
427 sumHint = funcHint ;
428
429 } else {
430
431 std::list<Double_t>* newSumHint = new std::list<Double_t>(sumHint->size()+funcHint->size()) ;
432
433 // Merge hints into temporary array
434 merge(funcHint->begin(),funcHint->end(),sumHint->begin(),sumHint->end(),newSumHint->begin()) ;
435
436 // Copy merged array without duplicates to new sumHintArrau
437 delete sumHint ;
438 sumHint = newSumHint ;
439 needClean = kTRUE ;
440 }
441 }
442 }
443
444 // Remove consecutive duplicates
445 if (needClean) {
446 std::list<Double_t>::iterator new_end = unique(sumHint->begin(),sumHint->end()) ;
447 sumHint->erase(new_end,sumHint->end()) ;
448 }
449
450 return sumHint ;
451}
452
453
454
455////////////////////////////////////////////////////////////////////////////////
456/// Return list of all RooAbsArgs in cache element
457
459{
460 RooArgList ret(_I) ;
461 return ret ;
462}
463
465{
466 // Destructor
467}
468
469
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:363
RooAbsArg is the common abstract base class for objects that represent a value (of arbitrary type) an...
Definition: RooAbsArg.h:66
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:736
friend class RooArgSet
Definition: RooAbsArg.h:471
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:533
RooArgSet * getComponents() const
Definition: RooAbsArg.cxx:680
RooAbsCacheElement is the abstract base class for objects to be stored in RooAbsCache cache manager o...
Int_t getSize() const
virtual Bool_t addOwned(RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
RooFIter fwdIterator() const
TIterator * createIterator(Bool_t dir=kIterForward) const
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:190
virtual std::list< Double_t > * plotSamplingHint(RooAbsRealLValue &, Double_t, Double_t) const
Definition: RooAbsReal.h:280
virtual std::list< Double_t > * binBoundaries(RooAbsRealLValue &, Double_t, Double_t) const
Definition: RooAbsReal.h:279
virtual void enableOffsetting(Bool_t)
Definition: RooAbsReal.h:308
virtual Bool_t setData(RooAbsData &, Bool_t=kTRUE)
Definition: RooAbsReal.h:306
Double_t getVal(const RooArgSet *set=0) const
Evaluate object. Returns either cached value or triggers a recalculation.
Definition: RooAbsReal.h:64
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:502
virtual Bool_t isBinnedDistribution(const RooArgSet &) const
Definition: RooAbsReal.h:278
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...
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)
static void softAbort()
RooAbsArg * next()
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:125
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
RooProduct a RooAbsReal implementation that represent the product of a given set of other RooAbsReal ...
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
#define I(x, y, z)
@ InputArguments
Definition: RooGlobalFunc.h:58
Definition: first.py:1
STL namespace.
static long int sum(long int i)
Definition: Factory.cxx:2258