ATLAS Offline Software
Loading...
Searching...
No Matches
MuonDecayTruthTrajectoryBuilder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// Niels van Eldik 2010
6
8
9
10
17#include <stack>
18namespace Muon {
19
20 //================================================================
22 const IInterface* parent) :
23 AthAlgTool(type, name, parent)
24 // ,m_isDecayIntoTwoMuons(false)
25 {
26 declareInterface<Trk::ITruthTrajectoryBuilder>(this);
27 }
28 //================================================================
30 result->clear();
31 if (input) {
32 HepMC::ConstGenParticlePtr next{nullptr};
33 auto current = input;
34 ATH_MSG_DEBUG(" New TruthTrajectory: input: " << input << " PDG id " << input->pdg_id());
35
36 // Extend trajectory outwards. The last particle should go at [0]
37 // in the TruthTrajectory, so we need to use a tmp storage while
38 // traversing the structure.
39 std::stack<HepMC::ConstGenParticlePtr> tmp;
40 while ((next = getDaughter(current))) { tmp.push(current = next); }
41
42 // copy the outer half to result
43 while (!tmp.empty()) {
44 ATH_MSG_DEBUG(" Adding daughter: " << current); // FIXME "current" is not changed in this loop - it might make sense to print tmp.top() instead here?
45 result->emplace_back(tmp.top(),tmp.top()->parent_event()->event_number(),HepMcParticleLink::IS_EVENTNUM);
46 tmp.pop();
47 }
48
49 // The input particle itself
50 result->emplace_back(input,input->parent_event()->event_number(),HepMcParticleLink::IS_EVENTNUM);
51
52 // Now continue towards the interaction point
53 while ((next = getMother(current))) {
54 ATH_MSG_DEBUG(" Adding mother: " << current); // FIXME "current" here refers to the child particle rather than the mother? Consider moving this after "current = next"
55 current = next;
56 result->emplace_back(current,current->parent_event()->event_number(),HepMcParticleLink::IS_EVENTNUM);
57 }
58
59 ATH_MSG_DEBUG(" Final TruthTrajectory: ");
60 std::vector<HepMcParticleLink>::const_iterator pit = result->begin();
61 std::vector<HepMcParticleLink>::const_iterator pit_end = result->end();
62 for (; pit != pit_end; ++pit) {
63 const HepMC::GenParticle& par = *pit->cptr();
64 if (msgLvl(MSG::DEBUG)) {
65 msg(MSG::DEBUG) << " PDG ID " << par.pdg_id()
66 << " pt: " << par.momentum().perp();
67 if (par.production_vertex())
68 msg(MSG::DEBUG) << " vertices prod: r " << par.production_vertex()->position().perp() << " z "
69 << par.production_vertex()->position().z();
70 if (par.end_vertex())
71 msg(MSG::DEBUG) << " end: r " << par.end_vertex()->position().perp() << " z " << par.end_vertex()->position().z();
72 msg(MSG::DEBUG) << endmsg;
73 }
74 }
75 }
76 }
77
78 //================================================================
80 const HepMC::ConstGenVertexPtr& vtx) const {
81 HepMC::ConstGenParticlePtr mother{nullptr};
82 HepMC::ConstGenParticlePtr daughter{nullptr};
83 int particles_in_size = vtx ? vtx->particles_in_size() : 0;
84 int particles_out_size = vtx ? vtx->particles_out_size() : 0;
85 if (vtx && msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << " new vertex: nparticles in " << particles_in_size << endmsg;
86 // only truth vertices with 1 incoming particle
87 if (vtx && (particles_in_size == 1)) {
88#ifdef HEPMC3
89 mother = vtx->particles_in().front();
90#else
91 mother = *vtx->particles_in_const_begin();
92#endif
93
94 if (mother && msgLvl(MSG::DEBUG))
95 msg(MSG::DEBUG) << " new mother: " << mother->pdg_id() << " status " << mother->status() << " particles out "
96 << particles_out_size << endmsg;
97 // Allow status code 1 and 2. E.g. a pion that produced a long track can decay outside of InDet and have status==2.
98 if (mother && MC::isPhysical(mother)) {
99 unsigned int nDecayMuons = 0;
100 HepMC::ConstGenParticlePtr passed_cuts{nullptr};
101 for (const auto& candidate : *vtx) {
102 if (msgLvl(MSG::DEBUG)) {
103 msg(MSG::DEBUG) << " PDG ID " << candidate->pdg_id() << " particle: " << candidate
104 << " pt: " << candidate->momentum().perp();
105 if (candidate->production_vertex())
106 msg(MSG::DEBUG) << " vertices prod: r " << candidate->production_vertex()->position().perp() << " z "
107 << candidate->production_vertex()->position().z();
108 if (candidate->end_vertex())
109 msg(MSG::DEBUG) << " end: r " << candidate->end_vertex()->position().perp() << " z "
110 << candidate->end_vertex()->position().z();
111 msg(MSG::DEBUG) << endmsg;
112 }
113
114 if (candidate->pdg_id() == mother->pdg_id()) {
115 if (passed_cuts && MC::isElectron(mother)) { // second negative electron is a special case
116 if (candidate->momentum().e() > passed_cuts->momentum().e()) { passed_cuts = candidate; }
117 } else {
118 passed_cuts = candidate;
119 }
120 } else if (MC::isMuon(candidate)) {
121 ATH_MSG_DEBUG(" selecting Decay into muon ");
122 ++nDecayMuons;
123 passed_cuts = candidate;
124 } else { // temp addition for debugging
125 msg(MSG::DEBUG) << " Neither muon nor identical pdgId " << endmsg;
126 passed_cuts = candidate;
127 }
128 }
129
130 if (nDecayMuons > 0) {
131 daughter = std::move(passed_cuts);
132 if (nDecayMuons == 2) {
133 ATH_MSG_DEBUG(" decay into two muons ");
134 }
135 }
136 }
137 }
138
139 return std::make_pair(mother, daughter);
140 }
141
142 //================================================================
144 if(mother) {
145 MotherDaughter res = truthTrajectoryCuts(mother->end_vertex());
146 if(res.first == mother) return res.second;
147 }
148 return {nullptr};
149 }
150
151 //================================================================
153 return daughter ? truthTrajectoryCuts(daughter->production_vertex()).first : HepMC::ConstGenParticlePtr{nullptr};
154 }
155
156 //================================================================
157
158} // namespace Muon
#define endmsg
#define ATH_MSG_DEBUG(x)
An STL vector of pointers that by default owns its pointed-to elements.
ATLAS-specific HepMC functions.
std::pair< std::vector< unsigned int >, bool > res
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
bool msgLvl(const MSG::Level lvl) const
MsgStream & msg() const
HepMC::ConstGenParticlePtr getDaughter(const HepMC::ConstGenParticlePtr &particle) const override
Returns an umambiguous daughter of the truth particle on a TruthTrajectory, or 0.
HepMC::ConstGenParticlePtr getMother(const HepMC::ConstGenParticlePtr &particle) const override
Returns an umambiguous mother of the truth particle on a TruthTrajectory, or 0.
std::pair< HepMC::ConstGenParticlePtr, HepMC::ConstGenParticlePtr > MotherDaughter
Return type for the next method.
MotherDaughter truthTrajectoryCuts(const HepMC::ConstGenVertexPtr &vtx) const
Decides if the vertex connects two particles on the same TruthTrajectory.
MuonDecayTruthTrajectoryBuilder(const std::string &type, const std::string &name, const IInterface *parent)
void buildTruthTrajectory(TruthTrajectory *result, const HepMC::ConstGenParticlePtr &input) const override
Build a TruthTrajectory this particle belongs to.
A TruthTrajectory is a chain of charged MC particles connected through the mother-daughter relationsh...
const GenParticle * ConstGenParticlePtr
Definition GenParticle.h:38
const HepMC::GenVertex * ConstGenVertexPtr
Definition GenVertex.h:60
bool isElectron(const T &p)
bool isMuon(const T &p)
bool isPhysical(const T &p)
Identify if the particle is physical, i.e. is stable or decayed.
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.