9 #include "Pandora/AlgorithmHeaders.h"
34 m_pseudoChi2Cut(1.5f),
35 m_xOverlapWindow(1.f),
36 m_minMatchedFraction(0.5),
37 m_minMatchedPoints(3),
38 m_minProjectedPositions(3),
39 m_maxCosmicRayHitFraction(0.05f),
40 m_maxDistanceToCluster(0.5f),
41 m_maxDistanceToReferencePoint(5.f),
42 m_strayClusterSeparation(2.f)
51 for (
const Cluster *
const pCluster : *pInputClusterList)
53 if ((pCluster->IsAvailable()) && (this->DoesClusterPassTensorThreshold(pCluster)))
54 selectedClusterList.push_back(pCluster);
63 if (preparedClusterList.empty())
66 const PfoList *pMuonPfoList(
nullptr);
68 PANDORA_THROW_RESULT_IF_AND_IF(
69 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*
this, m_muonPfoListName, pMuonPfoList));
71 if ((!pMuonPfoList) || pMuonPfoList->empty())
76 m_deltaRayMatchingContainers.FillContainers(*pMuonPfoList, this->GetInputClusterList(hitType));
86 const ClusterList &inputClusterList(this->GetInputClusterList(hitType));
87 ClusterList &strayClusterList((hitType == TPC_VIEW_U) ? m_strayClusterListU : (hitType == TPC_VIEW_V) ? m_strayClusterListV : m_strayClusterListW);
89 for (
const Cluster *
const pCluster : inputClusterList)
91 if ((pCluster->IsAvailable()) && (!this->DoesClusterPassTensorThreshold(pCluster)))
92 strayClusterList.push_back(pCluster);
101 if (commonMuonPfoList.size() != 1)
102 return STATUS_CODE_NOT_FOUND;
104 ClusterList muonClusterList;
107 if (muonClusterList.size() != 1)
108 return STATUS_CODE_NOT_FOUND;
110 pMuonCluster = muonClusterList.front();
112 return STATUS_CODE_SUCCESS;
117 template <
typename T>
124 consideredClusters.push_back(pCluster);
126 const DeltaRayMatchingContainers::ClusterProximityMap::const_iterator clusterProximityIter(clusterProximityMap.find(pCluster));
128 if (clusterProximityIter == clusterProximityMap.end())
131 for (
const Cluster *
const pNearbyCluster : clusterProximityIter->second)
133 if (std::find(consideredClusters.begin(), consideredClusters.end(), pNearbyCluster) != consideredClusters.end())
136 const DeltaRayMatchingContainers::ClusterToPfoMap::const_iterator pfoIter(clusterToPfoMap.find(pNearbyCluster));
138 if (pfoIter != clusterToPfoMap.end())
140 if (std::find(nearbyMuonPfos.begin(), nearbyMuonPfos.end(), pfoIter->second) == nearbyMuonPfos.end())
141 nearbyMuonPfos.push_back(pfoIter->second);
146 this->GetNearbyMuonPfos(pNearbyCluster, consideredClusters, nearbyMuonPfos);
152 template <
typename T>
154 const Cluster *
const pCluster1,
const Cluster *
const pCluster2,
const Cluster *
const pCluster3,
float &reducedChiSquared)
const
156 float chiSquaredSum(0.f);
157 unsigned int nSamplingPoints(0), nMatchedSamplingPoints(0);
158 XOverlap xThreeViewOverlapObject(0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
160 if (this->PerformThreeViewMatching(pCluster1, pCluster2, pCluster3, chiSquaredSum, nSamplingPoints, nMatchedSamplingPoints,
161 xThreeViewOverlapObject) == STATUS_CODE_NOT_FOUND)
162 return STATUS_CODE_NOT_FOUND;
164 if (nSamplingPoints == 0)
165 return STATUS_CODE_NOT_FOUND;
167 reducedChiSquared = chiSquaredSum / nSamplingPoints;
169 return STATUS_CODE_SUCCESS;
174 template <
typename T>
176 const Cluster *
const pClusterW,
float &chiSquaredSum,
unsigned int &nSamplingPoints,
unsigned int &nMatchedSamplingPoints, XOverlap &xOverlapObject)
const
178 float xMinU(-std::numeric_limits<float>::max()), xMaxU(+std::numeric_limits<float>::max());
179 float xMinV(-std::numeric_limits<float>::max()), xMaxV(+std::numeric_limits<float>::max());
180 float xMinW(-std::numeric_limits<float>::max()), xMaxW(+std::numeric_limits<float>::max());
182 pClusterU->GetClusterSpanX(xMinU, xMaxU);
183 pClusterV->GetClusterSpanX(xMinV, xMaxV);
184 pClusterW->GetClusterSpanX(xMinW, xMaxW);
187 const float xMinCentre(std::max(xMinU, std::max(xMinV, xMinW)));
188 const float xMaxCentre(std::min(xMaxU, std::min(xMaxV, xMaxW)));
189 const float xCentreOverlap(xMaxCentre - xMinCentre);
191 if (xCentreOverlap < std::numeric_limits<float>::epsilon())
192 return STATUS_CODE_NOT_FOUND;
194 const float xPitch(0.5 * m_xOverlapWindow);
195 const float xMin(std::max(xMinU, std::max(xMinV, xMinW)) - xPitch);
196 const float xMax(std::min(xMaxU, std::min(xMaxV, xMaxW)) + xPitch);
197 const float xOverlap(xMax - xMin);
203 if (hitTypeU == hitTypeV || hitTypeU == hitTypeW || hitTypeV == hitTypeW)
204 return STATUS_CODE_FAILURE;
206 const unsigned int nPoints(1 + static_cast<unsigned int>(xOverlap / xPitch));
210 nMatchedSamplingPoints = 0;
212 for (
unsigned int n = 0;
n < nPoints; ++
n)
214 const float x(xMin + (xMax - xMin) * (static_cast<float>(
n) + 0.5f) / static_cast<float>(nPoints));
215 const float xmin(
x - xPitch);
216 const float xmax(
x + xPitch);
220 float zMinU(0.f), zMinV(0.f), zMinW(0.f), zMaxU(0.f), zMaxV(0.f), zMaxW(0.f);
221 pClusterU->GetClusterSpanZ(
xmin, xmax, zMinU, zMaxU);
222 pClusterV->GetClusterSpanZ(
xmin, xmax, zMinV, zMaxV);
223 pClusterW->GetClusterSpanZ(
xmin, xmax, zMinW, zMaxW);
225 const float zU(0.5f * (zMinU + zMaxU));
226 const float zV(0.5f * (zMinV + zMaxV));
227 const float zW(0.5f * (zMinW + zMaxW));
229 const float dzU(zMaxU - zMinU);
230 const float dzV(zMaxV - zMinV);
231 const float dzW(zMaxW - zMinW);
240 const float deltaSquared(((zU - zprojU) * (zU - zprojU) + (zV - zprojV) * (zV - zprojV) + (zW - zprojW) * (zW - zprojW)) / 3.f);
241 const float sigmaSquared(dzU * dzU + dzV * dzV + dzW * dzW + dzPitch * dzPitch);
242 const float pseudoChi2(deltaSquared / sigmaSquared);
244 chiSquaredSum += pseudoChi2;
246 if (pseudoChi2 < m_pseudoChi2Cut)
247 ++nMatchedSamplingPoints;
249 catch (StatusCodeException &statusCodeException)
251 if (statusCodeException.GetStatusCode() != STATUS_CODE_NOT_FOUND)
252 return statusCodeException.GetStatusCode();
259 if (nSamplingPoints == 0)
260 return STATUS_CODE_NOT_FOUND;
262 const float matchedFraction(static_cast<float>(nMatchedSamplingPoints) / static_cast<float>(nSamplingPoints));
264 if ((matchedFraction < m_minMatchedFraction) || (nMatchedSamplingPoints < m_minMatchedPoints))
265 return STATUS_CODE_NOT_FOUND;
267 xOverlapObject = XOverlap(xMinU, xMaxU, xMinV, xMaxV, xMinW, xMaxW, xCentreOverlap);
269 return STATUS_CODE_SUCCESS;
274 template <
typename T>
276 const CaloHitList &pCluster1,
const CaloHitList &pCluster2,
const CaloHitList &pCluster3,
float &reducedChiSquared)
const
278 float chiSquaredSum(0.f);
279 unsigned int nSamplingPoints(0), nMatchedSamplingPoints(0);
280 XOverlap xThreeViewOverlapObject(0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
282 if (this->PerformThreeViewMatching(pCluster1, pCluster2, pCluster3, chiSquaredSum, nSamplingPoints, nMatchedSamplingPoints,
283 xThreeViewOverlapObject) == STATUS_CODE_NOT_FOUND)
284 return STATUS_CODE_NOT_FOUND;
286 if (nSamplingPoints == 0)
287 return STATUS_CODE_NOT_FOUND;
289 reducedChiSquared = chiSquaredSum / nSamplingPoints;
291 return STATUS_CODE_SUCCESS;
296 template <
typename T>
298 const CaloHitList &clusterW,
float &chiSquaredSum,
unsigned int &nSamplingPoints,
unsigned int &nMatchedSamplingPoints, XOverlap &xOverlapObject)
const
300 float xMinU(-std::numeric_limits<float>::max()), xMaxU(+std::numeric_limits<float>::max());
301 float xMinV(-std::numeric_limits<float>::max()), xMaxV(+std::numeric_limits<float>::max());
302 float xMinW(-std::numeric_limits<float>::max()), xMaxW(+std::numeric_limits<float>::max());
304 this->GetClusterSpanX(clusterU, xMinU, xMaxU);
305 this->GetClusterSpanX(clusterV, xMinV, xMaxV);
306 this->GetClusterSpanX(clusterW, xMinW, xMaxW);
309 const float xMinCentre(std::max(xMinU, std::max(xMinV, xMinW)));
310 const float xMaxCentre(std::min(xMaxU, std::min(xMaxV, xMaxW)));
311 const float xCentreOverlap(xMaxCentre - xMinCentre);
313 if (xCentreOverlap < std::numeric_limits<float>::epsilon())
314 return STATUS_CODE_NOT_FOUND;
316 const float xPitch(0.5 * m_xOverlapWindow);
317 const float xMin(std::max(xMinU, std::max(xMinV, xMinW)) - xPitch);
318 const float xMax(std::min(xMaxU, std::min(xMaxV, xMaxW)) + xPitch);
319 const float xOverlap(xMax - xMin);
321 const HitType hitTypeU(clusterU.front()->GetHitType());
322 const HitType hitTypeV(clusterV.front()->GetHitType());
323 const HitType hitTypeW(clusterW.front()->GetHitType());
325 if (hitTypeU == hitTypeV || hitTypeU == hitTypeW || hitTypeV == hitTypeW)
326 return STATUS_CODE_FAILURE;
328 const unsigned int nPoints(1 + static_cast<unsigned int>(xOverlap / xPitch));
332 nMatchedSamplingPoints = 0;
334 for (
unsigned int n = 0;
n < nPoints; ++
n)
336 const float x(xMin + (xMax - xMin) * (static_cast<float>(
n) + 0.5f) / static_cast<float>(nPoints));
337 const float xmin(
x - xPitch);
338 const float xmax(
x + xPitch);
342 float zMinU(0.f), zMinV(0.f), zMinW(0.f), zMaxU(0.f), zMaxV(0.f), zMaxW(0.f);
343 this->GetClusterSpanZ(clusterU,
xmin, xmax, zMinU, zMaxU);
344 this->GetClusterSpanZ(clusterV,
xmin, xmax, zMinV, zMaxV);
345 this->GetClusterSpanZ(clusterW,
xmin, xmax, zMinW, zMaxW);
347 const float zU(0.5f * (zMinU + zMaxU));
348 const float zV(0.5f * (zMinV + zMaxV));
349 const float zW(0.5f * (zMinW + zMaxW));
351 const float dzU(zMaxU - zMinU);
352 const float dzV(zMaxV - zMinV);
353 const float dzW(zMaxW - zMinW);
362 const float deltaSquared(((zU - zprojU) * (zU - zprojU) + (zV - zprojV) * (zV - zprojV) + (zW - zprojW) * (zW - zprojW)) / 3.f);
363 const float sigmaSquared(dzU * dzU + dzV * dzV + dzW * dzW + dzPitch * dzPitch);
364 const float pseudoChi2(deltaSquared / sigmaSquared);
366 chiSquaredSum += pseudoChi2;
368 if (pseudoChi2 < m_pseudoChi2Cut)
369 ++nMatchedSamplingPoints;
371 catch (StatusCodeException &statusCodeException)
373 if (statusCodeException.GetStatusCode() != STATUS_CODE_NOT_FOUND)
374 return statusCodeException.GetStatusCode();
381 if (nSamplingPoints == 0)
382 return STATUS_CODE_NOT_FOUND;
384 const float matchedFraction(static_cast<float>(nMatchedSamplingPoints) / static_cast<float>(nSamplingPoints));
386 if ((matchedFraction < m_minMatchedFraction) || (nMatchedSamplingPoints < m_minMatchedPoints))
387 return STATUS_CODE_NOT_FOUND;
389 xOverlapObject = XOverlap(xMinU, xMaxU, xMinV, xMaxV, xMinW, xMaxW, xCentreOverlap);
391 return STATUS_CODE_SUCCESS;
396 template <
typename T>
399 xMin = std::numeric_limits<float>::max();
400 xMax = -std::numeric_limits<float>::max();
402 for (
const CaloHit *
const pCaloHit : caloHitList)
404 const float xCoordinate(pCaloHit->GetPositionVector().GetX());
406 if (xCoordinate < xMin)
409 if (xCoordinate > xMax)
416 template <
typename T>
418 const CaloHitList &caloHitList,
const float xMin,
const float xMax,
float &zMin,
float &zMax)
const
420 zMin = std::numeric_limits<float>::max();
421 zMax = -std::numeric_limits<float>::max();
424 for (
const CaloHit *
const pCaloHit : caloHitList)
426 const float xCoordinate(pCaloHit->GetPositionVector().GetX());
427 const float zCoordinate(pCaloHit->GetPositionVector().GetZ());
429 if ((xCoordinate < xMin) || (xCoordinate > xMax))
434 if (zCoordinate < zMin)
437 if (zCoordinate > zMax)
442 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
444 return STATUS_CODE_SUCCESS;
449 template <
typename T>
451 const HitType &thirdViewHitType,
const ParticleFlowObject *
const pParentMuon, CartesianPointVector &projectedPositions)
const
453 ClusterList muonClusterList1, muonClusterList2;
455 HitTypeVector hitTypes({TPC_VIEW_U, TPC_VIEW_V, TPC_VIEW_W});
457 hitTypes.erase(std::find(hitTypes.begin(), hitTypes.end(), thirdViewHitType));
462 if ((muonClusterList1.size() != 1) || (muonClusterList2.size() != 1))
463 return STATUS_CODE_NOT_FOUND;
465 return (this->GetProjectedPositions(muonClusterList1.front(), muonClusterList2.front(), projectedPositions));
470 template <
typename T>
472 const Cluster *
const pCluster1,
const Cluster *
const pCluster2, CartesianPointVector &projectedPositions)
const
474 float xMin1(0.f), xMax1(0.f), xMin2(0.f), xMax2(0.f);
475 pCluster1->GetClusterSpanX(xMin1, xMax1);
476 pCluster2->GetClusterSpanX(xMin2, xMax2);
478 const float xPitch(0.5 * m_xOverlapWindow);
479 const float xMin(std::max(xMin1, xMin2) - xPitch);
480 const float xMax(std::min(xMax1, xMax2) + xPitch);
481 const float xOverlap(xMax - xMin);
483 if (xOverlap < std::numeric_limits<float>::epsilon())
484 return STATUS_CODE_NOT_FOUND;
489 if (hitType1 == hitType2)
490 throw StatusCodeException(STATUS_CODE_FAILURE);
492 const unsigned int nPoints(1 + static_cast<unsigned int>(xOverlap / xPitch));
495 for (
unsigned int n = 0;
n < nPoints; ++
n)
497 const float x(xMin + (xMax - xMin) * (static_cast<float>(
n) + 0.5f) / static_cast<float>(nPoints));
498 const float xmin(x - xPitch);
499 const float xmax(x + xPitch);
503 float zMin1(0.f), zMin2(0.f), zMax1(0.f), zMax2(0.f);
504 pCluster1->GetClusterSpanZ(xmin, xmax, zMin1, zMax1);
505 pCluster2->GetClusterSpanZ(xmin, xmax, zMin2, zMax2);
507 const float z1(0.5f * (zMin1 + zMax1));
508 const float z2(0.5f * (zMin2 + zMax2));
511 CartesianVector projection(0.f, 0.f, 0.f);
513 this->GetPandora(), hitType1, hitType2, CartesianVector(x, 0.f, z1), CartesianVector(x, 0.f, z2), projection, chi2);
515 projectedPositions.push_back(projection);
517 catch (StatusCodeException &statusCodeException)
519 if (statusCodeException.GetStatusCode() != STATUS_CODE_NOT_FOUND)
520 throw statusCodeException.GetStatusCode();
527 if (projectedPositions.size() < m_minProjectedPositions)
528 return STATUS_CODE_NOT_FOUND;
530 return STATUS_CODE_SUCCESS;
535 template <
typename T>
537 const Cluster *
const pThirdViewCluster,
const ParticleFlowObject *
const pParentMuon,
const float minDistanceFromMuon,
538 const float maxDistanceToCollected, CaloHitList &collectedHits)
const
540 HitType thirdViewHitType(TPC_VIEW_U);
541 CartesianPointVector deltaRayProjectedPositions;
543 if (!pThirdViewCluster)
545 if (this->GetProjectedPositions(pCluster1, pCluster2, deltaRayProjectedPositions) != STATUS_CODE_SUCCESS)
546 return STATUS_CODE_NOT_FOUND;
548 for (
const HitType hitType : {TPC_VIEW_U, TPC_VIEW_V, TPC_VIEW_W})
552 thirdViewHitType = hitType;
559 CaloHitList deltaRayCaloHitList;
560 pThirdViewCluster->GetOrderedCaloHitList().FillCaloHitList(deltaRayCaloHitList);
562 for (
const CaloHit *
const pCaloHit : deltaRayCaloHitList)
563 deltaRayProjectedPositions.push_back(pCaloHit->GetPositionVector());
568 ClusterList muonClusterList;
571 if (muonClusterList.size() != 1)
572 return STATUS_CODE_NOT_FOUND;
574 const Cluster *
const pMuonCluster(muonClusterList.front());
577 CartesianVector positionOnMuon(0.f, 0.f, 0.f), muonDirection(0.f, 0.f, 0.f);
578 if (this->ParameteriseMuon(pParentMuon, deltaRayProjectedPositions, thirdViewHitType, positionOnMuon, muonDirection) != STATUS_CODE_SUCCESS)
579 return STATUS_CODE_NOT_FOUND;
581 this->CollectHitsFromMuon(
582 positionOnMuon, muonDirection, pMuonCluster, deltaRayProjectedPositions, minDistanceFromMuon, maxDistanceToCollected, collectedHits);
584 if (collectedHits.empty())
585 return STATUS_CODE_NOT_FOUND;
588 if ((static_cast<float>(collectedHits.size()) / pMuonCluster->GetNCaloHits()) > m_maxCosmicRayHitFraction)
589 return STATUS_CODE_NOT_FOUND;
591 return STATUS_CODE_SUCCESS;
596 template <
typename T>
598 const Cluster *
const pMuonCluster,
const CartesianPointVector &deltaRayProjectedPositions,
const float &minDistanceFromMuon,
599 const float maxDistanceToCollected, CaloHitList &collectedHits)
const
601 CaloHitList cosmicRayHitList;
602 pMuonCluster->GetOrderedCaloHitList().FillCaloHitList(cosmicRayHitList);
604 bool hitsAdded(
true);
609 for (
const CaloHit *
const pCaloHit : cosmicRayHitList)
611 if (std::find(collectedHits.begin(), collectedHits.end(), pCaloHit) != collectedHits.end())
615 collectedHits.empty() ? std::numeric_limits<float>::max()
616 : LArClusterHelper::GetClosestDistance(pCaloHit->GetPositionVector(), collectedHits)));
617 const float distanceToMuonHits(muonDirection.GetCrossProduct(pCaloHit->GetPositionVector() - positionOnMuon).GetMagnitude());
619 if ((std::fabs(distanceToMuonHits - distanceToCollectedHits) < std::numeric_limits<float>::epsilon()) ||
620 (distanceToMuonHits < minDistanceFromMuon) || (distanceToCollectedHits > distanceToMuonHits) ||
621 (distanceToCollectedHits > maxDistanceToCollected))
626 collectedHits.push_back(pCaloHit);
634 template <
typename T>
636 const Cluster *
const pDeltaRayCluster, CartesianVector &positionOnMuon, CartesianVector &muonDirection)
const
638 CaloHitList deltaRayHitList;
639 pDeltaRayCluster->GetOrderedCaloHitList().FillCaloHitList(deltaRayHitList);
641 CartesianPointVector deltaRayProjectedPositions;
643 for (
const CaloHit *
const pCaloHit : deltaRayHitList)
644 deltaRayProjectedPositions.push_back(pCaloHit->GetPositionVector());
646 return this->ParameteriseMuon(
652 template <
typename T>
654 const CartesianPointVector &deltaRayProjectedPositions,
const HitType hitType, CartesianVector &positionOnMuon, CartesianVector &muonDirection)
const
656 ClusterList muonClusterList;
659 if (muonClusterList.size() != 1)
660 return STATUS_CODE_NOT_FOUND;
662 CartesianPointVector muonProjectedPositions;
663 if (this->ProjectMuonPositions(hitType, pParentMuon, muonProjectedPositions) != STATUS_CODE_SUCCESS)
664 return STATUS_CODE_NOT_FOUND;
666 const Cluster *
const pMuonCluster(muonClusterList.front());
668 const TwoDSlidingFitResult slidingFitResult(pMuonCluster, 40, slidingFitPitch);
670 CartesianVector deltaRayVertex(0.f, 0.f, 0.f), muonVertex(0.f, 0.f, 0.f);
674 muonVertex, muonProjectedPositions, pMuonCluster, m_maxDistanceToCluster, m_maxDistanceToReferencePoint, positionOnMuon));
676 if (status != STATUS_CODE_SUCCESS)
677 return STATUS_CODE_NOT_FOUND;
679 float rL(0.f), rT(0.f);
680 slidingFitResult.GetLocalPosition(positionOnMuon, rL, rT);
682 if (slidingFitResult.GetGlobalFitDirection(rL, muonDirection) != STATUS_CODE_SUCCESS)
683 return STATUS_CODE_NOT_FOUND;
685 return STATUS_CODE_SUCCESS;
690 template <
typename T>
692 const CaloHitList &collectedHits,
const Cluster *&pDeltaRayCluster)
const
694 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*
this, clusterListName));
696 CaloHitList muonCaloHitList;
697 pMuonCluster->GetOrderedCaloHitList().FillCaloHitList(muonCaloHitList);
699 for (
const CaloHit *
const pCaloHit : muonCaloHitList)
701 if (std::find(collectedHits.begin(), collectedHits.end(), pCaloHit) != collectedHits.end())
703 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromCluster(*
this, pMuonCluster, pCaloHit));
705 if (!pDeltaRayCluster)
707 const ClusterList *pTemporaryList(
nullptr);
708 std::string temporaryListName, currentListName;
709 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentListName<Cluster>(*
this, currentListName));
710 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
711 PandoraContentApi::CreateTemporaryListAndSetCurrent<ClusterList>(*
this, pTemporaryList, temporaryListName));
714 parameters.m_caloHitList.push_back(pCaloHit);
716 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*
this, parameters, pDeltaRayCluster));
717 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Cluster>(*
this, temporaryListName, currentListName));
718 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*
this, currentListName));
722 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*
this, pDeltaRayCluster, pCaloHit));
730 template <
typename T>
734 unsigned int aHitTotal(0);
736 aHitTotal += pCluster->GetNCaloHits();
738 unsigned int bHitTotal(0);
739 for (
const Cluster *
const pCluster : b.m_clusterList)
740 bHitTotal += pCluster->GetNCaloHits();
742 return (aHitTotal > bHitTotal);
747 float longestSpan(-std::numeric_limits<float>::max()), spanMinX(0.f), spanMaxX(0.f);
749 for (
const Cluster *
const pCluster : protoParticle.m_clusterList)
751 float minX(0.f), maxX(0.f);
752 pCluster->GetClusterSpanX(minX, maxX);
754 const float span(maxX - minX);
756 if (span > longestSpan)
764 for (
const Cluster *
const pCluster : protoParticle.m_clusterList)
766 ClusterList collectedClusters;
767 this->CollectStrayClusters(pCluster, spanMinX, spanMaxX, collectedClusters);
769 if (!collectedClusters.empty())
770 this->AddInStrayClusters(pCluster, collectedClusters);
774 return (this->CreateThreeDParticles(protoParticleVector));
779 template <
typename T>
781 const Cluster *
const pClusterToEnlarge,
const float rangeMinX,
const float rangeMaxX, ClusterList &collectedClusters)
784 const ClusterList &strayClusterList((hitType == TPC_VIEW_U) ? m_strayClusterListU : (hitType == TPC_VIEW_V) ? m_strayClusterListV : m_strayClusterListW);
786 const DeltaRayMatchingContainers::ClusterProximityMap::const_iterator clusterProximityIter(clusterProximityMap.find(pClusterToEnlarge));
788 if (clusterProximityIter == clusterProximityMap.end())
791 for (
const Cluster *
const pNearbyCluster : clusterProximityIter->second)
793 if (std::find(strayClusterList.begin(), strayClusterList.end(), pNearbyCluster) == strayClusterList.end())
796 float xMin(-std::numeric_limits<float>::max()), xMax(+std::numeric_limits<float>::max());
797 pNearbyCluster->GetClusterSpanX(xMin, xMax);
799 if (!(((xMin > rangeMinX) && (xMin < rangeMaxX)) || ((xMax > rangeMinX) && (xMax < rangeMaxX))))
805 if (std::find(collectedClusters.begin(), collectedClusters.end(), pNearbyCluster) == collectedClusters.end())
806 collectedClusters.push_back(pNearbyCluster);
812 template <
typename T>
815 this->UpdateUponDeletion(pClusterToEnlarge);
817 for (
const Cluster *
const pCollectedCluster : collectedClusters)
819 this->UpdateUponDeletion(pCollectedCluster);
822 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
823 PandoraContentApi::MergeAndDeleteClusters(*
this, pClusterToEnlarge, pCollectedCluster, clusterListName, clusterListName));
826 m_deltaRayMatchingContainers.AddClustersToContainers({pClusterToEnlarge}, {
nullptr});
831 template <
typename T>
835 ClusterList &strayClusterList((hitType == TPC_VIEW_U) ? m_strayClusterListU : (hitType == TPC_VIEW_V) ? m_strayClusterListV : m_strayClusterListW);
836 const ClusterList::const_iterator strayClusterIter(std::find(strayClusterList.begin(), strayClusterList.end(), pDeletedCluster));
838 if (strayClusterIter != strayClusterList.end())
839 strayClusterList.erase(strayClusterIter);
842 const bool isMuonCluster(clusterToPfoMap.find(pDeletedCluster) != clusterToPfoMap.end());
844 m_deltaRayMatchingContainers.RemoveClusterFromContainers(pDeletedCluster);
852 template <
typename T>
855 m_deltaRayMatchingContainers.AddClustersToContainers(newClusterVector, pfoVector);
857 for (
unsigned int i = 0; i < newClusterVector.size(); i++)
859 const Cluster *
const pNewCluster(newClusterVector.at(i));
860 const ParticleFlowObject *
const pMuonPfo(pfoVector.at(i));
870 template <
typename T>
873 m_deltaRayMatchingContainers.ClearContainers();
875 m_strayClusterListU.clear();
876 m_strayClusterListV.clear();
877 m_strayClusterListW.clear();
884 template <
typename T>
887 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"MuonPfoListName", m_muonPfoListName));
889 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
890 XmlHelper::ReadValue(xmlHandle,
"SearchRegion1D", m_deltaRayMatchingContainers.m_searchRegion1D));
892 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"PseudoChi2Cut", m_pseudoChi2Cut));
894 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"OverlapWindow", m_xOverlapWindow));
896 PANDORA_RETURN_RESULT_IF_AND_IF(
897 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinMatchedFraction", m_minMatchedFraction));
899 PANDORA_RETURN_RESULT_IF_AND_IF(
900 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinMatchedPoints", m_minMatchedPoints));
902 PANDORA_RETURN_RESULT_IF_AND_IF(
903 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinProjectedPositions", m_minProjectedPositions));
905 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
906 XmlHelper::ReadValue(xmlHandle,
"MaxCosmicRayHitFraction", m_maxCosmicRayHitFraction));
908 PANDORA_RETURN_RESULT_IF_AND_IF(
909 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxDistanceToCluster", m_maxDistanceToCluster));
911 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
912 XmlHelper::ReadValue(xmlHandle,
"MaxDistanceToReferencePoint", m_maxDistanceToReferencePoint));
914 PANDORA_RETURN_RESULT_IF_AND_IF(
915 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"StrayClusterSeparation", m_strayClusterSeparation));
std::vector< pandora::HitType > HitTypeVector
void SelectInputClusters(const pandora::ClusterList *const pInputClusterList, pandora::ClusterList &selectedClusterList) const
Select a subset of input clusters for processing in this algorithm.
std::vector< ProtoParticle > ProtoParticleVector
static float GetClosestDistance(const pandora::Cluster *const pCluster, const pandora::CartesianPointVector &cartesianPointVector)
Get closest distance between a specified cluster and list of positions.
Header file for the kd tree linker algo template class.
std::map< const pandora::Cluster *, const pandora::ParticleFlowObject * > ClusterToPfoMap
Header file for the pfo helper class.
pandora::StatusCode GetProjectedPositions(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, pandora::CartesianPointVector &projectedPositions) const
Use two clusters from different views to calculate projected positions in the remaining third view...
pandora::StatusCode GetClusterSpanZ(const pandora::CaloHitList &caloHitList, const float xMin, const float xMax, float &zMin, float &zMax) const
Calculate the zSpan of a list of CaloHits in a specified x range.
static void GetClusters(const pandora::PfoList &pfoList, const pandora::HitType &hitType, pandora::ClusterList &clusterList)
Get a list of clusters of a particular hit type from a list of pfos.
process_name opflash particleana ie x
pandora::StatusCode CollectHitsFromMuon(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const pandora::Cluster *const pThirdViewCluster, const pandora::ParticleFlowObject *const pParentMuon, const float minDistanceFromMuon, const float maxDistanceToCollected, pandora::CaloHitList &collectedHits) const
In one view, pull out any hits from a cosmic ray cluster that belong to the child delta ray cluster...
virtual void TidyUp()
Tidy member variables in derived class.
void UpdateForNewClusters(const pandora::ClusterVector &newClusterVector, const pandora::PfoVector &pfoVector)
Add a new cluster to algorithm ownership maps and, if it a delta ray cluster, to the underlying match...
void TidyUp()
Tidy member variables in derived class.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
void UpdateUponDeletion(const pandora::Cluster *const pDeletedCluster)
Update to reflect cluster deletion.
void PrepareInputClusters(pandora::ClusterList &preparedClusterList)
Perform any preparatory steps required on the input clusters, e.g. caching expensive fit results...
void CollectStrayClusters(const pandora::Cluster *const pClusterToEnlarge, const float rangeMinX, const float rangeMaxX, pandora::ClusterList &collectedClusters)
Collect the stray clusters that are close to a specified cluster and that lie within a given x range...
void GetClusterSpanX(const pandora::CaloHitList &caloHitList, float &xMin, float &xMax) const
Calculate the xSpan of a list of CaloHits.
process_name pandoraGausCryo1 vertexChargeCryo1 vertexStubCryo1 xmin
pandora::StatusCode PerformThreeViewMatching(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const pandora::Cluster *const pCluster3, float &reducedChiSquared) const
To determine how well three clusters (one in each view) map onto one another expressing this in terms...
void UpdateUponDeletion(const pandora::Cluster *const pDeletedCluster)
Update to reflect cluster deletion.
Header file for the geometry helper class.
void UpdateForNewCluster(const pandora::Cluster *const pNewCluster)
Update to reflect addition of a new cluster to the problem space.
Header file for the cluster helper class.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Header file for the muon leading helper class.
pandora::StatusCode ParameteriseMuon(const pandora::ParticleFlowObject *const pParentMuon, const pandora::Cluster *const pDeltaRayCluster, pandora::CartesianVector &positionOnMuon, pandora::CartesianVector &muonDirection) const
Parameterise the projection of a cosmic ray track in order to avoid poor/sparse projections.
Header file for the lar two dimensional sliding fit result class.
static void GetClosestPositions(const pandora::CartesianPointVector &cartesianPointVector1, const pandora::Cluster *const pCluster2, pandora::CartesianVector &outputPosition1, pandora::CartesianVector &outputPosition2)
Get the closest positions between a list of positions and a cluster.
void FillStrayClusterList(const pandora::HitType hitType)
Fill the stray cluster list with clusters that do not pass the tensor threshold requirement.
pandora::ClusterList m_clusterList
List of 2D clusters in a 3D proto particle.
static float MergeTwoPositions(const pandora::Pandora &pandora, const pandora::HitType view1, const pandora::HitType view2, const float position1, const float position2)
Merge two views (U,V) to give a third view (Z).
void SplitMuonCluster(const std::string &clusterListName, const pandora::Cluster *const pMuonCluster, const pandora::CaloHitList &collectedHits, const pandora::Cluster *&pDeltaRayCluster) const
Move a list of hits from a cosmic ray cluster into the given child delta ray cluster.
void AddInStrayClusters(const pandora::Cluster *const pClusterToEnlarge, const pandora::ClusterList &collectedClusters)
Merge in the collected stray clusters of a given delta ray cluster.
void GetNearbyMuonPfos(const pandora::Cluster *const pCluster, pandora::ClusterList &consideredClusters, pandora::PfoList &nearbyMuonPfos) const
Use the cluster proximity map to travel along paths of nearby clusters finding the cosmic ray cluster...
static pandora::StatusCode GetClosestPosition(const pandora::CartesianVector &referencePoint, const pandora::CartesianPointVector &cartesianPointVector, const pandora::Cluster *const pCluster, const float maxDistanceToCluster, const float maxDistanceToReferencePoint, pandora::CartesianVector &closestPosition)
Get the closest position from an input list of projected positions that lies close to both a referenc...
fhicl::Table< sbnd::crt::CRTDetSimParams > Parameters
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch pandora
std::map< const pandora::Cluster *, pandora::ClusterList > ClusterProximityMap
Header file for the lar track overlap result class.
Header file for the three view matching control class.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
bool CreatePfos(ProtoParticleVector &protoParticleVector)
Create delta ray pfos maxmising completeness by searching for and merging in any stray clusters...
pandora::StatusCode ProjectMuonPositions(const pandora::HitType &thirdViewHitType, const pandora::ParticleFlowObject *const pParentMuon, pandora::CartesianPointVector &projectedPositions) const
Use two views of a cosmic ray pfo to calculate projected positions in a given the third view...
Header file for the two view matching control class.
Header file for the lar track two view overlap result class.
pandora::StatusCode GetMuonCluster(const pandora::PfoList &commonMuonPfoList, const pandora::HitType hitType, const pandora::Cluster *&pMuonCluster) const
Return the cluster of the common cosmic ray pfo in a given view (function demands there to be only on...
NViewDeltaRayMatchingAlgorithm class.
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.