9 #include "Pandora/AlgorithmHeaders.h" 20 ClusterAssociationAlgorithm::ClusterAssociationAlgorithm() :
22 m_resolveAmbiguousAssociations(true)
30 const ClusterList *pClusterList = NULL;
31 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*
this, pClusterList));
48 for (
const Cluster *
const pCluster : clusterVector)
51 if (pClusterList->end() == std::find(pClusterList->begin(), pClusterList->end(), pCluster))
63 for (
const Cluster *
const pCluster : clusterVector)
68 if (clusterAssociationMap.end() == mapIter)
71 if (mapIter->second.m_backwardAssociations.empty() && !mapIter->second.m_forwardAssociations.empty())
74 if (mapIter->second.m_forwardAssociations.empty() && !mapIter->second.m_backwardAssociations.empty())
79 return STATUS_CODE_SUCCESS;
86 const Cluster *
const pClusterToEnlarge = pCluster;
89 if (clusterAssociationMap.end() == iterEnlarge)
92 ClusterSet &clusterSetEnlarge(isForward ? iterEnlarge->second.m_forwardAssociations : iterEnlarge->second.m_backwardAssociations);
94 if (clusterSetEnlarge.size() != 1)
97 const Cluster *
const pClusterToDelete = *(clusterSetEnlarge.begin());
100 if (clusterAssociationMap.end() == iterDelete)
103 ClusterSet &clusterSetDelete(isForward ? iterDelete->second.m_backwardAssociations : iterDelete->second.m_forwardAssociations);
105 if (clusterSetDelete.size() != 1)
109 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*
this, pClusterToEnlarge, pClusterToDelete));
121 if (clusterAssociationMap.end() == cIter)
122 throw StatusCodeException(STATUS_CODE_FAILURE);
124 const Cluster *pExtremalCluster = pCluster;
126 ClusterSet firstClusterSet;
129 ClusterSet secondClusterSet;
130 this->
NavigateAlongAssociations(clusterAssociationMap, pExtremalCluster, !isForward, pExtremalCluster, secondClusterSet);
134 if (pCluster == pExtremalCluster)
136 for (
const Cluster *
const pFirstCluster : firstClusterSet)
138 if ((pCluster != pFirstCluster) && (secondClusterSet.count(pFirstCluster)) &&
139 (daughterClusterVector.end() == std::find(daughterClusterVector.begin(), daughterClusterVector.end(), pFirstCluster)))
141 daughterClusterVector.push_back(pFirstCluster);
148 for (
ClusterVector::iterator dIter = daughterClusterVector.begin(), dIterEnd = daughterClusterVector.end(); dIter != dIterEnd; ++dIter)
151 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*
this, pCluster, *dIter));
165 if ((clusterAssociationMap.end() == iterEnlarge) || (clusterAssociationMap.end() == iterDelete))
166 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
168 ClusterSet &clusterSetToMove(isForwardMerge ? iterDelete->second.m_forwardAssociations : iterDelete->second.m_backwardAssociations);
169 ClusterSet &clusterSetToReplace(isForwardMerge ? iterEnlarge->second.m_forwardAssociations : iterEnlarge->second.m_backwardAssociations);
170 clusterSetToReplace = clusterSetToMove;
171 clusterAssociationMap.erase(iterDelete);
175 ClusterSet &forwardClusters = iter->second.m_forwardAssociations;
176 ClusterSet &backwardClusters = iter->second.m_backwardAssociations;
181 if (forwardClusters.end() != forwardIter)
183 forwardClusters.erase(forwardIter);
184 forwardClusters.insert(pClusterToEnlarge);
187 if (backwardClusters.end() != backwardIter)
189 backwardClusters.erase(backwardIter);
190 backwardClusters.insert(pClusterToEnlarge);
203 if ((clusterAssociationMap.end() == iterEnlarge) || (clusterAssociationMap.end() == iterDelete))
204 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
206 ClusterSet &clusterSetEnlarge(isForwardMerge ? iterEnlarge->second.m_forwardAssociations : iterEnlarge->second.m_backwardAssociations);
207 ClusterSet &clusterSetDelete(isForwardMerge ? iterDelete->second.m_backwardAssociations : iterDelete->second.m_forwardAssociations);
211 if ((*iter) != pClusterToDelete)
215 if (clusterAssociationMap.end() == iterAssociation)
216 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
218 ClusterSet &associatedClusterSet(isForwardMerge ? iterAssociation->second.m_backwardAssociations : iterAssociation->second.m_forwardAssociations);
222 if (associatedClusterSet.end() == enlargeIter)
223 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
225 associatedClusterSet.erase(enlargeIter);
226 clusterSetEnlarge.erase(iter++);
236 if ((*iter) != pClusterToEnlarge)
240 if (clusterAssociationMap.end() == iterAssociation)
241 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
243 ClusterSet &associatedClusterSet(isForwardMerge ? iterAssociation->second.m_forwardAssociations : iterAssociation->second.m_backwardAssociations);
247 if (associatedClusterSet.end() == deleteIter)
248 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
250 associatedClusterSet.erase(deleteIter);
251 clusterSetDelete.erase(iter++);
265 const bool isForward,
const Cluster *&pExtremalCluster, ClusterSet &clusterSet)
const 269 if (clusterAssociationMap.end() == iterAssociation)
270 throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
272 (void) clusterSet.insert(pCluster);
274 if ((pCluster != pExtremalCluster) && this->
IsExtremalCluster(isForward, pExtremalCluster, pCluster))
275 pExtremalCluster = pCluster;
277 const ClusterSet &associatedClusterSet(isForward ? iterAssociation->second.m_forwardAssociations : iterAssociation->second.m_backwardAssociations);
279 for (
ClusterSet::const_iterator iter = associatedClusterSet.begin(), iterEnd = associatedClusterSet.end(); iter != iterEnd; ++iter)
289 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
292 return STATUS_CODE_SUCCESS;
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.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
void UpdateForAmbiguousMerge(const pandora::Cluster *const pClusterToEnlarge, const pandora::Cluster *const pClusterToDelete, const bool isForwardMerge, ClusterAssociationMap &clusterAssociationMap) const
Update cluster association map to reflect an ambiguous cluster merge.
bool m_resolveAmbiguousAssociations
Whether to resolve ambiguous associations.
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.
Header file for the cluster helper class.
Header file for the cluster association algorithm class.
void AmbiguousPropagation(const pandora::Cluster *const pCluster, const bool isForward, ClusterAssociationMap &clusterAssociationMap) const
Ambiguous propagation.
virtual void PopulateClusterAssociationMap(const pandora::ClusterVector &clusterVector, ClusterAssociationMap &clusterAssociationMap) const =0
Populate the cluster association map.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
void UnambiguousPropagation(const pandora::Cluster *const pCluster, const bool isForward, ClusterAssociationMap &clusterAssociationMap) const
Unambiguous propagation.
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.
virtual pandora::StatusCode Run()
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
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...
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.