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