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>
48 m_ownsParticles(false), m_userHandler(0), m_primaryMap(0)
50 InstanceCount::increment(
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);
64 m_needsControl =
true;
68 Geant4ParticleHandler::Geant4ParticleHandler()
70 m_ownsParticles(false), m_userHandler(0), m_primaryMap(0)
72 m_globalParticleID = 0;
73 declareProperty(
"PrintEndTracking", m_printEndTracking =
false);
74 declareProperty(
"PrintStartTracking", m_printStartTracking =
false);
75 declareProperty(
"KeepAllParticles", m_keepAll =
false);
76 declareProperty(
"SaveProcesses", m_processNames);
77 declareProperty(
"MinimalKineticEnergy", m_kinEnergyCut = 100e0*CLHEP::MeV);
78 declareProperty(
"MinDistToParentVertex", m_minDistToParentVertex = 2.2e-14*CLHEP::mm);
79 m_needsControl =
true;
83 Geant4ParticleHandler::~Geant4ParticleHandler() {
103 except(
"Cannot add an invalid user particle handler object [Invalid-object-type].");
105 except(
"Cannot add an user particle handler object [Object-exists].");
107 except(
"Cannot add an invalid user particle handler object [NULL-object].");
116 assert(
m_suspendedPM.empty() &&
"There was something wrong with the particle record treatment, please open a bug report!");
128 except(
"Cannot mark the G4Track if the pointer is invalid!");
134 mark(step_value->GetTrack(),reason);
137 except(
"Cannot mark the G4Track if the step-pointer is invalid!");
143 mark(step_value->GetTrack());
146 except(
"Cannot mark the G4Track if the step-pointer is invalid!");
155 G4LogicalVolume* vol = track->GetVolume()->GetLogicalVolume();
159 if ( typ ==
"calorimeter" )
161 else if ( typ ==
"tracker" )
172 debug(
"+++ Event:%d Add EVENT extension of type Geant4ParticleHandler.....",event->GetEventID());
183 typedef std::vector<const G4Track*> _Sec;
191 const _Sec* sec=step_value->GetSecondaryInCurrentStep();
192 if ( not sec->empty() ) {
205 double kine = h.kineticEnergy();
206 G4ThreeVector mom = h.momentum();
207 const G4ThreeVector&
v = h.vertex();
209 const G4PrimaryParticle* prim = h.primary();
225 delete (*existingParticle).second;
234 except(
"+++ Tracking preaction: Primary particle without generator particle!");
314 const int g4_id = h.id();
319 G4ThreeVector mom = track->GetMomentum();
320 const G4ThreeVector& pos = track->GetPosition();
332 const G4Step* theLastStep = track->GetStep();
333 G4StepPoint* theLastPostStepPoint = NULL;
334 if(theLastStep) theLastPostStepPoint = theLastStep->GetPostStepPoint();
335 if( theLastPostStepPoint &&
336 ( theLastPostStepPoint->GetStepStatus() == fWorldBoundary
343 if(track->GetKineticEnergy() <= 0.) {
362 if ( !mask.isNull() || track_info ) {
371 else part = (*ip).second;
388 ParticleMap::iterator ip;
391 pid = (*iequiv).second;
394 (*ip).second->reason |= track_reason;
396 ph.dumpWithVertex(
outputLevel()+3,
name(),
"FATAL: No real particle parent present");
399 if(track->GetTrackStatus() == fSuspend) {
414 info(
"+++ Event %d Begin event action. Access event related information.",event->GetEventID());
427 const std::string& n =
name();
439 if ( level <= VERBOSE )
dumpMap(
"Particle ");
443 if ( level <= VERBOSE )
dumpMap(
"Recombined");
446 if ( level <= VERBOSE )
dumpMap(
"Rebased ");
467 ParticleMap::const_iterator ipar, iend, i;
475 for(count = 0, iend=pm.end(), i=pm.begin(); i!=iend; ++i) {
477 orgParticles[p->id] = p->
id;
478 finalParticles[p->id] = p;
479 if ( p->id > count ) count = p->id;
489 orgParticles[p->id] = count;
490 finalParticles[count] = p;
497 int g4_equiv = (*ie).first;
500 if ( iequiv == ie_end ) {
503 g4_equiv = (*iequiv).second;
505 TrackEquivalents::mapped_type equiv = (*ie).second;
508 equivalents[(*ie).first] = p->
id;
509 const G4ParticleDefinition* def = p.
definition();
510 int pdg = int(std::abs(def->GetPDGEncoding())+0.1);
511 if ( pdg != 0 && pdg<36 && !(pdg > 10 && pdg < 17) && pdg != 22 ) {
512 error(
"+++ ERROR: Geant4 particle for track:%d last known is:%d -- is gluon or quark!",equiv,g4_equiv);
514 pdg = int(std::abs(p->
pdgID)+0.1);
515 if ( pdg != 0 && pdg<36 && !(pdg > 10 && pdg < 17) && pdg != 22 ) {
516 error(
"+++ ERROR(2): Geant4 particle for track:%d last known is:%d -- is gluon or quark!",equiv,g4_equiv);
520 error(
"+++ No Equivalent particle for track:%d last known is:%d",equiv,g4_equiv);
532 for(
auto& part : finalParticles ) {
533 auto& p = part.second;
535 TrackEquivalents::iterator iequ = equivalents.find(p->
g4Parent);
536 if ( iequ != equivalents.end() ) {
537 equiv_id = (*iequ).second;
538 if ( (ipar=finalParticles.find(equiv_id)) != finalParticles.end() ) {
547 int parent_id = (*p->
parents.begin());
548 if ( parent_id == q->id )
549 q->daughters.insert(p->
id);
551 error(
"+++ Inconsistency in equivalent record! Parent: %d Daughter:%d",q->id, p->
id);
554 error(
"+++ Inconsistency in parent relashionship: %d NO parent!", p->
id);
559 error(
"+++ Inconsistency in particle record: Geant4 parent %d "
560 "of particle %d not in record of final particles!",
565 for(iend=finalParticles.end(), i=finalParticles.begin(); i!=iend; ++i) {
567 if ( p->g4Parent > 0 ) {
568 int parent_id = (*p->parents.begin());
569 if ( (ipar=finalParticles.find(parent_id)) != finalParticles.end() ) {
574 if ( parent_id == q->id )
577 error(
"+++ Inconsistency in equivalent record! Parent: %d Daughter:%d",q->id, p->id);
580 error(
"+++ Inconsistency in particle record: Geant4 parent %d "
581 "of particle %d not in record of final particles!",
600 if ( mask.isNull() || (secondaries && low_energy && !hits_produced) ) {
604 else if ( !hits_produced && low_energy ) {
608 else if ( !tracker_track && calo_track && low_energy ) {
620 std::set<int> remove;
657 Particle* parent_part = (*ip).second;
670 int g4_id = (*i).first;
671 remove.insert(g4_id);
674 Particle* parent_part = (*ip).second;
676 parent_part->steps += p->steps;
677 parent_part->secondaries += p->secondaries;
685 for(
int r : remove ) {
687 (*ir).second->release();
691 return int(remove.size());
704 std::set<int>& daughters = p->daughters;
705 ParticleMap::const_iterator j;
707 for(
int id_dau : daughters ) {
710 error(
"+++ Particle:%d Daughter %d is not in particle map!",p->id,id_dau);
716 bool in_map =
false, in_parent_list =
false;
719 parent_id = (*eq_it).second;
721 in_parent_list = p->parents.find(parent_id) != p->parents.end();
723 if ( !in_map || !in_parent_list ) {
724 char parent_list[1024];
727 p.dumpWithMomentum(ERROR,
name(),
"INCONSISTENCY");
728 for(
int ip : p->parents )
729 ::snprintf(parent_list+strlen(parent_list),
sizeof(parent_list)-strlen(parent_list),
"%d ",ip);
730 error(
"+++ Particle:%d Parent %d (G4id:%d) In record:%s In parent list:%s [%s]",
731 p->id,parent_id,p->g4Parent,yes_no(in_map),yes_no(in_parent_list),parent_list);
736 if ( num_errors > 0 ) {
737 except(
"+++ Consistency check failed. Found %d problems.",num_errors);
743 auto* p = part.second;
744 if( !p->parents.empty() ) {
746 const double X( parent->vex - p->vsx );
747 const double Y( parent->vey - p->vsy );
748 const double Z( parent->vez - p->vsz );