LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
HitWidthClusterMergingAlgorithm.cc
Go to the documentation of this file.
1 
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_t x
Definition: compare.C:6
float m_minClusterWeight
The threshold hit weight of the original, unscaled cluster to be considered in the merging process...
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 -> cl...
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
Double_t z
Definition: plot.C:276
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.
intermediate_table::const_iterator const_iterator
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.
TFile f
Definition: plotHisto.C:6
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...
std::vector< pandora::CartesianVector > EigenVectors
Definition: LArPcaHelper.h:25
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 -> cluster parameters].
float m_maxZMergeDistance
The maximum z distance between merging points of associated clusters, units cm.
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...