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