LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
LArClusterHelper.cc
Go to the documentation of this file.
1 
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
73  float minX(std::numeric_limits<float>::max()), maxX(-std::numeric_limits<float>::max());
74  float minY(std::numeric_limits<float>::max()), maxY(-std::numeric_limits<float>::max());
75  float minZ(std::numeric_limits<float>::max()), maxZ(-std::numeric_limits<float>::max());
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  return LArClusterHelper::GetClosestPosition(position, pCluster->GetOrderedCaloHitList());
252 }
253 
254 //------------------------------------------------------------------------------------------------------------------------------------------
255 
256 CartesianVector LArClusterHelper::GetClosestPosition(const CartesianVector &position, const OrderedCaloHitList &caloHitList)
257 {
258  const CaloHit *pClosestCaloHit(nullptr);
259  float closestDistanceSquared(std::numeric_limits<float>::max());
260 
261  for (const auto &entry : caloHitList)
262  {
263  for (const CaloHit *const pCaloHit : *entry.second)
264  {
265  const float distanceSquared((pCaloHit->GetPositionVector() - position).GetMagnitudeSquared());
266 
267  if (distanceSquared < closestDistanceSquared)
268  {
269  closestDistanceSquared = distanceSquared;
270  pClosestCaloHit = pCaloHit;
271  }
272  }
273  }
274 
275  if (pClosestCaloHit)
276  return pClosestCaloHit->GetPositionVector();
277 
278  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
279 }
280 
281 //------------------------------------------------------------------------------------------------------------------------------------------
282 
283 CartesianVector LArClusterHelper::GetClosestPosition(const CartesianVector &position, const CaloHitList &caloHitList)
284 {
285  const CaloHit *pClosestCaloHit(nullptr);
286  float closestDistanceSquared(std::numeric_limits<float>::max());
287 
288  for (const CaloHit *const pCaloHit : caloHitList)
289  {
290  const float distanceSquared((pCaloHit->GetPositionVector() - position).GetMagnitudeSquared());
291 
292  if (distanceSquared < closestDistanceSquared)
293  {
294  closestDistanceSquared = distanceSquared;
295  pClosestCaloHit = pCaloHit;
296  }
297  }
298 
299  if (pClosestCaloHit)
300  return pClosestCaloHit->GetPositionVector();
301 
302  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
303 }
304 
305 //------------------------------------------------------------------------------------------------------------------------------------------
306 
307 void LArClusterHelper::GetClosestPositions(
308  const Cluster *const pCluster1, const Cluster *const pCluster2, CartesianVector &outputPosition1, CartesianVector &outputPosition2)
309 {
310  bool distanceFound(false);
311  float minDistanceSquared(std::numeric_limits<float>::max());
312 
313  CartesianVector closestPosition1(0.f, 0.f, 0.f);
314  CartesianVector closestPosition2(0.f, 0.f, 0.f);
315 
316  const OrderedCaloHitList &orderedCaloHitList1(pCluster1->GetOrderedCaloHitList());
317  const OrderedCaloHitList &orderedCaloHitList2(pCluster2->GetOrderedCaloHitList());
318 
319  // Loop over hits in cluster 1
320  for (OrderedCaloHitList::const_iterator iter1 = orderedCaloHitList1.begin(), iter1End = orderedCaloHitList1.end(); iter1 != iter1End; ++iter1)
321  {
322  for (CaloHitList::const_iterator hitIter1 = iter1->second->begin(), hitIter1End = iter1->second->end(); hitIter1 != hitIter1End; ++hitIter1)
323  {
324  const CartesianVector &positionVector1((*hitIter1)->GetPositionVector());
325 
326  // Loop over hits in cluster 2
327  for (OrderedCaloHitList::const_iterator iter2 = orderedCaloHitList2.begin(), iter2End = orderedCaloHitList2.end(); iter2 != iter2End; ++iter2)
328  {
329  for (CaloHitList::const_iterator hitIter2 = iter2->second->begin(), hitIter2End = iter2->second->end(); hitIter2 != hitIter2End; ++hitIter2)
330  {
331  const CartesianVector &positionVector2((*hitIter2)->GetPositionVector());
332 
333  const float distanceSquared((positionVector1 - positionVector2).GetMagnitudeSquared());
334 
335  if (distanceSquared < minDistanceSquared)
336  {
337  minDistanceSquared = distanceSquared;
338  closestPosition1 = positionVector1;
339  closestPosition2 = positionVector2;
340  distanceFound = true;
341  }
342  }
343  }
344  }
345  }
346 
347  if (!distanceFound)
348  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
349 
350  outputPosition1 = closestPosition1;
351  outputPosition2 = closestPosition2;
352 }
353 
354 //------------------------------------------------------------------------------------------------------------------------------------------
355 
356 void LArClusterHelper::GetClusterBoundingBox(const Cluster *const pCluster, CartesianVector &minimumCoordinate, CartesianVector &maximumCoordinate)
357 {
358  const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
359 
360  float xmin(std::numeric_limits<float>::max());
361  float ymin(std::numeric_limits<float>::max());
362  float zmin(std::numeric_limits<float>::max());
363  float xmax(-std::numeric_limits<float>::max());
364  float ymax(-std::numeric_limits<float>::max());
365  float zmax(-std::numeric_limits<float>::max());
366 
367  for (OrderedCaloHitList::const_iterator ochIter = orderedCaloHitList.begin(), ochIterEnd = orderedCaloHitList.end(); ochIter != ochIterEnd; ++ochIter)
368  {
369  for (CaloHitList::const_iterator hIter = ochIter->second->begin(), hIterEnd = ochIter->second->end(); hIter != hIterEnd; ++hIter)
370  {
371  const CaloHit *const pCaloHit = *hIter;
372  const CartesianVector &hit(pCaloHit->GetPositionVector());
373  xmin = std::min(hit.GetX(), xmin);
374  xmax = std::max(hit.GetX(), xmax);
375  ymin = std::min(hit.GetY(), ymin);
376  ymax = std::max(hit.GetY(), ymax);
377  zmin = std::min(hit.GetZ(), zmin);
378  zmax = std::max(hit.GetZ(), zmax);
379  }
380  }
381 
382  minimumCoordinate.SetValues(xmin, ymin, zmin);
383  maximumCoordinate.SetValues(xmax, ymax, zmax);
384 }
385 
386 //------------------------------------------------------------------------------------------------------------------------------------------
387 
388 StatusCode LArClusterHelper::GetAverageZ(const Cluster *const pCluster, const float xmin, const float xmax, float &averageZ)
389 {
390  averageZ = std::numeric_limits<float>::max();
391 
392  if (xmin > xmax)
393  return STATUS_CODE_INVALID_PARAMETER;
394 
395  const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
396 
397  float zsum(0.f);
398  int count(0);
399 
400  for (OrderedCaloHitList::const_iterator ochIter = orderedCaloHitList.begin(), ochIterEnd = orderedCaloHitList.end(); ochIter != ochIterEnd; ++ochIter)
401  {
402  for (CaloHitList::const_iterator hIter = ochIter->second->begin(), hIterEnd = ochIter->second->end(); hIter != hIterEnd; ++hIter)
403  {
404  const CaloHit *const pCaloHit = *hIter;
405  const CartesianVector &hit(pCaloHit->GetPositionVector());
406 
407  if (hit.GetX() < xmin || hit.GetX() > xmax)
408  continue;
409 
410  zsum += hit.GetZ();
411  ++count;
412  }
413  }
414 
415  if (count == 0)
416  return STATUS_CODE_NOT_FOUND;
417 
418  averageZ = zsum / static_cast<float>(count);
419  return STATUS_CODE_SUCCESS;
420 }
421 
422 //------------------------------------------------------------------------------------------------------------------------------------------
423 
424 void LArClusterHelper::GetExtremalCoordinates(const ClusterList &clusterList, CartesianVector &innerCoordinate, CartesianVector &outerCoordinate)
425 {
426  OrderedCaloHitList orderedCaloHitList;
427 
428  for (ClusterList::const_iterator cIter = clusterList.begin(), cIterEnd = clusterList.end(); cIter != cIterEnd; ++cIter)
429  {
430  const Cluster *const pCluster = *cIter;
431  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, orderedCaloHitList.Add(pCluster->GetOrderedCaloHitList()));
432  }
433 
434  return LArClusterHelper::GetExtremalCoordinates(orderedCaloHitList, innerCoordinate, outerCoordinate);
435 }
436 
437 //------------------------------------------------------------------------------------------------------------------------------------------
438 
439 void LArClusterHelper::GetExtremalCoordinates(const Cluster *const pCluster, CartesianVector &innerCoordinate, CartesianVector &outerCoordinate)
440 {
441  return LArClusterHelper::GetExtremalCoordinates(pCluster->GetOrderedCaloHitList(), innerCoordinate, outerCoordinate);
442 }
443 
444 //------------------------------------------------------------------------------------------------------------------------------------------
445 
446 void LArClusterHelper::GetExtremalCoordinates(const OrderedCaloHitList &orderedCaloHitList, CartesianVector &innerCoordinate, CartesianVector &outerCoordinate)
447 {
448  if (orderedCaloHitList.empty())
449  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
450 
451  CartesianPointVector coordinateVector;
452 
453  for (OrderedCaloHitList::const_iterator iter = orderedCaloHitList.begin(), iterEnd = orderedCaloHitList.end(); iter != iterEnd; ++iter)
454  {
455  for (CaloHitList::const_iterator hitIter = iter->second->begin(), hitIterEnd = iter->second->end(); hitIter != hitIterEnd; ++hitIter)
456  {
457  const CaloHit *const pCaloHit = *hitIter;
458  coordinateVector.push_back(pCaloHit->GetPositionVector());
459  }
460  }
461 
462  std::sort(coordinateVector.begin(), coordinateVector.end(), LArClusterHelper::SortCoordinatesByPosition);
463  return LArClusterHelper::GetExtremalCoordinates(coordinateVector, innerCoordinate, outerCoordinate);
464 }
465 
466 //------------------------------------------------------------------------------------------------------------------------------------------
467 
468 void LArClusterHelper::GetExtremalCoordinates(const CartesianPointVector &coordinateVector, CartesianVector &innerCoordinate, CartesianVector &outerCoordinate)
469 {
470  if (coordinateVector.empty())
471  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
472 
473  // Find the extremal values of the X, Y and Z coordinates
474  float xMin(+std::numeric_limits<float>::max());
475  float yMin(+std::numeric_limits<float>::max());
476  float zMin(+std::numeric_limits<float>::max());
477  float xMax(-std::numeric_limits<float>::max());
478  float yMax(-std::numeric_limits<float>::max());
479  float zMax(-std::numeric_limits<float>::max());
480 
481  for (CartesianPointVector::const_iterator pIter = coordinateVector.begin(), pIterEnd = coordinateVector.end(); pIter != pIterEnd; ++pIter)
482  {
483  const CartesianVector &pos = *pIter;
484  xMin = std::min(pos.GetX(), xMin);
485  xMax = std::max(pos.GetX(), xMax);
486  yMin = std::min(pos.GetY(), yMin);
487  yMax = std::max(pos.GetY(), yMax);
488  zMin = std::min(pos.GetZ(), zMin);
489  zMax = std::max(pos.GetZ(), zMax);
490  }
491 
492  // Choose the coordinate with the greatest span (keeping any ties)
493  const float xAve(0.5f * (xMin + xMax));
494  const float yAve(0.5f * (yMin + yMax));
495  const float zAve(0.5f * (zMin + zMax));
496 
497  const float xSpan(xMax - xMin);
498  const float ySpan(yMax - yMin);
499  const float zSpan(zMax - zMin);
500 
501  const bool useX((xSpan > std::numeric_limits<float>::epsilon()) && (xSpan + std::numeric_limits<float>::epsilon() > std::max(ySpan, zSpan)));
502  const bool useY((ySpan > std::numeric_limits<float>::epsilon()) && (ySpan + std::numeric_limits<float>::epsilon() > std::max(zSpan, xSpan)));
503  const bool useZ((zSpan > std::numeric_limits<float>::epsilon()) && (zSpan + std::numeric_limits<float>::epsilon() > std::max(xSpan, ySpan)));
504 
505  // Find the extremal hits separately for the chosen coordinates
506  CartesianPointVector candidateVector;
507 
508  for (CartesianPointVector::const_iterator pIter = coordinateVector.begin(), pIterEnd = coordinateVector.end(); pIter != pIterEnd; ++pIter)
509  {
510  const CartesianVector &pos = *pIter;
511 
512  if (useX)
513  {
514  if (((pos.GetX() - xMin) < std::numeric_limits<float>::epsilon()) || ((pos.GetX() - xMax) > -std::numeric_limits<float>::epsilon()))
515  candidateVector.push_back(pos);
516  }
517 
518  if (useY)
519  {
520  if (((pos.GetY() - yMin) < std::numeric_limits<float>::epsilon()) || ((pos.GetY() - yMax) > -std::numeric_limits<float>::epsilon()))
521  candidateVector.push_back(pos);
522  }
523 
524  if (useZ)
525  {
526  if (((pos.GetZ() - zMin) < std::numeric_limits<float>::epsilon()) || ((pos.GetZ() - zMax) > -std::numeric_limits<float>::epsilon()))
527  candidateVector.push_back(pos);
528  }
529  }
530 
531  // Finally, find the pair of hits that are separated by the greatest distance
532  CartesianVector firstCoordinate(xAve, yAve, zAve);
533  CartesianVector secondCoordinate(xAve, yAve, zAve);
534  float maxDistanceSquared(+std::numeric_limits<float>::epsilon());
535 
536  for (CartesianPointVector::const_iterator iterI = candidateVector.begin(), iterEndI = candidateVector.end(); iterI != iterEndI; ++iterI)
537  {
538  const CartesianVector &posI = *iterI;
539 
540  for (CartesianPointVector::const_iterator iterJ = iterI, iterEndJ = candidateVector.end(); iterJ != iterEndJ; ++iterJ)
541  {
542  const CartesianVector &posJ = *iterJ;
543 
544  const float distanceSquared((posI - posJ).GetMagnitudeSquared());
545 
546  if (distanceSquared > maxDistanceSquared)
547  {
548  maxDistanceSquared = distanceSquared;
549  firstCoordinate = posI;
550  secondCoordinate = posJ;
551  }
552  }
553  }
554 
555  // Set the inner and outer coordinates (Check Z first, then X in the event of a tie)
556  const float deltaZ(secondCoordinate.GetZ() - firstCoordinate.GetZ());
557  const float deltaX(secondCoordinate.GetX() - firstCoordinate.GetX());
558 
559  if ((deltaZ > 0.f) || ((std::fabs(deltaZ) < std::numeric_limits<float>::epsilon()) && (deltaX > 0.f)))
560  {
561  innerCoordinate = firstCoordinate;
562  outerCoordinate = secondCoordinate;
563  }
564  else
565  {
566  innerCoordinate = secondCoordinate;
567  outerCoordinate = firstCoordinate;
568  }
569 }
570 
571 //------------------------------------------------------------------------------------------------------------------------------------------
572 
573 void LArClusterHelper::GetCoordinateVector(const Cluster *const pCluster, CartesianPointVector &coordinateVector)
574 {
575  for (const OrderedCaloHitList::value_type &layerEntry : pCluster->GetOrderedCaloHitList())
576  {
577  for (const CaloHit *const pCaloHit : *layerEntry.second)
578  coordinateVector.push_back(pCaloHit->GetPositionVector());
579  }
580 
581  std::sort(coordinateVector.begin(), coordinateVector.end(), LArClusterHelper::SortCoordinatesByPosition);
582 }
583 
584 //------------------------------------------------------------------------------------------------------------------------------------------
585 
586 void LArClusterHelper::GetCaloHitListInBoundingBox(const pandora::Cluster *const pCluster, const pandora::CartesianVector &lowerBound,
587  const pandora::CartesianVector &upperBound, pandora::CaloHitList &caloHitList)
588 {
589  const bool useX(std::fabs(upperBound.GetX() - lowerBound.GetX()) > std::numeric_limits<float>::epsilon());
590  const bool useY(std::fabs(upperBound.GetY() - lowerBound.GetY()) > std::numeric_limits<float>::epsilon());
591  const bool useZ(std::fabs(upperBound.GetZ() - lowerBound.GetZ()) > std::numeric_limits<float>::epsilon());
592  if (!useX && !useY && !useZ)
593  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
594 
595  const float minX(std::min(lowerBound.GetX(), upperBound.GetX()));
596  const float maxX(std::max(lowerBound.GetX(), upperBound.GetX()));
597  const float minY(std::min(lowerBound.GetY(), upperBound.GetY()));
598  const float maxY(std::max(lowerBound.GetY(), upperBound.GetY()));
599  const float minZ(std::min(lowerBound.GetZ(), upperBound.GetZ()));
600  const float maxZ(std::max(lowerBound.GetZ(), upperBound.GetZ()));
601 
602  for (const OrderedCaloHitList::value_type &layerEntry : pCluster->GetOrderedCaloHitList())
603  {
604  for (const CaloHit *const pCaloHit : *layerEntry.second)
605  {
606  const CartesianVector &hitPosition = pCaloHit->GetPositionVector();
607  if (useX &&
608  (hitPosition.GetX() < minX - std::numeric_limits<float>::epsilon() || hitPosition.GetX() > maxX + std::numeric_limits<float>::epsilon()))
609  continue;
610  else if (useY &&
611  (hitPosition.GetY() < minY - std::numeric_limits<float>::epsilon() || hitPosition.GetY() > maxY + std::numeric_limits<float>::epsilon()))
612  continue;
613  else if (useZ &&
614  (hitPosition.GetZ() < minZ - std::numeric_limits<float>::epsilon() || hitPosition.GetZ() > maxZ + std::numeric_limits<float>::epsilon()))
615  continue;
616 
617  caloHitList.push_back(pCaloHit);
618  }
619  }
620  caloHitList.sort(LArClusterHelper::SortHitsByPosition);
621 }
622 
623 //------------------------------------------------------------------------------------------------------------------------------------------
624 
625 void LArClusterHelper::GetDaughterVolumeIDs(const Cluster *const pCluster, UIntSet &daughterVolumeIds)
626 {
627  const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
628 
629  for (OrderedCaloHitList::const_iterator ochIter = orderedCaloHitList.begin(), ochIterEnd = orderedCaloHitList.end(); ochIter != ochIterEnd; ++ochIter)
630  {
631  for (CaloHitList::const_iterator hIter = ochIter->second->begin(), hIterEnd = ochIter->second->end(); hIter != hIterEnd; ++hIter)
632  {
633  const CaloHit *const pCaloHit(*hIter);
634  const LArCaloHit *const pLArCaloHit(dynamic_cast<const LArCaloHit *>(pCaloHit));
635 
636  if (pLArCaloHit)
637  daughterVolumeIds.insert(pLArCaloHit->GetDaughterVolumeId());
638  }
639  }
640 }
641 //------------------------------------------------------------------------------------------------------------------------------------------
642 
643 bool LArClusterHelper::SortByNOccupiedLayers(const Cluster *const pLhs, const Cluster *const pRhs)
644 {
645  const unsigned int nOccupiedLayersLhs(pLhs->GetOrderedCaloHitList().size());
646  const unsigned int nOccupiedLayersRhs(pRhs->GetOrderedCaloHitList().size());
647 
648  if (nOccupiedLayersLhs != nOccupiedLayersRhs)
649  return (nOccupiedLayersLhs > nOccupiedLayersRhs);
650 
651  return SortByNHits(pLhs, pRhs);
652 }
653 
654 //------------------------------------------------------------------------------------------------------------------------------------------
655 
656 bool LArClusterHelper::SortByNHits(const Cluster *const pLhs, const Cluster *const pRhs)
657 {
658  const unsigned int nHitsLhs(pLhs->GetNCaloHits());
659  const unsigned int nHitsRhs(pRhs->GetNCaloHits());
660 
661  if (nHitsLhs != nHitsRhs)
662  return (nHitsLhs > nHitsRhs);
663 
664  return SortByLayerSpan(pLhs, pRhs);
665 }
666 
667 //------------------------------------------------------------------------------------------------------------------------------------------
668 
669 bool LArClusterHelper::SortByLayerSpan(const Cluster *const pLhs, const Cluster *const pRhs)
670 {
671  const unsigned int layerSpanLhs(pLhs->GetOuterPseudoLayer() - pLhs->GetInnerPseudoLayer());
672  const unsigned int layerSpanRhs(pRhs->GetOuterPseudoLayer() - pRhs->GetInnerPseudoLayer());
673 
674  if (layerSpanLhs != layerSpanRhs)
675  return (layerSpanLhs > layerSpanRhs);
676 
677  return SortByInnerLayer(pLhs, pRhs);
678 }
679 
680 //------------------------------------------------------------------------------------------------------------------------------------------
681 
682 bool LArClusterHelper::SortByInnerLayer(const Cluster *const pLhs, const Cluster *const pRhs)
683 {
684  const unsigned int innerLayerLhs(pLhs->GetInnerPseudoLayer());
685  const unsigned int innerLayerRhs(pRhs->GetInnerPseudoLayer());
686 
687  if (innerLayerLhs != innerLayerRhs)
688  return (innerLayerLhs < innerLayerRhs);
689 
690  return SortByPosition(pLhs, pRhs);
691 }
692 
693 //------------------------------------------------------------------------------------------------------------------------------------------
694 
695 bool LArClusterHelper::SortByPosition(const Cluster *const pLhs, const Cluster *const pRhs)
696 {
697  const CartesianVector deltaPositionIL(pRhs->GetCentroid(pRhs->GetInnerPseudoLayer()) - pLhs->GetCentroid(pLhs->GetInnerPseudoLayer()));
698 
699  if (std::fabs(deltaPositionIL.GetZ()) > std::numeric_limits<float>::epsilon())
700  return (deltaPositionIL.GetZ() > std::numeric_limits<float>::epsilon());
701 
702  if (std::fabs(deltaPositionIL.GetX()) > std::numeric_limits<float>::epsilon())
703  return (deltaPositionIL.GetX() > std::numeric_limits<float>::epsilon());
704 
705  if (std::fabs(deltaPositionIL.GetY()) > std::numeric_limits<float>::epsilon())
706  return (deltaPositionIL.GetY() > std::numeric_limits<float>::epsilon());
707 
708  const CartesianVector deltaPositionOL(pRhs->GetCentroid(pRhs->GetOuterPseudoLayer()) - pLhs->GetCentroid(pLhs->GetOuterPseudoLayer()));
709 
710  if (std::fabs(deltaPositionOL.GetZ()) > std::numeric_limits<float>::epsilon())
711  return (deltaPositionOL.GetZ() > std::numeric_limits<float>::epsilon());
712 
713  if (std::fabs(deltaPositionOL.GetX()) > std::numeric_limits<float>::epsilon())
714  return (deltaPositionOL.GetX() > std::numeric_limits<float>::epsilon());
715 
716  if (std::fabs(deltaPositionOL.GetY()) > std::numeric_limits<float>::epsilon())
717  return (deltaPositionOL.GetY() > std::numeric_limits<float>::epsilon());
718 
719  // Use pulse height to resolve ties
720  return SortByPulseHeight(pLhs, pRhs);
721 }
722 
723 //------------------------------------------------------------------------------------------------------------------------------------------
724 
725 bool LArClusterHelper::SortByPulseHeight(const Cluster *const pLhs, const Cluster *const pRhs)
726 {
727  return (pLhs->GetHadronicEnergy() > pRhs->GetHadronicEnergy());
728 }
729 
730 //------------------------------------------------------------------------------------------------------------------------------------------
731 
732 bool LArClusterHelper::SortHitsByPosition(const CaloHit *const pLhs, const CaloHit *const pRhs)
733 {
734  const CartesianVector deltaPosition(pRhs->GetPositionVector() - pLhs->GetPositionVector());
735 
736  if (std::fabs(deltaPosition.GetZ()) > std::numeric_limits<float>::epsilon())
737  return (deltaPosition.GetZ() > std::numeric_limits<float>::epsilon());
738 
739  if (std::fabs(deltaPosition.GetX()) > std::numeric_limits<float>::epsilon())
740  return (deltaPosition.GetX() > std::numeric_limits<float>::epsilon());
741 
742  if (std::fabs(deltaPosition.GetY()) > std::numeric_limits<float>::epsilon())
743  return (deltaPosition.GetY() > std::numeric_limits<float>::epsilon());
744 
745  // Use pulse height to resolve ties
746  return SortHitsByPulseHeight(pLhs, pRhs);
747 }
748 
749 //------------------------------------------------------------------------------------------------------------------------------------------
750 
751 bool LArClusterHelper::SortHitsByPositionInX(const pandora::CaloHit *const pLhs, const pandora::CaloHit *const pRhs)
752 {
753  const CartesianVector deltaPosition(pRhs->GetPositionVector() - pLhs->GetPositionVector());
754 
755  if (std::fabs(deltaPosition.GetX()) > std::numeric_limits<float>::epsilon())
756  return (deltaPosition.GetX() > std::numeric_limits<float>::epsilon());
757 
758  return SortHitsByPosition(pLhs, pRhs);
759 }
760 
761 //------------------------------------------------------------------------------------------------------------------------------------------
762 
763 bool LArClusterHelper::SortHitsByPulseHeight(const CaloHit *const pLhs, const CaloHit *const pRhs)
764 {
765  // TODO: Think about the correct energy to use here (should they ever be different)
766  return (pLhs->GetHadronicEnergy() > pRhs->GetHadronicEnergy());
767 }
768 
769 //------------------------------------------------------------------------------------------------------------------------------------------
770 
771 bool LArClusterHelper::SortCoordinatesByPosition(const CartesianVector &lhs, const CartesianVector &rhs)
772 {
773  const CartesianVector deltaPosition(rhs - lhs);
774 
775  if (std::fabs(deltaPosition.GetZ()) > std::numeric_limits<float>::epsilon())
776  return (deltaPosition.GetZ() > std::numeric_limits<float>::epsilon());
777 
778  if (std::fabs(deltaPosition.GetX()) > std::numeric_limits<float>::epsilon())
779  return (deltaPosition.GetX() > std::numeric_limits<float>::epsilon());
780 
781  return (deltaPosition.GetY() > std::numeric_limits<float>::epsilon());
782 }
783 
784 } // namespace lar_content
double minY
Definition: plot_hist.C:9
Header file for the lar calo hit class.
double maxY
Definition: plot_hist.C:10
intermediate_table::const_iterator const_iterator
LAr calo hit class.
Definition: LArCaloHit.h:39
TFile f
Definition: plotHisto.C:6
Header file for the cluster helper class.
std::set< unsigned int > UIntSet
Detector simulation of raw signals on wires.
HitType
Definition: HitType.h:12
unsigned int GetDaughterVolumeId() const
Get the daughter volume id.
Definition: LArCaloHit.h:174