Belle II Software release-09-00-04
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 // 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
44EvtGenParticlePDG* 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
88void 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
182{
183 const double c_mm_per_s = Const::speedOfLight / (Unit::mm / Unit::s);
184 if (fParticleList) {
185 for (TObject* object : *fParticleList) {
186 auto* part = dynamic_cast<EvtGenParticlePDG*>(object);
187 if (!part) {
188 B2FATAL("EvtGenDatabasePDG::WriteEvtgenTable: Particle "
189 << object->GetName() <<
190 " does not inherit from EventGenParticlePDG");
191 }
192 out << "add p Particle " << part->GetName() << " " << part->PdgCode()
193 << " " << std::scientific << std::setprecision(7) << part->Mass()
194 << " " << std::scientific << std::setprecision(7) << part->Width()
195 << " " << std::scientific << std::setprecision(7) << part->MaxWidth()
196 << " " << (int)(part->Charge())
197 << " " << (int)(part->Spin() * 2)
198 << " " << std::scientific << std::setprecision(7) << part->Lifetime() * c_mm_per_s
199 << " " << part->PythiaID()
200 << std::endl;
201 }
202 }
203 out << "end" << std::endl << std::flush;
204}
205
206void EvtGenDatabasePDG::WriteEvtGenTable(const char* filename)
207{
208 std::ofstream out(filename);
209 if (!out) {
210 B2FATAL("Cannot write evtgen pdl to '" << filename << "'");
211 }
212 WriteEvtGenTable(out);
213}
214
216{
217 if (!fParticleList)
218 return true;
219 bool testPassed = true;
220 for (TObject* object : *fParticleList) {
221 EvtGenParticlePDG* particle = dynamic_cast<EvtGenParticlePDG*>(object);
222 if (!particle) {
223 B2FATAL("EvtGenDatabasePDG::testParticleData: Particle"
224 << object->GetName() <<
225 " does not inherit from EventGenParticlePDG.");
226 }
227 /*
228 * Check width and mass range. The mass range in EvtGen is
229 * [M - max_Dm, M + 15 * Gamma]. Thus, max_Dm values are required to
230 * be less than or equal to 15 * Gamma, except for zero width. Zero width
231 * and non-zero max_Dm is a valid case for some special particles like
232 * quark pairs.
233 */
234 if ((particle->MaxWidth() > 15.000000000001 * particle->Width()) &&
235 (particle->Width() != 0)) {
236 B2ERROR("Maximum Delta_M is greater than 15 widths for "
237 << particle->GetName()
238 << LogVar("Width", particle->Width())
239 << LogVar("max_Dm", particle->MaxWidth()));
240 testPassed = false;
241 }
242 }
243 return testPassed;
244}
static const double speedOfLight
[cm/ns]
Definition: Const.h:695
Replacement for TDatabasePDG that is filled from EvtGen's evt.pdl.
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...
Definition: FileSystem.cc:151
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.