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