LArClusterHelper.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArHelpers/LArClusterHelper.cc
3  *
4  * @brief Implementation of the cluster helper class.
5  *
6  * $Log: $
7  */
8 
11 
12 #include <algorithm>
13 #include <cmath>
14 #include <limits>
15 
16 using namespace pandora;
17 
18 namespace lar_content
19 {
20 
21 HitType LArClusterHelper::GetClusterHitType(const Cluster *const pCluster)
22 {
23  if (0 == pCluster->GetNCaloHits())
24  throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
25 
26  // TODO Find a way of confirming single hit-type clustering mode; currently only checked in ListPreparation algorithm
27  // if (!pandora->GetSettings()->SingleHitTypeClusteringMode())
28  // throw StatusCodeException(STATUS_CODE_FAILURE);
29 
30  return (*(pCluster->GetOrderedCaloHitList().begin()->second->begin()))->GetHitType();
31 }
32 
33 //------------------------------------------------------------------------------------------------------------------------------------------
34 
35 void LArClusterHelper::GetClustersUVW(const ClusterList &inputClusters, ClusterList &clusterListU, ClusterList &clusterListV, ClusterList &clusterListW)
36 {
37  for (ClusterList::const_iterator iter = inputClusters.begin(), iterEnd = inputClusters.end(); iter != iterEnd; ++iter)
38  {
39  const HitType hitType(LArClusterHelper::GetClusterHitType(*iter));
40 
41  if (TPC_VIEW_U == hitType)
42  clusterListU.push_back(*iter);
43  else if (TPC_VIEW_V == hitType)
44  clusterListV.push_back(*iter);
45  else if (TPC_VIEW_W == hitType)
46  clusterListW.push_back(*iter);
47  else
48  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
49  }
50 }
51 
52 //------------------------------------------------------------------------------------------------------------------------------------------
53 
54 void LArClusterHelper::GetClustersByHitType(const ClusterList &inputClusters, const HitType hitType, ClusterList &clusterList)
55 {
56  for (ClusterList::const_iterator iter = inputClusters.begin(), iterEnd = inputClusters.end(); iter != iterEnd; ++iter)
57  {
58  if (hitType == LArClusterHelper::GetClusterHitType(*iter))
59  clusterList.push_back(*iter);
60  }
61 }
62 
63 //------------------------------------------------------------------------------------------------------------------------------------------
64 
65 float LArClusterHelper::GetLengthSquared(const Cluster *const pCluster)
66 {
67  const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
68 
69  if (orderedCaloHitList.empty())
70  throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
71 
72  // ATTN In 2D case, we will actually calculate the quadrature sum of deltaX and deltaU/V/W
76 
77  for (OrderedCaloHitList::const_iterator iter = orderedCaloHitList.begin(), iterEnd = orderedCaloHitList.end(); iter != iterEnd; ++iter)
78  {
79  for (CaloHitList::const_iterator hitIter = iter->second->begin(), hitIterEnd = iter->second->end(); hitIter != hitIterEnd; ++hitIter)
80  {
81  const CartesianVector &hitPosition((*hitIter)->GetPositionVector());
82  minX = std::min(hitPosition.GetX(), minX);
83  maxX = std::max(hitPosition.GetX(), maxX);
84  minY = std::min(hitPosition.GetY(), minY);
85  maxY = std::max(hitPosition.GetY(), maxY);
86  minZ = std::min(hitPosition.GetZ(), minZ);
87  maxZ = std::max(hitPosition.GetZ(), maxZ);
88  }
89  }
90 
91  const float deltaX(maxX - minX), deltaY(maxY - minY), deltaZ(maxZ - minZ);
92  return (deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ);
93 }
94 
95 //------------------------------------------------------------------------------------------------------------------------------------------
96 
97 float LArClusterHelper::GetLength(const Cluster *const pCluster)
98 {
99  return std::sqrt(LArClusterHelper::GetLengthSquared(pCluster));
100 }
101 
102 //------------------------------------------------------------------------------------------------------------------------------------------
103 
104 float LArClusterHelper::GetEnergyFromLength(const Cluster *const pCluster)
105 {
106  const float dEdX(0.002f); // approximately 2 MeV/cm
107  return (dEdX * LArClusterHelper::GetLength(pCluster));
108 }
109 
110 //------------------------------------------------------------------------------------------------------------------------------------------
111 
112 unsigned int LArClusterHelper::GetLayerSpan(const Cluster *const pCluster)
113 {
114  return (1 + pCluster->GetOuterPseudoLayer() - pCluster->GetInnerPseudoLayer());
115 }
116 
117 //------------------------------------------------------------------------------------------------------------------------------------------
118 
119 float LArClusterHelper::GetLayerOccupancy(const Cluster *const pCluster)
120 {
121  const unsigned int nOccupiedLayers(pCluster->GetOrderedCaloHitList().size());
122  const unsigned int nLayers(1 + pCluster->GetOuterPseudoLayer() - pCluster->GetInnerPseudoLayer());
123 
124  if (nLayers > 0)
125  return (static_cast<float>(nOccupiedLayers) / static_cast<float>(nLayers));
126 
127  return 0.f;
128 }
129 
130 //------------------------------------------------------------------------------------------------------------------------------------------
131 
132 float LArClusterHelper::GetLayerOccupancy(const Cluster *const pCluster1, const Cluster *const pCluster2)
133 {
134  const unsigned int nOccupiedLayers(pCluster1->GetOrderedCaloHitList().size() + pCluster2->GetOrderedCaloHitList().size());
135  const unsigned int nLayers(1 + std::max(pCluster1->GetOuterPseudoLayer(), pCluster2->GetOuterPseudoLayer()) -
136  std::min(pCluster1->GetInnerPseudoLayer(), pCluster2->GetInnerPseudoLayer()));
137 
138  if (nLayers > 0)
139  return (static_cast<float>(nOccupiedLayers) / static_cast<float>(nLayers));
140 
141  return 0.f;
142 }
143 
144 //------------------------------------------------------------------------------------------------------------------------------------------
145 
146 float LArClusterHelper::GetClosestDistance(const ClusterList &clusterList1, const ClusterList &clusterList2)
147 {
148  if (clusterList1.empty() || clusterList2.empty())
149  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
150 
151  float closestDistance(std::numeric_limits<float>::max());
152 
153  for (ClusterList::const_iterator iter1 = clusterList1.begin(), iterEnd1 = clusterList1.end(); iter1 != iterEnd1; ++iter1)
154  {
155  const Cluster *const pCluster1 = *iter1;
156  const float thisDistance(LArClusterHelper::GetClosestDistance(pCluster1, clusterList2));
157 
158  if (thisDistance < closestDistance)
159  closestDistance = thisDistance;
160  }
161 
162  return closestDistance;
163 }
164 
165 //------------------------------------------------------------------------------------------------------------------------------------------
166 
167 float LArClusterHelper::GetClosestDistance(const Cluster *const pCluster, const ClusterList &clusterList)
168 {
169  if (clusterList.empty())
170  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
171 
172  float closestDistance(std::numeric_limits<float>::max());
173 
174  for (ClusterList::const_iterator iter = clusterList.begin(), iterEnd = clusterList.end(); iter != iterEnd; ++iter)
175  {
176  const Cluster *const pTestCluster = *iter;
177  const float thisDistance(LArClusterHelper::GetClosestDistance(pCluster, pTestCluster));
178 
179  if (thisDistance < closestDistance)
180  closestDistance = thisDistance;
181  }
182 
183  return closestDistance;
184 }
185 
186 //------------------------------------------------------------------------------------------------------------------------------------------
187 
188 float LArClusterHelper::GetClosestDistance(const Cluster *const pCluster1, const Cluster *const pCluster2)
189 {
190  CartesianVector closestPosition1(0.f, 0.f, 0.f);
191  CartesianVector closestPosition2(0.f, 0.f, 0.f);
192 
193  LArClusterHelper::GetClosestPositions(pCluster1, pCluster2, closestPosition1, closestPosition2);
194 
195  return (closestPosition1 - closestPosition2).GetMagnitude();
196 }
197 
198 //------------------------------------------------------------------------------------------------------------------------------------------
199 
200 float LArClusterHelper::GetClosestDistance(const CartesianVector &position, const ClusterList &clusterList)
201 {
202  return (position - LArClusterHelper::GetClosestPosition(position, clusterList)).GetMagnitude();
203 }
204 
205 //------------------------------------------------------------------------------------------------------------------------------------------
206 
207 float LArClusterHelper::GetClosestDistance(const CartesianVector &position, const Cluster *const pCluster)
208 {
209  return (position - LArClusterHelper::GetClosestPosition(position, pCluster)).GetMagnitude();
210 }
211 
212 //------------------------------------------------------------------------------------------------------------------------------------------
213 
214 float LArClusterHelper::GetClosestDistance(const CartesianVector &position, const CaloHitList &caloHitList)
215 {
216  return (position - LArClusterHelper::GetClosestPosition(position, caloHitList)).GetMagnitude();
217 }
218 
219 //------------------------------------------------------------------------------------------------------------------------------------------
220 
221 CartesianVector LArClusterHelper::GetClosestPosition(const CartesianVector &position, const ClusterList &clusterList)
222 {
223  bool distanceFound(false);
224  float closestDistanceSquared(std::numeric_limits<float>::max());
225  CartesianVector closestPosition(0.f, 0.f, 0.f);
226 
227  for (ClusterList::const_iterator iter = clusterList.begin(), iterEnd = clusterList.end(); iter != iterEnd; ++iter)
228  {
229  const Cluster *const pTestCluster = *iter;
230  const CartesianVector thisPosition(LArClusterHelper::GetClosestPosition(position, pTestCluster));
231  const float thisDistanceSquared((position - thisPosition).GetMagnitudeSquared());
232 
233  if (thisDistanceSquared < closestDistanceSquared)
234  {
235  distanceFound = true;
236  closestDistanceSquared = thisDistanceSquared;
237  closestPosition = thisPosition;
238  }
239  }
240 
241  if (distanceFound)
242  return closestPosition;
243 
244  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
245 }
246 
247 //------------------------------------------------------------------------------------------------------------------------------------------
248 
249 CartesianVector LArClusterHelper::GetClosestPosition(const CartesianVector &position, const Cluster *const pCluster)
250 {
251  CaloHitList caloHitList;
252  pCluster->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
253 
254  return LArClusterHelper::GetClosestPosition(position, caloHitList);
255 }
256 
257 //------------------------------------------------------------------------------------------------------------------------------------------
258 
259 CartesianVector LArClusterHelper::GetClosestPosition(const CartesianVector &position, const CaloHitList &caloHitList)
260 {
261  const CaloHit *pClosestCaloHit(nullptr);
262  float closestDistanceSquared(std::numeric_limits<float>::max());
263 
264  for (const CaloHit *const pCaloHit : caloHitList)
265  {
266  const float distanceSquared((pCaloHit->GetPositionVector() - position).GetMagnitudeSquared());
267 
268  if (distanceSquared < closestDistanceSquared)
269  {
270  closestDistanceSquared = distanceSquared;
271  pClosestCaloHit = pCaloHit;
272  }
273  }
274 
275  if (pClosestCaloHit)
276  return pClosestCaloHit->GetPositionVector();
277 
278  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
279 }
280 
281 //------------------------------------------------------------------------------------------------------------------------------------------
282 
283 void LArClusterHelper::GetClosestPositions(
284  const Cluster *const pCluster1, const Cluster *const pCluster2, CartesianVector &outputPosition1, CartesianVector &outputPosition2)
285 {
286  bool distanceFound(false);
287  float minDistanceSquared(std::numeric_limits<float>::max());
288 
289  CartesianVector closestPosition1(0.f, 0.f, 0.f);
290  CartesianVector closestPosition2(0.f, 0.f, 0.f);
291 
292  const OrderedCaloHitList &orderedCaloHitList1(pCluster1->GetOrderedCaloHitList());
293  const OrderedCaloHitList &orderedCaloHitList2(pCluster2->GetOrderedCaloHitList());
294 
295  // Loop over hits in cluster 1
296  for (OrderedCaloHitList::const_iterator iter1 = orderedCaloHitList1.begin(), iter1End = orderedCaloHitList1.end(); iter1 != iter1End; ++iter1)
297  {
298  for (CaloHitList::const_iterator hitIter1 = iter1->second->begin(), hitIter1End = iter1->second->end(); hitIter1 != hitIter1End; ++hitIter1)
299  {
300  const CartesianVector &positionVector1((*hitIter1)->GetPositionVector());
301 
302  // Loop over hits in cluster 2
303  for (OrderedCaloHitList::const_iterator iter2 = orderedCaloHitList2.begin(), iter2End = orderedCaloHitList2.end(); iter2 != iter2End; ++iter2)
304  {
305  for (CaloHitList::const_iterator hitIter2 = iter2->second->begin(), hitIter2End = iter2->second->end(); hitIter2 != hitIter2End; ++hitIter2)
306  {
307  const CartesianVector &positionVector2((*hitIter2)->GetPositionVector());
308 
309  const float distanceSquared((positionVector1 - positionVector2).GetMagnitudeSquared());
310 
311  if (distanceSquared < minDistanceSquared)
312  {
313  minDistanceSquared = distanceSquared;
314  closestPosition1 = positionVector1;
315  closestPosition2 = positionVector2;
316  distanceFound = true;
317  }
318  }
319  }
320  }
321  }
322 
323  if (!distanceFound)
324  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
325 
326  outputPosition1 = closestPosition1;
327  outputPosition2 = closestPosition2;
328 }
329 
330 //------------------------------------------------------------------------------------------------------------------------------------------
331 
332 void LArClusterHelper::GetClusterBoundingBox(const Cluster *const pCluster, CartesianVector &minimumCoordinate, CartesianVector &maximumCoordinate)
333 {
334  const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
335 
336  float xmin(std::numeric_limits<float>::max());
337  float ymin(std::numeric_limits<float>::max());
338  float zmin(std::numeric_limits<float>::max());
339  float xmax(-std::numeric_limits<float>::max());
340  float ymax(-std::numeric_limits<float>::max());
341  float zmax(-std::numeric_limits<float>::max());
342 
343  for (OrderedCaloHitList::const_iterator ochIter = orderedCaloHitList.begin(), ochIterEnd = orderedCaloHitList.end(); ochIter != ochIterEnd; ++ochIter)
344  {
345  for (CaloHitList::const_iterator hIter = ochIter->second->begin(), hIterEnd = ochIter->second->end(); hIter != hIterEnd; ++hIter)
346  {
347  const CaloHit *const pCaloHit = *hIter;
348  const CartesianVector &hit(pCaloHit->GetPositionVector());
349  xmin = std::min(hit.GetX(), xmin);
350  xmax = std::max(hit.GetX(), xmax);
351  ymin = std::min(hit.GetY(), ymin);
352  ymax = std::max(hit.GetY(), ymax);
353  zmin = std::min(hit.GetZ(), zmin);
354  zmax = std::max(hit.GetZ(), zmax);
355  }
356  }
357 
358  minimumCoordinate.SetValues(xmin, ymin, zmin);
359  maximumCoordinate.SetValues(xmax, ymax, zmax);
360 }
361 
362 //------------------------------------------------------------------------------------------------------------------------------------------
363 
364 StatusCode LArClusterHelper::GetAverageZ(const Cluster *const pCluster, const float xmin, const float xmax, float &averageZ)
365 {
366  averageZ = std::numeric_limits<float>::max();
367 
368  if (xmin > xmax)
369  return STATUS_CODE_INVALID_PARAMETER;
370 
371  const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
372 
373  float zsum(0.f);
374  int count(0);
375 
376  for (OrderedCaloHitList::const_iterator ochIter = orderedCaloHitList.begin(), ochIterEnd = orderedCaloHitList.end(); ochIter != ochIterEnd; ++ochIter)
377  {
378  for (CaloHitList::const_iterator hIter = ochIter->second->begin(), hIterEnd = ochIter->second->end(); hIter != hIterEnd; ++hIter)
379  {
380  const CaloHit *const pCaloHit = *hIter;
381  const CartesianVector &hit(pCaloHit->GetPositionVector());
382 
383  if (hit.GetX() < xmin || hit.GetX() > xmax)
384  continue;
385 
386  zsum += hit.GetZ();
387  ++count;
388  }
389  }
390 
391  if (count == 0)
392  return STATUS_CODE_NOT_FOUND;
393 
394  averageZ = zsum / static_cast<float>(count);
395  return STATUS_CODE_SUCCESS;
396 }
397 
398 //------------------------------------------------------------------------------------------------------------------------------------------
399 
400 void LArClusterHelper::GetExtremalCoordinates(const ClusterList &clusterList, CartesianVector &innerCoordinate, CartesianVector &outerCoordinate)
401 {
402  OrderedCaloHitList orderedCaloHitList;
403 
404  for (ClusterList::const_iterator cIter = clusterList.begin(), cIterEnd = clusterList.end(); cIter != cIterEnd; ++cIter)
405  {
406  const Cluster *const pCluster = *cIter;
407  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, orderedCaloHitList.Add(pCluster->GetOrderedCaloHitList()));
408  }
409 
410  return LArClusterHelper::GetExtremalCoordinates(orderedCaloHitList, innerCoordinate, outerCoordinate);
411 }
412 
413 //------------------------------------------------------------------------------------------------------------------------------------------
414 
415 void LArClusterHelper::GetExtremalCoordinates(const Cluster *const pCluster, CartesianVector &innerCoordinate, CartesianVector &outerCoordinate)
416 {
417  return LArClusterHelper::GetExtremalCoordinates(pCluster->GetOrderedCaloHitList(), innerCoordinate, outerCoordinate);
418 }
419 
420 //------------------------------------------------------------------------------------------------------------------------------------------
421 
422 void LArClusterHelper::GetExtremalCoordinates(const OrderedCaloHitList &orderedCaloHitList, CartesianVector &innerCoordinate, CartesianVector &outerCoordinate)
423 {
424  if (orderedCaloHitList.empty())
425  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
426 
427  CartesianPointVector coordinateVector;
428 
429  for (OrderedCaloHitList::const_iterator iter = orderedCaloHitList.begin(), iterEnd = orderedCaloHitList.end(); iter != iterEnd; ++iter)
430  {
431  for (CaloHitList::const_iterator hitIter = iter->second->begin(), hitIterEnd = iter->second->end(); hitIter != hitIterEnd; ++hitIter)
432  {
433  const CaloHit *const pCaloHit = *hitIter;
434  coordinateVector.push_back(pCaloHit->GetPositionVector());
435  }
436  }
437 
438  std::sort(coordinateVector.begin(), coordinateVector.end(), LArClusterHelper::SortCoordinatesByPosition);
439  return LArClusterHelper::GetExtremalCoordinates(coordinateVector, innerCoordinate, outerCoordinate);
440 }
441 
442 //------------------------------------------------------------------------------------------------------------------------------------------
443 
444 void LArClusterHelper::GetExtremalCoordinates(const CartesianPointVector &coordinateVector, CartesianVector &innerCoordinate, CartesianVector &outerCoordinate)
445 {
446  if (coordinateVector.empty())
447  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
448 
449  // Find the extremal values of the X, Y and Z coordinates
450  float xMin(+std::numeric_limits<float>::max());
451  float yMin(+std::numeric_limits<float>::max());
452  float zMin(+std::numeric_limits<float>::max());
453  float xMax(-std::numeric_limits<float>::max());
454  float yMax(-std::numeric_limits<float>::max());
455  float zMax(-std::numeric_limits<float>::max());
456 
457  for (CartesianPointVector::const_iterator pIter = coordinateVector.begin(), pIterEnd = coordinateVector.end(); pIter != pIterEnd; ++pIter)
458  {
459  const CartesianVector &pos = *pIter;
460  xMin = std::min(pos.GetX(), xMin);
461  xMax = std::max(pos.GetX(), xMax);
462  yMin = std::min(pos.GetY(), yMin);
463  yMax = std::max(pos.GetY(), yMax);
464  zMin = std::min(pos.GetZ(), zMin);
465  zMax = std::max(pos.GetZ(), zMax);
466  }
467 
468  // Choose the coordinate with the greatest span (keeping any ties)
469  const float xAve(0.5f * (xMin + xMax));
470  const float yAve(0.5f * (yMin + yMax));
471  const float zAve(0.5f * (zMin + zMax));
472 
473  const float xSpan(xMax - xMin);
474  const float ySpan(yMax - yMin);
475  const float zSpan(zMax - zMin);
476 
477  const bool useX((xSpan > std::numeric_limits<float>::epsilon()) && (xSpan + std::numeric_limits<float>::epsilon() > std::max(ySpan, zSpan)));
478  const bool useY((ySpan > std::numeric_limits<float>::epsilon()) && (ySpan + std::numeric_limits<float>::epsilon() > std::max(zSpan, xSpan)));
479  const bool useZ((zSpan > std::numeric_limits<float>::epsilon()) && (zSpan + std::numeric_limits<float>::epsilon() > std::max(xSpan, ySpan)));
480 
481  // Find the extremal hits separately for the chosen coordinates
482  CartesianPointVector candidateVector;
483 
484  for (CartesianPointVector::const_iterator pIter = coordinateVector.begin(), pIterEnd = coordinateVector.end(); pIter != pIterEnd; ++pIter)
485  {
486  const CartesianVector &pos = *pIter;
487 
488  if (useX)
489  {
490  if (((pos.GetX() - xMin) < std::numeric_limits<float>::epsilon()) || ((pos.GetX() - xMax) > -std::numeric_limits<float>::epsilon()))
491  candidateVector.push_back(pos);
492  }
493 
494  if (useY)
495  {
496  if (((pos.GetY() - yMin) < std::numeric_limits<float>::epsilon()) || ((pos.GetY() - yMax) > -std::numeric_limits<float>::epsilon()))
497  candidateVector.push_back(pos);
498  }
499 
500  if (useZ)
501  {
502  if (((pos.GetZ() - zMin) < std::numeric_limits<float>::epsilon()) || ((pos.GetZ() - zMax) > -std::numeric_limits<float>::epsilon()))
503  candidateVector.push_back(pos);
504  }
505  }
506 
507  // Finally, find the pair of hits that are separated by the greatest distance
508  CartesianVector firstCoordinate(xAve, yAve, zAve);
509  CartesianVector secondCoordinate(xAve, yAve, zAve);
510  float maxDistanceSquared(+std::numeric_limits<float>::epsilon());
511 
512  for (CartesianPointVector::const_iterator iterI = candidateVector.begin(), iterEndI = candidateVector.end(); iterI != iterEndI; ++iterI)
513  {
514  const CartesianVector &posI = *iterI;
515 
516  for (CartesianPointVector::const_iterator iterJ = iterI, iterEndJ = candidateVector.end(); iterJ != iterEndJ; ++iterJ)
517  {
518  const CartesianVector &posJ = *iterJ;
519 
520  const float distanceSquared((posI - posJ).GetMagnitudeSquared());
521 
522  if (distanceSquared > maxDistanceSquared)
523  {
524  maxDistanceSquared = distanceSquared;
525  firstCoordinate = posI;
526  secondCoordinate = posJ;
527  }
528  }
529  }
530 
531  // Set the inner and outer coordinates (Check Z first, then X in the event of a tie)
532  const float deltaZ(secondCoordinate.GetZ() - firstCoordinate.GetZ());
533  const float deltaX(secondCoordinate.GetX() - firstCoordinate.GetX());
534 
535  if ((deltaZ > 0.f) || ((std::fabs(deltaZ) < std::numeric_limits<float>::epsilon()) && (deltaX > 0.f)))
536  {
537  innerCoordinate = firstCoordinate;
538  outerCoordinate = secondCoordinate;
539  }
540  else
541  {
542  innerCoordinate = secondCoordinate;
543  outerCoordinate = firstCoordinate;
544  }
545 }
546 
547 //------------------------------------------------------------------------------------------------------------------------------------------
548 
549 void LArClusterHelper::GetCoordinateVector(const Cluster *const pCluster, CartesianPointVector &coordinateVector)
550 {
551  for (const OrderedCaloHitList::value_type &layerEntry : pCluster->GetOrderedCaloHitList())
552  {
553  for (const CaloHit *const pCaloHit : *layerEntry.second)
554  coordinateVector.push_back(pCaloHit->GetPositionVector());
555  }
556 
557  std::sort(coordinateVector.begin(), coordinateVector.end(), LArClusterHelper::SortCoordinatesByPosition);
558 }
559 
560 //------------------------------------------------------------------------------------------------------------------------------------------
561 
562 void LArClusterHelper::GetCaloHitListInBoundingBox(const pandora::Cluster *const pCluster, const pandora::CartesianVector &lowerBound,
563  const pandora::CartesianVector &upperBound, pandora::CaloHitList &caloHitList)
564 {
565  const bool useX(std::fabs(upperBound.GetX() - lowerBound.GetX()) > std::numeric_limits<float>::epsilon());
566  const bool useY(std::fabs(upperBound.GetY() - lowerBound.GetY()) > std::numeric_limits<float>::epsilon());
567  const bool useZ(std::fabs(upperBound.GetZ() - lowerBound.GetZ()) > std::numeric_limits<float>::epsilon());
568  if (!useX && !useY && !useZ)
569  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
570 
571  const float minX(std::min(lowerBound.GetX(), upperBound.GetX()));
572  const float maxX(std::max(lowerBound.GetX(), upperBound.GetX()));
573  const float minY(std::min(lowerBound.GetY(), upperBound.GetY()));
574  const float maxY(std::max(lowerBound.GetY(), upperBound.GetY()));
575  const float minZ(std::min(lowerBound.GetZ(), upperBound.GetZ()));
576  const float maxZ(std::max(lowerBound.GetZ(), upperBound.GetZ()));
577 
578  for (const OrderedCaloHitList::value_type &layerEntry : pCluster->GetOrderedCaloHitList())
579  {
580  for (const CaloHit *const pCaloHit : *layerEntry.second)
581  {
582  const CartesianVector &hitPosition = pCaloHit->GetPositionVector();
583  if (useX && (hitPosition.GetX() < minX - std::numeric_limits<float>::epsilon() ||
584  hitPosition.GetX() > maxX + std::numeric_limits<float>::epsilon()))
585  continue;
586  else if (useY && (hitPosition.GetY() < minY - std::numeric_limits<float>::epsilon() ||
587  hitPosition.GetY() > maxY + std::numeric_limits<float>::epsilon()))
588  continue;
589  else if (useZ && (hitPosition.GetZ() < minZ - std::numeric_limits<float>::epsilon() ||
590  hitPosition.GetZ() > maxZ + std::numeric_limits<float>::epsilon()))
591  continue;
592 
593  caloHitList.push_back(pCaloHit);
594  }
595  }
596  caloHitList.sort(LArClusterHelper::SortHitsByPosition);
597 }
598 
599 //------------------------------------------------------------------------------------------------------------------------------------------
600 
601 void LArClusterHelper::GetDaughterVolumeIDs(const Cluster *const pCluster, UIntSet &daughterVolumeIds)
602 {
603  const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
604 
605  for (OrderedCaloHitList::const_iterator ochIter = orderedCaloHitList.begin(), ochIterEnd = orderedCaloHitList.end(); ochIter != ochIterEnd; ++ochIter)
606  {
607  for (CaloHitList::const_iterator hIter = ochIter->second->begin(), hIterEnd = ochIter->second->end(); hIter != hIterEnd; ++hIter)
608  {
609  const CaloHit *const pCaloHit(*hIter);
610  const LArCaloHit *const pLArCaloHit(dynamic_cast<const LArCaloHit *>(pCaloHit));
611 
612  if (pLArCaloHit)
613  daughterVolumeIds.insert(pLArCaloHit->GetDaughterVolumeId());
614  }
615  }
616 }
617 //------------------------------------------------------------------------------------------------------------------------------------------
618 
619 bool LArClusterHelper::SortByNOccupiedLayers(const Cluster *const pLhs, const Cluster *const pRhs)
620 {
621  const unsigned int nOccupiedLayersLhs(pLhs->GetOrderedCaloHitList().size());
622  const unsigned int nOccupiedLayersRhs(pRhs->GetOrderedCaloHitList().size());
623 
624  if (nOccupiedLayersLhs != nOccupiedLayersRhs)
625  return (nOccupiedLayersLhs > nOccupiedLayersRhs);
626 
627  return SortByNHits(pLhs, pRhs);
628 }
629 
630 //------------------------------------------------------------------------------------------------------------------------------------------
631 
632 bool LArClusterHelper::SortByNHits(const Cluster *const pLhs, const Cluster *const pRhs)
633 {
634  const unsigned int nHitsLhs(pLhs->GetNCaloHits());
635  const unsigned int nHitsRhs(pRhs->GetNCaloHits());
636 
637  if (nHitsLhs != nHitsRhs)
638  return (nHitsLhs > nHitsRhs);
639 
640  return SortByLayerSpan(pLhs, pRhs);
641 }
642 
643 //------------------------------------------------------------------------------------------------------------------------------------------
644 
645 bool LArClusterHelper::SortByLayerSpan(const Cluster *const pLhs, const Cluster *const pRhs)
646 {
647  const unsigned int layerSpanLhs(pLhs->GetOuterPseudoLayer() - pLhs->GetInnerPseudoLayer());
648  const unsigned int layerSpanRhs(pRhs->GetOuterPseudoLayer() - pRhs->GetInnerPseudoLayer());
649 
650  if (layerSpanLhs != layerSpanRhs)
651  return (layerSpanLhs > layerSpanRhs);
652 
653  return SortByInnerLayer(pLhs, pRhs);
654 }
655 
656 //------------------------------------------------------------------------------------------------------------------------------------------
657 
658 bool LArClusterHelper::SortByInnerLayer(const Cluster *const pLhs, const Cluster *const pRhs)
659 {
660  const unsigned int innerLayerLhs(pLhs->GetInnerPseudoLayer());
661  const unsigned int innerLayerRhs(pRhs->GetInnerPseudoLayer());
662 
663  if (innerLayerLhs != innerLayerRhs)
664  return (innerLayerLhs < innerLayerRhs);
665 
666  return SortByPosition(pLhs, pRhs);
667 }
668 
669 //------------------------------------------------------------------------------------------------------------------------------------------
670 
671 bool LArClusterHelper::SortByPosition(const Cluster *const pLhs, const Cluster *const pRhs)
672 {
673  const CartesianVector deltaPositionIL(pRhs->GetCentroid(pRhs->GetInnerPseudoLayer()) - pLhs->GetCentroid(pLhs->GetInnerPseudoLayer()));
674 
675  if (std::fabs(deltaPositionIL.GetZ()) > std::numeric_limits<float>::epsilon())
676  return (deltaPositionIL.GetZ() > std::numeric_limits<float>::epsilon());
677 
678  if (std::fabs(deltaPositionIL.GetX()) > std::numeric_limits<float>::epsilon())
679  return (deltaPositionIL.GetX() > std::numeric_limits<float>::epsilon());
680 
681  if (std::fabs(deltaPositionIL.GetY()) > std::numeric_limits<float>::epsilon())
682  return (deltaPositionIL.GetY() > std::numeric_limits<float>::epsilon());
683 
684  const CartesianVector deltaPositionOL(pRhs->GetCentroid(pRhs->GetOuterPseudoLayer()) - pLhs->GetCentroid(pLhs->GetOuterPseudoLayer()));
685 
686  if (std::fabs(deltaPositionOL.GetZ()) > std::numeric_limits<float>::epsilon())
687  return (deltaPositionOL.GetZ() > std::numeric_limits<float>::epsilon());
688 
689  if (std::fabs(deltaPositionOL.GetX()) > std::numeric_limits<float>::epsilon())
690  return (deltaPositionOL.GetX() > std::numeric_limits<float>::epsilon());
691 
692  if (std::fabs(deltaPositionOL.GetY()) > std::numeric_limits<float>::epsilon())
693  return (deltaPositionOL.GetY() > std::numeric_limits<float>::epsilon());
694 
695  // Use pulse height to resolve ties
696  return SortByPulseHeight(pLhs, pRhs);
697 }
698 
699 //------------------------------------------------------------------------------------------------------------------------------------------
700 
701 bool LArClusterHelper::SortByPulseHeight(const Cluster *const pLhs, const Cluster *const pRhs)
702 {
703  return (pLhs->GetHadronicEnergy() > pRhs->GetHadronicEnergy());
704 }
705 
706 //------------------------------------------------------------------------------------------------------------------------------------------
707 
708 bool LArClusterHelper::SortHitsByPosition(const CaloHit *const pLhs, const CaloHit *const pRhs)
709 {
710  const CartesianVector deltaPosition(pRhs->GetPositionVector() - pLhs->GetPositionVector());
711 
712  if (std::fabs(deltaPosition.GetZ()) > std::numeric_limits<float>::epsilon())
713  return (deltaPosition.GetZ() > std::numeric_limits<float>::epsilon());
714 
715  if (std::fabs(deltaPosition.GetX()) > std::numeric_limits<float>::epsilon())
716  return (deltaPosition.GetX() > std::numeric_limits<float>::epsilon());
717 
718  if (std::fabs(deltaPosition.GetY()) > std::numeric_limits<float>::epsilon())
719  return (deltaPosition.GetY() > std::numeric_limits<float>::epsilon());
720 
721  // Use pulse height to resolve ties
722  return SortHitsByPulseHeight(pLhs, pRhs);
723 }
724 
725 //------------------------------------------------------------------------------------------------------------------------------------------
726 
727 bool LArClusterHelper::SortHitsByPositionInX(const pandora::CaloHit *const pLhs, const pandora::CaloHit *const pRhs)
728 {
729  const CartesianVector deltaPosition(pRhs->GetPositionVector() - pLhs->GetPositionVector());
730 
731  if (std::fabs(deltaPosition.GetX()) > std::numeric_limits<float>::epsilon())
732  return (deltaPosition.GetX() > std::numeric_limits<float>::epsilon());
733 
734  return SortHitsByPosition(pLhs, pRhs);
735 }
736 
737 //------------------------------------------------------------------------------------------------------------------------------------------
738 
739 bool LArClusterHelper::SortHitsByPulseHeight(const CaloHit *const pLhs, const CaloHit *const pRhs)
740 {
741  // TODO: Think about the correct energy to use here (should they ever be different)
742  return (pLhs->GetHadronicEnergy() > pRhs->GetHadronicEnergy());
743 }
744 
745 //------------------------------------------------------------------------------------------------------------------------------------------
746 
747 bool LArClusterHelper::SortCoordinatesByPosition(const CartesianVector &lhs, const CartesianVector &rhs)
748 {
749  const CartesianVector deltaPosition(rhs - lhs);
750 
751  if (std::fabs(deltaPosition.GetZ()) > std::numeric_limits<float>::epsilon())
752  return (deltaPosition.GetZ() > std::numeric_limits<float>::epsilon());
753 
754  if (std::fabs(deltaPosition.GetX()) > std::numeric_limits<float>::epsilon())
755  return (deltaPosition.GetX() > std::numeric_limits<float>::epsilon());
756 
757  return (deltaPosition.GetY() > std::numeric_limits<float>::epsilon());
758 }
759 
760 } // namespace lar_content
enum cvn::HType HitType
Header file for the lar calo hit class.
intermediate_table::const_iterator const_iterator
LAr calo hit class.
Definition: LArCaloHit.h:39
double dEdX(double KE, const simb::MCParticle *part)
Header file for the cluster helper class.
static int max(int a, int b)
std::set< unsigned int > UIntSet
Detector simulation of raw signals on wires.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
unsigned int GetDaughterVolumeId() const
Get the daughter volume id.
Definition: LArCaloHit.h:174