ShowerGrowingAlgorithm.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArTrackShowerId/ShowerGrowingAlgorithm.cc
3  *
4  * @brief Implementation of the shower growing algorithm class.
5  *
6  * $Log: $
7  */
8 
9 #include "Pandora/AlgorithmHeaders.h"
10 
12 
15 
17 
19 
20 using namespace pandora;
21 
22 namespace lar_content
23 {
24 
25 ShowerGrowingAlgorithm::ShowerGrowingAlgorithm() :
26  m_minCaloHitsPerCluster(5),
27  m_nearbyClusterDistance(2.5f),
28  m_remoteClusterDistance(10.f),
29  m_directionTanAngle(1.732f),
30  m_directionApexShift(0.333f),
31  m_minVertexLongitudinalDistance(-2.5f),
32  m_maxVertexLongitudinalDistance(20.f),
33  m_maxVertexTransverseDistance(1.5f),
34  m_vertexAngularAllowance(3.f)
35 {
36 }
37 
38 //------------------------------------------------------------------------------------------------------------------------------------------
39 
40 bool ShowerGrowingAlgorithm::IsVertexAssociated(const LArPointingCluster &pointingCluster, const CartesianVector &vertexPosition2D) const
41 {
48 }
49 
50 //------------------------------------------------------------------------------------------------------------------------------------------
51 
52 bool ShowerGrowingAlgorithm::SortClusters(const Cluster *const pLhs, const Cluster *const pRhs)
53 {
54  CartesianVector innerCoordinateLhs(0.f, 0.f, 0.f), outerCoordinateLhs(0.f, 0.f, 0.f);
55  LArClusterHelper::GetExtremalCoordinates(pLhs, innerCoordinateLhs, outerCoordinateLhs);
56  const float dLhs2((outerCoordinateLhs - innerCoordinateLhs).GetMagnitudeSquared());
57 
58  CartesianVector innerCoordinateRhs(0.f, 0.f, 0.f), outerCoordinateRhs(0.f, 0.f, 0.f);
59  LArClusterHelper::GetExtremalCoordinates(pRhs, innerCoordinateRhs, outerCoordinateRhs);
60  const float dRhs2((outerCoordinateRhs - innerCoordinateRhs).GetMagnitudeSquared());
61 
62  return (dLhs2 > dRhs2);
63 }
64 
65 //------------------------------------------------------------------------------------------------------------------------------------------
66 
68 {
69  for (const std::string &clusterListName : m_inputClusterListNames)
70  {
71  try
72  {
73  const ClusterList *pClusterList = nullptr;
74  PANDORA_RETURN_RESULT_IF_AND_IF(
75  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, clusterListName, pClusterList));
76 
77  if (!pClusterList || pClusterList->empty())
78  {
79  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
80  std::cout << "ShowerGrowingAlgorithm: unable to find cluster list " << clusterListName << std::endl;
81 
82  continue;
83  }
84 
85  this->SimpleModeShowerGrowing(pClusterList, clusterListName);
86  m_clusterDirectionMap.clear();
87  }
88  catch (StatusCodeException &statusCodeException)
89  {
90  m_clusterDirectionMap.clear();
91  throw statusCodeException;
92  }
93  }
94 
95  return STATUS_CODE_SUCCESS;
96 }
97 
98 //------------------------------------------------------------------------------------------------------------------------------------------
99 
100 void ShowerGrowingAlgorithm::SimpleModeShowerGrowing(const ClusterList *const pClusterList, const std::string &clusterListName) const
101 {
102  const VertexList *pVertexList(nullptr);
103  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pVertexList));
104  const Vertex *const pVertex(
105  ((pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) : nullptr);
106 
107  ClusterSet usedClusters;
108 
109  // Pick up all showers starting at vertex
110  if (pVertex)
111  {
112  ClusterVector seedClusters;
113  this->GetAllVertexSeedCandidates(pClusterList, pVertex, seedClusters);
114 
115  SeedAssociationList vertexSeedAssociationList;
116  this->GetSeedAssociationList(seedClusters, pClusterList, vertexSeedAssociationList);
117  this->ProcessSeedAssociationDetails(vertexSeedAssociationList, clusterListName, usedClusters);
118  }
119 
120  // Non-vertex showers
121  const Cluster *pSeedCluster(nullptr);
122 
123  while (this->GetNextSeedCandidate(pClusterList, usedClusters, pSeedCluster))
124  {
125  SeedAssociationList seedAssociationList;
126  this->GetSeedAssociationList(ClusterVector(1, pSeedCluster), pClusterList, seedAssociationList);
127  this->ProcessSeedAssociationDetails(seedAssociationList, clusterListName, usedClusters);
128  }
129 }
130 
131 //------------------------------------------------------------------------------------------------------------------------------------------
132 
133 bool ShowerGrowingAlgorithm::GetNextSeedCandidate(const ClusterList *const pClusterList, const ClusterSet &usedClusters, const Cluster *&pSeedCluster) const
134 {
135  pSeedCluster = nullptr;
136 
137  ClusterVector clusterVector;
138  clusterVector.insert(clusterVector.end(), pClusterList->begin(), pClusterList->end());
139  std::sort(clusterVector.begin(), clusterVector.end(), ShowerGrowingAlgorithm::SortClusters);
140 
141  for (const Cluster *const pCluster : clusterVector)
142  {
143  if (!pCluster->IsAvailable())
144  continue;
145 
146  if (MU_MINUS == std::abs(pCluster->GetParticleId()))
147  continue;
148 
149  if (pCluster->GetNCaloHits() < m_minCaloHitsPerCluster)
150  continue;
151 
152  if (usedClusters.count(pCluster))
153  continue;
154 
155  pSeedCluster = pCluster;
156  return true;
157  }
158 
159  return false;
160 }
161 
162 //------------------------------------------------------------------------------------------------------------------------------------------
163 
164 void ShowerGrowingAlgorithm::GetAllVertexSeedCandidates(const ClusterList *const pClusterList, const Vertex *const pVertex, ClusterVector &seedClusters) const
165 {
166  ClusterVector clusterVector;
167  clusterVector.insert(clusterVector.end(), pClusterList->begin(), pClusterList->end());
168 
169  if (clusterVector.empty())
170  return;
171 
172  const HitType hitType(LArClusterHelper::GetClusterHitType(clusterVector.at(0)));
173  const CartesianVector vertexPosition2D(LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex->GetPosition(), hitType));
174 
175  for (const Cluster *const pCluster : clusterVector)
176  {
177  if (!pCluster->IsAvailable())
178  continue;
179 
180  if (MU_MINUS == std::abs(pCluster->GetParticleId()))
181  continue;
182 
183  if (pCluster->GetNCaloHits() < m_minCaloHitsPerCluster)
184  continue;
185 
186  try
187  {
188  if (this->IsVertexAssociated(LArPointingCluster(pCluster), vertexPosition2D))
189  seedClusters.push_back(pCluster);
190  }
191  catch (StatusCodeException &)
192  {
193  }
194  }
195 
196  std::sort(seedClusters.begin(), seedClusters.end(), ShowerGrowingAlgorithm::SortClusters);
197 }
198 
199 //------------------------------------------------------------------------------------------------------------------------------------------
200 
202  const ClusterVector &particleSeedVector, const ClusterList *const pClusterList, SeedAssociationList &seedAssociationList) const
203 {
204  if (particleSeedVector.empty())
205  return;
206 
207  ClusterVector candidateClusters;
208  const ClusterList clusterList(*pClusterList);
209 
210  for (const Cluster *const pCandidateCluster : clusterList)
211  {
212  if (!pCandidateCluster->IsAvailable())
213  continue;
214 
215  if (MU_MINUS == std::abs(pCandidateCluster->GetParticleId()))
216  continue;
217 
218  if (pCandidateCluster->GetNCaloHits() < m_minCaloHitsPerCluster)
219  continue;
220 
221  if (particleSeedVector.end() == std::find(particleSeedVector.begin(), particleSeedVector.end(), pCandidateCluster))
222  candidateClusters.push_back(pCandidateCluster);
223  }
224 
225  std::sort(candidateClusters.begin(), candidateClusters.end(), ShowerGrowingAlgorithm::SortClusters);
226  ClusterUsageMap forwardUsageMap, backwardUsageMap;
227 
228  for (const Cluster *const pSeedCluster : particleSeedVector)
229  {
230  this->FindAssociatedClusters(pSeedCluster, candidateClusters, forwardUsageMap, backwardUsageMap);
231  }
232 
233  this->IdentifyClusterMerges(particleSeedVector, backwardUsageMap, seedAssociationList);
234 }
235 
236 //------------------------------------------------------------------------------------------------------------------------------------------
237 
239  const SeedAssociationList &seedAssociationList, const std::string &clusterListName, ClusterSet &usedClusters) const
240 {
241  ClusterList clusterList;
242  for (const auto &mapEntry : seedAssociationList)
243  clusterList.push_back(mapEntry.first);
244  clusterList.sort(LArClusterHelper::SortByNHits);
245 
246  for (const Cluster *const pParentCluster : clusterList)
247  {
248  const ClusterVector &branchClusters(seedAssociationList.at(pParentCluster));
249  this->ProcessBranchClusters(pParentCluster, branchClusters, clusterListName);
250 
251  usedClusters.insert(pParentCluster);
252  usedClusters.insert(branchClusters.begin(), branchClusters.end());
253  }
254 }
255 
256 //------------------------------------------------------------------------------------------------------------------------------------------
257 
258 void ShowerGrowingAlgorithm::ProcessBranchClusters(const Cluster *const pParentCluster, const ClusterVector &branchClusters, const std::string &listName) const
259 {
260  m_clusterDirectionMap.erase(pParentCluster);
261 
262  for (const Cluster *const pBranchCluster : branchClusters)
263  {
264  if (pBranchCluster->IsAvailable())
265  {
266  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
267  PandoraContentApi::MergeAndDeleteClusters(*this, pParentCluster, pBranchCluster, listName, listName));
268  }
269 
270  m_clusterDirectionMap.erase(pBranchCluster);
271  }
272 }
273 
274 //------------------------------------------------------------------------------------------------------------------------------------------
275 
276 ShowerGrowingAlgorithm::AssociationType ShowerGrowingAlgorithm::AreClustersAssociated(const Cluster *const pClusterSeed, const Cluster *const pCluster) const
277 {
278  const VertexList *pVertexList(nullptr);
279  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pVertexList));
280  const Vertex *const pVertex(
281  ((pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) : nullptr);
282 
283  // Direction of seed cluster (cache for efficiency)
284  ClusterDirectionMap::const_iterator seedIter = m_clusterDirectionMap.find(pClusterSeed);
285 
286  if (m_clusterDirectionMap.end() == seedIter)
287  {
289  : LArVertexHelper::GetClusterDirectionInZ(this->GetPandora(), pVertex,
290  pClusterSeed, m_directionTanAngle, m_directionApexShift));
291  seedIter = m_clusterDirectionMap.insert(ClusterDirectionMap::value_type(pClusterSeed, direction)).first;
292  }
293 
294  const LArVertexHelper::ClusterDirection seedDirection(seedIter->second);
295  const bool checkSeedForward(seedDirection != LArVertexHelper::DIRECTION_BACKWARD_IN_Z);
296  const bool checkSeedBackward(seedDirection != LArVertexHelper::DIRECTION_FORWARD_IN_Z);
297 
298  // Direction of candidate cluster (cache for efficiency)
300 
301  if (m_clusterDirectionMap.end() == candIter)
302  {
304  : LArVertexHelper::GetClusterDirectionInZ(this->GetPandora(), pVertex,
306  candIter = m_clusterDirectionMap.insert(ClusterDirectionMap::value_type(pCluster, direction)).first;
307  }
308 
309  const LArVertexHelper::ClusterDirection candidateDirection(candIter->second);
310  const bool checkCandidateForward(candidateDirection != LArVertexHelper::DIRECTION_BACKWARD_IN_Z);
311  const bool checkCandidateBackward(candidateDirection != LArVertexHelper::DIRECTION_FORWARD_IN_Z);
312 
313  // Calculate distances of association
314  const float sOuter(LArClusterHelper::GetClosestDistance(pClusterSeed->GetCentroid(pClusterSeed->GetOuterPseudoLayer()), pCluster));
315  const float cOuter(LArClusterHelper::GetClosestDistance(pCluster->GetCentroid(pCluster->GetOuterPseudoLayer()), pClusterSeed));
316  const float sInner(LArClusterHelper::GetClosestDistance(pClusterSeed->GetCentroid(pClusterSeed->GetInnerPseudoLayer()), pCluster));
317  const float cInner(LArClusterHelper::GetClosestDistance(pCluster->GetCentroid(pCluster->GetInnerPseudoLayer()), pClusterSeed));
318 
319  // Association check 1(a), look for enclosed clusters
320  if ((cOuter < m_nearbyClusterDistance && cInner < m_nearbyClusterDistance) &&
321  (!checkSeedForward || (sInner > m_nearbyClusterDistance)) && (!checkSeedBackward || (sOuter > m_nearbyClusterDistance)))
322  {
323  return STRONG;
324  }
325 
326  // Association check 1(b), look for overlapping clusters
327  if ((checkSeedForward == checkCandidateForward) && (checkSeedBackward == checkCandidateBackward))
328  {
329  if ((cInner < m_nearbyClusterDistance && sOuter < m_nearbyClusterDistance) &&
330  (!checkSeedForward || (sInner > m_nearbyClusterDistance)) && (!checkSeedBackward || (cOuter > m_nearbyClusterDistance)))
331  {
332  return STRONG;
333  }
334 
335  if ((cOuter < m_nearbyClusterDistance && sInner < m_nearbyClusterDistance) &&
336  (!checkSeedBackward || (sOuter > m_nearbyClusterDistance)) && (!checkSeedForward || (cInner > m_nearbyClusterDistance)))
337  {
338  return STRONG;
339  }
340  }
341 
342  // Association check 2, look for branching clusters
343  if ((!checkSeedForward || (sInner > m_remoteClusterDistance)) && (!checkSeedBackward || (sOuter > m_remoteClusterDistance)) &&
344  ((checkCandidateForward && (cInner < m_nearbyClusterDistance)) || (checkCandidateBackward && (cOuter < m_nearbyClusterDistance))))
345  {
346  return STANDARD;
347  }
348 
349  // Association check 3, look any distance below threshold
350  if ((sOuter < m_nearbyClusterDistance) || (cOuter < m_nearbyClusterDistance) || (sInner < m_nearbyClusterDistance) || (cInner < m_nearbyClusterDistance))
351  return SINGLE_ORDER;
352 
353  return NONE;
354 }
355 
356 //------------------------------------------------------------------------------------------------------------------------------------------
357 
358 float ShowerGrowingAlgorithm::GetFigureOfMerit(const SeedAssociationList &seedAssociationList) const
359 {
360  const VertexList *pVertexList(nullptr);
361  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pVertexList));
362  const Vertex *const pVertex(
363  ((pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) : nullptr);
364 
365  // ATTN Consistently returning same value will accept all candidate cluster merges
366  if (!pVertex)
367  return -1.f;
368 
369  unsigned int nVertexAssociatedSeeds(0), nVertexAssociatedNonSeeds(0);
370 
371  ClusterList clusterList;
372  for (const auto &mapEntry : seedAssociationList)
373  clusterList.push_back(mapEntry.first);
374  clusterList.sort(LArClusterHelper::SortByNHits);
375 
376  for (const Cluster *const pSeedCluster : clusterList)
377  {
378  const ClusterVector &associatedClusters(seedAssociationList.at(pSeedCluster));
379  const HitType hitType(LArClusterHelper::GetClusterHitType(pSeedCluster));
380  const CartesianVector vertex2D(LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex->GetPosition(), hitType));
381 
382  LArPointingClusterList pointingClusterSeedList;
383  try
384  {
385  pointingClusterSeedList.push_back(LArPointingCluster(pSeedCluster));
386  }
387  catch (StatusCodeException &)
388  {
389  }
390 
391  LArPointingClusterList pointingClusterNonSeedList;
392  for (const Cluster *const pAssociatedCluster : associatedClusters)
393  {
394  try
395  {
396  pointingClusterNonSeedList.push_back(LArPointingCluster(pAssociatedCluster));
397  }
398  catch (StatusCodeException &)
399  {
400  }
401  }
402 
403  nVertexAssociatedSeeds += this->GetNVertexConnections(vertex2D, pointingClusterSeedList);
404  nVertexAssociatedNonSeeds += this->GetNVertexConnections(vertex2D, pointingClusterNonSeedList);
405  }
406 
407  const float figureOfMerit(static_cast<float>(nVertexAssociatedSeeds) - static_cast<float>(nVertexAssociatedNonSeeds));
408  return figureOfMerit;
409 }
410 
411 //------------------------------------------------------------------------------------------------------------------------------------------
412 
413 unsigned int ShowerGrowingAlgorithm::GetNVertexConnections(const CartesianVector &vertexPosition2D, const LArPointingClusterList &pointingClusterList) const
414 {
415  unsigned int nConnections(0);
416 
417  for (LArPointingClusterList::const_iterator cIter = pointingClusterList.begin(), cIterEnd = pointingClusterList.end(); cIter != cIterEnd; ++cIter)
418  {
419  if (this->IsVertexAssociated(*cIter, vertexPosition2D))
420  ++nConnections;
421  }
422 
423  return nConnections;
424 }
425 
426 //------------------------------------------------------------------------------------------------------------------------------------------
427 
428 StatusCode ShowerGrowingAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
429 {
430  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadVectorOfValues(xmlHandle, "InputClusterListNames", m_inputClusterListNames));
431 
432  PANDORA_RETURN_RESULT_IF_AND_IF(
433  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinCaloHitsPerCluster", m_minCaloHitsPerCluster));
434 
435  PANDORA_RETURN_RESULT_IF_AND_IF(
436  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "NearbyClusterDistance", m_nearbyClusterDistance));
437 
438  PANDORA_RETURN_RESULT_IF_AND_IF(
439  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "RemoteClusterDistance", m_remoteClusterDistance));
440 
441  PANDORA_RETURN_RESULT_IF_AND_IF(
442  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "DirectionTanAngle", m_directionTanAngle));
443 
444  PANDORA_RETURN_RESULT_IF_AND_IF(
445  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "DirectionApexShift", m_directionApexShift));
446 
447  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
448  XmlHelper::ReadValue(xmlHandle, "MinVertexLongitudinalDistance", m_minVertexLongitudinalDistance));
449 
450  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
451  XmlHelper::ReadValue(xmlHandle, "MaxVertexLongitudinalDistance", m_maxVertexLongitudinalDistance));
452 
453  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
454  XmlHelper::ReadValue(xmlHandle, "MaxVertexTransverseDistance", m_maxVertexTransverseDistance));
455 
456  PANDORA_RETURN_RESULT_IF_AND_IF(
457  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "VertexAngularAllowance", m_vertexAngularAllowance));
458 
459  return BranchGrowingAlgorithm::ReadSettings(xmlHandle);
460 }
461 
462 } // 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.
pandora::StringVector m_inputClusterListNames
The names of the input cluster lists.
Header file for the lar pointing cluster class.
static bool IsEmission(const pandora::CartesianVector &parentVertex, const LArPointingCluster::Vertex &daughterVertex, const float minLongitudinalDistance, const float maxLongitudinalDistance, const float maxTransverseDistance, const float angularAllowance)
Whether pointing vertex is emitted from a given position.
enum cvn::HType HitType
std::string string
Definition: nybbler.cc:12
std::vector< LArPointingCluster > LArPointingClusterList
float m_directionApexShift
Direction determination, look for vertex inside triangle with apex shifted along the cluster length...
float m_maxVertexLongitudinalDistance
Vertex association check: max longitudinal distance cut.
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
intermediate_table::const_iterator const_iterator
LArPointingCluster class.
std::unordered_map< const pandora::Cluster *, ClusterAssociationMap > ClusterUsageMap
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
void GetSeedAssociationList(const pandora::ClusterVector &particleSeedVector, const pandora::ClusterList *const pClusterList, SeedAssociationList &seedAssociationList) const
Get the seed association list for a given vector of particle seed candidates.
void GetAllVertexSeedCandidates(const pandora::ClusterList *const pClusterList, const pandora::Vertex *const pVertex, pandora::ClusterVector &seedClusters) const
Get all seed candidates associated with a provided vertex.
bool GetNextSeedCandidate(const pandora::ClusterList *const pClusterList, const pandora::ClusterSet &usedClusters, const pandora::Cluster *&pSeedCluster) const
Get the next seed candidate, using a list of available candidates and a list of those already used...
Header file for the geometry helper class.
T abs(T value)
std::unordered_map< const pandora::Cluster *, pandora::ClusterVector > SeedAssociationList
float m_directionTanAngle
Direction determination, look for vertex inside triangle with apex shifted along the cluster length...
void FindAssociatedClusters(const pandora::Cluster *const pParticleSeed, pandora::ClusterVector &candidateClusters, ClusterUsageMap &forwardUsageMap, ClusterUsageMap &backwardUsageMap) const
Find clusters associated with a particle seed.
Header file for the cluster helper class.
unsigned int GetNVertexConnections(const pandora::CartesianVector &vertexPosition2D, const LArPointingClusterList &pointingClusterList) const
Get the number of clusters associated with the vertex.
void ProcessSeedAssociationDetails(const SeedAssociationList &seedAssociationList, const std::string &clusterListName, pandora::ClusterSet &usedClusters) const
Process the details stored in a specified seed association list.
float m_minVertexLongitudinalDistance
Vertex association check: min longitudinal distance cut.
const Vertex & GetOuterVertex() const
Get the outer vertex.
static bool SortClusters(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sorting for clusters to determine order in which seeds are considered.
const Vertex & GetInnerVertex() const
Get the inner vertex.
void SimpleModeShowerGrowing(const pandora::ClusterList *const pClusterList, const std::string &clusterListName) const
Simple single-pass shower growing mode.
void ProcessBranchClusters(const pandora::Cluster *const pParentCluster, const pandora::ClusterVector &branchClusters, const std::string &listName) const
Process the list of branch clusters, merging with specified parent cluster, dealing with any existing...
static void GetExtremalCoordinates(const pandora::ClusterList &clusterList, pandora::CartesianVector &innerCoordinate, pandora::CartesianVector &outerCoordinate)
Get positions of the two most distant calo hits in a list of cluster (ordered by Z) ...
float m_nearbyClusterDistance
The nearby cluster distance, used for determining cluster associations.
float m_maxVertexTransverseDistance
Vertex association check: max transverse distance cut.
Header file for the shower growing algorithm class.
void IdentifyClusterMerges(const pandora::ClusterVector &particleSeedVector, const ClusterUsageMap &backwardUsageMap, SeedAssociationList &seedAssociationList) const
Identify cluster merges.
unsigned int m_minCaloHitsPerCluster
The minimum number of calo hits per (seed or branch) cluster.
bool IsVertexAssociated(const LArPointingCluster &pointingCluster, const pandora::CartesianVector &vertexPosition2D) const
Whether a pointing cluster is assciated with a provided 2D vertex projection.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
Definition: ModuleGraph.h:25
AssociationType AreClustersAssociated(const pandora::Cluster *const pClusterSeed, const pandora::Cluster *const pCluster) const
Determine whether two clusters are associated.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
float GetFigureOfMerit(const SeedAssociationList &seedAssociationList) const
Get a figure of merit representing the consistency of the provided seed associated list...
std::list< Vertex > VertexList
Definition: DCEL.h:182
ClusterDirectionMap m_clusterDirectionMap
The cluster direction map.
float m_vertexAngularAllowance
Vertex association check: pointing angular allowance in degrees.
QTextStream & endl(QTextStream &s)
static bool IsNode(const pandora::CartesianVector &parentVertex, const LArPointingCluster::Vertex &daughterVertex, const float minLongitudinalDistance, const float maxTransverseDistance)
Whether pointing vertex is adjacent to a given position.
static ClusterDirection GetClusterDirectionInZ(const pandora::Pandora &pandora, const pandora::Vertex *const pVertex, const pandora::Cluster *const pCluster, const float tanAngle, const float apexShift)
Get the direction of the cluster in z, using a projection of the provided vertex. ...
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.
float m_remoteClusterDistance
The remote cluster distance, used for determining cluster associations.