TracksCrossingGapsTool.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArThreeDReco/LArTransverseTrackMatching/TracksCrossingGapsTool.cc
3  *
4  * @brief Implementation of the long tracks tool class.
5  *
6  * $Log: $
7  */
8 
9 #include "Pandora/AlgorithmHeaders.h"
10 
13 
16 
17 using namespace pandora;
18 
19 namespace lar_content
20 {
21 
22 TracksCrossingGapsTool::TracksCrossingGapsTool() :
23  m_minMatchedFraction(0.5f),
24  m_minMatchedSamplingPoints(10),
25  m_minXOverlapFraction(0.9f),
26  m_minMatchedSamplingPointRatio(2),
27  m_maxGapTolerance(2.f),
28  m_sampleStepSize(0.5f),
29  m_maxAngleRatio(2)
30 {
31 }
32 
33 //------------------------------------------------------------------------------------------------------------------------------------------
34 
36 {
37  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
38  std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
39 
40  if (PandoraContentApi::GetGeometry(*pAlgorithm)->GetDetectorGapList().empty())
41  return false;
42 
43  ProtoParticleVector protoParticleVector;
44  this->FindTracks(pAlgorithm, overlapTensor, protoParticleVector);
45 
46  const bool particlesMade(pAlgorithm->CreateThreeDParticles(protoParticleVector));
47  return particlesMade;
48 }
49 
50 //------------------------------------------------------------------------------------------------------------------------------------------
51 
53  ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const TensorType &overlapTensor, ProtoParticleVector &protoParticleVector) const
54 {
55  ClusterSet usedClusters;
56  ClusterVector sortedKeyClusters;
57  overlapTensor.GetSortedKeyClusters(sortedKeyClusters);
58 
59  for (const Cluster *const pKeyCluster : sortedKeyClusters)
60  {
61  if (!pKeyCluster->IsAvailable())
62  continue;
63 
64  unsigned int nU(0), nV(0), nW(0);
65  TensorType::ElementList elementList;
66  overlapTensor.GetConnectedElements(pKeyCluster, true, elementList, nU, nV, nW);
67 
68  IteratorList iteratorList;
69  this->SelectElements(pAlgorithm, elementList, usedClusters, iteratorList);
70 
71  // Check that elements are not directly connected and are significantly longer than any other directly connected elements
72  for (IteratorList::const_iterator iIter = iteratorList.begin(), iIterEnd = iteratorList.end(); iIter != iIterEnd; ++iIter)
73  {
74  if (LongTracksTool::HasLongDirectConnections(iIter, iteratorList))
75  continue;
76 
78  continue;
79 
80  ProtoParticle protoParticle;
81  protoParticle.m_clusterList.push_back((*iIter)->GetClusterU());
82  protoParticle.m_clusterList.push_back((*iIter)->GetClusterV());
83  protoParticle.m_clusterList.push_back((*iIter)->GetClusterW());
84  protoParticleVector.push_back(protoParticle);
85 
86  usedClusters.insert((*iIter)->GetClusterU());
87  usedClusters.insert((*iIter)->GetClusterV());
88  usedClusters.insert((*iIter)->GetClusterW());
89  }
90  }
91 }
92 
93 //------------------------------------------------------------------------------------------------------------------------------------------
94 
96  const TensorType::ElementList &elementList, const pandora::ClusterSet &usedClusters, IteratorList &iteratorList) const
97 {
98  for (TensorType::ElementList::const_iterator eIter = elementList.begin(); eIter != elementList.end(); ++eIter)
99  {
100  if (usedClusters.count(eIter->GetClusterU()) || usedClusters.count(eIter->GetClusterV()) || usedClusters.count(eIter->GetClusterW()))
101  continue;
102 
103  if (eIter->GetOverlapResult().GetMatchedFraction() < m_minMatchedFraction)
104  continue;
105 
106  if (eIter->GetOverlapResult().GetNMatchedSamplingPoints() < m_minMatchedSamplingPoints)
107  continue;
108 
109  const XOverlap &xOverlap(eIter->GetOverlapResult().GetXOverlap());
110 
111  if (xOverlap.GetXOverlapSpan() < std::numeric_limits<float>::epsilon())
112  continue;
113 
114  // Calculate effective overlap fraction, including the information about gaps
115  float xOverlapFractionU(0.f), xOverlapFractionV(0.f), xOverlapFractionW(0.f);
116  this->CalculateEffectiveOverlapFractions(pAlgorithm, *eIter, xOverlapFractionU, xOverlapFractionV, xOverlapFractionW);
117 
118  if ((xOverlap.GetXSpanU() > std::numeric_limits<float>::epsilon()) && (xOverlapFractionU > m_minXOverlapFraction) &&
119  (xOverlap.GetXSpanV() > std::numeric_limits<float>::epsilon()) && (xOverlapFractionV > m_minXOverlapFraction) &&
120  (xOverlap.GetXSpanW() > std::numeric_limits<float>::epsilon()) && (xOverlapFractionW > m_minXOverlapFraction))
121  {
122  iteratorList.push_back(eIter);
123  }
124  }
125 }
126 
127 //------------------------------------------------------------------------------------------------------------------------------------------
128 
130  const TensorType::Element &element, float &xOverlapFractionU, float &xOverlapFractionV, float &xOverlapFractionW) const
131 {
132  float xMinEffU(element.GetOverlapResult().GetXOverlap().GetUMinX()), xMaxEffU(element.GetOverlapResult().GetXOverlap().GetUMaxX());
133  float xMinEffV(element.GetOverlapResult().GetXOverlap().GetVMinX()), xMaxEffV(element.GetOverlapResult().GetXOverlap().GetVMaxX());
134  float xMinEffW(element.GetOverlapResult().GetXOverlap().GetWMinX()), xMaxEffW(element.GetOverlapResult().GetXOverlap().GetWMaxX());
135  this->CalculateEffectiveOverlapSpan(pAlgorithm, element, xMinEffU, xMaxEffU, xMinEffV, xMaxEffV, xMinEffW, xMaxEffW);
136 
137  const float effectiveXSpanU(xMaxEffU - xMinEffU), effectiveXSpanV(xMaxEffV - xMinEffV), effectiveXSpanW(xMaxEffW - xMinEffW);
138  const float minCommonX(std::max(xMinEffU, std::max(xMinEffV, xMinEffW)));
139  const float maxCommonX(std::min(xMaxEffU, std::min(xMaxEffV, xMaxEffW)));
140  const float effectiveXOverlapSpan(maxCommonX - minCommonX);
141 
142  // TODO check that this shouldn't be greater than 1 any more
143  xOverlapFractionU = effectiveXSpanU > 0.f ? std::min(1.f, (effectiveXOverlapSpan / effectiveXSpanU)) : 0.f;
144  xOverlapFractionV = effectiveXSpanV > 0.f ? std::min(1.f, (effectiveXOverlapSpan / effectiveXSpanV)) : 0.f;
145  xOverlapFractionW = effectiveXSpanW > 0.f ? std::min(1.f, (effectiveXOverlapSpan / effectiveXSpanW)) : 0.f;
146 }
147 
148 //------------------------------------------------------------------------------------------------------------------------------------------
149 
151  const TensorType::Element &element, float &xMinEffU, float &xMaxEffU, float &xMinEffV, float &xMaxEffV, float &xMinEffW, float &xMaxEffW) const
152 {
153  const float xMinAll(std::min(xMinEffU, std::min(xMinEffV, xMinEffW)));
154  const float xMaxAll(std::max(xMaxEffU, std::max(xMaxEffV, xMaxEffW)));
155  const float minCommonX(std::max(xMinEffU, std::max(xMinEffV, xMinEffW)));
156  const float maxCommonX(std::min(xMaxEffU, std::min(xMaxEffV, xMaxEffW)));
157 
158  float dxUmin(0.f), dxVmin(0.f), dxWmin(0.f);
159  float dxUmax(0.f), dxVmax(0.f), dxWmax(0.f);
160 
161  // ATTN break out of loops to to avoid finding a non-related gap far from cluster itself
162  const int nSamplingPointsLeft(1 + static_cast<int>((minCommonX - xMinAll) / m_sampleStepSize));
163  const int nSamplingPointsRight(1 + static_cast<int>((xMaxAll - maxCommonX) / m_sampleStepSize));
164 
165  for (int iSample = 1; iSample <= nSamplingPointsLeft; ++iSample)
166  {
167  bool gapInU(false), gapInV(false), gapInW(false);
168  const float xSample(std::max(xMinAll, minCommonX - static_cast<float>(iSample) * m_sampleStepSize));
169 
170  if (!this->PassesGapChecks(pAlgorithm, element, xSample, gapInU, gapInV, gapInW))
171  break;
172 
173  if (gapInU)
174  dxUmin = xMinEffU - xSample;
175  if (gapInV)
176  dxVmin = xMinEffV - xSample;
177  if (gapInW)
178  dxWmin = xMinEffW - xSample;
179  }
180 
181  for (int iSample = 1; iSample <= nSamplingPointsRight; ++iSample)
182  {
183  bool gapInU(false), gapInV(false), gapInW(false);
184  const float xSample(std::min(xMaxAll, maxCommonX + static_cast<float>(iSample) * m_sampleStepSize));
185 
186  if (!this->PassesGapChecks(pAlgorithm, element, xSample, gapInU, gapInV, gapInW))
187  break;
188 
189  if (gapInU)
190  dxUmax = xSample - xMaxEffU;
191  if (gapInV)
192  dxVmax = xSample - xMaxEffV;
193  if (gapInW)
194  dxWmax = xSample - xMaxEffW;
195  }
196 
197  xMinEffU -= dxUmin;
198  xMaxEffU += dxUmax;
199  xMinEffV -= dxVmin;
200  xMaxEffV += dxVmax;
201  xMinEffW -= dxWmin;
202  xMaxEffW += dxWmax;
203 }
204 
205 //------------------------------------------------------------------------------------------------------------------------------------------
206 
207 bool TracksCrossingGapsTool::PassesGapChecks(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const TensorType::Element &element,
208  const float xSample, bool &gapInU, bool &gapInV, bool &gapInW) const
209 {
210  const TwoDSlidingFitResult &slidingFitResultU(pAlgorithm->GetCachedSlidingFitResult(element.GetClusterU()));
211  const TwoDSlidingFitResult &slidingFitResultV(pAlgorithm->GetCachedSlidingFitResult(element.GetClusterV()));
212  const TwoDSlidingFitResult &slidingFitResultW(pAlgorithm->GetCachedSlidingFitResult(element.GetClusterW()));
213 
214  // If we have access to the global x position in all three clusters, there are no gaps involved (or cluster already spans small gaps)
215  CartesianVector fitUPosition(0.f, 0.f, 0.f), fitVPosition(0.f, 0.f, 0.f), fitWPosition(0.f, 0.f, 0.f);
216  const StatusCode statusCodeU(slidingFitResultU.GetGlobalFitPositionAtX(xSample, fitUPosition));
217  const StatusCode statusCodeV(slidingFitResultV.GetGlobalFitPositionAtX(xSample, fitVPosition));
218  const StatusCode statusCodeW(slidingFitResultW.GetGlobalFitPositionAtX(xSample, fitWPosition));
219 
220  if ((STATUS_CODE_SUCCESS == statusCodeU) && (STATUS_CODE_SUCCESS == statusCodeV) && (STATUS_CODE_SUCCESS == statusCodeW))
221  return false;
222 
223  try
224  {
225  // Note: argument order important - initially assume first view has a gap, but inside CheckXPositionInGap do check other two views
226  if ((STATUS_CODE_SUCCESS != statusCodeU) && (!this->IsEndOfCluster(xSample, slidingFitResultU)))
227  return this->CheckXPositionInGap(xSample, slidingFitResultU, slidingFitResultV, slidingFitResultW, gapInU, gapInV, gapInW);
228 
229  if ((STATUS_CODE_SUCCESS != statusCodeV) && (!this->IsEndOfCluster(xSample, slidingFitResultV)))
230  return this->CheckXPositionInGap(xSample, slidingFitResultV, slidingFitResultU, slidingFitResultW, gapInV, gapInU, gapInW);
231 
232  if ((STATUS_CODE_SUCCESS != statusCodeW) && (!this->IsEndOfCluster(xSample, slidingFitResultW)))
233  return this->CheckXPositionInGap(xSample, slidingFitResultW, slidingFitResultU, slidingFitResultV, gapInW, gapInU, gapInV);
234  }
235  catch (const StatusCodeException &statusCodeException)
236  {
237  }
238 
239  return false;
240 }
241 
242 //------------------------------------------------------------------------------------------------------------------------------------------
243 
244 bool TracksCrossingGapsTool::CheckXPositionInGap(const float xSample, const TwoDSlidingFitResult &slidingFitResult1,
245  const TwoDSlidingFitResult &slidingFitResult2, const TwoDSlidingFitResult &slidingFitResult3, bool &gapIn1, bool &gapIn2, bool &gapIn3) const
246 {
247  CartesianVector fitPosition2(0.f, 0.f, 0.f), fitPosition3(0.f, 0.f, 0.f);
248 
249  // If we have the global position at X from the two other clusters, calculate projection in the first view and check for gaps
250  if ((STATUS_CODE_SUCCESS == slidingFitResult2.GetGlobalFitPositionAtX(xSample, fitPosition2)) &&
251  (STATUS_CODE_SUCCESS == slidingFitResult3.GetGlobalFitPositionAtX(xSample, fitPosition3)))
252  {
253  const HitType hitType1(LArClusterHelper::GetClusterHitType(slidingFitResult1.GetCluster()));
254  const HitType hitType2(LArClusterHelper::GetClusterHitType(slidingFitResult2.GetCluster()));
255  const HitType hitType3(LArClusterHelper::GetClusterHitType(slidingFitResult3.GetCluster()));
256 
257  const float zSample(LArGeometryHelper::MergeTwoPositions(this->GetPandora(), hitType2, hitType3, fitPosition2.GetZ(), fitPosition3.GetZ()));
258  const CartesianVector samplingPoint(xSample, 0.f, zSample);
259  return LArGeometryHelper::IsInGap(this->GetPandora(), CartesianVector(xSample, 0.f, zSample), hitType1, m_maxGapTolerance);
260  }
261 
262  // ATTN Only safe to return here (for efficiency) because gapIn2 and gapIn3 values aren't used by calling function if we return false
263  gapIn1 = LArGeometryHelper::IsXSamplingPointInGap(this->GetPandora(), xSample, slidingFitResult1, m_sampleStepSize);
264 
265  if (!gapIn1)
266  return false;
267 
268  // If we dont have a projection at x in the other two clusters, check if they are in gaps or at the end of the cluster
269  if ((STATUS_CODE_SUCCESS != slidingFitResult2.GetGlobalFitPositionAtX(xSample, fitPosition2)) &&
270  (STATUS_CODE_SUCCESS != slidingFitResult3.GetGlobalFitPositionAtX(xSample, fitPosition3)))
271  {
272  const bool endIn2(this->IsEndOfCluster(xSample, slidingFitResult2));
273  const bool endIn3(this->IsEndOfCluster(xSample, slidingFitResult3));
274 
275  if (!endIn2)
276  gapIn2 = LArGeometryHelper::IsXSamplingPointInGap(this->GetPandora(), xSample, slidingFitResult2, m_sampleStepSize);
277 
278  if (!endIn3)
279  gapIn3 = LArGeometryHelper::IsXSamplingPointInGap(this->GetPandora(), xSample, slidingFitResult3, m_sampleStepSize);
280 
281  return ((gapIn2 && endIn3) || (gapIn3 && endIn2) || (endIn2 && endIn3));
282  }
283 
284  // Finally, check whether there is a second gap involved
285  if (STATUS_CODE_SUCCESS != slidingFitResult2.GetGlobalFitPositionAtX(xSample, fitPosition2))
286  {
287  gapIn2 = LArGeometryHelper::IsXSamplingPointInGap(this->GetPandora(), xSample, slidingFitResult2, m_sampleStepSize);
288  return (gapIn2 || this->IsEndOfCluster(xSample, slidingFitResult2));
289  }
290  else
291  {
292  gapIn3 = LArGeometryHelper::IsXSamplingPointInGap(this->GetPandora(), xSample, slidingFitResult3, m_sampleStepSize);
293  return (gapIn3 || this->IsEndOfCluster(xSample, slidingFitResult3));
294  }
295 }
296 
297 //------------------------------------------------------------------------------------------------------------------------------------------
298 
299 bool TracksCrossingGapsTool::IsEndOfCluster(const float xSample, const TwoDSlidingFitResult &slidingFitResult) const
300 {
301  return ((std::fabs(slidingFitResult.GetGlobalMinLayerPosition().GetX() - xSample) < slidingFitResult.GetLayerPitch()) ||
302  (std::fabs(slidingFitResult.GetGlobalMaxLayerPosition().GetX() - xSample) < slidingFitResult.GetLayerPitch()));
303 }
304 
305 //------------------------------------------------------------------------------------------------------------------------------------------
306 
307 StatusCode TracksCrossingGapsTool::ReadSettings(const TiXmlHandle xmlHandle)
308 {
309  PANDORA_RETURN_RESULT_IF_AND_IF(
310  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinMatchedFraction", m_minMatchedFraction));
311 
312  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
313  XmlHelper::ReadValue(xmlHandle, "MinMatchedSamplingPoints", m_minMatchedSamplingPoints));
314 
315  PANDORA_RETURN_RESULT_IF_AND_IF(
316  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinXOverlapFraction", m_minXOverlapFraction));
317 
318  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
319  XmlHelper::ReadValue(xmlHandle, "MinMatchedSamplingPointRatio", m_minMatchedSamplingPointRatio));
320 
321  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxGapTolerance", m_maxGapTolerance));
322 
323  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SampleStepSize", m_sampleStepSize));
324 
325  if (m_sampleStepSize < std::numeric_limits<float>::epsilon())
326  {
327  std::cout << "TracksCrossingGapsTool: Invalid value for SampleStepSize " << m_sampleStepSize << std::endl;
328  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
329  }
330 
331  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxAngleRatio", m_maxAngleRatio));
332 
333  return STATUS_CODE_SUCCESS;
334 }
335 
336 } // namespace lar_content
unsigned int m_minMatchedSamplingPoints
The min number of matched sampling points for particle creation.
std::vector< ProtoParticle > ProtoParticleVector
void CalculateEffectiveOverlapSpan(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const TensorType::Element &element, float &xMinEffU, float &xMaxEffU, float &xMinEffV, float &xMaxEffV, float &xMinEffW, float &xMaxEffW) const
Calculate the effective overlap span given a set of clusters, taking gaps into account.
void CalculateEffectiveOverlapFractions(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const TensorType::Element &element, float &xOverlapFractionU, float &xOverlapFractionV, float &xOverlapFractionW) const
Calculate the effective overlap fractions given a set of clusters, taking gaps into account...
float m_maxGapTolerance
The max gap tolerance.
std::vector< TensorType::ElementList::const_iterator > IteratorList
enum cvn::HType HitType
static bool IsLongerThanDirectConnections(IteratorList::const_iterator iIter, const TensorType::ElementList &elementList, const unsigned int minMatchedSamplingPointRatio, const pandora::ClusterSet &usedClusters)
Whether a long element is significantly longer that other elements with which it shares a cluster...
const TwoDSlidingFitResult & GetCachedSlidingFitResult(const pandora::Cluster *const pCluster) const
Get a sliding fit result from the algorithm cache.
float m_minXOverlapFraction
The min x overlap fraction (in each view) for particle creation.
void GetConnectedElements(const pandora::Cluster *const pCluster, const bool ignoreUnavailable, ElementList &elementList) const
Get a list of elements connected to a specified cluster.
void FindTracks(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const TensorType &overlapTensor, ProtoParticleVector &protoParticleVector) const
Find tracks crossing gaps, with unambiguous connection but poor overlap due to gaps.
intermediate_table::const_iterator const_iterator
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
static bool IsInGap(const pandora::Pandora &pandora, const pandora::CartesianVector &testPoint2D, const pandora::HitType hitType, const float gapTolerance=0.f)
Whether a 2D test point lies in a registered gap with the associated hit type.
void SelectElements(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const TensorType::ElementList &elementList, const pandora::ClusterSet &usedClusters, IteratorList &iteratorList) const
Select a list of track-like elements crossing a gap in one or more views from a set of connected tens...
Header file for the geometry helper class.
unsigned int m_minMatchedSamplingPointRatio
The min ratio between 1st and 2nd highest msps for simple ambiguity resolution.
bool CheckXPositionInGap(const float xSample, const TwoDSlidingFitResult &slidingFitResult1, const TwoDSlidingFitResult &slidingFitResult2, const TwoDSlidingFitResult &slidingFitResult3, bool &gapIn1, bool &gapIn2, bool &gapIn3) const
Check individually each cluster where a gap might be present.
bool IsEndOfCluster(const float xSample, const TwoDSlidingFitResult &slidingFitResult) const
Check whether a x position is at the end of the cluster.
Header file for the cluster helper class.
float m_minMatchedFraction
The min matched sampling point fraction for particle creation.
bool Run(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, TensorType &overlapTensor)
Run the algorithm tool.
pandora::ClusterList m_clusterList
List of 2D clusters in a 3D proto particle.
static float MergeTwoPositions(const pandora::Pandora &pandora, const pandora::HitType view1, const pandora::HitType view2, const float position1, const float position2)
Merge two views (U,V) to give a third view (Z).
float GetLayerPitch() const
Get the layer pitch, units cm.
pandora::CartesianVector GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.
Header file for the long tracks tool class.
static int max(int a, int b)
void GetSortedKeyClusters(pandora::ClusterVector &sortedKeyClusters) const
Get a sorted vector of key clusters (U clusters with current implementation)
bool PassesGapChecks(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const TensorType::Element &element, const float xSample, bool &gapInU, bool &gapInV, bool &gapInW) const
Check whether there is any gap in the three U-V-W clusters combination.
static bool IsXSamplingPointInGap(const pandora::Pandora &pandora, const float xSample, const TwoDSlidingFitResult &slidingFitResult, const float gapTolerance=0.f)
Whether there is a gap in a cluster (described via its sliding fit result) at a specified x sampling ...
const pandora::Cluster * GetCluster() const
Get the address of the cluster, if originally provided.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
unsigned int m_maxAngleRatio
The max ratio allowed in the angle.
pandora::StatusCode GetGlobalFitPositionAtX(const float x, pandora::CartesianVector &position) const
Get global fit position for a given input x coordinate.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
virtual bool CreateThreeDParticles(const ProtoParticleVector &protoParticleVector)
Create particles using findings from recent algorithm processing.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
static bool HasLongDirectConnections(IteratorList::const_iterator iIter, const IteratorList &iteratorList)
Whether a long element shares clusters with any other long elements.
float m_sampleStepSize
The sampling step size used in association checks, units cm.
XOverlap class.
Definition: LArXOverlap.h:17
pandora::CartesianVector GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
QTextStream & endl(QTextStream &s)
Header file for the long tracks tool class.
GeomAnalyzerI * GetGeometry(void)
Definition: gAtmoEvGen.cxx:433