ATLAS Offline Software
Loading...
Searching...
No Matches
xAODtoHepMCTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6#ifndef XAOD_STANDALONE
8#endif
10
11xAODtoHepMCTool::xAODtoHepMCTool(const std::string &name)
12 : asg::AsgTool(name)
13{
14}
15
17{
18 ATH_MSG_INFO("Initializing xAODtoHepMCTool " << name() << "...");
19 ATH_MSG_INFO("SignalOnly = " << m_signalOnly);
20 return StatusCode::SUCCESS;
21}
22
23StatusCode xAODtoHepMCTool ::finalize()
24{
25 ATH_MSG_INFO("==============================================================");
26 ATH_MSG_INFO("========== xAOD -> HepMC Tool :: Run Summary ==========");
27 ATH_MSG_INFO("==============================================================");
28 if (m_noProdVtx)
29 {
30 ATH_MSG_INFO("Number of events that have a missing production vertex = " << m_noProdVtx);
31 }
32 else
33 {
34 ATH_MSG_INFO("No missing production vertices");
35 }
36 if (m_badBeams)
37 {
38 ATH_MSG_INFO("Number events with improperly defined beamparticles = " << m_badBeams);
39 ATH_MSG_INFO("Inconsistencies with the beam particles storage in the event record!");
40 ATH_MSG_INFO("... check xAOD::TruthEvent record ...");
41 }
42 else
43 {
44 ATH_MSG_INFO("No events with undefined beams.");
45 }
46 ATH_MSG_INFO("==============================================================");
47 ATH_MSG_INFO("=================== End Run Summary ===================");
48 ATH_MSG_INFO("==============================================================");
49 return StatusCode::SUCCESS;
50}
51
52std::vector<HepMC::GenEvent> xAODtoHepMCTool ::getHepMCEvents(const xAOD::TruthEventContainer *xTruthEventContainer, const xAOD::EventInfo *eventInfo) const
53{
54 ++m_evtCount;
55 bool doPrint = m_evtCount < m_maxCount;
56 // CREATE HEPMC EVENT COLLECTION
57 std::vector<HepMC::GenEvent> mcEventCollection;
58 // Loop over xAOD truth container
59 // Signal event is always first, followed by pileup events
60 ATH_MSG_DEBUG("Start event loop");
61 for (const xAOD::TruthEvent *xAODEvent : *xTruthEventContainer)
62 {
63 if (doPrint)
64 ATH_MSG_DEBUG("XXX Printing xAOD Event");
65 if (doPrint)
66 printxAODEvent(xAODEvent, eventInfo);
67 // Create GenEvent for each xAOD truth event
68 ATH_MSG_DEBUG("Create new GenEvent");
69 HepMC::GenEvent&& hepmcEvent = createHepMCEvent(xAODEvent, eventInfo);
70 std::shared_ptr<HepMC3::GenRunInfo> runinfo = std::make_shared<HepMC3::GenRunInfo>(*(hepmcEvent.run_info().get()));
71 //possibly print info, before moving the object
72 if (doPrint){
73 ATH_MSG_DEBUG("XXX Printing HepMC Event");
74 HepMC::Print::line(std::cout, hepmcEvent);
75 }
76 // Insert into McEventCollection
77 mcEventCollection.push_back(std::move(hepmcEvent));
78 mcEventCollection[mcEventCollection.size()-1].set_run_info(std::move(runinfo));
79 // Quit if signal only
80 if (m_signalOnly)
81 break;
82 }
83 return mcEventCollection;
84}
85
87{
88
90 HepMC::GenEvent genEvt;
91 genEvt.set_units(HepMC3::Units::MEV, HepMC3::Units::MM);
92
93 long long int evtNum = eventInfo->eventNumber();
94 genEvt.set_event_number(evtNum);
95 ATH_MSG_DEBUG("Start createHepMCEvent for event " << evtNum);
96
97 //Weights
98 #ifndef XAOD_STANDALONE
99 const std::vector<float> weights = xEvt->weights();
100 std::map<std::string, int> weightNameMap;
101 if (AthAnalysisHelper::retrieveMetadata("/Generation/Parameters","HepMCWeightNames", weightNameMap).isFailure()) {
102 ATH_MSG_DEBUG("Couldn't find meta-data for weight names.");
103 }
104 std::shared_ptr<HepMC3::GenRunInfo> runinfo = std::make_shared<HepMC3::GenRunInfo>();
105 genEvt.set_run_info(std::move(runinfo));
106 std::vector<std::string> wnames;
107 wnames.reserve(weights.size());
108 for (int idx = 0; idx < int(weights.size()); ++idx) {
109 for (const auto& it : weightNameMap) {
110 if (it.second == idx) {
111 wnames.push_back(it.first);
112 break;
113 }
114 }
115 }
116 genEvt.run_info()->set_weight_names(wnames);
117 for ( std::vector<float>::const_iterator wgt = weights.begin(); wgt != weights.end(); ++wgt ) {
118 genEvt.weights().push_back(*wgt);
119 }
120 #endif
121
122 // PARTICLES AND VERTICES
123 // Map of existing vertices - needed for the tree linking
124 std::map<const xAOD::TruthVertex *, HepMC::GenVertexPtr> vertexMap;
125
126 // Loop over all of the particles in the event, call particle builder
127 for (auto tlink : xEvt->truthParticleLinks()) {
128 if (!tlink.isValid()) { continue; }
129 const xAOD::TruthParticle *xPart = *tlink;
130
131 // sanity check
132 if (xPart == nullptr) {
133 ATH_MSG_WARNING("xAOD TruthParticle is equal to NULL. This should not happen!");
134 continue;
135 }
136
137 if (!xPart->hasProdVtx() && !xPart->hasDecayVtx()) {
138 ATH_MSG_WARNING("xAOD particle with no vertices, uniqueID = " << HepMC::uniqueID(xPart));
139 continue;
140 }
141
142 // skip particles which are Geant4 secondaries
143 if (HepMC::is_simulation_particle(xPart)) { continue; }
144
145 // Create GenParticle
146 // presumably the GenEvent takes ownership of this, but creating a unique_ptr here as that will only happen if there's an associated vertex
147 auto hepmcParticle = createHepMCParticle(xPart);
148
149 // Get the production and decay vertices
150 if (xPart->hasProdVtx()) {
151 const xAOD::TruthVertex *xAODProdVtx = xPart->prodVtx();
152 // skip production vertices which are Geant4 secondaries
153 if (HepMC::is_simulation_vertex(xAODProdVtx)) { continue; }
154 bool prodVtxSeenBefore(false); // is this new?
155 auto hepmcProdVtx = vertexHelper(xAODProdVtx, vertexMap, prodVtxSeenBefore);
156 // Set the decay/production links
157 hepmcProdVtx->add_particle_out(hepmcParticle);
158 // Insert into Event
159 if (!prodVtxSeenBefore) {
160 genEvt.add_vertex(std::move(hepmcProdVtx));
161 }
162 }
163 else {
164 ATH_MSG_VERBOSE("No production vertex found for particle " << HepMC::uniqueID(xPart));
165 }
166
167 if (xPart->hasDecayVtx()) {
168 const xAOD::TruthVertex *xAODDecayVtx = xPart->decayVtx();
169 // skip decay vertices which are Geant4 secondaries
170 if (HepMC::is_simulation_vertex(xAODDecayVtx)) {
172 continue;
173 }
174 bool decayVtxSeenBefore(false); // is this new?
175 auto hepmcDecayVtx = vertexHelper(xAODDecayVtx, vertexMap, decayVtxSeenBefore);
176 // Set the decay/production links
177 hepmcDecayVtx->add_particle_in(std::move(hepmcParticle));
178 // Insert into Event
179 if (!decayVtxSeenBefore) {
180 genEvt.add_vertex(std::move(hepmcDecayVtx));
181 }
182 }
183
184 } // end of particle loop
185
186 return genEvt;
187}
188
189// Helper to check whether a vertex exists or not using a map;
190// calls createHepMCVertex if not
192 std::map<const xAOD::TruthVertex *, HepMC::GenVertexPtr> &vertexMap,
193 bool &seenBefore) const
194{
195
196 HepMC::GenVertexPtr hepmcVertex;
197 std::map<const xAOD::TruthVertex *, HepMC::GenVertexPtr>::iterator vMapItr;
198 vMapItr = vertexMap.find(xaodVertex);
199 // Vertex seen before?
200 if (vMapItr != vertexMap.end()) {
201 // YES: use the HepMC::Vertex already in the map
202 hepmcVertex = (*vMapItr).second;
203 seenBefore = true;
204 }
205 else {
206 // NO: create a new HepMC::Vertex
207 vertexMap[xaodVertex] = createHepMCVertex(xaodVertex);
208 hepmcVertex = vertexMap[xaodVertex];
209 seenBefore = false;
210 }
211 return hepmcVertex;
212}
213
214// Create the HepMC GenParticle
216{
217 ATH_MSG_VERBOSE("Creating GenParticle for uniqueID " << HepMC::uniqueID(particle));
218 const HepMC::FourVector fourVec(m_momFac * particle->px(), m_momFac * particle->py(), m_momFac * particle->pz(), m_momFac * particle->e());
219 auto hepmcParticle = HepMC::newGenParticlePtr(fourVec, particle->pdgId(), particle->status());
220 hepmcParticle->set_generated_mass(m_momFac * particle->m());
221 return hepmcParticle;
222}
223
224// Create the HepMC GenVertex
226{
227 ATH_MSG_VERBOSE("Creating GenVertex for uniqueID " << HepMC::uniqueID(vertex));
228 HepMC::FourVector prod_pos(m_lenFac * vertex->x(), m_lenFac * vertex->y(), m_lenFac * vertex->z(), m_lenFac * vertex->t());
229 auto genVertex = HepMC::newGenVertexPtr(prod_pos);
230 return genVertex;
231}
232
233// Print xAODTruth Event. The printout is particle oriented, unlike the HepMC particle/vertex printout. Regenerated Geant (i.e. ones surving an interaction) and pileup particles (e.g. suppressed pileup barcodes), with barcode > 1000000 are omitted. Thus we output only the original particles created in Geant4.
234
235void xAODtoHepMCTool::printxAODEvent(const xAOD::TruthEvent *event, const xAOD::EventInfo *eventInfo) const
236{
237
238 std::vector<int> uidPars;
239 std::vector<int> uidKids;
240
241 long long int evtNum = eventInfo->eventNumber();
242
243 std::cout << "======================================================================================" << std::endl;
244 std::cout << "xAODTruth Event " << evtNum << std::endl;
245 std::cout << " UniqueID PDG Id Status px(GeV) py(GeV) pz(GeV) E(GeV) Parent: Decay" << std::endl;
246 std::cout << " -----------------------------------------------------------------------------------" << std::endl;
247
248 int nPart = event->nTruthParticles();
249 std::ios oldState(nullptr);
250 oldState.copyfmt(std::cout); //save ostream format
251 for (int i = 0; i < nPart; ++i)
252 {
253 const xAOD::TruthParticle *part = event->truthParticle(i);
254 if (part == nullptr) continue;
255 if (HepMC::generations(part) > 0) continue;
256 int id = part->pdgId();
257 if (id != 25) continue;
258 int stat = part->status();
259 float px = part->px() / 1000.;
260 float py = part->py() / 1000.;
261 float pz = part->pz() / 1000.;
262 float e = part->e() / 1000.;
263 uidPars.clear();
264 uidKids.clear();
265
266 if (part->hasProdVtx())
267 {
268 const xAOD::TruthVertex *pvtx = part->prodVtx();
269 if (pvtx)
270 uidPars.push_back(HepMC::uniqueID(pvtx));
271 }
272
273 if (part->hasDecayVtx())
274 {
275 const xAOD::TruthVertex *dvtx = part->decayVtx();
276 if (dvtx)
277 uidKids.push_back(HepMC::uniqueID(dvtx));
278 }
279
280
281 std::cout << std::setw(10) << HepMC::uniqueID(part) << std::setw(12) << id
282 << std::setw(8) << stat
283 << std::setprecision(2) << std::fixed
284 << std::setw(10) << px << std::setw(10) << py
285 << std::setw(10) << pz << std::setw(10) << e << " ";
286 std::cout << "P: ";
287 for (unsigned int k = 0; k < uidPars.size(); ++k)
288 {
289 std::cout << uidPars[k] << " ";
290 }
291 std::cout << " D: ";
292 for (unsigned int k = 0; k < uidKids.size(); ++k)
293 {
294 std::cout << uidKids[k] << " ";
295 }
296 std::cout << std::endl;
297 }
298 std::cout << "======================================================================================" << std::endl;
299 std::cout.copyfmt(oldState);//restore ostream format
300}
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static std::string retrieveMetadata(const std::string &folder, const std::string &key, const ServiceHandle< StoreGateSvc > &inputMetaStore)
method that always returns as a string you can use from, e.g, pyROOT with evt = ROOT....
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
uint64_t eventNumber() const
The current event's event number.
const TruthParticleLinks_t & truthParticleLinks() const
Get all the truth particles.
const std::vector< float > & weights() const
Const access to the weights vector.
const TruthVertex_v1 * decayVtx() const
The decay vertex of this particle.
bool hasProdVtx() const
Check for a production vertex on this particle.
bool hasDecayVtx() const
Check for a decay vertex on this particle.
const TruthVertex_v1 * prodVtx() const
The production vertex of this particle.
std::atomic< int > m_evtCount
Counters.
HepMC::GenEvent createHepMCEvent(const xAOD::TruthEvent *xEvt, const xAOD::EventInfo *eventInfo) const
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
xAODtoHepMCTool(const std::string &name)
HepMC::GenVertexPtr vertexHelper(const xAOD::TruthVertex *, std::map< const xAOD::TruthVertex *, HepMC::GenVertexPtr > &, bool &) const
HepMC::GenVertexPtr createHepMCVertex(const xAOD::TruthVertex *) const
Gaudi::Property< bool > m_signalOnly
Gaudi::Property< float > m_momFac
Input container key (job property).
HepMC::GenParticlePtr createHepMCParticle(const xAOD::TruthParticle *) const
void printxAODEvent(const xAOD::TruthEvent *event, const xAOD::EventInfo *eventInfo) const
Gaudi::Property< float > m_lenFac
Gaudi::Property< int > m_maxCount
bool is_simulation_vertex(const T &v)
Method to establish if the vertex was created during simulation (TODO migrate to be based on status).
HepMC3::FourVector FourVector
int uniqueID(const T &p)
GenParticlePtr newGenParticlePtr(const HepMC3::FourVector &mom=HepMC3::FourVector::ZERO_VECTOR(), int pid=0, int status=0)
Definition GenParticle.h:21
HepMC3::GenParticlePtr GenParticlePtr
Definition GenParticle.h:19
GenVertexPtr newGenVertexPtr(const HepMC3::FourVector &pos=HepMC3::FourVector::ZERO_VECTOR(), const int i=0)
Definition GenVertex.h:25
HepMC3::GenVertexPtr GenVertexPtr
Definition GenVertex.h:23
bool is_simulation_particle(const T &p)
Method to establish if a particle (or barcode) was created during the simulation (TODO update to be s...
int generations(const T &p)
Method to return how many interactions a particle has undergone during simulation (TODO migrate to be...
HepMC3::GenEvent GenEvent
Definition GenEvent.h:39
TruthEventContainer_v1 TruthEventContainer
Declare the latest version of the truth event container.
EventInfo_v1 EventInfo
Definition of the latest event info version.
TruthVertex_v1 TruthVertex
Typedef to implementation.
Definition TruthVertex.h:15
TruthEvent_v1 TruthEvent
Typedef to implementation.
Definition TruthEvent.h:17
TruthParticle_v1 TruthParticle
Typedef to implementation.