NViewTrackMatchingAlgorithm.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArThreeDReco/LArThreeDBase/NViewTrackMatchingAlgorithm.cc
3  *
4  * @brief Implementation of the n view track matching algorithm class.
5  *
6  * $Log: $
7  */
8 
9 #include "Pandora/AlgorithmHeaders.h"
10 
13 
17 
21 
22 using namespace pandora;
23 
24 namespace lar_content
25 {
26 
27 template <typename T>
29  m_slidingFitWindow(20),
30  m_minClusterCaloHits(5),
31  m_minClusterLengthSquared(3.f * 3.f)
32 {
33 }
34 
35 //------------------------------------------------------------------------------------------------------------------------------------------
36 
37 template <typename T>
39 {
40 }
41 
42 //------------------------------------------------------------------------------------------------------------------------------------------
43 
44 template <typename T>
46 {
48 
49  if (m_slidingFitResultMap.end() == iter)
50  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
51 
52  return iter->second;
53 }
54 
55 //------------------------------------------------------------------------------------------------------------------------------------------
56 
57 template <typename T>
59 {
60  bool changesMade(false);
61 
62  ClusterList splitClusters;
63  for (const auto &mapEntry : splitPositionMap)
64  splitClusters.push_back(mapEntry.first);
65  splitClusters.sort(LArClusterHelper::SortByNHits);
66 
67  for (const Cluster *pCurrentCluster : splitClusters)
68  {
69  CartesianPointVector splitPositions(splitPositionMap.at(pCurrentCluster));
70  std::sort(splitPositions.begin(), splitPositions.end(), NViewTrackMatchingAlgorithm<T>::SortSplitPositions);
71 
72  const HitType hitType(LArClusterHelper::GetClusterHitType(pCurrentCluster));
73  const std::string &clusterListName(this->GetClusterListName(hitType));
74 
75  if (!((TPC_VIEW_U == hitType) || (TPC_VIEW_V == hitType) || (TPC_VIEW_W == hitType)))
76  throw StatusCodeException(STATUS_CODE_FAILURE);
77 
78  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*this, clusterListName));
79 
80  for (const CartesianVector &splitPosition : splitPositions)
81  {
82  const Cluster *pLowXCluster(nullptr), *pHighXCluster(nullptr);
83  this->UpdateUponDeletion(pCurrentCluster);
84 
85  if (this->MakeClusterSplit(splitPosition, pCurrentCluster, pLowXCluster, pHighXCluster))
86  {
87  changesMade = true;
88  this->UpdateForNewCluster(pLowXCluster);
89  this->UpdateForNewCluster(pHighXCluster);
90  pCurrentCluster = pHighXCluster;
91  }
92  else
93  {
94  this->UpdateForNewCluster(pCurrentCluster);
95  }
96  }
97  }
98 
99  return changesMade;
100 }
101 
102 //------------------------------------------------------------------------------------------------------------------------------------------
103 
104 template <typename T>
106  const CartesianVector &splitPosition, const Cluster *&pCurrentCluster, const Cluster *&pLowXCluster, const Cluster *&pHighXCluster) const
107 {
108  CartesianVector lowXEnd(0.f, 0.f, 0.f), highXEnd(0.f, 0.f, 0.f);
109 
110  try
111  {
112  LArPointingCluster pointingCluster(pCurrentCluster);
113  const bool innerIsLowX(pointingCluster.GetInnerVertex().GetPosition().GetX() < pointingCluster.GetOuterVertex().GetPosition().GetX());
114  lowXEnd = (innerIsLowX ? pointingCluster.GetInnerVertex().GetPosition() : pointingCluster.GetOuterVertex().GetPosition());
115  highXEnd = (innerIsLowX ? pointingCluster.GetOuterVertex().GetPosition() : pointingCluster.GetInnerVertex().GetPosition());
116  }
117  catch (const StatusCodeException &)
118  {
119  return false;
120  }
121 
122  const CartesianVector lowXUnitVector((lowXEnd - splitPosition).GetUnitVector());
123  const CartesianVector highXUnitVector((highXEnd - splitPosition).GetUnitVector());
124 
125  CaloHitList caloHitList;
126  pCurrentCluster->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
127 
128  std::string originalListName, fragmentListName;
129  const ClusterList clusterList(1, pCurrentCluster);
130  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::InitializeFragmentation(*this, clusterList, originalListName, fragmentListName));
131 
132  pLowXCluster = nullptr;
133  pHighXCluster = nullptr;
134 
135  for (const CaloHit *const pCaloHit : caloHitList)
136  {
137  const CartesianVector unitVector((pCaloHit->GetPositionVector() - splitPosition).GetUnitVector());
138  const float dotProductLowX(unitVector.GetDotProduct(lowXUnitVector));
139  const float dotProductHighX(unitVector.GetDotProduct(highXUnitVector));
140 
141  const Cluster *&pClusterToModify((dotProductLowX > dotProductHighX) ? pLowXCluster : pHighXCluster);
142 
143  if (!pClusterToModify)
144  {
145  PandoraContentApi::Cluster::Parameters parameters;
146  parameters.m_caloHitList.push_back(pCaloHit);
147  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*this, parameters, pClusterToModify));
148  }
149  else
150  {
151  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*this, pClusterToModify, pCaloHit));
152  }
153  }
154 
155  if (!pLowXCluster || !pHighXCluster)
156  {
157  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*this, originalListName, fragmentListName));
158  return false;
159  }
160 
161  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*this, fragmentListName, originalListName));
162  return true;
163 }
164 
165 //------------------------------------------------------------------------------------------------------------------------------------------
166 
167 template <typename T>
168 bool NViewTrackMatchingAlgorithm<T>::SortSplitPositions(const pandora::CartesianVector &lhs, const pandora::CartesianVector &rhs)
169 {
170  return (lhs.GetX() < rhs.GetX());
171 }
172 
173 //------------------------------------------------------------------------------------------------------------------------------------------
174 
175 template <typename T>
176 void NViewTrackMatchingAlgorithm<T>::UpdateForNewCluster(const Cluster *const pNewCluster)
177 {
178  try
179  {
180  this->AddToSlidingFitCache(pNewCluster);
181  }
182  catch (const StatusCodeException &statusCodeException)
183  {
184  if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
185  throw statusCodeException;
186 
187  return;
188  }
189 
191 }
192 
193 //------------------------------------------------------------------------------------------------------------------------------------------
194 
195 template <typename T>
196 void NViewTrackMatchingAlgorithm<T>::UpdateUponDeletion(const Cluster *const pDeletedCluster)
197 {
198  this->RemoveFromSlidingFitCache(pDeletedCluster);
200 }
201 
202 //------------------------------------------------------------------------------------------------------------------------------------------
203 
204 template <typename T>
205 void NViewTrackMatchingAlgorithm<T>::SelectInputClusters(const ClusterList *const pInputClusterList, ClusterList &selectedClusterList) const
206 {
207  for (const Cluster *const pCluster : *pInputClusterList)
208  {
209  if (!pCluster->IsAvailable())
210  continue;
211 
212  if (pCluster->GetNCaloHits() < m_minClusterCaloHits)
213  continue;
214 
216  continue;
217 
218  selectedClusterList.push_back(pCluster);
219  }
220 }
221 
222 //------------------------------------------------------------------------------------------------------------------------------------------
223 
224 template <typename T>
225 void NViewTrackMatchingAlgorithm<T>::PrepareInputClusters(ClusterList &preparedClusterList)
226 {
227  for (ClusterList::iterator iter = preparedClusterList.begin(), iterEnd = preparedClusterList.end(); iter != iterEnd;)
228  {
229  try
230  {
231  this->AddToSlidingFitCache(*iter);
232  ++iter;
233  }
234  catch (const StatusCodeException &statusCodeException)
235  {
236  preparedClusterList.erase(iter++);
237 
238  if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
239  throw statusCodeException;
240  }
241  }
242 }
243 
244 //------------------------------------------------------------------------------------------------------------------------------------------
245 
246 template <typename T>
247 void NViewTrackMatchingAlgorithm<T>::SetPfoParticleId(PandoraContentApi::ParticleFlowObject::Parameters &pfoParameters) const
248 {
249  pfoParameters.m_particleId = MU_MINUS; // Track
250 }
251 
252 //------------------------------------------------------------------------------------------------------------------------------------------
253 
254 template <typename T>
255 void NViewTrackMatchingAlgorithm<T>::AddToSlidingFitCache(const Cluster *const pCluster)
256 {
257  const float slidingFitPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
258  const TwoDSlidingFitResult slidingFitResult(pCluster, m_slidingFitWindow, slidingFitPitch);
259 
260  if (!m_slidingFitResultMap.insert(TwoDSlidingFitResultMap::value_type(pCluster, slidingFitResult)).second)
261  throw StatusCodeException(STATUS_CODE_FAILURE);
262 }
263 
264 //------------------------------------------------------------------------------------------------------------------------------------------
265 
266 template <typename T>
268 {
270 
271  if (m_slidingFitResultMap.end() != iter)
272  m_slidingFitResultMap.erase(iter);
273 }
274 
275 //------------------------------------------------------------------------------------------------------------------------------------------
276 
277 template <typename T>
279 {
280  m_slidingFitResultMap.clear();
282 }
283 
284 //------------------------------------------------------------------------------------------------------------------------------------------
285 
286 template <typename T>
287 StatusCode NViewTrackMatchingAlgorithm<T>::ReadSettings(const TiXmlHandle xmlHandle)
288 {
289  PANDORA_RETURN_RESULT_IF_AND_IF(
290  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitWindow", m_slidingFitWindow));
291 
292  PANDORA_RETURN_RESULT_IF_AND_IF(
293  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinClusterCaloHits", m_minClusterCaloHits));
294 
295  float minClusterLength = std::sqrt(m_minClusterLengthSquared);
296  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinClusterLength", minClusterLength));
297  m_minClusterLengthSquared = minClusterLength * minClusterLength;
298 
299  return NViewMatchingAlgorithm<T>::ReadSettings(xmlHandle);
300 }
301 
302 //------------------------------------------------------------------------------------------------------------------------------------------
303 
310 
311 } // namespace lar_content
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
static bool SortSplitPositions(const pandora::CartesianVector &lhs, const pandora::CartesianVector &rhs)
Sort split position cartesian vectors by increasing x coordinate.
intermediate_table::iterator iterator
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.
void AddToSlidingFitCache(const pandora::Cluster *const pCluster)
Add a new sliding fit result, for the specified cluster, to the algorithm cache.
Header file for the n view track matching algorithm class.
virtual bool MakeClusterSplits(const SplitPositionMap &splitPositionMap)
Make cluster splits.
Header file for the lar pointing cluster class.
virtual void PrepareInputClusters(pandora::ClusterList &preparedClusterList)
Perform any preparatory steps required on the input clusters, e.g. caching expensive fit results...
virtual void UpdateUponDeletion(const pandora::Cluster *const pDeletedCluster)
Update to reflect cluster deletion.
enum cvn::HType HitType
std::string string
Definition: nybbler.cc:12
const TwoDSlidingFitResult & GetCachedSlidingFitResult(const pandora::Cluster *const pCluster) const
Get a sliding fit result from the algorithm cache.
virtual void TidyUp()
Tidy member variables in derived class.
intermediate_table::const_iterator const_iterator
LArPointingCluster class.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
virtual void TidyUp()
Tidy member variables in derived class.
float m_minClusterLengthSquared
The min length (squared) in base cluster selection method.
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.
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.
Header file for the cluster helper class.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
const Vertex & GetOuterVertex() const
Get the outer vertex.
std::unordered_map< const pandora::Cluster *, pandora::CartesianPointVector > SplitPositionMap
const Vertex & GetInnerVertex() const
Get the inner vertex.
void RemoveFromSlidingFitCache(const pandora::Cluster *const pCluster)
Remova an existing sliding fit result, for the specified cluster, from the algorithm cache...
Header file for the lar track overlap result class.
virtual void SetPfoParticleId(PandoraContentApi::ParticleFlowObject::Parameters &pfoParameters) const
Set pfo particle id.
unsigned int m_minClusterCaloHits
The min number of hits in base cluster selection method.
virtual bool MakeClusterSplit(const pandora::CartesianVector &splitPosition, const pandora::Cluster *&pCurrentCluster, const pandora::Cluster *&pLowXCluster, const pandora::Cluster *&pHighXCluster) const
Make a cluster split.
Header file for the three view matching control class.
virtual void SelectInputClusters(const pandora::ClusterList *const pInputClusterList, pandora::ClusterList &selectedClusterList) const
Select a subset of input clusters for processing in this algorithm.
unsigned int m_slidingFitWindow
The layer window for the sliding linear fits.
TwoDSlidingFitResultMap m_slidingFitResultMap
The sliding fit result map.
const std::string & GetClusterListName(const pandora::HitType hitType) const
Get the cluster list name corresponding to a specified hit type.
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
Header file for the two view matching control class.
virtual void UpdateForNewCluster(const pandora::Cluster *const pNewCluster)
Update to reflect addition of a new cluster to the problem space.
Header file for the lar track two view overlap result class.
const pandora::CartesianVector & GetPosition() const
Get the vertex position.