9 #include "Pandora/AlgorithmHeaders.h" 10 #include "Pandora/StatusCodes.h" 26 DLCheatHierarchyTool::DLCheatHierarchyTool() :
27 m_mcParticleListName(
"Input"),
28 m_neutrinoPfoListName(
"NeutrinoParticles3D"),
29 m_pfoListNames({
"TrackParticles3D",
"ShowerParticles3D"})
36 const HierarchyPfo &parentPfo,
const HierarchyPfo &childPfo,
bool &isTrueLink,
bool &trueParentOrientation,
bool &trueChildOrientation)
39 if ((pfoToMCParticleMap.find(parentPfo.
GetPfo()) == pfoToMCParticleMap.end()) ||
40 (pfoToMCParticleMap.find(childPfo.
GetPfo()) == pfoToMCParticleMap.end()))
42 return STATUS_CODE_NOT_FOUND;
46 if (childToParentPfoMap.find(childPfo.
GetPfo()) == childToParentPfoMap.end())
47 return STATUS_CODE_NOT_FOUND;
49 isTrueLink = (childToParentPfoMap.at(childPfo.
GetPfo()).first == parentPfo.
GetPfo());
59 return STATUS_CODE_SUCCESS;
65 const ParticleFlowObject *
const pNeutrinoPfo,
const HierarchyPfo &childPfo,
bool &isTrueLink,
bool &trueChildOrientation)
68 if (pfoToMCParticleMap.find(childPfo.
GetPfo()) == pfoToMCParticleMap.end())
69 return STATUS_CODE_NOT_FOUND;
72 if (childToParentPfoMap.find(childPfo.
GetPfo()) == childToParentPfoMap.end())
73 return STATUS_CODE_NOT_FOUND;
75 isTrueLink = (childToParentPfoMap.at(childPfo.
GetPfo()).first == pNeutrinoPfo);
81 return STATUS_CODE_SUCCESS;
89 if (pfoToMCParticleMap.find(pPfo) == pfoToMCParticleMap.end())
90 return STATUS_CODE_NOT_FOUND;
92 const MCParticleList &parentList(pfoToMCParticleMap.at(pPfo)->GetParentList());
94 if (parentList.size() != 1)
96 std::cout <<
"No MCParent for MCParticle" << std::endl;
97 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
100 isNeutronChild = ((*parentList.begin())->GetParticleId() == 2112);
102 return STATUS_CODE_SUCCESS;
108 const CartesianVector &upstreamVertex,
const CartesianVector &downstreamVertex)
110 const MCParticle *
const pMatchedMCParticle(pfoToMCParticleMap.at(pPfo));
112 const float upstreamSepSq((pMatchedMCParticle->GetVertex() - upstreamVertex).GetMagnitudeSquared());
113 const float downstreamSepSq((pMatchedMCParticle->GetVertex() - downstreamVertex).GetMagnitudeSquared());
115 return (upstreamSepSq < downstreamSepSq);
123 pfoToMCParticleMap.clear();
124 childToParentPfoMap.clear();
127 const MCParticleList *pMCParticleList(
nullptr);
132 const ParticleFlowObject *pNeutrinoPfo(
nullptr);
151 if (PandoraContentApi::GetList(*pAlgorithm,
m_mcParticleListName, pMCParticleList) != STATUS_CODE_SUCCESS)
154 if (!pMCParticleList || pMCParticleList->empty())
164 const PfoList *pPfoList =
nullptr;
166 PANDORA_THROW_RESULT_IF_AND_IF(
167 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*pAlgorithm,
m_neutrinoPfoListName, pPfoList));
169 if (!pPfoList || pPfoList->empty())
173 pNeutrinoPfo = (1 == pPfoList->size()) ? *(pPfoList->begin()) :
nullptr;
175 if (!pNeutrinoPfo || !LArPfoHelper::IsNeutrino(pNeutrinoPfo))
176 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
187 const PfoList *pPfoList(
nullptr);
189 if (PandoraContentApi::GetList(*pAlgorithm, pfoListName, pPfoList) != STATUS_CODE_SUCCESS)
195 for (
const ParticleFlowObject *pPfo : *pPfoList)
204 for (
const HitType hitType : {TPC_VIEW_U, TPC_VIEW_V, TPC_VIEW_W})
206 CaloHitList caloHitList;
207 LArPfoHelper::GetCaloHits(pPfo, hitType, caloHitList);
209 for (
const CaloHit *
const pCaloHit : caloHitList)
213 const MCParticle *pHitMCParticle(MCParticleHelper::GetMainMCParticle(pCaloHit));
219 contributionMap[pHitMCParticle].emplace_back(pCaloHit);
229 unsigned int highestHit(0);
230 float highestEnergy(-1.
f);
231 const MCParticle *pMatchedMCParticle(
nullptr);
233 for (
const auto &entry : contributionMap)
235 if (entry.second.size() > highestHit)
237 highestHit = entry.second.size();
238 highestEnergy = this->
SumEnergy(entry.second);
239 pMatchedMCParticle = entry.first;
241 else if (entry.second.size() == highestHit)
243 const float totalEnergy(this->
SumEnergy(entry.second));
245 if (totalEnergy > highestEnergy)
247 highestHit = entry.second.size();
248 highestEnergy = totalEnergy;
249 pMatchedMCParticle = entry.first;
254 if (!pMatchedMCParticle)
255 throw StatusCodeException(STATUS_CODE_FAILURE);
257 pfoToMCParticleMap[pPfo] = pMatchedMCParticle;
266 ClusterList clusterList3D;
267 LArPfoHelper::GetThreeDClusterList(pPfo, clusterList3D);
271 for (
const Cluster *
const pCluster3D : clusterList3D)
272 total3DHits += pCluster3D->GetNCaloHits();
281 return ((pMCParticle->GetParticleId() == 22) || (
std::abs(pMCParticle->GetParticleId()) == 11));
289 throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
291 const MCParticle *pThisMCParticle(pMCParticle);
292 const MCParticle *pParentMCParticle(pMCParticle);
296 const MCParticleList &parentList(pThisMCParticle->GetParentList());
298 if (parentList.size() != 1)
300 std::cout <<
"EM shower has no parent?" << std::endl;
301 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
304 pParentMCParticle = *parentList.begin();
307 pThisMCParticle = pParentMCParticle;
310 return pThisMCParticle;
317 float totalEnergy(0.
f);
319 for (
const CaloHit *
const pCaloHit : caloHitList)
321 if (pCaloHit->GetHitType() == TPC_VIEW_W)
322 totalEnergy += pCaloHit->GetElectromagneticEnergy();
332 MCParticleList reconstructedMCList;
334 for (
const auto &entry : pfoToMCParticleMap)
336 if (std::find(reconstructedMCList.begin(), reconstructedMCList.end(), entry.second) == reconstructedMCList.end())
337 reconstructedMCList.emplace_back(entry.second);
340 for (
const MCParticle *
const pMCParticle : reconstructedMCList)
342 bool foundParent(
false);
343 const MCParticle *pThisMCParticle(pMCParticle);
344 const MCParticle *pParentMCParticle(
nullptr);
348 const MCParticleList &parentList(pThisMCParticle->GetParentList());
350 if (parentList.size() != 1)
352 std::cout <<
"No MCParent for MCParticle" << std::endl;
353 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
356 pParentMCParticle = *parentList.begin();
358 foundParent = (LArMCParticleHelper::IsNeutrino(pParentMCParticle) ||
359 (std::find(reconstructedMCList.begin(), reconstructedMCList.end(), pParentMCParticle) != reconstructedMCList.end()));
361 pThisMCParticle = pParentMCParticle;
364 childToParentMCMap[pMCParticle] = pParentMCParticle;
373 std::map<const MCParticle *, PfoList> mcParticleToPfoListMap;
375 for (
const auto &entry : pfoToMCParticleMap)
376 mcParticleToPfoListMap[entry.second].emplace_back(entry.first);
379 for (
const auto &entry : mcParticleToPfoListMap)
381 if (entry.second.size() == 1)
388 for (
const auto &entry : mcParticleToPfoListMap)
390 const MCParticle *
const pMatchedMCParticle(entry.first);
392 if (childToParentMCMap.find(pMatchedMCParticle) == childToParentMCMap.end())
394 std::cout <<
"have found a mcparticle with no parent" << std::endl;
395 throw StatusCodeException(STATUS_CODE_FAILURE);
398 const MCParticle *
const pMatchedMCParent(childToParentMCMap.at(pMatchedMCParticle));
400 for (
const ParticleFlowObject *
const pChildPfo : entry.second)
403 if (childToParentPfoMap.find(pChildPfo) != childToParentPfoMap.end())
406 if (LArMCParticleHelper::IsNeutrino(pMatchedMCParent))
409 childToParentPfoMap[pChildPfo] = std::make_pair(pNeutrinoPfo, 0);
414 if (mcParticleToPfoListMap.find(pMatchedMCParent) == mcParticleToPfoListMap.end())
415 throw StatusCodeException(STATUS_CODE_FAILURE);
417 const PfoList &parentPfoList(mcParticleToPfoListMap.at(pMatchedMCParent));
419 if (parentPfoList.size() == 1)
420 childToParentPfoMap[pChildPfo] = std::make_pair(*parentPfoList.begin(), 0);
436 std::vector<std::pair<const ParticleFlowObject *, float>> pfoComponents;
438 for (
const ParticleFlowObject *
const pSplitPfo : splitPfo.second)
440 ClusterList clusterList;
441 LArPfoHelper::GetThreeDClusterList(pSplitPfo, clusterList);
443 if (clusterList.empty())
444 throw StatusCodeException(STATUS_CODE_FAILURE);
446 pfoComponents.emplace_back(std::make_pair(pSplitPfo, LArClusterHelper::GetClosestDistance(splitPfo.first->GetVertex(), clusterList)));
449 std::sort(pfoComponents.begin(), pfoComponents.end(),
450 [](
const std::pair<const ParticleFlowObject *, float> &a,
const std::pair<const ParticleFlowObject *, float> &b)
451 {
return a.second < b.second; });
454 childToParentPfoMap[pfoComponents.at(1).first] = std::make_pair(pfoComponents.at(0).first, 0);
456 for (
unsigned int i = 2; i < pfoComponents.size(); ++i)
458 const ParticleFlowObject *
const pChildPfo(pfoComponents.at(i).first);
459 double closestSep = std::numeric_limits<double>::max();
460 const ParticleFlowObject *pParentPfo(
nullptr);
462 for (
unsigned int j = 0; j < i; ++j)
464 const ParticleFlowObject *
const pPotentialParentPfo(pfoComponents.at(j).first);
467 if (thisSep < closestSep)
469 closestSep = thisSep;
470 pParentPfo = pPotentialParentPfo;
475 throw StatusCodeException(STATUS_CODE_FAILURE);
477 childToParentPfoMap[pChildPfo] = std::make_pair(pParentPfo, 0);
485 ClusterList clusterList1, clusterList2;
486 LArPfoHelper::GetThreeDClusterList(pPfo1, clusterList1);
487 LArPfoHelper::GetThreeDClusterList(pPfo2, clusterList2);
489 return LArClusterHelper::GetClosestDistance(clusterList1, clusterList2);
496 float closestSep = std::numeric_limits<float>::max();
497 const ParticleFlowObject *pParentPfo(
nullptr);
499 for (
const ParticleFlowObject *
const pPotentialParent : splitParticle)
503 if (thisSep < closestSep)
505 closestSep = thisSep;
506 pParentPfo = pPotentialParent;
512 std::cout <<
"No closest Pfo?" << std::endl;
513 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
522 const ParticleFlowObject *
const pParentPfo,
const int generationToFind,
ChildToParentPfoMap &childToParentPfoMap)
const 525 for (ChildToParentPfoMap::value_type &entry : childToParentPfoMap)
527 const ParticleFlowObject *
const pThisPfo(entry.first);
528 const ParticleFlowObject *
const pThisParent(entry.second.first);
530 if (pParentPfo == pThisParent)
532 entry.second.second = generationToFind;
533 this->
AssignGeneration(pThisPfo, (generationToFind + 1), childToParentPfoMap);
543 PANDORA_RETURN_RESULT_IF_AND_IF(
544 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MCParticleListName",
m_mcParticleListName));
546 PANDORA_RETURN_RESULT_IF_AND_IF(
547 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"NeutrinoPfoListName",
m_neutrinoPfoListName));
549 PANDORA_RETURN_RESULT_IF_AND_IF(
550 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadVectorOfValues(xmlHandle,
"PfoListNames",
m_pfoListNames));
552 return STATUS_CODE_SUCCESS;
std::map< const pandora::ParticleFlowObject *, std::pair< const pandora::ParticleFlowObject *, int > > ChildToParentPfoMap
pandora::StringVector m_pfoListNames
the vector of pfo list names
Header file for the pfo helper class.
const pandora::ParticleFlowObject * BestParentInSplitHierarchy(const pandora::ParticleFlowObject *const pChildPfo, const pandora::PfoList &splitParticle) const
In cases in which the true parent pfo is ambiguous (because the parent particle has been split)...
float SumEnergy(const pandora::CaloHitList &caloHitList) const
Sum the 'energy' of the W hits in an input CaloHitList.
std::unordered_map< const pandora::MCParticle *, pandora::CaloHitList > MCContributionMap
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
const pandora::ParticleFlowObject * GetPfo() const
Get the pfo.
std::map< const pandora::MCParticle *, const pandora::MCParticle * > MCToMCMap
void FillHierarchyMap(const pandora::Algorithm *const pAlgorithm, PfoToMCParticleMap &pfoToMCParticleMap, ChildToParentPfoMap &childToParentPfoMap) const
Determine the true child -> parent pfo visible matches, filling the pfo->MCParticle matching map in t...
void GetVisibleMCHierarchy(const PfoToMCParticleMap &pfoToMCParticleMap, MCToMCMap &childToParentMCMap) const
Determine the true child->parent MCParticle visible matches.
Header file for the HierarchyPfo class.
constexpr auto abs(T v)
Returns the absolute value of the argument.
void BuildSplitHierarchy(const std::pair< const pandora::MCParticle *, pandora::PfoList > &splitPfo, ChildToParentPfoMap &childToParentPfoMap) const
Determine the 'internal' hierachy of reconstructed particles that match to the same MCParticle i...
pandora::StatusCode Run(const PfoToMCParticleMap &pfoToMCParticleMap, const ChildToParentPfoMap &childToParentPfoMap, const HierarchyPfo &parentPfo, const HierarchyPfo &childPfo, bool &isTrueLink, bool &trueParentOrientation, bool &trueChildOrientation)
std::string m_neutrinoPfoListName
the neutrino pfo list name
void MatchPFParticles(const pandora::Algorithm *const pAlgorithm, PfoToMCParticleMap &pfoToMCParticleMap) const
Perform the pfo->MCParticle matching, folding back EM shower hierarchies.
bool IsEMParticle(const pandora::MCParticle *const pMCParticle) const
Whether a MCParticle is an electron or photon.
const ExtremalPoint & GetUpstreamPoint() const
Get the upstream extremal point.
Header file for the lar monte carlo particle helper helper class.
Header file for the cluster helper class.
const ExtremalPoint & GetDownstreamPoint() const
Get the downstream extremal point.
pandora::StatusCode IsNeutronChild(const pandora::ParticleFlowObject *const pPfo, const PfoToMCParticleMap &pfoToMCParticleMap, bool &isNeutronChild) const
Whether the true invisible parent of a particle is a neutron.
std::string m_mcParticleListName
the MCParticle list name
const pandora::CartesianVector & GetPosition() const
Get the position.
bool IsUpstreamTrueVertex(const PfoToMCParticleMap &pfoToMCParticleMap, const pandora::ParticleFlowObject *const pPfo, const pandora::CartesianVector &upstreamVertex, const pandora::CartesianVector &downstreamVertex)
Whether the true startpoint of the particle is in the upstream position (i.e. the endpoint closest to...
float GetClosestDistance(const pandora::ParticleFlowObject *const pPfo1, const pandora::ParticleFlowObject *const pPfo2) const
Determine the closest distance between two pfos.
void GetVisiblePfoHierarchy(const pandora::ParticleFlowObject *const pNeutrinoPfo, const PfoToMCParticleMap &pfoToMCParticleMap, const MCToMCMap &childToParentMCMap, ChildToParentPfoMap &childToParentPfoMap) const
Determine the true child->parent pfo visible matches.
float GetNSpacepoints(const pandora::ParticleFlowObject *const pPfo) const
Get the number of 3D hits owned by a pfo.
void AssignGeneration(const pandora::ParticleFlowObject *const pParentPfo, const int generationToFind, ChildToParentPfoMap &childToParentPfoMap) const
Find the children of an input parent pfo in the ChildToParentPfoMap, and assign their generation...
std::map< const pandora::ParticleFlowObject *, const pandora::MCParticle * > PfoToMCParticleMap
bool GetMCParticleList(const pandora::Algorithm *const pAlgorithm, const pandora::MCParticleList *&pMCParticleList) const
Get the MCParticle list from Pandora.
bool GetNeutrinoPfo(const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *&pNeutrinoPfo) const
Get the neutrino pfo.
const pandora::MCParticle * GetLeadEMParticle(const pandora::MCParticle *const pMCParticle) const
Get the leading EM Particle in an EM MCParticle hierarchy.