ATLAS Offline Software
CustomParticleFactory.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include <fstream>
6 #include <iomanip>
7 #include <iostream>
8 #include <stdexcept>
9 #include <sstream>
10 #include <iterator>
11 #include <map>
12 #include <set>
13 
14 #include "CustomPDGParser.h"
15 #include "CustomParticle.h"
16 #include "CustomParticleFactory.h"
17 #include "G4DecayTable.hh"
18 #include "G4ParticleTable.hh"
19 #include "G4PhaseSpaceDecayChannel.hh"
20 
22 {
23  static const std::set<G4ParticleDefinition *> particles = load();
24  return (particle!=nullptr && particles.find(particle)!=particles.end());
25 }
26 
28 {
29  // tickle the loading of the particles if it wasn't done yet
30  isCustomParticle(nullptr);
31 }
32 
33 std::set<G4ParticleDefinition *> CustomParticleFactory::load()
34 {
35  // the existing particle table
36  G4ParticleTable *theParticleTable = G4ParticleTable::GetParticleTable();
37 
38 
39  std::set<G4ParticleDefinition *> particles;
40 
41  std::ifstream configFile("particles.txt");
42  G4String pType="custom";
43  G4String pSubType="";
44  G4double spectatormass = 0;
45  G4ParticleDefinition* spectator = 0;
46  bool first = true;
47  double mass;
48  int pdgCode;
49  std::string name,line;
50  // This should be compatible IMO to SLHA
51  while (getline(configFile,line)) {
52  G4cout << "-------------------------------------------------" << G4endl;
53  std::string::size_type beg_idx,end_idx;
54 
55  beg_idx = line.find_first_not_of("\t #");
56  if (beg_idx > 0 && line[beg_idx-1] == '#') continue;
57  end_idx = line.find_first_of( "\t ", beg_idx);
58  if (end_idx == std::string::npos) continue;
59  char *endptr;
60  const std::string pdgCodeString = line.substr( beg_idx, end_idx - beg_idx );
61  pdgCode = strtol(pdgCodeString.c_str(), &endptr, 0);
62  if (endptr[0] != '\0') {
63  throw std::invalid_argument("Could not convert string to int: " + line.substr( beg_idx, end_idx - beg_idx ));
64  }
65 
66  beg_idx = line.find_first_not_of("\t ",end_idx);
67  end_idx = line.find_first_of( "\t #", beg_idx);
68  if (end_idx == std::string::npos) continue;
69  mass = atof(line.substr( beg_idx, end_idx - beg_idx ).c_str());
70 
71  beg_idx = line.find_first_not_of("\t# ",end_idx);
72  end_idx = line.length();
73  if (beg_idx==std::string::npos) beg_idx = end_idx;
74  name = line.substr( beg_idx, end_idx - beg_idx );
75  while (name.c_str()[0] == ' ') { name.erase(0,1); }
76  while (name[name.size()-1] == ' ') { name.erase(name.size()-1,1); }
77 
78  if (abs(pdgCode) / 1000000 == 0){
79  G4cout << "Pdg code too low " << pdgCode << " "<<abs(pdgCode) / 1000000 << std::endl;
80  continue;
81  }
82 
83  pType="custom";
84  if (CustomPDGParser::s_isRHadron(pdgCode)) pType = "rhadron";
85  if (CustomPDGParser::s_isSLepton(pdgCode)) pType = "sLepton";
86  if (CustomPDGParser::s_isMesonino(pdgCode)) pType = "mesonino";
87  if (CustomPDGParser::s_isSbaryon(pdgCode)) pType = "sbaryon";
88 
89  G4cout<<"pType: "<<pType<<G4endl;
90  G4cout<<"Charge of "<<name<<" is "<<CustomPDGParser::s_charge(pdgCode)<<G4endl;
91 
92  G4ParticleDefinition* previousDefinition = theParticleTable->FindParticle(pdgCode);
93  // if the particle has somehow already been added to the G4ParticleTable remove it
94  if (previousDefinition) {
95  G4cout << "Found a previousDefinition for " << name << "(" << pdgCode << ") in G4ParticleTable. Assuming that we want the new definition, so removing previous defnition! May cause issues elsewhere though..." << G4endl;
96  previousDefinition->DumpTable();
97  theParticleTable->Remove(previousDefinition);
98  delete previousDefinition;
99  }
100 
103  (int)CustomPDGParser::s_spin(pdgCode)-1, +1, 0,
104  0, 0, 0,
105  pType, 0, +1, pdgCode,
106  true, -1.0, NULL );
107  if (pType=="custom") {
108  spectatormass = mass;
109  spectator=particle;
110  particle->SetCloud(0);
111  particle->SetSpectator(0);
112  }
113  if (first) {
114  first = false;
115  spectatormass = mass;
116  spectator=particle;
117  particle->SetCloud(0);
118  particle->SetSpectator(0);
119  } else {
120  G4String cloudname = name+"cloud";
121  G4String cloudtype = pType+"cloud";
122  G4double cloudmass = mass-spectatormass;
123  CustomParticle *tmpParticle = new CustomParticle(
124  cloudname, cloudmass * CLHEP::GeV , 0.0*CLHEP::MeV, 0 ,
125  0, +1, 0,
126  0, 0, 0,
127  cloudtype, 0, +1, 0,
128  true, -1.0, NULL );
129  particle->SetCloud(tmpParticle);
130  particle->SetSpectator(spectator);
131 
132  G4cout << name << " being assigned cloud " << particle->GetCloud()->GetParticleName() << " and spectator " << particle->GetSpectator()->GetParticleName() << G4endl;
133  G4cout << "Masses: "
134  << particle->GetPDGMass()/CLHEP::GeV << " Gev, "
135  << particle->GetCloud()->GetPDGMass()/CLHEP::GeV << " GeV and "
136  << particle->GetSpectator()->GetPDGMass()/CLHEP::GeV << " GeV."
137  << G4endl;
138  }
139 
140  particles.insert(particle);
141  }
142  configFile.close();
143  G4cout << "-------------------------------------------------" << G4endl;
144 
145  // Reading decays from file
146  std::vector<std::vector<std::string>* > decays;
147  std::ifstream decayFile("decays.txt");
148  while (getline(decayFile,line)) {
149  std::istringstream is(line);
150  std::vector<std::string>* txtvec = new std::vector<std::string>(std::istream_iterator<std::string>(is),std::istream_iterator<std::string>());
151  decays.push_back(txtvec);
152  }
153  decayFile.close();
154 
155  // Looping over custom particles to add decays
157  name=(*part)->GetParticleName();
158  std::vector<std::vector<std::string> > mydecays;
159  for (unsigned int i = 0; i!= decays.size(); i++) {
160  if (name==(*(decays[i]))[0]) {
161  // Is this decay for me?
162  mydecays.push_back(*(decays[i]));
163  }
164  } // End of the for loop
165  if (mydecays.size()>0) { // Did I get any decays?
166  const int ndec=std::ssize(mydecays);
167  G4DecayTable* table = new G4DecayTable();
168  G4VDecayChannel** mode = new G4VDecayChannel*[ndec]{};
169  for (int i=0;i!=ndec;i++) {
170  std::vector<std::string> thisdec=mydecays[i];//deliberate copy
171  if (thisdec.empty()) continue;
172  const double branch = std::stod(thisdec.back()); // Reading branching ratio
173  thisdec.pop_back(); // Removing the number from the vector
174  for (const auto & thisString:thisdec) G4cout<<thisString<<G4endl;
175  if (thisdec.size()==3) {
176  mode[i] = new G4PhaseSpaceDecayChannel(thisdec[0],branch,2,thisdec[1],thisdec[2]);
177  } else if (thisdec.size()==4) {
178  mode[i] = new G4PhaseSpaceDecayChannel(thisdec[0],branch,3,thisdec[1],thisdec[2],thisdec[3]);
179  } else {
180  G4cout<<"Decay chain invalid!!!"<<std::endl;
181  }
182  }
183  for (G4int index=0; index <ndec; index++ ) { table->Insert(mode[index]); }
184  delete [] mode;
185  (*part)->SetDecayTable(table);
186  }
187  }
188  return particles;
189 }
LArG4FSStartPointFilter.part
part
Definition: LArG4FSStartPointFilter.py:21
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
CustomPDGParser::s_spin
static double s_spin(int pdg)
Definition: CustomPDGParser.cxx:133
GeV
#define GeV
Definition: PhysicsAnalysis/TauID/TauAnalysisTools/Root/HelperFunctions.cxx:17
checkFileSG.line
line
Definition: checkFileSG.py:75
Trk::ParticleSwitcher::particle
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:76
taskman.configFile
configFile
Definition: taskman.py:311
Base_Fragment.mass
mass
Definition: Sherpa_i/share/common/Base_Fragment.py:59
index
Definition: index.py:1
CustomParticleFactory::loadCustomParticles
static void loadCustomParticles()
Definition: CustomParticleFactory.cxx:27
SUSY_SimplifiedModel_PreInclude.decays
dictionary decays
Definition: SUSY_SimplifiedModel_PreInclude.py:12
python.SystemOfUnits.MeV
int MeV
Definition: SystemOfUnits.py:154
CustomPDGParser::s_charge
static double s_charge(int pdg)
Definition: CustomPDGParser.cxx:74
CustomPDGParser.h
lumiFormat.i
int i
Definition: lumiFormat.py:85
EvtGen_Fragment.decayFile
decayFile
Definition: EvtGen_Fragment.py:27
CustomParticleFactory.h
Preparation.mode
mode
Definition: Preparation.py:94
CustomParticleFactory::isCustomParticle
static bool isCustomParticle(G4ParticleDefinition *particle)
Definition: CustomParticleFactory.cxx:21
CustomParticleFactory::load
static std::set< G4ParticleDefinition * > load()
Definition: CustomParticleFactory.cxx:33
CxxUtils::atof
double atof(std::string_view str)
Converts a string into a double / float.
Definition: Control/CxxUtils/Root/StringUtils.cxx:91
CustomParticle
Definition: CustomParticle.h:17
CustomPDGParser::s_isRHadron
static bool s_isRHadron(int pdg)
Definition: CustomPDGParser.cxx:13
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
python.ext.table_printer.table
list table
Definition: table_printer.py:81
RTTAlgmain.branch
branch
Definition: RTTAlgmain.py:61
CustomParticle.h
CustomPDGParser::s_isMesonino
static bool s_isMesonino(int pdg)
Definition: CustomPDGParser.cxx:59
DeMoScan.first
bool first
Definition: DeMoScan.py:536
LArG4FSStartPointFilter.particles
list particles
Definition: LArG4FSStartPointFilter.py:84
CustomPDGParser::s_isSbaryon
static bool s_isSbaryon(int pdg)
Definition: CustomPDGParser.cxx:66
python.SystemOfUnits.eplus
int eplus
Definition: SystemOfUnits.py:137
CustomPDGParser::s_isSLepton
static bool s_isSLepton(int pdg)
Definition: CustomPDGParser.cxx:32