Belle II Software  release-05-01-25
mcmatching.cc
1 #include <analysis/utility/MCMatching.h>
2 #include <analysis/dataobjects/Particle.h>
3 #include <analysis/dataobjects/ParticleExtraInfoMap.h>
4 #include <analysis/variables/BasicParticleInformation.h>
5 #include <analysis/variables/MCTruthVariables.h>
6 
7 #include <mdst/dataobjects/MCParticle.h>
8 #include <mdst/dataobjects/MCParticleGraph.h>
9 #include <framework/datastore/StoreArray.h>
10 #include <framework/datastore/StoreObjPtr.h>
11 
12 #include <gtest/gtest.h>
13 
14 using namespace std;
15 using namespace Belle2;
16 
17 //checks against update3
18 #if defined(__INTEL_COMPILER) && ((__INTEL_COMPILER < 1400) || (__INTEL_COMPILER_BUILD_DATE < 20140422))
19 namespace {
20  TEST(MCMatchingTest, TestsDisabled)
21  {
22  EXPECT_TRUE(false) <<
23  "MC matching test disabled on intel compiler (version < 14 sp1 update2), please see https://software.intel.com/en-us/forums/topic/475378";
24  }
25 }
26 #else
27 
28 namespace {
29  MCParticleGraph gParticleGraph;
30 
32  bool isFSP(int pdg)
33  {
34  switch (abs(pdg)) {
35  case 211:
36  case 321:
37  case 11:
38  case 13:
39  case 2212:
40  case 22:
41  case 130:
42  return true;
43  default:
44  return false;
45  }
46  }
47 
49  struct Decay {
50  public:
52  enum EBehavior {
53  c_Default,
54  c_CreateNewMCParticle,
55  c_RelateWith,
56  c_ReconstructFrom,
57  };
59  // cppcheck-suppress noExplicitConstructor; yes, there is no explicit constructor for this class, and this isn't one
60  Decay(int pdg, const std::vector<Decay>& daughters = std::vector<Decay>()):
61  m_pdg(pdg), m_daughterDecays(daughters), m_mcparticle(nullptr), m_particle(nullptr)
62  {
63  m_graphParticle = &gParticleGraph.addParticle();
64  m_graphParticle->setPDG(m_pdg);
65  m_graphParticle->setStatus(MCParticle::c_PrimaryParticle);
66  for (const Decay& d : daughters) {
67  gParticleGraph.addDecay(*m_graphParticle, *d.m_graphParticle);
68  }
69  }
71  void finalize()
72  {
73  gParticleGraph.generateList();
74  gParticleGraph.clear(); //don't add them again in the next call..
75 
76  StoreArray<MCParticle> mcparticles;
77  m_mcparticle = mcparticles[m_graphParticle->getIndex() - 1];
78 
79  for (Decay& d : m_daughterDecays)
80  d.finalize();
81  }
82 
84  [[nodiscard]] Particle* getParticle(int pdg) const
85  {
86  if (m_pdg == pdg and m_particle)
87  return m_particle;
88 
89  for (auto& d : m_daughterDecays) {
90  Particle* res = d.getParticle(pdg);
91  if (res)
92  return res;
93  }
94  return nullptr;
95  }
97  [[nodiscard]] MCParticle* getMCParticle(int pdg) const
98  {
99  if (m_pdg == pdg and m_mcparticle)
100  return m_mcparticle;
101 
102  for (auto& d : m_daughterDecays) {
103  MCParticle* res = d.getMCParticle(pdg);
104  if (res)
105  return res;
106  }
107  return nullptr;
108  }
110  Decay* getDecay(int pdg)
111  {
112  if (m_pdg == pdg)
113  return this;
114 
115  for (auto& d : m_daughterDecays) {
116  Decay* res = d.getDecay(pdg);
117  if (res)
118  return res;
119  }
120  return nullptr;
121  }
122 
123  Decay& operator[](int i) { return m_daughterDecays[i]; }
124 
126  struct ReconstructedDecay {
127  // cppcheck-suppress noExplicitConstructor; yes, there is no explicit constructor for this class, and this isn't one
128  ReconstructedDecay(int pdg, const std::vector<ReconstructedDecay>& daughters = std::vector<ReconstructedDecay>(),
129  EBehavior behavior = c_Default):
130  m_pdg(pdg), m_daughterDecays(daughters), m_behavior(behavior), m_optMcPart(nullptr), m_optDecay(nullptr) { }
131  ReconstructedDecay(int pdg, const std::vector<ReconstructedDecay>& daughters, EBehavior behavior, MCParticle* optMcPart):
132  m_pdg(pdg), m_daughterDecays(daughters), m_behavior(behavior), m_optMcPart(optMcPart), m_optDecay(nullptr) { }
133  ReconstructedDecay(int pdg, const std::vector<ReconstructedDecay>& daughters, EBehavior behavior, Decay* optDecay):
134  m_pdg(pdg), m_daughterDecays(daughters), m_behavior(behavior), m_optMcPart(nullptr), m_optDecay(optDecay) { }
135  int m_pdg;
136  vector<ReconstructedDecay> m_daughterDecays;
137  EBehavior m_behavior;
138  MCParticle* m_optMcPart;
139  Decay* m_optDecay;
140  };
141 
148  void reconstruct(ReconstructedDecay decay)
149  {
150  if (!m_mcparticle) {
151  finalize();
152  }
153  if (decay.m_behavior == c_CreateNewMCParticle) {
154  m_graphParticle = &gParticleGraph.addParticle();
155  m_graphParticle->setPDG(decay.m_pdg);
156  finalize(); //overwrites m_mcparticle with the new particle
157  } else if (decay.m_behavior == c_RelateWith) {
158  m_mcparticle = decay.m_optMcPart;
159  } else if (decay.m_behavior == c_ReconstructFrom) {
160  ASSERT_TRUE(decay.m_optDecay != nullptr);
161  Decay* mcDecay = decay.m_optDecay;
162  decay.m_optDecay = nullptr;
163  decay.m_behavior = Decay::c_Default;
164  mcDecay->reconstruct(decay);
165  return;
166  }
167 
168  StoreArray<Particle> particles;
169  if (isFSP(decay.m_pdg)) {
170  //is a final state particle, link with MCParticle
171  m_particle = particles.appendNew(m_graphParticle->get4Vector(), decay.m_pdg);
172  m_particle->addRelationTo(m_mcparticle);
173  }
174 
175  if (!decay.m_daughterDecays.empty()) {
176  Decay* mcDecay = this;
177  if (decay.m_behavior == c_ReconstructFrom) {
178  //use given decay to reconstruct daughters instead
179  mcDecay = decay.m_optDecay;
180  }
181  std::vector<int> daughterIndices;
182  for (unsigned int i = 0; i < decay.m_daughterDecays.size(); i++) {
183  Decay* d = nullptr;
184  ReconstructedDecay rd = decay.m_daughterDecays[i];
185  //we must make sure that m_graphParticle always corresponds to the same thing in the reconstructed thing.
186  if (rd.m_behavior == c_ReconstructFrom) {
187  ASSERT_NE(rd.m_optDecay, nullptr);
188  d = rd.m_optDecay;
189  rd.m_optDecay = nullptr;
190  rd.m_behavior = Decay::c_Default;
191  } else {
192  ASSERT_TRUE(decay.m_daughterDecays.size() > i);
193  d = &(mcDecay->m_daughterDecays[i]);
194  }
195  d->reconstruct({rd});
196  if (d->m_particle)
197  daughterIndices.push_back(d->m_particle->getArrayIndex());
198 
199  }
200  if (decay.m_pdg != 0) {
201  //is decay self conjugated?
202  std::vector<int> decaylist, decaybarlist;
203  for (int idx : daughterIndices) {
204  const Particle* daughterPart = particles[idx];
205  int daughterPDG = daughterPart->getPDGCode();
206  decaylist.push_back(daughterPDG);
207  decaybarlist.push_back((daughterPart->getFlavorType() == Particle::c_Flavored) ? (-daughterPDG) : daughterPDG);
208  }
209  std::sort(decaylist.begin(), decaylist.end());
210  std::sort(decaybarlist.begin(), decaybarlist.end());
211  bool isUnflavored = (decaylist == decaybarlist);
212 
213  m_particle = particles.appendNew(TLorentzVector(), decay.m_pdg, isUnflavored ? (Particle::c_Unflavored) : (Particle::c_Flavored),
214  daughterIndices);
215  }
216  }
217  }
218 
219  [[nodiscard]] string getString() const { return "Particles(MCParticles,MCMatch,Flags):\n" + getStringInternal(); }
220 
221  int m_pdg;
222  vector<Decay> m_daughterDecays;
224  m_graphParticle;
225  MCParticle* m_mcparticle;
226  Particle* m_particle;
228  private:
230  [[nodiscard]] string getStringInternal(int depth = 0) const
231  {
232  stringstream s;
233  string spaces;
234  for (int i = 0; i < depth; i++)
235  spaces += " ";
236  s << spaces;
237 
238  if (m_particle)
239  s << m_particle->getPDGCode();
240  else
241  s << "?";
242 
243  s << " (";
244  if (m_mcparticle)
245  s << m_mcparticle->getPDG();
246  else
247  s << "?";
248  const MCParticle* mcMatch = nullptr;
249  if (m_particle)
250  mcMatch = m_particle->getRelated<MCParticle>();
251  if (mcMatch) {
252  s << ", " << mcMatch->getPDG() << ", ";
253  if (m_particle->hasExtraInfo(MCMatching::c_extraInfoMCErrors))
254  s << MCMatching::explainFlags(m_particle->getExtraInfo(MCMatching::c_extraInfoMCErrors));
255  else
256  s << "-not set-";
257  } else {
258  s << ", ?";
259  s << ", ?";
260  }
261  s << ") ";
262 
263  if (!m_daughterDecays.empty()) {
264  s << " [";
265  for (const Decay& d : m_daughterDecays) {
266  s << "\n" << d.getStringInternal(depth + 1);
267  }
268 
269  s << "\n" << spaces << "]";
270  }
271 
272  return s.str();
273  }
274  };
275 
277  class MCMatchingTest : public ::testing::Test {
278  protected:
280  void SetUp() override
281  {
282  StoreObjPtr<ParticleExtraInfoMap> particleExtraInfo;
283  StoreArray<Particle> particles;
284  StoreArray<MCParticle> mcparticles;
285  particleExtraInfo.registerInDataStore();
286  particles.registerInDataStore();
287  mcparticles.registerInDataStore();
288  particles.registerRelationTo(mcparticles);
289  }
290 
292  void TearDown() override
293  {
294  DataStore::Instance().reset();
295  }
296  };
297 
298 
300  TEST_F(MCMatchingTest, MCParticleGraph)
301  {
302  Decay d(111, {22, 22});
303  StoreArray<MCParticle> mcparticles;
304  //actually push things into StoreArray
305  d.finalize();
306  EXPECT_EQ(mcparticles.getEntries(), 3);
307  EXPECT_EQ(mcparticles[0]->getPDG(), 111);
308  EXPECT_EQ(mcparticles[1]->getPDG(), 22);
309  EXPECT_EQ(mcparticles[2]->getPDG(), 22);
310  EXPECT_EQ(mcparticles[0]->getMother(), nullptr);
311  EXPECT_EQ(mcparticles[1]->getMother(), mcparticles[0]);
312  EXPECT_EQ(mcparticles[2]->getMother(), mcparticles[0]);
313 
314  Decay e(111, {22, 22});
315  e.finalize();
316  EXPECT_EQ(mcparticles.getEntries(), 6);
317  EXPECT_EQ(mcparticles[3]->getPDG(), 111);
318  EXPECT_EQ(mcparticles[3]->getNDaughters(), 2);
319  EXPECT_EQ(mcparticles[4]->getPDG(), 22);
320  EXPECT_EQ(mcparticles[5]->getPDG(), 22);
321  EXPECT_EQ(mcparticles[4]->getNDaughters(), 0);
322  EXPECT_EQ(mcparticles[5]->getNDaughters(), 0);
323  EXPECT_EQ(mcparticles[3]->getMother(), nullptr);
324  EXPECT_EQ(mcparticles[4]->getMother(), mcparticles[3]);
325  EXPECT_EQ(mcparticles[5]->getMother(), mcparticles[3]);
326 
327  Decay f(211);
328  f.finalize();
329  EXPECT_EQ(mcparticles.getEntries(), 7);
330  EXPECT_EQ(mcparticles[6]->getPDG(), 211);
331 
332  Decay g(421, {321, -211, {111, {22, 22}}});
333  g.finalize();
334  EXPECT_EQ(3, g.m_mcparticle->getNDaughters());
335  EXPECT_EQ(mcparticles.getEntries(), 13);
336  }
337 
339  TEST_F(MCMatchingTest, CorrectReconstruction)
340  {
341  StoreArray<MCParticle> mcparticles;
342  StoreArray<Particle> particles;
343 
344  Decay d(421, {321, -211, {111, {22, 22}}});
345  d.reconstruct({421, {321, -211, {111, {22, 22}}}});
346  //reconstruct() calls finalize(), so MCParticles are filled now
347  EXPECT_EQ(mcparticles.getEntries(), 6);
348  EXPECT_EQ(mcparticles[0]->getPDG(), 421);
349  EXPECT_EQ(mcparticles[5]->getPDG(), 22);
350  EXPECT_EQ(particles.getEntries(), 6);
351 
352  ASSERT_NE(d.m_particle, nullptr);
353  const auto& fspParticles = d.m_particle->getFinalStateDaughters();
354  EXPECT_EQ(fspParticles.size(), 4u);
355  //all final state particles should have relations...
356  for (const Particle* p : fspParticles) {
357  EXPECT_EQ(p->getRelated<MCParticle>()->getDaughters().size(), 0u);
358  }
359  //composite particles don't have them
360  EXPECT_TRUE(mcparticles[0] == d.m_mcparticle);
361  EXPECT_TRUE(mcparticles[0]->getRelated<Particle>() == nullptr);
362  EXPECT_TRUE(mcparticles[3]->getRelated<Particle>() == nullptr);
363 
364  //run MC matching (should be able to set a relation)
365  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
366 
367  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(d.m_particle)) << d.getString();
368 
369  }
371  TEST_F(MCMatchingTest, SetMCTruthNeverRun)
372  {
373  Decay d(421, {321, -211, {111, {22, 22}}});
374  d.reconstruct({421, {211, -211, {111, {22, 22}}}});
375 
376  EXPECT_EQ(nullptr, d.m_particle->getRelated<MCParticle>());
377  ASSERT_FALSE(d.m_particle->hasExtraInfo(MCMatching::c_extraInfoMCErrors));
378  EXPECT_EQ(MCMatching::c_InternalError, MCMatching::getMCErrors(d.m_particle)) << d.getString();
379  }
380 
381  TEST_F(MCMatchingTest, SettingTruths)
382  {
383  Decay d(421, {321, -211, {111, {22, 22}}});
384  d.reconstruct({421, {211, -211, {111, {22, 22}}}});
385 
386  //setMCTruth should set relation
387  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
388  EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<MCParticle>()->getPDG());
389 
390  //but no extra-info flags
391  ASSERT_FALSE(d.m_particle->hasExtraInfo(MCMatching::c_extraInfoMCErrors));
392  ASSERT_FALSE(d.getParticle(111)->hasExtraInfo(MCMatching::c_extraInfoMCErrors));
393 
394  EXPECT_EQ(MCMatching::c_MisID, MCMatching::getMCErrors(d.m_particle)) << d.getString();
395 
396  //now it's set
397  ASSERT_TRUE(d.m_particle->hasExtraInfo(MCMatching::c_extraInfoMCErrors));
398  ASSERT_TRUE(d.getParticle(111)->hasExtraInfo(MCMatching::c_extraInfoMCErrors));
399  }
400 
402  TEST_F(MCMatchingTest, MisID)
403  {
404  {
405  Decay d(421, {321, -211, {111, {22, 22}}});
406  d.reconstruct({421, {211, -211, {111, {22, 22}}}});
407  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
408  EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<MCParticle>()->getPDG());
409  EXPECT_EQ(MCMatching::c_MisID, MCMatching::getMCErrors(d.m_particle)) << d.getString();
410  }
411  {
412  //+ wrong non-FSP
413  Decay d(421, {321, -211, {111, {22, 22}}});
414  d.reconstruct({413, {321, -13, {111, {22, 22}}}});
415  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
416  EXPECT_EQ(MCMatching::c_MisID | MCMatching::c_AddedWrongParticle, MCMatching::getMCErrors(d.m_particle)) << d.getString();
417  }
418  {
419  Decay d(421, {321, -211, {111, {22, 22}}});
420  d.reconstruct({421, {321, 13, {111, {22, 22}}}});
421  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
422  EXPECT_EQ(MCMatching::c_MisID, MCMatching::getMCErrors(d.m_particle)) << d.getString();
423  }
424  {
425  Decay d(421, {321, -211, {111, {22, 22}}});
426  d.reconstruct({421, {211, 13, {111, {22, 22}}}});
427  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
428  EXPECT_EQ(MCMatching::c_MisID, MCMatching::getMCErrors(d.m_particle)) << d.getString();
429  }
430  {
431  //pion and kaon switched
432  Decay d(421, {321, -211, {111, {22, 22}}});
433  d.reconstruct({421, { -211, 321, {111, {22, 22}}}});
434  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
435  EXPECT_EQ(MCMatching::c_MisID, MCMatching::getMCErrors(d.m_particle)) << d.getString();
436  }
437  }
438 
440  TEST_F(MCMatchingTest, MissingParticles)
441  {
442  {
443  //pi0 is not FSP, so doesn't get MCMatching::c_MissMassiveParticle (but MCMatching::c_MissingResonance)
444  Decay d(421, {321, -211, {111, {22, 22}}});
445  d.reconstruct({421, {321, -211, {0}}});
446  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
447  EXPECT_EQ(MCMatching::c_MissGamma | MCMatching::c_MissingResonance, MCMatching::getMCErrors(d.m_particle)) << d.getString();
448  }
449  {
450  Decay d(421, {321, -211, {111, {22, 22}}});
451  d.reconstruct({421, {321, 0, {111, {22, 22}}}});
452  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
453  EXPECT_EQ(MCMatching::getMCErrors(d.m_particle), MCMatching::c_MissMassiveParticle) << d.getString();
454  }
455  {
456  Decay d(421, {321, -211, {111, {22, 22}}});
457  d.reconstruct({421, {0, -211, {111, {22, 22}}}});
458  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
459  EXPECT_EQ(MCMatching::getMCErrors(d.m_particle), MCMatching::c_MissMassiveParticle) << d.getString();
460  }
461  {
462  Decay d(421, {321, -211, {111, {22, 22}}});
463  d.reconstruct({421, {0, -13, {111, {22, 22}}}});
464  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
465  EXPECT_EQ(MCMatching::getMCErrors(d.m_particle), MCMatching::c_MissMassiveParticle | MCMatching::c_MisID) << d.getString();
466  }
467  }
468  TEST_F(MCMatchingTest, KLongCorrect)
469  {
470  //correct (we miss the 'K0' resonance, but that's fine)
471  Decay d(431, { {323, {321, {111, {22, 22}} }}, { -311, {130}}});
472  d.finalize();
473  //K0L and daughters are secondary
474  MCParticle* k0l = d.getMCParticle(130);
475  k0l->setStatus(k0l->getStatus() & (~MCParticle::c_PrimaryParticle)); //remove c_PrimaryParticle
476 
477  d.reconstruct({431, { {323, {321, {111, {22, 22}} }}, {130, {}, Decay::c_ReconstructFrom, d.getDecay(130)}}});
478  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
479  EXPECT_EQ(MCMatching::c_MissingResonance, MCMatching::getMCErrors(d.m_particle)) << d.getString();
480  }
481  TEST_F(MCMatchingTest, KLongMissed)
482  {
483  //K0L not reconstructed
484  Decay d(431, { {323, {321, {111, {22, 22}} }}, { -311, {130}}});
485  d.finalize();
486  //K0L and daughters are secondary
487  MCParticle* k0l = d.getMCParticle(130);
488  k0l->setStatus(k0l->getStatus() & (~MCParticle::c_PrimaryParticle)); //remove c_PrimaryParticle
489 
490  d.reconstruct({431, { {323, {321, {111, {22, 22}} }}, 0}});
491  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
492  EXPECT_EQ(MCMatching::c_MissKlong | MCMatching::c_MissMassiveParticle | MCMatching::c_MissingResonance,
493  MCMatching::getMCErrors(d.m_particle)) << d.getString();
494  }
495  TEST_F(MCMatchingTest, KShortCorrect)
496  {
497  //correct (we miss the 'K0' resonance, but that's fine)
498  Decay d(431, { {323, {321, {111, {22, 22}} }}, { -311, {{310, {211, -211}}}}});
499  d.finalize();
500  //K0S and daughters are secondary
501  MCParticle* k0s = d.getMCParticle(310);
502  k0s->setStatus(k0s->getStatus() & (~MCParticle::c_PrimaryParticle)); //remove c_PrimaryParticle
503  MCParticle* pi1 = d.getMCParticle(211);
504  pi1->setStatus(pi1->getStatus() & (~MCParticle::c_PrimaryParticle));
505  MCParticle* pi2 = d.getMCParticle(-211);
506  pi2->setStatus(pi1->getStatus() & (~MCParticle::c_PrimaryParticle));
507 
508  d.reconstruct({431, { {323, {321, {111, {22, 22}} }}, {310, {{211, {}, Decay::c_ReconstructFrom, d.getDecay(211)}, { -211, {}, Decay::c_ReconstructFrom, d.getDecay(-211)}}}}});
509  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
510  EXPECT_EQ(MCMatching::c_MissingResonance, MCMatching::getMCErrors(d.m_particle)) << d.getString();
511  }
512  TEST_F(MCMatchingTest, KShortMissed)
513  {
514  //K0S not reconstructed
515  Decay d(431, { {323, {321, {111, {22, 22}} }}, { -311, {{310, {211, -211}}}}});
516  d.finalize();
517  //K0S and daughters are secondary
518  MCParticle* k0s = d.getMCParticle(310);
519  k0s->setStatus(k0s->getStatus() & (~MCParticle::c_PrimaryParticle)); //remove c_PrimaryParticle
520  MCParticle* pi1 = d.getMCParticle(211);
521  pi1->setStatus(pi1->getStatus() & (~MCParticle::c_PrimaryParticle));
522  MCParticle* pi2 = d.getMCParticle(-211);
523  pi2->setStatus(pi1->getStatus() & (~MCParticle::c_PrimaryParticle));
524 
525  d.reconstruct({431, { {323, {321, {111, {22, 22}} }}, 0}});
526  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
527  EXPECT_EQ(MCMatching::c_MissMassiveParticle | MCMatching::c_MissingResonance,
528  MCMatching::getMCErrors(d.m_particle)) << d.getString();
529  }
531  TEST_F(MCMatchingTest, PionWithOneGamma)
532  {
533  {
534  StoreArray<Particle> particles;
535  StoreArray<MCParticle> mcparticles;
536  Decay d(421, {321, -211, {111, {22, 22}}});
537  d.reconstruct({421, {321, -211, {111, {0, 22}}}});
538  EXPECT_EQ(mcparticles.getEntries(), 6);
539  EXPECT_EQ(particles.getEntries(), 5); //we added only 5 Particles
540  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
541  EXPECT_EQ(MCMatching::c_MissGamma, MCMatching::getMCErrors(d.m_particle)) << d.getString();
542  }
543  {
544  Decay d(421, {321, -211, {111, {22, 22}}});
545  d.reconstruct({421, {321, 0, {111, {0, 22}}}});
546  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
547  EXPECT_EQ(MCMatching::c_MissMassiveParticle | MCMatching::c_MissGamma, MCMatching::getMCErrors(d.m_particle)) << d.getString();
548  }
549  }
550  TEST_F(MCMatchingTest, TauWithResonance)
551  {
552  // Correct tau
553  {
554  StoreArray<Particle> particles;
555  StoreArray<MCParticle> mcparticles;
556  Decay d(15, {16, { -213, { -211, {111, {22, 22}}}}});
557  d.reconstruct({15, {0, { -213, { -211, {111, {22, 22}}}}}});
558  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
559  EXPECT_EQ(MCMatching::c_MissNeutrino, MCMatching::getMCErrors(d.m_particle)) << d.getString();
560  }
561  // Miss Resoanace
562  {
563  StoreArray<Particle> particles;
564  StoreArray<MCParticle> mcparticles;
565  Decay d(15, {16, { -213, { -211, {111, {22, 22}}}}});
566  d.reconstruct({15, {{ -211, {}, Decay::c_ReconstructFrom, &d[1][0]}, {111, {22, 22}, Decay::c_ReconstructFrom, &d[1][1]}}});
567  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
568  EXPECT_EQ(MCMatching::c_MissingResonance, MCMatching::getMCErrors(d.m_particle)) << d.getString();
569  }
570  // Miss Gamma
571  {
572  StoreArray<Particle> particles;
573  StoreArray<MCParticle> mcparticles;
574  Decay d(15, {16, { -213, { -211, {111, {22, 22}}}}});
575  d.reconstruct({15, {{ -211, {}, Decay::c_ReconstructFrom, &d[1][0]}, {111, {0, {22, {}, Decay::c_ReconstructFrom, &d[1][1][1]}}, Decay::c_ReconstructFrom, &d[1][1]}}});
576  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
577  EXPECT_EQ(MCMatching::c_MissGamma | MCMatching::c_MissingResonance, MCMatching::getMCErrors(d.m_particle)) << d.getString();
578  }
579  // Added Wrong Pion
580  {
581  StoreArray<Particle> particles;
582  StoreArray<MCParticle> mcparticles;
583  Decay g(-512, {211, -211, -16, {15, {16, { -213, { -211, {111, {22, 22}}}}}}});
584  Decay& d = g[3];
585  d.reconstruct({15, {{ -211, {}, Decay::c_ReconstructFrom, &g[1]}, {111, {22, 22}, Decay::c_ReconstructFrom, &d[1][1]}}});
586  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
587  EXPECT_EQ(MCMatching::c_MissMassiveParticle | MCMatching::c_MissingResonance | MCMatching::c_MissNeutrino |
588  MCMatching::c_AddedWrongParticle,
589  MCMatching::getMCErrors(d.m_particle)) << d.getString();
590  }
591 
592 
593  }
594  TEST_F(MCMatchingTest, MissGamma)
595  {
596  {
597  //D*+ -> D+ pi0
598  Decay d(431, {{421, {321, -211, {111, {22, 22}}}}, {111, {22, 22}}});
599  d.reconstruct({431, {{421, {321, -211, {111, {22, 22}}}}, {111, {22, 22}}}});
600  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
601  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(d.m_particle)) << d.getString();
602  }
603  {
604  //D*+ -> D+ pi0 reconstructed as D*+ -> D+ gamma
605  Decay d(431, {{421, {321, -211, {111, {22, 22}}}}, {111, {22, 22}}});
606  Decay& gamma = d[1][0]; //first gamma from second pi0
607  d.reconstruct({431, {{421, {321, -211, {111, {22, 22}}}}, {22, {}, Decay::c_ReconstructFrom, &gamma}}});
608  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
609  EXPECT_EQ(MCMatching::c_MissGamma | MCMatching::c_MissingResonance, MCMatching::getMCErrors(d.m_particle)) << d.getString();
610  }
611 
612  {
613  //D*+ -> D+ gamma
614  Decay d(431, {{421, {321, -211, {111, {22, 22}}}}, 22});
615  d.reconstruct({431, {{421, {321, -211, {111, {22, 22}}}}, 22}});
616  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
617  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(d.m_particle)) << d.getString();
618  }
619  {
620  //pi0 -> e+ e- gamma
621  Decay d(111, {11, -11, 22});
622  d.reconstruct({111, {11, -11, 22}});
623  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
624  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(d.m_particle)) << d.getString();
625  }
626  {
627  //pi0 -> e+ e- gamma reconstructed without gamma
628  Decay d(111, {11, -11, 22});
629  d.reconstruct({111, {11, -11, 0}});
630  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
631  EXPECT_EQ(MCMatching::c_MissGamma, MCMatching::getMCErrors(d.m_particle)) << d.getString();
632  }
633  {
634  //pi0 -> 2 gamma, with both clusters coming from same photon
635  Decay d(111, {22, 22});
636  Decay& gamma = d[0];
637  d.reconstruct({111, {22, {22, {}, Decay::c_ReconstructFrom, &gamma}}});
638  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
639  //MCMatch of pi0 is first gamma
640  EXPECT_EQ(MCMatching::c_AddedWrongParticle, MCMatching::getMCErrors(d.m_particle)) << d.getString();
641  }
642  {
643  //pi0 -> 4 gamma
644  Decay d(111, {22, 22, 22, 22});
645  d.reconstruct({111, {22, 22, 22, 22}});
646  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
647  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(d.m_particle)) << d.getString();
648  }
649  {
650  //pi0 -> 4 gamma as 2 gamma
651  Decay d(111, {22, 22, 22, 22});
652  d.reconstruct({111, {22, 22, 0, 0}});
653  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
654  EXPECT_EQ(MCMatching::c_MissGamma, MCMatching::getMCErrors(d.m_particle)) << d.getString();
655  }
656  {
657  //pi0 -> 4 gamma, with two clusters coming from same photon
658  Decay d(111, {22, 22, 22, 22});
659  Decay& gamma = d[0];
660  d.reconstruct({111, {22, 22, 22, {22, {}, Decay::c_ReconstructFrom, &gamma}}});
661  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
662  EXPECT_EQ(MCMatching::c_MissGamma, MCMatching::getMCErrors(d.m_particle)) << d.getString();
663  }
664  }
666  TEST_F(MCMatchingTest, WrongPhotonForPi0)
667  {
668  {
669  Decay d(521, {211, Decay(421, {321, -211, Decay(111, {22, 22})}), 22});
670  d.finalize();
671  d.reconstruct({521, {211, {421, {321, -211, {111, {{22}, {22, {}, Decay::c_RelateWith, d.getMCParticle(211)}}}}}}});
672  //result: pi0 gets MC match 521.
673  //Gets misID & c_AddedWrongParticle because of 'wrong' photon,
674  //plus c_MissMassiveParticle since the B's daughters are missing,
675  //plus c_MissGamma because one photon was not reconstructed,
676  //plus c_MissingResonance because non-FSPs were missed (MC matched particle (521) has lots of daughters)
677 
678  Particle* pi0 = d.getParticle(111);
679  Decay* pi0decay = d.getDecay(111);
680  ASSERT_TRUE(MCMatching::setMCTruth(pi0)) << pi0decay->getString();
681  EXPECT_EQ(521, pi0->getRelated<MCParticle>()->getPDG());
682  EXPECT_EQ(MCMatching::c_MisID | MCMatching::c_AddedWrongParticle | MCMatching::c_MissMassiveParticle | MCMatching::c_MissGamma |
683  MCMatching::c_MissingResonance,
684  MCMatching::getMCErrors(pi0)) << pi0decay->getString();
685 
686  //flags migrate upstream
687  Particle* p = d.getParticle(421);
688  Decay* d0decay = d.getDecay(421);
689  ASSERT_TRUE(MCMatching::setMCTruth(p)) << d0decay->getString();
690  EXPECT_EQ(MCMatching::c_MisID | MCMatching::c_AddedWrongParticle | MCMatching::c_MissGamma | MCMatching::c_MissingResonance,
691  MCMatching::getMCErrors(p)) << d0decay->getString();
692 
693  //even with addedWrongParticle (inherited from daughter), missFSR should be detected.
694  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
695  EXPECT_EQ(MCMatching::c_MisID | MCMatching::c_AddedWrongParticle | MCMatching::c_MissGamma | MCMatching::c_MissingResonance,
696  MCMatching::getMCErrors(d.m_particle)) << d.getString();
697  }
698  }
699 
701  TEST_F(MCMatchingTest, DecayInFlightCorrect)
702  {
703  {
704  Decay d(421, {321, { -211, {13}}, {111, {22, 22}}});
705  d.finalize();
706  MCParticle* muon = d.getMCParticle(13);
707  muon->setStatus(muon->getStatus() & (~MCParticle::c_PrimaryParticle)); //remove c_PrimaryParticle
708  ASSERT_FALSE(muon->hasStatus(MCParticle::c_PrimaryParticle));
709  d.reconstruct({421, {321, -211, {111, {22, 22}}}});
710 
711  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
712  EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<MCParticle>()->getPDG());
713  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(d.m_particle)) << d.getString();
714  }
715  {
716  Decay d(421, {{321, {11, -12, {111, {22, 22}}}}, -211, {111, {22, 22}}});
717  d.reconstruct({421, {321, -211, {111, {22, 22}}}});
718 
719  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
720  EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<MCParticle>()->getPDG());
721  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(d.m_particle)) << d.getString();
722  }
723  }
725  TEST_F(MCMatchingTest, DecayInFlight)
726  {
727  {
728  Decay d(-211, {13});
729  d.finalize();
730  MCParticle* muon = d.getMCParticle(13);
731  muon->setStatus(muon->getStatus() & (~MCParticle::c_PrimaryParticle)); //remove c_PrimaryParticle
732  d.reconstruct({ -211, {}, Decay::c_RelateWith, muon});
733 
734  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
735  EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<MCParticle>()->getPDG());
736  EXPECT_EQ(MCMatching::c_DecayInFlight, MCMatching::getMCErrors(d.m_particle)) << d.getString();
737  }
738  {
739  Decay d(421, {321, { -211, {13}}, {111, {22, 22}}});
740  d.finalize();
741  MCParticle* muon = d.getMCParticle(13);
742  muon->setStatus(muon->getStatus() & (~MCParticle::c_PrimaryParticle)); //remove c_PrimaryParticle
743  d.reconstruct({421, {321, { -211, {}, Decay::c_RelateWith, muon}, {111, {22, 22}}}});
744 
745 
746  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
747  EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<MCParticle>()->getPDG());
748  EXPECT_EQ(MCMatching::c_DecayInFlight, MCMatching::getMCErrors(d.m_particle)) << d.getString();
749  }
750  }
752  TEST_F(MCMatchingTest, CorrectFSPsWrongDecay)
753  {
754  {
755  Decay d(-413, {{ -411, {321, -211, -211}}, {111, {22, 22}}});
756 
757  Decay& pi0 = d[1];
758  Decay& pi2 = d[0][2];
759 
760  ASSERT_TRUE(d.getDecay(111) == &pi0);
761 
762  d.reconstruct({ -413, {{ -421, {321, -211, {111, {22, 22}, Decay::c_ReconstructFrom, &pi0}}}, { -211, {}, Decay::c_ReconstructFrom, &pi2}}});
763 
764 
765  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
766  EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<MCParticle>()->getPDG());
767  //inherits c_AddedWrongParticle from D0, gets c_MissingResonance since D+ is missing
768  EXPECT_EQ(MCMatching::c_AddedWrongParticle | MCMatching::c_MissingResonance,
769  MCMatching::getMCErrors(d.m_particle)) << d.getString();
770  }
771  }
773  TEST_F(MCMatchingTest, WrongCombination)
774  {
776  {
777  Decay d(-413, {{ -421, {321, -211, {111, {22, 22}}}}, -211});
778 
779  Decay* pi1 = &(d[0][1]);
780  Decay* pi2 = &(d[1]);
781  ASSERT_TRUE(pi1->m_pdg == pi2->m_pdg);
782 
783  d.reconstruct({ -413, {{ -421, {321, { -211, {}, Decay::c_ReconstructFrom, pi2}, {111, {22, 22}}}}, { -211, {}, Decay::c_ReconstructFrom, pi1}}});
784 
785 
786  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
787  EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<MCParticle>()->getPDG());
788  //gets c_MissingResonance since none of the Particles got the D0 MCParticle as MC match
789  EXPECT_EQ(MCMatching::c_AddedWrongParticle | MCMatching::c_MissingResonance,
790  MCMatching::getMCErrors(d.m_particle)) << d.getString();
791  }
792 
794  {
795  Decay d(511, {{333, {321, -321}}, {333, {321, -321}}});
796 
797  Decay* k1 = &(d[0][1]);
798  Decay* k2 = &(d[1][1]);
799  ASSERT_TRUE(k1->m_pdg == k2->m_pdg);
800 
801  d.reconstruct({511, {
802  {333, {321, { -321, {}, Decay::c_ReconstructFrom, k2}}},
803  {333, {321, { -321, {}, Decay::c_ReconstructFrom, k1}}}
804  }
805  });
806 
807 
808  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
809  EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<MCParticle>()->getPDG());
810  //gets c_MissingResonance since none of the Particles got the phi MCParticle as MC match
811  EXPECT_EQ(MCMatching::c_AddedWrongParticle | MCMatching::c_MissingResonance,
812  MCMatching::getMCErrors(d.m_particle)) << d.getString();
813  }
814  }
816  TEST_F(MCMatchingTest, SelfCrossFeed)
817  {
818  {
819  Decay d(300533, {{511, {321, -211, {111, {22, 22}}}}, { -511, { -321, 211, {111, {22, 22}}}}});
820 
821  Decay* pi1 = &(d[0][2]);
822  Decay* pi2 = &(d[1][2]);
823  ASSERT_TRUE(pi1->m_pdg == pi2->m_pdg);
824 
825  d.reconstruct({300533, {
826  {511, {321, -211, {111, {22, 22}, Decay::c_ReconstructFrom, pi2}}},
827  { -511, { -321, 211, {111, {22, 22}, Decay::c_ReconstructFrom, pi1}}}
828  }
829  });
830 
831 
832  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
833  EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<MCParticle>()->getPDG());
834  //gets c_MissingResonance since none of the Particles got the B0/anti-B0 MCParticle as MC match
835  EXPECT_EQ(MCMatching::c_AddedWrongParticle | MCMatching::c_MissingResonance,
836  MCMatching::getMCErrors(d.m_particle)) << d.getString();
837  }
838  }
839 
840  TEST_F(MCMatchingTest, FlavouredD0Decay)
841  {
842  {
843  //ok
844  Decay d(421, { -321, 211});
845  d.reconstruct({421, { -321, 211}});
846  ASSERT_EQ(Particle::c_Flavored, d.m_particle->getFlavorType());
847 
848  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
849  EXPECT_EQ(d.m_particle->getPDGCode(), d.m_particle->getRelated<MCParticle>()->getPDG());
850  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(d.m_particle)) << d.getString();
851  }
852  {
853  //also exists, but suppressed
854  Decay d(-421, { -321, 211});
855  d.reconstruct({ -421, { -321, 211}});
856  ASSERT_EQ(Particle::c_Flavored, d.m_particle->getFlavorType());
857 
858  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
859  EXPECT_EQ(d.m_particle->getPDGCode(), d.m_particle->getRelated<MCParticle>()->getPDG());
860  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(d.m_particle)) << d.getString();
861  }
862  {
863  //however, reconstructing the wrong D0 is not okay
864  Decay d(421, { -321, 211});
865  d.reconstruct({ -421, { -321, 211}});
866  ASSERT_EQ(Particle::c_Flavored, d.m_particle->getFlavorType());
867 
868  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
869  EXPECT_EQ(MCMatching::c_AddedWrongParticle, MCMatching::getMCErrors(d.m_particle)) << d.getString();
870  }
871  {
872  //however, reconstructing the wrong D0 is not okay
873  Decay d(-421, { -321, 211});
874  d.reconstruct({421, { -321, 211}});
875  ASSERT_EQ(Particle::c_Flavored, d.m_particle->getFlavorType());
876 
877  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
878  EXPECT_EQ(MCMatching::c_AddedWrongParticle, MCMatching::getMCErrors(d.m_particle)) << d.getString();
879  }
880  }
881 
882  TEST_F(MCMatchingTest, UnflavouredD0Decay)
883  {
884  {
885  //ok
886  Decay d(421, { -321, 321});
887  d.reconstruct({421, { -321, 321}});
888  ASSERT_EQ(Particle::c_Unflavored, d.m_particle->getFlavorType());
889 
890  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
891  EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<MCParticle>()->getPDG());
892  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(d.m_particle)) << d.getString();
893  }
894  {
895  //ok
896  Decay d(-421, { -321, 321});
897  d.reconstruct({ -421, { -321, 321}});
898  ASSERT_EQ(Particle::c_Unflavored, d.m_particle->getFlavorType());
899 
900  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
901  EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<MCParticle>()->getPDG());
902  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(d.m_particle)) << d.getString();
903  }
904  {
905  //we don't know the flavour, so this is also fine
906  Decay d(421, { -321, 321});
907  d.reconstruct({ -421, { -321, 321}});
908  ASSERT_EQ(Particle::c_Unflavored, d.m_particle->getFlavorType());
909 
910  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
911  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(d.m_particle)) << d.getString();
912  }
913  {
914  //we don't know the flavour, so this is also fine
915  Decay d(-421, { -321, 321});
916  d.reconstruct({421, { -321, 321}});
917  ASSERT_EQ(Particle::c_Unflavored, d.m_particle->getFlavorType());
918 
919  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
920  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(d.m_particle)) << d.getString();
921  }
922  }
923 
924  //B0 -> rho+ D-
925  TEST_F(MCMatchingTest, MissingResonance)
926  {
927  //explicitly reconstruct the rho
928  {
929  Decay d(511, {{ -411, { -321, 321, 211}}, {213, {211, {111, {22, 22}}}}});
930  d.reconstruct({511, {{ -411, { -321, 321, 211}}, {213, {211, {111, {22, 22}}}}}});
931 
932  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
933  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(d.m_particle)) << d.getString();
934  }
935  //missing rho
936  {
937  Decay d(511, {{ -411, { -321, 321, 211}}, {213, {211, {111, {22, 22}}}}});
938  //d.reconstruct({511, {{-411, {-321, 321, 211}}, {0, {211, {111, {22, 22}}}}}});
939  Decay* piplus = &(d[1][0]);
940  Decay* pi0 = &(d[1][1]);
941 
942  d.reconstruct({511, {{ -411, { -321, 321, 211}}, {211, {}, Decay::c_ReconstructFrom, piplus}, {111, {22, 22}, Decay::c_ReconstructFrom, pi0}}});
943 
944  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
945  EXPECT_EQ(MCMatching::c_MissingResonance, MCMatching::getMCErrors(d.m_particle)) << d.getString();
946  }
947  }
948 
949  TEST_F(MCMatchingTest, MissingFSPReplacedBySecondary)
950  {
951  Decay d(521, {{ -421, {321, { -211, {22, -211}}}}, 211, 211, -211});
952  Decay* pi = &(d[0][1][1]);
953  d.reconstruct({521, {{ -421, {321, -211}}, 211, 211, {
954  -211, {},
955  Decay::c_ReconstructFrom, pi
956  }
957  }
958  });
959  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
960  EXPECT_EQ(MCMatching::c_MissMassiveParticle, MCMatching::getMCErrors(d.m_particle)) << d.getString();
961  }
962  TEST_F(MCMatchingTest, BeamBackground)
963  {
964  Decay d(421, {321, -211, {111, {22, 22}}});
965  d.finalize();
966  MCParticle* noParticle = nullptr;
967  d.reconstruct({421, {321, { -211, {}, Decay::c_RelateWith, noParticle}, {111, {22, 22}}}});
968 
969  //no common mother
970  ASSERT_FALSE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
971  EXPECT_EQ(MCMatching::c_InternalError, MCMatching::getMCErrors(d.m_particle)) << d.getString();
972  EXPECT_EQ(nullptr, d.m_particle->getRelated<MCParticle>()) << d.getString();
973  }
974 
975  TEST_F(MCMatchingTest, DuplicateTrack)
976  {
977  {
978  Decay d(421, {321, -211, {111, {22, 22}}});
979  d.finalize();
980  MCParticle* kaon = d.getMCParticle(321);
981  ASSERT_TRUE(kaon != nullptr);
982  //tracks for the same MCParticle used twice:
983  d.reconstruct({421, {321, { -211, {}, Decay::c_RelateWith, kaon}, {111, {22, 22}}}});
984 
985  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
986  EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<MCParticle>()->getPDG());
987  EXPECT_EQ(MCMatching::c_MissMassiveParticle | MCMatching::c_MisID, MCMatching::getMCErrors(d.m_particle)) << d.getString();
988  }
989  }
990 
992  TEST_F(MCMatchingTest, MissingFSRMissingPHOTOS)
993  {
994  {
995  Decay d(521, { -11, 12, 22});
996  d.finalize();
997  MCParticle* photon = d.getMCParticle(22);
998  EXPECT_FALSE(MCMatching::isFSR(photon));
999 
1000  d.reconstruct({521, { -11}});
1001  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
1002  EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<MCParticle>()->getPDG());
1003  EXPECT_EQ(MCMatching::c_MissGamma | MCMatching::c_MissNeutrino, MCMatching::getMCErrors(d.m_particle)) << d.getString();
1004 
1005  }
1006  {
1007  //ISR flag should not trigger anything special
1008  Decay d(521, { -11, 12, 22});
1009  d.finalize();
1010  MCParticle* photon = d.getMCParticle(22);
1011  photon->setStatus(MCParticle::c_PrimaryParticle | MCParticle::c_IsISRPhoton);
1012  EXPECT_FALSE(MCMatching::isFSR(photon));
1013 
1014  d.reconstruct({521, { -11}});
1015  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
1016  EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<MCParticle>()->getPDG());
1017  EXPECT_EQ(MCMatching::c_MissGamma | MCMatching::c_MissNeutrino, MCMatching::getMCErrors(d.m_particle)) << d.getString();
1018  }
1019 
1020  {
1021  //now try the same with FSR flag
1022  Decay d(521, { -11, 12, 22});
1023  d.finalize();
1024  MCParticle* photon = d.getMCParticle(22);
1025  photon->setStatus(MCParticle::c_PrimaryParticle | MCParticle::c_IsFSRPhoton);
1026  EXPECT_TRUE(MCMatching::isFSR(photon));
1027 
1028  d.reconstruct({521, { -11}});
1029  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
1030  EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<MCParticle>()->getPDG());
1031  EXPECT_EQ(MCMatching::c_MissFSR | MCMatching::c_MissNeutrino, MCMatching::getMCErrors(d.m_particle)) << d.getString();
1032  }
1033 
1034  {
1035  //now try PHOTOS photon
1036  Decay d(521, { -11, 12, 22});
1037  d.finalize();
1038  MCParticle* photon = d.getMCParticle(22);
1039  photon->setStatus(MCParticle::c_PrimaryParticle | MCParticle::c_IsPHOTOSPhoton);
1040  EXPECT_FALSE(MCMatching::isFSR(photon));
1041 
1042  d.reconstruct({521, { -11}});
1043  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
1044  EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<MCParticle>()->getPDG());
1045  EXPECT_EQ(MCMatching::c_MissPHOTOS | MCMatching::c_MissNeutrino, MCMatching::getMCErrors(d.m_particle)) << d.getString();
1046  }
1047  }
1048 
1050  TEST_F(MCMatchingTest, UnspecifiedParticleReconstruction)
1051  {
1052  {
1054  Decay d(511, {{30343, {321, -211}}, -13, 13});
1055  d.reconstruct({511, {{30343, {321, -211}}, -13, 13}});
1056 
1057  Particle* Xsd = d.m_particle->getDaughters()[0];
1058  ASSERT_TRUE(Xsd != nullptr);
1059  EXPECT_EQ(Variable::particleIsUnspecified(Xsd), false);
1060  Xsd->setProperty(Particle::PropertyFlags::c_IsUnspecified);
1061  EXPECT_EQ(Variable::particleIsUnspecified(Xsd), true);
1062 
1063  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
1064  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(d.m_particle)) << d.getString();
1065  }
1066  {
1068  Decay d(511, {{313, {321, -211}}, -13, 13});
1069  d.reconstruct({511, {{30343, {321, -211}}, -13, 13}});
1070 
1071  Particle* Xsd = d.m_particle->getDaughters()[0];
1072  ASSERT_TRUE(Xsd != nullptr);
1073  EXPECT_EQ(Variable::particleIsUnspecified(Xsd), false);
1074  Xsd->setProperty(Particle::PropertyFlags::c_IsUnspecified);
1075  EXPECT_EQ(Variable::particleIsUnspecified(Xsd), true);
1076 
1077  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
1078  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(d.m_particle)) << d.getString();
1079  }
1080  {
1082  Decay d(511, { {313, {321, -211}}, {443, { -13, 13}}});
1083  Decay* mup = &(d[1][0]);
1084  Decay* mum = &(d[1][1]);
1085  d.reconstruct({511, {{30343, {321, -211}}, { -13, {}, Decay::c_ReconstructFrom, mup}, {13, {}, Decay::c_ReconstructFrom, mum}}});
1086 
1087  Particle* Xsd = d.m_particle->getDaughters()[0];
1088  ASSERT_TRUE(Xsd != nullptr);
1089  EXPECT_EQ(Variable::particleIsUnspecified(Xsd), false);
1090  Xsd->setProperty(Particle::PropertyFlags::c_IsUnspecified);
1091  EXPECT_EQ(Variable::particleIsUnspecified(Xsd), true);
1092 
1093  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
1094  EXPECT_EQ(MCMatching::c_MissingResonance, MCMatching::getMCErrors(d.m_particle)) << d.getString();
1095  }
1096  }
1097 
1099  TEST_F(MCMatchingTest, CountMissingParticle)
1100  {
1101  {
1102  // pi0 not reconstructed
1103  Decay d(421, {321, -211, {111, {22, 22}}});
1104  d.reconstruct({421, {321, -211, {0}}});
1105  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
1106  EXPECT_EQ(MCMatching::c_MissGamma | MCMatching::c_MissingResonance, MCMatching::getMCErrors(d.m_particle)) << d.getString();
1107  ASSERT_NE(nullptr, d.m_particle->getRelated<MCParticle>()) << d.getString();
1108  vector<int> daughterPDG{111};
1109  EXPECT_EQ(MCMatching::countMissingParticle(d.m_particle, d.m_particle->getRelated<MCParticle>(), daughterPDG), 1);
1110  }
1111  {
1112  // pi not reconstructed
1113  Decay d(421, {321, -211, {111, {22, 22}}});
1114  d.reconstruct({421, {321, 0, {111, {22, 22}}}});
1115  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
1116  EXPECT_EQ(MCMatching::getMCErrors(d.m_particle), MCMatching::c_MissMassiveParticle) << d.getString();
1117  ASSERT_NE(nullptr, d.m_particle->getRelated<MCParticle>()) << d.getString();
1118  vector<int> daughterPDG{211};
1119  EXPECT_EQ(MCMatching::countMissingParticle(d.m_particle, d.m_particle->getRelated<MCParticle>(), daughterPDG), 1);
1120  }
1121  {
1122  // K not reconstructed
1123  Decay d(421, {321, -211, {111, {22, 22}}});
1124  d.reconstruct({421, {0, -211, {111, {22, 22}}}});
1125  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
1126  EXPECT_EQ(MCMatching::getMCErrors(d.m_particle), MCMatching::c_MissMassiveParticle) << d.getString();
1127  ASSERT_NE(nullptr, d.m_particle->getRelated<MCParticle>()) << d.getString();
1128  vector<int> daughterPDG{321};
1129  EXPECT_EQ(MCMatching::countMissingParticle(d.m_particle, d.m_particle->getRelated<MCParticle>(), daughterPDG), 1);
1130  }
1131  {
1132  // 2K not reconstructed
1133  Decay d(-521, { -321, {421, {321, -211, {111, {22, 22}}}}});
1134  d.reconstruct({ -521, {0, {421, {0, -211, {111, {22, 22}}}}}});
1135  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
1136  EXPECT_EQ(MCMatching::getMCErrors(d.m_particle), MCMatching::c_MissMassiveParticle) << d.getString();
1137  ASSERT_NE(nullptr, d.m_particle->getRelated<MCParticle>()) << d.getString();
1138  vector<int> daughterPDG{321};
1139  EXPECT_EQ(MCMatching::countMissingParticle(d.m_particle, d.m_particle->getRelated<MCParticle>(), daughterPDG), 2);
1140  }
1141  {
1142  //K0S not reconstructed
1143  Decay d(431, { {323, {321, {111, {22, 22}} }}, { -311, {{310, {211, -211}}}}});
1144  d.finalize();
1145  //K0S and daughters are secondary
1146  MCParticle* k0s = d.getMCParticle(310);
1147  k0s->setStatus(k0s->getStatus() & (~MCParticle::c_PrimaryParticle)); //remove c_PrimaryParticle
1148  MCParticle* pi1 = d.getMCParticle(211);
1149  pi1->setStatus(pi1->getStatus() & (~MCParticle::c_PrimaryParticle));
1150  MCParticle* pi2 = d.getMCParticle(-211);
1151  pi2->setStatus(pi1->getStatus() & (~MCParticle::c_PrimaryParticle));
1152 
1153  d.reconstruct({431, { {323, {321, {111, {22, 22}} }}, 0}});
1154  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
1155  EXPECT_EQ(MCMatching::c_MissMassiveParticle | MCMatching::c_MissingResonance,
1156  MCMatching::getMCErrors(d.m_particle)) << d.getString();
1157  ASSERT_NE(nullptr, d.m_particle->getRelated<MCParticle>()) << d.getString();
1158  vector<int> daughterPDG{310};
1159  EXPECT_EQ(MCMatching::countMissingParticle(d.m_particle, d.m_particle->getRelated<MCParticle>(), daughterPDG), 1);
1160  }
1161  {
1162  //K0L not reconstructed
1163  Decay d(431, { {323, {321, {111, {22, 22}} }}, { -311, {130}}});
1164  d.finalize();
1165  //K0L and daughters are secondary
1166  MCParticle* k0l = d.getMCParticle(130);
1167  k0l->setStatus(k0l->getStatus() & (~MCParticle::c_PrimaryParticle)); //remove c_PrimaryParticle
1168 
1169  d.reconstruct({431, { {323, {321, {111, {22, 22}} }}, 0}});
1170  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
1171  EXPECT_EQ(MCMatching::c_MissKlong | MCMatching::c_MissMassiveParticle | MCMatching::c_MissingResonance,
1172  MCMatching::getMCErrors(d.m_particle)) << d.getString();
1173  ASSERT_NE(nullptr, d.m_particle->getRelated<MCParticle>()) << d.getString();
1174  vector<int> daughterPDG{130};
1175  EXPECT_EQ(MCMatching::countMissingParticle(d.m_particle, d.m_particle->getRelated<MCParticle>(), daughterPDG), 1);
1176  }
1177  {
1178  // e and nutrino not reconstructed
1179  Decay d(521, { -11, 12, 22});
1180  d.reconstruct({521, {0, 0, 22}});
1181  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
1182  EXPECT_EQ(MCMatching::c_MissNeutrino | MCMatching::c_MissMassiveParticle,
1183  MCMatching::getMCErrors(d.m_particle)) << d.getString();
1184  ASSERT_NE(nullptr, d.m_particle->getRelated<MCParticle>()) << d.getString();
1185  vector<int> daughterPDG_E{11};
1186  EXPECT_EQ(MCMatching::countMissingParticle(d.m_particle, d.m_particle->getRelated<MCParticle>(), daughterPDG_E), 1);
1187  vector<int> daughterPDG_NuE{12};
1188  EXPECT_EQ(MCMatching::countMissingParticle(d.m_particle, d.m_particle->getRelated<MCParticle>(), daughterPDG_NuE), 1);
1189  vector<int> daughterPDG_Nu{12, 14, 16};
1190  EXPECT_EQ(MCMatching::countMissingParticle(d.m_particle, d.m_particle->getRelated<MCParticle>(), daughterPDG_Nu), 1);
1191  }
1192  {
1193  // e and nutrino not reconstructed
1194  Decay d(521, { -13, 14, 22});
1195  d.reconstruct({521, {0, 0, 22}});
1196  ASSERT_TRUE(MCMatching::setMCTruth(d.m_particle)) << d.getString();
1197  EXPECT_EQ(MCMatching::c_MissNeutrino | MCMatching::c_MissMassiveParticle,
1198  MCMatching::getMCErrors(d.m_particle)) << d.getString();
1199  ASSERT_NE(nullptr, d.m_particle->getRelated<MCParticle>()) << d.getString();
1200  vector<int> daughterPDG_Mu{13};
1201  EXPECT_EQ(MCMatching::countMissingParticle(d.m_particle, d.m_particle->getRelated<MCParticle>(), daughterPDG_Mu), 1);
1202  vector<int> daughterPDG_NuMu{14};
1203  EXPECT_EQ(MCMatching::countMissingParticle(d.m_particle, d.m_particle->getRelated<MCParticle>(), daughterPDG_NuMu), 1);
1204  vector<int> daughterPDG_Nu{12, 14, 16};
1205  EXPECT_EQ(MCMatching::countMissingParticle(d.m_particle, d.m_particle->getRelated<MCParticle>(), daughterPDG_Nu), 1);
1206  }
1207 
1208  }
1209 
1211  TEST_F(MCMatchingTest, IsSignalBehavior)
1212  {
1213  {
1215  Decay d(511, { {313, {321, -211}}, {443, { -11, 11, 22}}});
1216  Decay* ep = &(d[1][0]);
1217  Decay* em = &(d[1][1]);
1218 
1220  d.reconstruct({511, {{313, {321, -211}}, { -11, {}, Decay::c_ReconstructFrom, ep}, {11, {}, Decay::c_ReconstructFrom, em}}});
1221 
1222  MCParticle* photon = d.getMCParticle(22);
1223  photon->setStatus(MCParticle::c_PrimaryParticle | MCParticle::c_IsPHOTOSPhoton);
1224 
1225  Particle* B = d.m_particle;
1226 
1227  // '=exact=>' c_Ordinary
1228  B->setProperty(Particle::PropertyFlags::c_Ordinary);
1229  ASSERT_TRUE(MCMatching::setMCTruth(B)) << d.getString();
1230  EXPECT_EQ(MCMatching::c_MissingResonance | MCMatching::c_MissPHOTOS, MCMatching::getMCErrors(B)) << d.getString();
1231  EXPECT_EQ(Variable::isSignal(B), 0.0) << d.getString();
1232 
1233  B->removeExtraInfo();
1234 
1235  // '=norad=>' c_IsIgnoreIntermediate
1236  B->setProperty(Particle::PropertyFlags::c_IsIgnoreIntermediate);
1237  ASSERT_TRUE(MCMatching::setMCTruth(B)) << d.getString();
1238  EXPECT_EQ(MCMatching::c_MissPHOTOS, MCMatching::getMCErrors(B)) << d.getString();
1239  EXPECT_EQ(Variable::isSignal(B), 0.0) << d.getString();
1240 
1241  B->removeExtraInfo();
1242 
1243  // '=direct=>' c_IsIgnoreRadiatedPhotons
1244  B->setProperty(Particle::PropertyFlags::c_IsIgnoreRadiatedPhotons);
1245  ASSERT_TRUE(MCMatching::setMCTruth(B)) << d.getString();
1246  EXPECT_EQ(MCMatching::c_MissingResonance, MCMatching::getMCErrors(B)) << d.getString();
1247  EXPECT_EQ(Variable::isSignal(B), 0.0) << d.getString();
1248 
1249  B->removeExtraInfo();
1250 
1251  // '->' c_IsIgnoreRadiatedPhotons and c_IsIgnoreIntermediate
1252  B->setProperty(Particle::PropertyFlags::c_IsIgnoreRadiatedPhotons | Particle::PropertyFlags::c_IsIgnoreIntermediate);
1253  ASSERT_TRUE(MCMatching::setMCTruth(B)) << d.getString();
1254  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(B)) << d.getString();
1255  EXPECT_EQ(Variable::isSignal(B), 1.0) << d.getString();
1256  }
1257  }
1258 
1259 
1260  TEST_F(MCMatchingTest, MissingFlagsOfDaughters)
1261  {
1262  {
1264  Decay d(300553, { {511, { -13, 13, 321, -211, {111, {22, 22}}}}, {511, {{ -411, {321, -211, -211}}, 211}} });
1265 
1267  d.reconstruct({300553, { {511, { -13, 13, 0, 0, {0, {0, 0}}}}, {511, {{ -411, {321, -211, -211}}, 211}} } });
1268 
1269  Particle* Y4S = d.m_particle;
1270  Particle* B1 = d.m_particle->getDaughters()[0];
1271  Particle* B2 = d.m_particle->getDaughters()[1];
1272 
1273  // don't set any properties
1274  ASSERT_TRUE(MCMatching::setMCTruth(B1)) << d.getString();
1275  EXPECT_EQ(MCMatching::c_MissingResonance | MCMatching::c_MissGamma | MCMatching::c_MissMassiveParticle,
1276  MCMatching::getMCErrors(B1)) << d.getString();
1277  EXPECT_EQ(Variable::isSignal(B1), 0.0) << d.getString();
1278 
1279  ASSERT_TRUE(MCMatching::setMCTruth(B2)) << d.getString();
1280  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(B2)) << d.getString();
1281  EXPECT_EQ(Variable::isSignal(B2), 1.0) << d.getString();
1282 
1283  ASSERT_TRUE(MCMatching::setMCTruth(Y4S)) << d.getString();
1284  EXPECT_EQ(Y4S->getProperty(), Particle::PropertyFlags::c_Ordinary) << d.getString();
1285  EXPECT_EQ(MCMatching::c_MissingResonance | MCMatching::c_MissGamma | MCMatching::c_MissMassiveParticle,
1286  MCMatching::getMCErrors(Y4S)) << d.getString();
1287  EXPECT_EQ(Variable::isSignal(Y4S), 0.0) << d.getString();
1288 
1289  }
1290  {
1292  Decay d(300553, { {511, { -13, 13, 321, -211, {111, {22, 22}}}}, {511, {{ -411, {321, -211, -211}}, 211}} });
1293 
1295  d.reconstruct({300553, { {511, { -13, 13, 0, 0, {0, {0, 0}}}}, {511, {{ -411, {321, -211, -211}}, 211}} } });
1296 
1297  Particle* Y4S = d.m_particle;
1298  Particle* B1 = d.m_particle->getDaughters()[0];
1299  Particle* B2 = d.m_particle->getDaughters()[1];
1300 
1301  int isIgnoreMissing = Particle::PropertyFlags::c_IsIgnoreRadiatedPhotons |
1302  Particle::PropertyFlags::c_IsIgnoreIntermediate |
1303  Particle::PropertyFlags::c_IsIgnoreMassive |
1304  Particle::PropertyFlags::c_IsIgnoreNeutrino |
1305  Particle::PropertyFlags::c_IsIgnoreGamma;
1306 
1307  // set missing particle properties on B1
1308  B1->setProperty(isIgnoreMissing);
1309  ASSERT_TRUE(MCMatching::setMCTruth(B1)) << d.getString();
1310  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(B1)) << d.getString();
1311  EXPECT_EQ(Variable::isSignal(B1), 1.0) << d.getString();
1312 
1313 
1314  ASSERT_TRUE(MCMatching::setMCTruth(B2)) << d.getString();
1315  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(B2)) << d.getString();
1316  EXPECT_EQ(Variable::isSignal(B2), 1.0) << d.getString();
1317 
1318  ASSERT_TRUE(MCMatching::setMCTruth(Y4S)) << d.getString();
1319  EXPECT_EQ(Y4S->getProperty(), Particle::PropertyFlags::c_Ordinary) << d.getString();
1320  EXPECT_EQ(MCMatching::c_Correct, MCMatching::getMCErrors(Y4S)) << d.getString();
1321  EXPECT_EQ(Variable::isSignal(Y4S), 1.0) << d.getString();
1322 
1323  }
1324 
1325  {
1327  Decay d(511, {{ -411, { -211, 211, -211, {111, {22, 22}}}}, 211, {113, {211, -211}}});
1328 
1330  d.reconstruct({511, {{ -411, { -211, 0, 0, {111, {22, 22}}}}, 211, {0, {0, 0}}}});
1331 
1332  Particle* B = d.m_particle;
1333  Particle* D = d.m_particle->getDaughters()[0];
1334 
1335  // don't set any properties
1336 
1337  // D missed pi+ pi- -> c_MissMassiveParticle
1338  ASSERT_TRUE(MCMatching::setMCTruth(D)) << d.getString();
1339  EXPECT_EQ(MCMatching::c_MissMassiveParticle,
1340  MCMatching::getMCErrors(D)) << d.getString();
1341  EXPECT_EQ(Variable::isSignal(D), 0.0) << d.getString();
1342 
1343  // B missed [rho0 -> pi+ pi-] and D's daughters -> c_MissMassiveParticle and c_MissingResonance
1344  ASSERT_TRUE(MCMatching::setMCTruth(B)) << d.getString();
1345  EXPECT_EQ(MCMatching::c_MissingResonance | MCMatching::c_MissMassiveParticle,
1346  MCMatching::getMCErrors(B)) << d.getString();
1347  EXPECT_EQ(Variable::isSignal(B), 0.0) << d.getString();
1348  }
1349  {
1351  Decay d(511, {{ -411, { -211, 211, -211, {111, {22, 22}}}}, 211, {113, {211, -211}}});
1352 
1354  d.reconstruct({511, {{ -411, { -211, 0, 0, {111, {22, 22}}}}, 211, {0, {0, 0}}}});
1355 
1356  Particle* B = d.m_particle;
1357  Particle* D = d.m_particle->getDaughters()[0];
1358 
1359  int isIgnoreMissing = Particle::PropertyFlags::c_IsIgnoreIntermediate |
1360  Particle::PropertyFlags::c_IsIgnoreMassive;
1361  // set missing particle properties on B1
1362  B->setProperty(isIgnoreMissing);
1363 
1364  // D missed pi+ pi- -> c_MissMassiveParticle
1365  ASSERT_TRUE(MCMatching::setMCTruth(D)) << d.getString();
1366  EXPECT_EQ(MCMatching::c_MissMassiveParticle,
1367  MCMatching::getMCErrors(D)) << d.getString();
1368  EXPECT_EQ(Variable::isSignal(D), 0.0) << d.getString();
1369 
1370  // B missed [rho0 -> pi+ pi-] and D's daughters.
1371  // B should accept missing [rho0 -> pi+ pi-]. But the D's daughters are supposed to still fire the missing massive flag.
1372  // -> c_MissMassiveParticle
1373  ASSERT_TRUE(MCMatching::setMCTruth(B)) << d.getString();
1374  EXPECT_EQ(MCMatching::c_MissMassiveParticle,
1375  MCMatching::getMCErrors(B)) << d.getString();
1376  EXPECT_EQ(Variable::isSignal(B), 0.0) << d.getString();
1377  }
1378 
1379  }
1380 
1381 
1382 } // namespace
1383 #endif
Belle2::MCParticleGraph::generateList
void generateList(const std::string &name="", int options=c_setNothing)
Generates the MCParticle list and stores it in the StoreArray with the given name.
Definition: MCParticleGraph.cc:211
Belle2::Particle::getPDGCode
int getPDGCode(void) const
Returns PDG code.
Definition: Particle.h:380
Belle2::Particle::getProperty
int getProperty() const
Returns particle property as a bit pattern The values are defined in the PropertyFlags enum and descr...
Definition: Particle.h:424
prepareAsicCrosstalkSimDB.e
e
aux.
Definition: prepareAsicCrosstalkSimDB.py:53
Belle2::isFSP
bool isFSP(int pdg)
defines what is a final state particle for this purpose.
Definition: ParticleMCDecayStringModule.cc:201
Belle2::MCParticleGraph
Class to build, validate and sort a particle decay chain.
Definition: MCParticleGraph.h:48
Belle2::MCParticle::setStatus
void setStatus(unsigned short int status)
Set Status code for the particle.
Definition: MCParticle.h:354
Belle2::RelationsInterface::getRelated
T * getRelated(const std::string &name="", const std::string &namedRelation="") const
Get the object to or from which this object has a relation.
Definition: RelationsObject.h:280
Belle2::MCParticle::getStatus
unsigned int getStatus(unsigned short int bitmask=USHRT_MAX) const
Return status code of particle.
Definition: MCParticle.h:133
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::StoreObjPtr
Type-safe access to single objects in the data store.
Definition: ParticleList.h:33
Belle2::HTML::getString
std::string getString(const TMatrixFBase &matrix, int precision=2, bool color=true)
get HTML table representing a matrix.
Definition: HTML.cc:18
Belle2::MCParticle::setPDG
void setPDG(int pdg)
Set PDG code of the particle.
Definition: MCParticle.h:343
Belle2::MCParticle::getPDG
int getPDG() const
Return PDG code of particle.
Definition: MCParticle.h:123
Belle2::MCParticleGraph::addParticle
GraphParticle & addParticle()
Add new particle to the graph.
Definition: MCParticleGraph.h:305
Belle2::TEST_F
TEST_F(GlobalLabelTest, LargeNumberOfTimeDependentParameters)
Test large number of time-dep params for registration and retrieval.
Definition: globalLabel.cc:65
Belle2::Particle::getExtraInfo
float getExtraInfo(const std::string &name) const
Return given value if set.
Definition: Particle.cc:1177
Belle2::TEST
TEST(TestgetDetectorRegion, TestgetDetectorRegion)
Test Constructors.
Definition: utilityFunctions.cc:18
Belle2::MCParticle::getDaughters
std::vector< Belle2::MCParticle * > getDaughters() const
Get vector of all daughter particles, empty vector if none.
Definition: MCParticle.cc:51
Belle2::Particle
Class to store reconstructed particles.
Definition: Particle.h:77
Belle2::Particle::getFlavorType
EFlavorType getFlavorType() const
Returns flavor type of the decay (for FS particles: flavor type of particle)
Definition: Particle.h:395
Belle2::MCParticle
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:43
Belle2::StoreArray< MCParticle >
Belle2::MCParticleGraph::clear
void clear()
Reset particles and decay information to make the class reusable.
Definition: MCParticleGraph.h:298
Belle2::Particle::setProperty
void setProperty(const int properties)
sets m_properties
Definition: Particle.h:316
Belle2::StoreArray::getEntries
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:226
Belle2::MCParticleGraph::GraphParticle
Class to represent Particle data in graph.
Definition: MCParticleGraph.h:86
Belle2::MCParticleGraph::addDecay
void addDecay(GraphParticle &mother, GraphParticle &daughter)
Add decay information between two particles.
Definition: MCParticleGraph.h:313
Belle2::Particle::hasExtraInfo
bool hasExtraInfo(const std::string &name) const
Return wether the extra info with the given name is set.
Definition: Particle.cc:1154