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>
49 InstanceCount::increment(
this);
51 eventAction().callAtBegin(
this, &Geant4ParticleHandler::beginEvent);
52 eventAction().callAtEnd(
this, &Geant4ParticleHandler::endEvent);
53 trackingAction().callAtFinal(
this, &Geant4ParticleHandler::end,CallbackSequence::FRONT);
54 trackingAction().callUpFront(
this, &Geant4ParticleHandler::begin,CallbackSequence::FRONT);
55 steppingAction().call(
this, &Geant4ParticleHandler::step);
56 m_globalParticleID = 0;
57 declareProperty(
"PrintEndTracking", m_printEndTracking =
false);
58 declareProperty(
"PrintStartTracking", m_printStartTracking =
false);
59 declareProperty(
"KeepAllParticles", m_keepAll =
false);
60 declareProperty(
"SaveProcesses", m_processNames);
61 declareProperty(
"MinimalKineticEnergy", m_kinEnergyCut = 100e0*CLHEP::MeV);
62 declareProperty(
"MinDistToParentVertex", m_minDistToParentVertex = 2.2e-14*CLHEP::mm);
63 m_needsControl =
true;
67 Geant4ParticleHandler::Geant4ParticleHandler()
70 m_globalParticleID = 0;
71 declareProperty(
"PrintEndTracking", m_printEndTracking =
false);
72 declareProperty(
"PrintStartTracking", m_printStartTracking =
false);
73 declareProperty(
"KeepAllParticles", m_keepAll =
false);
74 declareProperty(
"SaveProcesses", m_processNames);
75 declareProperty(
"MinimalKineticEnergy", m_kinEnergyCut = 100e0*CLHEP::MeV);
76 declareProperty(
"MinDistToParentVertex", m_minDistToParentVertex = 2.2e-14*CLHEP::mm);
77 m_needsControl =
true;
81 Geant4ParticleHandler::~Geant4ParticleHandler() {
84 detail::releasePtr(h);
85 this->m_userHandlers.clear();
98 this->m_userHandlers.push_back(h);
102 except(
"Cannot add an user particle handler object [Object-exists].");
104 except(
"Cannot add an invalid user particle handler object [NULL-object].");
113 assert(
m_suspendedPM.empty() &&
"There was something wrong with the particle record treatment, please open a bug report!");
125 except(
"Cannot mark the G4Track if the pointer is invalid!");
131 mark(step_value->GetTrack(),reason);
134 except(
"Cannot mark the G4Track if the step-pointer is invalid!");
140 this->
mark(step_value->GetTrack());
143 except(
"Cannot mark the G4Track if the step-pointer is invalid!");
152 G4LogicalVolume* vol = track->GetVolume()->GetLogicalVolume();
158 if ( typ ==
"calorimeter" )
160 else if ( typ ==
"tracker" )
165 if( !this->m_userHandlers.empty() ) {
166 for(
auto* h : this->m_userHandlers )
174 debug(
"+++ Event:%d Add EVENT extension of type Geant4ParticleHandler.....",event->GetEventID());
178 for(
auto* h : this->m_userHandlers )
179 h->generate(event,
this);
184 typedef std::vector<const G4Track*> _Sec;
192 const _Sec* sec=step_value->GetSecondaryInCurrentStep();
193 if ( not sec->empty() ) {
198 for(
auto* h : this->m_userHandlers )
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!");
305 for(
auto* handler : this->m_userHandlers )
313 const int g4_id = h.id();
318 G4ThreeVector mom = track->GetMomentum();
319 const G4ThreeVector& pos = track->GetPosition();
331 const G4Step* theLastStep = track->GetStep();
332 G4StepPoint* theLastPostStepPoint = NULL;
333 if(theLastStep) theLastPostStepPoint = theLastStep->GetPostStepPoint();
334 if( theLastPostStepPoint &&
335 ( theLastPostStepPoint->GetStepStatus() == fWorldBoundary
342 if(track->GetKineticEnergy() <= 0.) {
347 for(
auto* handler : this->m_userHandlers )
360 if ( !mask.isNull() || track_info ) {
369 else part = (*ip).second;
386 ParticleMap::iterator ip;
389 pid = (*iequiv).second;
392 (*ip).second->reason |= track_reason;
394 ph.dumpWithVertex(
outputLevel()+3,
name(),
"FATAL: No real particle parent present");
397 if(track->GetTrackStatus() == fSuspend) {
412 info(
"+++ Event %d Begin event action. Access event related information.",event->GetEventID());
418 for(
auto* h : this->m_userHandlers )
424 const std::string& n =
name();
436 if ( level <= VERBOSE )
dumpMap(
"Particle ");
440 if ( level <= VERBOSE )
dumpMap(
"Recombined");
443 if ( level <= VERBOSE )
dumpMap(
"Rebased ");
447 for(
auto* h : this->m_userHandlers )
463 ParticleMap::const_iterator ipar, iend, i;
471 for(count = 0, iend=pm.end(), i=pm.begin(); i!=iend; ++i) {
473 orgParticles[p->id] = p->
id;
474 finalParticles[p->id] = p;
475 if ( p->id > count ) count = p->id;
485 orgParticles[p->id] = count;
486 finalParticles[count] = p;
493 int g4_equiv = (*ie).first;
496 if ( iequiv == ie_end ) {
499 g4_equiv = (*iequiv).second;
501 TrackEquivalents::mapped_type equiv = (*ie).second;
504 equivalents[(*ie).first] = p->
id;
505 const G4ParticleDefinition* def = p.
definition();
506 int pdg = int(std::abs(def->GetPDGEncoding())+0.1);
507 if ( pdg != 0 && pdg<36 && !(pdg > 10 && pdg < 17) && pdg != 22 ) {
508 error(
"+++ ERROR: Geant4 particle for track:%d last known is:%d -- is gluon or quark!",equiv,g4_equiv);
510 pdg = int(std::abs(p->
pdgID)+0.1);
511 if ( pdg != 0 && pdg<36 && !(pdg > 10 && pdg < 17) && pdg != 22 ) {
512 error(
"+++ ERROR(2): Geant4 particle for track:%d last known is:%d -- is gluon or quark!",equiv,g4_equiv);
516 error(
"+++ No Equivalent particle for track:%d last known is:%d",equiv,g4_equiv);
528 for(
auto& part : finalParticles ) {
529 auto& p = part.second;
531 TrackEquivalents::iterator iequ = equivalents.find(p->
g4Parent);
532 if ( iequ != equivalents.end() ) {
533 equiv_id = (*iequ).second;
534 if ( (ipar=finalParticles.find(equiv_id)) != finalParticles.end() ) {
543 int parent_id = (*p->
parents.begin());
544 if ( parent_id == q->id )
545 q->daughters.insert(p->
id);
547 error(
"+++ Inconsistency in equivalent record! Parent: %d Daughter:%d",q->id, p->
id);
550 error(
"+++ Inconsistency in parent relashionship: %d NO parent!", p->
id);
555 error(
"+++ Inconsistency in particle record: Geant4 parent %d "
556 "of particle %d not in record of final particles!",
561 for(iend=finalParticles.end(), i=finalParticles.begin(); i!=iend; ++i) {
563 if ( p->g4Parent > 0 ) {
564 int parent_id = (*p->parents.begin());
565 if ( (ipar=finalParticles.find(parent_id)) != finalParticles.end() ) {
570 if ( parent_id == q->id )
573 error(
"+++ Inconsistency in equivalent record! Parent: %d Daughter:%d",q->id, p->id);
576 error(
"+++ Inconsistency in particle record: Geant4 parent %d "
577 "of particle %d not in record of final particles!",
596 if ( mask.isNull() || (secondaries && low_energy && !hits_produced) ) {
600 else if ( !hits_produced && low_energy ) {
604 else if ( !tracker_track && calo_track && low_energy ) {
616 std::set<int> remove;
630 bool remove_me =
false;
631 if ( !this->m_userHandlers.empty() ) {
632 for(
auto* h : this->m_userHandlers )
633 remove_me |= h->keepParticle(*p);
659 Particle* parent_part = (*ip).second;
672 int g4_id = (*i).first;
673 remove.insert(g4_id);
676 Particle* parent_part = (*ip).second;
678 parent_part->steps += p->steps;
679 parent_part->secondaries += p->secondaries;
681 for(
auto* h : this->m_userHandlers )
682 h->combine(*p, *parent_part);
686 for(
int r : remove ) {
688 (*ir).second->release();
692 return int(remove.size());
705 std::set<int>& daughters = p->daughters;
706 ParticleMap::const_iterator j;
708 for(
int id_dau : daughters ) {
711 error(
"+++ Particle:%d Daughter %d is not in particle map!",p->id,id_dau);
717 bool in_map =
false, in_parent_list =
false;
720 parent_id = (*eq_it).second;
722 in_parent_list = p->parents.find(parent_id) != p->parents.end();
724 if ( !in_map || !in_parent_list ) {
725 char parent_list[1024];
728 p.dumpWithMomentum(ERROR,
name(),
"INCONSISTENCY");
729 for(
int ip : p->parents )
730 ::snprintf(parent_list+strlen(parent_list),
sizeof(parent_list)-strlen(parent_list),
"%d ",ip);
731 error(
"+++ Particle:%d Parent %d (G4id:%d) In record:%s In parent list:%s [%s]",
732 p->id,parent_id,p->g4Parent,yes_no(in_map),yes_no(in_parent_list),parent_list);
737 if ( num_errors > 0 ) {
738 except(
"+++ Consistency check failed. Found %d problems.",num_errors);
744 auto* p = part.second;
745 if( !p->parents.empty() ) {
758 const double X( parent->vex - p->vsx );
759 const double Y( parent->vey - p->vsy );
760 const double Z( parent->vez - p->vsz );