17 #include "TEfficiency.h"
19 #include "TVirtualPad.h"
20 #include "TPaveStats.h"
23 #include "TCollection.h"
24 #include "THashList.h"
46 m_drawNormalized(kFALSE),
62 Int_t canvasWidth = 1000;
63 Int_t canvasHeight = 580;
67 m_can =
new TCanvas(
"can",
"can",canvasWidth,canvasHeight);
74 cout <<
"Summary:" << endl;
75 cout <<
"========" << endl;
76 cout <<
"Total histograms compared: " <<
m_histTotal << endl;
78 cout <<
"Matching histograms: " <<
m_histMatch << endl;
83 cout <<
"List of different histograms:" << endl;
88 cout << setw(2) <<
i <<
") " << *iter << endl;
93 cout << endl <<
"List of ignored histograms:" << endl;
98 cout << setw(2) <<
i <<
") " << *iter << endl;
104 cout <<
"Comparison results written to " <<
m_outFile->GetName() << endl;
110 cout <<
"Comparison results written to " <<
m_psFile << endl;
122 if (TString(
key.GetName()).Contains(
"/")) {
123 cout <<
"IGNORE: " <<
key.GetName() <<
" contains '/'" << endl;
127 std::unique_ptr<TObject>
obj(
key.ReadObj());
141 TObject* refObj =
m_refFile->Get(keyPath);
143 cout <<
"Cannot find " << keyPath <<
" in reference file" << endl;
148 if (
obj->Class()!=refObj->Class()) {
149 cout <<
key.GetName() <<
" is of different type in file and reference file." << endl;
153 if (
obj->IsA()->InheritsFrom(
"TH1")) {
154 TH1&
h = *((TH1*)
obj.get());
155 TH1&
href = *((TH1*)refObj);
176 m_can->cd(1)->SetPad(0,1,1,0.90);
177 m_can->cd(2)->SetPad(0,0.90,1,0);
178 TVirtualPad* pad =
m_can->cd(2);
181 m_can->SetName(
h.GetName());
182 m_can->SetTitle(
h.GetTitle());
187 if (
h.Integral())
h.Scale(1/
h.Integral());
190 Double_t
ymax = 1.05*
max(
h.GetMaximum(),
href.GetMaximum());
192 h.SetLineColor(kBlue);
195 TPaveStats* st1 = (TPaveStats*)gPad->GetPrimitive(
"stats");
197 st1->SetName(
"stats1");
198 st1->SetLineColor(kBlue);
201 href.SetLineColor(kRed);
204 TPaveStats* st2 = (TPaveStats*)gPad->GetPrimitive(
"stats");
207 Double_t
x1 = st1->GetX1NDC()-0.01;
208 st2->SetName(
"stats2");
209 Double_t
w = st2->GetX2NDC()-st2->GetX1NDC();
212 st2->SetLineColor(kRed);
218 hdiff = (TH1*)
h.Clone();
220 if (hdiff->GetDimension()==1 &&
221 hdiff->GetNbinsX()==
href.GetNbinsX()) {
224 hdiff->SetName(TString(
href.GetName())+
" (diff)");
225 hdiff->SetTitle(TString(
href.GetTitle())+
" (diff)");
226 hdiff->SetLineColor(kBlack);
227 hdiff->Add(&
href,-1);
229 TPaveStats* st = (TPaveStats*)gPad->GetPrimitive(
"stats1");
230 if (st) st->SetLineColor(kBlack);
232 if(hdiff->GetDimension()==2 &&
233 hdiff->GetNbinsX()==
href.GetNbinsX() &&
234 hdiff->GetNbinsY()==
href.GetNbinsY()) {
236 hdiff->SetName(TString(
href.GetName())+
" (diff)");
237 hdiff->SetTitle(TString(
href.GetTitle())+
" (diff)");
238 hdiff->SetLineColor(kBlack);
239 hdiff->Add(&
href,-1);
240 if(hdiff->GetXaxis()->GetLabels()!=0 && hdiff->GetNbinsX()>100) {
241 TH1 * hdiffred = (TH1*)hdiff->Clone();
242 hdiffred->GetXaxis()->GetLabels()->Delete();
244 hdiffred->SetName(TString(
href.GetName())+
" (diff reduced)");
245 hdiffred->SetTitle(TString(
href.GetTitle())+
" (diff reduced)");
247 for(
int x=1;
x<=hdiff->GetNbinsX(); ++
x) {
249 for(
int y=1;
y<=hdiff->GetNbinsY();++
y) {
250 if(hdiff->GetBinContent(
x,
y)!=0) { isEmpty=
false;
break; }
253 for(
int y=1;
y<=hdiff->GetNbinsY();++
y) {
254 if(hdiff->GetBinContent(
x,
y)!=0)
255 hdiffred->SetBinContent(targetbin,
y,hdiff->GetBinContent(
x,
y));
257 hdiffred->GetXaxis()->SetBinLabel(targetbin,hdiff->GetXaxis()->GetBinLabel(
x));
261 hdiffred->LabelsDeflate();
262 hdiffred->Draw(
"text");
266 TPaveStats* st = (TPaveStats*)gPad->GetPrimitive(
"stats1");
267 if (st) st->SetLineColor(kBlack);
274 text.SetTextSize(0.03);
275 text.SetTextAlign(22);
276 TString
page(
"page ");
285 const int maxchars = 120;
287 text.SetTextColor(kBlue);
289 text.DrawTextNDC(0.5,0.93,
s.substr(
max(0,
int(
s.size()-maxchars))).c_str());
292 text.SetTextColor(kRed);
294 text.DrawTextNDC(0.5,0.96,
s.substr(
max(0,
int(
s.size()-maxchars))).c_str());
305 if (hdiff)
delete hdiff;
308 else if (
obj->IsA()->InheritsFrom(
"TEfficiency")) {
309 auto h = (TEfficiency*)
obj.get();
310 auto href = (TEfficiency*)refObj;
317 else m_noMatch.push_back(keyPath.Data());
326 cout <<
"Invalid file name" << endl;
332 cout <<
"Cannot open reference file " <<
filename << endl;
346 cout <<
"Invalid file name" << endl;
352 cout <<
"Cannot open file " <<
filename << endl;
363 cout <<
"Invalid file name" << endl;
372 if (
m_can==0)
return;
375 if (TString(
filename).EndsWith(
".ps"))
387 cout <<
"Comparing " <<
h.GetName() <<
" using ";
391 if (
verbose()) cout <<
"BIN: ";
393 if (
h.GetNbinsX()!=
href.GetNbinsX() ||
394 h.GetNbinsY()!=
href.GetNbinsY() ||
395 h.GetNbinsZ()!=
href.GetNbinsZ()) {
396 cout <<
h.GetName() <<
" has different number of bins: ("
397 <<
h.GetNbinsX() <<
"," <<
h.GetNbinsY() <<
"," <<
h.GetNbinsZ() <<
") vs ("
398 <<
href.GetNbinsX() <<
"," <<
href.GetNbinsY() <<
"," <<
href.GetNbinsZ() <<
")" << endl;
402 for (Int_t
z=1;
z<=
h.GetNbinsZ() &&
result;
z++) {
403 for (Int_t
y=1;
y<=
h.GetNbinsY() &&
result;
y++) {
404 for (Int_t
x=1;
x<=
h.GetNbinsX() &&
result;
x++) {
405 Double_t binDiff = fabs(
h.GetBinContent(
x,
y,
z)-
href.GetBinContent(
x,
y,
z));
414 if (
verbose()) cout <<
"AXIS: ";
415 const TAxis *
xa(
h.GetXaxis()), *xaref(
href.GetXaxis());
416 const TAxis *ya(
h.GetXaxis()), *yaref(
href.GetXaxis());
417 const TAxis *za(
h.GetXaxis()), *zaref(
href.GetXaxis());
418 if(
xa->GetNbins() != xaref->GetNbins() )
result = kFALSE;
419 if(
result && (ya->GetNbins() != yaref->GetNbins()) )
result = kFALSE;
420 if(
result && (za->GetNbins() != zaref->GetNbins()) )
result = kFALSE;
432 if (
verbose()) cout <<
"CHI2: ";
435 if (
h.GetEntries()==0 &&
href.GetEntries()==0)
result = kTRUE;
436 else if (
h.Integral()==0 &&
href.Integral()==0)
result = kTRUE;
437 else if (
h.Integral()*
href.Integral()==0)
result = kFALSE;
450 cout <<
"ERROR: Invalid algorithm." << endl;
460 if (
h.GetXaxis()->IsAlphanumeric()) {
461 h.GetXaxis()->LabelsOption(
"a");
462 h.LabelsDeflate(
"X");
464 if (
h.GetYaxis()->IsAlphanumeric()) {
465 h.GetYaxis()->LabelsOption(
"a");
466 h.LabelsDeflate(
"Y");
473 if ((
f==0) || (dirpath==0))
return;
477 TObjArray*
a =
s.Tokenize(
"/");
478 for (
int i=0;
i<
a->GetEntries();
i++) {
479 const char*
dir =
a->At(
i)->GetName();