LArTwoDSlidingShowerFitResult.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArObjects/LArTwoDSlidingShowerFitResult.cc
3  *
4  * @brief Implementation of the lar two dimensional sliding shower fit result class.
5  *
6  * $Log: $
7  */
8 
9 #include "Objects/Cluster.h"
10 
12 
14 
15 #include <algorithm>
16 #include <cmath>
17 #include <limits>
18 
19 using namespace pandora;
20 
21 namespace lar_content
22 {
23 
24 template <typename T>
25 TwoDSlidingShowerFitResult::TwoDSlidingShowerFitResult(
26  const T *const pT, const unsigned int slidingFitWindow, const float slidingFitLayerPitch, const float showerEdgeMultiplier) :
27  m_showerFitResult(TwoDSlidingFitResult(pT, slidingFitWindow, slidingFitLayerPitch)),
28  m_negativeEdgeFitResult(TwoDSlidingShowerFitResult::LArTwoDShowerEdgeFit(pT, m_showerFitResult, NEGATIVE_SHOWER_EDGE, showerEdgeMultiplier)),
29  m_positiveEdgeFitResult(TwoDSlidingShowerFitResult::LArTwoDShowerEdgeFit(pT, m_showerFitResult, POSITIVE_SHOWER_EDGE, showerEdgeMultiplier))
30 {
31 }
32 
33 //------------------------------------------------------------------------------------------------------------------------------------------
34 
35 void TwoDSlidingShowerFitResult::GetShowerEdges(const float x, const bool widenIfAmbiguity, FloatVector &edgePositions) const
36 {
37  edgePositions.clear();
38  CartesianPointVector fitPositionVector;
39  PANDORA_THROW_RESULT_IF_AND_IF(
40  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, this->GetNegativeEdgeFitResult().GetGlobalFitPositionListAtX(x, fitPositionVector));
41  PANDORA_THROW_RESULT_IF_AND_IF(
42  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, this->GetPositiveEdgeFitResult().GetGlobalFitPositionListAtX(x, fitPositionVector));
43 
44  if (fitPositionVector.size() < 2)
45  {
46  float minXn(0.f), maxXn(0.f), minXp(0.f), maxXp(0.f);
47  this->GetNegativeEdgeFitResult().GetMinAndMaxX(minXn, maxXn);
48  this->GetPositiveEdgeFitResult().GetMinAndMaxX(minXp, maxXp);
49  const float minX(std::min(minXn, minXp)), maxX(std::max(maxXn, maxXp));
50 
51  if ((x < minX) || (x > maxX))
52  return;
53 
54  float minZn(0.f), maxZn(0.f), minZp(0.f), maxZp(0.f);
55  this->GetNegativeEdgeFitResult().GetMinAndMaxZ(minZn, maxZn);
56  this->GetPositiveEdgeFitResult().GetMinAndMaxZ(minZp, maxZp);
57  const float minZ(std::min(minZn, minZp)), maxZ(std::max(maxZn, maxZp));
58 
59  if (!widenIfAmbiguity)
60  {
61  return;
62  }
63  else if (fitPositionVector.empty())
64  {
65  fitPositionVector.push_back(CartesianVector(x, 0.f, minZ));
66  fitPositionVector.push_back(CartesianVector(x, 0.f, maxZ));
67  }
68  else if (1 == fitPositionVector.size())
69  {
70  // ATTN Could improve sophistication of choice of second bounding edge
71  const float existingEdge(fitPositionVector.front().GetZ());
72  const float secondEdge((std::fabs(existingEdge - minZ) < std::fabs(existingEdge - maxZ)) ? minZ : maxZ);
73  fitPositionVector.push_back(CartesianVector(x, 0.f, secondEdge));
74  }
75  }
76 
77  FloatVector localEdgePositions;
78  for (const CartesianVector &fitPosition : fitPositionVector)
79  localEdgePositions.push_back(fitPosition.GetZ());
80 
81  if (localEdgePositions.size() < 2)
82  throw StatusCodeException(STATUS_CODE_FAILURE);
83 
84  std::sort(localEdgePositions.begin(), localEdgePositions.end());
85  edgePositions.push_back(localEdgePositions.front());
86  edgePositions.push_back(localEdgePositions.back());
87 }
88 
89 //------------------------------------------------------------------------------------------------------------------------------------------
90 
92  const Cluster *const pCluster, const TwoDSlidingFitResult &fullShowerFit, const ShowerEdge showerEdge, const float showerEdgeMultiplier)
93 {
94  CartesianPointVector pointVector;
95  LArClusterHelper::GetCoordinateVector(pCluster, pointVector);
96  return TwoDSlidingShowerFitResult::LArTwoDShowerEdgeFit(&pointVector, fullShowerFit, showerEdge, showerEdgeMultiplier);
97 }
98 
99 //------------------------------------------------------------------------------------------------------------------------------------------
100 
101 TwoDSlidingFitResult TwoDSlidingShowerFitResult::LArTwoDShowerEdgeFit(const CartesianPointVector *const pPointVector,
102  const TwoDSlidingFitResult &fullShowerFit, const ShowerEdge showerEdge, const float showerEdgeMultiplier)
103 {
104  // Examine all possible fit contributions
105  FitCoordinateMap fitCoordinateMap;
106 
107  for (const CartesianVector &hitPosition : *pPointVector)
108  {
109  float rL(0.f), rT(0.f);
110  fullShowerFit.GetLocalPosition(hitPosition, rL, rT);
111  rT *= showerEdgeMultiplier;
112 
113  CartesianVector fullShowerFitPosition(0.f, 0.f, 0.f);
114  if (STATUS_CODE_SUCCESS != fullShowerFit.GetGlobalFitPosition(rL, fullShowerFitPosition))
115  continue;
116 
117  float rLFit(0.f), rTFit(0.f);
118  fullShowerFit.GetLocalPosition(fullShowerFitPosition, rLFit, rTFit);
119 
120  const float rTDiff(rT - rTFit);
121  if (((POSITIVE_SHOWER_EDGE == showerEdge) && (rTDiff < 0.f)) || ((NEGATIVE_SHOWER_EDGE == showerEdge) && (rTDiff > 0.f)))
122  rT = rTFit;
123 
124  const int layer(fullShowerFit.GetLayer(rL));
125  fitCoordinateMap[layer].push_back(FitCoordinate(rL, rT));
126  }
127 
128  // Select fit contributions representing relevant shower edge
129  LayerFitContributionMap layerFitContributionMap;
130 
131  for (const FitCoordinateMap::value_type &mapEntry : fitCoordinateMap)
132  {
133  // ATTN Could modify this hit selection, e.g. add inertia to edge positions
134  bool bestFitCoordinateFound(false);
135  FitCoordinate bestFitCoordinate = (POSITIVE_SHOWER_EDGE == showerEdge) ? FitCoordinate(0.f, -std::numeric_limits<float>::max())
137 
138  for (const FitCoordinate &fitCoordinate : mapEntry.second)
139  {
140  if (((POSITIVE_SHOWER_EDGE == showerEdge) && (fitCoordinate.second > bestFitCoordinate.second)) ||
141  ((NEGATIVE_SHOWER_EDGE == showerEdge) && (fitCoordinate.second < bestFitCoordinate.second)))
142  {
143  bestFitCoordinate = fitCoordinate;
144  bestFitCoordinateFound = true;
145  }
146  }
147 
148  if (bestFitCoordinateFound)
149  layerFitContributionMap[mapEntry.first].AddPoint(bestFitCoordinate.first, bestFitCoordinate.second);
150  }
151 
152  return TwoDSlidingFitResult(fullShowerFit.GetLayerFitHalfWindow(), fullShowerFit.GetLayerPitch(), fullShowerFit.GetAxisIntercept(),
153  fullShowerFit.GetAxisDirection(), fullShowerFit.GetOrthoDirection(), layerFitContributionMap);
154 }
155 
156 //------------------------------------------------------------------------------------------------------------------------------------------
157 //------------------------------------------------------------------------------------------------------------------------------------------
158 
159 template TwoDSlidingShowerFitResult::TwoDSlidingShowerFitResult(const pandora::Cluster *const, const unsigned int, const float, const float);
160 template TwoDSlidingShowerFitResult::TwoDSlidingShowerFitResult(const pandora::CartesianPointVector *const, const unsigned int, const float, const float);
161 
162 } // namespace lar_content
unsigned int GetLayerFitHalfWindow() const
Get the layer fit half window.
Header file for the lar two dimensional sliding shower fit result class.
ShowerEdge
ShowerEdge enum.
void GetMinAndMaxX(float &minX, float &maxX) const
Get the minimum and maximum x coordinates associated with the sliding fit.
std::map< int, FitCoordinateList > FitCoordinateMap
static TwoDSlidingFitResult LArTwoDShowerEdgeFit(const pandora::Cluster *const pCluster, const TwoDSlidingFitResult &fullShowerFit, const ShowerEdge showerEdge, const float showerEdgeMultiplier)
Perform two dimensional sliding fit to shower edge, using specified primary axis. ...
const pandora::CartesianVector & GetAxisDirection() const
Get the axis direction vector.
std::map< int, LayerFitContribution > LayerFitContributionMap
const pandora::CartesianVector & GetAxisIntercept() const
Get the axis intercept position.
void GetMinAndMaxZ(float &minZ, float &maxZ) const
Get the minimum and maximum z coordinates associated with the sliding fit.
Header file for the cluster helper class.
pandora::StatusCode GetGlobalFitPosition(const float rL, pandora::CartesianVector &position) const
Get global fit position for a given longitudinal coordinate.
const pandora::CartesianVector & GetOrthoDirection() const
Get the orthogonal direction vector.
float GetLayerPitch() const
Get the layer pitch, units cm.
const TwoDSlidingFitResult & GetPositiveEdgeFitResult() const
Get the sliding fit result for the positive shower edge.
static int max(int a, int b)
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
const TwoDSlidingFitResult & GetNegativeEdgeFitResult() const
Get the sliding fit result for the negative shower edge.
static void GetCoordinateVector(const pandora::Cluster *const pCluster, pandora::CartesianPointVector &coordinateVector)
Get vector of hit coordinates from an input cluster.
list x
Definition: train.py:276
Dft::FloatVector FloatVector
TwoDSlidingShowerFitResult(const T *const pT, const unsigned int slidingFitWindow, const float slidingFitLayerPitch, const float showerEdgeMultiplier=1.f)
Constructor.
void GetLocalPosition(const pandora::CartesianVector &position, float &rL, float &rT) const
Get local sliding fit coordinates for a given global position.
int GetLayer(const float rL) const
Get layer number for given sliding linear fit longitudinal coordinate.
void GetShowerEdges(const float x, const bool widenIfAmbiguity, pandora::FloatVector &edgePositions) const
Get the most appropriate shower edges at a given x coordinate.