LArSoft  v10_04_05
Liquid Argon Software toolkit - https://larsoft.org/
ThreeDReclusteringAlgorithm.cc
Go to the documentation of this file.
1 
9 #include "Managers/ClusterManager.h"
10 #include "Pandora/AlgorithmHeaders.h"
11 
16 
18 
19 using namespace pandora;
20 
21 namespace lar_content
22 {
23 
24 //Figure of merit type enum to string map
25 const std::unordered_map<std::string, ThreeDReclusteringAlgorithm::FigureOfMeritType> ThreeDReclusteringAlgorithm::m_stringToEnumMap = {
26  {"cheated", ThreeDReclusteringAlgorithm::FigureOfMeritType::CHEATED}};
27 
28 ThreeDReclusteringAlgorithm::ThreeDReclusteringAlgorithm() :
29  m_pfoListName("ShowerParticles3D"),
30  m_clusterListName("ShowerClusters3D"),
31  m_fomThresholdForReclustering(0.3),
32  m_minNumCaloHitsForReclustering(2),
33  m_uClustersListName("ClustersU"),
34  m_vClustersListName("ClustersV"),
35  m_wClustersListName("ClustersW")
36 {
37 }
38 
39 //------------------------------------------------------------------------------------------------------------------------------------------
40 
42 {
43 }
44 
45 //------------------------------------------------------------------------------------------------------------------------------------------
46 
48 {
49  //Only proceed if successfuly get shower pfo list, and it has at least one pfo
50  const PfoList *pShowerPfoList(nullptr);
51  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, m_pfoListName, pShowerPfoList));
52 
53  if (pShowerPfoList->empty())
54  return STATUS_CODE_SUCCESS;
55 
56  m_PfosForReclusteringListName = "newShowerParticles3D";
57  PfoList unchangedPfoList;
58 
59  //Save current pfo list name, so that this can be set as current again at the end of reclustering
60  std::string initialPfoListName;
61  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentListName<Pfo>(*this, initialPfoListName));
62 
63  //Some pfos are shower-like and yet include track-like 3D clusters. For the moment I don't want to deal with these.
64  const ClusterList *pShowerClusters(nullptr);
65  PandoraContentApi::GetList(*this, m_clusterListName, pShowerClusters);
66 
67  if (!pShowerClusters)
68  return STATUS_CODE_NOT_FOUND;
69 
70  for (const Pfo *const pShowerPfo : *pShowerPfoList)
71  {
72  ClusterList clusterList3D;
73  LArPfoHelper::GetThreeDClusterList(pShowerPfo, clusterList3D);
74 
75  //Check if pfo passes cuts for reclustering. Also, some pfos are shower-like and yet are made of track-like 3D clusters. For the moment I don't want to deal with these.
76  if ((!this->PassesCutsForReclustering(pShowerPfo)) ||
77  (pShowerClusters->end() == std::find(pShowerClusters->begin(), pShowerClusters->end(), clusterList3D.front())))
78  {
79  unchangedPfoList.push_back(pShowerPfo);
80  continue;
81  }
82 
83  CaloHitList initialCaloHitList;
84  clusterList3D.front()->GetOrderedCaloHitList().FillCaloHitList(initialCaloHitList);
85 
86  //Create a variable for the minimum figure of merit and initialize to initial FOM
87  float minimumFigureOfMerit(this->GetFigureOfMerit(initialCaloHitList));
88 
89  //Free the hits in this cluster, so that they are not owned by the original pfo, and are available for reclustering
90  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromPfo(*this, pShowerPfo, clusterList3D.front()));
91 
92  // Initialize reclustering with these local lists
93  std::string currentClustersListName;
94  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentListName<Cluster>(*this, currentClustersListName));
95  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*this, m_clusterListName));
96 
97  //Split the calo hit list into a new set of calo hit lists, taking the best outcome out of different algorithms
98  std::vector<CaloHitList> newCaloHitListsVector, minimumFigureOfMeritCaloHitListsVector;
99  minimumFigureOfMeritCaloHitListsVector.push_back(initialCaloHitList);
100 
101  for (auto *const pTool : m_algorithmToolVector)
102  {
103  try
104  {
105  pTool->Run(initialCaloHitList, newCaloHitListsVector);
106  }
107  catch (const StatusCodeException &)
108  {
109  std::cout << "Exception caught! Cannot run reclustering tool!" << std::endl;
110  continue;
111  }
112 
113  //Calculate FOM for this vector of new CaloHitLists
114  const float newFigureOfMerit(this->GetFigureOfMerit(newCaloHitListsVector));
115 
116  //Is this FOM smaller?
117  if (newFigureOfMerit < minimumFigureOfMerit)
118  {
119  minimumFigureOfMerit = newFigureOfMerit;
120  minimumFigureOfMeritCaloHitListsVector = newCaloHitListsVector;
121  }
122  newCaloHitListsVector.clear();
123  }
124 
125  //If the new best calo hit lists outcome is equivalent to original, move pfo to unchanged pfo list. Else, create new vector of 3D clusters
126  if ((minimumFigureOfMeritCaloHitListsVector.size() == 1) && (minimumFigureOfMeritCaloHitListsVector.at(0) == initialCaloHitList))
127  {
128  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToPfo(*this, pShowerPfo, clusterList3D.front()));
129  unchangedPfoList.push_back(pShowerPfo);
130  continue;
131  }
132 
133  const ClusterList reclusterClusterList(1, clusterList3D.front());
134  std::string clusterListToSaveName, clusterListToDeleteName;
135 
136  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
137  PandoraContentApi::InitializeFragmentation(*this, reclusterClusterList, clusterListToDeleteName, clusterListToSaveName));
138 
139  ClusterList newClustersList;
140  for (CaloHitList &list : minimumFigureOfMeritCaloHitListsVector)
141  {
142  const Cluster *pCluster = nullptr;
143  PandoraContentApi::Cluster::Parameters parameters;
144  parameters.m_caloHitList = list;
145  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*this, parameters, pCluster));
146  newClustersList.push_back(pCluster);
147  }
148 
149  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*this, clusterListToSaveName, clusterListToDeleteName));
150  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->RebuildPfo(pShowerPfo, newClustersList));
151  newCaloHitListsVector.clear();
152  }
153  //If there are any pfos that did not change after reclustering procedure, move them into list of new pfos after reclustering (where there may be some reclustered showers too)
154  if (unchangedPfoList.size() > 0)
155  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
156  PandoraContentApi::SaveList<PfoList>(*this, m_pfoListName, m_PfosForReclusteringListName, unchangedPfoList));
157 
158  //Save list of Pfos after reclustering and save into list called m_pfoListName
159  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Pfo>(*this, m_PfosForReclusteringListName, m_pfoListName));
160 
161  //Set current list to be the same as before reclustering
162  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Pfo>(*this, initialPfoListName));
163 
164  return STATUS_CODE_SUCCESS;
165 }
166 
167 //------------------------------------------------------------------------------------------------------------------------------------------
168 
169 StatusCode ThreeDReclusteringAlgorithm::BuildNewTwoDClusters(const Pfo *pPfoToRebuild, ClusterList &newClustersList)
170 {
171  ClusterList clusterList2D;
172  LArPfoHelper::GetTwoDClusterList(pPfoToRebuild, clusterList2D);
173 
174  for (const Cluster *const pTwoDCluster : clusterList2D)
175  {
176  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromPfo(*this, pPfoToRebuild, pTwoDCluster));
177  HitType hitType = LArClusterHelper::GetClusterHitType(pTwoDCluster);
178  std::string clusterListName(hitType == TPC_VIEW_U ? m_uClustersListName
179  : hitType == TPC_VIEW_V ? m_vClustersListName
181 
182  std::string initialListName = "";
183  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentListName<Cluster>(*this, initialListName));
184  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*this, clusterListName));
185 
186  std::string originalListName, fragmentListName;
187  ClusterList originalClusterList;
188  originalClusterList.push_back(pTwoDCluster);
189  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
190  PandoraContentApi::InitializeFragmentation(*this, originalClusterList, originalListName, fragmentListName));
191 
192  const OrderedCaloHitList &twoDClusterOrderedCaloHitList(pTwoDCluster->GetOrderedCaloHitList());
193  OrderedCaloHitList leftoverCaloHitList = twoDClusterOrderedCaloHitList;
194 
195  int iCluster(0);
196  for (const Cluster *pNewCluster3D : newClustersList)
197  {
198  if (!pNewCluster3D)
199  {
200  std::cout << "Error: found null pointer in list of new clusters!" << std::endl;
201  continue;
202  }
203  PandoraContentApi::Cluster::Parameters parameters;
204  CaloHitList newClusterCaloHitList3D;
205  pNewCluster3D->GetOrderedCaloHitList().FillCaloHitList(newClusterCaloHitList3D);
206 
207  for (const CaloHit *const p3DCaloHit : newClusterCaloHitList3D)
208  {
209  for (const OrderedCaloHitList::value_type &mapEntry : twoDClusterOrderedCaloHitList)
210  {
211  for (const CaloHit *const pCaloHit : *mapEntry.second)
212  {
213  if (pCaloHit == static_cast<const CaloHit *>(p3DCaloHit->GetParentAddress()))
214  {
215  parameters.m_caloHitList.push_back(static_cast<const CaloHit *>(pCaloHit));
216  leftoverCaloHitList.Remove(pCaloHit);
217  break;
218  }
219  }
220  }
221  }
222  const Cluster *pNewTwoDCluster(nullptr);
223  if (!parameters.m_caloHitList.empty())
224  {
225  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*this, parameters, pNewTwoDCluster));
226  }
227  if (pNewTwoDCluster != nullptr && !parameters.m_caloHitList.empty() && hitType == TPC_VIEW_U)
228  {
229  m_newClustersUMap.insert(std::make_pair(iCluster, pNewTwoDCluster));
230  }
231  else if (pNewTwoDCluster != nullptr && !parameters.m_caloHitList.empty() && hitType == TPC_VIEW_V)
232  {
233  m_newClustersVMap.insert(std::make_pair(iCluster, pNewTwoDCluster));
234  }
235  else if (pNewTwoDCluster != nullptr && !parameters.m_caloHitList.empty() && hitType == TPC_VIEW_W)
236  {
237  m_newClustersWMap.insert(std::make_pair(iCluster, pNewTwoDCluster));
238  }
239 
240  iCluster++;
241  }
242 
243  //Check the leftover caloHits. Attach to the nearest cluster in the new cluster list.
244  std::map<int, const Cluster *> clustersForLeftoverHitsMap(hitType == TPC_VIEW_U ? m_newClustersUMap
245  : hitType == TPC_VIEW_V ? m_newClustersVMap
247 
248  if (!clustersForLeftoverHitsMap.empty())
249  {
250  for (const OrderedCaloHitList::value_type &mapEntry : leftoverCaloHitList)
251  {
252  for (const CaloHit *const pCaloHit : *mapEntry.second)
253  {
254  const Cluster *pNearestCluster(nullptr);
255  double minimumDistance(std::numeric_limits<float>::max());
256  for (const auto &[clusterIndex, pNewTwoDCluster] : clustersForLeftoverHitsMap)
257  {
258  double dist = LArClusterHelper::GetClosestDistance(pCaloHit->GetPositionVector(), pNewTwoDCluster);
259  if (dist < minimumDistance)
260  {
261  minimumDistance = dist;
262  pNearestCluster = pNewTwoDCluster;
263  }
264  }
265  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*this, pNearestCluster, pCaloHit));
266  }
267  }
268  }
269 
270  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*this, fragmentListName, originalListName));
271  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*this, initialListName));
272  }
273 
274  return STATUS_CODE_SUCCESS;
275 }
276 
277 //------------------------------------------------------------------------------------------------------------------------------------------
278 
279 StatusCode ThreeDReclusteringAlgorithm::BuildNewPfos(const Pfo *pPfoToRebuild, ClusterList &newClustersList)
280 {
281  const PfoList *pNewPfoList(nullptr);
282  std::string newPfoListName = "changedShowerParticles3D";
283  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pNewPfoList, newPfoListName));
284 
285  const std::string originalClusterListName = "InitialCluster";
286  int iCluster(0);
287 
288  for (const Cluster *pNewThreeDCluster : newClustersList)
289  {
290  PandoraContentApi::ParticleFlowObject::Parameters pfoParameters;
291  const bool isAvailableU((m_newClustersUMap.count(iCluster)) && m_newClustersUMap.at(iCluster)->IsAvailable());
292  const bool isAvailableV((m_newClustersVMap.count(iCluster)) && m_newClustersVMap.at(iCluster)->IsAvailable());
293  const bool isAvailableW((m_newClustersWMap.count(iCluster)) && m_newClustersWMap.at(iCluster)->IsAvailable());
294  CaloHitList clusterUHits, clusterVHits, clusterWHits;
295  if (isAvailableU)
296  {
297  m_newClustersUMap.at(iCluster)->GetOrderedCaloHitList().FillCaloHitList(clusterUHits);
298  pfoParameters.m_clusterList.push_back(m_newClustersUMap.at(iCluster));
299  }
300  if (isAvailableV)
301  {
302  m_newClustersVMap.at(iCluster)->GetOrderedCaloHitList().FillCaloHitList(clusterVHits);
303  pfoParameters.m_clusterList.push_back(m_newClustersVMap.at(iCluster));
304  }
305  if (isAvailableW)
306  {
307  m_newClustersWMap.at(iCluster)->GetOrderedCaloHitList().FillCaloHitList(clusterWHits);
308  pfoParameters.m_clusterList.push_back(m_newClustersWMap.at(iCluster));
309  }
310  pfoParameters.m_clusterList.push_back(pNewThreeDCluster);
311 
312  pfoParameters.m_particleId = pPfoToRebuild->GetParticleId();
313  pfoParameters.m_charge = PdgTable::GetParticleCharge(pfoParameters.m_particleId.Get());
314  pfoParameters.m_mass = PdgTable::GetParticleMass(pfoParameters.m_particleId.Get());
315  pfoParameters.m_energy = 0.f;
316  pfoParameters.m_momentum = CartesianVector(0.f, 0.f, 0.f);
317 
318  const ParticleFlowObject *pNewPfo(nullptr);
319  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::Create(*this, pfoParameters, pNewPfo));
320 
321  iCluster++;
322  }
323  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Pfo>(*this, newPfoListName, m_PfosForReclusteringListName));
324 
325  return STATUS_CODE_SUCCESS;
326 }
327 
328 //------------------------------------------------------------------------------------------------------------------------------------------
329 
330 StatusCode ThreeDReclusteringAlgorithm::RebuildPfo(const Pfo *pPfoToRebuild, ClusterList &newClustersList)
331 {
332  m_newClustersUMap.clear();
333  m_newClustersVMap.clear();
334  m_newClustersWMap.clear();
335 
336  //For each of the new 3D clusters, build a new 2D cluster in each view, and a new Pfo
337  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->BuildNewTwoDClusters(pPfoToRebuild, newClustersList));
338  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->BuildNewPfos(pPfoToRebuild, newClustersList));
339 
340  return STATUS_CODE_SUCCESS;
341 }
342 
343 //------------------------------------------------------------------------------------------------------------------------------------------
344 
345 bool ThreeDReclusteringAlgorithm::PassesCutsForReclustering(const pandora::ParticleFlowObject *const pShowerPfo)
346 {
347  if (!LArPfoHelper::IsShower(pShowerPfo))
348  return false;
349  ClusterList clusterList3D;
350  LArPfoHelper::GetThreeDClusterList(pShowerPfo, clusterList3D);
351 
352  if (clusterList3D.empty())
353  return false;
354  CaloHitList caloHitList3D;
355  clusterList3D.front()->GetOrderedCaloHitList().FillCaloHitList(caloHitList3D);
356 
357  //Quality cuts
358  if (caloHitList3D.size() < m_minNumCaloHitsForReclustering)
359  return false;
360 
361  //Some pfos are shower-like and yet include track-like 3D clusters. For the moment I don't want to deal with these.
362  const ClusterList *pShowerClusters(nullptr);
363  PandoraContentApi::GetList(*this, m_clusterListName, pShowerClusters);
364  if (!pShowerClusters)
365  return false;
366 
367  if (this->GetFigureOfMerit(caloHitList3D) < m_fomThresholdForReclustering)
368  return false;
369  return true;
370 }
371 
372 //------------------------------------------------------------------------------------------------------------------------------------------
373 
374 float ThreeDReclusteringAlgorithm::GetCheatedFigureOfMerit(const CaloHitList &mergedClusterCaloHitList3D)
375 {
376  std::map<const pandora::MCParticle *, int> mainMcParticleMap;
377  for (const CaloHit *const pCaloHit3D : mergedClusterCaloHitList3D)
378  {
379  const CaloHit *const pParentCaloHit2D = static_cast<const CaloHit *>(pCaloHit3D->GetParentAddress());
380 
381  const MCParticle *const pMainMCParticle(MCParticleHelper::GetMainMCParticle(pParentCaloHit2D));
382 
383  std::map<const pandora::MCParticle *, int>::iterator it = mainMcParticleMap.find(pMainMCParticle);
384 
385  if (it != mainMcParticleMap.end())
386  it->second++;
387  else
388  mainMcParticleMap.insert(std::make_pair(pMainMCParticle, 1));
389  }
390  const auto maxSharedHits =
391  std::max_element(mainMcParticleMap.begin(), mainMcParticleMap.end(), [](const auto &x, const auto &y) { return x.second < y.second; });
392  const float mainMcParticleFraction = (float)maxSharedHits->second / mergedClusterCaloHitList3D.size();
393  return (1.f - mainMcParticleFraction);
394 }
395 
396 //------------------------------------------------------------------------------------------------------------------------------------------
397 
398 float ThreeDReclusteringAlgorithm::GetFigureOfMerit(const std::string &figureOfMeritName, const CaloHitList &mergedClusterCaloHitList3D)
399 {
400  float figureOfMerit(-999.f);
401 
402  FigureOfMeritType figureOfMeritType(FigureOfMeritType::CHEATED);
403  auto stringToEnumIt = m_stringToEnumMap.find(figureOfMeritName);
404  if (stringToEnumIt != m_stringToEnumMap.end())
405  {
406  figureOfMeritType = stringToEnumIt->second;
407  }
408 
409  if (figureOfMeritType == FigureOfMeritType::CHEATED)
410  figureOfMerit = this->GetCheatedFigureOfMerit(mergedClusterCaloHitList3D);
411  else
412  throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
413 
414  return figureOfMerit;
415 }
416 
417 //------------------------------------------------------------------------------------------------------------------------------------------
418 
419 float ThreeDReclusteringAlgorithm::GetFigureOfMerit(const std::string &figureOfMeritName, const std::vector<CaloHitList> &newClustersCaloHitLists3D)
420 {
421  std::vector<float> newClustersFigureOfMeritVector;
422  for (auto clusterCaloHitLists3D : newClustersCaloHitLists3D)
423  {
424  newClustersFigureOfMeritVector.push_back(this->GetFigureOfMerit(figureOfMeritName, clusterCaloHitLists3D));
425  }
426  const float figureOfMerit(*std::min_element(newClustersFigureOfMeritVector.begin(), newClustersFigureOfMeritVector.end()));
427  return figureOfMerit;
428 }
429 
430 //------------------------------------------------------------------------------------------------------------------------------------------
431 
432 float ThreeDReclusteringAlgorithm::GetFigureOfMerit(const std::vector<CaloHitList> &newClustersCaloHitLists3D)
433 {
434  std::vector<float> figureOfMeritVector;
435  for (StringVector::const_iterator iter = m_figureOfMeritNames.begin(), iterEnd = m_figureOfMeritNames.end(); iter != iterEnd; ++iter)
436  {
437  figureOfMeritVector.push_back(this->GetFigureOfMerit(*iter, newClustersCaloHitLists3D));
438  }
439 
440  const float figureOfMerit = *(std::min_element(figureOfMeritVector.begin(), figureOfMeritVector.end()));
441  return figureOfMerit;
442 }
443 
444 //------------------------------------------------------------------------------------------------------------------------------------------
445 
446 float ThreeDReclusteringAlgorithm::GetFigureOfMerit(const CaloHitList &mergedClusterCaloHitList3D)
447 {
448  std::vector<float> figureOfMeritVector;
449  for (StringVector::const_iterator iter = m_figureOfMeritNames.begin(), iterEnd = m_figureOfMeritNames.end(); iter != iterEnd; ++iter)
450  {
451  figureOfMeritVector.push_back(this->GetFigureOfMerit(*iter, mergedClusterCaloHitList3D));
452  }
453  const float figureOfMerit = *(std::min_element(figureOfMeritVector.begin(), figureOfMeritVector.end()));
454  return figureOfMerit;
455 }
456 
457 //------------------------------------------------------------------------------------------------------------------------------------------
458 
459 StatusCode ThreeDReclusteringAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
460 {
461  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadVectorOfValues(xmlHandle, "FigureOfMeritNames", m_figureOfMeritNames));
462  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "MCParticleListName", m_mcParticleListName));
463  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "PfoListName", m_pfoListName));
464  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ClusterListName", m_clusterListName));
465  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
466  XmlHelper::ReadValue(xmlHandle, "FOMThresholdForReclustering", m_fomThresholdForReclustering));
467  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
468  XmlHelper::ReadValue(xmlHandle, "MinimumNumberCaloHitsForReclustering", m_minNumCaloHitsForReclustering));
469  PANDORA_RETURN_RESULT_IF_AND_IF(
470  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "UClustersListName", m_uClustersListName));
471  PANDORA_RETURN_RESULT_IF_AND_IF(
472  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "VClustersListName", m_vClustersListName));
473  PANDORA_RETURN_RESULT_IF_AND_IF(
474  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "WClustersListName", m_wClustersListName));
475 
476  AlgorithmToolVector algorithmToolVector;
477  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*this, xmlHandle, "ClusteringTools", algorithmToolVector));
478 
479  for (auto algorithmTool : algorithmToolVector)
480  {
481  ClusteringTool *const pClusteringTool(dynamic_cast<ClusteringTool *>(algorithmTool));
482 
483  if (!pClusteringTool)
484  return STATUS_CODE_INVALID_PARAMETER;
485 
486  m_algorithmToolVector.push_back(pClusteringTool);
487  }
488  return STATUS_CODE_SUCCESS;
489 }
490 
491 } // namespace lar_content
Float_t x
Definition: compare.C:6
intermediate_table::iterator iterator
Header file for the pfo helper class.
pandora::StatusCode BuildNewPfos(const pandora::Pfo *pPfoToRebuild, pandora::ClusterList &newClustersList)
Create new Pfos for each new ThreeD cluster in newClustersList.
static void GetTwoDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 2D clusters from an input pfo.
Float_t y
Definition: compare.C:6
std::map< int, const pandora::Cluster * > m_newClustersVMap
Header file for the principal curve analysis helper class.
intermediate_table::const_iterator const_iterator
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
TFile f
Definition: plotHisto.C:6
std::string m_clusterListName
Name of the list of clusters to consider for reclustering.
std::string m_PfosForReclusteringListName
Name of the internal list to contain new Pfos before/after reclustering.
float m_fomThresholdForReclustering
A threshold on the minimum figure of merit for reclustering.
std::string m_pfoListName
Name of the list of pfos to consider for reclustering.
static bool IsShower(const pandora::ParticleFlowObject *const pPfo)
Return shower flag based on Pfo Particle ID.
pandora::StatusCode RebuildPfo(const pandora::Pfo *pPfoToRebuild, pandora::ClusterList &newClustersList)
Create new TwoD clusters and Pfos for each new ThreeD cluster in newClustersList. ...
std::map< int, const pandora::Cluster * > m_newClustersWMap
Per-view maps associating new 3D clusters with new 2D clusters.
Header file for the lar monte carlo particle helper helper class.
Header file for the cluster helper class.
float GetCheatedFigureOfMerit(const pandora::CaloHitList &mergedClusterCaloHitList3D)
Get cheated FOM as an impurity: the fraction of hits that are NOT contributed by the main MC particle...
static const std::unordered_map< std::string, ThreeDReclusteringAlgorithm::FigureOfMeritType > m_stringToEnumMap
FigureOfMeritType
FigureOfMerit type enumeration.
static void GetThreeDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 3D clusters from an input pfo.
std::string m_mcParticleListName
The mc particle list name.
double dist(const TReal *x, const TReal *y, const unsigned int dimension)
Header file for the reclustering algorithm class.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
HitType
Definition: HitType.h:12
std::map< int, const pandora::Cluster * > m_newClustersUMap
float GetFigureOfMerit(const pandora::CaloHitList &mergedClusterCaloHitList3D)
Loop over all specified figure of merit names, calculate figures of merit for the CaloHitList under c...
bool PassesCutsForReclustering(const pandora::ParticleFlowObject *const pPfo)
Select pfos to be reclustered if it passes reclustering criteria.
ClusteringToolVector m_algorithmToolVector
The reclustering algorithm tool vector.
pandora::StringVector m_figureOfMeritNames
The names of the figures of merit to use.
pandora::StatusCode BuildNewTwoDClusters(const pandora::Pfo *pPfoToRebuild, pandora::ClusterList &newClustersList)
Create new TwoD clusters for each new ThreeD cluster in newClustersList.
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.