LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
ThreeDBaseAlgorithm.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
10 
12 
16 
18 
19 using namespace pandora;
20 
21 namespace lar_content
22 {
23 
24 template <typename T>
26  m_pInputClusterListU(NULL),
27  m_pInputClusterListV(NULL),
28  m_pInputClusterListW(NULL)
29 {
30 }
31 
32 //------------------------------------------------------------------------------------------------------------------------------------------
33 
34 template <typename T>
36 {
37 }
38 
39 //------------------------------------------------------------------------------------------------------------------------------------------
40 
41 template <typename T>
43 {
44  bool particlesMade(false);
45  const PfoList *pPfoList = NULL; std::string pfoListName;
46  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pPfoList, pfoListName));
47 
48  for (typename ProtoParticleVector::const_iterator iter = protoParticleVector.begin(), iterEnd = protoParticleVector.end(); iter != iterEnd; ++iter)
49  {
50  PandoraContentApi::ParticleFlowObject::Parameters pfoParameters;
51  this->SetPfoParameters(*iter, pfoParameters);
52 
53  const ParticleFlowObject *pPfo(NULL);
54  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::Create(*this, pfoParameters, pPfo));
55  particlesMade = true;
56  }
57 
58  if (!pPfoList->empty())
59  {
60  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Pfo>(*this, m_outputPfoListName));
61  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Pfo>(*this, m_outputPfoListName));
62  }
63 
64  return particlesMade;
65 }
66 
67 //------------------------------------------------------------------------------------------------------------------------------------------
68 
69 template <typename T>
71 {
72  ClusterSet deletedClusters;
73 
74  ClusterList parentClusters;
75  for (const auto &mapEntry : clusterMergeMap) parentClusters.push_back(mapEntry.first);
76  parentClusters.sort(LArClusterHelper::SortByNHits);
77 
78  for (const Cluster *const pParentCluster : parentClusters)
79  {
80  const HitType hitType(LArClusterHelper::GetClusterHitType(pParentCluster));
81  const std::string clusterListName((TPC_VIEW_U == hitType) ? this->GetClusterListNameU() : (TPC_VIEW_V == hitType) ? this->GetClusterListNameV() : this->GetClusterListNameW());
82 
83  if (!((TPC_VIEW_U == hitType) || (TPC_VIEW_V == hitType) || (TPC_VIEW_W == hitType)))
84  throw StatusCodeException(STATUS_CODE_FAILURE);
85 
86  ClusterList daughterClusters(clusterMergeMap.at(pParentCluster));
87  daughterClusters.sort(LArClusterHelper::SortByNHits);
88 
89  for (const Cluster *const pDaughterCluster : daughterClusters)
90  {
91  if (deletedClusters.count(pParentCluster) || deletedClusters.count(pDaughterCluster))
92  throw StatusCodeException(STATUS_CODE_FAILURE);
93 
94  this->UpdateUponDeletion(pDaughterCluster);
95  this->UpdateUponDeletion(pParentCluster);
96  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*this, pParentCluster, pDaughterCluster, clusterListName, clusterListName));
97 
98  this->UpdateForNewCluster(pParentCluster);
99  deletedClusters.insert(pDaughterCluster);
100  }
101  }
102 
103  return !(deletedClusters.empty());
104 }
105 
106 //------------------------------------------------------------------------------------------------------------------------------------------
107 
108 template <typename T>
109 void ThreeDBaseAlgorithm<T>::UpdateForNewCluster(const Cluster *const pNewCluster)
110 {
111  const HitType hitType(LArClusterHelper::GetClusterHitType(pNewCluster));
112 
113  if (!((TPC_VIEW_U == hitType) || (TPC_VIEW_V == hitType) || (TPC_VIEW_W == hitType)))
114  throw StatusCodeException(STATUS_CODE_FAILURE);
115 
116  ClusterList &clusterList((TPC_VIEW_U == hitType) ? m_clusterListU : (TPC_VIEW_V == hitType) ? m_clusterListV : m_clusterListW);
117 
118  if (clusterList.end() != std::find(clusterList.begin(), clusterList.end(), pNewCluster))
119  throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
120 
121  clusterList.push_back(pNewCluster);
122 
123  const ClusterList &clusterList1((TPC_VIEW_U == hitType) ? m_clusterListV : m_clusterListU);
124  const ClusterList &clusterList2((TPC_VIEW_W == hitType) ? m_clusterListV : m_clusterListW);
125 
126  ClusterVector clusterVector1(clusterList1.begin(), clusterList1.end());
127  ClusterVector clusterVector2(clusterList2.begin(), clusterList2.end());
128  std::sort(clusterVector1.begin(), clusterVector1.end(), LArClusterHelper::SortByNHits);
129  std::sort(clusterVector2.begin(), clusterVector2.end(), LArClusterHelper::SortByNHits);
130 
131  for (const Cluster *const pCluster1 : clusterVector1)
132  {
133  for (const Cluster *const pCluster2 : clusterVector2)
134  {
135  if (TPC_VIEW_U == hitType)
136  {
137  this->CalculateOverlapResult(pNewCluster, pCluster1, pCluster2);
138  }
139  else if (TPC_VIEW_V == hitType)
140  {
141  this->CalculateOverlapResult(pCluster1, pNewCluster, pCluster2);
142  }
143  else
144  {
145  this->CalculateOverlapResult(pCluster1, pCluster2, pNewCluster);
146  }
147  }
148  }
149 }
150 
151 //------------------------------------------------------------------------------------------------------------------------------------------
152 
153 template <typename T>
154 void ThreeDBaseAlgorithm<T>::UpdateUponDeletion(const Cluster *const pDeletedCluster)
155 {
156  ClusterList::iterator iterU = std::find(m_clusterListU.begin(), m_clusterListU.end(), pDeletedCluster);
157  ClusterList::iterator iterV = std::find(m_clusterListV.begin(), m_clusterListV.end(), pDeletedCluster);
158  ClusterList::iterator iterW = std::find(m_clusterListW.begin(), m_clusterListW.end(), pDeletedCluster);
159 
160  if (m_clusterListU.end() != iterU)
161  m_clusterListU.erase(iterU);
162 
163  if (m_clusterListV.end() != iterV)
164  m_clusterListV.erase(iterV);
165 
166  if (m_clusterListW.end() != iterW)
167  m_clusterListW.erase(iterW);
168 
169  m_overlapTensor.RemoveCluster(pDeletedCluster);
170 }
171 
172 //------------------------------------------------------------------------------------------------------------------------------------------
173 
174 template <typename T>
176 {
180  ClusterList usedClusters;
181 
182  for (typename TensorType::ClusterNavigationMap::const_iterator iter = navigationMapUV.begin(), iterEnd = navigationMapUV.end(); iter != iterEnd; ++iter)
183  {
184  if (!(iter->first->IsAvailable()))
185  usedClusters.push_back(iter->first);
186  }
187 
188  for (typename TensorType::ClusterNavigationMap::const_iterator iter = navigationMapVW.begin(), iterEnd = navigationMapVW.end(); iter != iterEnd; ++iter)
189  {
190  if (!(iter->first->IsAvailable()))
191  usedClusters.push_back(iter->first);
192  }
193 
194  for (typename TensorType::ClusterNavigationMap::const_iterator iter = navigationMapWU.begin(), iterEnd = navigationMapWU.end(); iter != iterEnd; ++iter)
195  {
196  if (!(iter->first->IsAvailable()))
197  usedClusters.push_back(iter->first);
198  }
199 
200  usedClusters.sort(LArClusterHelper::SortByNHits);
201 
202  for (ClusterList::const_iterator iter = usedClusters.begin(), iterEnd = usedClusters.end(); iter != iterEnd; ++iter)
203  this->UpdateUponDeletion(*iter);
204 }
205 
206 //------------------------------------------------------------------------------------------------------------------------------------------
207 
208 template <typename T>
210 {
214 }
215 
216 //------------------------------------------------------------------------------------------------------------------------------------------
217 
218 template <typename T>
220 {
221 }
222 
223 //------------------------------------------------------------------------------------------------------------------------------------------
224 
225 template <typename T>
227 {
229 
230  m_pInputClusterListU = NULL;
231  m_pInputClusterListV = NULL;
232  m_pInputClusterListW = NULL;
233 
234  m_clusterListU.clear();
235  m_clusterListV.clear();
236  m_clusterListW.clear();
237 }
238 
239 //------------------------------------------------------------------------------------------------------------------------------------------
240 
241 template <typename T>
243 {
244  try
245  {
246  PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this,
248  PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this,
250  PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this,
252 
253  if ((NULL == m_pInputClusterListU) || (NULL == m_pInputClusterListV) || (NULL == m_pInputClusterListW))
254  {
255  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
256  std::cout << "ThreeDBaseAlgorithm: one or more input cluster lists unavailable." << std::endl;
257  throw StatusCodeException(STATUS_CODE_SUCCESS);
258  }
259 
260  this->SelectAllInputClusters();
261  this->PreparationStep();
262  this->PerformMainLoop();
263  this->ExamineTensor();
264  this->TidyUp();
265  }
266  catch (StatusCodeException &statusCodeException)
267  {
268  this->TidyUp();
269 
270  if (STATUS_CODE_SUCCESS != statusCodeException.GetStatusCode())
271  throw statusCodeException;
272  }
273 
274  return STATUS_CODE_SUCCESS;
275 }
276 
277 //------------------------------------------------------------------------------------------------------------------------------------------
278 
279 template <typename T>
281 {
282  ClusterVector clusterVectorU(m_clusterListU.begin(), m_clusterListU.end());
283  ClusterVector clusterVectorV(m_clusterListV.begin(), m_clusterListV.end());
284  ClusterVector clusterVectorW(m_clusterListW.begin(), m_clusterListW.end());
285  std::sort(clusterVectorU.begin(), clusterVectorU.end(), LArClusterHelper::SortByNHits);
286  std::sort(clusterVectorV.begin(), clusterVectorV.end(), LArClusterHelper::SortByNHits);
287  std::sort(clusterVectorW.begin(), clusterVectorW.end(), LArClusterHelper::SortByNHits);
288 
289  for (const Cluster *const pClusterU : clusterVectorU)
290  {
291  for (const Cluster *const pClusterV : clusterVectorV)
292  {
293  for (const Cluster *const pClusterW : clusterVectorW)
294  this->CalculateOverlapResult(pClusterU, pClusterV, pClusterW);
295  }
296  }
297 }
298 
299 //------------------------------------------------------------------------------------------------------------------------------------------
300 
301 template <typename T>
302 StatusCode ThreeDBaseAlgorithm<T>::ReadSettings(const TiXmlHandle xmlHandle)
303 {
304  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputClusterListNameU", m_inputClusterListNameU));
305  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputClusterListNameV", m_inputClusterListNameV));
306  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputClusterListNameW", m_inputClusterListNameW));
307  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "OutputPfoListName", m_outputPfoListName));
308 
309  return STATUS_CODE_SUCCESS;
310 }
311 
312 template class ThreeDBaseAlgorithm<float>;
317 
318 } // namespace lar_content
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.
std::vector< ProtoParticle > ProtoParticleVector
ThreeDBaseAlgorithm class.
virtual void PerformMainLoop()
Main loop over cluster combinations in order to populate the tensor. Responsible for calling Calculat...
virtual void CalculateOverlapResult(const pandora::Cluster *const pClusterU, const pandora::Cluster *const pClusterV, const pandora::Cluster *const pClusterW)=0
Calculate cluster overlap result and store in tensor.
virtual void SelectInputClusters(const pandora::ClusterList *const pInputClusterList, pandora::ClusterList &selectedClusterList) const =0
Select a subset of input clusters for processing in this algorithm.
const std::string & GetClusterListNameU() const
Get the name of the u cluster list.
std::string m_inputClusterListNameV
The name of the view V cluster list.
pandora::ClusterList m_clusterListW
The selected modified cluster list W.
const ClusterNavigationMap & GetClusterNavigationMapVW() const
Get the cluster navigation map V->W.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Header file for the lar overlap tensor class.
intermediate_table::iterator iterator
virtual bool CreateThreeDParticles(const ProtoParticleVector &protoParticleVector)
Create particles using findings from recent algorithm processing.
const std::string & GetClusterListNameV() const
Get the name of the v cluster list.
const ClusterNavigationMap & GetClusterNavigationMapUV() const
Get the cluster navigation map U->V.
const pandora::ClusterList * m_pInputClusterListV
Address of the input cluster list V.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
const pandora::ClusterList * m_pInputClusterListU
Address of the input cluster list U.
virtual void SelectAllInputClusters()
Select a subset of input clusters for processing in this algorithm.
const pandora::ClusterList * m_pInputClusterListW
Address of the input cluster list W.
pandora::ClusterList m_clusterListV
The selected modified cluster list V.
const std::string & GetClusterListNameW() const
Get the name of the w cluster list.
virtual void ExamineTensor()=0
Examine contents of tensor, collect together best-matching 2D particles and modify clusters as requir...
void Clear()
Clear overlap tensor.
intermediate_table::const_iterator const_iterator
Header file for the three dimension algorithm base class.
virtual ~ThreeDBaseAlgorithm()
Destructor.
Header file for the cluster helper class.
TensorType m_overlapTensor
The overlap tensor.
virtual void RemoveUnavailableTensorElements()
Update tensor to remove all elements that have been added to pfos and so are unavailable.
virtual void SetPfoParameters(const ProtoParticle &protoParticle, PandoraContentApi::ParticleFlowObject::Parameters &pfoParameters) const =0
Calculate Pfo properties from proto particle.
virtual void TidyUp()
Tidy member variables in derived class.
Header file for the lar shower overlap result class.
std::string m_inputClusterListNameW
The name of the view W cluster list.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterMergeMap
Header file for the lar track overlap result class.
virtual void PreparationStep()
Perform any preparatory steps required, e.g. caching expensive fit results for clusters.
virtual void UpdateUponDeletion(const pandora::Cluster *const pDeletedCluster)
Update to reflect cluster deletion.
virtual void UpdateForNewCluster(const pandora::Cluster *const pNewCluster)
Update to reflect addition of a new cluster to the problem space.
pandora::ClusterList m_clusterListU
The selected modified cluster list U.
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterNavigationMap
std::string m_inputClusterListNameU
The name of the view U cluster list.
void RemoveCluster(const pandora::Cluster *const pCluster)
Remove entries from tensor corresponding to specified cluster.
const ClusterNavigationMap & GetClusterNavigationMapWU() const
Get the cluster navigation map W->U.
std::string m_outputPfoListName
The output pfo list name.
TheTensor::const_iterator const_iterator
virtual bool MakeClusterMerges(const ClusterMergeMap &clusterMergeMap)
Merge clusters together.