LDMX Software
PrimaryGeneratorAction.cxx
Go to the documentation of this file.
1
8
9/*~~~~~~~~~~~~*/
10/* Geant4 */
11/*~~~~~~~~~~~~*/
12#include "G4Event.hh"
13#include "G4RunManager.hh" // Needed for CLHEP
14
15/*~~~~~~~~~~~~~*/
16/* SimCore */
17/*~~~~~~~~~~~~~*/
19#include "SimCore/UserEventInformation.h"
21
22/*~~~~~~~~~~*/
23/* ROOT */
24/*~~~~~~~~~~*/
25#include "TRandom3.h"
26
27namespace simcore::g4user {
28
29PrimaryGeneratorAction::PrimaryGeneratorAction(
30 const framework::config::Parameters& parameters)
31 : G4VUserPrimaryGeneratorAction() {
32 // Check whether a beamspot should be used or not.
33 auto beamSpot{
34 parameters.getParameter<std::vector<double> >("beamSpotSmear", {})};
35 if (!beamSpot.empty()) {
36 useBeamspot_ = true;
37 beamspotXSize_ = beamSpot[0];
38 beamspotYSize_ = beamSpot[1];
39 beamspotZSize_ = beamSpot[2];
40 }
41
42 time_shift_primaries_ = parameters.getParameter<bool>("time_shift_primaries");
43
44 auto generators{
45 parameters.getParameter<std::vector<framework::config::Parameters> >(
46 "generators", {})};
47 if (generators.empty()) {
48 EXCEPTION_RAISE("MissingGenerator",
49 "Need to define some generator of primaries.");
50 }
51
52 for (auto& generator : generators) {
53 PrimaryGenerator::Factory::get().make(
54 generator.getParameter<std::string>("class_name"),
55 generator.getParameter<std::string>("instance_name"), generator);
56 }
57}
58
59void PrimaryGeneratorAction::GeneratePrimaries(G4Event* event) {
60 /*
61 * Create our Event information first so that it
62 * can be accessed by everyone from now on.
63 */
64 // Make sure we aren't overwriting a different information container
65 if (event->GetUserInformation()) {
66 EXCEPTION_RAISE(
67 "Misconfig",
68 "There was a UserEventInformation attached before beginning event."
69 "\nI don't know how this happend!!");
70 }
71
72 // Make our information container and give it to geant4
73 // G4Event owns the event information and will delete it
74 auto event_info = new UserEventInformation;
75 event->SetUserInformation(event_info);
76
77 PrimaryGenerator::Factory::get().apply([event](const auto& generator) {
78 generator->GeneratePrimaryVertex(event);
79 });
80
81 // smear all primary vertices (if activated)
82 int nPV = event->GetNumberOfPrimaryVertex();
83 if (nPV > 0) {
84 // loop over all vertices generated
85 for (int iPV = 0; iPV < nPV; ++iPV) {
86 G4PrimaryVertex* primary_vertex = event->GetPrimaryVertex(iPV);
87
88 if (not primary_vertex) {
89 EXCEPTION_RAISE(
90 "BadGen",
91 "One of the primary generators created a NULL primary vertex.");
92 }
93
94 // Loop over all particle associated with the primary vertex and
95 // set the generator status to 1.
96 for (int iparticle = 0; iparticle < primary_vertex->GetNumberOfParticle();
97 ++iparticle) {
98 G4PrimaryParticle* primary = primary_vertex->GetPrimary(iparticle);
99
100 if (not primary) {
101 EXCEPTION_RAISE(
102 "BadGen",
103 "One of the primary generators created a NULL primary particle.");
104 }
105
106 auto primary_info{dynamic_cast<UserPrimaryParticleInformation*>(
107 primary->GetUserInformation())};
108 if (not primary_info) {
109 // no user info defined
110 // ==> make a new one
111 primary_info = new UserPrimaryParticleInformation;
112 primary->SetUserInformation(primary_info);
113 } // check if primaryinfo is defined
114
115 int hepStatus = primary_info->getHepEvtStatus();
116 if (hepStatus <= 0) {
117 // undefined hepStatus ==> set to 1
118 primary_info->setHepEvtStatus(1);
119 } // check if hepStatus defined
120
121 } // iparticle - loop over primary particles from this vertex
122
123 // include the weight of this primary vertex in the event weight
124 event_info->incWeight(primary_vertex->GetWeight());
125
126 // smear beamspot if it is turned on
127 if (useBeamspot_) {
128 double x0_i = primary_vertex->GetX0();
129 double y0_i = primary_vertex->GetY0();
130 double z0_i = primary_vertex->GetZ0();
131 /*
132 * G4UniformRand returns a number in [0,1]
133 * - we shift this range so that it is [-0.5,0.5]
134 * - multiply by the width to get [-0.5*size,0.5*size]
135 * - add the initial point (in case its off center) to get
136 * [init-0.5*size, init+0.5*size]
137 */
138 double x0_f = beamspotXSize_ * (G4UniformRand() - 0.5) + x0_i;
139 double y0_f = beamspotYSize_ * (G4UniformRand() - 0.5) + y0_i;
140 double z0_f = beamspotZSize_ * (G4UniformRand() - 0.5) + z0_i;
141 primary_vertex->SetPosition(x0_f, y0_f, z0_f);
142 }
143
144 // shift so that t=0 coincides with primaries arriving at (or coming from)
145 // the target
146 if (time_shift_primaries_) {
147 primary_vertex->SetT0(primary_vertex->GetT0() +
148 primary_vertex->GetZ0() / 299.702547);
149 }
150
151 } // iPV - loop over primary vertices
152 } else {
153 EXCEPTION_RAISE(
154 "NoPrimaries",
155 "No primary vertices were produced by any of the generators.");
156 }
157}
158} // namespace simcore::g4user
Class implementing the Geant4 primary generator action.
Header file for PrimaryGenerator.
Class that provides extra information for Geant4 primary particles.
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:29
Encapsulates user defined information associated with a Geant4 event.
Defines extra information attached to a Geant4 primary particle.