Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooAbsReal.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
19/** \class RooAbsReal
20
21 Abstract base class for objects that represent a
22 real value and implements functionality common to all real-valued objects
23 such as the ability to plot them, to construct integrals of them, the
24 ability to advertise (partial) analytical integrals etc.
25
26 Implementation of RooAbsReal may be derived, thus no interface
27 is provided to modify the contents.
28
29 \ingroup Roofitcore
30*/
31
32#include "RooAbsReal.h"
33
34#include "FitHelpers.h"
36#include "RooAbsData.h"
37#include "RooAddPdf.h"
38#include "RooAddition.h"
39#include "RooArgList.h"
40#include "RooArgProxy.h"
41#include "RooArgSet.h"
42#include "RooBinning.h"
43#include "RooBrentRootFinder.h"
44#include "RooCachedReal.h"
45#include "RooCategory.h"
46#include "RooCmdConfig.h"
47#include "RooConstVar.h"
48#include "RooCurve.h"
49#include "RooCustomizer.h"
50#include "RooDataHist.h"
51#include "RooDataSet.h"
52#include "RooDerivative.h"
53#include "RooFirstMoment.h"
55#include "RooFit/Evaluator.h"
56#include "RooFitResult.h"
57#include "RooFormulaVar.h"
58#include "RooFunctor.h"
59#include "RooGlobalFunc.h"
60#include "RooFitImplHelpers.h"
61#include "RooHist.h"
62#include "RooMoment.h"
63#include "RooMsgService.h"
64#include "RooNumIntConfig.h"
65#include "RooNumRunningInt.h"
66#include "RooParamBinning.h"
67#include "RooPlot.h"
68#include "RooProduct.h"
69#include "RooProfileLL.h"
70#include "RooRealBinding.h"
71#include "RooRealIntegral.h"
72#include "RooRealVar.h"
73#include "RooSecondMoment.h"
74#include "RooVectorDataStore.h"
75#include "TreeReadBuffer.h"
76#include "ValueChecking.h"
77
78#include "ROOT/StringUtils.hxx"
79#include "Compression.h"
80#include "Math/IFunction.h"
81#include "TMath.h"
82#include "TObjString.h"
83#include "TTree.h"
84#include "TH1.h"
85#include "TH2.h"
86#include "TH3.h"
87#include "TBranch.h"
88#include "TLeaf.h"
89#include "TAttLine.h"
90#include "TF1.h"
91#include "TF2.h"
92#include "TF3.h"
93#include "TMatrixD.h"
94#include "TVector.h"
95#include "strlcpy.h"
96#ifndef NDEBUG
97#include <TSystem.h> // To print stack traces when caching errors are detected
98#endif
99
100#include <iomanip>
101#include <iostream>
102#include <limits>
103#include <sstream>
104#include <sys/types.h>
105
106namespace {
107
108// Internal helper RooAbsFunc that evaluates the scaled data-weighted average of
109// given RooAbsReal as a function of a single variable using the RooFit::Evaluator.
110class ScaledDataWeightedAverage : public RooAbsFunc {
111public:
112 ScaledDataWeightedAverage(RooAbsReal const &arg, RooAbsData const &data, double scaleFactor, RooAbsRealLValue &var)
113 : RooAbsFunc{1}, _var{var}, _dataWeights{data.getWeightBatch(0, data.numEntries())}, _scaleFactor{scaleFactor}
114 {
115 _arg = RooFit::Detail::compileForNormSet(arg, *data.get());
116 _arg->recursiveRedirectServers(RooArgList{var});
117 _evaluator = std::make_unique<RooFit::Evaluator>(*_arg);
118 std::stack<std::vector<double>>{}.swap(_vectorBuffers);
119 auto dataSpans =
120 RooFit::Detail::BatchModeDataHelpers::getDataSpans(data, "", nullptr, /*skipZeroWeights=*/false,
121 /*takeGlobalObservablesFromData=*/true, _vectorBuffers);
122 for (auto const& item : dataSpans) {
123 _evaluator->setInput(item.first->GetName(), item.second, false);
124 }
125 }
126
127 double operator()(const double xvector[]) const override
128 {
129 double oldVal = _var.getVal();
130 _var.setVal(xvector[0]);
131
132 double out = 0.0;
133 std::span<const double> pdfValues = _evaluator->run();
134 if (_dataWeights.empty()) {
135 out = std::accumulate(pdfValues.begin(), pdfValues.end(), 0.0) / pdfValues.size();
136 } else {
137 double weightsSum = 0.0;
138 for (std::size_t i = 0; i < pdfValues.size(); ++i) {
139 out += pdfValues[i] * _dataWeights[i];
140 weightsSum += _dataWeights[i];
141 }
142 out /= weightsSum;
143 }
144 out *= _scaleFactor;
145
146 _var.setVal(oldVal);
147 return out;
148 }
149 double getMinLimit(UInt_t /*dimension*/) const override { return _var.getMin(); }
150 double getMaxLimit(UInt_t /*dimension*/) const override { return _var.getMax(); }
151
152private:
153 RooAbsRealLValue &_var;
154 std::unique_ptr<RooAbsReal> _arg;
155 std::span<const double> _dataWeights;
156 double _scaleFactor;
157 std::unique_ptr<RooFit::Evaluator> _evaluator;
158 std::stack<std::vector<double>> _vectorBuffers;
159};
160
161} // namespace
162
164
166bool RooAbsReal::_hideOffset = true ;
167
168void RooAbsReal::setHideOffset(bool flag) { _hideOffset = flag ; }
170
173std::map<const RooAbsArg*,std::pair<std::string,std::list<RooAbsReal::EvalError> > > RooAbsReal::_evalErrorList ;
174
175
176////////////////////////////////////////////////////////////////////////////////
177/// coverity[UNINIT_CTOR]
178/// Default constructor
179
181
182
183////////////////////////////////////////////////////////////////////////////////
184/// Constructor with unit label
185
186RooAbsReal::RooAbsReal(const char *name, const char *title, const char *unit) : RooAbsReal{name, title, 0.0, 0.0, unit}
187{
188}
189
190
191////////////////////////////////////////////////////////////////////////////////
192/// Constructor with plot range and unit label
193
194RooAbsReal::RooAbsReal(const char *name, const char *title, double inMinVal,
195 double inMaxVal, const char *unit) :
196 RooAbsArg(name,title), _plotMin(inMinVal), _plotMax(inMaxVal), _unit(unit)
197{
198 setValueDirty() ;
199 setShapeDirty() ;
200}
201
202
203////////////////////////////////////////////////////////////////////////////////
204/// Copy constructor
205RooAbsReal::RooAbsReal(const RooAbsReal& other, const char* name) :
206 RooAbsArg(other,name), _plotMin(other._plotMin), _plotMax(other._plotMax),
207 _plotBins(other._plotBins), _value(other._value), _unit(other._unit), _label(other._label),
208 _forceNumInt(other._forceNumInt), _selectComp(other._selectComp)
209{
210 if (other._specIntegratorConfig) {
211 _specIntegratorConfig = std::make_unique<RooNumIntConfig>(*other._specIntegratorConfig) ;
212 }
213}
214
215
216////////////////////////////////////////////////////////////////////////////////
217/// Destructor
218
220
221
222////////////////////////////////////////////////////////////////////////////////
223/// Equality operator comparing to a double
224
226{
227 return (getVal()==value) ;
228}
229
230
231
232////////////////////////////////////////////////////////////////////////////////
233/// Equality operator when comparing to another RooAbsArg.
234/// Only functional when the other arg is a RooAbsReal
235
236bool RooAbsReal::operator==(const RooAbsArg& other) const
237{
238 const RooAbsReal* otherReal = dynamic_cast<const RooAbsReal*>(&other) ;
239 return otherReal ? operator==(otherReal->getVal()) : false ;
240}
241
242
243////////////////////////////////////////////////////////////////////////////////
244
245bool RooAbsReal::isIdentical(const RooAbsArg& other, bool assumeSameType) const
246{
247 if (!assumeSameType) {
248 const RooAbsReal* otherReal = dynamic_cast<const RooAbsReal*>(&other) ;
249 return otherReal ? operator==(otherReal->getVal()) : false ;
250 } else {
251 return getVal() == static_cast<const RooAbsReal&>(other).getVal();
252 }
253}
254
255
256////////////////////////////////////////////////////////////////////////////////
257/// Return this variable's title string. If appendUnit is true and
258/// this variable has units, also append a string " (<unit>)".
259
260TString RooAbsReal::getTitle(bool appendUnit) const
261{
262 if(appendUnit && 0 != strlen(getUnit())) {
263 return std::string{GetTitle()} + " (" + getUnit() + ")";
264 }
265 return GetTitle();
266}
267
268
269
270////////////////////////////////////////////////////////////////////////////////
271/// Return value of object. If the cache is clean, return the
272/// cached value, otherwise recalculate on the fly and refill
273/// the cache
274
275double RooAbsReal::getValV(const RooArgSet* nset) const
276{
277 if (nset && nset->uniqueId().value() != _lastNormSetId) {
278 const_cast<RooAbsReal*>(this)->setProxyNormSet(nset);
279 _lastNormSetId = nset->uniqueId().value();
280 }
281
282 if (isValueDirtyAndClear()) {
283 _value = traceEval(nullptr) ;
284 // clearValueDirty() ;
285 }
286
287 return hideOffset() ? _value + offset() : _value;
288}
289
290
291////////////////////////////////////////////////////////////////////////////////
292/// Calculate current value of object, with error tracing wrapper
293
294double RooAbsReal::traceEval(const RooArgSet* /*nset*/) const
295{
296 double value = evaluate() ;
297
298 if (TMath::IsNaN(value)) {
299 logEvalError("function value is NAN") ;
300 }
301
302 //cxcoutD(Tracing) << "RooAbsReal::getValF(" << GetName() << ") operMode = " << _operMode << " recalculated, new value = " << value << std::endl ;
303
304 //Standard tracing code goes here
305 if (!isValidReal(value)) {
306 coutW(Tracing) << "RooAbsReal::traceEval(" << GetName()
307 << "): validation failed: " << value << std::endl ;
308 }
309
310 //Call optional subclass tracing code
311 // traceEvalHook(value) ;
312
313 return value ;
314}
315
316
317
318////////////////////////////////////////////////////////////////////////////////
319/// Variant of getAnalyticalIntegral that is also passed the normalization set
320/// that should be applied to the integrand of which the integral is requested.
321/// For certain operator p.d.f it is useful to overload this function rather
322/// than analyticalIntegralWN() as the additional normalization information
323/// may be useful in determining a more efficient decomposition of the
324/// requested integral.
325
327 const RooArgSet* /*normSet*/, const char* rangeName) const
328{
329 return _forceNumInt ? 0 : getAnalyticalIntegral(allDeps,analDeps,rangeName) ;
330}
331
332
333
334////////////////////////////////////////////////////////////////////////////////
335/// Interface function getAnalyticalIntergral advertises the
336/// analytical integrals that are supported. 'integSet'
337/// is the set of dependents for which integration is requested. The
338/// function should copy the subset of dependents it can analytically
339/// integrate to anaIntSet and return a unique identification code for
340/// this integration configuration. If no integration can be
341/// performed, zero should be returned.
342
343Int_t RooAbsReal::getAnalyticalIntegral(RooArgSet& /*integSet*/, RooArgSet& /*anaIntSet*/, const char* /*rangeName*/) const
344{
345 return 0 ;
346}
347
348
349
350////////////////////////////////////////////////////////////////////////////////
351/// Implements the actual analytical integral(s) advertised by
352/// getAnalyticalIntegral. This functions will only be called with
353/// codes returned by getAnalyticalIntegral, except code zero.
354
355double RooAbsReal::analyticalIntegralWN(Int_t code, const RooArgSet* normSet, const char* rangeName) const
356{
357// cout << "RooAbsReal::analyticalIntegralWN(" << GetName() << ") code = " << code << " normSet = " << (normSet?*normSet:RooArgSet()) << std::endl ;
358 if (code==0) return getVal(normSet) ;
359 return analyticalIntegral(code,rangeName) ;
360}
361
362
363
364////////////////////////////////////////////////////////////////////////////////
365/// Implements the actual analytical integral(s) advertised by
366/// getAnalyticalIntegral. This functions will only be called with
367/// codes returned by getAnalyticalIntegral, except code zero.
368
369double RooAbsReal::analyticalIntegral(Int_t code, const char* /*rangeName*/) const
370{
371 // By default no analytical integrals are implemented
372 coutF(Eval) << "RooAbsReal::analyticalIntegral(" << GetName() << ") code " << code << " not implemented" << std::endl ;
373 return 0 ;
374}
375
376
377
378////////////////////////////////////////////////////////////////////////////////
379/// Get the label associated with the variable
380
381const char *RooAbsReal::getPlotLabel() const
382{
383 return _label.IsNull() ? fName.Data() : _label.Data();
384}
385
386
387
388////////////////////////////////////////////////////////////////////////////////
389/// Set the label associated with this variable
390
391void RooAbsReal::setPlotLabel(const char *label)
392{
393 _label= label;
394}
395
396
397
398////////////////////////////////////////////////////////////////////////////////
399///Read object contents from stream (dummy for now)
400
401bool RooAbsReal::readFromStream(std::istream& /*is*/, bool /*compact*/, bool /*verbose*/)
402{
403 return false ;
404}
405
406
407
408////////////////////////////////////////////////////////////////////////////////
409///Write object contents to stream (dummy for now)
410
411void RooAbsReal::writeToStream(std::ostream& /*os*/, bool /*compact*/) const
412{
413}
414
415
416
417////////////////////////////////////////////////////////////////////////////////
418/// Print object value
419
420void RooAbsReal::printValue(std::ostream& os) const
421{
422 os << getVal() ;
423}
424
425
426
427////////////////////////////////////////////////////////////////////////////////
428/// Structure printing
429
430void RooAbsReal::printMultiline(std::ostream& os, Int_t contents, bool verbose, TString indent) const
431{
432 RooAbsArg::printMultiline(os,contents,verbose,indent) ;
433 os << indent << "--- RooAbsReal ---" << std::endl;
434 TString unit(_unit);
435 if(!unit.IsNull()) unit.Prepend(' ');
436 //os << indent << " Value = " << getVal() << unit << std::endl;
437 os << std::endl << indent << " Plot label is \"" << getPlotLabel() << "\"" << "\n";
438}
439
440
441////////////////////////////////////////////////////////////////////////////////
442/// Create a RooProfileLL object that eliminates all nuisance parameters in the
443/// present function. The nuisance parameters are defined as all parameters
444/// of the function except the stated paramsOfInterest
445
447{
448 // Construct name of profile object
449 auto name = std::string(GetName()) + "_Profile[";
450 bool first = true;
451 for (auto const& arg : paramsOfInterest) {
452 if (first) {
453 first = false ;
454 } else {
455 name.append(",") ;
456 }
457 name.append(arg->GetName()) ;
458 }
459 name.append("]") ;
460
461 // Create and return profile object
462 auto out = std::make_unique<RooProfileLL>(name.c_str(),(std::string("Profile of ") + GetTitle()).c_str(),*this,paramsOfInterest);
463 return RooFit::makeOwningPtr<RooAbsReal>(std::move(out));
464}
465
466
467
468
469
470
471////////////////////////////////////////////////////////////////////////////////
472/// Create an object that represents the integral of the function over one or more observables listed in `iset`.
473/// The actual integration calculation is only performed when the returned object is evaluated. The name
474/// of the integral object is automatically constructed from the name of the input function, the variables
475/// it integrates and the range integrates over.
476///
477/// \note The integral over a PDF is usually not normalised (*i.e.*, it is usually not
478/// 1 when integrating the PDF over the full range). In fact, this integral is used *to compute*
479/// the normalisation of each PDF. See the [rf110 tutorial](group__tutorial__roofit.html)
480/// for details on PDF normalisation.
481///
482/// The following named arguments are accepted
483/// | | Effect on integral creation
484/// |--|-------------------------------
485/// | `NormSet(const RooArgSet&)` | Specify normalization set, mostly useful when working with PDFs
486/// | `NumIntConfig(const RooNumIntConfig&)` | Use given configuration for any numeric integration, if necessary
487/// | `Range(const char* name)` | Integrate only over given range. Multiple ranges may be specified by passing multiple Range() arguments
488
490 const RooCmdArg& arg3, const RooCmdArg& arg4, const RooCmdArg& arg5,
491 const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8) const
492{
493 // Define configuration for this method
494 RooCmdConfig pc("RooAbsReal::createIntegral(" + std::string(GetName()) + ")");
495 pc.defineString("rangeName","RangeWithName",0,"",true) ;
496 pc.defineSet("normSet","NormSet",0,nullptr) ;
497 pc.defineObject("numIntConfig","NumIntConfig",0,nullptr) ;
498
499 // Process & check varargs
500 pc.process(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) ;
501 if (!pc.ok(true)) {
502 return nullptr;
503 }
504
505 // Extract values from named arguments
506 const char* rangeName = pc.getString("rangeName",nullptr,true) ;
507 const RooArgSet* nset = pc.getSet("normSet",nullptr);
508 const RooNumIntConfig* cfg = static_cast<const RooNumIntConfig*>(pc.getObject("numIntConfig",nullptr)) ;
509
510 return createIntegral(iset,nset,cfg,rangeName) ;
511}
512
513
514
515
516
517////////////////////////////////////////////////////////////////////////////////
518/// Create an object that represents the integral of the function over one or more observables listed in iset.
519/// The actual integration calculation is only performed when the return object is evaluated. The name
520/// of the integral object is automatically constructed from the name of the input function, the variables
521/// it integrates and the range integrates over. If nset is specified the integrand is request
522/// to be normalized over nset (only meaningful when the integrand is a pdf). If rangename is specified
523/// the integral is performed over the named range, otherwise it is performed over the domain of each
524/// integrated observable. If cfg is specified it will be used to configure any numeric integration
525/// aspect of the integral. It will not force the integral to be performed numerically, which is
526/// decided automatically by RooRealIntegral.
527
529 const RooNumIntConfig* cfg, const char* rangeName) const
530{
531 if (!rangeName || strchr(rangeName,',')==nullptr) {
532 // Simple case: integral over full range or single limited range
533 return createIntObj(iset,nset,cfg,rangeName);
534 }
535
536 // Integral over multiple ranges
537 std::vector<std::string> tokens = ROOT::Split(rangeName, ",");
538
539 if(RooHelpers::checkIfRangesOverlap(iset, tokens)) {
540 std::stringstream errMsg;
541 errMsg << GetName() << " : integrating with respect to the variables " << iset << " on the ranges \"" << rangeName
542 << "\" is not possible because the ranges are overlapping";
543 const std::string errMsgString = errMsg.str();
544 coutE(Integration) << errMsgString << std::endl;
545 throw std::invalid_argument(errMsgString);
546 }
547
548 RooArgSet components ;
549 for (const std::string& token : tokens) {
550 components.addOwned(std::unique_ptr<RooAbsReal>{createIntObj(iset,nset,cfg, token.c_str())});
551 }
552
553 const std::string title = std::string("Integral of ") + GetTitle();
554 const std::string fullName = std::string(GetName()) + integralNameSuffix(iset,nset,rangeName).Data();
555
556 auto out = std::make_unique<RooAddition>(fullName.c_str(), title.c_str(), components);
557 out->addOwnedComponents(std::move(components));
558 return RooFit::makeOwningPtr<RooAbsReal>(std::move(out));
559}
560
561
562
563////////////////////////////////////////////////////////////////////////////////
564/// Internal utility function for createIntegral() that creates the actual integral object.
566 const RooNumIntConfig* cfg, const char* rangeName) const
567{
568 // Make internal use copies of iset and nset
569 RooArgSet iset(iset2) ;
570 const RooArgSet* nset = nset2 ;
571
572
573 // Initialize local variables perparing for recursive loop
574 bool error = false ;
575 const RooAbsReal* integrand = this ;
576 std::unique_ptr<RooAbsReal> integral;
577
578 // Handle trivial case of no integration here explicitly
579 if (iset.empty()) {
580
581 const std::string title = std::string("Integral of ") + GetTitle();
582 const std::string name = std::string(GetName()) + integralNameSuffix(iset,nset,rangeName).Data();
583
584 auto out = std::make_unique<RooRealIntegral>(name.c_str(), title.c_str(), *this, iset, nset, cfg, rangeName);
585 return RooFit::makeOwningPtr<RooAbsReal>(std::move(out));
586 }
587
588 // Process integration over remaining integration variables
589 while(!iset.empty()) {
590
591
592 // Find largest set of observables that can be integrated in one go
593 RooArgSet innerSet ;
594 findInnerMostIntegration(iset,innerSet,rangeName) ;
595
596 // If largest set of observables that can be integrated is empty set, problem was ill defined
597 // Postpone error messaging and handling to end of function, exit loop here
598 if (innerSet.empty()) {
599 error = true ;
600 break ;
601 }
602
603 // Prepare name and title of integral to be created
604 const std::string title = std::string("Integral of ") + integrand->GetTitle();
605 const std::string name = std::string(integrand->GetName()) + integrand->integralNameSuffix(innerSet,nset,rangeName).Data();
606
607 std::unique_ptr<RooAbsReal> innerIntegral = std::move(integral);
608
609 // Construct innermost integral
610 integral = std::make_unique<RooRealIntegral>(name.c_str(),title.c_str(),*integrand,innerSet,nset,cfg,rangeName);
611
612 // Integral of integral takes ownership of innermost integral
613 if (innerIntegral) {
614 integral->addOwnedComponents(std::move(innerIntegral));
615 }
616
617 // Remove already integrated observables from to-do list
618 iset.remove(innerSet) ;
619
620 // Send info message on recursion if needed
621 if (integrand == this && !iset.empty()) {
622 coutI(Integration) << GetName() << " : multidimensional integration over observables with parameterized ranges in terms of other integrated observables detected, using recursive integration strategy to construct final integral" << std::endl ;
623 }
624
625 // Prepare for recursion, next integral should integrate last integrand
626 integrand = integral.get();
627
628
629 // Only need normalization set in innermost integration
630 nset = nullptr;
631 }
632
633 if (error) {
634 coutE(Integration) << GetName() << " : ERROR while defining recursive integral over observables with parameterized integration ranges, please check that integration rangs specify uniquely defined integral " << std::endl;
635 return nullptr;
636 }
637
638
639 // After-burner: apply interpolating cache on (numeric) integral if requested by user
640 const char* cacheParamsStr = getStringAttribute("CACHEPARAMINT") ;
641 if (cacheParamsStr && strlen(cacheParamsStr)) {
642
643 std::unique_ptr<RooArgSet> intParams{integral->getVariables()};
644
645 RooArgSet cacheParams = RooHelpers::selectFromArgSet(*intParams, cacheParamsStr);
646
647 if (!cacheParams.empty()) {
648 cxcoutD(Caching) << "RooAbsReal::createIntObj(" << GetName() << ") INFO: constructing " << cacheParams.size()
649 << "-dim value cache for integral over " << iset2 << " as a function of " << cacheParams << " in range " << (rangeName?rangeName:"<none>") << std::endl ;
650 std::string name = Form("%s_CACHE_[%s]",integral->GetName(),cacheParams.contentsString().c_str()) ;
651 auto cachedIntegral = std::make_unique<RooCachedReal>(name.c_str(),name.c_str(),*integral,cacheParams);
652 cachedIntegral->setInterpolationOrder(2) ;
653 cachedIntegral->addOwnedComponents(std::move(integral));
654 cachedIntegral->setCacheSource(true) ;
655 if (integral->operMode()==ADirty) {
656 cachedIntegral->setOperMode(ADirty) ;
657 }
658 //cachedIntegral->disableCache(true) ;
659 return RooFit::makeOwningPtr<RooAbsReal>(std::move(cachedIntegral));
660 }
661 }
662
663 return RooFit::makeOwningPtr(std::move(integral));
664}
665
666
667
668////////////////////////////////////////////////////////////////////////////////
669/// Utility function for createIntObj() that aids in the construct of recursive integrals
670/// over functions with multiple observables with parameterized ranges. This function
671/// finds in a given set allObs over which integration is requested the largeset subset
672/// of observables that can be integrated simultaneously. This subset consists of
673/// observables with fixed ranges and observables with parameterized ranges whose
674/// parameterization does not depend on any observable that is also integrated.
675
676void RooAbsReal::findInnerMostIntegration(const RooArgSet& allObs, RooArgSet& innerObs, const char* rangeName) const
677{
678 // Make lists of
679 // a) integrated observables with fixed ranges,
680 // b) integrated observables with parameterized ranges depending on other integrated observables
681 // c) integrated observables used in definition of any parameterized ranges of integrated observables
682 RooArgSet obsWithFixedRange(allObs) ;
683 RooArgSet obsWithParamRange ;
684 RooArgSet obsServingAsRangeParams ;
685
686 // Loop over all integrated observables
687 for (const auto aarg : allObs) {
688 // Check if observable is real-valued lvalue
689 if (auto arglv = dynamic_cast<RooAbsRealLValue*>(aarg)) {
690
691 // Check if range is parameterized
692 RooAbsBinning& binning = arglv->getBinning(rangeName,false,true) ;
693 if (binning.isParameterized()) {
694 RooArgSet loBoundObs;
695 RooArgSet hiBoundObs;
696 binning.lowBoundFunc()->getObservables(&allObs, loBoundObs) ;
697 binning.highBoundFunc()->getObservables(&allObs, hiBoundObs) ;
698
699 // Check if range parameterization depends on other integrated observables
700 if (loBoundObs.overlaps(allObs) || hiBoundObs.overlaps(allObs)) {
701 obsWithParamRange.add(*aarg) ;
702 obsWithFixedRange.remove(*aarg) ;
703 obsServingAsRangeParams.add(loBoundObs,false) ;
704 obsServingAsRangeParams.add(hiBoundObs,false) ;
705 }
706 }
707 }
708 }
709
710 // Make list of fixed-range observables that are _not_ involved in the parameterization of ranges of other observables
711 RooArgSet obsWithFixedRangeNP(obsWithFixedRange) ;
712 obsWithFixedRangeNP.remove(obsServingAsRangeParams) ;
713
714 // Make list of param-range observables that are _not_ involved in the parameterization of ranges of other observables
715 RooArgSet obsWithParamRangeNP(obsWithParamRange) ;
716 obsWithParamRangeNP.remove(obsServingAsRangeParams) ;
717
718 // Construct inner-most integration: over observables (with fixed or param range) not used in any other param range definitions
719 innerObs.removeAll() ;
720 innerObs.add(obsWithFixedRangeNP) ;
721 innerObs.add(obsWithParamRangeNP) ;
722
723}
724
725
726////////////////////////////////////////////////////////////////////////////////
727/// Construct string with unique suffix name to give to integral object that encodes
728/// integrated observables, normalization observables and the integration range name
729
730TString RooAbsReal::integralNameSuffix(const RooArgSet& iset, const RooArgSet* nset, const char* rangeName, bool omitEmpty) const
731{
732 TString name ;
733 if (!iset.empty()) {
735 if (rangeName) {
736 name.Append("|" + std::string{rangeName});
737 }
738 name.Append("]");
739 } else if (!omitEmpty) {
740 name.Append("_Int[]") ;
741 }
742
743 if (nset && !nset->empty()) {
745 const RooAbsPdf* thisPdf = dynamic_cast<const RooAbsPdf*>(this) ;
746 if (thisPdf && thisPdf->normRange()) {
747 name.Append("|" + std::string{thisPdf->normRange()}) ;
748 }
749 name.Append("]") ;
750 }
751
752 return name ;
753}
754
755
756
757////////////////////////////////////////////////////////////////////////////////
758/// Utility function for plotOn() that creates a projection of a function or p.d.f
759/// to be plotted on a RooPlot.
760/// \ref createPlotProjAnchor "createPlotProjection()"
761
762const RooAbsReal* RooAbsReal::createPlotProjection(const RooArgSet& depVars, const RooArgSet& projVars,
763 RooArgSet*& cloneSet) const
764{
765 return createPlotProjection(depVars,&projVars,cloneSet) ;
766}
767
768
769////////////////////////////////////////////////////////////////////////////////
770/// Utility function for plotOn() that creates a projection of a function or p.d.f
771/// to be plotted on a RooPlot.
772/// \anchor createPlotProjAnchor
773///
774/// Create a new object \f$ G \f$ that represents the normalized projection:
775/// \f[
776/// G[x,p] = \frac{\int F[x,y,p] \; \mathrm{d}\{y\}}
777/// {\int F[x,y,p] \; \mathrm{d}\{x\} \, \mathrm{d}\{y\}}
778/// \f]
779/// where \f$ F[x,y,p] \f$ is the function we represent, and
780/// \f$ \{ p \} \f$ are the remaining variables ("parameters").
781///
782/// \param[in] dependentVars Dependent variables over which to normalise, \f$ \{x\} \f$.
783/// \param[in] projectedVars Variables to project out, \f$ \{ y \} \f$.
784/// \param[out] cloneSet Will be set to a RooArgSet*, which will contain a clone of *this plus its projection integral object.
785/// The latter will also be returned. The caller takes ownership of this set.
786/// \param[in] rangeName Optional range for projection integrals
787/// \param[in] condObs Conditional observables, which are not integrated for normalisation, even if they
788/// are in `dependentVars` or `projectedVars`.
789/// \return A pointer to the newly created object, or zero in case of an
790/// error. The caller is responsible for deleting the `cloneSet` (which includes the returned projection object).
791const RooAbsReal *RooAbsReal::createPlotProjection(const RooArgSet &dependentVars, const RooArgSet *projectedVars,
792 RooArgSet *&cloneSet, const char* rangeName, const RooArgSet* condObs) const
793{
794 // Get the set of our leaf nodes
795 RooArgSet leafNodes;
796 RooArgSet treeNodes;
797 leafNodeServerList(&leafNodes,this);
798 treeNodeServerList(&treeNodes,this) ;
799
800
801 // Check that the dependents are all fundamental. Filter out any that we
802 // do not depend on, and make substitutions by name in our leaf list.
803 // Check for overlaps with the projection variables.
804 for (const auto arg : dependentVars) {
805 if(!arg->isFundamental() && !dynamic_cast<const RooAbsLValue*>(arg)) {
806 coutE(Plotting) << ClassName() << "::" << GetName() << ":createPlotProjection: variable \"" << arg->GetName()
807 << "\" of wrong type: " << arg->ClassName() << std::endl;
808 return nullptr;
809 }
810
811 RooAbsArg *found= treeNodes.find(arg->GetName());
812 if(!found) {
813 coutE(Plotting) << ClassName() << "::" << GetName() << ":createPlotProjection: \"" << arg->GetName()
814 << "\" is not a dependent and will be ignored." << std::endl;
815 continue;
816 }
817 if(found != arg) {
818 if (leafNodes.find(found->GetName())) {
819 leafNodes.replace(*found,*arg);
820 } else {
821 leafNodes.add(*arg) ;
822
823 // Remove any dependents of found, replace by dependents of LV node
824 RooArgSet lvDep;
825 arg->getObservables(&leafNodes, lvDep);
826 for (const auto lvs : lvDep) {
827 RooAbsArg* tmp = leafNodes.find(lvs->GetName()) ;
828 if (tmp) {
829 leafNodes.remove(*tmp) ;
830 leafNodes.add(*lvs) ;
831 }
832 }
833 }
834 }
835
836 // check if this arg is also in the projection set
837 if(nullptr != projectedVars && projectedVars->find(arg->GetName())) {
838 coutE(Plotting) << ClassName() << "::" << GetName() << ":createPlotProjection: \"" << arg->GetName()
839 << "\" cannot be both a dependent and a projected variable." << std::endl;
840 return nullptr;
841 }
842 }
843
844 // Remove the projected variables from the list of leaf nodes, if necessary.
845 if(nullptr != projectedVars) leafNodes.remove(*projectedVars,true);
846
847 // Make a deep-clone of ourself so later operations do not disturb our original state
848 cloneSet = new RooArgSet;
849 if (RooArgSet(*this).snapshot(*cloneSet, true)) {
850 coutE(Plotting) << "RooAbsPdf::createPlotProjection(" << GetName() << ") Couldn't deep-clone PDF, abort," << std::endl ;
851 return nullptr ;
852 }
853 RooAbsReal *theClone= static_cast<RooAbsReal*>(cloneSet->find(GetName()));
854
855 // The remaining entries in our list of leaf nodes are the external
856 // dependents (x) and parameters (p) of the projection. Patch them back
857 // into the theClone. This orphans the nodes they replace, but the orphans
858 // are still in the cloneList and so will be cleaned up eventually.
859 //cout << "redirection leafNodes : " ; leafNodes.Print("1") ;
860
861 std::unique_ptr<RooArgSet> plotLeafNodes{leafNodes.selectCommon(dependentVars)};
862 theClone->recursiveRedirectServers(*plotLeafNodes,false,false,false);
863
864 // Create the set of normalization variables to use in the projection integrand
865 RooArgSet normSet(dependentVars);
866 if(nullptr != projectedVars) normSet.add(*projectedVars);
867 if(nullptr != condObs) {
868 normSet.remove(*condObs,true,true) ;
869 }
870
871 // Try to create a valid projection integral. If no variables are to be projected,
872 // create a null projection anyway to bind our normalization over the dependents
873 // consistently with the way they would be bound with a non-trivial projection.
874 RooArgSet empty;
875 if(nullptr == projectedVars) projectedVars= &empty;
876
877 std::string name = GetName();
878 name += integralNameSuffix(*projectedVars,&normSet,rangeName,true) ;
879
880 std::string title = std::string{"Projection of "} + GetTitle();
881
882 std::unique_ptr<RooAbsReal> projected{theClone->createIntegral(*projectedVars,normSet,rangeName)};
883
884 if(nullptr == projected || !projected->isValid()) {
885 coutE(Plotting) << ClassName() << "::" << GetName() << ":createPlotProjection: cannot integrate out ";
886 projectedVars->printStream(std::cout,kName|kArgs,kSingleLine);
887 return nullptr;
888 }
889
890 if(projected->InheritsFrom(RooRealIntegral::Class())){
891 static_cast<RooRealIntegral&>(*projected).setAllowComponentSelection(true);
892 }
893
894 projected->SetName(name.c_str()) ;
895 projected->SetTitle(title.c_str()) ;
896
897 // Add the projection integral to the cloneSet so that it eventually gets cleaned up by the caller.
898 RooAbsReal *projectedPtr = projected.get();
899 cloneSet->addOwned(std::move(projected));
900
901 // return a const pointer to remind the caller that they do not delete the returned object
902 // directly (it is contained in the cloneSet instead).
903 return projectedPtr;
904}
905
906
907
908////////////////////////////////////////////////////////////////////////////////
909/// Fill the ROOT histogram 'hist' with values sampled from this
910/// function at the bin centers. Our value is calculated by first
911/// integrating out any variables in projectedVars and then scaling
912/// the result by scaleFactor. Returns a pointer to the input
913/// histogram, or zero in case of an error. The input histogram can
914/// be any TH1 subclass, and therefore of arbitrary
915/// dimension. Variables are matched with the (x,y,...) dimensions of
916/// the input histogram according to the order in which they appear
917/// in the input plotVars list. If scaleForDensity is true the
918/// histogram is filled with a the functions density rather than
919/// the functions value (i.e. the value at the bin center is multiplied
920/// with bin volume)
921
923 double scaleFactor, const RooArgSet *projectedVars, bool scaleForDensity,
924 const RooArgSet* condObs, bool setError) const
925{
926 // Do we have a valid histogram to use?
927 if(nullptr == hist) {
928 coutE(InputArguments) << ClassName() << "::" << GetName() << ":fillHistogram: no valid histogram to fill" << std::endl;
929 return nullptr;
930 }
931
932 // Check that the number of plotVars matches the input histogram's dimension
933 Int_t hdim= hist->GetDimension();
934 if(hdim != int(plotVars.size())) {
935 coutE(InputArguments) << ClassName() << "::" << GetName() << ":fillHistogram: plotVars has the wrong dimension" << std::endl;
936 return nullptr;
937 }
938
939
940 // Check that the plot variables are all actually RooRealVars and print a warning if we do not
941 // explicitly depend on one of them. Fill a set (not list!) of cloned plot variables.
942 RooArgSet plotClones;
943 for(std::size_t index= 0; index < plotVars.size(); index++) {
944 const RooAbsArg *var= plotVars.at(index);
945 const RooRealVar *realVar= dynamic_cast<const RooRealVar*>(var);
946 if(nullptr == realVar) {
947 coutE(InputArguments) << ClassName() << "::" << GetName() << ":fillHistogram: cannot plot variable \"" << var->GetName()
948 << "\" of type " << var->ClassName() << std::endl;
949 return nullptr;
950 }
951 if(!this->dependsOn(*realVar)) {
952 coutE(InputArguments) << ClassName() << "::" << GetName()
953 << ":fillHistogram: WARNING: variable is not an explicit dependent: " << realVar->GetName() << std::endl;
954 }
955 plotClones.addClone(*realVar,true); // do not complain about duplicates
956 }
957
958 // Reconnect all plotClones to each other, imported when plotting N-dim integrals with entangled parameterized ranges
959 for(RooAbsArg * pc : plotClones) {
960 pc->recursiveRedirectServers(plotClones,false,false,true) ;
961 }
962
963 // Call checkObservables
964 RooArgSet allDeps(plotClones) ;
965 if (projectedVars) {
966 allDeps.add(*projectedVars) ;
967 }
968 if (checkObservables(&allDeps)) {
969 coutE(InputArguments) << "RooAbsReal::fillHistogram(" << GetName() << ") error in checkObservables, abort" << std::endl ;
970 return hist ;
971 }
972
973 // Create a standalone projection object to use for calculating bin contents
974 RooArgSet *cloneSet = nullptr;
975 const RooAbsReal *projected= createPlotProjection(plotClones,projectedVars,cloneSet,nullptr,condObs);
976
977 cxcoutD(Plotting) << "RooAbsReal::fillHistogram(" << GetName() << ") plot projection object is " << projected->GetName() << std::endl ;
978
979 // Prepare to loop over the histogram bins
980 Int_t xbins(0);
981 Int_t ybins(1);
982 Int_t zbins(1);
983 RooRealVar *xvar = nullptr;
984 RooRealVar *yvar = nullptr;
985 RooRealVar *zvar = nullptr;
986 TAxis *xaxis = nullptr;
987 TAxis *yaxis = nullptr;
988 TAxis *zaxis = nullptr;
989 switch(hdim) {
990 case 3:
991 zbins= hist->GetNbinsZ();
992 zvar= dynamic_cast<RooRealVar*>(plotClones.find(plotVars.at(2)->GetName()));
993 zaxis= hist->GetZaxis();
994 assert(nullptr != zvar && nullptr != zaxis);
995 if (scaleForDensity) {
996 scaleFactor*= (zaxis->GetXmax() - zaxis->GetXmin())/zbins;
997 }
998 // fall through to next case...
999 case 2:
1000 ybins= hist->GetNbinsY();
1001 yvar= dynamic_cast<RooRealVar*>(plotClones.find(plotVars.at(1)->GetName()));
1002 yaxis= hist->GetYaxis();
1003 assert(nullptr != yvar && nullptr != yaxis);
1004 if (scaleForDensity) {
1005 scaleFactor*= (yaxis->GetXmax() - yaxis->GetXmin())/ybins;
1006 }
1007 // fall through to next case...
1008 case 1:
1009 xbins= hist->GetNbinsX();
1010 xvar= dynamic_cast<RooRealVar*>(plotClones.find(plotVars.at(0)->GetName()));
1011 xaxis= hist->GetXaxis();
1012 assert(nullptr != xvar && nullptr != xaxis);
1013 if (scaleForDensity) {
1014 scaleFactor*= (xaxis->GetXmax() - xaxis->GetXmin())/xbins;
1015 }
1016 break;
1017 default:
1018 coutE(InputArguments) << ClassName() << "::" << GetName() << ":fillHistogram: cannot fill histogram with "
1019 << hdim << " dimensions" << std::endl;
1020 break;
1021 }
1022
1023 // Loop over the input histogram's bins and fill each one with our projection's
1024 // value, calculated at the center.
1026 Int_t xbin(0);
1027 Int_t ybin(0);
1028 Int_t zbin(0);
1029 Int_t bins= xbins*ybins*zbins;
1030 for(Int_t bin= 0; bin < bins; bin++) {
1031 switch(hdim) {
1032 case 3:
1033 if(bin % (xbins*ybins) == 0) {
1034 zbin++;
1035 zvar->setVal(zaxis->GetBinCenter(zbin));
1036 }
1037 // fall through to next case...
1038 case 2:
1039 if(bin % xbins == 0) {
1040 ybin= (ybin%ybins) + 1;
1041 yvar->setVal(yaxis->GetBinCenter(ybin));
1042 }
1043 // fall through to next case...
1044 case 1:
1045 xbin= (xbin%xbins) + 1;
1046 xvar->setVal(xaxis->GetBinCenter(xbin));
1047 break;
1048 default:
1049 coutE(InputArguments) << "RooAbsReal::fillHistogram: Internal Error!" << std::endl;
1050 break;
1051 }
1052
1053 double result= scaleFactor*projected->getVal();
1054 if (RooAbsReal::numEvalErrors()>0) {
1055 coutW(Plotting) << "WARNING: Function evaluation error(s) at coordinates [x]=" << xvar->getVal() ;
1056 if (hdim==2) ccoutW(Plotting) << " [y]=" << yvar->getVal() ;
1057 if (hdim==3) ccoutW(Plotting) << " [z]=" << zvar->getVal() ;
1058 ccoutW(Plotting) << std::endl ;
1059 // RooAbsReal::printEvalErrors(ccoutW(Plotting),10) ;
1060 result = 0 ;
1061 }
1063
1064 hist->SetBinContent(hist->GetBin(xbin,ybin,zbin),result);
1065 if (setError) {
1066 hist->SetBinError(hist->GetBin(xbin,ybin,zbin),sqrt(result)) ;
1067 }
1068
1069 //cout << "bin " << bin << " -> (" << xbin << "," << ybin << "," << zbin << ") = " << result << std::endl;
1070 }
1072
1073 // cleanup
1074 delete cloneSet;
1075
1076 return hist;
1077}
1078
1079
1080
1081////////////////////////////////////////////////////////////////////////////////
1082/// Fill a RooDataHist with values sampled from this function at the
1083/// bin centers. If extendedMode is true, the p.d.f. values is multiplied
1084/// by the number of expected events in each bin
1085///
1086/// An optional scaling by a given scaleFactor can be performed.
1087/// Returns a pointer to the input RooDataHist, or zero
1088/// in case of an error.
1089///
1090/// If correctForBinSize is true the RooDataHist
1091/// is filled with the functions density (function value times the
1092/// bin volume) rather than function value.
1093///
1094/// If showProgress is true
1095/// a process indicator is printed on stdout in steps of one percent,
1096/// which is mostly useful for the sampling of expensive functions
1097/// such as likelihoods
1098
1099RooDataHist* RooAbsReal::fillDataHist(RooDataHist *hist, const RooArgSet* normSet, double scaleFactor,
1100 bool correctForBinSize, bool showProgress) const
1101{
1102 // Do we have a valid histogram to use?
1103 if(nullptr == hist) {
1104 coutE(InputArguments) << ClassName() << "::" << GetName() << ":fillDataHist: no valid RooDataHist to fill" << std::endl;
1105 return nullptr;
1106 }
1107
1108 // Call checkObservables
1109 RooArgSet allDeps(*hist->get()) ;
1110 if (checkObservables(&allDeps)) {
1111 coutE(InputArguments) << "RooAbsReal::fillDataHist(" << GetName() << ") error in checkObservables, abort" << std::endl ;
1112 return hist ;
1113 }
1114
1115 // Make deep clone of self and attach to dataset observables
1116 //RooArgSet* origObs = getObservables(hist) ;
1117 RooArgSet cloneSet;
1118 RooArgSet(*this).snapshot(cloneSet, true);
1119 RooAbsReal* theClone = static_cast<RooAbsReal*>(cloneSet.find(GetName()));
1120 theClone->recursiveRedirectServers(*hist->get()) ;
1121 //const_cast<RooAbsReal*>(this)->recursiveRedirectServers(*hist->get()) ;
1122
1123 // Iterator over all bins of RooDataHist and fill weights
1124 Int_t onePct = hist->numEntries()/100 ;
1125 if (onePct==0) {
1126 onePct++ ;
1127 }
1128 for (Int_t i=0 ; i<hist->numEntries() ; i++) {
1129 if (showProgress && (i%onePct==0)) {
1130 ccoutP(Eval) << "." << std::flush ;
1131 }
1132 const RooArgSet* obs = hist->get(i) ;
1133 double binVal = theClone->getVal(normSet?normSet:obs)*scaleFactor ;
1134 if (correctForBinSize) {
1135 binVal*= hist->binVolume() ;
1136 }
1137 hist->set(i, binVal, 0.);
1138 }
1139
1140 return hist;
1141}
1142
1143
1144
1145
1146////////////////////////////////////////////////////////////////////////////////
1147/// Create and fill a ROOT histogram TH1, TH2 or TH3 with the values of this function for the variables with given names.
1148/// \param[in] varNameList List of variables to use for x, y, z axis, separated by ':'
1149/// \param[in] xbins Number of bins for first variable
1150/// \param[in] ybins Number of bins for second variable
1151/// \param[in] zbins Number of bins for third variable
1152/// \return TH1*, which is one of TH[1-3]. The histogram is owned by the caller.
1153///
1154/// For a greater degree of control use
1155/// RooAbsReal::createHistogram(const char *, const RooAbsRealLValue&, const RooCmdArg&, const RooCmdArg&, const RooCmdArg&, const RooCmdArg&, const RooCmdArg&, const RooCmdArg&, const RooCmdArg&, const RooCmdArg&) const
1156///
1157
1158TH1* RooAbsReal::createHistogram(RooStringView varNameList, Int_t xbins, Int_t ybins, Int_t zbins) const
1159{
1160 std::unique_ptr<RooArgSet> vars{getVariables()};
1161
1162 auto varNames = ROOT::Split(varNameList, ",:");
1163 std::vector<RooRealVar*> histVars(3, nullptr);
1164
1165 for(std::size_t iVar = 0; iVar < varNames.size(); ++iVar) {
1166 if(varNames[iVar].empty()) continue;
1167 if(iVar >= 3) {
1168 std::stringstream errMsg;
1169 errMsg << "RooAbsPdf::createHistogram(" << GetName() << ") ERROR more than three variable names passed, but maximum number of supported variables is three";
1170 coutE(Plotting) << errMsg.str() << std::endl;
1171 throw std::invalid_argument(errMsg.str());
1172 }
1173 auto var = static_cast<RooRealVar*>(vars->find(varNames[iVar].c_str()));
1174 if(!var) {
1175 std::stringstream errMsg;
1176 errMsg << "RooAbsPdf::createHistogram(" << GetName() << ") ERROR variable " << varNames[iVar] << " does not exist in argset: " << *vars;
1177 coutE(Plotting) << errMsg.str() << std::endl;
1178 throw std::runtime_error(errMsg.str());
1179 }
1180 histVars[iVar] = var;
1181 }
1182
1183 // Construct list of named arguments to pass to the implementation version of createHistogram()
1184
1185 RooLinkedList argList ;
1186 if (xbins>0) {
1187 argList.Add(RooFit::Binning(xbins).Clone()) ;
1188 }
1189
1190 if (histVars[1]) {
1191 argList.Add(RooFit::YVar(*histVars[1], ybins > 0 ? RooFit::Binning(ybins) : RooCmdArg::none()).Clone()) ;
1192 }
1193
1194 if (histVars[2]) {
1195 argList.Add(RooFit::ZVar(*histVars[2], zbins > 0 ? RooFit::Binning(zbins) : RooCmdArg::none()).Clone()) ;
1196 }
1197
1198 // Call implementation function
1199 TH1* result = createHistogram(GetName(), *histVars[0], argList) ;
1200
1201 // Delete temporary list of RooCmdArgs
1202 argList.Delete() ;
1203
1204 return result ;
1205}
1206
1207
1208
1209////////////////////////////////////////////////////////////////////////////////
1210/// Create and fill a ROOT histogram TH1, TH2 or TH3 with the values of this function.
1211///
1212/// \param[in] name Name of the ROOT histogram
1213/// \param[in] xvar Observable to be std::mapped on x axis of ROOT histogram
1214/// \param[in] arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8 Arguments according to list below
1215/// \return TH1 *, one of TH{1,2,3}. The caller takes ownership.
1216///
1217/// <table>
1218/// <tr><th><th> Effect on histogram creation
1219/// <tr><td> `IntrinsicBinning()` <td> Apply binning defined by function or pdf (as advertised via binBoundaries() method)
1220/// <tr><td> `Binning(const char* name)` <td> Apply binning with given name to x axis of histogram
1221/// <tr><td> `Binning(RooAbsBinning& binning)` <td> Apply specified binning to x axis of histogram
1222/// <tr><td> `Binning(int nbins, [double lo, double hi])` <td> Apply specified binning to x axis of histogram
1223/// <tr><td> `ConditionalObservables(Args_t &&... argsOrArgSet)` <td> Do not normalise PDF over following observables when projecting PDF into histogram.
1224// Arguments can either be multiple RooRealVar or a single RooArgSet containing them.
1225/// <tr><td> `Scaling(bool)` <td> Apply density-correction scaling (multiply by bin volume), default is true
1226/// <tr><td> `Extended(bool)` <td> Plot event yield instead of probability density (for extended pdfs only)
1227///
1228/// <tr><td> `YVar(const RooAbsRealLValue& var,...)` <td> Observable to be std::mapped on y axis of ROOT histogram.
1229/// The YVar() and ZVar() arguments can be supplied with optional Binning() arguments to control the binning of the Y and Z axes, e.g.
1230/// ```
1231/// createHistogram("histo",x,Binning(-1,1,20), YVar(y,Binning(-1,1,30)), ZVar(z,Binning("zbinning")))
1232/// ```
1233/// <tr><td> `ZVar(const RooAbsRealLValue& var,...)` <td> Observable to be std::mapped on z axis of ROOT histogram
1234/// </table>
1235///
1236///
1237
1239 const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3, const RooCmdArg& arg4,
1240 const RooCmdArg& arg5, const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8) const
1241{
1242
1244 l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
1245 l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
1246 l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
1247 l.Add((TObject*)&arg7) ; l.Add((TObject*)&arg8) ;
1248
1249 return createHistogram(name,xvar,l) ;
1250}
1251
1252
1253////////////////////////////////////////////////////////////////////////////////
1254/// Internal method implementing createHistogram
1255
1256TH1* RooAbsReal::createHistogram(const char *name, const RooAbsRealLValue& xvar, RooLinkedList& argList) const
1257{
1258
1259 // Define configuration for this method
1260 RooCmdConfig pc("RooAbsReal::createHistogram(" + std::string(GetName()) + ")");
1261 pc.defineInt("scaling","Scaling",0,1) ;
1262 pc.defineInt("intBinning","IntrinsicBinning",0,2) ;
1263 pc.defineInt("extended","Extended",0,2) ;
1264
1265 pc.defineSet("compSet","SelectCompSet",0);
1266 pc.defineString("compSpec","SelectCompSpec",0) ;
1267 pc.defineSet("projObs","ProjectedObservables",0,nullptr) ;
1268 pc.defineObject("yvar","YVar",0,nullptr) ;
1269 pc.defineObject("zvar","ZVar",0,nullptr) ;
1270 pc.defineMutex("SelectCompSet","SelectCompSpec") ;
1271 pc.defineMutex("IntrinsicBinning","Binning") ;
1272 pc.defineMutex("IntrinsicBinning","BinningName") ;
1273 pc.defineMutex("IntrinsicBinning","BinningSpec") ;
1274 pc.allowUndefined() ;
1275
1276 // Process & check varargs
1277 pc.process(argList) ;
1278 if (!pc.ok(true)) {
1279 return nullptr ;
1280 }
1281
1282 RooArgList vars(xvar) ;
1283 RooAbsArg* yvar = static_cast<RooAbsArg*>(pc.getObject("yvar")) ;
1284 if (yvar) {
1285 vars.add(*yvar) ;
1286 }
1287 RooAbsArg* zvar = static_cast<RooAbsArg*>(pc.getObject("zvar")) ;
1288 if (zvar) {
1289 vars.add(*zvar) ;
1290 }
1291
1292 auto projObs = pc.getSet("projObs");
1293 RooArgSet* intObs = nullptr ;
1294
1295 bool doScaling = pc.getInt("scaling") ;
1296 Int_t doIntBinning = pc.getInt("intBinning") ;
1297 Int_t doExtended = pc.getInt("extended") ;
1298
1299 // If doExtended is two, selection is automatic, set to 1 of pdf is extended, to zero otherwise
1300 const RooAbsPdf* pdfSelf = dynamic_cast<const RooAbsPdf*>(this) ;
1301 if (!pdfSelf && doExtended == 1) {
1302 coutW(InputArguments) << "RooAbsReal::createHistogram(" << GetName() << ") WARNING extended mode requested for a non-pdf object, ignored" << std::endl ;
1303 doExtended=0 ;
1304 }
1305 if (pdfSelf && doExtended==1 && pdfSelf->extendMode()==RooAbsPdf::CanNotBeExtended) {
1306 coutW(InputArguments) << "RooAbsReal::createHistogram(" << GetName() << ") WARNING extended mode requested for a non-extendable pdf, ignored" << std::endl ;
1307 doExtended=0 ;
1308 }
1309 if (pdfSelf && doExtended==2) {
1310 doExtended = pdfSelf->extendMode()==RooAbsPdf::CanNotBeExtended ? 0 : 1 ;
1311 } else if(!pdfSelf) {
1312 doExtended = 0;
1313 }
1314
1315 const char* compSpec = pc.getString("compSpec") ;
1316 const RooArgSet* compSet = pc.getSet("compSet");
1317 bool haveCompSel = ( (compSpec && strlen(compSpec)>0) || compSet) ;
1318
1319 std::unique_ptr<RooBinning> intBinning;
1320 if (doIntBinning>0) {
1321 // Given RooAbsPdf* pdf and RooRealVar* obs
1322 std::unique_ptr<std::list<double>> bl{binBoundaries(const_cast<RooAbsRealLValue&>(xvar),xvar.getMin(),xvar.getMax())};
1323 if (!bl) {
1324 // Only emit warning when intrinsic binning is explicitly requested
1325 if (doIntBinning==1) {
1326 coutW(InputArguments) << "RooAbsReal::createHistogram(" << GetName()
1327 << ") WARNING, intrinsic model binning requested for histogram, but model does not define bin boundaries, reverting to default binning"<< std::endl ;
1328 }
1329 } else {
1330 if (doIntBinning==2) {
1331 coutI(InputArguments) << "RooAbsReal::createHistogram(" << GetName()
1332 << ") INFO: Model has intrinsic binning definition, selecting that binning for the histogram"<< std::endl ;
1333 }
1334 std::vector<double> edges(bl->size());
1335 int i=0 ;
1336 for (auto const& elem : *bl) { edges[i++] = elem ; }
1337 intBinning = std::make_unique<RooBinning>(bl->size()-1,edges.data()) ;
1338 }
1339 }
1340
1341 RooLinkedList argListCreate(argList) ;
1342 RooCmdConfig::stripCmdList(argListCreate,"Scaling,ProjectedObservables,IntrinsicBinning,SelectCompSet,SelectCompSpec,Extended") ;
1343
1344 TH1* histo(nullptr) ;
1345 if (intBinning) {
1346 RooCmdArg tmp = RooFit::Binning(*intBinning) ;
1347 argListCreate.Add(&tmp) ;
1348 histo = xvar.createHistogram(name,argListCreate) ;
1349 } else {
1350 histo = xvar.createHistogram(name,argListCreate) ;
1351 }
1352
1353 // Do component selection here
1354 if (haveCompSel) {
1355
1356 // Get complete set of tree branch nodes
1357 RooArgSet branchNodeSet ;
1358 branchNodeServerList(&branchNodeSet) ;
1359
1360 // Discard any non-RooAbsReal nodes
1361 for(RooAbsArg * arg : branchNodeSet) {
1362 if (!dynamic_cast<RooAbsReal*>(arg)) {
1363 branchNodeSet.remove(*arg) ;
1364 }
1365 }
1366
1367 std::unique_ptr<RooArgSet> dirSelNodes;
1368 if (compSet) {
1369 dirSelNodes = std::unique_ptr<RooArgSet>{branchNodeSet.selectCommon(*compSet)};
1370 } else {
1371 dirSelNodes = std::unique_ptr<RooArgSet>{branchNodeSet.selectByName(compSpec)};
1372 }
1373 if (!dirSelNodes->empty()) {
1374 coutI(Plotting) << "RooAbsPdf::createHistogram(" << GetName() << ") directly selected PDF components: " << *dirSelNodes << std::endl ;
1375
1376 // Do indirect selection and activate both
1377 plotOnCompSelect(dirSelNodes.get()) ;
1378 } else {
1379 if (compSet) {
1380 coutE(Plotting) << "RooAbsPdf::createHistogram(" << GetName() << ") ERROR: component selection set " << *compSet << " does not match any components of p.d.f." << std::endl ;
1381 } else {
1382 coutE(Plotting) << "RooAbsPdf::createHistogram(" << GetName() << ") ERROR: component selection expression '" << compSpec << "' does not select any components of p.d.f." << std::endl ;
1383 }
1384 return nullptr ;
1385 }
1386 }
1387
1388 double scaleFactor(1.0) ;
1389 if (doExtended) {
1390 scaleFactor = pdfSelf->expectedEvents(vars) ;
1391 doScaling=false ;
1392 }
1393
1394 fillHistogram(histo,vars,scaleFactor,intObs,doScaling,projObs,false) ;
1395
1396 // Deactivate component selection
1397 if (haveCompSel) {
1398 plotOnCompSelect(nullptr) ;
1399 }
1400
1401
1402 return histo ;
1403}
1404
1405
1406////////////////////////////////////////////////////////////////////////////////
1407/// Helper function for plotting of composite p.d.fs. Given
1408/// a set of selected components that should be plotted,
1409/// find all nodes that (in)directly depend on these selected
1410/// nodes. Mark all directly and indirectly selected nodes
1411/// as 'selected' using the selectComp() method
1412
1414{
1415 // Get complete set of tree branch nodes
1416 RooArgSet branchNodeSet;
1417 branchNodeServerList(&branchNodeSet);
1418
1419 // Discard any non-PDF nodes
1420 // Iterate by number because collection is being modified! Iterators may invalidate ...
1421 for (unsigned int i = 0; i < branchNodeSet.size(); ++i) {
1422 const auto arg = branchNodeSet[i];
1423 if (!dynamic_cast<RooAbsReal*>(arg)) {
1424 branchNodeSet.remove(*arg) ;
1425 }
1426 }
1427
1428 // If no set is specified, restored all selection bits to true
1429 if (!selNodes) {
1430 // Reset PDF selection bits to true
1431 for (const auto arg : branchNodeSet) {
1432 static_cast<RooAbsReal*>(arg)->selectComp(true);
1433 }
1434 return ;
1435 }
1436
1437
1438 // Add all nodes below selected nodes that are value servers
1439 RooArgSet tmp;
1440 for (const auto arg : branchNodeSet) {
1441 for (const auto selNode : *selNodes) {
1442 if (selNode->dependsOn(*arg, nullptr, /*valueOnly=*/true)) {
1443 tmp.add(*arg,true);
1444 }
1445 }
1446 }
1447
1448 // Add all nodes that depend on selected nodes by value
1449 for (const auto arg : branchNodeSet) {
1450 if (arg->dependsOn(*selNodes, nullptr, /*valueOnly=*/true)) {
1451 tmp.add(*arg,true);
1452 }
1453 }
1454
1455 tmp.remove(*selNodes, true);
1456 tmp.remove(*this);
1457 selNodes->add(tmp);
1458 coutI(Plotting) << "RooAbsPdf::plotOn(" << GetName() << ") indirectly selected PDF components: " << tmp << std::endl ;
1459
1460 // Set PDF selection bits according to selNodes
1461 for (const auto arg : branchNodeSet) {
1462 bool select = selNodes->find(arg->GetName()) != nullptr;
1463 static_cast<RooAbsReal*>(arg)->selectComp(select);
1464 }
1465}
1466
1467
1468
1469////////////////////////////////////////////////////////////////////////////////
1470/// Plot (project) PDF on specified frame. If a PDF is plotted in an empty frame, it
1471/// will show a unit normalized curve in the frame variable, taken at the present value
1472/// of other observables defined for this PDF.
1473///
1474/// \param[in] frame pointer to RooPlot
1475/// \param[in] arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10 Ordered arguments
1476///
1477/// If a PDF is plotted in a frame in which a dataset has already been plotted, it will
1478/// show a projected curve integrated over all variables that were present in the shown
1479/// dataset except for the one on the x-axis. The normalization of the curve will also
1480/// be adjusted to the event count of the plotted dataset. An informational message
1481/// will be printed for each projection step that is performed.
1482///
1483/// This function takes the following named arguments
1484/// <table>
1485/// <tr><th><th> Projection control
1486/// <tr><td> `Slice(const RooArgSet& set)` <td> Override default projection behaviour by omitting observables listed
1487/// in set from the projection, i.e. by not integrating over these.
1488/// Slicing is usually only sensible in discrete observables, by e.g. creating a slice
1489/// of the PDF at the current value of the category observable.
1490///
1491/// <tr><td> `Slice(RooCategory& cat, const char* label)` <td> Override default projection behaviour by omitting the specified category
1492/// observable from the projection, i.e., by not integrating over all states of this category.
1493/// The slice is positioned at the given label value. To pass multiple Slice() commands, please use the
1494/// Slice(std::map<RooCategory*, std::string> const&) argument explained below.
1495///
1496/// <tr><td> `Slice(std::map<RooCategory*, std::string> const&)` <td> Omits multiple categories from the projection, as explianed above.
1497/// Can be used with initializer lists for convenience, e.g.
1498/// ```{.cpp}
1499/// pdf.plotOn(frame, Slice({{&tagCategory, "2tag"}, {&jetCategory, "3jet"}});
1500/// ```
1501///
1502/// <tr><td> `Project(const RooArgSet& set)` <td> Override default projection behaviour by projecting over observables
1503/// given in the set, ignoring the default projection behavior. Advanced use only.
1504///
1505/// <tr><td> `ProjWData(const RooAbsData& d)` <td> Override default projection _technique_ (integration). For observables present in given dataset
1506/// projection of PDF is achieved by constructing an average over all observable values in given set.
1507/// Consult RooFit plotting tutorial for further explanation of meaning & use of this technique
1508///
1509/// <tr><td> `ProjWData(const RooArgSet& s, const RooAbsData& d)` <td> As above but only consider subset 's' of observables in dataset 'd' for projection through data averaging
1510///
1511/// <tr><td> `ProjectionRange(const char* rn)` <td> Override default range of projection integrals to a different range specified by given range name.
1512/// This technique allows you to project a finite width slice in a real-valued observable
1513///
1514/// <tr><td> `NumCPU(Int_t ncpu)` <td> Number of CPUs to use simultaneously to calculate data-weighted projections (only in combination with ProjWData)
1515///
1516///
1517/// <tr><th><th> Misc content control
1518/// <tr><td> `PrintEvalErrors(Int_t numErr)` <td> Control number of p.d.f evaluation errors printed per curve. A negative
1519/// value suppress output completely, a zero value will only print the error count per p.d.f component,
1520/// a positive value is will print details of each error up to numErr messages per p.d.f component.
1521///
1522/// <tr><td> `EvalErrorValue(double value)` <td> Set curve points at which (pdf) evaluation errors occur to specified value. By default the
1523/// function value is plotted.
1524///
1525/// <tr><td> `Normalization(double scale, ScaleType code)` <td> Adjust normalization by given scale factor. Interpretation of number depends on code:
1526/// - Relative: relative adjustment factor for a normalized function,
1527/// - NumEvent: scale to match given number of events.
1528/// - Raw: relative adjustment factor for an un-normalized function.
1529///
1530/// <tr><td> `Name(const chat* name)` <td> Give curve specified name in frame. Useful if curve is to be referenced later
1531///
1532/// <tr><td> `Asymmetry(const RooCategory& c)` <td> Show the asymmetry of the PDF in given two-state category [F(+)-F(-)] / [F(+)+F(-)] rather than
1533/// the PDF projection. Category must have two states with indices -1 and +1 or three states with
1534/// indices -1,0 and +1.
1535///
1536/// <tr><td> `ShiftToZero(bool flag)` <td> Shift entire curve such that lowest visible point is at exactly zero. Mostly useful when plotting \f$ -\log(L) \f$ or \f$ \chi^2 \f$ distributions
1537///
1538/// <tr><td> `AddTo(const char* name, double_t wgtSelf, double_t wgtOther)` <td> Add constructed projection to already existing curve with given name and relative weight factors
1539/// <tr><td> `Components(const char* names)` <td> When plotting sums of PDFs, plot only the named components (*e.g.* only
1540/// the signal of a signal+background model).
1541/// <tr><td> `Components(const RooArgSet& compSet)` <td> As above, but pass a RooArgSet of the components themselves.
1542///
1543/// <tr><th><th> Plotting control
1544/// <tr><td> `DrawOption(const char* opt)` <td> Select ROOT draw option for resulting TGraph object. Currently supported options are "F" (fill), "L" (line), and "P" (points).
1545/// \note Option "P" will cause RooFit to plot (and treat) this pdf as if it were data! This is intended for plotting "corrected data"-type pdfs such as "data-minus-background" or unfolded datasets.
1546///
1547/// <tr><td> `LineStyle(Int_t style)` <td> Select line style by ROOT line style code, default is solid
1548///
1549/// <tr><td> `LineColor(Int_t color)` <td> Select line color by ROOT color code, default is blue
1550///
1551/// <tr><td> `LineWidth(Int_t width)` <td> Select line with in pixels, default is 3
1552///
1553/// <tr><td> `MarkerStyle(Int_t style)` <td> Select the ROOT marker style, default is 21
1554///
1555/// <tr><td> `MarkerColor(Int_t color)` <td> Select the ROOT marker color, default is black
1556///
1557/// <tr><td> `MarkerSize(double size)` <td> Select the ROOT marker size
1558///
1559/// <tr><td> `FillStyle(Int_t style)` <td> Select fill style, default is not filled. If a filled style is selected, also use VLines()
1560/// to add vertical downward lines at end of curve to ensure proper closure. Add `DrawOption("F")` for filled drawing.
1561/// <tr><td> `FillColor(Int_t color)` <td> Select fill color by ROOT color code
1562///
1563/// <tr><td> `Range(const char* name)` <td> Only draw curve in range defined by given name
1564///
1565/// <tr><td> `Range(double lo, double hi)` <td> Only draw curve in specified range
1566///
1567/// <tr><td> `VLines()` <td> Add vertical lines to y=0 at end points of curve
1568///
1569/// <tr><td> `Precision(double eps)` <td> Control precision of drawn curve w.r.t to scale of plot, default is 1e-3. Higher precision
1570/// will result in more and more densely spaced curve points
1571///
1572/// <tr><td> `Invisible(bool flag)` <td> Add curve to frame, but do not display. Useful in combination AddTo()
1573///
1574/// <tr><td> `VisualizeError(const RooFitResult& fitres, double Z=1, bool linearMethod=true)`
1575/// <td> Visualize the uncertainty on the parameters, as given in fitres, at 'Z' sigma'. 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. 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
1576///
1577/// <tr><td> `VisualizeError(const RooFitResult& fitres, const RooArgSet& param, double Z=1, bool linearMethod=true)`
1578/// <td> Visualize the uncertainty on the subset of parameters 'param', as given in fitres, at 'Z' sigma'
1579/// </table>
1580///
1581/// Details on error band visualization
1582/// -----------------------------------
1583/// *VisualizeError() uses plotOnWithErrorBand(). Documentation of the latter:*
1584/// \see plotOnWithErrorBand()
1585
1586RooPlot* RooAbsReal::plotOn(RooPlot* frame, const RooCmdArg& arg1, const RooCmdArg& arg2,
1587 const RooCmdArg& arg3, const RooCmdArg& arg4,
1588 const RooCmdArg& arg5, const RooCmdArg& arg6,
1589 const RooCmdArg& arg7, const RooCmdArg& arg8,
1590 const RooCmdArg& arg9, const RooCmdArg& arg10) const
1591{
1593 l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
1594 l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
1595 l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
1596 l.Add((TObject*)&arg7) ; l.Add((TObject*)&arg8) ;
1597 l.Add((TObject*)&arg9) ; l.Add((TObject*)&arg10) ;
1598 return plotOn(frame,l) ;
1599}
1600
1601
1602
1603////////////////////////////////////////////////////////////////////////////////
1604/// Internal back-end function of plotOn() with named arguments
1605
1607{
1608 // Special handling here if argList contains RangeWithName argument with multiple
1609 // range names -- Need to translate this call into multiple calls
1610
1611 RooCmdArg* rcmd = static_cast<RooCmdArg*>(argList.FindObject("RangeWithName")) ;
1612 if (rcmd && TString(rcmd->getString(0)).Contains(",")) {
1613
1614 // List joint ranges as choice of normalization for all later processing
1615 RooCmdArg rnorm = RooFit::NormRange(rcmd->getString(0)) ;
1616 argList.Add(&rnorm) ;
1617
1618 for (const auto& rangeString : ROOT::Split(rcmd->getString(0), ",")) {
1619 // Process each range with a separate command with a single range to be plotted
1620 rcmd->setString(0, rangeString.c_str());
1621 RooAbsReal::plotOn(frame,argList);
1622 }
1623 return frame ;
1624
1625 }
1626
1627 // Define configuration for this method
1628 RooCmdConfig pc("RooAbsReal::plotOn(" + std::string(GetName()) + ")");
1629 pc.defineString("drawOption","DrawOption",0,"L") ;
1630 pc.defineString("projectionRangeName","ProjectionRange",0,"",true) ;
1631 pc.defineString("curveNameSuffix","CurveNameSuffix",0,"") ;
1632 pc.defineString("sliceCatState","SliceCat",0,"",true) ;
1633 pc.defineDouble("scaleFactor","Normalization",0,1.0) ;
1634 pc.defineInt("scaleType","Normalization",0,Relative) ;
1635 pc.defineSet("sliceSet","SliceVars",0) ;
1636 pc.defineObject("sliceCatList","SliceCat",0,nullptr,true) ;
1637 // This dummy is needed for plotOn to recognize the "SliceCatMany" command.
1638 // It is not used directly, but the "SliceCat" commands are nested in it.
1639 // Removing this dummy definition results in "ERROR: unrecognized command: SliceCatMany".
1640 pc.defineObject("dummy1","SliceCatMany",0) ;
1641 pc.defineSet("projSet","Project",0) ;
1642 pc.defineObject("asymCat","Asymmetry",0) ;
1643 pc.defineDouble("precision","Precision",0,1e-3) ;
1644 pc.defineDouble("evalErrorVal","EvalErrorValue",0,0) ;
1645 pc.defineInt("doEvalError","EvalErrorValue",0,0) ;
1646 pc.defineInt("shiftToZero","ShiftToZero",0,0) ;
1647 pc.defineSet("projDataSet","ProjData",0) ;
1648 pc.defineObject("projData","ProjData",1) ;
1649 pc.defineObject("errorFR","VisualizeError",0) ;
1650 pc.defineDouble("errorZ","VisualizeError",0,1.) ;
1651 pc.defineSet("errorPars","VisualizeError",0) ;
1652 pc.defineInt("linearMethod","VisualizeError",0,0) ;
1653 pc.defineInt("binProjData","ProjData",0,0) ;
1654 pc.defineDouble("rangeLo","Range",0,-999.) ;
1655 pc.defineDouble("rangeHi","Range",1,-999.) ;
1656 pc.defineInt("numee","PrintEvalErrors",0,10) ;
1657 pc.defineInt("rangeAdjustNorm","Range",0,0) ;
1658 pc.defineInt("rangeWNAdjustNorm","RangeWithName",0,0) ;
1659 pc.defineInt("VLines","VLines",0,2) ; // 2==ExtendedWings
1660 pc.defineString("rangeName","RangeWithName",0,"") ;
1661 pc.defineString("normRangeName","NormRange",0,"") ;
1662 pc.defineInt("markerColor","MarkerColor",0,-999) ;
1663 pc.defineInt("markerStyle","MarkerStyle",0,-999) ;
1664 pc.defineDouble("markerSize","MarkerSize",0,-999) ;
1665 pc.defineInt("lineColor","LineColor",0,-999) ;
1666 pc.defineInt("lineStyle","LineStyle",0,-999) ;
1667 pc.defineInt("lineWidth","LineWidth",0,-999) ;
1668 pc.defineInt("fillColor","FillColor",0,-999) ;
1669 pc.defineInt("fillStyle","FillStyle",0,-999) ;
1670 pc.defineString("curveName","Name",0,"") ;
1671 pc.defineInt("curveInvisible","Invisible",0,0) ;
1672 pc.defineInt("showProg","ShowProgress",0,0) ;
1673 pc.defineInt("numCPU","NumCPU",0,1) ;
1674 pc.defineInt("interleave","NumCPU",1,0) ;
1675 pc.defineString("addToCurveName","AddTo",0,"") ;
1676 pc.defineDouble("addToWgtSelf","AddTo",0,1.) ;
1677 pc.defineDouble("addToWgtOther","AddTo",1,1.) ;
1678 pc.defineInt("moveToBack","MoveToBack",0,0) ;
1679 pc.defineMutex("SliceVars","Project") ;
1680 pc.defineMutex("AddTo","Asymmetry") ;
1681 pc.defineMutex("Range","RangeWithName") ;
1682 pc.defineMutex("VisualizeError","VisualizeErrorData") ;
1683
1684 // Process & check varargs
1685 pc.process(argList) ;
1686 if (!pc.ok(true)) {
1687 return frame ;
1688 }
1689
1690 TString drawOpt(pc.getString("drawOption"));
1691
1692 RooFitResult* errFR = static_cast<RooFitResult*>(pc.getObject("errorFR")) ;
1693 if (!drawOpt.Contains("P") && errFR) {
1694 return plotOnWithErrorBand(frame, *errFR, pc.getDouble("errorZ"), pc.getSet("errorPars"), argList,
1695 pc.getInt("linearMethod"));
1696 }
1697
1698 // Extract values from named arguments
1699 PlotOpt o ;
1700 o.numee = pc.getInt("numee") ;
1701 o.drawOptions = drawOpt.Data();
1702 o.curveNameSuffix = pc.getString("curveNameSuffix") ;
1703 o.scaleFactor = pc.getDouble("scaleFactor") ;
1704 o.stype = (ScaleType) pc.getInt("scaleType") ;
1705 o.projData = static_cast<const RooAbsData*>(pc.getObject("projData")) ;
1706 o.binProjData = pc.getInt("binProjData") ;
1707 o.projDataSet = pc.getSet("projDataSet");
1708 o.numCPU = pc.getInt("numCPU") ;
1709 o.interleave = (RooFit::MPSplit) pc.getInt("interleave") ;
1710 o.eeval = pc.getDouble("evalErrorVal") ;
1711 o.doeeval = pc.getInt("doEvalError") ;
1712 o.errorFR = errFR;
1713
1714 const RooArgSet* sliceSetTmp = pc.getSet("sliceSet");
1715 std::unique_ptr<RooArgSet> sliceSet{sliceSetTmp ? static_cast<RooArgSet*>(sliceSetTmp->Clone()) : nullptr};
1716 const RooArgSet* projSet = pc.getSet("projSet") ;
1717 const RooAbsCategoryLValue* asymCat = static_cast<const RooAbsCategoryLValue*>(pc.getObject("asymCat")) ;
1718
1719
1720 // Look for category slice arguments and add them to the master slice list if found
1721 if (const char* sliceCatState = pc.getString("sliceCatState",nullptr,true)) {
1722 const RooLinkedList& sliceCatList = pc.getObjectList("sliceCatList") ;
1723
1724 // Make the master slice set if it doesnt exist
1725 if (!sliceSet) {
1726 sliceSet = std::make_unique<RooArgSet>();
1727 }
1728
1729 // Loop over all categories provided by (multiple) Slice() arguments
1730 auto iter = sliceCatList.begin();
1731 for (auto const& catToken : ROOT::Split(sliceCatState, ",")) {
1732 if (auto scat = static_cast<RooCategory*>(*iter)) {
1733 // Set the slice position to the value indicate by slabel
1734 scat->setLabel(catToken);
1735 // Add the slice category to the master slice set
1736 sliceSet->add(*scat,false) ;
1737 }
1738 ++iter;
1739 }
1740 }
1741
1742 o.precision = pc.getDouble("precision") ;
1743 o.shiftToZero = (pc.getInt("shiftToZero")!=0) ;
1744 Int_t vlines = pc.getInt("VLines");
1745 if (pc.hasProcessed("Range")) {
1746 o.rangeLo = pc.getDouble("rangeLo") ;
1747 o.rangeHi = pc.getDouble("rangeHi") ;
1748 o.postRangeFracScale = pc.getInt("rangeAdjustNorm") ;
1749 if (vlines==2) vlines=0 ; // Default is NoWings if range was specified
1750 } else if (pc.hasProcessed("RangeWithName")) {
1751 o.normRangeName = pc.getString("rangeName",nullptr,true) ;
1752 o.rangeLo = frame->getPlotVar()->getMin(pc.getString("rangeName",nullptr,true)) ;
1753 o.rangeHi = frame->getPlotVar()->getMax(pc.getString("rangeName",nullptr,true)) ;
1754 o.postRangeFracScale = pc.getInt("rangeWNAdjustNorm") ;
1755 if (vlines==2) vlines=0 ; // Default is NoWings if range was specified
1756 }
1757
1758
1759 // If separate normalization range was specified this overrides previous settings
1760 if (pc.hasProcessed("NormRange")) {
1761 o.normRangeName = pc.getString("normRangeName") ;
1762 o.postRangeFracScale = true ;
1763 }
1764
1765 o.wmode = (vlines==2)?RooCurve::Extended:(vlines==1?RooCurve::Straight:RooCurve::NoWings) ;
1766 o.projectionRangeName = pc.getString("projectionRangeName",nullptr,true) ;
1767 o.curveName = pc.getString("curveName",nullptr,true) ;
1768 o.curveInvisible = pc.getInt("curveInvisible") ;
1769 o.progress = pc.getInt("showProg") ;
1770 o.addToCurveName = pc.getString("addToCurveName",nullptr,true) ;
1771 o.addToWgtSelf = pc.getDouble("addToWgtSelf") ;
1772 o.addToWgtOther = pc.getDouble("addToWgtOther") ;
1773
1775 coutE(InputArguments) << "RooAbsReal::plotOn(" << GetName() << ") cannot find existing curve " << o.addToCurveName << " to add to in RooPlot" << std::endl ;
1776 return frame ;
1777 }
1778
1779 RooArgSet projectedVars ;
1780 if (sliceSet) {
1781 cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") Preprocessing: have slice " << *sliceSet << std::endl ;
1782
1783 makeProjectionSet(frame->getPlotVar(),frame->getNormVars(),projectedVars,true) ;
1784
1785 // Take out the sliced variables
1786 for (const auto sliceArg : *sliceSet) {
1787 if (RooAbsArg* arg = projectedVars.find(sliceArg->GetName())) {
1788 projectedVars.remove(*arg) ;
1789 } else {
1790 coutI(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") slice variable "
1791 << sliceArg->GetName() << " was not projected anyway" << std::endl ;
1792 }
1793 }
1794 } else if (projSet) {
1795 cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") Preprocessing: have projSet " << *projSet << std::endl ;
1796 makeProjectionSet(frame->getPlotVar(),projSet,projectedVars,false) ;
1797 } else {
1798 cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") Preprocessing: have neither sliceSet nor projSet " << std::endl ;
1799 makeProjectionSet(frame->getPlotVar(),frame->getNormVars(),projectedVars,true) ;
1800 }
1801 o.projSet = &projectedVars ;
1802
1803 cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") Preprocessing: projectedVars = " << projectedVars << std::endl ;
1804
1805
1806 // Forward to actual calculation
1807 RooPlot* ret = asymCat ? RooAbsReal::plotAsymOn(frame,*asymCat,o) : RooAbsReal::plotOn(frame,o);
1808
1809 // Optionally adjust line/fill attributes
1810 Int_t lineColor = pc.getInt("lineColor") ;
1811 Int_t lineStyle = pc.getInt("lineStyle") ;
1812 Int_t lineWidth = pc.getInt("lineWidth") ;
1813 Int_t markerColor = pc.getInt("markerColor") ;
1814 Int_t markerStyle = pc.getInt("markerStyle") ;
1815 Size_t markerSize = pc.getDouble("markerSize") ;
1816 Int_t fillColor = pc.getInt("fillColor") ;
1817 Int_t fillStyle = pc.getInt("fillStyle") ;
1818 if (lineColor!=-999) ret->getAttLine()->SetLineColor(lineColor) ;
1819 if (lineStyle!=-999) ret->getAttLine()->SetLineStyle(lineStyle) ;
1820 if (lineWidth!=-999) ret->getAttLine()->SetLineWidth(lineWidth) ;
1821 if (fillColor!=-999) ret->getAttFill()->SetFillColor(fillColor) ;
1822 if (fillStyle!=-999) ret->getAttFill()->SetFillStyle(fillStyle) ;
1823 if (markerColor!=-999) ret->getAttMarker()->SetMarkerColor(markerColor) ;
1824 if (markerStyle!=-999) ret->getAttMarker()->SetMarkerStyle(markerStyle) ;
1825 if (markerSize!=-999) ret->getAttMarker()->SetMarkerSize(markerSize) ;
1826
1827 if ((fillColor != -999 || fillStyle != -999) && !drawOpt.Contains("F")) {
1828 coutW(Plotting) << "Fill color or style was set for plotting \"" << GetName()
1829 << "\", but these only have an effect when 'DrawOption(\"F\")' for fill is used at the same time." << std::endl;
1830 }
1831
1832 // Move last inserted object to back to drawing stack if requested
1833 if (pc.getInt("moveToBack") && frame->numItems()>1) {
1834 frame->drawBefore(frame->getObject(0)->GetName(), frame->getCurve()->GetName());
1835 }
1836
1837 return ret ;
1838}
1839
1840
1841
1842/// Plotting engine function for internal use
1843///
1844/// Plot ourselves on given frame. If frame contains a histogram, all dimensions of the plotted
1845/// function that occur in the previously plotted dataset are projected via partial integration,
1846/// otherwise no projections are performed. Optionally, certain projections can be performed
1847/// by summing over the values present in a provided dataset ('projData'), to correctly
1848/// project out data dependents that are not properly described by the PDF (e.g. per-event errors).
1849///
1850/// The functions value can be multiplied with an optional scale factor. The interpretation
1851/// of the scale factor is unique for generic real functions, for PDFs there are various interpretations
1852/// possible, which can be selection with 'stype' (see RooAbsPdf::plotOn() for details).
1853///
1854/// The default projection behaviour can be overridden by supplying an optional set of dependents
1855/// to project via RooFit command arguments.
1856//_____________________________________________________________________________
1857// coverity[PASS_BY_VALUE]
1859{
1860 // Sanity checks
1861 if (plotSanityChecks(frame)) return frame ;
1862
1863 // ProjDataVars is either all projData observables, or the user indicated subset of it
1864 RooArgSet projDataVars ;
1865 if (o.projData) {
1866 cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") have ProjData with observables = " << *o.projData->get() << std::endl ;
1867 if (o.projDataSet) {
1868 projDataVars.add(*std::unique_ptr<RooArgSet>{o.projData->get()->selectCommon(*o.projDataSet)}) ;
1869 cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") have ProjDataSet = " << *o.projDataSet << " will only use this subset of projData" << std::endl ;
1870 } else {
1871 cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") using full ProjData" << std::endl ;
1872 projDataVars.add(*o.projData->get()) ;
1873 }
1874 }
1875
1876 cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") ProjDataVars = " << projDataVars << std::endl ;
1877
1878 // Make list of variables to be projected
1879 RooArgSet projectedVars ;
1880 RooArgSet sliceSet ;
1881 if (o.projSet) {
1882 cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") have input projSet = " << *o.projSet << std::endl ;
1883 makeProjectionSet(frame->getPlotVar(),o.projSet,projectedVars,false) ;
1884 cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") calculated projectedVars = " << *o.projSet << std::endl ;
1885
1886 // Print list of non-projected variables
1887 if (frame->getNormVars()) {
1888 RooArgSet sliceSetTmp;
1889 getObservables(frame->getNormVars(), sliceSetTmp) ;
1890
1891 cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") frame->getNormVars() that are also observables = " << sliceSetTmp << std::endl ;
1892
1893 sliceSetTmp.remove(projectedVars,true,true) ;
1894 sliceSetTmp.remove(*frame->getPlotVar(),true,true) ;
1895
1896 if (o.projData) {
1897 std::unique_ptr<RooArgSet> tmp{projDataVars.selectCommon(*o.projSet)};
1898 sliceSetTmp.remove(*tmp,true,true) ;
1899 }
1900
1901 if (!sliceSetTmp.empty()) {
1902 coutI(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") plot on "
1903 << frame->getPlotVar()->GetName() << " represents a slice in " << sliceSetTmp << std::endl ;
1904 }
1905 sliceSet.add(sliceSetTmp) ;
1906 }
1907 } else {
1908 makeProjectionSet(frame->getPlotVar(),frame->getNormVars(),projectedVars,true) ;
1909 }
1910
1911 cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") projectedVars = " << projectedVars << " sliceSet = " << sliceSet << std::endl ;
1912
1913
1914 RooArgSet* projDataNeededVars = nullptr ;
1915 // Take out data-projected dependents from projectedVars
1916 if (o.projData) {
1917 projDataNeededVars = projectedVars.selectCommon(projDataVars);
1918 projectedVars.remove(projDataVars,true,true) ;
1919 }
1920
1921 // Get the plot variable and remember its original value
1922 auto* plotVar = static_cast<RooRealVar*>(frame->getPlotVar());
1923 double oldPlotVarVal = plotVar->getVal();
1924
1925 // Inform user about projections
1926 if (!projectedVars.empty()) {
1927 coutI(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") plot on " << plotVar->GetName()
1928 << " integrates over variables " << projectedVars
1929 << (o.projectionRangeName?Form(" in range %s",o.projectionRangeName):"") << std::endl;
1930 }
1931 if (projDataNeededVars && !projDataNeededVars->empty()) {
1932 coutI(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") plot on " << plotVar->GetName()
1933 << " averages using data variables " << *projDataNeededVars << std::endl ;
1934 }
1935
1936 // Create projection integral
1937 RooArgSet* projectionCompList = nullptr ;
1938
1939 RooArgSet deps;
1940 getObservables(frame->getNormVars(), deps) ;
1941 deps.remove(projectedVars,true,true) ;
1942 if (projDataNeededVars) {
1943 deps.remove(*projDataNeededVars,true,true) ;
1944 }
1945 deps.remove(*plotVar,true,true) ;
1946 deps.add(*plotVar) ;
1947
1948 // Now that we have the final set of dependents, call checkObservables()
1949
1950 // WVE take out conditional observables
1951 if (checkObservables(&deps)) {
1952 coutE(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") error in checkObservables, abort" << std::endl ;
1953 if (projDataNeededVars) delete projDataNeededVars ;
1954 return frame ;
1955 }
1956
1957 RooAbsReal *projection = const_cast<RooAbsReal*>(createPlotProjection(deps, &projectedVars, projectionCompList, o.projectionRangeName));
1958 cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") plot projection object is " << projection->GetName() << std::endl ;
1959 if (dologD(Plotting)) {
1960 projection->printStream(ccoutD(Plotting),0,kVerbose) ;
1961 }
1962
1963 // Always fix RooAddPdf normalizations
1964 RooArgSet fullNormSet(deps) ;
1965 fullNormSet.add(projectedVars) ;
1966 if (projDataNeededVars && !projDataNeededVars->empty()) {
1967 fullNormSet.add(*projDataNeededVars) ;
1968 }
1969
1970 std::unique_ptr<RooArgSet> projectionComponents(projection->getComponents());
1971 for(auto * pdf : dynamic_range_cast<RooAbsPdf*>(*projectionComponents)) {
1972 if (pdf) {
1973 pdf->selectNormalization(&fullNormSet) ;
1974 }
1975 }
1976
1977 // Apply data projection, if requested
1978 if (o.projData && projDataNeededVars && !projDataNeededVars->empty()) {
1979
1980 // If data set contains more rows than needed, make reduced copy first
1981 RooAbsData* projDataSel = const_cast<RooAbsData*>(o.projData);
1982 std::unique_ptr<RooAbsData> projDataSelOwned;
1983
1984 if (projDataNeededVars->size() < o.projData->get()->size()) {
1985
1986 // Determine if there are any slice variables in the projection set
1987 std::unique_ptr<RooArgSet> sliceDataSet{sliceSet.selectCommon(*o.projData->get())};
1988 TString cutString ;
1989 if (!sliceDataSet->empty()) {
1990 bool first(true) ;
1991 for(RooAbsArg * sliceVar : *sliceDataSet) {
1992 if (!first) {
1993 cutString.Append("&&") ;
1994 } else {
1995 first=false ;
1996 }
1997
1998 RooAbsRealLValue* real ;
2000 if ((real = dynamic_cast<RooAbsRealLValue*>(sliceVar))) {
2001 cutString.Append(Form("%s==%f",real->GetName(),real->getVal())) ;
2002 } else if ((cat = dynamic_cast<RooAbsCategoryLValue*>(sliceVar))) {
2003 cutString.Append(Form("%s==%d",cat->GetName(),cat->getCurrentIndex())) ;
2004 }
2005 }
2006 }
2007
2008 if (!cutString.IsNull()) {
2009 coutI(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") reducing given projection dataset to entries with " << cutString << std::endl ;
2010 }
2011 projDataSelOwned = std::unique_ptr<RooAbsData>{const_cast<RooAbsData*>(o.projData)->reduce(*projDataNeededVars, cutString.IsNull() ? nullptr : cutString)};
2012 projDataSel = projDataSelOwned.get();
2013 coutI(Plotting) << "RooAbsReal::plotOn(" << GetName()
2014 << ") only the following components of the projection data will be used: " << *projDataNeededVars << std::endl ;
2015 }
2016
2017 // Request binning of unbinned projection dataset that consists exclusively of category observables
2018 if (!o.binProjData && dynamic_cast<RooDataSet*>(projDataSel)!=nullptr) {
2019
2020 // Determine if dataset contains only categories
2021 bool allCat(true) ;
2022 for(RooAbsArg * arg2 : *projDataSel->get()) {
2023 if (!dynamic_cast<RooCategory*>(arg2)) allCat = false ;
2024 }
2025 if (allCat) {
2026 o.binProjData = true ;
2027 coutI(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") unbinned projection dataset consist only of discrete variables,"
2028 << " performing projection with binned copy for optimization." << std::endl ;
2029
2030 }
2031 }
2032
2033 // Bin projection dataset if requested
2034 if (o.binProjData) {
2035 projDataSelOwned = std::make_unique<RooDataHist>(std::string(projDataSel->GetName()) + "_binned","Binned projection data",*projDataSel->get(),*projDataSel);
2036 projDataSel = projDataSelOwned.get();
2037 }
2038
2039 // Construct scaled data weighted average
2040 ScaledDataWeightedAverage scaleBind{*projection, *projDataSel, o.scaleFactor, *plotVar};
2041
2042 // Set default range, if not specified
2043 if (o.rangeLo==0 && o.rangeHi==0) {
2044 o.rangeLo = frame->GetXaxis()->GetXmin() ;
2045 o.rangeHi = frame->GetXaxis()->GetXmax() ;
2046 }
2047
2048 // Construct name of curve for data weighed average
2049 std::string curveName(projection->GetName()) ;
2050 curveName.append("_DataAvg[" + projDataSel->get()->contentsString() + "]");
2051 // Append slice set specification if any
2052 if (!sliceSet.empty()) {
2053 curveName.append("_Slice[" + sliceSet.contentsString() + "]");
2054 }
2055 // Append any suffixes imported from RooAbsPdf::plotOn
2056 if (o.curveNameSuffix) {
2057 curveName.append(o.curveNameSuffix) ;
2058 }
2059
2060 // Curve constructor for data weighted average
2062 RooCurve *curve = new RooCurve(projection->GetName(),projection->GetTitle(),scaleBind,
2065
2066 curve->SetName(curveName.c_str()) ;
2067
2068 // Add self to other curve if requested
2069 if (o.addToCurveName) {
2070 RooCurve* otherCurve = static_cast<RooCurve*>(frame->findObject(o.addToCurveName,RooCurve::Class())) ;
2071
2072 // Curve constructor for sum of curves
2073 RooCurve* sumCurve = new RooCurve(projection->GetName(),projection->GetTitle(),*curve,*otherCurve,o.addToWgtSelf,o.addToWgtOther) ;
2074 sumCurve->SetName(Form("%s_PLUS_%s",curve->GetName(),otherCurve->GetName())) ;
2075 delete curve ;
2076 curve = sumCurve ;
2077
2078 }
2079
2080 if (o.curveName) {
2081 curve->SetName(o.curveName) ;
2082 }
2083
2084 // add this new curve to the specified plot frame
2085 frame->addPlotable(curve, o.drawOptions, o.curveInvisible);
2086
2087 } else {
2088
2089 // Set default range, if not specified
2090 if (o.rangeLo==0 && o.rangeHi==0) {
2091 o.rangeLo = frame->GetXaxis()->GetXmin() ;
2092 o.rangeHi = frame->GetXaxis()->GetXmax() ;
2093 }
2094
2095 // Calculate a posteriori range fraction scaling if requested (2nd part of normalization correction for
2096 // result fit on subrange of data)
2097 if (o.postRangeFracScale) {
2098 if (!o.normRangeName) {
2099 o.normRangeName = "plotRange" ;
2100 plotVar->setRange("plotRange",o.rangeLo,o.rangeHi) ;
2101 }
2102
2103 // Evaluate fractional correction integral always on full p.d.f, not component.
2104 GlobalSelectComponentRAII selectCompRAII(true);
2105 std::unique_ptr<RooAbsReal> intFrac{projection->createIntegral(*plotVar,*plotVar,o.normRangeName)};
2106 if(o.stype != RooAbsReal::Raw || this->InheritsFrom(RooAbsPdf::Class())){
2107 // this scaling should only be !=1 when plotting partial ranges
2108 // still, raw means raw
2109 o.scaleFactor /= intFrac->getVal() ;
2110 }
2111 }
2112
2113 // create a new curve of our function using the clone to do the evaluations
2114 // Curve constructor for regular projections
2115
2116 // Set default name of curve
2117 std::string curveName(projection->GetName()) ;
2118 if (!sliceSet.empty()) {
2119 curveName.append("_Slice[" + sliceSet.contentsString() + "]");
2120 }
2121 if (o.curveNameSuffix) {
2122 // Append any suffixes imported from RooAbsPdf::plotOn
2123 curveName.append(o.curveNameSuffix) ;
2124 }
2125
2126 TString opt(o.drawOptions);
2127 if(opt.Contains("P")){
2129 RooHist *graph= new RooHist(*projection,*plotVar,1.,o.scaleFactor,frame->getNormVars(),o.errorFR);
2131
2132 // Override name of curve by user name, if specified
2133 if (o.curveName) {
2134 graph->SetName(o.curveName) ;
2135 }
2136
2137 // add this new curve to the specified plot frame
2139 } else {
2141 RooCurve *curve = new RooCurve(*projection,*plotVar,o.rangeLo,o.rangeHi,frame->GetNbinsX(),
2144 curve->SetName(curveName.c_str()) ;
2145
2146 // Add self to other curve if requested
2147 if (o.addToCurveName) {
2148 RooCurve* otherCurve = static_cast<RooCurve*>(frame->findObject(o.addToCurveName,RooCurve::Class())) ;
2149 RooCurve* sumCurve = new RooCurve(projection->GetName(),projection->GetTitle(),*curve,*otherCurve,o.addToWgtSelf,o.addToWgtOther) ;
2150 sumCurve->SetName(Form("%s_PLUS_%s",curve->GetName(),otherCurve->GetName())) ;
2151 delete curve ;
2152 curve = sumCurve ;
2153 }
2154
2155 // Override name of curve by user name, if specified
2156 if (o.curveName) {
2157 curve->SetName(o.curveName) ;
2158 }
2159
2160 // add this new curve to the specified plot frame
2161 frame->addPlotable(curve, o.drawOptions, o.curveInvisible);
2162 }
2163 }
2164
2165 if (projDataNeededVars) delete projDataNeededVars ;
2166 delete projectionCompList ;
2167 plotVar->setVal(oldPlotVarVal); // reset the plot variable value to not disturb the original state
2168 return frame;
2169}
2170
2171
2172//_____________________________________________________________________________
2173// coverity[PASS_BY_VALUE]
2175
2176{
2177 // Plotting engine for asymmetries. Implements the functionality if plotOn(frame,Asymmetry(...)))
2178 //
2179 // Plot asymmetry of ourselves, defined as
2180 //
2181 // asym = f(asymCat=-1) - f(asymCat=+1) / ( f(asymCat=-1) + f(asymCat=+1) )
2182 //
2183 // on frame. If frame contains a histogram, all dimensions of the plotted
2184 // asymmetry function that occur in the previously plotted dataset are projected via partial integration.
2185 // Otherwise no projections are performed,
2186 //
2187 // The asymmetry function can be multiplied with an optional scale factor. The default projection
2188 // behaviour can be overridden by supplying an optional set of dependents to project.
2189
2190 // Sanity checks
2191 if (plotSanityChecks(frame)) return frame ;
2192
2193 // ProjDataVars is either all projData observables, or the user indicated subset of it
2194 RooArgSet projDataVars ;
2195 if (o.projData) {
2196 if (o.projDataSet) {
2197 std::unique_ptr<RooArgSet> tmp{o.projData->get()->selectCommon(*o.projDataSet)};
2198 projDataVars.add(*tmp) ;
2199 } else {
2200 projDataVars.add(*o.projData->get()) ;
2201 }
2202 }
2203
2204 // Must depend on asymCat
2205 if (!dependsOn(asymCat)) {
2206 coutE(Plotting) << "RooAbsReal::plotAsymOn(" << GetName()
2207 << ") function doesn't depend on asymmetry category " << asymCat.GetName() << std::endl ;
2208 return frame ;
2209 }
2210
2211 // asymCat must be a signCat
2212 if (!asymCat.isSignType()) {
2213 coutE(Plotting) << "RooAbsReal::plotAsymOn(" << GetName()
2214 << ") asymmetry category must have 2 or 3 states with index values -1,0,1" << std::endl ;
2215 return frame ;
2216 }
2217
2218 // Make list of variables to be projected
2219 RooArgSet projectedVars ;
2220 RooArgSet sliceSet ;
2221 if (o.projSet) {
2222 makeProjectionSet(frame->getPlotVar(),o.projSet,projectedVars,false) ;
2223
2224 // Print list of non-projected variables
2225 if (frame->getNormVars()) {
2226 RooArgSet sliceSetTmp;
2227 getObservables(frame->getNormVars(), sliceSetTmp) ;
2228 sliceSetTmp.remove(projectedVars,true,true) ;
2229 sliceSetTmp.remove(*frame->getPlotVar(),true,true) ;
2230
2231 if (o.projData) {
2232 std::unique_ptr<RooArgSet> tmp{projDataVars.selectCommon(*o.projSet)};
2233 sliceSetTmp.remove(*tmp,true,true) ;
2234 }
2235
2236 if (!sliceSetTmp.empty()) {
2237 coutI(Plotting) << "RooAbsReal::plotAsymOn(" << GetName() << ") plot on "
2238 << frame->getPlotVar()->GetName() << " represents a slice in " << sliceSetTmp << std::endl ;
2239 }
2240 sliceSet.add(sliceSetTmp) ;
2241 }
2242 } else {
2243 makeProjectionSet(frame->getPlotVar(),frame->getNormVars(),projectedVars,true) ;
2244 }
2245
2246
2247 // Take out data-projected dependens from projectedVars
2248 RooArgSet* projDataNeededVars = nullptr ;
2249 if (o.projData) {
2250 projDataNeededVars = projectedVars.selectCommon(projDataVars);
2251 projectedVars.remove(projDataVars,true,true) ;
2252 }
2253
2254 // Take out plotted asymmetry from projection
2255 if (projectedVars.find(asymCat.GetName())) {
2256 projectedVars.remove(*projectedVars.find(asymCat.GetName())) ;
2257 }
2258
2259 // Clone the plot variable
2260 RooAbsReal* realVar = static_cast<RooRealVar*>(frame->getPlotVar()) ;
2261 RooRealVar* plotVar = static_cast<RooRealVar*>(realVar->Clone()) ;
2262
2263 // Inform user about projections
2264 if (!projectedVars.empty()) {
2265 coutI(Plotting) << "RooAbsReal::plotAsymOn(" << GetName() << ") plot on " << plotVar->GetName()
2266 << " projects variables " << projectedVars << std::endl ;
2267 }
2268 if (projDataNeededVars && !projDataNeededVars->empty()) {
2269 coutI(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") plot on " << plotVar->GetName()
2270 << " averages using data variables "<< *projDataNeededVars << std::endl ;
2271 }
2272
2273
2274 // Customize two copies of projection with fixed negative and positive asymmetry
2275 std::unique_ptr<RooAbsCategoryLValue> asymPos{static_cast<RooAbsCategoryLValue*>(asymCat.Clone("asym_pos"))};
2276 std::unique_ptr<RooAbsCategoryLValue> asymNeg{static_cast<RooAbsCategoryLValue*>(asymCat.Clone("asym_neg"))};
2277 asymPos->setIndex(1) ;
2278 asymNeg->setIndex(-1) ;
2279 RooCustomizer custPos{*this,"pos"};
2280 RooCustomizer custNeg{*this,"neg"};
2281 //custPos->setOwning(true) ;
2282 //custNeg->setOwning(true) ;
2283 custPos.replaceArg(asymCat,*asymPos) ;
2284 custNeg.replaceArg(asymCat,*asymNeg) ;
2285 std::unique_ptr<RooAbsReal> funcPos{static_cast<RooAbsReal*>(custPos.build())};
2286 std::unique_ptr<RooAbsReal> funcNeg{static_cast<RooAbsReal*>(custNeg.build())};
2287
2288 // Create projection integral
2289 RooArgSet *posProjCompList;
2290 RooArgSet *negProjCompList;
2291
2292 // Add projDataVars to normalized dependents of projection
2293 // This is needed only for asymmetries (why?)
2294 RooArgSet depPos(*plotVar,*asymPos) ;
2295 RooArgSet depNeg(*plotVar,*asymNeg) ;
2296 depPos.add(projDataVars) ;
2297 depNeg.add(projDataVars) ;
2298
2299 const RooAbsReal *posProj = funcPos->createPlotProjection(depPos, &projectedVars, posProjCompList, o.projectionRangeName) ;
2300 const RooAbsReal *negProj = funcNeg->createPlotProjection(depNeg, &projectedVars, negProjCompList, o.projectionRangeName) ;
2301 if (!posProj || !negProj) {
2302 coutE(Plotting) << "RooAbsReal::plotAsymOn(" << GetName() << ") Unable to create projections, abort" << std::endl ;
2303 return frame ;
2304 }
2305
2306 // Create a RooFormulaVar representing the asymmetry
2307 TString asymName(GetName()) ;
2308 asymName.Append("_Asym[") ;
2309 asymName.Append(asymCat.GetName()) ;
2310 asymName.Append("]") ;
2311 TString asymTitle(asymCat.GetName()) ;
2312 asymTitle.Append(" Asymmetry of ") ;
2313 asymTitle.Append(GetTitle()) ;
2314 RooFormulaVar funcAsym{asymName,asymTitle,"(@0-@1)/(@0+@1)",RooArgSet(*posProj,*negProj)};
2315
2316 if (o.projData) {
2317
2318 // If data set contains more rows than needed, make reduced copy first
2319 RooAbsData* projDataSel = const_cast<RooAbsData*>(o.projData);
2320 std::unique_ptr<RooAbsData> projDataSelOwned;
2321 if (projDataNeededVars && projDataNeededVars->size() < o.projData->get()->size()) {
2322
2323 // Determine if there are any slice variables in the projection set
2324 RooArgSet sliceDataSet;
2325 sliceSet.selectCommon(*o.projData->get(), sliceDataSet);
2326 TString cutString ;
2327 if (!sliceDataSet.empty()) {
2328 bool first(true) ;
2329 for(RooAbsArg * sliceVar : sliceDataSet) {
2330 if (!first) {
2331 cutString.Append("&&") ;
2332 } else {
2333 first=false ;
2334 }
2335
2336 RooAbsRealLValue* real ;
2338 if ((real = dynamic_cast<RooAbsRealLValue*>(sliceVar))) {
2339 cutString.Append(Form("%s==%f",real->GetName(),real->getVal())) ;
2340 } else if ((cat = dynamic_cast<RooAbsCategoryLValue*>(sliceVar))) {
2341 cutString.Append(Form("%s==%d",cat->GetName(),cat->getCurrentIndex())) ;
2342 }
2343 }
2344 }
2345
2346 if (!cutString.IsNull()) {
2347 coutI(Plotting) << "RooAbsReal::plotAsymOn(" << GetName()
2348 << ") reducing given projection dataset to entries with " << cutString << std::endl ;
2349 }
2350 projDataSelOwned = std::unique_ptr<RooAbsData>{const_cast<RooAbsData*>(o.projData)->reduce(*projDataNeededVars,cutString.IsNull() ? nullptr : cutString)};
2351 projDataSel = projDataSelOwned.get();
2352 coutI(Plotting) << "RooAbsReal::plotAsymOn(" << GetName()
2353 << ") only the following components of the projection data will be used: " << *projDataNeededVars << std::endl ;
2354 }
2355
2356
2357 // Construct scaled data weighted average
2358 ScaledDataWeightedAverage scaleBind{funcAsym, *projDataSel, o.scaleFactor, *plotVar};
2359
2360 // Set default range, if not specified
2361 if (o.rangeLo==0 && o.rangeHi==0) {
2362 o.rangeLo = frame->GetXaxis()->GetXmin() ;
2363 o.rangeHi = frame->GetXaxis()->GetXmax() ;
2364 }
2365
2366 // Construct name of curve for data weighed average
2367 TString curveName(funcAsym.GetName()) ;
2368 curveName.Append(Form("_DataAvg[%s]",projDataSel->get()->contentsString().c_str())) ;
2369 // Append slice set specification if any
2370 if (!sliceSet.empty()) {
2371 curveName.Append(Form("_Slice[%s]",sliceSet.contentsString().c_str())) ;
2372 }
2373 // Append any suffixes imported from RooAbsPdf::plotOn
2374 if (o.curveNameSuffix) {
2375 curveName.Append(o.curveNameSuffix) ;
2376 }
2377
2378
2380 RooCurve *curve = new RooCurve(funcAsym.GetName(),funcAsym.GetTitle(),scaleBind,
2381 o.rangeLo,o.rangeHi,frame->GetNbinsX(),o.precision,o.precision,false,o.wmode,o.numee,o.doeeval,o.eeval) ;
2383
2384 dynamic_cast<TAttLine*>(curve)->SetLineColor(2) ;
2385 // add this new curve to the specified plot frame
2386 frame->addPlotable(curve, o.drawOptions);
2387
2388 ccoutW(Eval) << std::endl ;
2389 } else {
2390
2391 // Set default range, if not specified
2392 if (o.rangeLo==0 && o.rangeHi==0) {
2393 o.rangeLo = frame->GetXaxis()->GetXmin() ;
2394 o.rangeHi = frame->GetXaxis()->GetXmax() ;
2395 }
2396
2398 RooCurve* curve= new RooCurve(funcAsym,*plotVar,o.rangeLo,o.rangeHi,frame->GetNbinsX(),
2399 o.scaleFactor,nullptr,o.precision,o.precision,false,o.wmode,o.numee,o.doeeval,o.eeval);
2401
2402 dynamic_cast<TAttLine*>(curve)->SetLineColor(2) ;
2403
2404
2405 // Set default name of curve
2406 TString curveName(funcAsym.GetName()) ;
2407 if (!sliceSet.empty()) {
2408 curveName.Append(Form("_Slice[%s]",sliceSet.contentsString().c_str())) ;
2409 }
2410 if (o.curveNameSuffix) {
2411 // Append any suffixes imported from RooAbsPdf::plotOn
2412 curveName.Append(o.curveNameSuffix) ;
2413 }
2414 curve->SetName(curveName.Data()) ;
2415
2416 // add this new curve to the specified plot frame
2417 frame->addPlotable(curve, o.drawOptions);
2418
2419 }
2420
2421 // Cleanup
2422 delete posProjCompList ;
2423 delete negProjCompList ;
2424
2425 delete plotVar ;
2426
2427 return frame;
2428}
2429
2430
2431
2432////////////////////////////////////////////////////////////////////////////////
2433/// \brief Propagates parameter uncertainties to an uncertainty estimate for this RooAbsReal.
2434///
2435/// Estimates the uncertainty \f$\sigma_f(x;\theta)\f$ on a function \f$f(x;\theta)\f$ represented by this RooAbsReal.
2436/// Here, \f$\theta\f$ is a vector of parameters with uncertainties \f$\sigma_\theta\f$, and \f$x\f$ are usually observables.
2437/// The uncertainty is estimated by *linearly* propagating the parameter uncertainties using the correlation matrix from a fit result.
2438///
2439/// The square of the uncertainty on \f$f(x;\theta)\f$ is calculated as follows:
2440/// \f[
2441/// \sigma_f(x)^2 = \Delta f_i(x) \cdot \mathrm{Corr}_{i, j} \cdot \Delta f_j(x),
2442/// \f]
2443/// where \f$ \Delta f_i(x) = \frac{1}{2} \left(f(x;\theta_i + \sigma_{\theta_i}) - f(x; \theta_i - \sigma_{\theta_i}) \right) \f$
2444/// is the vector of function variations when changing the parameters one at a time, and
2445/// \f$ \mathrm{Corr}_{i,j} = \left(\sigma_{\theta_i} \sigma_{\theta_j}\right)^{-1} \cdot \mathrm{Cov}_{i,j} \f$ is the correlation matrix from the fit result.
2446
2447double RooAbsReal::getPropagatedError(const RooFitResult &fr, const RooArgSet &nset) const
2448{
2449 // Calling getParameters() might be costly, but necessary to get the right
2450 // parameters in the RooAbsReal. The RooFitResult only stores snapshots.
2451 RooArgSet allParamsInAbsReal;
2452 getParameters(&nset, allParamsInAbsReal);
2453
2454 RooArgList paramList;
2455 for(auto * rrvFitRes : static_range_cast<RooRealVar*>(fr.floatParsFinal())) {
2456
2457 auto rrvInAbsReal = static_cast<RooRealVar const*>(allParamsInAbsReal.find(*rrvFitRes));
2458
2459 // If this RooAbsReal is a RooRealVar in the fit result, we don't need to
2460 // propagate anything and can just return the error in the fit result
2461 if(rrvFitRes->namePtr() == namePtr()) return rrvFitRes->getError();
2462
2463 // Strip out parameters with zero error
2464 if (rrvFitRes->getError() <= std::abs(rrvFitRes->getVal()) * std::numeric_limits<double>::epsilon()) continue;
2465
2466 // Ignore parameters in the fit result that this RooAbsReal doesn't depend on
2467 if(!rrvInAbsReal) continue;
2468
2469 // Checking for float equality is a bad. We check if the values are
2470 // negligibly far away from each other, relative to the uncertainty.
2471 if(std::abs(rrvInAbsReal->getVal() - rrvFitRes->getVal()) > 0.01 * rrvFitRes->getError()) {
2472 std::stringstream errMsg;
2473 errMsg << "RooAbsReal::getPropagatedError(): the parameters of the RooAbsReal don't have"
2474 << " the same values as in the fit result! The logic of getPropagatedError is broken in this case.";
2475
2476 throw std::runtime_error(errMsg.str());
2477 }
2478
2479 paramList.add(*rrvInAbsReal);
2480 }
2481
2482 std::vector<double> plusVar;
2483 std::vector<double> minusVar;
2484 plusVar.reserve(paramList.size());
2485 minusVar.reserve(paramList.size());
2486
2487 // Create std::vector of plus,minus variations for each parameter
2488 TMatrixDSym V(paramList.size() == fr.floatParsFinal().size() ?
2489 fr.covarianceMatrix() :
2490 fr.reducedCovarianceMatrix(paramList)) ;
2491
2492 for (std::size_t ivar=0 ; ivar<paramList.size() ; ivar++) {
2493
2494 auto& rrv = static_cast<RooRealVar&>(paramList[ivar]);
2495
2496 double cenVal = rrv.getVal() ;
2497 double errVal = sqrt(V(ivar,ivar)) ;
2498
2499 // Make Plus variation
2500 rrv.setVal(cenVal+errVal) ;
2501 plusVar.push_back(getVal(nset)) ;
2502
2503 // Make Minus variation
2504 rrv.setVal(cenVal-errVal) ;
2505 minusVar.push_back(getVal(nset)) ;
2506
2507 rrv.setVal(cenVal) ;
2508 }
2509
2510 // Re-evaluate this RooAbsReal with the central parameters just to be
2511 // extra-safe that a call to `getPropagatedError()` doesn't change any state.
2512 // It should not be necessary because thanks to the dirty flag propagation
2513 // the RooAbsReal is re-evaluated anyway the next time getVal() is called.
2514 // Still there are imaginable corner cases where it would not be triggered,
2515 // for example if the user changes the RooFit operation more after the error
2516 // propagation.
2517 getVal(nset);
2518
2519 TMatrixDSym C(paramList.size()) ;
2520 std::vector<double> errVec(paramList.size()) ;
2521 for (std::size_t i=0 ; i<paramList.size() ; i++) {
2522 errVec[i] = std::sqrt(V(i,i)) ;
2523 for (std::size_t j=i ; j<paramList.size() ; j++) {
2524 C(i,j) = V(i,j) / std::sqrt(V(i,i)*V(j,j));
2525 C(j,i) = C(i,j) ;
2526 }
2527 }
2528
2529 // Make std::vector of variations
2530 TVectorD F(plusVar.size()) ;
2531 for (std::size_t j=0 ; j<plusVar.size() ; j++) {
2532 F[j] = (plusVar[j]-minusVar[j]) * 0.5;
2533 }
2534
2535 // Calculate error in linear approximation from variations and correlation coefficient
2536 double sum = F*(C*F) ;
2537
2538 return sqrt(sum) ;
2539}
2540
2541
2542
2543////////////////////////////////////////////////////////////////////////////////
2544/// Plot function or PDF on frame with support for visualization of the uncertainty encoded in the given fit result fr.
2545/// \param[in] frame RooPlot to plot on
2546/// \param[in] fr The RooFitResult, where errors can be extracted
2547/// \param[in] Z The desired significance (width) of the error band
2548/// \param[in] params If non-zero, consider only the subset of the parameters in fr for the error evaluation
2549/// \param[in] argList Optional `RooCmdArg` that can be applied to a regular plotOn() operation
2550/// \param[in] linMethod By default (linMethod=true), a linearized error is shown.
2551/// \return The RooPlot the band was plotted on (for chaining of plotting commands).
2552///
2553/// The linearized error is calculated as follows:
2554/// \f[
2555/// \mathrm{error}(x) = Z * F_a(x) * \mathrm{Corr}(a,a') * F_{a'}^\mathrm{T}(x),
2556/// \f]
2557///
2558/// where
2559/// \f[
2560/// F_a(x) = \frac{ f(x,a+\mathrm{d}a) - f(x,a-\mathrm{d}a) }{2},
2561/// \f]
2562/// with \f$ f(x) \f$ the plotted curve and \f$ \mathrm{d}a \f$ taken from the fit result, and
2563/// \f$ \mathrm{Corr}(a,a') \f$ = the correlation matrix from the fit result, and \f$ Z \f$ = requested signifance (\f$ Z \sigma \f$ band)
2564///
2565/// The linear method is fast (required 2*N evaluations of the curve, where N is the number of parameters), but may
2566/// not be accurate in the presence of strong correlations (~>0.9) and at Z>2 due to linear and Gaussian approximations made
2567///
2568/// Alternatively, a more robust error is calculated using a sampling method. In this method a number of curves
2569/// is calculated with variations of the parameter values, as drawn from a multi-variate Gaussian p.d.f. that is constructed
2570/// from the fit results covariance matrix. The error(x) is determined by calculating a central interval that capture N% of the variations
2571/// for each value of x, where N% is controlled by Z (i.e. Z=1 gives N=68%). The number of sampling curves is chosen to be such
2572/// that at least 30 curves are expected to be outside the N% interval, and is minimally 100 (e.g. Z=1->Ncurve=100, Z=2->Ncurve=659, Z=3->Ncurve=11111)
2573/// Intervals from the sampling method can be asymmetric, and may perform better in the presence of strong correlations, but may take (much)
2574/// longer to calculate.
2575
2576RooPlot* RooAbsReal::plotOnWithErrorBand(RooPlot* frame,const RooFitResult& fr, double Z,const RooArgSet* params, const RooLinkedList& argList, bool linMethod) const
2577{
2578 RooLinkedList plotArgListTmp(argList) ;
2579 RooCmdConfig::stripCmdList(plotArgListTmp,"VisualizeError,MoveToBack") ;
2580
2581 // Strip any 'internal normalization' arguments from list
2582 RooLinkedList plotArgList ;
2583 for (auto * cmd : static_range_cast<RooCmdArg*>(plotArgListTmp)) {
2584 if (std::string("Normalization")==cmd->GetName()) {
2585 if (((RooCmdArg*)cmd)->getInt(1)!=0) {
2586 } else {
2587 plotArgList.Add(cmd) ;
2588 }
2589 } else {
2590 plotArgList.Add(cmd) ;
2591 }
2592 }
2593
2594 // Function to plot a single curve, creating a copy of the plotArgList to
2595 // pass as plot command arguments. The "FillColor" command is removed because
2596 // it has no effect on plotting single curves and would cause a warning.
2597 auto plotFunc = [&](RooAbsReal const& absReal) {
2598 RooLinkedList tmp(plotArgList) ;
2599 RooCmdConfig::stripCmdList(tmp, "FillColor");
2600 absReal.plotOn(frame, tmp);
2601 };
2602
2603 // Generate central value curve
2604 plotFunc(*this);
2605 RooCurve* cenCurve = frame->getCurve() ;
2606 if(!cenCurve){
2607 coutE(Plotting) << ClassName() << "::" << GetName() << ":plotOnWithErrorBand: no curve for central value available" << std::endl;
2608 return frame;
2609 }
2610 frame->remove(nullptr,false) ;
2611
2612 RooCurve* band(nullptr) ;
2613 if (!linMethod) {
2614
2615 // *** Interval method ***
2616 //
2617 // Make N variations of parameters samples from V and visualize N% central interval where N% is defined from Z
2618
2619 // Clone self for internal use
2620 RooAbsReal* cloneFunc = static_cast<RooAbsReal*>(cloneTree()) ;
2621 RooArgSet cloneParams;
2622 cloneFunc->getObservables(&fr.floatParsFinal(), cloneParams) ;
2623 RooArgSet errorParams{cloneParams};
2624 if(params) {
2625 // clear and fill errorParams only with parameters that both in params and cloneParams
2626 cloneParams.selectCommon(*params, errorParams);
2627 }
2628
2629 // Generate 100 random parameter points distributed according to fit result covariance matrix
2630 RooAbsPdf* paramPdf = fr.createHessePdf(errorParams) ;
2631 Int_t n = Int_t(100./TMath::Erfc(Z/sqrt(2.))) ;
2632 if (n<100) n=100 ;
2633
2634 coutI(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") INFO: visualizing " << Z << "-sigma uncertainties in parameters "
2635 << errorParams << " from fit result " << fr.GetName() << " using " << n << " samplings." << std::endl ;
2636
2637 // Generate variation curves with above set of parameter values
2638 double ymin = frame->GetMinimum() ;
2639 double ymax = frame->GetMaximum() ;
2640 std::unique_ptr<RooDataSet> generatedData{paramPdf->generate(errorParams,n)};
2641 std::vector<RooCurve*> cvec ;
2642 for (int i=0 ; i<generatedData->numEntries() ; i++) {
2643 cloneParams.assign(*generatedData->get(i)) ;
2644 plotFunc(*cloneFunc);
2645 cvec.push_back(frame->getCurve()) ;
2646 frame->remove(nullptr,false) ;
2647 }
2648 frame->SetMinimum(ymin) ;
2649 frame->SetMaximum(ymax) ;
2650
2651
2652 // Generate upper and lower curve points from 68% interval around each point of central curve
2653 band = cenCurve->makeErrorBand(cvec,Z) ;
2654
2655 // Cleanup
2656 delete paramPdf ;
2657 delete cloneFunc ;
2658 for (std::vector<RooCurve*>::iterator i=cvec.begin() ; i!=cvec.end() ; ++i) {
2659 delete (*i) ;
2660 }
2661
2662 } else {
2663
2664 // *** Linear Method ***
2665 //
2666 // Make a one-sigma up- and down fluctation for each parameter and visualize
2667 // a from a linearized calculation as follows
2668 //
2669 // error(x) = F(a) C_aa' F(a')
2670 //
2671 // Where F(a) = (f(x,a+da) - f(x,a-da))/2
2672 // and C_aa' is the correlation matrix
2673
2674 // Strip out parameters with zero error
2675 RooArgList fpf_stripped;
2676 for (auto const* frv : static_range_cast<RooRealVar*>(fr.floatParsFinal())) {
2677 if (frv->getError() > frv->getVal() * std::numeric_limits<double>::epsilon()) {
2678 fpf_stripped.add(*frv);
2679 }
2680 }
2681
2682 // Clone self for internal use
2683 RooAbsReal* cloneFunc = static_cast<RooAbsReal*>(cloneTree()) ;
2684 RooArgSet cloneParams;
2685 cloneFunc->getObservables(&fpf_stripped, cloneParams) ;
2686 RooArgSet errorParams{cloneParams};
2687 if(params) {
2688 // clear and fill errorParams only with parameters that both in params and cloneParams
2689 cloneParams.selectCommon(*params, errorParams);
2690 }
2691
2692
2693 // Make list of parameter instances of cloneFunc in order of error matrix
2694 RooArgList paramList ;
2695 const RooArgList& fpf = fr.floatParsFinal() ;
2696 std::vector<int> fpf_idx ;
2697 for (std::size_t i=0 ; i<fpf.size() ; i++) {
2698 RooAbsArg* par = errorParams.find(fpf[i].GetName()) ;
2699 if (par) {
2700 paramList.add(*par) ;
2701 fpf_idx.push_back(i) ;
2702 }
2703 }
2704
2705 std::vector<RooCurve *> plusVar;
2706 std::vector<RooCurve *> minusVar;
2707
2708 // Create std::vector of plus,minus variations for each parameter
2709
2710 TMatrixDSym V(paramList.size() == fr.floatParsFinal().size() ?
2711 fr.covarianceMatrix():
2712 fr.reducedCovarianceMatrix(paramList)) ;
2713
2714
2715 for (std::size_t ivar=0 ; ivar<paramList.size() ; ivar++) {
2716
2717 RooRealVar& rrv = static_cast<RooRealVar&>(fpf[fpf_idx[ivar]]) ;
2718
2719 double cenVal = rrv.getVal() ;
2720 double errVal = sqrt(V(ivar,ivar)) ;
2721
2722 // Make Plus variation
2723 (static_cast<RooRealVar*>(paramList.at(ivar)))->setVal(cenVal+Z*errVal) ;
2724
2725
2726 plotFunc(*cloneFunc);
2727 plusVar.push_back(frame->getCurve()) ;
2728 frame->remove(nullptr,false) ;
2729
2730
2731 // Make Minus variation
2732 (static_cast<RooRealVar*>(paramList.at(ivar)))->setVal(cenVal-Z*errVal) ;
2733 plotFunc(*cloneFunc);
2734 minusVar.push_back(frame->getCurve()) ;
2735 frame->remove(nullptr,false) ;
2736
2737 (static_cast<RooRealVar*>(paramList.at(ivar)))->setVal(cenVal) ;
2738 }
2739
2740 TMatrixDSym C(paramList.size()) ;
2741 std::vector<double> errVec(paramList.size()) ;
2742 for (std::size_t i=0 ; i<paramList.size() ; i++) {
2743 errVec[i] = sqrt(V(i,i)) ;
2744 for (std::size_t j=i ; j<paramList.size() ; j++) {
2745 C(i,j) = V(i,j)/sqrt(V(i,i)*V(j,j)) ;
2746 C(j,i) = C(i,j) ;
2747 }
2748 }
2749
2750 band = cenCurve->makeErrorBand(plusVar,minusVar,C,Z) ;
2751
2752
2753 // Cleanup
2754 delete cloneFunc ;
2755 for (std::vector<RooCurve*>::iterator i=plusVar.begin() ; i!=plusVar.end() ; ++i) {
2756 delete (*i) ;
2757 }
2758 for (std::vector<RooCurve*>::iterator i=minusVar.begin() ; i!=minusVar.end() ; ++i) {
2759 delete (*i) ;
2760 }
2761
2762 }
2763
2764 delete cenCurve ;
2765 if (!band) return frame ;
2766
2767 // Define configuration for this method
2768 RooCmdConfig pc("RooAbsPdf::plotOn(" + std::string(GetName()) + ")");
2769 pc.defineString("drawOption","DrawOption",0,"F") ;
2770 pc.defineString("curveNameSuffix","CurveNameSuffix",0,"") ;
2771 pc.defineInt("lineColor","LineColor",0,-999) ;
2772 pc.defineInt("lineStyle","LineStyle",0,-999) ;
2773 pc.defineInt("lineWidth","LineWidth",0,-999) ;
2774 pc.defineInt("markerColor","MarkerColor",0,-999) ;
2775 pc.defineInt("markerStyle","MarkerStyle",0,-999) ;
2776 pc.defineDouble("markerSize","MarkerSize",0,-999) ;
2777 pc.defineInt("fillColor","FillColor",0,-999) ;
2778 pc.defineInt("fillStyle","FillStyle",0,-999) ;
2779 pc.defineString("curveName","Name",0,"") ;
2780 pc.defineInt("curveInvisible","Invisible",0,0) ;
2781 pc.defineInt("moveToBack","MoveToBack",0,0) ;
2782 pc.allowUndefined() ;
2783
2784 // Process & check varargs
2785 pc.process(argList) ;
2786 if (!pc.ok(true)) {
2787 return frame ;
2788 }
2789
2790 // Insert error band in plot frame
2791 frame->addPlotable(band,pc.getString("drawOption"),pc.getInt("curveInvisible")) ;
2792
2793 // Optionally adjust line/fill attributes
2794 Int_t lineColor = pc.getInt("lineColor") ;
2795 Int_t lineStyle = pc.getInt("lineStyle") ;
2796 Int_t lineWidth = pc.getInt("lineWidth") ;
2797 Int_t markerColor = pc.getInt("markerColor") ;
2798 Int_t markerStyle = pc.getInt("markerStyle") ;
2799 Size_t markerSize = pc.getDouble("markerSize") ;
2800 Int_t fillColor = pc.getInt("fillColor") ;
2801 Int_t fillStyle = pc.getInt("fillStyle") ;
2802 if (lineColor!=-999) frame->getAttLine()->SetLineColor(lineColor) ;
2803 if (lineStyle!=-999) frame->getAttLine()->SetLineStyle(lineStyle) ;
2804 if (lineWidth!=-999) frame->getAttLine()->SetLineWidth(lineWidth) ;
2805 if (fillColor!=-999) frame->getAttFill()->SetFillColor(fillColor) ;
2806 if (fillStyle!=-999) frame->getAttFill()->SetFillStyle(fillStyle) ;
2807 if (markerColor!=-999) frame->getAttMarker()->SetMarkerColor(markerColor) ;
2808 if (markerStyle!=-999) frame->getAttMarker()->SetMarkerStyle(markerStyle) ;
2809 if (markerSize!=-999) frame->getAttMarker()->SetMarkerSize(markerSize) ;
2810
2811 // Adjust name if requested
2812 if (pc.getString("curveName",nullptr,true)) {
2813 band->SetName(pc.getString("curveName",nullptr,true)) ;
2814 } else if (pc.getString("curveNameSuffix",nullptr,true)) {
2815 TString name(band->GetName()) ;
2816 name.Append(pc.getString("curveNameSuffix",nullptr,true)) ;
2817 band->SetName(name.Data()) ;
2818 }
2819
2820 // Move last inserted object to back to drawing stack if requested
2821 if (pc.getInt("moveToBack") && frame->numItems()>1) {
2822 frame->drawBefore(frame->getObject(0)->GetName(), frame->getCurve()->GetName());
2823 }
2824
2825
2826 return frame ;
2827}
2828
2829
2830
2831
2832////////////////////////////////////////////////////////////////////////////////
2833/// Utility function for plotOn(), perform general sanity check on frame to ensure safe plotting operations
2834
2836{
2837 // check that we are passed a valid plot frame to use
2838 if(nullptr == frame) {
2839 coutE(Plotting) << ClassName() << "::" << GetName() << ":plotOn: frame is null" << std::endl;
2840 return true;
2841 }
2842
2843 // check that this frame knows what variable to plot
2844 RooAbsReal* var = frame->getPlotVar() ;
2845 if(!var) {
2846 coutE(Plotting) << ClassName() << "::" << GetName()
2847 << ":plotOn: frame does not specify a plot variable" << std::endl;
2848 return true;
2849 }
2850
2851 // check that the plot variable is not derived
2852 if(!dynamic_cast<RooAbsRealLValue*>(var)) {
2853 coutE(Plotting) << ClassName() << "::" << GetName() << ":plotOn: cannot plot variable \""
2854 << var->GetName() << "\" of type " << var->ClassName() << std::endl;
2855 return true;
2856 }
2857
2858 // check if we actually depend on the plot variable
2859 if(!this->dependsOn(*var)) {
2860 coutE(Plotting) << ClassName() << "::" << GetName() << ":plotOn: WARNING: variable is not an explicit dependent: "
2861 << var->GetName() << std::endl;
2862 }
2863
2864 return false ;
2865}
2866
2867
2868
2869
2870////////////////////////////////////////////////////////////////////////////////
2871/// Utility function for plotOn() that constructs the set of
2872/// observables to project when plotting ourselves as function of
2873/// 'plotVar'. 'allVars' is the list of variables that must be
2874/// projected, but may contain variables that we do not depend on. If
2875/// 'silent' is cleared, warnings about inconsistent input parameters
2876/// will be printed.
2877
2878void RooAbsReal::makeProjectionSet(const RooAbsArg* plotVar, const RooArgSet* allVars,
2879 RooArgSet& projectedVars, bool silent) const
2880{
2881 cxcoutD(Plotting) << "RooAbsReal::makeProjectionSet(" << GetName() << ") plotVar = " << plotVar->GetName()
2882 << " allVars = " << (allVars?(*allVars):RooArgSet()) << std::endl ;
2883
2884 projectedVars.removeAll() ;
2885 if (!allVars) return ;
2886
2887 // Start out with suggested list of variables
2888 projectedVars.add(*allVars) ;
2889
2890 // Take out plot variable
2891 RooAbsArg *found= projectedVars.find(plotVar->GetName());
2892 if(found) {
2893 projectedVars.remove(*found);
2894
2895 // Take out eventual servers of plotVar
2896 std::unique_ptr<RooArgSet> plotServers{plotVar->getObservables(&projectedVars)};
2897 for(RooAbsArg * ps : *plotServers) {
2898 RooAbsArg* tmp = projectedVars.find(ps->GetName()) ;
2899 if (tmp) {
2900 cxcoutD(Plotting) << "RooAbsReal::makeProjectionSet(" << GetName() << ") removing " << tmp->GetName()
2901 << " from projection set because it a server of " << plotVar->GetName() << std::endl ;
2902 projectedVars.remove(*tmp) ;
2903 }
2904 }
2905
2906 if (!silent) {
2907 coutW(Plotting) << "RooAbsReal::plotOn(" << GetName()
2908 << ") WARNING: cannot project out frame variable ("
2909 << found->GetName() << "), ignoring" << std::endl ;
2910 }
2911 }
2912
2913 // Take out all non-dependents of function
2914 for(RooAbsArg * arg : *allVars) {
2915 if (!dependsOnValue(*arg)) {
2916 projectedVars.remove(*arg,true) ;
2917
2918 cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName()
2919 << ") function doesn't depend on projection variable "
2920 << arg->GetName() << ", ignoring" << std::endl ;
2921 }
2922 }
2923}
2924
2925
2926
2927
2928////////////////////////////////////////////////////////////////////////////////
2929/// If true, the current pdf is a selected component (for use in plotting)
2930
2932{
2933 return _selectComp || _globalSelectComp ;
2934}
2935
2936
2937
2938////////////////////////////////////////////////////////////////////////////////
2939/// Global switch controlling the activation of the selectComp() functionality
2940
2942{
2943 _globalSelectComp = flag ;
2944}
2945
2946
2947
2948
2949////////////////////////////////////////////////////////////////////////////////
2950/// Create an interface adaptor f(vars) that binds us to the specified variables
2951/// (in arbitrary order). For example, calling bindVars({x1,x3}) on an object
2952/// F(x1,x2,x3,x4) returns an object f(x1,x3) that is evaluated using the
2953/// current values of x2 and x4. The caller takes ownership of the returned adaptor.
2954
2955RooFit::OwningPtr<RooAbsFunc> RooAbsReal::bindVars(const RooArgSet &vars, const RooArgSet* nset, bool clipInvalid) const
2956{
2957 auto binding = std::make_unique<RooRealBinding>(*this,vars,nset,clipInvalid);
2958 if(!binding->isValid()) {
2959 coutE(InputArguments) << ClassName() << "::" << GetName() << ":bindVars: cannot bind to " << vars << std::endl ;
2960 return nullptr;
2961 }
2962 return RooFit::makeOwningPtr(std::unique_ptr<RooAbsFunc>{std::move(binding)});
2963}
2964
2965
2966
2967////////////////////////////////////////////////////////////////////////////////
2968/// Copy the cached value of another RooAbsArg to our cache.
2969/// Warning: This function just copies the cached values of source,
2970/// it is the callers responsibility to make sure the cache is clean.
2971
2972void RooAbsReal::copyCache(const RooAbsArg* source, bool /*valueOnly*/, bool setValDirty)
2973{
2974 auto other = static_cast<const RooAbsReal*>(source);
2975 assert(dynamic_cast<const RooAbsReal*>(source));
2976
2977 _value = other->_treeReadBuffer ? other->_treeReadBuffer->operator double() : other->_value;
2978
2979 if (setValDirty) {
2980 setValueDirty() ;
2981 }
2982}
2983
2984
2985////////////////////////////////////////////////////////////////////////////////
2986
2988{
2989 vstore.addReal(this)->setBuffer(this,&_value);
2990}
2991
2992
2993////////////////////////////////////////////////////////////////////////////////
2994/// Attach object to a branch of given TTree. By default it will
2995/// register the internal value cache RooAbsReal::_value as branch
2996/// buffer for a double tree branch with the same name as this
2997/// object. If no double branch is found with the name of this
2998/// object, this method looks for a Float_t Int_t, UChar_t and UInt_t, etc
2999/// branch. If any of these are found, a TreeReadBuffer
3000/// that branch is created, and saved in _treeReadBuffer.
3001/// TreeReadBuffer::operator double() can be used to convert the values.
3002/// This is used by copyCache().
3004{
3005 // First determine if branch is taken
3006 TString cleanName(cleanBranchName()) ;
3007 TBranch* branch = t.GetBranch(cleanName) ;
3008 if (branch) {
3009
3010 // Determine if existing branch is Float_t or double
3011 TLeaf* leaf = static_cast<TLeaf*>(branch->GetListOfLeaves()->At(0)) ;
3012
3013 // Check that leaf is _not_ an array
3014 Int_t dummy ;
3015 TLeaf* counterLeaf = leaf->GetLeafCounter(dummy) ;
3016 if (counterLeaf) {
3017 coutE(Eval) << "RooAbsReal::attachToTree(" << GetName() << ") ERROR: TTree branch " << GetName()
3018 << " is an array and cannot be attached to a RooAbsReal" << std::endl ;
3019 return ;
3020 }
3021
3022 TString typeName(leaf->GetTypeName()) ;
3023
3024
3025 // For different type names, store three items:
3026 // first: A tag attached to this instance. Not used inside RooFit, any more, but users might rely on it.
3027 // second: A function to attach
3028 std::map<std::string, std::pair<std::string, std::function<std::unique_ptr<TreeReadBuffer>()>>> typeMap {
3029 {"Float_t", {"FLOAT_TREE_BRANCH", [&](){ return createTreeReadBuffer<Float_t >(cleanName, t); }}},
3030 {"Int_t", {"INTEGER_TREE_BRANCH", [&](){ return createTreeReadBuffer<Int_t >(cleanName, t); }}},
3031 {"UChar_t", {"BYTE_TREE_BRANCH", [&](){ return createTreeReadBuffer<UChar_t >(cleanName, t); }}},
3032 {"Bool_t", {"BOOL_TREE_BRANCH", [&](){ return createTreeReadBuffer<Bool_t >(cleanName, t); }}},
3033 {"Char_t", {"SIGNEDBYTE_TREE_BRANCH", [&](){ return createTreeReadBuffer<Char_t >(cleanName, t); }}},
3034 {"UInt_t", {"UNSIGNED_INTEGER_TREE_BRANCH", [&](){ return createTreeReadBuffer<UInt_t >(cleanName, t); }}},
3035 {"Long64_t", {"LONG_TREE_BRANCH", [&](){ return createTreeReadBuffer<Long64_t >(cleanName, t); }}},
3036 {"ULong64_t", {"UNSIGNED_LONG_TREE_BRANCH", [&](){ return createTreeReadBuffer<ULong64_t>(cleanName, t); }}},
3037 {"Short_t", {"SHORT_TREE_BRANCH", [&](){ return createTreeReadBuffer<Short_t >(cleanName, t); }}},
3038 {"UShort_t", {"UNSIGNED_SHORT_TREE_BRANCH", [&](){ return createTreeReadBuffer<UShort_t >(cleanName, t); }}},
3039 };
3040
3041 auto typeDetails = typeMap.find(typeName.Data());
3042 if (typeDetails != typeMap.end()) {
3043 coutI(DataHandling) << "RooAbsReal::attachToTree(" << GetName() << ") TTree " << typeDetails->first << " branch " << GetName()
3044 << " will be converted to double precision." << std::endl ;
3045 setAttribute(typeDetails->second.first.c_str(), true);
3046 _treeReadBuffer = typeDetails->second.second();
3047 } else {
3048 _treeReadBuffer = nullptr;
3049
3050 if (!typeName.CompareTo("Double_t")) {
3051 t.SetBranchAddress(cleanName, &_value);
3052 }
3053 else {
3054 coutE(InputArguments) << "RooAbsReal::attachToTree(" << GetName() << ") data type " << typeName << " is not supported." << std::endl ;
3055 }
3056 }
3057 } else {
3058
3059 TString format(cleanName);
3060 format.Append("/D");
3061 branch = t.Branch(cleanName, &_value, (const Text_t*)format, bufSize);
3062 }
3063
3064}
3065
3066
3067
3068////////////////////////////////////////////////////////////////////////////////
3069/// Fill the tree branch that associated with this object with its current value
3070
3072{
3073 // First determine if branch is taken
3074 TBranch* branch = t.GetBranch(cleanBranchName()) ;
3075 if (!branch) {
3076 coutE(Eval) << "RooAbsReal::fillTreeBranch(" << GetName() << ") ERROR: not attached to tree: " << cleanBranchName() << std::endl ;
3077 assert(0) ;
3078 }
3079 branch->Fill() ;
3080
3081}
3082
3083
3084
3085////////////////////////////////////////////////////////////////////////////////
3086/// (De)Activate associated tree branch
3087
3089{
3090 TBranch* branch = t.GetBranch(cleanBranchName()) ;
3091 if (branch) {
3092 t.SetBranchStatus(cleanBranchName(),active?true:false) ;
3093 }
3094}
3095
3096
3097
3098////////////////////////////////////////////////////////////////////////////////
3099/// Create a RooRealVar fundamental object with our properties. The new
3100/// object will be created without any fit limits.
3101
3103{
3104 auto fund = std::make_unique<RooRealVar>(newname?newname:GetName(),GetTitle(),_value,getUnit());
3105 fund->removeRange();
3106 fund->setPlotLabel(getPlotLabel());
3107 fund->setAttribute("fundamentalCopy");
3108 return RooFit::makeOwningPtr<RooAbsArg>(std::move(fund));
3109}
3110
3111
3112
3113////////////////////////////////////////////////////////////////////////////////
3114/// Utility function for use in getAnalyticalIntegral(). If the
3115/// content of proxy 'a' occurs in set 'allDeps' then the argument
3116/// held in 'a' is copied from allDeps to analDeps
3117
3118bool RooAbsReal::matchArgs(const RooArgSet& allDeps, RooArgSet& analDeps,
3119 const RooArgProxy& a) const
3120{
3121 TList nameList ;
3122 nameList.Add(new TObjString(a.absArg()->GetName())) ;
3123 bool result = matchArgsByName(allDeps,analDeps,nameList) ;
3124 nameList.Delete() ;
3125 return result ;
3126}
3127
3128
3129
3130////////////////////////////////////////////////////////////////////////////////
3131/// Utility function for use in getAnalyticalIntegral(). If the
3132/// contents of proxies a,b occur in set 'allDeps' then the arguments
3133/// held in a,b are copied from allDeps to analDeps
3134
3135bool RooAbsReal::matchArgs(const RooArgSet& allDeps, RooArgSet& analDeps,
3136 const RooArgProxy& a, const RooArgProxy& b) const
3137{
3138 TList nameList ;
3139 nameList.Add(new TObjString(a.absArg()->GetName())) ;
3140 nameList.Add(new TObjString(b.absArg()->GetName())) ;
3141 bool result = matchArgsByName(allDeps,analDeps,nameList) ;
3142 nameList.Delete() ;
3143 return result ;
3144}
3145
3146
3147
3148////////////////////////////////////////////////////////////////////////////////
3149/// Utility function for use in getAnalyticalIntegral(). If the
3150/// contents of proxies a,b,c occur in set 'allDeps' then the arguments
3151/// held in a,b,c are copied from allDeps to analDeps
3152
3153bool RooAbsReal::matchArgs(const RooArgSet& allDeps, RooArgSet& analDeps,
3154 const RooArgProxy& a, const RooArgProxy& b,
3155 const RooArgProxy& c) const
3156{
3157 TList nameList ;
3158 nameList.Add(new TObjString(a.absArg()->GetName())) ;
3159 nameList.Add(new TObjString(b.absArg()->GetName())) ;
3160 nameList.Add(new TObjString(c.absArg()->GetName())) ;
3161 bool result = matchArgsByName(allDeps,analDeps,nameList) ;
3162 nameList.Delete() ;
3163 return result ;
3164}
3165
3166
3167
3168////////////////////////////////////////////////////////////////////////////////
3169/// Utility function for use in getAnalyticalIntegral(). If the
3170/// contents of proxies a,b,c,d occur in set 'allDeps' then the arguments
3171/// held in a,b,c,d are copied from allDeps to analDeps
3172
3173bool RooAbsReal::matchArgs(const RooArgSet& allDeps, RooArgSet& analDeps,
3174 const RooArgProxy& a, const RooArgProxy& b,
3175 const RooArgProxy& c, const RooArgProxy& d) const
3176{
3177 TList nameList ;
3178 nameList.Add(new TObjString(a.absArg()->GetName())) ;
3179 nameList.Add(new TObjString(b.absArg()->GetName())) ;
3180 nameList.Add(new TObjString(c.absArg()->GetName())) ;
3181 nameList.Add(new TObjString(d.absArg()->GetName())) ;
3182 bool result = matchArgsByName(allDeps,analDeps,nameList) ;
3183 nameList.Delete() ;
3184 return result ;
3185}
3186
3187
3188////////////////////////////////////////////////////////////////////////////////
3189/// Utility function for use in getAnalyticalIntegral(). If the
3190/// contents of 'refset' occur in set 'allDeps' then the arguments
3191/// held in 'refset' are copied from allDeps to analDeps.
3192
3193bool RooAbsReal::matchArgs(const RooArgSet& allDeps, RooArgSet& analDeps,
3194 const RooArgSet& refset) const
3195{
3196 TList nameList ;
3197 for(RooAbsArg * arg : refset) {
3198 nameList.Add(new TObjString(arg->GetName())) ;
3199 }
3200
3201 bool result = matchArgsByName(allDeps,analDeps,nameList) ;
3202 nameList.Delete() ;
3203 return result ;
3204}
3205
3206
3207
3208////////////////////////////////////////////////////////////////////////////////
3209/// Check if allArgs contains matching elements for each name in nameList. If it does,
3210/// add the corresponding args from allArgs to matchedArgs and return true. Otherwise
3211/// return false and do not change matchedArgs.
3212
3213bool RooAbsReal::matchArgsByName(const RooArgSet &allArgs, RooArgSet &matchedArgs,
3214 const TList &nameList) const
3215{
3216 RooArgSet matched("matched");
3217 bool isMatched(true);
3218 for(auto * name : static_range_cast<TObjString*>(nameList)) {
3219 RooAbsArg *found= allArgs.find(name->String().Data());
3220 if(found) {
3221 matched.add(*found);
3222 }
3223 else {
3224 isMatched= false;
3225 break;
3226 }
3227 }
3228
3229 // nameList may not contain multiple entries with the same name
3230 // that are both matched
3231 if (isMatched && int(matched.size())!=nameList.GetSize()) {
3232 isMatched = false ;
3233 }
3234
3235 if(isMatched) matchedArgs.add(matched);
3236 return isMatched;
3237}
3238
3239
3240
3241////////////////////////////////////////////////////////////////////////////////
3242/// Returns the default numeric integration configuration for all RooAbsReals
3243
3245{
3247}
3248
3249
3250////////////////////////////////////////////////////////////////////////////////
3251/// Returns the specialized integrator configuration for _this_ RooAbsReal.
3252/// If this object has no specialized configuration, a null pointer is returned.
3253
3255{
3256 return _specIntegratorConfig.get();
3257}
3258
3259
3260////////////////////////////////////////////////////////////////////////////////
3261/// Returns the specialized integrator configuration for _this_ RooAbsReal.
3262/// If this object has no specialized configuration, a null pointer is returned,
3263/// unless createOnTheFly is true in which case a clone of the default integrator
3264/// configuration is created, installed as specialized configuration, and returned
3265
3267{
3268 if (!_specIntegratorConfig && createOnTheFly) {
3269 _specIntegratorConfig = std::make_unique<RooNumIntConfig>(*defaultIntegratorConfig()) ;
3270 }
3271 return _specIntegratorConfig.get();
3272}
3273
3274
3275
3276////////////////////////////////////////////////////////////////////////////////
3277/// Return the numeric integration configuration used for this object. If
3278/// a specialized configuration was associated with this object, that configuration
3279/// is returned, otherwise the default configuration for all RooAbsReals is returned
3280
3282{
3283 const RooNumIntConfig* config = specialIntegratorConfig() ;
3284 if (config) return config ;
3285 return defaultIntegratorConfig() ;
3286}
3287
3288
3289////////////////////////////////////////////////////////////////////////////////
3290/// Return the numeric integration configuration used for this object. If
3291/// a specialized configuration was associated with this object, that configuration
3292/// is returned, otherwise the default configuration for all RooAbsReals is returned
3293
3295{
3297 if (config) return config ;
3298 return defaultIntegratorConfig() ;
3299}
3300
3301
3302
3303////////////////////////////////////////////////////////////////////////////////
3304/// Set the given integrator configuration as default numeric integration
3305/// configuration for this object
3306
3308{
3309 _specIntegratorConfig = std::make_unique<RooNumIntConfig>(config);
3310}
3311
3312
3313
3314////////////////////////////////////////////////////////////////////////////////
3315/// Remove the specialized numeric integration configuration associated
3316/// with this object
3317
3319{
3320 _specIntegratorConfig.reset();
3321}
3322
3323
3324
3325
3326////////////////////////////////////////////////////////////////////////////////
3327/// Interface function to force use of a given set of observables
3328/// to interpret function value. Needed for functions or p.d.f.s
3329/// whose shape depends on the choice of normalization such as
3330/// RooAddPdf
3331
3333{
3334}
3335
3336
3337
3338
3339////////////////////////////////////////////////////////////////////////////////
3340/// Interface function to force use of a given normalization range
3341/// to interpret function value. Needed for functions or p.d.f.s
3342/// whose shape depends on the choice of normalization such as
3343/// RooAddPdf
3344
3346{
3347}
3348
3349
3350
3351////////////////////////////////////////////////////////////////////////////////
3352/// Advertise capability to determine maximum value of function for given set of
3353/// observables. If no direct generator method is provided, this information
3354/// will assist the accept/reject generator to operate more efficiently as
3355/// it can skip the initial trial sampling phase to empirically find the function
3356/// maximum
3357
3359{
3360 return 0 ;
3361}
3362
3363
3364
3365////////////////////////////////////////////////////////////////////////////////
3366/// Return maximum value for set of observables identified by code assigned
3367/// in getMaxVal
3368
3369double RooAbsReal::maxVal(Int_t /*code*/) const
3370{
3371 assert(1) ;
3372 return 0 ;
3373}
3374
3375
3376
3377////////////////////////////////////////////////////////////////////////////////
3378/// Interface to insert remote error logging messages received by RooRealMPFE into current error logging stream.
3379
3380void RooAbsReal::logEvalError(const RooAbsReal* originator, const char* origName, const char* message, const char* serverValueString)
3381{
3382 if (_evalErrorMode==Ignore) {
3383 return ;
3384 }
3385
3387 _evalErrorCount++ ;
3388 return ;
3389 }
3390
3391 static bool inLogEvalError = false ;
3392
3393 if (inLogEvalError) {
3394 return ;
3395 }
3396 inLogEvalError = true ;
3397
3398 EvalError ee ;
3399 ee.setMessage(message) ;
3400
3401 if (serverValueString) {
3402 ee.setServerValues(serverValueString) ;
3403 }
3404
3406 oocoutE(nullptr,Eval) << "RooAbsReal::logEvalError(" << "<STATIC>" << ") evaluation error, " << std::endl
3407 << " origin : " << origName << std::endl
3408 << " message : " << ee._msg << std::endl
3409 << " server values: " << ee._srvval << std::endl ;
3410 } else if (_evalErrorMode==CollectErrors) {
3411 _evalErrorList[originator].first = origName ;
3412 _evalErrorList[originator].second.push_back(ee) ;
3413 }
3414
3415
3416 inLogEvalError = false ;
3417}
3418
3419
3420
3421////////////////////////////////////////////////////////////////////////////////
3422/// Log evaluation error message. Evaluation errors may be routed through a different
3423/// protocol than generic RooFit warning message (which go straight through RooMsgService)
3424/// because evaluation errors can occur in very large numbers in the use of likelihood
3425/// evaluations. In logEvalError mode, controlled by global method enableEvalErrorLogging()
3426/// messages reported through this function are not printed but all stored in a list,
3427/// along with server values at the time of reporting. Error messages logged in this
3428/// way can be printed in a structured way, eliminating duplicates and with the ability
3429/// to truncate the list by printEvalErrors. This is the standard mode of error logging
3430/// during MINUIT operations. If enableEvalErrorLogging() is false, all errors
3431/// reported through this method are passed for immediate printing through RooMsgService.
3432/// A string with server names and values is constructed automatically for error logging
3433/// purposes, unless a custom string with similar information is passed as argument.
3434
3435void RooAbsReal::logEvalError(const char* message, const char* serverValueString) const
3436{
3437 if (_evalErrorMode==Ignore) {
3438 return ;
3439 }
3440
3442 _evalErrorCount++ ;
3443 return ;
3444 }
3445
3446 static bool inLogEvalError = false ;
3447
3448 if (inLogEvalError) {
3449 return ;
3450 }
3451 inLogEvalError = true ;
3452
3453 EvalError ee ;
3454 ee.setMessage(message) ;
3455
3456 if (serverValueString) {
3457 ee.setServerValues(serverValueString) ;
3458 } else {
3459 std::string srvval ;
3460 std::ostringstream oss ;
3461 bool first(true) ;
3462 for (Int_t i=0 ; i<numProxies() ; i++) {
3463 RooAbsProxy* p = getProxy(i) ;
3464 if (!p) continue ;
3465 //if (p->name()[0]=='!') continue ;
3466 if (first) {
3467 first=false ;
3468 } else {
3469 oss << ", " ;
3470 }
3471 p->print(oss,true) ;
3472 }
3473 ee.setServerValues(oss.str().c_str()) ;
3474 }
3475
3476 std::ostringstream oss2 ;
3478
3480 coutE(Eval) << "RooAbsReal::logEvalError(" << GetName() << ") evaluation error, " << std::endl
3481 << " origin : " << oss2.str() << std::endl
3482 << " message : " << ee._msg << std::endl
3483 << " server values: " << ee._srvval << std::endl ;
3484 } else if (_evalErrorMode==CollectErrors) {
3485 if (_evalErrorList[this].second.size() >= 2048) {
3486 // avoid overflowing the error list, so if there are very many, print
3487 // the oldest one first, and pop it off the list
3488 const EvalError& oee = _evalErrorList[this].second.front();
3489 // print to debug stream, since these would normally be suppressed, and
3490 // we do not want to increase the error count in the message service...
3491 ccoutD(Eval) << "RooAbsReal::logEvalError(" << GetName()
3492 << ") delayed evaluation error, " << std::endl
3493 << " origin : " << oss2.str() << std::endl
3494 << " message : " << oee._msg << std::endl
3495 << " server values: " << oee._srvval << std::endl ;
3496 _evalErrorList[this].second.pop_front();
3497 }
3498 _evalErrorList[this].first = oss2.str() ;
3499 _evalErrorList[this].second.push_back(ee) ;
3500 }
3501
3502 inLogEvalError = false ;
3503 //coutE(Tracing) << "RooAbsReal::logEvalError(" << GetName() << ") message = " << message << std::endl ;
3504}
3505
3506
3507
3508
3509////////////////////////////////////////////////////////////////////////////////
3510/// Clear the stack of evaluation error messages
3511
3513{
3515 return ;
3516 } else if (_evalErrorMode==CollectErrors) {
3517 _evalErrorList.clear() ;
3518 } else {
3519 _evalErrorCount = 0 ;
3520 }
3521}
3522
3523
3524////////////////////////////////////////////////////////////////////////////////
3525/// Retrieve bin boundaries if this distribution is binned in `obs`.
3526/// \param[in] obs Observable to retrieve boundaries for.
3527/// \param[in] xlo Beginning of range.
3528/// \param[in] xhi End of range.
3529/// \return The caller owns the returned std::list.
3530std::list<double>* RooAbsReal::binBoundaries(RooAbsRealLValue& /*obs*/, double /*xlo*/, double /*xhi*/) const {
3531 return nullptr;
3532}
3533
3534
3535////////////////////////////////////////////////////////////////////////////////
3536/// Interface for returning an optional hint for initial sampling points when constructing a curve projected on observable `obs`.
3537/// \param[in] obs Observable to retrieve sampling hint for.
3538/// \param[in] xlo Beginning of range.
3539/// \param[in] xhi End of range.
3540/// \return The caller owns the returned std::list.
3541std::list<double>* RooAbsReal::plotSamplingHint(RooAbsRealLValue& /*obs*/, double /*xlo*/, double /*xhi*/) const {
3542 return nullptr;
3543}
3544
3545////////////////////////////////////////////////////////////////////////////////
3546/// Print all outstanding logged evaluation error on the given ostream. If maxPerNode
3547/// is zero, only the number of errors for each source (object with unique name) is listed.
3548/// If maxPerNode is greater than zero, up to maxPerNode detailed error messages are shown
3549/// per source of errors. A truncation message is shown if there were more errors logged
3550/// than shown.
3551
3552void RooAbsReal::printEvalErrors(std::ostream& os, Int_t maxPerNode)
3553{
3554 if (_evalErrorMode == CountErrors) {
3555 os << _evalErrorCount << " errors counted" << std::endl ;
3556 }
3557
3558 if (maxPerNode<0) return ;
3559
3560 for(auto iter = _evalErrorList.begin();iter!=_evalErrorList.end() ; ++iter) {
3561 if (maxPerNode==0) {
3562
3563 // Only print node name with total number of errors
3564 os << iter->second.first ;
3565 //iter->first->printStream(os,kName|kClassName|kArgs,kInline) ;
3566 os << " has " << iter->second.second.size() << " errors" << std::endl ;
3567
3568 } else {
3569
3570 // Print node name and details of 'maxPerNode' errors
3571 os << iter->second.first << std::endl ;
3572 //iter->first->printStream(os,kName|kClassName|kArgs,kSingleLine) ;
3573
3574 Int_t i(0) ;
3575 for(auto iter2 = iter->second.second.begin();iter2!=iter->second.second.end() ; ++iter2, i++) {
3576 os << " " << iter2->_msg << " @ " << iter2->_srvval << std::endl ;
3577 if (i>maxPerNode) {
3578 os << " ... (remaining " << iter->second.second.size() - maxPerNode << " messages suppressed)" << std::endl ;
3579 break ;
3580 }
3581 }
3582 }
3583 }
3584}
3585
3586
3587
3588////////////////////////////////////////////////////////////////////////////////
3589/// Return the number of logged evaluation errors since the last clearing.
3590
3592{
3594 return _evalErrorCount ;
3595 }
3596
3597 Int_t ntot(0) ;
3598 for(auto const& elem : _evalErrorList) {
3599 ntot += elem.second.second.size() ;
3600 }
3601 return ntot ;
3602}
3603
3604
3605
3606////////////////////////////////////////////////////////////////////////////////
3607/// Fix the interpretation of the coefficient of any RooAddPdf component in
3608/// the expression tree headed by this object to the given set of observables.
3609///
3610/// If the force flag is false, the normalization choice is only fixed for those
3611/// RooAddPdf components that have the default 'automatic' interpretation of
3612/// coefficients (i.e. the interpretation is defined by the observables passed
3613/// to getVal()). If force is true, also RooAddPdf that already have a fixed
3614/// interpretation are changed to a new fixed interpretation.
3615
3616void RooAbsReal::fixAddCoefNormalization(const RooArgSet& addNormSet, bool force)
3617{
3618 std::unique_ptr<RooArgSet> compSet{getComponents()};
3619 for(auto * pdf : dynamic_range_cast<RooAbsPdf*>(*compSet)) {
3620 if (pdf) {
3621 if (!addNormSet.empty()) {
3622 pdf->selectNormalization(&addNormSet,force) ;
3623 } else {
3624 pdf->selectNormalization(nullptr,force) ;
3625 }
3626 }
3627 }
3628}
3629
3630
3631
3632////////////////////////////////////////////////////////////////////////////////
3633/// Fix the interpretation of the coefficient of any RooAddPdf component in
3634/// the expression tree headed by this object to the given set of observables.
3635///
3636/// If the force flag is false, the normalization range choice is only fixed for those
3637/// RooAddPdf components that currently use the default full domain to interpret their
3638/// coefficients. If force is true, also RooAddPdf that already have a fixed
3639/// interpretation range are changed to a new fixed interpretation range.
3640
3641void RooAbsReal::fixAddCoefRange(const char* rangeName, bool force)
3642{
3643 std::unique_ptr<RooArgSet> compSet{getComponents()};
3644 for(auto * pdf : dynamic_range_cast<RooAbsPdf*>(*compSet)) {
3645 if (pdf) {
3646 pdf->selectNormalizationRange(rangeName,force) ;
3647 }
3648 }
3649}
3650
3651
3652
3653////////////////////////////////////////////////////////////////////////////////
3654/// Interface method for function objects to indicate their preferred order of observables
3655/// for scanning their values into a (multi-dimensional) histogram or RooDataSet. The observables
3656/// to be ordered are offered in argument 'obs' and should be copied in their preferred
3657/// order into argument 'orderedObs', This default implementation indicates no preference
3658/// and copies the original order of 'obs' into 'orderedObs'
3659
3661{
3662 // Dummy implementation, do nothing
3663 orderedObs.removeAll() ;
3664 orderedObs.add(obs) ;
3665}
3666
3667
3668
3669////////////////////////////////////////////////////////////////////////////////
3670/// Calls createRunningIntegral(const RooArgSet&, const RooCmdArg&, const RooCmdArg&, const RooCmdArg&, const RooCmdArg&, const RooCmdArg&, const RooCmdArg&, const RooCmdArg&, const RooCmdArg&)
3671
3673{
3674 return createRunningIntegral(iset,RooFit::SupNormSet(nset)) ;
3675}
3676
3677
3678
3679////////////////////////////////////////////////////////////////////////////////
3680/// Create an object that represents the running integral of the function over one or more observables listed in iset, i.e.
3681/// \f[
3682/// \int_{x_\mathrm{lo}}^x f(x') \, \mathrm{d}x'
3683/// \f]
3684///
3685/// The actual integration calculation is only performed when the return object is evaluated. The name
3686/// of the integral object is automatically constructed from the name of the input function, the variables
3687/// it integrates and the range integrates over. The default strategy to calculate the running integrals is
3688///
3689/// - If the integrand (this object) supports analytical integration, construct an integral object
3690/// that calculate the running integrals value by calculating the analytical integral each
3691/// time the running integral object is evaluated
3692///
3693/// - If the integrand (this object) requires numeric integration to construct the running integral
3694/// create an object of class RooNumRunningInt which first samples the entire function and integrates
3695/// the sampled function numerically. This method has superior performance as there is no need to
3696/// perform a full (numeric) integration for each evaluation of the running integral object, but
3697/// only when one of its parameters has changed.
3698///
3699/// The choice of strategy can be changed with the ScanAll() argument, which forces the use of the
3700/// scanning technique implemented in RooNumRunningInt for all use cases, and with the ScanNone()
3701/// argument which forces the 'integrate each evaluation' technique for all use cases. The sampling
3702/// granularity for the scanning technique can be controlled with the ScanParameters technique
3703/// which allows to specify the number of samples to be taken, and to which order the resulting
3704/// running integral should be interpolated. The default values are 1000 samples and 2nd order
3705/// interpolation.
3706///
3707/// The following named arguments are accepted
3708/// | | Effect on integral creation
3709/// |-|-------------------------------
3710/// | `SupNormSet(const RooArgSet&)` | Observables over which should be normalized _in addition_ to the integration observables
3711/// | `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
3712/// | `ScanNum()` | Apply scanning technique if cdf integral involves numeric integration
3713/// | `ScanAll()` | Always apply scanning technique
3714/// | `ScanNone()` | Never apply scanning technique
3715
3717 const RooCmdArg& arg3, const RooCmdArg& arg4, const RooCmdArg& arg5,
3718 const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8)
3719{
3720 // Define configuration for this method
3721 RooCmdConfig pc("RooAbsReal::createRunningIntegral(" + std::string(GetName()) + ")");
3722 pc.defineSet("supNormSet","SupNormSet",0,nullptr) ;
3723 pc.defineInt("numScanBins","ScanParameters",0,1000) ;
3724 pc.defineInt("intOrder","ScanParameters",1,2) ;
3725 pc.defineInt("doScanNum","ScanNum",0,1) ;
3726 pc.defineInt("doScanAll","ScanAll",0,0) ;
3727 pc.defineInt("doScanNon","ScanNone",0,0) ;
3728 pc.defineMutex("ScanNum","ScanAll","ScanNone") ;
3729
3730 // Process & check varargs
3731 pc.process(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) ;
3732 if (!pc.ok(true)) {
3733 return nullptr ;
3734 }
3735
3736 // Extract values from named arguments
3737 RooArgSet nset ;
3738 if (const RooArgSet* snset = pc.getSet("supNormSet",nullptr)) {
3739 nset.add(*snset) ;
3740 }
3741 Int_t numScanBins = pc.getInt("numScanBins") ;
3742 Int_t intOrder = pc.getInt("intOrder") ;
3743 Int_t doScanNum = pc.getInt("doScanNum") ;
3744 Int_t doScanAll = pc.getInt("doScanAll") ;
3745 Int_t doScanNon = pc.getInt("doScanNon") ;
3746
3747 // If scanning technique is not requested make integral-based cdf and return
3748 if (doScanNon) {
3749 return createIntRI(iset,nset) ;
3750 }
3751 if (doScanAll) {
3752 return createScanRI(iset,nset,numScanBins,intOrder) ;
3753 }
3754 if (doScanNum) {
3755 std::unique_ptr<RooAbsReal> tmp{createIntegral(iset)} ;
3756 Int_t isNum= !static_cast<RooRealIntegral&>(*tmp).numIntRealVars().empty();
3757
3758 if (isNum) {
3759 coutI(NumIntegration) << "RooAbsPdf::createRunningIntegral(" << GetName() << ") integration over observable(s) " << iset << " involves numeric integration," << std::endl
3760 << " constructing cdf though numeric integration of sampled pdf in " << numScanBins << " bins and applying order "
3761 << intOrder << " interpolation on integrated histogram." << std::endl
3762 << " To override this choice of technique use argument ScanNone(), to change scan parameters use ScanParameters(nbins,order) argument" << std::endl ;
3763 }
3764
3765 return isNum ? createScanRI(iset,nset,numScanBins,intOrder) : createIntRI(iset,nset) ;
3766 }
3767 return nullptr;
3768}
3769
3770
3771
3772////////////////////////////////////////////////////////////////////////////////
3773/// Utility function for createRunningIntegral that construct an object
3774/// implementing the numeric scanning technique for calculating the running integral
3775
3777{
3778 std::string name = std::string(GetName()) + "_NUMRUNINT_" + integralNameSuffix(iset,&nset).Data() ;
3779 RooRealVar* ivar = static_cast<RooRealVar*>(iset.first()) ;
3780 ivar->setBins(numScanBins,"numcdf") ;
3781 auto ret = std::make_unique<RooNumRunningInt>(name.c_str(),name.c_str(),*this,*ivar,"numrunint") ;
3782 ret->setInterpolationOrder(intOrder) ;
3783 return RooFit::makeOwningPtr<RooAbsReal>(std::move(ret));
3784}
3785
3786
3787
3788////////////////////////////////////////////////////////////////////////////////
3789/// Utility function for createRunningIntegral. It creates an
3790/// object implementing the standard (analytical) integration
3791/// technique for calculating the running integral.
3792
3794{
3795 // Make list of input arguments keeping only RooRealVars
3796 RooArgList ilist ;
3797 for(RooAbsArg * arg : iset) {
3798 if (dynamic_cast<RooRealVar*>(arg)) {
3799 ilist.add(*arg) ;
3800 } else {
3801 coutW(InputArguments) << "RooAbsPdf::createRunningIntegral(" << GetName() << ") WARNING ignoring non-RooRealVar input argument " << arg->GetName() << std::endl ;
3802 }
3803 }
3804
3805 RooArgList cloneList ;
3806 RooArgList loList ;
3807 RooArgSet clonedBranchNodes ;
3808
3809 // Setup customizer that stores all cloned branches in our non-owning list
3810 RooCustomizer cust(*this,"cdf") ;
3811 cust.setCloneBranchSet(clonedBranchNodes) ;
3812 cust.setOwning(false) ;
3813
3814 // Make integration observable x_prime for each observable x as well as an x_lowbound
3815 for(auto * rrv : static_range_cast<RooRealVar*>(ilist)) {
3816
3817 // Make clone x_prime of each c.d.f observable x represening running integral
3818 RooRealVar* cloneArg = static_cast<RooRealVar*>(rrv->clone(Form("%s_prime",rrv->GetName()))) ;
3819 cloneList.add(*cloneArg) ;
3820 cust.replaceArg(*rrv,*cloneArg) ;
3821
3822 // Make clone x_lowbound of each c.d.f observable representing low bound of x
3823 RooRealVar* cloneLo = static_cast<RooRealVar*>(rrv->clone(Form("%s_lowbound",rrv->GetName()))) ;
3824 cloneLo->setVal(rrv->getMin()) ;
3825 loList.add(*cloneLo) ;
3826
3827 // Make parameterized binning from [x_lowbound,x] for each x_prime
3828 RooParamBinning pb(*cloneLo,*rrv,100) ;
3829 cloneArg->setBinning(pb,"CDF") ;
3830
3831 }
3832
3833 RooAbsReal* tmp = static_cast<RooAbsReal*>(cust.build()) ;
3834
3835 // Construct final normalization set for c.d.f = integrated observables + any extra specified by user
3836 RooArgSet finalNset(nset) ;
3837 finalNset.add(cloneList,true) ;
3838 std::unique_ptr<RooAbsReal> cdf{tmp->createIntegral(cloneList,finalNset,"CDF")};
3839
3840 // Transfer ownership of cloned items to top-level c.d.f object
3841 cdf->addOwnedComponents(*tmp) ;
3842 cdf->addOwnedComponents(cloneList) ;
3843 cdf->addOwnedComponents(loList) ;
3844
3845 return RooFit::makeOwningPtr(std::move(cdf));
3846}
3847
3848
3849////////////////////////////////////////////////////////////////////////////////
3850/// Return a RooFunctor object bound to this RooAbsReal with given definition of observables
3851/// and parameters
3852
3853RooFunctor* RooAbsReal::functor(const RooArgList& obs, const RooArgList& pars, const RooArgSet& nset) const
3854{
3855 RooArgSet realObs;
3856 getObservables(&obs, realObs);
3857 if (realObs.size() != obs.size()) {
3858 coutE(InputArguments) << "RooAbsReal::functor(" << GetName() << ") ERROR: one or more specified observables are not variables of this p.d.f" << std::endl ;
3859 return nullptr;
3860 }
3861 RooArgSet realPars;
3862 getObservables(&pars, realPars);
3863 if (realPars.size() != pars.size()) {
3864 coutE(InputArguments) << "RooAbsReal::functor(" << GetName() << ") ERROR: one or more specified parameters are not variables of this p.d.f" << std::endl ;
3865 return nullptr;
3866 }
3867
3868 return new RooFunctor(*this,obs,pars,nset) ;
3869}
3870
3871
3872
3873////////////////////////////////////////////////////////////////////////////////
3874/// Return a ROOT TF1,2,3 object bound to this RooAbsReal with given definition of observables
3875/// and parameters
3876
3877TF1* RooAbsReal::asTF(const RooArgList& obs, const RooArgList& pars, const RooArgSet& nset) const
3878{
3879 // Check that specified input are indeed variables of this function
3880 RooArgSet realObs;
3881 getObservables(&obs, realObs) ;
3882 if (realObs.size() != obs.size()) {
3883 coutE(InputArguments) << "RooAbsReal::functor(" << GetName() << ") ERROR: one or more specified observables are not variables of this p.d.f" << std::endl ;
3884 return nullptr ;
3885 }
3886 RooArgSet realPars;
3887 getObservables(&pars, realPars) ;
3888 if (realPars.size() != pars.size()) {
3889 coutE(InputArguments) << "RooAbsReal::functor(" << GetName() << ") ERROR: one or more specified parameters are not variables of this p.d.f" << std::endl ;
3890 return nullptr ;
3891 }
3892
3893 // Check that all obs and par are of type RooRealVar
3894 for (std::size_t i=0 ; i<obs.size() ; i++) {
3895 if (dynamic_cast<RooRealVar*>(obs.at(i))==nullptr) {
3896 coutE(ObjectHandling) << "RooAbsReal::asTF(" << GetName() << ") ERROR: proposed observable " << obs.at(0)->GetName() << " is not of type RooRealVar" << std::endl ;
3897 return nullptr ;
3898 }
3899 }
3900 for (std::size_t i=0 ; i<pars.size() ; i++) {
3901 if (dynamic_cast<RooRealVar*>(pars.at(i))==nullptr) {
3902 coutE(ObjectHandling) << "RooAbsReal::asTF(" << GetName() << ") ERROR: proposed parameter " << pars.at(0)->GetName() << " is not of type RooRealVar" << std::endl ;
3903 return nullptr ;
3904 }
3905 }
3906
3907 // Create functor and TFx of matching dimension
3908 TF1* tf=nullptr ;
3909 RooFunctor* f ;
3910 switch(obs.size()) {
3911 case 1: {
3912 RooRealVar* x = static_cast<RooRealVar*>(obs.at(0)) ;
3913 f = functor(obs,pars,nset) ;
3914 tf = new TF1(GetName(),f,x->getMin(),x->getMax(),pars.size()) ;
3915 break ;
3916 }
3917 case 2: {
3918 RooRealVar* x = static_cast<RooRealVar*>(obs.at(0)) ;
3919 RooRealVar* y = static_cast<RooRealVar*>(obs.at(1)) ;
3920 f = functor(obs,pars,nset) ;
3921 tf = new TF2(GetName(),f,x->getMin(),x->getMax(),y->getMin(),y->getMax(),pars.size()) ;
3922 break ;
3923 }
3924 case 3: {
3925 RooRealVar* x = static_cast<RooRealVar*>(obs.at(0)) ;
3926 RooRealVar* y = static_cast<RooRealVar*>(obs.at(1)) ;
3927 RooRealVar* z = static_cast<RooRealVar*>(obs.at(2)) ;
3928 f = functor(obs,pars,nset) ;
3929 tf = new TF3(GetName(),f,x->getMin(),x->getMax(),y->getMin(),y->getMax(),z->getMin(),z->getMax(),pars.size()) ;
3930 break ;
3931 }
3932 default:
3933 coutE(InputArguments) << "RooAbsReal::asTF(" << GetName() << ") ERROR: " << obs.size()
3934 << " observables specified, but a ROOT TFx can only have 1,2 or 3 observables" << std::endl ;
3935 return nullptr ;
3936 }
3937
3938 // Set initial parameter values of TFx to those of RooRealVars
3939 for (std::size_t i=0 ; i<pars.size() ; i++) {
3940 RooRealVar* p = static_cast<RooRealVar*>(pars.at(i)) ;
3941 tf->SetParameter(i,p->getVal()) ;
3942 tf->SetParName(i,p->GetName()) ;
3943 //tf->SetParLimits(i,p->getMin(),p->getMax()) ;
3944 }
3945
3946 return tf ;
3947}
3948
3949
3950////////////////////////////////////////////////////////////////////////////////
3951/// Return function representing first, second or third order derivative of this function
3952
3954{
3955 std::string name=Form("%s_DERIV_%s",GetName(),obs.GetName()) ;
3956 std::string title=Form("Derivative of %s w.r.t %s ",GetName(),obs.GetName()) ;
3957 return new RooDerivative(name.c_str(),title.c_str(),*this,obs,order,eps) ;
3958}
3959
3960
3961
3962////////////////////////////////////////////////////////////////////////////////
3963/// Return function representing first, second or third order derivative of this function
3964
3965RooDerivative* RooAbsReal::derivative(RooRealVar& obs, const RooArgSet& normSet, Int_t order, double eps)
3966{
3967 std::string name=Form("%s_DERIV_%s",GetName(),obs.GetName()) ;
3968 std::string title=Form("Derivative of %s w.r.t %s ",GetName(),obs.GetName()) ;
3969 return new RooDerivative(name.c_str(),title.c_str(),*this,obs,normSet,order,eps) ;
3970}
3971
3972
3973
3974////////////////////////////////////////////////////////////////////////////////
3975/// Return function representing moment of function of given order.
3976/// \param[in] obs Observable to calculate the moments for
3977/// \param[in] order Order of the moment
3978/// \param[in] central If true, the central moment is given by \f$ \langle (x- \langle x \rangle )^2 \rangle \f$
3979/// \param[in] takeRoot Calculate the square root
3980
3981RooAbsMoment* RooAbsReal::moment(RooRealVar& obs, Int_t order, bool central, bool takeRoot)
3982{
3983 std::string name=Form("%s_MOMENT_%d%s_%s",GetName(),order,(central?"C":""),obs.GetName()) ;
3984 std::string title=Form("%sMoment of order %d of %s w.r.t %s ",(central?"Central ":""),order,GetName(),obs.GetName()) ;
3985 if (order==1) return new RooFirstMoment(name.c_str(),title.c_str(),*this,obs) ;
3986 if (order==2) return new RooSecondMoment(name.c_str(),title.c_str(),*this,obs,central,takeRoot) ;
3987 return new RooMoment(name.c_str(),title.c_str(),*this,obs,order,central,takeRoot) ;
3988}
3989
3990
3991////////////////////////////////////////////////////////////////////////////////
3992/// Return function representing moment of p.d.f (normalized w.r.t given observables) of given order.
3993/// \param[in] obs Observable to calculate the moments for
3994/// \param[in] normObs Normalise w.r.t. these observables
3995/// \param[in] order Order of the moment
3996/// \param[in] central If true, the central moment is given by \f$ \langle (x- \langle x \rangle )^2 \rangle \f$
3997/// \param[in] takeRoot Calculate the square root
3998/// \param[in] intNormObs If true, the moment of the function integrated over all normalization observables is returned.
3999
4000RooAbsMoment* RooAbsReal::moment(RooRealVar& obs, const RooArgSet& normObs, Int_t order, bool central, bool takeRoot, bool intNormObs)
4001{
4002 std::string name=Form("%s_MOMENT_%d%s_%s",GetName(),order,(central?"C":""),obs.GetName()) ;
4003 std::string title=Form("%sMoment of order %d of %s w.r.t %s ",(central?"Central ":""),order,GetName(),obs.GetName()) ;
4004
4005 if (order==1) return new RooFirstMoment(name.c_str(),title.c_str(),*this,obs,normObs,intNormObs) ;
4006 if (order==2) return new RooSecondMoment(name.c_str(),title.c_str(),*this,obs,normObs,central,takeRoot,intNormObs) ;
4007 return new RooMoment(name.c_str(),title.c_str(),*this,obs,normObs,order,central,takeRoot,intNormObs) ;
4008}
4009
4010
4011
4012////////////////////////////////////////////////////////////////////////////////
4013///
4014/// Return value of x (in range xmin,xmax) at which function equals yval.
4015/// (Calculation is performed with Brent root finding algorithm)
4016
4017double RooAbsReal::findRoot(RooRealVar& x, double xmin, double xmax, double yval)
4018{
4019 double result(0) ;
4021 return result ;
4022}
4023
4024
4025
4026////////////////////////////////////////////////////////////////////////////////
4027/// Perform a \f$ \chi^2 \f$ fit to given histogram. By default the fit is executed through the MINUIT
4028/// commands MIGRAD, HESSE in succession
4029///
4030/// The following named arguments are supported
4031///
4032/// <table>
4033/// <tr><th> <th> Options to control construction of chi2
4034/// <tr><td> `Extended(bool flag)` <td> **Only applicable when fitting a RooAbsPdf**. Scale the normalized pdf by the number of events predicted by the model instead of scaling by the total data weight.
4035/// This imposes a constraint on the predicted number of events analogous to the extended term in a likelihood fit.
4036/// - If you don't pass this command, an extended fit will be done by default if the pdf makes a prediction on the number of events
4037/// (in RooFit jargon, "if the pdf can be extended").
4038/// - Passing `Extended(true)` when the the pdf makes no prediction on the expected number of events will result in error messages,
4039/// and the chi2 will fall back to the total data weight to scale the normalized pdf.
4040/// - There are cases where the fit **must** be done in extended mode. This happens for example when you have a RooAddPdf
4041/// where the coefficients represent component yields. If the fit is not extended, these coefficients will not be
4042/// well-defined, as the RooAddPdf always normalizes itself. If you pass `Extended(false)` in such a case, an error will be
4043/// printed and you'll most likely get garbage results.
4044/// <tr><td> `Range(const char* name)` <td> Fit only data inside range with given name
4045/// <tr><td> `Range(double lo, double hi)` <td> Fit only data inside given range. A range named "fit" is created on the fly on all observables.
4046/// Multiple comma separated range names can be specified.
4047/// <tr><td> `NumCPU(int num)` <td> Parallelize NLL calculation on num CPUs
4048/// <tr><td> `Optimize(bool flag)` <td> Activate constant term optimization (on by default)
4049/// <tr><td> `IntegrateBins()` <td> Integrate PDF within each bin. This sets the desired precision.
4050///
4051/// <tr><th> <th> Options to control flow of fit procedure
4052/// <tr><td> `InitialHesse(bool flag)` <td> Flag controls if HESSE before MIGRAD as well, off by default
4053/// <tr><td> `Hesse(bool flag)` <td> Flag controls if HESSE is run after MIGRAD, on by default
4054/// <tr><td> `Minos(bool flag)` <td> Flag controls if MINOS is run after HESSE, on by default
4055/// <tr><td> `Minos(const RooArgSet& set)` <td> Only run MINOS on given subset of arguments
4056/// <tr><td> `Save(bool flag)` <td> Flag controls if RooFitResult object is produced and returned, off by default
4057/// <tr><td> `Strategy(Int_t flag)` <td> Set Minuit strategy (0 through 2, default is 1)
4058///
4059/// <tr><th> <th> Options to control informational output
4060/// <tr><td> `Verbose(bool flag)` <td> Flag controls if verbose output is printed (NLL, parameter changes during fit
4061/// <tr><td> `Timer(bool flag)` <td> Time CPU and wall clock consumption of fit steps, off by default
4062/// <tr><td> `PrintLevel(Int_t level)` <td> Set Minuit print level (-1 through 3, default is 1). At -1 all RooFit informational
4063/// messages are suppressed as well
4064/// <tr><td> `Warnings(bool flag)` <td> Enable or disable MINUIT warnings (enabled by default)
4065/// <tr><td> `PrintEvalErrors(Int_t numErr)` <td> Control number of p.d.f evaluation errors printed per likelihood evaluation. A negative
4066/// value suppress output completely, a zero value will only print the error count per p.d.f component,
4067/// a positive value is will print details of each error up to numErr messages per p.d.f component.
4068/// </table>
4069///
4070
4072 const RooCmdArg& arg3, const RooCmdArg& arg4, const RooCmdArg& arg5,
4073 const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8)
4074{
4076 l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
4077 l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
4078 l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
4079 l.Add((TObject*)&arg7) ; l.Add((TObject*)&arg8) ;
4080 return chi2FitTo(data,l) ;
4081}
4082
4083
4084
4085////////////////////////////////////////////////////////////////////////////////
4086/// Calls RooAbsReal::createChi2(RooDataSet& data, const RooLinkedList& cmdList) and returns fit result.
4087///
4088/// List of possible commands in the `cmdList`:
4089///
4090/// <table>
4091/// <tr><th> Type of CmdArg <th> Effect on \f$ \chi^2 \f$
4092/// <tr><td>
4093/// <tr><td> `DataError()` <td> Choose between:
4094/// - RooAbsData::Expected: Expected Poisson error (\f$ \sqrt{n_\text{expected}} \f$ from the PDF).
4095/// - RooAbsData::SumW2: The observed error from the square root of the sum of weights,
4096/// i.e., symmetric errors calculated with the standard deviation of a Poisson distribution.
4097/// - RooAbsData::Poisson: Asymmetric errors from the central 68 % interval around a Poisson distribution with mean \f$ n_\text{observed} \f$.
4098/// If for a given bin \f$ n_\text{expected} \f$ is lower than the \f$ n_\text{observed} \f$, the lower uncertainty is taken
4099/// (e.g., the difference between the mean and the 16 % quantile).
4100/// If \f$ n_\text{expected} \f$ is higher than \f$ n_\text{observed} \f$, the higher uncertainty is taken
4101/// (e.g., the difference between the 84 % quantile and the mean).
4102/// - RooAbsData::Auto (default): RooAbsData::Expected for unweighted data, RooAbsData::SumW2 for weighted data.
4103/// <tr><td>
4104/// `Extended()` <td> Use expected number of events of an extended p.d.f as normalization
4105/// <tr><td>
4106/// NumCPU() <td> Activate parallel processing feature
4107/// <tr><td>
4108/// Range() <td> Calculate \f$ \chi^2 \f$ only in selected region
4109/// <tr><td>
4110/// Verbose() <td> Verbose output of GOF framework
4111/// <tr><td>
4112/// IntegrateBins() <td> Integrate PDF within each bin. This sets the desired precision. Only useful for binned fits.
4113/// <tr><td> `SumCoefRange()` <td> Set the range in which to interpret the coefficients of RooAddPdf components
4114/// <tr><td> `SplitRange()` <td> Fit ranges used in different categories get named after the category.
4115/// Using `Range("range"), SplitRange()` as switches, different ranges could be set like this:
4116/// ```
4117/// myVariable.setRange("range_pi0", 135, 210);
4118/// myVariable.setRange("range_gamma", 50, 210);
4119/// ```
4120/// <tr><td> `ConditionalObservables(Args_t &&... argsOrArgSet)` <td> Define projected observables.
4121/// Arguments can either be multiple RooRealVar or a single RooArgSet containing them.
4122///
4123/// </table>
4124
4126{
4127 return RooFit::makeOwningPtr(RooFit::FitHelpers::fitTo(*this, data, cmdList, true));
4128}
4129
4130
4131
4132
4133////////////////////////////////////////////////////////////////////////////////
4134/// Create a \f$ \chi^2 \f$ variable from a histogram and this function.
4135///
4136/// \param arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8 ordered arguments
4137///
4138/// The list of supported command arguments is given in the documentation for
4139/// RooChi2Var::RooChi2Var(const char *name, const char* title, RooAbsReal& func, RooDataHist& hdata, const RooCmdArg&,const RooCmdArg&,const RooCmdArg&, const RooCmdArg&,const RooCmdArg&,const RooCmdArg&, const RooCmdArg&,const RooCmdArg&,const RooCmdArg&).
4140///
4141/// \param data Histogram with data
4142/// \return \f$ \chi^2 \f$ variable
4143
4145 const RooCmdArg &arg3, const RooCmdArg &arg4,
4146 const RooCmdArg &arg5, const RooCmdArg &arg6,
4147 const RooCmdArg &arg7, const RooCmdArg &arg8)
4148{
4150 l.Add((TObject *)&arg1);
4151 l.Add((TObject *)&arg2);
4152 l.Add((TObject *)&arg3);
4153 l.Add((TObject *)&arg4);
4154 l.Add((TObject *)&arg5);
4155 l.Add((TObject *)&arg6);
4156 l.Add((TObject *)&arg7);
4157 l.Add((TObject *)&arg8);
4158 return createChi2(data, l);
4159}
4160
4161////////////////////////////////////////////////////////////////////////////////
4162/// \see RooAbsReal::createChi2(RooDataHist&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&)
4163/// \param data hist data
4164/// \param cmdList List with RooCmdArg() from the table
4165
4167{
4168 return RooFit::makeOwningPtr(RooFit::FitHelpers::createChi2(*this, data, cmdList));
4169}
4170
4171////////////////////////////////////////////////////////////////////////////////
4172/// Perform a 2-D \f$ \chi^2 \f$ fit using a series of x and y values stored in the dataset `xydata`.
4173/// The y values can either be the event weights, or can be another column designated
4174/// by the YVar() argument. The y value must have errors defined for the \f$ \chi^2 \f$ to
4175/// be well defined.
4176///
4177/// <table>
4178/// <tr><th><th> Options to control construction of the chi-square
4179/// <tr><td> `YVar(RooRealVar& yvar)` <td> Designate given column in dataset as Y value
4180/// <tr><td> `Integrate(bool flag)` <td> Integrate function over range specified by X errors
4181/// rather than take value at bin center.
4182///
4183/// <tr><th><th> Options to control flow of fit procedure
4184/// <tr><td> `InitialHesse(bool flag)` <td> Flag controls if HESSE before MIGRAD as well, off by default
4185/// <tr><td> `Hesse(bool flag)` <td> Flag controls if HESSE is run after MIGRAD, on by default
4186/// <tr><td> `Minos(bool flag)` <td> Flag controls if MINOS is run after HESSE, on by default
4187/// <tr><td> `Minos(const RooArgSet& set)` <td> Only run MINOS on given subset of arguments
4188/// <tr><td> `Save(bool flag)` <td> Flag controls if RooFitResult object is produced and returned, off by default
4189/// <tr><td> `Strategy(Int_t flag)` <td> Set Minuit strategy (0 through 2, default is 1)
4190///
4191/// <tr><th><th> Options to control informational output
4192/// <tr><td> `Verbose(bool flag)` <td> Flag controls if verbose output is printed (NLL, parameter changes during fit
4193/// <tr><td> `Timer(bool flag)` <td> Time CPU and wall clock consumption of fit steps, off by default
4194/// <tr><td> `PrintLevel(Int_t level)` <td> Set Minuit print level (-1 through 3, default is 1). At -1 all RooFit informational
4195/// messages are suppressed as well
4196/// <tr><td> `Warnings(bool flag)` <td> Enable or disable MINUIT warnings (enabled by default)
4197/// <tr><td> `PrintEvalErrors(Int_t numErr)` <td> Control number of p.d.f evaluation errors printed per likelihood evaluation. A negative
4198/// value suppress output completely, a zero value will only print the error count per p.d.f component,
4199/// a positive value is will print details of each error up to numErr messages per p.d.f component.
4200/// </table>
4201
4203 const RooCmdArg& arg3, const RooCmdArg& arg4, const RooCmdArg& arg5,
4204 const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8)
4205{
4207 l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
4208 l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
4209 l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
4210 l.Add((TObject*)&arg7) ; l.Add((TObject*)&arg8) ;
4211 return chi2FitTo(xydata,l) ;
4212}
4213
4214
4215
4216
4217////////////////////////////////////////////////////////////////////////////////
4218/// \copydoc RooAbsReal::chi2FitTo(RooDataSet&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&)
4219
4221{
4222 return RooFit::makeOwningPtr(RooFit::FitHelpers::fitTo(*this, xydata, cmdList, true));
4223}
4224
4225
4226
4227
4228////////////////////////////////////////////////////////////////////////////////
4229/// Create a \f$ \chi^2 \f$ from a series of x and y values stored in a dataset.
4230/// The y values can either be the event weights (default), or can be another column designated
4231/// by the YVar() argument. The y value must have errors defined for the \f$ \chi^2 \f$ to
4232/// be well defined.
4233///
4234/// The following named arguments are supported
4235///
4236/// | | Options to control construction of the \f$ \chi^2 \f$
4237/// |-|-----------------------------------------
4238/// | `YVar(RooRealVar& yvar)` | Designate given column in dataset as Y value
4239/// | `Integrate(bool flag)` | Integrate function over range specified by X errors rather than take value at bin center.
4240///
4241
4243 const RooCmdArg& arg3, const RooCmdArg& arg4, const RooCmdArg& arg5,
4244 const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8)
4245{
4247 l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
4248 l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
4249 l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
4250 l.Add((TObject*)&arg7) ; l.Add((TObject*)&arg8) ;
4251 return createChi2(data,l) ;
4252}
4253
4254
4255////////////////////////////////////////////////////////////////////////////////
4256/// See RooAbsReal::createChi2(RooDataSet&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&)
4257
4259{
4260 return RooFit::makeOwningPtr(RooFit::FitHelpers::createChi2(*this, data, cmdList));
4261}
4262
4263
4264
4265////////////////////////////////////////////////////////////////////////////////
4266/// Return current evaluation error logging mode.
4267
4269{
4270 return _evalErrorMode ;
4271}
4272
4273////////////////////////////////////////////////////////////////////////////////
4274/// Set evaluation error logging mode. Options are
4275///
4276/// PrintErrors - Print each error through RooMsgService() as it occurs
4277/// CollectErrors - Accumulate errors, but do not print them. A subsequent call
4278/// to printEvalErrors() will print a summary
4279/// CountErrors - Accumulate error count, but do not print them.
4280///
4281
4283{
4284 _evalErrorMode = m;
4285}
4286
4287
4288////////////////////////////////////////////////////////////////////////////////
4289
4291{
4292 std::string plist ;
4293 for (auto const* arg : paramVars) {
4294 if (!dependsOnValue(*arg)) {
4295 coutW(InputArguments) << "RooAbsReal::setParameterizeIntegral(" << GetName()
4296 << ") function does not depend on listed parameter " << arg->GetName() << ", ignoring" << std::endl ;
4297 continue ;
4298 }
4299 if (!plist.empty()) plist += ":" ;
4300 plist += arg->GetName() ;
4301 }
4302 setStringAttribute("CACHEPARAMINT",plist.c_str()) ;
4303}
4304
4305
4306/** Base function for computing multiple values of a RooAbsReal.
4307\param ctx An evaluation context object
4308**/
4310{
4311 std::span<double> output = ctx.output();
4312
4313 // Find all servers that are serving real numbers to us, retrieve their batch data,
4314 // and switch them into "always clean" operating mode, so they return always the last-set value.
4315 struct ServerData {
4316 RooAbsArg* server;
4317 std::span<const double> batch;
4318 double oldValue;
4319 RooAbsArg::OperMode oldOperMode;
4320 bool oldValueDirty;
4321 bool oldShapeDirty;
4322 };
4323 std::vector<ServerData> ourServers;
4324 ourServers.reserve(servers().size());
4325
4326 for (auto server : servers()) {
4327 auto serverValues = ctx.at(server);
4328 if(serverValues.empty()) continue;
4329
4330 // maybe we are still missing inhibit dirty here
4331 auto oldOperMode = server->operMode();
4332 // See note at the bottom of this function to learn why we can only set
4333 // the operation mode to "always clean" if there are no other value
4334 // clients.
4335 server->setOperMode(RooAbsArg::AClean);
4336 ourServers.push_back({server,
4337 serverValues,
4338 server->isCategory() ? static_cast<RooAbsCategory const*>(server)->getCurrentIndex() : static_cast<RooAbsReal const*>(server)->_value,
4339 oldOperMode,
4340 server->_valueDirty,
4341 server->_shapeDirty});
4342 // Prevent the server from evaluating; just return cached result, which we will side load:
4343 }
4344
4345
4346 // Make sure that we restore all state when we finish:
4347 struct RestoreStateRAII {
4348 RestoreStateRAII(std::vector<ServerData>& servers) :
4349 _servers{servers} { }
4350
4351 ~RestoreStateRAII() {
4352 for (auto& serverData : _servers) {
4353 serverData.server->setCachedValue(serverData.oldValue, true);
4354 serverData.server->setOperMode(serverData.oldOperMode);
4355 serverData.server->_valueDirty = serverData.oldValueDirty;
4356 serverData.server->_shapeDirty = serverData.oldShapeDirty;
4357 }
4358 }
4359
4360 std::vector<ServerData>& _servers;
4361 } restoreState{ourServers};
4362
4363
4364 // Advising to implement the batch interface makes only sense if the batch was not a scalar.
4365 // Otherwise, there would be no speedup benefit.
4367 coutI(FastEvaluations) << "The class " << ClassName() << " does not implement the faster batch evaluation interface."
4368 << " Consider requesting or implementing it to benefit from a speed up." << std::endl;
4369 }
4370
4371
4372 // For each event, write temporary values into our servers' caches, and run a single-value computation.
4373
4374 for (std::size_t i=0; i < output.size(); ++i) {
4375 for (auto& serv : ourServers) {
4376 serv.server->setCachedValue(serv.batch[std::min(i, serv.batch.size()-1)], false);
4377 }
4378
4379 output[i] = evaluate();
4380 }
4381}
4382
4383////////////////////////////////////////////////////////////////////////////////
4384/// This function defines the analytical integral translation for the class.
4385///
4386/// \param[in] code The code that decides the integrands.
4387/// \param[in] rangeName Name of the normalization range.
4388/// \param[in] ctx An object to manage auxiliary information for code-squashing.
4389///
4390/// \returns The representative code string of the integral for the given object.
4391std::string RooAbsReal::buildCallToAnalyticIntegral(Int_t /* code */, const char * /* rangeName */,
4392 RooFit::Detail::CodeSquashContext & /*ctx*/) const
4393{
4394 std::stringstream errorMsg;
4395 errorMsg << "An analytical integral function for class \"" << ClassName() << "\" has not yet been implemented.";
4396 coutE(Minimization) << errorMsg.str() << std::endl;
4397 throw std::runtime_error(errorMsg.str().c_str());
4398}
4399
4400double RooAbsReal::_DEBUG_getVal(const RooArgSet* normalisationSet) const {
4401
4402 const bool tmpFast = _fast;
4403 const double tmp = _value;
4404
4405 double fullEval = 0.;
4406 try {
4407 fullEval = getValV(normalisationSet);
4408 }
4409 catch (CachingError& error) {
4410 throw CachingError(std::move(error),
4411 FormatPdfTree() << *this);
4412 }
4413
4414 const double ret = (_fast && !_inhibitDirty) ? _value : fullEval;
4415
4416 if (std::isfinite(ret) && ( ret != 0. ? (ret - fullEval)/ret : ret - fullEval) > 1.E-9) {
4417#ifndef NDEBUG
4419#endif
4420 FormatPdfTree formatter;
4421 formatter << "--> (Scalar computation wrong here:)\n"
4422 << GetName() << " " << this << " _fast=" << tmpFast
4423 << "\n\tcached _value=" << std::setprecision(16) << tmp
4424 << "\n\treturning =" << ret
4425 << "\n\trecomputed =" << fullEval
4426 << "\n\tnew _value =" << _value << "] ";
4427 formatter << "\nServers:";
4428 for (const auto server : _serverList) {
4429 formatter << "\n ";
4430 server->printStream(formatter.stream(), kName | kClassName | kArgs | kExtras | kAddress | kValue, kInline);
4431 }
4432
4433 throw CachingError(formatter);
4434 }
4435
4436 return ret;
4437}
4438
4439
4440bool RooAbsReal::redirectServersHook(const RooAbsCollection & newServerList, bool mustReplaceAll,
4441 bool nameChange, bool isRecursiveStep)
4442{
4444 return RooAbsArg::redirectServersHook(newServerList, mustReplaceAll, nameChange, isRecursiveStep);
4445}
4446
4447
4448////////////////////////////////////////////////////////////////////////////////
4449
4451{
4452 for (RooAbsArg* arg : servers()) {
4453 if(auto realArg = dynamic_cast<RooAbsReal*>(arg)) {
4454 realArg->enableOffsetting(flag) ;
4455 }
4456 }
4457}
4458
4459
4460RooAbsReal::Ref::Ref(double val) : _ref{RooFit::RooConst(val)} {}
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define a(i)
Definition RSha256.hxx:99
#define e(i)
Definition RSha256.hxx:103
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define coutI(a)
#define cxcoutD(a)
#define coutW(a)
#define ccoutP(a)
#define dologD(a)
#define coutF(a)
#define oocoutE(o, a)
#define coutE(a)
#define ccoutW(a)
#define ccoutD(a)
int Int_t
Definition RtypesCore.h:45
float Size_t
Definition RtypesCore.h:89
char Text_t
Definition RtypesCore.h:62
#define ClassImp(name)
Definition Rtypes.h:377
static void indent(ostringstream &buf, int indent_level)
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t SetLineColor
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t format
char name[80]
Definition TGX11.cxx:110
float xmin
float ymin
float xmax
float ymax
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2489
R__EXTERN TSystem * gSystem
Definition TSystem.h:561
std::ostream & stream()
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:79
bool dependsOn(const RooAbsCollection &serverList, const RooAbsArg *ignoreArg=nullptr, bool valueOnly=false) const
Test whether we depend on (ie, are served by) any object in the specified collection.
bool recursiveRedirectServers(const RooAbsCollection &newServerList, bool mustReplaceAll=false, bool nameChange=false, bool recurseInNewSet=true)
Recursively replace all servers with the new servers in newSet.
const TNamed * namePtr() const
De-duplicated pointer to this object's name.
Definition RooAbsArg.h:535
R__DEPRECATED(6, 36, "Use getObservables().") RooFit R__DEPRECATED(6, 36, "Use getObservables().") RooFit R__DEPRECATED(6, 36, "Use getObservables().") RooFit const RooAbsArg &testArg const
Definition RooAbsArg.h:145
void setShapeDirty()
Notify that a shape-like property (e.g. binning) has changed.
Definition RooAbsArg.h:467
void setStringAttribute(const Text_t *key, const Text_t *value)
Associate string 'value' to this object under key 'key'.
bool isValueDirtyAndClear() const
Definition RooAbsArg.h:408
bool _fast
Definition RooAbsArg.h:689
RooFit::OwningPtr< RooArgSet > getParameters(const RooAbsData *data, bool stripDisconnected=true) const
Create a list of leaf nodes in the arg tree starting with ourself as top node that don't match any of...
RooFit::OwningPtr< RooArgSet > getObservables(const RooArgSet &set, bool valueOnly=true) const
Given a set of possible observables, return the observables that this PDF depends on.
const Text_t * getStringAttribute(const Text_t *key) const
Get string attribute mapped under key 'key'.
RooFit::OwningPtr< RooArgSet > getComponents() const
Create a RooArgSet with all components (branch nodes) of the expression tree headed by this object.
const RefCountList_t & servers() const
List of all servers of this object.
Definition RooAbsArg.h:180
bool dependsOnValue(const RooAbsCollection &serverList, const RooAbsArg *ignoreArg=nullptr) const
Check whether this object depends on values from an element in the serverList.
Definition RooAbsArg.h:108
void setValueDirty()
Mark the element dirty. This forces a re-evaluation when a value is requested.
Definition RooAbsArg.h:462
RooFit::OwningPtr< RooArgSet > getVariables(bool stripDisconnected=true) const
Return RooArgSet with all variables (tree leaf nodes of expression tree)
void printMultiline(std::ostream &os, Int_t contents, bool verbose=false, TString indent="") const override
Implement multi-line detailed printing.
virtual RooAbsArg * cloneTree(const char *newname=nullptr) const
Clone tree expression of objects.
TString cleanBranchName() const
Construct a mangled name from the actual name that is free of any math symbols that might be interpre...
Int_t numProxies() const
Return the number of registered proxies.
static bool _inhibitDirty
Definition RooAbsArg.h:668
void setAttribute(const Text_t *name, bool value=true)
Set (default) or clear a named boolean attribute of this object.
void setProxyNormSet(const RooArgSet *nset)
Forward a change in the cached normalization argset to all the registered proxies.
void branchNodeServerList(RooAbsCollection *list, const RooAbsArg *arg=nullptr, bool recurseNonDerived=false) const
Fill supplied list with all branch nodes of the arg tree starting with ourself as top node.
RooAbsProxy * getProxy(Int_t index) const
Return the nth proxy from the proxy list.
TObject * Clone(const char *newname=nullptr) const override
Make a clone of an object using the Streamer facility.
Definition RooAbsArg.h:91
RefCountList_t _serverList
Definition RooAbsArg.h:606
void leafNodeServerList(RooAbsCollection *list, const RooAbsArg *arg=nullptr, bool recurseNonDerived=false) const
Fill supplied list with all leaf nodes of the arg tree, starting with ourself as top node.
virtual bool isFundamental() const
Is this object a fundamental type that can be added to a dataset? Fundamental-type subclasses overrid...
Definition RooAbsArg.h:223
virtual bool redirectServersHook(const RooAbsCollection &newServerList, bool mustReplaceAll, bool nameChange, bool isRecursiveStep)
Function that is called at the end of redirectServers().
virtual bool checkObservables(const RooArgSet *nset) const
Overloadable function in which derived classes can implement consistency checks of the variables.
void treeNodeServerList(RooAbsCollection *list, const RooAbsArg *arg=nullptr, bool doBranch=true, bool doLeaf=true, bool valueOnly=false, bool recurseNonDerived=false) const
Fill supplied list with nodes of the arg tree, following all server links, starting with ourself as t...
Abstract base class for RooRealVar binning definitions.
virtual bool isParameterized() const
Interface function.
virtual RooAbsReal * highBoundFunc() const
Return pointer to RooAbsReal parameterized upper bound, if any.
virtual RooAbsReal * lowBoundFunc() const
Return pointer to RooAbsReal parameterized lower bound, if any.
Abstract base class for objects that represent a discrete value that can be set from the outside,...
virtual bool setIndex(value_type index, bool printError=true)=0
Change category state by specifying the index code of the desired state.
A space to attach TBranches.
virtual value_type getCurrentIndex() const
Return index number of current state.
bool isSignType(bool mustHaveZero=false) const
Determine if category has 2 or 3 states with index values -1,0,1.
Abstract container object that can hold multiple RooAbsArg objects.
RooFit::UniqueId< RooAbsCollection > const & uniqueId() const
Returns a unique ID that is different for every instantiated RooAbsCollection.
virtual void removeAll()
Remove all arguments from our set, deleting them if we own them.
virtual bool remove(const RooAbsArg &var, bool silent=false, bool matchByNameOnly=false)
Remove the specified argument from our list.
const char * GetName() const override
Returns name of object.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
TObject * Clone(const char *newname=nullptr) const override
Make a clone of an object using the Streamer facility.
bool overlaps(Iterator_t otherCollBegin, Iterator_t otherCollEnd) const
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...
Storage_t::size_type size() const
RooAbsArg * first() const
virtual bool replace(const RooAbsArg &var1, const RooAbsArg &var2)
Replace var1 with var2 and return true for success.
virtual bool addOwned(RooAbsArg &var, bool silent=false)
Add an argument and transfer the ownership to the collection.
virtual RooAbsArg * addClone(const RooAbsArg &var, bool silent=false)
Add a clone of the specified argument to list.
std::string contentsString() const
Return comma separated list of contained object names as STL string.
RooAbsArg * find(const char *name) const
Find object with given name in list.
Abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:57
virtual const RooArgSet * get() const
Definition RooAbsData.h:101
virtual Int_t numEntries() const
Return number of entries in dataset, i.e., count unweighted entries.
Abstract interface for evaluating a real-valued function of one real variable and performing numerica...
Definition RooAbsFunc.h:27
virtual double getMaxLimit(UInt_t dimension) const =0
virtual double operator()(const double xvector[]) const =0
virtual double getMinLimit(UInt_t dimension) const =0
Abstract base class for objects that are lvalues, i.e.
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:40
virtual double expectedEvents(const RooArgSet *nset) const
Return expected number of events to be used in calculation of extended likelihood.
static TClass * Class()
@ CanNotBeExtended
Definition RooAbsPdf.h:212
const char * normRange() const
Definition RooAbsPdf.h:250
RooFit::OwningPtr< RooDataSet > generate(const RooArgSet &whatVars, Int_t nEvents, const RooCmdArg &arg1, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={})
See RooAbsPdf::generate(const RooArgSet&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,...
Definition RooAbsPdf.h:57
virtual ExtendMode extendMode() const
Returns ability of PDF to provide extended likelihood terms.
Definition RooAbsPdf.h:216
Abstract interface for proxy classes.
Definition RooAbsProxy.h:37
Abstract base class for objects that represent a real value that may appear on the left hand side of ...
virtual double getMax(const char *name=nullptr) const
Get maximum of currently defined range.
TH1 * createHistogram(const char *name, const RooCmdArg &arg1={}, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={}) const
virtual double getMin(const char *name=nullptr) const
Get minimum of currently defined range.
void setServerValues(const char *tmp)
Definition RooAbsReal.h:312
void setMessage(const char *tmp)
Definition RooAbsReal.h:311
Ref(RooAbsReal &ref)
Definition RooAbsReal.h:70
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:59
RooDataHist * fillDataHist(RooDataHist *hist, const RooArgSet *nset, double scaleFactor, bool correctForBinVolume=false, bool showProgress=false) const
Fill a RooDataHist with values sampled from this function at the bin centers.
virtual void selectNormalizationRange(const char *rangeName=nullptr, bool force=false)
Interface function to force use of a given normalization range to interpret function value.
void plotOnCompSelect(RooArgSet *selNodes) const
Helper function for plotting of composite p.d.fs.
bool isSelectedComp() const
If true, the current pdf is a selected component (for use in plotting)
std::unique_ptr< TreeReadBuffer > _treeReadBuffer
Definition RooAbsReal.h:542
virtual std::list< double > * binBoundaries(RooAbsRealLValue &obs, double xlo, double xhi) const
Retrieve bin boundaries if this distribution is binned in obs.
RooFit::OwningPtr< RooAbsReal > createIntegral(const RooArgSet &iset, const RooCmdArg &arg1, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={}) const
Create an object that represents the integral of the function over one or more observables listed in ...
void selectComp(bool flag)
Definition RooAbsReal.h:378
TString _label
Plot label for objects value.
Definition RooAbsReal.h:539
bool _selectComp
A buffer for reading values from trees.
Definition RooAbsReal.h:543
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:103
double findRoot(RooRealVar &x, double xmin, double xmax, double yval)
Return value of x (in range xmin,xmax) at which function equals yval.
virtual double getValV(const RooArgSet *normalisationSet=nullptr) const
Return value of object.
RooAbsReal()
coverity[UNINIT_CTOR] Default constructor
friend class RooRealBinding
Definition RooAbsReal.h:402
virtual void fixAddCoefNormalization(const RooArgSet &addNormSet=RooArgSet(), bool force=true)
Fix the interpretation of the coefficient of any RooAddPdf component in the expression tree headed by...
static std::map< const RooAbsArg *, std::pair< std::string, std::list< EvalError > > > _evalErrorList
Definition RooAbsReal.h:547
virtual Int_t getAnalyticalIntegralWN(RooArgSet &allVars, RooArgSet &analVars, const RooArgSet *normSet, const char *rangeName=nullptr) const
Variant of getAnalyticalIntegral that is also passed the normalization set that should be applied to ...
bool _forceNumInt
Force numerical integration if flag set.
Definition RooAbsReal.h:540
~RooAbsReal() override
Destructor.
void setParameterizeIntegral(const RooArgSet &paramVars)
bool matchArgsByName(const RooArgSet &allArgs, RooArgSet &matchedArgs, const TList &nameList) const
Check if allArgs contains matching elements for each name in nameList.
static bool hideOffset()
void setTreeBranchStatus(TTree &t, bool active) override
(De)Activate associated tree branch
TH1 * fillHistogram(TH1 *hist, const RooArgList &plotVars, double scaleFactor=1, const RooArgSet *projectedVars=nullptr, bool scaling=true, const RooArgSet *condObs=nullptr, bool setError=true) const
Fill the ROOT histogram 'hist' with values sampled from this function at the bin centers.
RooFit::OwningPtr< RooAbsReal > createScanRI(const RooArgSet &iset, const RooArgSet &nset, Int_t numScanBins, Int_t intOrder)
Utility function for createRunningIntegral that construct an object implementing the numeric scanning...
double _DEBUG_getVal(const RooArgSet *normalisationSet) const
Debug version of getVal(), which is slow and does error checking.
RooFit::OwningPtr< RooAbsArg > createFundamental(const char *newname=nullptr) const override
Create a RooRealVar fundamental object with our properties.
bool plotSanityChecks(RooPlot *frame) const
Utility function for plotOn(), perform general sanity check on frame to ensure safe plotting operatio...
RooFit::OwningPtr< RooAbsFunc > bindVars(const RooArgSet &vars, const RooArgSet *nset=nullptr, bool clipInvalid=false) const
Create an interface adaptor f(vars) that binds us to the specified variables (in arbitrary order).
virtual void selectNormalization(const RooArgSet *depSet=nullptr, bool force=false)
Interface function to force use of a given set of observables to interpret function value.
RooDerivative * derivative(RooRealVar &obs, Int_t order=1, double eps=0.001)
Return function representing first, second or third order derivative of this function.
virtual RooFit::OwningPtr< RooFitResult > chi2FitTo(RooDataHist &data, const RooCmdArg &arg1={}, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={})
Perform a fit to given histogram.
TF1 * asTF(const RooArgList &obs, const RooArgList &pars=RooArgList(), const RooArgSet &nset=RooArgSet()) const
Return a ROOT TF1,2,3 object bound to this RooAbsReal with given definition of observables and parame...
TString _unit
Unit for objects value.
Definition RooAbsReal.h:538
static RooNumIntConfig * defaultIntegratorConfig()
Returns the default numeric integration configuration for all RooAbsReals.
bool readFromStream(std::istream &is, bool compact, bool verbose=false) override
Read object contents from stream (dummy for now)
bool matchArgs(const RooArgSet &allDeps, RooArgSet &numDeps, const RooArgProxy &a) const
Utility function for use in getAnalyticalIntegral().
void fillTreeBranch(TTree &t) override
Fill the tree branch that associated with this object with its current value.
void printMultiline(std::ostream &os, Int_t contents, bool verbose=false, TString indent="") const override
Structure printing.
virtual RooPlot * plotAsymOn(RooPlot *frame, const RooAbsCategoryLValue &asymCat, PlotOpt o) const
bool operator==(double value) const
Equality operator comparing to a double.
static ErrorLoggingMode evalErrorLoggingMode()
Return current evaluation error logging mode.
bool redirectServersHook(const RooAbsCollection &newServerList, bool mustReplaceAll, bool nameChange, bool isRecursiveStep) override
Function that is called at the end of redirectServers().
virtual bool isValidReal(double, bool printError=false) const
Interface function to check if given value is a valid value for this object. Returns true unless over...
Definition RooAbsReal.h:448
void setIntegratorConfig()
Remove the specialized numeric integration configuration associated with this object.
void printValue(std::ostream &os) const override
Print object value.
bool isIdentical(const RooAbsArg &other, bool assumeSameType=false) const override
virtual RooFit::OwningPtr< RooAbsReal > createProfile(const RooArgSet &paramsOfInterest)
Create a RooProfileLL object that eliminates all nuisance parameters in the present function.
static bool _hideOffset
Offset hiding flag.
Definition RooAbsReal.h:550
static ErrorLoggingMode _evalErrorMode
Definition RooAbsReal.h:546
void attachToVStore(RooVectorDataStore &vstore) override
static Int_t _evalErrorCount
Definition RooAbsReal.h:548
void copyCache(const RooAbsArg *source, bool valueOnly=false, bool setValDirty=true) override
Copy the cached value of another RooAbsArg to our cache.
TH1 * createHistogram(RooStringView varNameList, Int_t xbins=0, Int_t ybins=0, Int_t zbins=0) const
Create and fill a ROOT histogram TH1, TH2 or TH3 with the values of this function for the variables w...
virtual void fixAddCoefRange(const char *rangeName=nullptr, bool force=true)
Fix the interpretation of the coefficient of any RooAddPdf component in the expression tree headed by...
double _value
Cache for current value of object.
Definition RooAbsReal.h:537
virtual double analyticalIntegral(Int_t code, const char *rangeName=nullptr) const
Implements the actual analytical integral(s) advertised by getAnalyticalIntegral.
void attachToTree(TTree &t, Int_t bufSize=32000) override
Attach object to a branch of given TTree.
RooNumIntConfig * specialIntegratorConfig() const
Returns the specialized integrator configuration for this RooAbsReal.
void writeToStream(std::ostream &os, bool compact) const override
Write object contents to stream (dummy for now)
double traceEval(const RooArgSet *set) const
Calculate current value of object, with error tracing wrapper.
double getPropagatedError(const RooFitResult &fr, const RooArgSet &nset={}) const
Propagates parameter uncertainties to an uncertainty estimate for this RooAbsReal.
static void setHideOffset(bool flag)
static void globalSelectComp(bool flag)
Global switch controlling the activation of the selectComp() functionality.
RooAbsMoment * moment(RooRealVar &obs, Int_t order, bool central, bool takeRoot)
Return function representing moment of function of given order.
virtual std::string buildCallToAnalyticIntegral(Int_t code, const char *rangeName, RooFit::Detail::CodeSquashContext &ctx) const
This function defines the analytical integral translation for the class.
RooPlot * plotOnWithErrorBand(RooPlot *frame, const RooFitResult &fr, double Z, const RooArgSet *params, const RooLinkedList &argList, bool method1) const
Plot function or PDF on frame with support for visualization of the uncertainty encoded in the given ...
RooFit::UniqueId< RooArgSet >::Value_t _lastNormSetId
Component selection flag for RooAbsPdf::plotCompOn.
Definition RooAbsReal.h:544
const char * getPlotLabel() const
Get the label associated with the variable.
RooFit::OwningPtr< RooAbsReal > createRunningIntegral(const RooArgSet &iset, const RooArgSet &nset={})
Calls createRunningIntegral(const RooArgSet&, const RooCmdArg&, const RooCmdArg&, const RooCmdArg&,...
std::unique_ptr< RooNumIntConfig > _specIntegratorConfig
Definition RooAbsReal.h:541
virtual Int_t getAnalyticalIntegral(RooArgSet &allVars, RooArgSet &analVars, const char *rangeName=nullptr) const
Interface function getAnalyticalIntergral advertises the analytical integrals that are supported.
static Int_t numEvalErrors()
Return the number of logged evaluation errors since the last clearing.
static void setEvalErrorLoggingMode(ErrorLoggingMode m)
Set evaluation error logging mode.
virtual void preferredObservableScanOrder(const RooArgSet &obs, RooArgSet &orderedObs) const
Interface method for function objects to indicate their preferred order of observables for scanning t...
virtual double maxVal(Int_t code) const
Return maximum value for set of observables identified by code assigned in getMaxVal.
void findInnerMostIntegration(const RooArgSet &allObs, RooArgSet &innerObs, const char *rangeName) const
Utility function for createIntObj() that aids in the construct of recursive integrals over functions ...
TString integralNameSuffix(const RooArgSet &iset, const RooArgSet *nset=nullptr, const char *rangeName=nullptr, bool omitEmpty=false) const
Construct string with unique suffix name to give to integral object that encodes integrated observabl...
virtual double evaluate() const =0
Evaluate this PDF / function / constant. Needs to be overridden by all derived classes.
TString getTitle(bool appendUnit=false) const
Return this variable's title string.
void logEvalError(const char *message, const char *serverValueString=nullptr) const
Log evaluation error message.
virtual double analyticalIntegralWN(Int_t code, const RooArgSet *normSet, const char *rangeName=nullptr) const
Implements the actual analytical integral(s) advertised by getAnalyticalIntegral.
const Text_t * getUnit() const
Definition RooAbsReal.h:143
const RooNumIntConfig * getIntegratorConfig() const
Return the numeric integration configuration used for this object.
static void printEvalErrors(std::ostream &os=std::cout, Int_t maxPerNode=10000000)
Print all outstanding logged evaluation error on the given ostream.
RooFit::OwningPtr< RooAbsReal > createIntRI(const RooArgSet &iset, const RooArgSet &nset={})
Utility function for createRunningIntegral.
virtual void enableOffsetting(bool)
static void clearEvalErrorLog()
Clear the stack of evaluation error messages.
RooFit::OwningPtr< RooAbsReal > createIntObj(const RooArgSet &iset, const RooArgSet *nset, const RooNumIntConfig *cfg, const char *rangeName) const
Internal utility function for createIntegral() that creates the actual integral object.
RooFunctor * functor(const RooArgList &obs, const RooArgList &pars=RooArgList(), const RooArgSet &nset=RooArgSet()) const
Return a RooFunctor object bound to this RooAbsReal with given definition of observables and paramete...
const RooAbsReal * createPlotProjection(const RooArgSet &depVars, const RooArgSet &projVars, RooArgSet *&cloneSet) const
Utility function for plotOn() that creates a projection of a function or p.d.f to be plotted on a Roo...
virtual std::list< double > * plotSamplingHint(RooAbsRealLValue &obs, double xlo, double xhi) const
Interface for returning an optional hint for initial sampling points when constructing a curve projec...
void setPlotLabel(const char *label)
Set the label associated with this variable.
virtual RooPlot * plotOn(RooPlot *frame, const RooCmdArg &arg1={}, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={}, const RooCmdArg &arg9={}, const RooCmdArg &arg10={}) const
Plot (project) PDF on specified frame.
virtual void doEval(RooFit::EvalContext &) const
Base function for computing multiple values of a RooAbsReal.
void makeProjectionSet(const RooAbsArg *plotVar, const RooArgSet *allVars, RooArgSet &projectedVars, bool silent) const
Utility function for plotOn() that constructs the set of observables to project when plotting ourselv...
virtual Int_t getMaxVal(const RooArgSet &vars) const
Advertise capability to determine maximum value of function for given set of observables.
virtual RooFit::OwningPtr< RooAbsReal > createChi2(RooDataHist &data, const RooLinkedList &cmdList)
virtual double offset() const
Definition RooAbsReal.h:372
static bool _globalSelectComp
Definition RooAbsReal.h:549
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
Abstract interface for RooAbsArg proxy classes.
Definition RooArgProxy.h:24
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
RooArgSet * snapshot(bool deepCopy=true) const
Use RooAbsCollection::snapshot(), but return as RooArgSet.
Definition RooArgSet.h:154
RooArgSet * selectByName(const char *nameList, bool verbose=false) const
Use RooAbsCollection::selectByName(), but return as RooArgSet.
Definition RooArgSet.h:144
RooArgSet * selectCommon(const RooAbsCollection &refColl) const
Use RooAbsCollection::selecCommon(), but return as RooArgSet.
Definition RooArgSet.h:149
Implement the abstract 1-dimensional root finding interface using the Brent-Decker method.
bool findRoot(double &result, double xlo, double xhi, double value=0) const
Do the root finding using the Brent-Decker method.
Object to represent discrete states.
Definition RooCategory.h:28
Named container for two doubles, two integers two object points and three string pointers that can be...
Definition RooCmdArg.h:26
static const RooCmdArg & none()
Return reference to null argument.
Definition RooCmdArg.cxx:48
const char * getString(Int_t idx) const
Return string stored in slot idx.
Definition RooCmdArg.h:95
void setString(Int_t idx, const char *value)
Definition RooCmdArg.h:78
Configurable parser for RooCmdArg named arguments.
void defineMutex(const char *head, Args_t &&... tail)
Define arguments where any pair is mutually exclusive.
bool process(const RooCmdArg &arg)
Process given RooCmdArg.
bool hasProcessed(const char *cmdName) const
Return true if RooCmdArg with name 'cmdName' has been processed.
double getDouble(const char *name, double defaultValue=0.0) const
Return double property registered with name 'name'.
bool defineDouble(const char *name, const char *argName, int doubleNum, double defValue=0.0)
Define double property name 'name' mapped to double in slot 'doubleNum' in RooCmdArg with name argNam...
static void stripCmdList(RooLinkedList &cmdList, const char *cmdsToPurge)
Utility function that strips command names listed (comma separated) in cmdsToPurge from cmdList.
RooArgSet * getSet(const char *name, RooArgSet *set=nullptr) const
Return RooArgSet property registered with name 'name'.
bool defineSet(const char *name, const char *argName, int setNum, const RooArgSet *set=nullptr)
Define TObject property name 'name' mapped to object in slot 'setNum' in RooCmdArg with name argName ...
bool ok(bool verbose) const
Return true of parsing was successful.
bool defineObject(const char *name, const char *argName, int setNum, const TObject *obj=nullptr, bool isArray=false)
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 convEmptyToNull=false) const
Return string property registered with name 'name'.
bool defineString(const char *name, const char *argName, int stringNum, const char *defValue="", bool appendMode=false)
Define double property name 'name' mapped to double in slot 'stringNum' in RooCmdArg with name argNam...
const RooLinkedList & getObjectList(const char *name) const
Return list of objects registered with name 'name'.
bool defineInt(const char *name, const char *argName, int intNum, int defValue=0)
Define integer property name 'name' mapped to integer in slot 'intNum' in RooCmdArg with name argName...
void allowUndefined(bool flag=true)
If flag is true the processing of unrecognized RooCmdArgs is not considered an error.
int getInt(const char *name, int defaultValue=0) const
Return integer property registered with name 'name'.
TObject * getObject(const char *name, TObject *obj=nullptr) const
Return TObject property registered with name 'name'.
One-dimensional graphical representation of a real-valued function.
Definition RooCurve.h:36
@ Extended
Definition RooCurve.h:39
@ NoWings
Definition RooCurve.h:39
@ Straight
Definition RooCurve.h:39
RooCurve * makeErrorBand(const std::vector< RooCurve * > &variations, double Z=1) const
Construct filled RooCurve represented error band that captures alpha% of the variations of the curves...
Definition RooCurve.cxx:701
static TClass * Class()
RooCustomizer is a factory class to produce clones of a prototype composite PDF object with the same ...
void setCloneBranchSet(RooArgSet &cloneBranchSet)
Releases ownership of list of cloned branch nodes.
void replaceArg(const RooAbsArg &orig, const RooAbsArg &subst)
Replace any occurrence of arg 'orig' with arg 'subst'.
RooAbsArg * build(const char *masterCatState, bool verbose=false)
Build a clone of the prototype executing all registered 'replace' rules and 'split' rules for the mas...
void setOwning(bool flag)
If flag is true, make customizer own all created components.
Container class to hold N-dimensional binned data.
Definition RooDataHist.h:40
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 binVolume(std::size_t i) const
Return bin volume of i-th bin.
const RooArgSet * get() const override
Get bin centre of current bin.
Definition RooDataHist.h:82
Container class to hold unbinned data.
Definition RooDataSet.h:33
Represents the first, second, or third order derivative of any RooAbsReal as calculated (numerically)...
RooFitResult is a container class to hold the input and output of a PDF fit to a dataset.
const TMatrixDSym & covarianceMatrix() const
Return covariance matrix.
TMatrixDSym reducedCovarianceMatrix(const RooArgList &params) const
Return a reduced covariance matrix (Note that Vred is a simple sub-matrix of V, row/columns are order...
const RooArgList & floatParsFinal() const
Return list of floating parameters after fit.
RooAbsPdf * createHessePdf(const RooArgSet &params) const
Return a p.d.f that represents the fit result as a multi-variate probability densisty function on the...
A class to maintain the context for squashing of RooFit models into code.
std::span< const double > at(RooAbsArg const *arg, RooAbsArg const *caller=nullptr)
std::span< double > output()
A RooFormulaVar is a generic implementation of a real-valued object, which takes a RooArgList of serv...
Lightweight interface adaptor that exports a RooAbsPdf as a functor.
Definition RooFunctor.h:25
Graphical representation of binned data based on the TGraphAsymmErrors class.
Definition RooHist.h:29
Collection class for internal use, storing a collection of RooAbsArg pointers in a doubly linked list...
void Delete(Option_t *o=nullptr) override
Remove all elements in collection and delete all elements NB: Collection does not own elements,...
virtual void Add(TObject *arg)
RooLinkedListIterImpl begin() const
TObject * FindObject(const char *name) const override
Return pointer to object with given name.
static RooMsgService & instance()
Return reference to singleton instance.
bool isActive(T self, RooFit::MsgTopic topic, RooFit::MsgLevel level)
Check if logging is active for given object/topic/RooFit::MsgLevel combination.
Holds the configuration parameters of the various numeric integrators used by RooRealIntegral.
static RooNumIntConfig & defaultConfig()
Return reference to instance of default numeric integrator configuration object.
Implementation of RooAbsBinning that constructs a binning with a range definition that depends on ext...
Plot frame and a container for graphics objects within that frame.
Definition RooPlot.h:45
void remove(const char *name=nullptr, bool deleteToo=true)
Remove object with given name, or last object added if no name is given.
Definition RooPlot.cxx:868
bool drawBefore(const char *before, const char *target)
Change the order in which our contained objects are drawn so that the target object is drawn just bef...
Definition RooPlot.cxx:906
TObject * findObject(const char *name, const TClass *tClass=nullptr) const
Find the named object in our list of items and return a pointer to it.
Definition RooPlot.cxx:942
const RooArgSet * getNormVars() const
Definition RooPlot.h:152
double GetMaximum(double maxval=FLT_MAX) const
Definition RooPlot.cxx:1272
TAttLine * getAttLine(const char *name=nullptr) const
Return a pointer to the line attributes of the named object in this plot, or zero if the named object...
Definition RooPlot.cxx:807
Stat_t numItems() const
Definition RooPlot.h:119
TAttFill * getAttFill(const char *name=nullptr) const
Return a pointer to the fill attributes of the named object in this plot, or zero if the named object...
Definition RooPlot.cxx:817
TObject * getObject(Int_t idx) const
Return the name of the object at slot 'idx' in this RooPlot.
Definition RooPlot.cxx:791
RooAbsRealLValue * getPlotVar() const
Definition RooPlot.h:143
TAttMarker * getAttMarker(const char *name=nullptr) const
Return a pointer to the marker attributes of the named object in this plot, or zero if the named obje...
Definition RooPlot.cxx:827
TAxis * GetXaxis() const
Definition RooPlot.cxx:1262
RooCurve * getCurve(const char *name=nullptr) const
Return a RooCurve pointer of the named object in this plot, or zero if the named object does not exis...
Definition RooPlot.cxx:848
SetMaximum(ymax)
Int_t GetNbinsX() const
Definition RooPlot.cxx:1266
SetMinimum(ymin)
void addPlotable(RooPlotable *plotable, Option_t *drawOptions="", bool invisible=false, bool refreshNorm=false)
Add the specified plotable object to our plot.
Definition RooPlot.cxx:516
double GetMinimum(double minval=-FLT_MAX) const
Definition RooPlot.cxx:1270
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,...
Performs hybrid numerical/analytical integrals of RooAbsReal objects.
const RooArgSet & numIntRealVars() const
void setAllowComponentSelection(bool allow)
Set component selection to be allowed/forbidden.
static TClass * Class()
Variable that can be changed from the outside.
Definition RooRealVar.h:37
void setVal(double value) override
Set value of variable to 'value'.
void setBinning(const RooAbsBinning &binning, const char *name=nullptr)
Add given binning under name 'name' with this variable.
void setBins(Int_t nBins, const char *name=nullptr)
Create a uniform binning under name 'name' for this variable.
The RooStringView is a wrapper around a C-style string that can also be constructed from a std::strin...
void setBuffer(RooAbsReal *real, double *newBuf)
Uses std::vector to store data columns.
RealVector * addReal(RooAbsReal *real)
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:37
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:39
Line Attributes class.
Definition TAttLine.h:18
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:42
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:43
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:40
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition TAttMarker.h:38
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition TAttMarker.h:40
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition TAttMarker.h:45
Class to manage histogram axis.
Definition TAxis.h:31
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx:478
Double_t GetXmax() const
Definition TAxis.h:140
Double_t GetXmin() const
Definition TAxis.h:139
A TTree is a list of TBranches.
Definition TBranch.h:93
TObjArray * GetListOfLeaves()
Definition TBranch.h:247
Int_t Fill()
Definition TBranch.h:205
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
1-Dim function class
Definition TF1.h:233
virtual void SetParName(Int_t ipar, const char *name)
Set name of parameter number ipar.
Definition TF1.cxx:3448
virtual void SetParameter(Int_t param, Double_t value)
Definition TF1.h:667
A 2-Dim function with parameters.
Definition TF2.h:29
A 3-Dim function with parameters.
Definition TF3.h:28
void SetName(const char *name="") override
Set graph name.
Definition TGraph.cxx:2381
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:59
TAxis * GetZaxis()
Definition TH1.h:326
virtual Int_t GetNbinsY() const
Definition TH1.h:298
virtual Int_t GetNbinsZ() const
Definition TH1.h:299
virtual Int_t GetDimension() const
Definition TH1.h:283
TAxis * GetXaxis()
Definition TH1.h:324
virtual Int_t GetBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Return Global bin number corresponding to binx,y,z.
Definition TH1.cxx:4952
virtual Int_t GetNbinsX() const
Definition TH1.h:297
virtual void SetBinError(Int_t bin, Double_t error)
Set the bin Error Note that this resets the bin eror option to be of Normal Type and for the non-empt...
Definition TH1.cxx:9197
TAxis * GetYaxis()
Definition TH1.h:325
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
Definition TH1.cxx:9213
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition TLeaf.h:57
virtual const char * GetTypeName() const
Definition TLeaf.h:139
virtual TLeaf * GetLeafCounter(Int_t &countval) const
Return a pointer to the counter of this leaf (if any) or store the number of elements that the leaf c...
Definition TLeaf.cxx:249
A doubly linked list.
Definition TList.h:38
void Add(TObject *obj) override
Definition TList.h:83
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:468
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
TString fName
Definition TNamed.h:32
TObject * At(Int_t idx) const override
Definition TObjArray.h:164
Collectable string class.
Definition TObjString.h:28
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:438
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:207
Basic string class.
Definition TString.h:139
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition TString.cxx:457
const char * Data() const
Definition TString.h:376
TString & Prepend(const char *cs)
Definition TString.h:673
Bool_t IsNull() const
Definition TString.h:414
TString & Append(const char *cs)
Definition TString.h:572
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
virtual void StackTrace()
Print a stack trace.
Definition TSystem.cxx:734
A TTree represents a columnar dataset.
Definition TTree.h:79
virtual void SetBranchStatus(const char *bname, bool status=true, UInt_t *found=nullptr)
Set branch status to Process or DoNotProcess.
Definition TTree.cxx:8534
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition TTree.cxx:5294
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=nullptr)
Change branch address, dealing with clone trees properly.
Definition TTree.cxx:8385
TBranch * Branch(const char *name, T *obj, Int_t bufsize=32000, Int_t splitlevel=99)
Add a new branch, and infer the data type from the type of obj being passed.
Definition TTree.h:353
RooCmdArg YVar(const RooAbsRealLValue &var, const RooCmdArg &arg={})
RooCmdArg ZVar(const RooAbsRealLValue &var, const RooCmdArg &arg={})
RooCmdArg SupNormSet(const RooArgSet &nset)
RooCmdArg Binning(const RooAbsBinning &binning)
RooCmdArg NormRange(const char *rangeNameList)
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
#define F(x, y, z)
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< T > compileForNormSet(T const &arg, RooArgSet const &normSet)
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition JSONIO.h:26
@ FastEvaluations
OwningPtr< T > makeOwningPtr(std::unique_ptr< T > &&ptr)
Internal helper to turn a std::unique_ptr<T> into an OwningPtr.
Definition Config.h:40
T * OwningPtr
An alias for raw pointers for indicating that the return type of a RooFit function is an owning point...
Definition Config.h:35
RooArgSet selectFromArgSet(RooArgSet const &, std::string const &names)
bool checkIfRangesOverlap(RooArgSet const &observables, std::vector< std::string > const &rangeNames)
std::string getColonSeparatedNameString(RooArgSet const &argSet, char delim=':')
Bool_t IsNaN(Double_t x)
Definition TMath.h:892
Double_t Erfc(Double_t x)
Computes the complementary error function erfc(x).
Definition TMath.cxx:199
Definition graph.py:1
RooCurve::WingMode wmode
Definition RooAbsReal.h:478
const char * normRangeName
Definition RooAbsReal.h:474
RooFit::MPSplit interleave
Definition RooAbsReal.h:486
const char * projectionRangeName
Definition RooAbsReal.h:479
const RooArgSet * projDataSet
Definition RooAbsReal.h:473
const char * curveNameSuffix
Definition RooAbsReal.h:487
const char * addToCurveName
Definition RooAbsReal.h:482
const RooFitResult * errorFR
Definition RooAbsReal.h:492
const RooArgSet * projSet
Definition RooAbsReal.h:470
const char * curveName
Definition RooAbsReal.h:481
const RooAbsData * projData
Definition RooAbsReal.h:468
Option_t * drawOptions
Definition RooAbsReal.h:465
A UniqueId can be added as a class member to enhance any class with a unique identifier for each inst...
Definition UniqueId.h:39
constexpr Value_t value() const
Return numerical value of ID.
Definition UniqueId.h:59
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2345
static void output()