9 #include "Pandora/AlgorithmHeaders.h"
22 CrossGapsExtensionAlgorithm::CrossGapsExtensionAlgorithm() :
23 m_minClusterLength(5.f),
24 m_minGapFraction(0.5f),
25 m_maxGapTolerance(2.f),
26 m_maxTransverseDisplacement(2.5f),
27 m_maxRelativeAngle(10.f)
39 for (
const Cluster *
const pCluster : *pClusterList)
44 clusterVector.push_back(pCluster);
62 const float zInner(pointingVertexInner.GetPosition().GetZ());
67 const float zOuter(pointingVertexOuter.GetPosition().GetZ());
72 if (!this->
IsAssociated(pointingVertexInner, pointingVertexOuter))
75 const Cluster *
const pClusterInner(pointingClusterInner.GetCluster());
76 const Cluster *
const pClusterOuter(pointingClusterOuter.GetCluster());
81 (
void)clusterAssociationMatrix[pClusterInner].insert(ClusterAssociationMap::value_type(pClusterOuter,
83 (
void)clusterAssociationMatrix[pClusterOuter].insert(ClusterAssociationMap::value_type(pClusterInner,
97 for (
const Cluster *
const pCluster : clusterVector)
103 catch (StatusCodeException &)
120 const LArPointingCluster::Vertex &pointingVertex(useInner ? pointingCluster.GetInnerVertex() : pointingCluster.GetOuterVertex());
124 outputPointingClusterList.push_back(pointingCluster);
132 const float maxLongitudinalDisplacement((pointingVertex2.
GetPosition() - pointingVertex1.
GetPosition()).GetMagnitude());
139 return (isAssociated1 && isAssociated2);
146 if (maxZ - minZ < std::numeric_limits<float>::epsilon())
170 for (
const auto &mapEntry : inputAssociationMatrix)
171 sortedInputClusters.push_back(mapEntry.first);
174 for (
const Cluster *
const pCluster1 : sortedInputClusters)
178 for (
const Cluster *
const pCluster2 : sortedInputClusters)
180 if (pCluster1 == pCluster2)
185 ClusterAssociationMap::const_iterator iter12 = associationMap1.find(pCluster2);
186 if (associationMap1.end() == iter12)
189 ClusterAssociationMap::const_iterator iter21 = associationMap2.find(pCluster1);
190 if (associationMap2.end() == iter21)
196 bool isAssociated(
true);
199 for (
const auto &mapEntry : associationMap1)
200 sortedAssociationClusters.push_back(mapEntry.first);
203 for (
const Cluster *
const pCluster3 : sortedAssociationClusters)
207 ClusterAssociationMap::const_iterator iter23 = associationMap2.find(pCluster3);
208 if (associationMap2.end() == iter23)
214 association13.GetDaughter() != association23.
GetDaughter())
216 isAssociated =
false;
223 (
void)clusterAssociationMatrix[pCluster1].insert(ClusterAssociationMap::value_type(pCluster2, association12));
224 (
void)clusterAssociationMatrix[pCluster2].insert(ClusterAssociationMap::value_type(pCluster1, association21));
233 for (
const auto &mapEntry : clusterAssociationMatrix)
234 sortedClusters.push_back(mapEntry.first);
237 for (
const Cluster *
const pParentCluster : sortedClusters)
241 const Cluster *pBestClusterInner(
nullptr);
244 const Cluster *pBestClusterOuter(
nullptr);
248 for (
const auto &mapEntry : clusterAssociationMap)
249 sortedAssociationClusters.push_back(mapEntry.first);
252 for (
const Cluster *
const pDaughterCluster : sortedAssociationClusters)
254 const ClusterAssociation &clusterAssociation(clusterAssociationMap.at(pDaughterCluster));
259 if (clusterAssociation.GetFigureOfMerit() > bestAssociationInner.
GetFigureOfMerit())
261 bestAssociationInner = clusterAssociation;
262 pBestClusterInner = pDaughterCluster;
269 if (clusterAssociation.GetFigureOfMerit() > bestAssociationOuter.
GetFigureOfMerit())
271 bestAssociationOuter = clusterAssociation;
272 pBestClusterOuter = pDaughterCluster;
277 if (pBestClusterInner)
278 (
void)intermediateAssociationMatrix[pParentCluster].insert(ClusterAssociationMap::value_type(pBestClusterInner, bestAssociationInner));
280 if (pBestClusterOuter)
281 (
void)intermediateAssociationMatrix[pParentCluster].insert(ClusterAssociationMap::value_type(pBestClusterOuter, bestAssociationOuter));
286 for (
const auto &mapEntry : intermediateAssociationMatrix)
287 intermediateSortedClusters.push_back(mapEntry.first);
290 for (
const Cluster *
const pParentCluster : intermediateSortedClusters)
295 for (
const auto &mapEntry : parentAssociationMap)
296 sortedAssociationClusters.push_back(mapEntry.first);
299 for (
const Cluster *
const pDaughterCluster : sortedAssociationClusters)
301 const ClusterAssociation &parentToDaughterAssociation(parentAssociationMap.at(pDaughterCluster));
303 ClusterAssociationMatrix::const_iterator iter5 = intermediateAssociationMatrix.find(pDaughterCluster);
305 if (intermediateAssociationMatrix.end() == iter5)
310 ClusterAssociationMap::const_iterator iter6 = daughterAssociationMap.find(pParentCluster);
312 if (daughterAssociationMap.end() == iter6)
317 if (parentToDaughterAssociation.GetParent() == daughterToParentAssociation.
GetDaughter() &&
318 parentToDaughterAssociation.GetDaughter() == daughterToParentAssociation.
GetParent())
320 ClusterList &parentList(clusterMergeMap[pParentCluster]);
322 if (parentList.end() == std::find(parentList.begin(), parentList.end(), pDaughterCluster))
323 parentList.push_back(pDaughterCluster);
333 PANDORA_RETURN_RESULT_IF_AND_IF(
334 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinClusterLength",
m_minClusterLength));
336 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinGapFraction",
m_minGapFraction));
338 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxGapTolerance",
m_maxGapTolerance));
340 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
344 PANDORA_RETURN_RESULT_IF_AND_IF(
345 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxCosRelativeAngle", maxCosRelativeAngle));
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.
static bool IsEmission(const pandora::CartesianVector &parentVertex, const LArPointingCluster::Vertex &daughterVertex, const float minLongitudinalDistance, const float maxLongitudinalDistance, const float maxTransverseDistance, const float angularAllowance)
Whether pointing vertex is emitted from a given position.
void BuildPointingClusterList(const pandora::ClusterVector &clusterVector, LArPointingClusterList &innerPointingClusterList, LArPointingClusterList &outerPointingClusterList) const
Build lists of pointing clusters that are adjacent to a detector gap.
std::vector< LArPointingCluster > LArPointingClusterList
static float CalculateGapDeltaZ(const pandora::Pandora &pandora, const float minZ, const float maxZ, const pandora::HitType hitType)
Calculate the total distance within a given 2D region that is composed of detector gaps...
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...
ClusterAssociation class.
void FillClusterMergeMap(const ClusterAssociationMatrix &clusterAssociationMatrix, ClusterMergeMap &clusterMergeMap) const
Fill the cluster merge map.
LArPointingCluster class.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
static bool IsInGap(const pandora::Pandora &pandora, const pandora::CartesianVector &testPoint2D, const pandora::HitType hitType, const float gapTolerance=0.f)
Whether a 2D test point lies in a registered gap with the associated hit type.
Header file for the geometry helper class.
Header file for the cluster helper class.
void FillClusterAssociationMatrix(const pandora::ClusterVector &clusterVector, ClusterAssociationMatrix &clusterAssociationMatrix) const
Fill the cluster association matrix.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
std::unordered_map< const pandora::Cluster *, ClusterAssociationMap > ClusterAssociationMatrix
float m_maxTransverseDisplacement
bool IsAcrossGap(const float minZ, const float maxZ, const pandora::HitType hitType) const
Determine whether a start and end position sit either side of a gap.
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch pandora
VertexType GetParent() const
Get parent.
bool IsAssociated(const LArPointingCluster::Vertex &pointingVertex1, const LArPointingCluster::Vertex &pointingVertex2) const
Use pointing information to determine whether two clusters are associated.
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
VertexType GetDaughter() const
Get daughter.
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterMergeMap
std::vector< art::Ptr< recob::Cluster > > ClusterVector
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Header file for the cross gaps extension algorithm class.
float GetFigureOfMerit() const
Get figure of merit.