LArSoft  v10_06_00
Liquid Argon Software toolkit - https://larsoft.org/
lar_content::ThreeDMultiReclusteringAlgorithm Class Reference

ThreeDMultiReclusteringAlgorithm class. More...

#include "ThreeDMultiReclusteringAlgorithm.h"

Inheritance diagram for lar_content::ThreeDMultiReclusteringAlgorithm:

Public Member Functions

 ThreeDMultiReclusteringAlgorithm ()
 Default constructor. More...
 
 ~ThreeDMultiReclusteringAlgorithm ()=default
 Default destructor. More...
 

Private Member Functions

pandora::StatusCode Run ()
 
pandora::StatusCode FreeClustersFromPfos (const pandora::PfoList &pfos, std::map< pandora::HitType, pandora::ClusterList > &viewToFreeClusters, std::map< const pandora::Pfo *const, pandora::ClusterList > &pfoToFreeClusters) const
 Remove clusters from the pfos and store them them in maps. More...
 
pandora::StatusCode RelinkClustersToOriginalPfos (std::map< const pandora::Pfo *const, pandora::ClusterList > &pfoToClusters) const
 Remake the original pfos by adding back their removed clusters. More...
 
pandora::StatusCode FreeCaloHitsFromClusters (const pandora::ClusterList &clusters, const pandora::HitType &view, pandora::CaloHitList &freeCaloHits) const
 Delete clusters of a single hit type and store the associated hits in a list. More...
 
pandora::StatusCode BuildNewPfos (const pandora::ClusterList &clusters3D, std::map< pandora::HitType, pandora::CaloHitList > &viewToFreeCaloHits2D) const
 Create new pfos from the reclustered 3D clusters and original 2D hits. The original 2D hits are put into new 2D clusters that follow the new 3D clusters,. More...
 
pandora::StatusCode Build2DClustersFrom3D (const pandora::Cluster *const pCluster3D, std::map< pandora::HitType, pandora::CaloHitList > &viewToFreeCaloHits2D, pandora::ClusterList &newClusters2D) const
 Create 2D clusters following a 3D cluster. More...
 
pandora::StatusCode MopUpCaloHits (const pandora::CaloHitList &caloHits, const pandora::ClusterList &clusters, bool addAsIso) const
 Add hits to their nearest cluster. More...
 
pandora::StatusCode CreatePfoFromClusters (const pandora::ClusterList &clusters) const
 Create a new pfo from a list of clusters. More...
 
pandora::StatusCode ReadSettings (const pandora::TiXmlHandle xmlHandle)
 

Private Attributes

std::string m_pfoListName
 Name of list of pfos to consider for reclustering. More...
 
std::map< pandora::HitType, std::string > m_clusterListNames
 Map of list names for 3D clusters that comprise the pfos and 2D U, V, W clusters that may need reclustering. More...
 
bool m_mopUp2DCaloHits
 Add hits from reclustered 2D clusters without an associated 3D hit to the nearest new 2D cluster in their view. More...
 
std::vector< std::string > m_clusteringAlgs
 The ordered list of clustering algorithms to use. More...
 
ThreeDReclusteringFigureOfMeritBaseToolm_pFomAlgTool
 The address of the figure of merit algorithm tool to use. More...
 

Detailed Description

Constructor & Destructor Documentation

lar_content::ThreeDMultiReclusteringAlgorithm::ThreeDMultiReclusteringAlgorithm ( )

Default constructor.

Definition at line 24 of file ThreeDMultiReclusteringAlgorithm.cc.

References m_mopUp2DCaloHits, and m_pFomAlgTool.

24  :
25  m_clusterListNames{{TPC_3D, {}}, {TPC_VIEW_U, "ClustersU"}, {TPC_VIEW_V, "ClustersV"}, {TPC_VIEW_W, "ClustersW"}},
26  m_mopUp2DCaloHits{true},
27  m_pFomAlgTool{nullptr}
28 {
29 }
ThreeDReclusteringFigureOfMeritBaseTool * m_pFomAlgTool
The address of the figure of merit algorithm tool to use.
bool m_mopUp2DCaloHits
Add hits from reclustered 2D clusters without an associated 3D hit to the nearest new 2D cluster in t...
std::map< pandora::HitType, std::string > m_clusterListNames
Map of list names for 3D clusters that comprise the pfos and 2D U, V, W clusters that may need reclus...
lar_content::ThreeDMultiReclusteringAlgorithm::~ThreeDMultiReclusteringAlgorithm ( )
default

