TrackSplittingTool.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArThreeDReco/LArTransverseTrackMatching/TrackSplittingTool.cc
3  *
4  * @brief Implementation of the long tracks tool class.
5  *
6  * $Log: $
7  */
8 
9 #include "Pandora/AlgorithmHeaders.h"
10 
14 
17 
18 using namespace pandora;
19 
20 namespace lar_content
21 {
22 
23 TrackSplittingTool::TrackSplittingTool() :
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 {
41  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
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 
95 void 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 
134 bool 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 
212 bool 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 
230 TrackSplittingTool::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 
244  m_pLongCluster =
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 
259 StatusCode TrackSplittingTool::ReadSettings(const TiXmlHandle xmlHandle)
260 {
261  PANDORA_RETURN_RESULT_IF_AND_IF(
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 
267  PANDORA_RETURN_RESULT_IF_AND_IF(
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 
273  PANDORA_RETURN_RESULT_IF_AND_IF(
274  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxShortDeltaXFraction", m_maxShortDeltaXFraction));
275 
276  PANDORA_RETURN_RESULT_IF_AND_IF(
277  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxAbsoluteShortDeltaX", m_maxAbsoluteShortDeltaX));
278 
279  PANDORA_RETURN_RESULT_IF_AND_IF(
280  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinLongDeltaXFraction", m_minLongDeltaXFraction));
281 
282  PANDORA_RETURN_RESULT_IF_AND_IF(
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
unsigned int m_minMatchedSamplingPoints
The min number of matched sampling points for particle creation.
virtual bool MakeClusterSplits(const SplitPositionMap &splitPositionMap)
Make cluster splits.
Header file for the lar pointing cluster class.
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...
std::vector< TensorType::ElementList::const_iterator > IteratorList
enum cvn::HType HitType
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...
float m_minSplitToVertexProjection
Min projected distance between split position and either inner or outer vertex of long cluster...
const TwoDSlidingFitResult & GetCachedSlidingFitResult(const pandora::Cluster *const pCluster) const
Get a sliding fit result from the algorithm cache.
Header file for the track splitting tool class.
void GetConnectedElements(const pandora::Cluster *const pCluster, const bool ignoreUnavailable, ElementList &elementList) const
Get a list of elements connected to a specified cluster.
const pandora::Cluster * m_pCluster2
Address of short cluster in view 2.
bool Run(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, TensorType &overlapTensor)
Run the algorithm tool.
intermediate_table::const_iterator const_iterator
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_short2MinX
The min x coordinate of short cluster 2.
LArPointingCluster class.
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.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
float m_maxAbsoluteShortDeltaX
Max x distance between ends of two short clusters (measured as an absolute distance) ...
float m_minMatchedFraction
The min matched sampling point fraction for particle creation.
Header file for the geometry helper class.
float m_longMinX
The min x coordinate of the long cluster.
float m_minAbsoluteLongDeltaX
Min x distance between ends of short and long clusters (measured as an absolute distance) ...
float m_maxShortDeltaXFraction
Max x distance between ends of two short clusters (measured as fraction of long cluster x length) ...
Header file for the cluster helper class.
float m_minLongDeltaXFraction
Min x distance between ends of short and long clusters (measured as fraction of long cluster x length...
std::unordered_map< const pandora::Cluster *, pandora::CartesianPointVector > SplitPositionMap
const Vertex & GetInnerVertex() const
Get the inner vertex.
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).
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Header file for the long tracks tool class.
static int max(int a, int b)
void GetSortedKeyClusters(pandora::ClusterVector &sortedKeyClusters) const
Get a sorted vector of key clusters (U clusters with current implementation)
float m_longMaxX
The max x coordinate of the long cluster.
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_short2MaxX
The max x coordinate of short cluster 2.
const pandora::Cluster * m_pCluster1
Address of short cluster in view 1.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
float m_short1MaxX
The max x coordinate of short cluster 1.
float m_minXOverlapFraction
The min x overlap fraction (between long clusters and short cluster vs. shared overlap) ...
unsigned int m_minMatchedSamplingPointRatio
The min ratio between 1st and 2nd highest msps for simple ambiguity resolution.
float m_short1MinX
The min x coordinate of short cluster 1.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
static bool HasLongDirectConnections(IteratorList::const_iterator iIter, const IteratorList &iteratorList)
Whether a long element shares clusters with any other long elements.
XOverlap class.
Definition: LArXOverlap.h:17
float m_maxSplitVsFitPositionDistance
Max allowed distance between split position and sliding linear fit position at the split x coordinate...
pandora::StatusCode GetGlobalFitPositionListAtX(const float x, pandora::CartesianPointVector &positionList) const
Get a list of projected positions for a given input x coordinate.
const pandora::Cluster * m_pLongCluster
Address of the long cluster.
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
Particle(const TensorType::Element &element)
Constructor.
QTextStream & endl(QTextStream &s)