Classes | Public Member Functions | Private Types | Private Member Functions | Private Attributes | List of all members
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...
 
- Public Member Functions inherited from lar_content::ClusterAssociationAlgorithm
 ClusterAssociationAlgorithm ()
 Default constructor. More...
 

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...
 

Additional Inherited Members

- Protected Types inherited from lar_content::ClusterAssociationAlgorithm
typedef std::unordered_map< const pandora::Cluster *, ClusterAssociationClusterAssociationMap
 
- Protected Member Functions inherited from lar_content::ClusterAssociationAlgorithm
virtual pandora::StatusCode Run ()
 

Detailed Description

TransverseAssociationAlgorithm class.

Definition at line 28 of file TransverseAssociationAlgorithm.h.

Member Typedef Documentation

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.

Definition at line 98 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.

Definition at line 94 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 }
float m_searchRegionX
Search region, applied to x dimension, for look-up from kd-trees.
#define M_PI
Definition: includeROOT.h:54
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 212 of file TransverseAssociationAlgorithm.cc.

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

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

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

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

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

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

771 {
772  ClusterAssociationMap intermediateAssociationMap;
773  this->FillSymmetricAssociationMap(inputAssociationMap, intermediateAssociationMap);
774  this->FillReducedAssociationMap(intermediateAssociationMap, outputAssociationMap);
775 }
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 305 of file TransverseAssociationAlgorithm.cc.

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

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

547 {
548  return this->GetExtremalCoordinatesXZ(pCluster, false, minZ, maxZ);
549 }
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.

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 475 of file TransverseAssociationAlgorithm.cc.

476 {
477  float minZ(+std::numeric_limits<float>::max());
478  float maxZ(-std::numeric_limits<float>::max());
479 
480  this->GetExtremalCoordinatesZ(pCluster, minZ, maxZ);
481 
482  return (maxZ - minZ);
483 }
static int max(int a, int b)
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.

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 
149  kdTree.search(searchRegionHits, found);
150 
151  for (const auto &hit : found)
152  (void)nearbyClusters[pCluster].insert(hitToClusterMap.at(hit.data));
153  }
154  }
155 }
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
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 335 of file TransverseAssociationAlgorithm.cc.

337 {
338  if ((0 == nearbyClusters.at(pFirstCluster).count(pSecondCluster)) || (0 == nearbyClusters.at(pSecondCluster).count(pFirstCluster)))
339  return false;
340 
341  CartesianVector firstInner(0.f, 0.f, 0.f), firstOuter(0.f, 0.f, 0.f);
342  CartesianVector secondInner(0.f, 0.f, 0.f), secondOuter(0.f, 0.f, 0.f);
343  this->GetExtremalCoordinatesX(pFirstCluster, firstInner, firstOuter);
344  this->GetExtremalCoordinatesX(pSecondCluster, secondInner, secondOuter);
345 
346  const CartesianVector firstCoordinate(isForward ? firstOuter : firstInner);
347  const CartesianVector secondCoordinate(isForward ? secondOuter : secondInner);
348 
349  if ((firstCoordinate.GetZ() > std::max(secondInner.GetZ(), secondOuter.GetZ()) + m_maxLongitudinalOverlap) ||
350  (firstCoordinate.GetZ() < std::min(secondInner.GetZ(), secondOuter.GetZ()) - m_maxLongitudinalOverlap))
351  return false;
352 
353  if ((isForward && secondCoordinate.GetX() < firstCoordinate.GetX()) || (!isForward && secondCoordinate.GetX() > firstCoordinate.GetX()))
354  return false;
355 
356  const CartesianVector firstProjection(LArClusterHelper::GetClosestPosition(firstCoordinate, pSecondCluster));
357 
358  if ((isForward && firstProjection.GetX() < firstCoordinate.GetX() - m_maxTransverseOverlap) ||
359  (!isForward && firstProjection.GetX() > firstCoordinate.GetX() + m_maxTransverseOverlap))
360  return false;
361 
362  if ((isForward && firstProjection.GetX() > firstCoordinate.GetX() + m_clusterWindow) ||
363  (!isForward && firstProjection.GetX() < firstCoordinate.GetX() - m_clusterWindow))
364  return false;
365 
366  return true;
367 }
void GetExtremalCoordinatesX(const pandora::Cluster *const pCluster, float &minX, float &maxX) const
Get minimum and maximum X coordinates for a given cluster.
static int max(int a, int b)
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
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 515 of file TransverseAssociationAlgorithm.cc.

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

