Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooAbsPdf.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 RooAbsPdf
19 \ingroup Roofitcore
20 \brief Abstract interface for all probability density functions.
21
22## RooAbsPdf, the base class of all PDFs
23
24RooAbsPdf is the base class for all probability density
25functions (PDFs). The class provides hybrid analytical/numerical
26normalization for its implementations, error tracing, and a Monte Carlo
27generator interface.
28
29### A Minimal PDF Implementation
30
31A minimal implementation of a PDF class derived from RooAbsPdf
32should override the `evaluate()` function. This function should
33return the PDF's value (which does not need to be normalised).
34
35
36#### Normalization/Integration
37
38Although the normalization of a PDF is an integral part of a
39probability density function, normalization is treated separately
40in RooAbsPdf. The reason is that a RooAbsPdf object is more than a
41PDF: it can be a building block for a more complex composite PDF
42if any of its variables are functions instead of variables. In
43such cases, the normalization of the composite PDF may not simply be
44integral over the dependents of the top-level PDF: these are
45functions with potentially non-trivial Jacobian terms themselves.
46\note Therefore, no explicit attempt should be made to normalize the
47function output in evaluate(). In particular, normalisation constants
48can be omitted to speed up the function evaluations, and included later
49in the integration of the PDF (see below), which is rarely called in
50comparison to the `evaluate()` function.
51
52In addition, RooAbsPdf objects do not have a static concept of what
53variables are parameters, and what variables are dependents (which
54need to be integrated over for a correct PDF normalization).
55Instead, the choice of normalization is always specified each time a
56normalized value is requested from the PDF via the getVal()
57method.
58
59RooAbsPdf manages the entire normalization logic of each PDF with
60the help of a RooRealIntegral object, which coordinates the integration
61of a given choice of normalization. By default, RooRealIntegral will
62perform an entirely numeric integration of all dependents. However,
63PDFs can advertise one or more (partial) analytical integrals of
64their function, and these will be used by RooRealIntegral, if it
65determines that this is safe (i.e., no hidden Jacobian terms,
66multiplication with other PDFs that have one or more dependents in
67common, etc).
68
69#### Implementing analytical integrals
70To implement analytical integrals, two functions must be implemented. First,
71
72```
73Int_t getAnalyticalIntegral(const RooArgSet& integSet, RooArgSet& anaIntSet)
74```
75should return the analytical integrals that are supported. `integSet`
76is the set of dependents for which integration is requested. The
77function should copy the subset of dependents it can analytically
78integrate to `anaIntSet`, and return a unique identification code for
79this integration configuration. If no integration can be
80performed, zero should be returned. Second,
81
82```
83double analyticalIntegral(Int_t code)
84```
85
86implements the actual analytical integral(s) advertised by
87`getAnalyticalIntegral()`. This function will only be called with
88codes returned by `getAnalyticalIntegral()`, except code zero.
89
90The integration range for each dependent to be integrated can
91be obtained from the dependent's proxy functions `min()` and
92`max()`. Never call these proxy functions for any proxy not known to
93be a dependent via the integration code. Doing so may be
94ill-defined, e.g., in case the proxy holds a function, and will
95trigger an assert. Integrated category dependents should always be
96summed over all of their states.
97
98
99
100### Direct generation of observables
101
102Distributions for any PDF can be generated with the accept/reject method,
103but for certain PDFs, more efficient methods may be implemented. To
104implement direct generation of one or more observables, two
105functions need to be implemented, similar to those for analytical
106integrals:
107
108```
109Int_t getGenerator(const RooArgSet& generateVars, RooArgSet& directVars)
110```
111and
112```
113void generateEvent(Int_t code)
114```
115
116The first function advertises observables, for which distributions can be generated,
117similar to the way analytical integrals are advertised. The second
118function implements the actual generator for the advertised observables.
119
120The generated dependent values should be stored in the proxy
121objects. For this, the assignment operator can be used (i.e. `xProxy
122= 3.0` ). Never call assign to any proxy not known to be a dependent
123via the generation code. Doing so may be ill-defined, e.g. in case
124the proxy holds a function, and will trigger an assert.
125
126
127### Batched function evaluations (Advanced usage)
128
129To speed up computations with large numbers of data events in unbinned fits,
130it is beneficial to override `doEval()`. Like this, large spans of
131computations can be done, without having to call `evaluate()` for each single data event.
132`doEval()` should execute the same computation as `evaluate()`, but it
133may choose an implementation that is capable of SIMD computations.
134If doEval is not implemented, the classic and slower `evaluate()` will be
135called for each data event.
136*/
137
138#include "RooAbsPdf.h"
139
140#include "FitHelpers.h"
141#include "RooNormalizedPdf.h"
142#include "RooMsgService.h"
143#include "RooArgSet.h"
144#include "RooArgProxy.h"
145#include "RooRealProxy.h"
146#include "RooRealVar.h"
147#include "RooGenContext.h"
148#include "RooBinnedGenContext.h"
149#include "RooPlot.h"
150#include "RooCurve.h"
151#include "RooCategory.h"
152#include "RooNameReg.h"
153#include "RooCmdConfig.h"
154#include "RooGlobalFunc.h"
155#include "RooRandom.h"
156#include "RooNumIntConfig.h"
157#include "RooProjectedPdf.h"
158#include "RooParamBinning.h"
159#include "RooNumCdf.h"
160#include "RooFitResult.h"
161#include "RooNumGenConfig.h"
162#include "RooCachedReal.h"
163#include "RooRealIntegral.h"
164#include "RooWorkspace.h"
165#include "RooNaNPacker.h"
166#include "RooFitImplHelpers.h"
167#include "RooHelpers.h"
168#include "RooFormulaVar.h"
169#include "RooDerivative.h"
170
171#include "ROOT/StringUtils.hxx"
172#include "TMath.h"
173#include "TPaveText.h"
174#include "TMatrixD.h"
175#include "TMatrixDSym.h"
176
177#include <algorithm>
178#include <iostream>
179#include <string>
180#include <cmath>
181#include <stdexcept>
182
183namespace {
184
185inline double getLog(double prob, RooAbsReal const *caller)
186{
187
188 if (std::abs(prob) > 1e6) {
189 oocoutW(caller, Eval) << "RooAbsPdf::getLogVal(" << caller->GetName()
190 << ") WARNING: top-level pdf has a large value: " << prob << std::endl;
191 }
192
193 if (prob < 0) {
194 caller->logEvalError("getLogVal() top-level p.d.f evaluates to a negative number");
195 return RooNaNPacker::packFloatIntoNaN(-prob);
196 }
197
198 if (prob == 0) {
199 caller->logEvalError("getLogVal() top-level p.d.f evaluates to zero");
200
201 return -std::numeric_limits<double>::infinity();
202 }
203
204 if (TMath::IsNaN(prob)) {
205 caller->logEvalError("getLogVal() top-level p.d.f evaluates to NaN");
206
207 return prob;
208 }
209
210 return std::log(prob);
211}
212
213} // namespace
214
215using std::endl, std::string, std::ostream, std::vector, std::pair, std::make_pair;
216
218
220
222
223
226
227////////////////////////////////////////////////////////////////////////////////
228/// Default constructor
229
230RooAbsPdf::RooAbsPdf() : _normMgr(this, 10) {}
231
232////////////////////////////////////////////////////////////////////////////////
233/// Constructor with name and title only
234
235RooAbsPdf::RooAbsPdf(const char *name, const char *title) :
236 RooAbsReal(name,title), _normMgr(this,10), _selectComp(true)
237{
239 setTraceCounter(0) ;
240}
241
242
243
244////////////////////////////////////////////////////////////////////////////////
245/// Constructor with name, title, and plot range
246
247RooAbsPdf::RooAbsPdf(const char *name, const char *title,
248 double plotMin, double plotMax) :
249 RooAbsReal(name,title,plotMin,plotMax), _normMgr(this,10), _selectComp(true)
250{
252 setTraceCounter(0) ;
253}
254
255
256
257////////////////////////////////////////////////////////////////////////////////
258/// Copy constructor
259
260RooAbsPdf::RooAbsPdf(const RooAbsPdf& other, const char* name) :
261 RooAbsReal(other,name),
262 _normMgr(other._normMgr,this), _selectComp(other._selectComp), _normRange(other._normRange)
263{
266
267 if (other._specGeneratorConfig) {
268 _specGeneratorConfig = std::make_unique<RooNumGenConfig>(*other._specGeneratorConfig);
269 }
270}
271
272
273
274////////////////////////////////////////////////////////////////////////////////
275/// Destructor
276
278{
279}
280
281
282double RooAbsPdf::normalizeWithNaNPacking(double rawVal, double normVal) const {
283
284 if (normVal < 0. || (normVal == 0. && rawVal != 0)) {
285 //Unreasonable normalisations. A zero integral can be tolerated if the function vanishes, though.
286 const std::string msg = "p.d.f normalization integral is zero or negative: " + std::to_string(normVal);
287 logEvalError(msg.c_str());
289 return RooNaNPacker::packFloatIntoNaN(-normVal + (rawVal < 0. ? -rawVal : 0.));
290 }
291
292 if (rawVal < 0.) {
293 logEvalError(Form("p.d.f value is less than zero (%f), trying to recover", rawVal));
295 return RooNaNPacker::packFloatIntoNaN(-rawVal);
296 }
297
298 if (TMath::IsNaN(rawVal)) {
299 logEvalError("p.d.f value is Not-a-Number");
301 return rawVal;
302 }
303
304 return (rawVal == 0. && normVal == 0.) ? 0. : rawVal / normVal;
305}
307
308////////////////////////////////////////////////////////////////////////////////
309/// Return current value, normalized by integrating over
310/// the observables in `nset`. If `nset` is 0, the unnormalized value
311/// is returned. All elements of `nset` must be lvalues.
312///
313/// Unnormalized values are not cached.
314/// Doing so would be complicated as `_norm->getVal()` could
315/// spoil the cache and interfere with returning the cached
316/// return value. Since unnormalized calls are typically
317/// done in integration calls, there is no performance hit.
318
319double RooAbsPdf::getValV(const RooArgSet* nset) const
320{
321
322 // Special handling of case without normalization set (used in numeric integration of pdfs)
323 if (!nset) {
324 RooArgSet const* tmp = _normSet ;
325 _normSet = nullptr ;
326 double val = evaluate() ;
327 _normSet = tmp ;
328
329 return TMath::IsNaN(val) ? 0. : val;
330 }
331
332
333 // Process change in last data set used
334 bool nintChanged(false) ;
335 if (!isActiveNormSet(nset) || _norm==nullptr) {
336 nintChanged = syncNormalization(nset) ;
337 }
338
339 // Return value of object. Calculated if dirty, otherwise cached value is returned.
340 if (isValueDirty() || nintChanged || _norm->isValueDirty()) {
341
342 // Evaluate numerator
343 const double rawVal = evaluate();
344
345 // Evaluate denominator
346 const double normVal = _norm->getVal();
347
348 _value = normalizeWithNaNPacking(rawVal, normVal);
349
351 }
352
353 return _value ;
354}
355
356
357////////////////////////////////////////////////////////////////////////////////
358/// Analytical integral with normalization (see RooAbsReal::analyticalIntegralWN() for further information).
359///
360/// This function applies the normalization specified by `normSet` to the integral returned
361/// by RooAbsReal::analyticalIntegral(). The passthrough scenario (code=0) is also changed
362/// to return a normalized answer.
363
364double RooAbsPdf::analyticalIntegralWN(Int_t code, const RooArgSet* normSet, const char* rangeName) const
365{
366 cxcoutD(Eval) << "RooAbsPdf::analyticalIntegralWN(" << GetName() << ") code = " << code << " normset = " << (normSet?*normSet:RooArgSet()) << endl ;
367
368
369 if (code==0) return getVal(normSet) ;
370 if (normSet) {
371 return analyticalIntegral(code,rangeName) / getNorm(normSet) ;
372 } else {
373 return analyticalIntegral(code,rangeName) ;
374 }
375}
376
377
378
379////////////////////////////////////////////////////////////////////////////////
380/// Check that passed value is positive and not 'not-a-number'. If
381/// not, print an error, until the error counter reaches its set
382/// maximum.
383
385{
386 // check for a math error or negative value
387 bool error(false) ;
388 if (TMath::IsNaN(value)) {
389 logEvalError(Form("p.d.f value is Not-a-Number (%f), forcing value to zero",value)) ;
390 error=true ;
391 }
392 if (value<0) {
393 logEvalError(Form("p.d.f value is less than zero (%f), forcing value to zero",value)) ;
394 error=true ;
395 }
396
397 // do nothing if we are no longer tracing evaluations and there was no error
398 if(!error) return error ;
399
400 // otherwise, print out this evaluations input values and result
401 if(++_errorCount <= 10) {
402 cxcoutD(Tracing) << "*** Evaluation Error " << _errorCount << " ";
403 if(_errorCount == 10) cxcoutD(Tracing) << "(no more will be printed) ";
404 }
405 else {
406 return error ;
407 }
408
409 Print() ;
410 return error ;
411}
412
413
414////////////////////////////////////////////////////////////////////////////////
415/// Get normalisation term needed to normalise the raw values returned by
416/// getVal(). Note that `getVal(normalisationVariables)` will automatically
417/// apply the normalisation term returned here.
418/// \param nset Set of variables to normalise over.
419double RooAbsPdf::getNorm(const RooArgSet* nset) const
420{
421 if (!nset) return 1 ;
422
423 syncNormalization(nset,true) ;
424 if (_verboseEval>1) cxcoutD(Tracing) << ClassName() << "::getNorm(" << GetName() << "): norm(" << _norm << ") = " << _norm->getVal() << endl ;
425
426 double ret = _norm->getVal() ;
427 if (ret==0.) {
428 if(++_errorCount <= 10) {
429 coutW(Eval) << "RooAbsPdf::getNorm(" << GetName() << ":: WARNING normalization is zero, nset = " ; nset->Print("1") ;
430 if(_errorCount == 10) coutW(Eval) << "RooAbsPdf::getNorm(" << GetName() << ") INFO: no more messages will be printed " << endl ;
431 }
432 }
433
434 return ret ;
435}
436
437
438
439////////////////////////////////////////////////////////////////////////////////
440/// Return pointer to RooAbsReal object that implements calculation of integral over observables iset in range
441/// rangeName, optionally taking the integrand normalized over observables nset
442
443const RooAbsReal* RooAbsPdf::getNormObj(const RooArgSet* nset, const RooArgSet* iset, const TNamed* rangeName) const
444{
445 // Check normalization is already stored
446 CacheElem* cache = static_cast<CacheElem*>(_normMgr.getObj(nset,iset,nullptr,rangeName)) ;
447 if (cache) {
448 return cache->_norm ;
449 }
450
451 // If not create it now
452 RooArgSet depList;
453 getObservables(iset, depList);
454
455 // Normalization is always over all pdf components. Overriding the global
456 // component selection temporarily makes all RooRealIntegrals created during
457 // that time always include all components.
458 GlobalSelectComponentRAII globalSelComp(true);
459 RooAbsReal* norm = std::unique_ptr<RooAbsReal>{createIntegral(depList,*nset, *getIntegratorConfig(), RooNameReg::str(rangeName))}.release();
460
461 // Store it in the cache
462 cache = new CacheElem(*norm) ;
463 _normMgr.setObj(nset,iset,cache,rangeName) ;
464
465 // And return the newly created integral
466 return norm ;
467}
468
469
470
471////////////////////////////////////////////////////////////////////////////////
472/// Verify that the normalization integral cached with this PDF
473/// is valid for given set of normalization observables.
474///
475/// If not, the cached normalization integral (if any) is deleted
476/// and a new integral is constructed for use with 'nset'.
477/// Elements in 'nset' can be discrete and real, but must be lvalues.
478///
479/// For functions that declare to be self-normalized by overloading the
480/// selfNormalized() function, a unit normalization is always constructed.
481
482bool RooAbsPdf::syncNormalization(const RooArgSet* nset, bool adjustProxies) const
483{
484 setActiveNormSet(nset);
485
486 // Check if data sets are identical
487 CacheElem* cache = static_cast<CacheElem*>(_normMgr.getObj(nset)) ;
488 if (cache) {
489
490 bool nintChanged = (_norm!=cache->_norm) ;
491 _norm = cache->_norm ;
492
493 // In the past, this condition read `if (nintChanged && adjustProxies)`.
494 // However, the cache checks if the nset was already cached **by content**,
495 // and not by RooArgSet instance! So it can happen that the normalization
496 // set object is different, but the integral object is the same, in which
497 // case it would be wrong to not adjust the proxies. They always have to be
498 // adjusted when the nset changed, which is always the case when
499 // `syncNormalization()` is called.
500 if (adjustProxies) {
501 // Update dataset pointers of proxies
502 const_cast<RooAbsPdf*>(this)->setProxyNormSet(nset) ;
503 }
504
505 return nintChanged ;
506 }
507
508 // Update dataset pointers of proxies
509 if (adjustProxies) {
510 const_cast<RooAbsPdf*>(this)->setProxyNormSet(nset) ;
511 }
512
513 RooArgSet depList;
514 getObservables(nset, depList);
515
516 if (_verboseEval>0) {
517 if (!selfNormalized()) {
518 cxcoutD(Tracing) << ClassName() << "::syncNormalization(" << GetName()
519 << ") recreating normalization integral " << endl ;
520 depList.printStream(ccoutD(Tracing),kName|kValue|kArgs,kSingleLine) ;
521 } else {
522 cxcoutD(Tracing) << ClassName() << "::syncNormalization(" << GetName() << ") selfNormalized, creating unit norm" << endl;
523 }
524 }
525
526 // Destroy old normalization & create new
527 if (selfNormalized() || !dependsOn(depList)) {
528 auto ntitle = std::string(GetTitle()) + " Unit Normalization";
529 auto nname = std::string(GetName()) + "_UnitNorm";
530 _norm = new RooRealVar(nname.c_str(),ntitle.c_str(),1) ;
531 } else {
532 const char* nr = (_normRangeOverride.Length()>0 ? _normRangeOverride.Data() : (_normRange.Length()>0 ? _normRange.Data() : nullptr)) ;
533
534// cout << "RooAbsPdf::syncNormalization(" << GetName() << ") rangeName for normalization is " << (nr?nr:"<null>") << endl ;
535 RooAbsReal* normInt;
536 {
537 // Normalization is always over all pdf components. Overriding the global
538 // component selection temporarily makes all RooRealIntegrals created during
539 // that time always include all components.
540 GlobalSelectComponentRAII selCompRAII(true);
541 normInt = std::unique_ptr<RooAbsReal>{createIntegral(depList,*getIntegratorConfig(),nr)}.release();
542 }
543 static_cast<RooRealIntegral*>(normInt)->setAllowComponentSelection(false);
544 normInt->getVal() ;
545// cout << "resulting normInt = " << normInt->GetName() << endl ;
546
547 const char* cacheParamsStr = getStringAttribute("CACHEPARAMINT") ;
548 if (cacheParamsStr && strlen(cacheParamsStr)) {
549
550 std::unique_ptr<RooArgSet> intParams{normInt->getVariables()} ;
551
552 RooArgSet cacheParams = RooHelpers::selectFromArgSet(*intParams, cacheParamsStr);
553
554 if (!cacheParams.empty()) {
555 cxcoutD(Caching) << "RooAbsReal::createIntObj(" << GetName() << ") INFO: constructing " << cacheParams.size()
556 << "-dim value cache for integral over " << depList << " as a function of " << cacheParams << " in range " << (nr?nr:"<default>") << endl ;
557 string name = Form("%s_CACHE_[%s]",normInt->GetName(),cacheParams.contentsString().c_str()) ;
558 RooCachedReal* cachedIntegral = new RooCachedReal(name.c_str(),name.c_str(),*normInt,cacheParams) ;
559 cachedIntegral->setInterpolationOrder(2) ;
560 cachedIntegral->addOwnedComponents(*normInt) ;
561 cachedIntegral->setCacheSource(true) ;
562 if (normInt->operMode()==ADirty) {
563 cachedIntegral->setOperMode(ADirty) ;
564 }
565 normInt= cachedIntegral ;
566 }
567
568 }
569 _norm = normInt ;
570 }
571
572 // Register new normalization with manager (takes ownership)
573 cache = new CacheElem(*_norm) ;
574 _normMgr.setObj(nset,cache) ;
575
576// cout << "making new object " << _norm->GetName() << endl ;
577
578 return true ;
579}
580
581
582
583////////////////////////////////////////////////////////////////////////////////
584/// Reset error counter to given value, limiting the number
585/// of future error messages for this pdf to 'resetValue'
586
588{
589 _errorCount = resetValue ;
590 _negCount = resetValue ;
591}
592
593
594
595////////////////////////////////////////////////////////////////////////////////
596/// Reset trace counter to given value, limiting the
597/// number of future trace messages for this pdf to 'value'
598
600{
601 if (!allNodes) {
603 return ;
604 } else {
605 RooArgList branchList ;
606 branchNodeServerList(&branchList) ;
607 for(auto * pdf : dynamic_range_cast<RooAbsPdf*>(branchList)) {
608 if (pdf) pdf->setTraceCounter(value,false) ;
609 }
610 }
611
612}
613
614
615
616
617////////////////////////////////////////////////////////////////////////////////
618/// Return the log of the current value with given normalization
619/// An error message is printed if the argument of the log is negative.
620
621double RooAbsPdf::getLogVal(const RooArgSet* nset) const
622{
623 return getLog(getVal(nset), this);
624}
625
626
627////////////////////////////////////////////////////////////////////////////////
628/// Check for infinity or NaN.
629/// \param[in] inputs Array to check
630/// \return True if either infinity or NaN were found.
631namespace {
632template<class T>
633bool checkInfNaNNeg(const T& inputs) {
634 // check for a math error or negative value
635 bool inf = false;
636 bool nan = false;
637 bool neg = false;
638
639 for (double val : inputs) { //CHECK_VECTORISE
640 inf |= !std::isfinite(val);
641 nan |= TMath::IsNaN(val); // Works also during fast math
642 neg |= val < 0;
643 }
644
645 return inf || nan || neg;
646}
647}
648
649
650////////////////////////////////////////////////////////////////////////////////
651/// Scan through outputs and fix+log all nans and negative values.
652/// \param[in,out] outputs Array to be scanned & fixed.
653/// \param[in] begin Begin of event range. Only needed to print the correct event number
654/// where the error occurred.
655void RooAbsPdf::logBatchComputationErrors(std::span<const double>& outputs, std::size_t begin) const {
656 for (unsigned int i=0; i<outputs.size(); ++i) {
657 const double value = outputs[i];
658 if (TMath::IsNaN(outputs[i])) {
659 logEvalError(Form("p.d.f value of (%s) is Not-a-Number (%f) for entry %zu",
660 GetName(), value, begin+i));
661 } else if (!std::isfinite(outputs[i])){
662 logEvalError(Form("p.d.f value of (%s) is (%f) for entry %zu",
663 GetName(), value, begin+i));
664 } else if (outputs[i] < 0.) {
665 logEvalError(Form("p.d.f value of (%s) is less than zero (%f) for entry %zu",
666 GetName(), value, begin+i));
667 }
668 }
669}
670
671
672void RooAbsPdf::getLogProbabilities(std::span<const double> pdfValues, double * output) const {
673 for (std::size_t i = 0; i < pdfValues.size(); ++i) {
674 output[i] = getLog(pdfValues[i], this);
675 }
676}
677
678////////////////////////////////////////////////////////////////////////////////
679/// Return the extended likelihood term (\f$ N_\mathrm{expect} - N_\mathrm{observed} \cdot \log(N_\mathrm{expect} \f$)
680/// of this PDF for the given number of observed events.
681///
682/// For successful operation, the PDF implementation must indicate that
683/// it is extendable by overloading `canBeExtended()`, and must
684/// implement the `expectedEvents()` function.
685///
686/// \param[in] observed The number of observed events.
687/// \param[in] nset The normalization set when asking the pdf for the expected
688/// number of events.
689/// \param[in] observedSumW2 The number of observed events when weighting with
690/// squared weights. If non-zero, the weight-squared error
691/// correction is applied to the extended term.
692/// \param[in] doOffset Offset the extended term by a counterterm where the
693/// expected number of events equals the observed number of events.
694/// This constant shift results in a term closer to zero that is
695/// approximately chi-square distributed. It is useful to do this
696/// also when summing multiple NLL terms to avoid numeric precision
697/// loss that happens if you sum multiple terms of different orders
698/// of magnitude.
699///
700/// The weight-squared error correction works as follows:
701/// adjust poisson such that
702/// estimate of \f$N_\mathrm{expect}\f$ stays at the same value, but has a different variance, rescale
703/// both the observed and expected count of the Poisson with a factor \f$ \sum w_{i} / \sum w_{i}^2 \f$
704/// (the effective weight of the Poisson term),
705/// i.e., change \f$\mathrm{Poisson}(N_\mathrm{observed} = \sum w_{i} | N_\mathrm{expect} )\f$
706/// to \f$ \mathrm{Poisson}(\sum w_{i} \cdot \sum w_{i} / \sum w_{i}^2 | N_\mathrm{expect} \cdot \sum w_{i} / \sum w_{i}^2 ) \f$,
707/// weighted by the effective weight \f$ \sum w_{i}^2 / \sum w_{i} \f$ in the likelihood.
708/// Since here we compute the likelihood with the weight square, we need to multiply by the
709/// square of the effective weight:
710/// - \f$ W_\mathrm{expect} = N_\mathrm{expect} \cdot \sum w_{i} / \sum w_{i}^2 \f$ : effective expected entries
711/// - \f$ W_\mathrm{observed} = \sum w_{i} \cdot \sum w_{i} / \sum w_{i}^2 \f$ : effective observed entries
712///
713/// The extended term for the likelihood weighted by the square of the weight will be then:
714///
715/// \f$ \left(\sum w_{i}^2 / \sum w_{i}\right)^2 \cdot W_\mathrm{expect} - (\sum w_{i}^2 / \sum w_{i})^2 \cdot W_\mathrm{observed} \cdot \log{W_\mathrm{expect}} \f$
716///
717/// aund this is using the previous expressions for \f$ W_\mathrm{expect} \f$ and \f$ W_\mathrm{observed} \f$:
718///
719/// \f$ \sum w_{i}^2 / \sum w_{i} \cdot N_\mathrm{expect} - \sum w_{i}^2 \cdot \log{W_\mathrm{expect}} \f$
720///
721/// Since the weights are constants in the likelihood we can use \f$\log{N_\mathrm{expect}}\f$ instead of \f$\log{W_\mathrm{expect}}\f$.
722///
723/// See also RooAbsPdf::extendedTerm(RooAbsData const& data, bool weightSquared, bool doOffset),
724/// which takes a dataset to extract \f$N_\mathrm{observed}\f$ and the
725/// normalization set.
726double RooAbsPdf::extendedTerm(double sumEntries, RooArgSet const* nset, double sumEntriesW2, bool doOffset) const
727{
728 return extendedTerm(sumEntries, expectedEvents(nset), sumEntriesW2, doOffset);
729}
730
731double RooAbsPdf::extendedTerm(double sumEntries, double expected, double sumEntriesW2, bool doOffset) const
732{
733 // check if this PDF supports extended maximum likelihood fits
734 if(!canBeExtended()) {
735 coutE(InputArguments) << GetName() << ": this PDF does not support extended maximum likelihood"
736 << std::endl;
737 return 0.0;
738 }
739
740 if(expected < 0.0) {
741 coutE(InputArguments) << GetName() << ": calculated negative expected events: " << expected
742 << std::endl;
743 logEvalError("extendedTerm #expected events is <0 return a NaN");
744 return TMath::QuietNaN();
745 }
746
747
748 // Explicitly handle case Nobs=Nexp=0
749 if (std::abs(expected)<1e-10 && std::abs(sumEntries)<1e-10) {
750 return 0.0;
751 }
752
753 // Check for errors in Nexpected
754 if (TMath::IsNaN(expected)) {
755 logEvalError("extendedTerm #expected events is a NaN") ;
756 return TMath::QuietNaN() ;
757 }
758
759 double extra = doOffset
760 ? (expected - sumEntries) - sumEntries * (std::log(expected) - std::log(sumEntries))
761 : expected - sumEntries * std::log(expected);
762
763 if(sumEntriesW2 != 0.0) {
764 extra *= sumEntriesW2 / sumEntries;
765 }
766
767 return extra;
768}
769
770////////////////////////////////////////////////////////////////////////////////
771/// Return the extended likelihood term (\f$ N_\mathrm{expect} - N_\mathrm{observed} \cdot \log(N_\mathrm{expect} \f$)
772/// of this PDF for the given number of observed events.
773///
774/// This function is a wrapper around
775/// RooAbsPdf::extendedTerm(double, RooArgSet const *, double, bool) const,
776/// where the number of observed events and observables to be used as the
777/// normalization set for the pdf is extracted from a RooAbsData.
778///
779/// For successful operation, the PDF implementation must indicate that
780/// it is extendable by overloading `canBeExtended()`, and must
781/// implement the `expectedEvents()` function.
782///
783/// \param[in] data The RooAbsData to retrieve the set of observables and
784/// number of expected events.
785/// \param[in] weightSquared If set to `true`, the extended term will be scaled by
786/// the ratio of squared event weights over event weights:
787/// \f$ \sum w_{i}^2 / \sum w_{i} \f$.
788/// Intended to be used by fits with the `SumW2Error()` option that
789/// can be passed to RooAbsPdf::fitTo()
790/// (see the documentation of said function to learn more about the
791/// interpretation of fits with squared weights).
792/// \param[in] doOffset See RooAbsPdf::extendedTerm(double, RooArgSet const*, double, bool) const.
793
794double RooAbsPdf::extendedTerm(RooAbsData const& data, bool weightSquared, bool doOffset) const {
795 double sumW = data.sumEntries();
796 double sumW2 = 0.0;
797 if (weightSquared) {
798 sumW2 = data.sumEntriesW2();
799 }
800 return extendedTerm(sumW, data.get(), sumW2, doOffset);
801}
802
803
804/** @fn RooAbsPdf::createNLL()
805 *
806 * @brief Construct representation of -log(L) of PDF with given dataset.
807 *
808 * If dataset is unbinned, an unbinned likelihood is constructed.
809 * If the dataset is binned, a binned likelihood is constructed.
810 *
811 * @param data Reference to a RooAbsData object representing the dataset.
812 * @param cmdArgs Variadic template arguments representing optional command arguments.
813 * You can pass either an arbitrary number of RooCmdArg instances
814 * or a single RooLinkedList that points to the RooCmdArg objects.
815 * @return An owning pointer to the created RooAbsReal NLL object.
816 *
817 * @tparam CmdArgs_t Template types for optional command arguments.
818 * Can either be an arbitrary number of RooCmdArg or a single RooLinkedList.
819 *
820 * \note This front-end function should not be re-implemented in derived PDF types.
821 * If you mean to customize the NLL creation routine,
822 * you need to override the virtual RooAbsPdf::createNLLImpl() method.
823 *
824 * The following named arguments are supported:
825 *
826 * <table>
827 * <tr><th> Type of CmdArg <th> Effect on NLL
828 * <tr><td> `ConditionalObservables(Args_t &&... argsOrArgSet)` <td> Do not normalize PDF over listed observables.
829 * Arguments can either be multiple RooRealVar or a single RooArgSet containing them.
830 * <tr><td> `Extended(bool flag)` <td> Add extended likelihood term, off by default.
831 * <tr><td> `Range(const char* name)` <td> Fit only data inside range with given name. Multiple comma-separated range names can be specified.
832 * In this case, the unnormalized PDF \f$f(x)\f$ is normalized by the integral over all ranges \f$r_i\f$:
833 * \f[
834 * p(x) = \frac{f(x)}{\sum_i \int_{r_i} f(x) dx}.
835 * \f]
836 * <tr><td> `Range(double lo, double hi)` <td> Fit only data inside given range. A range named "fit" is created on the fly on all observables.
837 * <tr><td> `SumCoefRange(const char* name)` <td> Set the range in which to interpret the coefficients of RooAddPdf components
838 * <tr><td> `NumCPU(int num, int istrat)` <td> Parallelize NLL calculation on num CPUs
839 * <table>
840 * <tr><th> Strategy <th> Effect
841 * <tr><td> 0 = RooFit::BulkPartition - *default* <td> Divide events in N equal chunks
842 * <tr><td> 1 = RooFit::Interleave <td> Process event i%N in process N. Recommended for binned data with
843 * a substantial number of zero-bins, which will be distributed across processes more equitably in this strategy
844 * <tr><td> 2 = RooFit::SimComponents <td> Process each component likelihood of a RooSimultaneous fully in a single process
845 * and distribute components over processes. This approach can be beneficial if normalization calculation time
846 * dominates the total computation time of a component (since the normalization calculation must be performed
847 * in each process in strategies 0 and 1. However beware that if the RooSimultaneous components do not share many
848 * parameters this strategy is inefficient: as most minuit-induced likelihood calculations involve changing
849 * a single parameter, only 1 of the N processes will be active most of the time if RooSimultaneous components
850 * do not share many parameters
851 * <tr><td> 3 = RooFit::Hybrid <td> Follow strategy 0 for all RooSimultaneous components, except those with less than
852 * 30 dataset entries, for which strategy 2 is followed.
853 * </table>
854 * <tr><td> `EvalBackend(std::string const&)` <td> Choose a likelihood evaluation backend:
855 * <table>
856 * <tr><th> Backend <th> Description
857 * <tr><td> **cpu** - *default* <td> New vectorized evaluation mode, using faster math functions and auto-vectorisation.
858 * Since ROOT 6.23, this is the default if `EvalBackend()` is not passed, succeeding the **legacy** backend.
859 * If all RooAbsArg objects in the model support vectorized evaluation,
860 * likelihood computations are 2 to 10 times faster than with the **legacy** backend
861 * - unless your dataset is so small that the vectorization is not worth it.
862 * The relative difference of the single log-likelihoods with respect to the legacy mode is usually better than \f$10^{-12}\f$,
863 * and for fit parameters it's usually better than \f$10^{-6}\f$. In past ROOT releases, this backend could be activated with the now deprecated `BatchMode()` option.
864 * <tr><td> **cuda** <td> Evaluate the likelihood on a GPU that supports CUDA.
865 * This backend re-uses code from the **cpu** backend, but compiled in CUDA kernels.
866 * Hence, the results are expected to be identical, modulo some numerical differences that can arise from the different order in which the GPU is summing the log probabilities.
867 * This backend can drastically speed up the fit if all RooAbsArg object in the model support it.
868 * <tr><td> **legacy** <td> The original likelihood evaluation method.
869 * Evaluates the PDF for each single data entry at a time before summing the negative log probabilities.
870 * <tr><td> **codegen** <td> **Experimental** - Generates and compiles minimal C++ code for the NLL on-the-fly and wraps it in the returned RooAbsReal.
871 * Also generates and compiles the code for the gradient using Automatic Differentiation (AD) with [Clad](https://github.com/vgvassilev/clad).
872 * This analytic gradient is passed to the minimizer, which can result in significant speedups for many-parameter fits,
873 * even compared to the **cpu** backend. However, if one of the RooAbsArg objects in the model does not support the code generation,
874 * this backend can't be used.
875 * <tr><td> **codegen_no_grad** <td> **Experimental** - Same as **codegen**, but doesn't generate and compile the gradient code and use the regular numerical differentiation instead.
876 * This is expected to be slower, but useful for debugging problems with the analytic gradient.
877 * </table>
878 * <tr><td> `Optimize(bool flag)` <td> Activate constant term optimization (on by default)
879 * <tr><td> `SplitRange(bool flag)` <td> Use separate fit ranges in a simultaneous fit. Actual range name for each subsample is assumed to
880 * be `rangeName_indexState`, where `indexState` is the state of the master index category of the simultaneous fit.
881 * Using `Range("range"), SplitRange()` as switches, different ranges could be set like this:
882 * ```
883 * myVariable.setRange("range_pi0", 135, 210);
884 * myVariable.setRange("range_gamma", 50, 210);
885 * ```
886 * <tr><td> `Constrain(const RooArgSet&pars)` <td> For p.d.f.s that contain internal parameter constraint terms (that is usually product PDFs, where one
887 * term of the product depends on parameters but not on the observable(s),), only apply constraints to the given subset of parameters.
888 * <tr><td> `ExternalConstraints(const RooArgSet& )` <td> Include given external constraints to likelihood by multiplying them with the original likelihood.
889 * <tr><td> `GlobalObservables(const RooArgSet&)` <td> Define the set of normalization observables to be used for the constraint terms.
890 * If none are specified the constrained parameters are used.
891 * <tr><td> `GlobalObservablesSource(const char* sourceName)` <td> Which source to prioritize for global observable values.
892 * Can be either:
893 * - `data`: to take the values from the dataset,
894 * falling back to the pdf value if a given global observable is not available.
895 * If no `GlobalObservables` or `GlobalObservablesTag` command argument is given, the set
896 * of global observables will be automatically defined to be the set stored in the data.
897 * - `model`: to take all values from the pdf and completely ignore the set of global observables stored in the data
898 * (not even using it to automatically define the set of global observables
899 * if the `GlobalObservables` or `GlobalObservablesTag` command arguments are not given).
900 * The default option is `data`.
901 * <tr><td> `GlobalObservablesTag(const char* tagName)` <td> Define the set of normalization observables to be used for the constraint terms by
902 * a string attribute associated with pdf observables that match the given tagName.
903 * <tr><td> `Verbose(bool flag)` <td> Controls RooFit informational messages in likelihood construction
904 * <tr><td> `CloneData(bool flag)` <td> Use clone of dataset in NLL (default is true).
905 * \warning Deprecated option that is ignored. It is up to the implementation of the NLL creation method if the data is cloned or not.
906 * <tr><td> `Offset(std::string const& mode)` <td> Likelihood offsetting mode. Can be either:
907 * <table>
908 * <tr><th> Mode <th> Description
909 * <tr><td> **none** - *default* <td> No offsetting.
910 * <tr><td> **initial** <td> Offset likelihood by initial value (so that starting value of FCN in minuit is zero).
911 * This can improve numeric stability in simultaneous fits with components with large likelihood values.
912 * <tr><td> **bin** <td> Offset likelihood bin-by-bin with a template histogram model based on the obersved data.
913 * This results in per-bin values that are all in the same order of magnitude, which reduces precision loss in the sum,
914 * which can drastically improve numeric stability.
915 * Furthermore, \f$2\cdot \text{NLL}\f$ defined like this is approximately chi-square distributed, allowing for goodness-of-fit tests.
916 * </table>
917 * <tr><td> `IntegrateBins(double precision)` <td> In binned fits, integrate the PDF over the bins instead of using the probability density at the bin centre.
918 * This can reduce the bias observed when fitting functions with high curvature to binned data.
919 * - precision > 0: Activate bin integration everywhere. Use precision between 0.01 and 1.E-6, depending on binning.
920 * Note that a low precision such as 0.01 might yield identical results to 1.E-4, since the integrator might reach 1.E-4 already in its first
921 * integration step. If lower precision is desired (more speed), a RooBinSamplingPdf has to be created manually, and its integrator
922 * has to be manipulated directly.
923 * - precision = 0: Activate bin integration only for continuous PDFs fit to a RooDataHist.
924 * - precision < 0: Deactivate.
925 * \see RooBinSamplingPdf
926 * <tr><td> `ModularL(bool flag)` <td> Enable or disable modular likelihoods, which will become the default in a future release.
927 * This does not change any user-facing code, but only enables a different likelihood class in the back-end. Note that this
928 * should be set to true for parallel minimization of likelihoods!
929 * Note that it is currently not recommended to use Modular likelihoods without any parallelization enabled in the minimization, since
930 * some features such as offsetting might not yet work in this case.
931 * </table>
932 */
933
934
935/** @brief Protected implementation of the NLL creation routine.
936 *
937 * This virtual function can be overridden in case you want to change the NLL creation logic for custom PDFs.
938 *
939 * \note Never call this function directly. Instead, call RooAbsPdf::createNLL().
940 */
941
942std::unique_ptr<RooAbsReal> RooAbsPdf::createNLLImpl(RooAbsData &data, const RooLinkedList &cmdList)
943{
944 return RooFit::FitHelpers::createNLL(*this, data, cmdList);
945}
946
947
948/** @fn RooAbsPdf::fitTo()
949 *
950 * @brief Fit PDF to given dataset.
951 *
952 * If dataset is unbinned, an unbinned maximum likelihood is performed.
953 * If the dataset is binned, a binned maximum likelihood is performed.
954 * By default the fit is executed through the MINUIT commands MIGRAD, HESSE in succession.
955 *
956 * @param data Reference to a RooAbsData object representing the dataset.
957 * @param cmdArgs Variadic template arguments representing optional command arguments.
958 * You can pass either an arbitrary number of RooCmdArg instances
959 * or a single RooLinkedList that points to the RooCmdArg objects.
960 * @return An owning pointer to the created RooAbsReal NLL object.
961 * @return RooFitResult with fit status and parameters if option Save() is used, `nullptr` otherwise. The user takes ownership of the fit result.
962 *
963 * @tparam CmdArgs_t Template types for optional command arguments.
964 * Can either be an arbitrary number of RooCmdArg or a single RooLinkedList.
965 *
966 * \note This front-end function should not be re-implemented in derived PDF types.
967 * If you mean to customize the likelihood fitting routine,
968 * you need to override the virtual RooAbsPdf::fitToImpl() method.
969 *
970 * The following named arguments are supported:
971 *
972 * <table>
973 * <tr><th> Type of CmdArg <th> Options to control construction of -log(L)
974 * <tr><td> <td> All command arguments that can also be passed to the NLL creation method.
975 * \see RooAbsPdf::createNLL()
976 *
977 * <tr><th><th> Options to control flow of fit procedure
978 * <tr><td> `Minimizer("<type>", "<algo>")` <td> Choose minimization package and optionally the algorithm to use. Default is MINUIT/MIGRAD through the RooMinimizer interface,
979 * but others can be specified (through RooMinimizer interface).
980 * <table>
981 * <tr><th> Type <th> Algorithm
982 * <tr><td> Minuit <td> migrad, simplex, minimize (=migrad+simplex), migradimproved (=migrad+improve)
983 * <tr><td> Minuit2 <td> migrad, simplex, minimize, scan
984 * <tr><td> GSLMultiMin <td> conjugatefr, conjugatepr, bfgs, bfgs2, steepestdescent
985 * <tr><td> GSLSimAn <td> -
986 * </table>
987 *
988 * <tr><td> `InitialHesse(bool flag)` <td> Flag controls if HESSE before MIGRAD as well, off by default
989 * <tr><td> `Optimize(bool flag)` <td> Activate constant term optimization of test statistic during minimization (on by default)
990 * <tr><td> `Hesse(bool flag)` <td> Flag controls if HESSE is run after MIGRAD, on by default
991 * <tr><td> `Minos(bool flag)` <td> Flag controls if MINOS is run after HESSE, off by default
992 * <tr><td> `Minos(const RooArgSet& set)` <td> Only run MINOS on given subset of arguments
993 * <tr><td> `Save(bool flag)` <td> Flag controls if RooFitResult object is produced and returned, off by default
994 * <tr><td> `Strategy(Int_t flag)` <td> Set Minuit strategy (0 to 2, default is 1)
995 * <tr><td> `MaxCalls(int n)` <td> Change maximum number of likelihood function calls from MINUIT (if `n <= 0`, the default of 500 * #%parameters is used)
996 * <tr><td> `EvalErrorWall(bool flag=true)` <td> When parameters are in disallowed regions (e.g. PDF is negative), return very high value to fitter
997 * to force it out of that region. This can, however, mean that the fitter gets lost in this region. If
998 * this happens, try switching it off.
999 * <tr><td> `RecoverFromUndefinedRegions(double strength)` <td> When PDF is invalid (e.g. parameter in undefined region), try to direct minimiser away from that region.
1000 * `strength` controls the magnitude of the penalty term. Leaving out this argument defaults to 10. Switch off with `strength = 0.`.
1001 *
1002 * <tr><td> `SumW2Error(bool flag)` <td> Apply correction to errors and covariance matrix.
1003 * This uses two covariance matrices, one with the weights, the other with squared weights,
1004 * to obtain the correct errors for weighted likelihood fits. If this option is activated, the
1005 * corrected covariance matrix is calculated as \f$ V_\mathrm{corr} = V C^{-1} V \f$, where \f$ V \f$ is the original
1006 * covariance matrix and \f$ C \f$ is the inverse of the covariance matrix calculated using the
1007 * squared weights. This allows to switch between two interpretations of errors:
1008 * <table>
1009 * <tr><th> SumW2Error <th> Interpretation
1010 * <tr><td> true <td> The errors reflect the uncertainty of the Monte Carlo simulation.
1011 * Use this if you want to know how much accuracy you can get from the available Monte Carlo statistics.
1012 *
1013 * **Example**: Simulation with 1000 events, the average weight is 0.1.
1014 * The errors are as big as if one fitted to 1000 events.
1015 * <tr><td> false <td> The errors reflect the errors of a dataset, which is as big as the sum of weights.
1016 * Use this if you want to know what statistical errors you would get if you had a dataset with as many
1017 * events as the (weighted) Monte Carlo simulation represents.
1018 *
1019 * **Example** (Data as above):
1020 * The errors are as big as if one fitted to 100 events.
1021 * </table>
1022 * \note If the `SumW2Error` correction is enabled, the covariance matrix quality stored in the RooFitResult
1023 * object will be the minimum of the original covariance matrix quality and the quality of the covariance
1024 * matrix calculated with the squared weights.
1025 * <tr><td> `AsymptoticError()` <td> Use the asymptotically correct approach to estimate errors in the presence of weights.
1026 * This is slower but more accurate than `SumW2Error`. See also https://arxiv.org/abs/1911.01303).
1027 * <tr><td> `PrefitDataFraction(double fraction)`
1028 * <td> Runs a prefit on a small dataset of size fraction*(actual data size). This can speed up fits
1029 * by finding good starting values for the parameters for the actual fit.
1030 * \warning Prefitting may give bad results when used in binned analysis.
1031 *
1032 * <tr><th><th> Options to control informational output
1033 * <tr><td> `Verbose(bool flag)` <td> Flag controls if verbose output is printed (NLL, parameter changes during fit).
1034 * <tr><td> `Timer(bool flag)` <td> Time CPU and wall clock consumption of fit steps, off by default.
1035 * <tr><td> `PrintLevel(Int_t level)` <td> Set Minuit print level (-1 to 3, default is 1). At -1 all RooFit informational messages are suppressed as well.
1036 * See RooMinimizer::PrintLevel for the meaning of the levels.
1037 * <tr><td> `Warnings(bool flag)` <td> Enable or disable MINUIT warnings (enabled by default)
1038 * <tr><td> `PrintEvalErrors(Int_t numErr)` <td> Control number of p.d.f evaluation errors printed per likelihood evaluation.
1039 * A negative value suppresses output completely, a zero value will only print the error count per p.d.f component,
1040 * a positive value will print details of each error up to `numErr` messages per p.d.f component.
1041 * <tr><td> `Parallelize(Int_t nWorkers)` <td> Control global parallelization settings. Arguments 1 and above enable the use of RooFit's parallel minimization
1042 * backend and uses the number given as the number of workers to use in the parallelization. -1 also enables
1043 * RooFit's parallel minimization backend, and sets the number of workers to the number of available processes.
1044 * 0 disables this feature.
1045 * In case parallelization is requested, this option implies `ModularL(true)` in the internal call to the NLL creation method.
1046 * <tr><td> `ParallelGradientOptions(bool enable=true, int orderStrategy=0, int chainFactor=1)` <td> **Experimental** - Control gradient parallelization settings. The first argument
1047 * only disables or enables gradient parallelization, this is on by default.
1048 * The second argument determines the internal partial derivative calculation
1049 * ordering strategy. The third argument determines the number of partial
1050 * derivatives that are executed per task package on each worker.
1051 * <tr><td> `ParallelDescentOptions(bool enable=false, int splitStrategy=0, int numSplits=4)` <td> **Experimental** - Control settings related to the parallelization of likelihoods
1052 * outside of the gradient calculation but in the minimization, most prominently
1053 * in the linesearch step. The first argument this disables or enables likelihood
1054 * parallelization. The second argument determines whether to split the task batches
1055 * per event or per likelihood component. And the third argument how many events or
1056 * respectively components to include in each batch.
1057 * <tr><td> `TimingAnalysis(bool flag)` <td> **Experimental** - Log timings. This feature logs timings with NewStyle likelihoods on multiple processes simultaneously
1058 * and outputs the timings at the end of a run to json log files, which can be analyzed with the
1059 * `RooFit::MultiProcess::HeatmapAnalyzer`. Only works with simultaneous likelihoods.
1060 * </table>
1061 */
1062
1063
1064/** @brief Protected implementation of the likelihood fitting routine.
1065 *
1066 * This virtual function can be overridden in case you want to change the likelihood fitting logic for custom PDFs.
1067 *
1068 * \note Never call this function directly. Instead, call RooAbsPdf::fitTo().
1069 */
1070
1071std::unique_ptr<RooFitResult> RooAbsPdf::fitToImpl(RooAbsData& data, const RooLinkedList& cmdList)
1072{
1073 return RooFit::FitHelpers::fitTo(*this, data, cmdList, false);
1074}
1075
1076
1077////////////////////////////////////////////////////////////////////////////////
1078/// Print value of p.d.f, also print normalization integral that was last used, if any
1079
1080void RooAbsPdf::printValue(ostream& os) const
1081{
1082 // silent warning messages coming when evaluating a RooAddPdf without a normalization set
1084
1085 getVal() ;
1086
1087 if (_norm) {
1088 os << getVal() << "/" << _norm->getVal() ;
1089 } else {
1090 os << getVal();
1091 }
1092}
1093
1094
1095
1096////////////////////////////////////////////////////////////////////////////////
1097/// Print multi line detailed information of this RooAbsPdf
1098
1099void RooAbsPdf::printMultiline(ostream& os, Int_t contents, bool verbose, TString indent) const
1100{
1101 RooAbsReal::printMultiline(os,contents,verbose,indent);
1102 os << indent << "--- RooAbsPdf ---" << endl;
1103 os << indent << "Cached value = " << _value << endl ;
1104 if (_norm) {
1105 os << indent << " Normalization integral: " << endl ;
1106 auto moreIndent = std::string(indent.Data()) + " " ;
1107 _norm->printStream(os,kName|kAddress|kTitle|kValue|kArgs,kSingleLine,moreIndent.c_str()) ;
1108 }
1109}
1110
1111
1112
1113////////////////////////////////////////////////////////////////////////////////
1114/// Return a binned generator context
1115
1117{
1118 return new RooBinnedGenContext(*this,vars,nullptr,nullptr,verbose) ;
1119}
1120
1121
1122////////////////////////////////////////////////////////////////////////////////
1123/// Interface function to create a generator context from a p.d.f. This default
1124/// implementation returns a 'standard' context that works for any p.d.f
1125
1127 const RooArgSet* auxProto, bool verbose) const
1128{
1129 return new RooGenContext(*this,vars,prototype,auxProto,verbose) ;
1130}
1131
1132
1133////////////////////////////////////////////////////////////////////////////////
1134
1135RooAbsGenContext* RooAbsPdf::autoGenContext(const RooArgSet &vars, const RooDataSet* prototype, const RooArgSet* auxProto,
1136 bool verbose, bool autoBinned, const char* binnedTag) const
1137{
1138 if (prototype || (auxProto && !auxProto->empty())) {
1139 return genContext(vars,prototype,auxProto,verbose);
1140 }
1141
1142 RooAbsGenContext *context(nullptr) ;
1143 if ( (autoBinned && isBinnedDistribution(vars)) || ( binnedTag && strlen(binnedTag) && (getAttribute(binnedTag)||string(binnedTag)=="*"))) {
1144 context = binnedGenContext(vars,verbose) ;
1145 } else {
1146 context= genContext(vars,nullptr,nullptr,verbose);
1147 }
1148 return context ;
1149}
1150
1151
1152
1153////////////////////////////////////////////////////////////////////////////////
1154/// Generate a new dataset containing the specified variables with events sampled from our distribution.
1155/// Generate the specified number of events or expectedEvents() if not specified.
1156/// \param[in] whatVars Choose variables in which to generate events. Variables not listed here will remain
1157/// constant and not be used for event generation.
1158/// \param[in] arg1,arg2,arg3,arg4,arg5,arg6 Optional RooCmdArg() to change behaviour of generate().
1159/// \return RooDataSet *, owned by caller.
1160///
1161/// Any variables of this PDF that are not in whatVars will use their
1162/// current values and be treated as fixed parameters. Returns zero
1163/// in case of an error.
1164///
1165/// <table>
1166/// <tr><th> Type of CmdArg <th> Effect on generate
1167/// <tr><td> `Name(const char* name)` <td> Name of the output dataset
1168/// <tr><td> `Verbose(bool flag)` <td> Print informational messages during event generation
1169/// <tr><td> `NumEvents(int nevt)` <td> Generate specified number of events
1170/// <tr><td> `Extended()` <td> If no number of events to be generated is given,
1171/// use expected number of events from extended likelihood term.
1172/// This evidently only works for extended PDFs.
1173/// <tr><td> `GenBinned(const char* tag)` <td> Use binned generation for all component pdfs that have 'setAttribute(tag)' set
1174/// <tr><td> `AutoBinned(bool flag)` <td> Automatically deploy binned generation for binned distributions (e.g. RooHistPdf, sums and products of
1175/// RooHistPdfs etc)
1176/// \note Datasets that are generated in binned mode are returned as weighted unbinned datasets. This means that
1177/// for each bin, there will be one event in the dataset with a weight corresponding to the (possibly randomised) bin content.
1178///
1179///
1180/// <tr><td> `AllBinned()` <td> As above, but for all components.
1181/// \note The notion of components is only meaningful for simultaneous PDFs
1182/// as binned generation is always executed at the top-level node for a regular
1183/// PDF, so for those it only mattes that the top-level node is tagged.
1184///
1185/// <tr><td> ProtoData(const RooDataSet& data, bool randOrder)
1186/// <td> Use specified dataset as prototype dataset. If randOrder in ProtoData() is set to true,
1187/// the order of the events in the dataset will be read in a random order if the requested
1188/// number of events to be generated does not match the number of events in the prototype dataset.
1189/// \note If ProtoData() is used, the specified existing dataset as a prototype: the new dataset will contain
1190/// the same number of events as the prototype (unless otherwise specified), and any prototype variables not in
1191/// whatVars will be copied into the new dataset for each generated event and also used to set our PDF parameters.
1192/// The user can specify a number of events to generate that will override the default. The result is a
1193/// copy of the prototype dataset with only variables in whatVars randomized. Variables in whatVars that
1194/// are not in the prototype will be added as new columns to the generated dataset.
1195///
1196/// </table>
1197///
1198/// #### Accessing the underlying event generator
1199/// Depending on the fit model (if it is difficult to sample), it may be necessary to change generator settings.
1200/// For the default generator (RooFoamGenerator), the number of samples or cells could be increased by e.g. using
1201/// myPdf->specialGeneratorConfig()->getConfigSection("RooFoamGenerator").setRealValue("nSample",1e4);
1202///
1203/// The foam generator e.g. has the following config options:
1204/// - nCell[123N]D
1205/// - nSample
1206/// - chatLevel
1207/// \see rf902_numgenconfig.C
1208
1210 const RooCmdArg& arg3,const RooCmdArg& arg4, const RooCmdArg& arg5,const RooCmdArg& arg6)
1211{
1212 // Select the pdf-specific commands
1213 RooCmdConfig pc("RooAbsPdf::generate(" + std::string(GetName()) + ")");
1214 pc.defineObject("proto","PrototypeData",0,nullptr) ;
1215 pc.defineString("dsetName","Name",0,"") ;
1216 pc.defineInt("randProto","PrototypeData",0,0) ;
1217 pc.defineInt("resampleProto","PrototypeData",1,0) ;
1218 pc.defineInt("verbose","Verbose",0,0) ;
1219 pc.defineInt("extended","Extended",0,0) ;
1220 pc.defineInt("nEvents","NumEvents",0,0) ;
1221 pc.defineInt("autoBinned","AutoBinned",0,1) ;
1222 pc.defineInt("expectedData","ExpectedData",0,0) ;
1223 pc.defineDouble("nEventsD","NumEventsD",0,-1.) ;
1224 pc.defineString("binnedTag","GenBinned",0,"") ;
1225 pc.defineMutex("GenBinned","ProtoData") ;
1226 pc.defineMutex("Extended", "NumEvents");
1227
1228 // Process and check varargs
1229 pc.process(arg1,arg2,arg3,arg4,arg5,arg6) ;
1230 if (!pc.ok(true)) {
1231 return nullptr;
1232 }
1233
1234 // Decode command line arguments
1235 RooDataSet* protoData = static_cast<RooDataSet*>(pc.getObject("proto",nullptr)) ;
1236 const char* dsetName = pc.getString("dsetName") ;
1237 bool verbose = pc.getInt("verbose") ;
1238 bool randProto = pc.getInt("randProto") ;
1239 bool resampleProto = pc.getInt("resampleProto") ;
1240 bool extended = pc.getInt("extended") ;
1241 bool autoBinned = pc.getInt("autoBinned") ;
1242 const char* binnedTag = pc.getString("binnedTag") ;
1243 Int_t nEventsI = pc.getInt("nEvents") ;
1244 double nEventsD = pc.getInt("nEventsD") ;
1245 //bool verbose = pc.getInt("verbose") ;
1246 bool expectedData = pc.getInt("expectedData") ;
1247
1248 double nEvents = (nEventsD>0) ? nEventsD : double(nEventsI);
1249
1250 // Force binned mode for expected data mode
1251 if (expectedData) {
1252 binnedTag="*" ;
1253 }
1254
1255 if (extended) {
1256 if (nEvents == 0) nEvents = expectedEvents(&whatVars);
1257 } else if (nEvents==0) {
1258 cxcoutI(Generation) << "No number of events specified , number of events generated is "
1259 << GetName() << "::expectedEvents() = " << expectedEvents(&whatVars)<< endl ;
1260 }
1261
1262 if (extended && protoData && !randProto) {
1263 cxcoutI(Generation) << "WARNING Using generator option Extended() (Poisson distribution of #events) together "
1264 << "with a prototype dataset implies incomplete sampling or oversampling of proto data. "
1265 << "Set randomize flag in ProtoData() option to randomize prototype dataset order and thus "
1266 << "to randomize the set of over/undersampled prototype events for each generation cycle." << endl ;
1267 }
1268
1269
1270 // Forward to appropriate implementation
1271 std::unique_ptr<RooDataSet> data;
1272 if (protoData) {
1273 data = std::unique_ptr<RooDataSet>{generate(whatVars,*protoData,Int_t(nEvents),verbose,randProto,resampleProto)};
1274 } else {
1275 data = std::unique_ptr<RooDataSet>{generate(whatVars,nEvents,verbose,autoBinned,binnedTag,expectedData, extended)};
1276 }
1277
1278 // Rename dataset to given name if supplied
1279 if (dsetName && strlen(dsetName)>0) {
1280 data->SetName(dsetName) ;
1281 }
1282
1283 return RooFit::makeOwningPtr(std::move(data));
1284}
1285
1286
1287
1288
1289
1290
1291////////////////////////////////////////////////////////////////////////////////
1292/// \note This method does not perform any generation. To generate according to generations specification call RooAbsPdf::generate(RooAbsPdf::GenSpec&) const
1293///
1294/// Details copied from RooAbsPdf::generate():
1295/// --------------------------------------------
1296/// \copydetails RooAbsPdf::generate(const RooArgSet&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&)
1297
1299 const RooCmdArg& arg1,const RooCmdArg& arg2,
1300 const RooCmdArg& arg3,const RooCmdArg& arg4,
1301 const RooCmdArg& arg5,const RooCmdArg& arg6)
1302{
1303
1304 // Select the pdf-specific commands
1305 RooCmdConfig pc("RooAbsPdf::generate(" + std::string(GetName()) + ")");
1306 pc.defineObject("proto","PrototypeData",0,nullptr) ;
1307 pc.defineString("dsetName","Name",0,"") ;
1308 pc.defineInt("randProto","PrototypeData",0,0) ;
1309 pc.defineInt("resampleProto","PrototypeData",1,0) ;
1310 pc.defineInt("verbose","Verbose",0,0) ;
1311 pc.defineInt("extended","Extended",0,0) ;
1312 pc.defineInt("nEvents","NumEvents",0,0) ;
1313 pc.defineInt("autoBinned","AutoBinned",0,1) ;
1314 pc.defineString("binnedTag","GenBinned",0,"") ;
1315 pc.defineMutex("GenBinned","ProtoData") ;
1316
1317
1318 // Process and check varargs
1319 pc.process(arg1,arg2,arg3,arg4,arg5,arg6) ;
1320 if (!pc.ok(true)) {
1321 return nullptr ;
1322 }
1323
1324 // Decode command line arguments
1325 RooDataSet* protoData = static_cast<RooDataSet*>(pc.getObject("proto",nullptr)) ;
1326 const char* dsetName = pc.getString("dsetName") ;
1327 Int_t nEvents = pc.getInt("nEvents") ;
1328 bool verbose = pc.getInt("verbose") ;
1329 bool randProto = pc.getInt("randProto") ;
1330 bool resampleProto = pc.getInt("resampleProto") ;
1331 bool extended = pc.getInt("extended") ;
1332 bool autoBinned = pc.getInt("autoBinned") ;
1333 const char* binnedTag = pc.getString("binnedTag") ;
1334
1335 RooAbsGenContext* cx = autoGenContext(whatVars,protoData,nullptr,verbose,autoBinned,binnedTag) ;
1336
1337 return new GenSpec(cx,whatVars,protoData,nEvents,extended,randProto,resampleProto,dsetName) ;
1338}
1339
1340
1341////////////////////////////////////////////////////////////////////////////////
1342/// If many identical generation requests
1343/// are needed, e.g. in toy MC studies, it is more efficient to use the prepareMultiGen()/generate()
1344/// combination than calling the standard generate() multiple times as
1345/// initialization overhead is only incurred once.
1346
1348{
1349 //Int_t nEvt = spec._extended ? RooRandom::randomGenerator()->Poisson(spec._nGen) : spec._nGen ;
1350 //Int_t nEvt = spec._extended ? RooRandom::randomGenerator()->Poisson(spec._nGen==0?expectedEvents(spec._whatVars):spec._nGen) : spec._nGen ;
1351 //Int_t nEvt = spec._nGen == 0 ? RooRandom::randomGenerator()->Poisson(expectedEvents(spec._whatVars)) : spec._nGen;
1352
1353 double nEvt = spec._nGen == 0 ? expectedEvents(spec._whatVars) : spec._nGen;
1354
1355 std::unique_ptr<RooDataSet> ret{generate(*spec._genContext,spec._whatVars,spec._protoData, nEvt,false,spec._randProto,spec._resampleProto,
1356 spec._init,spec._extended)};
1357 spec._init = true ;
1358 return RooFit::makeOwningPtr(std::move(ret));
1359}
1360
1361
1362
1363
1364
1365////////////////////////////////////////////////////////////////////////////////
1366/// Generate a new dataset containing the specified variables with
1367/// events sampled from our distribution.
1368///
1369/// \param[in] whatVars Generate a dataset with the variables (and categories) in this set.
1370/// Any variables of this PDF that are not in `whatVars` will use their
1371/// current values and be treated as fixed parameters.
1372/// \param[in] nEvents Generate the specified number of events or else try to use
1373/// expectedEvents() if nEvents <= 0 (default).
1374/// \param[in] verbose Show which generator strategies are being used.
1375/// \param[in] autoBinned If original distribution is binned, return bin centers and randomise weights
1376/// instead of generating single events.
1377/// \param[in] binnedTag
1378/// \param[in] expectedData Call setExpectedData on the genContext.
1379/// \param[in] extended Randomise number of events generated according to Poisson(nEvents). Only useful
1380/// if PDF is extended.
1381/// \return New dataset. Returns zero in case of an error. The caller takes ownership of the returned
1382/// dataset.
1383
1384RooFit::OwningPtr<RooDataSet> RooAbsPdf::generate(const RooArgSet &whatVars, double nEvents, bool verbose, bool autoBinned, const char* binnedTag, bool expectedData, bool extended) const
1385{
1386 if (nEvents==0 && extendMode()==CanNotBeExtended) {
1387 return RooFit::makeOwningPtr(std::make_unique<RooDataSet>("emptyData","emptyData",whatVars));
1388 }
1389
1390 // Request for binned generation
1391 std::unique_ptr<RooAbsGenContext> context{autoGenContext(whatVars,nullptr,nullptr,verbose,autoBinned,binnedTag)};
1392 if (expectedData) {
1393 context->setExpectedData(true) ;
1394 }
1395
1396 std::unique_ptr<RooDataSet> generated;
1397 if(nullptr != context && context->isValid()) {
1398 generated = std::unique_ptr<RooDataSet>{context->generate(nEvents, false, extended)};
1399 }
1400 else {
1401 coutE(Generation) << "RooAbsPdf::generate(" << GetName() << ") cannot create a valid context" << endl;
1402 }
1403 return RooFit::makeOwningPtr(std::move(generated));
1404}
1405
1406
1407
1408
1409////////////////////////////////////////////////////////////////////////////////
1410/// Internal method
1411
1412std::unique_ptr<RooDataSet> RooAbsPdf::generate(RooAbsGenContext& context, const RooArgSet &whatVars, const RooDataSet *prototype,
1413 double nEvents, bool /*verbose*/, bool randProtoOrder, bool resampleProto,
1414 bool skipInit, bool extended) const
1415{
1416 if (nEvents==0 && (prototype==nullptr || prototype->numEntries()==0)) {
1417 return std::make_unique<RooDataSet>("emptyData","emptyData",whatVars);
1418 }
1419
1420 std::unique_ptr<RooDataSet> generated;
1421
1422 // Resampling implies reshuffling in the implementation
1423 if (resampleProto) {
1424 randProtoOrder=true ;
1425 }
1426
1427 if (randProtoOrder && prototype && prototype->numEntries()!=nEvents) {
1428 coutI(Generation) << "RooAbsPdf::generate (Re)randomizing event order in prototype dataset (Nevt=" << nEvents << ")" << endl ;
1429 Int_t* newOrder = randomizeProtoOrder(prototype->numEntries(),Int_t(nEvents),resampleProto) ;
1430 context.setProtoDataOrder(newOrder) ;
1431 delete[] newOrder ;
1432 }
1433
1434 if(context.isValid()) {
1435 generated = std::unique_ptr<RooDataSet>{context.generate(nEvents,skipInit,extended)};
1436 }
1437 else {
1438 coutE(Generation) << "RooAbsPdf::generate(" << GetName() << ") do not have a valid generator context" << endl;
1439 }
1440 return generated;
1441}
1442
1443
1444
1445
1446////////////////////////////////////////////////////////////////////////////////
1447/// Generate a new dataset using a prototype dataset as a model,
1448/// with values of the variables in `whatVars` sampled from our distribution.
1449///
1450/// \param[in] whatVars Generate for these variables.
1451/// \param[in] prototype Use this dataset
1452/// as a prototype: the new dataset will contain the same number of
1453/// events as the prototype (by default), and any prototype variables not in
1454/// whatVars will be copied into the new dataset for each generated
1455/// event and also used to set our PDF parameters. The user can specify a
1456/// number of events to generate that will override the default. The result is a
1457/// copy of the prototype dataset with only variables in whatVars
1458/// randomized. Variables in whatVars that are not in the prototype
1459/// will be added as new columns to the generated dataset.
1460/// \param[in] nEvents Number of events to generate. Defaults to 0, which means number
1461/// of event in prototype dataset.
1462/// \param[in] verbose Show which generator strategies are being used.
1463/// \param[in] randProtoOrder Randomise order of retrieval of events from proto dataset.
1464/// \param[in] resampleProto Resample from the proto dataset.
1465/// \return The new dataset. Returns zero in case of an error. The caller takes ownership of the
1466/// returned dataset.
1467
1469 Int_t nEvents, bool verbose, bool randProtoOrder, bool resampleProto) const
1470{
1471 std::unique_ptr<RooAbsGenContext> context{genContext(whatVars,&prototype,nullptr,verbose)};
1472 if (context) {
1473 return RooFit::makeOwningPtr(generate(*context,whatVars,&prototype,nEvents,verbose,randProtoOrder,resampleProto));
1474 }
1475 coutE(Generation) << "RooAbsPdf::generate(" << GetName() << ") ERROR creating generator context" << endl ;
1476 return nullptr;
1477}
1478
1479
1480
1481////////////////////////////////////////////////////////////////////////////////
1482/// Return lookup table with randomized order for nProto prototype events.
1483
1484Int_t* RooAbsPdf::randomizeProtoOrder(Int_t nProto, Int_t, bool resampleProto) const
1485{
1486 // Make output list
1487 Int_t* lut = new Int_t[nProto] ;
1488
1489 // Randomly sample input list into output list
1490 if (!resampleProto) {
1491 // In this mode, randomization is a strict reshuffle of the order
1492 std::iota(lut, lut + nProto, 0); // fill the vector with 0 to nProto - 1
1493 // Shuffle code taken from https://en.cppreference.com/w/cpp/algorithm/random_shuffle.
1494 // The std::random_shuffle function was deprecated in C++17. We could have
1495 // used std::shuffle instead, but this is not straight-forward to use with
1496 // RooRandom::integer() and we didn't want to change the random number
1497 // generator. It might cause unwanted effects like reproducibility problems.
1498 for (int i = nProto-1; i > 0; --i) {
1499 std::swap(lut[i], lut[RooRandom::integer(i+1)]);
1500 }
1501 } else {
1502 // In this mode, we resample, i.e. events can be used more than once
1503 std::generate(lut, lut + nProto, [&]{ return RooRandom::integer(nProto); });
1504 }
1505
1506
1507 return lut ;
1508}
1509
1510
1511
1512////////////////////////////////////////////////////////////////////////////////
1513/// Load generatedVars with the subset of directVars that we can generate events for,
1514/// and return a code that specifies the generator algorithm we will use. A code of
1515/// zero indicates that we cannot generate any of the directVars (in this case, nothing
1516/// should be added to generatedVars). Any non-zero codes will be passed to our generateEvent()
1517/// implementation, but otherwise its value is arbitrary. The default implementation of
1518/// this method returns zero. Subclasses will usually implement this method using the
1519/// matchArgs() methods to advertise the algorithms they provide.
1520
1521Int_t RooAbsPdf::getGenerator(const RooArgSet &/*directVars*/, RooArgSet &/*generatedVars*/, bool /*staticInitOK*/) const
1522{
1523 return 0 ;
1524}
1525
1526
1527
1528////////////////////////////////////////////////////////////////////////////////
1529/// Interface for one-time initialization to setup the generator for the specified code.
1530
1532{
1533}
1534
1535
1536
1537////////////////////////////////////////////////////////////////////////////////
1538/// Interface for generation of an event using the algorithm
1539/// corresponding to the specified code. The meaning of each code is
1540/// defined by the getGenerator() implementation. The default
1541/// implementation does nothing.
1542
1544{
1545}
1546
1547
1548
1549////////////////////////////////////////////////////////////////////////////////
1550/// Check if given observable can be safely generated using the
1551/// pdfs internal generator mechanism (if that existsP). Observables
1552/// on which a PDF depends via more than route are not safe
1553/// for use with internal generators because they introduce
1554/// correlations not known to the internal generator
1555
1557{
1558 // Arg must be direct server of self
1559 if (!findServer(arg.GetName())) return false ;
1560
1561 // There must be no other dependency routes
1562 for (const auto server : _serverList) {
1563 if(server == &arg) continue;
1564 if(server->dependsOn(arg)) {
1565 return false ;
1566 }
1567 }
1568
1569 return true ;
1570}
1571
1572
1573////////////////////////////////////////////////////////////////////////////////
1574/// Generate a new dataset containing the specified variables with events sampled from our distribution.
1575/// \param[in] whatVars Choose variables in which to generate events. Variables not listed here will remain
1576/// constant and not be used for event generation
1577/// \param[in] arg1,arg2,arg3,arg4,arg5,arg6 Optional RooCmdArg to change behaviour of generateBinned()
1578/// \return RooDataHist *, to be managed by caller.
1579///
1580/// Generate the specified number of events or expectedEvents() if not specified.
1581///
1582/// Any variables of this PDF that are not in whatVars will use their
1583/// current values and be treated as fixed parameters. Returns zero
1584/// in case of an error. The caller takes ownership of the returned
1585/// dataset.
1586///
1587/// The following named arguments are supported
1588/// | Type of CmdArg | Effect on generation
1589/// |---------------------------|-----------------------
1590/// | `Name(const char* name)` | Name of the output dataset
1591/// | `Verbose(bool flag)` | Print informational messages during event generation
1592/// | `NumEvents(int nevt)` | Generate specified number of events
1593/// | `Extended()` | The actual number of events generated will be sampled from a Poisson distribution with mu=nevt. This can be *much* faster for peaked PDFs, but the number of events is not exactly what was requested.
1594/// | `ExpectedData()` | Return a binned dataset _without_ statistical fluctuations (also aliased as Asimov())
1595///
1596
1598 const RooCmdArg& arg3,const RooCmdArg& arg4, const RooCmdArg& arg5,const RooCmdArg& arg6) const
1599{
1600
1601 // Select the pdf-specific commands
1602 RooCmdConfig pc("RooAbsPdf::generate(" + std::string(GetName()) + ")");
1603 pc.defineString("dsetName","Name",0,"") ;
1604 pc.defineInt("verbose","Verbose",0,0) ;
1605 pc.defineInt("extended","Extended",0,0) ;
1606 pc.defineInt("nEvents","NumEvents",0,0) ;
1607 pc.defineDouble("nEventsD","NumEventsD",0,-1.) ;
1608 pc.defineInt("expectedData","ExpectedData",0,0) ;
1609
1610 // Process and check varargs
1611 pc.process(arg1,arg2,arg3,arg4,arg5,arg6) ;
1612 if (!pc.ok(true)) {
1613 return nullptr;
1614 }
1615
1616 // Decode command line arguments
1617 double nEvents = pc.getDouble("nEventsD") ;
1618 if (nEvents<0) {
1619 nEvents = pc.getInt("nEvents") ;
1620 }
1621 //bool verbose = pc.getInt("verbose") ;
1622 bool extended = pc.getInt("extended") ;
1623 bool expectedData = pc.getInt("expectedData") ;
1624 const char* dsetName = pc.getString("dsetName") ;
1625
1626 if (extended) {
1627 //nEvents = (nEvents==0?Int_t(expectedEvents(&whatVars)+0.5):nEvents) ;
1628 nEvents = (nEvents==0 ? expectedEvents(&whatVars) :nEvents) ;
1629 cxcoutI(Generation) << " Extended mode active, number of events generated (" << nEvents << ") is Poisson fluctuation on "
1630 << GetName() << "::expectedEvents() = " << nEvents << endl ;
1631 // If Poisson fluctuation results in zero events, stop here
1632 if (nEvents==0) {
1633 return nullptr ;
1634 }
1635 } else if (nEvents==0) {
1636 cxcoutI(Generation) << "No number of events specified , number of events generated is "
1637 << GetName() << "::expectedEvents() = " << expectedEvents(&whatVars)<< endl ;
1638 }
1639
1640 // Forward to appropriate implementation
1641 auto data = generateBinned(whatVars,nEvents,expectedData,extended);
1642
1643 // Rename dataset to given name if supplied
1644 if (dsetName && strlen(dsetName)>0) {
1645 data->SetName(dsetName) ;
1646 }
1647
1648 return data;
1649}
1650
1651
1652
1653
1654////////////////////////////////////////////////////////////////////////////////
1655/// Generate a new dataset containing the specified variables with
1656/// events sampled from our distribution.
1657///
1658/// \param[in] whatVars Variables that values should be generated for.
1659/// \param[in] nEvents How many events to generate. If `nEvents <=0`, use the value returned by expectedEvents() as target.
1660/// \param[in] expectedData If set to true (false by default), the returned histogram returns the 'expected'
1661/// data sample, i.e. no statistical fluctuations are present.
1662/// \param[in] extended For each bin, generate Poisson(x, mu) events, where `mu` is chosen such that *on average*,
1663/// one would obtain `nEvents` events. This means that the true number of events will fluctuate around the desired value,
1664/// but the generation happens a lot faster.
1665/// Especially if the PDF is sharply peaked, the multinomial event generation necessary to generate *exactly* `nEvents` events can
1666/// be very slow.
1667///
1668/// The binning used for generation of events is the currently set binning for the variables.
1669/// It can e.g. be changed using
1670/// ```
1671/// x.setBins(15);
1672/// x.setRange(-5., 5.);
1673/// pdf.generateBinned(RooArgSet(x), 1000);
1674/// ```
1675///
1676/// Any variables of this PDF that are not in `whatVars` will use their
1677/// current values and be treated as fixed parameters.
1678/// \return RooDataHist* owned by the caller. Returns `nullptr` in case of an error.
1679RooFit::OwningPtr<RooDataHist> RooAbsPdf::generateBinned(const RooArgSet &whatVars, double nEvents, bool expectedData, bool extended) const
1680{
1681 // Create empty RooDataHist
1682 auto hist = std::make_unique<RooDataHist>("genData","genData",whatVars);
1683
1684 // Scale to number of events and introduce Poisson fluctuations
1685 if (nEvents<=0) {
1686 if (!canBeExtended()) {
1687 coutE(InputArguments) << "RooAbsPdf::generateBinned(" << GetName() << ") ERROR: No event count provided and p.d.f does not provide expected number of events" << endl ;
1688 return nullptr;
1689 } else {
1690
1691 // Don't round in expectedData or extended mode
1692 if (expectedData || extended) {
1693 nEvents = expectedEvents(&whatVars) ;
1694 } else {
1695 nEvents = std::round(expectedEvents(&whatVars));
1696 }
1697 }
1698 }
1699
1700 // Sample p.d.f. distribution
1701 fillDataHist(hist.get(),&whatVars,1,true) ;
1702
1703 vector<int> histOut(hist->numEntries()) ;
1704 double histMax(-1) ;
1705 Int_t histOutSum(0) ;
1706 for (int i=0 ; i<hist->numEntries() ; i++) {
1707 hist->get(i) ;
1708 if (expectedData) {
1709
1710 // Expected data, multiply p.d.f by nEvents
1711 double w=hist->weight()*nEvents ;
1712 hist->set(i, w, sqrt(w));
1713
1714 } else if (extended) {
1715
1716 // Extended mode, set contents to Poisson(pdf*nEvents)
1717 double w = RooRandom::randomGenerator()->Poisson(hist->weight()*nEvents) ;
1718 hist->set(w,sqrt(w)) ;
1719
1720 } else {
1721
1722 // Regular mode, fill array of weights with Poisson(pdf*nEvents), but to not fill
1723 // histogram yet.
1724 if (hist->weight()>histMax) {
1725 histMax = hist->weight() ;
1726 }
1727 histOut[i] = RooRandom::randomGenerator()->Poisson(hist->weight()*nEvents) ;
1728 histOutSum += histOut[i] ;
1729 }
1730 }
1731
1732
1733 if (!expectedData && !extended) {
1734
1735 // Second pass for regular mode - Trim/Extend dataset to exact number of entries
1736
1737 // Calculate difference between what is generated so far and what is requested
1738 Int_t nEvtExtra = std::abs(Int_t(nEvents)-histOutSum) ;
1739 Int_t wgt = (histOutSum>nEvents) ? -1 : 1 ;
1740
1741 // Perform simple binned accept/reject procedure to get to exact event count
1742 std::size_t counter = 0;
1743 bool havePrintedInfo = false;
1744 while(nEvtExtra>0) {
1745
1746 Int_t ibinRand = RooRandom::randomGenerator()->Integer(hist->numEntries()) ;
1747 hist->get(ibinRand) ;
1748 double ranY = RooRandom::randomGenerator()->Uniform(histMax) ;
1749
1750 if (ranY<hist->weight()) {
1751 if (wgt==1) {
1752 histOut[ibinRand]++ ;
1753 } else {
1754 // If weight is negative, prior bin content must be at least 1
1755 if (histOut[ibinRand]>0) {
1756 histOut[ibinRand]-- ;
1757 } else {
1758 continue ;
1759 }
1760 }
1761 nEvtExtra-- ;
1762 }
1763
1764 if ((counter++ > 10*nEvents || nEvents > 1.E7) && !havePrintedInfo) {
1765 havePrintedInfo = true;
1766 coutP(Generation) << "RooAbsPdf::generateBinned(" << GetName() << ") Performing costly accept/reject sampling. If this takes too long, use "
1767 << "extended mode to speed up the process." << std::endl;
1768 }
1769 }
1770
1771 // Transfer working array to histogram
1772 for (int i=0 ; i<hist->numEntries() ; i++) {
1773 hist->get(i) ;
1774 hist->set(histOut[i],sqrt(1.0*histOut[i])) ;
1775 }
1776
1777 } else if (expectedData) {
1778
1779 // Second pass for expectedData mode -- Normalize to exact number of requested events
1780 // Minor difference may be present in first round due to difference between
1781 // bin average and bin integral in sampling bins
1782 double corr = nEvents/hist->sumEntries() ;
1783 for (int i=0 ; i<hist->numEntries() ; i++) {
1784 hist->get(i) ;
1785 hist->set(hist->weight()*corr,sqrt(hist->weight()*corr)) ;
1786 }
1787
1788 }
1789
1790 return RooFit::makeOwningPtr(std::move(hist));
1791}
1792
1793
1794
1795////////////////////////////////////////////////////////////////////////////////
1796/// Special generator interface for generation of 'global observables' -- for RooStats tools
1797
1799{
1800 return generate(whatVars,nEvents) ;
1801}
1802
1803namespace {
1804void removeRangeOverlap(std::vector<std::pair<double, double>>& ranges) {
1805 //Sort from left to right
1806 std::sort(ranges.begin(), ranges.end());
1807
1808 for (auto it = ranges.begin(); it != ranges.end(); ++it) {
1809 double& startL = it->first;
1810 double& endL = it->second;
1811
1812 for (auto innerIt = it+1; innerIt != ranges.end(); ++innerIt) {
1813 const double startR = innerIt->first;
1814 const double endR = innerIt->second;
1815
1816 if (startL <= startR && startR <= endL) {
1817 //Overlapping ranges, extend left one
1818 endL = std::max(endL, endR);
1819 *innerIt = make_pair(0., 0.);
1820 }
1821 }
1822 }
1823
1824 auto newEnd = std::remove_if(ranges.begin(), ranges.end(),
1825 [](const std::pair<double,double>& input){
1826 return input.first == input.second;
1827 });
1828 ranges.erase(newEnd, ranges.end());
1829}
1830}
1831
1832
1833////////////////////////////////////////////////////////////////////////////////
1834/// Plot (project) PDF on specified frame.
1835/// - If a PDF is plotted in an empty frame, it
1836/// will show a unit-normalized curve in the frame variable. When projecting a multi-
1837/// dimensional PDF onto the frame axis, hidden parameters are taken are taken at
1838/// their current value.
1839/// - If a PDF is plotted in a frame in which a dataset has already been plotted, it will
1840/// show a projection integrated over all variables that were present in the shown
1841/// dataset (except for the one on the x-axis). The normalization of the curve will
1842/// be adjusted to the event count of the plotted dataset. An informational message
1843/// will be printed for each projection step that is performed.
1844/// - If a PDF is plotted in a frame showing a dataset *after* a fit, the above happens,
1845/// but the PDF will be drawn and normalised only in the fit range. If this is not desired,
1846/// plotting and normalisation range can be overridden using Range() and NormRange() as
1847/// documented in the table below.
1848///
1849/// This function takes the following named arguments (for more arguments, see also
1850/// RooAbsReal::plotOn(RooPlot*,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,
1851/// const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,
1852/// const RooCmdArg&) const )
1853///
1854///
1855/// <table>
1856/// <tr><th> Type of argument <th> Controlling normalisation
1857/// <tr><td> `NormRange(const char* name)` <td> Calculate curve normalization w.r.t. specified range[s].
1858/// See the tutorial rf212_plottingInRanges_blinding.C
1859/// \note Setting a Range() by default also sets a NormRange() on the same range, meaning that the
1860/// PDF is plotted and normalised in the same range. Overriding this can be useful if the PDF was fit
1861/// in limited range[s] such as side bands, `NormRange("sidebandLeft,sidebandRight")`, but the PDF
1862/// should be drawn in the full range, `Range("")`.
1863///
1864/// <tr><td> `Normalization(double scale, ScaleType code)` <td> Adjust normalization by given scale factor.
1865/// Interpretation of number depends on code:
1866/// `RooAbsReal::Relative`: relative adjustment factor
1867/// `RooAbsReal::NumEvent`: scale to match given number of events.
1868///
1869/// <tr><th> Type of argument <th> Misc control
1870/// <tr><td> `Name(const chat* name)` <td> Give curve specified name in frame. Useful if curve is to be referenced later
1871/// <tr><td> `Asymmetry(const RooCategory& c)` <td> Show the asymmetry of the PDF in given two-state category
1872/// \f$ \frac{F(+)-F(-)}{F(+)+F(-)} \f$ rather than the PDF projection. Category must have two
1873/// states with indices -1 and +1 or three states with indices -1,0 and +1.
1874/// <tr><td> `ShiftToZero(bool flag)` <td> Shift entire curve such that lowest visible point is at exactly zero.
1875/// Mostly useful when plotting -log(L) or \f$ \chi^2 \f$ distributions
1876/// <tr><td> `AddTo(const char* name, double_t wgtSelf, double_t wgtOther)` <td> Create a projection of this PDF onto the x-axis, but
1877/// instead of plotting it directly, add it to an existing curve with given name (and relative weight factors).
1878/// <tr><td> `Components(const char* names)` <td> When plotting sums of PDFs, plot only the named components (*e.g.* only
1879/// the signal of a signal+background model).
1880/// <tr><td> `Components(const RooArgSet& compSet)` <td> As above, but pass a RooArgSet of the components themselves.
1881///
1882/// <tr><th> Type of argument <th> Projection control
1883/// <tr><td> `Slice(const RooArgSet& set)` <td> Override default projection behaviour by omitting observables listed
1884/// in set from the projection, i.e. by not integrating over these.
1885/// Slicing is usually only sensible in discrete observables, by e.g. creating a slice
1886/// of the PDF at the current value of the category observable.
1887/// <tr><td> `Slice(RooCategory& cat, const char* label)` <td> Override default projection behaviour by omitting the specified category
1888/// observable from the projection, i.e., by not integrating over all states of this category.
1889/// The slice is positioned at the given label value. Multiple Slice() commands can be given to specify slices
1890/// in multiple observables, e.g.
1891/// ```{.cpp}
1892/// pdf.plotOn(frame, Slice(tagCategory, "2tag"), Slice(jetCategory, "3jet"));
1893/// ```
1894/// <tr><td> `Project(const RooArgSet& set)` <td> Override default projection behaviour by projecting
1895/// over observables given in set, completely ignoring the default projection behavior. Advanced use only.
1896/// <tr><td> `ProjWData(const RooAbsData& d)` <td> Override default projection _technique_ (integration). For observables
1897/// present in given dataset projection of PDF is achieved by constructing an average over all observable
1898/// values in given set. Consult RooFit plotting tutorial for further explanation of meaning & use of this technique
1899/// <tr><td> `ProjWData(const RooArgSet& s, const RooAbsData& d)` <td> As above but only consider subset 's' of
1900/// observables in dataset 'd' for projection through data averaging
1901/// <tr><td> `ProjectionRange(const char* rn)` <td> When projecting the PDF onto the plot axis, it is usually integrated
1902/// over the full range of the invisible variables. The ProjectionRange overrides this.
1903/// This is useful if the PDF was fitted in a limited range in y, but it is now projected onto x. If
1904/// `ProjectionRange("<name of fit range>")` is passed, the projection is normalised correctly.
1905///
1906/// <tr><th> Type of argument <th> Plotting control
1907/// <tr><td> `LineStyle(Int_t style)` <td> Select line style by ROOT line style code, default is solid
1908/// <tr><td> `LineColor(Int_t color)` <td> Select line color by ROOT color code, default is blue
1909/// <tr><td> `LineWidth(Int_t width)` <td> Select line with in pixels, default is 3
1910/// <tr><td> `FillStyle(Int_t style)` <td> Select fill style, default is not filled. If a filled style is selected,
1911/// also use VLines() to add vertical downward lines at end of curve to ensure proper closure
1912/// <tr><td> `FillColor(Int_t color)` <td> Select fill color by ROOT color code
1913/// <tr><td> `Range(const char* name)` <td> Only draw curve in range defined by given name. Multiple comma-separated ranges can be given.
1914/// An empty string "" or `nullptr` means to use the default range of the variable.
1915/// <tr><td> `Range(double lo, double hi)` <td> Only draw curve in specified range
1916/// <tr><td> `VLines()` <td> Add vertical lines to y=0 at end points of curve
1917/// <tr><td> `Precision(double eps)` <td> Control precision of drawn curve w.r.t to scale of plot, default is 1e-3. A higher precision will
1918/// result in more and more densely spaced curve points. A negative precision value will disable
1919/// adaptive point spacing and restrict sampling to the grid point of points defined by the binning
1920/// of the plotted observable (recommended for expensive functions such as profile likelihoods)
1921/// <tr><td> `Invisible(bool flag)` <td> Add curve to frame, but do not display. Useful in combination AddTo()
1922/// <tr><td> `VisualizeError(const RooFitResult& fitres, double Z=1, bool linearMethod=true)`
1923/// <td> Visualize the uncertainty on the parameters, as given in fitres, at 'Z' sigma.
1924/// The linear method is fast but may not be accurate in the presence of strong correlations (~>0.9) and at Z>2 due to linear and Gaussian approximations made.
1925/// Intervals from the sampling method can be asymmetric, and may perform better in the presence of strong correlations, but may take (much) longer to calculate
1926/// \note To include the uncertainty from the expected number of events,
1927/// the Normalization() argument with `ScaleType` `RooAbsReal::RelativeExpected` has to be passed, e.g.
1928/// ```{.cpp}
1929/// pdf.plotOn(frame, VisualizeError(fitResult), Normalization(1.0, RooAbsReal::RelativeExpected));
1930/// ```
1931///
1932/// <tr><td> `VisualizeError(const RooFitResult& fitres, const RooArgSet& param, double Z=1, bool linearMethod=true)`
1933/// <td> Visualize the uncertainty on the subset of parameters 'param', as given in fitres, at 'Z' sigma
1934/// </table>
1935
1937{
1938
1939 // Pre-processing if p.d.f. contains a fit range and there is no command specifying one,
1940 // add a fit range as default range
1941 std::unique_ptr<RooCmdArg> plotRange;
1942 std::unique_ptr<RooCmdArg> normRange2;
1943 if (getStringAttribute("fitrange") && !cmdList.FindObject("Range") &&
1944 !cmdList.FindObject("RangeWithName")) {
1945 plotRange.reset(static_cast<RooCmdArg*>(RooFit::Range(getStringAttribute("fitrange")).Clone()));
1946 cmdList.Add(plotRange.get());
1947 }
1948
1949 if (getStringAttribute("fitrange") && !cmdList.FindObject("NormRange")) {
1950 normRange2.reset(static_cast<RooCmdArg*>(RooFit::NormRange(getStringAttribute("fitrange")).Clone()));
1951 cmdList.Add(normRange2.get());
1952 }
1953
1954 if (plotRange || normRange2) {
1955 coutI(Plotting) << "RooAbsPdf::plotOn(" << GetName() << ") p.d.f was fitted in a subrange and no explicit "
1956 << (plotRange?"Range()":"") << ((plotRange&&normRange2)?" and ":"")
1957 << (normRange2?"NormRange()":"") << " was specified. Plotting / normalising in fit range. To override, do one of the following"
1958 << "\n\t- Clear the automatic fit range attribute: <pdf>.removeStringAttribute(\"fitrange\");"
1959 << "\n\t- Explicitly specify the plotting range: Range(\"<rangeName>\")."
1960 << "\n\t- Explicitly specify where to compute the normalisation: NormRange(\"<rangeName>\")."
1961 << "\n\tThe default (full) range can be denoted with Range(\"\") / NormRange(\"\")."<< endl ;
1962 }
1963
1964 // Sanity checks
1965 if (plotSanityChecks(frame)) return frame ;
1966
1967 // Select the pdf-specific commands
1968 RooCmdConfig pc("RooAbsPdf::plotOn(" + std::string(GetName()) + ")");
1969 pc.defineDouble("scaleFactor","Normalization",0,1.0) ;
1970 pc.defineInt("scaleType","Normalization",0,Relative) ;
1971 pc.defineSet("compSet","SelectCompSet",0) ;
1972 pc.defineString("compSpec","SelectCompSpec",0) ;
1973 pc.defineObject("asymCat","Asymmetry",0) ;
1974 pc.defineDouble("rangeLo","Range",0,-999.) ;
1975 pc.defineDouble("rangeHi","Range",1,-999.) ;
1976 pc.defineString("rangeName","RangeWithName",0,"") ;
1977 pc.defineString("normRangeName","NormRange",0,"") ;
1978 pc.defineInt("rangeAdjustNorm","Range",0,0) ;
1979 pc.defineInt("rangeWNAdjustNorm","RangeWithName",0,0) ;
1980 pc.defineMutex("SelectCompSet","SelectCompSpec") ;
1981 pc.defineMutex("Range","RangeWithName") ;
1982 pc.allowUndefined() ; // unknowns may be handled by RooAbsReal
1983
1984 // Process and check varargs
1985 pc.process(cmdList) ;
1986 if (!pc.ok(true)) {
1987 return frame ;
1988 }
1989
1990 // Decode command line arguments
1991 ScaleType stype = (ScaleType) pc.getInt("scaleType") ;
1992 double scaleFactor = pc.getDouble("scaleFactor") ;
1993 const RooAbsCategoryLValue* asymCat = static_cast<const RooAbsCategoryLValue*>(pc.getObject("asymCat")) ;
1994 const char* compSpec = pc.getString("compSpec") ;
1995 const RooArgSet* compSet = pc.getSet("compSet");
1996 bool haveCompSel = ( (compSpec && strlen(compSpec)>0) || compSet) ;
1997
1998 // Suffix for curve name
1999 std::string nameSuffix ;
2000 if (compSpec && strlen(compSpec)>0) {
2001 nameSuffix.append("_Comp[") ;
2002 nameSuffix.append(compSpec) ;
2003 nameSuffix.append("]") ;
2004 } else if (compSet) {
2005 nameSuffix += "_Comp[" + compSet->contentsString() + "]";
2006 }
2007
2008 // Remove PDF-only commands from command list
2009 RooCmdConfig::stripCmdList(cmdList,"SelectCompSet,SelectCompSpec") ;
2010
2011 // Adjust normalization, if so requested
2012 if (asymCat) {
2013 RooCmdArg cnsuffix("CurveNameSuffix",0,0,0,0,nameSuffix.c_str(),nullptr,nullptr,nullptr) ;
2014 cmdList.Add(&cnsuffix);
2015 return RooAbsReal::plotOn(frame,cmdList) ;
2016 }
2017
2018 // More sanity checks
2019 double nExpected(1) ;
2020 if (stype==RelativeExpected) {
2021 if (!canBeExtended()) {
2022 coutE(Plotting) << "RooAbsPdf::plotOn(" << GetName()
2023 << "): ERROR the 'Expected' scale option can only be used on extendable PDFs" << endl ;
2024 return frame ;
2025 }
2026 frame->updateNormVars(*frame->getPlotVar()) ;
2027 nExpected = expectedEvents(frame->getNormVars()) ;
2028 }
2029
2030 if (stype != Raw) {
2031
2032 if (frame->getFitRangeNEvt() && stype==Relative) {
2033
2034 bool hasCustomRange(false);
2035 bool adjustNorm(false);
2036
2037 std::vector<pair<double,double> > rangeLim;
2038
2039 // Retrieve plot range to be able to adjust normalization to data
2040 if (pc.hasProcessed("Range")) {
2041
2042 double rangeLo = pc.getDouble("rangeLo") ;
2043 double rangeHi = pc.getDouble("rangeHi") ;
2044 rangeLim.push_back(make_pair(rangeLo,rangeHi)) ;
2045 adjustNorm = pc.getInt("rangeAdjustNorm") ;
2046 hasCustomRange = true ;
2047
2048 coutI(Plotting) << "RooAbsPdf::plotOn(" << GetName() << ") only plotting range ["
2049 << rangeLo << "," << rangeHi << "]" ;
2050 if (!pc.hasProcessed("NormRange")) {
2051 ccoutI(Plotting) << ", curve is normalized to data in " << (adjustNorm?"given":"full") << " range" << endl ;
2052 } else {
2053 ccoutI(Plotting) << endl ;
2054 }
2055
2056 nameSuffix.append(Form("_Range[%f_%f]",rangeLo,rangeHi)) ;
2057
2058 } else if (pc.hasProcessed("RangeWithName")) {
2059
2060 for (const std::string& rangeNameToken : ROOT::Split(pc.getString("rangeName", "", false), ",")) {
2061 const char* thisRangeName = rangeNameToken.empty() ? nullptr : rangeNameToken.c_str();
2062 if (thisRangeName && !frame->getPlotVar()->hasRange(thisRangeName)) {
2063 coutE(Plotting) << "Range '" << rangeNameToken << "' not defined for variable '"
2064 << frame->getPlotVar()->GetName() << "'. Ignoring ..." << std::endl;
2065 continue;
2066 }
2067 rangeLim.push_back(frame->getPlotVar()->getRange(thisRangeName));
2068 }
2069 adjustNorm = pc.getInt("rangeWNAdjustNorm") ;
2070 hasCustomRange = true ;
2071
2072 coutI(Plotting) << "RooAbsPdf::plotOn(" << GetName() << ") only plotting range '" << pc.getString("rangeName", "", false) << "'" ;
2073 if (!pc.hasProcessed("NormRange")) {
2074 ccoutI(Plotting) << ", curve is normalized to data in " << (adjustNorm?"given":"full") << " range" << endl ;
2075 } else {
2076 ccoutI(Plotting) << endl ;
2077 }
2078
2079 nameSuffix.append("_Range[" + std::string(pc.getString("rangeName")) + "]");
2080 }
2081 // Specification of a normalization range override those in a regular range
2082 if (pc.hasProcessed("NormRange")) {
2083 rangeLim.clear();
2084 for (const auto& rangeNameToken : ROOT::Split(pc.getString("normRangeName", "", false), ",")) {
2085 const char* thisRangeName = rangeNameToken.empty() ? nullptr : rangeNameToken.c_str();
2086 if (thisRangeName && !frame->getPlotVar()->hasRange(thisRangeName)) {
2087 coutE(Plotting) << "Range '" << rangeNameToken << "' not defined for variable '"
2088 << frame->getPlotVar()->GetName() << "'. Ignoring ..." << std::endl;
2089 continue;
2090 }
2091 rangeLim.push_back(frame->getPlotVar()->getRange(thisRangeName));
2092 }
2093 adjustNorm = true ;
2094 hasCustomRange = true ;
2095 coutI(Plotting) << "RooAbsPdf::plotOn(" << GetName() << ") p.d.f. curve is normalized using explicit choice of ranges '" << pc.getString("normRangeName", "", false) << "'" << endl ;
2096
2097 nameSuffix.append("_NormRange[" + std::string(pc.getString("rangeName")) + "]");
2098
2099 }
2100
2101 if (hasCustomRange && adjustNorm) {
2102 // If overlapping ranges were given, remove them now
2103 const std::size_t oldSize = rangeLim.size();
2104 removeRangeOverlap(rangeLim);
2105
2106 if (oldSize != rangeLim.size() && !pc.hasProcessed("NormRange")) {
2107 // User gave overlapping ranges. This leads to double-counting events and integrals, and must
2108 // therefore be avoided. If a NormRange has been given, the overlap is already gone.
2109 // It's safe to plot even with overlap now.
2110 coutE(Plotting) << "Requested plot/integration ranges overlap. For correct plotting, new ranges "
2111 "will be defined." << std::endl;
2112 auto plotVar = dynamic_cast<RooRealVar*>(frame->getPlotVar());
2113 assert(plotVar);
2114 std::string rangesNoOverlap;
2115 for (auto it = rangeLim.begin(); it != rangeLim.end(); ++it) {
2116 std::stringstream rangeName;
2117 rangeName << "Remove_overlap_range_" << it - rangeLim.begin();
2118 plotVar->setRange(rangeName.str().c_str(), it->first, it->second);
2119 if (!rangesNoOverlap.empty())
2120 rangesNoOverlap += ",";
2121 rangesNoOverlap += rangeName.str();
2122 }
2123
2124 auto rangeArg = static_cast<RooCmdArg*>(cmdList.FindObject("RangeWithName"));
2125 if (rangeArg) {
2126 rangeArg->setString(0, rangesNoOverlap.c_str());
2127 } else {
2128 plotRange = std::make_unique<RooCmdArg>(RooFit::Range(rangesNoOverlap.c_str()));
2129 cmdList.Add(plotRange.get());
2130 }
2131 }
2132
2133 double rangeNevt(0) ;
2134 for (const auto& riter : rangeLim) {
2135 double nevt= frame->getFitRangeNEvt(riter.first, riter.second);
2136 rangeNevt += nevt ;
2137 }
2138
2139 scaleFactor *= rangeNevt/nExpected ;
2140
2141 } else {
2142 scaleFactor *= frame->getFitRangeNEvt()/nExpected ;
2143 }
2144 } else if (stype==RelativeExpected) {
2145 scaleFactor *= nExpected ;
2146 } else if (stype==NumEvent) {
2147 scaleFactor /= nExpected ;
2148 }
2149 scaleFactor *= frame->getFitRangeBinW() ;
2150 }
2151 frame->updateNormVars(*frame->getPlotVar()) ;
2152
2153 // Append overriding scale factor command at end of original command list
2154 RooCmdArg tmp = RooFit::Normalization(scaleFactor,Raw) ;
2155 tmp.setInt(1,1) ; // Flag this normalization command as created for internal use (so that VisualizeError can strip it)
2156 cmdList.Add(&tmp) ;
2157
2158 // Was a component selected requested
2159 if (haveCompSel) {
2160
2161 // Get complete set of tree branch nodes
2162 RooArgSet branchNodeSet ;
2163 branchNodeServerList(&branchNodeSet) ;
2164
2165 // Discard any non-RooAbsReal nodes
2166 for (const auto arg : branchNodeSet) {
2167 if (!dynamic_cast<RooAbsReal*>(arg)) {
2168 branchNodeSet.remove(*arg) ;
2169 }
2170 }
2171
2172 // Obtain direct selection
2173 std::unique_ptr<RooArgSet> dirSelNodes;
2174 if (compSet) {
2175 dirSelNodes.reset(static_cast<RooArgSet*>(branchNodeSet.selectCommon(*compSet)));
2176 } else {
2177 dirSelNodes.reset(static_cast<RooArgSet*>(branchNodeSet.selectByName(compSpec)));
2178 }
2179 if (!dirSelNodes->empty()) {
2180 coutI(Plotting) << "RooAbsPdf::plotOn(" << GetName() << ") directly selected PDF components: " << *dirSelNodes << endl ;
2181
2182 // Do indirect selection and activate both
2183 plotOnCompSelect(dirSelNodes.get());
2184 } else {
2185 if (compSet) {
2186 coutE(Plotting) << "RooAbsPdf::plotOn(" << GetName() << ") ERROR: component selection set " << *compSet << " does not match any components of p.d.f." << endl ;
2187 } else {
2188 coutE(Plotting) << "RooAbsPdf::plotOn(" << GetName() << ") ERROR: component selection expression '" << compSpec << "' does not select any components of p.d.f." << endl ;
2189 }
2190 return nullptr ;
2191 }
2192 }
2193
2194
2195 RooCmdArg cnsuffix("CurveNameSuffix",0,0,0,0,nameSuffix.c_str(),nullptr,nullptr,nullptr) ;
2196 cmdList.Add(&cnsuffix);
2197
2198 RooPlot* ret = RooAbsReal::plotOn(frame,cmdList) ;
2199
2200 // Restore selection status ;
2201 if (haveCompSel) plotOnCompSelect(nullptr) ;
2202
2203 return ret ;
2204}
2205
2206
2207//_____________________________________________________________________________
2208/// Plot oneself on 'frame'. In addition to features detailed in RooAbsReal::plotOn(),
2209/// the scale factor for a PDF can be interpreted in three different ways. The interpretation
2210/// is controlled by ScaleType
2211/// ```
2212/// Relative - Scale factor is applied on top of PDF normalization scale factor
2213/// NumEvent - Scale factor is interpreted as a number of events. The surface area
2214/// under the PDF curve will match that of a histogram containing the specified
2215/// number of event
2216/// Raw - Scale factor is applied to the raw (projected) probability density.
2217/// Not too useful, option provided for completeness.
2218/// ```
2219// coverity[PASS_BY_VALUE]
2221{
2222
2223 // Sanity checks
2224 if (plotSanityChecks(frame)) return frame ;
2225
2226 // More sanity checks
2227 double nExpected(1) ;
2228 if (o.stype==RelativeExpected) {
2229 if (!canBeExtended()) {
2230 coutE(Plotting) << "RooAbsPdf::plotOn(" << GetName()
2231 << "): ERROR the 'Expected' scale option can only be used on extendable PDFs" << endl ;
2232 return frame ;
2233 }
2234 frame->updateNormVars(*frame->getPlotVar()) ;
2235 nExpected = expectedEvents(frame->getNormVars()) ;
2236 }
2237
2238 // Adjust normalization, if so requested
2239 if (o.stype != Raw) {
2240
2241 if (frame->getFitRangeNEvt() && o.stype==Relative) {
2242 // If non-default plotting range is specified, adjust number of events in fit range
2243 o.scaleFactor *= frame->getFitRangeNEvt()/nExpected ;
2244 } else if (o.stype==RelativeExpected) {
2245 o.scaleFactor *= nExpected ;
2246 } else if (o.stype==NumEvent) {
2247 o.scaleFactor /= nExpected ;
2248 }
2249 o.scaleFactor *= frame->getFitRangeBinW() ;
2250 }
2251 frame->updateNormVars(*frame->getPlotVar()) ;
2252
2253 return RooAbsReal::plotOn(frame,o) ;
2254}
2255
2256
2257
2258
2259////////////////////////////////////////////////////////////////////////////////
2260/// The following named arguments are supported
2261/// <table>
2262/// <tr><th> Type of CmdArg <th> Effect on parameter box
2263/// <tr><td> `Parameters(const RooArgSet& param)` <td> Only the specified subset of parameters will be shown. By default all non-constant parameters are shown.
2264/// <tr><td> `ShowConstants(bool flag)` <td> Also display constant parameters
2265/// <tr><td> `Format(const char* what,...)` <td> Parameter formatting options.
2266/// | Parameter | Format
2267/// | ---------------------- | --------------------------
2268/// | `const char* what` | Controls what is shown. "N" adds name (alternatively, "T" adds the title), "E" adds error, "A" shows asymmetric error, "U" shows unit, "H" hides the value
2269/// | `FixedPrecision(int n)`| Controls precision, set fixed number of digits
2270/// | `AutoPrecision(int n)` | Controls precision. Number of shown digits is calculated from error + n specified additional digits (1 is sensible default)
2271/// <tr><td> `Label(const chat* label)` <td> Add label to parameter box. Use `\n` for multi-line labels.
2272/// <tr><td> `Layout(double xmin, double xmax, double ymax)` <td> Specify relative position of left/right side of box and top of box.
2273/// Coordinates are given as position on the pad between 0 and 1.
2274/// The lower end of the box is calculated automatically from the number of lines in the box.
2275/// </table>
2276///
2277///
2278/// Example use:
2279/// ```
2280/// pdf.paramOn(frame, Label("fit result"), Format("NEU",AutoPrecision(1)) ) ;
2281/// ```
2282///
2283
2284RooPlot* RooAbsPdf::paramOn(RooPlot* frame, const RooCmdArg& arg1, const RooCmdArg& arg2,
2285 const RooCmdArg& arg3, const RooCmdArg& arg4, const RooCmdArg& arg5,
2286 const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8)
2287{
2288 // Stuff all arguments in a list
2289 RooLinkedList cmdList;
2290 cmdList.Add(const_cast<RooCmdArg*>(&arg1)) ; cmdList.Add(const_cast<RooCmdArg*>(&arg2)) ;
2291 cmdList.Add(const_cast<RooCmdArg*>(&arg3)) ; cmdList.Add(const_cast<RooCmdArg*>(&arg4)) ;
2292 cmdList.Add(const_cast<RooCmdArg*>(&arg5)) ; cmdList.Add(const_cast<RooCmdArg*>(&arg6)) ;
2293 cmdList.Add(const_cast<RooCmdArg*>(&arg7)) ; cmdList.Add(const_cast<RooCmdArg*>(&arg8)) ;
2294
2295 // Select the pdf-specific commands
2296 RooCmdConfig pc("RooAbsPdf::paramOn(" + std::string(GetName()) + ")");
2297 pc.defineString("label","Label",0,"") ;
2298 pc.defineDouble("xmin","Layout",0,0.65) ;
2299 pc.defineDouble("xmax","Layout",1,0.9) ;
2300 pc.defineInt("ymaxi","Layout",0,Int_t(0.9*10000)) ;
2301 pc.defineInt("showc","ShowConstants",0,0) ;
2302 pc.defineSet("params","Parameters",0,nullptr) ;
2303 pc.defineInt("dummy","FormatArgs",0,0) ;
2304
2305 // Process and check varargs
2306 pc.process(cmdList) ;
2307 if (!pc.ok(true)) {
2308 return frame ;
2309 }
2310
2311 auto formatCmd = static_cast<RooCmdArg const*>(cmdList.FindObject("FormatArgs")) ;
2312
2313 const char* label = pc.getString("label") ;
2314 double xmin = pc.getDouble("xmin") ;
2315 double xmax = pc.getDouble("xmax") ;
2316 double ymax = pc.getInt("ymaxi") / 10000. ;
2317 int showc = pc.getInt("showc") ;
2318
2319 // Decode command line arguments
2320 std::unique_ptr<RooArgSet> params{getParameters(frame->getNormVars())} ;
2321 if(RooArgSet* requestedParams = pc.getSet("params")) {
2322 params = std::unique_ptr<RooArgSet>{static_cast<RooArgSet*>(params->selectCommon(*requestedParams))};
2323 }
2324 paramOn(frame,*params,showc,label,xmin,xmax,ymax,formatCmd);
2325
2326 return frame ;
2327}
2328
2329
2330////////////////////////////////////////////////////////////////////////////////
2331/// Add a text box with the current parameter values and their errors to the frame.
2332/// Observables of this PDF appearing in the 'data' dataset will be omitted.
2333///
2334/// An optional label will be inserted if passed. Multi-line labels can be generated
2335/// by adding `\n` to the label string. Use 'sigDigits'
2336/// to modify the default number of significant digits printed. The 'xmin,xmax,ymax'
2337/// values specify the initial relative position of the text box in the plot frame.
2338
2339RooPlot* RooAbsPdf::paramOn(RooPlot* frame, const RooArgSet& params, bool showConstants, const char *label,
2340 double xmin, double xmax ,double ymax, const RooCmdArg* formatCmd)
2341{
2342
2343 // parse the options
2344 bool showLabel= (label != nullptr && strlen(label) > 0);
2345
2346 // calculate the box's size, adjusting for constant parameters
2347
2348 double ymin(ymax);
2349 double dy(0.06);
2350 for (const auto param : params) {
2351 auto var = static_cast<RooRealVar*>(param);
2352 if(showConstants || !var->isConstant()) ymin-= dy;
2353 }
2354
2355 std::string labelString = label;
2356 unsigned int numLines = std::count(labelString.begin(), labelString.end(), '\n') + 1;
2357 if (showLabel) ymin -= numLines * dy;
2358
2359 // create the box and set its options
2360 TPaveText *box= new TPaveText(xmin,ymax,xmax,ymin,"BRNDC");
2361 if(!box) return nullptr;
2362 box->SetName((std::string(GetName()) + "_paramBox").c_str());
2363 box->SetFillColor(0);
2364 box->SetBorderSize(0);
2365 box->SetTextAlign(12);
2366 box->SetTextSize(0.04F);
2367 box->SetFillStyle(0);
2368
2369 for (const auto param : params) {
2370 auto var = static_cast<const RooRealVar*>(param);
2371 if(var->isConstant() && !showConstants) continue;
2372
2373 std::unique_ptr<TString> formatted{formatCmd ? var->format(*formatCmd) : var->format(2, "NELU")};
2374 box->AddText(formatted->Data());
2375 }
2376
2377 // add the optional label if specified
2378 if (showLabel) {
2379 for (const auto& line : ROOT::Split(label, "\n")) {
2380 box->AddText(line.c_str());
2381 }
2382 }
2383
2384 // Add box to frame
2385 frame->addObject(box) ;
2386
2387 return frame ;
2388}
2389
2390
2391
2392
2393////////////////////////////////////////////////////////////////////////////////
2394/// Return expected number of events from this p.d.f for use in extended
2395/// likelihood calculations. This default implementation returns zero
2396
2398{
2399 return 0 ;
2400}
2401
2402
2403
2404////////////////////////////////////////////////////////////////////////////////
2405/// Change global level of verbosity for p.d.f. evaluations
2406
2408{
2409 _verboseEval = stat ;
2410}
2411
2412
2413
2414////////////////////////////////////////////////////////////////////////////////
2415/// Return global level of verbosity for p.d.f. evaluations
2416
2418{
2419 return _verboseEval ;
2420}
2421
2422
2423
2424////////////////////////////////////////////////////////////////////////////////
2425/// Destructor of normalization cache element. If this element
2426/// provides the 'current' normalization stored in RooAbsPdf::_norm
2427/// zero _norm pointer here before object pointed to is deleted here
2428
2430{
2431 // Zero _norm pointer in RooAbsPdf if it is points to our cache payload
2432 if (_owner) {
2433 RooAbsPdf* pdfOwner = static_cast<RooAbsPdf*>(_owner) ;
2434 if (pdfOwner->_norm == _norm) {
2435 pdfOwner->_norm = nullptr ;
2436 }
2437 }
2438
2439 delete _norm ;
2440}
2441
2442
2443
2444////////////////////////////////////////////////////////////////////////////////
2445/// Return a p.d.f that represent a projection of this p.d.f integrated over given observables
2446
2448{
2449 // Construct name for new object
2450 std::string name(GetName()) ;
2451 name.append("_Proj[") ;
2452 if (!iset.empty()) {
2453 bool first = true;
2454 for(auto const& arg : iset) {
2455 if (first) {
2456 first = false ;
2457 } else {
2458 name.append(",") ;
2459 }
2460 name.append(arg->GetName()) ;
2461 }
2462 }
2463 name.append("]") ;
2464
2465 // Return projected p.d.f.
2466 return new RooProjectedPdf(name.c_str(),name.c_str(),*this,iset) ;
2467}
2468
2469
2470
2471////////////////////////////////////////////////////////////////////////////////
2472/// Create a cumulative distribution function of this p.d.f in terms
2473/// of the observables listed in iset. If no nset argument is given
2474/// the c.d.f normalization is constructed over the integrated
2475/// observables, so that its maximum value is precisely 1. It is also
2476/// possible to choose a different normalization for
2477/// multi-dimensional p.d.f.s: eg. for a pdf f(x,y,z) one can
2478/// construct a partial cdf c(x,y) that only when integrated itself
2479/// over z results in a maximum value of 1. To construct such a cdf pass
2480/// z as argument to the optional nset argument
2481
2483{
2484 return createCdf(iset,RooFit::SupNormSet(nset)) ;
2485}
2486
2487
2488
2489////////////////////////////////////////////////////////////////////////////////
2490/// Create an object that represents the integral of the function over one or more observables listed in `iset`.
2491/// The actual integration calculation is only performed when the return object is evaluated. The name
2492/// of the integral object is automatically constructed from the name of the input function, the variables
2493/// it integrates and the range integrates over
2494///
2495/// The following named arguments are accepted
2496/// | Type of CmdArg | Effect on CDF
2497/// | ---------------------|-------------------
2498/// | SupNormSet(const RooArgSet&) | Observables over which should be normalized _in addition_ to the integration observables
2499/// | ScanNumCdf() | Apply scanning technique if cdf integral involves numeric integration [ default ]
2500/// | ScanAllCdf() | Always apply scanning technique
2501/// | ScanNoCdf() | Never apply scanning technique
2502/// | ScanParameters(Int_t nbins, Int_t intOrder) | Parameters for scanning technique of making CDF: number of sampled bins and order of interpolation applied on numeric cdf
2503
2505 const RooCmdArg& arg3, const RooCmdArg& arg4, const RooCmdArg& arg5,
2506 const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8)
2507{
2508 // Define configuration for this method
2509 RooCmdConfig pc("RooAbsReal::createCdf(" + std::string(GetName()) + ")");
2510 pc.defineSet("supNormSet","SupNormSet",0,nullptr) ;
2511 pc.defineInt("numScanBins","ScanParameters",0,1000) ;
2512 pc.defineInt("intOrder","ScanParameters",1,2) ;
2513 pc.defineInt("doScanNum","ScanNumCdf",0,1) ;
2514 pc.defineInt("doScanAll","ScanAllCdf",0,0) ;
2515 pc.defineInt("doScanNon","ScanNoCdf",0,0) ;
2516 pc.defineMutex("ScanNumCdf","ScanAllCdf","ScanNoCdf") ;
2517
2518 // Process & check varargs
2519 pc.process(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) ;
2520 if (!pc.ok(true)) {
2521 return nullptr ;
2522 }
2523
2524 // Extract values from named arguments
2525 const RooArgSet* snset = pc.getSet("supNormSet",nullptr);
2526 RooArgSet nset ;
2527 if (snset) {
2528 nset.add(*snset) ;
2529 }
2530 Int_t numScanBins = pc.getInt("numScanBins") ;
2531 Int_t intOrder = pc.getInt("intOrder") ;
2532 Int_t doScanNum = pc.getInt("doScanNum") ;
2533 Int_t doScanAll = pc.getInt("doScanAll") ;
2534 Int_t doScanNon = pc.getInt("doScanNon") ;
2535
2536 // If scanning technique is not requested make integral-based cdf and return
2537 if (doScanNon) {
2538 return createIntRI(iset,nset) ;
2539 }
2540 if (doScanAll) {
2541 return createScanCdf(iset,nset,numScanBins,intOrder) ;
2542 }
2543 if (doScanNum) {
2544 std::unique_ptr<RooAbsReal> tmp{createIntegral(iset)} ;
2545 Int_t isNum= !static_cast<RooRealIntegral&>(*tmp).numIntRealVars().empty();
2546
2547 if (isNum) {
2548 coutI(NumIntegration) << "RooAbsPdf::createCdf(" << GetName() << ") integration over observable(s) " << iset << " involves numeric integration," << endl
2549 << " constructing cdf though numeric integration of sampled pdf in " << numScanBins << " bins and applying order "
2550 << intOrder << " interpolation on integrated histogram." << endl
2551 << " To override this choice of technique use argument ScanNone(), to change scan parameters use ScanParameters(nbins,order) argument" << endl ;
2552 }
2553
2554 return isNum ? createScanCdf(iset,nset,numScanBins,intOrder) : createIntRI(iset,nset) ;
2555 }
2556 return nullptr ;
2557}
2558
2560{
2561 string name = string(GetName()) + "_NUMCDF_" + integralNameSuffix(iset,&nset).Data() ;
2562 RooRealVar* ivar = static_cast<RooRealVar*>(iset.first()) ;
2563 ivar->setBins(numScanBins,"numcdf") ;
2564 auto ret = std::make_unique<RooNumCdf>(name.c_str(),name.c_str(),*this,*ivar,"numcdf");
2565 ret->setInterpolationOrder(intOrder) ;
2566 return RooFit::makeOwningPtr<RooAbsReal>(std::move(ret));
2567}
2568
2569
2570
2571
2572////////////////////////////////////////////////////////////////////////////////
2573/// This helper function finds and collects all constraints terms of all component p.d.f.s
2574/// and returns a RooArgSet with all those terms.
2575
2576RooArgSet* RooAbsPdf::getAllConstraints(const RooArgSet& observables, RooArgSet& constrainedParams,
2577 bool stripDisconnected, bool removeConstraintsFromPdf) const
2578{
2579 RooArgSet* ret = new RooArgSet("AllConstraints") ;
2580
2581 std::unique_ptr<RooArgSet> comps(getComponents());
2582 for (const auto arg : *comps) {
2583 auto pdf = dynamic_cast<const RooAbsPdf*>(arg) ;
2584 if (pdf && !ret->find(pdf->GetName())) {
2585 std::unique_ptr<RooArgSet> compRet(
2586 pdf->getConstraints(observables,constrainedParams,stripDisconnected,removeConstraintsFromPdf));
2587 if (compRet) {
2588 ret->add(*compRet,false) ;
2589 }
2590 }
2591 }
2592
2593 return ret ;
2594}
2595
2596
2597////////////////////////////////////////////////////////////////////////////////
2598/// Returns the default numeric MC generator configuration for all RooAbsReals
2599
2601{
2603}
2604
2605
2606////////////////////////////////////////////////////////////////////////////////
2607/// Returns the specialized integrator configuration for _this_ RooAbsReal.
2608/// If this object has no specialized configuration, a null pointer is returned
2609
2611{
2612 return _specGeneratorConfig.get();
2613}
2614
2615
2616
2617////////////////////////////////////////////////////////////////////////////////
2618/// Returns the specialized integrator configuration for _this_ RooAbsReal.
2619/// If this object has no specialized configuration, a null pointer is returned,
2620/// unless createOnTheFly is true in which case a clone of the default integrator
2621/// configuration is created, installed as specialized configuration, and returned
2622
2624{
2625 if (!_specGeneratorConfig && createOnTheFly) {
2626 _specGeneratorConfig = std::make_unique<RooNumGenConfig>(*defaultGeneratorConfig()) ;
2627 }
2628 return _specGeneratorConfig.get();
2629}
2630
2631
2632
2633////////////////////////////////////////////////////////////////////////////////
2634/// Return the numeric MC generator configuration used for this object. If
2635/// a specialized configuration was associated with this object, that configuration
2636/// is returned, otherwise the default configuration for all RooAbsReals is returned
2637
2639{
2640 const RooNumGenConfig* config = specialGeneratorConfig() ;
2641 if (config) return config ;
2642 return defaultGeneratorConfig() ;
2643}
2644
2645
2646
2647////////////////////////////////////////////////////////////////////////////////
2648/// Set the given configuration as default numeric MC generator
2649/// configuration for this object
2650
2652{
2653 _specGeneratorConfig = std::make_unique<RooNumGenConfig>(config);
2654}
2655
2656
2657
2658////////////////////////////////////////////////////////////////////////////////
2659/// Remove the specialized numeric MC generator configuration associated
2660/// with this object
2661
2663{
2664 _specGeneratorConfig.reset();
2665}
2666
2667
2668
2669////////////////////////////////////////////////////////////////////////////////
2670
2672{
2673 delete _genContext ;
2674}
2675
2676
2677////////////////////////////////////////////////////////////////////////////////
2678
2679RooAbsPdf::GenSpec::GenSpec(RooAbsGenContext* context, const RooArgSet& whatVars, RooDataSet* protoData, Int_t nGen,
2680 bool extended, bool randProto, bool resampleProto, TString dsetName, bool init) :
2681 _genContext(context), _whatVars(whatVars), _protoData(protoData), _nGen(nGen), _extended(extended),
2682 _randProto(randProto), _resampleProto(resampleProto), _dsetName(dsetName), _init(init)
2683{
2684}
2685
2686
2687namespace {
2688
2689void sterilizeClientCaches(RooAbsArg & arg) {
2690 auto const& clients = arg.clients();
2691 for(std::size_t iClient = 0; iClient < clients.size(); ++iClient) {
2692
2693 const std::size_t oldClientsSize = clients.size();
2694 RooAbsArg* client = clients[iClient];
2695
2696 for(int iCache = 0; iCache < client->numCaches(); ++iCache) {
2697 if(auto cacheMgr = dynamic_cast<RooObjCacheManager*>(client->getCache(iCache))) {
2698 cacheMgr->sterilize();
2699 }
2700 }
2701
2702 // It can happen that the objects cached by the client are also clients of
2703 // the arg itself! In that case, the position of the client in the client
2704 // list might have changed, and we need to find the new index.
2705 if(clients.size() != oldClientsSize) {
2706 auto clientIter = std::find(clients.begin(), clients.end(), client);
2707 if(clientIter == clients.end()) {
2708 throw std::runtime_error("After a clients caches were cleared, the client was gone! This should not happen.");
2709 }
2710 iClient = std::distance(clients.begin(), clientIter);
2711 }
2712 }
2713}
2714
2715} // namespace
2716
2717
2718////////////////////////////////////////////////////////////////////////////////
2719
2720void RooAbsPdf::setNormRange(const char* rangeName)
2721{
2722 if (rangeName) {
2723 _normRange = rangeName ;
2724 } else {
2725 _normRange.Clear() ;
2726 }
2727
2728 // the stuff that the clients have cached may depend on the normalization range
2729 sterilizeClientCaches(*this);
2730
2731 if (_norm) {
2733 _norm = nullptr ;
2734 }
2735}
2736
2737
2738////////////////////////////////////////////////////////////////////////////////
2739
2740void RooAbsPdf::setNormRangeOverride(const char* rangeName)
2741{
2742 if (rangeName) {
2743 _normRangeOverride = rangeName ;
2744 } else {
2746 }
2747
2748 // the stuff that the clients have cached may depend on the normalization range
2749 sterilizeClientCaches(*this);
2750
2751 if (_norm) {
2753 _norm = nullptr ;
2754 }
2755}
2756
2757
2758////////////////////////////////////////////////////////////////////////////////
2759/// Hook function intercepting redirectServer calls. Discard current
2760/// normalization object if any server is redirected
2761
2762bool RooAbsPdf::redirectServersHook(const RooAbsCollection & newServerList, bool mustReplaceAll,
2763 bool nameChange, bool isRecursiveStep)
2764{
2765 // If servers are redirected, the cached normalization integrals and
2766 // normalization sets are most likely invalid.
2768
2769 // Object is own by _normCacheManager that will delete object as soon as cache
2770 // is sterilized by server redirect
2771 _norm = nullptr ;
2772
2773 // Similar to the situation with the normalization integral above: if a
2774 // server is redirected, the cached normalization set might not point to
2775 // the right observables anymore. We need to reset it.
2776 setActiveNormSet(nullptr);
2777 return RooAbsReal::redirectServersHook(newServerList, mustReplaceAll, nameChange, isRecursiveStep);
2778}
2779
2780
2781std::unique_ptr<RooAbsArg>
2783{
2784 if (normSet.empty() || selfNormalized()) {
2785 return RooAbsReal::compileForNormSet(normSet, ctx);
2786 }
2787 std::unique_ptr<RooAbsPdf> pdfClone(static_cast<RooAbsPdf *>(this->Clone()));
2788 ctx.compileServers(*pdfClone, normSet);
2789
2790 auto newArg = std::make_unique<RooNormalizedPdf>(*pdfClone, normSet);
2791
2792 // The direct servers are this pdf and the normalization integral, which
2793 // don't need to be compiled further.
2794 for (RooAbsArg *server : newArg->servers()) {
2795 ctx.markAsCompiled(*server);
2796 }
2797 ctx.markAsCompiled(*newArg);
2798 newArg->addOwnedComponents(std::move(pdfClone));
2799 return newArg;
2800}
2801
2802/// Returns an object that represents the expected number of events for a given
2803/// normalization set, similar to how createIntegral() returns an object that
2804/// returns the integral. This is used to build the computation graph for the
2805/// final likelihood.
2806std::unique_ptr<RooAbsReal> RooAbsPdf::createExpectedEventsFunc(const RooArgSet * /*nset*/) const
2807{
2808 std::stringstream errMsg;
2809 errMsg << "The pdf \"" << GetName() << "\" of type " << ClassName()
2810 << " did not overload RooAbsPdf::createExpectedEventsFunc()!";
2811 coutE(InputArguments) << errMsg.str() << std::endl;
2812 return nullptr;
2813}
#define e(i)
Definition RSha256.hxx:103
bool _init
! Is object initialized
#define coutI(a)
#define cxcoutI(a)
#define cxcoutD(a)
#define coutP(a)
#define oocoutW(o, a)
#define coutW(a)
#define coutE(a)
#define ccoutI(a)
#define ccoutD(a)
bool _extended
Definition RooNLLVar.h:43
int Int_t
Definition RtypesCore.h:45
#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 input
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
char name[80]
Definition TGX11.cxx:110
float xmin
float ymin
float xmax
float ymax
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2489
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:77
void clearValueAndShapeDirty() const
Definition RooAbsArg.h:597
void Print(Option_t *options=nullptr) const override
Print the object to the defaultPrintStream().
Definition RooAbsArg.h:320
bool dependsOn(const RooAbsCollection &serverList, const RooAbsArg *ignoreArg=nullptr, bool valueOnly=false) const
Test whether we depend on (ie, are served by) any object in the specified collection.
void setOperMode(OperMode mode, bool recurseADirty=true)
Set the operation mode of this node.
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 addOwnedComponents(const RooAbsCollection &comps)
Take ownership of the contents of 'comps'.
const Text_t * getStringAttribute(const Text_t *key) const
Get string attribute mapped under key 'key'.
TIterator Use clients() and begin()
virtual std::unique_ptr< RooAbsArg > compileForNormSet(RooArgSet const &normSet, RooFit::Detail::CompileContext &ctx) const
RooFit::OwningPtr< RooArgSet > getComponents() const
Create a RooArgSet with all components (branch nodes) of the expression tree headed by this object.
bool getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
RooFit::OwningPtr< RooArgSet > getVariables(bool stripDisconnected=true) const
Return RooArgSet with all variables (tree leaf nodes of expression tree)
RooAbsCache * getCache(Int_t index) const
Return registered cache object by index.
bool isValueDirty() const
Definition RooAbsArg.h:419
void setProxyNormSet(const RooArgSet *nset)
Forward a change in the cached normalization argset to all the registered proxies.
void branchNodeServerList(RooAbsCollection *list, const RooAbsArg *arg=nullptr, bool recurseNonDerived=false) const
Fill supplied list with all branch nodes of the arg tree starting with ourself as top node.
TObject * Clone(const char *newname=nullptr) const override
Make a clone of an object using the Streamer facility.
Definition RooAbsArg.h:89
RefCountList_t _serverList
Definition RooAbsArg.h:632
Int_t numCaches() const
Return number of registered caches.
RooAbsArg * findServer(const char *name) const
Return server of this with name name. Returns nullptr if not found.
Definition RooAbsArg.h:210
OperMode operMode() const
Query the operation mode of this node.
Definition RooAbsArg.h:482
RooAbsArg * _owner
! Pointer to owning RooAbsArg
void setInterpolationOrder(Int_t order)
Set interpolation order of RooHistFunct representing cache histogram.
Abstract base class for objects that represent a discrete value that can be set from the outside,...
Abstract container object that can hold multiple RooAbsArg objects.
virtual bool remove(const RooAbsArg &var, bool silent=false, bool matchByNameOnly=false)
Remove the specified argument from our list.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
RooAbsArg * first() const
RooAbsCollection * selectByName(const char *nameList, bool verbose=false) const
Create a subset of the current collection, consisting only of those elements with names matching the ...
bool selectCommon(const RooAbsCollection &refColl, RooAbsCollection &outColl) const
Create a subset of the current collection, consisting only of those elements that are contained as we...
std::string contentsString() const
Return comma separated list of contained object names as STL string.
RooAbsArg * find(const char *name) const
Find object with given name in list.
void Print(Option_t *options=nullptr) const override
This method must be overridden when a class wants to print itself.
Abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:57
virtual Int_t numEntries() const
Return number of entries in dataset, i.e., count unweighted entries.
Abstract base class for generator contexts of RooAbsPdf objects.
virtual void setExpectedData(bool)
virtual RooDataSet * generate(double nEvents=0, bool skipInit=false, bool extendedMode=false)
Generate the specified number of events with nEvents>0 and and return a dataset containing the genera...
bool isValid() const
virtual void setProtoDataOrder(Int_t *lut)
Set the traversal order of prototype data to that in the lookup tables passed as argument.
Normalization set with for above integral.
Definition RooAbsPdf.h:323
~CacheElem() override
Destructor of normalization cache element.
RooAbsReal * _norm
Definition RooAbsPdf.h:328
RooArgSet _whatVars
Definition RooAbsPdf.h:84
RooAbsGenContext * _genContext
Definition RooAbsPdf.h:83
RooDataSet * _protoData
Definition RooAbsPdf.h:85
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:40
virtual bool syncNormalization(const RooArgSet *dset, bool adjustProxies=true) const
Verify that the normalization integral cached with this PDF is valid for given set of normalization o...
double getNorm(const RooArgSet &nset) const
Get normalisation term needed to normalise the raw values returned by getVal().
Definition RooAbsPdf.h:196
std::unique_ptr< RooAbsArg > compileForNormSet(RooArgSet const &normSet, RooFit::Detail::CompileContext &ctx) const override
RooObjCacheManager _normMgr
Definition RooAbsPdf.h:330
std::unique_ptr< RooNumGenConfig > _specGeneratorConfig
! MC generator configuration specific for this object
Definition RooAbsPdf.h:341
double getValV(const RooArgSet *set=nullptr) const override
Return current value, normalized by integrating over the observables in nset.
virtual std::unique_ptr< RooFitResult > fitToImpl(RooAbsData &data, const RooLinkedList &cmdList)
Protected implementation of the likelihood fitting routine.
virtual void generateEvent(Int_t code)
Interface for generation of an event using the algorithm corresponding to the specified code.
RooFit::OwningPtr< RooAbsReal > createScanCdf(const RooArgSet &iset, const RooArgSet &nset, Int_t numScanBins, Int_t intOrder)
void setGeneratorConfig()
Remove the specialized numeric MC generator configuration associated with this object.
virtual void resetErrorCounters(Int_t resetValue=10)
Reset error counter to given value, limiting the number of future error messages for this pdf to 'res...
static int verboseEval()
Return global level of verbosity for p.d.f. evaluations.
RooFit::OwningPtr< RooAbsReal > createCdf(const RooArgSet &iset, const RooArgSet &nset=RooArgSet())
Create a cumulative distribution function of this p.d.f in terms of the observables listed in iset.
bool isActiveNormSet(RooArgSet const *normSet) const
Checks if normSet is the currently active normalization set of this PDF, meaning is exactly the same ...
Definition RooAbsPdf.h:300
virtual double expectedEvents(const RooArgSet *nset) const
Return expected number of events to be used in calculation of extended likelihood.
virtual RooAbsGenContext * binnedGenContext(const RooArgSet &vars, bool verbose=false) const
Return a binned generator context.
TString _normRange
Normalization range.
Definition RooAbsPdf.h:343
virtual bool isDirectGenSafe(const RooAbsArg &arg) const
Check if given observable can be safely generated using the pdfs internal generator mechanism (if tha...
Int_t * randomizeProtoOrder(Int_t nProto, Int_t nGen, bool resample=false) const
Return lookup table with randomized order for nProto prototype events.
void setNormRange(const char *rangeName)
~RooAbsPdf() override
Destructor.
RooArgSet const * _normSet
Normalization integral (owned by _normMgr)
Definition RooAbsPdf.h:321
RooPlot * plotOn(RooPlot *frame, 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 RooCmdArg &arg9={}, const RooCmdArg &arg10={}) const override
Helper calling plotOn(RooPlot*, RooLinkedList&) const.
Definition RooAbsPdf.h:124
RooNumGenConfig * specialGeneratorConfig() const
Returns the specialized integrator configuration for this RooAbsReal.
virtual bool selfNormalized() const
Shows if a PDF is self-normalized, which means that no attempt is made to add a normalization term.
Definition RooAbsPdf.h:208
void printMultiline(std::ostream &os, Int_t contents, bool verbose=false, TString indent="") const override
Print multi line detailed information of this RooAbsPdf.
Int_t _traceCount
Number of traces remaining to print.
Definition RooAbsPdf.h:336
bool canBeExtended() const
If true, PDF can provide extended likelihood term.
Definition RooAbsPdf.h:219
RooAbsReal * _norm
Definition RooAbsPdf.h:320
void setTraceCounter(Int_t value, bool allNodes=false)
Reset trace counter to given value, limiting the number of future trace messages for this pdf to 'val...
GenSpec * prepareMultiGen(const RooArgSet &whatVars, const RooCmdArg &arg1={}, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={})
Prepare GenSpec configuration object for efficient generation of multiple datasets from identical spe...
Int_t _errorCount
Number of errors remaining to print.
Definition RooAbsPdf.h:335
@ CanNotBeExtended
Definition RooAbsPdf.h:213
virtual std::unique_ptr< RooAbsReal > createExpectedEventsFunc(const RooArgSet *nset) const
Returns an object that represents the expected number of events for a given normalization set,...
virtual RooPlot * paramOn(RooPlot *frame, const RooCmdArg &arg1={}, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={})
Add a box with parameter values (and errors) to the specified frame.
Int_t _negCount
Number of negative probabilities remaining to print.
Definition RooAbsPdf.h:337
RooFit::OwningPtr< RooDataSet > generate(const RooArgSet &whatVars, Int_t nEvents, const RooCmdArg &arg1, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={})
See RooAbsPdf::generate(const RooArgSet&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,...
Definition RooAbsPdf.h:57
virtual const RooAbsReal * getNormObj(const RooArgSet *set, const RooArgSet *iset, const TNamed *rangeName=nullptr) const
Return pointer to RooAbsReal object that implements calculation of integral over observables iset in ...
void setActiveNormSet(RooArgSet const *normSet) const
Setter for the _normSet member, which should never be set directly.
Definition RooAbsPdf.h:285
double analyticalIntegralWN(Int_t code, const RooArgSet *normSet, const char *rangeName=nullptr) const override
Analytical integral with normalization (see RooAbsReal::analyticalIntegralWN() for further informatio...
void setNormRangeOverride(const char *rangeName)
virtual RooFit::OwningPtr< RooDataSet > generateSimGlobal(const RooArgSet &whatVars, Int_t nEvents)
Special generator interface for generation of 'global observables' – for RooStats tools.
double normalizeWithNaNPacking(double rawVal, double normVal) const
virtual RooAbsGenContext * autoGenContext(const RooArgSet &vars, const RooDataSet *prototype=nullptr, const RooArgSet *auxProto=nullptr, bool verbose=false, bool autoBinned=true, const char *binnedTag="") const
RooArgSet * getAllConstraints(const RooArgSet &observables, RooArgSet &constrainedParams, bool stripDisconnected=true, bool removeConstraintsFromPdf=false) const
This helper function finds and collects all constraints terms of all component p.d....
const RooNumGenConfig * getGeneratorConfig() const
Return the numeric MC generator configuration used for this object.
virtual void initGenerator(Int_t code)
Interface for one-time initialization to setup the generator for the specified code.
virtual ExtendMode extendMode() const
Returns ability of PDF to provide extended likelihood terms.
Definition RooAbsPdf.h:217
RooAbsPdf()
Default constructor.
virtual RooFit::OwningPtr< RooDataHist > generateBinned(const RooArgSet &whatVars, double nEvents, const RooCmdArg &arg1, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}) const
As RooAbsPdf::generateBinned(const RooArgSet&, const RooCmdArg&,const RooCmdArg&, const RooCmdArg&,...
Definition RooAbsPdf.h:110
bool traceEvalPdf(double value) const
Check that passed value is positive and not 'not-a-number'.
static RooNumGenConfig * defaultGeneratorConfig()
Returns the default numeric MC generator configuration for all RooAbsReals.
bool redirectServersHook(const RooAbsCollection &newServerList, bool mustReplaceAll, bool nameChange, bool isRecursiveStep) override
The cache manager.
void printValue(std::ostream &os) const override
Print value of p.d.f, also print normalization integral that was last used, if any.
virtual std::unique_ptr< RooAbsReal > createNLLImpl(RooAbsData &data, const RooLinkedList &cmdList)
Protected implementation of the NLL creation routine.
void logBatchComputationErrors(std::span< const double > &outputs, std::size_t begin) const
Scan through outputs and fix+log all nans and negative values.
virtual RooAbsGenContext * genContext(const RooArgSet &vars, const RooDataSet *prototype=nullptr, const RooArgSet *auxProto=nullptr, bool verbose=false) const
Interface function to create a generator context from a p.d.f.
void getLogProbabilities(std::span< const double > pdfValues, double *output) const
static TString _normRangeOverride
Definition RooAbsPdf.h:344
static Int_t _verboseEval
Definition RooAbsPdf.h:315
double extendedTerm(double sumEntries, double expected, double sumEntriesW2=0.0, bool doOffset=false) const
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...
virtual RooAbsPdf * createProjection(const RooArgSet &iset)
Return a p.d.f that represent a projection of this p.d.f integrated over given observables.
virtual double getLogVal(const RooArgSet *set=nullptr) const
Return the log of the current value with given normalization An error message is printed if the argum...
bool hasRange(const char *name) const override
Check if variable has a binning with given name.
std::pair< double, double > getRange(const char *name=nullptr) const
Get low and high bound of the variable.
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:59
RooDataHist * fillDataHist(RooDataHist *hist, const RooArgSet *nset, double scaleFactor, bool correctForBinVolume=false, bool showProgress=false) const
Fill a RooDataHist with values sampled from this function at the bin centers.
void plotOnCompSelect(RooArgSet *selNodes) const
Helper function for plotting of composite p.d.fs.
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 plotSanityChecks(RooPlot *frame) const
Utility function for plotOn(), perform general sanity check on frame to ensure safe plotting operatio...
void printMultiline(std::ostream &os, Int_t contents, bool verbose=false, TString indent="") const override
Structure printing.
bool redirectServersHook(const RooAbsCollection &newServerList, bool mustReplaceAll, bool nameChange, bool isRecursiveStep) override
Function that is called at the end of redirectServers().
double _value
Cache for current value of object.
Definition RooAbsReal.h:543
virtual double analyticalIntegral(Int_t code, const char *rangeName=nullptr) const
Implements the actual analytical integral(s) advertised by getAnalyticalIntegral.
TString integralNameSuffix(const RooArgSet &iset, const RooArgSet *nset=nullptr, const char *rangeName=nullptr, bool omitEmpty=false) const
Construct string with unique suffix name to give to integral object that encodes integrated observabl...
virtual double evaluate() const =0
Evaluate this PDF / function / constant. Needs to be overridden by all derived classes.
void logEvalError(const char *message, const char *serverValueString=nullptr) const
Log evaluation error message.
const RooNumIntConfig * getIntegratorConfig() const
Return the numeric integration configuration used for this object.
virtual bool isBinnedDistribution(const RooArgSet &) const
Tests if the distribution is binned. Unless overridden by derived classes, this always returns false.
Definition RooAbsReal.h:353
RooFit::OwningPtr< RooAbsReal > createIntRI(const RooArgSet &iset, const RooArgSet &nset={})
Utility function for createRunningIntegral.
virtual RooPlot * plotOn(RooPlot *frame, 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 RooCmdArg &arg9={}, const RooCmdArg &arg10={}) const
Plot (project) PDF on specified frame.
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:55
Efficient implementation of the generator context specific for binned pdfs.
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.
Implementation of RooAbsCachedReal that can cache any external RooAbsReal input function provided in ...
void setCacheSource(bool flag)
Named container for two doubles, two integers two object points and three string pointers that can be...
Definition RooCmdArg.h:26
void setString(Int_t idx, const char *value)
Definition RooCmdArg.h:78
Configurable parser for RooCmdArg named arguments.
void defineMutex(const char *head, Args_t &&... tail)
Define arguments where any pair is mutually exclusive.
bool process(const RooCmdArg &arg)
Process given RooCmdArg.
bool hasProcessed(const char *cmdName) const
Return true if RooCmdArg with name 'cmdName' has been processed.
double getDouble(const char *name, double defaultValue=0.0) const
Return double property registered with name 'name'.
bool defineDouble(const char *name, const char *argName, int doubleNum, double defValue=0.0)
Define double property name 'name' mapped to double in slot 'doubleNum' in RooCmdArg with name argNam...
static void stripCmdList(RooLinkedList &cmdList, const char *cmdsToPurge)
Utility function that strips command names listed (comma separated) in cmdsToPurge from cmdList.
RooArgSet * getSet(const char *name, RooArgSet *set=nullptr) const
Return RooArgSet property registered with name 'name'.
bool defineSet(const char *name, const char *argName, int setNum, const RooArgSet *set=nullptr)
Define TObject property name 'name' mapped to object in slot 'setNum' in RooCmdArg with name argName ...
bool ok(bool verbose) const
Return true of parsing was successful.
bool defineObject(const char *name, const char *argName, int setNum, const TObject *obj=nullptr, bool isArray=false)
Define TObject property name 'name' mapped to object in slot 'setNum' in RooCmdArg with name argName ...
const char * getString(const char *name, const char *defaultValue="", bool convEmptyToNull=false) const
Return string property registered with name 'name'.
bool defineString(const char *name, const char *argName, int stringNum, const char *defValue="", bool appendMode=false)
Define double property name 'name' mapped to double in slot 'stringNum' in RooCmdArg with name argNam...
bool defineInt(const char *name, const char *argName, int intNum, int defValue=0)
Define integer property name 'name' mapped to integer in slot 'intNum' in RooCmdArg with name argName...
void allowUndefined(bool flag=true)
If flag is true the processing of unrecognized RooCmdArgs is not considered an error.
int getInt(const char *name, int defaultValue=0) const
Return integer property registered with name 'name'.
TObject * getObject(const char *name, TObject *obj=nullptr) const
Return TObject property registered with name 'name'.
Container class to hold unbinned data.
Definition RooDataSet.h:57
void markAsCompiled(RooAbsArg &arg) const
void compileServers(RooAbsArg &arg, RooArgSet const &normSet)
Implements a universal generator context for all RooAbsPdf classes that do not have or need a special...
Switches the message service to a different level while the instance is alive.
Definition RooHelpers.h:37
Collection class for internal use, storing a collection of RooAbsArg pointers in a doubly linked list...
virtual void Add(TObject *arg)
TObject * FindObject(const char *name) const override
Return pointer to object with given name.
static const char * str(const TNamed *ptr)
Return C++ string corresponding to given TNamed pointer.
Definition RooNameReg.h:39
Holds the configuration parameters of the various numeric integrators used by RooRealIntegral.
static RooNumGenConfig & defaultConfig()
Return reference to instance of default numeric integrator configuration object.
Implementation of a RooCacheManager<RooAbsCacheElement> that specializes in the storage of cache elem...
void sterilize() override
Clear the cache payload but retain slot mapping w.r.t to normalization and integration sets.
Plot frame and a container for graphics objects within that frame.
Definition RooPlot.h:43
void addObject(TObject *obj, Option_t *drawOptions="", bool invisible=false)
Add a generic object to this plot.
Definition RooPlot.cxx:378
double getFitRangeNEvt() const
Return the number of events in the fit range.
Definition RooPlot.h:141
const RooArgSet * getNormVars() const
Definition RooPlot.h:148
RooAbsRealLValue * getPlotVar() const
Definition RooPlot.h:139
void updateNormVars(const RooArgSet &vars)
Install the given set of observables are reference normalization variables for this frame.
Definition RooPlot.cxx:363
double getFitRangeBinW() const
Return the bin width that is being used to normalise the PDF.
Definition RooPlot.h:144
virtual void printStream(std::ostream &os, Int_t contents, StyleOption style, TString indent="") const
Print description of object on ostream, printing contents set by contents integer,...
A RooAbsPdf implementation that represent a projection of a given input p.d.f and the object returned...
static UInt_t integer(UInt_t max, TRandom *generator=randomGenerator())
Return an integer uniformly distributed from [0,n-1].
Definition RooRandom.cxx:96
static TRandom * randomGenerator()
Return a pointer to a singleton random-number generator implementation.
Definition RooRandom.cxx:48
Performs hybrid numerical/analytical integrals of RooAbsReal objects.
const RooArgSet & numIntRealVars() const
Variable that can be changed from the outside.
Definition RooRealVar.h:37
void setBins(Int_t nBins, const char *name=nullptr)
Create a uniform binning under name 'name' for this variable.
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
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:207
A Pave (see TPave) with text, lines or/and boxes inside.
Definition TPaveText.h:21
virtual ULong64_t Poisson(Double_t mean)
Generates a random integer N according to a Poisson law.
Definition TRandom.cxx:404
virtual Double_t Uniform(Double_t x1=1)
Returns a uniform deviate on the interval (0, x1).
Definition TRandom.cxx:682
virtual UInt_t Integer(UInt_t imax)
Returns a random integer uniformly distributed on the interval [ 0, imax-1 ].
Definition TRandom.cxx:361
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
void Clear()
Clear string without changing its capacity.
Definition TString.cxx:1235
const char * Data() const
Definition TString.h:376
TLine * line
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition fillpatterns.C:1
RooCmdArg SupNormSet(const RooArgSet &nset)
RooCmdArg NormRange(const char *rangeNameList)
RooCmdArg Range(const char *rangeName, bool adjustNorm=true)
RooCmdArg Normalization(double scaleFactor)
std::vector< std::string > Split(std::string_view str, std::string_view delims, bool skipEmpty=false)
Splits a string at each character in delims.
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
RooArgSet selectFromArgSet(RooArgSet const &, std::string const &names)
std::string getColonSeparatedNameString(RooArgSet const &argSet, char delim=':')
Bool_t IsNaN(Double_t x)
Definition TMath.h:892
Double_t QuietNaN()
Returns a quiet NaN as defined by IEEE 754.
Definition TMath.h:902
__roodevice__ static __roohost__ double packFloatIntoNaN(float payload)
Pack float into mantissa of a NaN.
static void output()