LArHitWidthHelper.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArHelpers/LArHitWidthHelper.cc
3  *
4  * @brief Implementation of the lar hit width helper class.
5  *
6  * $Log: $
7  */
10 
11 using namespace pandora;
12 
13 namespace lar_content
14 {
15 
16 LArHitWidthHelper::ConstituentHit::ConstituentHit(const CartesianVector &positionVector, const float hitWidth, const Cluster *const pParentClusterAddress) :
17  m_positionVector(positionVector),
18  m_hitWidth(hitWidth),
19  m_pParentClusterAddress(pParentClusterAddress)
20 {
21 }
22 
23 //------------------------------------------------------------------------------------------------------------------------------------------
24 
26 {
27  const CartesianVector &lhsPosition(lhs.GetPositionVector());
28  const CartesianVector &rhsPosition(rhs.GetPositionVector());
29 
30  return (m_referencePoint.GetDistanceSquared(lhsPosition) < m_referencePoint.GetDistanceSquared(rhsPosition));
31 }
32 
33 //------------------------------------------------------------------------------------------------------------------------------------------
34 //------------------------------------------------------------------------------------------------------------------------------------------
35 
37  const Cluster *const pCluster, const float maxConstituentHitWidth, const bool isUniformHits, const float hitWidthScalingFactor) :
38  m_pCluster(pCluster),
39  m_numCaloHits(pCluster->GetNCaloHits()),
40  m_constituentHitVector(LArHitWidthHelper::GetConstituentHits(pCluster, maxConstituentHitWidth, hitWidthScalingFactor, isUniformHits)),
41  m_totalWeight(LArHitWidthHelper::GetTotalClusterWeight(m_constituentHitVector)),
42  m_lowerXExtrema(LArHitWidthHelper::GetExtremalCoordinatesLowerX(m_constituentHitVector)),
43  m_higherXExtrema(LArHitWidthHelper::GetExtremalCoordinatesHigherX(m_constituentHitVector))
44 {
45 }
46 
47 //------------------------------------------------------------------------------------------------------------------------------------------
48 
49 LArHitWidthHelper::ClusterParameters::ClusterParameters(const Cluster *const pCluster, const unsigned int numCaloHits, const float totalWeight,
50  const LArHitWidthHelper::ConstituentHitVector &constituentHitVector, const CartesianVector &lowerXExtrema, const CartesianVector &higherXExtrema) :
51  m_pCluster(pCluster),
52  m_numCaloHits(numCaloHits),
53  m_constituentHitVector(constituentHitVector),
54  m_totalWeight(totalWeight),
55  m_lowerXExtrema(lowerXExtrema),
56  m_higherXExtrema(higherXExtrema)
57 {
58 }
59 
60 //------------------------------------------------------------------------------------------------------------------------------------------
61 //------------------------------------------------------------------------------------------------------------------------------------------
62 
63 bool LArHitWidthHelper::SortByHigherXExtrema::operator()(const Cluster *const pLhs, const Cluster *const pRhs)
64 {
65  const LArHitWidthHelper::ClusterParameters &lhsClusterParameters(LArHitWidthHelper::GetClusterParameters(pLhs, m_clusterToParametersMap));
66  const LArHitWidthHelper::ClusterParameters &rhsClusterParameters(LArHitWidthHelper::GetClusterParameters(pRhs, m_clusterToParametersMap));
67 
68  return (lhsClusterParameters.GetHigherXExtrema().GetX() < rhsClusterParameters.GetHigherXExtrema().GetX());
69 }
70 
71 //------------------------------------------------------------------------------------------------------------------------------------------
72 //------------------------------------------------------------------------------------------------------------------------------------------
73 
75  const Cluster *const pCluster, const ClusterToParametersMap &clusterToParametersMap)
76 {
77  if (clusterToParametersMap.empty())
78  throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
79 
80  const auto clusterParametersIter(clusterToParametersMap.find(pCluster));
81 
82  if (clusterParametersIter == clusterToParametersMap.end())
83  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
84 
85  return clusterParametersIter->second;
86 }
87 
88 //------------------------------------------------------------------------------------------------------------------------------------------
89 
90 unsigned int LArHitWidthHelper::GetNProposedConstituentHits(const Cluster *const pCluster, const float maxConstituentHitWidth, const float hitWidthScalingFactor)
91 {
92  if (maxConstituentHitWidth < std::numeric_limits<float>::epsilon())
93  {
94  std::cout << "LArHitWidthHelper::GetConstituentHits - Negative or equivalent to zero constitent hit width not allowed" << std::endl;
95  throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
96  }
97 
98  const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
99 
100  if (orderedCaloHitList.empty())
101  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
102 
103  unsigned int totalConstituentHits(0);
104  for (const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
105  {
106  for (const CaloHit *const pCaloHit : *mapEntry.second)
107  {
108  const float hitWidth = pCaloHit->GetCellSize1() * hitWidthScalingFactor;
109  const unsigned int numberOfConstituentHits = std::ceil(hitWidth / maxConstituentHitWidth);
110 
111  totalConstituentHits += numberOfConstituentHits;
112  }
113  }
114 
115  return totalConstituentHits;
116 }
117 
118 //------------------------------------------------------------------------------------------------------------------------------------------
119 
121  const Cluster *const pCluster, const float maxConstituentHitWidth, const float hitWidthScalingFactor, const bool isUniform)
122 {
123  if (maxConstituentHitWidth < std::numeric_limits<float>::epsilon())
124  {
125  std::cout << "LArHitWidthHelper::GetConstituentHits - Negative or equivalent to zero constitent hit width not allowed" << std::endl;
126  throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
127  }
128 
129  const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
130 
131  if (orderedCaloHitList.empty())
132  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
133 
134  ConstituentHitVector constituentHitVector;
135  for (const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
136  {
137  for (const CaloHit *const pCaloHit : *mapEntry.second)
138  {
139  const float hitWidth = pCaloHit->GetCellSize1() * hitWidthScalingFactor;
140  const unsigned int numberOfConstituentHits = std::ceil(hitWidth / maxConstituentHitWidth);
141  if (isUniform)
142  {
143  LArHitWidthHelper::SplitHitIntoConstituents(pCaloHit, pCluster, numberOfConstituentHits, maxConstituentHitWidth, constituentHitVector);
144  }
145  else
146  {
147  const float constituentHitWidth = hitWidth / numberOfConstituentHits;
148  LArHitWidthHelper::SplitHitIntoConstituents(pCaloHit, pCluster, numberOfConstituentHits, constituentHitWidth, constituentHitVector);
149  }
150  }
151  }
152 
153  return constituentHitVector;
154 }
155 
156 //------------------------------------------------------------------------------------------------------------------------------------------
157 
158 void LArHitWidthHelper::SplitHitIntoConstituents(const CaloHit *const pCaloHit, const Cluster *const pCluster,
159  const unsigned int numberOfConstituentHits, const float constituentHitWidth, LArHitWidthHelper::ConstituentHitVector &constituentHitVector)
160 {
161  const CartesianVector &hitCenter(pCaloHit->GetPositionVector());
162  const bool isOdd(numberOfConstituentHits % 2 == 1);
163  float xDistanceFromCenter(0.f);
164 
165  // find constituent hit centers by moving out from the original hit center position
166  unsigned int loopIterations(std::ceil(numberOfConstituentHits / 2.0));
167  for (unsigned int i = 0; i < loopIterations; ++i)
168  {
169  if (i == 0)
170  {
171  if (isOdd)
172  {
173  constituentHitVector.push_back(ConstituentHit(hitCenter, constituentHitWidth, pCluster));
174  continue;
175  }
176  else
177  {
178  xDistanceFromCenter += constituentHitWidth / 2;
179  }
180  }
181  else
182  {
183  xDistanceFromCenter += constituentHitWidth;
184  }
185 
186  CartesianVector positivePosition(hitCenter + CartesianVector(xDistanceFromCenter, 0.f, 0.f)),
187  negativePosition(hitCenter - CartesianVector(xDistanceFromCenter, 0.f, 0.f));
188 
189  constituentHitVector.push_back(ConstituentHit(positivePosition, constituentHitWidth, pCluster));
190  constituentHitVector.push_back(ConstituentHit(negativePosition, constituentHitWidth, pCluster));
191  }
192 }
193 
194 //------------------------------------------------------------------------------------------------------------------------------------------
195 
197 {
198  float clusterWeight(0.f);
199  for (const ConstituentHit &constituentHit : constituentHitVector)
200  clusterWeight += constituentHit.GetHitWidth();
201 
202  return clusterWeight;
203 }
204 
205 //------------------------------------------------------------------------------------------------------------------------------------------
206 
207 float LArHitWidthHelper::GetOriginalTotalClusterWeight(const Cluster *const pCluster)
208 {
209  float clusterWeight(0.f);
210  const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
211 
212  for (const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
213  {
214  for (const CaloHit *const pCaloHit : *mapEntry.second)
215  clusterWeight += pCaloHit->GetCellSize1();
216  }
217 
218  return clusterWeight;
219 }
220 
221 //------------------------------------------------------------------------------------------------------------------------------------------
222 
223 CartesianPointVector LArHitWidthHelper::GetConstituentHitPositionVector(const ConstituentHitVector &constituentHitVector)
224 {
225  CartesianPointVector constituentHitPositionVector;
226 
227  for (const ConstituentHit &constituentHit : constituentHitVector)
228  constituentHitPositionVector.push_back(constituentHit.GetPositionVector());
229 
230  return constituentHitPositionVector;
231 }
232 
233 //------------------------------------------------------------------------------------------------------------------------------------------
234 
235 CartesianVector LArHitWidthHelper::GetExtremalCoordinatesLowerX(const ConstituentHitVector &constituentHitVector)
236 {
237  CartesianVector lowerXCoordinate(0.f, 0.f, 0.f), higherXCoordinate(0.f, 0.f, 0.f);
238  LArHitWidthHelper::GetExtremalCoordinatesX(constituentHitVector, lowerXCoordinate, higherXCoordinate);
239 
240  return lowerXCoordinate;
241 }
242 
243 //------------------------------------------------------------------------------------------------------------------------------------------
244 
245 CartesianVector LArHitWidthHelper::GetExtremalCoordinatesHigherX(const ConstituentHitVector &constituentHitVector)
246 {
247  CartesianVector lowerXCoordinate(0.f, 0.f, 0.f), higherXCoordinate(0.f, 0.f, 0.f);
248  LArHitWidthHelper::GetExtremalCoordinatesX(constituentHitVector, lowerXCoordinate, higherXCoordinate);
249 
250  return higherXCoordinate;
251 }
252 
253 //------------------------------------------------------------------------------------------------------------------------------------------
254 
256  const ConstituentHitVector &constituentHitVector, CartesianVector &lowerXCoordinate, CartesianVector &higherXCoordinate)
257 {
258  const CartesianPointVector &constituentHitPositionVector(GetConstituentHitPositionVector(constituentHitVector));
259 
260  CartesianVector innerCoordinate(0.f, 0.f, 0.f), outerCoordinate(0.f, 0.f, 0.f);
261  LArClusterHelper::GetExtremalCoordinates(constituentHitPositionVector, innerCoordinate, outerCoordinate);
262 
263  // set the lower/higher XCoordinate (in the event of a tie, use z)
264  const float deltaX(outerCoordinate.GetX() - innerCoordinate.GetX());
265  const float deltaZ(outerCoordinate.GetZ() - innerCoordinate.GetZ());
266 
267  if ((deltaX > 0.f) || ((std::fabs(deltaX) < std::numeric_limits<float>::epsilon()) && (deltaZ > 0.f)))
268  {
269  lowerXCoordinate = innerCoordinate;
270  higherXCoordinate = outerCoordinate;
271  }
272  else
273  {
274  lowerXCoordinate = outerCoordinate;
275  higherXCoordinate = innerCoordinate;
276  }
277 }
278 
279 //------------------------------------------------------------------------------------------------------------------------------------------
280 
282  const CartesianVector &lineStart, const CartesianVector &lineDirection, const CaloHit *const pCaloHit)
283 {
284  const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
285 
286  if (std::fabs(lineDirection.GetZ()) < std::numeric_limits<float>::epsilon())
287  return hitPosition;
288 
289  float xOnLine(lineStart.GetX());
290  if (std::fabs(lineDirection.GetX()) > std::numeric_limits<float>::epsilon())
291  {
292  const float gradient(lineDirection.GetZ() / lineDirection.GetX());
293  xOnLine += ((hitPosition.GetZ() - lineStart.GetZ()) / gradient);
294  }
295 
296  const float &hitWidth(pCaloHit->GetCellSize1());
297  const float hitLowXEdge(hitPosition.GetX() - (hitWidth * 0.5f));
298  const float hitHighXEdge(hitPosition.GetX() + (hitWidth * 0.5f));
299  const float closestPointX(xOnLine < hitLowXEdge ? hitLowXEdge : xOnLine > hitHighXEdge ? hitHighXEdge : xOnLine);
300 
301  return CartesianVector(closestPointX, 0.f, hitPosition.GetZ());
302 }
303 
304 //------------------------------------------------------------------------------------------------------------------------------------------
305 
306 float LArHitWidthHelper::GetClosestDistanceToPoint2D(const CaloHit *const pCaloHit, const CartesianVector &point2D)
307 {
308  const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
309  const float hitWidth(pCaloHit->GetCellSize1());
310  const float hitLowXEdge(hitPosition.GetX() - (hitWidth * 0.5f));
311  const float hitHighXEdge(hitPosition.GetX() + (hitWidth * 0.5f));
312  const float modDeltaZ(std::fabs(hitPosition.GetZ() - point2D.GetZ()));
313 
314  if ((hitLowXEdge < point2D.GetX()) && (hitHighXEdge > point2D.GetX()))
315  return modDeltaZ;
316 
317  const float deltaX = hitLowXEdge > point2D.GetX() ? (point2D.GetX() - hitLowXEdge) : (point2D.GetX() - hitHighXEdge);
318 
319  return std::sqrt((deltaX * deltaX) + (modDeltaZ * modDeltaZ));
320 }
321 
322 } // namespace lar_content
static float GetOriginalTotalClusterWeight(const pandora::Cluster *const pCluster)
Sum the widths of the original, unscaled hits contained within a cluster.
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...
Header file for the lar hit width helper class.
bool operator()(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by the higher x extremal point of their constituent hits.
static void SplitHitIntoConstituents(const pandora::CaloHit *const pCaloHit, const pandora::Cluster *const pCluster, const unsigned int numberOfConstituentHits, const float constituentHitWidth, ConstituentHitVector &constituentHitVector)
Break up the calo hit into constituent hits.
static void GetExtremalCoordinatesX(const ConstituentHitVector &constituentHitVector, pandora::CartesianVector &lowerXCoordinate, pandora::CartesianVector &higherXCoordinate)
Calculate the higher and lower x extremal points of the constituent hits.
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.
static pandora::CartesianVector GetClosestPointToLine2D(const pandora::CartesianVector &lineStart, const pandora::CartesianVector &lineDirection, const pandora::CaloHit *const pCaloHit)
Consider the hit width to find the closest position of a calo hit to a specified line.
const pandora::CartesianVector & GetPositionVector() const
Returns the constituent hit central position.
Header file for the cluster helper class.
const pandora::CartesianVector & GetHigherXExtrema() const
Returns the higher x extremal point of the constituent hits.
std::vector< ConstituentHit > ConstituentHitVector
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.
static pandora::CartesianPointVector GetConstituentHitPositionVector(const ConstituentHitVector &constituentHitVector)
Obtain a vector of the contituent hit central positions.
static pandora::CartesianVector GetExtremalCoordinatesLowerX(const ConstituentHitVector &constituentHitVector)
Return the lower x extremal point of the constituent hits.
static float GetTotalClusterWeight(const ConstituentHitVector &constituentHitVector)
Sum the widths of constituent hits.
static float GetClosestDistanceToPoint2D(const pandora::CaloHit *const pCaloHit, const pandora::CartesianVector &point2D)
Consider the hit width to find the smallest distance between a calo hit and a given point...
ConstituentHit(const pandora::CartesianVector &positionVector, const float hitWidth, const pandora::Cluster *const pParentClusterAddress)
Constructor.
static void GetExtremalCoordinates(const pandora::ClusterList &clusterList, pandora::CartesianVector &innerCoordinate, pandora::CartesianVector &outerCoordinate)
Get positions of the two most distant calo hits in a list of cluster (ordered by Z) ...
static pandora::CartesianVector GetExtremalCoordinatesHigherX(const ConstituentHitVector &constituentHitVector)
Return the higher x extremal point of the constituent hits.
bool operator()(const ConstituentHit &lhs, const ConstituentHit &rhs)
Sort constituent hits by their position relative to a referencePoint.
std::unordered_map< const pandora::Cluster *, const ClusterParameters > ClusterToParametersMap
ClusterParameters(const pandora::Cluster *const pCluster, const float maxConsituentHitWidth, const bool isUniformHits, const float hitWidthScalingFactor)
Constructor.
QTextStream & endl(QTextStream &s)