EnergyDepositionAsymmetryFeatureTool.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArVertex/EnergyDepositionAsymmetryFeatureTool.cc
3  *
4  * @brief Implementation of the energy deposition 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 EnergyDepositionAsymmetryFeatureTool::EnergyDepositionAsymmetryFeatureTool() : GlobalAsymmetryFeatureTool()
20 {
21 }
22 
23 //------------------------------------------------------------------------------------------------------------------------------------------
24 
25 float EnergyDepositionAsymmetryFeatureTool::CalculateAsymmetry(const bool useEnergyMetrics, const CartesianVector &vertexPosition2D,
26  const ClusterVector &clusterVector, const CartesianVector &localWeightedDirectionSum) const
27 {
28  // Project every hit onto local event axis direction and record side of the projected vtx position on which it falls
29  float beforeVtxEnergy(0.f), afterVtxEnergy(0.f);
30  unsigned int beforeVtxHits(0), afterVtxHits(0);
31 
32  const CartesianVector localWeightedDirection(localWeightedDirectionSum.GetUnitVector());
33  const float evtProjectedVtxPos(vertexPosition2D.GetDotProduct(localWeightedDirection));
34 
35  float minBeforeProjectedPos(std::numeric_limits<float>::max());
36  float maxBeforeProjectedPos(-std::numeric_limits<float>::max());
37 
38  float minAfterProjectedPos(std::numeric_limits<float>::max());
39  float maxAfterProjectedPos(-std::numeric_limits<float>::max());
40 
41  for (const Cluster *const pCluster : clusterVector)
42  {
43  CaloHitList caloHitList;
44  pCluster->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
45 
46  CaloHitVector caloHitVector(caloHitList.begin(), caloHitList.end());
47  std::sort(caloHitVector.begin(), caloHitVector.end(), LArClusterHelper::SortHitsByPosition);
48 
49  for (const CaloHit *const pCaloHit : caloHitVector)
50  {
51  if (pCaloHit->GetPositionVector().GetDotProduct(localWeightedDirection) < evtProjectedVtxPos)
52  {
53  minBeforeProjectedPos = std::min(minBeforeProjectedPos, pCaloHit->GetPositionVector().GetDotProduct(localWeightedDirection));
54  maxBeforeProjectedPos = std::max(maxBeforeProjectedPos, pCaloHit->GetPositionVector().GetDotProduct(localWeightedDirection));
55 
56  beforeVtxEnergy += pCaloHit->GetElectromagneticEnergy();
57  ++beforeVtxHits;
58  }
59 
60  else
61  {
62  minAfterProjectedPos = std::min(minAfterProjectedPos, pCaloHit->GetPositionVector().GetDotProduct(localWeightedDirection));
63  maxAfterProjectedPos = std::max(maxAfterProjectedPos, pCaloHit->GetPositionVector().GetDotProduct(localWeightedDirection));
64 
65  afterVtxEnergy += pCaloHit->GetElectromagneticEnergy();
66  ++afterVtxHits;
67  }
68  }
69  }
70 
71  // Use energy metrics if possible, otherwise fall back on hit counting.
72  const unsigned int totalHits(beforeVtxHits + afterVtxHits);
73 
74  const float beforeLength(std::fabs(maxBeforeProjectedPos - minBeforeProjectedPos));
75  const float afterLength(std::fabs(maxAfterProjectedPos - minAfterProjectedPos));
76 
77  const float beforeVtxEnergyDeposition(beforeLength < std::numeric_limits<float>::epsilon() ? 0 : beforeVtxEnergy / beforeLength);
78 
79  const float afterVtxEnergyDeposition(afterLength < std::numeric_limits<float>::epsilon() ? 0 : afterVtxEnergy / afterLength);
80 
81  const float totalEnergyDeposition(beforeVtxEnergyDeposition + afterVtxEnergyDeposition);
82 
83  if (useEnergyMetrics && totalEnergyDeposition > std::numeric_limits<float>::epsilon())
84  return std::fabs((afterVtxEnergyDeposition - beforeVtxEnergyDeposition)) / totalEnergyDeposition;
85 
86  if (0 == totalHits)
87  throw StatusCodeException(STATUS_CODE_FAILURE);
88 
89  const float beforeVtxHitDeposition(beforeLength < std::numeric_limits<float>::epsilon() ? 0 : beforeVtxHits / beforeLength);
90 
91  const float afterVtxHitDeposition(afterLength < std::numeric_limits<float>::epsilon() ? 0 : afterVtxHits / afterLength);
92 
93  const float totalHitDeposition(beforeVtxHitDeposition + afterVtxHitDeposition);
94 
95  if (totalHitDeposition > std::numeric_limits<float>::epsilon())
96  return std::fabs((afterVtxHitDeposition - beforeVtxHitDeposition)) / totalHitDeposition;
97 
98  return 0.f;
99 }
100 
101 //------------------------------------------------------------------------------------------------------------------------------------------
102 
103 StatusCode EnergyDepositionAsymmetryFeatureTool::ReadSettings(const TiXmlHandle xmlHandle)
104 {
106 }
107 
108 } // namespace lar_content
float CalculateAsymmetry(const bool useEnergyMetrics, const pandora::CartesianVector &vertexPosition2D, const pandora::ClusterVector &clusterVector, const pandora::CartesianVector &localWeightedDirectionSum) const override
Calculate the energy deposition asymmetry feature.
Header file for the energy deposition asymmetry feature tool class.
Header file for the geometry helper class.
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.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle) override
static int max(int a, int b)
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle) override
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
std::vector< art::Ptr< recob::Cluster > > ClusterVector