Default destructor.

Member Function Documentation

StatusCode lar_content::ThreeDMultiReclusteringAlgorithm::Build2DClustersFrom3D ( const pandora::Cluster *const  pCluster3D,
std::map< pandora::HitType, pandora::CaloHitList > &  viewToFreeCaloHits2D,
pandora::ClusterList &  newClusters2D 
) const
private

Create 2D clusters following a 3D cluster.

Parameters
pCluster3Da 3D cluster
viewToFreeCaloHits2Dmap of hit type to original 2D hits that need to be clustered
newClusters2Doutput list of newly created 2D clusters

Definition at line 224 of file ThreeDMultiReclusteringAlgorithm.cc.

References m_clusterListNames.

Referenced by BuildNewPfos().

226 {
227  std::map<HitType, PandoraContentApi::Cluster::Parameters> viewToParamsCluster2D = {{TPC_VIEW_U, {}}, {TPC_VIEW_V, {}}, {TPC_VIEW_W, {}}};
228 
229  CaloHitList cluster3DCaloHits3D;
230  pCluster3D->GetOrderedCaloHitList().FillCaloHitList(cluster3DCaloHits3D);
231  for (const CaloHit *const pCaloHit3D : cluster3DCaloHits3D)
232  {
233  const CaloHit *const pCaloHit3DParent2D{static_cast<const CaloHit *>(pCaloHit3D->GetParentAddress())};
234  const HitType view{pCaloHit3DParent2D->GetHitType()};
235  if (std::find(viewToFreeCaloHits2D.at(view).begin(), viewToFreeCaloHits2D.at(view).end(), pCaloHit3DParent2D) ==
236  viewToFreeCaloHits2D.at(view).end())
237  return STATUS_CODE_FAILURE;
238  viewToParamsCluster2D.at(view).m_caloHitList.push_back(pCaloHit3DParent2D);
239  viewToFreeCaloHits2D.at(view).remove(pCaloHit3DParent2D);
240  }
241 
242  CaloHitList cluster3DIsoCaloHits3D{pCluster3D->GetIsolatedCaloHitList()};
243  for (const CaloHit *const pCaloHit3D : cluster3DIsoCaloHits3D)
244  {
245  const CaloHit *const pCaloHit3DParent2D{static_cast<const CaloHit *>(pCaloHit3D->GetParentAddress())};
246  const HitType view{pCaloHit3DParent2D->GetHitType()};
247  if (std::find(viewToFreeCaloHits2D.at(view).begin(), viewToFreeCaloHits2D.at(view).end(), pCaloHit3DParent2D) ==
248  viewToFreeCaloHits2D.at(view).end())
249  return STATUS_CODE_FAILURE;
250  viewToParamsCluster2D.at(view).m_isolatedCaloHitList.push_back(pCaloHit3DParent2D);
251  viewToFreeCaloHits2D.at(view).remove(pCaloHit3DParent2D);
252  }
253 
254  for (const auto &[view, params] : viewToParamsCluster2D)
255  {
256  if (params.m_caloHitList.empty() && params.m_isolatedCaloHitList.empty())
257  continue;
258 
259  std::string tempListName;
260  const ClusterList *pTempClusterList{nullptr};
261  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pTempClusterList, tempListName));
262  const Cluster *pNewCluster2D{nullptr};
263  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*this, params, pNewCluster2D));
264  std::string cluster2DListName{m_clusterListNames.at(view)};
265  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Cluster>(*this, tempListName, cluster2DListName));
266  newClusters2D.push_back(pNewCluster2D);
267  }
268 
269  return STATUS_CODE_SUCCESS;
270 }
std::map< pandora::HitType, std::string > m_clusterListNames
Map of list names for 3D clusters that comprise the pfos and 2D U, V, W clusters that may need reclus...
HitType
Definition: HitType.h:12
StatusCode lar_content::ThreeDMultiReclusteringAlgorithm::BuildNewPfos ( const pandora::ClusterList &  clusters3D,
std::map< pandora::HitType, pandora::CaloHitList > &  viewToFreeCaloHits2D 
) const
private

Create new pfos from the reclustered 3D clusters and original 2D hits. The original 2D hits are put into new 2D clusters that follow the new 3D clusters,.

