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