Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
LArClusterHelper.cc
Go to the documentation of this file.
1
11
12#include <algorithm>
13#include <cmath>
14#include <limits>
15
16using namespace pandora;
17
18namespace lar_content
19{
20
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
35void 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
54void 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
65float 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
97float LArClusterHelper::GetLength(const Cluster *const pCluster)
98{
99 return std::sqrt(LArClusterHelper::GetLengthSquared(pCluster));
100}
101
102//------------------------------------------------------------------------------------------------------------------------------------------
103
105{
106 const float dEdX(0.002f); // approximately 2 MeV/cm
107 return (dEdX * LArClusterHelper::GetLength(pCluster));
108}
109
110//------------------------------------------------------------------------------------------------------------------------------------------
111
112unsigned int LArClusterHelper::GetLayerSpan(const Cluster *const pCluster)
113{
114 return (1 + pCluster->GetOuterPseudoLayer() - pCluster->GetInnerPseudoLayer());
115}
116
117//------------------------------------------------------------------------------------------------------------------------------------------
118
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
132float 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
146float 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
167float 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
188float 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
200float LArClusterHelper::GetClosestDistance(const CartesianVector &position, const ClusterList &clusterList)
201{
202 return (position - LArClusterHelper::GetClosestPosition(position, clusterList)).GetMagnitude();
203}
204
205//------------------------------------------------------------------------------------------------------------------------------------------
206
207float LArClusterHelper::GetClosestDistance(const CartesianVector &position, const Cluster *const pCluster)
208{
209 return (position - LArClusterHelper::GetClosestPosition(position, pCluster)).GetMagnitude();
210}
211
212//------------------------------------------------------------------------------------------------------------------------------------------
213
214float LArClusterHelper::GetClosestDistance(const CartesianVector &position, const CaloHitList &caloHitList)
215{
216 return (position - LArClusterHelper::GetClosestPosition(position, caloHitList)).GetMagnitude();
217}
218
219//------------------------------------------------------------------------------------------------------------------------------------------
220
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
250{
252}
253
254//------------------------------------------------------------------------------------------------------------------------------------------
255
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
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
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
356void 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
388StatusCode 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
424void 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
439void LArClusterHelper::GetExtremalCoordinates(const Cluster *const pCluster, CartesianVector &innerCoordinate, CartesianVector &outerCoordinate)
440{
441 return LArClusterHelper::GetExtremalCoordinates(pCluster->GetOrderedCaloHitList(), innerCoordinate, outerCoordinate);
442}
443
444//------------------------------------------------------------------------------------------------------------------------------------------
445
446void 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
468void 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
573void 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
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 && (hitPosition.GetX() < minX - std::numeric_limits<float>::epsilon() ||
608 hitPosition.GetX() > maxX + std::numeric_limits<float>::epsilon()))
609 continue;
610 else if (useY && (hitPosition.GetY() < minY - std::numeric_limits<float>::epsilon() ||
611 hitPosition.GetY() > maxY + std::numeric_limits<float>::epsilon()))
612 continue;
613 else if (useZ && (hitPosition.GetZ() < minZ - std::numeric_limits<float>::epsilon() ||
614 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
625void 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
643bool 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
656bool 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
669bool 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
682bool 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
695bool 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
725bool LArClusterHelper::SortByPulseHeight(const Cluster *const pLhs, const Cluster *const pRhs)
726{
727 return (pLhs->GetHadronicEnergy() > pRhs->GetHadronicEnergy());
728}
729
730//------------------------------------------------------------------------------------------------------------------------------------------
731
732bool 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
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
763bool 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
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
Header file for the lar calo hit class.
Header file for the cluster helper class.
#define PANDORA_THROW_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:43
LAr calo hit class.
Definition LArCaloHit.h:40
unsigned int GetDaughterVolumeId() const
Get the daughter volume id.
Definition LArCaloHit.h:174
std::set< unsigned int > UIntSet
static pandora::CartesianVector GetClosestPosition(const pandora::CartesianVector &position, const pandora::ClusterList &clusterList)
Get closest position in a list of clusters to a specified input position vector.
static void GetClustersByHitType(const pandora::ClusterList &inputClusters, const pandora::HitType hitType, pandora::ClusterList &clusterList)
Get the subset of clusters, from a provided list, that match the specified hit type.
static bool SortByInnerLayer(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by inner layer, then position, then pulse-height.
static bool SortHitsByPositionInX(const pandora::CaloHit *const pLhs, const pandora::CaloHit *const pRhs)
Sort calo hits by their position (use X, followed by Z, followed by Y)
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
static void GetCoordinateVector(const pandora::Cluster *const pCluster, pandora::CartesianPointVector &coordinateVector)
Get vector of hit coordinates from an input cluster.
static bool SortByPulseHeight(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by pulse-height.
static pandora::StatusCode GetAverageZ(const pandora::Cluster *const pCluster, const float xmin, const float xmax, float &averageZ)
Get average Z positions of the calo hits in a cluster in range xmin to xmax.
static bool SortHitsByPulseHeight(const pandora::CaloHit *const pLhs, const pandora::CaloHit *const pRhs)
Sort calo hits by their pulse height.
static bool SortHitsByPosition(const pandora::CaloHit *const pLhs, const pandora::CaloHit *const pRhs)
Sort calo hits by their position (use Z, followed by X, followed by Y)
static float GetEnergyFromLength(const pandora::Cluster *const pCluster)
Get energy of cluster, based on length.
static bool SortCoordinatesByPosition(const pandora::CartesianVector &lhs, const pandora::CartesianVector &rhs)
Sort cartesian vectors by their position (use Z, followed by X, followed by Y)
static bool SortByNHits(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by number of hits, then layer span, then inner layer, then position,...
static void GetClosestPositions(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, pandora::CartesianVector &position1, pandora::CartesianVector &position2)
Get pair of closest positions for a pair of clusters.
static void GetExtremalCoordinates(const pandora::ClusterList &clusterList, pandora::CartesianVector &innerCoordinate, pandora::CartesianVector &outerCoordinate)
Get positions of the two most distant calo hits in a list of cluster (ordered by Z)
static bool SortByNOccupiedLayers(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by number of occupied layers, and by inner layer, then energy in event of a tie.
static unsigned int GetLayerSpan(const pandora::Cluster *const pCluster)
Get number of layers spanned by cluster (1+Last-First)
static void GetClustersUVW(const pandora::ClusterList &inputClusters, pandora::ClusterList &clusterListU, pandora::ClusterList &clusterListV, pandora::ClusterList &clusterListW)
Divide an input cluster list into separate u, v and w lists (exception raised if alternative hit type...
static bool SortByLayerSpan(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by layer span, then inner layer, then position, then pulse-height.
static bool SortByPosition(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by position, then pulse-height.
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
static float GetLength(const pandora::Cluster *const pCluster)
Get length of cluster.
static void GetCaloHitListInBoundingBox(const pandora::Cluster *const pCluster, const pandora::CartesianVector &lowerBound, const pandora::CartesianVector &upperBound, pandora::CaloHitList &caloHitList)
Get list of Calo hits from an input cluster that are contained in a bounding box. The hits are sorted...
static float GetLayerOccupancy(const pandora::Cluster *const pCluster)
Fraction of occupied layers in cluster.
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.
static void GetDaughterVolumeIDs(const pandora::Cluster *const pCluster, UIntSet &daughterVolumeIds)
Get the set of the daughter volumes that contains the cluster.
static void GetClusterBoundingBox(const pandora::Cluster *const pCluster, pandora::CartesianVector &minimumCoordinate, pandora::CartesianVector &maximumCoordinate)
Get minimum and maximum X, Y and Z positions of the calo hits in a cluster.
CaloHit class.
Definition CaloHit.h:26
const CartesianVector & GetPositionVector() const
Get the position vector of center of calorimeter cell, units mm.
Definition CaloHit.h:350
float GetHadronicEnergy() const
Get the calibrated hadronic energy measure.
Definition CaloHit.h:490
CartesianVector class.
void SetValues(float x, float y, float z)
Set the values of cartesian vector components.
float GetX() const
Get the cartesian x coordinate.
float GetZ() const
Get the cartesian z coordinate.
float GetY() const
Get the cartesian y coordinate.
Cluster class.
Definition Cluster.h:31
unsigned int GetOuterPseudoLayer() const
Get the outermost pseudo layer in the cluster.
Definition Cluster.h:568
float GetHadronicEnergy() const
Get the sum of hadronic energy measures of all constituent calo hits, units GeV.
Definition Cluster.h:526
unsigned int GetNCaloHits() const
Get the number of calo hits in the cluster.
Definition Cluster.h:484
unsigned int GetInnerPseudoLayer() const
Get the innermost pseudo layer in the cluster.
Definition Cluster.h:561
const CartesianVector GetCentroid(const unsigned int pseudoLayer) const
Get unweighted centroid for cluster at a particular pseudo layer, calculated using cached values of h...
Definition Cluster.cc:37
const OrderedCaloHitList & GetOrderedCaloHitList() const
Get the ordered calo hit list.
Definition Cluster.h:470
Calo hit lists arranged by pseudo layer.
const_iterator end() const
Returns a const iterator referring to the past-the-end element in the ordered calo hit list.
const_iterator begin() const
Returns a const iterator referring to the first element in the ordered calo hit list.
TheList::const_iterator const_iterator
StatusCode Add(const OrderedCaloHitList &rhs)
Add the hits from a second ordered calo hit list to this list.
unsigned int size() const
Returns the number of elements in the container.
bool empty() const
Returns whether the map container is empty (i.e. whether its size is 0)
StatusCodeException class.
HitType
Calorimeter hit type enum.
MANAGED_CONTAINER< const Cluster * > ClusterList
std::vector< CartesianVector > CartesianPointVector
MANAGED_CONTAINER< const CaloHit * > CaloHitList
StatusCode
The StatusCode enum.