File indexing completed on 2025-12-16 09:18:01
0001 #include <TFile.h>
0002 #include <TTree.h>
0003 #include <TH1.h>
0004 #include <TH2.h>
0005 #include <TNtuple.h>
0006
0007 #include <TLorentzVector.h>
0008
0009 #include <cmath>
0010 #include <string>
0011 #include <vector>
0012
0013 const float electron_mass = 0.000511;
0014 const float pion_mass = 0.1396;
0015
0016 void analyze_SiSeedPair(
0017
0018
0019
0020
0021
0022
0023 const std::string& filename="/sphenix/tg/tg01/commissioning/INTT/work/hachiya/SiCaloTrack/data/ana_em/all_em.root",
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 float phi_threshold = 0.05
0034 )
0035 {
0036 TFile *f = TFile::Open(filename.c_str(), "READ");
0037
0038 TTree *trackTree = (TTree *)f->Get("trackTree");
0039 TTree *caloTree = (TTree *)f->Get("caloTree");
0040 TTree *siClusTree = (TTree *)f->Get("SiClusTree");
0041 TTree *truthTree = (TTree *)f->Get("truthTree");
0042
0043 int evt;
0044 std::vector<float> *track_phi = 0, *track_pt = 0, *track_pz = 0, *track_eta = 0, *track_z = 0;
0045 std::vector<float> *track_chi2ndf= 0;
0046 std::vector<int> *track_charge = 0, *track_nmaps = 0, *track_nintt = 0;
0047 std::vector<float> *track_phi_emc= 0, *track_z_emc = 0;
0048
0049 int calo_evt;
0050 std::vector<float> *calo_phi = 0, *calo_energy = 0;
0051 std::vector<float> *calo_x = 0, *calo_y = 0, *calo_z = 0;
0052 std::vector<float> *calo_chi2 = 0, *calo_prob = 0;
0053
0054
0055 std::vector<float>* truth_pt=0, *truth_eta=0, *truth_phi=0;
0056 std::vector<float> *truth_pz = 0;
0057
0058
0059
0060 std::vector<int> *SiClus_trackid=0;
0061 std::vector<int> *SiClus_layer=0;
0062 std::vector<float> *SiClus_x=0;
0063 std::vector<float> *SiClus_y=0;
0064 std::vector<float> *SiClus_z=0;
0065
0066
0067
0068 trackTree->SetBranchAddress("evt", &evt);
0069 trackTree->SetBranchAddress("chi2ndf", &track_chi2ndf);
0070 trackTree->SetBranchAddress("charge", &track_charge);
0071 trackTree->SetBranchAddress("nmaps", &track_nmaps);
0072 trackTree->SetBranchAddress("nintt", &track_nintt);
0073 trackTree->SetBranchAddress("pt0", &track_pt);
0074 trackTree->SetBranchAddress("pz0", &track_pz);
0075 trackTree->SetBranchAddress("eta0", &track_eta);
0076 trackTree->SetBranchAddress("phi0", &track_phi);
0077 trackTree->SetBranchAddress("z0", &track_z);
0078 trackTree->SetBranchAddress("phi_proj_emc", &track_phi_emc);
0079 trackTree->SetBranchAddress("z_proj_emc", &track_z_emc);
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091 if(truthTree!=nullptr){
0092 truthTree->SetBranchAddress("truth_pt", &truth_pt);
0093 truthTree->SetBranchAddress("truth_pz", &truth_pz);
0094 truthTree->SetBranchAddress("truth_eta", &truth_eta);
0095 truthTree->SetBranchAddress("truth_phi", &truth_phi);
0096 }
0097
0098
0099
0100
0101
0102
0103
0104
0105 siClusTree->SetBranchAddress("Siclus_trackid", &SiClus_trackid);
0106 siClusTree->SetBranchAddress("Siclus_layer", &SiClus_layer);
0107 siClusTree->SetBranchAddress("Siclus_x", &SiClus_x);
0108 siClusTree->SetBranchAddress("Siclus_y", &SiClus_y);
0109 siClusTree->SetBranchAddress("Siclus_z", &SiClus_z);
0110
0111
0112
0113 caloTree->SetBranchAddress("calo_evt", &calo_evt);
0114 caloTree->SetBranchAddress("phi", &calo_phi);
0115 caloTree->SetBranchAddress("x", &calo_x);
0116 caloTree->SetBranchAddress("y", &calo_y);
0117 caloTree->SetBranchAddress("z", &calo_z);
0118 caloTree->SetBranchAddress("energy", &calo_energy);
0119 caloTree->SetBranchAddress("chi2", &calo_chi2);
0120 caloTree->SetBranchAddress("prob", &calo_prob);
0121
0122
0123
0124
0125 TFile *outFile = new TFile("dphi_distribution.root", "RECREATE");
0126 TH1F *h_dphi = new TH1F("h_dphi", "Track - Calo #Delta#phi;#Delta#phi;Counts", 200, -0.3, 0.3);
0127 TH1F *h_dphi_emc = new TH1F("h_dphi (EMCal Proj)", "Track - Calo #Delta#phi;#Delta#phi;Counts", 200, -0.3, 0.3);
0128 TH2F *h_dphi_emc_pt = new TH2F("h_dphi_pt", "Track - Calo #Delta#phi;pT;#Delta#phi", 200, 0, 20, 200, -0.3, 0.3);
0129 TH2F *h_dphi_emc_pt_truth = new TH2F("h_dphi_pt_truth", "Track - Calo #Delta#phi;pT{true};#Delta#phi", 200, 0, 20, 200, -0.3, 0.3);
0130 TH1F *h_EoverP_all = new TH1F("h_EoverP_all", "E/p of matched track-calo;E/p;Counts", 100, 0, 5);
0131 TH1F *h_EoverP_cut = new TH1F("h_EoverP_cut", "E/p of matched track-calo phi cut;E/p;Counts", 100, 0, 5);
0132 TH1F *h_dz = new TH1F("h_dz", "Track - Calo #Delta z;#Delta z (cm);Counts", 200, -50, 50);
0133 TH1F *h_dz_emc = new TH1F("h_dz_emc", "Track(EMCal Proj) - Calo #Delta z;#Delta z (cm);Counts", 200, -50, 50);
0134
0135 TH1F *h_mass = new TH1F("h_mass", "Invariant mass of matched track pairs (e^{+}e^{-});Mass (GeV/c^{2});Counts", 200, 0, 5);
0136
0137 TH1F *h_mass_pt0_1 = new TH1F("h_mass_pt0_1", "Invariant mass (pT 0-1 GeV/c);Mass (GeV/c^{2});Counts", 200, 0, 5);
0138 TH1F *h_mass_pt1_2 = new TH1F("h_mass_pt1_2", "Invariant mass (pT 1-2 GeV/c);Mass (GeV/c^{2});Counts", 200, 0, 5);
0139 TH1F *h_mass_pt2_3 = new TH1F("h_mass_pt2_3", "Invariant mass (pT 2-3 GeV/c);Mass (GeV/c^{2});Counts", 200, 0, 5);
0140 TH1F *h_mass_pt3_4 = new TH1F("h_mass_pt3_4", "Invariant mass (pT 3-4 GeV/c);Mass (GeV/c^{2});Counts", 200, 0, 5);
0141 TH1F *h_mass_pt4up = new TH1F("h_mass_pt4up", "Invariant mass (pT >4 GeV/c);Mass (GeV/c^{2});Counts", 200, 0, 5);
0142 TH1F *h_track_chi2ndf_matched = new TH1F("h_track_chi2ndf_matched", "Chi2/NDF of matched tracks;#chi^{2}/ndf;Counts", 100, 0, 10);
0143
0144 TH2F *h_reco_vs_truth_pt = new TH2F("h_reco_vs_truth_pt", "Reconstructed pT vs Truth pT;Truth pT (GeV/c);Reconstructed pT (GeV/c)", 100, 0, 20, 100, 0, 20);
0145
0146 TNtuple *h_ntp_sicalo = new TNtuple("ntp_sicalo", "SiSeed + Calo combination", "pt:pz:c:chi2:nintt:nmaps:hitbit:eta:the:phi:z:phi_pemc:z_pemc:phi_intt:pt_tr:pz_tr:phi_tr:phi_emc:z_emc:e_emc:chi2_emc:phi_calo:pt_calo");
0147
0148 TNtuple *h_ntp_sicalotrk = new TNtuple("ntp_sicalotrk", "SiSeed + Calo combination", "pt:pz:c:chi2:nintt:nmaps:hitbit:eta:the:phi:z:phi_pemc:z_pemc:phi_intt:pt_tr:pz_tr:phi_tr:phi_emc:z_emc:e_emc:chi2_emc:phi_calo:pt_calo");
0149
0150 TNtuple *h_ntp_pair = new TNtuple("ntp_pair", "pair", "mass:pt:phi:eta:massc:ptc:ptp:pzp:eopp:dpp:dzp:ptm:pzm:eopm:dpm:dzm");
0151
0152
0153
0154 struct MatchedTrack {
0155 size_t track_idx;
0156 size_t calo_idx;
0157 float min_dphi;
0158 float min_dphi_emc;
0159 float min_dz;
0160 float min_dz_emc;
0161 float eop;
0162 float pt_calo;
0163 float eop_calo;
0164 int nmaps;
0165 int nintt;
0166 int charge;
0167 float chi2ndf;
0168 };
0169
0170 struct stCluster {
0171 int m_clsTrkid;
0172 int m_clslyr ;
0173 float m_clsx ;
0174 float m_clsy ;
0175 float m_clsz ;
0176 };
0177
0178
0179 Long64_t nentries = trackTree->GetEntries();
0180
0181 int nskip=0;
0182
0183 for (Long64_t i = 0; i < nentries; ++i)
0184 {
0185
0186 trackTree->GetEntry(i);
0187 caloTree->GetEntry(i);
0188 siClusTree->GetEntry(i);
0189 if(truthTree!=nullptr) truthTree->GetEntry(i);
0190
0191 if (evt != calo_evt)
0192 {
0193 std::cerr << "Warning: evt mismatch at entry " << i << ": track evt = " << evt << ", calo evt = " << calo_evt << std::endl;
0194 continue;
0195 }
0196
0197 if((evt%1000)==0) {
0198 std::cout << "Matching evt = " << evt << std::endl;
0199 }
0200
0201 std::vector<stCluster> vClus;
0202
0203
0204
0205 int nclusSize = SiClus_trackid->size();
0206
0207 cout<<evt <<" : ntrk, nemc : "<<track_phi->size()<<", "<< calo_phi->size()<< " "<<nclusSize<<endl;
0208 std::vector<MatchedTrack> matched_tracks;
0209
0210 int itotalClus=0;
0211
0212
0213 for (size_t it = 0; it < track_phi->size(); ++it)
0214 {
0215 int nmaps = (*track_nmaps)[it];
0216 int nintt = (*track_nintt)[it];
0217
0218 float& pt = ((*track_pt)[it]);
0219 float& pz = ((*track_pz)[it]);
0220 float& eta = ((*track_eta)[it]);
0221 int& charge = ((*track_charge)[it]);
0222
0223 int nclus = nmaps+nintt;
0224
0225
0226
0227 int hitbit=0;
0228 stCluster iCl, oCl;
0229 for(int ic=0; ic<nclus; ic++) {
0230 int clsid = ic+itotalClus;
0231
0232 int layer = ((*SiClus_layer)[clsid]);
0233 stCluster Cl {
0234 ((*SiClus_trackid)[clsid]),
0235 layer,
0236 ((*SiClus_x)[clsid]),
0237 ((*SiClus_y)[clsid]),
0238 ((*SiClus_z)[clsid])
0239 };
0240 vClus.push_back(Cl);
0241
0242 if(0<=Cl.m_clslyr&&Cl.m_clslyr<5) iCl = Cl;
0243 else oCl = Cl;
0244
0245 hitbit |= (1<<layer);
0246
0247
0248 }
0249 itotalClus+=nclus;
0250
0251
0252 float pt_tr=0, pz_tr=0, phi_tr=0, eta_tr=0;
0253
0254 if(truthTree!=nullptr){
0255 int ntruth = truth_pt->size();
0256 for (size_t itr = 0; itr < (ntruth>0?1:0); ++itr)
0257 {
0258 pt_tr = ((*truth_pt)[itr]);
0259 pz_tr = ((*truth_pz)[itr]);
0260 phi_tr = ((*truth_phi)[itr]);
0261 eta_tr = ((*truth_eta)[itr]);
0262 cout<<"tru : "<<itr<<" "<<pt_tr<<" "<<pz_tr<<" "<<phi_tr<<" "<<eta_tr<<endl;
0263 }
0264 }
0265
0266 if (pt < 0.3) continue;
0267
0268 if (nmaps < 1 || nintt < 1)
0269 {
0270 if(nskip<1000) {
0271 std::cout << "Skipping track with nmaps = " << nmaps << " and nintt = " << nintt << std::endl;
0272 } else if(nskip==1000) {
0273 std::cout << "exceed nskip. comment suppressed" << std::endl;
0274 }
0275 nskip++;
0276
0277 continue;
0278 }
0279
0280
0281
0282
0283
0284 float phi_intt = atan2(oCl.m_clsy-iCl.m_clsy, oCl.m_clsx-iCl.m_clsx);
0285
0286
0287
0288 float ntp_value[30] = {
0289 pt,
0290 pz,
0291 (float)(charge),
0292 (*track_chi2ndf)[it],
0293 (float)nintt,
0294 (float)nmaps,
0295 (float)hitbit,
0296 (*track_eta)[it],
0297 (float)(2.* std::atan( std::exp(-eta) )),
0298 (*track_phi)[it],
0299 (*track_z)[it],
0300 (*track_phi_emc)[it],
0301 (*track_z_emc)[it],
0302 phi_intt,
0303 pt_tr,
0304 pz_tr,
0305 phi_tr
0306 };
0307
0308
0309 const float par[2] = {0.21, -0.986};
0310
0311 float min_dr = 1e9;
0312 size_t min_ic = calo_phi->size();
0313 float min_dphi = 0, min_dphi_emc = 0, min_dz = 0, min_dz_emc = 0;
0314 float match_pt_calo=0;
0315
0316 for (size_t ic = 0; ic < calo_phi->size(); ++ic)
0317 {
0318
0319
0320 float dphi_emc = (*track_phi_emc)[it] - (*calo_phi)[ic];
0321 if (dphi_emc > M_PI) dphi_emc -= 2 * M_PI;
0322 if (dphi_emc < -M_PI) dphi_emc += 2 * M_PI;
0323
0324 const float p0 = -0.181669;
0325 const float p1 = 0.00389827;
0326
0327 float dphi_emc_corr = charge*dphi_emc - 0.18*std::pow(pt, -0.986);
0328
0329 float x_calo = (*calo_x)[ic];
0330 float y_calo = (*calo_y)[ic];
0331 float z_calo = (*calo_z)[ic];
0332
0333 float dz_emc = (*track_z_emc)[it] - z_calo;
0334
0335
0336 float phi_calo = atan2(y_calo - oCl.m_clsy, x_calo - oCl.m_clsx);
0337
0338 float dphi = phi_calo - phi_intt;
0339 float pt_calo = par[0]*pow(-charge*dphi, par[1]);
0340
0341 ntp_value[17] = (*calo_phi)[ic];
0342 ntp_value[18] = z_calo;
0343 ntp_value[19] = (*calo_energy)[ic];
0344 ntp_value[20] = (*calo_chi2)[ic];
0345 ntp_value[21] = phi_calo;
0346 ntp_value[22] = pt_calo;
0347
0348 h_ntp_sicalo->Fill(ntp_value);
0349
0350
0351
0352 if (fabs(dphi_emc) < min_dr)
0353
0354
0355 {
0356
0357
0358
0359 min_dr = fabs(dz_emc);
0360 min_ic = ic;
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371 }
0372 }
0373
0374 if (min_ic != calo_phi->size())
0375 {
0376 float x_calo = (*calo_x)[min_ic];
0377 float y_calo = (*calo_y)[min_ic];
0378 float z_calo = (*calo_z)[min_ic];
0379
0380 float phi_calo = atan2(y_calo - oCl.m_clsy, x_calo - oCl.m_clsx);
0381
0382 float dphi = phi_calo - phi_intt;
0383 float pt_calo = par[0]*pow(-charge*dphi, par[1]);
0384
0385 ntp_value[17] = (*calo_phi)[min_ic];
0386 ntp_value[18] = z_calo;
0387 ntp_value[19] = (*calo_energy)[min_ic];
0388 ntp_value[20] = (*calo_chi2)[min_ic];
0389 ntp_value[21] = phi_calo;
0390 ntp_value[22] = pt_calo;
0391 }
0392 else {
0393 ntp_value[17] = -9999.;
0394 ntp_value[18] = -9999.;
0395 ntp_value[19] = -9999.;
0396 ntp_value[20] = -9999.;
0397 ntp_value[21] = -9999.;
0398 ntp_value[22] = -9999.;
0399 }
0400 h_ntp_sicalotrk->Fill(ntp_value);
0401
0402 if (min_ic == calo_phi->size()) {
0403 continue;
0404 }
0405
0406 float p = (*track_pt)[it] * std::cosh((*track_eta)[it]);
0407 float E = (*calo_energy)[min_ic];
0408 float eop = -999;
0409 if (p > 0)
0410 {
0411 eop = E / p;
0412 h_EoverP_all->Fill(eop);
0413 }
0414 float p_calo = match_pt_calo * std::cosh((*track_eta)[it]);
0415 float eop_calo = E/p_calo;
0416
0417 h_dphi->Fill(min_dphi);
0418 h_dphi_emc->Fill(min_dphi_emc);
0419 h_dphi_emc_pt->Fill((*track_pt)[it], min_dphi_emc);
0420
0421 h_dz->Fill(min_dz);
0422 h_dz_emc->Fill(min_dz_emc);
0423
0424
0425 h_track_chi2ndf_matched->Fill((*track_chi2ndf)[it]);
0426 if ((*track_chi2ndf)[it] > 5)
0427 continue;
0428 if (min_dz_emc > 4)
0429 continue;
0430
0431
0432 matched_tracks.push_back({it, min_ic, min_dphi, min_dphi_emc, min_dz, min_dz_emc, eop, match_pt_calo, eop_calo, nmaps, nintt, (*track_charge)[it], (*track_chi2ndf)[it]});
0433 }
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449 cout<<"matched track : "<<matched_tracks.size()<<endl;
0450 float v_pair[20];
0451 for (size_t idx = 0; idx < matched_tracks.size(); ++idx)
0452 {
0453 const auto& mt = matched_tracks[idx];
0454
0455 if (mt.nmaps > 2 && mt.nintt > 1 && std::abs(mt.min_dz_emc) < 4)
0456 {
0457 h_EoverP_cut->Fill(mt.eop);
0458
0459 if (!(mt.eop > 0.6 && mt.eop < 2)) continue;
0460
0461 for (size_t jdx = idx+1; jdx < matched_tracks.size(); ++jdx)
0462 {
0463 const auto& mt2 = matched_tracks[jdx];
0464
0465
0466
0467
0468 if (mt2.nmaps > 2 && mt2.nintt > 1 && std::abs(mt2.min_dz_emc) < 4) {
0469
0470 if (mt.charge * mt2.charge >= 0) continue;
0471
0472
0473
0474
0475
0476
0477
0478 if (!(mt2.eop > 0.6 && mt2.eop < 2)) continue;
0479
0480 float pt1 = (*track_pt)[mt.track_idx], eta1 = (*track_eta)[mt.track_idx], phi1 = (*track_phi)[mt.track_idx];
0481 float pt2 = (*track_pt)[mt2.track_idx], eta2 = (*track_eta)[mt2.track_idx], phi2 = (*track_phi)[mt2.track_idx];
0482 TLorentzVector v1, v2;
0483 v1.SetPtEtaPhiM(pt1, eta1, phi1, electron_mass);
0484 v2.SetPtEtaPhiM(pt2, eta2, phi2, electron_mass);
0485
0486
0487
0488 TLorentzVector vpair = v1 + v2;
0489
0490
0491
0492 float mass = vpair.M();
0493 float total_pt = vpair.Pt();
0494
0495
0496 float ptc1 = mt.pt_calo;
0497 float ptc2 = mt2.pt_calo;
0498 TLorentzVector vc1, vc2;
0499 vc1.SetPtEtaPhiM(ptc1, eta1, phi1, electron_mass);
0500 vc2.SetPtEtaPhiM(ptc2, eta2, phi2, electron_mass);
0501
0502
0503 TLorentzVector vpairc = vc1 + vc2;
0504
0505 float massc = vpairc.M();
0506 float total_ptc = vpairc.Pt();
0507
0508
0509
0510 {
0511 h_mass->Fill(mass);
0512
0513
0514 if (total_pt < 1.0) {
0515 h_mass_pt0_1->Fill(mass);
0516 } else if (total_pt < 2.0) {
0517 h_mass_pt1_2->Fill(mass);
0518 } else if (total_pt < 3.0) {
0519 h_mass_pt2_3->Fill(mass);
0520 } else if (total_pt < 4.0) {
0521 h_mass_pt3_4->Fill(mass);
0522 } else {
0523 h_mass_pt4up->Fill(mass);
0524 }
0525 }
0526
0527
0528
0529
0530 v_pair[ 0] = mass;
0531 v_pair[ 1] = total_pt;
0532 v_pair[ 2] = vpair.Phi();
0533 v_pair[ 3] = vpair.Eta();
0534 v_pair[ 4] = massc;
0535 v_pair[ 5] = total_ptc;
0536 v_pair[ 6] = pt1;
0537 v_pair[ 7] = v1.Pz();
0538 v_pair[ 8] = mt.eop_calo;
0539 v_pair[ 9] = mt.min_dphi_emc;
0540 v_pair[10] = mt.min_dz_emc;
0541 v_pair[11] = pt2;
0542 v_pair[12] = v2.Pz();
0543 v_pair[13] = mt2.eop_calo;
0544 v_pair[15] = mt2.min_dphi_emc;
0545 v_pair[15] = mt2.min_dz_emc;
0546
0547 h_ntp_pair->Fill(v_pair);
0548 }
0549 }
0550 }
0551 }
0552 }
0553
0554 std::cout<<"total nskip : "<< nskip <<std::endl;
0555
0556
0557
0558 std::cout << "Saving histogram to dphi_distribution.root" << std::endl;
0559 h_dphi->Write();
0560 h_dphi_emc->Write();
0561 h_dphi_emc_pt->Write();
0562 h_dphi_emc_pt_truth->Write();
0563 h_EoverP_all->Write();
0564 h_EoverP_cut->Write();
0565 h_dz->Write();
0566 h_dz_emc->Write();
0567 h_mass->Write();
0568 h_mass_pt0_1->Write();
0569 h_mass_pt1_2->Write();
0570 h_mass_pt2_3->Write();
0571 h_mass_pt3_4->Write();
0572 h_mass_pt4up->Write();
0573 h_track_chi2ndf_matched->Write();
0574 h_reco_vs_truth_pt->Write();
0575 h_ntp_sicalo->Write();
0576 h_ntp_sicalotrk->Write();
0577 h_ntp_pair->Write();
0578
0579 outFile->Close();
0580
0581 std::cout << "Δφ histogram saved to 'dphi_distribution.root'" << std::endl;
0582 f->Close();
0583 }