Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RooPlot.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 \file RooPlot.cxx
19 \class RooPlot
20 \ingroup Roofitcore
21 
22 A RooPlot is a plot frame and a container for graphics objects
23 within that frame. As a frame, it provides the TH1-style public interface
24 for settting plot ranges, configuring axes, etc. As a container, it
25 holds an arbitrary set of objects that might be histograms of data,
26 curves representing a fit model, or text labels. Use the Draw()
27 method to draw a frame and the objects it contains. Use the various
28 add...() methods to add objects to be drawn. In general, the
29 add...() methods create a private copy of the object you pass them
30 and return a pointer to this copy. The caller owns the input object
31 and this class owns the returned object.
32 All RooAbsReal and RooAbsData derived classes implement plotOn()
33 functions that facilitate to plot themselves on a given RooPlot, e.g.
34 ~~~ {.cpp}
35 RooPlot *frame = x.frame() ;
36 data.plotOn(frame) ;
37 pdf.plotOn(frame) ;
38 ~~~
39 These high level functions also take care of any projections
40 or other mappings that need to be made to plot a multi-dimensional
41 object onto a one-dimensional plot.
42 **/
43 
44 #include "RooPlot.h"
45 
46 #include "RooAbsReal.h"
47 #include "RooAbsRealLValue.h"
48 #include "RooPlotable.h"
49 #include "RooArgSet.h"
50 #include "RooCurve.h"
51 #include "RooHist.h"
52 #include "RooMsgService.h"
53 
54 #include "TClass.h"
55 #include "TH1D.h"
56 #include "TBrowser.h"
57 #include "TPad.h"
58 
59 #include "TAttLine.h"
60 #include "TAttFill.h"
61 #include "TAttMarker.h"
62 #include "TAttText.h"
63 #include "TDirectory.h"
64 #include "TDirectoryFile.h"
65 #include "TLegend.h"
66 
67 #include "Riostream.h"
68 #include <string.h>
69 
70 using namespace std;
71 
72 ClassImp(RooPlot);
73 ;
74 
75 Bool_t RooPlot::_addDirStatus = kTRUE ;
76 
77 Bool_t RooPlot::addDirectoryStatus() { return _addDirStatus ; }
78 Bool_t RooPlot::setAddDirectoryStatus(Bool_t flag) { Bool_t ret = flag ; _addDirStatus = flag ; return ret ; }
79 
80 
81 ////////////////////////////////////////////////////////////////////////////////
82 /// Default constructor
83 /// coverity[UNINIT_CTOR]
84 
85 RooPlot::RooPlot() : _hist(0), _plotVarClone(0), _plotVarSet(0), _normVars(0), _normObj(0), _dir(0)
86 {
87  _iterator= _items.MakeIterator() ;
88 
89  if (gDirectory && addDirectoryStatus()) {
90  _dir = gDirectory ;
91  gDirectory->Append(this) ;
92  }
93 }
94 
95 
96 ////////////////////////////////////////////////////////////////////////////////
97 /// Constructor of RooPlot with range [xmin,xmax]
98 
99 RooPlot::RooPlot(Double_t xmin, Double_t xmax) :
100  _hist(0), _items(), _plotVarClone(0), _plotVarSet(0), _normObj(0),
101  _defYmin(1e-5), _defYmax(1), _dir(0)
102 {
103  Bool_t histAddDirStatus = TH1::AddDirectoryStatus();
104  TH1::AddDirectory(kFALSE) ;
105 
106  _hist = new TH1D(histName(),"A RooPlot",100,xmin,xmax) ;
107  _hist->Sumw2(kFALSE) ;
108  _hist->GetSumw2()->Set(0) ;
109 
110 
111  TH1::AddDirectory(histAddDirStatus) ;
112 
113 
114  // Create an empty frame with the specified x-axis limits.
115  initialize();
116 
117 }
118 
119 
120 
121 ////////////////////////////////////////////////////////////////////////////////
122 /// Construct of a two-dimensioanl RooPlot with ranges [xmin,xmax] x [ymin,ymax]
123 
124 RooPlot::RooPlot(Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax) :
125  _hist(0), _items(), _plotVarClone(0),
126  _plotVarSet(0), _normObj(0), _defYmin(1e-5), _defYmax(0), _dir(0)
127 {
128  Bool_t histAddDirStatus = TH1::AddDirectoryStatus();
129  TH1::AddDirectory(kFALSE) ;
130 
131  _hist = new TH1D(histName(),"A RooPlot",100,xmin,xmax) ;
132  _hist->Sumw2(kFALSE) ;
133  _hist->GetSumw2()->Set(0) ;
134 
135  TH1::AddDirectory(histAddDirStatus) ;
136 
137  SetMinimum(ymin);
138  SetMaximum(ymax);
139  initialize();
140 }
141 
142 
143 ////////////////////////////////////////////////////////////////////////////////
144 /// Construct a two-dimensional RooPlot with ranges and properties taken
145 /// from variables var1 and var2
146 
147 RooPlot::RooPlot(const RooAbsRealLValue &var1, const RooAbsRealLValue &var2) :
148  _hist(0), _items(),
149  _plotVarClone(0), _plotVarSet(0), _normObj(0), _defYmin(1e-5), _defYmax(0), _dir(0)
150 {
151  Bool_t histAddDirStatus = TH1::AddDirectoryStatus();
152  TH1::AddDirectory(kFALSE) ;
153 
154  _hist = new TH1D(histName(),"A RooPlot",100,var1.getMin(),var1.getMax()) ;
155  _hist->Sumw2(kFALSE) ;
156  _hist->GetSumw2()->Set(0) ;
157 
158  TH1::AddDirectory(histAddDirStatus) ;
159 
160  if(!var1.hasMin() || !var1.hasMax()) {
161  coutE(InputArguments) << "RooPlot::RooPlot: cannot create plot for variable without finite limits: "
162  << var1.GetName() << endl;
163  return;
164  }
165  if(!var2.hasMin() || !var2.hasMax()) {
166  coutE(InputArguments) << "RooPlot::RooPlot: cannot create plot for variable without finite limits: "
167  << var1.GetName() << endl;
168  return;
169  }
170  SetMinimum(var2.getMin());
171  SetMaximum(var2.getMax());
172  SetXTitle(var1.getTitle(kTRUE));
173  SetYTitle(var2.getTitle(kTRUE));
174  initialize();
175 }
176 
177 
178 ////////////////////////////////////////////////////////////////////////////////
179 /// Construct a two-dimensional RooPlot with ranges and properties taken
180 /// from variables var1 and var2 but with an overriding range definition
181 /// of [xmin,xmax] x [ymin,ymax]
182 
183 RooPlot::RooPlot(const RooAbsRealLValue &var1, const RooAbsRealLValue &var2,
184  Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax) :
185  _hist(0), _items(), _plotVarClone(0),
186  _plotVarSet(0), _normObj(0), _defYmin(1e-5), _defYmax(0), _dir(0)
187 {
188  Bool_t histAddDirStatus = TH1::AddDirectoryStatus();
189  TH1::AddDirectory(kFALSE) ;
190 
191  _hist = new TH1D(histName(),"A RooPlot",100,xmin,xmax) ;
192  _hist->Sumw2(kFALSE) ;
193  _hist->GetSumw2()->Set(0) ;
194 
195  TH1::AddDirectory(histAddDirStatus) ;
196 
197  SetMinimum(ymin);
198  SetMaximum(ymax);
199  SetXTitle(var1.getTitle(kTRUE));
200  SetYTitle(var2.getTitle(kTRUE));
201  initialize();
202 }
203 
204 
205 ////////////////////////////////////////////////////////////////////////////////
206 /// Create an 1-dimensional with all properties taken from 'var', but
207 /// with an explicit range [xmin,xmax] and a default binning of 'nbins'
208 
209 RooPlot::RooPlot(const char* name, const char* title, const RooAbsRealLValue &var, Double_t xmin, Double_t xmax, Int_t nbins) :
210  _hist(0), _items(),
211  _plotVarClone(0), _plotVarSet(0), _normObj(0), _defYmin(1e-5), _defYmax(1), _dir(0)
212 {
213  Bool_t histAddDirStatus = TH1::AddDirectoryStatus();
214  TH1::AddDirectory(kFALSE) ;
215 
216  _hist = new TH1D(name,title,nbins,xmin,xmax) ;
217  _hist->Sumw2(kFALSE) ;
218  _hist->GetSumw2()->Set(0) ;
219 
220  TH1::AddDirectory(histAddDirStatus) ;
221 
222  // plotVar can be a composite in case of a RooDataSet::plot, need deepClone
223  _plotVarSet = (RooArgSet*) RooArgSet(var).snapshot() ;
224  _plotVarClone= (RooAbsRealLValue*)_plotVarSet->find(var.GetName()) ;
225 
226  TString xtitle= var.getTitle(kTRUE);
227  SetXTitle(xtitle.Data());
228 
229  initialize();
230 
231  _normBinWidth = (xmax-xmin)/nbins ;
232 }
233 
234 
235 ////////////////////////////////////////////////////////////////////////////////
236 /// Create an 1-dimensional with all properties taken from 'var', but
237 /// with an explicit range [xmin,xmax] and a default binning of 'nbins'
238 
239 RooPlot::RooPlot(const RooAbsRealLValue &var, Double_t xmin, Double_t xmax, Int_t nbins) :
240  _hist(0), _items(),
241  _plotVarClone(0), _plotVarSet(0), _normObj(0), _defYmin(1e-5), _defYmax(1), _dir(0)
242 {
243  Bool_t histAddDirStatus = TH1::AddDirectoryStatus();
244  TH1::AddDirectory(kFALSE) ;
245 
246  _hist = new TH1D(histName(),"RooPlot",nbins,xmin,xmax) ;
247  _hist->Sumw2(kFALSE) ;
248  _hist->GetSumw2()->Set(0) ;
249 
250  TH1::AddDirectory(histAddDirStatus) ;
251 
252  // plotVar can be a composite in case of a RooDataSet::plot, need deepClone
253  _plotVarSet = (RooArgSet*) RooArgSet(var).snapshot() ;
254  _plotVarClone= (RooAbsRealLValue*)_plotVarSet->find(var.GetName()) ;
255 
256  TString xtitle= var.getTitle(kTRUE);
257  SetXTitle(xtitle.Data());
258 
259  TString title("A RooPlot of \"");
260  title.Append(var.getTitle());
261  title.Append("\"");
262  SetTitle(title.Data());
263  initialize();
264 
265  _normBinWidth = (xmax-xmin)/nbins ;
266 }
267 
268 ////////////////////////////////////////////////////////////////////////////////
269 /// Create a new frame for a given variable in x. This is just a
270 /// wrapper for the RooPlot constructor with the same interface.
271 ///
272 /// More details.
273 /// \param[in] var The variable on the x-axis
274 /// \param[in] xmin Left edge of the x-axis
275 /// \param[in] xmax Right edge of the x-axis
276 /// \param[in] nBins number of bins on the x-axis
277 RooPlot* RooPlot::frame(const RooAbsRealLValue &var, Double_t xmin, Double_t xmax, Int_t nBins){
278  return new RooPlot(var,xmin,xmax,nBins);
279 }
280 
281 ////////////////////////////////////////////////////////////////////////////////
282 /// Create a new frame for a given variable in x, adding bin labels.
283 /// The binning will be extracted from the variable given. The bin
284 /// labels will be set as "%g-%g" for the left and right edges of each
285 /// bin of the given variable.
286 ///
287 /// More details.
288 /// \param[in] var The variable on the x-axis
289 RooPlot* RooPlot::frameWithLabels(const RooAbsRealLValue &var){
290  RooPlot* pl = new RooPlot();
291  int nbins = var.getBinning().numBins();
292 
293  Bool_t histAddDirStatus = TH1::AddDirectoryStatus();
294  TH1::AddDirectory(kFALSE) ;
295  pl->_hist = new TH1D(pl->histName(),"RooPlot",nbins,var.getMin(),var.getMax()) ;
296  pl->_hist->Sumw2(kFALSE) ;
297  pl->_hist->GetSumw2()->Set(0) ;
298  TH1::AddDirectory(histAddDirStatus) ;
299 
300  pl->_hist->SetNdivisions(-nbins);
301  for(int i=0; i<nbins; ++i){
302  TString s = TString::Format("%g-%g",var.getBinning().binLow(i),var.getBinning().binHigh(i));
303  pl->_hist->GetXaxis()->SetBinLabel(i+1,s);
304  }
305 
306  // plotVar can be a composite in case of a RooDataSet::plot, need deepClone
307  pl->_plotVarSet = (RooArgSet*) RooArgSet(var).snapshot() ;
308  pl->_plotVarClone= (RooAbsRealLValue*)pl->_plotVarSet->find(var.GetName()) ;
309 
310  TString xtitle= var.getTitle(kTRUE);
311  pl->SetXTitle(xtitle.Data());
312 
313  TString title("A RooPlot of \"");
314  title.Append(var.getTitle());
315  title.Append("\"");
316  pl->SetTitle(title.Data());
317  pl->initialize();
318 
319  pl->_normBinWidth = 1.;
320  return pl;
321 }
322 
323 ////////////////////////////////////////////////////////////////////////////////
324 /// Return empty clone of current RooPlot
325 
326 RooPlot* RooPlot::emptyClone(const char* name)
327 {
328  RooPlot* clone = new RooPlot(*_plotVarClone,_hist->GetXaxis()->GetXmin(),_hist->GetXaxis()->GetXmax(),_hist->GetNbinsX()) ;
329  clone->SetName(name) ;
330  return clone ;
331 }
332 
333 
334 ////////////////////////////////////////////////////////////////////////////////
335 /// Perform initialization that is common to all constructors.
336 
337 void RooPlot::initialize()
338 {
339  SetName(histName()) ;
340 
341  if (gDirectory && addDirectoryStatus()) {
342  _dir = gDirectory ;
343  gDirectory->Append(this) ;
344  }
345 
346  // We do not have useful stats of our own
347  _hist->SetStats(kFALSE);
348  // Default vertical padding of our enclosed objects
349  setPadFactor(0.05);
350  // We don't know our normalization yet
351  _normNumEvts= 0;
352  _normBinWidth = 0;
353  _normVars= 0;
354  // Create an iterator over our enclosed objects
355  _iterator= _items.MakeIterator();
356  assert(0 != _iterator);
357 }
358 
359 
360 ////////////////////////////////////////////////////////////////////////////////
361 /// Construct automatic name of internal TH1
362 
363 TString RooPlot::histName() const
364 {
365  if (_plotVarClone) {
366  return TString(Form("frame_%s_%lx",_plotVarClone->GetName(),(ULong_t)this)) ;
367  } else {
368  return TString(Form("frame_%lx",(ULong_t)this)) ;
369  }
370 }
371 
372 
373 ////////////////////////////////////////////////////////////////////////////////
374 /// Destructor
375 
376 RooPlot::~RooPlot()
377 {
378  // Delete the items in our container and our iterator.
379  if (_dir) {
380  if (!_dir->TestBit(TDirectoryFile::kCloseDirectory)) {
381  _dir->GetList()->RecursiveRemove(this) ;
382  }
383  }
384 
385  _items.Delete();
386  delete _iterator;
387  if(_plotVarSet) delete _plotVarSet;
388  if(_normVars) delete _normVars;
389  delete _hist ;
390 
391 }
392 
393 
394 ////////////////////////////////////////////////////////////////////////////////
395 /// Install the given set of observables are reference normalization
396 /// variables for this frame. These observables are e.g. later used
397 /// to automatically project out observables when plotting functions
398 /// on this frame. This function is only effective when called the
399 /// first time on a frame
400 
401 void RooPlot::updateNormVars(const RooArgSet &vars)
402 {
403  if(0 == _normVars) _normVars= (RooArgSet*) vars.snapshot(kTRUE);
404 }
405 
406 
407 ////////////////////////////////////////////////////////////////////////////////
408 /// A plot object is a frame without any bin contents of its own so this
409 /// method always returns zero.
410 
411 Stat_t RooPlot::GetBinContent(Int_t /*i*/) const {
412  return 0;
413 }
414 
415 
416 ////////////////////////////////////////////////////////////////////////////////
417 /// A plot object is a frame without any bin contents of its own so this
418 /// method always returns zero.
419 
420 Stat_t RooPlot::GetBinContent(Int_t, Int_t) const
421 {
422  return 0;
423 }
424 
425 
426 ////////////////////////////////////////////////////////////////////////////////
427 /// A plot object is a frame without any bin contents of its own so this
428 /// method always returns zero.
429 
430 Stat_t RooPlot::GetBinContent(Int_t, Int_t, Int_t) const
431 {
432  return 0;
433 }
434 
435 
436 
437 ////////////////////////////////////////////////////////////////////////////////
438 /// Add a generic object to this plot. The specified options will be
439 /// used to Draw() this object later. The caller transfers ownership
440 /// of the object with this call, and the object will be deleted
441 /// when its containing plot object is destroyed.
442 
443 void RooPlot::addObject(TObject *obj, Option_t *drawOptions, Bool_t invisible)
444 {
445  if(0 == obj) {
446  coutE(InputArguments) << fName << "::addObject: called with a null pointer" << endl;
447  return;
448  }
449  DrawOpt opt(drawOptions) ;
450  opt.invisible = invisible ;
451  _items.Add(obj,opt.rawOpt());
452 }
453 
454 
455 ////////////////////////////////////////////////////////////////////////////////
456 /// Add a TH1 histogram object to this plot. The specified options
457 /// will be used to Draw() this object later. "SAME" will be added to
458 /// the options if they are not already present. The caller transfers
459 /// ownership of the object with this call, and the object will be
460 /// deleted when its containing plot object is destroyed.
461 
462 void RooPlot::addTH1(TH1 *hist, Option_t *drawOptions, Bool_t invisible)
463 {
464  if(0 == hist) {
465  coutE(InputArguments) << fName << "::addTH1: called with a null pointer" << endl;
466  return;
467  }
468  // check that this histogram is really 1D
469  if(1 != hist->GetDimension()) {
470  coutE(InputArguments) << fName << "::addTH1: cannot plot histogram with "
471  << hist->GetDimension() << " dimensions" << endl;
472  return;
473  }
474 
475  // add option "SAME" if necessary
476  TString options(drawOptions);
477  options.ToUpper();
478  if(!options.Contains("SAME")) options.Append("SAME");
479 
480  // update our y-axis label and limits
481  updateYAxis(hist->GetMinimum(),hist->GetMaximum(),hist->GetYaxis()->GetTitle());
482 
483  // use this histogram's normalization if necessary
484  updateFitRangeNorm(hist);
485 
486  // add the histogram to our list
487  addObject(hist,options.Data(),invisible);
488 }
489 
490 
491 namespace {
492  // this helper function is intended to translate a graph from a regular axis to a labelled axis
493  // this version uses TGraph, which is a parent of RooCurve
494  void translateGraph(TH1* hist, RooAbsRealLValue* xvar, TGraph* graph){
495  // if the graph already has a labelled axis, don't do anything
496  if(graph->GetXaxis()->IsAlphanumeric()) return;
497  double xmin = hist->GetXaxis()->GetXmin();
498  double xmax = hist->GetXaxis()->GetXmax();
499  if(graph->TestBit(TGraph::kIsSortedX)){
500  // sorted graphs are "line graphs"
501  // evaluate the graph at the lower and upper edge as well as the center of each bin
502  std::vector<double> x;
503  std::vector<double> y;
504  x.push_back(xmin);
505  y.push_back(graph->Eval(xvar->getBinning().binLow(0)));
506  for(int i=0; i<hist->GetNbinsX(); ++i){
507  x.push_back(hist->GetXaxis()->GetBinUpEdge(i+1));
508  y.push_back(graph->Eval(xvar->getBinning().binHigh(i)));
509  x.push_back(hist->GetXaxis()->GetBinCenter(i+1));
510  y.push_back(graph->Eval(xvar->getBinning().binCenter(i)));
511  }
512  int n = x.size();
513  graph->Set(n);
514  for(int i=0; i<n; ++i){
515  graph->SetPoint(i,x[i],y[i]);
516  }
517  graph->Sort();
518  } else {
519  // unsorted graphs are "area graphs"
520  std::map<int,double> minValues;
521  std::map<int,double> maxValues;
522  int n = graph->GetN();
523  double x, y;
524  // for each bin, find the min and max points to form an envelope
525  for(int i=0; i<n; ++i){
526  graph->GetPoint(i,x,y);
527  int bin = xvar->getBinning().binNumber(x)+1;
528  if(maxValues.find(bin)!=maxValues.end()){
529  maxValues[bin] = std::max(maxValues[bin],y);
530  } else {
531  maxValues[bin] = y;
532  }
533  if(minValues.find(bin)!=minValues.end()){
534  minValues[bin] = std::min(minValues[bin],y);
535  } else {
536  minValues[bin] = y;
537  }
538  }
539  double xminY = graph->Eval(xmin);
540  double xmaxY = graph->Eval(xmax);
541  graph->Set(hist->GetNbinsX()+2);
542  int np=0;
543  graph->SetPoint(np,xmin,xminY);
544  // assign the calculated envelope boundaries to the bin centers of the bins
545  for(auto it = maxValues.begin(); it != maxValues.end(); ++it){
546  graph->SetPoint(++np,hist->GetXaxis()->GetBinCenter(it->first),it->second);
547  }
548  graph->SetPoint(++np,xmax,xmaxY);
549  for(auto it = minValues.rbegin(); it != minValues.rend(); ++it){
550  graph->SetPoint(++np,hist->GetXaxis()->GetBinCenter(it->first),it->second);
551  }
552  graph->SetPoint(++np,xmin,xminY);
553  }
554  // make sure that the graph also has the labels set, such that subsequent calls to translate this graph will not do anything
555  graph->GetXaxis()->Set(hist->GetNbinsX(),xmin,xmax);
556  for(int i=0; i<hist->GetNbinsX(); ++i){
557  graph->GetXaxis()->SetBinLabel(i+1,hist->GetXaxis()->GetBinLabel(i+1));
558  }
559  }
560  // this version uses TGraphErrors, which is a parent of RooHist
561  void translateGraph(TH1* hist, RooAbsRealLValue* xvar, TGraphAsymmErrors* graph){
562  // if the graph already has a labelled axis, don't do anything
563  if(graph->GetXaxis()->IsAlphanumeric()) return;
564  int n = graph->GetN();
565  double xmin = hist->GetXaxis()->GetXmin();
566  double xmax = hist->GetXaxis()->GetXmax();
567  double x, y;
568  // as this graph is histogram-like, we expect there to be one point per bin
569  // we just move these points to the respective bin centers
570  for(int i=0; i<n; ++i){
571  if(graph->GetPoint(i,x,y)!=i) break;
572  int bin = xvar->getBinning().binNumber(x);
573  graph->SetPoint(i,hist->GetXaxis()->GetBinCenter(bin+1),y);
574  graph->SetPointEXhigh(i,0.5*hist->GetXaxis()->GetBinWidth(bin+1));
575  graph->SetPointEXlow(i,0.5*hist->GetXaxis()->GetBinWidth(bin+1));
576  }
577  graph->GetXaxis()->Set(hist->GetNbinsX(),xmin,xmax);
578  // make sure that the graph also has the labels set, such that subsequent calls to translate this graph will not do anything
579  for(int i=0; i<hist->GetNbinsX(); ++i){
580  graph->GetXaxis()->SetBinLabel(i+1,hist->GetXaxis()->GetBinLabel(i+1));
581  }
582  }
583 }
584 
585 ////////////////////////////////////////////////////////////////////////////////
586 /// Add the specified plotable object to our plot. Increase our y-axis
587 /// limits to fit this object if necessary. The default lower-limit
588 /// is zero unless we are plotting an object that takes on negative values.
589 /// This call transfers ownership of the plotable object to this class.
590 /// The plotable object will be deleted when this plot object is deleted.
591 void RooPlot::addPlotable(RooPlotable *plotable, Option_t *drawOptions, Bool_t invisible, Bool_t refreshNorm)
592 {
593  // update our y-axis label and limits
594  updateYAxis(plotable->getYAxisMin(),plotable->getYAxisMax(),plotable->getYAxisLabel());
595 
596  // use this object's normalization if necessary
597  updateFitRangeNorm(plotable,refreshNorm) ;
598 
599  // add this element to our list and remember its drawing option
600  TObject *obj= plotable->crossCast();
601  if(0 == obj) {
602  coutE(InputArguments) << fName << "::add: cross-cast to TObject failed (nothing added)" << endl;
603  }
604  else {
605  // if the frame axis is alphanumeric, the coordinates of the graph need to be translated to this binning
606  if(this->_hist->GetXaxis()->IsAlphanumeric()){
607  if(obj->InheritsFrom(RooCurve::Class())){
608  ::translateGraph(this->_hist,_plotVarClone,static_cast<RooCurve*>(obj));
609  } else if(obj->InheritsFrom(RooHist::Class())){
610  ::translateGraph(this->_hist,_plotVarClone,static_cast<RooHist*>(obj));
611  }
612  }
613 
614  DrawOpt opt(drawOptions) ;
615  opt.invisible = invisible ;
616  _items.Add(obj,opt.rawOpt());
617  }
618 }
619 
620 
621 ////////////////////////////////////////////////////////////////////////////////
622 /// Update our plot normalization over our plot variable's fit range,
623 /// which will be determined by the first suitable object added to our plot.
624 
625 void RooPlot::updateFitRangeNorm(const TH1* hist)
626 {
627  const TAxis* xa = ((TH1*)hist)->GetXaxis() ;
628  _normBinWidth = (xa->GetXmax()-xa->GetXmin())/hist->GetNbinsX() ;
629  _normNumEvts = hist->GetEntries()/_normBinWidth ;
630 }
631 
632 
633 ////////////////////////////////////////////////////////////////////////////////
634 /// Update our plot normalization over our plot variable's fit range,
635 /// which will be determined by the first suitable object added to our plot.
636 
637 void RooPlot::updateFitRangeNorm(const RooPlotable* rp, Bool_t refreshNorm)
638 {
639  if (_normNumEvts != 0) {
640 
641  // If refresh feature is disabled stop here
642  if (!refreshNorm) return ;
643 
644  Double_t corFac(1.0) ;
645  if (dynamic_cast<const RooHist*>(rp)) corFac = _normBinWidth/rp->getFitRangeBinW() ;
646 
647 
648  if (fabs(rp->getFitRangeNEvt()/corFac-_normNumEvts)>1e-6) {
649  coutI(Plotting) << "RooPlot::updateFitRangeNorm: New event count of " << rp->getFitRangeNEvt()/corFac
650  << " will supercede previous event count of " << _normNumEvts << " for normalization of PDF projections" << endl ;
651  }
652 
653  // Nominal bin width (i.e event density) is already locked in by previously drawn histogram
654  // scale this histogram to match that density
655  _normNumEvts = rp->getFitRangeNEvt()/corFac ;
656  _normObj = rp ;
657  // cout << "correction factor = " << _normBinWidth << "/" << rp->getFitRangeBinW() << endl ;
658  // cout << "updating numevts to " << _normNumEvts << endl ;
659 
660  } else {
661 
662  _normObj = rp ;
663  _normNumEvts = rp->getFitRangeNEvt() ;
664  if (rp->getFitRangeBinW()) {
665  _normBinWidth = rp->getFitRangeBinW() ;
666  }
667 
668  // cout << "updating numevts to " << _normNumEvts << endl ;
669  }
670 
671 }
672 
673 
674 
675 ////////////////////////////////////////////////////////////////////////////////
676 /// Update our y-axis limits to accomodate an object whose spread
677 /// in y is (ymin,ymax). Use the specified y-axis label if we don't
678 /// have one assigned already.
679 
680 void RooPlot::updateYAxis(Double_t ymin, Double_t ymax, const char *label)
681 {
682  // force an implicit lower limit of zero if appropriate
683  if(GetMinimum() == 0 && ymin > 0) ymin= 0;
684 
685  // calculate padded values
686  Double_t ypad= getPadFactor()*(ymax-ymin);
687  ymax+= ypad;
688  if(ymin < 0) ymin-= ypad;
689 
690  // update our limits if necessary
691  if(GetMaximum() < ymax) {
692  _defYmax = ymax ;
693  SetMaximum(ymax);
694  // if we don't do this - Unzoom on y-axis will reset upper bound to 1
695  _hist->SetBinContent(1,ymax) ;
696  }
697  if(GetMinimum() > ymin) {
698  _defYmin = ymin ;
699  SetMinimum(ymin);
700  }
701 
702  // use the specified y-axis label if we don't have one already
703  if(0 == strlen(_hist->GetYaxis()->GetTitle())) _hist->SetYTitle(label);
704 }
705 
706 
707 ////////////////////////////////////////////////////////////////////////////////
708 /// Draw this plot and all of the elements it contains. The specified options
709 /// only apply to the drawing of our frame. The options specified in our add...()
710 /// methods will be used to draw each object we contain.
711 
712 void RooPlot::Draw(Option_t *option)
713 {
714  TString optArg = option ;
715  optArg.ToLower() ;
716 
717  // This draw options prevents the histogram with one dummy entry
718  // to be drawn
719  if (optArg.Contains("same")) {
720  _hist->Draw("FUNCSAME");
721  } else {
722  _hist->Draw("FUNC");
723  }
724 
725  _iterator->Reset();
726  TObject *obj = 0;
727  while((obj= _iterator->Next())) {
728  DrawOpt opt(_iterator->GetOption()) ;
729  if (!opt.invisible) {
730  //LM: in case of a TGraph derived object, do not use default "" option
731  // which is "ALP" from 5.34.10 (and will then redrawn the axis) but use "LP"
732  if (!strlen(opt.drawOptions) && obj->IsA()->InheritsFrom(TGraph::Class()) ) strlcpy(opt.drawOptions,"LP",3);
733  obj->Draw(opt.drawOptions);
734  }
735  }
736 
737  _hist->Draw("AXISSAME");
738 }
739 
740 
741 
742 ////////////////////////////////////////////////////////////////////////////////
743 /// Print frame name
744 
745 void RooPlot::printName(ostream& os) const
746 {
747  os << GetName() ;
748 }
749 
750 
751 ////////////////////////////////////////////////////////////////////////////////
752 /// Print frame title
753 
754 void RooPlot::printTitle(ostream& os) const
755 {
756  os << GetTitle() ;
757 }
758 
759 
760 ////////////////////////////////////////////////////////////////////////////////
761 /// Print frame class name
762 
763 void RooPlot::printClassName(ostream& os) const
764 {
765  os << IsA()->GetName() ;
766 }
767 
768 
769 
770 ////////////////////////////////////////////////////////////////////////////////
771 
772 void RooPlot::printArgs(ostream& os) const
773 {
774  if (_plotVarClone) {
775  os << "[" ;
776  _plotVarClone->printStream(os,kName,kInline) ;
777  os << "]" ;
778  }
779 }
780 
781 
782 
783 ////////////////////////////////////////////////////////////////////////////////
784 /// Print frame arguments
785 
786 void RooPlot::printValue(ostream& os) const
787 {
788  os << "(" ;
789  _iterator->Reset();
790  TObject *obj = 0;
791  Bool_t first(kTRUE) ;
792  while((obj= _iterator->Next())) {
793  if (first) {
794  first=kFALSE ;
795  } else {
796  os << "," ;
797  }
798  if(obj->IsA()->InheritsFrom(RooPrintable::Class())) {
799  RooPrintable* po = dynamic_cast<RooPrintable*>(obj) ;
800  // coverity[FORWARD_NULL]
801  po->printStream(os,kClassName|kName,kInline) ;
802  }
803  // is it a TNamed subclass?
804  else {
805  os << obj->ClassName() << "::" << obj->GetName() ;
806  }
807  }
808  os << ")" ;
809 }
810 
811 
812 ////////////////////////////////////////////////////////////////////////////////
813 /// Frame detailed printing
814 
815 void RooPlot::printMultiline(ostream& os, Int_t /*content*/, Bool_t verbose, TString indent) const
816 {
817  TString deeper(indent);
818  deeper.Append(" ");
819  if(0 != _plotVarClone) {
820  os << indent << "RooPlot " << GetName() << " (" << GetTitle() << ") plots variable ";
821  _plotVarClone->printStream(os,kName|kTitle,kSingleLine,"");
822  }
823  else {
824  os << indent << "RooPlot " << GetName() << " (" << GetTitle() << ") has no associated plot variable" << endl ;
825  }
826  os << indent << " Plot frame contains " << _items.GetSize() << " object(s):" << endl;
827 
828  if(verbose) {
829  _iterator->Reset();
830  TObject *obj = 0;
831  Int_t i=0 ;
832  while((obj= _iterator->Next())) {
833  os << deeper << "[" << i++ << "] (Options=\"" << _iterator->GetOption() << "\") ";
834  // Is this a printable object?
835  if(obj->IsA()->InheritsFrom(RooPrintable::Class())) {
836  RooPrintable* po = dynamic_cast<RooPrintable*>(obj) ;
837  if (po) {
838  po->printStream(os,kName|kClassName|kArgs|kExtras,kSingleLine) ;
839  }
840  }
841  // is it a TNamed subclass?
842  else {
843  os << obj->ClassName() << "::" << obj->GetName() << endl;
844  }
845  }
846  }
847 }
848 
849 
850 
851 ////////////////////////////////////////////////////////////////////////////////
852 /// Return the name of the object at slot 'idx' in this RooPlot.
853 /// If the given index is out of range, return a null pointer
854 
855 const char* RooPlot::nameOf(Int_t idx) const
856 {
857  TObject* obj = _items.At(idx) ;
858  if (!obj) {
859  coutE(InputArguments) << "RooPlot::nameOf(" << GetName() << ") index " << idx << " out of range" << endl ;
860  return 0 ;
861  }
862  return obj->GetName() ;
863 }
864 
865 
866 
867 ////////////////////////////////////////////////////////////////////////////////
868 /// Return the name of the object at slot 'idx' in this RooPlot.
869 /// If the given index is out of range, return a null pointer
870 
871 TObject* RooPlot::getObject(Int_t idx) const
872 {
873  TObject* obj = _items.At(idx) ;
874  if (!obj) {
875  coutE(InputArguments) << "RooPlot::getObject(" << GetName() << ") index " << idx << " out of range" << endl ;
876  return 0 ;
877  }
878  return obj ;
879 }
880 
881 
882 
883 ////////////////////////////////////////////////////////////////////////////////
884 /// Return a pointer to the line attributes of the named object in this plot,
885 /// or zero if the named object does not exist or does not have line attributes.
886 
887 TAttLine *RooPlot::getAttLine(const char *name) const
888 {
889  return dynamic_cast<TAttLine*>(findObject(name));
890 }
891 
892 
893 ////////////////////////////////////////////////////////////////////////////////
894 /// Return a pointer to the fill attributes of the named object in this plot,
895 /// or zero if the named object does not exist or does not have fill attributes.
896 
897 TAttFill *RooPlot::getAttFill(const char *name) const
898 {
899  return dynamic_cast<TAttFill*>(findObject(name));
900 }
901 
902 
903 ////////////////////////////////////////////////////////////////////////////////
904 /// Return a pointer to the marker attributes of the named object in this plot,
905 /// or zero if the named object does not exist or does not have marker attributes.
906 
907 TAttMarker *RooPlot::getAttMarker(const char *name) const
908 {
909  return dynamic_cast<TAttMarker*>(findObject(name));
910 }
911 
912 
913 ////////////////////////////////////////////////////////////////////////////////
914 /// Return a pointer to the text attributes of the named object in this plot,
915 /// or zero if the named object does not exist or does not have text attributes.
916 
917 TAttText *RooPlot::getAttText(const char *name) const
918 {
919  return dynamic_cast<TAttText*>(findObject(name));
920 }
921 
922 
923 
924 ////////////////////////////////////////////////////////////////////////////////
925 /// Return a RooCurve pointer of the named object in this plot,
926 /// or zero if the named object does not exist or is not a RooCurve
927 
928 RooCurve* RooPlot::getCurve(const char* name) const
929 {
930  return dynamic_cast<RooCurve*>(findObject(name)) ;
931 }
932 
933 
934 ////////////////////////////////////////////////////////////////////////////////
935 /// Return a RooCurve pointer of the named object in this plot,
936 /// or zero if the named object does not exist or is not a RooCurve
937 
938 RooHist* RooPlot::getHist(const char* name) const
939 {
940  return dynamic_cast<RooHist*>(findObject(name)) ;
941 }
942 
943 
944 
945 ////////////////////////////////////////////////////////////////////////////////
946 /// Remove object with given name, or last object added if no name is given.
947 /// If deleteToo is true (default), the object removed from the RooPlot is
948 /// also deleted.
949 
950 void RooPlot::remove(const char* name, Bool_t deleteToo)
951 {
952  TObject* obj = findObject(name) ;
953  if (!obj) {
954  if (name) {
955  coutE(InputArguments) << "RooPlot::remove(" << GetName() << ") ERROR: no object found with name " << name << endl ;
956  } else {
957  coutE(InputArguments) << "RooPlot::remove(" << GetName() << ") ERROR: plot frame is empty, cannot remove last object" << endl ;
958  }
959  return ;
960  }
961 
962  _items.Remove(obj) ;
963 
964  if (deleteToo) {
965  delete obj ;
966  }
967 }
968 
969 
970 ////////////////////////////////////////////////////////////////////////////////
971 /// Change the order in which our contained objects are drawn so that
972 /// the target object is drawn just before the specified object.
973 /// Returns kFALSE if either object does not exist.
974 
975 Bool_t RooPlot::drawBefore(const char *before, const char *target)
976 {
977  return _items.moveBefore(before, target, caller("drawBefore"));
978 }
979 
980 
981 ////////////////////////////////////////////////////////////////////////////////
982 /// Change the order in which our contained objects are drawn so that
983 /// the target object is drawn just after the specified object.
984 /// Returns kFALSE if either object does not exist.
985 
986 Bool_t RooPlot::drawAfter(const char *after, const char *target)
987 {
988  return _items.moveAfter(after, target, caller("drawAfter"));
989 }
990 
991 
992 ////////////////////////////////////////////////////////////////////////////////
993 /// Find the named object in our list of items and return a pointer
994 /// to it. Return zero and print a warning message if the named
995 /// object cannot be found. If no name is supplied the last object
996 /// added is returned.
997 ///
998 /// Note that the returned pointer is to a
999 /// TObject and so will generally need casting. Use the getAtt...()
1000 /// methods to change the drawing style attributes of a contained
1001 /// object directly.
1002 
1003 TObject *RooPlot::findObject(const char *name, const TClass* clas) const
1004 {
1005  TObject *obj = 0;
1006  TObject *ret = 0;
1007 
1008  TIterator* iter = _items.MakeIterator() ;
1009  while((obj=iter->Next())) {
1010  if ((!name || !TString(name).CompareTo(obj->GetName())) &&
1011  (!clas || (obj->IsA()==clas))) {
1012  ret = obj ;
1013  }
1014  }
1015  delete iter ;
1016 
1017  if (ret==0) {
1018  coutE(InputArguments) << "RooPlot::findObject(" << GetName() << ") cannot find object " << (name?name:"<last>") << endl ;
1019  }
1020  return ret ;
1021 }
1022 
1023 
1024 ////////////////////////////////////////////////////////////////////////////////
1025 /// Return the Draw() options registered for the named object. Return
1026 /// an empty string if the named object cannot be found.
1027 
1028 TString RooPlot::getDrawOptions(const char *name) const
1029 {
1030  TObjOptLink *link= _items.findLink(name,caller("getDrawOptions"));
1031  DrawOpt opt(0 == link ? "" : link->GetOption()) ;
1032  return TString(opt.drawOptions) ;
1033 }
1034 
1035 
1036 ////////////////////////////////////////////////////////////////////////////////
1037 /// Register the specified drawing options for the named object.
1038 /// Return kFALSE if the named object cannot be found.
1039 
1040 Bool_t RooPlot::setDrawOptions(const char *name, TString options)
1041 {
1042  TObjOptLink *link= _items.findLink(name,caller("setDrawOptions"));
1043  if(0 == link) return kFALSE;
1044 
1045  DrawOpt opt(link->GetOption()) ;
1046  strlcpy(opt.drawOptions,options,128) ;
1047  link->SetOption(opt.rawOpt());
1048  return kTRUE;
1049 }
1050 
1051 
1052 ////////////////////////////////////////////////////////////////////////////////
1053 /// Returns true of object with given name is set to be invisible
1054 
1055 Bool_t RooPlot::getInvisible(const char* name) const
1056 {
1057  TObjOptLink *link= _items.findLink(name,caller("getInvisible"));
1058  if(0 == link) return kFALSE;
1059 
1060  return DrawOpt(link->GetOption()).invisible ;
1061 }
1062 
1063 
1064 ////////////////////////////////////////////////////////////////////////////////
1065 /// If flag is true object with 'name' is set to be invisible
1066 /// i.e. it is not drawn when Draw() is called
1067 
1068 void RooPlot::setInvisible(const char* name, Bool_t flag)
1069 {
1070  TObjOptLink *link= _items.findLink(name,caller("getInvisible"));
1071 
1072  DrawOpt opt ;
1073 
1074  if(link) {
1075  opt.initialize(link->GetOption()) ;
1076  opt.invisible = flag ;
1077  link->SetOption(opt.rawOpt()) ;
1078  }
1079 
1080 }
1081 
1082 
1083 
1084 ////////////////////////////////////////////////////////////////////////////////
1085 /// Utility function
1086 
1087 TString RooPlot::caller(const char *method) const
1088 {
1089  TString name(fName);
1090  if(strlen(method)) {
1091  name.Append("::");
1092  name.Append(method);
1093  }
1094  return name;
1095 }
1096 
1097 
1098 
1099 ////////////////////////////////////////////////////////////////////////////////
1100 /// Set maximum value of Y axis
1101 
1102 void RooPlot::SetMaximum(Double_t maximum)
1103 {
1104  _hist->SetMaximum(maximum==-1111?_defYmax:maximum) ;
1105 }
1106 
1107 
1108 
1109 ////////////////////////////////////////////////////////////////////////////////
1110 /// Set minimum value of Y axis
1111 
1112 void RooPlot::SetMinimum(Double_t minimum)
1113 {
1114  _hist->SetMinimum(minimum==-1111?_defYmin:minimum) ;
1115 }
1116 
1117 
1118 
1119 ////////////////////////////////////////////////////////////////////////////////
1120 /// Calculate and return reduced chi-squared of curve with given name with respect
1121 /// to histogram with given name.
1122 ///
1123 /// \param[in] curvename Name of the curve or nullptr for last curve
1124 /// \param[in] histname Name of the histogram to compare to or nullptr for last added histogram
1125 /// \param[in] nFitParam If non-zero, reduce the number of degrees of freedom by this
1126 /// number. This means that the curve was fitted to the data with nFitParam floating
1127 /// parameters, which needs to be reflected in the calculation of \f$\chi^2 / \mathrm{ndf}\f$.
1128 ///
1129 /// \return \f$ \chi^2 / \mathrm{ndf} \f$
1130 
1131 Double_t RooPlot::chiSquare(const char* curvename, const char* histname, int nFitParam) const
1132 {
1133 
1134  // Find curve object
1135  RooCurve* curve = (RooCurve*) findObject(curvename,RooCurve::Class()) ;
1136  if (!curve) {
1137  coutE(InputArguments) << "RooPlot::chiSquare(" << GetName() << ") cannot find curve" << endl ;
1138  return -1. ;
1139  }
1140 
1141  // Find histogram object
1142  RooHist* hist = (RooHist*) findObject(histname,RooHist::Class()) ;
1143  if (!hist) {
1144  coutE(InputArguments) << "RooPlot::chiSquare(" << GetName() << ") cannot find histogram" << endl ;
1145  return -1. ;
1146  }
1147 
1148  return curve->chiSquare(*hist,nFitParam) ;
1149 }
1150 
1151 
1152 ////////////////////////////////////////////////////////////////////////////////
1153 /// Return a RooHist containing the residuals of histogram 'histname' with respect
1154 /// to curve 'curvename'. If normalize is true the residuals are divided by the error
1155 /// on the histogram, effectively returning a pull histogram
1156 
1157 RooHist* RooPlot::residHist(const char* histname, const char* curvename, bool normalize, bool useAverage) const
1158 {
1159  // Find curve object
1160  RooCurve* curve = (RooCurve*) findObject(curvename,RooCurve::Class()) ;
1161  if (!curve) {
1162  coutE(InputArguments) << "RooPlot::residHist(" << GetName() << ") cannot find curve" << endl ;
1163  return 0 ;
1164  }
1165 
1166  // Find histogram object
1167  RooHist* hist = (RooHist*) findObject(histname,RooHist::Class()) ;
1168  if (!hist) {
1169  coutE(InputArguments) << "RooPlot::residHist(" << GetName() << ") cannot find histogram" << endl ;
1170  return 0 ;
1171  }
1172 
1173  return hist->makeResidHist(*curve,normalize,useAverage) ;
1174 }
1175 
1176 
1177 
1178 ////////////////////////////////////////////////////////////////////////////////
1179 /// Initialize the DrawOpt helper class
1180 
1181 void RooPlot::DrawOpt::initialize(const char* inRawOpt)
1182 {
1183  if (!inRawOpt) {
1184  drawOptions[0] = 0 ;
1185  invisible=kFALSE ;
1186  return ;
1187  }
1188  strlcpy(drawOptions,inRawOpt,128) ;
1189  strtok(drawOptions,":") ;
1190  const char* extraOpt = strtok(0,":") ;
1191  if (extraOpt) {
1192  invisible = (extraOpt[0]=='I') ;
1193  }
1194 }
1195 
1196 
1197 ////////////////////////////////////////////////////////////////////////////////
1198 /// Return the raw draw options
1199 
1200 const char* RooPlot::DrawOpt::rawOpt() const
1201 {
1202  static char buf[128] ;
1203  strlcpy(buf,drawOptions,128) ;
1204  if (invisible) {
1205  strlcat(buf,":I",128) ;
1206  }
1207  return buf ;
1208 }
1209 
1210 
1211 
1212 ////////////////////////////////////////////////////////////////////////////////
1213 /// Return the number of events that is associated with the range [xlo,xhi]
1214 /// This method is only fully functional for ranges not equal to the full
1215 /// range if the object that inserted the normalization data provided
1216 /// a link to an external object that can calculate the event count in
1217 /// in sub ranges. An error will be printed if this function is used
1218 /// on sub-ranges while that information is not available
1219 
1220 Double_t RooPlot::getFitRangeNEvt(Double_t xlo, Double_t xhi) const
1221 {
1222  Double_t scaleFactor = 1.0 ;
1223  if (_normObj) {
1224  scaleFactor = _normObj->getFitRangeNEvt(xlo,xhi)/_normObj->getFitRangeNEvt() ;
1225  } else {
1226  coutW(Plotting) << "RooPlot::getFitRangeNEvt(" << GetName() << ") WARNING: Unable to obtain event count in range "
1227  << xlo << " to " << xhi << ", substituting full event count" << endl ;
1228  }
1229  return getFitRangeNEvt()*scaleFactor ;
1230 }
1231 
1232 
1233 ////////////////////////////////////////////////////////////////////////////////
1234 /// Set the name of the RooPlot to 'name'
1235 
1236 void RooPlot::SetName(const char *name)
1237 {
1238  if (_dir) _dir->GetList()->Remove(this);
1239  TNamed::SetName(name) ;
1240  if (_dir) _dir->GetList()->Add(this);
1241 }
1242 
1243 
1244 ////////////////////////////////////////////////////////////////////////////////
1245 /// Set the name and title of the RooPlot to 'name' and 'title'
1246 
1247 void RooPlot::SetNameTitle(const char *name, const char* title)
1248 {
1249  if (_dir) _dir->GetList()->Remove(this);
1250  TNamed::SetNameTitle(name,title) ;
1251  if (_dir) _dir->GetList()->Add(this);
1252 }
1253 
1254 
1255 ////////////////////////////////////////////////////////////////////////////////
1256 /// Set the title of the RooPlot to 'title'
1257 
1258 void RooPlot::SetTitle(const char* title)
1259 {
1260  TNamed::SetTitle(title) ;
1261  _hist->SetTitle(title) ;
1262 }
1263 
1264 
1265 
1266 ////////////////////////////////////////////////////////////////////////////////
1267 /// Define default print options, for a given print style
1268 
1269 Int_t RooPlot::defaultPrintContents(Option_t* /*opt*/) const
1270 {
1271  return kName|kArgs|kValue ;
1272 }
1273 
1274 
1275 
1276 TAxis* RooPlot::GetXaxis() const { return _hist->GetXaxis() ; }
1277 TAxis* RooPlot::GetYaxis() const { return _hist->GetYaxis() ; }
1278 Int_t RooPlot::GetNbinsX() const { return _hist->GetNbinsX() ; }
1279 Int_t RooPlot::GetNdivisions(Option_t* axis) const { return _hist->GetNdivisions(axis) ; }
1280 Double_t RooPlot::GetMinimum(Double_t minval) const { return _hist->GetMinimum(minval) ; }
1281 Double_t RooPlot::GetMaximum(Double_t maxval) const { return _hist->GetMaximum(maxval) ; }
1282 
1283 
1284 void RooPlot::SetAxisColor(Color_t color, Option_t* axis) { _hist->SetAxisColor(color,axis) ; }
1285 void RooPlot::SetAxisRange(Double_t xmin, Double_t xmax, Option_t* axis) { _hist->SetAxisRange(xmin,xmax,axis) ; }
1286 void RooPlot::SetBarOffset(Float_t offset) { _hist->SetBarOffset(offset) ; }
1287 void RooPlot::SetBarWidth(Float_t width) { _hist->SetBarWidth(width) ; }
1288 void RooPlot::SetContour(Int_t nlevels, const Double_t* levels) { _hist->SetContour(nlevels,levels) ; }
1289 void RooPlot::SetContourLevel(Int_t level, Double_t value) { _hist->SetContourLevel(level,value) ; }
1290 void RooPlot::SetDrawOption(Option_t* option) { _hist->SetDrawOption(option) ; }
1291 void RooPlot::SetFillAttributes() { _hist->SetFillAttributes() ; }
1292 void RooPlot::SetFillColor(Color_t fcolor) { _hist->SetFillColor(fcolor) ; }
1293 void RooPlot::SetFillStyle(Style_t fstyle) { _hist->SetFillStyle(fstyle) ; }
1294 void RooPlot::SetLabelColor(Color_t color, Option_t* axis) { _hist->SetLabelColor(color,axis) ; }
1295 void RooPlot::SetLabelFont(Style_t font, Option_t* axis) { _hist->SetLabelFont(font,axis) ; }
1296 void RooPlot::SetLabelOffset(Float_t offset, Option_t* axis) { _hist->SetLabelOffset(offset,axis) ; }
1297 void RooPlot::SetLabelSize(Float_t size, Option_t* axis) { _hist->SetLabelSize(size,axis) ; }
1298 void RooPlot::SetLineAttributes() { _hist->SetLineAttributes() ; }
1299 void RooPlot::SetLineColor(Color_t lcolor) { _hist->SetLineColor(lcolor) ; }
1300 void RooPlot::SetLineStyle(Style_t lstyle) { _hist->SetLineStyle(lstyle) ; }
1301 void RooPlot::SetLineWidth(Width_t lwidth) { _hist->SetLineWidth(lwidth) ; }
1302 void RooPlot::SetMarkerAttributes() { _hist->SetMarkerAttributes() ; }
1303 void RooPlot::SetMarkerColor(Color_t tcolor) { _hist->SetMarkerColor(tcolor) ; }
1304 void RooPlot::SetMarkerSize(Size_t msize) { _hist->SetMarkerSize(msize) ; }
1305 void RooPlot::SetMarkerStyle(Style_t mstyle) { _hist->SetMarkerStyle(mstyle) ; }
1306 void RooPlot::SetNdivisions(Int_t n, Option_t* axis) { _hist->SetNdivisions(n,axis) ; }
1307 void RooPlot::SetOption(Option_t* option) { _hist->SetOption(option) ; }
1308 void RooPlot::SetStats(Bool_t stats) { _hist->SetStats(stats) ; }
1309 void RooPlot::SetTickLength(Float_t length, Option_t* axis) { _hist->SetTickLength(length,axis) ; }
1310 void RooPlot::SetTitleFont(Style_t font, Option_t* axis) { _hist->SetTitleFont(font,axis) ; }
1311 void RooPlot::SetTitleOffset(Float_t offset, Option_t* axis) { _hist->SetTitleOffset(offset,axis) ; }
1312 void RooPlot::SetTitleSize(Float_t size, Option_t* axis) { _hist->SetTitleSize(size,axis) ; }
1313 void RooPlot::SetXTitle(const char *title) { _hist->SetXTitle(title) ; }
1314 void RooPlot::SetYTitle(const char *title) { _hist->SetYTitle(title) ; }
1315 void RooPlot::SetZTitle(const char *title) { _hist->SetZTitle(title) ; }
1316 
1317 
1318 
1319 
1320 ////////////////////////////////////////////////////////////////////////////////
1321 /// Plot RooPlot when double-clicked in browser
1322 
1323 void RooPlot::Browse(TBrowser * /*b*/)
1324 {
1325  Draw();
1326  gPad->Update();
1327 }
1328 
1329 
1330 
1331 
1332 ////////////////////////////////////////////////////////////////////////////////
1333 
1334 void RooPlot::Streamer(TBuffer &R__b)
1335 {
1336  // Custom streamer, needed for backward compatibility
1337 
1338  if (R__b.IsReading()) {
1339 
1340  TH1::AddDirectory(kFALSE) ;
1341 
1342  // The default c'tor might have registered this with a TDirectory.
1343  // Streaming the TNamed will make this not retrievable anymore, so
1344  // unregister first.
1345  if (_dir)
1346  _dir->Remove(this);
1347 
1348  UInt_t R__s, R__c;
1349  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
1350  if (R__v > 1) {
1351  R__b.ReadClassBuffer(RooPlot::Class(),this,R__v,R__s,R__c);
1352  } else {
1353  // backward compatible streamer code here
1354  // Version 1 of RooPlot was deriving from TH1 and RooPrintable
1355  // Version 2 derives instead from TNamed and RooPrintable
1356  _hist = new TH1F();
1357  _hist->TH1::Streamer(R__b);
1358  SetName(_hist->GetName());
1359  SetTitle(_hist->GetTitle());
1360  RooPrintable::Streamer(R__b);
1361  _items.Streamer(R__b);
1362  R__b >> _padFactor;
1363  R__b >> _plotVarClone;
1364  R__b >> _plotVarSet;
1365  R__b >> _normVars;
1366  R__b >> _normNumEvts;
1367  R__b >> _normBinWidth;
1368  R__b >> _defYmin;
1369  R__b >> _defYmax;
1370  R__b.CheckByteCount(R__s, R__c, RooPlot::IsA());
1371  }
1372 
1373  TH1::AddDirectory(kTRUE) ;
1374  if (_dir)
1375  _dir->Append(this);
1376 
1377  } else {
1378  R__b.WriteClassBuffer(RooPlot::Class(),this);
1379  }
1380 }
1381 
1382 ////////////////////////////////////////////////////////////////////////////////
1383 /// Build a legend that contains all objects that have been drawn on the plot.
1384 std::unique_ptr<TLegend> RooPlot::BuildLegend() const {
1385  std::unique_ptr<TLegend> leg(new TLegend(0.5, 0.7, 0.9, 0.9));
1386  leg->SetBorderSize(0);
1387  leg->SetFillStyle(0);
1388  for (int i=0; i < _items.GetSize(); ++i) {
1389  leg->AddEntry(getObject(i));
1390  }
1391 
1392  return leg;
1393 }