LArSoft  v09_93_00
Liquid Argon Software toolkit - https://larsoft.org/
SlidingConePfoMopUpAlgorithm.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
10 
15 
17 
19 
20 using namespace pandora;
21 
22 namespace lar_content
23 {
24 
25 SlidingConePfoMopUpAlgorithm::SlidingConePfoMopUpAlgorithm() :
26  m_useVertex(true),
27  m_legacyMode(true),
28  m_maxIterations(1000),
29  m_maxHitsToConsider3DTrack(100),
30  m_minHitsToConsider3DShower(20),
31  m_halfWindowLayers(20),
32  m_nConeFitLayers(20),
33  m_nConeFits(5),
34  m_coneLengthMultiplier(7.f),
35  m_maxConeLength(126.f),
36  m_coneTanHalfAngle1(0.5f),
37  m_coneBoundedFraction1(0.5f),
38  m_coneTanHalfAngle2(0.75f),
39  m_coneBoundedFraction2(0.75f),
40  m_minVertexLongitudinalDistance(-2.5f),
41  m_maxVertexTransverseDistance(3.5f)
42 {
43 }
44 
45 //------------------------------------------------------------------------------------------------------------------------------------------
46 
48 {
49  const Vertex *pVertex(nullptr);
50  this->GetInteractionVertex(pVertex);
51 
52  if (m_useVertex && !pVertex)
53  {
54  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
55  std::cout << "SlidingConePfoMopUpAlgorithm - interaction vertex not available for use." << std::endl;
56  return STATUS_CODE_SUCCESS;
57  }
58 
59  unsigned int nIterations(0);
60 
61  while (nIterations++ < m_maxIterations)
62  {
63  ClusterVector clusters3D;
64  ClusterToPfoMap clusterToPfoMap;
65  this->GetThreeDClusters(clusters3D, clusterToPfoMap);
66 
67  ClusterMergeMap clusterMergeMap;
68  this->GetClusterMergeMap(pVertex, clusters3D, clusterToPfoMap, clusterMergeMap);
69 
70  if (!this->MakePfoMerges(clusterToPfoMap, clusterMergeMap))
71  break;
72  }
73 
74  return STATUS_CODE_SUCCESS;
75 }
76 
77 //------------------------------------------------------------------------------------------------------------------------------------------
78 
80 {
81  if (!m_useVertex)
82  return;
83 
84  const VertexList *pVertexList = nullptr;
85  PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetCurrentList(*this, pVertexList));
86 
87  pVertex =
88  ((pVertexList && (pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) : nullptr);
89 }
90 
91 //------------------------------------------------------------------------------------------------------------------------------------------
92 
94 {
95  for (const std::string &pfoListName : m_inputPfoListNames)
96  {
97  const PfoList *pPfoList(nullptr);
98 
99  if (STATUS_CODE_SUCCESS != PandoraContentApi::GetList(*this, pfoListName, pPfoList))
100  continue;
101 
102  for (const Pfo *const pPfo : *pPfoList)
103  {
104  ClusterList pfoClusters3D;
105  LArPfoHelper::GetThreeDClusterList(pPfo, pfoClusters3D);
106 
107  for (const Cluster *const pCluster3D : pfoClusters3D)
108  {
109  if (LArPfoHelper::IsTrack(pPfo) && (pCluster3D->GetNCaloHits() > m_maxHitsToConsider3DTrack))
110  continue;
111 
112  if (!clusterToPfoMap.insert(ClusterToPfoMap::value_type(pCluster3D, pPfo)).second)
113  throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
114 
115  clusters3D.push_back(pCluster3D);
116  }
117  }
118  }
119 
120  std::sort(clusters3D.begin(), clusters3D.end(), LArClusterHelper::SortByNHits);
121 }
122 
123 //------------------------------------------------------------------------------------------------------------------------------------------
124 
125 void SlidingConePfoMopUpAlgorithm::GetClusterMergeMap(const Vertex *const pVertex, const ClusterVector &clusters3D,
126  const ClusterToPfoMap &clusterToPfoMap, ClusterMergeMap &clusterMergeMap) const
127 {
128  VertexAssociationMap vertexAssociationMap;
129  const float pitchU{LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_U)};
130  const float pitchV{LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_V)};
131  const float pitchW{LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_W)};
132  const float pitchMax{std::max({pitchU, pitchV, pitchW})};
133 
134  for (const Cluster *const pShowerCluster : clusters3D)
135  {
136  if ((pShowerCluster->GetNCaloHits() < m_minHitsToConsider3DShower) || !LArPfoHelper::IsShower(clusterToPfoMap.at(pShowerCluster)))
137  continue;
138 
139  float coneLength(0.f);
140  SimpleConeList simpleConeList;
141  bool isShowerVertexAssociated(false);
142 
143  try
144  {
145  float layerPitch{0.f};
146  const HitType view{LArClusterHelper::GetClusterHitType(pShowerCluster)};
147  if (view == TPC_VIEW_U || view == TPC_VIEW_V || view == TPC_VIEW_W)
148  layerPitch = LArGeometryHelper::GetWirePitch(this->GetPandora(), view);
149  else
150  layerPitch = pitchMax;
151 
152  const ThreeDSlidingConeFitResult slidingConeFitResult3D(pShowerCluster, m_halfWindowLayers, layerPitch);
153 
154  const CartesianVector &minLayerPosition(slidingConeFitResult3D.GetSlidingFitResult().GetGlobalMinLayerPosition());
155  const CartesianVector &maxLayerPosition(slidingConeFitResult3D.GetSlidingFitResult().GetGlobalMaxLayerPosition());
156  coneLength = std::min(m_coneLengthMultiplier * (maxLayerPosition - minLayerPosition).GetMagnitude(), m_maxConeLength);
157 
158  const float vertexToMinLayer(!pVertex ? 0.f : (pVertex->GetPosition() - minLayerPosition).GetMagnitude());
159  const float vertexToMaxLayer(!pVertex ? 0.f : (pVertex->GetPosition() - maxLayerPosition).GetMagnitude());
160  const ConeSelection coneSelection(!pVertex ? CONE_BOTH_DIRECTIONS
161  : (vertexToMaxLayer > vertexToMinLayer) ? CONE_FORWARD_ONLY
163 
164  slidingConeFitResult3D.GetSimpleConeList(m_nConeFitLayers, m_nConeFits, coneSelection, simpleConeList, m_coneTanHalfAngle1, m_legacyMode);
165  isShowerVertexAssociated =
166  this->IsVertexAssociated(pShowerCluster, pVertex, vertexAssociationMap, &(slidingConeFitResult3D.GetSlidingFitResult()));
167  }
168  catch (const StatusCodeException &)
169  {
170  continue;
171  }
172 
173  for (const Cluster *const pNearbyCluster : clusters3D)
174  {
175  if (pNearbyCluster == pShowerCluster)
176  continue;
177 
178  ClusterMerge bestClusterMerge(nullptr, 0.f, 0.f);
179 
180  for (const SimpleCone &simpleCone : simpleConeList)
181  {
182  const float boundedFraction1(simpleCone.GetBoundedHitFraction(pNearbyCluster, coneLength, m_coneTanHalfAngle1));
183  const float boundedFraction2(simpleCone.GetBoundedHitFraction(pNearbyCluster, coneLength, m_coneTanHalfAngle2));
184  const ClusterMerge clusterMerge(pShowerCluster, boundedFraction1, boundedFraction2);
185 
186  if (clusterMerge < bestClusterMerge)
187  bestClusterMerge = clusterMerge;
188  }
189 
190  if (isShowerVertexAssociated && this->IsVertexAssociated(pNearbyCluster, pVertex, vertexAssociationMap))
191  continue;
192 
193  if (bestClusterMerge.GetParentCluster() && (bestClusterMerge.GetBoundedFraction1() > m_coneBoundedFraction1) &&
194  (bestClusterMerge.GetBoundedFraction2() > m_coneBoundedFraction2))
195  clusterMergeMap[pNearbyCluster].push_back(bestClusterMerge);
196  }
197  }
198 
199  for (ClusterMergeMap::value_type &mapEntry : clusterMergeMap)
200  std::sort(mapEntry.second.begin(), mapEntry.second.end());
201 }
202 
203 //------------------------------------------------------------------------------------------------------------------------------------------
204 
205 bool SlidingConePfoMopUpAlgorithm::IsVertexAssociated(const Cluster *const pCluster, const Vertex *const pVertex,
206  VertexAssociationMap &vertexAssociationMap, const ThreeDSlidingFitResult *const pSlidingFitResult) const
207 {
208  if (!pVertex)
209  return false;
210 
211  VertexAssociationMap::const_iterator iter = vertexAssociationMap.find(pCluster);
212 
213  if (vertexAssociationMap.end() != iter)
214  return iter->second;
215 
216  const bool isVertexAssociated(this->IsVertexAssociated(pCluster, pVertex->GetPosition(), pSlidingFitResult));
217  (void)vertexAssociationMap.insert(VertexAssociationMap::value_type(pCluster, isVertexAssociated));
218 
219  return isVertexAssociated;
220 }
221 
222 //------------------------------------------------------------------------------------------------------------------------------------------
223 
225  const Cluster *const pCluster, const CartesianVector &vertexPosition, const ThreeDSlidingFitResult *const pSlidingFitResult) const
226 {
227  const float pitchU{LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_U)};
228  const float pitchV{LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_V)};
229  const float pitchW{LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_W)};
230  const float pitchMax{std::max({pitchU, pitchV, pitchW})};
231 
232  try
233  {
234  float layerPitch{0.f};
235  const HitType view{LArClusterHelper::GetClusterHitType(pCluster)};
236  if (view == TPC_VIEW_U || view == TPC_VIEW_V || view == TPC_VIEW_W)
237  layerPitch = LArGeometryHelper::GetWirePitch(this->GetPandora(), view);
238  else
239  layerPitch = pitchMax;
240 
241  const LArPointingCluster pointingCluster(
242  pSlidingFitResult ? LArPointingCluster(*pSlidingFitResult) : LArPointingCluster(pCluster, m_halfWindowLayers, layerPitch));
243 
244  const bool useInner((pointingCluster.GetInnerVertex().GetPosition() - vertexPosition).GetMagnitudeSquared() <
245  (pointingCluster.GetOuterVertex().GetPosition() - vertexPosition).GetMagnitudeSquared());
246 
247  const LArPointingCluster::Vertex &daughterVertex(useInner ? pointingCluster.GetInnerVertex() : pointingCluster.GetOuterVertex());
249  }
250  catch (const StatusCodeException &)
251  {
252  }
253 
254  return false;
255 }
256 
257 //------------------------------------------------------------------------------------------------------------------------------------------
258 
259 bool SlidingConePfoMopUpAlgorithm::MakePfoMerges(const ClusterToPfoMap &clusterToPfoMap, const ClusterMergeMap &clusterMergeMap) const
260 {
261  ClusterVector daughterClusters;
262  for (const ClusterMergeMap::value_type &mapEntry : clusterMergeMap)
263  daughterClusters.push_back(mapEntry.first);
264  std::sort(daughterClusters.begin(), daughterClusters.end(), LArClusterHelper::SortByNHits);
265 
266  bool pfosMerged(false);
267  ClusterReplacementMap clusterReplacementMap;
268 
269  for (ClusterVector::const_reverse_iterator rIter = daughterClusters.rbegin(), rIterEnd = daughterClusters.rend(); rIter != rIterEnd; ++rIter)
270  {
271  const Cluster *const pDaughterCluster(*rIter);
272 
273  if (clusterReplacementMap.count(pDaughterCluster))
274  throw StatusCodeException(STATUS_CODE_FAILURE);
275 
276  const Cluster *pParentCluster(clusterMergeMap.at(pDaughterCluster).at(0).GetParentCluster());
277 
278  if (clusterReplacementMap.count(pParentCluster))
279  pParentCluster = clusterReplacementMap.at(pParentCluster);
280 
281  // ATTN Sign there was a reciprocal relationship in the cluster merge map (already actioned once)
282  if (pDaughterCluster == pParentCluster)
283  continue;
284 
285  // Key book-keeping on clusters and use cluster->pfo lookup
286  const Pfo *const pDaughterPfo(clusterToPfoMap.at(pDaughterCluster));
287  const Pfo *const pParentPfo(clusterToPfoMap.at(pParentCluster));
288  this->MergeAndDeletePfos(pParentPfo, pDaughterPfo);
289  pfosMerged = true;
290 
291  // Simple/placeholder book-keeping for reciprocal relationships and progressive merges
292  clusterReplacementMap[pDaughterCluster] = pParentCluster;
293 
294  for (ClusterReplacementMap::value_type &mapEntry : clusterReplacementMap)
295  {
296  if (pDaughterCluster == mapEntry.second)
297  mapEntry.second = pParentCluster;
298  }
299  }
300 
301  return pfosMerged;
302 }
303 
304 //------------------------------------------------------------------------------------------------------------------------------------------
305 //------------------------------------------------------------------------------------------------------------------------------------------
306 
308 {
309  if (!this->GetParentCluster() && !rhs.GetParentCluster())
310  return false;
311 
312  if (this->GetParentCluster() && !rhs.GetParentCluster())
313  return true;
314 
315  if (!this->GetParentCluster() && rhs.GetParentCluster())
316  return false;
317 
318  if (std::fabs(this->GetBoundedFraction1() - rhs.GetBoundedFraction1()) > std::numeric_limits<float>::epsilon())
319  return (this->GetBoundedFraction1() > rhs.GetBoundedFraction1());
320 
321  if (std::fabs(this->GetBoundedFraction2() - rhs.GetBoundedFraction2()) > std::numeric_limits<float>::epsilon())
322  return (this->GetBoundedFraction2() > rhs.GetBoundedFraction2());
323 
325 }
326 
327 //------------------------------------------------------------------------------------------------------------------------------------------
328 //------------------------------------------------------------------------------------------------------------------------------------------
329 
330 StatusCode SlidingConePfoMopUpAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
331 {
332  PANDORA_RETURN_RESULT_IF_AND_IF(
333  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadVectorOfValues(xmlHandle, "InputPfoListNames", m_inputPfoListNames));
334 
335  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "UseVertex", m_useVertex));
336 
337  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "LegacyMode", m_legacyMode));
338 
339  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxIterations", m_maxIterations));
340 
341  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
342  XmlHelper::ReadValue(xmlHandle, "MaxHitsToConsider3DTrack", m_maxHitsToConsider3DTrack));
343 
344  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
345  XmlHelper::ReadValue(xmlHandle, "MinHitsToConsider3DShower", m_minHitsToConsider3DShower));
346 
347  PANDORA_RETURN_RESULT_IF_AND_IF(
348  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitHalfWindow", m_halfWindowLayers));
349 
350  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "NConeFitLayers", m_nConeFitLayers));
351 
352  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "NConeFits", m_nConeFits));
353 
354  PANDORA_RETURN_RESULT_IF_AND_IF(
355  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ConeLengthMultiplier", m_coneLengthMultiplier));
356 
357  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxConeLength", m_maxConeLength));
358 
359  PANDORA_RETURN_RESULT_IF_AND_IF(
360  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ConeTanHalfAngle1", m_coneTanHalfAngle1));
361 
362  PANDORA_RETURN_RESULT_IF_AND_IF(
363  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ConeBoundedFraction1", m_coneBoundedFraction1));
364 
365  PANDORA_RETURN_RESULT_IF_AND_IF(
366  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ConeTanHalfAngle2", m_coneTanHalfAngle2));
367 
368  PANDORA_RETURN_RESULT_IF_AND_IF(
369  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ConeBoundedFraction2", m_coneBoundedFraction2));
370 
371  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
372  XmlHelper::ReadValue(xmlHandle, "MinVertexLongitudinalDistance", m_minVertexLongitudinalDistance));
373 
374  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
375  XmlHelper::ReadValue(xmlHandle, "MaxVertexTransverseDistance", m_maxVertexTransverseDistance));
376 
378 
379  return PfoMopUpBaseAlgorithm::ReadSettings(xmlHandle);
380 }
381 
382 } // namespace lar_content
std::unordered_map< const pandora::Cluster *, const pandora::Cluster * > ClusterReplacementMap
float GetBoundedFraction2() const
Get the bounded fraction for algorithm-specified cone angle 2.
void GetClusterMergeMap(const pandora::Vertex *const pVertex, const pandora::ClusterVector &clusters3D, const ClusterToPfoMap &clusterToPfoMap, ClusterMergeMap &clusterMergeMap) const
Get the cluster merge map describing all potential 3d cluster merges.
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_coneBoundedFraction2
The minimum cluster bounded fraction for association 2.
void GetInteractionVertex(const pandora::Vertex *&pVertex) const
Get the neutrino interaction vertex if it is available and if the algorithm is configured to do so...
Header file for the pfo helper class.
float m_maxConeLength
The maximum allowed cone length to use when calculating bounded cluster fractions.
float m_maxVertexTransverseDistance
Vertex association check: max transverse distance cut.
std::unordered_map< const pandora::Cluster *, const pandora::ParticleFlowObject * > ClusterToPfoMap
float m_coneLengthMultiplier
The cone length multiplier to use when calculating bounded cluster fractions.
std::vector< SimpleCone > SimpleConeList
pandora::StringVector m_daughterListNames
The list of potential daughter object list names.
void GetSimpleConeList(const unsigned int nLayersForConeFit, const unsigned int nCones, const ConeSelection coneSelection, SimpleConeList &simpleConeList, const float tanHalfAngle=0.5f, const bool legacyMode=true) const
Get the list of simple cones fitted to the three dimensional cluster.
intermediate_table::const_iterator const_iterator
bool MakePfoMerges(const ClusterToPfoMap &clusterToPfoMap, const ClusterMergeMap &clusterMergeMap) const
Make pfo merges based on the provided cluster merge map.
const ThreeDSlidingFitResult & GetSlidingFitResult() const
Get the sliding fit result for the full cluster.
LArPointingCluster class.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
void GetThreeDClusters(pandora::ClusterVector &clusters3D, ClusterToPfoMap &clusterToPfoMap) const
Get all 3d clusters contained in the input pfo lists and a mapping from clusters to pfos...
static bool IsTrack(const pandora::ParticleFlowObject *const pPfo)
Return track flag based on Pfo Particle ID.
bool m_useVertex
Whether to use the interaction vertex to select useful cone directions.
Header file for the lar three dimensional sliding cone fit result class.
float GetBoundedFraction1() const
Get the bounded fraction for algorithm-specified cone angle 1.
TFile f
Definition: plotHisto.C:6
bool IsVertexAssociated(const pandora::Cluster *const pCluster, const pandora::Vertex *const pVertex, VertexAssociationMap &vertexAssociationMap, const ThreeDSlidingFitResult *const pSlidingFitResult=nullptr) const
Whether a 3D cluster is nodally associated with a provided vertex.
Header file for the geometry helper class.
bool m_legacyMode
Whether to use the legacy cone generation.
float m_minVertexLongitudinalDistance
Vertex association check: min longitudinal distance cut.
static bool IsShower(const pandora::ParticleFlowObject *const pPfo)
Return shower flag based on Pfo Particle ID.
unsigned int m_nConeFitLayers
The number of layers over which to sum fitted direction to obtain cone fit.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Header file for the cluster helper class.
const Vertex & GetOuterVertex() const
Get the outer vertex.
unsigned int m_maxHitsToConsider3DTrack
The maximum number of hits in a 3d track cluster to warrant inclusion in algorithm.
const Vertex & GetInnerVertex() const
Get the inner vertex.
float m_coneTanHalfAngle1
The cone tan half angle to use when calculating bounded cluster fractions 1.
pandora::StringVector m_inputPfoListNames
The input pfo list names.
static float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
Header file for the sliding cone pfo mop up algorithm class.
static const pandora::Cluster * GetParentCluster(const pandora::ClusterList &clusterList, const pandora::HitType hitType)
Select the parent cluster (same hit type and most hits) using a provided cluster list and hit type...
static void GetThreeDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 3D clusters from an input pfo.
const pandora::CartesianVector & GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
float m_coneBoundedFraction1
The minimum cluster bounded fraction for association 1.
std::unordered_map< const pandora::Cluster *, bool > VertexAssociationMap
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
HitType
Definition: HitType.h:12
unsigned int m_maxIterations
The maximum allowed number of algorithm iterations.
virtual void MergeAndDeletePfos(const pandora::ParticleFlowObject *const pPfoToEnlarge, const pandora::ParticleFlowObject *const pPfoToDelete) const
Merge and delete a pair of pfos, with a specific set of conventions for cluster merging, vertex use, etc.
ConeSelection
ConeSelection enum.
unsigned int m_minHitsToConsider3DShower
The minimum number of hits in a 3d shower cluster to attempt cone fits.
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
Definition: ModuleGraph.h:25
std::vector< art::Ptr< recob::Cluster > > ClusterVector
bool operator<(const ClusterMerge &rhs) const
operator <
unsigned int m_nConeFits
The number of cone fits to perform, spread roughly uniformly along the shower length.
std::unordered_map< const pandora::Cluster *, ClusterMergeList > ClusterMergeMap
const pandora::Cluster * GetParentCluster() const
Get the address of the candidate parent (shower) cluster.
std::list< Vertex > VertexList
Definition: DCEL.h:169
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
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.
float m_coneTanHalfAngle2
The cone tan half angle to use when calculating bounded cluster fractions 2.
unsigned int m_halfWindowLayers
The number of layers to use for half-window of sliding fit.
const pandora::CartesianVector & GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.