Belle II Software  release-08-01-10
MCMatching.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/utility/MCMatching.h>
10 #include <analysis/utility/AnalysisConfiguration.h>
11 
12 #include <analysis/dataobjects/Particle.h>
13 #include <mdst/dataobjects/MCParticle.h>
14 
15 #include <framework/datastore/StoreArray.h>
16 #include <framework/gearbox/Const.h>
17 #include <framework/logging/Logger.h>
18 
19 #include <unordered_set>
20 
21 using namespace Belle2;
22 using namespace std;
23 
24 const std::string MCMatching::c_extraInfoMCErrors = "mcErrors";
25 
26 std::string MCMatching::explainFlags(unsigned int flags)
27 {
28  if (flags == c_Correct)
29  return "c_Correct";
30 
31  std::string s;
32  unsigned int f = 1;
33  while (flags != 0) {
34  if (flags & f) {
35  switch (f) {
36  case c_MissFSR : s += "c_MissFSR"; break;
37  case c_MissingResonance : s += "c_MissingResonance"; break;
38  case c_DecayInFlight : s += "c_DecayInFlight"; break;
39  case c_MissNeutrino : s += "c_MissNeutrino"; break;
40  case c_MissGamma : s += "c_MissGamma"; break;
41  case c_MissMassiveParticle : s += "c_MissMassiveParticle"; break;
42  case c_MissKlong : s += "c_MissKlong"; break;
43  case c_MisID : s += "c_MisID"; break;
44  case c_AddedWrongParticle : s += "c_AddedWrongParticle"; break;
45  case c_InternalError : s += "c_InternalError"; break;
46  case c_MissPHOTOS : s += "c_MissPHOTOS"; break;
47  case c_AddedRecoBremsPhoton : s += "c_AddedRecoBremsPhoton"; break;
48  default:
49  s += to_string(f);
50  B2ERROR("MCMatching::explainFlags() doesn't know about flag " << f << ", please update it.");
51  }
52  flags -= f; //remove flag
53  if (flags != 0)
54  s += " | ";
55  }
56  f *= 2;
57  }
58  return s;
59 }
60 
61 void MCMatching::fillGenMothers(const MCParticle* mcP, vector<int>& genMCPMothers)
62 {
63  while (mcP) {
64  genMCPMothers.push_back(mcP->getIndex());
65  mcP = mcP->getMother();
66  }
67 }
68 
69 
70 int MCMatching::findCommonMother(const MCParticle* mcP, const vector<int>& firstMothers, int lastMother)
71 {
72  while (mcP) {
73  int idx = mcP->getIndex();
74  for (unsigned int i = lastMother; i < firstMothers.size(); i++) {
75  if (firstMothers[i] == idx)
76  return i;
77  }
78 
79  mcP = mcP->getMother();
80  }
81  //not found
82  return -1;
83 }
84 
85 
86 bool MCMatching::setMCTruth(const Particle* particle)
87 {
88  //if extra-info is set, we already handled this particle
89  //TODO check whether this actually speeds things up or not
90  if (particle->hasExtraInfo(c_extraInfoMCErrors))
91  return true;
92 
93  if (particle->getRelatedTo<MCParticle>()) {
94  //nothing to do
95  return true;
96  }
97 
98  int nChildren = particle->getNDaughters();
99  if (nChildren == 0) {
100  //no daughters -> should be an FSP, but no related MCParticle. Probably background.
101  return false;
102  }
103 
104  // check, if for all daughter particles Particle -> MCParticle relation exists
105  bool daugMCTruth = true;
106  for (int i = 0; i < nChildren; ++i) {
107  const Particle* daugP = particle->getDaughter(i);
108  // call setMCTruth for all daughters
109  daugMCTruth &= setMCTruth(daugP);
110  }
111  if (!daugMCTruth)
112  return false;
113 
114  int motherIndex = 0;
115  if (nChildren == 1) {
116  // assign mother of MCParticle related to our daughter
117  const Particle* daugP = particle->getDaughter(0);
118  const MCParticle* daugMCP = daugP->getRelatedTo<MCParticle>();
119  if (!daugMCP)
120  return false;
121  const MCParticle* mom = daugMCP->getMother();
122  if (!mom)
123  return false;
124  motherIndex = mom->getIndex();
125 
126  } else {
127  // at this stage for all daughters particles the Particle <-> MCParticle relation exists
128  // first fill vector with indices of all mothers of first daughter,
129  // then search common mother for each other daughter
130 
131  vector<int> firstDaugMothers; // indices of generated mothers of first daughter
132 
133  int lastMother = 0; //index in firstDaugMothers (start with first daughter itself)
134  for (int i = 0; i < nChildren; ++i) {
135  const Particle* daugP = particle->getDaughter(i);
136  const MCParticle* daugMCP = daugP->getRelatedTo<MCParticle>();
137 
138  if (i == 0) {
139  fillGenMothers(daugMCP, firstDaugMothers);
140  } else {
141  lastMother = findCommonMother(daugMCP, firstDaugMothers, lastMother);
142  if (lastMother == -1)
143  break; //not found
144  }
145  }
146  if (lastMother >= 0)
147  motherIndex = firstDaugMothers[lastMother];
148  }
149 
150  // if index is less than 1, the common mother particle was not found
151  // remember: it's 1-based index
152  if (motherIndex < 1)
153  return false;
154 
155  // finally the relation can be set
156  StoreArray<MCParticle> mcParticles;
157 
158  // sanity check
159  if (motherIndex > mcParticles.getEntries()) {
160  B2ERROR("setMCTruth(): sanity check failed!");
161  return false;
162  }
163 
164  const MCParticle* mcMatch = mcParticles[motherIndex - 1];
165  particle->addRelationTo(mcMatch);
166 
167  return true;
168 }
169 
170 
171 //utility functions used by setMCErrorsExtraInfo() getMissingParticleFlags()
172 namespace {
174  void appendParticles(const Particle* p, unordered_set<const MCParticle*>& mcMatchedParticles)
175  {
176  for (unsigned i = 0; i < p->getNDaughters(); ++i) {
177  const Particle* daug = p->getDaughter(i);
178 
179  //add matched MCParticle for 'daug'
180  const MCParticle* mcParticle = daug->getRelatedTo<MCParticle>();
181  if (mcParticle)
182  mcMatchedParticles.insert(mcParticle);
183 
184  if (daug->getNDaughters() != 0) {
185  // if daug has daughters, call appendParticles recursively.
186  appendParticles(daug, mcMatchedParticles);
187  continue;
188  }
189 
190  if (mcParticle and daug->hasExtraInfo(MCMatching::c_extraInfoMCErrors)) {
191  if (static_cast<unsigned int>(daug->getExtraInfo(MCMatching::c_extraInfoMCErrors)) & MCMatching::c_DecayInFlight) {
192  //now daug does not have any daughters.
193  //particle at the bottom of reconstructed decay tree, reconstructed from an MCParticle that is actually slightly deeper than we want,
194  //so we'll also add all mother MCParticles until the first primary mother
195  mcParticle = mcParticle->getMother();
196  while (mcParticle) {
197  mcMatchedParticles.insert(mcParticle);
198  if (mcParticle->hasStatus(MCParticle::c_PrimaryParticle))
199  break;
200 
201  mcParticle = mcParticle->getMother();
202  }
203  }
204  }
205 
206  }
207  }
208 
210  void appendParticles(const MCParticle* gen, vector<const MCParticle*>& children)
211  {
212  if (MCMatching::isFSP(gen->getPDG()) and gen->getPDG() != Const::Kshort.getPDGCode())
213  return; //stop at the bottom of the MC decay tree (ignore secondaries)
214 
215  // Ks that decays interacting with materials can have additional daughters not only 2-pions.
216  // To check the missing daughters, the exception for Ks is introduced.
217 
218  const vector<MCParticle*>& genDaughters = gen->getDaughters();
219  for (auto daug : genDaughters) {
220  children.push_back(daug);
221  appendParticles(daug, children);
222  }
223  }
224 
225  // Check if mcDaug is accepted to be missed by the property of part.
226  bool isDaughterAccepted(const MCParticle* mcDaug, const Particle* part)
227  {
228  const int property = part->getProperty();
229 
230  const int absPDG = abs(mcDaug->getPDG());
231 
232  // if mcDaug is not FSP, check c_IsIgnoreIntermediate property
233  if (!MCMatching::isFSP(absPDG)) {
234  if (property & Particle::PropertyFlags::c_IsIgnoreIntermediate)
235  return true;
236  } else if (absPDG == Const::photon.getPDGCode()) { // gamma
238  or (AnalysisConfiguration::instance()->useLegacyMCMatching() and MCMatching::isFSRLegacy(mcDaug))) {
239  if (property & Particle::PropertyFlags::c_IsIgnoreRadiatedPhotons)
240  return true;
241  } else {
242  if (property & Particle::PropertyFlags::c_IsIgnoreGamma)
243  return true;
244  }
245  } else if (absPDG == 12 or absPDG == 14 or absPDG == 16) { // neutrino
246  if (property & Particle::PropertyFlags::c_IsIgnoreNeutrino)
247  return true;
248  } else { // otherwise, massive FSP
249  if (property & Particle::PropertyFlags::c_IsIgnoreMassive)
250  return true;
251  }
252 
253  return false;
254  }
255 
257  void appendAcceptedMissingDaughters(const Particle* p, unordered_set<const MCParticle*>& acceptedParticles)
258  {
259  const MCParticle* mcParticle = p->getRelatedTo<MCParticle>();
260  if (mcParticle) {
261  vector<const MCParticle*> genDaughters;
262  appendParticles(mcParticle, genDaughters);
263 
264  for (auto mcDaug : genDaughters) {
265  if (isDaughterAccepted(mcDaug, p))
266  acceptedParticles.insert(mcDaug);
267  else
268  acceptedParticles.erase(mcDaug);
269  }
270  }
271 
272  for (unsigned i = 0; i < p->getNDaughters(); ++i) {
273  const Particle* daug = p->getDaughter(i);
274  appendAcceptedMissingDaughters(daug, acceptedParticles);
275  }
276 
277  }
278 
279 
280 }
281 
282 int MCMatching::getMCErrors(const Particle* particle, const MCParticle* mcParticle)
283 {
284  if (particle->hasExtraInfo(c_extraInfoMCErrors)) {
285  return particle->getExtraInfo(c_extraInfoMCErrors);
286  } else {
287  if (!mcParticle)
288  mcParticle = particle->getRelatedTo<MCParticle>();
289  return setMCErrorsExtraInfo(const_cast<Particle*>(particle), mcParticle);
290  }
291 }
292 
293 int MCMatching::setMCErrorsExtraInfo(Particle* particle, const MCParticle* mcParticle)
294 {
295  auto setStatus = [](Particle * part, int s) -> int {
296  part->addExtraInfo(c_extraInfoMCErrors, s);
297  return s;
298  };
299 
300  if (!mcParticle)
301  return setStatus(particle, MCErrorFlags::c_InternalError);
302 
303  if (particle->getNDaughters() == 0) { //FSP
304  //other checks concern daughters of particle, so we're done here
305  return setStatus(particle, getFlagsOfFSP(particle, mcParticle));;
306  }
307 
308  int status = 0;
309 
310  // Check if particle (non FSP) has different PDG code than mcParticle
311  const Particle::EFlavorType flavorType = particle->getFlavorType();
312  if ((flavorType == Particle::c_Flavored and particle->getPDGCode() != mcParticle->getPDG())
313  or (flavorType == Particle::c_Unflavored and abs(particle->getPDGCode()) != abs(mcParticle->getPDG()))) {
314  auto mother = mcParticle->getMother();
315 
316  // Check if mother particle has the correct pdg code, if so we have to take care of the special case
317  // tau -> rho nu, where a the matched mother is the rho, but we have only a missing resonance and not added a wrong particle.
318  if (mother and particle->getPDGCode() == mother->getPDG() and getNumberOfDaughtersWithoutNeutrinos(mother) == 1
319  and !particle->hasExtraInfo("bremsCorrected")) {
320  if (abs(mother->getPDG()) != 15 and abs(mcParticle->getPDG()) != 15) {
321  B2WARNING("Special treatment in MCMatching for tau is called for a non-tau particle. Check if you discovered another special case here, or if we have a bug! "
322  << mother->getPDG() << " " << particle->getPDGCode() << " " << mcParticle->getPDG());
323  }
324  // if particle has c_IsIgnoreIntermediate flag, c_MissingResonance will not be added.
325  if (not(particle->getProperty() & Particle::PropertyFlags::c_IsIgnoreIntermediate))
326  status |= MCErrorFlags::c_MissingResonance;
327  } else if (!(particle->getProperty() & Particle::PropertyFlags::c_IsUnspecified)) {
328  // Check if the particle is unspecified. If so the flag of c_AddedWrongParticle will be ignored.
329  status |= MCErrorFlags::c_AddedWrongParticle;
330  }
331  }
332 
333  status |= getFlagsOfDaughters(particle, mcParticle);
334 
335  status |= getMissingParticleFlags(particle, mcParticle);
336 
337  // Mask the flags ignored by PropertyFlags of the particle
338  status &= ~(getFlagsIgnoredByProperty(particle));
339 
340  return setStatus(particle, status);
341 }
342 
343 int MCMatching::getFlagsOfFSP(const Particle* particle, const MCParticle* mcParticle)
344 {
345  if (particle->getPDGCode() == mcParticle->getPDG())
346  return MCErrorFlags::c_Correct;
347 
348  // if PDG of particle is different from that of mcParticle
349  if (mcParticle->hasStatus(MCParticle::c_PrimaryParticle)) {
350  // if particle is primary, add the c_MisID flag.
351  return MCErrorFlags::c_MisID;
352  } else {
353  // secondary particle, so the original particle probably decayed
354  int status = MCErrorFlags::c_DecayInFlight;
355 
356  //find first primary mother
357  const MCParticle* primary = mcParticle->getMother();
358  while (primary and !primary->hasStatus(MCParticle::c_PrimaryParticle))
359  primary = primary->getMother();
360 
361  if (!primary) {
362  status |= MCErrorFlags::c_InternalError;
363  } else if (particle->getPDGCode() != primary->getPDG()) {
364  //if primary particle also has wrong PDG code, we're actually MisIDed
365  status |= MCErrorFlags::c_MisID;
366  }
367  return status;
368  }
369 }
370 
371 int MCMatching::getFlagsOfDaughters(const Particle* particle, const MCParticle* mcParticle)
372 {
373  unsigned nChildren = particle->getNDaughters();
374 
375  //Vector to store all the MC (n*grand-)daughters of the mother of the bremsstrahlung corrected particle
376  vector<const MCParticle*> genParts;
377  //Fill it only in the case we have a particle that has been brems corrected
378  if (particle->hasExtraInfo("bremsCorrected") && nChildren > 1) {
379  if (mcParticle && mcParticle->getMother())
380  appendParticles(mcParticle->getMother(), genParts);
381  }
382 
383  int daughterStatuses = 0;
384  vector<int> daughterProperties = particle->getDaughterProperties();
385  for (unsigned i = 0; i < nChildren; ++i) {
386  const Particle* daughter = particle->getDaughter(i);
387  int daughterStatus = 0;
388  if (particle->hasExtraInfo("bremsCorrected") && daughter->getPDGCode() == Const::photon.getPDGCode()) {
389  // if the daughter is a brems photon, start the special treatment
390  daughterStatus |= getFlagsOfBremsPhotonDaughter(daughter, mcParticle, genParts);
391  } else {
392  daughterStatus |= getMCErrors(daughter);
393  }
394 
395  int daughterStatusAcceptMask = (~c_Correct);
396  if (i < daughterProperties.size()) // sanity check. daughterProperties should be larger than i.
397  daughterStatusAcceptMask = makeDaughterAcceptMask(daughterProperties[i]);
398 
399  daughterStatuses |= (daughterStatus & daughterStatusAcceptMask);
400  }
401 
402  //add up all (accepted) status flags we collected for our daughters
403  const int daughterStatusesAcceptMask = c_MisID | c_AddedWrongParticle | c_DecayInFlight | c_InternalError | c_AddedRecoBremsPhoton;
404  return (daughterStatuses & daughterStatusesAcceptMask);
405 
406 }
407 
408 
409 int MCMatching::getFlagsOfBremsPhotonDaughter(const Particle* daughter, const MCParticle* mcParticle,
410  const vector<const MCParticle*>& genParts)
411 {
412  //At first, call getMCErrors as usual
413  int daughterStatus = getMCErrors(daughter);
414 
415  //Check if the daugther has an MC particle related
416  const MCParticle* mcDaughter = daughter->getRelatedTo<MCParticle>();
417  //If it hasn't, add the c_BremsPhotonAdded flag to the mother and stop the propagation of c_InternalError
418  if (!mcDaughter) {
419  daughterStatus &= (~c_InternalError);
420  daughterStatus |= c_AddedRecoBremsPhoton;
421  }
422  //If it has, check if MCParticle of the daughter is same as the mother. If so, we'll stop the propagation of c_MisID
423  else if (mcDaughter == mcParticle) {
424  daughterStatus &= (~c_MisID);
425  }
426  //If it has, check if the MC particle is (n*grand)-daughter of the particle mother. If it isn't, we'll add the error flag
427  else if (std::find(genParts.begin(), genParts.end(), mcDaughter) == genParts.end()) {
428  daughterStatus |= c_AddedRecoBremsPhoton;
429  }
430  //else nothing to do
431 
432  return daughterStatus;
433 }
434 
436 {
437  auto daughters = mcParticle->getDaughters();
438  unsigned int number_of_neutrinos = 0;
439  for (auto& p : daughters) {
440  auto pdg = abs(p->getPDG());
441  if (pdg == 12 || pdg == 14 || pdg == 16) {
442  number_of_neutrinos++;
443  }
444  }
445  return daughters.size() - number_of_neutrinos;
446 }
447 
448 bool MCMatching::isFSP(int pdg)
449 {
450  switch (abs(pdg)) {
451  case 211: // pi
452  case 321: // K
453  case 11: // e
454  case 12: // nu_e
455  case 13: // mu
456  case 14: // nu_mu
457  case 16: // nu_tau
458  case 22: // gamma
459  case 2212: // proton
460  case 310: // K0S
461  case 130: // K0L
462  case 2112: // neutron
463  return true;
464  default:
465  return false;
466  }
467 }
468 
470 {
471  return p->hasStatus(MCParticle::c_IsFSRPhoton);
472 }
473 
475 {
476  // In older versions of MC MCParticles don't have c_IsFSRPhoton, c_IsISRPhoton or c_ISPHOTOSPhoton bits
477  // properly set. Instead this approximation is used to check if given photon is radiative (physics) photon
478  // or produced by PHOTOS (FSR).
479 
480  const MCParticle* mother = p->getMother();
481  if (!mother) {
482  B2ERROR("The hell? why would this gamma not have a mother?");
483  return false; //?
484  }
485 
486  int ndaug = mother->getNDaughters();
487  if (ndaug > 2) { // M -> A B (...) gamma is probably FSR
488  return true;
489  } else { // M -> A gamma is probably a decay
490  return false;
491  }
492 }
493 
494 
496 {
497  // Check if any of the bits c_IsFSRPhoton, c_IsISRPhoton or c_ISPHOTOSPhoton is set
498  return p->getStatus(MCParticle::c_IsRadiativePhoton) != 0;
499 }
500 
501 
502 int MCMatching::getMissingParticleFlags(const Particle* particle, const MCParticle* mcParticle)
503 {
504  int flags = 0;
505 
506  vector<const MCParticle*> genParts;
507  appendParticles(mcParticle, genParts);
508 
509  unordered_set<const MCParticle*> mcMatchedParticles;
510  appendParticles(particle, mcMatchedParticles);
511  unordered_set<const MCParticle*> acceptedParticles;
512  appendAcceptedMissingDaughters(particle, acceptedParticles);
513  for (auto part : acceptedParticles) {
514  mcMatchedParticles.insert(part);
515  }
516 
517 
518  for (const MCParticle* genPart : genParts) {
519 
520  // if genPart exists in mcMatchedParticles, continue.
521  if (mcMatchedParticles.find(genPart) != mcMatchedParticles.end())
522  continue;
523 
524  //we want to set a flag, so what kind of particle is genPart?
525  const int generatedPDG = genPart->getPDG();
526  const int absGeneratedPDG = abs(generatedPDG);
527 
528  if (!isFSP(generatedPDG)) {
529  flags |= c_MissingResonance;
530  } else if (generatedPDG == Const::photon.getPDGCode()) { //missing photon
531  if (AnalysisConfiguration::instance()->useLegacyMCMatching()) {
532  if (flags & (c_MissFSR | c_MissGamma)) {
533  // if flags already have c_MissFSR or c_MissGamm, do nothing.
534  } else {
535  if (isFSRLegacy(genPart)) {
536  flags |= c_MissFSR;
537  flags |= c_MissPHOTOS;
538  } else {
539  flags |= c_MissGamma;
540  }
541  }
542  } else {
543  if (isFSR(genPart))
544  flags |= c_MissFSR;
545  else if (genPart->hasStatus(MCParticle::c_IsPHOTOSPhoton))
546  flags |= c_MissPHOTOS;
547  else
548  flags |= c_MissGamma;
549  }
550  } else if (absGeneratedPDG == 12 || absGeneratedPDG == 14 || absGeneratedPDG == 16) { // missing neutrino
551  flags |= c_MissNeutrino;
552  } else { //neither photon nor neutrino -> massive
553  flags |= c_MissMassiveParticle;
554  if (absGeneratedPDG == Const::Klong.getPDGCode())
555  flags |= c_MissKlong;
556  }
557  }
558  return flags;
559 }
560 
561 int MCMatching::countMissingParticle(const Particle* particle, const MCParticle* mcParticle, const vector<int>& daughterPDG)
562 {
563  unordered_set<const MCParticle*> mcMatchedParticles;
564  // Missing particles which are accepted by the property flags are NOT stored.
565  // --> Such particles are also counted in nMissingDaughter.
566  appendParticles(particle, mcMatchedParticles);
567  vector<const MCParticle*> genParts;
568  appendParticles(mcParticle, genParts);
569 
570  int nMissingDaughter = 0;
571 
572  for (const MCParticle* genPart : genParts) {
573  const bool missing = (mcMatchedParticles.find(genPart) == mcMatchedParticles.end());
574  if (missing) {
575 
576  const int generatedPDG = genPart->getPDG();
577  const int absGeneratedPDG = abs(generatedPDG);
578 
579  auto result = find(daughterPDG.begin(), daughterPDG.end(), absGeneratedPDG);
580  if (result != daughterPDG.end())
581  nMissingDaughter++;
582  }
583  }
584 
585  return nMissingDaughter;
586 }
587 
589 {
590  int flags = 0;
591 
592  if (part->getProperty() & Particle::PropertyFlags::c_IsIgnoreBrems) flags |= (MCMatching::c_AddedRecoBremsPhoton);
593 
594  return flags;
595 }
596 
597 int MCMatching::makeDaughterAcceptMask(int daughterProperty)
598 {
599  int flags = 0;
600 
601  if (daughterProperty & Particle::PropertyFlags::c_IsIgnoreMisID) flags |= (MCMatching::c_MisID);
602  if (daughterProperty & Particle::PropertyFlags::c_IsIgnoreDecayInFlight) flags |= (MCMatching::c_DecayInFlight);
603 
604  return (~flags);
605 
606 }
static AnalysisConfiguration * instance()
Returns a pointer to the singleton instance.
int getPDGCode() const
PDG code.
Definition: Const.h:464
static const ParticleType Klong
K^0_L particle.
Definition: Const.h:669
static const ParticleType Kshort
K^0_S particle.
Definition: Const.h:668
static const ParticleType photon
photon particle
Definition: Const.h:664
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_IsPHOTOSPhoton
bit 8: Particle is an radiative photon from PHOTOS
Definition: MCParticle.h:63
@ c_IsRadiativePhoton
combined flag to test whether the particle is radiative
Definition: MCParticle.h:65
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition: MCParticle.h:47
int getIndex() const
Get 1-based index of the particle in the corresponding MCParticle list.
Definition: MCParticle.h:230
std::vector< Belle2::MCParticle * > getDaughters() const
Get vector of all daughter particles, empty vector if none.
Definition: MCParticle.cc:52
bool hasStatus(unsigned short int bitmask) const
Return if specific status bit is set.
Definition: MCParticle.h:129
int getPDG() const
Return PDG code of particle.
Definition: MCParticle.h:112
Class to store reconstructed particles.
Definition: Particle.h:75
EFlavorType
describes flavor type, see getFlavorType().
Definition: Particle.h:94
@ c_Unflavored
Is its own antiparticle or we don't know whether it is a particle/antiparticle.
Definition: Particle.h:95
@ c_Flavored
Is either particle or antiparticle.
Definition: Particle.h:96
TO * getRelatedTo(const std::string &name="", const std::string &namedRelation="") const
Get the object to which this object has a relation.
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:216
MCParticle * getMother() const
Returns a pointer to the mother particle.
Definition: MCParticle.h:600
Abstract base class for different kinds of events.
static int countMissingParticle(const Belle2::Particle *particle, const Belle2::MCParticle *mcParticle, const std::vector< int > &daughterPDG)
Count the number of missing daughters of the 'particle'.
Definition: MCMatching.cc:561
static std::string explainFlags(unsigned int flags)
Return string with all human-readable flags, e.g.
Definition: MCMatching.cc:26
@ c_DecayInFlight
A Particle was reconstructed from the secondary decay product of the actual particle.
Definition: MCMatching.h:37
@ c_MisID
One of the charged final state particles is mis-identified, i.e.
Definition: MCMatching.h:42
@ c_AddedRecoBremsPhoton
A photon added with the bremsstrahlung recovery tools (correctBrems or correctBremsBelle) has no MC p...
Definition: MCMatching.h:46
static bool isRadiativePhoton(const Belle2::MCParticle *p)
Returns true if given MCParticle is a radiative photon.
Definition: MCMatching.cc:495
static int makeDaughterAcceptMask(int daughterProperty)
Returns the daughter mask from given daughterProperty.
Definition: MCMatching.cc:597
static int getNumberOfDaughtersWithoutNeutrinos(const MCParticle *mcParticle)
Determines the number of daughter particles which are not neutrinos.
Definition: MCMatching.cc:435
static int getFlagsOfBremsPhotonDaughter(const Particle *daughter, const MCParticle *mcParticle, const std::vector< const MCParticle * > &genParts)
Returns flags of given daughter which is a brems photon.
Definition: MCMatching.cc:409
static bool setMCTruth(const Belle2::Particle *particle)
This is the main function of MC matching algorithm.
Definition: MCMatching.cc:86
static int getFlagsOfFSP(const Particle *particle, const MCParticle *mcParticle)
Returns flags of given Final State Particle.
Definition: MCMatching.cc:343
static int getMCErrors(const Belle2::Particle *particle, const Belle2::MCParticle *mcParticle=nullptr)
Returns quality indicator of the match as a bit pattern where the individual bits indicate the the ty...
Definition: MCMatching.cc:282
static int getFlagsOfDaughters(const Particle *daughter, const MCParticle *mcParticle)
Returns flags of daughters of given particle.
Definition: MCMatching.cc:371
static bool isFSR(const Belle2::MCParticle *p)
Returns true if given MCParticle is a final state radiation (FSR) photon based on MCParticle::c_IsFSR...
Definition: MCMatching.cc:469
static bool isFSRLegacy(const Belle2::MCParticle *p)
Returns true if given MCParticle is a final state radiation (FSR) photon.
Definition: MCMatching.cc:474
static void fillGenMothers(const Belle2::MCParticle *mcP, std::vector< int > &genMCPMothers)
Fills vector with array (1-based) indices of all generator ancestors of given MCParticle.
Definition: MCMatching.cc:61
static int setMCErrorsExtraInfo(Belle2::Particle *particle, const Belle2::MCParticle *mcParticle)
Sets error flags in extra-info (also returns it).
Definition: MCMatching.cc:293
static int getFlagsIgnoredByProperty(const Belle2::Particle *particle)
Returns the flags ignored by PropertyFlags of given particle.
Definition: MCMatching.cc:588
static int getMissingParticleFlags(const Belle2::Particle *particle, const Belle2::MCParticle *mcParticle)
Determines which daughters of 'mcParticle' are not reconstructed by any daughter of 'particle'.
Definition: MCMatching.cc:502
static bool isFSP(int pdg)
Returns true if given PDG code indicates a FSP.
Definition: MCMatching.cc:448
static const std::string c_extraInfoMCErrors
Name of extra-info field stored in Particle.
Definition: MCMatching.h:30
static int findCommonMother(const Belle2::MCParticle *mcP, const std::vector< int > &firstMothers, int lastMother)
Finds a mother of mcP that is in firstMothers, from [lastMother, end].
Definition: MCMatching.cc:70