All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Classes | Public Member Functions | Protected Types | Protected Member Functions | Protected Attributes | List of all members
lar_content::TrackRefinementBaseAlgorithm Class Referenceabstract

TrackRefinementBaseAlgorithm class. More...

#include <TrackRefinementBaseAlgorithm.h>

Inheritance diagram for lar_content::TrackRefinementBaseAlgorithm:
lar_content::TrackMergeRefinementAlgorithm

Classes

class  SortByDistanceAlongLine
 SortByDistanceAlongLine class. More...
 

Public Member Functions

 TrackRefinementBaseAlgorithm ()
 Default constructor. More...
 
template<typename T >
void InitialiseContainers (const ClusterList *pClusterList, const T sortFunction, ClusterVector &clusterVector, SlidingFitResultMapPair &slidingFitResultMapPair) const
 
template<typename T >
void UpdateContainers (const ClusterList &clustersToAdd, const ClusterList &clustersToDelete, const T sortFunction, ClusterVector &clusterVector, SlidingFitResultMapPair &slidingFitResultMapPair) const
 

Protected Types

typedef std::pair
< TwoDSlidingFitResultMap
*, TwoDSlidingFitResultMap * > 
SlidingFitResultMapPair
 
typedef std::unordered_map
< const pandora::Cluster
*, pandora::CaloHitList > 
ClusterToCaloHitListMap
 

Protected Member Functions

virtual pandora::StatusCode Run ()=0
 
virtual pandora::StatusCode ReadSettings (const pandora::TiXmlHandle xmlHandle)=0
 
template<typename T >
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. More...
 
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. More...
 
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 the distance to the connecting line. More...
 
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 More...
 
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. More...
 
bool AreExtrapolatedHitsGood (const ClusterToCaloHitListMap &clusterToCaloHitListMap, ClusterAssociation &clusterAssociation) const
 Perform topological checks on the collected hits to ensure no gaps are present. More...
 
virtual bool AreExtrapolatedHitsNearBoundaries (const pandora::CaloHitVector &extrapolatedHitVector, ClusterAssociation &clusterAssociation) const =0
 Check the separation of the extremal extrapolated hits with the expected endpoints or, in the case of no hits, the clusterMergePoint themselves. More...
 
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. More...
 
bool IsTrackContinuous (const ClusterAssociation &clusterAssociation, const pandora::CaloHitVector &extrapolatedCaloHitVector) const
 Check whether the extrapolatedCaloHitVector contains a continuous line of hits between the cluster merge points. More...
 
void GetTrackSegmentBoundaries (const ClusterAssociation &clusterAssociation, pandora::CartesianPointVector &trackSegmentBoundaries) const
 Obtain the segment boundaries of the connecting line to test whether extrapolated hits are continuous. More...
 
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. More...
 
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. More...
 
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. More...
 
const pandora::Cluster * RemoveOffAxisHitsFromTrack (const pandora::Cluster *const pCluster, const pandora::CartesianVector &splitPosition, const bool isEndUpstream, const ClusterToCaloHitListMap &clusterToCaloHitListMap, pandora::ClusterList &remnantClusterList, TwoDSlidingFitResultMap &microSlidingFitResultMap, TwoDSlidingFitResultMap &macroSlidingFitResultMap) const
 Remove any hits in the upstream/downstream cluster that lie off of the main track axis (i.e. clustering errors) More...
 
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 cluster. More...
 
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. More...
 
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. More...
 
bool IsClusterRemnantDisconnected (const pandora::Cluster *const pRemnantCluster) const
 Whether a remnant cluster is considered to be disconnected and therefore should undergo further fragmentation. More...
 
void FragmentRemnantCluster (const pandora::Cluster *const pRemnantCluster, pandora::ClusterList &fragmentedClusterList) const
 Fragment a cluster using simple hit separation logic. More...
 
template<typename T >
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 are determined to be track-like. More...
 
void RemoveClusterFromContainers (const pandora::Cluster *const pClustertoRemove, pandora::ClusterVector &clusterVector, SlidingFitResultMapPair &slidingFitResultMapPair) const
 Remove a cluster from the cluster vector and sliding fit maps. More...
 

Protected Attributes

float m_minClusterLength
 The minimum length of a considered cluster. More...
 
unsigned int m_microSlidingFitWindow
 The sliding fit window used in the fits contained within the microSlidingFitResultMap. More...
 
unsigned int m_macroSlidingFitWindow
 The sliding fit window used in the fits contained within the macroSlidingFitResultMap. More...
 
float m_stableRegionClusterFraction
 The threshold fraction of fit contributing layers which defines the stable region. More...
 
float m_mergePointMinCosAngleDeviation
 The threshold cos opening angle between the cluster local gradient and the associated cluster global gradient used to determine merge points. More...
 
float m_minHitFractionForHitRemoval
 The threshold fraction of hits to be removed from the cluster for hit removal to proceed. More...
 
float m_maxDistanceFromMainTrack
 The threshold distance for a hit to be added to the main track. More...
 
float m_maxHitDistanceFromCluster
 The threshold separation between a hit and cluster for the hit to be merged into the cluster. More...
 
float m_maxHitSeparationForConnectedCluster
 The maximum separation between two adjacent (in z) hits in a connected cluster. More...
 
unsigned int m_maxTrackGaps
 The maximum number of graps allowed in the extrapolated hit vector. More...
 
float m_lineSegmentLength
 The length of a track gap. More...
 
bool m_hitWidthMode
 Whether to consider the width of hits. More...
 

Detailed Description

TrackRefinementBaseAlgorithm class.

Definition at line 21 of file TrackRefinementBaseAlgorithm.h.

Member Typedef Documentation

typedef std::unordered_map<const pandora::Cluster *, pandora::CaloHitList> lar_content::TrackRefinementBaseAlgorithm::ClusterToCaloHitListMap
protected

Definition at line 31 of file TrackRefinementBaseAlgorithm.h.

Definition at line 30 of file TrackRefinementBaseAlgorithm.h.

Constructor & Destructor Documentation

lar_content::TrackRefinementBaseAlgorithm::TrackRefinementBaseAlgorithm ( )

Default constructor.

Definition at line 21 of file TrackRefinementBaseAlgorithm.cc.

21  :
22  m_minClusterLength(15.f),
31  m_maxTrackGaps(3),
33  m_hitWidthMode(false)
34 {
35 }
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.
float m_minClusterLength
The minimum length of a considered cluster.
unsigned int m_maxTrackGaps
The maximum number of graps allowed in the extrapolated hit vector.
float m_minHitFractionForHitRemoval
The threshold fraction of hits to be removed from the cluster for hit removal to proceed.
float m_maxHitDistanceFromCluster
The threshold separation between a hit and cluster for the hit to be merged into the cluster...
float m_maxHitSeparationForConnectedCluster
The maximum separation between two adjacent (in z) hits in a connected cluster.
float m_stableRegionClusterFraction
The threshold fraction of fit contributing layers which defines the stable region.
float m_lineSegmentLength
The length of a track gap.
float m_maxDistanceFromMainTrack
The threshold distance for a hit to be added to the main track.
unsigned int m_microSlidingFitWindow
The sliding fit window used in the fits contained within the microSlidingFitResultMap.
float m_mergePointMinCosAngleDeviation
The threshold cos opening angle between the cluster local gradient and the associated cluster global ...

