AsymmetryFeatureBaseTool.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArVertex/AsymmetryFeatureBaseTool.cc
3  *
4  * @brief Implementation of the asymmetry feature tool class.
5  *
6  * $Log: $
7  */
8 
10 #include "Pandora/AlgorithmHeaders.h"
13 
14 using namespace pandora;
15 
16 namespace lar_content
17 {
18 
19 AsymmetryFeatureBaseTool::AsymmetryFeatureBaseTool() : m_maxAsymmetryDistance(5.f)
20 {
21 }
22 
23 //------------------------------------------------------------------------------------------------------------------------------------------
24 
26  const Vertex *const pVertex, const VertexSelectionBaseAlgorithm::SlidingFitDataListMap &slidingFitDataListMap,
28  const VertexSelectionBaseAlgorithm::ShowerClusterListMap &showerClusterListMap, const float, float &)
29 {
30  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
31  std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
32 
33  float asymmetry(0.f);
34 
35  asymmetry += this->GetAsymmetryForView(LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex->GetPosition(), TPC_VIEW_U),
36  slidingFitDataListMap.at(TPC_VIEW_U),
37  showerClusterListMap.empty() ? VertexSelectionBaseAlgorithm::ShowerClusterList() : showerClusterListMap.at(TPC_VIEW_U));
38 
39  asymmetry += this->GetAsymmetryForView(LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex->GetPosition(), TPC_VIEW_V),
40  slidingFitDataListMap.at(TPC_VIEW_V),
41  showerClusterListMap.empty() ? VertexSelectionBaseAlgorithm::ShowerClusterList() : showerClusterListMap.at(TPC_VIEW_V));
42 
43  asymmetry += this->GetAsymmetryForView(LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex->GetPosition(), TPC_VIEW_W),
44  slidingFitDataListMap.at(TPC_VIEW_W),
45  showerClusterListMap.empty() ? VertexSelectionBaseAlgorithm::ShowerClusterList() : showerClusterListMap.at(TPC_VIEW_W));
46 
47  featureVector.push_back(asymmetry);
48 }
49 
50 //------------------------------------------------------------------------------------------------------------------------------------------
51 
53  const float weight, const CartesianVector &clusterDirection, CartesianVector &localWeightedDirectionSum) const
54 {
55  // If the new axis direction is at an angle of greater than 90 deg to the current axis direction, flip it 180 degs.
56  CartesianVector newDirection(clusterDirection);
57 
58  if (localWeightedDirectionSum.GetMagnitudeSquared() > std::numeric_limits<float>::epsilon())
59  {
60  if (localWeightedDirectionSum.GetCosOpeningAngle(clusterDirection) < 0.f)
61  newDirection *= -1.f;
62  }
63 
64  localWeightedDirectionSum += newDirection * weight;
65 }
66 
67 //------------------------------------------------------------------------------------------------------------------------------------------
68 
69 float AsymmetryFeatureBaseTool::CalculateAsymmetry(const bool useEnergyMetrics, const CartesianVector &vertexPosition2D,
70  const ClusterVector &asymmetryClusters, const CartesianVector &localWeightedDirectionSum) const
71 {
72  // Project every hit onto local event axis direction and record side of the projected vtx position on which it falls
73  float beforeVtxHitEnergy(0.f), afterVtxHitEnergy(0.f);
74  unsigned int beforeVtxHitCount(0), afterVtxHitCount(0);
75 
76  const CartesianVector localWeightedDirection(localWeightedDirectionSum.GetUnitVector());
77  const float evtProjectedVtxPos(vertexPosition2D.GetDotProduct(localWeightedDirection));
78 
79  for (const Cluster *const pCluster : asymmetryClusters)
80  {
81  CaloHitList caloHitList;
82  pCluster->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
83 
84  CaloHitVector caloHitVector(caloHitList.begin(), caloHitList.end());
85  std::sort(caloHitVector.begin(), caloHitVector.end(), LArClusterHelper::SortHitsByPosition);
86 
87  for (const CaloHit *const pCaloHit : caloHitVector)
88  {
89  if (pCaloHit->GetPositionVector().GetDotProduct(localWeightedDirection) < evtProjectedVtxPos)
90  {
91  beforeVtxHitEnergy += pCaloHit->GetElectromagneticEnergy();
92  ++beforeVtxHitCount;
93  }
94  else
95  {
96  afterVtxHitEnergy += pCaloHit->GetElectromagneticEnergy();
97  ++afterVtxHitCount;
98  }
99  }
100  }
101 
102  // Use energy metrics if possible, otherwise fall back on hit counting.
103  const float totHitEnergy(beforeVtxHitEnergy + afterVtxHitEnergy);
104  const unsigned int totHitCount(beforeVtxHitCount + afterVtxHitCount);
105 
106  if (useEnergyMetrics && (totHitEnergy > std::numeric_limits<float>::epsilon()))
107  return std::fabs((afterVtxHitEnergy - beforeVtxHitEnergy)) / totHitEnergy;
108 
109  if (0 == totHitCount)
110  throw StatusCodeException(STATUS_CODE_FAILURE);
111 
112  return std::fabs((static_cast<float>(afterVtxHitCount) - static_cast<float>(beforeVtxHitCount))) / static_cast<float>(totHitCount);
113 }
114 
115 //------------------------------------------------------------------------------------------------------------------------------------------
116 
117 StatusCode AsymmetryFeatureBaseTool::ReadSettings(const TiXmlHandle xmlHandle)
118 {
119  PANDORA_RETURN_RESULT_IF_AND_IF(
120  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxAsymmetryDistance", m_maxAsymmetryDistance));
121 
122  return STATUS_CODE_SUCCESS;
123 }
124 
125 } // namespace lar_content
MvaTypes::MvaFeatureVector MvaFeatureVector
Definition: LArMvaHelper.h:58
virtual float CalculateAsymmetry(const bool useEnergyMetrics, const pandora::CartesianVector &vertexPosition2D, const pandora::ClusterVector &asymmetryClusters, const pandora::CartesianVector &localWeightedDirectionSum) const
Calculate the asymmetry feature.
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
virtual float GetAsymmetryForView(const pandora::CartesianVector &vertexPosition2D, const VertexSelectionBaseAlgorithm::SlidingFitDataList &slidingFitDataList, const VertexSelectionBaseAlgorithm::ShowerClusterList &showerClusterList) const =0
Get the asymmetry feature for a given view.
float m_maxAsymmetryDistance
The max distance between cluster (any hit) and vertex to calculate asymmetry score.
weight
Definition: test.py:257
Header file for the geometry helper class.
std::map< pandora::HitType, const ShowerClusterList > ShowerClusterListMap
Map of shower cluster lists for passing to tools.
static bool SortHitsByPosition(const pandora::CaloHit *const pLhs, const pandora::CaloHit *const pRhs)
Sort calo hits by their position (use Z, followed by X, followed by Y)
Header file for the cluster helper class.
std::map< pandora::HitType, const pandora::ClusterList & > ClusterListMap
Map array of cluster lists for passing to tools.
Header file for the global asymmetry feature tool class.
void Run(LArMvaHelper::MvaFeatureVector &featureVector, const VertexSelectionBaseAlgorithm *const pAlgorithm, const pandora::Vertex *const pVertex, const VertexSelectionBaseAlgorithm::SlidingFitDataListMap &slidingFitDataListMap, const VertexSelectionBaseAlgorithm::ClusterListMap &, const VertexSelectionBaseAlgorithm::KDTreeMap &, const VertexSelectionBaseAlgorithm::ShowerClusterListMap &showerClusterListMap, const float, float &)
Run the tool.
std::map< pandora::HitType, const SlidingFitDataList > SlidingFitDataListMap
Map of sliding fit data lists for passing to tools.
void IncrementAsymmetryParameters(const float weight, const pandora::CartesianVector &clusterDirection, pandora::CartesianVector &localWeightedDirectionSum) const
Increment the asymmetry parameters.
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
Definition: ModuleGraph.h:25
std::map< pandora::HitType, const std::reference_wrapper< HitKDTree2D > > KDTreeMap
Map array of hit kd trees for passing to tools.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
QTextStream & endl(QTextStream &s)