Logo ROOT  
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.
25**/
26
27
28#include "Riostream.h"
29#include "RooAddition.h"
30#include "RooRealSumFunc.h"
31#include "RooRealSumPdf.h"
32#include "RooProduct.h"
33#include "RooErrorHandler.h"
34#include "RooArgSet.h"
35#include "RooNameReg.h"
36#include "RooNLLVar.h"
37#include "RooNLLVarNew.h"
38#include "RooChi2Var.h"
39#include "RooMsgService.h"
40#include "RooBatchCompute.h"
41
42#include <algorithm>
43#include <cmath>
44
46
47
48////////////////////////////////////////////////////////////////////////////////
49/// Constructor with a single set consisting of RooAbsReal.
50/// \param[in] name Name of the PDF
51/// \param[in] title Title
52/// \param[in] sumSet The value of the function will be the sum of the values in this set
53/// \param[in] takeOwnership If true, the RooAddition object will take ownership of the arguments in `sumSet`
54
55RooAddition::RooAddition(const char* name, const char* title, const RooArgList& sumSet, bool takeOwnership)
56 : RooAbsReal(name, title)
57 , _set("!set","set of components",this)
58 , _cacheMgr(this,10)
59{
60 for (const auto comp : sumSet) {
61 if (!dynamic_cast<RooAbsReal*>(comp)) {
62 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: component " << comp->GetName()
63 << " is not of type RooAbsReal" << std::endl;
65 }
66 _set.add(*comp) ;
67 if (takeOwnership) _ownedList.addOwned(*comp) ;
68 }
69
70}
71
72
73
74////////////////////////////////////////////////////////////////////////////////
75/// Constructor with two sets of RooAbsReals.
76///
77/// The sum of pair-wise products of elements in the sets will be computed:
78/// \f[
79/// A = \sum_i \mathrm{Set1}[i] * \mathrm{Set2}[i]
80/// \f]
81///
82/// \param[in] name Name of the PDF
83/// \param[in] title Title
84/// \param[in] sumSet1 Left-hand element of the pair-wise products
85/// \param[in] sumSet2 Right-hand element of the pair-wise products
86/// \param[in] takeOwnership If true, the RooAddition object will take ownership of the arguments in the `sumSets`
87///
88RooAddition::RooAddition(const char* name, const char* title, const RooArgList& sumSet1, const RooArgList& sumSet2, bool takeOwnership)
89 : RooAbsReal(name, title)
90 , _set("!set","set of components",this)
91 , _cacheMgr(this,10)
92{
93 if (sumSet1.getSize() != sumSet2.getSize()) {
94 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: input lists should be of equal length" << std::endl;
96 }
97
98 for (unsigned int i = 0; i < sumSet1.size(); ++i) {
99 const auto comp1 = &sumSet1[i];
100 const auto comp2 = &sumSet2[i];
101
102 if (!dynamic_cast<RooAbsReal*>(comp1)) {
103 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: component " << comp1->GetName()
104 << " in first list is not of type RooAbsReal" << std::endl;
106 }
107
108 if (!dynamic_cast<RooAbsReal*>(comp2)) {
109 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: component " << comp2->GetName()
110 << " in first list is not of type RooAbsReal" << std::endl;
112 }
113 // TODO: add flag to RooProduct c'tor to make it assume ownership...
114 TString _name(name);
115 _name.Append( "_[");
116 _name.Append(comp1->GetName());
117 _name.Append( "_x_");
118 _name.Append(comp2->GetName());
119 _name.Append( "]");
120 RooProduct *prod = new RooProduct( _name, _name , RooArgSet(*comp1, *comp2) /*, takeOwnership */ ) ;
121 _set.add(*prod);
122 _ownedList.addOwned(*prod) ;
123 if (takeOwnership) {
124 _ownedList.addOwned(*comp1) ;
125 _ownedList.addOwned(*comp2) ;
126 }
127 }
128}
129
130
131
132////////////////////////////////////////////////////////////////////////////////
133/// Copy constructor
134
135RooAddition::RooAddition(const RooAddition& other, const char* name)
136 : RooAbsReal(other, name)
137 , _set("!set",this,other._set)
138 , _cacheMgr(other._cacheMgr,this)
139{
140 // Member _ownedList is intentionally not copy-constructed -- ownership is not transferred
141}
142
143////////////////////////////////////////////////////////////////////////////////
144/// Calculate and return current value of self
145
147{
148 double sum(0);
149 const RooArgSet* nset = _set.nset() ;
150
151 for (auto* comp : static_range_cast<RooAbsReal*>(_set)) {
152 const double tmp = comp->getVal(nset);
153 sum += tmp ;
154 }
155 return sum ;
156}
157
158
159////////////////////////////////////////////////////////////////////////////////
160/// Compute addition of PDFs in batches.
161void RooAddition::computeBatch(cudaStream_t* stream, double* output, size_t nEvents, RooFit::Detail::DataMap const& dataMap) const
162{
165 pdfs.reserve(_set.size());
166 coefs.reserve(_set.size());
167 for (const auto arg : _set)
168 {
169 pdfs.push_back(dataMap.at(arg));
170 coefs.push_back(1.0);
171 }
173 dispatch->compute(stream, RooBatchCompute::AddPdf, output, nEvents, pdfs, coefs);
174}
175
176
177////////////////////////////////////////////////////////////////////////////////
178/// Return the default error level for MINUIT error analysis
179/// If the addition contains one or more RooNLLVars and
180/// no RooChi2Vars, return the defaultErrorLevel() of
181/// RooNLLVar. If the addition contains one ore more RooChi2Vars
182/// and no RooNLLVars, return the defaultErrorLevel() of
183/// RooChi2Var. If the addition contains neither or both
184/// issue a warning message and return a value of 1
185
187{
188 RooAbsReal* nllArg(0) ;
189 RooAbsReal* chi2Arg(0) ;
190
191 std::unique_ptr<RooArgSet> comps{getComponents()};
192 for(RooAbsArg * arg : *comps) {
193 if (dynamic_cast<RooNLLVar*>(arg) || dynamic_cast<ROOT::Experimental::RooNLLVarNew*>(arg)) {
194 nllArg = (RooAbsReal*)arg ;
195 }
196 if (dynamic_cast<RooChi2Var*>(arg)) {
197 chi2Arg = (RooAbsReal*)arg ;
198 }
199 }
200
201 if (nllArg && !chi2Arg) {
202 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName()
203 << ") Summation contains a RooNLLVar, using its error level" << std::endl;
204 return nllArg->defaultErrorLevel() ;
205 } else if (chi2Arg && !nllArg) {
206 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName()
207 << ") Summation contains a RooChi2Var, using its error level" << std::endl;
208 return chi2Arg->defaultErrorLevel() ;
209 } else if (!nllArg && !chi2Arg) {
210 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName() << ") WARNING: "
211 << "Summation contains neither RooNLLVar nor RooChi2Var server, using default level of 1.0" << std::endl;
212 } else {
213 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName() << ") WARNING: "
214 << "Summation contains BOTH RooNLLVar and RooChi2Var server, using default level of 1.0" << std::endl;
215 }
216
217 return 1.0 ;
218}
219
220
221////////////////////////////////////////////////////////////////////////////////
222
224{
225 for (auto arg : _set) {
226 static_cast<RooAbsReal*>(arg)->enableOffsetting(flag) ;
227 }
228}
229
230
231
232////////////////////////////////////////////////////////////////////////////////
233
235{
236 for (const auto arg : _set) {
237 static_cast<RooAbsReal*>(arg)->setData(data,cloneData) ;
238 }
239 return true ;
240}
241
242
243
244////////////////////////////////////////////////////////////////////////////////
245
246void RooAddition::printMetaArgs(std::ostream& os) const
247{
248 // We can use the implementation of RooRealSumPdf with an empy coefficient list.
249 static const RooArgList coefs{};
251}
252
253////////////////////////////////////////////////////////////////////////////////
254
255Int_t RooAddition::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName) const
256{
257 // we always do things ourselves -- actually, always delegate further down the line ;-)
258 analVars.add(allVars);
259
260 // check if we already have integrals for this combination of factors
261 Int_t sterileIndex(-1);
262 CacheElem* cache = (CacheElem*) _cacheMgr.getObj(&analVars,&analVars,&sterileIndex,RooNameReg::ptr(rangeName));
263 if (cache!=0) {
264 Int_t code = _cacheMgr.lastIndex();
265 return code+1;
266 }
267
268 // we don't, so we make it right here....
269 cache = new CacheElem;
270 for (const auto arg : _set) {// checked in c'tor that this will work...
271 RooAbsReal *I = static_cast<const RooAbsReal*>(arg)->createIntegral(analVars,rangeName);
272 cache->_I.addOwned(*I);
273 }
274
275 Int_t code = _cacheMgr.setObj(&analVars,&analVars,(RooAbsCacheElement*)cache,RooNameReg::ptr(rangeName));
276 return 1+code;
277}
278
279////////////////////////////////////////////////////////////////////////////////
280/// Calculate integral internally from appropriate integral cache
281
282double RooAddition::analyticalIntegral(Int_t code, const char* rangeName) const
283{
284 // note: rangeName implicit encoded in code: see _cacheMgr.setObj in getPartIntList...
285 CacheElem *cache = (CacheElem*) _cacheMgr.getObjByIndex(code-1);
286 if (cache==0) {
287 // cache got sterilized, trigger repopulation of this slot, then try again...
288 std::unique_ptr<RooArgSet> vars( getParameters(RooArgSet()) );
289 RooArgSet iset = _cacheMgr.selectFromSet2(*vars, code-1);
290 RooArgSet dummy;
291 Int_t code2 = getAnalyticalIntegral(iset,dummy,rangeName);
292 assert(code==code2); // must have revived the right (sterilized) slot...
293 return analyticalIntegral(code2,rangeName);
294 }
295 assert(cache!=0);
296
297 // loop over cache, and sum...
298 double result(0);
299 for (auto I : cache->_I) {
300 result += static_cast<const RooAbsReal*>(I)->getVal();
301 }
302 return result;
303
304}
305
306
307////////////////////////////////////////////////////////////////////////////////
308
309std::list<double>* RooAddition::binBoundaries(RooAbsRealLValue& obs, double xlo, double xhi) const
310{
311 return RooRealSumPdf::binBoundaries(_set, obs, xlo, xhi);
312}
313
314
316{
318}
319
320
321////////////////////////////////////////////////////////////////////////////////
322
323std::list<double>* RooAddition::plotSamplingHint(RooAbsRealLValue& obs, double xlo, double xhi) const
324{
325 return RooRealSumPdf::plotSamplingHint(_set, obs, xlo, xhi);
326}
#define coutI(a)
Definition: RooMsgService.h:34
#define coutE(a)
Definition: RooMsgService.h:37
#define ClassImp(name)
Definition: Rtypes.h:375
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
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:71
RooArgSet * getComponents() const
Create a RooArgSet with all components (branch nodes) of the expression tree headed by this object.
Definition: RooAbsArg.cxx:754
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...
Definition: RooAbsArg.cxx:541
RooAbsCacheElement is the abstract base class for objects to be stored in RooAbsCache cache manager o...
Int_t getSize() const
Return the number of elements in the collection.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
virtual bool addOwned(RooAbsArg &var, bool silent=false)
Add an argument and transfer the ownership to the collection.
RooAbsData is the common abstract base class for binned and unbinned datasets.
Definition: RooAbsData.h:62
const RooArgSet * nset() const
Definition: RooAbsProxy.h:48
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:62
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition: RooAbsReal.h:91
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:526
virtual double defaultErrorLevel() const
Definition: RooAbsReal.h:253
RooAddition calculates the sum of a set of RooAbsReal terms, or when constructed with two sets,...
Definition: RooAddition.h:27
RooArgList _ownedList
List of owned components.
Definition: RooAddition.h:63
Int_t getAnalyticalIntegral(RooArgSet &allVars, RooArgSet &numVars, const char *rangeName=nullptr) const override
Interface function getAnalyticalIntergral advertises the analytical integrals that are supported.
void computeBatch(cudaStream_t *, double *output, size_t nEvents, RooFit::Detail::DataMap const &) const override
Compute addition of PDFs in batches.
std::list< double > * binBoundaries(RooAbsRealLValue &, double, double) const override
Retrieve bin boundaries if this distribution is binned in obs.
RooListProxy _set
set of terms to be summed
Definition: RooAddition.h:64
void printMetaArgs(std::ostream &os) const override
bool setData(RooAbsData &data, bool cloneData=true) override
double analyticalIntegral(Int_t code, const char *rangeName=nullptr) const override
Calculate integral internally from appropriate integral cache.
RooObjCacheManager _cacheMgr
! The cache manager
Definition: RooAddition.h:72
double defaultErrorLevel() const override
Return the default error level for MINUIT error analysis If the addition contains one or more RooNLLV...
double evaluate() const override
Calculate and return current value of self.
std::list< double > * plotSamplingHint(RooAbsRealLValue &, double, double) const override
Interface for returning an optional hint for initial sampling points when constructing a curve projec...
bool isBinnedDistribution(const RooArgSet &obs) const override
Tests if the distribution is binned. Unless overridden by derived classes, this always returns false.
void enableOffsetting(bool) override
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:56
virtual void compute(cudaStream_t *, Computer, RestrictArr, size_t, const VarVector &, const ArgVector &={})=0
Int_t setObj(const RooArgSet *nset, T *obj, const TNamed *isetRangeName=nullptr)
Setter function without integration set.
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
Return index of slot used in last get or set operation.
T * getObj(const RooArgSet *nset, Int_t *sterileIndex=nullptr, const TNamed *isetRangeName=nullptr)
Getter function without integration set.
RooChi2Var implements a simple calculation from a binned dataset and a PDF.
Definition: RooChi2Var.h:25
bool add(const RooAbsArg &var, bool valueServer, bool shapeServer, bool silent)
Overloaded RooCollection_t::add() method insert object into set and registers object as server to own...
static void softAbort()
Soft abort function that interrupts macro execution but doesn't kill ROOT.
auto & at(RooAbsArg const *arg, RooAbsArg const *=nullptr)
Definition: DataMap.h:88
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.
Definition: RooNameReg.cxx:81
A RooProduct represents the product of a given set of RooAbsReal objects.
Definition: RooProduct.h:29
std::list< double > * plotSamplingHint(RooAbsRealLValue &, double, double) const override
Interface for returning an optional hint for initial sampling points when constructing a curve projec...
std::list< double > * binBoundaries(RooAbsRealLValue &, double, double) const override
Retrieve bin boundaries if this distribution is binned in obs.
void printMetaArgs(std::ostream &os) const override
Customized printing of arguments of a RooRealSumPdf to more intuitively reflect the contents of the p...
bool isBinnedDistribution(const RooArgSet &obs) const override
Check if all components that depend on obs are binned.
const char * GetName() const override
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
@ InputArguments
Definition: RooGlobalFunc.h:64
static uint64_t sum(uint64_t i)
Definition: Factory.cxx:2345
static void output()