9 #include "Pandora/AlgorithmHeaders.h" 21 ThreeDTrackFragmentsAlgorithm::ThreeDTrackFragmentsAlgorithm() :
22 m_nMaxTensorToolRepeats(1000),
24 m_minXOverlapFraction(0.8
f),
25 m_maxPointDisplacementSquared(1.5
f * 1.5
f),
26 m_minMatchedSamplingPointFraction(0.5
f),
39 catch (StatusCodeException &statusCodeException)
41 if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
42 throw statusCodeException;
49 if (!((TPC_VIEW_U == hitType) || (TPC_VIEW_V == hitType) || (TPC_VIEW_W == hitType)))
50 throw StatusCodeException(STATUS_CODE_FAILURE);
54 if (clusterList.end() != std::find(clusterList.begin(), clusterList.end(), pNewCluster))
55 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
57 clusterList.push_back(pNewCluster);
60 const ClusterList &clusterList2((TPC_VIEW_W == hitType) ?
m_clusterListV : m_clusterListW);
62 ClusterVector clusterVector1(clusterList1.begin(), clusterList1.end());
63 ClusterVector clusterVector2(clusterList2.begin(), clusterList2.end());
67 for (
const Cluster *
const pCluster1 : clusterVector1)
69 if (TPC_VIEW_U == hitType)
73 else if (TPC_VIEW_V == hitType)
83 for (
const Cluster *
const pCluster2 : clusterVector2)
85 if (TPC_VIEW_U == hitType)
89 else if (TPC_VIEW_V == hitType)
104 const ClusterList *pNewClusterList = NULL;
105 std::string oldClusterListName, newClusterListName;
107 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::InitializeReclustering(*
this, TrackList(), rebuildList,
108 oldClusterListName));
110 pNewClusterList, newClusterListName));
112 newClusters.insert(newClusters.end(), pNewClusterList->begin(), pNewClusterList->end());
113 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndReclustering(*
this, newClusterListName));
127 for (
const Cluster *
const pClusterU : clusterVectorU)
129 for (
const Cluster *
const pClusterV : clusterVectorV)
133 for (
const Cluster *
const pClusterU : clusterVectorU)
135 for (
const Cluster *
const pClusterW : clusterVectorW)
139 for (
const Cluster *
const pClusterV : clusterVectorV)
141 for (
const Cluster *
const pClusterW : clusterVectorW)
150 const HitType missingHitType(
151 ((NULL != pClusterU) && (NULL != pClusterV) && (NULL == pClusterW)) ? TPC_VIEW_W :
152 ((NULL != pClusterU) && (NULL == pClusterV) && (NULL != pClusterW)) ? TPC_VIEW_V :
153 ((NULL == pClusterU) && (NULL != pClusterV) && (NULL != pClusterW)) ? TPC_VIEW_U : HIT_CUSTOM);
155 if (HIT_CUSTOM == missingHitType)
156 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
160 const Cluster *pMatchedClusterU(NULL), *pMatchedClusterV(NULL), *pMatchedClusterW(NULL);
168 const ClusterList &inputClusterList((TPC_VIEW_U == missingHitType) ? this->
GetInputClusterListU() :
171 const Cluster *pBestMatchedCluster(NULL);
172 const StatusCode statusCode(this->
CalculateOverlapResult(fitResult1, fitResult2, inputClusterList, pBestMatchedCluster, newOverlapResult));
174 if ((STATUS_CODE_SUCCESS != statusCode) && (STATUS_CODE_NOT_FOUND != statusCode))
175 throw StatusCodeException(statusCode);
180 if (STATUS_CODE_SUCCESS == statusCode)
182 pMatchedClusterU = ((NULL != pClusterU) ? pClusterU : pBestMatchedCluster);
183 pMatchedClusterV = ((NULL != pClusterV) ? pClusterV : pBestMatchedCluster);
184 pMatchedClusterW = ((NULL != pClusterW) ? pClusterW : pBestMatchedCluster);
186 if (NULL == pMatchedClusterU || NULL == pMatchedClusterV || NULL == pMatchedClusterW)
187 throw StatusCodeException(STATUS_CODE_FAILURE);
193 catch (StatusCodeException &)
208 float newEnergySum(0.
f), oldEnergySum(0.
f);
209 for (
const CaloHit *
const pCaloHit : newOverlapResult.
GetFragmentCaloHitList()) newEnergySum += pCaloHit->GetHadronicEnergy();
210 for (
const CaloHit *
const pCaloHit : oldOverlapResult.
GetFragmentCaloHitList()) oldEnergySum += pCaloHit->GetHadronicEnergy();
212 if (newEnergySum > oldEnergySum)
220 const ClusterList &inputClusterList,
const Cluster *&pBestMatchedCluster,
FragmentOverlapResult &fragmentOverlapResult)
const 222 const Cluster *
const pCluster1(fitResult1.
GetCluster());
223 const Cluster *
const pCluster2(fitResult2.
GetCluster());
225 float xMin1(0.
f), xMax1(0.
f), xMin2(0.
f), xMax2(0.
f);
231 if (xOverlap < std::numeric_limits<float>::epsilon())
232 return STATUS_CODE_NOT_FOUND;
234 CartesianPointVector projectedPositions;
235 const StatusCode statusCode1(this->
GetProjectedPositions(fitResult1, fitResult2, projectedPositions));
237 if (STATUS_CODE_SUCCESS != statusCode1)
240 CaloHitList matchedHits;
241 ClusterList matchedClusters;
243 const StatusCode statusCode2(this->
GetMatchedHits(inputClusterList, projectedPositions, hitToClusterMap, matchedHits));
245 if (STATUS_CODE_SUCCESS != statusCode2)
248 const StatusCode statusCode3(this->
GetMatchedClusters(matchedHits, hitToClusterMap, matchedClusters, pBestMatchedCluster));
250 if (STATUS_CODE_SUCCESS != statusCode3)
254 return STATUS_CODE_NOT_FOUND;
260 return STATUS_CODE_NOT_FOUND;
262 fragmentOverlapResult = overlapResult;
263 return STATUS_CODE_SUCCESS;
269 CartesianPointVector &projectedPositions)
const 271 const Cluster *
const pCluster1(fitResult1.
GetCluster());
272 const Cluster *
const pCluster2(fitResult2.
GetCluster());
277 const HitType hitType3((TPC_VIEW_U != hitType1 && TPC_VIEW_U != hitType2) ? TPC_VIEW_U :
278 (TPC_VIEW_V != hitType1 && TPC_VIEW_V != hitType2) ? TPC_VIEW_V :
279 (TPC_VIEW_W != hitType1 && TPC_VIEW_W != hitType2) ? TPC_VIEW_W : HIT_CUSTOM);
281 if (HIT_CUSTOM == hitType3)
282 return STATUS_CODE_INVALID_PARAMETER;
285 float xMin1(0.
f), xMax1(0.
f), xMin2(0.
f), xMax2(0.
f);
293 return STATUS_CODE_NOT_FOUND;
301 const float dx_A(std::fabs(minPosition2.GetX() - minPosition1.GetX()));
302 const float dx_B(std::fabs(maxPosition2.GetX() - maxPosition1.GetX()));
303 const float dx_C(std::fabs(maxPosition2.GetX() - minPosition1.GetX()));
304 const float dx_D(std::fabs(minPosition2.GetX() - maxPosition1.GetX()));
307 return STATUS_CODE_NOT_FOUND;
309 const CartesianVector &vtxPosition1(minPosition1);
310 const CartesianVector &endPosition1(maxPosition1);
311 const CartesianVector &vtxPosition2((dx_A < dx_C) ? minPosition2 : maxPosition2);
312 const CartesianVector &endPosition2((dx_A < dx_C) ? maxPosition2 : minPosition2);
316 CartesianVector vtxPosition3D(0.
f, 0.
f, 0.
f);
320 CartesianVector endPosition3D(0.
f, 0.
f, 0.
f);
327 const float nSamplingPoints((endProjection3 - vtxProjection3).GetMagnitude() / samplingPitch);
329 if (nSamplingPoints < 1.
f)
330 return STATUS_CODE_NOT_FOUND;
333 bool foundLastPosition(
false);
334 CartesianVector lastPosition(0.
f,0.
f,0.
f);
336 for (
float iSample = 0.5
f; iSample < nSamplingPoints; iSample += 1.f)
338 const CartesianVector linearPosition3D(vtxPosition3D + (endPosition3D - vtxPosition3D) * (iSample / nSamplingPoints));
343 CartesianVector fitPosition1(0.
f, 0.
f, 0.
f), fitPosition2(0.
f, 0.
f, 0.
f);
351 float rL1(0.
f), rL2(0.
f), rT1(0.
f), rT2(0.
f);
355 const float x(0.5 * (fitPosition1.GetX() + fitPosition2.GetX()));
356 CartesianVector position1(0.
f, 0.
f, 0.
f), position2(0.
f, 0.
f, 0.
f), position3(0.
f, 0.
f, 0.
f);
369 catch (StatusCodeException &statusCodeException)
371 if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
372 throw statusCodeException;
380 if (foundLastPosition)
382 const float thisDisplacement((lastPosition - position3).GetMagnitude());
383 if (thisDisplacement > 2.
f * samplingPitch)
385 const float nExtraPoints(thisDisplacement / samplingPitch);
386 for (
float iExtra = 0.5
f; iExtra < nExtraPoints; iExtra += 1.f)
388 const CartesianVector extraPosition(position3 + (lastPosition - position3) * (iExtra / nExtraPoints));
389 projectedPositions.push_back(extraPosition);
394 projectedPositions.push_back(position3);
396 lastPosition = position3;
397 foundLastPosition =
true;
401 if (projectedPositions.empty())
402 return STATUS_CODE_NOT_FOUND;
404 return STATUS_CODE_SUCCESS;
412 CaloHitVector availableCaloHits;
416 const Cluster *
const pCluster = *iter;
418 if (!pCluster->IsAvailable())
421 CaloHitList caloHitList;
422 pCluster->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
423 availableCaloHits.insert(availableCaloHits.end(), caloHitList.begin(), caloHitList.end());
426 hitToClusterMap.insert(HitToClusterMap::value_type(*hIter, pCluster));
431 for (
const CartesianVector &projectedPosition : projectedPositions)
433 const CaloHit *pClosestCaloHit(NULL);
436 for (
const CaloHit *
const pCaloHit : availableCaloHits)
438 const float distanceSquared((pCaloHit->GetPositionVector() - projectedPosition).GetMagnitudeSquared());
440 if ((distanceSquared < closestDistanceSquared) || ((std::fabs(distanceSquared - closestDistanceSquared) < std::numeric_limits<float>::epsilon()) && (pCaloHit->GetHadronicEnergy() > tieBreakerBestEnergy)))
442 pClosestCaloHit = pCaloHit;
443 closestDistanceSquared = distanceSquared;
444 tieBreakerBestEnergy = pCaloHit->GetHadronicEnergy();
448 if ((closestDistanceSquared <
m_maxPointDisplacementSquared) && (NULL != pClosestCaloHit) && (matchedHits.end() == std::find(matchedHits.begin(), matchedHits.end(), pClosestCaloHit)))
449 matchedHits.push_back(pClosestCaloHit);
452 if (matchedHits.empty())
453 return STATUS_CODE_NOT_FOUND;
455 return STATUS_CODE_SUCCESS;
461 ClusterList &matchedClusters,
const Cluster *&pBestMatchedCluster)
const 467 const CaloHit *
const pCaloHit = *iter;
470 if (hitToClusterMap.end() == cIter)
471 throw StatusCodeException(STATUS_CODE_FAILURE);
473 ++clusterToMatchedHitsMap[cIter->second];
475 if (matchedClusters.end() == std::find(matchedClusters.begin(), matchedClusters.end(), cIter->second))
476 matchedClusters.push_back(cIter->second);
479 if (matchedClusters.empty())
480 return STATUS_CODE_NOT_FOUND;
482 pBestMatchedCluster = NULL;
483 unsigned int bestClusterMatchedHits(0);
484 float tieBreakerBestEnergy(0.
f);
487 for (
const auto &mapEntry : clusterToMatchedHitsMap) sortedClusters.push_back(mapEntry.first);
490 for (
const Cluster *
const pCluster : sortedClusters)
492 const unsigned int nMatchedHits(clusterToMatchedHitsMap.at(pCluster));
494 if ((nMatchedHits > bestClusterMatchedHits) || ((nMatchedHits == bestClusterMatchedHits) && (pCluster->GetHadronicEnergy() > tieBreakerBestEnergy)))
496 pBestMatchedCluster = pCluster;
497 bestClusterMatchedHits = nMatchedHits;
498 tieBreakerBestEnergy = pCluster->GetHadronicEnergy();
502 if (NULL == pBestMatchedCluster)
503 return STATUS_CODE_NOT_FOUND;
505 return STATUS_CODE_SUCCESS;
514 unsigned int nMatchedSamplingPoints(0);
516 CaloHitVector sortedMatchedHits(matchedHits.begin(), matchedHits.end());
519 for (
const CartesianVector &projectedPosition : projectedPositions)
523 for (
const CaloHit *
const pCaloHit : matchedHits)
525 const float distanceSquared((pCaloHit->GetPositionVector() - projectedPosition).GetMagnitudeSquared());
527 if (distanceSquared < closestDistanceSquared)
528 closestDistanceSquared = distanceSquared;
533 ++nMatchedSamplingPoints;
534 chi2Sum += closestDistanceSquared;
538 fragmentOverlapResult =
FragmentOverlapResult(nMatchedSamplingPoints, projectedPositions.size(), chi2Sum, matchedHits, matchedClusters);
545 if (projectedPositions.empty() || matchedClusters.empty())
554 for (
const CartesianVector &projectedPosition : projectedPositions)
556 minXproj =
std::min(minXproj, projectedPosition.GetX());
557 maxXproj =
std::max(maxXproj, projectedPosition.GetX());
558 minZproj =
std::min(minZproj, projectedPosition.GetZ());
559 maxZproj =
std::max(maxZproj, projectedPosition.GetZ());
562 const float dXproj(maxXproj - minXproj);
563 const float dZproj(maxZproj - minZproj);
564 const float projectedLengthSquared(dXproj * dXproj + dZproj * dZproj);
572 for (
const Cluster *
const pCluster : matchedClusters)
574 CartesianVector minPosition(0.
f,0.
f,0.
f);
575 CartesianVector maxPosition(0.
f,0.
f,0.
f);
579 minXcluster =
std::min(minXcluster, minPosition.GetX());
580 maxXcluster =
std::max(maxXcluster, maxPosition.GetX());
581 minZcluster =
std::min(minZcluster, minPosition.GetZ());
582 maxZcluster =
std::max(maxZcluster, maxPosition.GetZ());
585 const float dXcluster(maxXcluster - minXcluster);
586 const float dZcluster(maxZcluster - minZcluster);
587 const float clusterLengthSquared(dXcluster * dXcluster + dZcluster * dZcluster);
590 if (clusterLengthSquared > 4.
f * projectedLengthSquared)
614 unsigned int repeatCounter(0);
636 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithm(*
this, xmlHandle,
639 AlgorithmToolVector algorithmToolVector;
640 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*
this, xmlHandle,
641 "TrackTools", algorithmToolVector));
645 FragmentTensorTool *
const pFragmentTensorTool(dynamic_cast<FragmentTensorTool*>(*iter));
647 if (NULL == pFragmentTensorTool)
648 return STATUS_CODE_INVALID_PARAMETER;
653 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
656 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
659 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
663 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
664 "MaxPointDisplacement", maxPointDisplacement));
667 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
670 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_minMatchedSamplingPointFraction
minimum fraction of matched sampling points
FragmentOverlapResult class.
void ExamineTensor()
Examine contents of tensor, collect together best-matching 2D particles and modify clusters as requir...
const pandora::ClusterList & GetInputClusterListW() const
Get the input w cluster list.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
pandora::ClusterList m_clusterListW
The selected modified cluster list W.
void PerformMainLoop()
Main loop over cluster combinations in order to populate the tensor. Responsible for calling Calculat...
static void MergeTwoPositions3D(const pandora::Pandora &pandora, const pandora::HitType view1, const pandora::HitType view2, const pandora::CartesianVector &position1, const pandora::CartesianVector &position2, pandora::CartesianVector &position3D, float &chiSquared)
Merge 2D positions from two views to give unified 3D position.
bool IsInitialized() const
Whether the track overlap result has been initialized.
void CalculateOverlapResult(const pandora::Cluster *const pClusterU, const pandora::Cluster *const pClusterV, const pandora::Cluster *const pClusterW)
Calculate cluster overlap result and store in tensor.
pandora::StatusCode GetMatchedHits(const pandora::ClusterList &inputClusterList, const pandora::CartesianPointVector &projectedPositions, HitToClusterMap &hitToClusterMap, pandora::CaloHitList &matchedCaloHits) const
Get the list of hits associated with the projected positions and a useful hit to cluster map...
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
void ReplaceOverlapResult(const pandora::Cluster *const pClusterU, const pandora::Cluster *const pClusterV, const pandora::Cluster *const pClusterW, const OverlapResult &overlapResult)
SetReplace an existing overlap result.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
void UpdateForNewCluster(const pandora::Cluster *const pNewCluster)
Update to reflect addition of a new cluster to the problem space.
const TwoDSlidingFitResult & GetCachedSlidingFitResult(const pandora::Cluster *const pCluster) const
Get a sliding fit result from the algorithm cache.
std::unordered_map< const pandora::CaloHit *, const pandora::Cluster * > HitToClusterMap
std::unordered_map< const pandora::Cluster *, unsigned int > ClusterToMatchedHitsMap
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
void AddToSlidingFitCache(const pandora::Cluster *const pCluster)
Add a new sliding fit result, for the specified cluster, to the algorithm cache.
pandora::ClusterList m_clusterListV
The selected modified cluster list V.
Header file for the geometry helper class.
static void GetClusterBoundingBox(const pandora::Cluster *const pCluster, pandora::CartesianVector &minimumCoordinate, pandora::CartesianVector &maximumCoordinate)
Get minimum and maximum X, Y and Z positions of the calo hits in a cluster.
unsigned int m_nMaxTensorToolRepeats
The maximum number of repeat loops over tensor tools.
const pandora::CaloHitList & GetFragmentCaloHitList() const
Get the list of fragment-associated hits.
void SetOverlapResult(const pandora::Cluster *const pClusterU, const pandora::Cluster *const pClusterV, const pandora::Cluster *const pClusterW, const OverlapResult &overlapResult)
Set overlap result.
const pandora::ClusterList & GetInputClusterListV() const
Get the input v cluster list.
std::string m_reclusteringAlgorithmName
Name of daughter algorithm to use for cluster re-building.
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.
TensorType m_overlapTensor
The overlap tensor.
float GetMatchedFraction() const
Get the fraction of sampling points resulting in a match.
bool CheckMatchedClusters(const pandora::CartesianPointVector &projectedPositions, const pandora::ClusterList &matchedClusters) const
Whether the matched clusters are consistent with the projected positions.
const pandora::ClusterList & GetInputClusterListU() const
Get the input u cluster list.
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).
const FitSegment & GetFitSegment(const float rL) const
Get fit segment for a given longitudinal coordinate.
pandora::CartesianVector GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.
unsigned int m_minMatchedHits
minimum number of matched calo hits
TensorToolVector m_algorithmToolVector
The algorithm tool list.
Header file for the three dimensional fragments algorithm base class.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
float m_minXOverlapFraction
requirement on minimum X overlap fraction for associated clusters
const pandora::Cluster * GetCluster() const
Get the address of the cluster, if originally provided.
const OverlapResult & GetOverlapResult(const pandora::Cluster *const pClusterU, const pandora::Cluster *const pClusterV, const pandora::Cluster *const pClusterW) const
Get the overlap result for a specified trio of clusters.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
pandora::StatusCode GetGlobalFitProjection(const pandora::CartesianVector &inputPosition, pandora::CartesianVector &projectedPosition) const
Get projected position on global fit for a given position vector.
bool CheckOverlapResult(const FragmentOverlapResult &overlapResult) const
Whether the matched clusters and hits pass the algorithm quality cuts.
pandora::StatusCode GetTransverseProjection(const float x, const FitSegment &fitSegment, pandora::CartesianVector &position) const
Get projected position for a given input x coordinate and fit segment.
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.
pandora::ClusterList m_clusterListU
The selected modified cluster list U.
float m_minXOverlap
requirement on minimum X overlap for associated clusters
FragmentTensorTool class.
void GetLocalPosition(const pandora::CartesianVector &position, float &rL, float &rT) const
Get local sliding fit coordinates for a given global position.
pandora::CartesianVector GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
TwoDSlidingFitResult class.
float m_maxPointDisplacementSquared
maximum allowed distance (squared) between projected points and associated hits
pandora::StatusCode GetProjectedPositions(const TwoDSlidingFitResult &fitResult1, const TwoDSlidingFitResult &fitResult2, pandora::CartesianPointVector &projectedPositions) const
Get the list of projected positions, in the third view, corresponding to a pair of sliding fit result...
pandora::StatusCode GetMatchedClusters(const pandora::CaloHitList &matchedHits, const HitToClusterMap &hitToClusterMap, pandora::ClusterList &matchedClusters, const pandora::Cluster *&pBestMatchedCluster) const
Get the list of the relevant clusters and the address of the single best matched cluster.
void GetFragmentOverlapResult(const pandora::CartesianPointVector &projectedPositions, const pandora::CaloHitList &matchedHits, const pandora::ClusterList &matchedClusters, FragmentOverlapResult &fragmentOverlapResult) const
Get the populated fragment overlap result.
void RebuildClusters(const pandora::ClusterList &rebuildList, pandora::ClusterList &newClusters) const
Rebuild clusters after fragmentation.