Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
LArOverlapTensor.cc
Go to the documentation of this file.
1
10
13#include "Pandora/StatusCodes.h"
14
15#include "Objects/Cluster.h"
16
18
22
23#include <algorithm>
24
25using namespace pandora;
26
27namespace lar_content
28{
29
30template <typename T>
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
41template <typename T>
42void 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
78template <typename T>
79bool 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
94template <typename T>
95void 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}
105//------------------------------------------------------------------------------------------------------------------------------------------
106
107template <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
118template <typename T>
119void 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
145template <typename T>
146void 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
169template <typename T>
171{
172 ClusterList additionalRemovals;
173
174 if (m_clusterNavigationMapUV.erase(pCluster) > 0)
175 {
176 typename TheTensor::iterator iter = m_overlapTensor.find(pCluster);
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//------------------------------------------------------------------------------------------------------------------------------------------
251template <typename T>
252void 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;
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 }
287 }
288
289 std::sort(elementList.begin(), elementList.end());
290}
291
292//------------------------------------------------------------------------------------------------------------------------------------------
293
294template <typename T>
295void 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(
309
310 if (clusterList.end() != std::find(clusterList.begin(), clusterList.end(), pCluster))
311 return;
312
313 clusterList.push_back(pCluster);
314 ClusterNavigationMap::const_iterator iter = navigationMap.find(pCluster);
315
316 if (navigationMap.end() == iter)
317 throw StatusCodeException(STATUS_CODE_FAILURE);
318
319 for (ClusterList::const_iterator cIter = iter->second.begin(), cIterEnd = iter->second.end(); cIter != cIterEnd; ++cIter)
320 this->ExploreConnections(*cIter, ignoreUnavailable, clusterListU, clusterListV, clusterListW);
321}
322
323//------------------------------------------------------------------------------------------------------------------------------------------
324
325template class OverlapTensor<float>;
331
332} // namespace lar_content
Header file for the cluster class.
Header file for the cluster helper class.
Header file for the lar overlap tensor class.
Header file for the lar shower overlap result class.
Header file for the lar track overlap result class.
Header file for pandora input types and associated external typedefs exposed via the PandoraApi.
Header file defining relevant internal typedefs, sort and string conversion functions.
Header file defining status codes and relevant preprocessor macros.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
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,...
TheMatrix::const_iterator const_iterator
const pandora::Cluster * GetCluster(const pandora::HitType hitType) const
Get the address of the given hit type cluster.
const pandora::Cluster * m_pClusterW
The address of the w cluster.
const pandora::Cluster * m_pClusterU
The address of the u cluster.
const pandora::Cluster * m_pClusterV
The address of the v cluster.
const_iterator end() const
Returns an iterator referring to the past-the-end element in the overlap tensor.
ClusterNavigationMap m_clusterNavigationMapWU
The cluster navigation map W->U.
void SetOverlapResult(const pandora::Cluster *const pClusterU, const pandora::Cluster *const pClusterV, const pandora::Cluster *const pClusterW, const OverlapResult &overlapResult)
Set overlap result.
void GetConnectedElements(const pandora::Cluster *const pCluster, const bool ignoreUnavailable, ElementList &elementList) const
Get a list of elements connected to a specified cluster.
void ReplaceOverlapResult(const pandora::Cluster *const pClusterU, const pandora::Cluster *const pClusterV, const pandora::Cluster *const pClusterW, const OverlapResult &overlapResult)
SetReplace an existing overlap result.
ClusterNavigationMap m_clusterNavigationMapUV
The cluster navigation map U->V.
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterNavigationMap
TheTensor m_overlapTensor
The overlap tensor.
void GetUnambiguousElements(const bool ignoreUnavailable, ElementList &elementList) const
Get unambiguous elements.
void ExploreConnections(const pandora::Cluster *const pCluster, const bool ignoreUnavailable, pandora::ClusterList &clusterListU, pandora::ClusterList &clusterListV, pandora::ClusterList &clusterListW) const
Explore connections associated with a given cluster.
const_iterator begin() const
Returns an iterator referring to the first element in the overlap tensor.
void GetSortedKeyClusters(pandora::ClusterVector &sortedKeyClusters) const
Get a sorted vector of key clusters (U clusters with current implementation)
std::unordered_map< const pandora::Cluster *, OverlapResult > OverlapList
bool DefaultAmbiguityFunction(const pandora::ClusterList &clusterListU, const pandora::ClusterList &clusterListV, const pandora::ClusterList &clusterListW, const pandora::Cluster *&pClusterU, const pandora::Cluster *&pClusterV, const pandora::Cluster *&pClusterW) const
Default ambiguity function, checking that only one U, V and W cluster is found.
std::vector< Element > ElementList
void RemoveCluster(const pandora::Cluster *const pCluster)
Remove entries from tensor corresponding to specified cluster.
ClusterNavigationMap m_clusterNavigationMapVW
The cluster navigation map V->W.
Cluster class.
Definition Cluster.h:31
bool IsAvailable() const
Whether the cluster is available to be added to a particle flow object.
Definition Cluster.h:582
StatusCodeException class.
HitType
Calorimeter hit type enum.
std::vector< const Cluster * > ClusterVector
MANAGED_CONTAINER< const Cluster * > ClusterList