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>
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()
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);
78 m_needsControl =
true;
82 Geant4ParticleHandler::~Geant4ParticleHandler() {
85 detail::releasePtr(h);
86 this->m_userHandlers.clear();
99 this->m_userHandlers.push_back(h);
103 except(
"Cannot add an user particle handler object [Object-exists].");
105 except(
"Cannot add an invalid user particle handler object [NULL-object].");
114 assert(
m_suspendedPM.empty() &&
"There was something wrong with the particle record treatment, please open a bug report!");
126 except(
"Cannot mark the G4Track if the pointer is invalid!");
132 mark(step_value->GetTrack(),reason);
135 except(
"Cannot mark the G4Track if the step-pointer is invalid!");
141 this->
mark(step_value->GetTrack());
144 except(
"Cannot mark the G4Track if the step-pointer is invalid!");
153 G4LogicalVolume* vol = track->GetVolume()->GetLogicalVolume();
160 if ( typ ==
"calorimeter" ) {
163 else if ( typ ==
"tracker" ) {
170 if( !this->m_userHandlers.empty() ) {
171 for(
auto* h : this->m_userHandlers )
182 debug(
"+++ Event:%d Add EVENT extension of type Geant4ParticleHandler.....",event->GetEventID());
186 for(
auto* h : this->m_userHandlers )
187 h->generate(event,
this);
192 typedef std::vector<const G4Track*> _Sec;
200 const _Sec* sec=step_value->GetSecondaryInCurrentStep();
201 if ( not sec->empty() ) {
206 for(
auto* h : this->m_userHandlers )
213 double kine = h.kineticEnergy();
214 G4ThreeVector mom = h.momentum();
215 const G4ThreeVector&
v = h.vertex();
217 const G4PrimaryParticle* prim = h.primary();
233 delete (*existingParticle).second;
242 except(
"+++ Tracking preaction: Primary particle without generator particle!");
314 G4LogicalVolume* vol = track->GetVolume()->GetLogicalVolume();
319 if( typ ==
"calorimeter" ) {
325 for(
auto* handler : this->m_userHandlers )
333 const int g4_id = h.id();
338 G4ThreeVector mom = track->GetMomentum();
339 const G4ThreeVector& pos = track->GetPosition();
351 const G4Step* theLastStep = track->GetStep();
352 G4StepPoint* theLastPostStepPoint = NULL;
353 if( theLastStep ) theLastPostStepPoint = theLastStep->GetPostStepPoint();
354 if( theLastPostStepPoint &&
355 ( theLastPostStepPoint->GetStepStatus() == fWorldBoundary
362 if( track->GetKineticEnergy() <= 0. ) {
368 std::string end_volume_type;
371 G4LogicalVolume* vol = track->GetVolume()->GetLogicalVolume();
377 if( tracker_hits || end_volume_type ==
"tracker" ) {
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));
386 for(
auto* handler : this->m_userHandlers )
408 info(
"+++ Track: %6d Particle back-scattering to tracker --> keep particle in MC history.", g4_id);
413 else part = (*ip).second;
416 part->extension.reset(track_info->
release());
430 ParticleMap::iterator ip;
433 pid = (*iequiv).second;
436 (*ip).second->reason |= track_reason;
438 ph.dumpWithVertex(
outputLevel()+3,
name(),
"FATAL: No real particle parent present");
441 if( track->GetTrackStatus() == fSuspend ) {
456 info(
"+++ Event %d Begin event action. Access event related information.",event->GetEventID());
462 for(
auto* h : this->m_userHandlers )
468 const std::string& n =
name();
480 if ( level <= VERBOSE )
dumpMap(
"Particle ");
484 if ( level <= VERBOSE )
dumpMap(
"Recombined");
487 if ( level <= VERBOSE )
dumpMap(
"Rebased ");
491 for(
auto* h : this->m_userHandlers )
507 ParticleMap::const_iterator ipar, iend, i;
515 for(count = 0, iend=pm.end(), i=pm.begin(); i!=iend; ++i) {
517 orgParticles[p->id] = p->
id;
518 finalParticles[p->id] = p;
519 if ( p->id > count ) count = p->id;
529 orgParticles[p->id] = count;
530 finalParticles[count] = p;
537 int g4_equiv = (*ie).first;
540 if ( iequiv == ie_end ) {
543 g4_equiv = (*iequiv).second;
545 TrackEquivalents::mapped_type equiv = (*ie).second;
548 equivalents[(*ie).first] = p->
id;
549 const G4ParticleDefinition* def = p.
definition();
550 int pdg = int(std::abs(def->GetPDGEncoding())+0.1);
551 if ( pdg != 0 && pdg<36 && !(pdg > 10 && pdg < 17) && pdg != 22 ) {
552 error(
"+++ ERROR: Geant4 particle for track:%d last known is:%d -- is gluon or quark!",equiv,g4_equiv);
554 pdg = int(std::abs(p->
pdgID)+0.1);
555 if ( pdg != 0 && pdg<36 && !(pdg > 10 && pdg < 17) && pdg != 22 ) {
556 error(
"+++ ERROR(2): Geant4 particle for track:%d last known is:%d -- is gluon or quark!",equiv,g4_equiv);
560 error(
"+++ No Equivalent particle for track:%d last known is:%d",equiv,g4_equiv);
572 for(
auto& part : finalParticles ) {
573 auto& p = part.second;
575 TrackEquivalents::iterator iequ = equivalents.find(p->
g4Parent);
576 if ( iequ != equivalents.end() ) {
577 equiv_id = (*iequ).second;
578 if ( (ipar=finalParticles.find(equiv_id)) != finalParticles.end() ) {
587 int parent_id = (*p->
parents.begin());
588 if ( parent_id == q->id )
589 q->daughters.insert(p->
id);
591 error(
"+++ Inconsistency in equivalent record! Parent: %d Daughter:%d",q->id, p->
id);
594 error(
"+++ Inconsistency in parent relashionship: %d NO parent!", p->
id);
599 error(
"+++ Inconsistency in particle record: Geant4 parent %d "
600 "of particle %d not in record of final particles!",
605 for(iend=finalParticles.end(), i=finalParticles.begin(); i!=iend; ++i) {
607 if ( p->g4Parent > 0 ) {
608 int parent_id = (*p->parents.begin());
609 if ( (ipar=finalParticles.find(parent_id)) != finalParticles.end() ) {
614 if ( parent_id == q->id )
617 error(
"+++ Inconsistency in equivalent record! Parent: %d Daughter:%d",q->id, p->id);
620 error(
"+++ Inconsistency in particle record: Geant4 parent %d "
621 "of particle %d not in record of final particles!",
645 else if ( mask.isNull() || (secondaries && low_energy && !hits_produced) ) {
649 else if ( !hits_produced && low_energy ) {
653 else if ( !tracker_track && calo_track && low_energy ) {
665 std::set<int> remove;
679 bool remove_me =
false;
680 if ( !this->m_userHandlers.empty() ) {
681 for(
auto* h : this->m_userHandlers )
682 remove_me |= h->dropParticle(*p);
708 Particle* parent_part = (*ip).second;
721 int g4_id = (*i).first;
722 remove.insert(g4_id);
725 Particle* parent_part = (*ip).second;
727 parent_part->steps += p->steps;
728 parent_part->secondaries += p->secondaries;
730 for(
auto* h : this->m_userHandlers )
731 h->combine(*p, *parent_part);
735 for(
int r : remove ) {
737 (*ir).second->release();
741 return int(remove.size());
754 std::set<int>& daughters = p->daughters;
755 ParticleMap::const_iterator j;
757 for(
int id_dau : daughters ) {
760 error(
"+++ Particle:%d Daughter %d is not in particle map!",p->id,id_dau);
766 bool in_map =
false, in_parent_list =
false;
769 parent_id = (*eq_it).second;
771 in_parent_list = p->parents.find(parent_id) != p->parents.end();
773 if ( !in_map || !in_parent_list ) {
774 char parent_list[1024];
777 p.dumpWithMomentum(ERROR,
name(),
"INCONSISTENCY");
778 for(
int ip : p->parents )
779 ::snprintf(parent_list+strlen(parent_list),
sizeof(parent_list)-strlen(parent_list),
"%d ",ip);
780 error(
"+++ Particle:%d Parent %d (G4id:%d) In record:%s In parent list:%s [%s]",
781 p->id,parent_id,p->g4Parent,yes_no(in_map),yes_no(in_parent_list),parent_list);
786 if ( num_errors > 0 ) {
787 except(
"+++ Consistency check failed. Found %d problems.",num_errors);
793 auto* p = part.second;
794 if( !p->parents.empty() ) {
807 const double X( parent->vex - p->vsx );
808 const double Y( parent->vey - p->vsy );
809 const double Z( parent->vez - p->vsz );