LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
lar_content::HitWidthClusterMergingAlgorithm Class Reference

HitWidthClusterMergingAlgorithm class. More...

#include "HitWidthClusterMergingAlgorithm.h"

Inheritance diagram for lar_content::HitWidthClusterMergingAlgorithm:
lar_content::ClusterAssociationAlgorithm

Public Member Functions

 HitWidthClusterMergingAlgorithm ()
 Default constructor. More...
 

Protected Types

typedef std::unordered_map< const pandora::Cluster *, ClusterAssociationClusterAssociationMap
 

Protected Member Functions

virtual pandora::StatusCode Run ()
 

Private Member Functions

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. More...
 
void PopulateClusterAssociationMap (const pandora::ClusterVector &clusterVector, ClusterAssociationMap &clusterAssociationMap) const
 Populate the cluster association map. More...
 
bool IsExtremalCluster (const bool isForward, const pandora::Cluster *const pCurrentCluster, const pandora::Cluster *const pTestCluster) const
 Determine which of two clusters is extremal. More...
 
bool AreClustersAssociated (const LArHitWidthHelper::ClusterParameters &currentClusterParameters, const LArHitWidthHelper::ClusterParameters &testClusterParameters) const
 Determine whether two clusters are associated. More...
 
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. More...
 
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 the input consitutent hit positions The fit is performed in a rotated cartesian coordinate system defined by a fitting axis determined by eigen The function is composed of two main loops that calculate the: More...
 
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. More...
 
void GetFittingAxes (const LArHitWidthHelper::ConstituentHitVector &constituentHitSubsetVector, pandora::CartesianVector &axisDirection, pandora::CartesianVector &orthoDirection) const
 Obtain the axes of the fitting frame. More...
 
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. More...
 
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. More...
 
void RemoveShortcutAssociations (const pandora::ClusterVector &clusterVector, ClusterAssociationMap &clusterAssociationMap) const
 Remove 'shortcut' associations from the cluster association map. More...
 
pandora::StatusCode ReadSettings (const pandora::TiXmlHandle xmlHandle)
 

Private Attributes

float m_maxConstituentHitWidth
 The maximum hit width of a constituent hit of broken up hit, units cm. More...
 
float m_hitWidthScalingFactor
 The scaling factor of the hit widths. More...
 
float m_fittingWeight
 The maximum hit weight considered in the least squared fit. More...
 
float m_minClusterWeight
 The threshold hit weight of the original, unscaled cluster to be considered in the merging process. More...
 
float m_maxXMergeDistance
 The maximum x distance between merging points of associated clusters, units cm. More...
 
float m_maxZMergeDistance
 The maximum z distance between merging points of associated clusters, units cm. More...
 
float m_minMergeCosOpeningAngle
 The minimum cosine opening angle of the directions of associated clusters. More...
 
float m_minDirectionDeviationCosAngle
 The minimum cosine opening angle of the direction of and associated cluster before and after merge. More...
 
float m_minClusterSparseness
 The threshold sparseness of a cluster to be considered in the merging process. More...
 
LArHitWidthHelper::ClusterToParametersMap m_clusterToParametersMap
 The map [cluster -> cluster parameters]. More...
 

Detailed Description

Member Typedef Documentation

typedef std::unordered_map<const pandora::Cluster *, ClusterAssociation> lar_content::ClusterAssociationAlgorithm::ClusterAssociationMap
protectedinherited

Definition at line 43 of file ClusterAssociationAlgorithm.h.

Constructor & Destructor Documentation

lar_content::HitWidthClusterMergingAlgorithm::HitWidthClusterMergingAlgorithm ( )

Default constructor.

Definition at line 21 of file HitWidthClusterMergingAlgorithm.cc.

21  :
24  m_fittingWeight(20.f),
31 {
32 }
float m_minClusterWeight
The threshold hit weight of the original, unscaled cluster to be considered in the merging process...
float m_maxXMergeDistance
The maximum x distance between merging points of associated clusters, units cm.
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.
TFile f
Definition: plotHisto.C:6
float m_minMergeCosOpeningAngle
The minimum cosine opening angle of the directions of associated clusters.
float m_maxConstituentHitWidth
The maximum hit width of a constituent hit of broken up hit, units cm.
float m_hitWidthScalingFactor
The scaling factor of the hit widths.
float m_fittingWeight
The maximum hit weight considered in the least squared fit.
float m_maxZMergeDistance
The maximum z distance between merging points of associated clusters, units cm.