Parameters
clusters3Dlist of reclustered 3D clusters
viewToFreeCaloHits2Dmap of hit type to original 2D hits that need to be clustered

Definition at line 170 of file ThreeDMultiReclusteringAlgorithm.cc.

References Build2DClustersFrom3D(), CreatePfoFromClusters(), lar_content::LArClusterHelper::GetClusterHitType(), m_clusterListNames, m_mopUp2DCaloHits, m_pfoListName, and MopUpCaloHits().

Referenced by Run().

171 {
172  // Cluster any 2D hits directly associated with 3D hits in the same way as the 3D clusters
173  std::map<HitType, ClusterList> viewToNewClusters2D = {{TPC_VIEW_U, {}}, {TPC_VIEW_V, {}}, {TPC_VIEW_W, {}}};
174  std::vector<ClusterList> newPfoClusters;
175  for (const Cluster *const pCluster3D : clusters)
176  {
177  ClusterList newClusters;
178  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, Build2DClustersFrom3D(pCluster3D, viewToFreeCaloHits2D, newClusters));
179  for (const Cluster *const pCluster : newClusters)
180  viewToNewClusters2D.at(LArClusterHelper::GetClusterHitType(pCluster)).emplace_back(pCluster);
181  newClusters.emplace_back(pCluster3D);
182  newPfoClusters.emplace_back(newClusters);
183  }
184 
185  // Put any remaining 2D hits into the nearest new 2D cluster made in the last step
186  // NOTE Hits added to 2D clusters this way are added as isolated
187  if (m_mopUp2DCaloHits)
188  {
189  for (const auto &[view, caloHits2D] : viewToFreeCaloHits2D)
190  {
191  // If no 2D clusters for a view could be made in the previous step (happens rarely when no 3D hits get made from a cluster view),
192  // just mop up the remaining 2D hits into the old 2D clusters
193  if (viewToNewClusters2D.at(view).empty())
194  {
195  std::string clusterListName{m_clusterListNames.at(view)};
196  const ClusterList *pOldClusters2D{nullptr};
197  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, clusterListName, pOldClusters2D));
198  // This means no hits in this view made any 3D hits, this happens very rarely for events with few hits.
199  // In this case, just leave these hits unclustered. Could also consider putting them in their own isolated hit-only cluster?
200  if (pOldClusters2D->empty())
201  continue;
202  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, MopUpCaloHits(caloHits2D, *pOldClusters2D, true));
203  continue;
204  }
205  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, MopUpCaloHits(caloHits2D, viewToNewClusters2D.at(view), true));
206  }
207  }
208 
209  // Create the new Pfos
210  // ATTN New pfos will: have no vertex, not be characterised as track/shower, not be part of any particle hierarchy.
211  // If desired, these these things will need to be added in succeeding algs.
212  const PfoList *pNewPfoList{nullptr};
213  std::string tempPfoListName;
214  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pNewPfoList, tempPfoListName));
215  for (const ClusterList &pfoClusters : newPfoClusters)
216  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, CreatePfoFromClusters(pfoClusters));
217  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Pfo>(*this, tempPfoListName, m_pfoListName));
218 
219  return STATUS_CODE_SUCCESS;
220 }
pandora::StatusCode CreatePfoFromClusters(const pandora::ClusterList &clusters) const
Create a new pfo from a list of clusters.
std::string m_pfoListName
Name of list of pfos to consider for reclustering.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
pandora::StatusCode Build2DClustersFrom3D(const pandora::Cluster *const pCluster3D, std::map< pandora::HitType, pandora::CaloHitList > &viewToFreeCaloHits2D, pandora::ClusterList &newClusters2D) const
Create 2D clusters following a 3D cluster.
bool m_mopUp2DCaloHits
Add hits from reclustered 2D clusters without an associated 3D hit to the nearest new 2D cluster in t...
pandora::StatusCode MopUpCaloHits(const pandora::CaloHitList &caloHits, const pandora::ClusterList &clusters, bool addAsIso) const
Add hits to their nearest cluster.
std::map< pandora::HitType, std::string > m_clusterListNames
Map of list names for 3D clusters that comprise the pfos and 2D U, V, W clusters that may need reclus...
StatusCode lar_content::ThreeDMultiReclusteringAlgorithm::CreatePfoFromClusters ( const pandora::ClusterList &  clusters) const
private

Create a new pfo from a list of clusters.

