Belle II Software  release-08-01-10
EvtGenDatabasePDG.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <framework/particledb/EvtGenDatabasePDG.h>
10 #include <framework/particledb/EvtGenParticlePDG.h>
11 #include <framework/logging/Logger.h>
12 #include <framework/gearbox/Unit.h>
13 #include <framework/gearbox/Const.h>
14 #include <framework/utilities/FileSystem.h>
15 #include <fstream>
16 #include <iomanip>
17 #include <cstring>
18 #include <string>
19 #include <THashList.h>
20 #include <TExMap.h>
21 #include <TInterpreter.h>
22 
23 using namespace Belle2;
24 
26 {
27  static bool instanceCreated = false;
28  if (!instanceCreated) {
29  // problem with 6.14: ROOT cannot find includes this early. Fix promised for 6.16.
30  // (https://root-forum.cern.ch/t/problem-with-loadclassinfo-for-class-instantiated-very-early/30831)
31  gInterpreter->Declare("#include <framework/particledb/EvtGenParticlePDG.h>");
32  //hope we are the first to create a TDatabasePDG instance (setting the instance pointer in the process)
33  auto instance = new EvtGenDatabasePDG();
34  //ok, now load the data
35  instance->ReadEvtGenTable();
36  instanceCreated = true;
37  if (instance != TDatabasePDG::Instance())
38  B2FATAL("EvtGenDatabasePDG created too late!");
39  }
40  //this cast should be safe as we stop execution above if we couldn't create the first instance ourselves
41  return static_cast<EvtGenDatabasePDG*>(TDatabasePDG::Instance());
42 }
43 
44 EvtGenParticlePDG* EvtGenDatabasePDG::AddParticle(const char* name, const char* title, Double_t mass, Bool_t stable, Double_t width,
45  Double_t charge, const char* ParticleClass, Int_t PDGcode, Int_t Anti, Int_t TrackingCode,
46  Double_t Lifetime, Double_t Spin, Double_t maxWidth, Int_t pythiaID)
47 {
48  //
49  // Particle definition normal constructor. If the particle is set to be
50  // stable, the decay width parameter does have no meaning and can be set to
51  // any value. The parameters granularity, LowerCutOff and HighCutOff are
52  // used for the construction of the mean free path look up tables. The
53  // granularity will be the number of logwise energy points for which the
54  // mean free path will be calculated.
55  //
56 
57  TParticlePDG* old = GetParticle(PDGcode);
58 
59  if (old) {
60  B2ERROR("EvtGenDatabasePDG::AddParticle: particle with PDGcode=" << PDGcode << " already defined");
61  return nullptr;
62  }
63 
64  if (std::strpbrk(name, " \t\n\v\f\r")) {
65  B2ERROR("EvtGenDatabasePDG::AddParticle: invalid particle name '" << name << "'. Names may not contain Whitespace");
66  return nullptr;
67  }
68 
69  auto* p = new EvtGenParticlePDG(name, title, mass, stable, width, charge, ParticleClass,
70  PDGcode, Anti, TrackingCode, Lifetime, Spin, maxWidth, pythiaID);
71 
72  fParticleList->Add(p);
73  if (fPdgMap)
74  fPdgMap->Add((Long_t)PDGcode, (Long_t)p);
75 
76  TParticleClassPDG* pclass = GetParticleClass(ParticleClass);
77 
78  if (!pclass) {
79  pclass = new TParticleClassPDG(ParticleClass);
80  fListOfClasses->Add(pclass);
81  }
82 
83  pclass->AddParticle(p);
84 
85  return p;
86 }
87 
88 void EvtGenDatabasePDG::ReadEvtGenTable(const char* filename)
89 {
90  //ok, now load the data
91  std::string defaultFilename = FileSystem::findFile("data/framework/particledb/evt.pdl");
92  if (defaultFilename.empty())
93  B2FATAL("Cannot find the default particle database file (evt.pdl).");
94  if (!filename) {
95  filename = defaultFilename.c_str();
96  } else {
97  if (filename != defaultFilename) {
98  B2RESULT("Loading non-standard evt.pdl file '" << filename << "'");
99  }
100  }
101 
102  // do we have lists already?
103  if (fParticleList == nullptr) {
104  //if not create them
105  fParticleList = new THashList;
106  fListOfClasses = new TObjArray;
107  } else {
108  //otherwise clear them
109  fParticleList->Delete();
110  fListOfClasses->Delete();
111  //and also reset the map from pdgcode to particle
112  delete fPdgMap;
113  fPdgMap = nullptr;
114  }
115  std::ifstream indec(filename);
116 
117  char cmnd[100], xxxx[100], pname[100];
118  int stdhepid; //aka PDG code
119  double mass, pwidth, pmaxwidth;
120  int chg3, spin2;
121  double ctau;
122  int lundkc;
123 
124  if (!indec) {
125  B2ERROR("EvtGenDatabasePDG::ReadEvtGenTable: Could not particle data file '" << filename << "'");
126  return;
127  }
128 
129  std::map<int, TParticlePDG*> pdgToPartMap;
130  do {
131 
132  char ch, ch1;
133 
134  do {
135 
136  indec.get(ch);
137  if (ch == '\n') indec.get(ch);
138  if (ch != '*') {
139  indec.putback(ch);
140  } else {
141  while (indec.get(ch1), ch1 != '\n');
142  }
143  } while (ch == '*');
144 
145  indec >> cmnd;
146 
147  if (strcmp(cmnd, "end")) {
148 
149  if (!strcmp(cmnd, "add")) {
150 
151  indec >> xxxx >> xxxx >> pname >> stdhepid;
152  indec >> mass >> pwidth >> pmaxwidth >> chg3 >> spin2 >> ctau >> lundkc;
153 
154  const double c_mm_per_s = Const::speedOfLight / (Unit::mm / Unit::s);
155  TParticlePDG* part = AddParticle(pname, pname, mass, false, pwidth, chg3, "Unknown", stdhepid, 0, 0,
156  ctau / c_mm_per_s, spin2 / 2.0, pmaxwidth, lundkc);
157  pdgToPartMap[stdhepid] = part;
158  if (!part) {
159  B2FATAL("EvtGenDatabasePDG::ReadPDGTable: Problem creating particle '" << pname << "'");
160  }
161  }
162  }
163  } while (strcmp(cmnd, "end"));
164 
165  //fix up particle <-> antiparticle settings
166  for (auto entry : pdgToPartMap) {
167  int pdg = entry.first;
168  TParticlePDG* part = entry.second;
169 
170  const auto& antiPartIter = pdgToPartMap.find(-pdg);
171  if (antiPartIter != pdgToPartMap.end()) {
172  //set anti-particle
173  part->SetAntiParticle(antiPartIter->second);
174  } else {
175  //we are our own antiparticle
176  part->SetAntiParticle(part);
177  }
178  }
179 }
180 
181 void EvtGenDatabasePDG::WriteEvtGenTable(std::ostream& out)
182 {
183  const double c_mm_per_s = Const::speedOfLight / (Unit::mm / Unit::s);
184  if (fParticleList) {
185  for (TObject* obj : *fParticleList) {
186  auto* part = dynamic_cast<EvtGenParticlePDG*>(obj);
187  if (!part) {
188  B2FATAL("EvtGenDatabasePDG::WriteEvtgenTable: Particle does not inherit from EventGenParticlePDG");
189  }
190  out << "add p Particle " << part->GetName() << " " << part->PdgCode()
191  << " " << std::scientific << std::setprecision(7) << part->Mass()
192  << " " << std::scientific << std::setprecision(7) << part->Width()
193  << " " << std::scientific << std::setprecision(7) << part->MaxWidth()
194  << " " << (int)(part->Charge())
195  << " " << (int)(part->Spin() * 2)
196  << " " << std::scientific << std::setprecision(7) << part->Lifetime() * c_mm_per_s
197  << " " << part->PythiaID()
198  << std::endl;
199  }
200  }
201  out << "end" << std::endl << std::flush;
202 }
203 
204 void EvtGenDatabasePDG::WriteEvtGenTable(const char* filename)
205 {
206  std::ofstream out(filename);
207  if (!out) {
208  B2FATAL("Cannot write evtgen pdl to '" << filename << "'");
209  }
210  WriteEvtGenTable(out);
211 }
static const double speedOfLight
[cm/ns]
Definition: Const.h:686
Replacement for TDatabasePDG that is filled from EvtGen's evt.pdl.
static EvtGenDatabasePDG * Instance()
Instance method that loads the EvtGen table.
TParticlePDG * AddParticle(const char *name, const char *title, Double_t mass, Bool_t stable, Double_t width, Double_t charge, const char *ParticleClass, Int_t PDGcode, Int_t Anti, Int_t TrackingCode) override
override old AddParticle
void WriteEvtGenTable(std::ostream &out)
Write current database as EvtGen table to a stream.
void ReadEvtGenTable(const char *filename=nullptr)
Read EvtGen table.
Helper class for setting additional TParticlePDG members and storing the ones it doesn't have yet.
static std::string findFile(const std::string &path, bool silent=false)
Search for given file or directory in local or central release directory, and return absolute path if...
Definition: FileSystem.cc:148
static const double mm
[millimeters]
Definition: Unit.h:70
static const double s
[second]
Definition: Unit.h:95
Abstract base class for different kinds of events.