Member Function Documentation

bool lar_content::HitWidthClusterMergingAlgorithm::AreClustersAssociated ( const LArHitWidthHelper::ClusterParameters currentClusterParameters,
const LArHitWidthHelper::ClusterParameters testClusterParameters 
) const
private

Determine whether two clusters are associated.

Parameters
currentClusterParametersparameters defining the current cluster
testClusterParametersparameters defining the test cluster
Returns
boolean whether the clusters are associated

Definition at line 129 of file HitWidthClusterMergingAlgorithm.cc.

References f, FindClosestPointToPosition(), GetClusterDirection(), lar_content::LArHitWidthHelper::ClusterParameters::GetConstituentHitVector(), lar_content::LArHitWidthHelper::ClusterParameters::GetHigherXExtrema(), lar_content::LArHitWidthHelper::ClusterParameters::GetLowerXExtrema(), m_fittingWeight, m_maxXMergeDistance, m_maxZMergeDistance, m_minDirectionDeviationCosAngle, and m_minMergeCosOpeningAngle.

Referenced by PopulateClusterAssociationMap().

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 }
float m_maxXMergeDistance
The maximum x distance between merging points of associated clusters, units cm.
float m_minDirectionDeviationCosAngle
The minimum cosine opening angle of the direction of and associated cluster before and after merge...
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.
std::vector< ConstituentHit > ConstituentHitVector
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.
float m_maxZMergeDistance
The maximum z distance between merging points of associated clusters, units cm.
void lar_content::HitWidthClusterMergingAlgorithm::FindClosestPointToPosition ( const pandora::CartesianVector &  position,
const LArHitWidthHelper::ConstituentHitVector constituentHitVector,
pandora::CartesianVector &  closestPoint 
) const
private

Determine the position of the constituent hit that lies closest to a specified position.

Parameters
positionthe point to which the consituent hits will be compared
constituentHitVectorthe input vector of constituent hits
closestPointthe position of the closest constituent hit

Definition at line 206 of file HitWidthClusterMergingAlgorithm.cc.

Referenced by AreClustersAssociated().

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 }
void lar_content::HitWidthClusterMergingAlgorithm::GetClusterDirection ( const LArHitWidthHelper::ConstituentHitVector constituentHitVector,
pandora::CartesianVector &  direction,
const pandora::CartesianVector &  fitReferencePoint,
const float  fittingWeight 
) const
private

Determine the cluster direction at a reference point by performing a weighted least squared fit to the input consitutent hit positions The fit is performed in a rotated cartesian coordinate system defined by a fitting axis determined by eigen The function is composed of two main loops that calculate the:

  1. rL & rT weighted means
  2. gradient of the fit The fit is performed using a subset of points that are closest to the fitReferencePoint
Parameters
constituentHitVectorthe input vector of constituent hits
directionthe fitted cluster direction
fitReferencePointthe hits closest to this point are included in the fit
fittingWeightthe weight that is considered in the fit

Definition at line 225 of file HitWidthClusterMergingAlgorithm.cc.

References f, GetConstituentHitSubsetVector(), GetFittingAxes(), GetFittingCoordinates(), and GetGlobalDirection().

Referenced by AreClustersAssociated().

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 }
void GetFittingAxes(const LArHitWidthHelper::ConstituentHitVector &constituentHitSubsetVector, pandora::CartesianVector &axisDirection, pandora::CartesianVector &orthoDirection) const
Obtain the axes of the fitting frame.
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...
TFile f
Definition: plotHisto.C:6
std::vector< ConstituentHit > ConstituentHitVector
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.
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 lar_content::HitWidthClusterMergingAlgorithm::GetConstituentHitSubsetVector ( const LArHitWidthHelper::ConstituentHitVector constituentHitVector,
const pandora::CartesianVector &  fitReferencePoint,
const float  fittingWeight,
LArHitWidthHelper::ConstituentHitVector constituentHitSubsetVector 
) const
private

