All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HitWidthClusterMergingAlgorithm.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArTwoDReco/LArClusterAssociation/HitWidthClusterMergingAlgorithm.cc
3  *
4  * @brief Implementation of the hit width cluster merging algorithm class.
5  *
6  * $Log: $
7  */
8 #include "Pandora/AlgorithmHeaders.h"
9 
11 
15 
16 using namespace pandora;
17 
18 namespace lar_content
19 {
20 
21 HitWidthClusterMergingAlgorithm::HitWidthClusterMergingAlgorithm() :
22  m_maxConstituentHitWidth(0.5f),
23  m_hitWidthScalingFactor(1.f),
24  m_fittingWeight(20.f),
25  m_minClusterWeight(0.5f),
26  m_maxXMergeDistance(5.f),
27  m_maxZMergeDistance(2.f),
28  m_minMergeCosOpeningAngle(0.97f),
29  m_minDirectionDeviationCosAngle(0.9f),
30  m_minClusterSparseness(0.3f)
31 {
32 }
33 
34 //------------------------------------------------------------------------------------------------------------------------------------------
35 
36 void HitWidthClusterMergingAlgorithm::GetListOfCleanClusters(const ClusterList *const pClusterList, ClusterVector &clusterVector) const
37 {
38  // clear map if already full i.e. from other view clustering
39  if (!m_clusterToParametersMap.empty())
41 
42  for (const Cluster *const pCluster : *pClusterList)
43  {
44  // the original cluster weight, with no hit scaling or hit padding
46  continue;
47 
48  const unsigned int numberOfProposedConstituentHits(
50 
51  if (numberOfProposedConstituentHits == 0)
52  continue;
53 
54  // clusterSparseness [0 -> 1] where a higher value indicates sparseness
55  const float clusterSparseness(1.f - (static_cast<float>(pCluster->GetNCaloHits()) / static_cast<float>(numberOfProposedConstituentHits)));
56 
57  if (clusterSparseness < m_minClusterSparseness)
58  continue;
59 
60  m_clusterToParametersMap.insert(std::pair<const Cluster *, LArHitWidthHelper::ClusterParameters>(
62 
63  clusterVector.push_back(pCluster);
64  }
65 
66  std::sort(clusterVector.begin(), clusterVector.end(), LArHitWidthHelper::SortByHigherXExtrema(m_clusterToParametersMap));
67 }
68 
69 //------------------------------------------------------------------------------------------------------------------------------------------
70 
72 {
73  // ATTN this method assumes that clusters have been sorted by extremal x position (low higherXExtrema -> high higherXExtrema)
74  for (ClusterVector::const_iterator iterCurrentCluster = clusterVector.begin(); iterCurrentCluster != clusterVector.end(); ++iterCurrentCluster)
75  {
76  const Cluster *const pCurrentCluster = *iterCurrentCluster;
77  const LArHitWidthHelper::ClusterParameters &currentClusterParameters(
79 
80  for (ClusterVector::const_iterator iterTestCluster = iterCurrentCluster; iterTestCluster != clusterVector.end(); ++iterTestCluster)
81  {
82  if (iterCurrentCluster == iterTestCluster)
83  continue;
84 
85  const Cluster *const pTestCluster = *iterTestCluster;
86  const LArHitWidthHelper::ClusterParameters &testClusterParameters(
88 
89  if (!this->AreClustersAssociated(currentClusterParameters, testClusterParameters))
90  continue;
91 
92  clusterAssociationMap[pCurrentCluster].m_forwardAssociations.insert(pTestCluster);
93  clusterAssociationMap[pTestCluster].m_backwardAssociations.insert(pCurrentCluster);
94  }
95  }
96 
97  this->RemoveShortcutAssociations(clusterVector, clusterAssociationMap);
98 }
99 
100 //------------------------------------------------------------------------------------------------------------------------------------------
101 
102 bool HitWidthClusterMergingAlgorithm::IsExtremalCluster(const bool isForward, const Cluster *const pCurrentCluster, const Cluster *const pTestCluster) const
103 {
104  //ATTN - cannot use map since higherXExtrema may have changed during merging
105  const LArHitWidthHelper::ConstituentHitVector currentConstituentHitVector(
107  const LArHitWidthHelper::ConstituentHitVector testConstituentHitVector(
109  const CartesianVector currentHigherXExtrema(LArHitWidthHelper::GetExtremalCoordinatesHigherX(currentConstituentHitVector));
110  const CartesianVector testHigherXExtrema(LArHitWidthHelper::GetExtremalCoordinatesHigherX(testConstituentHitVector));
111  float currentMaxX(currentHigherXExtrema.GetX()), testMaxX(testHigherXExtrema.GetX());
112 
113  if (isForward)
114  {
115  if (std::fabs(testMaxX - currentMaxX) > std::numeric_limits<float>::epsilon())
116  return (testMaxX > currentMaxX);
117  }
118  else
119  {
120  if (std::fabs(testMaxX - currentMaxX) > std::numeric_limits<float>::epsilon())
121  return (testMaxX < currentMaxX);
122  }
123 
124  return LArClusterHelper::SortByNHits(pTestCluster, pCurrentCluster);
125 }
126 
127 //------------------------------------------------------------------------------------------------------------------------------------------
128 
130  const LArHitWidthHelper::ClusterParameters &currentFitParameters, const LArHitWidthHelper::ClusterParameters &testFitParameters) const
131 {
132  // check cluster extrema are not too far away in x
133  if (testFitParameters.GetLowerXExtrema().GetX() > (currentFitParameters.GetHigherXExtrema().GetX() + m_maxXMergeDistance))
134  return false;
135 
136  // check cluster extrema are not too far away in z
137  if (testFitParameters.GetLowerXExtrema().GetZ() > (currentFitParameters.GetHigherXExtrema().GetZ() + m_maxZMergeDistance) ||
138  testFitParameters.GetLowerXExtrema().GetZ() < (currentFitParameters.GetHigherXExtrema().GetZ() - m_maxZMergeDistance))
139  {
140  return false;
141  }
142 
143  // find appropriate test merging point (may be different to lowerXExtrema when hits overlap)
144  CartesianVector testMergePoint(0.f, 0.f, 0.f);
145  if (testFitParameters.GetLowerXExtrema().GetX() < currentFitParameters.GetHigherXExtrema().GetX())
146  {
147  this->FindClosestPointToPosition(currentFitParameters.GetHigherXExtrema(), testFitParameters.GetConstituentHitVector(), testMergePoint);
148 
149  // check closeness in z is maintained
150  if (testMergePoint.GetZ() > (currentFitParameters.GetHigherXExtrema().GetZ() + m_maxZMergeDistance) ||
151  testMergePoint.GetZ() < (currentFitParameters.GetHigherXExtrema().GetZ() - m_maxZMergeDistance))
152  {
153  return false;
154  }
155  }
156  else
157  {
158  testMergePoint = testFitParameters.GetLowerXExtrema();
159  }
160 
161  CartesianVector currentClusterDirection(0.f, 0.f, 0.f), testClusterDirection(0.f, 0.f, 0.f);
162 
163  try
164  {
165  this->GetClusterDirection(currentFitParameters.GetConstituentHitVector(), currentClusterDirection,
166  currentFitParameters.GetHigherXExtrema(), m_fittingWeight);
167  this->GetClusterDirection(testFitParameters.GetConstituentHitVector(), testClusterDirection, testMergePoint, m_fittingWeight);
168  }
169  catch (const StatusCodeException &)
170  {
171  return false;
172  }
173 
174  // check clusters have a similar direction
175  if (currentClusterDirection.GetCosOpeningAngle(testClusterDirection) < m_minMergeCosOpeningAngle)
176  return false;
177 
178  // check that the new direction is consistent with the old clusters
179  LArHitWidthHelper::ConstituentHitVector newConstituentHitVector(currentFitParameters.GetConstituentHitVector());
180  newConstituentHitVector.insert(newConstituentHitVector.end(), testFitParameters.GetConstituentHitVector().begin(),
181  testFitParameters.GetConstituentHitVector().end());
182 
183  const CartesianVector midpoint((currentFitParameters.GetHigherXExtrema() + testMergePoint) * 0.5);
184  CartesianVector newClusterDirection(0.f, 0.f, 0.f);
185 
186  try
187  {
188  this->GetClusterDirection(newConstituentHitVector, newClusterDirection, midpoint, m_fittingWeight);
189  }
190  catch (const StatusCodeException &)
191  {
192  return false;
193  }
194 
195  if (newClusterDirection.GetCosOpeningAngle(currentClusterDirection) < m_minDirectionDeviationCosAngle ||
196  newClusterDirection.GetCosOpeningAngle(testClusterDirection) < m_minDirectionDeviationCosAngle)
197  {
198  return false;
199  }
200 
201  return true;
202 }
203 
204 //------------------------------------------------------------------------------------------------------------------------------------------
205 
207  const LArHitWidthHelper::ConstituentHitVector &constituentHitVector, CartesianVector &closestPoint) const
208 {
209  float minDistanceSquared(std::numeric_limits<float>::max());
210  for (const LArHitWidthHelper::ConstituentHit &constituentHit : constituentHitVector)
211  {
212  const CartesianVector &hitPosition(constituentHit.GetPositionVector());
213  const float separationDistanceSquared(hitPosition.GetDistanceSquared(position));
214 
215  if (separationDistanceSquared < minDistanceSquared)
216  {
217  minDistanceSquared = separationDistanceSquared;
218  closestPoint = hitPosition;
219  }
220  }
221 }
222 
223 //------------------------------------------------------------------------------------------------------------------------------------------
224 
226  CartesianVector &direction, const CartesianVector &fitReferencePoint, const float fittingWeight) const
227 {
228  float weightSum(0.f), weightedLSum(0.f), weightedTSum(0.f);
229  bool isLConstant(true), isTConstant(true);
230 
231  // get fitting subset vector
232  LArHitWidthHelper::ConstituentHitVector constituentHitSubsetVector;
233  this->GetConstituentHitSubsetVector(constituentHitVector, fitReferencePoint, fittingWeight, constituentHitSubsetVector);
234 
235  // determine the fitting axes
236  CartesianVector axisDirection(0.f, 0.f, 0.f), orthoDirection(0.f, 0.f, 0.f);
237  this->GetFittingAxes(constituentHitSubsetVector, axisDirection, orthoDirection);
238 
239  // the comparison to check if constituent hit positions are constant in rL or rT (would lead to a division by zero)
240  float firstHitL(0.f), firstHitT(0.f);
241  this->GetFittingCoordinates(axisDirection, constituentHitSubsetVector.begin()->GetPositionVector(), firstHitL, firstHitT);
242 
243  for (const LArHitWidthHelper::ConstituentHit &constituentHit : constituentHitSubsetVector)
244  {
245  const float hitWeight(constituentHit.GetHitWidth());
246  float rL(0.f), rT(0.f);
247  this->GetFittingCoordinates(axisDirection, constituentHit.GetPositionVector(), rL, rT);
248 
249  if (std::fabs(firstHitL - rL) > std::numeric_limits<float>::epsilon())
250  isLConstant = false;
251 
252  if (std::fabs(firstHitT - rT) > std::numeric_limits<float>::epsilon())
253  isTConstant = false;
254 
255  weightedLSum += rL * hitWeight;
256  weightedTSum += rT * hitWeight;
257  weightSum += hitWeight;
258  }
259 
260  if (weightSum < std::numeric_limits<float>::epsilon())
261  {
262  std::cout << "HitWidthClusterMergingAlgorithm::GetWeightedGradient - hit weight in fit is negative or equivalent to zero" << std::endl;
263  throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
264  }
265 
266  // return ortho direction for a cluster with constant rL
267  if (isLConstant)
268  {
269  // ATTN direction convention is to point in direction of increasing x
270  direction = (orthoDirection.GetX() < 0.f) ? orthoDirection * (-1.f) : orthoDirection;
271  return;
272  }
273 
274  // return axis direction for a cluster with constant rT
275  if (isTConstant)
276  {
277  // ATTN direction convention is to point in direction of increasing x
278  direction = (axisDirection.GetX() < 0.f) ? axisDirection * (-1.f) : axisDirection;
279  return;
280  }
281 
282  const float weightedLMean(weightedLSum / weightSum), weightedTMean(weightedTSum / weightSum);
283  float numerator(0.f), denominator(0.f);
284 
285  for (const LArHitWidthHelper::ConstituentHit &constituentHit : constituentHitSubsetVector)
286  {
287  const float hitWeight(constituentHit.GetHitWidth());
288  float rL(0.f), rT(0.f);
289  this->GetFittingCoordinates(axisDirection, constituentHit.GetPositionVector(), rL, rT);
290 
291  numerator += hitWeight * (rL - weightedLMean) * (rT - weightedTMean);
292  denominator += hitWeight * pow(rL - weightedLMean, 2);
293  }
294 
295  const float gradient(numerator / denominator);
296 
297  // change coordinates to z=mx+c fit and normalise
298  this->GetGlobalDirection(axisDirection, gradient, direction);
299 
300  // ATTN direction convention is to point in direction of increasing x
301  if (direction.GetX() < 0.f)
302  direction *= -1.f;
303 }
304 
305 //------------------------------------------------------------------------------------------------------------------------------------------
306 
308  const CartesianVector &fitReferencePoint, const float fittingWeight, LArHitWidthHelper::ConstituentHitVector &constituentHitSubsetVector) const
309 {
310  LArHitWidthHelper::ConstituentHitVector sortedConstituentHitVector(constituentHitVector);
311 
312  // sort hits with respect to their distance to the fitReferencePoint (closest -> furthest)
313  std::sort(sortedConstituentHitVector.begin(), sortedConstituentHitVector.end(),
315 
316  float weightCount(0.f);
317  for (const LArHitWidthHelper::ConstituentHit &constituentHit : sortedConstituentHitVector)
318  {
319  constituentHitSubsetVector.push_back(constituentHit);
320 
321  weightCount += constituentHit.GetHitWidth();
322 
323  if (weightCount > fittingWeight)
324  break;
325  }
326 }
327 
328 //------------------------------------------------------------------------------------------------------------------------------------------
329 
331  CartesianVector &axisDirection, CartesianVector &orthoDirection) const
332 {
333  CartesianPointVector constituentHitSubsetPositionVector(LArHitWidthHelper::GetConstituentHitPositionVector(constituentHitSubsetVector));
334 
335  if (constituentHitSubsetPositionVector.size() < 2)
336  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
337 
338  CartesianVector centroid(0.f, 0.f, 0.f);
339  LArPcaHelper::EigenVectors eigenVecs;
340  LArPcaHelper::EigenValues eigenValues(0.f, 0.f, 0.f);
341  LArPcaHelper::RunPca(constituentHitSubsetPositionVector, centroid, eigenValues, eigenVecs);
342 
343  axisDirection = eigenVecs.at(0);
344 
345  // ATTN fitting convention is to point in direction of increasing z
346  if (axisDirection.GetZ() < 0.f)
347  axisDirection *= -1.f;
348 
349  // Use y-axis to generate an orthogonal axis (assuming that cluster occupies x-z plane)
350  const CartesianVector yAxis(0.f, 1.f, 0.f);
351  orthoDirection = yAxis.GetCrossProduct(axisDirection).GetUnitVector();
352 }
353 
354 //------------------------------------------------------------------------------------------------------------------------------------------
355 
357  const CartesianVector &axisDirection, const CartesianVector &constituentHitPosition, float &rL, float &rT) const
358 {
359  // axisDirection is in positive z by convention so use opening angle to obtain coordinates in rotated frame
360  const CartesianVector xAxis(1.f, 0.f, 0.f);
361  const float openingAngle(axisDirection.GetOpeningAngle(xAxis)), c(std::cos(openingAngle)), s(std::sin(openingAngle));
362 
363  rL = (c * constituentHitPosition.GetX()) + (s * constituentHitPosition.GetZ());
364  rT = (c * constituentHitPosition.GetZ()) - (s * constituentHitPosition.GetX());
365 }
366 
367 //------------------------------------------------------------------------------------------------------------------------------------------
368 
369 void HitWidthClusterMergingAlgorithm::GetGlobalDirection(const CartesianVector &axisDirection, const float gradient, CartesianVector &globalDirection) const
370 {
371  const CartesianVector xAxis(1.f, 0.f, 0.f);
372  const float openingAngle(axisDirection.GetOpeningAngle(xAxis)), c(std::cos(openingAngle)), s(std::sin(openingAngle));
373  const float deltaL(1.f), deltaT(gradient);
374 
375  const float x = (c * deltaL) - (s * deltaT);
376  const float z = (c * deltaT) + (s * deltaL);
377 
378  globalDirection.SetValues(x, 0.f, z);
379  globalDirection = globalDirection.GetUnitVector();
380 }
381 
382 //------------------------------------------------------------------------------------------------------------------------------------------
383 
385 {
386  // Create temporary map so can delete elements whilst still iterating over them
387  ClusterAssociationMap tempMap(clusterAssociationMap);
388 
389  for (const Cluster *const pCluster : clusterVector)
390  {
391  const ClusterAssociationMap::const_iterator primaryMapIter = clusterAssociationMap.find(pCluster);
392 
393  if (primaryMapIter == clusterAssociationMap.end())
394  continue;
395 
396  // put ClusterSet into ClusterVector
397  ClusterVector primaryForwardAssociations(
398  primaryMapIter->second.m_forwardAssociations.begin(), primaryMapIter->second.m_forwardAssociations.end());
399  std::sort(primaryForwardAssociations.begin(), primaryForwardAssociations.end(), LArClusterHelper::SortByNHits);
400 
401  // remove primary clusters that are present in secondary associations of other primary clusters
402  for (const Cluster *const pConsideredCluster : primaryForwardAssociations)
403  {
404  for (const Cluster *const pPrimaryCluster : primaryForwardAssociations)
405  {
406  if (pConsideredCluster == pPrimaryCluster)
407  continue;
408 
409  const ClusterAssociationMap::const_iterator secondaryMapIter = clusterAssociationMap.find(pPrimaryCluster);
410 
411  // if primary cluster has no associations (this shouldn't ever be the case)
412  if (secondaryMapIter == clusterAssociationMap.end())
413  continue;
414 
415  const ClusterSet &secondaryForwardAssociations(secondaryMapIter->second.m_forwardAssociations);
416 
417  if (secondaryForwardAssociations.find(pConsideredCluster) != secondaryForwardAssociations.end())
418  {
419  ClusterSet &tempPrimaryForwardAssociations(tempMap.find(pCluster)->second.m_forwardAssociations);
420  const ClusterSet::const_iterator forwardAssociationToRemove(tempPrimaryForwardAssociations.find(pConsideredCluster));
421 
422  // if association has already been removed
423  if (forwardAssociationToRemove == tempPrimaryForwardAssociations.end())
424  continue;
425 
426  ClusterSet &tempPrimaryBackwardAssociations(tempMap.find(pConsideredCluster)->second.m_backwardAssociations);
427  const ClusterSet::const_iterator backwardAssociationToRemove(tempPrimaryBackwardAssociations.find(pCluster));
428 
429  // if association has already been removed
430  if (backwardAssociationToRemove == tempPrimaryBackwardAssociations.end())
431  continue;
432 
433  tempPrimaryForwardAssociations.erase(forwardAssociationToRemove);
434  tempPrimaryBackwardAssociations.erase(backwardAssociationToRemove);
435  }
436  }
437  }
438  }
439 
440  clusterAssociationMap = tempMap;
441 }
442 
443 //------------------------------------------------------------------------------------------------------------------------------------------
444 
445 StatusCode HitWidthClusterMergingAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
446 {
447  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "FittingWeight", m_fittingWeight));
448 
449  PANDORA_RETURN_RESULT_IF_AND_IF(
450  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinClusterWeight", m_minClusterWeight));
451 
452  PANDORA_RETURN_RESULT_IF_AND_IF(
453  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxXMergeDistance", m_maxXMergeDistance));
454 
455  PANDORA_RETURN_RESULT_IF_AND_IF(
456  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxZMergeDistance", m_maxZMergeDistance));
457 
458  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
459  XmlHelper::ReadValue(xmlHandle, "MinMergeCosOpeningAngle", m_minMergeCosOpeningAngle));
460 
461  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
462  XmlHelper::ReadValue(xmlHandle, "MinDirectionDeviationCosAngle", m_minDirectionDeviationCosAngle));
463 
464  PANDORA_RETURN_RESULT_IF_AND_IF(
465  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxConstituentHitWidth", m_maxConstituentHitWidth));
466 
467  PANDORA_RETURN_RESULT_IF_AND_IF(
468  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "HitWidthScalingFactor", m_hitWidthScalingFactor));
469 
470  PANDORA_RETURN_RESULT_IF_AND_IF(
471  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinClusterSparseness", m_minClusterSparseness));
472 
474 }
475 
476 } // namespace lar_content
float m_minClusterWeight
The threshold hit weight of the original, unscaled cluster to be considered in the merging process...
process_name opflash particleana ie ie ie z
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.
const pandora::CartesianVector & GetLowerXExtrema() const
Returns the lower x extremal point of the constituent hits.
static float GetOriginalTotalClusterWeight(const pandora::Cluster *const pCluster)
Sum the widths of the original, unscaled hits contained within a cluster.
static const ClusterParameters & GetClusterParameters(const pandora::Cluster *const pCluster, const ClusterToParametersMap &clusterToParametersMap)
Return the cluster parameters of a given cluster, exception thrown if not found in map [cluster -&gt; cl...
process_name opflash particleana ie x
bool IsExtremalCluster(const bool isForward, const pandora::Cluster *const pCurrentCluster, const pandora::Cluster *const pTestCluster) const
Determine which of two clusters is extremal.
pandora::CartesianVector EigenValues
Definition: LArPcaHelper.h:24
float m_maxXMergeDistance
The maximum x distance between merging points of associated clusters, units cm.
Header file for the hit width cluster merging algorithm class.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
void GetFittingAxes(const LArHitWidthHelper::ConstituentHitVector &constituentHitSubsetVector, pandora::CartesianVector &axisDirection, pandora::CartesianVector &orthoDirection) const
Obtain the axes of the fitting frame.
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
static ConstituentHitVector GetConstituentHits(const pandora::Cluster *const pCluster, const float maxConstituentHitWidth, const float hitWidthScalingFactor, const bool isUniform)
Break up the cluster hits into constituent hits.
Header file for the principal curve analysis helper class.
void PopulateClusterAssociationMap(const pandora::ClusterVector &clusterVector, ClusterAssociationMap &clusterAssociationMap) const
Populate the cluster association map.
void GetGlobalDirection(const pandora::CartesianVector &axisDirection, const float gradient, pandora::CartesianVector &globalDirection) const
Translate a gradient in the fitting coordinate frame to a direction vector in the detector frame...
float m_minDirectionDeviationCosAngle
The minimum cosine opening angle of the direction of and associated cluster before and after merge...
float m_minClusterSparseness
The threshold sparseness of a cluster to be considered in the merging process.
void FindClosestPointToPosition(const pandora::CartesianVector &position, const LArHitWidthHelper::ConstituentHitVector &constituentHitVector, pandora::CartesianVector &closestPoint) const
Determine the position of the constituent hit that lies closest to a specified position.
float m_minMergeCosOpeningAngle
The minimum cosine opening angle of the directions of associated clusters.
Header file for the geometry helper class.
Header file for the cluster helper class.
const pandora::CartesianVector & GetHigherXExtrema() const
Returns the higher x extremal point of the constituent hits.
std::vector< ConstituentHit > ConstituentHitVector
bool AreClustersAssociated(const LArHitWidthHelper::ClusterParameters &currentClusterParameters, const LArHitWidthHelper::ClusterParameters &testClusterParameters) const
Determine whether two clusters are associated.
static unsigned int GetNProposedConstituentHits(const pandora::Cluster *const pCluster, const float maxConstituentHitWidth, const float hitWidthScalingFactor)
Return the number of constituent hits that a given cluster would be broken into.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
static pandora::CartesianPointVector GetConstituentHitPositionVector(const ConstituentHitVector &constituentHitVector)
Obtain a vector of the contituent hit central positions.
void RemoveShortcutAssociations(const pandora::ClusterVector &clusterVector, ClusterAssociationMap &clusterAssociationMap) const
Remove &#39;shortcut&#39; associations from the cluster association map.
float m_maxConstituentHitWidth
The maximum hit width of a constituent hit of broken up hit, units cm.
static pandora::CartesianVector GetExtremalCoordinatesHigherX(const ConstituentHitVector &constituentHitVector)
Return the higher x extremal point of the constituent hits.
static void RunPca(const T &t, pandora::CartesianVector &centroid, EigenValues &outputEigenValues, EigenVectors &outputEigenVectors)
Run principal component analysis using input calo hits (TPC_VIEW_U,V,W or TPC_3D; all treated as 3D p...
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch pandora
Definition: reco_sbnd.fcl:182
std::vector< pandora::CartesianVector > EigenVectors
Definition: LArPcaHelper.h:25
then echo File list $list not found else cat $list while read file do echo $file sed s
Definition: file_to_url.sh:60
float m_hitWidthScalingFactor
The scaling factor of the hit widths.
void GetFittingCoordinates(const pandora::CartesianVector &axisDirection, const pandora::CartesianVector &constituentHitPosition, float &rL, float &rT) const
Translate from (x, y, z) coordinates to (rL, rT) coordinates.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
void GetClusterDirection(const LArHitWidthHelper::ConstituentHitVector &constituentHitVector, pandora::CartesianVector &direction, const pandora::CartesianVector &fitReferencePoint, const float fittingWeight) const
Determine the cluster direction at a reference point by performing a weighted least squared fit to th...
float m_fittingWeight
The maximum hit weight considered in the least squared fit.
const ConstituentHitVector & GetConstituentHitVector() const
Returns the vector of constituent hits.
LArHitWidthHelper::ClusterToParametersMap m_clusterToParametersMap
The map [cluster -&gt; cluster parameters].
float m_maxZMergeDistance
The maximum z distance between merging points of associated clusters, units cm.
BEGIN_PROLOG could also be cout
void GetConstituentHitSubsetVector(const LArHitWidthHelper::ConstituentHitVector &constituentHitVector, const pandora::CartesianVector &fitReferencePoint, const float fittingWeight, LArHitWidthHelper::ConstituentHitVector &constituentHitSubsetVector) const
Obtain a vector of the minimum number of hits closest to a reference point that exceed a given weight...
void GetListOfCleanClusters(const pandora::ClusterList *const pClusterList, pandora::ClusterVector &clusterVector) const
Populate cluster vector with subset of cluster list, containing clusters judged to be clean...