DeltaRayRemovalTool.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArThreeDReco/LArCosmicRay/DeltaRayRemovalTool.cc
3  *
4  * @brief Implementation of the delta ray removal tool class.
5  *
6  * $Log: $
7  */
8 
9 #include "Pandora/AlgorithmHeaders.h"
10 
13 
15 
17 
18 using namespace pandora;
19 
20 namespace lar_content
21 {
22 
23 DeltaRayRemovalTool::DeltaRayRemovalTool() :
24  m_slidingFitWindow(10000),
25  m_minDeviationFromTransverse(0.35f),
26  m_contaminationWindow(5.f),
27  m_significantHitThreshold(3),
28  m_minDistanceFromMuon(1.f),
29  m_maxDistanceToCollected(1.f)
30 {
31 }
32 
33 //------------------------------------------------------------------------------------------------------------------------------------------
34 
36 {
37  m_pParentAlgorithm = pAlgorithm;
38 
39  if (PandoraContentApi::GetSettings(*m_pParentAlgorithm)->ShouldDisplayAlgorithmInfo())
40  std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
41 
42  bool changesMade(false);
43 
44  ClusterVector sortedKeyClusters;
45  overlapTensor.GetSortedKeyClusters(sortedKeyClusters);
46 
47  ClusterSet usedKeyClusters;
48  for (const Cluster *const pKeyCluster : sortedKeyClusters)
49  {
50  if (usedKeyClusters.count(pKeyCluster))
51  continue;
52 
53  TensorType::ElementList elementList;
54  overlapTensor.GetConnectedElements(pKeyCluster, true, elementList);
55 
56  for (const TensorType::Element &element : elementList)
57  usedKeyClusters.insert(element.GetClusterU());
58 
59  const bool changesMadeInIteration = this->RemoveDeltaRayHits(elementList);
60 
61  changesMade = (changesMade ? changesMade : changesMadeInIteration);
62  }
63 
64  return changesMade;
65 }
66 
67 //------------------------------------------------------------------------------------------------------------------------------------------
68 
70 {
71  ClusterSet modifiedClusters, checkedClusters;
72 
73  for (const TensorType::Element &element : elementList)
74  {
75  for (const HitType hitType : {TPC_VIEW_U, TPC_VIEW_V, TPC_VIEW_W})
76  {
77  const Cluster *pDeltaRayCluster(element.GetCluster(hitType));
78  const ParticleFlowObject *const pMuonPfo(element.GetOverlapResult().GetCommonMuonPfoList().front());
79 
80  if (checkedClusters.count(pDeltaRayCluster))
81  continue;
82 
83  // ATTN: The underlying tensor will update during this loop, do not proceed if element has been modified
84  if ((modifiedClusters.count(element.GetClusterU())) || (modifiedClusters.count(element.GetClusterV())) ||
85  (modifiedClusters.count(element.GetClusterW())))
86  continue;
87 
88  if (!this->PassElementChecks(element, hitType))
89  continue;
90 
91  if (!this->IsContaminated(element, hitType))
92  continue;
93 
94  if (!this->IsBestElement(element, hitType, elementList, modifiedClusters))
95  continue;
96 
97  checkedClusters.insert(pDeltaRayCluster);
98 
99  CaloHitList deltaRayHits;
100  if (m_pParentAlgorithm->CollectHitsFromMuon(nullptr, nullptr, pDeltaRayCluster, pMuonPfo, m_minDistanceFromMuon,
101  m_maxDistanceToCollected, deltaRayHits) != STATUS_CODE_SUCCESS)
102  continue;
103 
104  modifiedClusters.insert(pDeltaRayCluster);
105 
106  this->SplitMuonCluster(element, hitType, deltaRayHits);
107  }
108  }
109 
110  return !modifiedClusters.empty();
111 }
112 
113 //------------------------------------------------------------------------------------------------------------------------------------------
114 
115 bool DeltaRayRemovalTool::PassElementChecks(const TensorType::Element &element, const HitType hitType) const
116 {
117  // ATTN: Avoid endpoints, topological michel reconstruction is very ambiguous
118  if (this->IsMuonEndpoint(element, false))
119  return false;
120 
121  return RemovalBaseTool::PassElementChecks(element, hitType);
122 }
123 
124 //------------------------------------------------------------------------------------------------------------------------------------------
125 
126 bool DeltaRayRemovalTool::IsContaminated(const TensorType::Element &element, const HitType hitType) const
127 {
128  const Cluster *pMuonCluster(nullptr), *const pDeltaRayCluster(element.GetCluster(hitType));
129 
130  if (m_pParentAlgorithm->GetMuonCluster(element.GetOverlapResult().GetCommonMuonPfoList(), hitType, pMuonCluster) != STATUS_CODE_SUCCESS)
131  return false;
132 
133  const float slidingFitPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
134  const TwoDSlidingFitResult slidingFitResult(pMuonCluster, m_slidingFitWindow, slidingFitPitch);
135 
136  CartesianVector muonDirection(0.f, 0.f, 0.f);
137  slidingFitResult.GetGlobalDirection(slidingFitResult.GetLayerFitResultMap().begin()->second.GetGradient(), muonDirection);
138 
139  const CartesianVector xAxis(1.f, 0.f, 0.f);
140  const bool isTransverse((muonDirection.GetOpeningAngle(xAxis) < m_minDeviationFromTransverse) ||
141  ((M_PI - muonDirection.GetOpeningAngle(xAxis)) < m_minDeviationFromTransverse));
142 
143  if (isTransverse)
144  return false;
145 
146  CartesianVector deltaRayVertex(0.f, 0.f, 0.f), muonVertex(0.f, 0.f, 0.f);
147  LArClusterHelper::GetClosestPositions(pDeltaRayCluster, pMuonCluster, deltaRayVertex, muonVertex);
148 
149  CaloHitList minusMuonHits, minusDeltaRayHits, plusMuonHits, plusDeltaRayHits;
150  const CartesianVector minusPosition(muonVertex - (muonDirection * m_contaminationWindow));
151  const CartesianVector plusPosition(muonVertex + (muonDirection * m_contaminationWindow));
152 
153  this->FindExtrapolatedHits(pMuonCluster, muonVertex, minusPosition, minusMuonHits);
154  this->FindExtrapolatedHits(pMuonCluster, muonVertex, plusPosition, plusMuonHits);
155  this->FindExtrapolatedHits(pDeltaRayCluster, muonVertex, minusPosition, minusDeltaRayHits);
156  this->FindExtrapolatedHits(pDeltaRayCluster, muonVertex, plusPosition, plusDeltaRayHits);
157 
158  if ((minusMuonHits.size() < m_significantHitThreshold) && (plusMuonHits.size() < m_significantHitThreshold))
159  return true;
160 
161  if ((minusMuonHits.size() < m_significantHitThreshold) && (minusDeltaRayHits.size() >= m_significantHitThreshold) &&
162  (plusDeltaRayHits.size() < m_significantHitThreshold) && (plusMuonHits.size() >= m_significantHitThreshold))
163  {
164  return true;
165  }
166 
167  if ((plusMuonHits.size() < m_significantHitThreshold) && (plusDeltaRayHits.size() >= m_significantHitThreshold) &&
168  (minusDeltaRayHits.size() < m_significantHitThreshold) && (minusMuonHits.size() >= m_significantHitThreshold))
169  {
170  return true;
171  }
172 
173  return false;
174 }
175 
176 //------------------------------------------------------------------------------------------------------------------------------------------
177 
178 void DeltaRayRemovalTool::SplitMuonCluster(const TensorType::Element &element, const HitType hitType, const CaloHitList &deltaRayHits) const
179 {
180  const Cluster *pDeltaRayCluster(element.GetCluster(hitType)), *pMuonCluster(nullptr);
181 
182  if (m_pParentAlgorithm->GetMuonCluster(element.GetOverlapResult().GetCommonMuonPfoList(), hitType, pMuonCluster) != STATUS_CODE_SUCCESS)
183  throw StatusCodeException(STATUS_CODE_FAILURE);
184 
185  m_pParentAlgorithm->UpdateUponDeletion(pMuonCluster);
186  m_pParentAlgorithm->UpdateUponDeletion(pDeltaRayCluster);
187 
188  m_pParentAlgorithm->SplitMuonCluster(m_pParentAlgorithm->GetClusterListName(hitType), pMuonCluster, deltaRayHits, pDeltaRayCluster);
189 
190  ClusterVector clusterVector;
191  PfoVector pfoVector;
192  clusterVector.push_back(pMuonCluster);
193  pfoVector.push_back(element.GetOverlapResult().GetCommonMuonPfoList().front());
194  clusterVector.push_back(pDeltaRayCluster);
195  pfoVector.push_back(nullptr);
196  m_pParentAlgorithm->UpdateForNewClusters(clusterVector, pfoVector);
197 }
198 
199 //------------------------------------------------------------------------------------------------------------------------------------------
200 
201 StatusCode DeltaRayRemovalTool::ReadSettings(const TiXmlHandle xmlHandle)
202 {
203  PANDORA_RETURN_RESULT_IF_AND_IF(
204  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitWindow", m_slidingFitWindow));
205 
206  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
207  XmlHelper::ReadValue(xmlHandle, "MinDeviationFromTransverse", m_minDeviationFromTransverse));
208 
209  PANDORA_RETURN_RESULT_IF_AND_IF(
210  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ContaminationWindow", m_contaminationWindow));
211 
212  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
213  XmlHelper::ReadValue(xmlHandle, "SignificantHitThreshold", m_significantHitThreshold));
214 
215  PANDORA_RETURN_RESULT_IF_AND_IF(
216  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinDistanceFromMuon", m_minDistanceFromMuon));
217 
218  PANDORA_RETURN_RESULT_IF_AND_IF(
219  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxDistanceToCollected", m_maxDistanceToCollected));
220 
221  return STATUS_CODE_SUCCESS;
222 }
223 
224 } // namespace lar_content
unsigned int m_slidingFitWindow
The sliding fit window used in cosmic ray parameterisations.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
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...
float m_contaminationWindow
The distance in which to search for delta ray contamination in the cosmic ray track.
enum cvn::HType HitType
Header file for the delta ray removal 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.
bool IsContaminated(const TensorType::Element &element, const pandora::HitType hitType) const
Determine whether the cosmic ray cluster under investigation has delta ray contamination.
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...
ThreeViewDeltaRayMatchingAlgorithm * m_pParentAlgorithm
Address of the parent matching algorithm.
static void GetClosestPositions(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, pandora::CartesianVector &position1, pandora::CartesianVector &position2)
Get pair of closest positions for a pair of clusters.
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
void UpdateUponDeletion(const pandora::Cluster *const pDeletedCluster)
Update to reflect cluster deletion.
float m_minDistanceFromMuon
The minimum distance of a hit from the cosmic ray track required for removal.
bool Run(ThreeViewDeltaRayMatchingAlgorithm *const pAlgorithm, TensorType &overlapTensor)
Run the algorithm tool.
Header file for the geometry helper class.
bool IsBestElement(const TensorType::Element &element, const pandora::HitType hitType, const TensorType::ElementList &elementList, const pandora::ClusterSet &modifiedClusters) const
Determine whether the input element is the best to use to modify the contaminated cluster (best is de...
float m_minDeviationFromTransverse
The minimum deviation from transverse required to avoid mistakes.
Header file for the cluster helper class.
float m_maxDistanceToCollected
The maximim distance of a hit from the projected delta ray hits required for removal.
virtual bool PassElementChecks(const TensorType::Element &element, const pandora::HitType hitType) const =0
Determine whether element satifies simple checks.
Header file for the lar two dimensional sliding fit result class.
void FindExtrapolatedHits(const pandora::Cluster *const pCluster, const pandora::CartesianVector &lowerBoundary, const pandora::CartesianVector &upperBoundary, pandora::CaloHitList &collectedHits) const
Collect the hits that are closest to and can be projected onto a defined line.
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 GetSortedKeyClusters(pandora::ClusterVector &sortedKeyClusters) const
Get a sorted vector of key clusters (U clusters with current implementation)
void GetGlobalDirection(const float dTdL, pandora::CartesianVector &direction) const
Get global direction coordinates for given sliding linear fit gradient.
const LayerFitResultMap & GetLayerFitResultMap() const
Get the layer fit result map.
#define M_PI
Definition: includeROOT.h:54
void SplitMuonCluster(const TensorType::Element &element, const pandora::HitType hitType, const pandora::CaloHitList &deltaRayHits) const
Remove collected delta ray hits from the cosmic ray pfo.
virtual bool PassElementChecks(const TensorType::Element &element, const pandora::HitType hitType) const
Determine whether element satifies simple checks.
const std::string & GetClusterListName(const pandora::HitType hitType) const
Get the cluster list name corresponding to a specified hit type.
unsigned int m_significantHitThreshold
The threshold number of hits which define significant contimination.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
bool IsMuonEndpoint(const TensorType::Element &element, const bool ignoreHitType, const pandora::HitType hitTypeToIgnore=pandora::TPC_VIEW_U) const
Determine whether the matched clusters suggest that the delta ray is at the endpoint of the cosmic ra...
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...
QTextStream & endl(QTextStream &s)
bool RemoveDeltaRayHits(const TensorType::ElementList &elementList) const
Remove hits from cosmic ray clusters that belong to a child delta ray.