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