File indexing completed on 2026-05-23 08:12:15
0001 #include "analysisHelper.h"
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 TH2D* SubMatrix(TH2D* hFull,
0038 const std::vector<int>& recoSel,
0039 const std::vector<int>& trueSel,
0040 const char* name, const char* title,
0041 const char* xlbl, const char* ylbl)
0042 {
0043 int nX = (int)recoSel.size();
0044 int nY = (int)trueSel.size();
0045 TH2D* hSub = new TH2D(name, title, nX, 0, nX, nY, 0, nY);
0046 hSub->GetXaxis()->SetTitle(xlbl);
0047 hSub->GetYaxis()->SetTitle(ylbl);
0048 hSub->SetDirectory(0);
0049 for (int ix = 0; ix < nX; ++ix)
0050 for (int iy = 0; iy < nY; ++iy)
0051 hSub->SetBinContent(ix+1, iy+1,
0052 hFull->GetBinContent(recoSel[ix], trueSel[iy]));
0053 return hSub;
0054 }
0055
0056
0057
0058 void DrawMatrix(TH2D* h, const char* ztitle = "cross-section weight")
0059 {
0060 h->GetZaxis()->SetTitle(ztitle);
0061 gPad->SetLogz(h->GetMaximum() > 0);
0062 gPad->SetRightMargin(0.15);
0063 gPad->SetBottomMargin(0.20);
0064 gPad->SetLeftMargin(0.20);
0065 h->Draw("COLZ");
0066 gPad->Update();
0067 if (h->GetNbinsX() == h->GetNbinsY()) {
0068 double xlo = gPad->GetUxmin(), xhi = gPad->GetUxmax();
0069 double ylo = gPad->GetUymin(), yhi = gPad->GetUymax();
0070 TLine* diag = new TLine(xlo, ylo, xhi, yhi);
0071 diag->SetLineColor(kRed); diag->SetLineWidth(1);
0072 diag->SetLineStyle(2); diag->Draw();
0073 }
0074 }
0075
0076
0077 void drawResponse(const char* outDir = ".",
0078 const char* respFile = nullptr,
0079 Mode mode = Mode::kFull,
0080 int kDphi = 0,
0081 int iLsel = 2,
0082 int iSsel = 1,
0083 int iPwsel = 5)
0084 {
0085
0086 if (iLsel < 0 || iLsel >= nTrueLead) {
0087 std::cerr << "iLsel out of range [0," << nTrueLead-1 << "]\n"; return; }
0088 if (iSsel < 0 || iSsel >= nTrueSubl) {
0089 std::cerr << "iSsel out of range [0," << nTrueSubl-1 << "]\n"; return; }
0090 if (iPwsel < 0 || iPwsel >= nPairWeight) {
0091 std::cerr << "iPwsel out of range [0," << nPairWeight-1 << "]\n"; return; }
0092 if (TrueFlatIndex(iLsel, iSsel) < 0) {
0093 std::cerr << "iLsel/iSsel is a kinematically forbidden (iL,iS) pair\n"; return; }
0094
0095 gROOT->SetBatch(true);
0096 gStyle->SetOptStat(0);
0097 gStyle->SetPalette(kBird);
0098
0099 const std::string label = ModeLabel(mode);
0100 const std::string plotDir = std::format("{}/Plots", outDir);
0101
0102
0103 if (!respFile) { std::cerr << "respFile is required\n"; return; }
0104 TFile* fIn = TFile::Open(respFile, "READ");
0105 if (!fIn || fIn->IsZombie()) {
0106 std::cerr << "Cannot open " << respFile << "\n"; return; }
0107
0108 RooUnfoldResponse* resp = (RooUnfoldResponse*)fIn->Get(
0109 std::format("response_wEEC3D_{}", kDphi).c_str());
0110 if (!resp) {
0111 std::cerr << "Cannot find response_wEEC3D_" << kDphi << "\n"; return; }
0112
0113 TH2D* hFull = (TH2D*)resp->Hresponse();
0114 if (!hFull) {
0115 std::cerr << "Response has no internal TH2D\n"; return; }
0116 hFull = (TH2D*)hFull->Clone("hFull"); hFull->SetDirectory(0);
0117
0118
0119 auto leadLbl = [](int iL) {
0120 return std::format("{:.0f}-{:.0f} GeV",
0121 trueLeadPtBins[iL], trueLeadPtBins[iL+1]); };
0122 auto sublLbl = [](int iS) {
0123 return std::format("{:.0f}-{:.0f} GeV",
0124 trueSublPtBins[iS], trueSublPtBins[iS+1]); };
0125 auto pwLbl = [](int iPw) {
0126 return std::format("{:.3g}-{:.3g}",
0127 pairWeightBins[iPw], pairWeightBins[iPw+1]); };
0128
0129 const std::string dphiLbl = std::format(
0130 "#Delta#phi bin {} ({:.2f}-{:.2f})",
0131 kDphi, dPhiBins[kDphi], dPhiBins[kDphi+1]);
0132
0133
0134
0135
0136
0137
0138 std::vector<int> recoSel1, trueSel1;
0139 for (int iF = 0; iF < nRecoFlat3D(); ++iF) {
0140 int iL, iS, iPw; RecoFlat3DToIJK(iF, iL, iS, iPw);
0141 if (iL == iLsel) recoSel1.push_back(iF + 1);
0142 }
0143 for (int iF = 0; iF < nTrueFlat3D(); ++iF) {
0144 int iL, iS, iPw; TrueFlat3DToIJK(iF, iL, iS, iPw);
0145 if (iL == iLsel) trueSel1.push_back(iF + 1);
0146 }
0147
0148
0149 std::vector<int> recoSel2, trueSel2;
0150 for (int iPw = 0; iPw < nPairWeight; ++iPw) {
0151 int iF = RecoFlat3DIndex(iLsel, iSsel, iPw);
0152 if (iF >= 0) recoSel2.push_back(iF + 1);
0153 }
0154 for (int iPw = 0; iPw < nPairWeight; ++iPw) {
0155 int iF = TrueFlat3DIndex(iLsel, iSsel, iPw);
0156 if (iF >= 0) trueSel2.push_back(iF + 1);
0157 }
0158
0159
0160
0161
0162 int truthCell = TrueFlat3DIndex(iLsel, iSsel, iPwsel) + 1;
0163 int recoCell = RecoFlat3DIndex(iLsel, iSsel, iPwsel) + 1;
0164
0165
0166 TH1D* hCol = new TH1D("hCol",
0167 std::format("Truth ({},{},{}) #rightarrow reco migration;reco flat3D bin;weight",
0168 iLsel, iSsel, iPwsel).c_str(),
0169 hFull->GetNbinsX(), 0, hFull->GetNbinsX());
0170 hCol->SetDirectory(0);
0171 for (int ib = 1; ib <= hFull->GetNbinsX(); ++ib)
0172 hCol->SetBinContent(ib, hFull->GetBinContent(ib, truthCell));
0173
0174
0175 TH1D* hRow = new TH1D("hRow",
0176 std::format("Reco ({},{},{}) #leftarrow truth sources;truth flat3D bin;weight",
0177 iLsel, iSsel, iPwsel).c_str(),
0178 hFull->GetNbinsY(), 0, hFull->GetNbinsY());
0179 hRow->SetDirectory(0);
0180 for (int ib = 1; ib <= hFull->GetNbinsY(); ++ib)
0181 hRow->SetBinContent(ib, hFull->GetBinContent(recoCell, ib));
0182
0183
0184 auto outName = [&](int lvl) {
0185 return std::format("{}/response_level{}-{}.pdf", plotDir, lvl, label); };
0186
0187
0188
0189
0190 {
0191 TCanvas* c0 = new TCanvas("cL0", "Level 0: full response matrix", 1000, 900);
0192 c0->SetRightMargin(0.15);
0193 c0->SetBottomMargin(0.15);
0194 c0->SetLeftMargin(0.15);
0195
0196 TH2D* hL0 = (TH2D*)hFull->Clone("hL0");
0197 hL0->SetTitle(
0198 std::format("Full response matrix | {};reco flat3D;truth flat3D",
0199 dphiLbl).c_str());
0200 hL0->GetXaxis()->SetTitle("reco flat3D [lead #times subl #times pair weight]");
0201 hL0->GetYaxis()->SetTitle("truth flat3D [lead #times subl #times pair weight]");
0202 DrawMatrix(hL0);
0203
0204
0205
0206
0207 auto drawBoundaries = [&](bool isTruth) {
0208 int nBins = isTruth ? nTrueFlat3D() : nRecoFlat3D();
0209 int nTotal = isTruth ? nTrueFlat3D() : nRecoFlat3D();
0210 int prev = -1, curL = -1;
0211 for (int iF = 0; iF < nBins; ++iF) {
0212 int iL, iS, iPw;
0213 if (isTruth) TrueFlat3DToIJK(iF, iL, iS, iPw);
0214 else RecoFlat3DToIJK(iF, iL, iS, iPw);
0215 if (iL != curL) {
0216 if (curL >= 0) {
0217
0218 TLine* l = isTruth
0219 ? new TLine(0, iF, nRecoFlat3D(), iF)
0220 : new TLine(iF, 0, iF, nTrueFlat3D());
0221 l->SetLineColor(kWhite); l->SetLineWidth(1);
0222 l->SetLineStyle(2); l->Draw();
0223 }
0224 curL = iL;
0225 }
0226 }
0227 };
0228 drawBoundaries(false);
0229 drawBoundaries(true);
0230
0231
0232 {
0233
0234 auto labelLeadBins = [&](TAxis* ax, bool isTruth) {
0235 int nBins = isTruth ? nTrueFlat3D() : nRecoFlat3D();
0236 int prevL = -1, blockStart = 0;
0237 for (int iF = 0; iF <= nBins; ++iF) {
0238 int iL = -1;
0239 if (iF < nBins) {
0240 int iS, iPw;
0241 if (isTruth) TrueFlat3DToIJK(iF, iL, iS, iPw);
0242 else RecoFlat3DToIJK(iF, iL, iS, iPw);
0243 }
0244 if (iL != prevL) {
0245 if (prevL >= 0) {
0246 int mid = (blockStart + iF) / 2;
0247 ax->SetBinLabel(mid + 1,
0248 std::format("{:.0f}-{:.0f}",
0249 trueLeadPtBins[prevL],
0250 trueLeadPtBins[prevL+1]).c_str());
0251 }
0252 blockStart = iF;
0253 prevL = iL;
0254 }
0255 }
0256 };
0257 labelLeadBins(hL0->GetXaxis(), false);
0258 labelLeadBins(hL0->GetYaxis(), true);
0259 hL0->GetXaxis()->LabelsOption("h");
0260 hL0->GetYaxis()->LabelsOption("h");
0261 hL0->GetXaxis()->SetLabelSize(0.03);
0262 hL0->GetYaxis()->SetLabelSize(0.03);
0263 }
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298 gPad->Update();
0299 c0->Print(outName(0).c_str());
0300 std::cout << "Written: " << outName(0) << "\n";
0301 delete c0;
0302 }
0303
0304
0305
0306
0307 {
0308 TCanvas* c1 = new TCanvas("cL1", "Level 1: lead pT slice", 900, 800);
0309 c1->SetRightMargin(0.15);
0310 c1->SetBottomMargin(0.22);
0311 c1->SetLeftMargin(0.22);
0312
0313 TH2D* hL1 = SubMatrix(hFull, recoSel1, trueSel1, "hL1",
0314 std::format("Lead pT = {} | {}",
0315 leadLbl(iLsel), dphiLbl).c_str(),
0316 "", "");
0317 hL1->GetXaxis()->SetTitle("reco subl p_{T} bin");
0318 hL1->GetYaxis()->SetTitle("truth subl p_{T} bin");
0319 DrawMatrix(hL1);
0320
0321
0322
0323 auto labelSublBins = [&](TAxis* ax, const std::vector<int>& sel, bool isTruth) {
0324 int n = (int)sel.size();
0325 int prevS = -1, blockStart = 0;
0326 for (int i = 0; i <= n; ++i) {
0327 int curS = -1;
0328 if (i < n) {
0329 int iL, iS, iPw;
0330 if (isTruth) TrueFlat3DToIJK(sel[i]-1, iL, iS, iPw);
0331 else RecoFlat3DToIJK(sel[i]-1, iL, iS, iPw);
0332 curS = iS;
0333 }
0334 if (curS != prevS) {
0335 if (prevS >= 0) {
0336 int mid = (blockStart + i) / 2;
0337 ax->SetBinLabel(mid + 1,
0338 std::format("{:.0f}-{:.0f}",
0339 trueSublPtBins[prevS],
0340 trueSublPtBins[prevS+1]).c_str());
0341 }
0342 blockStart = i;
0343 prevS = curS;
0344 }
0345 }
0346 ax->LabelsOption("h");
0347 ax->SetLabelSize(0.03);
0348 };
0349 labelSublBins(hL1->GetXaxis(), recoSel1, false);
0350 labelSublBins(hL1->GetYaxis(), trueSel1, true);
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383 c1->Print(outName(1).c_str());
0384 std::cout << "Written: " << outName(1) << "\n";
0385 delete c1;
0386 }
0387
0388
0389
0390
0391 {
0392 TCanvas* c2 = new TCanvas("cL2", "Level 2: dijet pT slice", 800, 750);
0393 c2->SetRightMargin(0.15);
0394 c2->SetBottomMargin(0.28);
0395 c2->SetLeftMargin(0.28);
0396
0397 TH2D* hL2 = SubMatrix(hFull, recoSel2, trueSel2, "hL2",
0398 std::format("Lead {} / Subl {} | {}",
0399 leadLbl(iLsel), sublLbl(iSsel), dphiLbl).c_str(),
0400 "", "");
0401 hL2->GetXaxis()->SetTitle("reco pair weight bin");
0402 hL2->GetYaxis()->SetTitle("truth pair weight bin");
0403
0404
0405 auto labelPWBins = [&](TAxis* ax, const std::vector<int>& sel, bool isTruth) {
0406 ax->SetLabelSize(0.025);
0407 for (int i = 0; i < (int)sel.size(); ++i) {
0408 int iL, iS, iPw;
0409 if (isTruth) TrueFlat3DToIJK(sel[i]-1, iL, iS, iPw);
0410 else RecoFlat3DToIJK(sel[i]-1, iL, iS, iPw);
0411 ax->SetBinLabel(i + 1,
0412 std::format("{:.2g}-{:.2g}",
0413 pairWeightBins[iPw], pairWeightBins[iPw+1]).c_str());
0414 }
0415 ax->LabelsOption("v");
0416 };
0417 labelPWBins(hL2->GetXaxis(), recoSel2, false);
0418 labelPWBins(hL2->GetYaxis(), trueSel2, true);
0419 DrawMatrix(hL2);
0420
0421 c2->Print(outName(2).c_str());
0422 std::cout << "Written: " << outName(2) << "\n";
0423 delete c2;
0424 }
0425
0426
0427
0428
0429 {
0430 TCanvas* c3 = new TCanvas("cL3", "Level 3: single cell", 1400, 600);
0431 c3->Divide(2, 1);
0432
0433
0434 c3->cd(1);
0435 gPad->SetLogy(hCol->GetMaximum() > 0);
0436 gPad->SetLeftMargin(0.15); gPad->SetBottomMargin(0.12);
0437 hCol->SetFillColor(kAzure+7); hCol->SetLineColor(kAzure+9);
0438 hCol->Draw("HIST");
0439 TLatex tx3; tx3.SetNDC(); tx3.SetTextSize(0.038);
0440 tx3.DrawLatex(0.17, 0.93,
0441 std::format("Truth ({},{},{}) #rightarrow reco",
0442 iLsel, iSsel, iPwsel).c_str());
0443 tx3.DrawLatex(0.17, 0.87,
0444 std::format("Lead {} Subl {} PW {}",
0445 leadLbl(iLsel), sublLbl(iSsel), pwLbl(iPwsel)).c_str());
0446 tx3.DrawLatex(0.17, 0.81, dphiLbl.c_str());
0447
0448
0449 c3->cd(2);
0450 gPad->SetLogy(hRow->GetMaximum() > 0);
0451 gPad->SetLeftMargin(0.15); gPad->SetBottomMargin(0.12);
0452 hRow->SetFillColor(kOrange-3); hRow->SetLineColor(kOrange+2);
0453 hRow->Draw("HIST");
0454 TLatex tx4; tx4.SetNDC(); tx4.SetTextSize(0.038);
0455 tx4.DrawLatex(0.17, 0.93,
0456 std::format("Reco ({},{},{}) #leftarrow truth",
0457 iLsel, iSsel, iPwsel).c_str());
0458 tx4.DrawLatex(0.17, 0.87,
0459 std::format("Lead {} Subl {} PW {}",
0460 leadLbl(iLsel), sublLbl(iSsel), pwLbl(iPwsel)).c_str());
0461 tx4.DrawLatex(0.17, 0.81, dphiLbl.c_str());
0462
0463 c3->Print(outName(3).c_str());
0464 std::cout << "Written: " << outName(3) << "\n";
0465 delete c3;
0466 }
0467
0468 fIn->Close(); delete fIn;
0469 }