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