9 #include "Pandora/PdgTable.h" 10 #include "Pandora/StatusCodes.h" 22 m_foldToLeadingShowers{
false},
52 std::cout <<
"LArHierarchyHelper: Error - attempting to fold to non-positive tier" <<
std::endl;
53 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
101 const auto predicate = [](
const MCParticle *pMCParticle) {
return std::abs(pMCParticle->GetParticleId()) == NEUTRON; };
103 for (
const CaloHit *pCaloHit : caloHitList)
107 const MCParticle *pMCParticle{MCParticleHelper::GetMainMCParticle(pCaloHit)};
110 catch (
const StatusCodeException &)
117 MCParticleList primaries(primarySet.begin(), primarySet.end());
120 primaries.erase(std::remove_if(primaries.begin(), primaries.end(), predicate), primaries.end());
123 for (
const MCParticle *pPrimary : primaries)
125 MCParticleList allParticles{pPrimary};
133 MCParticleList
dummy;
137 for (
const MCParticle *pMCParticle : allParticles)
143 allHits.insert(allHits.begin(), caloHits.begin(), caloHits.end());
151 for (
const MCParticle *pPrimary : primaries)
153 MCParticleList allParticles{pPrimary};
156 const bool isNeutron{
pdg == NEUTRON};
160 for (
const MCParticle *pMCParticle : allParticles)
166 allHits.insert(allHits.begin(), caloHits.begin(), caloHits.end());
169 Node *pNode{
new Node(*
this, allParticles, allHits)};
171 if (!(isShower || isNeutron))
174 const MCParticleList &children{pPrimary->GetDaughterList()};
175 for (
const MCParticle *pChild : children)
176 pNode->FillHierarchy(pChild, foldParameters);
182 for (
const MCParticle *pPrimary : primaries)
184 MCParticleList leadingParticles, childParticles;
187 for (
const MCParticle *pMCParticle : leadingParticles)
193 allHits.insert(allHits.begin(), caloHits.begin(), caloHits.end());
197 Node *pNode{
new Node(*
this, leadingParticles, allHits)};
199 for (
const MCParticle *pChild : childParticles)
200 pNode->FillHierarchy(pChild, foldParameters);
206 for (
const MCParticle *pPrimary : primaries)
208 MCParticleList allParticles{pPrimary};
210 for (
const MCParticle *pMCParticle : allParticles)
216 allHits.insert(allHits.begin(), caloHits.begin(), caloHits.end());
219 Node *pNode{
new Node(*
this, allParticles, allHits)};
222 const MCParticleList &children{pPrimary->GetDaughterList()};
223 for (
const MCParticle *pChild : children)
224 pNode->FillHierarchy(pChild, foldParameters);
228 Node *pLeadingLepton{
nullptr};
232 const MCParticle *pMC{pNode->GetLeadingMCParticle()};
236 if ((
pdg == MU_MINUS ||
pdg == E_MINUS ||
pdg == TAU_MINUS) && pMC->GetEnergy() > leadingLeptonEnergy)
238 pLeadingLepton =
const_cast<Node *
>(pNode);
239 leadingLeptonEnergy = pMC->GetEnergy();
250 const MCParticle *
const pRoot, MCParticleList &leadingParticles, MCParticleList &childParticles,
const float cosAngleTolerance)
const 252 leadingParticles.emplace_back(pRoot);
253 MCParticleList foldCandidates, childCandidates;
254 const MCParticleList &children{pRoot->GetDaughterList()};
255 for (
const MCParticle *pMCParticle : children)
264 if (pMCParticle->GetParticleId() == pRoot->GetParticleId())
265 foldCandidates.emplace_back(pMCParticle);
267 childCandidates.emplace_back(pMCParticle);
272 childCandidates.emplace_back(pMCParticle);
275 const MCParticle *pBestFoldCandidate{
nullptr};
277 for (
const MCParticle *pMCParticle : foldCandidates)
279 if (foldCandidates.size() == 1)
284 pBestFoldCandidate = pMCParticle;
286 childCandidates.emplace_back(pMCParticle);
293 const float dp{pRoot->GetMomentum().GetMagnitude() - pMCParticle->GetMomentum().GetMagnitude()};
296 pBestFoldCandidate = pMCParticle;
302 childCandidates.emplace_back(pMCParticle);
306 if (pBestFoldCandidate)
308 leadingParticles.emplace_back(pBestFoldCandidate);
311 this->
CollectContinuations(pBestFoldCandidate, leadingParticles, childCandidates, cosAngleTolerance);
313 for (
const MCParticle *pMCParticle : childCandidates)
317 childParticles.emplace_back(pMCParticle);
320 MCParticleList localHierarchy{pMCParticle};
321 CaloHitList localHits;
323 for (
const MCParticle *pLocalMCParticle : localHierarchy)
327 const CaloHitList &caloHits(
m_mcToHitsMap.at(pLocalMCParticle));
328 localHits.insert(localHits.begin(), caloHits.begin(), caloHits.end());
332 childParticles.emplace_back(pMCParticle);
340 const MCParticle *pRoot, MCParticleList &continuingParticles, MCParticleList &childParticles,
const float cosAngleTolerance)
const 342 const MCParticleList &children{pRoot->GetDaughterList()};
343 MCParticleList foldCandidates;
344 for (
const MCParticle *pMCParticle : children)
352 if (pMCParticle->GetParticleId() == pRoot->GetParticleId())
353 foldCandidates.emplace_back(pMCParticle);
358 childParticles.emplace_back(pMCParticle);
361 const MCParticle *pBestFoldCandidate{
nullptr};
363 for (
const MCParticle *pMCParticle : foldCandidates)
365 if (foldCandidates.size() == 1)
370 pBestFoldCandidate = pMCParticle;
377 const float dp{pRoot->GetMomentum().GetMagnitude() - pMCParticle->GetMomentum().GetMagnitude()};
380 pBestFoldCandidate = pMCParticle;
386 if (pBestFoldCandidate)
388 continuingParticles.emplace_back(pBestFoldCandidate);
389 const MCParticleList &newLeadingParticles{pBestFoldCandidate->GetDaughterList()};
391 childParticles.insert(childParticles.begin(), newLeadingParticles.begin(), newLeadingParticles.end());
393 const auto iter{std::find(childParticles.begin(), childParticles.end(), pBestFoldCandidate)};
394 if (iter != childParticles.end())
395 childParticles.erase(iter);
409 nodeVector.emplace_back(pNode);
410 queue.emplace_back(pNode);
412 while (!queue.empty())
414 const NodeVector &children{queue.front()->GetChildren()};
416 for (
const Node *pChild : children)
418 nodeVector.emplace_back(pChild);
419 queue.emplace_back(pChild);
438 str += pNode->ToString(
"") +
"\n";
449 unsigned int nHitsU{0}, nHitsV{0}, nHitsW{0};
450 for (
const CaloHit *pCaloHit :
m_mcToHitsMap.at(pMCParticle))
452 const HitType view{pCaloHit->GetHitType()};
453 if (view == TPC_VIEW_U)
455 else if (view == TPC_VIEW_V)
457 else if (view == TPC_VIEW_W)
460 const unsigned int nHits{nHitsU + nHitsV + nHitsW};
461 unsigned int nGoodViews{0};
476 unsigned int nHitsU{0}, nHitsV{0}, nHitsW{0};
477 for (
const CaloHit *pCaloHit : caloHits)
479 const HitType view{pCaloHit->GetHitType()};
480 if (view == TPC_VIEW_U)
482 else if (view == TPC_VIEW_V)
484 else if (view == TPC_VIEW_W)
487 const unsigned int nHits{nHitsU + nHitsV + nHitsW};
488 unsigned int nGoodViews{0};
500 m_hierarchy(hierarchy),
501 m_mainParticle(pMCParticle),
504 m_isLeadingLepton{
false}
508 m_pdg = pMCParticle->GetParticleId();
509 m_mcParticles.emplace_back(pMCParticle);
511 m_hierarchy.RegisterNode(
this);
517 m_hierarchy(hierarchy),
518 m_mcParticles(mcParticleList),
519 m_caloHits(caloHitList),
520 m_mainParticle(
nullptr),
523 m_isLeadingLepton{
false}
525 if (!mcParticleList.empty())
527 m_mainParticle = mcParticleList.front();
528 m_pdg = m_mainParticle->GetParticleId();
532 m_hierarchy.RegisterNode(
this);
539 m_mcParticles.clear();
541 for (
const Node *node : m_children)
552 MCParticleList leadingParticles, childParticles;
553 m_hierarchy.InterpretHierarchy(pRoot, leadingParticles, childParticles, foldParameters.
m_cosAngleTolerance);
555 for (
const MCParticle *pMCParticle : leadingParticles)
558 if (m_hierarchy.m_mcToHitsMap.find(pMCParticle) != m_hierarchy.m_mcToHitsMap.end())
560 const CaloHitList &caloHits(m_hierarchy.m_mcToHitsMap.at(pMCParticle));
561 allHits.insert(allHits.begin(), caloHits.begin(), caloHits.end());
565 Node *pNode{
new Node(m_hierarchy, leadingParticles, allHits, this->m_tier + 1)};
566 m_children.emplace_back(pNode);
567 for (
const MCParticle *pChild : childParticles)
568 pNode->FillHierarchy(pChild, foldParameters);
572 MCParticleList allParticles{pRoot};
575 const bool isNeutron{
pdg == NEUTRON};
579 else if (foldParameters.
m_foldToLeadingShowers && (isShower || (isNeutron && !m_hierarchy.m_recoCriteria.m_removeNeutrons)))
581 else if (m_hierarchy.m_recoCriteria.m_removeNeutrons && isNeutron)
585 for (
const MCParticle *pMCParticle : allParticles)
588 if (m_hierarchy.m_mcToHitsMap.find(pMCParticle) != m_hierarchy.m_mcToHitsMap.end())
590 const CaloHitList &caloHits(m_hierarchy.m_mcToHitsMap.at(pMCParticle));
591 allHits.insert(allHits.begin(), caloHits.begin(), caloHits.end());
595 if (!allParticles.empty())
601 if (hasChildren || (!hasChildren && !allHits.empty()))
603 Node *pNode{
new Node(m_hierarchy, allParticles, allHits, this->m_tier + 1)};
604 m_children.emplace_back(pNode);
608 const MCParticleList &children{pRoot->GetDaughterList()};
609 for (
const MCParticle *pChild : children)
610 pNode->FillHierarchy(pChild, foldParameters);
621 MCParticleList allParticles{pRoot};
622 if (!m_hierarchy.m_recoCriteria.m_removeNeutrons)
632 for (
const MCParticle *pMCParticle : allParticles)
635 if (m_hierarchy.m_mcToHitsMap.find(pMCParticle) != m_hierarchy.m_mcToHitsMap.end())
637 const CaloHitList &caloHits(m_hierarchy.m_mcToHitsMap.at(pMCParticle));
638 allHits.insert(allHits.begin(), caloHits.begin(), caloHits.end());
641 if (!allParticles.empty())
643 Node *pNode{
new Node(m_hierarchy, allParticles, allHits, this->m_tier + 1)};
644 m_children.emplace_back(pNode);
652 return m_hierarchy.m_nodeToIdMap.at(
this);
659 const bool enoughHits{m_caloHits.size() >= m_hierarchy.m_recoCriteria.m_minHits};
662 bool enoughGoodViews{
false};
663 unsigned int nHitsU{0}, nHitsV{0}, nHitsW{0};
664 for (
const CaloHit *pCaloHit : m_caloHits)
666 switch (pCaloHit->GetHitType())
680 unsigned int nGoodViews{0};
681 if (nHitsU >= m_hierarchy.m_recoCriteria.m_minHitsForGoodView)
683 if (nHitsV >= m_hierarchy.m_recoCriteria.m_minHitsForGoodView)
685 if (nHitsW >= m_hierarchy.m_recoCriteria.m_minHitsForGoodView)
687 if (nGoodViews >= m_hierarchy.m_recoCriteria.m_minGoodViews)
689 enoughGoodViews =
true;
694 return enoughGoodViews;
723 for (
const Node *pChild : m_children)
724 str += pChild->ToString(prefix +
" ");
753 const unsigned int minHits,
const unsigned int minHitsForGoodView,
const unsigned int minGoodViews,
const bool removeNeutrons) :
783 PfoList primaries(primarySet.begin(), primarySet.end());
787 for (
const ParticleFlowObject *pPrimary : primaries)
789 PfoList allParticles;
793 for (
const ParticleFlowObject *pPfo : allParticles)
800 for (
const ParticleFlowObject *pPrimary : primaries)
802 PfoList allParticles;
804 const bool isShower{
pdg == E_MINUS};
809 allParticles.emplace_back(pPrimary);
812 for (
const ParticleFlowObject *pPfo : allParticles)
814 Node *pNode{
new Node(*
this, allParticles, allHits)};
819 const PfoList &children{pPrimary->GetDaughterPfoList()};
820 for (
const ParticleFlowObject *pChild : children)
821 pNode->FillHierarchy(pChild, foldParameters);
828 for (
const ParticleFlowObject *pPrimary : primaries)
830 PfoList allParticles{pPrimary};
832 for (
const ParticleFlowObject *pPfo : allParticles)
834 Node *pNode{
new Node(*
this, allParticles, allHits)};
837 const PfoList &children{pPrimary->GetDaughterPfoList()};
838 for (
const ParticleFlowObject *pChild : children)
851 nodeVector.emplace_back(pNode);
852 queue.emplace_back(pNode);
854 while (!queue.empty())
856 const NodeVector &children{queue.front()->GetChildren()};
858 for (
const Node *pChild : children)
860 nodeVector.emplace_back(pChild);
861 queue.emplace_back(pChild);
872 str += pNode->ToString(
"") +
"\n";
881 m_hierarchy(hierarchy),
886 m_pdg = pPfo->GetParticleId();
887 m_pfos.emplace_back(pPfo);
897 if (!pfoList.empty())
898 m_pdg = pfoList.front()->GetParticleId();
920 PfoList allParticles;
922 const bool isShower{
pdg == E_MINUS};
928 allParticles.emplace_back(pRoot);
931 for (
const ParticleFlowObject *pPfo : allParticles)
937 if (hasChildren || (!hasChildren && !allHits.empty()))
944 const PfoList &children{pRoot->GetDaughterPfoList()};
945 for (
const ParticleFlowObject *pChild : children)
946 pNode->FillHierarchy(pChild, foldParameters);
955 PfoList allParticles;
958 for (
const ParticleFlowObject *pPfo : allParticles)
991 str += pChild->ToString(prefix +
" ");
1017 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
1029 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
1031 const CaloHitList &recoHits{pReco->
GetCaloHits()};
1033 CaloHitVector intersection;
1034 std::set_intersection(mcHits.begin(), mcHits.end(), recoHits.begin(), recoHits.end(), std::back_inserter(intersection));
1036 return this->
GetPurity(intersection, recoHits, adcWeighted);
1046 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
1048 CaloHitList recoHits;
1049 for (
const CaloHit *pCaloHit : pReco->
GetCaloHits())
1050 if (pCaloHit->GetHitType() == view)
1051 recoHits.emplace_back(pCaloHit);
1054 if (pCaloHit->GetHitType() == view)
1055 mcHits.emplace_back(pCaloHit);
1057 CaloHitVector intersection;
1058 std::set_intersection(mcHits.begin(), mcHits.end(), recoHits.begin(), recoHits.end(), std::back_inserter(intersection));
1060 return this->
GetPurity(intersection, recoHits, adcWeighted);
1069 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
1071 const CaloHitList &recoHits{pReco->
GetCaloHits()};
1073 CaloHitVector intersection;
1074 std::set_intersection(mcHits.begin(), mcHits.end(), recoHits.begin(), recoHits.end(), std::back_inserter(intersection));
1086 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
1088 CaloHitList recoHits;
1089 for (
const CaloHit *pCaloHit : pReco->
GetCaloHits())
1090 if (pCaloHit->GetHitType() == view)
1091 recoHits.emplace_back(pCaloHit);
1094 if (pCaloHit->GetHitType() == view)
1095 mcHits.emplace_back(pCaloHit);
1097 CaloHitVector intersection;
1098 std::set_intersection(mcHits.begin(), mcHits.end(), recoHits.begin(), recoHits.end(), std::back_inserter(intersection));
1108 if (!intersection.empty())
1113 for (
const CaloHit *pCaloHit : recoHits)
1114 adcSum += pCaloHit->GetInputEnergy();
1115 if (adcSum > std::numeric_limits<float>::epsilon())
1117 for (
const CaloHit *pCaloHit : intersection)
1118 purity += pCaloHit->GetInputEnergy();
1124 purity = intersection.size() /
static_cast<float>(recoHits.size());
1135 float completeness{0.f};
1136 if (!intersection.empty())
1141 for (
const CaloHit *pCaloHit : mcHits)
1142 adcSum += pCaloHit->GetInputEnergy();
1143 if (adcSum > std::numeric_limits<float>::epsilon())
1145 for (
const CaloHit *pCaloHit : intersection)
1146 completeness += pCaloHit->GetInputEnergy();
1147 completeness /= adcSum;
1152 completeness = intersection.size() /
static_cast<float>(mcHits.size());
1156 return completeness;
1202 std::sort(mcNodes.begin(), mcNodes.end(),
1204 std::sort(recoNodes.begin(), recoNodes.end(),
1207 std::map<const MCHierarchy::Node *, MCMatches> mcToMatchMap;
1210 const CaloHitList &recoHits{pRecoNode->GetCaloHits()};
1212 size_t bestSharedHits{0};
1215 if (!pMCNode->IsReconstructable())
1217 const CaloHitList &mcHits{pMCNode->
GetCaloHits()};
1218 CaloHitVector intersection;
1219 std::set_intersection(mcHits.begin(), mcHits.end(), recoHits.begin(), recoHits.end(), std::back_inserter(intersection));
1221 if (!intersection.empty())
1223 const size_t sharedHits{intersection.size()};
1224 if (sharedHits > bestSharedHits)
1226 bestSharedHits = sharedHits;
1227 pBestNode = pMCNode;
1233 auto iter{mcToMatchMap.find(pBestNode)};
1234 if (iter != mcToMatchMap.end())
1237 match.
AddRecoMatch(pRecoNode, static_cast<int>(bestSharedHits));
1242 match.
AddRecoMatch(pRecoNode, static_cast<int>(bestSharedHits));
1243 mcToMatchMap.insert(std::make_pair(pBestNode, match));
1252 for (
auto [pMCNode,
matches] : mcToMatchMap)
1256 return lhs.
GetMC()->
GetCaloHits().size() > rhs.GetMC()->GetCaloHits().size();
1262 if (pMCNode->IsReconstructable() && mcToMatchMap.find(pMCNode) == mcToMatchMap.end())
1274 return static_cast<unsigned int>(
m_matches.size());
1281 unsigned int nNodes{0};
1285 if (!(pNode->IsCosmicRay() || pNode->IsTestBeamParticle()))
1296 unsigned int nNodes{0};
1300 if (pNode->IsCosmicRay())
1311 unsigned int nNodes{0};
1315 if (pNode->IsTestBeamParticle())
1326 unsigned int nNeutrinoMCParticles{this->
GetNNeutrinoMCNodes()}, nNeutrinoRecoParticles{0};
1327 unsigned int nCosmicMCParticles{this->
GetNCosmicRayMCNodes()}, nCosmicRecoParticles{0}, nCosmicRecoBTParticles{0};
1328 unsigned int nTestBeamMCParticles{this->
GetNTestBeamMCNodes()}, nTestBeamRecoParticles{0}, nTestBeamRecoBTParticles{0};
1329 std::cout <<
"=== Matches ===" <<
std::endl;
1333 const int pdg{pMCNode->GetParticleId()};
1334 const size_t mcHits{pMCNode->GetCaloHits().size()};
1335 const std::string tag{pMCNode->IsTestBeamParticle() ?
"(Beam) " : pMCNode->IsCosmicRay() ?
"(Cosmic) " :
""};
1341 const unsigned int recoHits{
static_cast<unsigned int>(pRecoNode->GetCaloHits().size())};
1342 const unsigned int sharedHits{match.GetSharedHits(pRecoNode)};
1343 const float purity{match.GetPurity(pRecoNode)};
1344 const float completeness{match.GetCompleteness(pRecoNode)};
1345 std::cout <<
" Matched " << sharedHits <<
" out of " << recoHits <<
" with purity " << purity <<
" and completeness " 1348 if (nodeVector.empty())
1349 std::cout <<
" Unmatched" << std::endl;
1351 if (pMCNode->IsTestBeamParticle())
1352 ++nTestBeamRecoParticles;
1353 else if (pMCNode->IsCosmicRay())
1354 ++nCosmicRecoParticles;
1356 ++nNeutrinoRecoParticles;
1361 std::cout <<
"Neutrino Interaction Summary:" <<
std::endl;
1363 if (nNeutrinoMCParticles)
1365 std::cout <<
"Matched final state particles: " << nNeutrinoRecoParticles <<
" of " << nNeutrinoMCParticles <<
" : " 1366 << (100 * nNeutrinoRecoParticles /
static_cast<float>(nNeutrinoMCParticles)) <<
"%" <<
std::endl;
1368 if (nCosmicMCParticles)
1370 std::cout <<
"Matched cosmics: " << nCosmicRecoParticles <<
" of " << nCosmicMCParticles <<
" : " 1371 << (100 * nCosmicRecoParticles /
static_cast<float>(nCosmicMCParticles)) <<
"%" <<
std::endl;
1376 std::cout <<
"Test Beam Interaction Summary:" <<
std::endl;
1378 if (nTestBeamMCParticles)
1380 std::cout <<
"Matched test beam particles: " << nTestBeamRecoParticles <<
" of " << nTestBeamMCParticles <<
" : " 1381 << (100 * nTestBeamRecoParticles /
static_cast<float>(nTestBeamMCParticles)) <<
"%" <<
std::endl;
1382 std::cout <<
"Loosely matched test beam particles: " << (nTestBeamRecoParticles + nTestBeamRecoBTParticles) <<
" of " << nTestBeamMCParticles
1383 <<
" : " << (100 * (nTestBeamRecoParticles + nTestBeamRecoBTParticles) /
static_cast<float>(nTestBeamMCParticles))
1386 if (nCosmicMCParticles)
1388 std::cout <<
"Matched cosmics: " << nCosmicRecoParticles <<
" of " << nCosmicMCParticles <<
" : " 1389 << (100 * nCosmicRecoParticles /
static_cast<float>(nCosmicMCParticles)) <<
"%" <<
std::endl;
1390 std::cout <<
"Loosely matched cosmics: " << (nCosmicRecoParticles + nCosmicRecoBTParticles) <<
" of " << nCosmicMCParticles <<
" : " 1391 << (100 * (nCosmicRecoParticles + nCosmicRecoBTParticles) /
static_cast<float>(nCosmicMCParticles)) <<
"%" <<
std::endl;
1404 hierarchy.
FillHierarchy(mcParticleList, caloHitList, foldParameters);
1418 matchInfo.
Match(mcHierarchy, recoHierarchy);
1426 const MCParticle *pRoot{
nullptr};
1427 for (
const MCParticle *pMCParticle : mcParticleList)
1433 primaries.insert(pPrimary);
1435 primaries.insert(pPrimary);
1437 catch (
const StatusCodeException &)
1440 pRoot = pMCParticle;
1441 else if (pMCParticle->GetParticleId() != 111 && pMCParticle->GetParticleId() < 1e9)
1442 std::cout <<
"LArHierarchyHelper::MCHierarchy::FillHierarchy: MC particle with PDG code " << pMCParticle->GetParticleId()
1443 <<
" at address " << pMCParticle <<
" has no associated primary particle" <<
std::endl;
1452 const ParticleFlowObject *pRoot{
nullptr};
1454 for (
const ParticleFlowObject *pPfo : pfoList)
1476 primaries.insert(pPfo);
1484 cosmicPfos.insert(pPfo);
1491 const PfoList &children{pRoot->GetDaughterPfoList()};
1492 for (
const ParticleFlowObject *pPrimary : children)
1493 primaries.insert(pPrimary);
1497 for (
const ParticleFlowObject *pPfo : cosmicPfos)
1498 primaries.insert(pPfo);
const pandora::MCParticle * m_pNeutrino
The incident neutrino, if it exists.
const pandora::CaloHitList & GetCaloHits() const
Retrieve the CaloHits associated with this node.
MCMatchesVector m_matches
The vector of good matches from MC to reco.
const unsigned int m_minHitsForGoodView
the minimum number of Hits for a good view
std::set< const pandora::MCParticle * > MCParticleSet
FoldingParameters()
Default constructor.
static bool SortByNHits(const pandora::ParticleFlowObject *const pLhs, const pandora::ParticleFlowObject *const pRhs)
Sort pfos by number of constituent hits.
const MCHierarchy::Node * m_pMCParticle
MC node associated with any matches.
bool m_foldToTier
Whether or not to apply folding based on particle tier.
int m_tier
If folding to a tier, the tier to be combined with its child particles.
RecoHierarchy::NodeVector m_recoNodes
Matched reco nodes.
void CollectContinuations(const pandora::MCParticle *pRoot, pandora::MCParticleList &continuingParticles, pandora::MCParticleList &childParticles, const float cosAngleTolerance) const
Identify downstream particles that represent continuations of the parent particle from a reconstructi...
MatchInfo()
Default constructor.
const std::string ToString() const
Produce a string representation of the hierarchy.
std::vector< const Node * > NodeVector
pandora::IntVector m_sharedHits
Number of shared hits for each match.
const std::string ToString(const std::string &prefix) const
Produce a string representation of the hierarchy.
std::map< const pandora::MCParticle *, pandora::CaloHitList > m_mcToHitsMap
The map between MC particles and calo hits.
MCHierarchy()
Default constructor.
ReconstructabilityCriteria()
Default constructor.
static int GetHierarchyTier(const pandora::MCParticle *const pMCParticle)
Determine the position in the hierarchy for the MCParticle.
const RecoHierarchy & m_hierarchy
The parent reco hierarchy.
static const pandora::MCParticle * GetPrimaryMCParticle(const pandora::MCParticle *const pMCParticle)
Get the primary parent mc particle.
int m_pdg
The particle ID (track = muon, shower = electron)
void GetFlattenedNodes(NodeVector &nodeVector) const
Retrieve a flat vector of the ndoes in the hierarchy.
void FillHierarchy(const pandora::MCParticleList &mcParticleList, const pandora::CaloHitList &caloHitList, const FoldingParameters &foldParameters)
Creates an MC hierarchy representation. Without folding this will be a mirror image of the standard M...
QualityCuts m_qualityCuts
The quality cuts to be applied to matches.
virtual ~RecoHierarchy()
Destructor.
const pandora::CaloHitList & GetCaloHits() const
Retrieve the CaloHits associated with this node.
static void MatchHierarchies(const MCHierarchy &mcHierarchy, const RecoHierarchy &recoHierarchy, MatchInfo &matchInfo)
Finds the matches between reconstructed and MC hierarchies.
const pandora::ParticleFlowObject * m_pNeutrino
The incident neutrino, if it exists.
static const pandora::ParticleFlowObject * GetRecoPrimaries(const pandora::PfoList &pfoList, PfoSet &primaries)
Retrieves the primary PFOs from a list and returns the root (neutrino) for hierarchy, if it exists.
Node(const RecoHierarchy &hierarchy, const pandora::ParticleFlowObject *pPfo)
Create a node with a primary PFO.
unsigned int GetNTestBeamMCNodes() const
Retrieve the number of test beam derived MC nodes available to match.
Q_EXPORT QTSManip setprecision(int p)
unsigned int GetNNeutrinoMCNodes() const
Retrieve the number of neutrino interaction derived MC nodes available to match.
static void GetAllCaloHits(const pandora::ParticleFlowObject *pPfo, pandora::CaloHitList &caloHitList)
Get a list of all calo hits (including isolated) of all types from a given pfo.
bool IsQuality(const QualityCuts &qualityCuts) const
Get whether this match passes quality cuts.
const MCHierarchy::Node * GetMC() const
Retrieve the MC node.
unsigned int GetNMCNodes() const
Retrieve the number of MC nodes available to match.
MCMatches(const MCHierarchy::Node *pMCParticle)
Constructor.
void Match(const MCHierarchy &mcHierarchy, const RecoHierarchy &recoHierarchy)
Match the nodes in the MC and reco hierarchies.
static bool SortByMomentum(const pandora::MCParticle *const pLhs, const pandora::MCParticle *const pRhs)
Sort mc particles by their momentum.
void FillHierarchy(const pandora::PfoList &pfoList, const FoldingParameters &foldParameters)
Creates a reconstructed hierarchy representation. Without folding this will be a mirror image of the ...
virtual ~Node()
Destructor.
static bool IsCosmicRay(const pandora::MCParticle *const pMCParticle)
Return true if passed a primary cosmic ray MCParticle.
static bool IsInelasticScatter(const pandora::MCParticle *const pMCParticle)
Check whether or not an MC particle came from an inelastic scattering process.
bool IsNeutrinoHierarchy() const
Check if this is a neutrino hierarchy.
static void FillRecoHierarchy(const pandora::PfoList &pfoList, const FoldingParameters &foldParameters, RecoHierarchy &hierarchy)
Fill a reconstructed hierarchy based on the specified folding criteria (see RecoHierarchy::FillHierar...
std::vector< const Node * > NodeVector
static int GetHierarchyTier(const pandora::ParticleFlowObject *const pPfo)
Determine the position in the hierarchy for the MCParticle.
static bool IsTestBeam(const pandora::ParticleFlowObject *const pPfo)
Whether a pfo is a test beam particle.
static const pandora::ParticleFlowObject * GetParentPfo(const pandora::ParticleFlowObject *const pPfo)
Get the primary parent pfo.
const pandora::MCParticle * GetNeutrino() const
Retrieve the neutrino at the root of the hierarchy if it exists.
void InterpretHierarchy(const pandora::MCParticle *const pRoot, pandora::MCParticleList &leadingParticles, pandora::MCParticleList &childParticles, const float cosAngleTolerance) const
Interpret the hierarchy below a particular particle to determine if and how it should be folded...
const float m_minPurity
The minimum purity for a match to be considered good.
static bool IsBeamParticle(const pandora::MCParticle *const pMCParticle)
Returns true if passed a primary beam MCParticle.
bool IsReconstructable() const
Return whether or not this node should be considered reconstructable.
ReconstructabilityCriteria class.
bool IsCosmicRay() const
Check if this is a cosmic ray particle.
std::list< const Node * > NodeList
void FillHierarchy(const pandora::ParticleFlowObject *pRoot, const FoldingParameters &foldParameters)
Recursively fill the hierarchy based on the criteria established for this RecoHierarchy.
unsigned int GetSharedHits(const RecoHierarchy::Node *pReco) const
Retrieve the number of shared hits in the match.
float GetPurity(const RecoHierarchy::Node *pReco, const bool adcWeighted=false) const
Retrieve the purity of the match.
static bool IsTriggeredBeamParticle(const pandora::MCParticle *const pMCParticle)
Returns true if passed a primary triggered beam MCParticle.
pandora::PfoList m_pfos
The list of PFOs of which this node is composed.
const std::string ToString(const std::string &prefix) const
Produce a string representation of the hierarchy.
static int max(int a, int b)
float m_cosAngleTolerance
Cosine of the maximum angle at which topologies can be considered continuous.
virtual ~MCHierarchy()
Destructor.
NodeVector m_rootNodes
The leading nodes (e.g. primary particles, cosmic rays, ...)
static bool IsNeutrino(const pandora::ParticleFlowObject *const pPfo)
Whether a pfo is a neutrino or (antineutrino)
NodeVector m_children
The child nodes of this node.
virtual ~Node()
Destructor.
bool m_foldDynamic
Whether or not to use process and topological information to make folding decisions.
const RecoHierarchy::NodeVector & GetUnmatchedReco() const
Retrieve the vector of unmatched reco nodes.
const pandora::PfoList & GetRecoParticles() const
Retrieve the PFOs associated with this node.
static bool AreTopologicallyContinuous(const pandora::MCParticle *const pMCParent, const pandora::MCParticle *const pMCChild, const float cosAngleTolerance)
Determine if two MC particles are topologically continuous within a given tolerance. If the parent does not travel any distance, a travelling parent is sought and the comparison made between this and the child. If no travelling parent can be found, the particles are treated as continuous.
ReconstructabilityCriteria m_recoCriteria
The criteria used to determine if the node is reconstructable.
void Print(const MCHierarchy &mcHierarchy) const
Prints information about which reco nodes are matched to the MC nodes, information about hit sharing...
bool m_foldToLeadingShowers
Whether or not to fold shower children to the leading shower particle.
const pandora::ParticleFlowObject * GetNeutrino() const
Retrieve the neutrino at the root of the hierarchy if it exists.
const bool m_removeNeutrons
whether to remove neutrons and their downstream particles
Header file for the lar hierarchy helper class.
QualityCuts()
Default constructor.
void GetFlattenedNodes(NodeVector &nodeVector) const
Retrieve a flat vector of the nodes in the hierarchy.
const std::string ToString() const
Produce a string representation of the hierarchy.
pandora::CaloHitList m_caloHits
The list of calo hits of which this node is composed.
bool IsReconstructable(const pandora::MCParticle *pMCParticle) const
Checks if an individual particle meets reconstructability criteria.
void SetLeadingLepton()
Tags the particle as the leading lepton.
Node(MCHierarchy &hierarchy, const pandora::MCParticle *pMCParticle, const int tier=1)
Create a node with a primary MC particle.
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...
static void FillMCHierarchy(const pandora::MCParticleList &mcParticleList, const pandora::CaloHitList &caloHitList, const FoldingParameters &foldParameters, MCHierarchy &hierarchy)
Fill an MC hierarchy based on the specified folding criteria (see MCHierarchy::FillHierarchy for deta...
cet::LibraryManager dummy("noplugin")
std::list< const Node * > NodeList
int GetParticleId() const
Retrieve the PDG code for the leading particle in this node Note, for reco objects the PDG codes repr...
bool IsTestBeamHierarchy() const
Check if this is a test beam hierarchy.
void FillFlat(const pandora::MCParticle *pRoot)
Fill this node by folding all descendent particles to this node.
int GetId() const
Retrieve the unique ID of this node.
int m_nextNodeId
The ID to use for the next node.
const unsigned int m_minHits
the minimum number of primary good Hits
RecoHierarchy::NodeVector m_unmatchedReco
The vector of unmatched reco nodes.
const unsigned int m_minGoodViews
the minimum number of primary good views
void RegisterNode(const Node *pNode)
Register a node with the hierarchy.
static void GetAllDescendentMCParticles(const pandora::MCParticle *const pMCParticle, pandora::MCParticleList &descendentMCParticleList)
Get all descendent mc particles.
float GetCompleteness(const RecoHierarchy::Node *pReco, const bool adcWeighted=false) const
Retrieve the completeness of the match.
RecoHierarchy()
Default constructor.
const pandora::MCParticle * m_pMCNeutrino
The parent neutrino if it exists.
void FillHierarchy(const pandora::MCParticle *pRoot, const FoldingParameters &foldParameters)
Recursively fill the hierarchy based on the criteria established for this MCHierarchy.
bool IsTestBeamParticle() const
Check if this is a test beam particle.
std::string to_string(ModuleType const mt)
std::set< const pandora::ParticleFlowObject * > PfoSet
const pandora::ParticleFlowObject * m_pRecoNeutrino
The parent neutrino if it exists.
const float m_minCompleteness
The minimum completeness for a match to be considered good.
static bool IsElasticScatter(const pandora::MCParticle *const pMCParticle)
Check whether or not an MC particle came from an elastic scattering process.
static const pandora::MCParticle * GetMCPrimaries(const pandora::MCParticleList &mcParticleList, MCParticleSet &primaries)
Retrieves the primary MC particles from a list and returns the root (neutrino) for hierarchy...
static bool IsNeutrino(const pandora::MCParticle *const pMCParticle)
Whether a mc particle is a neutrino or antineutrino.
void FillFlat(const pandora::ParticleFlowObject *pRoot)
Fill this node by folding all descendent particles to this node.
std::map< const Node *, int > m_nodeToIdMap
A map from nodes to unique ids.
QTextStream & endl(QTextStream &s)
NodeVector m_rootNodes
The leading nodes (e.g. primary particles, cosmic rays, ...)
unsigned int GetNCosmicRayMCNodes() const
Retrieve the number of cosmic ray derived MC nodes available to match.
void AddRecoMatch(const RecoHierarchy::Node *pReco, const int nSharedHits)
Add a reconstructed node as a match for this MC node.