446 {
447  CartesianVector innerInner(0.f, 0.f, 0.f), innerOuter(0.f, 0.f, 0.f);
448  CartesianVector outerInner(0.f, 0.f, 0.f), outerOuter(0.f, 0.f, 0.f);
449  this->GetExtremalCoordinatesX(pInnerCluster, innerInner, innerOuter);
450  this->GetExtremalCoordinatesX(pOuterCluster, outerInner, outerOuter);
451 
452  const CartesianVector innerProjection(LArClusterHelper::GetClosestPosition(outerInner, pInnerCluster));
453  const CartesianVector outerProjection(LArClusterHelper::GetClosestPosition(innerOuter, pOuterCluster));
454 
455  const float innerOverlapSquared((innerProjection - innerOuter).GetMagnitudeSquared());
456  const float outerOverlapSquared((outerProjection - outerInner).GetMagnitudeSquared());
457 
458  return (std::max(innerOverlapSquared, outerOverlapSquared) > m_maxProjectedOverlap * m_maxProjectedOverlap);
459 }
void GetExtremalCoordinatesX(const pandora::Cluster *const pCluster, float &minX, float &maxX) const
Get minimum and maximum X coordinates for a given cluster.
static int max(int a, int b)
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
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 404 of file TransverseAssociationAlgorithm.cc.

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

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::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.
QTextStream & endl(QTextStream &s)
StatusCode lar_content::TransverseAssociationAlgorithm::ReadSettings ( const pandora::TiXmlHandle  xmlHandle)
privatevirtual

Reimplemented from lar_content::ClusterAssociationAlgorithm.

Definition at line 851 of file TransverseAssociationAlgorithm.cc.

852 {
853  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "FirstLengthCut", m_firstLengthCut));
854 
855  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SecondLengthCut", m_secondLengthCut));
856 
857  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ClusterWindow", m_clusterWindow));
858 
859  const StatusCode angleStatusCode(XmlHelper::ReadValue(xmlHandle, "clusterAngle", m_clusterAngle));
860 
861  if (STATUS_CODE_SUCCESS == angleStatusCode)
862  {
863  m_clusterCosAngle = std::cos(m_clusterAngle * M_PI / 180.f);
864  m_clusterTanAngle = std::tan(m_clusterAngle * M_PI / 180.f);
865  }
866  else if (STATUS_CODE_NOT_FOUND != angleStatusCode)
867  {
868  return angleStatusCode;
869  }
870 
871  PANDORA_RETURN_RESULT_IF_AND_IF(
872  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxTransverseOverlap", m_maxTransverseOverlap));
873 
874  PANDORA_RETURN_RESULT_IF_AND_IF(
875  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxProjectedOverlap", m_maxProjectedOverlap));
876 
877  PANDORA_RETURN_RESULT_IF_AND_IF(
878  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxLongitudinalOverlap", m_maxLongitudinalOverlap));
879 
880  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
881  XmlHelper::ReadValue(xmlHandle, "TransverseClusterMinCosTheta", m_transverseClusterMinCosTheta));
882 
883  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
884  XmlHelper::ReadValue(xmlHandle, "TransverseClusterMinLength", m_transverseClusterMinLength));
885 
886  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
887  XmlHelper::ReadValue(xmlHandle, "TransverseClusterMaxDisplacement", m_transverseClusterMaxDisplacement));
888 
890 }
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
#define M_PI
Definition: includeROOT.h:54
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.

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

float lar_content::TransverseAssociationAlgorithm::m_clusterCosAngle
private

Definition at line 341 of file TransverseAssociationAlgorithm.h.

float lar_content::TransverseAssociationAlgorithm::m_clusterTanAngle
private

Definition at line 342 of file TransverseAssociationAlgorithm.h.

float lar_content::TransverseAssociationAlgorithm::m_clusterWindow
private

Definition at line 339 of file TransverseAssociationAlgorithm.h.

float lar_content::TransverseAssociationAlgorithm::m_firstLengthCut
private

Definition at line 336 of file TransverseAssociationAlgorithm.h.

float lar_content::TransverseAssociationAlgorithm::m_maxLongitudinalOverlap
private

Definition at line 346 of file TransverseAssociationAlgorithm.h.

float lar_content::TransverseAssociationAlgorithm::m_maxProjectedOverlap
private

Definition at line 345 of file TransverseAssociationAlgorithm.h.

float lar_content::TransverseAssociationAlgorithm::m_maxTransverseOverlap
private

Definition at line 344 of file TransverseAssociationAlgorithm.h.

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.

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.

float lar_content::TransverseAssociationAlgorithm::m_secondLengthCut
private

Definition at line 337 of file TransverseAssociationAlgorithm.h.

float lar_content::TransverseAssociationAlgorithm::m_transverseClusterMaxDisplacement
private

Definition at line 350 of file TransverseAssociationAlgorithm.h.

float lar_content::TransverseAssociationAlgorithm::m_transverseClusterMinCosTheta
private

Definition at line 348 of file TransverseAssociationAlgorithm.h.

float lar_content::TransverseAssociationAlgorithm::m_transverseClusterMinLength
private

Definition at line 349 of file TransverseAssociationAlgorithm.h.


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