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