9 #include "Pandora/AlgorithmHeaders.h" 18 HierarchyMonitoringAlgorithm::HierarchyMonitoringAlgorithm() :
20 m_visualizeReco(false),
21 m_visualizeDistinct(false),
22 m_visualizeProcess{
false},
42 PANDORA_MONITORING_API(SaveTree(this->GetPandora(),
"processes",
m_rootFileName,
"UPDATE"));
51 PANDORA_MONITORING_API(
54 const CaloHitList *pCaloHitList(
nullptr);
55 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*
this,
m_caloHitListName, pCaloHitList));
56 const MCParticleList *pMCParticleList(
nullptr);
57 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*
this, pMCParticleList));
71 std::cout << mcHierarchy.
ToString() << std::endl;
75 const PfoList *pPfoList(
nullptr);
76 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*
this,
m_pfoListName, pPfoList));
78 std::cout << recoHierarchy.
ToString() << std::endl;
85 matchInfo.
Print(mcHierarchy);
86 this->VisualizeMatches(matchInfo);
93 this->VisualizeMCDistinct(mcHierarchy);
95 this->VisualizeMCProcess(mcHierarchy);
97 this->VisualizeMC(mcHierarchy);
100 this->VisualizeReco(recoHierarchy);
104 return STATUS_CODE_SUCCESS;
111 const std::map<int, const std::string> keys = {{13,
"mu"}, {11,
"e"}, {22,
"gamma"}, {321,
"kaon"}, {211,
"pi"}, {2212,
"p"}};
112 const std::map<std::string, int> colors = {{
"mu", 5}, {
"e", 2}, {
"gamma", 9}, {
"kaon", 1}, {
"pi", 3}, {
"p", 4}, {
"other", 14}};
114 MCParticleList rootMCParticles;
116 for (
const MCParticle *
const pRoot : rootMCParticles)
121 bool depositedHits{
false};
125 std::string key(
"other");
126 const int pdg{
std::abs(pNode->GetParticleId())};
127 if (keys.find(pdg) != keys.end())
130 CaloHitList uHits, vHits, wHits;
131 this->FillHitLists(pNode->GetCaloHits(), uHits, vHits, wHits);
132 if (!(uHits.empty() && vHits.empty() && wHits.empty()))
134 depositedHits =
true;
136 this->Visualize(uHits,
"u_" + suffix, colors.at(key));
137 this->Visualize(vHits,
"v_" + suffix, colors.at(key));
138 this->Visualize(wHits,
"w_" + suffix, colors.at(key));
144 PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
153 const std::map<int, const std::string> keys = {{13,
"mu"}, {11,
"e"}, {22,
"gamma"}, {321,
"kaon"}, {211,
"pi"}, {2212,
"p"}};
154 const int nColours{9};
155 const int colors[nColours] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
157 MCParticleList rootMCParticles;
159 for (
const MCParticle *
const pRoot : rootMCParticles)
164 bool depositedHits{
false};
165 int nodeIdx{0}, colorIdx{0};
168 std::string key(
"other");
169 const int pdg{
std::abs(pNode->GetParticleId())};
170 if (keys.find(pdg) != keys.end())
173 CaloHitList uHits, vHits, wHits;
174 this->FillHitLists(pNode->GetCaloHits(), uHits, vHits, wHits);
175 if (!(uHits.empty() && vHits.empty() && wHits.empty()))
177 depositedHits =
true;
179 this->Visualize(uHits,
"u_" + suffix, colors[colorIdx]);
180 this->Visualize(vHits,
"v_" + suffix, colors[colorIdx]);
181 this->Visualize(wHits,
"w_" + suffix, colors[colorIdx]);
182 colorIdx = (colorIdx + 1) >= nColours ? 0 : colorIdx + 1;
189 PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
199 {
MC_PROC_PRIMARY,
"primary"}, {
MC_PROC_COMPT,
"compt"}, {
MC_PROC_PHOT,
"phot"}, {
MC_PROC_ANNIHIL,
"annihil"}, {
MC_PROC_E_IONI,
"ioni"},
215 const std::map<std::string, int> categoryToColorMap = {{
"invisible", 0}, {
"primary", 1}, {
"compt", 2}, {
"phot", 3}, {
"annihil", 4},
216 {
"ioni", 5}, {
"brem", 6}, {
"conv", 3}, {
"capture", 6}, {
"inelastic", 9}, {
"elastic", 8}, {
"decay", 7}, {
"coulomb", 9},
217 {
"pair_prod", 4}, {
"transport", 1}, {
"rayleigh", 9}, {
"kill", 2}, {
"nuclear", 5}, {
"background", 7}};
219 MCParticleList rootMCParticles;
221 for (
const MCParticle *
const pRoot : rootMCParticles)
233 const std::string category{procToCategoryMap.at(process)};
234 const int pdg{
std::abs(pNode->GetParticleId())};
237 CaloHitList uHits, vHits, wHits;
238 this->FillHitLists(pNode->GetCaloHits(), uHits, vHits, wHits);
243 const MCParticleList &parentList{pMC->GetParentList()};
244 if (!parentList.empty())
246 const MCParticle *pParent{parentList.front()};
247 const int parentPdg{
std::abs(pParent->GetParticleId())};
252 this->Visualize(uHits,
"U " + suffix, categoryToColorMap.at(category));
253 this->Visualize(vHits,
"V " + suffix, categoryToColorMap.at(category));
254 this->Visualize(wHits,
"W " + suffix, categoryToColorMap.at(category));
257 const int proc{
static_cast<int>(process)};
258 const float mom{pMC->GetMomentum().GetMagnitude()};
261 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
"processes",
"process", proc));
262 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
"processes",
"momentum", mom));
263 PANDORA_MONITORING_API(FillTree(this->GetPandora(),
"processes"));
267 PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
275 const int nColors{7};
276 const int colors[nColors] = {5, 2, 9, 1, 3, 4, 14};
280 for (
const ParticleFlowObject *
const pRoot : rootPfos)
289 CaloHitList uHits, vHits, wHits;
290 this->FillHitLists(pNode->GetCaloHits(), uHits, vHits, wHits);
291 const int pdg{pNode->GetParticleId()};
292 const std::string key{pdg == MU_MINUS ?
"T" : pdg == E_MINUS ?
"S" :
"?"};
294 this->Visualize(uHits,
"u_" + suffix, colors[colorIdx]);
295 this->Visualize(vHits,
"v_" + suffix, colors[colorIdx]);
296 this->Visualize(wHits,
"w_" + suffix, colors[colorIdx]);
297 colorIdx = (colorIdx + 1) >= nColors ? 0 : colorIdx + 1;
301 PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
309 const int nColors{8};
310 const int colors[nColors] = {2, 3, 4, 5, 6, 7, 8, 9};
311 MCParticleList rootMCParticles;
317 std::map<const LArHierarchyHelper::RecoHierarchy::Node *, int> recoNodeToColorMap;
318 std::map<const LArHierarchyHelper::RecoHierarchy::Node *, int> recoNodeToIdMap;
319 std::map<const ParticleFlowObject *, int> recoRootToSliceMap;
320 std::map<const LArHierarchyHelper::RecoHierarchy::Node *, const ParticleFlowObject *> recoNodeToRootMap;
321 std::map<const LArHierarchyHelper::MCHierarchy::Node *, int> mcNodeToIdMap;
322 int colorIdx{0}, recoIdx{0}, sliceIdx{0}, mcIdx{0};
323 for (
const ParticleFlowObject *
const pRoot : rootPfos)
325 recoRootToSliceMap[pRoot] = sliceIdx;
327 recoHierarchy.GetFlattenedNodes(pRoot, nodes);
330 recoNodeToColorMap[pNode] = colors[colorIdx];
331 recoNodeToIdMap[pNode] = recoIdx;
332 recoNodeToRootMap[pNode] = pRoot;
337 if (colorIdx >= nColors)
340 for (
const MCParticle *
const pRoot : rootMCParticles)
342 bool isReconstructable{
false};
344 mcHierarchy.GetFlattenedNodes(pRoot, nodes);
349 const MCParticle *pMC{pNode->GetLeadingMCParticle()};
352 const int pdg{
std::abs(pNode->GetParticleId())};
354 CaloHitList uHits, vHits, wHits;
355 this->FillHitLists(pNode->GetCaloHits(), uHits, vHits, wHits);
357 this->Visualize(uHits,
"U " + suffix, 1);
358 this->Visualize(vHits,
"V " + suffix, 1);
359 this->Visualize(wHits,
"W " + suffix, 1);
360 if (!(uHits.empty() && vHits.empty() && wHits.empty()))
361 isReconstructable =
true;
362 mcNodeToIdMap[pNode] = mcIdx;
368 std::map<const LArHierarchyHelper::RecoHierarchy::Node *, bool> matchedReco;
369 std::map<const ParticleFlowObject *, bool> matchedRoots;
370 for (
const auto &match : matches)
375 CaloHitList uHits, vHits, wHits;
376 const float purity{match.GetPurity(pReco,
true)};
377 const float completeness{match.GetCompleteness(pReco,
true)};
378 const std::string purityStr{this->
ToStringSF(purity)};
379 const std::string completenessStr{this->
ToStringSF(completeness)};
381 this->FillHitLists(pReco->GetCaloHits(), uHits, vHits, wHits);
382 const std::string suffix{
"Reco - Slice " +
std::to_string(recoRootToSliceMap[recoNodeToRootMap[pReco]]) +
" ID " +
385 if (purity >= quality.m_minPurity && completeness >= quality.m_minCompleteness)
387 this->Visualize(uHits,
"U " + suffix +
"(" + purityStr +
"," + completenessStr +
")", recoNodeToColorMap[pReco]);
388 this->Visualize(vHits,
"V " + suffix +
"(" + purityStr +
"," + completenessStr +
")", recoNodeToColorMap[pReco]);
389 this->Visualize(wHits,
"W " + suffix +
"(" + purityStr +
"," + completenessStr +
")", recoNodeToColorMap[pReco]);
391 matchedReco[pReco] =
true;
392 matchedRoots[recoNodeToRootMap[pReco]] =
true;
399 matchedReco[pReco] =
true;
400 matchedRoots[recoNodeToRootMap[pReco]] =
true;
402 this->Visualize(uHits,
"U " + suffix +
"(" + purityStr +
"," + completenessStr +
")", 14);
403 this->Visualize(vHits,
"V " + suffix +
"(" + purityStr +
"," + completenessStr +
")", 14);
404 this->Visualize(wHits,
"W " + suffix +
"(" + purityStr +
"," + completenessStr +
")", 14);
411 for (
const auto [pRecoRoot, val] : matchedRoots)
415 recoHierarchy.GetFlattenedNodes(pRecoRoot, recoNodes);
418 if (matchedReco.find(pNode) == matchedReco.end())
420 CaloHitList uHits, vHits, wHits;
421 this->FillHitLists(pNode->GetCaloHits(), uHits, vHits, wHits);
422 const std::string suffix{
"Reco - Slice " +
std::to_string(recoRootToSliceMap[recoNodeToRootMap[pNode]]) +
" ID " +
424 this->Visualize(uHits,
"U " + suffix, 14);
425 this->Visualize(vHits,
"V " + suffix, 14);
426 this->Visualize(wHits,
"W " + suffix, 14);
431 if (isReconstructable)
433 PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
440 void HierarchyMonitoringAlgorithm::Visualize(
const CaloHitList &
hits,
const std::string &label,
const int color)
const 446 PANDORA_MONITORING_API(VisualizeCaloHits(this->GetPandora(), &hits, label, static_cast<Color>(color)));
452 void HierarchyMonitoringAlgorithm::FillHitLists(
const CaloHitList &hits, CaloHitList &uHits, CaloHitList &vHits, CaloHitList &wHits)
const 454 for (
const CaloHit *pCaloHit : hits)
456 const HitType view{pCaloHit->GetHitType()};
457 if (view == HitType::TPC_VIEW_U)
458 uHits.emplace_back(pCaloHit);
459 else if (view == HitType::TPC_VIEW_V)
460 vHits.emplace_back(pCaloHit);
461 else if (view == HitType::TPC_VIEW_W)
462 wHits.emplace_back(pCaloHit);
471 std::ostringstream out;
473 out << std::fixed << val;
481 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"CaloHitListName",
m_caloHitListName));
484 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"PfoListName",
m_pfoListName));
487 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"RootFileName",
m_rootFileName));
488 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"VisualizeMC",
m_visualizeMC));
489 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"VisualizeReco",
m_visualizeReco));
490 PANDORA_RETURN_RESULT_IF_AND_IF(
491 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"VisualizeDistinct",
m_visualizeDistinct));
492 PANDORA_RETURN_RESULT_IF_AND_IF(
493 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"VisualizeProcess",
m_visualizeProcess));
494 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"PerformMatching",
m_match));
495 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"CollectionOnly",
m_collectionOnly));
496 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"FoldToPrimaries",
m_foldToPrimaries));
497 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"FoldDynamic",
m_foldDynamic));
500 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinPurity",
m_minPurity));
501 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinCompleteness",
m_minCompleteness));
502 PANDORA_RETURN_RESULT_IF_AND_IF(
503 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinMatchCompleteness",
m_minMatchCompleteness));
504 PANDORA_RETURN_RESULT_IF_AND_IF(
505 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"TransparencyThresholdE",
m_transparencyThresholdE));
506 PANDORA_RETURN_RESULT_IF_AND_IF(
507 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"EnergyScaleThresholdE",
m_energyScaleThresholdE));
508 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"ScalingFactor",
m_scalingFactor));
510 return STATUS_CODE_SUCCESS;
void GetRootMCParticles(pandora::MCParticleList &rootMCParticles) const
Retrieve the root MC particles of the interaction hierarchies.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
const MCMatchesVector & GetMatches(const pandora::MCParticle *const pRoot) const
Retrieve the vector of matches (this will include null matches - i.e. MC nodes with no corresponding ...
void GetFlattenedNodes(const pandora::MCParticle *const pRoot, NodeVector &nodeVector) const
Retrieve a flat vector of the ndoes in the hierarchy.
const RecoHierarchy & GetRecoHierarchy() const
Retrieve the reco hierarchy used for the matching.
bool m_foldToTier
Whether or not to apply folding based on particle tier.
std::string m_pfoListName
Name of input PFO list.
bool m_visualizeMC
Whether or not to visualize the MC nodes.
const std::string ToString() const
Produce a string representation of the hierarchy.
std::vector< const Node * > NodeVector
void GetRootMCParticles(pandora::MCParticleList &rootMCParticles) const
Retrieve the root MC particles of the interaction hierarchies.
MCProcess GetProcess() const
Get the process.
bool m_visualizeProcess
If true, allocate colours based on the MC process.
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::string ToStringSF(const float val, const int sf=3) const
static int GetHierarchyTier(const pandora::MCParticle *const pMCParticle)
Determine the position in the hierarchy for the MCParticle.
float m_scalingFactor
TEve works with [cm], Pandora usually works with [mm] (but LArContent went with cm too) ...
bool m_visualizeReco
Whether or not to visualize the reco nodes.
static void MatchHierarchies(MatchInfo &matchInfo)
Finds the matches between reconstructed and MC hierarchies.
float m_minCompleteness
The minimum completeness for a match to be considered good.
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...
bool m_foldToPrimaries
Whether or not to fold everything back to primaries.
std::vector< const Node * > NodeVector
float m_minPurity
The minimum purity for a match to be considered good.
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
pandora::StatusCode Run()
ReconstructabilityCriteria class.
std::string m_rootFileName
Name of the output ROOT file (optional)
Header file for the particle visualisation algorithm.
float m_minMatchCompleteness
The minimum completeness at which to a PFO should be considered matching at all.
const QualityCuts & GetQualityCuts() const
Retrieve the quality cuts for matching.
std::string m_caloHitListName
Name of input calo hit list.
bool m_foldDynamic
Whether or not to use process and topological information to make folding decisions.
bool m_match
Whether or not to visualize the reco to MC matches.
void Print(const MCHierarchy &mcHierarchy) const
Prints information about which reco nodes are matched to the MC nodes, information about hit sharing...
std::size_t color(std::string const &procname)
const std::string ToString() const
Produce a string representation of the hierarchy.
virtual ~HierarchyMonitoringAlgorithm()
std::vector< MCMatches > MCMatchesVector
const MCHierarchy & GetMCHierarchy() const
Retrieve the MC hierarchy used for the matching.
void GetRootPfos(pandora::PfoList &rootPfos) const
Retrieve the root particle flow objects of the interaction hierarchies.
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...
bool m_collectionOnly
Limit display to the collection plane only.
void GetFlattenedNodes(const pandora::ParticleFlowObject *const pRoot, NodeVector &nodeVector) const
Retrieve a flat vector of the nodes in the hierarchy.
float m_transparencyThresholdE
Cell energy for which transparency is saturated (0%, fully opaque)
bool m_foldDynamic
Whether or not to fold based on process information.
float m_energyScaleThresholdE
Cell energy for which color is at top end of continous color palette.
bool m_visualizeDistinct
If true, allocate colours without consideration of particle id.