Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// $Id: Geant4Field.cpp 888 2013-11-14 15:54:56Z markus.frank@cern.ch $
//====================================================================
// AIDA Detector description implementation for LCD
//--------------------------------------------------------------------
//
// Author : M.Frank
//
//====================================================================
// Framework include files
#include "DD4hep/Printout.h"
#include "DD4hep/Primitives.h"
#include "DD4hep/InstanceCount.h"
#include "DDG4/Geant4ParticlePrint.h"
#include "DDG4/Geant4Data.h"
#include "G4ParticleDefinition.hh"
#include "G4VProcess.hh"
#include "G4Event.hh"
using namespace std;
using namespace DD4hep;
using namespace DD4hep::Simulation;
typedef ReferenceBitMask<const int> PropertyMask;
/// Standard constructor
Geant4ParticlePrint::Geant4ParticlePrint(Geant4Context* context, const std::string& nam)
: Geant4EventAction(context,nam)
{
declareProperty("OutputType",m_outputType=3);
InstanceCount::increment(this);
}
/// Default destructor
Geant4ParticlePrint::~Geant4ParticlePrint() {
InstanceCount::decrement(this);
}
/// Pre-event action callback
void Geant4ParticlePrint::begin(const G4Event* ) {
}
/// Post-event action callback
void Geant4ParticlePrint::end(const G4Event* ) {
Geant4MonteCarloTruth* truth = context()->event().extension<Geant4MonteCarloTruth>();
if ( truth ) {
const ParticleMap& particles = truth->particles();
if ( (m_outputType&1) != 0 ) printParticles(particles); // Table printout....
if ( (m_outputType&2) != 0 ) printParticleTree(particles); // Tree printout....
return;
}
except("No Geant4MonteCarloTruth object present in the event structure to access the particle information!", c_name());
}
void Geant4ParticlePrint::printParticle(const std::string& prefix, const Particle* p) const {
char equiv[32];
PropertyMask mask(p->reason);
const char* proc_name = "???";
const char* proc_type = p->process ? G4VProcess::GetProcessTypeName(p->process->GetProcessType()).c_str() : "";
if ( p->process ) proc_name = p->process->GetProcessName().c_str();
else if ( mask.isSet(G4PARTICLE_PRIMARY) ) proc_name = "Primary";
equiv[0] = 0;
if ( p->g4Parent != p->parent ) {
::snprintf(equiv,sizeof(equiv),"/%d",p->g4Parent);
}
printout(INFO,name(),"+++ %sID: %6d %12s %6d%-7s %7s %3s %5d %6s %8.3g %-4s %-7s %-7s %-3s [%s%s%s]",
prefix.c_str(),
p->id,
p->definition->GetParticleName().c_str(),
p->parent,equiv,
yes_no(mask.isSet(G4PARTICLE_PRIMARY)),
yes_no(mask.isSet(G4PARTICLE_HAS_SECONDARIES)),
int(p->daughters.size()),
yes_no(mask.isSet(G4PARTICLE_ABOVE_ENERGY_THRESHOLD)),
p->energy,
yes_no(mask.isSet(G4PARTICLE_CREATED_CALORIMETER_HIT)),
yes_no(mask.isSet(G4PARTICLE_CREATED_TRACKER_HIT)),
yes_no(mask.isSet(G4PARTICLE_KEEP_PROCESS)),
mask.isSet(G4PARTICLE_KEEP_PARENT) ? "YES" : "",
proc_name,
p->process ? "/" : "",
proc_type
);
}
/// Print record of kept particles
void Geant4ParticlePrint::printParticles(const ParticleMap& particles) const {
int num_energy = 0;
int num_parent = 0;
int num_process = 0;
int num_primary = 0;
int num_secondaries = 0;
int num_calo_hits = 0;
int num_tracker_hits = 0;
printout(INFO,name(),"+++ MC Particles #Tracks:%6d %-12s Parent%-7s "
"Primary Secondary Energy %-8s Calo Tracker Process/Par Details",
int(particles.size()),"ParticleType","","in [MeV]");
for(ParticleMap::const_iterator i=particles.begin(); i!=particles.end(); ++i) {
const Particle* p = (*i).second;
PropertyMask mask(p->reason);
printParticle("MC Particle Track",p);
num_secondaries += int(p->daughters.size());
if ( mask.isSet(G4PARTICLE_ABOVE_ENERGY_THRESHOLD) ) ++num_energy;
if ( mask.isSet(G4PARTICLE_PRIMARY) ) ++num_primary;
if ( mask.isSet(G4PARTICLE_CREATED_TRACKER_HIT) ) ++num_tracker_hits;
if ( mask.isSet(G4PARTICLE_CREATED_CALORIMETER_HIT) ) ++num_calo_hits;
if ( mask.isSet(G4PARTICLE_KEEP_PARENT) ) ++num_parent;
else if ( mask.isSet(G4PARTICLE_KEEP_PROCESS) ) ++num_process;
}
printout(INFO,name(),"+++ MC Particles #Tracks:%6d %-12s Parent%-7s "
"Primary Secondary Energy %-8s Calo Tracker Process/Parent",
int(particles.size()),"","","");
printout(INFO,name(),"+++ MC Particle Summary: %6s %-12s %6s%-7s "
"%7d %9d %6d %-8s %4d %7d %7d %6d",
"","","","",
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
num_primary, num_secondaries, num_energy,"",
num_calo_hits,num_tracker_hits,num_process,num_parent);
}
void Geant4ParticlePrint::printParticleTree(const ParticleMap& particles, int level, const Particle* p) const {
char txt[32];
size_t len = sizeof(txt)-1;
// Ensure we do not overwrite the array
if ( level>int(len)-3 ) level=len-3;
::snprintf(txt,sizeof(txt),"%5d ",level);
::memset(txt+6,' ',len-6);
txt[len] = 0;
txt[len-2] = '>';
txt[level+6]='+';
::memset(txt+level+6+1,'-',len-level-3-6);
printParticle(txt, p);
const set<int>& daughters = p->daughters;
// For all particles, the set of daughters must be contained in the record.
for(set<int>::const_iterator id=daughters.begin(); id!=daughters.end(); ++id) {
int id_dau = *id;
const Particle* dau = (*particles.find(id_dau)).second;
printParticleTree(particles,level+1,dau);
}
}
/// Print tree of kept particles
void Geant4ParticlePrint::printParticleTree(const ParticleMap& particles) const {
printout(INFO,name(),"+++ MC Particle Parent daughter relationships. [%d particles]",int(particles.size()));
printout(INFO,name(),"+++ MC Particles %12s #Tracks:%7d %-12s Parent%-7s "
"Primary Secondary Energy %-8s Calo Tracker Process/Par Details",
"",int(particles.size()),"ParticleType","","in [MeV]");
for(ParticleMap::const_iterator i=particles.begin(); i!=particles.end(); ++i) {
const Particle* p = (*i).second;
PropertyMask mask(p->reason);
if ( mask.isSet(G4PARTICLE_PRIMARY) ) printParticleTree(particles,0,p);
}
}