Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
TrackSplittingTool.cc
Go to the documentation of this file.
1
10
14
17
18using namespace pandora;
19
20namespace lar_content
21{
22
24 m_minMatchedFraction(0.75f),
25 m_minMatchedSamplingPoints(10),
26 m_minXOverlapFraction(0.75f),
27 m_minMatchedSamplingPointRatio(2),
28 m_maxShortDeltaXFraction(0.2f),
29 m_maxAbsoluteShortDeltaX(5.f),
30 m_minLongDeltaXFraction(0.2f),
31 m_minAbsoluteLongDeltaX(1.f),
32 m_minSplitToVertexProjection(1.f),
33 m_maxSplitVsFitPositionDistance(1.5f)
34{
35}
36
37//------------------------------------------------------------------------------------------------------------------------------------------
38
40{
42 std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
43
44 SplitPositionMap splitPositionMap;
45 this->FindTracks(pAlgorithm, overlapTensor, splitPositionMap);
46
47 const bool splitsMade(pAlgorithm->MakeClusterSplits(splitPositionMap));
48 return splitsMade;
49}
50
51//------------------------------------------------------------------------------------------------------------------------------------------
52
54 ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const TensorType &overlapTensor, SplitPositionMap &splitPositionMap) const
55{
56 ClusterSet usedClusters;
57 ClusterVector sortedKeyClusters;
58 overlapTensor.GetSortedKeyClusters(sortedKeyClusters);
59
60 for (const Cluster *const pKeyCluster : sortedKeyClusters)
61 {
62 if (!pKeyCluster->IsAvailable())
63 continue;
64
65 unsigned int nU(0), nV(0), nW(0);
66 TensorType::ElementList elementList;
67 overlapTensor.GetConnectedElements(pKeyCluster, true, elementList, nU, nV, nW);
68
69 IteratorList iteratorList;
70 this->SelectElements(elementList, usedClusters, iteratorList);
71
72 for (IteratorList::const_iterator iIter = iteratorList.begin(), iIterEnd = iteratorList.end(); iIter != iIterEnd; ++iIter)
73 {
74 if (LongTracksTool::HasLongDirectConnections(iIter, iteratorList))
75 continue;
76
78 continue;
79
80 if (!this->PassesChecks(pAlgorithm, *(*iIter), true, usedClusters, splitPositionMap) &&
81 !this->PassesChecks(pAlgorithm, *(*iIter), false, usedClusters, splitPositionMap))
82 {
83 continue;
84 }
85
86 usedClusters.insert((*iIter)->GetClusterU());
87 usedClusters.insert((*iIter)->GetClusterV());
88 usedClusters.insert((*iIter)->GetClusterW());
89 }
90 }
91}
92
93//------------------------------------------------------------------------------------------------------------------------------------------
94
95void TrackSplittingTool::SelectElements(const TensorType::ElementList &elementList, const pandora::ClusterSet &usedClusters, IteratorList &iteratorList) const
96{
97 for (TensorType::ElementList::const_iterator eIter = elementList.begin(); eIter != elementList.end(); ++eIter)
98 {
99 if (usedClusters.count(eIter->GetClusterU()) || usedClusters.count(eIter->GetClusterV()) || usedClusters.count(eIter->GetClusterW()))
100 continue;
101
102 if (eIter->GetOverlapResult().GetMatchedFraction() < m_minMatchedFraction)
103 continue;
104
105 if (eIter->GetOverlapResult().GetNMatchedSamplingPoints() < m_minMatchedSamplingPoints)
106 continue;
107
108 const XOverlap &xOverlap(eIter->GetOverlapResult().GetXOverlap());
109 const float longSpan(std::max(xOverlap.GetXSpanU(), std::max(xOverlap.GetXSpanV(), xOverlap.GetXSpanW())));
110 const float shortSpan1(std::min(xOverlap.GetXSpanU(), std::min(xOverlap.GetXSpanV(), xOverlap.GetXSpanW())));
111 const float shortSpan2(
112 ((xOverlap.GetXSpanU() > shortSpan1) && (xOverlap.GetXSpanU() < longSpan))
113 ? xOverlap.GetXSpanU()
114 : ((xOverlap.GetXSpanV() > shortSpan1) && (xOverlap.GetXSpanV() < longSpan)) ? xOverlap.GetXSpanV() : xOverlap.GetXSpanW());
115
116 if ((shortSpan1 < std::numeric_limits<float>::epsilon()) || (longSpan < std::numeric_limits<float>::epsilon()))
117 continue;
118
119 if ((shortSpan1 / xOverlap.GetXOverlapSpan()) < m_minXOverlapFraction)
120 continue;
121
122 if ((shortSpan1 / shortSpan2) < m_minXOverlapFraction)
123 continue;
124
125 if ((shortSpan1 / longSpan) > m_minXOverlapFraction)
126 continue;
127
128 iteratorList.push_back(eIter);
129 }
130}
131
132//------------------------------------------------------------------------------------------------------------------------------------------
133
134bool TrackSplittingTool::PassesChecks(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const TensorType::Element &element,
135 const bool isMinX, ClusterSet &usedClusters, SplitPositionMap &splitPositionMap) const
136{
137 try
138 {
139 const Particle particle(element);
140
141 if (usedClusters.count(particle.m_pLongCluster) || usedClusters.count(particle.m_pCluster1) || usedClusters.count(particle.m_pCluster2))
142 return false;
143
144 const float longXSpan(particle.m_longMaxX - particle.m_longMinX);
145
146 if (longXSpan < std::numeric_limits<float>::epsilon())
147 return false;
148
149 const float splitX(isMinX ? (0.5f * (particle.m_short1MinX + particle.m_short2MinX)) : (0.5f * (particle.m_short1MaxX + particle.m_short2MaxX)));
150 const float shortDeltaX(
151 isMinX ? std::fabs(particle.m_short1MinX - particle.m_short2MinX) : std::fabs(particle.m_short1MaxX - particle.m_short2MaxX));
152 const float longDeltaX(isMinX ? (splitX - particle.m_longMinX) : (particle.m_longMaxX - splitX));
153
154 if (((shortDeltaX / longXSpan) > m_maxShortDeltaXFraction) || (shortDeltaX > m_maxAbsoluteShortDeltaX) ||
155 ((longDeltaX / longXSpan) < m_minLongDeltaXFraction) || (longDeltaX < m_minAbsoluteLongDeltaX))
156 {
157 return false;
158 }
159
160 const LArPointingCluster pointingCluster1(pAlgorithm->GetCachedSlidingFitResult(particle.m_pCluster1));
161 const LArPointingCluster pointingCluster2(pAlgorithm->GetCachedSlidingFitResult(particle.m_pCluster2));
162 const LArPointingCluster longPointingCluster(pAlgorithm->GetCachedSlidingFitResult(particle.m_pLongCluster));
163
164 const CartesianVector &minPos1{
165 pointingCluster1.GetInnerVertex().GetPosition().GetX() < pointingCluster1.GetOuterVertex().GetPosition().GetX()
166 ? pointingCluster1.GetInnerVertex().GetPosition()
167 : pointingCluster1.GetOuterVertex().GetPosition()};
168 const CartesianVector &minPos2{
169 pointingCluster2.GetInnerVertex().GetPosition().GetX() < pointingCluster2.GetOuterVertex().GetPosition().GetX()
170 ? pointingCluster2.GetInnerVertex().GetPosition()
171 : pointingCluster2.GetOuterVertex().GetPosition()};
172 const CartesianVector &maxPos1{
173 pointingCluster1.GetInnerVertex().GetPosition().GetX() > pointingCluster1.GetOuterVertex().GetPosition().GetX()
174 ? pointingCluster1.GetInnerVertex().GetPosition()
175 : pointingCluster1.GetOuterVertex().GetPosition()};
176 const CartesianVector &maxPos2{
177 pointingCluster2.GetInnerVertex().GetPosition().GetX() > pointingCluster2.GetOuterVertex().GetPosition().GetX()
178 ? pointingCluster2.GetInnerVertex().GetPosition()
179 : pointingCluster2.GetOuterVertex().GetPosition()};
180 const CartesianVector position1(isMinX ? minPos1 : maxPos1);
181 const CartesianVector position2(isMinX ? minPos2 : maxPos2);
182
183 CartesianVector splitPosition(0.f, 0.f, 0.f);
184 float chiSquared(std::numeric_limits<float>::max());
186 LArClusterHelper::GetClusterHitType(particle.m_pCluster2), position1, position2, splitPosition, chiSquared);
187
188 if (!this->CheckSplitPosition(splitPosition, splitX, pAlgorithm->GetCachedSlidingFitResult(particle.m_pLongCluster)))
189 return false;
190
191 const CartesianVector splitToInnerVertex(splitPosition - longPointingCluster.GetInnerVertex().GetPosition());
192 const CartesianVector outerVertexToSplit(longPointingCluster.GetOuterVertex().GetPosition() - splitPosition);
193 const CartesianVector outerToInnerUnitVector(
194 (longPointingCluster.GetOuterVertex().GetPosition() - longPointingCluster.GetInnerVertex().GetPosition()).GetUnitVector());
195
196 if ((splitToInnerVertex.GetDotProduct(outerToInnerUnitVector) > m_minSplitToVertexProjection) &&
197 (outerVertexToSplit.GetDotProduct(outerToInnerUnitVector) > m_minSplitToVertexProjection))
198 {
199 splitPositionMap[particle.m_pLongCluster].push_back(splitPosition);
200 return true;
201 }
202 }
203 catch (StatusCodeException &)
204 {
205 }
206
207 return false;
208}
209
210//------------------------------------------------------------------------------------------------------------------------------------------
211
212bool TrackSplittingTool::CheckSplitPosition(const CartesianVector &splitPosition, const float splitX, const TwoDSlidingFitResult &longFitResult) const
213{
214 CartesianPointVector fitPositionList;
215 if (STATUS_CODE_SUCCESS != longFitResult.GetGlobalFitPositionListAtX(splitX, fitPositionList))
216 return false;
217
218 for (CartesianPointVector::const_iterator iter = fitPositionList.begin(), iterEnd = fitPositionList.end(); iter != iterEnd; ++iter)
219 {
220 if ((splitPosition - *iter).GetMagnitude() < m_maxSplitVsFitPositionDistance)
221 return true;
222 }
223
224 return false;
225}
226
227//------------------------------------------------------------------------------------------------------------------------------------------
228//------------------------------------------------------------------------------------------------------------------------------------------
229
230TrackSplittingTool::Particle::Particle(const TensorType::Element &element)
231{
232 const XOverlap &xOverlap(element.GetOverlapResult().GetXOverlap());
233
234 const HitType longHitType =
235 ((xOverlap.GetXSpanU() > xOverlap.GetXSpanV()) && (xOverlap.GetXSpanU() > xOverlap.GetXSpanW()))
236 ? TPC_VIEW_U
237 : ((xOverlap.GetXSpanV() > xOverlap.GetXSpanU()) && (xOverlap.GetXSpanV() > xOverlap.GetXSpanW()))
238 ? TPC_VIEW_V
239 : ((xOverlap.GetXSpanW() > xOverlap.GetXSpanU()) && (xOverlap.GetXSpanW() > xOverlap.GetXSpanV())) ? TPC_VIEW_W : HIT_CUSTOM;
240
241 if (HIT_CUSTOM == longHitType)
242 throw StatusCodeException(STATUS_CODE_FAILURE);
243
245 (TPC_VIEW_U == longHitType) ? element.GetClusterU() : (TPC_VIEW_V == longHitType) ? element.GetClusterV() : element.GetClusterW();
246 m_pCluster1 = (TPC_VIEW_U == longHitType) ? element.GetClusterV() : element.GetClusterU();
247 m_pCluster2 = (TPC_VIEW_W == longHitType) ? element.GetClusterV() : element.GetClusterW();
248 m_longMinX = (TPC_VIEW_U == longHitType) ? xOverlap.GetUMinX() : (TPC_VIEW_V == longHitType) ? xOverlap.GetVMinX() : xOverlap.GetWMinX();
249 m_longMaxX = (TPC_VIEW_U == longHitType) ? xOverlap.GetUMaxX() : (TPC_VIEW_V == longHitType) ? xOverlap.GetVMaxX() : xOverlap.GetWMaxX();
250 m_short1MinX = (TPC_VIEW_U == longHitType) ? xOverlap.GetVMinX() : xOverlap.GetUMinX();
251 m_short1MaxX = (TPC_VIEW_U == longHitType) ? xOverlap.GetVMaxX() : xOverlap.GetUMaxX();
252 m_short2MinX = (TPC_VIEW_W == longHitType) ? xOverlap.GetVMinX() : xOverlap.GetWMinX();
253 m_short2MaxX = (TPC_VIEW_W == longHitType) ? xOverlap.GetVMaxX() : xOverlap.GetWMaxX();
254}
255
256//------------------------------------------------------------------------------------------------------------------------------------------
257//------------------------------------------------------------------------------------------------------------------------------------------
258
260{
262 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinMatchedFraction", m_minMatchedFraction));
263
264 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
265 XmlHelper::ReadValue(xmlHandle, "MinMatchedSamplingPoints", m_minMatchedSamplingPoints));
266
268 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinXOverlapFraction", m_minXOverlapFraction));
269
270 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
271 XmlHelper::ReadValue(xmlHandle, "MinMatchedSamplingPointRatio", m_minMatchedSamplingPointRatio));
272
274 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxShortDeltaXFraction", m_maxShortDeltaXFraction));
275
277 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxAbsoluteShortDeltaX", m_maxAbsoluteShortDeltaX));
278
280 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinLongDeltaXFraction", m_minLongDeltaXFraction));
281
283 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinAbsoluteLongDeltaX", m_minAbsoluteLongDeltaX));
284
285 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
286 XmlHelper::ReadValue(xmlHandle, "MinSplitToVertexProjection", m_minSplitToVertexProjection));
287
288 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
289 XmlHelper::ReadValue(xmlHandle, "MaxSplitVsFitPositionDistance", m_maxSplitVsFitPositionDistance));
290
291 return STATUS_CODE_SUCCESS;
292}
293
294} // 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 lar pointing cluster class.
Header file for the long tracks tool class.
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
Definition StatusCodes.h:31
Header file for the track splitting tool class.
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 float MergeTwoPositions(const pandora::Pandora &pandora, const pandora::HitType view1, const pandora::HitType view2, const float position1, const float position2)
Merge two views (U,V) to give a third view (Z).
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
LArPointingCluster class.
const Vertex & GetInnerVertex() const
Get the inner vertex.
const Vertex & GetOuterVertex() const
Get the outer vertex.
static bool HasLongDirectConnections(IteratorList::const_iterator iIter, const IteratorList &iteratorList)
Whether a long element shares clusters with any other long elements.
static bool IsLongerThanDirectConnections(IteratorList::const_iterator iIter, const TensorType::ElementList &elementList, const unsigned int minMatchedSamplingPointRatio, const pandora::ClusterSet &usedClusters)
Whether a long element is significantly longer that other elements with which it shares a cluster.
virtual bool MakeClusterSplits(const SplitPositionMap &splitPositionMap)
Make cluster splits.
const TwoDSlidingFitResult & GetCachedSlidingFitResult(const pandora::Cluster *const pCluster) const
Get a sliding fit result from the algorithm cache.
const pandora::Cluster * m_pCluster1
Address of short cluster in view 1.
const pandora::Cluster * m_pCluster2
Address of short cluster in view 2.
float m_short2MinX
The min x coordinate of short cluster 2.
float m_short2MaxX
The max x coordinate of short cluster 2.
float m_short1MaxX
The max x coordinate of short cluster 1.
float m_short1MinX
The min x coordinate of short cluster 1.
float m_longMaxX
The max x coordinate of the long cluster.
float m_longMinX
The min x coordinate of the long cluster.
const pandora::Cluster * m_pLongCluster
Address of the long cluster.
Particle(const TensorType::Element &element)
Constructor.
float m_minMatchedFraction
The min matched sampling point fraction for particle creation.
unsigned int m_minMatchedSamplingPointRatio
The min ratio between 1st and 2nd highest msps for simple ambiguity resolution.
float m_maxShortDeltaXFraction
Max x distance between ends of two short clusters (measured as fraction of long cluster x length)
float m_minXOverlapFraction
The min x overlap fraction (between long clusters and short cluster vs. shared overlap)
void FindTracks(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const TensorType &overlapTensor, SplitPositionMap &splitPositionMap) const
Find remaining tracks, hidden by spurious track segments (and maybe other ambiguities) in the tensor.
float m_minAbsoluteLongDeltaX
Min x distance between ends of short and long clusters (measured as an absolute distance)
float m_minSplitToVertexProjection
Min projected distance between split position and either inner or outer vertex of long cluster.
float m_minLongDeltaXFraction
Min x distance between ends of short and long clusters (measured as fraction of long cluster x length...
float m_maxAbsoluteShortDeltaX
Max x distance between ends of two short clusters (measured as an absolute distance)
bool PassesChecks(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const TensorType::Element &element, const bool isMinX, pandora::ClusterSet &usedClusters, SplitPositionMap &splitPositionMap) const
Whether a provided tensor element can be used to construct a pfo.
float m_maxSplitVsFitPositionDistance
Max allowed distance between split position and sliding linear fit position at the split x coordinate...
bool CheckSplitPosition(const pandora::CartesianVector &splitPosition, const float splitX, const TwoDSlidingFitResult &longFitResult) const
Check a candidate split position for consistency with the associated track cluster sliding linear fit...
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
bool Run(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, TensorType &overlapTensor)
Run the algorithm tool.
void SelectElements(const TensorType::ElementList &elementList, const pandora::ClusterSet &usedClusters, IteratorList &iteratorList) const
Select a list of the relevant elements from a set of connected tensor elements.
unsigned int m_minMatchedSamplingPoints
The min number of matched sampling points for particle creation.
TrackSplittingTool()
Default constructor.
ThreeViewTransverseTracksAlgorithm::MatchingType::TensorType TensorType
std::vector< TensorType::ElementList::const_iterator > IteratorList
pandora::StatusCode GetGlobalFitPositionListAtX(const float x, pandora::CartesianPointVector &positionList) const
Get a list of projected positions for a given input x coordinate.
XOverlap class.
Definition LArXOverlap.h:18
float GetUMinX() const
Get the min x value in the u view.
float GetXSpanV() const
Get the x span in the v view.
float GetWMaxX() const
Get the max x value in the w view.
float GetXOverlapSpan() const
Get the x overlap span.
float GetWMinX() const
Get the min x value in the w view.
float GetVMinX() const
Get the min x value in the v view.
float GetXSpanW() const
Get the x span in the w view.
float GetUMaxX() const
Get the max x value in the u view.
float GetVMaxX() const
Get the max x value in the v view.
float GetXSpanU() const
Get the x span in the u view.
CartesianVector class.
float GetX() const
Get the cartesian x coordinate.
float GetDotProduct(const CartesianVector &rhs) const
Get the dot product of the cartesian vector with a second cartesian vector.
Cluster class.
Definition Cluster.h:31
bool ShouldDisplayAlgorithmInfo() const
Whether to display algorithm information during processing.
const std::string & GetType() const
Get the type.
Definition Process.h:102
const Pandora & GetPandora() const
Get the associated pandora instance.
Definition Process.h:116
const std::string & GetInstanceName() const
Get the instance name.
Definition Process.h:109
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 *, pandora::CartesianPointVector > SplitPositionMap
HitType
Calorimeter hit type enum.
std::vector< const Cluster * > ClusterVector
std::vector< CartesianVector > CartesianPointVector
std::unordered_set< const Cluster * > ClusterSet
StatusCode
The StatusCode enum.