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