9 #include "Pandora/AlgorithmHeaders.h" 21 CrossGapsAssociationAlgorithm::CrossGapsAssociationAlgorithm() :
23 m_minClusterLayers(6),
24 m_slidingFitWindow(20),
25 m_maxSamplingPoints(1000),
26 m_sampleStepSize(0.5
f),
27 m_maxUnmatchedSampleRun(8),
28 m_maxOnClusterDistance(1.5
f),
29 m_minMatchedSamplingPoints(10),
30 m_minMatchedSamplingFraction(0.5
f),
43 for (
const Cluster *
const pCluster : *pClusterList)
48 if (1 + pCluster->GetOuterPseudoLayer() - pCluster->GetInnerPseudoLayer() <
m_minClusterLayers)
51 clusterVector.push_back(pCluster);
63 for (
const Cluster *
const pCluster : clusterVector)
68 slidingFitResultMap.insert(
71 catch (StatusCodeException &)
79 const Cluster *
const pInnerCluster = *iterI;
82 if (slidingFitResultMap.end() == fitIterI)
87 const Cluster *
const pOuterCluster = *iterJ;
89 if (pInnerCluster == pOuterCluster)
94 if (slidingFitResultMap.end() == fitIterJ)
100 clusterAssociationMap[pInnerCluster].m_forwardAssociations.insert(pOuterCluster);
101 clusterAssociationMap[pOuterCluster].m_backwardAssociations.insert(pInnerCluster);
110 const unsigned int currentLayer(isForward ? pCurrentCluster->GetOuterPseudoLayer() : pCurrentCluster->GetInnerPseudoLayer());
111 const unsigned int testLayer(isForward ? pTestCluster->GetOuterPseudoLayer() : pTestCluster->GetInnerPseudoLayer());
113 if (isForward && ((testLayer > currentLayer) || ((testLayer == currentLayer) &&
LArClusterHelper::SortByNHits(pTestCluster, pCurrentCluster))))
116 if (!isForward && ((testLayer < currentLayer) || ((testLayer == currentLayer) &&
LArClusterHelper::SortByNHits(pTestCluster, pCurrentCluster))))
126 if (outerFitResult.
GetCluster()->GetInnerPseudoLayer() < innerFitResult.
GetCluster()->GetInnerPseudoLayer())
127 throw pandora::StatusCodeException(STATUS_CODE_NOT_ALLOWED);
129 if (outerFitResult.
GetCluster()->GetInnerPseudoLayer() < innerFitResult.
GetCluster()->GetOuterPseudoLayer())
139 const CartesianVector &startPosition,
const CartesianVector &startDirection,
const TwoDSlidingFitResult &targetFitResult)
const 144 unsigned int nSamplingPoints(0), nGapSamplingPoints(0), nMatchedSamplingPoints(0), nUnmatchedSampleRun(0);
149 const CartesianVector samplingPoint(startPosition + startDirection * static_cast<float>(iSample) * sampleStepSizeAdjusted);
153 ++nGapSamplingPoints;
154 nUnmatchedSampleRun = 0;
160 ++nMatchedSamplingPoints;
161 nUnmatchedSampleRun = 0;
169 const float expectation(
171 const float matchedSamplingFraction(expectation > 0.
f ? static_cast<float>(nMatchedSamplingPoints) / expectation : 0.
f);
187 float rL(std::numeric_limits<float>::max()), rT(std::numeric_limits<float>::max());
190 CartesianVector fitPosition(0.
f, 0.
f, 0.
f);
194 if ((fitPosition - samplingPoint).GetMagnitudeSquared() < maxOnClusterDistanceAdjusted * maxOnClusterDistanceAdjusted)
198 CartesianVector fitPositionAtX(0.
f, 0.
f, 0.
f);
202 if ((fitPositionAtX - samplingPoint).GetMagnitudeSquared() < maxOnClusterDistanceAdjusted * maxOnClusterDistanceAdjusted)
213 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinClusterHits",
m_minClusterHits));
215 PANDORA_RETURN_RESULT_IF_AND_IF(
216 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinClusterLayers",
m_minClusterLayers));
218 PANDORA_RETURN_RESULT_IF_AND_IF(
219 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"SlidingFitWindow",
m_slidingFitWindow));
221 PANDORA_RETURN_RESULT_IF_AND_IF(
222 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxSamplingPoints",
m_maxSamplingPoints));
224 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"SampleStepSize",
m_sampleStepSize));
228 std::cout <<
"CrossGapsAssociationAlgorithm: Invalid value for SampleStepSize " <<
m_sampleStepSize << std::endl;
229 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
232 PANDORA_RETURN_RESULT_IF_AND_IF(
233 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxUnmatchedSampleRun",
m_maxUnmatchedSampleRun));
235 PANDORA_RETURN_RESULT_IF_AND_IF(
236 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxOnClusterDistance",
m_maxOnClusterDistance));
238 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
241 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
244 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"GapTolerance",
m_gapTolerance));
float m_minMatchedSamplingFraction
Minimum ratio between matched sampling points and expectation to declare association.
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...
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 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...
void PopulateClusterAssociationMap(const pandora::ClusterVector &clusterVector, ClusterAssociationMap &clusterAssociationMap) const
Populate the cluster association map.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Header file for the cross gaps association algorithm class.
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
unsigned int m_minClusterLayers
The minimum allowed number of layers for a clean cluster.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
pandora::CartesianVector GetGlobalMinLayerDirection() const
Get global direction corresponding to the fit result in minimum fit layer.
unsigned int m_minClusterHits
The minimum allowed number of hits in a clean cluster.
unsigned int m_maxSamplingPoints
The maximum number of extension sampling points considered per association check. ...
bool IsAssociated(const pandora::CartesianVector &startPosition, const pandora::CartesianVector &startDirection, const TwoDSlidingFitResult &targetFitResult) const
Sample points along the extrapolation from a starting position to a target fit result to declare clus...
unsigned int m_slidingFitWindow
The layer window for the sliding linear fits.
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.
float m_gapTolerance
The tolerance to use when querying whether a sampling point is in a gap, units cm.
Header file for the cluster helper class.
pandora::StatusCode GetGlobalFitPosition(const float rL, pandora::CartesianVector &position) const
Get global fit position for a given longitudinal coordinate.
unsigned int m_maxUnmatchedSampleRun
The maximum run of unmatched (and non-gap) samples to consider before stopping.
pandora::CartesianVector GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.
static float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
std::unordered_map< const pandora::Cluster *, TwoDSlidingFitResult > TwoDSlidingFitResultMap
float m_maxOnClusterDistance
The maximum distance between a sampling point and sliding fit to target cluster.
const pandora::Cluster * GetCluster() const
Get the address of the cluster, if originally provided.
pandora::StatusCode GetGlobalFitPositionAtX(const float x, pandora::CartesianVector &position) const
Get global fit position for a given input x coordinate.
unsigned int m_minMatchedSamplingPoints
Minimum number of matched sampling points to declare association.
pandora::CartesianVector GetGlobalMaxLayerDirection() const
Get global direction corresponding to the fit result in maximum fit layer.
bool AreClustersAssociated(const TwoDSlidingFitResult &innerFitResult, const TwoDSlidingFitResult &outerFitResult) const
Determine whether two clusters are associated.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
void GetLocalPosition(const pandora::CartesianVector &position, float &rL, float &rT) const
Get local sliding fit coordinates for a given global position.
bool IsNearCluster(const pandora::CartesianVector &samplingPoint, const TwoDSlidingFitResult &targetFitResult) const
Whether a sampling point lies near a target 2d sliding fit result.
pandora::CartesianVector GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
bool IsExtremalCluster(const bool isForward, const pandora::Cluster *const pCurrentCluster, const pandora::Cluster *const pTestCluster) const
Determine which of two clusters is extremal.
float m_sampleStepSize
The sampling step size used in association checks, units cm.
TwoDSlidingFitResult class.
static bool SortByInnerLayer(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by inner layer, then position, then pulse-height.