Member Function Documentation

void lar_content::TrackRefinementBaseAlgorithm::AddHitsToMainTrack ( const pandora::Cluster *const  pMainTrackCluster,
const pandora::Cluster *const  pShowerTrackCluster,
const pandora::CaloHitList &  caloHitsToMerge,
const ClusterAssociation clusterAssociation,
pandora::ClusterList &  remnantClusterList 
) const
protected

Remove the hits from a shower cluster that belong to the main track and add them into the main track cluster.

Parameters
pMainTrackClusterthe main track cluster
pShowerClusterthe input shower cluster
caloHitsToMergethe list of calo hits to remove from the shower cluster
clusterAssociationthe clusterAssociation
remnantClusterListthe input list to store the remnant clusters

Definition at line 573 of file TrackRefinementBaseAlgorithm.cc.

575 {
576  // To ignore crossing CR muon or test beam tracks
577  if (((static_cast<float>(caloHitsToMerge.size()) / static_cast<float>(pShowerCluster->GetNCaloHits())) < m_minHitFractionForHitRemoval) &&
579  return;
580 
581  if (pShowerCluster->GetNCaloHits() == caloHitsToMerge.size())
582  {
583  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*this, pMainTrackCluster, pShowerCluster));
584  return;
585  }
586 
587  // Fragmentation initialisation
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));
592 
593  const Cluster *pAboveCluster(nullptr), *pBelowCluster(nullptr);
594 
595  const bool isVertical(std::fabs(clusterAssociation.GetConnectingLineDirection().GetX()) < std::numeric_limits<float>::epsilon());
596  const float connectingLineGradient(
597  isVertical ? 0.f : clusterAssociation.GetConnectingLineDirection().GetZ() / clusterAssociation.GetConnectingLineDirection().GetX());
598  const float connectingLineIntercept(isVertical ? clusterAssociation.GetUpstreamMergePoint().GetX()
599  : clusterAssociation.GetUpstreamMergePoint().GetZ() -
600  (connectingLineGradient * clusterAssociation.GetUpstreamMergePoint().GetX()));
601 
602  const OrderedCaloHitList orderedCaloHitList(pShowerCluster->GetOrderedCaloHitList());
603  for (const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
604  {
605  for (const CaloHit *const pCaloHit : *mapEntry.second)
606  {
607  const bool isAnExtrapolatedHit(std::find(caloHitsToMerge.begin(), caloHitsToMerge.end(), pCaloHit) != caloHitsToMerge.end());
608  if (isAnExtrapolatedHit)
609  {
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));
612  }
613  else
614  {
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);
619 
620  if (pClusterToModify)
621  {
622  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*this, pClusterToModify, pCaloHit));
623  }
624  else
625  {
627  parameters.m_caloHitList.push_back(pCaloHit);
628  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*this, parameters, pClusterToModify));
629 
630  remnantClusterList.push_back(pClusterToModify);
631  }
632  }
633  }
634  }
635 
636  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*this, fragmentListName, originalListName));
637 }
float m_minClusterLength
The minimum length of a considered cluster.
float m_minHitFractionForHitRemoval
The threshold fraction of hits to be removed from the cluster for hit removal to proceed.
fhicl::Table< sbnd::crt::CRTDetSimParams > Parameters
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
bool lar_content::TrackRefinementBaseAlgorithm::AddToNearestCluster ( const pandora::Cluster *const  pClusterToMerge,
const pandora::Cluster *const  pMainTrackCluster,
const pandora::ClusterList *const  pClusterList 
) const
protected

Add a cluster to the nearest cluster satisfying separation distance thresholds.

Parameters
pClusterToMergethe cluster to merge
pMainTrackClusterthe main track cluster
pClusterListthe list of all clusters
Returns
whether cluster was added to a nearby cluster

Definition at line 668 of file TrackRefinementBaseAlgorithm.cc.

670 {
671  const Cluster *pClosestCluster(nullptr);
672  float closestDistance(std::numeric_limits<float>::max());
673 
674  for (const Cluster *const pCluster : *pClusterList)
675  {
676  if (pCluster == pClusterToMerge)
677  continue;
678 
679  const float separationDistance(LArClusterHelper::GetClosestDistance(pClusterToMerge, pCluster));
680 
681  if (separationDistance < closestDistance)
682  {
683  if ((pCluster == pMainTrackCluster) && (separationDistance > m_maxDistanceFromMainTrack))
684  continue;
685 
686  pClosestCluster = pCluster;
687  closestDistance = separationDistance;
688  }
689  }
690 
692  {
693  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*this, pClosestCluster, pClusterToMerge));
694  return true;
695  }
696 
697  return false;
698 }
double closestDistance(const TVector3 &line0, const TVector3 &line1, const TVector3 &p)
float m_maxHitDistanceFromCluster
The threshold separation between a hit and cluster for the hit to be merged into the cluster...
float m_maxDistanceFromMainTrack
The threshold distance for a hit to be added to the main track.
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.
bool lar_content::TrackRefinementBaseAlgorithm::AreExtrapolatedHitsGood ( const ClusterToCaloHitListMap clusterToCaloHitListMap,
ClusterAssociation clusterAssociation 
) const
protected

Perform topological checks on the collected hits to ensure no gaps are present.

Parameters
clusterToCaloHitListMapthe input map [parent cluster -> list of hits which belong to the main track]
clusterAssociationthe clusterAssociation
Returns
whether the checks pass

Definition at line 188 of file TrackRefinementBaseAlgorithm.cc.

189 {
190  CaloHitVector extrapolatedHitVector;
191  for (const auto &entry : clusterToCaloHitListMap)
192  extrapolatedHitVector.insert(extrapolatedHitVector.begin(), entry.second.begin(), entry.second.end());
193 
194  // ATTN: Extrapolated hit checks require extrapolatedHitVector to be ordered from upstream -> downstream merge point
195  std::sort(extrapolatedHitVector.begin(), extrapolatedHitVector.end(),
196  SortByDistanceAlongLine(clusterAssociation.GetUpstreamMergePoint(), clusterAssociation.GetConnectingLineDirection(), m_hitWidthMode));
197 
198  if (!this->AreExtrapolatedHitsNearBoundaries(extrapolatedHitVector, clusterAssociation))
199  return false;
200 
201  if (clusterToCaloHitListMap.empty())
202  return true;
203 
204  if (!this->IsTrackContinuous(clusterAssociation, extrapolatedHitVector))
205  return false;
206 
207  return true;
208 }
bool m_hitWidthMode
Whether to consider the width of hits.
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...
virtual bool lar_content::TrackRefinementBaseAlgorithm::AreExtrapolatedHitsNearBoundaries ( const pandora::CaloHitVector &  extrapolatedHitVector,
ClusterAssociation clusterAssociation 
) const
protectedpure virtual

Check the separation of the extremal extrapolated hits with the expected endpoints or, in the case of no hits, the clusterMergePoint themselves.

Parameters
extrapolatedHitVectorthe extrapolated hit vector (ordered closest hit to the upstream merge point -> furthest hit)
clusterAssociationthe clusterAssociation
Returns
whether the check passes

Implemented in lar_content::TrackMergeRefinementAlgorithm.

float lar_content::TrackRefinementBaseAlgorithm::DistanceInGap ( const pandora::CartesianVector &  upstreamPoint,
const pandora::CartesianVector &  downstreamPoint,
const pandora::CartesianVector &  connectingLine,
pandora::DetectorGapList &  consideredGaps 
) const
protected

