9 #include "Pandora/AlgorithmHeaders.h" 21 ThreeViewTrackFragmentsAlgorithm::ThreeViewTrackFragmentsAlgorithm() :
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 ClusterList &clusterList((TPC_VIEW_U == hitType) ? matchingControl.
m_clusterListU 58 if (clusterList.end() != std::find(clusterList.begin(), clusterList.end(), pNewCluster))
59 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
61 clusterList.push_back(pNewCluster);
68 for (
const Cluster *
const pCluster1 : clusterList1)
70 if (TPC_VIEW_U == hitType)
74 else if (TPC_VIEW_V == hitType)
84 for (
const Cluster *
const pCluster2 : clusterList2)
86 if (TPC_VIEW_U == hitType)
90 else if (TPC_VIEW_V == hitType)
105 const ClusterList *pNewClusterList =
nullptr;
106 std::string oldClusterListName, newClusterListName;
108 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::InitializeReclustering(*
this, TrackList(), rebuildList, oldClusterListName));
109 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
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 : clusterListU)
129 for (
const Cluster *
const pClusterV : clusterListV)
133 for (
const Cluster *
const pClusterU : clusterListU)
135 for (
const Cluster *
const pClusterW : clusterListW)
139 for (
const Cluster *
const pClusterV : clusterListV)
141 for (
const Cluster *
const pClusterW : clusterListW)
150 const HitType missingHitType(((
nullptr != pClusterU) && (
nullptr != pClusterV) && (
nullptr == pClusterW)) ? TPC_VIEW_W
151 : ((
nullptr != pClusterU) && (
nullptr == pClusterV) && (
nullptr != pClusterW)) ? TPC_VIEW_V
152 : ((
nullptr == pClusterU) && (
nullptr != pClusterV) && (
nullptr != pClusterW)) ? TPC_VIEW_U
155 if (HIT_CUSTOM == missingHitType)
156 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
160 const Cluster *pMatchedClusterU(
nullptr), *pMatchedClusterV(
nullptr), *pMatchedClusterW(
nullptr);
171 const Cluster *pBestMatchedCluster(
nullptr);
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);
182 if (STATUS_CODE_SUCCESS == statusCode)
184 pMatchedClusterU = ((
nullptr != pClusterU) ? pClusterU : pBestMatchedCluster);
185 pMatchedClusterV = ((
nullptr != pClusterV) ? pClusterV : pBestMatchedCluster);
186 pMatchedClusterW = ((
nullptr != pClusterW) ? pClusterW : pBestMatchedCluster);
188 if (
nullptr == pMatchedClusterU ||
nullptr == pMatchedClusterV ||
nullptr == pMatchedClusterW)
189 throw StatusCodeException(STATUS_CODE_FAILURE);
193 oldOverlapResult = overlapTensor.
GetOverlapResult(pMatchedClusterU, pMatchedClusterV, pMatchedClusterW);
195 catch (StatusCodeException &)
202 overlapTensor.
SetOverlapResult(pMatchedClusterU, pMatchedClusterV, pMatchedClusterW, newOverlapResult);
206 overlapTensor.
ReplaceOverlapResult(pMatchedClusterU, pMatchedClusterV, pMatchedClusterW, newOverlapResult);
210 float newEnergySum(0.
f), oldEnergySum(0.
f);
212 newEnergySum += pCaloHit->GetHadronicEnergy();
214 oldEnergySum += pCaloHit->GetHadronicEnergy();
216 if (newEnergySum > oldEnergySum)
217 overlapTensor.
ReplaceOverlapResult(pMatchedClusterU, pMatchedClusterV, pMatchedClusterW, newOverlapResult);
224 const ClusterList &inputClusterList,
const Cluster *&pBestMatchedCluster,
FragmentOverlapResult &fragmentOverlapResult)
const 226 const Cluster *
const pCluster1(fitResult1.
GetCluster());
227 const Cluster *
const pCluster2(fitResult2.
GetCluster());
229 float xMin1(0.
f), xMax1(0.
f), xMin2(0.
f), xMax2(0.
f);
230 pCluster1->GetClusterSpanX(xMin1, xMax1);
231 pCluster2->GetClusterSpanX(xMin2, xMax2);
233 const float xOverlap(std::min(xMax1, xMax2) - std::max(xMin1, xMin2));
235 if (xOverlap < std::numeric_limits<float>::epsilon())
236 return STATUS_CODE_NOT_FOUND;
238 CartesianPointVector projectedPositions;
239 const StatusCode statusCode1(this->
GetProjectedPositions(fitResult1, fitResult2, projectedPositions));
241 if (STATUS_CODE_SUCCESS != statusCode1)
244 CaloHitList matchedHits;
245 ClusterList matchedClusters;
247 const StatusCode statusCode2(this->
GetMatchedHits(inputClusterList, projectedPositions, hitToClusterMap, matchedHits));
249 if (STATUS_CODE_SUCCESS != statusCode2)
252 const StatusCode statusCode3(this->
GetMatchedClusters(matchedHits, hitToClusterMap, matchedClusters, pBestMatchedCluster));
254 if (STATUS_CODE_SUCCESS != statusCode3)
258 return STATUS_CODE_NOT_FOUND;
264 return STATUS_CODE_NOT_FOUND;
266 fragmentOverlapResult = overlapResult;
267 return STATUS_CODE_SUCCESS;
275 const Cluster *
const pCluster1(fitResult1.
GetCluster());
276 const Cluster *
const pCluster2(fitResult2.
GetCluster());
281 const HitType hitType3((TPC_VIEW_U != hitType1 && TPC_VIEW_U != hitType2) ? TPC_VIEW_U
282 : (TPC_VIEW_V != hitType1 && TPC_VIEW_V != hitType2) ? TPC_VIEW_V
283 : (TPC_VIEW_W != hitType1 && TPC_VIEW_W != hitType2) ? TPC_VIEW_W
286 if (HIT_CUSTOM == hitType3)
287 return STATUS_CODE_INVALID_PARAMETER;
290 float xMin1(0.
f), xMax1(0.
f), xMin2(0.
f), xMax2(0.
f);
291 pCluster1->GetClusterSpanX(xMin1, xMax1);
292 pCluster2->GetClusterSpanX(xMin2, xMax2);
294 const float xOverlap(std::min(xMax1, xMax2) - std::max(xMin1, xMin2));
295 const float xSpan(std::max(xMax1, xMax2) - std::min(xMin1, xMin2));
298 return STATUS_CODE_NOT_FOUND;
306 const float dx_A(std::fabs(minPosition2.GetX() - minPosition1.GetX()));
307 const float dx_B(std::fabs(maxPosition2.GetX() - maxPosition1.GetX()));
308 const float dx_C(std::fabs(maxPosition2.GetX() - minPosition1.GetX()));
309 const float dx_D(std::fabs(minPosition2.GetX() - maxPosition1.GetX()));
311 if (std::min(dx_C, dx_D) > std::max(dx_A, dx_B) && std::min(dx_A, dx_B) > std::max(dx_C, dx_D))
312 return STATUS_CODE_NOT_FOUND;
314 const CartesianVector &vtxPosition1(minPosition1);
315 const CartesianVector &endPosition1(maxPosition1);
316 const CartesianVector &vtxPosition2((dx_A < dx_C) ? minPosition2 : maxPosition2);
317 const CartesianVector &endPosition2((dx_A < dx_C) ? maxPosition2 : minPosition2);
321 CartesianVector vtxPosition3D(0.
f, 0.
f, 0.
f);
325 CartesianVector endPosition3D(0.
f, 0.
f, 0.
f);
334 const float pitchMax{std::max({pitchU, pitchV, pitchW})};
335 const float samplingPitch(0.5
f * pitchMax);
336 const float nSamplingPoints((endProjection3 - vtxProjection3).GetMagnitude() / samplingPitch);
338 if (nSamplingPoints < 1.
f)
339 return STATUS_CODE_NOT_FOUND;
342 bool foundLastPosition(
false);
343 CartesianVector lastPosition(0.
f, 0.
f, 0.
f);
345 for (
float iSample = 0.5
f; iSample < nSamplingPoints; iSample += 1.f)
347 const CartesianVector linearPosition3D(vtxPosition3D + (endPosition3D - vtxPosition3D) * (iSample / nSamplingPoints));
352 CartesianVector fitPosition1(0.
f, 0.
f, 0.
f), fitPosition2(0.
f, 0.
f, 0.
f);
360 float rL1(0.
f), rL2(0.
f), rT1(0.
f), rT2(0.
f);
364 const float x(0.5 * (fitPosition1.GetX() + fitPosition2.GetX()));
365 CartesianVector position1(0.
f, 0.
f, 0.
f), position2(0.
f, 0.
f, 0.
f), position3(0.
f, 0.
f, 0.
f);
378 catch (StatusCodeException &statusCodeException)
380 if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
381 throw statusCodeException;
389 if (foundLastPosition)
391 const float thisDisplacement((lastPosition - position3).GetMagnitude());
392 if (thisDisplacement > 2.
f * samplingPitch)
394 const float nExtraPoints(thisDisplacement / samplingPitch);
395 for (
float iExtra = 0.5
f; iExtra < nExtraPoints; iExtra += 1.f)
397 const CartesianVector extraPosition(position3 + (lastPosition - position3) * (iExtra / nExtraPoints));
398 projectedPositions.push_back(extraPosition);
403 projectedPositions.push_back(position3);
405 lastPosition = position3;
406 foundLastPosition =
true;
410 if (projectedPositions.empty())
411 return STATUS_CODE_NOT_FOUND;
413 return STATUS_CODE_SUCCESS;
419 const CartesianPointVector &projectedPositions,
HitToClusterMap &hitToClusterMap, CaloHitList &matchedHits)
const 421 CaloHitVector availableCaloHits;
425 const Cluster *
const pCluster = *iter;
427 if (!pCluster->IsAvailable())
430 CaloHitList caloHitList;
431 pCluster->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
432 availableCaloHits.insert(availableCaloHits.end(), caloHitList.begin(), caloHitList.end());
435 hitToClusterMap.insert(HitToClusterMap::value_type(*hIter, pCluster));
440 for (
const CartesianVector &projectedPosition : projectedPositions)
442 const CaloHit *pClosestCaloHit(
nullptr);
443 float closestDistanceSquared(std::numeric_limits<float>::max()), tieBreakerBestEnergy(0.
f);
445 for (
const CaloHit *
const pCaloHit : availableCaloHits)
447 const float distanceSquared((pCaloHit->GetPositionVector() - projectedPosition).GetMagnitudeSquared());
449 if ((distanceSquared < closestDistanceSquared) ||
450 ((std::fabs(distanceSquared - closestDistanceSquared) < std::numeric_limits<float>::epsilon()) &&
451 (pCaloHit->GetHadronicEnergy() > tieBreakerBestEnergy)))
453 pClosestCaloHit = pCaloHit;
454 closestDistanceSquared = distanceSquared;
455 tieBreakerBestEnergy = pCaloHit->GetHadronicEnergy();
460 (matchedHits.end() == std::find(matchedHits.begin(), matchedHits.end(), pClosestCaloHit)))
461 matchedHits.push_back(pClosestCaloHit);
464 if (matchedHits.empty())
465 return STATUS_CODE_NOT_FOUND;
467 return STATUS_CODE_SUCCESS;
473 ClusterList &matchedClusters,
const Cluster *&pBestMatchedCluster)
const 479 const CaloHit *
const pCaloHit = *iter;
482 if (hitToClusterMap.end() == cIter)
483 throw StatusCodeException(STATUS_CODE_FAILURE);
485 ++clusterToMatchedHitsMap[cIter->second];
487 if (matchedClusters.end() == std::find(matchedClusters.begin(), matchedClusters.end(), cIter->second))
488 matchedClusters.push_back(cIter->second);
491 if (matchedClusters.empty())
492 return STATUS_CODE_NOT_FOUND;
494 pBestMatchedCluster =
nullptr;
495 unsigned int bestClusterMatchedHits(0);
496 float tieBreakerBestEnergy(0.
f);
499 for (
const auto &mapEntry : clusterToMatchedHitsMap)
500 sortedClusters.push_back(mapEntry.first);
503 for (
const Cluster *
const pCluster : sortedClusters)
505 const unsigned int nMatchedHits(clusterToMatchedHitsMap.at(pCluster));
507 if ((nMatchedHits > bestClusterMatchedHits) || ((nMatchedHits == bestClusterMatchedHits) && (pCluster->GetHadronicEnergy() > tieBreakerBestEnergy)))
509 pBestMatchedCluster = pCluster;
510 bestClusterMatchedHits = nMatchedHits;
511 tieBreakerBestEnergy = pCluster->GetHadronicEnergy();
515 if (
nullptr == pBestMatchedCluster)
516 return STATUS_CODE_NOT_FOUND;
518 return STATUS_CODE_SUCCESS;
524 const CaloHitList &matchedHits,
const ClusterList &matchedClusters,
FragmentOverlapResult &fragmentOverlapResult)
const 527 unsigned int nMatchedSamplingPoints(0);
529 CaloHitVector sortedMatchedHits(matchedHits.begin(), matchedHits.end());
532 for (
const CartesianVector &projectedPosition : projectedPositions)
534 float closestDistanceSquared(std::numeric_limits<float>::max());
536 for (
const CaloHit *
const pCaloHit : matchedHits)
538 const float distanceSquared((pCaloHit->GetPositionVector() - projectedPosition).GetMagnitudeSquared());
540 if (distanceSquared < closestDistanceSquared)
541 closestDistanceSquared = distanceSquared;
546 ++nMatchedSamplingPoints;
547 chi2Sum += closestDistanceSquared;
551 fragmentOverlapResult =
FragmentOverlapResult(nMatchedSamplingPoints, projectedPositions.size(), chi2Sum, matchedHits, matchedClusters);
558 if (projectedPositions.empty() || matchedClusters.empty())
562 float minXproj(+std::numeric_limits<float>::max());
563 float maxXproj(-std::numeric_limits<float>::max());
564 float minZproj(+std::numeric_limits<float>::max());
565 float maxZproj(-std::numeric_limits<float>::max());
567 for (
const CartesianVector &projectedPosition : projectedPositions)
569 minXproj = std::min(minXproj, projectedPosition.GetX());
570 maxXproj = std::max(maxXproj, projectedPosition.GetX());
571 minZproj = std::min(minZproj, projectedPosition.GetZ());
572 maxZproj = std::max(maxZproj, projectedPosition.GetZ());
575 const float dXproj(maxXproj - minXproj);
576 const float dZproj(maxZproj - minZproj);
577 const float projectedLengthSquared(dXproj * dXproj + dZproj * dZproj);
580 float minXcluster(+std::numeric_limits<float>::max());
581 float maxXcluster(-std::numeric_limits<float>::max());
582 float minZcluster(+std::numeric_limits<float>::max());
583 float maxZcluster(-std::numeric_limits<float>::max());
585 for (
const Cluster *
const pCluster : matchedClusters)
587 CartesianVector minPosition(0.
f, 0.
f, 0.
f);
588 CartesianVector maxPosition(0.
f, 0.
f, 0.
f);
592 minXcluster = std::min(minXcluster, minPosition.GetX());
593 maxXcluster = std::max(maxXcluster, maxPosition.GetX());
594 minZcluster = std::min(minZcluster, minPosition.GetZ());
595 maxZcluster = std::max(maxZcluster, maxPosition.GetZ());
598 const float dXcluster(maxXcluster - minXcluster);
599 const float dZcluster(maxZcluster - minZcluster);
600 const float clusterLengthSquared(dXcluster * dXcluster + dZcluster * dZcluster);
603 if (clusterLengthSquared > 4.
f * projectedLengthSquared)
627 unsigned int repeatCounter(0);
631 if ((*iter)->Run(
this, this->GetMatchingControl().GetOverlapTensor()))
649 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithm(*
this, xmlHandle,
"ClusterRebuilding",
m_reclusteringAlgorithmName));
651 AlgorithmToolVector algorithmToolVector;
652 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*
this, xmlHandle,
"TrackTools", algorithmToolVector));
656 FragmentTensorTool *
const pFragmentTensorTool(dynamic_cast<FragmentTensorTool *>(*iter));
658 if (!pFragmentTensorTool)
659 return STATUS_CODE_INVALID_PARAMETER;
664 PANDORA_RETURN_RESULT_IF_AND_IF(
665 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"NMaxTensorToolRepeats",
m_nMaxTensorToolRepeats));
667 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinXOverlap",
m_minXOverlap));
669 PANDORA_RETURN_RESULT_IF_AND_IF(
670 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinXOverlapFraction",
m_minXOverlapFraction));
673 PANDORA_RETURN_RESULT_IF_AND_IF(
674 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxPointDisplacement", maxPointDisplacement));
677 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
680 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinMatchedHits",
m_minMatchedHits));
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
pandora::ClusterList m_clusterListW
The selected modified cluster list W.
pandora::ClusterList m_clusterListU
The selected modified cluster list U.
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.
FragmentOverlapResult class.
void AddToSlidingFitCache(const pandora::Cluster *const pCluster)
Add a new sliding fit result, for the specified cluster, to the algorithm cache.
void RebuildClusters(const pandora::ClusterList &rebuildList, pandora::ClusterList &newClusters) const
Rebuild clusters after fragmentation.
void GetFragmentOverlapResult(const pandora::CartesianPointVector &projectedPositions, const pandora::CaloHitList &matchedHits, const pandora::ClusterList &matchedClusters, FragmentOverlapResult &fragmentOverlapResult) const
Get the populated fragment overlap result.
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.
pandora::ClusterList m_clusterListV
The selected modified cluster list V.
void PerformMainLoop()
Main loop over cluster combinations in order to populate the overlap container. Responsible for calli...
bool IsInitialized() const
Whether the track overlap result has been initialized.
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.
const TwoDSlidingFitResult & GetCachedSlidingFitResult(const pandora::Cluster *const pCluster) const
Get a sliding fit result from the algorithm cache.
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...
std::unordered_map< const pandora::Cluster *, unsigned int > ClusterToMatchedHitsMap
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
unsigned int m_minMatchedHits
minimum number of matched calo hits
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 ExamineOverlapContainer()
Examine contents of overlap container, collect together best-matching 2D particles and modify cluster...
MatchingType & GetMatchingControl()
Get the matching control.
Header file for the geometry helper class.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
void UpdateForNewCluster(const pandora::Cluster *const pNewCluster)
Update to reflect addition of a new cluster to the problem space.
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.
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.
bool CheckOverlapResult(const FragmentOverlapResult &overlapResult) const
Whether the matched clusters and hits pass the algorithm quality cuts.
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.
std::string m_reclusteringAlgorithmName
Name of daughter algorithm to use for cluster re-building.
float GetMatchedFraction() const
Get the fraction of sampling points resulting in a match.
const pandora::ClusterList & GetInputClusterList(const pandora::HitType hitType) const
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.
static float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
Header file for the three view fragments algorithm base class.
void CalculateOverlapResult(const pandora::Cluster *const pClusterU, const pandora::Cluster *const pClusterV, const pandora::Cluster *const pClusterW)
Calculate cluster overlap result and store in container.
bool CheckMatchedClusters(const pandora::CartesianPointVector &projectedPositions, const pandora::ClusterList &matchedClusters) const
Whether the matched clusters are consistent with the projected positions.
const pandora::ClusterList & GetSelectedClusterList(const pandora::HitType hitType) const
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.
pandora::StatusCode GetGlobalFitProjection(const pandora::CartesianVector &inputPosition, pandora::CartesianVector &projectedPosition) const
Get projected position on global fit for a given position vector.
TensorToolVector m_algorithmToolVector
The algorithm tool list.
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.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
FragmentTensorTool class.
void GetLocalPosition(const pandora::CartesianVector &position, float &rL, float &rT) const
Get local sliding fit coordinates for a given global position.
std::unordered_map< const pandora::CaloHit *, const pandora::Cluster * > HitToClusterMap
pandora::CartesianVector GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
unsigned int m_nMaxTensorToolRepeats
The maximum number of repeat loops over tensor tools.
float m_minXOverlapFraction
requirement on minimum X overlap fraction for associated clusters
TwoDSlidingFitResult class.
float m_maxPointDisplacementSquared
maximum allowed distance (squared) between projected points and associated hits
float m_minXOverlap
requirement on minimum X overlap for associated clusters
float m_minMatchedSamplingPointFraction
minimum fraction of matched sampling points
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...