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