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