9 #include "Helpers/MCParticleHelper.h" 11 #include "Objects/CaloHit.h" 12 #include "Objects/Cluster.h" 13 #include "Objects/MCParticle.h" 15 #include "Pandora/PdgTable.h" 16 #include "Pandora/StatusCodes.h" 32 m_minPrimaryGoodHits(15),
33 m_minHitsForGoodView(5),
34 m_minPrimaryGoodViews(2),
35 m_selectInputHits(true),
36 m_maxPhotonPropagation(2.5
f),
37 m_minHitSharingFraction(0.9
f)
70 const LArMCParticle *
const pLArMCParticle(dynamic_cast<const LArMCParticle*>(pMCParticle));
74 std::cout <<
"LArMCParticleHelper::GetNuanceCode - Error: Can't cast to LArMCParticle" << std::endl;
75 throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
83 if ((nuance == 0) || (nuance == 2000) || (nuance == 2001) || (nuance == 3000))
86 const int absoluteParticleId(std::abs(pMCParticle->GetParticleId()));
87 return ((NU_E == absoluteParticleId) || (NU_MU == absoluteParticleId) || (NU_TAU == absoluteParticleId));
98 catch (
const StatusCodeException &) {}
107 const int absoluteParticleId(std::abs(pMCParticle->GetParticleId()));
109 if ((E_MINUS == absoluteParticleId) || (MU_MINUS == absoluteParticleId) ||
110 (PI_PLUS == absoluteParticleId) || (K_PLUS == absoluteParticleId) ||
111 (SIGMA_MINUS == absoluteParticleId) || (SIGMA_PLUS == absoluteParticleId) || (HYPERON_MINUS == absoluteParticleId) ||
112 (PROTON == absoluteParticleId) || (PHOTON == absoluteParticleId) ||
113 (NEUTRON == absoluteParticleId))
123 for (
const MCParticle *
const pMCParticle : *pMCParticleList)
126 trueNeutrinos.push_back(pMCParticle);
136 const MCParticle *pParentMCParticle = pMCParticle;
138 while (pParentMCParticle->GetParentList().empty() ==
false)
140 if (1 != pParentMCParticle->GetParentList().size())
141 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
143 pParentMCParticle = *(pParentMCParticle->GetParentList().begin());
146 return pParentMCParticle;
153 for (
const MCParticle *
const pMCParticle : *pMCParticleList)
156 mcPrimaryVector.push_back(pMCParticle);
169 const MCParticle *pParentMCParticle = pMCParticle;
170 mcVector.push_back(pParentMCParticle);
172 while (!pParentMCParticle->GetParentList().empty())
174 if (1 != pParentMCParticle->GetParentList().size())
175 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
177 pParentMCParticle = *(pParentMCParticle->GetParentList().begin());
178 mcVector.push_back(pParentMCParticle);
182 for (MCParticleVector::const_reverse_iterator iter = mcVector.rbegin(), iterEnd = mcVector.rend(); iter != iterEnd; ++iter)
184 const MCParticle *
const pNextParticle = *iter;
187 return pNextParticle;
190 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
197 for (
const MCParticle *
const pMCParticle : *pMCParticleList)
202 mcPrimaryMap[pMCParticle] = pPrimaryMCParticle;
204 catch (
const StatusCodeException &) {}
212 ClusterList clusterList;
214 return MCParticleHelper::GetMainMCParticle(&clusterList);
222 const float momentumLhs(pLhs->GetMomentum().GetMagnitudeSquared());
223 const float momentumRhs(pRhs->GetMomentum().GetMagnitudeSquared());
225 if (std::fabs(momentumLhs - momentumRhs) > std::numeric_limits<float>::epsilon())
226 return (momentumLhs > momentumRhs);
229 if (std::fabs(pLhs->GetEnergy() - pRhs->GetEnergy()) > std::numeric_limits<float>::epsilon())
230 return (pLhs->GetEnergy() < pRhs->GetEnergy());
233 if (pLhs->GetParticleId() != pRhs->GetParticleId())
234 return (pLhs->GetParticleId() < pRhs->GetParticleId());
237 const float positionLhs(pLhs->GetVertex().GetMagnitudeSquared());
238 const float positionRhs(pRhs->GetVertex().GetMagnitudeSquared());
240 return (positionLhs < positionRhs);
248 for (
const CaloHit *
const pCaloHit : *pCaloHitList)
252 const MCParticle *
const pHitParticle(MCParticleHelper::GetMainMCParticle(pCaloHit));
253 const MCParticle *pPrimaryParticle(pHitParticle);
256 if (!mcToPrimaryMCMap.empty())
260 if (mcToPrimaryMCMap.end() == mcIter)
263 pPrimaryParticle = mcIter->second;
266 mcToTrueHitListMap[pPrimaryParticle].push_back(pCaloHit);
267 hitToMCMap[pCaloHit] = pPrimaryParticle;
269 catch (StatusCodeException &statusCodeException)
271 if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
272 throw statusCodeException;
280 std::function<
bool(
const MCParticle *
const)> fCriteria,
MCContributionMap &selectedMCParticlesToHitsMap)
287 CaloHitList selectedCaloHitList;
320 for (
const ParticleFlowObject *
const pPfo : pfoList)
322 CaloHitList pfoHitList;
325 if (!pfoToReconstructable2DHitsMap.insert(PfoContributionMap::value_type(pPfo, pfoHitList)).second)
326 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
335 PfoVector sortedPfos;
336 for (
const auto &mapEntry : pfoToReconstructable2DHitsMap) sortedPfos.push_back(mapEntry.first);
339 for (
const ParticleFlowObject *
const pPfo : sortedPfos)
341 for (
const MCContributionMap &mcParticleToHitsMap : selectedMCParticleToHitsMaps)
344 for (
const auto &mapEntry : mcParticleToHitsMap) sortedMCParticles.push_back(mapEntry.first);
345 std::sort(sortedMCParticles.begin(), sortedMCParticles.end(), PointerLessThan<MCParticle>());
347 for (
const MCParticle *
const pMCParticle : sortedMCParticles)
350 if (pfoToMCParticleHitSharingMap.find(pPfo) == pfoToMCParticleHitSharingMap.end())
352 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
354 if (mcParticleToPfoHitSharingMap.find(pMCParticle) == mcParticleToPfoHitSharingMap.end())
355 if (!mcParticleToPfoHitSharingMap.insert(MCParticleToPfoHitSharingMap::value_type(pMCParticle,
PfoToSharedHitsVector())).second)
356 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
362 if (std::any_of(mcHitPairs.begin(), mcHitPairs.end(), [&] (
const MCParticleCaloHitListPair &pair) {
return (pair.first == pMCParticle); }))
363 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
365 if (std::any_of(pfoHitPairs.begin(), pfoHitPairs.end(), [&] (
const PfoCaloHitListPair &pair) {
return (pair.first == pPfo); }))
366 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
371 if (!sharedHits.empty())
380 return ((a.second.size() != b.second.size()) ? a.second.size() > b.second.size() :
LArPfoHelper::SortByNHits(a.first, b.first)); });
391 pandora::CaloHitList &reconstructableCaloHitList2D)
397 CaloHitList caloHitList2D;
406 for (
const CaloHit *
const pCaloHit : caloHitList2D)
408 bool isTargetHit(
false);
409 for (
const MCContributionMap &mcParticleToHitsMap : selectedMCParticleToHitsMaps)
412 for (
const MCContributionMap::value_type &mapEntry : mcParticleToHitsMap)
414 if (std::find(mapEntry.second.begin(), mapEntry.second.end(), pCaloHit) != mapEntry.second.end())
420 if (isTargetHit)
break;
424 reconstructableCaloHitList2D.push_back(pCaloHit);
431 CaloHitList &selectedCaloHitList,
const bool selectInputHits,
const float maxPhotonPropagation)
433 if (!selectInputHits)
435 selectedCaloHitList.insert(selectedCaloHitList.end(), pCaloHitList->begin(), pCaloHitList->end());
439 for (
const CaloHit *
const pCaloHit : *pCaloHitList)
443 const MCParticle *
const pHitParticle(MCParticleHelper::GetMainMCParticle(pCaloHit));
447 if (mcToPrimaryMCMap.end() == mcIter)
450 const MCParticle *
const pPrimaryParticle = mcIter->second;
452 if (
PassMCParticleChecks(pPrimaryParticle, pPrimaryParticle, pHitParticle, maxPhotonPropagation))
453 selectedCaloHitList.push_back(pCaloHit);
455 catch (
const StatusCodeException &)
464 CaloHitList &selectedGoodCaloHitList,
const bool selectInputHits,
const float minHitSharingFraction)
466 if (!selectInputHits)
468 selectedGoodCaloHitList.insert(selectedGoodCaloHitList.end(), pSelectedCaloHitList->begin(), pSelectedCaloHitList->end());
472 for (
const CaloHit *
const pCaloHit : *pSelectedCaloHitList)
475 for (
const auto &mapEntry : pCaloHit->GetMCParticleWeightMap()) mcParticleVector.push_back(mapEntry.first);
476 std::sort(mcParticleVector.begin(), mcParticleVector.end(), PointerLessThan<MCParticle>());
478 MCParticleWeightMap primaryWeightMap;
480 for (
const MCParticle *
const pMCParticle : mcParticleVector)
482 const float weight(pCaloHit->GetMCParticleWeightMap().at(pMCParticle));
485 if (mcToPrimaryMCMap.end() != mcIter)
486 primaryWeightMap[mcIter->second] +=
weight;
490 for (
const auto &mapEntry : primaryWeightMap) mcPrimaryVector.push_back(mapEntry.first);
491 std::sort(mcPrimaryVector.begin(), mcPrimaryVector.end(), PointerLessThan<MCParticle>());
493 const MCParticle *pBestPrimaryParticle(
nullptr);
494 float bestPrimaryWeight(0.
f), primaryWeightSum(0.
f);
496 for (
const MCParticle *
const pPrimaryMCParticle : mcPrimaryVector)
498 const float primaryWeight(primaryWeightMap.at(pPrimaryMCParticle));
499 primaryWeightSum += primaryWeight;
501 if (primaryWeight > bestPrimaryWeight)
503 bestPrimaryWeight = primaryWeight;
504 pBestPrimaryParticle = pPrimaryMCParticle;
508 if (!pBestPrimaryParticle || (primaryWeightSum < std::numeric_limits<float>::epsilon()) || ((bestPrimaryWeight / primaryWeightSum) < minHitSharingFraction))
511 selectedGoodCaloHitList.push_back(pCaloHit);
520 for (
const MCParticle *
const pMCParticle : inputMCParticles)
522 if (fCriteria(pMCParticle))
523 selectedParticles.push_back(pMCParticle);
533 for (
const MCParticle *
const pMCTarget : candidateTargets)
536 if (mcToTrueHitListMap.end() == trueHitsIter)
539 const CaloHitList &caloHitList(trueHitsIter->second);
542 CaloHitList goodCaloHitList;
548 unsigned int nGoodViews(0);
561 if (!selectedMCParticlesToHitsMap.insert(MCContributionMap::value_type(pMCTarget, caloHitList)).second)
562 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
569 const MCParticle *
const pHitMCParticle,
const float maxPhotonPropagation)
571 if (NEUTRON == std::abs(pThisMCParticle->GetParticleId()))
574 if ((PHOTON == pThisMCParticle->GetParticleId()) && (PHOTON != pOriginalPrimary->GetParticleId()) && (E_MINUS != std::abs(pOriginalPrimary->GetParticleId())))
576 if ((pThisMCParticle->GetEndpoint() - pThisMCParticle->GetVertex()).GetMagnitude() > maxPhotonPropagation)
580 if (pThisMCParticle == pHitMCParticle)
583 for (
const MCParticle *
const pDaughterMCParticle : pThisMCParticle->GetDaughterList())
585 if (
PassMCParticleChecks(pOriginalPrimary, pDaughterMCParticle, pHitMCParticle, maxPhotonPropagation))
596 CaloHitList sharedHits;
598 for (
const CaloHit *
const pCaloHit : hitListA)
600 if (std::find(hitListB.begin(), hitListB.end(), pCaloHit) != hitListB.end())
601 sharedHits.push_back(pCaloHit);
static bool IsVisible(const pandora::MCParticle *const pMCParticle)
Whether a mc particle is visible (i.e. long-lived charged particle)
static bool PassMCParticleChecks(const pandora::MCParticle *const pOriginalPrimary, const pandora::MCParticle *const pThisMCParticle, const pandora::MCParticle *const pHitMCParticle, const float maxPhotonPropagation)
Whether it is possible to navigate from a primary mc particle to a downstream mc particle without "pa...
unsigned int m_minPrimaryGoodViews
the minimum number of primary good views
static bool SortByNHits(const pandora::ParticleFlowObject *const pLhs, const pandora::ParticleFlowObject *const pRhs)
Sort pfos by number of constituent hits.
Header file for the pfo helper class.
bool m_selectInputHits
whether to select input hits
static bool IsPrimary(const pandora::MCParticle *const pMCParticle)
Whether a provided mc particle matches the implemented definition of being primary.
static void GetTwoDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 2D clusters from an input pfo.
unsigned int m_minPrimaryGoodHits
the minimum number of primary good Hits
int GetNuanceCode() const
Get the nuance code.
static void GetPfoMCParticleHitSharingMaps(const PfoContributionMap &pfoToReconstructable2DHitsMap, const MCContributionMapVector &selectedMCParticleToHitsMaps, PfoToMCParticleHitSharingMap &pfoToMCParticleHitSharingMap, MCParticleToPfoHitSharingMap &mcParticleToPfoHitSharingMap)
Get the mappings from Pfo -> pair (reconstructable MCparticles, number of reconstructable 2D hits sha...
static const pandora::MCParticle * GetPrimaryMCParticle(const pandora::MCParticle *const pMCParticle)
Get the primary parent mc particle.
std::vector< PfoCaloHitListPair > PfoToSharedHitsVector
static void GetMCPrimaryMap(const pandora::MCParticleList *const pMCParticleList, MCRelationMap &mcPrimaryMap)
Get mapping from individual mc particles (in a provided list) and their primary parent mc particles...
Header file for the lar monitoring helper helper class.
static const pandora::MCParticle * GetMainMCParticle(const pandora::ParticleFlowObject *const pPfo)
Find the mc particle making the largest contribution to 2D clusters in a specified pfo...
std::vector< art::Ptr< simb::MCParticle > > MCParticleVector
static unsigned int GetNuanceCode(const pandora::MCParticle *const pMCParticle)
Get the nuance code of an MCParticle.
unsigned int m_minHitsForGoodView
the minimum number of Hits for a good view
float m_maxPhotonPropagation
the maximum photon propagation length
static void SelectCaloHits(const pandora::CaloHitList *const pCaloHitList, const MCRelationMap &mcToPrimaryMCMap, pandora::CaloHitList &selectedCaloHitList, const bool selectInputHits, const float maxPhotonPropagation)
Select a subset of calo hits representing those that represent "reconstructable" regions of the event...
static void SelectParticlesByHitCount(const pandora::MCParticleVector &candidateTargets, const MCContributionMap &mcToTrueHitListMap, const MCRelationMap &mcToPrimaryMCMap, const PrimaryParameters ¶meters, MCContributionMap &selectedMCParticlesToHitsMap)
Filter an input vector of MCParticles to ensure they have sufficient good hits to be reconstructable...
static bool SortByMomentum(const pandora::MCParticle *const pLhs, const pandora::MCParticle *const pRhs)
Sort mc particles by their momentum.
static bool IsCosmicRay(const pandora::MCParticle *const pMCParticle)
Return true if passed a primary cosmic ray MCParticle.
static void SelectReconstructableMCParticles(const pandora::MCParticleList *pMCParticleList, const pandora::CaloHitList *pCaloHitList, const PrimaryParameters ¶meters, std::function< bool(const pandora::MCParticle *const)> fCriteria, MCContributionMap &selectedMCParticlesToHitsMap)
Select primary, reconstructable mc particles that match given criteria.
static void SelectParticlesMatchingCriteria(const pandora::MCParticleVector &inputMCParticles, std::function< bool(const pandora::MCParticle *const)> fCriteria, pandora::MCParticleVector &selectedParticles)
Select mc particles matching given criteria from an input list.
std::unordered_map< const pandora::MCParticle *, pandora::CaloHitList > MCContributionMap
static void GetPfoToReconstructable2DHitsMap(const pandora::PfoList &pfoList, const MCContributionMap &selectedMCParticleToHitsMap, PfoContributionMap &pfoToReconstructable2DHitsMap)
Get mapping from Pfo to reconstructable 2D hits (=good hits belonging to a selected reconstructable M...
Header file for the lar monte carlo particle helper helper class.
Header file for the cluster helper class.
static bool IsBeamParticle(const pandora::MCParticle *const pMCParticle)
Returns true if passed a primary beam MCParticle.
std::map< const pandora::MCParticle *, PfoToSharedHitsVector > MCParticleToPfoHitSharingMap
static const pandora::MCParticle * GetParentMCParticle(const pandora::MCParticle *const pMCParticle)
Get the parent mc particle.
static void CollectReconstructable2DHits(const pandora::ParticleFlowObject *const pPfo, const MCContributionMapVector &selectedMCParticleToHitsMaps, pandora::CaloHitList &reconstructableCaloHitList2D)
For a given Pfo, collect the hits which are reconstructable (=good hits belonging to a selected recon...
float m_minHitSharingFraction
the minimum Hit sharing fraction
static void SelectGoodCaloHits(const pandora::CaloHitList *const pSelectedCaloHitList, const MCRelationMap &mcToPrimaryMCMap, pandora::CaloHitList &selectedGoodCaloHitList, const bool selectInputHits, const float minHitSharingFraction)
Apply further selection criteria to end up with a collection of "good" calo hits that can be use to d...
std::vector< MCContributionMap > MCContributionMapVector
std::map< const pandora::ParticleFlowObject *, MCParticleToSharedHitsVector > PfoToMCParticleHitSharingMap
static void GetPrimaryMCParticleList(const pandora::MCParticleList *const pMCParticleList, pandora::MCParticleVector &mcPrimaryVector)
Get vector of primary MC particles from an input list of MC particles.
std::unordered_map< const pandora::CaloHit *, const pandora::MCParticle * > CaloHitToMCMap
static void GetTrueNeutrinos(const pandora::MCParticleList *const pMCParticleList, pandora::MCParticleVector &trueNeutrinos)
Get neutrino MC particles from an input MC particle list.
std::pair< const pandora::MCParticle *, pandora::CaloHitList > MCParticleCaloHitListPair
static void GetIsolatedCaloHits(const pandora::PfoList &pfoList, const pandora::HitType &hitType, pandora::CaloHitList &caloHitList)
Get a list of isolated calo hits of a particular hit type from a list of pfos.
PrimaryParameters()
Constructor.
static void GetMCParticleToCaloHitMatches(const pandora::CaloHitList *const pCaloHitList, const MCRelationMap &mcToPrimaryMCMap, CaloHitToMCMap &hitToMCMap, MCContributionMap &mcToTrueHitListMap)
Match calo hits to their parent particles.
static void GetAllDownstreamPfos(const pandora::PfoList &inputPfoList, pandora::PfoList &outputPfoList)
Get a flat list of all pfos, recursively, of all daughters associated with those pfos in an input lis...
std::vector< MCParticleCaloHitListPair > MCParticleToSharedHitsVector
std::unordered_map< const pandora::ParticleFlowObject *, pandora::CaloHitList > PfoContributionMap
std::unordered_map< const pandora::MCParticle *, const pandora::MCParticle * > MCRelationMap
static void GetCaloHits(const pandora::PfoList &pfoList, const pandora::HitType &hitType, pandora::CaloHitList &caloHitList)
Get a list of calo hits of a particular hit type from a list of pfos.
static pandora::CaloHitList GetSharedHits(const pandora::CaloHitList &hitListA, const pandora::CaloHitList &hitListB)
Get the hits in the intersection of two hit lists.
static bool IsBeamNeutrinoFinalState(const pandora::MCParticle *const pMCParticle)
Returns true if passed a primary neutrino final state MCParticle.
static unsigned int CountHitsByType(const pandora::HitType hitType, const pandora::CaloHitList &caloHitList)
Count the number of calo hits, in a provided list, of a specified type.
static bool IsNeutrino(const pandora::MCParticle *const pMCParticle)
Whether a mc particle is a neutrino or antineutrino.
std::pair< const pandora::ParticleFlowObject *, pandora::CaloHitList > PfoCaloHitListPair