3 #include "nug4/G4Base/PrimaryParticleInformation.h"
5 #include "nusimdata/SimulationBase/MCParticle.h"
7 #include "canvas/Persistency/Common/Ptr.h"
9 #include "messagefacility/MessageLogger/MessageLogger.h"
11 #include "fhiclcpp/ParameterSet.h"
13 #include "Geant4/G4Event.hh"
14 #include "Geant4/G4IonTable.hh"
15 #include "Geant4/G4ParticleDefinition.hh"
16 #include "Geant4/G4ParticleTable.hh"
17 #include "Geant4/G4PrimaryParticle.hh"
18 #include "Geant4/G4PrimaryVertex.hh"
19 #include "Geant4/G4Types.hh"
21 #include "CLHEP/Vector/LorentzVector.h"
23 #include "TLorentzVector.h"
33 genie_specific(
int const pdg)
35 constexpr
int genieLoPdg = 2000000001;
36 constexpr
int genieHiPdg = 2000000300;
37 return pdg >= genieLoPdg && pdg <= genieHiPdg;
44 : PrimaryGeneratorActionBase(p.
get<string>(
"name",
"MCTruthEventActionService"))
50 if (!fUnknownPDG.empty()) {
51 std::ostringstream badtxt;
52 for (
auto const [
pdg,
n] : fUnknownPDG) {
53 badtxt <<
"\n Unknown PDG code = " <<
pdg <<
", seen " <<
n <<
" times.";
54 if (genie_specific(
pdg)) { badtxt <<
" (GENIE specific)"; }
57 mf::LogWarning(
"MCTruthEventAction") <<
"The following unknown PDG codes were present in the "
58 <<
"simb::MCTruth input.\n"
59 <<
"They were not processed by Geant4." << badtxt.str();
63 if (!fNon1StatusPDG.empty()) {
64 std::ostringstream non1txt;
65 for (
auto const [
pdg,
n] : fNon1StatusPDG) {
66 non1txt <<
"\n PDG code = " <<
pdg <<
", seen " <<
n <<
" times.";
67 if (genie_specific(
pdg)) { non1txt <<
" (GENIE specific)"; }
70 mf::LogDebug(
"MCTruthEventAction") <<
"The following PDG codes were present in the "
71 <<
"simb::MCTruth input with Status != 1.\n"
72 <<
"They were not processed by Geant4." << non1txt.str();
76 if (!fProcessedPDG.empty()) {
77 std::ostringstream goodtxt;
78 for (
auto const [
pdg,
n] : fProcessedPDG) {
79 goodtxt <<
"\n PDG code = " <<
pdg <<
", seen " <<
n <<
" times.";
81 mf::LogDebug(
"MCTruthEventAction") <<
"The following PDG codes were present in the "
82 <<
"simb::MCTruth input with Status = 1 "
83 <<
"and were processed by Geant4" << goodtxt.str();
94 auto const& mclistHandles = *fMCLists;
96 size_t mclSize = mclistHandles.size();
97 mf::LogDebug(
"generatePrimaries") <<
"MCTruth Handles Size: " << mclSize;
101 std::map<CLHEP::HepLorentzVector, G4PrimaryVertex*> vertexMap;
102 for (
size_t mcl = 0; mcl < mclSize; ++mcl) {
103 mf::LogDebug(
"generatePrimaries")
104 <<
"MCTruth Handle Number: " << (mcl + 1) <<
" of " << mclSize;
105 art::Handle<std::vector<simb::MCTruth>> mclistHandle = mclistHandles[mcl];
108 for (
size_t i = 0; i < mclistHandle->size(); ++i) {
109 art::Ptr<simb::MCTruth> mclist(mclistHandle, i);
111 mf::LogDebug(
"generatePrimaries")
112 <<
"art::Ptr number " << (i + 1) <<
" of " << mclistHandle->size() <<
", Ptr: " << mclist;
113 int nPart = mclist->NParticles();
114 MF_LOG_INFO(
"generatePrimaries") <<
"Generating " << nPart <<
" particles";
117 for (
int m = 0;
m != nPart; ++
m) {
118 simb::MCParticle
const& particle = mclist->GetParticle(
m);
119 G4int
const pdgCode = particle.PdgCode();
121 if (particle.StatusCode() != 1) {
122 MF_LOG_DEBUG(
"generatePrimaries")
123 <<
"Status code != 1, skipping particle number with MCTruth index = "
124 <<
"(" << mcl <<
"," << i <<
")"
125 <<
" and particle index = " <<
m;
126 fNon1StatusPDG[pdgCode] += 1;
130 if (((
m + 1) % nPart) < 2)
132 mf::LogDebug(
"generatePrimaries") <<
"Particle Number: " << (
m + 1) <<
" of " << nPart;
133 mf::LogDebug(
"generatePrimaries") <<
"TrackID: " << particle.TrackId();
134 mf::LogDebug(
"generatePrimaries") <<
"index: " << index;
137 G4double
x = particle.Vx() * CLHEP::cm;
138 G4double
y = particle.Vy() * CLHEP::cm;
139 G4double
z = particle.Vz() * CLHEP::cm;
140 G4double t = particle.T() * CLHEP::ns;
143 CLHEP::HepLorentzVector fourpos(x, y, z, t);
146 G4PrimaryVertex*
vertex =
nullptr;
147 auto result = vertexMap.find(fourpos);
148 if (result == vertexMap.end()) {
150 vertex =
new G4PrimaryVertex(x, y, z, t);
151 vertexMap[fourpos] =
vertex;
154 anEvent->AddPrimaryVertex(vertex);
158 vertex = result->second;
162 TLorentzVector
const& momentum = particle.Momentum();
163 TVector3
const& polarization = particle.Polarization();
168 if (fParticleTable ==
nullptr) { fParticleTable = G4ParticleTable::GetParticleTable(); }
171 G4ParticleDefinition* particleDefinition =
nullptr;
173 if (pdgCode == 0) { particleDefinition = fParticleTable->FindParticle(
"opticalphoton"); }
175 particleDefinition = fParticleTable->FindParticle(pdgCode);
178 if (pdgCode >= 2
'000'000
'000) { // If the particle is generator-specific
179 mf::LogDebug("ConvertPrimaryToGeant4")
180 << ": %%% Will skip particle with generator-specific PDG code = " << pdgCode;
181 fUnknownPDG[pdgCode] += 1;
184 if (pdgCode > 1'000
'000'000) {
185 mf::LogDebug(
"ConvertPrimaryToGeant4")
186 <<
": %%% Nuclear PDG code = " << pdgCode <<
" (x,y,z,t)=(" << x <<
"," << y <<
"," << z
188 <<
" P=" << momentum.P() <<
", E=" << momentum.E();
192 if (!particleDefinition) {
193 int const Z = (pdgCode % 10
'000'000) / 10
'000; // atomic number
194 int const A = (pdgCode % 10'000) / 10;
195 particleDefinition = fParticleTable->GetIonTable()->GetIon(Z,
A, 0.);
201 if (particleDefinition ==
nullptr) {
202 mf::LogDebug(
"ConvertPrimaryToGeant4") <<
": %%% Code not found = " << pdgCode;
203 fUnknownPDG[pdgCode] += 1;
207 fProcessedPDG[pdgCode] += 1;
210 auto* g4particle =
new G4PrimaryParticle(particleDefinition,
216 g4particle->SetCharge(particleDefinition->GetPDGCharge());
217 g4particle->SetPolarization(polarization.x(), polarization.y(), polarization.z());
220 vertex->SetPrimary(g4particle);
227 auto* primaryParticleInfo =
new g4b::PrimaryParticleInformation;
228 primaryParticleInfo->SetMCTruth(mclist.get(), index,
m);
232 g4particle->SetUserInformation(primaryParticleInfo);
util::quantities::gigaelectronvolt GeV
process_name opflash particleana ie ie ie z
~MCTruthEventActionService()
static G4ParticleTable * fParticleTable
Geant4's table of particle definitions.
process_name opflash particleana ie x
tuple m
now if test mode generate materials, CRT shell, world, gdml header else just generate CRT shell for u...
process_name opflash particleana ie ie y
void generatePrimaries(G4Event *anEvent) override
MCTruthEventActionService(fhicl::ParameterSet const &)