9 #include "Pandora/AlgorithmHeaders.h" 23 TransverseAssociationAlgorithm::TransverseAssociationAlgorithm() :
24 m_firstLengthCut(1.5
f),
25 m_secondLengthCut(7.5
f),
28 m_clusterCosAngle(
std::cos(m_clusterAngle * M_PI / 180.
f)),
29 m_clusterTanAngle(
std::tan(m_clusterAngle * M_PI / 180.
f)),
30 m_maxTransverseOverlap(0.5
f),
31 m_maxProjectedOverlap(1.
f),
32 m_maxLongitudinalOverlap(1.5
f),
33 m_transverseClusterMinCosTheta(0.866
f),
34 m_transverseClusterMinLength(0.5
f),
35 m_transverseClusterMaxDisplacement(1.5
f),
36 m_searchRegionX(3.5
f),
45 clusterVector.clear();
46 clusterVector.insert(clusterVector.begin(), pClusterList->begin(), pClusterList->end());
61 if (nearbyClusters.empty())
68 ClusterVector shortClusters, transverseMediumClusters, longitudinalMediumClusters, longClusters;
69 this->
SortInputClusters(allClusters, shortClusters, transverseMediumClusters, longitudinalMediumClusters, longClusters);
71 ClusterVector transverseClusters(shortClusters.begin(), shortClusters.end());
72 transverseClusters.insert(transverseClusters.end(), transverseMediumClusters.begin(), transverseMediumClusters.end());
74 ClusterVector establishedClusters(transverseMediumClusters.begin(), transverseMediumClusters.end());
75 establishedClusters.insert(establishedClusters.end(), longitudinalMediumClusters.begin(), longitudinalMediumClusters.end());
76 establishedClusters.insert(establishedClusters.end(), longClusters.begin(), longClusters.end());
106 catch (StatusCodeException &statusCodeException)
108 std::cout <<
"TransverseAssociationAlgorithm: exception " << statusCodeException.ToString() << std::endl;
122 CaloHitList allCaloHits;
124 for (
const Cluster *
const pCluster : allClusters)
126 CaloHitList daughterHits;
127 pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
128 allCaloHits.insert(allCaloHits.end(), daughterHits.begin(), daughterHits.end());
130 for (
const CaloHit *
const pCaloHit : daughterHits)
131 (void)hitToClusterMap.insert(HitToClusterMap::value_type(pCaloHit, pCluster));
138 kdTree.
build(hitKDNode2DList, hitsBoundingRegion2D);
140 for (
const Cluster *
const pCluster : allClusters)
142 CaloHitList daughterHits;
143 pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
145 for (
const CaloHit *
const pCaloHit : daughterHits)
150 kdTree.
search(searchRegionHits, found);
152 for (
const auto &
hit : found)
153 (void)nearbyClusters[pCluster].insert(hitToClusterMap.at(
hit.data));
165 const Cluster *
const pCluster = *iter;
169 const float clusterLengthSquared(clusterLengthT * clusterLengthT + clusterLengthL * clusterLengthL);
173 shortVector.push_back(pCluster);
178 transverseMediumVector.push_back(pCluster);
180 longitudinalMediumVector.push_back(pCluster);
184 longVector.push_back(pCluster);
206 this->
FillAssociationMap(nearbyClusters, firstVector, firstVector, firstAssociationMap, firstAssociationMapSwapped);
207 this->
FillAssociationMap(nearbyClusters, firstVector, secondVector, secondAssociationMap, secondAssociationMapSwapped);
208 this->
FillReducedAssociationMap(firstAssociationMap, secondAssociationMap, secondAssociationMapSwapped, clusterAssociationMap);
218 const Cluster *
const pClusterI = *iterI;
222 const Cluster *
const pClusterJ = *iterJ;
224 if (pClusterI == pClusterJ)
227 if (this->
IsAssociated(
true, pClusterI, pClusterJ, nearbyClusters))
229 firstAssociationMap[pClusterI].m_forwardAssociations.insert(pClusterJ);
230 secondAssociationMap[pClusterJ].m_backwardAssociations.insert(pClusterI);
233 if (this->
IsAssociated(
false, pClusterI, pClusterJ, nearbyClusters))
235 firstAssociationMap[pClusterI].m_backwardAssociations.insert(pClusterJ);
236 secondAssociationMap[pClusterJ].m_forwardAssociations.insert(pClusterI);
249 const Cluster *
const pCluster = *iter;
257 if (this->
GetTransverseSpan(pCluster, associatedClusters) < transverseClusterMinLengthAdjusted)
273 const Cluster *
const pInnerCluster(pInnerTransverseCluster->
GetSeedCluster());
276 if (transverseAssociationMap.end() == iterInner)
280 iter2 != iterEnd2; ++iter2)
283 const Cluster *
const pOuterCluster(pOuterTransverseCluster->
GetSeedCluster());
286 if (transverseAssociationMap.end() == iterOuter)
289 if (pInnerCluster == pOuterCluster)
292 if (iterInner->second.m_forwardAssociations.count(pOuterCluster) == 0 || iterOuter->second.m_backwardAssociations.count(pInnerCluster) == 0)
301 clusterAssociationMap[pInnerCluster].m_forwardAssociations.insert(pOuterCluster);
302 clusterAssociationMap[pOuterCluster].m_backwardAssociations.insert(pInnerCluster);
313 if (associationMap.end() == iterI)
316 for (
ClusterSet::const_iterator iterJ = iterI->second.m_forwardAssociations.begin(), iterEndJ = iterI->second.m_forwardAssociations.end();
317 iterJ != iterEndJ; ++iterJ)
319 const Cluster *
const pClusterJ = *iterJ;
322 associatedVector.push_back(pClusterJ);
325 for (
ClusterSet::const_iterator iterJ = iterI->second.m_backwardAssociations.begin(), iterEndJ = iterI->second.m_backwardAssociations.end();
326 iterJ != iterEndJ; ++iterJ)
328 const Cluster *
const pClusterJ = *iterJ;
331 associatedVector.push_back(pClusterJ);
342 if ((0 == nearbyClusters.at(pFirstCluster).count(pSecondCluster)) || (0 == nearbyClusters.at(pSecondCluster).count(pFirstCluster)))
345 CartesianVector firstInner(0.
f, 0.
f, 0.
f), firstOuter(0.
f, 0.
f, 0.
f);
346 CartesianVector secondInner(0.
f, 0.
f, 0.
f), secondOuter(0.
f, 0.
f, 0.
f);
350 const CartesianVector firstCoordinate(isForward ? firstOuter : firstInner);
351 const CartesianVector secondCoordinate(isForward ? secondOuter : secondInner);
357 if ((isForward && secondCoordinate.GetX() < firstCoordinate.GetX()) || (!isForward && secondCoordinate.GetX() > firstCoordinate.GetX()))
366 if ((isForward && firstProjection.GetX() > firstCoordinate.GetX() +
m_clusterWindow) ||
367 (!isForward && firstProjection.GetX() < firstCoordinate.GetX() -
m_clusterWindow))
376 const Cluster *
const pInnerCluster,
const Cluster *
const pOuterCluster,
const ClusterToClustersMap &nearbyClusters)
const 378 if ((0 == nearbyClusters.at(pInnerCluster).count(pOuterCluster)) || (0 == nearbyClusters.at(pOuterCluster).count(pInnerCluster)))
381 CartesianVector innerInner(0.
f, 0.
f, 0.
f), innerOuter(0.
f, 0.
f, 0.
f);
382 CartesianVector outerInner(0.
f, 0.
f, 0.
f), outerOuter(0.
f, 0.
f, 0.
f);
386 const CartesianVector innerCentroid((innerInner + innerOuter) * 0.5);
387 const CartesianVector outerCentroid((outerInner + outerOuter) * 0.5);
389 if ((std::fabs(innerCentroid.GetZ() - outerInner.GetZ()) > std::fabs(innerCentroid.GetX() - outerInner.GetX()) * std::fabs(
m_clusterTanAngle)) &&
390 (std::fabs(innerCentroid.GetZ() - outerOuter.GetZ()) > std::fabs(innerCentroid.GetX() - outerOuter.GetX()) * std::fabs(
m_clusterTanAngle)))
393 if ((std::fabs(outerCentroid.GetZ() - innerInner.GetZ()) > std::fabs(outerCentroid.GetX() - innerInner.GetX()) * std::fabs(
m_clusterTanAngle)) &&
394 (std::fabs(outerCentroid.GetZ() - innerOuter.GetZ()) > std::fabs(outerCentroid.GetX() - innerOuter.GetX()) * std::fabs(
m_clusterTanAngle)))
433 const CartesianVector &innerVertex(pTransverseCluster->
GetInnerVertex());
434 const CartesianVector &outerVertex(pTransverseCluster->
GetOuterVertex());
435 const CartesianVector &direction(pTransverseCluster->
GetDirection());
440 const float transverseMaxDisplacementSquaredAdjusted{transverseMaxDisplacementAdjusted * transverseMaxDisplacementAdjusted};
442 if (direction.GetCrossProduct(testVertex - innerVertex).GetMagnitudeSquared() > transverseMaxDisplacementSquaredAdjusted)
445 if ((direction.GetDotProduct(testVertex - innerVertex) < -1.f *
m_clusterWindow) ||
446 (direction.GetDotProduct(testVertex - outerVertex) > +1.f *
m_clusterWindow))
456 CartesianVector innerInner(0.
f, 0.
f, 0.
f), innerOuter(0.
f, 0.
f, 0.
f);
457 CartesianVector outerInner(0.
f, 0.
f, 0.
f), outerOuter(0.
f, 0.
f, 0.
f);
464 const float innerOverlapSquared((innerProjection - innerOuter).GetMagnitudeSquared());
465 const float outerOverlapSquared((outerProjection - outerInner).GetMagnitudeSquared());
474 float minX(+std::numeric_limits<float>::max());
475 float maxX(-std::numeric_limits<float>::max());
479 return (maxX - minX);
486 float minZ(+std::numeric_limits<float>::max());
487 float maxZ(-std::numeric_limits<float>::max());
491 return (maxZ - minZ);
498 float overallMinX(+std::numeric_limits<float>::max());
499 float overallMaxX(-std::numeric_limits<float>::max());
503 float localMinX(+std::numeric_limits<float>::max());
504 float localMaxX(-std::numeric_limits<float>::max());
508 const Cluster *
const pAssociatedCluster = *iter;
512 if (localMinX < overallMinX)
513 overallMinX = localMinX;
515 if (localMaxX > overallMaxX)
516 overallMaxX = localMaxX;
519 return (overallMaxX - overallMinX);
526 float currentMinX(0.
f), currentMaxX(0.
f);
529 float testMinX(0.
f), testMaxX(0.
f);
534 if (std::fabs(testMaxX - currentMaxX) > std::numeric_limits<float>::epsilon())
535 return (testMaxX > currentMaxX);
539 if (std::fabs(testMinX - currentMaxX) > std::numeric_limits<float>::epsilon())
540 return (testMinX < currentMinX);
564 minXZ = +std::numeric_limits<float>::max();
565 maxXZ = -std::numeric_limits<float>::max();
567 const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
571 for (
CaloHitList::const_iterator hitIter = iter->second->begin(), hitIterEnd = iter->second->end(); hitIter != hitIterEnd; ++hitIter)
573 const float caloHitXZ(useX ? (*hitIter)->GetPositionVector().GetX() : (*hitIter)->GetPositionVector().GetZ());
575 if (caloHitXZ < minXZ)
578 if (caloHitXZ > maxXZ)
584 throw pandora::StatusCodeException(STATUS_CODE_FAILURE);
590 const Cluster *
const pCluster, CartesianVector &innerCoordinate, CartesianVector &outerCoordinate)
const 592 CartesianVector firstCoordinate(0.
f, 0.
f, 0.
f), secondCoordinate(0.
f, 0.
f, 0.
f);
595 innerCoordinate = (firstCoordinate.GetX() < secondCoordinate.GetX() ? firstCoordinate : secondCoordinate);
596 outerCoordinate = (firstCoordinate.GetX() > secondCoordinate.GetX() ? firstCoordinate : secondCoordinate);
604 return this->
FillReducedAssociationMap(inputAssociationMap, inputAssociationMap, inputAssociationMap, outputAssociationMap);
621 for (
const auto &mapEntry : firstAssociationMap)
622 sortedClusters.push_back(mapEntry.first);
625 for (
const Cluster *
const pCluster : sortedClusters)
629 ClusterVector sortedOuterClusters(firstAssociation.m_forwardAssociations.begin(), firstAssociation.m_forwardAssociations.end());
632 ClusterVector sortedInnerClusters(firstAssociation.m_backwardAssociations.begin(), firstAssociation.m_backwardAssociations.end());
638 if (secondAssociationMap.end() != iterSecond)
640 sortedMiddleClustersF.insert(sortedMiddleClustersF.end(), iterSecond->second.m_forwardAssociations.begin(),
641 iterSecond->second.m_forwardAssociations.end());
642 sortedMiddleClustersB.insert(sortedMiddleClustersB.end(), iterSecond->second.m_backwardAssociations.begin(),
643 iterSecond->second.m_backwardAssociations.end());
648 for (
const Cluster *
const pOuterCluster : sortedOuterClusters)
650 bool isNeighbouringCluster(
true);
652 for (
const Cluster *
const pMiddleCluster : sortedMiddleClustersF)
655 if (secondAssociationMapSwapped.end() == iterSecondCheck)
658 if (iterSecondCheck->second.m_forwardAssociations.count(pOuterCluster) > 0)
660 isNeighbouringCluster =
false;
665 if (isNeighbouringCluster)
666 clusterAssociationMap[pCluster].m_forwardAssociations.insert(pOuterCluster);
669 for (
const Cluster *
const pInnerCluster : sortedInnerClusters)
671 bool isNeighbouringCluster(
true);
673 for (
const Cluster *
const pMiddleCluster : sortedMiddleClustersB)
676 if (secondAssociationMapSwapped.end() == iterSecondCheck)
679 if (iterSecondCheck->second.m_backwardAssociations.count(pInnerCluster) > 0)
681 isNeighbouringCluster =
false;
686 if (isNeighbouringCluster)
687 clusterAssociationMap[pCluster].m_backwardAssociations.insert(pInnerCluster);
702 for (
const auto &mapEntry : inputAssociationMap)
703 sortedClusters.push_back(mapEntry.first);
706 for (
const Cluster *
const pCluster : sortedClusters)
710 ClusterVector sortedForwardClusters(inputAssociation.m_forwardAssociations.begin(), inputAssociation.m_forwardAssociations.end());
713 ClusterVector sortedBackwardClusters(inputAssociation.m_backwardAssociations.begin(), inputAssociation.m_backwardAssociations.end());
717 for (
const Cluster *
const pForwardCluster : sortedForwardClusters)
721 if (inputAssociation.m_backwardAssociations.count(pForwardCluster))
725 if (inputAssociationMap.end() != iterCheck)
727 if (iterCheck->second.m_forwardAssociations.count(pCluster))
730 if (iterCheck->second.m_backwardAssociations.count(pCluster))
736 if (!(outputAssociationMap[pCluster].m_backwardAssociations.count(pForwardCluster) == 0 &&
737 outputAssociationMap[pForwardCluster].m_forwardAssociations.count(pCluster) == 0))
738 throw StatusCodeException(STATUS_CODE_FAILURE);
740 outputAssociationMap[pCluster].m_forwardAssociations.insert(pForwardCluster);
741 outputAssociationMap[pForwardCluster].m_backwardAssociations.insert(pCluster);
746 for (
const Cluster *
const pBackwardCluster : sortedBackwardClusters)
750 if (inputAssociation.m_forwardAssociations.count(pBackwardCluster))
754 if (inputAssociationMap.end() != iterCheck)
756 if (iterCheck->second.m_backwardAssociations.count(pCluster))
759 if (iterCheck->second.m_forwardAssociations.count(pCluster))
765 if (!(outputAssociationMap[pCluster].m_forwardAssociations.count(pBackwardCluster) == 0 &&
766 outputAssociationMap[pBackwardCluster].m_backwardAssociations.count(pCluster) == 0))
767 throw StatusCodeException(STATUS_CODE_FAILURE);
769 outputAssociationMap[pCluster].m_backwardAssociations.insert(pBackwardCluster);
770 outputAssociationMap[pBackwardCluster].m_forwardAssociations.insert(pCluster);
790 m_pSeedCluster(pSeedCluster),
791 m_associatedClusters(associatedClusters),
792 m_innerVertex(0.
f, 0.
f, 0.
f),
793 m_outerVertex(0.
f, 0.
f, 0.
f),
794 m_direction(0.
f, 0.
f, 0.
f)
796 double Swxx(0.), Swzx(0.), Swz(0.), Swx(0.), Sw(0.);
797 double minX(std::numeric_limits<double>::max());
798 double maxX(-std::numeric_limits<double>::max());
800 ClusterList clusterList(1, pSeedCluster);
801 clusterList.insert(clusterList.end(), associatedClusters.begin(), associatedClusters.end());
806 iterEndJ = (*iterI)->GetOrderedCaloHitList().end();
807 iterJ != iterEndJ; ++iterJ)
811 const CaloHit *
const pCaloHit = *iterK;
813 if (pCaloHit->GetPositionVector().GetX() < minX)
814 minX = pCaloHit->GetPositionVector().GetX();
816 if (pCaloHit->GetPositionVector().GetX() > maxX)
817 maxX = pCaloHit->GetPositionVector().GetX();
819 Swxx += pCaloHit->GetPositionVector().GetX() * pCaloHit->GetPositionVector().GetX();
820 Swzx += pCaloHit->GetPositionVector().GetZ() * pCaloHit->GetPositionVector().GetX();
821 Swz += pCaloHit->GetPositionVector().GetZ();
822 Swx += pCaloHit->GetPositionVector().GetX();
830 const double averageX(Swx / Sw);
831 const double averageZ(Swz / Sw);
833 if (Sw * Swxx - Swx * Swx > 0.)
835 double m((Sw * Swzx - Swx * Swz) / (Sw * Swxx - Swx * Swx));
836 double px(1. / std::sqrt(1. + m * m));
837 double pz(m / std::sqrt(1. + m * m));
839 m_innerVertex.SetValues(static_cast<float>(minX), 0.
f, static_cast<float>(averageZ + m * (minX - averageX)));
840 m_outerVertex.SetValues(static_cast<float>(maxX), 0.
f, static_cast<float>(averageZ + m * (maxX - averageX)));
841 m_direction.SetValues(static_cast<float>(px), 0.
f, static_cast<float>(pz));
845 m_innerVertex.SetValues(static_cast<float>(averageX), 0.
f, static_cast<float>(averageZ));
846 m_outerVertex.SetValues(static_cast<float>(averageX), 0.
f, static_cast<float>(averageZ));
852 throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
861 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"FirstLengthCut",
m_firstLengthCut));
863 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"SecondLengthCut",
m_secondLengthCut));
865 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"ClusterWindow",
m_clusterWindow));
867 const StatusCode angleStatusCode(XmlHelper::ReadValue(xmlHandle,
"clusterAngle",
m_clusterAngle));
869 if (STATUS_CODE_SUCCESS == angleStatusCode)
874 else if (STATUS_CODE_NOT_FOUND != angleStatusCode)
876 return angleStatusCode;
879 PANDORA_RETURN_RESULT_IF_AND_IF(
880 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxTransverseOverlap",
m_maxTransverseOverlap));
882 PANDORA_RETURN_RESULT_IF_AND_IF(
883 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxProjectedOverlap",
m_maxProjectedOverlap));
885 PANDORA_RETURN_RESULT_IF_AND_IF(
886 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxLongitudinalOverlap",
m_maxLongitudinalOverlap));
888 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
891 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
894 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
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.
void PopulateClusterAssociationMap(const pandora::ClusterVector &clusterVector, ClusterAssociationMap &clusterAssociationMap) const
Populate the cluster association map.
const pandora::Cluster * GetSeedCluster() const
Constructor.
Header file for the kd tree linker algo template class.
pandora::CartesianVector m_outerVertex
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...
const pandora::CartesianVector & GetInnerVertex() const
Get the inner vertex position.
float GetTransverseSpan(const pandora::Cluster *const pCluster) const
Calculate the overall span in X for a clusters.
void FillTransverseAssociationMap(const ClusterToClustersMap &nearbyClusters, const TransverseClusterList &transverseClusterList, const ClusterAssociationMap &transverseAssociationMap, ClusterAssociationMap &clusterAssociationMap) const
Form associations between transverse cluster objects.
Box structure used to define 2D field. It's used in KDTree building step to divide the detector space...
float m_transverseClusterMinLength
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
void GetExtremalCoordinatesXZ(const pandora::Cluster *const pCluster, const bool useX, float &minXZ, float &maxXZ) const
Get minimum and maximum X or Z coordinates for a given cluster.
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
pandora::CartesianVector m_innerVertex
bool IsExtremalCluster(const bool isForward, const pandora::Cluster *const pCurrentCluster, const pandora::Cluster *const pTestCluster) const
Determine which of two clusters is extremal.
void FillSymmetricAssociationMap(const ClusterAssociationMap &inputAssociationMap, ClusterAssociationMap &outputAssociationMap) const
Symmetrise an association map.
bool IsTransverseAssociated(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const ClusterToClustersMap &nearbyClusters) const
Determine whether two clusters are within the same cluster window.
void FillAssociationMap(const ClusterToClustersMap &nearbyClusters, const pandora::ClusterVector &firstVector, const pandora::ClusterVector &secondVector, ClusterAssociationMap &firstAssociationMap, ClusterAssociationMap &secondAssociationMap) const
Form associations between two input lists of cluster.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
std::vector< LArTransverseCluster * > TransverseClusterList
float m_transverseClusterMaxDisplacement
bool IsOverlapping(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2) const
Determine whether two clusters are overlapping.
Header file for the geometry helper class.
float m_maxTransverseOverlap
void GetExtremalCoordinatesX(const pandora::Cluster *const pCluster, float &minX, float &maxX) const
Get minimum and maximum X coordinates for a given cluster.
Header file for the cluster helper class.
pandora::CartesianVector m_direction
float m_searchRegionX
Search region, applied to x dimension, for look-up from kd-trees.
void SortInputClusters(const pandora::ClusterVector &inputClusters, pandora::ClusterVector &shortClusters, pandora::ClusterVector &transverseMediumClusters, pandora::ClusterVector &longitudinalMediumClusters, pandora::ClusterVector &longClusters) const
Separate input clusters by length.
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".
void FillTransverseClusterList(const ClusterToClustersMap &nearbyClusters, const pandora::ClusterVector &inputClusters, const ClusterAssociationMap &inputAssociationMap, TransverseClusterList &transverseClusterList) const
Create transverse cluster objects, these are protoclusters with a direction and inner/outer vertices...
const pandora::CartesianVector & GetOuterVertex() const
Get the outer vertex position.
std::unordered_map< const pandora::Cluster *, pandora::ClusterSet > ClusterToClustersMap
float m_maxLongitudinalOverlap
float m_transverseClusterMinCosTheta
std::unordered_map< const pandora::CaloHit *, const pandora::Cluster * > HitToClusterMap
Detector simulation of raw signals on wires.
ClusterAssociation class.
static void GetExtremalCoordinates(const pandora::ClusterList &clusterList, pandora::CartesianVector &innerCoordinate, pandora::CartesianVector &outerCoordinate)
Get positions of the two most distant calo hits in a list of cluster (ordered by Z) ...
void FinalizeClusterAssociationMap(const ClusterAssociationMap &inputAssociationMap, ClusterAssociationMap &outputAssociationMap) const
Symmetrise and then remove double-counting from an association map.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
float m_maxProjectedOverlap
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...
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
void GetNearbyClusterMap(const pandora::ClusterVector &allClusters, ClusterToClustersMap &nearbyClusters) const
Use a kd-tree to obtain details of all nearby cluster combinations.
const pandora::CartesianVector & GetDirection() const
Get the direction.
bool IsAssociated(const bool isForward, const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const ClusterToClustersMap &nearbyClusters) const
Determine whether clusters are association.
std::vector< HitKDNode2D > HitKDNode2DList
std::vector< art::Ptr< recob::Cluster > > ClusterVector
void FillReducedAssociationMap(const ClusterToClustersMap &nearbyClusters, const pandora::ClusterVector &firstVector, const pandora::ClusterVector &secondVector, ClusterAssociationMap &clusterAssociationMap) const
Form a reduced set of associations between two input lists of clusters.
float GetLongitudinalSpan(const pandora::Cluster *const pCluster) const
Calculate the overall span in Z for a clusters.
Header file for the transverse association algorithm class.
LArTransverseCluster class.
void GetAssociatedClusters(const ClusterToClustersMap &nearbyClusters, const pandora::Cluster *const pCluster, const ClusterAssociationMap &inputAssociationMap, pandora::ClusterVector &associatedClusters) const
Find the clusters that are transversely associated with a target cluster.
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.
float m_searchRegionZ
Search region, applied to u/v/w dimension, for look-up from kd-trees.
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 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...
void GetExtremalCoordinatesZ(const pandora::Cluster *const pCluster, float &minZ, float &maxZ) const
Get minimum and maximum Z coordinates for a given cluster.
LArTransverseCluster(const pandora::Cluster *const pSeedCluster, const pandora::ClusterVector &associatedClusters)
Constructor.