Logo ROOT  
Reference Guide
RooProdPdf.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 RooProdPdf.cxx
19\class RooProdPdf
20\ingroup Roofitcore
21
22RooProdPdf is an efficient implementation of a product of PDFs of the form
23\f[ \prod_{i=1}^{N} \mathrm{PDF}_i (x, \ldots) \f]
24
25PDFs may share observables. If that is the case any irreducible subset
26of PDFs that share observables will be normalised with explicit numeric
27integration as any built-in normalisation will no longer be valid.
28
29Alternatively, products using conditional PDFs can be defined, *e.g.*
30
31\f[ F(x|y) \cdot G(y), \f]
32
33meaning a PDF \f$ F(x) \f$ **given** \f$ y \f$ and a PDF \f$ G(y) \f$.
34In this construction, \f$ F \f$ is only
35normalised w.r.t \f$ x\f$, and \f$ G \f$ is normalised w.r.t \f$ y \f$. The product in this construction
36is properly normalised.
37
38If exactly one of the component PDFs supports extended likelihood fits, the
39product will also be usable in extended mode, returning the number of expected
40events from the extendable component PDF. The extendable component does not
41have to appear in any specific place in the list.
42**/
43
44#include "RooProdPdf.h"
45#include "RooRealProxy.h"
46#include "RooProdGenContext.h"
47#include "RooGenProdProj.h"
48#include "RooProduct.h"
49#include "RooNameReg.h"
50#include "RooMsgService.h"
51#include "RooFormulaVar.h"
52#include "RooRealVar.h"
53#include "RooAddition.h"
54#include "RooGlobalFunc.h"
55#include "RooConstVar.h"
56#include "RooWorkspace.h"
57#include "RooRangeBoolean.h"
58#include "RooCustomizer.h"
59#include "RooRealIntegral.h"
60#include "RooTrace.h"
61
62#include <cstring>
63#include <sstream>
64#include <algorithm>
65
66#ifndef _WIN32
67#include <strings.h>
68#endif
69
70
71#include "TSystem.h"
72
73using namespace std;
74
76;
77
78
79
80////////////////////////////////////////////////////////////////////////////////
81/// Default constructor
82
84 _curNormSet(0),
85 _cutOff(0),
86 _extendedIndex(-1),
87 _useDefaultGen(kFALSE),
88 _refRangeName(0),
89 _selfNorm(kTRUE)
90{
91 // Default constructor
93}
94
95
96
97////////////////////////////////////////////////////////////////////////////////
98/// Dummy constructor
99
100RooProdPdf::RooProdPdf(const char *name, const char *title, Double_t cutOff) :
101 RooAbsPdf(name,title),
102 _cacheMgr(this,10),
103 _genCode(10),
104 _cutOff(cutOff),
105 _pdfList("!pdfs","List of PDFs",this),
106 _extendedIndex(-1),
107 _useDefaultGen(kFALSE),
108 _refRangeName(0),
109 _selfNorm(kTRUE)
110{
112}
113
114
115
116////////////////////////////////////////////////////////////////////////////////
117/// Constructor with 2 PDFs (most frequent use case).
118///
119/// The optional cutOff parameter can be used as a speed optimization if
120/// one or more of the PDF have sizable regions with very small values,
121/// which would pull the entire product of PDFs to zero in those regions.
122///
123/// After each PDF multiplication, the running product is compared with
124/// the cutOff parameter. If the running product is smaller than the
125/// cutOff value, the product series is terminated and remaining PDFs
126/// are not evaluated.
127///
128/// There is no magic value of the cutOff, the user should experiment
129/// to find the appropriate balance between speed and precision.
130/// If a cutoff is specified, the PDFs most likely to be small should
131/// be put first in the product. The default cutOff value is zero.
132///
133
134RooProdPdf::RooProdPdf(const char *name, const char *title,
135 RooAbsPdf& pdf1, RooAbsPdf& pdf2, Double_t cutOff) :
136 RooAbsPdf(name,title),
137 _cacheMgr(this,10),
138 _genCode(10),
139 _cutOff(cutOff),
140 _pdfList("!pdfs","List of PDFs",this),
141 _extendedIndex(-1),
142 _useDefaultGen(kFALSE),
143 _refRangeName(0),
144 _selfNorm(kTRUE)
145{
146 _pdfList.add(pdf1) ;
147 RooArgSet* nset1 = new RooArgSet("nset") ;
148 _pdfNSetList.Add(nset1) ;
149 if (pdf1.canBeExtended()) {
150 _extendedIndex = _pdfList.index(&pdf1) ;
151 }
152
153 _pdfList.add(pdf2) ;
154 RooArgSet* nset2 = new RooArgSet("nset") ;
155 _pdfNSetList.Add(nset2) ;
156
157 if (pdf2.canBeExtended()) {
158 if (_extendedIndex>=0) {
159 // Protect against multiple extended terms
160 coutW(InputArguments) << "RooProdPdf::RooProdPdf(" << GetName()
161 << ") multiple components with extended terms detected,"
162 << " product will not be extendible." << endl ;
163 _extendedIndex=-1 ;
164 } else {
166 }
167 }
169}
170
171
172
173////////////////////////////////////////////////////////////////////////////////
174/// Constructor from a list of PDFs.
175///
176/// The optional cutOff parameter can be used as a speed optimization if
177/// one or more of the PDF have sizable regions with very small values,
178/// which would pull the entire product of PDFs to zero in those regions.
179///
180/// After each PDF multiplication, the running product is compared with
181/// the cutOff parameter. If the running product is smaller than the
182/// cutOff value, the product series is terminated and remaining PDFs
183/// are not evaluated.
184///
185/// There is no magic value of the cutOff, the user should experiment
186/// to find the appropriate balance between speed and precision.
187/// If a cutoff is specified, the PDFs most likely to be small should
188/// be put first in the product. The default cutOff value is zero.
189
190RooProdPdf::RooProdPdf(const char* name, const char* title, const RooArgList& inPdfList, Double_t cutOff) :
191 RooAbsPdf(name,title),
192 _cacheMgr(this,10),
193 _genCode(10),
194 _cutOff(cutOff),
195 _pdfList("!pdfs","List of PDFs",this),
196 _extendedIndex(-1),
197 _useDefaultGen(kFALSE),
198 _refRangeName(0),
199 _selfNorm(kTRUE)
200{
201 RooFIter iter = inPdfList.fwdIterator();
202 RooAbsArg* arg ;
203 Int_t numExtended(0) ;
204 while((arg=(RooAbsArg*)iter.next())) {
205 RooAbsPdf* pdf = dynamic_cast<RooAbsPdf*>(arg) ;
206 if (!pdf) {
207 coutW(InputArguments) << "RooProdPdf::RooProdPdf(" << GetName() << ") list arg "
208 << arg->GetName() << " is not a PDF, ignored" << endl ;
209 continue ;
210 }
211 _pdfList.add(*pdf) ;
212
213 RooArgSet* nset = new RooArgSet("nset") ;
214 _pdfNSetList.Add(nset) ;
215
216 if (pdf->canBeExtended()) {
218 numExtended++ ;
219 }
220 }
221
222 // Protect against multiple extended terms
223 if (numExtended>1) {
224 coutW(InputArguments) << "RooProdPdf::RooProdPdf(" << GetName()
225 << ") WARNING: multiple components with extended terms detected,"
226 << " product will not be extendible." << endl ;
227 _extendedIndex = -1 ;
228 }
229
231}
232
233
234
235////////////////////////////////////////////////////////////////////////////////
236/// Constructor from named argument list.
237/// \param[in] name Name used by RooFit
238/// \param[in] title Title used for plotting
239/// \param[in] fullPdfSet Set of "regular" PDFs that are normalised over all their observables
240/// \param[in] argX Optional arguments according to table below.
241///
242/// <table>
243/// <tr><th> Argument <th> Description
244/// <tr><td> `Conditional(pdfSet,depSet)` <td> Add PDF to product with condition that it
245/// only be normalized over specified observables. Any remaining observables will be conditional observables.
246/// </table>
247///
248/// For example, given a PDF \f$ F(x,y) \f$ and \f$ G(y) \f$,
249///
250/// `RooProdPdf("P", "P", G, Conditional(F,x))` will construct a 2-dimensional PDF as follows:
251/// \f[
252/// P(x,y) = \frac{G(y)}{\int_y G(y)} \cdot \frac{F(x,y)}{\int_x F(x,y)},
253/// \f]
254///
255/// which is a well normalised and properly defined PDF, but different from
256/// \f[
257/// P'(x,y) = \frac{F(x,y) \cdot G(y)}{\int_x\int_y F(x,y) \cdot G(y)}.
258/// \f]
259///
260/// In the former case, the \f$ y \f$ distribution of \f$ P \f$ is identical to that of \f$ G \f$, while
261/// \f$ F \f$ only is used to determine the correlation between \f$ X \f$ and \f$ Y \f$. In the latter
262/// case, the \f$ Y \f$ distribution is defined by the product of \f$ F \f$ and \f$ G \f$.
263///
264/// This \f$ P(x,y) \f$ construction is analoguous to generating events from \f$ F(x,y) \f$ with
265/// a prototype dataset sampled from \f$ G(y) \f$.
266
267RooProdPdf::RooProdPdf(const char* name, const char* title, const RooArgSet& fullPdfSet,
268 const RooCmdArg& arg1, const RooCmdArg& arg2,
269 const RooCmdArg& arg3, const RooCmdArg& arg4,
270 const RooCmdArg& arg5, const RooCmdArg& arg6,
271 const RooCmdArg& arg7, const RooCmdArg& arg8) :
272 RooAbsPdf(name,title),
273 _cacheMgr(this,10),
274 _genCode(10),
275 _cutOff(0),
276 _pdfList("!pdfs","List of PDFs",this),
277 _extendedIndex(-1),
278 _useDefaultGen(kFALSE),
279 _refRangeName(0),
280 _selfNorm(kTRUE)
281{
283 l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
284 l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
285 l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
286 l.Add((TObject*)&arg7) ; l.Add((TObject*)&arg8) ;
287
288 initializeFromCmdArgList(fullPdfSet,l) ;
290}
291
292
293
294////////////////////////////////////////////////////////////////////////////////
295/// Constructor from named argument list
296
297RooProdPdf::RooProdPdf(const char* name, const char* title,
298 const RooCmdArg& arg1, const RooCmdArg& arg2,
299 const RooCmdArg& arg3, const RooCmdArg& arg4,
300 const RooCmdArg& arg5, const RooCmdArg& arg6,
301 const RooCmdArg& arg7, const RooCmdArg& arg8) :
302 RooAbsPdf(name,title),
303 _cacheMgr(this,10),
304 _genCode(10),
305 _cutOff(0),
306 _pdfList("!pdfList","List of PDFs",this),
307 _extendedIndex(-1),
308 _useDefaultGen(kFALSE),
309 _refRangeName(0),
310 _selfNorm(kTRUE)
311{
313 l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
314 l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
315 l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
316 l.Add((TObject*)&arg7) ; l.Add((TObject*)&arg8) ;
317
320}
321
322
323
324////////////////////////////////////////////////////////////////////////////////
325/// Internal constructor from list of named arguments
326
327RooProdPdf::RooProdPdf(const char* name, const char* title, const RooArgSet& fullPdfSet, const RooLinkedList& cmdArgList) :
328 RooAbsPdf(name,title),
329 _cacheMgr(this,10),
330 _genCode(10),
331 _cutOff(0),
332 _pdfList("!pdfs","List of PDFs",this),
333 _extendedIndex(-1),
334 _useDefaultGen(kFALSE),
335 _refRangeName(0),
336 _selfNorm(kTRUE)
337{
338 initializeFromCmdArgList(fullPdfSet, cmdArgList) ;
340}
341
342
343
344////////////////////////////////////////////////////////////////////////////////
345/// Copy constructor
346
347RooProdPdf::RooProdPdf(const RooProdPdf& other, const char* name) :
348 RooAbsPdf(other,name),
349 _cacheMgr(other._cacheMgr,this),
350 _genCode(other._genCode),
351 _cutOff(other._cutOff),
352 _pdfList("!pdfs",this,other._pdfList),
353 _extendedIndex(other._extendedIndex),
354 _useDefaultGen(other._useDefaultGen),
355 _refRangeName(other._refRangeName),
356 _selfNorm(other._selfNorm),
357 _defNormSet(other._defNormSet)
358{
359 // Clone contents of normalizarion set list
360 RooFIter iter = other._pdfNSetList.fwdIterator();
361 RooArgSet* nset ;
362 while((nset=(RooArgSet*)iter.next())) {
363 RooArgSet* tmp = (RooArgSet*) nset->snapshot() ;
364 tmp->setName(nset->GetName()) ;
365 _pdfNSetList.Add(tmp) ;
366 }
368}
369
370
371
372////////////////////////////////////////////////////////////////////////////////
373/// Initialize RooProdPdf configuration from given list of RooCmdArg configuration arguments
374/// and set of 'regular' p.d.f.s in product
375
377{
378 Int_t numExtended(0) ;
379
380 // Process set of full PDFS
381 RooFIter siter = fullPdfSet.fwdIterator() ;
382 RooAbsPdf* pdf ;
383 while((pdf=(RooAbsPdf*)siter.next())) {
384 _pdfList.add(*pdf) ;
385 RooArgSet* nset1 = new RooArgSet("nset") ;
386 _pdfNSetList.Add(nset1) ;
387
388 if (pdf->canBeExtended()) {
390 numExtended++ ;
391 }
392
393 }
394
395 // Process list of conditional PDFs
396 RooFIter iter = l.fwdIterator();
397 RooCmdArg* carg ;
398 while((carg=(RooCmdArg*)iter.next())) {
399
400 if (0 == strcmp(carg->GetName(), "Conditional")) {
401
402 Int_t argType = carg->getInt(0) ;
403 RooArgSet* pdfSet = (RooArgSet*) carg->getSet(0) ;
404 RooArgSet* normSet = (RooArgSet*) carg->getSet(1) ;
405
406 RooFIter siter2 = pdfSet->fwdIterator() ;
407 RooAbsPdf* thePdf ;
408 while ((thePdf=(RooAbsPdf*)siter2.next())) {
409 _pdfList.add(*thePdf) ;
410
411 RooArgSet* tmp = (RooArgSet*) normSet->snapshot() ;
412 tmp->setName(0 == argType ? "nset" : "cset") ;
413 _pdfNSetList.Add(tmp) ;
414
415 if (thePdf->canBeExtended()) {
416 _extendedIndex = _pdfList.index(thePdf) ;
417 numExtended++ ;
418 }
419
420 }
421
422 } else if (0 != strlen(carg->GetName())) {
423 coutW(InputArguments) << "Unknown arg: " << carg->GetName() << endl ;
424 }
425 }
426
427 // Protect against multiple extended terms
428 if (numExtended>1) {
429 coutW(InputArguments) << "RooProdPdf::RooProdPdf(" << GetName()
430 << ") WARNING: multiple components with extended terms detected,"
431 << " product will not be extendible." << endl ;
432 _extendedIndex = -1 ;
433 }
434
435
436}
437
438
439
440////////////////////////////////////////////////////////////////////////////////
441/// Destructor
442
444{
447}
448
449
450
451////////////////////////////////////////////////////////////////////////////////
452/// Overload getVal() to intercept normalization set for use in evaluate()
453
455{
456 _curNormSet = (RooArgSet*)set ;
457 return RooAbsPdf::getValV(set) ;
458}
459
460
461
462////////////////////////////////////////////////////////////////////////////////
463/// Calculate current value of object
464
466{
467 Int_t code ;
468 CacheElem* cache = (CacheElem*) _cacheMgr.getObj(_curNormSet,0,&code) ;
469
470 // If cache doesn't have our configuration, recalculate here
471 if (!cache) {
472 code = getPartIntList(_curNormSet, nullptr) ;
473 cache = (CacheElem*) _cacheMgr.getObj(_curNormSet,0,&code) ;
474 }
475
476
477 return calculate(*cache) ;
478}
479
480
481
482////////////////////////////////////////////////////////////////////////////////
483/// Calculate running product of pdfs terms, using the supplied
484/// normalization set in 'normSetList' for each component
485
487{
488 //cout << "RooProdPdf::calculate from cache" << endl ;
489
490 if (cache._isRearranged) {
491 if (dologD(Eval)) {
492 cxcoutD(Eval) << "RooProdPdf::calculate(" << GetName() << ") rearranged product calculation"
493 << " calculate: num = " << cache._rearrangedNum->GetName() << " = " << cache._rearrangedNum->getVal() << endl ;
494// cache._rearrangedNum->printComponentTree("",0,5) ;
495 cxcoutD(Eval) << "calculate: den = " << cache._rearrangedDen->GetName() << " = " << cache._rearrangedDen->getVal() << endl ;
496// cache._rearrangedDen->printComponentTree("",0,5) ;
497 }
498
499 return cache._rearrangedNum->getVal() / cache._rearrangedDen->getVal();
500 } else {
501
502 Double_t value = 1.0;
503 assert(cache._normList.size() == cache._partList.size());
504 for (std::size_t i = 0; i < cache._partList.size(); ++i) {
505 const auto& partInt = static_cast<const RooAbsReal&>(cache._partList[i]);
506 const auto normSet = cache._normList[i].get();
507
508 const Double_t piVal = partInt.getVal(normSet->getSize() > 0 ? normSet : nullptr);
509 value *= piVal ;
510 if (value <= _cutOff) break;
511 }
512
513 return value ;
514 }
515}
516
517RooSpan<double> RooProdPdf::evaluateBatch(std::size_t begin, std::size_t size) const {
518 int code;
519 auto cache = static_cast<CacheElem*>(_cacheMgr.getObj(_curNormSet, nullptr, &code));
520
521 // If cache doesn't have our configuration, recalculate here
522 if (!cache) {
523 code = getPartIntList(_curNormSet, nullptr);
524 cache = static_cast<CacheElem*>(_cacheMgr.getObj(_curNormSet, nullptr, &code));
525 }
526
527 if (cache->_isRearranged) {
528 if (dologD(Eval)) {
529 cxcoutD(Eval) << "RooProdPdf::calculate(" << GetName() << ") rearranged product calculation"
530 << " calculate: num = " << cache->_rearrangedNum->GetName() << " = " << cache->_rearrangedNum->getVal() << endl ;
531 cxcoutD(Eval) << "calculate: den = " << cache->_rearrangedDen->GetName() << " = " << cache->_rearrangedDen->getVal() << endl ;
532 }
533
534 auto outputs = _batchData.makeWritableBatchUnInit(begin, size);
535 auto numerator = cache->_rearrangedNum->getValBatch(begin, size);
536 auto denominator = cache->_rearrangedDen->getValBatch(begin, size);
537
538 for (std::size_t i=0; i < outputs.size(); ++i) {
539 outputs[i] = numerator[i] / denominator[i];
540 }
541
542 return outputs;
543 } else {
544
545 auto outputs = _batchData.makeWritableBatchInit(begin, size, 1.);
546 assert(cache->_normList.size() == cache->_partList.size());
547 for (std::size_t i = 0; i < cache->_partList.size(); ++i) {
548 const auto& partInt = static_cast<const RooAbsReal&>(cache->_partList[i]);
549 const auto normSet = cache->_normList[i].get();
550
551 const auto partialInts = partInt.getValBatch(begin, size, normSet->getSize() > 0 ? normSet : nullptr);
552 for (std::size_t j=0; j < outputs.size(); ++j) {
553 outputs[j] *= partialInts[j];
554 }
555 }
556
557 return outputs;
558 }
559}
560
561
562
563////////////////////////////////////////////////////////////////////////////////
564/// Factorize product in irreducible terms for given choice of integration/normalization
565
566void RooProdPdf::factorizeProduct(const RooArgSet& normSet, const RooArgSet& intSet,
567 RooLinkedList& termList, RooLinkedList& normList,
568 RooLinkedList& impDepList, RooLinkedList& crossDepList,
569 RooLinkedList& intList) const
570{
571 // List of all term dependents: normalization and imported
572 RooLinkedList depAllList;
573 RooLinkedList depIntNoNormList;
574
575 // Setup lists for factorization terms and their dependents
576 RooArgSet* term(0);
577 RooArgSet* termNormDeps(0);
578 RooArgSet* termAllDeps(0);
579 RooArgSet* termIntDeps(0);
580 RooArgSet* termIntNoNormDeps(0);
581
582 // Loop over the PDFs
583 RooAbsPdf* pdf;
584 RooArgSet* pdfNSetOrig;
585 for (RooFIter pdfIter = _pdfList.fwdIterator(),
586 nIter = _pdfNSetList.fwdIterator();
587 (pdfNSetOrig = (RooArgSet*) nIter.next(),
588 pdf = (RooAbsPdf*) pdfIter.next()); ) {
589 RooArgSet* pdfNSet, *pdfCSet;
590
591 // Reduce pdfNSet to actual dependents
592 if (0 == strcmp("nset", pdfNSetOrig->GetName())) {
593 pdfNSet = pdf->getObservables(*pdfNSetOrig);
594 pdfCSet = new RooArgSet;
595 } else if (0 == strcmp("cset", pdfNSetOrig->GetName())) {
596 RooArgSet* tmp = pdf->getObservables(normSet);
597 tmp->remove(*pdfNSetOrig, kTRUE, kTRUE);
598 pdfCSet = pdfNSetOrig;
599 pdfNSet = tmp;
600 } else {
601 // Legacy mode. Interpret at NSet for backward compatibility
602 pdfNSet = pdf->getObservables(*pdfNSetOrig);
603 pdfCSet = new RooArgSet;
604 }
605
606
607 RooArgSet pdfNormDeps; // Dependents to be normalized for the PDF
608 RooArgSet pdfAllDeps; // All dependents of this PDF
609
610 // Make list of all dependents of this PDF
611 RooArgSet* tmp = pdf->getObservables(normSet);
612 pdfAllDeps.add(*tmp);
613 delete tmp;
614
615
616// cout << GetName() << ": pdf = " << pdf->GetName() << " pdfAllDeps = " << pdfAllDeps << " pdfNSet = " << *pdfNSet << " pdfCSet = " << *pdfCSet << endl;
617
618 // Make list of normalization dependents for this PDF;
619 if (pdfNSet->getSize() > 0) {
620 // PDF is conditional
621 RooArgSet* tmp2 = (RooArgSet*) pdfAllDeps.selectCommon(*pdfNSet);
622 pdfNormDeps.add(*tmp2);
623 delete tmp2;
624 } else {
625 // PDF is regular
626 pdfNormDeps.add(pdfAllDeps);
627 }
628
629// cout << GetName() << ": pdfNormDeps for " << pdf->GetName() << " = " << pdfNormDeps << endl;
630
631 RooArgSet* pdfIntSet = pdf->getObservables(intSet) ;
632
633 // WVE if we have no norm deps, conditional observables should be taken out of pdfIntSet
634 if (0 == pdfNormDeps.getSize() && pdfCSet->getSize() > 0) {
635 pdfIntSet->remove(*pdfCSet, kTRUE, kTRUE);
636// cout << GetName() << ": have no norm deps, removing conditional observables from intset" << endl;
637 }
638
639 RooArgSet pdfIntNoNormDeps(*pdfIntSet);
640 pdfIntNoNormDeps.remove(pdfNormDeps, kTRUE, kTRUE);
641
642// cout << GetName() << ": pdf = " << pdf->GetName() << " intset = " << *pdfIntSet << " pdfIntNoNormDeps = " << pdfIntNoNormDeps << endl;
643
644 // Check if this PDF has dependents overlapping with one of the existing terms
645 Bool_t done(kFALSE);
646 for (RooFIter lIter = termList.fwdIterator(),
647 ldIter = normList.fwdIterator(),
648 laIter = depAllList.fwdIterator();
649 (termNormDeps = (RooArgSet*) ldIter.next(),
650 termAllDeps = (RooArgSet*) laIter.next(),
651 term = (RooArgSet*) lIter.next()); ) {
652 // PDF should be added to existing term if
653 // 1) It has overlapping normalization dependents with any other PDF in existing term
654 // 2) It has overlapping dependents of any class for which integration is requested
655 // 3) If normalization happens over multiple ranges, and those ranges are both defined
656 // in either observable
657
658 Bool_t normOverlap = pdfNormDeps.overlaps(*termNormDeps);
659 //Bool_t intOverlap = pdfIntSet->overlaps(*termAllDeps);
660
661 if (normOverlap) {
662// cout << GetName() << ": this term overlaps with term " << (*term) << " in normalization observables" << endl;
663
664 term->add(*pdf);
665 termNormDeps->add(pdfNormDeps, kFALSE);
666 termAllDeps->add(pdfAllDeps, kFALSE);
667 if (!termIntDeps) {
668 termIntDeps = new RooArgSet("termIntDeps");
669 }
670 termIntDeps->add(*pdfIntSet, kFALSE);
671 if (!termIntNoNormDeps) {
672 termIntNoNormDeps = new RooArgSet("termIntNoNormDeps");
673 }
674 termIntNoNormDeps->add(pdfIntNoNormDeps, kFALSE);
675 done = kTRUE;
676 }
677 }
678
679 // If not, create a new term
680 if (!done) {
681 if (!(0 == pdfNormDeps.getSize() && 0 == pdfAllDeps.getSize() &&
682 0 == pdfIntSet->getSize()) || 0 == normSet.getSize()) {
683// cout << GetName() << ": creating new term" << endl;
684 term = new RooArgSet("term");
685 termNormDeps = new RooArgSet("termNormDeps");
686 termAllDeps = new RooArgSet("termAllDeps");
687 termIntDeps = new RooArgSet("termIntDeps");
688 termIntNoNormDeps = new RooArgSet("termIntNoNormDeps");
689
690 term->add(*pdf);
691 termNormDeps->add(pdfNormDeps, kFALSE);
692 termAllDeps->add(pdfAllDeps, kFALSE);
693 termIntDeps->add(*pdfIntSet, kFALSE);
694 termIntNoNormDeps->add(pdfIntNoNormDeps, kFALSE);
695
696 termList.Add(term);
697 normList.Add(termNormDeps);
698 depAllList.Add(termAllDeps);
699 intList.Add(termIntDeps);
700 depIntNoNormList.Add(termIntNoNormDeps);
701 }
702 }
703
704 // We own the reduced version of pdfNSet
705 delete pdfNSet;
706 delete pdfIntSet;
707 if (pdfCSet != pdfNSetOrig) {
708 delete pdfCSet;
709 }
710 }
711
712 // Loop over list of terms again to determine 'imported' observables
713 RooArgSet *normDeps, *allDeps, *intNoNormDeps;
714 for (RooFIter lIter = termList.fwdIterator(),
715 ldIter = normList.fwdIterator(),
716 laIter = depAllList.fwdIterator(),
717 innIter = depIntNoNormList.fwdIterator();
718 (normDeps = (RooArgSet*) ldIter.next(),
719 allDeps = (RooArgSet*) laIter.next(),
720 intNoNormDeps = (RooArgSet*) innIter.next(),
721 term=(RooArgSet*)lIter.next()); ) {
722 // Make list of wholly imported dependents
723 RooArgSet impDeps(*allDeps);
724 impDeps.remove(*normDeps, kTRUE, kTRUE);
725 impDepList.Add(impDeps.snapshot());
726// cout << GetName() << ": list of imported dependents for term " << (*term) << " set to " << impDeps << endl ;
727
728 // Make list of cross dependents (term is self contained for these dependents,
729 // but components import dependents from other components)
730 RooArgSet* crossDeps = (RooArgSet*) intNoNormDeps->selectCommon(*normDeps);
731 crossDepList.Add(crossDeps->snapshot());
732// cout << GetName() << ": list of cross dependents for term " << (*term) << " set to " << *crossDeps << endl ;
733 delete crossDeps;
734 }
735
736 depAllList.Delete();
737 depIntNoNormList.Delete();
738
739 return;
740}
741
742
743
744
745////////////////////////////////////////////////////////////////////////////////
746/// Return list of (partial) integrals of product terms for integration
747/// of p.d.f over observables iset while normalization over observables nset.
748/// Also return list of normalization sets to be used to evaluate
749/// each component in the list correctly.
750
751Int_t RooProdPdf::getPartIntList(const RooArgSet* nset, const RooArgSet* iset, const char* isetRangeName) const
752{
753// cout << " FOLKERT::RooProdPdf::getPartIntList(" << GetName() <<") nset = " << (nset?*nset:RooArgSet()) << endl
754// << " _normRange = " << _normRange << endl
755// << " iset = " << (iset?*iset:RooArgSet()) << endl
756// << " isetRangeName = " << (isetRangeName?isetRangeName:"<null>") << endl ;
757
758 // Check if this configuration was created before
759 Int_t sterileIdx(-1);
760
761 CacheElem* cache = (CacheElem*) _cacheMgr.getObj(nset,iset,&sterileIdx,isetRangeName);
762 if (cache) {
763 return _cacheMgr.lastIndex();
764 }
765
766 // Create containers for partial integral components to be generated
767 cache = new CacheElem;
768
769 // Factorize the product in irreducible terms for this nset
770 RooLinkedList terms, norms, imp, ints, cross;
771// cout << "RooProdPdf::getPIL -- now calling factorizeProduct()" << endl ;
772
773
774 // Normalization set used for factorization
775 RooArgSet factNset(nset ? (*nset) : _defNormSet);
776// cout << GetName() << "factNset = " << factNset << endl ;
777
778 factorizeProduct(factNset, iset ? (*iset) : RooArgSet(), terms, norms, imp, cross, ints);
779
780 RooArgSet *norm, *integ, *xdeps, *imps;
781
782 // Group irriducible terms that need to be (partially) integrated together
783 RooLinkedList groupedList;
784 RooArgSet outerIntDeps;
785// cout << "RooProdPdf::getPIL -- now calling groupProductTerms()" << endl;
786 groupProductTerms(groupedList, outerIntDeps, terms, norms, imp, ints, cross);
787 RooFIter gIter = groupedList.fwdIterator();
789
790 // Loop over groups
791// cout<<"FK: pdf("<<GetName()<<") Starting selecting F(x|y)!"<<endl;
792 // Find groups of type F(x|y), i.e. termImpSet!=0, construct ratio object
793 map<string, RooArgSet> ratioTerms;
794 while ((group = (RooLinkedList*) gIter.next())) {
795 if (1 == group->GetSize()) {
796// cout<<"FK: Starting Single Term"<<endl;
797
798 RooArgSet* term = (RooArgSet*) group->At(0);
799
800 Int_t termIdx = terms.IndexOf(term);
801 norm=(RooArgSet*) norms.At(termIdx);
802 imps=(RooArgSet*)imp.At(termIdx);
803 RooArgSet termNSet(*norm), termImpSet(*imps);
804
805// cout<<"FK: termImpSet.getSize() = "<<termImpSet.getSize()<< " " << termImpSet << endl;
806// cout<<"FK: _refRangeName = "<<_refRangeName<<endl;
807
808 if (termImpSet.getSize() > 0 && 0 != _refRangeName) {
809
810// cout << "WVE now here" << endl;
811
812 // WVE we can skip this if the ref range is equal to the normalization range
813 Bool_t rangeIdentical(kTRUE);
814 RooFIter niter = termNSet.fwdIterator();
815 RooRealVar* normObs;
816// cout << "_normRange = " << _normRange << " _refRangeName = " << RooNameReg::str(_refRangeName) << endl ;
817 while ((normObs = (RooRealVar*) niter.next())) {
818 //FK: Here the refRange should be compared to _normRange, if it's set, and to the normObs range if it's not set
819 if (_normRange.Length() > 0) {
820 if (normObs->getMin(_normRange.Data()) != normObs->getMin(RooNameReg::str(_refRangeName))) rangeIdentical = kFALSE;
821 if (normObs->getMax(_normRange.Data()) != normObs->getMax(RooNameReg::str(_refRangeName))) rangeIdentical = kFALSE;
822 }
823 else{
824 if (normObs->getMin() != normObs->getMin(RooNameReg::str(_refRangeName))) rangeIdentical = kFALSE;
825 if (normObs->getMax() != normObs->getMax(RooNameReg::str(_refRangeName))) rangeIdentical = kFALSE;
826 }
827 }
828// cout<<"FK: rangeIdentical Single = "<<(rangeIdentical ? 'T':'F')<<endl;
829 // coverity[CONSTANT_EXPRESSION_RESULT]
830 if (!rangeIdentical || 1) {
831// cout << "PREPARING RATIO HERE (SINGLE TERM)" << endl ;
832 RooAbsReal* ratio = makeCondPdfRatioCorr(*(RooAbsReal*)term->first(), termNSet, termImpSet, normRange(), RooNameReg::str(_refRangeName));
833 ostringstream str; termImpSet.printValue(str);
834// cout << GetName() << "inserting ratio term" << endl;
835 ratioTerms[str.str()].add(*ratio);
836 }
837 }
838
839 } else {
840// cout<<"FK: Starting Composite Term"<<endl;
841
842 RooArgSet compTermSet, compTermNorm;
843 RooFIter tIter = group->fwdIterator();
844 RooArgSet* term;
845 while ((term = (RooArgSet*) tIter.next())) {
846
847 Int_t termIdx = terms.IndexOf(term);
848 norm=(RooArgSet*) norms.At(termIdx);
849 imps=(RooArgSet*)imp.At(termIdx);
850 RooArgSet termNSet(*norm), termImpSet(*imps);
851
852 if (termImpSet.getSize() > 0 && 0 != _refRangeName) {
853
854 // WVE we can skip this if the ref range is equal to the normalization range
855 Bool_t rangeIdentical(kTRUE);
856 RooFIter niter = termNSet.fwdIterator();
857 RooRealVar* normObs;
858 //FK: Here the refRange should be compared to _normRange, if it's set, and to the normObs range if it's not set
859 if(_normRange.Length() > 0) {
860 while ((normObs = (RooRealVar*) niter.next())) {
861 if (normObs->getMin(_normRange.Data()) != normObs->getMin(RooNameReg::str(_refRangeName))) rangeIdentical = kFALSE;
862 if (normObs->getMax(_normRange.Data()) != normObs->getMax(RooNameReg::str(_refRangeName))) rangeIdentical = kFALSE;
863 }
864 } else {
865 while ((normObs = (RooRealVar*) niter.next())) {
866 if (normObs->getMin() != normObs->getMin(RooNameReg::str(_refRangeName))) rangeIdentical = kFALSE;
867 if (normObs->getMax() != normObs->getMax(RooNameReg::str(_refRangeName))) rangeIdentical = kFALSE;
868 }
869 }
870// cout<<"FK: rangeIdentical Composite = "<<(rangeIdentical ? 'T':'F') <<endl;
871 if (!rangeIdentical || 1) {
872// cout << "PREPARING RATIO HERE (COMPOSITE TERM)" << endl ;
873 RooAbsReal* ratio = makeCondPdfRatioCorr(*(RooAbsReal*)term->first(), termNSet, termImpSet, normRange(), RooNameReg::str(_refRangeName));
874 ostringstream str; termImpSet.printValue(str);
875 ratioTerms[str.str()].add(*ratio);
876 }
877 }
878 }
879 }
880
881 }
882
883 // Find groups with y as termNSet
884 // Replace G(y) with (G(y),ratio)
885 gIter = groupedList.fwdIterator();
886 while ((group = (RooLinkedList*) gIter.next())) {
887 if (1 == group->GetSize()) {
888 RooArgSet* term = (RooArgSet*) group->At(0);
889
890 Int_t termIdx = terms.IndexOf(term);
891 norm = (RooArgSet*) norms.At(termIdx);
892 imps = (RooArgSet*) imp.At(termIdx);
893 RooArgSet termNSet(*norm), termImpSet(*imps);
894
895 // If termNset matches index of ratioTerms, insert ratio here
896 ostringstream str; termNSet.printValue(str);
897 if (ratioTerms[str.str()].getSize() > 0) {
898// cout << "MUST INSERT RATIO OBJECT IN TERM (SINGLE) " << *term << endl;
899 term->add(ratioTerms[str.str()]);
900 }
901 } else {
902 RooArgSet compTermSet, compTermNorm;
903 RooFIter tIter = group->fwdIterator();
904 RooArgSet* term;
905 while ((term = (RooArgSet*) tIter.next())) {
906 Int_t termIdx = terms.IndexOf(term);
907 norm = (RooArgSet*) norms.At(termIdx);
908 imps = (RooArgSet*) imp.At(termIdx);
909 RooArgSet termNSet(*norm), termImpSet(*imps);
910
911 // If termNset matches index of ratioTerms, insert ratio here
912 ostringstream str; termNSet.printValue(str);
913 if (ratioTerms[str.str()].getSize() > 0) {
914// cout << "MUST INSERT RATIO OBJECT IN TERM (COMPOSITE)" << *term << endl;
915 term->add(ratioTerms[str.str()]);
916 }
917 }
918 }
919 }
920
921 gIter = groupedList.fwdIterator();
922 while ((group = (RooLinkedList*) gIter.next())) {
923// cout << GetName() << ":now processing group" << endl;
924// group->Print("1");
925
926 if (1 == group->GetSize()) {
927// cout << "processing atomic item" << endl;
928 RooArgSet* term = (RooArgSet*) group->At(0);
929
930 Int_t termIdx = terms.IndexOf(term);
931 norm = (RooArgSet*) norms.At(termIdx);
932 integ = (RooArgSet*) ints.At(termIdx);
933 xdeps = (RooArgSet*) cross.At(termIdx);
934 imps = (RooArgSet*) imp.At(termIdx);
935
936 RooArgSet termNSet, termISet, termXSet, termImpSet;
937
938 // Take list of normalization, integrated dependents from factorization algorithm
939 termISet.add(*integ);
940 termNSet.add(*norm);
941
942 // Cross-imported integrated dependents
943 termXSet.add(*xdeps);
944 termImpSet.add(*imps);
945
946// cout << GetName() << ": termISet = " << termISet << endl;
947// cout << GetName() << ": termNSet = " << termNSet << endl;
948// cout << GetName() << ": termXSet = " << termXSet << endl;
949// cout << GetName() << ": termImpSet = " << termImpSet << endl;
950
951 // Add prefab term to partIntList.
952 Bool_t isOwned(kFALSE);
953 vector<RooAbsReal*> func = processProductTerm(nset, iset, isetRangeName, term, termNSet, termISet, isOwned);
954 if (func[0]) {
955 cache->_partList.add(*func[0]);
956 if (isOwned) cache->_ownedList.addOwned(*func[0]);
957
958 cache->_normList.emplace_back(norm->snapshot(kFALSE));
959
960 cache->_numList.addOwned(*func[1]);
961 cache->_denList.addOwned(*func[2]);
962// cout << "func[0]=" << func[0]->IsA()->GetName() << "::" << func[0]->GetName() << endl;
963// cout << "func[1]=" << func[1]->IsA()->GetName() << "::" << func[1]->GetName() << endl;
964// cout << "func[2]=" << func[2]->IsA()->GetName() << "::" << func[2]->GetName() << endl;
965 }
966 } else {
967// cout << "processing composite item" << endl;
968 RooArgSet compTermSet, compTermNorm, compTermNum, compTermDen;
969 RooFIter tIter = group->fwdIterator();
970 RooArgSet* term;
971 while ((term = (RooArgSet*) tIter.next())) {
972// cout << GetName() << ": processing term " << (*term) << " of composite item" << endl ;
973 Int_t termIdx = terms.IndexOf(term);
974 norm = (RooArgSet*) norms.At(termIdx);
975 integ = (RooArgSet*) ints.At(termIdx);
976 xdeps = (RooArgSet*) cross.At(termIdx);
977 imps = (RooArgSet*) imp.At(termIdx);
978
979 RooArgSet termNSet, termISet, termXSet, termImpSet;
980 termISet.add(*integ);
981 termNSet.add(*norm);
982 termXSet.add(*xdeps);
983 termImpSet.add(*imps);
984
985 // Remove outer integration dependents from termISet
986 termISet.remove(outerIntDeps, kTRUE, kTRUE);
987// cout << "termISet = "; termISet.Print("1");
988
989// cout << GetName() << ": termISet = " << termISet << endl;
990// cout << GetName() << ": termNSet = " << termNSet << endl;
991// cout << GetName() << ": termXSet = " << termXSet << endl;
992// cout << GetName() << ": termImpSet = " << termImpSet << endl;
993
994 Bool_t isOwned = false;
995 vector<RooAbsReal*> func = processProductTerm(nset, iset, isetRangeName, term, termNSet, termISet, isOwned, kTRUE);
996// cout << GetName() << ": created composite term component " << func[0]->GetName() << endl;
997 if (func[0]) {
998 compTermSet.add(*func[0]);
999 if (isOwned) cache->_ownedList.addOwned(*func[0]);
1000 compTermNorm.add(*norm, kFALSE);
1001
1002 compTermNum.add(*func[1]);
1003 compTermDen.add(*func[2]);
1004 //cache->_numList.add(*func[1]);
1005 //cache->_denList.add(*func[2]);
1006
1007// cout << "func[0]=" << func[0]->IsA()->GetName() << "::" << func[0]->GetName() << endl;
1008// cout << "func[1]=" << func[1]->IsA()->GetName() << "::" << func[1]->GetName() << endl;
1009// cout << "func[2]=" << func[2]->IsA()->GetName() << "::" << func[2]->GetName() << endl;
1010 }
1011 }
1012
1013// cout << GetName() << ": constructing special composite product" << endl;
1014// cout << GetName() << ": compTermSet = " ; compTermSet.Print("1");
1015
1016 // WVE THIS NEEDS TO BE REARRANGED
1017
1018 // compTermset is set van partial integrals to be multiplied
1019 // prodtmp = product (compTermSet)
1020 // inttmp = int ( prodtmp ) d (outerIntDeps) _range_isetRangeName
1021
1022 const std::string prodname = makeRGPPName("SPECPROD", compTermSet, outerIntDeps, RooArgSet(), isetRangeName);
1023 RooProduct* prodtmp = new RooProduct(prodname.c_str(), prodname.c_str(), compTermSet);
1024 cache->_ownedList.addOwned(*prodtmp);
1025
1026 const std::string intname = makeRGPPName("SPECINT", compTermSet, outerIntDeps, RooArgSet(), isetRangeName);
1027 RooRealIntegral* inttmp = new RooRealIntegral(intname.c_str(), intname.c_str(), *prodtmp, outerIntDeps, 0, 0, isetRangeName);
1028 inttmp->setStringAttribute("PROD_TERM_TYPE", "SPECINT");
1029
1030 cache->_ownedList.addOwned(*inttmp);
1031 cache->_partList.add(*inttmp);
1032
1033 // Product of numerator terms
1034 const string prodname_num = makeRGPPName("SPECPROD_NUM", compTermNum, RooArgSet(), RooArgSet(), 0);
1035 RooProduct* prodtmp_num = new RooProduct(prodname_num.c_str(), prodname_num.c_str(), compTermNum);
1036 prodtmp_num->addOwnedComponents(compTermNum);
1037 cache->_ownedList.addOwned(*prodtmp_num);
1038
1039 // Product of denominator terms
1040 const string prodname_den = makeRGPPName("SPECPROD_DEN", compTermDen, RooArgSet(), RooArgSet(), 0);
1041 RooProduct* prodtmp_den = new RooProduct(prodname_den.c_str(), prodname_den.c_str(), compTermDen);
1042 prodtmp_den->addOwnedComponents(compTermDen);
1043 cache->_ownedList.addOwned(*prodtmp_den);
1044
1045 // Ratio
1046 string name = Form("SPEC_RATIO(%s,%s)", prodname_num.c_str(), prodname_den.c_str());
1047 RooFormulaVar* ndr = new RooFormulaVar(name.c_str(), "@0/@1", RooArgList(*prodtmp_num, *prodtmp_den));
1048
1049 // Integral of ratio
1050 RooAbsReal* numtmp = ndr->createIntegral(outerIntDeps,isetRangeName);
1051 numtmp->addOwnedComponents(*ndr);
1052
1053 cache->_numList.addOwned(*numtmp);
1055 cache->_normList.emplace_back(compTermNorm.snapshot(kFALSE));
1056 }
1057 }
1058
1059 // Store the partial integral list and return the assigned code
1060 Int_t returnCode = _cacheMgr.setObj(nset, iset, (RooAbsCacheElement*)cache, RooNameReg::ptr(isetRangeName));
1061
1062 // WVE DEBUG PRINTING
1063// cout << "RooProdPdf::getPartIntList(" << GetName() << ") made cache " << cache << " with the following nset pointers ";
1064// TIterator* nliter = nsetList->MakeIterator();
1065// RooArgSet* ns;
1066// while((ns=(RooArgSet*)nliter->Next())) {
1067// cout << ns << " ";
1068// }
1069// cout << endl;
1070// delete nliter;
1071
1072// cout << " FOLKERT::RooProdPdf::getPartIntList END(" << GetName() <<") nset = " << (nset?*nset:RooArgSet()) << endl
1073// << " _normRange = " << _normRange << endl
1074// << " iset = " << (iset?*iset:RooArgSet()) << endl
1075// << " partList = ";
1076// if(partListPointer) partListPointer->Print();
1077// cout << " nsetList = ";
1078// if(nsetListPointer) nsetListPointer->Print("");
1079// cout << " code = " << returnCode << endl
1080// << " isetRangeName = " << (isetRangeName?isetRangeName:"<null>") << endl;
1081
1082
1083 // Need to rearrange product in case of multiple ranges
1084 if (_normRange.Contains(",")) {
1085 rearrangeProduct(*cache);
1086 }
1087
1088 // We own contents of all lists filled by factorizeProduct()
1089 groupedList.Delete();
1090 terms.Delete();
1091 ints.Delete();
1092 imp.Delete();
1093 norms.Delete();
1094 cross.Delete();
1095
1096 return returnCode;
1097}
1098
1099
1100
1101
1102////////////////////////////////////////////////////////////////////////////////
1103/// For single normalization ranges
1104
1105RooAbsReal* RooProdPdf::makeCondPdfRatioCorr(RooAbsReal& pdf, const RooArgSet& termNset, const RooArgSet& /*termImpSet*/, const char* normRangeTmp, const char* refRange) const
1106{
1107 RooAbsReal* ratio_num = pdf.createIntegral(termNset,normRangeTmp) ;
1108 RooAbsReal* ratio_den = pdf.createIntegral(termNset,refRange) ;
1109 RooFormulaVar* ratio = new RooFormulaVar(Form("ratio(%s,%s)",ratio_num->GetName(),ratio_den->GetName()),"@0/@1",
1110 RooArgList(*ratio_num,*ratio_den)) ;
1111
1112 ratio->addOwnedComponents(RooArgSet(*ratio_num,*ratio_den)) ;
1113 ratio->setAttribute("RATIO_TERM") ;
1114 return ratio ;
1115}
1116
1117
1118
1119
1120////////////////////////////////////////////////////////////////////////////////
1121
1123{
1124 RooAbsReal* part, *num, *den ;
1125 RooArgSet nomList ;
1126
1127 list<string> rangeComps ;
1128 {
1129 char* buf = new char[strlen(_normRange.Data()) + 1] ;
1130 strcpy(buf,_normRange.Data()) ;
1131 char* save(0) ;
1132 char* token = R__STRTOK_R(buf,",",&save) ;
1133 while(token) {
1134 rangeComps.push_back(token) ;
1135 token = R__STRTOK_R(0,",",&save) ;
1136 }
1137 delete[] buf;
1138 }
1139
1140
1141 map<string,RooArgSet> denListList ;
1142 RooArgSet specIntDeps ;
1143 string specIntRange ;
1144
1145// cout << "THIS IS REARRANGEPRODUCT" << endl ;
1146
1147 RooFIter iterp = cache._partList.fwdIterator() ;
1148 RooFIter iter1 = cache._numList.fwdIterator() ;
1149 RooFIter iter2 = cache._denList.fwdIterator() ;
1150 while((part=(RooAbsReal*)iterp.next())) {
1151
1152 num = (RooAbsReal*) iter1.next() ;
1153 den = (RooAbsReal*) iter2.next() ;
1154
1155// cout << "now processing part " << part->GetName() << " of type " << part->getStringAttribute("PROD_TERM_TYPE") << endl ;
1156// cout << "corresponding numerator = " << num->GetName() << endl ;
1157// cout << "corresponding denominator = " << den->GetName() << endl ;
1158
1159
1160 RooFormulaVar* ratio(0) ;
1161 RooArgSet origNumTerm ;
1162
1163 if (string("SPECINT")==part->getStringAttribute("PROD_TERM_TYPE")) {
1164
1165 RooRealIntegral* orig = (RooRealIntegral*) num;
1166 RooFormulaVar* specratio = (RooFormulaVar*) &orig->integrand() ;
1167 RooProduct* func = (RooProduct*) specratio->getParameter(0) ;
1168
1169 RooArgSet* comps = orig->getComponents() ;
1170 RooFIter iter = comps->fwdIterator() ;
1171 RooAbsArg* carg ;
1172 while((carg=(RooAbsArg*)iter.next())) {
1173 if (carg->getAttribute("RATIO_TERM")) {
1174 ratio = (RooFormulaVar*)carg ;
1175 break ;
1176 }
1177 }
1178 delete comps ;
1179
1180 if (ratio) {
1181 RooCustomizer cust(*func,"blah") ;
1182 cust.replaceArg(*ratio,RooFit::RooConst(1)) ;
1183 RooAbsArg* funcCust = cust.build() ;
1184// cout << "customized function = " << endl ;
1185// funcCust->printComponentTree() ;
1186 nomList.add(*funcCust) ;
1187 } else {
1188 nomList.add(*func) ;
1189 }
1190
1191
1192 } else {
1193
1194 // Find the ratio term
1195 RooAbsReal* func = num;
1196 // If top level object is integral, navigate to integrand
1197 if (func->InheritsFrom(RooRealIntegral::Class())) {
1198 func = (RooAbsReal*) &((RooRealIntegral*)(func))->integrand();
1199 }
1200 if (func->InheritsFrom(RooProduct::Class())) {
1201// cout << "product term found: " ; func->Print() ;
1202 RooArgSet comps(((RooProduct*)(func))->components()) ;
1203 RooFIter iter = comps.fwdIterator() ;
1204 RooAbsArg* arg ;
1205 while((arg=(RooAbsArg*)iter.next())) {
1206 if (arg->getAttribute("RATIO_TERM")) {
1207 ratio = (RooFormulaVar*)(arg) ;
1208 } else {
1209 origNumTerm.add(*arg) ;
1210 }
1211 }
1212 }
1213
1214 if (ratio) {
1215// cout << "Found ratio term in numerator: " << ratio->GetName() << endl ;
1216// cout << "Adding only original term to numerator: " << origNumTerm << endl ;
1217 nomList.add(origNumTerm) ;
1218 } else {
1219 nomList.add(*num) ;
1220 }
1221
1222 }
1223
1224 for (list<string>::iterator iter = rangeComps.begin() ; iter != rangeComps.end() ; ++iter) {
1225 // If denominator is an integral, make a clone with the integration range adjusted to
1226 // the selected component of the normalization integral
1227// cout << "NOW PROCESSING DENOMINATOR " << den->IsA()->GetName() << "::" << den->GetName() << endl ;
1228
1229 if (string("SPECINT")==part->getStringAttribute("PROD_TERM_TYPE")) {
1230
1231// cout << "create integral: SPECINT case" << endl ;
1232 RooRealIntegral* orig = (RooRealIntegral*) num;
1233 RooFormulaVar* specRatio = (RooFormulaVar*) &orig->integrand() ;
1234 specIntDeps.add(orig->intVars()) ;
1235 if (orig->intRange()) {
1236 specIntRange = orig->intRange() ;
1237 }
1238 //RooProduct* numtmp = (RooProduct*) specRatio->getParameter(0) ;
1239 RooProduct* dentmp = (RooProduct*) specRatio->getParameter(1) ;
1240
1241// cout << "numtmp = " << numtmp->IsA()->GetName() << "::" << numtmp->GetName() << endl ;
1242// cout << "dentmp = " << dentmp->IsA()->GetName() << "::" << dentmp->GetName() << endl ;
1243
1244// cout << "denominator components are " << dentmp->components() << endl ;
1245 RooArgSet comps(dentmp->components()) ;
1246 RooFIter piter = comps.fwdIterator() ;
1247 RooAbsReal* parg ;
1248 while((parg=(RooAbsReal*)piter.next())) {
1249// cout << "now processing denominator component " << parg->IsA()->GetName() << "::" << parg->GetName() << endl ;
1250
1251 if (ratio && parg->dependsOn(*ratio)) {
1252// cout << "depends in value of ratio" << endl ;
1253
1254 // Make specialize ratio instance
1255 RooAbsReal* specializedRatio = specializeRatio(*(RooFormulaVar*)ratio,iter->c_str()) ;
1256
1257// cout << "specRatio = " << endl ;
1258// specializedRatio->printComponentTree() ;
1259
1260 // Replace generic ratio with specialized ratio
1261 RooAbsArg *partCust(0) ;
1262 if (parg->InheritsFrom(RooAddition::Class())) {
1263
1264
1265
1266 RooAddition* tmpadd = (RooAddition*)(parg) ;
1267
1268 RooCustomizer cust(*tmpadd->list1().first(),Form("blah_%s",iter->c_str())) ;
1269 cust.replaceArg(*ratio,*specializedRatio) ;
1270 partCust = cust.build() ;
1271
1272 } else {
1273 RooCustomizer cust(*parg,Form("blah_%s",iter->c_str())) ;
1274 cust.replaceArg(*ratio,*specializedRatio) ;
1275 partCust = cust.build() ;
1276 }
1277
1278 // Print customized denominator
1279// cout << "customized function = " << endl ;
1280// partCust->printComponentTree() ;
1281
1282 RooAbsReal* specializedPartCust = specializeIntegral(*(RooAbsReal*)partCust,iter->c_str()) ;
1283
1284 // Finally divide again by ratio
1285 string name = Form("%s_divided_by_ratio",specializedPartCust->GetName()) ;
1286 RooFormulaVar* specIntFinal = new RooFormulaVar(name.c_str(),"@0/@1",RooArgList(*specializedPartCust,*specializedRatio)) ;
1287
1288 denListList[*iter].add(*specIntFinal) ;
1289 } else {
1290
1291// cout << "does NOT depend on value of ratio" << endl ;
1292// parg->Print("t") ;
1293
1294 denListList[*iter].add(*specializeIntegral(*parg,iter->c_str())) ;
1295
1296 }
1297 }
1298// cout << "end iteration over denominator components" << endl ;
1299 } else {
1300
1301 if (ratio) {
1302
1303 RooAbsReal* specRatio = specializeRatio(*(RooFormulaVar*)ratio,iter->c_str()) ;
1304
1305 // If integral is 'Int r(y)*g(y) dy ' then divide a posteriori by r(y)
1306// cout << "have ratio, orig den = " << den->GetName() << endl ;
1307
1308 RooArgSet tmp(origNumTerm) ;
1309 tmp.add(*specRatio) ;
1310 const string pname = makeRGPPName("PROD",tmp,RooArgSet(),RooArgSet(),0) ;
1311 RooProduct* specDenProd = new RooProduct(pname.c_str(),pname.c_str(),tmp) ;
1312 RooAbsReal* specInt(0) ;
1313
1315 specInt = specDenProd->createIntegral(((RooRealIntegral*)den)->intVars(),iter->c_str()) ;
1316 } else if (den->InheritsFrom(RooAddition::Class())) {
1317 RooAddition* orig = (RooAddition*)den ;
1318 RooRealIntegral* origInt = (RooRealIntegral*) orig->list1().first() ;
1319 specInt = specDenProd->createIntegral(origInt->intVars(),iter->c_str()) ;
1320 } else {
1321 throw string("this should not happen") ;
1322 }
1323
1324 //RooAbsReal* specInt = specializeIntegral(*den,iter->c_str()) ;
1325 string name = Form("%s_divided_by_ratio",specInt->GetName()) ;
1326 RooFormulaVar* specIntFinal = new RooFormulaVar(name.c_str(),"@0/@1",RooArgList(*specInt,*specRatio)) ;
1327 denListList[*iter].add(*specIntFinal) ;
1328 } else {
1329 denListList[*iter].add(*specializeIntegral(*den,iter->c_str())) ;
1330 }
1331
1332 }
1333 }
1334
1335 }
1336
1337 // Do not rearrage terms if numerator and denominator are effectively empty
1338 if (nomList.getSize()==0) {
1339 return ;
1340 }
1341
1342 string name = Form("%s_numerator",GetName()) ;
1343 // WVE FIX THIS (2)
1344
1345 RooAbsReal* numerator = new RooProduct(name.c_str(),name.c_str(),nomList) ;
1346
1347 RooArgSet products ;
1348// cout << "nomList = " << nomList << endl ;
1349 for (map<string,RooArgSet>::iterator iter = denListList.begin() ; iter != denListList.end() ; ++iter) {
1350// cout << "denList[" << iter->first << "] = " << iter->second << endl ;
1351 name = Form("%s_denominator_comp_%s",GetName(),iter->first.c_str()) ;
1352 // WVE FIX THIS (2)
1353 RooProduct* prod_comp = new RooProduct(name.c_str(),name.c_str(),iter->second) ;
1354 products.add(*prod_comp) ;
1355 }
1356 name = Form("%s_denominator_sum",GetName()) ;
1357 RooAbsReal* norm = new RooAddition(name.c_str(),name.c_str(),products) ;
1358 norm->addOwnedComponents(products) ;
1359
1360 if (specIntDeps.getSize()>0) {
1361 // Apply posterior integration required for SPECINT case
1362
1363 string namesr = Form("SPEC_RATIO(%s,%s)",numerator->GetName(),norm->GetName()) ;
1364 RooFormulaVar* ndr = new RooFormulaVar(namesr.c_str(),"@0/@1",RooArgList(*numerator,*norm)) ;
1365
1366 // Integral of ratio
1367 RooAbsReal* numtmp = ndr->createIntegral(specIntDeps,specIntRange.c_str()) ;
1368
1369 numerator = numtmp ;
1370 norm = (RooAbsReal*) RooFit::RooConst(1).Clone() ;
1371 }
1372
1373
1374// cout << "numerator" << endl ;
1375// numerator->printComponentTree("",0,5) ;
1376// cout << "denominator" << endl ;
1377// norm->printComponentTree("",0,5) ;
1378
1379
1380 // WVE DEBUG
1381 //RooMsgService::instance().debugWorkspace()->import(RooArgSet(*numerator,*norm)) ;
1382
1383 cache._rearrangedNum.reset(numerator);
1384 cache._rearrangedDen.reset(norm);
1385 cache._isRearranged = kTRUE ;
1386
1387}
1388
1389
1390////////////////////////////////////////////////////////////////////////////////
1391
1392RooAbsReal* RooProdPdf::specializeRatio(RooFormulaVar& input, const char* targetRangeName) const
1393{
1394 RooRealIntegral* numint = (RooRealIntegral*) input.getParameter(0) ;
1395 RooRealIntegral* denint = (RooRealIntegral*) input.getParameter(1) ;
1396
1397 RooAbsReal* numint_spec = specializeIntegral(*numint,targetRangeName) ;
1398
1399 RooAbsReal* ret = new RooFormulaVar(Form("ratio(%s,%s)",numint_spec->GetName(),denint->GetName()),"@0/@1",RooArgList(*numint_spec,*denint)) ;
1400 ret->addOwnedComponents(*numint_spec) ;
1401
1402 return ret ;
1403}
1404
1405
1406
1407////////////////////////////////////////////////////////////////////////////////
1408
1409RooAbsReal* RooProdPdf::specializeIntegral(RooAbsReal& input, const char* targetRangeName) const
1410{
1411 if (input.InheritsFrom(RooRealIntegral::Class())) {
1412
1413 // If input is integral, recreate integral but override integration range to be targetRangeName
1414 RooRealIntegral* orig = (RooRealIntegral*)&input ;
1415// cout << "creating integral: integrand = " << orig->integrand().GetName() << " vars = " << orig->intVars() << " range = " << targetRangeName << endl ;
1416 return orig->integrand().createIntegral(orig->intVars(),targetRangeName) ;
1417
1418 } else if (input.InheritsFrom(RooAddition::Class())) {
1419
1420 // If input is sum of integrals, recreate integral from first component of set, but override integration range to be targetRangeName
1421 RooAddition* orig = (RooAddition*)&input ;
1422 RooRealIntegral* origInt = (RooRealIntegral*) orig->list1().first() ;
1423// cout << "creating integral from addition: integrand = " << origInt->integrand().GetName() << " vars = " << origInt->intVars() << " range = " << targetRangeName << endl ;
1424 return origInt->integrand().createIntegral(origInt->intVars(),targetRangeName) ;
1425
1426 } else {
1427
1428// cout << "specializeIntegral: unknown input type " << input.IsA()->GetName() << "::" << input.GetName() << endl ;
1429 }
1430
1431 return &input ;
1432}
1433
1434
1435////////////////////////////////////////////////////////////////////////////////
1436/// Group product into terms that can be calculated independently
1437
1439 const RooLinkedList& terms, const RooLinkedList& norms,
1440 const RooLinkedList& imps, const RooLinkedList& ints, const RooLinkedList& /*cross*/) const
1441{
1442 // Start out with each term in its own group
1443 RooFIter tIter = terms.fwdIterator() ;
1444 RooArgSet* term ;
1445 while((term=(RooArgSet*)tIter.next())) {
1447 group->Add(term) ;
1448 groupedTerms.Add(group) ;
1449 }
1450
1451 // Make list of imported dependents that occur in any term
1452 RooArgSet allImpDeps ;
1453 RooFIter iIter = imps.fwdIterator() ;
1454 RooArgSet *impDeps ;
1455 while((impDeps=(RooArgSet*)iIter.next())) {
1456 allImpDeps.add(*impDeps,kFALSE) ;
1457 }
1458
1459 // Make list of integrated dependents that occur in any term
1460 RooArgSet allIntDeps ;
1461 iIter = ints.fwdIterator() ;
1462 RooArgSet *intDeps ;
1463 while((intDeps=(RooArgSet*)iIter.next())) {
1464 allIntDeps.add(*intDeps,kFALSE) ;
1465 }
1466
1467 RooArgSet* tmp = (RooArgSet*) allIntDeps.selectCommon(allImpDeps) ;
1468 outerIntDeps.removeAll() ;
1469 outerIntDeps.add(*tmp) ;
1470 delete tmp ;
1471
1472 // Now iteratively merge groups that should be (partially) integrated together
1473 RooFIter oidIter = outerIntDeps.fwdIterator() ;
1474 RooAbsArg* outerIntDep ;
1475 while ((outerIntDep =(RooAbsArg*)oidIter.next())) {
1476
1477 // Collect groups that feature this dependent
1478 RooLinkedList* newGroup = 0 ;
1479
1480 // Loop over groups
1482 RooFIter glIter = groupedTerms.fwdIterator() ;
1483 Bool_t needMerge = kFALSE ;
1484 while((group=(RooLinkedList*)glIter.next())) {
1485
1486 // See if any term in this group depends in any ay on outerDepInt
1487 RooArgSet* term2 ;
1488 RooFIter tIter2 = group->fwdIterator() ;
1489 while((term2=(RooArgSet*)tIter2.next())) {
1490
1491 Int_t termIdx = terms.IndexOf(term2) ;
1492 RooArgSet* termNormDeps = (RooArgSet*) norms.At(termIdx) ;
1493 RooArgSet* termIntDeps = (RooArgSet*) ints.At(termIdx) ;
1494 RooArgSet* termImpDeps = (RooArgSet*) imps.At(termIdx) ;
1495
1496 if (termNormDeps->contains(*outerIntDep) ||
1497 termIntDeps->contains(*outerIntDep) ||
1498 termImpDeps->contains(*outerIntDep)) {
1499 needMerge = kTRUE ;
1500 }
1501
1502 }
1503
1504 if (needMerge) {
1505 // Create composite group if not yet existing
1506 if (newGroup==0) {
1507 newGroup = new RooLinkedList ;
1508 }
1509
1510 // Add terms of this group to new term
1511 tIter2 = group->fwdIterator() ;
1512 while((term2=(RooArgSet*)tIter2.next())) {
1513 newGroup->Add(term2) ;
1514 }
1515
1516 // Remove this group from list and delete it (but not its contents)
1517 groupedTerms.Remove(group) ;
1518 delete group ;
1519 }
1520 }
1521 // If a new group has been created to merge terms dependent on current outerIntDep, add it to group list
1522 if (newGroup) {
1523 groupedTerms.Add(newGroup) ;
1524 }
1525
1526 }
1527}
1528
1529
1530
1531////////////////////////////////////////////////////////////////////////////////
1532/// Calculate integrals of factorized product terms over observables iset while normalized
1533/// to observables in nset.
1534
1535std::vector<RooAbsReal*> RooProdPdf::processProductTerm(const RooArgSet* nset, const RooArgSet* iset, const char* isetRangeName,
1536 const RooArgSet* term,const RooArgSet& termNSet, const RooArgSet& termISet,
1537 Bool_t& isOwned, Bool_t forceWrap) const
1538{
1539// cout << " FOLKERT::RooProdPdf(" << GetName() <<") processProductTerm nset = " << (nset?*nset:RooArgSet()) << endl
1540// << " _normRange = " << _normRange << endl
1541// << " iset = " << (iset?*iset:RooArgSet()) << endl
1542// << " isetRangeName = " << (isetRangeName?isetRangeName:"<null>") << endl
1543// << " term = " << (term?*term:RooArgSet()) << endl
1544// << " termNSet = " << termNSet << endl
1545// << " termISet = " << termISet << endl
1546// << " isOwned = " << isOwned << endl
1547// << " forceWrap = " << forceWrap << endl ;
1548
1549 vector<RooAbsReal*> ret(3) ; ret[0] = 0 ; ret[1] = 0 ; ret[2] = 0 ;
1550
1551 // CASE I: factorizing term: term is integrated over all normalizing observables
1552 // -----------------------------------------------------------------------------
1553 // Check if all observbales of this term are integrated. If so the term cancels
1554 if (termNSet.getSize()>0 && termNSet.getSize()==termISet.getSize() && isetRangeName==0) {
1555
1556
1557 //cout << "processProductTerm(" << GetName() << ") case I " << endl ;
1558
1559 // Term factorizes
1560 return ret ;
1561 }
1562
1563 // CASE II: Dropped terms: if term is entirely unnormalized, it should be dropped
1564 // ------------------------------------------------------------------------------
1565 if (nset && termNSet.getSize()==0) {
1566
1567 //cout << "processProductTerm(" << GetName() << ") case II " << endl ;
1568
1569 // Drop terms that are not asked to be normalized
1570 return ret ;
1571 }
1572
1573 if (iset && termISet.getSize()>0) {
1574 if (term->getSize()==1) {
1575
1576 // CASE IIIa: Normalized and partially integrated single PDF term
1577 //---------------------------------------------------------------
1578
1579 RooAbsPdf* pdf = (RooAbsPdf*) term->first() ;
1580
1581 RooAbsReal* partInt = pdf->createIntegral(termISet,termNSet,isetRangeName) ;
1582 //partInt->setOperMode(operMode()) ;
1583 partInt->setStringAttribute("PROD_TERM_TYPE","IIIa") ;
1584
1585 isOwned=kTRUE ;
1586
1587 //cout << "processProductTerm(" << GetName() << ") case IIIa func = " << partInt->GetName() << endl ;
1588
1589 ret[0] = partInt ;
1590
1591 // Split mode results
1592 ret[1] = pdf->createIntegral(termISet,isetRangeName) ;
1593 ret[2] = pdf->createIntegral(termNSet,normRange()) ;
1594
1595 return ret ;
1596
1597
1598 } else {
1599
1600 // CASE IIIb: Normalized and partially integrated composite PDF term
1601 //---------------------------------------------------------------
1602
1603 // Use auxiliary class RooGenProdProj to calculate this term
1604 const std::string name = makeRGPPName("GENPROJ_",*term,termISet,termNSet,isetRangeName) ;
1605 RooAbsReal* partInt = new RooGenProdProj(name.c_str(),name.c_str(),*term,termISet,termNSet,isetRangeName) ;
1606 partInt->setStringAttribute("PROD_TERM_TYPE","IIIb") ;
1607 //partInt->setOperMode(operMode()) ;
1608
1609 //cout << "processProductTerm(" << GetName() << ") case IIIb func = " << partInt->GetName() << endl ;
1610
1611 isOwned=kTRUE ;
1612 ret[0] = partInt ;
1613
1614 const std::string name1 = makeRGPPName("PROD",*term,RooArgSet(),RooArgSet(),0) ;
1615
1616 // WVE FIX THIS
1617 RooProduct* tmp_prod = new RooProduct(name1.c_str(),name1.c_str(),*term) ;
1618
1619 ret[1] = tmp_prod->createIntegral(termISet,isetRangeName) ;
1620 ret[2] = tmp_prod->createIntegral(termNSet,normRange()) ;
1621
1622 return ret ;
1623 }
1624 }
1625
1626 // CASE IVa: Normalized non-integrated composite PDF term
1627 // -------------------------------------------------------
1628 if (nset && nset->getSize()>0 && term->getSize()>1) {
1629 // Composite term needs normalized integration
1630
1631 const std::string name = makeRGPPName("GENPROJ_",*term,termISet,termNSet,isetRangeName) ;
1632 RooAbsReal* partInt = new RooGenProdProj(name.c_str(),name.c_str(),*term,termISet,termNSet,isetRangeName,normRange()) ;
1634
1635 partInt->setStringAttribute("PROD_TERM_TYPE","IVa") ;
1636 //partInt->setOperMode(operMode()) ;
1637
1638 //cout << "processProductTerm(" << GetName() << ") case IVa func = " << partInt->GetName() << endl ;
1639
1640 isOwned=kTRUE ;
1641 ret[0] = partInt ;
1642
1643 const std::string name1 = makeRGPPName("PROD",*term,RooArgSet(),RooArgSet(),0) ;
1644
1645 // WVE FIX THIS
1646 RooProduct* tmp_prod = new RooProduct(name1.c_str(),name1.c_str(),*term) ;
1647
1648 ret[1] = tmp_prod->createIntegral(termISet,isetRangeName) ;
1649 ret[2] = tmp_prod->createIntegral(termNSet,normRange()) ;
1650
1651 return ret ;
1652 }
1653
1654 // CASE IVb: Normalized, non-integrated single PDF term
1655 // -----------------------------------------------------
1656 RooFIter pIter = term->fwdIterator() ;
1657 RooAbsPdf* pdf ;
1658 while((pdf=(RooAbsPdf*)pIter.next())) {
1659
1660 if (forceWrap) {
1661
1662 // Construct representative name of normalization wrapper
1663 TString name(pdf->GetName()) ;
1664 name.Append("_NORM[") ;
1665 RooFIter nIter = termNSet.fwdIterator() ;
1666 RooAbsArg* arg ;
1667 Bool_t first(kTRUE) ;
1668 while((arg=(RooAbsArg*)nIter.next())) {
1669 if (!first) {
1670 name.Append(",") ;
1671 } else {
1672 first=kFALSE ;
1673 }
1674 name.Append(arg->GetName()) ;
1675 }
1676 if (normRange()) {
1677 name.Append("|") ;
1678 name.Append(normRange()) ;
1679 }
1680 name.Append("]") ;
1681
1682 RooAbsReal* partInt = new RooRealIntegral(name.Data(),name.Data(),*pdf,RooArgSet(),&termNSet) ;
1683 partInt->setStringAttribute("PROD_TERM_TYPE","IVb") ;
1684 isOwned=kTRUE ;
1685
1686 //cout << "processProductTerm(" << GetName() << ") case IVb func = " << partInt->GetName() << endl ;
1687
1688 ret[0] = partInt ;
1689
1690 ret[1] = pdf->createIntegral(RooArgSet()) ;
1691 ret[2] = pdf->createIntegral(termNSet,normRange()) ;
1692
1693 return ret ;
1694
1695
1696 } else {
1697 isOwned=kFALSE ;
1698
1699 //cout << "processProductTerm(" << GetName() << ") case IVb func = " << pdf->GetName() << endl ;
1700
1701
1702 pdf->setStringAttribute("PROD_TERM_TYPE","IVb") ;
1703 ret[0] = pdf ;
1704
1705 ret[1] = pdf->createIntegral(RooArgSet()) ;
1706 ret[2] = termNSet.getSize()>0 ? pdf->createIntegral(termNSet,normRange()) : ((RooAbsReal*)RooFit::RooConst(1).clone("1")) ;
1707 return ret ;
1708 }
1709 }
1710
1711 coutE(Eval) << "RooProdPdf::processProductTerm(" << GetName() << ") unidentified term!!!" << endl ;
1712 return ret ;
1713}
1714
1715
1716
1717
1718////////////////////////////////////////////////////////////////////////////////
1719/// Make an appropriate automatic name for a RooGenProdProj object in getPartIntList()
1720
1721std::string RooProdPdf::makeRGPPName(const char* pfx, const RooArgSet& term, const RooArgSet& iset,
1722 const RooArgSet& nset, const char* isetRangeName) const
1723{
1724 // Make an appropriate automatic name for a RooGenProdProj object in getPartIntList()
1725
1726 std::ostringstream os(pfx);
1727 os << "[";
1728
1729 RooFIter pIter = term.fwdIterator() ;
1730 // Encode component names
1731 Bool_t first(kTRUE) ;
1732 RooAbsPdf* pdf ;
1733 while ((pdf=(RooAbsPdf*)pIter.next())) {
1734 if (!first) os << "_X_";
1735 first = kFALSE;
1736 os << pdf->GetName();
1737 }
1738 os << "]" << integralNameSuffix(iset,&nset,isetRangeName,kTRUE);
1739
1740 return os.str();
1741}
1742
1743
1744
1745////////////////////////////////////////////////////////////////////////////////
1746/// Force RooRealIntegral to offer all observables for internal integration
1747
1749{
1750 return kTRUE ;
1751}
1752
1753
1754
1755////////////////////////////////////////////////////////////////////////////////
1756/// Determine which part (if any) of given integral can be performed analytically.
1757/// If any analytical integration is possible, return integration scenario code.
1758///
1759/// RooProdPdf implements two strategies in implementing analytical integrals
1760///
1761/// First, PDF components whose entire set of dependents are requested to be integrated
1762/// can be dropped from the product, as they will integrate out to 1 by construction
1763///
1764/// Second, RooProdPdf queries each remaining component PDF for its analytical integration
1765/// capability of the requested set ('allVars'). It finds the largest common set of variables
1766/// that can be integrated by all remaining components. If such a set exists, it reconfirms that
1767/// each component is capable of analytically integrating the common set, and combines the components
1768/// individual integration codes into a single integration code valid for RooProdPdf.
1769
1771 const RooArgSet* normSet, const char* rangeName) const
1772{
1773 if (_forceNumInt) return 0 ;
1774
1775 // Declare that we can analytically integrate all requested observables
1776 analVars.add(allVars) ;
1777
1778 // Retrieve (or create) the required partial integral list
1779 Int_t code = getPartIntList(normSet,&allVars,rangeName);
1780
1781 return code+1 ;
1782}
1783
1784
1785
1786
1787////////////////////////////////////////////////////////////////////////////////
1788/// Return analytical integral defined by given scenario code
1789
1790Double_t RooProdPdf::analyticalIntegralWN(Int_t code, const RooArgSet* normSet, const char* rangeName) const
1791{
1792 // No integration scenario
1793 if (code==0) {
1794 return getVal(normSet) ;
1795 }
1796
1797
1798 // WVE needs adaptation for rangename feature
1799
1800 // Partial integration scenarios
1801 CacheElem* cache = (CacheElem*) _cacheMgr.getObjByIndex(code-1) ;
1802
1803 // If cache has been sterilized, revive this slot
1804 if (cache==0) {
1805 RooArgSet* vars = getParameters(RooArgSet()) ;
1806 RooArgSet* nset = _cacheMgr.nameSet1ByIndex(code-1)->select(*vars) ;
1807 RooArgSet* iset = _cacheMgr.nameSet2ByIndex(code-1)->select(*vars) ;
1808
1809 Int_t code2 = getPartIntList(nset, iset, rangeName) ;
1810
1811 delete vars ;
1812
1813 // preceding call to getPartIntList guarantees non-null return
1814 // coverity[NULL_RETURNS]
1815 cache = (CacheElem*) _cacheMgr.getObj(nset,iset,&code2,rangeName) ;
1816
1817 delete nset ;
1818 delete iset ;
1819
1820 }
1821
1822 Double_t val = calculate(*cache,kTRUE) ;
1823// cout << "RPP::aIWN(" << GetName() << ") ,code = " << code << ", value = " << val << endl ;
1824
1825 return val ;
1826}
1827
1828
1829
1830////////////////////////////////////////////////////////////////////////////////
1831/// Obsolete
1832
1834{ return kFALSE ; }
1835
1836
1837
1838
1839////////////////////////////////////////////////////////////////////////////////
1840/// If this product contains exactly one extendable p.d.f return the extension abilities of
1841/// that p.d.f, otherwise return CanNotBeExtended
1842
1844{
1846}
1847
1848
1849
1850////////////////////////////////////////////////////////////////////////////////
1851/// Return the expected number of events associated with the extendable input PDF
1852/// in the product. If there is no extendable term, abort.
1853
1855{
1856 if (_extendedIndex<0) {
1857 coutF(Generation) << "Requesting expected number of events from a RooProdPdf that does not contain an extended p.d.f" << endl ;
1858 throw std::logic_error(std::string("RooProdPdf ") + GetName() + " could not be extended.");
1859 }
1860
1861 return ((RooAbsPdf*)_pdfList.at(_extendedIndex))->expectedEvents(nset) ;
1862}
1863
1864
1865
1866////////////////////////////////////////////////////////////////////////////////
1867/// Return generator context optimized for generating events from product p.d.f.s
1868
1870 const RooArgSet* auxProto, Bool_t verbose) const
1871{
1872 if (_useDefaultGen) return RooAbsPdf::genContext(vars,prototype,auxProto,verbose) ;
1873 return new RooProdGenContext(*this,vars,prototype,auxProto,verbose) ;
1874}
1875
1876
1877
1878////////////////////////////////////////////////////////////////////////////////
1879/// Query internal generation capabilities of component p.d.f.s and aggregate capabilities
1880/// into master configuration passed to the generator context
1881
1882Int_t RooProdPdf::getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, Bool_t staticInitOK) const
1883{
1884 if (!_useDefaultGen) return 0 ;
1885
1886 // Find the subset directVars that only depend on a single PDF in the product
1887 RooArgSet directSafe ;
1888 RooFIter dIter = directVars.fwdIterator() ;
1889 RooAbsArg* arg ;
1890 while((arg=(RooAbsArg*)dIter.next())) {
1891 if (isDirectGenSafe(*arg)) directSafe.add(*arg) ;
1892 }
1893
1894
1895 // Now find direct integrator for relevant components ;
1896 RooAbsPdf* pdf ;
1897 std::vector<Int_t> code;
1898 code.reserve(64);
1899 RooFIter pdfIter = _pdfList.fwdIterator();
1900 while((pdf=(RooAbsPdf*)pdfIter.next())) {
1901 RooArgSet pdfDirect ;
1902 Int_t pdfCode = pdf->getGenerator(directSafe,pdfDirect,staticInitOK);
1903 code.push_back(pdfCode);
1904 if (pdfCode != 0) {
1905 generateVars.add(pdfDirect) ;
1906 }
1907 }
1908
1909
1910 if (generateVars.getSize()>0) {
1911 Int_t masterCode = _genCode.store(code) ;
1912 return masterCode+1 ;
1913 } else {
1914 return 0 ;
1915 }
1916}
1917
1918
1919
1920////////////////////////////////////////////////////////////////////////////////
1921/// Forward one-time initialization call to component generation initialization
1922/// methods.
1923
1925{
1926 if (!_useDefaultGen) return ;
1927
1928 const std::vector<Int_t>& codeList = _genCode.retrieve(code-1) ;
1929 RooAbsPdf* pdf ;
1930 Int_t i(0) ;
1931 RooFIter pdfIter = _pdfList.fwdIterator();
1932 while((pdf=(RooAbsPdf*)pdfIter.next())) {
1933 if (codeList[i]!=0) {
1934 pdf->initGenerator(codeList[i]) ;
1935 }
1936 i++ ;
1937 }
1938}
1939
1940
1941
1942////////////////////////////////////////////////////////////////////////////////
1943/// Generate a single event with configuration specified by 'code'
1944/// Defer internal generation to components as encoded in the _genCode
1945/// registry for given generator code.
1946
1948{
1949 if (!_useDefaultGen) return ;
1950
1951 const std::vector<Int_t>& codeList = _genCode.retrieve(code-1) ;
1952 RooAbsPdf* pdf ;
1953 Int_t i(0) ;
1954 RooFIter pdfIter = _pdfList.fwdIterator();
1955 while((pdf=(RooAbsPdf*)pdfIter.next())) {
1956 if (codeList[i]!=0) {
1957 pdf->generateEvent(codeList[i]) ;
1958 }
1959 i++ ;
1960 }
1961}
1962
1963
1964
1965////////////////////////////////////////////////////////////////////////////////
1966/// Return RooAbsArg components contained in the cache
1967
1969{
1970 RooArgList ret ;
1971 ret.add(_partList) ;
1972 ret.add(_numList) ;
1973 ret.add(_denList) ;
1974 if (_rearrangedNum) ret.add(*_rearrangedNum) ;
1975 if (_rearrangedDen) ret.add(*_rearrangedDen) ;
1976 return ret ;
1977
1978}
1979
1980
1981
1982////////////////////////////////////////////////////////////////////////////////
1983/// Hook function to print cache contents in tree printing of RooProdPdf
1984
1985void RooProdPdf::CacheElem::printCompactTreeHook(ostream& os, const char* indent, Int_t curElem, Int_t maxElem)
1986{
1987 if (curElem==0) {
1988 os << indent << "RooProdPdf begin partial integral cache" << endl ;
1989 }
1990
1991 RooFIter iter = _partList.fwdIterator() ;
1992 RooAbsArg* arg ;
1993 TString indent2(indent) ;
1994 indent2 += Form("[%d] ",curElem) ;
1995 while((arg=(RooAbsArg*)iter.next())) {
1996 arg->printCompactTree(os,indent2) ;
1997 }
1998
1999 if (curElem==maxElem) {
2000 os << indent << "RooProdPdf end partial integral cache" << endl ;
2001 }
2002}
2003
2004
2005
2006////////////////////////////////////////////////////////////////////////////////
2007/// Forward determination of safety of internal generator code to
2008/// component p.d.f that would generate the given observable
2009
2011{
2012 // Only override base class behaviour if default generator method is enabled
2013 if (!_useDefaultGen) return RooAbsPdf::isDirectGenSafe(arg) ;
2014
2015 // Argument may appear in only one PDF component
2016 RooAbsPdf* pdf, *thePdf(0) ;
2017 RooFIter pdfIter = _pdfList.fwdIterator();
2018 while((pdf=(RooAbsPdf*)pdfIter.next())) {
2019
2020 if (pdf->dependsOn(arg)) {
2021 // Found PDF depending on arg
2022
2023 // If multiple PDFs depend on arg directGen is not safe
2024 if (thePdf) return kFALSE ;
2025
2026 thePdf = pdf ;
2027 }
2028 }
2029 // Forward call to relevant component PDF
2030 return thePdf?(thePdf->isDirectGenSafe(arg)):kFALSE ;
2031}
2032
2033
2034
2035////////////////////////////////////////////////////////////////////////////////
2036/// Look up user specified normalization set for given input PDF component
2037
2039{
2040 Int_t idx = _pdfList.index(&pdf) ;
2041 if (idx<0) return 0 ;
2042 return (RooArgSet*) _pdfNSetList.At(idx) ;
2043}
2044
2045
2046
2047////////////////////////////////////////////////////////////////////////////////
2048/// Return all parameter constraint p.d.f.s on parameters listed in constrainedParams.
2049/// The observables set is required to distinguish unambiguously p.d.f in terms
2050/// of observables and parameters, which are not constraints, and p.d.fs in terms
2051/// of parameters only, which can serve as constraints p.d.f.s
2052
2053RooArgSet* RooProdPdf::getConstraints(const RooArgSet& observables, RooArgSet& constrainedParams, Bool_t stripDisconnected) const
2054{
2055 RooArgSet constraints ;
2056 RooArgSet pdfParams, conParams ;
2057
2058 // Loop over p.d.f. components
2059 RooFIter piter = _pdfList.fwdIterator() ;
2060 RooAbsPdf* pdf ;
2061 while((pdf=(RooAbsPdf*)piter.next())) {
2062 // A constraint term is a p.d.f that does not depend on any of the listed observables
2063 // but does depends on any of the parameters that should be constrained
2064 if (!pdf->dependsOnValue(observables) && pdf->dependsOnValue(constrainedParams)) {
2065 constraints.add(*pdf) ;
2066 RooArgSet* tmp = pdf->getParameters(observables) ;
2067 conParams.add(*tmp,kTRUE) ;
2068 delete tmp ;
2069 } else {
2070 RooArgSet* tmp = pdf->getParameters(observables) ;
2071 pdfParams.add(*tmp,kTRUE) ;
2072 delete tmp ;
2073 }
2074 }
2075
2076 // Strip any constraints that are completely decoupled from the other product terms
2077 RooArgSet* finalConstraints = new RooArgSet("constraints") ;
2078 RooFIter citer = constraints.fwdIterator() ;
2079 while((pdf=(RooAbsPdf*)citer.next())) {
2080 if (pdf->dependsOnValue(pdfParams) || !stripDisconnected) {
2081 finalConstraints->add(*pdf) ;
2082 } else {
2083 coutI(Minimization) << "RooProdPdf::getConstraints(" << GetName() << ") omitting term " << pdf->GetName()
2084 << " as constraint term as it does not share any parameters with the other pdfs in product. "
2085 << "To force inclusion in likelihood, add an explicit Constrain() argument for the target parameter" << endl ;
2086 }
2087 }
2088
2089 // Now remove from constrainedParams all parameters that occur exclusively in constraint term and not in regular pdf term
2090
2091 RooArgSet* cexl = (RooArgSet*) conParams.selectCommon(constrainedParams) ;
2092 cexl->remove(pdfParams,kTRUE,kTRUE) ;
2093 constrainedParams.remove(*cexl,kTRUE,kTRUE) ;
2094 delete cexl ;
2095
2096 return finalConstraints ;
2097}
2098
2099
2100
2101
2102////////////////////////////////////////////////////////////////////////////////
2103/// Return all parameter constraint p.d.f.s on parameters listed in constrainedParams.
2104/// The observables set is required to distinguish unambiguously p.d.f in terms
2105/// of observables and parameters, which are not constraints, and p.d.fs in terms
2106/// of parameters only, which can serve as constraints p.d.f.s
2107
2109{
2110 RooArgSet* connectedPars = new RooArgSet("connectedPars") ;
2111 for (const auto arg : _pdfList) {
2112 // Check if term is relevant
2113 if (arg->dependsOn(observables)) {
2114 RooArgSet* tmp = arg->getParameters(observables) ;
2115 connectedPars->add(*tmp) ;
2116 delete tmp ;
2117 }
2118 }
2119 return connectedPars ;
2120}
2121
2122
2123
2124
2125////////////////////////////////////////////////////////////////////////////////
2126
2127void RooProdPdf::getParametersHook(const RooArgSet* nset, RooArgSet* params, Bool_t stripDisconnected) const
2128{
2129 if (!stripDisconnected) return ;
2130 if (!nset || nset->getSize()==0) return ;
2131
2132 // Get/create appropriate term list for this normalization set
2133 Int_t code = getPartIntList(nset, nullptr);
2134 RooArgList & plist = static_cast<CacheElem*>(_cacheMgr.getObj(nset, &code))->_partList;
2135
2136 // Strip any terms from params that do not depend on any term
2137 RooArgSet tostrip ;
2138 for (auto param : *params) {
2139 Bool_t anyDep(kFALSE) ;
2140 for (auto term : plist) {
2141 if (term->dependsOnValue(*param)) {
2142 anyDep=kTRUE ;
2143 }
2144 }
2145 if (!anyDep) {
2146 tostrip.add(*param) ;
2147 }
2148 }
2149
2150 if (tostrip.getSize()>0) {
2151 params->remove(tostrip,kTRUE,kTRUE);
2152 }
2153
2154}
2155
2156
2157
2158////////////////////////////////////////////////////////////////////////////////
2159/// Interface function used by test statistics to freeze choice of range
2160/// for interpretation of conditional product terms
2161
2162void RooProdPdf::selectNormalizationRange(const char* rangeName, Bool_t force)
2163{
2164 if (!force && _refRangeName) {
2165 return ;
2166 }
2167
2168 fixRefRange(rangeName) ;
2169}
2170
2171
2172
2173
2174////////////////////////////////////////////////////////////////////////////////
2175
2176void RooProdPdf::fixRefRange(const char* rangeName)
2177{
2178 _refRangeName = (TNamed*)RooNameReg::ptr(rangeName) ;
2179}
2180
2181
2182
2183////////////////////////////////////////////////////////////////////////////////
2184/// Forward the plot sampling hint from the p.d.f. that defines the observable obs
2185
2186std::list<Double_t>* RooProdPdf::plotSamplingHint(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const
2187{
2188 RooAbsPdf* pdf ;
2189 RooFIter pdfIter = _pdfList.fwdIterator();
2190 while((pdf=(RooAbsPdf*)pdfIter.next())) {
2191 list<Double_t>* hint = pdf->plotSamplingHint(obs,xlo,xhi) ;
2192 if (hint) {
2193 return hint ;
2194 }
2195 }
2196
2197 return 0 ;
2198}
2199
2200
2201
2202////////////////////////////////////////////////////////////////////////////////
2203/// If all components that depend on obs are binned that so is the product
2204
2206{
2207 RooAbsPdf* pdf ;
2208 RooFIter pdfIter = _pdfList.fwdIterator();
2209 while((pdf=(RooAbsPdf*)pdfIter.next())) {
2210 if (pdf->dependsOn(obs) && !pdf->isBinnedDistribution(obs)) {
2211 return kFALSE ;
2212 }
2213 }
2214
2215 return kTRUE ;
2216}
2217
2218
2219
2220
2221
2222
2223////////////////////////////////////////////////////////////////////////////////
2224/// Forward the plot sampling hint from the p.d.f. that defines the observable obs
2225
2226std::list<Double_t>* RooProdPdf::binBoundaries(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const
2227{
2228 RooAbsPdf* pdf ;
2229 RooFIter pdfIter = _pdfList.fwdIterator();
2230 while((pdf=(RooAbsPdf*)pdfIter.next())) {
2231 list<Double_t>* hint = pdf->binBoundaries(obs,xlo,xhi) ;
2232 if (hint) {
2233 return hint ;
2234 }
2235 }
2236
2237 return 0 ;
2238}
2239
2240
2241////////////////////////////////////////////////////////////////////////////////
2242/// Label OK'ed components of a RooProdPdf with cache-and-track, _and_ label all RooProdPdf
2243/// descendants with extra information about (conditional) normalization, needed to be able
2244/// to Cache-And-Track them outside the RooProdPdf context.
2245
2247{
2248 for (const auto parg : _pdfList) {
2249
2250 if (parg->canNodeBeCached()==Always) {
2251 trackNodes.add(*parg) ;
2252// cout << "tracking node RooProdPdf component " << parg << " " << parg->IsA()->GetName() << "::" << parg->GetName() << endl ;
2253
2254 // Additional processing to fix normalization sets in case product defines conditional observables
2255 RooArgSet* pdf_nset = findPdfNSet((RooAbsPdf&)(*parg)) ;
2256 if (pdf_nset) {
2257 // Check if conditional normalization is specified
2258 if (string("nset")==pdf_nset->GetName() && pdf_nset->getSize()>0) {
2259 RooNameSet n(*pdf_nset) ;
2260 parg->setStringAttribute("CATNormSet",n.content()) ;
2261 }
2262 if (string("cset")==pdf_nset->GetName()) {
2263 RooNameSet c(*pdf_nset) ;
2264 parg->setStringAttribute("CATCondSet",c.content()) ;
2265 }
2266 } else {
2267 coutW(Optimization) << "RooProdPdf::setCacheAndTrackHints(" << GetName() << ") WARNING product pdf does not specify a normalization set for component " << parg->GetName() << endl ;
2268 }
2269 }
2270 }
2271}
2272
2273
2274
2275////////////////////////////////////////////////////////////////////////////////
2276/// Customized printing of arguments of a RooProdPdf to more intuitively reflect the contents of the
2277/// product operator construction
2278
2279void RooProdPdf::printMetaArgs(ostream& os) const
2280{
2282 for (int i=0 ; i<_pdfList.getSize() ; i++) {
2283 if (i>0) os << " * " ;
2284 RooArgSet* ncset = (RooArgSet*) niter.next() ;
2285 os << _pdfList.at(i)->GetName() ;
2286 if (ncset->getSize()>0) {
2287 if (string("nset")==ncset->GetName()) {
2288 os << *ncset ;
2289 } else {
2290 os << "|" ;
2291 RooFIter nciter = ncset->fwdIterator() ;
2292 RooAbsArg* arg ;
2293 Bool_t first(kTRUE) ;
2294 while((arg=(RooAbsArg*)nciter.next())) {
2295 if (!first) {
2296 os << "," ;
2297 } else {
2298 first = kFALSE ;
2299 }
2300 os << arg->GetName() ;
2301 }
2302 }
2303 }
2304 }
2305 os << " " ;
2306}
2307
2308
2309
2310////////////////////////////////////////////////////////////////////////////////
2311/// Implement support for node removal
2312
2313Bool_t RooProdPdf::redirectServersHook(const RooAbsCollection& /*newServerList*/, Bool_t /*mustReplaceAll*/, Bool_t nameChange, Bool_t /*isRecursive*/)
2314{
2315 if (nameChange && _pdfList.find("REMOVAL_DUMMY")) {
2316
2317 cxcoutD(LinkStateMgmt) << "RooProdPdf::redirectServersHook(" << GetName() << "): removing REMOVAL_DUMMY" << endl ;
2318
2319 // Remove node from _pdfList proxy and remove corresponding entry from normset list
2320 RooAbsArg* pdfDel = _pdfList.find("REMOVAL_DUMMY") ;
2321
2322 TObject* setDel = _pdfNSetList.At(_pdfList.index("REMOVAL_DUMMY")) ;
2323 _pdfList.remove(*pdfDel) ;
2324 _pdfNSetList.Remove(setDel) ;
2325
2326 // Clear caches
2327 _cacheMgr.reset() ;
2328 }
2329 return kFALSE ;
2330}
void Class()
Definition: Class.C:29
#define c(i)
Definition: RSha256.hxx:101
#define coutI(a)
Definition: RooMsgService.h:31
#define cxcoutD(a)
Definition: RooMsgService.h:82
#define coutW(a)
Definition: RooMsgService.h:33
#define dologD(a)
Definition: RooMsgService.h:66
#define coutF(a)
Definition: RooMsgService.h:35
#define coutE(a)
Definition: RooMsgService.h:34
#define TRACE_DESTROY
Definition: RooTrace.h:23
#define TRACE_CREATE
Definition: RooTrace.h:22
int Int_t
Definition: RtypesCore.h:41
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
double Double_t
Definition: RtypesCore.h:55
const Bool_t kTRUE
Definition: RtypesCore.h:87
#define ClassImp(name)
Definition: Rtypes.h:365
char * R__STRTOK_R(char *str, const char *delim, char **saveptr)
Definition: Rtypes.h:486
static void indent(ostringstream &buf, int indent_level)
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)
Make a batch and return a span pointing to the pdf-local memory.
Definition: BatchData.cxx:83
RooSpan< double > makeWritableBatchUnInit(std::size_t begin, std::size_t batchSize)
Make a batch and return a span pointing to the pdf-local memory.
Definition: BatchData.cxx:58
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:71
RooExpensiveObjectCache & expensiveObjectCache() const
Definition: RooAbsArg.cxx:2176
RooArgSet * getObservables(const RooArgSet &set, Bool_t valueOnly=kTRUE) const
Return the observables of this pdf given a set of observables.
Definition: RooAbsArg.h:240
void printCompactTree(const char *indent="", const char *fileName=0, const char *namePat=0, RooAbsArg *client=0)
Print tree structure of expression tree on stdout, or to file if filename is specified.
Definition: RooAbsArg.cxx:1753
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:734
void setStringAttribute(const Text_t *key, const Text_t *value)
Associate string 'value' to this object under key 'key'.
Definition: RooAbsArg.cxx:293
virtual TObject * Clone(const char *newname=0) const
Make a clone of an object using the Streamer facility.
Definition: RooAbsArg.h:83
friend class RooArgSet
Definition: RooAbsArg.h:551
virtual void setExpensiveObjectCache(RooExpensiveObjectCache &cache)
Definition: RooAbsArg.h:500
const Text_t * getStringAttribute(const Text_t *key) const
Get string attribute mapped under key 'key'.
Definition: RooAbsArg.cxx:306
RooArgSet * getParameters(const RooAbsData *data, Bool_t stripDisconnected=kTRUE) const
Create a list of leaf nodes in the arg tree starting with ourself as top node that don't match any of...
Definition: RooAbsArg.cxx:548
void setAttribute(const Text_t *name, Bool_t value=kTRUE)
Set (default) or clear a named boolean attribute of this object.
Definition: RooAbsArg.cxx:261
Bool_t addOwnedComponents(const RooArgSet &comps)
Take ownership of the contents of 'comps'.
Definition: RooAbsArg.cxx:2115
Bool_t getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
Definition: RooAbsArg.cxx:284
Bool_t dependsOnValue(const RooAbsCollection &serverList, const RooAbsArg *ignoreArg=0) const
Definition: RooAbsArg.h:97
RooArgSet * getComponents() const
Definition: RooAbsArg.cxx:678
RooAbsCacheElement is the abstract base class for objects to be stored in RooAbsCache cache manager o...
RooAbsCollection is an abstract container object that can hold multiple RooAbsArg objects.
RooFIter fwdIterator() const R__SUGGEST_ALTERNATIVE("begin()
One-time forward iterator.
virtual void removeAll()
Remove all arguments from our set, deleting them if we own them.
RooAbsCollection * selectCommon(const RooAbsCollection &refColl) const
Create a subset of the current collection, consisting only of those elements that are contained as we...
Int_t getSize() const
Bool_t contains(const RooAbsArg &var) const
virtual Bool_t addOwned(RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
Int_t index(const RooAbsArg *arg) const
Returns index of given arg, or -1 if arg is not in the collection.
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
Bool_t overlaps(const RooAbsCollection &otherColl) const
Check if this and other collection have common entries.
const char * GetName() const
Returns name of object.
void setName(const char *name)
virtual Bool_t remove(const RooAbsArg &var, Bool_t silent=kFALSE, Bool_t matchByNameOnly=kFALSE)
Remove the specified argument from our list.
RooAbsArg * find(const char *name) const
Find object with given name in list.
virtual void printValue(std::ostream &os) const
Print value of collection, i.e.
RooAbsGenContext is the abstract base class for generator contexts of RooAbsPdf objects.
friend class CacheElem
Definition: RooAbsPdf.h:334
virtual void generateEvent(Int_t code)
Interface for generation of an event using the algorithm corresponding to the specified code.
Definition: RooAbsPdf.cxx:2453
virtual RooAbsGenContext * genContext(const RooArgSet &vars, const RooDataSet *prototype=0, const RooArgSet *auxProto=0, Bool_t verbose=kFALSE) const
Interface function to create a generator context from a p.d.f.
Definition: RooAbsPdf.cxx:2033
TString _normRange
MC generator configuration specific for this object.
Definition: RooAbsPdf.h:355
virtual Int_t getGenerator(const RooArgSet &directVars, RooArgSet &generateVars, Bool_t staticInitOK=kTRUE) const
Load generatedVars with the subset of directVars that we can generate events for, and return a code t...
Definition: RooAbsPdf.cxx:2431
Bool_t canBeExtended() const
Definition: RooAbsPdf.h:237
friend class RooRealIntegral
Definition: RooAbsPdf.h:314
virtual Double_t getValV(const RooArgSet *set=0) const
Return current value, normalized by integrating over the observables in nset.
Definition: RooAbsPdf.cxx:281
@ CanNotBeExtended
Definition: RooAbsPdf.h:230
const char * normRange() const
Definition: RooAbsPdf.h:261
virtual Bool_t isDirectGenSafe(const RooAbsArg &arg) const
Check if given observable can be safely generated using the pdfs internal generator mechanism (if tha...
Definition: RooAbsPdf.cxx:2466
virtual void initGenerator(Int_t code)
Interface for one-time initialization to setup the generator for the specified code.
Definition: RooAbsPdf.cxx:2441
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:59
Bool_t _forceNumInt
Definition: RooAbsReal.h:450
virtual std::list< Double_t > * plotSamplingHint(RooAbsRealLValue &, Double_t, Double_t) const
Definition: RooAbsReal.h:311
TString integralNameSuffix(const RooArgSet &iset, const RooArgSet *nset=0, const char *rangeName=0, Bool_t omitEmpty=kFALSE) const
Construct string with unique suffix name to give to integral object that encodes integrated observabl...
Definition: RooAbsReal.cxx:809
virtual RooSpan< const double > getValBatch(std::size_t begin, std::size_t maxSize, const RooArgSet *normSet=nullptr) const
Return value of object for all data events in the batch.
Definition: RooAbsReal.cxx:296
virtual std::list< Double_t > * binBoundaries(RooAbsRealLValue &, Double_t, Double_t) const
Definition: RooAbsReal.h:310
Double_t getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition: RooAbsReal.h:87
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:562
BatchHelpers::BatchData _batchData
Definition: RooAbsReal.h:447
virtual Bool_t isBinnedDistribution(const RooArgSet &) const
Definition: RooAbsReal.h:309
RooAddition calculates the sum of a set of RooAbsReal terms, or when constructed with two sets,...
Definition: RooAddition.h:26
const RooArgList & list1() const
Definition: RooAddition.h:41
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
RooArgSet * snapshot(bool deepCopy=true) const
Use RooAbsCollection::snapshot(), but return as RooArgSet.
Definition: RooArgSet.h:134
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)
const RooNameSet * nameSet2ByIndex(Int_t index) const
Retrieve RooNameSet associated with slot at given index.
T * getObjByIndex(Int_t index) const
Retrieve payload object by slot index.
void reset()
Clear the cache.
Int_t lastIndex() const
const RooNameSet * nameSet1ByIndex(Int_t index) const
Retrieve RooNameSet associated with slot at given index.
Int_t setObj(const RooArgSet *nset, T *obj, const TNamed *isetRangeName=0)
RooCmdArg is a named container for two doubles, two integers two object points and three string point...
Definition: RooCmdArg.h:28
const RooArgSet * getSet(Int_t idx) const
Return RooArgSet stored in slot idx.
Definition: RooCmdArg.cxx:200
Int_t getInt(Int_t idx) const
Definition: RooCmdArg.h:81
virtual TObject * clone(const char *newname) const
Definition: RooConstVar.h:31
RooCustomizer is a factory class to produce clones of a prototype composite PDF object with the same ...
Definition: RooCustomizer.h:32
void replaceArg(const RooAbsArg &orig, const RooAbsArg &subst)
Replace any occurence of arg 'orig' with arg 'subst'.
RooAbsArg * build(const char *masterCatState, Bool_t verbose=kFALSE)
Build a clone of the prototype executing all registered 'replace' rules and 'split' rules for the mas...
RooDataSet is a container class to hold unbinned data.
Definition: RooDataSet.h:31
A one-time forward iterator working on RooLinkedList or RooAbsCollection.
RooAbsArg * next()
Return next element or nullptr if at end.
A RooFormulaVar is a generic implementation of a real-valued object, which takes a RooArgList of serv...
Definition: RooFormulaVar.h:29
RooAbsArg * getParameter(const char *name) const
Definition: RooFormulaVar.h:40
RooGenProdProj is an auxiliary class for RooProdPdf that calculates a general normalised projection o...
RooLinkedList is an collection class for internal use, storing a collection of RooAbsArg pointers in ...
Definition: RooLinkedList.h:36
RooFIter fwdIterator() const
Create a one-time-use forward iterator for this list.
TObject * At(Int_t index) const
Return object stored in sequential position given by index.
void Delete(Option_t *o=0)
Remove all elements in collection and delete all elements NB: Collection does not own elements,...
virtual void Add(TObject *arg)
Definition: RooLinkedList.h:63
virtual Bool_t Remove(TObject *arg)
Remove object from collection.
Int_t IndexOf(const char *name) const
Return position of given object in list.
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Reimplementation of standard RooArgList::add()
virtual Bool_t remove(const RooAbsArg &var, Bool_t silent=kFALSE, Bool_t matchByNameOnly=kFALSE)
Reimplementation of standard RooArgList::remove()
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
RooNameSet is a utility class that stores the names the objects in a RooArget.
Definition: RooNameSet.h:24
RooArgSet * select(const RooArgSet &list) const
Construct a RooArgSet of objects in input 'list' whose names match to those in the internal name list...
Definition: RooNameSet.cxx:187
virtual void printCompactTreeHook(std::ostream &, const char *, Int_t, Int_t)
Hook function to print cache contents in tree printing of RooProdPdf.
std::unique_ptr< RooAbsReal > _rearrangedNum
Definition: RooProdPdf.h:142
RooArgList _ownedList
Definition: RooProdPdf.h:139
RooArgList _partList
Definition: RooProdPdf.h:136
std::vector< std::unique_ptr< RooArgSet > > _normList
Definition: RooProdPdf.h:140
std::unique_ptr< RooAbsReal > _rearrangedDen
Definition: RooProdPdf.h:143
virtual RooArgList containedArgs(Action)
Return RooAbsArg components contained in the cache.
RooProdPdf is an efficient implementation of a product of PDFs of the form.
Definition: RooProdPdf.h:31
void rearrangeProduct(CacheElem &) const
virtual Double_t expectedEvents(const RooArgSet *nset) const
Return the expected number of events associated with the extendable input PDF in the product.
void factorizeProduct(const RooArgSet &normSet, const RooArgSet &intSet, RooLinkedList &termList, RooLinkedList &normList, RooLinkedList &impDepList, RooLinkedList &crossDepList, RooLinkedList &intList) const
Factorize product in irreducible terms for given choice of integration/normalization.
Definition: RooProdPdf.cxx:566
void groupProductTerms(RooLinkedList &groupedTerms, RooArgSet &outerIntDeps, const RooLinkedList &terms, const RooLinkedList &norms, const RooLinkedList &imps, const RooLinkedList &ints, const RooLinkedList &cross) const
Group product into terms that can be calculated independently.
RooArgSet * _curNormSet
Registry of composite direct generator codes.
Definition: RooProdPdf.h:165
Int_t _extendedIndex
Definition: RooProdPdf.h:169
Int_t getPartIntList(const RooArgSet *nset, const RooArgSet *iset, const char *isetRangeName=0) const
Return list of (partial) integrals of product terms for integration of p.d.f over observables iset wh...
Definition: RooProdPdf.cxx:751
RooProdPdf()
Default constructor.
Definition: RooProdPdf.cxx:83
virtual Bool_t checkObservables(const RooArgSet *nset) const
Obsolete.
Double_t _cutOff
Definition: RooProdPdf.h:166
void printMetaArgs(std::ostream &os) const
Customized printing of arguments of a RooProdPdf to more intuitively reflect the contents of the prod...
Double_t evaluate() const
Calculate current value of object.
Definition: RooProdPdf.cxx:465
TNamed * _refRangeName
Definition: RooProdPdf.h:174
RooAICRegistry _genCode
Definition: RooProdPdf.h:163
RooListProxy _pdfList
Definition: RooProdPdf.h:167
Bool_t isBinnedDistribution(const RooArgSet &obs) const
If all components that depend on obs are binned that so is the product.
virtual Bool_t isDirectGenSafe(const RooAbsArg &arg) const
Forward determination of safety of internal generator code to component p.d.f that would generate the...
Bool_t _useDefaultGen
Definition: RooProdPdf.h:172
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.
RooAbsReal * specializeIntegral(RooAbsReal &orig, const char *targetRangeName) const
virtual ExtendMode extendMode() const
If this product contains exactly one extendable p.d.f return the extension abilities of that p....
RooObjCacheManager _cacheMgr
Definition: RooProdPdf.h:150
virtual void initGenerator(Int_t code)
Forward one-time initialization call to component generation initialization methods.
std::string makeRGPPName(const char *pfx, const RooArgSet &term, const RooArgSet &iset, const RooArgSet &nset, const char *isetRangeName) const
Make an appropriate automatic name for a RooGenProdProj object in getPartIntList()
Double_t analyticalIntegralWN(Int_t code, const RooArgSet *normSet, const char *rangeName=0) const
Return analytical integral defined by given scenario code.
virtual ~RooProdPdf()
Destructor.
Definition: RooProdPdf.cxx:443
virtual void getParametersHook(const RooArgSet *, RooArgSet *, Bool_t stripDisconnected) const
virtual Double_t getValV(const RooArgSet *set=0) const
Overload getVal() to intercept normalization set for use in evaluate()
Definition: RooProdPdf.cxx:454
RooAbsReal * makeCondPdfRatioCorr(RooAbsReal &term, const RooArgSet &termNset, const RooArgSet &termImpSet, const char *normRange, const char *refRange) const
For single normalization ranges.
RooArgSet * findPdfNSet(RooAbsPdf &pdf) const
Look up user specified normalization set for given input PDF component.
virtual RooSpan< double > evaluateBatch(std::size_t begin, std::size_t size) const
Evaluate function for a batch of input data points.
Definition: RooProdPdf.cxx:517
virtual void setCacheAndTrackHints(RooArgSet &)
Label OK'ed components of a RooProdPdf with cache-and-track, and label all RooProdPdf descendants wit...
virtual RooArgSet * getConstraints(const RooArgSet &observables, RooArgSet &constrainedParams, Bool_t stripDisconnected) const
Return all parameter constraint p.d.f.s on parameters listed in constrainedParams.
RooLinkedList _pdfNSetList
Definition: RooProdPdf.h:168
friend class RooProdGenContext
Definition: RooProdPdf.h:158
virtual Int_t getGenerator(const RooArgSet &directVars, RooArgSet &generateVars, Bool_t staticInitOK=kTRUE) const
Query internal generation capabilities of component p.d.f.s and aggregate capabilities into master co...
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 conditiona...
RooArgSet * getConnectedParameters(const RooArgSet &observables) const
Return all parameter constraint p.d.f.s on parameters listed in constrainedParams.
Double_t calculate(const RooProdPdf::CacheElem &cache, Bool_t verbose=kFALSE) const
Calculate running product of pdfs terms, using the supplied normalization set in 'normSetList' for ea...
Definition: RooProdPdf.cxx:486
RooArgSet _defNormSet
Definition: RooProdPdf.h:177
virtual std::list< Double_t > * plotSamplingHint(RooAbsRealLValue &obs, Double_t xlo, Double_t xhi) const
Forward the plot sampling hint from the p.d.f. that defines the observable obs.
RooAbsReal * specializeRatio(RooFormulaVar &input, const char *targetRangeName) const
Bool_t redirectServersHook(const RooAbsCollection &, Bool_t, Bool_t, Bool_t)
Implement support for node removal.
void fixRefRange(const char *rangeName)
virtual Bool_t forceAnalyticalInt(const RooAbsArg &dep) const
Force RooRealIntegral to offer all observables for internal integration.
virtual TObject * clone(const char *newname) const
Definition: RooProdPdf.h:53
virtual RooAbsGenContext * genContext(const RooArgSet &vars, const RooDataSet *prototype=0, const RooArgSet *auxProto=0, Bool_t verbose=kFALSE) const
Return generator context optimized for generating events from product p.d.f.s.
void initializeFromCmdArgList(const RooArgSet &fullPdfSet, const RooLinkedList &l)
Initialize RooProdPdf configuration from given list of RooCmdArg configuration arguments and set of '...
Definition: RooProdPdf.cxx:376
virtual void generateEvent(Int_t code)
Generate a single event with configuration specified by 'code' Defer internal generation to component...
std::vector< RooAbsReal * > processProductTerm(const RooArgSet *nset, const RooArgSet *iset, const char *isetRangeName, const RooArgSet *term, const RooArgSet &termNSet, const RooArgSet &termISet, Bool_t &isOwned, Bool_t forceWrap=kFALSE) const
Calculate integrals of factorized product terms over observables iset while normalized to observables...
virtual std::list< Double_t > * binBoundaries(RooAbsRealLValue &, Double_t, Double_t) const
Forward the plot sampling hint from the p.d.f. that defines the observable obs.
A RooProduct represents the product of a given set of RooAbsReal objects.
Definition: RooProduct.h:32
RooArgList components()
Definition: RooProduct.h:47
RooRealIntegral performs hybrid numerical/analytical integrals of RooAbsReal objects.
RooArgSet intVars() const
const RooAbsReal & integrand() const
const char * intRange()
RooRealVar represents a variable that can be changed from the outside.
Definition: RooRealVar.h:35
A simple container to hold a batch of data values.
Definition: RooSpan.h:32
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
Mother of all ROOT objects.
Definition: TObject.h:37
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
const char * Data() const
Definition: TString.h:364
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
const Int_t n
Definition: legend1.C:16
R__EXTERN PyObject * gIter
Definition: PyStrings.h:28
@ Minimization
Definition: RooGlobalFunc.h:67
@ Generation
Definition: RooGlobalFunc.h:67
@ Optimization
Definition: RooGlobalFunc.h:68
@ InputArguments
Definition: RooGlobalFunc.h:68
@ LinkStateMgmt
Definition: RooGlobalFunc.h:67
RooConstVar & RooConst(Double_t val)
Definition: first.py:1
auto * l
Definition: textangle.C:4