25 std::pair<ParticleType, ParticleOrigin>
28 const EventContext& ctx =
info ?
info->eventContext : Gaudi::Hive::currentContext();
30 if (!truthParticleLinkVecReadHandle.
isValid()) {
31 ATH_MSG_WARNING(
" Invalid ReadHandle for xAODTruthParticleLinkVector with key: " << truthParticleLinkVecReadHandle.
key());
36 return particleTruthClassifier (*tplink,
info);
41 std::pair<ParticleType, ParticleOrigin>
46 if (!theGenPart)
return std::make_pair(partType, partOrig);
49 const EventContext& ctx =
info ?
info->eventContext : Gaudi::Hive::currentContext();
52 if (!truthParticleLinkVecReadHandle.
isValid()) {
53 ATH_MSG_WARNING(
" Invalid ReadHandle for xAODTruthParticleLinkVector with key: " << truthParticleLinkVecReadHandle.
key());
54 return std::make_pair(partType, partOrig);
56 for (
const auto *
const entry : *truthParticleLinkVecReadHandle) {
59 if (!theGenPart || !truthParticle ||
61 theGenPart->status() != truthParticle->
status() ||
64 "HepMC::GenParticle and xAOD::TruthParticle do not match");
65 return std::make_pair(partType, partOrig);
67 return particleTruthClassifier(truthParticle,
info);
70 return std::make_pair(partType, partOrig);
74 std::pair<ParticleType, ParticleOrigin>
84 return std::make_pair(partType, partOrig);
86 info.genPart = thePart;
90 if (!truthParticleContainerReadHandle.
isValid()) {
91 ATH_MSG_WARNING(
" Invalid ReadHandle for xAOD::TruthParticleContainer with key: " << truthParticleContainerReadHandle.
key());
92 return std::make_pair(partType, partOrig);
95 ATH_MSG_DEBUG(
"xAODTruthParticleContainer with key " << truthParticleContainerReadHandle.
key() <<
" has valid ReadHandle ");
144 partOrig = defOrigOfElectron(*truthParticleContainerReadHandle, thePart,
isPrompt,
info);
150 partOrig = defOrigOfMuon(*truthParticleContainerReadHandle, thePart,
isPrompt,
info);
153 if (!partProdVtx &&
MC::isTau(thePart)) {
155 partOrig = defOrigOfTau(*truthParticleContainerReadHandle, thePart, parentPDG,
info);
161 partOrig = defOrigOfPhoton(*truthParticleContainerReadHandle, thePart,
isPrompt,
info);
167 return std::make_pair(
Neutrino, partOrig);
173 if (isPartHadr)
return std::make_pair(
Hadron, partOrig);
199 partOrig = defOrigOfElectron(*truthParticleContainerReadHandle, thePart,
isPrompt,
info);
203 partOrig = defOrigOfMuon(*truthParticleContainerReadHandle, thePart,
isPrompt,
info);
206 partOrig = defOrigOfTau(*truthParticleContainerReadHandle, thePart, parentPDG,
info);
210 partOrig = defOrigOfPhoton(*truthParticleContainerReadHandle, thePart,
isPrompt,
info);
214 partOrig = defOrigOfNeutrino(*truthParticleContainerReadHandle, thePart,
isPrompt,
info);
219 return std::make_pair(partType, partOrig);
226 const int parentPDG =
parent->pdgId();
228 if (!aChild)
continue;
239 return TruthLoopDetectionMethod3(childOrigVtx,
parent);
257 parent_prdVtx =
parent->hasProdVtx() ?
parent->prodVtx() :
nullptr;
258 parent_endVtx =
parent->decayVtx();
262 return (child_endVtx == parent_prdVtx && child_prdVtx == parent_endVtx);
301 info.setMotherProperties(ancestor);
305 bool samePart = TruthLoopDetectionMethod1(partProdVtx, ancestor);
317 if (ancestor == ancestorParent) {
break; }
318 if (TruthLoopDetectionMethod2(ancestor,ancestorParent)) {
319 ancestorParent = ancestor;
324 if (ancestorParent) {
325 pPDG = ancestorParent->
pdgId();
327 ancestor = ancestorParent;
336 ancestor = ancestorParent;
340 info.setMotherProperties(ancestor);
341 const int ancestorPDG = ancestor->
pdgId();
348 auto DP = DecayProducts(partProdVtx);
349 const int NumOfPhot = DP.pd(MC::PHOTON);
350 const int NumOfEl = DP.pd(MC::ELECTRON);
351 const int NumOfPos = DP.pd(MC::POSITRON);
352 const int NumOfquark = DP.apd({MC::DQUARK,MC::UQUARK,MC::SQUARK,MC::CQUARK,MC::BQUARK,MC::TQUARK});
353 const int NumOfgluon = DP.apd(MC::GLUON);
354 const int NumOfElNeut = DP.apd(MC::NU_E);
355 const int NumOfLQ = DP.apd(MC::LEPTOQUARK);
356 const int NumOfMuPl = DP.pd(-MC::MUON);
357 const int NumOfMuMin = DP.pd(MC::MUON);
358 const int NumOfMuNeut = DP.apd(MC::NU_MU);
359 const int NumOfTau = DP.apd(MC::TAU);
360 const int NumOfTauNeut = DP.apd(MC::NU_TAU);
364 const bool possibleNuclearFragment = (numOfParents == 1 && (
MC::isPhoton(ancestorPDG) ||
MC::isElectron(ancestorPDG) ||
MC::isMuon(ancestorPDG) || std::abs(ancestorPDG) == MC::PIPLUS));
366 if (!aChild)
continue;
367 const int childPDG = aChild->pdgId();
369 if (possibleNuclearFragment &&
370 (
MC::isNucleus(childPDG) || childPDG == 0 || childPDG == MC::PROTON || childPDG == MC::NEUTRON ||
371 std::abs(childPDG) == MC::PIPLUS || std::abs(childPDG) == MC::PI0))
378 for (
const auto& photonParent: ancestorProdVtx->
particles_in()) {
379 if (!photonParent)
continue;
380 info.photonMother = photonParent;
384 if ((
MC::isPhoton(ancestorPDG) && numberOfChildren == 2 && NumOfEl == 1 && NumOfPos == 1) || (
MC::isPhoton(ancestorPDG) && numberOfChildren == 1 && (NumOfEl == 1 || NumOfPos == 1)))
return PhotonConv;
389 if (numOfParents == 1 && std::abs(ancestorPDG) == MC::PIPLUS && numberOfChildren > 2 && NumOfNucFr != 0)
return ElMagProc;
398 if (ancestorPDG == MC::ELECTRON && numberOfChildren == 2 && NumOfEl == 2 && NumOfPos == 0)
return ElMagProc;
401 if (ancestorPDG == MC::POSITRON && numberOfChildren == 2 && NumOfEl == 0 && NumOfPos == 2)
return ElMagProc;
408 if (numberOfChildren == 2 && (NumOfEl == 1 || NumOfPos == 1) && !
MC::isElectron(ancestorPDG) && samePart)
return ElMagProc;
410 if ((ancestorPDG == MC::PI0 && numberOfChildren == 3 && NumOfPhot == 1 && NumOfEl == 1 && NumOfPos == 1) ||
411 (ancestorPDG == MC::PI0 && numberOfChildren == 4 && NumOfPhot == 0 && NumOfEl == 2 && NumOfPos == 2))
415 if (
MC::isSMQuark(ancestorPDG) && numOfParents == 1 && numberOfChildren == 3 && NumOfquark == 1 && NumOfElNeut == 1)
return QuarkWeakDec;
427 prodVert = ptrPart->hasProdVtx() ? ptrPart->prodVtx() :
nullptr;
428 }
while (
MC::isW(ptrPart) && prodVert);
431 if (std::abs(ptrPart->pdgId()) == MC::RH_NU_E)
return NuREle;
432 if (std::abs(ptrPart->pdgId()) == MC::RH_NU_MU)
return NuRMu;
433 if (std::abs(ptrPart->pdgId()) == MC::RH_NU_TAU)
return NuRTau;
447 bool isZboson =
false;
448 bool isWboson =
false;
449 bool skipnext =
false;
451 for (
unsigned int ipOut = 0; ipOut + 1 < partProdVtx->
nOutgoingParticles(); ++ipOut) {
453 if (!aChild)
continue;
455 for (
unsigned int ipOut1 = ipOut + 1; ipOut1 < partProdVtx->
nOutgoingParticles(); ipOut1++) {
457 if (theNextChild)
break;
459 if (!theNextChild)
continue;
467 if (thePartToCheck == aChild || thePartToCheck == theNextChild) {
474 if (thePartToCheck == aChild || thePartToCheck == theNextChild) {
481 if (isWboson)
return WBoson;
482 if (isZboson)
return ZBoson;
484 if (numOfParents == 2) {
486 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && NumOfEl == 1 && NumOfPos == 1)
return ZBoson;
489 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && (NumOfEl == 1 || NumOfPos == 1) && NumOfElNeut == 1)
return WBoson;
494 if ((numberOfChildren - NumOfquark - NumOfgluon) == 4 &&
495 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 4) &&
499 if ((numberOfChildren - NumOfquark - NumOfgluon - NumOfPhot) == 6 &&
500 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 6) &&
505 if (partProdVtx == ancestorProdVtx) {
506 int NumOfEleLoop = 0;
507 int NumOfLepLoop = 0;
508 int NumOfEleNeuLoop = 0;
511 for (
const auto *
const pin: partProdVtx->
particles_in()) {
515 if (std::abs(
pout->pdgId()) == MC::NU_E) NumOfEleNeuLoop++;
520 if (NumOfEleLoop == 2 && NumOfEleNeuLoop == 0)
return ZBoson;
521 if (NumOfEleLoop == 1 && NumOfEleNeuLoop == 1)
return WBoson;
522 if ((NumOfEleLoop == 4 && NumOfEleNeuLoop == 0) || (NumOfEleLoop == 3 && NumOfEleNeuLoop == 1) ||
523 (NumOfEleLoop == 2 && NumOfEleNeuLoop == 2))
return DiBoson;
524 if (NumOfLepLoop == 4)
return DiBoson;
537 const ParticleOrigin tauOrig = defOrigOfTau(xTruthParticleContainer, ancestor, ancestorPDG,
info);
542 if (std::abs(ancestorPDG) == MC::WBOSON_LRSM)
return WBosonLRSM;
543 if (std::abs(ancestorPDG) == MC::RH_NU_E)
return NuREle;
544 if (std::abs(ancestorPDG) == MC::RH_NU_MU)
return NuRMu;
545 if (std::abs(ancestorPDG) == MC::RH_NU_TAU)
return NuRTau;
577 info.setMotherProperties(ancestor);
590 if (ancestor == ancestorParent) {
break; }
591 if (TruthLoopDetectionMethod2(ancestor,ancestorParent)) {
592 ancestorParent = ancestor;
597 if (ancestorParent) {
598 pPDG = ancestorParent->
pdgId();
601 ancestor = ancestorParent;
610 ancestor = ancestorParent;
614 info.setMotherProperties(ancestor);
615 const int ancestorPDG = ancestor->
pdgId();
622 auto DP = DecayProducts(partProdVtx);
623 const int NumOfPhot = DP.pd(MC::PHOTON);
624 const int NumOfEl = DP.pd(MC::ELECTRON);
625 const int NumOfPos = DP.pd(MC::POSITRON);
626 const int NumOfElNeut = DP.apd(MC::NU_E);
627 const int NumOfMuNeut = DP.apd(MC::NU_MU);
628 const int NumOfLQ = DP.apd(MC::LEPTOQUARK);
629 const int NumOfquark = DP.apd({MC::DQUARK,MC::UQUARK,MC::SQUARK,MC::CQUARK,MC::BQUARK,MC::TQUARK});
630 const int NumOfgluon = DP.apd(MC::GLUON);
631 const int NumOfMuPl = DP.pd(-MC::MUON);
632 const int NumOfMuMin = DP.pd(MC::MUON);
633 const int NumOfTau = DP.apd(MC::TAU);
634 const int NumOfTauNeut = DP.apd(MC::NU_TAU);
637 if (std::abs(ancestorPDG) == MC::PIPLUS && numberOfChildren == 2 && NumOfMuNeut == 1)
return PionDecay;
638 if (std::abs(ancestorPDG) == MC::KPLUS && numberOfChildren == 2 && NumOfMuNeut == 1)
return KaonDecay;
640 const ParticleOrigin tauOrig = defOrigOfTau(xTruthParticleContainer, ancestor, ancestorPDG,
info);
647 if (
MC::isSMQuark(ancestorPDG) && numOfParents == 1 && numberOfChildren == 3 && NumOfquark == 1 && NumOfMuNeut == 1)
return QuarkWeakDec;
655 }
while (
MC::isW(itrP) && prodVert);
658 if (std::abs(itrP->
pdgId()) == MC::RH_NU_E)
return NuREle;
659 if (std::abs(itrP->
pdgId()) == MC::RH_NU_MU)
return NuRMu;
660 if (std::abs(itrP->
pdgId()) == MC::RH_NU_TAU)
return NuRTau;
666 if (
MC::isPhoton(ancestorPDG) && numberOfChildren == 2 && NumOfMuMin == 1 && NumOfMuPl == 1)
return PhotonConv;
671 bool isZboson =
false;
672 bool isWboson =
false;
673 bool skipnext =
false;
674 for (
unsigned int ipOut = 0; ipOut + 1 < partProdVtx->
nOutgoingParticles(); ipOut++) {
680 if (!aChild)
continue;
682 for (
unsigned int ipOut1 = ipOut + 1; ipOut1 < partProdVtx->
nOutgoingParticles(); ipOut1++) {
684 if (theNextChild)
break;
686 if (!theNextChild)
continue;
689 if (thePriPart == aChild || thePriPart == theNextChild) {
694 }
else if (
MC::isMuon(aChild) && std::abs(theNextChild->pdgId()) == MC::NU_MU) {
696 if (thePriPart == aChild || thePriPart == theNextChild) {
703 if (isWboson)
return WBoson;
704 if (isZboson)
return ZBoson;
706 if (numOfParents == 2 ) {
708 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && NumOfMuPl == 1 && NumOfMuMin == 1)
return ZBoson;
712 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && (NumOfMuPl == 1 || NumOfMuMin == 1) && NumOfMuNeut == 1)
return WBoson;
717 if ((numberOfChildren - NumOfquark - NumOfgluon) == 4 &&
718 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 4) &&
722 if ((numberOfChildren - NumOfquark - NumOfgluon - NumOfPhot) == 6 &&
723 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 6) &&
728 if (partProdVtx == ancestorProdVtx) {
730 int NumOfMuNeuLoop = 0;
731 int NumOfLepLoop = 0;
738 if (std::abs(
pout->pdg_id()) == MC::NU_MU) NumOfMuNeuLoop++;
744 if (NumOfMuLoop == 2 && NumOfMuNeuLoop == 0)
return ZBoson;
745 if (NumOfMuLoop == 1 && NumOfMuNeuLoop == 1)
return WBoson;
746 if ((NumOfMuLoop == 4 && NumOfMuNeuLoop == 0) || (NumOfMuLoop == 3 && NumOfMuNeuLoop == 1) ||
747 (NumOfMuLoop == 2 && NumOfMuNeuLoop == 2))
return DiBoson;
748 if (NumOfLepLoop == 4)
return DiBoson;
759 if (std::abs(ancestorPDG) == MC::WBOSON_LRSM)
return WBosonLRSM;
760 if (std::abs(ancestorPDG) == MC::RH_NU_E)
return NuREle;
761 if (std::abs(ancestorPDG) == MC::RH_NU_MU)
return NuRMu;
762 if (std::abs(ancestorPDG) == MC::RH_NU_TAU)
return NuRTau;
795 info.setMotherProperties(ancestor);
805 ancestor = ancestorParent;
809 const int ancestorPDG = ancestor->
pdgId();
810 info.setMotherProperties(ancestor);
817 auto DP = DecayProducts(partProdVtx);
818 const int numberOfChildren = DP.size();
819 const int NumOfPhot = DP.pd(MC::PHOTON);
820 const int NumOfEl = DP.pd(MC::ELECTRON);
821 const int NumOfPos = DP.pd(MC::POSITRON);
822 const int NumOfElNeut = DP.apd(MC::NU_E);
823 const int NumOfMuNeut = DP.apd(MC::NU_MU);
825 const int NumOfquark = DP.apd({MC::DQUARK,MC::UQUARK,MC::SQUARK,MC::CQUARK,MC::BQUARK,MC::TQUARK});
826 const int NumOfgluon = DP.apd(MC::GLUON);
827 const int NumOfMuPl = DP.pd(-MC::MUON);
828 const int NumOfMuMin = DP.pd(MC::MUON);
829 const int NumOfTau = DP.apd(MC::TAU);
830 const int NumOfTauNeut = DP.apd(MC::NU_TAU);
840 }
while (
MC::isW(itrP) && prodVert);
843 if (std::abs(itrP->
pdgId()) == MC::RH_NU_E)
return NuREle;
844 if (std::abs(itrP->
pdgId()) == MC::RH_NU_MU)
return NuRMu;
845 if (std::abs(itrP->
pdgId()) == MC::RH_NU_TAU)
return NuRTau;
852 bool isZboson =
false;
853 bool isWboson =
false;
854 bool skipnext =
false;
855 for (
unsigned int ipOut = 0; ipOut + 1 < partProdVtx->
nOutgoingParticles(); ipOut++) {
861 if (!aChild)
continue;
863 for (
unsigned int ipOut1 = ipOut + 1; ipOut1 < partProdVtx->
nOutgoingParticles(); ipOut1++) {
865 if (theNextChild)
break;
872 if (thePriPart == aChild || thePriPart == theNextChild) {
877 }
else if (
MC::isTau(aChild) && std::abs(theNextChild->pdgId()) == MC::NU_TAU) {
879 if (thePriPart == aChild || thePriPart == theNextChild) {
886 if (isWboson)
return WBoson;
887 if (isZboson)
return ZBoson;
889 if (numOfParents == 2 ) {
896 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && NumOfTau == 1 && NumOfTauNeut == 1)
return WBoson;
899 if ((numberOfChildren - NumOfquark - NumOfgluon) == 4 &&
900 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 4) &&
904 if ((numberOfChildren - NumOfquark - NumOfgluon - NumOfPhot) == 6 &&
905 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 6) &&
910 if (partProdVtx == ancestorProdVtx) {
911 int NumOfTauLoop = 0;
912 int NumOfTauNeuLoop = 0;
913 int NumOfLepLoop = 0;
916 for (
const auto *
const pin: partProdVtx->
particles_in()) {
920 if (std::abs(
pout->pdgId()) == MC::NU_TAU) NumOfTauNeuLoop++;
925 if (NumOfTauLoop == 2 && NumOfTauNeuLoop == 0)
return ZBoson;
926 if (NumOfTauLoop == 1 && NumOfTauNeuLoop == 1)
return WBoson;
927 if ((NumOfTauLoop == 4 && NumOfTauNeuLoop == 0) || (NumOfTauLoop == 3 && NumOfTauNeuLoop == 1) || (NumOfTauLoop == 2 && NumOfTauNeuLoop == 2))
return DiBoson;
928 if (NumOfLepLoop == 4)
return DiBoson;
936 if (std::abs(ancestorPDG) == MC::WBOSON_LRSM)
return WBosonLRSM;
937 if (std::abs(ancestorPDG) == MC::RH_NU_TAU)
return NuRTau;
940 if (std::abs(ancestorPDG) == MC::JPSI)
return JPsi;
955 info.resetMotherProperties();
956 info.photonMother =
nullptr;
974 info.setMotherProperties(ancestor);
977 int ancestorPDG = ancestor->
pdgId();
987 auto DP = DecayProducts(partProdVtx);
988 const int NumOfEl = DP.pd(MC::ELECTRON);
989 const int NumOfPos = DP.pd(MC::POSITRON);
990 const int NumOfMu = DP.apd(MC::MUON);
991 const int NumOfTau = DP.apd(MC::TAU);
992 const int NumOfLQ = DP.apd(MC::LEPTOQUARK);
993 const int NumOfLep = NumOfEl + NumOfPos + NumOfMu + NumOfTau;
994 const int NumOfNeut = DP.apd({MC::NU_E,MC::NU_MU,MC::NU_TAU});
995 const int NumOfPht = DP.pd(MC::PHOTON);
1000 const bool possibleNuclearFragment = (numOfParents == 1 && (
MC::isPhoton(ancestorPDG) ||
MC::isElectron(ancestorPDG) || std::abs(ancestorPDG) == MC::PIPLUS));
1003 if (!
pout)
continue;
1004 childPDG =
pout->pdg_id();
1005 if (possibleNuclearFragment &&
1006 (
MC::isNucleus(childPDG) || childPDG == 0 || childPDG == MC::PROTON || childPDG == MC::NEUTRON)) {
1009 if (std::abs(childPDG) < MC::ELECTRON ||
1010 (std::abs(childPDG) > MC::NU_TAU && std::abs(childPDG) < 43 && !
MC::isPhoton(childPDG))) {
1017 if (childPDG == ancestorPDG) {
1023 bool foundISR =
false;
1024 bool foundFSR =
false;
1026 if (numOfParents == 1 && numberOfChildren == 2 &&
MC::isElectron(ancestorPDG) && NumOfPht == 2)
return ElMagProc;
1038 for (
const auto & pin: Vert->particles_in()) {
1040 PartPDG = std::abs(pin->pdgId());
1041 prodVert = pin->prodVtx();
1049 }
while (prodVert && std::abs(ancestorPDG) == PartPDG);
1059 if ((numOfParents == 1 && (
MC::isPhoton(ancestorPDG) ||
MC::isElectron(ancestorPDG)) && numberOfChildren > 2 && NumOfNucFr != 0) ||
1060 (numOfParents == 1 && std::abs(ancestorPDG) == MC::PIPLUS && numberOfChildren > 10 && NumOfNucFr != 0) ||
1062 (numOfParents == 1 &&
MC::isNucleus(ancestorPDG) && std::abs(ancestorPDG) != MC::PROTON))
1065 if (
MC::isMuon(ancestorPDG) && NumOfMu == 0)
return Mu;
1075 if (!
pout)
continue;
1076 if (ancestorPDG !=
pout->pdgId())
continue;
1078 if (!Vrtx)
continue;
1091 if (numOfParents == 2 && ((
MC::isElectron(ancestorPDG) && NumOfEl == 1 && NumOfPos == 1) || (
MC::isMuon(ancestorPDG) && NumOfMu == 2) || (
MC::isTau(ancestorPDG) && NumOfTau == 2))) {
1095 if (numOfParents == 2 && NumOfLep == 1 && NumOfNeut == 1 && (
MC::isElectron(ancestorPDG) || std::abs(ancestorPDG) == MC::NU_E))
return FSRPhot;
1098 if (
MC::isElectron(ancestorPDG) && numOfParents == 1 && numberOfChildren == 2 && (NumOfEl == 1 || NumOfPos == 1) && NumOfPht == 1 &&
1103 if (
MC::isZ(ancestorPDG) && ((NumOfEl + NumOfPos == 2 || NumOfEl + NumOfPos == 4) || (NumOfMu == 2 || NumOfMu == 4) || (NumOfTau == 2 || NumOfTau == 4)) && NumOfPht > 0)
return FSRPhot;
1105 if (NumOfPht > 0 && (std::abs(ancestorPDG) == MC::WBOSON_LRSM ||
MC::isNeutrinoRH(ancestorPDG)))
return FSRPhot;
1107 if (numOfParents == 2 && NumOfLQ == 1)
return FSRPhot;
1114 if (NumOfLep == 1 && NumOfNeut == 1 && numberOfChildren == NumOfLep + NumOfNeut + NumOfPht)
return FSRPhot;
1122 }
while (
MC::isW(itrP) && prodVert);
1127 if ( std::abs(itrP->
pdgId()) == MC::RH_NU_E)
return NuREle;
1128 if ( std::abs(itrP->
pdgId()) == MC::RH_NU_MU)
return NuRMu;
1129 if ( std::abs(itrP->
pdgId()) == MC::RH_NU_TAU)
return NuRTau;
1137 bool isZboson =
false;
1138 bool isWboson =
false;
1139 bool skipnext =
false;
1140 for (
unsigned int ipOut = 0; ipOut + 1 < partProdVtx->
nOutgoingParticles(); ipOut++) {
1146 if (!aChild)
continue;
1148 for (
unsigned int ipOut1 = ipOut + 1; ipOut1 < partProdVtx->
nOutgoingParticles(); ipOut1++) {
1150 if (theNextChild)
break;
1152 if (!theNextChild)
continue;
1155 if (thePriPart == aChild || thePriPart == theNextChild) {
1160 }
else if (
MC::isTau(aChild) && std::abs(theNextChild->pdgId()) == MC::NU_TAU) {
1162 if (thePriPart == aChild || thePriPart == theNextChild) {
1169 if (isWboson)
return WBoson;
1170 if (isZboson)
return ZBoson;
1174 if (numOfParents == 4 && (numberOfChildren - NumOfPht) == 4 && (NumOfLep + NumOfNeut == 4)) {
1181 if (partProdVtx == ancestorProdVtx) {
1183 if (!
pout)
continue;
1184 for (
const auto *
const pin: partProdVtx->
particles_in()) {
1194 if (std::abs(ancestorPDG) == MC::PI0)
return PiZero;
1217 const int nuFlav = std::abs(thePart->
pdgId());
1232 info.setMotherProperties(ancestor);
1237 bool samePart = TruthLoopDetectionMethod1(partProdVtx, ancestor);
1248 if (TruthLoopDetectionMethod2(ancestor,ancestorParent)) {
1249 ancestorParent = ancestor;
1253 if (ancestorParent) {
1254 pPDG = ancestorParent->
pdgId();
1257 if (ancestor == ancestorParent) {
break; }
1261 ancestor = ancestorParent;
1262 info.setMotherProperties(ancestor);
1271 ancestor = ancestorParent;
1272 info.setMotherProperties(ancestor);
1278 info.setMotherProperties(ancestor);
1279 const int ancestorPDG = ancestor->
pdgId();
1280 partProdVtx = ancestor->
decayVtx();
1286 auto DP = DecayProducts(partProdVtx);
1287 const int NumOfPhot = DP.pd(MC::PHOTON);
1288 const int NumOfquark = DP.apd({MC::DQUARK,MC::UQUARK,MC::SQUARK,MC::CQUARK,MC::BQUARK,MC::TQUARK});
1289 const int NumOfgluon = DP.apd(MC::GLUON);
1290 const int NumOfLQ = DP.apd(MC::LEPTOQUARK);
1291 const int NumOfElNeut = DP.apd(MC::NU_E);
1292 const int NumOfMuNeut = DP.apd(MC::NU_MU);
1293 const int NumOfTauNeut = DP.apd(MC::NU_TAU);
1294 const int NumOfEl = DP.apd(MC::ELECTRON);
1295 const int NumOfMu = DP.apd(MC::MUON);
1296 const int NumOfTau = DP.apd(MC::TAU);
1300 if (!aChild)
continue;
1309 if (
MC::isQuark(ancestorPDG) && numOfParents == 1 && numberOfChildren == 3 && NumOfquark == 1 && (NumOfEl == 1 || NumOfMu == 1 || NumOfTau == 1))
return QuarkWeakDec;
1318 }
while (
MC::isW(ptrPart) && prodVert);
1321 if (std::abs(ptrPart->
pdgId()) == MC::RH_NU_E)
return NuREle;
1322 if (std::abs(ptrPart->
pdgId()) == MC::RH_NU_MU)
return NuRMu;
1323 if (std::abs(ptrPart->
pdgId()) == MC::RH_NU_TAU)
return NuRTau;
1339 bool isZboson =
false;
1340 bool isWboson =
false;
1341 bool skipnext =
false;
1343 for (
unsigned int ipOut = 0; ipOut + 1 < partProdVtx->
nOutgoingParticles(); ++ipOut) {
1345 if (!aChild)
continue;
1347 for (
unsigned int ipOut1 = ipOut + 1; ipOut1 < partProdVtx->
nOutgoingParticles(); ipOut1++) {
1349 if (theNextChild)
break;
1351 if (!theNextChild)
continue;
1358 const int apdgID1 = std::abs(aChild->
pdgId());
1359 const int apdgID2 = std::abs(theNextChild->pdgId());
1362 if (thePartToCheck == aChild || thePartToCheck == theNextChild) {
1367 }
else if ((apdgID1 == MC::ELECTRON && apdgID2 == MC::NU_E) ||
1368 (apdgID1 == MC::NU_E && apdgID2 == MC::ELECTRON) ||
1369 (apdgID1 == MC::MUON && apdgID2 == MC::NU_MU) ||
1370 (apdgID1 == MC::NU_MU && apdgID2 == MC::MUON) ||
1371 (apdgID1 == MC::TAU && apdgID2 == MC::NU_TAU) ||
1372 (apdgID1 == MC::NU_TAU && apdgID2 == MC::TAU)
1375 if (thePartToCheck == aChild || thePartToCheck == theNextChild) {
1382 if (isWboson)
return WBoson;
1383 if (isZboson)
return ZBoson;
1386 if (numOfParents == 2) {
1388 if ( (numberOfChildren - NumOfquark - NumOfgluon) == 2 && (NumOfElNeut == 2 || NumOfMuNeut == 2 || NumOfTauNeut == 2))
return ZBoson;
1391 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && ((NumOfEl == 1 && NumOfElNeut == 1) || (NumOfMu == 1 && NumOfMuNeut == 1) || (NumOfTau == 1 && NumOfTauNeut == 1)))
return WBoson;
1396 if ( (numberOfChildren - NumOfquark - NumOfgluon) == 4 && (NumOfEl + NumOfMu + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 4) &&
1400 if ((numberOfChildren - NumOfquark - NumOfgluon - NumOfPhot) == 6 && (NumOfEl + NumOfMu + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 6) &&
1405 if (partProdVtx == ancestorProdVtx) {
1406 int NumOfLepLoop = 0;
1407 int NumOfNeuLoop = 0;
1409 if (!
pout)
continue;
1410 for (
const auto *
const pin: partProdVtx->
particles_in()) {
1413 const int apdgid = std::abs(
pout->pdgId());
1416 else { NumOfLepLoop++; }
1421 if (NumOfNeuLoop == 2 && NumOfLepLoop == 0)
return ZBoson;
1422 if (NumOfNeuLoop == 1 && NumOfLepLoop == 1)
return WBoson;
1423 if (NumOfNeuLoop + NumOfLepLoop == 4)
return DiBoson;
1433 const ParticleOrigin tauOrig = defOrigOfTau(xTruthParticleContainer, ancestor, ancestorPDG,
info);
1438 if (std::abs(ancestorPDG) == MC::WBOSON_LRSM)
return WBosonLRSM;
1439 if (std::abs(ancestorPDG) == MC::RH_NU_E)
return NuREle;
1440 if (std::abs(ancestorPDG) == MC::RH_NU_MU)
return NuRMu;
1441 if (std::abs(ancestorPDG) == MC::RH_NU_TAU)
return NuRTau;