NViewDeltaRayMatchingAlgorithm.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArThreeDReco/LArCosmicRay/NViewDeltaRayMatchingAlgorithm.cc
3  *
4  * @brief Implementation of the three view delta ray matching class
5  *
6  * $Log: $
7  */
8 
9 #include "Pandora/AlgorithmHeaders.h"
10 
15 
19 
21 
24 
26 
27 using namespace pandora;
28 
29 namespace lar_content
30 {
31 
32 template <typename T>
34  m_pseudoChi2Cut(1.5f),
35  m_xOverlapWindow(1.f),
36  m_minMatchedFraction(0.5),
37  m_minMatchedPoints(3),
38  m_minProjectedPositions(3),
39  m_maxCosmicRayHitFraction(0.05f),
40  m_maxDistanceToCluster(0.5f),
41  m_maxDistanceToReferencePoint(5.f),
42  m_strayClusterSeparation(2.f)
43 {
44 }
45 
46 //------------------------------------------------------------------------------------------------------------------------------------------
47 
48 template <typename T>
49 void NViewDeltaRayMatchingAlgorithm<T>::SelectInputClusters(const ClusterList *const pInputClusterList, ClusterList &selectedClusterList) const
50 {
51  for (const Cluster *const pCluster : *pInputClusterList)
52  {
53  if ((pCluster->IsAvailable()) && (this->DoesClusterPassTensorThreshold(pCluster)))
54  selectedClusterList.push_back(pCluster);
55  }
56 }
57 
58 //------------------------------------------------------------------------------------------------------------------------------------------
59 
60 template <typename T>
61 void NViewDeltaRayMatchingAlgorithm<T>::PrepareInputClusters(ClusterList &preparedClusterList)
62 {
63  if (preparedClusterList.empty())
64  return;
65 
66  const PfoList *pMuonPfoList(nullptr);
67 
68  PANDORA_THROW_RESULT_IF_AND_IF(
69  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, m_muonPfoListName, pMuonPfoList));
70 
71  if ((!pMuonPfoList) || pMuonPfoList->empty())
72  return;
73 
74  const HitType hitType(LArClusterHelper::GetClusterHitType(preparedClusterList.front()));
75 
77 
78  this->FillStrayClusterList(LArClusterHelper::GetClusterHitType(preparedClusterList.front()));
79 }
80 
81 //------------------------------------------------------------------------------------------------------------------------------------------
82 
83 template <typename T>
85 {
86  const ClusterList &inputClusterList(this->GetInputClusterList(hitType));
87  ClusterList &strayClusterList((hitType == TPC_VIEW_U) ? m_strayClusterListU : (hitType == TPC_VIEW_V) ? m_strayClusterListV : m_strayClusterListW);
88 
89  for (const Cluster *const pCluster : inputClusterList)
90  {
91  if ((pCluster->IsAvailable()) && (!this->DoesClusterPassTensorThreshold(pCluster)))
92  strayClusterList.push_back(pCluster);
93  }
94 }
95 
96 //------------------------------------------------------------------------------------------------------------------------------------------
97 
98 template <typename T>
99 StatusCode NViewDeltaRayMatchingAlgorithm<T>::GetMuonCluster(const PfoList &commonMuonPfoList, const HitType hitType, const Cluster *&pMuonCluster) const
100 {
101  if (commonMuonPfoList.size() != 1)
102  return STATUS_CODE_NOT_FOUND;
103 
104  ClusterList muonClusterList;
105  LArPfoHelper::GetClusters(commonMuonPfoList.front(), hitType, muonClusterList);
106 
107  if (muonClusterList.size() != 1)
108  return STATUS_CODE_NOT_FOUND;
109 
110  pMuonCluster = muonClusterList.front();
111 
112  return STATUS_CODE_SUCCESS;
113 }
114 
115 //------------------------------------------------------------------------------------------------------------------------------------------
116 
117 template <typename T>
118 void NViewDeltaRayMatchingAlgorithm<T>::GetNearbyMuonPfos(const Cluster *const pCluster, ClusterList &consideredClusters, PfoList &nearbyMuonPfos) const
119 {
120  const HitType hitType(LArClusterHelper::GetClusterHitType(pCluster));
123 
124  consideredClusters.push_back(pCluster);
125 
126  const DeltaRayMatchingContainers::ClusterProximityMap::const_iterator clusterProximityIter(clusterProximityMap.find(pCluster));
127 
128  if (clusterProximityIter == clusterProximityMap.end())
129  return;
130 
131  for (const Cluster *const pNearbyCluster : clusterProximityIter->second)
132  {
133  if (std::find(consideredClusters.begin(), consideredClusters.end(), pNearbyCluster) != consideredClusters.end())
134  continue;
135 
136  const DeltaRayMatchingContainers::ClusterToPfoMap::const_iterator pfoIter(clusterToPfoMap.find(pNearbyCluster));
137 
138  if (pfoIter != clusterToPfoMap.end())
139  {
140  if (std::find(nearbyMuonPfos.begin(), nearbyMuonPfos.end(), pfoIter->second) == nearbyMuonPfos.end())
141  nearbyMuonPfos.push_back(pfoIter->second);
142 
143  continue;
144  }
145 
146  this->GetNearbyMuonPfos(pNearbyCluster, consideredClusters, nearbyMuonPfos);
147  }
148 }
149 
150 //------------------------------------------------------------------------------------------------------------------------------------------
151 
152 template <typename T>
154  const Cluster *const pCluster1, const Cluster *const pCluster2, const Cluster *const pCluster3, float &reducedChiSquared) const
155 {
156  float chiSquaredSum(0.f);
157  unsigned int nSamplingPoints(0), nMatchedSamplingPoints(0);
158  XOverlap xThreeViewOverlapObject(0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
159 
160  if (this->PerformThreeViewMatching(pCluster1, pCluster2, pCluster3, chiSquaredSum, nSamplingPoints, nMatchedSamplingPoints,
161  xThreeViewOverlapObject) == STATUS_CODE_NOT_FOUND)
162  return STATUS_CODE_NOT_FOUND;
163 
164  if (nSamplingPoints == 0)
165  return STATUS_CODE_NOT_FOUND;
166 
167  reducedChiSquared = chiSquaredSum / nSamplingPoints;
168 
169  return STATUS_CODE_SUCCESS;
170 }
171 
172 //------------------------------------------------------------------------------------------------------------------------------------------
173 
174 template <typename T>
175 StatusCode NViewDeltaRayMatchingAlgorithm<T>::PerformThreeViewMatching(const Cluster *const pClusterU, const Cluster *const pClusterV,
176  const Cluster *const pClusterW, float &chiSquaredSum, unsigned int &nSamplingPoints, unsigned int &nMatchedSamplingPoints, XOverlap &xOverlapObject) const
177 {
181 
182  pClusterU->GetClusterSpanX(xMinU, xMaxU);
183  pClusterV->GetClusterSpanX(xMinV, xMaxV);
184  pClusterW->GetClusterSpanX(xMinW, xMaxW);
185 
186  // Need to remove the xPitch from calculations to be consistent with view xSpan calculated in the xOverlapObject
187  const float xMinCentre(std::max(xMinU, std::max(xMinV, xMinW)));
188  const float xMaxCentre(std::min(xMaxU, std::min(xMaxV, xMaxW)));
189  const float xCentreOverlap(xMaxCentre - xMinCentre);
190 
191  if (xCentreOverlap < std::numeric_limits<float>::epsilon())
192  return STATUS_CODE_NOT_FOUND;
193 
194  const float xPitch(0.5 * m_xOverlapWindow);
195  const float xMin(std::max(xMinU, std::max(xMinV, xMinW)) - xPitch);
196  const float xMax(std::min(xMaxU, std::min(xMaxV, xMaxW)) + xPitch);
197  const float xOverlap(xMax - xMin);
198 
199  const HitType hitTypeU(LArClusterHelper::GetClusterHitType(pClusterU));
200  const HitType hitTypeV(LArClusterHelper::GetClusterHitType(pClusterV));
201  const HitType hitTypeW(LArClusterHelper::GetClusterHitType(pClusterW));
202 
203  if (hitTypeU == hitTypeV || hitTypeU == hitTypeW || hitTypeV == hitTypeW)
204  return STATUS_CODE_FAILURE;
205 
206  const unsigned int nPoints(1 + static_cast<unsigned int>(xOverlap / xPitch));
207 
208  chiSquaredSum = 0.f;
209  nSamplingPoints = 0;
210  nMatchedSamplingPoints = 0;
211 
212  for (unsigned int n = 0; n < nPoints; ++n)
213  {
214  const float x(xMin + (xMax - xMin) * (static_cast<float>(n) + 0.5f) / static_cast<float>(nPoints));
215  const float xmin(x - xPitch);
216  const float xmax(x + xPitch);
217 
218  try
219  {
220  float zMinU(0.f), zMinV(0.f), zMinW(0.f), zMaxU(0.f), zMaxV(0.f), zMaxW(0.f);
221  pClusterU->GetClusterSpanZ(xmin, xmax, zMinU, zMaxU);
222  pClusterV->GetClusterSpanZ(xmin, xmax, zMinV, zMaxV);
223  pClusterW->GetClusterSpanZ(xmin, xmax, zMinW, zMaxW);
224 
225  const float zU(0.5f * (zMinU + zMaxU));
226  const float zV(0.5f * (zMinV + zMaxV));
227  const float zW(0.5f * (zMinW + zMaxW));
228 
229  const float dzU(zMaxU - zMinU);
230  const float dzV(zMaxV - zMinV);
231  const float dzW(zMaxW - zMinW);
232  const float dzPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
233 
234  const float zprojU(LArGeometryHelper::MergeTwoPositions(this->GetPandora(), hitTypeV, hitTypeW, zV, zW));
235  const float zprojV(LArGeometryHelper::MergeTwoPositions(this->GetPandora(), hitTypeW, hitTypeU, zW, zU));
236  const float zprojW(LArGeometryHelper::MergeTwoPositions(this->GetPandora(), hitTypeU, hitTypeV, zU, zV));
237 
238  ++nSamplingPoints;
239 
240  const float deltaSquared(((zU - zprojU) * (zU - zprojU) + (zV - zprojV) * (zV - zprojV) + (zW - zprojW) * (zW - zprojW)) / 3.f);
241  const float sigmaSquared(dzU * dzU + dzV * dzV + dzW * dzW + dzPitch * dzPitch);
242  const float pseudoChi2(deltaSquared / sigmaSquared);
243 
244  chiSquaredSum += pseudoChi2;
245 
246  if (pseudoChi2 < m_pseudoChi2Cut)
247  ++nMatchedSamplingPoints;
248  }
249  catch (StatusCodeException &statusCodeException)
250  {
251  if (statusCodeException.GetStatusCode() != STATUS_CODE_NOT_FOUND)
252  return statusCodeException.GetStatusCode();
253 
254  continue;
255  }
256  }
257 
258  // Apply tensor threshold cuts
259  if (nSamplingPoints == 0)
260  return STATUS_CODE_NOT_FOUND;
261 
262  const float matchedFraction(static_cast<float>(nMatchedSamplingPoints) / static_cast<float>(nSamplingPoints));
263 
264  if ((matchedFraction < m_minMatchedFraction) || (nMatchedSamplingPoints < m_minMatchedPoints))
265  return STATUS_CODE_NOT_FOUND;
266 
267  xOverlapObject = XOverlap(xMinU, xMaxU, xMinV, xMaxV, xMinW, xMaxW, xCentreOverlap);
268 
269  return STATUS_CODE_SUCCESS;
270 }
271 
272 //------------------------------------------------------------------------------------------------------------------------------------------
273 
274 template <typename T>
276  const CaloHitList &pCluster1, const CaloHitList &pCluster2, const CaloHitList &pCluster3, float &reducedChiSquared) const
277 {
278  float chiSquaredSum(0.f);
279  unsigned int nSamplingPoints(0), nMatchedSamplingPoints(0);
280  XOverlap xThreeViewOverlapObject(0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
281 
282  if (this->PerformThreeViewMatching(pCluster1, pCluster2, pCluster3, chiSquaredSum, nSamplingPoints, nMatchedSamplingPoints,
283  xThreeViewOverlapObject) == STATUS_CODE_NOT_FOUND)
284  return STATUS_CODE_NOT_FOUND;
285 
286  if (nSamplingPoints == 0)
287  return STATUS_CODE_NOT_FOUND;
288 
289  reducedChiSquared = chiSquaredSum / nSamplingPoints;
290 
291  return STATUS_CODE_SUCCESS;
292 }
293 
294 //------------------------------------------------------------------------------------------------------------------------------------------
295 
296 template <typename T>
297 StatusCode NViewDeltaRayMatchingAlgorithm<T>::PerformThreeViewMatching(const CaloHitList &clusterU, const CaloHitList &clusterV,
298  const CaloHitList &clusterW, float &chiSquaredSum, unsigned int &nSamplingPoints, unsigned int &nMatchedSamplingPoints, XOverlap &xOverlapObject) const
299 {
303 
304  this->GetClusterSpanX(clusterU, xMinU, xMaxU);
305  this->GetClusterSpanX(clusterV, xMinV, xMaxV);
306  this->GetClusterSpanX(clusterW, xMinW, xMaxW);
307 
308  // Need to remove the xPitch from calculations to be consistent with view xSpan calculated in the xOverlapObject
309  const float xMinCentre(std::max(xMinU, std::max(xMinV, xMinW)));
310  const float xMaxCentre(std::min(xMaxU, std::min(xMaxV, xMaxW)));
311  const float xCentreOverlap(xMaxCentre - xMinCentre);
312 
313  if (xCentreOverlap < std::numeric_limits<float>::epsilon())
314  return STATUS_CODE_NOT_FOUND;
315 
316  const float xPitch(0.5 * m_xOverlapWindow);
317  const float xMin(std::max(xMinU, std::max(xMinV, xMinW)) - xPitch);
318  const float xMax(std::min(xMaxU, std::min(xMaxV, xMaxW)) + xPitch);
319  const float xOverlap(xMax - xMin);
320 
321  const HitType hitTypeU(clusterU.front()->GetHitType());
322  const HitType hitTypeV(clusterV.front()->GetHitType());
323  const HitType hitTypeW(clusterW.front()->GetHitType());
324 
325  if (hitTypeU == hitTypeV || hitTypeU == hitTypeW || hitTypeV == hitTypeW)
326  return STATUS_CODE_FAILURE;
327 
328  const unsigned int nPoints(1 + static_cast<unsigned int>(xOverlap / xPitch));
329 
330  chiSquaredSum = 0.f;
331  nSamplingPoints = 0;
332  nMatchedSamplingPoints = 0;
333 
334  for (unsigned int n = 0; n < nPoints; ++n)
335  {
336  const float x(xMin + (xMax - xMin) * (static_cast<float>(n) + 0.5f) / static_cast<float>(nPoints));
337  const float xmin(x - xPitch);
338  const float xmax(x + xPitch);
339 
340  try
341  {
342  float zMinU(0.f), zMinV(0.f), zMinW(0.f), zMaxU(0.f), zMaxV(0.f), zMaxW(0.f);
343  this->GetClusterSpanZ(clusterU, xmin, xmax, zMinU, zMaxU);
344  this->GetClusterSpanZ(clusterV, xmin, xmax, zMinV, zMaxV);
345  this->GetClusterSpanZ(clusterW, xmin, xmax, zMinW, zMaxW);
346 
347  const float zU(0.5f * (zMinU + zMaxU));
348  const float zV(0.5f * (zMinV + zMaxV));
349  const float zW(0.5f * (zMinW + zMaxW));
350 
351  const float dzU(zMaxU - zMinU);
352  const float dzV(zMaxV - zMinV);
353  const float dzW(zMaxW - zMinW);
354  const float dzPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
355 
356  const float zprojU(LArGeometryHelper::MergeTwoPositions(this->GetPandora(), hitTypeV, hitTypeW, zV, zW));
357  const float zprojV(LArGeometryHelper::MergeTwoPositions(this->GetPandora(), hitTypeW, hitTypeU, zW, zU));
358  const float zprojW(LArGeometryHelper::MergeTwoPositions(this->GetPandora(), hitTypeU, hitTypeV, zU, zV));
359 
360  ++nSamplingPoints;
361 
362  const float deltaSquared(((zU - zprojU) * (zU - zprojU) + (zV - zprojV) * (zV - zprojV) + (zW - zprojW) * (zW - zprojW)) / 3.f);
363  const float sigmaSquared(dzU * dzU + dzV * dzV + dzW * dzW + dzPitch * dzPitch);
364  const float pseudoChi2(deltaSquared / sigmaSquared);
365 
366  chiSquaredSum += pseudoChi2;
367 
368  if (pseudoChi2 < m_pseudoChi2Cut)
369  ++nMatchedSamplingPoints;
370  }
371  catch (StatusCodeException &statusCodeException)
372  {
373  if (statusCodeException.GetStatusCode() != STATUS_CODE_NOT_FOUND)
374  return statusCodeException.GetStatusCode();
375 
376  continue;
377  }
378  }
379 
380  // Apply tensor threshold cuts
381  if (nSamplingPoints == 0)
382  return STATUS_CODE_NOT_FOUND;
383 
384  const float matchedFraction(static_cast<float>(nMatchedSamplingPoints) / static_cast<float>(nSamplingPoints));
385 
386  if ((matchedFraction < m_minMatchedFraction) || (nMatchedSamplingPoints < m_minMatchedPoints))
387  return STATUS_CODE_NOT_FOUND;
388 
389  xOverlapObject = XOverlap(xMinU, xMaxU, xMinV, xMaxV, xMinW, xMaxW, xCentreOverlap);
390 
391  return STATUS_CODE_SUCCESS;
392 }
393 
394 //------------------------------------------------------------------------------------------------------------------------------------------
395 
396 template <typename T>
397 void NViewDeltaRayMatchingAlgorithm<T>::GetClusterSpanX(const CaloHitList &caloHitList, float &xMin, float &xMax) const
398 {
401 
402  for (const CaloHit *const pCaloHit : caloHitList)
403  {
404  const float xCoordinate(pCaloHit->GetPositionVector().GetX());
405 
406  if (xCoordinate < xMin)
407  xMin = xCoordinate;
408 
409  if (xCoordinate > xMax)
410  xMax = xCoordinate;
411  }
412 }
413 
414 //------------------------------------------------------------------------------------------------------------------------------------------
415 
416 template <typename T>
418  const CaloHitList &caloHitList, const float xMin, const float xMax, float &zMin, float &zMax) const
419 {
422 
423  bool found(false);
424  for (const CaloHit *const pCaloHit : caloHitList)
425  {
426  const float xCoordinate(pCaloHit->GetPositionVector().GetX());
427  const float zCoordinate(pCaloHit->GetPositionVector().GetZ());
428 
429  if ((xCoordinate < xMin) || (xCoordinate > xMax))
430  continue;
431 
432  found = true;
433 
434  if (zCoordinate < zMin)
435  zMin = zCoordinate;
436 
437  if (zCoordinate > zMax)
438  zMax = zCoordinate;
439  }
440 
441  if (!found)
442  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
443 
444  return STATUS_CODE_SUCCESS;
445 }
446 
447 //------------------------------------------------------------------------------------------------------------------------------------------
448 
449 template <typename T>
451  const HitType &thirdViewHitType, const ParticleFlowObject *const pParentMuon, CartesianPointVector &projectedPositions) const
452 {
453  ClusterList muonClusterList1, muonClusterList2;
454 
455  HitTypeVector hitTypes({TPC_VIEW_U, TPC_VIEW_V, TPC_VIEW_W});
456 
457  hitTypes.erase(std::find(hitTypes.begin(), hitTypes.end(), thirdViewHitType));
458 
459  LArPfoHelper::GetClusters(pParentMuon, hitTypes[0], muonClusterList1);
460  LArPfoHelper::GetClusters(pParentMuon, hitTypes[1], muonClusterList2);
461 
462  if ((muonClusterList1.size() != 1) || (muonClusterList2.size() != 1))
463  return STATUS_CODE_NOT_FOUND;
464 
465  return (this->GetProjectedPositions(muonClusterList1.front(), muonClusterList2.front(), projectedPositions));
466 }
467 
468 //------------------------------------------------------------------------------------------------------------------------------------------
469 
470 template <typename T>
472  const Cluster *const pCluster1, const Cluster *const pCluster2, CartesianPointVector &projectedPositions) const
473 {
474  float xMin1(0.f), xMax1(0.f), xMin2(0.f), xMax2(0.f);
475  pCluster1->GetClusterSpanX(xMin1, xMax1);
476  pCluster2->GetClusterSpanX(xMin2, xMax2);
477 
478  const float xPitch(0.5 * m_xOverlapWindow);
479  const float xMin(std::max(xMin1, xMin2) - xPitch);
480  const float xMax(std::min(xMax1, xMax2) + xPitch);
481  const float xOverlap(xMax - xMin);
482 
483  if (xOverlap < std::numeric_limits<float>::epsilon())
484  return STATUS_CODE_NOT_FOUND;
485 
486  const HitType hitType1(LArClusterHelper::GetClusterHitType(pCluster1));
487  const HitType hitType2(LArClusterHelper::GetClusterHitType(pCluster2));
488 
489  if (hitType1 == hitType2)
490  throw StatusCodeException(STATUS_CODE_FAILURE);
491 
492  const unsigned int nPoints(1 + static_cast<unsigned int>(xOverlap / xPitch));
493 
494  // Projection into third view
495  for (unsigned int n = 0; n < nPoints; ++n)
496  {
497  const float x(xMin + (xMax - xMin) * (static_cast<float>(n) + 0.5f) / static_cast<float>(nPoints));
498  const float xmin(x - xPitch);
499  const float xmax(x + xPitch);
500 
501  try
502  {
503  float zMin1(0.f), zMin2(0.f), zMax1(0.f), zMax2(0.f);
504  pCluster1->GetClusterSpanZ(xmin, xmax, zMin1, zMax1);
505  pCluster2->GetClusterSpanZ(xmin, xmax, zMin2, zMax2);
506 
507  const float z1(0.5f * (zMin1 + zMax1));
508  const float z2(0.5f * (zMin2 + zMax2));
509 
510  float chi2;
511  CartesianVector projection(0.f, 0.f, 0.f);
513  this->GetPandora(), hitType1, hitType2, CartesianVector(x, 0.f, z1), CartesianVector(x, 0.f, z2), projection, chi2);
514 
515  projectedPositions.push_back(projection);
516  }
517  catch (StatusCodeException &statusCodeException)
518  {
519  if (statusCodeException.GetStatusCode() != STATUS_CODE_NOT_FOUND)
520  throw statusCodeException.GetStatusCode();
521 
522  continue;
523  }
524  }
525 
526  // Reject if projection is not good
527  if (projectedPositions.size() < m_minProjectedPositions)
528  return STATUS_CODE_NOT_FOUND;
529 
530  return STATUS_CODE_SUCCESS;
531 }
532 
533 //------------------------------------------------------------------------------------------------------------------------------------------
534 
535 template <typename T>
536 StatusCode NViewDeltaRayMatchingAlgorithm<T>::CollectHitsFromMuon(const Cluster *const pCluster1, const Cluster *const pCluster2,
537  const Cluster *const pThirdViewCluster, const ParticleFlowObject *const pParentMuon, const float minDistanceFromMuon,
538  const float maxDistanceToCollected, CaloHitList &collectedHits) const
539 {
540  HitType thirdViewHitType(TPC_VIEW_U);
541  CartesianPointVector deltaRayProjectedPositions;
542 
543  if (!pThirdViewCluster)
544  {
545  if (this->GetProjectedPositions(pCluster1, pCluster2, deltaRayProjectedPositions) != STATUS_CODE_SUCCESS)
546  return STATUS_CODE_NOT_FOUND;
547 
548  for (const HitType hitType : {TPC_VIEW_U, TPC_VIEW_V, TPC_VIEW_W})
549  {
550  if ((LArClusterHelper::GetClusterHitType(pCluster1) != hitType) && (LArClusterHelper::GetClusterHitType(pCluster2) != hitType))
551  {
552  thirdViewHitType = hitType;
553  break;
554  }
555  }
556  }
557  else
558  {
559  CaloHitList deltaRayCaloHitList;
560  pThirdViewCluster->GetOrderedCaloHitList().FillCaloHitList(deltaRayCaloHitList);
561 
562  for (const CaloHit *const pCaloHit : deltaRayCaloHitList)
563  deltaRayProjectedPositions.push_back(pCaloHit->GetPositionVector());
564 
565  thirdViewHitType = LArClusterHelper::GetClusterHitType(pThirdViewCluster);
566  }
567 
568  ClusterList muonClusterList;
569  LArPfoHelper::GetClusters(pParentMuon, thirdViewHitType, muonClusterList);
570 
571  if (muonClusterList.size() != 1)
572  return STATUS_CODE_NOT_FOUND;
573 
574  const Cluster *const pMuonCluster(muonClusterList.front());
575 
576  // To avoid fluctuatuions, parameterise the muon track
577  CartesianVector positionOnMuon(0.f, 0.f, 0.f), muonDirection(0.f, 0.f, 0.f);
578  if (this->ParameteriseMuon(pParentMuon, deltaRayProjectedPositions, thirdViewHitType, positionOnMuon, muonDirection) != STATUS_CODE_SUCCESS)
579  return STATUS_CODE_NOT_FOUND;
580 
581  this->CollectHitsFromMuon(
582  positionOnMuon, muonDirection, pMuonCluster, deltaRayProjectedPositions, minDistanceFromMuon, maxDistanceToCollected, collectedHits);
583 
584  if (collectedHits.empty())
585  return STATUS_CODE_NOT_FOUND;
586 
587  // Catch if delta ray has travelled along muon
588  if ((static_cast<float>(collectedHits.size()) / pMuonCluster->GetNCaloHits()) > m_maxCosmicRayHitFraction)
589  return STATUS_CODE_NOT_FOUND;
590 
591  return STATUS_CODE_SUCCESS;
592 }
593 
594 //------------------------------------------------------------------------------------------------------------------------------------------
595 
596 template <typename T>
597 void NViewDeltaRayMatchingAlgorithm<T>::CollectHitsFromMuon(const CartesianVector &positionOnMuon, const CartesianVector &muonDirection,
598  const Cluster *const pMuonCluster, const CartesianPointVector &deltaRayProjectedPositions, const float &minDistanceFromMuon,
599  const float maxDistanceToCollected, CaloHitList &collectedHits) const
600 {
601  CaloHitList cosmicRayHitList;
602  pMuonCluster->GetOrderedCaloHitList().FillCaloHitList(cosmicRayHitList);
603 
604  bool hitsAdded(true);
605  while (hitsAdded)
606  {
607  hitsAdded = false;
608 
609  for (const CaloHit *const pCaloHit : cosmicRayHitList)
610  {
611  if (std::find(collectedHits.begin(), collectedHits.end(), pCaloHit) != collectedHits.end())
612  continue;
613 
614  const float distanceToCollectedHits(std::min(LArMuonLeadingHelper::GetClosestDistance(pCaloHit, deltaRayProjectedPositions),
615  collectedHits.empty() ? std::numeric_limits<float>::max()
616  : LArClusterHelper::GetClosestDistance(pCaloHit->GetPositionVector(), collectedHits)));
617  const float distanceToMuonHits(muonDirection.GetCrossProduct(pCaloHit->GetPositionVector() - positionOnMuon).GetMagnitude());
618 
619  if ((std::fabs(distanceToMuonHits - distanceToCollectedHits) < std::numeric_limits<float>::epsilon()) ||
620  (distanceToMuonHits < minDistanceFromMuon) || (distanceToCollectedHits > distanceToMuonHits) ||
621  (distanceToCollectedHits > maxDistanceToCollected))
622  {
623  continue;
624  }
625 
626  collectedHits.push_back(pCaloHit);
627  hitsAdded = true;
628  }
629  }
630 }
631 
632 //------------------------------------------------------------------------------------------------------------------------------------------
633 
634 template <typename T>
635 StatusCode NViewDeltaRayMatchingAlgorithm<T>::ParameteriseMuon(const ParticleFlowObject *const pParentMuon,
636  const Cluster *const pDeltaRayCluster, CartesianVector &positionOnMuon, CartesianVector &muonDirection) const
637 {
638  CaloHitList deltaRayHitList;
639  pDeltaRayCluster->GetOrderedCaloHitList().FillCaloHitList(deltaRayHitList);
640 
641  CartesianPointVector deltaRayProjectedPositions;
642 
643  for (const CaloHit *const pCaloHit : deltaRayHitList)
644  deltaRayProjectedPositions.push_back(pCaloHit->GetPositionVector());
645 
646  return this->ParameteriseMuon(
647  pParentMuon, deltaRayProjectedPositions, LArClusterHelper::GetClusterHitType(pDeltaRayCluster), positionOnMuon, muonDirection);
648 }
649 
650 //------------------------------------------------------------------------------------------------------------------------------------------
651 
652 template <typename T>
653 StatusCode NViewDeltaRayMatchingAlgorithm<T>::ParameteriseMuon(const ParticleFlowObject *const pParentMuon,
654  const CartesianPointVector &deltaRayProjectedPositions, const HitType hitType, CartesianVector &positionOnMuon, CartesianVector &muonDirection) const
655 {
656  ClusterList muonClusterList;
657  LArPfoHelper::GetClusters(pParentMuon, hitType, muonClusterList);
658 
659  if (muonClusterList.size() != 1)
660  return STATUS_CODE_NOT_FOUND;
661 
662  CartesianPointVector muonProjectedPositions;
663  if (this->ProjectMuonPositions(hitType, pParentMuon, muonProjectedPositions) != STATUS_CODE_SUCCESS)
664  return STATUS_CODE_NOT_FOUND;
665 
666  const Cluster *const pMuonCluster(muonClusterList.front());
667  const float slidingFitPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
668  const TwoDSlidingFitResult slidingFitResult(pMuonCluster, 40, slidingFitPitch);
669 
670  CartesianVector deltaRayVertex(0.f, 0.f, 0.f), muonVertex(0.f, 0.f, 0.f);
671  LArMuonLeadingHelper::GetClosestPositions(deltaRayProjectedPositions, pMuonCluster, deltaRayVertex, muonVertex);
672 
674  muonVertex, muonProjectedPositions, pMuonCluster, m_maxDistanceToCluster, m_maxDistanceToReferencePoint, positionOnMuon));
675 
676  if (status != STATUS_CODE_SUCCESS)
677  return STATUS_CODE_NOT_FOUND;
678 
679  float rL(0.f), rT(0.f);
680  slidingFitResult.GetLocalPosition(positionOnMuon, rL, rT);
681 
682  if (slidingFitResult.GetGlobalFitDirection(rL, muonDirection) != STATUS_CODE_SUCCESS)
683  return STATUS_CODE_NOT_FOUND;
684 
685  return STATUS_CODE_SUCCESS;
686 }
687 
688 //------------------------------------------------------------------------------------------------------------------------------------------
689 
690 template <typename T>
691 void NViewDeltaRayMatchingAlgorithm<T>::SplitMuonCluster(const std::string &clusterListName, const Cluster *const pMuonCluster,
692  const CaloHitList &collectedHits, const Cluster *&pDeltaRayCluster) const
693 {
694  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*this, clusterListName));
695 
696  CaloHitList muonCaloHitList;
697  pMuonCluster->GetOrderedCaloHitList().FillCaloHitList(muonCaloHitList);
698 
699  for (const CaloHit *const pCaloHit : muonCaloHitList)
700  {
701  if (std::find(collectedHits.begin(), collectedHits.end(), pCaloHit) != collectedHits.end())
702  {
703  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromCluster(*this, pMuonCluster, pCaloHit));
704 
705  if (!pDeltaRayCluster)
706  {
707  const ClusterList *pTemporaryList(nullptr);
708  std::string temporaryListName, currentListName;
709  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentListName<Cluster>(*this, currentListName));
710  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
711  PandoraContentApi::CreateTemporaryListAndSetCurrent<ClusterList>(*this, pTemporaryList, temporaryListName));
712 
713  PandoraContentApi::Cluster::Parameters parameters;
714  parameters.m_caloHitList.push_back(pCaloHit);
715 
716  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*this, parameters, pDeltaRayCluster));
717  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Cluster>(*this, temporaryListName, currentListName));
718  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*this, currentListName));
719  }
720  else
721  {
722  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*this, pDeltaRayCluster, pCaloHit));
723  }
724  }
725  }
726 }
727 
728 //------------------------------------------------------------------------------------------------------------------------------------------
729 
730 template <typename T>
732 {
733  std::sort(protoParticleVector.begin(), protoParticleVector.end(), [](const ProtoParticle &a, const ProtoParticle &b) -> bool {
734  unsigned int aHitTotal(0);
735  for (const Cluster *const pCluster : a.m_clusterList)
736  aHitTotal += pCluster->GetNCaloHits();
737 
738  unsigned int bHitTotal(0);
739  for (const Cluster *const pCluster : b.m_clusterList)
740  bHitTotal += pCluster->GetNCaloHits();
741 
742  return (aHitTotal > bHitTotal);
743  });
744 
745  for (ProtoParticle protoParticle : protoParticleVector)
746  {
747  float longestSpan(-std::numeric_limits<float>::max()), spanMinX(0.f), spanMaxX(0.f);
748 
749  for (const Cluster *const pCluster : protoParticle.m_clusterList)
750  {
751  float minX(0.f), maxX(0.f);
752  pCluster->GetClusterSpanX(minX, maxX);
753 
754  const float span(maxX - minX);
755 
756  if (span > longestSpan)
757  {
758  longestSpan = span;
759  spanMinX = minX;
760  spanMaxX = maxX;
761  }
762  }
763 
764  for (const Cluster *const pCluster : protoParticle.m_clusterList)
765  {
766  ClusterList collectedClusters;
767  this->CollectStrayClusters(pCluster, spanMinX, spanMaxX, collectedClusters);
768 
769  if (!collectedClusters.empty())
770  this->AddInStrayClusters(pCluster, collectedClusters);
771  }
772  }
773 
774  return (this->CreateThreeDParticles(protoParticleVector));
775 }
776 
777 //------------------------------------------------------------------------------------------------------------------------------------------
778 
779 template <typename T>
781  const Cluster *const pClusterToEnlarge, const float rangeMinX, const float rangeMaxX, ClusterList &collectedClusters)
782 {
783  const HitType hitType(LArClusterHelper::GetClusterHitType(pClusterToEnlarge));
784  const ClusterList &strayClusterList((hitType == TPC_VIEW_U) ? m_strayClusterListU : (hitType == TPC_VIEW_V) ? m_strayClusterListV : m_strayClusterListW);
786  const DeltaRayMatchingContainers::ClusterProximityMap::const_iterator clusterProximityIter(clusterProximityMap.find(pClusterToEnlarge));
787 
788  if (clusterProximityIter == clusterProximityMap.end())
789  return;
790 
791  for (const Cluster *const pNearbyCluster : clusterProximityIter->second)
792  {
793  if (std::find(strayClusterList.begin(), strayClusterList.end(), pNearbyCluster) == strayClusterList.end())
794  continue;
795 
797  pNearbyCluster->GetClusterSpanX(xMin, xMax);
798 
799  if (!(((xMin > rangeMinX) && (xMin < rangeMaxX)) || ((xMax > rangeMinX) && (xMax < rangeMaxX))))
800  continue;
801 
802  if (LArClusterHelper::GetClosestDistance(pClusterToEnlarge, pNearbyCluster) > m_strayClusterSeparation)
803  continue;
804 
805  if (std::find(collectedClusters.begin(), collectedClusters.end(), pNearbyCluster) == collectedClusters.end())
806  collectedClusters.push_back(pNearbyCluster);
807  }
808 }
809 
810 //------------------------------------------------------------------------------------------------------------------------------------------
811 
812 template <typename T>
813 void NViewDeltaRayMatchingAlgorithm<T>::AddInStrayClusters(const Cluster *const pClusterToEnlarge, const ClusterList &collectedClusters)
814 {
815  this->UpdateUponDeletion(pClusterToEnlarge);
816 
817  for (const Cluster *const pCollectedCluster : collectedClusters)
818  {
819  this->UpdateUponDeletion(pCollectedCluster);
820 
821  std::string clusterListName(this->GetClusterListName(LArClusterHelper::GetClusterHitType(pClusterToEnlarge)));
822  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
823  PandoraContentApi::MergeAndDeleteClusters(*this, pClusterToEnlarge, pCollectedCluster, clusterListName, clusterListName));
824  }
825 
826  m_deltaRayMatchingContainers.AddClustersToContainers({pClusterToEnlarge}, {nullptr});
827 }
828 
829 //------------------------------------------------------------------------------------------------------------------------------------------
830 
831 template <typename T>
832 void NViewDeltaRayMatchingAlgorithm<T>::UpdateUponDeletion(const Cluster *const pDeletedCluster)
833 {
834  const HitType hitType(LArClusterHelper::GetClusterHitType(pDeletedCluster));
835  ClusterList &strayClusterList((hitType == TPC_VIEW_U) ? m_strayClusterListU : (hitType == TPC_VIEW_V) ? m_strayClusterListV : m_strayClusterListW);
836  const ClusterList::const_iterator strayClusterIter(std::find(strayClusterList.begin(), strayClusterList.end(), pDeletedCluster));
837 
838  if (strayClusterIter != strayClusterList.end())
839  strayClusterList.erase(strayClusterIter);
840 
842  const bool isMuonCluster(clusterToPfoMap.find(pDeletedCluster) != clusterToPfoMap.end());
843 
845 
846  if (!isMuonCluster)
848 }
849 
850 //------------------------------------------------------------------------------------------------------------------------------------------
851 
852 template <typename T>
853 void NViewDeltaRayMatchingAlgorithm<T>::UpdateForNewClusters(const ClusterVector &newClusterVector, const PfoVector &pfoVector)
854 {
855  m_deltaRayMatchingContainers.AddClustersToContainers(newClusterVector, pfoVector);
856 
857  for (unsigned int i = 0; i < newClusterVector.size(); i++)
858  {
859  const Cluster *const pNewCluster(newClusterVector.at(i));
860  const ParticleFlowObject *const pMuonPfo(pfoVector.at(i));
861 
862  // ATTN: Only add delta ray clusters into the tensor
863  if (!pMuonPfo)
865  }
866 }
867 
868 //------------------------------------------------------------------------------------------------------------------------------------------
869 
870 template <typename T>
872 {
874 
875  m_strayClusterListU.clear();
876  m_strayClusterListV.clear();
877  m_strayClusterListW.clear();
878 
880 }
881 
882 //------------------------------------------------------------------------------------------------------------------------------------------
883 
884 template <typename T>
885 StatusCode NViewDeltaRayMatchingAlgorithm<T>::ReadSettings(const TiXmlHandle xmlHandle)
886 {
887  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "MuonPfoListName", m_muonPfoListName));
888 
889  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
890  XmlHelper::ReadValue(xmlHandle, "SearchRegion1D", m_deltaRayMatchingContainers.m_searchRegion1D));
891 
892  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "PseudoChi2Cut", m_pseudoChi2Cut));
893 
894  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "OverlapWindow", m_xOverlapWindow));
895 
896  PANDORA_RETURN_RESULT_IF_AND_IF(
897  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinMatchedFraction", m_minMatchedFraction));
898 
899  PANDORA_RETURN_RESULT_IF_AND_IF(
900  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinMatchedPoints", m_minMatchedPoints));
901 
902  PANDORA_RETURN_RESULT_IF_AND_IF(
903  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinProjectedPositions", m_minProjectedPositions));
904 
905  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
906  XmlHelper::ReadValue(xmlHandle, "MaxCosmicRayHitFraction", m_maxCosmicRayHitFraction));
907 
908  PANDORA_RETURN_RESULT_IF_AND_IF(
909  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxDistanceToCluster", m_maxDistanceToCluster));
910 
911  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
912  XmlHelper::ReadValue(xmlHandle, "MaxDistanceToReferencePoint", m_maxDistanceToReferencePoint));
913 
914  PANDORA_RETURN_RESULT_IF_AND_IF(
915  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "StrayClusterSeparation", m_strayClusterSeparation));
916 
917  return NViewMatchingAlgorithm<T>::ReadSettings(xmlHandle);
918 }
919 
920 //------------------------------------------------------------------------------------------------------------------------------------------
921 
924 
925 } // namespace lar_content
span(IterB &&b, IterE &&e, Adaptor &&adaptor) -> span< decltype(adaptor(std::forward< IterB >(b))), decltype(adaptor(std::forward< IterE >(e))) >
void SelectInputClusters(const pandora::ClusterList *const pInputClusterList, pandora::ClusterList &selectedClusterList) const
Select a subset of input clusters for processing in this algorithm.
std::vector< ProtoParticle > ProtoParticleVector
static float GetClosestDistance(const pandora::Cluster *const pCluster, const pandora::CartesianPointVector &cartesianPointVector)
Get closest distance between a specified cluster and list of positions.
Header file for the kd tree linker algo template class.
std::map< const pandora::Cluster *, const pandora::ParticleFlowObject * > ClusterToPfoMap
Header file for the pfo helper class.
pandora::StatusCode GetProjectedPositions(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, pandora::CartesianPointVector &projectedPositions) const
Use two clusters from different views to calculate projected positions in the remaining third view...
const ClusterProximityMap & GetClusterProximityMap(const pandora::HitType hitType) const
Get the mapping of clusters to to their neighbouring clusters.
pandora::StatusCode GetClusterSpanZ(const pandora::CaloHitList &caloHitList, const float xMin, const float xMax, float &zMin, float &zMax) const
Calculate the zSpan of a list of CaloHits in a specified x range.
unsigned int m_minProjectedPositions
The threshold number of projected points for a good projection.
static void GetClusters(const pandora::PfoList &pfoList, const pandora::HitType &hitType, pandora::ClusterList &clusterList)
Get a list of clusters of a particular hit type from a list of pfos.
pandora::StatusCode CollectHitsFromMuon(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const pandora::Cluster *const pThirdViewCluster, const pandora::ParticleFlowObject *const pParentMuon, const float minDistanceFromMuon, const float maxDistanceToCollected, pandora::CaloHitList &collectedHits) const
In one view, pull out any hits from a cosmic ray cluster that belong to the child delta ray cluster...
pandora::ClusterList m_strayClusterListU
The list of U clusters that do not pass the tensor threshold requirement.
enum cvn::HType HitType
std::string string
Definition: nybbler.cc:12
virtual void TidyUp()
Tidy member variables in derived class.
void UpdateForNewClusters(const pandora::ClusterVector &newClusterVector, const pandora::PfoVector &pfoVector)
Add a new cluster to algorithm ownership maps and, if it a delta ray cluster, to the underlying match...
void TidyUp()
Tidy member variables in derived class.
float m_pseudoChi2Cut
Pseudo chi2 cut for three view matching.
intermediate_table::const_iterator const_iterator
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
void FillContainers(const pandora::PfoList &inputPfoList, const pandora::ClusterList &inputClusterList1, const pandora::ClusterList &inputClusterList2=pandora::ClusterList(), const pandora::ClusterList &inputClusterList3=pandora::ClusterList())
Fill the HitToClusterMap, the ClusterProximityMap and the ClusterToPfoMap in all input views...
void UpdateUponDeletion(const pandora::Cluster *const pDeletedCluster)
Update to reflect cluster deletion.
void PrepareInputClusters(pandora::ClusterList &preparedClusterList)
Perform any preparatory steps required on the input clusters, e.g. caching expensive fit results...
void CollectStrayClusters(const pandora::Cluster *const pClusterToEnlarge, const float rangeMinX, const float rangeMaxX, pandora::ClusterList &collectedClusters)
Collect the stray clusters that are close to a specified cluster and that lie within a given x range...
void GetClusterSpanX(const pandora::CaloHitList &caloHitList, float &xMin, float &xMax) const
Calculate the xSpan of a list of CaloHits.
pandora::StatusCode PerformThreeViewMatching(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const pandora::Cluster *const pCluster3, float &reducedChiSquared) const
To determine how well three clusters (one in each view) map onto one another expressing this in terms...
void UpdateUponDeletion(const pandora::Cluster *const pDeletedCluster)
Update to reflect cluster deletion.
Header file for the geometry helper class.
void UpdateForNewCluster(const pandora::Cluster *const pNewCluster)
Update to reflect addition of a new cluster to the problem space.
float m_xOverlapWindow
The maximum allowed displacement in x position.
std::string m_muonPfoListName
The list of reconstructed cosmic ray pfos.
virtual bool DoesClusterPassTensorThreshold(const pandora::Cluster *const pCluster) const =0
To check whether a given cluster meets the requirements to be added into the matching container (tens...
Header file for the cluster helper class.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Header file for the muon leading helper class.
pandora::StatusCode ParameteriseMuon(const pandora::ParticleFlowObject *const pParentMuon, const pandora::Cluster *const pDeltaRayCluster, pandora::CartesianVector &positionOnMuon, pandora::CartesianVector &muonDirection) const
Parameterise the projection of a cosmic ray track in order to avoid poor/sparse projections.
std::void_t< T > n
void AddClustersToContainers(const pandora::ClusterVector &newClusterVector, const pandora::PfoVector &pfoVector)
Add a list of clusters to the hit to cluster and cluster proximity maps and, if appropriate, to the cluster to pfo map.
const double a
Header file for the lar two dimensional sliding fit result class.
static void GetClosestPositions(const pandora::CartesianPointVector &cartesianPointVector1, const pandora::Cluster *const pCluster2, pandora::CartesianVector &outputPosition1, pandora::CartesianVector &outputPosition2)
Get the closest positions between a list of positions and a cluster.
void FillStrayClusterList(const pandora::HitType hitType)
Fill the stray cluster list with clusters that do not pass the tensor threshold requirement.
pandora::ClusterList m_strayClusterListV
The list of V clusters that do not pass the tensor threshold requirement.
pandora::ClusterList m_clusterList
List of 2D clusters in a 3D proto particle.
pandora::ClusterList m_strayClusterListW
The list of W clusters that do not pass the tensor threshold requirement.
const pandora::ClusterList & GetInputClusterList(const pandora::HitType hitType) const
Get the input cluster list corresponding to a specified hit type.
const ClusterToPfoMap & GetClusterToPfoMap(const pandora::HitType hitType) const
Get the mapping of clusters to the pfos to which they belong.
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).
void SplitMuonCluster(const std::string &clusterListName, const pandora::Cluster *const pMuonCluster, const pandora::CaloHitList &collectedHits, const pandora::Cluster *&pDeltaRayCluster) const
Move a list of hits from a cosmic ray cluster into the given child delta ray cluster.
void AddInStrayClusters(const pandora::Cluster *const pClusterToEnlarge, const pandora::ClusterList &collectedClusters)
Merge in the collected stray clusters of a given delta ray cluster.
float m_strayClusterSeparation
The maximum allowed separation of a stray cluster and a delta ray cluster for merge.
static int max(int a, int b)
void GetNearbyMuonPfos(const pandora::Cluster *const pCluster, pandora::ClusterList &consideredClusters, pandora::PfoList &nearbyMuonPfos) const
Use the cluster proximity map to travel along paths of nearby clusters finding the cosmic ray cluster...
static pandora::StatusCode GetClosestPosition(const pandora::CartesianVector &referencePoint, const pandora::CartesianPointVector &cartesianPointVector, const pandora::Cluster *const pCluster, const float maxDistanceToCluster, const float maxDistanceToReferencePoint, pandora::CartesianVector &closestPosition)
Get the closest position from an input list of projected positions that lies close to both a referenc...
float m_maxDistanceToReferencePoint
the maximum distance of a projected point to the cosmic ray vertex used when parameterising the cosmi...
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
pandora::StatusCode GetGlobalFitDirection(const float rL, pandora::CartesianVector &direction) const
Get global fit direction for a given longitudinal coordinate.
std::map< const pandora::Cluster *, pandora::ClusterList > ClusterProximityMap
Header file for the lar track overlap result class.
Header file for the three view matching control class.
static bool * b
Definition: config.cpp:1043
const std::string & GetClusterListName(const pandora::HitType hitType) const
Get the cluster list name corresponding to a specified hit type.
list x
Definition: train.py:276
virtual bool CreateThreeDParticles(const ProtoParticleVector &protoParticleVector)
Create particles using findings from recent algorithm processing.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
float m_maxCosmicRayHitFraction
The maximum allowed fraction of hits to be removed from the cosmic ray track.
bool CreatePfos(ProtoParticleVector &protoParticleVector)
Create delta ray pfos maxmising completeness by searching for and merging in any stray clusters...
pandora::StatusCode ProjectMuonPositions(const pandora::HitType &thirdViewHitType, const pandora::ParticleFlowObject *const pParentMuon, pandora::CartesianPointVector &projectedPositions) const
Use two views of a cosmic ray pfo to calculate projected positions in a given the third view...
DeltaRayMatchingContainers m_deltaRayMatchingContainers
The class of hit, cluster and pfo ownership and proximity maps.
XOverlap class.
Definition: LArXOverlap.h:17
void ClearContainers()
Empty all algorithm containers.
Header file for the two view matching control class.
void GetLocalPosition(const pandora::CartesianVector &position, float &rL, float &rT) const
Get local sliding fit coordinates for a given global position.
Header file for the lar track two view overlap result class.
pandora::StatusCode GetMuonCluster(const pandora::PfoList &commonMuonPfoList, const pandora::HitType hitType, const pandora::Cluster *&pMuonCluster) const
Return the cluster of the common cosmic ray pfo in a given view (function demands there to be only on...
void RemoveClusterFromContainers(const pandora::Cluster *const pDeletedCluster)
Remove an input cluster&#39;s hits from the hit to cluster and cluster proximity maps and...
float m_minMatchedFraction
The threshold matched fraction of sampling points for a good match.
unsigned int m_minMatchedPoints
The threshold number of matched sampling points for a good match.
float m_maxDistanceToCluster
the maximum distance of a projected point to the cosmic ray cluster used when parameterising the cosm...
float m_searchRegion1D
Search region, applied to each dimension, for look-up from kd-tree.
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.