CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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  G4DecayTable *decaytable = nullptr;
131  G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
132 
133  CustomParticle *particle = new CustomParticle(name, massGeV, width, charge, spin,
134  parity, conjugation, isospin, isospinZ,
135  gParity, pType, lepton, baryon, pdgCode,
136  stable, lifetime, decaytable);
137 
138  if(pType == "rhadron" && name!="~g"){
139  G4String cloudname = name+"cloud";
140  G4String cloudtype = pType+"cloud";
141  spectator = theParticleTable->FindParticle(1000021);
142  spectatormass = spectator->GetPDGMass();
143  G4double cloudmass = mass-spectatormass/GeV;
144  CustomParticle *tmpParticle = new CustomParticle(
145  cloudname, cloudmass * GeV , 0.0*MeV, 0 ,
146  0, +1, 0,
147  0, 0, 0,
148  cloudtype, 0, +1, 0,
149  true, -1.0, NULL );
150  particle->SetCloud(tmpParticle);
151  particle->SetSpectator(spectator);
152 
153  edm::LogInfo("SimG4CoreCustomPhysics")
154  <<"CustomParticleFactory: " <<name<<" being assigned "
155  <<particle->GetCloud()->GetParticleName()
156  <<" and "<<particle->GetSpectator()->GetParticleName() << "\n"
157  <<" Masses: "<<particle->GetPDGMass()/GeV<<" Gev, "
158  <<particle->GetCloud()->GetPDGMass()/GeV<<" GeV and "
159  <<particle->GetSpectator()->GetPDGMass()/GeV<<" GeV.";
160  } else if(pType == "mesonino" || pType == "sbaryon") {
161  int sign=1;
162  if(pdgCode < 0 ) sign=-1;
163 
164  G4String cloudname = name+"cloud";
165  G4String cloudtype = pType+"cloud";
166  if(CustomPDGParser::s_isstopHadron(pdgCode)) {
167  spectator = theParticleTable->FindParticle(1000006*sign);
168  }
169  else {
170  if (CustomPDGParser::s_issbottomHadron(pdgCode)) {
171  spectator = theParticleTable->FindParticle(1000005*sign);
172  } else {
173  spectator = nullptr;
174  edm::LogError("SimG4CoreCustomPhysics")<< "CustomParticleFactory: Cannot find spectator parton";
175  }
176  }
177  if(spectator) spectatormass = spectator->GetPDGMass();
178  G4double cloudmass = mass-spectatormass/GeV;
179  CustomParticle *tmpParticle = new CustomParticle(
180  cloudname, cloudmass * GeV , 0.0*MeV, 0 ,
181  0, +1, 0,
182  0, 0, 0,
183  cloudtype, 0, +1, 0,
184  true, -1.0, NULL );
185  particle->SetCloud(tmpParticle);
186  particle->SetSpectator(spectator);
187 
188  edm::LogInfo("SimG4CoreCustomPhysics")
189  <<"CustomParticleFactory: "<<name<<" being assigned "
190  <<particle->GetCloud()->GetParticleName()
191  <<" and "<<particle->GetSpectator()->GetParticleName() << "\n"
192  <<" Masses: "
193  <<particle->GetPDGMass()/GeV<<" Gev, "
194  <<particle->GetCloud()->GetPDGMass()/GeV<<" GeV and "
195  <<particle->GetSpectator()->GetPDGMass()/GeV<<" GeV.";
196  }
197  else{
198  particle->SetCloud(0);
199  particle->SetSpectator(0);
200  }
201  m_particles.insert(particle);
202 }
203 
205 
206  int pdgId;
207  double mass;
210  // This should be compatible IMO to SLHA
211  while (getline(*configFile,line)) {
212  line.erase(0, line.find_first_not_of(" \t")); // remove leading whitespace
213  if (line.length()==0 || line.at(0) == '#') continue; // skip blank lines and comments
214  if (ToLower(line).find("block") < line.npos) {
215  edm::LogInfo("SimG4CoreCustomPhysics")
216  <<"CustomParticleFactory: Finished the Mass Table ";
217  break;
218  }
219  std::stringstream sstr(line);
220  sstr >> pdgId >> mass >> tmp >> name; // Assume SLHA format, e.g.: 1000001 5.68441109E+02 # ~d_L
221 
222  edm::LogInfo("SimG4CoreCustomPhysics")
223  <<"CustomParticleFactory: Calling addCustomParticle for pdgId: " << pdgId
224  << ", mass " << mass << ", name " << name;
225  addCustomParticle(pdgId, fabs(mass), name);
227  int pdgIdPartner = pdgId%100;
228  G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
229  G4ParticleDefinition *aParticle = theParticleTable->FindParticle(pdgIdPartner);
230  //Add antiparticles for SUSY particles only, not for rHadrons.
231  edm::LogInfo("SimG4CoreCustomPhysics")
232  <<"CustomParticleFactory: Found aParticle = " << aParticle
233  << ", pdgId = " << pdgId
234  << ", pdgIdPartner = " << pdgIdPartner
235  << ", CustomPDGParser::s_isRHadron(pdgId) = " << CustomPDGParser::s_isRHadron(pdgId)
236  << ", CustomPDGParser::s_isstopHadron(pdgId) = " << CustomPDGParser::s_isstopHadron(pdgId);
237 
238  if (aParticle &&
239  !CustomPDGParser::s_isRHadron(pdgId) &&
240  !CustomPDGParser::s_isstopHadron(pdgId) &&
241  pdgId!=1000006 &&
242  pdgId!=-1000006 &&
243  pdgId!=25 &&
244  pdgId!=35 &&
245  pdgId!=36 &&
246  pdgId!=37){
247  int sign = aParticle->GetAntiPDGEncoding()/pdgIdPartner;
248  edm::LogInfo("SimG4CoreCustomPhysics")
249  <<"CustomParticleFactory: Found sign = " << sign
250  << ", aParticle->GetAntiPDGEncoding() " << aParticle->GetAntiPDGEncoding()
251  << ", pdgIdPartner = " << pdgIdPartner;
252  if(abs(sign)!=1) {
253  edm::LogInfo("SimG4CoreCustomPhysics")
254  <<"CustomParticleFactory: sgn= "<<sign<<" a "
255  <<aParticle->GetAntiPDGEncoding()<<" b "<<pdgIdPartner;
256  aParticle->DumpTable();
257  }
258  if(sign==-1 && pdgId!=25 && pdgId!=35 && pdgId!=36 && pdgId!=37 && pdgId!=1000039){
259  tmp = "anti_"+name;
260  edm::LogInfo("SimG4CoreCustomPhysics")
261  <<"CustomParticleFactory: Calling addCustomParticle for antiparticle with pdgId: "
262  << -pdgId << ", mass " << mass << ", name " << tmp;
263  addCustomParticle(-pdgId, mass, tmp);
264  theParticleTable->FindParticle(pdgId)->SetAntiPDGEncoding(-pdgId);
265  }
266  else theParticleTable->FindParticle(pdgId)->SetAntiPDGEncoding(pdgId);
267  }
268 
269  if(pdgId==1000039) theParticleTable->FindParticle(pdgId)->SetAntiPDGEncoding(pdgId); // gravitino
270  if(pdgId==1000024 || pdgId==1000037 || pdgId==37) {
271  tmp = "anti_"+name;
272  edm::LogInfo("SimG4CoreCustomPhysics")
273  <<"CustomParticleFactory: Calling addCustomParticle for antiparticle (2) with pdgId: "
274  << -pdgId << ", mass " << mass << ", name " << tmp;
275  addCustomParticle(-pdgId, mass, tmp);
276  theParticleTable->FindParticle(pdgId)->SetAntiPDGEncoding(-pdgId);
277  }
278  }
279 }
280 
281 G4DecayTable* CustomParticleFactory::getDecayTable(std::ifstream *configFile, int pdgId) {
282 
283  double br;
284  int nDaughters;
285  std::vector<int> pdg(4);
287  std::vector<std::string> name(4);
288 
289  G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
290 
291  std::string parentName = theParticleTable->FindParticle(pdgId)->GetParticleName();
292  G4DecayTable *decaytable= new G4DecayTable();
293 
294  while(getline(*configFile,line)) {
295 
296  line.erase(0, line.find_first_not_of(" \t")); // remove leading whitespace
297  if (line.length()==0) continue; // skip blank lines
298  if (line.at(0) == '#' &&
299  ToLower(line).find("br") < line.npos &&
300  ToLower(line).find("nda") < line.npos) continue; // skip a comment of the form: # BR NDA ID1 ID2
301  if (line.at(0) == '#') { // other comments signal the end of the decay block
302  edm::LogInfo("SimG4CoreCustomPhysics") <<"CustomParticleFactory: Finished the Decay Table ";
303  break;
304  }
305 
306  pdg.clear();
307  name.clear();
308 
309  std::stringstream sstr(line);
310  sstr >> br >> nDaughters; // assume SLHA format, e.g.: 1.49435135E-01 2 -15 16 # BR(H+ -> tau+ nu_tau)
311  edm::LogInfo("SimG4CoreCustomPhysics")
312  <<"CustomParticleFactory: Branching Ratio: " << br << ", Number of Daughters: " << nDaughters;
313  if (nDaughters > 4) {
314  edm::LogError("SimG4CoreCustomPhysics")
315  <<"CustomParticleFactory: Number of daughters is too large (max = 4): " << nDaughters
316  << " for pdgId: " << pdgId;
317  break;
318  }
319  for(int i=0; i<nDaughters; i++) {
320  sstr >> pdg[i];
321  edm::LogInfo("SimG4CoreCustomPhysics") <<"CustomParticleFactory: Daughter ID " << pdg[i];
322  const G4ParticleDefinition* part = theParticleTable->FindParticle(pdg[i]);
323  if (!part) {
324  edm::LogWarning("SimG4CoreCustomPhysics")
325  <<"CustomParticleFactory: particle with PDG code"<<pdg[i] <<" not found!";
326  continue;
327  }
328  name[i] = part->GetParticleName();
329  }
331  G4PhaseSpaceDecayChannel *aDecayChannel = new G4PhaseSpaceDecayChannel(parentName, br, nDaughters,
332  name[0],name[1],name[2],name[3]);
333  decaytable->Insert(aDecayChannel);
334  }
335  return decaytable;
336 }
337 
338 G4DecayTable* CustomParticleFactory::getAntiDecayTable(int pdgId, G4DecayTable *theDecayTable) {
339 
340  std::vector<std::string> name(4);
341  G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
342 
343  std::string parentName = theParticleTable->FindParticle(-pdgId)->GetParticleName();
344  G4DecayTable *decaytable= new G4DecayTable();
345 
346  for(int i=0;i<theDecayTable->entries();i++){
347  G4VDecayChannel *theDecayChannel = theDecayTable->GetDecayChannel(i);
348  int nd = std::min(4, theDecayChannel->GetNumberOfDaughters());
349  for(int j=0; j<nd; ++j){
350  int id = theDecayChannel->GetDaughter(j)->GetAntiPDGEncoding();
351  const G4ParticleDefinition* part = theParticleTable->FindParticle(id);
352  if (!part) {
353  edm::LogWarning("SimG4CoreCustomPhysics")
354  <<"CustomParticleFactory: antiparticle with PDG code"<<id <<" not found!";
355  continue;
356  }
357  name[i] = part->GetParticleName();
358  }
359  G4PhaseSpaceDecayChannel *aDecayChannel =
360  new G4PhaseSpaceDecayChannel(parentName,
361  theDecayChannel->GetBR(), nd,
362  name[0],name[1],name[2],name[3]);
363  decaytable->Insert(aDecayChannel);
364  }
365  return decaytable;
366 }
367 
369  std::locale loc;
370  for (std::string::size_type i=0; i<str.length(); ++i)
371  str.at(i) = std::tolower(str.at(i),loc);
372  return str;
373 }
374 
int i
Definition: DBlmapReader.cc:9
const double GeV
Definition: MathUtil.h:16
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)
double sign(double x)
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)