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