1 #ifndef Core_Plotting_h
2 #define Core_Plotting_h
26 #include "TMultiGraph.h"
43 std::vector<TPad*>
OnePad();
62 std::vector<TPad*>
TwoPadSplit(
double split_point,
double gap_low,
91 std::vector<TH1*>
CreateAxisHists(
unsigned n, TH1* src,
double xmin = 0,
121 std::vector<TH1*>
CreateAxisHists(
unsigned n, TGraph* src,
bool at_limits);
157 TH1*
MakeRatioHist(TH1* num, TH1* den,
bool num_err,
bool den_err);
172 TGraph
TGraphFromTree(TTree* tree, TString
const& xvar, TString
const& yvar,
173 TString
const& selection =
"");
188 TGraph2D
TGraph2DFromTree(TTree* tree, TString
const& xvar, TString
const& yvar,
189 TString
const& zvar, TString
const& selection =
"");
239 TH1* lower, TString y_title,
bool y_centered,
240 float y_min,
float y_max);
261 bool y_centered,
float y_min,
float y_max);
275 void StandardAxes(TAxis* xaxis, TAxis* yaxis, TString var, TString units);
289 void UnitAxes(TAxis* xaxis, TAxis* yaxis, TString var, TString units);
310 TLegend*
PositionedLegend(
double width,
double height,
int pos,
double offset);
345 void DrawTitle(TPad* pad, TString text,
int align);
372 void DrawCMSLogo(TPad* pad, TString cmsText, TString extraText,
int iPosX,
373 float relPosX,
float relPosY,
float relExtraDY);
383 void DrawCMSLogo(TPad* pad, TString cmsText, TString extraText,
int iPosX);
405 double GetPadYMax(TPad* pad,
double x_min,
double x_max);
427 void FixTopRange(TPad *pad,
double fix_y,
double fraction);
460 TPad* pad =
new TPad(
"pad",
"pad", 0., 0., 1., 1.);
463 std::vector<TPad*> result;
464 result.push_back(pad);
468 std::vector<TPad*>
TwoPadSplit(
double split_point,
double gap_low,
470 TPad* upper =
new TPad(
"upper",
"upper", 0., 0., 1., 1.);
471 upper->SetBottomMargin(split_point + gap_high);
472 upper->SetFillStyle(4000);
474 TPad* lower =
new TPad(
"lower",
"lower", 0., 0., 1., 1.);
475 lower->SetTopMargin(1 - split_point + gap_low);
476 lower->SetFillStyle(4000);
479 std::vector<TPad*> result;
480 result.push_back(upper);
481 result.push_back(lower);
486 TH1 *res =
reinterpret_cast<TH1F*
>(src->Clone());
489 res->SetAxisRange(xmin, xmax);
496 std::vector<TH1*> result;
497 for (
unsigned i = 0; i < n; ++i) {
504 TVirtualPad *backup = gPad;
508 TH1 * result = (TH1*)src->GetHistogram()->Clone();
514 src->GetPoint(0, x, y);
517 for (
int i = 1; i < src->GetN(); ++i) {
518 src->GetPoint(i, x, y);
519 if (x < min) min = x;
520 if (x > max) max = x;
522 result->GetXaxis()->SetLimits(min, max);
529 std::vector<TH1*> result;
530 for (
unsigned i = 0; i < n; ++i) {
537 TList* pad_obs = pad->GetListOfPrimitives();
538 if (!pad_obs)
return NULL;
542 while ((obj = next())) {
543 if (obj->InheritsFrom(TH1::Class())) {
544 hobj =
reinterpret_cast<TH1*
>(obj);
547 if (obj->InheritsFrom(TMultiGraph::Class())) {
548 TMultiGraph *mg =
reinterpret_cast<TMultiGraph*
>(obj);
549 if (mg)
return mg->GetHistogram();
551 if (obj->InheritsFrom(TGraph::Class())) {
552 TGraph *g =
reinterpret_cast<TGraph*
>(obj);
553 if (g)
return g->GetHistogram();
555 if (obj->InheritsFrom(THStack::Class())) {
556 THStack *hs =
reinterpret_cast<THStack*
>(obj);
557 if (hs)
return hs->GetHistogram();
568 TH1* result =
reinterpret_cast<TH1*
>(num->Clone());
570 for (
int i = 1; i <= result->GetNbinsX(); ++i) result->SetBinError(i, 0.);
572 TH1* den_fix =
reinterpret_cast<TH1*
>(den->Clone());
574 for (
int i = 1; i <= den_fix->GetNbinsX(); ++i) den_fix->SetBinError(i, 0.);
576 result->Divide(den_fix);
582 TString
const& selection) {
583 tree->Draw(xvar+
":"+yvar, selection,
"goff");
584 TGraph gr(tree->GetSelectedRows(), tree->GetV1(), tree->GetV2());
589 TString
const& zvar, TString
const& selection) {
590 tree->Draw(xvar+
":"+yvar+
":"+zvar, selection,
"goff");
591 TGraph2D gr(tree->GetSelectedRows(), tree->GetV1(), tree->GetV2(), tree->GetV3());
596 unsigned n = gr->GetN();
600 for (
unsigned i = 0; i < n; ++i) {
601 gr->GetPoint(i, x, y);
602 if (y < min) min = y;
604 for (
unsigned i = 0; i < n; ++i) {
605 gr->GetPoint(i, x, y);
607 gr->SetPoint(i, x, y);
615 TColor* adapt = gROOT->GetColor(color);
616 int new_idx = gROOT->GetListOfColors()->GetSize() + 1;
617 TColor* trans =
new TColor(new_idx, adapt->GetRed(), adapt->GetGreen(),
618 adapt->GetBlue(),
"", alpha);
619 trans->SetName(Form(
"userColor%i", new_idx));
624 TString y_title,
bool y_centered,
float y_min,
633 TH1* lower, TString y_title,
bool y_centered,
634 float y_min,
float y_max) {
635 upper->GetXaxis()->SetTitle(
"");
636 upper->GetXaxis()->SetLabelSize(0);
637 double upper_h = 1. - pads[0]->GetTopMargin() - pads[0]->GetBottomMargin();
638 double lower_h = 1. - pads[1]->GetTopMargin() - pads[1]->GetBottomMargin();
639 lower->GetYaxis()->SetTickLength(gStyle->GetTickLength() *
640 (upper_h / lower_h));
641 pads[1]->SetTickx(1);
642 pads[1]->SetTicky(1);
643 lower->GetYaxis()->SetTitle(y_title);
644 lower->GetYaxis()->CenterTitle(y_centered);
646 lower->SetMinimum(y_min);
647 lower->SetMaximum(y_max);
651 void StandardAxes(TAxis* xaxis, TAxis* yaxis, TString var, TString units) {
652 double width = xaxis->GetBinWidth(1);
653 TString w_label = TString::Format(
"%.1f", width);
655 xaxis->SetTitle(var);
656 yaxis->SetTitle(
"Events / " + w_label);
658 xaxis->SetTitle(var +
" (" + units +
")");
659 yaxis->SetTitle(
"Events / " + w_label +
" " + units);
664 void UnitAxes(TAxis* xaxis, TAxis* yaxis, TString var, TString units) {
665 xaxis->SetTitle(var +
" (" + units +
")");
666 yaxis->SetTitle(
"dN/d"+ var +
" (1/" + units +
")");
673 double l = gPad->GetLeftMargin();
674 double t = gPad->GetTopMargin();
675 double b = gPad->GetBottomMargin();
676 double r = gPad->GetRightMargin();
679 leg =
new TLegend(l + o, 1 - t - o - h, l + o + w, 1 - t - o,
"",
"NBNDC");
682 double c = l + 0.5 * (1 - l - r);
683 leg =
new TLegend(c - 0.5 * w, 1 - t - o - h, c + 0.5 * w, 1 - t - o,
"",
687 leg =
new TLegend(1 - r - o - w, 1 - t - o - h, 1 - r - o, 1 - t - o,
"",
691 leg =
new TLegend(l + o, b + o, l + o + w, b + o + h,
"",
"NBNDC");
694 double c = l + 0.5 * (1 - l - r);
695 leg =
new TLegend(c - 0.5 * w, b + o, c + 0.5 * w, b + o + h,
"",
699 leg =
new TLegend(1 - r - o - w, b + o, 1 - r - o, b + o + h,
"",
707 std::cout <<
"pad: " << pad <<
"\n";
708 double xmin = axis->GetXaxis()->GetXmin();
709 double xmax = axis->GetXaxis()->GetXmax();
710 return line->DrawLine(xmin, yval, xmax, yval);
714 TVirtualPad *pad_backup = gPad;
716 float t = pad->GetTopMargin();
717 float l = pad->GetLeftMargin();
718 float r = pad->GetRightMargin();
720 float pad_ratio = (
static_cast<float>(pad->GetWh()) * pad->GetAbsHNDC()) /
721 (
static_cast<float>(pad->GetWw()) * pad->GetAbsWNDC());
722 if (pad_ratio < 1.) pad_ratio = 1.;
724 float textSize = 0.6;
725 float textOffset = 0.2;
729 latex.SetTextAngle(0);
730 latex.SetTextColor(kBlack);
732 latex.SetTextFont(42);
733 latex.SetTextSize(textSize * t * pad_ratio);
734 double y_off = 1 - t + textOffset * t;
735 if (align == 1) latex.SetTextAlign(11);
736 if (align == 1) latex.DrawLatex(l, y_off, text);
737 if (align == 2) latex.SetTextAlign(21);
738 if (align == 2) latex.DrawLatex(l + (1 - l - r) * 0.5, y_off, text);
739 if (align == 3) latex.SetTextAlign(31);
740 if (align == 3) latex.DrawLatex(1 - r, y_off, text);
744 void DrawCMSLogo(TPad* pad, TString cmsText, TString extraText,
int iPosX,
745 float relPosX,
float relPosY,
float relExtraDY) {
746 TVirtualPad *pad_backup = gPad;
748 float cmsTextFont = 61;
750 bool writeExtraText = extraText.Length() > 0;
751 float extraTextFont = 52;
755 float lumiTextOffset = 0.2;
756 float cmsTextSize = 0.8;
760 float extraOverCmsTextSize = 0.76;
762 TString lumi_13TeV =
"20.1 fb^{-1}";
763 TString lumi_8TeV =
"19.7 fb^{-1}";
764 TString lumi_7TeV =
"5.1 fb^{-1}";
766 bool outOfFrame =
false;
767 if (iPosX / 10 == 0) {
772 if (iPosX / 10 == 0) alignX_ = 1;
773 if (iPosX == 0) alignX_ = 1;
774 if (iPosX == 0) alignY_ = 1;
775 if (iPosX / 10 == 1) alignX_ = 1;
776 if (iPosX / 10 == 2) alignX_ = 2;
777 if (iPosX / 10 == 3) alignX_ = 3;
778 if (iPosX == 0) relPosX = 0.14;
779 int align_ = 10 * alignX_ + alignY_;
781 float l = pad->GetLeftMargin();
782 float t = pad->GetTopMargin();
783 float r = pad->GetRightMargin();
784 float b = pad->GetBottomMargin();
788 latex.SetTextAngle(0);
789 latex.SetTextColor(kBlack);
791 float extraTextSize = extraOverCmsTextSize * cmsTextSize;
792 float pad_ratio = (
static_cast<float>(pad->GetWh()) * pad->GetAbsHNDC()) /
793 (
static_cast<float>(pad->GetWw()) * pad->GetAbsWNDC());
794 if (pad_ratio < 1.) pad_ratio = 1.;
798 latex.SetTextFont(cmsTextFont);
799 latex.SetTextAlign(11);
800 latex.SetTextSize(cmsTextSize * t * pad_ratio);
801 latex.DrawLatex(l, 1 - t + lumiTextOffset * t, cmsText);
805 if (iPosX % 10 <= 1) {
806 posX_ = l + relPosX * (1 - l - r);
807 }
else if (iPosX % 10 == 2) {
808 posX_ = l + 0.5 * (1 - l - r);
809 }
else if (iPosX % 10 == 3) {
810 posX_ = 1 - r - relPosX * (1 - l - r);
812 float posY_ = 1 - t - relPosY * (1 - t - b);
814 latex.SetTextFont(cmsTextFont);
815 latex.SetTextSize(cmsTextSize * t * pad_ratio);
816 latex.SetTextAlign(align_);
817 latex.DrawLatex(posX_, posY_, cmsText);
818 if (writeExtraText) {
819 latex.SetTextFont(extraTextFont);
820 latex.SetTextAlign(align_);
821 latex.SetTextSize(extraTextSize * t * pad_ratio);
822 latex.DrawLatex(posX_, posY_ - relExtraDY * cmsTextSize * t, extraText);
824 }
else if (writeExtraText) {
826 posX_ = l + relPosX * (1 - l - r);
827 posY_ = 1 - t + lumiTextOffset * t;
829 latex.SetTextFont(extraTextFont);
830 latex.SetTextSize(extraTextSize * t * pad_ratio);
831 latex.SetTextAlign(align_);
832 latex.DrawLatex(posX_, posY_, extraText);
837 void DrawCMSLogo(TPad* pad, TString cmsText, TString extraText,
int iPosX) {
838 DrawCMSLogo(pad, cmsText, extraText, iPosX, 0.045, 0.035, 1.2);
845 TList *pad_obs = pad->GetListOfPrimitives();
846 if (!pad_obs)
return 0.;
848 double h_max = -99999;
850 while ((obj = next())) {
851 if (obj->InheritsFrom(TH1::Class())) {
852 TH1 *hobj =
reinterpret_cast<TH1*
>(obj);
853 for (
int j = 1; j < hobj->GetNbinsX(); ++j) {
854 if (hobj->GetBinLowEdge(j) + hobj->GetBinWidth(j) < x_min ||
855 hobj->GetBinLowEdge(j) > x_max)
857 if (hobj->GetBinContent(j) + hobj->GetBinError(j) > h_max) {
858 h_max = hobj->GetBinContent(j) + hobj->GetBinError(j);
862 if (obj->InheritsFrom(TGraph::Class())) {
863 TGraph *gobj =
reinterpret_cast<TGraph*
>(obj);
864 unsigned n = gobj->GetN();
867 for (
unsigned k = 0; k < n; ++k) {
868 gobj->GetPoint(k, x, y);
869 if (x < x_min || x > x_max)
continue;
870 if (y > h_max) h_max = y;
878 TList *pad_obs = pad->GetListOfPrimitives();
879 if (!pad_obs)
return 0.;
880 double xmin =
GetAxisHist(pad)->GetXaxis()->GetXmin();
881 double xmax =
GetAxisHist(pad)->GetXaxis()->GetXmax();
887 double ymin = hobj->GetMinimum();
888 hobj->SetMaximum((fix_y - fraction * ymin) / (1. - fraction));
889 if (gPad->GetLogy()) {
892 <<
"Can't adjust log-scale y-axis range if the minimum is zero!\n";
896 (std::log10(fix_y) - fraction * std::log10(ymin)) / (1 - fraction);
897 max = std::pow(10, max);
898 hobj->SetMaximum(max);
905 double p_x1 = box->GetX1();
906 double p_x2 = box->GetX2();
907 double p_y1 = box->GetY1();
911 double f_x1 = (p_x1 - pad->GetLeftMargin()) /
912 (1. - pad->GetLeftMargin() - pad->GetRightMargin());
913 double f_x2 = (p_x2 - pad->GetLeftMargin()) /
914 (1. - pad->GetLeftMargin() - pad->GetRightMargin());
915 double f_y1 = (p_y1 - pad->GetBottomMargin()) /
916 (1. - pad->GetTopMargin() - pad->GetBottomMargin());
921 double xmin = hobj->GetBinLowEdge(hobj->GetXaxis()->GetFirst());
922 double xmax = hobj->GetBinLowEdge(hobj->GetXaxis()->GetLast()+1);
923 double ymin = hobj->GetMinimum();
924 double ymax = hobj->GetMaximum();
927 double a_x1 = xmin + (xmax - xmin) * f_x1;
928 double a_x2 = xmin + (xmax - xmin) * f_x2;
934 double f_max_h = (a_max_h - ymin) / (ymax - ymin);
935 if (gPad->GetLogy()) {
936 f_max_h = (log10(a_max_h) - log10(ymin)) / (log10(ymax) - log10(ymin));
939 if (f_y1 - f_max_h < frac) {
940 double f_target = 1. - (f_y1 - frac);
945 void FixOverlay() { gPad->GetFrame()->Draw(); gPad->RedrawAxis(); }
void FixBoxPadding(TPad *pad, TBox *box, double frac)
Modify the pad y-axis range to ensure there is at least a given gap between a particular TBox and the...
void DrawTitle(TPad *pad, TString text, int align)
Draw text in the top-margin region of a TPad.
void FixOverlay()
Just re-draws the axes on the current TPad.
void UnitAxes(TAxis *xaxis, TAxis *yaxis, TString var, TString units)
Sets standard x- and y-axis titles when histograms are drawn divided by bin width.
TH1 * MakeRatioHist(TH1 *num, TH1 *den, bool num_err, bool den_err)
Create a new histogram by dividing one by the other.
void FixTopRange(TPad *pad, double fix_y, double fraction)
Adjusts the y-axis maximum on the pad such that the specified y-value is positioned a fixed fraction ...
TLegend * PositionedLegend(double width, double height, int pos, double offset)
Create a legend with fixed height, width and positioning.
TGraph TGraphFromTree(TTree *tree, TString const &xvar, TString const &yvar, TString const &selection="")
Create a TGraph from entries in a TTree.
double GetPadYMax(TPad *pad, double x_min, double x_max)
Find the maximum value of all drawn objects in a given x-axis range.
void StandardAxes(TAxis *xaxis, TAxis *yaxis, TString var, TString units)
Sets standard x- and y-axis titles with given units.
std::vector< TPad * > OnePad()
Just creates a single pad filling the entire canvas.
TLine * DrawHorizontalLine(TPad *pad, TLine *line, double yval)
Use an existing TLine to draw a new horizontal line across the current frame.
std::vector< TH1 * > CreateAxisHists(unsigned n, TH1 *src, double xmin=0, double xmax=-1)
Create multiple axis TH1s from another TH1.
TH1 * GetAxisHist(TPad *pad)
Finds the TH1 used to draw the axes on a given TPad.
void SetupTwoPadSplitAsRatio(std::vector< TPad * > const &pads, TH1 *upper, TH1 *lower, TString y_title, bool y_centered, float y_min, float y_max)
Set a few style options for a two-pad setup used to show a data-MC comparison and ratio plot.
void DrawCMSLogo(TPad *pad, TString cmsText, TString extraText, int iPosX, float relPosX, float relPosY, float relExtraDY)
Draw the CMS logo and subtitle in the new style.
TH1 * CreateAxisHist(TH1 *src, double xmin=0, double xmax=-1)
Create an empty TH1 from another TH1 for drawing the axes.
int CreateTransparentColor(int color, float alpha)
Create a transparent version of a colour.
std::vector< TPad * > TwoPadSplit(double split_point, double gap_low, double gap_high)
Create two pads, split horizontally, on the current canvas split.
void ReZeroTGraph(TGraph *gr)
Shift all the graph y-values upwards such that there are no negative values and the minimum point is ...
TGraph2D TGraph2DFromTree(TTree *tree, TString const &xvar, TString const &yvar, TString const &zvar, TString const &selection="")
Create a TGraph2D from entries in a TTree.