9 #include "Pandora/AlgorithmHeaders.h" 23 OvershootSplittingAlgorithm::OvershootSplittingAlgorithm() :
25 m_minClusterLength(5.
f),
26 m_maxClusterSeparation(5.
f),
27 m_minVertexDisplacement(2.
f),
28 m_maxIntersectDisplacement(1.5
f),
29 m_minSplitDisplacement(10.
f)
39 const Cluster *
const pCluster = *iter;
44 clusterVector.push_back(pCluster);
72 ClusterList clusterList;
73 for (
const auto &mapEntry : slidingFitResultMap) clusterList.push_back(mapEntry.first);
76 for (
const Cluster *
const pCluster1 : clusterList)
80 for (
const Cluster *
const pCluster2 : clusterList)
82 if (pCluster1 == pCluster2)
96 const bool useInner((innerDisplacement < outerDisplacement) ?
true :
false);
101 float rL2(0.
f), rT2(0.
f);
102 CartesianVector intersectPosition2(0.
f, 0.
f, 0.
f);
108 catch (
const StatusCodeException &)
117 float rL1(0.
f), rT1(0.
f);
118 CartesianVector projectedPosition1(0.
f, 0.
f, 0.
f), projectedDirection1(0.
f, 0.
f, 0.
f);
119 slidingFitResult1.GetLocalPosition(intersectPosition2, rL1, rT1);
121 const StatusCode statusCodePosition(slidingFitResult1.GetGlobalFitPosition(rL1, projectedPosition1));
122 if (STATUS_CODE_SUCCESS != statusCodePosition)
123 throw pandora::StatusCodeException(statusCodePosition);
125 const StatusCode statusCodeDirection(slidingFitResult1.GetGlobalFitDirection(rL1, projectedDirection1));
126 if (STATUS_CODE_SUCCESS != statusCodeDirection)
127 throw pandora::StatusCodeException(statusCodeDirection);
129 const CartesianVector projectedPosition2(clusterVertex.
GetPosition());
130 const CartesianVector projectedDirection2(clusterVertex.
GetDirection());
133 float firstDisplacement(0.
f), secondDisplacement(0.
f);
134 CartesianVector intersectPosition1(0.
f, 0.
f, 0.
f);
139 intersectPosition1, firstDisplacement, secondDisplacement);
141 catch (
const StatusCodeException &)
150 if (
std::max(closestDisplacement1, closestDisplacement2) > m_maxClusterSeparation)
153 const CartesianVector minPosition(slidingFitResult1.GetGlobalMinLayerPosition());
154 const CartesianVector maxPosition(slidingFitResult1.GetGlobalMaxLayerPosition());
155 const float lengthSquared((maxPosition - minPosition).GetMagnitudeSquared());
157 const float minDisplacementSquared((minPosition - intersectPosition1).GetMagnitudeSquared());
158 const float maxDisplacementSquared((maxPosition - intersectPosition1).GetMagnitudeSquared());
161 std::max(minDisplacementSquared, maxDisplacementSquared) > lengthSquared)
164 clusterIntersectionMap[pCluster1].push_back(intersectPosition1);
166 catch (StatusCodeException &statusCodeException)
168 if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
169 throw statusCodeException;
180 ClusterList clusterList;
181 for (
const auto &mapEntry : clusterIntersectionMap) clusterList.push_back(mapEntry.first);
184 for (
const Cluster *
const pCluster : clusterList)
186 const CartesianPointVector &inputPositionVector(clusterIntersectionMap.at(pCluster));
188 if (inputPositionVector.empty())
192 if (slidingFitResultMap.end() == sIter)
193 throw StatusCodeException(STATUS_CODE_FAILURE);
199 pIter != pIterEnd; ++pIter)
201 const CartesianVector &position = *pIter;
202 float rL(0.
f), rT(0.
f);
209 if (trajectoryPointList.empty())
210 throw StatusCodeException(STATUS_CODE_FAILURE);
213 qIter != qIterEnd; ++qIter)
215 const CartesianVector &clusterPosition = qIter->second;
216 sortedIntersectionMap[pCluster].push_back(clusterPosition);
226 ClusterList clusterList;
227 for (
const auto &mapEntry : clusterIntersectionMap) clusterList.push_back(mapEntry.first);
230 for (
const Cluster *
const pCluster : clusterList)
232 const CartesianPointVector &inputPositionVector(clusterIntersectionMap.at(pCluster));
234 if (inputPositionVector.empty())
240 bool foundPrevPosition(
false);
241 CartesianVector prevPosition(0.
f, 0.
f, 0.
f);
244 pIter != pIterEnd; ++pIter)
246 const CartesianVector &nextPosition = *pIter;
248 if (foundPrevPosition)
250 const CartesianVector averagePosition((nextPosition + prevPosition) * 0.5
f);
251 const float displacementSquared((nextPosition - prevPosition).GetMagnitudeSquared());
254 candidatePositionList.push_back(
MyTrajectoryPoint(displacementSquared, averagePosition));
257 prevPosition = nextPosition;
258 foundPrevPosition =
true;
261 if (candidatePositionList.empty())
267 bool foundPrevCandidate(
false);
268 CartesianVector prevCandidate(0.
f, 0.
f, 0.
f);
271 pIter != pIterEnd; ++pIter)
273 const CartesianVector &nextCandidate = pIter->second;
275 if (foundPrevCandidate)
281 clusterSplittingMap[pCluster].push_back(nextCandidate);
282 prevCandidate = nextCandidate;
283 foundPrevCandidate =
true;
292 if (lhs.first != rhs.first)
293 return (lhs.first < rhs.first);
295 return (lhs.second.GetMagnitudeSquared() > rhs.second.GetMagnitudeSquared());
302 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
305 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
308 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
311 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
314 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.
float m_maxClusterSeparation
Header file for the lar pointing cluster 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...
static void GetIntersection(const LArPointingCluster::Vertex &firstVertex, const LArPointingCluster::Vertex &secondVertex, pandora::CartesianVector &intersectPosition, float &firstDisplacement, float &secondDisplacement)
Get intersection of two vertices.
Header file for the overshoot splitting algorithm class.
LArPointingCluster class.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
std::unordered_map< const pandora::Cluster *, TwoDSlidingFitResult > TwoDSlidingFitResultMap
Header file for the cluster helper class.
const Vertex & GetOuterVertex() const
Get the outer vertex.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
const Vertex & GetInnerVertex() const
Get the inner vertex.
float m_maxIntersectDisplacement
float m_minVertexDisplacement
void BuildIntersectionMap(const TwoDSlidingFitResultMap &slidingFitResultMap, ClusterPositionMap &clusterIntersectionMap) const
Use sliding fit results to calculate intersections of clusters.
const pandora::CartesianVector & GetDirection() const
Get the vertex direction.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
void FindBestSplitPositions(const TwoDSlidingFitResultMap &slidingFitResultMap, ClusterPositionMap &clusterSplittingMap) const
Determine best split positions based on sliding fit result.
TwoDTrackSplittingAlgorithm class.
std::vector< MyTrajectoryPoint > MyTrajectoryPointList
float m_minSplitDisplacement
std::pair< float, pandora::CartesianVector > MyTrajectoryPoint
static bool SortByHitProjection(const MyTrajectoryPoint &lhs, const MyTrajectoryPoint &rhs)
Sort pfos by number of constituent hits.
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
void PopulateSplitPositionMap(const ClusterPositionMap &sortedIntersectionMap, ClusterPositionMap &clusterSplittingMap) const
Select split positions from sorted list of candidate positions.
void GetLocalPosition(const pandora::CartesianVector &position, float &rL, float &rT) const
Get local sliding fit coordinates for a given global position.
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
TwoDSlidingFitResult class.
std::unordered_map< const pandora::Cluster *, pandora::CartesianPointVector > ClusterPositionMap
void BuildSortedIntersectionMap(const TwoDSlidingFitResultMap &slidingFitResultMap, const ClusterPositionMap &clusterIntersectionMap, ClusterPositionMap &sortedIntersectionMap) const
Use intersection points to decide on splitting points.
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.