Belle II Software development
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
23using namespace Belle2;
24
26{
27 static bool instanceCreated = false;
28 if (!instanceCreated) {
29 // Necessary to avoid "Error in <TClass::LoadClassInfo>: no interpreter information for class..."
30 gInterpreter->Declare("#include <framework/particledb/EvtGenParticlePDG.h>");
31 // hope we are the first to create a TDatabasePDG instance (setting the instance pointer in the process)
32 auto instance = new EvtGenDatabasePDG();
33 // ok, now load the data
34 instance->ReadEvtGenTable();
35 instanceCreated = true;
36 if (instance != TDatabasePDG::Instance())
37 B2FATAL("EvtGenDatabasePDG created too late!");
38 }
39 // this cast should be safe as we stop execution above if we couldn't create the first instance ourselves
40 return static_cast<EvtGenDatabasePDG*>(TDatabasePDG::Instance());
41}
42
43EvtGenParticlePDG* EvtGenDatabasePDG::AddParticle(const char* name, const char* title, Double_t mass, Bool_t stable, Double_t width,
44 Double_t charge, const char* ParticleClass, Int_t PDGcode, Int_t Anti, Int_t TrackingCode,
45 Double_t Lifetime, Double_t Spin, Double_t maxWidth, Int_t pythiaID)
46{
47 //
48 // Particle definition normal constructor. If the particle is set to be
49 // stable, the decay width parameter does have no meaning and can be set to
50 // any value. The parameters granularity, LowerCutOff and HighCutOff are
51 // used for the construction of the mean free path look up tables. The
52 // granularity will be the number of logwise energy points for which the
53 // mean free path will be calculated.
54 //
55
56 TParticlePDG* old = GetParticle(PDGcode);
57
58 if (old) {
59 B2ERROR("EvtGenDatabasePDG::AddParticle: particle with PDGcode=" << PDGcode << " already defined");
60 return nullptr;
61 }
62
63 if (std::strpbrk(name, " \t\n\v\f\r")) {
64 B2ERROR("EvtGenDatabasePDG::AddParticle: invalid particle name '" << name << "'. Names may not contain Whitespace");
65 return nullptr;
66 }
67
68 auto* p = new EvtGenParticlePDG(name, title, mass, stable, width, charge, ParticleClass,
69 PDGcode, Anti, TrackingCode, Lifetime, Spin, maxWidth, pythiaID);
70
71 fParticleList->Add(p);
72 if (fPdgMap)
73 fPdgMap->Add((Long_t)PDGcode, (Long_t)p);
74
75 TParticleClassPDG* pclass = GetParticleClass(ParticleClass);
76
77 if (!pclass) {
78 pclass = new TParticleClassPDG(ParticleClass);
79 fListOfClasses->Add(pclass);
80 }
81
82 pclass->AddParticle(p);
83
84 return p;
85}
86
87void EvtGenDatabasePDG::ReadEvtGenTable(const char* filename)
88{
89 //ok, now load the data
90 std::string defaultFilename = FileSystem::findFile("data/framework/particledb/evt.pdl");
91 if (defaultFilename.empty())
92 B2FATAL("Cannot find the default particle database file (evt.pdl).");
93 if (!filename) {
94 filename = defaultFilename.c_str();
95 } else {
96 if (filename != defaultFilename) {
97 B2RESULT("Loading non-standard evt.pdl file '" << filename << "'");
98 }
99 }
100
101 // do we have lists already?
102 if (fParticleList == nullptr) {
103 //if not create them
104 fParticleList = new THashList;
105 fListOfClasses = new TObjArray;
106 } else {
107 //otherwise clear them
108 fParticleList->Delete();
109 fListOfClasses->Delete();
110 //and also reset the map from pdgcode to particle
111 delete fPdgMap;
112 fPdgMap = nullptr;
113 }
114 std::ifstream indec(filename);
115
116 char cmnd[100], xxxx[100], pname[100];
117 int stdhepid; //aka PDG code
118 double mass, pwidth, pmaxwidth;
119 int chg3, spin2;
120 double ctau;
121 int lundkc;
122
123 if (!indec) {
124 B2ERROR("EvtGenDatabasePDG::ReadEvtGenTable: Could not particle data file '" << filename << "'");
125 return;
126 }
127
128 std::map<int, TParticlePDG*> pdgToPartMap;
129 do {
130
131 char ch, ch1;
132
133 do {
134
135 indec.get(ch);
136 if (ch == '\n') indec.get(ch);
137 if (ch != '*') {
138 indec.putback(ch);
139 } else {
140 while (indec.get(ch1), ch1 != '\n');
141 }
142 } while (ch == '*');
143
144 indec >> cmnd;
145
146 if (strcmp(cmnd, "end")) {
147
148 if (!strcmp(cmnd, "add")) {
149
150 indec >> xxxx >> xxxx >> pname >> stdhepid;
151 indec >> mass >> pwidth >> pmaxwidth >> chg3 >> spin2 >> ctau >> lundkc;
152
153 const double c_mm_per_s = Const::speedOfLight / (Unit::mm / Unit::s);
154 TParticlePDG* part = AddParticle(pname, pname, mass, false, pwidth, chg3, "Unknown", stdhepid, 0, 0,
155 ctau / c_mm_per_s, spin2 / 2.0, pmaxwidth, lundkc);
156 pdgToPartMap[stdhepid] = part;
157 if (!part) {
158 B2FATAL("EvtGenDatabasePDG::ReadPDGTable: Problem creating particle '" << pname << "'");
159 }
160 }
161 }
162 } while (strcmp(cmnd, "end"));
163
164 //fix up particle <-> antiparticle settings
165 for (auto entry : pdgToPartMap) {
166 int pdg = entry.first;
167 TParticlePDG* part = entry.second;
168
169 const auto& antiPartIter = pdgToPartMap.find(-pdg);
170 if (antiPartIter != pdgToPartMap.end()) {
171 //set anti-particle
172 part->SetAntiParticle(antiPartIter->second);
173 } else {
174 //we are our own antiparticle
175 part->SetAntiParticle(part);
176 }
177 }
178}
179
181{
182 const double c_mm_per_s = Const::speedOfLight / (Unit::mm / Unit::s);
183 if (fParticleList) {
184 for (TObject* object : *fParticleList) {
185 auto* part = dynamic_cast<EvtGenParticlePDG*>(object);
186 if (!part) {
187 B2FATAL("EvtGenDatabasePDG::WriteEvtgenTable: Particle "
188 << object->GetName() <<
189 " does not inherit from EventGenParticlePDG");
190 }
191 out << "add p Particle " << part->GetName() << " " << part->PdgCode()
192 << " " << std::scientific << std::setprecision(7) << part->Mass()
193 << " " << std::scientific << std::setprecision(7) << part->Width()
194 << " " << std::scientific << std::setprecision(7) << part->MaxWidth()
195 << " " << (int)(part->Charge())
196 << " " << (int)(part->Spin() * 2)
197 << " " << std::scientific << std::setprecision(7) << part->Lifetime() * c_mm_per_s
198 << " " << part->PythiaID()
199 << std::endl;
200 }
201 }
202 out << "end" << std::endl << std::flush;
203}
204
205void EvtGenDatabasePDG::WriteEvtGenTable(const char* filename)
206{
207 std::ofstream out(filename);
208 if (!out) {
209 B2FATAL("Cannot write evtgen pdl to '" << filename << "'");
210 }
211 WriteEvtGenTable(out);
212}
213
215{
216 if (!fParticleList)
217 return true;
218 bool testPassed = true;
219 for (TObject* object : *fParticleList) {
220 EvtGenParticlePDG* particle = dynamic_cast<EvtGenParticlePDG*>(object);
221 if (!particle) {
222 B2FATAL("EvtGenDatabasePDG::testParticleData: Particle"
223 << object->GetName() <<
224 " does not inherit from EventGenParticlePDG.");
225 }
226 /*
227 * Check width and mass range. The mass range in EvtGen is
228 * [M - max_Dm, M + 15 * Gamma]. Thus, max_Dm values are required to
229 * be less than or equal to 15 * Gamma, except for zero width. Zero width
230 * and non-zero max_Dm is a valid case for some special particles like
231 * quark pairs.
232 */
233 if ((particle->MaxWidth() > 15.000000000001 * particle->Width()) &&
234 (particle->Width() != 0)) {
235 B2ERROR("Maximum Delta_M is greater than 15 widths for "
236 << particle->GetName()
237 << LogVar("Width", particle->Width())
238 << LogVar("max_Dm", particle->MaxWidth()));
239 testPassed = false;
240 }
241 }
242 return testPassed;
243}
static const double speedOfLight
[cm/ns]
Definition Const.h:695
static EvtGenDatabasePDG * Instance()
Instance method that loads the EvtGen table.
void WriteEvtGenTable(std::ostream &out)
Write current database as EvtGen table to a stream.
bool testParticleData()
Test particle data.
void ReadEvtGenTable(const char *filename=nullptr)
Read 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
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...
static const double mm
[millimeters]
Definition Unit.h:70
static const double s
[second]
Definition Unit.h:95
Class to store variables with their name which were sent to the logging service.
Abstract base class for different kinds of events.