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>
43 double isSignal(
const Particle* part)
52 double isSignalAcceptWrongFSPs(
const Particle* part)
59 status &= (~MCMatching::c_MisID);
60 status &= (~MCMatching::c_AddedWrongParticle);
65 double isPrimarySignal(
const Particle* part)
67 return (isSignal(part) > 0.5 and particleMCPrimaryParticle(part) > 0.5);
70 double isMisidentified(
const Particle* part)
78 double isWrongCharge(
const Particle* part)
82 return (part->getCharge() != mcp->getCharge());
85 double isCloneTrack(
const Particle* particle)
91 const auto mcpww = particle->getRelatedToWithWeight<MCParticle>();
93 return (mcpww.second < 0);
96 double isOrHasCloneTrack(
const Particle* particle)
99 std::queue<const Particle*> qq;
101 while (!qq.empty()) {
102 const auto d = qq.front();
104 if (isCloneTrack(d) == 1.0)
return 1.0;
105 size_t nDau = d->getNDaughters();
106 for (
size_t iDau = 0; iDau < nDau; ++iDau)
107 qq.push(d->getDaughter(iDau));
112 double genNthMotherPDG(
const Particle* part,
const std::vector<double>& args)
115 if (!mcparticle)
return 0.0;
117 unsigned int nLevels = args.empty() ? 0 : args[0];
119 const MCParticle* curMCParticle = mcparticle;
120 for (
unsigned int i = 0; i <= nLevels; ++i) {
121 const MCParticle* curMCMother = curMCParticle->getMother();
122 if (!curMCMother)
return 0.0;
123 curMCParticle = curMCMother;
125 return curMCParticle->getPDG();
128 double genNthMotherIndex(
const Particle* part,
const std::vector<double>& args)
131 if (!mcparticle)
return 0.0;
133 unsigned int nLevels = args.empty() ? 0 : args[0];
135 const MCParticle* curMCParticle = mcparticle;
136 for (
unsigned int i = 0; i <= nLevels; ++i) {
137 const MCParticle* curMCMother = curMCParticle->getMother();
138 if (!curMCMother)
return 0.0;
139 curMCParticle = curMCMother;
144 double genQ2PmPd(
const Particle* part,
const std::vector<double>& daughter_indices)
149 auto daughters = mcparticle->getDaughters();
151 ROOT::Math::PxPyPzEVector p4Daughters;
152 for (
auto& double_daughter : daughter_indices) {
153 unsigned long daughter = std::lround(double_daughter);
156 p4Daughters += daughters[daughter]->get4Vector();
158 auto p4Mother = mcparticle->get4Vector();
159 return (p4Mother - p4Daughters).mag2();
162 double genMotherPDG(
const Particle* part)
164 return genNthMotherPDG(part, {});
167 double genMotherP(
const Particle* part)
172 const MCParticle* mcmother = mcparticle->getMother();
175 return mcmother->getMomentum().R();
178 double genMotherIndex(
const Particle* part)
180 return genNthMotherIndex(part, {});
183 double genParticleIndex(
const Particle* part)
187 return mcparticle->getArrayIndex();
190 double isSignalAcceptMissingNeutrino(
const Particle* part)
197 status &= (~MCMatching::c_MissNeutrino);
202 double isSignalAcceptMissingMassive(
const Particle* part)
209 status &= (~MCMatching::c_MissMassiveParticle);
210 status &= (~MCMatching::c_MissKlong);
215 double isSignalAcceptMissingGamma(
const Particle* part)
222 status &= (~MCMatching::c_MissGamma);
227 double isSignalAcceptMissing(
const Particle* part)
234 status &= (~MCMatching::c_MissGamma);
235 status &= (~MCMatching::c_MissMassiveParticle);
236 status &= (~MCMatching::c_MissKlong);
237 status &= (~MCMatching::c_MissNeutrino);
242 double isSignalAcceptBremsPhotons(
const Particle* part)
249 status &= (~MCMatching::c_AddedRecoBremsPhoton);
254 double particleMCMatchPDGCode(
const Particle* part)
258 return mcparticle->getPDG();
261 double particleMCErrors(
const Particle* part)
266 double particleNumberOfMCMatch(
const Particle* particle)
268 RelationVector<MCParticle> mcRelations = particle->getRelationsTo<MCParticle>();
269 return (mcRelations.size());
272 double particleMCMatchWeight(
const Particle* particle)
274 auto relWithWeight = particle->getRelatedToWithWeight<MCParticle>();
276 return relWithWeight.second;
279 double particleMCMatchDecayTime(
const Particle* part)
283 return mcparticle->getDecayTime();
286 double particleMCMatchLifeTime(
const Particle* part)
290 return mcparticle->getLifetime();
293 double particleMCMatchPX(
const Particle* part)
299 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
300 return frame.getMomentum(mcpP4).Px();
303 double particleMCMatchPY(
const Particle* part)
309 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
310 return frame.getMomentum(mcpP4).Py();
313 double particleMCMatchPZ(
const Particle* part)
319 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
320 return frame.getMomentum(mcpP4).Pz();
323 double particleMCMatchPT(
const Particle* part)
329 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
330 return frame.getMomentum(mcpP4).Pt();
333 double particleMCMatchE(
const Particle* part)
339 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
340 return frame.getMomentum(mcpP4).E();
343 double particleMCMatchP(
const Particle* part)
349 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
350 return frame.getMomentum(mcpP4).P();
353 double particleMCMatchTheta(
const Particle* part)
359 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
360 return frame.getMomentum(mcpP4).Theta();
363 double particleMCMatchPhi(
const Particle* part)
369 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
370 return frame.getMomentum(mcpP4).Phi();
373 double mcParticleNDaughters(
const Particle* part)
378 return mcparticle->getNDaughters();
381 double particleMCRecoilMass(
const Particle* part)
383 StoreArray<MCParticle> mcparticles;
386 ROOT::Math::PxPyPzEVector pInitial = mcparticles[0]->get4Vector();
387 ROOT::Math::PxPyPzEVector pDaughters;
388 const std::vector<Particle*> daughters = part->getDaughters();
389 for (
auto daughter : daughters) {
390 const MCParticle* mcD = daughter->getMCParticle();
393 pDaughters += mcD->get4Vector();
395 return (pInitial - pDaughters).M();
398 ROOT::Math::PxPyPzEVector MCInvisibleP4(
const MCParticle* mcparticle)
400 ROOT::Math::PxPyPzEVector ResultP4;
401 int pdg = abs(mcparticle->getPDG());
402 bool isNeutrino = (pdg == 12 or pdg == 14 or pdg == 16);
404 if (mcparticle->getNDaughters() > 0) {
405 const std::vector<MCParticle*> daughters = mcparticle->getDaughters();
406 for (
auto daughter : daughters)
407 ResultP4 += MCInvisibleP4(daughter);
408 }
else if (isNeutrino)
409 ResultP4 += mcparticle->get4Vector();
414 double particleMCCosThetaBetweenParticleAndNominalB(
const Particle* part)
416 int particlePDG = abs(part->getPDGCode());
417 if (particlePDG != 511 and particlePDG != 521)
418 B2FATAL(
"The variable mcCosThetaBetweenParticleAndNominalB is only meant to be used on B mesons!");
421 double e_Beam = T.getCMSEnergy() / 2.0;
422 double m_B = part->getPDGMass();
425 const double mY4S = 10.5794;
428 if (e_Beam * e_Beam - m_B * m_B < 0) {
431 double p_B = std::sqrt(e_Beam * e_Beam - m_B * m_B);
437 int mcParticlePDG = abs(mcB->getPDG());
438 if (mcParticlePDG != 511 and mcParticlePDG != 521)
441 ROOT::Math::PxPyPzEVector p = T.rotateLabToCms() * (mcB->get4Vector() - MCInvisibleP4(mcB));
446 double theta_BY = (2 * e_Beam * e_d - m_B * m_B - m_d * m_d)
451 double mcParticleSecondaryPhysicsProcess(
const Particle* p)
453 const MCParticle* mcp = p->getMCParticle();
455 return mcp->getSecondaryPhysicsProcess();
458 double mcParticleStatus(
const Particle* p)
460 const MCParticle* mcp = p->getMCParticle();
462 return mcp->getStatus();
465 double particleMCPrimaryParticle(
const Particle* p)
467 const MCParticle* mcp = p->getMCParticle();
471 return mcp->hasStatus(bitmask);
474 double particleMCVirtualParticle(
const Particle* p)
476 const MCParticle* mcp = p->getMCParticle();
480 return mcp->hasStatus(bitmask);
483 double particleMCInitialParticle(
const Particle* p)
485 const MCParticle* mcp = p->getMCParticle();
489 return mcp->hasStatus(bitmask);
492 double particleMCISRParticle(
const Particle* p)
494 const MCParticle* mcp = p->getMCParticle();
498 return mcp->hasStatus(bitmask);
501 double particleMCFSRParticle(
const Particle* p)
503 const MCParticle* mcp = p->getMCParticle();
507 return mcp->hasStatus(bitmask);
510 double particleMCPhotosParticle(
const Particle* p)
512 const MCParticle* mcp = p->getMCParticle();
516 return mcp->hasStatus(bitmask);
519 double generatorEventWeight(
const Particle*)
521 StoreObjPtr<EventMetaData> evtMetaData;
523 return evtMetaData->getGeneratedWeight();
526 int tauPlusMcMode(
const Particle*)
528 StoreObjPtr<TauPairDecay> tauDecay;
530 B2WARNING(
"Cannot find tau decay ID, did you forget to run TauDecayMarkerModule?");
533 return tauDecay->getTauPlusIdMode();
536 int tauMinusMcMode(
const Particle*)
538 StoreObjPtr<TauPairDecay> tauDecay;
540 B2WARNING(
"Cannot find tau decay ID, did you forget to run TauDecayMarkerModule?");
543 return tauDecay->getTauMinusIdMode();
546 int tauPlusMcProng(
const Particle*)
548 StoreObjPtr<TauPairDecay> tauDecay;
550 B2WARNING(
"Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
553 return tauDecay->getTauPlusMcProng();
556 int tauMinusMcProng(
const Particle*)
558 StoreObjPtr<TauPairDecay> tauDecay;
560 B2WARNING(
"Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
563 return tauDecay->getTauMinusMcProng();
566 double isReconstructible(
const Particle* p)
568 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
570 const MCParticle* mcp = p->getMCParticle();
575 return (abs(mcp->getCharge()) > 0) ? seenInSVD(p) : seenInECL(p);
578 double isTrackFound(
const Particle* p)
580 if (p->getParticleSource() != Particle::EParticleSourceObject::c_MCParticle)
582 const MCParticle* tmp_mcP = p->getMCParticle();
585 Track* tmp_track = tmp_mcP->getRelated<Track>();
587 const TrackFitResult* tmp_tfr = tmp_track->getTrackFitResultWithClosestMass(Const::ChargedStable(abs(tmp_mcP->getPDG())));
588 if (tmp_tfr->getChargeSign()*tmp_mcP->getCharge() > 0)
596 double seenInPXD(
const Particle* p)
598 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
600 const MCParticle* mcp = p->getMCParticle();
602 return mcp->hasSeenInDetector(Const::PXD);
605 double seenInSVD(
const Particle* p)
607 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
609 const MCParticle* mcp = p->getMCParticle();
611 return mcp->hasSeenInDetector(Const::SVD);
614 double seenInCDC(
const Particle* p)
616 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
618 const MCParticle* mcp = p->getMCParticle();
620 return mcp->hasSeenInDetector(Const::CDC);
623 double seenInTOP(
const Particle* p)
625 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
627 const MCParticle* mcp = p->getMCParticle();
629 return mcp->hasSeenInDetector(Const::TOP);
632 double seenInECL(
const Particle* p)
634 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
636 const MCParticle* mcp = p->getMCParticle();
638 return mcp->hasSeenInDetector(Const::ECL);
641 double seenInARICH(
const Particle* p)
643 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
645 const MCParticle* mcp = p->getMCParticle();
647 return mcp->hasSeenInDetector(Const::ARICH);
650 double seenInKLM(
const Particle* p)
652 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
654 const MCParticle* mcp = p->getMCParticle();
656 return mcp->hasSeenInDetector(Const::KLM);
659 int genNStepsToDaughter(
const Particle* p,
const std::vector<double>& arguments)
661 if (arguments.size() != 1)
662 B2FATAL(
"Wrong number of arguments for genNStepsToDaughter");
664 const MCParticle* mcp = p->getMCParticle();
666 B2WARNING(
"No MCParticle is associated to the particle");
670 int nChildren = p->getNDaughters();
671 if (arguments[0] >= nChildren) {
675 const Particle* daugP = p->getDaughter(arguments[0]);
680 B2WARNING(
"No MCParticle is associated to the i-th daughter");
684 if (nChildren == 1)
return 1;
686 std::vector<int> genMothers;
688 auto match = std::find(genMothers.begin(), genMothers.end(), mcp->getIndex());
689 return match - genMothers.begin();
692 int genNMissingDaughter(
const Particle* p,
const std::vector<double>& arguments)
694 if (arguments.size() < 1)
695 B2FATAL(
"Wrong number of arguments for genNMissingDaughter");
697 const std::vector<int> PDGcodes(arguments.begin(), arguments.end());
699 const MCParticle* mcp = p->getMCParticle();
701 B2WARNING(
"No MCParticle is associated to the particle");
708 double getHEREnergy(
const Particle*)
710 static DBObjPtr<BeamParameters> beamParamsDB;
711 return (beamParamsDB->getHER()).E();
714 double getLEREnergy(
const Particle*)
716 static DBObjPtr<BeamParameters> beamParamsDB;
717 return (beamParamsDB->getLER()).E();
720 double getCrossingAngleX(
const Particle*)
723 static DBObjPtr<BeamParameters> beamParamsDB;
724 B2Vector3D herVec = beamParamsDB->getHER().Vect();
725 B2Vector3D lerVec = beamParamsDB->getLER().Vect();
732 return herVec.Angle(-lerVec);
735 double getCrossingAngleY(
const Particle*)
738 static DBObjPtr<BeamParameters> beamParamsDB;
739 B2Vector3D herVec = beamParamsDB->getHER().Vect();
740 B2Vector3D lerVec = beamParamsDB->getLER().Vect();
747 return herVec.Angle(-lerVec);
751 double particleClusterMatchWeight(
const Particle* particle)
759 const MCParticle* matchedToParticle = particle->
getMCParticle();
761 int matchedToIndex = matchedToParticle->getArrayIndex();
763 const ECLCluster* cluster = particle->getECLCluster();
766 const auto mcps = cluster->getRelationsTo<MCParticle>();
767 for (
unsigned int i = 0; i < mcps.size(); ++i)
768 if (mcps[i]->getArrayIndex() == matchedToIndex)
769 return mcps.weight(i);
774 double particleClusterBestMCMatchWeight(
const Particle* particle)
786 const ECLCluster* cluster = particle->getECLCluster();
792 auto mcps = cluster->getRelationsTo<MCParticle>();
795 std::vector<double> weights;
796 for (
unsigned int i = 0; i < mcps.size(); ++i)
797 weights.emplace_back(mcps.weight(i));
800 std::sort(weights.begin(), weights.end());
801 std::reverse(weights.begin(), weights.end());
805 double particleClusterBestMCPDGCode(
const Particle* particle)
815 const ECLCluster* cluster = particle->getECLCluster();
818 auto mcps = cluster->getRelationsTo<MCParticle>();
821 std::vector<std::pair<double, int>> weightsAndIndices;
822 for (
unsigned int i = 0; i < mcps.size(); ++i)
823 weightsAndIndices.emplace_back(mcps.weight(i), i);
826 std::sort(weightsAndIndices.begin(), weightsAndIndices.end(),
827 ValueIndexPairSorting::higherPair<
decltype(weightsAndIndices)::value_type>);
829 return mcps.object(weightsAndIndices[0].second)->getPDG();
832 double particleClusterTotalMCMatchWeight(
const Particle* particle)
834 const ECLCluster* cluster = particle->getECLCluster();
837 auto mcps = cluster->getRelationsTo<MCParticle>();
840 double weightsum = 0;
841 for (
unsigned int i = 0; i < mcps.size(); ++i)
842 weightsum += mcps.weight(i);
848 void getKlongWeightMap(
const Particle* particle, std::map<int, double>& mapMCParticleIndxAndWeight)
850 const ECLCluster* cluster = particle->getECLCluster();
851 auto mcps = cluster->getRelationsTo<MCParticle>();
853 for (
unsigned int i = 0; i < mcps.size(); ++i) {
854 double weight = mcps.weight(i);
855 const MCParticle* mcp = mcps[i];
858 if (mcp->getPDG() == 130) {
859 int index = mcp->getArrayIndex();
860 if (mapMCParticleIndxAndWeight.find(index) != mapMCParticleIndxAndWeight.end()) {
861 mapMCParticleIndxAndWeight.at(index) = mapMCParticleIndxAndWeight.at(index) + weight;
863 mapMCParticleIndxAndWeight.insert({index, weight});
867 mcp = mcp->getMother();
873 double particleClusterTotalMCMatchWeightForKlong(
const Particle* particle)
875 const ECLCluster* cluster = particle->getECLCluster();
878 auto mcps = cluster->getRelationsTo<MCParticle>();
881 std::map<int, double> mapMCParticleIndxAndWeight;
882 getKlongWeightMap(particle, mapMCParticleIndxAndWeight);
884 double totalWeight = 0;
885 for (
const auto& map : mapMCParticleIndxAndWeight) {
886 totalWeight += map.second;
892 double particleClusterTotalMCMatchWeightForBestKlong(
const Particle* particle)
894 const ECLCluster* cluster = particle->getECLCluster();
897 auto mcps = cluster->getRelationsTo<MCParticle>();
900 std::map<int, double> mapMCParticleIndxAndWeight;
901 getKlongWeightMap(particle, mapMCParticleIndxAndWeight);
903 if (mapMCParticleIndxAndWeight.size() == 0)
906 auto maxMap = std::max_element(mapMCParticleIndxAndWeight.begin(), mapMCParticleIndxAndWeight.end(),
907 [](
const auto & x,
const auto & y) { return x.second < y.second; }
910 return maxMap->second;
913 double isBBCrossfeed(
const Particle* particle)
915 if (particle ==
nullptr)
918 int pdg = particle->getPDGCode();
919 if (abs(pdg) != 511 && abs(pdg) != 521 && abs(pdg) != 531)
922 std::vector<const Particle*> daughters = particle->getFinalStateDaughters();
923 int nDaughters = daughters.size();
926 std::vector<int> mother_ids;
928 for (
int j = 0; j < nDaughters; ++j) {
929 const MCParticle* curMCParticle = daughters[j]->
getMCParticle();
930 while (curMCParticle !=
nullptr) {
931 pdg = curMCParticle->getPDG();
932 if (abs(pdg) == 511 || abs(pdg) == 521 || abs(pdg) == 531) {
933 mother_ids.emplace_back(curMCParticle->getArrayIndex());
936 const MCParticle* curMCMother = curMCParticle->getMother();
937 curMCParticle = curMCMother;
939 if (curMCParticle ==
nullptr) {
944 std::set<int> distinctIDs = std::set(mother_ids.begin(), mother_ids.end());
945 if (distinctIDs.size() == 1)
951 int ancestorBIndex(
const Particle* particle)
956 int pdg = std::abs(mcpart->getPDG());
958 if ((pdg == 521) || (pdg == 511))
959 return mcpart->getArrayIndex();
961 mcpart = mcpart->getMother();
967 VARIABLE_GROUP(
"MC matching and MC truth");
968 REGISTER_VARIABLE(
"isSignal", isSignal,
969 "1.0 if Particle is correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found. \n"
970 "It behaves according to DecayStringGrammar.");
971 REGISTER_VARIABLE(
"isSignalAcceptWrongFSPs", isSignalAcceptWrongFSPs,
972 "1.0 if Particle is almost correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found.\n"
973 "Misidentification of charged FSP is allowed.");
974 REGISTER_VARIABLE(
"isPrimarySignal", isPrimarySignal,
975 "1.0 if Particle is correctly reconstructed (SIGNAL) and primary, 0.0 if not, and NaN if no related MCParticle could be found");
976 REGISTER_VARIABLE(
"isSignalAcceptBremsPhotons", isSignalAcceptBremsPhotons,
977 "1.0 if Particle is correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found.\n"
978 "Particles with gamma daughters attached through the bremsstrahlung recovery modules are allowed.");
979 REGISTER_VARIABLE(
"genMotherPDG", genMotherPDG,
980 "Check the PDG code of a particles MC mother particle");
981 REGISTER_VARIABLE(
"genMotherPDG(i)", genNthMotherPDG,
982 "Check the PDG code of a particles n-th MC mother particle by providing an argument. 0 is first mother, 1 is grandmother etc. :noindex:");
984 REGISTER_VARIABLE(
"genQ2PmPd(i,j,...)", genQ2PmPd, R
"DOC(
985 Returns the generated four momentum transfer squared :math:`q^2` calculated as :math:`q^2 = (p_m - p_{d_i} - p_{d_j} - ...)^2`.
987 Here :math:`p_m` is the four momentum of the given (mother) particle,
988 and :math:`p_{d_{i,j,...}}` are the daughter particles with indices given as arguments .
989 The ordering of daughters is as defined in the DECAY.DEC file used in the generation, with the numbering starting at :math:`N=0`.
991 Returns NaN if no related MCParticle could be found.
992 Returns NaN if any of the given indices is larger than the number of daughters of the given particle.
994 )DOC", ":math:`[\\text{GeV}/\\text{c}]^2`");
996 REGISTER_VARIABLE(
"genMotherID", genMotherIndex,
997 "Check the array index of a particles generated mother");
998 REGISTER_VARIABLE(
"genMotherID(i)", genNthMotherIndex,
999 "Check the array index of a particle n-th MC mother particle by providing an argument. 0 is first mother, 1 is grandmother etc. :noindex:");
1003 REGISTER_VARIABLE(
"isBBCrossfeed", isBBCrossfeed,
1004 "Returns 1 for crossfeed in reconstruction of given B meson, 0 for no crossfeed and NaN for no true B meson or failed truthmatching.");
1005 REGISTER_VARIABLE(
"ancestorBIndex", ancestorBIndex,
1006 "Returns array index of B ancestor, or -1 if no B or no MC-matching is found.");
1007 REGISTER_VARIABLE(
"genMotherP", genMotherP,
1008 "Generated momentum of a particles MC mother particle\n\n",
"GeV/c");
1009 REGISTER_VARIABLE(
"genParticleID", genParticleIndex,
1010 "Check the array index of a particle's related MCParticle");
1011 REGISTER_VARIABLE(
"isSignalAcceptMissingNeutrino",
1012 isSignalAcceptMissingNeutrino,
1013 "Same as isSignal, but also accept missing neutrino");
1014 REGISTER_VARIABLE(
"isSignalAcceptMissingMassive",
1015 isSignalAcceptMissingMassive,
1016 "Same as isSignal, but also accept missing massive particle");
1017 REGISTER_VARIABLE(
"isSignalAcceptMissingGamma",
1018 isSignalAcceptMissingGamma,
1019 "Same as isSignal, but also accept missing gamma, such as B -> K* gamma, pi0 -> gamma gamma");
1020 REGISTER_VARIABLE(
"isSignalAcceptMissing",
1021 isSignalAcceptMissing,
1022 "Same as isSignal, but also accept missing particle");
1023 REGISTER_VARIABLE(
"isMisidentified", isMisidentified,
1024 "Return 1 if the particle is misidentified: at least one of the final state particles has the wrong PDG code assignment (including wrong charge), 0 if PDG code is fine, and NaN if no related MCParticle could be found.");
1025 REGISTER_VARIABLE(
"isWrongCharge", isWrongCharge,
1026 "Return 1 if the charge of the particle is wrongly assigned, 0 if it's the correct charge, and NaN if no related MCParticle could be found.");
1027 REGISTER_VARIABLE(
"isCloneTrack", isCloneTrack,
1028 "Return 1 if the charged final state particle comes from a cloned track, 0 if not a clone. Returns NAN if neutral, composite, or MCParticle not found (like for data or if not MCMatched)");
1029 REGISTER_VARIABLE(
"isOrHasCloneTrack", isOrHasCloneTrack,
1030 "Return 1 if the particle is a clone track or has a clone track as a daughter, 0 otherwise.");
1031 REGISTER_VARIABLE(
"mcPDG", particleMCMatchPDGCode,
1032 "The PDG code of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).");
1033 REGISTER_VARIABLE(
"mcErrors", particleMCErrors,
1034 "The bit pattern indicating the quality of MC match (see MCMatching::MCErrorFlags)");
1035 REGISTER_VARIABLE(
"mcMatchWeight", particleMCMatchWeight,
1036 "The weight of the Particle -> MCParticle relation (only for the first Relation = largest weight).");
1037 REGISTER_VARIABLE(
"nMCMatches", particleNumberOfMCMatch,
1038 "The number of relations of this Particle to MCParticle.");
1039 REGISTER_VARIABLE(
"mcDecayTime", particleMCMatchDecayTime,
1040 "The decay time of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
1042 REGISTER_VARIABLE(
"mcLifeTime", particleMCMatchLifeTime,
1043 "The life time of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
1045 REGISTER_VARIABLE(
"mcPX", particleMCMatchPX,
1046 "The px of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
1048 REGISTER_VARIABLE(
"mcPY", particleMCMatchPY,
1049 "The py of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
1051 REGISTER_VARIABLE(
"mcPZ", particleMCMatchPZ,
1052 "The pz of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
1054 REGISTER_VARIABLE(
"mcPT", particleMCMatchPT,
1055 "The pt of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
1057 REGISTER_VARIABLE(
"mcE", particleMCMatchE,
1058 "The energy of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
1060 REGISTER_VARIABLE(
"mcP", particleMCMatchP,
1061 "The total momentum of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
1063 REGISTER_VARIABLE(
"mcPhi", particleMCMatchPhi,
1064 "The phi of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
1066 REGISTER_VARIABLE(
"mcTheta", particleMCMatchTheta,
1067 "The theta of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
1069 REGISTER_VARIABLE(
"nMCDaughters", mcParticleNDaughters,
1070 "The number of daughters of the matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).");
1071 REGISTER_VARIABLE(
"mcRecoilMass", particleMCRecoilMass,
1072 "The mass recoiling against the particles attached as particle's daughters calculated using MC truth values.\n\n",
1073 "GeV/:math:`\\text{c}^2`");
1074 REGISTER_VARIABLE(
"mcCosThetaBetweenParticleAndNominalB",
1075 particleMCCosThetaBetweenParticleAndNominalB,
1076 "Cosine of the angle in CMS between momentum the particle and a nominal B particle. In this calculation, the momenta of all descendant neutrinos are subtracted from the B momentum.");
1079 REGISTER_VARIABLE(
"mcSecPhysProc", mcParticleSecondaryPhysicsProcess,
1081Returns the secondary physics process flag, which is set by Geant4 on secondary particles. It indicates the type of process that produced the particle.
1083Returns NaN if the particle is not matched to a MCParticle.
1085Returns -1 in case of unknown process.
1087Returns 0 if the particle is primary, i.e. produced by the event generator and not Geant4. Particles produced by Geant4 (i.e. secondary particles) include those produced in interaction with detector material, Bremsstrahlung, and the decay products of long-lived particles (e.g. muons, pions, K_S0, K_L0, Lambdas, ...).
1089List of possible values (taken from the Geant4 source of
1090`G4DecayProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/decay/include/G4DecayProcessType.hh>`_,
1091`G4HadronicProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/hadronic/management/include/G4HadronicProcessType.hh>`_,
1092`G4TransportationProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/transportation/include/G4TransportationProcessType.hh>`_ and
1093`G4EmProcessSubType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/electromagnetic/utils/include/G4EmProcessSubType.hh>`_)
1095* 1 Coulomb scattering
1098* 4 Pair production by charged
1100* 6 Annihilation to mu mu
1101* 7 Annihilation to hadrons
1103* 9 Electron general process
1104* 10 Multiple scattering
1106* 12 Photo-electric effect
1107* 13 Compton scattering
1108* 14 Gamma conversion
1109* 15 Gamma conversion to mu mu
1110* 16 Gamma general process
1113* 23 Synchrotron radiation
1114* 24 Transition radiation
1116* 92 Coupled transportation
1118* 121 Hadron inelastic
1120* 132 Mu atomic capture
1124* 161 Charge exchange
1126* 202 Decay with spin
1127* 203 Decay (pion make spin)
1128* 210 Radioactive decay
1133.. note:: This is what `modularAnalysis.printMCParticles` shows as ``creation process`` when ``showStatus`` is set to ``True``.
1135 REGISTER_VARIABLE("mcParticleStatus", mcParticleStatus,
1136 "Returns status bits of related MCParticle or NaN if MCParticle relation is not set.");
1137 REGISTER_VARIABLE(
"mcPrimary", particleMCPrimaryParticle,
1138 "Returns 1 if Particle is related to primary MCParticle, 0 if Particle is related to non - primary MCParticle, "
1139 "NaN if Particle is not related to MCParticle.");
1140 REGISTER_VARIABLE(
"mcVirtual", particleMCVirtualParticle,
1141 "Returns 1 if Particle is related to virtual MCParticle, 0 if Particle is related to non - virtual MCParticle, "
1142 "NaN if Particle is not related to MCParticle.")
1143 REGISTER_VARIABLE("mcInitial", particleMCInitialParticle,
1144 "Returns 1 if Particle is related to initial MCParticle, 0 if Particle is related to non - initial MCParticle, "
1145 "NaN if Particle is not related to MCParticle.")
1146 REGISTER_VARIABLE("mcISR", particleMCISRParticle,
1147 "Returns 1 if Particle is related to ISR MCParticle, 0 if Particle is related to non - ISR MCParticle, "
1148 "NaN if Particle is not related to MCParticle.")
1149 REGISTER_VARIABLE("mcFSR", particleMCFSRParticle,
1150 "Returns 1 if Particle is related to FSR MCParticle, 0 if Particle is related to non - FSR MCParticle ,"
1151 "NaN if Particle is not related to MCParticle.")
1152 REGISTER_VARIABLE("mcPhotos", particleMCPhotosParticle,
1153 "Returns 1 if Particle is related to Photos MCParticle, 0 if Particle is related to non - Photos MCParticle, "
1154 "NaN if Particle is not related to MCParticle.")
1155 REGISTER_VARIABLE("generatorEventWeight", generatorEventWeight,
1156 "[Eventbased] Returns the event weight produced by the event generator")
1158 REGISTER_VARIABLE("genNStepsToDaughter(i)", genNStepsToDaughter,
1159 "Returns number of steps to i-th daughter from the particle at generator level. "
1160 "NaN if no MCParticle is associated to the particle or i-th daughter. "
1161 "NaN if i-th daughter does not exist.");
1162 REGISTER_VARIABLE("genNMissingDaughter(PDG)", genNMissingDaughter,
1163 "Returns the number of missing daughters having assigned PDG codes. "
1164 "NaN if no MCParticle is associated to the particle.");
1165 REGISTER_VARIABLE("Eher", getHEREnergy, R"DOC(
1166[Eventbased] The nominal HER energy used by the generator.
1168.. warning:: This variable does not make sense for data.
1171 REGISTER_VARIABLE("Eler", getLEREnergy, R"DOC(
1172[Eventbased] The nominal LER energy used by the generator.
1174.. warning:: This variable does not make sense for data.
1177 REGISTER_VARIABLE("XAngle", getCrossingAngleX, R"DOC(
1178[Eventbased] The nominal beam crossing angle in the x-z plane from generator level beam kinematics.
1180.. warning:: This variable does not make sense for data.
1183 REGISTER_VARIABLE("YAngle", getCrossingAngleY, R"DOC(
1184[Eventbased] The nominal beam crossing angle in the y-z plane from generator level beam kinematics.
1186.. warning:: This variable does not make sense for data.
1190 VARIABLE_GROUP("Generated tau decay information");
1191 REGISTER_VARIABLE("tauPlusMCMode", tauPlusMcMode,
1192 "[Eventbased] Decay ID for the positive tau lepton in a tau pair generated event.");
1193 REGISTER_VARIABLE("tauMinusMCMode", tauMinusMcMode,
1194 "[Eventbased] Decay ID for the negative tau lepton in a tau pair generated event.");
1195 REGISTER_VARIABLE("tauPlusMCProng", tauPlusMcProng,
1196 "[Eventbased] Prong for the positive tau lepton in a tau pair generated event.");
1197 REGISTER_VARIABLE("tauMinusMCProng", tauMinusMcProng,
1198 "[Eventbased] Prong for the negative tau lepton in a tau pair generated event.");
1200 VARIABLE_GROUP("MC particle seen in subdetectors");
1201 REGISTER_VARIABLE("isReconstructible", isReconstructible,
1202 "Checks charged particles were seen in the SVD and neutrals in the ECL, returns 1.0 if so, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
1203 REGISTER_VARIABLE("seenInPXD", seenInPXD,
1204 "Returns 1.0 if the MC particle was seen in the PXD, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
1205 REGISTER_VARIABLE("isTrackFound", isTrackFound,
1206 "works on charged stable particle list created from MCParticles, returns NaN if not ; returns 1.0 if there is a reconstructed track related to the charged stable MCParticle with the correct charge, return -1.0 if the reconstructed track has the wrong charge, return 0.0 when no reconstructed track is found.");
1207 REGISTER_VARIABLE("seenInSVD", seenInSVD,
1208 "Returns 1.0 if the MC particle was seen in the SVD, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
1209 REGISTER_VARIABLE("seenInCDC", seenInCDC,
1210 "Returns 1.0 if the MC particle was seen in the CDC, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
1211 REGISTER_VARIABLE("seenInTOP", seenInTOP,
1212 "Returns 1.0 if the MC particle was seen in the TOP, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
1213 REGISTER_VARIABLE("seenInECL", seenInECL,
1214 "Returns 1.0 if the MC particle was seen in the ECL, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
1215 REGISTER_VARIABLE("seenInARICH", seenInARICH,
1216 "Returns 1.0 if the MC particle was seen in the ARICH, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
1217 REGISTER_VARIABLE("seenInKLM", seenInKLM,
1218 "Returns 1.0 if the MC particle was seen in the KLM, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
1220 VARIABLE_GROUP("MC Matching for ECLClusters");
1221 REGISTER_VARIABLE("clusterMCMatchWeight", particleClusterMatchWeight,
1222 "Returns the weight of the ECLCluster -> MCParticle relation for the MCParticle matched to the particle. "
1223 "Returns NaN if: no cluster is related to the particle, the particle is not MC matched, or if there are no mcmatches for the cluster. "
1224 "Returns -1 if the cluster *was* matched to particles, but not the match of the particle provided.");
1225 REGISTER_VARIABLE("clusterBestMCMatchWeight", particleClusterBestMCMatchWeight,
1226 "Returns the weight of the ECLCluster -> MCParticle relation for the relation with the largest weight.");
1227 REGISTER_VARIABLE("clusterBestMCPDG", particleClusterBestMCPDGCode,
1228 "Returns the PDG code of the MCParticle for the ECLCluster -> MCParticle relation with the largest weight.");
1229 REGISTER_VARIABLE("clusterTotalMCMatchWeight", particleClusterTotalMCMatchWeight,
1230 "Returns the sum of all weights of the ECLCluster -> MCParticles relations.");
1232 REGISTER_VARIABLE("clusterTotalMCMatchWeightForKlong", particleClusterTotalMCMatchWeightForKlong,
1233 "Returns the sum of all weights of the ECLCluster -> MCParticles relations when MCParticle is a Klong or daughter of a Klong");
1234 REGISTER_VARIABLE("clusterTotalMCMatchWeightForBestKlong", particleClusterTotalMCMatchWeightForBestKlong,
1235 "Returns the sum of all weights of the ECLCluster -> MCParticles relations when MCParticle is the same Klong or daughter of the Klong. If multiple MC Klongs are related to the ECLCluster, returns the sum of weights for the best matched Klong.");
void SetX(DataType x)
set X/1st-coordinate
void SetY(DataType y)
set Y/2nd-coordinate
static const ParticleSet chargedStableSet
set of charged stable particles
static const double doubleNaN
quiet_NaN
@ c_IsFSRPhoton
bit 7: Particle is from finial 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
const MCParticle * getMCParticle() const
Returns the pointer to the MCParticle object that was used to create this Particle (ParticleType == c...
static const ReferenceFrame & GetCurrent()
Get current rest frame.
int getArrayIndex() const
Returns this object's array index (in StoreArray), or -1 if not found.
B2Vector3< double > B2Vector3D
typedef for common usage with double
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'.
@ 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 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 void fillGenMothers(const Belle2::MCParticle *mcP, std::vector< int > &genMCPMothers)
Fills vector with array (1-based) indices of all generator ancestors of given MCParticle.