diff --git a/codeHF/Compare.C b/codeHF/Compare.C index 0a64b549..f5953338 100644 --- a/codeHF/Compare.C +++ b/codeHF/Compare.C @@ -1,42 +1,21 @@ -// Comparison of AliPhysics and O2 histograms - -#include "utils_plot.h" +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. -// vectors of histogram specifications -using VecSpecHis = std::vector>; +// Comparison of AliPhysics and O2 histograms -// Add histogram specification in the vector. -void AddHistogram(VecSpecHis& vec, TString label, TString nameAli, TString nameO2, int rebin, bool logH, bool logR, TString proj = "x") -{ - vec.push_back(std::make_tuple(label, nameAli, nameO2, rebin, logH, logR, proj)); -} +#include "../exec/utilitiesValidation.h" -Int_t Compare(TString fileO2 = "AnalysisResults_O2.root", TString fileAli = "AnalysisResults_ALI.root", TString options = "", bool doRatio = false) +Int_t Compare(TString pathFileO2 = "AnalysisResults_O2.root", TString pathFileAli = "AnalysisResults_ALI.root", TString options = "", bool doRatio = false) { - gStyle->SetOptStat(0); - gStyle->SetPalette(0); - gStyle->SetCanvasColor(0); - gStyle->SetFrameFillColor(0); - - TFile* fO2 = new TFile(fileO2.Data()); - if (fO2->IsZombie()) { - printf("Failed to open file %s\n", fileO2.Data()); - return 1; - } - TFile* fAli = new TFile(fileAli.Data()); - if (fAli->IsZombie()) { - printf("Failed to open file %s\n", fileAli.Data()); - return 1; - } - TString pathListAli = "HFVertices/clistHFVertices"; - TList* lAli = nullptr; - fAli->GetObject(pathListAli.Data(), lAli); - if (!lAli) { - printf("Failed to load list %s from %s\n", pathListAli.Data(), fileAli.Data()); - return 1; - } - TString labelParticle = ""; // Histogram specification: axis label, AliPhysics name, O2Physics path/name, rebin, log scale histogram, log scale ratio, projection axis @@ -251,7 +230,7 @@ Int_t Compare(TString fileO2 = "AnalysisResults_O2.root", TString fileAli = "Ana AddHistogram(vecHisJetSubstructureMC, "#it{n}_{SD,gen}", "fHistJetNsd_Part", "jet-substructure-hf-mcp/h_jet_nsd", 1, 0, 0); // vector of specifications of vectors: name, VecSpecHis, pads X, pads Y - std::vector> vecSpecVecSpec; + VecSpecVecSpec vecSpecVecSpec; // Add vector specifications in the vector. if (options.Contains(" events ")) @@ -295,138 +274,5 @@ Int_t Compare(TString fileO2 = "AnalysisResults_O2.root", TString fileAli = "Ana if (options.Contains(" jets-substructure-mc ")) vecSpecVecSpec.push_back(std::make_tuple("jets-substructure-mc", vecHisJetSubstructureMC, 5, 3)); - // Histogram plot vertical margins - Float_t marginHigh = 0.05; - Float_t marginLow = 0.05; - bool logScaleH = false; - // Ratio plot vertical margins - Float_t marginRHigh = 0.05; - Float_t marginRLow = 0.05; - bool logScaleR = false; - Float_t yMin, yMax; - Int_t nAli, nO2, rebin; - - TH1F* hAli = nullptr; - TH1D* hO2 = nullptr; - TH1F* hRatio = nullptr; - TString labelAxis = ""; - TString nameHisAli = ""; - TString nameHisO2 = ""; - TString projAx = ""; - TCanvas* canHis = nullptr; - TCanvas* canRat = nullptr; - - // loop over lists - for (const auto& specVecSpec : vecSpecVecSpec) { - auto nameSpec = std::get<0>(specVecSpec); // list name - auto vecSpec = std::get<1>(specVecSpec); // list of histogram specs. - int nPadsX = std::get<2>(specVecSpec); // number of horizontal pads - int nPadsY = std::get<3>(specVecSpec); // number of vertical pads - Printf("\nProcessing histogram list: %s (%d)", nameSpec.Data(), (int)vecSpec.size()); - if (nPadsX * nPadsY < vecSpec.size()) { - Printf("Not enough pads (%d)", nPadsX * nPadsY); - return 1; - } - - canHis = new TCanvas(Form("canHis_%s", nameSpec.Data()), Form("Histos_%s", nameSpec.Data()), 3000, 1600); - SetCanvas(canHis, nPadsX, nPadsY); - if (doRatio) { - canRat = new TCanvas(Form("canRat_%s", nameSpec.Data()), Form("Ratios_%s", nameSpec.Data()), 3000, 1600); - SetCanvas(canRat, nPadsX, nPadsY); - } - - // loop over histograms - for (int index = 0; index < vecSpec.size(); index++) { - auto spec = vecSpec[index]; - labelAxis = std::get<0>(spec); - nameHisAli = std::get<1>(spec); - nameHisO2 = std::get<2>(spec); - rebin = std::get<3>(spec); - logScaleH = std::get<4>(spec); - logScaleR = std::get<5>(spec); - projAx = std::get<6>(spec); - - // Get AliPhysics histogram. - hAli = (TH1F*)lAli->FindObject(nameHisAli.Data()); - if (!hAli) { - printf("Failed to load %s from %s\n", nameHisAli.Data(), fileAli.Data()); - return 1; - } - - // Get O2 histogram. - auto oO2 = fO2->Get(nameHisO2.Data()); - if (!oO2) { - printf("Failed to load %s from %s\n", nameHisO2.Data(), fileO2.Data()); - return 1; - } - - if (oO2->InheritsFrom("TH3")) { - if (projAx == "x") { - hO2 = ((TH3D*)oO2)->ProjectionX(); - } else if (projAx == "y") { - hO2 = ((TH3D*)oO2)->ProjectionY(); - } - } else if (oO2->InheritsFrom("TH2")) { - if (projAx == "x") { - hO2 = ((TH2D*)oO2)->ProjectionX(); - } else if (projAx == "y") { - hO2 = ((TH2D*)oO2)->ProjectionY(); - } - } else { - hO2 = (TH1D*)oO2; - } - - Printf("%d (%s, %s): bins: %d, %d, ranges: %g-%g, %g-%g", - index, nameHisAli.Data(), nameHisO2.Data(), - hAli->GetNbinsX(), hO2->GetNbinsX(), - hAli->GetXaxis()->GetBinLowEdge(1), hAli->GetXaxis()->GetBinUpEdge(hAli->GetNbinsX()), - hO2->GetXaxis()->GetBinLowEdge(1), hO2->GetXaxis()->GetBinUpEdge(hO2->GetNbinsX())); - - nAli = hAli->GetEntries(); - nO2 = hO2->GetEntries(); - - // Histograms - auto padH = canHis->cd(index + 1); - hAli->Rebin(rebin); - hO2->Rebin(rebin); - hAli->SetLineColor(1); - hAli->SetLineWidth(2); - hO2->SetLineColor(2); - hO2->SetLineWidth(1); - hAli->SetTitle(Form("Entries: Ali: %d, O^{2}: %d;%s;Entries", nAli, nO2, labelAxis.Data())); - hAli->GetYaxis()->SetMaxDigits(3); - yMin = TMath::Min(hO2->GetMinimum(0), hAli->GetMinimum(0)); - yMax = TMath::Max(hO2->GetMaximum(), hAli->GetMaximum()); - SetHistogram(hAli, yMin, yMax, marginLow, marginHigh, logScaleH); - SetPad(padH, logScaleH); - hAli->Draw(); - hO2->Draw("same"); - TLegend* legend = new TLegend(0.8, 0.72, 1., 0.92); - legend->AddEntry(hAli, "Ali", "L"); - legend->AddEntry(hO2, "O^{2}", "L"); - legend->Draw(); - - // Ratio - if (doRatio) { - auto padR = canRat->cd(index + 1); - hRatio = (TH1F*)hO2->Clone(Form("hRatio%d", index)); - hRatio->Divide(hAli); - hRatio->SetTitle(Form("Entries ratio: %g;%s;O^{2}/Ali", (double)nO2 / (double)nAli, labelAxis.Data())); - yMin = hRatio->GetMinimum(0); - yMax = hRatio->GetMaximum(); - SetHistogram(hRatio, yMin, yMax, marginRLow, marginRHigh, logScaleR); - SetPad(padR, logScaleR); - hRatio->Draw(); - } - } - canHis->SaveAs(Form("comparison_histos_%s.pdf", nameSpec.Data())); - canHis->SaveAs(Form("comparison_histos_%s.png", nameSpec.Data())); - if (doRatio) { - canRat->SaveAs(Form("comparison_ratios_%s.pdf", nameSpec.Data())); - canRat->SaveAs(Form("comparison_ratios_%s.png", nameSpec.Data())); - } - delete canHis; - delete canRat; - } - return 0; + return MakePlots(vecSpecVecSpec, pathFileO2, pathFileAli, pathListAli, doRatio); } diff --git a/codeHF/PlotEfficiency.C b/codeHF/PlotEfficiency.C index 6e4171f5..dfdda396 100644 --- a/codeHF/PlotEfficiency.C +++ b/codeHF/PlotEfficiency.C @@ -1,6 +1,17 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + // Plotting of reconstruction efficiency -#include "utils_plot.h" +#include "../exec/utilitiesPlot.h" Int_t PlotEfficiency(TString pathFile = "AnalysisResults.root", TString particles = "d0") { @@ -88,12 +99,12 @@ Int_t PlotEfficiency(TString pathFile = "AnalysisResults.root", TString particle bool okPrompt = true; TH1F* hPtRecPrompt = (TH1F*)file->Get(nameHistRec.Data()); if (!hPtRecPrompt) { - Printf("Warning: Failed to load %s from %s", nameHistRec.Data(), pathFile.Data()); + Warning("PlotEfficiency", "Failed to load %s from %s", nameHistRec.Data(), pathFile.Data()); okPrompt = false; } TH1F* hPtGenPrompt = (TH1F*)file->Get(nameHistgen.Data()); if (!hPtGenPrompt) { - Printf("Warning: Failed to load %s from %s", nameHistgen.Data(), pathFile.Data()); + Warning("PlotEfficiency", "Failed to load %s from %s", nameHistgen.Data(), pathFile.Data()); okPrompt = false; } @@ -109,12 +120,12 @@ Int_t PlotEfficiency(TString pathFile = "AnalysisResults.root", TString particle bool okNonPrompt = true; TH1F* hPtRecNonPrompt = (TH1F*)file->Get(nameHistRec.Data()); if (!hPtRecNonPrompt) { - Printf("Warning: Failed to load %s from %s", nameHistRec.Data(), pathFile.Data()); + Warning("PlotEfficiency", "Failed to load %s from %s", nameHistRec.Data(), pathFile.Data()); okNonPrompt = false; } TH1F* hPtGenNonPrompt = (TH1F*)file->Get(nameHistgen.Data()); if (!hPtGenNonPrompt) { - Printf("Warning: Failed to load %s from %s", nameHistgen.Data(), pathFile.Data()); + Warning("PlotEfficiency", "Failed to load %s from %s", nameHistgen.Data(), pathFile.Data()); okNonPrompt = false; } diff --git a/codeHF/PlotEfficiencyRecoStep.C b/codeHF/PlotEfficiencyRecoStep.C index e4045203..dd279634 100644 --- a/codeHF/PlotEfficiencyRecoStep.C +++ b/codeHF/PlotEfficiencyRecoStep.C @@ -1,3 +1,14 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + // Computation and plotting of reconstruction efficiency step-by-step // Four steps defined: RecoHFFlag, RecoTopol, RecoCand, RecoPID // RecoHFFlag: candidates properly flagged (e.g. in HFD0CandidateSelector --> hfflag() is D0ToPiK) @@ -10,7 +21,7 @@ // .L PlotEfficiencyRecoStep.C // PlotEfficiencyRecoStep("InputName.root","particlename",true); -#include "utils_plot.h" +#include "../exec/utilitiesPlot.h" void SetProperAxisRange(TH1F** histo, int NIteration, float marginHigh, float marginLow, bool logScaleH); diff --git a/codeHF/RunHFTaskLocal.C b/codeHF/RunHFTaskLocal.C index b4edb1b4..49bbfb33 100644 --- a/codeHF/RunHFTaskLocal.C +++ b/codeHF/RunHFTaskLocal.C @@ -1,4 +1,17 @@ -TChain* CreateLocalChain(const char* txtfile); +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// Macro to run the HF AliPhysics task that produces validation histograms + +#include "../exec/utilitiesAli.h" Long64_t RunHFTaskLocal(TString txtfile = "./list_ali.txt", TString jsonfilename = "dpl-config_std.json", @@ -26,7 +39,7 @@ Long64_t RunHFTaskLocal(TString txtfile = "./list_ali.txt", TChain* chainESD = CreateLocalChain(txtfile.Data()); if (!chainESD) { - Error("CreateLocalChain", "Failed to create chain from file %s", txtfile.Data()); + Fatal("CreateLocalChain", "Failed to create chain from file %s", txtfile.Data()); return -1; } @@ -60,34 +73,3 @@ Long64_t RunHFTaskLocal(TString txtfile = "./list_ali.txt", mgr->PrintStatus(); return mgr->StartAnalysis("local", chainESD); }; - -TChain* CreateLocalChain(const char* txtfile) -{ - // Open the file - ifstream in; - in.open(txtfile); - Int_t count = 0; - // Read the input list of files and add them to the chain - TString line; - TChain* chain = new TChain("esdTree"); - while (in.good()) { - in >> line; - if (line.IsNull() || line.BeginsWith("#")) - continue; - TString esdFile(line); - TFile* file = TFile::Open(esdFile); - if (file && !file->IsZombie()) { - chain->Add(esdFile); - file->Close(); - } else { - Error("CreateLocalChain", "Skipping un-openable file: %s", esdFile.Data()); - } - } - in.close(); - if (!chain->GetListOfFiles()->GetEntries()) { - Error("CreateLocalChain", "No file from %s could be opened", txtfile); - delete chain; - return nullptr; - } - return chain; -} diff --git a/codeHF/utils_plot.h b/codeHF/utils_plot.h deleted file mode 100644 index 94f98bf3..00000000 --- a/codeHF/utils_plot.h +++ /dev/null @@ -1,45 +0,0 @@ -// Plotting utilities - -void SetCanvas(TCanvas* can, int nPadsX, int nPadsY) -{ - can->Divide(nPadsX, nPadsY, 0.005, 0.005); -} - -void SetPad(TVirtualPad* pad, bool logScale) -{ - pad->SetBottomMargin(0.11); - pad->SetLeftMargin(0.1); - pad->SetTopMargin(0.08); - pad->SetRightMargin(0.08); - if (logScale) { - pad->SetLogy(); - } -} - -void SetHistogram(TH1* his, Float_t yMin, Float_t yMax, Float_t marginLow, Float_t marginHigh, bool& logScale) -{ - Float_t textsize = 0.05; - his->GetYaxis()->SetTitleSize(textsize); - his->GetXaxis()->SetTitleSize(textsize); - his->GetYaxis()->SetTitleOffset(1.0); - his->GetXaxis()->SetTitleOffset(1.0); - Float_t k = 1. - marginHigh - marginLow; - Float_t yRange; - if (logScale && yMin > 0 && yMax > 0) { - yRange = yMax / yMin; - his->GetYaxis()->SetRangeUser(yMin / std::pow(yRange, marginLow / k), yMax * std::pow(yRange, marginHigh / k)); - } else { - logScale = false; - yRange = yMax - yMin; - his->GetYaxis()->SetRangeUser(yMin - marginLow / k * yRange, yMax + marginHigh / k * yRange); - } -} - -void SetHistogramStyle(TH1* his, Int_t colour = 1, Int_t markerStyle = 1, Float_t markerSize = 1, Float_t lineWidth = 1) -{ - his->SetLineColor(colour); - his->SetLineWidth(lineWidth); - his->SetMarkerColor(colour); - his->SetMarkerStyle(markerStyle); - his->SetMarkerSize(markerSize); -} diff --git a/codeJE/Compare.C b/codeJE/Compare.C index f681a132..90c43a6d 100644 --- a/codeJE/Compare.C +++ b/codeJE/Compare.C @@ -1,214 +1,42 @@ -// Comparison of AliPhysics and O2 histograms - -#include "utils_plot.h" +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. -// vectors of histogram specifications -using VecSpecHis = std::vector>; +// Comparison of AliPhysics and O2 histograms -// Add histogram specification in the vector. -void AddHistogram(VecSpecHis& vec, TString label, TString nameRun2, TString nameRun3, int rebin, bool logH, bool logR, TString proj = "x") -{ - vec.push_back(std::make_tuple(label, nameRun2, nameRun3, rebin, logH, logR, proj)); -} +#include "../exec/utilitiesValidation.h" -Int_t Compare(TString filerun3 = "AnalysisResults_O2.root", TString filerun2 = "AnalysisResults_ALI.root", TString options = "jets", bool doRatio = true) +Int_t Compare(TString pathFileO2 = "AnalysisResults_O2.root", TString pathFileAli = "AnalysisResults_ALI.root", TString options = "", bool doRatio = false) { - gStyle->SetOptStat(0); - gStyle->SetPalette(0); - gStyle->SetCanvasColor(0); - gStyle->SetFrameFillColor(0); - - TFile* fRun3 = new TFile(filerun3.Data()); - if (fRun3->IsZombie()) { - printf("Failed to open file %s\n", filerun3.Data()); - return 1; - } - TFile* fRun2 = new TFile(filerun2.Data()); - if (fRun2->IsZombie()) { - printf("Failed to open file %s\n", filerun2.Data()); - return 1; - } - - TString pathListRun2 = Form("ChJetSpectraAliAnalysisTaskEmcalJetValidation/AliAnalysisTaskEmcalJetValidation"); // - TList* lRun2 = nullptr; - fRun2->GetObject(pathListRun2.Data(), lRun2); - if (!lRun2) { - printf("Failed to load list %s from %s\n", pathListRun2.Data(), filerun2.Data()); - return 1; - } + TString pathListAli = "ChJetSpectraAliAnalysisTaskEmcalJetValidation/AliAnalysisTaskEmcalJetValidation"; // Histogram specification: axis label, AliPhysics name, O2Physics path/name, rebin, log scale histogram, log scale ratio, projection axis VecSpecHis vecHisEvents; - VecSpecHis vecHisJets; //X axis , Hist Name Run2, Hist Name in Run3, rebin, logScaleH , logScaleR - AddHistogram(vecHisJets, "#it{p}_{T,ch jet} (GeV/#it{c}", "jetPt", "jet-validation-track-collision-qa/jetPt", 1, 1, 0); // - AddHistogram(vecHisJets, "#varphi_{jet}", "jetPhi", "jet-validation-track-collision-qa/jetPhi", 1, 0, 0); - AddHistogram(vecHisJets, "#eta_{jet}", "jetEta", "jet-validation-track-collision-qa/jetEta", 1, 0, 0); - AddHistogram(vecHisJets, "#it{p}_{T,track} (GeV/#it{c}", "jetTrackPt", "jet-validation-track-collision-qa/selectedTrackPt", 1, 1, 0); // - AddHistogram(vecHisJets, "#varphi_{track}", "jetTrackPhi", "jet-validation-track-collision-qa/selectedTrackPhi", 1, 0, 0); - AddHistogram(vecHisJets, "#eta_{track}", "jetTrackEta", "jet-validation-track-collision-qa/selectedTrackEta", 1, 0, 0); + VecSpecHis vecHisJets; + AddHistogram(vecHisJets, "#it{p}_{T, ch jet} (GeV/#it{c})", "jetPt", "jet-validation-track-collision-qa/jetPt", 1, 1, 0); + AddHistogram(vecHisJets, "#it{#varphi}_{jet}", "jetPhi", "jet-validation-track-collision-qa/jetPhi", 1, 0, 0); + AddHistogram(vecHisJets, "#it{#eta}_{jet}", "jetEta", "jet-validation-track-collision-qa/jetEta", 1, 0, 0); + AddHistogram(vecHisJets, "#it{p}_{T, track} (GeV/#it{c})", "jetTrackPt", "jet-validation-track-collision-qa/selectedTrackPt", 1, 1, 0); + AddHistogram(vecHisJets, "#it{#varphi}_{track}", "jetTrackPhi", "jet-validation-track-collision-qa/selectedTrackPhi", 1, 0, 0); + AddHistogram(vecHisJets, "#it{#eta}_{track}", "jetTrackEta", "jet-validation-track-collision-qa/selectedTrackEta", 1, 0, 0); // vector of specifications of vectors: name, VecSpecHis, pads X, pads Y - std::vector> vecSpecVecSpec; + VecSpecVecSpec vecSpecVecSpec; // Add vector specifications in the vector. // if (options.Contains(" events ")) // vecSpecVecSpec.push_back(std::make_tuple("events", vecHisEvents, 4, 2)); if (options.Contains("jets")) vecSpecVecSpec.push_back(std::make_tuple("jets", vecHisJets, 3, 2)); - // if (options.Contains(" skim ")) - // vecSpecVecSpec.push_back(std::make_tuple("skim", vecHisSkim, 5, 3)); - - // Histogram plot vertical margins - Float_t marginHigh = 0.05; - Float_t marginLow = 0.05; - bool logScaleH = false; - // Ratio plot vertical margins - Float_t marginRHigh = 0.05; - Float_t marginRLow = 0.05; - bool logScaleR = false; - Float_t yMin, yMax; - Int_t nRun2, nRun3, rebin; - - TH1F* hRun2 = nullptr; - TH1D* hRun3 = nullptr; - TH1F* hRatio = nullptr; - TString labelAxis = ""; - TString nameHisRun2 = ""; - TString nameHisRun3 = ""; - TString projAx = ""; - TCanvas* canHis = nullptr; - TCanvas* canRat = nullptr; - - // loop over lists - for (const auto& specVecSpec : vecSpecVecSpec) { - auto nameSpec = std::get<0>(specVecSpec); // list name - auto vecSpec = std::get<1>(specVecSpec); // list of histogram specs. - int nPadsX = std::get<2>(specVecSpec); // number of horizontal pads - int nPadsY = std::get<3>(specVecSpec); // number of vertical pads - Printf("\nProcessing histogram list: %s (%d)", nameSpec.Data(), (int)vecSpec.size()); - if (nPadsX * nPadsY < vecSpec.size()) { - Printf("Not enough pads (%d)", nPadsX * nPadsY); - return 1; - } - - canHis = new TCanvas(Form("canHis_%s", nameSpec.Data()), Form("Histos_%s", nameSpec.Data()), 3000, 1600); - SetCanvas(canHis, nPadsX, nPadsY); - if (doRatio) { - canRat = new TCanvas(Form("canRat_%s", nameSpec.Data()), Form("Ratios_%s", nameSpec.Data()), 3000, 1600); - SetCanvas(canRat, nPadsX, nPadsY); - } - - // loop over histograms - for (int index = 0; index < vecSpec.size(); index++) { - auto spec = vecSpec[index]; - labelAxis = std::get<0>(spec); - nameHisRun2 = std::get<1>(spec); - nameHisRun3 = std::get<2>(spec); - rebin = std::get<3>(spec); - logScaleH = std::get<4>(spec); - logScaleR = std::get<5>(spec); - projAx = std::get<6>(spec); - - // Get AliPhysics histogram. - hRun2 = (TH1F*)lRun2->FindObject(nameHisRun2.Data()); - if (!hRun2) { - printf("Failed to load %s from %s\n", nameHisRun2.Data(), filerun2.Data()); - return 1; - } - - // Get O2 histogram. - auto oRun3 = fRun3->Get(nameHisRun3.Data()); - if (!oRun3) { - printf("Failed to load %s from %s\n", nameHisRun3.Data(), filerun3.Data()); - return 1; - } - - if (oRun3->InheritsFrom("TH3")) { - if (projAx == "x") { - hRun3 = ((TH3D*)oRun3)->ProjectionX(); - } else if (projAx == "y") { - hRun3 = ((TH3D*)oRun3)->ProjectionY(); - } - } else if (oRun3->InheritsFrom("TH2")) { - if (projAx == "x") { - hRun3 = ((TH2D*)oRun3)->ProjectionX(); - } else if (projAx == "y") { - hRun3 = ((TH2D*)oRun3)->ProjectionY(); - } - } else { - hRun3 = (TH1D*)oRun3; - } - - Printf("%d (%s, %s): bins: %d, %d, ranges: %g-%g, %g-%g", - index, nameHisRun2.Data(), nameHisRun3.Data(), - hRun2->GetNbinsX(), hRun3->GetNbinsX(), - hRun2->GetXaxis()->GetBinLowEdge(1), hRun2->GetXaxis()->GetBinUpEdge(hRun2->GetNbinsX()), - hRun3->GetXaxis()->GetBinLowEdge(1), hRun3->GetXaxis()->GetBinUpEdge(hRun3->GetNbinsX())); - - nRun2 = hRun2->GetEntries(); - nRun3 = hRun3->GetEntries(); - // Histograms - auto padH = canHis->cd(index + 1); - - Printf("histo name: %s", hRun2->GetName()); - hRun2->Rebin(rebin); - hRun3->Rebin(rebin); - hRun2->SetLineColor(1); - hRun2->SetLineWidth(2); - hRun2->SetMarkerStyle(22); - hRun2->SetMarkerColor(1); - hRun3->SetLineColor(2); - hRun3->SetLineWidth(2); - hRun3->SetMarkerStyle(22); - hRun3->SetMarkerColor(2); - hRun2->SetTitle(" "); - hRun2->GetYaxis()->SetTitle("number of entries"); - hRun2->GetYaxis()->SetMaxDigits(3); - yMin = TMath::Min(hRun3->GetMinimum(0), hRun2->GetMinimum(0)); - yMax = TMath::Max(hRun3->GetMaximum(), hRun2->GetMaximum()); - SetHistogram(hRun2, yMin, yMax, marginLow, marginHigh, logScaleH); - SetPad(padH, logScaleH); - hRun2->Draw(""); - hRun3->Draw("Esame"); - - if (std::string(hRun2->GetName()) == "jetPt" || std::string(hRun2->GetName()) == "jetTrackPt") { - TLegend* legend = new TLegend(0.2, 0.84, 0.82, 0.92); - legend->SetNColumns(2); - legend->AddEntry(hRun2, Form("AliPhysics: %d", nRun2), "L"); - legend->AddEntry(hRun3, Form("O2Physics: %d", nRun3), "L"); - legend->Draw(); - } else { - TLegend* legend = new TLegend(0.2, 0.92, 0.82, 1.0); - legend->SetNColumns(2); - legend->SetBorderSize(0); - legend->AddEntry(hRun2, Form("AliPhysics: %d", nRun2), "L"); - legend->AddEntry(hRun3, Form("O2Physics: %d", nRun3), "L"); - legend->Draw(); - } - - // Ratio - if (doRatio) { - auto padR = canRat->cd(index + 1); - hRatio = (TH1F*)hRun3->Clone(Form("hRatio%d", index)); - hRatio->Divide(hRun2); - hRatio->SetTitle(""); - hRatio->GetYaxis()->SetTitle("O2Physics/AliPhysics"); - yMin = hRatio->GetMinimum(0) * 0.3; - yMax = hRatio->GetMaximum() * 1.3; - SetHistogram(hRatio, yMin, yMax, marginRLow, marginRHigh, logScaleR); - SetPad(padR, logScaleR); - hRatio->Draw(); - } - } - canHis->SaveAs(Form("comparison_histos_%s.png", nameSpec.Data())); - if (doRatio) { - canRat->SaveAs(Form("comparison_ratios_%s.png", nameSpec.Data())); - } - // delete canHis; - delete canRat; - } - return 0; + return MakePlots(vecSpecVecSpec, pathFileO2, pathFileAli, pathListAli, doRatio); } diff --git a/codeJE/RunJetTaskLocal.C b/codeJE/RunJetTaskLocal.C index 02388459..fe1e5588 100644 --- a/codeJE/RunJetTaskLocal.C +++ b/codeJE/RunJetTaskLocal.C @@ -1,3 +1,18 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// Macro to run the JE AliPhysics task that produces validation histograms + +#include "../exec/utilitiesAli.h" + #ifdef __CLING__ // Tell ROOT where to find AliRoot headers R__ADD_INCLUDE_PATH($ALICE_ROOT) @@ -8,8 +23,6 @@ R__ADD_INCLUDE_PATH($ALICE_PHYSICS) #endif -TChain* CreateLocalChain(const char* txtfile); - Long64_t RunJetTaskLocal(TString txtfile = "./list_ali.txt", TString jsonfilename = "dpl-config_std.json", Bool_t isMC = kFALSE, @@ -33,7 +46,7 @@ Long64_t RunJetTaskLocal(TString txtfile = "./list_ali.txt", TChain* chainESD = CreateLocalChain(txtfile.Data()); if (!chainESD) { - Error("CreateLocalChain", "Failed to create chain from file %s", txtfile.Data()); + Fatal("CreateLocalChain", "Failed to create chain from file %s", txtfile.Data()); return -1; } @@ -67,34 +80,3 @@ Long64_t RunJetTaskLocal(TString txtfile = "./list_ali.txt", mgr->PrintStatus(); return mgr->StartAnalysis("local", chainESD); }; - -TChain* CreateLocalChain(const char* txtfile) -{ - // Open the file - ifstream in; - in.open(txtfile); - Int_t count = 0; - // Read the input list of files and add them to the chain - TString line; - TChain* chain = new TChain("esdTree"); - while (in.good()) { - in >> line; - if (line.IsNull() || line.BeginsWith("#")) - continue; - TString esdFile(line); - TFile* file = TFile::Open(esdFile); - if (file && !file->IsZombie()) { - chain->Add(esdFile); - file->Close(); - } else { - Error("CreateLocalChain", "Skipping un-openable file: %s", esdFile.Data()); - } - } - in.close(); - if (!chain->GetListOfFiles()->GetEntries()) { - Error("CreateLocalChain", "No file from %s could be opened", txtfile); - delete chain; - return nullptr; - } - return chain; -} diff --git a/codeJE/utils_plot.h b/codeJE/utils_plot.h deleted file mode 120000 index 04a6f997..00000000 --- a/codeJE/utils_plot.h +++ /dev/null @@ -1 +0,0 @@ -../codeHF/utils_plot.h \ No newline at end of file diff --git a/codeHF/compare.py b/exec/compare.py similarity index 100% rename from codeHF/compare.py rename to exec/compare.py diff --git a/exec/convertAO2D.C b/exec/convertAO2D.C index 7a031316..e7b602d3 100644 --- a/exec/convertAO2D.C +++ b/exec/convertAO2D.C @@ -1,3 +1,14 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + R__ADD_INCLUDE_PATH($ALICE_ROOT) R__ADD_INCLUDE_PATH($ALICE_PHYSICS) #include @@ -8,7 +19,7 @@ R__ADD_INCLUDE_PATH($ALICE_PHYSICS) #include #include -TChain* CreateLocalChain(const char* txtfile, const char* type, int nfiles); +#include "utilitiesAli.h" Long64_t convertAO2D(TString listoffiles, bool isMC = 1, bool useAliEvCuts = false, bool isESD = 1, int nmaxevents = -1) { @@ -57,42 +68,3 @@ Long64_t convertAO2D(TString listoffiles, bool isMC = 1, bool useAliEvCuts = fal mgr->SetDebugLevel(1); return mgr->StartAnalysis("localfile", chain, nentries, 0); } - -TChain* CreateLocalChain(const char* txtfile, const char* type, int nfiles) -{ - TString treename = type; - treename.ToLower(); - treename += "Tree"; - printf("***************************************\n"); - printf(" Getting chain of trees %s\n", treename.Data()); - printf("***************************************\n"); - // Open the file - ifstream in; - in.open(txtfile); - Int_t count = 0; - // Read the input list of files and add them to the chain - TString line; - TChain* chain = new TChain(treename); - while (in.good()) { - in >> line; - if (line.IsNull() || line.BeginsWith("#")) - continue; - if (count++ == nfiles) - break; - TString esdFile(line); - TFile* file = TFile::Open(esdFile); - if (file && !file->IsZombie()) { - chain->Add(esdFile); - file->Close(); - } else { - Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data()); - } - } - in.close(); - if (!chain->GetListOfFiles()->GetEntries()) { - Error("CreateLocalChain", "No file from %s could be opened", txtfile); - delete chain; - return nullptr; - } - return chain; -} diff --git a/exec/utilitiesAli.h b/exec/utilitiesAli.h new file mode 100644 index 00000000..c2e4e81f --- /dev/null +++ b/exec/utilitiesAli.h @@ -0,0 +1,53 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// AliPhysics utilities + +#ifndef EXEC_UTILITIESALI_H_ +#define EXEC_UTILITIESALI_H_ + +TChain* CreateLocalChain(const char* txtfile, const char* type = "esd", int nfiles = -1) +{ + TString treename = type; + treename.ToLower(); + treename += "Tree"; + // Open the file + ifstream in; + in.open(txtfile); + Int_t count = 0; + // Read the input list of files and add them to the chain + TString line; + TChain* chain = new TChain(treename); + while (in.good()) { + in >> line; + if (line.IsNull() || line.BeginsWith("#")) + continue; + if (count++ == nfiles) + break; + TString esdFile(line); + TFile* file = TFile::Open(esdFile); + if (file && !file->IsZombie()) { + chain->Add(esdFile); + file->Close(); + } else { + Error("CreateLocalChain", "Skipping un-openable file: %s", esdFile.Data()); + } + } + in.close(); + if (!chain->GetListOfFiles()->GetEntries()) { + Error("CreateLocalChain", "No file from %s could be opened", txtfile); + delete chain; + return nullptr; + } + return chain; +} + +#endif // EXEC_UTILITIESALI_H_ diff --git a/exec/utilitiesPlot.h b/exec/utilitiesPlot.h new file mode 100644 index 00000000..250362ed --- /dev/null +++ b/exec/utilitiesPlot.h @@ -0,0 +1,126 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// Plotting utilities + +#ifndef EXEC_UTILITIESPLOT_H_ +#define EXEC_UTILITIESPLOT_H_ + +#include // std::min, std::max + +void SetCanvas(TCanvas* can, int nPadsX, int nPadsY) +{ + if (!can) { + Fatal("SetCanvas", "Invalid canvas"); + return; + } + can->Divide(nPadsX, nPadsY, 0.005, 0.005); +} + +void SetPad(TVirtualPad* pad, bool logScale) +{ + if (!pad) { + Fatal("SetPad", "Invalid pad"); + return; + } + pad->SetBottomMargin(0.11); + pad->SetLeftMargin(0.1); + pad->SetTopMargin(0.08); + pad->SetRightMargin(0.08); + if (logScale) { + pad->SetLogy(); + } +} + +/// @brief Get maximum and minimum of a histograms with non-negative bin contents and errors +/// @param his histogram +/// @param yMin variable to set minimum +/// @param yMax variable to set maximum +/// @param onlyPositive make sure that yMin, yMax are positive +/// @param includeErrors consider heights of error bars +void GetYRange(TH1* his, Float_t& yMin, Float_t& yMax, bool onlyPositive = true, bool includeErrors = true) +{ + if (!his) { + Fatal("GetYRange", "Invalid histogram"); + return; + } + yMin = his->GetMinimum(0); + yMax = his->GetMaximum(); + if (onlyPositive) { + if (yMin <= 0.) { + yMin = 1.; + } + if (yMax <= 0.) { + yMax = 1.; + } + } + if (includeErrors) { + Float_t cont, err, yLow; + for (Int_t i = 0; i < his->GetNbinsX(); i++) { + cont = his->GetBinContent(i + 1); + if (cont <= 0.) { + continue; + } + err = his->GetBinError(i + 1); + yLow = cont - err; + if (onlyPositive && yLow <= 0.) { + yLow = cont; + } + yMin = std::min(yMin, yLow); + yMax = std::max(yMax, cont + err); + } + } +} + +/// @brief Set plotting properties of a histogram +/// @param his histogram +/// @param yMin minimum y value to display +/// @param yMax maximum y value to display +/// @param marginLow margin to keep below yMin (expressed as a fraction of the full y-axis plotting range) +/// @param marginHigh margin to keep above yMax (expressed as a fraction of the full y-axis plotting range) +/// @note The full y-axis plotting range is calculated from yMin, yMax, marginLow, marginHigh, logScale. +void SetHistogram(TH1* his, Float_t yMin, Float_t yMax, Float_t marginLow, Float_t marginHigh, bool& logScale) +{ + if (!his) { + Fatal("SetHistogram", "Invalid histogram"); + return; + } + Float_t textsize = 0.05; + his->GetYaxis()->SetTitleSize(textsize); + his->GetXaxis()->SetTitleSize(textsize); + his->GetYaxis()->SetTitleOffset(1.0); + his->GetXaxis()->SetTitleOffset(1.0); + Float_t k = 1. - marginHigh - marginLow; + Float_t yRange; + if (logScale && yMin > 0 && yMax > 0) { + yRange = yMax / yMin; + his->GetYaxis()->SetRangeUser(yMin / std::pow(yRange, marginLow / k), yMax * std::pow(yRange, marginHigh / k)); + } else { + logScale = false; + yRange = yMax - yMin; + his->GetYaxis()->SetRangeUser(yMin - marginLow / k * yRange, yMax + marginHigh / k * yRange); + } +} + +void SetHistogramStyle(TH1* his, Int_t colour = 1, Int_t markerStyle = 1, Float_t markerSize = 1, Float_t lineWidth = 1) +{ + if (!his) { + Fatal("SetHistogramStyle", "Invalid histogram"); + return; + } + his->SetLineColor(colour); + his->SetLineWidth(lineWidth); + his->SetMarkerColor(colour); + his->SetMarkerStyle(markerStyle); + his->SetMarkerSize(markerSize); +} + +#endif // EXEC_UTILITIESPLOT_H_ diff --git a/exec/utilitiesValidation.h b/exec/utilitiesValidation.h new file mode 100644 index 00000000..3da415e4 --- /dev/null +++ b/exec/utilitiesValidation.h @@ -0,0 +1,205 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// Validation utilities + +#ifndef EXEC_UTILITIESVALIDATION_H_ +#define EXEC_UTILITIESVALIDATION_H_ + +#include // std::min, std::max +#include // std::tuple, std::make_tuple +#include // std::vector + +#include "utilitiesPlot.h" + +// vectors of histogram specifications: axis label, AliPhysics name, O2Physics path/name, rebin, log scale histogram, log scale ratio, projection axis +using VecSpecHis = std::vector>; + +// vector of specifications of vectors: name, VecSpecHis, pads X, pads Y +using VecSpecVecSpec = std::vector>; + +// Add histogram specification in the vector. +void AddHistogram(VecSpecHis& vec, TString label, TString nameAli, TString nameO2, int rebin, bool logH, bool logR, TString proj = "x") +{ + vec.push_back(std::make_tuple(label, nameAli, nameO2, rebin, logH, logR, proj)); +} + +// Make validation plots. +Int_t MakePlots(const VecSpecVecSpec& vecSpecVecSpec, + TString pathFileO2 = "AnalysisResults_O2.root", + TString pathFileAli = "AnalysisResults_ALI.root", + TString pathListAli = "list", + bool doRatio = false) +{ + gStyle->SetOptStat(0); + gStyle->SetPalette(0); + gStyle->SetCanvasColor(0); + gStyle->SetFrameFillColor(0); + + TFile* fO2 = new TFile(pathFileO2.Data()); + if (fO2->IsZombie()) { + Fatal("MakePlots", "Failed to open file %s\n", pathFileO2.Data()); + return 1; + } + TFile* fAli = new TFile(pathFileAli.Data()); + if (fAli->IsZombie()) { + Fatal("MakePlots", "Failed to open file %s\n", pathFileAli.Data()); + return 1; + } + + TList* lAli = nullptr; + fAli->GetObject(pathListAli.Data(), lAli); + if (!lAli) { + Fatal("MakePlots", "Failed to load list %s from %s\n", pathListAli.Data(), pathFileAli.Data()); + return 1; + } + + // Histogram plot vertical margins + Float_t marginHigh = 0.05; + Float_t marginLow = 0.05; + bool logScaleH = false; + // Ratio plot vertical margins + Float_t marginRHigh = 0.05; + Float_t marginRLow = 0.05; + bool logScaleR = false; + Float_t yMin, yMax; + Int_t nAli, nO2, rebin; + + TH1F* hAli = nullptr; + TH1D* hO2 = nullptr; + TH1F* hRatio = nullptr; + TString labelAxis = ""; + TString nameHisAli = ""; + TString nameHisO2 = ""; + TString projAx = ""; + TCanvas* canHis = nullptr; + TCanvas* canRat = nullptr; + + // loop over lists + for (const auto& specVecSpec : vecSpecVecSpec) { + auto nameSpec = std::get<0>(specVecSpec); // list name + auto vecSpec = std::get<1>(specVecSpec); // list of histogram specs. + int nPadsX = std::get<2>(specVecSpec); // number of horizontal pads + int nPadsY = std::get<3>(specVecSpec); // number of vertical pads + Printf("\nProcessing histogram list: %s (%lu)", nameSpec.Data(), vecSpec.size()); + if (nPadsX * nPadsY < vecSpec.size()) { + Printf("Not enough pads (%d)", nPadsX * nPadsY); + return 1; + } + + canHis = new TCanvas(Form("canHis_%s", nameSpec.Data()), Form("Histos_%s", nameSpec.Data()), 3000, 1600); + SetCanvas(canHis, nPadsX, nPadsY); + if (doRatio) { + canRat = new TCanvas(Form("canRat_%s", nameSpec.Data()), Form("Ratios_%s", nameSpec.Data()), 3000, 1600); + SetCanvas(canRat, nPadsX, nPadsY); + } + + // loop over histograms + for (int index = 0; index < vecSpec.size(); index++) { + auto spec = vecSpec[index]; + labelAxis = std::get<0>(spec); + nameHisAli = std::get<1>(spec); + nameHisO2 = std::get<2>(spec); + rebin = std::get<3>(spec); + logScaleH = std::get<4>(spec); + logScaleR = std::get<5>(spec); + projAx = std::get<6>(spec); + + // Get AliPhysics histogram. + hAli = reinterpret_cast(lAli->FindObject(nameHisAli.Data())); + if (!hAli) { + Fatal("MakePlots", "Failed to load %s from %s\n", nameHisAli.Data(), pathFileAli.Data()); + return 1; + } + + // Get O2 histogram. + auto oO2 = fO2->Get(nameHisO2.Data()); + if (!oO2) { + Fatal("MakePlots", "Failed to load %s from %s\n", nameHisO2.Data(), pathFileO2.Data()); + return 1; + } + + if (oO2->InheritsFrom("TH3")) { + if (projAx == "x") { + hO2 = (reinterpret_cast(oO2))->ProjectionX(); + } else if (projAx == "y") { + hO2 = (reinterpret_cast(oO2))->ProjectionY(); + } + } else if (oO2->InheritsFrom("TH2")) { + if (projAx == "x") { + hO2 = (reinterpret_cast(oO2))->ProjectionX(); + } else if (projAx == "y") { + hO2 = (reinterpret_cast(oO2))->ProjectionY(); + } + } else { + hO2 = reinterpret_cast(oO2); + } + + Printf("%d (%s, %s): bins: %d, %d, ranges: %g-%g, %g-%g", + index, nameHisAli.Data(), nameHisO2.Data(), + hAli->GetNbinsX(), hO2->GetNbinsX(), + hAli->GetXaxis()->GetBinLowEdge(1), hAli->GetXaxis()->GetBinUpEdge(hAli->GetNbinsX()), + hO2->GetXaxis()->GetBinLowEdge(1), hO2->GetXaxis()->GetBinUpEdge(hO2->GetNbinsX())); + + nAli = hAli->GetEntries(); + nO2 = hO2->GetEntries(); + + // Histograms + auto padH = canHis->cd(index + 1); + hAli->Rebin(rebin); + hO2->Rebin(rebin); + hAli->SetLineColor(1); + hAli->SetLineWidth(2); + hO2->SetLineColor(2); + hO2->SetLineWidth(1); + hAli->SetTitle(Form(";%s;Entries", labelAxis.Data())); + hAli->GetYaxis()->SetMaxDigits(3); + Float_t yMinO2, yMaxO2; + GetYRange(hO2, yMinO2, yMaxO2, logScaleH, false); + GetYRange(hAli, yMin, yMax, logScaleH, false); + yMin = std::min(yMinO2, yMin); + yMax = std::max(yMaxO2, yMax); + SetHistogram(hAli, yMin, yMax, marginLow, marginHigh, logScaleH); + SetPad(padH, logScaleH); + hAli->Draw("hist"); + hO2->Draw("hist same"); + TLegend* legend = new TLegend(0.2, 0.92, 0.82, 1.0); + legend->SetNColumns(2); + legend->SetBorderSize(0); + legend->AddEntry(hAli, Form("Ali: %d", nAli), "L"); + legend->AddEntry(hO2, Form("O^{2}: %d", nO2), "L"); + legend->Draw(); + + // Ratio + if (doRatio) { + auto padR = canRat->cd(index + 1); + hRatio = reinterpret_cast(hO2->Clone(Form("hRatio%d", index))); + hRatio->Divide(hAli); + hRatio->SetTitle(Form("Entries ratio: %g;%s;O^{2}/Ali", static_cast(nO2) / static_cast(nAli), labelAxis.Data())); + GetYRange(hRatio, yMin, yMax, logScaleR, false); + SetHistogram(hRatio, yMin, yMax, marginRLow, marginRHigh, logScaleR); + SetPad(padR, logScaleR); + hRatio->Draw("hist"); + } + } + canHis->SaveAs(Form("comparison_histos_%s.pdf", nameSpec.Data())); + canHis->SaveAs(Form("comparison_histos_%s.png", nameSpec.Data())); + if (doRatio) { + canRat->SaveAs(Form("comparison_ratios_%s.pdf", nameSpec.Data())); + canRat->SaveAs(Form("comparison_ratios_%s.png", nameSpec.Data())); + } + delete canHis; + delete canRat; + } + return 0; +} + +#endif // EXEC_UTILITIESVALIDATION_H_