Parameters
clusterslist of clusters, expect a 3D and up to 3 2D clusters.

Definition at line 307 of file ThreeDMultiReclusteringAlgorithm.cc.

References f.

Referenced by BuildNewPfos().

308 {
309  PandoraContentApi::ParticleFlowObject::Parameters params;
310  params.m_clusterList = clusters;
311  params.m_particleId = MU_MINUS; // Arbitrary choice to mark all new pfos as track-like
312  params.m_charge = PdgTable::GetParticleCharge(params.m_particleId.Get());
313  params.m_mass = PdgTable::GetParticleMass(params.m_particleId.Get());
314  params.m_energy = 0.f;
315  params.m_momentum = CartesianVector(0.f, 0.f, 0.f);
316  const Pfo *pPfo{nullptr};
317  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::Create(*this, params, pPfo));
318 
319  return STATUS_CODE_SUCCESS;
320 }
TFile f
Definition: plotHisto.C:6
StatusCode lar_content::ThreeDMultiReclusteringAlgorithm::FreeCaloHitsFromClusters ( const pandora::ClusterList &  clusters,
const pandora::HitType &  view,
pandora::CaloHitList &  freeCaloHits 
) const
private

Delete clusters of a single hit type and store the associated hits in a list.

Parameters
clusterslist of clusters to be deleted
viewhit type of the clusters
freeCaloHitsoutput hits of the deleted clusters

Definition at line 153 of file ThreeDMultiReclusteringAlgorithm.cc.

References m_clusterListNames.

Referenced by Run().

154 {
155  std::string clusterListName{m_clusterListNames.at(view)};
156  for (const Cluster *const pCluster : clusters)
157  {
158  CaloHitList caloHits;
159  pCluster->GetOrderedCaloHitList().FillCaloHitList(caloHits);
160  freeCaloHits.insert(freeCaloHits.end(), caloHits.begin(), caloHits.end());
161  freeCaloHits.insert(freeCaloHits.end(), pCluster->GetIsolatedCaloHitList().begin(), pCluster->GetIsolatedCaloHitList().end());
162  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete(*this, pCluster, clusterListName));
163  }
164 
165  return STATUS_CODE_SUCCESS;
166 }
std::map< pandora::HitType, std::string > m_clusterListNames
Map of list names for 3D clusters that comprise the pfos and 2D U, V, W clusters that may need reclus...
StatusCode lar_content::ThreeDMultiReclusteringAlgorithm::FreeClustersFromPfos ( const pandora::PfoList &  pfos,
std::map< pandora::HitType, pandora::ClusterList > &  viewToFreeClusters,
std::map< const pandora::Pfo *const, pandora::ClusterList > &  pfoToFreeClusters 
) const
private

Remove clusters from the pfos and store them them in maps.

Parameters
pfospfo list
viewToFreeClustersoutput map of hit type to list of removed clusters
pfoToFreeClustersoutput map of original pfo to list of removed clusters

Definition at line 117 of file ThreeDMultiReclusteringAlgorithm.cc.

References lar_content::LArPfoHelper::GetClusters().

Referenced by Run().

119 {
120  for (const Pfo *const pPfo : pfos)
121  {
122  ClusterList thisPfoClusters;
123  for (auto &[view, freeClusters] : viewToFreeClusters)
124  {
125  ClusterList clusters;
126  LArPfoHelper::GetClusters(pPfo, view, clusters);
127  for (const Cluster *const pCluster : clusters)
128  {
129  freeClusters.emplace_back(pCluster);
130  thisPfoClusters.emplace_back(pCluster);
131  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromPfo(*this, pPfo, pCluster));
132  }
133  }
134  pfoToFreeClusters.insert(std::make_pair(pPfo, thisPfoClusters));
135  }
136 
137  return STATUS_CODE_SUCCESS;
138 }
static void GetClusters(const pandora::PfoList &pfoList, const pandora::HitType &hitType, pandora::ClusterList &clusterList)
Get a list of clusters of a particular hit type from a list of pfos.
StatusCode lar_content::ThreeDMultiReclusteringAlgorithm::MopUpCaloHits ( const pandora::CaloHitList &  caloHits,
const pandora::ClusterList &  clusters,
bool  addAsIso 
) const
private

Add hits to their nearest cluster.

