LArSoft  v06_85_00
Liquid Argon Software toolkit - http://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 98 of file TransverseAssociationAlgorithm.h.

Definition at line 95 of file TransverseAssociationAlgorithm.h.

Definition at line 94 of file TransverseAssociationAlgorithm.h.

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

Definition at line 99 of file TransverseAssociationAlgorithm.h.

Constructor & Destructor Documentation

lar_content::TransverseAssociationAlgorithm::TransverseAssociationAlgorithm ( )

Default constructor.

Definition at line 22 of file TransverseAssociationAlgorithm.cc.

22  :
23  m_firstLengthCut(1.5f),
24  m_secondLengthCut(7.5f),
25  m_clusterWindow(3.f),
26  m_clusterAngle(45.f),
27  m_clusterCosAngle(std::cos(m_clusterAngle * M_PI / 180.f)),
28  m_clusterTanAngle(std::tan(m_clusterAngle * M_PI / 180.f)),
35  m_searchRegionX(3.5f),
37 {
38 }
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 211 of file TransverseAssociationAlgorithm.cc.

References IsAssociated().

Referenced by SortInputClusters().

213 {
214  for (ClusterVector::const_iterator iterI = firstVector.begin(), iterEndI = firstVector.end(); iterI != iterEndI; ++iterI)
215  {
216  const Cluster *const pClusterI = *iterI;
217 
218  for (ClusterVector::const_iterator iterJ = secondVector.begin(), iterEndJ = secondVector.end(); iterJ != iterEndJ; ++iterJ)
219  {
220  const Cluster *const pClusterJ = *iterJ;
221 
222  if (pClusterI == pClusterJ)
223  continue;
224 
225  if (this->IsAssociated(true, pClusterI, pClusterJ, nearbyClusters))
226  {
227  firstAssociationMap[pClusterI].m_forwardAssociations.insert(pClusterJ);
228  secondAssociationMap[pClusterJ].m_backwardAssociations.insert(pClusterI);
229  }
230 
231  if (this->IsAssociated(false, pClusterI, pClusterJ, nearbyClusters))
232  {
233  firstAssociationMap[pClusterI].m_backwardAssociations.insert(pClusterJ);
234  secondAssociationMap[pClusterJ].m_forwardAssociations.insert(pClusterI);
235  }
236  }
237  }
238 }
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 589 of file TransverseAssociationAlgorithm.cc.

References FillReducedAssociationMap().

590 {
591  return this->FillReducedAssociationMap(inputAssociationMap, inputAssociationMap, inputAssociationMap, outputAssociationMap);
592 }
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 596 of file TransverseAssociationAlgorithm.cc.

References lar_content::LArClusterHelper::SortByNHits().

