CMS 3D CMS Logo

CustomParticleFactory.cc
Go to the documentation of this file.
1 #include <fstream>
2 #include <iomanip>
3 #include <iostream>
4 #include <string>
5 #include <vector>
6 #include <sstream>
7 #include <set>
8 #include <locale>
9 
13 
17 
18 #include <G4ParticleTable.hh>
19 #include "G4DecayTable.hh"
20 #include <G4PhaseSpaceDecayChannel.hh>
21 #include "G4ProcessManager.hh"
22 
23 using namespace CLHEP;
24 
26 std::vector<G4ParticleDefinition *> CustomParticleFactory::m_particles;
27 
29  if(loaded) return;
30  loaded = true;
31 
32  std::ifstream configFile(filePath.c_str());
33 
35  edm::LogInfo("SimG4CoreCustomPhysics")
36  <<"CustomParticleFactory: Reading Custom Particle and G4DecayTable from \n"
37  << filePath;
38  // This should be compatible IMO to SLHA
39  G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
40  while(getline(configFile,line)){
41  line.erase(0, line.find_first_not_of(" \t")); // Remove leading whitespace.
42  if (line.length()==0 || line.at(0) == '#') continue; // Skip blank lines and comments.
43  if (ToLower(line).find("block") < line.npos && // The mass table begins with a line containing "BLOCK MASS".
44  ToLower(line).find("mass") < line.npos) {
45  edm::LogInfo("SimG4CoreCustomPhysics") <<"CustomParticleFactory: Retrieving mass table.";
46  getMassTable(&configFile);
47  }
48  if(line.find("DECAY")<line.npos){
49  int pdgId;
50  double width;
51  std::string tmpString;
52  std::stringstream lineStream(line);
53  lineStream >> tmpString >> pdgId >> width;
54  // assume SLHA format, e.g.: DECAY 1000021 5.50675438E+00 # gluino decays
55  edm::LogInfo("SimG4CoreCustomPhysics")
56  <<"CustomParticleFactory: entry to G4DecayTable: pdgID, width " << pdgId << ", " << width;
57  G4DecayTable* aDecayTable = getDecayTable(&configFile, pdgId);
58  G4ParticleDefinition *aParticle = theParticleTable->FindParticle(pdgId);
59  G4ParticleDefinition *aAntiParticle = theParticleTable->FindAntiParticle(pdgId);
60  if (!aParticle) continue;
61  aParticle->SetDecayTable(aDecayTable);
62  aParticle->SetPDGStable(false);
63  aParticle->SetPDGLifeTime(1.0/(width*GeV)*6.582122e-22*MeV*s);
64  if(aAntiParticle && aAntiParticle->GetPDGEncoding()!=pdgId){
65  aAntiParticle->SetDecayTable(getAntiDecayTable(pdgId,aDecayTable));
66  aAntiParticle->SetPDGStable(false);
67  aAntiParticle->SetPDGLifeTime(1.0/(width*GeV)*6.582122e-22*MeV*s);
68  }
69  }
70  }
71 }
72 
74 
75  if(abs(pdgCode)%100 <14 && abs(pdgCode) / 1000000 == 0){
76  edm::LogError("") << "Pdg code too low " << pdgCode << " "<<abs(pdgCode) / 1000000;
77  return;
78  }
79 
81  G4String pType="custom";
82  G4String pSubType="";
83  G4double spectatormass = 0.0;
84  G4ParticleDefinition* spectator = nullptr;
86  if(CustomPDGParser::s_isRHadron(pdgCode)) pType = "rhadron";
87  if(CustomPDGParser::s_isSLepton(pdgCode)) pType = "sLepton";
88  if(CustomPDGParser::s_isMesonino(pdgCode)) pType = "mesonino";
89  if(CustomPDGParser::s_isSbaryon(pdgCode)) pType = "sbaryon";
90 
91  double massGeV =mass*GeV;
92  double width = 0.0*MeV;
93  double charge = eplus* CustomPDGParser::s_charge(pdgCode);
94  if (name.compare(0,4,"~HIP") == 0)
95  {
96  if ((name.compare(0,7,"~HIPbar") == 0)) {
97  std::string str = name.substr(7);
98  charge=eplus*atoi(str.c_str())/3.;
99  } else {
100  std::string str = name.substr(4);
101  charge=eplus*atoi(str.c_str())*-1./3.;
102  }
103  }
104  if (name.compare(0,9,"anti_~HIP") == 0)
105  {
106  if ((name.compare(0,12,"anti_~HIPbar") == 0)) {
107  std::string str = name.substr (12);
108  charge=eplus*atoi(str.c_str())*-1./3.;
109  } else {
110  std::string str = name.substr (9);
111  charge=eplus*atoi(str.c_str())*1./3.;
112  }
113  }
114  int spin = (int)CustomPDGParser::s_spin(pdgCode)-1;
115  int parity = +1;
116  int conjugation = 0;
117  int isospin = 0;
118  int isospinZ = 0;
119  int gParity = 0;
120  int lepton = 0; //FIXME:
121  int baryon = 1; //FIXME:
122  bool stable = true;
123  double lifetime = -1;
124 
125  if(CustomPDGParser::s_isDphoton(pdgCode)){
126  pType = "darkpho";
127  spin = 2;
128  parity = -1;
129  conjugation = -1;
130  isospin = 0;
131  isospinZ = 0;
132  gParity = 0;
133  lepton = 0;
134  baryon =0;
135  stable = true;
136  lifetime = -1;
137  }
138 
139  G4DecayTable *decaytable = nullptr;
140  G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
141 
142  CustomParticle *particle = new CustomParticle(name, massGeV, width, charge, spin,
143  parity, conjugation, isospin, isospinZ,
144  gParity, pType, lepton, baryon, pdgCode,
145  stable, lifetime, decaytable);
146 
147  if(pType == "rhadron" && name!="~g"){
148  G4String cloudname = name+"cloud";
149  G4String cloudtype = pType+"cloud";
150  spectator = theParticleTable->FindParticle(1000021);
151  spectatormass = spectator->GetPDGMass();
152  G4double cloudmass = mass-spectatormass/GeV;
153  CustomParticle *tmpParticle = new CustomParticle(
154  cloudname, cloudmass * GeV , 0.0*MeV, 0 ,
155  0, +1, 0,
156  0, 0, 0,
157  cloudtype, 0, +1, 0,
158  true, -1.0, NULL );
159  particle->SetCloud(tmpParticle);
160  particle->SetSpectator(spectator);
161 
162  edm::LogInfo("SimG4CoreCustomPhysics")
163  <<"CustomParticleFactory: " <<name<<" being assigned "
164  <<particle->GetCloud()->GetParticleName()
165  <<" and "<<particle->GetSpectator()->GetParticleName() << "\n"
166  <<" Masses: "<<particle->GetPDGMass()/GeV<<" Gev, "
167  <<particle->GetCloud()->GetPDGMass()/GeV<<" GeV and "
168  <<particle->GetSpectator()->GetPDGMass()/GeV<<" GeV.";
169  } else if(pType == "mesonino" || pType == "sbaryon") {
170  int sign=1;
171  if(pdgCode < 0 ) sign=-1;
172 
173  G4String cloudname = name+"cloud";
174  G4String cloudtype = pType+"cloud";
175  if(CustomPDGParser::s_isstopHadron(pdgCode)) {
176  spectator = theParticleTable->FindParticle(1000006*sign);
177  }
178  else {
179  if (CustomPDGParser::s_issbottomHadron(pdgCode)) {
180  spectator = theParticleTable->FindParticle(1000005*sign);
181  } else {
182  spectator = nullptr;
183  edm::LogError("SimG4CoreCustomPhysics")<< "CustomParticleFactory: Cannot find spectator parton";
184  }
185  }
186  if(spectator) spectatormass = spectator->GetPDGMass();
187  G4double cloudmass = mass-spectatormass/GeV;
188  CustomParticle *tmpParticle = new CustomParticle(
189  cloudname, cloudmass * GeV , 0.0*MeV, 0 ,
190  0, +1, 0,
191  0, 0, 0,
192  cloudtype, 0, +1, 0,
193  true, -1.0, NULL );
194  particle->SetCloud(tmpParticle);
195  particle->SetSpectator(spectator);
196 
197  edm::LogInfo("SimG4CoreCustomPhysics")
198  <<"CustomParticleFactory: "<<name<<" being assigned "
199  <<particle->GetCloud()->GetParticleName()
200  <<" and "<<particle->GetSpectator()->GetParticleName() << "\n"
201  <<" Masses: "
202  <<particle->GetPDGMass()/GeV<<" Gev, "
203  <<particle->GetCloud()->GetPDGMass()/GeV<<" GeV and "
204  <<particle->GetSpectator()->GetPDGMass()/GeV<<" GeV.";
205  }
206  else{
207  particle->SetCloud(0);
208  particle->SetSpectator(0);
209  }
210  m_particles.push_back(particle);
211 }
212 
213 void CustomParticleFactory::getMassTable(std::ifstream *configFile) {
214 
215  int pdgId;
216  double mass;
219  // This should be compatible IMO to SLHA
220  while (getline(*configFile,line)) {
221  line.erase(0, line.find_first_not_of(" \t")); // remove leading whitespace
222  if (line.length()==0 || line.at(0) == '#') continue; // skip blank lines and comments
223  if (ToLower(line).find("block") < line.npos) {
224  edm::LogInfo("SimG4CoreCustomPhysics")
225  <<"CustomParticleFactory: Finished the Mass Table ";
226  break;
227  }
228  std::stringstream sstr(line);
229  sstr >> pdgId >> mass >> tmp >> name; // Assume SLHA format, e.g.: 1000001 5.68441109E+02 # ~d_L
230 
231  edm::LogInfo("SimG4CoreCustomPhysics")
232  <<"CustomParticleFactory: Calling addCustomParticle for pdgId: " << pdgId
233  << ", mass " << mass << ", name " << name;
234  addCustomParticle(pdgId, fabs(mass), name);
236  int pdgIdPartner = pdgId%100;
237  G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
238  G4ParticleDefinition *aParticle = theParticleTable->FindParticle(pdgIdPartner);
239  //Add antiparticles for SUSY particles only, not for rHadrons.
240  edm::LogInfo("SimG4CoreCustomPhysics")
241  <<"CustomParticleFactory: Found aParticle = " << aParticle
242  << ", pdgId = " << pdgId
243  << ", pdgIdPartner = " << pdgIdPartner
244  << ", CustomPDGParser::s_isRHadron(pdgId) = " << CustomPDGParser::s_isRHadron(pdgId)
245  << ", CustomPDGParser::s_isstopHadron(pdgId) = " << CustomPDGParser::s_isstopHadron(pdgId);
246 
247  if (aParticle &&
248  !CustomPDGParser::s_isRHadron(pdgId) &&
249  !CustomPDGParser::s_isstopHadron(pdgId) &&
250  pdgId!=1000006 &&
251  pdgId!=-1000006 &&
252  pdgId!=25 &&
253  pdgId!=35 &&
254  pdgId!=36 &&
255  pdgId!=37){
256  int sign = aParticle->GetAntiPDGEncoding()/pdgIdPartner;
257  edm::LogInfo("SimG4CoreCustomPhysics")
258  <<"CustomParticleFactory: Found sign = " << sign
259  << ", aParticle->GetAntiPDGEncoding() " << aParticle->GetAntiPDGEncoding()
260  << ", pdgIdPartner = " << pdgIdPartner;
261  if(abs(sign)!=1) {
262  edm::LogInfo("SimG4CoreCustomPhysics")
263  <<"CustomParticleFactory: sgn= "<<sign<<" a "
264  <<aParticle->GetAntiPDGEncoding()<<" b "<<pdgIdPartner;
265  aParticle->DumpTable();
266  }
267  if(sign==-1 && pdgId!=25 && pdgId!=35 && pdgId!=36 && pdgId!=37 && pdgId!=1000039){
268  tmp = "anti_"+name;
269  edm::LogInfo("SimG4CoreCustomPhysics")
270  <<"CustomParticleFactory: Calling addCustomParticle for antiparticle with pdgId: "
271  << -pdgId << ", mass " << mass << ", name " << tmp;
272  addCustomParticle(-pdgId, mass, tmp);
273  theParticleTable->FindParticle(pdgId)->SetAntiPDGEncoding(-pdgId);
274  }
275  else theParticleTable->FindParticle(pdgId)->SetAntiPDGEncoding(pdgId);
276  }
277 
278  if(pdgId==1000039) theParticleTable->FindParticle(pdgId)->SetAntiPDGEncoding(pdgId); // gravitino
279  if(pdgId==1000024 || pdgId==1000037 || pdgId==37) {
280  tmp = "anti_"+name;
281  edm::LogInfo("SimG4CoreCustomPhysics")
282  <<"CustomParticleFactory: Calling addCustomParticle for antiparticle (2) with pdgId: "
283  << -pdgId << ", mass " << mass << ", name " << tmp;
284  addCustomParticle(-pdgId, mass, tmp);
285  theParticleTable->FindParticle(pdgId)->SetAntiPDGEncoding(-pdgId);
286  }
287  }
288 }
289 
290 G4DecayTable* CustomParticleFactory::getDecayTable(std::ifstream *configFile, int pdgId) {
291 
292  double br;
293  int nDaughters;
294  std::vector<int> pdg(4);
296  std::vector<std::string> name(4);
297 
298  G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
299 
300  std::string parentName = theParticleTable->FindParticle(pdgId)->GetParticleName();
301  G4DecayTable *decaytable= new G4DecayTable();
302 
303  while(getline(*configFile,line)) {
304 
305  line.erase(0, line.find_first_not_of(" \t")); // remove leading whitespace
306  if (line.length()==0) continue; // skip blank lines
307  if (line.at(0) == '#' &&
308  ToLower(line).find("br") < line.npos &&
309  ToLower(line).find("nda") < line.npos) continue; // skip a comment of the form: # BR NDA ID1 ID2
310  if (line.at(0) == '#') { // other comments signal the end of the decay block
311  edm::LogInfo("SimG4CoreCustomPhysics") <<"CustomParticleFactory: Finished the Decay Table ";
312  break;
313  }
314 
315  pdg.clear();
316  name.clear();
317 
318  std::stringstream sstr(line);
319  sstr >> br >> nDaughters; // assume SLHA format, e.g.: 1.49435135E-01 2 -15 16 # BR(H+ -> tau+ nu_tau)
320  edm::LogInfo("SimG4CoreCustomPhysics")
321  <<"CustomParticleFactory: Branching Ratio: " << br << ", Number of Daughters: " << nDaughters;
322  if (nDaughters > 4) {
323  edm::LogError("SimG4CoreCustomPhysics")
324  <<"CustomParticleFactory: Number of daughters is too large (max = 4): " << nDaughters
325  << " for pdgId: " << pdgId;
326  break;
327  }
328  for(int i=0; i<nDaughters; i++) {
329  sstr >> pdg[i];
330  edm::LogInfo("SimG4CoreCustomPhysics") <<"CustomParticleFactory: Daughter ID " << pdg[i];
331  const G4ParticleDefinition* part = theParticleTable->FindParticle(pdg[i]);
332  if (!part) {
333  edm::LogWarning("SimG4CoreCustomPhysics")
334  <<"CustomParticleFactory: particle with PDG code"<<pdg[i] <<" not found!";
335  continue;
336  }
337  name[i] = part->GetParticleName();
338  }
340  G4PhaseSpaceDecayChannel *aDecayChannel = new G4PhaseSpaceDecayChannel(parentName, br, nDaughters,
341  name[0],name[1],name[2],name[3]);
342  decaytable->Insert(aDecayChannel);
343  }
344  return decaytable;
345 }
346 
347 G4DecayTable* CustomParticleFactory::getAntiDecayTable(int pdgId, G4DecayTable *theDecayTable) {
348 
349  std::vector<std::string> name(4);
350  G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
351 
352  std::string parentName = theParticleTable->FindParticle(-pdgId)->GetParticleName();
353  G4DecayTable *decaytable= new G4DecayTable();
354 
355  for(int i=0;i<theDecayTable->entries();i++){
356  G4VDecayChannel *theDecayChannel = theDecayTable->GetDecayChannel(i);
357  int nd = std::min(4, theDecayChannel->GetNumberOfDaughters());
358  for(int j=0; j<nd; ++j){
359  int id = theDecayChannel->GetDaughter(j)->GetAntiPDGEncoding();
360  const G4ParticleDefinition* part = theParticleTable->FindParticle(id);
361  if (!part) {
362  edm::LogWarning("SimG4CoreCustomPhysics")
363  <<"CustomParticleFactory: antiparticle with PDG code"<<id <<" not found!";
364  continue;
365  }
366  name[j] = part->GetParticleName();
367  }
368  G4PhaseSpaceDecayChannel *aDecayChannel =
369  new G4PhaseSpaceDecayChannel(parentName,
370  theDecayChannel->GetBR(), nd,
371  name[0],name[1],name[2],name[3]);
372  decaytable->Insert(aDecayChannel);
373  }
374  return decaytable;
375 }
376 
378  std::locale loc;
379  for (std::string::size_type i=0; i<str.length(); ++i)
380  str.at(i) = std::tolower(str.at(i),loc);
381  return str;
382 }
383 
384 const std::vector<G4ParticleDefinition *>& CustomParticleFactory::GetCustomParticles()
385 {
386  return m_particles;
387 }
const double GeV
Definition: MathUtil.h:16
static bool s_isDphoton(int pdg)
static double s_charge(int pdg)
static const int stable
Definition: TopGenEvent.h:11
static bool s_isSbaryon(int pdg)
void SetCloud(G4ParticleDefinition *theCloud)
G4ParticleDefinition * GetCloud()
#define NULL
Definition: scimark2.h:8
uint16_t size_type
static void loadCustomParticles(const std::string &filePath)
static std::vector< G4ParticleDefinition * > m_particles
const double MeV
static bool s_isMesonino(int pdg)
static bool s_isSLepton(int pdg)
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
static std::string ToLower(std::string str)
void SetSpectator(G4ParticleDefinition *theSpectator)
T min(T a, T b)
Definition: MathUtil.h:58
static double s_spin(int pdg)
G4ParticleDefinition * GetSpectator()
static void getMassTable(std::ifstream *configFile)
static G4DecayTable * getDecayTable(std::ifstream *configFile, int pdgId)
static void addCustomParticle(int pdgCode, double mass, const std::string &name)
part
Definition: HCALResponse.h:20
static G4DecayTable * getAntiDecayTable(int pdgId, G4DecayTable *theDecayTable)
static bool s_isRHadron(int pdg)
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
static const std::vector< G4ParticleDefinition * > & GetCustomParticles()
static bool s_issbottomHadron(int pdg)
static bool s_isstopHadron(int pdg)
float spin(float ph)