void GetMinMax(TH1* h, Double_t& ymin, Double_t& ymax) { ymax = -1e30; ymin = 1e30; for (Int_t i = 1; i <= h->GetNbinsX(); i++) { Double_t y = h->GetBinContent(i); ymax = TMath::Max(ymax,y); if (y > 0) ymin = TMath::Min(ymin,y); } } Bool_t LogScale(TH1* h) { Double_t ymin, ymax; GetMinMax(h, ymin, ymax); if (ymin > ymax) return false; return (ymax > ymin * 1000); } void CompareTrees(TTree* mine, TTree* dev, TDirectory* ret, TCanvas* canvas) { TDirectory* sub = ret->mkdir(mine->GetName()); auto mineL = mine->GetListOfBranches(); Int_t ncol = mineL->GetEntriesFast() > 10 ? 3 : 2; Int_t nrow = (mineL->GetEntriesFast() + ncol-1) / ncol; canvas->Clear(); canvas->Divide(ncol, nrow); canvas->Draw(); TVirtualPad* pad = 0; Int_t ipad = 1; Int_t mineN = mine->GetEntries(); Int_t devN = dev ->GetEntries(); if (mineN != devN) { Warning(mine->GetName(), "Inconsistent selected %d (mine) vs %d (dev)", mineN, devN); } sub->cd(); for (auto ob : *mineL) { TBranch* mineB = static_cast(ob); TObject* db = dev->GetListOfBranches()->FindObject(mineB->GetName()); if (not db) { Warning(mineB->GetName(),"Branch not in dev %s", dev->GetName()); continue; } TBranch* devB = static_cast(db); Info(""," %s/%s", mine->GetName(), mineB->GetName()); mine->Draw(Form("%s>>hmine",mineB->GetName()),"","goff"); dev ->Draw(Form("%s>>hdev", devB ->GetName()),"","goff"); mineN = mine->GetSelectedRows(); devN = dev ->GetSelectedRows(); Double_t* mineX = mine->GetV1(); Double_t* devX = dev ->GetV1(); Int_t nDiff = 0; Int_t diff1 = -1; for (size_t i = 0; i < TMath::Min(mineN,devN); i++) { if (TMath::Abs((mineX[i] - devX[i]) / devX[i]) > 0.001) { nDiff++; // Info(mineB->GetName(), " %8d: %g vs %g", // i, mineX[i], devX[i]); if (diff1 >= 0) continue; diff1 = i; } } if (nDiff > 0) Warning(mineB->GetName(), "%d values differ, starting at %d", nDiff, diff1); TH1* mineH = static_cast(sub->Get("hmine")); TH1* devH = static_cast(sub->Get("hdev")); if ((mineH and not devH) or (not mineH and devH)) { Warning(mineB->GetName(),"One histogram is missing %p %p", mineH, devH); continue; } if (not mineH and not devH) { // Warning(mineB->GetName(),"No histograms"); continue; } mineH->SetName(mineB->GetName()); mineH->SetTitle("Mine"); mineH->SetLineColor(kRed+1); mineH->SetFillColor(kRed+1); mineH->SetMarkerColor(kRed+1); mineH->SetMarkerStyle(20); devH ->SetName(devB->GetName()); devH ->SetTitle("Dev"); devH ->SetLineColor (kBlue+1); devH ->SetFillColor (kBlue+1); devH ->SetMarkerColor(kBlue+1); devH ->SetMarkerStyle(25); devH ->SetMarkerSize(1.2); THStack* stack = new THStack(mineB->GetName(), mineB->GetName()); stack->Add(mineH); stack->Add(devH); stack->Write(); pad = canvas->cd(ipad); stack->Draw("no stack ep"); TH1* h = stack->GetHistogram(); if (LogScale(mineH) or LogScale(devH)) pad->SetLogy(); pad->BuildLegend(); ipad++; } } void CompareAO2D() { TFile* mineFile = TFile::Open("mine/AO2D.root","READ"); TFile* devFile = TFile::Open("dev/AO2D.root", "READ"); TFile* output = TFile::Open("compare.root","RECREATE"); TDirectory* mineDF = mineFile->GetDirectory("DF_1"); TDirectory* devDF = devFile->GetDirectory("DF_1"); Printf("%p %p", mineDF, devDF); TCanvas* canvas = new TCanvas("compare","Compare AODs",600,800); canvas->Print(Form("%s.pdf[",canvas->GetName())); for (auto key : *mineDF->GetListOfKeys()) { Info("","%s",key->GetName()); TObject* mineO = static_cast(key)->ReadObj(); if (not mineO) { Warning(key->GetName(),"Gave up on this"); continue; } if (not mineO->InheritsFrom(TTree::Class())) { Warning(mineO->GetName(),"Not a TTree"); continue; } TObject* devO = devDF->Get(mineO->GetName()); if (not devO) { if (not TString(mineO->GetName()).BeginsWith("O2hepmc")) Warning(mineO->GetName(), "Object not found in dev output"); continue; } if (not devO->InheritsFrom(TTree::Class())) { Warning(devO->GetName(),"Is not a TTree"); continue; } TTree* mineT = static_cast(mineO); TTree* devT = static_cast(devO); CompareTrees(mineT,devT,output, canvas); canvas->Print(Form("%s.pdf",canvas->GetName()), Form("Title: %s", mineT->GetName())); } canvas->Print(Form("%s.pdf]",canvas->GetName())); output->Write(); }