Logo ROOT  
Reference Guide
RooAddPdf.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/** \class RooAddPdf
19 \ingroup Roofitcore
20
21RooAddPdf is an efficient implementation of a sum of PDFs of the form
22
23\f[
24 \sum_{i=1}^{n} c_i \cdot \mathrm{PDF}_i
25\f]
26
27or
28\f[
29 c_1\cdot\mathrm{PDF}_1 + c_2\cdot\mathrm{PDF}_2 \; + \; ... \; + \; \left( 1-\sum_{i=1}^{n-1}c_i \right) \cdot \mathrm{PDF}_n
30\f]
31
32The first form is for extended likelihood fits, where the
33expected number of events is \f$ \sum_i c_i \f$. The coefficients \f$ c_i \f$
34can either be explicitly provided, or, if all components support
35extended likelihood fits, they can be calculated from the contribution
36of each PDF to the total expected number of events.
37
38In the second form, the sum of the coefficients is required to be 1 or less,
39and the coefficient of the last PDF is calculated automatically from the condition
40that the sum of all coefficients has to be 1.
41
42### Recursive coefficients
43It is also possible to parameterise the coefficients recursively
44
45\f[
46 \sum_{i=1}^n c_i \prod_{j=1}^{i-1} \left[ (1-c_j) \right] \cdot \mathrm{PDF}_i \\
47 = c_1 \cdot \mathrm{PDF}_1 + (1-c_1)\, c_2 \cdot \mathrm{PDF}_2 + \ldots + (1-c_1)\ldots(1-c_{n-1}) \cdot 1 \cdot \mathrm{PDF}_n \\
48\f]
49
50In this form the sum of the coefficients is always less than 1.0
51for all possible values of the individual coefficients between 0 and 1.
52\note Don't pass the \f$ n^\mathrm{th} \f$ coefficient. It is always 1, since the normalisation condition removes one degree of freedom.
53
54RooAddPdf relies on each component PDF to be normalized and will perform
55no normalization other than calculating the proper last coefficient \f$ c_n \f$, if requested.
56An (enforced) condition for this assumption is that each \f$ \mathrm{PDF}_i \f$ is independent of each \f$ c_i \f$.
57
58## Difference between RooAddPdf / RooRealSumFunc / RooRealSumPdf
59- RooAddPdf is a PDF of PDFs, *i.e.* its components need to be normalised and non-negative.
60- RooRealSumPdf is a PDF of functions, *i.e.*, its components can be negative, but their sum cannot be. The normalisation
61 is computed automatically, unless the PDF is extended (see above).
62- RooRealSumFunc is a sum of functions. It is neither normalised, nor need it be positive.
63
64*/
65
66
67#include "RooFit.h"
68#include "RooMsgService.h"
69
70#include "TIterator.h"
71#include "TList.h"
72#include "RooAddPdf.h"
73#include "RooDataSet.h"
74#include "RooRealProxy.h"
75#include "RooPlot.h"
76#include "RooRealVar.h"
77#include "RooAddGenContext.h"
78#include "RooRealConstant.h"
79#include "RooNameReg.h"
81#include "RooGlobalFunc.h"
82#include "RooRealIntegral.h"
83#include "RooTrace.h"
84
85#include "Riostream.h"
86#include <algorithm>
87
88
89using namespace std;
90
92;
93
94
95////////////////////////////////////////////////////////////////////////////////
96/// Default constructor used for persistence
97
99 _refCoefNorm("!refCoefNorm","Reference coefficient normalization set",this,kFALSE,kFALSE),
100 _refCoefRangeName(0),
101 _projectCoefs(false),
102 _codeReg(10),
103 _snormList(0),
104 _haveLastCoef(false),
105 _allExtendable(false),
106 _recursive(false)
107{
110}
111
112
113
114////////////////////////////////////////////////////////////////////////////////
115/// Dummy constructor
116
117RooAddPdf::RooAddPdf(const char *name, const char *title) :
118 RooAbsPdf(name,title),
119 _refCoefNorm("!refCoefNorm","Reference coefficient normalization set",this,kFALSE,kFALSE),
120 _refCoefRangeName(0),
121 _projectCoefs(kFALSE),
122 _projCacheMgr(this,10),
123 _codeReg(10),
124 _pdfList("!pdfs","List of PDFs",this),
125 _coefList("!coefficients","List of coefficients",this),
126 _snormList(0),
127 _haveLastCoef(kFALSE),
128 _allExtendable(kFALSE),
129 _recursive(kFALSE)
130{
133}
134
135
136
137////////////////////////////////////////////////////////////////////////////////
138/// Constructor with two PDFs and one coefficient
139
140RooAddPdf::RooAddPdf(const char *name, const char *title,
141 RooAbsPdf& pdf1, RooAbsPdf& pdf2, RooAbsReal& coef1) :
142 RooAbsPdf(name,title),
143 _refCoefNorm("!refCoefNorm","Reference coefficient normalization set",this,kFALSE,kFALSE),
144 _refCoefRangeName(0),
145 _projectCoefs(kFALSE),
146 _projCacheMgr(this,10),
147 _codeReg(10),
148 _pdfList("!pdfs","List of PDFs",this),
149 _coefList("!coefficients","List of coefficients",this),
150 _haveLastCoef(kFALSE),
151 _allExtendable(kFALSE),
152 _recursive(kFALSE)
153{
154 _pdfList.add(pdf1) ;
155 _pdfList.add(pdf2) ;
156 _coefList.add(coef1) ;
157
158 _coefCache.resize(_pdfList.size());
161}
162
163
164
165////////////////////////////////////////////////////////////////////////////////
166/// Generic constructor from list of PDFs and list of coefficients.
167/// Each pdf list element (i) is paired with coefficient list element (i).
168/// The number of coefficients must be either equal to the number of PDFs,
169/// in which case extended MLL fitting is enabled, or be one less.
170///
171/// All PDFs must inherit from RooAbsPdf. All coefficients must inherit from RooAbsReal
172///
173/// If the recursiveFraction flag is true, the coefficients are interpreted as recursive
174/// coefficients as explained in the class description.
175
176RooAddPdf::RooAddPdf(const char *name, const char *title, const RooArgList& inPdfList, const RooArgList& inCoefList, Bool_t recursiveFractions) :
177 RooAbsPdf(name,title),
178 _refCoefNorm("!refCoefNorm","Reference coefficient normalization set",this,kFALSE,kFALSE),
179 _refCoefRangeName(0),
180 _projectCoefs(kFALSE),
181 _projCacheMgr(this,10),
182 _codeReg(10),
183 _pdfList("!pdfs","List of PDFs",this),
184 _coefList("!coefficients","List of coefficients",this),
185 _haveLastCoef(kFALSE),
186 _allExtendable(kFALSE),
187 _recursive(recursiveFractions)
188{
189 if (inPdfList.getSize()>inCoefList.getSize()+1 || inPdfList.getSize()<inCoefList.getSize()) {
190 std::stringstream errorMsg;
191 errorMsg << "RooAddPdf::RooAddPdf(" << GetName()
192 << ") number of pdfs and coefficients inconsistent, must have Npdf=Ncoef or Npdf=Ncoef+1." << endl ;
193 coutE(InputArguments) << errorMsg.str();
194 throw std::invalid_argument(errorMsg.str().c_str());
195 }
196
197 if (recursiveFractions && inPdfList.getSize()!=inCoefList.getSize()+1) {
198 std::stringstream errorMsg;
199 errorMsg << "RooAddPdf::RooAddPdf(" << GetName()
200 << "): Recursive fractions option can only be used if Npdf=Ncoef+1." << endl;
201 coutE(InputArguments) << errorMsg.str();
202 throw std::invalid_argument(errorMsg.str());
203 }
204
205 // Constructor with N PDFs and N or N-1 coefs
206 RooArgList partinCoefList ;
207
209
210 for (auto i = 0u; i < inCoefList.size(); ++i) {
211 auto coef = dynamic_cast<RooAbsReal*>(inCoefList.at(i));
212 auto pdf = dynamic_cast<RooAbsPdf*>(inPdfList.at(i));
213 if (inPdfList.at(i) == nullptr) {
214 std::stringstream errorMsg;
215 errorMsg << "RooAddPdf::RooAddPdf(" << GetName()
216 << ") number of pdfs and coefficients inconsistent, must have Npdf=Ncoef or Npdf=Ncoef+1" << endl ;
217 coutE(InputArguments) << errorMsg.str();
218 throw std::invalid_argument(errorMsg.str());
219 }
220 if (!coef) {
221 std::stringstream errorMsg;
222 errorMsg << "RooAddPdf::RooAddPdf(" << GetName() << ") coefficient " << (coef ? coef->GetName() : "") << " is not of type RooAbsReal, ignored" << endl ;
223 coutE(InputArguments) << errorMsg.str();
224 throw std::invalid_argument(errorMsg.str());
225 }
226 if (!pdf) {
227 std::stringstream errorMsg;
228 errorMsg << "RooAddPdf::RooAddPdf(" << GetName() << ") pdf " << (pdf ? pdf->GetName() : "") << " is not of type RooAbsPdf, ignored" << endl ;
229 coutE(InputArguments) << errorMsg.str();
230 throw std::invalid_argument(errorMsg.str());
231 }
232 _pdfList.add(*pdf) ;
233
234 // Process recursive fraction mode separately
235 if (recursiveFractions) {
236 partinCoefList.add(*coef) ;
237 if (first) {
238
239 // The first fraction is the first plain fraction
240 first = kFALSE ;
241 _coefList.add(*coef) ;
242
243 } else {
244
245 // The i-th recursive fraction = (1-f1)*(1-f2)*...(fi) and is calculated from the list (f1,...,fi) by RooRecursiveFraction)
246 RooAbsReal* rfrac = new RooRecursiveFraction(Form("%s_recursive_fraction_%s",GetName(),pdf->GetName()),"Recursive Fraction",partinCoefList) ;
247 addOwnedComponents(*rfrac) ;
248 _coefList.add(*rfrac) ;
249
250 }
251
252 } else {
253 _coefList.add(*coef) ;
254 }
255 }
256
257 if (inPdfList.size() == inCoefList.size() + 1) {
258 auto pdf = dynamic_cast<RooAbsPdf*>(inPdfList.at(inCoefList.size()));
259
260 if (!pdf) {
261 coutE(InputArguments) << "RooAddPdf::RooAddPdf(" << GetName() << ") last argument " << inPdfList.at(inCoefList.size())->GetName() << " is not of type RooAbsPdf." << endl ;
262 throw std::invalid_argument("Last argument for RooAddPdf is not a PDF.");
263 }
264 _pdfList.add(*pdf) ;
265
266 // Process recursive fractions mode. Above, we verified that we don't have a last coefficient
267 if (recursiveFractions) {
268
269 // The last recursive fraction = (1-f1)*(1-f2)*...(1-fN) and is calculated from the list (f1,...,fN,1) by RooRecursiveFraction
270 partinCoefList.add(RooFit::RooConst(1)) ;
271 RooAbsReal* rfrac = new RooRecursiveFraction(Form("%s_recursive_fraction_%s",GetName(),pdf->GetName()),"Recursive Fraction",partinCoefList) ;
272 addOwnedComponents(*rfrac) ;
273 _coefList.add(*rfrac) ;
274
275 // In recursive mode we always have Ncoef=Npdf, since we added it just above
277 }
278
279 } else {
281 }
282
283
284 _coefCache.resize(_pdfList.size());
286
288}
289
290
291
292////////////////////////////////////////////////////////////////////////////////
293/// Generic constructor from list of extended PDFs. There are no coefficients as the expected
294/// number of events from each components determine the relative weight of the PDFs.
295///
296/// All PDFs must inherit from RooAbsPdf.
297
298RooAddPdf::RooAddPdf(const char *name, const char *title, const RooArgList& inPdfList) :
299 RooAbsPdf(name,title),
300 _refCoefNorm("!refCoefNorm","Reference coefficient normalization set",this,kFALSE,kFALSE),
301 _refCoefRangeName(0),
302 _projectCoefs(kFALSE),
303 _projCacheMgr(this,10),
304 _pdfList("!pdfs","List of PDFs",this),
305 _coefList("!coefficients","List of coefficients",this),
306 _haveLastCoef(kFALSE),
307 _allExtendable(kTRUE),
308 _recursive(kFALSE)
309{
310 // Constructor with N PDFs
311 for (const auto pdfArg : inPdfList) {
312 auto pdf = dynamic_cast<const RooAbsPdf*>(pdfArg);
313
314 if (!pdf) {
315 coutE(InputArguments) << "RooAddPdf::RooAddPdf(" << GetName() << ") pdf " << (pdf ? pdf->GetName() : "") << " is not of type RooAbsPdf, ignored" << endl ;
316 continue ;
317 }
318 if (!pdf->canBeExtended()) {
319 coutE(InputArguments) << "RooAddPdf::RooAddPdf(" << GetName() << ") pdf " << pdf->GetName() << " is not extendable, ignored" << endl ;
320 continue ;
321 }
322 _pdfList.add(*pdf) ;
323 }
324
325 _coefCache.resize(_pdfList.size());
328}
329
330
331
332
333////////////////////////////////////////////////////////////////////////////////
334/// Copy constructor
335
336RooAddPdf::RooAddPdf(const RooAddPdf& other, const char* name) :
337 RooAbsPdf(other,name),
338 _refCoefNorm("!refCoefNorm",this,other._refCoefNorm),
339 _refCoefRangeName((TNamed*)other._refCoefRangeName),
340 _projectCoefs(other._projectCoefs),
341 _projCacheMgr(other._projCacheMgr,this),
342 _codeReg(other._codeReg),
343 _pdfList("!pdfs",this,other._pdfList),
344 _coefList("!coefficients",this,other._coefList),
345 _haveLastCoef(other._haveLastCoef),
346 _allExtendable(other._allExtendable),
347 _recursive(other._recursive)
348{
349 _coefCache.resize(_pdfList.size());
352}
353
354
355
356////////////////////////////////////////////////////////////////////////////////
357/// Destructor
358
360{
362}
363
364
365
366////////////////////////////////////////////////////////////////////////////////
367/// By default the interpretation of the fraction coefficients is
368/// performed in the contextual choice of observables. This makes the
369/// shape of the p.d.f explicitly dependent on the choice of
370/// observables. This method instructs RooAddPdf to freeze the
371/// interpretation of the coefficients to be done in the given set of
372/// observables. If frozen, fractions are automatically transformed
373/// from the reference normalization set to the contextual normalization
374/// set by ratios of integrals.
375
377{
378 if (refCoefNorm.getSize()==0) {
380 return ;
381 }
383
385 _refCoefNorm.add(refCoefNorm) ;
386
388}
389
390
391
392////////////////////////////////////////////////////////////////////////////////
393/// By default, fraction coefficients are assumed to refer to the default
394/// fit range. This makes the shape of a RooAddPdf
395/// explicitly dependent on the range of the observables. Calling this function
396/// allows for a range-independent definition of the fractions, because it
397/// ties all coefficients to the given
398/// named range. If the normalisation range is different
399/// from this reference range, the appropriate fraction coefficients
400/// are automatically calculated from the reference fractions by
401/// integrating over the ranges, and comparing these integrals.
402
403void RooAddPdf::fixCoefRange(const char* rangeName)
404{
407}
408
409
410
411////////////////////////////////////////////////////////////////////////////////
412/// Retrieve cache element for the computation of the PDF normalisation.
413/// \param[in] nset Current normalisation set (integration over these variables yields 1).
414/// \param[in] iset Integration set. Variables to be integrated over (if integrations are performed).
415/// \param[in] rangeName Reference range for the integrals.
416///
417/// If a cache element does not exist, create and fill it on the fly. The cache also contains
418/// - Supplemental normalization terms (in case not all added p.d.f.s have the same observables)
419/// - Projection integrals to calculate transformed fraction coefficients when a frozen reference frame is provided
420/// - Projection integrals for similar transformations when a frozen reference range is provided.
421
422RooAddPdf::CacheElem* RooAddPdf::getProjCache(const RooArgSet* nset, const RooArgSet* iset, const char* rangeName) const
423{
424
425 // Check if cache already exists
426 CacheElem* cache = (CacheElem*) _projCacheMgr.getObj(nset,iset,0,rangeName) ;
427 if (cache) {
428 return cache ;
429 }
430
431 //Create new cache
432 cache = new CacheElem ;
433
434 // *** PART 1 : Create supplemental normalization list ***
435
436 // Retrieve the combined set of dependents of this PDF ;
437 RooArgSet *fullDepList = getObservables(nset) ;
438 if (iset) {
439 fullDepList->remove(*iset,kTRUE,kTRUE) ;
440 }
441
442 // Fill with dummy unit RRVs for now
443 for (int i = 0; i < _pdfList.getSize(); ++i) {
444 auto pdf = static_cast<const RooAbsPdf *>(_pdfList.at(i));
445 auto coef = static_cast<const RooAbsReal*>(_coefList.at(i));
446
447 // Start with full list of dependents
448 RooArgSet supNSet(*fullDepList) ;
449
450 // Remove PDF dependents
451 RooArgSet* pdfDeps = pdf->getObservables(nset) ;
452 if (pdfDeps) {
453 supNSet.remove(*pdfDeps,kTRUE,kTRUE) ;
454 delete pdfDeps ;
455 }
456
457 // Remove coef dependents
458 RooArgSet* coefDeps = coef ? coef->getObservables(nset) : 0 ;
459 if (coefDeps) {
460 supNSet.remove(*coefDeps,kTRUE,kTRUE) ;
461 delete coefDeps ;
462 }
463
464 RooAbsReal* snorm ;
465 TString name(GetName()) ;
466 name.Append("_") ;
467 name.Append(pdf->GetName()) ;
468 name.Append("_SupNorm") ;
469 cache->_needSupNorm = kFALSE ;
470 if (supNSet.getSize()>0) {
471 snorm = new RooRealIntegral(name,"Supplemental normalization integral",RooRealConstant::value(1.0),supNSet) ;
472 cxcoutD(Caching) << "RooAddPdf " << GetName() << " making supplemental normalization set " << supNSet << " for pdf component " << pdf->GetName() << endl ;
473 cache->_needSupNorm = kTRUE ;
474 } else {
475 snorm = new RooRealVar(name,"Unit Supplemental normalization integral",1.0) ;
476 }
477 cache->_suppNormList.addOwned(*snorm) ;
478 }
479
480 delete fullDepList ;
481
482 if (_verboseEval>1) {
483 cxcoutD(Caching) << "RooAddPdf::syncSuppNormList(" << GetName() << ") synching supplemental normalization list for norm" << (nset?*nset:RooArgSet()) << endl ;
484 if dologD(Caching) {
485 cache->_suppNormList.Print("v") ;
486 }
487 }
488
489
490 // *** PART 2 : Create projection coefficients ***
491
492// cout << " this = " << this << " (" << GetName() << ")" << endl ;
493// cout << "projectCoefs = " << (_projectCoefs?"T":"F") << endl ;
494// cout << "_normRange.Length() = " << _normRange.Length() << endl ;
495
496 // If no projections required stop here
497 if (!_projectCoefs && !rangeName) {
498 _projCacheMgr.setObj(nset,iset,cache,RooNameReg::ptr(rangeName)) ;
499// cout << " no projection required" << endl ;
500 return cache ;
501 }
502
503
504// cout << "calculating projection" << endl ;
505
506 // Reduce iset/nset to actual dependents of this PDF
507 RooArgSet* nset2 = nset ? getObservables(nset) : new RooArgSet() ;
508 cxcoutD(Caching) << "RooAddPdf(" << GetName() << ")::getPC nset = " << (nset?*nset:RooArgSet()) << " nset2 = " << *nset2 << endl ;
509
510 if (nset2->getSize()==0 && _refCoefNorm.getSize()!=0) {
511 //cout << "WVE: evaluating RooAddPdf without normalization, but have reference normalization for coefficient definition" << endl ;
512
513 nset2->add(_refCoefNorm) ;
514 if (_refCoefRangeName) {
516 }
517 }
518
519
520 // Check if requested transformation is not identity
521 if (!nset2->equals(_refCoefNorm) || _refCoefRangeName !=0 || rangeName !=0 || _normRange.Length()>0) {
522
523 cxcoutD(Caching) << "ALEX: RooAddPdf::syncCoefProjList(" << GetName() << ") projecting coefficients from "
524 << *nset2 << (rangeName?":":"") << (rangeName?rangeName:"")
525 << " to " << ((_refCoefNorm.getSize()>0)?_refCoefNorm:*nset2) << (_refCoefRangeName?":":"") << (_refCoefRangeName?RooNameReg::str(_refCoefRangeName):"") << endl ;
526
527 // Recalculate projection integrals of PDFs
528 for (auto arg : _pdfList) {
529 auto thePdf = static_cast<const RooAbsPdf*>(arg);
530
531 // Calculate projection integral
532 RooAbsReal* pdfProj ;
533 if (!nset2->equals(_refCoefNorm)) {
534 pdfProj = thePdf->createIntegral(*nset2,_refCoefNorm,_normRange.Length()>0?_normRange.Data():0) ;
535 pdfProj->setOperMode(operMode()) ;
536 cxcoutD(Caching) << "RooAddPdf(" << GetName() << ")::getPC nset2(" << *nset2 << ")!=_refCoefNorm(" << _refCoefNorm << ") --> pdfProj = " << pdfProj->GetName() << endl ;
537 } else {
538 TString name(GetName()) ;
539 name.Append("_") ;
540 name.Append(thePdf->GetName()) ;
541 name.Append("_ProjectNorm") ;
542 pdfProj = new RooRealVar(name,"Unit Projection normalization integral",1.0) ;
543 cxcoutD(Caching) << "RooAddPdf(" << GetName() << ")::getPC nset2(" << *nset2 << ")==_refCoefNorm(" << _refCoefNorm << ") --> pdfProj = " << pdfProj->GetName() << endl ;
544 }
545
546 cache->_projList.addOwned(*pdfProj) ;
547 cxcoutD(Caching) << " RooAddPdf::syncCoefProjList(" << GetName() << ") PP = " << pdfProj->GetName() << endl ;
548
549 // Calculation optional supplemental normalization term
550 RooArgSet supNormSet(_refCoefNorm) ;
551 RooArgSet* deps = thePdf->getParameters(RooArgSet()) ;
552 supNormSet.remove(*deps,kTRUE,kTRUE) ;
553 delete deps ;
554
555 RooAbsReal* snorm ;
556 TString name(GetName()) ;
557 name.Append("_") ;
558 name.Append(thePdf->GetName()) ;
559 name.Append("_ProjSupNorm") ;
560 if (supNormSet.getSize()>0 && !nset2->equals(_refCoefNorm) ) {
561 snorm = new RooRealIntegral(name,"Projection Supplemental normalization integral",
562 RooRealConstant::value(1.0),supNormSet) ;
563 } else {
564 snorm = new RooRealVar(name,"Unit Projection Supplemental normalization integral",1.0) ;
565 }
566 cxcoutD(Caching) << " RooAddPdf::syncCoefProjList(" << GetName() << ") SN = " << snorm->GetName() << endl ;
567 cache->_suppProjList.addOwned(*snorm) ;
568
569 // Calculate reference range adjusted projection integral
570 RooAbsReal* rangeProj1 ;
571
572 // cout << "ALEX >>>> RooAddPdf(" << GetName() << ")::getPC _refCoefRangeName WVE = "
573// <<(_refCoefRangeName?":":"") << (_refCoefRangeName?RooNameReg::str(_refCoefRangeName):"")
574// <<" _refCoefRangeName AK = " << (_refCoefRangeName?_refCoefRangeName->GetName():"")
575// << " && _refCoefNorm" << _refCoefNorm << " with size = _refCoefNorm.getSize() " << _refCoefNorm.getSize() << endl ;
576
577 // Check if _refCoefRangeName is identical to default range for all observables,
578 // If so, substitute by unit integral
579
580 // ----------
581 RooArgSet* tmpObs = thePdf->getObservables(_refCoefNorm) ;
582 RooAbsArg* obsArg ;
583 TIterator* iter = tmpObs->createIterator() ;
584 Bool_t allIdent = kTRUE ;
585 while((obsArg=(RooAbsArg*)iter->Next())) {
586 RooRealVar* rvarg = dynamic_cast<RooRealVar*>(obsArg) ;
587 if (rvarg) {
588 if (rvarg->getMin(RooNameReg::str(_refCoefRangeName))!=rvarg->getMin() ||
589 rvarg->getMax(RooNameReg::str(_refCoefRangeName))!=rvarg->getMax()) {
590 allIdent=kFALSE ;
591 }
592 }
593 }
594 delete iter ;
595 delete tmpObs ;
596 // -------------
597
598 if (_refCoefRangeName && _refCoefNorm.getSize()>0 && !allIdent) {
599
600
601 RooArgSet* tmp = thePdf->getObservables(_refCoefNorm) ;
602 rangeProj1 = thePdf->createIntegral(*tmp,*tmp,RooNameReg::str(_refCoefRangeName)) ;
603
604 //rangeProj1->setOperMode(operMode()) ;
605
606 delete tmp ;
607 } else {
608
609 TString theName(GetName()) ;
610 theName.Append("_") ;
611 theName.Append(thePdf->GetName()) ;
612 theName.Append("_RangeNorm1") ;
613 rangeProj1 = new RooRealVar(theName,"Unit range normalization integral",1.0) ;
614
615 }
616 cxcoutD(Caching) << " RooAddPdf::syncCoefProjList(" << GetName() << ") R1 = " << rangeProj1->GetName() << endl ;
617 cache->_refRangeProjList.addOwned(*rangeProj1) ;
618
619
620 // Calculate range adjusted projection integral
621 RooAbsReal* rangeProj2 ;
622 cxcoutD(Caching) << "RooAddPdf::syncCoefProjList(" << GetName() << ") rangename = " << (rangeName?rangeName:"<null>")
623 << " nset = " << (nset?*nset:RooArgSet()) << endl ;
624 if (rangeName && _refCoefNorm.getSize()>0) {
625
626 rangeProj2 = thePdf->createIntegral(_refCoefNorm,_refCoefNorm,rangeName) ;
627 //rangeProj2->setOperMode(operMode()) ;
628
629 } else if (_normRange.Length()>0) {
630
631 RooArgSet* tmp = thePdf->getObservables(_refCoefNorm) ;
632 rangeProj2 = thePdf->createIntegral(*tmp,*tmp,_normRange.Data()) ;
633 delete tmp ;
634
635 } else {
636
637 TString theName(GetName()) ;
638 theName.Append("_") ;
639 theName.Append(thePdf->GetName()) ;
640 theName.Append("_RangeNorm2") ;
641 rangeProj2 = new RooRealVar(theName,"Unit range normalization integral",1.0) ;
642
643 }
644 cxcoutD(Caching) << " RooAddPdf::syncCoefProjList(" << GetName() << ") R2 = " << rangeProj2->GetName() << endl ;
645 cache->_rangeProjList.addOwned(*rangeProj2) ;
646
647 }
648
649 }
650
651 delete nset2 ;
652
653 _projCacheMgr.setObj(nset,iset,cache,RooNameReg::ptr(rangeName)) ;
654
655 return cache ;
656}
657
658
659////////////////////////////////////////////////////////////////////////////////
660/// Update the coefficient values in the given cache element: calculate new remainder
661/// fraction, normalize fractions obtained from extended ML terms to unity, and
662/// multiply the various range and dimensional corrections needed in the
663/// current use context.
664
665void RooAddPdf::updateCoefficients(CacheElem& cache, const RooArgSet* nset) const
666{
667 // Since this function updates the cache, it obviously needs write access:
668 auto& myCoefCache = const_cast<std::vector<double>&>(_coefCache);
669 myCoefCache.resize(_haveLastCoef ? _coefList.size() : _pdfList.size(), 0.);
670
671 // Straight coefficients
672 if (_allExtendable) {
673
674 // coef[i] = expectedEvents[i] / SUM(expectedEvents)
675 Double_t coefSum(0) ;
676 std::size_t i = 0;
677 for (auto arg : _pdfList) {
678 auto pdf = static_cast<RooAbsPdf*>(arg);
679 myCoefCache[i] = pdf->expectedEvents(_refCoefNorm.getSize()>0?&_refCoefNorm:nset) ;
680 coefSum += myCoefCache[i] ;
681 i++ ;
682 }
683
684 if (coefSum==0.) {
685 coutW(Eval) << "RooAddPdf::updateCoefCache(" << GetName() << ") WARNING: total number of expected events is 0" << endl ;
686 } else {
687 for (int j=0; j < _pdfList.getSize(); j++) {
688 myCoefCache[j] /= coefSum ;
689 }
690 }
691
692 } else {
693 if (_haveLastCoef) {
694
695 // coef[i] = coef[i] / SUM(coef)
696 Double_t coefSum(0) ;
697 std::size_t i=0;
698 for (auto coefArg : _coefList) {
699 auto coef = static_cast<RooAbsReal*>(coefArg);
700 myCoefCache[i] = coef->getVal(nset) ;
701 coefSum += myCoefCache[i++];
702 }
703 if (coefSum==0.) {
704 coutW(Eval) << "RooAddPdf::updateCoefCache(" << GetName() << ") WARNING: sum of coefficients is zero 0" << endl ;
705 } else {
706 for (int j=0; j < _coefList.getSize(); j++) {
707 myCoefCache[j] /= coefSum;
708 }
709 }
710 } else {
711
712 // coef[i] = coef[i] ; coef[n] = 1-SUM(coef[0...n-1])
713 Double_t lastCoef(1) ;
714 std::size_t i=0;
715 for (auto coefArg : _coefList) {
716 auto coef = static_cast<RooAbsReal*>(coefArg);
717 myCoefCache[i] = coef->getVal(nset) ;
718 //cxcoutD(Caching) << "SYNC: orig coef[" << i << "] = " << myCoefCache[i] << endl ;
719 lastCoef -= myCoefCache[i++];
720 }
721 myCoefCache[_coefList.getSize()] = lastCoef ;
722 //cxcoutD(Caching) << "SYNC: orig coef[" << _coefList.getSize() << "] = " << myCoefCache[_coefList.getSize()] << endl ;
723
724
725 // Warn about coefficient degeneration
726 if ((lastCoef<-1e-05 || (lastCoef-1)>1e-5) && _coefErrCount-->0) {
727 coutW(Eval) << "RooAddPdf::updateCoefCache(" << GetName()
728 << " WARNING: sum of PDF coefficients not in range [0-1], value="
729 << 1-lastCoef ;
730 if (_coefErrCount==0) {
731 coutW(Eval) << " (no more will be printed)" ;
732 }
733 coutW(Eval) << endl ;
734 }
735 }
736 }
737
738
739
740// cout << "XXXX" << GetName() << "updateCoefs _projectCoefs = " << (_projectCoefs?"T":"F") << " cache._projList.getSize()= " << cache._projList.getSize() << endl ;
741
742 // Stop here if not projection is required or needed
743 if ((!_projectCoefs && _normRange.Length()==0) || cache._projList.getSize()==0) {
744 //if (cache._projList.getSize()==0) {
745// cout << GetName() << " SYNC no projection required rangeName = " << (_normRange.Length()>0?_normRange.Data():"<none>") << endl ;
746 return ;
747 }
748
749// cout << "XXXX" << GetName() << " updateCoefs, applying correction" << endl ;
750// cout << "PROJLIST = " << endl ;
751// cache._projList.Print("v") ;
752
753
754 // Adjust coefficients for given projection
755 Double_t coefSum(0) ;
756 {
758
759 for (int i = 0; i < _pdfList.getSize(); i++) {
760
761 RooAbsReal* pp = ((RooAbsReal*)cache._projList.at(i)) ;
762 RooAbsReal* sn = ((RooAbsReal*)cache._suppProjList.at(i)) ;
763 RooAbsReal* r1 = ((RooAbsReal*)cache._refRangeProjList.at(i)) ;
764 RooAbsReal* r2 = ((RooAbsReal*)cache._rangeProjList.at(i)) ;
765
766 Double_t proj = pp->getVal()/sn->getVal()*(r2->getVal()/r1->getVal()) ;
767
768 // cxcoutD(Caching) << "ALEX: RooAddPdf::updateCoef(" << GetName() << ") with nset = " << (nset?*nset:RooArgSet()) << "for pdf component #" << i << " = " << _pdfList.at(i)->GetName() << endl
769 // << "ALEX: pp = " << pp->GetName() << " = " << pp->getVal() << endl
770 // << "ALEX: sn = " << sn->GetName() << " = " << sn->getVal() << endl
771 // << "ALEX: r1 = " << r1->GetName() << " = " << r1->getVal() << endl
772 // << "ALEX: r2 = " << r2->GetName() << " = " << r2->getVal() << endl
773 // << "ALEX: proj = (" << pp->getVal() << "/" << sn->getVal() << ")*(" << r2->getVal() << "/" << r1->getVal() << ") = " << proj << endl ;
774
775 myCoefCache[i] *= proj ;
776 coefSum += myCoefCache[i] ;
777 }
778 }
779
780
782 for (int i=0; i < _pdfList.getSize(); ++i) {
783 ccoutD(Caching) << " ALEX: POST-SYNC coef[" << i << "] = " << myCoefCache[i]
784 << " ( _coefCache[i]/coefSum = " << myCoefCache[i]*coefSum << "/" << coefSum << " ) "<< endl ;
785 }
786 }
787
788 if (coefSum==0.) {
789 coutE(Eval) << "RooAddPdf::updateCoefCache(" << GetName() << ") sum of coefficients is zero." << endl ;
790 }
791
792 for (int i=0; i < _pdfList.getSize(); i++) {
793 myCoefCache[i] /= coefSum ;
794 }
795
796
797
798}
799
800std::pair<const RooArgSet*, RooAddPdf::CacheElem*> RooAddPdf::getNormAndCache() const {
801 const RooArgSet* nset = _normSet ;
802 //cxcoutD(Caching) << "RooAddPdf::evaluate(" << GetName() << ") calling getProjCache with nset = " << nset << " = " << (nset?*nset:RooArgSet()) << endl ;
803
804 if (nset==0 || nset->getSize()==0) {
805 if (_refCoefNorm.getSize()!=0) {
806 nset = &_refCoefNorm ;
807 }
808 }
809
810 CacheElem* cache = getProjCache(nset) ;
811 updateCoefficients(*cache,nset) ;
812
813 return {nset, cache};
814}
815
816
817////////////////////////////////////////////////////////////////////////////////
818/// Calculate and return the current value
819
821{
822 auto normAndCache = getNormAndCache();
823 const RooArgSet* nset = normAndCache.first;
824 CacheElem* cache = normAndCache.second;
825
826
827 // Do running sum of coef/pdf pairs, calculate lastCoef.
828 Double_t value(0);
829
830 for (unsigned int i=0; i < _pdfList.size(); ++i) {
831 const auto& pdf = static_cast<RooAbsPdf&>(_pdfList[i]);
832 double snormVal = 1.;
833 if (cache->_needSupNorm) {
834 snormVal = ((RooAbsReal*)cache->_suppNormList.at(i))->getVal();
835 }
836
837 Double_t pdfVal = pdf.getVal(nset);
838 if (pdf.isSelectedComp()) {
839 value += pdfVal*_coefCache[i]/snormVal;
840 }
841 }
842
843 return value;
844}
845
846
847
848
849////////////////////////////////////////////////////////////////////////////////
850/// Compute addition of PDFs in batches.
851
852RooSpan<double> RooAddPdf::evaluateBatch(std::size_t begin, std::size_t batchSize) const {
853 auto normAndCache = getNormAndCache();
854 const RooArgSet* nset = normAndCache.first;
855 CacheElem* cache = normAndCache.second;
856
857
858 auto output = _batchData.makeWritableBatchInit(begin, batchSize, 0.);
859 const std::size_t n = output.size();
860
861
862 for (unsigned int pdfNo = 0; pdfNo < _pdfList.size(); ++pdfNo) {
863 const auto& pdf = static_cast<RooAbsPdf&>(_pdfList[pdfNo]);
864 auto pdfOutputs = pdf.getValBatch(begin, batchSize, nset);
865 assert(pdfOutputs.size() == output.size());
866
867 const double coef = _coefCache[pdfNo] / (cache->_needSupNorm ?
868 static_cast<RooAbsReal*>(cache->_suppNormList.at(pdfNo))->getVal() :
869 1.);
870
871 if (pdf.isSelectedComp()) {
872 for (std::size_t i = 0; i < n; ++i) { //CHECK_VECTORISE
873 output[i] += pdfOutputs[i] * coef;
874 }
875 }
876 }
877
878 return output;
879}
880
881
882////////////////////////////////////////////////////////////////////////////////
883/// Reset error counter to given value, limiting the number
884/// of future error messages for this pdf to 'resetValue'
885
887{
889 _coefErrCount = resetValue ;
890}
891
892
893
894////////////////////////////////////////////////////////////////////////////////
895/// Check if PDF is valid for given normalization set.
896/// Coeffient and PDF must be non-overlapping, but pdf-coefficient
897/// pairs may overlap each other
898
900{
901 Bool_t ret(kFALSE) ;
902
903 // There may be fewer coefficients than PDFs.
904 int end = std::min(_pdfList.getSize(), _coefList.getSize());
905 for (int i = 0; i < end; ++i) {
906 auto pdf = static_cast<const RooAbsPdf *>(_pdfList.at(i));
907 auto coef = static_cast<const RooAbsReal*>(_coefList.at(i));
908 if (pdf->observableOverlaps(nset,*coef)) {
909 coutE(InputArguments) << "RooAddPdf::checkObservables(" << GetName() << "): ERROR: coefficient " << coef->GetName()
910 << " and PDF " << pdf->GetName() << " have one or more dependents in common" << endl ;
911 ret = kTRUE ;
912 }
913 }
914
915 return ret ;
916}
917
918
919////////////////////////////////////////////////////////////////////////////////
920/// Determine which part (if any) of given integral can be performed analytically.
921/// If any analytical integration is possible, return integration scenario code
922///
923/// RooAddPdf queries each component PDF for its analytical integration capability of the requested
924/// set ('allVars'). It finds the largest common set of variables that can be integrated
925/// by all components. If such a set exists, it reconfirms that each component is capable of
926/// analytically integrating the common set, and combines the components individual integration
927/// codes into a single integration code valid for RooAddPdf.
928
930 const RooArgSet* normSet, const char* rangeName) const
931{
932
933 RooArgSet* allDepVars = getObservables(allVars) ;
934 RooArgSet allAnalVars(*allDepVars) ;
935 delete allDepVars ;
936
937 Int_t n(0) ;
938
939 // First iteration, determine what each component can integrate analytically
940 for (const auto pdfArg : _pdfList) {
941 auto pdf = static_cast<const RooAbsPdf *>(pdfArg);
942 RooArgSet subAnalVars ;
943 pdf->getAnalyticalIntegralWN(allVars,subAnalVars,normSet,rangeName) ;
944
945 // Observables that cannot be integrated analytically by this component are dropped from the common list
946 for (const auto arg : allVars) {
947 if (!subAnalVars.find(arg->GetName()) && pdf->dependsOn(*arg)) {
948 allAnalVars.remove(*arg,kTRUE,kTRUE) ;
949 }
950 }
951 n++ ;
952 }
953
954 // If no observables can be integrated analytically, return code 0 here
955 if (allAnalVars.getSize()==0) {
956 return 0 ;
957 }
958
959
960 // Now retrieve codes for integration over common set of analytically integrable observables for each component
961 n=0 ;
962 std::vector<Int_t> subCode(_pdfList.getSize());
963 Bool_t allOK(kTRUE) ;
964 for (const auto arg : _pdfList) {
965 auto pdf = static_cast<const RooAbsPdf *>(arg);
966 RooArgSet subAnalVars ;
967 RooArgSet* allAnalVars2 = pdf->getObservables(allAnalVars) ;
968 subCode[n] = pdf->getAnalyticalIntegralWN(*allAnalVars2,subAnalVars,normSet,rangeName) ;
969 if (subCode[n]==0 && allAnalVars2->getSize()>0) {
970 coutE(InputArguments) << "RooAddPdf::getAnalyticalIntegral(" << GetName() << ") WARNING: component PDF " << pdf->GetName()
971 << " advertises inconsistent set of integrals (e.g. (X,Y) but not X or Y individually."
972 << " Distributed analytical integration disabled. Please fix PDF" << endl ;
973 allOK = kFALSE ;
974 }
975 delete allAnalVars2 ;
976 n++ ;
977 }
978 if (!allOK) {
979 return 0 ;
980 }
981
982 // Mare all analytically integrated observables as such
983 analVars.add(allAnalVars) ;
984
985 // Store set of variables analytically integrated
986 RooArgSet* intSet = new RooArgSet(allAnalVars) ;
987 Int_t masterCode = _codeReg.store(subCode,intSet)+1 ;
988
989 return masterCode ;
990}
991
992
993
994////////////////////////////////////////////////////////////////////////////////
995/// Return analytical integral defined by given scenario code
996
997Double_t RooAddPdf::analyticalIntegralWN(Int_t code, const RooArgSet* normSet, const char* rangeName) const
998{
999 // WVE needs adaptation to handle new rangeName feature
1000 if (code==0) {
1001 return getVal(normSet) ;
1002 }
1003
1004 // Retrieve analytical integration subCodes and set of observabels integrated over
1005 RooArgSet* intSet ;
1006 const std::vector<Int_t>& subCode = _codeReg.retrieve(code-1,intSet) ;
1007 if (subCode.empty()) {
1008 coutE(InputArguments) << "RooAddPdf::analyticalIntegral(" << GetName() << "): ERROR unrecognized integration code, " << code << endl ;
1009 assert(0) ;
1010 }
1011
1012 cxcoutD(Caching) << "RooAddPdf::aiWN(" << GetName() << ") calling getProjCache with nset = " << (normSet?*normSet:RooArgSet()) << endl ;
1013
1014 if ((normSet==0 || normSet->getSize()==0) && _refCoefNorm.getSize()>0) {
1015// cout << "WVE integration of RooAddPdf without normalization, but have reference set, using ref set for normalization" << endl ;
1016 normSet = &_refCoefNorm ;
1017 }
1018
1019 CacheElem* cache = getProjCache(normSet,intSet,0) ; // WVE rangename here?
1020 updateCoefficients(*cache,normSet) ;
1021
1022 // Calculate the current value of this object
1023 Double_t value(0) ;
1024
1025 // Do running sum of coef/pdf pairs, calculate lastCoef.
1026 Double_t snormVal ;
1027
1028 //cout << "ROP::aIWN updateCoefCache with rangeName = " << (rangeName?rangeName:"<null>") << endl ;
1029 RooArgList* snormSet = (cache->_suppNormList.getSize()>0) ? &cache->_suppNormList : 0 ;
1030 for (int i = 0; i < _pdfList.getSize(); ++i ) {
1031 auto pdf = static_cast<const RooAbsPdf*>(_pdfList.at(i));
1032
1033 if (_coefCache[i]) {
1034 snormVal = snormSet ? ((RooAbsReal*) cache->_suppNormList.at(i))->getVal() : 1.0 ;
1035
1036 // WVE swap this?
1037 Double_t val = pdf->analyticalIntegralWN(subCode[i],normSet,rangeName) ;
1038 if (pdf->isSelectedComp()) {
1039 value += val*_coefCache[i]/snormVal ;
1040 }
1041 }
1042 }
1043
1044 return value ;
1045}
1046
1047
1048
1049////////////////////////////////////////////////////////////////////////////////
1050/// Return the number of expected events, which is either the sum of all coefficients
1051/// or the sum of the components extended terms, multiplied with the fraction that
1052/// is in the current range w.r.t the reference range
1053
1055{
1056 Double_t expectedTotal(0.0);
1057
1058 cxcoutD(Caching) << "RooAddPdf::expectedEvents(" << GetName() << ") calling getProjCache with nset = " << (nset?*nset:RooArgSet()) << endl ;
1059 CacheElem* cache = getProjCache(nset) ;
1060 updateCoefficients(*cache,nset) ;
1061
1062 if (cache->_rangeProjList.getSize()>0) {
1063
1064 RooFIter iter1 = cache->_refRangeProjList.fwdIterator() ;
1065 RooFIter iter2 = cache->_rangeProjList.fwdIterator() ;
1066 RooFIter iter3 = _pdfList.fwdIterator() ;
1067
1068 if (_allExtendable) {
1069
1070 RooAbsPdf* pdf ;
1071 while ((pdf=(RooAbsPdf*)iter3.next())) {
1072 RooAbsReal* r1 = (RooAbsReal*)iter1.next() ;
1073 RooAbsReal* r2 = (RooAbsReal*)iter2.next() ;
1074 expectedTotal += (r2->getVal()/r1->getVal()) * pdf->expectedEvents(nset) ;
1075 }
1076
1077 } else {
1078
1079 RooFIter citer = _coefList.fwdIterator() ;
1080 RooAbsReal* coef ;
1081 while((coef=(RooAbsReal*)citer.next())) {
1082 Double_t ncomp = coef->getVal(nset) ;
1083 RooAbsReal* r1 = (RooAbsReal*)iter1.next() ;
1084 RooAbsReal* r2 = (RooAbsReal*)iter2.next() ;
1085 expectedTotal += (r2->getVal()/r1->getVal()) * ncomp ;
1086 }
1087
1088 }
1089
1090
1091
1092 } else {
1093
1094 if (_allExtendable) {
1095
1096 RooFIter iter = _pdfList.fwdIterator() ;
1097 RooAbsPdf* pdf ;
1098 while((pdf=(RooAbsPdf*)iter.next())) {
1099 expectedTotal += pdf->expectedEvents(nset) ;
1100 }
1101
1102 } else {
1103
1104 RooFIter citer = _coefList.fwdIterator() ;
1105 RooAbsReal* coef ;
1106 while((coef=(RooAbsReal*)citer.next())) {
1107 Double_t ncomp = coef->getVal(nset) ;
1108 expectedTotal += ncomp ;
1109 }
1110
1111 }
1112
1113 }
1114 return expectedTotal ;
1115}
1116
1117
1118
1119////////////////////////////////////////////////////////////////////////////////
1120/// Interface function used by test statistics to freeze choice of observables
1121/// for interpretation of fraction coefficients
1122
1124{
1125
1126 if (!force && _refCoefNorm.getSize()!=0) {
1127 return ;
1128 }
1129
1130 if (!depSet) {
1132 return ;
1133 }
1134
1135 RooArgSet* myDepSet = getObservables(depSet) ;
1136 fixCoefNormalization(*myDepSet) ;
1137 delete myDepSet ;
1138}
1139
1140
1141
1142////////////////////////////////////////////////////////////////////////////////
1143/// Interface function used by test statistics to freeze choice of range
1144/// for interpretation of fraction coefficients
1145
1146void RooAddPdf::selectNormalizationRange(const char* rangeName, Bool_t force)
1147{
1148 if (!force && _refCoefRangeName) {
1149 return ;
1150 }
1151
1152 fixCoefRange(rangeName) ;
1153}
1154
1155
1156
1157////////////////////////////////////////////////////////////////////////////////
1158/// Return specialized context to efficiently generate toy events from RooAddPdfs
1159/// return RooAbsPdf::genContext(vars,prototype,auxProto,verbose) ; // WVE DEBUG
1160
1162 const RooArgSet* auxProto, Bool_t verbose) const
1163{
1164 return new RooAddGenContext(*this,vars,prototype,auxProto,verbose) ;
1165}
1166
1167
1168
1169////////////////////////////////////////////////////////////////////////////////
1170/// List all RooAbsArg derived contents in this cache element
1171
1173{
1174 RooArgList allNodes;
1175 allNodes.add(_projList) ;
1176 allNodes.add(_suppProjList) ;
1177 allNodes.add(_refRangeProjList) ;
1178 allNodes.add(_rangeProjList) ;
1179
1180 return allNodes ;
1181}
1182
1183
1184
1185////////////////////////////////////////////////////////////////////////////////
1186/// Loop over components for plot sampling hints and merge them if there are multiple
1187
1188std::list<Double_t>* RooAddPdf::plotSamplingHint(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const
1189{
1190 list<Double_t>* sumHint = 0 ;
1191 Bool_t needClean(kFALSE) ;
1192
1193 // Loop over components pdf
1194 for (const auto arg : _pdfList) {
1195 auto pdf = static_cast<const RooAbsPdf*>(arg);
1196
1197 list<Double_t>* pdfHint = pdf->plotSamplingHint(obs,xlo,xhi) ;
1198
1199 // Process hint
1200 if (pdfHint) {
1201 if (!sumHint) {
1202
1203 // If this is the first hint, then just save it
1204 sumHint = pdfHint ;
1205
1206 } else {
1207
1208 list<Double_t>* newSumHint = new list<Double_t>(sumHint->size()+pdfHint->size()) ;
1209
1210 // Merge hints into temporary array
1211 merge(pdfHint->begin(),pdfHint->end(),sumHint->begin(),sumHint->end(),newSumHint->begin()) ;
1212
1213 // Copy merged array without duplicates to new sumHintArrau
1214 delete sumHint ;
1215 sumHint = newSumHint ;
1216 needClean = kTRUE ;
1217
1218 }
1219 }
1220 }
1221 if (needClean) {
1222 list<Double_t>::iterator new_end = unique(sumHint->begin(),sumHint->end()) ;
1223 sumHint->erase(new_end,sumHint->end()) ;
1224 }
1225
1226 return sumHint ;
1227}
1228
1229
1230////////////////////////////////////////////////////////////////////////////////
1231/// Loop over components for plot sampling hints and merge them if there are multiple
1232
1233std::list<Double_t>* RooAddPdf::binBoundaries(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const
1234{
1235 list<Double_t>* sumBinB = 0 ;
1236 Bool_t needClean(kFALSE) ;
1237
1238 // Loop over components pdf
1239 for (auto arg : _pdfList) {
1240 auto pdf = static_cast<const RooAbsPdf *>(arg);
1241 list<Double_t>* pdfBinB = pdf->binBoundaries(obs,xlo,xhi) ;
1242
1243 // Process hint
1244 if (pdfBinB) {
1245 if (!sumBinB) {
1246
1247 // If this is the first hint, then just save it
1248 sumBinB = pdfBinB ;
1249
1250 } else {
1251
1252 list<Double_t>* newSumBinB = new list<Double_t>(sumBinB->size()+pdfBinB->size()) ;
1253
1254 // Merge hints into temporary array
1255 merge(pdfBinB->begin(),pdfBinB->end(),sumBinB->begin(),sumBinB->end(),newSumBinB->begin()) ;
1256
1257 // Copy merged array without duplicates to new sumBinBArrau
1258 delete sumBinB ;
1259 delete pdfBinB ;
1260 sumBinB = newSumBinB ;
1261 needClean = kTRUE ;
1262 }
1263 }
1264 }
1265
1266 // Remove consecutive duplicates
1267 if (needClean) {
1268 list<Double_t>::iterator new_end = unique(sumBinB->begin(),sumBinB->end()) ;
1269 sumBinB->erase(new_end,sumBinB->end()) ;
1270 }
1271
1272 return sumBinB ;
1273}
1274
1275
1276////////////////////////////////////////////////////////////////////////////////
1277/// If all components that depend on obs are binned that so is the product
1278
1280{
1281 for (const auto arg : _pdfList) {
1282 auto pdf = static_cast<const RooAbsPdf*>(arg);
1283 if (pdf->dependsOn(obs) && !pdf->isBinnedDistribution(obs)) {
1284 return kFALSE ;
1285 }
1286 }
1287
1288 return kTRUE ;
1289}
1290
1291
1292////////////////////////////////////////////////////////////////////////////////
1293/// Label OK'ed components of a RooAddPdf with cache-and-track
1294
1296{
1297 RooFIter aiter = pdfList().fwdIterator() ;
1298 RooAbsArg* aarg ;
1299 while ((aarg=aiter.next())) {
1300 if (aarg->canNodeBeCached()==Always) {
1301 trackNodes.add(*aarg) ;
1302 //cout << "tracking node RooAddPdf component " << aarg->IsA()->GetName() << "::" << aarg->GetName() << endl ;
1303 }
1304 }
1305}
1306
1307
1308
1309////////////////////////////////////////////////////////////////////////////////
1310/// Customized printing of arguments of a RooAddPdf to more intuitively reflect the contents of the
1311/// product operator construction
1312
1313void RooAddPdf::printMetaArgs(ostream& os) const
1314{
1315 Bool_t first(kTRUE) ;
1316
1317 if (_coefList.getSize() != 0) {
1318 for (int i = 0; i < _pdfList.getSize(); ++i ) {
1319 const RooAbsArg * coef = _coefList.at(i);
1320 const RooAbsArg * pdf = _pdfList.at(i);
1321 if (!first) {
1322 os << " + " ;
1323 } else {
1324 first = kFALSE ;
1325 }
1326
1327 if (i < _coefList.getSize()) {
1328 os << coef->GetName() << " * " << pdf->GetName();
1329 } else {
1330 os << "[%] * " << pdf->GetName();
1331 }
1332 }
1333 } else {
1334
1335 for (const auto pdf : _pdfList) {
1336 if (!first) {
1337 os << " + " ;
1338 } else {
1339 first = kFALSE ;
1340 }
1341 os << pdf->GetName() ;
1342 }
1343 }
1344
1345 os << " " ;
1346}
#define e(i)
Definition: RSha256.hxx:103
#define cxcoutD(a)
Definition: RooMsgService.h:81
#define coutW(a)
Definition: RooMsgService.h:32
#define dologD(a)
Definition: RooMsgService.h:65
#define coutE(a)
Definition: RooMsgService.h:33
#define ccoutD(a)
Definition: RooMsgService.h:37
#define TRACE_DESTROY
Definition: RooTrace.h:23
#define TRACE_CREATE
Definition: RooTrace.h:22
const Bool_t kFALSE
Definition: RtypesCore.h:90
const Bool_t kTRUE
Definition: RtypesCore.h:89
#define ClassImp(name)
Definition: Rtypes.h:361
char name[80]
Definition: TGX11.cxx:109
char * Form(const char *fmt,...)
RooSpan< double > makeWritableBatchInit(std::size_t begin, std::size_t batchSize, double value, const RooArgSet *const normSet=nullptr, Tag_t ownerTag=kUnspecified)
Make a batch and return a span pointing to the pdf-local memory.
Definition: BatchData.cxx:148
const std::vector< Int_t > & retrieve(Int_t masterCode) const
Retrieve the array of integer codes associated with the given master code.
Int_t store(const std::vector< Int_t > &codeList, RooArgSet *set1=0, RooArgSet *set2=0, RooArgSet *set3=0, RooArgSet *set4=0)
Store given arrays of integer codes, and up to four RooArgSets in the registry (each setX pointer may...
RooAbsArg is the common abstract base class for objects that represent a value (of arbitrary type) an...
Definition: RooAbsArg.h:73
RooArgSet * getObservables(const RooArgSet &set, Bool_t valueOnly=kTRUE) const
Return the observables of this pdf given a set of observables.
Definition: RooAbsArg.h:276
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:730
virtual CacheMode canNodeBeCached() const
Definition: RooAbsArg.h:392
friend class RooArgSet
Definition: RooAbsArg.h:572
void setOperMode(OperMode mode, Bool_t recurseADirty=kTRUE)
Change cache operation mode to given mode.
Definition: RooAbsArg.cxx:1718
Bool_t addOwnedComponents(const RooArgSet &comps)
Take ownership of the contents of 'comps'.
Definition: RooAbsArg.cxx:2107
OperMode operMode() const
Definition: RooAbsArg.h:474
Int_t getSize() const
virtual Bool_t addOwned(RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
RooFIter fwdIterator() const
One-time forward iterator.
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
Storage_t::size_type size() const
RooAbsArg * first() const
virtual void Print(Option_t *options=0) const
This method must be overridden when a class wants to print itself.
Bool_t equals(const RooAbsCollection &otherColl) const
Check if this and other collection have identically-named contents.
const char * GetName() const
Returns name of object.
virtual Bool_t remove(const RooAbsArg &var, Bool_t silent=kFALSE, Bool_t matchByNameOnly=kFALSE)
Remove the specified argument from our list.
TIterator * createIterator(Bool_t dir=kIterForward) const
TIterator-style iteration over contained elements.
RooAbsArg * find(const char *name) const
Find object with given name in list.
RooAbsGenContext is the abstract base class for generator contexts of RooAbsPdf objects.
friend class CacheElem
Definition: RooAbsPdf.h:333
virtual void resetErrorCounters(Int_t resetValue=10)
Reset error counter to given value, limiting the number of future error messages for this pdf to 'res...
Definition: RooAbsPdf.cxx:622
TString _normRange
MC generator configuration specific for this object.
Definition: RooAbsPdf.h:354
friend class RooRealIntegral
Definition: RooAbsPdf.h:313
Int_t _errorCount
Definition: RooAbsPdf.h:343
RooSpan< const double > getValBatch(std::size_t begin, std::size_t batchSize, const RooArgSet *normSet=nullptr) const final
Compute batch of values for given range, and normalise by integrating over the observables in nset.
Definition: RooAbsPdf.cxx:347
virtual Double_t expectedEvents(const RooArgSet *nset) const
Return expected number of events from this p.d.f for use in extended likelihood calculations.
Definition: RooAbsPdf.cxx:3283
RooArgSet * _normSet
Normalization integral (owned by _normMgr)
Definition: RooAbsPdf.h:321
static Int_t _verboseEval
Definition: RooAbsPdf.h:314
RooAbsRealLValue is the common abstract base class for objects that represent a real value that may a...
virtual Double_t getMax(const char *name=0) const
Get maximum of currently defined range.
virtual Double_t getMin(const char *name=0) const
Get miniminum of currently defined range.
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition: RooAbsReal.h:60
virtual std::list< Double_t > * plotSamplingHint(RooAbsRealLValue &, Double_t, Double_t) const
Definition: RooAbsReal.h:314
virtual std::list< Double_t > * binBoundaries(RooAbsRealLValue &, Double_t, Double_t) const
Definition: RooAbsReal.h:313
Double_t getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition: RooAbsReal.h:90
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:560
BatchHelpers::BatchData _batchData
Definition: RooAbsReal.h:450
Transient cache with transformed values of coefficients.
Definition: RooAddPdf.h:105
virtual RooArgList containedArgs(Action)
List all RooAbsArg derived contents in this cache element.
Definition: RooAddPdf.cxx:1172
RooArgList _rangeProjList
Definition: RooAddPdf.h:115
RooArgList _refRangeProjList
Definition: RooAddPdf.h:114
RooArgList _projList
Definition: RooAddPdf.h:112
RooArgList _suppNormList
Definition: RooAddPdf.h:107
RooArgList _suppProjList
Definition: RooAddPdf.h:113
RooAddPdf is an efficient implementation of a sum of PDFs of the form.
Definition: RooAddPdf.h:29
RooListProxy _coefList
Definition: RooAddPdf.h:137
virtual void resetErrorCounters(Int_t resetValue=10)
Reset error counter to given value, limiting the number of future error messages for this pdf to 'res...
Definition: RooAddPdf.cxx:886
friend class RooAddGenContext
Definition: RooAddPdf.h:125
virtual void setCacheAndTrackHints(RooArgSet &)
Label OK'ed components of a RooAddPdf with cache-and-track.
Definition: RooAddPdf.cxx:1295
virtual Double_t expectedEvents(const RooArgSet *nset) const
Return the number of expected events, which is either the sum of all coefficients or the sum of the c...
Definition: RooAddPdf.cxx:1054
RooAICRegistry _codeReg
Definition: RooAddPdf.h:134
Bool_t isBinnedDistribution(const RooArgSet &obs) const
If all components that depend on obs are binned that so is the product.
Definition: RooAddPdf.cxx:1279
virtual RooSpan< double > evaluateBatch(std::size_t begin, std::size_t batchSize) const
Compute addition of PDFs in batches.
Definition: RooAddPdf.cxx:852
Int_t _coefErrCount
Definition: RooAddPdf.h:144
Bool_t _allExtendable
Definition: RooAddPdf.h:141
virtual void selectNormalizationRange(const char *rangeName=0, Bool_t force=kFALSE)
Interface function used by test statistics to freeze choice of range for interpretation of fraction c...
Definition: RooAddPdf.cxx:1146
Double_t evaluate() const
Calculate and return the current value.
Definition: RooAddPdf.cxx:820
void updateCoefficients(CacheElem &cache, const RooArgSet *nset) const
Update the coefficient values in the given cache element: calculate new remainder fraction,...
Definition: RooAddPdf.cxx:665
virtual ~RooAddPdf()
Destructor.
Definition: RooAddPdf.cxx:359
CacheElem * getProjCache(const RooArgSet *nset, const RooArgSet *iset=0, const char *rangeName=0) const
Retrieve cache element for the computation of the PDF normalisation.
Definition: RooAddPdf.cxx:422
std::pair< const RooArgSet *, CacheElem * > getNormAndCache() const
Coefficient error counter.
Definition: RooAddPdf.cxx:800
RooObjCacheManager _projCacheMgr
Definition: RooAddPdf.h:120
void printMetaArgs(std::ostream &os) const
Customized printing of arguments of a RooAddPdf to more intuitively reflect the contents of the produ...
Definition: RooAddPdf.cxx:1313
RooAddPdf()
Default constructor used for persistence.
Definition: RooAddPdf.cxx:98
virtual std::list< Double_t > * plotSamplingHint(RooAbsRealLValue &obs, Double_t xlo, Double_t xhi) const
Loop over components for plot sampling hints and merge them if there are multiple.
Definition: RooAddPdf.cxx:1188
virtual std::list< Double_t > * binBoundaries(RooAbsRealLValue &, Double_t, Double_t) const
Loop over components for plot sampling hints and merge them if there are multiple.
Definition: RooAddPdf.cxx:1233
void fixCoefNormalization(const RooArgSet &refCoefNorm)
By default the interpretation of the fraction coefficients is performed in the contextual choice of o...
Definition: RooAddPdf.cxx:376
virtual RooAbsGenContext * genContext(const RooArgSet &vars, const RooDataSet *prototype=0, const RooArgSet *auxProto=0, Bool_t verbose=kFALSE) const
Return specialized context to efficiently generate toy events from RooAddPdfs return RooAbsPdf::genCo...
Definition: RooAddPdf.cxx:1161
RooSetProxy _refCoefNorm
Definition: RooAddPdf.h:98
Double_t analyticalIntegralWN(Int_t code, const RooArgSet *normSet, const char *rangeName=0) const
Return analytical integral defined by given scenario code.
Definition: RooAddPdf.cxx:997
virtual void selectNormalization(const RooArgSet *depSet=0, Bool_t force=kFALSE)
Interface function used by test statistics to freeze choice of observables for interpretation of frac...
Definition: RooAddPdf.cxx:1123
void fixCoefRange(const char *rangeName)
By default, fraction coefficients are assumed to refer to the default fit range.
Definition: RooAddPdf.cxx:403
RooListProxy _pdfList
Registry of component analytical integration codes.
Definition: RooAddPdf.h:136
TNamed * _refCoefRangeName
Definition: RooAddPdf.h:99
const RooArgList & pdfList() const
Definition: RooAddPdf.h:67
Int_t getAnalyticalIntegralWN(RooArgSet &allVars, RooArgSet &numVars, const RooArgSet *normSet, const char *rangeName=0) const
Determine which part (if any) of given integral can be performed analytically.
Definition: RooAddPdf.cxx:929
Bool_t _projectCoefs
Definition: RooAddPdf.h:101
std::vector< double > _coefCache
Definition: RooAddPdf.h:102
Bool_t _haveLastCoef
List of supplemental normalization factors.
Definition: RooAddPdf.h:140
virtual Bool_t checkObservables(const RooArgSet *nset) const
Check if PDF is valid for given normalization set.
Definition: RooAddPdf.cxx:899
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgList.h:21
RooAbsArg * at(Int_t idx) const
Return object at given index, or nullptr if index is out of range.
Definition: RooArgList.h:74
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgSet.h:28
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:88
T * getObj(const RooArgSet *nset, Int_t *sterileIndex=0, const TNamed *isetRangeName=0)
void reset()
Clear the cache.
Int_t setObj(const RooArgSet *nset, T *obj, const TNamed *isetRangeName=0)
RooDataSet is a container class to hold unbinned data.
Definition: RooDataSet.h:33
A one-time forward iterator working on RooLinkedList or RooAbsCollection.
RooAbsArg * next()
Return next element or nullptr if at end.
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Reimplementation of standard RooArgList::add()
static RooMsgService & instance()
Return reference to singleton instance.
static Int_t _debugCount
Bool_t isActive(const RooAbsArg *self, RooFit::MsgTopic facility, RooFit::MsgLevel level)
Check if logging is active for given object/topic/RooFit::MsgLevel combination.
static const char * str(const TNamed *ptr)
Return C++ string corresponding to given TNamed pointer.
Definition: RooNameReg.cxx:103
static const TNamed * ptr(const char *stringPtr)
Return a unique TNamed pointer for given C++ string.
Definition: RooNameReg.cxx:93
static RooConstVar & value(Double_t value)
Return a constant value object with given value.
RooRealVar represents a variable that can be changed from the outside.
Definition: RooRealVar.h:35
Class RooRecursiveFraction is a RooAbsReal implementation that calculates the plain fraction of sum o...
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Overloaded RooArgSet::add() method inserts 'var' into set and registers 'var' as server to owner with...
virtual void removeAll()
Remove all argument inset using remove(const RooAbsArg&).
A simple container to hold a batch of data values.
Definition: RooSpan.h:32
Iterator abstract base class.
Definition: TIterator.h:30
virtual TObject * Next()=0
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
const char * Data() const
Definition: TString.h:364
TString & Append(const char *cs)
Definition: TString.h:559
RooConstVar & RooConst(Double_t val)
const Int_t n
Definition: legend1.C:16
for(Int_t i=0;i< n;i++)
Definition: legend1.C:18
@ InputArguments
Definition: RooGlobalFunc.h:68
Definition: first.py:1
static void output(int code)
Definition: gifencode.c:226