10 #include <analysis/variables/MCTruthVariables.h>
13 #include <analysis/VariableManager/Manager.h>
15 #include <analysis/dataobjects/Particle.h>
16 #include <analysis/dataobjects/TauPairDecay.h>
17 #include <analysis/utility/MCMatching.h>
18 #include <analysis/utility/ReferenceFrame.h>
19 #include <analysis/utility/ValueIndexPairSorting.h>
21 #include <mdst/dataobjects/MCParticle.h>
22 #include <mdst/dataobjects/ECLCluster.h>
23 #include <mdst/dataobjects/Track.h>
26 #include <framework/datastore/StoreArray.h>
27 #include <framework/datastore/StoreObjPtr.h>
28 #include <framework/dataobjects/EventMetaData.h>
29 #include <framework/gearbox/Const.h>
30 #include <framework/logging/Logger.h>
31 #include <framework/database/DBObjPtr.h>
32 #include <framework/dbobjects/BeamParameters.h>
43 double isSignal(
const Particle* part)
45 const MCParticle* mcparticle = part->getMCParticle();
52 double isSignalAcceptWrongFSPs(
const Particle* part)
54 const MCParticle* mcparticle = part->getMCParticle();
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)
72 const MCParticle* mcp = part->getMCParticle();
78 double isWrongCharge(
const Particle* part)
80 const MCParticle* mcp = part->getMCParticle();
82 return (part->getCharge() != mcp->getCharge());
85 double isCloneTrack(
const Particle* particle)
91 const auto mcpww = particle->getRelatedToWithWeight<MCParticle>();
93 return (mcpww.second < 0);
96 double isOrHasCloneTrack(
const Particle* particle)
99 std::queue<const Particle*> qq;
101 while (!qq.empty()) {
102 const auto d = qq.front();
104 if (isCloneTrack(d) == 1.0)
return 1.0;
105 size_t nDau = d->getNDaughters();
106 for (
size_t iDau = 0; iDau < nDau; ++iDau)
107 qq.push(d->getDaughter(iDau));
112 double genNthMotherPDG(
const Particle* part,
const std::vector<double>& args)
114 const MCParticle* mcparticle = part->getMCParticle();
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)
130 const MCParticle* mcparticle = part->getMCParticle();
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)
151 const MCParticle* mcparticle = part->getMCParticle();
154 const MCParticle* mcmother = mcparticle->getMother();
157 return mcmother->getMomentum().R();
160 double genMotherIndex(
const Particle* part)
162 return genNthMotherIndex(part, {});
165 double genParticleIndex(
const Particle* part)
167 const MCParticle* mcparticle = part->getMCParticle();
169 return mcparticle->getArrayIndex();
172 double isSignalAcceptMissingNeutrino(
const Particle* part)
174 const MCParticle* mcparticle = part->getMCParticle();
179 status &= (~MCMatching::c_MissNeutrino);
184 double isSignalAcceptMissingMassive(
const Particle* part)
186 const MCParticle* mcparticle = part->getMCParticle();
191 status &= (~MCMatching::c_MissMassiveParticle);
192 status &= (~MCMatching::c_MissKlong);
197 double isSignalAcceptMissingGamma(
const Particle* part)
199 const MCParticle* mcparticle = part->getMCParticle();
204 status &= (~MCMatching::c_MissGamma);
209 double isSignalAcceptMissing(
const Particle* part)
211 const MCParticle* mcparticle = part->getMCParticle();
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)
226 const MCParticle* mcparticle = part->getMCParticle();
231 status &= (~MCMatching::c_AddedRecoBremsPhoton);
236 double particleMCMatchPDGCode(
const Particle* part)
238 const MCParticle* mcparticle = part->getMCParticle();
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>();
258 return relWithWeight.second;
261 double particleMCMatchDecayTime(
const Particle* part)
263 const MCParticle* mcparticle = part->getMCParticle();
265 return mcparticle->getDecayTime();
268 double particleMCMatchLifeTime(
const Particle* part)
270 const MCParticle* mcparticle = part->getMCParticle();
272 return mcparticle->getLifetime();
275 double particleMCMatchPX(
const Particle* part)
277 const MCParticle* mcparticle = part->getMCParticle();
281 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
282 return frame.getMomentum(mcpP4).Px();
285 double particleMCMatchPY(
const Particle* part)
287 const MCParticle* mcparticle = part->getMCParticle();
291 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
292 return frame.getMomentum(mcpP4).Py();
295 double particleMCMatchPZ(
const Particle* part)
297 const MCParticle* mcparticle = part->getMCParticle();
301 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
302 return frame.getMomentum(mcpP4).Pz();
305 double particleMCMatchPT(
const Particle* part)
307 const MCParticle* mcparticle = part->getMCParticle();
311 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
312 return frame.getMomentum(mcpP4).Pt();
315 double particleMCMatchE(
const Particle* part)
317 const MCParticle* mcparticle = part->getMCParticle();
321 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
322 return frame.getMomentum(mcpP4).E();
325 double particleMCMatchP(
const Particle* part)
327 const MCParticle* mcparticle = part->getMCParticle();
331 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
332 return frame.getMomentum(mcpP4).P();
335 double particleMCMatchTheta(
const Particle* part)
337 const MCParticle* mcparticle = part->getMCParticle();
341 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
342 return frame.getMomentum(mcpP4).Theta();
345 double particleMCMatchPhi(
const Particle* part)
347 const MCParticle* mcparticle = part->getMCParticle();
351 ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
352 return frame.getMomentum(mcpP4).Phi();
355 double mcParticleNDaughters(
const Particle* part)
357 const MCParticle* mcparticle = part->getMCParticle();
360 return mcparticle->getNDaughters();
363 double particleMCRecoilMass(
const Particle* part)
365 StoreArray<MCParticle> mcparticles;
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();
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);
416 const MCParticle* mcB = part->getMCParticle();
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();
437 return mcp->getSecondaryPhysicsProcess();
440 double mcParticleStatus(
const Particle* p)
442 const MCParticle* mcp = p->getMCParticle();
444 return mcp->getStatus();
447 double particleMCPrimaryParticle(
const Particle* p)
449 const MCParticle* mcp = p->getMCParticle();
453 return mcp->hasStatus(bitmask);
456 double particleMCVirtualParticle(
const Particle* p)
458 const MCParticle* mcp = p->getMCParticle();
462 return mcp->hasStatus(bitmask);
465 double particleMCInitialParticle(
const Particle* p)
467 const MCParticle* mcp = p->getMCParticle();
471 return mcp->hasStatus(bitmask);
474 double particleMCISRParticle(
const Particle* p)
476 const MCParticle* mcp = p->getMCParticle();
480 return mcp->hasStatus(bitmask);
483 double particleMCFSRParticle(
const Particle* p)
485 const MCParticle* mcp = p->getMCParticle();
489 return mcp->hasStatus(bitmask);
492 double particleMCPhotosParticle(
const Particle* p)
494 const MCParticle* mcp = p->getMCParticle();
498 return mcp->hasStatus(bitmask);
501 double generatorEventWeight(
const Particle*)
503 StoreObjPtr<EventMetaData> evtMetaData;
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 tauPlusEgstar(
const Particle*)
550 StoreObjPtr<TauPairDecay> tauDecay;
552 B2WARNING(
"Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
555 return tauDecay->getTauPlusEgstar();
558 double tauMinusEgstar(
const Particle*)
560 StoreObjPtr<TauPairDecay> tauDecay;
562 B2WARNING(
"Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
565 return tauDecay->getTauMinusEgstar();
568 double isReconstructible(
const Particle* p)
570 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
572 const MCParticle* mcp = p->getMCParticle();
577 return (abs(mcp->getCharge()) > 0) ? seenInSVD(p) : seenInECL(p);
580 double isTrackFound(
const Particle* p)
582 if (p->getParticleSource() != Particle::EParticleSourceObject::c_MCParticle)
584 const MCParticle* tmp_mcP = p->getMCParticle();
587 Track* tmp_track = tmp_mcP->getRelated<Track>();
589 const TrackFitResult* tmp_tfr = tmp_track->getTrackFitResultWithClosestMass(Const::ChargedStable(abs(tmp_mcP->getPDG())));
590 if (tmp_tfr->getChargeSign()*tmp_mcP->getCharge() > 0)
598 double seenInPXD(
const Particle* p)
600 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
602 const MCParticle* mcp = p->getMCParticle();
604 return mcp->hasSeenInDetector(Const::PXD);
607 double seenInSVD(
const Particle* p)
609 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
611 const MCParticle* mcp = p->getMCParticle();
613 return mcp->hasSeenInDetector(Const::SVD);
616 double seenInCDC(
const Particle* p)
618 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
620 const MCParticle* mcp = p->getMCParticle();
622 return mcp->hasSeenInDetector(Const::CDC);
625 double seenInTOP(
const Particle* p)
627 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
629 const MCParticle* mcp = p->getMCParticle();
631 return mcp->hasSeenInDetector(Const::TOP);
634 double seenInECL(
const Particle* p)
636 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
638 const MCParticle* mcp = p->getMCParticle();
640 return mcp->hasSeenInDetector(Const::ECL);
643 double seenInARICH(
const Particle* p)
645 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
647 const MCParticle* mcp = p->getMCParticle();
649 return mcp->hasSeenInDetector(Const::ARICH);
652 double seenInKLM(
const Particle* p)
654 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
656 const MCParticle* mcp = p->getMCParticle();
658 return mcp->hasSeenInDetector(Const::KLM);
661 int genNStepsToDaughter(
const Particle* p,
const std::vector<double>& arguments)
663 if (arguments.size() != 1)
664 B2FATAL(
"Wrong number of arguments for genNStepsToDaughter");
666 const MCParticle* mcp = p->getMCParticle();
668 B2WARNING(
"No MCParticle is associated to the particle");
672 int nChildren = p->getNDaughters();
673 if (arguments[0] >= nChildren) {
677 const Particle* daugP = p->getDaughter(arguments[0]);
682 B2WARNING(
"No MCParticle is associated to the i-th daughter");
686 if (nChildren == 1)
return 1;
688 std::vector<int> genMothers;
690 auto match = std::find(genMothers.begin(), genMothers.end(), mcp->getIndex());
691 return match - genMothers.begin();
694 int genNMissingDaughter(
const Particle* p,
const std::vector<double>& arguments)
696 if (arguments.size() < 1)
697 B2FATAL(
"Wrong number of arguments for genNMissingDaughter");
699 const std::vector<int> PDGcodes(arguments.begin(), arguments.end());
701 const MCParticle* mcp = p->getMCParticle();
703 B2WARNING(
"No MCParticle is associated to the particle");
710 double getHEREnergy(
const Particle*)
712 static DBObjPtr<BeamParameters> beamParamsDB;
713 return (beamParamsDB->getHER()).E();
716 double getLEREnergy(
const Particle*)
718 static DBObjPtr<BeamParameters> beamParamsDB;
719 return (beamParamsDB->getLER()).E();
722 double getCrossingAngleX(
const Particle*)
725 static DBObjPtr<BeamParameters> beamParamsDB;
726 B2Vector3D herVec = beamParamsDB->getHER().Vect();
727 B2Vector3D lerVec = beamParamsDB->getLER().Vect();
734 return herVec.Angle(-lerVec);
737 double getCrossingAngleY(
const Particle*)
740 static DBObjPtr<BeamParameters> beamParamsDB;
741 B2Vector3D herVec = beamParamsDB->getHER().Vect();
742 B2Vector3D lerVec = beamParamsDB->getLER().Vect();
749 return herVec.Angle(-lerVec);
753 double particleClusterMatchWeight(
const Particle* particle)
761 const MCParticle* matchedToParticle = particle->getMCParticle();
763 int matchedToIndex = matchedToParticle->getArrayIndex();
765 const ECLCluster* cluster = particle->getECLCluster();
768 const auto mcps = cluster->getRelationsTo<MCParticle>();
769 for (
unsigned int i = 0; i < mcps.size(); ++i)
770 if (mcps[i]->getArrayIndex() == matchedToIndex)
771 return mcps.weight(i);
776 double particleClusterBestMCMatchWeight(
const Particle* particle)
788 const ECLCluster* cluster = particle->getECLCluster();
794 auto mcps = cluster->getRelationsTo<MCParticle>();
797 std::vector<double> weights;
798 for (
unsigned int i = 0; i < mcps.size(); ++i)
799 weights.emplace_back(mcps.weight(i));
802 std::sort(weights.begin(), weights.end());
803 std::reverse(weights.begin(), weights.end());
807 double particleClusterBestMCPDGCode(
const Particle* particle)
817 const ECLCluster* cluster = particle->getECLCluster();
820 auto mcps = cluster->getRelationsTo<MCParticle>();
823 std::vector<std::pair<double, int>> weightsAndIndices;
824 for (
unsigned int i = 0; i < mcps.size(); ++i)
825 weightsAndIndices.emplace_back(mcps.weight(i), i);
828 std::sort(weightsAndIndices.begin(), weightsAndIndices.end(),
829 ValueIndexPairSorting::higherPair<decltype(weightsAndIndices)::value_type>);
831 return mcps.object(weightsAndIndices[0].second)->getPDG();
834 double particleClusterTotalMCMatchWeight(
const Particle* particle)
836 const ECLCluster* cluster = particle->getECLCluster();
839 auto mcps = cluster->getRelationsTo<MCParticle>();
842 double weightsum = 0;
843 for (
unsigned int i = 0; i < mcps.size(); ++i)
844 weightsum += mcps.weight(i);
849 double isBBCrossfeed(
const Particle* particle)
851 if (particle ==
nullptr)
854 int pdg = particle->getPDGCode();
855 if (abs(pdg) != 511 && abs(pdg) != 521 && abs(pdg) != 531)
858 std::vector<const Particle*> daughters = particle->getFinalStateDaughters();
859 int nDaughters = daughters.size();
862 std::vector<int> mother_ids;
864 for (
int j = 0; j < nDaughters; ++j) {
865 const MCParticle* curMCParticle = daughters[j]->
getMCParticle();
866 while (curMCParticle !=
nullptr) {
867 pdg = curMCParticle->getPDG();
868 if (abs(pdg) == 511 || abs(pdg) == 521 || abs(pdg) == 531) {
869 mother_ids.emplace_back(curMCParticle->getArrayIndex());
872 const MCParticle* curMCMother = curMCParticle->getMother();
873 curMCParticle = curMCMother;
875 if (curMCParticle ==
nullptr) {
880 std::set<int> distinctIDs = std::set(mother_ids.begin(), mother_ids.end());
881 if (distinctIDs.size() == 1)
887 VARIABLE_GROUP(
"MC matching and MC truth");
888 REGISTER_VARIABLE(
"isSignal", isSignal,
889 "1.0 if Particle is correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found. \n"
890 "It behaves according to DecayStringGrammar.");
891 REGISTER_VARIABLE(
"isSignalAcceptWrongFSPs", isSignalAcceptWrongFSPs,
892 "1.0 if Particle is almost correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found.\n"
893 "Misidentification of charged FSP is allowed.");
894 REGISTER_VARIABLE(
"isPrimarySignal", isPrimarySignal,
895 "1.0 if Particle is correctly reconstructed (SIGNAL) and primary, 0.0 if not, and NaN if no related MCParticle could be found");
896 REGISTER_VARIABLE(
"isSignalAcceptBremsPhotons", isSignalAcceptBremsPhotons,
897 "1.0 if Particle is correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found.\n"
898 "Particles with gamma daughters attached through the bremsstrahlung recovery modules are allowed.");
899 REGISTER_VARIABLE(
"genMotherPDG", genMotherPDG,
900 "Check the PDG code of a particles MC mother particle");
901 REGISTER_VARIABLE(
"genMotherPDG(i)", genNthMotherPDG,
902 "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:");
904 REGISTER_VARIABLE(
"genMotherID", genMotherIndex,
905 "Check the array index of a particles generated mother");
906 REGISTER_VARIABLE(
"genMotherID(i)", genNthMotherIndex,
907 "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:");
911 REGISTER_VARIABLE(
"isBBCrossfeed", isBBCrossfeed,
912 "Returns 1 for crossfeed in reconstruction of given B meson, 0 for no crossfeed and NaN for no true B meson or failed truthmatching.");
913 REGISTER_VARIABLE(
"genMotherP", genMotherP,
914 "Generated momentum of a particles MC mother particle\n\n",
"GeV/c");
915 REGISTER_VARIABLE(
"genParticleID", genParticleIndex,
916 "Check the array index of a particle's related MCParticle");
917 REGISTER_VARIABLE(
"isSignalAcceptMissingNeutrino",
918 isSignalAcceptMissingNeutrino,
919 "Same as isSignal, but also accept missing neutrino");
920 REGISTER_VARIABLE(
"isSignalAcceptMissingMassive",
921 isSignalAcceptMissingMassive,
922 "Same as isSignal, but also accept missing massive particle");
923 REGISTER_VARIABLE(
"isSignalAcceptMissingGamma",
924 isSignalAcceptMissingGamma,
925 "Same as isSignal, but also accept missing gamma, such as B -> K* gamma, pi0 -> gamma gamma");
926 REGISTER_VARIABLE(
"isSignalAcceptMissing",
927 isSignalAcceptMissing,
928 "Same as isSignal, but also accept missing particle");
929 REGISTER_VARIABLE(
"isMisidentified", isMisidentified,
930 "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.");
931 REGISTER_VARIABLE(
"isWrongCharge", isWrongCharge,
932 "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.");
933 REGISTER_VARIABLE(
"isCloneTrack", isCloneTrack,
934 "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)");
935 REGISTER_VARIABLE(
"isOrHasCloneTrack", isOrHasCloneTrack,
936 "Return 1 if the particle is a clone track or has a clone track as a daughter, 0 otherwise.");
937 REGISTER_VARIABLE(
"mcPDG", particleMCMatchPDGCode,
938 "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).");
939 REGISTER_VARIABLE(
"mcErrors", particleMCErrors,
940 "The bit pattern indicating the quality of MC match (see MCMatching::MCErrorFlags)");
941 REGISTER_VARIABLE(
"mcMatchWeight", particleMCMatchWeight,
942 "The weight of the Particle -> MCParticle relation (only for the first Relation = largest weight).");
943 REGISTER_VARIABLE(
"nMCMatches", particleNumberOfMCMatch,
944 "The number of relations of this Particle to MCParticle.");
945 REGISTER_VARIABLE(
"mcDecayTime", particleMCMatchDecayTime,
946 "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",
948 REGISTER_VARIABLE(
"mcLifeTime", particleMCMatchLifeTime,
949 "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",
951 REGISTER_VARIABLE(
"mcPX", particleMCMatchPX,
952 "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",
954 REGISTER_VARIABLE(
"mcPY", particleMCMatchPY,
955 "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",
957 REGISTER_VARIABLE(
"mcPZ", particleMCMatchPZ,
958 "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",
960 REGISTER_VARIABLE(
"mcPT", particleMCMatchPT,
961 "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",
963 REGISTER_VARIABLE(
"mcE", particleMCMatchE,
964 "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",
966 REGISTER_VARIABLE(
"mcP", particleMCMatchP,
967 "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",
969 REGISTER_VARIABLE(
"mcPhi", particleMCMatchPhi,
970 "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",
972 REGISTER_VARIABLE(
"mcTheta", particleMCMatchTheta,
973 "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",
975 REGISTER_VARIABLE(
"nMCDaughters", mcParticleNDaughters,
976 "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).");
977 REGISTER_VARIABLE(
"mcRecoilMass", particleMCRecoilMass,
978 "The mass recoiling against the particles attached as particle's daughters calculated using MC truth values.\n\n",
979 "GeV/:math:`\\text{c}^2`");
980 REGISTER_VARIABLE(
"mcCosThetaBetweenParticleAndNominalB",
981 particleMCCosThetaBetweenParticleAndNominalB,
982 "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.");
985 REGISTER_VARIABLE(
"mcSecPhysProc", mcParticleSecondaryPhysicsProcess,
987 Returns the secondary physics process flag, which is set by Geant4 on secondary particles. It indicates the type of process that produced the particle.
989 Returns NaN if the particle is not matched to a MCParticle.
991 Returns -1 in case of unknown process.
993 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, ...).
995 List of possible values (taken from the Geant4 source of
996 `G4DecayProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/decay/include/G4DecayProcessType.hh>`_,
997 `G4HadronicProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/hadronic/management/include/G4HadronicProcessType.hh>`_,
998 `G4TransportationProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/transportation/include/G4TransportationProcessType.hh>`_ and
999 `G4EmProcessSubType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/electromagnetic/utils/include/G4EmProcessSubType.hh>`_)
1001 * 1 Coulomb scattering
1004 * 4 Pair production by charged
1006 * 6 Annihilation to mu mu
1007 * 7 Annihilation to hadrons
1008 * 8 Nuclear stopping
1009 * 9 Electron general process
1010 * 10 Multiple scattering
1012 * 12 Photo-electric effect
1013 * 13 Compton scattering
1014 * 14 Gamma conversion
1015 * 15 Gamma conversion to mu mu
1016 * 16 Gamma general process
1019 * 23 Synchrotron radiation
1020 * 24 Transition radiation
1022 * 92 Coupled transportation
1023 * 111 Hadron elastic
1024 * 121 Hadron inelastic
1026 * 132 Mu atomic capture
1028 * 151 Hadron at rest
1029 * 152 Lepton at rest
1030 * 161 Charge exchange
1032 * 202 Decay with spin
1033 * 203 Decay (pion make spin)
1034 * 210 Radioactive decay
1037 * 231 External decay
1039 .. note:: This is what `modularAnalysis.printMCParticles` shows as ``creation process`` when ``showStatus`` is set to ``True``.
1041 REGISTER_VARIABLE("mcParticleStatus", mcParticleStatus,
1042 "Returns status bits of related MCParticle or NaN if MCParticle relation is not set.");
1043 REGISTER_VARIABLE(
"mcPrimary", particleMCPrimaryParticle,
1044 "Returns 1 if Particle is related to primary MCParticle, 0 if Particle is related to non - primary MCParticle, "
1045 "NaN if Particle is not related to MCParticle.");
1046 REGISTER_VARIABLE(
"mcVirtual", particleMCVirtualParticle,
1047 "Returns 1 if Particle is related to virtual MCParticle, 0 if Particle is related to non - virtual MCParticle, "
1048 "NaN if Particle is not related to MCParticle.")
1049 REGISTER_VARIABLE("mcInitial", particleMCInitialParticle,
1050 "Returns 1 if Particle is related to initial MCParticle, 0 if Particle is related to non - initial MCParticle, "
1051 "NaN if Particle is not related to MCParticle.")
1052 REGISTER_VARIABLE("mcISR", particleMCISRParticle,
1053 "Returns 1 if Particle is related to ISR MCParticle, 0 if Particle is related to non - ISR MCParticle, "
1054 "NaN if Particle is not related to MCParticle.")
1055 REGISTER_VARIABLE("mcFSR", particleMCFSRParticle,
1056 "Returns 1 if Particle is related to FSR MCParticle, 0 if Particle is related to non - FSR MCParticle ,"
1057 "NaN if Particle is not related to MCParticle.")
1058 REGISTER_VARIABLE("mcPhotos", particleMCPhotosParticle,
1059 "Returns 1 if Particle is related to Photos MCParticle, 0 if Particle is related to non - Photos MCParticle, "
1060 "NaN if Particle is not related to MCParticle.")
1061 REGISTER_VARIABLE("generatorEventWeight", generatorEventWeight,
1062 "[Eventbased] Returns the event weight produced by the event generator")
1064 REGISTER_VARIABLE("genNStepsToDaughter(i)", genNStepsToDaughter,
1065 "Returns number of steps to i-th daughter from the particle at generator level. "
1066 "NaN if no MCParticle is associated to the particle or i-th daughter. "
1067 "NaN if i-th daughter does not exist.");
1068 REGISTER_VARIABLE("genNMissingDaughter(PDG)", genNMissingDaughter,
1069 "Returns the number of missing daughters having assigned PDG codes. "
1070 "NaN if no MCParticle is associated to the particle.");
1071 REGISTER_VARIABLE("Eher", getHEREnergy,
R"DOC(
1072 [Eventbased] The nominal HER energy used by the generator.
1074 .. warning:: This variable does not make sense for data.
1077 REGISTER_VARIABLE("Eler", getLEREnergy,
R"DOC(
1078 [Eventbased] The nominal LER energy used by the generator.
1080 .. warning:: This variable does not make sense for data.
1083 REGISTER_VARIABLE("XAngle", getCrossingAngleX,
R"DOC(
1084 [Eventbased] The nominal beam crossing angle in the x-z plane from generator level beam kinematics.
1086 .. warning:: This variable does not make sense for data.
1089 REGISTER_VARIABLE("YAngle", getCrossingAngleY,
R"DOC(
1090 [Eventbased] The nominal beam crossing angle in the y-z plane from generator level beam kinematics.
1092 .. warning:: This variable does not make sense for data.
1096 VARIABLE_GROUP("Generated tau decay information");
1097 REGISTER_VARIABLE("tauPlusMCMode", tauPlusMcMode,
1098 "[Eventbased] Decay ID for the positive tau lepton in a tau pair generated event.");
1099 REGISTER_VARIABLE("tauMinusMCMode", tauMinusMcMode,
1100 "[Eventbased] Decay ID for the negative tau lepton in a tau pair generated event.");
1101 REGISTER_VARIABLE("tauPlusMCProng", tauPlusMcProng,
1102 "[Eventbased] Prong for the positive tau lepton in a tau pair generated event.");
1103 REGISTER_VARIABLE("tauMinusMCProng", tauMinusMcProng,
1104 "[Eventbased] Prong for the negative tau lepton in a tau pair generated event.");
1105 REGISTER_VARIABLE("tauPlusEgstar", tauPlusEgstar,
1106 "[Eventbased] Energy of radiated gamma from positive tau lepton in a tau pair generated event.");
1107 REGISTER_VARIABLE("tauMinusEgstar", tauMinusEgstar,
1108 "[Eventbased] Energy of radiated gamma from negative tau lepton in a tau pair generated event.");
1110 VARIABLE_GROUP("MC particle seen in subdetectors");
1111 REGISTER_VARIABLE("isReconstructible", isReconstructible,
1112 "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.");
1113 REGISTER_VARIABLE("seenInPXD", seenInPXD,
1114 "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.");
1115 REGISTER_VARIABLE("isTrackFound", isTrackFound,
1116 "works on charged stable particle list created from MCParticles, returns NaN if not ; returns 1.0 if there is a reconstructed track related to the charged stable MCParticle with the correct charge, return -1.0 if the reconstucted track has the wrong charge, return 0.0 when no reconstructed track is found.");
1117 REGISTER_VARIABLE("seenInSVD", seenInSVD,
1118 "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.");
1119 REGISTER_VARIABLE("seenInCDC", seenInCDC,
1120 "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.");
1121 REGISTER_VARIABLE("seenInTOP", seenInTOP,
1122 "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.");
1123 REGISTER_VARIABLE("seenInECL", seenInECL,
1124 "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.");
1125 REGISTER_VARIABLE("seenInARICH", seenInARICH,
1126 "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.");
1127 REGISTER_VARIABLE("seenInKLM", seenInKLM,
1128 "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.");
1130 VARIABLE_GROUP("MC Matching for ECLClusters");
1131 REGISTER_VARIABLE("clusterMCMatchWeight", particleClusterMatchWeight,
1132 "Returns the weight of the ECLCluster -> MCParticle relation for the MCParticle matched to the particle. "
1133 "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. "
1134 "Returns -1 if the cluster *was* matched to particles, but not the match of the particle provided.");
1135 REGISTER_VARIABLE("clusterBestMCMatchWeight", particleClusterBestMCMatchWeight,
1136 "Returns the weight of the ECLCluster -> MCParticle relation for the relation with the largest weight.");
1137 REGISTER_VARIABLE("clusterBestMCPDG", particleClusterBestMCPDGCode,
1138 "Returns the PDG code of the MCParticle for the ECLCluster -> MCParticle relation with the largest weight.");
1139 REGISTER_VARIABLE("clusterTotalMCMatchWeight", particleClusterTotalMCMatchWeight,
1140 "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
static const double doubleNaN
quiet_NaN
@ c_IsFSRPhoton
bit 7: Particle is from finial state radiation
@ c_Initial
bit 5: Particle is initial such as e+ or e- and not going to Geant4
@ c_IsPHOTOSPhoton
bit 8: Particle is an radiative photon from PHOTOS
@ c_PrimaryParticle
bit 0: Particle is primary particle.
@ c_IsVirtual
bit 4: Particle is virtual and not going to Geant4.
@ c_IsISRPhoton
bit 6: Particle is from initial state radiation
const MCParticle * getMCParticle() const
Returns the pointer to the MCParticle object that was used to create this Particle (ParticleType == c...
static const ReferenceFrame & GetCurrent()
Get current rest frame.
int getArrayIndex() const
Returns this object's array index (in StoreArray), or -1 if not found.
B2Vector3< double > B2Vector3D
typedef for common usage with double
double sqrt(double a)
sqrt for 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.