9 #include "Pandora/AlgorithmHeaders.h" 22 TransverseAssociationAlgorithm::TransverseAssociationAlgorithm() :
23 m_firstLengthCut(1.5
f),
24 m_secondLengthCut(7.5
f),
27 m_clusterCosAngle(
std::cos(m_clusterAngle *
M_PI / 180.
f)),
28 m_clusterTanAngle(
std::tan(m_clusterAngle *
M_PI / 180.
f)),
29 m_maxTransverseOverlap(0.5
f),
30 m_maxProjectedOverlap(1.
f),
31 m_maxLongitudinalOverlap(1.5
f),
32 m_transverseClusterMinCosTheta(0.866
f),
33 m_transverseClusterMinLength(0.5
f),
34 m_transverseClusterMaxDisplacement(1.5
f),
35 m_searchRegionX(3.5
f),
44 clusterVector.clear();
45 clusterVector.insert(clusterVector.begin(), pClusterList->begin(), pClusterList->end());
60 if (nearbyClusters.empty())
67 ClusterVector shortClusters, transverseMediumClusters, longitudinalMediumClusters, longClusters;
68 this->
SortInputClusters(allClusters, shortClusters, transverseMediumClusters, longitudinalMediumClusters, longClusters);
70 ClusterVector transverseClusters(shortClusters.begin(), shortClusters.end());
71 transverseClusters.insert(transverseClusters.end(), transverseMediumClusters.begin(), transverseMediumClusters.end());
73 ClusterVector establishedClusters(transverseMediumClusters.begin(), transverseMediumClusters.end());
74 establishedClusters.insert(establishedClusters.end(), longitudinalMediumClusters.begin(), longitudinalMediumClusters.end());
75 establishedClusters.insert(establishedClusters.end(), longClusters.begin(), longClusters.end());
105 catch (StatusCodeException &statusCodeException)
107 std::cout <<
"TransverseAssociationAlgorithm: exception " << statusCodeException.ToString() <<
std::endl;
121 CaloHitList allCaloHits;
123 for (
const Cluster *
const pCluster : allClusters)
125 CaloHitList daughterHits;
126 pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
127 allCaloHits.insert(allCaloHits.end(), daughterHits.begin(), daughterHits.end());
129 for (
const CaloHit *
const pCaloHit : daughterHits)
130 (void)hitToClusterMap.insert(HitToClusterMap::value_type(pCaloHit, pCluster));
137 kdTree.
build(hitKDNode2DList, hitsBoundingRegion2D);
139 for (
const Cluster *
const pCluster : allClusters)
141 CaloHitList daughterHits;
142 pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
144 for (
const CaloHit *
const pCaloHit : daughterHits)
149 kdTree.
search(searchRegionHits, found);
151 for (
const auto &
hit : found)
152 (void)nearbyClusters[pCluster].insert(hitToClusterMap.at(
hit.data));
164 const Cluster *
const pCluster = *iter;
168 const float clusterLengthSquared(clusterLengthT * clusterLengthT + clusterLengthL * clusterLengthL);
172 shortVector.push_back(pCluster);
177 transverseMediumVector.push_back(pCluster);
179 longitudinalMediumVector.push_back(pCluster);
183 longVector.push_back(pCluster);
205 this->
FillAssociationMap(nearbyClusters, firstVector, firstVector, firstAssociationMap, firstAssociationMapSwapped);
206 this->
FillAssociationMap(nearbyClusters, firstVector, secondVector, secondAssociationMap, secondAssociationMapSwapped);
207 this->
FillReducedAssociationMap(firstAssociationMap, secondAssociationMap, secondAssociationMapSwapped, clusterAssociationMap);
217 const Cluster *
const pClusterI = *iterI;
221 const Cluster *
const pClusterJ = *iterJ;
223 if (pClusterI == pClusterJ)
226 if (this->
IsAssociated(
true, pClusterI, pClusterJ, nearbyClusters))
228 firstAssociationMap[pClusterI].m_forwardAssociations.insert(pClusterJ);
229 secondAssociationMap[pClusterJ].m_backwardAssociations.insert(pClusterI);
232 if (this->
IsAssociated(
false, pClusterI, pClusterJ, nearbyClusters))
234 firstAssociationMap[pClusterI].m_backwardAssociations.insert(pClusterJ);
235 secondAssociationMap[pClusterJ].m_forwardAssociations.insert(pClusterI);
248 const Cluster *
const pCluster = *iter;
269 const Cluster *
const pInnerCluster(pInnerTransverseCluster->
GetSeedCluster());
272 if (transverseAssociationMap.end() == iterInner)
276 iter2 != iterEnd2; ++iter2)
279 const Cluster *
const pOuterCluster(pOuterTransverseCluster->
GetSeedCluster());
282 if (transverseAssociationMap.end() == iterOuter)
285 if (pInnerCluster == pOuterCluster)
288 if (iterInner->second.m_forwardAssociations.count(pOuterCluster) == 0 || iterOuter->second.m_backwardAssociations.count(pInnerCluster) == 0)
297 clusterAssociationMap[pInnerCluster].m_forwardAssociations.insert(pOuterCluster);
298 clusterAssociationMap[pOuterCluster].m_backwardAssociations.insert(pInnerCluster);
309 if (associationMap.end() == iterI)
312 for (
ClusterSet::const_iterator iterJ = iterI->second.m_forwardAssociations.begin(), iterEndJ = iterI->second.m_forwardAssociations.end();
313 iterJ != iterEndJ; ++iterJ)
315 const Cluster *
const pClusterJ = *iterJ;
318 associatedVector.push_back(pClusterJ);
321 for (
ClusterSet::const_iterator iterJ = iterI->second.m_backwardAssociations.begin(), iterEndJ = iterI->second.m_backwardAssociations.end();
322 iterJ != iterEndJ; ++iterJ)
324 const Cluster *
const pClusterJ = *iterJ;
327 associatedVector.push_back(pClusterJ);
338 if ((0 == nearbyClusters.at(pFirstCluster).count(pSecondCluster)) || (0 == nearbyClusters.at(pSecondCluster).count(pFirstCluster)))
341 CartesianVector firstInner(0.
f, 0.
f, 0.
f), firstOuter(0.
f, 0.
f, 0.
f);
342 CartesianVector secondInner(0.
f, 0.
f, 0.
f), secondOuter(0.
f, 0.
f, 0.
f);
346 const CartesianVector firstCoordinate(isForward ? firstOuter : firstInner);
347 const CartesianVector secondCoordinate(isForward ? secondOuter : secondInner);
353 if ((isForward && secondCoordinate.GetX() < firstCoordinate.GetX()) || (!isForward && secondCoordinate.GetX() > firstCoordinate.GetX()))
362 if ((isForward && firstProjection.GetX() > firstCoordinate.GetX() +
m_clusterWindow) ||
363 (!isForward && firstProjection.GetX() < firstCoordinate.GetX() -
m_clusterWindow))
372 const Cluster *
const pInnerCluster,
const Cluster *
const pOuterCluster,
const ClusterToClustersMap &nearbyClusters)
const 374 if ((0 == nearbyClusters.at(pInnerCluster).count(pOuterCluster)) || (0 == nearbyClusters.at(pOuterCluster).count(pInnerCluster)))
377 CartesianVector innerInner(0.
f, 0.
f, 0.
f), innerOuter(0.
f, 0.
f, 0.
f);
378 CartesianVector outerInner(0.
f, 0.
f, 0.
f), outerOuter(0.
f, 0.
f, 0.
f);
382 const CartesianVector innerCentroid((innerInner + innerOuter) * 0.5);
383 const CartesianVector outerCentroid((outerInner + outerOuter) * 0.5);
385 if ((std::fabs(innerCentroid.GetZ() - outerInner.GetZ()) > std::fabs(innerCentroid.GetX() - outerInner.GetX()) * std::fabs(
m_clusterTanAngle)) &&
386 (std::fabs(innerCentroid.GetZ() - outerOuter.GetZ()) > std::fabs(innerCentroid.GetX() - outerOuter.GetX()) * std::fabs(
m_clusterTanAngle)))
389 if ((std::fabs(outerCentroid.GetZ() - innerInner.GetZ()) > std::fabs(outerCentroid.GetX() - innerInner.GetX()) * std::fabs(
m_clusterTanAngle)) &&
390 (std::fabs(outerCentroid.GetZ() - innerOuter.GetZ()) > std::fabs(outerCentroid.GetX() - innerOuter.GetX()) * std::fabs(
m_clusterTanAngle)))
429 const CartesianVector &innerVertex(pTransverseCluster->
GetInnerVertex());
430 const CartesianVector &outerVertex(pTransverseCluster->
GetOuterVertex());
447 CartesianVector innerInner(0.
f, 0.
f, 0.
f), innerOuter(0.
f, 0.
f, 0.
f);
448 CartesianVector outerInner(0.
f, 0.
f, 0.
f), outerOuter(0.
f, 0.
f, 0.
f);
455 const float innerOverlapSquared((innerProjection - innerOuter).GetMagnitudeSquared());
456 const float outerOverlapSquared((outerProjection - outerInner).GetMagnitudeSquared());
470 return (maxX - minX);
482 return (maxZ - minZ);
499 const Cluster *
const pAssociatedCluster = *iter;
503 if (localMinX < overallMinX)
504 overallMinX = localMinX;
506 if (localMaxX > overallMaxX)
507 overallMaxX = localMaxX;
510 return (overallMaxX - overallMinX);
517 float currentMinX(0.
f), currentMaxX(0.
f);
520 float testMinX(0.
f), testMaxX(0.
f);
525 if (std::fabs(testMaxX - currentMaxX) > std::numeric_limits<float>::epsilon())
526 return (testMaxX > currentMaxX);
530 if (std::fabs(testMinX - currentMaxX) > std::numeric_limits<float>::epsilon())
531 return (testMinX < currentMinX);
558 const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
562 for (
CaloHitList::const_iterator hitIter = iter->second->begin(), hitIterEnd = iter->second->end(); hitIter != hitIterEnd; ++hitIter)
564 const float caloHitXZ(useX ? (*hitIter)->GetPositionVector().GetX() : (*hitIter)->GetPositionVector().GetZ());
566 if (caloHitXZ < minXZ)
569 if (caloHitXZ > maxXZ)
575 throw pandora::StatusCodeException(STATUS_CODE_FAILURE);
581 const Cluster *
const pCluster, CartesianVector &innerCoordinate, CartesianVector &outerCoordinate)
const 583 CartesianVector firstCoordinate(0.
f, 0.
f, 0.
f), secondCoordinate(0.
f, 0.
f, 0.
f);
586 innerCoordinate = (firstCoordinate.GetX() < secondCoordinate.GetX() ? firstCoordinate : secondCoordinate);
587 outerCoordinate = (firstCoordinate.GetX() > secondCoordinate.GetX() ? firstCoordinate : secondCoordinate);
595 return this->
FillReducedAssociationMap(inputAssociationMap, inputAssociationMap, inputAssociationMap, outputAssociationMap);
612 for (
const auto &mapEntry : firstAssociationMap)
613 sortedClusters.push_back(mapEntry.first);
616 for (
const Cluster *
const pCluster : sortedClusters)
620 ClusterVector sortedOuterClusters(firstAssociation.m_forwardAssociations.begin(), firstAssociation.m_forwardAssociations.end());
623 ClusterVector sortedInnerClusters(firstAssociation.m_backwardAssociations.begin(), firstAssociation.m_backwardAssociations.end());
629 if (secondAssociationMap.end() != iterSecond)
631 sortedMiddleClustersF.insert(sortedMiddleClustersF.end(), iterSecond->second.m_forwardAssociations.begin(),
632 iterSecond->second.m_forwardAssociations.end());
633 sortedMiddleClustersB.insert(sortedMiddleClustersB.end(), iterSecond->second.m_backwardAssociations.begin(),
634 iterSecond->second.m_backwardAssociations.end());
639 for (
const Cluster *
const pOuterCluster : sortedOuterClusters)
641 bool isNeighbouringCluster(
true);
643 for (
const Cluster *
const pMiddleCluster : sortedMiddleClustersF)
646 if (secondAssociationMapSwapped.end() == iterSecondCheck)
649 if (iterSecondCheck->second.m_forwardAssociations.count(pOuterCluster) > 0)
651 isNeighbouringCluster =
false;
656 if (isNeighbouringCluster)
657 clusterAssociationMap[pCluster].m_forwardAssociations.insert(pOuterCluster);
660 for (
const Cluster *
const pInnerCluster : sortedInnerClusters)
662 bool isNeighbouringCluster(
true);
664 for (
const Cluster *
const pMiddleCluster : sortedMiddleClustersB)
667 if (secondAssociationMapSwapped.end() == iterSecondCheck)
670 if (iterSecondCheck->second.m_backwardAssociations.count(pInnerCluster) > 0)
672 isNeighbouringCluster =
false;
677 if (isNeighbouringCluster)
678 clusterAssociationMap[pCluster].m_backwardAssociations.insert(pInnerCluster);
693 for (
const auto &mapEntry : inputAssociationMap)
694 sortedClusters.push_back(mapEntry.first);
697 for (
const Cluster *
const pCluster : sortedClusters)
701 ClusterVector sortedForwardClusters(inputAssociation.m_forwardAssociations.begin(), inputAssociation.m_forwardAssociations.end());
704 ClusterVector sortedBackwardClusters(inputAssociation.m_backwardAssociations.begin(), inputAssociation.m_backwardAssociations.end());
708 for (
const Cluster *
const pForwardCluster : sortedForwardClusters)
712 if (inputAssociation.m_backwardAssociations.count(pForwardCluster))
716 if (inputAssociationMap.end() != iterCheck)
718 if (iterCheck->second.m_forwardAssociations.count(pCluster))
721 if (iterCheck->second.m_backwardAssociations.count(pCluster))
727 if (!(outputAssociationMap[pCluster].m_backwardAssociations.count(pForwardCluster) == 0 &&
728 outputAssociationMap[pForwardCluster].m_forwardAssociations.count(pCluster) == 0))
729 throw StatusCodeException(STATUS_CODE_FAILURE);
731 outputAssociationMap[pCluster].m_forwardAssociations.insert(pForwardCluster);
732 outputAssociationMap[pForwardCluster].m_backwardAssociations.insert(pCluster);
737 for (
const Cluster *
const pBackwardCluster : sortedBackwardClusters)
741 if (inputAssociation.m_forwardAssociations.count(pBackwardCluster))
745 if (inputAssociationMap.end() != iterCheck)
747 if (iterCheck->second.m_backwardAssociations.count(pCluster))
750 if (iterCheck->second.m_forwardAssociations.count(pCluster))
756 if (!(outputAssociationMap[pCluster].m_forwardAssociations.count(pBackwardCluster) == 0 &&
757 outputAssociationMap[pBackwardCluster].m_backwardAssociations.count(pCluster) == 0))
758 throw StatusCodeException(STATUS_CODE_FAILURE);
760 outputAssociationMap[pCluster].m_backwardAssociations.insert(pBackwardCluster);
761 outputAssociationMap[pBackwardCluster].m_forwardAssociations.insert(pCluster);
781 m_pSeedCluster(pSeedCluster),
782 m_associatedClusters(associatedClusters),
783 m_innerVertex(0.
f, 0.
f, 0.
f),
784 m_outerVertex(0.
f, 0.
f, 0.
f),
785 m_direction(0.
f, 0.
f, 0.
f)
787 double Swzz(0.), Swxx(0.), Swzx(0.), Swz(0.), Swx(0.), Sw(0.);
791 ClusterList clusterList(1, pSeedCluster);
792 clusterList.insert(clusterList.end(), associatedClusters.begin(), associatedClusters.end());
797 iterEndJ = (*iterI)->GetOrderedCaloHitList().end();
798 iterJ != iterEndJ; ++iterJ)
802 const CaloHit *
const pCaloHit = *iterK;
804 if (pCaloHit->GetPositionVector().GetX() < minX)
805 minX = pCaloHit->GetPositionVector().GetX();
807 if (pCaloHit->GetPositionVector().GetX() > maxX)
808 maxX = pCaloHit->GetPositionVector().GetX();
810 Swzz += pCaloHit->GetPositionVector().GetZ() * pCaloHit->GetPositionVector().GetZ();
811 Swxx += pCaloHit->GetPositionVector().GetX() * pCaloHit->GetPositionVector().GetX();
812 Swzx += pCaloHit->GetPositionVector().GetZ() * pCaloHit->GetPositionVector().GetX();
813 Swz += pCaloHit->GetPositionVector().GetZ();
814 Swx += pCaloHit->GetPositionVector().GetX();
822 const double averageX(Swx / Sw);
823 const double averageZ(Swz / Sw);
825 if (Sw * Swxx - Swx * Swx > 0.)
827 double m((Sw * Swzx - Swx * Swz) / (Sw * Swxx - Swx * Swx));
828 double px(1. / std::sqrt(1. + m * m));
829 double pz(m / std::sqrt(1. + m * m));
831 m_innerVertex.SetValues(static_cast<float>(minX), 0.
f, static_cast<float>(averageZ + m * (minX - averageX)));
832 m_outerVertex.SetValues(static_cast<float>(maxX), 0.
f, static_cast<float>(averageZ + m * (maxX - averageX)));
833 m_direction.SetValues(static_cast<float>(px), 0.
f, static_cast<float>(pz));
837 m_innerVertex.SetValues(static_cast<float>(averageX), 0.
f, static_cast<float>(averageZ));
838 m_outerVertex.SetValues(static_cast<float>(averageX), 0.
f, static_cast<float>(averageZ));
844 throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
853 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"FirstLengthCut",
m_firstLengthCut));
855 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"SecondLengthCut",
m_secondLengthCut));
857 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"ClusterWindow",
m_clusterWindow));
859 const StatusCode angleStatusCode(XmlHelper::ReadValue(xmlHandle,
"clusterAngle",
m_clusterAngle));
861 if (STATUS_CODE_SUCCESS == angleStatusCode)
866 else if (STATUS_CODE_NOT_FOUND != angleStatusCode)
868 return angleStatusCode;
871 PANDORA_RETURN_RESULT_IF_AND_IF(
872 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxTransverseOverlap",
m_maxTransverseOverlap));
874 PANDORA_RETURN_RESULT_IF_AND_IF(
875 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxProjectedOverlap",
m_maxProjectedOverlap));
877 PANDORA_RETURN_RESULT_IF_AND_IF(
878 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxLongitudinalOverlap",
m_maxLongitudinalOverlap));
880 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
883 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
886 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
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.
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.
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.
static int max(int a, int b)
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.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
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.
QTextStream & endl(QTextStream &s)
LArTransverseCluster(const pandora::Cluster *const pSeedCluster, const pandora::ClusterVector &associatedClusters)
Constructor.