Calculate the track length between two points that lies in gaps.

Parameters
upstreamPointthe upstream point
downstreamPointthe downstream point
connectingLinethe track direction
consideredGapsthe list of gaps to ignore

Definition at line 385 of file TrackRefinementBaseAlgorithm.cc.

387 {
388  const CartesianVector &lowerXPoint(upstreamPoint.GetX() < downstreamPoint.GetX() ? upstreamPoint : downstreamPoint);
389  const CartesianVector &higherXPoint(upstreamPoint.GetX() < downstreamPoint.GetX() ? downstreamPoint : upstreamPoint);
390 
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))));
393 
394  float distanceInGaps(0.f);
395  const DetectorGapList detectorGapList(this->GetPandora().GetGeometry()->GetDetectorGapList());
396  for (const DetectorGap *const pDetectorGap : detectorGapList)
397  {
398  if (std::find(consideredGaps.begin(), consideredGaps.end(), pDetectorGap) != consideredGaps.end())
399  continue;
400 
401  const LineGap *const pLineGap(dynamic_cast<const LineGap *>(pDetectorGap));
402 
403  if (pLineGap)
404  {
405  const LineGapType lineGapType(pLineGap->GetLineGapType());
406 
407  if (lineGapType == TPC_DRIFT_GAP)
408  {
409  float xDistanceInGap(0.f);
410 
411  if ((pLineGap->GetLineStartX() > lowerXPoint.GetX()) && (pLineGap->GetLineEndX() < higherXPoint.GetX()))
412  {
413  xDistanceInGap = (pLineGap->GetLineEndX() - pLineGap->GetLineStartX());
414  }
415  else if ((pLineGap->GetLineStartX() < lowerXPoint.GetX()) && (pLineGap->GetLineEndX() > lowerXPoint.GetX()))
416  {
417  xDistanceInGap = (pLineGap->GetLineEndX() - lowerXPoint.GetX());
418  }
419  else if ((pLineGap->GetLineStartX() < higherXPoint.GetX()) && (pLineGap->GetLineEndX() > higherXPoint.GetX()))
420  {
421  xDistanceInGap = (higherXPoint.GetX() - pLineGap->GetLineStartX());
422  }
423  else
424  {
425  continue;
426  }
427 
428  if (std::fabs(cosAngleToX) < std::numeric_limits<float>::epsilon())
429  throw StatusCodeException(STATUS_CODE_FAILURE);
430 
431  distanceInGaps += (xDistanceInGap / cosAngleToX);
432 
433  consideredGaps.push_back(pDetectorGap);
434  }
435 
436  if ((lineGapType == TPC_WIRE_GAP_VIEW_U) || (lineGapType == TPC_WIRE_GAP_VIEW_V) || (lineGapType == TPC_WIRE_GAP_VIEW_W))
437  {
438  float zDistanceInGap(0.f);
439 
440  if ((pLineGap->GetLineStartZ() > upstreamPoint.GetZ()) && (pLineGap->GetLineEndZ() < downstreamPoint.GetZ()))
441  {
442  zDistanceInGap = pLineGap->GetLineEndZ() - pLineGap->GetLineStartZ();
443  }
444  else if ((pLineGap->GetLineStartZ() < upstreamPoint.GetZ()) && (pLineGap->GetLineEndZ() > upstreamPoint.GetZ()))
445  {
446  zDistanceInGap = pLineGap->GetLineEndZ() - upstreamPoint.GetZ();
447  }
448  else if ((pLineGap->GetLineStartZ() < downstreamPoint.GetZ()) && (pLineGap->GetLineEndZ() > downstreamPoint.GetZ()))
449  {
450  zDistanceInGap = downstreamPoint.GetZ() - pLineGap->GetLineStartZ();
451  }
452  else
453  {
454  continue;
455  }
456 
457  if (std::fabs(cosAngleToZ) < std::numeric_limits<float>::epsilon())
458  throw StatusCodeException(STATUS_CODE_FAILURE);
459 
460  distanceInGaps += (zDistanceInGap / cosAngleToZ);
461 
462  consideredGaps.push_back(pDetectorGap);
463  }
464  }
465  }
466 
467  return distanceInGaps;
468 }
void lar_content::TrackRefinementBaseAlgorithm::FragmentRemnantCluster ( const pandora::Cluster *const  pRemnantCluster,
pandora::ClusterList &  fragmentedClusterList 
) const
protected

Fragment a cluster using simple hit separation logic.

Parameters
pRemnantClusterthe input remnant cluster to fragment
fragmentedClusterListthe input list to store the final remnant clusters

Definition at line 731 of file TrackRefinementBaseAlgorithm.cc.

732 {
733  // Fragmentation initialisation
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));
738 
739  ClusterList createdClusters;
740 
741  const OrderedCaloHitList &orderedCaloHitList(pRemnantCluster->GetOrderedCaloHitList());
742  for (const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
743  {
744  for (const CaloHit *const pCaloHit : *mapEntry.second)
745  {
746  const Cluster *pClosestCluster(nullptr);
747 
748  if (!createdClusters.empty())
749  {
750  float closestDistance(std::numeric_limits<float>::max());
751 
752  for (const Cluster *const pCreatedCluster : createdClusters)
753  {
754  const float separationDistance(LArClusterHelper::GetClosestDistance(pCaloHit->GetPositionVector(), pCreatedCluster));
755  if ((separationDistance < closestDistance) && (separationDistance < m_maxHitDistanceFromCluster))
756  {
757  closestDistance = separationDistance;
758  pClosestCluster = pCreatedCluster;
759  }
760  }
761  }
762 
763  if (pClosestCluster)
764  {
765  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*this, pClosestCluster, pCaloHit));
766  }
767  else
768  {
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);
773  }
774  }
775  }
776 
777  // End fragmentation
778  if (createdClusters.empty())
779  {
780  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*this, originalListName, fragmentListName));
781  fragmentedClusterList.push_back(pRemnantCluster);
782  }
783  else
784  {
785  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*this, fragmentListName, originalListName));
786  fragmentedClusterList.insert(fragmentedClusterList.begin(), createdClusters.begin(), createdClusters.end());
787  }
788 }
double closestDistance(const TVector3 &line0, const TVector3 &line1, const TVector3 &p)
float m_maxHitDistanceFromCluster
The threshold separation between a hit and cluster for the hit to be merged into the cluster...
fhicl::Table< sbnd::crt::CRTDetSimParams > Parameters
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.
bool lar_content::TrackRefinementBaseAlgorithm::GetClusterMergingCoordinates ( const TwoDSlidingFitResult clusterMicroFitResult,
const TwoDSlidingFitResult clusterMacroFitResult,
const TwoDSlidingFitResult associatedMacroFitResult,
const bool  isEndUpstream,
pandora::CartesianVector &  clusterMergePosition,
pandora::CartesianVector &  clusterMergeDirection 
) const
protected

Get the merging coordinate and direction for an input cluster with respect to an associated cluster.

Parameters
clusterMicroFitResultthe local TwoDSlidingFitResult of the cluster
clusterMacroFitResultthe global TwoDSlidingFitResult of the cluster
associatedMacroFitReultthe global TwoDSlidingFitResult of the associated cluster
isEndUpstreamwhether the sought cluster merge point is the upstream
clusterMergePositionthe merge position of the cluster
clusterMergeDirectionthe merge direction of the cluster
Returns
whether it was possible to find a suitable merge position

