Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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 "RooNLLVarNew.h"
37#include "RooMsgService.h"
38#include "RooBatchCompute.h"
39
40#ifdef ROOFIT_LEGACY_EVAL_BACKEND
41#include "RooNLLVar.h"
42#include "RooChi2Var.h"
43#endif
44
45#include <algorithm>
46#include <cmath>
47
49
50
51////////////////////////////////////////////////////////////////////////////////
52/// Constructor with a single set consisting of RooAbsReal.
53/// \param[in] name Name of the PDF
54/// \param[in] title Title
55/// \param[in] sumSet The value of the function will be the sum of the values in this set
56/// \param[in] takeOwnership If true, the RooAddition object will take ownership of the arguments in `sumSet`
57
58RooAddition::RooAddition(const char* name, const char* title, const RooArgList& sumSet
59#ifndef ROOFIT_MEMORY_SAFE_INTERFACES
60 , bool takeOwnership
61#endif
62 )
63 : RooAbsReal(name, title)
64 , _set("!set","set of components",this)
65 , _cacheMgr(this,10)
66{
67 for (RooAbsArg *comp : sumSet) {
68 if (!dynamic_cast<RooAbsReal*>(comp)) {
69 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: component " << comp->GetName()
70 << " is not of type RooAbsReal" << std::endl;
72 }
73 _set.add(*comp) ;
74#ifndef ROOFIT_MEMORY_SAFE_INTERFACES
75 if (takeOwnership) _ownedList.addOwned(std::unique_ptr<RooAbsArg>{comp});
76#endif
77 }
78
79}
80
81
82
83////////////////////////////////////////////////////////////////////////////////
84/// Constructor with two sets of RooAbsReals.
85///
86/// The sum of pair-wise products of elements in the sets will be computed:
87/// \f[
88/// A = \sum_i \mathrm{Set1}[i] * \mathrm{Set2}[i]
89/// \f]
90///
91/// \param[in] name Name of the PDF
92/// \param[in] title Title
93/// \param[in] sumSet1 Left-hand element of the pair-wise products
94/// \param[in] sumSet2 Right-hand element of the pair-wise products
95/// \param[in] takeOwnership If true, the RooAddition object will take ownership of the arguments in the `sumSets`
96///
97RooAddition::RooAddition(const char* name, const char* title, const RooArgList& sumSet1, const RooArgList& sumSet2
98#ifndef ROOFIT_MEMORY_SAFE_INTERFACES
99 , bool takeOwnership
100#endif
101 )
102 : RooAbsReal(name, title)
103 , _set("!set","set of components",this)
104 , _cacheMgr(this,10)
105{
106 if (sumSet1.getSize() != sumSet2.getSize()) {
107 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: input lists should be of equal length" << std::endl;
109 }
110
111 for (unsigned int i = 0; i < sumSet1.size(); ++i) {
112 const auto comp1 = &sumSet1[i];
113 const auto comp2 = &sumSet2[i];
114
115 if (!dynamic_cast<RooAbsReal*>(comp1)) {
116 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: component " << comp1->GetName()
117 << " in first list is not of type RooAbsReal" << std::endl;
119 }
120
121 if (!dynamic_cast<RooAbsReal*>(comp2)) {
122 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: component " << comp2->GetName()
123 << " in first list is not of type RooAbsReal" << std::endl;
125 }
126 TString _name(name);
127 _name.Append( "_[");
128 _name.Append(comp1->GetName());
129 _name.Append( "_x_");
130 _name.Append(comp2->GetName());
131 _name.Append( "]");
132 auto prod = std::make_unique<RooProduct>( _name, _name , RooArgSet(*comp1, *comp2));
133 _set.add(*prod);
134 _ownedList.addOwned(std::move(prod));
135#ifndef ROOFIT_MEMORY_SAFE_INTERFACES
136 if (takeOwnership) {
137 _ownedList.addOwned(std::unique_ptr<RooAbsArg>{comp1});
138 _ownedList.addOwned(std::unique_ptr<RooAbsArg>{comp2});
139 }
140#endif
141 }
142}
143
144
145
146////////////////////////////////////////////////////////////////////////////////
147/// Copy constructor
148
149RooAddition::RooAddition(const RooAddition& other, const char* name)
150 : RooAbsReal(other, name)
151 , _set("!set",this,other._set)
152 , _cacheMgr(other._cacheMgr,this)
153{
154 // Member _ownedList is intentionally not copy-constructed -- ownership is not transferred
155}
156
157////////////////////////////////////////////////////////////////////////////////
158/// Calculate and return current value of self
159
161{
162 double sum(0);
163 const RooArgSet* nset = _set.nset() ;
164
165 for (auto* comp : static_range_cast<RooAbsReal*>(_set)) {
166 const double tmp = comp->getVal(nset);
167 sum += tmp ;
168 }
169 return sum ;
170}
171
172
173////////////////////////////////////////////////////////////////////////////////
174/// Compute addition of PDFs in batches.
175void RooAddition::computeBatch(double* output, size_t nEvents, RooFit::Detail::DataMap const& dataMap) const
176{
179 pdfs.reserve(_set.size());
180 coefs.reserve(_set.size());
181 for (const auto arg : _set)
182 {
183 pdfs.push_back(dataMap.at(arg));
184 coefs.push_back(1.0);
185 }
186 RooBatchCompute::compute(dataMap.config(this), RooBatchCompute::AddPdf, output, nEvents, pdfs, coefs);
187}
188
189////////////////////////////////////////////////////////////////////////////////
190
192{
193 // If the number of elements to sum is less than 3, just build a sum expression.
194 // else build a loop to sum over the values.
195 unsigned int eleSize = _set.size();
196 std::string result;
197 if (eleSize > 3) {
198 std::string className = GetName();
199 std::string varName = "elements" + className;
200 std::string sumName = "sum" + className;
201 std::string code = "";
202 std::string decl = "double " + varName + "[" + std::to_string(eleSize) + "]{";
203 int idx = 0;
204 for (RooAbsArg *it : _set) {
205 decl += ctx.getResult(*it) + ",";
206 ctx.addResult(it, varName + "[" + std::to_string(idx) + "]");
207 idx++;
208 }
209 decl.back() = '}';
210 code += decl + ";\n";
211
212 ctx.addToGlobalScope("double " + sumName + " = 0;\n");
213 std::string iterator = "i_" + className;
214 code += "for(int " + iterator + " = 0; " + iterator + " < " + std::to_string(eleSize) + "; " + iterator +
215 "++) {\n" + sumName + " += " + varName + "[" + iterator + "];\n}\n";
216 result = sumName;
217 ctx.addResult(this, result);
218
219 ctx.addToCodeBody(this, code);
220 }
221
222 result = "(";
223 for (RooAbsArg *it : _set) {
224 result += ctx.getResult(*it) + '+';
225 }
226 result.back() = ')';
227 ctx.addResult(this, result);
228}
229
230////////////////////////////////////////////////////////////////////////////////
231/// Return the default error level for MINUIT error analysis
232/// If the addition contains one or more RooNLLVars and
233/// no RooChi2Vars, return the defaultErrorLevel() of
234/// RooNLLVar. If the addition contains one ore more RooChi2Vars
235/// and no RooNLLVars, return the defaultErrorLevel() of
236/// RooChi2Var. If the addition contains neither or both
237/// issue a warning message and return a value of 1
238
240{
241 RooAbsReal* nllArg(nullptr) ;
242 RooAbsReal* chi2Arg(nullptr) ;
243
244 std::unique_ptr<RooArgSet> comps{getComponents()};
245 for(RooAbsArg * arg : *comps) {
246 if (dynamic_cast<RooNLLVarNew*>(arg)) {
247 nllArg = (RooAbsReal*)arg ;
248 }
249#ifdef ROOFIT_LEGACY_EVAL_BACKEND
250 if (dynamic_cast<RooNLLVar*>(arg)) {
251 nllArg = (RooAbsReal*)arg ;
252 }
253 if (dynamic_cast<RooChi2Var*>(arg)) {
254 chi2Arg = (RooAbsReal*)arg ;
255 }
256#endif
257 }
258
259 if (nllArg && !chi2Arg) {
260 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName()
261 << ") Summation contains a RooNLLVar, using its error level" << std::endl;
262 return nllArg->defaultErrorLevel() ;
263 } else if (chi2Arg && !nllArg) {
264 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName()
265 << ") Summation contains a RooChi2Var, using its error level" << std::endl;
266 return chi2Arg->defaultErrorLevel() ;
267 } else if (!nllArg && !chi2Arg) {
268 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName() << ") WARNING: "
269 << "Summation contains neither RooNLLVar nor RooChi2Var server, using default level of 1.0" << std::endl;
270 } else {
271 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName() << ") WARNING: "
272 << "Summation contains BOTH RooNLLVar and RooChi2Var server, using default level of 1.0" << std::endl;
273 }
274
275 return 1.0 ;
276}
277
278
279
280////////////////////////////////////////////////////////////////////////////////
281
283{
284 for (const auto arg : _set) {
285 static_cast<RooAbsReal*>(arg)->setData(data,cloneData) ;
286 }
287 return true ;
288}
289
290
291
292////////////////////////////////////////////////////////////////////////////////
293
294void RooAddition::printMetaArgs(std::ostream& os) const
295{
296 // We can use the implementation of RooRealSumPdf with an empty coefficient list.
297 static const RooArgList coefs{};
299}
300
301////////////////////////////////////////////////////////////////////////////////
302
303Int_t RooAddition::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName) const
304{
305 // we always do things ourselves -- actually, always delegate further down the line ;-)
306 analVars.add(allVars);
307
308 // check if we already have integrals for this combination of factors
309 Int_t sterileIndex(-1);
310 CacheElem* cache = (CacheElem*) _cacheMgr.getObj(&analVars,&analVars,&sterileIndex,RooNameReg::ptr(rangeName));
311 if (cache!=nullptr) {
312 Int_t code = _cacheMgr.lastIndex();
313 return code+1;
314 }
315
316 // we don't, so we make it right here....
317 cache = new CacheElem;
318 for (auto *arg : static_range_cast<RooAbsReal const*>(_set)) {// checked in c'tor that this will work...
319 cache->_I.addOwned(std::unique_ptr<RooAbsReal>{arg->createIntegral(analVars,rangeName)});
320 }
321
322 Int_t code = _cacheMgr.setObj(&analVars,&analVars,(RooAbsCacheElement*)cache,RooNameReg::ptr(rangeName));
323 return 1+code;
324}
325
326////////////////////////////////////////////////////////////////////////////////
327/// Calculate integral internally from appropriate integral cache
328
329double RooAddition::analyticalIntegral(Int_t code, const char* rangeName) const
330{
331 // note: rangeName implicit encoded in code: see _cacheMgr.setObj in getPartIntList...
332 CacheElem *cache = (CacheElem*) _cacheMgr.getObjByIndex(code-1);
333 if (cache==nullptr) {
334 // cache got sterilized, trigger repopulation of this slot, then try again...
335 std::unique_ptr<RooArgSet> vars( getParameters(RooArgSet()) );
336 RooArgSet iset = _cacheMgr.selectFromSet2(*vars, code-1);
337 RooArgSet dummy;
338 Int_t code2 = getAnalyticalIntegral(iset,dummy,rangeName);
339 assert(code==code2); // must have revived the right (sterilized) slot...
340 return analyticalIntegral(code2,rangeName);
341 }
342 assert(cache!=nullptr);
343
344 // loop over cache, and sum...
345 double result(0);
346 for (auto I : cache->_I) {
347 result += static_cast<const RooAbsReal*>(I)->getVal();
348 }
349 return result;
350
351}
352
353
354////////////////////////////////////////////////////////////////////////////////
355
356std::list<double>* RooAddition::binBoundaries(RooAbsRealLValue& obs, double xlo, double xhi) const
357{
358 return RooRealSumPdf::binBoundaries(_set, obs, xlo, xhi);
359}
360
361
363{
365}
366
367
368////////////////////////////////////////////////////////////////////////////////
369
370std::list<double>* RooAddition::plotSamplingHint(RooAbsRealLValue& obs, double xlo, double xhi) const
371{
372 return RooRealSumPdf::plotSamplingHint(_set, obs, xlo, xhi);
373}
#define coutI(a)
#define coutE(a)
#define ClassImp(name)
Definition Rtypes.h:377
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
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:79
RooFit::OwningPtr< 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...
RooFit::OwningPtr< RooArgSet > getComponents() const
Create a RooArgSet with all components (branch nodes) of the expression tree headed by this object.
Abstract base class for objects to be stored in RooAbsCache cache manager objects.
Int_t getSize() const
Return the number of elements in the collection.
const char * GetName() const override
Returns name of object.
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.
Abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:57
const RooArgSet * nset() const
Definition RooAbsProxy.h:52
RooAbsRealLValue is the common abstract base class for objects that represent a real value that may a...
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:59
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:103
virtual double defaultErrorLevel() const
Definition RooAbsReal.h:248
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:71
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(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:72
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:80
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 translate(RooFit::Detail::CodeSquashContext &ctx) const override
This function defines a translation for each RooAbsReal based object that can be used to express the ...
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:55
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 containing the objects that are both in the cached set 2 with a given index and an i...
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.
A class to maintain the context for squashing of RooFit models into code.
void addResult(RooAbsArg const *key, std::string const &value)
A function to save an expression that includes/depends on the result of the input node.
void addToCodeBody(RooAbsArg const *klass, std::string const &in)
Adds the input string to the squashed code body.
std::string const & getResult(RooAbsArg const &arg)
Gets the result for the given node using the node name.
void addToGlobalScope(std::string const &str)
Adds the given string to the string block that will be emitted at the top of the squashed function.
RooBatchCompute::Config config(RooAbsArg const *arg) const
Definition DataMap.cxx:40
std::span< const double > at(RooAbsArg const *arg, RooAbsArg const *caller=nullptr)
Definition DataMap.cxx:22
This is a simple class designed to produce the nll values needed by the fitter.
Class RooNLLVar implements a -log(likelihood) calculation from a dataset and a PDF.
Definition RooNLLVar.h:25
static const TNamed * ptr(const char *stringPtr)
Return a unique TNamed pointer for given C++ string.
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:139
TString & Append(const char *cs)
Definition TString.h:576
#define I(x, y, z)
std::vector< std::span< const double > > VarVector
std::vector< double > ArgVector
void compute(Config cfg, Computer comp, RestrictArr output, size_t size, const VarVector &vars, ArgVector &extraArgs)
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2345
static void output()