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 isReconstructible(
const Particle* p)
550 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
552 const MCParticle* mcp = p->getMCParticle();
557 return (abs(mcp->getCharge()) > 0) ? seenInSVD(p) : seenInECL(p);
560 double isTrackFound(
const Particle* p)
562 if (p->getParticleSource() != Particle::EParticleSourceObject::c_MCParticle)
564 const MCParticle* tmp_mcP = p->getMCParticle();
567 Track* tmp_track = tmp_mcP->getRelated<Track>();
569 const TrackFitResult* tmp_tfr = tmp_track->getTrackFitResultWithClosestMass(Const::ChargedStable(abs(tmp_mcP->getPDG())));
570 if (tmp_tfr->getChargeSign()*tmp_mcP->getCharge() > 0)
578 double seenInPXD(
const Particle* p)
580 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
582 const MCParticle* mcp = p->getMCParticle();
584 return mcp->hasSeenInDetector(Const::PXD);
587 double seenInSVD(
const Particle* p)
589 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
591 const MCParticle* mcp = p->getMCParticle();
593 return mcp->hasSeenInDetector(Const::SVD);
596 double seenInCDC(
const Particle* p)
598 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
600 const MCParticle* mcp = p->getMCParticle();
602 return mcp->hasSeenInDetector(Const::CDC);
605 double seenInTOP(
const Particle* p)
607 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
609 const MCParticle* mcp = p->getMCParticle();
611 return mcp->hasSeenInDetector(Const::TOP);
614 double seenInECL(
const Particle* p)
616 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
618 const MCParticle* mcp = p->getMCParticle();
620 return mcp->hasSeenInDetector(Const::ECL);
623 double seenInARICH(
const Particle* p)
625 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
627 const MCParticle* mcp = p->getMCParticle();
629 return mcp->hasSeenInDetector(Const::ARICH);
632 double seenInKLM(
const Particle* p)
634 if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
636 const MCParticle* mcp = p->getMCParticle();
638 return mcp->hasSeenInDetector(Const::KLM);
641 int genNStepsToDaughter(
const Particle* p,
const std::vector<double>& arguments)
643 if (arguments.size() != 1)
644 B2FATAL(
"Wrong number of arguments for genNStepsToDaughter");
646 const MCParticle* mcp = p->getMCParticle();
648 B2WARNING(
"No MCParticle is associated to the particle");
652 int nChildren = p->getNDaughters();
653 if (arguments[0] >= nChildren) {
657 const Particle* daugP = p->getDaughter(arguments[0]);
662 B2WARNING(
"No MCParticle is associated to the i-th daughter");
666 if (nChildren == 1)
return 1;
668 std::vector<int> genMothers;
670 auto match = std::find(genMothers.begin(), genMothers.end(), mcp->getIndex());
671 return match - genMothers.begin();
674 int genNMissingDaughter(
const Particle* p,
const std::vector<double>& arguments)
676 if (arguments.size() < 1)
677 B2FATAL(
"Wrong number of arguments for genNMissingDaughter");
679 const std::vector<int> PDGcodes(arguments.begin(), arguments.end());
681 const MCParticle* mcp = p->getMCParticle();
683 B2WARNING(
"No MCParticle is associated to the particle");
690 double getHEREnergy(
const Particle*)
692 static DBObjPtr<BeamParameters> beamParamsDB;
693 return (beamParamsDB->getHER()).E();
696 double getLEREnergy(
const Particle*)
698 static DBObjPtr<BeamParameters> beamParamsDB;
699 return (beamParamsDB->getLER()).E();
702 double getCrossingAngleX(
const Particle*)
705 static DBObjPtr<BeamParameters> beamParamsDB;
706 B2Vector3D herVec = beamParamsDB->getHER().Vect();
707 B2Vector3D lerVec = beamParamsDB->getLER().Vect();
714 return herVec.Angle(-lerVec);
717 double getCrossingAngleY(
const Particle*)
720 static DBObjPtr<BeamParameters> beamParamsDB;
721 B2Vector3D herVec = beamParamsDB->getHER().Vect();
722 B2Vector3D lerVec = beamParamsDB->getLER().Vect();
729 return herVec.Angle(-lerVec);
733 double particleClusterMatchWeight(
const Particle* particle)
741 const MCParticle* matchedToParticle = particle->getMCParticle();
743 int matchedToIndex = matchedToParticle->getArrayIndex();
745 const ECLCluster* cluster = particle->getECLCluster();
748 const auto mcps = cluster->getRelationsTo<MCParticle>();
749 for (
unsigned int i = 0; i < mcps.size(); ++i)
750 if (mcps[i]->getArrayIndex() == matchedToIndex)
751 return mcps.weight(i);
756 double particleClusterBestMCMatchWeight(
const Particle* particle)
768 const ECLCluster* cluster = particle->getECLCluster();
774 auto mcps = cluster->getRelationsTo<MCParticle>();
777 std::vector<double> weights;
778 for (
unsigned int i = 0; i < mcps.size(); ++i)
779 weights.emplace_back(mcps.weight(i));
782 std::sort(weights.begin(), weights.end());
783 std::reverse(weights.begin(), weights.end());
787 double particleClusterBestMCPDGCode(
const Particle* particle)
797 const ECLCluster* cluster = particle->getECLCluster();
800 auto mcps = cluster->getRelationsTo<MCParticle>();
803 std::vector<std::pair<double, int>> weightsAndIndices;
804 for (
unsigned int i = 0; i < mcps.size(); ++i)
805 weightsAndIndices.emplace_back(mcps.weight(i), i);
808 std::sort(weightsAndIndices.begin(), weightsAndIndices.end(),
809 ValueIndexPairSorting::higherPair<decltype(weightsAndIndices)::value_type>);
811 return mcps.object(weightsAndIndices[0].second)->getPDG();
814 double particleClusterTotalMCMatchWeight(
const Particle* particle)
816 const ECLCluster* cluster = particle->getECLCluster();
819 auto mcps = cluster->getRelationsTo<MCParticle>();
822 double weightsum = 0;
823 for (
unsigned int i = 0; i < mcps.size(); ++i)
824 weightsum += mcps.weight(i);
829 double isBBCrossfeed(
const Particle* particle)
831 if (particle ==
nullptr)
834 int pdg = particle->getPDGCode();
835 if (abs(pdg) != 511 && abs(pdg) != 521 && abs(pdg) != 531)
838 std::vector<const Particle*> daughters = particle->getFinalStateDaughters();
839 int nDaughters = daughters.size();
842 std::vector<int> mother_ids;
844 for (
int j = 0; j < nDaughters; ++j) {
845 const MCParticle* curMCParticle = daughters[j]->
getMCParticle();
846 while (curMCParticle !=
nullptr) {
847 pdg = curMCParticle->getPDG();
848 if (abs(pdg) == 511 || abs(pdg) == 521 || abs(pdg) == 531) {
849 mother_ids.emplace_back(curMCParticle->getArrayIndex());
852 const MCParticle* curMCMother = curMCParticle->getMother();
853 curMCParticle = curMCMother;
855 if (curMCParticle ==
nullptr) {
860 std::set<int> distinctIDs = std::set(mother_ids.begin(), mother_ids.end());
861 if (distinctIDs.size() == 1)
867 VARIABLE_GROUP(
"MC matching and MC truth");
868 REGISTER_VARIABLE(
"isSignal", isSignal,
869 "1.0 if Particle is correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found. \n"
870 "It behaves according to DecayStringGrammar.");
871 REGISTER_VARIABLE(
"isSignalAcceptWrongFSPs", isSignalAcceptWrongFSPs,
872 "1.0 if Particle is almost correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found.\n"
873 "Misidentification of charged FSP is allowed.");
874 REGISTER_VARIABLE(
"isPrimarySignal", isPrimarySignal,
875 "1.0 if Particle is correctly reconstructed (SIGNAL) and primary, 0.0 if not, and NaN if no related MCParticle could be found");
876 REGISTER_VARIABLE(
"isSignalAcceptBremsPhotons", isSignalAcceptBremsPhotons,
877 "1.0 if Particle is correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found.\n"
878 "Particles with gamma daughters attached through the bremsstrahlung recovery modules are allowed.");
879 REGISTER_VARIABLE(
"genMotherPDG", genMotherPDG,
880 "Check the PDG code of a particles MC mother particle");
881 REGISTER_VARIABLE(
"genMotherPDG(i)", genNthMotherPDG,
882 "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:");
884 REGISTER_VARIABLE(
"genMotherID", genMotherIndex,
885 "Check the array index of a particles generated mother");
886 REGISTER_VARIABLE(
"genMotherID(i)", genNthMotherIndex,
887 "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:");
891 REGISTER_VARIABLE(
"isBBCrossfeed", isBBCrossfeed,
892 "Returns 1 for crossfeed in reconstruction of given B meson, 0 for no crossfeed and NaN for no true B meson or failed truthmatching.");
893 REGISTER_VARIABLE(
"genMotherP", genMotherP,
894 "Generated momentum of a particles MC mother particle\n\n",
"GeV/c");
895 REGISTER_VARIABLE(
"genParticleID", genParticleIndex,
896 "Check the array index of a particle's related MCParticle");
897 REGISTER_VARIABLE(
"isSignalAcceptMissingNeutrino",
898 isSignalAcceptMissingNeutrino,
899 "Same as isSignal, but also accept missing neutrino");
900 REGISTER_VARIABLE(
"isSignalAcceptMissingMassive",
901 isSignalAcceptMissingMassive,
902 "Same as isSignal, but also accept missing massive particle");
903 REGISTER_VARIABLE(
"isSignalAcceptMissingGamma",
904 isSignalAcceptMissingGamma,
905 "Same as isSignal, but also accept missing gamma, such as B -> K* gamma, pi0 -> gamma gamma");
906 REGISTER_VARIABLE(
"isSignalAcceptMissing",
907 isSignalAcceptMissing,
908 "Same as isSignal, but also accept missing particle");
909 REGISTER_VARIABLE(
"isMisidentified", isMisidentified,
910 "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.");
911 REGISTER_VARIABLE(
"isWrongCharge", isWrongCharge,
912 "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.");
913 REGISTER_VARIABLE(
"isCloneTrack", isCloneTrack,
914 "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)");
915 REGISTER_VARIABLE(
"isOrHasCloneTrack", isOrHasCloneTrack,
916 "Return 1 if the particle is a clone track or has a clone track as a daughter, 0 otherwise.");
917 REGISTER_VARIABLE(
"mcPDG", particleMCMatchPDGCode,
918 "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).");
919 REGISTER_VARIABLE(
"mcErrors", particleMCErrors,
920 "The bit pattern indicating the quality of MC match (see MCMatching::MCErrorFlags)");
921 REGISTER_VARIABLE(
"mcMatchWeight", particleMCMatchWeight,
922 "The weight of the Particle -> MCParticle relation (only for the first Relation = largest weight).");
923 REGISTER_VARIABLE(
"nMCMatches", particleNumberOfMCMatch,
924 "The number of relations of this Particle to MCParticle.");
925 REGISTER_VARIABLE(
"mcDecayTime", particleMCMatchDecayTime,
926 "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",
928 REGISTER_VARIABLE(
"mcLifeTime", particleMCMatchLifeTime,
929 "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",
931 REGISTER_VARIABLE(
"mcPX", particleMCMatchPX,
932 "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",
934 REGISTER_VARIABLE(
"mcPY", particleMCMatchPY,
935 "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",
937 REGISTER_VARIABLE(
"mcPZ", particleMCMatchPZ,
938 "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",
940 REGISTER_VARIABLE(
"mcPT", particleMCMatchPT,
941 "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",
943 REGISTER_VARIABLE(
"mcE", particleMCMatchE,
944 "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",
946 REGISTER_VARIABLE(
"mcP", particleMCMatchP,
947 "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",
949 REGISTER_VARIABLE(
"mcPhi", particleMCMatchPhi,
950 "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",
952 REGISTER_VARIABLE(
"mcTheta", particleMCMatchTheta,
953 "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",
955 REGISTER_VARIABLE(
"nMCDaughters", mcParticleNDaughters,
956 "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).");
957 REGISTER_VARIABLE(
"mcRecoilMass", particleMCRecoilMass,
958 "The mass recoiling against the particles attached as particle's daughters calculated using MC truth values.\n\n",
959 "GeV/:math:`\\text{c}^2`");
960 REGISTER_VARIABLE(
"mcCosThetaBetweenParticleAndNominalB",
961 particleMCCosThetaBetweenParticleAndNominalB,
962 "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.");
965 REGISTER_VARIABLE(
"mcSecPhysProc", mcParticleSecondaryPhysicsProcess,
967 Returns the secondary physics process flag, which is set by Geant4 on secondary particles. It indicates the type of process that produced the particle.
969 Returns NaN if the particle is not matched to a MCParticle.
971 Returns -1 in case of unknown process.
973 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, ...).
975 List of possible values (taken from the Geant4 source of
976 `G4DecayProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/decay/include/G4DecayProcessType.hh>`_,
977 `G4HadronicProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/hadronic/management/include/G4HadronicProcessType.hh>`_,
978 `G4TransportationProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/transportation/include/G4TransportationProcessType.hh>`_ and
979 `G4EmProcessSubType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/electromagnetic/utils/include/G4EmProcessSubType.hh>`_)
981 * 1 Coulomb scattering
984 * 4 Pair production by charged
986 * 6 Annihilation to mu mu
987 * 7 Annihilation to hadrons
989 * 9 Electron general process
990 * 10 Multiple scattering
992 * 12 Photo-electric effect
993 * 13 Compton scattering
994 * 14 Gamma conversion
995 * 15 Gamma conversion to mu mu
996 * 16 Gamma general process
999 * 23 Synchrotron radiation
1000 * 24 Transition radiation
1002 * 92 Coupled transportation
1003 * 111 Hadron elastic
1004 * 121 Hadron inelastic
1006 * 132 Mu atomic capture
1008 * 151 Hadron at rest
1009 * 152 Lepton at rest
1010 * 161 Charge exchange
1012 * 202 Decay with spin
1013 * 203 Decay (pion make spin)
1014 * 210 Radioactive decay
1017 * 231 External decay
1019 .. note:: This is what `modularAnalysis.printMCParticles` shows as ``creation process`` when ``showStatus`` is set to ``True``.
1021 REGISTER_VARIABLE("mcParticleStatus", mcParticleStatus,
1022 "Returns status bits of related MCParticle or NaN if MCParticle relation is not set.");
1023 REGISTER_VARIABLE(
"mcPrimary", particleMCPrimaryParticle,
1024 "Returns 1 if Particle is related to primary MCParticle, 0 if Particle is related to non - primary MCParticle, "
1025 "NaN if Particle is not related to MCParticle.");
1026 REGISTER_VARIABLE(
"mcVirtual", particleMCVirtualParticle,
1027 "Returns 1 if Particle is related to virtual MCParticle, 0 if Particle is related to non - virtual MCParticle, "
1028 "NaN if Particle is not related to MCParticle.")
1029 REGISTER_VARIABLE("mcInitial", particleMCInitialParticle,
1030 "Returns 1 if Particle is related to initial MCParticle, 0 if Particle is related to non - initial MCParticle, "
1031 "NaN if Particle is not related to MCParticle.")
1032 REGISTER_VARIABLE("mcISR", particleMCISRParticle,
1033 "Returns 1 if Particle is related to ISR MCParticle, 0 if Particle is related to non - ISR MCParticle, "
1034 "NaN if Particle is not related to MCParticle.")
1035 REGISTER_VARIABLE("mcFSR", particleMCFSRParticle,
1036 "Returns 1 if Particle is related to FSR MCParticle, 0 if Particle is related to non - FSR MCParticle ,"
1037 "NaN if Particle is not related to MCParticle.")
1038 REGISTER_VARIABLE("mcPhotos", particleMCPhotosParticle,
1039 "Returns 1 if Particle is related to Photos MCParticle, 0 if Particle is related to non - Photos MCParticle, "
1040 "NaN if Particle is not related to MCParticle.")
1041 REGISTER_VARIABLE("generatorEventWeight", generatorEventWeight,
1042 "[Eventbased] Returns the event weight produced by the event generator")
1044 REGISTER_VARIABLE("genNStepsToDaughter(i)", genNStepsToDaughter,
1045 "Returns number of steps to i-th daughter from the particle at generator level. "
1046 "NaN if no MCParticle is associated to the particle or i-th daughter. "
1047 "NaN if i-th daughter does not exist.");
1048 REGISTER_VARIABLE("genNMissingDaughter(PDG)", genNMissingDaughter,
1049 "Returns the number of missing daughters having assigned PDG codes. "
1050 "NaN if no MCParticle is associated to the particle.");
1051 REGISTER_VARIABLE("Eher", getHEREnergy,
R"DOC(
1052 [Eventbased] The nominal HER energy used by the generator.
1054 .. warning:: This variable does not make sense for data.
1057 REGISTER_VARIABLE("Eler", getLEREnergy,
R"DOC(
1058 [Eventbased] The nominal LER energy used by the generator.
1060 .. warning:: This variable does not make sense for data.
1063 REGISTER_VARIABLE("XAngle", getCrossingAngleX,
R"DOC(
1064 [Eventbased] The nominal beam crossing angle in the x-z plane from generator level beam kinematics.
1066 .. warning:: This variable does not make sense for data.
1069 REGISTER_VARIABLE("YAngle", getCrossingAngleY,
R"DOC(
1070 [Eventbased] The nominal beam crossing angle in the y-z plane from generator level beam kinematics.
1072 .. warning:: This variable does not make sense for data.
1076 VARIABLE_GROUP("Generated tau decay information");
1077 REGISTER_VARIABLE("tauPlusMCMode", tauPlusMcMode,
1078 "[Eventbased] Decay ID for the positive tau lepton in a tau pair generated event.");
1079 REGISTER_VARIABLE("tauMinusMCMode", tauMinusMcMode,
1080 "[Eventbased] Decay ID for the negative tau lepton in a tau pair generated event.");
1081 REGISTER_VARIABLE("tauPlusMCProng", tauPlusMcProng,
1082 "[Eventbased] Prong for the positive tau lepton in a tau pair generated event.");
1083 REGISTER_VARIABLE("tauMinusMCProng", tauMinusMcProng,
1084 "[Eventbased] Prong for the negative tau lepton in a tau pair generated event.");
1086 VARIABLE_GROUP("MC particle seen in subdetectors");
1087 REGISTER_VARIABLE("isReconstructible", isReconstructible,
1088 "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.");
1089 REGISTER_VARIABLE("seenInPXD", seenInPXD,
1090 "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.");
1091 REGISTER_VARIABLE("isTrackFound", isTrackFound,
1092 "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.");
1093 REGISTER_VARIABLE("seenInSVD", seenInSVD,
1094 "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.");
1095 REGISTER_VARIABLE("seenInCDC", seenInCDC,
1096 "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.");
1097 REGISTER_VARIABLE("seenInTOP", seenInTOP,
1098 "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.");
1099 REGISTER_VARIABLE("seenInECL", seenInECL,
1100 "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.");
1101 REGISTER_VARIABLE("seenInARICH", seenInARICH,
1102 "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.");
1103 REGISTER_VARIABLE("seenInKLM", seenInKLM,
1104 "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.");
1106 VARIABLE_GROUP("MC Matching for ECLClusters");
1107 REGISTER_VARIABLE("clusterMCMatchWeight", particleClusterMatchWeight,
1108 "Returns the weight of the ECLCluster -> MCParticle relation for the MCParticle matched to the particle. "
1109 "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. "
1110 "Returns -1 if the cluster *was* matched to particles, but not the match of the particle provided.");
1111 REGISTER_VARIABLE("clusterBestMCMatchWeight", particleClusterBestMCMatchWeight,
1112 "Returns the weight of the ECLCluster -> MCParticle relation for the relation with the largest weight.");
1113 REGISTER_VARIABLE("clusterBestMCPDG", particleClusterBestMCPDGCode,
1114 "Returns the PDG code of the MCParticle for the ECLCluster -> MCParticle relation with the largest weight.");
1115 REGISTER_VARIABLE("clusterTotalMCMatchWeight", particleClusterTotalMCMatchWeight,
1116 "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.