9 #include "Pandora/AlgorithmHeaders.h" 21 LongitudinalAssociationAlgorithm::LongitudinalAssociationAlgorithm() :
22 m_minClusterLayers(4),
25 m_maxGapDistanceSquared(10.
f),
26 m_minCosRelativeAngle(0.985
f),
27 m_maxTransverseDisplacement(2.
f),
28 m_maxLongitudinalDisplacement(2.
f),
39 if (!pClusterList->empty())
44 const Cluster *
const pCluster = *iter;
46 if (1 + pCluster->GetOuterPseudoLayer() - pCluster->GetInnerPseudoLayer() <
m_minClusterLayers)
49 clusterVector.push_back(pCluster);
62 const Cluster *
const pInnerCluster = *iterI;
66 const Cluster *
const pOuterCluster = *iterJ;
68 if (pInnerCluster == pOuterCluster)
74 clusterAssociationMap[pInnerCluster].m_forwardAssociations.insert(pOuterCluster);
75 clusterAssociationMap[pOuterCluster].m_backwardAssociations.insert(pInnerCluster);
84 const unsigned int currentLayer(isForward ? pCurrentCluster->GetOuterPseudoLayer() : pCurrentCluster->GetInnerPseudoLayer());
85 const unsigned int testLayer(isForward ? pTestCluster->GetOuterPseudoLayer() : pTestCluster->GetInnerPseudoLayer());
87 if (isForward && ((testLayer > currentLayer) || ((testLayer == currentLayer) &&
LArClusterHelper::SortByNHits(pTestCluster, pCurrentCluster))))
90 if (!isForward && ((testLayer < currentLayer) || ((testLayer == currentLayer) &&
LArClusterHelper::SortByNHits(pTestCluster, pCurrentCluster))))
100 if (pOuterCluster->GetInnerPseudoLayer() < pInnerCluster->GetInnerPseudoLayer())
101 throw pandora::StatusCodeException(STATUS_CODE_NOT_ALLOWED);
104 if ((pOuterCluster->GetInnerPseudoLayer() < pInnerCluster->GetInnerPseudoLayer() + 3) ||
105 (pInnerCluster->GetOuterPseudoLayer() + 3 > pOuterCluster->GetOuterPseudoLayer()))
110 if ((pInnerCluster->GetOuterPseudoLayer() > pOuterCluster->GetInnerPseudoLayer() + 1) ||
111 (pOuterCluster->GetInnerPseudoLayer() > pInnerCluster->GetOuterPseudoLayer() +
m_maxGapLayers))
116 if ((2 * pInnerCluster->GetOuterPseudoLayer() < pOuterCluster->GetInnerPseudoLayer() + pInnerCluster->GetInnerPseudoLayer()) ||
117 (pInnerCluster->GetOuterPseudoLayer() + pOuterCluster->GetOuterPseudoLayer() < 2 * pOuterCluster->GetInnerPseudoLayer()))
122 const CartesianVector innerEndCentroid(pInnerCluster->GetCentroid(pInnerCluster->GetOuterPseudoLayer()));
123 const CartesianVector outerStartCentroid(pOuterCluster->GetCentroid(pOuterCluster->GetInnerPseudoLayer()));
128 if ((innerEndCentroid - outerStartCentroid).GetMagnitudeSquared() > maxGapDistanceSquaredAdjusted)
131 ClusterFitResult innerEndFit, outerStartFit;
132 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, ClusterFitHelper::FitEnd(pInnerCluster,
m_fitLayers, innerEndFit));
133 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, ClusterFitHelper::FitStart(pOuterCluster,
m_fitLayers, outerStartFit));
144 const CartesianVector &outerClusterStart,
const ClusterFitResult &innerFit,
const ClusterFitResult &outerFit)
const 146 if (!innerFit.IsFitSuccessful() || !outerFit.IsFitSuccessful())
156 const CartesianVector innerEndFit1(
157 innerFit.GetIntercept() + innerFit.GetDirection() * (innerFit.GetDirection().GetDotProduct(innerClusterEnd - innerFit.GetIntercept())));
158 const CartesianVector innerEndFit2(
159 outerFit.GetIntercept() + outerFit.GetDirection() * (outerFit.GetDirection().GetDotProduct(innerClusterEnd - outerFit.GetIntercept())));
161 const CartesianVector outerStartFit1(outerFit.GetIntercept() +
162 outerFit.GetDirection() * (outerFit.GetDirection().GetDotProduct(outerClusterStart - outerFit.GetIntercept())));
163 const CartesianVector outerStartFit2(innerFit.GetIntercept() +
164 innerFit.GetDirection() * (innerFit.GetDirection().GetDotProduct(outerClusterStart - innerFit.GetIntercept())));
166 const CartesianVector clusterSeparation(outerClusterStart - innerClusterEnd);
168 if ((std::fabs(clusterSeparation.GetX()) <
m_hitSizeX * maxTransverseDisplacementAdjusted) &&
169 (std::fabs(clusterSeparation.GetZ()) <
m_hitSizeZ * maxLongitudinalDisplacementAdjusted))
172 const CartesianVector fittedSeparation(outerStartFit1 - innerEndFit1);
174 if ((std::fabs(fittedSeparation.GetX()) <
m_hitSizeX * maxTransverseDisplacementAdjusted) &&
175 (std::fabs(fittedSeparation.GetZ()) <
m_hitSizeZ * maxLongitudinalDisplacementAdjusted))
178 const CartesianVector fittedInnerSeparation(innerEndFit2 - innerEndFit1);
180 if ((std::fabs(fittedInnerSeparation.GetX()) <
m_hitSizeX * maxTransverseDisplacementAdjusted) &&
181 (std::fabs(fittedInnerSeparation.GetZ()) <
m_hitSizeZ * maxLongitudinalDisplacementAdjusted))
184 const CartesianVector fittedOuterSeparation(outerStartFit2 - outerStartFit1);
186 if ((std::fabs(fittedOuterSeparation.GetX()) <
m_hitSizeX * maxTransverseDisplacementAdjusted) &&
187 (std::fabs(fittedOuterSeparation.GetZ()) <
m_hitSizeZ * maxLongitudinalDisplacementAdjusted))
197 PANDORA_RETURN_RESULT_IF_AND_IF(
198 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinClusterLayers",
m_minClusterLayers));
200 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxGapLayers",
m_maxGapLayers));
202 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"FitLayers",
m_fitLayers));
205 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxGapDistance", maxGapDistance));
208 PANDORA_RETURN_RESULT_IF_AND_IF(
209 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinCosRelativeAngle",
m_minCosRelativeAngle));
211 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
214 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
217 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"HitSizeZ",
m_hitSizeZ));
219 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"HitSizeX",
m_hitSizeX));
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.
Header file for the longitudinal association algorithm class.
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...
void PopulateClusterAssociationMap(const pandora::ClusterVector &clusterVector, ClusterAssociationMap &clusterAssociationMap) const
Populate the cluster association map.
static float GetWirePitchRatio(const pandora::Pandora &pandora, const pandora::HitType view)
Return the ratio of the wire pitch of the specified view to the minimum wire pitch for the detector...
float m_maxLongitudinalDisplacement
maximum allowed longitudinal displacement after extrapolation (normalised to cell size) ...
float m_minCosRelativeAngle
maximum allowed relative angle between associated clusters
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
pandora::HitType m_view
The view to which the hits under consideration belong.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
unsigned int m_minClusterLayers
minimum allowed number of layers for a clean cluster
Header file for the geometry helper class.
Header file for the cluster helper class.
float m_hitSizeX
estimated hit size in x (drift time) dimension, units cm
float m_maxGapDistanceSquared
maximum allowed distance (squared) between associated clusters
bool IsExtremalCluster(const bool isForward, const pandora::Cluster *const pCurrentCluster, const pandora::Cluster *const pTestCluster) const
Determine which of two clusters is extremal.
unsigned int m_maxGapLayers
maximum allowed number of layers between associated clusters
float m_hitSizeZ
estimated hit size in z (wire number) dimension, units cm
bool AreClustersAssociated(const pandora::Cluster *const pInnerCluster, const pandora::Cluster *const pOuterCluster) const
Determine whether two clusters are associated.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
unsigned int m_fitLayers
number of layers to fit at start and end of cluster
float m_maxTransverseDisplacement
maximum allowed transverse displacement after extrapolation (normalised to cell size) ...
static bool SortByInnerLayer(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by inner layer, then position, then pulse-height.