Parameters
caloHitslist of 2D hits of the same hit type to be added to nearest cluster
clusterslist of 2D clusters of the same hit type as the caloHits to have hits added to them
addAsIsobool for adding the hits as isolated or not

Definition at line 274 of file ThreeDMultiReclusteringAlgorithm.cc.

References larg4::dist(), and lar_content::LArClusterHelper::GetClosestDistance().

Referenced by BuildNewPfos().

275 {
276  for (const CaloHit *const pCaloHit : caloHits)
277  {
278  const Cluster *pNearestCluster{nullptr};
279  double minimumDistance{std::numeric_limits<float>::max()};
280  for (const Cluster *const pCluster : clusters)
281  {
282  double dist = LArClusterHelper::GetClosestDistance(pCaloHit->GetPositionVector(), pCluster);
283  if (dist < minimumDistance)
284  {
285  minimumDistance = dist;
286  pNearestCluster = pCluster;
287  }
288  }
289  if (!pNearestCluster)
290  return STATUS_CODE_FAILURE;
291 
292  if (addAsIso)
293  {
294  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddIsolatedToCluster(*this, pNearestCluster, pCaloHit));
295  }
296  else
297  {
298  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*this, pNearestCluster, pCaloHit));
299  }
300  }
301 
302  return STATUS_CODE_SUCCESS;
303 }
double dist(const TReal *x, const TReal *y, const unsigned int dimension)
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.
StatusCode lar_content::ThreeDMultiReclusteringAlgorithm::ReadSettings ( const pandora::TiXmlHandle  xmlHandle)
private

Definition at line 324 of file ThreeDMultiReclusteringAlgorithm.cc.

References m_clusteringAlgs, m_clusterListNames, m_mopUp2DCaloHits, m_pfoListName, and m_pFomAlgTool.

325 {
326  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "PfoListName", m_pfoListName));
327  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "Cluster3DListName", m_clusterListNames.at(TPC_3D)));
328  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
329  XmlHelper::ReadValue(xmlHandle, "ClusterUListName", m_clusterListNames.at(TPC_VIEW_U)));
330  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
331  XmlHelper::ReadValue(xmlHandle, "ClusterVListName", m_clusterListNames.at(TPC_VIEW_V)));
332  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
333  XmlHelper::ReadValue(xmlHandle, "ClusterWListName", m_clusterListNames.at(TPC_VIEW_W)));
334 
335  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MopUp2DCaloHits", m_mopUp2DCaloHits));
336 
337  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmList(*this, xmlHandle, "ClusteringAlgorithms", m_clusteringAlgs));
338 
339  AlgorithmTool *pAlgTool{nullptr};
340  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmTool(*this, xmlHandle, "FomAlgorithmTool", pAlgTool));
341  m_pFomAlgTool = dynamic_cast<ThreeDReclusteringFigureOfMeritBaseTool *>(pAlgTool);
342  if (!m_pFomAlgTool)
343  return STATUS_CODE_INVALID_PARAMETER;
344 
345  return STATUS_CODE_SUCCESS;
346 }
ThreeDReclusteringFigureOfMeritBaseTool * m_pFomAlgTool
The address of the figure of merit algorithm tool to use.
std::string m_pfoListName
Name of list of pfos to consider for reclustering.
bool m_mopUp2DCaloHits
Add hits from reclustered 2D clusters without an associated 3D hit to the nearest new 2D cluster in t...
std::map< pandora::HitType, std::string > m_clusterListNames
Map of list names for 3D clusters that comprise the pfos and 2D U, V, W clusters that may need reclus...
std::vector< std::string > m_clusteringAlgs
The ordered list of clustering algorithms to use.
StatusCode lar_content::ThreeDMultiReclusteringAlgorithm::RelinkClustersToOriginalPfos ( std::map< const pandora::Pfo *const, pandora::ClusterList > &  pfoToClusters) const
private

Remake the original pfos by adding back their removed clusters.

Parameters
pfoToClustersmap from pfo to a list of clusters

Definition at line 142 of file ThreeDMultiReclusteringAlgorithm.cc.

Referenced by Run().

143 {
144  for (const auto &[pPfo, clusters] : pfoToClusters)
145  for (const Cluster *const pCluster : clusters)
146  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToPfo(*this, pPfo, pCluster));
147 
148  return STATUS_CODE_SUCCESS;
149 }
StatusCode lar_content::ThreeDMultiReclusteringAlgorithm::Run ( )
private

