IsolatedClusterMopUpAlgorithm.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArTwoDReco/LArClusterMopUp/IsolatedClusterMopUpAlgorithm.cc
3  *
4  * @brief Implementation of the isolated cluster mop up algorithm class.
5  *
6  * $Log: $
7  */
8 
9 #include "Pandora/AlgorithmHeaders.h"
10 
12 
14 
16 
17 using namespace pandora;
18 
19 namespace lar_content
20 {
21 
22 IsolatedClusterMopUpAlgorithm::IsolatedClusterMopUpAlgorithm() :
23  m_maxCaloHitsInCluster(20),
24  m_maxHitClusterDistance(5.f),
25  m_addHitsAsIsolated(true)
26 {
27  // ATTN Default value differs from base class
29 }
30 
31 //------------------------------------------------------------------------------------------------------------------------------------------
32 
33 void IsolatedClusterMopUpAlgorithm::ClusterMopUp(const ClusterList &pfoClusters, const ClusterList &remnantClusters) const
34 {
35  CaloHitList caloHitList;
36  this->DissolveClustersToHits(remnantClusters, caloHitList);
37 
38  // ATTN remnantClusters now contains dangling pointers
39  CaloHitToClusterMap caloHitToClusterMap;
40  this->GetCaloHitToClusterMap(caloHitList, pfoClusters, caloHitToClusterMap);
41 
42  CaloHitList sortedCaloHitList;
43  for (const auto &mapEntry : caloHitToClusterMap)
44  sortedCaloHitList.push_back(mapEntry.first);
45  sortedCaloHitList.sort(LArClusterHelper::SortHitsByPosition);
46 
47  for (const CaloHit *pCaloHit : sortedCaloHitList)
48  {
50  {
51  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddIsolatedToCluster(*this, caloHitToClusterMap.at(pCaloHit), pCaloHit));
52  }
53  else
54  {
55  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*this, caloHitToClusterMap.at(pCaloHit), pCaloHit));
56  }
57  }
58 }
59 
60 //------------------------------------------------------------------------------------------------------------------------------------------
61 
62 void IsolatedClusterMopUpAlgorithm::DissolveClustersToHits(const ClusterList &clusterList, CaloHitList &caloHitList) const
63 {
64  for (const Cluster *const pRemnantCluster : clusterList)
65  {
66  if (pRemnantCluster->GetNCaloHits() < m_maxCaloHitsInCluster)
67  {
68  const std::string listNameR(this->GetListName(pRemnantCluster));
69  pRemnantCluster->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
70  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete(*this, pRemnantCluster, listNameR));
71  }
72  }
73 }
74 
75 //------------------------------------------------------------------------------------------------------------------------------------------
76 
78  const CaloHitList &caloHitList, const ClusterList &clusterList, CaloHitToClusterMap &caloHitToClusterMap) const
79 {
80  CaloHitList allCaloHits;
81  CaloHitToClusterMap hitToParentClusterMap;
82 
83  for (const Cluster *const pCluster : clusterList)
84  {
85  CaloHitList daughterHits;
86  pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
87  allCaloHits.insert(allCaloHits.end(), daughterHits.begin(), daughterHits.end());
88 
89  for (const CaloHit *const pCaloHit : daughterHits)
90  (void)hitToParentClusterMap.insert(CaloHitToClusterMap::value_type(pCaloHit, pCluster));
91  }
92 
93  HitKDTree2D kdTree;
94  HitKDNode2DList hitKDNode2DList;
95 
96  KDTreeBox hitsBoundingRegion2D(fill_and_bound_2d_kd_tree(allCaloHits, hitKDNode2DList));
97  kdTree.build(hitKDNode2DList, hitsBoundingRegion2D);
98 
99  for (const CaloHit *const pCaloHit : caloHitList)
100  {
101  if (!PandoraContentApi::IsAvailable(*this, pCaloHit))
102  throw StatusCodeException(STATUS_CODE_FAILURE);
103 
104  const HitKDNode2D *pResultHit(nullptr);
105  float resultDistance(std::numeric_limits<float>::max());
106  const HitKDNode2D targetHit(pCaloHit, pCaloHit->GetPositionVector().GetX(), pCaloHit->GetPositionVector().GetZ());
107  kdTree.findNearestNeighbour(targetHit, pResultHit, resultDistance);
108 
109  if (pResultHit && (resultDistance < m_maxHitClusterDistance))
110  (void)caloHitToClusterMap.insert(CaloHitToClusterMap::value_type(pCaloHit, hitToParentClusterMap.at(pResultHit->data)));
111  }
112 }
113 
114 //------------------------------------------------------------------------------------------------------------------------------------------
115 
116 StatusCode IsolatedClusterMopUpAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
117 {
118  PANDORA_RETURN_RESULT_IF_AND_IF(
119  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxCaloHitsInCluster", m_maxCaloHitsInCluster));
120 
121  PANDORA_RETURN_RESULT_IF_AND_IF(
122  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxHitClusterDistance", m_maxHitClusterDistance));
123 
124  PANDORA_RETURN_RESULT_IF_AND_IF(
125  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "AddHitsAsIsolated", m_addHitsAsIsolated));
126 
127  return ClusterMopUpBaseAlgorithm::ReadSettings(xmlHandle);
128 }
129 
130 } // namespace lar_content
Header file for the kd tree linker algo template class.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
void ClusterMopUp(const pandora::ClusterList &pfoClusters, const pandora::ClusterList &remnantClusters) const
Cluster mop up for a single view. This function is responsible for instructing pandora to make cluste...
std::string string
Definition: nybbler.cc:12
std::unordered_map< const pandora::CaloHit *, const pandora::Cluster * > CaloHitToClusterMap
Box structure used to define 2D field. It&#39;s used in KDTree building step to divide the detector space...
bool m_excludePfosContainingTracks
Whether to exclude any pfos containing clusters flagged as fixed tracks.
unsigned int m_maxCaloHitsInCluster
The maximum number of hits in a cluster to be dissolved.
void DissolveClustersToHits(const pandora::ClusterList &clusterList, pandora::CaloHitList &caloHitList) const
Examine a list of clusters, identify and delete remnants; receive the list of newly available hits...
void findNearestNeighbour(const KDTreeNodeInfoT< DATA, DIM > &point, const KDTreeNodeInfoT< DATA, DIM > *&result, float &distance)
findNearestNeighbour
Data stored in each KDTree node. The dim1/dim2 fields are usually the duplication of some PFRecHit va...
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
const std::string GetListName(const T *const pT) const
Find the name of the list hosting a specific object.
bool m_addHitsAsIsolated
Whether to add hits to clusters as "isolated" (don&#39;t contribute to spatial properties) ...
static bool SortHitsByPosition(const pandora::CaloHit *const pLhs, const pandora::CaloHit *const pRhs)
Sort calo hits by their position (use Z, followed by X, followed by Y)
Header file for the cluster helper class.
void build(std::vector< KDTreeNodeInfoT< DATA, DIM >> &eltList, const KDTreeBoxT< DIM > &region)
Build the KD tree from the "eltList" in the space define by "region".
static int max(int a, int b)
Header file for the isolated cluster mop up algorithm class.
float m_maxHitClusterDistance
The maximum hit to cluster distance for isolated hit merging.
KDTreeBox fill_and_bound_2d_kd_tree(const MANAGED_CONTAINER< const T * > &points, std::vector< KDTreeNodeInfoT< const T *, 2 >> &nodes)
fill_and_bound_2d_kd_tree
void GetCaloHitToClusterMap(const pandora::CaloHitList &caloHitList, const pandora::ClusterList &clusterList, CaloHitToClusterMap &caloHitToClusterMap) const
Look for isolated hit additions, considering a list of candidate hits and a list of host clusters...