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

CrossedTrackSplittingAlgorithm class. More...

#include <CrossedTrackSplittingAlgorithm.h>

Inheritance diagram for lar_content::CrossedTrackSplittingAlgorithm:
lar_content::TwoDSlidingFitSplittingAndSwitchingAlgorithm

Public Member Functions

 CrossedTrackSplittingAlgorithm ()
 Default constructor. More...
 
- Public Member Functions inherited from lar_content::TwoDSlidingFitSplittingAndSwitchingAlgorithm
 TwoDSlidingFitSplittingAndSwitchingAlgorithm ()
 Default constructor. More...
 

Private Types

typedef KDTreeLinkerAlgo
< const pandora::CaloHit *, 2 > 
HitKDTree2D
 
typedef KDTreeNodeInfoT< const
pandora::CaloHit *, 2 > 
HitKDNode2D
 
typedef std::vector< HitKDNode2DHitKDNode2DList
 
typedef std::unordered_map
< const pandora::Cluster
*, pandora::ClusterSet > 
ClusterToClustersMap
 
typedef std::unordered_map
< const pandora::CaloHit
*, const pandora::Cluster * > 
HitToClusterMap
 

Private Member Functions

pandora::StatusCode ReadSettings (const pandora::TiXmlHandle xmlHandle)
 
pandora::StatusCode PreparationStep (const pandora::ClusterVector &clusterVector)
 Perform any preparatory actions, such as caching information for subsequent expensive calculations. More...
 
pandora::StatusCode TidyUpStep ()
 Tidy up any information cached in e.g. the preparation step. More...
 
pandora::StatusCode FindBestSplitPosition (const TwoDSlidingFitResult &slidingFit1, const TwoDSlidingFitResult &slidingFit2, pandora::CartesianVector &splitPosition, pandora::CartesianVector &direction1, pandora::CartesianVector &direction2) const
 Find the best split position and direction for a pair of clusters. More...
 
void FindCandidateSplitPositions (const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, pandora::CartesianPointVector &candidateVector) const
 Find average positions of pairs of hits within a maximum separation. More...
 

Private Attributes

float m_maxClusterSeparation
 maximum separation of two clusters More...
 
float m_maxClusterSeparationSquared
 maximum separation of two clusters (squared) More...
 
float m_minCosRelativeAngle
 maximum relative angle between tracks after un-crossing More...
 
float m_searchRegion1D
 Search region, applied to each dimension, for look-up from kd-trees. More...
 
ClusterToClustersMap m_nearbyClusters
 The nearby clusters map. More...
 

Additional Inherited Members

- Protected Member Functions inherited from lar_content::TwoDSlidingFitSplittingAndSwitchingAlgorithm
virtual pandora::StatusCode Run ()
 

Detailed Description

CrossedTrackSplittingAlgorithm class.

Definition at line 28 of file CrossedTrackSplittingAlgorithm.h.

Member Typedef Documentation

typedef std::unordered_map<const pandora::Cluster *, pandora::ClusterSet> lar_content::CrossedTrackSplittingAlgorithm::ClusterToClustersMap
private

Definition at line 41 of file CrossedTrackSplittingAlgorithm.h.

typedef KDTreeNodeInfoT<const pandora::CaloHit *, 2> lar_content::CrossedTrackSplittingAlgorithm::HitKDNode2D
private

Definition at line 38 of file CrossedTrackSplittingAlgorithm.h.

Definition at line 39 of file CrossedTrackSplittingAlgorithm.h.

typedef KDTreeLinkerAlgo<const pandora::CaloHit *, 2> lar_content::CrossedTrackSplittingAlgorithm::HitKDTree2D
private

Definition at line 37 of file CrossedTrackSplittingAlgorithm.h.

typedef std::unordered_map<const pandora::CaloHit *, const pandora::Cluster *> lar_content::CrossedTrackSplittingAlgorithm::HitToClusterMap
private

Definition at line 42 of file CrossedTrackSplittingAlgorithm.h.

Constructor & Destructor Documentation

lar_content::CrossedTrackSplittingAlgorithm::CrossedTrackSplittingAlgorithm ( )

Default constructor.

Definition at line 23 of file CrossedTrackSplittingAlgorithm.cc.

