LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
DeltaRayExtensionAlgorithm.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
10 
12 
14 
15 using namespace pandora;
16 
17 namespace lar_content
18 {
19 
20 DeltaRayExtensionAlgorithm::DeltaRayExtensionAlgorithm() :
21  m_minClusterLength(1.f),
22  m_maxClusterLength(10.f),
23  m_maxLongitudinalDisplacement(2.5f),
24  m_maxTransverseDisplacement(1.5f)
25 {
26 }
27 
28 //------------------------------------------------------------------------------------------------------------------------------------------
29 
30 void DeltaRayExtensionAlgorithm::GetListOfCleanClusters(const ClusterList *const pClusterList, ClusterVector &clusterVector) const
31 {
32  for (ClusterList::const_iterator iter = pClusterList->begin(), iterEnd = pClusterList->end(); iter != iterEnd; ++iter)
33  {
34  const Cluster *const pCluster = *iter;
35 
37  continue;
38 
39  clusterVector.push_back(pCluster);
40  }
41 
42  std::sort(clusterVector.begin(), clusterVector.end(), LArClusterHelper::SortByNHits);
43 }
44 
45 //------------------------------------------------------------------------------------------------------------------------------------------
46 
47 void DeltaRayExtensionAlgorithm::FillClusterAssociationMatrix(const ClusterVector &clusterVector, ClusterAssociationMatrix &clusterAssociationMatrix) const
48 {
49  ClusterToCoordinateMap innerCoordinateMap, outerCoordinateMap;
50 
51  for (const Cluster *const pParentCluster : clusterVector)
52  {
53  for (const Cluster *const pDaughterCluster : clusterVector)
54  {
55  if (pParentCluster == pDaughterCluster)
56  continue;
57 
58  this->FillClusterAssociationMatrix(pParentCluster, pDaughterCluster, innerCoordinateMap, outerCoordinateMap, clusterAssociationMatrix);
59  }
60  }
61 }
62 
63 //------------------------------------------------------------------------------------------------------------------------------------------
64 
65 void DeltaRayExtensionAlgorithm::GetExtremalCoordinatesFromCache(const Cluster *const pCluster, ClusterToCoordinateMap &innerCoordinateMap,
66  ClusterToCoordinateMap &outerCoordinateMap, CartesianVector &innerCoordinate, CartesianVector &outerCoordinate) const
67 {
68  ClusterToCoordinateMap::const_iterator innerIter = innerCoordinateMap.find(pCluster);
69  ClusterToCoordinateMap::const_iterator outerIter = outerCoordinateMap.find(pCluster);
70 
71  if ((innerCoordinateMap.end() == innerIter) || (outerCoordinateMap.end() == outerIter))
72  {
73  LArClusterHelper::GetExtremalCoordinates(pCluster, innerCoordinate, outerCoordinate);
74  (void) innerCoordinateMap.insert(ClusterToCoordinateMap::value_type(pCluster, innerCoordinate));
75  (void) outerCoordinateMap.insert(ClusterToCoordinateMap::value_type(pCluster, outerCoordinate));
76  }
77  else
78  {
79  innerCoordinate = innerIter->second;
80  outerCoordinate = outerIter->second;
81  }
82 }
83 
84 //------------------------------------------------------------------------------------------------------------------------------------------
85 
86 void DeltaRayExtensionAlgorithm::FillClusterAssociationMatrix(const Cluster *const pParentCluster, const Cluster *const pDaughterCluster,
87  ClusterToCoordinateMap &innerCoordinateMap, ClusterToCoordinateMap &outerCoordinateMap, ClusterAssociationMatrix &clusterAssociationMatrix) const
88 {
89  // Daughter cluster must be available for any association to proceed
90  if (!PandoraContentApi::IsAvailable(*this, pDaughterCluster))
91  return;
92 
93  // Weak association: between parent cosmic-ray muon and daughter delta ray
94  // Strong association: between parent and daughter fragments of delta ray
95  // Figure of merit: distance between parent and daughter clusters
96  CartesianVector innerCoordinateP(0.f, 0.f, 0.f), outerCoordinateP(0.f, 0.f, 0.f);
97  this->GetExtremalCoordinatesFromCache(pParentCluster, innerCoordinateMap, outerCoordinateMap, innerCoordinateP, outerCoordinateP);
98 
99  CartesianVector innerCoordinateD(0.f, 0.f, 0.f), outerCoordinateD(0.f, 0.f, 0.f);
100  this->GetExtremalCoordinatesFromCache(pDaughterCluster, innerCoordinateMap, outerCoordinateMap, innerCoordinateD, outerCoordinateD);
101 
102  for (unsigned int useInnerD = 0; useInnerD < 2; ++useInnerD)
103  {
104  const CartesianVector daughterVertex(useInnerD == 1 ? innerCoordinateD : outerCoordinateD);
105  const CartesianVector daughterEnd(useInnerD == 1 ? outerCoordinateD : innerCoordinateD);
106 
107  const float daughterLengthSquared((daughterEnd - daughterVertex).GetMagnitudeSquared());
108 
109  // Daughter cluster must be available and below a length cut for any association
110  if (daughterLengthSquared > m_maxClusterLength * m_maxClusterLength)
111  continue;
112 
113  const CartesianVector projectedVertex(LArClusterHelper::GetClosestPosition(daughterVertex, pParentCluster));
114 
115  const float daughterVertexDistanceSquared((projectedVertex - daughterVertex).GetMagnitudeSquared());
116  const float daughterEndDistanceSquared((projectedVertex - daughterEnd).GetMagnitudeSquared());
117 
118  // Cut on proximity of daughter cluster to parent cluster
119  if (daughterVertexDistanceSquared > std::min(m_maxLongitudinalDisplacement * m_maxLongitudinalDisplacement,
120  std::min(daughterEndDistanceSquared, daughterLengthSquared)))
121  continue;
122 
123  const ClusterAssociation::VertexType daughterVertexType(useInnerD == 1 ? ClusterAssociation::INNER : ClusterAssociation::OUTER);
124  const float figureOfMerit(daughterVertexDistanceSquared);
125 
128 
129  for (unsigned int useInnerP = 0; useInnerP < 2; ++useInnerP)
130  {
131  const CartesianVector parentVertex(useInnerP == 1 ? innerCoordinateP : outerCoordinateP);
132  const CartesianVector parentEnd(useInnerP == 1 ? outerCoordinateP : innerCoordinateP);
133 
134  const float parentVertexDistanceSquared((projectedVertex - parentVertex).GetMagnitudeSquared());
135  const float parentEndDistanceSquared((projectedVertex - parentEnd).GetMagnitudeSquared());
136  const float parentLengthSquared((parentEnd - parentVertex).GetMagnitudeSquared());
137 
138  if (parentVertexDistanceSquared < parentEndDistanceSquared)
139  parentVertexType = (useInnerP == 1 ? ClusterAssociation::INNER : ClusterAssociation::OUTER);
140 
141  // Parent cluster must be available and below a length cut for a strong association
142  if (!PandoraContentApi::IsAvailable(*this, pParentCluster) || parentLengthSquared > m_maxClusterLength * m_maxClusterLength)
143  continue;
144 
145  // Require an end-to-end join between parent and daughter cluster
146  if (parentVertexDistanceSquared > std::min(m_maxTransverseDisplacement * m_maxTransverseDisplacement,
147  std::min(parentEndDistanceSquared, daughterEndDistanceSquared)))
148  continue;
149 
150  // Cut on pointing information
151  const CartesianVector daughterDirection((daughterEnd - daughterVertex).GetUnitVector());
152  const CartesianVector parentDirection((parentEnd - projectedVertex).GetUnitVector());
153 
154  const float forwardDistance(daughterDirection.GetDotProduct((daughterVertex - projectedVertex)));
155  const float sidewaysDistance(daughterDirection.GetCrossProduct((daughterVertex - projectedVertex)).GetMagnitude());
156 
157  if (forwardDistance < 0.f || forwardDistance > m_maxLongitudinalDisplacement || sidewaysDistance > m_maxTransverseDisplacement)
158  continue;
159 
160  if (-parentDirection.GetDotProduct(daughterDirection) < 0.25f)
161  continue;
162 
163  associationType = ClusterAssociation::STRONG;
164  break;
165  }
166 
167  if (parentVertexType > ClusterAssociation::UNDEFINED)
168  {
169  (void) clusterAssociationMatrix[pParentCluster].insert(ClusterAssociationMap::value_type(pDaughterCluster,
170  ClusterAssociation(parentVertexType, daughterVertexType, associationType, figureOfMerit)));
171  }
172  }
173 }
174 
175 //------------------------------------------------------------------------------------------------------------------------------------------
176 
177 void DeltaRayExtensionAlgorithm::FillClusterMergeMap(const ClusterAssociationMatrix &parentToDaughterMatrix, ClusterMergeMap &clusterMergeMap) const
178 {
179  // Merge parent and daughter clusters if they are strongly associated
180  // and the associations have the best figures of merit
181  // (i.e. the P --> D association is the best P --> X association,
182  // and the P <-- D association is the best X <-- D association).
183  ClusterAssociationMatrix daughterToParentMatrix;
184 
185  ClusterVector sortedParentClusters;
186  for (const auto &mapEntry : parentToDaughterMatrix) sortedParentClusters.push_back(mapEntry.first);
187  std::sort(sortedParentClusters.begin(), sortedParentClusters.end(), LArClusterHelper::SortByNHits);
188 
189  for (const Cluster *const pParentCluster : sortedParentClusters)
190  {
191  const ClusterAssociationMap &daughterToAssociationMap(parentToDaughterMatrix.at(pParentCluster));
192 
193  ClusterVector sortedLocalDaughterClusters;
194  for (const auto &mapEntry : daughterToAssociationMap) sortedLocalDaughterClusters.push_back(mapEntry.first);
195  std::sort(sortedLocalDaughterClusters.begin(), sortedLocalDaughterClusters.end(), LArClusterHelper::SortByNHits);
196 
197  for (const Cluster *const pDaughterCluster : sortedLocalDaughterClusters)
198  {
199  const ClusterAssociation &clusterAssociation(daughterToAssociationMap.at(pDaughterCluster));
200  (void) daughterToParentMatrix[pDaughterCluster].insert(ClusterAssociationMap::value_type(pParentCluster, clusterAssociation));
201  }
202  }
203 
204 
205  ClusterAssociationMatrix reducedParentToDaughterMatrix;
206 
207  ClusterVector sortedDaughterClusters;
208  for (const auto &mapEntry : daughterToParentMatrix) sortedDaughterClusters.push_back(mapEntry.first);
209  std::sort(sortedDaughterClusters.begin(), sortedDaughterClusters.end(), LArClusterHelper::SortByNHits);
210 
211  // Loop over parent clusters and select nearby daughter clusters that are closer than another parent cluster
212  for (const Cluster *const pDaughterCluster : sortedDaughterClusters)
213  {
214  const ClusterAssociationMap &parentToAssociationMap(daughterToParentMatrix.at(pDaughterCluster));
215 
216  const Cluster *pBestInner(NULL);
217  const Cluster *pBestOuter(NULL);
218 
219  float bestFomInner(std::numeric_limits<float>::max());
220  float bestFomOuter(std::numeric_limits<float>::max());
221 
222  ClusterVector sortedLocalParentClusters;
223  for (const auto &mapEntry : parentToAssociationMap) sortedLocalParentClusters.push_back(mapEntry.first);
224  std::sort(sortedLocalParentClusters.begin(), sortedLocalParentClusters.end(), LArClusterHelper::SortByNHits);
225 
226  for (const Cluster *const pParentCluster : sortedLocalParentClusters)
227  {
228  const ClusterAssociation &clusterAssociation(parentToAssociationMap.at(pParentCluster));
229 
230  if (clusterAssociation.GetParent() == ClusterAssociation::INNER)
231  {
232  if (clusterAssociation.GetFigureOfMerit() < bestFomInner)
233  {
234  bestFomInner = clusterAssociation.GetFigureOfMerit();
235 
236  if (clusterAssociation.GetAssociation() == ClusterAssociation::STRONG)
237  {
238  pBestInner = pParentCluster;
239  }
240  else
241  {
242  pBestInner = NULL;
243  }
244  }
245  }
246 
247  if (clusterAssociation.GetParent() == ClusterAssociation::OUTER)
248  {
249  if (clusterAssociation.GetFigureOfMerit() < bestFomOuter)
250  {
251  bestFomOuter = clusterAssociation.GetFigureOfMerit();
252 
253  if (clusterAssociation.GetAssociation() == ClusterAssociation::STRONG)
254  {
255  pBestOuter = pParentCluster;
256  }
257  else
258  {
259  pBestOuter = NULL;
260  }
261  }
262  }
263  }
264 
265  if (pBestInner)
266  {
267  ClusterAssociationMatrix::const_iterator iter3A = parentToDaughterMatrix.find(pBestInner);
268 
269  if (parentToDaughterMatrix.end() == iter3A)
270  throw pandora::StatusCodeException(STATUS_CODE_FAILURE);
271 
272  const ClusterAssociationMap &parentToDaughterMap(iter3A->second);
273  ClusterAssociationMap::const_iterator iter3B = parentToDaughterMap.find(pDaughterCluster);
274 
275  if (parentToDaughterMap.end() == iter3B)
276  throw pandora::StatusCodeException(STATUS_CODE_FAILURE);
277 
278  const ClusterAssociation &bestAssociationInner(iter3B->second);
279  (void) reducedParentToDaughterMatrix[pBestInner].insert(ClusterAssociationMap::value_type(pDaughterCluster, bestAssociationInner));
280  }
281 
282  if (pBestOuter)
283  {
284  ClusterAssociationMatrix::const_iterator iter3A = parentToDaughterMatrix.find(pBestOuter);
285 
286  if (parentToDaughterMatrix.end() == iter3A)
287  throw pandora::StatusCodeException(STATUS_CODE_FAILURE);
288 
289  const ClusterAssociationMap &parentToDaughterMap(iter3A->second);
290  ClusterAssociationMap::const_iterator iter3B = parentToDaughterMap.find(pDaughterCluster);
291 
292  if (parentToDaughterMap.end() == iter3B)
293  throw pandora::StatusCodeException(STATUS_CODE_FAILURE);
294 
295  const ClusterAssociation &bestAssociationOuter(iter3B->second);
296  (void) reducedParentToDaughterMatrix[pBestOuter].insert(ClusterAssociationMap::value_type(pDaughterCluster, bestAssociationOuter));
297  }
298  }
299 
300 
301  ClusterVector sortedReducedParentClusters;
302  for (const auto &mapEntry : reducedParentToDaughterMatrix) sortedReducedParentClusters.push_back(mapEntry.first);
303  std::sort(sortedReducedParentClusters.begin(), sortedReducedParentClusters.end(), LArClusterHelper::SortByNHits);
304 
305  for (const Cluster *const pParentCluster : sortedReducedParentClusters)
306  {
307  const ClusterAssociationMap &daughterToAssociationMap(reducedParentToDaughterMatrix.at(pParentCluster));
308 
309  const Cluster *pBestInner(NULL);
310  const Cluster *pBestOuter(NULL);
311 
312  float bestFomInner(std::numeric_limits<float>::max());
313  float bestFomOuter(std::numeric_limits<float>::max());
314 
315  ClusterVector sortedLocalDaughterClusters;
316  for (const auto &mapEntry : daughterToAssociationMap) sortedLocalDaughterClusters.push_back(mapEntry.first);
317  std::sort(sortedLocalDaughterClusters.begin(), sortedLocalDaughterClusters.end(), LArClusterHelper::SortByNHits);
318 
319  for (const Cluster *const pDaughterCluster : sortedLocalDaughterClusters)
320  {
321  const ClusterAssociation &clusterAssociation(daughterToAssociationMap.at(pDaughterCluster));
322 
323  if (clusterAssociation.GetParent() == ClusterAssociation::INNER)
324  {
325  if (clusterAssociation.GetFigureOfMerit() < bestFomInner)
326  {
327  bestFomInner = clusterAssociation.GetFigureOfMerit();
328 
329  if (clusterAssociation.GetAssociation() == ClusterAssociation::STRONG)
330  {
331  pBestInner = pDaughterCluster;
332  }
333  else
334  {
335  pBestInner = NULL;
336  }
337  }
338  }
339 
340  if (clusterAssociation.GetParent() == ClusterAssociation::OUTER)
341  {
342  if (clusterAssociation.GetFigureOfMerit() < bestFomOuter)
343  {
344  bestFomOuter = clusterAssociation.GetFigureOfMerit();
345 
346  if (clusterAssociation.GetAssociation() == ClusterAssociation::STRONG)
347  {
348  pBestOuter = pDaughterCluster;
349  }
350  else
351  {
352  pBestOuter = NULL;
353  }
354  }
355  }
356  }
357 
358  if (pBestInner)
359  {
360  ClusterList &parentList(clusterMergeMap[pParentCluster]);
361 
362  if (parentList.end() == std::find(parentList.begin(), parentList.end(), pBestInner))
363  parentList.push_back(pBestInner);
364 
365  ClusterList &bestInnerList(clusterMergeMap[pBestInner]);
366 
367  if (bestInnerList.end() == std::find(bestInnerList.begin(), bestInnerList.end(), pParentCluster))
368  bestInnerList.push_back(pParentCluster);
369  }
370 
371  if (pBestOuter)
372  {
373  ClusterList &parentList(clusterMergeMap[pParentCluster]);
374 
375  if (parentList.end() == std::find(parentList.begin(), parentList.end(), pBestOuter))
376  parentList.push_back(pBestOuter);
377 
378  ClusterList &bestOuterList(clusterMergeMap[pBestOuter]);
379 
380  if (bestOuterList.end() == std::find(bestOuterList.begin(), bestOuterList.end(), pParentCluster))
381  bestOuterList.push_back(pParentCluster);
382  }
383  }
384 }
385 
386 //------------------------------------------------------------------------------------------------------------------------------------------
387 
388 StatusCode DeltaRayExtensionAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
389 {
390  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
391  "MinClusterLength", m_minClusterLength));
392 
393  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
394  "MaxClusterLength", m_maxClusterLength));
395 
396  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
397  "MaxLongitudinalDisplacement", m_maxLongitudinalDisplacement));
398 
399  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
400  "MaxTransverseDisplacement", m_maxTransverseDisplacement));
401 
402  return ClusterExtensionAlgorithm::ReadSettings(xmlHandle);
403 }
404 
405 } // 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::unordered_map< const pandora::Cluster *, ClusterAssociationMap > ClusterAssociationMatrix
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
TFile f
Definition: plotHisto.C:6
Header file for the delta ray extension algorithm class.
Int_t max
Definition: plot.C:27
intermediate_table::const_iterator const_iterator
Header file for the cluster helper class.
std::unordered_map< const pandora::Cluster *, pandora::CartesianVector > ClusterToCoordinateMap
void FillClusterMergeMap(const ClusterAssociationMatrix &clusterAssociationMatrix, ClusterMergeMap &clusterMergeMap) const
Fill the cluster merge map.
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...
std::vector< art::Ptr< recob::Cluster > > ClusterVector
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterMergeMap
static void GetExtremalCoordinates(const pandora::ClusterList &clusterList, pandora::CartesianVector &innerCoordinate, pandora::CartesianVector &outerCoordinate)
Get positions of the two most distant calo hits in a list of cluster (ordered by Z) ...
Int_t min
Definition: plot.C:26
void GetExtremalCoordinatesFromCache(const pandora::Cluster *const pCluster, ClusterToCoordinateMap &innerCoordinateMap, ClusterToCoordinateMap &outerCoordinateMap, pandora::CartesianVector &innerCoordinate, pandora::CartesianVector &outerCoordinate) const
Reduce number of extremal coordinates calculations by caching results when they are first obtained...
void FillClusterAssociationMatrix(const pandora::ClusterVector &clusterVector, ClusterAssociationMatrix &clusterAssociationMatrix) const
Fill the cluster association matrix.
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
static pandora::CartesianVector GetClosestPosition(const pandora::CartesianVector &position, const pandora::ClusterList &clusterList)
Get closest position in a list of clusters to a specified input position vector.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap