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)
42 for (
const Cluster *
const pCluster : *pClusterList)
48 const unsigned int numberOfProposedConstituentHits(
51 if (numberOfProposedConstituentHits == 0)
55 const float clusterSparseness(1.f - (
static_cast<float>(pCluster->GetNCaloHits()) /
static_cast<float>(numberOfProposedConstituentHits)));
63 clusterVector.push_back(pCluster);
74 for (ClusterVector::const_iterator iterCurrentCluster = clusterVector.begin(); iterCurrentCluster != clusterVector.end(); ++iterCurrentCluster)
76 const Cluster *
const pCurrentCluster = *iterCurrentCluster;
80 for (ClusterVector::const_iterator iterTestCluster = iterCurrentCluster; iterTestCluster != clusterVector.end(); ++iterTestCluster)
82 if (iterCurrentCluster == iterTestCluster)
85 const Cluster *
const pTestCluster = *iterTestCluster;
92 clusterAssociationMap[pCurrentCluster].m_forwardAssociations.insert(pTestCluster);
93 clusterAssociationMap[pTestCluster].m_backwardAssociations.insert(pCurrentCluster);
111 float currentMaxX(currentHigherXExtrema.
GetX()), testMaxX(testHigherXExtrema.
GetX());
115 if (std::fabs(testMaxX - currentMaxX) > std::numeric_limits<float>::epsilon())
116 return (testMaxX > currentMaxX);
120 if (std::fabs(testMaxX - currentMaxX) > std::numeric_limits<float>::epsilon())
121 return (testMaxX < currentMaxX);
161 CartesianVector currentClusterDirection(0.f, 0.f, 0.f), testClusterDirection(0.f, 0.f, 0.f);
180 newConstituentHitVector.insert(newConstituentHitVector.end(), testFitParameters.
GetConstituentHitVector().begin(),
209 float minDistanceSquared(std::numeric_limits<float>::max());
212 const CartesianVector &hitPosition(constituentHit.GetPositionVector());
215 if (separationDistanceSquared < minDistanceSquared)
217 minDistanceSquared = separationDistanceSquared;
218 closestPoint = hitPosition;
228 float weightSum(0.f), weightedLSum(0.f), weightedTSum(0.f);
229 bool isLConstant(
true), isTConstant(
true);
236 CartesianVector axisDirection(0.f, 0.f, 0.f), orthoDirection(0.f, 0.f, 0.f);
237 this->
GetFittingAxes(constituentHitSubsetVector, axisDirection, orthoDirection);
240 float firstHitL(0.f), firstHitT(0.f);
241 this->
GetFittingCoordinates(axisDirection, constituentHitSubsetVector.begin()->GetPositionVector(), firstHitL, firstHitT);
245 const float hitWeight(constituentHit.GetHitWidth());
246 float rL(0.f), rT(0.f);
249 if (std::fabs(firstHitL - rL) > std::numeric_limits<float>::epsilon())
252 if (std::fabs(firstHitT - rT) > std::numeric_limits<float>::epsilon())
255 weightedLSum += rL * hitWeight;
256 weightedTSum += rT * hitWeight;
257 weightSum += hitWeight;
260 if (weightSum < std::numeric_limits<float>::epsilon())
262 std::cout <<
"HitWidthClusterMergingAlgorithm::GetWeightedGradient - hit weight in fit is negative or equivalent to zero" << std::endl;
270 direction = (orthoDirection.
GetX() < 0.f) ? orthoDirection * (-1.f) : orthoDirection;
278 direction = (axisDirection.GetX() < 0.f) ? axisDirection * (-1.f) : axisDirection;
282 const float weightedLMean(weightedLSum / weightSum), weightedTMean(weightedTSum / weightSum);
283 float numerator(0.f), denominator(0.f);
287 const float hitWeight(constituentHit.GetHitWidth());
288 float rL(0.f), rT(0.f);
291 numerator += hitWeight * (rL - weightedLMean) * (rT - weightedTMean);
292 denominator += hitWeight * pow(rL - weightedLMean, 2);
295 const float gradient(numerator / denominator);
301 if (direction.
GetX() < 0.f)
313 std::sort(sortedConstituentHitVector.begin(), sortedConstituentHitVector.end(),
316 float weightCount(0.f);
319 constituentHitSubsetVector.push_back(constituentHit);
321 weightCount += constituentHit.GetHitWidth();
323 if (weightCount > fittingWeight)
335 if (constituentHitSubsetPositionVector.size() < 2)
343 axisDirection = eigenVecs.at(0);
346 if (axisDirection.
GetZ() < 0.f)
347 axisDirection *= -1.f;
361 const float openingAngle(axisDirection.
GetOpeningAngle(xAxis)), c(std::cos(openingAngle)), s(std::sin(openingAngle));
363 rL = (c * constituentHitPosition.
GetX()) + (s * constituentHitPosition.
GetZ());
364 rT = (c * constituentHitPosition.
GetZ()) - (s * constituentHitPosition.
GetX());
372 const float openingAngle(axisDirection.
GetOpeningAngle(xAxis)), c(std::cos(openingAngle)), s(std::sin(openingAngle));
373 const float deltaL(1.f), deltaT(gradient);
375 const float x = (c * deltaL) - (s * deltaT);
376 const float z = (c * deltaT) + (s * deltaL);
389 for (
const Cluster *
const pCluster : clusterVector)
391 const ClusterAssociationMap::const_iterator primaryMapIter = clusterAssociationMap.find(pCluster);
393 if (primaryMapIter == clusterAssociationMap.end())
398 primaryMapIter->second.m_forwardAssociations.begin(), primaryMapIter->second.m_forwardAssociations.end());
402 for (
const Cluster *
const pConsideredCluster : primaryForwardAssociations)
404 for (
const Cluster *
const pPrimaryCluster : primaryForwardAssociations)
406 if (pConsideredCluster == pPrimaryCluster)
409 const ClusterAssociationMap::const_iterator secondaryMapIter = clusterAssociationMap.find(pPrimaryCluster);
412 if (secondaryMapIter == clusterAssociationMap.end())
415 const ClusterSet &secondaryForwardAssociations(secondaryMapIter->second.m_forwardAssociations);
417 if (secondaryForwardAssociations.find(pConsideredCluster) != secondaryForwardAssociations.end())
419 ClusterSet &tempPrimaryForwardAssociations(tempMap.find(pCluster)->second.m_forwardAssociations);
420 const ClusterSet::const_iterator forwardAssociationToRemove(tempPrimaryForwardAssociations.find(pConsideredCluster));
423 if (forwardAssociationToRemove == tempPrimaryForwardAssociations.end())
426 ClusterSet &tempPrimaryBackwardAssociations(tempMap.find(pConsideredCluster)->second.m_backwardAssociations);
427 const ClusterSet::const_iterator backwardAssociationToRemove(tempPrimaryBackwardAssociations.find(pCluster));
430 if (backwardAssociationToRemove == tempPrimaryBackwardAssociations.end())
433 tempPrimaryForwardAssociations.erase(forwardAssociationToRemove);
434 tempPrimaryBackwardAssociations.erase(backwardAssociationToRemove);
440 clusterAssociationMap = tempMap;
Header file for the hit width cluster merging algorithm class.
Header file for the cluster helper class.
Header file for the geometry helper class.
Header file for the principal curve analysis helper class.
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
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.
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.
bool AreClustersAssociated(const LArHitWidthHelper::ClusterParameters ¤tClusterParameters, const LArHitWidthHelper::ClusterParameters &testClusterParameters) const
Determine whether two clusters are associated.
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...
float m_maxXMergeDistance
The maximum x distance between merging points of associated clusters, units cm.
void RemoveShortcutAssociations(const pandora::ClusterVector &clusterVector, ClusterAssociationMap &clusterAssociationMap) const
Remove 'shortcut' associations from the cluster association map.
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.
HitWidthClusterMergingAlgorithm()
Default constructor.
float m_maxConstituentHitWidth
The maximum hit width of a constituent hit of broken up hit, units cm.
float m_minClusterWeight
The threshold hit weight of the original, unscaled cluster to be considered in the merging process.
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 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.
void PopulateClusterAssociationMap(const pandora::ClusterVector &clusterVector, ClusterAssociationMap &clusterAssociationMap) const
Populate the cluster association map.
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.
LArHitWidthHelper::ClusterToParametersMap m_clusterToParametersMap
The map [cluster -> cluster parameters].
float m_hitWidthScalingFactor
The scaling factor of the hit widths.
bool IsExtremalCluster(const bool isForward, const pandora::Cluster *const pCurrentCluster, const pandora::Cluster *const pTestCluster) const
Determine which of two clusters is extremal.
void GetFittingAxes(const LArHitWidthHelper::ConstituentHitVector &constituentHitSubsetVector, pandora::CartesianVector &axisDirection, pandora::CartesianVector &orthoDirection) const
Obtain the axes of the fitting frame.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
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_minDirectionDeviationCosAngle
The minimum cosine opening angle of the direction of and associated cluster before and after merge.
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,...
const pandora::CartesianVector & GetHigherXExtrema() const
Returns the higher x extremal point of the constituent hits.
const pandora::CartesianVector & GetLowerXExtrema() const
Returns the lower x extremal point of the constituent hits.
const ConstituentHitVector & GetConstituentHitVector() const
Returns the vector of constituent hits.
SortByDistanceToPoint class.
SortByHigherExtrema class.
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.
std::vector< ConstituentHit > ConstituentHitVector
static pandora::CartesianPointVector GetConstituentHitPositionVector(const ConstituentHitVector &constituentHitVector)
Obtain a vector of the contituent hit central positions.
static pandora::CartesianVector GetExtremalCoordinatesHigherX(const ConstituentHitVector &constituentHitVector)
Return the higher x extremal point of the constituent hits.
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...
static float GetOriginalTotalClusterWeight(const pandora::Cluster *const pCluster)
Sum the widths of the original, unscaled hits contained within a cluster.
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< pandora::CartesianVector > EigenVectors
static void RunPca(const T &t, pandora::CartesianVector ¢roid, 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...
void SetValues(float x, float y, float z)
Set the values of cartesian vector components.
float GetCosOpeningAngle(const CartesianVector &rhs) const
Get the cosine of the opening angle of the cartesian vector with respect to a second cartesian vector...
float GetX() const
Get the cartesian x coordinate.
float GetDistanceSquared(const CartesianVector &rhs) const
Get the distance squared of a cartesian vector with respect to a second cartesian vector.
CartesianVector GetUnitVector() const
Get a unit vector in the direction of the cartesian vector.
float GetZ() const
Get the cartesian z coordinate.
CartesianVector GetCrossProduct(const CartesianVector &rhs) const
Get the cross product of the cartesian vector with a second cartesian vector.
float GetOpeningAngle(const CartesianVector &rhs) const
Get the opening angle of the cartesian vector with respect to a second cartesian vector.
StatusCodeException class.
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
std::vector< const Cluster * > ClusterVector
MANAGED_CONTAINER< const Cluster * > ClusterList
std::vector< CartesianVector > CartesianPointVector
std::unordered_set< const Cluster * > ClusterSet
StatusCode
The StatusCode enum.