Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:12:43

0001 #include "HFFastSim.h"
0002 
0003 #include <fun4all/Fun4AllReturnCodes.h>
0004 #include <fun4all/Fun4AllServer.h>
0005 #include <phool/getClass.h>
0006 
0007 #include <phool/PHCompositeNode.h>
0008 
0009 #include <phhepmc/PHGenIntegral.h>
0010 
0011 #include <TDatabasePDG.h>
0012 #include <TFile.h>
0013 #include <TH1.h>
0014 #include <TH2.h>
0015 #include <TH3.h>
0016 #include <TLorentzVector.h>
0017 #include <TString.h>
0018 #include <TTree.h>
0019 #include <g4jets/Jet.h>
0020 #include <g4jets/JetMap.h>
0021 
0022 #include <HepMC/GenEvent.h>
0023 #include <HepMC/GenRanges.h>
0024 #include <HepMC/GenVertex.h>
0025 #include <phhepmc/PHHepMCGenEvent.h>
0026 #include <phhepmc/PHHepMCGenEventMap.h>
0027 
0028 #include <gsl/gsl_const.h>
0029 
0030 #include <cassert>
0031 #include <cmath>
0032 #include <cstddef>
0033 #include <iostream>
0034 
0035 using namespace std;
0036 
0037 HFFastSim::HFFastSim(std::string filename, int flavor, int maxevent)
0038   : SubsysReco("HFFastSim")
0039   , _verbose(0)
0040   , _ievent(0)
0041   , _total_pass(0)
0042   , _f(nullptr)
0043   , _h2(nullptr)
0044   , _h2all(nullptr)
0045   , _h2_b(nullptr)
0046   , _h2_c(nullptr)
0047   , m_hNorm(nullptr)
0048   , m_DRapidity(nullptr)
0049   , m_tSingleD(nullptr)
0050   , m_singleD(nullptr)
0051   , m_tSingleLc(nullptr)
0052   , m_singleLc(nullptr)
0053   , _embedding_id(1)
0054 {
0055   _foutname = filename;
0056 
0057   _flavor = flavor;
0058 
0059   _maxevent = maxevent;
0060 
0061   _pt_min = 0;
0062   _pt_max = 100;
0063 
0064   _eta_min = -1.1;
0065   _eta_max = +1.1;
0066 
0067   _rejection_action = Fun4AllReturnCodes::DISCARDEVENT;
0068 }
0069 
0070 int HFFastSim::Init(PHCompositeNode* topNode)
0071 {
0072   _verbose = true;
0073 
0074   _ievent = 0;
0075 
0076   _total_pass = 0;
0077 
0078   _f = new TFile(_foutname.c_str(), "RECREATE");
0079 
0080   m_hNorm = new TH1D("hNormalization",  //
0081                      "Normalization;Items;Summed quantity", 10, .5, 10.5);
0082   int i = 1;
0083   m_hNorm->GetXaxis()->SetBinLabel(i++, "IntegratedLumi");
0084   m_hNorm->GetXaxis()->SetBinLabel(i++, "Event");
0085   m_hNorm->GetXaxis()->SetBinLabel(i++, "D0");
0086   m_hNorm->GetXaxis()->SetBinLabel(i++, "D0->PiK");
0087   m_hNorm->GetXaxis()->SetBinLabel(i++, "D0-Pair");
0088   m_hNorm->GetXaxis()->SetBinLabel(i++, "D0->PiK-Pair");
0089   m_hNorm->GetXaxis()->SetBinLabel(i++, "Lc");
0090   m_hNorm->GetXaxis()->SetBinLabel(i++, "Lc->pPiK");
0091   m_hNorm->GetXaxis()->SetBinLabel(i++, "Accepted");
0092 
0093   m_hNorm->GetXaxis()->LabelsOption("v");
0094 
0095   m_DRapidity = new TH2F("hDRapidity",  //
0096                          "hDRapidity;Rapidity of D0 meson;Accepted", 1000, -5, 5, 2, -.5, 1.5);
0097 
0098   _h2 = new TH2D("h2", "", 100, 0, 100.0, 40, -2, +2);
0099   _h2_b = new TH2D("h2_b", "", 100, 0, 100.0, 40, -2, +2);
0100   _h2_c = new TH2D("h2_c", "", 100, 0, 100.0, 40, -2, +2);
0101   _h2all = new TH2D("h2all", "", 100, 0, 100.0, 40, -2, +2);
0102 
0103   m_tSingleD = new TTree("TSingleD", "TSingleD");
0104 
0105   m_singleD = new D02PiK;
0106   m_tSingleD->Branch("D02PiK", "HFFastSim::D02PiK", &m_singleD);
0107 
0108   m_tSingleLc = new TTree("TSingleLc", "TSingleLc");
0109 
0110   m_singleLc = new Lc2pPiK;
0111   m_tSingleLc->Branch("Lc2pPiK", "HFFastSim::Lc2pPiK", &m_singleLc);
0112 
0113   return 0;
0114 }
0115 
0116 std::pair<int, TString> HFFastSim::quark_trace(const HepMC::GenParticle* p, HepMC::GenEvent* theEvent)
0117 {
0118   int max_abs_q_pid = 0;
0119   TString chain;
0120 
0121   while (p)
0122   {
0123     int pidabs = 0;
0124 
0125     TParticlePDG* pdg_p = TDatabasePDG::Instance()->GetParticle((p)->pdg_id());
0126     if (pdg_p)
0127     {
0128       chain = TString(" -> ") + TString(pdg_p->GetName()) + chain;
0129 
0130       if (TString(pdg_p->ParticleClass()).BeginsWith("B-"))
0131       {
0132         pidabs = TDatabasePDG::Instance()->GetParticle("b")->PdgCode();
0133       }
0134       else if (TString(pdg_p->ParticleClass()).BeginsWith("Charmed"))
0135       {
0136         pidabs = TDatabasePDG::Instance()->GetParticle("c")->PdgCode();
0137       }
0138     }
0139     else
0140     {
0141       chain = TString(" -> ") + Form("%d", (p)->pdg_id()) + chain;
0142     }
0143 
0144     if (pidabs > max_abs_q_pid) max_abs_q_pid = pidabs;
0145 
0146     const HepMC::GenVertex* vtx = p->production_vertex();
0147     if (vtx)
0148     {
0149       if (vtx->particles_in_size() == 1)
0150       {
0151         //trace parent
0152         p = *(vtx->particles_in_const_begin());
0153       }
0154       else
0155       {
0156         // vac, beam, or lund string
0157         //        vtx->print();
0158 
0159         break;
0160       }
0161     }
0162   }
0163 
0164   return make_pair(max_abs_q_pid, chain);
0165 }
0166 
0167 bool HFFastSim::process_D02PiK(HepMC::GenEvent* theEvent)
0168 {
0169   assert(theEvent);
0170 
0171   const double mom_factor = HepMC::Units::conversion_factor(theEvent->momentum_unit(), HepMC::Units::GEV);
0172   const double length_factor = HepMC::Units::conversion_factor(theEvent->length_unit(), HepMC::Units::CM);
0173   //  const double time_factor = HepMC::Units::conversion_factor(theEvent->length_unit(), HepMC::Units::CM) / GSL_CONST_CGS_SPEED_OF_LIGHT * 1e9;  // from length_unit()/c to ns
0174 
0175   TDatabasePDG* pdg = TDatabasePDG::Instance();
0176 
0177   int targetPID = std::abs(pdg->GetParticle("D0")->PdgCode());
0178   int daughter1PID = std::abs(pdg->GetParticle("pi+")->PdgCode());
0179   int daughter2PID = std::abs(pdg->GetParticle("K+")->PdgCode());
0180 
0181   unsigned int nD0(0);
0182   unsigned int nD0PiK(0);
0183 
0184   auto range = theEvent->particle_range();
0185   for (HepMC::GenEvent::particle_const_iterator piter = range.begin(); piter != range.end(); ++piter)
0186   {
0187     const HepMC::GenParticle* p = *piter;
0188     assert(p);
0189 
0190     if (std::abs(p->pdg_id()) == targetPID)
0191     {
0192       if (Verbosity() >= VERBOSITY_MORE)
0193       {
0194         cout << "process_D02PiK - Accept signal particle : ";
0195         p->print();
0196         cout << endl;
0197       }
0198 
0199       m_hNorm->Fill("D0", 1);
0200       ++nD0;
0201 
0202       assert(m_DRapidity);
0203       const double rapidity = 0.5 * log((p->momentum().e() + p->momentum().z()) /
0204                                         (p->momentum().e() - p->momentum().z()));
0205 
0206       m_DRapidity->Fill(rapidity, 0);
0207 
0208       const HepMC::GenVertex* decayVertex = p->end_vertex();
0209 
0210       int hasDecay1(0);
0211       int hasDecay2(0);
0212       int hasDecayOther(0);
0213 
0214       if (decayVertex)  // decay
0215       {
0216         for (auto diter = decayVertex->particles_out_const_begin();
0217              diter != decayVertex->particles_out_const_end();
0218              ++diter)
0219 
0220         {
0221           const HepMC::GenParticle* pd = *diter;
0222           assert(pd);
0223 
0224           if (Verbosity() >= VERBOSITY_MORE)
0225           {
0226             cout << "process_D02PiK - Testing daughter particle: ";
0227             pd->print();
0228             cout << endl;
0229           }
0230 
0231           if (std::abs(pd->pdg_id()) == daughter1PID)
0232           {
0233             const double eta = pd->momentum().eta();
0234 
0235             if (eta > _eta_min and eta < _eta_max)
0236               ++hasDecay1;
0237           }
0238           else if (std::abs(pd->pdg_id()) == daughter2PID)
0239           {
0240             const double eta = pd->momentum().eta();
0241 
0242             if (eta > _eta_min and eta < _eta_max)
0243               ++hasDecay2;
0244           }
0245           else
0246             ++hasDecayOther;
0247         }  // for ...
0248 
0249         // found a D0->piK
0250         if (hasDecay1 == 1 and hasDecay2 == 1 and hasDecayOther == 0)
0251         {
0252           m_hNorm->Fill("D0->PiK", 1);
0253           ++nD0PiK;
0254 
0255           assert(m_singleD);
0256           m_singleD->pid = p->pdg_id();
0257           m_singleD->y = rapidity;
0258           m_singleD->pt = p->momentum().perp() * mom_factor;
0259 
0260           m_singleD->decayL = decayVertex->point3d().r() * length_factor;
0261           m_singleD->prodL = p->production_vertex()->point3d().r() * length_factor;
0262 
0263           auto trace = quark_trace(p, theEvent);
0264           m_singleD->hadron_origion_qpid = trace.first;
0265           m_singleD->decayChain = trace.second;
0266 
0267           if (Verbosity())
0268           {
0269             cout << "process_D02PiK - Found D0->piK:";
0270             cout << "m_singleD->pid = " << m_singleD->pid << ", ";
0271             cout << "m_singleD->y = " << m_singleD->y << ", ";
0272             cout << "m_singleD->pt = " << m_singleD->pt;
0273             cout << " origin " << m_singleD->decayChain << endl;
0274           }
0275 
0276           assert(m_tSingleD);
0277           m_tSingleD->Fill();
0278           m_singleD->Clear();
0279 
0280           m_DRapidity->Fill(rapidity, 1);
0281         }
0282 
0283       }  //      if (decayVertex)
0284       else
0285       {
0286         cout << "process_D02PiK - Warning - target particle did not have decay vertex : ";
0287         p->print();
0288         cout << endl;
0289       }
0290 
0291     }  //    if (std::abs(p-> pdg_id()) == targetPID)
0292   }    //  for (HepMC::GenEvent::particle_const_iterator piter = range.begin(); piter != range.end(); ++piter)
0293 
0294   if (nD0 >= 2)
0295   {
0296     if (Verbosity() >= VERBOSITY_MORE)
0297       cout << "process_D02PiK - D0-Pair with nD0 = " << nD0 << endl;
0298     m_hNorm->Fill("D0-Pair", nD0 * (nD0 - 1) / 2);
0299   }
0300   if (nD0PiK >= 2)
0301   {
0302     m_hNorm->Fill("D0->PiK-Pair", nD0PiK * (nD0PiK - 1) / 2);
0303   }
0304 
0305   return nD0PiK >= 1;
0306 }
0307 
0308 bool HFFastSim::process_Lc2pPiK(HepMC::GenEvent* theEvent)
0309 {
0310   assert(theEvent);
0311 
0312   const double mom_factor = HepMC::Units::conversion_factor(theEvent->momentum_unit(), HepMC::Units::GEV);
0313   const double length_factor = HepMC::Units::conversion_factor(theEvent->length_unit(), HepMC::Units::CM);
0314   //  const double time_factor = HepMC::Units::conversion_factor(theEvent->length_unit(), HepMC::Units::CM) / GSL_CONST_CGS_SPEED_OF_LIGHT * 1e9;  // from length_unit()/c to ns
0315 
0316   TDatabasePDG* pdg = TDatabasePDG::Instance();
0317 
0318   const int targetPID = std::abs(pdg->GetParticle("Lambda_c+")->PdgCode());
0319   assert(targetPID == 4122);
0320   const int daughter1PID = std::abs(pdg->GetParticle("pi+")->PdgCode());
0321   assert(daughter1PID == 211);
0322   const int daughter2PID = std::abs(pdg->GetParticle("K+")->PdgCode());
0323   assert(daughter2PID == 321);
0324   const int daughter3PID = std::abs(pdg->GetParticle("proton")->PdgCode());
0325   assert(daughter3PID == 2212);
0326 
0327   unsigned int nLc(0);
0328   unsigned int nLc2pPiK(0);
0329 
0330   auto range = theEvent->particle_range();
0331   for (HepMC::GenEvent::particle_const_iterator piter = range.begin(); piter != range.end(); ++piter)
0332   {
0333     const HepMC::GenParticle* p = *piter;
0334     assert(p);
0335 
0336     if (std::abs(p->pdg_id()) == targetPID)
0337     {
0338       if (Verbosity() >= VERBOSITY_MORE)
0339       {
0340         cout << "HFFastSim::process_Lc2pPiK - Accept signal particle : ";
0341         p->print();
0342         cout << endl;
0343       }
0344 
0345       m_hNorm->Fill("Lc", 1);
0346       ++nLc;
0347 
0348       const double rapidity = 0.5 * log((p->momentum().e() + p->momentum().z()) /
0349                                         (p->momentum().e() - p->momentum().z()));
0350 
0351       const HepMC::GenVertex* decayVertex = p->end_vertex();
0352 
0353       int hasDecay1(0);
0354       int hasDecay2(0);
0355       int hasDecay3(0);
0356       int hasDecayOther(0);
0357 
0358       if (decayVertex)  // decay
0359       {
0360         for (auto diter = decayVertex->particles_out_const_begin();
0361              diter != decayVertex->particles_out_const_end();
0362              ++diter)
0363 
0364         {
0365           const HepMC::GenParticle* pd = *diter;
0366           assert(pd);
0367 
0368           if (Verbosity() >= VERBOSITY_MORE)
0369           {
0370             cout << "HFFastSim::process_Lc2pPiK - Testing daughter particle: ";
0371             pd->print();
0372             cout << endl;
0373           }
0374 
0375           if (std::abs(pd->pdg_id()) == daughter1PID)
0376           {
0377             const double eta = pd->momentum().eta();
0378 
0379             if (eta > _eta_min and eta < _eta_max)
0380               ++hasDecay1;
0381           }
0382           else if (std::abs(pd->pdg_id()) == daughter2PID)
0383           {
0384             const double eta = pd->momentum().eta();
0385 
0386             if (eta > _eta_min and eta < _eta_max)
0387               ++hasDecay2;
0388           }
0389           else if (std::abs(pd->pdg_id()) == daughter3PID)
0390           {
0391             const double eta = pd->momentum().eta();
0392 
0393             if (eta > _eta_min and eta < _eta_max)
0394               ++hasDecay3;
0395           }
0396           else
0397             ++hasDecayOther;
0398         }  // for ...
0399 
0400         // found a D0->piK
0401         if (hasDecay1 == 1 and hasDecay2 == 1 and hasDecay3 == 1 and hasDecayOther == 0)
0402         {
0403           m_hNorm->Fill("Lc->pPiK", 1);
0404           ++nLc2pPiK;
0405 
0406           assert(m_singleLc);
0407           m_singleLc->pid = p->pdg_id();
0408           m_singleLc->y = rapidity;
0409           m_singleLc->pt = p->momentum().perp() * mom_factor;
0410 
0411           m_singleLc->decayL = decayVertex->point3d().r() * length_factor;
0412           m_singleLc->prodL = p->production_vertex()->point3d().r() * length_factor;
0413 
0414           auto trace = quark_trace(p, theEvent);
0415           m_singleLc->hadron_origion_qpid = trace.first;
0416           m_singleLc->decayChain = trace.second;
0417 
0418           if (Verbosity())
0419           {
0420             cout << "HFFastSim::process_Lc2pPiK - Found D0->piK:";
0421             cout << "m_singleLc->pid = " << m_singleLc->pid << ", ";
0422             cout << "m_singleLc->y = " << m_singleLc->y << ", ";
0423             cout << "m_singleLc->pt = " << m_singleLc->pt;
0424             cout << " origin " << m_singleLc->decayChain << endl;
0425           }
0426 
0427           assert(m_tSingleLc);
0428           m_tSingleLc->Fill();
0429           m_singleLc->Clear();
0430 
0431           m_DRapidity->Fill(rapidity, 1);
0432         }
0433 
0434       }  //      if (decayVertex)
0435       else
0436       {
0437         cout << "HFFastSim::process_Lc2pPiK - Warning - target particle did not have decay vertex : ";
0438         p->print();
0439         cout << endl;
0440       }
0441 
0442     }  //    if (std::abs(p-> pdg_id()) == targetPID)
0443   }    //  for (HepMC::GenEvent::particle_const_iterator piter = range.begin(); piter != range.end(); ++piter)
0444 
0445   return nLc2pPiK >= 1;
0446 }
0447 
0448 int HFFastSim::process_event(PHCompositeNode* topNode)
0449 {
0450   assert(m_hNorm);
0451   m_hNorm->Fill("Event", 1);
0452 
0453   PHHepMCGenEventMap* geneventmap = findNode::getClass<PHHepMCGenEventMap>(topNode, "PHHepMCGenEventMap");
0454   if (!geneventmap)
0455   {
0456     std::cout << PHWHERE << " - Fatal error - missing node PHHepMCGenEventMap" << std::endl;
0457     return Fun4AllReturnCodes::ABORTRUN;
0458   }
0459 
0460   PHHepMCGenEvent* genevt = geneventmap->get(_embedding_id);
0461   if (!genevt)
0462   {
0463     std::cout << PHWHERE << " - Fatal error - node PHHepMCGenEventMap missing subevent with embedding ID " << _embedding_id;
0464     std::cout << ". Print PHHepMCGenEventMap:";
0465     geneventmap->identify();
0466     return Fun4AllReturnCodes::ABORTRUN;
0467   }
0468 
0469   HepMC::GenEvent* theEvent = genevt->getEvent();
0470   //theEvent->print();
0471   assert(theEvent);
0472 
0473   if (Verbosity() >= VERBOSITY_MORE)
0474   {
0475     cout << "HFFastSim::process_event - process HepMC::GenEvent with signal_process_id = "
0476          << theEvent->signal_process_id();
0477     if (theEvent->signal_process_vertex())
0478     {
0479       cout << " and signal_process_vertex : ";
0480       theEvent->signal_process_vertex()->print();
0481     }
0482     cout << "  - Event record:" << endl;
0483     theEvent->print();
0484   }
0485 
0486   // process quarks
0487   for (HepMC::GenEvent::particle_const_iterator p = theEvent->particles_begin();
0488        p != theEvent->particles_end(); ++p)
0489   {
0490     int pidabs = abs((*p)->pdg_id());
0491     if (pidabs == TDatabasePDG::Instance()->GetParticle("c")->PdgCode()      //
0492         or pidabs == TDatabasePDG::Instance()->GetParticle("b")->PdgCode()   //
0493         or pidabs == TDatabasePDG::Instance()->GetParticle("t")->PdgCode())  // handle heavy quarks only. All other favor tagged as default 0
0494     {
0495       if (pidabs == TDatabasePDG::Instance()->GetParticle("b")->PdgCode())
0496       {
0497         if (Verbosity() >= VERBOSITY_MORE)
0498           std::cout << __PRETTY_FUNCTION__
0499                     << " --BOTTOM--> pt / eta / phi = "
0500                     << ((*p)->momentum().perp()) << " / "
0501                     << (*p)->momentum().pseudoRapidity() << " / "
0502                     << (*p)->momentum().phi() << std::endl;
0503 
0504         _h2_b->Fill((*p)->momentum().perp(), (*p)->momentum().pseudoRapidity());
0505       }
0506       else if (pidabs == TDatabasePDG::Instance()->GetParticle("c")->PdgCode())
0507       {
0508         if (Verbosity() >= VERBOSITY_MORE)
0509           std::cout << __PRETTY_FUNCTION__
0510                     << " --CHARM --> pt / eta / phi = "
0511                     << (*p)->momentum().perp() << " / "
0512                     << (*p)->momentum().pseudoRapidity() << " / "
0513                     << (*p)->momentum().phi() << std::endl;
0514 
0515         _h2_c->Fill((*p)->momentum().perp(), (*p)->momentum().pseudoRapidity());
0516       }
0517     }
0518 
0519   }  //       for (HepMC::GenEvent::particle_const_iterator p =
0520 
0521   bool pass_event = process_D02PiK(theEvent);
0522   process_Lc2pPiK(theEvent);
0523 
0524   if (pass_event && _total_pass >= _maxevent)
0525   {
0526     if (Verbosity() >= HFFastSim::VERBOSITY_MORE)
0527       std::cout << __PRETTY_FUNCTION__ << " --> FAIL due to max events = "
0528                 << _total_pass << std::endl;
0529     _ievent++;
0530     return _rejection_action;
0531   }
0532   else if (pass_event)
0533   {
0534     _total_pass++;
0535     if (Verbosity() >= HFFastSim::VERBOSITY_MORE)
0536       std::cout << __PRETTY_FUNCTION__ << " --> PASS, total = " << _total_pass
0537                 << std::endl;
0538     _ievent++;
0539     m_hNorm->Fill("Accepted", 1);
0540     return Fun4AllReturnCodes::EVENT_OK;
0541   }
0542   else
0543   {
0544     if (Verbosity() >= HFFastSim::VERBOSITY_MORE)
0545       std::cout << __PRETTY_FUNCTION__ << " --> FAIL " << std::endl;
0546     _ievent++;
0547     return _rejection_action;
0548   }
0549 }
0550 
0551 int HFFastSim::End(PHCompositeNode* topNode)
0552 {
0553   if (Verbosity() >= HFFastSim::VERBOSITY_SOME)
0554     std::cout << __PRETTY_FUNCTION__ << " PASSED " << _total_pass
0555               << " events" << std::endl;
0556 
0557   PHGenIntegral* integral_node = findNode::getClass<PHGenIntegral>(topNode, "PHGenIntegral");
0558   if (integral_node)
0559   {
0560     integral_node->identify();
0561     assert(m_hNorm);
0562     m_hNorm->Fill("IntegratedLumi", integral_node->get_Integrated_Lumi());
0563   }
0564 
0565   _f->cd();
0566   _f->Write();
0567   //_f->Close();
0568 
0569   return 0;
0570 }