4Bool_t PlottingUtils::preferences_set_ = kFALSE;
5Width_t PlottingUtils::line_width_ = 2;
6TString PlottingUtils::plots_base_dir_ =
"plots";
10 while (d.Length() > 0 && d[d.Length() - 1] ==
'/')
17void PlottingUtils::WarnIfNotConfigured(
const TString method_name) {
18 if (!preferences_set_)
19 std::cout <<
"WARNING: " << method_name
20 <<
" called before SetStylePreferences()." << std::endl;
24 save_format_ = save_format;
25 preferences_set_ = kTRUE;
28 gStyle->SetOptStat(0);
30 gStyle->SetPadLeftMargin(0.15);
31 gStyle->SetPadRightMargin(0.1);
32 gStyle->SetPadTopMargin(0.12);
33 gStyle->SetPadBottomMargin(0.15);
34 gStyle->SetTitleSize(0.06,
"XY");
35 gStyle->SetLabelSize(0.06,
"XY");
36 gStyle->SetLegendFont(132);
37 gStyle->SetTitleOffset(1.2,
"X");
38 gStyle->SetTitleOffset(1.2,
"Y");
39 gStyle->SetTextFont(42);
40 gStyle->SetHistLineWidth(line_width_);
41 gStyle->SetLineWidth(line_width_);
42 gStyle->SetPadGridX(1);
43 gStyle->SetPadGridY(1);
44 gStyle->SetGridStyle(3);
45 gStyle->SetGridWidth(line_width_);
46 gStyle->SetGridColor(kGray);
47 gStyle->SetPadTickX(1);
48 gStyle->SetPadTickY(1);
54 const TString title) {
55 WarnIfNotConfigured(
"ConfigureGraph");
56 graph->SetLineColor(color);
57 graph->SetTitle(title);
58 graph->GetXaxis()->SetTitleSize(0.06);
59 graph->GetYaxis()->SetTitleSize(0.06);
60 graph->GetXaxis()->SetLabelSize(0.06);
61 graph->GetYaxis()->SetLabelSize(0.06);
62 graph->GetXaxis()->SetTitleOffset(1.2);
63 graph->GetYaxis()->SetTitleOffset(1.2);
64 graph->GetXaxis()->SetNdivisions(506);
65 graph->SetLineWidth(line_width_);
69 const TString title) {
70 WarnIfNotConfigured(
"ConfigureGraph");
71 graph->SetLineColor(color);
72 graph->SetTitle(title);
73 graph->GetXaxis()->SetTitleSize(0.06);
74 graph->GetYaxis()->SetTitleSize(0.06);
75 graph->GetXaxis()->SetLabelSize(0.06);
76 graph->GetYaxis()->SetLabelSize(0.06);
77 graph->GetXaxis()->SetTitleOffset(1.2);
78 graph->GetYaxis()->SetTitleOffset(1.2);
79 graph->GetXaxis()->SetNdivisions(506);
80 graph->SetMarkerStyle(20);
81 graph->SetMarkerSize(1.2);
82 graph->SetMarkerColor(color);
83 graph->SetLineWidth(line_width_);
87 const TString title) {
90 WarnIfNotConfigured(
"ConfigureHistogram");
92 hist->SetLineColor(color);
93 hist->SetTitle(title);
94 hist->SetLineWidth(line_width_);
95 hist->SetFillStyle(0);
96 hist->GetYaxis()->SetMoreLogLabels(kFALSE);
97 hist->GetYaxis()->SetNoExponent(kFALSE);
98 hist->GetXaxis()->SetNoExponent(kTRUE);
99 hist->GetYaxis()->SetNdivisions(50109);
100 hist->GetXaxis()->SetNdivisions(505);
101 hist->GetXaxis()->SetTitleSize(0.06);
102 hist->GetYaxis()->SetTitleSize(0.06);
103 hist->GetXaxis()->SetLabelSize(0.06);
104 hist->GetYaxis()->SetLabelSize(0.06);
105 hist->GetXaxis()->SetTitleOffset(1.2);
106 hist->GetYaxis()->SetTitleOffset(1.2);
110 const TString title) {
115 WarnIfNotConfigured(
"Configure2DHistogram");
117 hist->SetTitle(title);
118 hist->GetYaxis()->SetMoreLogLabels(kFALSE);
119 hist->GetYaxis()->SetNoExponent(kFALSE);
120 hist->GetXaxis()->SetTitleSize(0.06);
121 hist->GetYaxis()->SetTitleSize(0.06);
122 hist->GetXaxis()->SetLabelSize(0.06);
123 hist->GetYaxis()->SetLabelSize(0.06);
124 hist->GetXaxis()->SetTitleOffset(1.2);
125 hist->GetYaxis()->SetTitleOffset(1);
126 hist->GetXaxis()->SetNdivisions(506);
127 hist->GetYaxis()->SetNdivisions(506);
129 canvas->SetLogz(kTRUE);
130 canvas->SetRightMargin(0.15);
134 const TString title) {
143 const TString title) {
152 const TString title) {
163 WarnIfNotConfigured(
"GetConfiguredCanvas");
164 TCanvas *canvas =
new TCanvas(
GetRandomName(),
"", 1200, 800);
168 canvas->SetLogy(logy);
170 canvas->SetTicks(1, 1);
171 gPad->SetTicks(1, 1);
177 TString output_subdirectory,
179 WarnIfNotConfigured(
"SaveFigure");
180 canvas->SetLogy(kFALSE);
185 TString output_filename = output_name + extension;
189 output_subdirectory ==
"" ? base : base +
"/" + output_subdirectory;
191 if (gSystem->AccessPathName(full_dir)) {
192 gSystem->mkdir(full_dir, kTRUE);
195 TString prefix = full_dir +
"/";
198 canvas->Print(prefix + output_filename);
201 TList *primitives = canvas->GetListOfPrimitives();
202 Int_t size = primitives->GetSize();
204 for (Int_t i = 0; i < size; i++) {
205 TObject *
object = primitives->At(i);
206 if (object->InheritsFrom(TH2::Class())) {
207 std::cout << std::endl;
208 std::cerr <<
"ERROR: Used PlotSaveOptions::kLOG for 2D histogram."
211 <<
"This option is exclusive to 1D histograms/graphs because it refers to the y axis."
213 std::cout <<
"Use PlotSaveOptions::kLINEAR." << std::endl;
215 <<
"The z axis is already log by default if you used PlottingUtils::Configure2DHistogram()."
217 std::cout <<
"Plot " << prefix +
"log_" + output_filename
218 <<
" was not saved." << std::endl;
223 canvas->SetLogy(kTRUE);
226 canvas->Print(prefix +
"log_" + output_filename);
228 canvas->SetLogy(kFALSE);
235 return {kRed + 1, kBlue + 1, kGreen + 2, kOrange + 1, kMagenta + 1,
236 kCyan + 2, kViolet + 1, kSpring - 1, kPink + 1, kTeal + 2,
237 kAzure + 2, kYellow + 1, kOrange - 3, kMagenta - 3, kCyan - 6,
238 kRed - 4, kBlue - 4, kGreen - 6, kViolet - 4, kSpring + 5,
239 kPink - 3, kTeal - 5, kAzure - 3, kOrange + 7};
244 TLegend *leg =
new TLegend(x1, y1, x2, y2);
245 leg->SetBorderSize(1);
246 leg->SetFillColor(kWhite);
247 leg->SetTextSize(30);
248 leg->SetTextFont(43);
256 TLatex *text =
new TLatex(x, y, label);
258 text->SetTextSize(30);
259 text->SetTextAlign(33);
260 text->SetTextFont(43);
261 text->SetTextAngle(angle);
268 static TRandom3 generator(0);
269 Double_t number = generator.Rndm();
270 TString name = Form(
"name%.7f", number);
275 TH1 *hist, TGraph *total_graph,
276 const std::vector<TGraph *> &component_graphs, Float_t fit_range_low,
277 Float_t fit_range_high,
const TString &output_name,
278 const TString &output_subdirectory,
const TString &label, Bool_t logy) {
281 TPad *pad1 =
new TPad(
"pad1",
"pad1", 0, 0.3, 1, 1.0);
282 TPad *pad2 =
new TPad(
"pad2",
"pad2", 0, 0, 1, 0.3);
283 pad1->SetBottomMargin(0.04);
286 pad1->SetTopMargin(0.12);
287 pad2->SetTopMargin(0.04);
288 pad2->SetBottomMargin(0.35);
295 Float_t min_hist_value = 0.9 * fit_range_low;
296 Float_t max_hist_value = 1.1 * fit_range_high;
298 hist->GetXaxis()->SetRangeUser(min_hist_value, max_hist_value);
299 hist->GetXaxis()->SetLabelSize(0);
300 hist->GetXaxis()->SetTitleSize(0);
301 hist->SetLineColor(kViolet);
302 hist->GetYaxis()->SetTitleOffset(1);
303 hist->SetLineWidth(line_width_);
308 total_graph->Draw(
"L same");
309 for (std::size_t i = 0; i < component_graphs.size(); i++) {
310 if (component_graphs[i])
311 component_graphs[i]->Draw(
"L same");
316 Int_t nbins = hist->GetNbinsX();
317 TGraph *residuals =
new TGraph();
318 Int_t point_counter = 0;
319 for (Int_t i = 1; i <= nbins; i++) {
320 Double_t x = hist->GetBinCenter(i);
321 if (x < fit_range_low || x > fit_range_high)
323 Double_t data = hist->GetBinContent(i);
324 Double_t fit_val = total_graph ? total_graph->Eval(x) : 0.0;
325 Double_t error = hist->GetBinError(i);
327 if (error > 0 && data > 0) {
328 Double_t pull = (data - fit_val) / error;
329 residuals->SetPoint(point_counter, x, pull);
334 residuals->SetMarkerStyle(20);
335 residuals->SetMarkerSize(0.8);
336 residuals->SetMarkerColor(kAzure);
337 residuals->SetLineColor(kAzure);
338 residuals->SetTitle(
"");
339 Double_t actual_min =
340 hist->GetXaxis()->GetBinLowEdge(hist->GetXaxis()->GetFirst());
341 Double_t actual_max =
342 hist->GetXaxis()->GetBinUpEdge(hist->GetXaxis()->GetLast());
343 residuals->GetXaxis()->SetLimits(actual_min, actual_max);
344 residuals->GetYaxis()->SetTitle(
"#delta/#sigma");
345 residuals->GetXaxis()->SetTitle(hist->GetXaxis()->GetTitle());
346 residuals->GetXaxis()->SetTitleSize(0.13);
347 residuals->GetYaxis()->SetTitleSize(0.13);
348 residuals->GetXaxis()->SetLabelSize(0.12);
349 residuals->GetYaxis()->SetLabelSize(0.12);
350 residuals->GetXaxis()->SetTitleOffset(1.0);
351 residuals->GetYaxis()->SetTitleOffset(0.3);
352 residuals->GetYaxis()->SetNdivisions(505);
353 residuals->GetXaxis()->SetNdivisions(510);
354 residuals->GetYaxis()->CenterTitle(kTRUE);
355 residuals->GetYaxis()->SetRangeUser(-5.5, 5.5);
356 residuals->Draw(
"AP");
358 TF1 *zero_line =
new TF1(
"zero_line",
"0", actual_min, actual_max);
359 zero_line->SetLineColor(kBlack);
360 zero_line->SetLineStyle(2);
361 zero_line->SetLineWidth(line_width_);
362 zero_line->Draw(
"same");
364 TF1 *plus3_line =
new TF1(
"plus3_line",
"3", actual_min, actual_max);
365 plus3_line->SetLineColor(kGray + 2);
366 plus3_line->SetLineStyle(3);
367 plus3_line->SetLineWidth(line_width_);
368 plus3_line->Draw(
"same");
370 TF1 *minus3_line =
new TF1(
"minus3_line",
"-3", actual_min, actual_max);
371 minus3_line->SetLineColor(kGray + 2);
372 minus3_line->SetLineStyle(3);
373 minus3_line->SetLineWidth(line_width_);
374 minus3_line->Draw(
"same");
378 if (label.Length() > 0) {
384 SaveFigure(canvas, output_name, output_subdirectory, save_opts);
386 PlotPullHistogram(residuals, output_name, output_subdirectory);
388 gROOT->GetListOfCanvases()->Remove(canvas);
389 canvas->SetBatch(kTRUE);
397void PlottingUtils::PlotPullHistogram(TGraph *residuals,
398 const TString &output_name,
399 const TString &output_subdirectory) {
400 Int_t npoints = residuals->GetN();
405 new TH1D(
"pull_hist",
";#delta/#sigma;Counts", 82, -5.5, 5.5);
407 Double_t *y = residuals->GetY();
408 for (Int_t i = 0; i < npoints; i++) {
409 pull_hist->Fill(y[i]);
412 TH1D *gauss_ref =
new TH1D(
"gauss_ref",
"", 82, -5.5, 5.5);
413 for (Int_t i = 1; i <= gauss_ref->GetNbinsX(); i++) {
414 Double_t lo = gauss_ref->GetBinLowEdge(i);
415 Double_t hi = lo + gauss_ref->GetBinWidth(i);
416 gauss_ref->SetBinContent(i, npoints * (TMath::Freq(hi) - TMath::Freq(lo)));
419 Double_t ks_pvalue = pull_hist->KolmogorovTest(gauss_ref);
423 AddText(TString::Format(
"KS p = %.3f", ks_pvalue), 0.85, 0.85);
425 SaveFigure(hist_canvas,
"residuals_" + output_name,
433void PlottingUtils::SetTurboPalette() {
434 Int_t N_COLORS = 255;
436 std::vector<Double_t> stops(N_COLORS);
437 std::vector<Double_t> reds(N_COLORS);
438 std::vector<Double_t> greens(N_COLORS);
439 std::vector<Double_t> blues(N_COLORS);
441 for (Int_t i = 0; i < N_COLORS; ++i) {
442 Double_t x = Double_t(i) / Double_t(N_COLORS - 1);
444 Double_t r = 0.13572138 + 4.61539260 * x - 42.66032258 * x * x +
445 132.13108234 * x * x * x - 152.94239396 * x * x * x * x +
446 59.28637943 * x * x * x * x * x;
448 Double_t g = 0.09140261 + 2.19418839 * x + 4.84296658 * x * x -
449 14.18503333 * x * x * x + 4.27729857 * x * x * x * x +
450 2.82956604 * x * x * x * x * x;
452 Double_t b = 0.10667330 + 12.64194608 * x - 60.58204836 * x * x +
453 110.36276771 * x * x * x - 89.90310912 * x * x * x * x +
454 27.34824973 * x * x * x * x * x;
457 reds[i] = std::max(0.0, std::min(1.0, r));
458 greens[i] = std::max(0.0, std::min(1.0, g));
459 blues[i] = std::max(0.0, std::min(1.0, b));
463 TColor::CreateGradientColorTable(N_COLORS, stops.data(), reds.data(),
464 greens.data(), blues.data(), N_COLORS);
466 std::vector<Int_t> palette(N_COLORS);
467 for (Int_t i = 0; i < N_COLORS; ++i) {
468 palette[i] = firstColor + i;
471 gStyle->SetNumberContours(N_COLORS);
472 gStyle->SetPalette(N_COLORS, palette.data());
PlotSaveOptions
Which axis scalings SaveFigure() should write out.
@ kLOG
Logarithmic y only, written with a log_ filename prefix.
PlotSaveFormat
Output file format for saved figures.
@ kPNG
PNG raster output; line width 2.
static TLatex * AddText(const TString label, Double_t x=0.9, Double_t y=0.85, Double_t angle=0)
Create and draw a text annotation on the current pad.
static void ConfigureAndDrawGraph(TGraph *graph, Int_t color, const TString title="")
ConfigureGraph() followed by Draw().
static TLegend * AddLegend(Double_t x1=0.7, Double_t x2=0.9, Double_t y1=0.7, Double_t y2=0.9)
Create, style and draw a legend on the current pad.
static void SaveFigure(TCanvas *canvas, TString output_filename, TString output_subdirectory="", PlotSaveOptions save_options=PlotSaveOptions::kBOTH)
Write a canvas to disk under the configured plots base directory.
static void SetPlotsBaseDir(const TString &dir)
Set the base directory that saved figures are written under.
static TString GetRandomName()
Generate a name unlikely to collide with existing ROOT objects.
static void ConfigureGraph(TGraph *graph, Int_t color, const TString title="")
Apply the house style to a graph without drawing it.
static void SetStylePreferences(PlotSaveFormat save_format=PlotSaveFormat::kPNG)
Install the global ROOT style and choose the output format.
static void Configure2DHistogram(TH2 *hist, TCanvas *canvas, const TString title="")
Apply the house style to a 2-D histogram and its canvas.
static void ConfigureAndDrawHistogram(TH1 *hist, Int_t color, const TString title="")
ConfigureHistogram() followed by Draw("HIST").
static void ConfigureHistogram(TH1 *hist, Int_t color, const TString title="")
Apply the house style to a 1-D histogram without drawing it.
static TCanvas * GetConfiguredCanvas(Bool_t logy=kFALSE)
Create a 1200x800 canvas with grid and ticks already set up.
static void PlotFitWithResiduals(TH1 *hist, TGraph *total_graph, const std::vector< TGraph * > &component_graphs, Float_t fit_range_low, Float_t fit_range_high, const TString &output_name, const TString &output_subdirectory="fits", const TString &label="", Bool_t logy=kTRUE)
Draw a fit over its data with a residual panel and save it.
static std::vector< Int_t > GetDefaultColors()
A palette of visually distinct ROOT colour indices.
static void ConfigureAndDraw2DHistogram(TH2 *hist, TCanvas *canvas, const TString title="")
Configure2DHistogram() followed by Draw("COLZ").
static TString GetPlotsBaseDir()
Current base directory for saved figures, without trailing slash.