Definition at line 33 of file ThreeDMultiReclusteringAlgorithm.cc.

References BuildNewPfos(), lar_content::ThreeDReclusteringFigureOfMeritBaseTool::CalcClusteringFom(), FreeCaloHitsFromClusters(), FreeClustersFromPfos(), lar_content::ThreeDReclusteringFigureOfMeritBaseTool::GetPfosToRecluster(), m_clusteringAlgs, m_clusterListNames, m_pfoListName, m_pFomAlgTool, and RelinkClustersToOriginalPfos().

34 {
35  const PfoList *pPfos{nullptr};
36  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, m_pfoListName, pPfos));
37  if (!pPfos || pPfos->empty())
38  return STATUS_CODE_SUCCESS;
39 
40  // Ask the FOM alg tool which pfos to recluster
41  PfoList pfosToRecluster;
42  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, m_pFomAlgTool->GetPfosToRecluster(pPfos, pfosToRecluster));
43  if (pfosToRecluster.empty())
44  return STATUS_CODE_SUCCESS;
45 
46  // Remove clusters from the pfos, keeping track of their original pfo
47  std::map<HitType, ClusterList> viewToFreeClusters = {{TPC_3D, {}}, {TPC_VIEW_U, {}}, {TPC_VIEW_V, {}}, {TPC_VIEW_W, {}}};
48  std::map<const Pfo *const, ClusterList> pfoToFreeClusters;
49  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, FreeClustersFromPfos(pfosToRecluster, viewToFreeClusters, pfoToFreeClusters));
50  if (viewToFreeClusters.at(TPC_3D).empty()) // No 3D clusters to work with, rebuild original pfos as if nothing happened...
51  return RelinkClustersToOriginalPfos(pfoToFreeClusters);
52 
53  // Run reclustering algs over the free 3D clusters to see if there is a superior 3D clustering
54  // NOTE Temporarily replacing the current list doesn't seem to work
55  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*this, m_clusterListNames.at(TPC_3D)));
56  std::string originalClusterListName;
57  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
58  PandoraContentApi::InitializeReclustering(*this, TrackList(), viewToFreeClusters.at(TPC_3D), originalClusterListName));
59 
60  float bestReclusterFom{std::numeric_limits<float>::lowest()};
61  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, m_pFomAlgTool->CalcClusteringFom(viewToFreeClusters.at(TPC_3D), bestReclusterFom));
62  std::string bestReclusterListName{originalClusterListName};
63  ClusterList bestReclusterList;
64 
65  for (const std::string &clusteringAlg : m_clusteringAlgs)
66  {
67  std::string reclusterListName;
68  const ClusterList *pReclusterList{nullptr};
69  PANDORA_RETURN_RESULT_IF(
70  STATUS_CODE_SUCCESS, !=, PandoraContentApi::RunClusteringAlgorithm(*this, clusteringAlg, pReclusterList, reclusterListName));
71  if (!pReclusterList || pReclusterList->empty())
72  continue;
73 
74  float reclusterFom{std::numeric_limits<float>::lowest()};
75  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, m_pFomAlgTool->CalcClusteringFom(*pReclusterList, reclusterFom));
76  if (reclusterFom > bestReclusterFom)
77  {
78  bestReclusterFom = reclusterFom;
79  bestReclusterListName = reclusterListName;
80  bestReclusterList = *pReclusterList;
81  }
82  }
83 
84  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::TemporarilyReplaceCurrentList<Cluster>(*this, bestReclusterListName));
85  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndReclustering(*this, bestReclusterListName));
86 
87  if (bestReclusterListName == originalClusterListName) // No clustering alg has better 3D clusters, rebuild original pfos as if nothing happened...
88  {
89  return RelinkClustersToOriginalPfos(pfoToFreeClusters);
90  }
91  else
92  {
93  // Delete the original pfos in preparation for making new ones
94  // ATTN This will break any existing particle hierarchy
95  for (const Pfo *const pPfo : pfosToRecluster)
96  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete(*this, pPfo, m_pfoListName));
97  }
98 
99  // The 3D clusters are reclustered, now need to manually recluster the 2D clusters to be consistent with the 3D reclustering
100  // First, remove the original 2D clusters
101  std::map<HitType, CaloHitList> viewToFreeCaloHits2D = {{TPC_VIEW_U, {}}, {TPC_VIEW_V, {}}, {TPC_VIEW_W, {}}};
102  for (const auto &[view, freeClusters] : viewToFreeClusters)
103  {
104  if (view == TPC_3D)
105  continue;
106  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, FreeCaloHitsFromClusters(freeClusters, view, viewToFreeCaloHits2D.at(view)));
107  }
108 
109  // Now make new 2D clusters following the new 3D clusters, and make new corresponding pfos
110  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, BuildNewPfos(bestReclusterList, viewToFreeCaloHits2D));
111 
112  return STATUS_CODE_SUCCESS;
113 }
ThreeDReclusteringFigureOfMeritBaseTool * m_pFomAlgTool
The address of the figure of merit algorithm tool to use.
pandora::StatusCode FreeCaloHitsFromClusters(const pandora::ClusterList &clusters, const pandora::HitType &view, pandora::CaloHitList &freeCaloHits) const
Delete clusters of a single hit type and store the associated hits in a list.
pandora::StatusCode RelinkClustersToOriginalPfos(std::map< const pandora::Pfo *const, pandora::ClusterList > &pfoToClusters) const
Remake the original pfos by adding back their removed clusters.
std::string m_pfoListName
Name of list of pfos to consider for reclustering.
virtual pandora::StatusCode CalcClusteringFom(const pandora::ClusterList &clusters, float &fom)=0
Calculate a measure of the goodness of a clustering.
virtual pandora::StatusCode GetPfosToRecluster(const pandora::PfoList *pPfos, pandora::PfoList &pfosToRecluster)=0
Identify pfos for which an attempt at 3D reclustering should be made.
std::map< pandora::HitType, std::string > m_clusterListNames
Map of list names for 3D clusters that comprise the pfos and 2D U, V, W clusters that may need reclus...
std::vector< std::string > m_clusteringAlgs
The ordered list of clustering algorithms to use.
pandora::StatusCode BuildNewPfos(const pandora::ClusterList &clusters3D, std::map< pandora::HitType, pandora::CaloHitList > &viewToFreeCaloHits2D) const
Create new pfos from the reclustered 3D clusters and original 2D hits. The original 2D hits are put i...
pandora::StatusCode FreeClustersFromPfos(const pandora::PfoList &pfos, std::map< pandora::HitType, pandora::ClusterList > &viewToFreeClusters, std::map< const pandora::Pfo *const, pandora::ClusterList > &pfoToFreeClusters) const
Remove clusters from the pfos and store them them in maps.

