BCHistogramBase.cxx
1 /*
2  * Copyright (C) 2007-2013, 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 "BCHistogramBase.h"
12 
13 #include "BCAux.h"
14 #include "BCLog.h"
15 #include "config.h"
16 
17 #include <TArrow.h>
18 #include <TAxis.h>
19 #include <TH1.h>
20 #include <TH2D.h>
21 #include <TLegend.h>
22 #include <TLegendEntry.h>
23 #include <TMarker.h>
24 #include <TPad.h>
25 #include <TROOT.h>
26 #include <TString.h>
27 
28 #include <algorithm>
29 #include <math.h>
30 
31 // ---------------------------------------------------------
32 BCHistogramBase::BCHistogramBase(const TH1* const hist, int dimension)
33  : fHistogram(0),
34  fNLegendColumns(2),
35  fBandOvercoverage(true),
36  fBandFillStyle(1001),
37  fLineColor(kBlack),
38  fLineStyle(1),
39  fLineWidth(1),
40  fMarkerColor(kBlack),
41  fMarkerScale(1.6),
42  fLogx(false),
43  fLogy(false),
44  fLogz(false),
45  fGridx(false),
46  fGridy(false),
47  fNBands(3),
48  fNSmooth(0),
49  fDrawGlobalMode(true),
50  fDrawGlobalModeArrows(true),
51  fGlobalModeMarkerStyle(24),
52  fDrawLocalMode(false),
53  fDrawLocalModeArrows(true),
54  fLocalModeMarkerStyle(25),
55  fDrawMean(true),
56  fMeanMarkerStyle(20),
57  fDrawStandardDeviation(true),
58  fDrawLegend(true),
59  fDrawStats(false),
60  fDimension(dimension),
61  fROOToptions("HIST")
62 {
63  SetHistogram(hist);
64  SetColorScheme(kGreenYellowRed);
65 
66  fLegend.SetNColumns(fNLegendColumns);
67  fLegend.SetBorderSize(0);
68  fLegend.SetFillColor(kWhite);
69  fLegend.SetTextAlign(12);
70  fLegend.SetTextSize(0.03);
71 
73 }
74 
75 // ---------------------------------------------------------
77  : fHistogram(0)
78  , fLegend(other.fLegend)
79  , fGlobalMode(other.fGlobalMode)
80  , fDimension(other.fDimension)
81 {
82  SetHistogram(other.fHistogram);
83  fLegend.Clear();
84 
85  CopyOptions(other);
86 }
87 
88 // ---------------------------------------------------------
90 {
91  delete fHistogram;
92  for (unsigned i = 0; i < fROOTObjects.size(); ++i)
93  delete fROOTObjects[i];
94 }
95 
96 // ---------------------------------------------------------
98 {
101  fLineColor = other.fLineColor;
102  fLineStyle = other.fLineStyle;
103  fLineWidth = other.fLineWidth;
104  fMarkerColor = other.fMarkerColor;
105  fMarkerScale = other.fMarkerScale;
106  fLogx = other.fLogx;
107  fLogy = other.fLogy;
108  fLogz = other.fLogz;
109  fGridx = other.fGridx;
110  fGridy = other.fGridy;
111  fNBands = other.fNBands;
112  fNSmooth = other.fNSmooth;
119  fDrawMean = other.fDrawMean;
122  fDrawLegend = other.fDrawLegend;
123  fDrawStats = other.fDrawStats;
124  fBandColors = other.fBandColors;
126  fIntervals = other.fIntervals;
127  fROOToptions = other.fROOToptions;
128 }
129 
130 // ---------------------------------------------------------
132 {
133  // swap into this
134  swap(*this, other);
135 
136  return *this;
137 }
138 
139 // ---------------------------------------------------------
140 void swap(BCHistogramBase& first, BCHistogramBase& second)
141 {
142  // swap histogram pointers
143  std::swap(first.fHistogram, second.fHistogram);
144 
145  // swap modes
146  std::swap(first.fLocalMode, second.fLocalMode);
147  std::swap(first.fGlobalMode, second.fGlobalMode);
148 
149  // swap legends
150  TLegend temp(first.fLegend);
151  second.fLegend.Copy(first.fLegend);
152  temp.Copy(second.fLegend);
153  // std::swap(first.fLegend, second.fLegend);
154 
155  // swap dimension
156  std::swap(first.fDimension, second.fDimension);
157 
158  // swap ROOT object pointer vectors
159  std::swap(first.fROOTObjects, second.fROOTObjects);
160 
161  // swap options
162  std::swap(first.fNLegendColumns, second.fNLegendColumns);
163  std::swap(first.fBandFillStyle, second.fBandFillStyle);
164  std::swap(first.fLineColor, second.fLineColor);
165  std::swap(first.fLineStyle, second.fLineStyle);
166  std::swap(first.fLineWidth, second.fLineWidth);
167  std::swap(first.fMarkerColor, second.fMarkerColor);
168  std::swap(first.fMarkerScale, second.fMarkerScale);
169  std::swap(first.fLogx, second.fLogx);
170  std::swap(first.fLogy, second.fLogy);
171  std::swap(first.fLogz, second.fLogz);
172  std::swap(first.fGridx, second.fGridx);
173  std::swap(first.fGridy, second.fGridy);
174  std::swap(first.fNBands, second.fNBands);
175  std::swap(first.fNSmooth, second.fNSmooth);
176  std::swap(first.fDrawGlobalMode, second.fDrawGlobalMode);
177  std::swap(first.fDrawGlobalModeArrows, second.fDrawGlobalModeArrows);
178  std::swap(first.fGlobalModeMarkerStyle, second.fGlobalModeMarkerStyle);
179  std::swap(first.fDrawLocalMode, second.fDrawLocalMode);
180  std::swap(first.fDrawLocalModeArrows, second.fDrawLocalModeArrows);
181  std::swap(first.fLocalModeMarkerStyle, second.fLocalModeMarkerStyle);
182  std::swap(first.fDrawMean, second.fDrawMean);
183  std::swap(first.fMeanMarkerStyle, second.fMeanMarkerStyle);
184  std::swap(first.fDrawStandardDeviation, second.fDrawStandardDeviation);
185  std::swap(first.fDrawLegend, second.fDrawLegend);
186  std::swap(first.fDrawStats, second.fDrawStats);
187  std::swap(first.fBandColors, second.fBandColors);
188  std::swap(first.fBandOvercoverage, second.fBandOvercoverage);
189  std::swap(first.fIntervals, second.fIntervals);
190  std::swap(first.fROOToptions, second.fROOToptions);
191 }
192 
193 // ---------------------------------------------------------
194 void BCHistogramBase::SetHistogram(const TH1* const hist)
195 {
196  delete fHistogram;
197 
198  if (!hist || (fDimension >= 0 && hist->GetDimension() != fDimension)) {
199  fHistogram = 0;
200  fLocalMode.clear();
201  return;
202  }
203 
204  fHistogram = BCAux::OwnClone(hist, Form("%s_bch", hist->GetName()));
205  fHistogram->SetStats(false);
206  fHistogram->SetDirectory(0);
207  fDimension = fHistogram->GetDimension();
208 
209  // normalize; TODO: replace with division of each bin by width/area for arbitrary binning
210  double integral = GetHistogram()->Integral("width");
211  if (integral != 0)
212  GetHistogram()->Scale(1. / integral);
213 
214  // Get local mode
215  int b = GetHistogram()->GetMaximumBin();
216  int bx, by, bz;
217  GetHistogram()->GetBinXYZ(b, bx, by, bz);
218  fLocalMode.assign(1, GetHistogram()->GetXaxis()->GetBinCenter(bx));
219  if (by > 0)
220  fLocalMode.push_back(GetHistogram()->GetYaxis()->GetBinCenter(by));
221  if (bz > 0)
222  fLocalMode.push_back(GetHistogram()->GetZaxis()->GetBinCenter(bz));
223 }
224 
225 // ---------------------------------------------------------
227 {
228  return fHistogram and (fHistogram->Integral() != 0);
229 }
230 
231 // ---------------------------------------------------------
233 {
234  fBandColors.clear();
235 
236  switch (scheme) {
237 
238  case kBlackWhite:
239  AddBandColor(12); // dark
240  AddBandColor(14);
241  AddBandColor(16);
242  AddBandColor(17); // to
243  AddBandColor(18);
244  AddBandColor(19); // light
245  AddBandColor(10); // white
246  SetMarkerColor(kBlack);
247  SetLineColor(kBlack);
248  break;
249 
250  case kBlueOrange:
251  AddBandColor(kBlue);
252  AddBandColor(kBlue - 3);
253  AddBandColor(kBlue - 1);
254  AddBandColor(kBlue - 6);
255  AddBandColor(kBlue - 8);
256  AddBandColor(kBlue - 9);
257  AddBandColor(kBlue - 10);
258  SetMarkerColor(kOrange);
259  SetLineColor(kBlack);
260  break;
261 
262  case kRedGreen:
263  AddBandColor(kRed);
264  AddBandColor(kRed - 3);
265  AddBandColor(kRed - 1);
266  AddBandColor(kRed - 6);
267  AddBandColor(kRed - 8);
268  AddBandColor(kRed - 9);
269  AddBandColor(kRed - 10);
270  SetMarkerColor(kGreen);
271  SetLineColor(kBlack);
272  break;
273 
274  case kGreenYellowRed:
275  default:
276  AddBandColor(kGreen);
277  AddBandColor(kYellow);
278  AddBandColor(kRed);
279  AddBandColor(kRed - 3);
280  AddBandColor(kRed - 1);
281  AddBandColor(kRed - 6);
282  SetMarkerColor(kBlack);
283  SetLineColor(kBlack);
284  break;
285 
286  }
287 
288 }
289 
290 // ---------------------------------------------------------
292 {
293  if (n < 0)
294  n = fNSmooth;
295  if (n <= 0)
296  return;
297  GetHistogram()->Scale(GetHistogram()->Integral("width"));
298  if (GetHistogram()->GetDimension() == 1) {
299  if (GetHistogram()->GetNbinsX() >= 3)
300  GetHistogram()->Smooth(n);
301  } else // ROOT currently only allows single instances of smoothing for TH2
302  for (int i = 0; i < n; ++i)
303  GetHistogram()->Smooth(1);
304  double integral = GetHistogram()->Integral("width");
305  if ( integral != 0 )
306  GetHistogram()->Scale(1. / integral);
307 }
308 
309 // ---------------------------------------------------------
310 void BCHistogramBase::CheckIntervals(std::vector<double>& intervals, int sort)
311 {
312  // remove out-of-bounds entries
313  for (int i = intervals.size() - 1; i >= 0; --i)
314  if (intervals[i] < 0 || intervals[i] > 1) {
315  BCLog::OutWarning(Form("BCHistogramBase::CheckIntervals : interval out of bounds, removing %f", intervals[i]));
316  intervals.erase(intervals.begin() + i);
317  }
318 
319  // sort
320  if (sort > 0)
321  std::stable_sort(intervals.begin(), intervals.end(), std::less<double>());
322  if (sort < 0)
323  std::stable_sort(intervals.begin(), intervals.end(), std::greater<double>());
324 
325  // warning: unique will not reliably remove all duplicates unless the vector has first been sorted.
326  unsigned old_size = intervals.size();
327  std::vector<double>::iterator last = std::unique(intervals.begin(), intervals.end());
328  intervals.erase(last, intervals.end());
329  if (intervals.size() < old_size)
330  BCLog::OutWarning(Form("BCHistogramBase::CheckIntervals : %lu duplicate interval values were removed.", old_size - intervals.size()));
331 }
332 
333 // ---------------------------------------------------------
334 std::vector<double> BCHistogramBase::DefaultIntervals(int nbands)
335 {
336  if (nbands < 0)
337  nbands = fNBands;
338  std::vector<double> intervals;
339  if (nbands > 0) intervals.push_back(0.682689492137);
340  if (nbands > 1) intervals.push_back(0.954499736104);
341  if (nbands > 2) intervals.push_back(0.997300203937);
342  if (nbands > 3) intervals.push_back(0.999936657516);
343  if (nbands > 4) intervals.push_back(0.999999426697);
344  if (nbands > 5) intervals.push_back(0.999999998027);
345  if (nbands > 6) intervals.push_back(0.999999999997);
346  if (nbands > 7) intervals.push_back(1);
347  return intervals;
348 }
349 
350 // ---------------------------------------------------------
351 void BCHistogramBase::GetNonzeroBinDensityMassVector(std::vector<std::pair<double, double> >& bin_dens_mass, int sort)
352 {
353  if (!GetHistogram())
354  return;
355 
356  // calculate number of bins
357  unsigned nbins = GetHistogram()->GetBin(GetHistogram()->GetNbinsX(), GetHistogram()->GetNbinsY(), GetHistogram()->GetNbinsZ());
358 
359  // reserve space
360  bin_dens_mass.reserve(nbins);
361 
362  // fill bin_dens_mass with pairs of (prob. density, prob. mass) for all non-empty bins
363  for (unsigned i = 1; i <= nbins; ++i)
364  if (!GetHistogram()->IsBinUnderflow(i) && !GetHistogram()->IsBinOverflow(i) && GetHistogram()->GetBinContent(i) > 0) {
365  // if 1D, by = bz = -1; if 2D, bz = -1
366  int bx, by, bz;
367  GetHistogram()->GetBinXYZ(i, bx, by, bz);
368  // bin val
369  double v = GetHistogram()->GetBinContent(i);
370  // bin width / area / volume
371  double w = (bx > 0 ? GetHistogram()->GetXaxis()->GetBinWidth(bx) : 1) * (by > 0 ? GetHistogram()->GetYaxis()->GetBinWidth(by) : 1) * (bz > 0 ? GetHistogram()->GetZaxis()->GetBinWidth(bz) : 1);
372  bin_dens_mass.push_back(std::make_pair(v, v * w));
373  }
374  // sort
375  if (sort < 0)
376  std::stable_sort(bin_dens_mass.begin(), bin_dens_mass.end(), std::greater<std::pair<double, double> >());
377  if (sort > 0)
378  std::stable_sort(bin_dens_mass.begin(), bin_dens_mass.end(), std::less<std::pair<double, double> >());
379 }
380 
381 // ---------------------------------------------------------
382 std::vector<std::pair<double, double> > BCHistogramBase::GetSmallestIntervalBounds(std::vector<double> masses, bool overcoverage)
383 {
384  std::vector<std::pair<double, double> > levels;
385 
386  // if no masses asked for or no histogram set, return empty vector
387  if (masses.empty() || !GetHistogram())
388  return levels;
389 
390  // check and sort masses to decreasing order
391  CheckIntervals(masses, -1);
392 
393  // reserce space in the levels vector
394  levels.reserve(masses.size());
395 
396  std::vector<std::pair<double, double> > bin_dens_mass;
397  GetNonzeroBinDensityMassVector(bin_dens_mass, -1); // sorted in decreasing order
398 
399  // consolidate bins by density
400  std::vector<std::pair<double, double> > dens_mass;
401  dens_mass.reserve(bin_dens_mass.size());
402  for (unsigned i = 0; i < bin_dens_mass.size(); ++i) {
403  dens_mass.push_back(bin_dens_mass[i]);
404  while (i < bin_dens_mass.size() - 1 and bin_dens_mass[i + 1].first == dens_mass.back().first)
405  dens_mass.back().second += bin_dens_mass[++i].second;
406  }
407 
408  if (overcoverage) {
409  double prob_sum = 0;
410  for (unsigned i = 0; i < dens_mass.size() and !masses.empty() and prob_sum <= 1; ++i) {
411  prob_sum += dens_mass[i].second;
412  while (!masses.empty() and prob_sum >= masses.back()) {
413  levels.push_back(std::make_pair(dens_mass[i].first, prob_sum));
414  masses.pop_back();
415  }
416  }
417  } else { // undercoverage
418  // remove mass levels that cannot be undercovered
419  double prob_sum = dens_mass.front().second;
420  while (!masses.empty() and masses.back() < prob_sum)
421  masses.pop_back();
422  for (unsigned i = 1; i < dens_mass.size() and !masses.empty() and prob_sum <= 1; ++i) {
423  prob_sum += dens_mass[i].second;
424  while (!masses.empty() and prob_sum >= masses.back()) {
425  levels.push_back(std::make_pair(dens_mass[i - 1].first, prob_sum - dens_mass[i].second));
426  masses.pop_back();
427  }
428  }
429  }
430 
431  std::vector<std::pair<double, double> >::iterator last = std::unique(levels.begin(), levels.end());
432  levels.erase(last, levels.end());
433  return levels;
434 }
435 
436 // ---------------------------------------------------------
437 std::vector<double> BCHistogramBase::GetSmallestIntervalSize(std::vector<double> masses, bool overcoverage)
438 {
439  // vector of sizes
440  std::vector<double> S;
441 
442  // remove out-of-bounds entries
443  for (int i = masses.size() - 1; i >= 0; --i)
444  if (masses[i] < 0 || masses[i] > 1) {
445  BCLog::OutWarning(Form("BCHistogramBase::GetSmallestIntervalSize : mass out of bounds, removing %f", masses[i]));
446  masses.erase(masses.begin() + i);
447  }
448  if (masses.empty())
449  return S;
450 
451  std::vector<std::pair<double, double> > bin_dens_mass;
452  GetNonzeroBinDensityMassVector(bin_dens_mass, -1); // sorted in decreasing order
453 
454  if (bin_dens_mass.empty())
455  return S;
456 
457  S.assign(masses.size(), 0);
458  double mass = 0;
459  for (std::vector<std::pair<double, double> >::const_iterator bin = bin_dens_mass.begin(); bin != bin_dens_mass.end(); ++bin) {
460  for (unsigned i = 0; i < masses.size(); ++i)
461  // if more mass is needed, add area
462  if (mass + (overcoverage ? 0 : bin->second) < masses[i])
463  S[i] += bin->second / bin->first;
464  mass += bin->second;
465  }
466  return S;
467 }
468 
469 // ---------------------------------------------------------
470 double BCHistogramBase::GetSmallestIntervalSize(double mass, bool overcoverage)
471 {
472  std::vector<double> s = GetSmallestIntervalSize(std::vector<double>(1, mass), overcoverage);
473  if (s.empty())
474  return 0;
475  return s[0];
476 }
477 
478 // ---------------------------------------------------------
480 {
481  if (!GetHistogram())
482  return;
483 
484  GetHistogram()->SetStats(fDrawStats);
485  fLegend.SetNColumns(fNLegendColumns);
486 
487  Smooth(fNSmooth);
488 
489  std::string options = fROOToptions;
490  std::transform(options.begin(), options.end(), options.begin(), ::tolower);
491  // if option "same" is not specified, draw axes and add "same" to options
492  if (options.find("same") == std::string::npos) {
493  gPad->SetLogx(fLogx);
494  gPad->SetLogy(fLogy);
495  gPad->SetLogz(fLogz);
496  gPad->SetGridx(fGridx);
497  gPad->SetGridy(fGridy);
498  if (GetHistogram()->GetDimension() == 1) {
499  // necessary because ROOT will otherwise draw space below zero for the errors---which we don't have
500  double ymin = GetHistogram()->GetMinimum();
501  double ymax = GetHistogram()->GetMaximum();
502  GetHistogram()->GetYaxis()->SetRangeUser(ymin, (gPad->GetLogy() ? 2 * ymax : ymax + 0.1 * (ymax - ymin)));
503  }
504  GetHistogram()->Draw("axis");
505  options += "same";
506  }
507 
508  GetHistogram()->SetLineColor(GetLineColor());
509  GetHistogram()->SetLineStyle(GetLineStyle());
510  GetHistogram()->SetLineWidth(GetLineWidth());
511  DrawBands(options);
512 
513  DrawMarkers();
514  if (fDrawLegend)
515  DrawLegend();
516 
517  gPad->RedrawAxis();
518  gPad->Update();
519 }
520 
521 // ---------------------------------------------------------
523 {
524  DrawGlobalMode();
525  DrawLocalMode();
526  DrawMean();
527 }
528 
529 // ---------------------------------------------------------
531 {
532  gPad->Update();
533  double ymin = gPad->GetUymin();
534  double ymax = gPad->GetUymax();
535  double y = ymin + 0.3 * (ymax - ymin);
536  if (gPad->GetLogy()) {
537  ymin = pow(10, ymin);
538  ymax = pow(10, ymax);
539  y = ymin * pow(ymax / ymin, 0.3);
540  }
541  if (GetHistogram()->GetDimension() > 1 && fGlobalMode.size() > 1)
542  y = fGlobalMode[1];
543 
544  if (fDrawGlobalMode && !fGlobalMode.empty()) {
545  TMarker* marker_mode = new TMarker(fGlobalMode[0], y, fGlobalModeMarkerStyle);
546  fROOTObjects.push_back(marker_mode);
547  marker_mode->SetMarkerColor(GetMarkerColor());
548  marker_mode->SetMarkerSize(fMarkerScale * gPad->GetWNDC());
549  marker_mode->Draw();
550 
551  TLegendEntry* le = AddLegendEntry(marker_mode, "global mode", "P");
552  le->SetMarkerStyle(marker_mode->GetMarkerStyle());
553  le->SetMarkerSize(marker_mode->GetMarkerSize());
554  le->SetMarkerColor(marker_mode->GetMarkerColor());
555 
556  if (fDrawGlobalModeArrows) {
557  TArrow* arrow_mode = new TArrow(marker_mode->GetX(), (gPad->GetLogy() ? marker_mode->GetY()*pow(ymax / ymin, -1.5e-2) : marker_mode->GetY() + (ymax - ymin) * -1.5e-2),
558  marker_mode->GetX(), (gPad->GetLogy() ? ymin * pow(ymax / ymin, 4e-2) : ymin + (ymax - ymin) * 4e-2),
559  2e-2 * gPad->GetWNDC(), "|>");
560  fROOTObjects.push_back(arrow_mode);
561  arrow_mode->SetLineColor(marker_mode->GetMarkerColor());
562  arrow_mode->SetFillColor(marker_mode->GetMarkerColor());
563  arrow_mode->Draw();
564 
565  if (GetHistogram()->GetDimension() > 1 && fGlobalMode.size() > 1) {
566  double xmin = gPad->GetUxmin();
567  double xmax = gPad->GetUxmax();
568  if (gPad->GetLogx()) {
569  ymin = pow(10, xmin);
570  ymax = pow(10, xmax);
571  }
572  TArrow* arrow_mode2 = new TArrow((gPad->GetLogx() ? marker_mode->GetX()*pow(xmax / xmin, -1.5e-2) : marker_mode->GetX() + (xmax - xmin) * -1.5e-2), marker_mode->GetY(),
573  (gPad->GetLogx() ? xmin * pow(xmax / xmin, 4e-2) : xmin + (xmax - xmin) * 4e-2), marker_mode->GetY(),
574  2e-2 * gPad->GetWNDC(), "|>");
575  fROOTObjects.push_back(arrow_mode2);
576  arrow_mode2->SetLineColor(marker_mode->GetMarkerColor());
577  arrow_mode2->SetFillColor(marker_mode->GetMarkerColor());
578  arrow_mode2->Draw();
579  }
580  }
581 
582  }
583 }
584 
585 // ---------------------------------------------------------
587 {
588  gPad->Update();
589  double ymin = gPad->GetUymin();
590  double ymax = gPad->GetUymax();
591  double y = ymin + 0.25 * (ymax - ymin);
592  if (gPad->GetLogy()) {
593  ymin = pow(10, ymin);
594  ymax = pow(10, ymax);
595  y = ymin * pow(ymax / ymin, 0.25);
596  }
597  if (GetHistogram()->GetDimension() > 1 && fLocalMode.size() > 1)
598  y = fLocalMode[1];
599 
600  if (fDrawLocalMode && !fLocalMode.empty()) {
601  TMarker* marker_mode = new TMarker(fLocalMode[0], y, fLocalModeMarkerStyle);
602  fROOTObjects.push_back(marker_mode);
603  marker_mode->SetMarkerColor(GetMarkerColor());
604  marker_mode->SetMarkerSize(fMarkerScale * gPad->GetWNDC());
605  marker_mode->Draw();
606 
607  TLegendEntry* le = AddLegendEntry(marker_mode, "local mode", "P");
608  le->SetMarkerStyle(marker_mode->GetMarkerStyle());
609  le->SetMarkerSize(marker_mode->GetMarkerSize());
610  le->SetMarkerColor(marker_mode->GetMarkerColor());
611 
612  if (fDrawLocalModeArrows) {
613  TArrow* arrow_mode = new TArrow(marker_mode->GetX(), (gPad->GetLogy() ? marker_mode->GetY()*pow(ymax / ymin, -1.5e-2) : marker_mode->GetY() + (ymax - ymin) * -1.5e-2),
614  marker_mode->GetX(), (gPad->GetLogy() ? ymin * pow(ymax / ymin, 3e-2) : ymin + (ymax - ymin) * 3e-2),
615  2e-2 * gPad->GetWNDC(), "|>");
616  fROOTObjects.push_back(arrow_mode);
617  arrow_mode->SetLineColor(marker_mode->GetMarkerColor());
618  arrow_mode->SetFillColor(marker_mode->GetMarkerColor());
619  arrow_mode->Draw();
620 
621  if (GetHistogram()->GetDimension() > 1 && fLocalMode.size() > 1) {
622  double xmin = gPad->GetUxmin();
623  double xmax = gPad->GetUxmax();
624  if (gPad->GetLogx()) {
625  ymin = pow(10, xmin);
626  ymax = pow(10, xmax);
627  }
628  TArrow* arrow_mode2 = new TArrow((gPad->GetLogx() ? marker_mode->GetX()*pow(xmax / xmin, -1.5e-2) : marker_mode->GetX() + (xmax - xmin) * -1.5e-2), marker_mode->GetY(),
629  (gPad->GetLogx() ? xmin * pow(xmax / xmin, 3e-2) : xmin + (xmax - xmin) * 3e-2), marker_mode->GetY(),
630  2e-2 * gPad->GetWNDC(), "|>");
631  fROOTObjects.push_back(arrow_mode2);
632  arrow_mode2->SetLineColor(marker_mode->GetMarkerColor());
633  arrow_mode2->SetFillColor(marker_mode->GetMarkerColor());
634  arrow_mode2->Draw();
635  }
636  }
637 
638  }
639 }
640 
641 // ---------------------------------------------------------
643 {
644  gPad->Update();
645  double ymin = gPad->GetUymin();
646  double ymax = gPad->GetUymax();
647  double y = ymin + 0.4 * (ymax - ymin);
648  if (gPad->GetLogy()) {
649  ymin = pow(10, ymin);
650  ymax = pow(10, ymax);
651  y = ymin * pow(ymax / ymin, 0.4);
652  }
653  if (GetHistogram()->GetDimension() > 1)
654  y = GetHistogram()->GetMean(2);
655 
656  if ( fDrawMean ) {
657  TMarker* marker_mean = new TMarker(GetHistogram()->GetMean(1), y, fMeanMarkerStyle);
658  fROOTObjects.push_back(marker_mean);
659  marker_mean->SetMarkerColor(GetMarkerColor());
660  marker_mean->SetMarkerSize(fMarkerScale * gPad->GetWNDC());
661  marker_mean->Draw();
662 
663  // legend entry is managed separately and need not be in trash
664  TLegendEntry* le = 0;
665  if ( fDrawStandardDeviation ) {
666  TArrow* arrow_std = new TArrow(marker_mean->GetX() - GetHistogram()->GetRMS(1), marker_mean->GetY(),
667  marker_mean->GetX() + GetHistogram()->GetRMS(1), marker_mean->GetY(),
668  0.02 * gPad->GetWNDC(), "<|>");
669  fROOTObjects.push_back(arrow_std);
670  arrow_std->SetLineColor(marker_mean->GetMarkerColor());
671  arrow_std->SetFillColor(marker_mean->GetMarkerColor());
672  arrow_std->Draw();
673  le = AddLegendEntry(arrow_std, "mean and std. dev.", "PL");
674  le->SetLineColor(arrow_std->GetLineColor());
675 
676  if (GetHistogram()->GetDimension() > 1) {
677  TArrow* arrow_std2 = new TArrow(marker_mean->GetX(), marker_mean->GetY() - GetHistogram()->GetRMS(2),
678  marker_mean->GetX(), marker_mean->GetY() + GetHistogram()->GetRMS(2),
679  0.02 * gPad->GetWNDC(), "<|>");
680  fROOTObjects.push_back(arrow_std2);
681  arrow_std2->SetLineColor(marker_mean->GetMarkerColor());
682  arrow_std2->SetFillColor(marker_mean->GetMarkerColor());
683  arrow_std2->Draw();
684  }
685  } else {
686  le = AddLegendEntry(marker_mean, "mean", "P");
687  }
688  le->SetMarkerStyle(marker_mean->GetMarkerStyle());
689  le->SetMarkerSize(marker_mean->GetMarkerSize());
690  le->SetMarkerColor(marker_mean->GetMarkerColor());
691  }
692 }
693 
694 // ---------------------------------------------------------
696 {
697 #if ROOTVERSION >= 6000000
698  fLegend.SetX1(gPad->GetLeftMargin() + (1 - gPad->GetRightMargin() - gPad->GetLeftMargin()) * 10e-2);
699  fLegend.SetX2(1 - gPad->GetRightMargin());
700  fLegend.SetY1(1 - gPad->GetTopMargin() - fLegend.GetTextSize()*fLegend.GetNRows());
701  fLegend.SetY2(1 - gPad->GetTopMargin());
702  fLegend.SetColumnSeparation(0.0);
703  return fLegend.GetY1();
704 #else
705  fLegend.SetX1NDC(gPad->GetLeftMargin() + (1 - gPad->GetRightMargin() - gPad->GetLeftMargin()) * 10e-2);
706  fLegend.SetX2NDC(1 - gPad->GetRightMargin());
707  fLegend.SetY1NDC(1 - gPad->GetTopMargin() - fLegend.GetTextSize()*fLegend.GetNRows());
708  fLegend.SetY2NDC(1 - gPad->GetTopMargin());
709  fLegend.SetColumnSeparation(0.0);
710  return fLegend.GetY1NDC();
711 #endif
712 }
713 
714 // ---------------------------------------------------------
715 TLegendEntry* BCHistogramBase::AddLegendEntry(TObject* obj, const std::string& label, const std::string& options)
716 {
717  if (fExtraLegendEntries.empty())
718  return fLegend.AddEntry(obj, label.data(), options.data());
719  TLegendEntry* le = fExtraLegendEntries.front();
720  le->SetObject(obj);
721  le->SetLabel(label.data());
722  le->SetOption(options.data());
724  return le;
725 }
726 
727 // ---------------------------------------------------------
728 TLegendEntry* BCHistogramBase::AddBandLegendEntry(TObject* obj, const std::string& label, const std::string& options)
729 {
730  TLegendEntry* le = fLegend.AddEntry(obj, label.data(), options.data());
731  for (int i = 1; i < fLegend.GetNColumns(); ++i)
732  fExtraLegendEntries.push_back(fLegend.AddEntry((TObject*)0, "", ""));
733  return le;
734 }
735 
736 // ---------------------------------------------------------
738 {
739  double ymin = gPad->GetUymin();
740  double ymax = gPad->GetUymax();
741  if (gPad->GetLogy()) {
742  ymin = pow(10, ymin);
743  ymax = pow(10, ymax);
744  }
745 
746  fHistogram->GetYaxis()->SetRangeUser(ymin, ymax * (1.15 + fLegend.GetTextSize()*fLegend.GetNRows()) * 1.05);
747 
748  gPad->SetTopMargin(0.02);
749 
750  double y1ndc = ResizeLegend();
751  fLegend.Draw();
752 
753  // rescale top margin
754  gPad->SetTopMargin(1 - y1ndc + 0.01);
755 
756 }
double fMarkerScale
Marker size scale.
friend void swap(BCHistogramBase &first, BCHistogramBase &second)
Swap function.
BCHistogramBase & operator=(BCHistogramBase other)
Assignment operator.
bool fDrawGlobalModeArrows
Flag for drawing global mode arrows.
std::vector< int > fBandColors
The colors of the color scheme.
virtual void DrawMean()
Draw mean and standard deviation.
std::string fROOToptions
ROOT drawing options.
virtual void DrawMarkers()
Draw markers (global mode, local mode, etc.).
int fMarkerColor
Marker color.
bool fGridy
Flag for drawing of grid on y axis.
int GetLineWidth() const
void SetLineColor(int c)
Set histogram line color.
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
virtual std::vector< double > GetSmallestIntervalSize(std::vector< double > masses, bool overcoverage=true)
Get smallest interval sizes in dimensions of histogram: length (1D), area (2D), volume (3D)...
bool fLogz
Flag for controlling log plotting of z axis.
bool fLogx
Flag for controlling log plotting of x axis.
TLegendEntry * AddLegendEntry(TObject *obj, const std::string &label, const std::string &options)
Add legend entry, checking first for unused extra entries.
short fBandFillStyle
The fill style for the bands.
int fLineStyle
histogram line style.
virtual void CheckIntervals(std::vector< double > &intervals, int sort)
Check intervals: remove values below 0 or above 1.
int fMeanMarkerStyle
Holds option for mean marker style.
virtual void Draw()
Draw distribution into the active pad.
void GetNonzeroBinDensityMassVector(std::vector< std::pair< double, double > > &bin_dens_mass, int sort=-1)
Fill vector with values and integrals of nonzero bins sorted by value.
virtual void DrawBands(const std::string &)
Draw bands.
virtual void CopyOptions(const BCHistogramBase &other)
Copy options from.
TH1 * fHistogram
The histogram.
bool fDrawStandardDeviation
Flag for drawing standard deviation.
std::vector< double > fIntervals
intervals to draw.
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...
std::vector< double > fLocalMode
Local mode.
void Smooth(int n=-1)
Applying ROOT smoothing to histogram, and renormalize.
BCHistogramBase(const TH1 *const hist=0, int dimension=0)
The default constructor.
virtual ~BCHistogramBase()
The default destructor.
BCHColorScheme
An enumerator for the color schemes.
A base class for drawing histograms in BAT style.
virtual void SetHistogram(const TH1 *const hist)
Sets the histogram.
int fLineColor
histogram line color.
virtual void SetColorScheme(BCHColorScheme scheme)
Sets the color scheme.
void AddBandColor(int c)
Add band color.
virtual void DrawGlobalMode()
Draw global mode.
unsigned GetDimension() const
virtual std::vector< double > DefaultIntervals(int nbands=-1)
Return default intervals.
int fGlobalModeMarkerStyle
Holds option for global-mode marker style.
bool fBandOvercoverage
flag for whether bands should overcover.
bool fGridx
Flag for drawing of grid on x axis.
std::vector< TObject * > fROOTObjects
Storage for plot objects.
virtual void DrawLocalMode()
Draw global mode.
int fLineWidth
histogram line width.
virtual double ResizeLegend()
Resize legend and set it for placement at the top of the pad.
int GetLineColor() const
virtual bool Valid() const
Whether histogram has been set and filled.
int GetLineStyle() const
int GetMarkerColor() const
Returns the marker colors (used for mean, median, and mode.
bool fDrawMean
Flag for drawing mean.
std::vector< TLegendEntry * > fExtraLegendEntries
Storage for unused legend entries (for use with multicolumn legends).
bool fDrawGlobalMode
Flag for drawing global mode.
std::vector< double > fGlobalMode
Global mode.
int fLocalModeMarkerStyle
Holds option for local-mode marker style.
bool fDrawLegend
Flag for drawing legend.
unsigned fNLegendColumns
number of columns to be set for legend.
bool fDrawLocalModeArrows
Flag for drawing local mode arrows.
bool fDrawLocalMode
Flag for drawing local mode.
unsigned fNSmooth
Number of times to smooth histogram using ROOT&#39;s smooth function.
void SetMarkerColor(int c)
Set marker color (used for mean, median, and mode).
int fDimension
Dimension of histogram.
virtual void DrawLegend()
Resize histogram and draw legend.
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.
bool fLogy
Flag for controlling log plotting of y axis.
TLegend fLegend
Legend.
bool fDrawStats
Flag for drawing stats box.