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