Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
ClusterAssociationAlgorithm.cc
Go to the documentation of this file.
1
10
12
14
15using namespace pandora;
16
17namespace lar_content
18{
19
20ClusterAssociationAlgorithm::ClusterAssociationAlgorithm() : m_mergeMade(false), m_resolveAmbiguousAssociations(true)
21{
22}
23
24//------------------------------------------------------------------------------------------------------------------------------------------
25
27{
28 const ClusterList *pClusterList = NULL;
29 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pClusterList));
30
31 ClusterVector clusterVector;
32 this->GetListOfCleanClusters(pClusterList, clusterVector);
33
34 ClusterAssociationMap clusterAssociationMap;
35 this->PopulateClusterAssociationMap(clusterVector, clusterAssociationMap);
36
37 m_mergeMade = true;
38
39 while (m_mergeMade)
40 {
41 // Unambiguous propagation
42 while (m_mergeMade)
43 {
44 m_mergeMade = false;
45
46 for (const Cluster *const pCluster : clusterVector)
47 {
48 // ATTN The clusterVector may end up with dangling pointers; only protected by this check against managed cluster list
49 if (pClusterList->end() == std::find(pClusterList->begin(), pClusterList->end(), pCluster))
50 continue;
51
52 this->UnambiguousPropagation(pCluster, true, clusterAssociationMap);
53 this->UnambiguousPropagation(pCluster, false, clusterAssociationMap);
54 }
55 }
56
58 continue;
59
60 // Propagation with ambiguities
61 for (const Cluster *const pCluster : clusterVector)
62 {
63 // ATTN The clusterVector may end up with dangling pointers; only protected by this check against up-to-date association list
64 ClusterAssociationMap::const_iterator mapIterFwd = clusterAssociationMap.find(pCluster);
65
66 if (clusterAssociationMap.end() == mapIterFwd)
67 continue;
68
69 if (mapIterFwd->second.m_backwardAssociations.empty() && !mapIterFwd->second.m_forwardAssociations.empty())
70 this->AmbiguousPropagation(pCluster, true, clusterAssociationMap);
71
72 ClusterAssociationMap::const_iterator mapIterBwd = clusterAssociationMap.find(pCluster);
73
74 if (clusterAssociationMap.end() == mapIterBwd)
75 continue;
76
77 if (mapIterBwd->second.m_forwardAssociations.empty() && !mapIterBwd->second.m_backwardAssociations.empty())
78 this->AmbiguousPropagation(pCluster, false, clusterAssociationMap);
79 }
80 }
81
82 return STATUS_CODE_SUCCESS;
83}
84
85//------------------------------------------------------------------------------------------------------------------------------------------
86
87void ClusterAssociationAlgorithm::UnambiguousPropagation(const Cluster *const pCluster, const bool isForward, ClusterAssociationMap &clusterAssociationMap) const
88{
89 const Cluster *const pClusterToEnlarge = pCluster;
90 ClusterAssociationMap::iterator iterEnlarge = clusterAssociationMap.find(pClusterToEnlarge);
91
92 if (clusterAssociationMap.end() == iterEnlarge)
93 return;
94
95 ClusterSet &clusterSetEnlarge(isForward ? iterEnlarge->second.m_forwardAssociations : iterEnlarge->second.m_backwardAssociations);
96
97 if (clusterSetEnlarge.size() != 1)
98 return;
99
100 const Cluster *const pClusterToDelete = *(clusterSetEnlarge.begin());
101 ClusterAssociationMap::iterator iterDelete = clusterAssociationMap.find(pClusterToDelete);
102
103 if (clusterAssociationMap.end() == iterDelete)
104 return;
105
106 ClusterSet &clusterSetDelete(isForward ? iterDelete->second.m_backwardAssociations : iterDelete->second.m_forwardAssociations);
107
108 if (clusterSetDelete.size() != 1)
109 return;
110
111 this->UpdateForUnambiguousMerge(pClusterToEnlarge, pClusterToDelete, isForward, clusterAssociationMap);
112
113 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*this, pClusterToEnlarge, pClusterToDelete));
114 m_mergeMade = true;
115
116 this->UnambiguousPropagation(pClusterToEnlarge, isForward, clusterAssociationMap);
117}
118
119//------------------------------------------------------------------------------------------------------------------------------------------
120
121void ClusterAssociationAlgorithm::AmbiguousPropagation(const Cluster *const pCluster, const bool isForward, ClusterAssociationMap &clusterAssociationMap) const
122{
123 ClusterAssociationMap::iterator cIter = clusterAssociationMap.find(pCluster);
124
125 if (clusterAssociationMap.end() == cIter)
126 throw StatusCodeException(STATUS_CODE_FAILURE);
127
128 const Cluster *pExtremalCluster = pCluster;
129
130 ClusterSet firstClusterSet;
131 this->NavigateAlongAssociations(clusterAssociationMap, pCluster, isForward, pExtremalCluster, firstClusterSet);
132
133 ClusterSet secondClusterSet;
134 this->NavigateAlongAssociations(clusterAssociationMap, pExtremalCluster, !isForward, pExtremalCluster, secondClusterSet);
135
136 ClusterVector daughterClusterVector;
137
138 if (pCluster == pExtremalCluster)
139 {
140 for (const Cluster *const pFirstCluster : firstClusterSet)
141 {
142 if ((pCluster != pFirstCluster) && (secondClusterSet.count(pFirstCluster)) &&
143 (daughterClusterVector.end() == std::find(daughterClusterVector.begin(), daughterClusterVector.end(), pFirstCluster)))
144 {
145 daughterClusterVector.push_back(pFirstCluster);
146 }
147 }
148 }
149
150 std::sort(daughterClusterVector.begin(), daughterClusterVector.end(), LArClusterHelper::SortByNHits);
151
152 for (ClusterVector::iterator dIter = daughterClusterVector.begin(), dIterEnd = daughterClusterVector.end(); dIter != dIterEnd; ++dIter)
153 {
154 this->UpdateForAmbiguousMerge(*dIter, clusterAssociationMap);
155
156 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*this, pCluster, *dIter));
157 m_mergeMade = true;
158 *dIter = NULL;
159 }
160
161 this->UpdateForAmbiguousMerge(pCluster, clusterAssociationMap);
162}
163
164//------------------------------------------------------------------------------------------------------------------------------------------
165
166void ClusterAssociationAlgorithm::UpdateForUnambiguousMerge(const Cluster *const pClusterToEnlarge, const Cluster *const pClusterToDelete,
167 const bool isForwardMerge, ClusterAssociationMap &clusterAssociationMap) const
168{
169 ClusterAssociationMap::iterator iterEnlarge = clusterAssociationMap.find(pClusterToEnlarge);
170 ClusterAssociationMap::iterator iterDelete = clusterAssociationMap.find(pClusterToDelete);
171
172 if ((clusterAssociationMap.end() == iterEnlarge) || (clusterAssociationMap.end() == iterDelete))
173 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
174
175 ClusterSet &clusterSetToMove(isForwardMerge ? iterDelete->second.m_forwardAssociations : iterDelete->second.m_backwardAssociations);
176 ClusterSet &clusterSetToReplace(isForwardMerge ? iterEnlarge->second.m_forwardAssociations : iterEnlarge->second.m_backwardAssociations);
177 clusterSetToReplace = clusterSetToMove;
178 clusterAssociationMap.erase(iterDelete);
179
180 for (ClusterAssociationMap::iterator iter = clusterAssociationMap.begin(), iterEnd = clusterAssociationMap.end(); iter != iterEnd; ++iter)
181 {
182 ClusterSet &forwardClusters = iter->second.m_forwardAssociations;
183 ClusterSet &backwardClusters = iter->second.m_backwardAssociations;
184
185 ClusterSet::iterator forwardIter = forwardClusters.find(pClusterToDelete);
186 ClusterSet::iterator backwardIter = backwardClusters.find(pClusterToDelete);
187
188 if (forwardClusters.end() != forwardIter)
189 {
190 forwardClusters.erase(forwardIter);
191 forwardClusters.insert(pClusterToEnlarge);
192 }
193
194 if (backwardClusters.end() != backwardIter)
195 {
196 backwardClusters.erase(backwardIter);
197 backwardClusters.insert(pClusterToEnlarge);
198 }
199 }
200}
201
202//------------------------------------------------------------------------------------------------------------------------------------------
203
204void ClusterAssociationAlgorithm::UpdateForAmbiguousMerge(const Cluster *const pCluster, ClusterAssociationMap &clusterAssociationMap) const
205{
206 ClusterAssociationMap::iterator cIter = clusterAssociationMap.find(pCluster);
207
208 if (clusterAssociationMap.end() == cIter)
209 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
210
211 for (ClusterAssociationMap::iterator mIter = clusterAssociationMap.begin(), mIterEnd = clusterAssociationMap.end(); mIter != mIterEnd; ++mIter)
212 {
213 ClusterSet &forwardClusters = mIter->second.m_forwardAssociations;
214 ClusterSet &backwardClusters = mIter->second.m_backwardAssociations;
215
216 ClusterSet::iterator fIter = forwardClusters.find(pCluster);
217 ClusterSet::iterator bIter = backwardClusters.find(pCluster);
218
219 if (forwardClusters.end() != fIter)
220 forwardClusters.erase(fIter);
221
222 if (backwardClusters.end() != bIter)
223 backwardClusters.erase(bIter);
224 }
225
226 clusterAssociationMap.erase(pCluster);
227}
228
229//------------------------------------------------------------------------------------------------------------------------------------------
230
232 const Cluster *const pCluster, const bool isForward, const Cluster *&pExtremalCluster, ClusterSet &clusterSet) const
233{
234 ClusterAssociationMap::const_iterator iterAssociation = clusterAssociationMap.find(pCluster);
235
236 if (clusterAssociationMap.end() == iterAssociation)
237 throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
238
239 (void)clusterSet.insert(pCluster);
240
241 if ((pCluster != pExtremalCluster) && this->IsExtremalCluster(isForward, pExtremalCluster, pCluster))
242 pExtremalCluster = pCluster;
243
244 const ClusterSet &associatedClusterSet(isForward ? iterAssociation->second.m_forwardAssociations : iterAssociation->second.m_backwardAssociations);
245
246 for (ClusterSet::const_iterator iter = associatedClusterSet.begin(), iterEnd = associatedClusterSet.end(); iter != iterEnd; ++iter)
247 {
248 this->NavigateAlongAssociations(clusterAssociationMap, *iter, isForward, pExtremalCluster, clusterSet);
249 }
250}
251
252//------------------------------------------------------------------------------------------------------------------------------------------
253
255{
256 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
257 XmlHelper::ReadValue(xmlHandle, "ResolveAmbiguousAssociations", m_resolveAmbiguousAssociations));
258
259 return STATUS_CODE_SUCCESS;
260}
261
262} // namespace lar_content
Grouping of header files for many classes of use in particle flow algorithms.
Header file for the cluster association algorithm class.
Header file for the cluster helper class.
#define PANDORA_THROW_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:43
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
Definition StatusCodes.h:31
#define PANDORA_RETURN_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:19
static pandora::StatusCode GetCurrentList(const pandora::Algorithm &algorithm, const T *&pT)
Get the current list.
static pandora::StatusCode MergeAndDeleteClusters(const pandora::Algorithm &algorithm, const pandora::Cluster *const pClusterToEnlarge, const pandora::Cluster *const pClusterToDelete)
Merge two clusters in the current list, enlarging one cluster and deleting the second.
void UpdateForAmbiguousMerge(const pandora::Cluster *const pCluster, ClusterAssociationMap &clusterAssociationMap) const
Update cluster association map to reflect an ambiguous cluster merge.
virtual void GetListOfCleanClusters(const pandora::ClusterList *const pClusterList, pandora::ClusterVector &clusterVector) const =0
Populate cluster vector with subset of cluster list, containing clusters judged to be clean.
bool m_resolveAmbiguousAssociations
Whether to resolve ambiguous associations.
virtual pandora::StatusCode Run()
Run the algorithm.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
void UnambiguousPropagation(const pandora::Cluster *const pCluster, const bool isForward, ClusterAssociationMap &clusterAssociationMap) const
Unambiguous propagation.
void NavigateAlongAssociations(const ClusterAssociationMap &clusterAssociationMap, const pandora::Cluster *const pCluster, const bool isForward, const pandora::Cluster *&pExtremalCluster, pandora::ClusterSet &clusterSet) const
Navigate along cluster associations, from specified cluster, in specified direction.
virtual void PopulateClusterAssociationMap(const pandora::ClusterVector &clusterVector, ClusterAssociationMap &clusterAssociationMap) const =0
Populate the cluster association map.
virtual bool IsExtremalCluster(const bool isForward, const pandora::Cluster *const pCurrentCluster, const pandora::Cluster *const pTestCluster) const =0
Determine which of two clusters is extremal.
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
void UpdateForUnambiguousMerge(const pandora::Cluster *const pClusterToEnlarge, const pandora::Cluster *const pClusterToDelete, const bool isForwardMerge, ClusterAssociationMap &clusterAssociationMap) const
Update cluster association map to reflect an unambiguous cluster merge.
void AmbiguousPropagation(const pandora::Cluster *const pCluster, const bool isForward, ClusterAssociationMap &clusterAssociationMap) const
Ambiguous propagation.
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,...
Cluster class.
Definition Cluster.h:31
StatusCodeException class.
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
Definition XmlHelper.h:136
std::vector< const Cluster * > ClusterVector
MANAGED_CONTAINER< const Cluster * > ClusterList
std::unordered_set< const Cluster * > ClusterSet
StatusCode
The StatusCode enum.