Belle II Software  light-2212-foldex
PrintMCParticlesModule.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 <analysis/modules/PrintMCParticles/PrintMCParticlesModule.h>
10 #include <analysis/dataobjects/StringWrapper.h>
11 
12 #include <mdst/dataobjects/MCParticle.h>
13 
14 #include <framework/geometry/B2Vector3.h>
15 
16 #include <framework/logging/LogConnectionConsole.h>
17 
18 #include <boost/format.hpp>
19 #include <boost/algorithm/string.hpp>
20 
21 #include <TDatabasePDG.h>
22 #include <Math/Vector3D.h>
23 
24 using namespace Belle2;
25 
26 //-----------------------------------------------------------------
27 // Register the Module
28 //-----------------------------------------------------------------
29 REG_MODULE(PrintMCParticles);
30 
31 //-----------------------------------------------------------------
32 // Implementation
33 //-----------------------------------------------------------------
34 
35 namespace {
37  std::string statusToString(const MCParticle& mc)
38  {
39  static std::map<int, std::string> names {
40  {MCParticle::c_PrimaryParticle, "PrimaryParticle"},
41  {MCParticle::c_StableInGenerator, "StableInGenerator"},
42  {MCParticle::c_LeftDetector, "LeftDetector"},
43  {MCParticle::c_StoppedInDetector, "StoppedInDetector"},
44  {MCParticle::c_IsVirtual, "IsVirtual"},
45  {MCParticle::c_Initial, "Initial"},
46  {MCParticle::c_IsISRPhoton, "IsISRPhoton"},
47  {MCParticle::c_IsFSRPhoton, "IsFSRPhoton"},
48  {MCParticle::c_IsPHOTOSPhoton, "IsPHOTOSPhoton"},
49  };
50  std::vector<std::string> set;
51  for (auto&& [status, name] : names) {
52  if (mc.hasStatus(status)) set.emplace_back(name);
53  }
54  return boost::join(set, ", ");
55  }
56 
58  std::string g4ProcessToName(int process)
59  {
60  // Just copy all the values from the enums given by MCParticle.h documentation ...
61  // This was made from the externals version v01-09-01 so we might
62  static std::map<int, std::string> translation{
63  {1, "CoulombScattering"},
64  {2, "Ionisation"},
65  {3, "Bremsstrahlung"},
66  {4, "PairProdByCharged"},
67  {5, "Annihilation"},
68  {6, "AnnihilationToMuMu"},
69  {7, "AnnihilationToHadrons"},
70  {8, "NuclearStopping"},
71  {9, "ElectronGeneralProcess"},
72  {10, "MultipleScattering"},
73  {11, "Rayleigh"},
74  {12, "PhotoElectricEffect"},
75  {13, "ComptonScattering"},
76  {14, "GammaConversion"},
77  {15, "GammaConversionToMuMu"},
78  {16, "GammaGeneralProcess"},
79  {21, "Cerenkov"},
80  {22, "Scintillation"},
81  {23, "SynchrotronRadiation"},
82  {24, "TransitionRadiation"},
83  {111, "HadronElastic"},
84  {121, "HadronInelastic"},
85  {131, "Capture"},
86  {132, "MuAtomicCapture"},
87  {141, "Fission"},
88  {151, "HadronAtRest"},
89  {152, "LeptonAtRest"},
90  {161, "ChargeExchange"},
91  {210, "RadioactiveDecay"},
92  {201, "Decay"},
93  {202, "Decay_WithSpin"},
94  {203, "Decay_PionMakeSpin"},
95  {210, "Decay_Radioactive"},
96  {211, "Decay_Unknown"},
97  {221, "Decay_MuAtom "},
98  {231, "Decay_External"},
99  };
100  if (auto it = translation.find(process); it != translation.end()) {
101  return it->second;
102  }
103  return "[Unknown process]";
104  }
105 }
106 
108 {
109  //Set module properties
110  setDescription("Print an MCParticle List");
111 
112  //Parameter definition
113  addParam("storeName", m_particleList, "Name of the StoreArray to print", m_particleList);
114  addParam("onlyPrimaries", m_onlyPrimaries, "Show only primary particles", true);
115  addParam("maxLevel", m_maxLevel, "Show only up to specified depth level, -1 means no limit", -1);
116  addParam("showVertices", m_showVertices, "Show also the particle production vertices and times", false);
117  addParam("showMomenta", m_showMomenta, "Show also the particle momenta", false);
118  addParam("showProperties", m_showProperties, "Show the basic particle properties", false);
119  addParam("showStatus", m_showStatus, "Show extendend status information of the particle", false);
120  addParam("suppressPrint", m_suppressPrint, "Suppress print the information", false);
121 }
122 
124 {
125  m_mcparticles.isRequired(m_particleList);
126  m_stringWrapper.registerInDataStore("MCDecayString");
127 }
128 
130 {
131  // clear any previous outputs
132  m_output.str(std::string());
133 
134  if (not m_particleList.empty()) {
135  m_output << "Content from MCParticle list '" << m_mcparticles.getName() << "'" << std::endl;
136  } else {
137  m_output << "Content of MCParticle list" << std::endl;
138  }
139 
140  //Loop over the top level particles (no mother particle exists)
141  std::vector<MCParticle*> first_gen;
142  for (MCParticle& mc : m_mcparticles) {
143  if (mc.getMother() != nullptr) continue;
144  first_gen.emplace_back(&mc);
145  }
146  filterPrimaryOnly(first_gen);
147  printTree(first_gen);
148 
149  if (!m_suppressPrint)
150  B2INFO(m_output.str());
151 
152  if (not m_stringWrapper.isValid())
153  m_stringWrapper.create();
154 
155  m_stringWrapper->setString(std::string(m_output.str()));
156 }
157 
158 void PrintMCParticlesModule::filterPrimaryOnly(std::vector<MCParticle*>& particles) const
159 {
160  if (!m_onlyPrimaries or particles.empty()) return;
161  particles.erase(std::remove_if(particles.begin(), particles.end(), [](MCParticle * mc) {
162  return not mc->hasStatus(MCParticle::c_PrimaryParticle);
163  }), particles.end());
164 }
165 
166 void PrintMCParticlesModule::printTree(const std::vector<MCParticle*>& particles, int level, const std::string& indent)
167 {
168  //If we show extra content make the particle name and pdg code bold if supported
169  //And if we also show secondaries make those red to distinguish
170  const bool useColor = LogConnectionConsole::terminalSupportsColors(STDOUT_FILENO);
171  const bool anyExtraInfo = m_showProperties or m_showMomenta or m_showVertices or m_showStatus;
172  std::string colorStart[] = {"", ""};
173  std::string colorEnd = "";
174  if (useColor) {
175  // make it bold if we have extra info, otherwise no need
176  colorStart[0] = anyExtraInfo ? "\x1b[31;1m" : "\x1b[31m";
177  colorStart[1] = anyExtraInfo ? "\x1b[1m" : "";
178  colorEnd = "\x1b[m";
179  }
180 
181  TDatabasePDG* pdb = TDatabasePDG::Instance();
182 
183  // ok, go over all particles and print them
184  const auto num_particles = particles.size();
185  size_t particle_index{0};
186  for (const auto* mc : particles) {
187  // are we the last in the list? if so we need a different box char
188  const bool last = ++particle_index == num_particles;
189  m_output << indent << (last ? "╰" : "├");
190  m_output << (mc->hasStatus(MCParticle::c_PrimaryParticle) ? "── " : "╶╶ ");
191  // now print the name and pdg code. Optionally with color
192  TParticlePDG* pdef = pdb->GetParticle(mc->getPDG());
193  m_output << colorStart[mc->hasStatus(MCParticle::c_PrimaryParticle)] << (pdef ? pdef->GetTitle() : "[UNKNOWN]");
194  m_output << " (" << mc->getPDG() << ")" << colorEnd;
195 
196  // Particle itself is done but we might need to show more things like properties and daughters so ...
197  auto daughters = mc->getDaughters();
198  filterPrimaryOnly(daughters);
199  const bool showDaughters = (not daughters.empty()) and (m_maxLevel <= 0 or level < m_maxLevel);
200 
201  // new indent level for any information related to this particle.
202  const std::string newIndent = indent + (last ? " " : "│") + " ";
203  // and the indent level for any properties associated to this particle
204  const std::string propIndent = "\n" + newIndent + (showDaughters ? "│ " : "");
205  // limited by level restriction? add an indicator that something is skipped
206  if ((not showDaughters) and (not daughters.empty())) {
207  m_output << " → …";
208  }
209  // Now show whatever the user wants
210  if (m_showProperties) {
211  m_output << propIndent;
212  m_output << boost::format("mass=%.3g energy=%.3g charge=%d") % mc->getMass() % mc->getEnergy() % mc->getCharge();
213  if (not mc->hasStatus(MCParticle::c_LeftDetector)) m_output << boost::format(" lifetime=%.3g") % mc->getLifetime();
214  }
215  if (m_showMomenta) {
216  const B2Vector3F& p = mc->getMomentum();
217  m_output << propIndent;
218  m_output << boost::format("p=(%.3g, %.3g, %.3g) |p|=%.3g") % p.X() % p.Y() % p.Z() % p.Mag();
219  }
220  if (m_showVertices) {
221  const ROOT::Math::XYZVector& v = mc->getVertex();
222  m_output << propIndent;
223  m_output << boost::format("production vertex=(%.3g, %.3g, %.3g), time=%.3g") % v.X() % v.Y() % v.Z() % mc->getProductionTime();
224  }
225  if (m_showStatus) {
226  m_output << propIndent;
227  m_output << "status flags=" << statusToString(*mc);
228  if (not mc->hasStatus(MCParticle::c_PrimaryParticle)) {
229  m_output << propIndent;
230  m_output << "creation process=" << g4ProcessToName(mc->getSecondaryPhysicsProcess());
231  }
232  m_output << propIndent;
233  m_output << "list index=" << mc->getIndex();
234  }
235  // and if we have shown any extra info and have daughters leave a blank line
236  if (showDaughters and anyExtraInfo) m_output << propIndent;
237  // now we're done with the particle ...
238  m_output << std::endl;
239  // but maybe we need to show the daughters
240  if (showDaughters) {
241  printTree(daughters, level + 1, newIndent);
242  }
243  // and if we show any extra info also leave blank line to sibling
244  if (anyExtraInfo and not last) m_output << newIndent << std::endl;
245  }
246 }
static bool terminalSupportsColors(int fileDescriptor)
Returns true if the given file descriptor is a tty and supports colors.
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
@ c_IsFSRPhoton
bit 7: Particle is from finial state radiation
Definition: MCParticle.h:61
@ c_Initial
bit 5: Particle is initial such as e+ or e- and not going to Geant4
Definition: MCParticle.h:57
@ c_IsPHOTOSPhoton
bit 8: Particle is an radiative photon from PHOTOS
Definition: MCParticle.h:63
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition: MCParticle.h:47
@ c_LeftDetector
bit 2: Particle left the detector (the simulation volume).
Definition: MCParticle.h:51
@ c_IsVirtual
bit 4: Particle is virtual and not going to Geant4.
Definition: MCParticle.h:55
@ c_StableInGenerator
bit 1: Particle is stable, i.e., not decaying in the generator.
Definition: MCParticle.h:49
@ c_StoppedInDetector
bit 3: Particle was stopped in the detector (the simulation volume).
Definition: MCParticle.h:53
@ c_IsISRPhoton
bit 6: Particle is from initial state radiation
Definition: MCParticle.h:59
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
std::stringstream m_output
Buffer to keep all the output while building the tree.
virtual void initialize() override
init.
bool m_showProperties
Show remaining properties.
virtual void event() override
Method is called for each event.
StoreArray< MCParticle > m_mcparticles
store array for the MCParticles
bool m_showStatus
Show extended status information.
int m_maxLevel
Show only up to specified depth level.
bool m_showVertices
Show particle production vertices.
void filterPrimaryOnly(std::vector< MCParticle * > &particles) const
if m_onlyPrimary is set remove all non primary particles from the given vector inplace
StoreObjPtr< StringWrapper > m_stringWrapper
string wrapper to store the MCDecayString
void printTree(const std::vector< MCParticle * > &particles, int level=1, const std::string &indent="")
Loops recursively over the MCParticle list and prints information about each particle.
bool m_showMomenta
Show particle momenta.
std::string m_particleList
The name of the MCParticle collection.
bool m_suppressPrint
Suppress print the information.
bool m_onlyPrimaries
Print only primary particles.
REG_MODULE(B2BIIConvertBeamParams)
Register the module.
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
Abstract base class for different kinds of events.
Definition: ClusterUtils.h:23