LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
LArOverlapTensor.cc
Go to the documentation of this file.
1 
9 #include "Pandora/PandoraInputTypes.h"
10 
11 #include "Pandora/PandoraInputTypes.h"
12 #include "Pandora/PandoraInternal.h"
13 #include "Pandora/StatusCodes.h"
14 
15 #include "Objects/Cluster.h"
16 
18 
22 
23 #include <algorithm>
24 
25 using namespace pandora;
26 
27 namespace lar_content
28 {
29 
30 template <typename T>
31 const Cluster *OverlapTensor<T>::Element::GetCluster(const HitType hitType) const
32 {
33  if ((hitType != TPC_VIEW_U) && (hitType != TPC_VIEW_V) && (hitType != TPC_VIEW_W))
34  throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
35 
36  return (hitType == TPC_VIEW_U) ? m_pClusterU : (hitType == TPC_VIEW_V) ? m_pClusterV : m_pClusterW;
37 }
38 
39 //------------------------------------------------------------------------------------------------------------------------------------------
40 
41 template <typename T>
42 void OverlapTensor<T>::GetUnambiguousElements(const bool ignoreUnavailable, ElementList &elementList) const
43 {
44  for (typename TheTensor::const_iterator iterU = this->begin(), iterUEnd = this->end(); iterU != iterUEnd; ++iterU)
45  {
46  ElementList tempElementList;
47  ClusterList clusterListU, clusterListV, clusterListW;
48  this->GetConnectedElements(iterU->first, ignoreUnavailable, tempElementList, clusterListU, clusterListV, clusterListW);
49 
50  const Cluster *pClusterU(nullptr), *pClusterV(nullptr), *pClusterW(nullptr);
51  if (!this->DefaultAmbiguityFunction(clusterListU, clusterListV, clusterListW, pClusterU, pClusterV, pClusterW))
52  continue;
53 
54  // ATTN With HIT_CUSTOM definitions, it is possible to navigate from different U clusters to same combination
55  if (iterU->first != pClusterU)
56  continue;
57 
58  if (!pClusterU || !pClusterV || !pClusterW)
59  continue;
60 
61  typename OverlapMatrix::const_iterator iterV = iterU->second.find(pClusterV);
62  if (iterU->second.end() == iterV)
63  throw StatusCodeException(STATUS_CODE_FAILURE);
64 
65  typename OverlapList::const_iterator iterW = iterV->second.find(pClusterW);
66  if (iterV->second.end() == iterW)
67  throw StatusCodeException(STATUS_CODE_FAILURE);
68 
69  Element element(pClusterU, pClusterV, pClusterW, iterW->second);
70  elementList.push_back(element);
71  }
72 
73  std::sort(elementList.begin(), elementList.end());
74 }
75 
76 //------------------------------------------------------------------------------------------------------------------------------------------
77 
78 template <typename T>
79 bool OverlapTensor<T>::DefaultAmbiguityFunction(const ClusterList &clusterListU, const ClusterList &clusterListV,
80  const ClusterList &clusterListW, const Cluster *&pClusterU, const Cluster *&pClusterV, const Cluster *&pClusterW) const
81 {
82  if ((1 != clusterListU.size()) || (1 != clusterListV.size()) || (1 != clusterListW.size()))
83  return false;
84 
85  pClusterU = *(clusterListU.begin());
86  pClusterV = *(clusterListV.begin());
87  pClusterW = *(clusterListW.begin());
88 
89  return true;
90 }
91 
92 //------------------------------------------------------------------------------------------------------------------------------------------
93 
94 template <typename T>
95 void OverlapTensor<T>::GetConnectedElements(const pandora::Cluster *const pCluster, const bool ignoreUnavailable, ElementList &elementList,
96  unsigned int &nU, unsigned int &nV, unsigned int &nW) const
97 {
98  ClusterList clusterListU, clusterListV, clusterListW;
99  this->GetConnectedElements(pCluster, ignoreUnavailable, elementList, clusterListU, clusterListV, clusterListW);
100  nU = clusterListU.size();
101  nV = clusterListV.size();
102  nW = clusterListW.size();
103 }
104 
105 //------------------------------------------------------------------------------------------------------------------------------------------
106 
107 template <typename T>
109 {
110  for (typename TheTensor::const_iterator iterU = this->begin(), iterUEnd = this->end(); iterU != iterUEnd; ++iterU)
111  sortedKeyClusters.push_back(iterU->first);
112 
113  std::sort(sortedKeyClusters.begin(), sortedKeyClusters.end(), LArClusterHelper::SortByNHits);
114 }
115 
116 //------------------------------------------------------------------------------------------------------------------------------------------
117 
118 template <typename T>
119 void OverlapTensor<T>::SetOverlapResult(const pandora::Cluster *const pClusterU, const pandora::Cluster *const pClusterV,
120  const pandora::Cluster *const pClusterW, const OverlapResult &overlapResult)
121 {
122  OverlapList &overlapList = m_overlapTensor[pClusterU][pClusterV];
123  typename OverlapList::const_iterator iter = overlapList.find(pClusterW);
124 
125  if (overlapList.end() != iter)
126  throw pandora::StatusCodeException(pandora::STATUS_CODE_ALREADY_PRESENT);
127 
128  if (!overlapList.insert(typename OverlapList::value_type(pClusterW, overlapResult)).second)
129  throw pandora::StatusCodeException(pandora::STATUS_CODE_FAILURE);
130 
131  ClusterList &navigationUV(m_clusterNavigationMapUV[pClusterU]);
132  ClusterList &navigationVW(m_clusterNavigationMapVW[pClusterV]);
133  ClusterList &navigationWU(m_clusterNavigationMapWU[pClusterW]);
134 
135  if (navigationUV.end() == std::find(navigationUV.begin(), navigationUV.end(), pClusterV))
136  navigationUV.push_back(pClusterV);
137  if (navigationVW.end() == std::find(navigationVW.begin(), navigationVW.end(), pClusterW))
138  navigationVW.push_back(pClusterW);
139  if (navigationWU.end() == std::find(navigationWU.begin(), navigationWU.end(), pClusterU))
140  navigationWU.push_back(pClusterU);
141 }
142 
143 //------------------------------------------------------------------------------------------------------------------------------------------
144 
145 template <typename T>
146 void OverlapTensor<T>::ReplaceOverlapResult(const pandora::Cluster *const pClusterU, const pandora::Cluster *const pClusterV,
147  const pandora::Cluster *const pClusterW, const OverlapResult &overlapResult)
148 {
149  typename TheTensor::iterator iterU = m_overlapTensor.find(pClusterU);
150 
151  if (m_overlapTensor.end() == iterU)
152  throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
153 
154  typename OverlapMatrix::iterator iterV = iterU->second.find(pClusterV);
155 
156  if (iterU->second.end() == iterV)
157  throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
158 
159  typename OverlapList::iterator iterW = iterV->second.find(pClusterW);
160 
161  if (iterV->second.end() == iterW)
162  throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
163 
164  iterW->second = overlapResult;
165 }
166 
167 //------------------------------------------------------------------------------------------------------------------------------------------
168 
169 template <typename T>
170 void OverlapTensor<T>::RemoveCluster(const pandora::Cluster *const pCluster)
171 {
172  ClusterList additionalRemovals;
173 
174  if (m_clusterNavigationMapUV.erase(pCluster) > 0)
175  {
176  typename TheTensor::iterator iter = m_overlapTensor.find(pCluster);
177 
178  if (m_overlapTensor.end() != iter)
179  m_overlapTensor.erase(iter);
180 
181  for (ClusterNavigationMap::iterator navIter = m_clusterNavigationMapWU.begin(); navIter != m_clusterNavigationMapWU.end();)
182  {
183  ClusterNavigationMap::iterator thisIter = navIter++;
184  ClusterList::iterator listIter = std::find(thisIter->second.begin(), thisIter->second.end(), pCluster);
185 
186  if (thisIter->second.end() != listIter)
187  thisIter->second.erase(listIter);
188 
189  if (thisIter->second.empty())
190  additionalRemovals.push_back(thisIter->first);
191  }
192  }
193 
194  if (m_clusterNavigationMapVW.erase(pCluster) > 0)
195  {
196  for (typename TheTensor::iterator iterU = m_overlapTensor.begin(), iterUEnd = m_overlapTensor.end(); iterU != iterUEnd; ++iterU)
197  {
198  typename OverlapMatrix::iterator iter = iterU->second.find(pCluster);
199 
200  if (iterU->second.end() != iter)
201  iterU->second.erase(iter);
202  }
203 
204  for (ClusterNavigationMap::iterator navIter = m_clusterNavigationMapUV.begin(); navIter != m_clusterNavigationMapUV.end();)
205  {
206  ClusterNavigationMap::iterator thisIter = navIter++;
207  ClusterList::iterator listIter = std::find(thisIter->second.begin(), thisIter->second.end(), pCluster);
208 
209  if (thisIter->second.end() != listIter)
210  thisIter->second.erase(listIter);
211 
212  if (thisIter->second.empty())
213  additionalRemovals.push_back(thisIter->first);
214  }
215  }
216 
217  if (m_clusterNavigationMapWU.erase(pCluster) > 0)
218  {
219  for (typename TheTensor::iterator iterU = m_overlapTensor.begin(), iterUEnd = m_overlapTensor.end(); iterU != iterUEnd; ++iterU)
220  {
221  for (typename OverlapMatrix::iterator iterV = iterU->second.begin(), iterVEnd = iterU->second.end(); iterV != iterVEnd; ++iterV)
222  {
223  typename OverlapList::iterator iter = iterV->second.find(pCluster);
224 
225  if (iterV->second.end() != iter)
226  iterV->second.erase(iter);
227  }
228  }
229 
230  for (ClusterNavigationMap::iterator navIter = m_clusterNavigationMapVW.begin(); navIter != m_clusterNavigationMapVW.end();)
231  {
232  ClusterNavigationMap::iterator thisIter = navIter++;
233  ClusterList::iterator listIter = std::find(thisIter->second.begin(), thisIter->second.end(), pCluster);
234 
235  if (thisIter->second.end() != listIter)
236  thisIter->second.erase(listIter);
237 
238  if (thisIter->second.empty())
239  additionalRemovals.push_back(thisIter->first);
240  }
241  }
242 
243  additionalRemovals.sort(LArClusterHelper::SortByNHits);
244 
245  for (ClusterList::const_iterator iter = additionalRemovals.begin(), iterEnd = additionalRemovals.end(); iter != iterEnd; ++iter)
246  this->RemoveCluster(*iter);
247 }
248 
249 //------------------------------------------------------------------------------------------------------------------------------------------
250 
251 template <typename T>
252 void OverlapTensor<T>::GetConnectedElements(const Cluster *const pCluster, const bool ignoreUnavailable, ElementList &elementList,
253  ClusterList &clusterListU, ClusterList &clusterListV, ClusterList &clusterListW) const
254 {
255  ClusterList localClusterListU, localClusterListV, localClusterListW;
256  this->ExploreConnections(pCluster, ignoreUnavailable, localClusterListU, localClusterListV, localClusterListW);
257 
258  // ATTN Now need to check that all clusters received are from fully available tensor elements
259  elementList.clear();
260  clusterListU.clear();
261  clusterListV.clear();
262  clusterListW.clear();
263 
264  for (typename TheTensor::const_iterator iterU = this->begin(), iterUEnd = this->end(); iterU != iterUEnd; ++iterU)
265  {
266  if (localClusterListU.end() == std::find(localClusterListU.begin(), localClusterListU.end(), iterU->first))
267  continue;
268 
269  for (typename OverlapMatrix::const_iterator iterV = iterU->second.begin(), iterVEnd = iterU->second.end(); iterV != iterVEnd; ++iterV)
270  {
271  for (typename OverlapList::const_iterator iterW = iterV->second.begin(), iterWEnd = iterV->second.end(); iterW != iterWEnd; ++iterW)
272  {
273  if (ignoreUnavailable && (!iterU->first->IsAvailable() || !iterV->first->IsAvailable() || !iterW->first->IsAvailable()))
274  continue;
275 
276  Element element(iterU->first, iterV->first, iterW->first, iterW->second);
277  elementList.push_back(element);
278 
279  if (clusterListU.end() == std::find(clusterListU.begin(), clusterListU.end(), iterU->first))
280  clusterListU.push_back(iterU->first);
281  if (clusterListV.end() == std::find(clusterListV.begin(), clusterListV.end(), iterV->first))
282  clusterListV.push_back(iterV->first);
283  if (clusterListW.end() == std::find(clusterListW.begin(), clusterListW.end(), iterW->first))
284  clusterListW.push_back(iterW->first);
285  }
286  }
287  }
288 
289  std::sort(elementList.begin(), elementList.end());
290 }
291 
292 //------------------------------------------------------------------------------------------------------------------------------------------
293 
294 template <typename T>
295 void OverlapTensor<T>::ExploreConnections(const Cluster *const pCluster, const bool ignoreUnavailable, ClusterList &clusterListU,
296  ClusterList &clusterListV, ClusterList &clusterListW) const
297 {
298  if (ignoreUnavailable && !pCluster->IsAvailable())
299  return;
300 
301  const HitType hitType(LArClusterHelper::GetClusterHitType(pCluster));
302 
303  if (!((TPC_VIEW_U == hitType) || (TPC_VIEW_V == hitType) || (TPC_VIEW_W == hitType)))
304  throw StatusCodeException(STATUS_CODE_FAILURE);
305 
306  ClusterList &clusterList((TPC_VIEW_U == hitType) ? clusterListU : (TPC_VIEW_V == hitType) ? clusterListV : clusterListW);
307  const ClusterNavigationMap &navigationMap((TPC_VIEW_U == hitType) ? m_clusterNavigationMapUV
308  : (TPC_VIEW_V == hitType) ? m_clusterNavigationMapVW
309  : m_clusterNavigationMapWU);
310 
311  if (clusterList.end() != std::find(clusterList.begin(), clusterList.end(), pCluster))
312  return;
313 
314  clusterList.push_back(pCluster);
315  ClusterNavigationMap::const_iterator iter = navigationMap.find(pCluster);
316 
317  if (navigationMap.end() == iter)
318  throw StatusCodeException(STATUS_CODE_FAILURE);
319 
320  for (ClusterList::const_iterator cIter = iter->second.begin(), cIterEnd = iter->second.end(); cIter != cIterEnd; ++cIter)
321  this->ExploreConnections(*cIter, ignoreUnavailable, clusterListU, clusterListV, clusterListW);
322 }
323 
324 //------------------------------------------------------------------------------------------------------------------------------------------
325 
326 template class OverlapTensor<float>;
332 
333 } // namespace lar_content
intermediate_table::iterator iterator
OverlapTensor class.
Header file for the lar overlap tensor class.
intermediate_table::const_iterator const_iterator
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
std::vector< Element > ElementList
Header file for the cluster helper class.
TheMatrix::const_iterator const_iterator
Header file for the lar shower overlap result class.
std::unordered_map< const pandora::Cluster *, OverlapResult > OverlapList
Header file for the lar track overlap result class.
HitType
Definition: HitType.h:12
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterNavigationMap
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:69
std::vector< art::Ptr< recob::Cluster > > ClusterVector