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>
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>
20#include <gtest/gtest.h>
52 c_CreateNewMCParticle,
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)
62 m_graphParticle->
setPDG(m_pdg);
64 for (
const Decay& d : daughters) {
65 gParticleGraph.
addDecay(*m_graphParticle, *d.m_graphParticle);
72 gParticleGraph.
clear();
75 m_mcparticle = mcparticles[m_graphParticle->getIndex() - 1];
77 for (Decay& d : m_daughterDecays)
82 [[nodiscard]]
Particle* getParticle(
int pdg)
const
84 if (m_pdg == pdg and m_particle)
87 for (
auto& d : m_daughterDecays) {
95 [[nodiscard]]
MCParticle* getMCParticle(
int pdg)
const
97 if (m_pdg == pdg and m_mcparticle)
100 for (
auto& d : m_daughterDecays) {
108 Decay* getDecay(
int pdg)
113 for (
auto& d : m_daughterDecays) {
114 Decay* res = d.getDecay(pdg);
121 Decay& operator[](
int i) {
return m_daughterDecays[i]; }
124 struct ReconstructedDecay {
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) { }
134 vector<ReconstructedDecay> m_daughterDecays;
135 EBehavior m_behavior;
146 void reconstruct(ReconstructedDecay decay)
151 if (decay.m_behavior == c_CreateNewMCParticle) {
153 m_graphParticle->
setPDG(decay.m_pdg);
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);
167 if (isFSP(decay.m_pdg)) {
169 m_particle = particles.appendNew(m_graphParticle->get4Vector(), decay.m_pdg);
170 m_particle->addRelationTo(m_mcparticle);
173 if (!decay.m_daughterDecays.empty()) {
174 Decay* mcDecay =
this;
175 if (decay.m_behavior == c_ReconstructFrom) {
177 mcDecay = decay.m_optDecay;
179 std::vector<int> daughterIndices;
180 for (
unsigned int i = 0; i < decay.m_daughterDecays.size(); i++) {
182 ReconstructedDecay rd = decay.m_daughterDecays[i];
184 if (rd.m_behavior == c_ReconstructFrom) {
185 ASSERT_NE(rd.m_optDecay,
nullptr);
187 rd.m_optDecay =
nullptr;
188 rd.m_behavior = Decay::c_Default;
190 ASSERT_TRUE(decay.m_daughterDecays.size() > i);
191 d = &(mcDecay->m_daughterDecays[i]);
193 d->reconstruct({rd});
195 daughterIndices.push_back(d->m_particle->getArrayIndex());
198 if (decay.m_pdg != 0) {
200 std::vector<int> decaylist, decaybarlist;
201 for (
int idx : daughterIndices) {
202 const Particle* daughterPart = particles[idx];
204 decaylist.push_back(daughterPDG);
207 std::sort(decaylist.begin(), decaylist.end());
208 std::sort(decaybarlist.begin(), decaybarlist.end());
209 bool isUnflavored = (decaylist == decaybarlist);
211 m_particle = particles.appendNew(ROOT::Math::PxPyPzEVector(), decay.m_pdg,
218 [[nodiscard]]
string getString()
const {
return "Particles(MCParticles,MCMatch,Flags):\n" + getStringInternal(); }
221 vector<Decay> m_daughterDecays;
229 [[nodiscard]]
string getStringInternal(
int depth = 0)
const
233 for (
int i = 0; i < depth; i++)
244 s << m_mcparticle->
getPDG();
251 s <<
", " << mcMatch->
getPDG() <<
", ";
262 if (!m_daughterDecays.empty()) {
264 for (
const Decay& d : m_daughterDecays) {
265 s <<
"\n" << d.getStringInternal(depth + 1);
268 s <<
"\n" << spaces <<
"]";
276 class MCMatchingTest :
public ::testing::Test {
279 void SetUp()
override
285 particles.registerInDataStore();
287 particles.registerRelationTo(mcparticles);
291 void TearDown()
override
301 Decay d(111, {22, 22});
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]);
313 Decay e(111, {22, 22});
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]);
328 EXPECT_EQ(mcparticles.getEntries(), 7);
329 EXPECT_EQ(mcparticles[6]->getPDG(),
Const::pion.getPDGCode());
331 Decay g(421, {321, -211, {111, {22, 22}}});
333 EXPECT_EQ(3, g.m_mcparticle->getNDaughters());
334 EXPECT_EQ(mcparticles.getEntries(), 13);
338 TEST_F(MCMatchingTest, CorrectReconstruction)
343 Decay d(421, {321, -211, {111, {22, 22}}});
344 d.reconstruct({421, {321, -211, {111, {22, 22}}}});
347 EXPECT_EQ(mcparticles[0]->getPDG(), 421);
348 EXPECT_EQ(mcparticles[5]->getPDG(),
Const::photon.getPDGCode());
349 EXPECT_EQ(particles.getEntries(), 6);
351 ASSERT_NE(d.m_particle,
nullptr);
352 const auto& fspParticles = d.m_particle->getFinalStateDaughters();
353 EXPECT_EQ(fspParticles.size(), 4u);
355 for (
const Particle* p : fspParticles) {
359 EXPECT_TRUE(mcparticles[0] == d.m_mcparticle);
360 EXPECT_TRUE(mcparticles[0]->getRelated<Particle>() ==
nullptr);
361 EXPECT_TRUE(mcparticles[3]->getRelated<Particle>() ==
nullptr);
370 TEST_F(MCMatchingTest, SetMCTruthNeverRun)
372 Decay d(421, {321, -211, {111, {22, 22}}});
373 d.reconstruct({421, {211, -211, {111, {22, 22}}}});
375 EXPECT_EQ(
nullptr, d.m_particle->getRelated<
MCParticle>());
380 TEST_F(MCMatchingTest, SettingTruths)
382 Decay d(421, {321, -211, {111, {22, 22}}});
383 d.reconstruct({421, {211, -211, {111, {22, 22}}}});
387 EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
401 TEST_F(MCMatchingTest, MisID)
404 Decay d(421, {321, -211, {111, {22, 22}}});
405 d.reconstruct({421, {211, -211, {111, {22, 22}}}});
407 EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
412 Decay d(421, {321, -211, {111, {22, 22}}});
413 d.reconstruct({413, {321, -13, {111, {22, 22}}}});
418 Decay d(421, {321, -211, {111, {22, 22}}});
419 d.reconstruct({421, {321, 13, {111, {22, 22}}}});
424 Decay d(421, {321, -211, {111, {22, 22}}});
425 d.reconstruct({421, {211, 13, {111, {22, 22}}}});
431 Decay d(421, {321, -211, {111, {22, 22}}});
432 d.reconstruct({421, { -211, 321, {111, {22, 22}}}});
439 TEST_F(MCMatchingTest, MissingParticles)
443 Decay d(421, {321, -211, {111, {22, 22}}});
444 d.reconstruct({421, {321, -211, {0}}});
449 Decay d(421, {321, -211, {111, {22, 22}}});
450 d.reconstruct({421, {321, 0, {111, {22, 22}}}});
455 Decay d(421, {321, -211, {111, {22, 22}}});
456 d.reconstruct({421, {0, -211, {111, {22, 22}}}});
461 Decay d(421, {321, -211, {111, {22, 22}}});
462 d.reconstruct({421, {0, -13, {111, {22, 22}}}});
467 TEST_F(MCMatchingTest, KLongCorrect)
470 Decay d(431, { {323, {321, {111, {22, 22}} }}, { -311, {130}}});
476 d.reconstruct({431, { {323, {321, {111, {22, 22}} }}, {130, {}, Decay::c_ReconstructFrom, d.getDecay(130)}}});
480 TEST_F(MCMatchingTest, KLongMissed)
483 Decay d(431, { {323, {321, {111, {22, 22}} }}, { -311, {130}}});
489 d.reconstruct({431, { {323, {321, {111, {22, 22}} }}, 0}});
494 TEST_F(MCMatchingTest, KShortCorrect)
497 Decay d(431, { {323, {321, {111, {22, 22}} }}, { -311, {{310, {211, -211}}}}});
507 d.reconstruct({431, { {323, {321, {111, {22, 22}} }}, {310, {{211, {}, Decay::c_ReconstructFrom, d.getDecay(211)}, { -211, {}, Decay::c_ReconstructFrom, d.getDecay(-211)}}}}});
511 TEST_F(MCMatchingTest, KShortMissed)
514 Decay d(431, { {323, {321, {111, {22, 22}} }}, { -311, {{310, {211, -211}}}}});
524 d.reconstruct({431, { {323, {321, {111, {22, 22}} }}, 0}});
530 TEST_F(MCMatchingTest, PionWithOneGamma)
535 Decay d(421, {321, -211, {111, {22, 22}}});
536 d.reconstruct({421, {321, -211, {111, {0, 22}}}});
538 EXPECT_EQ(particles.getEntries(), 5);
543 Decay d(421, {321, -211, {111, {22, 22}}});
544 d.reconstruct({421, {321, 0, {111, {0, 22}}}});
549 TEST_F(MCMatchingTest, TauWithResonance)
553 Decay d(15, {16, { -213, { -211, {111, {22, 22}}}}});
554 d.reconstruct({15, {0, { -213, { -211, {111, {22, 22}}}}}});
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]}}});
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]}}});
574 Decay g(-512, {211, -211, -16, {15, {16, { -213, { -211, {111, {22, 22}}}}}}});
576 d.reconstruct({15, {{ -211, {}, Decay::c_ReconstructFrom, &g[1]}, {111, {22, 22}, Decay::c_ReconstructFrom, &d[1][1]}}});
585 TEST_F(MCMatchingTest, MissGamma)
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}}}});
596 Decay d(431, {{421, {321, -211, {111, {22, 22}}}}, {111, {22, 22}}});
597 Decay& gamma = d[1][0];
598 d.reconstruct({431, {{421, {321, -211, {111, {22, 22}}}}, {22, {}, Decay::c_ReconstructFrom, &gamma}}});
605 Decay d(431, {{421, {321, -211, {111, {22, 22}}}}, 22});
606 d.reconstruct({431, {{421, {321, -211, {111, {22, 22}}}}, 22}});
612 Decay d(111, {11, -11, 22});
613 d.reconstruct({111, {11, -11, 22}});
619 Decay d(111, {11, -11, 22});
620 d.reconstruct({111, {11, -11, 0}});
626 Decay d(111, {22, 22});
628 d.reconstruct({111, {22, {22, {}, Decay::c_ReconstructFrom, &gamma}}});
635 Decay d(111, {22, 22, 22, 22});
636 d.reconstruct({111, {22, 22, 22, 22}});
642 Decay d(111, {22, 22, 22, 22});
643 d.reconstruct({111, {22, 22, 0, 0}});
649 Decay d(111, {22, 22, 22, 22});
651 d.reconstruct({111, {22, 22, 22, {22, {}, Decay::c_ReconstructFrom, &gamma}}});
657 TEST_F(MCMatchingTest, WrongPhotonForPi0)
660 Decay d(521, {211, Decay(421, {321, -211, Decay(111, {22, 22})}), 22});
662 d.reconstruct({521, {211, {421, {321, -211, {111, {{22}, {22, {}, Decay::c_RelateWith, d.getMCParticle(211)}}}}}}});
670 Decay* pi0decay = d.getDecay(111);
679 Decay* d0decay = d.getDecay(421);
692 TEST_F(MCMatchingTest, DecayInFlightCorrect)
695 Decay d(421, {321, { -211, {13}}, {111, {22, 22}}});
700 d.reconstruct({421, {321, -211, {111, {22, 22}}}});
703 EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
707 Decay d(421, {{321, {11, -12, {111, {22, 22}}}}, -211, {111, {22, 22}}});
708 d.reconstruct({421, {321, -211, {111, {22, 22}}}});
711 EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
716 TEST_F(MCMatchingTest, DecayInFlight)
723 d.reconstruct({ -211, {}, Decay::c_RelateWith, muon});
726 EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
730 Decay d(421, {321, { -211, {13}}, {111, {22, 22}}});
734 d.reconstruct({421, {321, { -211, {}, Decay::c_RelateWith, muon}, {111, {22, 22}}}});
738 EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
743 TEST_F(MCMatchingTest, CorrectFSPsWrongDecay)
746 Decay d(-413, {{ -411, {321, -211, -211}}, {111, {22, 22}}});
749 Decay& pi2 = d[0][2];
751 ASSERT_TRUE(d.getDecay(111) == &pi0);
753 d.reconstruct({ -413, {{ -421, {321, -211, {111, {22, 22}, Decay::c_ReconstructFrom, &pi0}}}, { -211, {}, Decay::c_ReconstructFrom, &pi2}}});
757 EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
764 TEST_F(MCMatchingTest, WrongCombination)
768 Decay d(-413, {{ -421, {321, -211, {111, {22, 22}}}}, -211});
770 Decay* pi1 = &(d[0][1]);
771 Decay* pi2 = &(d[1]);
772 ASSERT_TRUE(pi1->m_pdg == pi2->m_pdg);
774 d.reconstruct({ -413, {{ -421, {321, { -211, {}, Decay::c_ReconstructFrom, pi2}, {111, {22, 22}}}}, { -211, {}, Decay::c_ReconstructFrom, pi1}}});
778 EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
786 Decay d(511, {{333, {321, -321}}, {333, {321, -321}}});
788 Decay* k1 = &(d[0][1]);
789 Decay* k2 = &(d[1][1]);
790 ASSERT_TRUE(k1->m_pdg == k2->m_pdg);
792 d.reconstruct({511, {
793 {333, {321, { -321, {}, Decay::c_ReconstructFrom, k2}}},
794 {333, {321, { -321, {}, Decay::c_ReconstructFrom, k1}}}
800 EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
807 TEST_F(MCMatchingTest, SelfCrossFeed)
810 Decay d(300533, {{511, {321, -211, {111, {22, 22}}}}, { -511, { -321, 211, {111, {22, 22}}}}});
812 Decay* pi1 = &(d[0][2]);
813 Decay* pi2 = &(d[1][2]);
814 ASSERT_TRUE(pi1->m_pdg == pi2->m_pdg);
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}}}
824 EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
831 TEST_F(MCMatchingTest, FlavouredD0Decay)
835 Decay d(421, { -321, 211});
836 d.reconstruct({421, { -321, 211}});
840 EXPECT_EQ(d.m_particle->getPDGCode(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
845 Decay d(-421, { -321, 211});
846 d.reconstruct({ -421, { -321, 211}});
850 EXPECT_EQ(d.m_particle->getPDGCode(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
855 Decay d(421, { -321, 211});
856 d.reconstruct({ -421, { -321, 211}});
864 Decay d(-421, { -321, 211});
865 d.reconstruct({421, { -321, 211}});
873 TEST_F(MCMatchingTest, UnflavouredD0Decay)
877 Decay d(421, { -321, 321});
878 d.reconstruct({421, { -321, 321}});
882 EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
887 Decay d(-421, { -321, 321});
888 d.reconstruct({ -421, { -321, 321}});
892 EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
897 Decay d(421, { -321, 321});
898 d.reconstruct({ -421, { -321, 321}});
906 Decay d(-421, { -321, 321});
907 d.reconstruct({421, { -321, 321}});
916 TEST_F(MCMatchingTest, MissingResonance)
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}}}}}});
928 Decay d(511, {{ -411, { -321, 321, 211}}, {213, {211, {111, {22, 22}}}}});
930 Decay* piplus = &(d[1][0]);
931 Decay* pi0 = &(d[1][1]);
933 d.reconstruct({511, {{ -411, { -321, 321, 211}}, {211, {}, Decay::c_ReconstructFrom, piplus}, {111, {22, 22}, Decay::c_ReconstructFrom, pi0}}});
940 TEST_F(MCMatchingTest, MissingFSPReplacedBySecondary)
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, {
946 Decay::c_ReconstructFrom, pi
953 TEST_F(MCMatchingTest, BeamBackground)
955 Decay d(421, {321, -211, {111, {22, 22}}});
958 d.reconstruct({421, {321, { -211, {}, Decay::c_RelateWith, noParticle}, {111, {22, 22}}}});
963 EXPECT_EQ(
nullptr, d.m_particle->getRelated<
MCParticle>()) << d.getString();
966 TEST_F(MCMatchingTest, DuplicateTrack)
969 Decay d(421, {321, -211, {111, {22, 22}}});
972 ASSERT_TRUE(kaon !=
nullptr);
974 d.reconstruct({421, {321, { -211, {}, Decay::c_RelateWith, kaon}, {111, {22, 22}}}});
977 EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
983 TEST_F(MCMatchingTest, MissingFSRMissingPHOTOS)
986 Decay d(521, { -11, 12, 22});
991 d.reconstruct({521, { -11}});
993 EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
999 Decay d(521, { -11, 12, 22});
1005 d.reconstruct({521, { -11}});
1007 EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
1013 Decay d(521, { -11, 12, 22});
1019 d.reconstruct({521, { -11}});
1021 EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
1027 Decay d(521, { -11, 12, 22});
1033 d.reconstruct({521, { -11}});
1035 EXPECT_EQ(d.m_mcparticle->getPDG(), d.m_particle->getRelated<
MCParticle>()->
getPDG());
1041 TEST_F(MCMatchingTest, UnspecifiedParticleReconstruction)
1045 Decay d(511, {{30343, {321, -211}}, -13, 13});
1046 d.reconstruct({511, {{30343, {321, -211}}, -13, 13}});
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);
1059 Decay d(511, {{313, {321, -211}}, -13, 13});
1060 d.reconstruct({511, {{30343, {321, -211}}, -13, 13}});
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);
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}}});
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);
1090 TEST_F(MCMatchingTest, CountMissingParticle)
1094 Decay d(421, {321, -211, {111, {22, 22}}});
1095 d.reconstruct({421, {321, -211, {0}}});
1098 ASSERT_NE(
nullptr, d.m_particle->getRelated<
MCParticle>()) << d.getString();
1104 Decay d(421, {321, -211, {111, {22, 22}}});
1105 d.reconstruct({421, {321, 0, {111, {22, 22}}}});
1108 ASSERT_NE(
nullptr, d.m_particle->getRelated<
MCParticle>()) << d.getString();
1114 Decay d(421, {321, -211, {111, {22, 22}}});
1115 d.reconstruct({421, {0, -211, {111, {22, 22}}}});
1118 ASSERT_NE(
nullptr, d.m_particle->getRelated<
MCParticle>()) << d.getString();
1124 Decay d(-521, { -321, {421, {321, -211, {111, {22, 22}}}}});
1125 d.reconstruct({ -521, {0, {421, {0, -211, {111, {22, 22}}}}}});
1128 ASSERT_NE(
nullptr, d.m_particle->getRelated<
MCParticle>()) << d.getString();
1134 Decay d(431, { {323, {321, {111, {22, 22}} }}, { -311, {{310, {211, -211}}}}});
1144 d.reconstruct({431, { {323, {321, {111, {22, 22}} }}, 0}});
1148 ASSERT_NE(
nullptr, d.m_particle->getRelated<
MCParticle>()) << d.getString();
1154 Decay d(431, { {323, {321, {111, {22, 22}} }}, { -311, {130}}});
1160 d.reconstruct({431, { {323, {321, {111, {22, 22}} }}, 0}});
1164 ASSERT_NE(
nullptr, d.m_particle->getRelated<
MCParticle>()) << d.getString();
1170 Decay d(521, { -11, 12, 22});
1171 d.reconstruct({521, {0, 0, 22}});
1175 ASSERT_NE(
nullptr, d.m_particle->getRelated<
MCParticle>()) << d.getString();
1178 vector<int> daughterPDG_NuE{12};
1180 vector<int> daughterPDG_Nu{12, 14, 16};
1185 Decay d(521, { -13, 14, 22});
1186 d.reconstruct({521, {0, 0, 22}});
1190 ASSERT_NE(
nullptr, d.m_particle->getRelated<
MCParticle>()) << d.getString();
1193 vector<int> daughterPDG_NuMu{14};
1195 vector<int> daughterPDG_Nu{12, 14, 16};
1202 TEST_F(MCMatchingTest, IsSignalBehavior)
1206 Decay d(511, { {313, {321, -211}}, {443, { -11, 11, 22}}});
1207 Decay* ep = &(d[1][0]);
1208 Decay* em = &(d[1][1]);
1211 d.reconstruct({511, {{313, {321, -211}}, { -11, {}, Decay::c_ReconstructFrom, ep}, {11, {}, Decay::c_ReconstructFrom, em}}});
1219 B->setProperty(Particle::PropertyFlags::c_Ordinary);
1222 EXPECT_EQ(Variable::isSignal(B), 0.0) << d.getString();
1224 B->removeExtraInfo();
1227 B->setProperty(Particle::PropertyFlags::c_IsIgnoreIntermediate);
1230 EXPECT_EQ(Variable::isSignal(B), 0.0) << d.getString();
1232 B->removeExtraInfo();
1235 B->setProperty(Particle::PropertyFlags::c_IsIgnoreRadiatedPhotons);
1238 EXPECT_EQ(Variable::isSignal(B), 0.0) << d.getString();
1240 B->removeExtraInfo();
1243 B->setProperty(Particle::PropertyFlags::c_IsIgnoreRadiatedPhotons | Particle::PropertyFlags::c_IsIgnoreIntermediate);
1246 EXPECT_EQ(Variable::isSignal(B), 1.0) << d.getString();
1251 TEST_F(MCMatchingTest, MissingFlagsOfDaughters)
1255 Decay d(300553, { {511, { -13, 13, 321, -211, {111, {22, 22}}}}, {511, {{ -411, {321, -211, -211}}, 211}} });
1258 d.reconstruct({300553, { {511, { -13, 13, 0, 0, {0, {0, 0}}}}, {511, {{ -411, {321, -211, -211}}, 211}} } });
1261 Particle* B1 = d.m_particle->getDaughters()[0];
1262 Particle* B2 = d.m_particle->getDaughters()[1];
1268 EXPECT_EQ(Variable::isSignal(B1), 0.0) << d.getString();
1272 EXPECT_EQ(Variable::isSignal(B2), 1.0) << d.getString();
1275 EXPECT_EQ(Y4S->
getProperty(), Particle::PropertyFlags::c_Ordinary) << d.getString();
1278 EXPECT_EQ(Variable::isSignal(Y4S), 0.0) << d.getString();
1283 Decay d(300553, { {511, { -13, 13, 321, -211, {111, {22, 22}}}}, {511, {{ -411, {321, -211, -211}}, 211}} });
1286 d.reconstruct({300553, { {511, { -13, 13, 0, 0, {0, {0, 0}}}}, {511, {{ -411, {321, -211, -211}}, 211}} } });
1289 Particle* B1 = d.m_particle->getDaughters()[0];
1290 Particle* B2 = d.m_particle->getDaughters()[1];
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;
1302 EXPECT_EQ(Variable::isSignal(B1), 1.0) << d.getString();
1307 EXPECT_EQ(Variable::isSignal(B2), 1.0) << d.getString();
1310 EXPECT_EQ(Y4S->
getProperty(), Particle::PropertyFlags::c_Ordinary) << d.getString();
1312 EXPECT_EQ(Variable::isSignal(Y4S), 1.0) << d.getString();
1318 Decay d(511, {{ -411, { -211, 211, -211, {111, {22, 22}}}}, 211, {113, {211, -211}}});
1321 d.reconstruct({511, {{ -411, { -211, 0, 0, {111, {22, 22}}}}, 211, {0, {0, 0}}}});
1324 Particle* D = d.m_particle->getDaughters()[0];
1332 EXPECT_EQ(Variable::isSignal(D), 0.0) << d.getString();
1338 EXPECT_EQ(Variable::isSignal(B), 0.0) << d.getString();
1342 Decay d(511, {{ -411, { -211, 211, -211, {111, {22, 22}}}}, 211, {113, {211, -211}}});
1345 d.reconstruct({511, {{ -411, { -211, 0, 0, {111, {22, 22}}}}, 211, {0, {0, 0}}}});
1348 Particle* D = d.m_particle->getDaughters()[0];
1350 int isIgnoreMissing = Particle::PropertyFlags::c_IsIgnoreIntermediate |
1351 Particle::PropertyFlags::c_IsIgnoreMassive;
1353 B->setProperty(isIgnoreMissing);
1359 EXPECT_EQ(Variable::isSignal(D), 0.0) << d.getString();
1367 EXPECT_EQ(Variable::isSignal(B), 0.0) << d.getString();
int getPDGCode() const
PDG code.
static const ParticleType pi0
neutral pion particle
static const ChargedStable muon
muon particle
static const ChargedStable pion
charged pion particle
static const ParticleType Klong
K^0_L particle.
static const ParticleType Kshort
K^0_S particle.
static const ChargedStable kaon
charged kaon particle
static const ParticleType photon
photon particle
static const ChargedStable electron
electron particle
static DataStore & Instance()
Instance of singleton Store.
void reset(EDurability durability)
Frees memory occupied by data store items and removes all objects from the map.
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.
@ c_IsFSRPhoton
bit 7: Particle is from finial state radiation
@ c_IsPHOTOSPhoton
bit 8: Particle is an radiative photon from PHOTOS
@ c_PrimaryParticle
bit 0: Particle is primary particle.
@ c_IsISRPhoton
bit 6: Particle is from initial state radiation
std::vector< Belle2::MCParticle * > getDaughters() const
Get vector of all daughter particles, empty vector if none.
bool hasStatus(unsigned short int bitmask) const
Return if specific status bit is set.
unsigned int getStatus(unsigned short int bitmask=USHRT_MAX) const
Return status code of particle.
void setPDG(int pdg)
Set PDG code of the particle.
int getPDG() const
Return PDG code of particle.
void setStatus(unsigned short int status)
Set Status code for the particle.
Class to store reconstructed particles.
void setProperty(const int properties)
sets m_properties
bool hasExtraInfo(const std::string &name) const
Return whether the extra info with the given name is set.
EFlavorType getFlavorType() const
Returns flavor type of the decay (for FS particles: flavor type of particle)
int getPDGCode(void) const
Returns PDG code.
int getProperty() const
Returns particle property as a bit pattern The values are defined in the PropertyFlags enum and descr...
@ c_Unflavored
Is its own antiparticle or we don't know whether it is a particle/antiparticle.
@ c_Flavored
Is either particle or antiparticle.
double getExtraInfo(const std::string &name) const
Return given value if set.
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.
int getEntries() const
Get the number of objects in the array.
Type-safe access to single objects in the data store.
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.
Abstract base class for different kinds of events.
static int countMissingParticle(const Belle2::Particle *particle, const Belle2::MCParticle *mcParticle, const std::vector< int > &daughterPDG)
Count the number of missing daughters of the 'particle'.
static std::string explainFlags(unsigned int flags)
Return string with all human-readable flags, e.g.
@ c_MissMassiveParticle
A generated massive FSP is missing (not reconstructed).
@ c_MissFSR
A Final State Radiation (FSR) photon is not reconstructed (based on MCParticle::c_IsFSRPhoton).
@ c_AddedWrongParticle
A non-FSP Particle has wrong PDG code, meaning one of the daughters (or their daughters) belongs to a...
@ c_MissNeutrino
A neutrino is missing (not reconstructed).
@ c_Correct
This Particle and all its daughters are perfectly reconstructed.
@ c_DecayInFlight
A Particle was reconstructed from the secondary decay product of the actual particle.
@ c_InternalError
There was an error in MC matching.
@ c_MissingResonance
The associated MCParticle decay contained additional non-final-state particles (e....
@ c_MissPHOTOS
A photon created by PHOTOS was not reconstructed (based on MCParticle::c_IsPHOTOSPhoton)
@ c_MissGamma
A photon (not FSR) is missing (not reconstructed).
@ c_MisID
One of the charged final state particles is mis-identified, i.e.
@ c_MissKlong
A Klong is missing (not reconstructed).
static bool setMCTruth(const Belle2::Particle *particle)
This is the main function of MC matching algorithm.
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...
static bool isFSR(const Belle2::MCParticle *p)
Returns true if given MCParticle is a final state radiation (FSR) photon based on MCParticle::c_IsFSR...
static const std::string c_extraInfoMCErrors
Name of extra-info field stored in Particle.