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