9 #include "Pandora/AlgorithmHeaders.h"
23 CrossedTrackSplittingAlgorithm::CrossedTrackSplittingAlgorithm() :
24 m_maxClusterSeparation(2.f),
25 m_maxClusterSeparationSquared(m_maxClusterSeparation * m_maxClusterSeparation),
26 m_minCosRelativeAngle(0.966f),
37 CaloHitList allCaloHits;
39 for (
const Cluster *
const pCluster : clusterVector)
41 CaloHitList daughterHits;
42 pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
43 allCaloHits.insert(allCaloHits.end(), daughterHits.begin(), daughterHits.end());
45 for (
const CaloHit *
const pCaloHit : daughterHits)
46 (
void)hitToClusterMap.insert(HitToClusterMap::value_type(pCaloHit, pCluster));
53 kdTree.
build(hitKDNode2DList, hitsBoundingRegion2D);
55 for (
const Cluster *
const pCluster : clusterVector)
57 CaloHitList daughterHits;
58 pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
60 for (
const CaloHit *
const pCaloHit : daughterHits)
65 kdTree.
search(searchRegionHits, found);
67 for (
const auto &
hit : found)
72 return STATUS_CODE_SUCCESS;
81 return STATUS_CODE_SUCCESS;
87 const TwoDSlidingFitResult &slidingFitResult2, CartesianVector &splitPosition, CartesianVector &firstDirection, CartesianVector &secondDirection)
const
94 return STATUS_CODE_NOT_FOUND;
109 return STATUS_CODE_NOT_FOUND;
113 return STATUS_CODE_NOT_FOUND;
115 CartesianPointVector candidateVector;
118 if (candidateVector.empty())
119 return STATUS_CODE_NOT_FOUND;
122 bool foundSplit(
false);
123 float closestSeparationSquared(std::numeric_limits<float>::max());
128 for (CartesianPointVector::const_iterator iter = candidateVector.begin(), iterEnd = candidateVector.end(); iter != iterEnd; ++iter)
130 const CartesianVector &candidatePosition(*iter);
133 float rL1(0.f), rT1(0.f);
134 CartesianVector R1(0.f, 0.f, 0.f);
135 CartesianVector
F1(0.f, 0.f, 0.f);
136 CartesianVector B1(0.f, 0.f, 0.f);
142 if ((STATUS_CODE_SUCCESS != slidingFitResult1.
GetGlobalFitPosition(rL1 + halfWindowLength1, F1)) ||
149 float rL2(0.f), rT2(0.f);
150 CartesianVector R2(0.f, 0.f, 0.f);
151 CartesianVector
F2(0.f, 0.f, 0.f);
152 CartesianVector B2(0.f, 0.f, 0.f);
158 if ((STATUS_CODE_SUCCESS != slidingFitResult2.
GetGlobalFitPosition(rL2 + halfWindowLength2, F2)) ||
165 const CartesianVector C0((R1 + R2) * 0.5);
185 const CartesianVector
a1(B1);
186 const CartesianVector
a2(F1);
188 for (
unsigned int iForward = 0; iForward < 2; ++iForward)
190 const CartesianVector b1((0 == iForward) ? F2 : B2);
191 const CartesianVector b2((0 == iForward) ? B2 : F2);
193 const CartesianVector s1((b1 - R2).GetUnitVector());
194 const CartesianVector t1((R1 - a1).GetUnitVector());
195 const CartesianVector s2((b2 - R2).GetUnitVector());
196 const CartesianVector t2((R1 - a2).GetUnitVector());
202 const CartesianVector
p1((b1 - a1).GetUnitVector());
203 const CartesianVector p2((b2 - a2).GetUnitVector());
205 float mu1(0.f), mu2(0.f);
206 CartesianVector C1(0.f, 0.f, 0.f);
212 catch (
const StatusCodeException &)
217 if (mu1 < 0.f || mu2 < 0.f || mu1 > (b1 - a1).GetMagnitude() || mu2 > (b2 - a2).GetMagnitude())
220 const float thisSeparationSquared((C0 - C1).GetMagnitudeSquared());
222 if (thisSeparationSquared < closestSeparationSquared)
224 closestSeparationSquared = thisSeparationSquared;
225 splitPosition = (C0 + C1) * 0.5;
226 firstDirection = t2 * -1.f;
227 secondDirection = t1;
234 return STATUS_CODE_NOT_FOUND;
236 return STATUS_CODE_SUCCESS;
242 const Cluster *
const pCluster1,
const Cluster *
const pCluster2, CartesianPointVector &candidateVector)
const
245 CaloHitList caloHitList1, caloHitList2;
246 pCluster1->GetOrderedCaloHitList().FillCaloHitList(caloHitList1);
247 pCluster2->GetOrderedCaloHitList().FillCaloHitList(caloHitList2);
249 CaloHitVector caloHitVector1(caloHitList1.begin(), caloHitList1.end()), caloHitVector2(caloHitList2.begin(), caloHitList2.end());
253 for (
const CaloHit *
const pCaloHit : caloHitVector1)
255 const CartesianVector position1(pCaloHit->GetPositionVector());
259 candidateVector.push_back((position1 + position2) * 0.5);
262 for (
const CaloHit *
const pCaloHit : caloHitVector2)
264 const CartesianVector position2(pCaloHit->GetPositionVector());
268 candidateVector.push_back((position2 + position1) * 0.5);
276 PANDORA_RETURN_RESULT_IF_AND_IF(
277 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxClusterSeparation",
m_maxClusterSeparation));
280 PANDORA_RETURN_RESULT_IF_AND_IF(
281 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinCosRelativeAngle",
m_minCosRelativeAngle));
283 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"SearchRegion1D",
m_searchRegion1D));
std::vector< HitKDNode2D > HitKDNode2DList
Header file for the kd tree linker algo template class.
pandora::StatusCode FindBestSplitPosition(const TwoDSlidingFitResult &slidingFit1, const TwoDSlidingFitResult &slidingFit2, pandora::CartesianVector &splitPosition, pandora::CartesianVector &direction1, pandora::CartesianVector &direction2) const
Find the best split position and direction for a pair of clusters.
static void GetIntersection(const LArPointingCluster::Vertex &firstVertex, const LArPointingCluster::Vertex &secondVertex, pandora::CartesianVector &intersectPosition, float &firstDisplacement, float &secondDisplacement)
Get intersection of two vertices.
Box structure used to define 2D field. It's used in KDTree building step to divide the detector space...
Header file for the crossed track splitting algorithm class.
float GetLayerFitHalfWindowLength() const
Get the layer fit half window length.
float m_minCosRelativeAngle
maximum relative angle between tracks after un-crossing
float m_maxClusterSeparationSquared
maximum separation of two clusters (squared)
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
std::unordered_map< const pandora::CaloHit *, const pandora::Cluster * > HitToClusterMap
static bool SortHitsByPosition(const pandora::CaloHit *const pLhs, const pandora::CaloHit *const pRhs)
Sort calo hits by their position (use Z, followed by X, followed by Y)
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.
void build(std::vector< KDTreeNodeInfoT< DATA, DIM >> &eltList, const KDTreeBoxT< DIM > ®ion)
Build the KD tree from the "eltList" in the space define by "region".
pandora::CartesianVector GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.
pandora::StatusCode TidyUpStep()
Tidy up any information cached in e.g. the preparation step.
void FindCandidateSplitPositions(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, pandora::CartesianPointVector &candidateVector) const
Find average positions of pairs of hits within a maximum separation.
const pandora::Cluster * GetCluster() const
Get the address of the cluster, if originally provided.
pandora::StatusCode PreparationStep(const pandora::ClusterVector &clusterVector)
Perform any preparatory actions, such as caching information for subsequent expensive calculations...
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch pandora
float m_maxClusterSeparation
maximum separation of two clusters
pandora::StatusCode GetGlobalFitProjection(const pandora::CartesianVector &inputPosition, pandora::CartesianVector &projectedPosition) const
Get projected position on global fit for a given position vector.
KDTreeBox fill_and_bound_2d_kd_tree(const MANAGED_CONTAINER< const T * > &points, std::vector< KDTreeNodeInfoT< const T *, 2 >> &nodes)
fill_and_bound_2d_kd_tree
ClusterToClustersMap m_nearbyClusters
The nearby clusters map.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
std::size_t count(Cont const &cont)
static pandora::CartesianVector GetClosestPosition(const pandora::CartesianVector &position, const pandora::ClusterList &clusterList)
Get closest position in a list of clusters to a specified input position vector.
KDTreeBox build_2d_kd_search_region(const pandora::CaloHit *const point, const float x_span, const float z_span)
build_2d_kd_search_region
void GetLocalPosition(const pandora::CartesianVector &position, float &rL, float &rT) const
Get local sliding fit coordinates for a given global position.
void search(const KDTreeBoxT< DIM > &searchBox, std::vector< KDTreeNodeInfoT< DATA, DIM >> &resRecHitList)
Search in the KDTree for all points that would be contained in the given searchbox The founded points...
float m_searchRegion1D
Search region, applied to each dimension, for look-up from kd-trees.
pandora::CartesianVector GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
physics associatedGroupsWithLeft p1
TwoDSlidingFitResult class.
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.