9 #include "Pandora/AlgorithmHeaders.h" 24 DeltaRayMatchingAlgorithm::DeltaRayMatchingAlgorithm() :
25 m_minCaloHitsPerCluster(3),
26 m_xOverlapWindow(1.
f),
27 m_distanceForMatching(5.
f),
40 if (pfoVector.empty())
42 if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
43 std::cout <<
"DeltaRayMatchingAlgorithm: pfo list " <<
m_parentPfoListName <<
" unavailable." << std::endl;
45 return STATUS_CODE_SUCCESS;
57 return STATUS_CODE_SUCCESS;
74 const ClusterList *pClusterList = NULL;
75 PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*
this,
76 clusterListName, pClusterList))
78 if ((NULL == pClusterList) || pClusterList->empty())
82 CaloHitList allCaloHits;
84 for (
const Cluster *
const pCluster : *pClusterList)
86 CaloHitList daughterHits;
87 pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
88 allCaloHits.insert(allCaloHits.end(), daughterHits.begin(), daughterHits.end());
90 for (
const CaloHit *
const pCaloHit : daughterHits)
91 (void) hitToClusterMap.insert(HitToClusterMap::value_type(pCaloHit, pCluster));
98 kdTree.
build(hitKDNode2DList, hitsBoundingRegion2D);
100 for (
const Cluster *
const pCluster : *pClusterList)
102 CaloHitList daughterHits;
103 pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
105 for (
const CaloHit *
const pCaloHit : daughterHits)
110 kdTree.
search(searchRegionHits, found);
112 for (
const auto &
hit : found)
114 ClusterList &nearbyClusterList(nearbyClusters[pCluster]);
115 const Cluster *
const pNearbyCluster(hitToClusterMap.at(
hit.data));
117 if (nearbyClusterList.end() == std::find(nearbyClusterList.begin(), nearbyClusterList.end(), pNearbyCluster))
118 nearbyClusterList.push_back(pNearbyCluster);
137 const PfoList *pPfoList = NULL;
138 PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*
this,
139 inputPfoListName, pPfoList));
141 if (NULL == pPfoList)
145 pfoVector.push_back(*iter);
154 PfoVector inputVector;
155 this->
GetAllPfos(inputPfoListName, inputVector);
159 const ParticleFlowObject *
const pPfo = *iter;
164 pfoVector.push_back(pPfo);
174 const ClusterList *pClusterList = NULL;
175 PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*
this,
176 inputClusterListName, pClusterList))
178 if (NULL == pClusterList)
183 const Cluster *
const pCluster = *cIter;
188 clusterVector.push_back(pCluster);
205 this->
ThreeViewMatching(clustersU, clustersV, clustersW, clusterLengthMap, pfoLengthMap, initialParticleList);
206 this->
SelectParticles(initialParticleList, clusterLengthMap, finalParticleList);
221 this->
TwoViewMatching(clustersU, clustersV, clusterLengthMap, pfoLengthMap, initialParticleList);
222 this->
TwoViewMatching(clustersV, clustersW, clusterLengthMap, pfoLengthMap, initialParticleList);
223 this->
TwoViewMatching(clustersW, clustersU, clusterLengthMap, pfoLengthMap, initialParticleList);
224 this->
SelectParticles(initialParticleList, clusterLengthMap, finalParticleList);
239 this->
ThreeViewMatching(clustersU, clustersV, clustersW, clusterLengthMap, pfoLengthMap, initialParticleList);
240 this->
OneViewMatching(clustersU, clusterLengthMap, pfoLengthMap, initialParticleList);
241 this->
OneViewMatching(clustersV, clusterLengthMap, pfoLengthMap, initialParticleList);
242 this->
OneViewMatching(clustersW, clusterLengthMap, pfoLengthMap, initialParticleList);
243 this->
SelectParticles(initialParticleList, clusterLengthMap, finalParticleList);
252 if (clusters1.empty() || clusters2.empty() || clusters3.empty())
255 for (
const Cluster *
const pCluster1 : clusters1)
257 if (!pCluster1->IsAvailable())
260 for (
const Cluster *
const pCluster2 : clusters2)
262 if (!pCluster2->IsAvailable())
265 for (
const Cluster *
const pCluster3 : clusters3)
267 if (!pCluster3->IsAvailable())
273 const ParticleFlowObject *pBestPfo = NULL;
274 this->
FindBestParentPfo(pCluster1, pCluster2, pCluster3, clusterLengthMap, pfoLengthMap, pBestPfo);
277 particleList.push_back(
Particle(pCluster1, pCluster2, pCluster3, pBestPfo));
288 if (clusters1.empty() || clusters2.empty())
291 for (
const Cluster *
const pCluster1 : clusters1)
293 if (!pCluster1->IsAvailable())
296 for (
const Cluster *
const pCluster2 : clusters2)
298 if (!pCluster2->IsAvailable())
304 const ParticleFlowObject *pBestPfo = NULL;
305 this->
FindBestParentPfo(pCluster1, pCluster2, NULL, clusterLengthMap, pfoLengthMap, pBestPfo);
307 if (NULL == pBestPfo)
310 particleList.push_back(
Particle(pCluster1, pCluster2, NULL, pBestPfo));
320 if (clusters.empty())
323 for (
const Cluster *
const pCluster : clusters)
325 if (!pCluster->IsAvailable())
328 const ParticleFlowObject *pBestPfo = NULL;
329 this->
FindBestParentPfo(pCluster, NULL, NULL, clusterLengthMap, pfoLengthMap, pBestPfo);
331 if (NULL == pBestPfo)
334 particleList.push_back(
Particle(pCluster, NULL, NULL, pBestPfo));
342 for (
const Particle &particle1 : initialParticles)
344 bool isGoodParticle(
true);
346 for (
const Particle &particle2 : initialParticles)
348 const bool commonU(particle1.GetClusterU() == particle2.GetClusterU());
349 const bool commonV(particle1.GetClusterV() == particle2.GetClusterV());
350 const bool commonW(particle1.GetClusterW() == particle2.GetClusterW());
352 const bool ambiguousU(commonU && NULL != particle1.GetClusterU());
353 const bool ambiguousV(commonV && NULL != particle1.GetClusterV());
354 const bool ambiguousW(commonW && NULL != particle1.GetClusterW());
356 if (commonU && commonV && commonW)
359 if (ambiguousU || ambiguousV || ambiguousW)
361 if (particle2.GetNViews() > particle1.GetNViews())
363 isGoodParticle =
false;
365 else if (particle2.GetNViews() == particle1.GetNViews() && NULL != particle2.GetParentPfo())
367 if ((NULL == particle1.GetParentPfo()) || (particle2.GetNCaloHits() > particle1.GetNCaloHits()) ||
368 (particle2.GetNCaloHits() == particle1.GetNCaloHits() && this->
GetLength(particle2, clusterLengthMap) >= this->
GetLength(particle1, clusterLengthMap)) )
370 isGoodParticle =
false;
379 if (isGoodParticle && NULL != particle1.GetParentPfo())
380 finalParticles.push_back(particle1);
388 PfoVector parentVector, daughterVector;
392 PfoList parentList(parentVector.begin(), parentVector.end());
393 PfoList daughterList(daughterVector.begin(), daughterVector.end());
395 for (
const Particle &particle : particleList)
397 const ParticleFlowObject *
const pParentPfo = particle.GetParentPfo();
399 if (NULL == pParentPfo)
402 const Cluster *
const pClusterU = particle.GetClusterU();
403 const Cluster *
const pClusterV = particle.GetClusterV();
404 const Cluster *
const pClusterW = particle.GetClusterW();
406 if (NULL == pClusterU && NULL == pClusterV && NULL == pClusterW)
407 throw StatusCodeException(STATUS_CODE_FAILURE);
409 ClusterList clusterList;
412 clusterList.push_back(pClusterU);
415 clusterList.push_back(pClusterV);
418 clusterList.push_back(pClusterW);
420 if (parentList.end() != std::find(parentList.begin(), parentList.end(), pParentPfo))
424 else if (daughterList.end() != std::find(daughterList.begin(), daughterList.end(), pParentPfo))
430 throw StatusCodeException(STATUS_CODE_FAILURE);
438 const Cluster *
const pCluster3)
const 440 if (NULL == pCluster1 && NULL == pCluster2 && NULL == pCluster3)
441 throw StatusCodeException(STATUS_CODE_FAILURE);
448 if (NULL != pCluster1)
451 if (NULL != pCluster2)
454 if (NULL != pCluster3)
460 const float xOverlap(xMax - xMin);
462 if (xOverlap < std::numeric_limits<float>::epsilon())
465 if (NULL == pCluster1 || NULL == pCluster2 || NULL == pCluster3)
473 if (hitType1 == hitType2 || hitType2 == hitType3 || hitType3 == hitType1)
474 throw StatusCodeException(STATUS_CODE_FAILURE);
476 const unsigned int nSamplingPoints(1 + static_cast<unsigned int>(xOverlap / xPitch));
478 for (
unsigned int n = 0;
n < nSamplingPoints; ++
n)
480 const float x(xMin + (xMax - xMin) * (static_cast<float>(
n) + 0.5
f) / static_cast<float>(nSamplingPoints));
481 const float xmin(x - xPitch);
482 const float xmax(x + xPitch);
486 float zMin1(0.
f), zMin2(0.
f), zMin3(0.
f), zMax1(0.
f), zMax2(0.
f), zMax3(0.
f);
491 const float z1(0.5
f * (zMin1 + zMax1));
492 const float z2(0.5
f * (zMin2 + zMax2));
493 const float z3(0.5
f * (zMin3 + zMax3));
495 const float dz1(zMax1 - zMin1);
496 const float dz2(zMax2 - zMin2);
497 const float dz3(zMax3 - zMin3);
504 const float deltaSquared(((z1 - zproj1) * (z1 - zproj1) + (z2 - zproj2) * (z2 - zproj2) + (z3 - zproj3) * (z3 - zproj3)) / 3.
f);
505 const float sigmaSquared(dz1 * dz1 + dz2 * dz2 + dz3 * dz3 + dz4 * dz4);
506 const float pseudoChi2(deltaSquared / sigmaSquared);
511 catch(StatusCodeException &statusCodeException)
513 if (STATUS_CODE_NOT_FOUND != statusCodeException.GetStatusCode())
514 throw statusCodeException;
530 if (pfoVector.empty())
531 throw StatusCodeException(STATUS_CODE_FAILURE);
533 unsigned int numViews(0);
534 float lengthSquared(0.
f);
556 for (
const ParticleFlowObject *
const pPfo : pfoVector)
563 float distanceSquared(0.
f);
565 if (NULL != pCluster1)
568 if (NULL != pCluster2)
571 if (NULL != pCluster3)
574 if (distanceSquared < bestDistanceSquared)
577 bestDistanceSquared = distanceSquared;
580 catch (StatusCodeException &statusCodeException)
582 if (!(STATUS_CODE_NOT_FOUND == statusCodeException.GetStatusCode()))
583 throw statusCodeException;
594 if (clusterLengthMap.end() != iter)
598 (void) clusterLengthMap.insert(ClusterLengthMap::value_type(pCluster, lengthSquared));
599 return lengthSquared;
608 if (pfoLengthMap.end() != iter)
612 (void) pfoLengthMap.insert(PfoLengthMap::value_type(pPfo, lengthSquared));
613 return lengthSquared;
620 float lengthSquared(0.
f);
631 return lengthSquared;
640 if ((TPC_VIEW_U != hitType) && (TPC_VIEW_V != hitType) && (TPC_VIEW_W != hitType))
641 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
643 ClusterList comparisonList;
646 if (!nearbyClusters.count(pCluster))
649 ClusterList pfoClusterList;
652 for (
const Cluster *
const pPfoCluster : pfoClusterList)
654 const ClusterList &clusterList(nearbyClusters.at(pCluster));
656 if ((clusterList.end() != std::find(clusterList.begin(), clusterList.end(), pPfoCluster)) &&
657 (comparisonList.end() == std::find(comparisonList.begin(), comparisonList.end(), pPfoCluster)))
659 comparisonList.push_back(pPfoCluster);
663 if (comparisonList.empty())
673 const PfoList *pPfoList = NULL; std::string pfoListName;
674 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*
this, pPfoList, pfoListName));
677 PandoraContentApi::ParticleFlowObject::Parameters pfoParameters;
678 pfoParameters.m_particleId = E_MINUS;
679 pfoParameters.m_charge = PdgTable::GetParticleCharge(pfoParameters.m_particleId.Get());
680 pfoParameters.m_mass = PdgTable::GetParticleMass(pfoParameters.m_particleId.Get());
681 pfoParameters.m_energy = 0.f;
682 pfoParameters.m_momentum = CartesianVector(0.
f, 0.
f, 0.
f);
683 pfoParameters.m_clusterList = clusterList;
685 const ParticleFlowObject *pDaughterPfo(NULL);
686 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::Create(*
this, pfoParameters, pDaughterPfo));
688 if (!pPfoList->empty())
690 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Pfo>(*
this,
m_daughterPfoListName));
691 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SetPfoParentDaughterRelationship(*
this, pParentPfo, pDaughterPfo));
699 for (
const Cluster *
const pDaughterCluster : clusterList)
705 ClusterList pfoClusters;
708 if (pfoClusters.empty())
709 throw StatusCodeException(STATUS_CODE_FAILURE);
711 const Cluster *
const pParentCluster = *(pfoClusters.begin());
713 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*
this, pParentCluster, pDaughterCluster,
714 clusterListName, clusterListName));
722 const ParticleFlowObject *
const pPfo) :
732 m_pClusterU = ((TPC_VIEW_U == hitType1) ? pCluster1 : (TPC_VIEW_U == hitType2) ? pCluster2 : (TPC_VIEW_U == hitType3) ? pCluster3 : NULL);
733 m_pClusterV = ((TPC_VIEW_V == hitType1) ? pCluster1 : (TPC_VIEW_V == hitType2) ? pCluster2 : (TPC_VIEW_V == hitType3) ? pCluster3 : NULL);
734 m_pClusterW = ((TPC_VIEW_W == hitType1) ? pCluster1 : (TPC_VIEW_W == hitType2) ? pCluster2 : (TPC_VIEW_W == hitType3) ? pCluster3 : NULL);
738 throw StatusCodeException(STATUS_CODE_FAILURE);
745 unsigned int numViews(0);
763 unsigned int numCaloHits(0);
782 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"ParentPfoListName",
m_parentPfoListName));
783 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"DaughterPfoListName",
m_daughterPfoListName));
784 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"InputClusterListNameU",
m_inputClusterListNameU));
785 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"InputClusterListNameV",
m_inputClusterListNameV));
786 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"InputClusterListNameW",
m_inputClusterListNameW));
788 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
791 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
794 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
797 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
800 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
803 return STATUS_CODE_SUCCESS;
void InitializeNearbyClusterMap(const std::string &clusterListName, ClusterToClustersMap &nearbyClusters)
Initialize a nearby cluster map with details relating to a specific cluster list. ...
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
float m_xOverlapWindow
The maximum allowed displacement in x position.
float m_pseudoChi2Cut
Pseudo chi2 cut for three view matching.
std::vector< HitKDNode2D > HitKDNode2DList
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.
Header file for the kd tree linker algo template class.
static bool SortByNHits(const pandora::ParticleFlowObject *const pLhs, const pandora::ParticleFlowObject *const pRhs)
Sort pfos by number of constituent hits.
Header file for the pfo helper class.
const pandora::Cluster * GetClusterV() const
Get cluster in V view.
Particle(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const pandora::Cluster *const pCluster3, const pandora::ParticleFlowObject *const pPfo)
Constructor.
void GetTrackPfos(const std::string &inputPfoListName, pandora::PfoVector &pfoVector) const
Get a vector of track-like Pfos in the provided input Pfo lists.
ClusterToClustersMap m_nearbyClustersU
The nearby clusters map for the u view.
static void GetClusters(const pandora::PfoList &pfoList, const pandora::HitType &hitType, pandora::ClusterList &clusterList)
Get a list of clusters of a particular hit type from a list of pfos.
void TwoViewMatching(ClusterLengthMap &clusterLengthMap) const
Match clusters using pairs of views.
std::unordered_map< const pandora::Cluster *, float > ClusterLengthMap
ClusterToClustersMap m_nearbyClustersV
The nearby clusters map for the v view.
void CreateParticles(const ParticleList &particleList) const
Build new particle flow objects.
ClusterToClustersMap m_nearbyClustersW
The nearby clusters map for the w view.
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterToClustersMap
unsigned int GetNCaloHits() const
Get number of calo hits.
Class that implements the KDTree partition of 2D space and a closest point search algorithm...
std::unordered_map< const pandora::ParticleFlowObject *, float > PfoLengthMap
Box structure used to define 2D field. It's used in KDTree building step to divide the detector space...
static void GetClusterSpanZ(const pandora::Cluster *const pCluster, const float xmin, const float xmax, float &zmin, float &zmax)
Get upper and lower Z positions of the calo hits in a cluster in range xmin to xmax.
unsigned int m_minCaloHitsPerCluster
The min number of calo hits per candidate cluster.
std::string m_inputClusterListNameV
The input cluster list name for the v view.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
static bool IsTrack(const pandora::ParticleFlowObject *const pPfo)
Return track flag based on Pfo Particle ID.
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
static float GetTwoDLengthSquared(const pandora::ParticleFlowObject *const pPfo)
Calculate length of Pfo using 2D clusters.
Header file for the geometry helper class.
const pandora::Cluster * m_pClusterU
Address of cluster in U view.
void GetAllPfos(const std::string &inputPfoListName, pandora::PfoVector &pfoVector) const
Get a vector of all Pfos in the provided input Pfo lists.
pandora::StatusCode Run()
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...
std::string m_parentPfoListName
The parent pfo list name.
std::string m_inputClusterListNameW
The input cluster list name for the w view.
float m_searchRegion1D
Search region, applied to each dimension, for look-up from kd-trees.
void OneViewMatching(ClusterLengthMap &clusterLengthMap) const
Match clusters using single views.
Header file for the cluster helper class.
void ThreeViewMatching(ClusterLengthMap &clusterLengthMap) const
Match clusters using all three views.
void InitializeNearbyClusterMaps()
Initialize nearby cluster maps.
static float MergeTwoPositions(const pandora::Pandora &pandora, const pandora::HitType view1, const pandora::HitType view2, const float position1, const float position2)
Merge two views (U,V) to give a third view (Z).
Header file for the delta ray matching algorithm class.
float GetDistanceSquaredToPfo(const pandora::Cluster *const pCluster, const pandora::ParticleFlowObject *const pPfo) const
Get displacementr between cluster and particle flow object.
bool AreClustersMatched(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const pandora::Cluster *const pCluster3) const
Look at consistency of a combination of clusters.
Detector simulation of raw signals on wires.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
void FindBestParentPfo(const pandora::Cluster *const pClusterU, const pandora::Cluster *const pClusterV, const pandora::Cluster *const pClusterW, ClusterLengthMap &clusterLengthMap, PfoLengthMap &pfoLengthMap, const pandora::ParticleFlowObject *&pBestPfo) const
Find best Pfo to associate a UVW triplet.
void AddToDaughterPfo(const pandora::ClusterList &clusterList, const pandora::ParticleFlowObject *const pParentPfo) const
Merge an input cluster list with an existing daughter Pfo.
std::string m_inputClusterListNameU
The input cluster list name for the u view.
float m_distanceForMatching
The maximum allowed distance between tracks and delta rays.
const pandora::Cluster * GetClusterW() const
Get cluster in W view.
void CreateDaughterPfo(const pandora::ClusterList &clusterList, const pandora::ParticleFlowObject *const pParentPfo) const
Create a new Pfo from an input cluster list and set up a parent/daughter relationship.
float GetLength(const Particle &particle, ClusterLengthMap &clusterLengthMap) const
Get the length (squared) of a candidate particle.
const pandora::ParticleFlowObject * m_pParentPfo
Address of parent Pfo.
void ClearNearbyClusterMaps()
Clear nearby cluster maps.
void SelectParticles(const ParticleList &inputParticles, ClusterLengthMap &clusterLengthMap, ParticleList &outputParticles) const
Resolve any ambiguities between candidate particles.
const pandora::Cluster * m_pClusterV
Address of cluster in V view.
std::unordered_map< const pandora::CaloHit *, const pandora::Cluster * > HitToClusterMap
void GetClusters(const std::string &clusterListName, pandora::ClusterVector &clusterVector) const
Get a vector containing all available input clusters in the provided cluster list, storing sliding linear fits in the algorithm cache.
static void GetClusterSpanX(const pandora::Cluster *const pCluster, float &xmin, float &xmax)
Get minimum and maximum X positions of the calo hits in a cluster.
float GetLengthFromCache(const pandora::Cluster *const pCluster, ClusterLengthMap &clusterLengthMap) const
Reduce number of length (squared) calculations by caching results when they are first obtained...
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
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
const pandora::Cluster * m_pClusterW
Address of cluster in W view.
const pandora::Cluster * GetClusterU() const
Get cluster in U view.
std::vector< Particle > ParticleList
unsigned int GetNViews() const
Get number of views.
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 build(std::vector< KDTreeNodeInfoT< DATA, DIM > > &eltList, const KDTreeBoxT< DIM > ®ion)
Build the KD tree from the "eltList" in the space define by "region".
std::string m_daughterPfoListName
The daughter pfo list name for new daughter particles.
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.