LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
ClusterGrowingAlgorithm.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
10 
12 
14 
15 using namespace pandora;
16 
17 namespace lar_content
18 {
19 
20 ClusterGrowingAlgorithm::ClusterGrowingAlgorithm() :
21  m_maxClusterSeparation(2.5f)
22 {
23 }
24 
25 //------------------------------------------------------------------------------------------------------------------------------------------
26 
28 {
29  const ClusterList *pClusterList = NULL;
30 
31  if (m_inputClusterListName.empty())
32  {
33  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pClusterList));
34  }
35  else
36  {
37  PANDORA_RETURN_RESULT_IF_AND_IF(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 
72 void ClusterGrowingAlgorithm::GetListOfNonSeedClusters(const ClusterVector &inputClusters, const ClusterVector &seedClusters,
73  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 
90 void ClusterGrowingAlgorithm::PopulateClusterMergeMap(const ClusterVector &seedClusters, const ClusterVector &nonSeedClusters,
91  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) parentClusterList.push_back(mapEntry.first);
123  parentClusterList.sort(LArClusterHelper::SortByNHits);
124 
125  for (const Cluster *const pParentCluster : parentClusterList)
126  {
127  const ClusterList &clusterList(clusterMergeMap.at(pParentCluster));
128 
129  if (clusterList.empty())
130  throw StatusCodeException(STATUS_CODE_FAILURE);
131 
132  for (const Cluster *const pAssociatedCluster : clusterList)
133  {
134  if (m_inputClusterListName.empty())
135  {
136  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*this, pParentCluster, pAssociatedCluster));
137  }
138  else
139  {
140  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*this, pParentCluster, pAssociatedCluster,
142  }
143  }
144  }
145 }
146 
147 //------------------------------------------------------------------------------------------------------------------------------------------
148 
149 StatusCode ClusterGrowingAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
150 {
151  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
152  "InputClusterListName", m_inputClusterListName));
153 
154  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
155  "MaxClusterSeparation", m_maxClusterSeparation));
156 
157  return STATUS_CODE_SUCCESS;
158 }
159 
160 } // 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.
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.
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.
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterMergeMap
TFile f
Definition: plotHisto.C:6
intermediate_table::const_iterator const_iterator
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.
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.