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.05
f),
26 m_mergePointMinCosAngleDeviation(0.999
f),
27 m_minHitFractionForHitRemoval(0.05
f),
28 m_maxDistanceFromMainTrack(0.75
f),
29 m_maxHitDistanceFromCluster(4.
f),
30 m_maxHitSeparationForConnectedCluster(4.
f),
32 m_lineSegmentLength(3.
f),
43 for (
const Cluster *
const pCluster : *pClusterList)
54 slidingFitResultMapPair.first->insert(TwoDSlidingFitResultMap::value_type(pCluster, microSlidingFitResult));
55 slidingFitResultMapPair.second->insert(TwoDSlidingFitResultMap::value_type(pCluster, macroSlidingFitResult));
56 clusterVector.push_back(pCluster);
58 catch (
const StatusCodeException &)
63 std::sort(clusterVector.begin(), clusterVector.end(), sortFunction);
70 CartesianVector &clusterMergePosition, CartesianVector &clusterMergeDirection)
const 72 CartesianVector clusterAverageDirection(0.
f, 0.
f, 0.
f), associatedAverageDirection(0.
f, 0.
f, 0.
f);
77 const int startLayer(isEndUpstream ? clusterMicroFitResult.
GetMinLayer() : clusterMicroFitResult.
GetMaxLayer());
78 const int endLayer(isEndUpstream ? clusterMicroFitResult.
GetMaxLayer() : clusterMicroFitResult.
GetMinLayer());
79 const int loopTerminationLayer(endLayer + (isEndUpstream ? 1 : -1));
80 const int step(isEndUpstream ? 1 : -1);
84 unsigned int goodLayerCount(0);
86 clusterMicroLayerFitResultMap.at(endLayer);
88 for (
int i = startLayer; i != loopTerminationLayer; i += step)
90 const auto microIter(clusterMicroLayerFitResultMap.find(i));
92 if (microIter == clusterMicroLayerFitResultMap.end())
95 CartesianVector microDirection(0.
f, 0.
f, 0.
f);
96 clusterMicroFitResult.
GetGlobalDirection(microIter->second.GetGradient(), microDirection);
98 const float cosDirectionOpeningAngle(microDirection.GetCosOpeningAngle(associatedAverageDirection));
102 if (goodLayerCount == 0)
104 clusterMergeDirection = clusterAverageDirection;
105 PANDORA_THROW_RESULT_IF(
106 STATUS_CODE_SUCCESS, !=, clusterMicroFitResult.
GetGlobalFitPosition(microIter->second.GetL(), clusterMergePosition));
116 if (goodLayerCount > gradientStabilityWindow)
131 const ClusterList &unavailableProtectedClusters,
const float distanceToLine)
const 133 const float minX(std::min(firstCorner.GetX(), secondCorner.GetX())), maxX(std::max(firstCorner.GetX(), secondCorner.GetX()));
134 const float minZ(std::min(firstCorner.GetZ(), secondCorner.GetZ())), maxZ(std::max(firstCorner.GetZ(), secondCorner.GetZ()));
136 CartesianVector connectingLineDirection(firstCorner - secondCorner);
137 connectingLineDirection = connectingLineDirection.GetUnitVector();
139 for (
const Cluster *
const pCluster : *pClusterList)
141 if (std::find(unavailableProtectedClusters.begin(), unavailableProtectedClusters.end(), pCluster) != unavailableProtectedClusters.end())
144 const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
145 for (
const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
147 for (
const CaloHit *
const pCaloHit : *mapEntry.second)
150 : pCaloHit->GetPositionVector());
155 if (distanceToLine > 0.
f)
157 if (!this->
IsCloseToLine(hitPosition, firstCorner, connectingLineDirection, distanceToLine))
161 clusterToCaloHitListMap[pCluster].push_back(pCaloHit);
170 const float minX,
const float maxX,
const float minZ,
const float maxZ,
const CartesianVector &hitPosition)
const 172 return !((hitPosition.GetX() < minX) || (hitPosition.GetX() > maxX) || (hitPosition.GetZ() < minZ) || (hitPosition.GetZ() > maxZ));
178 const CartesianVector &lineDirection,
const float distanceToLine)
const 180 const float transverseDistanceFromLine(lineDirection.GetCrossProduct(hitPosition - lineStart).GetMagnitude());
182 return (transverseDistanceFromLine < distanceToLine);
189 CaloHitVector extrapolatedHitVector;
190 for (
const auto &entry : clusterToCaloHitListMap)
191 extrapolatedHitVector.insert(extrapolatedHitVector.begin(), entry.second.begin(), entry.second.end());
194 std::sort(extrapolatedHitVector.begin(), extrapolatedHitVector.end(),
200 if (clusterToCaloHitListMap.empty())
215 return (distanceToBoundary < boundaryTolerance);
222 CartesianPointVector trackSegmentBoundaries;
225 if (trackSegmentBoundaries.size() < 2)
227 std::cout <<
"TrackInEMShowerAlgorithm: Less than two track segment boundaries" << std::endl;
228 throw STATUS_CODE_NOT_ALLOWED;
231 unsigned int segmentsWithoutHits(0);
235 : (*caloHitIter)->GetPositionVector());
237 for (
unsigned int i = 0; i < (trackSegmentBoundaries.size() - 1); ++i)
239 if (caloHitIter == extrapolatedCaloHitVector.end())
241 ++segmentsWithoutHits;
249 unsigned int hitsInSegment(0);
250 while (this->
IsInLineSegment(trackSegmentBoundaries.at(i), trackSegmentBoundaries.at(i + 1), hitPosition))
255 if (caloHitIter == extrapolatedCaloHitVector.end())
260 : (*caloHitIter)->GetPositionVector();
263 segmentsWithoutHits = hitsInSegment ? 0 : segmentsWithoutHits + 1;
278 std::cout <<
"TrackInEMShowerAlgorithm: Line segment length must be positive and nonzero" << std::endl;
279 throw STATUS_CODE_INVALID_PARAMETER;
286 DetectorGapList consideredGaps;
289 consideredGaps.clear();
293 if (fullSegments == 0)
301 const bool splitFinalSegment(lengthOfTrackRemainder > m_lineSegmentLength * 0.5
f);
302 const int numberOfBoundaries(fullSegments + (splitFinalSegment ? 2 : 1));
304 CartesianVector segmentUpstreamBoundary(clusterAssociation.
GetUpstreamMergePoint()), segmentDownstreamBoundary(segmentUpstreamBoundary);
306 trackSegmentBoundaries.push_back(segmentUpstreamBoundary);
308 for (
int i = 1; i < numberOfBoundaries; ++i)
310 if (i < fullSegments)
316 if (splitFinalSegment)
318 segmentDownstreamBoundary += trackDirection * (m_lineSegmentLength + lengthOfTrackRemainder) * 0.5f;
322 segmentDownstreamBoundary += trackDirection * (m_lineSegmentLength + lengthOfTrackRemainder);
326 float distanceInGap(this->
DistanceInGap(segmentUpstreamBoundary, segmentDownstreamBoundary, trackDirection, consideredGaps));
327 while (distanceInGap > std::numeric_limits<float>::epsilon())
330 segmentDownstreamBoundary += trackDirection * distanceInGap;
331 distanceInGap = this->
DistanceInGap(segmentUpstreamBoundary, segmentDownstreamBoundary, trackDirection, consideredGaps);
334 trackSegmentBoundaries.push_back(segmentDownstreamBoundary);
342 const DetectorGapList detectorGapList(this->GetPandora().GetGeometry()->GetDetectorGapList());
343 for (
const DetectorGap *
const pDetectorGap : detectorGapList)
345 const LineGap *
const pLineGap(dynamic_cast<const LineGap *>(pDetectorGap));
349 const LineGapType lineGapType(pLineGap->GetLineGapType());
351 if (lineGapType == TPC_DRIFT_GAP)
353 if ((pLineGap->GetLineStartX() < trackPoint.GetX()) && (pLineGap->GetLineEndX() > trackPoint.GetX()))
355 if (std::fabs(mergeDirection.GetX()) < std::numeric_limits<float>::epsilon())
356 throw StatusCodeException(STATUS_CODE_FAILURE);
358 const float gradient(mergeDirection.GetZ() / mergeDirection.GetX());
360 trackPoint = CartesianVector(
361 pLineGap->GetLineEndX(), 0.f, trackPoint.GetZ() + (gradient * (pLineGap->GetLineEndX() - trackPoint.GetX())));
365 if ((lineGapType == TPC_WIRE_GAP_VIEW_U) || (lineGapType == TPC_WIRE_GAP_VIEW_V) || (lineGapType == TPC_WIRE_GAP_VIEW_W))
367 if ((pLineGap->GetLineStartZ() < trackPoint.GetZ()) && (pLineGap->GetLineEndZ() > trackPoint.GetZ()))
369 if (std::fabs(mergeDirection.GetZ()) < std::numeric_limits<float>::epsilon())
370 throw StatusCodeException(STATUS_CODE_FAILURE);
372 const float gradient(mergeDirection.GetX() / mergeDirection.GetZ());
374 trackPoint = CartesianVector(
375 trackPoint.GetX() + (gradient * (pLineGap->GetLineEndZ() - trackPoint.GetZ())), 0.f, pLineGap->GetLineEndZ());
385 const CartesianVector &connectingLine, DetectorGapList &consideredGaps)
const 387 const CartesianVector &lowerXPoint(upstreamPoint.GetX() < downstreamPoint.GetX() ? upstreamPoint : downstreamPoint);
388 const CartesianVector &higherXPoint(upstreamPoint.GetX() < downstreamPoint.GetX() ? downstreamPoint : upstreamPoint);
390 const float cosAngleToX(std::fabs(connectingLine.GetDotProduct(CartesianVector(1.
f, 0.
f, 0.
f))));
391 const float cosAngleToZ(std::fabs(connectingLine.GetDotProduct(CartesianVector(0.
f, 0.
f, 1.
f))));
393 float distanceInGaps(0.
f);
394 const DetectorGapList detectorGapList(this->GetPandora().GetGeometry()->GetDetectorGapList());
395 for (
const DetectorGap *
const pDetectorGap : detectorGapList)
397 if (std::find(consideredGaps.begin(), consideredGaps.end(), pDetectorGap) != consideredGaps.end())
400 const LineGap *
const pLineGap(dynamic_cast<const LineGap *>(pDetectorGap));
404 const LineGapType lineGapType(pLineGap->GetLineGapType());
406 if (lineGapType == TPC_DRIFT_GAP)
408 float xDistanceInGap(0.
f);
410 if ((pLineGap->GetLineStartX() > lowerXPoint.GetX()) && (pLineGap->GetLineEndX() < higherXPoint.GetX()))
412 xDistanceInGap = (pLineGap->GetLineEndX() - pLineGap->GetLineStartX());
414 else if ((pLineGap->GetLineStartX() < lowerXPoint.GetX()) && (pLineGap->GetLineEndX() > lowerXPoint.GetX()))
416 xDistanceInGap = (pLineGap->GetLineEndX() - lowerXPoint.GetX());
418 else if ((pLineGap->GetLineStartX() < higherXPoint.GetX()) && (pLineGap->GetLineEndX() > higherXPoint.GetX()))
420 xDistanceInGap = (higherXPoint.GetX() - pLineGap->GetLineStartX());
427 if (std::fabs(cosAngleToX) < std::numeric_limits<float>::epsilon())
428 throw StatusCodeException(STATUS_CODE_FAILURE);
430 distanceInGaps += (xDistanceInGap / cosAngleToX);
432 consideredGaps.push_back(pDetectorGap);
435 if ((lineGapType == TPC_WIRE_GAP_VIEW_U) || (lineGapType == TPC_WIRE_GAP_VIEW_V) || (lineGapType == TPC_WIRE_GAP_VIEW_W))
437 float zDistanceInGap(0.
f);
439 if ((pLineGap->GetLineStartZ() > upstreamPoint.GetZ()) && (pLineGap->GetLineEndZ() < downstreamPoint.GetZ()))
441 zDistanceInGap = pLineGap->GetLineEndZ() - pLineGap->GetLineStartZ();
443 else if ((pLineGap->GetLineStartZ() < upstreamPoint.GetZ()) && (pLineGap->GetLineEndZ() > upstreamPoint.GetZ()))
445 zDistanceInGap = pLineGap->GetLineEndZ() - upstreamPoint.GetZ();
447 else if ((pLineGap->GetLineStartZ() < downstreamPoint.GetZ()) && (pLineGap->GetLineEndZ() > downstreamPoint.GetZ()))
449 zDistanceInGap = downstreamPoint.GetZ() - pLineGap->GetLineStartZ();
456 if (std::fabs(cosAngleToZ) < std::numeric_limits<float>::epsilon())
457 throw StatusCodeException(STATUS_CODE_FAILURE);
459 distanceInGaps += (zDistanceInGap / cosAngleToZ);
461 consideredGaps.push_back(pDetectorGap);
466 return distanceInGaps;
472 const CartesianVector &lowerBoundary,
const CartesianVector &upperBoundary,
const CartesianVector &point)
const 474 const float segmentBoundaryGradient = (-1.f) * (upperBoundary.GetX() - lowerBoundary.GetX()) / (upperBoundary.GetZ() - lowerBoundary.GetZ());
475 const float xPointOnUpperLine((point.GetZ() - upperBoundary.GetZ()) / segmentBoundaryGradient + upperBoundary.GetX());
476 const float xPointOnLowerLine((point.GetZ() - lowerBoundary.GetZ()) / segmentBoundaryGradient + lowerBoundary.GetX());
478 if (std::fabs(xPointOnUpperLine - point.GetX()) < std::numeric_limits<float>::epsilon())
481 if (std::fabs(xPointOnLowerLine - point.GetX()) < std::numeric_limits<float>::epsilon())
484 if ((point.GetX() > xPointOnUpperLine) && (point.GetX() > xPointOnLowerLine))
487 if ((point.GetX() < xPointOnUpperLine) && (point.GetX() < xPointOnLowerLine))
496 const bool isEndUpstream,
const ClusterToCaloHitListMap &clusterToCaloHitListMap, ClusterList &remnantClusterList,
499 float rL(0.
f), rT(0.
f);
504 CartesianVector averageDirection(0.
f, 0.
f, 0.
f);
505 macroFitResult.GetGlobalDirection(macroFitResult.GetLayerFitResultMap().begin()->second.GetGradient(), averageDirection);
507 const bool isVertical(std::fabs(averageDirection.GetX()) < std::numeric_limits<float>::epsilon());
508 const float clusterGradient(isVertical ? 0.
f : averageDirection.GetZ() / averageDirection.GetX());
509 const float clusterIntercept(isVertical ? splitPosition.GetX() : splitPosition.GetZ() - (clusterGradient * splitPosition.GetX()));
512 std::string originalListName, fragmentListName;
513 const ClusterList originalClusterList(1, pCluster);
514 PANDORA_THROW_RESULT_IF(
515 STATUS_CODE_SUCCESS, !=, PandoraContentApi::InitializeFragmentation(*
this, originalClusterList, originalListName, fragmentListName));
517 const Cluster *pMainTrackCluster(
nullptr), *pAboveCluster(
nullptr), *pBelowCluster(
nullptr);
519 const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
520 for (
const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
522 for (
const CaloHit *
const pCaloHit : *mapEntry.second)
524 const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
525 float thisL(0.
f), thisT(0.
f);
527 microFitResult.GetLocalPosition(pCaloHit->GetPositionVector(), thisL, thisT);
529 bool isAnExtrapolatedHit(
false);
530 const auto extrapolatedCaloHitIter(clusterToCaloHitListMap.find(pCluster));
532 if (extrapolatedCaloHitIter != clusterToCaloHitListMap.end())
533 isAnExtrapolatedHit = std::find(extrapolatedCaloHitIter->second.begin(), extrapolatedCaloHitIter->second.end(), pCaloHit) !=
534 extrapolatedCaloHitIter->second.end();
536 const bool isAbove(((clusterGradient * hitPosition.GetX()) + clusterIntercept) < (isVertical ? hitPosition.GetX() : hitPosition.GetZ()));
537 const bool isToRemove(!isAnExtrapolatedHit && (((thisL < rL) && isEndUpstream) || ((thisL > rL) && !isEndUpstream)));
539 const Cluster *&pClusterToModify(isToRemove ? (isAbove ? pAboveCluster : pBelowCluster) : pMainTrackCluster);
541 if (pClusterToModify)
543 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*
this, pClusterToModify, pCaloHit));
547 PandoraContentApi::Cluster::Parameters parameters;
548 parameters.m_caloHitList.push_back(pCaloHit);
549 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*
this, parameters, pClusterToModify));
551 if (pClusterToModify != pMainTrackCluster)
552 remnantClusterList.push_back(pClusterToModify);
558 if (pAboveCluster || pBelowCluster)
560 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*
this, fragmentListName, originalListName));
561 return pMainTrackCluster;
565 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*
this, originalListName, fragmentListName));
573 const CaloHitList &caloHitsToMerge,
const ClusterAssociation &clusterAssociation, ClusterList &remnantClusterList)
const 580 if (pShowerCluster->GetNCaloHits() == caloHitsToMerge.size())
582 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*
this, pMainTrackCluster, pShowerCluster));
587 std::string originalListName, fragmentListName;
588 const ClusterList originalClusterList(1, pShowerCluster);
589 PANDORA_THROW_RESULT_IF(
590 STATUS_CODE_SUCCESS, !=, PandoraContentApi::InitializeFragmentation(*
this, originalClusterList, originalListName, fragmentListName));
592 const Cluster *pAboveCluster(
nullptr), *pBelowCluster(
nullptr);
594 const bool isVertical(std::fabs(clusterAssociation.
GetConnectingLineDirection().GetX()) < std::numeric_limits<float>::epsilon());
595 const float connectingLineGradient(
597 const float connectingLineIntercept(isVertical
601 const OrderedCaloHitList orderedCaloHitList(pShowerCluster->GetOrderedCaloHitList());
602 for (
const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
604 for (
const CaloHit *
const pCaloHit : *mapEntry.second)
606 const bool isAnExtrapolatedHit(std::find(caloHitsToMerge.begin(), caloHitsToMerge.end(), pCaloHit) != caloHitsToMerge.end());
607 if (isAnExtrapolatedHit)
609 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromCluster(*
this, pShowerCluster, pCaloHit));
610 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*
this, pMainTrackCluster, pCaloHit));
614 const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
615 const bool isAbove(((connectingLineGradient * hitPosition.GetX()) + connectingLineIntercept) <
616 (isVertical ? hitPosition.GetX() : hitPosition.GetZ()));
617 const Cluster *&pClusterToModify(isAbove ? pAboveCluster : pBelowCluster);
619 if (pClusterToModify)
621 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*
this, pClusterToModify, pCaloHit));
625 PandoraContentApi::Cluster::Parameters parameters;
626 parameters.m_caloHitList.push_back(pCaloHit);
627 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*
this, parameters, pClusterToModify));
629 remnantClusterList.push_back(pClusterToModify);
635 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*
this, fragmentListName, originalListName));
641 const ClusterList *
const pClusterList, ClusterList &createdClusters)
const 643 ClusterList fragmentedClusters;
644 for (
const Cluster *
const pRemnantCluster : remnantClusterList)
652 fragmentedClusters.push_back(pRemnantCluster);
656 for (
const Cluster *
const pFragmentedCluster : fragmentedClusters)
658 if ((pFragmentedCluster->GetNCaloHits() == 1) && (this->
AddToNearestCluster(pFragmentedCluster, pMainTrackCluster, pClusterList)))
661 createdClusters.push_back(pFragmentedCluster);
668 const Cluster *
const pClusterToMerge,
const Cluster *
const pMainTrackCluster,
const ClusterList *
const pClusterList)
const 670 const Cluster *pClosestCluster(
nullptr);
671 float closestDistance(std::numeric_limits<float>::max());
673 for (
const Cluster *
const pCluster : *pClusterList)
675 if (pCluster == pClusterToMerge)
680 if (separationDistance < closestDistance)
685 pClosestCluster = pCluster;
686 closestDistance = separationDistance;
692 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*
this, pClosestCluster, pClusterToMerge));
703 if (pRemnantCluster->GetNCaloHits() == 1)
706 const OrderedCaloHitList &orderedCaloHitList(pRemnantCluster->GetOrderedCaloHitList());
707 const CaloHit *pPreviousCaloHit(orderedCaloHitList.begin()->second->front());
709 for (
const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
711 for (
const CaloHit *
const pCaloHit : *mapEntry.second)
713 if (pCaloHit == pPreviousCaloHit)
716 const float separationDistanceSquared(pCaloHit->GetPositionVector().GetDistanceSquared(pPreviousCaloHit->GetPositionVector()));
721 pPreviousCaloHit = pCaloHit;
733 std::string originalListName, fragmentListName;
734 const ClusterList originalClusterList(1, pRemnantCluster);
735 PANDORA_THROW_RESULT_IF(
736 STATUS_CODE_SUCCESS, !=, PandoraContentApi::InitializeFragmentation(*
this, originalClusterList, originalListName, fragmentListName));
738 ClusterList createdClusters;
740 const OrderedCaloHitList &orderedCaloHitList(pRemnantCluster->GetOrderedCaloHitList());
741 for (
const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
743 for (
const CaloHit *
const pCaloHit : *mapEntry.second)
745 const Cluster *pClosestCluster(
nullptr);
747 if (!createdClusters.empty())
749 float closestDistance(std::numeric_limits<float>::max());
751 for (
const Cluster *
const pCreatedCluster : createdClusters)
756 closestDistance = separationDistance;
757 pClosestCluster = pCreatedCluster;
764 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*
this, pClosestCluster, pCaloHit));
768 PandoraContentApi::Cluster::Parameters parameters;
769 parameters.m_caloHitList.push_back(pCaloHit);
770 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*
this, parameters, pClosestCluster));
771 createdClusters.push_back(pClosestCluster);
777 if (createdClusters.empty())
779 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*
this, originalListName, fragmentListName));
780 fragmentedClusterList.push_back(pRemnantCluster);
784 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*
this, fragmentListName, originalListName));
785 fragmentedClusterList.insert(fragmentedClusterList.begin(), createdClusters.begin(), createdClusters.end());
791 template <
typename T>
796 for (
const Cluster *
const pClusterToDelete : clustersToDelete)
799 this->
InitialiseContainers(&clustersToAdd, sortFunction, clusterVector, slidingFitResultMapPair);
808 if (microFitToDelete != slidingFitResultMapPair.first->end())
809 slidingFitResultMapPair.first->erase(microFitToDelete);
812 if (macroFitToDelete != slidingFitResultMapPair.second->end())
813 slidingFitResultMapPair.second->erase(macroFitToDelete);
816 if (clusterToDelete != clusterVector.end())
817 clusterVector.erase(clusterToDelete);
824 PANDORA_RETURN_RESULT_IF_AND_IF(
825 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinClusterLength",
m_minClusterLength));
827 PANDORA_RETURN_RESULT_IF_AND_IF(
828 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MicroSlidingFitWindow",
m_microSlidingFitWindow));
830 PANDORA_RETURN_RESULT_IF_AND_IF(
831 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MacroSlidingFitWindow",
m_macroSlidingFitWindow));
833 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
836 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
839 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
842 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
845 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
848 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
851 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxTrackGaps",
m_maxTrackGaps));
853 PANDORA_RETURN_RESULT_IF_AND_IF(
854 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"LineSegmentLength",
m_lineSegmentLength));
858 std::cout <<
"TrackInEMShowerAlgorithm: Line segment length must be positive and nonzero" << std::endl;
859 throw STATUS_CODE_INVALID_PARAMETER;
862 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"HitWidthMode",
m_hitWidthMode));
864 return STATUS_CODE_SUCCESS;
872 const CartesianVector lhsHitPosition(
875 const CartesianVector rhsHitPosition(
878 const float lhsLongitudinal = m_lineDirection.GetDotProduct(lhsHitPosition - m_startPoint);
879 const float rhsLongitudinal = m_lineDirection.GetDotProduct(rhsHitPosition - m_startPoint);
881 if (std::fabs(lhsLongitudinal - rhsLongitudinal) > std::numeric_limits<float>::epsilon())
884 return (lhsLongitudinal < rhsLongitudinal);
895 template void TrackRefinementBaseAlgorithm::UpdateContainers<SortFunction>(
897 template void TrackRefinementBaseAlgorithm::InitialiseContainers<SortFunction>(
bool(* SortFunction)(const Cluster *, const Cluster *)
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.
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
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.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
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.
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 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...
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.
static float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
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
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.
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.
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.
float m_mergePointMinCosAngleDeviation
The threshold cos opening angle between the cluster local gradient and the associated cluster global ...
virtual bool AreExtrapolatedHitsNearBoundaries(const pandora::CaloHitVector &extrapolatedHitVector, ClusterAssociation &clusterAssociation) const =0
Check the separation of the extremal extrapolated hits with the expected endpoints or...
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.