REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestGeant4ParticleSource.cxx
1
17
18#include "TRestGeant4ParticleSource.h"
19
20#include <TRestReflector.h>
21#include <TRestStringHelper.h>
22#include <TRestStringOutput.h>
23
24#include "TRestGeant4Metadata.h"
25
26using namespace std;
27using namespace TRestGeant4PrimaryGeneratorTypes;
28
30
31TRestGeant4ParticleSource::TRestGeant4ParticleSource() = default;
32
33TRestGeant4ParticleSource::~TRestGeant4ParticleSource() = default;
34
36 RESTMetadata << " " << RESTendl;
37 if (GetParticleName() != "" && GetParticleName() != "NO_SUCH_PARA")
38 RESTMetadata << "Particle Source Name: " << GetParticleName() << RESTendl;
39 if (!fParticlesTemplate.empty() && fGenFilename != "NO_SUCH_PARA") {
40 RESTMetadata << "Generator file: " << GetGenFilename() << RESTendl;
41 RESTMetadata << "Stored templates: " << fParticlesTemplate.size() << RESTendl;
42 RESTMetadata << "Particles: ";
43 for (const auto& particle : fParticles) RESTMetadata << particle.GetParticleName() << ", ";
44 RESTMetadata << RESTendl;
45 } else {
46 if (GetParticleCharge() != 0) {
47 RESTMetadata << "Particle charge: " << GetParticleCharge() << RESTendl;
48 }
49 RESTMetadata << "Angular distribution type: " << GetAngularDistributionType() << RESTendl;
50 if ((StringToAngularDistributionTypes(GetAngularDistributionType().Data()) ==
51 AngularDistributionTypes::TH1D) ||
52 (StringToAngularDistributionTypes(GetAngularDistributionType().Data()) ==
53 AngularDistributionTypes::TH2D)) {
54 RESTMetadata << "Angular distribution filename: "
55 << TRestTools::GetPureFileName((string)GetAngularDistributionFilename()) << RESTendl;
56 RESTMetadata << "Angular distribution histogram name: " << GetAngularDistributionNameInFile()
57 << RESTendl;
58 }
59 RESTMetadata << "Angular distribution direction: (" << GetDirection().X() << "," << GetDirection().Y()
60 << "," << GetDirection().Z() << ")" << RESTendl;
61 if ((StringToAngularDistributionTypes(GetAngularDistributionType().Data()) ==
62 AngularDistributionTypes::ISOTROPIC)) {
63 if (GetAngularDistributionIsotropicConeHalfAngle() != 0) {
64 const double solidAngle =
65 2 * TMath::Pi() * (1 - TMath::Cos(GetAngularDistributionIsotropicConeHalfAngle()));
66 RESTMetadata << "Angular distribution isotropic cone half angle (deg): "
67 << GetAngularDistributionIsotropicConeHalfAngle() * TMath::RadToDeg()
68 << " - solid angle: " << solidAngle << " ("
69 << solidAngle / (4 * TMath::Pi()) * 100 << "%)" << RESTendl;
70 }
71 }
72 if ((StringToAngularDistributionTypes(GetAngularDistributionType().Data()) ==
73 AngularDistributionTypes::TH1D) ||
74 StringToAngularDistributionTypes(GetAngularDistributionType().Data()) ==
75 AngularDistributionTypes::TH2D) {
76 RESTMetadata << "Angular distribution range (deg): ("
77 << GetAngularDistributionRangeMin() * TMath::RadToDeg() << ", "
78 << GetAngularDistributionRangeMax() * TMath::RadToDeg() << ")" << RESTendl;
79 RESTMetadata << "Angular distribution random sampling grid size: "
80 << GetAngularDistributionFormulaNPoints() << RESTendl;
81 }
82 RESTMetadata << "Energy distribution type: " << GetEnergyDistributionType() << RESTendl;
83 if ((StringToEnergyDistributionTypes(GetEnergyDistributionType().Data()) ==
84 EnergyDistributionTypes::TH1D) ||
85 StringToEnergyDistributionTypes(GetEnergyDistributionType().Data()) ==
86 EnergyDistributionTypes::TH2D) {
87 RESTMetadata << "Energy distribution filename: "
88 << TRestTools::GetPureFileName((string)GetEnergyDistributionFilename()) << RESTendl;
89 RESTMetadata << "Energy distribution histogram name: " << GetEnergyDistributionNameInFile()
90 << RESTendl;
91 }
92 if (GetEnergyDistributionRangeMin() == GetEnergyDistributionRangeMax()) {
93 RESTMetadata << "Energy distribution energy: " << GetEnergy() << " keV" << RESTendl;
94 } else {
95 RESTMetadata << "Energy distribution range (keV): (" << GetEnergyDistributionRangeMin() << ", "
96 << GetEnergyDistributionRangeMax() << ")" << RESTendl;
97 }
98 if ((StringToEnergyDistributionTypes(GetEnergyDistributionType().Data()) ==
99 EnergyDistributionTypes::FORMULA) ||
100 StringToEnergyDistributionTypes(GetEnergyDistributionType().Data()) ==
101 EnergyDistributionTypes::FORMULA2) {
102 RESTMetadata << "Energy distribution random sampling grid size: "
103 << GetEnergyDistributionFormulaNPoints() << RESTendl;
104 }
105 }
106}
107
108TRestGeant4ParticleSource* TRestGeant4ParticleSource::instantiate(std::string model) {
109 if (model.empty() || model == "geant4" || model.find(".dat") != string::npos) {
110 // use default generator
111 return new TRestGeant4ParticleSource();
112 } else {
113 // use specific generator
114 // naming convention: TRestGeant4ParticleSourceXXX
115 // currently supported generators: decay0, source
116 // in future we may add wrapper of generators: pythia(for HEP), etc.
117 model[0] = *REST_StringHelper::ToUpper(std::string(&model[0], 1)).c_str();
118 TClass* c = TClass::GetClass(("TRestGeant4ParticleSource" + model).c_str());
119 if (c) // this means we have the package installed
120 {
121 return (TRestGeant4ParticleSource*)c->New();
122 } else {
123 std::cout << "REST ERROR! generator wrapper \"" << ("TRestGeant4ParticleSource" + model)
124 << "\" not found!" << std::endl;
125 }
126 }
127 return nullptr;
128}
129
131 TString modelUse = GetParameter("use");
132 if (((string)modelUse).find(".dat") != string::npos) {
133 string fullPathName = SearchFile((string)modelUse);
134 if (fullPathName == "") {
135 RESTError << "File not found: " << modelUse << RESTendl;
136 RESTError << "Decay0 generator file could not be found!!" << RESTendl;
137 exit(1);
138 }
139 modelUse = fullPathName;
140 }
141 SetGenFilename(modelUse);
142
143 if (((string)fGenFilename).find(".dat") != std::string::npos) {
144 if (TRestTools::fileExists((string)fGenFilename)) {
145 ReadEventDataFile(fGenFilename);
146 }
147 }
148}
149
150// base class's generator action: randomize the particle's energy/direction with distribution file
151void TRestGeant4ParticleSource::Update() {
152 if (!fParticlesTemplate.empty()) {
153 // we use particle template to generate particles
154 Int_t rndCollection = (Int_t)(fRandomMethod() * fParticlesTemplate.size());
155 Int_t pCollectionID = rndCollection % fParticlesTemplate.size();
156 fParticles = fParticlesTemplate[pCollectionID];
157 } else {
158 TRestGeant4Particle p(*this);
159 // TODO: implement particle generation for toy simulation
160 fParticles = {p};
161 }
162}
163
164TVector3 TRestGeant4ParticleSource::GetDirection() const {
165 // direction should be unit (normalized) vector with a tolerance of 0.001
166
167 const double magnitude = fDirection.Mag();
168 constexpr double tolerance = 0.001;
169 if (TMath::Abs(magnitude - 1) > tolerance) {
170 cerr << "TRestGeant4ParticleSource::GetDirection: Direction must be unit vector" << endl;
171 exit(1);
172 }
173
174 return fDirection;
175}
190 if (!ReadOldDecay0File(fName)) {
191 ReadNewDecay0File(fName);
192 }
193}
194
202 ifstream infile;
203 infile.open(fileName);
204 if (!infile.is_open()) {
205 printf("Error when opening file %s\n", fileName.Data());
206 return false;
207 }
208
209 int generatorEvents = 0;
210 string s;
211 // First lines are discarded.
212 for (int i = 0; i < 24; i++) {
213 getline(infile, s);
214 int pos = s.find("@nevents=");
215 if (pos != -1) generatorEvents = StringToInteger(s.substr(10, s.length() - 10));
216 }
217
218 if (generatorEvents == 0) {
219 RESTError << "TRestG4Metadata::ReadNewDecay0File. Problem reading generator file" << RESTendl;
220 exit(1);
221 }
222
223 TRestGeant4Particle particle;
224
225 RESTDebug << "Reading generator file: " << fileName << RESTendl;
226 RESTDebug << "Total number of events: " << generatorEvents << RESTendl;
227 for (int n = 0; n < generatorEvents && !infile.eof(); n++) {
228 int pos = -1;
229 while (!infile.eof() && pos == -1) {
230 getline(infile, s);
231 pos = s.find("@event_start");
232 }
233
234 // Time - nuclide is skipped
235 getline(infile, s);
236
237 Int_t nParticles;
238 infile >> nParticles;
239 RESTDebug << "Number of particles: " << nParticles << RESTendl;
240
241 // cout << evID <<" "<< time <<" "<< nParticles <<" "<< std::endl;
242 for (int i = 0; i < nParticles && !infile.eof(); i++) {
243 Int_t pID;
244 Double_t momx, momy, momz, mass;
245 Double_t energy = -1, momentum2;
246 TString pName;
247
248 Double_t time;
249 infile >> pID >> time >> momx >> momy >> momz >> pName;
250
251 RESTDebug << " ---- New particle found --- " << RESTendl;
252 RESTDebug << " Particle name: " << pName << RESTendl;
253 RESTDebug << " - pId: " << pID << RESTendl;
254 RESTDebug << " - Relative time: " << time << RESTendl;
255 RESTDebug << " - px: " << momx << " py: " << momy << " pz: " << momz << " " << RESTendl;
256
257 if (pID == 3) {
258 momentum2 = (momx * momx) + (momy * momy) + (momz * momz);
259 mass = 0.511;
260
261 energy = TMath::Sqrt(momentum2 + mass * mass) - mass;
262 particle.SetParticleName("e-");
263 particle.SetParticleCharge(-1);
264 particle.SetExcitationLevel(0);
265
266 } else if (pID == 1) {
267 momentum2 = (momx * momx) + (momy * momy) + (momz * momz);
268
269 energy = TMath::Sqrt(momentum2);
270 particle.SetParticleName("gamma");
271 particle.SetParticleCharge(0);
272 particle.SetExcitationLevel(0);
273 } else {
274 cout << "Particle id " << pID << " not recognized" << std::endl;
275 }
276
277 TVector3 momDirection(momx, momy, momz);
278 momDirection = momDirection.Unit();
279
280 particle.SetEnergy(1000. * energy);
281 particle.SetDirection(momDirection);
282
283 this->AddParticle(particle);
284 }
285 this->FlushParticlesTemplate();
286 }
287
288 return true;
289}
290
298 ifstream infile;
299 infile.open(fileName);
300 if (!infile.is_open()) {
301 printf("Error when opening file %s\n", fileName.Data());
302 return false;
303 }
304
305 string s;
306 // First lines are discarded.
307 int headerFound = 0;
308 for (int i = 0; i < 30; i++) {
309 getline(infile, s);
310 if (s.find("#!bxdecay0 1.0.0") != string::npos) return false;
311 if (s.find("First event and full number of events:") != string::npos) {
312 headerFound = 1;
313 break;
314 }
315 }
316 if (!headerFound) {
317 RESTError
318 << "TRestG4Metadata::ReadOldDecay0File. Problem reading generator file: no \"First event and "
319 "full number of events:\" header.\n";
320 abort();
321 }
322 int tmpInt;
323 int fGeneratorEvents;
324 infile >> tmpInt >> fGeneratorEvents;
325
326 // cout << "i: " << tmpInt << " fN: " << fGeneratorEvents << std::endl;
327 // TRestGeant4ParticleSource* src = TRestGeant4ParticleSource::instantiate();
328 // this->SetGenFilename(fileName);
329 // this->SetAngularDistributionType("flux");
330 // this->SetEnergyDistributionType("mono");
331
332 TRestGeant4Particle particle;
333
334 cout << "Reading generator file: " << fileName << std::endl;
335 cout << "Total number of events: " << fGeneratorEvents << std::endl;
336 for (int n = 0; n < fGeneratorEvents && !infile.eof(); n++) {
337 Int_t nParticles;
338 Int_t evID;
339 Double_t time;
340
341 infile >> evID >> time >> nParticles;
342
343 // cout << evID <<" "<< time <<" "<< nParticles <<" "<< std::endl;
344 for (int i = 0; i < nParticles && !infile.eof(); i++) {
345 Int_t pID;
346 Double_t momx, momy, momz, mass;
347 Double_t energy = -1, momentum2;
348 Double_t x = 0, y = 0, z = 0;
349
350 infile >> pID >> momx >> momy >> momz >> time;
351 // infile >> x >> y >> z;
352
353 // cout << momx << " " << momy << " " << momz << " " << std::endl;
354
355 bool ise = 2 <= pID && pID <= 3, ismu = 5 <= pID && pID <= 6, isp = pID == 14, isg = pID == 1;
356 if (ise || ismu || isp || isg) {
357 momentum2 = (momx * momx) + (momy * momy) + (momz * momz);
358 if (ise) {
359 mass = 0.511;
360 particle.SetParticleName(pID == 2 ? "e+" : "e-");
361 particle.SetParticleCharge(pID == 2 ? 1 : -1);
362 } else if (ismu) {
363 mass = 105.7;
364 particle.SetParticleName(pID == 5 ? "mu+" : "mu-");
365 particle.SetParticleCharge(pID == 5 ? 1 : -1);
366 } else if (isp) {
367 mass = 938.3;
368 particle.SetParticleName("proton");
369 particle.SetParticleCharge(1);
370 } else {
371 mass = 0;
372 particle.SetParticleName("gamma");
373 particle.SetParticleCharge(0);
374 }
375
376 energy = TMath::Sqrt(momentum2 + mass * mass) - mass;
377 particle.SetExcitationLevel(0);
378 } else {
379 cout << "Particle id " << pID << " not recognized" << std::endl;
380 }
381
382 TVector3 momDirection(momx, momy, momz);
383 momDirection = momDirection.Unit();
384
385 particle.SetEnergy(1000. * energy);
386 particle.SetDirection(momDirection);
387 particle.SetOrigin(TVector3(x, y, z));
388
389 this->AddParticle(particle);
390 }
391
392 this->FlushParticlesTemplate();
393 }
394
395 return true;
396}
void ReadEventDataFile(TString fName)
Reads an input file produced by Decay0.
virtual void InitFromConfigFile() override
To make settings from rml file. This method must be implemented in the derived class.
virtual void PrintMetadata() override
Implemented it in the derived metadata class to print out specific metadata information.
bool ReadOldDecay0File(TString fileName)
Reads particle information using the file format from older Decay0 versions.
bool ReadNewDecay0File(TString fileName)
Reads particle information using the file format from newer Decay0 versions.
A class used to store particle properties.
endl_t RESTendl
Termination flag object for TRestStringOutput.
std::string SearchFile(std::string filename)
Search files in current directory and directories specified in "searchPath" section.
std::string GetParameter(std::string parName, TiXmlElement *e, TString defaultValue=PARAMETER_NOT_FOUND_STR)
Returns the value for the parameter named parName in the given section.
static std::string GetPureFileName(const std::string &fullPathFileName)
Removes all directories in the full path filename description given in the argument.
Definition: TRestTools.cxx:863
static bool fileExists(const std::string &filename)
Returns true if the file (or directory) with path filename exists.
Definition: TRestTools.cxx:728
std::string ToUpper(std::string in)
Convert string to its upper case. Alternative of TString::ToUpper.
Int_t StringToInteger(std::string in)
Gets an integer from a string.