BCH1D.cxx
1 /*
2  * Copyright (C) 2007-2018, the BAT core developer team
3  * All rights reserved.
4  *
5  * For the licensing terms see doc/COPYING.
6  * For documentation see http://mpp.mpg.de/bat
7  */
8 
9 // ---------------------------------------------------------
10 
11 #include "BCH1D.h"
12 
13 #include "BCAux.h"
14 #include "BCLog.h"
15 
16 #include <TArrow.h>
17 #include <TAxis.h>
18 #include <TH1D.h>
19 #include <TLegendEntry.h>
20 #include <TLine.h>
21 #include <TMarker.h>
22 #include <TPad.h>
23 #include <TROOT.h>
24 #include <TString.h>
25 #include <TStyle.h>
26 
27 #include <algorithm>
28 #include <limits>
29 #include <math.h>
30 
31 // ---------------------------------------------------------
32 BCH1D::BCH1D(const TH1* const hist)
33  : BCHistogramBase(hist, 1)
34  , fBandType(kSmallestInterval)
35  , fNQuantiles(0)
36  , fQuantileLineColor(kBlack)
37  , fDrawMedian(false)
38  , fDrawCentral68(true)
39 {
40 }
41 
42 // ---------------------------------------------------------
43 BCH1D::BCH1D(const BCH1D& other)
44  : BCHistogramBase(other)
45 {
46  CopyOptions(other);
47 }
48 
49 // ---------------------------------------------------------
50 void BCH1D::CopyOptions(const BCH1D& other)
51 {
53  fBandType = other.fBandType;
54  fNQuantiles = other.fNQuantiles;
56  fDrawMedian = other.fDrawMedian;
58 }
59 
60 // ---------------------------------------------------------
62 {
65 }
66 
67 // ---------------------------------------------------------
68 double BCH1D::GetQuantile(double probability)
69 {
70  int nquantiles = 1;
71  double quantiles[1];
72  double probsum[1];
73 
74  probsum[0] = probability;
75 
76  // use ROOT function to calculate quantile.
77  fHistogram->GetQuantiles(nquantiles, quantiles, probsum);
78 
79  return quantiles[0];
80 }
81 
82 // ---------------------------------------------------------
83 void BCH1D::CheckIntervals(std::vector<double>& intervals)
84 {
85  // check & sort interval values
86  if (fBandType != kNoBands)
87  BCHistogramBase::CheckIntervals(fIntervals, (fBandType == kLowerLimit) ? -1 : +1);
88 
89  // check number of intervals values if user-specified
90  if (fBandType == kUserSpecified && intervals.size() == 1) {
91  BCLog::OutWarning("BCH1D::CheckIntervals : at least two intervals values must be specified for user-specified intervals. No bands will be drawn.");
92  intervals.clear();
93  }
94 }
95 
96 // ---------------------------------------------------------
97 std::vector<double> BCH1D::DefaultIntervals(int nbands)
98 {
99  if (nbands < 0)
100  nbands = fNBands;
101 
102  std::vector<double> intervals;
103 
104  switch (fBandType) {
105 
106  case kNoBands:
107  case kUserSpecified:
108  return intervals;
109 
110  case kUpperLimit:
111  if (nbands > 0) intervals.push_back(0.90);
112  if (nbands > 1) intervals.push_back(0.95);
113  if (nbands > 2) intervals.push_back(0.99);
114  for (int i = 3; i < nbands; ++i) // not recommended to go (far) beyond 3
115  intervals.push_back(0.9 + intervals.back() / 10.);
116  return intervals;
117 
118  case kLowerLimit:
119  if (nbands > 0) intervals.push_back(0.10);
120  if (nbands > 1) intervals.push_back(0.05);
121  if (nbands > 2) intervals.push_back(0.01);
122  for (int i = 3; i < nbands; ++i) // not recommended to go (far) beyond 3
123  intervals.push_back(intervals.back() / 10.);
124  return intervals;
125 
126  case kCentralInterval:
127  case kSmallestInterval:
128  default:
129  return BCHistogramBase::DefaultIntervals(nbands);
130 
131  }
132 }
133 
134 // ---------------------------------------------------------
135 void BCH1D::DrawBands(const std::string& options)
136 {
137  GetHistogram()->Draw(options.data());
138 
139  if ( fBandType == kNoBands || GetHistogram()->Integral() <= 0 )
140  return;
141 
142  std::vector<double> intervals = fIntervals;
143  CheckIntervals(intervals);
144 
145  if (intervals.empty())
146  return;
147 
148  unsigned nbands = intervals.size() - ((fBandType == kUserSpecified) ? 1 : 0);
149 
150  // calculate bounds for smallest intervals, if using
151  std::vector<std::pair<double, double> > bounds;
152  if (fBandType == kSmallestInterval) {
153  bounds = GetSmallestIntervalBounds(intervals, fBandOvercoverage);
154  nbands = bounds.size();
155  }
156 
157  // make sure enough colors have been designated
158  while (nbands > fBandColors.size())
159  fBandColors.push_back(fBandColors.back() - 1);
160 
161  int i0 = fROOTObjects.size();
162  for (int i = nbands - 1; i >= 0; --i) {
163 
164  TH1* hist_band = NULL;
165  std::string legend_text;
166 
167  if (fBandType == kSmallestInterval) {
168  hist_band = BCAux::OwnClone(GetHistogram(), std::string(GetHistogram()->GetName()) + "_band");
169 
170  for (int b = 1; b <= hist_band->GetNbinsX(); ++b)
171  if (hist_band->GetBinContent(b) < bounds[i].first)
172  hist_band->SetBinContent(b, 0);
173  legend_text = "smallest %.1f%% interval(s)";
174  } else {
175  double p[2] = {0, 1};
176  switch (fBandType) {
177 
178  case kUpperLimit:
179  p[1] = intervals[i];
180  legend_text = "%.0f%% upper limit";
181  break;
182 
183  case kLowerLimit:
184  p[0] = intervals[i];
185  legend_text = "%.0f%% lower limit";
186  break;
187 
188  case kUserSpecified:
189  p[0] = intervals[i];
190  p[1] = intervals[i + 1];
191  legend_text = Form("%%.1f%%%% interval from %.1f%%%% to %.1f%%%%", p[0] * 100, p[1] * 100);
192  break;
193 
194  case kCentralInterval:
195  default:
196  p[0] = 0.5 - intervals[i] / 2;
197  p[1] = 0.5 + intervals[i] / 2;
198  legend_text = "central %.1f%% interval";
199  break;
200  }
201  double q[2];
202  if (fHistogram->GetQuantiles(2, q, p) == 2)
203  hist_band = GetSubHistogram(q[0], q[1]);
204  }
205 
206  if (!hist_band)
207  continue;
208 
209  // set style of band histogram
210  hist_band->SetFillStyle(GetBandFillStyle());
211  hist_band->SetFillColor(GetBandColor(i));
212  hist_band->SetLineColor(GetBandColor(i));
213  hist_band->SetLineWidth(0);
214  hist_band->SetLineStyle(0);
215  hist_band->SetTitle(Form(legend_text.data(), hist_band->Integral("width") * 100));
216 
217  // draw band
218  hist_band->Draw(options.data());
219  fROOTObjects.push_back(hist_band);
220 
221  }
222  for (int i = fROOTObjects.size() - 1; i >= i0; --i)
223  AddBandLegendEntry(fROOTObjects[i], "", "F");
224 
225  // redraw histogram
226  GetHistogram()->Draw(options.data());
227 }
228 
229 // ---------------------------------------------------------
231 {
234  DrawMedian();
235 }
236 
237 
238 // ---------------------------------------------------------
239 void BCH1D::DrawQuantiles(const unsigned n)
240 {
241  if (n <= 1)
242  return;
243 
244  // calculate quantile values (q)
245  std::vector<double> q(n - 1, 0);
246  std::vector<double> p(n - 1, 0);
247  for (unsigned i = 1; i < n; ++i)
248  p[i - 1] = i * 1. / n;
249  if (GetHistogram()->GetQuantiles(n - 1, &q[0], &p[0]) != (int)n - 1)
250  return;
251 
252  TLine* quantile_line = new TLine();
253  fROOTObjects.push_back(quantile_line);
254  quantile_line->SetLineStyle(2);
255  quantile_line->SetLineColor(GetQuantileLineColor());
256 
257  double ymin = gPad->GetUymin();
258  double ymax = gPad->GetUymax();
259  if (gPad->GetLogy()) {
260  ymin = pow(10, ymin);
261  ymax = pow(10, ymax);
262  }
263 
264  // draw quantile lines
265  for (unsigned i = 0; i < n - 1; ++i)
266  quantile_line->DrawLine(q[i], ymin, q[i], GetHistogram()->GetBinContent(GetHistogram()->FindFixBin(q[i])));
267 
268  std::string quantile_text;
269  switch (n) {
270  case 2:
271  quantile_text = "median";
272  break;
273  case 3:
274  quantile_text = "terciles";
275  break;
276  case 4:
277  quantile_text = "quartiles";
278  break;
279  case 5:
280  quantile_text = "quintiles";
281  break;
282  case 6:
283  quantile_text = "sextiles";
284  break;
285  case 7:
286  quantile_text = "septiles";
287  break;
288  case 8:
289  quantile_text = "octiles";
290  break;
291  case 10:
292  quantile_text = "deciles";
293  break;
294  case 12:
295  quantile_text = "duodeciles";
296  break;
297  case 20:
298  quantile_text = "vigintiles";
299  break;
300  case 100:
301  quantile_text = "percentiles";
302  break;
303  default:
304  quantile_text = Form("%d-quantiles", n);
305  break;
306  }
307  AddLegendEntry(quantile_line, quantile_text.data(), "L");
308 }
309 
310 // ---------------------------------------------------------
312 {
313  if ( !fDrawMedian || fNQuantiles == 2)
314  return;
315 
316  double ymin = gPad->GetUymin();
317  double ymax = gPad->GetUymax();
318  double ymid = 0.5 * (ymin + ymax);
319  if (gPad->GetLogy()) {
320  ymin = pow(10, ymin);
321  ymax = pow(10, ymax);
322  ymid = pow(10, ymid);
323  }
324 
325  TMarker* marker_median = new TMarker(GetMedian(), ymid * (fLogy ? pow(ymax / ymin, -0.1) : 0.8), 21);
326  fROOTObjects.push_back(marker_median);
327  marker_median->SetMarkerColor(GetMarkerColor());
328  marker_median->SetMarkerSize(fMarkerScale * gPad->GetWNDC());
329  marker_median->Draw();
330 
331  TLegendEntry* le = 0;
332  double q[2], p[2] = {0.1587, 0.8413};
333 
334  if (fDrawCentral68 && GetHistogram()->GetQuantiles(2, q, p) == 2) {
335  TArrow* arrow_ci = new TArrow(q[0], ymid * (fLogy ? pow(ymax / ymin, -0.1) : 0.8),
336  q[1], ymid * (fLogy ? pow(ymax / ymin, -0.1) : 0.8),
337  0.02 * gPad->GetWNDC(), "<|>");
338  fROOTObjects.push_back(arrow_ci);
339  arrow_ci->SetLineColor(marker_median->GetMarkerColor());
340  arrow_ci->SetFillColor(marker_median->GetMarkerColor());
341  arrow_ci->Draw();
342  le = AddLegendEntry(arrow_ci, "median and central 68% interval", "PL");
343  le->SetLineColor(arrow_ci->GetLineColor());
344  } else
345  le = AddLegendEntry(marker_median, "median", "P");
346  le->SetMarkerStyle(marker_median->GetMarkerStyle());
347  le->SetMarkerSize(marker_median->GetMarkerSize());
348  le->SetMarkerColor(marker_median->GetMarkerColor());
349 }
350 
351 // ---------------------------------------------------------
352 TH1* BCH1D::GetSubHistogram(double min, double max, const std::string& name, bool preserve_range)
353 {
354  if (min == max || !GetHistogram())
355  return 0;
356  if (min > max)
357  return GetSubHistogram(max, min, name);
358 
359  double xmin = GetHistogram()->GetXaxis()->GetXmin();
360  double xmax = GetHistogram()->GetXaxis()->GetXmax();
361 
362  if (max < xmin || min > xmax)
363  return 0;
364 
365  std::string newName(name);
366  if (name.empty())
367  newName = std::string(GetHistogram()->GetName()) + "_subhist";
368 
369  if ( min <= xmin && max >= xmax ) {
370  return BCAux::OwnClone(GetHistogram(), name);
371  }
372  min = std::max<double>(min, xmin);
373  max = std::min<double>(max, xmax);
374 
375  int imin = (min > xmin) ? GetHistogram()->FindFixBin(min) : 1;
376  int imax = (max < xmax) ? GetHistogram()->FindFixBin(max) : GetHistogram()->GetNbinsX();
377 
378  // create binning for new histogram
379  std::vector<double> bins(GetHistogram()->GetNbinsX() + 2, 0);
380  bins[0] = (preserve_range) ? xmin : min;
381  int i0 = (preserve_range) ? 2 : imin + 1;
382  int i1 = (preserve_range) ? GetHistogram()->GetNbinsX() : imax;
383  unsigned n = 1;
384  for (int i = i0; i <= i1; ++i) {
385  bins[n++] = GetHistogram()->GetXaxis()->GetBinLowEdge(i);
386  if (min > GetHistogram()->GetXaxis()->GetBinLowEdge(i) && min < GetHistogram()->GetXaxis()->GetBinUpEdge(i))
387  bins[n++] = min;
388  if (max > GetHistogram()->GetXaxis()->GetBinLowEdge(i) && max < GetHistogram()->GetXaxis()->GetBinUpEdge(i))
389  bins[n++] = max;
390  }
391  if (preserve_range || max == GetHistogram()->GetXaxis()->GetBinUpEdge(i1))
392  bins[n++] = GetHistogram()->GetXaxis()->GetBinUpEdge(i1);
393 
394  // now define the new histogram
395  TH1* h0;
396  {
398  h0 = new TH1D(newName.data(), Form("%s;%s;%s", GetHistogram()->GetTitle(), GetHistogram()->GetXaxis()->GetTitle(), GetHistogram()->GetYaxis()->GetTitle()), n - 1, &bins[0]);
399  }
400  imin = h0->FindFixBin(min);
401  imax = h0->FindFixBin(max);
402  for (int i = imin; i <= imax; ++i)
403  h0->SetBinContent(i, GetHistogram()->GetBinContent(GetHistogram()->FindFixBin(h0->GetBinCenter(i))));
404  return h0;
405 }
406 
407 // ---------------------------------------------------------
408 void BCH1D::PrintSummary(const std::string& prefix, unsigned prec, std::vector<double> intervals)
409 {
410  if (!GetHistogram())
411  return;
412 
413  double p[7] = {5e-2, 10e-2, 16e-2, 50e-2, 84e-2, 90e-2, 95e-2};
414  double q[7];
415  GetHistogram()->GetQuantiles(7, q, p);
416 
417  BCLog::OutSummary(prefix + Form("Mean +- sqrt(Variance): %+.*g +- %.*g", prec, GetHistogram()->GetMean(), prec, GetHistogram()->GetRMS()));
418  BCLog::OutSummary(prefix + Form("Median +- central 68%% interval: %+.*g + %.*g - %.*g", prec, q[3], prec, q[4] - q[3], prec, q[3] - q[2]));
419  BCLog::OutSummary(prefix + Form("(Marginalized) mode: %+.*g", prec, GetLocalMode()));
420  BCLog::OutSummary(prefix + Form("%2.0f%% quantile: %+.*g", 100 * p[0], prec, q[0]));
421  BCLog::OutSummary(prefix + Form("%2.0f%% quantile: %+.*g", 100 * p[1], prec, q[1]));
422  BCLog::OutSummary(prefix + Form("%2.0f%% quantile: %+.*g", 100 * p[2], prec, q[2]));
423  BCLog::OutSummary(prefix + Form("%2.0f%% quantile: %+.*g", 100 * p[4], prec, q[4]));
424  BCLog::OutSummary(prefix + Form("%2.0f%% quantile: %+.*g", 100 * p[5], prec, q[5]));
425  BCLog::OutSummary(prefix + Form("%2.0f%% quantile: %+.*g", 100 * p[6], prec, q[6]));
426 
427  std::vector<BCH1D::BCH1DSmallestInterval> v = GetSmallestIntervals(intervals);
428  for (unsigned i = 0; i < v.size(); ++i)
429  v[i].PrintSummary(prefix, prec);
430 }
431 
432 // ---------------------------------------------------------
433 void BCH1D::BCH1DSmallestInterval::PrintSummary(const std::string& prefix, unsigned prec) const
434 {
435  BCLog::OutSummary(prefix + Form("Smallest interval%s containing %.1f%% and local mode%s:", (intervals.size() > 1 ? "s" : ""), 100. * total_mass, (intervals.size() > 1 ? "s" : "")));
436  for (unsigned i = 0; i < intervals.size(); ++i)
437  intervals[i].PrintSummary(prefix, prec);
438 }
439 
440 // ---------------------------------------------------------
441 void BCH1D::BCH1DInterval::PrintSummary(const std::string& prefix, unsigned prec) const
442 {
443  BCLog::OutSummary(prefix + Form("(%.*g, %.*g) (local mode at %.*g with rel. height %.*g; rel. area %.*g)",
444  prec, xmin,
445  prec, xmax,
446  prec, mode,
447  prec, relative_height,
448  prec, relative_mass));
449 }
450 
451 // ---------------------------------------------------------
452 std::vector<BCH1D::BCH1DSmallestInterval> BCH1D::GetSmallestIntervals(std::vector<double> masses)
453 {
454  std::vector<std::pair<double, double> > bounds = GetSmallestIntervalBounds(masses);
455 
456  std::vector<BCH1D::BCH1DSmallestInterval> result;
457 
458  for (unsigned i = 0; i < bounds.size(); ++i) {
459  BCH1D::BCH1DSmallestInterval smallest_interval;
460  smallest_interval.total_mass = 0;
461  for (int b = 1; b <= GetHistogram()->GetNbinsX(); ++b)
462  if (GetHistogram()->GetBinContent(b) >= bounds[i].first) {
463  BCH1D::BCH1DInterval interval;
464  interval.xmin = GetHistogram()->GetXaxis()->GetBinLowEdge(b);
465  interval.xmax = GetHistogram()->GetXaxis()->GetBinUpEdge(b);
466  interval.relative_height = GetHistogram()->GetBinContent(b);
467  interval.mode = GetHistogram()->GetBinCenter(b);
468  interval.relative_mass += GetHistogram()->Integral(b, b, "width");
469  while (b < GetHistogram()->GetNbinsX() and GetHistogram()->GetBinContent(b + 1) >= bounds[i].first) {
470  interval.xmax = GetHistogram()->GetXaxis()->GetBinUpEdge(++b);
471  interval.relative_mass += GetHistogram()->Integral(b, b, "width");
472  if (GetHistogram()->GetBinContent(b) > interval.relative_height) {
473  interval.relative_height = GetHistogram()->GetBinContent(b);
474  interval.mode = GetHistogram()->GetBinCenter(b);
475  }
476  }
477  smallest_interval.intervals.push_back(interval);
478  if (smallest_interval.total_mass == 0) {
479  smallest_interval.mode = interval.mode;
480  smallest_interval.max_val = interval.relative_height;
481  } else if (interval.relative_height > smallest_interval.max_val) {
482  smallest_interval.mode = interval.mode;
483  smallest_interval.max_val = interval.relative_height;
484  }
485  smallest_interval.total_mass += interval.relative_mass;
486  }
487  for (unsigned j = 0; j < smallest_interval.intervals.size(); ++j) {
488  smallest_interval.intervals[j].relative_mass /= smallest_interval.total_mass;
489  smallest_interval.intervals[j].relative_height /= smallest_interval.max_val;
490  }
491  result.push_back(smallest_interval);
492  }
493  return result;
494 }
495 
496 // ---------------------------------------------------------
497 BCH1D::BCH1DInterval::BCH1DInterval():
498  xmin(std::numeric_limits<double>::quiet_NaN()),
499  xmax(std::numeric_limits<double>::quiet_NaN()),
500  mode(std::numeric_limits<double>::quiet_NaN()),
501  relative_height(0),
502  relative_mass(0)
503 {
504 }
505 
506 // ---------------------------------------------------------
507 BCH1D::BCH1DSmallestInterval::BCH1DSmallestInterval():
508  intervals(),
509  total_mass(0),
510  mode(0),
511  max_val(0)
512 {
513 }
double fMarkerScale
Marker size scale.
std::vector< int > fBandColors
The colors of the color scheme.
unsigned fNQuantiles
Number of quantiles to draw.
Definition: BCH1D.h:301
virtual void DrawBands(const std::string &options="same")
Draw bands.
Definition: BCH1D.cxx:135
int GetQuantileLineColor()
Definition: BCH1D.h:119
virtual void DrawMarkers()
Draw markers (global mode, local mode, etc.).
double GetLocalMode()
Definition: BCH1D.h:78
T * OwnClone(const T *o)
Create a clone of the input but avoid registering the object with ROOT so it cannot be deleted twice...
Definition: BCAux.h:189
void PrintSummary(const std::string &prefix="", unsigned prec=6) const
Print information to log.
Definition: BCH1D.cxx:441
double GetQuantile(double probability)
Returns the quantile of the distribution.
Definition: BCH1D.cxx:68
virtual std::vector< double > DefaultIntervals(int nbands=-1)
Return default intervals.
Definition: BCH1D.cxx:97
A guard object to prevent ROOT from taking over ownership of TNamed objects.
Definition: BCAux.h:171
TH1 * GetSubHistogram(double min, double max, const std::string &name="", bool preserve_range=false)
Get histogram with bins outside min, max band being zero.
Definition: BCH1D.cxx:352
virtual void DrawMarkers()
Draw markers: global mode, local mode, mean, quantiles, median.
Definition: BCH1D.cxx:230
TLegendEntry * AddLegendEntry(TObject *obj, const std::string &label, const std::string &options)
Add legend entry, checking first for unused extra entries.
void CopyOptions(const BCH1D &other)
Copy options from other.
Definition: BCH1D.cxx:50
void PrintSummary(const std::string &prefix="", unsigned prec=6) const
Print information to log.
Definition: BCH1D.cxx:433
virtual void CheckIntervals(std::vector< double > &intervals)
Check intervals: remove values below 0 or above 1, and sort to proper order for band type...
Definition: BCH1D.cxx:83
virtual void CheckIntervals(std::vector< double > &intervals, int sort)
Check intervals: remove values below 0 or above 1.
BCH1D(const TH1 *const hist=0)
The default constructor.
Definition: BCH1D.cxx:32
int GetBandColor(int index) const
Returns a band color of the current color scheme.
virtual void CopyOptions(const BCHistogramBase &other)
Copy options from.
TH1 * fHistogram
The histogram.
std::vector< double > fIntervals
intervals to draw.
Contains information about an interval.
Definition: BCH1D.h:228
std::vector< std::pair< double, double > > GetSmallestIntervalBounds(std::vector< double > masses, bool overcoverage=true)
Get probability density levels bounding from below the smallest-interval levels with probability mass...
short GetBandFillStyle() const
double GetMedian()
Definition: BCH1D.h:89
BCHColorScheme
An enumerator for the color schemes.
A base class for drawing histograms in BAT style.
virtual void SetColorScheme(BCHColorScheme scheme)
Sets the color scheme.
virtual std::vector< double > DefaultIntervals(int nbands=-1)
Return default intervals.
bool fBandOvercoverage
flag for whether bands should overcover.
std::vector< TObject * > fROOTObjects
Storage for plot objects.
std::vector< BCH1D::BCH1DSmallestInterval > GetSmallestIntervals(std::vector< double > masses)
Definition: BCH1D.cxx:452
void SetQuantileLineColor(int c)
Set quantile line color.
Definition: BCH1D.h:175
void PrintSummary(const std::string &prefix="", unsigned prec=6, std::vector< double > intervals=std::vector< double >(0))
Print information to log.
Definition: BCH1D.cxx:408
bool fDrawMedian
flag for drawing median.
Definition: BCH1D.h:309
virtual void DrawQuantiles(unsigned n)
Draw quantiles.
Definition: BCH1D.cxx:239
int GetMarkerColor() const
Returns the marker colors (used for mean, median, and mode.
void SetColorScheme(BCHColorScheme scheme)
Sets the color scheme.
Definition: BCH1D.cxx:61
bool fDrawCentral68
flag for darwing central 68% interval arrows.
Definition: BCH1D.h:313
A class for handling 1D distributions.
Definition: BCH1D.h:34
Vector of intervals with information about total mass.
Definition: BCH1D.h:247
int fQuantileLineColor
Quantile line color.
Definition: BCH1D.h:305
virtual void DrawMedian()
Draw median & central 68% interval.
Definition: BCH1D.cxx:311
unsigned fNBands
Number of credibility interval bands to draw.
TLegendEntry * AddBandLegendEntry(TObject *obj, const std::string &label, const std::string &options)
Add band legend entry, creating unused extra entries if necessary.
BCH1DBandType fBandType
Band type.
Definition: BCH1D.h:297
bool fLogy
Flag for controlling log plotting of y axis.