25 m_minCaloHitsPerCluster(3),
26 m_xOverlapWindow(1.f),
27 m_distanceForMatching(5.f),
40 if (pfoVector.empty())
43 std::cout <<
"DeltaRayMatchingAlgorithm: pfo list " <<
m_parentPfoListName <<
" unavailable." << std::endl;
45 return STATUS_CODE_SUCCESS;
57 return STATUS_CODE_SUCCESS;
77 if ((NULL == pClusterList) || pClusterList->empty())
83 for (
const Cluster *
const pCluster : *pClusterList)
86 pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
87 allCaloHits.insert(allCaloHits.end(), daughterHits.begin(), daughterHits.end());
89 for (
const CaloHit *
const pCaloHit : daughterHits)
90 (
void)hitToClusterMap.insert(HitToClusterMap::value_type(pCaloHit, pCluster));
97 kdTree.
build(hitKDNode2DList, hitsBoundingRegion2D);
99 for (
const Cluster *
const pCluster : *pClusterList)
102 pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
104 for (
const CaloHit *
const pCaloHit : daughterHits)
109 kdTree.
search(searchRegionHits, found);
111 for (
const auto &hit : found)
113 ClusterList &nearbyClusterList(nearbyClusters[pCluster]);
114 const Cluster *
const pNearbyCluster(hitToClusterMap.at(hit.data));
116 if (nearbyClusterList.end() == std::find(nearbyClusterList.begin(), nearbyClusterList.end(), pNearbyCluster))
117 nearbyClusterList.push_back(pNearbyCluster);
136 const PfoList *pPfoList = NULL;
139 if (NULL == pPfoList)
142 for (PfoList::const_iterator iter = pPfoList->begin(), iterEnd = pPfoList->end(); iter != iterEnd; ++iter)
143 pfoVector.push_back(*iter);
153 this->
GetAllPfos(inputPfoListName, inputVector);
155 for (PfoVector::const_iterator iter = inputVector.begin(), iterEnd = inputVector.end(); iter != iterEnd; ++iter)
162 pfoVector.push_back(pPfo);
176 if (NULL == pClusterList)
179 for (ClusterList::const_iterator cIter = pClusterList->begin(), cIterEnd = pClusterList->end(); cIter != cIterEnd; ++cIter)
181 const Cluster *
const pCluster = *cIter;
186 clusterVector.push_back(pCluster);
203 this->
ThreeViewMatching(clustersU, clustersV, clustersW, clusterLengthMap, pfoLengthMap, initialParticleList);
204 this->
SelectParticles(initialParticleList, clusterLengthMap, finalParticleList);
219 this->
TwoViewMatching(clustersU, clustersV, clusterLengthMap, pfoLengthMap, initialParticleList);
220 this->
TwoViewMatching(clustersV, clustersW, clusterLengthMap, pfoLengthMap, initialParticleList);
221 this->
TwoViewMatching(clustersW, clustersU, clusterLengthMap, pfoLengthMap, initialParticleList);
222 this->
SelectParticles(initialParticleList, clusterLengthMap, finalParticleList);
237 this->
ThreeViewMatching(clustersU, clustersV, clustersW, clusterLengthMap, pfoLengthMap, initialParticleList);
238 this->
OneViewMatching(clustersU, clusterLengthMap, pfoLengthMap, initialParticleList);
239 this->
OneViewMatching(clustersV, clusterLengthMap, pfoLengthMap, initialParticleList);
240 this->
OneViewMatching(clustersW, clusterLengthMap, pfoLengthMap, initialParticleList);
241 this->
SelectParticles(initialParticleList, clusterLengthMap, finalParticleList);
250 if (clusters1.empty() || clusters2.empty() || clusters3.empty())
253 for (
const Cluster *
const pCluster1 : clusters1)
255 if (!pCluster1->IsAvailable())
258 for (
const Cluster *
const pCluster2 : clusters2)
260 if (!pCluster2->IsAvailable())
263 for (
const Cluster *
const pCluster3 : clusters3)
265 if (!pCluster3->IsAvailable())
272 this->
FindBestParentPfo(pCluster1, pCluster2, pCluster3, clusterLengthMap, pfoLengthMap, pBestPfo);
275 particleList.push_back(
Particle(pCluster1, pCluster2, pCluster3, pBestPfo));
286 if (clusters1.empty() || clusters2.empty())
289 for (
const Cluster *
const pCluster1 : clusters1)
291 if (!pCluster1->IsAvailable())
294 for (
const Cluster *
const pCluster2 : clusters2)
296 if (!pCluster2->IsAvailable())
303 this->
FindBestParentPfo(pCluster1, pCluster2, NULL, clusterLengthMap, pfoLengthMap, pBestPfo);
305 if (NULL == pBestPfo)
308 particleList.push_back(
Particle(pCluster1, pCluster2, NULL, pBestPfo));
318 if (clusters.empty())
321 for (
const Cluster *
const pCluster : clusters)
323 if (!pCluster->IsAvailable())
327 this->
FindBestParentPfo(pCluster, NULL, NULL, clusterLengthMap, pfoLengthMap, pBestPfo);
329 if (NULL == pBestPfo)
332 particleList.push_back(
Particle(pCluster, NULL, NULL, pBestPfo));
340 for (
const Particle &particle1 : initialParticles)
342 bool isGoodParticle(
true);
344 for (
const Particle &particle2 : initialParticles)
346 const bool commonU(particle1.GetClusterU() == particle2.GetClusterU());
347 const bool commonV(particle1.GetClusterV() == particle2.GetClusterV());
348 const bool commonW(particle1.GetClusterW() == particle2.GetClusterW());
350 const bool ambiguousU(commonU && NULL != particle1.GetClusterU());
351 const bool ambiguousV(commonV && NULL != particle1.GetClusterV());
352 const bool ambiguousW(commonW && NULL != particle1.GetClusterW());
354 if (commonU && commonV && commonW)
357 if (ambiguousU || ambiguousV || ambiguousW)
359 if (particle2.GetNViews() > particle1.GetNViews())
361 isGoodParticle =
false;
363 else if (particle2.GetNViews() == particle1.GetNViews() && NULL != particle2.GetParentPfo())
365 if ((NULL == particle1.GetParentPfo()) || (particle2.GetNCaloHits() > particle1.GetNCaloHits()) ||
366 (particle2.GetNCaloHits() == particle1.GetNCaloHits() &&
367 this->GetLength(particle2, clusterLengthMap) >= this->GetLength(particle1, clusterLengthMap)))
369 isGoodParticle =
false;
378 if (isGoodParticle && NULL != particle1.GetParentPfo())
379 finalParticles.push_back(particle1);
391 PfoList parentList(parentVector.begin(), parentVector.end());
392 PfoList daughterList(daughterVector.begin(), daughterVector.end());
394 for (
const Particle &particle : particleList)
398 if (NULL == pParentPfo)
401 const Cluster *
const pClusterU = particle.GetClusterU();
402 const Cluster *
const pClusterV = particle.GetClusterV();
403 const Cluster *
const pClusterW = particle.GetClusterW();
405 if (NULL == pClusterU && NULL == pClusterV && NULL == pClusterW)
411 clusterList.push_back(pClusterU);
414 clusterList.push_back(pClusterV);
417 clusterList.push_back(pClusterW);
419 if (parentList.end() != std::find(parentList.begin(), parentList.end(), pParentPfo))
423 else if (daughterList.end() != std::find(daughterList.begin(), daughterList.end(), pParentPfo))
438 if (
nullptr == pCluster1 &&
nullptr == pCluster2 &&
nullptr == pCluster3)
442 float xMin1(-std::numeric_limits<float>::max()), xMax1(+std::numeric_limits<float>::max());
443 float xMin2(-std::numeric_limits<float>::max()), xMax2(+std::numeric_limits<float>::max());
444 float xMin3(-std::numeric_limits<float>::max()), xMax3(+std::numeric_limits<float>::max());
446 if (
nullptr != pCluster1)
449 if (
nullptr != pCluster2)
452 if (
nullptr != pCluster3)
456 const float xMin(std::max(xMin1, std::max(xMin2, xMin3)) - xPitch);
457 const float xMax(std::min(xMax1, std::min(xMax2, xMax3)) + xPitch);
458 const float xOverlap(xMax - xMin);
460 if (xOverlap < std::numeric_limits<float>::epsilon())
463 if (
nullptr == pCluster1 ||
nullptr == pCluster2 ||
nullptr == pCluster3)
471 if (hitType1 == hitType2 || hitType2 == hitType3 || hitType3 == hitType1)
474 const unsigned int nSamplingPoints(1 +
static_cast<unsigned int>(xOverlap / xPitch));
476 for (
unsigned int n = 0; n < nSamplingPoints; ++n)
478 const float x(xMin + (xMax - xMin) * (
static_cast<float>(n) + 0.5f) /
static_cast<float>(nSamplingPoints));
479 const float xmin(x - xPitch);
480 const float xmax(x + xPitch);
484 float zMin1(0.f), zMin2(0.f), zMin3(0.f), zMax1(0.f), zMax2(0.f), zMax3(0.f);
489 const float z1(0.5f * (zMin1 + zMax1));
490 const float z2(0.5f * (zMin2 + zMax2));
491 const float z3(0.5f * (zMin3 + zMax3));
493 const float dz1(zMax1 - zMin1);
494 const float dz2(zMax2 - zMin2);
495 const float dz3(zMax3 - zMin3);
502 const float deltaSquared(((z1 - zproj1) * (z1 - zproj1) + (z2 - zproj2) * (z2 - zproj2) + (z3 - zproj3) * (z3 - zproj3)) / 3.f);
503 const float sigmaSquared(dz1 * dz1 + dz2 * dz2 + dz3 * dz3 + dz4 * dz4);
504 const float pseudoChi2(deltaSquared / sigmaSquared);
511 if (STATUS_CODE_NOT_FOUND != statusCodeException.
GetStatusCode())
512 throw statusCodeException;
528 if (pfoVector.empty())
531 unsigned int numViews(0);
532 float lengthSquared(0.f);
561 float distanceSquared(0.f);
563 if (NULL != pCluster1)
566 if (NULL != pCluster2)
569 if (NULL != pCluster3)
572 if (distanceSquared < bestDistanceSquared)
575 bestDistanceSquared = distanceSquared;
580 if (!(STATUS_CODE_NOT_FOUND == statusCodeException.
GetStatusCode()))
581 throw statusCodeException;
590 ClusterLengthMap::const_iterator iter = clusterLengthMap.find(pCluster);
592 if (clusterLengthMap.end() != iter)
596 (void)clusterLengthMap.insert(ClusterLengthMap::value_type(pCluster, lengthSquared));
597 return lengthSquared;
604 PfoLengthMap::const_iterator iter = pfoLengthMap.find(pPfo);
606 if (pfoLengthMap.end() != iter)
610 (void)pfoLengthMap.insert(PfoLengthMap::value_type(pPfo, lengthSquared));
611 return lengthSquared;
618 float lengthSquared(0.f);
629 return lengthSquared;
644 if (!nearbyClusters.count(pCluster))
645 return std::numeric_limits<float>::max();
650 for (
const Cluster *
const pPfoCluster : pfoClusterList)
652 const ClusterList &clusterList(nearbyClusters.at(pCluster));
654 if ((clusterList.end() != std::find(clusterList.begin(), clusterList.end(), pPfoCluster)) &&
655 (comparisonList.end() == std::find(comparisonList.begin(), comparisonList.end(), pPfoCluster)))
657 comparisonList.push_back(pPfoCluster);
661 if (comparisonList.empty())
662 return std::numeric_limits<float>::max();
671 const PfoList *pPfoList = NULL;
672 std::string pfoListName;
676 PandoraContentApi::ParticleFlowObject::Parameters pfoParameters;
677 pfoParameters.m_particleId = E_MINUS;
680 pfoParameters.m_energy = 0.f;
682 pfoParameters.m_clusterList = clusterList;
685 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::Create(*
this, pfoParameters, pDaughterPfo));
687 if (!pPfoList->empty())
698 for (
const Cluster *
const pDaughterCluster : clusterList)
701 const std::string clusterListName(
707 if (pfoClusters.empty())
710 const Cluster *
const pParentCluster = *(pfoClusters.begin());
744 unsigned int numViews(0);
746 if (NULL != m_pClusterU)
749 if (NULL != m_pClusterV)
752 if (NULL != m_pClusterW)
762 unsigned int numCaloHits(0);
764 if (NULL != m_pClusterU)
765 numCaloHits += m_pClusterU->GetNCaloHits();
767 if (NULL != m_pClusterV)
768 numCaloHits += m_pClusterV->GetNCaloHits();
770 if (NULL != m_pClusterW)
771 numCaloHits += m_pClusterW->GetNCaloHits();
799 return STATUS_CODE_SUCCESS;
Header file for the delta ray matching algorithm class.
Header file for the kd tree linker algo template class.
Header file for the cluster helper class.
Header file for the geometry helper class.
Header file for the pfo helper class.
#define PANDORA_THROW_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
#define PANDORA_THROW_RESULT_IF(StatusCode1, Operator, Command)
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
#define PANDORA_RETURN_RESULT_IF(StatusCode1, Operator, Command)
static pandora::StatusCode ReplaceCurrentList(const pandora::Algorithm &algorithm, const std::string &newListName)
Replace the current list with a pre-saved list; use this new list as a permanent replacement for the ...
static pandora::StatusCode CreateTemporaryListAndSetCurrent(const pandora::Algorithm &algorithm, const T *&pT, std::string &temporaryListName)
Create a temporary list and set it to be the current list, enabling object creation.
static pandora::StatusCode MergeAndDeleteClusters(const pandora::Algorithm &algorithm, const pandora::Cluster *const pClusterToEnlarge, const pandora::Cluster *const pClusterToDelete)
Merge two clusters in the current list, enlarging one cluster and deleting the second.
static pandora::StatusCode SetPfoParentDaughterRelationship(const pandora::Algorithm &algorithm, const pandora::ParticleFlowObject *const pParentPfo, const pandora::ParticleFlowObject *const pDaughterPfo)
Set parent-daughter particle flow object relationship.
static pandora::StatusCode GetList(const pandora::Algorithm &algorithm, const std::string &listName, const T *&pT)
Get a named list.
static const pandora::PandoraSettings * GetSettings(const pandora::Algorithm &algorithm)
Get the pandora settings instance.
const pandora::ParticleFlowObject * m_pParentPfo
Address of parent Pfo.
const pandora::Cluster * m_pClusterV
Address of cluster in V view.
unsigned int GetNCaloHits() const
Get number of calo hits.
const pandora::Cluster * m_pClusterU
Address of cluster in U view.
const pandora::Cluster * GetClusterV() const
Get cluster in V view.
unsigned int GetNViews() const
Get number of views.
Particle(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const pandora::Cluster *const pCluster3, const pandora::ParticleFlowObject *const pPfo)
Constructor.
const pandora::Cluster * GetClusterW() const
Get cluster in W view.
const pandora::Cluster * GetClusterU() const
Get cluster in U view.
const pandora::Cluster * m_pClusterW
Address of cluster in W view.
std::unordered_map< const pandora::CaloHit *, const pandora::Cluster * > HitToClusterMap
std::string m_inputClusterListNameW
The input cluster list name for the w view.
float m_searchRegion1D
Search region, applied to each dimension, for look-up from kd-trees.
std::unordered_map< const pandora::Cluster *, float > ClusterLengthMap
void OneViewMatching(ClusterLengthMap &clusterLengthMap) const
Match clusters using single views.
ClusterToClustersMap m_nearbyClustersV
The nearby clusters map for the v view.
void CreateDaughterPfo(const pandora::ClusterList &clusterList, const pandora::ParticleFlowObject *const pParentPfo) const
Create a new Pfo from an input cluster list and set up a parent/daughter relationship.
void CreateParticles(const ParticleList &particleList) const
Build new particle flow objects.
float m_distanceForMatching
The maximum allowed distance between tracks and delta rays.
void InitializeNearbyClusterMaps()
Initialize nearby cluster maps.
DeltaRayMatchingAlgorithm()
Default constructor.
pandora::StatusCode Run()
Run the algorithm.
void ThreeViewMatching(ClusterLengthMap &clusterLengthMap) const
Match clusters using all three views.
std::string m_inputClusterListNameV
The input cluster list name for the v view.
std::string m_parentPfoListName
The parent pfo list name.
void SelectParticles(const ParticleList &inputParticles, ClusterLengthMap &clusterLengthMap, ParticleList &outputParticles) const
Resolve any ambiguities between candidate particles.
float m_xOverlapWindow
The maximum allowed displacement in x position.
bool AreClustersMatched(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const pandora::Cluster *const pCluster3) const
Look at consistency of a combination of clusters.
std::vector< HitKDNode2D > HitKDNode2DList
ClusterToClustersMap m_nearbyClustersW
The nearby clusters map for the w view.
void InitializeNearbyClusterMap(const std::string &clusterListName, ClusterToClustersMap &nearbyClusters)
Initialize a nearby cluster map with details relating to a specific cluster list.
void ClearNearbyClusterMaps()
Clear nearby cluster maps.
float m_pseudoChi2Cut
Pseudo chi2 cut for three view matching.
std::string m_inputClusterListNameU
The input cluster list name for the u view.
void FindBestParentPfo(const pandora::Cluster *const pClusterU, const pandora::Cluster *const pClusterV, const pandora::Cluster *const pClusterW, ClusterLengthMap &clusterLengthMap, PfoLengthMap &pfoLengthMap, const pandora::ParticleFlowObject *&pBestPfo) const
Find best Pfo to associate a UVW triplet.
std::string m_daughterPfoListName
The daughter pfo list name for new daughter particles.
unsigned int m_minCaloHitsPerCluster
The min number of calo hits per candidate cluster.
std::unordered_map< const pandora::ParticleFlowObject *, float > PfoLengthMap
void AddToDaughterPfo(const pandora::ClusterList &clusterList, const pandora::ParticleFlowObject *const pParentPfo) const
Merge an input cluster list with an existing daughter Pfo.
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterToClustersMap
void GetAllPfos(const std::string &inputPfoListName, pandora::PfoVector &pfoVector) const
Get a vector of all Pfos in the provided input Pfo lists.
float GetLength(const Particle &particle, ClusterLengthMap &clusterLengthMap) const
Get the length (squared) of a candidate particle.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
float GetLengthFromCache(const pandora::Cluster *const pCluster, ClusterLengthMap &clusterLengthMap) const
Reduce number of length (squared) calculations by caching results when they are first obtained.
void GetTrackPfos(const std::string &inputPfoListName, pandora::PfoVector &pfoVector) const
Get a vector of track-like Pfos in the provided input Pfo lists.
void TwoViewMatching(ClusterLengthMap &clusterLengthMap) const
Match clusters using pairs of views.
std::vector< Particle > ParticleList
ClusterToClustersMap m_nearbyClustersU
The nearby clusters map for the u view.
void GetClusters(const std::string &clusterListName, pandora::ClusterVector &clusterVector) const
Get a vector containing all available input clusters in the provided cluster list,...
float GetDistanceSquaredToPfo(const pandora::Cluster *const pCluster, const pandora::ParticleFlowObject *const pPfo) const
Get displacementr between cluster and particle flow object.
Box structure used to define 2D field. It's used in KDTree building step to divide the detector space...
void build(std::vector< KDTreeNodeInfoT< DATA, DIM > > &eltList, const KDTreeBoxT< DIM > ®ion)
Build the KD tree from the "eltList" in the space define by "region".
void search(const KDTreeBoxT< DIM > &searchBox, std::vector< KDTreeNodeInfoT< DATA, DIM > > &resRecHitList)
Search in the KDTree for all points that would be contained in the given searchbox The founded points...
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,...
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.
static float MergeTwoPositions(const pandora::Pandora &pandora, const pandora::HitType view1, const pandora::HitType view2, const float position1, const float position2)
Merge two views (U,V) to give a third view (Z).
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
static bool IsTrack(const pandora::ParticleFlowObject *const pPfo)
Return track flag based on Pfo Particle ID.
static bool SortByNHits(const pandora::ParticleFlowObject *const pLhs, const pandora::ParticleFlowObject *const pRhs)
Sort pfos by number of constituent hits.
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.
static float GetTwoDLengthSquared(const pandora::ParticleFlowObject *const pPfo)
Calculate length of Pfo using 2D clusters.
bool IsAvailable() const
Whether the cluster is available to be added to a particle flow object.
unsigned int GetNCaloHits() const
Get the number of calo hits in the cluster.
void GetClusterSpanX(float &xmin, float &xmax) const
Get minimum and maximum X positions of the calo hits in this cluster.
void GetClusterSpanZ(const float xmin, const float xmax, float &zmin, float &zmax) const
Get upper and lower Z positions of the calo hits in a cluster in range xmin to xmax.
bool ShouldDisplayAlgorithmInfo() const
Whether to display algorithm information during processing.
ParticleFlowObject class.
static float GetParticleMass(const int pdgCode)
Get the mass of a particle type.
static int GetParticleCharge(const int pdgCode)
Get the charge of a particle type.
const Pandora & GetPandora() const
Get the associated pandora instance.
StatusCodeException class.
StatusCode GetStatusCode() const
Get status code.
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
KDTreeBox fill_and_bound_2d_kd_tree(const MANAGED_CONTAINER< const T * > &points, std::vector< KDTreeNodeInfoT< const T *, 2 > > &nodes)
fill_and_bound_2d_kd_tree
KDTreeBox build_2d_kd_search_region(const pandora::CaloHit *const point, const float x_span, const float z_span)
build_2d_kd_search_region
HitType
Calorimeter hit type enum.
std::vector< const Cluster * > ClusterVector
MANAGED_CONTAINER< const Cluster * > ClusterList
std::vector< const ParticleFlowObject * > PfoVector
MANAGED_CONTAINER< const CaloHit * > CaloHitList
StatusCode
The StatusCode enum.
MANAGED_CONTAINER< const ParticleFlowObject * > PfoList