14 #include <analysis/modules/ParticleLoader/ParticleLoaderModule.h>
17 #include <framework/datastore/StoreArray.h>
18 #include <framework/datastore/StoreObjPtr.h>
21 #include <framework/logging/Logger.h>
22 #include <framework/core/ModuleParam.templateDetails.h>
25 #include <mdst/dataobjects/V0.h>
26 #include <mdst/dataobjects/ECLCluster.h>
27 #include <mdst/dataobjects/KLMCluster.h>
28 #include <mdst/dataobjects/MCParticle.h>
29 #include <mdst/dataobjects/Track.h>
30 #include <mdst/dataobjects/PIDLikelihood.h>
32 #include <analysis/dataobjects/Particle.h>
33 #include <analysis/dataobjects/ParticleList.h>
34 #include <analysis/dataobjects/ParticleExtraInfoMap.h>
35 #include <analysis/dataobjects/EventExtraInfo.h>
38 #include <analysis/DecayDescriptor/ParticleListName.h>
39 #include <analysis/utility/PCmsLabTransform.h>
64 setDescription(
"Loads MDST dataobjects as Particle objects to the StoreArray<Particle> and collects them in specified ParticleList.");
65 setPropertyFlags(c_ParallelProcessingCertified);
68 std::vector<std::tuple<std::string, std::string>> emptyDecayStringsAndCuts;
70 addParam(
"decayStringsWithCuts", m_decayStringsWithCuts,
71 "List of (decayString, Variable::Cut) tuples that specify all output ParticleLists to be created by the module. Only Particles that pass specified selection criteria are added to the ParticleList (see :ref:`DecayString` and `cut_strings_selections`).",
72 emptyDecayStringsAndCuts);
74 addParam(
"useMCParticles", m_useMCParticles,
75 "Use MCParticles instead of reconstructed MDST dataobjects (tracks, ECL, KLM, clusters, V0s, ...)",
false);
77 addParam(
"useROEs", m_useROEs,
78 "Use ROE instead of reconstructed MDST dataobjects (tracks, ECL, KLM, clusters, V0s, ...)",
false);
80 addParam(
"roeMaskName", m_roeMaskName,
81 "ROE mask name to load", std::string(
""));
83 addParam(
"sourceParticleListName", m_sourceParticleListName,
84 "Particle list name from which we need to get ROEs", std::string(
""));
86 addParam(
"useMissing", m_useMissing,
87 "If true, the Particle List will be filled with missing momentum from the ROE and signal particle.",
false);
89 addParam(
"writeOut", m_writeOut,
90 "If true, the output ParticleList will be saved by RootOutput. If false, it will be ignored when writing the file.",
false);
92 addParam(
"addDaughters", m_addDaughters,
93 "If true, the particles from the bottom part of the selected particle's decay chain will also be created in the datastore and mother-daughter relations are recursively set",
96 addParam(
"skipNonPrimaryDaughters", m_skipNonPrimaryDaughters,
97 "If true, the secondary MC daughters will be skipped, default is false",
100 addParam(
"trackHypothesis", m_trackHypothesis,
101 "Track hypothesis to use when loading the particle. By default, use the particle's own hypothesis.",
104 addParam(
"enforceFitHypothesis", m_enforceFitHypothesis,
105 "If true, a Particle is only created if a track fit with the particle hypothesis passed to the ParticleLoader is available.",
106 m_enforceFitHypothesis);
109 void ParticleLoaderModule::initialize()
111 B2INFO(
"ParticleLoader's Summary of Actions:");
120 particles.registerInDataStore();
121 extraInfoMap.registerInDataStore();
122 eventExtraInfo.registerInDataStore();
124 if (mcparticles.isOptional()) {
125 particles.registerRelationTo(mcparticles);
127 if (pidlikelihoods.isOptional()) {
128 particles.registerRelationTo(pidlikelihoods);
130 if (trackfitresults.isOptional()) {
131 particles.registerRelationTo(trackfitresults);
134 if (m_useMCParticles) {
135 mcparticles.isRequired();
138 if (m_decayStringsWithCuts.empty()) {
139 B2WARNING(
"Obsolete usage of the ParticleLoader module (load all MDST objects as all possible Particle object types). Specify the particle type via decayStringsWithCuts module parameter instead.");
141 for (
auto decayStringCutTuple : m_decayStringsWithCuts) {
144 string decayString = get<0>(decayStringCutTuple);
145 std::string cutParameter = get<1>(decayStringCutTuple);
148 bool valid = m_decaydescriptor.init(decayString);
150 B2ERROR(
"ParticleLoaderModule::initialize Invalid input DecayString: " << decayString);
155 int pdgCode = mother->getPDGCode();
156 string listName = mother->getFullName();
160 string listLabel = mother->getLabel();
161 if (listLabel ==
"all")
162 if (cutParameter !=
"")
163 B2FATAL(
"You have tried to create a list " << listName <<
" with cuts! This is *very* error prone, so it is now forbidden.");
165 if (not isValidPDGCode(pdgCode) and (m_useMCParticles ==
false and m_useROEs ==
false))
166 B2ERROR(
"Invalid particle type requested to be loaded. Set a valid decayString module parameter.");
169 bool mdstSourceIsV0 =
false;
170 if (!m_useMCParticles &&
171 (abs(pdgCode) == abs(Const::Kshort.getPDGCode()) || abs(pdgCode) == abs(Const::Lambda.getPDGCode())
172 || (abs(pdgCode) == abs(Const::photon.getPDGCode()) && m_addDaughters ==
true)))
173 mdstSourceIsV0 =
true;
175 int nProducts = m_decaydescriptor.getNDaughters();
176 if (mdstSourceIsV0 ==
false) {
179 B2ERROR(
"ParticleLoaderModule::initialize Invalid input DecayString " << decayString
180 <<
". DecayString should not contain any daughters, only the mother particle.");
182 B2INFO(
"ParticleLoaderModule: Replacing the source particle list name by " <<
183 m_decaydescriptor.getDaughter(0)->getMother()->getFullName()
184 <<
" all other daughters will be ignored.");
185 m_sourceParticleListName = m_decaydescriptor.getDaughter(0)->getMother()->getFullName();
190 B2ERROR(
"ParticleLoaderModule::initialize Invalid input DecayString " << decayString
191 <<
". MDST source of the particle list is V0, DecayString should contain exactly two daughters, as well as the mother particle.");
193 if (m_decaydescriptor.getDaughter(0)->getMother()->getPDGCode() * m_decaydescriptor.getDaughter(1)->getMother()->getPDGCode() > 0)
194 B2ERROR(
"MDST source of the particle list is V0, the two daughters should have opposite charge");
198 string antiListName = ParticleListName::antiParticleListName(listName);
199 bool isSelfConjugatedParticle = (listName == antiListName);
202 if (!particleList.isOptional()) {
206 particleList.registerInDataStore(flags);
207 if (!isSelfConjugatedParticle) {
209 antiParticleList.registerInDataStore(flags);
213 B2WARNING(
"The ParticleList with name " << listName <<
" already exists in the DataStore. Nothing to do.");
217 std::shared_ptr<Variable::Cut> cut = std::shared_ptr<Variable::Cut>(Variable::Cut::compile(cutParameter));
220 B2INFO(
" o) creating (anti-)ParticleList with name: " << listName <<
" (" << antiListName <<
")");
222 B2INFO(
" -> MDST source: RestOfEvents");
223 m_ROE2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle, cut);
224 }
else if (m_useMCParticles) {
225 B2INFO(
" -> MDST source: MCParticles");
226 m_MCParticles2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle, cut);
230 B2INFO(
" -> MDST source: Tracks");
231 m_Tracks2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle, cut);
234 if (abs(pdgCode) == abs(Const::photon.getPDGCode())) {
235 if (m_addDaughters ==
false) {
236 B2INFO(
" -> MDST source: ECLClusters");
237 m_ECLClusters2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle, cut);
239 B2INFO(
" -> MDST source: V0");
240 m_V02Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle, cut);
244 if (abs(pdgCode) == abs(Const::Kshort.getPDGCode())) {
245 B2INFO(
" -> MDST source: V0");
246 m_V02Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle, cut);
249 if (abs(pdgCode) == abs(Const::Klong.getPDGCode()) || abs(pdgCode) == abs(Const::neutron.getPDGCode())) {
250 B2INFO(
" -> MDST source: exclusively KLMClusters or exclusively ECLClusters (matching between those not used)");
251 m_KLMClusters2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle, cut);
252 m_ECLClusters2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle, cut);
255 if (abs(pdgCode) == abs(Const::Lambda.getPDGCode())) {
256 B2INFO(
" -> MDST source: V0");
257 m_V02Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle, cut);
260 B2INFO(
" -> With cuts : " << cutParameter);
265 m_chargeZeroTrackCounts = std::vector<int>(m_Tracks2Plists.size(), 0);
266 m_sameChargeDaughtersV0Counts = std::vector<int>(m_V02Plists.size(), 0);
269 void ParticleLoaderModule::event()
273 if (not particleExtraInfoMap) {
274 particleExtraInfoMap.create();
279 else if (m_useMCParticles)
280 mcParticlesToParticles();
283 eclClustersToParticles();
284 klmClustersToParticles();
289 void ParticleLoaderModule::terminate()
292 for (
size_t i = 0; i < m_Tracks2Plists.size(); i++)
293 if (m_chargeZeroTrackCounts[i] > 0) {
294 auto track2Plist = m_Tracks2Plists[i];
295 B2WARNING(
"There were " << m_chargeZeroTrackCounts[i]
296 <<
" tracks skipped because of zero charge for "
297 << get<c_PListName>(track2Plist));
300 for (
size_t i = 0; i < m_V02Plists.size(); i++)
301 if (m_sameChargeDaughtersV0Counts[i] > 0) {
302 auto v02Plist = m_V02Plists[i];
303 B2WARNING(
"There were " << m_sameChargeDaughtersV0Counts[i]
304 <<
" v0s skipped because of same charge daughters for "
305 << get<c_PListName>(v02Plist));
309 void ParticleLoaderModule::roeToParticles()
311 if (m_ROE2Plists.empty())
314 auto roe2Plist = m_ROE2Plists[0];
315 string listName = get<c_PListName>(roe2Plist);
316 string antiListName = get<c_AntiPListName>(roe2Plist);
317 int pdgCode = get<c_PListPDGCode>(roe2Plist);
318 bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(roe2Plist);
322 plist->initialize(pdgCode, listName);
324 if (!isSelfConjugatedParticle) {
327 antiPlist->initialize(-1 * pdgCode, antiListName);
328 antiPlist->bindAntiParticleList(*(plist));
330 if (m_sourceParticleListName !=
"") {
334 B2FATAL(
"ParticleList " << m_sourceParticleListName <<
" could not be found or is not valid!");
335 for (
unsigned int i = 0; i < pList->getListSize(); i++) {
338 B2ERROR(
"ParticleList " << m_sourceParticleListName <<
" has no associated ROEs!");
340 addROEToParticleList(roe, pdgCode);
348 addROEToParticleList(roes[i]);
353 void ParticleLoaderModule::addROEToParticleList(
RestOfEvent* roe,
int pdgCode,
bool isSelfConjugatedParticle)
359 newPart = roe->
convertToParticle(m_roeMaskName, pdgCode, isSelfConjugatedParticle);
367 TLorentzVector signal4Vector = signalSideParticle->get4Vector();
368 TLorentzVector roe4Vector = roe->
get4Vector(m_roeMaskName);
369 TLorentzVector missing4Vector;
370 missing4Vector.SetVect(boost4Vector.Vect() - (signal4Vector.Vect() + roe4Vector.Vect()));
371 missing4Vector.SetE(missing4Vector.Vect().Mag());
372 newPart = particles.appendNew(missing4Vector, pdgCode);
375 for (
auto roe2Plist : m_ROE2Plists) {
376 string listName = get<c_PListName>(roe2Plist);
377 auto& cut = get<c_CutPointer>(roe2Plist);
379 if (cut->check(newPart))
380 plist->addParticle(newPart);
386 void ParticleLoaderModule::v0sToParticles()
388 if (m_V02Plists.empty())
392 for (
auto v02Plist : m_V02Plists) {
393 string listName = get<c_PListName>(v02Plist);
394 string antiListName = get<c_AntiPListName>(v02Plist);
395 int pdgCode = get<c_PListPDGCode>(v02Plist);
396 bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(v02Plist);
400 plist->initialize(pdgCode, listName);
402 if (!isSelfConjugatedParticle) {
405 antiPlist->initialize(-1 * pdgCode, antiListName);
407 antiPlist->bindAntiParticleList(*(plist));
415 bool matchingDaughtersOrder =
true;
416 if (m_decaydescriptor.getDaughter(0)->getMother()->getPDGCode() < 0
417 && m_decaydescriptor.getDaughter(1)->getMother()->getPDGCode() > 0)
418 matchingDaughtersOrder =
false;
422 const V0* v0 = V0s[i];
426 for (
size_t ilist = 0; ilist < m_V02Plists.size(); ilist++) {
427 auto v02Plist = m_V02Plists[ilist];
428 int listPDGCode = get<c_PListPDGCode>(v02Plist);
430 if (abs(listPDGCode) != abs(v0Type.
getPDGCode()))
435 B2DEBUG(19,
"V0 with same charge daughters skipped!");
436 m_sameChargeDaughtersV0Counts[ilist]++;
444 if (v0Type.
getPDGCode() == Const::Kshort.getPDGCode()) {
445 pTypeP = Const::pion;
446 pTypeM = Const::pion;
447 }
else if (v0Type.
getPDGCode() == Const::Lambda.getPDGCode()) {
448 pTypeP = Const::proton;
449 pTypeM = Const::pion;
450 v0FlavorType = Particle::c_Flavored;
451 }
else if (v0Type.
getPDGCode() == Const::antiLambda.getPDGCode()) {
452 pTypeP = Const::pion;
453 pTypeM = Const::proton;
454 v0FlavorType = Particle::c_Flavored;
455 }
else if (v0Type.
getPDGCode() == Const::photon.getPDGCode()) {
456 pTypeP = Const::electron;
457 pTypeM = Const::electron;
459 B2WARNING(
"Unknown V0 hypothesis!");
465 bool correctOrder = matchingDaughtersOrder;
466 if (abs(v0Type.
getPDGCode()) == abs(m_decaydescriptor.getMother()->getPDGCode())
467 && v0Type.
getPDGCode() != m_decaydescriptor.getMother()->getPDGCode())
468 correctOrder = !correctOrder;
470 std::pair<Track*, Track*> v0Tracks = v0->
getTracks();
471 std::pair<TrackFitResult*, TrackFitResult*> v0TrackFitResults = v0->
getTrackFitResults();
473 Particle daugP((v0Tracks.first)->getArrayIndex(), v0TrackFitResults.first, pTypeP);
474 Particle daugM((v0Tracks.second)->getArrayIndex(), v0TrackFitResults.second, pTypeM);
476 const PIDLikelihood* pidP = (v0Tracks.first)->getRelated<PIDLikelihood>();
477 const PIDLikelihood* pidM = (v0Tracks.second)->getRelated<PIDLikelihood>();
479 const auto& mcParticlePWithWeight = (v0Tracks.first)->getRelatedToWithWeight<MCParticle>();
480 const auto& mcParticleMWithWeight = (v0Tracks.second)->getRelatedToWithWeight<MCParticle>();
487 newDaugP = particles.appendNew(daugP);
488 newDaugM = particles.appendNew(daugM);
490 newDaugM = particles.appendNew(daugM);
491 newDaugP = particles.appendNew(daugP);
497 if (mcParticlePWithWeight.first)
498 newDaugP->
addRelationTo(mcParticlePWithWeight.first, mcParticlePWithWeight.second);
503 if (mcParticleMWithWeight.first)
504 newDaugM->
addRelationTo(mcParticleMWithWeight.first, mcParticleMWithWeight.second);
524 Particle* newPart = particles.appendNew(v0P);
525 string listName = get<c_PListName>(v02Plist);
526 auto& cut = get<c_CutPointer>(v02Plist);
529 if (cut->check(newPart))
530 plist->addParticle(newPart);
535 void ParticleLoaderModule::tracksToParticles()
537 if (m_Tracks2Plists.empty())
541 for (
auto track2Plist : m_Tracks2Plists) {
542 string listName = get<c_PListName>(track2Plist);
543 string antiListName = get<c_AntiPListName>(track2Plist);
544 int pdgCode = get<c_PListPDGCode>(track2Plist);
545 bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(track2Plist);
549 plist->initialize(pdgCode, listName);
552 if (!isSelfConjugatedParticle) {
555 antiPlist->initialize(-1 * pdgCode, antiListName);
557 antiPlist->bindAntiParticleList(*(plist));
567 for (
int i = 0; i < Tracks.
getEntries(); i++) {
568 const Track* track = Tracks[i];
570 const auto& mcParticleWithWeight = track->getRelatedToWithWeight<
MCParticle>();
573 for (
size_t ilist = 0; ilist < m_Tracks2Plists.size(); ilist++) {
574 auto track2Plist = m_Tracks2Plists[ilist];
575 string listName = get<c_PListName>(track2Plist);
576 auto& cut = get<c_CutPointer>(track2Plist);
581 if (m_trackHypothesis == 0)
582 pdgCode = get<c_PListPDGCode>(track2Plist);
583 else pdgCode = m_trackHypothesis;
588 const TrackFitResult* trackFit = track->getTrackFitResultWithClosestMass(type);
591 B2WARNING(
"Track returned null TrackFitResult pointer for ChargedStable::getPDGCode() = " << type.getPDGCode());
604 B2DEBUG(19,
"Track with charge = 0 skipped!");
605 m_chargeZeroTrackCounts[ilist]++;
610 Particle particle(track->getArrayIndex(), trackFit, type);
612 if (particle.getParticleSource() == Particle::c_Track) {
614 Particle* newPart = particles.appendNew(particle);
617 if (mcParticleWithWeight.first)
618 newPart->
addRelationTo(mcParticleWithWeight.first, mcParticleWithWeight.second);
621 if (cut->check(newPart))
622 plist->addParticle(newPart);
629 void ParticleLoaderModule::eclClustersToParticles()
631 if (m_ECLClusters2Plists.empty())
635 for (
auto eclCluster2Plist : m_ECLClusters2Plists) {
636 string listName = get<c_PListName>(eclCluster2Plist);
637 string antiListName = get<c_AntiPListName>(eclCluster2Plist);
638 int pdgCode = get<c_PListPDGCode>(eclCluster2Plist);
639 bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(eclCluster2Plist);
644 plist->initialize(pdgCode, listName);
647 if (!isSelfConjugatedParticle) {
650 antiPlist->initialize(-1 * pdgCode, antiListName);
652 antiPlist->bindAntiParticleList(*(plist));
664 for (
int i = 0; i < ECLClusters.
getEntries(); i++) {
670 if (!cluster->isNeutral())
continue;
671 if (not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons)
672 and not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron))
680 std::vector<std::pair<int, double>> weightsAndIndices;
681 for (
unsigned int iMCParticle = 0; iMCParticle < mcRelations.
size(); iMCParticle++) {
682 const MCParticle* relMCParticle = mcRelations[iMCParticle];
683 double weight = mcRelations.
weight(iMCParticle);
685 weightsAndIndices.emplace_back(relMCParticle->
getArrayIndex(), weight);
688 std::sort(weightsAndIndices.begin(), weightsAndIndices.end(),
689 [](
const std::pair<int, double>& left,
const std::pair<int, double>& right) {
690 return left.second > right.second;
695 for (
auto eclCluster2Plist : m_ECLClusters2Plists) {
696 string listName = get<c_PListName>(eclCluster2Plist);
697 int listPdgCode = get<c_PListPDGCode>(eclCluster2Plist);
702 if (listPdgCode == Const::photon.getPDGCode()
703 and not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons))
708 if (listPdgCode == Const::Klong.getPDGCode()
709 and not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron))
714 if (abs(listPdgCode) == Const::neutron.getPDGCode()
715 and not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron))
719 Particle particle(cluster, thisType);
720 if (particle.getParticleSource() != Particle::c_ECLCluster) {
721 B2FATAL(
"Particle created from ECLCluster does not have ECLCluster type.");
724 Particle* newPart = particles.appendNew(particle);
727 for (
auto& weightsAndIndex : weightsAndIndices) {
728 const MCParticle* relMCParticle = mcParticles[weightsAndIndex.first];
729 double weight = weightsAndIndex.second;
736 && weight / relMCParticle->
getEnergy() > 0.30)
742 auto& cut = get<c_CutPointer>(eclCluster2Plist);
744 if (cut->check(newPart))
745 plist->addParticle(newPart);
751 void ParticleLoaderModule::klmClustersToParticles()
753 if (m_KLMClusters2Plists.empty())
757 for (
auto klmCluster2Plist : m_KLMClusters2Plists) {
758 string listName = get<c_PListName>(klmCluster2Plist);
759 string antiListName = get<c_AntiPListName>(klmCluster2Plist);
760 int pdgCode = get<c_PListPDGCode>(klmCluster2Plist);
761 bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(klmCluster2Plist);
766 plist->initialize(pdgCode, listName);
768 if (!isSelfConjugatedParticle) {
771 antiPlist->initialize(-1 * pdgCode, antiListName);
773 antiPlist->bindAntiParticleList(*(plist));
782 for (
int i = 0; i < KLMClusters.
getEntries(); i++) {
785 if (std::isnan(cluster->getMomentumMag())) {
786 B2WARNING(
"Skipping KLMCluster because of nan momentum.");
792 for (
auto klmCluster2Plist : m_KLMClusters2Plists) {
793 string listName = get<c_PListName>(klmCluster2Plist);
794 int pdgCode = get<c_PListPDGCode>(klmCluster2Plist);
797 Particle particle(cluster, pdgCode);
798 if (particle.getParticleSource() != Particle::c_KLMCluster) {
799 B2FATAL(
"Particle created from KLMCluster does not have KLMCluster type.");
801 Particle* newPart = particles.appendNew(particle);
807 auto& cut = get<c_CutPointer>(klmCluster2Plist);
810 if (cut->check(newPart))
811 plist->addParticle(newPart);
816 void ParticleLoaderModule::mcParticlesToParticles()
818 if (m_MCParticles2Plists.empty())
822 for (
auto mcParticle2Plist : m_MCParticles2Plists) {
823 string listName = get<c_PListName>(mcParticle2Plist);
824 string antiListName = get<c_AntiPListName>(mcParticle2Plist);
825 int pdgCode = get<c_PListPDGCode>(mcParticle2Plist);
826 bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(mcParticle2Plist);
830 plist->initialize(pdgCode, listName);
832 if (!isSelfConjugatedParticle) {
835 antiPlist->initialize(-1 * pdgCode, antiListName);
837 antiPlist->bindAntiParticleList(*(plist));
844 for (
int i = 0; i < MCParticles.
getEntries(); i++) {
845 const MCParticle* mcParticle = MCParticles[i];
847 for (
auto mcParticle2Plist : m_MCParticles2Plists) {
848 int pdgCode = get<c_PListPDGCode>(mcParticle2Plist);
850 if (abs(pdgCode) != abs(mcParticle->
getPDG()))
854 Particle* newPart = particles.appendNew(particle);
858 if (m_addDaughters) appendDaughtersRecursive(newPart);
860 string listName = get<c_PListName>(mcParticle2Plist);
861 auto& cut = get<c_CutPointer>(mcParticle2Plist);
864 if (cut->check(newPart))
865 plist->addParticle(newPart);
870 bool ParticleLoaderModule::isValidPDGCode(
const int pdgCode)
875 if (Const::chargedStableSet.find(abs(pdgCode)) != Const::invalidParticle)
878 if (abs(pdgCode) == abs(Const::photon.getPDGCode()))
881 if (abs(pdgCode) == abs(Const::Kshort.getPDGCode()))
884 if (abs(pdgCode) == abs(Const::Klong.getPDGCode()))
887 if (abs(pdgCode) == abs(Const::Lambda.getPDGCode()))
890 if (abs(pdgCode) == abs(Const::neutron.getPDGCode()))
896 void ParticleLoaderModule::appendDaughtersRecursive(
Particle* mother)
899 auto* mcmother = mother->getRelated<
MCParticle>();
904 vector<MCParticle*> mcdaughters = mcmother->
getDaughters();
906 for (
auto& mcdaughter : mcdaughters) {
907 if (!mcdaughter->hasStatus(MCParticle::c_PrimaryParticle) and m_skipNonPrimaryDaughters)
continue;
909 Particle* daughter = particles.appendNew(particle);
910 daughter->addRelationTo(mcdaughter);
911 mother->appendDaughter(daughter,
false);
913 if (mcdaughter->getNDaughters() > 0)
914 appendDaughtersRecursive(daughter);