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 // Loop over all particle associated with the primary vertex and
89 // set the generator status to 1.
90 for (int iparticle = 0; iparticle < primary_vertex->GetNumberOfParticle();
91 ++iparticle) {
92 G4PrimaryParticle* primary = primary_vertex->GetPrimary(iparticle);
93
94 auto primary_info{dynamic_cast<UserPrimaryParticleInformation*>(
95 primary->GetUserInformation())};
96 if (not primary_info) {
97 // no user info defined
98 // ==> make a new one
99 primary_info = new UserPrimaryParticleInformation;
100 primary->SetUserInformation(primary_info);
101 } // check if primaryinfo is defined
102
103 int hepStatus = primary_info->getHepEvtStatus();
104 if (hepStatus <= 0) {
105 // undefined hepStatus ==> set to 1
106 primary_info->setHepEvtStatus(1);
107 } // check if hepStatus defined
108
109 } // iparticle - loop over primary particles from this vertex
110
111 // include the weight of this primary vertex in the event weight
112 event_info->incWeight(primary_vertex->GetWeight());
113
114 // smear beamspot if it is turned on
115 if (useBeamspot_) {
116 double x0_i = primary_vertex->GetX0();
117 double y0_i = primary_vertex->GetY0();
118 double z0_i = primary_vertex->GetZ0();
119 /*
120 * G4UniformRand returns a number in [0,1]
121 * - we shift this range so that it is [-0.5,0.5]
122 * - multiply by the width to get [-0.5*size,0.5*size]
123 * - add the initial point (in case its off center) to get
124 * [init-0.5*size, init+0.5*size]
125 */
126 double x0_f = beamspotXSize_ * (G4UniformRand() - 0.5) + x0_i;
127 double y0_f = beamspotYSize_ * (G4UniformRand() - 0.5) + y0_i;
128 double z0_f = beamspotZSize_ * (G4UniformRand() - 0.5) + z0_i;
129 primary_vertex->SetPosition(x0_f, y0_f, z0_f);
130 }
131
132 // shift so that t=0 coincides with primaries arriving at (or coming from)
133 // the target
134 if (time_shift_primaries_) {
135 primary_vertex->SetT0(primary_vertex->GetT0() +
136 primary_vertex->GetZ0() / 299.702547);
137 }
138
139 } // iPV - loop over primary vertices
140 } else {
141 EXCEPTION_RAISE(
142 "NoPrimaries",
143 "No primary vertices were produced by any of the generators.");
144 }
145}
146} // 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:27
T getParameter(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:89
Encapsulates user defined information associated with a Geant4 event.
Defines extra information attached to a Geant4 primary particle.