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