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>
24 #include <framework/datastore/StoreArray.h>
25 #include <framework/datastore/StoreObjPtr.h>
26 #include <framework/dataobjects/EventMetaData.h>
27 #include <framework/gearbox/Const.h>
28 #include <framework/logging/Logger.h>
29 #include <framework/database/DBObjPtr.h>
30 #include <framework/dbobjects/BeamParameters.h>
41 static const double realNaN = std::numeric_limits<double>::quiet_NaN();
44 double isSignal(
const Particle* part)
47 if (!mcparticle)
return realNaN;
53 double isSignalAcceptWrongFSPs(
const Particle* part)
56 if (!mcparticle)
return realNaN;
60 status &= (~MCMatching::c_MisID);
61 status &= (~MCMatching::c_AddedWrongParticle);
66 double isPrimarySignal(
const Particle* part)
68 return (isSignal(part) > 0.5 and particleMCPrimaryParticle(part) > 0.5);
71 double isMisidentified(
const Particle* part)
74 if (!mcp)
return realNaN;
79 double isWrongCharge(
const Particle* part)
82 if (!mcp)
return realNaN;
83 return (part->getCharge() != mcp->getCharge());
86 double isCloneTrack(
const Particle* particle)
92 const auto mcpww = particle->getRelatedToWithWeight<MCParticle>();
93 if (!mcpww.first)
return realNaN;
94 return (mcpww.second < 0);
97 double isOrHasCloneTrack(
const Particle* particle)
100 std::queue<const Particle*> qq;
102 while (!qq.empty()) {
103 const auto d = qq.front();
105 if (isCloneTrack(d) == 1.0)
return 1.0;
106 size_t nDau = d->getNDaughters();
107 for (
size_t iDau = 0; iDau < nDau; ++iDau)
108 qq.push(d->getDaughter(iDau));
113 double genNthMotherPDG(
const Particle* part,
const std::vector<double>& args)
116 if (!mcparticle)
return 0.0;
118 unsigned int nLevels = args.empty() ? 0 : args[0];
120 const MCParticle* curMCParticle = mcparticle;
121 for (
unsigned int i = 0; i <= nLevels; ++i) {
122 const MCParticle* curMCMother = curMCParticle->getMother();
123 if (!curMCMother)
return 0.0;
124 curMCParticle = curMCMother;
126 return curMCParticle->getPDG();
129 double genNthMotherIndex(
const Particle* part,
const std::vector<double>& args)
132 if (!mcparticle)
return 0.0;
134 unsigned int nLevels = args.empty() ? 0 : args[0];
136 const MCParticle* curMCParticle = mcparticle;
137 for (
unsigned int i = 0; i <= nLevels; ++i) {
138 const MCParticle* curMCMother = curMCParticle->getMother();
139 if (!curMCMother)
return 0.0;
140 curMCParticle = curMCMother;
145 double genMotherPDG(
const Particle* part)
147 return genNthMotherPDG(part, {});
150 double genMotherP(
const Particle* part)
153 if (!mcparticle)
return realNaN;
155 const MCParticle* mcmother = mcparticle->getMother();
156 if (!mcmother)
return realNaN;
158 return mcmother->getMomentum().R();
161 double genMotherIndex(
const Particle* part)
163 return genNthMotherIndex(part, {});
166 double genParticleIndex(
const Particle* part)
169 if (!mcparticle)
return realNaN;
170 return mcparticle->getArrayIndex();
173 double isSignalAcceptMissingNeutrino(
const Particle* part)
176 if (!mcparticle)
return realNaN;
180 status &= (~MCMatching::c_MissNeutrino);
185 double isSignalAcceptMissingMassive(
const Particle* part)
188 if (!mcparticle)
return realNaN;
192 status &= (~MCMatching::c_MissMassiveParticle);
193 status &= (~MCMatching::c_MissKlong);
198 double isSignalAcceptMissingGamma(
const Particle* part)
201 if (!mcparticle)
return realNaN;
205 status &= (~MCMatching::c_MissGamma);
210 double isSignalAcceptMissing(
const Particle* part)
213 if (!mcparticle)
return realNaN;
217 status &= (~MCMatching::c_MissGamma);
218 status &= (~MCMatching::c_MissMassiveParticle);
219 status &= (~MCMatching::c_MissKlong);
220 status &= (~MCMatching::c_MissNeutrino);
225 double isSignalAcceptBremsPhotons(
const Particle* part)
228 if (!mcparticle)
return realNaN;
232 status &= (~MCMatching::c_AddedRecoBremsPhoton);
237 double particleMCMatchPDGCode(
const Particle* part)
240 if (!mcparticle)
return realNaN;
241 return mcparticle->getPDG();
244 double particleMCErrors(
const Particle* part)
249 double particleNumberOfMCMatch(
const Particle* particle)
251 RelationVector<MCParticle> mcRelations = particle->getRelationsTo<MCParticle>();
252 return (mcRelations.size());
255 double particleMCMatchWeight(
const Particle* particle)
257 auto relWithWeight = particle->getRelatedToWithWeight<MCParticle>();
258 if (!relWithWeight.first)
return realNaN;
259 return relWithWeight.second;
262 double particleMCMatchDecayTime(
const Particle* part)
265 if (!mcparticle)
return realNaN;
266 return mcparticle->getDecayTime();
269 double particleMCMatchLifeTime(
const Particle* part)
272 if (!mcparticle)
return realNaN;
273 return mcparticle->getLifetime();
276 double particleMCMatchPX(
const Particle* part)
279 if (!mcparticle)
return realNaN;
282 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
283 return frame.getMomentum(mcpP4).Px();
286 double particleMCMatchPY(
const Particle* part)
289 if (!mcparticle)
return realNaN;
292 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
293 return frame.getMomentum(mcpP4).Py();
296 double particleMCMatchPZ(
const Particle* part)
299 if (!mcparticle)
return realNaN;
302 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
303 return frame.getMomentum(mcpP4).Pz();
306 double particleMCMatchPT(
const Particle* part)
309 if (!mcparticle)
return realNaN;
312 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
313 return frame.getMomentum(mcpP4).Pt();
316 double particleMCMatchE(
const Particle* part)
319 if (!mcparticle)
return realNaN;
322 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
323 return frame.getMomentum(mcpP4).E();
326 double particleMCMatchP(
const Particle* part)
329 if (!mcparticle)
return realNaN;
332 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
333 return frame.getMomentum(mcpP4).P();
336 double particleMCMatchTheta(
const Particle* part)
339 if (!mcparticle)
return realNaN;
342 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
343 return frame.getMomentum(mcpP4).Theta();
346 double particleMCMatchPhi(
const Particle* part)
349 if (!mcparticle)
return realNaN;
352 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
353 return frame.getMomentum(mcpP4).Phi();
356 double mcParticleNDaughters(
const Particle* part)
360 if (!mcparticle)
return realNaN;
361 return mcparticle->getNDaughters();
364 double particleMCRecoilMass(
const Particle* part)
366 StoreArray<MCParticle> mcparticles;
367 if (mcparticles.getEntries() < 1)
return realNaN;
369 ROOT::Math::PxPyPzEVector pInitial = mcparticles[0]->get4Vector();
370 ROOT::Math::PxPyPzEVector pDaughters;
371 const std::vector<Particle*> daughters = part->getDaughters();
372 for (
auto daughter : daughters) {
373 const MCParticle* mcD = daughter->getMCParticle();
374 if (!mcD)
return realNaN;
376 pDaughters += mcD->get4Vector();
378 return (pInitial - pDaughters).M();
381 ROOT::Math::PxPyPzEVector MCInvisibleP4(
const MCParticle* mcparticle)
383 ROOT::Math::PxPyPzEVector ResultP4;
384 int pdg = abs(mcparticle->getPDG());
385 bool isNeutrino = (pdg == 12 or pdg == 14 or pdg == 16);
387 if (mcparticle->getNDaughters() > 0) {
388 const std::vector<MCParticle*> daughters = mcparticle->getDaughters();
389 for (
auto daughter : daughters)
390 ResultP4 += MCInvisibleP4(daughter);
391 }
else if (isNeutrino)
392 ResultP4 += mcparticle->get4Vector();
397 double particleMCCosThetaBetweenParticleAndNominalB(
const Particle* part)
399 int particlePDG = abs(part->getPDGCode());
400 if (particlePDG != 511 and particlePDG != 521)
401 B2FATAL(
"The variable mcCosThetaBetweenParticleAndNominalB is only meant to be used on B mesons!");
404 double e_Beam = T.getCMSEnergy() / 2.0;
405 double m_B = part->getPDGMass();
408 const double mY4S = 10.5794;
411 if (e_Beam * e_Beam - m_B * m_B < 0) {
414 double p_B = std::sqrt(e_Beam * e_Beam - m_B * m_B);
418 if (!mcB)
return realNaN;
420 int mcParticlePDG = abs(mcB->getPDG());
421 if (mcParticlePDG != 511 and mcParticlePDG != 521)
424 ROOT::Math::PxPyPzEVector p = T.rotateLabToCms() * (mcB->get4Vector() - MCInvisibleP4(mcB));
429 double theta_BY = (2 * e_Beam * e_d - m_B * m_B - m_d * m_d)
434 double mcParticleSecondaryPhysicsProcess(
const Particle* p)
436 const MCParticle* mcp = p->getMCParticle();
437 if (!mcp)
return realNaN;
438 return mcp->getSecondaryPhysicsProcess();
441 double mcParticleStatus(
const Particle* p)
443 const MCParticle* mcp = p->getMCParticle();
444 if (!mcp)
return realNaN;
445 return mcp->getStatus();
448 double particleMCPrimaryParticle(
const Particle* p)
450 const MCParticle* mcp = p->getMCParticle();
451 if (!mcp)
return realNaN;
454 return mcp->hasStatus(bitmask);
457 double particleMCVirtualParticle(
const Particle* p)
459 const MCParticle* mcp = p->getMCParticle();
460 if (!mcp)
return realNaN;
463 return mcp->hasStatus(bitmask);
466 double particleMCInitialParticle(
const Particle* p)
468 const MCParticle* mcp = p->getMCParticle();
469 if (!mcp)
return realNaN;
472 return mcp->hasStatus(bitmask);
475 double particleMCISRParticle(
const Particle* p)
477 const MCParticle* mcp = p->getMCParticle();
478 if (!mcp)
return realNaN;
481 return mcp->hasStatus(bitmask);
484 double particleMCFSRParticle(
const Particle* p)
486 const MCParticle* mcp = p->getMCParticle();
487 if (!mcp)
return realNaN;
490 return mcp->hasStatus(bitmask);
493 double particleMCPhotosParticle(
const Particle* p)
495 const MCParticle* mcp = p->getMCParticle();
496 if (!mcp)
return realNaN;
499 return mcp->hasStatus(bitmask);
502 double generatorEventWeight(
const Particle*)
504 StoreObjPtr<EventMetaData> evtMetaData;
505 if (!evtMetaData)
return realNaN;
506 return evtMetaData->getGeneratedWeight();
509 int tauPlusMcMode(
const Particle*)
511 StoreObjPtr<TauPairDecay> tauDecay;
513 B2WARNING(
"Cannot find tau decay ID, did you forget to run TauDecayMarkerModule?");
516 return tauDecay->getTauPlusIdMode();
519 int tauMinusMcMode(
const Particle*)
521 StoreObjPtr<TauPairDecay> tauDecay;
523 B2WARNING(
"Cannot find tau decay ID, did you forget to run TauDecayMarkerModule?");
526 return tauDecay->getTauMinusIdMode();
529 int tauPlusMcProng(
const Particle*)
531 StoreObjPtr<TauPairDecay> tauDecay;
533 B2WARNING(
"Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
536 return tauDecay->getTauPlusMcProng();
539 int tauMinusMcProng(
const Particle*)
541 StoreObjPtr<TauPairDecay> tauDecay;
543 B2WARNING(
"Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
546 return tauDecay->getTauMinusMcProng();
549 double isReconstructible(
const Particle* p)
551 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
553 const MCParticle* mcp = p->getMCParticle();
554 if (!mcp)
return realNaN;
558 return (abs(mcp->getCharge()) > 0) ? seenInSVD(p) : seenInECL(p);
561 double seenInPXD(
const Particle* p)
563 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
565 const MCParticle* mcp = p->getMCParticle();
566 if (!mcp)
return realNaN;
567 return mcp->hasSeenInDetector(Const::PXD);
570 double seenInSVD(
const Particle* p)
572 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
574 const MCParticle* mcp = p->getMCParticle();
575 if (!mcp)
return realNaN;
576 return mcp->hasSeenInDetector(Const::SVD);
579 double seenInCDC(
const Particle* p)
581 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
583 const MCParticle* mcp = p->getMCParticle();
584 if (!mcp)
return realNaN;
585 return mcp->hasSeenInDetector(Const::CDC);
588 double seenInTOP(
const Particle* p)
590 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
592 const MCParticle* mcp = p->getMCParticle();
593 if (!mcp)
return realNaN;
594 return mcp->hasSeenInDetector(Const::TOP);
597 double seenInECL(
const Particle* p)
599 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
601 const MCParticle* mcp = p->getMCParticle();
602 if (!mcp)
return realNaN;
603 return mcp->hasSeenInDetector(Const::ECL);
606 double seenInARICH(
const Particle* p)
608 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
610 const MCParticle* mcp = p->getMCParticle();
611 if (!mcp)
return realNaN;
612 return mcp->hasSeenInDetector(Const::ARICH);
615 double seenInKLM(
const Particle* p)
617 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
619 const MCParticle* mcp = p->getMCParticle();
620 if (!mcp)
return realNaN;
621 return mcp->hasSeenInDetector(Const::KLM);
624 int genNStepsToDaughter(
const Particle* p,
const std::vector<double>& arguments)
626 if (arguments.size() != 1)
627 B2FATAL(
"Wrong number of arguments for genNStepsToDaughter");
629 const MCParticle* mcp = p->getMCParticle();
631 B2WARNING(
"No MCParticle is associated to the particle");
635 int nChildren = p->getNDaughters();
636 if (arguments[0] >= nChildren) {
640 const Particle* daugP = p->getDaughter(arguments[0]);
645 B2WARNING(
"No MCParticle is associated to the i-th daughter");
649 if (nChildren == 1)
return 1;
651 std::vector<int> genMothers;
653 auto match = std::find(genMothers.begin(), genMothers.end(), mcp->getIndex());
654 return match - genMothers.begin();
657 int genNMissingDaughter(
const Particle* p,
const std::vector<double>& arguments)
659 if (arguments.size() < 1)
660 B2FATAL(
"Wrong number of arguments for genNMissingDaughter");
662 const std::vector<int> PDGcodes(arguments.begin(), arguments.end());
664 const MCParticle* mcp = p->getMCParticle();
666 B2WARNING(
"No MCParticle is associated to the particle");
673 double getHEREnergy(
const Particle*)
675 static DBObjPtr<BeamParameters> beamParamsDB;
676 return (beamParamsDB->getHER()).E();
679 double getLEREnergy(
const Particle*)
681 static DBObjPtr<BeamParameters> beamParamsDB;
682 return (beamParamsDB->getLER()).E();
685 double getCrossingAngleX(
const Particle*)
688 static DBObjPtr<BeamParameters> beamParamsDB;
689 B2Vector3D herVec = beamParamsDB->getHER().Vect();
690 B2Vector3D lerVec = beamParamsDB->getLER().Vect();
697 return herVec.Angle(-lerVec);
700 double getCrossingAngleY(
const Particle*)
703 static DBObjPtr<BeamParameters> beamParamsDB;
704 B2Vector3D herVec = beamParamsDB->getHER().Vect();
705 B2Vector3D lerVec = beamParamsDB->getLER().Vect();
712 return herVec.Angle(-lerVec);
716 double particleClusterMatchWeight(
const Particle* particle)
724 const MCParticle* matchedToParticle = particle->
getMCParticle();
725 if (!matchedToParticle)
return realNaN;
726 int matchedToIndex = matchedToParticle->getArrayIndex();
728 const ECLCluster* cluster = particle->getECLCluster();
729 if (!cluster)
return realNaN;
731 const auto mcps = cluster->getRelationsTo<MCParticle>();
732 for (
unsigned int i = 0; i < mcps.size(); ++i)
733 if (mcps[i]->getArrayIndex() == matchedToIndex)
734 return mcps.weight(i);
739 double particleClusterBestMCMatchWeight(
const Particle* particle)
751 const ECLCluster* cluster = particle->getECLCluster();
752 if (!cluster)
return realNaN;
757 auto mcps = cluster->getRelationsTo<MCParticle>();
758 if (mcps.size() == 0)
return realNaN;
760 std::vector<double> weights;
761 for (
unsigned int i = 0; i < mcps.size(); ++i)
762 weights.emplace_back(mcps.weight(i));
765 std::sort(weights.begin(), weights.end());
766 std::reverse(weights.begin(), weights.end());
770 double particleClusterBestMCPDGCode(
const Particle* particle)
780 const ECLCluster* cluster = particle->getECLCluster();
781 if (!cluster)
return realNaN;
783 auto mcps = cluster->getRelationsTo<MCParticle>();
784 if (mcps.size() == 0)
return realNaN;
786 std::vector<std::pair<double, int>> weightsAndIndices;
787 for (
unsigned int i = 0; i < mcps.size(); ++i)
788 weightsAndIndices.emplace_back(mcps.weight(i), i);
791 std::sort(weightsAndIndices.begin(), weightsAndIndices.end(),
792 ValueIndexPairSorting::higherPair<decltype(weightsAndIndices)::value_type>);
794 return mcps.object(weightsAndIndices[0].second)->getPDG();
797 double particleClusterTotalMCMatchWeight(
const Particle* particle)
799 const ECLCluster* cluster = particle->getECLCluster();
800 if (!cluster)
return realNaN;
802 auto mcps = cluster->getRelationsTo<MCParticle>();
805 double weightsum = 0;
806 for (
unsigned int i = 0; i < mcps.size(); ++i)
807 weightsum += mcps.weight(i);
812 double isBBCrossfeed(
const Particle* particle)
814 if (particle ==
nullptr)
815 return std::numeric_limits<double>::quiet_NaN();
817 int pdg = particle->getPDGCode();
818 if (abs(pdg) != 511 && abs(pdg) != 521 && abs(pdg) != 531)
819 return std::numeric_limits<double>::quiet_NaN();
821 std::vector<const Particle*> daughters = particle->getFinalStateDaughters();
822 int nDaughters = daughters.size();
825 std::vector<int> mother_ids;
827 for (
int j = 0; j < nDaughters; ++j) {
828 const MCParticle* curMCParticle = daughters[j]->
getMCParticle();
829 while (curMCParticle !=
nullptr) {
830 pdg = curMCParticle->getPDG();
831 if (abs(pdg) == 511 || abs(pdg) == 521 || abs(pdg) == 531) {
832 mother_ids.emplace_back(curMCParticle->getArrayIndex());
835 const MCParticle* curMCMother = curMCParticle->getMother();
836 curMCParticle = curMCMother;
838 if (curMCParticle ==
nullptr) {
839 return std::numeric_limits<double>::quiet_NaN();
843 std::set<int> distinctIDs = std::set(mother_ids.begin(), mother_ids.end());
844 if (distinctIDs.size() == 1)
850 VARIABLE_GROUP(
"MC matching and MC truth");
851 REGISTER_VARIABLE(
"isSignal", isSignal,
852 "1.0 if Particle is correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found. \n"
853 "It behaves according to DecayStringGrammar.");
854 REGISTER_VARIABLE(
"isSignalAcceptWrongFSPs", isSignalAcceptWrongFSPs,
855 "1.0 if Particle is almost correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found.\n"
856 "Misidentification of charged FSP is allowed.");
857 REGISTER_VARIABLE(
"isPrimarySignal", isPrimarySignal,
858 "1.0 if Particle is correctly reconstructed (SIGNAL) and primary, 0.0 if not, and NaN if no related MCParticle could be found");
859 REGISTER_VARIABLE(
"isSignalAcceptBremsPhotons", isSignalAcceptBremsPhotons,
860 "1.0 if Particle is correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found.\n"
861 "Particles with gamma daughters attached through the bremsstrahlung recovery modules are allowed.");
862 REGISTER_VARIABLE(
"genMotherPDG", genMotherPDG,
863 "Check the PDG code of a particles MC mother particle");
864 REGISTER_VARIABLE(
"genMotherPDG(i)", genNthMotherPDG,
865 "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:");
867 REGISTER_VARIABLE(
"genMotherID", genMotherIndex,
868 "Check the array index of a particles generated mother");
869 REGISTER_VARIABLE(
"genMotherID(i)", genNthMotherIndex,
870 "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:");
874 REGISTER_VARIABLE(
"isBBCrossfeed", isBBCrossfeed,
875 "Returns 1 for crossfeed in reconstruction of given B meson, 0 for no crossfeed and NaN for no true B meson or failed truthmatching.");
876 REGISTER_VARIABLE(
"genMotherP", genMotherP,
877 "Generated momentum of a particles MC mother particle\n\n",
"GeV/c");
878 REGISTER_VARIABLE(
"genParticleID", genParticleIndex,
879 "Check the array index of a particle's related MCParticle");
880 REGISTER_VARIABLE(
"isSignalAcceptMissingNeutrino",
881 isSignalAcceptMissingNeutrino,
882 "Same as isSignal, but also accept missing neutrino");
883 REGISTER_VARIABLE(
"isSignalAcceptMissingMassive",
884 isSignalAcceptMissingMassive,
885 "Same as isSignal, but also accept missing massive particle");
886 REGISTER_VARIABLE(
"isSignalAcceptMissingGamma",
887 isSignalAcceptMissingGamma,
888 "Same as isSignal, but also accept missing gamma, such as B -> K* gamma, pi0 -> gamma gamma");
889 REGISTER_VARIABLE(
"isSignalAcceptMissing",
890 isSignalAcceptMissing,
891 "Same as isSignal, but also accept missing particle");
892 REGISTER_VARIABLE(
"isMisidentified", isMisidentified,
893 "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.");
894 REGISTER_VARIABLE(
"isWrongCharge", isWrongCharge,
895 "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.");
896 REGISTER_VARIABLE(
"isCloneTrack", isCloneTrack,
897 "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)");
898 REGISTER_VARIABLE(
"isOrHasCloneTrack", isOrHasCloneTrack,
899 "Return 1 if the particle is a clone track or has a clone track as a daughter, 0 otherwise.");
900 REGISTER_VARIABLE(
"mcPDG", particleMCMatchPDGCode,
901 "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).");
902 REGISTER_VARIABLE(
"mcErrors", particleMCErrors,
903 "The bit pattern indicating the quality of MC match (see MCMatching::MCErrorFlags)");
904 REGISTER_VARIABLE(
"mcMatchWeight", particleMCMatchWeight,
905 "The weight of the Particle -> MCParticle relation (only for the first Relation = largest weight).");
906 REGISTER_VARIABLE(
"nMCMatches", particleNumberOfMCMatch,
907 "The number of relations of this Particle to MCParticle.");
908 REGISTER_VARIABLE(
"mcDecayTime", particleMCMatchDecayTime,
909 "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",
911 REGISTER_VARIABLE(
"mcLifeTime", particleMCMatchLifeTime,
912 "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",
914 REGISTER_VARIABLE(
"mcPX", particleMCMatchPX,
915 "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",
917 REGISTER_VARIABLE(
"mcPY", particleMCMatchPY,
918 "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",
920 REGISTER_VARIABLE(
"mcPZ", particleMCMatchPZ,
921 "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",
923 REGISTER_VARIABLE(
"mcPT", particleMCMatchPT,
924 "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",
926 REGISTER_VARIABLE(
"mcE", particleMCMatchE,
927 "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",
929 REGISTER_VARIABLE(
"mcP", particleMCMatchP,
930 "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",
932 REGISTER_VARIABLE(
"mcPhi", particleMCMatchPhi,
933 "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",
935 REGISTER_VARIABLE(
"mcTheta", particleMCMatchTheta,
936 "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",
938 REGISTER_VARIABLE(
"nMCDaughters", mcParticleNDaughters,
939 "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).");
940 REGISTER_VARIABLE(
"mcRecoilMass", particleMCRecoilMass,
941 "The mass recoiling against the particles attached as particle's daughters calculated using MC truth values.\n\n",
942 "GeV/:math:`\\text{c}^2`");
943 REGISTER_VARIABLE(
"mcCosThetaBetweenParticleAndNominalB",
944 particleMCCosThetaBetweenParticleAndNominalB,
945 "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.");
948 REGISTER_VARIABLE(
"mcSecPhysProc", mcParticleSecondaryPhysicsProcess,
950 Returns the secondary physics process flag, which is set by Geant4 on secondary particles. It indicates the type of process that produced the particle.
952 Returns NaN if the particle is not matched to a MCParticle.
954 Returns -1 in case of unknown process.
956 Returns 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, ...).
958 List of possible values (taken from the Geant4 source of
959 `G4DecayProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/decay/include/G4DecayProcessType.hh>`_,
960 `G4HadronicProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/hadronic/management/include/G4HadronicProcessType.hh>`_,
961 `G4TransportationProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/transportation/include/G4TransportationProcessType.hh>`_ and
962 `G4EmProcessSubType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/electromagnetic/utils/include/G4EmProcessSubType.hh>`_)
964 * 1 Coulomb scattering
967 * 4 Pair production by charged
969 * 6 Annihilation to mu mu
970 * 7 Annihilation to hadrons
972 * 9 Electron general process
973 * 10 Multiple scattering
975 * 12 Photo-electric effect
976 * 13 Compton scattering
977 * 14 Gamma conversion
978 * 15 Gamma conversion to mu mu
979 * 16 Gamma general process
982 * 23 Synchrotron radiation
983 * 24 Transition radiation
985 * 92 Coupled transportation
987 * 121 Hadron inelastic
989 * 132 Mu atomic capture
993 * 161 Charge exchange
995 * 202 Decay with spin
996 * 203 Decay (pion make spin)
997 * 210 Radioactive decay
1000 * 231 External decay
1002 .. note:: This is what `modularAnalysis.printMCParticles` shows as ``creation process`` when ``showStatus`` is set to ``True``.
1004 REGISTER_VARIABLE("mcParticleStatus", mcParticleStatus,
1005 "Returns status bits of related MCParticle or NaN if MCParticle relation is not set.");
1006 REGISTER_VARIABLE(
"mcPrimary", particleMCPrimaryParticle,
1007 "Returns 1 if Particle is related to primary MCParticle, 0 if Particle is related to non - primary MCParticle, "
1008 "NaN if Particle is not related to MCParticle.");
1009 REGISTER_VARIABLE(
"mcVirtual", particleMCVirtualParticle,
1010 "Returns 1 if Particle is related to virtual MCParticle, 0 if Particle is related to non - virtual MCParticle, "
1011 "NaN if Particle is not related to MCParticle.")
1012 REGISTER_VARIABLE("mcInitial", particleMCInitialParticle,
1013 "Returns 1 if Particle is related to initial MCParticle, 0 if Particle is related to non - initial MCParticle, "
1014 "NaN if Particle is not related to MCParticle.")
1015 REGISTER_VARIABLE("mcISR", particleMCISRParticle,
1016 "Returns 1 if Particle is related to ISR MCParticle, 0 if Particle is related to non - ISR MCParticle, "
1017 "NaN if Particle is not related to MCParticle.")
1018 REGISTER_VARIABLE("mcFSR", particleMCFSRParticle,
1019 "Returns 1 if Particle is related to FSR MCParticle, 0 if Particle is related to non - FSR MCParticle ,"
1020 "NaN if Particle is not related to MCParticle.")
1021 REGISTER_VARIABLE("mcPhotos", particleMCPhotosParticle,
1022 "Returns 1 if Particle is related to Photos MCParticle, 0 if Particle is related to non - Photos MCParticle, "
1023 "NaN if Particle is not related to MCParticle.")
1024 REGISTER_VARIABLE("generatorEventWeight", generatorEventWeight,
1025 "[Eventbased] Returns the event weight produced by the event generator")
1027 REGISTER_VARIABLE("genNStepsToDaughter(i)", genNStepsToDaughter,
1028 "Returns number of steps to i-th daughter from the particle at generator level. "
1029 "NaN if no MCParticle is associated to the particle or i-th daughter. "
1030 "NaN if i-th daughter does not exist.");
1031 REGISTER_VARIABLE("genNMissingDaughter(PDG)", genNMissingDaughter,
1032 "Returns the number of missing daughters having assigned PDG codes. "
1033 "NaN if no MCParticle is associated to the particle.");
1034 REGISTER_VARIABLE("Eher", getHEREnergy, R"DOC(
1035 [Eventbased] The nominal HER energy used by the generator.
1037 .. warning:: This variable does not make sense for data.
1040 REGISTER_VARIABLE("Eler", getLEREnergy, R"DOC(
1041 [Eventbased] The nominal LER energy used by the generator.
1043 .. warning:: This variable does not make sense for data.
1046 REGISTER_VARIABLE("XAngle", getCrossingAngleX, R"DOC(
1047 [Eventbased] The nominal beam crossing angle in the x-z plane from generator level beam kinematics.
1049 .. warning:: This variable does not make sense for data.
1052 REGISTER_VARIABLE("YAngle", getCrossingAngleY, R"DOC(
1053 [Eventbased] The nominal beam crossing angle in the y-z plane from generator level beam kinematics.
1055 .. warning:: This variable does not make sense for data.
1059 VARIABLE_GROUP("Generated tau decay information");
1060 REGISTER_VARIABLE("tauPlusMCMode", tauPlusMcMode,
1061 "[Eventbased] Decay ID for the positive tau lepton in a tau pair generated event.");
1062 REGISTER_VARIABLE("tauMinusMCMode", tauMinusMcMode,
1063 "[Eventbased] Decay ID for the negative tau lepton in a tau pair generated event.");
1064 REGISTER_VARIABLE("tauPlusMCProng", tauPlusMcProng,
1065 "[Eventbased] Prong for the positive tau lepton in a tau pair generated event.");
1066 REGISTER_VARIABLE("tauMinusMCProng", tauMinusMcProng,
1067 "[Eventbased] Prong for the negative tau lepton in a tau pair generated event.");
1069 VARIABLE_GROUP("MC particle seen in subdetectors");
1070 REGISTER_VARIABLE("isReconstructible", isReconstructible,
1071 "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.");
1072 REGISTER_VARIABLE("seenInPXD", seenInPXD,
1073 "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.");
1074 REGISTER_VARIABLE("seenInSVD", seenInSVD,
1075 "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.");
1076 REGISTER_VARIABLE("seenInCDC", seenInCDC,
1077 "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.");
1078 REGISTER_VARIABLE("seenInTOP", seenInTOP,
1079 "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.");
1080 REGISTER_VARIABLE("seenInECL", seenInECL,
1081 "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.");
1082 REGISTER_VARIABLE("seenInARICH", seenInARICH,
1083 "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.");
1084 REGISTER_VARIABLE("seenInKLM", seenInKLM,
1085 "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.");
1087 VARIABLE_GROUP("MC Matching for ECLClusters");
1088 REGISTER_VARIABLE("clusterMCMatchWeight", particleClusterMatchWeight,
1089 "Returns the weight of the ECLCluster -> MCParticle relation for the MCParticle matched to the particle. "
1090 "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. "
1091 "Returns -1 if the cluster *was* matched to particles, but not the match of the particle provided.");
1092 REGISTER_VARIABLE("clusterBestMCMatchWeight", particleClusterBestMCMatchWeight,
1093 "Returns the weight of the ECLCluster -> MCParticle relation for the relation with the largest weight.");
1094 REGISTER_VARIABLE("clusterBestMCPDG", particleClusterBestMCPDGCode,
1095 "Returns the PDG code of the MCParticle for the ECLCluster -> MCParticle relation with the largest weight.");
1096 REGISTER_VARIABLE("clusterTotalMCMatchWeight", particleClusterTotalMCMatchWeight,
1097 "Returns the sum of all weights of the ECLCluster -> MCParticles relations.");
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
@ 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.