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 mother = vtx->particles_in().front();
89
90 if (mother && msgLvl(MSG::DEBUG))
91 msg(MSG::DEBUG) << " new mother: " << mother->pdg_id() << " status " << mother->status() << " particles out "
92 << particles_out_size << endmsg;
93 // Allow status code 1 and 2. E.g. a pion that produced a long track can decay outside of InDet and have status==2.
94 if (mother && MC::isPhysical(mother)) {
95 unsigned int nDecayMuons = 0;
96 HepMC::ConstGenParticlePtr passed_cuts{nullptr};
97 for (const auto& candidate : *vtx) {
98 if (msgLvl(MSG::DEBUG)) {
99 msg(MSG::DEBUG) << " PDG ID " << candidate->pdg_id() << " particle: " << candidate
100 << " pt: " << candidate->momentum().perp();
101 if (candidate->production_vertex())
102 msg(MSG::DEBUG) << " vertices prod: r " << candidate->production_vertex()->position().perp() << " z "
103 << candidate->production_vertex()->position().z();
104 if (candidate->end_vertex())
105 msg(MSG::DEBUG) << " end: r " << candidate->end_vertex()->position().perp() << " z "
106 << candidate->end_vertex()->position().z();
107 msg(MSG::DEBUG) << endmsg;
108 }
109
110 if (candidate->pdg_id() == mother->pdg_id()) {
111 if (passed_cuts && MC::isElectron(mother)) { // second negative electron is a special case
112 if (candidate->momentum().e() > passed_cuts->momentum().e()) { passed_cuts = candidate; }
113 } else {
114 passed_cuts = candidate;
115 }
116 } else if (MC::isMuon(candidate)) {
117 ATH_MSG_DEBUG(" selecting Decay into muon ");
118 ++nDecayMuons;
119 passed_cuts = candidate;
120 } else { // temp addition for debugging
121 msg(MSG::DEBUG) << " Neither muon nor identical pdgId " << endmsg;
122 passed_cuts = candidate;
123 }
124 }
125
126 if (nDecayMuons > 0) {
127 daughter = std::move(passed_cuts);
128 if (nDecayMuons == 2) {
129 ATH_MSG_DEBUG(" decay into two muons ");
130 }
131 }
132 }
133 }
134
135 return std::make_pair(mother, daughter);
136 }
137
138 //================================================================
140 if(mother) {
141 MotherDaughter res = truthTrajectoryCuts(mother->end_vertex());
142 if(res.first == mother) return res.second;
143 }
144 return {nullptr};
145 }
146
147 //================================================================
149 return daughter ? truthTrajectoryCuts(daughter->production_vertex()).first : HepMC::ConstGenParticlePtr{nullptr};
150 }
151
152 //================================================================
153
154} // 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...
HepMC3::ConstGenParticlePtr ConstGenParticlePtr
Definition GenParticle.h:20
HepMC3::ConstGenVertexPtr ConstGenVertexPtr
Definition GenVertex.h:24
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.