10#include <analysis/variables/MCTruthVariables.h>
13#include <analysis/VariableManager/Manager.h>
15#include <analysis/dataobjects/Particle.h>
16#include <analysis/dataobjects/TauPairDecay.h>
17#include <analysis/utility/MCMatching.h>
18#include <analysis/utility/ReferenceFrame.h>
19#include <analysis/utility/ValueIndexPairSorting.h>
21#include <mdst/dataobjects/MCParticle.h>
22#include <mdst/dataobjects/ECLCluster.h>
23#include <mdst/dataobjects/Track.h>
26#include <framework/datastore/StoreArray.h>
27#include <framework/datastore/StoreObjPtr.h>
28#include <framework/dataobjects/EventMetaData.h>
29#include <framework/gearbox/Const.h>
30#include <framework/logging/Logger.h>
31#include <framework/database/DBObjPtr.h>
32#include <framework/dbobjects/BeamParameters.h>
34#include <Math/VectorUtil.h>
46 double isSignal(
const Particle* part)
48 const MCParticle* mcparticle = part->getMCParticle();
55 double isSignalAcceptWrongFSPs(
const Particle* part)
57 const MCParticle* mcparticle = part->getMCParticle();
62 status &= (~MCMatching::c_MisID);
63 status &= (~MCMatching::c_AddedWrongParticle);
68 double isPrimarySignal(
const Particle* part)
70 return (isSignal(part) > 0.5 and particleMCPrimaryParticle(part) > 0.5);
73 double isMisidentified(
const Particle* part)
75 const MCParticle* mcp = part->getMCParticle();
81 double isWrongCharge(
const Particle* part)
83 const MCParticle* mcp = part->getMCParticle();
85 return (part->getCharge() != mcp->getCharge());
88 double isCloneTrack(
const Particle* particle)
94 const auto mcpww = particle->getRelatedToWithWeight<MCParticle>();
96 return (mcpww.second < 0);
99 double isOrHasCloneTrack(
const Particle* particle)
102 std::queue<const Particle*> qq;
104 while (!qq.empty()) {
105 const auto d = qq.front();
107 if (isCloneTrack(d) == 1.0)
return 1.0;
108 size_t nDau = d->getNDaughters();
109 for (
size_t iDau = 0; iDau < nDau; ++iDau)
110 qq.push(d->getDaughter(iDau));
115 double genNthMotherPDG(
const Particle* part,
const std::vector<double>& args)
117 const MCParticle* mcparticle = part->getMCParticle();
118 if (!mcparticle)
return 0.0;
120 unsigned int nLevels = args.empty() ? 0 : args[0];
122 const MCParticle* curMCParticle = mcparticle;
123 for (
unsigned int i = 0; i <= nLevels; ++i) {
124 const MCParticle* curMCMother = curMCParticle->getMother();
125 if (!curMCMother)
return 0.0;
126 curMCParticle = curMCMother;
128 return curMCParticle->getPDG();
131 double genNthMotherIndex(
const Particle* part,
const std::vector<double>& args)
133 const MCParticle* mcparticle = part->getMCParticle();
134 if (!mcparticle)
return 0.0;
136 unsigned int nLevels = args.empty() ? 0 : args[0];
138 const MCParticle* curMCParticle = mcparticle;
139 for (
unsigned int i = 0; i <= nLevels; ++i) {
140 const MCParticle* curMCMother = curMCParticle->getMother();
141 if (!curMCMother)
return 0.0;
142 curMCParticle = curMCMother;
144 return curMCParticle->getArrayIndex();
147 double genQ2PmPd(
const Particle* part,
const std::vector<double>& daughter_indices)
149 const MCParticle* mcparticle = part->getMCParticle();
152 auto daughters = mcparticle->getDaughters();
154 ROOT::Math::PxPyPzEVector p4Daughters;
155 for (
const auto& double_daughter : daughter_indices) {
156 unsigned long daughter = std::lround(double_daughter);
159 p4Daughters += daughters[daughter]->get4Vector();
161 auto p4Mother = mcparticle->get4Vector();
162 return (p4Mother - p4Daughters).mag2();
165 double genMotherPDG(
const Particle* part)
167 return genNthMotherPDG(part, {});
170 double genMotherP(
const Particle* part)
172 const MCParticle* mcparticle = part->getMCParticle();
175 const MCParticle* mcmother = mcparticle->getMother();
178 return mcmother->getMomentum().R();
181 double genMotherIndex(
const Particle* part)
183 return genNthMotherIndex(part, {});
186 double genParticleIndex(
const Particle* part)
188 const MCParticle* mcparticle = part->getMCParticle();
190 return mcparticle->getArrayIndex();
193 double isSignalAcceptMissingNeutrino(
const Particle* part)
195 const MCParticle* mcparticle = part->getMCParticle();
200 status &= (~MCMatching::c_MissNeutrino);
205 double isSignalAcceptMissingMassive(
const Particle* part)
207 const MCParticle* mcparticle = part->getMCParticle();
212 status &= (~MCMatching::c_MissMassiveParticle);
213 status &= (~MCMatching::c_MissKlong);
218 double isSignalAcceptMissingGamma(
const Particle* part)
220 const MCParticle* mcparticle = part->getMCParticle();
225 status &= (~MCMatching::c_MissGamma);
230 double isSignalAcceptMissing(
const Particle* part)
232 const MCParticle* mcparticle = part->getMCParticle();
237 status &= (~MCMatching::c_MissGamma);
238 status &= (~MCMatching::c_MissMassiveParticle);
239 status &= (~MCMatching::c_MissKlong);
240 status &= (~MCMatching::c_MissNeutrino);
245 double isSignalAcceptBremsPhotons(
const Particle* part)
247 const MCParticle* mcparticle = part->getMCParticle();
252 status &= (~MCMatching::c_AddedRecoBremsPhoton);
257 double particleMCMatchPDGCode(
const Particle* part)
259 const MCParticle* mcparticle = part->getMCParticle();
261 return mcparticle->getPDG();
264 double particleMCErrors(
const Particle* part)
269 double particleNumberOfMCMatch(
const Particle* particle)
271 RelationVector<MCParticle> mcRelations = particle->getRelationsTo<MCParticle>();
272 return (mcRelations.size());
275 double particleMCMatchWeight(
const Particle* particle)
277 auto relWithWeight = particle->getRelatedToWithWeight<MCParticle>();
279 return relWithWeight.second;
282 double particleMCMatchDecayTime(
const Particle* part)
284 const MCParticle* mcparticle = part->getMCParticle();
286 return mcparticle->getDecayTime();
289 double particleMCMatchLifeTime(
const Particle* part)
291 const MCParticle* mcparticle = part->getMCParticle();
293 return mcparticle->getLifetime();
296 double particleMCMatchPX(
const Particle* part)
298 const MCParticle* mcparticle = part->getMCParticle();
302 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
303 return frame.getMomentum(mcpP4).Px();
306 double particleMCMatchPY(
const Particle* part)
308 const MCParticle* mcparticle = part->getMCParticle();
312 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
313 return frame.getMomentum(mcpP4).Py();
316 double particleMCMatchPZ(
const Particle* part)
318 const MCParticle* mcparticle = part->getMCParticle();
322 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
323 return frame.getMomentum(mcpP4).Pz();
326 double particleMCMatchPT(
const Particle* part)
328 const MCParticle* mcparticle = part->getMCParticle();
332 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
333 return frame.getMomentum(mcpP4).Pt();
336 double particleMCMatchE(
const Particle* part)
338 const MCParticle* mcparticle = part->getMCParticle();
342 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
343 return frame.getMomentum(mcpP4).E();
346 double particleMCMatchP(
const Particle* part)
348 const MCParticle* mcparticle = part->getMCParticle();
352 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
353 return frame.getMomentum(mcpP4).P();
356 double particleMCMatchTheta(
const Particle* part)
358 const MCParticle* mcparticle = part->getMCParticle();
362 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
363 return frame.getMomentum(mcpP4).Theta();
366 double particleMCMatchPhi(
const Particle* part)
368 const MCParticle* mcparticle = part->getMCParticle();
372 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
373 return frame.getMomentum(mcpP4).Phi();
376 double mcParticleNDaughters(
const Particle* part)
378 const MCParticle* mcparticle = part->getMCParticle();
381 return mcparticle->getNDaughters();
384 double particleMCRecoilMass(
const Particle* part)
386 StoreArray<MCParticle> mcparticles;
389 ROOT::Math::PxPyPzEVector pInitial = mcparticles[0]->get4Vector();
390 ROOT::Math::PxPyPzEVector pDaughters;
391 const std::vector<Particle*> daughters = part->getDaughters();
392 for (
const auto* daughter : daughters) {
393 const MCParticle* mcD = daughter->getMCParticle();
396 pDaughters += mcD->get4Vector();
398 return (pInitial - pDaughters).M();
401 ROOT::Math::PxPyPzEVector MCInvisibleP4(
const MCParticle* mcparticle)
403 ROOT::Math::PxPyPzEVector ResultP4;
404 int pdg = std::abs(mcparticle->getPDG());
405 bool isNeutrino = (pdg == 12 or pdg == 14 or pdg == 16);
407 if (mcparticle->getNDaughters() > 0) {
408 const std::vector<MCParticle*> daughters = mcparticle->getDaughters();
409 for (
const auto* daughter : daughters)
410 ResultP4 += MCInvisibleP4(daughter);
411 }
else if (isNeutrino)
412 ResultP4 += mcparticle->get4Vector();
417 double particleMCCosThetaBetweenParticleAndNominalB(
const Particle* part)
419 int particlePDG = abs(part->getPDGCode());
420 if (particlePDG != 511 and particlePDG != 521)
421 B2FATAL(
"The variable mcCosThetaBetweenParticleAndNominalB is only meant to be used on B mesons!");
424 double e_Beam = T.getCMSEnergy() / 2.0;
425 double m_B = part->getPDGMass();
428 const double mY4S = 10.5794;
431 if (e_Beam * e_Beam - m_B * m_B < 0) {
434 double p_B = std::sqrt(e_Beam * e_Beam - m_B * m_B);
437 const MCParticle* mcB = part->getMCParticle();
440 int mcParticlePDG = std::abs(mcB->getPDG());
441 if (mcParticlePDG != 511 and mcParticlePDG != 521)
444 ROOT::Math::PxPyPzEVector p = T.rotateLabToCms() * (mcB->get4Vector() - MCInvisibleP4(mcB));
449 double theta_BY = (2 * e_Beam * e_d - m_B * m_B - m_d * m_d)
454 double mcParticleSecondaryPhysicsProcess(
const Particle* p)
456 const MCParticle* mcp = p->getMCParticle();
458 return mcp->getSecondaryPhysicsProcess();
461 double mcParticleStatus(
const Particle* p)
463 const MCParticle* mcp = p->getMCParticle();
465 return mcp->getStatus();
468 double particleMCPrimaryParticle(
const Particle* p)
470 const MCParticle* mcp = p->getMCParticle();
474 return mcp->hasStatus(bitmask);
477 double particleMCVirtualParticle(
const Particle* p)
479 const MCParticle* mcp = p->getMCParticle();
483 return mcp->hasStatus(bitmask);
486 double particleMCInitialParticle(
const Particle* p)
488 const MCParticle* mcp = p->getMCParticle();
492 return mcp->hasStatus(bitmask);
495 double particleMCISRParticle(
const Particle* p)
497 const MCParticle* mcp = p->getMCParticle();
501 return mcp->hasStatus(bitmask);
504 double particleMCFSRParticle(
const Particle* p)
506 const MCParticle* mcp = p->getMCParticle();
510 return mcp->hasStatus(bitmask);
513 double particleMCPhotosParticle(
const Particle* p)
515 const MCParticle* mcp = p->getMCParticle();
519 return mcp->hasStatus(bitmask);
522 double generatorEventWeight(
const Particle*)
524 StoreObjPtr<EventMetaData> evtMetaData;
526 return evtMetaData->getGeneratedWeight();
529 int tauPlusMcMode(
const Particle*)
531 StoreObjPtr<TauPairDecay> tauDecay;
533 B2WARNING(
"Cannot find tau decay ID, did you forget to run TauDecayMarkerModule?");
536 return tauDecay->getTauPlusIdMode();
539 int tauMinusMcMode(
const Particle*)
541 StoreObjPtr<TauPairDecay> tauDecay;
543 B2WARNING(
"Cannot find tau decay ID, did you forget to run TauDecayMarkerModule?");
546 return tauDecay->getTauMinusIdMode();
549 int tauPlusMcProng(
const Particle*)
551 StoreObjPtr<TauPairDecay> tauDecay;
553 B2WARNING(
"Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
556 return tauDecay->getTauPlusMcProng();
559 int tauMinusMcProng(
const Particle*)
561 StoreObjPtr<TauPairDecay> tauDecay;
563 B2WARNING(
"Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
566 return tauDecay->getTauMinusMcProng();
569 double tauPlusEgstar(
const Particle*)
571 StoreObjPtr<TauPairDecay> tauDecay;
573 B2WARNING(
"Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
576 return tauDecay->getTauPlusEgstar();
579 double tauMinusEgstar(
const Particle*)
581 StoreObjPtr<TauPairDecay> tauDecay;
583 B2WARNING(
"Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
586 return tauDecay->getTauMinusEgstar();
589 double isReconstructible(
const Particle* p)
591 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
593 const MCParticle* mcp = p->getMCParticle();
598 return (std::abs(mcp->getCharge()) > 0) ? seenInSVD(p) : seenInECL(p);
601 double isTrackFound(
const Particle* p)
603 if (p->getParticleSource() != Particle::EParticleSourceObject::c_MCParticle)
605 const MCParticle* tmp_mcP = p->getMCParticle();
608 const Track* tmp_track = tmp_mcP->getRelated<Track>();
610 const TrackFitResult* tmp_tfr = tmp_track->getTrackFitResultWithClosestMass(Const::ChargedStable(std::abs(tmp_mcP->getPDG())));
615 if (tmp_tfr->getChargeSign()*tmp_mcP->getCharge() > 0)
623 double seenInPXD(
const Particle* p)
625 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
627 const MCParticle* mcp = p->getMCParticle();
629 return mcp->hasSeenInDetector(Const::PXD);
632 double seenInSVD(
const Particle* p)
634 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
636 const MCParticle* mcp = p->getMCParticle();
638 return mcp->hasSeenInDetector(Const::SVD);
641 double seenInCDC(
const Particle* p)
643 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
645 const MCParticle* mcp = p->getMCParticle();
647 return mcp->hasSeenInDetector(Const::CDC);
650 double seenInTOP(
const Particle* p)
652 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
654 const MCParticle* mcp = p->getMCParticle();
656 return mcp->hasSeenInDetector(Const::TOP);
659 double seenInECL(
const Particle* p)
661 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
663 const MCParticle* mcp = p->getMCParticle();
665 return mcp->hasSeenInDetector(Const::ECL);
668 double seenInARICH(
const Particle* p)
670 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
672 const MCParticle* mcp = p->getMCParticle();
674 return mcp->hasSeenInDetector(Const::ARICH);
677 double seenInKLM(
const Particle* p)
679 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
681 const MCParticle* mcp = p->getMCParticle();
683 return mcp->hasSeenInDetector(Const::KLM);
686 int genNStepsToDaughter(
const Particle* p,
const std::vector<double>& arguments)
688 if (arguments.size() != 1)
689 B2FATAL(
"Wrong number of arguments for genNStepsToDaughter");
691 const MCParticle* mcp = p->getMCParticle();
693 B2WARNING(
"No MCParticle is associated to the particle");
697 int nChildren = p->getNDaughters();
698 if (arguments[0] >= nChildren) {
702 const Particle* daugP = p->getDaughter(arguments[0]);
703 const MCParticle* daugMCP = daugP->getMCParticle();
707 B2WARNING(
"No MCParticle is associated to the i-th daughter");
711 if (nChildren == 1)
return 1;
713 std::vector<int> genMothers;
715 auto match = std::find(genMothers.begin(), genMothers.end(), mcp->getIndex());
716 return match - genMothers.begin();
719 int genNMissingDaughter(
const Particle* p,
const std::vector<double>& arguments)
721 if (arguments.size() < 1)
722 B2FATAL(
"Wrong number of arguments for genNMissingDaughter");
724 const std::vector<int> PDGcodes(arguments.begin(), arguments.end());
726 const MCParticle* mcp = p->getMCParticle();
728 B2WARNING(
"No MCParticle is associated to the particle");
735 double getHEREnergy(
const Particle*)
737 static DBObjPtr<BeamParameters> beamParamsDB;
738 if (!beamParamsDB.isValid())
740 return (beamParamsDB->getHER()).E();
743 double getLEREnergy(
const Particle*)
745 static DBObjPtr<BeamParameters> beamParamsDB;
746 if (!beamParamsDB.isValid())
748 return (beamParamsDB->getLER()).E();
751 double getCrossingAngleX(
const Particle*)
754 static DBObjPtr<BeamParameters> beamParamsDB;
755 if (!beamParamsDB.isValid())
757 ROOT::Math::PxPyPzEVector herVec = beamParamsDB->getHER();
758 ROOT::Math::PxPyPzEVector lerVec = beamParamsDB->getLER();
763 return ROOT::Math::VectorUtil::Angle(herVec, -lerVec);
766 double getCrossingAngleY(
const Particle*)
769 static DBObjPtr<BeamParameters> beamParamsDB;
770 if (!beamParamsDB.isValid())
772 ROOT::Math::PxPyPzEVector herVec = beamParamsDB->getHER();
773 ROOT::Math::PxPyPzEVector lerVec = beamParamsDB->getLER();
778 return ROOT::Math::VectorUtil::Angle(herVec, -lerVec);
782 double particleClusterMatchWeight(
const Particle* particle)
790 const MCParticle* matchedToParticle = particle->getMCParticle();
792 int matchedToIndex = matchedToParticle->getArrayIndex();
794 const ECLCluster* cluster = particle->getECLCluster();
797 const auto mcps = cluster->getRelationsTo<MCParticle>();
798 for (
unsigned int i = 0; i < mcps.size(); ++i)
799 if (mcps[i]->getArrayIndex() == matchedToIndex)
800 return mcps.weight(i);
805 double particleClusterBestMCMatchWeight(
const Particle* particle)
817 const ECLCluster* cluster = particle->getECLCluster();
823 auto mcps = cluster->getRelationsTo<MCParticle>();
826 std::vector<double> weights;
827 for (
unsigned int i = 0; i < mcps.size(); ++i)
828 weights.emplace_back(mcps.weight(i));
831 std::sort(weights.begin(), weights.end());
832 std::reverse(weights.begin(), weights.end());
836 double particleClusterBestMCPDGCode(
const Particle* particle)
846 const ECLCluster* cluster = particle->getECLCluster();
849 auto mcps = cluster->getRelationsTo<MCParticle>();
852 std::vector<std::pair<double, int>> weightsAndIndices;
853 for (
unsigned int i = 0; i < mcps.size(); ++i)
854 weightsAndIndices.emplace_back(mcps.weight(i), i);
857 std::sort(weightsAndIndices.begin(), weightsAndIndices.end(),
858 ValueIndexPairSorting::higherPair<
decltype(weightsAndIndices)::value_type>);
859 return mcps.object(weightsAndIndices[0].second)->getPDG();
862 double particleClusterTotalMCMatchWeight(
const Particle* particle)
864 const ECLCluster* cluster = particle->getECLCluster();
867 auto mcps = cluster->getRelationsTo<MCParticle>();
870 double weightsum = 0;
871 for (
unsigned int i = 0; i < mcps.size(); ++i)
872 weightsum += mcps.weight(i);
878 void getKlongWeightMap(
const Particle* particle, std::map<int, double>& mapMCParticleIndxAndWeight)
880 const ECLCluster* cluster = particle->getECLCluster();
881 auto mcps = cluster->getRelationsTo<MCParticle>();
883 for (
unsigned int i = 0; i < mcps.size(); ++i) {
884 double weight = mcps.weight(i);
885 const MCParticle* mcp = mcps[i];
888 if (mcp->getPDG() == 130) {
889 int index = mcp->getArrayIndex();
890 if (mapMCParticleIndxAndWeight.find(index) != mapMCParticleIndxAndWeight.end()) {
891 mapMCParticleIndxAndWeight.at(index) = mapMCParticleIndxAndWeight.at(index) + weight;
893 mapMCParticleIndxAndWeight.insert({index, weight});
897 mcp = mcp->getMother();
903 double particleClusterTotalMCMatchWeightForKlong(
const Particle* particle)
905 const ECLCluster* cluster = particle->getECLCluster();
908 auto mcps = cluster->getRelationsTo<MCParticle>();
911 std::map<int, double> mapMCParticleIndxAndWeight;
912 getKlongWeightMap(particle, mapMCParticleIndxAndWeight);
914 double totalWeight = 0;
915 for (
const auto& map : mapMCParticleIndxAndWeight) {
916 totalWeight += map.second;
922 double particleClusterTotalMCMatchWeightForBestKlong(
const Particle* particle)
924 const ECLCluster* cluster = particle->getECLCluster();
927 auto mcps = cluster->getRelationsTo<MCParticle>();
930 std::map<int, double> mapMCParticleIndxAndWeight;
931 getKlongWeightMap(particle, mapMCParticleIndxAndWeight);
933 if (mapMCParticleIndxAndWeight.size() == 0)
936 auto maxMap = std::max_element(mapMCParticleIndxAndWeight.begin(), mapMCParticleIndxAndWeight.end(),
937 [](
const auto & x,
const auto & y) { return x.second < y.second; }
940 return maxMap->second;
943 double isBBCrossfeed(
const Particle* particle)
945 if (particle ==
nullptr)
948 int pdg = particle->getPDGCode();
949 if (std::abs(pdg) != 511 && std::abs(pdg) != 521 && std::abs(pdg) != 531)
952 std::vector<const Particle*> daughters = particle->getFinalStateDaughters();
953 int nDaughters = daughters.size();
956 std::vector<int> mother_ids;
958 for (
int j = 0; j < nDaughters; ++j) {
959 const MCParticle* curMCParticle = daughters[j]->getMCParticle();
960 while (curMCParticle !=
nullptr) {
961 pdg = curMCParticle->getPDG();
962 if (std::abs(pdg) == 511 || std::abs(pdg) == 521 || std::abs(pdg) == 531) {
963 mother_ids.emplace_back(curMCParticle->getArrayIndex());
966 const MCParticle* curMCMother = curMCParticle->getMother();
967 curMCParticle = curMCMother;
969 if (curMCParticle ==
nullptr) {
974 std::set<int> distinctIDs = std::set(mother_ids.begin(), mother_ids.end());
975 if (distinctIDs.size() == 1)
981 int ancestorBIndex(
const Particle* particle)
983 const MCParticle* mcpart = particle->getMCParticle();
986 int pdg = std::abs(mcpart->getPDG());
988 if ((pdg == 521) || (pdg == 511))
989 return mcpart->getArrayIndex();
991 mcpart = mcpart->getMother();
998 VARIABLE_GROUP(
"MC matching and MC truth");
999 REGISTER_VARIABLE(
"isSignal", isSignal,
1000 "Returns 1.0 if the particle is correctly reconstructed, 0.0 if not, and ``NaN`` if no related MC particle could be found.");
1001 REGISTER_VARIABLE(
"isSignalAcceptWrongFSPs", isSignalAcceptWrongFSPs,
1002 "Returns 1.0 if the particle is almost correctly reconstructed (mis-identified final state particles are allowed), 0.0 if not, and ``NaN`` if no related MC particle could be found.");
1003 REGISTER_VARIABLE(
"isPrimarySignal", isPrimarySignal,
1004 "Returns 1.0 if the particle is correctly reconstructed and primary, 0.0 if not, and ``NaN`` if no related MC particle could be found.");
1005 REGISTER_VARIABLE(
"isSignalAcceptBremsPhotons", isSignalAcceptBremsPhotons,
1006 "Returns 1.0 if the particle is correctly reconstructed, 0.0 if not, and ``NaN`` if no related MC particle could be found.\n"
1007 "Reconstruction involving any recovered Bremsstrahlung photons attached to the particle are still considered correct.");
1008 REGISTER_VARIABLE(
"genMotherPDG", genMotherPDG,
1009 "Returns the PDG code of generated mother of the particle.");
1010 REGISTER_VARIABLE(
"genMotherPDG(i)", genNthMotherPDG,
1011 "Returns the PDG code the :math:`n`-th generated mother of the particle. The argument is the generation: 0 is first mother, 1 is grandmother etc.:noindex:");
1012 REGISTER_VARIABLE(
"genQ2PmPd(i,j,...)", genQ2PmPd, R
"DOC(
1013Returns the generated 4-momentum transfer squared :math:`q^2` calculated as
1015.. math:: q^2 = (p_m - p_{d_i} - p_{d_j} - ...)^2
1017where :math:`p_m` is the 4-momentum of the given (mother) particle,
1018and :math:`p_{d_{i,j,...}}` are the daughter particles with indices :math:`i, j, ...` given as arguments .
1019The ordering of daughters is as defined in the ``DECAY_BELLE2.DEC``
1020file used in the generation, with the numbering starting at :math:`n=0`.
1022Returns ``NaN`` if no related MC particle could be found ot if any of the given indices are larger than the number of daughters of
1025.. admonition:: Remember
1027 The ``DECAY_BELLE2.DEC`` can change between MC campaigns so make sure you look at the correct decay file corresponding to your MC samples.
1029)DOC", ":math:`[\\text{GeV}/\\text{c}]^2`");
1030 REGISTER_VARIABLE(
"genMotherID", genMotherIndex,
1031 "Returns the generated particle array index of a particle's generated mother");
1032 REGISTER_VARIABLE(
"genMotherID(i)", genNthMotherIndex,
1033 "Returns the generated particle array index of the particle's :math:`i`-th generated mother. 0 is first mother, 1 is grandmother etc. :noindex:");
1037 REGISTER_VARIABLE(
"isBBCrossfeed", isBBCrossfeed, R
"DOC(
1038Returns 1 if there is cross-feed between the reconstructed :math:`B` mesons, 0 for no cross-feed and ``NaN`` for
1039no :math:`B` meson reconstructed or there is a failed truth-matching.
1041 REGISTER_VARIABLE("ancestorBIndex", ancestorBIndex,
1042 "Returns the generated particle array index of the particle's :math:`B` meson ancestor, or -1 if no :math:`B` meson or MC particle is found.");
1043 REGISTER_VARIABLE(
"genMotherP", genMotherP, R
"DOC(
1044Returns the equivalent of ``genParticle(genMotherID, p)`` and can be extended to any other (kinematic) variable by replacing the second argument.
1047 Check out the documentation for ``genParticle(index, variable)`` to better understand this.
1050 REGISTER_VARIABLE(
"genParticleID", genParticleIndex,
1051 "Returns the generated particle array index of the particle's matched MC particle.");
1052 REGISTER_VARIABLE(
"isSignalAcceptMissingNeutrino",
1053 isSignalAcceptMissingNeutrino,
1054 "Returns 1.0 if the particle is almost correctly reconstructed (missing neutrinos are allowed), 0.0 if not, and ``NaN`` if no related MC particle could be found.");
1055 REGISTER_VARIABLE(
"isSignalAcceptMissingMassive",
1056 isSignalAcceptMissingMassive,
1057 "Returns 1.0 if the particle is almost correctly reconstructed (missing massive particles are allowed), 0.0 if not, and ``NaN`` if no related MC particle could be found.");
1058 REGISTER_VARIABLE(
"isSignalAcceptMissingGamma",
1059 isSignalAcceptMissingGamma,
1060 "Returns 1.0 if the particle is almost correctly reconstructed (missing photons are allowed), 0.0 if not, and ``NaN`` if no related MC particle could be found.");
1061 REGISTER_VARIABLE(
"isSignalAcceptMissing",
1062 isSignalAcceptMissing,
1063 "Returns 1.0 if the particle is almost correctly reconstructed (missing particles are allowed), 0.0 if not, and ``NaN`` if no related MC particle could be found.");
1064 REGISTER_VARIABLE(
"isMisidentified", isMisidentified,
1065 "Returns 1 if the particle is mis-identified (the wrong PDG code is assigned), 0 if PDG code is correct, and ``NaN`` if no related MC particle could be found.");
1066 REGISTER_VARIABLE(
"isWrongCharge", isWrongCharge,
1067 "Returns 1 if the charge of the particle is wrongly assigned, 0 if it's the correct charge, and ``NaN`` if no related MC particle could be found.");
1068 REGISTER_VARIABLE(
"isCloneTrack", isCloneTrack,
1069 "Returns 1 if the charged final state particle comes from a cloned track, 0 if it does not come from a clone, and ``NaN`` if the particle is neutral, composite, or no MC particle could be found.");
1070 REGISTER_VARIABLE(
"isOrHasCloneTrack", isOrHasCloneTrack,
1071 "Returns 1 if the particle is a clone track or has a clone track as a daughter, 0 otherwise.");
1072 REGISTER_VARIABLE(
"mcPDG", particleMCMatchPDGCode, R
"DOC(
1073Returns the PDG code of matched MC particle or ``NaN`` if no match could be found.
1076 This requires running `matchMCTruth()` either on the reconstructed particle, or one of its ancestors, or a particle list filled with MC particle objects.
1079 REGISTER_VARIABLE("mcErrors", particleMCErrors, R
"DOC(
1080Returns the bit pattern indicating the quality of MC matching.
1082.. note:: The bit pattern is explained in :ref:`Error_flags`.
1085 REGISTER_VARIABLE("mcMatchWeight", particleMCMatchWeight, R
"DOC(
1086Returns the weight of the first (and largest) ``Particle -> MCParticle`` relation.
1088 REGISTER_VARIABLE("nMCMatches", particleNumberOfMCMatch,
1089 "Returns the number of ``Particle -> MCParticle`` relations.");
1090 REGISTER_VARIABLE(
"mcDecayTime", particleMCMatchDecayTime, R
"DOC(
1091Returns the decay time of matched MC particle, or ``NaN`` if no match is found.
1094 This requires running `matchMCTruth()` either on the reconstructed particle, or one of its ancestors, or a particle list filled with MC particle objects.
1097 REGISTER_VARIABLE(
"mcLifeTime", particleMCMatchLifeTime,R
"DOC(
1098Returns the lifetime of matched MC particle, or ``NaN`` if no match is found.
1101 This requires running `matchMCTruth()` either on the reconstructed particle, or one of its ancestors, or a particle list filled with MC particle objects.
1104 REGISTER_VARIABLE(
"mcPX", particleMCMatchPX, R
"DOC(
1105Returns the momentum component :math:`p_x` of matched MC particle, or ``NaN`` if no match is found.
1108 This requires running `matchMCTruth()` either on the reconstructed particle, or one of its ancestors, or a particle list filled with MC particle objects.
1111 REGISTER_VARIABLE(
"mcPY", particleMCMatchPY,R
"DOC(
1112Returns the momentum component :math:`p_y` of matched MC particle, or ``NaN`` if no match is found.
1115 This requires running `matchMCTruth()` either on the reconstructed particle, or one of its ancestors, or a particle list filled with MC particle objects.
1118 REGISTER_VARIABLE(
"mcPZ", particleMCMatchPZ,R
"DOC(
1119Returns the momentum component :math:`p_z` of matched MC particle, or ``NaN`` if no match is found.
1122 This requires running `matchMCTruth()` either on the reconstructed particle, or one of its ancestors, or a particle list filled with MC particle objects.
1125 REGISTER_VARIABLE(
"mcPT", particleMCMatchPT,R
"DOC(
1126Returns the transverse momentum component :math:`p_T` of matched MC particle, or ``NaN`` if no match is found.
1129 This requires running `matchMCTruth()` either on the reconstructed particle, or one of its ancestors, or a particle list filled with MC particle objects.
1132 REGISTER_VARIABLE(
"mcE", particleMCMatchE,R
"DOC(
1133Returns the energy of matched MC particle, or ``NaN`` if no match is found.
1136 This requires running `matchMCTruth()` either on the reconstructed particle, or one of its ancestors, or a particle list filled with MC particle objects.
1139 REGISTER_VARIABLE(
"mcP", particleMCMatchP,R
"DOC(
1140Returns the total momentum :math:`p` of matched MC particle, or ``NaN`` if no match is found.
1143 This requires running `matchMCTruth()` either on the reconstructed particle, or one of its ancestors, or a particle list filled with MC particle objects.
1146 REGISTER_VARIABLE(
"mcPhi", particleMCMatchPhi,R
"DOC(
1147Returns the azimuthal angle :math:`\phi` of matched MC particle, or ``NaN`` if no match is found.
1150 This requires running `matchMCTruth()` either on the reconstructed particle, or one of its ancestors, or a particle list filled with MC particle objects.
1153 REGISTER_VARIABLE(
"mcTheta", particleMCMatchTheta,R
"DOC(
1154Returns the polar angle :math:`\theta` of matched MC particle, or ``NaN`` if no match is found.
1157 This requires running `matchMCTruth()` either on the reconstructed particle, or one of its ancestors, or a particle list filled with MC particle objects.
1160 REGISTER_VARIABLE(
"nMCDaughters", mcParticleNDaughters,R
"DOC(
1161Returns the number of daughters of the matched MC particle, or ``NaN`` if no match is found.
1164 This requires running `matchMCTruth()` either on the reconstructed particle, or one of its ancestors, or a particle list filled with MC particle objects.
1167 REGISTER_VARIABLE("mcRecoilMass", particleMCRecoilMass,
1168 "Returns the mass recoiling against the given particle's daughters, calculated using MC truth values.",
1169 "GeV/:math:`\\text{c}^2`");
1170 REGISTER_VARIABLE(
"mcCosThetaBetweenParticleAndNominalB",
1171 particleMCCosThetaBetweenParticleAndNominalB,
1172 "Returns the cosine of the angle between the CM momentum :math:`p_{CM}` of the selected :math:`B` meson and its daughters. It is calculated using MC truth values, with all neutrinos descending from the :math:`B` removed.");
1173 REGISTER_VARIABLE(
"mcSecPhysProc", mcParticleSecondaryPhysicsProcess, R
"DOC(
1174Returns the Geant4 process flag for the matched (secondary) MC particle, ``NaN`` if no MC particle is found, 0 if the matched MC particle is primary
1175or -1 in the case of an unknown process.
1177The process flags are:
1179* 1 - Coulomb scattering
1182* 4 - Pair production by charged
1184* 6 - Annihilation to mu mu
1185* 7 - Annihilation to hadrons
1186* 8 - Nuclear stopping
1187* 9 - Electron general process
1188* 10 - Multiple scattering
1190* 12 - Photo-electric effect
1191* 13 - Compton scattering
1192* 14 - Photon conversion
1193* 15 - Photon conversion to mu mu
1194* 16 - Photon general process
1197* 23 - Synchrotron radiation
1198* 24 - Transition radiation
1199* 91 - Transportation
1200* 92 - Coupled transportation
1201* 111 - Hadron elastic
1202* 121 - Hadron inelastic
1204* 132 - Mu atomic capture
1206* 151 - Hadron at rest
1207* 152 - Lepton at rest
1208* 161 - Charge exchange
1210* 202 - Decay with spin
1211* 203 - Decay (pion make spin)
1212* 210 - Radioactive decay
1213* 211 - Unknown decay
1214* 221 - Mu atom decay
1215* 231 - External decay
1218 The list of Geant4 processes was taken from the following sources:
1220 - `G4DecayProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/decay/include/G4DecayProcessType.hh>`_
1221 - `G4HadronicProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/hadronic/management/include/G4HadronicProcessType.hh>`_
1222 - `G4TransportationProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/transportation/include/G4TransportationProcessType.hh>`_
1223 - `G4EmProcessSubType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/electromagnetic/utils/include/G4EmProcessSubType.hh>`_
1227 This code is shown by `modularAnalysis.printMCParticles` under the name of ``creation process`` when ``showStatus`` is set.
1230 REGISTER_VARIABLE("mcParticleStatus", mcParticleStatus, R
"DOC(
1231Returns the status bit of the matched MC particle, or ``NaN`` if the MC particle relation was not set.
1233.. note:: The particle status is explained in :ref:`Particle_status`.
1236 REGISTER_VARIABLE("mcPrimary", particleMCPrimaryParticle,
1237 "Returns 1 if the particle is matched to a primary MC particle, 0 if Particle is matched to secondary MC particle, "
1238 "or ``NaN`` if no MC particle is found.");
1239 REGISTER_VARIABLE(
"mcVirtual", particleMCVirtualParticle,
1240 "Returns 1 if the particle is matched to a virtual MC particle, 0 if the particle is matched to a non-virtual MC particle, "
1241 "or ``NaN`` if no MC particle is found.");
1242 REGISTER_VARIABLE(
"mcInitial", particleMCInitialParticle,
1243 "Returns 1 if the particle is matched to an initial MC particle, 0 if the particle is matched to a non-initial MC particle, "
1244 "or ``NaN`` if no MC particle is found.");
1245 REGISTER_VARIABLE(
"mcISR", particleMCISRParticle,
1246 "Returns 1 if the particle is related to an ISR MC particle, 0 if it is related to a non-ISR MC particle, or "
1247 "or ``NaN`` if no MC particle is found.");
1248 REGISTER_VARIABLE(
"mcFSR", particleMCFSRParticle,
1249 "Returns 1 if the particle is related to an FSR MC particle, 0 if it is related to a non-FSR MC particle, or "
1250 "or ``NaN`` if no MC particle is found.");
1251 REGISTER_VARIABLE(
"mcPhotos", particleMCPhotosParticle,
1252 "Returns 1 if the particle is related to Photos particle, 0 if it is related to a non-Photos MC particle, or "
1253 "or ``NaN`` if no MC particle is found.");
1254 REGISTER_VARIABLE(
"generatorEventWeight", generatorEventWeight,
1255 "**[Eventbased]** Returns the event weight produced by the event generator.");
1256 REGISTER_VARIABLE(
"genNStepsToDaughter(i)", genNStepsToDaughter,
1257 "Returns the number of steps to :math:`i`-th daughter of the particle at generator level, or "
1258 "``NaN`` if no MC particle is associated to the particle or :math:`i`-th daughter, or if the "
1259 ":math:`i`-th daughter does not exist.");
1260 REGISTER_VARIABLE(
"genNMissingDaughter(PDG)", genNMissingDaughter,
1261 "Returns the number of missing daughters with the specified PDG code, or ``NaN`` if no related MC particle could be found.");
1262 REGISTER_VARIABLE(
"Eher", getHEREnergy, R
"DOC(
1263**[Eventbased]** Returns the nominal HER energy used by the generator.
1265.. warning:: This variable does not make sense for data and should not be used.
1268 REGISTER_VARIABLE("Eler", getLEREnergy, R"DOC(
1269**[Eventbased]** Returns the nominal LER energy used by the generator.
1271.. warning:: This variable does not make sense for data and should not be used.
1274 REGISTER_VARIABLE("XAngle", getCrossingAngleX, R"DOC(
1275**[Eventbased]** Returns the nominal beam crossing angle in the :math:`x-z` plane from generator-level beam kinematics.
1277.. warning:: This variable does not make sense for data and should not be used.
1280 REGISTER_VARIABLE("YAngle", getCrossingAngleY, R"DOC(
1281**[Eventbased]** Returns the nominal beam crossing angle in the :math:`y-z` plane from generator-level beam kinematics.
1283.. warning:: This variable does not make sense for data and should not be used.
1287 VARIABLE_GROUP("Generated tau decay information");
1288 REGISTER_VARIABLE("tauPlusMCMode", tauPlusMcMode, R"DOC(
1289**[Eventbased]** Returns the decay ID for the positive :math:`\tau` lepton in a :math:`\tau\tau` generated event."
1291.. attention:: Calculating this variable requires using the ``TauDecayMarkerModule`` in your steering file.
1293.. note:: The list of decay modes is documented in :ref:`TauDecayMCModes`.
1296 REGISTER_VARIABLE("tauMinusMCMode", tauMinusMcMode, R
"DOC(
1297**[Eventbased]** Returns the decay ID for the negative :math:`\tau` lepton in a :math:`\tau\tau` generated event.
1299.. attention:: Calculating this variable requires using the ``TauDecayMarkerModule`` in your steering file.
1301.. note:: The list of decay modes is documented in :ref:`TauDecayMCModes`.
1304 REGISTER_VARIABLE("tauPlusMCProng", tauPlusMcProng, R
"DOC(
1305**[Eventbased]** Returns the prong for the positive :math:`\tau` lepton in a :math:`\tau\tau` generated event.
1307.. attention:: Calculating this variable requires using the ``TauDecayMarkerModule`` in your steering file.
1309.. note:: The list of decay modes is documented in :ref:`TauDecayMCModes`.
1312 REGISTER_VARIABLE("tauMinusMCProng", tauMinusMcProng, R
"DOC(
1313**[Eventbased]** Returns the prong for the negative :math:`\tau` lepton in a :math:`\tau\tau` generated event.
1315.. attention:: Calculating this variable requires using the ``TauDecayMarkerModule`` in your steering file.
1317.. note:: The list of decay modes is documented in :ref:`TauDecayMCModes`.
1320 REGISTER_VARIABLE("tauPlusEgstar", tauPlusEgstar, R
"DOC(
1321**[Eventbased]** Returns the energy of radiated photon from the positive :math:`\tau` lepton in a :math:`\tau\tau` generated event.
1323.. attention:: Calculating this variable requires using the ``TauDecayMarkerModule`` in your steering file.
1325.. note:: The list of decay modes is documented in :ref:`TauDecayMCModes`.
1328 REGISTER_VARIABLE("tauMinusEgstar", tauMinusEgstar, R
"DOC(
1329**[Eventbased]** Returns the energy of radiated photon from the negative :math:`\tau` lepton in a :math:`\tau\tau` generated event.
1331.. attention:: Calculating this variable requires using the ``TauDecayMarkerModule`` in your steering file.
1333.. note:: The list of decay modes is documented in :ref:`TauDecayMCModes`.
1337 VARIABLE_GROUP("MC particle seen in subdetectors");
1338 REGISTER_VARIABLE(
"isReconstructible", isReconstructible, R
"DOC(
1339Returns 1.0 if a charged particle was seen in the SVD or a neutral particle was seen in the ECL, 0.0 if not, or ``NaN`` for composite particles or if no related MC particle could be found.
1341.. tip:: This is useful for generator studies not for particle reconstruction.
1344 REGISTER_VARIABLE("seenInPXD", seenInPXD, R
"DOC(
1345Returns 1.0 if the particle was seen in the PXD, 0.0 if not, or ``NaN`` for composite particles or if no related MC particle could be found.
1347.. tip:: This is useful for generator studies not for particle reconstruction.
1350 REGISTER_VARIABLE("isTrackFound", isTrackFound, R
"DOC(
1351Returns 1.0 if there is a reconstructed track related to a charged stable MC particle with the correct charge, -1.0 if the reconstructed track has the wrong charge, or
13520.0 if no reconstructed track is found. Returns ``NaN`` if there is no charged stable particle list created from the MC particles.
1354 REGISTER_VARIABLE("seenInSVD", seenInSVD, R
"DOC(
1355Returns 1.0 if the particle was seen in the SVD, 0.0 if not, or ``NaN`` for composite particles or if no related MC particle could be found.
1357.. tip:: This is useful for generator studies not for particle reconstruction.
1360 REGISTER_VARIABLE("seenInCDC", seenInCDC, R
"DOC(
1361Returns 1.0 if the particle was seen in the CDC, 0.0 if not, or ``NaN`` for composite particles or if no related MC particle could be found.
1363.. tip:: This is useful for generator studies not for particle reconstruction.
1366 REGISTER_VARIABLE("seenInTOP", seenInTOP, R
"DOC(
1367Returns 1.0 if the particle was seen in the TOP, 0.0 if not, or ``NaN`` for composite particles or if no related MC particle could be found.
1369.. tip:: This is useful for generator studies not for particle reconstruction.
1372 REGISTER_VARIABLE("seenInECL", seenInECL, R
"DOC(
1373Returns 1.0 if the particle was seen in the ECL, 0.0 if not, or ``NaN`` for composite particles or if no related MC particle could be found.
1375.. tip:: This is useful for generator studies not for particle reconstruction.
1378 REGISTER_VARIABLE("seenInARICH", seenInARICH, R
"DOC(
1379Returns 1.0 if the particle was seen in the ARICH, 0.0 if not, or ``NaN`` for composite particles or if no related MC particle could be found.
1381.. tip:: This is useful for generator studies not for particle reconstruction.
1384 REGISTER_VARIABLE("seenInKLM", seenInKLM, R
"DOC(
1385Returns 1.0 if the particle was seen in the KLM, 0.0 if not, or ``NaN`` for composite particles or if no related MC particle could be found.
1387.. tip:: This is useful for generator studies not for particle reconstruction.
1390 REGISTER_VARIABLE("clusterMCMatchWeight", particleClusterMatchWeight, R
"DOC(
1391Returns the weight of the ``ECLCluster`` :math:`\rightarrow` ``MCParticle`` relation for the matched MC particle. It returns ``NaN``
1392if no ECL cluster is related to the reconstructed particle or if there are no MC matches for the cluster.
1394.. seealso:: The ``ECLCluster`` :math:`\rightarrow` ``MCParticle`` relation is described in detail in :ref:`ecl-mcmatching`.
1397 REGISTER_VARIABLE("clusterBestMCMatchWeight", particleClusterBestMCMatchWeight, R
"DOC(
1398Returns the weight of the ``ECLCluster`` :math:`\rightarrow` ``MCParticle`` relation for the relation with the largest weight. It returns ``NaN``
1399if no ECL cluster is related to the reconstructed particle or if there are no MC matches for the cluster.
1401.. seealso:: The ``ECLCluster`` :math:`\rightarrow` ``MCParticle`` relation is described in detail in :ref:`ecl-mcmatching`.
1404 REGISTER_VARIABLE("clusterBestMCPDG", particleClusterBestMCPDGCode, R
"DOC(
1405Returns the PDG code of the MC particle for the ``ECLCluster`` :math:`\rightarrow` ``MCParticle`` relation with the largest weight. It returns ``NaN``
1406if no ECL cluster is related to the reconstructed particle or if there are no MC matches for the cluster.
1408.. seealso:: The ``ECLCluster`` :math:`\rightarrow` ``MCParticle`` relation is described in detail in :ref:`ecl-mcmatching`.
1411 REGISTER_VARIABLE("clusterTotalMCMatchWeight", particleClusterTotalMCMatchWeight, R
"DOC(
1412Returns the sum of all weights for the ``ECLCluster`` :math:`\rightarrow` ``MCParticle`` relation. It returns ``NaN``
1413if no ECL cluster is related to the particle.
1415.. seealso:: The ``ECLCluster`` :math:`\rightarrow` ``MCParticle`` relation is described in detail in :ref:`ecl-mcmatching`.
1418 REGISTER_VARIABLE("clusterTotalMCMatchWeightForKlong", particleClusterTotalMCMatchWeightForKlong, R
"DOC(
1419Returns the sum of all weights for the ``ECLCluster`` :math:`\rightarrow` ``MCParticle`` relation when the MC particle is either a :math:`K_L^0` or
1420a daughter of a :math:`K_L^0`. It returns ``NaN`` if no ECL cluster is related to the reconstructed particle or if there are no MC matches for the cluster, and
1421it returns 0 if there are no weights between the ECL cluster and :math:`K_L^0` particles.
1423.. seealso:: The ``ECLCluster`` :math:`\rightarrow` ``MCParticle`` relation is described in detail in :ref:`ecl-mcmatching`.
1426 REGISTER_VARIABLE("clusterTotalMCMatchWeightForBestKlong", particleClusterTotalMCMatchWeightForBestKlong, R
"DOC(
1427Returns the sum of all weights for the ``ECLCluster`` :math:`\rightarrow` ``MCParticle`` relation when the MC particle is either a :math:`K_L^0` or
1428a daughter of a :math:`K_L^0`. If multiple :math:`K_L^0` are related to the ECL cluster, the sum of weights for the best-matched (highest weighted) :math:`K_L^0` are returned.
1429It returns ``NaN`` if no ECL cluster is related to the reconstructed particle or if there are no MC matches for the cluster, and it returns 0 if there are
1430no weights between the ECL cluster and :math:`K_L^0` particles.
1432.. seealso:: The ``ECLCluster`` :math:`\rightarrow` ``MCParticle`` relation is described in detail in :ref:`ecl-mcmatching`.
static const ParticleSet chargedStableSet
set of charged stable particles
static const double doubleNaN
quiet_NaN
@ c_IsFSRPhoton
bit 7: Particle is from final state radiation
@ c_Initial
bit 5: Particle is initial such as e+ or e- and not going to Geant4
@ c_IsPHOTOSPhoton
bit 8: Particle is an radiative photon from PHOTOS
@ c_PrimaryParticle
bit 0: Particle is primary particle.
@ c_IsVirtual
bit 4: Particle is virtual and not going to Geant4.
@ c_IsISRPhoton
bit 6: Particle is from initial state radiation
static const ReferenceFrame & GetCurrent()
Get current rest frame.
Abstract base class for different kinds of events.
@ c_Correct
This Particle and all its daughters are perfectly reconstructed.
@ c_MisID
One of the charged final state particles is mis-identified, i.e.
static void fillGenMothers(const MCParticle *mcP, std::vector< int > &genMCPMothers)
Fills vector with array (1-based) indices of all generator ancestors of given MCParticle.
static int countMissingParticle(const Particle *particle, const MCParticle *mcParticle, const std::vector< int > &daughterPDG)
Count the number of missing daughters of the 'particle'.
static int getMCErrors(const Particle *particle, const MCParticle *mcParticle=nullptr)
Returns quality indicator of the match as a bit pattern where the individual bits indicate the the ty...