24 std::pair<ParticleType, ParticleOrigin>
27 const EventContext& ctx =
info ?
info->eventContext : Gaudi::Hive::currentContext();
29 if (!truthParticleLinkVecReadHandle.
isValid()) {
30 ATH_MSG_WARNING(
" Invalid ReadHandle for xAODTruthParticleLinkVector with key: " << truthParticleLinkVecReadHandle.
key());
35 return particleTruthClassifier (*tplink,
info);
41 std::pair<ParticleType, ParticleOrigin>
51 return std::make_pair(partType, partOrig);
53 info.genPart = thePart;
57 if (!truthParticleContainerReadHandle.
isValid()) {
58 ATH_MSG_WARNING(
" Invalid ReadHandle for xAOD::TruthParticleContainer with key: " << truthParticleContainerReadHandle.
key());
59 return std::make_pair(partType, partOrig);
62 ATH_MSG_DEBUG(
"xAODTruthParticleContainer with key " << truthParticleContainerReadHandle.
key() <<
" has valid ReadHandle ");
111 partOrig = defOrigOfElectron(*truthParticleContainerReadHandle, thePart,
isPrompt,
info);
117 partOrig = defOrigOfMuon(*truthParticleContainerReadHandle, thePart,
isPrompt,
info);
120 if (!partProdVtx &&
MC::isTau(thePart)) {
122 partOrig = defOrigOfTau(*truthParticleContainerReadHandle, thePart, parentPDG,
info);
128 partOrig = defOrigOfPhoton(*truthParticleContainerReadHandle, thePart,
isPrompt,
info);
134 return std::make_pair(
Neutrino, partOrig);
140 if (isPartHadr)
return std::make_pair(
Hadron, partOrig);
166 partOrig = defOrigOfElectron(*truthParticleContainerReadHandle, thePart,
isPrompt,
info);
170 partOrig = defOrigOfMuon(*truthParticleContainerReadHandle, thePart,
isPrompt,
info);
173 partOrig = defOrigOfTau(*truthParticleContainerReadHandle, thePart, parentPDG,
info);
177 partOrig = defOrigOfPhoton(*truthParticleContainerReadHandle, thePart,
isPrompt,
info);
181 partOrig = defOrigOfNeutrino(*truthParticleContainerReadHandle, thePart,
isPrompt,
info);
186 return std::make_pair(partType, partOrig);
193 const int parentPDG =
parent->pdgId();
195 if (!aChild)
continue;
206 return TruthLoopDetectionMethod3(childOrigVtx,
parent);
224 parent_prdVtx =
parent->hasProdVtx() ?
parent->prodVtx() :
nullptr;
225 parent_endVtx =
parent->decayVtx();
229 return (child_endVtx == parent_prdVtx && child_prdVtx == parent_endVtx);
268 info.setMotherProperties(ancestor);
272 bool samePart = TruthLoopDetectionMethod1(partProdVtx, ancestor);
284 if (ancestor == ancestorParent) {
break; }
285 if (TruthLoopDetectionMethod2(ancestor,ancestorParent)) {
286 ancestorParent = ancestor;
291 if (ancestorParent) {
292 pPDG = ancestorParent->
pdgId();
294 ancestor = ancestorParent;
303 ancestor = ancestorParent;
307 info.setMotherProperties(ancestor);
308 const int ancestorPDG = ancestor->
pdgId();
315 auto DP = DecayProducts(partProdVtx);
316 const int NumOfPhot = DP.pd(MC::PHOTON);
317 const int NumOfEl = DP.pd(MC::ELECTRON);
318 const int NumOfPos = DP.pd(MC::POSITRON);
319 const int NumOfquark = DP.apd({MC::DQUARK,MC::UQUARK,MC::SQUARK,MC::CQUARK,MC::BQUARK,MC::TQUARK});
320 const int NumOfgluon = DP.apd(MC::GLUON);
321 const int NumOfElNeut = DP.apd(MC::NU_E);
322 const int NumOfLQ = DP.apd(MC::LEPTOQUARK);
323 const int NumOfMuPl = DP.pd(-MC::MUON);
324 const int NumOfMuMin = DP.pd(MC::MUON);
325 const int NumOfMuNeut = DP.apd(MC::NU_MU);
326 const int NumOfTau = DP.apd(MC::TAU);
327 const int NumOfTauNeut = DP.apd(MC::NU_TAU);
331 const bool possibleNuclearFragment = (numOfParents == 1 && (
MC::isPhoton(ancestorPDG) ||
MC::isElectron(ancestorPDG) ||
MC::isMuon(ancestorPDG) || std::abs(ancestorPDG) == MC::PIPLUS));
333 if (!aChild)
continue;
334 const int childPDG = aChild->pdgId();
336 if (possibleNuclearFragment &&
337 (
MC::isNucleus(childPDG) || childPDG == 0 || childPDG == MC::PROTON || childPDG == MC::NEUTRON ||
338 std::abs(childPDG) == MC::PIPLUS || std::abs(childPDG) == MC::PI0))
345 for (
const auto& photonParent: ancestorProdVtx->
particles_in()) {
346 if (!photonParent)
continue;
347 info.photonMother = photonParent;
351 if ((
MC::isPhoton(ancestorPDG) && numberOfChildren == 2 && NumOfEl == 1 && NumOfPos == 1) || (
MC::isPhoton(ancestorPDG) && numberOfChildren == 1 && (NumOfEl == 1 || NumOfPos == 1)))
return PhotonConv;
356 if (numOfParents == 1 && std::abs(ancestorPDG) == MC::PIPLUS && numberOfChildren > 2 && NumOfNucFr != 0)
return ElMagProc;
365 if (ancestorPDG == MC::ELECTRON && numberOfChildren == 2 && NumOfEl == 2 && NumOfPos == 0)
return ElMagProc;
368 if (ancestorPDG == MC::POSITRON && numberOfChildren == 2 && NumOfEl == 0 && NumOfPos == 2)
return ElMagProc;
375 if (numberOfChildren == 2 && (NumOfEl == 1 || NumOfPos == 1) && !
MC::isElectron(ancestorPDG) && samePart)
return ElMagProc;
377 if ((ancestorPDG == MC::PI0 && numberOfChildren == 3 && NumOfPhot == 1 && NumOfEl == 1 && NumOfPos == 1) ||
378 (ancestorPDG == MC::PI0 && numberOfChildren == 4 && NumOfPhot == 0 && NumOfEl == 2 && NumOfPos == 2))
382 if (
MC::isSMQuark(ancestorPDG) && numOfParents == 1 && numberOfChildren == 3 && NumOfquark == 1 && NumOfElNeut == 1)
return QuarkWeakDec;
394 prodVert = ptrPart->hasProdVtx() ? ptrPart->prodVtx() :
nullptr;
395 }
while (
MC::isW(ptrPart) && prodVert);
398 if (std::abs(ptrPart->pdgId()) == MC::RH_NU_E)
return NuREle;
399 if (std::abs(ptrPart->pdgId()) == MC::RH_NU_MU)
return NuRMu;
400 if (std::abs(ptrPart->pdgId()) == MC::RH_NU_TAU)
return NuRTau;
414 bool isZboson =
false;
415 bool isWboson =
false;
416 bool skipnext =
false;
418 for (
unsigned int ipOut = 0; ipOut + 1 < partProdVtx->
nOutgoingParticles(); ++ipOut) {
420 if (!aChild)
continue;
422 for (
unsigned int ipOut1 = ipOut + 1; ipOut1 < partProdVtx->
nOutgoingParticles(); ipOut1++) {
424 if (theNextChild)
break;
426 if (!theNextChild)
continue;
434 if (thePartToCheck == aChild || thePartToCheck == theNextChild) {
441 if (thePartToCheck == aChild || thePartToCheck == theNextChild) {
448 if (isWboson)
return WBoson;
449 if (isZboson)
return ZBoson;
451 if (numOfParents == 2) {
453 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && NumOfEl == 1 && NumOfPos == 1)
return ZBoson;
456 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && (NumOfEl == 1 || NumOfPos == 1) && NumOfElNeut == 1)
return WBoson;
461 if ((numberOfChildren - NumOfquark - NumOfgluon) == 4 &&
462 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 4) &&
466 if ((numberOfChildren - NumOfquark - NumOfgluon - NumOfPhot) == 6 &&
467 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 6) &&
472 if (partProdVtx == ancestorProdVtx) {
473 int NumOfEleLoop = 0;
474 int NumOfLepLoop = 0;
475 int NumOfEleNeuLoop = 0;
478 for (
const auto *
const pin: partProdVtx->
particles_in()) {
482 if (std::abs(
pout->pdgId()) == MC::NU_E) NumOfEleNeuLoop++;
487 if (NumOfEleLoop == 2 && NumOfEleNeuLoop == 0)
return ZBoson;
488 if (NumOfEleLoop == 1 && NumOfEleNeuLoop == 1)
return WBoson;
489 if ((NumOfEleLoop == 4 && NumOfEleNeuLoop == 0) || (NumOfEleLoop == 3 && NumOfEleNeuLoop == 1) ||
490 (NumOfEleLoop == 2 && NumOfEleNeuLoop == 2))
return DiBoson;
491 if (NumOfLepLoop == 4)
return DiBoson;
504 const ParticleOrigin tauOrig = defOrigOfTau(xTruthParticleContainer, ancestor, ancestorPDG,
info);
509 if (std::abs(ancestorPDG) == MC::WBOSON_LRSM)
return WBosonLRSM;
510 if (std::abs(ancestorPDG) == MC::RH_NU_E)
return NuREle;
511 if (std::abs(ancestorPDG) == MC::RH_NU_MU)
return NuRMu;
512 if (std::abs(ancestorPDG) == MC::RH_NU_TAU)
return NuRTau;
544 info.setMotherProperties(ancestor);
557 if (ancestor == ancestorParent) {
break; }
558 if (TruthLoopDetectionMethod2(ancestor,ancestorParent)) {
559 ancestorParent = ancestor;
564 if (ancestorParent) {
565 pPDG = ancestorParent->
pdgId();
568 ancestor = ancestorParent;
577 ancestor = ancestorParent;
581 info.setMotherProperties(ancestor);
582 const int ancestorPDG = ancestor->
pdgId();
589 auto DP = DecayProducts(partProdVtx);
590 const int NumOfPhot = DP.pd(MC::PHOTON);
591 const int NumOfEl = DP.pd(MC::ELECTRON);
592 const int NumOfPos = DP.pd(MC::POSITRON);
593 const int NumOfElNeut = DP.apd(MC::NU_E);
594 const int NumOfMuNeut = DP.apd(MC::NU_MU);
595 const int NumOfLQ = DP.apd(MC::LEPTOQUARK);
596 const int NumOfquark = DP.apd({MC::DQUARK,MC::UQUARK,MC::SQUARK,MC::CQUARK,MC::BQUARK,MC::TQUARK});
597 const int NumOfgluon = DP.apd(MC::GLUON);
598 const int NumOfMuPl = DP.pd(-MC::MUON);
599 const int NumOfMuMin = DP.pd(MC::MUON);
600 const int NumOfTau = DP.apd(MC::TAU);
601 const int NumOfTauNeut = DP.apd(MC::NU_TAU);
604 if (std::abs(ancestorPDG) == MC::PIPLUS && numberOfChildren == 2 && NumOfMuNeut == 1)
return PionDecay;
605 if (std::abs(ancestorPDG) == MC::KPLUS && numberOfChildren == 2 && NumOfMuNeut == 1)
return KaonDecay;
607 const ParticleOrigin tauOrig = defOrigOfTau(xTruthParticleContainer, ancestor, ancestorPDG,
info);
614 if (
MC::isSMQuark(ancestorPDG) && numOfParents == 1 && numberOfChildren == 3 && NumOfquark == 1 && NumOfMuNeut == 1)
return QuarkWeakDec;
622 }
while (
MC::isW(itrP) && prodVert);
625 if (std::abs(itrP->
pdgId()) == MC::RH_NU_E)
return NuREle;
626 if (std::abs(itrP->
pdgId()) == MC::RH_NU_MU)
return NuRMu;
627 if (std::abs(itrP->
pdgId()) == MC::RH_NU_TAU)
return NuRTau;
633 if (
MC::isPhoton(ancestorPDG) && numberOfChildren == 2 && NumOfMuMin == 1 && NumOfMuPl == 1)
return PhotonConv;
638 bool isZboson =
false;
639 bool isWboson =
false;
640 bool skipnext =
false;
641 for (
unsigned int ipOut = 0; ipOut + 1 < partProdVtx->
nOutgoingParticles(); ipOut++) {
647 if (!aChild)
continue;
649 for (
unsigned int ipOut1 = ipOut + 1; ipOut1 < partProdVtx->
nOutgoingParticles(); ipOut1++) {
651 if (theNextChild)
break;
653 if (!theNextChild)
continue;
656 if (thePriPart == aChild || thePriPart == theNextChild) {
661 }
else if (
MC::isMuon(aChild) && std::abs(theNextChild->pdgId()) == MC::NU_MU) {
663 if (thePriPart == aChild || thePriPart == theNextChild) {
670 if (isWboson)
return WBoson;
671 if (isZboson)
return ZBoson;
673 if (numOfParents == 2 ) {
675 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && NumOfMuPl == 1 && NumOfMuMin == 1)
return ZBoson;
679 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && (NumOfMuPl == 1 || NumOfMuMin == 1) && NumOfMuNeut == 1)
return WBoson;
684 if ((numberOfChildren - NumOfquark - NumOfgluon) == 4 &&
685 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 4) &&
689 if ((numberOfChildren - NumOfquark - NumOfgluon - NumOfPhot) == 6 &&
690 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 6) &&
695 if (partProdVtx == ancestorProdVtx) {
697 int NumOfMuNeuLoop = 0;
698 int NumOfLepLoop = 0;
705 if (std::abs(
pout->pdg_id()) == MC::NU_MU) NumOfMuNeuLoop++;
711 if (NumOfMuLoop == 2 && NumOfMuNeuLoop == 0)
return ZBoson;
712 if (NumOfMuLoop == 1 && NumOfMuNeuLoop == 1)
return WBoson;
713 if ((NumOfMuLoop == 4 && NumOfMuNeuLoop == 0) || (NumOfMuLoop == 3 && NumOfMuNeuLoop == 1) ||
714 (NumOfMuLoop == 2 && NumOfMuNeuLoop == 2))
return DiBoson;
715 if (NumOfLepLoop == 4)
return DiBoson;
726 if (std::abs(ancestorPDG) == MC::WBOSON_LRSM)
return WBosonLRSM;
727 if (std::abs(ancestorPDG) == MC::RH_NU_E)
return NuREle;
728 if (std::abs(ancestorPDG) == MC::RH_NU_MU)
return NuRMu;
729 if (std::abs(ancestorPDG) == MC::RH_NU_TAU)
return NuRTau;
762 info.setMotherProperties(ancestor);
772 ancestor = ancestorParent;
776 const int ancestorPDG = ancestor->
pdgId();
777 info.setMotherProperties(ancestor);
784 auto DP = DecayProducts(partProdVtx);
785 const int numberOfChildren = DP.size();
786 const int NumOfPhot = DP.pd(MC::PHOTON);
787 const int NumOfEl = DP.pd(MC::ELECTRON);
788 const int NumOfPos = DP.pd(MC::POSITRON);
789 const int NumOfElNeut = DP.apd(MC::NU_E);
790 const int NumOfMuNeut = DP.apd(MC::NU_MU);
792 const int NumOfquark = DP.apd({MC::DQUARK,MC::UQUARK,MC::SQUARK,MC::CQUARK,MC::BQUARK,MC::TQUARK});
793 const int NumOfgluon = DP.apd(MC::GLUON);
794 const int NumOfMuPl = DP.pd(-MC::MUON);
795 const int NumOfMuMin = DP.pd(MC::MUON);
796 const int NumOfTau = DP.apd(MC::TAU);
797 const int NumOfTauNeut = DP.apd(MC::NU_TAU);
807 }
while (
MC::isW(itrP) && prodVert);
810 if (std::abs(itrP->
pdgId()) == MC::RH_NU_E)
return NuREle;
811 if (std::abs(itrP->
pdgId()) == MC::RH_NU_MU)
return NuRMu;
812 if (std::abs(itrP->
pdgId()) == MC::RH_NU_TAU)
return NuRTau;
819 bool isZboson =
false;
820 bool isWboson =
false;
821 bool skipnext =
false;
822 for (
unsigned int ipOut = 0; ipOut + 1 < partProdVtx->
nOutgoingParticles(); ipOut++) {
828 if (!aChild)
continue;
830 for (
unsigned int ipOut1 = ipOut + 1; ipOut1 < partProdVtx->
nOutgoingParticles(); ipOut1++) {
832 if (theNextChild)
break;
839 if (thePriPart == aChild || thePriPart == theNextChild) {
844 }
else if (
MC::isTau(aChild) && std::abs(theNextChild->pdgId()) == MC::NU_TAU) {
846 if (thePriPart == aChild || thePriPart == theNextChild) {
853 if (isWboson)
return WBoson;
854 if (isZboson)
return ZBoson;
856 if (numOfParents == 2 ) {
863 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && NumOfTau == 1 && NumOfTauNeut == 1)
return WBoson;
866 if ((numberOfChildren - NumOfquark - NumOfgluon) == 4 &&
867 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 4) &&
871 if ((numberOfChildren - NumOfquark - NumOfgluon - NumOfPhot) == 6 &&
872 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 6) &&
877 if (partProdVtx == ancestorProdVtx) {
878 int NumOfTauLoop = 0;
879 int NumOfTauNeuLoop = 0;
880 int NumOfLepLoop = 0;
883 for (
const auto *
const pin: partProdVtx->
particles_in()) {
887 if (std::abs(
pout->pdgId()) == MC::NU_TAU) NumOfTauNeuLoop++;
892 if (NumOfTauLoop == 2 && NumOfTauNeuLoop == 0)
return ZBoson;
893 if (NumOfTauLoop == 1 && NumOfTauNeuLoop == 1)
return WBoson;
894 if ((NumOfTauLoop == 4 && NumOfTauNeuLoop == 0) || (NumOfTauLoop == 3 && NumOfTauNeuLoop == 1) || (NumOfTauLoop == 2 && NumOfTauNeuLoop == 2))
return DiBoson;
895 if (NumOfLepLoop == 4)
return DiBoson;
903 if (std::abs(ancestorPDG) == MC::WBOSON_LRSM)
return WBosonLRSM;
904 if (std::abs(ancestorPDG) == MC::RH_NU_TAU)
return NuRTau;
907 if (std::abs(ancestorPDG) == MC::JPSI)
return JPsi;
922 info.resetMotherProperties();
923 info.photonMother =
nullptr;
941 info.setMotherProperties(ancestor);
944 int ancestorPDG = ancestor->
pdgId();
954 auto DP = DecayProducts(partProdVtx);
955 const int NumOfEl = DP.pd(MC::ELECTRON);
956 const int NumOfPos = DP.pd(MC::POSITRON);
957 const int NumOfMu = DP.apd(MC::MUON);
958 const int NumOfTau = DP.apd(MC::TAU);
959 const int NumOfLQ = DP.apd(MC::LEPTOQUARK);
960 const int NumOfLep = NumOfEl + NumOfPos + NumOfMu + NumOfTau;
961 const int NumOfNeut = DP.apd({MC::NU_E,MC::NU_MU,MC::NU_TAU});
962 const int NumOfPht = DP.pd(MC::PHOTON);
967 const bool possibleNuclearFragment = (numOfParents == 1 && (
MC::isPhoton(ancestorPDG) ||
MC::isElectron(ancestorPDG) || std::abs(ancestorPDG) == MC::PIPLUS));
971 childPDG =
pout->pdg_id();
972 if (possibleNuclearFragment &&
973 (
MC::isNucleus(childPDG) || childPDG == 0 || childPDG == MC::PROTON || childPDG == MC::NEUTRON)) {
976 if (std::abs(childPDG) < MC::ELECTRON ||
977 (std::abs(childPDG) > MC::NU_TAU && std::abs(childPDG) < 43 && !
MC::isPhoton(childPDG))) {
984 if (childPDG == ancestorPDG) {
990 bool foundISR =
false;
991 bool foundFSR =
false;
993 if (numOfParents == 1 && numberOfChildren == 2 &&
MC::isElectron(ancestorPDG) && NumOfPht == 2)
return ElMagProc;
1005 for (
const auto & pin: Vert->particles_in()) {
1007 PartPDG = std::abs(pin->pdgId());
1008 prodVert = pin->prodVtx();
1016 }
while (prodVert && std::abs(ancestorPDG) == PartPDG);
1026 if ((numOfParents == 1 && (
MC::isPhoton(ancestorPDG) ||
MC::isElectron(ancestorPDG)) && numberOfChildren > 2 && NumOfNucFr != 0) ||
1027 (numOfParents == 1 && std::abs(ancestorPDG) == MC::PIPLUS && numberOfChildren > 10 && NumOfNucFr != 0) ||
1029 (numOfParents == 1 &&
MC::isNucleus(ancestorPDG) && std::abs(ancestorPDG) != MC::PROTON))
1032 if (
MC::isMuon(ancestorPDG) && NumOfMu == 0)
return Mu;
1042 if (!
pout)
continue;
1043 if (ancestorPDG !=
pout->pdgId())
continue;
1045 if (!Vrtx)
continue;
1058 if (numOfParents == 2 && ((
MC::isElectron(ancestorPDG) && NumOfEl == 1 && NumOfPos == 1) || (
MC::isMuon(ancestorPDG) && NumOfMu == 2) || (
MC::isTau(ancestorPDG) && NumOfTau == 2))) {
1062 if (numOfParents == 2 && NumOfLep == 1 && NumOfNeut == 1 && (
MC::isElectron(ancestorPDG) || std::abs(ancestorPDG) == MC::NU_E))
return FSRPhot;
1065 if (
MC::isElectron(ancestorPDG) && numOfParents == 1 && numberOfChildren == 2 && (NumOfEl == 1 || NumOfPos == 1) && NumOfPht == 1 &&
1070 if (
MC::isZ(ancestorPDG) && ((NumOfEl + NumOfPos == 2 || NumOfEl + NumOfPos == 4) || (NumOfMu == 2 || NumOfMu == 4) || (NumOfTau == 2 || NumOfTau == 4)) && NumOfPht > 0)
return FSRPhot;
1072 if (NumOfPht > 0 && (std::abs(ancestorPDG) == MC::WBOSON_LRSM ||
MC::isNeutrinoRH(ancestorPDG)))
return FSRPhot;
1074 if (numOfParents == 2 && NumOfLQ == 1)
return FSRPhot;
1081 if (NumOfLep == 1 && NumOfNeut == 1 && numberOfChildren == NumOfLep + NumOfNeut + NumOfPht)
return FSRPhot;
1089 }
while (
MC::isW(itrP) && prodVert);
1094 if ( std::abs(itrP->
pdgId()) == MC::RH_NU_E)
return NuREle;
1095 if ( std::abs(itrP->
pdgId()) == MC::RH_NU_MU)
return NuRMu;
1096 if ( std::abs(itrP->
pdgId()) == MC::RH_NU_TAU)
return NuRTau;
1104 bool isZboson =
false;
1105 bool isWboson =
false;
1106 bool skipnext =
false;
1107 for (
unsigned int ipOut = 0; ipOut + 1 < partProdVtx->
nOutgoingParticles(); ipOut++) {
1113 if (!aChild)
continue;
1115 for (
unsigned int ipOut1 = ipOut + 1; ipOut1 < partProdVtx->
nOutgoingParticles(); ipOut1++) {
1117 if (theNextChild)
break;
1119 if (!theNextChild)
continue;
1122 if (thePriPart == aChild || thePriPart == theNextChild) {
1127 }
else if (
MC::isTau(aChild) && std::abs(theNextChild->pdgId()) == MC::NU_TAU) {
1129 if (thePriPart == aChild || thePriPart == theNextChild) {
1136 if (isWboson)
return WBoson;
1137 if (isZboson)
return ZBoson;
1141 if (numOfParents == 4 && (numberOfChildren - NumOfPht) == 4 && (NumOfLep + NumOfNeut == 4)) {
1148 if (partProdVtx == ancestorProdVtx) {
1150 if (!
pout)
continue;
1151 for (
const auto *
const pin: partProdVtx->
particles_in()) {
1161 if (std::abs(ancestorPDG) == MC::PI0)
return PiZero;
1184 const int nuFlav = std::abs(thePart->
pdgId());
1199 info.setMotherProperties(ancestor);
1204 bool samePart = TruthLoopDetectionMethod1(partProdVtx, ancestor);
1215 if (TruthLoopDetectionMethod2(ancestor,ancestorParent)) {
1216 ancestorParent = ancestor;
1220 if (ancestorParent) {
1221 pPDG = ancestorParent->
pdgId();
1224 if (ancestor == ancestorParent) {
break; }
1228 ancestor = ancestorParent;
1229 info.setMotherProperties(ancestor);
1238 ancestor = ancestorParent;
1239 info.setMotherProperties(ancestor);
1245 info.setMotherProperties(ancestor);
1246 const int ancestorPDG = ancestor->
pdgId();
1247 partProdVtx = ancestor->
decayVtx();
1253 auto DP = DecayProducts(partProdVtx);
1254 const int NumOfPhot = DP.pd(MC::PHOTON);
1255 const int NumOfquark = DP.apd({MC::DQUARK,MC::UQUARK,MC::SQUARK,MC::CQUARK,MC::BQUARK,MC::TQUARK});
1256 const int NumOfgluon = DP.apd(MC::GLUON);
1257 const int NumOfLQ = DP.apd(MC::LEPTOQUARK);
1258 const int NumOfElNeut = DP.apd(MC::NU_E);
1259 const int NumOfMuNeut = DP.apd(MC::NU_MU);
1260 const int NumOfTauNeut = DP.apd(MC::NU_TAU);
1261 const int NumOfEl = DP.apd(MC::ELECTRON);
1262 const int NumOfMu = DP.apd(MC::MUON);
1263 const int NumOfTau = DP.apd(MC::TAU);
1267 if (!aChild)
continue;
1276 if (
MC::isQuark(ancestorPDG) && numOfParents == 1 && numberOfChildren == 3 && NumOfquark == 1 && (NumOfEl == 1 || NumOfMu == 1 || NumOfTau == 1))
return QuarkWeakDec;
1285 }
while (
MC::isW(ptrPart) && prodVert);
1288 if (std::abs(ptrPart->
pdgId()) == MC::RH_NU_E)
return NuREle;
1289 if (std::abs(ptrPart->
pdgId()) == MC::RH_NU_MU)
return NuRMu;
1290 if (std::abs(ptrPart->
pdgId()) == MC::RH_NU_TAU)
return NuRTau;
1306 bool isZboson =
false;
1307 bool isWboson =
false;
1308 bool skipnext =
false;
1310 for (
unsigned int ipOut = 0; ipOut + 1 < partProdVtx->
nOutgoingParticles(); ++ipOut) {
1312 if (!aChild)
continue;
1314 for (
unsigned int ipOut1 = ipOut + 1; ipOut1 < partProdVtx->
nOutgoingParticles(); ipOut1++) {
1316 if (theNextChild)
break;
1318 if (!theNextChild)
continue;
1325 const int apdgID1 = std::abs(aChild->
pdgId());
1326 const int apdgID2 = std::abs(theNextChild->pdgId());
1329 if (thePartToCheck == aChild || thePartToCheck == theNextChild) {
1334 }
else if ((apdgID1 == MC::ELECTRON && apdgID2 == MC::NU_E) ||
1335 (apdgID1 == MC::NU_E && apdgID2 == MC::ELECTRON) ||
1336 (apdgID1 == MC::MUON && apdgID2 == MC::NU_MU) ||
1337 (apdgID1 == MC::NU_MU && apdgID2 == MC::MUON) ||
1338 (apdgID1 == MC::TAU && apdgID2 == MC::NU_TAU) ||
1339 (apdgID1 == MC::NU_TAU && apdgID2 == MC::TAU)
1342 if (thePartToCheck == aChild || thePartToCheck == theNextChild) {
1349 if (isWboson)
return WBoson;
1350 if (isZboson)
return ZBoson;
1353 if (numOfParents == 2) {
1355 if ( (numberOfChildren - NumOfquark - NumOfgluon) == 2 && (NumOfElNeut == 2 || NumOfMuNeut == 2 || NumOfTauNeut == 2))
return ZBoson;
1358 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && ((NumOfEl == 1 && NumOfElNeut == 1) || (NumOfMu == 1 && NumOfMuNeut == 1) || (NumOfTau == 1 && NumOfTauNeut == 1)))
return WBoson;
1363 if ( (numberOfChildren - NumOfquark - NumOfgluon) == 4 && (NumOfEl + NumOfMu + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 4) &&
1367 if ((numberOfChildren - NumOfquark - NumOfgluon - NumOfPhot) == 6 && (NumOfEl + NumOfMu + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 6) &&
1372 if (partProdVtx == ancestorProdVtx) {
1373 int NumOfLepLoop = 0;
1374 int NumOfNeuLoop = 0;
1376 if (!
pout)
continue;
1377 for (
const auto *
const pin: partProdVtx->
particles_in()) {
1380 const int apdgid = std::abs(
pout->pdgId());
1383 else { NumOfLepLoop++; }
1388 if (NumOfNeuLoop == 2 && NumOfLepLoop == 0)
return ZBoson;
1389 if (NumOfNeuLoop == 1 && NumOfLepLoop == 1)
return WBoson;
1390 if (NumOfNeuLoop + NumOfLepLoop == 4)
return DiBoson;
1400 const ParticleOrigin tauOrig = defOrigOfTau(xTruthParticleContainer, ancestor, ancestorPDG,
info);
1405 if (std::abs(ancestorPDG) == MC::WBOSON_LRSM)
return WBosonLRSM;
1406 if (std::abs(ancestorPDG) == MC::RH_NU_E)
return NuREle;
1407 if (std::abs(ancestorPDG) == MC::RH_NU_MU)
return NuRMu;
1408 if (std::abs(ancestorPDG) == MC::RH_NU_TAU)
return NuRTau;