Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooAbsAnaConvPdf.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
11 * *
12 * Redistribution and use in source and binary forms, *
13 * with or without modification, are permitted according to the terms *
14 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15 *****************************************************************************/
16
17//////////////////////////////////////////////////////////////////////////////
18/// \class RooAbsAnaConvPdf
19/// \ingroup Roofitcore
20///
21/// Base class for PDFs that represent a
22/// physics model that can be analytically convolved with a resolution model.
23///
24/// To achieve factorization between the physics model and the resolution
25/// model, each physics model must be able to be written in the form
26/// \f[
27/// \mathrm{Phys}(x, \bar{a}, \bar{b}) = \sum_k \mathrm{coef}_k(\bar{a}) * \mathrm{basis}_k(x,\bar{b})
28/// \f]
29///
30/// where \f$ \mathrm{basis}_k \f$ are a limited number of functions in terms of the variable
31/// to be convoluted, and \f$ \mathrm{coef}_k \f$ are coefficients independent of the convolution
32/// variable.
33///
34/// Classes derived from RooResolutionModel implement
35/// \f[
36/// R_k(x,\bar{b},\bar{c}) = \int \mathrm{basis}_k(x', \bar{b}) \cdot \mathrm{resModel}(x-x',\bar{c}) \; \mathrm{d}x',
37/// \f]
38///
39/// which RooAbsAnaConvPdf uses to construct the pdf for [ Phys (x) R ] :
40/// \f[
41/// \mathrm{PDF}(x,\bar{a},\bar{b},\bar{c}) = \sum_k \mathrm{coef}_k(\bar{a}) * R_k(x,\bar{b},\bar{c})
42/// \f]
43///
44/// A minimal implementation of a RooAbsAnaConvPdf physics model consists of
45///
46/// - A constructor that declares the required basis functions using the declareBasis() method.
47/// The declareBasis() function assigns a unique identifier code to each declare basis
48///
49/// - An implementation of `coefficient(Int_t code)` returning the coefficient value for each
50/// declared basis function
51///
52/// Optionally, analytical integrals can be provided for the coefficient functions. The
53/// interface for this is quite similar to that for integrals of regular PDFs. Two functions,
54/// \code{.cpp}
55/// Int_t getCoefAnalyticalIntegral(Int_t coef, RooArgSet& allVars, RooArgSet& analVars, const char* rangeName) const
56/// double coefAnalyticalIntegral(Int_t coef, Int_t code, const char* rangeName) const
57/// \endcode
58///
59/// advertise the coefficient integration capabilities and implement them respectively.
60/// Please see RooAbsPdf for additional details. Advertised analytical integrals must be
61/// valid for all coefficients.
62
63#include "RooAbsAnaConvPdf.h"
64
65#include "RooNormalizedPdf.h"
66#include "RooMsgService.h"
67#include "Riostream.h"
68#include "RooResolutionModel.h"
69#include "RooRealVar.h"
70#include "RooFormulaVar.h"
71#include "RooConvGenContext.h"
72#include "RooGenContext.h"
73#include "RooTruthModel.h"
74#include "RooConvCoefVar.h"
75#include "RooNameReg.h"
76
77using std::endl, std::string, std::ostream;
78
80
81
82////////////////////////////////////////////////////////////////////////////////
83/// Default constructor, required for persistence
84
86 _isCopy(false),
87 _coefNormMgr(this,10)
88{
89}
90
91
92
93////////////////////////////////////////////////////////////////////////////////
94/// Constructor. The supplied resolution model must be constructed with the same
95/// convoluted variable as this physics model ('convVar')
96
97RooAbsAnaConvPdf::RooAbsAnaConvPdf(const char *name, const char *title,
98 const RooResolutionModel& model, RooRealVar& cVar) :
99 RooAbsPdf(name,title), _isCopy(false),
100 _model("!model","Original resolution model",this,(RooResolutionModel&)model,false,false),
101 _convVar("!convVar","Convolution variable",this,cVar,false,false),
102 _convSet("!convSet","Set of resModel X basisFunc convolutions",this),
103 _coefNormMgr(this,10),
104 _codeReg(10)
105{
106 _model.absArg()->setAttribute("NOCacheAndTrack") ;
107}
108
109
110
111////////////////////////////////////////////////////////////////////////////////
112
114 RooAbsPdf(other,name), _isCopy(true),
115 _model("!model",this,other._model),
116 _convVar("!convVar",this,other._convVar),
117 _convSet("!convSet",this,other._convSet),
118 _coefNormMgr(other._coefNormMgr,this),
119 _codeReg(other._codeReg)
120{
121 // Copy constructor
122 if (_model.absArg()) {
123 _model.absArg()->setAttribute("NOCacheAndTrack") ;
124 }
126}
127
128
129
130////////////////////////////////////////////////////////////////////////////////
131/// Destructor
132
134{
135 if (!_isCopy) {
136 std::vector<RooAbsArg*> tmp(_convSet.begin(), _convSet.end());
137
138 for (auto arg : tmp) {
139 _convSet.remove(*arg) ;
140 delete arg ;
141 }
142 }
143
144}
145
146
147////////////////////////////////////////////////////////////////////////////////
148/// Declare a basis function for use in this physics model. The string expression
149/// must be a valid RooFormulVar expression representing the basis function, referring
150/// to the convolution variable as '@0', and any additional parameters (supplied in
151/// 'params' as '@1','@2' etc.
152///
153/// The return value is a unique identifier code, that will be passed to coefficient()
154/// to identify the basis function for which the coefficient is requested. If the
155/// resolution model used does not support the declared basis function, code -1 is
156/// returned.
157///
158
159Int_t RooAbsAnaConvPdf::declareBasis(const char* expression, const RooArgList& params)
160{
161 // Sanity check
162 if (_isCopy) {
163 coutE(InputArguments) << "RooAbsAnaConvPdf::declareBasis(" << GetName() << "): ERROR attempt to "
164 << " declare basis functions in a copied RooAbsAnaConvPdf" << endl ;
165 return -1 ;
166 }
167
168 // Resolution model must support declared basis
169 if (!(static_cast<RooResolutionModel*>(_model.absArg()))->isBasisSupported(expression)) {
170 coutE(InputArguments) << "RooAbsAnaConvPdf::declareBasis(" << GetName() << "): resolution model "
171 << _model.absArg()->GetName()
172 << " doesn't support basis function " << expression << endl ;
173 return -1 ;
174 }
175
176 // Instantiate basis function
177 RooArgList basisArgs(_convVar.arg()) ;
178 basisArgs.add(params) ;
179
180 TString basisName(expression) ;
181 for (const auto arg : basisArgs) {
182 basisName.Append("_") ;
183 basisName.Append(arg->GetName()) ;
184 }
185
186 auto basisFunc = std::make_unique<RooFormulaVar>(basisName, expression, basisArgs);
187 basisFunc->setAttribute("RooWorkspace::Recycle") ;
188 basisFunc->setAttribute("NOCacheAndTrack") ;
189 basisFunc->setOperMode(operMode()) ;
190
191 // Instantiate resModel x basisFunc convolution
192 RooAbsReal* conv = static_cast<RooResolutionModel*>(_model.absArg())->convolution(basisFunc.get(),this);
193 _basisList.addOwned(std::move(basisFunc));
194 if (!conv) {
195 coutE(InputArguments) << "RooAbsAnaConvPdf::declareBasis(" << GetName() << "): unable to construct convolution with basis function '"
196 << expression << "'" << endl ;
197 return -1 ;
198 }
199 _convSet.add(*conv) ;
200
201 return _convSet.index(conv) ;
202}
203
204
205
206////////////////////////////////////////////////////////////////////////////////
207/// Change the current resolution model to newModel
208
210{
211 RooArgList newConvSet ;
212 bool allOK(true) ;
213 for (auto convArg : _convSet) {
214 auto conv = static_cast<RooResolutionModel*>(convArg);
215
216 // Build new resolution model
217 std::unique_ptr<RooResolutionModel> newConv{newModel.convolution(const_cast<RooFormulaVar*>(&conv->basis()),this)};
218 if (!newConvSet.addOwned(std::move(newConv))) {
219 allOK = false ;
220 break ;
221 }
222 }
223
224 // Check if all convolutions were successfully built
225 if (!allOK) {
226 return true ;
227 }
228
229 // Replace old convolutions with new set
231 _convSet.addOwned(std::move(newConvSet));
232
233 const std::string attrib = std::string("ORIGNAME:") + _model->GetName();
234 const bool oldAttrib = newModel.getAttribute(attrib.c_str());
235 const_cast<RooResolutionModel&>(newModel).setAttribute(attrib.c_str());
236
237 redirectServers(RooArgSet{newModel}, false, true);
238
239 // reset temporary attribute for server redirection
240 const_cast<RooResolutionModel&>(newModel).setAttribute(attrib.c_str(), oldAttrib);
241
242 return false ;
243}
244
245
246
247
248////////////////////////////////////////////////////////////////////////////////
249/// Create a generator context for this p.d.f. If both the p.d.f and the resolution model
250/// support internal generation of the convolution observable on an infinite domain,
251/// deploy a specialized convolution generator context, which generates the physics distribution
252/// and the smearing separately, adding them a posteriori. If this is not possible return
253/// a (slower) generic generation context that uses accept/reject sampling
254
256 const RooArgSet* auxProto, bool verbose) const
257{
258 // Check if the resolution model specifies a special context to be used.
259 RooResolutionModel* conv = dynamic_cast<RooResolutionModel*>(_model.absArg());
260 assert(conv);
261
262 std::unique_ptr<RooArgSet> modelDep {_model->getObservables(&vars)};
263 modelDep->remove(*convVar(),true,true) ;
264 Int_t numAddDep = modelDep->size() ;
265
266 // Check if physics PDF and resolution model can both directly generate the convolution variable
267 RooArgSet dummy ;
268 bool pdfCanDir = (getGenerator(*convVar(),dummy) != 0) ;
269 bool resCanDir = conv && (conv->getGenerator(*convVar(),dummy)!=0) && conv->isDirectGenSafe(*convVar()) ;
270
271 if (numAddDep>0 || !pdfCanDir || !resCanDir) {
272 // Any resolution model with more dependents than the convolution variable
273 // or pdf or resmodel do not support direct generation
274 string reason ;
275 if (numAddDep>0) reason += "Resolution model has more observables than the convolution variable. " ;
276 if (!pdfCanDir) reason += "PDF does not support internal generation of convolution observable. " ;
277 if (!resCanDir) reason += "Resolution model does not support internal generation of convolution observable. " ;
278
279 coutI(Generation) << "RooAbsAnaConvPdf::genContext(" << GetName() << ") Using regular accept/reject generator for convolution p.d.f because: " << reason.c_str() << endl ;
280 return new RooGenContext(*this,vars,prototype,auxProto,verbose) ;
281 }
282
283 RooAbsGenContext* context = conv->modelGenContext(*this, vars, prototype, auxProto, verbose);
284 if (context) return context;
285
286 // Any other resolution model: use specialized generator context
287 return new RooConvGenContext(*this,vars,prototype,auxProto,verbose) ;
288}
289
290
291
292////////////////////////////////////////////////////////////////////////////////
293/// Return true if it is safe to generate the convolution observable
294/// from the internal generator (this is the case if the chosen resolution
295/// model is the truth model)
296
298{
299
300 // All direct generation of convolution arg if model is truth model
301 if (!TString(_convVar.absArg()->GetName()).CompareTo(arg.GetName()) &&
302 dynamic_cast<RooTruthModel*>(_model.absArg())) {
303 return true ;
304 }
305
306 return RooAbsPdf::isDirectGenSafe(arg) ;
307}
308
309
310
311////////////////////////////////////////////////////////////////////////////////
312/// Return a pointer to the convolution variable instance used in the resolution model
313
315{
316 auto* conv = static_cast<RooResolutionModel*>(_convSet.at(0));
317 if (!conv) return nullptr;
318 return &conv->convVar() ;
319}
320
321
322
323////////////////////////////////////////////////////////////////////////////////
324/// Calculate the current unnormalized value of the PDF
325///
326/// PDF = sum_k coef_k * [ basis_k (x) ResModel ]
327///
328
330{
331 double result(0) ;
332
333 Int_t index(0) ;
334 for (auto convArg : _convSet) {
335 auto conv = static_cast<RooAbsPdf*>(convArg);
336 double coef = coefficient(index++) ;
337 if (coef!=0.) {
338 const double c = conv->getVal(nullptr);
339 cxcoutD(Eval) << "RooAbsAnaConvPdf::evaluate(" << GetName() << ") val += coef*conv [" << index-1 << "/"
340 << _convSet.size() << "] coef = " << coef << " conv = " << c << endl ;
341 result += c * coef;
342 } else {
343 cxcoutD(Eval) << "RooAbsAnaConvPdf::evaluate(" << GetName() << ") [" << index-1 << "/" << _convSet.size() << "] coef = 0" << endl ;
344 }
345 }
346
347 return result ;
348}
349
350
351
352////////////////////////////////////////////////////////////////////////////////
353/// Advertise capability to perform (analytical) integrals
354/// internally. For a given integration request over allVars while
355/// normalized over normSet2 and in range 'rangeName', returns
356/// largest subset that can be performed internally in analVars
357/// Return code is unique integer code identifying integration scenario
358/// to be passed to analyticalIntegralWN() to calculate requeste integral
359///
360/// Class RooAbsAnaConv defers analytical integration request to
361/// resolution model and/or coefficient implementations and
362/// aggregates results into composite configuration with a unique
363/// code assigned by RooAICRegistry
364
366 RooArgSet& analVars, const RooArgSet* normSet2, const char* /*rangeName*/) const
367{
368 // Handle trivial no-integration scenario
369 if (allVars.empty()) return 0 ;
370
371 if (_forceNumInt) return 0 ;
372
373 // Select subset of allVars that are actual dependents
374 RooArgSet allDeps;
375 getObservables(&allVars, allDeps);
376 std::unique_ptr<RooArgSet> normSet{normSet2 ? getObservables(normSet2) : nullptr};
377
378 RooArgSet intSetAll{allDeps,"intSetAll"};
379
380 // Split intSetAll in coef/conv parts
381 auto intCoefSet = std::make_unique<RooArgSet>("intCoefSet");
382 auto intConvSet = std::make_unique<RooArgSet>("intConvSet");
383
384 for (RooAbsArg * arg : intSetAll) {
385 bool ok(true) ;
386 for (RooAbsArg * conv : _convSet) {
387 if (conv->dependsOn(*arg)) ok=false ;
388 }
389
390 if (ok) {
391 intCoefSet->add(*arg) ;
392 } else {
393 intConvSet->add(*arg) ;
394 }
395
396 }
397
398 // Split normSetAll in coef/conv parts
399 auto normCoefSet = std::make_unique<RooArgSet>("normCoefSet");
400 auto normConvSet = std::make_unique<RooArgSet>("normConvSet");
401 if (normSet) {
402 for (RooAbsArg * arg : *normSet) {
403 bool ok(true) ;
404 for (RooAbsArg * conv : _convSet) {
405 if (conv->dependsOn(*arg)) ok=false ;
406 }
407
408 if (ok) {
409 normCoefSet->add(*arg) ;
410 } else {
411 normConvSet->add(*arg) ;
412 }
413
414 }
415 }
416
417 if (intCoefSet->empty()) intCoefSet.reset();
418 if (intConvSet->empty()) intConvSet.reset();
419 if (normCoefSet->empty()) normCoefSet.reset();
420 if (normConvSet->empty()) normConvSet.reset();
421
422
423 // Store integration configuration in registry
424 Int_t masterCode(0) ;
425 std::vector<Int_t> tmp(1, 0) ;
426
427 // takes ownership of all sets
428 masterCode = _codeReg.store(tmp,
429 intCoefSet.release(),
430 intConvSet.release(),
431 normCoefSet.release(),
432 normConvSet.release()) + 1;
433
434 analVars.add(allDeps) ;
435
436 return masterCode ;
437}
438
439
440
441
442////////////////////////////////////////////////////////////////////////////////
443/// Return analytical integral defined by given code, which is returned
444/// by getAnalyticalIntegralWN()
445///
446/// For unnormalized integrals the returned value is
447/// \f[
448/// \mathrm{PDF} = \sum_k \int \mathrm{coef}_k \; \mathrm{d}\bar{x}
449/// \cdot \int \mathrm{basis}_k (x) \mathrm{ResModel} \; \mathrm{d}\bar{y},
450/// \f]
451/// where \f$ \bar{x} \f$ is the set of coefficient dependents to be integrated,
452/// and \f$ \bar{y} \f$ the set of basis function dependents to be integrated.
453///
454/// For normalized integrals this becomes
455/// \f[
456/// \mathrm{PDF} = \frac{\sum_k \int \mathrm{coef}_k \; \mathrm{d}x
457/// \cdot \int \mathrm{basis}_k (x) \mathrm{ResModel} \; \mathrm{d}y}
458/// {\sum_k \int \mathrm{coef}_k \; \mathrm{d}v
459/// \cdot \int \mathrm{basis}_k (x) \mathrm{ResModel} \; \mathrm{d}w},
460/// \f]
461/// where
462/// * \f$ x \f$ is the set of coefficient dependents to be integrated,
463/// * \f$ y \f$ the set of basis function dependents to be integrated,
464/// * \f$ v \f$ is the set of coefficient dependents over which is normalized and
465/// * \f$ w \f$ is the set of basis function dependents over which is normalized.
466///
467/// Set \f$ x \f$ must be contained in \f$ v \f$ and set \f$ y \f$ must be contained in \f$ w \f$.
468///
469
470double RooAbsAnaConvPdf::analyticalIntegralWN(Int_t code, const RooArgSet *normSet, const char *rangeName) const
471{
472 // WVE needs adaptation to handle new rangeName feature
473
474 // Handle trivial passthrough scenario
475 if (code == 0)
476 return getVal(normSet);
477
478 // Unpack master code
479 RooArgSet *intCoefSet;
480 RooArgSet *intConvSet;
481 RooArgSet *normCoefSet;
482 RooArgSet *normConvSet;
483 _codeReg.retrieve(code - 1, intCoefSet, intConvSet, normCoefSet, normConvSet);
484
485 Int_t index(0);
486
487 if (normCoefSet == nullptr && normConvSet == nullptr) {
488 // Integral over unnormalized function
489 double integral(0);
490 const TNamed *rangeNamePtr = RooNameReg::ptr(rangeName);
491 for (auto *conv : static_range_cast<RooAbsPdf *>(_convSet)) {
492 double coef = getCoefNorm(index++, intCoefSet, rangeNamePtr);
493 if (coef != 0) {
494 const double term = coef * conv->getNormObj(nullptr, intConvSet, rangeNamePtr)->getVal();
495 integral += term;
496 cxcoutD(Eval) << "RooAbsAnaConv::aiWN(" << GetName() << ") [" << index - 1 << "] integral += " << term
497 << std::endl;
498 }
499 }
500 return integral;
501 }
502
503 // Integral over normalized function
504 double integral(0);
505 double norm(0);
506 const TNamed *rangeNamePtr = RooNameReg::ptr(rangeName);
507 for (auto *conv : static_range_cast<RooAbsPdf *>(_convSet)) {
508
509 double coefInt = getCoefNorm(index, intCoefSet, rangeNamePtr);
510 if (coefInt != 0) {
511 double term = conv->getNormObj(nullptr, intConvSet, rangeNamePtr)->getVal();
512 integral += coefInt * term;
513 }
514
515 double coefNorm = getCoefNorm(index, normCoefSet);
516 if (coefNorm != 0) {
517 double term = conv->getNormObj(nullptr, normConvSet)->getVal();
518 norm += coefNorm * term;
519 }
520
521 index++;
522 }
523 return integral / norm;
524}
525
526
527
528////////////////////////////////////////////////////////////////////////////////
529/// Default implementation of function advertising integration capabilities. The interface is
530/// similar to that of getAnalyticalIntegral except that an integer code is added that
531/// designates the coefficient number for which the integration capabilities are requested
532///
533/// This default implementation advertises that no internal integrals are supported.
534
535Int_t RooAbsAnaConvPdf::getCoefAnalyticalIntegral(Int_t /* coef*/, RooArgSet& /*allVars*/, RooArgSet& /*analVars*/, const char* /*rangeName*/) const
536{
537 return 0 ;
538}
539
540
541
542////////////////////////////////////////////////////////////////////////////////
543/// Default implementation of function implementing advertised integrals. Only
544/// the pass-through scenario (no integration) is implemented.
545
546double RooAbsAnaConvPdf::coefAnalyticalIntegral(Int_t coef, Int_t code, const char* /*rangeName*/) const
547{
548 if (code==0) return coefficient(coef) ;
549 coutE(InputArguments) << "RooAbsAnaConvPdf::coefAnalyticalIntegral(" << GetName() << ") ERROR: unrecognized integration code: " << code << endl ;
550 assert(0) ;
551 return 1 ;
552}
553
554
555
556////////////////////////////////////////////////////////////////////////////////
557/// This function forces RooRealIntegral to offer all integration dependents
558/// to RooAbsAnaConvPdf::getAnalyticalIntegralWN() for consideration for
559/// internal integration, if RooRealIntegral considers this to be unsafe (e.g. due
560/// to hidden Jacobian terms).
561///
562/// RooAbsAnaConvPdf will not attempt to actually integrate all these dependents
563/// but feed them to the resolution models integration interface, which will
564/// make the final determination on how to integrate these dependents.
565
567{
568 return true ;
569}
570
571
572
573////////////////////////////////////////////////////////////////////////////////
574/// Returns the normalization integral value of the coefficient with number coefIdx over normalization
575/// set nset in range rangeName
576
577double RooAbsAnaConvPdf::getCoefNorm(Int_t coefIdx, const RooArgSet* nset, const TNamed* rangeName) const
578{
579 if (nset==nullptr) return coefficient(coefIdx) ;
580
581 CacheElem* cache = static_cast<CacheElem*>(_coefNormMgr.getObj(nset,nullptr,nullptr,rangeName)) ;
582 if (!cache) {
583
584 cache = new CacheElem ;
585
586 // Make list of coefficient normalizations
588
589 for (std::size_t i=0 ; i<cache->_coefVarList.size() ; i++) {
590 cache->_normList.addOwned(std::unique_ptr<RooAbsReal>{static_cast<RooAbsReal&>(*cache->_coefVarList.at(i)).createIntegral(*nset,RooNameReg::str(rangeName))});
591 }
592
593 _coefNormMgr.setObj(nset,nullptr,cache,rangeName) ;
594 }
595
596 return (static_cast<RooAbsReal*>(cache->_normList.at(coefIdx)))->getVal() ;
597}
598
599
600
601////////////////////////////////////////////////////////////////////////////////
602/// Build complete list of coefficient variables
603
605{
606 // Instantiate a coefficient variables
607 for (std::size_t i=0 ; i<_convSet.size() ; i++) {
608 auto cvars = coefVars(i);
609 std::string name = std::string{GetName()} + "_coefVar_" + std::to_string(i);
610 varList.addOwned(std::make_unique<RooConvCoefVar>(name.c_str(),"coefVar",*this,i,&*cvars));
611 }
612
613}
614
615
616////////////////////////////////////////////////////////////////////////////////
617/// Return set of parameters with are used exclusively by the coefficient functions
618
620{
621 std::unique_ptr<RooArgSet> cVars{getParameters(static_cast<RooArgSet*>(nullptr))};
622 std::vector<RooAbsArg*> tmp;
623 for (auto arg : *cVars) {
624 for (auto convSetArg : _convSet) {
625 if (convSetArg->dependsOn(*arg)) {
626 tmp.push_back(arg);
627 }
628 }
629 }
630
631 cVars->remove(tmp.begin(), tmp.end(), true, true);
632
633 return RooFit::makeOwningPtr(std::move(cVars));
634}
635
636
637
638
639////////////////////////////////////////////////////////////////////////////////
640/// Print info about this object to the specified stream. In addition to the info
641/// from RooAbsPdf::printStream() we add:
642///
643/// Verbose : detailed information on convolution integrals
644
645void RooAbsAnaConvPdf::printMultiline(ostream& os, Int_t contents, bool verbose, TString indent) const
646{
647 RooAbsPdf::printMultiline(os,contents,verbose,indent);
648
649 os << indent << "--- RooAbsAnaConvPdf ---" << endl;
650 for (RooAbsArg * conv : _convSet) {
651 conv->printMultiline(os,contents,verbose,indent) ;
652 }
653}
654
655
656///////////////////////////////////////////////////////////////////////////////
657/// Label OK'ed components with cache-and-track
659{
660 for (auto const* carg : static_range_cast<RooAbsArg*>(_convSet)) {
661 if (carg->canNodeBeCached()==Always) {
662 trackNodes.add(*carg) ;
663 //cout << "tracking node RooAddPdf component " << carg->ClassName() << "::" << carg->GetName() << endl ;
664 }
665 }
666}
667
668std::unique_ptr<RooAbsArg>
670{
671 // If there is only one component in the linear sum of convolutions, we can
672 // just return that one, normalized.
673 if(_convSet.size() == 1) {
674 if (normSet.empty()) {
675 return _convSet[0].compileForNormSet(normSet, ctx);
676 }
677 std::unique_ptr<RooAbsPdf> pdfClone(static_cast<RooAbsPdf *>(_convSet[0].Clone()));
678 ctx.compileServers(*pdfClone, normSet);
679
680 auto newArg = std::make_unique<RooNormalizedPdf>(*pdfClone, normSet);
681
682 // The direct servers are this pdf and the normalization integral, which
683 // don't need to be compiled further.
684 for (RooAbsArg *server : newArg->servers()) {
685 server->setAttribute("_COMPILED");
686 }
687 newArg->setAttribute("_COMPILED");
688 newArg->addOwnedComponents(std::move(pdfClone));
689 return newArg;
690 }
691
692 // Here, we can't use directly the function from the RooAbsPdf base class,
693 // because the convolution argument servers need to be evaluated
694 // unnormalized, even if they are pdfs.
695
696 if (normSet.empty()) {
697 return RooAbsPdf::compileForNormSet(normSet, ctx);
698 }
699 std::unique_ptr<RooAbsAnaConvPdf> pdfClone(static_cast<RooAbsAnaConvPdf *>(this->Clone()));
700
701 // The actual resolution model is not serving the RooAbsAnaConvPdf
702 // in the evaluation. It was only used get the convolutions with a given
703 // basis. We can remove it for the compiled model.
704 pdfClone->removeServer(const_cast<RooAbsReal &>(pdfClone->_model.arg()), true);
705
706 // The other servers will be compiled with the original normSet, but the
707 // _convSet has to be evaluated unnormalized.
708 RooArgList convArgClones;
709 for (RooAbsArg *convArg : _convSet) {
710 if (auto convArgClone = ctx.compile(*convArg, *pdfClone, {})) {
711 convArgClones.add(*convArgClone);
712 }
713 }
714 pdfClone->redirectServers(convArgClones, false, true);
715
716 // Compile remaining servers that are evaluated normalized
717 ctx.compileServers(*pdfClone, normSet);
718
719 // Finally, this RooAbsAnaConvPdf needs to be normalized
720 auto newArg = std::make_unique<RooNormalizedPdf>(*pdfClone, normSet);
721
722 // The direct servers are this pdf and the normalization integral, which
723 // don't need to be compiled further.
724 for (RooAbsArg *server : newArg->servers()) {
725 server->setAttribute("_COMPILED");
726 }
727 newArg->setAttribute("_COMPILED");
728 newArg->addOwnedComponents(std::move(pdfClone));
729 return newArg;
730}
#define c(i)
Definition RSha256.hxx:101
#define coutI(a)
#define cxcoutD(a)
#define coutE(a)
#define ClassImp(name)
Definition Rtypes.h:377
static void indent(ostringstream &buf, int indent_level)
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
char name[80]
Definition TGX11.cxx:110
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=nullptr, RooArgSet *set2=nullptr, RooArgSet *set3=nullptr, RooArgSet *set4=nullptr)
Store given arrays of integer codes, and up to four RooArgSets in the registry (each setX pointer may...
Base class for PDFs that represent a physics model that can be analytically convolved with a resoluti...
friend class RooConvGenContext
Int_t getAnalyticalIntegralWN(RooArgSet &allVars, RooArgSet &analVars, const RooArgSet *normSet, const char *rangeName=nullptr) const override
Advertise capability to perform (analytical) integrals internally.
double analyticalIntegralWN(Int_t code, const RooArgSet *normSet, const char *rangeName=nullptr) const override
Return analytical integral defined by given code, which is returned by getAnalyticalIntegralWN()
virtual double coefAnalyticalIntegral(Int_t coef, Int_t code, const char *rangeName=nullptr) const
Default implementation of function implementing advertised integrals.
virtual bool changeModel(const RooResolutionModel &newModel)
Change the current resolution model to newModel.
double getCoefNorm(Int_t coefIdx, const RooArgSet &nset, const char *rangeName) const
void setCacheAndTrackHints(RooArgSet &) override
Label OK'ed components with cache-and-track.
bool forceAnalyticalInt(const RooAbsArg &dep) const override
This function forces RooRealIntegral to offer all integration dependents to RooAbsAnaConvPdf::getAnal...
RooAbsGenContext * genContext(const RooArgSet &vars, const RooDataSet *prototype=nullptr, const RooArgSet *auxProto=nullptr, bool verbose=false) const override
Create a generator context for this p.d.f.
virtual double coefficient(Int_t basisIndex) const =0
RooArgList _basisList
! List of created basis functions
RooObjCacheManager _coefNormMgr
! Coefficient normalization manager
void makeCoefVarList(RooArgList &) const
Build complete list of coefficient variables.
RooAICRegistry _codeReg
! Registry of analytical integration codes
virtual Int_t getCoefAnalyticalIntegral(Int_t coef, RooArgSet &allVars, RooArgSet &analVars, const char *rangeName=nullptr) const
Default implementation of function advertising integration capabilities.
~RooAbsAnaConvPdf() override
Destructor.
bool isDirectGenSafe(const RooAbsArg &arg) const override
Return true if it is safe to generate the convolution observable from the internal generator (this is...
RooAbsRealLValue * convVar()
Retrieve the convolution variable.
double evaluate() const override
Calculate the current unnormalized value of the PDF.
RooRealProxy _model
Original model.
void printMultiline(std::ostream &stream, Int_t contents, bool verbose=false, TString indent="") const override
Print info about this object to the specified stream.
RooRealProxy _convVar
Convolution variable.
RooAbsAnaConvPdf()
Default constructor, required for persistence.
Int_t declareBasis(const char *expression, const RooArgList &params)
Declare a basis function for use in this physics model.
RooListProxy _convSet
Set of (resModel (x) basisFunc) convolution objects.
virtual RooFit::OwningPtr< RooArgSet > coefVars(Int_t coefIdx) const
Return set of parameters with are used exclusively by the coefficient functions.
std::unique_ptr< RooAbsArg > compileForNormSet(RooArgSet const &normSet, RooFit::Detail::CompileContext &ctx) const override
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:77
RooFit::OwningPtr< RooArgSet > getParameters(const RooAbsData *data, bool stripDisconnected=true) const
Create a list of leaf nodes in the arg tree starting with ourself as top node that don't match any of...
RooFit::OwningPtr< RooArgSet > getObservables(const RooArgSet &set, bool valueOnly=true) const
Given a set of possible observables, return the observables that this PDF depends on.
bool redirectServers(const RooAbsCollection &newServerList, bool mustReplaceAll=false, bool nameChange=false, bool isRecursionStep=false)
Replace all direct servers of this object with the new servers in newServerList.
bool getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
void setAttribute(const Text_t *name, bool value=true)
Set (default) or clear a named boolean attribute of this object.
TObject * Clone(const char *newname=nullptr) const override
Make a clone of an object using the Streamer facility.
Definition RooAbsArg.h:89
OperMode operMode() const
Query the operation mode of this node.
Definition RooAbsArg.h:482
RooAbsCollection * snapshot(bool deepCopy=true) const
Take a snap shot of current collection contents.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Int_t index(const RooAbsArg *arg) const
Returns index of given arg, or -1 if arg is not in the collection.
Storage_t::size_type size() const
TIterator begin()
virtual bool addOwned(RooAbsArg &var, bool silent=false)
Add an argument and transfer the ownership to the collection.
TIterator end() and range-based for loops.")
Abstract base class for generator contexts of RooAbsPdf objects.
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:40
std::unique_ptr< RooAbsArg > compileForNormSet(RooArgSet const &normSet, RooFit::Detail::CompileContext &ctx) const override
virtual bool isDirectGenSafe(const RooAbsArg &arg) const
Check if given observable can be safely generated using the pdfs internal generator mechanism (if tha...
void printMultiline(std::ostream &os, Int_t contents, bool verbose=false, TString indent="") const override
Print multi line detailed information of this RooAbsPdf.
virtual Int_t getGenerator(const RooArgSet &directVars, RooArgSet &generateVars, bool staticInitOK=true) const
Load generatedVars with the subset of directVars that we can generate events for, and return a code t...
Abstract base class for objects that represent a real value that may appear on the left hand side of ...
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:59
RooFit::OwningPtr< RooAbsReal > createIntegral(const RooArgSet &iset, const RooCmdArg &arg1, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={}) const
Create an object that represents the integral of the function over one or more observables listed in ...
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:103
bool _forceNumInt
Force numerical integration if flag set.
Definition RooAbsReal.h:546
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooAbsArg * at(Int_t idx) const
Return object at given index, or nullptr if index is out of range.
Definition RooArgList.h:110
RooAbsArg * absArg() const
Return pointer to contained argument.
Definition RooArgProxy.h:46
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:55
Int_t setObj(const RooArgSet *nset, T *obj, const TNamed *isetRangeName=nullptr)
Setter function without integration set.
T * getObj(const RooArgSet *nset, Int_t *sterileIndex=nullptr, const TNamed *isetRangeName=nullptr)
Getter function without integration set.
void removeAll() override
Remove all argument inset using remove(const RooAbsArg&).
bool addOwned(RooAbsArg &var, bool silent=false) override
Overloaded RooCollection_t::addOwned() method insert object into owning set and registers object as s...
bool add(const RooAbsArg &var, bool valueServer, bool shapeServer, bool silent)
Overloaded RooCollection_t::add() method insert object into set and registers object as server to own...
bool remove(const RooAbsArg &var, bool silent=false, bool matchByNameOnly=false) override
Remove object 'var' from set and deregister 'var' as server to owner.
Container class to hold unbinned data.
Definition RooDataSet.h:57
void compileServers(RooAbsArg &arg, RooArgSet const &normSet)
T * compile(T &arg, RooAbsArg &owner, RooArgSet const &normSet)
A RooFormulaVar is a generic implementation of a real-valued object, which takes a RooArgList of serv...
Implements a universal generator context for all RooAbsPdf classes that do not have or need a special...
static const char * str(const TNamed *ptr)
Return C++ string corresponding to given TNamed pointer.
Definition RooNameReg.h:39
static const TNamed * ptr(const char *stringPtr)
Return a unique TNamed pointer for given C++ string.
Variable that can be changed from the outside.
Definition RooRealVar.h:37
RooResolutionModel is the base class for PDFs that represent a resolution model that can be convolute...
virtual RooResolutionModel * convolution(RooFormulaVar *basis, RooAbsArg *owner) const
Instantiate a clone of this resolution model representing a convolution with given basis function.
virtual RooAbsGenContext * modelGenContext(const RooAbsAnaConvPdf &, const RooArgSet &, const RooDataSet *, const RooArgSet *, bool) const
RooAbsRealLValue & convVar() const
Return the convolution variable of the resolution model.
const T & arg() const
Return reference to object held in proxy.
Implements a RooResolution model that corresponds to a delta function.
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
Basic string class.
Definition TString.h:139
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition TString.cxx:457
TString & Append(const char *cs)
Definition TString.h:572
OwningPtr< T > makeOwningPtr(std::unique_ptr< T > &&ptr)
Internal helper to turn a std::unique_ptr<T> into an OwningPtr.
Definition Config.h:40
T * OwningPtr
An alias for raw pointers for indicating that the return type of a RooFit function is an owning point...
Definition Config.h:35