Definition at line 69 of file TrackRefinementBaseAlgorithm.cc.

72 {
73  CartesianVector clusterAverageDirection(0.f, 0.f, 0.f), associatedAverageDirection(0.f, 0.f, 0.f);
74  clusterMacroFitResult.GetGlobalDirection(clusterMacroFitResult.GetLayerFitResultMap().begin()->second.GetGradient(), clusterAverageDirection);
75  associatedMacroFitResult.GetGlobalDirection(associatedMacroFitResult.GetLayerFitResultMap().begin()->second.GetGradient(), associatedAverageDirection);
76 
77  const LayerFitResultMap &clusterMicroLayerFitResultMap(clusterMicroFitResult.GetLayerFitResultMap());
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);
82 
83  // ATTN: Search for stable region for which the local layer gradient agrees well with associated cluster global gradient
84  unsigned int gradientStabilityWindow(std::ceil(clusterMicroLayerFitResultMap.size() * m_stableRegionClusterFraction));
85  unsigned int goodLayerCount(0);
86 
87  clusterMicroLayerFitResultMap.at(endLayer);
88 
89  for (int i = startLayer; i != loopTerminationLayer; i += step)
90  {
91  const auto microIter(clusterMicroLayerFitResultMap.find(i));
92 
93  if (microIter == clusterMicroLayerFitResultMap.end())
94  continue;
95 
96  CartesianVector microDirection(0.f, 0.f, 0.f);
97  clusterMicroFitResult.GetGlobalDirection(microIter->second.GetGradient(), microDirection);
98 
99  const float cosDirectionOpeningAngle(microDirection.GetCosOpeningAngle(associatedAverageDirection));
100  if (cosDirectionOpeningAngle > m_mergePointMinCosAngleDeviation)
101  {
102  // ATTN: Set merge point and direction as that at the first layer in the stable region
103  if (goodLayerCount == 0)
104  {
105  clusterMergeDirection = clusterAverageDirection;
106  PANDORA_THROW_RESULT_IF(
107  STATUS_CODE_SUCCESS, !=, clusterMicroFitResult.GetGlobalFitPosition(microIter->second.GetL(), clusterMergePosition));
108  }
109 
110  ++goodLayerCount;
111  }
112  else
113  {
114  goodLayerCount = 0;
115  }
116 
117  if (goodLayerCount > gradientStabilityWindow)
118  break;
119 
120  // ATTN: Abort merging process have not found a stable region
121  if (i == endLayer)
122  return false;
123  }
124 
125  return true;
126 }
float m_stableRegionClusterFraction
The threshold fraction of fit contributing layers which defines the stable region.
std::map< int, LayerFitResult > LayerFitResultMap
float m_mergePointMinCosAngleDeviation
The threshold cos opening angle between the cluster local gradient and the associated cluster global ...
void lar_content::TrackRefinementBaseAlgorithm::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
protected

Find the unprotected hits that are contained within a defined box with the option to apply a cut on the distance to the connecting line.

Parameters
firstCornerthe position of one corner
secondCornerthe position of the opposite corner
pClusterListthe list of all clusters
clusterToCaloHitListMapthe output map [parent cluster -> list of hits which belong to the main track]
unavailableProtectedClustersthe list of clusters whose hits are protected
distanceToLinethe maximum perpendicular distance of a collected hit from the connecting line

Definition at line 130 of file TrackRefinementBaseAlgorithm.cc.

133 {
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()));
136 
137  CartesianVector connectingLineDirection(firstCorner - secondCorner);
138  connectingLineDirection = connectingLineDirection.GetUnitVector();
139 
140  for (const Cluster *const pCluster : *pClusterList)
141  {
142  if (std::find(unavailableProtectedClusters.begin(), unavailableProtectedClusters.end(), pCluster) != unavailableProtectedClusters.end())
143  continue;
144 
145  const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
146  for (const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
147  {
148  for (const CaloHit *const pCaloHit : *mapEntry.second)
149  {
150  CartesianVector hitPosition(m_hitWidthMode ? LArHitWidthHelper::GetClosestPointToLine2D(firstCorner, connectingLineDirection, pCaloHit)
151  : pCaloHit->GetPositionVector());
152 
153  if (!this->IsInBoundingBox(minX, maxX, minZ, maxZ, hitPosition))
154  continue;
155 
156  if (distanceToLine > 0.f)
157  {
158  if (!this->IsCloseToLine(hitPosition, firstCorner, connectingLineDirection, distanceToLine))
159  continue;
160  }
161 
162  clusterToCaloHitListMap[pCluster].push_back(pCaloHit);
163  }
164  }
165  }
166 }
bool m_hitWidthMode
Whether to consider the width of hits.
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.
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.
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
void lar_content::TrackRefinementBaseAlgorithm::GetTrackSegmentBoundaries ( const ClusterAssociation clusterAssociation,
pandora::CartesianPointVector &  trackSegmentBoundaries 
) const
protected

Obtain the segment boundaries of the connecting line to test whether extrapolated hits are continuous.

Parameters
clusterAssociationthe clusterAssociation
trackSegmentBoundariesthe output vector of segment boundaries

Definition at line 275 of file TrackRefinementBaseAlgorithm.cc.

276 {
277  if (m_lineSegmentLength < std::numeric_limits<float>::epsilon())
278  {
279  std::cout << "TrackInEMShowerAlgorithm: Line segment length must be positive and nonzero" << std::endl;
280  throw STATUS_CODE_INVALID_PARAMETER;
281  }
282 
283  const CartesianVector &trackDirection(clusterAssociation.GetConnectingLineDirection());
284  float trackLength((clusterAssociation.GetUpstreamMergePoint() - clusterAssociation.GetDownstreamMergePoint()).GetMagnitude());
285 
286  // ATTN: Consider the existence of gaps where no hits will be found
287  DetectorGapList consideredGaps;
288  trackLength -= this->DistanceInGap(
289  clusterAssociation.GetUpstreamMergePoint(), clusterAssociation.GetDownstreamMergePoint(), trackDirection, consideredGaps);
290  consideredGaps.clear();
291 
292  const int fullSegments(std::floor(trackLength / m_lineSegmentLength));
293 
294  if (fullSegments == 0)
295  {
296  trackSegmentBoundaries = {clusterAssociation.GetUpstreamMergePoint(), clusterAssociation.GetDownstreamMergePoint()};
297  return;
298  }
299 
300  // ATTN: To handle final segment merge track remainder with preceding segment and if track remainder was more than half of the segment length split into two
301  const float lengthOfTrackRemainder(trackLength - (fullSegments * m_lineSegmentLength));
302  const bool splitFinalSegment(lengthOfTrackRemainder > m_lineSegmentLength * 0.5f);
303  const int numberOfBoundaries(fullSegments + (splitFinalSegment ? 2 : 1));
304 
305  CartesianVector segmentUpstreamBoundary(clusterAssociation.GetUpstreamMergePoint()), segmentDownstreamBoundary(segmentUpstreamBoundary);
306  this->RepositionIfInGap(trackDirection, segmentUpstreamBoundary);
307  trackSegmentBoundaries.push_back(segmentUpstreamBoundary);
308 
309  for (int i = 1; i < numberOfBoundaries; ++i)
310  {
311  if (i < fullSegments)
312  {
313  segmentDownstreamBoundary += trackDirection * m_lineSegmentLength;
314  }
315  else
316  {
317  if (splitFinalSegment)
318  {
319  segmentDownstreamBoundary += trackDirection * (m_lineSegmentLength + lengthOfTrackRemainder) * 0.5f;
320  }
321  else
322  {
323  segmentDownstreamBoundary += trackDirection * (m_lineSegmentLength + lengthOfTrackRemainder);
324  }
325  }
326 
327  float distanceInGap(this->DistanceInGap(segmentUpstreamBoundary, segmentDownstreamBoundary, trackDirection, consideredGaps));
328  while (distanceInGap > std::numeric_limits<float>::epsilon())
329  {
330  this->RepositionIfInGap(trackDirection, segmentDownstreamBoundary);
331  segmentDownstreamBoundary += trackDirection * distanceInGap;
332  distanceInGap = this->DistanceInGap(segmentUpstreamBoundary, segmentDownstreamBoundary, trackDirection, consideredGaps);
333  }
334 
335  trackSegmentBoundaries.push_back(segmentDownstreamBoundary);
336  }
337 }
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.
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.
BEGIN_PROLOG could also be cout
template<typename T >
void lar_content::TrackRefinementBaseAlgorithm::InitialiseContainers ( const ClusterList *  pClusterList,
const T  sortFunction,
ClusterVector &  clusterVector,
SlidingFitResultMapPair slidingFitResultMapPair 
) const

