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