ClusterMergingAlgorithm.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArTwoDReco/LArClusterAssociation/ClusterMergingAlgorithm.cc
3  *
4  * @brief Implementation of the cluster merging 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 StatusCode ClusterMergingAlgorithm::Run()
21 {
22  const ClusterList *pClusterList = NULL;
23 
24  if (m_inputClusterListName.empty())
25  {
26  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pClusterList));
27  }
28  else
29  {
30  PANDORA_RETURN_RESULT_IF_AND_IF(
31  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, m_inputClusterListName, pClusterList));
32  }
33 
34  if (!pClusterList || pClusterList->empty())
35  {
36  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
37  std::cout << "ClusterMergingAlgorithm: unable to find cluster list " << m_inputClusterListName << std::endl;
38 
39  return STATUS_CODE_SUCCESS;
40  }
41 
42  while (true)
43  {
44  ClusterVector unsortedVector, clusterVector;
45  this->GetListOfCleanClusters(pClusterList, unsortedVector);
46  this->GetSortedListOfCleanClusters(unsortedVector, clusterVector);
47 
48  ClusterMergeMap clusterMergeMap;
49  this->PopulateClusterMergeMap(clusterVector, clusterMergeMap);
50 
51  if (clusterMergeMap.empty())
52  break;
53 
54  this->MergeClusters(clusterVector, clusterMergeMap);
55  }
56 
57  return STATUS_CODE_SUCCESS;
58 }
59 
60 //------------------------------------------------------------------------------------------------------------------------------------------
61 
62 void ClusterMergingAlgorithm::MergeClusters(ClusterVector &clusterVector, ClusterMergeMap &clusterMergeMap) const
63 {
64  ClusterSet clusterVetoList;
65 
66  for (const Cluster *const pSeedCluster : clusterVector)
67  {
68  ClusterList mergeList;
69  this->CollectAssociatedClusters(pSeedCluster, pSeedCluster, clusterMergeMap, clusterVetoList, mergeList);
70  mergeList.sort(LArClusterHelper::SortByNHits);
71 
72  for (const Cluster *const pAssociatedCluster : mergeList)
73  {
74  if (clusterVetoList.count(pAssociatedCluster))
75  throw StatusCodeException(STATUS_CODE_FAILURE);
76 
77  if (!pAssociatedCluster->IsAvailable())
78  throw StatusCodeException(STATUS_CODE_FAILURE);
79 
80  (void)clusterVetoList.insert(pAssociatedCluster);
81 
82  if (m_inputClusterListName.empty())
83  {
84  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*this, pSeedCluster, pAssociatedCluster));
85  }
86  else
87  {
88  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
89  PandoraContentApi::MergeAndDeleteClusters(*this, pSeedCluster, pAssociatedCluster, m_inputClusterListName, m_inputClusterListName));
90  }
91  }
92  }
93 }
94 
95 //------------------------------------------------------------------------------------------------------------------------------------------
96 
97 void ClusterMergingAlgorithm::CollectAssociatedClusters(
98  const Cluster *const pSeedCluster, const ClusterMergeMap &clusterMergeMap, ClusterList &associatedClusterList) const
99 {
100  ClusterSet clusterVetoList;
101  this->CollectAssociatedClusters(pSeedCluster, pSeedCluster, clusterMergeMap, clusterVetoList, associatedClusterList);
102 }
103 
104 //------------------------------------------------------------------------------------------------------------------------------------------
105 
106 void ClusterMergingAlgorithm::CollectAssociatedClusters(const Cluster *const pSeedCluster, const Cluster *const pCurrentCluster,
107  const ClusterMergeMap &clusterMergeMap, const ClusterSet &clusterVetoList, ClusterList &associatedClusterList) const
108 {
109  if (clusterVetoList.count(pCurrentCluster))
110  return;
111 
112  ClusterMergeMap::const_iterator iter1 = clusterMergeMap.find(pCurrentCluster);
113 
114  if (iter1 == clusterMergeMap.end())
115  return;
116 
117  ClusterVector associatedClusters(iter1->second.begin(), iter1->second.end());
118  std::sort(associatedClusters.begin(), associatedClusters.end(), LArClusterHelper::SortByNHits);
119 
120  for (const Cluster *const pAssociatedCluster : associatedClusters)
121  {
122  if (pAssociatedCluster == pSeedCluster)
123  continue;
124 
125  if (associatedClusterList.end() != std::find(associatedClusterList.begin(), associatedClusterList.end(), pAssociatedCluster))
126  continue;
127 
128  associatedClusterList.push_back(pAssociatedCluster);
129  this->CollectAssociatedClusters(pSeedCluster, pAssociatedCluster, clusterMergeMap, clusterVetoList, associatedClusterList);
130  }
131 }
132 
133 //------------------------------------------------------------------------------------------------------------------------------------------
134 
135 void ClusterMergingAlgorithm::GetSortedListOfCleanClusters(const ClusterVector &inputClusters, ClusterVector &outputClusters) const
136 {
137  ClusterVector pfoClusters, availableClusters;
138 
139  for (ClusterVector::const_iterator iter = inputClusters.begin(), iterEnd = inputClusters.end(); iter != iterEnd; ++iter)
140  {
141  const Cluster *const pCluster = *iter;
142 
143  if (!pCluster->IsAvailable())
144  {
145  pfoClusters.push_back(pCluster);
146  }
147  else
148  {
149  availableClusters.push_back(pCluster);
150  }
151  }
152 
153  std::sort(pfoClusters.begin(), pfoClusters.end(), LArClusterHelper::SortByNHits);
154  std::sort(availableClusters.begin(), availableClusters.end(), LArClusterHelper::SortByNHits);
155 
156  outputClusters.insert(outputClusters.end(), pfoClusters.begin(), pfoClusters.end());
157  outputClusters.insert(outputClusters.end(), availableClusters.begin(), availableClusters.end());
158 }
159 
160 //------------------------------------------------------------------------------------------------------------------------------------------
161 
162 StatusCode ClusterMergingAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
163 {
164  PANDORA_RETURN_RESULT_IF_AND_IF(
165  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "InputClusterListName", m_inputClusterListName));
166 
167  return STATUS_CODE_SUCCESS;
168 }
169 
170 } // namespace lar_content
intermediate_table::const_iterator const_iterator
Header file for the cluster helper class.
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterMergeMap
std::vector< art::Ptr< recob::Cluster > > ClusterVector
Header file for the cluster merging algorithm class.
QTextStream & endl(QTextStream &s)