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";
82 if (!(CheckAxes(fpObjL->GetXaxis(), fpObjR->GetXaxis(), fpObjL->GetName())
83 && CheckAxes(fpObjL->GetYaxis(), fpObjR->GetYaxis(), fpObjL->GetName())
84 && CheckAxes(fpObjL->GetZaxis(), fpObjR->GetZaxis(), fpObjL->GetName()))) {
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";
143 res.
fChi2NDF = fpObjL->Chi2Test(fpObjR, optParam);
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>) {
210 pHistL = fpObjL->ProjectionXY(Form(
"tmp_%s", fsLabelL.c_str()));
211 pHistR = fpObjR->ProjectionXY(Form(
"tmp_%s", fsLabelR.c_str()));
213 else if constexpr (std::is_base_of_v<TProfile, Obj>) {
214 pHistL = fpObjL->ProjectionX(Form(
"tmp_%s", fsLabelL.c_str()));
215 pHistR = fpObjR->ProjectionX(Form(
"tmp_%s", fsLabelR.c_str()));
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);