Obtain a vector of the minimum number of hits closest to a reference point that exceed a given weight.

Parameters
constituentHitVectorthe input vector of constituent hits
fitReferencePointthe reference point
fittingWeightthe specified cumulative hit weight
constituentHitSubsetVectorthe subset of constituent hits

Definition at line 307 of file HitWidthClusterMergingAlgorithm.cc.

References f.

Referenced by GetClusterDirection().

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(),
314  LArHitWidthHelper::ConstituentHit::SortByDistanceToPoint(fitReferencePoint));
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 }
TFile f
Definition: plotHisto.C:6
std::vector< ConstituentHit > ConstituentHitVector
void lar_content::HitWidthClusterMergingAlgorithm::GetFittingAxes ( const LArHitWidthHelper::ConstituentHitVector constituentHitSubsetVector,
pandora::CartesianVector &  axisDirection,
pandora::CartesianVector &  orthoDirection 
) const
private

Obtain the axes of the fitting frame.

Parameters
constituentHitSubsetVectorthe input vector of constituent hits
axisDirectionthe fitting 'x-axis'
orthoDirectionthe fitting 'z-axis'

Definition at line 330 of file HitWidthClusterMergingAlgorithm.cc.

References f, lar_content::LArHitWidthHelper::GetConstituentHitPositionVector(), and lar_content::LArPcaHelper::RunPca().

Referenced by GetClusterDirection().

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 }
pandora::CartesianVector EigenValues
Definition: LArPcaHelper.h:24
TFile f
Definition: plotHisto.C:6
static pandora::CartesianPointVector GetConstituentHitPositionVector(const ConstituentHitVector &constituentHitVector)
Obtain a vector of the contituent hit central positions.
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
void lar_content::HitWidthClusterMergingAlgorithm::GetFittingCoordinates ( const pandora::CartesianVector &  axisDirection,
const pandora::CartesianVector &  constituentHitPosition,
float &  rL,
float &  rT 
) const
private

Translate from (x, y, z) coordinates to (rL, rT) coordinates.

Parameters
axisDirectionthe fitting 'x-axis'
constituentHitPositionthe (x, y, z) position of a constituent hit
rLthe fitting 'x' coordinate
rTthe fitting 'z' coordinate

Definition at line 356 of file HitWidthClusterMergingAlgorithm.cc.

References f.

Referenced by GetClusterDirection().

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 }
TFile f
Definition: plotHisto.C:6
void lar_content::HitWidthClusterMergingAlgorithm::GetGlobalDirection ( const pandora::CartesianVector &  axisDirection,
const float  gradient,
pandora::CartesianVector &  globalDirection 
) const
private

Translate a gradient in the fitting coordinate frame to a direction vector in the detector frame.

Parameters
axisDirectionthe fitting 'x-axis'
gradientthe gradient dT/dL
globalDirectionthe direction vector in the detector frame

Definition at line 369 of file HitWidthClusterMergingAlgorithm.cc.

References f, x, and z.

Referenced by GetClusterDirection().

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 }
Float_t x
Definition: compare.C:6
Double_t z
Definition: plot.C:276
TFile f
Definition: plotHisto.C:6
void lar_content::HitWidthClusterMergingAlgorithm::GetListOfCleanClusters ( const pandora::ClusterList *const  pClusterList,
pandora::ClusterVector &  clusterVector 
) const
privatevirtual

Populate cluster vector with subset of cluster list, containing clusters judged to be clean.

Parameters
pClusterListaddress of the cluster list
clusterVectorto receive the populated cluster vector

Implements lar_content::ClusterAssociationAlgorithm.

Definition at line 36 of file HitWidthClusterMergingAlgorithm.cc.

