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 57 if (clusterList.end() != std::find(clusterList.begin(), clusterList.end(), pNewCluster))
58 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
60 clusterList.push_back(pNewCluster);
67 for (
const Cluster *
const pCluster1 : clusterList1)
69 if (TPC_VIEW_U == hitType)
73 else if (TPC_VIEW_V == hitType)
83 for (
const Cluster *
const pCluster2 : clusterList2)
85 if (TPC_VIEW_U == hitType)
89 else if (TPC_VIEW_V == hitType)
104 const ClusterList *pNewClusterList =
nullptr;
105 std::string oldClusterListName, newClusterListName;
107 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::InitializeReclustering(*
this,
TrackList(), rebuildList, oldClusterListName));
108 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
111 newClusters.insert(newClusters.end(), pNewClusterList->begin(), pNewClusterList->end());
112 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndReclustering(*
this, newClusterListName));
126 for (
const Cluster *
const pClusterU : clusterListU)
128 for (
const Cluster *
const pClusterV : clusterListV)
132 for (
const Cluster *
const pClusterU : clusterListU)
134 for (
const Cluster *
const pClusterW : clusterListW)
138 for (
const Cluster *
const pClusterV : clusterListV)
140 for (
const Cluster *
const pClusterW : clusterListW)
149 const HitType missingHitType(((
nullptr != pClusterU) && (
nullptr != pClusterV) && (
nullptr == pClusterW))
151 : ((
nullptr != pClusterU) && (
nullptr == pClusterV) && (
nullptr != pClusterW))
153 : ((
nullptr == pClusterU) && (
nullptr != pClusterV) && (
nullptr != pClusterW)) ? TPC_VIEW_U : HIT_CUSTOM);
155 if (HIT_CUSTOM == missingHitType)
156 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
160 const Cluster *pMatchedClusterU(
nullptr), *pMatchedClusterV(
nullptr), *pMatchedClusterW(
nullptr);
166 (TPC_VIEW_U == missingHitType)
172 const Cluster *pBestMatchedCluster(
nullptr);
173 const StatusCode statusCode(this->
CalculateOverlapResult(fitResult1, fitResult2, inputClusterList, pBestMatchedCluster, newOverlapResult));
175 if ((STATUS_CODE_SUCCESS != statusCode) && (STATUS_CODE_NOT_FOUND != statusCode))
176 throw StatusCodeException(statusCode);
183 if (STATUS_CODE_SUCCESS == statusCode)
185 pMatchedClusterU = ((
nullptr != pClusterU) ? pClusterU : pBestMatchedCluster);
186 pMatchedClusterV = ((
nullptr != pClusterV) ? pClusterV : pBestMatchedCluster);
187 pMatchedClusterW = ((
nullptr != pClusterW) ? pClusterW : pBestMatchedCluster);
189 if (
nullptr == pMatchedClusterU ||
nullptr == pMatchedClusterV ||
nullptr == pMatchedClusterW)
190 throw StatusCodeException(STATUS_CODE_FAILURE);
194 oldOverlapResult = overlapTensor.
GetOverlapResult(pMatchedClusterU, pMatchedClusterV, pMatchedClusterW);
196 catch (StatusCodeException &)
203 overlapTensor.
SetOverlapResult(pMatchedClusterU, pMatchedClusterV, pMatchedClusterW, newOverlapResult);
207 overlapTensor.
ReplaceOverlapResult(pMatchedClusterU, pMatchedClusterV, pMatchedClusterW, newOverlapResult);
211 float newEnergySum(0.
f), oldEnergySum(0.
f);
213 newEnergySum += pCaloHit->GetHadronicEnergy();
215 oldEnergySum += pCaloHit->GetHadronicEnergy();
217 if (newEnergySum > oldEnergySum)
218 overlapTensor.
ReplaceOverlapResult(pMatchedClusterU, pMatchedClusterV, pMatchedClusterW, newOverlapResult);
225 const ClusterList &inputClusterList,
const Cluster *&pBestMatchedCluster,
FragmentOverlapResult &fragmentOverlapResult)
const 227 const Cluster *
const pCluster1(fitResult1.
GetCluster());
228 const Cluster *
const pCluster2(fitResult2.
GetCluster());
230 float xMin1(0.
f), xMax1(0.
f), xMin2(0.
f), xMax2(0.
f);
231 pCluster1->GetClusterSpanX(xMin1, xMax1);
232 pCluster2->GetClusterSpanX(xMin2, xMax2);
236 if (xOverlap < std::numeric_limits<float>::epsilon())
237 return STATUS_CODE_NOT_FOUND;
239 CartesianPointVector projectedPositions;
240 const StatusCode statusCode1(this->
GetProjectedPositions(fitResult1, fitResult2, projectedPositions));
242 if (STATUS_CODE_SUCCESS != statusCode1)
245 CaloHitList matchedHits;
246 ClusterList matchedClusters;
248 const StatusCode statusCode2(this->
GetMatchedHits(inputClusterList, projectedPositions, hitToClusterMap, matchedHits));
250 if (STATUS_CODE_SUCCESS != statusCode2)
253 const StatusCode statusCode3(this->
GetMatchedClusters(matchedHits, hitToClusterMap, matchedClusters, pBestMatchedCluster));
255 if (STATUS_CODE_SUCCESS != statusCode3)
259 return STATUS_CODE_NOT_FOUND;
265 return STATUS_CODE_NOT_FOUND;
267 fragmentOverlapResult = overlapResult;
268 return STATUS_CODE_SUCCESS;
276 const Cluster *
const pCluster1(fitResult1.
GetCluster());
277 const Cluster *
const pCluster2(fitResult2.
GetCluster());
282 const HitType hitType3((TPC_VIEW_U != hitType1 && TPC_VIEW_U != hitType2)
284 : (TPC_VIEW_V != hitType1 && TPC_VIEW_V != hitType2)
286 : (TPC_VIEW_W != hitType1 && TPC_VIEW_W != hitType2) ? TPC_VIEW_W : HIT_CUSTOM);
288 if (HIT_CUSTOM == hitType3)
289 return STATUS_CODE_INVALID_PARAMETER;
292 float xMin1(0.
f), xMax1(0.
f), xMin2(0.
f), xMax2(0.
f);
293 pCluster1->GetClusterSpanX(xMin1, xMax1);
294 pCluster2->GetClusterSpanX(xMin2, xMax2);
300 return STATUS_CODE_NOT_FOUND;
308 const float dx_A(std::fabs(minPosition2.GetX() - minPosition1.GetX()));
309 const float dx_B(std::fabs(maxPosition2.GetX() - maxPosition1.GetX()));
310 const float dx_C(std::fabs(maxPosition2.GetX() - minPosition1.GetX()));
311 const float dx_D(std::fabs(minPosition2.GetX() - maxPosition1.GetX()));
314 return STATUS_CODE_NOT_FOUND;
316 const CartesianVector &vtxPosition1(minPosition1);
317 const CartesianVector &endPosition1(maxPosition1);
318 const CartesianVector &vtxPosition2((dx_A < dx_C) ? minPosition2 : maxPosition2);
319 const CartesianVector &endPosition2((dx_A < dx_C) ? maxPosition2 : minPosition2);
323 CartesianVector vtxPosition3D(0.
f, 0.
f, 0.
f);
327 CartesianVector endPosition3D(0.
f, 0.
f, 0.
f);
334 const float nSamplingPoints((endProjection3 - vtxProjection3).GetMagnitude() / samplingPitch);
336 if (nSamplingPoints < 1.
f)
337 return STATUS_CODE_NOT_FOUND;
340 bool foundLastPosition(
false);
341 CartesianVector lastPosition(0.
f, 0.
f, 0.
f);
343 for (
float iSample = 0.5
f; iSample < nSamplingPoints; iSample += 1.f)
345 const CartesianVector linearPosition3D(vtxPosition3D + (endPosition3D - vtxPosition3D) * (iSample / nSamplingPoints));
350 CartesianVector fitPosition1(0.
f, 0.
f, 0.
f), fitPosition2(0.
f, 0.
f, 0.
f);
358 float rL1(0.
f), rL2(0.
f), rT1(0.
f), rT2(0.
f);
362 const float x(0.5 * (fitPosition1.GetX() + fitPosition2.GetX()));
363 CartesianVector position1(0.
f, 0.
f, 0.
f), position2(0.
f, 0.
f, 0.
f), position3(0.
f, 0.
f, 0.
f);
376 catch (StatusCodeException &statusCodeException)
378 if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
379 throw statusCodeException;
387 if (foundLastPosition)
389 const float thisDisplacement((lastPosition - position3).GetMagnitude());
390 if (thisDisplacement > 2.
f * samplingPitch)
392 const float nExtraPoints(thisDisplacement / samplingPitch);
393 for (
float iExtra = 0.5
f; iExtra < nExtraPoints; iExtra += 1.f)
395 const CartesianVector extraPosition(position3 + (lastPosition - position3) * (iExtra / nExtraPoints));
396 projectedPositions.push_back(extraPosition);
401 projectedPositions.push_back(position3);
403 lastPosition = position3;
404 foundLastPosition =
true;
408 if (projectedPositions.empty())
409 return STATUS_CODE_NOT_FOUND;
411 return STATUS_CODE_SUCCESS;
417 const CartesianPointVector &projectedPositions,
HitToClusterMap &hitToClusterMap, CaloHitList &matchedHits)
const 419 CaloHitVector availableCaloHits;
423 const Cluster *
const pCluster = *iter;
425 if (!pCluster->IsAvailable())
428 CaloHitList caloHitList;
429 pCluster->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
430 availableCaloHits.insert(availableCaloHits.end(), caloHitList.begin(), caloHitList.end());
433 hitToClusterMap.insert(HitToClusterMap::value_type(*hIter, pCluster));
438 for (
const CartesianVector &projectedPosition : projectedPositions)
440 const CaloHit *pClosestCaloHit(
nullptr);
443 for (
const CaloHit *
const pCaloHit : availableCaloHits)
445 const float distanceSquared((pCaloHit->GetPositionVector() - projectedPosition).GetMagnitudeSquared());
447 if ((distanceSquared < closestDistanceSquared) ||
448 ((std::fabs(distanceSquared - closestDistanceSquared) < std::numeric_limits<float>::epsilon()) &&
449 (pCaloHit->GetHadronicEnergy() > tieBreakerBestEnergy)))
451 pClosestCaloHit = pCaloHit;
452 closestDistanceSquared = distanceSquared;
453 tieBreakerBestEnergy = pCaloHit->GetHadronicEnergy();
458 (matchedHits.end() == std::find(matchedHits.begin(), matchedHits.end(), pClosestCaloHit)))
459 matchedHits.push_back(pClosestCaloHit);
462 if (matchedHits.empty())
463 return STATUS_CODE_NOT_FOUND;
465 return STATUS_CODE_SUCCESS;
471 ClusterList &matchedClusters,
const Cluster *&pBestMatchedCluster)
const 477 const CaloHit *
const pCaloHit = *iter;
480 if (hitToClusterMap.end() == cIter)
481 throw StatusCodeException(STATUS_CODE_FAILURE);
483 ++clusterToMatchedHitsMap[cIter->second];
485 if (matchedClusters.end() == std::find(matchedClusters.begin(), matchedClusters.end(), cIter->second))
486 matchedClusters.push_back(cIter->second);
489 if (matchedClusters.empty())
490 return STATUS_CODE_NOT_FOUND;
492 pBestMatchedCluster =
nullptr;
493 unsigned int bestClusterMatchedHits(0);
494 float tieBreakerBestEnergy(0.
f);
497 for (
const auto &mapEntry : clusterToMatchedHitsMap)
498 sortedClusters.push_back(mapEntry.first);
501 for (
const Cluster *
const pCluster : sortedClusters)
503 const unsigned int nMatchedHits(clusterToMatchedHitsMap.at(pCluster));
505 if ((nMatchedHits > bestClusterMatchedHits) || ((nMatchedHits == bestClusterMatchedHits) && (pCluster->GetHadronicEnergy() > tieBreakerBestEnergy)))
507 pBestMatchedCluster = pCluster;
508 bestClusterMatchedHits = nMatchedHits;
509 tieBreakerBestEnergy = pCluster->GetHadronicEnergy();
513 if (
nullptr == pBestMatchedCluster)
514 return STATUS_CODE_NOT_FOUND;
516 return STATUS_CODE_SUCCESS;
522 const CaloHitList &matchedHits,
const ClusterList &matchedClusters,
FragmentOverlapResult &fragmentOverlapResult)
const 525 unsigned int nMatchedSamplingPoints(0);
527 CaloHitVector sortedMatchedHits(matchedHits.begin(), matchedHits.end());
530 for (
const CartesianVector &projectedPosition : projectedPositions)
534 for (
const CaloHit *
const pCaloHit : matchedHits)
536 const float distanceSquared((pCaloHit->GetPositionVector() - projectedPosition).GetMagnitudeSquared());
538 if (distanceSquared < closestDistanceSquared)
539 closestDistanceSquared = distanceSquared;
544 ++nMatchedSamplingPoints;
545 chi2Sum += closestDistanceSquared;
549 fragmentOverlapResult =
FragmentOverlapResult(nMatchedSamplingPoints, projectedPositions.size(), chi2Sum, matchedHits, matchedClusters);
556 if (projectedPositions.empty() || matchedClusters.empty())
565 for (
const CartesianVector &projectedPosition : projectedPositions)
567 minXproj =
std::min(minXproj, projectedPosition.GetX());
568 maxXproj =
std::max(maxXproj, projectedPosition.GetX());
569 minZproj =
std::min(minZproj, projectedPosition.GetZ());
570 maxZproj =
std::max(maxZproj, projectedPosition.GetZ());
573 const float dXproj(maxXproj - minXproj);
574 const float dZproj(maxZproj - minZproj);
575 const float projectedLengthSquared(dXproj * dXproj + dZproj * dZproj);
583 for (
const Cluster *
const pCluster : matchedClusters)
585 CartesianVector minPosition(0.
f, 0.
f, 0.
f);
586 CartesianVector maxPosition(0.
f, 0.
f, 0.
f);
590 minXcluster =
std::min(minXcluster, minPosition.GetX());
591 maxXcluster =
std::max(maxXcluster, maxPosition.GetX());
592 minZcluster =
std::min(minZcluster, minPosition.GetZ());
593 maxZcluster =
std::max(maxZcluster, maxPosition.GetZ());
596 const float dXcluster(maxXcluster - minXcluster);
597 const float dZcluster(maxZcluster - minZcluster);
598 const float clusterLengthSquared(dXcluster * dXcluster + dZcluster * dZcluster);
601 if (clusterLengthSquared > 4.
f * projectedLengthSquared)
625 unsigned int repeatCounter(0);
629 if ((*iter)->Run(
this, this->GetMatchingControl().GetOverlapTensor()))
647 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithm(*
this, xmlHandle,
"ClusterRebuilding",
m_reclusteringAlgorithmName));
649 AlgorithmToolVector algorithmToolVector;
650 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*
this, xmlHandle,
"TrackTools", algorithmToolVector));
654 FragmentTensorTool *
const pFragmentTensorTool(dynamic_cast<FragmentTensorTool *>(*iter));
656 if (!pFragmentTensorTool)
657 return STATUS_CODE_INVALID_PARAMETER;
662 PANDORA_RETURN_RESULT_IF_AND_IF(
663 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"NMaxTensorToolRepeats",
m_nMaxTensorToolRepeats));
665 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinXOverlap",
m_minXOverlap));
667 PANDORA_RETURN_RESULT_IF_AND_IF(
668 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinXOverlapFraction",
m_minXOverlapFraction));
671 PANDORA_RETURN_RESULT_IF_AND_IF(
672 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxPointDisplacement", maxPointDisplacement));
675 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
678 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.
std::set< const gar::rec::Track * > TrackList
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.
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
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 int max(int a, int b)
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.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
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...