Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
FixHepMC.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #ifndef XAOD_ANALYSIS
6 
9 #include "AtlasHepMC/GenVertex.h"
10 #include "AtlasHepMC/GenEvent.h"
11 #include <vector>
12 
13 
14 FixHepMC::FixHepMC(const std::string& name, ISvcLocator* pSvcLocator)
15  : GenBase(name, pSvcLocator)
16  , m_loopKilled(0)
17  , m_pdg0Killed(0)
18  , m_decayCleaned(0)
19  , m_unstablePurged(0)
20  , m_totalSeen(0)
21  , m_replacedPIDs(0)
22 {
23  declareProperty("KillLoops", m_killLoops = true, "Remove particles in loops?");
24  declareProperty("KillPDG0", m_killPDG0 = true, "Remove particles with PDG ID 0?");
25  declareProperty("CleanDecays", m_cleanDecays = true, "Clean decay chains from non-propagating particles?");
26  declareProperty("PurgeUnstableWithoutEndVtx", m_purgeUnstableWithoutEndVtx = false, "Remove unstable particles without decay vertex?");
27  declareProperty("PIDmap", m_pidmap = std::map<int,int>(), "Map of PDG IDs to replace");
28 }
29 #ifndef HEPMC3
30 //---->//This is copied from MCUtils
32 
33 
35 static inline void reduce(HepMC::GenEvent* ge, HepMC::GenParticle* gp) {
36  // Do nothing if for some reason this particle is not actually in this event
37  if (gp->parent_event() != ge) return;
38 
39  // Get start and end vertices
40  HepMC::GenVertex* vstart = gp->production_vertex();
41  HepMC::GenVertex* vend = gp->end_vertex();
42 
43  // Disconnect the unwanted particle from its vertices and delete it
44  if (vstart != nullptr) vstart->remove_particle(gp);
45  if (vend != nullptr) vend->remove_particle(gp);
46  delete gp;
47 
48  // If start/end vertices are valid and distinct, and this was the only particle that
49  // connected them, then reassign the end vertex decay products to the start vertex
50  // and rewrite the vertex position as most appropriate.
53  if (vstart != nullptr && vend != nullptr && vend != vstart) {
54  bool is_only_link = true;
55  for (auto pchild=vstart->particles_out_const_begin();pchild!=vstart->particles_out_const_end();++pchild) {
56  if ((*pchild)->end_vertex() == vend) is_only_link = false;
57  }
58  if (is_only_link) {
59  if (vend->position() != HepMC::FourVector())
60  vstart->set_position(vend->position()); //< @todo Always use end position if defined... ok?
61  while (vend->particles_out_size() > 0) {
62  vstart->add_particle_out(*vend->particles_out_const_begin());
63  }
64  while (vend->particles_in_size() > 0) {
65  vstart->add_particle_in(*vend->particles_in_const_begin());
66  }
67  }
68  }
69 
70  // Sweep up any vertices orphaned by the particle removal
75  std::vector<HepMC::GenVertex*> orphaned_vtxs;
76  for (HepMC::GenEvent::vertex_const_iterator vi = ge->vertices_begin(); vi != ge->vertices_end(); ++vi) {
77  if ((*vi)->particles_in_size() == 0 && (*vi)->particles_out_size() == 0) orphaned_vtxs.push_back(*vi);
78  }
79  for (HepMC::GenVertex* gv : orphaned_vtxs) delete gv;
80  }
81 
83  inline void reduce(HepMC::GenEvent* ge, std::vector<HepMC::GenParticlePtr> toremove) {
84  while (toremove.size()) {
85  auto gp = toremove.back();
86  toremove.pop_back();
87  reduce(ge, gp);
88  }
89  }
90 //<----//This is copied from MCUtils
91 #endif
92 
94  for (McEventCollection::const_iterator ievt = events()->begin(); ievt != events()->end(); ++ievt) {
95  // FIXME: const_cast
96  HepMC::GenEvent* evt = const_cast<HepMC::GenEvent*>(*ievt);
97  m_looper.findLoops(evt,true);
98  /* AV: To understand why some algorithms fail one would have to request debug explicitly, but that is the reviwers consensus.*/
99  if (!m_looper.loop_particles().empty() || !m_looper.loop_vertices().empty()) {
100  ATH_MSG_DEBUG("Found " << m_looper.loop_vertices().size() << " vertices in loops");
101  ATH_MSG_DEBUG("Found " << m_looper.loop_particles().size() << " particles in loops");
102  ATH_MSG_DEBUG("Please use MC::Loops::findLoops for this event to obtain all particles and vertices in the loops");
103  }
104  if (!m_pidmap.empty()) {
105  for (auto ip: *evt) {
106  // Skip this particle if (somehow) its pointer is null
107  if (!ip) continue;
108  auto newpid = m_pidmap.find(ip->pdg_id());
109  if (newpid == m_pidmap.end()) continue;
110  ip->set_pdg_id(newpid->second);
111  }
112  }
113 #ifdef HEPMC3
114  // Add a unit entry to the event weight vector if it's currently empty
115  if (evt->weights().empty()) {
116  ATH_MSG_DEBUG("Adding a unit weight to empty event weight vector");
117  evt->weights().push_back(1);
118  }
119  // Set a (0,0,0) vertex to be the signal vertex if not already set
121  const HepMC::FourVector nullpos;
122  for (auto iv: evt->vertices()) {
123  if (iv->position() == nullpos) {
124  ATH_MSG_DEBUG("Setting representative event position vertex");
126  break;
127  }
128  }
129  }
130 
131  // Catch cases with more than 2 beam particles (16.11.2021)
132  std::vector<HepMC::GenParticlePtr> beams_t;
133  for (const HepMC::GenParticlePtr& p : evt->beams()) {
134  if (p->status() == 4) beams_t.push_back(p);
135  }
136  if (beams_t.size() > 2) {
137  ATH_MSG_INFO("Invalid number of beam particles " << beams_t.size() << ". Will try to fix.");
138  std::vector<HepMC::GenParticlePtr> bparttoremove;
139  for (const auto& bpart : beams_t) {
140  if (bpart->id() == 0 && bpart->production_vertex()) bparttoremove.push_back(bpart);
141  }
142  for (auto bpart: bparttoremove) {
143  bpart->production_vertex()->remove_particle_out(bpart);
144  }
145  }
146 
147  // Some heuristics to catch problematic cases
148  std::vector<HepMC::GenParticlePtr> semi_disconnected, decay_loop_particles;
149  for (auto ip : evt->particles()) {
150  // Skip this particle if (somehow) its pointer is null
151  if (!ip) continue;
152  bool particle_to_fix = false;
153  int abspid = std::abs(ip->pdg_id());
154  auto vProd = ip->production_vertex();
155  auto vEnd = ip->end_vertex();
157  if ( (!vProd || vProd->id() == 0) && vEnd && ip->status() != 4) {
158  particle_to_fix = true;
159  ATH_MSG_DEBUG("Found particle " << ip->pdg_id() << " without production vertex! HepMC status = " << ip->status());
160  }
162  if (vProd && !vEnd && ip->status() != 1) {
163  particle_to_fix = true;
164  ATH_MSG_DEBUG("Found particle " << ip->pdg_id() << " without decay vertex! HepMC status = " << ip->status());
165  }
166  if (particle_to_fix) semi_disconnected.push_back(ip);
167  // Case 3: keep track of loop particles inside decay chains (seen in H7+EvtGen)
168  if (abspid == 43 || abspid == 44 || abspid == 30353 || abspid == 30343) {
169  decay_loop_particles.push_back(ip);
170  }
171  }
172 
176  if ( semi_disconnected.size() == 4 || semi_disconnected.size() == 3 || semi_disconnected.size() == 2) {
177  size_t no_endv = 0;
178  size_t no_prov = 0;
179  HepMC::FourVector sum(0,0,0,0);
180  for (const auto& part : semi_disconnected) {
181  if (!part->production_vertex() || !part->production_vertex()->id()) {
182  no_prov++; sum += part->momentum();
183  }
184  if (!part->end_vertex()) {
185  no_endv++; sum -= part->momentum();
186  }
187  }
188  ATH_MSG_INFO("Heuristics: found " << semi_disconnected.size() << " semi-disconnected particles. Momentum sum is " << sum);
190  if (no_endv && no_prov && ( no_endv + no_prov == semi_disconnected.size() )) {
191  if (std::abs(sum.px()) < 1e-2 && std::abs(sum.py()) < 1e-2 && std::abs(sum.pz()) < 1e-2 ) {
192  ATH_MSG_INFO("Try " << no_endv << "->" << no_prov << " splitting/merging.");
193  auto v = HepMC::newGenVertexPtr();
194  for (auto part : semi_disconnected) {
195  if (!part->production_vertex() || part->production_vertex()->id() == 0) v->add_particle_out(part);
196  }
197  for (auto part : semi_disconnected) {
198  if (!part->end_vertex()) v->add_particle_in(part);
199  }
200  evt->add_vertex(v);
201  }
202  }
203  }
204 
209  for (auto part: decay_loop_particles) {
211  auto vend = part->end_vertex();
212  auto vprod = part->production_vertex();
213  if (!vprod || !vend) continue;
214  bool loop_in_decay = true;
217  auto sisters = vend->particles_in();
218  for (auto sister: sisters) {
219  if (vprod != sister->production_vertex()) loop_in_decay = false;
220  }
221  if (!loop_in_decay) continue;
222 
224  auto daughters = vend->particles_out();
225  for (auto p : daughters) vprod->add_particle_out(p);
226  for (auto sister : sisters) {
227  vprod->remove_particle_out(sister);
228  vend->remove_particle_in(sister);
229  evt->remove_particle(sister);
230  }
231  evt->remove_vertex(vend);
232 
233  }
234 
235  // Event particle content cleaning -- remove "bad" structures
236  std::vector<HepMC::GenParticlePtr> toremove;
237  for (auto ip: evt->particles()) {
238  // Skip this particle if (somehow) its pointer is null
239  if (!ip) continue;
240  m_totalSeen += 1;
241  // Flag to declare if a particle should be removed
242  bool bad_particle = false;
243  // Check for loops
244  if ( m_killLoops && isSimpleLoop(ip) ) {
245  bad_particle = true;
246  m_loopKilled += 1;
247  ATH_MSG_DEBUG( "Found a looper : " );
249  }
250  // Check on PDG ID 0
251  if ( m_killPDG0 && isPID0(ip) ) {
252  bad_particle = true;
253  m_pdg0Killed += 1;
254  ATH_MSG_DEBUG( "Found PDG ID 0 : " );
256  }
257  // Clean decays
258  int abs_pdg_id = std::abs(ip->pdg_id());
259  bool is_decayed_weak_boson = ( abs_pdg_id == 23 || abs_pdg_id == 24 || abs_pdg_id == 25 ) && ip->end_vertex();
260  if ( m_cleanDecays && isNonTransportableInDecayChain(ip) && !is_decayed_weak_boson ) {
261  bad_particle = true;
262  m_decayCleaned += 1;
263  ATH_MSG_DEBUG( "Found a bad particle in a decay chain : " );
265  }
266  // Only add to the toremove vector once, even if multiple tests match
267  if (bad_particle) toremove.push_back(ip);
268  }
269 
270  // Properties before cleaning
271  const int num_particles_orig = evt->particles().size();
272 
273  // Do the cleaning
274  if (!toremove.empty()) {
275  ATH_MSG_DEBUG("Cleaning event record of " << toremove.size() << " bad particles");
276  for (auto part: toremove) evt->remove_particle(part);
277  }
278 
280  int purged=0;
281  do {
282  purged=0;
283  const std::vector <HepMC::GenParticlePtr> allParticles=evt->particles();
284  for(auto p : allParticles) {
285  HepMC::ConstGenVertexPtr end_v=p->end_vertex();
286  if(p->status() == 2 && !end_v) {
287  evt->remove_particle(p);
288  ++purged;
290  }
291  }
292  }
293  while (purged>0);
294  }
295 
296  const int num_particles_filt = evt->particles().size();
297 
298  if(num_particles_orig!=num_particles_filt) {
299  // Write out the change in the number of particles
300  ATH_MSG_INFO("Particles filtered: " << num_particles_orig << " -> " << num_particles_filt);
301  }
302  #else
303 
304  // Add a unit entry to the event weight vector if it's currently empty
305  if (evt->weights().empty()) {
306  ATH_MSG_DEBUG("Adding a unit weight to empty event weight vector");
307  evt->weights().push_back(1);
308  }
309 
310  // Set a (0,0,0) vertex to be the signal vertex if not already set
311  if (evt->signal_process_vertex() == NULL) {
312  const HepMC::FourVector nullpos;
313  for (HepMC::GenEvent::vertex_const_iterator iv = evt->vertices_begin(); iv != evt->vertices_end(); ++iv) {
314  if ((*iv)->position() == nullpos) {
315  ATH_MSG_DEBUG("Setting representative event position vertex");
316  evt->set_signal_process_vertex(const_cast<HepMC::GenVertex*>(*iv));
317  break;
318  }
319  }
320  }
321 
322 
323  // Some heuristics to catch problematic cases
324  std::vector<HepMC::GenParticlePtr> semi_disconnected, decay_loop_particles;
325  for (auto ip : *evt) {
326  // Skip this particle if (somehow) its pointer is null
327  if (!ip) continue;
328  bool particle_to_fix = false;
329  int abspid = std::abs(ip->pdg_id());
330  auto vProd = ip->production_vertex();
331  auto vEnd = ip->end_vertex();
333  if ( (!vProd || vProd->id() == 0) && vEnd && ip->status() != 4) {
334  particle_to_fix = true;
335  ATH_MSG_DEBUG("Found particle " << ip->pdg_id() << " without production vertex! HepMC status = " << ip->status());
336  }
338  if (vProd && !vEnd && ip->status() != 1) {
339  particle_to_fix = true;
340  ATH_MSG_DEBUG("Found particle " << ip->pdg_id() << " without decay vertex! HepMC status = " << ip->status());
341  }
342  if (particle_to_fix) semi_disconnected.push_back(ip);
343  // Case 3: keep track of loop particles inside decay chains (seen in H7+EvtGen)
344  if (abspid == 43 || abspid == 44 || abspid == 30353 || abspid == 30343) {
345  decay_loop_particles.push_back(ip);
346  }
347  }
348 
351  if (semi_disconnected.size() == 4 ||semi_disconnected.size() == 3 || semi_disconnected.size() == 2) {
352  size_t no_endv = 0;
353  size_t no_prov = 0;
354  double vsum[4] = {0,0,0,0};
355  for (auto part : semi_disconnected) {
356  if (!part->production_vertex() ) {
357  no_prov++;
358  vsum[0] += part->momentum().px();
359  vsum[1] += part->momentum().py();
360  vsum[2] += part->momentum().pz();
361  vsum[3] += part->momentum().e();
362  }
363  if (!part->end_vertex()) {
364  no_endv++;
365  vsum[0] -= part->momentum().px();
366  vsum[1] -= part->momentum().py();
367  vsum[2] -= part->momentum().pz();
368  vsum[3] -= part->momentum().e();
369  }
370  }
371  HepMC::FourVector sum(vsum[0],vsum[1],vsum[2],vsum[3]);
372  ATH_MSG_INFO("Heuristics: found " << semi_disconnected.size() << " semi-disconnected particles. Momentum sum is " << vsum[0] << " " << vsum[1] << " " << vsum[2] << " " << vsum[3]);
374  if (no_endv && no_prov && ( no_endv + no_prov == semi_disconnected.size() )) {
375  if (std::abs(sum.px()) < 1e-2 && std::abs(sum.py()) < 1e-2 && std::abs(sum.pz()) < 1e-2 ) {
376  ATH_MSG_INFO("Try " << no_endv << "->" << no_prov << " splitting/merging.");
377  auto v = HepMC::newGenVertexPtr();
378  for (auto part : semi_disconnected) {
379  if (!part->production_vertex()) v->add_particle_out(part);
380  }
381  for (auto part : semi_disconnected) {
382  if (!part->end_vertex()) v->add_particle_in(part);
383  }
384  evt->add_vertex(v);
385  }
386  }
387  }
388 
393  for (auto part: decay_loop_particles) {
395  auto vend = part->end_vertex();
396  auto vprod = part->production_vertex();
397  if (!vend || !vprod) continue;
398  bool loop_in_decay = true;
400  std::vector<HepMC::GenParticlePtr> sisters;
401  for (auto p = vend->particles_begin(HepMC::parents); p!= vend->particles_end(HepMC::parents); ++p) sisters.push_back(*p);
402  for (auto sister : sisters) {
403  if (vprod != sister->production_vertex()) loop_in_decay = false;
404  }
405  if (!loop_in_decay) continue;
406 
407  std::vector<HepMC::GenParticlePtr> daughters;
408  for (auto p = vend->particles_begin(HepMC::children); p!= vend->particles_end(HepMC::children); ++p) daughters.push_back(*p);
409  for (auto p : daughters) vprod->add_particle_out(p);
410  for (auto sister : sisters) {
411  vprod->remove_particle(sister);
412  vend->remove_particle(sister);
413  }
414  evt->remove_vertex(vend);
415 
416  }
417 
418 
419  // Event particle content cleaning -- remove "bad" structures
420  std::vector<HepMC::GenParticlePtr> toremove; toremove.reserve(10);
421  for (HepMC::GenEvent::particle_const_iterator ip = evt->particles_begin(); ip != evt->particles_end(); ++ip) {
422  // Skip this particle if (somehow) its pointer is null
423  if (*ip == NULL) continue;
424  m_totalSeen += 1;
425 
426  // Flag to declare if a particle should be removed
427  bool bad_particle = false;
428 
429  // Check for loops
430  if ( m_killLoops && isSimpleLoop(*ip) ) {
431  bad_particle = true;
432  m_loopKilled += 1;
433  ATH_MSG_DEBUG( "Found a looper : " );
434  if ( msgLvl( MSG::DEBUG ) ) (*ip)->print();
435  }
436 
437  // Check on PDG ID 0
438  if ( m_killPDG0 && isPID0(*ip) ) {
439  bad_particle = true;
440  m_pdg0Killed += 1;
441  ATH_MSG_DEBUG( "Found PDG ID 0 : " );
442  if ( msgLvl( MSG::DEBUG ) ) (*ip)->print();
443  }
444 
445  // Clean decays
446  int abs_pdg_id = std::abs((*ip)->pdg_id());
447  bool is_decayed_weak_boson = ( abs_pdg_id == 23 || abs_pdg_id == 24 || abs_pdg_id == 25 ) && (*ip)->end_vertex();
448  if ( m_cleanDecays && isNonTransportableInDecayChain(*ip) && !is_decayed_weak_boson ) {
449  bad_particle = true;
450  m_decayCleaned += 1;
451  ATH_MSG_DEBUG( "Found a bad particle in a decay chain : " );
452  if ( msgLvl( MSG::DEBUG ) ) (*ip)->print();
453  }
454 
455  // Only add to the toremove vector once, even if multiple tests match
456  if (bad_particle) toremove.push_back(*ip);
457  }
458 
459  // Properties before cleaning
460  const int num_particles_orig = evt->particles_size();
461  int num_orphan_vtxs_orig = 0;
462  int num_noparent_vtxs_orig = 0;
463  int num_nochild_vtxs_orig = 0;
464  for (auto v = evt->vertices_begin(); v != evt->vertices_end(); ++v) {
465  if ((*v)->particles_in_size()==0&&(*v)->particles_out_size()==0) num_orphan_vtxs_orig++;
466  if ((*v)->particles_in_size()==0) num_noparent_vtxs_orig++;
467  if ((*v)->particles_out_size()==0) num_nochild_vtxs_orig++;
468  }
469 
470  // Do the cleaning
471  if (!toremove.empty()) {
472  ATH_MSG_DEBUG("Cleaning event record of " << toremove.size() << " bad particles");
473  // Clean!
474  int signal_vertex_bc = evt->signal_process_vertex() ? evt->signal_process_vertex()->barcode() : 0;
475  //This is the only place where reduce is used.
476  reduce(evt , toremove);
477  if (evt->barcode_to_vertex (signal_vertex_bc) == nullptr) {
478  evt->set_signal_process_vertex (nullptr);
479  }
480  }
481 
483  int purged=0;
484  do {
485  for (HepMC::GenParticle* p : *evt) {
486  HepMC::ConstGenVertexPtr end_v = p->end_vertex();
487  if (p->status() == 2 && !end_v) {
488  delete p->production_vertex()->remove_particle(p);
489  ++purged;
491  }
492  }
493  }
494  while (purged>0);
495  }
496 
497  // Properties after cleaning
498  const int num_particles_filt = evt->particles_size();
499  if(num_particles_orig!=num_particles_filt) {
500  int num_orphan_vtxs_filt = 0;
501  int num_noparent_vtxs_filt = 0;
502  int num_nochild_vtxs_filt = 0;
503  for (auto v = evt->vertices_begin(); v != evt->vertices_end(); ++v) {
504  if ((*v)->particles_in_size()==0&&(*v)->particles_out_size()==0) num_orphan_vtxs_filt++;
505  if ((*v)->particles_in_size()==0) num_noparent_vtxs_filt++;
506  if ((*v)->particles_out_size()==0) num_nochild_vtxs_filt++;
507  }
508 
509  // Write out the change in the number of particles
510  ATH_MSG_INFO("Particles filtered: " << num_particles_orig << " -> " << num_particles_filt);
511  // Warn if the numbers of "strange" vertices have changed
512  if (num_orphan_vtxs_filt != num_orphan_vtxs_orig)
513  ATH_MSG_WARNING("Change in orphaned vertices: " << num_orphan_vtxs_orig << " -> " << num_orphan_vtxs_filt);
514  if (num_noparent_vtxs_filt != num_noparent_vtxs_orig)
515  ATH_MSG_WARNING("Change in no-parent vertices: " << num_noparent_vtxs_orig << " -> " << num_noparent_vtxs_filt);
516  if (num_nochild_vtxs_filt != num_nochild_vtxs_orig)
517  ATH_MSG_WARNING("Change in no-parent vertices: " << num_nochild_vtxs_orig << " -> " << num_nochild_vtxs_filt);
518  }
519 #endif
520  }
521  return StatusCode::SUCCESS;
522 }
523 
524 
526  if (m_killLoops ) ATH_MSG_INFO( "Removed " << m_loopKilled << " of " << m_totalSeen << " particles because of loops." );
527  if (m_killPDG0 ) ATH_MSG_INFO( "Removed " << m_pdg0Killed << " of " << m_totalSeen << " particles because of PDG ID 0." );
528  if (m_cleanDecays) ATH_MSG_INFO( "Removed " << m_decayCleaned << " of " << m_totalSeen << " particles while cleaning decay chains." );
529  if(m_purgeUnstableWithoutEndVtx) ATH_MSG_INFO( "Removed " << m_unstablePurged << " of " << m_totalSeen << " unstable particles because they had no decay vertex." );
530  if (!m_pidmap.empty()) ATH_MSG_INFO( "Replaced " << m_replacedPIDs << "PIDs of particles." );
531  return StatusCode::SUCCESS;
532 }
533 
534 
536 
537 
538 // Identify PDG ID = 0 particles, usually from HEPEVT padding
540  return p->pdg_id() == 0;
541 }
542 
543 // Identify the particles from
544 bool FixHepMC::fromDecay(const HepMC::ConstGenParticlePtr& p, std::shared_ptr<std::set<int> >& storage) const {
545  if (!p) return false;
546  auto v=p->production_vertex();
547  if (!v) return false;
548 #ifdef HEPMC3
549  for ( const auto& anc: v->particles_in()) {
550  if (MC::isDecayed(anc) && (MC::isTau(anc->pdg_id()) || MC::isHadron(anc->pdg_id()))) return true;
551  }
552  if (storage->find(p->id()) != storage->end()) return false;
553  storage->insert(p->id());
554  for ( const auto& anc: v->particles_in()) {
555  if (fromDecay(anc, storage)) return true;
556  }
557 #else
558  for (auto anc=v->particles_in_const_begin(); anc != v->particles_in_const_end(); ++anc) {
559  if (MC::isDecayed((*anc)) && (MC::isTau((*anc)->pdg_id()) || MC::isHadron((*anc)->pdg_id()))) return true;
560  }
561  if (storage->find(p->barcode()) != storage->end()) return false;
562  storage->insert(p->barcode());
563  for (auto anc=v->particles_in_const_begin(); anc != v->particles_in_const_end(); ++anc){
564  if (fromDecay(*anc, storage)) return true;
565  }
566 #endif
567  return false;
568 }
569 
570 // Identify non-transportable stuff _after_ hadronisation
572  auto storage = std::make_shared<std::set<int>>();
573  return !MC::isTransportable(p->pdg_id()) && fromDecay(p, storage);
574 }
575 
576 // Identify internal "loop" particles
578  return (p->production_vertex() == p->end_vertex() && p->end_vertex() != nullptr);
579 }
580 
582 
583 #endif
584 
LArG4FSStartPointFilter.part
part
Definition: LArG4FSStartPointFilter.py:21
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
FixHepMC::m_replacedPIDs
long m_replacedPIDs
Definition: FixHepMC.h:64
DataModel_detail::const_iterator
Const iterator class for DataVector/DataList.
Definition: DVLIterator.h:82
GenEvent.h
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
FixHepMC::finalize
StatusCode finalize()
Definition: FixHepMC.cxx:525
FixHepMC::m_pdg0Killed
long m_pdg0Killed
Definition: FixHepMC.h:60
AthCommonDataStore< AthCommonMsg< Algorithm > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
python.DecayParser.parents
parents
print ("==> buf:",buf)
Definition: DecayParser.py:31
GenVertex.h
HepMC::GenParticlePtr
GenParticle * GenParticlePtr
Definition: GenParticle.h:37
PlotCalibFromCool.begin
begin
Definition: PlotCalibFromCool.py:94
FixHepMC::m_cleanDecays
bool m_cleanDecays
Definition: FixHepMC.h:53
AthCommonMsg< Algorithm >::msgLvl
bool msgLvl(const MSG::Level lvl) const
Definition: AthCommonMsg.h:30
LArG4FSStartPointFilter.evt
evt
Definition: LArG4FSStartPointFilter.py:42
FixHepMC::execute
StatusCode execute()
Definition: FixHepMC.cxx:93
HepMC::Print::line
void line(std::ostream &os, const GenEvent &e)
Definition: GenEvent.h:676
python.DataFormatRates.events
events
Definition: DataFormatRates.py:105
reduce
void reduce(HepMC::GenEvent *ge, std::vector< HepMC::GenParticlePtr > toremove)
Remove unwanted particles from the event, collapsing the graph structure consistently.
Definition: FixHepMC.cxx:83
HepMC::set_signal_process_vertex
void set_signal_process_vertex(GenEvent *e, T v)
Definition: GenEvent.h:650
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
GenBase
Base class for common behaviour of MC truth algorithms.
Definition: GenBase.h:47
convertTimingResiduals.sum
sum
Definition: convertTimingResiduals.py:55
HepMC::newGenVertexPtr
GenVertexPtr newGenVertexPtr(const HepMC::FourVector &pos=HepMC::FourVector(0.0, 0.0, 0.0, 0.0), const int i=0)
Definition: GenVertex.h:64
FixHepMC.h
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
find_tgc_unfilled_channelids.ip
ip
Definition: find_tgc_unfilled_channelids.py:3
FixHepMC::m_decayCleaned
long m_decayCleaned
Definition: FixHepMC.h:61
FixHepMC::fromDecay
bool fromDecay(const HepMC::ConstGenParticlePtr &p, std::shared_ptr< std::set< int > > &storage) const
Definition: FixHepMC.cxx:544
isTau
bool isTau(const T &p)
Definition: AtlasPID.h:197
FixHepMC::m_totalSeen
long m_totalSeen
Definition: FixHepMC.h:63
FixHepMC::m_looper
MC::Loops< HepMC::GenEvent, HepMC::ConstGenParticlePtr, HepMC::ConstGenVertexPtr > m_looper
member to detect loops
Definition: FixHepMC.h:70
HepMC::ConstGenParticlePtr
const GenParticle * ConstGenParticlePtr
Definition: GenParticle.h:38
FixHepMC::m_purgeUnstableWithoutEndVtx
bool m_purgeUnstableWithoutEndVtx
Definition: FixHepMC.h:54
FixHepMC::isSimpleLoop
bool isSimpleLoop(const HepMC::ConstGenParticlePtr &p) const
Definition: FixHepMC.cxx:577
MC::Loops::loop_particles
const std::vector< Prt > & loop_particles() const
Definition: Loops.h:25
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
isHadron
bool isHadron(const T &p)
Definition: AtlasPID.h:324
FixHepMC::isNonTransportableInDecayChain
bool isNonTransportableInDecayChain(const HepMC::ConstGenParticlePtr &p) const
Definition: FixHepMC.cxx:571
python.PyAthena.v
v
Definition: PyAthena.py:154
MC::Loops::loop_vertices
const std::vector< Vtx > & loop_vertices() const
Definition: Loops.h:28
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
isTransportable
bool isTransportable(const T &p)
Definition: AtlasPID.h:807
FixHepMC::isPID0
bool isPID0(const HepMC::ConstGenParticlePtr &p) const
Definition: FixHepMC.cxx:539
MC::isDecayed
bool isDecayed(const T &p)
Identify if the particle decayed.
Definition: HepMCHelpers.h:42
DEBUG
#define DEBUG
Definition: page_access.h:11
python.DecayParser.children
children
Definition: DecayParser.py:32
FixHepMC::m_killLoops
bool m_killLoops
Definition: FixHepMC.h:51
HepMC::ConstGenVertexPtr
const HepMC::GenVertex * ConstGenVertexPtr
Definition: GenVertex.h:60
MC::Loops::findLoops
int findLoops(const Evt *evt, bool force)
Definition: Loops.h:31
FixHepMC::m_loopKilled
long m_loopKilled
Definition: FixHepMC.h:59
FixHepMC::m_killPDG0
bool m_killPDG0
Definition: FixHepMC.h:52
FixHepMC::m_pidmap
std::map< int, int > m_pidmap
map of pids to change.
Definition: FixHepMC.h:67
FixHepMC::m_unstablePurged
long m_unstablePurged
Definition: FixHepMC.h:62
HepMCHelpers.h
GenParticle
@ GenParticle
Definition: TruthClasses.h:30
FixHepMC::FixHepMC
FixHepMC(const std::string &name, ISvcLocator *pSvcLocator)
Definition: FixHepMC.cxx:14
HepMC::signal_process_vertex
GenVertex * signal_process_vertex(const GenEvent *e)
Definition: GenEvent.h:625