Belle II Software  release-06-02-00
ParticleCombinerFromMCModule.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 // Own include
10 #include <analysis/modules/ParticleCombinerFromMC/ParticleCombinerFromMCModule.h>
11 
12 // framework aux
13 #include <framework/logging/Logger.h>
14 
15 // decay descriptor
16 #include <analysis/DecayDescriptor/DecayDescriptorParticle.h>
17 
18 // utilities
19 #include <analysis/DecayDescriptor/ParticleListName.h>
20 #include <analysis/utility/MCMatching.h>
21 
22 #include <memory>
23 
24 using namespace std;
25 
26 namespace Belle2 {
32 //-----------------------------------------------------------------
33 // Register module
34 //-----------------------------------------------------------------
35 
36  REG_MODULE(ParticleCombinerFromMC)
37 
38 //-----------------------------------------------------------------
39 // Implementation
40 //-----------------------------------------------------------------
41 
43  Module()
44 
45  {
46  // set module description (e.g. insert text)
47  setDescription("Makes particle combinations");
48  setPropertyFlags(c_ParallelProcessingCertified);
49 
50  // Add parameters
51  addParam("decayString", m_decayString,
52  "Input DecayDescriptor string (see :ref:`DecayString`).");
53  addParam("cut", m_cutParameter, "Selection criteria to be applied", std::string(""));
54  addParam("decayMode", m_decayModeID, "User-specified decay mode identifier (saved in 'decayModeID' extra-info for each Particle)",
55  0);
56 
57  addParam("writeOut", m_writeOut,
58  "If true, the output ParticleList will be saved by RootOutput. If false, it will be ignored when writing the file.", false);
59  addParam("chargeConjugation", m_chargeConjugation,
60  "If true, the charge-conjugated mode will be reconstructed as well", true);
61 
62  // initializing the rest of private members
63  m_generator = nullptr;
64  m_cut = nullptr;
65  }
66 
67  void ParticleCombinerFromMCModule::initialize()
68  {
69  // obtain the input and output particle lists from the decay string
70  bool valid = m_decaydescriptor.init(m_decayString);
71  if (!valid)
72  B2ERROR("Invalid input DecayString: " << m_decayString);
73 
74  // Mother particle
75  const DecayDescriptorParticle* mother = m_decaydescriptor.getMother();
76 
77  m_listName = mother->getFullName();
78 
79  m_cut = Variable::Cut::compile(m_cutParameter);
80 
81  // register particles which have (sub-)decay recursively
82  registerParticleRecursively(m_decaydescriptor);
83 
84  }
85 
86  void ParticleCombinerFromMCModule::event()
87  {
88  B2DEBUG(10, "event() started !!!");
89 
90  // combine particles recursively
91  combineRecursively(m_decaydescriptor);
92 
93  StoreObjPtr<ParticleList> plist(m_listName);
94  bool existingList = plist.isValid();
95 
96  if (!existingList) {
97  B2WARNING("Output list " << m_listName << " was not created");
98  return;
99  }
100 
101  // loop over list only if cuts should be applied
102  if (!m_cutParameter.empty()) {
103  std::vector<unsigned int> toRemove;
104  unsigned int n = plist->getListSize();
105  for (unsigned i = 0; i < n; i++) {
106  const Particle* part = plist->getParticle(i);
107 
108  MCMatching::setMCTruth(part);
109  MCMatching::getMCErrors(part);
110 
111  if (!m_cut->check(part)) toRemove.push_back(part->getArrayIndex());
112  }
113  plist->removeParticles(toRemove);
114  }
115  }
116 
117 
118  void ParticleCombinerFromMCModule::registerParticleRecursively(const DecayDescriptor& decaydescriptor)
119  {
120  int nProducts = decaydescriptor.getNDaughters();
121 
122  for (int i = 0; i < nProducts; ++i) {
123  if (decaydescriptor.getDaughter(i)->getNDaughters() == 0) {
124  // if daughter does not have daughters, it must be already registered
125  const DecayDescriptorParticle* daughter = decaydescriptor.getDaughter(i)->getMother();
126  StoreObjPtr<ParticleList>().isRequired(daughter->getFullName());
127  } else {
128  // if daughter has daughters, call the function recursively
129  registerParticleRecursively(*(decaydescriptor.getDaughter(i)));
130  }
131  }
132 
133  // Mother particle
134  const DecayDescriptorParticle* mother = decaydescriptor.getMother();
135  std::string listName = mother->getFullName();
136  StoreObjPtr<ParticleList> particleList(listName);
137 
138  // if particleList already exists
139  auto existList = std::find(m_vector_listName.begin(), m_vector_listName.end(), listName);
140  if (existList != m_vector_listName.end()) {
141  B2ERROR(listName << " already exist ! You cannot write same sub-decay twice !!!");
142  return;
143  }
144 
145  std::string antiListName = ParticleListName::antiParticleListName(listName);
146  bool isSelfConjugatedParticle = (listName == antiListName);
147 
148  DataStore::EStoreFlags flags = m_writeOut ? DataStore::c_WriteOut : DataStore::c_DontWriteOut;
149  particleList.registerInDataStore(flags);
150  if (!isSelfConjugatedParticle && m_chargeConjugation) {
151  StoreObjPtr<ParticleList> antiParticleList(antiListName);
152  antiParticleList.registerInDataStore(flags);
153  }
154 
155  m_vector_listName.push_back(listName);
156 
157  }
158 
159  void ParticleCombinerFromMCModule::combineRecursively(const DecayDescriptor& decaydescriptor)
160  {
161  // Mother particle
162  const DecayDescriptorParticle* mother = decaydescriptor.getMother();
163  int pdgCode = mother->getPDGCode();
164  std::string listName = mother->getFullName();
165  std::string antiListName = ParticleListName::antiParticleListName(listName);
166  bool isSelfConjugatedParticle = (listName == antiListName);
167 
168  StoreObjPtr<ParticleList> outputList(listName);
169  outputList.create();
170  outputList->initialize(pdgCode, listName);
171 
172  if (!isSelfConjugatedParticle && m_chargeConjugation) {
173  StoreObjPtr<ParticleList> outputAntiList(antiListName);
174  outputAntiList.create();
175  outputAntiList->initialize(-1 * pdgCode, antiListName);
176 
177  outputList->bindAntiParticleList(*(outputAntiList));
178  }
179 
180  unsigned int numberOfLists = decaydescriptor.getNDaughters();
181 
182  for (unsigned int i = 0; i < numberOfLists; ++i) {
183  const DecayDescriptor* dDaughter = decaydescriptor.getDaughter(i);
184 
185  if (dDaughter->getNDaughters() == 0) {
186  // if daughter does not have daughters, check if it is not reconstructed particle.
187  const DecayDescriptorParticle* daughter = decaydescriptor.getDaughter(i)->getMother();
188  StoreObjPtr<ParticleList> plist(daughter->getFullName());
189  // if daughter is not created, returns error
190  if (!plist.isValid())
191  B2ERROR(daughter->getFullName() << " is not created");
192  // if daughter contains reconstructed particles, returns error.
193  unsigned nPart = plist->getListSize();
194  for (unsigned iPart = 0; iPart < nPart; iPart++) {
195  const Particle* part = plist->getParticle(iPart);
196  Particle::EParticleSourceObject particleType = part->getParticleSource();
197  if (particleType == Particle::c_Track or
198  particleType == Particle::c_ECLCluster or
199  particleType == Particle::c_KLMCluster)
200  B2ERROR(daughter->getFullName() << " contains a reconstructed particle! It is not accepted in ParticleCombinerFromMCModule!");
201  }
202  // if not, do nothing.
203  } else {
204  // if daughter has daughter, call the function recursively
205  combineRecursively(*dDaughter);
206  }
207  }
208 
209  // initialize the generator
210  m_generator = std::make_unique<ParticleGenerator>(decaydescriptor, "");
211  m_generator->init();
212 
213  while (m_generator->loadNext(m_chargeConjugation)) {
214  Particle&& particle = m_generator->getCurrentParticle();
215 
216  Particle* newParticle = m_particles.appendNew(particle);
217  // append to the created particle the user specified decay mode ID
218  newParticle->addExtraInfo("decayModeID", m_decayModeID);
219 
220  int iparticle = m_particles.getEntries() - 1;
221  outputList->addParticle(iparticle, particle.getPDGCode(), particle.getFlavorType());
222  }
223 
224  // select only signal particles
225  std::unique_ptr<Variable::Cut> cutIsSignal = Variable::Cut::compile("isSignal");
226 
227  std::vector<unsigned int> toRemove;
228  unsigned int n = outputList->getListSize();
229  for (unsigned i = 0; i < n; i++) {
230  const Particle* part = outputList->getParticle(i);
231 
232  MCMatching::setMCTruth(part);
233  MCMatching::getMCErrors(part);
234 
235  if (!cutIsSignal->check(part)) toRemove.push_back(part->getArrayIndex());
236  }
237  outputList->removeParticles(toRemove);
238 
239  }
240 
242 } // end Belle2 namespace
243 
EStoreFlags
Flags describing behaviours of objects etc.
Definition: DataStore.h:69
Represents a particle in the DecayDescriptor.
The DecayDescriptor stores information about a decay tree or parts of a decay tree.
const DecayDescriptorParticle * getMother() const
return mother.
int getNDaughters() const
return number of direct daughters.
const DecayDescriptor * getDaughter(int i) const
return i-th daughter (0 based index).
Base class for Modules.
Definition: Module.h:72
Class to store reconstructed particles.
Definition: Particle.h:74
EParticleSourceObject
particle source enumerators
Definition: Particle.h:81
void addExtraInfo(const std::string &name, float value)
Sets the user-defined data of given name to the given value.
Definition: Particle.cc:1289
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
bool create(bool replace=false)
Create a default object in the data store.
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:95
bool isValid() const
Check whether the object was created.
Definition: StoreObjPtr.h:110
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
Abstract base class for different kinds of events.