Definition at line 40 of file TrackRefinementBaseAlgorithm.cc.

42 {
43  const float slidingFitPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
44 
45  for (const Cluster *const pCluster : *pClusterList)
46  {
48  continue;
49 
50  try
51  {
52  const TwoDSlidingFitResult microSlidingFitResult(pCluster, m_microSlidingFitWindow, slidingFitPitch);
53  const TwoDSlidingFitResult macroSlidingFitResult(pCluster, m_macroSlidingFitWindow, slidingFitPitch);
54 
55  slidingFitResultMapPair.first->insert(TwoDSlidingFitResultMap::value_type(pCluster, microSlidingFitResult));
56  slidingFitResultMapPair.second->insert(TwoDSlidingFitResultMap::value_type(pCluster, macroSlidingFitResult));
57  clusterVector.push_back(pCluster);
58  }
59  catch (const StatusCodeException &)
60  {
61  }
62  }
63 
64  std::sort(clusterVector.begin(), clusterVector.end(), sortFunction);
65 }
unsigned int m_macroSlidingFitWindow
The sliding fit window used in the fits contained within the macroSlidingFitResultMap.
float m_minClusterLength
The minimum length of a considered cluster.
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
unsigned int m_microSlidingFitWindow
The sliding fit window used in the fits contained within the microSlidingFitResultMap.
template<typename T >
void lar_content::TrackRefinementBaseAlgorithm::InitialiseContainers ( const pandora::ClusterList *  pClusterList,
const T  sortFunction,
pandora::ClusterVector &  clusterVector,
SlidingFitResultMapPair slidingFitResultMapPair 
) const
protected

Fill the cluster vector and sliding fit maps with clusters that are determined to be track-like.

Parameters
pClusterListthe list of input clusters
sortFunctionthe sort class or function used to sort the clusterVector
clusterVectorthe input vector to store clusters considered within the algorithm
slidingFitResultMapPairthe {micro, macro} pair of [cluster -> TwoDSlidingFitResult] maps
bool lar_content::TrackRefinementBaseAlgorithm::IsCloseToLine ( const pandora::CartesianVector &  hitPosition,
const pandora::CartesianVector &  lineStart,
const pandora::CartesianVector &  lineDirection,
const float  distanceToLine 
) const
protected

Check whether a hit is close to a line.

Parameters
hitPositionthe position of the hit
lineStartthe start point of the line (can actually be any point on the line)
lineDirectionthe unit vector of the line direction
distanceToLinethe definition of 'close'
Returns
whether the hit is close to the line

Definition at line 178 of file TrackRefinementBaseAlgorithm.cc.

180 {
181  const float transverseDistanceFromLine(lineDirection.GetCrossProduct(hitPosition - lineStart).GetMagnitude());
182 
183  return (transverseDistanceFromLine < distanceToLine);
184 }
bool lar_content::TrackRefinementBaseAlgorithm::IsClusterRemnantDisconnected ( const pandora::Cluster *const  pRemnantCluster) const
protected

Whether a remnant cluster is considered to be disconnected and therefore should undergo further fragmentation.

Parameters
pRemnantClusterthe input remnant cluster
Returns
whether the remnant cluster is disconnected

Definition at line 702 of file TrackRefinementBaseAlgorithm.cc.

703 {
704  if (pRemnantCluster->GetNCaloHits() == 1)
705  return false;
706 
707  const OrderedCaloHitList &orderedCaloHitList(pRemnantCluster->GetOrderedCaloHitList());
708  const CaloHit *pPreviousCaloHit(orderedCaloHitList.begin()->second->front());
709 
710  for (const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
711  {
712  for (const CaloHit *const pCaloHit : *mapEntry.second)
713  {
714  if (pCaloHit == pPreviousCaloHit)
715  continue;
716 
717  const float separationDistanceSquared(pCaloHit->GetPositionVector().GetDistanceSquared(pPreviousCaloHit->GetPositionVector()));
718 
720  return true;
721 
722  pPreviousCaloHit = pCaloHit;
723  }
724  }
725 
726  return false;
727 }
float m_maxHitSeparationForConnectedCluster
The maximum separation between two adjacent (in z) hits in a connected cluster.
bool lar_content::TrackRefinementBaseAlgorithm::IsInBoundingBox ( const float  minX,
const float  maxX,
const float  minZ,
const float  maxZ,
const pandora::CartesianVector &  hitPosition 
) const
protected

check whether a hit is contained within a defined square region

Parameters
minXthe minimum x coordinate of the square region
maxXthe maximum x coordinate of the square region
minZthe minimum z coordinate of the square region
maxZthe maximum z coordinate of the square region
hitPositionthe position of the hit
Returns
whether the hit is contained within the square region

Definition at line 170 of file TrackRefinementBaseAlgorithm.cc.

172 {
173  return !((hitPosition.GetX() < minX) || (hitPosition.GetX() > maxX) || (hitPosition.GetZ() < minZ) || (hitPosition.GetZ() > maxZ));
174 }
bool lar_content::TrackRefinementBaseAlgorithm::IsInLineSegment ( const pandora::CartesianVector &  lowerBoundary,
const pandora::CartesianVector &  upperBoundary,
const pandora::CartesianVector &  point 
) const
protected

Whether a position falls within a specified segment of the cluster connecting line.

Parameters
lowerBoundarythe lower boundary of the segment
upperBoundarythe upper boundary of the segment
pointthe position
Returns
whether the position falls within segment

Definition at line 472 of file TrackRefinementBaseAlgorithm.cc.

474 {
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());
478 
479  if (std::fabs(xPointOnUpperLine - point.GetX()) < std::numeric_limits<float>::epsilon())
480  return true;
481 
482  if (std::fabs(xPointOnLowerLine - point.GetX()) < std::numeric_limits<float>::epsilon())
483  return true;
484 
485  if ((point.GetX() > xPointOnUpperLine) && (point.GetX() > xPointOnLowerLine))
486  return false;
487 
488  if ((point.GetX() < xPointOnUpperLine) && (point.GetX() < xPointOnLowerLine))
489  return false;
490 
491  return true;
492 }
bool lar_content::TrackRefinementBaseAlgorithm::IsNearBoundary ( const pandora::CaloHit *const  pCaloHit,
const pandora::CartesianVector &  boundaryPosition2D,
const float  boundaryTolerance 
) const
protected