Member Data Documentation

std::vector<std::string> lar_content::ThreeDMultiReclusteringAlgorithm::m_clusteringAlgs
private

The ordered list of clustering algorithms to use.

Definition at line 107 of file ThreeDMultiReclusteringAlgorithm.h.

Referenced by ReadSettings(), and Run().

std::map<pandora::HitType, std::string> lar_content::ThreeDMultiReclusteringAlgorithm::m_clusterListNames
private

Map of list names for 3D clusters that comprise the pfos and 2D U, V, W clusters that may need reclustering.

Definition at line 105 of file ThreeDMultiReclusteringAlgorithm.h.

Referenced by Build2DClustersFrom3D(), BuildNewPfos(), FreeCaloHitsFromClusters(), ReadSettings(), and Run().

bool lar_content::ThreeDMultiReclusteringAlgorithm::m_mopUp2DCaloHits
private

Add hits from reclustered 2D clusters without an associated 3D hit to the nearest new 2D cluster in their view.

Definition at line 106 of file ThreeDMultiReclusteringAlgorithm.h.

Referenced by BuildNewPfos(), ReadSettings(), and ThreeDMultiReclusteringAlgorithm().

std::string lar_content::ThreeDMultiReclusteringAlgorithm::m_pfoListName
private

Name of list of pfos to consider for reclustering.

Definition at line 104 of file ThreeDMultiReclusteringAlgorithm.h.

Referenced by BuildNewPfos(), ReadSettings(), and Run().

ThreeDReclusteringFigureOfMeritBaseTool* lar_content::ThreeDMultiReclusteringAlgorithm::m_pFomAlgTool
private

The address of the figure of merit algorithm tool to use.

Definition at line 108 of file ThreeDMultiReclusteringAlgorithm.h.

Referenced by ReadSettings(), Run(), and ThreeDMultiReclusteringAlgorithm().


The documentation for this class was generated from the following files: