TrackRefinementBaseAlgorithm.h
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArTwoDReco/LArCosmicRay/TrackRefinementBaseAlgorithm.h
3  *
4  * @brief Header file for the track refinement base class.
5  *
6  * $Log: $
7  */
8 #ifndef LAR_TRACK_REFINEMENT_BASE_ALGORITHM_H
9 #define LAR_TRACK_REFINEMENT_BASE_ALGORITHM_H 1
10 
11 #include "Pandora/Algorithm.h"
12 
15 
16 namespace lar_content
17 {
18 /**
19  * @brief TrackRefinementBaseAlgorithm class
20  */
21 class TrackRefinementBaseAlgorithm : public pandora::Algorithm
22 {
23 public:
24  /**
25  * @brief Default constructor
26  */
28 
29 protected:
30  typedef std::pair<TwoDSlidingFitResultMap *, TwoDSlidingFitResultMap *> SlidingFitResultMapPair;
31  typedef std::unordered_map<const pandora::Cluster *, pandora::CaloHitList> ClusterToCaloHitListMap;
32 
33  /**
34  * @brief SortByDistanceAlongLine class
35  */
37  {
38  public:
39  /**
40  * @brief Constructor
41  *
42  * @param startPoint the line start point
43  * @param lineDirection the line direction unit vector
44  * @param hitWidthMode whether to consider hit widths or not
45  */
46  SortByDistanceAlongLine(const pandora::CartesianVector &startPoint, const pandora::CartesianVector &lineDirection, const bool hitWidthMode);
47 
48  /**
49  * @brief Sort hits by their projected distance along a line from a start point
50  *
51  * @param pLhs the address of the first hit
52  * @param pRhs the address of the second hit
53  *
54  * @return whether lhs hit has a smaller projected distance along the line than rhs hit
55  */
56  bool operator()(const pandora::CaloHit *const pLhs, const pandora::CaloHit *const pRhs) const;
57 
58  private:
59  pandora::CartesianVector m_startPoint; ///< The line start point
60  pandora::CartesianVector m_lineDirection; ///< The line end point
61  bool m_hitWidthMode; ///< Wether to consider hit widths or not
62  };
63 
64  virtual pandora::StatusCode Run() = 0;
65  virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle) = 0;
66 
67  /**
68  * @brief Fill the cluster vector and sliding fit maps with clusters that are determined to be track-like
69  *
70  * @param pClusterList the list of input clusters
71  * @param sortFunction the sort class or function used to sort the clusterVector
72  * @param clusterVector the input vector to store clusters considered within the algorithm
73  * @param slidingFitResultMapPair the {micro, macro} pair of [cluster -> TwoDSlidingFitResult] maps
74  */
75  template <typename T>
76  void InitialiseContainers(const pandora::ClusterList *pClusterList, const T sortFunction, pandora::ClusterVector &clusterVector,
77  SlidingFitResultMapPair &slidingFitResultMapPair) const;
78 
79  /**
80  * @brief Get the merging coordinate and direction for an input cluster with respect to an associated cluster
81  *
82  * @param clusterMicroFitResult the local TwoDSlidingFitResult of the cluster
83  * @param clusterMacroFitResult the global TwoDSlidingFitResult of the cluster
84  * @param associatedMacroFitReult the global TwoDSlidingFitResult of the associated cluster
85  * @param isEndUpstream whether the sought cluster merge point is the upstream
86  * @param clusterMergePosition the merge position of the cluster
87  * @param clusterMergeDirection the merge direction of the cluster
88  *
89  * @return whether it was possible to find a suitable merge position
90  */
91  bool GetClusterMergingCoordinates(const TwoDSlidingFitResult &clusterMicroFitResult, const TwoDSlidingFitResult &clusterMacroFitResult,
92  const TwoDSlidingFitResult &associatedMacroFitResult, const bool isEndUpstream, pandora::CartesianVector &clusterMergePosition,
93  pandora::CartesianVector &clusterMergeDirection) const;
94 
95  /**
96  * @brief 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
97  *
98  * @param firstCorner the position of one corner
99  * @param secondCorner the position of the opposite corner
100  * @param pClusterList the list of all clusters
101  * @param clusterToCaloHitListMap the output map [parent cluster -> list of hits which belong to the main track]
102  * @param unavailableProtectedClusters the list of clusters whose hits are protected
103  * @param distanceToLine the maximum perpendicular distance of a collected hit from the connecting line
104  */
105  void GetHitsInBoundingBox(const pandora::CartesianVector &firstCorner, const pandora::CartesianVector &secondCorner,
106  const pandora::ClusterList *const pClusterList, ClusterToCaloHitListMap &clusterToCaloHitListMap,
107  const pandora::ClusterList &unavailableProtectedClusters = pandora::ClusterList(), const float distanceToLine = -1.f) const;
108 
109  /**
110  * @brief check whether a hit is contained within a defined square region
111  *
112  * @param minX the minimum x coordinate of the square region
113  * @param maxX the maximum x coordinate of the square region
114  * @param minZ the minimum z coordinate of the square region
115  * @param maxZ the maximum z coordinate of the square region
116  * @param hitPosition the position of the hit
117  *
118  * @return whether the hit is contained within the square region
119  */
120  bool IsInBoundingBox(const float minX, const float maxX, const float minZ, const float maxZ, const pandora::CartesianVector &hitPosition) const;
121 
122  /**
123  * @brief Check whether a hit is close to a line
124  *
125  * @param hitPosition the position of the hit
126  * @param lineStart the start point of the line (can actually be any point on the line)
127  * @param lineDirection the unit vector of the line direction
128  * @param distanceToLine the definition of 'close'
129  *
130  * @return whether the hit is close to the line
131  */
132  bool IsCloseToLine(const pandora::CartesianVector &hitPosition, const pandora::CartesianVector &lineStart,
133  const pandora::CartesianVector &lineDirection, const float distanceToLine) const;
134 
135  /**
136  * @brief Perform topological checks on the collected hits to ensure no gaps are present
137  *
138  * @param clusterToCaloHitListMap the input map [parent cluster -> list of hits which belong to the main track]
139  * @param clusterAssociation the clusterAssociation
140  *
141  * @return whether the checks pass
142  */
143  bool AreExtrapolatedHitsGood(const ClusterToCaloHitListMap &clusterToCaloHitListMap, ClusterAssociation &clusterAssociation) const;
144 
145  /**
146  * @brief Check the separation of the extremal extrapolated hits with the expected endpoints or, in the case of no hits, the clusterMergePoint themselves
147  *
148  * @param extrapolatedHitVector the extrapolated hit vector (ordered closest hit to the upstream merge point -> furthest hit)
149  * @param clusterAssociation the clusterAssociation
150  *
151  * @return whether the check passes
152  */
153  virtual bool AreExtrapolatedHitsNearBoundaries(const pandora::CaloHitVector &extrapolatedHitVector, ClusterAssociation &clusterAssociation) const = 0;
154 
155  /**
156  * @brief Check whether a hit is close to a boundary point
157  *
158  * @param pCaloHit the input calo hit
159  * @param boundaryPosition2D the position of the 2D boundary point
160  * @param boundaryTolerance the definition of close
161  *
162  * @return whether the check passes
163  */
164  bool IsNearBoundary(const pandora::CaloHit *const pCaloHit, const pandora::CartesianVector &boundaryPosition2D, const float boundaryTolerance) const;
165 
166  /**
167  * @brief Check whether the extrapolatedCaloHitVector contains a continuous line of hits between the cluster merge points
168  *
169  * @param clusterAssociation the clusterAssociation
170  * @param extrapolatedCaloHitVector the vector of extrapolated calo hits
171  *
172  * @return whether the calo hits are continuous
173  */
174  bool IsTrackContinuous(const ClusterAssociation &clusterAssociation, const pandora::CaloHitVector &extrapolatedCaloHitVector) const;
175 
176  /**
177  * @brief Obtain the segment boundaries of the connecting line to test whether extrapolated hits are continuous
178  *
179  * @param clusterAssociation the clusterAssociation
180  * @param trackSegmentBoundaries the output vector of segment boundaries
181  */
182  void GetTrackSegmentBoundaries(const ClusterAssociation &clusterAssociation, pandora::CartesianPointVector &trackSegmentBoundaries) const;
183 
184  /**
185  * @brief Move an input position to the higher line gap edge if it lies within a gap
186  *
187  * @param mergeDirection the direction of the track
188  * @param trackPoint the input position
189  */
190  void RepositionIfInGap(const pandora::CartesianVector &mergeDirection, pandora::CartesianVector &trackPoint) const;
191 
192  /**
193  * @brief Calculate the track length between two points that lies in gaps
194  *
195  * @param upstreamPoint the upstream point
196  * @param downstreamPoint the downstream point
197  * @param connectingLine the track direction
198  * @param consideredGaps the list of gaps to ignore
199  */
200  float DistanceInGap(const pandora::CartesianVector &upstreamPoint, const pandora::CartesianVector &downstreamPoint,
201  const pandora::CartesianVector &connectingLine, pandora::DetectorGapList &consideredGaps) const;
202 
203  /**
204  * @brief Whether a position falls within a specified segment of the cluster connecting line
205  *
206  * @param lowerBoundary the lower boundary of the segment
207  * @param upperBoundary the upper boundary of the segment
208  * @param point the position
209  *
210  * @return whether the position falls within segment
211  */
212  bool IsInLineSegment(const pandora::CartesianVector &lowerBoundary, const pandora::CartesianVector &upperBoundary,
213  const pandora::CartesianVector &point) const;
214 
215  /**
216  * @brief Remove any hits in the upstream/downstream cluster that lie off of the main track axis (i.e. clustering errors)
217  *
218  * @param pCluster the input cluster
219  * @param splitPosition the position after which hits are considered for removal
220  * @param isEndUpstream whether the upstream end is to be refined
221  * @param clusterToCaloHitListMap the map [parent cluster -> list of hits which belong to the main track]
222  * @param remnantClusterList the input list to store the remnant clusters
223  * @param microSlidingFitResultMap the mapping [cluster -> TwoDSlidingFitResult] where fits correspond to local gradients
224  * @param macroSlidingFitResultMap the mapping [cluster -> TwoDSlidingFitResult] where fits correspond to global cluster gradients
225  *
226  * @return the address of the (possibly) modified cluster
227  */
228  const pandora::Cluster *RemoveOffAxisHitsFromTrack(const pandora::Cluster *const pCluster, const pandora::CartesianVector &splitPosition,
229  const bool isEndUpstream, const ClusterToCaloHitListMap &clusterToCaloHitListMap, pandora::ClusterList &remnantClusterList,
230  TwoDSlidingFitResultMap &microSlidingFitResultMap, TwoDSlidingFitResultMap &macroSlidingFitResultMap) const;
231 
232  /**
233  * @brief Remove the hits from a shower cluster that belong to the main track and add them into the main track cluster
234  *
235  * @param pMainTrackCluster the main track cluster
236  * @param pShowerCluster the input shower cluster
237  * @param caloHitsToMerge the list of calo hits to remove from the shower cluster
238  * @param clusterAssociation the clusterAssociation
239  * @param remnantClusterList the input list to store the remnant clusters
240  */
241  void AddHitsToMainTrack(const pandora::Cluster *const pMainTrackCluster, const pandora::Cluster *const pShowerTrackCluster,
242  const pandora::CaloHitList &caloHitsToMerge, const ClusterAssociation &clusterAssociation, pandora::ClusterList &remnantClusterList) const;
243 
244  /**
245  * @brief Process the remnant clusters separating those that stradle the main track
246  *
247  * @param remnantClusterList the list of remnant clusters to process
248  * @param pMainTrackCluster the main track cluster
249  * @param pClusterList the list of all clusters
250  * @param createdClusters the input list to store the final remnant clusters
251  */
252  void ProcessRemnantClusters(const pandora::ClusterList &remnantClusterList, const pandora::Cluster *const pMainTrackCluster,
253  const pandora::ClusterList *const pClusterList, pandora::ClusterList &createdClusters) const;
254 
255  /**
256  * @brief Add a cluster to the nearest cluster satisfying separation distance thresholds
257  *
258  * @param pClusterToMerge the cluster to merge
259  * @param pMainTrackCluster the main track cluster
260  * @param pClusterList the list of all clusters
261  *
262  * @return whether cluster was added to a nearby cluster
263  */
264  bool AddToNearestCluster(const pandora::Cluster *const pClusterToMerge, const pandora::Cluster *const pMainTrackCluster,
265  const pandora::ClusterList *const pClusterList) const;
266 
267  /**
268  * @brief Whether a remnant cluster is considered to be disconnected and therefore should undergo further fragmentation
269  *
270  * @param pRemnantCluster the input remnant cluster
271  *
272  * @return whether the remnant cluster is disconnected
273  */
274  bool IsClusterRemnantDisconnected(const pandora::Cluster *const pRemnantCluster) const;
275 
276  /**
277  * @brief Fragment a cluster using simple hit separation logic
278  *
279  * @param pRemnantCluster the input remnant cluster to fragment
280  * @param fragmentedClusterList the input list to store the final remnant clusters
281  */
282  void FragmentRemnantCluster(const pandora::Cluster *const pRemnantCluster, pandora::ClusterList &fragmentedClusterList) const;
283 
284  /**
285  * @brief Remove deleted clusters from the cluster vector and sliding fit maps and add in created clusters that are determined to be track-like
286  *
287  * @param clustersToAdd the list of clusters to add to the containers
288  * @param clustersToDelete the list of clusters to remove from the containers
289  * @param sortFunction the sort class or function used to sort the clusterVector
290  * @param clusterVector the vector to store clusters considered within the algorithm
291  * @param slidingFitResultMapPair the {micro, macro} pair of [cluster -> TwoDSlidingFitResult] maps
292  */
293  template <typename T>
294  void UpdateContainers(const pandora::ClusterList &clustersToAdd, const pandora::ClusterList &clustersToDelete, const T sortFunction,
295  pandora::ClusterVector &clusterVector, SlidingFitResultMapPair &slidingFitResultMapPair) const;
296 
297  /**
298  * @brief Remove a cluster from the cluster vector and sliding fit maps
299  *
300  * @param pClustertoRemove the clusters to remove from the containers
301  * @param clusterVector the vector to store clusters considered within the algorithm
302  * @param slidingFitResultMapPair the {micro, macro} pair of [cluster -> TwoDSlidingFitResult] maps
303  */
304  void RemoveClusterFromContainers(const pandora::Cluster *const pClustertoRemove, pandora::ClusterVector &clusterVector,
305  SlidingFitResultMapPair &slidingFitResultMapPair) const;
306 
307  float m_minClusterLength; ///< The minimum length of a considered cluster
308  unsigned int m_microSlidingFitWindow; ///< The sliding fit window used in the fits contained within the microSlidingFitResultMap
309  unsigned int m_macroSlidingFitWindow; ///< The sliding fit window used in the fits contained within the macroSlidingFitResultMap
310  float m_stableRegionClusterFraction; ///< The threshold fraction of fit contributing layers which defines the stable region
311  float m_mergePointMinCosAngleDeviation; ///< The threshold cos opening angle between the cluster local gradient and the associated cluster global gradient used to determine merge points
312  float m_minHitFractionForHitRemoval; ///< The threshold fraction of hits to be removed from the cluster for hit removal to proceed
313  float m_maxDistanceFromMainTrack; ///< The threshold distance for a hit to be added to the main track
314  float m_maxHitDistanceFromCluster; ///< The threshold separation between a hit and cluster for the hit to be merged into the cluster
315  float m_maxHitSeparationForConnectedCluster; ///< The maximum separation between two adjacent (in z) hits in a connected cluster
316  unsigned int m_maxTrackGaps; ///< The maximum number of graps allowed in the extrapolated hit vector
317  float m_lineSegmentLength; ///< The length of a track gap
318  bool m_hitWidthMode; ///< Whether to consider the width of hits
319 };
320 
321 //------------------------------------------------------------------------------------------------------------------------------------------
322 
324  const pandora::CartesianVector &startPoint, const pandora::CartesianVector &lineDirection, const bool hitWidthMode) :
325  m_startPoint(startPoint),
326  m_lineDirection(lineDirection.GetUnitVector()),
327  m_hitWidthMode(hitWidthMode)
328 {
329 }
330 
331 } // namespace lar_content
332 
333 #endif // #ifndef TRACK_REFINEMENT_BASE_ALGORITHM_H
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.
ClusterAssociation 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.
std::unordered_map< const pandora::Cluster *, pandora::CaloHitList > ClusterToCaloHitListMap
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.
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.
bool IsClusterRemnantDisconnected(const pandora::Cluster *const pRemnantCluster) const
Whether a remnant cluster is considered to be disconnected and therefore should undergo further fragm...
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.
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.
Header file for the lar two dimensional sliding fit result class.
Header file for the lar cluster association class.
float m_stableRegionClusterFraction
The threshold fraction of fit contributing layers which defines the stable region.
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.
std::unordered_map< const pandora::Cluster *, TwoDSlidingFitResult > TwoDSlidingFitResultMap
virtual pandora::StatusCode Run()=0
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.
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
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 &microSlidingFitResultMap, TwoDSlidingFitResultMap &macroSlidingFitResultMap) 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...
SortByDistanceAlongLine(const pandora::CartesianVector &startPoint, const pandora::CartesianVector &lineDirection, const bool hitWidthMode)
Constructor.
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 ...
virtual bool AreExtrapolatedHitsNearBoundaries(const pandora::CaloHitVector &extrapolatedHitVector, ClusterAssociation &clusterAssociation) const =0
Check the separation of the extremal extrapolated hits with the expected endpoints or...