LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
ThreeDKinkBaseTool.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
10 
12 
14 
16 
17 using namespace pandora;
18 
19 namespace lar_content
20 {
21 
22 ThreeDKinkBaseTool::ThreeDKinkBaseTool(const unsigned int nCommonClusters) :
23  m_nCommonClusters(nCommonClusters),
24  m_majorityRulesMode(false),
25  m_minMatchedFraction(0.75f),
26  m_minMatchedSamplingPoints(10),
27  m_minLongitudinalImpactParameter(-1.f),
28  m_nLayersForKinkSearch(10),
29  m_additionalXStepForKinkSearch(0.01f)
30 {
31  if (!((1 == m_nCommonClusters) || (2 == m_nCommonClusters)))
32  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
33 }
34 
35 //------------------------------------------------------------------------------------------------------------------------------------------
36 
38 {
39 }
40 
41 //------------------------------------------------------------------------------------------------------------------------------------------
42 
43 bool ThreeDKinkBaseTool::PassesElementCuts(TensorType::ElementList::const_iterator eIter, const ClusterSet &usedClusters) const
44 {
45  if (usedClusters.count(eIter->GetClusterU()) || usedClusters.count(eIter->GetClusterV()) || usedClusters.count(eIter->GetClusterW()))
46  return false;
47 
48  if (eIter->GetOverlapResult().GetMatchedFraction() < m_minMatchedFraction)
49  return false;
50 
51  if (eIter->GetOverlapResult().GetNMatchedSamplingPoints() < m_minMatchedSamplingPoints)
52  return false;
53 
54  return true;
55 }
56 
57 //------------------------------------------------------------------------------------------------------------------------------------------
58 
59 float ThreeDKinkBaseTool::GetXSamplingPoint(const CartesianVector &splitPosition1, const bool isForwardInX, const TwoDSlidingFitResult &fitResult1,
60  const TwoDSlidingFitResult &fitResult2, const TwoDSlidingFitResult &fitResult3) const
61 {
62  // Nearest common x position
66  fitResult1.GetMinAndMaxX(xMin1, xMax1);
67  fitResult2.GetMinAndMaxX(xMin2, xMax2);
68  fitResult3.GetMinAndMaxX(xMin3, xMax3);
69 
70  const float commonX(isForwardInX ? std::max(xMin1, std::max(xMin2, xMin3)) : std::min(xMax1, std::min(xMax2, xMax3)));
71 
72  if (isForwardInX && ((commonX > xMax1) || (commonX > xMax2) || (commonX > xMax3)))
73  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
74 
75  if (!isForwardInX && ((commonX < xMin1) || (commonX < xMin2) || (commonX < xMin3)))
76  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
77 
78  // Layer step x position
79  float rL1(0.f), rT1(0.f);
80  fitResult1.GetLocalPosition(splitPosition1, rL1, rT1);
81  const int splitLayer(fitResult1.GetLayer(rL1));
82 
83  const int lowLayer(std::max(fitResult1.GetMinLayer(), std::min(fitResult1.GetMaxLayer(), splitLayer - m_nLayersForKinkSearch)));
84  const int highLayer(std::max(fitResult1.GetMinLayer(), std::min(fitResult1.GetMaxLayer(), splitLayer + m_nLayersForKinkSearch)));
85 
86  CartesianVector minus(0.f, 0.f, 0.f), plus(0.f, 0.f, 0.f);
87  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, fitResult1.GetGlobalFitPosition(fitResult1.GetL(lowLayer), minus));
88  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, fitResult1.GetGlobalFitPosition(fitResult1.GetL(highLayer), plus));
89 
90  if (minus.GetX() > plus.GetX())
91  {
92  CartesianVector temporary(minus);
93  minus = plus;
94  plus = temporary;
95  }
96 
97  const float layerStepX(isForwardInX ? plus.GetX() : minus.GetX());
98 
99  // Final x position selection
100  const float chosenX(isForwardInX ? std::max(layerStepX, commonX) : std::min(layerStepX, commonX));
101  const float finalX(isForwardInX ? chosenX + m_additionalXStepForKinkSearch : chosenX - m_additionalXStepForKinkSearch);
102  return finalX;
103 }
104 
105 //------------------------------------------------------------------------------------------------------------------------------------------
106 
107 bool ThreeDKinkBaseTool::IsALowestInX(const LArPointingCluster &pointingClusterA, const LArPointingCluster &pointingClusterB)
108 {
109  if ((pointingClusterA.GetInnerVertex().GetPosition().GetX() < pointingClusterB.GetInnerVertex().GetPosition().GetX()) &&
110  (pointingClusterA.GetInnerVertex().GetPosition().GetX() < pointingClusterB.GetOuterVertex().GetPosition().GetX()) )
111  {
112  return true;
113  }
114 
115  if ((pointingClusterA.GetOuterVertex().GetPosition().GetX() < pointingClusterB.GetInnerVertex().GetPosition().GetX()) &&
116  (pointingClusterA.GetOuterVertex().GetPosition().GetX() < pointingClusterB.GetOuterVertex().GetPosition().GetX()) )
117  {
118  return true;
119  }
120 
121  return false;
122 }
123 
124 //------------------------------------------------------------------------------------------------------------------------------------------
125 
127 {
128  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
129  std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
130 
131  ModificationList modificationList;
132  this->GetModifications(pAlgorithm, overlapTensor, modificationList);
133  const bool changesMade(this->ApplyChanges(pAlgorithm, modificationList));
134 
135  return changesMade;
136 }
137 
138 //------------------------------------------------------------------------------------------------------------------------------------------
139 
140 void ThreeDKinkBaseTool::GetModifications(ThreeDTransverseTracksAlgorithm *const pAlgorithm, const TensorType &overlapTensor, ModificationList &modificationList) const
141 {
142  ClusterSet usedClusters;
143  ClusterVector sortedKeyClusters;
144  overlapTensor.GetSortedKeyClusters(sortedKeyClusters);
145 
146  for (const Cluster *const pKeyCluster : sortedKeyClusters)
147  {
148  if (!pKeyCluster->IsAvailable())
149  continue;
150 
151  unsigned int nU(0), nV(0), nW(0);
152  TensorType::ElementList elementList;
153  overlapTensor.GetConnectedElements(pKeyCluster, true, elementList, nU, nV, nW);
154 
155  if (nU * nV * nW < 2)
156  continue;
157 
158  for (TensorType::ElementList::const_iterator eIter = elementList.begin(); eIter != elementList.end(); ++eIter)
159  {
160  if (!this->PassesElementCuts(eIter, usedClusters))
161  continue;
162 
163  IteratorList iteratorList;
164  this->SelectTensorElements(eIter, elementList, usedClusters, iteratorList);
165 
166  if (iteratorList.size() < 2)
167  continue;
168 
169  ModificationList localModificationList;
170  this->GetIteratorListModifications(pAlgorithm, iteratorList, localModificationList);
171 
172  if (localModificationList.empty())
173  continue;
174 
175  for (ModificationList::const_iterator mIter = localModificationList.begin(), mIterEnd = localModificationList.end(); mIter != mIterEnd; ++mIter)
176  {
177  usedClusters.insert(mIter->m_affectedClusters.begin(), mIter->m_affectedClusters.end());
178  }
179 
180  modificationList.insert(modificationList.end(), localModificationList.begin(), localModificationList.end());
181  }
182  }
183 }
184 
185 //------------------------------------------------------------------------------------------------------------------------------------------
186 
187 bool ThreeDKinkBaseTool::ApplyChanges(ThreeDTransverseTracksAlgorithm *const pAlgorithm, const ModificationList &modificationList) const
188 {
189  ClusterMergeMap consolidatedMergeMap;
190  SplitPositionMap consolidatedSplitMap;
191 
192  for (const Modification &modification : modificationList)
193  {
194  ClusterList parentClusters;
195  for (const auto &mapEntry : modification.m_clusterMergeMap) parentClusters.push_back(mapEntry.first);
196  parentClusters.sort(LArClusterHelper::SortByNHits);
197 
198  for (const Cluster *const pParentCluster : parentClusters)
199  {
200  const ClusterList &daughterClusters(modification.m_clusterMergeMap.at(pParentCluster));
201 
202  for (const Cluster *const pDaughterCluster : daughterClusters)
203  {
204  if (consolidatedMergeMap.count(pDaughterCluster))
205  throw StatusCodeException(STATUS_CODE_FAILURE);
206  }
207 
208  ClusterList &targetClusterList(consolidatedMergeMap[pParentCluster]);
209  targetClusterList.insert(targetClusterList.end(), daughterClusters.begin(), daughterClusters.end());
210  }
211 
212  ClusterList splitClusters;
213  for (const auto &mapEntry : modification.m_splitPositionMap) splitClusters.push_back(mapEntry.first);
214  splitClusters.sort(LArClusterHelper::SortByNHits);
215 
216  for (const Cluster *const pSplitCluster : splitClusters)
217  {
218  const CartesianPointVector &splitPositions(modification.m_splitPositionMap.at(pSplitCluster));
219 
220  CartesianPointVector &cartesianPointVector(consolidatedSplitMap[pSplitCluster]);
221  cartesianPointVector.insert(cartesianPointVector.end(), splitPositions.begin(), splitPositions.end());
222  }
223  }
224 
225  bool changesMade(false);
226  changesMade |= pAlgorithm->MakeClusterMerges(consolidatedMergeMap);
227  changesMade |= pAlgorithm->MakeClusterSplits(consolidatedSplitMap);
228 
229  return changesMade;
230 }
231 
232 //------------------------------------------------------------------------------------------------------------------------------------------
233 
235  const ClusterSet &usedClusters, IteratorList &iteratorList) const
236 {
237  iteratorList.push_back(eIter);
238 
239  for (TensorType::ElementList::const_iterator eIter2 = elementList.begin(); eIter2 != elementList.end(); ++eIter2)
240  {
241  if (eIter == eIter2)
242  continue;
243 
244  if (!this->PassesElementCuts(eIter2, usedClusters))
245  continue;
246 
247  for (IteratorList::const_iterator iIter = iteratorList.begin(); iIter != iteratorList.end(); ++iIter)
248  {
249  if ((*iIter) == eIter2)
250  continue;
251 
252  unsigned int nMatchedClusters(0);
253 
254  if ((*iIter)->GetClusterU() == eIter2->GetClusterU())
255  ++nMatchedClusters;
256 
257  if ((*iIter)->GetClusterV() == eIter2->GetClusterV())
258  ++nMatchedClusters;
259 
260  if ((*iIter)->GetClusterW() == eIter2->GetClusterW())
261  ++nMatchedClusters;
262 
263  if (m_nCommonClusters == nMatchedClusters)
264  {
265  iteratorList.push_back(eIter2);
266  return;
267  }
268  }
269  }
270 }
271 
272 //------------------------------------------------------------------------------------------------------------------------------------------
273 
274 StatusCode ThreeDKinkBaseTool::ReadSettings(const TiXmlHandle xmlHandle)
275 {
276  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
277  "MajorityRulesMode", m_majorityRulesMode));
278 
279  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
280  "MinMatchedFraction", m_minMatchedFraction));
281 
282  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
283  "MinMatchedSamplingPoints", m_minMatchedSamplingPoints));
284 
285  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
286  "MinLongitudinalImpactParameter", m_minLongitudinalImpactParameter));
287 
288  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
289  "NLayersForKinkSearch", m_nLayersForKinkSearch));
290 
291  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
292  "AdditionalXStepForKinkSearch", m_additionalXStepForKinkSearch));
293 
294  return STATUS_CODE_SUCCESS;
295 }
296 
297 } // namespace lar_content
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, then pulse-height.
std::vector< Modification > ModificationList
float GetXSamplingPoint(const pandora::CartesianVector &splitPosition1, const bool isForwardInX, const TwoDSlidingFitResult &fitResult1, const TwoDSlidingFitResult &fitResult2, const TwoDSlidingFitResult &fitResult3) const
Get a sampling point in x that is common to sliding linear fit objects in three views.
std::unordered_map< const pandora::Cluster *, pandora::CartesianPointVector > SplitPositionMap
Header file for the lar pointing cluster class.
virtual bool MakeClusterSplits(const SplitPositionMap &splitPositionMap)
Make cluster splits.
void GetMinAndMaxX(float &minX, float &maxX) const
Get the minimum and maximum x coordinates associated with the sliding fit.
std::vector< TensorType::ElementList::const_iterator > IteratorList
virtual void GetIteratorListModifications(ThreeDTransverseTracksAlgorithm *const pAlgorithm, const IteratorList &iteratorList, ModificationList &modificationList) const =0
Get modification objects for a specific elements of the tensor, identifying required splits and merge...
unsigned int m_nCommonClusters
The number of common clusters.
void GetConnectedElements(const pandora::Cluster *const pCluster, const bool ignoreUnavailable, ElementList &elementList) const
Get a list of elements connected to a specified cluster.
LArPointingCluster class.
virtual ~ThreeDKinkBaseTool()
Destructor.
TFile f
Definition: plotHisto.C:6
Header file for the three d kink base tool.
Int_t max
Definition: plot.C:27
int GetMaxLayer() const
Get the maximum occupied layer in the sliding fit.
bool Run(ThreeDTransverseTracksAlgorithm *const pAlgorithm, TensorType &overlapTensor)
Run the algorithm tool.
intermediate_table::const_iterator const_iterator
int GetMinLayer() const
Get the minimum occupied layer in the sliding fit.
int m_nLayersForKinkSearch
The number of sliding fit layers to step in the kink search.
Header file for the cluster helper class.
pandora::StatusCode GetGlobalFitPosition(const float rL, pandora::CartesianVector &position) const
Get global fit position for a given longitudinal coordinate.
const Vertex & GetOuterVertex() const
Get the outer vertex.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
const Vertex & GetInnerVertex() const
Get the inner vertex.
void SelectTensorElements(TensorType::ElementList::const_iterator eIter, const TensorType::ElementList &elementList, const pandora::ClusterSet &usedClusters, IteratorList &iteratorList) const
Select elements representing possible components of interest due to overshoots or undershoots in clus...
virtual bool PassesElementCuts(TensorType::ElementList::const_iterator eIter, const pandora::ClusterSet &usedClusters) const
Whether a provided (iterator to a) tensor element passes the selection cuts for overshoot identificat...
void GetSortedKeyClusters(pandora::ClusterVector &sortedKeyClusters) const
Get a sorted vector of key clusters (U clusters with current implementation)
static bool IsALowestInX(const LArPointingCluster &pointingClusterA, const LArPointingCluster &pointingClusterB)
Whether pointing cluster labelled A extends to lowest x positions (as opposed to that labelled B) ...
std::vector< art::Ptr< recob::Cluster > > ClusterVector
float m_additionalXStepForKinkSearch
An additional (safety) step to tack-on when choosing x sampling points.
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterMergeMap
Int_t min
Definition: plot.C:26
unsigned int m_minMatchedSamplingPoints
The min number of matched sampling points for use as a key tensor element.
float GetL(const int layer) const
Get longitudinal coordinate for a given sliding linear fit layer number.
bool m_majorityRulesMode
Whether to run in majority rules mode (always split overshoots, always merge undershoots) ...
float m_minLongitudinalImpactParameter
The min longitudinal impact parameter for connecting accompanying clusters.
bool ApplyChanges(ThreeDTransverseTracksAlgorithm *const pAlgorithm, const ModificationList &modificationList) const
Apply the changes cached in a modification list and update the tensor accordingly.
float m_minMatchedFraction
The min matched sampling point fraction for use as a key tensor element.
void GetLocalPosition(const pandora::CartesianVector &position, float &rL, float &rT) const
Get local sliding fit coordinates for a given global position.
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
int GetLayer(const float rL) const
Get layer number for given sliding linear fit longitudinal coordinate.
void GetModifications(ThreeDTransverseTracksAlgorithm *const pAlgorithm, const TensorType &overlapTensor, ModificationList &modificationList) const
Get modification objects, identifying required splits and merges for clusters.
virtual bool MakeClusterMerges(const ClusterMergeMap &clusterMergeMap)
Merge clusters together.