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