23  :
26  m_minCosRelativeAngle(0.966f),
27  m_searchRegion1D(2.f)
28 {
29 }
float m_minCosRelativeAngle
maximum relative angle between tracks after un-crossing
float m_maxClusterSeparationSquared
maximum separation of two clusters (squared)
float m_maxClusterSeparation
maximum separation of two clusters
float m_searchRegion1D
Search region, applied to each dimension, for look-up from kd-trees.

Member Function Documentation

StatusCode lar_content::CrossedTrackSplittingAlgorithm::FindBestSplitPosition ( const TwoDSlidingFitResult slidingFit1,
const TwoDSlidingFitResult slidingFit2,
pandora::CartesianVector &  splitPosition,
pandora::CartesianVector &  direction1,
pandora::CartesianVector &  direction2 
) const
privatevirtual

Find the best split position and direction for a pair of clusters.

Parameters
slidingFit1the sliding linear fit to the first cluster
slidingFit2the sliding linear fit to the second cluster
splitPositionthe output split position
direction1the output direction of the first new cluster
direction2the output direction of the second new cluster

Implements lar_content::TwoDSlidingFitSplittingAndSwitchingAlgorithm.

Definition at line 86 of file CrossedTrackSplittingAlgorithm.cc.

88 {
89  // Use cached results from kd-tree to avoid expensive calculations
90  if (!m_nearbyClusters.count(slidingFitResult1.GetCluster()) || !m_nearbyClusters.count(slidingFitResult2.GetCluster()) ||
91  !m_nearbyClusters.at(slidingFitResult1.GetCluster()).count(slidingFitResult2.GetCluster()) ||
92  !m_nearbyClusters.at(slidingFitResult2.GetCluster()).count(slidingFitResult1.GetCluster()))
93  {
94  return STATUS_CODE_NOT_FOUND;
95  }
96 
97  // Identify crossed-track topology and find candidate intersection positions
98  const CartesianVector &minPosition1(slidingFitResult1.GetGlobalMinLayerPosition());
99  const CartesianVector &maxPosition1(slidingFitResult1.GetGlobalMaxLayerPosition());
100 
101  const CartesianVector &minPosition2(slidingFitResult2.GetGlobalMinLayerPosition());
102  const CartesianVector &maxPosition2(slidingFitResult2.GetGlobalMaxLayerPosition());
103 
104  if (LArClusterHelper::GetClosestDistance(minPosition1, slidingFitResult2.GetCluster()) < 2.f * m_maxClusterSeparation ||
105  LArClusterHelper::GetClosestDistance(maxPosition1, slidingFitResult2.GetCluster()) < 2.f * m_maxClusterSeparation ||
106  LArClusterHelper::GetClosestDistance(minPosition2, slidingFitResult1.GetCluster()) < 2.f * m_maxClusterSeparation ||
107  LArClusterHelper::GetClosestDistance(maxPosition2, slidingFitResult1.GetCluster()) < 2.f * m_maxClusterSeparation)
108  {
109  return STATUS_CODE_NOT_FOUND;
110  }
111 
112  if (LArClusterHelper::GetClosestDistance(slidingFitResult1.GetCluster(), slidingFitResult2.GetCluster()) > m_maxClusterSeparation)
113  return STATUS_CODE_NOT_FOUND;
114 
115  CartesianPointVector candidateVector;
116  this->FindCandidateSplitPositions(slidingFitResult1.GetCluster(), slidingFitResult2.GetCluster(), candidateVector);
117 
118  if (candidateVector.empty())
119  return STATUS_CODE_NOT_FOUND;
120 
121  // Loop over candidate positions and find best split position
122  bool foundSplit(false);
123  float closestSeparationSquared(std::numeric_limits<float>::max());
124 
125  const float halfWindowLength1(slidingFitResult1.GetLayerFitHalfWindowLength());
126  const float halfWindowLength2(slidingFitResult2.GetLayerFitHalfWindowLength());
127 
128  for (CartesianPointVector::const_iterator iter = candidateVector.begin(), iterEnd = candidateVector.end(); iter != iterEnd; ++iter)
129  {
130  const CartesianVector &candidatePosition(*iter);
131 
132  // Projections onto first cluster
133  float rL1(0.f), rT1(0.f);
134  CartesianVector R1(0.f, 0.f, 0.f);
135  CartesianVector F1(0.f, 0.f, 0.f);
136  CartesianVector B1(0.f, 0.f, 0.f);
137 
138  if (STATUS_CODE_SUCCESS != slidingFitResult1.GetGlobalFitProjection(candidatePosition, R1))
139  continue;
140 
141  slidingFitResult1.GetLocalPosition(R1, rL1, rT1);
142  if ((STATUS_CODE_SUCCESS != slidingFitResult1.GetGlobalFitPosition(rL1 + halfWindowLength1, F1)) ||
143  (STATUS_CODE_SUCCESS != slidingFitResult1.GetGlobalFitPosition(rL1 - halfWindowLength1, B1)))
144  {
145  continue;
146  }
147 
148  // Projections onto second cluster
149  float rL2(0.f), rT2(0.f);
150  CartesianVector R2(0.f, 0.f, 0.f);
151  CartesianVector F2(0.f, 0.f, 0.f);
152  CartesianVector B2(0.f, 0.f, 0.f);
153 
154  if (STATUS_CODE_SUCCESS != slidingFitResult2.GetGlobalFitProjection(candidatePosition, R2))
155  continue;
156 
157  slidingFitResult2.GetLocalPosition(R2, rL2, rT2);
158  if ((STATUS_CODE_SUCCESS != slidingFitResult2.GetGlobalFitPosition(rL2 + halfWindowLength2, F2)) ||
159  (STATUS_CODE_SUCCESS != slidingFitResult2.GetGlobalFitPosition(rL2 - halfWindowLength2, B2)))
160  {
161  continue;
162  }
163 
164  // Calculate average position
165  const CartesianVector C0((R1 + R2) * 0.5);
166 
167  // Calculate intersected position:
168  // ==============================
169  // First cluster gives set of points: B1->R1->F1
170  // Second cluster gives set of points: B2->R2->F2
171  //
172  // Try swapping B1 with B2 to see if this gives intersecting straight lines:
173  //
174  // F1 F2 a2 b1
175  // | | | |
176  // | | | |
177  // R1 R2 R1 R2
178  // | | | |
179  // | | | |
180  // B1 B2 a1 b2
181 
182  // First straight line is a1->R1->b1
183  // Second straight line is a2->R2->b2
184 
185  const CartesianVector a1(B1);
186  const CartesianVector a2(F1);
187 
188  for (unsigned int iForward = 0; iForward < 2; ++iForward)
189  {
190  const CartesianVector b1((0 == iForward) ? F2 : B2);
191  const CartesianVector b2((0 == iForward) ? B2 : F2);
192 
193  const CartesianVector s1((b1 - R2).GetUnitVector());
194  const CartesianVector t1((R1 - a1).GetUnitVector());
195  const CartesianVector s2((b2 - R2).GetUnitVector());
196  const CartesianVector t2((R1 - a2).GetUnitVector());
197 
198  if (s1.GetDotProduct(t1) < std::max(m_minCosRelativeAngle, -s1.GetDotProduct(s2)) ||
199  s2.GetDotProduct(t2) < std::max(m_minCosRelativeAngle, -t1.GetDotProduct(t2)))
200  continue;
201 
202  const CartesianVector p1((b1 - a1).GetUnitVector());
203  const CartesianVector p2((b2 - a2).GetUnitVector());
204 
205  float mu1(0.f), mu2(0.f);
206  CartesianVector C1(0.f, 0.f, 0.f);
207 
208  try
209  {
210  LArPointingClusterHelper::GetIntersection(a1, p1, a2, p2, C1, mu1, mu2);
211  }
212  catch (const StatusCodeException &)
213  {
214  continue;
215  }
216 
217  if (mu1 < 0.f || mu2 < 0.f || mu1 > (b1 - a1).GetMagnitude() || mu2 > (b2 - a2).GetMagnitude())
218  continue;
219 
220  const float thisSeparationSquared((C0 - C1).GetMagnitudeSquared());
221 
222  if (thisSeparationSquared < closestSeparationSquared)
223  {
224  closestSeparationSquared = thisSeparationSquared;
225  splitPosition = (C0 + C1) * 0.5;
226  firstDirection = t2 * -1.f;
227  secondDirection = t1;
228  foundSplit = true;
229  }
230  }
231  }
232 
233  if (!foundSplit)
234  return STATUS_CODE_NOT_FOUND;
235 
236  return STATUS_CODE_SUCCESS;
237 }
static void GetIntersection(const LArPointingCluster::Vertex &firstVertex, const LArPointingCluster::Vertex &secondVertex, pandora::CartesianVector &intersectPosition, float &firstDisplacement, float &secondDisplacement)
Get intersection of two vertices.
float m_minCosRelativeAngle
maximum relative angle between tracks after un-crossing
constexpr MyFlag_t F2
Definition: FlagSet_test.cc:41
#define a2
void FindCandidateSplitPositions(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, pandora::CartesianPointVector &candidateVector) const
Find average positions of pairs of hits within a maximum separation.
constexpr MyFlag_t F1
Definition: FlagSet_test.cc:40
float m_maxClusterSeparation
maximum separation of two clusters
ClusterToClustersMap m_nearbyClusters
The nearby clusters map.
std::size_t count(Cont const &cont)
physics associatedGroupsWithLeft p1
#define a1
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.
void lar_content::CrossedTrackSplittingAlgorithm::FindCandidateSplitPositions ( const pandora::Cluster *const  pCluster1,
const pandora::Cluster *const  pCluster2,
pandora::CartesianPointVector &  candidateVector 
) const
private

