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