ClusterGrowingAlgorithm.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArTwoDReco/LArClusterAssociation/ClusterGrowingAlgorithm.cc
3  *
4  * @brief Implementation of the cluster growing algorithm class.
5  *
6  * $Log: $
7  */
8 
9 #include "Pandora/AlgorithmHeaders.h"
10 
12 
14 
15 using namespace pandora;
16 
17 namespace lar_content
18 {
19 
20 ClusterGrowingAlgorithm::ClusterGrowingAlgorithm() : m_maxClusterSeparation(2.5f)
21 {
22 }
23 
24 //------------------------------------------------------------------------------------------------------------------------------------------
25 
27 {
28  const ClusterList *pClusterList = NULL;
29 
30  if (m_inputClusterListName.empty())
31  {
32  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pClusterList));
33  }
34  else
35  {
36  PANDORA_RETURN_RESULT_IF_AND_IF(
37  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, m_inputClusterListName, pClusterList));
38  }
39 
40  if (!pClusterList || pClusterList->empty())
41  {
42  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
43  std::cout << "ClusterGrowingAlgorithm: unable to find cluster list " << m_inputClusterListName << std::endl;
44 
45  return STATUS_CODE_SUCCESS;
46  }
47 
48  ClusterVector inputClusters, seedClusters;
49  this->GetListOfCleanClusters(pClusterList, inputClusters);
50  this->GetListOfSeedClusters(inputClusters, seedClusters);
51 
52  while (true)
53  {
54  ClusterVector currentClusters, nonSeedClusters;
55  this->GetListOfCleanClusters(pClusterList, currentClusters);
56  this->GetListOfNonSeedClusters(currentClusters, seedClusters, nonSeedClusters);
57 
58  ClusterMergeMap clusterMergeMap;
59  this->PopulateClusterMergeMap(seedClusters, nonSeedClusters, clusterMergeMap);
60 
61  if (clusterMergeMap.empty())
62  break;
63 
64  this->MergeClusters(clusterMergeMap);
65  }
66 
67  return STATUS_CODE_SUCCESS;
68 }
69 
70 //------------------------------------------------------------------------------------------------------------------------------------------
71 
73  const ClusterVector &inputClusters, const ClusterVector &seedClusters, ClusterVector &nonSeedClusters) const
74 {
75  for (ClusterVector::const_iterator iter = inputClusters.begin(), iterEnd = inputClusters.end(); iter != iterEnd; ++iter)
76  {
77  const Cluster *const pCluster = *iter;
78 
79  if (seedClusters.end() != std::find(seedClusters.begin(), seedClusters.end(), pCluster))
80  continue;
81 
82  nonSeedClusters.push_back(pCluster);
83  }
84 
85  std::sort(nonSeedClusters.begin(), nonSeedClusters.end(), LArClusterHelper::SortByNHits);
86 }
87 
88 //------------------------------------------------------------------------------------------------------------------------------------------
89 
91  const ClusterVector &seedClusters, const ClusterVector &nonSeedClusters, ClusterMergeMap &clusterMergeMap) const
92 {
93  for (ClusterVector::const_iterator nIter = nonSeedClusters.begin(), nIterEnd = nonSeedClusters.end(); nIter != nIterEnd; ++nIter)
94  {
95  const Cluster *const pNonSeedCluster = *nIter;
96 
97  const Cluster *pBestSeedCluster(NULL);
98  float bestDistance(m_maxClusterSeparation);
99 
100  for (ClusterVector::const_iterator sIter = seedClusters.begin(), sIterEnd = seedClusters.end(); sIter != sIterEnd; ++sIter)
101  {
102  const Cluster *const pThisSeedCluster = *sIter;
103  const float thisDistance(LArClusterHelper::GetClosestDistance(pNonSeedCluster, pThisSeedCluster));
104 
105  if (thisDistance < bestDistance)
106  {
107  pBestSeedCluster = pThisSeedCluster;
108  bestDistance = thisDistance;
109  }
110  }
111 
112  if (pBestSeedCluster)
113  clusterMergeMap[pBestSeedCluster].push_back(pNonSeedCluster);
114  }
115 }
116 
117 //------------------------------------------------------------------------------------------------------------------------------------------
118 
119 void ClusterGrowingAlgorithm::MergeClusters(const ClusterMergeMap &clusterMergeMap) const
120 {
121  ClusterList parentClusterList;
122  for (const auto &mapEntry : clusterMergeMap)
123  parentClusterList.push_back(mapEntry.first);
124  parentClusterList.sort(LArClusterHelper::SortByNHits);
125 
126  for (const Cluster *const pParentCluster : parentClusterList)
127  {
128  const ClusterList &clusterList(clusterMergeMap.at(pParentCluster));
129 
130  if (clusterList.empty())
131  throw StatusCodeException(STATUS_CODE_FAILURE);
132 
133  for (const Cluster *const pAssociatedCluster : clusterList)
134  {
135  if (m_inputClusterListName.empty())
136  {
137  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*this, pParentCluster, pAssociatedCluster));
138  }
139  else
140  {
141  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
142  PandoraContentApi::MergeAndDeleteClusters(*this, pParentCluster, pAssociatedCluster, m_inputClusterListName, m_inputClusterListName));
143  }
144  }
145  }
146 }
147 
148 //------------------------------------------------------------------------------------------------------------------------------------------
149 
150 StatusCode ClusterGrowingAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
151 {
152  PANDORA_RETURN_RESULT_IF_AND_IF(
153  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "InputClusterListName", m_inputClusterListName));
154 
155  PANDORA_RETURN_RESULT_IF_AND_IF(
156  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxClusterSeparation", m_maxClusterSeparation));
157 
158  return STATUS_CODE_SUCCESS;
159 }
160 
161 } // namespace lar_content
Header file for the cluster growing algorithm class.
static bool SortByNHits(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by number of hits, then layer span, then inner layer, then position, then pulse-height.
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterMergeMap
void GetListOfNonSeedClusters(const pandora::ClusterVector &inputClusters, const pandora::ClusterVector &seedClusters, pandora::ClusterVector &nonSeedClusters) const
Get List of non-seed clusters.
float m_maxClusterSeparation
Maximum distance at which clusters can be joined.
void MergeClusters(const ClusterMergeMap &clusterMergeMap) const
Merge clusters.
intermediate_table::const_iterator const_iterator
virtual void GetListOfCleanClusters(const pandora::ClusterList *const pClusterList, pandora::ClusterVector &cleanClusters) const =0
Populate cluster vector with the subset of clusters judged to be clean.
Header file for the cluster helper class.
std::string m_inputClusterListName
The name of the input cluster list. If not specified, will access current list.
virtual void GetListOfSeedClusters(const pandora::ClusterVector &cleanClusters, pandora::ClusterVector &seedClusters) const =0
Select seed clusters for growing.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
std::vector< art::Ptr< recob::Cluster > > ClusterVector
void PopulateClusterMergeMap(const pandora::ClusterVector &seedClusters, const pandora::ClusterVector &nonSeedClusters, ClusterMergeMap &clusterMergeMap) const
Identify a set of cluster merges.
QTextStream & endl(QTextStream &s)
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.