Check whether a hit is close to a boundary point.

Parameters
pCaloHitthe input calo hit
boundaryPosition2Dthe position of the 2D boundary point
boundaryTolerancethe definition of close
Returns
whether the check passes

Definition at line 212 of file TrackRefinementBaseAlgorithm.cc.

213 {
214  const float distanceToBoundary(LArHitWidthHelper::GetClosestDistanceToPoint2D(pCaloHit, boundaryPosition2D));
215 
216  return (distanceToBoundary < boundaryTolerance);
217 }
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...
bool lar_content::TrackRefinementBaseAlgorithm::IsTrackContinuous ( const ClusterAssociation clusterAssociation,
const pandora::CaloHitVector &  extrapolatedCaloHitVector 
) const
protected

Check whether the extrapolatedCaloHitVector contains a continuous line of hits between the cluster merge points.

Parameters
clusterAssociationthe clusterAssociation
extrapolatedCaloHitVectorthe vector of extrapolated calo hits
Returns
whether the calo hits are continuous

Definition at line 221 of file TrackRefinementBaseAlgorithm.cc.

222 {
223  CartesianPointVector trackSegmentBoundaries;
224  this->GetTrackSegmentBoundaries(clusterAssociation, trackSegmentBoundaries);
225 
226  if (trackSegmentBoundaries.size() < 2)
227  {
228  std::cout << "TrackInEMShowerAlgorithm: Less than two track segment boundaries" << std::endl;
229  throw STATUS_CODE_NOT_ALLOWED;
230  }
231 
232  unsigned int segmentsWithoutHits(0);
233  CaloHitVector::const_iterator caloHitIter(extrapolatedCaloHitVector.begin());
234  CartesianVector hitPosition(m_hitWidthMode ? LArHitWidthHelper::GetClosestPointToLine2D(clusterAssociation.GetUpstreamMergePoint(),
235  clusterAssociation.GetConnectingLineDirection(), *caloHitIter)
236  : (*caloHitIter)->GetPositionVector());
237 
238  for (unsigned int i = 0; i < (trackSegmentBoundaries.size() - 1); ++i)
239  {
240  if (caloHitIter == extrapolatedCaloHitVector.end())
241  {
242  ++segmentsWithoutHits;
243 
244  if (segmentsWithoutHits > m_maxTrackGaps)
245  return false;
246 
247  continue;
248  }
249 
250  unsigned int hitsInSegment(0);
251  while (this->IsInLineSegment(trackSegmentBoundaries.at(i), trackSegmentBoundaries.at(i + 1), hitPosition))
252  {
253  ++hitsInSegment;
254  ++caloHitIter;
255 
256  if (caloHitIter == extrapolatedCaloHitVector.end())
257  break;
258 
259  hitPosition = m_hitWidthMode ? LArHitWidthHelper::GetClosestPointToLine2D(clusterAssociation.GetUpstreamMergePoint(),
260  clusterAssociation.GetConnectingLineDirection(), *caloHitIter)
261  : (*caloHitIter)->GetPositionVector();
262  }
263 
264  segmentsWithoutHits = hitsInSegment ? 0 : segmentsWithoutHits + 1;
265 
266  if (segmentsWithoutHits > m_maxTrackGaps)
267  return false;
268  }
269 
270  return true;
271 }
bool m_hitWidthMode
Whether to consider the width of hits.
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.
unsigned int m_maxTrackGaps
The maximum number of graps allowed in the extrapolated hit vector.
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.
void GetTrackSegmentBoundaries(const ClusterAssociation &clusterAssociation, pandora::CartesianPointVector &trackSegmentBoundaries) const
Obtain the segment boundaries of the connecting line to test whether extrapolated hits are continuous...
BEGIN_PROLOG could also be cout
void lar_content::TrackRefinementBaseAlgorithm::ProcessRemnantClusters ( const pandora::ClusterList &  remnantClusterList,
const pandora::Cluster *const  pMainTrackCluster,
const pandora::ClusterList *const  pClusterList,
pandora::ClusterList &  createdClusters 
) const
protected

Process the remnant clusters separating those that stradle the main track.

Parameters
remnantClusterListthe list of remnant clusters to process
pMainTrackClusterthe main track cluster
pClusterListthe list of all clusters
createdClustersthe input list to store the final remnant clusters

Definition at line 641 of file TrackRefinementBaseAlgorithm.cc.

643 {
644  ClusterList fragmentedClusters;
645  for (const Cluster *const pRemnantCluster : remnantClusterList)
646  {
647  if (this->IsClusterRemnantDisconnected(pRemnantCluster))
648  {
649  this->FragmentRemnantCluster(pRemnantCluster, fragmentedClusters);
650  }
651  else
652  {
653  fragmentedClusters.push_back(pRemnantCluster);
654  }
655  }
656 
657  for (const Cluster *const pFragmentedCluster : fragmentedClusters)
658  {
659  if ((pFragmentedCluster->GetNCaloHits() == 1) && (this->AddToNearestCluster(pFragmentedCluster, pMainTrackCluster, pClusterList)))
660  continue;
661 
662  createdClusters.push_back(pFragmentedCluster);
663  }
664 }
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.
bool IsClusterRemnantDisconnected(const pandora::Cluster *const pRemnantCluster) const
Whether a remnant cluster is considered to be disconnected and therefore should undergo further fragm...
void FragmentRemnantCluster(const pandora::Cluster *const pRemnantCluster, pandora::ClusterList &fragmentedClusterList) const
Fragment a cluster using simple hit separation logic.
StatusCode lar_content::TrackRefinementBaseAlgorithm::ReadSettings ( const pandora::TiXmlHandle  xmlHandle)
protectedpure virtual

Implemented in lar_content::TrackMergeRefinementAlgorithm.

Definition at line 823 of file TrackRefinementBaseAlgorithm.cc.