References f, lar_content::LArHitWidthHelper::GetNProposedConstituentHits(), lar_content::LArHitWidthHelper::GetOriginalTotalClusterWeight(), m_clusterToParametersMap, m_hitWidthScalingFactor, m_maxConstituentHitWidth, m_minClusterSparseness, and m_minClusterWeight.

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>(
61  pCluster, LArHitWidthHelper::ClusterParameters(pCluster, m_maxConstituentHitWidth, false, m_hitWidthScalingFactor)));
62 
63  clusterVector.push_back(pCluster);
64  }
65 
66  std::sort(clusterVector.begin(), clusterVector.end(), LArHitWidthHelper::SortByHigherXExtrema(m_clusterToParametersMap));
67 }
float m_minClusterWeight
The threshold hit weight of the original, unscaled cluster to be considered in the merging process...
static float GetOriginalTotalClusterWeight(const pandora::Cluster *const pCluster)
Sum the widths of the original, unscaled hits contained within a cluster.
float m_minClusterSparseness
The threshold sparseness of a cluster to be considered in the merging process.
TFile f
Definition: plotHisto.C:6
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.
float m_maxConstituentHitWidth
The maximum hit width of a constituent hit of broken up hit, units cm.
float m_hitWidthScalingFactor
The scaling factor of the hit widths.
LArHitWidthHelper::ClusterToParametersMap m_clusterToParametersMap
The map [cluster -> cluster parameters].
bool lar_content::HitWidthClusterMergingAlgorithm::IsExtremalCluster ( const bool  isForward,
const pandora::Cluster *const  pCurrentCluster,
const pandora::Cluster *const  pTestCluster 
) const
privatevirtual

Determine which of two clusters is extremal.

Parameters
isForwardwhether propagation direction is forward
pCurrentClustercurrent extremal cluster
pTestClusterpotential extremal cluster
Returns
boolean

Implements lar_content::ClusterAssociationAlgorithm.

Definition at line 102 of file HitWidthClusterMergingAlgorithm.cc.

References lar_content::LArHitWidthHelper::GetConstituentHits(), lar_content::LArHitWidthHelper::GetExtremalCoordinatesHigherX(), m_hitWidthScalingFactor, m_maxConstituentHitWidth, and lar_content::LArClusterHelper::SortByNHits().

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 }
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.
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.
std::vector< ConstituentHit > ConstituentHitVector
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.
float m_hitWidthScalingFactor
The scaling factor of the hit widths.
void lar_content::HitWidthClusterMergingAlgorithm::PopulateClusterAssociationMap ( const pandora::ClusterVector &  clusterVector,
ClusterAssociationMap clusterAssociationMap 
) const
privatevirtual

Populate the cluster association map.

Parameters
clusterVectorthe cluster vector
clusterAssociationMapto receive the populated cluster association map

Implements lar_content::ClusterAssociationAlgorithm.

Definition at line 71 of file HitWidthClusterMergingAlgorithm.cc.

References AreClustersAssociated(), lar_content::LArHitWidthHelper::GetClusterParameters(), m_clusterToParametersMap, and RemoveShortcutAssociations().

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 }
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...
intermediate_table::const_iterator const_iterator
bool AreClustersAssociated(const LArHitWidthHelper::ClusterParameters &currentClusterParameters, const LArHitWidthHelper::ClusterParameters &testClusterParameters) const
Determine whether two clusters are associated.
void RemoveShortcutAssociations(const pandora::ClusterVector &clusterVector, ClusterAssociationMap &clusterAssociationMap) const
Remove &#39;shortcut&#39; associations from the cluster association map.
LArHitWidthHelper::ClusterToParametersMap m_clusterToParametersMap
The map [cluster -> cluster parameters].
StatusCode lar_content::HitWidthClusterMergingAlgorithm::ReadSettings ( const pandora::TiXmlHandle  xmlHandle)
privatevirtual

Reimplemented from lar_content::ClusterAssociationAlgorithm.

Definition at line 445 of file HitWidthClusterMergingAlgorithm.cc.

