TwoViewThreeDKinkTool.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArThreeDReco/LArTwoViewMatching/TwoViewThreeDKinkTool.cc
3  *
4  * @brief Implementation of the two view three d kink tool class.
5  *
6  * $Log: $
7  */
8 
9 #include "Pandora/AlgorithmHeaders.h"
10 
15 
17 
18 using namespace pandora;
19 
20 namespace lar_content
21 {
22 
23 TwoViewThreeDKinkTool::TwoViewThreeDKinkTool() :
24  m_minXOverlapFraction(0.1f),
25  m_minMatchingScore(0.95f),
26  m_minLocallyMatchedFraction(0.3f),
27  m_minLongitudinalImpactParameter(-1.f),
28  m_nLayersForKinkSearch(10),
29  m_additionalXStepForKinkSearch(0.01f),
30  m_maxTransverseImpactParameter(5.f),
31  m_minImpactParameterCosTheta(0.5f),
32  m_cosThetaCutForKinkSearch(0.75f)
33 {
34 }
35 
36 //------------------------------------------------------------------------------------------------------------------------------------------
37 
39 {
40 }
41 
42 //------------------------------------------------------------------------------------------------------------------------------------------
43 
45 {
46  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
47  std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
48 
49  ModificationList modificationList;
50  this->GetModifications(pAlgorithm, overlapMatrix, modificationList);
51  const bool changesMade(this->ApplyChanges(pAlgorithm, modificationList));
52 
53  return changesMade;
54 }
55 
56 //------------------------------------------------------------------------------------------------------------------------------------------
57 
59 {
60  if (usedClusters.count(eIter->GetCluster1()) || usedClusters.count(eIter->GetCluster2()))
61  return false;
62 
63  if (eIter->GetOverlapResult().GetTwoViewXOverlap().GetXOverlapFraction0() - m_minXOverlapFraction < std::numeric_limits<float>::epsilon())
64  return false;
65 
66  if (eIter->GetOverlapResult().GetTwoViewXOverlap().GetXOverlapFraction1() - m_minXOverlapFraction < std::numeric_limits<float>::epsilon())
67  return false;
68 
69  if (eIter->GetOverlapResult().GetMatchingScore() - m_minMatchingScore < std::numeric_limits<float>::epsilon())
70  return false;
71 
72  if (eIter->GetOverlapResult().GetLocallyMatchedFraction() - m_minLocallyMatchedFraction < std::numeric_limits<float>::epsilon())
73  return false;
74 
75  return true;
76 }
77 
78 //------------------------------------------------------------------------------------------------------------------------------------------
79 
80 float TwoViewThreeDKinkTool::GetXSamplingPoint(const CartesianVector &splitPosition1, const bool isForwardInX,
81  const TwoDSlidingFitResult &fitResult1, const TwoDSlidingFitResult &fitResult2) const
82 {
83  // Nearest common x position
84  float xMin1(std::numeric_limits<float>::max()), xMax1(std::numeric_limits<float>::lowest());
85  float xMin2(std::numeric_limits<float>::max()), xMax2(std::numeric_limits<float>::lowest());
86  fitResult1.GetMinAndMaxX(xMin1, xMax1);
87  fitResult2.GetMinAndMaxX(xMin2, xMax2);
88 
89  const float commonX(isForwardInX ? std::max(xMin1, xMin2) : std::min(xMax1, xMax2));
90 
91  if (isForwardInX && ((commonX > xMax1) || (commonX > xMax2)))
92  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
93 
94  if (!isForwardInX && ((commonX < xMin1) || (commonX < xMin2)))
95  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
96 
97  // Layer step x position
98  float rL1(0.f), rT1(0.f);
99  fitResult1.GetLocalPosition(splitPosition1, rL1, rT1);
100  const int splitLayer(fitResult1.GetLayer(rL1));
101 
102  const int lowLayer(std::max(fitResult1.GetMinLayer(), std::min(fitResult1.GetMaxLayer(), splitLayer - m_nLayersForKinkSearch)));
103  const int highLayer(std::max(fitResult1.GetMinLayer(), std::min(fitResult1.GetMaxLayer(), splitLayer + m_nLayersForKinkSearch)));
104 
105  CartesianVector minus(0.f, 0.f, 0.f), plus(0.f, 0.f, 0.f);
106  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, fitResult1.GetGlobalFitPosition(fitResult1.GetL(lowLayer), minus));
107  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, fitResult1.GetGlobalFitPosition(fitResult1.GetL(highLayer), plus));
108 
109  if (minus.GetX() > plus.GetX())
110  std::swap(minus, plus);
111 
112  const float layerStepX(isForwardInX ? plus.GetX() : minus.GetX());
113 
114  // Final x position selection
115  const float chosenX(isForwardInX ? std::max(layerStepX, commonX) : std::min(layerStepX, commonX));
116  const float finalX(isForwardInX ? chosenX + m_additionalXStepForKinkSearch : chosenX - m_additionalXStepForKinkSearch);
117  return finalX;
118 }
119 
120 //------------------------------------------------------------------------------------------------------------------------------------------
121 
122 bool TwoViewThreeDKinkTool::IsALowestInX(const LArPointingCluster &pointingClusterA, const LArPointingCluster &pointingClusterB)
123 {
124  const float xMinA{std::min(pointingClusterA.GetInnerVertex().GetPosition().GetX(), pointingClusterA.GetOuterVertex().GetPosition().GetX())};
125  const float xMinB{std::min(pointingClusterB.GetInnerVertex().GetPosition().GetX(), pointingClusterB.GetOuterVertex().GetPosition().GetX())};
126  return xMinA < xMinB;
127 }
128 
129 //------------------------------------------------------------------------------------------------------------------------------------------
130 
132  TwoViewTransverseTracksAlgorithm *const pAlgorithm, const MatrixType &overlapMatrix, ModificationList &modificationList) const
133 {
134  ClusterSet usedClusters;
135  ClusterVector sortedKeyClusters;
136  overlapMatrix.GetSortedKeyClusters(sortedKeyClusters);
137 
138  for (const Cluster *const pKeyCluster : sortedKeyClusters)
139  {
140  if (!pKeyCluster->IsAvailable())
141  continue;
142 
143  unsigned int n1(0), n2(0);
144  MatrixType::ElementList elementList;
145  overlapMatrix.GetConnectedElements(pKeyCluster, true, elementList, n1, n2);
146 
147  if (n1 * n2 < 2)
148  continue;
149 
150  for (MatrixType::ElementList::const_iterator eIter = elementList.begin(); eIter != elementList.end(); ++eIter)
151  {
152  if (!this->PassesElementCuts(eIter, usedClusters))
153  continue;
154 
155  IteratorList iteratorList;
156  this->SelectMatrixElements(eIter, elementList, usedClusters, iteratorList);
157 
158  if (iteratorList.size() < 2)
159  continue;
160 
161  ModificationList localModificationList;
162  this->GetIteratorListModifications(pAlgorithm, iteratorList, localModificationList);
163 
164  if (localModificationList.empty())
165  continue;
166 
167  for (ModificationList::const_iterator mIter = localModificationList.begin(), mIterEnd = localModificationList.end(); mIter != mIterEnd; ++mIter)
168  {
169  usedClusters.insert(mIter->m_affectedClusters.begin(), mIter->m_affectedClusters.end());
170  }
171 
172  modificationList.insert(modificationList.end(), localModificationList.begin(), localModificationList.end());
173  }
174  }
175 }
176 
177 //------------------------------------------------------------------------------------------------------------------------------------------
178 
179 bool TwoViewThreeDKinkTool::ApplyChanges(TwoViewTransverseTracksAlgorithm *const pAlgorithm, const ModificationList &modificationList) const
180 {
181  ClusterMergeMap consolidatedMergeMap;
182  SplitPositionMap consolidatedSplitMap;
183 
184  for (const Modification &modification : modificationList)
185  {
186  ClusterList parentClusters;
187  for (const auto &mapEntry : modification.m_clusterMergeMap)
188  parentClusters.push_back(mapEntry.first);
189  parentClusters.sort(LArClusterHelper::SortByNHits);
190 
191  for (const Cluster *const pParentCluster : parentClusters)
192  {
193  const ClusterList &daughterClusters(modification.m_clusterMergeMap.at(pParentCluster));
194 
195  for (const Cluster *const pDaughterCluster : daughterClusters)
196  {
197  if (consolidatedMergeMap.count(pDaughterCluster))
198  throw StatusCodeException(STATUS_CODE_FAILURE);
199  }
200 
201  ClusterList &targetClusterList(consolidatedMergeMap[pParentCluster]);
202  targetClusterList.insert(targetClusterList.end(), daughterClusters.begin(), daughterClusters.end());
203  }
204 
205  ClusterList splitClusters;
206  for (const auto &mapEntry : modification.m_splitPositionMap)
207  splitClusters.push_back(mapEntry.first);
208  splitClusters.sort(LArClusterHelper::SortByNHits);
209 
210  for (const Cluster *const pSplitCluster : splitClusters)
211  {
212  const CartesianPointVector &splitPositions(modification.m_splitPositionMap.at(pSplitCluster));
213 
214  CartesianPointVector &cartesianPointVector(consolidatedSplitMap[pSplitCluster]);
215  cartesianPointVector.insert(cartesianPointVector.end(), splitPositions.begin(), splitPositions.end());
216  }
217  }
218 
219  bool changesMade(false);
220  changesMade |= pAlgorithm->MakeClusterMerges(consolidatedMergeMap);
221  changesMade |= pAlgorithm->MakeClusterSplits(consolidatedSplitMap);
222 
223  return changesMade;
224 }
225 
226 //------------------------------------------------------------------------------------------------------------------------------------------
227 
229  const ClusterSet &usedClusters, IteratorList &iteratorList) const
230 {
231  iteratorList.push_back(eIter);
232 
233  for (MatrixType::ElementList::const_iterator eIter2 = elementList.begin(); eIter2 != elementList.end(); ++eIter2)
234  {
235  if (eIter == eIter2)
236  continue;
237 
238  if (!this->PassesElementCuts(eIter2, usedClusters))
239  continue;
240 
241  for (IteratorList::const_iterator iIter = iteratorList.begin(); iIter != iteratorList.end(); ++iIter)
242  {
243  if ((*iIter) == eIter2)
244  continue;
245 
246  unsigned int nMatchedClusters(0);
247 
248  if ((*iIter)->GetCluster1() == eIter2->GetCluster1())
249  ++nMatchedClusters;
250 
251  if ((*iIter)->GetCluster2() == eIter2->GetCluster2())
252  ++nMatchedClusters;
253 
254  if (nMatchedClusters > 1)
255  continue;
256 
257  if (nMatchedClusters)
258  {
259  iteratorList.push_back(eIter2);
260  return;
261  }
262  }
263  }
264 }
265 
266 //------------------------------------------------------------------------------------------------------------------------------------------
267 
269  TwoViewTransverseTracksAlgorithm *const pAlgorithm, const IteratorList &iteratorList, ModificationList &modificationList) const
270 {
271  for (IteratorList::const_iterator iIter1 = iteratorList.begin(), iIter1End = iteratorList.end(); iIter1 != iIter1End; ++iIter1)
272  {
273  for (IteratorList::const_iterator iIter2 = std::next(iIter1); iIter2 != iIter1End; ++iIter2)
274  {
275  try
276  {
277  const unsigned int nMatchedReUpsampledSamplingPoints1((*iIter1)->GetOverlapResult().GetNMatchedReUpsampledSamplingPoints());
278  const unsigned int nMatchedReUpsampledSamplingPoints2((*iIter2)->GetOverlapResult().GetNMatchedReUpsampledSamplingPoints());
279  IteratorList::const_iterator iIterA((nMatchedReUpsampledSamplingPoints1 >= nMatchedReUpsampledSamplingPoints2) ? iIter1 : iIter2);
280  IteratorList::const_iterator iIterB((nMatchedReUpsampledSamplingPoints1 >= nMatchedReUpsampledSamplingPoints2) ? iIter2 : iIter1);
281 
282  Particle particle(*(*iIterA), *(*iIterB));
283  const LArPointingCluster pointingClusterA(pAlgorithm->GetCachedSlidingFitResult(particle.m_pClusterA));
284  const LArPointingCluster pointingClusterB(pAlgorithm->GetCachedSlidingFitResult(particle.m_pClusterB));
285 
286  LArPointingCluster::Vertex vertexA, vertexB;
287  LArPointingClusterHelper::GetClosestVertices(pointingClusterA, pointingClusterB, vertexA, vertexB);
288 
289  float transverseAB(std::numeric_limits<float>::max()), transverseBA(std::numeric_limits<float>::max());
290  float longitudinalAB(-std::numeric_limits<float>::max()), longitudinalBA(-std::numeric_limits<float>::max());
291 
292  LArPointingClusterHelper::GetImpactParameters(vertexA, vertexB, longitudinalAB, transverseAB);
293  LArPointingClusterHelper::GetImpactParameters(vertexB, vertexA, longitudinalBA, transverseBA);
294 
295  if (std::min(longitudinalAB, longitudinalBA) < m_minLongitudinalImpactParameter)
296  continue;
297 
298  if (std::min(transverseAB, transverseBA) > m_maxTransverseImpactParameter)
299  continue;
300 
301  const float cosTheta(-vertexA.GetDirection().GetCosOpeningAngle(vertexB.GetDirection()));
302 
303  if (cosTheta < m_minImpactParameterCosTheta)
304  continue;
305 
306  const bool isALowestInX(this->IsALowestInX(pointingClusterA, pointingClusterB));
307  const CartesianVector splitPosition((vertexA.GetPosition() + vertexB.GetPosition()) * 0.5f);
308  const bool isThreeDKink(this->IsThreeDKink(pAlgorithm, particle, splitPosition, isALowestInX));
309 
310  // Construct the modification object
311  Modification modification;
312 
313  if (isThreeDKink)
314  {
315  const TwoDSlidingFitResult &fitResultCommon(pAlgorithm->GetCachedSlidingFitResult(particle.m_pCommonCluster));
316 
317  CartesianVector splitPositionCommon(0.f, 0.f, 0.f);
318  if (STATUS_CODE_SUCCESS != fitResultCommon.GetGlobalFitPositionAtX(splitPosition.GetX(), splitPositionCommon))
319  {
320  continue;
321  }
322 
323  modification.m_splitPositionMap[particle.m_pCommonCluster].push_back(splitPositionCommon);
324  }
325  else
326  {
327  const bool vertexAIsLowX(vertexA.GetPosition().GetX() < vertexB.GetPosition().GetX());
328  const Cluster *const pLowXCluster(vertexAIsLowX ? particle.m_pClusterA : particle.m_pClusterB);
329  const Cluster *const pHighXCluster(vertexAIsLowX ? particle.m_pClusterB : particle.m_pClusterA);
330  modification.m_clusterMergeMap[pLowXCluster].push_back(pHighXCluster);
331  }
332 
333  modification.m_affectedClusters.push_back(particle.m_pClusterA);
334  modification.m_affectedClusters.push_back(particle.m_pClusterB);
335  modification.m_affectedClusters.push_back(particle.m_pCommonCluster);
336 
337  modificationList.push_back(modification);
338  }
339  catch (const StatusCodeException &statusCodeException)
340  {
341  if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
342  throw statusCodeException;
343 
344  continue;
345  }
346  }
347  }
348 }
349 
350 //------------------------------------------------------------------------------------------------------------------------------------------
351 
353  const CartesianVector &splitPosition, const bool isALowestInX) const
354 {
355  try
356  {
357  const TwoDSlidingFitResult &fitResultCommon(pAlgorithm->GetCachedSlidingFitResult(particle.m_pCommonCluster));
358  const TwoDSlidingFitResult &lowXFitResult(isALowestInX ? pAlgorithm->GetCachedSlidingFitResult(particle.m_pClusterA)
359  : pAlgorithm->GetCachedSlidingFitResult(particle.m_pClusterB));
360  const TwoDSlidingFitResult &highXFitResult(isALowestInX ? pAlgorithm->GetCachedSlidingFitResult(particle.m_pClusterB)
361  : pAlgorithm->GetCachedSlidingFitResult(particle.m_pClusterA));
362 
363  const float minusX(this->GetXSamplingPoint(splitPosition, false, lowXFitResult, fitResultCommon));
364  const float plusX(this->GetXSamplingPoint(splitPosition, true, highXFitResult, fitResultCommon));
365  const float splitX(splitPosition.GetX());
366 
367  CartesianVector minus1(0.f, 0.f, 0.f), split1(0.f, 0.f, 0.f), plus1(0.f, 0.f, 0.f);
368  CartesianVector minus2(0.f, 0.f, 0.f), split2(splitPosition), plus2(0.f, 0.f, 0.f);
369 
370  if ((STATUS_CODE_SUCCESS != fitResultCommon.GetGlobalFitPositionAtX(minusX, minus1)) ||
371  (STATUS_CODE_SUCCESS != fitResultCommon.GetGlobalFitPositionAtX(splitX, split1)) ||
372  (STATUS_CODE_SUCCESS != fitResultCommon.GetGlobalFitPositionAtX(plusX, plus1)) ||
373  (STATUS_CODE_SUCCESS != lowXFitResult.GetGlobalFitPositionAtX(minusX, minus2)) ||
374  (STATUS_CODE_SUCCESS != highXFitResult.GetGlobalFitPositionAtX(plusX, plus2)))
375  {
376  return true; // split by default
377  }
378 
379  // Extract results
381  const HitType hitType2(LArClusterHelper::GetClusterHitType(particle.m_pClusterA));
382 
383  CartesianVector minus(0.f, 0.f, 0.f), split(0.f, 0.f, 0.f), plus(0.f, 0.f, 0.f);
384  float chi2Dummy(std::numeric_limits<float>::max());
385  LArGeometryHelper::MergeTwoPositions3D(this->GetPandora(), hitType1, hitType2, minus1, minus2, minus, chi2Dummy);
386  LArGeometryHelper::MergeTwoPositions3D(this->GetPandora(), hitType1, hitType2, split1, split2, split, chi2Dummy);
387  LArGeometryHelper::MergeTwoPositions3D(this->GetPandora(), hitType1, hitType2, plus1, plus2, plus, chi2Dummy);
388 
389  // Apply final cuts
390  const CartesianVector minusToSplit((split - minus).GetUnitVector());
391  const CartesianVector splitToPlus((plus - split).GetUnitVector());
392  const float dotProduct(minusToSplit.GetDotProduct(splitToPlus));
393 
394  if (dotProduct < m_cosThetaCutForKinkSearch)
395  return true;
396  }
397  catch (const StatusCodeException &)
398  {
399  }
400 
401  return false;
402 }
403 
404 //------------------------------------------------------------------------------------------------------------------------------------------
405 //------------------------------------------------------------------------------------------------------------------------------------------
406 
407 TwoViewThreeDKinkTool::Particle::Particle(const MatrixType::Element &elementA, const MatrixType::Element &elementB)
408 {
409  m_pClusterA = (elementA.GetCluster1() != elementB.GetCluster1()) ? elementA.GetCluster1() : elementA.GetCluster2();
410  m_pClusterB = (elementA.GetCluster1() != elementB.GetCluster1()) ? elementB.GetCluster1() : elementB.GetCluster2();
411  m_pCommonCluster = (elementA.GetCluster1() == elementB.GetCluster1()) ? elementA.GetCluster1() : elementA.GetCluster2();
412 
413  if (m_pClusterA == m_pClusterB)
414  throw StatusCodeException(STATUS_CODE_FAILURE);
415 }
416 
417 //------------------------------------------------------------------------------------------------------------------------------------------
418 
419 StatusCode TwoViewThreeDKinkTool::ReadSettings(const TiXmlHandle xmlHandle)
420 {
421  PANDORA_RETURN_RESULT_IF_AND_IF(
422  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinMatchingScore", m_minMatchingScore));
423 
424  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
425  XmlHelper::ReadValue(xmlHandle, "MinLocallyMatchedFraction", m_minLocallyMatchedFraction));
426 
427  PANDORA_RETURN_RESULT_IF_AND_IF(
428  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinXOverlapFraction", m_minXOverlapFraction));
429 
430  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
431  XmlHelper::ReadValue(xmlHandle, "MinLongitudinalImpactParameter", m_minLongitudinalImpactParameter));
432 
433  PANDORA_RETURN_RESULT_IF_AND_IF(
434  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "NLayersForKinkSearch", m_nLayersForKinkSearch));
435 
436  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
437  XmlHelper::ReadValue(xmlHandle, "AdditionalXStepForKinkSearch", m_additionalXStepForKinkSearch));
438 
439  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
440  XmlHelper::ReadValue(xmlHandle, "MaxTransverseImpactParameter", m_maxTransverseImpactParameter));
441 
442  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
443  XmlHelper::ReadValue(xmlHandle, "MinImpactParameterCosTheta", m_minImpactParameterCosTheta));
444 
445  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
446  XmlHelper::ReadValue(xmlHandle, "CosThetaCutForKinkSearch", m_cosThetaCutForKinkSearch));
447 
448  return STATUS_CODE_SUCCESS;
449 }
450 
451 } // 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.
float m_minLocallyMatchedFraction
The min locally matched fraction for particle creation.
virtual bool MakeClusterSplits(const SplitPositionMap &splitPositionMap)
Make cluster splits.
Header file for the lar pointing cluster class.
const pandora::Cluster * m_pClusterB
Address of non-shared cluster in element B.
void GetMinAndMaxX(float &minX, float &maxX) const
Get the minimum and maximum x coordinates associated with the sliding fit.
static void MergeTwoPositions3D(const pandora::Pandora &pandora, const pandora::HitType view1, const pandora::HitType view2, const pandora::CartesianVector &position1, const pandora::CartesianVector &position2, pandora::CartesianVector &position3D, float &chiSquared)
Merge 2D positions from two views to give unified 3D position.
enum cvn::HType HitType
static bool IsALowestInX(const LArPointingCluster &pointingClusterA, const LArPointingCluster &pointingClusterB)
Whether pointing cluster labelled A extends to lowest x positions (as opposed to that labelled B) ...
SplitPositionMap m_splitPositionMap
The split position map.
const TwoDSlidingFitResult & GetCachedSlidingFitResult(const pandora::Cluster *const pCluster) const
Get a sliding fit result from the algorithm cache.
static void GetImpactParameters(const LArPointingCluster::Vertex &pointingVertex, const LArPointingCluster::Vertex &targetVertex, float &longitudinal, float &transverse)
Calculate impact parameters between a pair of pointing vertices.
intermediate_table::const_iterator const_iterator
LArPointingCluster class.
std::vector< Modification > ModificationList
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
void GetSortedKeyClusters(pandora::ClusterVector &sortedKeyClusters) const
Get a sorted vector of key clusters (view 1 clusters with current implementation) ...
float m_minMatchingScore
The min global matching score for particle creation.
static void GetClosestVertices(const bool useX, const bool useY, const bool useZ, const LArPointingCluster &pointingClusterI, const LArPointingCluster &pointingClusterJ, LArPointingCluster::Vertex &closestVertexI, LArPointingCluster::Vertex &closestVertexJ)
Given a pair of pointing clusters, receive the closest or farthest pair of vertices.
Particle(const MatrixType::Element &elementA, const MatrixType::Element &elementB)
Constructor.
const pandora::Cluster * m_pClusterA
Address of non-shared cluster in element A.
float m_minXOverlapFraction
The min x overlap fraction value for particle creation.
float m_additionalXStepForKinkSearch
An additional (safety) step to tack-on when choosing x sampling.
Header file for the geometry helper class.
bool IsThreeDKink(TwoViewTransverseTracksAlgorithm *const pAlgorithm, const Particle &particle, const pandora::CartesianVector &splitPosition, const bool isALowestInX) const
Whether the provided particle is consistent with being a kink, when examined in three dimensions at t...
int GetMaxLayer() const
Get the maximum occupied layer in the sliding fit.
int GetMinLayer() const
Get the minimum occupied layer in the sliding fit.
void swap(Handle< T > &a, Handle< T > &b)
void GetModifications(TwoViewTransverseTracksAlgorithm *const pAlgorithm, const MatrixType &overlapMatrix, ModificationList &modificationList) const
Get modification objects, identifying required splits and merges for clusters.
Header file for the cluster helper class.
void SelectMatrixElements(MatrixType::ElementList::const_iterator eIter, const MatrixType::ElementList &elementList, const pandora::ClusterSet &usedClusters, IteratorList &iteratorList) const
Select elements representing possible components of interest due to overshoots or undershoots in clus...
pandora::StatusCode GetGlobalFitPosition(const float rL, pandora::CartesianVector &position) const
Get global fit position for a given longitudinal coordinate.
const Vertex & GetOuterVertex() const
Get the outer vertex.
std::unordered_map< const pandora::Cluster *, pandora::CartesianPointVector > SplitPositionMap
float m_maxTransverseImpactParameter
The maximum transverse impact parameter for connecting broken clusters.
const Vertex & GetInnerVertex() const
Get the inner vertex.
int m_nLayersForKinkSearch
The number of sliding fit layers to step in the kink search.
bool Run(TwoViewTransverseTracksAlgorithm *const pAlgorithm, MatrixType &overlapMatrix)
Run the algorithm tool.
static int max(int a, int b)
virtual bool MakeClusterMerges(const ClusterMergeMap &clusterMergeMap)
Merge clusters together.
float m_cosThetaCutForKinkSearch
The cos theta cut used for the kink search in three dimensions.
bool PassesElementCuts(MatrixType::ElementList::const_iterator eIter, const pandora::ClusterSet &usedClusters) const
Whether a provided (iterator to a) matrix element passes the selection cuts for overshoot identificat...
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
float m_minImpactParameterCosTheta
The minimum cos theta (angle between vertex directions) for connecting broken clusters.
pandora::ClusterList m_affectedClusters
The list of affected clusters.
void GetIteratorListModifications(TwoViewTransverseTracksAlgorithm *const pAlgorithm, const IteratorList &iteratorList, ModificationList &modificationList) const
Get modification objects for specific elements of the matrix, identifying required splits and merges ...
float GetL(const int layer) const
Get longitudinal coordinate for a given sliding linear fit layer number.
bool ApplyChanges(TwoViewTransverseTracksAlgorithm *const pAlgorithm, const ModificationList &modificationList) const
Apply the changes cached in a modification list and update the matrix accordingly.
void GetConnectedElements(const pandora::Cluster *const pCluster, const bool ignoreUnavailable, ElementList &elementList) const
Get a list of elements connected to a specified cluster.
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterMergeMap
ClusterMergeMap m_clusterMergeMap
The cluster merge map.
Header file for the two view three d kink tool class.
void split(std::string const &s, char c, OutIter dest)
Definition: split.h:35
std::vector< art::Ptr< recob::Cluster > > ClusterVector
float m_minLongitudinalImpactParameter
The min longitudinal impact parameter for connecting accompanying clusters.
std::vector< MatrixType::ElementList::const_iterator > IteratorList
float GetXSamplingPoint(const pandora::CartesianVector &splitPosition1, const bool isForwardInX, const TwoDSlidingFitResult &fitResult1, const TwoDSlidingFitResult &fitResult2) const
Get a sampling point in x that is common to sliding linear fit objects in two views.
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.
int GetLayer(const float rL) const
Get layer number for given sliding linear fit longitudinal coordinate.
QTextStream & endl(QTextStream &s)
const pandora::Cluster * m_pCommonCluster
Address of the common cluster.