9 #include "Pandora/AlgorithmHeaders.h" 21 LongitudinalExtensionAlgorithm::LongitudinalExtensionAlgorithm() :
22 m_clusterMinLength(5.
f),
23 m_clusterMinLayerOccupancy(0.75
f),
24 m_nodeMaxDisplacement(1.5
f),
25 m_nodeMaxCosRelativeAngle(0.906
f),
26 m_emissionMaxLongitudinalDisplacement(15.
f),
27 m_emissionMaxTransverseDisplacement(2.5
f),
28 m_emissionMaxCosRelativeAngle(0.985
f)
38 const Cluster *
const pCluster = *iter;
46 clusterVector.push_back(pCluster);
65 catch (StatusCodeException &)
92 const Cluster *
const pClusterI(clusterI.
GetCluster());
93 const Cluster *
const pClusterJ(clusterJ.
GetCluster());
95 if (pClusterI == pClusterJ)
109 catch (StatusCodeException &)
116 throw StatusCodeException(STATUS_CODE_FAILURE);
118 const CartesianVector &vertexPositionI(targetVertexI.
GetPosition());
119 const CartesianVector &vertexPositionJ(targetVertexJ.
GetPosition());
120 const CartesianVector &vertexDirectionI(targetVertexI.
GetDirection());
121 const CartesianVector &vertexDirectionJ(targetVertexJ.
GetDirection());
124 const float distanceSquared((vertexPositionI - vertexPositionJ).GetMagnitudeSquared());
130 if (targetVertexI.
GetRms() > 1.f || targetVertexJ.
GetRms() > 1.f)
141 if (distanceSquared < m_nodeMaxDisplacement * m_nodeMaxDisplacement)
143 const float cosTheta(-vertexDirectionI.GetDotProduct(vertexDirectionJ));
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);
166 if ((rL1 > -2.5
f && rL1 <
std::min(0.66
f * clusterLengthJ, m_emissionMaxLongitudinalDisplacement)) &&
167 (rL2 > -2.5
f && rL2 <
std::min(0.66
f * clusterLengthI, m_emissionMaxLongitudinalDisplacement)) &&
169 (targetVertexI.
GetRms() < 0.5f && targetVertexJ.
GetRms() < 0.5f) &&
181 (void) clusterAssociationMatrix[pClusterI].insert(ClusterAssociationMap::value_type(pClusterJ,
ClusterAssociation(vertexTypeI, vertexTypeJ, associationType, clusterLengthJ)));
182 (void) clusterAssociationMatrix[pClusterJ].insert(ClusterAssociationMap::value_type(pClusterI,
ClusterAssociation(vertexTypeJ, vertexTypeI, associationType, clusterLengthI)));
200 for (
const auto &mapEntry : inputAssociationMatrix) sortedInputClusters.push_back(mapEntry.first);
203 for (
const Cluster *
const pCluster1 : sortedInputClusters)
207 for (
const Cluster *
const pCluster2 : sortedInputClusters)
209 if (pCluster1 == pCluster2)
215 if (associationMap1.end() == iter12)
219 if (associationMap2.end() == iter21)
225 bool isAssociated(
true);
228 for (
const auto &mapEntry : associationMap1) sortedAssociationClusters.push_back(mapEntry.first);
231 for (
const Cluster *
const pCluster3 : sortedAssociationClusters)
236 if (associationMap2.end() == iter23)
241 if (association12.
GetParent() == association13.GetParent() &&
243 association13.GetDaughter() != association23.
GetDaughter())
245 isAssociated =
false;
252 (void) clusterAssociationMatrix[pCluster1].insert(ClusterAssociationMap::value_type(pCluster2, association12));
253 (void) clusterAssociationMatrix[pCluster2].insert(ClusterAssociationMap::value_type(pCluster1, association21));
263 for (
const auto &mapEntry : clusterAssociationMatrix) sortedClusters.push_back(mapEntry.first);
266 for (
const Cluster *
const pParentCluster : sortedClusters)
270 const Cluster *pBestClusterInner(
nullptr);
273 const Cluster *pBestClusterOuter(
nullptr);
277 for (
const auto &mapEntry : clusterAssociationMap) sortedAssociationClusters.push_back(mapEntry.first);
280 for (
const Cluster *
const pDaughterCluster : sortedAssociationClusters)
282 const ClusterAssociation &clusterAssociation(clusterAssociationMap.at(pDaughterCluster));
287 if (clusterAssociation.GetFigureOfMerit() > bestAssociationInner.
GetFigureOfMerit())
289 bestAssociationInner = clusterAssociation;
292 pBestClusterInner = pDaughterCluster;
294 pBestClusterInner =
nullptr;
301 if (clusterAssociation.GetFigureOfMerit() > bestAssociationOuter.
GetFigureOfMerit())
303 bestAssociationOuter = clusterAssociation;
306 pBestClusterOuter = pDaughterCluster;
308 pBestClusterOuter =
nullptr;
313 if (pBestClusterInner)
314 (void) intermediateAssociationMatrix[pParentCluster].insert(ClusterAssociationMap::value_type(pBestClusterInner, bestAssociationInner));
316 if (pBestClusterOuter)
317 (void) intermediateAssociationMatrix[pParentCluster].insert(ClusterAssociationMap::value_type(pBestClusterOuter, bestAssociationOuter));
323 for (
const auto &mapEntry : intermediateAssociationMatrix) intermediateSortedClusters.push_back(mapEntry.first);
326 for (
const Cluster *
const pParentCluster : intermediateSortedClusters)
331 for (
const auto &mapEntry : parentAssociationMap) sortedAssociationClusters.push_back(mapEntry.first);
334 for (
const Cluster *
const pDaughterCluster : sortedAssociationClusters)
336 const ClusterAssociation &parentToDaughterAssociation(parentAssociationMap.at(pDaughterCluster));
340 if (intermediateAssociationMatrix.end() == iter5)
347 if (daughterAssociationMap.end() == iter6)
352 if (parentToDaughterAssociation.GetParent() == daughterToParentAssociation.
GetDaughter() &&
353 parentToDaughterAssociation.GetDaughter() == daughterToParentAssociation.
GetParent())
355 ClusterList &parentList(clusterMergeMap[pParentCluster]);
357 if (parentList.end() == std::find(parentList.begin(), parentList.end(), pDaughterCluster))
358 parentList.push_back(pDaughterCluster);
368 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
371 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
374 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
377 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
380 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
383 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
386 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
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.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
std::unordered_map< const pandora::Cluster *, ClusterAssociationMap > ClusterAssociationMatrix
void FillClusterAssociationMatrix(const pandora::ClusterVector &clusterVector, ClusterAssociationMatrix &clusterAssociationMatrix) const
Fill the cluster association matrix.
float m_clusterMinLayerOccupancy
float m_emissionMaxTransverseDisplacement
std::vector< LArPointingCluster > LArPointingClusterList
static void GetImpactParameters(const LArPointingCluster::Vertex &pointingVertex, const LArPointingCluster::Vertex &targetVertex, float &longitudinal, float &transverse)
Calculate impact parameters between a pair of pointing vertices.
float m_nodeMaxCosRelativeAngle
ClusterAssociation class.
static float GetLength(const LArPointingCluster &pointingCluster)
Calculate distance squared between inner and outer vertices of pointing cluster.
LArPointingCluster class.
const pandora::Cluster * GetCluster() const
Get the address of the 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.
float m_nodeMaxDisplacement
Header file for the cluster helper class.
bool IsInitialized() const
Whether the vertex has been initialized.
AssociationType
Association enumeration.
float m_emissionMaxCosRelativeAngle
float m_emissionMaxLongitudinalDisplacement
static float GetLayerOccupancy(const pandora::Cluster *const pCluster)
Fraction of occupied layers in cluster.
const pandora::CartesianVector & GetDirection() const
Get the vertex direction.
float GetRms() const
Get rms from vertex fit.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterMergeMap
void FillClusterMergeMap(const ClusterAssociationMatrix &clusterAssociationMatrix, ClusterMergeMap &clusterMergeMap) const
Fill the cluster merge map.
VertexType GetParent() const
Get parent.
Header file for the longitudinal extension algorithm class.
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
VertexType GetDaughter() const
Get daughter.
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...
bool IsInnerVertex() const
Is this the inner vertex.
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
VertexType
Vertex enumeration.
float GetFigureOfMerit() const
Get figure of merit.