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().Mag();
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 particleMCRecoilMass(
const Particle* part)
357 StoreArray<MCParticle> mcparticles;
358 if (mcparticles.getEntries() < 1)
return realNaN;
360 ROOT::Math::PxPyPzEVector pInitial = mcparticles[0]->get4Vector();
361 ROOT::Math::PxPyPzEVector pDaughters;
362 const std::vector<Particle*> daughters = part->getDaughters();
363 for (
auto daughter : daughters) {
364 const MCParticle* mcD = daughter->getMCParticle();
365 if (!mcD)
return realNaN;
367 pDaughters += mcD->get4Vector();
369 return (pInitial - pDaughters).M();
372 ROOT::Math::PxPyPzEVector MCInvisibleP4(
const MCParticle* mcparticle)
374 ROOT::Math::PxPyPzEVector ResultP4;
375 int pdg = abs(mcparticle->getPDG());
376 bool isNeutrino = (pdg == 12 or pdg == 14 or pdg == 16);
378 if (mcparticle->getNDaughters() > 0) {
379 const std::vector<MCParticle*> daughters = mcparticle->getDaughters();
380 for (
auto daughter : daughters)
381 ResultP4 += MCInvisibleP4(daughter);
382 }
else if (isNeutrino)
383 ResultP4 += mcparticle->get4Vector();
388 double particleMCCosThetaBetweenParticleAndNominalB(
const Particle* part)
390 int particlePDG = abs(part->getPDGCode());
391 if (particlePDG != 511 and particlePDG != 521)
392 B2FATAL(
"The variable mcCosThetaBetweenParticleAndNominalB is only meant to be used on B mesons!");
395 double e_Beam = T.getCMSEnergy() / 2.0;
396 double m_B = part->getPDGMass();
399 const double mY4S = 10.5794;
402 if (e_Beam * e_Beam - m_B * m_B < 0) {
405 double p_B = std::sqrt(e_Beam * e_Beam - m_B * m_B);
409 if (!mcB)
return realNaN;
411 int mcParticlePDG = abs(mcB->getPDG());
412 if (mcParticlePDG != 511 and mcParticlePDG != 521)
415 ROOT::Math::PxPyPzEVector p = T.rotateLabToCms() * (mcB->get4Vector() - MCInvisibleP4(mcB));
420 double theta_BY = (2 * e_Beam * e_d - m_B * m_B - m_d * m_d)
425 double mcParticleSecondaryPhysicsProcess(
const Particle* p)
427 const MCParticle* mcp = p->getMCParticle();
428 if (!mcp)
return realNaN;
429 return mcp->getSecondaryPhysicsProcess();
432 double mcParticleStatus(
const Particle* p)
434 const MCParticle* mcp = p->getMCParticle();
435 if (!mcp)
return realNaN;
436 return mcp->getStatus();
439 double particleMCPrimaryParticle(
const Particle* p)
441 const MCParticle* mcp = p->getMCParticle();
442 if (!mcp)
return realNaN;
445 return mcp->hasStatus(bitmask);
448 double particleMCVirtualParticle(
const Particle* p)
450 const MCParticle* mcp = p->getMCParticle();
451 if (!mcp)
return realNaN;
454 return mcp->hasStatus(bitmask);
457 double particleMCInitialParticle(
const Particle* p)
459 const MCParticle* mcp = p->getMCParticle();
460 if (!mcp)
return realNaN;
463 return mcp->hasStatus(bitmask);
466 double particleMCISRParticle(
const Particle* p)
468 const MCParticle* mcp = p->getMCParticle();
469 if (!mcp)
return realNaN;
472 return mcp->hasStatus(bitmask);
475 double particleMCFSRParticle(
const Particle* p)
477 const MCParticle* mcp = p->getMCParticle();
478 if (!mcp)
return realNaN;
481 return mcp->hasStatus(bitmask);
484 double particleMCPhotosParticle(
const Particle* p)
486 const MCParticle* mcp = p->getMCParticle();
487 if (!mcp)
return realNaN;
490 return mcp->hasStatus(bitmask);
493 double generatorEventWeight(
const Particle*)
495 StoreObjPtr<EventMetaData> evtMetaData;
496 if (!evtMetaData)
return realNaN;
497 return evtMetaData->getGeneratedWeight();
500 int tauPlusMcMode(
const Particle*)
502 StoreObjPtr<TauPairDecay> tauDecay;
504 B2WARNING(
"Cannot find tau decay ID, did you forget to run TauDecayMarkerModule?");
507 return tauDecay->getTauPlusIdMode();
510 int tauMinusMcMode(
const Particle*)
512 StoreObjPtr<TauPairDecay> tauDecay;
514 B2WARNING(
"Cannot find tau decay ID, did you forget to run TauDecayMarkerModule?");
517 return tauDecay->getTauMinusIdMode();
520 int tauPlusMcProng(
const Particle*)
522 StoreObjPtr<TauPairDecay> tauDecay;
524 B2WARNING(
"Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
527 return tauDecay->getTauPlusMcProng();
530 int tauMinusMcProng(
const Particle*)
532 StoreObjPtr<TauPairDecay> tauDecay;
534 B2WARNING(
"Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
537 return tauDecay->getTauMinusMcProng();
540 double isReconstructible(
const Particle* p)
542 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
544 const MCParticle* mcp = p->getMCParticle();
545 if (!mcp)
return realNaN;
549 return (abs(mcp->getCharge()) > 0) ? seenInSVD(p) : seenInECL(p);
552 double seenInPXD(
const Particle* p)
554 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
556 const MCParticle* mcp = p->getMCParticle();
557 if (!mcp)
return realNaN;
558 return mcp->hasSeenInDetector(Const::PXD);
561 double seenInSVD(
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::SVD);
570 double seenInCDC(
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::CDC);
579 double seenInTOP(
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::TOP);
588 double seenInECL(
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::ECL);
597 double seenInARICH(
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::ARICH);
606 double seenInKLM(
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::KLM);
615 int genNStepsToDaughter(
const Particle* p,
const std::vector<double>& arguments)
617 if (arguments.size() != 1)
618 B2FATAL(
"Wrong number of arguments for genNStepsToDaughter");
620 const MCParticle* mcp = p->getMCParticle();
622 B2WARNING(
"No MCParticle is associated to the particle");
626 int nChildren = p->getNDaughters();
627 if (arguments[0] >= nChildren) {
631 const Particle* daugP = p->getDaughter(arguments[0]);
636 B2WARNING(
"No MCParticle is associated to the i-th daughter");
640 if (nChildren == 1)
return 1;
642 std::vector<int> genMothers;
644 auto match = std::find(genMothers.begin(), genMothers.end(), mcp->getIndex());
645 return match - genMothers.begin();
648 int genNMissingDaughter(
const Particle* p,
const std::vector<double>& arguments)
650 if (arguments.size() < 1)
651 B2FATAL(
"Wrong number of arguments for genNMissingDaughter");
653 const std::vector<int> PDGcodes(arguments.begin(), arguments.end());
655 const MCParticle* mcp = p->getMCParticle();
657 B2WARNING(
"No MCParticle is associated to the particle");
664 double getHEREnergy(
const Particle*)
666 static DBObjPtr<BeamParameters> beamParamsDB;
667 return (beamParamsDB->getHER()).E();
670 double getLEREnergy(
const Particle*)
672 static DBObjPtr<BeamParameters> beamParamsDB;
673 return (beamParamsDB->getLER()).E();
676 double getCrossingAngleX(
const Particle*)
679 static DBObjPtr<BeamParameters> beamParamsDB;
680 B2Vector3D herVec = beamParamsDB->getHER().Vect();
681 B2Vector3D lerVec = beamParamsDB->getLER().Vect();
688 return herVec.Angle(-lerVec);
691 double getCrossingAngleY(
const Particle*)
694 static DBObjPtr<BeamParameters> beamParamsDB;
695 B2Vector3D herVec = beamParamsDB->getHER().Vect();
696 B2Vector3D lerVec = beamParamsDB->getLER().Vect();
703 return herVec.Angle(-lerVec);
707 double particleClusterMatchWeight(
const Particle* particle)
715 const MCParticle* matchedToParticle = particle->
getMCParticle();
716 if (!matchedToParticle)
return realNaN;
717 int matchedToIndex = matchedToParticle->getArrayIndex();
719 const ECLCluster* cluster = particle->getECLCluster();
720 if (!cluster)
return realNaN;
722 const auto mcps = cluster->getRelationsTo<MCParticle>();
723 for (
unsigned int i = 0; i < mcps.size(); ++i)
724 if (mcps[i]->getArrayIndex() == matchedToIndex)
725 return mcps.weight(i);
730 double particleClusterBestMCMatchWeight(
const Particle* particle)
742 const ECLCluster* cluster = particle->getECLCluster();
743 if (!cluster)
return realNaN;
748 auto mcps = cluster->getRelationsTo<MCParticle>();
749 if (mcps.size() == 0)
return realNaN;
751 std::vector<double> weights;
752 for (
unsigned int i = 0; i < mcps.size(); ++i)
753 weights.emplace_back(mcps.weight(i));
756 std::sort(weights.begin(), weights.end());
757 std::reverse(weights.begin(), weights.end());
761 double particleClusterBestMCPDGCode(
const Particle* particle)
771 const ECLCluster* cluster = particle->getECLCluster();
772 if (!cluster)
return realNaN;
774 auto mcps = cluster->getRelationsTo<MCParticle>();
775 if (mcps.size() == 0)
return realNaN;
777 std::vector<std::pair<double, int>> weightsAndIndices;
778 for (
unsigned int i = 0; i < mcps.size(); ++i)
779 weightsAndIndices.emplace_back(mcps.weight(i), i);
783 weightsAndIndices.begin(), weightsAndIndices.end(),
784 [](
const std::pair<double, int>& l,
const std::pair<double, int>& r) {
785 return l.first > r.first;
788 return mcps.object(weightsAndIndices[0].second)->getPDG();
791 double particleClusterTotalMCMatchWeight(
const Particle* particle)
793 const ECLCluster* cluster = particle->getECLCluster();
794 if (!cluster)
return realNaN;
796 auto mcps = cluster->getRelationsTo<MCParticle>();
799 double weightsum = 0;
800 for (
unsigned int i = 0; i < mcps.size(); ++i)
801 weightsum += mcps.weight(i);
806 double isBBCrossfeed(
const Particle* particle)
808 if (particle ==
nullptr)
809 return std::numeric_limits<double>::quiet_NaN();
811 int pdg = particle->getPDGCode();
812 if (abs(pdg) != 511 && abs(pdg) != 521 && abs(pdg) != 531)
813 return std::numeric_limits<double>::quiet_NaN();
815 std::vector<const Particle*> daughters = particle->getFinalStateDaughters();
816 int nDaughters = daughters.size();
819 std::vector<int> mother_ids;
821 for (
int j = 0; j < nDaughters; ++j) {
822 const MCParticle* curMCParticle = daughters[j]->
getMCParticle();
823 while (curMCParticle !=
nullptr) {
824 pdg = curMCParticle->getPDG();
825 if (abs(pdg) == 511 || abs(pdg) == 521 || abs(pdg) == 531) {
826 mother_ids.emplace_back(curMCParticle->getArrayIndex());
829 const MCParticle* curMCMother = curMCParticle->getMother();
830 curMCParticle = curMCMother;
832 if (curMCParticle ==
nullptr) {
833 return std::numeric_limits<double>::quiet_NaN();
837 std::set<int> distinctIDs = std::set(mother_ids.begin(), mother_ids.end());
838 if (distinctIDs.size() == 1)
844 VARIABLE_GROUP(
"MC matching and MC truth");
845 REGISTER_VARIABLE(
"isSignal", isSignal,
846 "1.0 if Particle is correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found. \n"
847 "It behaves according to DecayStringGrammar.");
848 REGISTER_VARIABLE(
"isSignalAcceptWrongFSPs", isSignalAcceptWrongFSPs,
849 "1.0 if Particle is almost correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found.\n"
850 "Misidentification of charged FSP is allowed.");
851 REGISTER_VARIABLE(
"isPrimarySignal", isPrimarySignal,
852 "1.0 if Particle is correctly reconstructed (SIGNAL) and primary, 0.0 if not, and NaN if no related MCParticle could be found");
853 REGISTER_VARIABLE(
"isSignalAcceptBremsPhotons", isSignalAcceptBremsPhotons,
854 "1.0 if Particle is correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found.\n"
855 "Particles with gamma daughters attached through the bremsstrahlung recovery modules are allowed.");
856 REGISTER_VARIABLE(
"genMotherPDG", genMotherPDG,
857 "Check the PDG code of a particles MC mother particle");
858 REGISTER_VARIABLE(
"genMotherPDG(i)", genNthMotherPDG,
859 "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:");
861 REGISTER_VARIABLE(
"genMotherID", genMotherIndex,
862 "Check the array index of a particles generated mother");
863 REGISTER_VARIABLE(
"genMotherID(i)", genNthMotherIndex,
864 "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:");
868 REGISTER_VARIABLE(
"isBBCrossfeed", isBBCrossfeed,
869 "Returns 1 for crossfeed in reconstruction of given B meson, 0 for no crossfeed and NaN for no true B meson or failed truthmatching.");
870 REGISTER_VARIABLE(
"genMotherP", genMotherP,
871 "Generated momentum of a particles MC mother particle",
"GeV/c");
872 REGISTER_VARIABLE(
"genParticleID", genParticleIndex,
873 "Check the array index of a particle's related MCParticle");
874 REGISTER_VARIABLE(
"isSignalAcceptMissingNeutrino",
875 isSignalAcceptMissingNeutrino,
876 "Same as isSignal, but also accept missing neutrino");
877 REGISTER_VARIABLE(
"isSignalAcceptMissingMassive",
878 isSignalAcceptMissingMassive,
879 "Same as isSignal, but also accept missing massive particle");
880 REGISTER_VARIABLE(
"isSignalAcceptMissingGamma",
881 isSignalAcceptMissingGamma,
882 "Same as isSignal, but also accept missing gamma, such as B -> K* gamma, pi0 -> gamma gamma");
883 REGISTER_VARIABLE(
"isSignalAcceptMissing",
884 isSignalAcceptMissing,
885 "Same as isSignal, but also accept missing particle");
886 REGISTER_VARIABLE(
"isMisidentified", isMisidentified,
887 "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.");
888 REGISTER_VARIABLE(
"isWrongCharge", isWrongCharge,
889 "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.");
890 REGISTER_VARIABLE(
"isCloneTrack", isCloneTrack,
891 "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)");
892 REGISTER_VARIABLE(
"isOrHasCloneTrack", isOrHasCloneTrack,
893 "Return 1 if the particle is a clone track or has a clone track as a daughter, 0 otherwise.");
894 REGISTER_VARIABLE(
"mcPDG", particleMCMatchPDGCode,
895 "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).");
896 REGISTER_VARIABLE(
"mcErrors", particleMCErrors,
897 "The bit pattern indicating the quality of MC match (see MCMatching::MCErrorFlags)");
898 REGISTER_VARIABLE(
"mcMatchWeight", particleMCMatchWeight,
899 "The weight of the Particle -> MCParticle relation (only for the first Relation = largest weight).");
900 REGISTER_VARIABLE(
"nMCMatches", particleNumberOfMCMatch,
901 "The number of relations of this Particle to MCParticle.");
902 REGISTER_VARIABLE(
"mcDecayTime", particleMCMatchDecayTime,
903 "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).",
905 REGISTER_VARIABLE(
"mcLifeTime", particleMCMatchLifeTime,
906 "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).",
908 REGISTER_VARIABLE(
"mcPX", particleMCMatchPX,
909 "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).",
911 REGISTER_VARIABLE(
"mcPY", particleMCMatchPY,
912 "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).",
914 REGISTER_VARIABLE(
"mcPZ", particleMCMatchPZ,
915 "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).",
917 REGISTER_VARIABLE(
"mcPT", particleMCMatchPT,
918 "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).",
920 REGISTER_VARIABLE(
"mcE", particleMCMatchE,
921 "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).",
923 REGISTER_VARIABLE(
"mcP", particleMCMatchP,
924 "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).",
926 REGISTER_VARIABLE(
"mcPhi", particleMCMatchPhi,
927 "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).",
929 REGISTER_VARIABLE(
"mcTheta", particleMCMatchTheta,
930 "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).",
932 REGISTER_VARIABLE(
"mcRecoilMass", particleMCRecoilMass,
933 "The mass recoiling against the particles attached as particle's daughters calculated using MC truth values.",
934 "GeV/:math:`\\text{c}^2`");
935 REGISTER_VARIABLE(
"mcCosThetaBetweenParticleAndNominalB",
936 particleMCCosThetaBetweenParticleAndNominalB,
937 "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.");
940 REGISTER_VARIABLE(
"mcSecPhysProc", mcParticleSecondaryPhysicsProcess,
941 "Returns the secondary physics process flag.");
942 REGISTER_VARIABLE(
"mcParticleStatus", mcParticleStatus,
943 "Returns status bits of related MCParticle or NaN if MCParticle relation is not set.");
944 REGISTER_VARIABLE(
"mcPrimary", particleMCPrimaryParticle,
945 "Returns 1 if Particle is related to primary MCParticle, 0 if Particle is related to non - primary MCParticle, "
946 "NaN if Particle is not related to MCParticle.");
947 REGISTER_VARIABLE(
"mcVirtual", particleMCVirtualParticle,
948 "Returns 1 if Particle is related to virtual MCParticle, 0 if Particle is related to non - virtual MCParticle, "
949 "NaN if Particle is not related to MCParticle.")
950 REGISTER_VARIABLE("mcInitial", particleMCInitialParticle,
951 "Returns 1 if Particle is related to initial MCParticle, 0 if Particle is related to non - initial MCParticle, "
952 "NaN if Particle is not related to MCParticle.")
953 REGISTER_VARIABLE("mcISR", particleMCISRParticle,
954 "Returns 1 if Particle is related to ISR MCParticle, 0 if Particle is related to non - ISR MCParticle, "
955 "NaN if Particle is not related to MCParticle.")
956 REGISTER_VARIABLE("mcFSR", particleMCFSRParticle,
957 "Returns 1 if Particle is related to FSR MCParticle, 0 if Particle is related to non - FSR MCParticle ,"
958 "NaN if Particle is not related to MCParticle.")
959 REGISTER_VARIABLE("mcPhotos", particleMCPhotosParticle,
960 "Returns 1 if Particle is related to Photos MCParticle, 0 if Particle is related to non - Photos MCParticle, "
961 "NaN if Particle is not related to MCParticle.")
962 REGISTER_VARIABLE("generatorEventWeight", generatorEventWeight,
963 "[Eventbased] Returns the event weight produced by the event generator")
965 REGISTER_VARIABLE("genNStepsToDaughter(i)", genNStepsToDaughter,
966 "Returns number of steps to i-th daughter from the particle at generator level. "
967 "NaN if no MCParticle is associated to the particle or i-th daughter. "
968 "NaN if i-th daughter does not exist.");
969 REGISTER_VARIABLE("genNMissingDaughter(PDG)", genNMissingDaughter,
970 "Returns the number of missing daughters having assigned PDG codes. "
971 "NaN if no MCParticle is associated to the particle.");
972 REGISTER_VARIABLE("Eher", getHEREnergy, R"DOC(
973 [Eventbased] The nominal HER energy used by the generator.
975 .. warning:: This variable does not make sense for data.
977 REGISTER_VARIABLE("Eler", getLEREnergy, R"DOC(
978 [Eventbased] The nominal LER energy used by the generator.
980 .. warning:: This variable does not make sense for data.
982 REGISTER_VARIABLE("XAngle", getCrossingAngleX, R"DOC(
983 [Eventbased] The nominal beam crossing angle in the x-z plane from generator level beam kinematics.
985 .. warning:: This variable does not make sense for data.
987 REGISTER_VARIABLE("YAngle", getCrossingAngleY, R"DOC(
988 [Eventbased] The nominal beam crossing angle in the y-z plane from generator level beam kinematics.
990 .. warning:: This variable does not make sense for data.
993 VARIABLE_GROUP("Generated tau decay information");
994 REGISTER_VARIABLE("tauPlusMCMode", tauPlusMcMode,
995 "[Eventbased] Decay ID for the positive tau lepton in a tau pair generated event.");
996 REGISTER_VARIABLE("tauMinusMCMode", tauMinusMcMode,
997 "[Eventbased] Decay ID for the negative tau lepton in a tau pair generated event.");
998 REGISTER_VARIABLE("tauPlusMCProng", tauPlusMcProng,
999 "[Eventbased] Prong for the positive tau lepton in a tau pair generated event.");
1000 REGISTER_VARIABLE("tauMinusMCProng", tauMinusMcProng,
1001 "[Eventbased] Prong for the negative tau lepton in a tau pair generated event.");
1003 VARIABLE_GROUP("MC particle seen in subdetectors");
1004 REGISTER_VARIABLE("isReconstructible", isReconstructible,
1005 "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.");
1006 REGISTER_VARIABLE("seenInPXD", seenInPXD,
1007 "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.");
1008 REGISTER_VARIABLE("seenInSVD", seenInSVD,
1009 "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.");
1010 REGISTER_VARIABLE("seenInCDC", seenInCDC,
1011 "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.");
1012 REGISTER_VARIABLE("seenInTOP", seenInTOP,
1013 "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.");
1014 REGISTER_VARIABLE("seenInECL", seenInECL,
1015 "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.");
1016 REGISTER_VARIABLE("seenInARICH", seenInARICH,
1017 "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.");
1018 REGISTER_VARIABLE("seenInKLM", seenInKLM,
1019 "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.");
1021 VARIABLE_GROUP("MC Matching for ECLClusters");
1022 REGISTER_VARIABLE("clusterMCMatchWeight", particleClusterMatchWeight,
1023 "Returns the weight of the ECLCluster -> MCParticle relation for the MCParticle matched to the particle. "
1024 "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. "
1025 "Returns -1 if the cluster *was* matched to particles, but not the match of the particle provided.");
1026 REGISTER_VARIABLE("clusterBestMCMatchWeight", particleClusterBestMCMatchWeight,
1027 "Returns the weight of the ECLCluster -> MCParticle relation for the relation with the largest weight.");
1028 REGISTER_VARIABLE("clusterBestMCPDG", particleClusterBestMCPDGCode,
1029 "Returns the PDG code of the MCParticle for the ECLCluster -> MCParticle relation with the largest weight.");
1030 REGISTER_VARIABLE("clusterTotalMCMatchWeight", particleClusterTotalMCMatchWeight,
1031 "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.