53 const std::string& optStat)
const
56 bool bCmpPointByPoint = opt.find(
"p") != std::string::npos;
57 bool bCmpStatTest = opt.find(
"s") != std::string::npos;
58 bool bCmpRatio = opt.find(
"r") != std::string::npos;
63 if constexpr (std::is_base_of_v<TH1, Obj>) {
64 auto CheckAxes = [&](
const TAxis* pL,
const TAxis* pR,
const char* name) {
66 if (pL->GetNbins() != pR->GetNbins()) {
67 LOG(warn) <<
"histogram " << name <<
" has inconsistent bin number with the default histogram";
70 if (pL->GetXmin() != pR->GetXmin()) {
71 LOG(warn) <<
"histogram " << name <<
" has inconsistent min of an axis x, y or z with the default histogram";
74 if (pL->GetXmax() != pR->GetXmax()) {
75 LOG(warn) <<
"histogram " << name <<
" has inconsistent max of an axis x, y or z with the default histogram";
93 if (bCmpPointByPoint || bCmpRatio) {
97 for (
int iBinX = 0; iBinX <=
fpObjL->GetNbinsX(); ++iBinX) {
98 for (
int iBinY = 0; iBinY <=
fpObjL->GetNbinsY(); ++iBinY) {
99 for (
int iBinZ = 0; iBinZ <=
fpObjL->GetNbinsZ(); ++iBinZ) {
100 auto numBinContent =
fpObjL->GetBinContent(iBinX, iBinY, iBinZ);
101 auto denBinContent =
fpObjR->GetBinContent(iBinX, iBinY, iBinZ);
102 double ratio =
static_cast<double>(numBinContent) / denBinContent;
104 if (!TMath::IsNaN(numBinContent) && !TMath::IsNaN(denBinContent)) {
105 if (numBinContent != denBinContent) {
119 if (TMath::IsNaN(numBinContent) != TMath::IsNaN(denBinContent)) {
123 auto numBinError =
fpObjL->GetBinError(iBinX, iBinY, iBinZ);
124 auto denBinError =
fpObjR->GetBinError(iBinX, iBinY, iBinZ);
126 if (!TMath::IsNaN(numBinError) && !TMath::IsNaN(denBinError)) {
127 if (numBinError != denBinError) {
132 if (TMath::IsNaN(numBinError) != TMath::IsNaN(denBinError)) {
142 TString optParam = optStat +
"CHI2/NDF";
155 constexpr int kPadPX = 500;
156 constexpr int kPadPY = 500;
157 constexpr double kPadMarginL = 0.15;
158 constexpr double kPadMarginR = 0.05;
159 constexpr double kPadMarginB = 0.12;
160 constexpr double kPadMarginT = 0.10;
161 constexpr Style_t kMarkerL = 24;
162 constexpr Style_t kMarkerR = 25;
163 constexpr Style_t kMarkerDif = 20;
164 constexpr Style_t kMarkerRat = 20;
167 bool bDrawCmp = opt.find(
"c") != std::string::npos;
168 bool bDrawRat = opt.find(
"r") != std::string::npos;
169 bool bDrawDif = opt.find(
"d") != std::string::npos;
170 int nPads = bDrawCmp + bDrawDif + bDrawRat;
176 auto* pCanv =
new TCanvas(
"comparison",
"comparison", kPadPX * nPads, kPadPY);
177 pCanv->Divide(nPads, 1);
179 if constexpr (std::is_base_of_v<TH1, Obj>) {
182 gPad->SetMargin(kPadMarginL, kPadMarginR, kPadMarginB, kPadMarginT);
183 auto* pMGraph =
new TMultiGraph(Form(
"%s_cmp",
fpObjL->GetName()),
fpObjL->GetTitle());
184 auto* pGrL =
new TGraphAsymmErrors(
fpObjL);
185 pGrL->SetLineColor(kOrange + 5);
186 pGrL->SetMarkerColor(kOrange + 5);
187 pGrL->SetMarkerStyle(kMarkerL);
188 auto* pGrR =
new TGraphAsymmErrors(
fpObjR);
189 pGrR->SetLineColor(kCyan - 2);
190 pGrR->SetMarkerColor(kCyan - 2);
191 pGrR->SetMarkerStyle(kMarkerR);
192 pMGraph->Add(pGrL,
"P");
193 pMGraph->Add(pGrR,
"P");
194 pMGraph->GetXaxis()->SetTitle(
fpObjL->GetXaxis()->GetTitle());
195 pMGraph->GetYaxis()->SetTitle(
fpObjL->GetYaxis()->GetTitle());
197 auto* pLegend =
new TLegend(0.55, 0.80, (1. - kPadMarginR), (1. - kPadMarginT));
198 pLegend->SetTextSize(0.035);
200 pLegend->SetFillStyle(0);
201 pLegend->SetMargin(0.2);
202 pLegend->AddEntry(pGrL,
fsLabelL.c_str(),
"P");
203 pLegend->AddEntry(pGrR,
fsLabelR.c_str(),
"P");
207 TH1* pHistL =
nullptr;
208 TH1* pHistR =
nullptr;
209 if constexpr (std::is_base_of_v<TProfile2D, Obj>) {
213 else if constexpr (std::is_base_of_v<TProfile, Obj>) {
218 pHistL =
static_cast<Obj*
>(
fpObjL->Clone(Form(
"tmp_%s",
fsLabelL.c_str())));
219 pHistR =
static_cast<Obj*
>(
fpObjR->Clone(Form(
"tmp_%s",
fsLabelR.c_str())));
224 pCanv->cd(
static_cast<int>(bDrawCmp) +
static_cast<int>(bDrawDif) + 1);
225 gPad->SetMargin(kPadMarginL, kPadMarginR, kPadMarginB, kPadMarginT);
226 auto currErrorLevel = gErrorIgnoreLevel;
227 gErrorIgnoreLevel = kError;
228 auto* pGrRat =
new TGraphAsymmErrors(pHistL, pHistR,
"pois");
229 gErrorIgnoreLevel = currErrorLevel;
230 pGrRat->GetXaxis()->SetTitle(pHistL->GetXaxis()->GetTitle());
231 pGrRat->GetYaxis()->SetTitle(
"ratio");
232 pGrRat->SetTitle(Form(
"Ratio of \"%s\" and \"%s\"",
fsLabelL.c_str(),
fsLabelR.c_str()));
233 pGrRat->SetMarkerStyle(kMarkerRat);
239 pCanv->cd(
static_cast<int>(bDrawCmp) + 1);
240 gPad->SetMargin(kPadMarginL, kPadMarginR, kPadMarginB, kPadMarginT);
241 auto* pDif =
static_cast<Obj*
>(pHistL->Clone());
242 pDif->Add(pHistR, -1.);
243 auto* pGrDif =
new TGraphAsymmErrors(pDif);
244 pGrDif->GetXaxis()->SetTitle(pHistL->GetXaxis()->GetTitle());
245 pGrDif->GetYaxis()->SetTitle(
"difference");
246 pGrDif->SetTitle(Form(
"Difference of \"%s\" and \"%s\"",
fsLabelL.c_str(),
fsLabelR.c_str()));
247 pGrDif->SetMarkerStyle(kMarkerDif);