DD4hep  1.37.0
Detector Description Toolkit for High Energy Physics
Geant4ParticleHandler.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 // Author : M.Frank
11 //
12 //==========================================================================
13 
14 // Framework include files
15 #include <DD4hep/Primitives.h>
16 #include <DD4hep/InstanceCount.h>
17 #include <DDG4/Geant4StepHandler.h>
19 #include <DDG4/Geant4EventAction.h>
26 
27 // Geant4 include files
28 #include <G4Step.hh>
29 #include <G4Track.hh>
30 #include <G4Event.hh>
31 #include <G4TrackStatus.hh>
32 #include <G4PrimaryVertex.hh>
33 #include <G4PrimaryParticle.hh>
34 #include <G4TrackingManager.hh>
35 #include <G4ParticleDefinition.hh>
36 #include <CLHEP/Units/SystemOfUnits.h>
37 
38 // C/C++ include files
39 #include <set>
40 #include <algorithm>
41 
42 using namespace dd4hep::sim;
43 using PropertyMask = dd4hep::detail::ReferenceBitMask<int>;
44 using PropertyMaskView = dd4hep::detail::ReferenceBitMask<const int>;
45 
49 {
50  InstanceCount::increment(this);
51  //generatorAction().adopt(this);
52  eventAction().callAtBegin(this, &Geant4ParticleHandler::beginEvent);
53  eventAction().callAtEnd(this, &Geant4ParticleHandler::endEvent);
54  trackingAction().callAtFinal(this, &Geant4ParticleHandler::end,CallbackSequence::FRONT);
55  trackingAction().callUpFront(this, &Geant4ParticleHandler::begin,CallbackSequence::FRONT);
56  steppingAction().call(this, &Geant4ParticleHandler::step);
57  m_globalParticleID = 0;
58  declareProperty("PrintEndTracking", m_printEndTracking = false);
59  declareProperty("PrintStartTracking", m_printStartTracking = false);
60  declareProperty("KeepAllParticles", m_keepAll = false);
61  declareProperty("SaveProcesses", m_processNames);
62  declareProperty("MinimalKineticEnergy", m_kinEnergyCut = 100e0*CLHEP::MeV);
63  declareProperty("MinDistToParentVertex", m_minDistToParentVertex = 2.2e-14*CLHEP::mm);//default tolerance for g4ThreeVector isNear
64  m_needsControl = true;
65 }
66 
68 Geant4ParticleHandler::Geant4ParticleHandler()
70 {
71  m_globalParticleID = 0;
72  declareProperty("PrintEndTracking", m_printEndTracking = false);
73  declareProperty("PrintStartTracking", m_printStartTracking = false);
74  declareProperty("KeepAllParticles", m_keepAll = false);
75  declareProperty("SaveProcesses", m_processNames);
76  declareProperty("MinimalKineticEnergy", m_kinEnergyCut = 100e0*CLHEP::MeV);
77  declareProperty("MinDistToParentVertex", m_minDistToParentVertex = 2.2e-14*CLHEP::mm);//default tolerance for g4ThreeVector isNear
78  m_needsControl = true;
79 }
80 
82 Geant4ParticleHandler::~Geant4ParticleHandler() {
83  clear();
84  for( auto* h : this->m_userHandlers )
85  detail::releasePtr(h);
86  this->m_userHandlers.clear();
88 }
89 
92  return *this;
93 }
94 
97  if ( action ) {
98  if ( Geant4UserParticleHandler* h = dynamic_cast<Geant4UserParticleHandler*>(action) ) {
99  this->m_userHandlers.push_back(h);
100  h->addRef();
101  return true;
102  }
103  except("Cannot add an user particle handler object [Object-exists].");
104  }
105  except("Cannot add an invalid user particle handler object [NULL-object].");
106  return false;
107 }
108 
111  detail::releaseObjects(m_particleMap);
112  m_particleMap.clear();
113  // m_suspendedPM should already be empty and cleared...
114  assert(m_suspendedPM.empty() && "There was something wrong with the particle record treatment, please open a bug report!");
115  m_equivalentTracks.clear();
116 }
117 
119 void Geant4ParticleHandler::mark(const G4Track* track, int reason) {
120  if ( track ) {
121  if ( reason != 0 ) {
122  PropertyMask(m_currTrack.reason).set(reason);
123  return;
124  }
125  }
126  except("Cannot mark the G4Track if the pointer is invalid!");
127 }
128 
130 void Geant4ParticleHandler::mark(const G4Step* step_value, int reason) {
131  if ( step_value ) {
132  mark(step_value->GetTrack(),reason);
133  return;
134  }
135  except("Cannot mark the G4Track if the step-pointer is invalid!");
136 }
137 
139 void Geant4ParticleHandler::mark(const G4Step* step_value) {
140  if ( step_value ) {
141  this->mark(step_value->GetTrack());
142  return;
143  }
144  except("Cannot mark the G4Track if the step-pointer is invalid!");
145 }
146 
148 void Geant4ParticleHandler::mark(const G4Track* track) {
150  mask.set(G4PARTICLE_CREATED_HIT);
152  // If yes, flag it, because it is a candidate for removal.
153  G4LogicalVolume* vol = track->GetVolume()->GetLogicalVolume();
154  // Volume is never null since track is always within the world volume
155  G4VSensitiveDetector* g4 = vol->GetSensitiveDetector();
156  Geant4ActionSD* sd = dynamic_cast<Geant4ActionSD*>(g4);
157  if( sd ) {
158  std::string typ = sd->sensitiveType();
159 
160  if ( typ == "calorimeter" ) {
162  }
163  else if ( typ == "tracker" ) {
164  mask.set( G4PARTICLE_CREATED_TRACKER_HIT );
165  }
166  else { // Assume by default "tracker"
167  mask.set( G4PARTICLE_CREATED_TRACKER_HIT );
168  }
169  }
170  if( !this->m_userHandlers.empty() ) {
171  for( auto* h : this->m_userHandlers )
172  h->mark_track( track, &m_currTrack );
173  }
174 }
175 
176 
177 
178 
180 void Geant4ParticleHandler::operator()(G4Event* event) {
181  typedef Geant4MonteCarloTruth _MC;
182  debug("+++ Event:%d Add EVENT extension of type Geant4ParticleHandler.....",event->GetEventID());
183  context()->event().addExtension((_MC*)this, false);
184  clear();
186  for( auto* h : this->m_userHandlers )
187  h->generate(event, this);
188 }
189 
191 void Geant4ParticleHandler::step(const G4Step* step_value, G4SteppingManager* mgr) {
192  typedef std::vector<const G4Track*> _Sec;
193  ++m_currTrack.steps;
195  //
196  // Tracks below the energy threshold are NOT stored.
197  // If these tracks produce hits or are selected due to another signature,
198  // this criterium will anyhow take precedence.
199  //
200  const _Sec* sec=step_value->GetSecondaryInCurrentStep();
201  if ( not sec->empty() ) {
203  }
204  }
206  for( auto* h : this->m_userHandlers )
207  h->step(step_value, mgr, m_currTrack);
208 }
209 
211 void Geant4ParticleHandler::begin(const G4Track* track) {
212  Geant4TrackHandler h(track);
213  double kine = h.kineticEnergy();
214  G4ThreeVector mom = h.momentum();
215  const G4ThreeVector& v = h.vertex();
216  int reason = (kine > m_kinEnergyCut) ? G4PARTICLE_ABOVE_ENERGY_THRESHOLD : 0;
217  const G4PrimaryParticle* prim = h.primary();
218  Particle* prim_part = 0;
219 
220  // if particles are not tracked to the end, we pick up where we stopped previously
221  if ( m_haveSuspended ) {
222  // primary particles are already in the particle map, we don't have to store them in another map
223  auto existingParticle = m_particleMap.find(h.id());
224  if ( existingParticle != m_particleMap.end() ) {
225  m_currTrack.get_data(*(existingParticle->second));
226  return;
227  }
228  //other particles might not be in the particleMap yet, so we take them from here
229  existingParticle = m_suspendedPM.find(h.id());
230  if ( existingParticle != m_suspendedPM.end() ) {
231  m_currTrack.get_data(*(existingParticle->second));
232  // make sure we delete a suspended particle in the map, fill it back later...
233  delete (*existingParticle).second;
234  m_suspendedPM.erase(existingParticle);
235  return;
236  }
237  }
238 
239  if ( prim ) {
240  prim_part = m_primaryMap->get(prim);
241  if ( !prim_part ) {
242  except("+++ Tracking preaction: Primary particle without generator particle!");
243  }
245  m_particleMap[h.id()] = prim_part->addRef();
246  }
247 
248  if ( prim_part ) {
249  m_currTrack.id = prim_part->id;
250  m_currTrack.reason = prim_part->reason|reason;
251  m_currTrack.mask = prim_part->mask;
252  m_currTrack.status = prim_part->status;
253  m_currTrack.genStatus = prim_part->genStatus;
254  m_currTrack.spin[0] = prim_part->spin[0];
255  m_currTrack.spin[1] = prim_part->spin[1];
256  m_currTrack.spin[2] = prim_part->spin[2];
257  m_currTrack.colorFlow[0] = prim_part->colorFlow[0];
258  m_currTrack.colorFlow[1] = prim_part->colorFlow[1];
259  m_currTrack.parents = prim_part->parents;
260  m_currTrack.daughters = prim_part->daughters;
261  m_currTrack.pdgID = prim_part->pdgID;
262  m_currTrack.mass = prim_part->mass;
263  m_currTrack.charge = int(3.0 * h.charge());
264  }
265  else {
267  m_currTrack.reason = reason;
268  m_currTrack.mask = 0;
271  m_currTrack.spin[0] = 0;
272  m_currTrack.spin[1] = 0;
273  m_currTrack.spin[2] = 0;
274  m_currTrack.colorFlow[0] = 0;
275  m_currTrack.colorFlow[1] = 0;
276  m_currTrack.parents.clear();
277  m_currTrack.daughters.clear();
278  m_currTrack.pdgID = h.pdgID();
279  m_currTrack.mass = h.mass();
280  m_currTrack.charge = int(3.0 * h.charge());
282  }
283  m_currTrack.steps = 0;
285  m_currTrack.g4Parent = h.parent();
286  m_currTrack.originalG4ID= h.id();
287  m_currTrack.process = h.creatorProcess();
288  m_currTrack.time = h.globalTime();
289  m_currTrack.vsx = v.x();
290  m_currTrack.vsy = v.y();
291  m_currTrack.vsz = v.z();
292  m_currTrack.vex = 0.0;
293  m_currTrack.vey = 0.0;
294  m_currTrack.vez = 0.0;
295  m_currTrack.psx = mom.x();
296  m_currTrack.psy = mom.y();
297  m_currTrack.psz = mom.z();
298  m_currTrack.pex = 0.0;
299  m_currTrack.pey = 0.0;
300  m_currTrack.pez = 0.0;
301 
303  // If the creator process of the track is in the list of process products to be kept, set the proper flag
304  if ( m_currTrack.process ) {
305  Processes::iterator i=find(m_processNames.begin(),m_processNames.end(),m_currTrack.process->GetProcessName());
306  if ( i != m_processNames.end() ) {
307  mask.set(G4PARTICLE_KEEP_PROCESS);
308  }
309  }
310  if ( m_keepAll ) {
311  mask.set(G4PARTICLE_KEEP_ALWAYS);
312  }
313 
314  G4LogicalVolume* vol = track->GetVolume()->GetLogicalVolume();
315  // Volume is never null since track is always within the world volume
316  G4VSensitiveDetector* g4 = vol->GetSensitiveDetector();
317  if( Geant4ActionSD* sd = dynamic_cast<Geant4ActionSD*>(g4) ) {
318  std::string typ = sd->sensitiveType();
319  if( typ == "calorimeter" ) {
321  }
322  }
323 
325  for( auto* handler : this->m_userHandlers )
326  handler->begin(track, m_currTrack);
327 }
328 
330 void Geant4ParticleHandler::end(const G4Track* track) {
331  Geant4TrackHandler h(track);
333  const int g4_id = h.id();
334 
335  int32_t track_reason = m_currTrack.reason;
337  // Update vertex end point and final momentum
338  G4ThreeVector mom = track->GetMomentum();
339  const G4ThreeVector& pos = track->GetPosition();
340  ph->pex = mom.x();
341  ph->pey = mom.y();
342  ph->pez = mom.z();
343  ph->vex = pos.x();
344  ph->vey = pos.y();
345  ph->vez = pos.z();
346 
347  // Set the simulator status bits
348  PropertyMask simStatus(m_currTrack.status);
349 
350  // check if the last step ended on the worldVolume boundary
351  const G4Step* theLastStep = track->GetStep();
352  G4StepPoint* theLastPostStepPoint = NULL;
353  if( theLastStep ) theLastPostStepPoint = theLastStep->GetPostStepPoint();
354  if( theLastPostStepPoint &&
355  ( theLastPostStepPoint->GetStepStatus() == fWorldBoundary //particle left world volume
356  //|| theLastPostStepPoint->GetStepStatus() == fGeomBoundary
357  )
358  ) {
359  simStatus.set(G4PARTICLE_SIM_LEFT_DETECTOR);
360  }
361 
362  if( track->GetKineticEnergy() <= 0. ) {
363  simStatus.set(G4PARTICLE_SIM_STOPPED);
364  }
365 
366  PropertyMask reason_mask(track_reason);
367  if( reason_mask.isSet( G4PARTICLE_STARTED_IN_CALORIMETER ) ) {
368  std::string end_volume_type;
369  bool calo_hits = reason_mask.isSet(G4PARTICLE_CREATED_CALORIMETER_HIT);
370  bool tracker_hits = reason_mask.isSet(G4PARTICLE_CREATED_TRACKER_HIT);
371  G4LogicalVolume* vol = track->GetVolume()->GetLogicalVolume();
372  // Volume is never null since track is always within the world volume
373  G4VSensitiveDetector* g4 = vol->GetSensitiveDetector();
374  if( Geant4ActionSD* sd = dynamic_cast<Geant4ActionSD*>(g4) ) {
375  end_volume_type = sd->sensitiveType();
376  }
377  if( tracker_hits || end_volume_type == "tracker" ) {
378  reason_mask.set(G4PARTICLE_SIM_BACKSCATTER);
379  debug("+++ Track: %6d back-scattered to tracking volume. Origin: calorimeter End: %s "
380  "CALO-hits:%s TRACKER-hits:%s --> keep particle in MC history",
381  g4_id, end_volume_type.c_str(), yes_no(calo_hits), yes_no(tracker_hits));
382  }
383  }
384 
386  for( auto* handler : this->m_userHandlers )
387  handler->end(track, m_currTrack);
388 
389  //
390  // These are candidate tracks with a probability to be stored due to their properties:
391  // - primary particle
392  // - hits created
393  // - secondaries
394  // - above energy threshold
395  // - to be kept due to creator process
396  // - to be kept due to user information of type 'Geant4ParticleInformation' stored in the G4Track
397  //
398  Geant4ParticleInformation* track_info =
399  dynamic_cast<Geant4ParticleInformation*>(track->GetUserInformation());
400  if( !mask.isNull() || track_info || reason_mask.isSet(G4PARTICLE_SIM_BACKSCATTER) ) {
401  m_equivalentTracks[g4_id] = g4_id;
402  ParticleMap::iterator ip = m_particleMap.find(g4_id);
403  if( mask.isSet(G4PARTICLE_PRIMARY) ) {
404  ph.dump2(outputLevel()-1,name(),"Add Primary", h.id(), ip != m_particleMap.end());
405  }
406  if( reason_mask.isSet(G4PARTICLE_SIM_BACKSCATTER) ) {
407  mask.set(G4PARTICLE_KEEP_ALWAYS);
408  info("+++ Track: %6d Particle back-scattering to tracker --> keep particle in MC history.", g4_id);
409  }
410  // Create a new MC particle from the current track information saved in the pre-tracking action
411  Particle* part = 0;
412  if( ip==m_particleMap.end() ) part = m_particleMap[g4_id] = new Particle();
413  else part = (*ip).second;
414  if( track_info ) {
415  mask.set(G4PARTICLE_KEEP_USER);
416  part->extension.reset(track_info->release());
417  }
418  part->get_data(m_currTrack);
419  }
420  else {
421  // These are tracks without any special properties.
422  //
423  // We will not store them on the record, but have to memorise the
424  // track identifier in order to restore the history for the created hits.
425  int pid = m_currTrack.g4Parent;
426  m_equivalentTracks[g4_id] = pid;
427  // Need to find the last stored particle and OR this particle's mask
428  // with the mask of the last stored particle.
429  // Walk up the equivalent-track chain to find the nearest kept ancestor.
430  auto iend = m_equivalentTracks.end(), iequiv=m_equivalentTracks.end();
431  const int start_pid = pid;
432  ParticleMap::iterator ip;
433  for(ip=m_particleMap.find(pid); ip == m_particleMap.end(); ip=m_particleMap.find(pid)) {
434  if (iequiv=m_equivalentTracks.find(pid); iequiv == iend) break; // ERROR
435  pid = (*iequiv).second;
436  }
437  // Path compression: point all intermediate entries directly to the root pid,
438  // so future walks from nearby tracks are O(1) instead of O(chain length).
439  if ( ip != m_particleMap.end() ) {
440  for(int compress=start_pid; compress != pid; ) {
441  auto it = m_equivalentTracks.find(compress);
442  if(it == iend) break;
443  int next = it->second;
444  it->second = pid;
445  compress = next;
446  }
447  (*ip).second->reason |= track_reason;
448  }
449  else
450  ph.dumpWithVertex(outputLevel()+3,name(),"FATAL: No real particle parent present");
451  }
452 
453  if( track->GetTrackStatus() == fSuspend ) {
454  m_haveSuspended = true;
455  //track is already in particle map, we pick it up from there in begin again
456  if(m_particleMap.find(g4_id) != m_particleMap.end()) return;
457  //track is not already stored, keep it in special map
458  auto iPart = m_suspendedPM.emplace(g4_id, new Particle());
459  (iPart.first->second)->get_data(m_currTrack);
460  return; // we trust that we eventually return to this function with another status and go on then
461  }
462 
463 }
464 
466 void Geant4ParticleHandler::beginEvent(const G4Event* event) {
468  info("+++ Event %d Begin event action. Access event related information.",event->GetEventID());
470  m_globalParticleID = interaction->nextPID();
471  m_particleMap.clear();
472  m_equivalentTracks.clear();
474  for( auto* h : this->m_userHandlers )
475  h->begin(event);
476 }
477 
479 void Geant4ParticleHandler::dumpMap(const char* tag) const {
480  const std::string& n = name();
481  Geant4ParticleHandle::header4(INFO,n,tag);
482  for(ParticleMap::const_iterator iend=m_particleMap.end(), i=m_particleMap.begin(); i!=iend; ++i) {
483  Geant4ParticleHandle((*i).second).dump4(INFO,n,tag);
484  }
485 }
486 
488 void Geant4ParticleHandler::endEvent(const G4Event* event) {
489  int count = 0;
490  int level = outputLevel();
491  do {
492  if ( level <= VERBOSE ) dumpMap("Particle ");
493  debug("+++ Iteration:%d Tracks:%d Equivalents:%d",++count,m_particleMap.size(),m_equivalentTracks.size());
494  } while( recombineParents() > 0 );
495 
496  if ( level <= VERBOSE ) dumpMap( "Recombined");
497  // Rebase the simulated tracks, so that they fit to the generator particles
499  if ( level <= VERBOSE ) dumpMap( "Rebased ");
500  // Consistency check....
503  for( auto* h : this->m_userHandlers )
504  h->end(event);
506 
507  // Now export the data to the final record.
510  m_primaryMap = 0;
511  clear();
512 }
513 
517  TrackEquivalents equivalents, orgParticles;
518  ParticleMap finalParticles;
519  ParticleMap::const_iterator ipar, iend, i;
520  int count;
521 
523  ParticleMap& pm = interaction->particles;
524 
525  // (1.0) Copy the pre-defined particle mapping for the simulated tracks
526  // It is assumed the mapping is ZERO based without holes.
527  for(count = 0, iend=pm.end(), i=pm.begin(); i!=iend; ++i) {
528  Particle* p = (*i).second;
529  orgParticles[p->id] = p->id;
530  finalParticles[p->id] = p;
531  if ( p->id > count ) count = p->id;
532  if ( (p->reason&G4PARTICLE_PRIMARY) != G4PARTICLE_PRIMARY ) {
533  p->addRef();
534  }
535  }
536  // (1.1) Define the new particle mapping for the simulated tracks
537  for(++count, iend=m_particleMap.end(), i=m_particleMap.begin(); i!=iend; ++i) {
538  Particle* p = (*i).second;
539  if ( (p->reason&G4PARTICLE_PRIMARY) != G4PARTICLE_PRIMARY ) {
540  //if ( orgParticles.find(p->id) == orgParticles.end() ) {
541  orgParticles[p->id] = count;
542  finalParticles[count] = p;
543  p->id = count;
544  ++count;
545  }
546  }
547  // (2) Re-evaluate the corresponding geant4 track equivalents using the new mapping
548  for(TrackEquivalents::iterator ie=m_equivalentTracks.begin(),ie_end=m_equivalentTracks.end(); ie!=ie_end; ++ie) {
549  int g4_equiv = (*ie).first;
550  while( (ipar=m_particleMap.find(g4_equiv)) == m_particleMap.end() ) {
551  TrackEquivalents::const_iterator iequiv = m_equivalentTracks.find(g4_equiv);
552  if ( iequiv == ie_end ) {
553  break; // ERROR !! Will be handled by printout below because ipar==end()
554  }
555  g4_equiv = (*iequiv).second;
556  }
557  TrackEquivalents::mapped_type equiv = (*ie).second;
558  if ( ipar != m_particleMap.end() ) {
559  Geant4ParticleHandle p = (*ipar).second;
560  equivalents[(*ie).first] = p->id; // requires (1) to be filled properly!
561  const G4ParticleDefinition* def = p.definition();
562  int pdg = int(std::abs(def->GetPDGEncoding())+0.1);
563  if ( pdg != 0 && pdg<36 && !(pdg > 10 && pdg < 17) && pdg != 22 ) {
564  error("+++ ERROR: Geant4 particle for track:%d last known is:%d -- is gluon or quark!",equiv,g4_equiv);
565  }
566  pdg = int(std::abs(p->pdgID)+0.1);
567  if ( pdg != 0 && pdg<36 && !(pdg > 10 && pdg < 17) && pdg != 22 ) {
568  error("+++ ERROR(2): Geant4 particle for track:%d last known is:%d -- is gluon or quark!",equiv,g4_equiv);
569  }
570  }
571  else {
572  error("+++ No Equivalent particle for track:%d last known is:%d",equiv,g4_equiv);
573  }
574  }
575 
576  // (3) Compute the particle's parents and daughters.
577  // Replace the original Geant4 track with the
578  // equivalent particle still present in the record.
579  // Note:
580  // We rely here on the ordering of the particles accoding to their
581  // Processing by Geant4 to establish mother daughter relationships.
582  // == > use finalParticles map and NOT m_particleMap.
583  int equiv_id = -1;
584  for( auto& part : finalParticles ) {
585  auto& p = part.second;
586  if ( p->g4Parent > 0 ) {
587  TrackEquivalents::iterator iequ = equivalents.find(p->g4Parent);
588  if ( iequ != equivalents.end() ) {
589  equiv_id = (*iequ).second;//equivalents[p->g4Parent];
590  if ( (ipar=finalParticles.find(equiv_id)) != finalParticles.end() ) {
591  Particle* q = (*ipar).second;
592  bool prim = (p->reason&G4PARTICLE_PRIMARY) == G4PARTICLE_PRIMARY;
593  // We assume that the mother daughter relationship
594  // is filled by the event readers!
595  if ( !prim ) {
596  p->parents.insert(q->id);
597  }
598  if ( !p->parents.empty() ) {
599  int parent_id = (*p->parents.begin());
600  if ( parent_id == q->id )
601  q->daughters.insert(p->id);
602  else if ( !prim )
603  error("+++ Inconsistency in equivalent record! Parent: %d Daughter:%d",q->id, p->id);
604  }
605  else {
606  error("+++ Inconsistency in parent relashionship: %d NO parent!", p->id);
607  }
608  continue;
609  }
610  }
611  error("+++ Inconsistency in particle record: Geant4 parent %d "
612  "of particle %d not in record of final particles!",
613  p->g4Parent,p->id);
614  }
615  }
616 #if 0
617  for(iend=finalParticles.end(), i=finalParticles.begin(); i!=iend; ++i) {
618  Particle* p = (*i).second;
619  if ( p->g4Parent > 0 ) {
620  int parent_id = (*p->parents.begin());
621  if ( (ipar=finalParticles.find(parent_id)) != finalParticles.end() ) {
622  Particle* q = (*ipar).second;
623  // Generator particles have a proper history.
624  // We only deal with particles, which are not of MC origin.
625  //p->parents.insert(q->id);
626  if ( parent_id == q->id )
627  q->daughters.insert(p->id);
628  else
629  error("+++ Inconsistency in equivalent record! Parent: %d Daughter:%d",q->id, p->id);
630  continue;
631  }
632  error("+++ Inconsistency in particle record: Geant4 parent %d "
633  "of particle %d not in record of final particles!",
634  p->g4Parent,p->id);
635  }
636  }
637 #endif
638  m_equivalentTracks = std::move(equivalents);
639  m_particleMap = std::move(finalParticles);
640 }
641 
643 bool Geant4ParticleHandler::defaultDropParticle(const Particle& particle) {
644  PropertyMaskView mask(particle.reason);
645  bool backscatter = mask.isSet(G4PARTICLE_SIM_BACKSCATTER);
646  bool secondaries = mask.isSet(G4PARTICLE_HAS_SECONDARIES);
647  bool tracker_track = mask.isSet(G4PARTICLE_CREATED_TRACKER_HIT);
648  bool calo_track = mask.isSet(G4PARTICLE_CREATED_CALORIMETER_HIT);
649  bool hits_produced = mask.isSet(G4PARTICLE_CREATED_HIT);
650  bool low_energy = !mask.isSet(G4PARTICLE_ABOVE_ENERGY_THRESHOLD);
651 
653  if ( backscatter ) {
654  return false;
655  }
657  else if ( mask.isNull() || (secondaries && low_energy && !hits_produced) ) {
658  return true;
659  }
661  else if ( !hits_produced && low_energy ) {
662  return true;
663  }
665  else if ( !tracker_track && calo_track && low_energy ) {
666  return true;
667  }
668  else {
669  // printout(INFO,name(),"+++ Track: %d should be kept for no obvious reason....",id);
670  }
671  return false;
672 }
673 
677  std::set<int> remove;
678 
680  for(ParticleMap::reverse_iterator i=m_particleMap.rbegin(); i!=m_particleMap.rend(); ++i) {
681  Particle* p = (*i).second;
682  PropertyMask mask(p->reason);
683  // Allow the user to force the particle handling either by
684  // or the reason mask with G4PARTICLE_KEEP_USER or
685  // to set the reason mask to NULL in order to drop it.
686  //
687  // If the mask entry is set to G4PARTICLE_FORCE_KILL
688  // or is set to NULL, the particle is ALWAYS removed
689  //
690  // Note: This may override all other decisions!
691  bool remove_me = false;
692  if ( !this->m_userHandlers.empty() ) {
693  for( auto* h : this->m_userHandlers )
694  remove_me |= h->dropParticle(*p);
695  } else {
696  remove_me = defaultDropParticle(*p);
697  }
698 
699  // Now look at the property mask of the particle
700  if ( mask.isNull() || mask.isSet(G4PARTICLE_FORCE_KILL) ) {
701  remove_me = true;
702  }
703  else if ( mask.isSet(G4PARTICLE_KEEP_USER) ) {
705  mask.set(G4PARTICLE_KEEP_USER);
706  continue;
707  }
708  else if ( mask.isSet(G4PARTICLE_PRIMARY) ) {
710  continue;
711  }
712  else if ( mask.isSet(G4PARTICLE_KEEP_ALWAYS) ) {
713  continue;
714  }
715  else if ( mask.isSet(G4PARTICLE_KEEP_PARENT) ) {
716  //continue;
717  }
718  else if ( mask.isSet(G4PARTICLE_KEEP_PROCESS) ) {
719  if(ParticleMap::iterator ip = m_particleMap.find(p->g4Parent); ip != m_particleMap.end() ) {
720  Particle* parent_part = (*ip).second;
721  PropertyMask parent_mask(parent_part->reason);
722  if ( parent_mask.isSet(G4PARTICLE_ABOVE_ENERGY_THRESHOLD) ) {
723  parent_mask.set(G4PARTICLE_KEEP_PARENT);
724  continue;
725  }
726  }
727  // Low energy stuff. Remove it. Reassign to parent.
728  //remove_me = true;
729  }
730 
732  if ( remove_me ) {
733  int g4_id = (*i).first;
734  remove.insert(g4_id);
735  m_equivalentTracks[g4_id] = p->g4Parent;
736  if(ParticleMap::iterator ip = m_particleMap.find(p->g4Parent); ip != m_particleMap.end() ) {
737  Particle* parent_part = (*ip).second;
738  PropertyMask(parent_part->reason).set(mask.value());
739  parent_part->steps += p->steps;
740  parent_part->secondaries += p->secondaries;
742  for( auto* h : this->m_userHandlers )
743  h->combine(*p, *parent_part);
744  }
745  }
746  }
747  for( int r : remove ) {
748  if( auto ir = m_particleMap.find(r); ir != m_particleMap.end() ) {
749  (*ir).second->release();
750  m_particleMap.erase(ir);
751  }
752  }
753  return int(remove.size());
754 }
755 
758  int num_errors = 0;
759 
761  for(const auto& part : m_particleMap ) {
762  Geant4Particle* particle = part.second;
763  Geant4ParticleHandle p(particle);
764  PropertyMask mask(p->reason);
765  PropertyMask status(p->status);
766  std::set<int>& daughters = p->daughters;
767  ParticleMap::const_iterator j;
768  // For all particles, the set of daughters must be contained in the record.
769  for( int id_dau : daughters ) {
770  if ( j=m_particleMap.find(id_dau); j == m_particleMap.end() ) {
771  ++num_errors;
772  error("+++ Particle:%d Daughter %d is not in particle map!",p->id,id_dau);
773  }
774  }
775  // We assume that particles from the generator have consistent parents
776  // For all other particles except the primaries, the parent must be contained in the record.
777  if ( !mask.isSet(G4PARTICLE_PRIMARY) && !status.anySet(G4PARTICLE_GEN_STATUS) ) {
778  bool in_map = false, in_parent_list = false;
779  int parent_id = -1;
780  if( auto eq_it=m_equivalentTracks.find(p->g4Parent); eq_it != m_equivalentTracks.end() ) {
781  parent_id = (*eq_it).second;
782  in_map = (j=m_particleMap.find(parent_id)) != m_particleMap.end();
783  in_parent_list = p->parents.find(parent_id) != p->parents.end();
784  }
785  if ( !in_map || !in_parent_list ) {
786  char parent_list[1024];
787  parent_list[0] = 0;
788  ++num_errors;
789  p.dumpWithMomentum(ERROR,name(),"INCONSISTENCY");
790  for( int ip : p->parents )
791  ::snprintf(parent_list+strlen(parent_list),sizeof(parent_list)-strlen(parent_list),"%d ",ip);
792  error("+++ Particle:%d Parent %d (G4id:%d) In record:%s In parent list:%s [%s]",
793  p->id,parent_id,p->g4Parent,yes_no(in_map),yes_no(in_parent_list),parent_list);
794  }
795  }
796  }
797 
798  if ( num_errors > 0 ) {
799  except("+++ Consistency check failed. Found %d problems.",num_errors);
800  }
801 }
802 
804  for( auto& part : m_particleMap ) {
805  auto* p = part.second;
806  if( !p->parents.empty() ) {
807  PropertyMask mask(p->status);
808  //if the particle did not go to geant4 none of these flags is set
809  // we shouldn't set the vertex bit in this case.
810  if(not mask.anySet(G4PARTICLE_SIM_CREATED
816  continue;
817  }
818  Geant4Particle *parent(m_particleMap[ *p->parents.begin() ]);
819  const double X( parent->vex - p->vsx );
820  const double Y( parent->vey - p->vsy );
821  const double Z( parent->vez - p->vsz );
822  if( sqrt(X*X + Y*Y + Z*Z) > m_minDistToParentVertex ){
824  }
825  }
826  }
827 }
dd4hep::sim::G4PARTICLE_SIM_CREATED
@ G4PARTICLE_SIM_CREATED
Definition: Geant4Particle.h:87
dd4hep::sim::G4PARTICLE_CREATED_TRACKER_HIT
@ G4PARTICLE_CREATED_TRACKER_HIT
Definition: Geant4Particle.h:65
dd4hep::sim::Geant4ParticleHandler::endEvent
virtual void endEvent(const G4Event *event)
Post-event action callback.
dd4hep::sim::Geant4ParticleHandler::m_keepAll
bool m_keepAll
Property: Flag to keep all particles generated.
Definition: Geant4ParticleHandler.h:99
dd4hep::sim::Geant4ParticleHandler::Geant4ParticleHandler
Geant4ParticleHandler()
No default constructor.
Geant4TrackHandler.h
dd4hep::sim::Geant4PrimaryMap
Data structure to map primaries to particles.
Definition: Geant4Primary.h:64
dd4hep::sim::Geant4PrimaryInteraction::nextPID
int nextPID()
Access a new particle identifier within the interaction.
Definition: Geant4Primary.cpp:65
dd4hep::sim::Geant4ParticleHandler::Particle
Geant4ParticleMap::Particle Particle
Definition: Geant4ParticleHandler.h:74
dd4hep::sim::G4PARTICLE_ABOVE_ENERGY_THRESHOLD
@ G4PARTICLE_ABOVE_ENERGY_THRESHOLD
Definition: Geant4Particle.h:61
dd4hep::sim::Geant4Particle::vsz
double vsz
Definition: Geant4Particle.h:126
dd4hep::sim::G4PARTICLE_KEEP_PARENT
@ G4PARTICLE_KEEP_PARENT
Definition: Geant4Particle.h:63
dd4hep::sim::Geant4Particle::reason
int reason
Definition: Geant4Particle.h:113
Geant4ParticleHandler
Geant4Action to collect the MC particle information.
dd4hep::sim::G4PARTICLE_SIM_PARENT_RADIATED
@ G4PARTICLE_SIM_PARENT_RADIATED
Definition: Geant4Particle.h:93
v
View * v
Definition: MultiView.cpp:28
dd4hep::sim::Geant4Particle::mass
double mass
Particle mass.
Definition: Geant4Particle.h:134
dd4hep::sim::Geant4ParticleHandler::recombineParents
int recombineParents()
Recombine particles and associate the to parents with cleanup.
dd4hep::sim::Geant4Particle::vey
double vey
Definition: Geant4Particle.h:128
dd4hep::sim::Geant4Particle::pez
double pez
Definition: Geant4Particle.h:132
dd4hep::sim::Geant4ParticleHandler::m_primaryMap
Geant4PrimaryMap * m_primaryMap
Primary map.
Definition: Geant4ParticleHandler.h:117
dd4hep::sim::Geant4ParticleInformation::release
ParticleExtension * release()
Definition: Geant4ParticleInformation.h:86
dd4hep::sim::G4PARTICLE_KEEP_USER
@ G4PARTICLE_KEEP_USER
Definition: Geant4Particle.h:66
dd4hep::sim::Geant4PrimaryInteraction
Class modelling a single interaction with multiple primary vertices and particles.
Definition: Geant4Primary.h:95
dd4hep::sim::G4PARTICLE_KEEP_PROCESS
@ G4PARTICLE_KEEP_PROCESS
Definition: Geant4Particle.h:62
dd4hep::sim::Geant4ParticleHandler::m_processNames
Processes m_processNames
Property: All the processes of which the decay products will be explicitly stored.
Definition: Geant4ParticleHandler.h:107
dd4hep::sim::Geant4Particle::id
int id
not persistent
Definition: Geant4Particle.h:110
dd4hep::sim::Geant4ParticleHandler::operator=
Geant4ParticleHandler & operator=(const Geant4ParticleHandler &c)
No assignment operator.
Geant4SensDetAction.h
Geant4TrackingAction.h
dd4hep::sim::Geant4ParticleMap::adopt
void adopt(ParticleMap &pm, TrackEquivalents &equiv)
Adopt particle maps.
Definition: Geant4Particle.cpp:522
Geant4EventAction.h
dd4hep::sim::Geant4ParticleHandler::checkConsistency
void checkConsistency() const
Check the record consistency.
dd4hep::sim::Geant4ParticleHandler::begin
virtual void begin(const G4Track *track)
Pre-track action callback.
dd4hep::sim::Geant4Particle::pdgID
int pdgID
Definition: Geant4Particle.h:117
dd4hep::sim::Geant4Particle::g4Parent
int g4Parent
not persistent
Definition: Geant4Particle.h:112
dd4hep::sim::Geant4Particle::psz
double psz
Definition: Geant4Particle.h:130
dd4hep::sim::G4PARTICLE_CREATED_HIT
@ G4PARTICLE_CREATED_HIT
Definition: Geant4Particle.h:58
dd4hep::sim::Geant4PrimaryInteraction::particles
ParticleMap particles
The map of particles participating in this primary interaction.
Definition: Geant4Primary.h:112
dd4hep::sim::Geant4ParticleHandler::step
virtual void step(const G4Step *step, G4SteppingManager *mgr)
User stepping callback.
dd4hep::sim::Geant4Context::event
Geant4Event & event() const
Access the geant4 event – valid only between BeginEvent() and EndEvent()!
Definition: Geant4Context.cpp:84
Geant4StepHandler.h
dd4hep::sim::Geant4Particle::secondaries
int secondaries
Definition: Geant4Particle.h:116
Geant4UserParticleHandler.h
dd4hep::sim::G4PARTICLE_SIM_BACKSCATTER
@ G4PARTICLE_SIM_BACKSCATTER
Definition: Geant4Particle.h:88
Geant4SteppingAction.h
dd4hep::sim::Geant4ParticleHandler::m_equivalentTracks
TrackEquivalents m_equivalentTracks
Map associating the G4Track identifiers with identifiers of existing MCParticles.
Definition: Geant4ParticleHandler.h:126
dd4hep::sim::Geant4ParticleHandler::m_suspendedPM
ParticleMap m_suspendedPM
Map with stored MC Particles that were suspended by the stepping action.
Definition: Geant4ParticleHandler.h:123
PropertyMask
dd4hep::detail::ReferenceBitMask< int > PropertyMask
Definition: Geant4ParticleHandler.cpp:43
dd4hep::sim::Geant4Particle::get_data
Geant4Particle & get_data(Geant4Particle &c)
Assignment operator.
Definition: Geant4Particle.cpp:67
dd4hep::sim::Geant4ParticleMap
Data structure to map particles produced during the generation and the simulation.
Definition: Geant4Particle.h:339
dd4hep::sim::Geant4Action::info
void info(const char *fmt,...) const
Support of info messages.
Definition: Geant4Action.cpp:215
dd4hep::sim::Geant4Event::extension
T * extension(bool alert=true)
Access to type safe extension object. Exception is thrown if the object is invalid.
Definition: Geant4Context.h:151
dd4hep::sim::Geant4Action::except
void except(const char *fmt,...) const
Support of exceptions: Print fatal message and throw runtime_error.
Definition: Geant4Action.cpp:256
dd4hep::sim::Geant4ParticleHandler::m_userHandlers
std::vector< Geant4UserParticleHandler * > m_userHandlers
User action pointer.
Definition: Geant4ParticleHandler.h:111
dd4hep::sim::G4PARTICLE_SIM_STOPPED
@ G4PARTICLE_SIM_STOPPED
Definition: Geant4Particle.h:91
dd4hep::sim::Geant4ParticleHandler::dumpMap
void dumpMap(const char *tag) const
Debugging: Dump Geant4 particle map.
Geant4UserParticleHandler
Geant4ParticleHandler user extension action called by the particle handler.
dd4hep::sim::Geant4Action::error
void error(const char *fmt,...) const
Support of error messages.
Definition: Geant4Action.cpp:231
Geant4ParticleInformation.h
dd4hep::sim::Geant4Particle::vez
double vez
Definition: Geant4Particle.h:128
Geant4ParticleHandler.h
dd4hep::sim::G4PARTICLE_SIM_DECAY_CALO
@ G4PARTICLE_SIM_DECAY_CALO
Definition: Geant4Particle.h:89
dd4hep::sim::Geant4ParticleHandler::rebaseSimulatedTracks
void rebaseSimulatedTracks(int base)
Rebase the simulated tracks, so that they fit to the generator particles.
dd4hep::sim::Geant4ParticleHandler::TrackEquivalents
Geant4ParticleMap::TrackEquivalents TrackEquivalents
Definition: Geant4ParticleHandler.h:76
G4VSensitiveDetector
Class of the Geant4 toolkit. See http://www-geant4.kek.jp/Reference.
Definition: Geant4Classes.h:59
dd4hep::sim::G4PARTICLE_KEEP_ALWAYS
@ G4PARTICLE_KEEP_ALWAYS
Definition: Geant4Particle.h:67
dd4hep::sim::Geant4Particle::colorFlow
int colorFlow[2]
Definition: Geant4Particle.h:119
dd4hep::sim::Geant4Particle::spin
float spin[3]
Definition: Geant4Particle.h:123
dd4hep::sim::G4PARTICLE_GEN_STATUS
@ G4PARTICLE_GEN_STATUS
Definition: Geant4Particle.h:84
dd4hep::InstanceCount::decrement
static void decrement(T *)
Decrement count according to type information.
Definition: InstanceCount.h:102
dd4hep::sim::Geant4MonteCarloTruth
Default Interface class to handle monte carlo truth records.
Definition: Geant4MonteCarloTruth.h:43
dd4hep::sim::Geant4Particle::genStatus
unsigned short genStatus
Definition: Geant4Particle.h:120
dd4hep::sim::Geant4GeneratorAction
Concrete implementation of the Geant4 generator action base class.
Definition: Geant4GeneratorAction.h:47
dd4hep::sim::Geant4ParticleHandler::m_minDistToParentVertex
double m_minDistToParentVertex
Property: Minimal distance after which the vertexIsNotEndpointOfParent flag is set.
Definition: Geant4ParticleHandler.h:105
dd4hep::sim::Geant4ParticleHandler::adopt
bool adopt(Geant4Action *action)
Adopt the user particle handler.
PropertyMaskView
dd4hep::detail::ReferenceBitMask< const int > PropertyMaskView
Definition: Geant4ParticleHandler.cpp:44
dd4hep::sim::Geant4Particle::status
int status
Definition: Geant4Particle.h:118
dd4hep::sim::Geant4TrackHandler
Helper class to ease the extraction of information from a G4Track object.
Definition: Geant4TrackHandler.h:53
dd4hep::sim::Geant4Particle::originalG4ID
int originalG4ID
Definition: Geant4Particle.h:111
dd4hep::sim::Geant4ActionSD::sensitiveType
virtual const std::string & sensitiveType() const =0
Access to the sensitive type of the detector.
dd4hep::sim::Geant4ParticleHandle::dump4
void dump4(int level, const std::string &src, const char *tag) const
Definition: Geant4Particle.cpp:382
dd4hep::sim::Geant4Particle::daughters
Particles daughters
The list of daughters of this MC particle.
Definition: Geant4Particle.h:142
dd4hep::sim::G4PARTICLE_SIM_DECAY_TRACKER
@ G4PARTICLE_SIM_DECAY_TRACKER
Definition: Geant4Particle.h:90
dd4hep::sim::Geant4Action
Default base class for all Geant 4 actions and derivates thereof.
Definition: Geant4Action.h:113
dd4hep::sim::G4PARTICLE_STARTED_IN_CALORIMETER
@ G4PARTICLE_STARTED_IN_CALORIMETER
Definition: Geant4Particle.h:69
dd4hep::sim::Geant4Action::name
const std::string & name() const
Access name of the action.
Definition: Geant4Action.h:280
dd4hep::sim::Geant4Particle::mask
int mask
Definition: Geant4Particle.h:114
dd4hep::sim::Geant4Particle::time
double time
Particle creation time.
Definition: Geant4Particle.h:136
dd4hep::sim::Geant4Particle::steps
int steps
Definition: Geant4Particle.h:115
dd4hep::sim::Geant4Particle::process
const G4VProcess * process
Reference to the G4VProcess, which created this track.
Definition: Geant4Particle.h:147
dd4hep::sim::Geant4ParticleHandler::defaultDropParticle
static bool defaultDropParticle(const Particle &particle)
Default callback to be answered if the particle should be dropped if NO user handler is installed.
dd4hep::sim::Geant4Particle::pex
double pex
The track momentum at the end vertex.
Definition: Geant4Particle.h:132
dd4hep::sim::Geant4ActionSD
Interface class to access properties of the underlying Geant4 sensitive detector structure.
Definition: Geant4SensDetAction.h:61
dd4hep::sim::Geant4Action::outputLevel
PrintLevel outputLevel() const
Access the output level.
Definition: Geant4Action.h:296
dd4hep::sim::G4PARTICLE_HAS_SECONDARIES
@ G4PARTICLE_HAS_SECONDARIES
Definition: Geant4Particle.h:60
dd4hep::sim::Geant4Particle::vex
double vex
The end vertex.
Definition: Geant4Particle.h:128
dd4hep::sim::Geant4ParticleHandler::m_globalParticleID
int m_globalParticleID
Global particle identifier. Obtained at the begin of the event.
Definition: Geant4ParticleHandler.h:115
dd4hep::sim::Geant4ParticleHandler::m_particleMap
ParticleMap m_particleMap
Map with stored MC Particles.
Definition: Geant4ParticleHandler.h:121
dd4hep::sim::Geant4ParticleHandler::m_haveSuspended
bool m_haveSuspended
Definition: Geant4ParticleHandler.h:124
dd4hep::sim::Geant4Particle::vsx
double vsx
The starting vertex.
Definition: Geant4Particle.h:126
dd4hep::sim::Geant4ParticleHandler::operator()
virtual void operator()(G4Event *event) override
Event generation action callback.
dd4hep::sim::Geant4Particle::psx
double psx
The track momentum at the start vertex.
Definition: Geant4Particle.h:130
dd4hep::sim::Geant4ParticleHandle::definition
const G4ParticleDefinition * definition() const
Access the Geant4 particle definition object (expensive!)
Definition: Geant4Particle.cpp:112
dd4hep::sim::Geant4ParticleHandler::setVertexEndpointBit
void setVertexEndpointBit()
set the endpointIsNotVertexOfParentFlag at the end of the event
dd4hep::sim::Geant4Particle::pey
double pey
Definition: Geant4Particle.h:132
dd4hep::sim::Geant4ParticleHandler::mark
virtual void mark(const G4Track *track) override
Mark a Geant4 track to be kept for later MC truth analysis. Default flag: CREATED_HIT.
dd4hep::sim::G4PARTICLE_FORCE_KILL
@ G4PARTICLE_FORCE_KILL
Definition: Geant4Particle.h:68
dd4hep::sim::Geant4Event::addExtension
void * addExtension(unsigned long long int k, ExtensionEntry *e)
Add an extension object to the detector element.
Definition: Geant4Context.h:140
Primitives.h
dd4hep::sim::G4PARTICLE_SIM_LEFT_DETECTOR
@ G4PARTICLE_SIM_LEFT_DETECTOR
Definition: Geant4Particle.h:92
dd4hep::sim
Namespace for the Geant4 based simulation part of the AIDA detector description toolkit.
Definition: EDM4hepFileReader.cpp:46
dd4hep::sim::Geant4ParticleHandler::clear
void clear()
Clear particle maps.
dd4hep::sim::Geant4ParticleHandle
Data structure to access derived MC particle information.
Definition: Geant4Particle.h:183
dd4hep::sim::Geant4ParticleHandler::m_currTrack
Particle m_currTrack
Local buffer about the 'current' G4Track.
Definition: Geant4ParticleHandler.h:119
dd4hep::sim::Geant4ParticleInformation
Wrapper to store user information in a G4Track.
Definition: Geant4ParticleInformation.h:48
dd4hep::sim::Geant4Particle::parents
Particles parents
The list of parents of this MC particle.
Definition: Geant4Particle.h:140
dd4hep::sim::Geant4Particle::vsy
double vsy
Definition: Geant4Particle.h:126
dd4hep::sim::G4PARTICLE_CREATED_CALORIMETER_HIT
@ G4PARTICLE_CREATED_CALORIMETER_HIT
Definition: Geant4Particle.h:64
dd4hep::sim::Geant4Action::debug
void debug(const char *fmt,...) const
Support of debug messages.
Definition: Geant4Action.cpp:207
dd4hep::sim::Geant4ParticleHandler::m_kinEnergyCut
double m_kinEnergyCut
Property: Flag if the handler is executed in standalone mode and hence must manage particles.
Definition: Geant4ParticleHandler.h:103
dd4hep::sim::Geant4ParticleHandler::end
virtual void end(const G4Track *track)
Post-track action callback.
dd4hep::sim::G4PARTICLE_PRIMARY
@ G4PARTICLE_PRIMARY
Definition: Geant4Particle.h:59
dd4hep::sim::Geant4Particle
Data structure to store the MC particle information.
Definition: Geant4Particle.h:105
dd4hep::sim::Geant4Particle::charge
char charge
Definition: Geant4Particle.h:121
PropertyMask
dd4hep::detail::ReferenceBitMask< int > PropertyMask
Definition: EDM4hepFileReader.cpp:43
InstanceCount.h
dd4hep::sim::Geant4PrimaryMap::get
Geant4Particle * get(const G4PrimaryParticle *particle)
Access DDG4 particle by G4 primary particle.
Definition: Geant4Primary.cpp:44
dd4hep::sim::Geant4Particle::psy
double psy
Definition: Geant4Particle.h:130
dd4hep::sim::Geant4ParticleHandler::ParticleMap
Geant4ParticleMap::ParticleMap ParticleMap
Definition: Geant4ParticleHandler.h:75
dd4hep::sim::Geant4ParticleHandler::beginEvent
virtual void beginEvent(const G4Event *event)
Pre-event action callback.
dd4hep::sim::Geant4ParticleHandle::header4
static void header4(int level, const std::string &src, const char *tag)
Definition: Geant4Particle.cpp:371
dd4hep::sim::Geant4Context
Generic context to extend user, run and event information.
Definition: Geant4Context.h:201
dd4hep::sim::Geant4Action::context
Geant4Context * context() const
Access the context.
Definition: Geant4Action.h:270