Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
CrossGapsAssociationAlgorithm.cc
Go to the documentation of this file.
1
10
13
15
16using namespace pandora;
17
18namespace lar_content
19{
20
22 m_minClusterHits(10),
23 m_minClusterLayers(6),
24 m_slidingFitWindow(20),
25 m_maxSamplingPoints(1000),
26 m_sampleStepSize(0.5f),
27 m_maxUnmatchedSampleRun(8),
28 m_maxOnClusterDistance(1.5f),
29 m_minMatchedSamplingPoints(10),
30 m_minMatchedSamplingFraction(0.5f),
31 m_gapTolerance(0.f)
32{
33}
34
35//------------------------------------------------------------------------------------------------------------------------------------------
36
37void CrossGapsAssociationAlgorithm::GetListOfCleanClusters(const ClusterList *const pClusterList, ClusterVector &clusterVector) const
38{
39 // ATTN May want to opt-out completely if no gap information available
40 // if (PandoraContentApi::GetGeometry(*this)->GetDetectorGapList().empty())
41 // return;
42
43 for (const Cluster *const pCluster : *pClusterList)
44 {
45 if (pCluster->GetNCaloHits() < m_minClusterHits)
46 continue;
47
48 if (1 + pCluster->GetOuterPseudoLayer() - pCluster->GetInnerPseudoLayer() < m_minClusterLayers)
49 continue;
50
51 clusterVector.push_back(pCluster);
52 }
53
54 std::sort(clusterVector.begin(), clusterVector.end(), LArClusterHelper::SortByInnerLayer);
55}
56
57//------------------------------------------------------------------------------------------------------------------------------------------
58
60{
61 TwoDSlidingFitResultMap slidingFitResultMap;
62 const float slidingFitPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
63
64 for (const Cluster *const pCluster : clusterVector)
65 {
66 try
67 {
68 (void)slidingFitResultMap.insert(
69 TwoDSlidingFitResultMap::value_type(pCluster, TwoDSlidingFitResult(pCluster, m_slidingFitWindow, slidingFitPitch)));
70 }
71 catch (StatusCodeException &)
72 {
73 }
74 }
75
76 // ATTN This method assumes that clusters have been sorted by layer
77 for (ClusterVector::const_iterator iterI = clusterVector.begin(), iterIEnd = clusterVector.end(); iterI != iterIEnd; ++iterI)
78 {
79 const Cluster *const pInnerCluster = *iterI;
80 TwoDSlidingFitResultMap::const_iterator fitIterI = slidingFitResultMap.find(pInnerCluster);
81
82 if (slidingFitResultMap.end() == fitIterI)
83 continue;
84
85 for (ClusterVector::const_iterator iterJ = iterI, iterJEnd = clusterVector.end(); iterJ != iterJEnd; ++iterJ)
86 {
87 const Cluster *const pOuterCluster = *iterJ;
88
89 if (pInnerCluster == pOuterCluster)
90 continue;
91
92 TwoDSlidingFitResultMap::const_iterator fitIterJ = slidingFitResultMap.find(pOuterCluster);
93
94 if (slidingFitResultMap.end() == fitIterJ)
95 continue;
96
97 if (!this->AreClustersAssociated(fitIterI->second, fitIterJ->second))
98 continue;
99
100 clusterAssociationMap[pInnerCluster].m_forwardAssociations.insert(pOuterCluster);
101 clusterAssociationMap[pOuterCluster].m_backwardAssociations.insert(pInnerCluster);
102 }
103 }
104}
105
106//------------------------------------------------------------------------------------------------------------------------------------------
107
108bool CrossGapsAssociationAlgorithm::IsExtremalCluster(const bool isForward, const Cluster *const pCurrentCluster, const Cluster *const pTestCluster) const
109{
110 const unsigned int currentLayer(isForward ? pCurrentCluster->GetOuterPseudoLayer() : pCurrentCluster->GetInnerPseudoLayer());
111 const unsigned int testLayer(isForward ? pTestCluster->GetOuterPseudoLayer() : pTestCluster->GetInnerPseudoLayer());
112
113 if (isForward && ((testLayer > currentLayer) || ((testLayer == currentLayer) && LArClusterHelper::SortByNHits(pTestCluster, pCurrentCluster))))
114 return true;
115
116 if (!isForward && ((testLayer < currentLayer) || ((testLayer == currentLayer) && LArClusterHelper::SortByNHits(pTestCluster, pCurrentCluster))))
117 return true;
118
119 return false;
120}
121
122//------------------------------------------------------------------------------------------------------------------------------------------
123
125{
126 if (outerFitResult.GetCluster()->GetInnerPseudoLayer() < innerFitResult.GetCluster()->GetInnerPseudoLayer())
127 throw pandora::StatusCodeException(STATUS_CODE_NOT_ALLOWED);
128
129 if (outerFitResult.GetCluster()->GetInnerPseudoLayer() < innerFitResult.GetCluster()->GetOuterPseudoLayer())
130 return false;
131
132 return (this->IsAssociated(innerFitResult.GetGlobalMaxLayerPosition(), innerFitResult.GetGlobalMaxLayerDirection(), outerFitResult) &&
133 this->IsAssociated(outerFitResult.GetGlobalMinLayerPosition(), outerFitResult.GetGlobalMinLayerDirection() * -1.f, innerFitResult));
134}
135
136//------------------------------------------------------------------------------------------------------------------------------------------
137
139 const CartesianVector &startPosition, const CartesianVector &startDirection, const TwoDSlidingFitResult &targetFitResult) const
140{
141 const HitType hitType(LArClusterHelper::GetClusterHitType(targetFitResult.GetCluster()));
142 unsigned int nSamplingPoints(0), nGapSamplingPoints(0), nMatchedSamplingPoints(0), nUnmatchedSampleRun(0);
143
144 for (unsigned int iSample = 0; iSample < m_maxSamplingPoints; ++iSample)
145 {
146 ++nSamplingPoints;
147 const CartesianVector samplingPoint(startPosition + startDirection * static_cast<float>(iSample) * m_sampleStepSize);
148
149 if (LArGeometryHelper::IsInGap(this->GetPandora(), samplingPoint, hitType, m_gapTolerance))
150 {
151 ++nGapSamplingPoints;
152 nUnmatchedSampleRun = 0; // ATTN Choose to also reset run when entering gap region
153 continue;
154 }
155
156 if (this->IsNearCluster(samplingPoint, targetFitResult))
157 {
158 ++nMatchedSamplingPoints;
159 nUnmatchedSampleRun = 0;
160 }
161 else if (++nUnmatchedSampleRun > m_maxUnmatchedSampleRun)
162 {
163 break;
164 }
165 }
166
167 const float expectation((targetFitResult.GetGlobalMaxLayerPosition() - targetFitResult.GetGlobalMinLayerPosition()).GetMagnitude() / m_sampleStepSize);
168 const float matchedSamplingFraction(expectation > 0.f ? static_cast<float>(nMatchedSamplingPoints) / expectation : 0.f);
169
170 if ((nMatchedSamplingPoints > m_minMatchedSamplingPoints) || (matchedSamplingFraction > m_minMatchedSamplingFraction))
171 return true;
172
173 return false;
174}
175
176//------------------------------------------------------------------------------------------------------------------------------------------
177
178bool CrossGapsAssociationAlgorithm::IsNearCluster(const CartesianVector &samplingPoint, const TwoDSlidingFitResult &targetFitResult) const
179{
180 float rL(std::numeric_limits<float>::max()), rT(std::numeric_limits<float>::max());
181 targetFitResult.GetLocalPosition(samplingPoint, rL, rT);
182
183 CartesianVector fitPosition(0.f, 0.f, 0.f);
184
185 if (STATUS_CODE_SUCCESS == targetFitResult.GetGlobalFitPosition(rL, fitPosition))
186 {
187 if ((fitPosition - samplingPoint).GetMagnitudeSquared() < m_maxOnClusterDistance * m_maxOnClusterDistance)
188 return true;
189 }
190
191 CartesianVector fitPositionAtX(0.f, 0.f, 0.f);
192
193 if (STATUS_CODE_SUCCESS == targetFitResult.GetGlobalFitPositionAtX(samplingPoint.GetX(), fitPositionAtX))
194 {
195 if ((fitPositionAtX - samplingPoint).GetMagnitudeSquared() < m_maxOnClusterDistance * m_maxOnClusterDistance)
196 return true;
197 }
198
199 return false;
200}
201
202//------------------------------------------------------------------------------------------------------------------------------------------
203
205{
206 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinClusterHits", m_minClusterHits));
207
209 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinClusterLayers", m_minClusterLayers));
210
212 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitWindow", m_slidingFitWindow));
213
215 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxSamplingPoints", m_maxSamplingPoints));
216
217 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SampleStepSize", m_sampleStepSize));
218
219 if (m_sampleStepSize < std::numeric_limits<float>::epsilon())
220 {
221 std::cout << "CrossGapsAssociationAlgorithm: Invalid value for SampleStepSize " << m_sampleStepSize << std::endl;
222 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
223 }
224
226 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxUnmatchedSampleRun", m_maxUnmatchedSampleRun));
227
229 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxOnClusterDistance", m_maxOnClusterDistance));
230
231 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
232 XmlHelper::ReadValue(xmlHandle, "MinMatchedSamplingPoints", m_minMatchedSamplingPoints));
233
234 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
235 XmlHelper::ReadValue(xmlHandle, "MinMatchedSamplingFraction", m_minMatchedSamplingFraction));
236
237 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "GapTolerance", m_gapTolerance));
238
240}
241
242} // namespace lar_content
Grouping of header files for many classes of use in particle flow algorithms.
Header file for the cross gaps association algorithm class.
Header file for the cluster helper class.
Header file for the geometry helper class.
#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
unsigned int m_minClusterHits
The minimum allowed number of hits in a clean cluster.
unsigned int m_minClusterLayers
The minimum allowed number of layers for a clean cluster.
unsigned int m_maxSamplingPoints
The maximum number of extension sampling points considered per association check.
unsigned int m_slidingFitWindow
The layer window for the sliding linear fits.
float m_sampleStepSize
The sampling step size used in association checks, units cm.
unsigned int m_minMatchedSamplingPoints
Minimum number of matched sampling points to declare association.
float m_maxOnClusterDistance
The maximum distance between a sampling point and sliding fit to target cluster.
bool IsNearCluster(const pandora::CartesianVector &samplingPoint, const TwoDSlidingFitResult &targetFitResult) const
Whether a sampling point lies near a target 2d sliding fit result.
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 IsAssociated(const pandora::CartesianVector &startPosition, const pandora::CartesianVector &startDirection, const TwoDSlidingFitResult &targetFitResult) const
Sample points along the extrapolation from a starting position to a target fit result to declare clus...
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
unsigned int m_maxUnmatchedSampleRun
The maximum run of unmatched (and non-gap) samples to consider before stopping.
float m_gapTolerance
The tolerance to use when querying whether a sampling point is in a gap, units cm.
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_minMatchedSamplingFraction
Minimum ratio between matched sampling points and expectation to declare association.
void PopulateClusterAssociationMap(const pandora::ClusterVector &clusterVector, ClusterAssociationMap &clusterAssociationMap) const
Populate the cluster association map.
bool AreClustersAssociated(const TwoDSlidingFitResult &innerFitResult, const TwoDSlidingFitResult &outerFitResult) const
Determine whether two clusters are associated.
static bool SortByInnerLayer(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by inner layer, then position, then pulse-height.
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 bool IsInGap(const pandora::Pandora &pandora, const pandora::CartesianVector &testPoint2D, const pandora::HitType hitType, const float gapTolerance=0.f)
Whether a 2D test point lies in a registered gap with the associated hit type.
pandora::CartesianVector GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.
void GetLocalPosition(const pandora::CartesianVector &position, float &rL, float &rT) const
Get local sliding fit coordinates for a given global position.
pandora::StatusCode GetGlobalFitPosition(const float rL, pandora::CartesianVector &position) const
Get global fit position for a given longitudinal coordinate.
pandora::CartesianVector GetGlobalMinLayerDirection() const
Get global direction corresponding to the fit result in minimum fit layer.
pandora::CartesianVector GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
const pandora::Cluster * GetCluster() const
Get the address of the cluster, if originally provided.
pandora::CartesianVector GetGlobalMaxLayerDirection() const
Get global direction corresponding to the fit result in maximum fit layer.
pandora::StatusCode GetGlobalFitPositionAtX(const float x, pandora::CartesianVector &position) const
Get global fit position for a given input x coordinate.
CartesianVector class.
float GetX() const
Get the cartesian x coordinate.
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 Pandora & GetPandora() const
Get the associated pandora instance.
Definition Process.h:116
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::unordered_map< const pandora::Cluster *, TwoDSlidingFitResult > TwoDSlidingFitResultMap
HitType
Calorimeter hit type enum.
std::vector< const Cluster * > ClusterVector
MANAGED_CONTAINER< const Cluster * > ClusterList
StatusCode
The StatusCode enum.