9 #include "Pandora/AlgorithmHeaders.h" 24 SlidingConeClusterMopUpAlgorithm::SlidingConeClusterMopUpAlgorithm() :
26 m_maxIterations(1000),
27 m_maxHitsToConsider3DTrack(100),
28 m_minHitsToConsider3DShower(20),
29 m_maxHitsToConsider2DCluster(50),
30 m_halfWindowLayers(20),
33 m_coneLengthMultiplier(3.
f),
34 m_maxConeLength(126.
f),
35 m_coneTanHalfAngle(0.2
f),
36 m_coneBoundedFraction(0.5
f)
44 const Vertex *pVertex(
nullptr);
49 if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
50 std::cout <<
"SlidingConeClusterMopUpAlgorithm - interaction vertex not available for use." << std::endl;
51 return STATUS_CODE_SUCCESS;
66 return STATUS_CODE_SUCCESS;
77 PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetCurrentList(*
this, pVertexList));
80 ((pVertexList && (pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) :
nullptr);
89 const PfoList *pPfoList(
nullptr);
91 if (STATUS_CODE_SUCCESS != PandoraContentApi::GetList(*
this, pfoListName, pPfoList))
94 for (
const Pfo *
const pPfo : *pPfoList)
96 ClusterList pfoClusters3D;
99 for (
const Cluster *
const pCluster3D : pfoClusters3D)
107 if (!clusterToPfoMap.insert(ClusterToPfoMap::value_type(pCluster3D, pPfo)).second)
108 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
110 clusters3D.push_back(pCluster3D);
124 const ClusterList *pClusterList(
nullptr);
126 if (STATUS_CODE_SUCCESS != PandoraContentApi::GetList(*
this, clusterListName, pClusterList))
129 for (
const Cluster *
const pCluster : *pClusterList)
131 if (!PandoraContentApi::IsAvailable(*
this, pCluster))
137 availableClusters2D.push_back(pCluster);
149 for (
const Cluster *
const pShowerCluster : clusters3D)
151 float coneLength3D(0.
f);
157 if (!(view == TPC_VIEW_U || view == TPC_VIEW_V))
166 const float vertexToMinLayer(!pVertex ? 0.
f : (pVertex->GetPosition() - minLayerPosition).GetMagnitude());
167 const float vertexToMaxLayer(!pVertex ? 0.
f : (pVertex->GetPosition() - maxLayerPosition).GetMagnitude());
174 catch (
const StatusCodeException &)
179 for (
const Cluster *
const pNearbyCluster2D : availableClusters2D)
184 for (
const SimpleCone &simpleCone3D : simpleConeList3D)
186 const CartesianVector coneBaseCentre3D(simpleCone3D.GetConeApex() + simpleCone3D.GetConeDirection() * coneLength3D);
190 const CartesianVector apexToBase2D(coneBaseCentre2D - coneApex2D);
193 pShowerCluster, simpleCone2D.GetBoundedHitFraction(pNearbyCluster2D), simpleCone2D.GetMeanRT(pNearbyCluster2D));
195 if (clusterMerge < bestClusterMerge)
196 bestClusterMerge = clusterMerge;
200 clusterMergeMap[pNearbyCluster2D].push_back(bestClusterMerge);
204 for (ClusterMergeMap::value_type &mapEntry : clusterMergeMap)
205 std::sort(mapEntry.second.begin(), mapEntry.second.end());
213 for (
const ClusterMergeMap::value_type &mapEntry : clusterMergeMap)
214 daughterClusters.push_back(mapEntry.first);
217 for (ClusterVector::const_reverse_iterator rIter = daughterClusters.rbegin(), rIterEnd = daughterClusters.rend(); rIter != rIterEnd; ++rIter)
219 const Cluster *
const pDaughterCluster(*rIter);
221 const Cluster *
const pParentCluster3D(clusterMergeMap.at(pDaughterCluster).at(0).GetParentCluster());
223 const Pfo *
const pParentPfo(clusterToPfoMap.at(pParentCluster3D));
224 const Cluster *
const pParentCluster(this->
GetParentCluster(pParentPfo->GetClusterList(), daughterHitType));
228 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
229 PandoraContentApi::MergeAndDeleteClusters(
230 *
this, pParentCluster, pDaughterCluster, this->
GetListName(pParentCluster), this->
GetListName(pDaughterCluster)));
234 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToPfo(*
this, pParentPfo, pDaughterCluster));
253 if (std::fabs(this->GetBoundedFraction() - rhs.
GetBoundedFraction()) > std::numeric_limits<float>::epsilon())
256 if (std::fabs(this->GetMeanRT() - rhs.
GetMeanRT()) > std::numeric_limits<float>::epsilon())
257 return (this->GetMeanRT() < rhs.
GetMeanRT());
267 PANDORA_RETURN_RESULT_IF_AND_IF(
268 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadVectorOfValues(xmlHandle,
"InputPfoListNames",
m_inputPfoListNames));
270 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"UseVertex",
m_useVertex));
272 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxIterations",
m_maxIterations));
274 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
277 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
280 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
283 PANDORA_RETURN_RESULT_IF_AND_IF(
284 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"SlidingFitHalfWindow",
m_halfWindowLayers));
286 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"NConeFitLayers",
m_nConeFitLayers));
288 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"NConeFits",
m_nConeFits));
290 PANDORA_RETURN_RESULT_IF_AND_IF(
291 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"ConeLengthMultiplier",
m_coneLengthMultiplier));
293 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxConeLength",
m_maxConeLength));
295 PANDORA_RETURN_RESULT_IF_AND_IF(
296 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"ConeTanHalfAngle",
m_coneTanHalfAngle));
298 PANDORA_RETURN_RESULT_IF_AND_IF(
299 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"ConeBoundedFraction",
m_coneBoundedFraction));
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.
bool m_useVertex
Whether to use the interaction vertex to select useful cone directions.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Header file for the pfo helper class.
Header file for the sliding cone cluster mop up algorithm class.
void GetThreeDClusters(pandora::ClusterVector &clusters3D, ClusterToPfoMap &clusterToPfoMap) const
Get all 3d clusters contained in the input pfo lists and a mapping from clusters to pfos...
unsigned int m_nConeFits
The number of cone fits to perform, spread roughly uniformly along the shower length.
const pandora::Cluster * GetParentCluster() const
Get the address of the candidate parent (shower) cluster.
std::vector< SimpleCone > SimpleConeList
unsigned int m_maxIterations
The maximum allowed number of algorithm iterations.
float GetMeanRT() const
Get the mean transverse distance of all hits (whether contained or not)
pandora::StringVector m_daughterListNames
The list of potential daughter object list names.
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
float GetBoundedFraction() const
Get the bounded fraction for algorithm-specified cone angle.
unsigned int m_nConeFitLayers
The number of layers over which to sum fitted direction to obtain cone fit.
const ThreeDSlidingFitResult & GetSlidingFitResult() const
Get the sliding fit result for the full cluster.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
static bool IsTrack(const pandora::ParticleFlowObject *const pPfo)
Return track flag based on Pfo Particle ID.
std::unordered_map< const pandora::Cluster *, ClusterMergeList > ClusterMergeMap
unsigned int m_maxHitsToConsider2DCluster
The maximum number of hits in a 2d cluster to allow pick-up via sliding cone fits.
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.
Header file for the geometry helper class.
const std::string GetListName(const T *const pT) const
Find the name of the list hosting a specific object.
static bool IsShower(const pandora::ParticleFlowObject *const pPfo)
Return shower flag based on Pfo Particle ID.
void GetClusterMergeMap(const pandora::Vertex *const pVertex, const pandora::ClusterVector &clusters3D, const pandora::ClusterVector &availableClusters2D, ClusterMergeMap &clusterMergeMap) const
Get the cluster merge map describing all potential 3d cluster merges.
Header file for the cluster helper class.
float m_coneLengthMultiplier
The cone length multiplier to use when calculating bounded cluster fractions.
unsigned int m_halfWindowLayers
The number of layers to use for half-window of sliding fit.
unsigned int m_minHitsToConsider3DShower
The minimum number of hits in a 3d shower cluster to attempt cone fits.
unsigned int m_maxHitsToConsider3DTrack
The maximum number of hits in a 3d track cluster to warrant inclusion in algorithm.
void MakeClusterMerges(const ClusterToPfoMap &clusterToPfoMap, const ClusterMergeMap &clusterMergeMap) const
Make cluster merges based on the provided cluster merge map.
static float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
static const pandora::Cluster * GetParentCluster(const pandora::ClusterList &clusterList, const pandora::HitType hitType)
Select the parent cluster (same hit type and most hits) using a provided cluster list and hit type...
static void GetThreeDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 3D clusters from an input pfo.
const pandora::CartesianVector & GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
float m_coneBoundedFraction
The minimum cluster bounded fraction for association.
pandora::StringVector m_inputPfoListNames
The input pfo list names.
std::unordered_map< const pandora::Cluster *, const pandora::ParticleFlowObject * > ClusterToPfoMap
float m_coneTanHalfAngle
The cone tan half angle to use when calculating bounded cluster fractions.
ConeSelection
ConeSelection enum.
void GetAvailableTwoDClusters(pandora::ClusterVector &availableClusters2D) const
Get all available 2d clusters contained in the input cluster lists.
void GetInteractionVertex(const pandora::Vertex *&pVertex) const
Get the neutrino interaction vertex if it is available and if the algorithm is configured to do so...
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
std::vector< art::Ptr< recob::Cluster > > ClusterVector
ThreeDSlidingConeFitResult class.
float m_maxConeLength
The maximum allowed cone length to use when calculating bounded cluster fractions.
std::list< Vertex > VertexList
pandora::StatusCode Run()
const pandora::CartesianVector & GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.
bool operator<(const ClusterMerge &rhs) const
operator <