9 #include "Managers/ClusterManager.h" 10 #include "Pandora/AlgorithmHeaders.h" 25 const std::unordered_map<std::string, ThreeDReclusteringAlgorithm::FigureOfMeritType> ThreeDReclusteringAlgorithm::m_stringToEnumMap = {
26 {
"cheated", ThreeDReclusteringAlgorithm::FigureOfMeritType::CHEATED}};
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")
50 const PfoList *pShowerPfoList(
nullptr);
51 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*
this,
m_pfoListName, pShowerPfoList));
53 if (pShowerPfoList->empty())
54 return STATUS_CODE_SUCCESS;
57 PfoList unchangedPfoList;
60 std::string initialPfoListName;
61 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentListName<Pfo>(*
this, initialPfoListName));
64 const ClusterList *pShowerClusters(
nullptr);
68 return STATUS_CODE_NOT_FOUND;
70 for (
const Pfo *
const pShowerPfo : *pShowerPfoList)
72 ClusterList clusterList3D;
77 (pShowerClusters->end() == std::find(pShowerClusters->begin(), pShowerClusters->end(), clusterList3D.front())))
79 unchangedPfoList.push_back(pShowerPfo);
83 CaloHitList initialCaloHitList;
84 clusterList3D.front()->GetOrderedCaloHitList().FillCaloHitList(initialCaloHitList);
90 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromPfo(*
this, pShowerPfo, clusterList3D.front()));
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));
98 std::vector<CaloHitList> newCaloHitListsVector, minimumFigureOfMeritCaloHitListsVector;
99 minimumFigureOfMeritCaloHitListsVector.push_back(initialCaloHitList);
105 pTool->Run(initialCaloHitList, newCaloHitListsVector);
107 catch (
const StatusCodeException &)
109 std::cout <<
"Exception caught! Cannot run reclustering tool!" << std::endl;
114 const float newFigureOfMerit(this->
GetFigureOfMerit(newCaloHitListsVector));
117 if (newFigureOfMerit < minimumFigureOfMerit)
119 minimumFigureOfMerit = newFigureOfMerit;
120 minimumFigureOfMeritCaloHitListsVector = newCaloHitListsVector;
122 newCaloHitListsVector.clear();
126 if ((minimumFigureOfMeritCaloHitListsVector.size() == 1) && (minimumFigureOfMeritCaloHitListsVector.at(0) == initialCaloHitList))
128 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToPfo(*
this, pShowerPfo, clusterList3D.front()));
129 unchangedPfoList.push_back(pShowerPfo);
133 const ClusterList reclusterClusterList(1, clusterList3D.front());
134 std::string clusterListToSaveName, clusterListToDeleteName;
136 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
137 PandoraContentApi::InitializeFragmentation(*
this, reclusterClusterList, clusterListToDeleteName, clusterListToSaveName));
139 ClusterList newClustersList;
140 for (CaloHitList &list : minimumFigureOfMeritCaloHitListsVector)
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);
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();
154 if (unchangedPfoList.size() > 0)
155 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
162 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Pfo>(*
this, initialPfoListName));
164 return STATUS_CODE_SUCCESS;
171 ClusterList clusterList2D;
174 for (
const Cluster *
const pTwoDCluster : clusterList2D)
176 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromPfo(*
this, pPfoToRebuild, pTwoDCluster));
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));
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));
192 const OrderedCaloHitList &twoDClusterOrderedCaloHitList(pTwoDCluster->GetOrderedCaloHitList());
193 OrderedCaloHitList leftoverCaloHitList = twoDClusterOrderedCaloHitList;
196 for (
const Cluster *pNewCluster3D : newClustersList)
200 std::cout <<
"Error: found null pointer in list of new clusters!" << std::endl;
203 PandoraContentApi::Cluster::Parameters parameters;
204 CaloHitList newClusterCaloHitList3D;
205 pNewCluster3D->GetOrderedCaloHitList().FillCaloHitList(newClusterCaloHitList3D);
207 for (
const CaloHit *
const p3DCaloHit : newClusterCaloHitList3D)
209 for (
const OrderedCaloHitList::value_type &mapEntry : twoDClusterOrderedCaloHitList)
211 for (
const CaloHit *
const pCaloHit : *mapEntry.second)
213 if (pCaloHit == static_cast<const CaloHit *>(p3DCaloHit->GetParentAddress()))
215 parameters.m_caloHitList.push_back(static_cast<const CaloHit *>(pCaloHit));
216 leftoverCaloHitList.Remove(pCaloHit);
222 const Cluster *pNewTwoDCluster(
nullptr);
223 if (!parameters.m_caloHitList.empty())
225 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*
this, parameters, pNewTwoDCluster));
227 if (pNewTwoDCluster !=
nullptr && !parameters.m_caloHitList.empty() && hitType == TPC_VIEW_U)
231 else if (pNewTwoDCluster !=
nullptr && !parameters.m_caloHitList.empty() && hitType == TPC_VIEW_V)
235 else if (pNewTwoDCluster !=
nullptr && !parameters.m_caloHitList.empty() && hitType == TPC_VIEW_W)
244 std::map<int, const Cluster *> clustersForLeftoverHitsMap(hitType == TPC_VIEW_U ?
m_newClustersUMap 248 if (!clustersForLeftoverHitsMap.empty())
250 for (
const OrderedCaloHitList::value_type &mapEntry : leftoverCaloHitList)
252 for (
const CaloHit *
const pCaloHit : *mapEntry.second)
254 const Cluster *pNearestCluster(
nullptr);
255 double minimumDistance(std::numeric_limits<float>::max());
256 for (
const auto &[clusterIndex, pNewTwoDCluster] : clustersForLeftoverHitsMap)
259 if (dist < minimumDistance)
261 minimumDistance =
dist;
262 pNearestCluster = pNewTwoDCluster;
265 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*
this, pNearestCluster, pCaloHit));
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));
274 return STATUS_CODE_SUCCESS;
281 const PfoList *pNewPfoList(
nullptr);
282 std::string newPfoListName =
"changedShowerParticles3D";
283 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*
this, pNewPfoList, newPfoListName));
285 const std::string originalClusterListName =
"InitialCluster";
288 for (
const Cluster *pNewThreeDCluster : newClustersList)
290 PandoraContentApi::ParticleFlowObject::Parameters pfoParameters;
294 CaloHitList clusterUHits, clusterVHits, clusterWHits;
297 m_newClustersUMap.at(iCluster)->GetOrderedCaloHitList().FillCaloHitList(clusterUHits);
302 m_newClustersVMap.at(iCluster)->GetOrderedCaloHitList().FillCaloHitList(clusterVHits);
307 m_newClustersWMap.at(iCluster)->GetOrderedCaloHitList().FillCaloHitList(clusterWHits);
310 pfoParameters.m_clusterList.push_back(pNewThreeDCluster);
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);
318 const ParticleFlowObject *pNewPfo(
nullptr);
319 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::Create(*
this, pfoParameters, pNewPfo));
325 return STATUS_CODE_SUCCESS;
337 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->
BuildNewTwoDClusters(pPfoToRebuild, newClustersList));
338 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->
BuildNewPfos(pPfoToRebuild, newClustersList));
340 return STATUS_CODE_SUCCESS;
349 ClusterList clusterList3D;
352 if (clusterList3D.empty())
354 CaloHitList caloHitList3D;
355 clusterList3D.front()->GetOrderedCaloHitList().FillCaloHitList(caloHitList3D);
362 const ClusterList *pShowerClusters(
nullptr);
364 if (!pShowerClusters)
376 std::map<const pandora::MCParticle *, int> mainMcParticleMap;
377 for (
const CaloHit *
const pCaloHit3D : mergedClusterCaloHitList3D)
379 const CaloHit *
const pParentCaloHit2D =
static_cast<const CaloHit *
>(pCaloHit3D->GetParentAddress());
381 const MCParticle *
const pMainMCParticle(MCParticleHelper::GetMainMCParticle(pParentCaloHit2D));
385 if (it != mainMcParticleMap.end())
388 mainMcParticleMap.insert(std::make_pair(pMainMCParticle, 1));
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);
400 float figureOfMerit(-999.
f);
406 figureOfMeritType = stringToEnumIt->second;
409 if (figureOfMeritType == FigureOfMeritType::CHEATED)
412 throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
414 return figureOfMerit;
421 std::vector<float> newClustersFigureOfMeritVector;
422 for (
auto clusterCaloHitLists3D : newClustersCaloHitLists3D)
424 newClustersFigureOfMeritVector.push_back(this->
GetFigureOfMerit(figureOfMeritName, clusterCaloHitLists3D));
426 const float figureOfMerit(*std::min_element(newClustersFigureOfMeritVector.begin(), newClustersFigureOfMeritVector.end()));
427 return figureOfMerit;
434 std::vector<float> figureOfMeritVector;
437 figureOfMeritVector.push_back(this->
GetFigureOfMerit(*iter, newClustersCaloHitLists3D));
440 const float figureOfMerit = *(std::min_element(figureOfMeritVector.begin(), figureOfMeritVector.end()));
441 return figureOfMerit;
448 std::vector<float> figureOfMeritVector;
451 figureOfMeritVector.push_back(this->
GetFigureOfMerit(*iter, mergedClusterCaloHitList3D));
453 const float figureOfMerit = *(std::min_element(figureOfMeritVector.begin(), figureOfMeritVector.end()));
454 return figureOfMerit;
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, !=,
467 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
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));
476 AlgorithmToolVector algorithmToolVector;
477 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*
this, xmlHandle,
"ClusteringTools", algorithmToolVector));
479 for (
auto algorithmTool : algorithmToolVector)
481 ClusteringTool *
const pClusteringTool(dynamic_cast<ClusteringTool *>(algorithmTool));
483 if (!pClusteringTool)
484 return STATUS_CODE_INVALID_PARAMETER;
488 return STATUS_CODE_SUCCESS;
std::string m_wClustersListName
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.
std::map< int, const pandora::Cluster * > m_newClustersVMap
Header file for the principal curve analysis helper class.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
pandora::StatusCode Run()
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.
std::string m_vClustersListName
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.
~ThreeDReclusteringAlgorithm()
Destructor.
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_uClustersListName
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)
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.
long unsigned int m_minNumCaloHitsForReclustering
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.