Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
TrackRefinementBaseAlgorithm.cc
Go to the documentation of this file.
1
9
11
15
16using namespace pandora;
17
18namespace lar_content
19{
20
22 m_minClusterLength(15.f),
23 m_microSlidingFitWindow(20),
24 m_macroSlidingFitWindow(1000),
25 m_stableRegionClusterFraction(0.05f),
26 m_mergePointMinCosAngleDeviation(0.999f),
27 m_minHitFractionForHitRemoval(0.05f),
28 m_maxDistanceFromMainTrack(0.75f),
29 m_maxHitDistanceFromCluster(4.f),
30 m_maxHitSeparationForConnectedCluster(4.f),
31 m_maxTrackGaps(3),
32 m_lineSegmentLength(3.f),
33 m_hitWidthMode(false)
34{
35}
36
37//------------------------------------------------------------------------------------------------------------------------------------------
38
39template <typename T>
40void TrackRefinementBaseAlgorithm::InitialiseContainers(const ClusterList *pClusterList, const T sortFunction, ClusterVector &clusterVector,
41 SlidingFitResultMapPair &slidingFitResultMapPair) const
42{
43 const float slidingFitPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
44
45 for (const Cluster *const pCluster : *pClusterList)
46 {
48 continue;
49
50 try
51 {
52 const TwoDSlidingFitResult microSlidingFitResult(pCluster, m_microSlidingFitWindow, slidingFitPitch);
53 const TwoDSlidingFitResult macroSlidingFitResult(pCluster, m_macroSlidingFitWindow, slidingFitPitch);
54
55 slidingFitResultMapPair.first->insert(TwoDSlidingFitResultMap::value_type(pCluster, microSlidingFitResult));
56 slidingFitResultMapPair.second->insert(TwoDSlidingFitResultMap::value_type(pCluster, macroSlidingFitResult));
57 clusterVector.push_back(pCluster);
58 }
59 catch (const StatusCodeException &)
60 {
61 }
62 }
63
64 std::sort(clusterVector.begin(), clusterVector.end(), sortFunction);
65}
66
67//------------------------------------------------------------------------------------------------------------------------------------------
68
70 const TwoDSlidingFitResult &clusterMacroFitResult, const TwoDSlidingFitResult &associatedMacroFitResult, const bool isEndUpstream,
71 CartesianVector &clusterMergePosition, CartesianVector &clusterMergeDirection) const
72{
73 CartesianVector clusterAverageDirection(0.f, 0.f, 0.f), associatedAverageDirection(0.f, 0.f, 0.f);
74 clusterMacroFitResult.GetGlobalDirection(clusterMacroFitResult.GetLayerFitResultMap().begin()->second.GetGradient(), clusterAverageDirection);
75 associatedMacroFitResult.GetGlobalDirection(associatedMacroFitResult.GetLayerFitResultMap().begin()->second.GetGradient(), associatedAverageDirection);
76
77 const LayerFitResultMap &clusterMicroLayerFitResultMap(clusterMicroFitResult.GetLayerFitResultMap());
78 const int startLayer(isEndUpstream ? clusterMicroFitResult.GetMinLayer() : clusterMicroFitResult.GetMaxLayer());
79 const int endLayer(isEndUpstream ? clusterMicroFitResult.GetMaxLayer() : clusterMicroFitResult.GetMinLayer());
80 const int loopTerminationLayer(endLayer + (isEndUpstream ? 1 : -1));
81 const int step(isEndUpstream ? 1 : -1);
82
83 // ATTN: Search for stable region for which the local layer gradient agrees well with associated cluster global gradient
84 unsigned int gradientStabilityWindow(std::ceil(clusterMicroLayerFitResultMap.size() * m_stableRegionClusterFraction));
85 unsigned int goodLayerCount(0);
86
87 clusterMicroLayerFitResultMap.at(endLayer);
88
89 for (int i = startLayer; i != loopTerminationLayer; i += step)
90 {
91 const auto microIter(clusterMicroLayerFitResultMap.find(i));
92
93 if (microIter == clusterMicroLayerFitResultMap.end())
94 continue;
95
96 CartesianVector microDirection(0.f, 0.f, 0.f);
97 clusterMicroFitResult.GetGlobalDirection(microIter->second.GetGradient(), microDirection);
98
99 const float cosDirectionOpeningAngle(microDirection.GetCosOpeningAngle(associatedAverageDirection));
100 if (cosDirectionOpeningAngle > m_mergePointMinCosAngleDeviation)
101 {
102 // ATTN: Set merge point and direction as that at the first layer in the stable region
103 if (goodLayerCount == 0)
104 {
105 clusterMergeDirection = clusterAverageDirection;
107 STATUS_CODE_SUCCESS, !=, clusterMicroFitResult.GetGlobalFitPosition(microIter->second.GetL(), clusterMergePosition));
108 }
109
110 ++goodLayerCount;
111 }
112 else
113 {
114 goodLayerCount = 0;
115 }
116
117 if (goodLayerCount > gradientStabilityWindow)
118 break;
119
120 // ATTN: Abort merging process have not found a stable region
121 if (i == endLayer)
122 return false;
123 }
124
125 return true;
126}
127
128//------------------------------------------------------------------------------------------------------------------------------------------
129
131 const ClusterList *const pClusterList, ClusterToCaloHitListMap &clusterToCaloHitListMap,
132 const ClusterList &unavailableProtectedClusters, const float distanceToLine) const
133{
134 const float minX(std::min(firstCorner.GetX(), secondCorner.GetX())), maxX(std::max(firstCorner.GetX(), secondCorner.GetX()));
135 const float minZ(std::min(firstCorner.GetZ(), secondCorner.GetZ())), maxZ(std::max(firstCorner.GetZ(), secondCorner.GetZ()));
136
137 CartesianVector connectingLineDirection(firstCorner - secondCorner);
138 connectingLineDirection = connectingLineDirection.GetUnitVector();
139
140 for (const Cluster *const pCluster : *pClusterList)
141 {
142 if (std::find(unavailableProtectedClusters.begin(), unavailableProtectedClusters.end(), pCluster) != unavailableProtectedClusters.end())
143 continue;
144
145 const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
146 for (const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
147 {
148 for (const CaloHit *const pCaloHit : *mapEntry.second)
149 {
150 CartesianVector hitPosition(m_hitWidthMode ? LArHitWidthHelper::GetClosestPointToLine2D(firstCorner, connectingLineDirection, pCaloHit)
151 : pCaloHit->GetPositionVector());
152
153 if (!this->IsInBoundingBox(minX, maxX, minZ, maxZ, hitPosition))
154 continue;
155
156 if (distanceToLine > 0.f)
157 {
158 if (!this->IsCloseToLine(hitPosition, firstCorner, connectingLineDirection, distanceToLine))
159 continue;
160 }
161
162 clusterToCaloHitListMap[pCluster].push_back(pCaloHit);
163 }
164 }
165 }
166}
167
168//------------------------------------------------------------------------------------------------------------------------------------------
169
171 const float minX, const float maxX, const float minZ, const float maxZ, const CartesianVector &hitPosition) const
172{
173 return !((hitPosition.GetX() < minX) || (hitPosition.GetX() > maxX) || (hitPosition.GetZ() < minZ) || (hitPosition.GetZ() > maxZ));
174}
175
176//------------------------------------------------------------------------------------------------------------------------------------------
177
179 const CartesianVector &lineDirection, const float distanceToLine) const
180{
181 const float transverseDistanceFromLine(lineDirection.GetCrossProduct(hitPosition - lineStart).GetMagnitude());
182
183 return (transverseDistanceFromLine < distanceToLine);
184}
185
186//------------------------------------------------------------------------------------------------------------------------------------------
187
188bool TrackRefinementBaseAlgorithm::AreExtrapolatedHitsGood(const ClusterToCaloHitListMap &clusterToCaloHitListMap, ClusterAssociation &clusterAssociation) const
189{
190 CaloHitVector extrapolatedHitVector;
191 for (const auto &entry : clusterToCaloHitListMap)
192 extrapolatedHitVector.insert(extrapolatedHitVector.begin(), entry.second.begin(), entry.second.end());
193
194 // ATTN: Extrapolated hit checks require extrapolatedHitVector to be ordered from upstream -> downstream merge point
195 std::sort(extrapolatedHitVector.begin(), extrapolatedHitVector.end(),
197
198 if (!this->AreExtrapolatedHitsNearBoundaries(extrapolatedHitVector, clusterAssociation))
199 return false;
200
201 if (clusterToCaloHitListMap.empty())
202 return true;
203
204 if (!this->IsTrackContinuous(clusterAssociation, extrapolatedHitVector))
205 return false;
206
207 return true;
208}
209
210//------------------------------------------------------------------------------------------------------------------------------------------
211
212bool TrackRefinementBaseAlgorithm::IsNearBoundary(const CaloHit *const pCaloHit, const CartesianVector &boundaryPosition2D, const float boundaryTolerance) const
213{
214 const float distanceToBoundary(LArHitWidthHelper::GetClosestDistanceToPoint2D(pCaloHit, boundaryPosition2D));
215
216 return (distanceToBoundary < boundaryTolerance);
217}
218
219//------------------------------------------------------------------------------------------------------------------------------------------
220
221bool TrackRefinementBaseAlgorithm::IsTrackContinuous(const ClusterAssociation &clusterAssociation, const CaloHitVector &extrapolatedCaloHitVector) const
222{
223 CartesianPointVector trackSegmentBoundaries;
224 this->GetTrackSegmentBoundaries(clusterAssociation, trackSegmentBoundaries);
225
226 if (trackSegmentBoundaries.size() < 2)
227 {
228 std::cout << "TrackInEMShowerAlgorithm: Less than two track segment boundaries" << std::endl;
229 throw STATUS_CODE_NOT_ALLOWED;
230 }
231
232 unsigned int segmentsWithoutHits(0);
233 CaloHitVector::const_iterator caloHitIter(extrapolatedCaloHitVector.begin());
235 clusterAssociation.GetConnectingLineDirection(), *caloHitIter)
236 : (*caloHitIter)->GetPositionVector());
237
238 for (unsigned int i = 0; i < (trackSegmentBoundaries.size() - 1); ++i)
239 {
240 if (caloHitIter == extrapolatedCaloHitVector.end())
241 {
242 ++segmentsWithoutHits;
243
244 if (segmentsWithoutHits > m_maxTrackGaps)
245 return false;
246
247 continue;
248 }
249
250 unsigned int hitsInSegment(0);
251 while (this->IsInLineSegment(trackSegmentBoundaries.at(i), trackSegmentBoundaries.at(i + 1), hitPosition))
252 {
253 ++hitsInSegment;
254 ++caloHitIter;
255
256 if (caloHitIter == extrapolatedCaloHitVector.end())
257 break;
258
260 clusterAssociation.GetConnectingLineDirection(), *caloHitIter)
261 : (*caloHitIter)->GetPositionVector();
262 }
263
264 segmentsWithoutHits = hitsInSegment ? 0 : segmentsWithoutHits + 1;
265
266 if (segmentsWithoutHits > m_maxTrackGaps)
267 return false;
268 }
269
270 return true;
271}
272
273//------------------------------------------------------------------------------------------------------------------------------------------
274
275void TrackRefinementBaseAlgorithm::GetTrackSegmentBoundaries(const ClusterAssociation &clusterAssociation, CartesianPointVector &trackSegmentBoundaries) const
276{
277 if (m_lineSegmentLength < std::numeric_limits<float>::epsilon())
278 {
279 std::cout << "TrackInEMShowerAlgorithm: Line segment length must be positive and nonzero" << std::endl;
280 throw STATUS_CODE_INVALID_PARAMETER;
281 }
282
283 const CartesianVector &trackDirection(clusterAssociation.GetConnectingLineDirection());
284 float trackLength((clusterAssociation.GetUpstreamMergePoint() - clusterAssociation.GetDownstreamMergePoint()).GetMagnitude());
285
286 // ATTN: Consider the existence of gaps where no hits will be found
287 DetectorGapList consideredGaps;
288 trackLength -= this->DistanceInGap(
289 clusterAssociation.GetUpstreamMergePoint(), clusterAssociation.GetDownstreamMergePoint(), trackDirection, consideredGaps);
290 consideredGaps.clear();
291
292 const int fullSegments(std::floor(trackLength / m_lineSegmentLength));
293
294 if (fullSegments == 0)
295 {
296 trackSegmentBoundaries = {clusterAssociation.GetUpstreamMergePoint(), clusterAssociation.GetDownstreamMergePoint()};
297 return;
298 }
299
300 // ATTN: To handle final segment merge track remainder with preceding segment and if track remainder was more than half of the segment length split into two
301 const float lengthOfTrackRemainder(trackLength - (fullSegments * m_lineSegmentLength));
302 const bool splitFinalSegment(lengthOfTrackRemainder > m_lineSegmentLength * 0.5f);
303 const int numberOfBoundaries(fullSegments + (splitFinalSegment ? 2 : 1));
304
305 CartesianVector segmentUpstreamBoundary(clusterAssociation.GetUpstreamMergePoint()), segmentDownstreamBoundary(segmentUpstreamBoundary);
306 this->RepositionIfInGap(trackDirection, segmentUpstreamBoundary);
307 trackSegmentBoundaries.push_back(segmentUpstreamBoundary);
308
309 for (int i = 1; i < numberOfBoundaries; ++i)
310 {
311 if (i < fullSegments)
312 {
313 segmentDownstreamBoundary += trackDirection * m_lineSegmentLength;
314 }
315 else
316 {
317 if (splitFinalSegment)
318 {
319 segmentDownstreamBoundary += trackDirection * (m_lineSegmentLength + lengthOfTrackRemainder) * 0.5f;
320 }
321 else
322 {
323 segmentDownstreamBoundary += trackDirection * (m_lineSegmentLength + lengthOfTrackRemainder);
324 }
325 }
326
327 float distanceInGap(this->DistanceInGap(segmentUpstreamBoundary, segmentDownstreamBoundary, trackDirection, consideredGaps));
328 while (distanceInGap > std::numeric_limits<float>::epsilon())
329 {
330 this->RepositionIfInGap(trackDirection, segmentDownstreamBoundary);
331 segmentDownstreamBoundary += trackDirection * distanceInGap;
332 distanceInGap = this->DistanceInGap(segmentUpstreamBoundary, segmentDownstreamBoundary, trackDirection, consideredGaps);
333 }
334
335 trackSegmentBoundaries.push_back(segmentDownstreamBoundary);
336 }
337}
338
339//------------------------------------------------------------------------------------------------------------------------------------------
340
342{
343 const DetectorGapList detectorGapList(this->GetPandora().GetGeometry()->GetDetectorGapList());
344 for (const DetectorGap *const pDetectorGap : detectorGapList)
345 {
346 const LineGap *const pLineGap(dynamic_cast<const LineGap *>(pDetectorGap));
347
348 if (pLineGap)
349 {
350 const LineGapType lineGapType(pLineGap->GetLineGapType());
351
352 if (lineGapType == TPC_DRIFT_GAP)
353 {
354 if ((pLineGap->GetLineStartX() < trackPoint.GetX()) && (pLineGap->GetLineEndX() > trackPoint.GetX()))
355 {
356 if (std::fabs(mergeDirection.GetX()) < std::numeric_limits<float>::epsilon())
357 throw StatusCodeException(STATUS_CODE_FAILURE);
358
359 const float gradient(mergeDirection.GetZ() / mergeDirection.GetX());
360
361 trackPoint = CartesianVector(
362 pLineGap->GetLineEndX(), 0.f, trackPoint.GetZ() + (gradient * (pLineGap->GetLineEndX() - trackPoint.GetX())));
363 }
364 }
365
366 if ((lineGapType == TPC_WIRE_GAP_VIEW_U) || (lineGapType == TPC_WIRE_GAP_VIEW_V) || (lineGapType == TPC_WIRE_GAP_VIEW_W))
367 {
368 if ((pLineGap->GetLineStartZ() < trackPoint.GetZ()) && (pLineGap->GetLineEndZ() > trackPoint.GetZ()))
369 {
370 if (std::fabs(mergeDirection.GetZ()) < std::numeric_limits<float>::epsilon())
371 throw StatusCodeException(STATUS_CODE_FAILURE);
372
373 const float gradient(mergeDirection.GetX() / mergeDirection.GetZ());
374
375 trackPoint = CartesianVector(
376 trackPoint.GetX() + (gradient * (pLineGap->GetLineEndZ() - trackPoint.GetZ())), 0.f, pLineGap->GetLineEndZ());
377 }
378 }
379 }
380 }
381}
382
383//------------------------------------------------------------------------------------------------------------------------------------------
384
385float TrackRefinementBaseAlgorithm::DistanceInGap(const CartesianVector &upstreamPoint, const CartesianVector &downstreamPoint,
386 const CartesianVector &connectingLine, DetectorGapList &consideredGaps) const
387{
388 const CartesianVector &lowerXPoint(upstreamPoint.GetX() < downstreamPoint.GetX() ? upstreamPoint : downstreamPoint);
389 const CartesianVector &higherXPoint(upstreamPoint.GetX() < downstreamPoint.GetX() ? downstreamPoint : upstreamPoint);
390
391 const float cosAngleToX(std::fabs(connectingLine.GetDotProduct(CartesianVector(1.f, 0.f, 0.f))));
392 const float cosAngleToZ(std::fabs(connectingLine.GetDotProduct(CartesianVector(0.f, 0.f, 1.f))));
393
394 float distanceInGaps(0.f);
395 const DetectorGapList detectorGapList(this->GetPandora().GetGeometry()->GetDetectorGapList());
396 for (const DetectorGap *const pDetectorGap : detectorGapList)
397 {
398 if (std::find(consideredGaps.begin(), consideredGaps.end(), pDetectorGap) != consideredGaps.end())
399 continue;
400
401 const LineGap *const pLineGap(dynamic_cast<const LineGap *>(pDetectorGap));
402
403 if (pLineGap)
404 {
405 const LineGapType lineGapType(pLineGap->GetLineGapType());
406
407 if (lineGapType == TPC_DRIFT_GAP)
408 {
409 float xDistanceInGap(0.f);
410
411 if ((pLineGap->GetLineStartX() > lowerXPoint.GetX()) && (pLineGap->GetLineEndX() < higherXPoint.GetX()))
412 {
413 xDistanceInGap = (pLineGap->GetLineEndX() - pLineGap->GetLineStartX());
414 }
415 else if ((pLineGap->GetLineStartX() < lowerXPoint.GetX()) && (pLineGap->GetLineEndX() > lowerXPoint.GetX()))
416 {
417 xDistanceInGap = (pLineGap->GetLineEndX() - lowerXPoint.GetX());
418 }
419 else if ((pLineGap->GetLineStartX() < higherXPoint.GetX()) && (pLineGap->GetLineEndX() > higherXPoint.GetX()))
420 {
421 xDistanceInGap = (higherXPoint.GetX() - pLineGap->GetLineStartX());
422 }
423 else
424 {
425 continue;
426 }
427
428 if (std::fabs(cosAngleToX) < std::numeric_limits<float>::epsilon())
429 throw StatusCodeException(STATUS_CODE_FAILURE);
430
431 distanceInGaps += (xDistanceInGap / cosAngleToX);
432
433 consideredGaps.push_back(pDetectorGap);
434 }
435
436 if ((lineGapType == TPC_WIRE_GAP_VIEW_U) || (lineGapType == TPC_WIRE_GAP_VIEW_V) || (lineGapType == TPC_WIRE_GAP_VIEW_W))
437 {
438 float zDistanceInGap(0.f);
439
440 if ((pLineGap->GetLineStartZ() > upstreamPoint.GetZ()) && (pLineGap->GetLineEndZ() < downstreamPoint.GetZ()))
441 {
442 zDistanceInGap = pLineGap->GetLineEndZ() - pLineGap->GetLineStartZ();
443 }
444 else if ((pLineGap->GetLineStartZ() < upstreamPoint.GetZ()) && (pLineGap->GetLineEndZ() > upstreamPoint.GetZ()))
445 {
446 zDistanceInGap = pLineGap->GetLineEndZ() - upstreamPoint.GetZ();
447 }
448 else if ((pLineGap->GetLineStartZ() < downstreamPoint.GetZ()) && (pLineGap->GetLineEndZ() > downstreamPoint.GetZ()))
449 {
450 zDistanceInGap = downstreamPoint.GetZ() - pLineGap->GetLineStartZ();
451 }
452 else
453 {
454 continue;
455 }
456
457 if (std::fabs(cosAngleToZ) < std::numeric_limits<float>::epsilon())
458 throw StatusCodeException(STATUS_CODE_FAILURE);
459
460 distanceInGaps += (zDistanceInGap / cosAngleToZ);
461
462 consideredGaps.push_back(pDetectorGap);
463 }
464 }
465 }
466
467 return distanceInGaps;
468}
469
470//------------------------------------------------------------------------------------------------------------------------------------------
471
473 const CartesianVector &lowerBoundary, const CartesianVector &upperBoundary, const CartesianVector &point) const
474{
475 const float segmentBoundaryGradient = (-1.f) * (upperBoundary.GetX() - lowerBoundary.GetX()) / (upperBoundary.GetZ() - lowerBoundary.GetZ());
476 const float xPointOnUpperLine((point.GetZ() - upperBoundary.GetZ()) / segmentBoundaryGradient + upperBoundary.GetX());
477 const float xPointOnLowerLine((point.GetZ() - lowerBoundary.GetZ()) / segmentBoundaryGradient + lowerBoundary.GetX());
478
479 if (std::fabs(xPointOnUpperLine - point.GetX()) < std::numeric_limits<float>::epsilon())
480 return true;
481
482 if (std::fabs(xPointOnLowerLine - point.GetX()) < std::numeric_limits<float>::epsilon())
483 return true;
484
485 if ((point.GetX() > xPointOnUpperLine) && (point.GetX() > xPointOnLowerLine))
486 return false;
487
488 if ((point.GetX() < xPointOnUpperLine) && (point.GetX() < xPointOnLowerLine))
489 return false;
490
491 return true;
492}
493
494//------------------------------------------------------------------------------------------------------------------------------------------
495
497 const bool isEndUpstream, const ClusterToCaloHitListMap &clusterToCaloHitListMap, ClusterList &remnantClusterList,
498 TwoDSlidingFitResultMap &microSlidingFitResultMap, TwoDSlidingFitResultMap &macroSlidingFitResultMap) const
499{
500 float rL(0.f), rT(0.f);
501 const TwoDSlidingFitResult &microFitResult(microSlidingFitResultMap.at(pCluster));
502 microFitResult.GetLocalPosition(splitPosition, rL, rT);
503
504 const TwoDSlidingFitResult &macroFitResult(macroSlidingFitResultMap.at(pCluster));
505 CartesianVector averageDirection(0.f, 0.f, 0.f);
506 macroFitResult.GetGlobalDirection(macroFitResult.GetLayerFitResultMap().begin()->second.GetGradient(), averageDirection);
507
508 const bool isVertical(std::fabs(averageDirection.GetX()) < std::numeric_limits<float>::epsilon());
509 const float clusterGradient(isVertical ? 0.f : averageDirection.GetZ() / averageDirection.GetX());
510 const float clusterIntercept(isVertical ? splitPosition.GetX() : splitPosition.GetZ() - (clusterGradient * splitPosition.GetX()));
511
512 // Fragmentation initialisation
513 std::string originalListName, fragmentListName;
514 const ClusterList originalClusterList(1, pCluster);
516 STATUS_CODE_SUCCESS, !=, PandoraContentApi::InitializeFragmentation(*this, originalClusterList, originalListName, fragmentListName));
517
518 const Cluster *pMainTrackCluster(nullptr), *pAboveCluster(nullptr), *pBelowCluster(nullptr);
519
520 const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
521 for (const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
522 {
523 for (const CaloHit *const pCaloHit : *mapEntry.second)
524 {
525 const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
526 float thisL(0.f), thisT(0.f);
527
528 microFitResult.GetLocalPosition(pCaloHit->GetPositionVector(), thisL, thisT);
529
530 bool isAnExtrapolatedHit(false);
531 const auto extrapolatedCaloHitIter(clusterToCaloHitListMap.find(pCluster));
532
533 if (extrapolatedCaloHitIter != clusterToCaloHitListMap.end())
534 isAnExtrapolatedHit = std::find(extrapolatedCaloHitIter->second.begin(), extrapolatedCaloHitIter->second.end(), pCaloHit) !=
535 extrapolatedCaloHitIter->second.end();
536
537 const bool isAbove(((clusterGradient * hitPosition.GetX()) + clusterIntercept) < (isVertical ? hitPosition.GetX() : hitPosition.GetZ()));
538 const bool isToRemove(!isAnExtrapolatedHit && (((thisL < rL) && isEndUpstream) || ((thisL > rL) && !isEndUpstream)));
539
540 const Cluster *&pClusterToModify(isToRemove ? (isAbove ? pAboveCluster : pBelowCluster) : pMainTrackCluster);
541
542 if (pClusterToModify)
543 {
544 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*this, pClusterToModify, pCaloHit));
545 }
546 else
547 {
548 PandoraContentApi::Cluster::Parameters parameters;
549 parameters.m_caloHitList.push_back(pCaloHit);
550 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*this, parameters, pClusterToModify));
551
552 if (pClusterToModify != pMainTrackCluster)
553 remnantClusterList.push_back(pClusterToModify);
554 }
555 }
556 }
557
558 // End fragmentation
559 if (pAboveCluster || pBelowCluster)
560 {
561 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*this, fragmentListName, originalListName));
562 return pMainTrackCluster;
563 }
564 else
565 {
566 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*this, originalListName, fragmentListName));
567 return pCluster;
568 }
569}
570
571//------------------------------------------------------------------------------------------------------------------------------------------
572
573void TrackRefinementBaseAlgorithm::AddHitsToMainTrack(const Cluster *const pMainTrackCluster, const Cluster *const pShowerCluster,
574 const CaloHitList &caloHitsToMerge, const ClusterAssociation &clusterAssociation, ClusterList &remnantClusterList) const
575{
576 // To ignore crossing CR muon or test beam tracks
577 if (((static_cast<float>(caloHitsToMerge.size()) / static_cast<float>(pShowerCluster->GetNCaloHits())) < m_minHitFractionForHitRemoval) &&
579 return;
580
581 if (pShowerCluster->GetNCaloHits() == caloHitsToMerge.size())
582 {
583 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*this, pMainTrackCluster, pShowerCluster));
584 return;
585 }
586
587 // Fragmentation initialisation
588 std::string originalListName, fragmentListName;
589 const ClusterList originalClusterList(1, pShowerCluster);
591 STATUS_CODE_SUCCESS, !=, PandoraContentApi::InitializeFragmentation(*this, originalClusterList, originalListName, fragmentListName));
592
593 const Cluster *pAboveCluster(nullptr), *pBelowCluster(nullptr);
594
595 const bool isVertical(std::fabs(clusterAssociation.GetConnectingLineDirection().GetX()) < std::numeric_limits<float>::epsilon());
596 const float connectingLineGradient(
597 isVertical ? 0.f : clusterAssociation.GetConnectingLineDirection().GetZ() / clusterAssociation.GetConnectingLineDirection().GetX());
598 const float connectingLineIntercept(isVertical ? clusterAssociation.GetUpstreamMergePoint().GetX()
599 : clusterAssociation.GetUpstreamMergePoint().GetZ() -
600 (connectingLineGradient * clusterAssociation.GetUpstreamMergePoint().GetX()));
601
602 const OrderedCaloHitList orderedCaloHitList(pShowerCluster->GetOrderedCaloHitList());
603 for (const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
604 {
605 for (const CaloHit *const pCaloHit : *mapEntry.second)
606 {
607 const bool isAnExtrapolatedHit(std::find(caloHitsToMerge.begin(), caloHitsToMerge.end(), pCaloHit) != caloHitsToMerge.end());
608 if (isAnExtrapolatedHit)
609 {
610 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromCluster(*this, pShowerCluster, pCaloHit));
611 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*this, pMainTrackCluster, pCaloHit));
612 }
613 else
614 {
615 const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
616 const bool isAbove(((connectingLineGradient * hitPosition.GetX()) + connectingLineIntercept) <
617 (isVertical ? hitPosition.GetX() : hitPosition.GetZ()));
618 const Cluster *&pClusterToModify(isAbove ? pAboveCluster : pBelowCluster);
619
620 if (pClusterToModify)
621 {
622 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*this, pClusterToModify, pCaloHit));
623 }
624 else
625 {
626 PandoraContentApi::Cluster::Parameters parameters;
627 parameters.m_caloHitList.push_back(pCaloHit);
628 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*this, parameters, pClusterToModify));
629
630 remnantClusterList.push_back(pClusterToModify);
631 }
632 }
633 }
634 }
635
636 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*this, fragmentListName, originalListName));
637}
638
639//------------------------------------------------------------------------------------------------------------------------------------------
640
641void TrackRefinementBaseAlgorithm::ProcessRemnantClusters(const ClusterList &remnantClusterList, const Cluster *const pMainTrackCluster,
642 const ClusterList *const pClusterList, ClusterList &createdClusters) const
643{
644 ClusterList fragmentedClusters;
645 for (const Cluster *const pRemnantCluster : remnantClusterList)
646 {
647 if (this->IsClusterRemnantDisconnected(pRemnantCluster))
648 {
649 this->FragmentRemnantCluster(pRemnantCluster, fragmentedClusters);
650 }
651 else
652 {
653 fragmentedClusters.push_back(pRemnantCluster);
654 }
655 }
656
657 for (const Cluster *const pFragmentedCluster : fragmentedClusters)
658 {
659 if ((pFragmentedCluster->GetNCaloHits() == 1) && (this->AddToNearestCluster(pFragmentedCluster, pMainTrackCluster, pClusterList)))
660 continue;
661
662 createdClusters.push_back(pFragmentedCluster);
663 }
664}
665
666//------------------------------------------------------------------------------------------------------------------------------------------
667
669 const Cluster *const pClusterToMerge, const Cluster *const pMainTrackCluster, const ClusterList *const pClusterList) const
670{
671 const Cluster *pClosestCluster(nullptr);
672 float closestDistance(std::numeric_limits<float>::max());
673
674 for (const Cluster *const pCluster : *pClusterList)
675 {
676 if (pCluster == pClusterToMerge)
677 continue;
678
679 const float separationDistance(LArClusterHelper::GetClosestDistance(pClusterToMerge, pCluster));
680
681 if (separationDistance < closestDistance)
682 {
683 if ((pCluster == pMainTrackCluster) && (separationDistance > m_maxDistanceFromMainTrack))
684 continue;
685
686 pClosestCluster = pCluster;
687 closestDistance = separationDistance;
688 }
689 }
690
691 if (closestDistance < m_maxHitDistanceFromCluster)
692 {
693 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*this, pClosestCluster, pClusterToMerge));
694 return true;
695 }
696
697 return false;
698}
699
700//------------------------------------------------------------------------------------------------------------------------------------------
701
703{
704 if (pRemnantCluster->GetNCaloHits() == 1)
705 return false;
706
707 const OrderedCaloHitList &orderedCaloHitList(pRemnantCluster->GetOrderedCaloHitList());
708 const CaloHit *pPreviousCaloHit(orderedCaloHitList.begin()->second->front());
709
710 for (const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
711 {
712 for (const CaloHit *const pCaloHit : *mapEntry.second)
713 {
714 if (pCaloHit == pPreviousCaloHit)
715 continue;
716
717 const float separationDistanceSquared(pCaloHit->GetPositionVector().GetDistanceSquared(pPreviousCaloHit->GetPositionVector()));
718
720 return true;
721
722 pPreviousCaloHit = pCaloHit;
723 }
724 }
725
726 return false;
727}
728
729//------------------------------------------------------------------------------------------------------------------------------------------
730
731void TrackRefinementBaseAlgorithm::FragmentRemnantCluster(const Cluster *const pRemnantCluster, ClusterList &fragmentedClusterList) const
732{
733 // Fragmentation initialisation
734 std::string originalListName, fragmentListName;
735 const ClusterList originalClusterList(1, pRemnantCluster);
737 STATUS_CODE_SUCCESS, !=, PandoraContentApi::InitializeFragmentation(*this, originalClusterList, originalListName, fragmentListName));
738
739 ClusterList createdClusters;
740
741 const OrderedCaloHitList &orderedCaloHitList(pRemnantCluster->GetOrderedCaloHitList());
742 for (const OrderedCaloHitList::value_type &mapEntry : orderedCaloHitList)
743 {
744 for (const CaloHit *const pCaloHit : *mapEntry.second)
745 {
746 const Cluster *pClosestCluster(nullptr);
747
748 if (!createdClusters.empty())
749 {
750 float closestDistance(std::numeric_limits<float>::max());
751
752 for (const Cluster *const pCreatedCluster : createdClusters)
753 {
754 const float separationDistance(LArClusterHelper::GetClosestDistance(pCaloHit->GetPositionVector(), pCreatedCluster));
755 if ((separationDistance < closestDistance) && (separationDistance < m_maxHitDistanceFromCluster))
756 {
757 closestDistance = separationDistance;
758 pClosestCluster = pCreatedCluster;
759 }
760 }
761 }
762
763 if (pClosestCluster)
764 {
765 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*this, pClosestCluster, pCaloHit));
766 }
767 else
768 {
769 PandoraContentApi::Cluster::Parameters parameters;
770 parameters.m_caloHitList.push_back(pCaloHit);
771 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*this, parameters, pClosestCluster));
772 createdClusters.push_back(pClosestCluster);
773 }
774 }
775 }
776
777 // End fragmentation
778 if (createdClusters.empty())
779 {
780 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*this, originalListName, fragmentListName));
781 fragmentedClusterList.push_back(pRemnantCluster);
782 }
783 else
784 {
785 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*this, fragmentListName, originalListName));
786 fragmentedClusterList.insert(fragmentedClusterList.begin(), createdClusters.begin(), createdClusters.end());
787 }
788}
789
790//------------------------------------------------------------------------------------------------------------------------------------------
791
792template <typename T>
793void TrackRefinementBaseAlgorithm::UpdateContainers(const ClusterList &clustersToAdd, const ClusterList &clustersToDelete,
794 const T sortFunction, ClusterVector &clusterVector, SlidingFitResultMapPair &slidingFitResultMapPair) const
795{
796 //ATTN: Very important to first delete pointers from containers
797 for (const Cluster *const pClusterToDelete : clustersToDelete)
798 this->RemoveClusterFromContainers(pClusterToDelete, clusterVector, slidingFitResultMapPair);
799
800 this->InitialiseContainers(&clustersToAdd, sortFunction, clusterVector, slidingFitResultMapPair);
801}
802
803//------------------------------------------------------------------------------------------------------------------------------------------
804
806 const Cluster *const pClusterToRemove, ClusterVector &clusterVector, SlidingFitResultMapPair &slidingFitResultMapPair) const
807{
808 const TwoDSlidingFitResultMap::const_iterator microFitToDelete(slidingFitResultMapPair.first->find(pClusterToRemove));
809 if (microFitToDelete != slidingFitResultMapPair.first->end())
810 slidingFitResultMapPair.first->erase(microFitToDelete);
811
812 const TwoDSlidingFitResultMap::const_iterator macroFitToDelete(slidingFitResultMapPair.second->find(pClusterToRemove));
813 if (macroFitToDelete != slidingFitResultMapPair.second->end())
814 slidingFitResultMapPair.second->erase(macroFitToDelete);
815
816 const ClusterVector::const_iterator clusterToDelete(std::find(clusterVector.begin(), clusterVector.end(), pClusterToRemove));
817 if (clusterToDelete != clusterVector.end())
818 clusterVector.erase(clusterToDelete);
819}
820
821//------------------------------------------------------------------------------------------------------------------------------------------
822
824{
826 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinClusterLength", m_minClusterLength));
827
829 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MicroSlidingFitWindow", m_microSlidingFitWindow));
830
832 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MacroSlidingFitWindow", m_macroSlidingFitWindow));
833
834 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
835 XmlHelper::ReadValue(xmlHandle, "StableRegionClusterFraction", m_stableRegionClusterFraction));
836
837 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
838 XmlHelper::ReadValue(xmlHandle, "MergePointMinCosAngleDeviation", m_mergePointMinCosAngleDeviation));
839
840 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
841 XmlHelper::ReadValue(xmlHandle, "MinHitFractionForHitRemoval", m_minHitFractionForHitRemoval));
842
843 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
844 XmlHelper::ReadValue(xmlHandle, "MaxDistanceFromMainTrack", m_maxDistanceFromMainTrack));
845
846 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
847 XmlHelper::ReadValue(xmlHandle, "MaxHitDistanceFromCluster", m_maxHitDistanceFromCluster));
848
849 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
850 XmlHelper::ReadValue(xmlHandle, "MaxHitSeparationForConnectedCluster", m_maxHitSeparationForConnectedCluster));
851
852 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxTrackGaps", m_maxTrackGaps));
853
855 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "LineSegmentLength", m_lineSegmentLength));
856
857 if (m_lineSegmentLength < std::numeric_limits<float>::epsilon())
858 {
859 std::cout << "TrackInEMShowerAlgorithm: Line segment length must be positive and nonzero" << std::endl;
860 throw STATUS_CODE_INVALID_PARAMETER;
861 }
862
863 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "HitWidthMode", m_hitWidthMode));
864
865 return STATUS_CODE_SUCCESS;
866}
867
868//------------------------------------------------------------------------------------------------------------------------------------------
869//------------------------------------------------------------------------------------------------------------------------------------------
870
872{
873 const CartesianVector lhsHitPosition(
875
876 const CartesianVector rhsHitPosition(
878
879 const float lhsLongitudinal = m_lineDirection.GetDotProduct(lhsHitPosition - m_startPoint);
880 const float rhsLongitudinal = m_lineDirection.GetDotProduct(rhsHitPosition - m_startPoint);
881
882 if (std::fabs(lhsLongitudinal - rhsLongitudinal) > std::numeric_limits<float>::epsilon())
883 {
884 // ATTN: Order from closest to furthest away
885 return (lhsLongitudinal < rhsLongitudinal);
886 }
887
888 // ATTN: To deal with tiebreaks
890}
891
892//------------------------------------------------------------------------------------------------------------------------------------------
893
894typedef bool (*SortFunction)(const Cluster *, const Cluster *);
895
896template void TrackRefinementBaseAlgorithm::UpdateContainers<SortFunction>(
897 const ClusterList &, const ClusterList &, const SortFunction, ClusterVector &, SlidingFitResultMapPair &) const;
898template void TrackRefinementBaseAlgorithm::InitialiseContainers<SortFunction>(
900
901} // namespace lar_content
Grouping of header files for many classes of use in particle flow algorithms.
Header file for the cluster helper class.
Header file for the geometry helper class.
Header file for the lar hit width helper class.
#define PANDORA_THROW_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:43
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
Definition StatusCodes.h:31
Header file for the track refinement base class.
static pandora::StatusCode InitializeFragmentation(const pandora::Algorithm &algorithm, const pandora::ClusterList &inputClusterList, std::string &originalClustersListName, std::string &fragmentClustersListName)
Initialize cluster fragmentation operations on clusters in the algorithm input list....
static pandora::StatusCode EndFragmentation(const pandora::Algorithm &algorithm, const std::string &clusterListToSaveName, const std::string &clusterListToDeleteName)
End cluster fragmentation operations on clusters in the algorithm input list.
static pandora::StatusCode MergeAndDeleteClusters(const pandora::Algorithm &algorithm, const pandora::Cluster *const pClusterToEnlarge, const pandora::Cluster *const pClusterToDelete)
Merge two clusters in the current list, enlarging one cluster and deleting the second.
static pandora::StatusCode AddToCluster(const pandora::Algorithm &algorithm, const pandora::Cluster *const pCluster, const T *const pT)
Add a calo hit, or a list of calo hits, to a cluster.
static pandora::StatusCode RemoveFromCluster(const pandora::Algorithm &algorithm, const pandora::Cluster *const pCluster, const pandora::CaloHit *const pCaloHit)
Remove a calo hit from a cluster. Note this function will not remove the final calo hit from a cluste...
ClusterAssociation class.
const pandora::CartesianVector GetConnectingLineDirection() const
Returns the unit vector of the line connecting the upstream and downstream merge points (upstream -> ...
const pandora::CartesianVector GetUpstreamMergePoint() const
Returns the upstream cluster merge point.
const pandora::CartesianVector GetDownstreamMergePoint() const
Returns the downstream cluster merge point.
static bool SortHitsByPulseHeight(const pandora::CaloHit *const pLhs, const pandora::CaloHit *const pRhs)
Sort calo hits by their pulse height.
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
static pandora::CartesianVector GetClosestPointToLine2D(const pandora::CartesianVector &lineStart, const pandora::CartesianVector &lineDirection, const pandora::CaloHit *const pCaloHit)
Consider the hit width to find the closest position of a calo hit to a specified line.
static float GetClosestDistanceToPoint2D(const pandora::CaloHit *const pCaloHit, const pandora::CartesianVector &point2D)
Consider the hit width to find the smallest distance between a calo hit and a given point.
bool operator()(const pandora::CaloHit *const pLhs, const pandora::CaloHit *const pRhs) const
Sort hits by their projected distance along a line from a start point.
bool IsInBoundingBox(const float minX, const float maxX, const float minZ, const float maxZ, const pandora::CartesianVector &hitPosition) const
check whether a hit is contained within a defined square region
bool GetClusterMergingCoordinates(const TwoDSlidingFitResult &clusterMicroFitResult, const TwoDSlidingFitResult &clusterMacroFitResult, const TwoDSlidingFitResult &associatedMacroFitResult, const bool isEndUpstream, pandora::CartesianVector &clusterMergePosition, pandora::CartesianVector &clusterMergeDirection) const
Get the merging coordinate and direction for an input cluster with respect to an associated cluster.
bool IsClusterRemnantDisconnected(const pandora::Cluster *const pRemnantCluster) const
Whether a remnant cluster is considered to be disconnected and therefore should undergo further fragm...
float m_maxHitSeparationForConnectedCluster
The maximum separation between two adjacent (in z) hits in a connected cluster.
std::pair< TwoDSlidingFitResultMap *, TwoDSlidingFitResultMap * > SlidingFitResultMapPair
void AddHitsToMainTrack(const pandora::Cluster *const pMainTrackCluster, const pandora::Cluster *const pShowerTrackCluster, const pandora::CaloHitList &caloHitsToMerge, const ClusterAssociation &clusterAssociation, pandora::ClusterList &remnantClusterList) const
Remove the hits from a shower cluster that belong to the main track and add them into the main track ...
std::unordered_map< const pandora::Cluster *, pandora::CaloHitList > ClusterToCaloHitListMap
const pandora::Cluster * RemoveOffAxisHitsFromTrack(const pandora::Cluster *const pCluster, const pandora::CartesianVector &splitPosition, const bool isEndUpstream, const ClusterToCaloHitListMap &clusterToCaloHitListMap, pandora::ClusterList &remnantClusterList, TwoDSlidingFitResultMap &microSlidingFitResultMap, TwoDSlidingFitResultMap &macroSlidingFitResultMap) const
Remove any hits in the upstream/downstream cluster that lie off of the main track axis (i....
float m_maxHitDistanceFromCluster
The threshold separation between a hit and cluster for the hit to be merged into the cluster.
unsigned int m_maxTrackGaps
The maximum number of graps allowed in the extrapolated hit vector.
bool IsNearBoundary(const pandora::CaloHit *const pCaloHit, const pandora::CartesianVector &boundaryPosition2D, const float boundaryTolerance) const
Check whether a hit is close to a boundary point.
bool IsTrackContinuous(const ClusterAssociation &clusterAssociation, const pandora::CaloHitVector &extrapolatedCaloHitVector) const
Check whether the extrapolatedCaloHitVector contains a continuous line of hits between the cluster me...
unsigned int m_microSlidingFitWindow
The sliding fit window used in the fits contained within the microSlidingFitResultMap.
float m_stableRegionClusterFraction
The threshold fraction of fit contributing layers which defines the stable region.
void GetHitsInBoundingBox(const pandora::CartesianVector &firstCorner, const pandora::CartesianVector &secondCorner, const pandora::ClusterList *const pClusterList, ClusterToCaloHitListMap &clusterToCaloHitListMap, const pandora::ClusterList &unavailableProtectedClusters=pandora::ClusterList(), const float distanceToLine=-1.f) const
Find the unprotected hits that are contained within a defined box with the option to apply a cut on t...
void RepositionIfInGap(const pandora::CartesianVector &mergeDirection, pandora::CartesianVector &trackPoint) const
Move an input position to the higher line gap edge if it lies within a gap.
float m_mergePointMinCosAngleDeviation
The threshold cos opening angle between the cluster local gradient and the associated cluster global ...
bool IsInLineSegment(const pandora::CartesianVector &lowerBoundary, const pandora::CartesianVector &upperBoundary, const pandora::CartesianVector &point) const
Whether a position falls within a specified segment of the cluster connecting line.
void RemoveClusterFromContainers(const pandora::Cluster *const pClustertoRemove, pandora::ClusterVector &clusterVector, SlidingFitResultMapPair &slidingFitResultMapPair) const
Remove a cluster from the cluster vector and sliding fit maps.
bool AddToNearestCluster(const pandora::Cluster *const pClusterToMerge, const pandora::Cluster *const pMainTrackCluster, const pandora::ClusterList *const pClusterList) const
Add a cluster to the nearest cluster satisfying separation distance thresholds.
void FragmentRemnantCluster(const pandora::Cluster *const pRemnantCluster, pandora::ClusterList &fragmentedClusterList) const
Fragment a cluster using simple hit separation logic.
bool IsCloseToLine(const pandora::CartesianVector &hitPosition, const pandora::CartesianVector &lineStart, const pandora::CartesianVector &lineDirection, const float distanceToLine) const
Check whether a hit is close to a line.
unsigned int m_macroSlidingFitWindow
The sliding fit window used in the fits contained within the macroSlidingFitResultMap.
void UpdateContainers(const pandora::ClusterList &clustersToAdd, const pandora::ClusterList &clustersToDelete, const T sortFunction, pandora::ClusterVector &clusterVector, SlidingFitResultMapPair &slidingFitResultMapPair) const
Remove deleted clusters from the cluster vector and sliding fit maps and add in created clusters that...
float m_maxDistanceFromMainTrack
The threshold distance for a hit to be added to the main track.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)=0
Read the algorithm settings.
void InitialiseContainers(const pandora::ClusterList *pClusterList, const T sortFunction, pandora::ClusterVector &clusterVector, SlidingFitResultMapPair &slidingFitResultMapPair) const
Fill the cluster vector and sliding fit maps with clusters that are determined to be track-like.
float m_minHitFractionForHitRemoval
The threshold fraction of hits to be removed from the cluster for hit removal to proceed.
virtual bool AreExtrapolatedHitsNearBoundaries(const pandora::CaloHitVector &extrapolatedHitVector, ClusterAssociation &clusterAssociation) const =0
Check the separation of the extremal extrapolated hits with the expected endpoints or,...
bool m_hitWidthMode
Whether to consider the width of hits.
void ProcessRemnantClusters(const pandora::ClusterList &remnantClusterList, const pandora::Cluster *const pMainTrackCluster, const pandora::ClusterList *const pClusterList, pandora::ClusterList &createdClusters) const
Process the remnant clusters separating those that stradle the main track.
void GetTrackSegmentBoundaries(const ClusterAssociation &clusterAssociation, pandora::CartesianPointVector &trackSegmentBoundaries) const
Obtain the segment boundaries of the connecting line to test whether extrapolated hits are continuous...
float DistanceInGap(const pandora::CartesianVector &upstreamPoint, const pandora::CartesianVector &downstreamPoint, const pandora::CartesianVector &connectingLine, pandora::DetectorGapList &consideredGaps) const
Calculate the track length between two points that lies in gaps.
float m_minClusterLength
The minimum length of a considered cluster.
bool AreExtrapolatedHitsGood(const ClusterToCaloHitListMap &clusterToCaloHitListMap, ClusterAssociation &clusterAssociation) const
Perform topological checks on the collected hits to ensure no gaps are present.
void GetLocalPosition(const pandora::CartesianVector &position, float &rL, float &rT) const
Get local sliding fit coordinates for a given global position.
const LayerFitResultMap & GetLayerFitResultMap() const
Get the layer fit result map.
pandora::StatusCode GetGlobalFitPosition(const float rL, pandora::CartesianVector &position) const
Get global fit position for a given longitudinal coordinate.
int GetMaxLayer() const
Get the maximum occupied layer in the sliding fit.
int GetMinLayer() const
Get the minimum occupied layer in the sliding fit.
void GetGlobalDirection(const float dTdL, pandora::CartesianVector &direction) const
Get global direction coordinates for given sliding linear fit gradient.
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
CartesianVector class.
float GetCosOpeningAngle(const CartesianVector &rhs) const
Get the cosine of the opening angle of the cartesian vector with respect to a second cartesian vector...
float GetX() const
Get the cartesian x coordinate.
CartesianVector GetUnitVector() const
Get a unit vector in the direction of the cartesian vector.
float GetZ() const
Get the cartesian z coordinate.
float GetDotProduct(const CartesianVector &rhs) const
Get the dot product of the cartesian vector with a second cartesian vector.
float GetMagnitude() const
Get the magnitude.
CartesianVector GetCrossProduct(const CartesianVector &rhs) const
Get the cross product of the cartesian vector with a second cartesian vector.
Cluster class.
Definition Cluster.h:31
unsigned int GetNCaloHits() const
Get the number of calo hits in the cluster.
Definition Cluster.h:484
const OrderedCaloHitList & GetOrderedCaloHitList() const
Get the ordered calo hit list.
Definition Cluster.h:470
DetectorGap class.
Definition DetectorGap.h:25
LineGap class, associated only with 2D TPC hit types and applied only to the z coordinate when sampli...
Definition DetectorGap.h:50
float GetLineEndZ() const
Get the line end z coordinate.
LineGapType GetLineGapType() const
Get the line gap type.
float GetLineStartX() const
Get the line start x coordinate.
float GetLineStartZ() const
Get the line start z coordinate.
float GetLineEndX() const
Get the line end x coordinate.
Calo hit lists arranged by pseudo layer.
const_iterator begin() const
Returns a const iterator referring to the first element in the ordered calo hit list.
const Pandora & GetPandora() const
Get the associated pandora instance.
Definition Process.h:116
StatusCodeException class.
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
Definition XmlHelper.h:136
std::unordered_map< const pandora::Cluster *, TwoDSlidingFitResult > TwoDSlidingFitResultMap
std::map< int, LayerFitResult > LayerFitResultMap
bool(* SortFunction)(const Cluster *, const Cluster *)
std::vector< const CaloHit * > CaloHitVector
std::vector< const Cluster * > ClusterVector
MANAGED_CONTAINER< const Cluster * > ClusterList
std::vector< CartesianVector > CartesianPointVector
MANAGED_CONTAINER< const DetectorGap * > DetectorGapList
MANAGED_CONTAINER< const CaloHit * > CaloHitList
StatusCode
The StatusCode enum.
LineGapType
Line gap type.