Find average positions of pairs of hits within a maximum separation.

Parameters
pCluster1the first cluster
pCluster2the second cluster
candidateVectorto receive the average positions

Definition at line 241 of file CrossedTrackSplittingAlgorithm.cc.

243 {
244  // ATTN The following is double-double counting
245  CaloHitList caloHitList1, caloHitList2;
246  pCluster1->GetOrderedCaloHitList().FillCaloHitList(caloHitList1);
247  pCluster2->GetOrderedCaloHitList().FillCaloHitList(caloHitList2);
248 
249  CaloHitVector caloHitVector1(caloHitList1.begin(), caloHitList1.end()), caloHitVector2(caloHitList2.begin(), caloHitList2.end());
250  std::sort(caloHitVector1.begin(), caloHitVector1.end(), LArClusterHelper::SortHitsByPosition);
251  std::sort(caloHitVector2.begin(), caloHitVector2.end(), LArClusterHelper::SortHitsByPosition);
252 
253  for (const CaloHit *const pCaloHit : caloHitVector1)
254  {
255  const CartesianVector position1(pCaloHit->GetPositionVector());
256  const CartesianVector position2(LArClusterHelper::GetClosestPosition(position1, pCluster2));
257 
258  if ((position1 - position2).GetMagnitudeSquared() < m_maxClusterSeparationSquared)
259  candidateVector.push_back((position1 + position2) * 0.5);
260  }
261 
262  for (const CaloHit *const pCaloHit : caloHitVector2)
263  {
264  const CartesianVector position2(pCaloHit->GetPositionVector());
265  const CartesianVector position1(LArClusterHelper::GetClosestPosition(position2, pCluster1));
266 
267  if ((position2 - position1).GetMagnitudeSquared() < m_maxClusterSeparationSquared)
268  candidateVector.push_back((position2 + position1) * 0.5);
269  }
270 }
float m_maxClusterSeparationSquared
maximum separation of two clusters (squared)
static bool SortHitsByPosition(const pandora::CaloHit *const pLhs, const pandora::CaloHit *const pRhs)
Sort calo hits by their position (use Z, followed by X, followed by Y)
static pandora::CartesianVector GetClosestPosition(const pandora::CartesianVector &position, const pandora::ClusterList &clusterList)
Get closest position in a list of clusters to a specified input position vector.
StatusCode lar_content::CrossedTrackSplittingAlgorithm::PreparationStep ( const pandora::ClusterVector &  clusterVector)
privatevirtual

Perform any preparatory actions, such as caching information for subsequent expensive calculations.

Parameters
clusterVectorthe cluster vector

Reimplemented from lar_content::TwoDSlidingFitSplittingAndSwitchingAlgorithm.

Definition at line 33 of file CrossedTrackSplittingAlgorithm.cc.

34 {
35  // ATTN Don't need to update nearby cluster map after cluster merges because algorithm does not revisit processed clusters
36  HitToClusterMap hitToClusterMap;
37  CaloHitList allCaloHits;
38 
39  for (const Cluster *const pCluster : clusterVector)
40  {
41  CaloHitList daughterHits;
42  pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
43  allCaloHits.insert(allCaloHits.end(), daughterHits.begin(), daughterHits.end());
44 
45  for (const CaloHit *const pCaloHit : daughterHits)
46  (void)hitToClusterMap.insert(HitToClusterMap::value_type(pCaloHit, pCluster));
47  }
48 
49  HitKDTree2D kdTree;
50  HitKDNode2DList hitKDNode2DList;
51 
52  KDTreeBox hitsBoundingRegion2D(fill_and_bound_2d_kd_tree(allCaloHits, hitKDNode2DList));
53  kdTree.build(hitKDNode2DList, hitsBoundingRegion2D);
54 
55  for (const Cluster *const pCluster : clusterVector)
56  {
57  CaloHitList daughterHits;
58  pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
59 
60  for (const CaloHit *const pCaloHit : daughterHits)
61  {
63 
64  HitKDNode2DList found;
65  kdTree.search(searchRegionHits, found);
66 
67  for (const auto &hit : found)
68  (void)m_nearbyClusters[pCluster].insert(hitToClusterMap.at(hit.data));
69  }
70  }
71 
72  return STATUS_CODE_SUCCESS;
73 }
process_name hit
Definition: cheaterreco.fcl:51
std::unordered_map< const pandora::CaloHit *, const pandora::Cluster * > HitToClusterMap
KDTreeLinkerAlgo< const pandora::CaloHit *, 2 > HitKDTree2D
j template void())
Definition: json.hpp:3108
KDTreeBox fill_and_bound_2d_kd_tree(const MANAGED_CONTAINER< const T * > &points, std::vector< KDTreeNodeInfoT< const T *, 2 >> &nodes)
fill_and_bound_2d_kd_tree
ClusterToClustersMap m_nearbyClusters
The nearby clusters map.
KDTreeBox build_2d_kd_search_region(const pandora::CaloHit *const point, const float x_span, const float z_span)
build_2d_kd_search_region
float m_searchRegion1D
Search region, applied to each dimension, for look-up from kd-trees.
KDTreeBoxT< 2 > KDTreeBox
StatusCode lar_content::CrossedTrackSplittingAlgorithm::ReadSettings ( const pandora::TiXmlHandle  xmlHandle)
privatevirtual

Reimplemented from lar_content::TwoDSlidingFitSplittingAndSwitchingAlgorithm.

Definition at line 274 of file CrossedTrackSplittingAlgorithm.cc.

275 {
276  PANDORA_RETURN_RESULT_IF_AND_IF(
277  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxClusterSeparation", m_maxClusterSeparation));
279 
280  PANDORA_RETURN_RESULT_IF_AND_IF(
281  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinCosRelativeAngle", m_minCosRelativeAngle));
282 
283  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SearchRegion1D", m_searchRegion1D));
284 
286 }
float m_minCosRelativeAngle
maximum relative angle between tracks after un-crossing
float m_maxClusterSeparationSquared
maximum separation of two clusters (squared)
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
float m_maxClusterSeparation
maximum separation of two clusters
float m_searchRegion1D
Search region, applied to each dimension, for look-up from kd-trees.
StatusCode lar_content::CrossedTrackSplittingAlgorithm::TidyUpStep ( )
privatevirtual

Tidy up any information cached in e.g. the preparation step.

Reimplemented from lar_content::TwoDSlidingFitSplittingAndSwitchingAlgorithm.

Definition at line 77 of file CrossedTrackSplittingAlgorithm.cc.

78 {
79  m_nearbyClusters.clear();
80 
81  return STATUS_CODE_SUCCESS;
82 }
ClusterToClustersMap m_nearbyClusters
The nearby clusters map.

Member Data Documentation

float lar_content::CrossedTrackSplittingAlgorithm::m_maxClusterSeparation
private

maximum separation of two clusters

Definition at line 60 of file CrossedTrackSplittingAlgorithm.h.

float lar_content::CrossedTrackSplittingAlgorithm::m_maxClusterSeparationSquared
private

maximum separation of two clusters (squared)

Definition at line 61 of file CrossedTrackSplittingAlgorithm.h.

float lar_content::CrossedTrackSplittingAlgorithm::m_minCosRelativeAngle
private

maximum relative angle between tracks after un-crossing

Definition at line 62 of file CrossedTrackSplittingAlgorithm.h.

ClusterToClustersMap lar_content::CrossedTrackSplittingAlgorithm::m_nearbyClusters
private

The nearby clusters map.

Definition at line 65 of file CrossedTrackSplittingAlgorithm.h.

float lar_content::CrossedTrackSplittingAlgorithm::m_searchRegion1D
private

Search region, applied to each dimension, for look-up from kd-trees.

Definition at line 64 of file CrossedTrackSplittingAlgorithm.h.


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