824 {
825  PANDORA_RETURN_RESULT_IF_AND_IF(
826  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinClusterLength", m_minClusterLength));
827 
828  PANDORA_RETURN_RESULT_IF_AND_IF(
829  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MicroSlidingFitWindow", m_microSlidingFitWindow));
830 
831  PANDORA_RETURN_RESULT_IF_AND_IF(
832  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MacroSlidingFitWindow", m_macroSlidingFitWindow));
833 
834  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
835  XmlHelper::ReadValue(xmlHandle, "StableRegionClusterFraction", m_stableRegionClusterFraction));
836 
837  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
838  XmlHelper::ReadValue(xmlHandle, "MergePointMinCosAngleDeviation", m_mergePointMinCosAngleDeviation));
839 
840  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
841  XmlHelper::ReadValue(xmlHandle, "MinHitFractionForHitRemoval", m_minHitFractionForHitRemoval));
842 
843  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
844  XmlHelper::ReadValue(xmlHandle, "MaxDistanceFromMainTrack", m_maxDistanceFromMainTrack));
845 
846  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
847  XmlHelper::ReadValue(xmlHandle, "MaxHitDistanceFromCluster", m_maxHitDistanceFromCluster));
848 
849  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
850  XmlHelper::ReadValue(xmlHandle, "MaxHitSeparationForConnectedCluster", m_maxHitSeparationForConnectedCluster));
851 
852  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxTrackGaps", m_maxTrackGaps));
853 
854  PANDORA_RETURN_RESULT_IF_AND_IF(
855  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "LineSegmentLength", m_lineSegmentLength));
856 
857  if (m_lineSegmentLength < std::numeric_limits<float>::epsilon())
858  {
859  std::cout << "TrackInEMShowerAlgorithm: Line segment length must be positive and nonzero" << std::endl;
860  throw STATUS_CODE_INVALID_PARAMETER;
861  }
862 
863  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "HitWidthMode", m_hitWidthMode));
864 
865  return STATUS_CODE_SUCCESS;
866 }
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.
float m_minClusterLength
The minimum length of a considered cluster.
unsigned int m_maxTrackGaps
The maximum number of graps allowed in the extrapolated hit vector.
float m_minHitFractionForHitRemoval
The threshold fraction of hits to be removed from the cluster for hit removal to proceed.
float m_maxHitDistanceFromCluster
The threshold separation between a hit and cluster for the hit to be merged into the cluster...
float m_maxHitSeparationForConnectedCluster
The maximum separation between two adjacent (in z) hits in a connected cluster.
float m_stableRegionClusterFraction
The threshold fraction of fit contributing layers which defines the stable region.
float m_lineSegmentLength
The length of a track gap.
float m_maxDistanceFromMainTrack
The threshold distance for a hit to be added to the main track.
unsigned int m_microSlidingFitWindow
The sliding fit window used in the fits contained within the microSlidingFitResultMap.
BEGIN_PROLOG could also be cout
float m_mergePointMinCosAngleDeviation
The threshold cos opening angle between the cluster local gradient and the associated cluster global ...
void lar_content::TrackRefinementBaseAlgorithm::RemoveClusterFromContainers ( const pandora::Cluster *const  pClustertoRemove,
pandora::ClusterVector &  clusterVector,
SlidingFitResultMapPair slidingFitResultMapPair 
) const
protected

Remove a cluster from the cluster vector and sliding fit maps.

Parameters
pClustertoRemovethe clusters to remove from the containers
clusterVectorthe vector to store clusters considered within the algorithm
slidingFitResultMapPairthe {micro, macro} pair of [cluster -> TwoDSlidingFitResult] maps

Definition at line 805 of file TrackRefinementBaseAlgorithm.cc.

807 {
808  const TwoDSlidingFitResultMap::const_iterator microFitToDelete(slidingFitResultMapPair.first->find(pClusterToRemove));
809  if (microFitToDelete != slidingFitResultMapPair.first->end())
810  slidingFitResultMapPair.first->erase(microFitToDelete);
811 
812  const TwoDSlidingFitResultMap::const_iterator macroFitToDelete(slidingFitResultMapPair.second->find(pClusterToRemove));
813  if (macroFitToDelete != slidingFitResultMapPair.second->end())
814  slidingFitResultMapPair.second->erase(macroFitToDelete);
815 
816  const ClusterVector::const_iterator clusterToDelete(std::find(clusterVector.begin(), clusterVector.end(), pClusterToRemove));
817  if (clusterToDelete != clusterVector.end())
818  clusterVector.erase(clusterToDelete);
819 }
const Cluster * lar_content::TrackRefinementBaseAlgorithm::RemoveOffAxisHitsFromTrack ( const pandora::Cluster *const  pCluster,
const pandora::CartesianVector &  splitPosition,
const bool  isEndUpstream,
const ClusterToCaloHitListMap clusterToCaloHitListMap,
pandora::ClusterList &  remnantClusterList,
TwoDSlidingFitResultMap microSlidingFitResultMap,
TwoDSlidingFitResultMap macroSlidingFitResultMap 
) const
protected

Remove any hits in the upstream/downstream cluster that lie off of the main track axis (i.e. clustering errors)

Parameters
pClusterthe input cluster
splitPositionthe position after which hits are considered for removal
isEndUpstreamwhether the upstream end is to be refined
clusterToCaloHitListMapthe map [parent cluster -> list of hits which belong to the main track]
remnantClusterListthe input list to store the remnant clusters
microSlidingFitResultMapthe mapping [cluster -> TwoDSlidingFitResult] where fits correspond to local gradients
macroSlidingFitResultMapthe mapping [cluster -> TwoDSlidingFitResult] where fits correspond to global cluster gradients
Returns
the address of the (possibly) modified cluster

Definition at line 496 of file TrackRefinementBaseAlgorithm.cc.

499 {
500  float rL(0.f), rT(0.f);
501  const TwoDSlidingFitResult &microFitResult(microSlidingFitResultMap.at(pCluster));
502  microFitResult.GetLocalPosition(splitPosition, rL, rT);
503 
504  const TwoDSlidingFitResult &macroFitResult(macroSlidingFitResultMap.at(pCluster));
505  CartesianVector averageDirection(0.f, 0.f, 0.f);
506  macroFitResult.GetGlobalDirection(macroFitResult.GetLayerFitResultMap().begin()->second.GetGradient(), averageDirection);
507 
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()));
511 
512  // Fragmentation initialisation
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));
517 
518  const Cluster *pMainTrackCluster(nullptr), *pAboveCluster(nullptr), *pBelowCluster(nullptr);
519 
520  const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
521  for (const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
522  {
523  for (const CaloHit *const pCaloHit : *mapEntry.second)
524  {
525  const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
526  float thisL(0.f), thisT(0.f);
527 
528  microFitResult.GetLocalPosition(pCaloHit->GetPositionVector(), thisL, thisT);
529 
530  bool isAnExtrapolatedHit(false);
531  const auto extrapolatedCaloHitIter(clusterToCaloHitListMap.find(pCluster));
532 
533  if (extrapolatedCaloHitIter != clusterToCaloHitListMap.end())
534  isAnExtrapolatedHit = std::find(extrapolatedCaloHitIter->second.begin(), extrapolatedCaloHitIter->second.end(), pCaloHit) !=
535  extrapolatedCaloHitIter->second.end();
536 
537  const bool isAbove(((clusterGradient * hitPosition.GetX()) + clusterIntercept) < (isVertical ? hitPosition.GetX() : hitPosition.GetZ()));
538  const bool isToRemove(!isAnExtrapolatedHit && (((thisL < rL) && isEndUpstream) || ((thisL > rL) && !isEndUpstream)));
539 
540  const Cluster *&pClusterToModify(isToRemove ? (isAbove ? pAboveCluster : pBelowCluster) : pMainTrackCluster);
541 
542  if (pClusterToModify)
543  {
544  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*this, pClusterToModify, pCaloHit));
545  }
546  else
547  {
549  parameters.m_caloHitList.push_back(pCaloHit);
550  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*this, parameters, pClusterToModify));
551 
552  if (pClusterToModify != pMainTrackCluster)
553  remnantClusterList.push_back(pClusterToModify);
554  }
555  }
556  }
557 
558  // End fragmentation
559  if (pAboveCluster || pBelowCluster)
560  {
561  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*this, fragmentListName, originalListName));
562  return pMainTrackCluster;
563  }
564  else
565  {
566  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*this, originalListName, fragmentListName));
567  return pCluster;
568  }
569 }
fhicl::Table< sbnd::crt::CRTDetSimParams > Parameters
void lar_content::TrackRefinementBaseAlgorithm::RepositionIfInGap ( const pandora::CartesianVector &  mergeDirection,
pandora::CartesianVector &  trackPoint 
) const
protected

