9 #include "Pandora/AlgorithmHeaders.h" 20 ClusterAssociationAlgorithm::ClusterAssociationAlgorithm() : m_mergeMade(false), m_resolveAmbiguousAssociations(true)
28 const ClusterList *pClusterList = NULL;
29 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*
this, pClusterList));
46 for (
const Cluster *
const pCluster : clusterVector)
49 if (pClusterList->end() == std::find(pClusterList->begin(), pClusterList->end(), pCluster))
61 for (
const Cluster *
const pCluster : clusterVector)
66 if (clusterAssociationMap.end() == mapIterFwd)
69 if (mapIterFwd->second.m_backwardAssociations.empty() && !mapIterFwd->second.m_forwardAssociations.empty())
74 if (clusterAssociationMap.end() == mapIterBwd)
77 if (mapIterBwd->second.m_forwardAssociations.empty() && !mapIterBwd->second.m_backwardAssociations.empty())
82 return STATUS_CODE_SUCCESS;
89 const Cluster *
const pClusterToEnlarge = pCluster;
92 if (clusterAssociationMap.end() == iterEnlarge)
95 ClusterSet &clusterSetEnlarge(isForward ? iterEnlarge->second.m_forwardAssociations : iterEnlarge->second.m_backwardAssociations);
97 if (clusterSetEnlarge.size() != 1)
100 const Cluster *
const pClusterToDelete = *(clusterSetEnlarge.begin());
103 if (clusterAssociationMap.end() == iterDelete)
106 ClusterSet &clusterSetDelete(isForward ? iterDelete->second.m_backwardAssociations : iterDelete->second.m_forwardAssociations);
108 if (clusterSetDelete.size() != 1)
113 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*
this, pClusterToEnlarge, pClusterToDelete));
125 if (clusterAssociationMap.end() == cIter)
126 throw StatusCodeException(STATUS_CODE_FAILURE);
128 const Cluster *pExtremalCluster = pCluster;
130 ClusterSet firstClusterSet;
133 ClusterSet secondClusterSet;
134 this->
NavigateAlongAssociations(clusterAssociationMap, pExtremalCluster, !isForward, pExtremalCluster, secondClusterSet);
138 if (pCluster == pExtremalCluster)
140 for (
const Cluster *
const pFirstCluster : firstClusterSet)
142 if ((pCluster != pFirstCluster) && (secondClusterSet.count(pFirstCluster)) &&
143 (daughterClusterVector.end() == std::find(daughterClusterVector.begin(), daughterClusterVector.end(), pFirstCluster)))
145 daughterClusterVector.push_back(pFirstCluster);
152 for (
ClusterVector::iterator dIter = daughterClusterVector.begin(), dIterEnd = daughterClusterVector.end(); dIter != dIterEnd; ++dIter)
156 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*
this, pCluster, *dIter));
172 if ((clusterAssociationMap.end() == iterEnlarge) || (clusterAssociationMap.end() == iterDelete))
173 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
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);
182 ClusterSet &forwardClusters = iter->second.m_forwardAssociations;
183 ClusterSet &backwardClusters = iter->second.m_backwardAssociations;
188 if (forwardClusters.end() != forwardIter)
190 forwardClusters.erase(forwardIter);
191 forwardClusters.insert(pClusterToEnlarge);
194 if (backwardClusters.end() != backwardIter)
196 backwardClusters.erase(backwardIter);
197 backwardClusters.insert(pClusterToEnlarge);
208 if (clusterAssociationMap.end() == cIter)
209 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
213 ClusterSet &forwardClusters = mIter->second.m_forwardAssociations;
214 ClusterSet &backwardClusters = mIter->second.m_backwardAssociations;
219 if (forwardClusters.end() != fIter)
220 forwardClusters.erase(fIter);
222 if (backwardClusters.end() != bIter)
223 backwardClusters.erase(bIter);
226 clusterAssociationMap.erase(pCluster);
232 const Cluster *
const pCluster,
const bool isForward,
const Cluster *&pExtremalCluster, ClusterSet &clusterSet)
const 236 if (clusterAssociationMap.end() == iterAssociation)
237 throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
239 (void)clusterSet.insert(pCluster);
241 if ((pCluster != pExtremalCluster) && this->
IsExtremalCluster(isForward, pExtremalCluster, pCluster))
242 pExtremalCluster = pCluster;
244 const ClusterSet &associatedClusterSet(isForward ? iterAssociation->second.m_forwardAssociations : iterAssociation->second.m_backwardAssociations);
246 for (
ClusterSet::const_iterator iter = associatedClusterSet.begin(), iterEnd = associatedClusterSet.end(); iter != iterEnd; ++iter)
256 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
259 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.