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();
156 if ( typ ==
"calorimeter" )
158 else if ( typ ==
"tracker" )
163 if ( !this->m_userHandlers.empty() ) {
164 for(
auto* h : this->m_userHandlers )
172 debug(
"+++ Event:%d Add EVENT extension of type Geant4ParticleHandler.....",event->GetEventID());
176 for(
auto* h : this->m_userHandlers )
177 h->generate(event,
this);
182 typedef std::vector<const G4Track*> _Sec;
190 const _Sec* sec=step_value->GetSecondaryInCurrentStep();
191 if ( not sec->empty() ) {
196 for(
auto* h : this->m_userHandlers )
203 double kine = h.kineticEnergy();
204 G4ThreeVector mom = h.momentum();
205 const G4ThreeVector&
v = h.vertex();
207 const G4PrimaryParticle* prim = h.primary();
223 delete (*existingParticle).second;
232 except(
"+++ Tracking preaction: Primary particle without generator particle!");
303 for(
auto* handler : this->m_userHandlers )
311 const int g4_id = h.id();
316 G4ThreeVector mom = track->GetMomentum();
317 const G4ThreeVector& pos = track->GetPosition();
329 const G4Step* theLastStep = track->GetStep();
330 G4StepPoint* theLastPostStepPoint = NULL;
331 if(theLastStep) theLastPostStepPoint = theLastStep->GetPostStepPoint();
332 if( theLastPostStepPoint &&
333 ( theLastPostStepPoint->GetStepStatus() == fWorldBoundary
340 if(track->GetKineticEnergy() <= 0.) {
345 for(
auto* handler : this->m_userHandlers )
358 if ( !mask.isNull() || track_info ) {
367 else part = (*ip).second;
384 ParticleMap::iterator ip;
387 pid = (*iequiv).second;
390 (*ip).second->reason |= track_reason;
392 ph.dumpWithVertex(
outputLevel()+3,
name(),
"FATAL: No real particle parent present");
395 if(track->GetTrackStatus() == fSuspend) {
410 info(
"+++ Event %d Begin event action. Access event related information.",event->GetEventID());
416 for(
auto* h : this->m_userHandlers )
422 const std::string& n =
name();
434 if ( level <= VERBOSE )
dumpMap(
"Particle ");
438 if ( level <= VERBOSE )
dumpMap(
"Recombined");
441 if ( level <= VERBOSE )
dumpMap(
"Rebased ");
445 for(
auto* h : this->m_userHandlers )
461 ParticleMap::const_iterator ipar, iend, i;
469 for(count = 0, iend=pm.end(), i=pm.begin(); i!=iend; ++i) {
471 orgParticles[p->id] = p->
id;
472 finalParticles[p->id] = p;
473 if ( p->id > count ) count = p->id;
483 orgParticles[p->id] = count;
484 finalParticles[count] = p;
491 int g4_equiv = (*ie).first;
494 if ( iequiv == ie_end ) {
497 g4_equiv = (*iequiv).second;
499 TrackEquivalents::mapped_type equiv = (*ie).second;
502 equivalents[(*ie).first] = p->
id;
503 const G4ParticleDefinition* def = p.
definition();
504 int pdg = int(std::abs(def->GetPDGEncoding())+0.1);
505 if ( pdg != 0 && pdg<36 && !(pdg > 10 && pdg < 17) && pdg != 22 ) {
506 error(
"+++ ERROR: Geant4 particle for track:%d last known is:%d -- is gluon or quark!",equiv,g4_equiv);
508 pdg = int(std::abs(p->
pdgID)+0.1);
509 if ( pdg != 0 && pdg<36 && !(pdg > 10 && pdg < 17) && pdg != 22 ) {
510 error(
"+++ ERROR(2): Geant4 particle for track:%d last known is:%d -- is gluon or quark!",equiv,g4_equiv);
514 error(
"+++ No Equivalent particle for track:%d last known is:%d",equiv,g4_equiv);
526 for(
auto& part : finalParticles ) {
527 auto& p = part.second;
529 TrackEquivalents::iterator iequ = equivalents.find(p->
g4Parent);
530 if ( iequ != equivalents.end() ) {
531 equiv_id = (*iequ).second;
532 if ( (ipar=finalParticles.find(equiv_id)) != finalParticles.end() ) {
541 int parent_id = (*p->
parents.begin());
542 if ( parent_id == q->id )
543 q->daughters.insert(p->
id);
545 error(
"+++ Inconsistency in equivalent record! Parent: %d Daughter:%d",q->id, p->
id);
548 error(
"+++ Inconsistency in parent relashionship: %d NO parent!", p->
id);
553 error(
"+++ Inconsistency in particle record: Geant4 parent %d "
554 "of particle %d not in record of final particles!",
559 for(iend=finalParticles.end(), i=finalParticles.begin(); i!=iend; ++i) {
561 if ( p->g4Parent > 0 ) {
562 int parent_id = (*p->parents.begin());
563 if ( (ipar=finalParticles.find(parent_id)) != finalParticles.end() ) {
568 if ( parent_id == q->id )
571 error(
"+++ Inconsistency in equivalent record! Parent: %d Daughter:%d",q->id, p->id);
574 error(
"+++ Inconsistency in particle record: Geant4 parent %d "
575 "of particle %d not in record of final particles!",
594 if ( mask.isNull() || (secondaries && low_energy && !hits_produced) ) {
598 else if ( !hits_produced && low_energy ) {
602 else if ( !tracker_track && calo_track && low_energy ) {
614 std::set<int> remove;
629 if ( !this->m_userHandlers.empty() ) {
631 for(
auto* h : this->m_userHandlers )
632 remove_me |= h->keepParticle(*p);
656 Particle* parent_part = (*ip).second;
669 int g4_id = (*i).first;
670 remove.insert(g4_id);
673 Particle* parent_part = (*ip).second;
675 parent_part->steps += p->steps;
676 parent_part->secondaries += p->secondaries;
678 for(
auto* h : this->m_userHandlers )
679 h->combine(*p, *parent_part);
683 for(
int r : remove ) {
685 (*ir).second->release();
689 return int(remove.size());
702 std::set<int>& daughters = p->daughters;
703 ParticleMap::const_iterator j;
705 for(
int id_dau : daughters ) {
708 error(
"+++ Particle:%d Daughter %d is not in particle map!",p->id,id_dau);
714 bool in_map =
false, in_parent_list =
false;
717 parent_id = (*eq_it).second;
719 in_parent_list = p->parents.find(parent_id) != p->parents.end();
721 if ( !in_map || !in_parent_list ) {
722 char parent_list[1024];
725 p.dumpWithMomentum(ERROR,
name(),
"INCONSISTENCY");
726 for(
int ip : p->parents )
727 ::snprintf(parent_list+strlen(parent_list),
sizeof(parent_list)-strlen(parent_list),
"%d ",ip);
728 error(
"+++ Particle:%d Parent %d (G4id:%d) In record:%s In parent list:%s [%s]",
729 p->id,parent_id,p->g4Parent,yes_no(in_map),yes_no(in_parent_list),parent_list);
734 if ( num_errors > 0 ) {
735 except(
"+++ Consistency check failed. Found %d problems.",num_errors);
741 auto* p = part.second;
742 if( !p->parents.empty() ) {
755 const double X( parent->vex - p->vsx );
756 const double Y( parent->vey - p->vsy );
757 const double Z( parent->vez - p->vsz );