Move an input position to the higher line gap edge if it lies within a gap.

Parameters
mergeDirectionthe direction of the track
trackPointthe input position

Definition at line 341 of file TrackRefinementBaseAlgorithm.cc.

342 {
343  const DetectorGapList detectorGapList(this->GetPandora().GetGeometry()->GetDetectorGapList());
344  for (const DetectorGap *const pDetectorGap : detectorGapList)
345  {
346  const LineGap *const pLineGap(dynamic_cast<const LineGap *>(pDetectorGap));
347 
348  if (pLineGap)
349  {
350  const LineGapType lineGapType(pLineGap->GetLineGapType());
351 
352  if (lineGapType == TPC_DRIFT_GAP)
353  {
354  if ((pLineGap->GetLineStartX() < trackPoint.GetX()) && (pLineGap->GetLineEndX() > trackPoint.GetX()))
355  {
356  if (std::fabs(mergeDirection.GetX()) < std::numeric_limits<float>::epsilon())
357  throw StatusCodeException(STATUS_CODE_FAILURE);
358 
359  const float gradient(mergeDirection.GetZ() / mergeDirection.GetX());
360 
361  trackPoint = CartesianVector(
362  pLineGap->GetLineEndX(), 0.f, trackPoint.GetZ() + (gradient * (pLineGap->GetLineEndX() - trackPoint.GetX())));
363  }
364  }
365 
366  if ((lineGapType == TPC_WIRE_GAP_VIEW_U) || (lineGapType == TPC_WIRE_GAP_VIEW_V) || (lineGapType == TPC_WIRE_GAP_VIEW_W))
367  {
368  if ((pLineGap->GetLineStartZ() < trackPoint.GetZ()) && (pLineGap->GetLineEndZ() > trackPoint.GetZ()))
369  {
370  if (std::fabs(mergeDirection.GetZ()) < std::numeric_limits<float>::epsilon())
371  throw StatusCodeException(STATUS_CODE_FAILURE);
372 
373  const float gradient(mergeDirection.GetX() / mergeDirection.GetZ());
374 
375  trackPoint = CartesianVector(
376  trackPoint.GetX() + (gradient * (pLineGap->GetLineEndZ() - trackPoint.GetZ())), 0.f, pLineGap->GetLineEndZ());
377  }
378  }
379  }
380  }
381 }
virtual pandora::StatusCode lar_content::TrackRefinementBaseAlgorithm::Run ( )
protectedpure virtual
template<typename T >
void lar_content::TrackRefinementBaseAlgorithm::UpdateContainers ( const pandora::ClusterList &  clustersToAdd,
const pandora::ClusterList &  clustersToDelete,
const T  sortFunction,
pandora::ClusterVector &  clusterVector,
SlidingFitResultMapPair slidingFitResultMapPair 
) const
protected

Remove deleted clusters from the cluster vector and sliding fit maps and add in created clusters that are determined to be track-like.

Parameters
clustersToAddthe list of clusters to add to the containers
clustersToDeletethe list of clusters to remove from the containers
sortFunctionthe sort class or function used to sort the clusterVector
clusterVectorthe vector to store clusters considered within the algorithm
slidingFitResultMapPairthe {micro, macro} pair of [cluster -> TwoDSlidingFitResult] maps
template<typename T >
void lar_content::TrackRefinementBaseAlgorithm::UpdateContainers ( const ClusterList &  clustersToAdd,
const ClusterList &  clustersToDelete,
const T  sortFunction,
ClusterVector &  clusterVector,
SlidingFitResultMapPair slidingFitResultMapPair 
) const

Definition at line 793 of file TrackRefinementBaseAlgorithm.cc.

795 {
796  //ATTN: Very important to first delete pointers from containers
797  for (const Cluster *const pClusterToDelete : clustersToDelete)
798  this->RemoveClusterFromContainers(pClusterToDelete, clusterVector, slidingFitResultMapPair);
799 
800  this->InitialiseContainers(&clustersToAdd, sortFunction, clusterVector, slidingFitResultMapPair);
801 }
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.

Member Data Documentation

bool lar_content::TrackRefinementBaseAlgorithm::m_hitWidthMode
protected

Whether to consider the width of hits.

Definition at line 318 of file TrackRefinementBaseAlgorithm.h.

float lar_content::TrackRefinementBaseAlgorithm::m_lineSegmentLength
protected

The length of a track gap.

Definition at line 317 of file TrackRefinementBaseAlgorithm.h.

unsigned int lar_content::TrackRefinementBaseAlgorithm::m_macroSlidingFitWindow
protected

The sliding fit window used in the fits contained within the macroSlidingFitResultMap.

Definition at line 309 of file TrackRefinementBaseAlgorithm.h.

float lar_content::TrackRefinementBaseAlgorithm::m_maxDistanceFromMainTrack
protected

The threshold distance for a hit to be added to the main track.

Definition at line 313 of file TrackRefinementBaseAlgorithm.h.

float lar_content::TrackRefinementBaseAlgorithm::m_maxHitDistanceFromCluster
protected

The threshold separation between a hit and cluster for the hit to be merged into the cluster.

Definition at line 314 of file TrackRefinementBaseAlgorithm.h.

float lar_content::TrackRefinementBaseAlgorithm::m_maxHitSeparationForConnectedCluster
protected

The maximum separation between two adjacent (in z) hits in a connected cluster.

Definition at line 315 of file TrackRefinementBaseAlgorithm.h.

unsigned int lar_content::TrackRefinementBaseAlgorithm::m_maxTrackGaps
protected

The maximum number of graps allowed in the extrapolated hit vector.

Definition at line 316 of file TrackRefinementBaseAlgorithm.h.

float lar_content::TrackRefinementBaseAlgorithm::m_mergePointMinCosAngleDeviation
protected

The threshold cos opening angle between the cluster local gradient and the associated cluster global gradient used to determine merge points.

Definition at line 311 of file TrackRefinementBaseAlgorithm.h.

unsigned int lar_content::TrackRefinementBaseAlgorithm::m_microSlidingFitWindow
protected

The sliding fit window used in the fits contained within the microSlidingFitResultMap.

Definition at line 308 of file TrackRefinementBaseAlgorithm.h.

float lar_content::TrackRefinementBaseAlgorithm::m_minClusterLength
protected

The minimum length of a considered cluster.

Definition at line 307 of file TrackRefinementBaseAlgorithm.h.

float lar_content::TrackRefinementBaseAlgorithm::m_minHitFractionForHitRemoval
protected

The threshold fraction of hits to be removed from the cluster for hit removal to proceed.

Definition at line 312 of file TrackRefinementBaseAlgorithm.h.

float lar_content::TrackRefinementBaseAlgorithm::m_stableRegionClusterFraction
protected

The threshold fraction of fit contributing layers which defines the stable region.

Definition at line 310 of file TrackRefinementBaseAlgorithm.h.


The documentation for this class was generated from the following files: