LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
OvershootSplittingAlgorithm.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
10 
13 
15 
17 
18 using namespace pandora;
19 
20 namespace lar_content
21 {
22 
23 OvershootSplittingAlgorithm::OvershootSplittingAlgorithm() :
25  m_minClusterLength(5.f),
26  m_maxClusterSeparation(5.f),
27  m_minVertexDisplacement(2.f),
28  m_maxIntersectDisplacement(1.5f),
29  m_minSplitDisplacement(10.f)
30 {
31 }
32 
33 //------------------------------------------------------------------------------------------------------------------------------------------
34 
35 void OvershootSplittingAlgorithm::GetListOfCleanClusters(const ClusterList *const pClusterList, ClusterVector &clusterVector) const
36 {
37  for (ClusterList::const_iterator iter = pClusterList->begin(), iterEnd = pClusterList->end(); iter != iterEnd; ++iter)
38  {
39  const Cluster *const pCluster = *iter;
40 
42  continue;
43 
44  clusterVector.push_back(pCluster);
45  }
46 
47  std::sort(clusterVector.begin(), clusterVector.end(), LArClusterHelper::SortByNHits);
48 }
49 
50 //------------------------------------------------------------------------------------------------------------------------------------------
51 
53  ClusterPositionMap &clusterSplittingMap) const
54 {
55  // Use sliding fit results to build a list of intersection points
56  ClusterPositionMap clusterIntersectionMap;
57  this->BuildIntersectionMap(slidingFitResultMap, clusterIntersectionMap);
58 
59  // Sort intersection points according to their position along the sliding fit
60  ClusterPositionMap sortedIntersectionMap;
61  this->BuildSortedIntersectionMap(slidingFitResultMap, clusterIntersectionMap, sortedIntersectionMap);
62 
63  // Use intersection points to decide where/if to split cluster
64  this->PopulateSplitPositionMap(sortedIntersectionMap, clusterSplittingMap);
65 }
66 
67 //------------------------------------------------------------------------------------------------------------------------------------------
68 
70  ClusterPositionMap &clusterIntersectionMap) const
71 {
72  ClusterList clusterList;
73  for (const auto &mapEntry : slidingFitResultMap) clusterList.push_back(mapEntry.first);
74  clusterList.sort(LArClusterHelper::SortByNHits);
75 
76  for (const Cluster *const pCluster1 : clusterList)
77  {
78  const TwoDSlidingFitResult &slidingFitResult1(slidingFitResultMap.at(pCluster1));
79 
80  for (const Cluster *const pCluster2 : clusterList)
81  {
82  if (pCluster1 == pCluster2)
83  continue;
84 
85  const TwoDSlidingFitResult &slidingFitResult2(slidingFitResultMap.at(pCluster2));
86 
87  try
88  {
89  const LArPointingCluster pointingCluster(slidingFitResult2);
90 
91  // Project pointing cluster onto target cluster
92  const CartesianVector innerPosition(pointingCluster.GetInnerVertex().GetPosition());
93  const CartesianVector outerPosition(pointingCluster.GetOuterVertex().GetPosition());
94  const float innerDisplacement(LArClusterHelper::GetClosestDistance(innerPosition, pCluster1));
95  const float outerDisplacement(LArClusterHelper::GetClosestDistance(outerPosition, pCluster1));
96  const bool useInner((innerDisplacement < outerDisplacement) ? true : false);
97 
98  const LArPointingCluster::Vertex &clusterVertex = (useInner ? pointingCluster.GetInnerVertex() :
99  pointingCluster.GetOuterVertex());
100 
101  float rL2(0.f), rT2(0.f);
102  CartesianVector intersectPosition2(0.f, 0.f, 0.f);
103 
104  try
105  {
106  LArPointingClusterHelper::GetIntersection(clusterVertex, pCluster1, intersectPosition2, rL2, rT2);
107  }
108  catch (const StatusCodeException &)
109  {
110  continue;
111  }
112 
113  if (rL2 < -m_maxIntersectDisplacement || rL2 > m_maxClusterSeparation)
114  continue;
115 
116  // Find projected position and direction on target cluster
117  float rL1(0.f), rT1(0.f);
118  CartesianVector projectedPosition1(0.f, 0.f, 0.f), projectedDirection1(0.f, 0.f, 0.f);
119  slidingFitResult1.GetLocalPosition(intersectPosition2, rL1, rT1);
120 
121  const StatusCode statusCodePosition(slidingFitResult1.GetGlobalFitPosition(rL1, projectedPosition1));
122  if (STATUS_CODE_SUCCESS != statusCodePosition)
123  throw pandora::StatusCodeException(statusCodePosition);
124 
125  const StatusCode statusCodeDirection(slidingFitResult1.GetGlobalFitDirection(rL1, projectedDirection1));
126  if (STATUS_CODE_SUCCESS != statusCodeDirection)
127  throw pandora::StatusCodeException(statusCodeDirection);
128 
129  const CartesianVector projectedPosition2(clusterVertex.GetPosition());
130  const CartesianVector projectedDirection2(clusterVertex.GetDirection());
131 
132  // Find intersection of pointing cluster and target cluster
133  float firstDisplacement(0.f), secondDisplacement(0.f);
134  CartesianVector intersectPosition1(0.f, 0.f, 0.f);
135 
136  try
137  {
138  LArPointingClusterHelper::GetIntersection(projectedPosition1, projectedDirection1, projectedPosition2, projectedDirection2,
139  intersectPosition1, firstDisplacement, secondDisplacement);
140  }
141  catch (const StatusCodeException &)
142  {
143  continue;
144  }
145 
146  // Store intersections if they're sufficiently far along the cluster trajectory
147  const float closestDisplacement1(LArClusterHelper::GetClosestDistance(intersectPosition1, pCluster1));
148  const float closestDisplacement2(LArClusterHelper::GetClosestDistance(intersectPosition1, pCluster2));
149 
150  if (std::max(closestDisplacement1, closestDisplacement2) > m_maxClusterSeparation)
151  continue;
152 
153  const CartesianVector minPosition(slidingFitResult1.GetGlobalMinLayerPosition());
154  const CartesianVector maxPosition(slidingFitResult1.GetGlobalMaxLayerPosition());
155  const float lengthSquared((maxPosition - minPosition).GetMagnitudeSquared());
156 
157  const float minDisplacementSquared((minPosition - intersectPosition1).GetMagnitudeSquared());
158  const float maxDisplacementSquared((maxPosition - intersectPosition1).GetMagnitudeSquared());
159 
160  if (std::min(minDisplacementSquared, maxDisplacementSquared) < (m_minVertexDisplacement * m_minVertexDisplacement) ||
161  std::max(minDisplacementSquared, maxDisplacementSquared) > lengthSquared)
162  continue;
163 
164  clusterIntersectionMap[pCluster1].push_back(intersectPosition1);
165  }
166  catch (StatusCodeException &statusCodeException)
167  {
168  if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
169  throw statusCodeException;
170  }
171  }
172  }
173 }
174 
175 //------------------------------------------------------------------------------------------------------------------------------------------
176 
178  const ClusterPositionMap &clusterIntersectionMap, ClusterPositionMap &sortedIntersectionMap) const
179 {
180  ClusterList clusterList;
181  for (const auto &mapEntry : clusterIntersectionMap) clusterList.push_back(mapEntry.first);
182  clusterList.sort(LArClusterHelper::SortByNHits);
183 
184  for (const Cluster *const pCluster : clusterList)
185  {
186  const CartesianPointVector &inputPositionVector(clusterIntersectionMap.at(pCluster));
187 
188  if (inputPositionVector.empty())
189  continue;
190 
191  TwoDSlidingFitResultMap::const_iterator sIter = slidingFitResultMap.find(pCluster);
192  if (slidingFitResultMap.end() == sIter)
193  throw StatusCodeException(STATUS_CODE_FAILURE);
194 
195  const TwoDSlidingFitResult &slidingFitResult = sIter->second;
196 
197  MyTrajectoryPointList trajectoryPointList;
198  for (CartesianPointVector::const_iterator pIter = inputPositionVector.begin(), pIterEnd = inputPositionVector.end();
199  pIter != pIterEnd; ++pIter)
200  {
201  const CartesianVector &position = *pIter;
202  float rL(0.f), rT(0.f);
203  slidingFitResult.GetLocalPosition(position, rL, rT);
204  trajectoryPointList.push_back(MyTrajectoryPoint(rL, position));
205  }
206 
207  std::sort(trajectoryPointList.begin(), trajectoryPointList.end(), OvershootSplittingAlgorithm::SortByHitProjection);
208 
209  if (trajectoryPointList.empty())
210  throw StatusCodeException(STATUS_CODE_FAILURE);
211 
212  for (MyTrajectoryPointList::const_iterator qIter = trajectoryPointList.begin(), qIterEnd = trajectoryPointList.end();
213  qIter != qIterEnd; ++qIter)
214  {
215  const CartesianVector &clusterPosition = qIter->second;
216  sortedIntersectionMap[pCluster].push_back(clusterPosition);
217  }
218  }
219 }
220 
221 //------------------------------------------------------------------------------------------------------------------------------------------
222 
224  ClusterPositionMap &clusterSplittingMap) const
225 {
226  ClusterList clusterList;
227  for (const auto &mapEntry : clusterIntersectionMap) clusterList.push_back(mapEntry.first);
228  clusterList.sort(LArClusterHelper::SortByNHits);
229 
230  for (const Cluster *const pCluster : clusterList)
231  {
232  const CartesianPointVector &inputPositionVector(clusterIntersectionMap.at(pCluster));
233 
234  if (inputPositionVector.empty())
235  continue;
236 
237  // Select pairs of positions within a given separation, and calculate their average position
238  MyTrajectoryPointList candidatePositionList;
239 
240  bool foundPrevPosition(false);
241  CartesianVector prevPosition(0.f, 0.f, 0.f);
242 
243  for (CartesianPointVector::const_iterator pIter = inputPositionVector.begin(), pIterEnd = inputPositionVector.end();
244  pIter != pIterEnd; ++pIter)
245  {
246  const CartesianVector &nextPosition = *pIter;
247 
248  if (foundPrevPosition)
249  {
250  const CartesianVector averagePosition((nextPosition + prevPosition) * 0.5f);
251  const float displacementSquared((nextPosition - prevPosition).GetMagnitudeSquared());
252 
253  if (displacementSquared < m_maxIntersectDisplacement * m_maxIntersectDisplacement)
254  candidatePositionList.push_back(MyTrajectoryPoint(displacementSquared, averagePosition));
255  }
256 
257  prevPosition = nextPosition;
258  foundPrevPosition = true;
259  }
260 
261  if (candidatePositionList.empty())
262  continue;
263 
264  std::sort(candidatePositionList.begin(), candidatePositionList.end(), OvershootSplittingAlgorithm::SortByHitProjection);
265 
266  // Use the average positions of the closest pairs of points as the split position
267  bool foundPrevCandidate(false);
268  CartesianVector prevCandidate(0.f, 0.f, 0.f);
269 
270  for (MyTrajectoryPointList::const_iterator pIter = candidatePositionList.begin(), pIterEnd = candidatePositionList.end();
271  pIter != pIterEnd; ++pIter)
272  {
273  const CartesianVector &nextCandidate = pIter->second;
274 
275  if (foundPrevCandidate)
276  {
277  if((nextCandidate - prevCandidate).GetMagnitudeSquared() < m_minSplitDisplacement * m_minSplitDisplacement)
278  continue;
279  }
280 
281  clusterSplittingMap[pCluster].push_back(nextCandidate);
282  prevCandidate = nextCandidate;
283  foundPrevCandidate = true;
284  }
285  }
286 }
287 
288 //------------------------------------------------------------------------------------------------------------------------------------------
289 
291 {
292  if (lhs.first != rhs.first)
293  return (lhs.first < rhs.first);
294 
295  return (lhs.second.GetMagnitudeSquared() > rhs.second.GetMagnitudeSquared());
296 }
297 
298 //------------------------------------------------------------------------------------------------------------------------------------------
299 
300 StatusCode OvershootSplittingAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
301 {
302  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
303  "MinClusterLength", m_minClusterLength));
304 
305  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
306  "MaxClusterSeparation", m_maxClusterSeparation));
307 
308  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
309  "MinVertexDisplacement", m_minVertexDisplacement));
310 
311  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
312  "MaxIntersectDisplacement", m_maxIntersectDisplacement));
313 
314  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
315  "MinSplitDisplacement", m_minSplitDisplacement));
316 
318 }
319 
320 } // namespace lar_content
static bool SortByNHits(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by number of hits, then layer span, then inner layer, then position, then pulse-height.
Header file for the lar pointing cluster class.
void GetListOfCleanClusters(const pandora::ClusterList *const pClusterList, pandora::ClusterVector &clusterVector) const
Populate cluster vector with subset of cluster list, containing clusters judged to be clean...
static void GetIntersection(const LArPointingCluster::Vertex &firstVertex, const LArPointingCluster::Vertex &secondVertex, pandora::CartesianVector &intersectPosition, float &firstDisplacement, float &secondDisplacement)
Get intersection of two vertices.
Header file for the overshoot splitting algorithm class.
LArPointingCluster class.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
std::unordered_map< const pandora::Cluster *, TwoDSlidingFitResult > TwoDSlidingFitResultMap
TFile f
Definition: plotHisto.C:6
Int_t max
Definition: plot.C:27
intermediate_table::const_iterator const_iterator
Header file for the cluster helper class.
const Vertex & GetOuterVertex() const
Get the outer vertex.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
const Vertex & GetInnerVertex() const
Get the inner vertex.
void BuildIntersectionMap(const TwoDSlidingFitResultMap &slidingFitResultMap, ClusterPositionMap &clusterIntersectionMap) const
Use sliding fit results to calculate intersections of clusters.
const pandora::CartesianVector & GetDirection() const
Get the vertex direction.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
void FindBestSplitPositions(const TwoDSlidingFitResultMap &slidingFitResultMap, ClusterPositionMap &clusterSplittingMap) const
Determine best split positions based on sliding fit result.
std::vector< MyTrajectoryPoint > MyTrajectoryPointList
std::pair< float, pandora::CartesianVector > MyTrajectoryPoint
Int_t min
Definition: plot.C:26
static bool SortByHitProjection(const MyTrajectoryPoint &lhs, const MyTrajectoryPoint &rhs)
Sort pfos by number of constituent hits.
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
void PopulateSplitPositionMap(const ClusterPositionMap &sortedIntersectionMap, ClusterPositionMap &clusterSplittingMap) const
Select split positions from sorted list of candidate positions.
void GetLocalPosition(const pandora::CartesianVector &position, float &rL, float &rT) const
Get local sliding fit coordinates for a given global position.
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
std::unordered_map< const pandora::Cluster *, pandora::CartesianPointVector > ClusterPositionMap
void BuildSortedIntersectionMap(const TwoDSlidingFitResultMap &slidingFitResultMap, const ClusterPositionMap &clusterIntersectionMap, ClusterPositionMap &sortedIntersectionMap) const
Use intersection points to decide on splitting points.
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.