8 #include "Pandora/AlgorithmHeaders.h"
21 TrackRefinementBaseAlgorithm::TrackRefinementBaseAlgorithm() :
22 m_minClusterLength(15.f),
23 m_microSlidingFitWindow(20),
24 m_macroSlidingFitWindow(1000),
25 m_stableRegionClusterFraction(0.05f),
26 m_mergePointMinCosAngleDeviation(0.999f),
27 m_minHitFractionForHitRemoval(0.05f),
28 m_maxDistanceFromMainTrack(0.75f),
29 m_maxHitDistanceFromCluster(4.f),
30 m_maxHitSeparationForConnectedCluster(4.f),
32 m_lineSegmentLength(3.f),
45 for (
const Cluster *
const pCluster : *pClusterList)
55 slidingFitResultMapPair.first->insert(TwoDSlidingFitResultMap::value_type(pCluster, microSlidingFitResult));
56 slidingFitResultMapPair.second->insert(TwoDSlidingFitResultMap::value_type(pCluster, macroSlidingFitResult));
57 clusterVector.push_back(pCluster);
59 catch (
const StatusCodeException &)
64 std::sort(clusterVector.begin(), clusterVector.end(), sortFunction);
71 CartesianVector &clusterMergePosition, CartesianVector &clusterMergeDirection)
const
73 CartesianVector clusterAverageDirection(0.f, 0.f, 0.f), associatedAverageDirection(0.f, 0.f, 0.f);
78 const int startLayer(isEndUpstream ? clusterMicroFitResult.
GetMinLayer() : clusterMicroFitResult.
GetMaxLayer());
79 const int endLayer(isEndUpstream ? clusterMicroFitResult.
GetMaxLayer() : clusterMicroFitResult.
GetMinLayer());
80 const int loopTerminationLayer(endLayer + (isEndUpstream ? 1 : -1));
81 const int step(isEndUpstream ? 1 : -1);
85 unsigned int goodLayerCount(0);
87 clusterMicroLayerFitResultMap.at(endLayer);
89 for (
int i = startLayer; i != loopTerminationLayer; i += step)
91 const auto microIter(clusterMicroLayerFitResultMap.find(i));
93 if (microIter == clusterMicroLayerFitResultMap.end())
96 CartesianVector microDirection(0.f, 0.f, 0.f);
97 clusterMicroFitResult.
GetGlobalDirection(microIter->second.GetGradient(), microDirection);
99 const float cosDirectionOpeningAngle(microDirection.GetCosOpeningAngle(associatedAverageDirection));
103 if (goodLayerCount == 0)
105 clusterMergeDirection = clusterAverageDirection;
106 PANDORA_THROW_RESULT_IF(
107 STATUS_CODE_SUCCESS, !=, clusterMicroFitResult.
GetGlobalFitPosition(microIter->second.GetL(), clusterMergePosition));
117 if (goodLayerCount > gradientStabilityWindow)
132 const ClusterList &unavailableProtectedClusters,
const float distanceToLine)
const
134 const float minX(std::min(firstCorner.GetX(), secondCorner.GetX())), maxX(std::max(firstCorner.GetX(), secondCorner.GetX()));
135 const float minZ(std::min(firstCorner.GetZ(), secondCorner.GetZ())), maxZ(std::max(firstCorner.GetZ(), secondCorner.GetZ()));
137 CartesianVector connectingLineDirection(firstCorner - secondCorner);
138 connectingLineDirection = connectingLineDirection.GetUnitVector();
140 for (
const Cluster *
const pCluster : *pClusterList)
142 if (std::find(unavailableProtectedClusters.begin(), unavailableProtectedClusters.end(), pCluster) != unavailableProtectedClusters.end())
145 const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
146 for (
const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
148 for (
const CaloHit *
const pCaloHit : *mapEntry.second)
151 : pCaloHit->GetPositionVector());
156 if (distanceToLine > 0.f)
158 if (!this->
IsCloseToLine(hitPosition, firstCorner, connectingLineDirection, distanceToLine))
162 clusterToCaloHitListMap[pCluster].push_back(pCaloHit);
171 const float minX,
const float maxX,
const float minZ,
const float maxZ,
const CartesianVector &hitPosition)
const
173 return !((hitPosition.GetX() < minX) || (hitPosition.GetX() > maxX) || (hitPosition.GetZ() < minZ) || (hitPosition.GetZ() > maxZ));
179 const CartesianVector &lineDirection,
const float distanceToLine)
const
181 const float transverseDistanceFromLine(lineDirection.GetCrossProduct(hitPosition - lineStart).GetMagnitude());
183 return (transverseDistanceFromLine < distanceToLine);
190 CaloHitVector extrapolatedHitVector;
191 for (
const auto &entry : clusterToCaloHitListMap)
192 extrapolatedHitVector.insert(extrapolatedHitVector.begin(), entry.second.begin(), entry.second.end());
195 std::sort(extrapolatedHitVector.begin(), extrapolatedHitVector.end(),
201 if (clusterToCaloHitListMap.empty())
216 return (distanceToBoundary < boundaryTolerance);
223 CartesianPointVector trackSegmentBoundaries;
226 if (trackSegmentBoundaries.size() < 2)
228 std::cout <<
"TrackInEMShowerAlgorithm: Less than two track segment boundaries" << std::endl;
229 throw STATUS_CODE_NOT_ALLOWED;
232 unsigned int segmentsWithoutHits(0);
233 CaloHitVector::const_iterator caloHitIter(extrapolatedCaloHitVector.begin());
236 : (*caloHitIter)->GetPositionVector());
238 for (
unsigned int i = 0; i < (trackSegmentBoundaries.size() - 1); ++i)
240 if (caloHitIter == extrapolatedCaloHitVector.end())
242 ++segmentsWithoutHits;
250 unsigned int hitsInSegment(0);
251 while (this->
IsInLineSegment(trackSegmentBoundaries.at(i), trackSegmentBoundaries.at(i + 1), hitPosition))
256 if (caloHitIter == extrapolatedCaloHitVector.end())
261 : (*caloHitIter)->GetPositionVector();
264 segmentsWithoutHits = hitsInSegment ? 0 : segmentsWithoutHits + 1;
279 std::cout <<
"TrackInEMShowerAlgorithm: Line segment length must be positive and nonzero" << std::endl;
280 throw STATUS_CODE_INVALID_PARAMETER;
287 DetectorGapList consideredGaps;
290 consideredGaps.clear();
294 if (fullSegments == 0)
302 const bool splitFinalSegment(lengthOfTrackRemainder > m_lineSegmentLength * 0.5f);
303 const int numberOfBoundaries(fullSegments + (splitFinalSegment ? 2 : 1));
305 CartesianVector segmentUpstreamBoundary(clusterAssociation.
GetUpstreamMergePoint()), segmentDownstreamBoundary(segmentUpstreamBoundary);
307 trackSegmentBoundaries.push_back(segmentUpstreamBoundary);
309 for (
int i = 1; i < numberOfBoundaries; ++i)
311 if (i < fullSegments)
317 if (splitFinalSegment)
319 segmentDownstreamBoundary += trackDirection * (m_lineSegmentLength + lengthOfTrackRemainder) * 0.5f;
323 segmentDownstreamBoundary += trackDirection * (m_lineSegmentLength + lengthOfTrackRemainder);
327 float distanceInGap(this->
DistanceInGap(segmentUpstreamBoundary, segmentDownstreamBoundary, trackDirection, consideredGaps));
328 while (distanceInGap > std::numeric_limits<float>::epsilon())
331 segmentDownstreamBoundary += trackDirection * distanceInGap;
332 distanceInGap = this->
DistanceInGap(segmentUpstreamBoundary, segmentDownstreamBoundary, trackDirection, consideredGaps);
335 trackSegmentBoundaries.push_back(segmentDownstreamBoundary);
343 const DetectorGapList detectorGapList(this->GetPandora().GetGeometry()->GetDetectorGapList());
344 for (
const DetectorGap *
const pDetectorGap : detectorGapList)
346 const LineGap *
const pLineGap(dynamic_cast<const LineGap *>(pDetectorGap));
350 const LineGapType lineGapType(pLineGap->GetLineGapType());
352 if (lineGapType == TPC_DRIFT_GAP)
354 if ((pLineGap->GetLineStartX() < trackPoint.GetX()) && (pLineGap->GetLineEndX() > trackPoint.GetX()))
356 if (std::fabs(mergeDirection.GetX()) < std::numeric_limits<float>::epsilon())
357 throw StatusCodeException(STATUS_CODE_FAILURE);
359 const float gradient(mergeDirection.GetZ() / mergeDirection.GetX());
361 trackPoint = CartesianVector(
362 pLineGap->GetLineEndX(), 0.f, trackPoint.GetZ() + (gradient * (pLineGap->GetLineEndX() - trackPoint.GetX())));
366 if ((lineGapType == TPC_WIRE_GAP_VIEW_U) || (lineGapType == TPC_WIRE_GAP_VIEW_V) || (lineGapType == TPC_WIRE_GAP_VIEW_W))
368 if ((pLineGap->GetLineStartZ() < trackPoint.GetZ()) && (pLineGap->GetLineEndZ() > trackPoint.GetZ()))
370 if (std::fabs(mergeDirection.GetZ()) < std::numeric_limits<float>::epsilon())
371 throw StatusCodeException(STATUS_CODE_FAILURE);
373 const float gradient(mergeDirection.GetX() / mergeDirection.GetZ());
375 trackPoint = CartesianVector(
376 trackPoint.GetX() + (gradient * (pLineGap->GetLineEndZ() - trackPoint.GetZ())), 0.f, pLineGap->GetLineEndZ());
386 const CartesianVector &connectingLine, DetectorGapList &consideredGaps)
const
388 const CartesianVector &lowerXPoint(upstreamPoint.GetX() < downstreamPoint.GetX() ? upstreamPoint : downstreamPoint);
389 const CartesianVector &higherXPoint(upstreamPoint.GetX() < downstreamPoint.GetX() ? downstreamPoint : upstreamPoint);
391 const float cosAngleToX(std::fabs(connectingLine.GetDotProduct(CartesianVector(1.f, 0.f, 0.f))));
392 const float cosAngleToZ(std::fabs(connectingLine.GetDotProduct(CartesianVector(0.f, 0.f, 1.f))));
394 float distanceInGaps(0.f);
395 const DetectorGapList detectorGapList(this->GetPandora().GetGeometry()->GetDetectorGapList());
396 for (
const DetectorGap *
const pDetectorGap : detectorGapList)
398 if (std::find(consideredGaps.begin(), consideredGaps.end(), pDetectorGap) != consideredGaps.end())
401 const LineGap *
const pLineGap(dynamic_cast<const LineGap *>(pDetectorGap));
405 const LineGapType lineGapType(pLineGap->GetLineGapType());
407 if (lineGapType == TPC_DRIFT_GAP)
409 float xDistanceInGap(0.f);
411 if ((pLineGap->GetLineStartX() > lowerXPoint.GetX()) && (pLineGap->GetLineEndX() < higherXPoint.GetX()))
413 xDistanceInGap = (pLineGap->GetLineEndX() - pLineGap->GetLineStartX());
415 else if ((pLineGap->GetLineStartX() < lowerXPoint.GetX()) && (pLineGap->GetLineEndX() > lowerXPoint.GetX()))
417 xDistanceInGap = (pLineGap->GetLineEndX() - lowerXPoint.GetX());
419 else if ((pLineGap->GetLineStartX() < higherXPoint.GetX()) && (pLineGap->GetLineEndX() > higherXPoint.GetX()))
421 xDistanceInGap = (higherXPoint.GetX() - pLineGap->GetLineStartX());
428 if (std::fabs(cosAngleToX) < std::numeric_limits<float>::epsilon())
429 throw StatusCodeException(STATUS_CODE_FAILURE);
431 distanceInGaps += (xDistanceInGap / cosAngleToX);
433 consideredGaps.push_back(pDetectorGap);
436 if ((lineGapType == TPC_WIRE_GAP_VIEW_U) || (lineGapType == TPC_WIRE_GAP_VIEW_V) || (lineGapType == TPC_WIRE_GAP_VIEW_W))
438 float zDistanceInGap(0.f);
440 if ((pLineGap->GetLineStartZ() > upstreamPoint.GetZ()) && (pLineGap->GetLineEndZ() < downstreamPoint.GetZ()))
442 zDistanceInGap = pLineGap->GetLineEndZ() - pLineGap->GetLineStartZ();
444 else if ((pLineGap->GetLineStartZ() < upstreamPoint.GetZ()) && (pLineGap->GetLineEndZ() > upstreamPoint.GetZ()))
446 zDistanceInGap = pLineGap->GetLineEndZ() - upstreamPoint.GetZ();
448 else if ((pLineGap->GetLineStartZ() < downstreamPoint.GetZ()) && (pLineGap->GetLineEndZ() > downstreamPoint.GetZ()))
450 zDistanceInGap = downstreamPoint.GetZ() - pLineGap->GetLineStartZ();
457 if (std::fabs(cosAngleToZ) < std::numeric_limits<float>::epsilon())
458 throw StatusCodeException(STATUS_CODE_FAILURE);
460 distanceInGaps += (zDistanceInGap / cosAngleToZ);
462 consideredGaps.push_back(pDetectorGap);
467 return distanceInGaps;
473 const CartesianVector &lowerBoundary,
const CartesianVector &upperBoundary,
const CartesianVector &point)
const
475 const float segmentBoundaryGradient = (-1.f) * (upperBoundary.GetX() - lowerBoundary.GetX()) / (upperBoundary.GetZ() - lowerBoundary.GetZ());
476 const float xPointOnUpperLine((point.GetZ() - upperBoundary.GetZ()) / segmentBoundaryGradient + upperBoundary.GetX());
477 const float xPointOnLowerLine((point.GetZ() - lowerBoundary.GetZ()) / segmentBoundaryGradient + lowerBoundary.GetX());
479 if (std::fabs(xPointOnUpperLine - point.GetX()) < std::numeric_limits<float>::epsilon())
482 if (std::fabs(xPointOnLowerLine - point.GetX()) < std::numeric_limits<float>::epsilon())
485 if ((point.GetX() > xPointOnUpperLine) && (point.GetX() > xPointOnLowerLine))
488 if ((point.GetX() < xPointOnUpperLine) && (point.GetX() < xPointOnLowerLine))
497 const bool isEndUpstream,
const ClusterToCaloHitListMap &clusterToCaloHitListMap, ClusterList &remnantClusterList,
500 float rL(0.f), rT(0.f);
505 CartesianVector averageDirection(0.f, 0.f, 0.f);
506 macroFitResult.GetGlobalDirection(macroFitResult.GetLayerFitResultMap().begin()->second.GetGradient(), averageDirection);
508 const bool isVertical(std::fabs(averageDirection.GetX()) < std::numeric_limits<float>::epsilon());
509 const float clusterGradient(isVertical ? 0.f : averageDirection.GetZ() / averageDirection.GetX());
510 const float clusterIntercept(isVertical ? splitPosition.GetX() : splitPosition.GetZ() - (clusterGradient * splitPosition.GetX()));
513 std::string originalListName, fragmentListName;
514 const ClusterList originalClusterList(1, pCluster);
515 PANDORA_THROW_RESULT_IF(
516 STATUS_CODE_SUCCESS, !=, PandoraContentApi::InitializeFragmentation(*
this, originalClusterList, originalListName, fragmentListName));
518 const Cluster *pMainTrackCluster(
nullptr), *pAboveCluster(
nullptr), *pBelowCluster(
nullptr);
520 const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
521 for (
const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
523 for (
const CaloHit *
const pCaloHit : *mapEntry.second)
525 const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
526 float thisL(0.f), thisT(0.f);
528 microFitResult.GetLocalPosition(pCaloHit->GetPositionVector(), thisL, thisT);
530 bool isAnExtrapolatedHit(
false);
531 const auto extrapolatedCaloHitIter(clusterToCaloHitListMap.find(pCluster));
533 if (extrapolatedCaloHitIter != clusterToCaloHitListMap.end())
534 isAnExtrapolatedHit = std::find(extrapolatedCaloHitIter->second.begin(), extrapolatedCaloHitIter->second.end(), pCaloHit) !=
535 extrapolatedCaloHitIter->second.end();
537 const bool isAbove(((clusterGradient * hitPosition.GetX()) + clusterIntercept) < (isVertical ? hitPosition.GetX() : hitPosition.GetZ()));
538 const bool isToRemove(!isAnExtrapolatedHit && (((thisL < rL) && isEndUpstream) || ((thisL > rL) && !isEndUpstream)));
540 const Cluster *&pClusterToModify(isToRemove ? (isAbove ? pAboveCluster : pBelowCluster) : pMainTrackCluster);
542 if (pClusterToModify)
544 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*
this, pClusterToModify, pCaloHit));
549 parameters.m_caloHitList.push_back(pCaloHit);
550 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*
this, parameters, pClusterToModify));
552 if (pClusterToModify != pMainTrackCluster)
553 remnantClusterList.push_back(pClusterToModify);
559 if (pAboveCluster || pBelowCluster)
561 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*
this, fragmentListName, originalListName));
562 return pMainTrackCluster;
566 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*
this, originalListName, fragmentListName));
574 const CaloHitList &caloHitsToMerge,
const ClusterAssociation &clusterAssociation, ClusterList &remnantClusterList)
const
581 if (pShowerCluster->GetNCaloHits() == caloHitsToMerge.size())
583 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*
this, pMainTrackCluster, pShowerCluster));
588 std::string originalListName, fragmentListName;
589 const ClusterList originalClusterList(1, pShowerCluster);
590 PANDORA_THROW_RESULT_IF(
591 STATUS_CODE_SUCCESS, !=, PandoraContentApi::InitializeFragmentation(*
this, originalClusterList, originalListName, fragmentListName));
593 const Cluster *pAboveCluster(
nullptr), *pBelowCluster(
nullptr);
595 const bool isVertical(std::fabs(clusterAssociation.
GetConnectingLineDirection().GetX()) < std::numeric_limits<float>::epsilon());
596 const float connectingLineGradient(
602 const OrderedCaloHitList orderedCaloHitList(pShowerCluster->GetOrderedCaloHitList());
603 for (
const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
605 for (
const CaloHit *
const pCaloHit : *mapEntry.second)
607 const bool isAnExtrapolatedHit(std::find(caloHitsToMerge.begin(), caloHitsToMerge.end(), pCaloHit) != caloHitsToMerge.end());
608 if (isAnExtrapolatedHit)
610 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromCluster(*
this, pShowerCluster, pCaloHit));
611 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*
this, pMainTrackCluster, pCaloHit));
615 const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
616 const bool isAbove(((connectingLineGradient * hitPosition.GetX()) + connectingLineIntercept) <
617 (isVertical ? hitPosition.GetX() : hitPosition.GetZ()));
618 const Cluster *&pClusterToModify(isAbove ? pAboveCluster : pBelowCluster);
620 if (pClusterToModify)
622 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*
this, pClusterToModify, pCaloHit));
627 parameters.m_caloHitList.push_back(pCaloHit);
628 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*
this, parameters, pClusterToModify));
630 remnantClusterList.push_back(pClusterToModify);
636 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*
this, fragmentListName, originalListName));
642 const ClusterList *
const pClusterList, ClusterList &createdClusters)
const
644 ClusterList fragmentedClusters;
645 for (
const Cluster *
const pRemnantCluster : remnantClusterList)
653 fragmentedClusters.push_back(pRemnantCluster);
657 for (
const Cluster *
const pFragmentedCluster : fragmentedClusters)
659 if ((pFragmentedCluster->GetNCaloHits() == 1) && (this->
AddToNearestCluster(pFragmentedCluster, pMainTrackCluster, pClusterList)))
662 createdClusters.push_back(pFragmentedCluster);
669 const Cluster *
const pClusterToMerge,
const Cluster *
const pMainTrackCluster,
const ClusterList *
const pClusterList)
const
671 const Cluster *pClosestCluster(
nullptr);
674 for (
const Cluster *
const pCluster : *pClusterList)
676 if (pCluster == pClusterToMerge)
681 if (separationDistance < closestDistance)
686 pClosestCluster = pCluster;
687 closestDistance = separationDistance;
693 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*
this, pClosestCluster, pClusterToMerge));
704 if (pRemnantCluster->GetNCaloHits() == 1)
707 const OrderedCaloHitList &orderedCaloHitList(pRemnantCluster->GetOrderedCaloHitList());
708 const CaloHit *pPreviousCaloHit(orderedCaloHitList.begin()->second->front());
710 for (
const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
712 for (
const CaloHit *
const pCaloHit : *mapEntry.second)
714 if (pCaloHit == pPreviousCaloHit)
717 const float separationDistanceSquared(pCaloHit->GetPositionVector().GetDistanceSquared(pPreviousCaloHit->GetPositionVector()));
722 pPreviousCaloHit = pCaloHit;
734 std::string originalListName, fragmentListName;
735 const ClusterList originalClusterList(1, pRemnantCluster);
736 PANDORA_THROW_RESULT_IF(
737 STATUS_CODE_SUCCESS, !=, PandoraContentApi::InitializeFragmentation(*
this, originalClusterList, originalListName, fragmentListName));
739 ClusterList createdClusters;
741 const OrderedCaloHitList &orderedCaloHitList(pRemnantCluster->GetOrderedCaloHitList());
742 for (
const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
744 for (
const CaloHit *
const pCaloHit : *mapEntry.second)
746 const Cluster *pClosestCluster(
nullptr);
748 if (!createdClusters.empty())
752 for (
const Cluster *
const pCreatedCluster : createdClusters)
757 closestDistance = separationDistance;
758 pClosestCluster = pCreatedCluster;
765 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*
this, pClosestCluster, pCaloHit));
770 parameters.m_caloHitList.push_back(pCaloHit);
771 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*
this, parameters, pClosestCluster));
772 createdClusters.push_back(pClosestCluster);
778 if (createdClusters.empty())
780 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*
this, originalListName, fragmentListName));
781 fragmentedClusterList.push_back(pRemnantCluster);
785 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*
this, fragmentListName, originalListName));
786 fragmentedClusterList.insert(fragmentedClusterList.begin(), createdClusters.begin(), createdClusters.end());
792 template <
typename T>
797 for (
const Cluster *
const pClusterToDelete : clustersToDelete)
800 this->
InitialiseContainers(&clustersToAdd, sortFunction, clusterVector, slidingFitResultMapPair);
808 const TwoDSlidingFitResultMap::const_iterator microFitToDelete(slidingFitResultMapPair.first->find(pClusterToRemove));
809 if (microFitToDelete != slidingFitResultMapPair.first->end())
810 slidingFitResultMapPair.first->erase(microFitToDelete);
812 const TwoDSlidingFitResultMap::const_iterator macroFitToDelete(slidingFitResultMapPair.second->find(pClusterToRemove));
813 if (macroFitToDelete != slidingFitResultMapPair.second->end())
814 slidingFitResultMapPair.second->erase(macroFitToDelete);
816 const ClusterVector::const_iterator clusterToDelete(std::find(clusterVector.begin(), clusterVector.end(), pClusterToRemove));
817 if (clusterToDelete != clusterVector.end())
818 clusterVector.erase(clusterToDelete);
825 PANDORA_RETURN_RESULT_IF_AND_IF(
826 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinClusterLength",
m_minClusterLength));
828 PANDORA_RETURN_RESULT_IF_AND_IF(
829 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MicroSlidingFitWindow",
m_microSlidingFitWindow));
831 PANDORA_RETURN_RESULT_IF_AND_IF(
832 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MacroSlidingFitWindow",
m_macroSlidingFitWindow));
834 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
837 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
840 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
843 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
846 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
849 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
852 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxTrackGaps",
m_maxTrackGaps));
854 PANDORA_RETURN_RESULT_IF_AND_IF(
855 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"LineSegmentLength",
m_lineSegmentLength));
859 std::cout <<
"TrackInEMShowerAlgorithm: Line segment length must be positive and nonzero" << std::endl;
860 throw STATUS_CODE_INVALID_PARAMETER;
863 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"HitWidthMode",
m_hitWidthMode));
865 return STATUS_CODE_SUCCESS;
873 const CartesianVector lhsHitPosition(
876 const CartesianVector rhsHitPosition(
882 if (std::fabs(lhsLongitudinal - rhsLongitudinal) > std::numeric_limits<float>::epsilon())
885 return (lhsLongitudinal < rhsLongitudinal);
896 template void TrackRefinementBaseAlgorithm::UpdateContainers<SortFunction>(
898 template void TrackRefinementBaseAlgorithm::InitialiseContainers<SortFunction>(
float DistanceInGap(const pandora::CartesianVector &upstreamPoint, const pandora::CartesianVector &downstreamPoint, const pandora::CartesianVector &connectingLine, pandora::DetectorGapList &consideredGaps) const
Calculate the track length between two points that lies in gaps.
unsigned int m_macroSlidingFitWindow
The sliding fit window used in the fits contained within the macroSlidingFitResultMap.
bool m_hitWidthMode
Whether to consider the width of hits.
SortByDistanceAlongLine class.
ClusterAssociation class.
static bool SortHitsByPulseHeight(const pandora::CaloHit *const pLhs, const pandora::CaloHit *const pRhs)
Sort calo hits by their pulse height.
Header file for the lar hit width helper class.
bool IsCloseToLine(const pandora::CartesianVector &hitPosition, const pandora::CartesianVector &lineStart, const pandora::CartesianVector &lineDirection, const float distanceToLine) const
Check whether a hit is close to a line.
bool IsInLineSegment(const pandora::CartesianVector &lowerBoundary, const pandora::CartesianVector &upperBoundary, const pandora::CartesianVector &point) const
Whether a position falls within a specified segment of the cluster connecting line.
void AddHitsToMainTrack(const pandora::Cluster *const pMainTrackCluster, const pandora::Cluster *const pShowerTrackCluster, const pandora::CaloHitList &caloHitsToMerge, const ClusterAssociation &clusterAssociation, pandora::ClusterList &remnantClusterList) const
Remove the hits from a shower cluster that belong to the main track and add them into the main track ...
float m_minClusterLength
The minimum length of a considered cluster.
double closestDistance(const TVector3 &line0, const TVector3 &line1, const TVector3 &p)
std::pair< TwoDSlidingFitResultMap *, TwoDSlidingFitResultMap * > SlidingFitResultMapPair
unsigned int m_maxTrackGaps
The maximum number of graps allowed in the extrapolated hit vector.
const pandora::CartesianVector GetUpstreamMergePoint() const
Returns the upstream cluster merge point.
std::unordered_map< const pandora::Cluster *, pandora::CaloHitList > ClusterToCaloHitListMap
bool m_hitWidthMode
Wether to consider hit widths or not.
static pandora::CartesianVector GetClosestPointToLine2D(const pandora::CartesianVector &lineStart, const pandora::CartesianVector &lineDirection, const pandora::CaloHit *const pCaloHit)
Consider the hit width to find the closest position of a calo hit to a specified line.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)=0
float m_minHitFractionForHitRemoval
The threshold fraction of hits to be removed from the cluster for hit removal to proceed.
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
virtual bool AreExtrapolatedHitsNearBoundaries(const pandora::CaloHitVector &extrapolatedHitVector, ClusterAssociation &clusterAssociation) const =0
Check the separation of the extremal extrapolated hits with the expected endpoints or...
bool IsTrackContinuous(const ClusterAssociation &clusterAssociation, const pandora::CaloHitVector &extrapolatedCaloHitVector) const
Check whether the extrapolatedCaloHitVector contains a continuous line of hits between the cluster me...
bool GetClusterMergingCoordinates(const TwoDSlidingFitResult &clusterMicroFitResult, const TwoDSlidingFitResult &clusterMacroFitResult, const TwoDSlidingFitResult &associatedMacroFitResult, const bool isEndUpstream, pandora::CartesianVector &clusterMergePosition, pandora::CartesianVector &clusterMergeDirection) const
Get the merging coordinate and direction for an input cluster with respect to an associated cluster...
bool(* SortFunction)(const Cluster *, const Cluster *)
bool AddToNearestCluster(const pandora::Cluster *const pClusterToMerge, const pandora::Cluster *const pMainTrackCluster, const pandora::ClusterList *const pClusterList) const
Add a cluster to the nearest cluster satisfying separation distance thresholds.
Header file for the geometry helper class.
float m_maxHitDistanceFromCluster
The threshold separation between a hit and cluster for the hit to be merged into the cluster...
bool AreExtrapolatedHitsGood(const ClusterToCaloHitListMap &clusterToCaloHitListMap, ClusterAssociation &clusterAssociation) const
Perform topological checks on the collected hits to ensure no gaps are present.
int GetMaxLayer() const
Get the maximum occupied layer in the sliding fit.
bool IsClusterRemnantDisconnected(const pandora::Cluster *const pRemnantCluster) const
Whether a remnant cluster is considered to be disconnected and therefore should undergo further fragm...
int GetMinLayer() const
Get the minimum occupied layer in the sliding fit.
void UpdateContainers(const pandora::ClusterList &clustersToAdd, const pandora::ClusterList &clustersToDelete, const T sortFunction, pandora::ClusterVector &clusterVector, SlidingFitResultMapPair &slidingFitResultMapPair) const
Remove deleted clusters from the cluster vector and sliding fit maps and add in created clusters that...
pandora::CartesianVector m_lineDirection
The line end point.
void FragmentRemnantCluster(const pandora::Cluster *const pRemnantCluster, pandora::ClusterList &fragmentedClusterList) const
Fragment a cluster using simple hit separation logic.
Header file for the cluster helper class.
pandora::StatusCode GetGlobalFitPosition(const float rL, pandora::CartesianVector &position) const
Get global fit position for a given longitudinal coordinate.
float m_maxHitSeparationForConnectedCluster
The maximum separation between two adjacent (in z) hits in a connected cluster.
void ProcessRemnantClusters(const pandora::ClusterList &remnantClusterList, const pandora::Cluster *const pMainTrackCluster, const pandora::ClusterList *const pClusterList, pandora::ClusterList &createdClusters) const
Process the remnant clusters separating those that stradle the main track.
float m_stableRegionClusterFraction
The threshold fraction of fit contributing layers which defines the stable region.
std::map< int, LayerFitResult > LayerFitResultMap
void RepositionIfInGap(const pandora::CartesianVector &mergeDirection, pandora::CartesianVector &trackPoint) const
Move an input position to the higher line gap edge if it lies within a gap.
float m_lineSegmentLength
The length of a track gap.
const pandora::CartesianVector GetDownstreamMergePoint() const
Returns the downstream cluster merge point.
void GetGlobalDirection(const float dTdL, pandora::CartesianVector &direction) const
Get global direction coordinates for given sliding linear fit gradient.
const LayerFitResultMap & GetLayerFitResultMap() const
Get the layer fit result map.
std::unordered_map< const pandora::Cluster *, TwoDSlidingFitResult > TwoDSlidingFitResultMap
fhicl::Table< sbnd::crt::CRTDetSimParams > Parameters
static float GetClosestDistanceToPoint2D(const pandora::CaloHit *const pCaloHit, const pandora::CartesianVector &point2D)
Consider the hit width to find the smallest distance between a calo hit and a given point...
void InitialiseContainers(const pandora::ClusterList *pClusterList, const T sortFunction, pandora::ClusterVector &clusterVector, SlidingFitResultMapPair &slidingFitResultMapPair) const
Fill the cluster vector and sliding fit maps with clusters that are determined to be track-like...
void RemoveClusterFromContainers(const pandora::Cluster *const pClustertoRemove, pandora::ClusterVector &clusterVector, SlidingFitResultMapPair &slidingFitResultMapPair) const
Remove a cluster from the cluster vector and sliding fit maps.
Header file for the track refinement base class.
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch pandora
bool IsInBoundingBox(const float minX, const float maxX, const float minZ, const float maxZ, const pandora::CartesianVector &hitPosition) const
check whether a hit is contained within a defined square region
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
float m_maxDistanceFromMainTrack
The threshold distance for a hit to be added to the main track.
bool operator()(const pandora::CaloHit *const pLhs, const pandora::CaloHit *const pRhs) const
Sort hits by their projected distance along a line from a start point.
void GetHitsInBoundingBox(const pandora::CartesianVector &firstCorner, const pandora::CartesianVector &secondCorner, const pandora::ClusterList *const pClusterList, ClusterToCaloHitListMap &clusterToCaloHitListMap, const pandora::ClusterList &unavailableProtectedClusters=pandora::ClusterList(), const float distanceToLine=-1.f) const
Find the unprotected hits that are contained within a defined box with the option to apply a cut on t...
std::vector< art::Ptr< recob::Cluster > > ClusterVector
bool IsNearBoundary(const pandora::CaloHit *const pCaloHit, const pandora::CartesianVector &boundaryPosition2D, const float boundaryTolerance) const
Check whether a hit is close to a boundary point.
pandora::CartesianVector m_startPoint
The line start point.
const pandora::Cluster * RemoveOffAxisHitsFromTrack(const pandora::Cluster *const pCluster, const pandora::CartesianVector &splitPosition, const bool isEndUpstream, const ClusterToCaloHitListMap &clusterToCaloHitListMap, pandora::ClusterList &remnantClusterList, TwoDSlidingFitResultMap µSlidingFitResultMap, TwoDSlidingFitResultMap ¯oSlidingFitResultMap) const
Remove any hits in the upstream/downstream cluster that lie off of the main track axis (i...
void GetTrackSegmentBoundaries(const ClusterAssociation &clusterAssociation, pandora::CartesianPointVector &trackSegmentBoundaries) const
Obtain the segment boundaries of the connecting line to test whether extrapolated hits are continuous...
const pandora::CartesianVector GetConnectingLineDirection() const
Returns the unit vector of the line connecting the upstream and downstream merge points (upstream -> ...
void GetLocalPosition(const pandora::CartesianVector &position, float &rL, float &rT) const
Get local sliding fit coordinates for a given global position.
unsigned int m_microSlidingFitWindow
The sliding fit window used in the fits contained within the microSlidingFitResultMap.
TwoDSlidingFitResult class.
BEGIN_PROLOG could also be cout
float m_mergePointMinCosAngleDeviation
The threshold cos opening angle between the cluster local gradient and the associated cluster global ...
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.