598 {
599  // Remove associations A->B from the first association map
600  // if A->C exists in the second map and C->B exists in the reversed second map
601 
602  // Method can also be accessed through FillReducedAssociationMap(input,output) method,
603  // which will remove association A->B from the input map if an association A->C and C->B
604  // already exists in the map.
605 
606  ClusterVector sortedClusters;
607  for (const auto &mapEntry : firstAssociationMap) sortedClusters.push_back(mapEntry.first);
608  std::sort(sortedClusters.begin(), sortedClusters.end(), LArClusterHelper::SortByNHits);
609 
610  for (const Cluster *const pCluster : sortedClusters)
611  {
612  const ClusterAssociation &firstAssociation(firstAssociationMap.at(pCluster));
613 
614  ClusterVector sortedOuterClusters(firstAssociation.m_forwardAssociations.begin(), firstAssociation.m_forwardAssociations.end());
615  std::sort(sortedOuterClusters.begin(), sortedOuterClusters.end(), LArClusterHelper::SortByNHits);
616 
617  ClusterVector sortedInnerClusters(firstAssociation.m_backwardAssociations.begin(), firstAssociation.m_backwardAssociations.end());
618  std::sort(sortedInnerClusters.begin(), sortedInnerClusters.end(), LArClusterHelper::SortByNHits);
619 
620  ClusterAssociationMap::const_iterator iterSecond = secondAssociationMap.find(pCluster);
621  ClusterVector sortedMiddleClustersF, sortedMiddleClustersB;
622 
623  if (secondAssociationMap.end() != iterSecond)
624  {
625  sortedMiddleClustersF.insert(sortedMiddleClustersF.end(), iterSecond->second.m_forwardAssociations.begin(), iterSecond->second.m_forwardAssociations.end());
626  sortedMiddleClustersB.insert(sortedMiddleClustersB.end(), iterSecond->second.m_backwardAssociations.begin(), iterSecond->second.m_backwardAssociations.end());
627  std::sort(sortedMiddleClustersF.begin(), sortedMiddleClustersF.end(), LArClusterHelper::SortByNHits);
628  std::sort(sortedMiddleClustersB.begin(), sortedMiddleClustersB.end(), LArClusterHelper::SortByNHits);
629  }
630 
631  for (const Cluster *const pOuterCluster : sortedOuterClusters)
632  {
633  bool isNeighbouringCluster(true);
634 
635  for (const Cluster *const pMiddleCluster : sortedMiddleClustersF)
636  {
637  ClusterAssociationMap::const_iterator iterSecondCheck = secondAssociationMapSwapped.find(pMiddleCluster);
638  if (secondAssociationMapSwapped.end() == iterSecondCheck)
639  continue;
640 
641  if (iterSecondCheck->second.m_forwardAssociations.count(pOuterCluster) > 0)
642  {
643  isNeighbouringCluster = false;
644  break;
645  }
646  }
647 
648  if (isNeighbouringCluster)
649  clusterAssociationMap[pCluster].m_forwardAssociations.insert(pOuterCluster);
650  }
651 
652  for (const Cluster *const pInnerCluster : sortedInnerClusters)
653  {
654  bool isNeighbouringCluster(true);
655 
656  for (const Cluster *const pMiddleCluster : sortedMiddleClustersB)
657  {
658  ClusterAssociationMap::const_iterator iterSecondCheck = secondAssociationMapSwapped.find(pMiddleCluster);
659  if (secondAssociationMapSwapped.end() == iterSecondCheck)
660  continue;
661 
662  if (iterSecondCheck->second.m_backwardAssociations.count(pInnerCluster) > 0)
663  {
664  isNeighbouringCluster = false;
665  break;
666  }
667  }
668 
669  if (isNeighbouringCluster)
670  clusterAssociationMap[pCluster].m_backwardAssociations.insert(pInnerCluster);
671  }
672  }
673 }
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 677 of file TransverseAssociationAlgorithm.cc.

References lar_content::LArClusterHelper::SortByNHits().

Referenced by FinalizeClusterAssociationMap().

678 {
679  // Generate a symmetrised association map, so that both A--Fwd-->B and B--Bwd-->A both exist.
680  // If A is associated to B through both a backward and forward association (very bad!),
681  // try to rationalise this through majority voting, otherwise remove the association.
682 
683  ClusterVector sortedClusters;
684  for (const auto &mapEntry : inputAssociationMap) sortedClusters.push_back(mapEntry.first);
685  std::sort(sortedClusters.begin(), sortedClusters.end(), LArClusterHelper::SortByNHits);
686 
687  for (const Cluster *const pCluster : sortedClusters)
688  {
689  const ClusterAssociation &inputAssociation(inputAssociationMap.at(pCluster));
690 
691  ClusterVector sortedForwardClusters(inputAssociation.m_forwardAssociations.begin(), inputAssociation.m_forwardAssociations.end());
692  std::sort(sortedForwardClusters.begin(), sortedForwardClusters.end(), LArClusterHelper::SortByNHits);
693 
694  ClusterVector sortedBackwardClusters(inputAssociation.m_backwardAssociations.begin(), inputAssociation.m_backwardAssociations.end());
695  std::sort(sortedBackwardClusters.begin(), sortedBackwardClusters.end(), LArClusterHelper::SortByNHits);
696 
697  // Symmetrise forward associations
698  for (const Cluster *const pForwardCluster : sortedForwardClusters)
699  {
700  int nCounter(+1);
701 
702  if (inputAssociation.m_backwardAssociations.count(pForwardCluster))
703  --nCounter;
704 
705  ClusterAssociationMap::const_iterator iterCheck = inputAssociationMap.find(pForwardCluster);
706  if (inputAssociationMap.end() != iterCheck)
707  {
708  if (iterCheck->second.m_forwardAssociations.count(pCluster))
709  --nCounter;
710 
711  if (iterCheck->second.m_backwardAssociations.count(pCluster))
712  ++nCounter;
713  }
714 
715  if (nCounter > 0)
716  {
717  if(!(outputAssociationMap[pCluster].m_backwardAssociations.count(pForwardCluster) == 0 &&
718  outputAssociationMap[pForwardCluster].m_forwardAssociations.count(pCluster) == 0))
719  throw StatusCodeException(STATUS_CODE_FAILURE);
720 
721  outputAssociationMap[pCluster].m_forwardAssociations.insert(pForwardCluster);
722  outputAssociationMap[pForwardCluster].m_backwardAssociations.insert(pCluster);
723  }
724  }
725 
726  // Symmetrise backward associations
727  for (const Cluster *const pBackwardCluster : sortedBackwardClusters)
728  {
729  int nCounter(-1);
730 
731  if (inputAssociation.m_forwardAssociations.count(pBackwardCluster))
732  ++nCounter;
733 
734  ClusterAssociationMap::const_iterator iterCheck = inputAssociationMap.find(pBackwardCluster);
735  if (inputAssociationMap.end() != iterCheck)
736  {
737  if (iterCheck->second.m_backwardAssociations.count(pCluster))
738  ++nCounter;
739 
740  if (iterCheck->second.m_forwardAssociations.count(pCluster))
741  --nCounter;
742  }
743 
744  if (nCounter < 0)
745  {
746  if(!(outputAssociationMap[pCluster].m_forwardAssociations.count(pBackwardCluster) == 0 &&
747  outputAssociationMap[pBackwardCluster].m_backwardAssociations.count(pCluster) == 0))
748  throw StatusCodeException(STATUS_CODE_FAILURE);
749 
750  outputAssociationMap[pCluster].m_backwardAssociations.insert(pBackwardCluster);
751  outputAssociationMap[pBackwardCluster].m_forwardAssociations.insert(pCluster);
752  }
753  }
754  }
755 }
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 261 of file TransverseAssociationAlgorithm.cc.

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

Referenced by PopulateClusterAssociationMap().

263 {
264  for (TransverseClusterList::const_iterator iter1 = transverseClusterList.begin(), iterEnd1 = transverseClusterList.end(); iter1 != iterEnd1; ++iter1)
265  {
266  LArTransverseCluster *const pInnerTransverseCluster = *iter1;
267  const Cluster *const pInnerCluster(pInnerTransverseCluster->GetSeedCluster());
268 
269  ClusterAssociationMap::const_iterator iterInner = transverseAssociationMap.find(pInnerCluster);
270  if (transverseAssociationMap.end() == iterInner)
271  continue;
272 
273  for (TransverseClusterList::const_iterator iter2 = transverseClusterList.begin(), iterEnd2 = transverseClusterList.end(); iter2 != iterEnd2; ++iter2)
274  {
275  LArTransverseCluster *const pOuterTransverseCluster = *iter2;
276  const Cluster *const pOuterCluster(pOuterTransverseCluster->GetSeedCluster());
277 
278  ClusterAssociationMap::const_iterator iterOuter = transverseAssociationMap.find(pOuterCluster);
279  if(transverseAssociationMap.end() == iterOuter)
280  continue;
281 
282  if (pInnerCluster == pOuterCluster)
283  continue;
284 
285  if (iterInner->second.m_forwardAssociations.count(pOuterCluster) == 0 ||
286  iterOuter->second.m_backwardAssociations.count(pInnerCluster) == 0)
287  continue;
288 
289  if (!this->IsExtremalCluster(true, pInnerCluster, pOuterCluster) ||
290  !this->IsExtremalCluster(false, pOuterCluster, pInnerCluster))
291  continue;
292 
293  if (!this->IsTransverseAssociated(pInnerTransverseCluster, pOuterTransverseCluster, nearbyClusters))
294  continue;
295 
296  clusterAssociationMap[pInnerCluster].m_forwardAssociations.insert(pOuterCluster);
297  clusterAssociationMap[pOuterCluster].m_backwardAssociations.insert(pInnerCluster);
298  }
299  }
300 }
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.
intermediate_table::const_iterator const_iterator
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 242 of file TransverseAssociationAlgorithm.cc.

References GetAssociatedClusters(), GetTransverseSpan(), and m_transverseClusterMinLength.

Referenced by PopulateClusterAssociationMap().

244 {
245  for (ClusterVector::const_iterator iter = inputVector.begin(), iterEnd = inputVector.end(); iter != iterEnd; ++iter)
246  {
247  const Cluster *const pCluster = *iter;
248  ClusterVector associatedClusters;
249 
250  this->GetAssociatedClusters(nearbyClusters, pCluster, inputAssociationMap, associatedClusters);
251 
252  if (this->GetTransverseSpan(pCluster, associatedClusters) < m_transverseClusterMinLength)
253  continue;
254 
255  transverseClusterList.push_back(new LArTransverseCluster(pCluster, associatedClusters));
256  }
257 }
float GetTransverseSpan(const pandora::Cluster *const pCluster) const
Calculate the overall span in X for a clusters.
intermediate_table::const_iterator const_iterator
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 759 of file TransverseAssociationAlgorithm.cc.

References FillReducedAssociationMap(), and FillSymmetricAssociationMap().

Referenced by PopulateClusterAssociationMap().

760 {
761  ClusterAssociationMap intermediateAssociationMap;
762  this->FillSymmetricAssociationMap(inputAssociationMap, intermediateAssociationMap);
763  this->FillReducedAssociationMap(intermediateAssociationMap, outputAssociationMap);
764 }
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.
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
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 304 of file TransverseAssociationAlgorithm.cc.

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

Referenced by FillTransverseClusterList().

306 {
307  ClusterAssociationMap::const_iterator iterI = associationMap.find(pClusterI);
308  if (associationMap.end() == iterI)
309  return;
310 
311  for (ClusterSet::const_iterator iterJ = iterI->second.m_forwardAssociations.begin(), iterEndJ = iterI->second.m_forwardAssociations.end(); iterJ != iterEndJ; ++iterJ)
312  {
313  const Cluster *const pClusterJ = *iterJ;
314 
315  if (this->IsTransverseAssociated(pClusterI, pClusterJ, nearbyClusters))
316  associatedVector.push_back(pClusterJ);
317  }
318 
319  for (ClusterSet::const_iterator iterJ = iterI->second.m_backwardAssociations.begin(), iterEndJ = iterI->second.m_backwardAssociations.end(); iterJ != iterEndJ; ++iterJ)
320  {
321  const Cluster *const pClusterJ = *iterJ;
322 
323  if (this->IsTransverseAssociated(pClusterJ, pClusterI, nearbyClusters))
324  associatedVector.push_back(pClusterJ);
325  }
326 
327  std::sort(associatedVector.begin(), associatedVector.end(), LArClusterHelper::SortByNHits);
328 }
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.
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.
intermediate_table::const_iterator const_iterator
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 551 of file TransverseAssociationAlgorithm.cc.

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

Referenced by GetExtremalCoordinatesZ(), and IsExtremalCluster().

552 {
555 
556  const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
557 
558  for (OrderedCaloHitList::const_iterator iter = orderedCaloHitList.begin(), iterEnd = orderedCaloHitList.end(); iter != iterEnd; ++iter)
559  {
560  for (CaloHitList::const_iterator hitIter = iter->second->begin(), hitIterEnd = iter->second->end(); hitIter != hitIterEnd; ++hitIter)
561  {
562  const float caloHitXZ(useX ? (*hitIter)->GetPositionVector().GetX() : (*hitIter)->GetPositionVector().GetZ());
563 
564  if (caloHitXZ < minXZ)
565  minXZ = caloHitXZ;
566 
567  if (caloHitXZ > maxXZ)
568  maxXZ = caloHitXZ;
569  }
570  }
571 
572  if (maxXZ < minXZ)
573  throw pandora::StatusCodeException(STATUS_CODE_FAILURE);
574 }
Int_t max
Definition: plot.C:27
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 544 of file TransverseAssociationAlgorithm.cc.

References GetExtremalCoordinatesXZ().

Referenced by GetLongitudinalSpan().

545 {
546  return this->GetExtremalCoordinatesXZ(pCluster, false, minZ, maxZ);
547 }
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 42 of file TransverseAssociationAlgorithm.cc.

References lar_content::LArClusterHelper::SortByNHits().

43 {
44  clusterVector.clear();
45  clusterVector.insert(clusterVector.begin(), pClusterList->begin(), pClusterList->end());
46  std::sort(clusterVector.begin(), clusterVector.end(), LArClusterHelper::SortByNHits);
47 }
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 473 of file TransverseAssociationAlgorithm.cc.

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

Referenced by SortInputClusters().

474 {
475  float minZ(+std::numeric_limits<float>::max());
476  float maxZ(-std::numeric_limits<float>::max());
477 
478  this->GetExtremalCoordinatesZ(pCluster, minZ, maxZ);
479 
480  return (maxZ - minZ);
481 }
Int_t max
Definition: plot.C:27
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 118 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().

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

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

Referenced by FillAssociationMap().

334 {
335  if ((0 == nearbyClusters.at(pFirstCluster).count(pSecondCluster)) || (0 == nearbyClusters.at(pSecondCluster).count(pFirstCluster)))
336  return false;
337 
338  CartesianVector firstInner(0.f,0.f,0.f), firstOuter(0.f,0.f,0.f);
339  CartesianVector secondInner(0.f,0.f,0.f), secondOuter(0.f,0.f,0.f);
340  this->GetExtremalCoordinatesX(pFirstCluster, firstInner, firstOuter);
341  this->GetExtremalCoordinatesX(pSecondCluster, secondInner, secondOuter);
342 
343  const CartesianVector firstCoordinate(isForward ? firstOuter : firstInner);
344  const CartesianVector secondCoordinate(isForward ? secondOuter : secondInner);
345 
346  if ((firstCoordinate.GetZ() > std::max(secondInner.GetZ(),secondOuter.GetZ()) + m_maxLongitudinalOverlap) ||
347  (firstCoordinate.GetZ() < std::min(secondInner.GetZ(),secondOuter.GetZ()) - m_maxLongitudinalOverlap))
348  return false;
349 
350  if ((isForward && secondCoordinate.GetX() < firstCoordinate.GetX()) ||
351  (!isForward && secondCoordinate.GetX() > firstCoordinate.GetX()))
352  return false;
353 
354  const CartesianVector firstProjection(LArClusterHelper::GetClosestPosition(firstCoordinate, pSecondCluster));
355 
356  if((isForward && firstProjection.GetX() < firstCoordinate.GetX() - m_maxTransverseOverlap) ||
357  (!isForward && firstProjection.GetX() > firstCoordinate.GetX() + m_maxTransverseOverlap))
358  return false;
359 
360  if((isForward && firstProjection.GetX() > firstCoordinate.GetX() + m_clusterWindow) ||
361  (!isForward && firstProjection.GetX() < firstCoordinate.GetX() - m_clusterWindow))
362  return false;
363 
364  return true;
365 }
TFile f
Definition: plotHisto.C:6
Int_t max
Definition: plot.C:27
void GetExtremalCoordinatesX(const pandora::Cluster *const pCluster, float &minX, float &maxX) const
Get minimum and maximum X coordinates for a given cluster.
Int_t min
Definition: plot.C:26
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 513 of file TransverseAssociationAlgorithm.cc.

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

Referenced by FillTransverseAssociationMap().

514 {
515  float currentMinX(0.f), currentMaxX(0.f);
516  this->GetExtremalCoordinatesX(pCurrentCluster, currentMinX, currentMaxX);
517 
518  float testMinX(0.f), testMaxX(0.f);
519  this->GetExtremalCoordinatesX(pTestCluster, testMinX, testMaxX);
520 
521  if (isForward)
522  {
523  if (std::fabs(testMaxX - currentMaxX) > std::numeric_limits<float>::epsilon())
524  return (testMaxX > currentMaxX);
525  }
526  else
527  {
528  if (std::fabs(testMinX - currentMaxX) > std::numeric_limits<float>::epsilon())
529  return (testMinX < currentMinX);
530  }
531 
532  return LArClusterHelper::SortByNHits(pTestCluster, pCurrentCluster);
533 }
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 443 of file TransverseAssociationAlgorithm.cc.

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

Referenced by IsTransverseAssociated().

444 {
445  CartesianVector innerInner(0.f,0.f,0.f), innerOuter(0.f,0.f,0.f);
446  CartesianVector outerInner(0.f,0.f,0.f), outerOuter(0.f,0.f,0.f);
447  this->GetExtremalCoordinatesX(pInnerCluster, innerInner, innerOuter);
448  this->GetExtremalCoordinatesX(pOuterCluster, outerInner, outerOuter);
449 
450  const CartesianVector innerProjection(LArClusterHelper::GetClosestPosition(outerInner, pInnerCluster));
451  const CartesianVector outerProjection(LArClusterHelper::GetClosestPosition(innerOuter, pOuterCluster));
452 
453  const float innerOverlapSquared((innerProjection - innerOuter).GetMagnitudeSquared());
454  const float outerOverlapSquared((outerProjection - outerInner).GetMagnitudeSquared());
455 
456  return (std::max(innerOverlapSquared, outerOverlapSquared) > m_maxProjectedOverlap * m_maxProjectedOverlap);
457 }
TFile f
Definition: plotHisto.C:6
Int_t max
Definition: plot.C:27
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 403 of file TransverseAssociationAlgorithm.cc.

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

405 {
406  if (pInnerTransverseCluster->GetDirection().GetDotProduct(pOuterTransverseCluster->GetDirection()) < m_transverseClusterMinCosTheta)
407  return false;
408 
409  if (!this->IsTransverseAssociated(pInnerTransverseCluster, pOuterTransverseCluster->GetInnerVertex()))
410  return false;
411 
412  if (!this->IsTransverseAssociated(pOuterTransverseCluster, pInnerTransverseCluster->GetOuterVertex()))
413  return false;
414 
415  if (!this->IsTransverseAssociated(pInnerTransverseCluster->GetSeedCluster(), pOuterTransverseCluster->GetSeedCluster(), nearbyClusters))
416  return false;
417 
418  if (this->IsOverlapping(pInnerTransverseCluster->GetSeedCluster(), pOuterTransverseCluster->GetSeedCluster()))
419  return false;
420 
421  return true;
422 }
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 51 of file TransverseAssociationAlgorithm.cc.

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

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

Reimplemented from lar_content::ClusterAssociationAlgorithm.

Definition at line 838 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().

