ROOT  6.06/09
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 //
19 // BEGIN_HTML
20 // RooAddition calculates the sum of a set of RooAbsReal terms, or
21 // when constructed with two sets, it sums the product of the terms
22 // in the two sets. This class does not (yet) do any smart handling of integrals,
23 // i.e. all integrals of the product are handled numerically
24 // END_HTML
25 //
26 
27 
28 #include "RooFit.h"
29 
30 #include "Riostream.h"
31 #include <math.h>
32 #include <memory>
33 #include <list>
34 #include <algorithm>
35 using namespace std ;
36 
37 #include "RooAddition.h"
38 #include "RooProduct.h"
39 #include "RooAbsReal.h"
40 #include "RooErrorHandler.h"
41 #include "RooArgSet.h"
42 #include "RooNameReg.h"
43 #include "RooNLLVar.h"
44 #include "RooChi2Var.h"
45 #include "RooMsgService.h"
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::auto_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::auto_ptr<TIterator> inputIter1( sumSet1.createIterator() );
106  std::auto_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::auto_ptr<RooArgSet> vars( getParameters(RooArgSet()) );
314  std::auto_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::auto_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 
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 
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 
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 
const RooArgSet * nset() const
Definition: RooAbsProxy.h:47
#define coutE(a)
Definition: RooMsgService.h:35
virtual Double_t defaultErrorLevel() const
Return the default error level for MINUIT error analysis If the addition contains one or more RooNLLV...
virtual std::list< Double_t > * binBoundaries(RooAbsRealLValue &, Double_t, Double_t) const
Definition: RooAbsReal.h:278
TIterator * _setIter
Definition: RooAddition.h:63
static void softAbort()
virtual std::list< Double_t > * binBoundaries(RooAbsRealLValue &, Double_t, Double_t) const
virtual void Reset()=0
Bool_t isBinnedDistribution(const RooArgSet &obs) const
virtual Bool_t isBinnedDistribution(const RooArgSet &) const
Definition: RooAbsReal.h:277
const RooNameSet * nameSet2ByIndex(Int_t index) const
virtual Bool_t addOwned(RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
#define coutI(a)
Definition: RooMsgService.h:32
void printMetaArgs(std::ostream &os) const
RooFIter fwdIterator() const
#define assert(cond)
Definition: unittest.h:542
Int_t getAnalyticalIntegral(RooArgSet &allVars, RooArgSet &numVars, const char *rangeName=0) const
Interface function getAnalyticalIntergral advertises the analytical integrals that are supported...
virtual RooArgList containedArgs(Action)
Return list of all RooAbsArgs in cache element.
Int_t lastIndex() const
Basic string class.
Definition: TString.h:137
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
STL namespace.
Iterator abstract base class.
Definition: TIterator.h:32
T * getObj(const RooArgSet *nset, Int_t *sterileIndex=0, const TNamed *isetRangeName=0)
std::map< std::string, std::string >::const_iterator iter
Definition: TAlienJob.cxx:54
TIterator * createIterator(Bool_t dir=kIterForward) const
TString & Append(const char *cs)
Definition: TString.h:492
Double_t analyticalIntegral(Int_t code, const char *rangeName=0) const
Calculate integral internally from appropriate integral cache.
friend class RooArgSet
Definition: RooAbsArg.h:469
Double_t getVal(const RooArgSet *set=0) const
Definition: RooAbsReal.h:64
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
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:559
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
Double_t evaluate() const
Calculate and return current value of self.
virtual Double_t defaultErrorLevel() const
Definition: RooAbsReal.h:189
static const TNamed * ptr(const char *stringPtr)
Return a unique TNamed pointer for given C++ string.
Definition: RooNameReg.cxx:124
RooObjCacheManager _cacheMgr
Definition: RooAddition.h:72
virtual void enableOffsetting(Bool_t)
ClassImp(RooAddition)
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
virtual std::list< Double_t > * plotSamplingHint(RooAbsRealLValue &, Double_t, Double_t) const
Definition: RooAbsReal.h:279
RooAbsArg * next()
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
static RooMathCoreReg dummy
double func(double *x, double *p)
Definition: stressTF1.cxx:213
virtual std::list< Double_t > * plotSamplingHint(RooAbsRealLValue &, Double_t, Double_t) const
RooArgSet * getComponents() const
Definition: RooAbsArg.cxx:687
#define name(a, b)
Definition: linkTestLib0.cpp:5
T * getObjByIndex(Int_t index) const
virtual TObject * Next()=0
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:743
virtual ~RooAddition()
double result[121]
Int_t setObj(const RooArgSet *nset, T *obj, const TNamed *isetRangeName=0)
Int_t getSize() const
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)
const Bool_t kTRUE
Definition: Rtypes.h:91
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:188
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add element to non-owning set.
Definition: RooArgSet.cxx:448
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:503