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() == mapIterFwd)
71 if (mapIterFwd->second.m_backwardAssociations.empty() && !mapIterFwd->second.m_forwardAssociations.empty())
76 if (clusterAssociationMap.end() == mapIterBwd)
79 if (mapIterBwd->second.m_forwardAssociations.empty() && !mapIterBwd->second.m_backwardAssociations.empty())
84 return STATUS_CODE_SUCCESS;
91 const Cluster *
const pClusterToEnlarge = pCluster;
94 if (clusterAssociationMap.end() == iterEnlarge)
97 ClusterSet &clusterSetEnlarge(isForward ? iterEnlarge->second.m_forwardAssociations : iterEnlarge->second.m_backwardAssociations);
99 if (clusterSetEnlarge.size() != 1)
102 const Cluster *
const pClusterToDelete = *(clusterSetEnlarge.begin());
105 if (clusterAssociationMap.end() == iterDelete)
108 ClusterSet &clusterSetDelete(isForward ? iterDelete->second.m_backwardAssociations : iterDelete->second.m_forwardAssociations);
110 if (clusterSetDelete.size() != 1)
115 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*
this, pClusterToEnlarge, pClusterToDelete));
127 if (clusterAssociationMap.end() == cIter)
128 throw StatusCodeException(STATUS_CODE_FAILURE);
130 const Cluster *pExtremalCluster = pCluster;
132 ClusterSet firstClusterSet;
135 ClusterSet secondClusterSet;
136 this->
NavigateAlongAssociations(clusterAssociationMap, pExtremalCluster, !isForward, pExtremalCluster, secondClusterSet);
140 if (pCluster == pExtremalCluster)
142 for (
const Cluster *
const pFirstCluster : firstClusterSet)
144 if ((pCluster != pFirstCluster) && (secondClusterSet.count(pFirstCluster)) &&
145 (daughterClusterVector.end() == std::find(daughterClusterVector.begin(), daughterClusterVector.end(), pFirstCluster)))
147 daughterClusterVector.push_back(pFirstCluster);
154 for (
ClusterVector::iterator dIter = daughterClusterVector.begin(), dIterEnd = daughterClusterVector.end(); dIter != dIterEnd; ++dIter)
158 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*
this, pCluster, *dIter));
174 if ((clusterAssociationMap.end() == iterEnlarge) || (clusterAssociationMap.end() == iterDelete))
175 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
177 ClusterSet &clusterSetToMove(isForwardMerge ? iterDelete->second.m_forwardAssociations : iterDelete->second.m_backwardAssociations);
178 ClusterSet &clusterSetToReplace(isForwardMerge ? iterEnlarge->second.m_forwardAssociations : iterEnlarge->second.m_backwardAssociations);
179 clusterSetToReplace = clusterSetToMove;
180 clusterAssociationMap.erase(iterDelete);
184 ClusterSet &forwardClusters = iter->second.m_forwardAssociations;
185 ClusterSet &backwardClusters = iter->second.m_backwardAssociations;
190 if (forwardClusters.end() != forwardIter)
192 forwardClusters.erase(forwardIter);
193 forwardClusters.insert(pClusterToEnlarge);
196 if (backwardClusters.end() != backwardIter)
198 backwardClusters.erase(backwardIter);
199 backwardClusters.insert(pClusterToEnlarge);
210 if (clusterAssociationMap.end() == cIter)
211 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
215 ClusterSet &forwardClusters = mIter->second.m_forwardAssociations;
216 ClusterSet &backwardClusters = mIter->second.m_backwardAssociations;
221 if (forwardClusters.end() != fIter)
222 forwardClusters.erase(fIter);
224 if (backwardClusters.end() != bIter)
225 backwardClusters.erase(bIter);
228 clusterAssociationMap.erase(pCluster);
234 const Cluster *
const pCluster,
const bool isForward,
const Cluster *&pExtremalCluster, ClusterSet &clusterSet)
const 238 if (clusterAssociationMap.end() == iterAssociation)
239 throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
241 (void)clusterSet.insert(pCluster);
243 if ((pCluster != pExtremalCluster) && this->
IsExtremalCluster(isForward, pExtremalCluster, pCluster))
244 pExtremalCluster = pCluster;
246 const ClusterSet &associatedClusterSet(isForward ? iterAssociation->second.m_forwardAssociations : iterAssociation->second.m_backwardAssociations);
248 for (
ClusterSet::const_iterator iter = associatedClusterSet.begin(), iterEnd = associatedClusterSet.end(); iter != iterEnd; ++iter)
258 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
261 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)
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
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.
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.
void UpdateForAmbiguousMerge(const pandora::Cluster *const pCluster, ClusterAssociationMap &clusterAssociationMap) const
Update cluster association map to reflect an ambiguous cluster merge.
virtual pandora::StatusCode Run()
std::vector< art::Ptr< recob::Cluster > > ClusterVector
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.