Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
LongitudinalAssociationAlgorithm.cc
Go to the documentation of this file.
1
10
12
14
15using namespace pandora;
16
17namespace lar_content
18{
19
21 m_minClusterLayers(4),
22 m_maxGapLayers(7),
23 m_fitLayers(30),
24 m_maxGapDistanceSquared(10.f),
25 m_minCosRelativeAngle(0.985f),
26 m_maxTransverseDisplacement(2.f),
27 m_maxLongitudinalDisplacement(2.f),
28 m_hitSizeZ(0.3f),
29 m_hitSizeX(0.5f)
30{
31}
32
33//------------------------------------------------------------------------------------------------------------------------------------------
34
35void LongitudinalAssociationAlgorithm::GetListOfCleanClusters(const ClusterList *const pClusterList, ClusterVector &clusterVector) const
36{
37 for (ClusterList::const_iterator iter = pClusterList->begin(), iterEnd = pClusterList->end(); iter != iterEnd; ++iter)
38 {
39 const Cluster *const pCluster = *iter;
40
41 if (1 + pCluster->GetOuterPseudoLayer() - pCluster->GetInnerPseudoLayer() < m_minClusterLayers)
42 continue;
43
44 clusterVector.push_back(pCluster);
45 }
46
47 std::sort(clusterVector.begin(), clusterVector.end(), LArClusterHelper::SortByInnerLayer);
48}
49
50//------------------------------------------------------------------------------------------------------------------------------------------
51
53{
54 // ATTN This method assumes that clusters have been sorted by layer
55 for (ClusterVector::const_iterator iterI = clusterVector.begin(), iterIEnd = clusterVector.end(); iterI != iterIEnd; ++iterI)
56 {
57 const Cluster *const pInnerCluster = *iterI;
58
59 for (ClusterVector::const_iterator iterJ = iterI, iterJEnd = clusterVector.end(); iterJ != iterJEnd; ++iterJ)
60 {
61 const Cluster *const pOuterCluster = *iterJ;
62
63 if (pInnerCluster == pOuterCluster)
64 continue;
65
66 if (!this->AreClustersAssociated(pInnerCluster, pOuterCluster))
67 continue;
68
69 clusterAssociationMap[pInnerCluster].m_forwardAssociations.insert(pOuterCluster);
70 clusterAssociationMap[pOuterCluster].m_backwardAssociations.insert(pInnerCluster);
71 }
72 }
73}
74
75//------------------------------------------------------------------------------------------------------------------------------------------
76
77bool LongitudinalAssociationAlgorithm::IsExtremalCluster(const bool isForward, const Cluster *const pCurrentCluster, const Cluster *const pTestCluster) const
78{
79 const unsigned int currentLayer(isForward ? pCurrentCluster->GetOuterPseudoLayer() : pCurrentCluster->GetInnerPseudoLayer());
80 const unsigned int testLayer(isForward ? pTestCluster->GetOuterPseudoLayer() : pTestCluster->GetInnerPseudoLayer());
81
82 if (isForward && ((testLayer > currentLayer) || ((testLayer == currentLayer) && LArClusterHelper::SortByNHits(pTestCluster, pCurrentCluster))))
83 return true;
84
85 if (!isForward && ((testLayer < currentLayer) || ((testLayer == currentLayer) && LArClusterHelper::SortByNHits(pTestCluster, pCurrentCluster))))
86 return true;
87
88 return false;
89}
90
91//------------------------------------------------------------------------------------------------------------------------------------------
92
93bool LongitudinalAssociationAlgorithm::AreClustersAssociated(const Cluster *const pInnerCluster, const Cluster *const pOuterCluster) const
94{
95 if (pOuterCluster->GetInnerPseudoLayer() < pInnerCluster->GetInnerPseudoLayer())
96 throw pandora::StatusCodeException(STATUS_CODE_NOT_ALLOWED);
97
98 // TODO Remove hardcoded numbers
99 if ((pOuterCluster->GetInnerPseudoLayer() < pInnerCluster->GetInnerPseudoLayer() + 3) ||
100 (pInnerCluster->GetOuterPseudoLayer() + 3 > pOuterCluster->GetOuterPseudoLayer()))
101 {
102 return false;
103 }
104
105 if ((pInnerCluster->GetOuterPseudoLayer() > pOuterCluster->GetInnerPseudoLayer() + 1) ||
106 (pOuterCluster->GetInnerPseudoLayer() > pInnerCluster->GetOuterPseudoLayer() + m_maxGapLayers))
107 {
108 return false;
109 }
110
111 if ((2 * pInnerCluster->GetOuterPseudoLayer() < pOuterCluster->GetInnerPseudoLayer() + pInnerCluster->GetInnerPseudoLayer()) ||
112 (pInnerCluster->GetOuterPseudoLayer() + pOuterCluster->GetOuterPseudoLayer() < 2 * pOuterCluster->GetInnerPseudoLayer()))
113 {
114 return false;
115 }
116
117 const CartesianVector innerEndCentroid(pInnerCluster->GetCentroid(pInnerCluster->GetOuterPseudoLayer()));
118 const CartesianVector outerStartCentroid(pOuterCluster->GetCentroid(pOuterCluster->GetInnerPseudoLayer()));
119
120 if ((innerEndCentroid - outerStartCentroid).GetMagnitudeSquared() > m_maxGapDistanceSquared)
121 return false;
122
123 ClusterFitResult innerEndFit, outerStartFit;
124 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, ClusterFitHelper::FitEnd(pInnerCluster, m_fitLayers, innerEndFit));
125 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, ClusterFitHelper::FitStart(pOuterCluster, m_fitLayers, outerStartFit));
126
127 if (this->AreClustersAssociated(innerEndCentroid, outerStartCentroid, innerEndFit, outerStartFit))
128 return true;
129
130 return false;
131}
132
133//------------------------------------------------------------------------------------------------------------------------------------------
134
136 const CartesianVector &outerClusterStart, const ClusterFitResult &innerFit, const ClusterFitResult &outerFit) const
137{
138 if (!innerFit.IsFitSuccessful() || !outerFit.IsFitSuccessful())
139 return false;
140
142 return false;
143
144 const CartesianVector innerEndFit1(
145 innerFit.GetIntercept() + innerFit.GetDirection() * (innerFit.GetDirection().GetDotProduct(innerClusterEnd - innerFit.GetIntercept())));
146 const CartesianVector innerEndFit2(
147 outerFit.GetIntercept() + outerFit.GetDirection() * (outerFit.GetDirection().GetDotProduct(innerClusterEnd - outerFit.GetIntercept())));
148
149 const CartesianVector outerStartFit1(
150 outerFit.GetIntercept() + outerFit.GetDirection() * (outerFit.GetDirection().GetDotProduct(outerClusterStart - outerFit.GetIntercept())));
151 const CartesianVector outerStartFit2(
152 innerFit.GetIntercept() + innerFit.GetDirection() * (innerFit.GetDirection().GetDotProduct(outerClusterStart - innerFit.GetIntercept())));
153
154 const CartesianVector clusterSeparation(outerClusterStart - innerClusterEnd);
155
156 if ((std::fabs(clusterSeparation.GetX()) < m_hitSizeX * m_maxTransverseDisplacement) &&
157 (std::fabs(clusterSeparation.GetZ()) < m_hitSizeZ * m_maxLongitudinalDisplacement))
158 return true;
159
160 const CartesianVector fittedSeparation(outerStartFit1 - innerEndFit1);
161
162 if ((std::fabs(fittedSeparation.GetX()) < m_hitSizeX * m_maxTransverseDisplacement) &&
163 (std::fabs(fittedSeparation.GetZ()) < m_hitSizeZ * m_maxLongitudinalDisplacement))
164 return true;
165
166 const CartesianVector fittedInnerSeparation(innerEndFit2 - innerEndFit1);
167
168 if ((std::fabs(fittedInnerSeparation.GetX()) < m_hitSizeX * m_maxTransverseDisplacement) &&
169 (std::fabs(fittedInnerSeparation.GetZ()) < m_hitSizeZ * m_maxLongitudinalDisplacement))
170 return true;
171
172 const CartesianVector fittedOuterSeparation(outerStartFit2 - outerStartFit1);
173
174 if ((std::fabs(fittedOuterSeparation.GetX()) < m_hitSizeX * m_maxTransverseDisplacement) &&
175 (std::fabs(fittedOuterSeparation.GetZ()) < m_hitSizeZ * m_maxLongitudinalDisplacement))
176 return true;
177
178 return false;
179}
180
181//------------------------------------------------------------------------------------------------------------------------------------------
182
184{
186 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinClusterLayers", m_minClusterLayers));
187
188 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxGapLayers", m_maxGapLayers));
189
190 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "FitLayers", m_fitLayers));
191
192 float maxGapDistance = std::sqrt(m_maxGapDistanceSquared);
193 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxGapDistance", maxGapDistance));
194 m_maxGapDistanceSquared = maxGapDistance * maxGapDistance;
195
197 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinCosRelativeAngle", m_minCosRelativeAngle));
198
199 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
200 XmlHelper::ReadValue(xmlHandle, "MaxTransverseDisplacement", m_maxTransverseDisplacement));
201
202 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
203 XmlHelper::ReadValue(xmlHandle, "MaxLongitudinalDisplacement", m_maxLongitudinalDisplacement));
204
205 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "HitSizeZ", m_hitSizeZ));
206
207 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "HitSizeX", m_hitSizeX));
208
210}
211
212} // 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 longitudinal association algorithm class.
#define PANDORA_THROW_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:43
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
Definition StatusCodes.h:31
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
static bool SortByInnerLayer(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by inner layer, then position, then pulse-height.
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,...
unsigned int m_fitLayers
number of layers to fit at start and end of cluster
unsigned int m_minClusterLayers
minimum allowed number of layers for a clean cluster
bool AreClustersAssociated(const pandora::Cluster *const pInnerCluster, const pandora::Cluster *const pOuterCluster) const
Determine whether two clusters are associated.
float m_maxGapDistanceSquared
maximum allowed distance (squared) between associated clusters
void PopulateClusterAssociationMap(const pandora::ClusterVector &clusterVector, ClusterAssociationMap &clusterAssociationMap) const
Populate the cluster association map.
float m_maxLongitudinalDisplacement
maximum allowed longitudinal displacement after extrapolation (normalised to cell size)
void GetListOfCleanClusters(const pandora::ClusterList *const pClusterList, pandora::ClusterVector &clusterVector) const
Populate cluster vector with subset of cluster list, containing clusters judged to be clean.
bool IsExtremalCluster(const bool isForward, const pandora::Cluster *const pCurrentCluster, const pandora::Cluster *const pTestCluster) const
Determine which of two clusters is extremal.
float m_minCosRelativeAngle
maximum allowed relative angle between associated clusters
float m_hitSizeX
estimated hit size in x (drift time) dimension, units cm
float m_maxTransverseDisplacement
maximum allowed transverse displacement after extrapolation (normalised to cell size)
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
float m_hitSizeZ
estimated hit size in z (wire number) dimension, units cm
unsigned int m_maxGapLayers
maximum allowed number of layers between associated clusters
CartesianVector class.
float GetCosOpeningAngle(const CartesianVector &rhs) const
Get the cosine of the opening angle of the cartesian vector with respect to a second cartesian vector...
float GetX() const
Get the cartesian x coordinate.
float GetZ() const
Get the cartesian z coordinate.
float GetDotProduct(const CartesianVector &rhs) const
Get the dot product of the cartesian vector with a second cartesian vector.
static StatusCode FitStart(const Cluster *const pCluster, const unsigned int maxOccupiedLayers, ClusterFitResult &clusterFitResult)
Fit points in first n occupied pseudolayers of a cluster.
static StatusCode FitEnd(const Cluster *const pCluster, const unsigned int maxOccupiedLayers, ClusterFitResult &clusterFitResult)
Fit points in last n occupied pseudolayers of a cluster.
ClusterFitResult class.
const CartesianVector & GetDirection() const
Get the fit direction.
bool IsFitSuccessful() const
Query whether fit was successful.
const CartesianVector & GetIntercept() const
Get the fit intercept.
Cluster class.
Definition Cluster.h:31
unsigned int GetOuterPseudoLayer() const
Get the outermost pseudo layer in the cluster.
Definition Cluster.h:568
unsigned int GetInnerPseudoLayer() const
Get the innermost pseudo layer in the cluster.
Definition Cluster.h:561
const CartesianVector GetCentroid(const unsigned int pseudoLayer) const
Get unweighted centroid for cluster at a particular pseudo layer, calculated using cached values of h...
Definition Cluster.cc:37
StatusCodeException class.
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
Definition XmlHelper.h:136
std::vector< const Cluster * > ClusterVector
MANAGED_CONTAINER< const Cluster * > ClusterList
StatusCode
The StatusCode enum.