18#include "TRestGeant4ParticleSource.h"
20#include <TRestReflector.h>
21#include <TRestStringHelper.h>
22#include <TRestStringOutput.h>
24#include "TRestGeant4Metadata.h"
27using namespace TRestGeant4PrimaryGeneratorTypes;
31TRestGeant4ParticleSource::TRestGeant4ParticleSource() =
default;
33TRestGeant4ParticleSource::~TRestGeant4ParticleSource() =
default;
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() <<
", ";
46 if (GetParticleCharge() != 0) {
47 RESTMetadata <<
"Particle charge: " << GetParticleCharge() <<
RESTendl;
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: "
56 RESTMetadata <<
"Angular distribution histogram name: " << GetAngularDistributionNameInFile()
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;
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;
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: "
89 RESTMetadata <<
"Energy distribution histogram name: " << GetEnergyDistributionNameInFile()
92 if (GetEnergyDistributionRangeMin() == GetEnergyDistributionRangeMax()) {
93 RESTMetadata <<
"Energy distribution energy: " << GetEnergy() <<
" keV" <<
RESTendl;
95 RESTMetadata <<
"Energy distribution range (keV): (" << GetEnergyDistributionRangeMin() <<
", "
96 << GetEnergyDistributionRangeMax() <<
")" <<
RESTendl;
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;
109 if (model.empty() || model ==
"geant4" || model.find(
".dat") != string::npos) {
118 TClass* c = TClass::GetClass((
"TRestGeant4ParticleSource" + model).c_str());
123 std::cout <<
"REST ERROR! generator wrapper \"" << (
"TRestGeant4ParticleSource" + model)
124 <<
"\" not found!" << std::endl;
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;
139 modelUse = fullPathName;
141 SetGenFilename(modelUse);
143 if (((
string)fGenFilename).find(
".dat") != std::string::npos) {
151void TRestGeant4ParticleSource::Update() {
152 if (!fParticlesTemplate.empty()) {
154 Int_t rndCollection = (Int_t)(fRandomMethod() * fParticlesTemplate.size());
155 Int_t pCollectionID = rndCollection % fParticlesTemplate.size();
156 fParticles = fParticlesTemplate[pCollectionID];
164TVector3 TRestGeant4ParticleSource::GetDirection()
const {
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;
203 infile.open(fileName);
204 if (!infile.is_open()) {
205 printf(
"Error when opening file %s\n", fileName.Data());
209 int generatorEvents = 0;
212 for (
int i = 0; i < 24; i++) {
214 int pos = s.find(
"@nevents=");
215 if (pos != -1) generatorEvents =
StringToInteger(s.substr(10, s.length() - 10));
218 if (generatorEvents == 0) {
219 RESTError <<
"TRestG4Metadata::ReadNewDecay0File. Problem reading generator file" <<
RESTendl;
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++) {
229 while (!infile.eof() && pos == -1) {
231 pos = s.find(
"@event_start");
238 infile >> nParticles;
239 RESTDebug <<
"Number of particles: " << nParticles <<
RESTendl;
242 for (
int i = 0; i < nParticles && !infile.eof(); i++) {
244 Double_t momx, momy, momz, mass;
245 Double_t energy = -1, momentum2;
249 infile >> pID >> time >> momx >> momy >> momz >> pName;
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;
258 momentum2 = (momx * momx) + (momy * momy) + (momz * momz);
261 energy = TMath::Sqrt(momentum2 + mass * mass) - mass;
262 particle.SetParticleName(
"e-");
263 particle.SetParticleCharge(-1);
264 particle.SetExcitationLevel(0);
266 }
else if (pID == 1) {
267 momentum2 = (momx * momx) + (momy * momy) + (momz * momz);
269 energy = TMath::Sqrt(momentum2);
270 particle.SetParticleName(
"gamma");
271 particle.SetParticleCharge(0);
272 particle.SetExcitationLevel(0);
274 cout <<
"Particle id " << pID <<
" not recognized" << std::endl;
277 TVector3 momDirection(momx, momy, momz);
278 momDirection = momDirection.Unit();
280 particle.SetEnergy(1000. * energy);
281 particle.SetDirection(momDirection);
283 this->AddParticle(particle);
285 this->FlushParticlesTemplate();
299 infile.open(fileName);
300 if (!infile.is_open()) {
301 printf(
"Error when opening file %s\n", fileName.Data());
308 for (
int i = 0; i < 30; i++) {
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) {
318 <<
"TRestG4Metadata::ReadOldDecay0File. Problem reading generator file: no \"First event and "
319 "full number of events:\" header.\n";
323 int fGeneratorEvents;
324 infile >> tmpInt >> fGeneratorEvents;
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++) {
341 infile >> evID >> time >> nParticles;
344 for (
int i = 0; i < nParticles && !infile.eof(); i++) {
346 Double_t momx, momy, momz, mass;
347 Double_t energy = -1, momentum2;
348 Double_t x = 0, y = 0, z = 0;
350 infile >> pID >> momx >> momy >> momz >> time;
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);
360 particle.SetParticleName(pID == 2 ?
"e+" :
"e-");
361 particle.SetParticleCharge(pID == 2 ? 1 : -1);
364 particle.SetParticleName(pID == 5 ?
"mu+" :
"mu-");
365 particle.SetParticleCharge(pID == 5 ? 1 : -1);
368 particle.SetParticleName(
"proton");
369 particle.SetParticleCharge(1);
372 particle.SetParticleName(
"gamma");
373 particle.SetParticleCharge(0);
376 energy = TMath::Sqrt(momentum2 + mass * mass) - mass;
377 particle.SetExcitationLevel(0);
379 cout <<
"Particle id " << pID <<
" not recognized" << std::endl;
382 TVector3 momDirection(momx, momy, momz);
383 momDirection = momDirection.Unit();
385 particle.SetEnergy(1000. * energy);
386 particle.SetDirection(momDirection);
387 particle.SetOrigin(TVector3(x, y, z));
389 this->AddParticle(particle);
392 this->FlushParticlesTemplate();
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.
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.