95 if (pClusterI == pClusterJ)
124 const float distanceSquared((vertexPositionI - vertexPositionJ).GetMagnitudeSquared());
130 if (targetVertexI.
GetRms() > 1.f || targetVertexJ.
GetRms() > 1.f)
134 ClusterAssociation::AssociationType associationType(ClusterAssociation::NONE);
139 associationType = ClusterAssociation::WEAK;
143 const float cosTheta(-vertexDirectionI.
GetDotProduct(vertexDirectionJ));
147 associationType = ClusterAssociation::STRONG;
156 if (associationType < ClusterAssociation::STRONG)
158 const float cosTheta(-vertexDirectionI.
GetDotProduct(vertexDirectionJ));
159 const float cosThetaI((vertexPositionI - vertexPositionJ).GetUnitVector().GetDotProduct(vertexDirectionI));
160 const float cosThetaJ((vertexPositionJ - vertexPositionI).GetUnitVector().GetDotProduct(vertexDirectionJ));
162 float rT1(0.f), rL1(0.f), rT2(0.f), rL2(0.f);
171 associationType = ClusterAssociation::STRONG;
176 if (ClusterAssociation::NONE != associationType)
178 const ClusterAssociation::VertexType vertexTypeI(targetVertexI.
IsInnerVertex() ? ClusterAssociation::INNER : ClusterAssociation::OUTER);
179 const ClusterAssociation::VertexType vertexTypeJ(targetVertexJ.
IsInnerVertex() ? ClusterAssociation::INNER : ClusterAssociation::OUTER);
180 (void)clusterAssociationMatrix[pClusterI].insert(
181 ClusterAssociationMap::value_type(pClusterJ,
ClusterAssociation(vertexTypeI, vertexTypeJ, associationType, clusterLengthJ)));
182 (void)clusterAssociationMatrix[pClusterJ].insert(
183 ClusterAssociationMap::value_type(pClusterI,
ClusterAssociation(vertexTypeJ, vertexTypeI, associationType, clusterLengthI)));
201 for (
const auto &mapEntry : inputAssociationMatrix)
202 sortedInputClusters.push_back(mapEntry.first);
205 for (
const Cluster *
const pCluster1 : sortedInputClusters)
209 for (
const Cluster *
const pCluster2 : sortedInputClusters)
211 if (pCluster1 == pCluster2)
216 ClusterAssociationMap::const_iterator iter12 = associationMap1.find(pCluster2);
217 if (associationMap1.end() == iter12)
220 ClusterAssociationMap::const_iterator iter21 = associationMap2.find(pCluster1);
221 if (associationMap2.end() == iter21)
227 bool isAssociated(
true);
230 for (
const auto &mapEntry : associationMap1)
231 sortedAssociationClusters.push_back(mapEntry.first);
234 for (
const Cluster *
const pCluster3 : sortedAssociationClusters)
238 ClusterAssociationMap::const_iterator iter23 = associationMap2.find(pCluster3);
239 if (associationMap2.end() == iter23)
247 isAssociated =
false;
254 (void)clusterAssociationMatrix[pCluster1].insert(ClusterAssociationMap::value_type(pCluster2, association12));
255 (void)clusterAssociationMatrix[pCluster2].insert(ClusterAssociationMap::value_type(pCluster1, association21));
264 for (
const auto &mapEntry : clusterAssociationMatrix)
265 sortedClusters.push_back(mapEntry.first);
268 for (
const Cluster *
const pParentCluster : sortedClusters)
272 const Cluster *pBestClusterInner(
nullptr);
273 ClusterAssociation bestAssociationInner(ClusterAssociation::UNDEFINED, ClusterAssociation::UNDEFINED, ClusterAssociation::NONE, 0.f);
275 const Cluster *pBestClusterOuter(
nullptr);
276 ClusterAssociation bestAssociationOuter(ClusterAssociation::UNDEFINED, ClusterAssociation::UNDEFINED, ClusterAssociation::NONE, 0.f);
279 for (
const auto &mapEntry : clusterAssociationMap)
280 sortedAssociationClusters.push_back(mapEntry.first);
283 for (
const Cluster *
const pDaughterCluster : sortedAssociationClusters)
285 const ClusterAssociation &clusterAssociation(clusterAssociationMap.at(pDaughterCluster));
288 if (clusterAssociation.
GetParent() == ClusterAssociation::INNER)
292 bestAssociationInner = clusterAssociation;
294 if (clusterAssociation.
GetAssociation() == ClusterAssociation::STRONG)
295 pBestClusterInner = pDaughterCluster;
297 pBestClusterInner =
nullptr;
302 if (clusterAssociation.
GetParent() == ClusterAssociation::OUTER)
306 bestAssociationOuter = clusterAssociation;
308 if (clusterAssociation.
GetAssociation() == ClusterAssociation::STRONG)
309 pBestClusterOuter = pDaughterCluster;
311 pBestClusterOuter =
nullptr;
316 if (pBestClusterInner)
317 (void)intermediateAssociationMatrix[pParentCluster].insert(ClusterAssociationMap::value_type(pBestClusterInner, bestAssociationInner));
319 if (pBestClusterOuter)
320 (void)intermediateAssociationMatrix[pParentCluster].insert(ClusterAssociationMap::value_type(pBestClusterOuter, bestAssociationOuter));
325 for (
const auto &mapEntry : intermediateAssociationMatrix)
326 intermediateSortedClusters.push_back(mapEntry.first);
329 for (
const Cluster *
const pParentCluster : intermediateSortedClusters)
334 for (
const auto &mapEntry : parentAssociationMap)
335 sortedAssociationClusters.push_back(mapEntry.first);
338 for (
const Cluster *
const pDaughterCluster : sortedAssociationClusters)
340 const ClusterAssociation &parentToDaughterAssociation(parentAssociationMap.at(pDaughterCluster));
342 ClusterAssociationMatrix::const_iterator iter5 = intermediateAssociationMatrix.find(pDaughterCluster);
344 if (intermediateAssociationMatrix.end() == iter5)
349 ClusterAssociationMap::const_iterator iter6 = daughterAssociationMap.find(pParentCluster);
351 if (daughterAssociationMap.end() == iter6)
359 ClusterList &parentList(clusterMergeMap[pParentCluster]);
361 if (parentList.end() == std::find(parentList.begin(), parentList.end(), pDaughterCluster))
362 parentList.push_back(pDaughterCluster);
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
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,...
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
static float GetLayerOccupancy(const pandora::Cluster *const pCluster)
Fraction of occupied layers in cluster.
static void GetClosestVertices(const bool useX, const bool useY, const bool useZ, const LArPointingCluster &pointingClusterI, const LArPointingCluster &pointingClusterJ, LArPointingCluster::Vertex &closestVertexI, LArPointingCluster::Vertex &closestVertexJ)
Given a pair of pointing clusters, receive the closest or farthest pair of vertices.
static void GetImpactParameters(const LArPointingCluster::Vertex &pointingVertex, const LArPointingCluster::Vertex &targetVertex, float &longitudinal, float &transverse)
Calculate impact parameters between a pair of pointing vertices.
static float GetLength(const LArPointingCluster &pointingCluster)
Calculate distance squared between inner and outer vertices of pointing cluster.
const pandora::Cluster * GetCluster() const
Get the address of the cluster.
void FillClusterMergeMap(const ClusterAssociationMatrix &clusterAssociationMatrix, ClusterMergeMap &clusterMergeMap) const
Fill the cluster merge map.
void FillClusterAssociationMatrix(const pandora::ClusterVector &clusterVector, ClusterAssociationMatrix &clusterAssociationMatrix) const
Fill the cluster association matrix.
void GetListOfCleanClusters(const pandora::ClusterList *const pClusterList, pandora::ClusterVector &clusterVector) const
Populate cluster vector with subset of cluster list, containing clusters judged to be clean.
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterMergeMap