LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
lar_content::TransverseAssociationAlgorithm Class Reference

TransverseAssociationAlgorithm class. More...

#include "TransverseAssociationAlgorithm.h"

Inheritance diagram for lar_content::TransverseAssociationAlgorithm:
lar_content::ClusterAssociationAlgorithm

Classes

class  LArTransverseCluster
 LArTransverseCluster class. More...
 

Public Member Functions

 TransverseAssociationAlgorithm ()
 Default constructor. More...
 

Protected Types

typedef std::unordered_map< const pandora::Cluster *, ClusterAssociationClusterAssociationMap
 

Protected Member Functions

virtual pandora::StatusCode Run ()
 

Private Types

typedef std::vector< LArTransverseCluster * > TransverseClusterList
 
typedef KDTreeLinkerAlgo< const pandora::CaloHit *, 2 > HitKDTree2D
 
typedef KDTreeNodeInfoT< const pandora::CaloHit *, 2 > HitKDNode2D
 
typedef std::vector< HitKDNode2DHitKDNode2DList
 
typedef std::unordered_map< const pandora::Cluster *, pandora::ClusterSet > ClusterToClustersMap
 
typedef std::unordered_map< const pandora::CaloHit *, const pandora::Cluster * > HitToClusterMap
 

Private Member Functions

pandora::StatusCode ReadSettings (const pandora::TiXmlHandle xmlHandle)
 
void GetListOfCleanClusters (const pandora::ClusterList *const pClusterList, pandora::ClusterVector &clusterVector) const
 Populate cluster vector with subset of cluster list, containing clusters judged to be clean. More...
 
void PopulateClusterAssociationMap (const pandora::ClusterVector &clusterVector, ClusterAssociationMap &clusterAssociationMap) const
 Populate the cluster association map. More...
 
bool IsExtremalCluster (const bool isForward, const pandora::Cluster *const pCurrentCluster, const pandora::Cluster *const pTestCluster) const
 Determine which of two clusters is extremal. More...
 
void GetNearbyClusterMap (const pandora::ClusterVector &allClusters, ClusterToClustersMap &nearbyClusters) const
 Use a kd-tree to obtain details of all nearby cluster combinations. More...
 
void SortInputClusters (const pandora::ClusterVector &inputClusters, pandora::ClusterVector &shortClusters, pandora::ClusterVector &transverseMediumClusters, pandora::ClusterVector &longitudinalMediumClusters, pandora::ClusterVector &longClusters) const
 Separate input clusters by length. More...
 
void FillReducedAssociationMap (const ClusterToClustersMap &nearbyClusters, const pandora::ClusterVector &firstVector, const pandora::ClusterVector &secondVector, ClusterAssociationMap &clusterAssociationMap) const
 Form a reduced set of associations between two input lists of clusters. More...
 
void FillAssociationMap (const ClusterToClustersMap &nearbyClusters, const pandora::ClusterVector &firstVector, const pandora::ClusterVector &secondVector, ClusterAssociationMap &firstAssociationMap, ClusterAssociationMap &secondAssociationMap) const
 Form associations between two input lists of cluster. More...
 
void FillTransverseClusterList (const ClusterToClustersMap &nearbyClusters, const pandora::ClusterVector &inputClusters, const ClusterAssociationMap &inputAssociationMap, TransverseClusterList &transverseClusterList) const
 Create transverse cluster objects, these are protoclusters with a direction and inner/outer vertices. More...
 
void FillTransverseAssociationMap (const ClusterToClustersMap &nearbyClusters, const TransverseClusterList &transverseClusterList, const ClusterAssociationMap &transverseAssociationMap, ClusterAssociationMap &clusterAssociationMap) const
 Form associations between transverse cluster objects. More...
 
void GetAssociatedClusters (const ClusterToClustersMap &nearbyClusters, const pandora::Cluster *const pCluster, const ClusterAssociationMap &inputAssociationMap, pandora::ClusterVector &associatedClusters) const
 Find the clusters that are transversely associated with a target cluster. More...
 
bool IsAssociated (const bool isForward, const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const ClusterToClustersMap &nearbyClusters) const
 Determine whether clusters are association. More...
 
bool IsTransverseAssociated (const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const ClusterToClustersMap &nearbyClusters) const
 Determine whether two clusters are within the same cluster window. More...
 
bool IsTransverseAssociated (const LArTransverseCluster *const pTransverseCluster1, const LArTransverseCluster *const pTransverseCluster2, const ClusterToClustersMap &nearbyClusters) const
 Determine whether two transverse clusters are associated. More...
 
bool IsTransverseAssociated (const LArTransverseCluster *const pTransverseCluster, const pandora::CartesianVector &testPosition) const
 Determine whether one transverse cluster is associated with the vertex from a second transverse cluster. More...
 
bool IsOverlapping (const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2) const
 Determine whether two clusters are overlapping. More...
 
float GetTransverseSpan (const pandora::Cluster *const pCluster) const
 Calculate the overall span in X for a clusters. More...
 
float GetLongitudinalSpan (const pandora::Cluster *const pCluster) const
 Calculate the overall span in Z for a clusters. More...
 
float GetTransverseSpan (const pandora::Cluster *const pCluster, const pandora::ClusterVector &associatedClusters) const
 Calculate the overall span in X for a set of clusters. More...
 
void GetExtremalCoordinatesX (const pandora::Cluster *const pCluster, float &minX, float &maxX) const
 Get minimum and maximum X coordinates for a given cluster. More...
 
void GetExtremalCoordinatesZ (const pandora::Cluster *const pCluster, float &minZ, float &maxZ) const
 Get minimum and maximum Z coordinates for a given cluster. More...
 
void GetExtremalCoordinatesXZ (const pandora::Cluster *const pCluster, const bool useX, float &minXZ, float &maxXZ) const
 Get minimum and maximum X or Z coordinates for a given cluster. More...
 
void GetExtremalCoordinatesX (const pandora::Cluster *const pCluster, pandora::CartesianVector &innerCoordinate, pandora::CartesianVector &outerCoordinate) const
 Get extremal 2D coordinates for a given cluster (ordered by X) More...
 
void FillReducedAssociationMap (const ClusterAssociationMap &inputAssociationMap, ClusterAssociationMap &outputAssociationMap) const
 Remove double-counting from association map. More...
 
void FillReducedAssociationMap (const ClusterAssociationMap &firstAssociationMap, const ClusterAssociationMap &secondAssociationMap, const ClusterAssociationMap &secondAssociationMapSwapped, ClusterAssociationMap &clusterAssociationMap) const
 Use one map to block associations from another map. More...
 
void FillSymmetricAssociationMap (const ClusterAssociationMap &inputAssociationMap, ClusterAssociationMap &outputAssociationMap) const
 Symmetrise an association map. More...
 
void FinalizeClusterAssociationMap (const ClusterAssociationMap &inputAssociationMap, ClusterAssociationMap &outputAssociationMap) const
 Symmetrise and then remove double-counting from an association map. More...
 

Private Attributes

float m_firstLengthCut
 
float m_secondLengthCut
 
float m_clusterWindow
 
float m_clusterAngle
 
float m_clusterCosAngle
 
float m_clusterTanAngle
 
float m_maxTransverseOverlap
 
float m_maxProjectedOverlap
 
float m_maxLongitudinalOverlap
 
float m_transverseClusterMinCosTheta
 
float m_transverseClusterMinLength
 
float m_transverseClusterMaxDisplacement
 
float m_searchRegionX
 Search region, applied to x dimension, for look-up from kd-trees. More...
 
float m_searchRegionZ
 Search region, applied to u/v/w dimension, for look-up from kd-trees. More...
 

Detailed Description

Member Typedef Documentation

typedef std::unordered_map<const pandora::Cluster *, ClusterAssociation> lar_content::ClusterAssociationAlgorithm::ClusterAssociationMap
protectedinherited

Definition at line 43 of file ClusterAssociationAlgorithm.h.

typedef std::unordered_map<const pandora::Cluster *, pandora::ClusterSet> lar_content::TransverseAssociationAlgorithm::ClusterToClustersMap
private

Definition at line 100 of file TransverseAssociationAlgorithm.h.

typedef KDTreeNodeInfoT<const pandora::CaloHit *, 2> lar_content::TransverseAssociationAlgorithm::HitKDNode2D
private

Definition at line 97 of file TransverseAssociationAlgorithm.h.

typedef KDTreeLinkerAlgo<const pandora::CaloHit *, 2> lar_content::TransverseAssociationAlgorithm::HitKDTree2D
private

Definition at line 96 of file TransverseAssociationAlgorithm.h.

typedef std::unordered_map<const pandora::CaloHit *, const pandora::Cluster *> lar_content::TransverseAssociationAlgorithm::HitToClusterMap
private

Definition at line 101 of file TransverseAssociationAlgorithm.h.

Constructor & Destructor Documentation

lar_content::TransverseAssociationAlgorithm::TransverseAssociationAlgorithm ( )

Default constructor.

Definition at line 23 of file TransverseAssociationAlgorithm.cc.

23  :
24  m_firstLengthCut(1.5f),
25  m_secondLengthCut(7.5f),
26  m_clusterWindow(3.f),
27  m_clusterAngle(45.f),
28  m_clusterCosAngle(std::cos(m_clusterAngle * M_PI / 180.f)),
29  m_clusterTanAngle(std::tan(m_clusterAngle * M_PI / 180.f)),
36  m_searchRegionX(3.5f),
38 {
39 }
TFile f
Definition: plotHisto.C:6
float m_searchRegionX
Search region, applied to x dimension, for look-up from kd-trees.
float m_searchRegionZ
Search region, applied to u/v/w dimension, for look-up from kd-trees.

Member Function Documentation

void lar_content::TransverseAssociationAlgorithm::FillAssociationMap ( const ClusterToClustersMap nearbyClusters,
const pandora::ClusterVector &  firstVector,
const pandora::ClusterVector &  secondVector,
ClusterAssociationMap firstAssociationMap,
ClusterAssociationMap secondAssociationMap 
) const
private

Form associations between two input lists of cluster.

Parameters
nearbyClustersthe nearby cluster map, extracted via use of a kd-tree
firstVectorthe first input vector of clusters
secondVectorthe second input vector of clusters
firstAssociationMapthe map of associations between first and second cluster vectors
secondAssociationMapthe reversed map of associations between first and cluster vectors

Definition at line 213 of file TransverseAssociationAlgorithm.cc.

References IsAssociated().

Referenced by SortInputClusters().

215 {
216  for (ClusterVector::const_iterator iterI = firstVector.begin(), iterEndI = firstVector.end(); iterI != iterEndI; ++iterI)
217  {
218  const Cluster *const pClusterI = *iterI;
219 
220  for (ClusterVector::const_iterator iterJ = secondVector.begin(), iterEndJ = secondVector.end(); iterJ != iterEndJ; ++iterJ)
221  {
222  const Cluster *const pClusterJ = *iterJ;
223 
224  if (pClusterI == pClusterJ)
225  continue;
226 
227  if (this->IsAssociated(true, pClusterI, pClusterJ, nearbyClusters))
228  {
229  firstAssociationMap[pClusterI].m_forwardAssociations.insert(pClusterJ);
230  secondAssociationMap[pClusterJ].m_backwardAssociations.insert(pClusterI);
231  }
232 
233  if (this->IsAssociated(false, pClusterI, pClusterJ, nearbyClusters))
234  {
235  firstAssociationMap[pClusterI].m_backwardAssociations.insert(pClusterJ);
236  secondAssociationMap[pClusterJ].m_forwardAssociations.insert(pClusterI);
237  }
238  }
239  }
240 }
intermediate_table::const_iterator const_iterator
bool IsAssociated(const bool isForward, const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const ClusterToClustersMap &nearbyClusters) const
Determine whether clusters are association.
void lar_content::TransverseAssociationAlgorithm::FillReducedAssociationMap ( const ClusterToClustersMap nearbyClusters,
const pandora::ClusterVector &  firstVector,
const pandora::ClusterVector &  secondVector,
ClusterAssociationMap clusterAssociationMap 
) const
private

Form a reduced set of associations between two input lists of clusters.

Parameters
nearbyClustersthe nearby cluster map, extracted via use of a kd-tree
firstVectorthe first input vector of clusters
secondVectorthe second input vector of clusters
clusterAssociationMapthe output map of associations between clusters

Referenced by FillReducedAssociationMap(), FinalizeClusterAssociationMap(), PopulateClusterAssociationMap(), and SortInputClusters().

void lar_content::TransverseAssociationAlgorithm::FillReducedAssociationMap ( const ClusterAssociationMap inputAssociationMap,
ClusterAssociationMap outputAssociationMap 
) const
private

Remove double-counting from association map.

Parameters
inputAssociationMapthe inputted association map
outputAssociationMapthe outputted association map

Definition at line 601 of file TransverseAssociationAlgorithm.cc.

References FillReducedAssociationMap().

603 {
604  return this->FillReducedAssociationMap(inputAssociationMap, inputAssociationMap, inputAssociationMap, outputAssociationMap);
605 }
void FillReducedAssociationMap(const ClusterToClustersMap &nearbyClusters, const pandora::ClusterVector &firstVector, const pandora::ClusterVector &secondVector, ClusterAssociationMap &clusterAssociationMap) const
Form a reduced set of associations between two input lists of clusters.
void lar_content::TransverseAssociationAlgorithm::FillReducedAssociationMap ( const ClusterAssociationMap firstAssociationMap,
const ClusterAssociationMap secondAssociationMap,
const ClusterAssociationMap secondAssociationMapSwapped,
ClusterAssociationMap clusterAssociationMap 
) const
private

Use one map to block associations from another map.

Parameters
firstAssociationMapthe first association map
secondAssociationMapthe second association map
secondAssociationMapthe second association map reversed
clusterAssociationMapthe outputted association map

Definition at line 609 of file TransverseAssociationAlgorithm.cc.

References lar_content::LArClusterHelper::SortByNHits().

612 {
613  // Remove associations A->B from the first association map
614  // if A->C exists in the second map and C->B exists in the reversed second map
615 
616  // Method can also be accessed through FillReducedAssociationMap(input,output) method,
617  // which will remove association A->B from the input map if an association A->C and C->B
618  // already exists in the map.
619 
620  ClusterVector sortedClusters;
621  for (const auto &mapEntry : firstAssociationMap)
622  sortedClusters.push_back(mapEntry.first);
623  std::sort(sortedClusters.begin(), sortedClusters.end(), LArClusterHelper::SortByNHits);
624 
625  for (const Cluster *const pCluster : sortedClusters)
626  {
627  const ClusterAssociation &firstAssociation(firstAssociationMap.at(pCluster));
628 
629  ClusterVector sortedOuterClusters(firstAssociation.m_forwardAssociations.begin(), firstAssociation.m_forwardAssociations.end());
630  std::sort(sortedOuterClusters.begin(), sortedOuterClusters.end(), LArClusterHelper::SortByNHits);
631 
632  ClusterVector sortedInnerClusters(firstAssociation.m_backwardAssociations.begin(), firstAssociation.m_backwardAssociations.end());
633  std::sort(sortedInnerClusters.begin(), sortedInnerClusters.end(), LArClusterHelper::SortByNHits);
634 
635  ClusterAssociationMap::const_iterator iterSecond = secondAssociationMap.find(pCluster);
636  ClusterVector sortedMiddleClustersF, sortedMiddleClustersB;
637 
638  if (secondAssociationMap.end() != iterSecond)
639  {
640  sortedMiddleClustersF.insert(sortedMiddleClustersF.end(), iterSecond->second.m_forwardAssociations.begin(),
641  iterSecond->second.m_forwardAssociations.end());
642  sortedMiddleClustersB.insert(sortedMiddleClustersB.end(), iterSecond->second.m_backwardAssociations.begin(),
643  iterSecond->second.m_backwardAssociations.end());
644  std::sort(sortedMiddleClustersF.begin(), sortedMiddleClustersF.end(), LArClusterHelper::SortByNHits);
645  std::sort(sortedMiddleClustersB.begin(), sortedMiddleClustersB.end(), LArClusterHelper::SortByNHits);
646  }
647 
648  for (const Cluster *const pOuterCluster : sortedOuterClusters)
649  {
650  bool isNeighbouringCluster(true);
651 
652  for (const Cluster *const pMiddleCluster : sortedMiddleClustersF)
653  {
654  ClusterAssociationMap::const_iterator iterSecondCheck = secondAssociationMapSwapped.find(pMiddleCluster);
655  if (secondAssociationMapSwapped.end() == iterSecondCheck)
656  continue;
657 
658  if (iterSecondCheck->second.m_forwardAssociations.count(pOuterCluster) > 0)
659  {
660  isNeighbouringCluster = false;
661  break;
662  }
663  }
664 
665  if (isNeighbouringCluster)
666  clusterAssociationMap[pCluster].m_forwardAssociations.insert(pOuterCluster);
667  }
668 
669  for (const Cluster *const pInnerCluster : sortedInnerClusters)
670  {
671  bool isNeighbouringCluster(true);
672 
673  for (const Cluster *const pMiddleCluster : sortedMiddleClustersB)
674  {
675  ClusterAssociationMap::const_iterator iterSecondCheck = secondAssociationMapSwapped.find(pMiddleCluster);
676  if (secondAssociationMapSwapped.end() == iterSecondCheck)
677  continue;
678 
679  if (iterSecondCheck->second.m_backwardAssociations.count(pInnerCluster) > 0)
680  {
681  isNeighbouringCluster = false;
682  break;
683  }
684  }
685 
686  if (isNeighbouringCluster)
687  clusterAssociationMap[pCluster].m_backwardAssociations.insert(pInnerCluster);
688  }
689  }
690 }
static bool SortByNHits(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by number of hits, then layer span, then inner layer, then position, then pulse-height.
intermediate_table::const_iterator const_iterator
std::vector< art::Ptr< recob::Cluster > > ClusterVector
void lar_content::TransverseAssociationAlgorithm::FillSymmetricAssociationMap ( const ClusterAssociationMap inputAssociationMap,
ClusterAssociationMap outputAssociationMap 
) const
private

Symmetrise an association map.

Parameters
inputAssociationMapthe inputted association map
outputAssociationMapthe outputted association map

Definition at line 694 of file TransverseAssociationAlgorithm.cc.

References lar_content::LArClusterHelper::SortByNHits().

Referenced by FinalizeClusterAssociationMap().

696 {
697  // Generate a symmetrised association map, so that both A--Fwd-->B and B--Bwd-->A both exist.
698  // If A is associated to B through both a backward and forward association (very bad!),
699  // try to rationalise this through majority voting, otherwise remove the association.
700 
701  ClusterVector sortedClusters;
702  for (const auto &mapEntry : inputAssociationMap)
703  sortedClusters.push_back(mapEntry.first);
704  std::sort(sortedClusters.begin(), sortedClusters.end(), LArClusterHelper::SortByNHits);
705 
706  for (const Cluster *const pCluster : sortedClusters)
707  {
708  const ClusterAssociation &inputAssociation(inputAssociationMap.at(pCluster));
709 
710  ClusterVector sortedForwardClusters(inputAssociation.m_forwardAssociations.begin(), inputAssociation.m_forwardAssociations.end());
711  std::sort(sortedForwardClusters.begin(), sortedForwardClusters.end(), LArClusterHelper::SortByNHits);
712 
713  ClusterVector sortedBackwardClusters(inputAssociation.m_backwardAssociations.begin(), inputAssociation.m_backwardAssociations.end());
714  std::sort(sortedBackwardClusters.begin(), sortedBackwardClusters.end(), LArClusterHelper::SortByNHits);
715 
716  // Symmetrise forward associations
717  for (const Cluster *const pForwardCluster : sortedForwardClusters)
718  {
719  int nCounter(+1);
720 
721  if (inputAssociation.m_backwardAssociations.count(pForwardCluster))
722  --nCounter;
723 
724  ClusterAssociationMap::const_iterator iterCheck = inputAssociationMap.find(pForwardCluster);
725  if (inputAssociationMap.end() != iterCheck)
726  {
727  if (iterCheck->second.m_forwardAssociations.count(pCluster))
728  --nCounter;
729 
730  if (iterCheck->second.m_backwardAssociations.count(pCluster))
731  ++nCounter;
732  }
733 
734  if (nCounter > 0)
735  {
736  if (!(outputAssociationMap[pCluster].m_backwardAssociations.count(pForwardCluster) == 0 &&
737  outputAssociationMap[pForwardCluster].m_forwardAssociations.count(pCluster) == 0))
738  throw StatusCodeException(STATUS_CODE_FAILURE);
739 
740  outputAssociationMap[pCluster].m_forwardAssociations.insert(pForwardCluster);
741  outputAssociationMap[pForwardCluster].m_backwardAssociations.insert(pCluster);
742  }
743  }
744 
745  // Symmetrise backward associations
746  for (const Cluster *const pBackwardCluster : sortedBackwardClusters)
747  {
748  int nCounter(-1);
749 
750  if (inputAssociation.m_forwardAssociations.count(pBackwardCluster))
751  ++nCounter;
752 
753  ClusterAssociationMap::const_iterator iterCheck = inputAssociationMap.find(pBackwardCluster);
754  if (inputAssociationMap.end() != iterCheck)
755  {
756  if (iterCheck->second.m_backwardAssociations.count(pCluster))
757  ++nCounter;
758 
759  if (iterCheck->second.m_forwardAssociations.count(pCluster))
760  --nCounter;
761  }
762 
763  if (nCounter < 0)
764  {
765  if (!(outputAssociationMap[pCluster].m_forwardAssociations.count(pBackwardCluster) == 0 &&
766  outputAssociationMap[pBackwardCluster].m_backwardAssociations.count(pCluster) == 0))
767  throw StatusCodeException(STATUS_CODE_FAILURE);
768 
769  outputAssociationMap[pCluster].m_backwardAssociations.insert(pBackwardCluster);
770  outputAssociationMap[pBackwardCluster].m_forwardAssociations.insert(pCluster);
771  }
772  }
773  }
774 }
static bool SortByNHits(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by number of hits, then layer span, then inner layer, then position, then pulse-height.
intermediate_table::const_iterator const_iterator
std::vector< art::Ptr< recob::Cluster > > ClusterVector
void lar_content::TransverseAssociationAlgorithm::FillTransverseAssociationMap ( const ClusterToClustersMap nearbyClusters,
const TransverseClusterList transverseClusterList,
const ClusterAssociationMap transverseAssociationMap,
ClusterAssociationMap clusterAssociationMap 
) const
private

Form associations between transverse cluster objects.

Parameters
nearbyClustersthe nearby cluster map, extracted via use of a kd-tree
transverseClusterListthe input vector of transverse cluster objects
transverseAssociationMapthe external map of associations between clusters
clusterAssociationMapthe output map of associations between clusters

Definition at line 266 of file TransverseAssociationAlgorithm.cc.

References lar_content::TransverseAssociationAlgorithm::LArTransverseCluster::GetSeedCluster(), IsExtremalCluster(), and IsTransverseAssociated().

Referenced by PopulateClusterAssociationMap().

269 {
270  for (TransverseClusterList::const_iterator iter1 = transverseClusterList.begin(), iterEnd1 = transverseClusterList.end(); iter1 != iterEnd1; ++iter1)
271  {
272  LArTransverseCluster *const pInnerTransverseCluster = *iter1;
273  const Cluster *const pInnerCluster(pInnerTransverseCluster->GetSeedCluster());
274 
275  ClusterAssociationMap::const_iterator iterInner = transverseAssociationMap.find(pInnerCluster);
276  if (transverseAssociationMap.end() == iterInner)
277  continue;
278 
279  for (TransverseClusterList::const_iterator iter2 = transverseClusterList.begin(), iterEnd2 = transverseClusterList.end();
280  iter2 != iterEnd2; ++iter2)
281  {
282  LArTransverseCluster *const pOuterTransverseCluster = *iter2;
283  const Cluster *const pOuterCluster(pOuterTransverseCluster->GetSeedCluster());
284 
285  ClusterAssociationMap::const_iterator iterOuter = transverseAssociationMap.find(pOuterCluster);
286  if (transverseAssociationMap.end() == iterOuter)
287  continue;
288 
289  if (pInnerCluster == pOuterCluster)
290  continue;
291 
292  if (iterInner->second.m_forwardAssociations.count(pOuterCluster) == 0 || iterOuter->second.m_backwardAssociations.count(pInnerCluster) == 0)
293  continue;
294 
295  if (!this->IsExtremalCluster(true, pInnerCluster, pOuterCluster) || !this->IsExtremalCluster(false, pOuterCluster, pInnerCluster))
296  continue;
297 
298  if (!this->IsTransverseAssociated(pInnerTransverseCluster, pOuterTransverseCluster, nearbyClusters))
299  continue;
300 
301  clusterAssociationMap[pInnerCluster].m_forwardAssociations.insert(pOuterCluster);
302  clusterAssociationMap[pOuterCluster].m_backwardAssociations.insert(pInnerCluster);
303  }
304  }
305 }
intermediate_table::const_iterator const_iterator
bool IsExtremalCluster(const bool isForward, const pandora::Cluster *const pCurrentCluster, const pandora::Cluster *const pTestCluster) const
Determine which of two clusters is extremal.
bool IsTransverseAssociated(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const ClusterToClustersMap &nearbyClusters) const
Determine whether two clusters are within the same cluster window.
void lar_content::TransverseAssociationAlgorithm::FillTransverseClusterList ( const ClusterToClustersMap nearbyClusters,
const pandora::ClusterVector &  inputClusters,
const ClusterAssociationMap inputAssociationMap,
TransverseClusterList transverseClusterList 
) const
private

Create transverse cluster objects, these are protoclusters with a direction and inner/outer vertices.

Parameters
nearbyClustersthe nearby cluster map, extracted via use of a kd-tree
inputClustersthe input vector of clusters
inputAssociationMapthe map of associations between input clusters
transverseClusterListthe output vector of transverse cluster objects

Definition at line 244 of file TransverseAssociationAlgorithm.cc.

References GetAssociatedClusters(), lar_content::LArClusterHelper::GetClusterHitType(), GetTransverseSpan(), lar_content::LArGeometryHelper::GetWirePitchRatio(), and m_transverseClusterMinLength.

Referenced by PopulateClusterAssociationMap().

246 {
247  for (ClusterVector::const_iterator iter = inputVector.begin(), iterEnd = inputVector.end(); iter != iterEnd; ++iter)
248  {
249  const Cluster *const pCluster = *iter;
250  const float ratio{LArGeometryHelper::GetWirePitchRatio(this->GetPandora(), LArClusterHelper::GetClusterHitType(pCluster))};
251  const float transverseClusterMinLengthAdjusted{ratio * m_transverseClusterMinLength};
252 
253  ClusterVector associatedClusters;
254 
255  this->GetAssociatedClusters(nearbyClusters, pCluster, inputAssociationMap, associatedClusters);
256 
257  if (this->GetTransverseSpan(pCluster, associatedClusters) < transverseClusterMinLengthAdjusted)
258  continue;
259 
260  transverseClusterList.push_back(new LArTransverseCluster(pCluster, associatedClusters));
261  }
262 }
static float GetWirePitchRatio(const pandora::Pandora &pandora, const pandora::HitType view)
Return the ratio of the wire pitch of the specified view to the minimum wire pitch for the detector...
float GetTransverseSpan(const pandora::Cluster *const pCluster) const
Calculate the overall span in X for a clusters.
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.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
void GetAssociatedClusters(const ClusterToClustersMap &nearbyClusters, const pandora::Cluster *const pCluster, const ClusterAssociationMap &inputAssociationMap, pandora::ClusterVector &associatedClusters) const
Find the clusters that are transversely associated with a target cluster.
void lar_content::TransverseAssociationAlgorithm::FinalizeClusterAssociationMap ( const ClusterAssociationMap inputAssociationMap,
ClusterAssociationMap outputAssociationMap 
) const
private

Symmetrise and then remove double-counting from an association map.

Parameters
inputAssociationMapthe inputted association map
outputAssociationMapthe outputted association map

Definition at line 778 of file TransverseAssociationAlgorithm.cc.

References FillReducedAssociationMap(), and FillSymmetricAssociationMap().

Referenced by PopulateClusterAssociationMap().

780 {
781  ClusterAssociationMap intermediateAssociationMap;
782  this->FillSymmetricAssociationMap(inputAssociationMap, intermediateAssociationMap);
783  this->FillReducedAssociationMap(intermediateAssociationMap, outputAssociationMap);
784 }
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
void FillSymmetricAssociationMap(const ClusterAssociationMap &inputAssociationMap, ClusterAssociationMap &outputAssociationMap) const
Symmetrise an association map.
void FillReducedAssociationMap(const ClusterToClustersMap &nearbyClusters, const pandora::ClusterVector &firstVector, const pandora::ClusterVector &secondVector, ClusterAssociationMap &clusterAssociationMap) const
Form a reduced set of associations between two input lists of clusters.
void lar_content::TransverseAssociationAlgorithm::GetAssociatedClusters ( const ClusterToClustersMap nearbyClusters,
const pandora::Cluster *const  pCluster,
const ClusterAssociationMap inputAssociationMap,
pandora::ClusterVector &  associatedClusters 
) const
private

Find the clusters that are transversely associated with a target cluster.

Parameters
nearbyClustersthe nearby cluster map, extracted via use of a kd-tree
pClusterthe target cluster
inputAssociationMapthe map of associations between clusters
outputClustersthe output vector of clusters transversely associated with target cluster

Definition at line 309 of file TransverseAssociationAlgorithm.cc.

References IsTransverseAssociated(), and lar_content::LArClusterHelper::SortByNHits().

Referenced by FillTransverseClusterList().

311 {
312  ClusterAssociationMap::const_iterator iterI = associationMap.find(pClusterI);
313  if (associationMap.end() == iterI)
314  return;
315 
316  for (ClusterSet::const_iterator iterJ = iterI->second.m_forwardAssociations.begin(), iterEndJ = iterI->second.m_forwardAssociations.end();
317  iterJ != iterEndJ; ++iterJ)
318  {
319  const Cluster *const pClusterJ = *iterJ;
320 
321  if (this->IsTransverseAssociated(pClusterI, pClusterJ, nearbyClusters))
322  associatedVector.push_back(pClusterJ);
323  }
324 
325  for (ClusterSet::const_iterator iterJ = iterI->second.m_backwardAssociations.begin(), iterEndJ = iterI->second.m_backwardAssociations.end();
326  iterJ != iterEndJ; ++iterJ)
327  {
328  const Cluster *const pClusterJ = *iterJ;
329 
330  if (this->IsTransverseAssociated(pClusterJ, pClusterI, nearbyClusters))
331  associatedVector.push_back(pClusterJ);
332  }
333 
334  std::sort(associatedVector.begin(), associatedVector.end(), LArClusterHelper::SortByNHits);
335 }
static bool SortByNHits(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by number of hits, then layer span, then inner layer, then position, then pulse-height.
intermediate_table::const_iterator const_iterator
bool IsTransverseAssociated(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const ClusterToClustersMap &nearbyClusters) const
Determine whether two clusters are within the same cluster window.
void lar_content::TransverseAssociationAlgorithm::GetExtremalCoordinatesX ( const pandora::Cluster *const  pCluster,
float &  minX,
float &  maxX 
) const
private

Get minimum and maximum X coordinates for a given cluster.

Parameters
pClusterthe input cluster
minXthe minimum X position
maxXthe maximum X position

Referenced by GetExtremalCoordinatesXZ(), GetLongitudinalSpan(), IsAssociated(), IsExtremalCluster(), and IsOverlapping().

void lar_content::TransverseAssociationAlgorithm::GetExtremalCoordinatesX ( const pandora::Cluster *const  pCluster,
pandora::CartesianVector &  innerCoordinate,
pandora::CartesianVector &  outerCoordinate 
) const
private

Get extremal 2D coordinates for a given cluster (ordered by X)

Parameters
pClusterthe input cluster
innerCoordinatethe inner coordinate
outerCoordinatethe outer coordinate
void lar_content::TransverseAssociationAlgorithm::GetExtremalCoordinatesXZ ( const pandora::Cluster *const  pCluster,
const bool  useX,
float &  minXZ,
float &  maxXZ 
) const
private

Get minimum and maximum X or Z coordinates for a given cluster.

Parameters
pClusterthe input cluster
useXcalculate extermal coordinates for X (rather than Z)
minXZthe minimum X or Z position
maxXZthe maximum X or Z position

Definition at line 562 of file TransverseAssociationAlgorithm.cc.

References f, lar_content::LArClusterHelper::GetExtremalCoordinates(), and GetExtremalCoordinatesX().

Referenced by GetExtremalCoordinatesZ(), and IsExtremalCluster().

563 {
564  minXZ = +std::numeric_limits<float>::max();
565  maxXZ = -std::numeric_limits<float>::max();
566 
567  const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
568 
569  for (OrderedCaloHitList::const_iterator iter = orderedCaloHitList.begin(), iterEnd = orderedCaloHitList.end(); iter != iterEnd; ++iter)
570  {
571  for (CaloHitList::const_iterator hitIter = iter->second->begin(), hitIterEnd = iter->second->end(); hitIter != hitIterEnd; ++hitIter)
572  {
573  const float caloHitXZ(useX ? (*hitIter)->GetPositionVector().GetX() : (*hitIter)->GetPositionVector().GetZ());
574 
575  if (caloHitXZ < minXZ)
576  minXZ = caloHitXZ;
577 
578  if (caloHitXZ > maxXZ)
579  maxXZ = caloHitXZ;
580  }
581  }
582 
583  if (maxXZ < minXZ)
584  throw pandora::StatusCodeException(STATUS_CODE_FAILURE);
585 }
intermediate_table::const_iterator const_iterator
void lar_content::TransverseAssociationAlgorithm::GetExtremalCoordinatesZ ( const pandora::Cluster *const  pCluster,
float &  minZ,
float &  maxZ 
) const
private

Get minimum and maximum Z coordinates for a given cluster.

Parameters
pClusterthe input cluster
minZthe minimum Z position
maxZthe maximum Z position

Definition at line 555 of file TransverseAssociationAlgorithm.cc.

References GetExtremalCoordinatesXZ().

Referenced by GetLongitudinalSpan().

556 {
557  return this->GetExtremalCoordinatesXZ(pCluster, false, minZ, maxZ);
558 }
void GetExtremalCoordinatesXZ(const pandora::Cluster *const pCluster, const bool useX, float &minXZ, float &maxXZ) const
Get minimum and maximum X or Z coordinates for a given cluster.
void lar_content::TransverseAssociationAlgorithm::GetListOfCleanClusters ( const pandora::ClusterList *const  pClusterList,
pandora::ClusterVector &  clusterVector 
) const
privatevirtual

Populate cluster vector with subset of cluster list, containing clusters judged to be clean.

Parameters
pClusterListaddress of the cluster list
clusterVectorto receive the populated cluster vector

Implements lar_content::ClusterAssociationAlgorithm.

Definition at line 43 of file TransverseAssociationAlgorithm.cc.

References lar_content::LArClusterHelper::SortByNHits().

44 {
45  clusterVector.clear();
46  clusterVector.insert(clusterVector.begin(), pClusterList->begin(), pClusterList->end());
47  std::sort(clusterVector.begin(), clusterVector.end(), LArClusterHelper::SortByNHits);
48 }
static bool SortByNHits(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by number of hits, then layer span, then inner layer, then position, then pulse-height.
float lar_content::TransverseAssociationAlgorithm::GetLongitudinalSpan ( const pandora::Cluster *const  pCluster) const
private

Calculate the overall span in Z for a clusters.

Parameters
pClusterthe target cluster

Definition at line 484 of file TransverseAssociationAlgorithm.cc.

References GetExtremalCoordinatesX(), GetExtremalCoordinatesZ(), and GetTransverseSpan().

Referenced by SortInputClusters().

485 {
486  float minZ(+std::numeric_limits<float>::max());
487  float maxZ(-std::numeric_limits<float>::max());
488 
489  this->GetExtremalCoordinatesZ(pCluster, minZ, maxZ);
490 
491  return (maxZ - minZ);
492 }
void GetExtremalCoordinatesZ(const pandora::Cluster *const pCluster, float &minZ, float &maxZ) const
Get minimum and maximum Z coordinates for a given cluster.
void lar_content::TransverseAssociationAlgorithm::GetNearbyClusterMap ( const pandora::ClusterVector &  allClusters,
ClusterToClustersMap nearbyClusters 
) const
private

Use a kd-tree to obtain details of all nearby cluster combinations.

Parameters
allClustersthe list of all clusters
nearbyClustersto obtain the nearby cluster map

Definition at line 119 of file TransverseAssociationAlgorithm.cc.

References lar_content::KDTreeLinkerAlgo< DATA, DIM >::build(), lar_content::build_2d_kd_search_region(), lar_content::fill_and_bound_2d_kd_tree(), m_searchRegionX, m_searchRegionZ, and lar_content::KDTreeLinkerAlgo< DATA, DIM >::search().

Referenced by PopulateClusterAssociationMap().

120 {
121  HitToClusterMap hitToClusterMap;
122  CaloHitList allCaloHits;
123 
124  for (const Cluster *const pCluster : allClusters)
125  {
126  CaloHitList daughterHits;
127  pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
128  allCaloHits.insert(allCaloHits.end(), daughterHits.begin(), daughterHits.end());
129 
130  for (const CaloHit *const pCaloHit : daughterHits)
131  (void)hitToClusterMap.insert(HitToClusterMap::value_type(pCaloHit, pCluster));
132  }
133 
134  HitKDTree2D kdTree;
135  HitKDNode2DList hitKDNode2DList;
136 
137  KDTreeBox hitsBoundingRegion2D(fill_and_bound_2d_kd_tree(allCaloHits, hitKDNode2DList));
138  kdTree.build(hitKDNode2DList, hitsBoundingRegion2D);
139 
140  for (const Cluster *const pCluster : allClusters)
141  {
142  CaloHitList daughterHits;
143  pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
144 
145  for (const CaloHit *const pCaloHit : daughterHits)
146  {
148 
149  HitKDNode2DList found;
150  kdTree.search(searchRegionHits, found);
151 
152  for (const auto &hit : found)
153  (void)nearbyClusters[pCluster].insert(hitToClusterMap.at(hit.data));
154  }
155  }
156 }
float m_searchRegionX
Search region, applied to x dimension, for look-up from kd-trees.
std::unordered_map< const pandora::CaloHit *, const pandora::Cluster * > HitToClusterMap
Detector simulation of raw signals on wires.
KDTreeLinkerAlgo< const pandora::CaloHit *, 2 > HitKDTree2D
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
float m_searchRegionZ
Search region, applied to u/v/w dimension, for look-up from kd-trees.
KDTreeBox build_2d_kd_search_region(const pandora::CaloHit *const point, const float x_span, const float z_span)
build_2d_kd_search_region
KDTreeBoxT< 2 > KDTreeBox
float lar_content::TransverseAssociationAlgorithm::GetTransverseSpan ( const pandora::Cluster *const  pCluster) const
private

Calculate the overall span in X for a clusters.

Parameters
pClusterthe target cluster

Referenced by FillTransverseClusterList(), GetLongitudinalSpan(), IsOverlapping(), and SortInputClusters().

float lar_content::TransverseAssociationAlgorithm::GetTransverseSpan ( const pandora::Cluster *const  pCluster,
const pandora::ClusterVector &  associatedClusters 
) const
private

Calculate the overall span in X for a set of clusters.

Parameters
pClusterthe target cluster
associatedClustersthe vector of associated clusters
bool lar_content::TransverseAssociationAlgorithm::IsAssociated ( const bool  isForward,
const pandora::Cluster *const  pCluster1,
const pandora::Cluster *const  pCluster2,
const ClusterToClustersMap nearbyClusters 
) const
private

Determine whether clusters are association.

Parameters
isForwardwhether the association is forwards or backwards
pCluster1the first cluster
pCluster2the second cluster
nearbyClustersthe nearby cluster map, extracted via use of a kd-tree
Returns
boolean

Definition at line 339 of file TransverseAssociationAlgorithm.cc.

References f, lar_content::LArClusterHelper::GetClosestPosition(), GetExtremalCoordinatesX(), IsTransverseAssociated(), m_clusterTanAngle, m_clusterWindow, m_maxLongitudinalOverlap, and m_maxTransverseOverlap.

Referenced by FillAssociationMap().

341 {
342  if ((0 == nearbyClusters.at(pFirstCluster).count(pSecondCluster)) || (0 == nearbyClusters.at(pSecondCluster).count(pFirstCluster)))
343  return false;
344 
345  CartesianVector firstInner(0.f, 0.f, 0.f), firstOuter(0.f, 0.f, 0.f);
346  CartesianVector secondInner(0.f, 0.f, 0.f), secondOuter(0.f, 0.f, 0.f);
347  this->GetExtremalCoordinatesX(pFirstCluster, firstInner, firstOuter);
348  this->GetExtremalCoordinatesX(pSecondCluster, secondInner, secondOuter);
349 
350  const CartesianVector firstCoordinate(isForward ? firstOuter : firstInner);
351  const CartesianVector secondCoordinate(isForward ? secondOuter : secondInner);
352 
353  if ((firstCoordinate.GetZ() > std::max(secondInner.GetZ(), secondOuter.GetZ()) + m_maxLongitudinalOverlap) ||
354  (firstCoordinate.GetZ() < std::min(secondInner.GetZ(), secondOuter.GetZ()) - m_maxLongitudinalOverlap))
355  return false;
356 
357  if ((isForward && secondCoordinate.GetX() < firstCoordinate.GetX()) || (!isForward && secondCoordinate.GetX() > firstCoordinate.GetX()))
358  return false;
359 
360  const CartesianVector firstProjection(LArClusterHelper::GetClosestPosition(firstCoordinate, pSecondCluster));
361 
362  if ((isForward && firstProjection.GetX() < firstCoordinate.GetX() - m_maxTransverseOverlap) ||
363  (!isForward && firstProjection.GetX() > firstCoordinate.GetX() + m_maxTransverseOverlap))
364  return false;
365 
366  if ((isForward && firstProjection.GetX() > firstCoordinate.GetX() + m_clusterWindow) ||
367  (!isForward && firstProjection.GetX() < firstCoordinate.GetX() - m_clusterWindow))
368  return false;
369 
370  return true;
371 }
TFile f
Definition: plotHisto.C:6
void GetExtremalCoordinatesX(const pandora::Cluster *const pCluster, float &minX, float &maxX) const
Get minimum and maximum X coordinates for a given cluster.
static pandora::CartesianVector GetClosestPosition(const pandora::CartesianVector &position, const pandora::ClusterList &clusterList)
Get closest position in a list of clusters to a specified input position vector.
bool lar_content::TransverseAssociationAlgorithm::IsExtremalCluster ( const bool  isForward,
const pandora::Cluster *const  pCurrentCluster,
const pandora::Cluster *const  pTestCluster 
) const
privatevirtual

Determine which of two clusters is extremal.

Parameters
isForwardwhether propagation direction is forward
pCurrentClustercurrent extremal cluster
pTestClusterpotential extremal cluster
Returns
boolean

Implements lar_content::ClusterAssociationAlgorithm.

Definition at line 524 of file TransverseAssociationAlgorithm.cc.

References f, GetExtremalCoordinatesX(), GetExtremalCoordinatesXZ(), and lar_content::LArClusterHelper::SortByNHits().

Referenced by FillTransverseAssociationMap().

525 {
526  float currentMinX(0.f), currentMaxX(0.f);
527  this->GetExtremalCoordinatesX(pCurrentCluster, currentMinX, currentMaxX);
528 
529  float testMinX(0.f), testMaxX(0.f);
530  this->GetExtremalCoordinatesX(pTestCluster, testMinX, testMaxX);
531 
532  if (isForward)
533  {
534  if (std::fabs(testMaxX - currentMaxX) > std::numeric_limits<float>::epsilon())
535  return (testMaxX > currentMaxX);
536  }
537  else
538  {
539  if (std::fabs(testMinX - currentMaxX) > std::numeric_limits<float>::epsilon())
540  return (testMinX < currentMinX);
541  }
542 
543  return LArClusterHelper::SortByNHits(pTestCluster, pCurrentCluster);
544 }
static bool SortByNHits(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by number of hits, then layer span, then inner layer, then position, then pulse-height.
TFile f
Definition: plotHisto.C:6
void GetExtremalCoordinatesX(const pandora::Cluster *const pCluster, float &minX, float &maxX) const
Get minimum and maximum X coordinates for a given cluster.
bool lar_content::TransverseAssociationAlgorithm::IsOverlapping ( const pandora::Cluster *const  pCluster1,
const pandora::Cluster *const  pCluster2 
) const
private

Determine whether two clusters are overlapping.

Parameters
pCluster1the first cluster
pCluster2the second cluster
Returns
boolean

Definition at line 454 of file TransverseAssociationAlgorithm.cc.

References f, lar_content::LArClusterHelper::GetClosestPosition(), GetExtremalCoordinatesX(), GetTransverseSpan(), and m_maxProjectedOverlap.

Referenced by IsTransverseAssociated().

455 {
456  CartesianVector innerInner(0.f, 0.f, 0.f), innerOuter(0.f, 0.f, 0.f);
457  CartesianVector outerInner(0.f, 0.f, 0.f), outerOuter(0.f, 0.f, 0.f);
458  this->GetExtremalCoordinatesX(pInnerCluster, innerInner, innerOuter);
459  this->GetExtremalCoordinatesX(pOuterCluster, outerInner, outerOuter);
460 
461  const CartesianVector innerProjection(LArClusterHelper::GetClosestPosition(outerInner, pInnerCluster));
462  const CartesianVector outerProjection(LArClusterHelper::GetClosestPosition(innerOuter, pOuterCluster));
463 
464  const float innerOverlapSquared((innerProjection - innerOuter).GetMagnitudeSquared());
465  const float outerOverlapSquared((outerProjection - outerInner).GetMagnitudeSquared());
466 
467  return (std::max(innerOverlapSquared, outerOverlapSquared) > m_maxProjectedOverlap * m_maxProjectedOverlap);
468 }
TFile f
Definition: plotHisto.C:6
void GetExtremalCoordinatesX(const pandora::Cluster *const pCluster, float &minX, float &maxX) const
Get minimum and maximum X coordinates for a given cluster.
static pandora::CartesianVector GetClosestPosition(const pandora::CartesianVector &position, const pandora::ClusterList &clusterList)
Get closest position in a list of clusters to a specified input position vector.
bool lar_content::TransverseAssociationAlgorithm::IsTransverseAssociated ( const pandora::Cluster *const  pCluster1,
const pandora::Cluster *const  pCluster2,
const ClusterToClustersMap nearbyClusters 
) const
private

Determine whether two clusters are within the same cluster window.

Parameters
pCluster1the first cluster
pCluster2the second cluster
nearbyClustersthe nearby cluster map, extracted via use of a kd-tree
Returns
boolean

Referenced by FillTransverseAssociationMap(), GetAssociatedClusters(), IsAssociated(), and IsTransverseAssociated().

bool lar_content::TransverseAssociationAlgorithm::IsTransverseAssociated ( const LArTransverseCluster *const  pTransverseCluster1,
const LArTransverseCluster *const  pTransverseCluster2,
const ClusterToClustersMap nearbyClusters 
) const
private

Determine whether two transverse clusters are associated.

Parameters
pTransverseCluster1the first transverse cluster
pTransverseCluster2the second transverse cluster
nearbyClustersthe nearby cluster map, extracted via use of a kd-tree
Returns
boolean

Definition at line 408 of file TransverseAssociationAlgorithm.cc.

References lar_content::LArClusterHelper::GetClusterHitType(), lar_content::TransverseAssociationAlgorithm::LArTransverseCluster::GetDirection(), lar_content::TransverseAssociationAlgorithm::LArTransverseCluster::GetInnerVertex(), lar_content::TransverseAssociationAlgorithm::LArTransverseCluster::GetOuterVertex(), lar_content::TransverseAssociationAlgorithm::LArTransverseCluster::GetSeedCluster(), lar_content::LArGeometryHelper::GetWirePitchRatio(), IsOverlapping(), IsTransverseAssociated(), m_clusterWindow, m_transverseClusterMaxDisplacement, and m_transverseClusterMinCosTheta.

410 {
411  if (pInnerTransverseCluster->GetDirection().GetDotProduct(pOuterTransverseCluster->GetDirection()) < m_transverseClusterMinCosTheta)
412  return false;
413 
414  if (!this->IsTransverseAssociated(pInnerTransverseCluster, pOuterTransverseCluster->GetInnerVertex()))
415  return false;
416 
417  if (!this->IsTransverseAssociated(pOuterTransverseCluster, pInnerTransverseCluster->GetOuterVertex()))
418  return false;
419 
420  if (!this->IsTransverseAssociated(pInnerTransverseCluster->GetSeedCluster(), pOuterTransverseCluster->GetSeedCluster(), nearbyClusters))
421  return false;
422 
423  if (this->IsOverlapping(pInnerTransverseCluster->GetSeedCluster(), pOuterTransverseCluster->GetSeedCluster()))
424  return false;
425 
426  return true;
427 }
bool IsTransverseAssociated(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const ClusterToClustersMap &nearbyClusters) const
Determine whether two clusters are within the same cluster window.
bool IsOverlapping(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2) const
Determine whether two clusters are overlapping.
bool lar_content::TransverseAssociationAlgorithm::IsTransverseAssociated ( const LArTransverseCluster *const  pTransverseCluster,
const pandora::CartesianVector &  testPosition 
) const
private

Determine whether one transverse cluster is associated with the vertex from a second transverse cluster.

Parameters
pTransverseClusterthe target cluster
theVertexthe vertex position
Returns
boolean
void lar_content::TransverseAssociationAlgorithm::PopulateClusterAssociationMap ( const pandora::ClusterVector &  clusterVector,
ClusterAssociationMap clusterAssociationMap 
) const
privatevirtual

Populate the cluster association map.

Parameters
clusterVectorthe cluster vector
clusterAssociationMapto receive the populated cluster association map

Implements lar_content::ClusterAssociationAlgorithm.

Definition at line 52 of file TransverseAssociationAlgorithm.cc.

References FillReducedAssociationMap(), FillTransverseAssociationMap(), FillTransverseClusterList(), FinalizeClusterAssociationMap(), GetNearbyClusterMap(), and SortInputClusters().

53 {
54  TransverseClusterList transverseClusterList;
55 
56  try
57  {
58  ClusterToClustersMap nearbyClusters;
59  this->GetNearbyClusterMap(allClusters, nearbyClusters);
60 
61  if (nearbyClusters.empty())
62  return;
63 
64  // Step 1: Sort the input clusters into sub-samples
65  // (a) shortClusters: below first length cut
66  // (b) mediumClusters: between first and second length cuts (separated into transverse and longitudinal)
67  // (c) longClusters: above second length cut
68  ClusterVector shortClusters, transverseMediumClusters, longitudinalMediumClusters, longClusters;
69  this->SortInputClusters(allClusters, shortClusters, transverseMediumClusters, longitudinalMediumClusters, longClusters);
70 
71  ClusterVector transverseClusters(shortClusters.begin(), shortClusters.end());
72  transverseClusters.insert(transverseClusters.end(), transverseMediumClusters.begin(), transverseMediumClusters.end());
73 
74  ClusterVector establishedClusters(transverseMediumClusters.begin(), transverseMediumClusters.end());
75  establishedClusters.insert(establishedClusters.end(), longitudinalMediumClusters.begin(), longitudinalMediumClusters.end());
76  establishedClusters.insert(establishedClusters.end(), longClusters.begin(), longClusters.end());
77 
78  // Step 2: Form loose transverse associations between short clusters,
79  // without hopping over any established clusters
80  ClusterAssociationMap firstAssociationMap;
81  this->FillReducedAssociationMap(nearbyClusters, shortClusters, establishedClusters, firstAssociationMap);
82 
83  // Step 3: Form transverse cluster objects. Basically, try to assign a direction to each
84  // of the clusters in the 'transverseClusters' list. For the short clusters in
85  // this list, the direction is obtained from a straight line fit to its associated
86  // clusters as selected in the previous step.
87  this->FillTransverseClusterList(nearbyClusters, transverseClusters, firstAssociationMap, transverseClusterList);
88 
89  // Step 4: Form loose transverse associations between transverse clusters
90  // (First, associate medium clusters, without hopping over long clusters
91  // Next, associate all transverse clusters, without hopping over any clusters)
92  ClusterAssociationMap secondAssociationMap;
93  this->FillReducedAssociationMap(nearbyClusters, transverseMediumClusters, longClusters, secondAssociationMap);
94  this->FillReducedAssociationMap(nearbyClusters, transverseClusters, allClusters, secondAssociationMap);
95 
96  // Step 5: Form associations between transverse cluster objects
97  // (These transverse associations must already exist as loose associations
98  // between transverse clusters as identified in the previous step).
99  ClusterAssociationMap transverseAssociationMap;
100  this->FillTransverseAssociationMap(nearbyClusters, transverseClusterList, secondAssociationMap, transverseAssociationMap);
101 
102  // Step 6: Finalise the forward/backward transverse associations by symmetrising the
103  // transverse association map and removing any double-counting
104  this->FinalizeClusterAssociationMap(transverseAssociationMap, clusterAssociationMap);
105  }
106  catch (StatusCodeException &statusCodeException)
107  {
108  std::cout << "TransverseAssociationAlgorithm: exception " << statusCodeException.ToString() << std::endl;
109  }
110 
111  for (TransverseClusterList::const_iterator iter = transverseClusterList.begin(), iterEnd = transverseClusterList.end(); iter != iterEnd; ++iter)
112  {
113  delete *iter;
114  }
115 }
void FillTransverseAssociationMap(const ClusterToClustersMap &nearbyClusters, const TransverseClusterList &transverseClusterList, const ClusterAssociationMap &transverseAssociationMap, ClusterAssociationMap &clusterAssociationMap) const
Form associations between transverse cluster objects.
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
intermediate_table::const_iterator const_iterator
std::vector< LArTransverseCluster * > TransverseClusterList
void SortInputClusters(const pandora::ClusterVector &inputClusters, pandora::ClusterVector &shortClusters, pandora::ClusterVector &transverseMediumClusters, pandora::ClusterVector &longitudinalMediumClusters, pandora::ClusterVector &longClusters) const
Separate input clusters by length.
void FillTransverseClusterList(const ClusterToClustersMap &nearbyClusters, const pandora::ClusterVector &inputClusters, const ClusterAssociationMap &inputAssociationMap, TransverseClusterList &transverseClusterList) const
Create transverse cluster objects, these are protoclusters with a direction and inner/outer vertices...
std::unordered_map< const pandora::Cluster *, pandora::ClusterSet > ClusterToClustersMap
void FinalizeClusterAssociationMap(const ClusterAssociationMap &inputAssociationMap, ClusterAssociationMap &outputAssociationMap) const
Symmetrise and then remove double-counting from an association map.
void GetNearbyClusterMap(const pandora::ClusterVector &allClusters, ClusterToClustersMap &nearbyClusters) const
Use a kd-tree to obtain details of all nearby cluster combinations.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
void FillReducedAssociationMap(const ClusterToClustersMap &nearbyClusters, const pandora::ClusterVector &firstVector, const pandora::ClusterVector &secondVector, ClusterAssociationMap &clusterAssociationMap) const
Form a reduced set of associations between two input lists of clusters.
StatusCode lar_content::TransverseAssociationAlgorithm::ReadSettings ( const pandora::TiXmlHandle  xmlHandle)
privatevirtual

Reimplemented from lar_content::ClusterAssociationAlgorithm.

Definition at line 859 of file TransverseAssociationAlgorithm.cc.

References f, m_clusterAngle, m_clusterCosAngle, m_clusterTanAngle, m_clusterWindow, m_firstLengthCut, m_maxLongitudinalOverlap, m_maxProjectedOverlap, m_maxTransverseOverlap, m_secondLengthCut, m_transverseClusterMaxDisplacement, m_transverseClusterMinCosTheta, m_transverseClusterMinLength, and lar_content::ClusterAssociationAlgorithm::ReadSettings().

860 {
861  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "FirstLengthCut", m_firstLengthCut));
862 
863  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SecondLengthCut", m_secondLengthCut));
864 
865  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ClusterWindow", m_clusterWindow));
866 
867  const StatusCode angleStatusCode(XmlHelper::ReadValue(xmlHandle, "clusterAngle", m_clusterAngle));
868 
869  if (STATUS_CODE_SUCCESS == angleStatusCode)
870  {
871  m_clusterCosAngle = std::cos(m_clusterAngle * M_PI / 180.f);
872  m_clusterTanAngle = std::tan(m_clusterAngle * M_PI / 180.f);
873  }
874  else if (STATUS_CODE_NOT_FOUND != angleStatusCode)
875  {
876  return angleStatusCode;
877  }
878 
879  PANDORA_RETURN_RESULT_IF_AND_IF(
880  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxTransverseOverlap", m_maxTransverseOverlap));
881 
882  PANDORA_RETURN_RESULT_IF_AND_IF(
883  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxProjectedOverlap", m_maxProjectedOverlap));
884 
885  PANDORA_RETURN_RESULT_IF_AND_IF(
886  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxLongitudinalOverlap", m_maxLongitudinalOverlap));
887 
888  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
889  XmlHelper::ReadValue(xmlHandle, "TransverseClusterMinCosTheta", m_transverseClusterMinCosTheta));
890 
891  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
892  XmlHelper::ReadValue(xmlHandle, "TransverseClusterMinLength", m_transverseClusterMinLength));
893 
894  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
895  XmlHelper::ReadValue(xmlHandle, "TransverseClusterMaxDisplacement", m_transverseClusterMaxDisplacement));
896 
898 }
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
TFile f
Definition: plotHisto.C:6
StatusCode lar_content::ClusterAssociationAlgorithm::Run ( )
protectedvirtualinherited

Definition at line 28 of file ClusterAssociationAlgorithm.cc.

References lar_content::ClusterAssociationAlgorithm::AmbiguousPropagation(), lar_content::ClusterAssociationAlgorithm::GetListOfCleanClusters(), lar_content::ClusterAssociationAlgorithm::m_mergeMade, lar_content::ClusterAssociationAlgorithm::m_resolveAmbiguousAssociations, lar_content::ClusterAssociationAlgorithm::PopulateClusterAssociationMap(), and lar_content::ClusterAssociationAlgorithm::UnambiguousPropagation().

29 {
30  const ClusterList *pClusterList = NULL;
31  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pClusterList));
32 
33  ClusterVector clusterVector;
34  this->GetListOfCleanClusters(pClusterList, clusterVector);
35 
36  ClusterAssociationMap clusterAssociationMap;
37  this->PopulateClusterAssociationMap(clusterVector, clusterAssociationMap);
38 
39  m_mergeMade = true;
40 
41  while (m_mergeMade)
42  {
43  // Unambiguous propagation
44  while (m_mergeMade)
45  {
46  m_mergeMade = false;
47 
48  for (const Cluster *const pCluster : clusterVector)
49  {
50  // ATTN The clusterVector may end up with dangling pointers; only protected by this check against managed cluster list
51  if (pClusterList->end() == std::find(pClusterList->begin(), pClusterList->end(), pCluster))
52  continue;
53 
54  this->UnambiguousPropagation(pCluster, true, clusterAssociationMap);
55  this->UnambiguousPropagation(pCluster, false, clusterAssociationMap);
56  }
57  }
58 
60  continue;
61 
62  // Propagation with ambiguities
63  for (const Cluster *const pCluster : clusterVector)
64  {
65  // ATTN The clusterVector may end up with dangling pointers; only protected by this check against up-to-date association list
66  ClusterAssociationMap::const_iterator mapIterFwd = clusterAssociationMap.find(pCluster);
67 
68  if (clusterAssociationMap.end() == mapIterFwd)
69  continue;
70 
71  if (mapIterFwd->second.m_backwardAssociations.empty() && !mapIterFwd->second.m_forwardAssociations.empty())
72  this->AmbiguousPropagation(pCluster, true, clusterAssociationMap);
73 
74  ClusterAssociationMap::const_iterator mapIterBwd = clusterAssociationMap.find(pCluster);
75 
76  if (clusterAssociationMap.end() == mapIterBwd)
77  continue;
78 
79  if (mapIterBwd->second.m_forwardAssociations.empty() && !mapIterBwd->second.m_backwardAssociations.empty())
80  this->AmbiguousPropagation(pCluster, false, clusterAssociationMap);
81  }
82  }
83 
84  return STATUS_CODE_SUCCESS;
85 }
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
intermediate_table::const_iterator const_iterator
bool m_resolveAmbiguousAssociations
Whether to resolve ambiguous associations.
void AmbiguousPropagation(const pandora::Cluster *const pCluster, const bool isForward, ClusterAssociationMap &clusterAssociationMap) const
Ambiguous propagation.
virtual void PopulateClusterAssociationMap(const pandora::ClusterVector &clusterVector, ClusterAssociationMap &clusterAssociationMap) const =0
Populate the cluster association map.
void UnambiguousPropagation(const pandora::Cluster *const pCluster, const bool isForward, ClusterAssociationMap &clusterAssociationMap) const
Unambiguous propagation.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
virtual void GetListOfCleanClusters(const pandora::ClusterList *const pClusterList, pandora::ClusterVector &clusterVector) const =0
Populate cluster vector with subset of cluster list, containing clusters judged to be clean...
void lar_content::TransverseAssociationAlgorithm::SortInputClusters ( const pandora::ClusterVector &  inputClusters,
pandora::ClusterVector &  shortClusters,
pandora::ClusterVector &  transverseMediumClusters,
pandora::ClusterVector &  longitudinalMediumClusters,
pandora::ClusterVector &  longClusters 
) const
private

Separate input clusters by length.

Parameters
inputClustersthe input vector of clusters
shortClustersthe output vector of short clusters
transverseMediumClustersthe output vector of transverse medium clusters
longitudinalMediumClustersthe output vector of longitudinal medium clusters
longClustersthe output vector of all long clusters

Definition at line 160 of file TransverseAssociationAlgorithm.cc.

References FillAssociationMap(), FillReducedAssociationMap(), GetLongitudinalSpan(), GetTransverseSpan(), m_clusterTanAngle, m_firstLengthCut, m_secondLengthCut, and lar_content::LArClusterHelper::SortByNHits().

Referenced by PopulateClusterAssociationMap().

162 {
163  for (ClusterVector::const_iterator iter = inputVector.begin(), iterEnd = inputVector.end(); iter != iterEnd; ++iter)
164  {
165  const Cluster *const pCluster = *iter;
166 
167  const float clusterLengthT(this->GetTransverseSpan(pCluster));
168  const float clusterLengthL(this->GetLongitudinalSpan(pCluster));
169  const float clusterLengthSquared(clusterLengthT * clusterLengthT + clusterLengthL * clusterLengthL);
170 
171  if (clusterLengthSquared < m_firstLengthCut * m_firstLengthCut)
172  {
173  shortVector.push_back(pCluster);
174  }
175  else if (clusterLengthSquared < m_secondLengthCut * m_secondLengthCut)
176  {
177  if (clusterLengthL < clusterLengthT * std::fabs(m_clusterTanAngle))
178  transverseMediumVector.push_back(pCluster);
179  else
180  longitudinalMediumVector.push_back(pCluster);
181  }
182  else
183  {
184  longVector.push_back(pCluster);
185  }
186  }
187 
188  std::sort(shortVector.begin(), shortVector.end(), LArClusterHelper::SortByNHits);
189  std::sort(transverseMediumVector.begin(), transverseMediumVector.end(), LArClusterHelper::SortByNHits);
190  std::sort(longitudinalMediumVector.begin(), longitudinalMediumVector.end(), LArClusterHelper::SortByNHits);
191  std::sort(longVector.begin(), longVector.end(), LArClusterHelper::SortByNHits);
192 }
static bool SortByNHits(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by number of hits, then layer span, then inner layer, then position, then pulse-height.
float GetTransverseSpan(const pandora::Cluster *const pCluster) const
Calculate the overall span in X for a clusters.
intermediate_table::const_iterator const_iterator
float GetLongitudinalSpan(const pandora::Cluster *const pCluster) const
Calculate the overall span in Z for a clusters.

Member Data Documentation

float lar_content::TransverseAssociationAlgorithm::m_clusterAngle
private

Definition at line 340 of file TransverseAssociationAlgorithm.h.

Referenced by ReadSettings().

float lar_content::TransverseAssociationAlgorithm::m_clusterCosAngle
private

Definition at line 341 of file TransverseAssociationAlgorithm.h.

Referenced by ReadSettings().

float lar_content::TransverseAssociationAlgorithm::m_clusterTanAngle
private

Definition at line 342 of file TransverseAssociationAlgorithm.h.

Referenced by IsAssociated(), ReadSettings(), and SortInputClusters().

float lar_content::TransverseAssociationAlgorithm::m_clusterWindow
private
float lar_content::TransverseAssociationAlgorithm::m_firstLengthCut
private

Definition at line 336 of file TransverseAssociationAlgorithm.h.

Referenced by ReadSettings(), and SortInputClusters().

float lar_content::TransverseAssociationAlgorithm::m_maxLongitudinalOverlap
private

Definition at line 346 of file TransverseAssociationAlgorithm.h.

Referenced by IsAssociated(), and ReadSettings().

float lar_content::TransverseAssociationAlgorithm::m_maxProjectedOverlap
private

Definition at line 345 of file TransverseAssociationAlgorithm.h.

Referenced by IsOverlapping(), and ReadSettings().

float lar_content::TransverseAssociationAlgorithm::m_maxTransverseOverlap
private

Definition at line 344 of file TransverseAssociationAlgorithm.h.

Referenced by IsAssociated(), and ReadSettings().

float lar_content::TransverseAssociationAlgorithm::m_searchRegionX
private

Search region, applied to x dimension, for look-up from kd-trees.

Definition at line 352 of file TransverseAssociationAlgorithm.h.

Referenced by GetNearbyClusterMap().

float lar_content::TransverseAssociationAlgorithm::m_searchRegionZ
private

Search region, applied to u/v/w dimension, for look-up from kd-trees.

Definition at line 353 of file TransverseAssociationAlgorithm.h.

Referenced by GetNearbyClusterMap().

float lar_content::TransverseAssociationAlgorithm::m_secondLengthCut
private

Definition at line 337 of file TransverseAssociationAlgorithm.h.

Referenced by ReadSettings(), and SortInputClusters().

float lar_content::TransverseAssociationAlgorithm::m_transverseClusterMaxDisplacement
private

Definition at line 350 of file TransverseAssociationAlgorithm.h.

Referenced by IsTransverseAssociated(), and ReadSettings().

float lar_content::TransverseAssociationAlgorithm::m_transverseClusterMinCosTheta
private

Definition at line 348 of file TransverseAssociationAlgorithm.h.

Referenced by IsTransverseAssociated(), and ReadSettings().

float lar_content::TransverseAssociationAlgorithm::m_transverseClusterMinLength
private

Definition at line 349 of file TransverseAssociationAlgorithm.h.

Referenced by FillTransverseClusterList(), and ReadSettings().


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