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
22Calculates 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 : RooAbsReal(name, title), _set("!set", "set of components", this), _cacheMgr(this, 10)
60{
61 _set.addTyped<RooAbsReal>(sumSet);
62}
63
64
65
66////////////////////////////////////////////////////////////////////////////////
67/// Constructor with two sets of RooAbsReals.
68///
69/// The sum of pair-wise products of elements in the sets will be computed:
70/// \f[
71/// A = \sum_i \mathrm{Set1}[i] * \mathrm{Set2}[i]
72/// \f]
73///
74/// \param[in] name Name of the PDF
75/// \param[in] title Title
76/// \param[in] sumSet1 Left-hand element of the pair-wise products
77/// \param[in] sumSet2 Right-hand element of the pair-wise products
78/// \param[in] takeOwnership If true, the RooAddition object will take ownership of the arguments in the `sumSets`
79///
80RooAddition::RooAddition(const char *name, const char *title, const RooArgList &sumSet1, const RooArgList &sumSet2)
81 : RooAbsReal(name, title), _set("!set", "set of components", this), _cacheMgr(this, 10)
82{
83 if (sumSet1.size() != sumSet2.size()) {
84 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: input lists should be of equal length" << std::endl;
86 }
87
88 for (unsigned int i = 0; i < sumSet1.size(); ++i) {
89 const auto comp1 = &sumSet1[i];
90 const auto comp2 = &sumSet2[i];
91
92 if (!dynamic_cast<RooAbsReal*>(comp1)) {
93 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: component " << comp1->GetName()
94 << " in first list is not of type RooAbsReal" << std::endl;
96 }
97
98 if (!dynamic_cast<RooAbsReal*>(comp2)) {
99 coutE(InputArguments) << "RooAddition::ctor(" << GetName() << ") ERROR: component " << comp2->GetName()
100 << " in first list is not of type RooAbsReal" << std::endl;
102 }
103 TString _name(name);
104 _name.Append( "_[");
105 _name.Append(comp1->GetName());
106 _name.Append( "_x_");
107 _name.Append(comp2->GetName());
108 _name.Append( "]");
109 auto prod = std::make_unique<RooProduct>( _name, _name , RooArgSet(*comp1, *comp2));
110 _set.add(*prod);
111 _ownedList.addOwned(std::move(prod));
112 }
113}
114
115
116
117////////////////////////////////////////////////////////////////////////////////
118/// Copy constructor
119
120RooAddition::RooAddition(const RooAddition& other, const char* name)
121 : RooAbsReal(other, name)
122 , _set("!set",this,other._set)
123 , _cacheMgr(other._cacheMgr,this)
124{
125 // Member _ownedList is intentionally not copy-constructed -- ownership is not transferred
126}
127
128////////////////////////////////////////////////////////////////////////////////
129/// Calculate and return current value of self
130
132{
133 double sum(0);
134 const RooArgSet* nset = _set.nset() ;
135
136 for (auto* comp : static_range_cast<RooAbsReal*>(_set)) {
137 const double tmp = comp->getVal(nset);
138 sum += tmp ;
139 }
140 return sum ;
141}
142
143
144////////////////////////////////////////////////////////////////////////////////
145/// Compute addition of PDFs in batches.
147{
148 std::vector<std::span<const double>> pdfs;
149 std::vector<double> coefs;
150 pdfs.reserve(_set.size());
151 coefs.reserve(_set.size());
152 for (const auto arg : _set) {
153 pdfs.push_back(ctx.at(arg));
154 coefs.push_back(1.0);
155 }
156 RooBatchCompute::compute(ctx.config(this), RooBatchCompute::AddPdf, ctx.output(), pdfs, coefs);
157}
158
159////////////////////////////////////////////////////////////////////////////////
160
162{
163 // If the number of elements to sum is less than 3, just build a sum expression.
164 // else build a loop to sum over the values.
165 unsigned int eleSize = _set.size();
166 std::string result;
167 if (eleSize > 3) {
168 std::string className = GetName();
169 std::string varName = "elements" + className;
170 std::string sumName = "sum" + className;
171 std::string code;
172 std::string decl = "double " + varName + "[" + std::to_string(eleSize) + "]{";
173 int idx = 0;
174 for (RooAbsArg *it : _set) {
175 decl += ctx.getResult(*it) + ",";
176 ctx.addResult(it, varName + "[" + std::to_string(idx) + "]");
177 idx++;
178 }
179 decl.back() = '}';
180 code += decl + ";\n";
181
182 ctx.addToGlobalScope("double " + sumName + " = 0;\n");
183 std::string iterator = "i_" + className;
184 code += "for(int " + iterator + " = 0; " + iterator + " < " + std::to_string(eleSize) + "; " + iterator +
185 "++) {\n" + sumName + " += " + varName + "[" + iterator + "];\n}\n";
186 result = sumName;
187 ctx.addResult(this, result);
188
189 ctx.addToCodeBody(this, code);
190 }
191
192 result = "(";
193 for (RooAbsArg *it : _set) {
194 result += ctx.getResult(*it) + '+';
195 }
196 result.back() = ')';
197 ctx.addResult(this, result);
198}
199
200////////////////////////////////////////////////////////////////////////////////
201/// Return the default error level for MINUIT error analysis
202/// If the addition contains one or more RooNLLVars and
203/// no RooChi2Vars, return the defaultErrorLevel() of
204/// RooNLLVar. If the addition contains one ore more RooChi2Vars
205/// and no RooNLLVars, return the defaultErrorLevel() of
206/// RooChi2Var. If the addition contains neither or both
207/// issue a warning message and return a value of 1
208
210{
211 RooAbsReal* nllArg(nullptr) ;
212 RooAbsReal* chi2Arg(nullptr) ;
213
214 std::unique_ptr<RooArgSet> comps{getComponents()};
215 for(RooAbsArg * arg : *comps) {
216 if (dynamic_cast<RooNLLVarNew*>(arg)) {
217 nllArg = static_cast<RooAbsReal*>(arg) ;
218 }
219#ifdef ROOFIT_LEGACY_EVAL_BACKEND
220 if (dynamic_cast<RooNLLVar*>(arg)) {
221 nllArg = static_cast<RooAbsReal*>(arg) ;
222 }
223 if (dynamic_cast<RooChi2Var*>(arg)) {
224 chi2Arg = static_cast<RooAbsReal*>(arg) ;
225 }
226#endif
227 }
228
229 if (nllArg && !chi2Arg) {
230 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName()
231 << ") Summation contains a RooNLLVar, using its error level" << std::endl;
232 return nllArg->defaultErrorLevel() ;
233 } else if (chi2Arg && !nllArg) {
234 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName()
235 << ") Summation contains a RooChi2Var, using its error level" << std::endl;
236 return chi2Arg->defaultErrorLevel() ;
237 } else if (!nllArg && !chi2Arg) {
238 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName() << ") WARNING: "
239 << "Summation contains neither RooNLLVar nor RooChi2Var server, using default level of 1.0" << std::endl;
240 } else {
241 coutI(Fitting) << "RooAddition::defaultErrorLevel(" << GetName() << ") WARNING: "
242 << "Summation contains BOTH RooNLLVar and RooChi2Var server, using default level of 1.0" << std::endl;
243 }
244
245 return 1.0 ;
246}
247
248
249
250////////////////////////////////////////////////////////////////////////////////
251
253{
254 for (const auto arg : _set) {
255 static_cast<RooAbsReal*>(arg)->setData(data,cloneData) ;
256 }
257 return true ;
258}
259
260
261
262////////////////////////////////////////////////////////////////////////////////
263
264void RooAddition::printMetaArgs(std::ostream& os) const
265{
266 // We can use the implementation of RooRealSumPdf with an empty coefficient list.
267 static const RooArgList coefs{};
269}
270
271////////////////////////////////////////////////////////////////////////////////
272
273Int_t RooAddition::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName) const
274{
275 // we always do things ourselves -- actually, always delegate further down the line ;-)
276 analVars.add(allVars);
277
278 // check if we already have integrals for this combination of factors
279 Int_t sterileIndex(-1);
280 CacheElem* cache = static_cast<CacheElem*>(_cacheMgr.getObj(&analVars,&analVars,&sterileIndex,RooNameReg::ptr(rangeName)));
281 if (cache!=nullptr) {
282 Int_t code = _cacheMgr.lastIndex();
283 return code+1;
284 }
285
286 // we don't, so we make it right here....
287 cache = new CacheElem;
288 for (auto *arg : static_range_cast<RooAbsReal const*>(_set)) {// checked in c'tor that this will work...
289 cache->_I.addOwned(std::unique_ptr<RooAbsReal>{arg->createIntegral(analVars,rangeName)});
290 }
291
292 Int_t code = _cacheMgr.setObj(&analVars,&analVars,(RooAbsCacheElement*)cache,RooNameReg::ptr(rangeName));
293 return 1+code;
294}
295
296////////////////////////////////////////////////////////////////////////////////
297/// Calculate integral internally from appropriate integral cache
298
299double RooAddition::analyticalIntegral(Int_t code, const char* rangeName) const
300{
301 // note: rangeName implicit encoded in code: see _cacheMgr.setObj in getPartIntList...
302 CacheElem *cache = static_cast<CacheElem*>(_cacheMgr.getObjByIndex(code-1));
303 if (cache==nullptr) {
304 // cache got sterilized, trigger repopulation of this slot, then try again...
305 std::unique_ptr<RooArgSet> vars( getParameters(RooArgSet()) );
306 RooArgSet iset = _cacheMgr.selectFromSet2(*vars, code-1);
307 RooArgSet dummy;
308 Int_t code2 = getAnalyticalIntegral(iset,dummy,rangeName);
309 assert(code==code2); // must have revived the right (sterilized) slot...
310 return analyticalIntegral(code2,rangeName);
311 }
312 assert(cache!=nullptr);
313
314 // loop over cache, and sum...
315 double result(0);
316 for (auto I : cache->_I) {
317 result += static_cast<const RooAbsReal*>(I)->getVal();
318 }
319 return result;
320
321}
322
323
324////////////////////////////////////////////////////////////////////////////////
325
326std::list<double>* RooAddition::binBoundaries(RooAbsRealLValue& obs, double xlo, double xhi) const
327{
328 return RooRealSumPdf::binBoundaries(_set, obs, xlo, xhi);
329}
330
331
333{
335}
336
337
338////////////////////////////////////////////////////////////////////////////////
339
340std::list<double>* RooAddition::plotSamplingHint(RooAbsRealLValue& obs, double xlo, double xhi) const
341{
342 return RooRealSumPdf::plotSamplingHint(_set, obs, xlo, xhi);
343}
#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:77
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.
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
bool addTyped(const RooAbsCollection &list, bool silent=false)
Adds elements of a given RooAbsCollection to the container if they match the specified type.
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
Abstract base class for objects that represent a real value that may appear on the left hand side of ...
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
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
void doEval(RooFit::EvalContext &) const override
Compute addition of PDFs in batches.
Int_t getAnalyticalIntegral(RooArgSet &allVars, RooArgSet &numVars, const char *rangeName=nullptr) const override
Interface function getAnalyticalIntergral advertises the analytical integrals that are supported.
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 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.
Simple calculation from a binned dataset and a PDF.
Definition RooChi2Var.h:50
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.
std::span< const double > at(RooAbsArg const *arg, RooAbsArg const *caller=nullptr)
std::span< double > output()
RooBatchCompute::Config config(RooAbsArg const *arg) const
Implements a -log(likelihood) calculation from a dataset and a PDF.
Definition RooNLLVar.h:50
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:572
#define I(x, y, z)
void compute(Config cfg, Computer comp, std::span< double > output, VarSpan vars, ArgSpan extraArgs={})
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2345