LocalAsymmetryFeatureTool.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArVertex/LocalAsymmetryFeatureTool.cc
3  *
4  * @brief Implementation of the local asymmetry feature tool class.
5  *
6  * $Log: $
7  */
8 
9 #include "Pandora/AlgorithmHeaders.h"
10 
12 
14 
15 using namespace pandora;
16 
17 namespace lar_content
18 {
19 
20 LocalAsymmetryFeatureTool::LocalAsymmetryFeatureTool() :
22  m_minAsymmetryCosAngle(0.9962),
23  m_maxAsymmetryNClusters(2)
24 {
25 }
26 
27 //------------------------------------------------------------------------------------------------------------------------------------------
28 
29 float LocalAsymmetryFeatureTool::GetAsymmetryForView(const CartesianVector &vertexPosition2D,
31 {
32  bool useEnergy(true), useAsymmetry(true);
33  CartesianVector energyWeightedDirectionSum(0.f, 0.f, 0.f), hitWeightedDirectionSum(0.f, 0.f, 0.f);
34  ClusterVector asymmetryClusters;
35 
36  for (const VertexSelectionBaseAlgorithm::SlidingFitData &slidingFitData : slidingFitDataList)
37  {
38  const Cluster *const pCluster(slidingFitData.GetCluster());
39 
40  if (pCluster->GetElectromagneticEnergy() < std::numeric_limits<float>::epsilon())
41  useEnergy = false;
42 
43  const CartesianVector vertexToMinLayer(slidingFitData.GetMinLayerPosition() - vertexPosition2D);
44  const CartesianVector vertexToMaxLayer(slidingFitData.GetMaxLayerPosition() - vertexPosition2D);
45 
46  const bool minLayerClosest(vertexToMinLayer.GetMagnitudeSquared() < vertexToMaxLayer.GetMagnitudeSquared());
47  const CartesianVector &clusterDirection((minLayerClosest) ? slidingFitData.GetMinLayerDirection() : slidingFitData.GetMaxLayerDirection());
48 
49  if (useAsymmetry && (LArClusterHelper::GetClosestDistance(vertexPosition2D, pCluster) < m_maxAsymmetryDistance))
50  {
51  useAsymmetry &= this->CheckAngle(energyWeightedDirectionSum, clusterDirection);
52  this->IncrementAsymmetryParameters(pCluster->GetElectromagneticEnergy(), clusterDirection, energyWeightedDirectionSum);
53 
54  useAsymmetry &= this->CheckAngle(hitWeightedDirectionSum, clusterDirection);
55  this->IncrementAsymmetryParameters(static_cast<float>(pCluster->GetNCaloHits()), clusterDirection, hitWeightedDirectionSum);
56 
57  asymmetryClusters.push_back(pCluster);
58  }
59 
60  if (!useAsymmetry)
61  return 1.f;
62  }
63 
64  // Default: maximum asymmetry (i.e. not suppressed), zero for energy kick (i.e. not suppressed)
65  if ((useEnergy && energyWeightedDirectionSum == CartesianVector(0.f, 0.f, 0.f)) ||
66  (!useEnergy && hitWeightedDirectionSum == CartesianVector(0.f, 0.f, 0.f)))
67  return 1.f;
68 
69  if (asymmetryClusters.empty() || (asymmetryClusters.size() > m_maxAsymmetryNClusters))
70  return 1.f;
71 
72  const CartesianVector &localWeightedDirectionSum(useEnergy ? energyWeightedDirectionSum : hitWeightedDirectionSum);
73  return this->CalculateAsymmetry(useEnergy, vertexPosition2D, asymmetryClusters, localWeightedDirectionSum);
74 }
75 
76 //------------------------------------------------------------------------------------------------------------------------------------------
77 
78 bool LocalAsymmetryFeatureTool::CheckAngle(const CartesianVector &weightedDirectionSum, const CartesianVector &clusterDirection) const
79 {
80  if (!(weightedDirectionSum.GetMagnitudeSquared() > std::numeric_limits<float>::epsilon()))
81  return true;
82 
83  const float cosOpeningAngle(weightedDirectionSum.GetCosOpeningAngle(clusterDirection));
84  return std::fabs(cosOpeningAngle) > m_minAsymmetryCosAngle;
85 }
86 
87 //------------------------------------------------------------------------------------------------------------------------------------------
88 
89 StatusCode LocalAsymmetryFeatureTool::ReadSettings(const TiXmlHandle xmlHandle)
90 {
91  PANDORA_RETURN_RESULT_IF_AND_IF(
92  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinAsymmetryCosAngle", m_minAsymmetryCosAngle));
93 
94  PANDORA_RETURN_RESULT_IF_AND_IF(
95  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxAsymmetryNClusters", m_maxAsymmetryNClusters));
96 
98 }
99 
100 } // namespace lar_content
float GetAsymmetryForView(const pandora::CartesianVector &vertexPosition2D, const VertexSelectionBaseAlgorithm::SlidingFitDataList &slidingFitDataList, const VertexSelectionBaseAlgorithm::ShowerClusterList &) const override
Get the local asymmetry feature in a given view.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle) override
virtual float CalculateAsymmetry(const bool useEnergyMetrics, const pandora::CartesianVector &vertexPosition2D, const pandora::ClusterVector &asymmetryClusters, const pandora::CartesianVector &localWeightedDirectionSum) const
Calculate the asymmetry feature.
bool CheckAngle(const pandora::CartesianVector &weightedDirectionSum, const pandora::CartesianVector &clusterDirection) const
Check whether a cluster&#39;s direction agrees with the current weighted direction.
float m_maxAsymmetryDistance
The max distance between cluster (any hit) and vertex to calculate asymmetry score.
Header file for the cluster helper class.
Header file for the local asymmetry feature tool class.
AsymmetryFeatureBaseTool class.
void IncrementAsymmetryParameters(const float weight, const pandora::CartesianVector &clusterDirection, pandora::CartesianVector &localWeightedDirectionSum) const
Increment the asymmetry parameters.
float m_minAsymmetryCosAngle
The min opening angle cosine used to determine viability of asymmetry score.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
unsigned int m_maxAsymmetryNClusters
The max number of associated clusters to calculate the asymmetry.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.