LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
ShowerGrowingAlgorithm.cc
Go to the documentation of this file.
1 
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 {
46 }
47 
48 //------------------------------------------------------------------------------------------------------------------------------------------
49 
50 bool ShowerGrowingAlgorithm::SortClusters(const Cluster *const pLhs, const Cluster *const pRhs)
51 {
52  CartesianVector innerCoordinateLhs(0.f, 0.f, 0.f), outerCoordinateLhs(0.f, 0.f, 0.f);
53  LArClusterHelper::GetExtremalCoordinates(pLhs, innerCoordinateLhs, outerCoordinateLhs);
54  const float dLhs2((outerCoordinateLhs - innerCoordinateLhs).GetMagnitudeSquared());
55 
56  CartesianVector innerCoordinateRhs(0.f, 0.f, 0.f), outerCoordinateRhs(0.f, 0.f, 0.f);
57  LArClusterHelper::GetExtremalCoordinates(pRhs, innerCoordinateRhs, outerCoordinateRhs);
58  const float dRhs2((outerCoordinateRhs - innerCoordinateRhs).GetMagnitudeSquared());
59 
60  return (dLhs2 > dRhs2);
61 }
62 
63 //------------------------------------------------------------------------------------------------------------------------------------------
64 
66 {
67  for (const std::string &clusterListName : m_inputClusterListNames)
68  {
69  try
70  {
71  const ClusterList *pClusterList = nullptr;
72  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, clusterListName, pClusterList));
73 
74  if (!pClusterList || pClusterList->empty())
75  {
76  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
77  std::cout << "ShowerGrowingAlgorithm: unable to find cluster list " << clusterListName << std::endl;
78 
79  continue;
80  }
81 
82  this->SimpleModeShowerGrowing(pClusterList, clusterListName);
83  m_clusterDirectionMap.clear();
84  }
85  catch (StatusCodeException &statusCodeException)
86  {
87  m_clusterDirectionMap.clear();
88  throw statusCodeException;
89  }
90  }
91 
92  return STATUS_CODE_SUCCESS;
93 }
94 
95 //------------------------------------------------------------------------------------------------------------------------------------------
96 
97 void ShowerGrowingAlgorithm::SimpleModeShowerGrowing(const ClusterList *const pClusterList, const std::string &clusterListName) const
98 {
99  const VertexList *pVertexList(nullptr);
100  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pVertexList));
101  const Vertex *const pVertex(((pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) : nullptr);
102 
103  ClusterSet usedClusters;
104 
105  // Pick up all showers starting at vertex
106  if (pVertex)
107  {
108  ClusterVector seedClusters;
109  this->GetAllVertexSeedCandidates(pClusterList, pVertex, seedClusters);
110 
111  SeedAssociationList vertexSeedAssociationList;
112  this->GetSeedAssociationList(seedClusters, pClusterList, vertexSeedAssociationList);
113  this->ProcessSeedAssociationDetails(vertexSeedAssociationList, clusterListName, usedClusters);
114  }
115 
116  // Non-vertex showers
117  const Cluster *pSeedCluster(nullptr);
118 
119  while (this->GetNextSeedCandidate(pClusterList, usedClusters, pSeedCluster))
120  {
121  SeedAssociationList seedAssociationList;
122  this->GetSeedAssociationList(ClusterVector(1, pSeedCluster), pClusterList, seedAssociationList);
123  this->ProcessSeedAssociationDetails(seedAssociationList, clusterListName, usedClusters);
124  }
125 }
126 
127 //------------------------------------------------------------------------------------------------------------------------------------------
128 
129 bool ShowerGrowingAlgorithm::GetNextSeedCandidate(const ClusterList *const pClusterList, const ClusterSet &usedClusters,
130  const Cluster *&pSeedCluster) const
131 {
132  pSeedCluster = nullptr;
133 
134  ClusterVector clusterVector;
135  clusterVector.insert(clusterVector.end(), pClusterList->begin(), pClusterList->end());
136  std::sort(clusterVector.begin(), clusterVector.end(), ShowerGrowingAlgorithm::SortClusters);
137 
138  for (const Cluster *const pCluster : clusterVector)
139  {
140  if (!pCluster->IsAvailable())
141  continue;
142 
143  if (MU_MINUS == std::abs(pCluster->GetParticleId()))
144  continue;
145 
146  if (pCluster->GetNCaloHits() < m_minCaloHitsPerCluster)
147  continue;
148 
149  if (usedClusters.count(pCluster))
150  continue;
151 
152  pSeedCluster = pCluster;
153  return true;
154  }
155 
156  return false;
157 }
158 
159 //------------------------------------------------------------------------------------------------------------------------------------------
160 
161 void ShowerGrowingAlgorithm::GetAllVertexSeedCandidates(const ClusterList *const pClusterList, const Vertex *const pVertex,
162  ClusterVector &seedClusters) const
163 {
164  ClusterVector clusterVector;
165  clusterVector.insert(clusterVector.end(), pClusterList->begin(), pClusterList->end());
166 
167  if (clusterVector.empty())
168  return;
169 
170  const HitType hitType(LArClusterHelper::GetClusterHitType(clusterVector.at(0)));
171  const CartesianVector vertexPosition2D(LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex->GetPosition(), hitType));
172 
173  for (const Cluster *const pCluster : clusterVector)
174  {
175  if (!pCluster->IsAvailable())
176  continue;
177 
178  if (MU_MINUS == std::abs(pCluster->GetParticleId()))
179  continue;
180 
181  if (pCluster->GetNCaloHits() < m_minCaloHitsPerCluster)
182  continue;
183 
184  try
185  {
186  if (this->IsVertexAssociated(LArPointingCluster(pCluster), vertexPosition2D))
187  seedClusters.push_back(pCluster);
188  }
189  catch (StatusCodeException &)
190  {
191  }
192  }
193 
194  std::sort(seedClusters.begin(), seedClusters.end(), ShowerGrowingAlgorithm::SortClusters);
195 }
196 
197 //------------------------------------------------------------------------------------------------------------------------------------------
198 
199 void ShowerGrowingAlgorithm::GetSeedAssociationList(const ClusterVector &particleSeedVector, const ClusterList *const pClusterList,
200  SeedAssociationList &seedAssociationList) const
201 {
202  if (particleSeedVector.empty())
203  return;
204 
205  ClusterVector candidateClusters;
206  const ClusterList clusterList(*pClusterList);
207 
208  for (const Cluster *const pCandidateCluster : clusterList)
209  {
210  if (!pCandidateCluster->IsAvailable())
211  continue;
212 
213  if (MU_MINUS == std::abs(pCandidateCluster->GetParticleId()))
214  continue;
215 
216  if (pCandidateCluster->GetNCaloHits() < m_minCaloHitsPerCluster)
217  continue;
218 
219  if (particleSeedVector.end() == std::find(particleSeedVector.begin(), particleSeedVector.end(), pCandidateCluster))
220  candidateClusters.push_back(pCandidateCluster);
221  }
222 
223  std::sort(candidateClusters.begin(), candidateClusters.end(), ShowerGrowingAlgorithm::SortClusters);
224  ClusterUsageMap forwardUsageMap, backwardUsageMap;
225 
226  for (const Cluster *const pSeedCluster : particleSeedVector)
227  {
228  this->FindAssociatedClusters(pSeedCluster, candidateClusters, forwardUsageMap, backwardUsageMap);
229  }
230 
231  this->IdentifyClusterMerges(particleSeedVector, backwardUsageMap, seedAssociationList);
232 }
233 
234 //------------------------------------------------------------------------------------------------------------------------------------------
235 
236 void ShowerGrowingAlgorithm::ProcessSeedAssociationDetails(const SeedAssociationList &seedAssociationList, const std::string &clusterListName,
237  ClusterSet &usedClusters) const
238 {
239  ClusterList clusterList;
240  for (const auto &mapEntry : seedAssociationList) clusterList.push_back(mapEntry.first);
241  clusterList.sort(LArClusterHelper::SortByNHits);
242 
243  for (const Cluster *const pParentCluster : clusterList)
244  {
245  const ClusterVector &branchClusters(seedAssociationList.at(pParentCluster));
246  this->ProcessBranchClusters(pParentCluster, branchClusters, clusterListName);
247 
248  usedClusters.insert(pParentCluster);
249  usedClusters.insert(branchClusters.begin(), branchClusters.end());
250  }
251 }
252 
253 //------------------------------------------------------------------------------------------------------------------------------------------
254 
255 void ShowerGrowingAlgorithm::ProcessBranchClusters(const Cluster *const pParentCluster, const ClusterVector &branchClusters, const std::string &listName) const
256 {
257  m_clusterDirectionMap.erase(pParentCluster);
258 
259  for (const Cluster *const pBranchCluster : branchClusters)
260  {
261  if (pBranchCluster->IsAvailable())
262  {
263  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*this, pParentCluster, pBranchCluster, listName, listName));
264  }
265 
266  m_clusterDirectionMap.erase(pBranchCluster);
267  }
268 }
269 
270 //------------------------------------------------------------------------------------------------------------------------------------------
271 
272 ShowerGrowingAlgorithm::AssociationType ShowerGrowingAlgorithm::AreClustersAssociated(const Cluster *const pClusterSeed, const Cluster *const pCluster) const
273 {
274  const VertexList *pVertexList(nullptr);
275  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pVertexList));
276  const Vertex *const pVertex(((pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) : nullptr);
277 
278  // Direction of seed cluster (cache for efficiency)
279  ClusterDirectionMap::const_iterator seedIter = m_clusterDirectionMap.find(pClusterSeed);
280 
281  if (m_clusterDirectionMap.end() == seedIter)
282  {
283  const LArVertexHelper::ClusterDirection direction((nullptr == pVertex) ? LArVertexHelper::DIRECTION_UNKNOWN :
284  LArVertexHelper::GetClusterDirectionInZ(this->GetPandora(), pVertex, pClusterSeed, m_directionTanAngle, m_directionApexShift));
285  seedIter = m_clusterDirectionMap.insert(ClusterDirectionMap::value_type(pClusterSeed, direction)).first;
286  }
287 
288  const LArVertexHelper::ClusterDirection seedDirection(seedIter->second);
289  const bool checkSeedForward(seedDirection != LArVertexHelper::DIRECTION_BACKWARD_IN_Z);
290  const bool checkSeedBackward(seedDirection != LArVertexHelper::DIRECTION_FORWARD_IN_Z);
291 
292  // Direction of candidate cluster (cache for efficiency)
294 
295  if (m_clusterDirectionMap.end() == candIter)
296  {
297  const LArVertexHelper::ClusterDirection direction((nullptr == pVertex) ? LArVertexHelper::DIRECTION_UNKNOWN :
298  LArVertexHelper::GetClusterDirectionInZ(this->GetPandora(), pVertex, pCluster, m_directionTanAngle, m_directionApexShift));
299  candIter = m_clusterDirectionMap.insert(ClusterDirectionMap::value_type(pCluster, direction)).first;
300  }
301 
302  const LArVertexHelper::ClusterDirection candidateDirection(candIter->second);
303  const bool checkCandidateForward(candidateDirection != LArVertexHelper::DIRECTION_BACKWARD_IN_Z);
304  const bool checkCandidateBackward(candidateDirection != LArVertexHelper::DIRECTION_FORWARD_IN_Z);
305 
306  // Calculate distances of association
307  const float sOuter(LArClusterHelper::GetClosestDistance(pClusterSeed->GetCentroid(pClusterSeed->GetOuterPseudoLayer()), pCluster));
308  const float cOuter(LArClusterHelper::GetClosestDistance(pCluster->GetCentroid(pCluster->GetOuterPseudoLayer()), pClusterSeed));
309  const float sInner(LArClusterHelper::GetClosestDistance(pClusterSeed->GetCentroid(pClusterSeed->GetInnerPseudoLayer()), pCluster));
310  const float cInner(LArClusterHelper::GetClosestDistance(pCluster->GetCentroid(pCluster->GetInnerPseudoLayer()), pClusterSeed));
311 
312  // Association check 1(a), look for enclosed clusters
313  if ((cOuter < m_nearbyClusterDistance && cInner < m_nearbyClusterDistance) &&
314  (!checkSeedForward || (sInner > m_nearbyClusterDistance)) &&
315  (!checkSeedBackward || (sOuter > m_nearbyClusterDistance)))
316  {
317  return STRONG;
318  }
319 
320  // Association check 1(b), look for overlapping clusters
321  if ((checkSeedForward == checkCandidateForward) && (checkSeedBackward == checkCandidateBackward))
322  {
323  if ((cInner < m_nearbyClusterDistance && sOuter < m_nearbyClusterDistance) &&
324  (!checkSeedForward || (sInner > m_nearbyClusterDistance)) &&
325  (!checkSeedBackward || (cOuter > m_nearbyClusterDistance)))
326  {
327  return STRONG;
328  }
329 
330  if ((cOuter < m_nearbyClusterDistance && sInner < m_nearbyClusterDistance) &&
331  (!checkSeedBackward || (sOuter > m_nearbyClusterDistance)) &&
332  (!checkSeedForward || (cInner > m_nearbyClusterDistance)))
333  {
334  return STRONG;
335  }
336  }
337 
338  // Association check 2, look for branching clusters
339  if ((!checkSeedForward || (sInner > m_remoteClusterDistance)) &&
340  (!checkSeedBackward || (sOuter > m_remoteClusterDistance)) &&
341  ((checkCandidateForward && (cInner < m_nearbyClusterDistance)) || (checkCandidateBackward && (cOuter < m_nearbyClusterDistance))))
342  {
343  return STANDARD;
344  }
345 
346  // Association check 3, look any distance below threshold
347  if ((sOuter < m_nearbyClusterDistance) || (cOuter < m_nearbyClusterDistance) || (sInner < m_nearbyClusterDistance) || (cInner < m_nearbyClusterDistance))
348  return SINGLE_ORDER;
349 
350  return NONE;
351 }
352 
353 //------------------------------------------------------------------------------------------------------------------------------------------
354 
355 float ShowerGrowingAlgorithm::GetFigureOfMerit(const SeedAssociationList &seedAssociationList) const
356 {
357  const VertexList *pVertexList(nullptr);
358  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pVertexList));
359  const Vertex *const pVertex(((pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) : nullptr);
360 
361  // ATTN Consistently returning same value will accept all candidate cluster merges
362  if (!pVertex)
363  return -1.f;
364 
365  unsigned int nVertexAssociatedSeeds(0), nVertexAssociatedNonSeeds(0);
366 
367  ClusterList clusterList;
368  for (const auto &mapEntry : seedAssociationList) clusterList.push_back(mapEntry.first);
369  clusterList.sort(LArClusterHelper::SortByNHits);
370 
371  for (const Cluster *const pSeedCluster : clusterList)
372  {
373  const ClusterVector &associatedClusters(seedAssociationList.at(pSeedCluster));
374  const HitType hitType(LArClusterHelper::GetClusterHitType(pSeedCluster));
375  const CartesianVector vertex2D(LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex->GetPosition(), hitType));
376 
377  LArPointingClusterList pointingClusterSeedList;
378  try {pointingClusterSeedList.push_back(LArPointingCluster(pSeedCluster));} catch (StatusCodeException &) {}
379 
380  LArPointingClusterList pointingClusterNonSeedList;
381  for (const Cluster *const pAssociatedCluster : associatedClusters)
382  {
383  try {pointingClusterNonSeedList.push_back(LArPointingCluster(pAssociatedCluster));} catch (StatusCodeException &) {}
384  }
385 
386  nVertexAssociatedSeeds += this->GetNVertexConnections(vertex2D, pointingClusterSeedList);
387  nVertexAssociatedNonSeeds += this->GetNVertexConnections(vertex2D, pointingClusterNonSeedList);
388  }
389 
390  const float figureOfMerit(static_cast<float>(nVertexAssociatedSeeds) - static_cast<float>(nVertexAssociatedNonSeeds));
391  return figureOfMerit;
392 }
393 
394 //------------------------------------------------------------------------------------------------------------------------------------------
395 
396 unsigned int ShowerGrowingAlgorithm::GetNVertexConnections(const CartesianVector &vertexPosition2D, const LArPointingClusterList &pointingClusterList) const
397 {
398  unsigned int nConnections(0);
399 
400  for (LArPointingClusterList::const_iterator cIter = pointingClusterList.begin(), cIterEnd = pointingClusterList.end(); cIter != cIterEnd; ++cIter)
401  {
402  if (this->IsVertexAssociated(*cIter, vertexPosition2D))
403  ++nConnections;
404  }
405 
406  return nConnections;
407 }
408 
409 //------------------------------------------------------------------------------------------------------------------------------------------
410 
411 StatusCode ShowerGrowingAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
412 {
413  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadVectorOfValues(xmlHandle, "InputClusterListNames", m_inputClusterListNames));
414 
415  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
416  "MinCaloHitsPerCluster", m_minCaloHitsPerCluster));
417 
418  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
419  "NearbyClusterDistance", m_nearbyClusterDistance));
420 
421  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
422  "RemoteClusterDistance", m_remoteClusterDistance));
423 
424  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
425  "DirectionTanAngle", m_directionTanAngle));
426 
427  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
428  "DirectionApexShift", m_directionApexShift));
429 
430  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
431  "MinVertexLongitudinalDistance", m_minVertexLongitudinalDistance));
432 
433  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
434  "MaxVertexLongitudinalDistance", m_maxVertexLongitudinalDistance));
435 
436  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
437  "MaxVertexTransverseDistance", m_maxVertexTransverseDistance));
438 
439  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
440  "VertexAngularAllowance", m_vertexAngularAllowance));
441 
442  return BranchGrowingAlgorithm::ReadSettings(xmlHandle);
443 }
444 
445 } // 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.
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.
std::unordered_map< const pandora::Cluster *, ClusterAssociationMap > ClusterUsageMap
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
LArPointingCluster class.
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...
TFile f
Definition: plotHisto.C:6
Header file for the geometry helper class.
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...
intermediate_table::const_iterator const_iterator
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...
std::vector< art::Ptr< recob::Cluster > > ClusterVector
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)
AssociationType AreClustersAssociated(const pandora::Cluster *const pClusterSeed, const pandora::Cluster *const pCluster) const
Determine whether two clusters are associated.
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:178
ClusterDirectionMap m_clusterDirectionMap
The cluster direction map.
float m_vertexAngularAllowance
Vertex association check: pointing angular allowance in degrees.
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.