839 {
840  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
841  "FirstLengthCut", m_firstLengthCut));
842 
843  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
844  "SecondLengthCut", m_secondLengthCut));
845 
846  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
847  "ClusterWindow", m_clusterWindow));
848 
849  const StatusCode angleStatusCode(XmlHelper::ReadValue(xmlHandle, "clusterAngle", m_clusterAngle));
850 
851  if (STATUS_CODE_SUCCESS == angleStatusCode)
852  {
853  m_clusterCosAngle = std::cos(m_clusterAngle * M_PI / 180.f);
854  m_clusterTanAngle = std::tan(m_clusterAngle * M_PI / 180.f);
855  }
856  else if (STATUS_CODE_NOT_FOUND != angleStatusCode)
857  {
858  return angleStatusCode;
859  }
860 
861  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
862  "MaxTransverseOverlap", m_maxTransverseOverlap));
863 
864  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
865  "MaxProjectedOverlap", m_maxProjectedOverlap));
866 
867  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
868  "MaxLongitudinalOverlap", m_maxLongitudinalOverlap));
869 
870  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
871  "TransverseClusterMinCosTheta", m_transverseClusterMinCosTheta));
872 
873  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
874  "TransverseClusterMinLength", m_transverseClusterMinLength));
875 
876  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
877  "TransverseClusterMaxDisplacement", m_transverseClusterMaxDisplacement));
878 
880 }
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 mapIter = clusterAssociationMap.find(pCluster);
67 
68  if (clusterAssociationMap.end() == mapIter)
69  continue;
70 
71  if (mapIter->second.m_backwardAssociations.empty() && !mapIter->second.m_forwardAssociations.empty())
72  this->AmbiguousPropagation(pCluster, true, clusterAssociationMap);
73 
74  if (mapIter->second.m_forwardAssociations.empty() && !mapIter->second.m_backwardAssociations.empty())
75  this->AmbiguousPropagation(pCluster, false, clusterAssociationMap);
76  }
77  }
78 
79  return STATUS_CODE_SUCCESS;
80 }
bool m_resolveAmbiguousAssociations
Whether to resolve ambiguous associations.
intermediate_table::const_iterator const_iterator
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.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
void UnambiguousPropagation(const pandora::Cluster *const pCluster, const bool isForward, ClusterAssociationMap &clusterAssociationMap) const
Unambiguous propagation.
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
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 159 of file TransverseAssociationAlgorithm.cc.

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

Referenced by PopulateClusterAssociationMap().

160 {
161  for (ClusterVector::const_iterator iter = inputVector.begin(), iterEnd = inputVector.end(); iter != iterEnd; ++iter)
162  {
163  const Cluster *const pCluster = *iter;
164 
165  const float clusterLengthT(this->GetTransverseSpan(pCluster));
166  const float clusterLengthL(this->GetLongitudinalSpan(pCluster));
167  const float clusterLengthSquared(clusterLengthT * clusterLengthT + clusterLengthL * clusterLengthL);
168 
169  if (clusterLengthSquared < m_firstLengthCut * m_firstLengthCut)
170  {
171  shortVector.push_back(pCluster);
172  }
173  else if (clusterLengthSquared < m_secondLengthCut * m_secondLengthCut)
174  {
175  if (clusterLengthL < clusterLengthT * std::fabs(m_clusterTanAngle))
176  transverseMediumVector.push_back(pCluster);
177  else
178  longitudinalMediumVector.push_back(pCluster);
179  }
180  else
181  {
182  longVector.push_back(pCluster);
183  }
184  }
185 
186  std::sort(shortVector.begin(), shortVector.end(), LArClusterHelper::SortByNHits);
187  std::sort(transverseMediumVector.begin(), transverseMediumVector.end(), LArClusterHelper::SortByNHits);
188  std::sort(longitudinalMediumVector.begin(), longitudinalMediumVector.end(), LArClusterHelper::SortByNHits);
189  std::sort(longVector.begin(), longVector.end(), LArClusterHelper::SortByNHits);
190 }
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: