9 #include "Pandora/AlgorithmHeaders.h" 30 EventSlicingTool::EventSlicingTool() :
31 m_minHitsPer3DCluster(20),
32 m_min3DHitsToSeedNewSlice(50),
33 m_halfWindowLayers(20),
34 m_usePointingAssociation(true),
35 m_minVertexLongitudinalDistance(-7.5
f),
36 m_maxVertexLongitudinalDistance(60.
f),
37 m_maxVertexTransverseDistance(10.5
f),
38 m_vertexAngularAllowance(9.
f),
39 m_maxClosestApproach(15.
f),
40 m_maxInterceptDistance(60.
f),
41 m_useProximityAssociation(true),
42 m_maxHitSeparationSquared(25.
f * 25.
f),
43 m_useShowerConeAssociation(true),
46 m_coneLengthMultiplier(7.
f),
47 m_maxConeLength(126.
f),
48 m_coneTanHalfAngle1(0.5
f),
49 m_coneBoundedFraction1(0.5
f),
50 m_coneTanHalfAngle2(0.75
f),
51 m_coneBoundedFraction2(0.75
f),
52 m_use3DProjectionsInHitPickUp(true)
61 if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
62 std::cout <<
"----> Running Algorithm Tool: " << this->GetInstanceName() <<
", " << this->GetType() << std::endl;
66 ClusterList trackClusters3D;
69 ClusterList showerClusters3D;
75 if (clusterSliceList.size() < 2)
82 this->
CreateSlices(clusterSliceList, sliceList, clusterToSliceIndexMap);
84 ClusterSet assignedClusters;
85 this->
CopyPfoHitsToSlices(clusterToSliceIndexMap, clusterToPfoMap, sliceList, assignedClusters);
87 ClusterList remainingClusters;
98 if (!sliceList.empty())
99 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
101 const CaloHitList *pCaloHitListU(
nullptr);
102 PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=,
103 PandoraContentApi::GetList(*pAlgorithm, caloHitListNames.at(TPC_VIEW_U), pCaloHitListU));
105 const CaloHitList *pCaloHitListV(
nullptr);
106 PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=,
107 PandoraContentApi::GetList(*pAlgorithm, caloHitListNames.at(TPC_VIEW_V), pCaloHitListV));
109 const CaloHitList *pCaloHitListW(
nullptr);
110 PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=,
111 PandoraContentApi::GetList(*pAlgorithm, caloHitListNames.at(TPC_VIEW_W), pCaloHitListW));
113 if (pCaloHitListU || pCaloHitListV || pCaloHitListW)
115 sliceList.push_back(
Slice());
116 Slice &slice(sliceList.at(0));
121 slice.m_caloHitListV = *pCaloHitListV;
123 slice.m_caloHitListW = *pCaloHitListW;
130 const Algorithm *
const pAlgorithm,
const std::string &pfoListName, ClusterList &clusters3D,
ClusterToPfoMap &clusterToPfoMap)
const 132 const PfoList *pPfoList(
nullptr);
133 PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*pAlgorithm, pfoListName, pPfoList));
135 if (!pPfoList || pPfoList->empty())
137 if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
138 std::cout <<
"EventSlicingTool: unable to find pfo list " << pfoListName << std::endl;
143 for (
const ParticleFlowObject *
const pPfo : *pPfoList)
145 ClusterList pfoClusters3D;
148 for (
const Cluster *
const pCluster3D : pfoClusters3D)
153 if (!clusterToPfoMap.insert(ClusterToPfoMap::value_type(pCluster3D, pPfo)).second)
154 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
156 if (clusters3D.end() != std::find(clusters3D.begin(), clusters3D.end(), pCluster3D))
157 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
159 clusters3D.push_back(pCluster3D);
171 const float pitchMax{std::max({pitchU, pitchV, pitchW})};
172 const float layerPitch(pitchMax);
176 for (
const Cluster *
const pCluster3D : trackClusters3D)
180 trackFitResults.insert(
183 catch (StatusCodeException &)
185 std::cout <<
"EventSlicingTool: ThreeDSlidingFitResult failure for track cluster." << std::endl;
191 for (
const Cluster *
const pCluster3D : showerClusters3D)
195 showerConeFitResults.insert(
198 catch (StatusCodeException &)
200 std::cout <<
"EventSlicingTool: ThreeDSlidingConeFitResult failure for shower cluster." << std::endl;
204 ClusterVector sortedClusters3D(trackClusters3D.begin(), trackClusters3D.end());
205 sortedClusters3D.insert(sortedClusters3D.end(), showerClusters3D.begin(), showerClusters3D.end());
208 ClusterSet usedClusters;
210 for (
const Cluster *
const pCluster3D : sortedClusters3D)
212 if (usedClusters.count(pCluster3D))
219 usedClusters.insert(pCluster3D);
222 this->
CollectAssociatedClusters(pCluster3D, sortedClusters3D, trackFitResults, showerConeFitResults, clusterSlice, usedClusters);
234 for (
const Cluster *
const pCandidateCluster : candidateClusters)
236 if (usedClusters.count(pCandidateCluster) || (pClusterInSlice == pCandidateCluster))
242 (this->
PassShowerCone(pClusterInSlice, pCandidateCluster, showerConeFitResults) ||
243 this->
PassShowerCone(pCandidateCluster, pClusterInSlice, showerConeFitResults))))
245 addedClusters.push_back(pCandidateCluster);
246 (void)usedClusters.insert(pCandidateCluster);
250 clusterSlice.insert(clusterSlice.end(), addedClusters.begin(), addedClusters.end());
252 for (
const Cluster *
const pAddedCluster : addedClusters)
253 this->
CollectAssociatedClusters(pAddedCluster, candidateClusters, trackFitResults, showerConeFitResults, clusterSlice, usedClusters);
259 const Cluster *
const pClusterInSlice,
const Cluster *
const pCandidateCluster,
const ThreeDSlidingFitResultMap &trackFitResults)
const 264 if ((trackFitResults.end() == inSliceIter) || (trackFitResults.end() == candidateIter))
271 this->
IsEmission(inSlicePointingCluster, candidatePointingCluster) || this->
IsNode(inSlicePointingCluster, candidatePointingCluster))
283 for (
const auto &orderedList1 : pClusterInSlice->GetOrderedCaloHitList())
285 for (
const CaloHit *
const pCaloHit1 : *(orderedList1.second))
287 const CartesianVector &positionVector1(pCaloHit1->GetPositionVector());
289 for (
const auto &orderedList2 : pCandidateCluster->GetOrderedCaloHitList())
291 for (
const CaloHit *
const pCaloHit2 : *(orderedList2.second))
310 if (showerConeFitResults.end() == fitIter)
313 float clusterLength(0.
f);
321 clusterLength = (slidingFitResult3D.GetGlobalMaxLayerPosition() - slidingFitResult3D.GetGlobalMinLayerPosition()).GetMagnitude();
323 catch (
const StatusCodeException &)
328 for (
const SimpleCone &simpleCone : simpleConeList)
358 CartesianVector intersectionPoint(0.
f, 0.
f, 0.
f);
359 float displacement1(std::numeric_limits<float>::max()), displacement2(std::numeric_limits<float>::max());
365 catch (
const StatusCodeException &)
372 const float closestApproach((approach1 - approach2).GetMagnitude());
426 unsigned int index(0);
430 for (
const Cluster *
const pCluster3D : clusterList)
433 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
435 if (!clusterToSliceIndexMap.insert(ClusterToSliceIndexMap::value_type(pCluster3D, index)).second)
436 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
439 sliceList.push_back(
Slice());
447 SliceList &sliceList, ClusterSet &assignedClusters)
const 449 ClusterList clusterList;
450 for (
const auto &mapEntry : clusterToSliceIndexMap)
451 clusterList.push_back(mapEntry.first);
454 for (
const Cluster *
const pCluster3D : clusterList)
456 const unsigned int index(clusterToSliceIndexMap.at(pCluster3D));
458 const Pfo *
const pPfo(clusterToPfoMap.at(pCluster3D));
459 Slice &slice(sliceList.at(index));
461 ClusterList clusters2D;
464 for (
const Cluster *
const pCluster2D : clusters2D)
468 if ((TPC_VIEW_U != hitType) && (TPC_VIEW_V != hitType) && (TPC_VIEW_W != hitType))
469 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
471 CaloHitList &targetList((TPC_VIEW_U == hitType) ? slice.m_caloHitListU
472 : (TPC_VIEW_V == hitType) ? slice.m_caloHitListV
473 : slice.m_caloHitListW);
475 pCluster2D->GetOrderedCaloHitList().FillCaloHitList(targetList);
476 targetList.insert(targetList.end(), pCluster2D->GetIsolatedCaloHitList().begin(), pCluster2D->GetIsolatedCaloHitList().end());
478 if (!assignedClusters.insert(pCluster2D).second)
479 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
487 const ClusterSet &assignedClusters, ClusterList &remainingClusters)
const 489 this->
GetRemainingClusters(pAlgorithm, clusterListNames.at(TPC_VIEW_U), assignedClusters, remainingClusters);
490 this->
GetRemainingClusters(pAlgorithm, clusterListNames.at(TPC_VIEW_V), assignedClusters, remainingClusters);
491 this->
GetRemainingClusters(pAlgorithm, clusterListNames.at(TPC_VIEW_W), assignedClusters, remainingClusters);
497 const ClusterSet &assignedClusters, ClusterList &remainingClusters)
const 499 const ClusterList *pClusterList(
nullptr);
500 PANDORA_THROW_RESULT_IF_AND_IF(
501 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*pAlgorithm, clusterListName, pClusterList));
503 if (!pClusterList || pClusterList->empty())
505 if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
506 std::cout <<
"EventSlicingTool: unable to find cluster list " << clusterListName << std::endl;
511 for (
const Cluster *
const pCluster2D : *pClusterList)
515 if ((TPC_VIEW_U != hitType) && (TPC_VIEW_V != hitType) && (TPC_VIEW_W != hitType))
516 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
518 if (assignedClusters.count(pCluster2D))
521 if (remainingClusters.end() != std::find(remainingClusters.begin(), remainingClusters.end(), pCluster2D))
522 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
524 remainingClusters.push_back(pCluster2D);
541 this->
GetKDTreeEntries3D(clusterToSliceIndexMap, pointsU, pointsV, pointsW, pointToSliceIndexMap);
553 kdTreeU.
build(kDNode2DListU, boundingRegionU);
554 kdTreeV.
build(kDNode2DListV, boundingRegionV);
555 kdTreeW.
build(kDNode2DListW, boundingRegionW);
557 ClusterVector sortedRemainingClusters(remainingClusters.begin(), remainingClusters.end());
560 for (
const Cluster *
const pCluster2D : sortedRemainingClusters)
564 if ((TPC_VIEW_U != hitType) && (TPC_VIEW_V != hitType) && (TPC_VIEW_W != hitType))
565 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
567 PointKDTree2D &kdTree((TPC_VIEW_U == hitType) ? kdTreeU : (TPC_VIEW_V == hitType) ? kdTreeV : kdTreeW);
570 if (!pBestResultPoint)
573 Slice &slice(sliceList.at(pointToSliceIndexMap.at(pBestResultPoint->
data)));
574 CaloHitList &targetList((TPC_VIEW_U == hitType) ? slice.
m_caloHitListU 578 pCluster2D->GetOrderedCaloHitList().FillCaloHitList(targetList);
579 targetList.insert(targetList.end(), pCluster2D->GetIsolatedCaloHitList().begin(), pCluster2D->GetIsolatedCaloHitList().end());
584 std::cout <<
"EventSlicingTool::AssignRemainingHitsToSlices - exception " << std::endl;
585 for (
const auto &pointMap : pointToSliceIndexMap)
586 delete pointMap.first;
590 for (
const auto &pointMap : pointToSliceIndexMap)
591 delete pointMap.first;
599 unsigned int sliceIndex(0);
601 for (
const Slice &slice : sliceList)
603 for (
const CaloHit *
const pCaloHit : slice.m_caloHitListU)
605 const CartesianVector *
const pPoint(
new CartesianVector(pCaloHit->GetPositionVector()));
606 pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pPoint, sliceIndex));
607 pointsU.push_back(pPoint);
610 for (
const CaloHit *
const pCaloHit : slice.m_caloHitListV)
612 const CartesianVector *
const pPoint(
new CartesianVector(pCaloHit->GetPositionVector()));
613 pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pPoint, sliceIndex));
614 pointsV.push_back(pPoint);
617 for (
const CaloHit *
const pCaloHit : slice.m_caloHitListW)
619 const CartesianVector *
const pPoint(
new CartesianVector(pCaloHit->GetPositionVector()));
620 pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pPoint, sliceIndex));
621 pointsW.push_back(pPoint);
633 ClusterList clusterList;
634 for (
const auto &mapEntry : clusterToSliceIndexMap)
635 clusterList.push_back(mapEntry.first);
638 for (
const Cluster *
const pCluster3D : clusterList)
640 const unsigned int sliceIndex(clusterToSliceIndexMap.at(pCluster3D));
642 CaloHitList caloHitList;
643 pCluster3D->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
645 for (
const CaloHit *
const pCaloHit3D : caloHitList)
647 if (TPC_3D != pCaloHit3D->GetHitType())
648 throw StatusCodeException(STATUS_CODE_FAILURE);
650 const CartesianVector &position3D(pCaloHit3D->GetPositionVector());
652 const CartesianVector *
const pProjectionU(
654 const CartesianVector *
const pProjectionV(
656 const CartesianVector *
const pProjectionW(
659 pointsU.push_back(pProjectionU);
660 pointsV.push_back(pProjectionV);
661 pointsW.push_back(pProjectionW);
663 pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pProjectionU, sliceIndex));
664 pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pProjectionV, sliceIndex));
665 pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pProjectionW, sliceIndex));
679 clusterPointList.push_back(
new CartesianVector(pCluster2D->GetCentroid(pCluster2D->GetInnerPseudoLayer())));
680 clusterPointList.push_back(
new CartesianVector(pCluster2D->GetCentroid(pCluster2D->GetOuterPseudoLayer())));
681 clusterPointList.push_back(
new CartesianVector(
682 (pCluster2D->GetCentroid(pCluster2D->GetInnerPseudoLayer()) + pCluster2D->GetCentroid(pCluster2D->GetOuterPseudoLayer())) * 0.5f));
684 float bestDistance(std::numeric_limits<float>::max());
686 for (
const CartesianVector *
const pClusterPoint : clusterPointList)
689 float resultDistance(std::numeric_limits<float>::max());
690 const PointKDNode2D targetPoint(pClusterPoint, pClusterPoint->GetX(), pClusterPoint->GetZ());
693 if (pResultPoint && (resultDistance < bestDistance))
695 pBestResultPoint = pResultPoint;
696 bestDistance = resultDistance;
702 std::cout <<
"EventSlicingTool::MatchClusterToSlice - exception " << std::endl;
703 for (
const CartesianVector *
const pPoint : clusterPointList)
708 for (
const CartesianVector *
const pPoint : clusterPointList)
711 return pBestResultPoint;
718 const CartesianVector deltaPosition(*pRhs - *pLhs);
720 if (std::fabs(deltaPosition.GetZ()) > std::numeric_limits<float>::epsilon())
721 return (deltaPosition.GetZ() > std::numeric_limits<float>::epsilon());
723 if (std::fabs(deltaPosition.GetX()) > std::numeric_limits<float>::epsilon())
724 return (deltaPosition.GetX() > std::numeric_limits<float>::epsilon());
726 return (deltaPosition.GetY() > std::numeric_limits<float>::epsilon());
733 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"TrackPfoListName",
m_trackPfoListName));
735 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"ShowerPfoListName",
m_showerPfoListName));
737 PANDORA_RETURN_RESULT_IF_AND_IF(
738 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinHitsPer3DCluster",
m_minHitsPer3DCluster));
740 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
743 PANDORA_RETURN_RESULT_IF_AND_IF(
744 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"SlidingFitHalfWindow",
m_halfWindowLayers));
746 PANDORA_RETURN_RESULT_IF_AND_IF(
747 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"UsePointingAssociation",
m_usePointingAssociation));
749 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
752 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
755 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
758 PANDORA_RETURN_RESULT_IF_AND_IF(
759 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"VertexAngularAllowance",
m_vertexAngularAllowance));
761 PANDORA_RETURN_RESULT_IF_AND_IF(
762 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxClosestApproach",
m_maxClosestApproach));
764 PANDORA_RETURN_RESULT_IF_AND_IF(
765 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxInterceptDistance",
m_maxInterceptDistance));
767 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
771 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxHitSeparation", maxHitSeparation));
774 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
777 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"NConeFitLayers",
m_nConeFitLayers));
779 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"NConeFits",
m_nConeFits));
781 PANDORA_RETURN_RESULT_IF_AND_IF(
782 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"ConeLengthMultiplier",
m_coneLengthMultiplier));
784 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxConeLength",
m_maxConeLength));
786 PANDORA_RETURN_RESULT_IF_AND_IF(
787 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"ConeTanHalfAngle1",
m_coneTanHalfAngle1));
789 PANDORA_RETURN_RESULT_IF_AND_IF(
790 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"ConeBoundedFraction1",
m_coneBoundedFraction1));
792 PANDORA_RETURN_RESULT_IF_AND_IF(
793 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"ConeTanHalfAngle2",
m_coneTanHalfAngle2));
795 PANDORA_RETURN_RESULT_IF_AND_IF(
796 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"ConeBoundedFraction2",
m_coneBoundedFraction2));
798 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
801 return STATUS_CODE_SUCCESS;
void GetThreeDClusters(const pandora::Algorithm *const pAlgorithm, const std::string &pfoListName, pandora::ClusterList &clusters3D, ClusterToPfoMap &clusterToPfoMap) const
Get the 3D clusters from a specified list of pfos, storing the 3D clusters in the provided list and p...
unsigned int m_nConeFits
The number of cone fits to perform, spread roughly uniformly along the shower length.
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, then pulse-height.
void GetClusterSliceList(const pandora::ClusterList &trackClusters3D, const pandora::ClusterList &showerClusters3D, ClusterSliceList &clusterSliceList) const
Divide the provided lists of 3D track and shower clusters into slices.
unsigned int m_min3DHitsToSeedNewSlice
The minimum number of hits in a 3D cluster to seed a new slice.
Header file for the kd tree linker algo template class.
Header file for the pfo helper class.
float m_maxHitSeparationSquared
Proximity association: max distance allowed between the closest pair of hits.
unsigned int m_nConeFitLayers
The number of layers over which to sum fitted direction to obtain cone fit.
float m_coneTanHalfAngle2
The cone tan half angle to use when calculating bounded cluster fractions 2.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
std::unordered_map< const pandora::Cluster *, const pandora::ParticleFlowObject * > ClusterToPfoMap
float m_maxVertexTransverseDistance
Pointing association check: max transverse distance cut.
static bool IsEmission(const pandora::CartesianVector &parentVertex, const LArPointingCluster::Vertex &daughterVertex, const float minLongitudinalDistance, const float maxLongitudinalDistance, const float maxTransverseDistance, const float angularAllowance)
Whether pointing vertex is emitted from a given position.
float m_coneBoundedFraction2
The minimum cluster bounded fraction for association 2.
std::string m_showerPfoListName
The name of the input shower pfo list.
static void GetIntersection(const LArPointingCluster::Vertex &firstVertex, const LArPointingCluster::Vertex &secondVertex, pandora::CartesianVector &intersectPosition, float &firstDisplacement, float &secondDisplacement)
Get intersection of two vertices.
static void GetTwoDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 2D clusters from an input pfo.
Class that implements the KDTree partition of 2D space and a closest point search algorithm...
void CopyPfoHitsToSlices(const ClusterToSliceIndexMap &clusterToSliceIndexMap, const ClusterToPfoMap &clusterToPfoMap, SliceList &sliceList, pandora::ClusterSet &assignedClusters) const
Use 3D clusters in the cluster slice list, find their parent pfos and assign all hits in all 2D clust...
Box structure used to define 2D field. It's used in KDTree building step to divide the detector space...
std::vector< SimpleCone > SimpleConeList
void CopyAllHitsToSingleSlice(const pandora::Algorithm *const pAlgorithm, const HitTypeToNameMap &caloHitListNames, SliceList &sliceList) const
Copy all the input hits in an event into a single slice.
bool PassShowerCone(const pandora::Cluster *const pConeCluster, const pandora::Cluster *const pNearbyCluster, const ThreeDSlidingConeFitResultMap &showerConeFitResults) const
Compare the provided clusters to assess whether they are associated via cone fits to the shower clust...
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
std::vector< Slice > SliceList
bool PassPointing(const pandora::Cluster *const pClusterInSlice, const pandora::Cluster *const pCandidateCluster, const ThreeDSlidingFitResultMap &trackFitResults) const
Compare the provided clusters to assess whether they are associated via pointing (checks association ...
const ThreeDSlidingFitResult & GetSlidingFitResult() const
Get the sliding fit result for the full cluster.
unsigned int m_minHitsPer3DCluster
The minimum number of hits in a 3D cluster to warrant consideration in slicing.
LArPointingCluster class.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
float m_coneTanHalfAngle1
The cone tan half angle to use when calculating bounded cluster fractions 1.
void CollectAssociatedClusters(const pandora::Cluster *const pClusterInSlice, const pandora::ClusterVector &candidateClusters, const ThreeDSlidingFitResultMap &trackFitResults, const ThreeDSlidingConeFitResultMap &showerConeFitResults, pandora::ClusterVector &clusterSlice, pandora::ClusterSet &usedClusters) const
Collect all clusters associated with a provided cluster.
const PointKDNode2D * MatchClusterToSlice(const pandora::Cluster *const pCluster2D, PointKDTree2D &kdTree) const
Use the provided kd tree to efficiently identify the most appropriate slice for the provided 2D clust...
pandora::CaloHitList m_caloHitListW
The w calo hit list.
Header file for the lar three dimensional sliding cone fit result class.
void GetSimpleConeList(const unsigned int nLayersForConeFit, const unsigned int nCones, const ConeSelection coneSelection, SimpleConeList &simpleConeList) const
Get the list of simple cones fitted to the three dimensional cluster.
float m_maxVertexLongitudinalDistance
Pointing association check: max longitudinal distance cut.
void findNearestNeighbour(const KDTreeNodeInfoT< DATA, DIM > &point, const KDTreeNodeInfoT< DATA, DIM > *&result, float &distance)
findNearestNeighbour
Data stored in each KDTree node. The dim1/dim2 fields are usually the duplication of some PFRecHit va...
std::unordered_map< const pandora::CartesianVector *, unsigned int > PointToSliceIndexMap
std::string m_trackPfoListName
The name of the input track pfo list.
pandora::CaloHitList m_caloHitListU
The u calo hit list.
Header file for the geometry helper class.
bool m_useProximityAssociation
Whether to use proximity association.
float m_maxClosestApproach
Pointing association: max distance of closest approach between straight line fits.
pandora::CaloHitList m_caloHitListV
The v calo hit list.
std::unordered_map< const pandora::Cluster *, ThreeDSlidingFitResult > ThreeDSlidingFitResultMap
bool IsNode(const LArPointingCluster &cluster1, const LArPointingCluster &cluster2) const
Check whether a pair of pointing clusters are nodally associated.
static bool SortPoints(const pandora::CartesianVector *const pLhs, const pandora::CartesianVector *const pRhs)
Sort points (use Z, followed by X, followed by Y)
std::map< pandora::HitType, std::string > HitTypeToNameMap
Header file for the cluster helper class.
bool m_usePointingAssociation
Whether to use pointing association.
float m_coneLengthMultiplier
The cone length multiplier to use when calculating bounded cluster fractions.
const Vertex & GetOuterVertex() const
Get the outer vertex.
void build(std::vector< KDTreeNodeInfoT< DATA, DIM >> &eltList, const KDTreeBoxT< DIM > ®ion)
Build the KD tree from the "eltList" in the space define by "region".
const Vertex & GetInnerVertex() const
Get the inner vertex.
bool PassProximity(const pandora::Cluster *const pClusterInSlice, const pandora::Cluster *const pCandidateCluster) const
Compare the provided clusters to assess whether they are associated via pointing. ...
static float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
void GetKDTreeEntries2D(const SliceList &sliceList, PointList &pointsU, PointList &pointsV, PointList &pointsW, PointToSliceIndexMap &pointToSliceIndexMap) const
Use projections of 3D hits already assigned to slices to populate kd trees to aid assignment of remai...
static void GetThreeDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 3D clusters from an input pfo.
std::vector< pandora::ClusterVector > ClusterSliceList
Header file for the lar three dimensional sliding fit result class.
const pandora::CartesianVector & GetDirection() const
Get the vertex direction.
std::unordered_map< const pandora::Cluster *, ThreeDSlidingConeFitResult > ThreeDSlidingConeFitResultMap
std::list< const pandora::CartesianVector * > PointList
void RunSlicing(const pandora::Algorithm *const pAlgorithm, const HitTypeToNameMap &caloHitListNames, const HitTypeToNameMap &clusterListNames, SliceList &sliceList)
Run the slicing tool.
bool CheckClosestApproach(const LArPointingCluster &cluster1, const LArPointingCluster &cluster2) const
Check closest approach metrics for a pair of pointing clusters.
std::vector< PointKDNode2D > PointKDNode2DList
std::unordered_map< const pandora::Cluster *, unsigned int > ClusterToSliceIndexMap
ThreeDSlidingFitResult class.
float m_maxInterceptDistance
Pointing association: max distance from cluster vertex to point of closest approach.
void GetRemainingClusters(const pandora::Algorithm *const pAlgorithm, const HitTypeToNameMap &clusterListNames, const pandora::ClusterSet &assignedClusters, pandora::ClusterList &remainingClusters) const
Get the list of 2D clusters with hits yets to be assigned to slices.
KDTreeBox fill_and_bound_2d_kd_tree(const MANAGED_CONTAINER< const T * > &points, std::vector< KDTreeNodeInfoT< const T *, 2 >> &nodes)
fill_and_bound_2d_kd_tree
float m_minVertexLongitudinalDistance
Pointing association check: min longitudinal distance cut.
bool IsEmission(const LArPointingCluster &cluster1, const LArPointingCluster &cluster2) const
Check whether a pair of pointing clusters are consistent with an emission.
bool m_use3DProjectionsInHitPickUp
Whether to include 3D cluster projections when assigning remaining clusters to slices.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
ThreeDSlidingConeFitResult class.
float m_maxConeLength
The maximum allowed cone length to use when calculating bounded cluster fractions.
bool m_useShowerConeAssociation
Whether to use shower cone association.
float m_vertexAngularAllowance
Pointing association check: pointing angular allowance in degrees.
void CreateSlices(const ClusterSliceList &clusterSliceList, SliceList &sliceList, ClusterToSliceIndexMap &clusterToSliceIndexMap) const
Create new slices for each of the groupings of 3D clusters in the provided cluster slice list...
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
void GetKDTreeEntries3D(const ClusterToSliceIndexMap &clusterToSliceIndexMap, PointList &pointsU, PointList &pointsV, PointList &pointsW, PointToSliceIndexMap &pointToSliceIndexMap) const
Use 2D hits already assigned to slices to populate kd trees to aid assignment of remaining clusters...
float m_coneBoundedFraction1
The minimum cluster bounded fraction for association 1.
void AssignRemainingHitsToSlices(const pandora::ClusterList &remainingClusters, const ClusterToSliceIndexMap &clusterToSliceIndexMap, SliceList &sliceList) const
Use the list of remaining 2D clusters to assign all remaining 2D hits to existing slices in the slice...
static bool IsNode(const pandora::CartesianVector &parentVertex, const LArPointingCluster::Vertex &daughterVertex, const float minLongitudinalDistance, const float maxTransverseDistance)
Whether pointing vertex is adjacent to a given position.
unsigned int m_halfWindowLayers
The number of layers to use for half-window of sliding fit.