File indexing completed on 2025-12-16 09:22:02
0001 #include "PHG4TruthTrackingAction.h"
0002
0003 #include "PHG4Particle.h" // for PHG4Particle
0004 #include "PHG4Particlev2.h"
0005 #include "PHG4Particlev3.h"
0006 #include "PHG4ProcessMapPhysics.h"
0007 #include "PHG4Shower.h" // for PHG4Shower
0008 #include "PHG4Showerv1.h"
0009 #include "PHG4TrackUserInfoV1.h"
0010 #include "PHG4TruthEventAction.h"
0011 #include "PHG4TruthInfoContainer.h"
0012 #include "PHG4UserPrimaryParticleInformation.h"
0013 #include "PHG4VtxPointv2.h"
0014
0015 #include <phool/getClass.h>
0016
0017 #include <Geant4/G4DynamicParticle.hh> // for G4DynamicParticle
0018 #include <Geant4/G4ParticleDefinition.hh> // for G4ParticleDefinition
0019 #include <Geant4/G4PrimaryParticle.hh>
0020 #include <Geant4/G4SystemOfUnits.hh>
0021 #include <Geant4/G4ThreeVector.hh> // for G4ThreeVector
0022 #include <Geant4/G4Track.hh>
0023 #include <Geant4/G4TrackVector.hh> // for G4TrackVector
0024 #include <Geant4/G4TrackingManager.hh>
0025 #include <Geant4/G4VUserTrackInformation.hh> // for G4VUserTrackInformation
0026
0027 #include <cmath> // for sqrt
0028 #include <iostream> // for operator<<, endl
0029 #include <utility> // for pair
0030
0031
0032 PHG4TruthTrackingAction::PHG4TruthTrackingAction(PHG4TruthEventAction* eventAction)
0033 : m_EventAction(eventAction)
0034 {
0035 return;
0036 }
0037
0038 void PHG4TruthTrackingAction::PreUserTrackingAction(const G4Track* track)
0039 {
0040
0041 PHG4Particle* ti = AddParticle(*m_TruthInfoList, *const_cast<G4Track*>(track));
0042
0043
0044
0045 int track_id_g4 = track->GetTrackID() * (track->GetParentID() ? -1 : +1);
0046 int trackid = ti->get_track_id();
0047
0048
0049 PHG4TrackUserInfo::SetUserTrackId(const_cast<G4Track*>(track), trackid);
0050
0051 if (PHG4TrackUserInfoV1* p = dynamic_cast<PHG4TrackUserInfoV1*>(track->GetUserInformation()))
0052 {
0053 ti->set_parent_id(p->GetUserParentId());
0054
0055 if (track->GetParentID())
0056 {
0057 ti->set_primary_id(p->GetUserPrimaryId());
0058 }
0059 else
0060 {
0061 PHG4TrackUserInfo::SetUserPrimaryId(const_cast<G4Track*>(track), trackid);
0062 ti->set_primary_id(trackid);
0063 }
0064 }
0065
0066 if (!track->GetParentID())
0067 {
0068
0069 PHG4UserPrimaryParticleInformation* userdata = static_cast<PHG4UserPrimaryParticleInformation*>(track->GetDynamicParticle()->GetPrimaryParticle()->GetUserInformation());
0070 if (userdata)
0071 {
0072 ti->set_barcode(userdata->get_user_barcode());
0073 }
0074 }
0075
0076 int vtxindex = ti->get_vtx_id();
0077
0078
0079
0080 if (issPHENIXPrimary(*m_TruthInfoList, ti))
0081 {
0082
0083 PHG4TrackUserInfoV1* userinfo = dynamic_cast<PHG4TrackUserInfoV1*>(track->GetUserInformation());
0084 if (userinfo)
0085 {
0086 userinfo->SetKeep(true);
0087 }
0088
0089 PHG4Particle* newparticle = dynamic_cast<PHG4Particle*>(ti->CloneMe());
0090
0091 m_TruthInfoList->AddsPHENIXPrimaryParticle(trackid, newparticle);
0092 }
0093
0094 m_CurrG4Particle = {track_id_g4, trackid, vtxindex};
0095
0096
0097 if (!track->GetParentID())
0098 {
0099 PHG4Showerv1* shower = new PHG4Showerv1();
0100 PHG4TrackUserInfo::SetShower(const_cast<G4Track*>(track), shower);
0101 m_TruthInfoList->AddShower(trackid, shower);
0102 shower->set_id(trackid);
0103 shower->set_parent_particle_id(trackid);
0104 shower->set_parent_shower_id(0);
0105 }
0106 else
0107 {
0108
0109 if (G4VUserTrackInformation* p = track->GetUserInformation())
0110 {
0111 if (PHG4TrackUserInfoV1* pp = dynamic_cast<PHG4TrackUserInfoV1*>(p))
0112 {
0113 if (pp->GetShower())
0114 {
0115 pp->GetShower()->add_g4particle_id(trackid);
0116 pp->GetShower()->add_g4vertex_id(vtxindex);
0117 }
0118 }
0119 }
0120 }
0121
0122
0123 if (!track->GetParentID())
0124 {
0125 PHG4UserPrimaryParticleInformation* userdata = static_cast<PHG4UserPrimaryParticleInformation*>(track->GetDynamicParticle()->GetPrimaryParticle()->GetUserInformation());
0126 if (userdata)
0127 {
0128 userdata->set_user_track_id(trackid);
0129 userdata->set_user_vtx_id(vtxindex);
0130 }
0131 }
0132
0133 return;
0134 }
0135
0136 void PHG4TruthTrackingAction::PostUserTrackingAction(const G4Track* track)
0137 {
0138 if (fpTrackingManager)
0139 {
0140 int trackid = track->GetTrackID();
0141 int primaryid = 0;
0142 PHG4Shower* shower = nullptr;
0143 if (PHG4TrackUserInfoV1* p = dynamic_cast<PHG4TrackUserInfoV1*>(track->GetUserInformation()))
0144 {
0145 trackid = p->GetUserTrackId();
0146 primaryid = p->GetUserPrimaryId();
0147 shower = p->GetShower();
0148 }
0149
0150 G4TrackVector* secondaries = fpTrackingManager->GimmeSecondaries();
0151 if (secondaries)
0152 {
0153 for (auto* secondary : *secondaries)
0154 {
0155 PHG4TrackUserInfo::SetUserParentId(const_cast<G4Track*>(secondary), trackid);
0156 PHG4TrackUserInfo::SetUserPrimaryId(const_cast<G4Track*>(secondary), primaryid);
0157 PHG4TrackUserInfo::SetShower(const_cast<G4Track*>(secondary), shower);
0158 }
0159 }
0160 }
0161
0162 if (PHG4TrackUserInfoV1* p = dynamic_cast<PHG4TrackUserInfoV1*>(track->GetUserInformation()))
0163 {
0164 if (p->GetKeep())
0165 {
0166 int trackid = p->GetUserTrackId();
0167 m_EventAction->AddTrackidToWritelist(trackid);
0168 }
0169 }
0170
0171 UpdateG4ParticleStack(track);
0172 }
0173
0174
0175
0176
0177
0178 void PHG4TruthTrackingAction::UpdateG4ParticleStack(const G4Track* track)
0179 {
0180 while (!m_G4ParticleStack.empty())
0181 {
0182 if (std::abs(m_G4ParticleStack.back().g4track_id) == track->GetParentID())
0183 {
0184 break;
0185 }
0186
0187 if (m_G4ParticleStack.back().g4track_id < 0)
0188 {
0189 m_TruthInfoList->delete_particle(m_G4ParticleStack.back().particle_id);
0190 }
0191 m_G4ParticleStack.pop_back();
0192 }
0193
0194 m_G4ParticleStack.push_back(m_CurrG4Particle);
0195
0196
0197
0198 PHG4TrackUserInfoV1* p = dynamic_cast<PHG4TrackUserInfoV1*>(track->GetUserInformation());
0199 bool keep_curr_track = p && p->GetKeep() ? true : false;
0200
0201 auto stack_iter = m_G4ParticleStack.rbegin();
0202 while (keep_curr_track && stack_iter != m_G4ParticleStack.rend() && stack_iter->g4track_id < 0)
0203 {
0204 stack_iter->g4track_id *= -1;
0205 ++stack_iter;
0206 }
0207 }
0208
0209 void PHG4TruthTrackingAction::SetInterfacePointers(PHCompositeNode* topNode)
0210 {
0211
0212 m_TruthInfoList = findNode::getClass<PHG4TruthInfoContainer>(topNode, "G4TruthInfo");
0213
0214
0215 if (!m_TruthInfoList)
0216 {
0217 std::cout << "PHG4TruthEventAction::SetInterfacePointers - unable to find G4TruthInfo" << std::endl;
0218 }
0219 }
0220
0221 int PHG4TruthTrackingAction::ResetEvent(PHCompositeNode* )
0222 {
0223 m_VertexMap.clear();
0224
0225 while (!m_G4ParticleStack.empty())
0226 {
0227 if (m_G4ParticleStack.back().g4track_id < 0)
0228 {
0229 m_TruthInfoList->delete_particle(m_G4ParticleStack.back().particle_id);
0230 }
0231 m_G4ParticleStack.pop_back();
0232 }
0233
0234 return 0;
0235 }
0236
0237 PHG4Particle* PHG4TruthTrackingAction::AddParticle(PHG4TruthInfoContainer& truth, G4Track& track)
0238 {
0239 int trackid = 0;
0240 if (track.GetParentID())
0241 {
0242
0243 trackid = truth.mintrkindex() - 1;
0244 }
0245 else
0246 {
0247
0248 trackid = truth.maxtrkindex() + 1;
0249 }
0250
0251
0252 G4ParticleDefinition* def = track.GetDefinition();
0253 int pdgid = def->GetPDGEncoding();
0254 double mass = def->GetPDGMass();
0255 double ke = track.GetVertexKineticEnergy();
0256 double ptot = sqrt(ke * ke + 2.0 * mass * ke);
0257 G4ThreeVector pdir = track.GetVertexMomentumDirection();
0258 pdir *= ptot;
0259 PHG4Particle* ti = nullptr;
0260
0261 if (def->IsGeneralIon())
0262 {
0263 ti = new PHG4Particlev3();
0264 ti->set_A(def->GetAtomicMass());
0265 ti->set_Z(def->GetAtomicNumber());
0266 }
0267 else
0268 {
0269 ti = new PHG4Particlev2;
0270 }
0271 ti->set_px(pdir[0] / GeV);
0272 ti->set_py(pdir[1] / GeV);
0273 ti->set_pz(pdir[2] / GeV);
0274 ti->set_track_id(trackid);
0275
0276 ti->set_parent_id(track.GetParentID());
0277 ti->set_primary_id(trackid);
0278
0279 ti->set_pid(pdgid);
0280 ti->set_name(def->GetParticleName());
0281 ti->set_e(track.GetTotalEnergy() / GeV);
0282
0283
0284 PHG4VtxPoint* vtx = AddVertex(truth, track);
0285 ti->set_vtx_id(vtx->get_id());
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305 return truth.AddParticle(trackid, ti)->second;
0306 }
0307
0308 PHG4VtxPoint* PHG4TruthTrackingAction::AddVertex(PHG4TruthInfoContainer& truth, const G4Track& track)
0309 {
0310 G4ThreeVector v = track.GetVertexPosition();
0311 int vtxindex = (track.GetParentID() == 0 ? truth.maxvtxindex() + 1 : truth.minvtxindex() - 1);
0312
0313 auto [iter, inserted] = m_VertexMap.insert(std::make_pair(v, vtxindex));
0314
0315
0316 if (!inserted)
0317 {
0318 return truth.GetVtxMap().find(iter->second)->second;
0319 }
0320
0321 const auto* const g4Process = track.GetCreatorProcess();
0322
0323 const auto process = PHG4ProcessMapPhysics::Instance().GetMCProcess(g4Process);
0324
0325 PHG4VtxPoint* vtxpt = new PHG4VtxPointv2(v[0] / cm, v[1] / cm, v[2] / cm, track.GetGlobalTime() / ns, vtxindex, process);
0326
0327 return truth.AddVertex(vtxindex, vtxpt)->second;
0328 }
0329
0330 bool PHG4TruthTrackingAction::issPHENIXPrimary(PHG4TruthInfoContainer& truth, PHG4Particle* particle) const
0331 {
0332 PHG4VtxPoint* vtx = truth.GetVtx(particle->get_vtx_id());
0333 if (!vtx)
0334 {
0335
0336 std::cerr << "PHG4TruthTrackingAction::issPHENIXPrimary - no vertex found for particle with track id " << particle->get_track_id() << std::endl;
0337 return false;
0338 }
0339 auto process = vtx->get_process();
0340 int pdgid = particle->get_pid();
0341
0342 if (!isLongLived(pdgid))
0343 {
0344 return false;
0345 }
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356 if (!(process == PHG4MCProcess::kPPrimary || process == PHG4MCProcess::kPDecay) && particle->get_parent_id())
0357 {
0358 return false;
0359 }
0360
0361 if (particle->get_parent_id() == 0)
0362 {
0363
0364 return true;
0365 }
0366
0367
0368 PHG4Particle* parent = truth.GetParticle(particle->get_parent_id());
0369
0370 while (parent)
0371 {
0372 if (isLongLived(parent->get_pid()))
0373 {
0374
0375 return false;
0376 }
0377 PHG4VtxPoint* vtx_parent = truth.GetVtx(parent->get_vtx_id());
0378 if (!vtx_parent)
0379 {
0380
0381 std::cerr << "PHG4TruthTrackingAction::issPHENIXPrimary - no vertex found for parent particle with track id " << parent->get_track_id() << std::endl;
0382 return false;
0383 }
0384 process = vtx_parent->get_process();
0385
0386 if (!(process == PHG4MCProcess::kPPrimary || process == PHG4MCProcess::kPDecay) && parent->get_parent_id())
0387 {
0388 return false;
0389 }
0390
0391 parent = truth.GetParticle(parent->get_parent_id());
0392 }
0393
0394 return true;
0395 }
0396
0397 bool PHG4TruthTrackingAction::isLongLived(int pid) const
0398 {
0399
0400
0401 if (pid > 1000000000)
0402 {
0403 return true;
0404 }
0405
0406
0407 switch (pid)
0408 {
0409 case 11:
0410 case -11:
0411 case 13:
0412 case -13:
0413 case 22:
0414 case 211:
0415 case -211:
0416 case 321:
0417 case -321:
0418 case 310:
0419 case 130:
0420 case 2212:
0421 case -2212:
0422 case 2112:
0423 case -2112:
0424 case 3122:
0425 case -3122:
0426 case 3222:
0427 case -3222:
0428 case 3112:
0429 case -3112:
0430 case 3312:
0431 case -3312:
0432 case 3322:
0433 case -3322:
0434 case 3334:
0435 case -3334:
0436 case 12:
0437 case -12:
0438 case 14:
0439 case -14:
0440 case 16:
0441 case -16:
0442
0443 return true;
0444 default:
0445 return false;
0446 }
0447 }