Belle II Software  release-06-02-00
MCMatcherParticlesModule.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/MCMatcherParticles/MCMatcherParticlesModule.h>
10 
11 // utility
12 #include <analysis/utility/MCMatching.h>
13 #include <analysis/utility/AnalysisConfiguration.h>
14 
15 // map
16 #include <unordered_map>
17 #include <algorithm>
18 typedef std::unordered_map<unsigned int, unsigned int> CounterMap;
19 
20 using namespace std;
21 
22 namespace Belle2 {
28  //-----------------------------------------------------------------
29  // Register module
30  //-----------------------------------------------------------------
31 
32  REG_MODULE(MCMatcherParticles)
33 
34  //-----------------------------------------------------------------
35  // Implementation
36  //-----------------------------------------------------------------
37 
39  {
40  setDescription("Performs MC matching (sets relation Particle->MCParticle) for all particles\n"
41  "(and its (grand)^N-daughter particles) in the ParticleList. The relation can\n"
42  "be used in conjunction with MCMatching::MCErrorFlags flags, e.g. using the\n"
43  "isSignal or mcPDG & mcErrors variables.\n"
44  "\n"
45  "In addition to the usual mc matching algorithm the module can run also loose mc\n"
46  "matching. The difference between loose and normal mc matching algorithm is that\n"
47  "the loose algorithm will find the common mother of the majority of daughter\n"
48  "particles while the normal algorithm finds the common mother of all daughters.\n"
49  "The results of loose mc matching algorithm are stored to the following extraInfo\n"
50  "items:\n\n"
51  " - looseMCMotherPDG: PDG code of most common mother\n"
52  " - looseMCMotherIndex: 1-based StoreArray<MCParticle> index of most common mother\n"
53  " - looseMCWrongDaughterN: number of daughters that don't originate from the most\n"
54  " common mother\n"
55  " - looseMCWrongDaughterPDG: PDG code of the daughter that doesn't originate from\n"
56  " the most common mother \n"
57  " (only if looseMCWrongDaughterN = 1)\n"
58  " - looseMCWrongDaughterBiB: 1 if the wrong daughter is Beam Induced Background\n"
59  " Particle\n\n");
60 
61  setPropertyFlags(c_ParallelProcessingCertified);
62 
63  addParam("listName", m_listName, "Name of the input ParticleList.");
64  addParam("looseMCMatching", m_looseMatching, "Perform loose mc matching", false);
65  }
66 
67 
68  void MCMatcherParticlesModule::initialize()
69  {
70  // check that there are MCParticles: shout if not
71  if (!m_mcparticles.isValid()) {
72  B2WARNING("No MCParticles array found!"
73  << " This is obvously fine if you're analysing real data,"
74  << " but you have added the MCMatcher module to your path,"
75  << " did you mean to do this?");
76  return;
77  }
78 
79  // if we have MCParticles then continue with the initialisation
80  m_particles.isRequired();
81  m_particles.registerRelationTo(m_mcparticles);
82  m_plist.isRequired(m_listName);
83 
84  bool legacyAlgorithm = AnalysisConfiguration::instance()->useLegacyMCMatching();
85  B2INFO("MCMatcher module will search for Particle -> MCParticle associations for the ParticleList " << m_listName << ".");
86  if (legacyAlgorithm)
87  B2INFO(" - The MCMatcher will use legacy algorithm suitable for analysis of Belle MC or Belle II MC5.");
88  else
89  B2INFO(" - The MCMatcher will use default algorithm suitable for analysis of Belle II MC (for MC5 use legacy algorithm).");
90  }
91 
92 
93  void MCMatcherParticlesModule::event()
94  {
95  // if no MCParticles then silently skip
96  if (!m_mcparticles.isValid())
97  return;
98  if (!m_plist) {
99  B2ERROR("ParticleList " << m_listName << " not found");
100  return;
101  }
102 
103  const unsigned int n = m_plist->getListSize();
104  for (unsigned i = 0; i < n; i++) {
105  const Particle* part = m_plist->getParticle(i);
106 
107  MCMatching::setMCTruth(part);
108 
109  if (m_looseMatching)
110  setLooseMCMatch(part);
111  }
112  }
113 
114  void MCMatcherParticlesModule::setLooseMCMatch(const Particle* particle)
115  {
116  if (particle->hasExtraInfo("looseMCMotherPDG")) // nothing to do; already set
117  return;
118 
119  // get all FS daughters
120  vector<const Belle2::Particle*> fsDaughters = particle->getFinalStateDaughters();
121 
122  // map for counting how many times given mcparticle is mother of daughters
123  CounterMap motherCount;
124 
125  for (auto daughter : fsDaughters) {
126  const MCParticle* mcDaughter = daughter->getRelatedTo<MCParticle>();
127  if (!mcDaughter)
128  continue;
129 
130  vector<int> genMothers;
131  MCMatching::fillGenMothers(mcDaughter, genMothers);
132 
133  for (auto motherIndex : genMothers) {
134  // exclude ROOT particles: Upsilon(nS), virtual photon
135  int motherPDG = m_mcparticles[motherIndex - 1]->getPDG();
136  if ((motherPDG == 553) ||
137  (motherPDG == 100553) ||
138  (motherPDG == 200553) ||
139  (motherPDG == 300553) ||
140  (motherPDG == 9000553) ||
141  (motherPDG == 9010553) ||
142  (motherPDG == 10022))
143  continue;
144 
145  motherCount[motherIndex]++;
146  }
147  }
148 
149  // find first most common mother
150  auto commonMother = std::max_element
151  (
152  std::begin(motherCount), std::end(motherCount),
153  [](std::pair <unsigned int, unsigned int> p1, std::pair <unsigned int, unsigned int> p2) {
154  bool returnValue = false;
155  if (p1.second < p2.second)
156  returnValue = true;
157  else if (p1.second == p2.second)
158  returnValue = p2.first > p1.first;
159 
160  return returnValue;
161  }
162  );
163 
164  // No common mother found, all daughters have no associated MC Particle
165  if (commonMother == std::end(motherCount)) {
166  Particle* thisParticle = m_particles[particle->getArrayIndex()];
167  thisParticle->addExtraInfo("looseMCMotherPDG", -1);
168  thisParticle->addExtraInfo("looseMCMotherIndex", -1);
169  thisParticle->addExtraInfo("looseMCWrongDaughterN", -1);
170  thisParticle->addExtraInfo("looseMCWrongDaughterPDG", -1);
171  thisParticle->addExtraInfo("looseMCWrongDaughterBiB", -1);
172  return;
173  }
174 
175  const MCParticle* mcMother = m_mcparticles[commonMother->first - 1];
176 
177  Particle* thisParticle = m_particles[particle->getArrayIndex()];
178  thisParticle->addExtraInfo("looseMCMotherPDG", mcMother->getPDG());
179  thisParticle->addExtraInfo("looseMCMotherIndex", mcMother->getArrayIndex());
180  thisParticle->addExtraInfo("looseMCWrongDaughterN", fsDaughters.size() - commonMother->second);
181 
182  // find out what kind of particle was wrongly added
183  // only for the case where there is only one such particle
184  // This is the most interesting case. If two or more
185  // particles are wrongly added, then a candidate looks
186  // like background
187  int wrongParticlePDG = 0; // PDG code of the wrongly matched particle
188  int wrongParticleBiB = 0; // true (false) if particle doesn't (does) have MCParticle relation
189  if (fsDaughters.size() - commonMother->second == 1) {
190  for (auto daughter : fsDaughters) {
191  const MCParticle* mcDaughter = daughter->getRelatedTo<MCParticle>();
192  if (!mcDaughter) {
193  wrongParticlePDG = daughter->getPDGCode();
194  wrongParticleBiB = 1;
195  }
196 
197  vector<int> genMothers;
198  MCMatching::fillGenMothers(mcDaughter, genMothers);
199 
200  // check if current daughter descends from common mother
201  if (find(genMothers.begin(), genMothers.end(), commonMother->first) != genMothers.end())
202  continue;
203 
204  // daughter is not a child of common mother
205  wrongParticlePDG = daughter->getPDGCode();
206  }
207  }
208 
209  thisParticle->addExtraInfo("looseMCWrongDaughterPDG", wrongParticlePDG);
210  thisParticle->addExtraInfo("looseMCWrongDaughterBiB", wrongParticleBiB);
211 
212  }
214 } // end Belle2 namespace
MC matching module: module performs MC matching (sets the relation Particle -> MCParticle) for all pa...
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
Base class for Modules.
Definition: Module.h:72
Class to store reconstructed particles.
Definition: Particle.h:74
void addExtraInfo(const std::string &name, float value)
Sets the user-defined data of given name to the given value.
Definition: Particle.cc:1289
#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.