Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
SlidingConeClusterMopUpAlgorithm.cc
Go to the documentation of this file.
1
10
14
16
18
19using namespace pandora;
20
21namespace lar_content
22{
23
25 m_useVertex(true),
26 m_maxIterations(1000),
27 m_maxHitsToConsider3DTrack(100),
28 m_minHitsToConsider3DShower(20),
29 m_maxHitsToConsider2DCluster(50),
30 m_halfWindowLayers(20),
31 m_nConeFitLayers(40),
32 m_nConeFits(5),
33 m_coneLengthMultiplier(3.f),
34 m_maxConeLength(126.f),
35 m_coneTanHalfAngle(0.2f),
36 m_coneBoundedFraction(0.5f)
37{
38}
39
40//------------------------------------------------------------------------------------------------------------------------------------------
41
43{
44 const Vertex *pVertex(nullptr);
45 this->GetInteractionVertex(pVertex);
46
47 if (m_useVertex && !pVertex)
48 {
50 std::cout << "SlidingConeClusterMopUpAlgorithm - interaction vertex not available for use." << std::endl;
51 return STATUS_CODE_SUCCESS;
52 }
53
54 ClusterVector clusters3D;
55 ClusterToPfoMap clusterToPfoMap;
56 this->GetThreeDClusters(clusters3D, clusterToPfoMap);
57
58 ClusterVector availableClusters2D;
59 this->GetAvailableTwoDClusters(availableClusters2D);
60
61 ClusterMergeMap clusterMergeMap;
62 this->GetClusterMergeMap(pVertex, clusters3D, availableClusters2D, clusterMergeMap);
63
64 this->MakeClusterMerges(clusterToPfoMap, clusterMergeMap);
65
66 return STATUS_CODE_SUCCESS;
67}
68
69//------------------------------------------------------------------------------------------------------------------------------------------
70
72{
73 if (!m_useVertex)
74 return;
75
76 const VertexList *pVertexList = nullptr;
77 PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetCurrentList(*this, pVertexList));
78
79 pVertex =
80 ((pVertexList && (pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) : nullptr);
81}
82
83//------------------------------------------------------------------------------------------------------------------------------------------
84
86{
87 for (const std::string &pfoListName : m_inputPfoListNames)
88 {
89 const PfoList *pPfoList(nullptr);
90
91 if (STATUS_CODE_SUCCESS != PandoraContentApi::GetList(*this, pfoListName, pPfoList))
92 continue;
93
94 for (const Pfo *const pPfo : *pPfoList)
95 {
96 ClusterList pfoClusters3D;
97 LArPfoHelper::GetThreeDClusterList(pPfo, pfoClusters3D);
98
99 for (const Cluster *const pCluster3D : pfoClusters3D)
100 {
101 if (LArPfoHelper::IsTrack(pPfo) && (pCluster3D->GetNCaloHits() > m_maxHitsToConsider3DTrack))
102 continue;
103
104 if (LArPfoHelper::IsShower(pPfo) && (pCluster3D->GetNCaloHits() < m_minHitsToConsider3DShower))
105 continue;
106
107 if (!clusterToPfoMap.insert(ClusterToPfoMap::value_type(pCluster3D, pPfo)).second)
108 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
109
110 clusters3D.push_back(pCluster3D);
111 }
112 }
113 }
114
115 std::sort(clusters3D.begin(), clusters3D.end(), LArClusterHelper::SortByNHits);
116}
117
118//------------------------------------------------------------------------------------------------------------------------------------------
119
121{
122 for (const std::string &clusterListName : m_daughterListNames)
123 {
124 const ClusterList *pClusterList(nullptr);
125
126 if (STATUS_CODE_SUCCESS != PandoraContentApi::GetList(*this, clusterListName, pClusterList))
127 continue;
128
129 for (const Cluster *const pCluster : *pClusterList)
130 {
131 if (!PandoraContentApi::IsAvailable(*this, pCluster))
132 continue;
133
134 if (pCluster->GetNCaloHits() > m_maxHitsToConsider2DCluster)
135 continue;
136
137 availableClusters2D.push_back(pCluster);
138 }
139 }
140
141 std::sort(availableClusters2D.begin(), availableClusters2D.end(), LArClusterHelper::SortByNHits);
142}
143
144//------------------------------------------------------------------------------------------------------------------------------------------
145
147 const ClusterVector &availableClusters2D, ClusterMergeMap &clusterMergeMap) const
148{
149 const float layerPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
150
151 for (const Cluster *const pShowerCluster : clusters3D)
152 {
153 float coneLength3D(0.f);
154 SimpleConeList simpleConeList3D;
155
156 try
157 {
158 const ThreeDSlidingConeFitResult slidingConeFitResult3D(pShowerCluster, m_halfWindowLayers, layerPitch);
159
160 const CartesianVector &minLayerPosition(slidingConeFitResult3D.GetSlidingFitResult().GetGlobalMinLayerPosition());
161 const CartesianVector &maxLayerPosition(slidingConeFitResult3D.GetSlidingFitResult().GetGlobalMaxLayerPosition());
162 coneLength3D = std::min(m_coneLengthMultiplier * (maxLayerPosition - minLayerPosition).GetMagnitude(), m_maxConeLength);
163
164 const float vertexToMinLayer(!pVertex ? 0.f : (pVertex->GetPosition() - minLayerPosition).GetMagnitude());
165 const float vertexToMaxLayer(!pVertex ? 0.f : (pVertex->GetPosition() - maxLayerPosition).GetMagnitude());
166 const ConeSelection coneSelection(
167 !pVertex ? CONE_BOTH_DIRECTIONS : (vertexToMaxLayer > vertexToMinLayer) ? CONE_FORWARD_ONLY : CONE_BACKWARD_ONLY);
168
169 slidingConeFitResult3D.GetSimpleConeList(m_nConeFitLayers, m_nConeFits, coneSelection, simpleConeList3D);
170 }
171 catch (const StatusCodeException &)
172 {
173 continue;
174 }
175
176 for (const Cluster *const pNearbyCluster2D : availableClusters2D)
177 {
178 ClusterMerge bestClusterMerge(nullptr, 0.f, 0.f);
179 const HitType hitType(LArClusterHelper::GetClusterHitType(pNearbyCluster2D));
180
181 for (const SimpleCone &simpleCone3D : simpleConeList3D)
182 {
183 const CartesianVector coneBaseCentre3D(simpleCone3D.GetConeApex() + simpleCone3D.GetConeDirection() * coneLength3D);
184 const CartesianVector coneApex2D(LArGeometryHelper::ProjectPosition(this->GetPandora(), simpleCone3D.GetConeApex(), hitType));
185 const CartesianVector coneBaseCentre2D(LArGeometryHelper::ProjectPosition(this->GetPandora(), coneBaseCentre3D, hitType));
186
187 const CartesianVector apexToBase2D(coneBaseCentre2D - coneApex2D);
188 const SimpleCone simpleCone2D(coneApex2D, apexToBase2D.GetUnitVector(), apexToBase2D.GetMagnitude(), m_coneTanHalfAngle);
189 const ClusterMerge clusterMerge(
190 pShowerCluster, simpleCone2D.GetBoundedHitFraction(pNearbyCluster2D), simpleCone2D.GetMeanRT(pNearbyCluster2D));
191
192 if (clusterMerge < bestClusterMerge)
193 bestClusterMerge = clusterMerge;
194 }
195
196 if (bestClusterMerge.GetParentCluster() && (bestClusterMerge.GetBoundedFraction() > m_coneBoundedFraction))
197 clusterMergeMap[pNearbyCluster2D].push_back(bestClusterMerge);
198 }
199 }
200
201 for (ClusterMergeMap::value_type &mapEntry : clusterMergeMap)
202 std::sort(mapEntry.second.begin(), mapEntry.second.end());
203}
204
205//------------------------------------------------------------------------------------------------------------------------------------------
206
207void SlidingConeClusterMopUpAlgorithm::MakeClusterMerges(const ClusterToPfoMap &clusterToPfoMap, const ClusterMergeMap &clusterMergeMap) const
208{
209 ClusterVector daughterClusters;
210 for (const ClusterMergeMap::value_type &mapEntry : clusterMergeMap)
211 daughterClusters.push_back(mapEntry.first);
212 std::sort(daughterClusters.begin(), daughterClusters.end(), LArClusterHelper::SortByNHits);
213
214 for (ClusterVector::const_reverse_iterator rIter = daughterClusters.rbegin(), rIterEnd = daughterClusters.rend(); rIter != rIterEnd; ++rIter)
215 {
216 const Cluster *const pDaughterCluster(*rIter);
217 const HitType daughterHitType(LArClusterHelper::GetClusterHitType(pDaughterCluster));
218 const Cluster *const pParentCluster3D(clusterMergeMap.at(pDaughterCluster).at(0).GetParentCluster());
219
220 const Pfo *const pParentPfo(clusterToPfoMap.at(pParentCluster3D));
221 const Cluster *const pParentCluster(this->GetParentCluster(pParentPfo->GetClusterList(), daughterHitType));
222
223 if (pParentCluster)
224 {
225 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
227 *this, pParentCluster, pDaughterCluster, this->GetListName(pParentCluster), this->GetListName(pDaughterCluster)));
228 }
229 else
230 {
231 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToPfo(*this, pParentPfo, pDaughterCluster));
232 }
233 }
234}
235
236//------------------------------------------------------------------------------------------------------------------------------------------
237//------------------------------------------------------------------------------------------------------------------------------------------
238
240{
241 if (!this->GetParentCluster() && !rhs.GetParentCluster())
242 return false;
243
244 if (this->GetParentCluster() && !rhs.GetParentCluster())
245 return true;
246
247 if (!this->GetParentCluster() && rhs.GetParentCluster())
248 return false;
249
250 if (std::fabs(this->GetBoundedFraction() - rhs.GetBoundedFraction()) > std::numeric_limits<float>::epsilon())
251 return (this->GetBoundedFraction() > rhs.GetBoundedFraction());
252
253 if (std::fabs(this->GetMeanRT() - rhs.GetMeanRT()) > std::numeric_limits<float>::epsilon())
254 return (this->GetMeanRT() < rhs.GetMeanRT());
255
257}
258
259//------------------------------------------------------------------------------------------------------------------------------------------
260//------------------------------------------------------------------------------------------------------------------------------------------
261
263{
265 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadVectorOfValues(xmlHandle, "InputPfoListNames", m_inputPfoListNames));
266
267 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "UseVertex", m_useVertex));
268
269 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxIterations", m_maxIterations));
270
271 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
272 XmlHelper::ReadValue(xmlHandle, "MaxHitsToConsider3DTrack", m_maxHitsToConsider3DTrack));
273
274 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
275 XmlHelper::ReadValue(xmlHandle, "MinHitsToConsider3DShower", m_minHitsToConsider3DShower));
276
277 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
278 XmlHelper::ReadValue(xmlHandle, "MaxHitsToConsider2DCluster", m_maxHitsToConsider2DCluster));
279
281 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitHalfWindow", m_halfWindowLayers));
282
283 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "NConeFitLayers", m_nConeFitLayers));
284
285 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "NConeFits", m_nConeFits));
286
288 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ConeLengthMultiplier", m_coneLengthMultiplier));
289
290 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxConeLength", m_maxConeLength));
291
293 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ConeTanHalfAngle", m_coneTanHalfAngle));
294
296 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ConeBoundedFraction", m_coneBoundedFraction));
297
298 return PfoMopUpBaseAlgorithm::ReadSettings(xmlHandle);
299}
300
301} // 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 pfo helper class.
Header file for the lar three dimensional sliding cone fit result class.
Header file for the sliding cone cluster mop up algorithm class.
#define PANDORA_THROW_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
Definition StatusCodes.h:55
#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
static bool IsAvailable(const pandora::Algorithm &algorithm, const T *const pT)
Is object, or a list of objects, available as a building block.
static pandora::StatusCode AddToPfo(const pandora::Algorithm &algorithm, const pandora::ParticleFlowObject *const pPfo, const T *const pT)
Add a cluster to a particle flow object.
static pandora::StatusCode GetCurrentList(const pandora::Algorithm &algorithm, const T *&pT)
Get the current 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 GetList(const pandora::Algorithm &algorithm, const std::string &listName, const T *&pT)
Get a named list.
static const pandora::PandoraSettings * GetSettings(const pandora::Algorithm &algorithm)
Get the pandora settings instance.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
static bool SortByNHits(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by number of hits, then layer span, then inner layer, then position,...
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
static void GetThreeDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 3D clusters from an input pfo.
static bool IsTrack(const pandora::ParticleFlowObject *const pPfo)
Return track flag based on Pfo Particle ID.
static bool IsShower(const pandora::ParticleFlowObject *const pPfo)
Return shower flag based on Pfo Particle ID.
const std::string GetListName(const T *const pT) const
Find the name of the list hosting a specific object.
pandora::StringVector m_daughterListNames
The list of potential daughter object list names.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
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.
float GetBoundedHitFraction(const pandora::Cluster *const pCluster) const
Get the fraction of hits in a provided cluster that are bounded within the cone, using fitted cone an...
float GetMeanRT(const pandora::Cluster *const pCluster) const
Get the mean transverse distance to all hits in a cluster (whether contained or not)
float GetMeanRT() const
Get the mean transverse distance of all hits (whether contained or not)
float GetBoundedFraction() const
Get the bounded fraction for algorithm-specified cone angle.
const pandora::Cluster * GetParentCluster() const
Get the address of the candidate parent (shower) cluster.
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_halfWindowLayers
The number of layers to use for half-window of sliding fit.
void GetAvailableTwoDClusters(pandora::ClusterVector &availableClusters2D) const
Get all available 2d clusters contained in the input cluster lists.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
float m_coneBoundedFraction
The minimum cluster bounded fraction for association.
float m_coneLengthMultiplier
The cone length multiplier to use when calculating bounded cluster fractions.
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.
bool m_useVertex
Whether to use the interaction vertex to select useful cone directions.
float m_maxConeLength
The maximum allowed cone length to use when calculating bounded cluster fractions.
unsigned int m_maxHitsToConsider2DCluster
The maximum number of hits in a 2d cluster to allow pick-up via sliding cone fits.
pandora::StringVector m_inputPfoListNames
The input pfo list names.
unsigned int m_maxIterations
The maximum allowed number of algorithm iterations.
std::unordered_map< const pandora::Cluster *, const pandora::ParticleFlowObject * > ClusterToPfoMap
unsigned int m_nConeFits
The number of cone fits to perform, spread roughly uniformly along the shower length.
float m_coneTanHalfAngle
The cone tan half angle to use when calculating bounded cluster fractions.
unsigned int m_minHitsToConsider3DShower
The minimum number of hits in a 3d shower cluster to attempt cone fits.
std::unordered_map< const pandora::Cluster *, ClusterMergeList > ClusterMergeMap
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.
unsigned int m_maxHitsToConsider3DTrack
The maximum number of hits in a 3d track cluster to warrant inclusion in algorithm.
unsigned int m_nConeFitLayers
The number of layers over which to sum fitted direction to obtain cone fit.
void MakeClusterMerges(const ClusterToPfoMap &clusterToPfoMap, const ClusterMergeMap &clusterMergeMap) const
Make cluster merges based on the provided cluster merge map.
const ThreeDSlidingFitResult & GetSlidingFitResult() const
Get the sliding fit result for the full cluster.
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.
const pandora::CartesianVector & GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
const pandora::CartesianVector & GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.
CartesianVector class.
CartesianVector GetUnitVector() const
Get a unit vector in the direction of the cartesian vector.
float GetMagnitude() const
Get the magnitude.
Cluster class.
Definition Cluster.h:31
bool ShouldDisplayAlgorithmInfo() const
Whether to display algorithm information during processing.
ParticleFlowObject class.
const ClusterList & GetClusterList() const
Get the cluster list.
const Pandora & GetPandora() const
Get the associated pandora instance.
Definition Process.h:116
StatusCodeException class.
Vertex class.
Definition Vertex.h:26
const CartesianVector & GetPosition() const
Get the vertex position.
Definition Vertex.h:103
static StatusCode ReadVectorOfValues(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, std::vector< T > &vector)
Read a vector of values from a (space separated) list in an xml element.
Definition XmlHelper.h:229
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
Definition XmlHelper.h:136
ConeSelection
ConeSelection enum.
std::vector< SimpleCone > SimpleConeList
HitType
Calorimeter hit type enum.
std::vector< const Cluster * > ClusterVector
MANAGED_CONTAINER< const Cluster * > ClusterList
MANAGED_CONTAINER< const Vertex * > VertexList
StatusCode
The StatusCode enum.
MANAGED_CONTAINER< const ParticleFlowObject * > PfoList