LArSoft  v09_90_00
Liquid Argon Software toolkit - https://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(
38  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, m_inputClusterListName, pClusterList));
39  }
40 
41  if (!pClusterList || pClusterList->empty())
42  {
43  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
44  std::cout << "ClusterGrowingAlgorithm: unable to find cluster list " << m_inputClusterListName << std::endl;
45 
46  return STATUS_CODE_SUCCESS;
47  }
48 
49  ClusterVector inputClusters, seedClusters;
50  this->GetListOfCleanClusters(pClusterList, inputClusters);
51  this->GetListOfSeedClusters(inputClusters, seedClusters);
52 
53  while (true)
54  {
55  ClusterVector currentClusters, nonSeedClusters;
56  this->GetListOfCleanClusters(pClusterList, currentClusters);
57  this->GetListOfNonSeedClusters(currentClusters, seedClusters, nonSeedClusters);
58 
59  ClusterMergeMap clusterMergeMap;
60  this->PopulateClusterMergeMap(seedClusters, nonSeedClusters, clusterMergeMap);
61 
62  if (clusterMergeMap.empty())
63  break;
64 
65  this->MergeClusters(clusterMergeMap);
66  }
67 
68  return STATUS_CODE_SUCCESS;
69 }
70 
71 //------------------------------------------------------------------------------------------------------------------------------------------
72 
74  const ClusterVector &inputClusters, const ClusterVector &seedClusters, ClusterVector &nonSeedClusters) const
75 {
76  for (ClusterVector::const_iterator iter = inputClusters.begin(), iterEnd = inputClusters.end(); iter != iterEnd; ++iter)
77  {
78  const Cluster *const pCluster = *iter;
79 
80  if (seedClusters.end() != std::find(seedClusters.begin(), seedClusters.end(), pCluster))
81  continue;
82 
83  nonSeedClusters.push_back(pCluster);
84  }
85 
86  std::sort(nonSeedClusters.begin(), nonSeedClusters.end(), LArClusterHelper::SortByNHits);
87 }
88 
89 //------------------------------------------------------------------------------------------------------------------------------------------
90 
92  const ClusterVector &seedClusters, const ClusterVector &nonSeedClusters, ClusterMergeMap &clusterMergeMap) const
93 {
94  for (ClusterVector::const_iterator nIter = nonSeedClusters.begin(), nIterEnd = nonSeedClusters.end(); nIter != nIterEnd; ++nIter)
95  {
96  const Cluster *const pNonSeedCluster = *nIter;
97 
98  const Cluster *pBestSeedCluster(NULL);
99  float bestDistance(m_maxClusterSeparation);
100 
101  for (ClusterVector::const_iterator sIter = seedClusters.begin(), sIterEnd = seedClusters.end(); sIter != sIterEnd; ++sIter)
102  {
103  const Cluster *const pThisSeedCluster = *sIter;
104  const float thisDistance(LArClusterHelper::GetClosestDistance(pNonSeedCluster, pThisSeedCluster));
105 
106  if (thisDistance < bestDistance)
107  {
108  pBestSeedCluster = pThisSeedCluster;
109  bestDistance = thisDistance;
110  }
111  }
112 
113  if (pBestSeedCluster)
114  clusterMergeMap[pBestSeedCluster].push_back(pNonSeedCluster);
115  }
116 }
117 
118 //------------------------------------------------------------------------------------------------------------------------------------------
119 
120 void ClusterGrowingAlgorithm::MergeClusters(const ClusterMergeMap &clusterMergeMap) const
121 {
122  ClusterList parentClusterList;
123  for (const auto &mapEntry : clusterMergeMap)
124  parentClusterList.push_back(mapEntry.first);
125  parentClusterList.sort(LArClusterHelper::SortByNHits);
126 
127  for (const Cluster *const pParentCluster : parentClusterList)
128  {
129  const ClusterList &clusterList(clusterMergeMap.at(pParentCluster));
130 
131  if (clusterList.empty())
132  throw StatusCodeException(STATUS_CODE_FAILURE);
133 
134  for (const Cluster *const pAssociatedCluster : clusterList)
135  {
136  if (m_inputClusterListName.empty())
137  {
138  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*this, pParentCluster, pAssociatedCluster));
139  }
140  else
141  {
142  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
143  PandoraContentApi::MergeAndDeleteClusters(*this, pParentCluster, pAssociatedCluster, m_inputClusterListName, m_inputClusterListName));
144  }
145  }
146  }
147 }
148 
149 //------------------------------------------------------------------------------------------------------------------------------------------
150 
151 StatusCode ClusterGrowingAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
152 {
153  PANDORA_RETURN_RESULT_IF_AND_IF(
154  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "InputClusterListName", m_inputClusterListName));
155 
156  PANDORA_RETURN_RESULT_IF_AND_IF(
157  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxClusterSeparation", m_maxClusterSeparation));
158 
159  return STATUS_CODE_SUCCESS;
160 }
161 
162 } // 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.
TFile f
Definition: plotHisto.C:6
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.