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>
20 #include <mdst/dataobjects/MCParticle.h>
21 #include <mdst/dataobjects/ECLCluster.h>
23 #include <framework/datastore/StoreArray.h>
24 #include <framework/datastore/StoreObjPtr.h>
25 #include <framework/dataobjects/EventMetaData.h>
26 #include <framework/gearbox/Const.h>
27 #include <framework/logging/Logger.h>
28 #include <framework/database/DBObjPtr.h>
29 #include <framework/dbobjects/BeamParameters.h>
40 static const double realNaN = std::numeric_limits<double>::quiet_NaN();
43 double isSignal(
const Particle* part)
46 if (!mcparticle)
return realNaN;
52 double isSignalAcceptWrongFSPs(
const Particle* part)
55 if (!mcparticle)
return realNaN;
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)
73 if (!mcp)
return realNaN;
78 double isWrongCharge(
const Particle* part)
81 if (!mcp)
return realNaN;
82 return (part->getCharge() != mcp->getCharge());
85 double isCloneTrack(
const Particle* particle)
91 const auto mcpww = particle->getRelatedToWithWeight<MCParticle>();
92 if (!mcpww.first)
return realNaN;
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 genMotherPDG(
const Particle* part)
146 return genNthMotherPDG(part, {});
149 double genMotherP(
const Particle* part)
152 if (!mcparticle)
return realNaN;
154 const MCParticle* mcmother = mcparticle->getMother();
155 if (!mcmother)
return realNaN;
157 return mcmother->getMomentum().R();
160 double genMotherIndex(
const Particle* part)
162 return genNthMotherIndex(part, {});
165 double genParticleIndex(
const Particle* part)
168 if (!mcparticle)
return realNaN;
169 return mcparticle->getArrayIndex();
172 double isSignalAcceptMissingNeutrino(
const Particle* part)
175 if (!mcparticle)
return realNaN;
179 status &= (~MCMatching::c_MissNeutrino);
184 double isSignalAcceptMissingMassive(
const Particle* part)
187 if (!mcparticle)
return realNaN;
191 status &= (~MCMatching::c_MissMassiveParticle);
192 status &= (~MCMatching::c_MissKlong);
197 double isSignalAcceptMissingGamma(
const Particle* part)
200 if (!mcparticle)
return realNaN;
204 status &= (~MCMatching::c_MissGamma);
209 double isSignalAcceptMissing(
const Particle* part)
212 if (!mcparticle)
return realNaN;
216 status &= (~MCMatching::c_MissGamma);
217 status &= (~MCMatching::c_MissMassiveParticle);
218 status &= (~MCMatching::c_MissKlong);
219 status &= (~MCMatching::c_MissNeutrino);
224 double isSignalAcceptBremsPhotons(
const Particle* part)
227 if (!mcparticle)
return realNaN;
231 status &= (~MCMatching::c_AddedRecoBremsPhoton);
236 double particleMCMatchPDGCode(
const Particle* part)
239 if (!mcparticle)
return realNaN;
240 return mcparticle->getPDG();
243 double particleMCErrors(
const Particle* part)
248 double particleNumberOfMCMatch(
const Particle* particle)
250 RelationVector<MCParticle> mcRelations = particle->getRelationsTo<MCParticle>();
251 return (mcRelations.size());
254 double particleMCMatchWeight(
const Particle* particle)
256 auto relWithWeight = particle->getRelatedToWithWeight<MCParticle>();
257 if (!relWithWeight.first)
return realNaN;
258 return relWithWeight.second;
261 double particleMCMatchDecayTime(
const Particle* part)
264 if (!mcparticle)
return realNaN;
265 return mcparticle->getDecayTime();
268 double particleMCMatchLifeTime(
const Particle* part)
271 if (!mcparticle)
return realNaN;
272 return mcparticle->getLifetime();
275 double particleMCMatchPX(
const Particle* part)
278 if (!mcparticle)
return realNaN;
281 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
282 return frame.getMomentum(mcpP4).Px();
285 double particleMCMatchPY(
const Particle* part)
288 if (!mcparticle)
return realNaN;
291 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
292 return frame.getMomentum(mcpP4).Py();
295 double particleMCMatchPZ(
const Particle* part)
298 if (!mcparticle)
return realNaN;
301 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
302 return frame.getMomentum(mcpP4).Pz();
305 double particleMCMatchPT(
const Particle* part)
308 if (!mcparticle)
return realNaN;
311 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
312 return frame.getMomentum(mcpP4).Pt();
315 double particleMCMatchE(
const Particle* part)
318 if (!mcparticle)
return realNaN;
321 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
322 return frame.getMomentum(mcpP4).E();
325 double particleMCMatchP(
const Particle* part)
328 if (!mcparticle)
return realNaN;
331 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
332 return frame.getMomentum(mcpP4).P();
335 double particleMCMatchTheta(
const Particle* part)
338 if (!mcparticle)
return realNaN;
341 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
342 return frame.getMomentum(mcpP4).Theta();
345 double particleMCMatchPhi(
const Particle* part)
348 if (!mcparticle)
return realNaN;
351 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
352 return frame.getMomentum(mcpP4).Phi();
355 double mcParticleNDaughters(
const Particle* part)
359 if (!mcparticle)
return realNaN;
360 return mcparticle->getNDaughters();
363 double particleMCRecoilMass(
const Particle* part)
365 StoreArray<MCParticle> mcparticles;
366 if (mcparticles.getEntries() < 1)
return realNaN;
368 ROOT::Math::PxPyPzEVector pInitial = mcparticles[0]->get4Vector();
369 ROOT::Math::PxPyPzEVector pDaughters;
370 const std::vector<Particle*> daughters = part->getDaughters();
371 for (
auto daughter : daughters) {
372 const MCParticle* mcD = daughter->getMCParticle();
373 if (!mcD)
return realNaN;
375 pDaughters += mcD->get4Vector();
377 return (pInitial - pDaughters).M();
380 ROOT::Math::PxPyPzEVector MCInvisibleP4(
const MCParticle* mcparticle)
382 ROOT::Math::PxPyPzEVector ResultP4;
383 int pdg = abs(mcparticle->getPDG());
384 bool isNeutrino = (pdg == 12 or pdg == 14 or pdg == 16);
386 if (mcparticle->getNDaughters() > 0) {
387 const std::vector<MCParticle*> daughters = mcparticle->getDaughters();
388 for (
auto daughter : daughters)
389 ResultP4 += MCInvisibleP4(daughter);
390 }
else if (isNeutrino)
391 ResultP4 += mcparticle->get4Vector();
396 double particleMCCosThetaBetweenParticleAndNominalB(
const Particle* part)
398 int particlePDG = abs(part->getPDGCode());
399 if (particlePDG != 511 and particlePDG != 521)
400 B2FATAL(
"The variable mcCosThetaBetweenParticleAndNominalB is only meant to be used on B mesons!");
403 double e_Beam = T.getCMSEnergy() / 2.0;
404 double m_B = part->getPDGMass();
407 const double mY4S = 10.5794;
410 if (e_Beam * e_Beam - m_B * m_B < 0) {
413 double p_B = std::sqrt(e_Beam * e_Beam - m_B * m_B);
417 if (!mcB)
return realNaN;
419 int mcParticlePDG = abs(mcB->getPDG());
420 if (mcParticlePDG != 511 and mcParticlePDG != 521)
423 ROOT::Math::PxPyPzEVector p = T.rotateLabToCms() * (mcB->get4Vector() - MCInvisibleP4(mcB));
428 double theta_BY = (2 * e_Beam * e_d - m_B * m_B - m_d * m_d)
433 double mcParticleSecondaryPhysicsProcess(
const Particle* p)
435 const MCParticle* mcp = p->getMCParticle();
436 if (!mcp)
return realNaN;
437 return mcp->getSecondaryPhysicsProcess();
440 double mcParticleStatus(
const Particle* p)
442 const MCParticle* mcp = p->getMCParticle();
443 if (!mcp)
return realNaN;
444 return mcp->getStatus();
447 double particleMCPrimaryParticle(
const Particle* p)
449 const MCParticle* mcp = p->getMCParticle();
450 if (!mcp)
return realNaN;
453 return mcp->hasStatus(bitmask);
456 double particleMCVirtualParticle(
const Particle* p)
458 const MCParticle* mcp = p->getMCParticle();
459 if (!mcp)
return realNaN;
462 return mcp->hasStatus(bitmask);
465 double particleMCInitialParticle(
const Particle* p)
467 const MCParticle* mcp = p->getMCParticle();
468 if (!mcp)
return realNaN;
471 return mcp->hasStatus(bitmask);
474 double particleMCISRParticle(
const Particle* p)
476 const MCParticle* mcp = p->getMCParticle();
477 if (!mcp)
return realNaN;
480 return mcp->hasStatus(bitmask);
483 double particleMCFSRParticle(
const Particle* p)
485 const MCParticle* mcp = p->getMCParticle();
486 if (!mcp)
return realNaN;
489 return mcp->hasStatus(bitmask);
492 double particleMCPhotosParticle(
const Particle* p)
494 const MCParticle* mcp = p->getMCParticle();
495 if (!mcp)
return realNaN;
498 return mcp->hasStatus(bitmask);
501 double generatorEventWeight(
const Particle*)
503 StoreObjPtr<EventMetaData> evtMetaData;
504 if (!evtMetaData)
return realNaN;
505 return evtMetaData->getGeneratedWeight();
508 int tauPlusMcMode(
const Particle*)
510 StoreObjPtr<TauPairDecay> tauDecay;
512 B2WARNING(
"Cannot find tau decay ID, did you forget to run TauDecayMarkerModule?");
515 return tauDecay->getTauPlusIdMode();
518 int tauMinusMcMode(
const Particle*)
520 StoreObjPtr<TauPairDecay> tauDecay;
522 B2WARNING(
"Cannot find tau decay ID, did you forget to run TauDecayMarkerModule?");
525 return tauDecay->getTauMinusIdMode();
528 int tauPlusMcProng(
const Particle*)
530 StoreObjPtr<TauPairDecay> tauDecay;
532 B2WARNING(
"Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
535 return tauDecay->getTauPlusMcProng();
538 int tauMinusMcProng(
const Particle*)
540 StoreObjPtr<TauPairDecay> tauDecay;
542 B2WARNING(
"Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
545 return tauDecay->getTauMinusMcProng();
548 double isReconstructible(
const Particle* p)
550 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
552 const MCParticle* mcp = p->getMCParticle();
553 if (!mcp)
return realNaN;
557 return (abs(mcp->getCharge()) > 0) ? seenInSVD(p) : seenInECL(p);
560 double seenInPXD(
const Particle* p)
562 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
564 const MCParticle* mcp = p->getMCParticle();
565 if (!mcp)
return realNaN;
566 return mcp->hasSeenInDetector(Const::PXD);
569 double seenInSVD(
const Particle* p)
571 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
573 const MCParticle* mcp = p->getMCParticle();
574 if (!mcp)
return realNaN;
575 return mcp->hasSeenInDetector(Const::SVD);
578 double seenInCDC(
const Particle* p)
580 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
582 const MCParticle* mcp = p->getMCParticle();
583 if (!mcp)
return realNaN;
584 return mcp->hasSeenInDetector(Const::CDC);
587 double seenInTOP(
const Particle* p)
589 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
591 const MCParticle* mcp = p->getMCParticle();
592 if (!mcp)
return realNaN;
593 return mcp->hasSeenInDetector(Const::TOP);
596 double seenInECL(
const Particle* p)
598 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
600 const MCParticle* mcp = p->getMCParticle();
601 if (!mcp)
return realNaN;
602 return mcp->hasSeenInDetector(Const::ECL);
605 double seenInARICH(
const Particle* p)
607 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
609 const MCParticle* mcp = p->getMCParticle();
610 if (!mcp)
return realNaN;
611 return mcp->hasSeenInDetector(Const::ARICH);
614 double seenInKLM(
const Particle* p)
616 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
618 const MCParticle* mcp = p->getMCParticle();
619 if (!mcp)
return realNaN;
620 return mcp->hasSeenInDetector(Const::KLM);
623 int genNStepsToDaughter(
const Particle* p,
const std::vector<double>& arguments)
625 if (arguments.size() != 1)
626 B2FATAL(
"Wrong number of arguments for genNStepsToDaughter");
628 const MCParticle* mcp = p->getMCParticle();
630 B2WARNING(
"No MCParticle is associated to the particle");
634 int nChildren = p->getNDaughters();
635 if (arguments[0] >= nChildren) {
639 const Particle* daugP = p->getDaughter(arguments[0]);
644 B2WARNING(
"No MCParticle is associated to the i-th daughter");
648 if (nChildren == 1)
return 1;
650 std::vector<int> genMothers;
652 auto match = std::find(genMothers.begin(), genMothers.end(), mcp->getIndex());
653 return match - genMothers.begin();
656 int genNMissingDaughter(
const Particle* p,
const std::vector<double>& arguments)
658 if (arguments.size() < 1)
659 B2FATAL(
"Wrong number of arguments for genNMissingDaughter");
661 const std::vector<int> PDGcodes(arguments.begin(), arguments.end());
663 const MCParticle* mcp = p->getMCParticle();
665 B2WARNING(
"No MCParticle is associated to the particle");
672 double getHEREnergy(
const Particle*)
674 static DBObjPtr<BeamParameters> beamParamsDB;
675 return (beamParamsDB->getHER()).E();
678 double getLEREnergy(
const Particle*)
680 static DBObjPtr<BeamParameters> beamParamsDB;
681 return (beamParamsDB->getLER()).E();
684 double getCrossingAngleX(
const Particle*)
687 static DBObjPtr<BeamParameters> beamParamsDB;
688 B2Vector3D herVec = beamParamsDB->getHER().Vect();
689 B2Vector3D lerVec = beamParamsDB->getLER().Vect();
696 return herVec.Angle(-lerVec);
699 double getCrossingAngleY(
const Particle*)
702 static DBObjPtr<BeamParameters> beamParamsDB;
703 B2Vector3D herVec = beamParamsDB->getHER().Vect();
704 B2Vector3D lerVec = beamParamsDB->getLER().Vect();
711 return herVec.Angle(-lerVec);
715 double particleClusterMatchWeight(
const Particle* particle)
723 const MCParticle* matchedToParticle = particle->
getMCParticle();
724 if (!matchedToParticle)
return realNaN;
725 int matchedToIndex = matchedToParticle->getArrayIndex();
727 const ECLCluster* cluster = particle->getECLCluster();
728 if (!cluster)
return realNaN;
730 const auto mcps = cluster->getRelationsTo<MCParticle>();
731 for (
unsigned int i = 0; i < mcps.size(); ++i)
732 if (mcps[i]->getArrayIndex() == matchedToIndex)
733 return mcps.weight(i);
738 double particleClusterBestMCMatchWeight(
const Particle* particle)
750 const ECLCluster* cluster = particle->getECLCluster();
751 if (!cluster)
return realNaN;
756 auto mcps = cluster->getRelationsTo<MCParticle>();
757 if (mcps.size() == 0)
return realNaN;
759 std::vector<double> weights;
760 for (
unsigned int i = 0; i < mcps.size(); ++i)
761 weights.emplace_back(mcps.weight(i));
764 std::sort(weights.begin(), weights.end());
765 std::reverse(weights.begin(), weights.end());
769 double particleClusterBestMCPDGCode(
const Particle* particle)
779 const ECLCluster* cluster = particle->getECLCluster();
780 if (!cluster)
return realNaN;
782 auto mcps = cluster->getRelationsTo<MCParticle>();
783 if (mcps.size() == 0)
return realNaN;
785 std::vector<std::pair<double, int>> weightsAndIndices;
786 for (
unsigned int i = 0; i < mcps.size(); ++i)
787 weightsAndIndices.emplace_back(mcps.weight(i), i);
791 weightsAndIndices.begin(), weightsAndIndices.end(),
792 [](
const std::pair<double, int>& l,
const std::pair<double, int>& r) {
793 return l.first > r.first;
796 return mcps.object(weightsAndIndices[0].second)->getPDG();
799 double particleClusterTotalMCMatchWeight(
const Particle* particle)
801 const ECLCluster* cluster = particle->getECLCluster();
802 if (!cluster)
return realNaN;
804 auto mcps = cluster->getRelationsTo<MCParticle>();
807 double weightsum = 0;
808 for (
unsigned int i = 0; i < mcps.size(); ++i)
809 weightsum += mcps.weight(i);
814 double isBBCrossfeed(
const Particle* particle)
816 if (particle ==
nullptr)
817 return std::numeric_limits<double>::quiet_NaN();
819 int pdg = particle->getPDGCode();
820 if (abs(pdg) != 511 && abs(pdg) != 521 && abs(pdg) != 531)
821 return std::numeric_limits<double>::quiet_NaN();
823 std::vector<const Particle*> daughters = particle->getFinalStateDaughters();
824 int nDaughters = daughters.size();
827 std::vector<int> mother_ids;
829 for (
int j = 0; j < nDaughters; ++j) {
830 const MCParticle* curMCParticle = daughters[j]->
getMCParticle();
831 while (curMCParticle !=
nullptr) {
832 pdg = curMCParticle->getPDG();
833 if (abs(pdg) == 511 || abs(pdg) == 521 || abs(pdg) == 531) {
834 mother_ids.emplace_back(curMCParticle->getArrayIndex());
837 const MCParticle* curMCMother = curMCParticle->getMother();
838 curMCParticle = curMCMother;
840 if (curMCParticle ==
nullptr) {
841 return std::numeric_limits<double>::quiet_NaN();
845 std::set<int> distinctIDs = std::set(mother_ids.begin(), mother_ids.end());
846 if (distinctIDs.size() == 1)
852 VARIABLE_GROUP(
"MC matching and MC truth");
853 REGISTER_VARIABLE(
"isSignal", isSignal,
854 "1.0 if Particle is correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found. \n"
855 "It behaves according to DecayStringGrammar.");
856 REGISTER_VARIABLE(
"isSignalAcceptWrongFSPs", isSignalAcceptWrongFSPs,
857 "1.0 if Particle is almost correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found.\n"
858 "Misidentification of charged FSP is allowed.");
859 REGISTER_VARIABLE(
"isPrimarySignal", isPrimarySignal,
860 "1.0 if Particle is correctly reconstructed (SIGNAL) and primary, 0.0 if not, and NaN if no related MCParticle could be found");
861 REGISTER_VARIABLE(
"isSignalAcceptBremsPhotons", isSignalAcceptBremsPhotons,
862 "1.0 if Particle is correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found.\n"
863 "Particles with gamma daughters attached through the bremsstrahlung recovery modules are allowed.");
864 REGISTER_VARIABLE(
"genMotherPDG", genMotherPDG,
865 "Check the PDG code of a particles MC mother particle");
866 REGISTER_VARIABLE(
"genMotherPDG(i)", genNthMotherPDG,
867 "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:");
869 REGISTER_VARIABLE(
"genMotherID", genMotherIndex,
870 "Check the array index of a particles generated mother");
871 REGISTER_VARIABLE(
"genMotherID(i)", genNthMotherIndex,
872 "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:");
876 REGISTER_VARIABLE(
"isBBCrossfeed", isBBCrossfeed,
877 "Returns 1 for crossfeed in reconstruction of given B meson, 0 for no crossfeed and NaN for no true B meson or failed truthmatching.");
878 REGISTER_VARIABLE(
"genMotherP", genMotherP,
879 "Generated momentum of a particles MC mother particle",
"GeV/c");
880 REGISTER_VARIABLE(
"genParticleID", genParticleIndex,
881 "Check the array index of a particle's related MCParticle");
882 REGISTER_VARIABLE(
"isSignalAcceptMissingNeutrino",
883 isSignalAcceptMissingNeutrino,
884 "Same as isSignal, but also accept missing neutrino");
885 REGISTER_VARIABLE(
"isSignalAcceptMissingMassive",
886 isSignalAcceptMissingMassive,
887 "Same as isSignal, but also accept missing massive particle");
888 REGISTER_VARIABLE(
"isSignalAcceptMissingGamma",
889 isSignalAcceptMissingGamma,
890 "Same as isSignal, but also accept missing gamma, such as B -> K* gamma, pi0 -> gamma gamma");
891 REGISTER_VARIABLE(
"isSignalAcceptMissing",
892 isSignalAcceptMissing,
893 "Same as isSignal, but also accept missing particle");
894 REGISTER_VARIABLE(
"isMisidentified", isMisidentified,
895 "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.");
896 REGISTER_VARIABLE(
"isWrongCharge", isWrongCharge,
897 "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.");
898 REGISTER_VARIABLE(
"isCloneTrack", isCloneTrack,
899 "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)");
900 REGISTER_VARIABLE(
"isOrHasCloneTrack", isOrHasCloneTrack,
901 "Return 1 if the particle is a clone track or has a clone track as a daughter, 0 otherwise.");
902 REGISTER_VARIABLE(
"mcPDG", particleMCMatchPDGCode,
903 "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).");
904 REGISTER_VARIABLE(
"mcErrors", particleMCErrors,
905 "The bit pattern indicating the quality of MC match (see MCMatching::MCErrorFlags)");
906 REGISTER_VARIABLE(
"mcMatchWeight", particleMCMatchWeight,
907 "The weight of the Particle -> MCParticle relation (only for the first Relation = largest weight).");
908 REGISTER_VARIABLE(
"nMCMatches", particleNumberOfMCMatch,
909 "The number of relations of this Particle to MCParticle.");
910 REGISTER_VARIABLE(
"mcDecayTime", particleMCMatchDecayTime,
911 "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).",
913 REGISTER_VARIABLE(
"mcLifeTime", particleMCMatchLifeTime,
914 "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).",
916 REGISTER_VARIABLE(
"mcPX", particleMCMatchPX,
917 "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).",
919 REGISTER_VARIABLE(
"mcPY", particleMCMatchPY,
920 "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).",
922 REGISTER_VARIABLE(
"mcPZ", particleMCMatchPZ,
923 "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).",
925 REGISTER_VARIABLE(
"mcPT", particleMCMatchPT,
926 "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).",
928 REGISTER_VARIABLE(
"mcE", particleMCMatchE,
929 "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).",
931 REGISTER_VARIABLE(
"mcP", particleMCMatchP,
932 "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).",
934 REGISTER_VARIABLE(
"mcPhi", particleMCMatchPhi,
935 "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).",
937 REGISTER_VARIABLE(
"mcTheta", particleMCMatchTheta,
938 "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).",
940 REGISTER_VARIABLE(
"nMCDaughters", mcParticleNDaughters,
941 "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).");
942 REGISTER_VARIABLE(
"mcRecoilMass", particleMCRecoilMass,
943 "The mass recoiling against the particles attached as particle's daughters calculated using MC truth values.",
944 "GeV/:math:`\\text{c}^2`");
945 REGISTER_VARIABLE(
"mcCosThetaBetweenParticleAndNominalB",
946 particleMCCosThetaBetweenParticleAndNominalB,
947 "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.");
950 REGISTER_VARIABLE(
"mcSecPhysProc", mcParticleSecondaryPhysicsProcess,
951 "Returns the secondary physics process flag.");
952 REGISTER_VARIABLE(
"mcParticleStatus", mcParticleStatus,
953 "Returns status bits of related MCParticle or NaN if MCParticle relation is not set.");
954 REGISTER_VARIABLE(
"mcPrimary", particleMCPrimaryParticle,
955 "Returns 1 if Particle is related to primary MCParticle, 0 if Particle is related to non - primary MCParticle, "
956 "NaN if Particle is not related to MCParticle.");
957 REGISTER_VARIABLE(
"mcVirtual", particleMCVirtualParticle,
958 "Returns 1 if Particle is related to virtual MCParticle, 0 if Particle is related to non - virtual MCParticle, "
959 "NaN if Particle is not related to MCParticle.")
960 REGISTER_VARIABLE("mcInitial", particleMCInitialParticle,
961 "Returns 1 if Particle is related to initial MCParticle, 0 if Particle is related to non - initial MCParticle, "
962 "NaN if Particle is not related to MCParticle.")
963 REGISTER_VARIABLE("mcISR", particleMCISRParticle,
964 "Returns 1 if Particle is related to ISR MCParticle, 0 if Particle is related to non - ISR MCParticle, "
965 "NaN if Particle is not related to MCParticle.")
966 REGISTER_VARIABLE("mcFSR", particleMCFSRParticle,
967 "Returns 1 if Particle is related to FSR MCParticle, 0 if Particle is related to non - FSR MCParticle ,"
968 "NaN if Particle is not related to MCParticle.")
969 REGISTER_VARIABLE("mcPhotos", particleMCPhotosParticle,
970 "Returns 1 if Particle is related to Photos MCParticle, 0 if Particle is related to non - Photos MCParticle, "
971 "NaN if Particle is not related to MCParticle.")
972 REGISTER_VARIABLE("generatorEventWeight", generatorEventWeight,
973 "[Eventbased] Returns the event weight produced by the event generator")
975 REGISTER_VARIABLE("genNStepsToDaughter(i)", genNStepsToDaughter,
976 "Returns number of steps to i-th daughter from the particle at generator level. "
977 "NaN if no MCParticle is associated to the particle or i-th daughter. "
978 "NaN if i-th daughter does not exist.");
979 REGISTER_VARIABLE("genNMissingDaughter(PDG)", genNMissingDaughter,
980 "Returns the number of missing daughters having assigned PDG codes. "
981 "NaN if no MCParticle is associated to the particle.");
982 REGISTER_VARIABLE("Eher", getHEREnergy, R"DOC(
983 [Eventbased] The nominal HER energy used by the generator.
985 .. warning:: This variable does not make sense for data.
987 REGISTER_VARIABLE("Eler", getLEREnergy, R"DOC(
988 [Eventbased] The nominal LER energy used by the generator.
990 .. warning:: This variable does not make sense for data.
992 REGISTER_VARIABLE("XAngle", getCrossingAngleX, R"DOC(
993 [Eventbased] The nominal beam crossing angle in the x-z plane from generator level beam kinematics.
995 .. warning:: This variable does not make sense for data.
997 REGISTER_VARIABLE("YAngle", getCrossingAngleY, R"DOC(
998 [Eventbased] The nominal beam crossing angle in the y-z plane from generator level beam kinematics.
1000 .. warning:: This variable does not make sense for data.
1003 VARIABLE_GROUP("Generated tau decay information");
1004 REGISTER_VARIABLE("tauPlusMCMode", tauPlusMcMode,
1005 "[Eventbased] Decay ID for the positive tau lepton in a tau pair generated event.");
1006 REGISTER_VARIABLE("tauMinusMCMode", tauMinusMcMode,
1007 "[Eventbased] Decay ID for the negative tau lepton in a tau pair generated event.");
1008 REGISTER_VARIABLE("tauPlusMCProng", tauPlusMcProng,
1009 "[Eventbased] Prong for the positive tau lepton in a tau pair generated event.");
1010 REGISTER_VARIABLE("tauMinusMCProng", tauMinusMcProng,
1011 "[Eventbased] Prong for the negative tau lepton in a tau pair generated event.");
1013 VARIABLE_GROUP("MC particle seen in subdetectors");
1014 REGISTER_VARIABLE("isReconstructible", isReconstructible,
1015 "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.");
1016 REGISTER_VARIABLE("seenInPXD", seenInPXD,
1017 "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.");
1018 REGISTER_VARIABLE("seenInSVD", seenInSVD,
1019 "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.");
1020 REGISTER_VARIABLE("seenInCDC", seenInCDC,
1021 "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.");
1022 REGISTER_VARIABLE("seenInTOP", seenInTOP,
1023 "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.");
1024 REGISTER_VARIABLE("seenInECL", seenInECL,
1025 "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.");
1026 REGISTER_VARIABLE("seenInARICH", seenInARICH,
1027 "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.");
1028 REGISTER_VARIABLE("seenInKLM", seenInKLM,
1029 "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.");
1031 VARIABLE_GROUP("MC Matching for ECLClusters");
1032 REGISTER_VARIABLE("clusterMCMatchWeight", particleClusterMatchWeight,
1033 "Returns the weight of the ECLCluster -> MCParticle relation for the MCParticle matched to the particle. "
1034 "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. "
1035 "Returns -1 if the cluster *was* matched to particles, but not the match of the particle provided.");
1036 REGISTER_VARIABLE("clusterBestMCMatchWeight", particleClusterBestMCMatchWeight,
1037 "Returns the weight of the ECLCluster -> MCParticle relation for the relation with the largest weight.");
1038 REGISTER_VARIABLE("clusterBestMCPDG", particleClusterBestMCPDGCode,
1039 "Returns the PDG code of the MCParticle for the ECLCluster -> MCParticle relation with the largest weight.");
1040 REGISTER_VARIABLE("clusterTotalMCMatchWeight", particleClusterTotalMCMatchWeight,
1041 "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.
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.