References m_fittingWeight, m_hitWidthScalingFactor, m_maxConstituentHitWidth, m_maxXMergeDistance, m_maxZMergeDistance, m_minClusterSparseness, m_minClusterWeight, m_minDirectionDeviationCosAngle, m_minMergeCosOpeningAngle, and lar_content::ClusterAssociationAlgorithm::ReadSettings().

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 }
float m_minClusterWeight
The threshold hit weight of the original, unscaled cluster to be considered in the merging process...
float m_maxXMergeDistance
The maximum x distance between merging points of associated clusters, units cm.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
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.
float m_minMergeCosOpeningAngle
The minimum cosine opening angle of the directions of associated clusters.
float m_maxConstituentHitWidth
The maximum hit width of a constituent hit of broken up hit, units cm.
float m_hitWidthScalingFactor
The scaling factor of the hit widths.
float m_fittingWeight
The maximum hit weight considered in the least squared fit.
float m_maxZMergeDistance
The maximum z distance between merging points of associated clusters, units cm.
void lar_content::HitWidthClusterMergingAlgorithm::RemoveShortcutAssociations ( const pandora::ClusterVector &  clusterVector,
ClusterAssociationMap clusterAssociationMap 
) const
private

Remove 'shortcut' associations from the cluster association map.

Parameters
clusterVectorthe vector of clusters considered in the merging process
clusterAssociationMapthe mapping of clusters to forward/backward associations

Definition at line 384 of file HitWidthClusterMergingAlgorithm.cc.

References lar_content::LArClusterHelper::SortByNHits().

Referenced by PopulateClusterAssociationMap().

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 }
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.
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
intermediate_table::const_iterator const_iterator
std::vector< art::Ptr< recob::Cluster > > ClusterVector
StatusCode lar_content::ClusterAssociationAlgorithm::Run ( )
protectedvirtualinherited

Definition at line 28 of file ClusterAssociationAlgorithm.cc.

References lar_content::ClusterAssociationAlgorithm::AmbiguousPropagation(), lar_content::ClusterAssociationAlgorithm::GetListOfCleanClusters(), lar_content::ClusterAssociationAlgorithm::m_mergeMade, lar_content::ClusterAssociationAlgorithm::m_resolveAmbiguousAssociations, lar_content::ClusterAssociationAlgorithm::PopulateClusterAssociationMap(), and lar_content::ClusterAssociationAlgorithm::UnambiguousPropagation().

29 {
30  const ClusterList *pClusterList = NULL;
31  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pClusterList));
32 
33  ClusterVector clusterVector;
34  this->GetListOfCleanClusters(pClusterList, clusterVector);
35 
36  ClusterAssociationMap clusterAssociationMap;
37  this->PopulateClusterAssociationMap(clusterVector, clusterAssociationMap);
38 
39  m_mergeMade = true;
40 
41  while (m_mergeMade)
42  {
43  // Unambiguous propagation
44  while (m_mergeMade)
45  {
46  m_mergeMade = false;
47 
48  for (const Cluster *const pCluster : clusterVector)
49  {
50  // ATTN The clusterVector may end up with dangling pointers; only protected by this check against managed cluster list
51  if (pClusterList->end() == std::find(pClusterList->begin(), pClusterList->end(), pCluster))
52  continue;
53 
54  this->UnambiguousPropagation(pCluster, true, clusterAssociationMap);
55  this->UnambiguousPropagation(pCluster, false, clusterAssociationMap);
56  }
57  }
58 
60  continue;
61 
62  // Propagation with ambiguities
63  for (const Cluster *const pCluster : clusterVector)
64  {
65  // ATTN The clusterVector may end up with dangling pointers; only protected by this check against up-to-date association list
66  ClusterAssociationMap::const_iterator mapIterFwd = clusterAssociationMap.find(pCluster);
67 
68  if (clusterAssociationMap.end() == mapIterFwd)
69  continue;
70 
71  if (mapIterFwd->second.m_backwardAssociations.empty() && !mapIterFwd->second.m_forwardAssociations.empty())
72  this->AmbiguousPropagation(pCluster, true, clusterAssociationMap);
73 
74  ClusterAssociationMap::const_iterator mapIterBwd = clusterAssociationMap.find(pCluster);
75 
76  if (clusterAssociationMap.end() == mapIterBwd)
77  continue;
78 
79  if (mapIterBwd->second.m_forwardAssociations.empty() && !mapIterBwd->second.m_backwardAssociations.empty())
80  this->AmbiguousPropagation(pCluster, false, clusterAssociationMap);
81  }
82  }
83 
84  return STATUS_CODE_SUCCESS;
85 }
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
intermediate_table::const_iterator const_iterator
bool m_resolveAmbiguousAssociations
Whether to resolve ambiguous associations.
void AmbiguousPropagation(const pandora::Cluster *const pCluster, const bool isForward, ClusterAssociationMap &clusterAssociationMap) const
Ambiguous propagation.
virtual void PopulateClusterAssociationMap(const pandora::ClusterVector &clusterVector, ClusterAssociationMap &clusterAssociationMap) const =0
Populate the cluster association map.
void UnambiguousPropagation(const pandora::Cluster *const pCluster, const bool isForward, ClusterAssociationMap &clusterAssociationMap) const
Unambiguous propagation.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
virtual void GetListOfCleanClusters(const pandora::ClusterList *const pClusterList, pandora::ClusterVector &clusterVector) const =0
Populate cluster vector with subset of cluster list, containing clusters judged to be clean...

Member Data Documentation

LArHitWidthHelper::ClusterToParametersMap lar_content::HitWidthClusterMergingAlgorithm::m_clusterToParametersMap
mutableprivate

The map [cluster -> cluster parameters].

Definition at line 142 of file HitWidthClusterMergingAlgorithm.h.

Referenced by GetListOfCleanClusters(), and PopulateClusterAssociationMap().

float lar_content::HitWidthClusterMergingAlgorithm::m_fittingWeight
private

The maximum hit weight considered in the least squared fit.

Definition at line 133 of file HitWidthClusterMergingAlgorithm.h.

Referenced by AreClustersAssociated(), and ReadSettings().

float lar_content::HitWidthClusterMergingAlgorithm::m_hitWidthScalingFactor
private

The scaling factor of the hit widths.

Definition at line 132 of file HitWidthClusterMergingAlgorithm.h.

Referenced by GetListOfCleanClusters(), IsExtremalCluster(), and ReadSettings().

float lar_content::HitWidthClusterMergingAlgorithm::m_maxConstituentHitWidth
private

The maximum hit width of a constituent hit of broken up hit, units cm.

Definition at line 131 of file HitWidthClusterMergingAlgorithm.h.

Referenced by GetListOfCleanClusters(), IsExtremalCluster(), and ReadSettings().

float lar_content::HitWidthClusterMergingAlgorithm::m_maxXMergeDistance
private

The maximum x distance between merging points of associated clusters, units cm.

Definition at line 135 of file HitWidthClusterMergingAlgorithm.h.

Referenced by AreClustersAssociated(), and ReadSettings().

float lar_content::HitWidthClusterMergingAlgorithm::m_maxZMergeDistance
private

The maximum z distance between merging points of associated clusters, units cm.

Definition at line 136 of file HitWidthClusterMergingAlgorithm.h.

Referenced by AreClustersAssociated(), and ReadSettings().

float lar_content::HitWidthClusterMergingAlgorithm::m_minClusterSparseness
private

The threshold sparseness of a cluster to be considered in the merging process.

Definition at line 139 of file HitWidthClusterMergingAlgorithm.h.

Referenced by GetListOfCleanClusters(), and ReadSettings().

float lar_content::HitWidthClusterMergingAlgorithm::m_minClusterWeight
private

The threshold hit weight of the original, unscaled cluster to be considered in the merging process.

Definition at line 134 of file HitWidthClusterMergingAlgorithm.h.

Referenced by GetListOfCleanClusters(), and ReadSettings().

float lar_content::HitWidthClusterMergingAlgorithm::m_minDirectionDeviationCosAngle
private

The minimum cosine opening angle of the direction of and associated cluster before and after merge.

Definition at line 138 of file HitWidthClusterMergingAlgorithm.h.

Referenced by AreClustersAssociated(), and ReadSettings().

float lar_content::HitWidthClusterMergingAlgorithm::m_minMergeCosOpeningAngle
private

The minimum cosine opening angle of the directions of associated clusters.

Definition at line 137 of file HitWidthClusterMergingAlgorithm.h.

Referenced by AreClustersAssociated(), and ReadSettings().


The documentation for this class was generated from the following files: