All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Public Member Functions | Private Types | Private Member Functions | Private Attributes | List of all members
lar_cluster3d::MSTPathFinder Class Reference
Inheritance diagram for lar_cluster3d::MSTPathFinder:
lar_cluster3d::IClusterModAlg

Public Member Functions

 MSTPathFinder (const fhicl::ParameterSet &)
 Constructor. More...
 
 ~MSTPathFinder ()
 Destructor. More...
 
void configure (fhicl::ParameterSet const &pset) override
 Interface for configuring the particular algorithm tool. More...
 
void initializeHistograms (art::TFileDirectory &) override
 Interface for initializing histograms if they are desired Note that the idea is to put hisgtograms in a subfolder. More...
 
void ModifyClusters (reco::ClusterParametersList &) const override
 Scan an input collection of clusters and modify those according to the specific implementing algorithm. More...
 
float getTimeToExecute () const override
 If monitoring, recover the time to execute a particular function. More...
 
- Public Member Functions inherited from lar_cluster3d::IClusterModAlg
virtual ~IClusterModAlg () noexcept=default
 Virtual Destructor. More...
 

Private Types

enum  TimeValues {
  BUILDTHREEDHITS = 0, BUILDHITTOHITMAP = 1, RUNDBSCAN = 2, BUILDCLUSTERINFO = 3,
  PATHFINDING = 4, NUMTIMEVALUES
}
 enumerate the possible values for time checking if monitoring timing More...
 
using BestNodeTuple = std::tuple< const reco::ClusterHit3D *, float, float >
 
using BestNodeMap = std::unordered_map< const reco::ClusterHit3D *, BestNodeTuple >
 
using MinMaxPoints = std::pair< reco::ProjectedPoint, reco::ProjectedPoint >
 Add ability to build the convex hull (these needs to be split out! ) More...
 
using MinMaxPointPair = std::pair< MinMaxPoints, MinMaxPoints >
 

Private Member Functions

void RunPrimsAlgorithm (const reco::HitPairListPtr &, kdTree::KdTreeNode &, reco::ClusterParametersList &) const
 Driver for Prim's algorithm. More...
 
void PruneAmbiguousHits (reco::ClusterParameters &, reco::Hit2DToClusterMap &) const
 Prune the obvious ambiguous hits. More...
 
void FindBestPathInCluster (reco::ClusterParameters &) const
 Algorithm to find the best path through the given cluster. More...
 
reco::HitPairListPtr DepthFirstSearch (const reco::EdgeTuple &, const reco::Hit3DToEdgeMap &, float &) const
 a depth first search to find longest branches More...
 
void FindBestPathInCluster (reco::ClusterParameters &, kdTree::KdTreeNode &) const
 Alternative version of FindBestPathInCluster utilizing an A* algorithm. More...
 
void AStar (const reco::ClusterHit3D *, const reco::ClusterHit3D *, float alpha, kdTree::KdTreeNode &, reco::ClusterParameters &) const
 Algorithm to find shortest path between two 3D hits. More...
 
void ReconstructBestPath (const reco::ClusterHit3D *, BestNodeMap &, reco::HitPairListPtr &, reco::EdgeList &) const
 
float DistanceBetweenNodes (const reco::ClusterHit3D *, const reco::ClusterHit3D *) const
 
void LeastCostPath (const reco::EdgeTuple &, const reco::ClusterHit3D *, reco::ClusterParameters &, float &) const
 Find the lowest cost path between two nodes using MST edges. More...
 
void buildConvexHull (reco::ClusterParameters &, reco::HitPairListPtr &, int level=0) const
 
float findConvexHullEndPoints (const reco::EdgeList &, const reco::ClusterHit3D *, const reco::ClusterHit3D *) const
 

Private Attributes

bool fEnableMonitoring
 Data members to follow. More...
 
size_t fMinTinyClusterSize
 Minimum size for a "tiny" cluster. More...
 
float fConvexHullKinkAngle
 Angle to declare a kink in convex hull calc. More...
 
float fConvexHullMinSep
 Min hit separation to conisder in convex hull. More...
 
std::vector< float > fTimeVector
 
geo::Geometry const * fGeometry
 
PrincipalComponentsAlg fPCAAlg
 
kdTree fkdTree
 
std::unique_ptr
< lar_cluster3d::IClusterParametersBuilder
fClusterBuilder
 Common cluster builder tool. More...
 

Detailed Description

Definition at line 50 of file MSTPathFinder_tool.cc.

Member Typedef Documentation

using lar_cluster3d::MSTPathFinder::BestNodeMap = std::unordered_map<const reco::ClusterHit3D*, BestNodeTuple>
private

Definition at line 143 of file MSTPathFinder_tool.cc.

using lar_cluster3d::MSTPathFinder::BestNodeTuple = std::tuple<const reco::ClusterHit3D*, float, float>
private

Definition at line 142 of file MSTPathFinder_tool.cc.

Definition at line 164 of file MSTPathFinder_tool.cc.

Add ability to build the convex hull (these needs to be split out! )

Definition at line 163 of file MSTPathFinder_tool.cc.

Member Enumeration Documentation

enumerate the possible values for time checking if monitoring timing

Enumerator
BUILDTHREEDHITS 
BUILDHITTOHITMAP 
RUNDBSCAN 
BUILDCLUSTERINFO 
PATHFINDING 
NUMTIMEVALUES 

Definition at line 95 of file MSTPathFinder_tool.cc.

Constructor & Destructor Documentation

lar_cluster3d::MSTPathFinder::MSTPathFinder ( const fhicl::ParameterSet &  pset)
explicit

Constructor.

Parameters
pset

Definition at line 191 of file MSTPathFinder_tool.cc.

192  : fPCAAlg(pset.get<fhicl::ParameterSet>("PrincipalComponentsAlg"))
193  , fkdTree(pset.get<fhicl::ParameterSet>("kdTree"))
194  {
195  this->configure(pset);
196  }
PrincipalComponentsAlg fPCAAlg
void configure(fhicl::ParameterSet const &pset) override
Interface for configuring the particular algorithm tool.
lar_cluster3d::MSTPathFinder::~MSTPathFinder ( )

Destructor.

Definition at line 200 of file MSTPathFinder_tool.cc.

200 {}

Member Function Documentation

void lar_cluster3d::MSTPathFinder::AStar ( const reco::ClusterHit3D startNode,
const reco::ClusterHit3D goalNode,
float  alpha,
kdTree::KdTreeNode topNode,
reco::ClusterParameters clusterParams 
) const
private

Algorithm to find shortest path between two 3D hits.

Definition at line 616 of file MSTPathFinder_tool.cc.

621  {
622  // Recover the list of hits and edges
623  reco::HitPairListPtr& pathNodeList = clusterParams.getBestHitPairListPtr();
624  reco::EdgeList& bestEdgeList = clusterParams.getBestEdgeList();
625  reco::Hit3DToEdgeMap& curEdgeMap = clusterParams.getHit3DToEdgeMap();
626 
627  // Find the shortest path from start to goal using an A* algorithm
628  // Keep track of the nodes which have already been evaluated
629  reco::HitPairListPtr closedList;
630 
631  // Keep track of the nodes that have been "discovered" but yet to be evaluated
632  reco::HitPairListPtr openList = {startNode};
633 
634  // Create a map which, for each node, will tell us the node it can be most efficiencly reached from.
635  BestNodeMap bestNodeMap;
636 
637  bestNodeMap[startNode] =
638  BestNodeTuple(startNode, 0., DistanceBetweenNodes(startNode, goalNode));
639 
640  alpha = 1.; //std::max(0.5,alpha);
641 
642  while (!openList.empty()) {
643  // The list is not empty so by def we will return something
644  reco::HitPairListPtr::iterator currentNodeItr = openList.begin();
645 
646  // If the list contains more than one element then we need to find the one with the smallest total estimated cost to the end
647  if (openList.size() > 1)
648  currentNodeItr = std::min_element(
649  openList.begin(), openList.end(), [bestNodeMap](const auto& next, const auto& best) {
650  return std::get<2>(bestNodeMap.at(next)) < std::get<2>(bestNodeMap.at(best));
651  });
652 
653  // Easier to deal directly with the pointer to the node
654  const reco::ClusterHit3D* currentNode = *currentNodeItr;
655 
656  // Check to see if we have reached the goal and need to evaluate the path
657  if (currentNode == goalNode) {
658  // The path reconstruction will
659  ReconstructBestPath(goalNode, bestNodeMap, pathNodeList, bestEdgeList);
660 
661  break;
662  }
663 
664  // Otherwise need to keep evaluating
665  else {
666  openList.erase(currentNodeItr);
668 
669  // Get tuple values for the current node
670  const BestNodeTuple& currentNodeTuple = bestNodeMap.at(currentNode);
671  float currentNodeScore = std::get<1>(currentNodeTuple);
672 
673  // Recover the edges associated to the current point
674  const reco::EdgeList& curEdgeList = curEdgeMap[currentNode];
675 
676  for (const auto& curEdge : curEdgeList) {
677  const reco::ClusterHit3D* candHit3D = std::get<1>(curEdge);
678 
679  if (candHit3D->getStatusBits() & reco::ClusterHit3D::PATHCHECKED) continue;
680 
681  float tentative_gScore = currentNodeScore + std::get<2>(curEdge);
682 
683  // Have we seen the candidate node before?
684  BestNodeMap::iterator candNodeItr = bestNodeMap.find(candHit3D);
685 
686  if (candNodeItr == bestNodeMap.end()) { openList.push_back(candHit3D); }
687  else if (tentative_gScore > std::get<1>(candNodeItr->second))
688  continue;
689 
690  // Make a guess at score to get to target...
691  float guessToTarget = DistanceBetweenNodes(candHit3D, goalNode) / 0.3;
692 
693  bestNodeMap[candHit3D] =
694  BestNodeTuple(currentNode, tentative_gScore, tentative_gScore + guessToTarget);
695  }
696  }
697  }
698 
699  return;
700  }
reco::HitPairListPtr & getBestHitPairListPtr()
Definition: Cluster3D.h:479
std::unordered_map< const reco::ClusterHit3D *, BestNodeTuple > BestNodeMap
std::tuple< const reco::ClusterHit3D *, float, float > BestNodeTuple
reco::EdgeList & getBestEdgeList()
Definition: Cluster3D.h:480
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
Definition: Cluster3D.h:478
unsigned int getStatusBits() const
Definition: Cluster3D.h:156
std::list< EdgeTuple > EdgeList
Definition: Cluster3D.h:344
Path checking algorithm has seen this hit.
Definition: Cluster3D.h:110
void ReconstructBestPath(const reco::ClusterHit3D *, BestNodeMap &, reco::HitPairListPtr &, reco::EdgeList &) const
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:334
float DistanceBetweenNodes(const reco::ClusterHit3D *, const reco::ClusterHit3D *) const
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:346
void setStatusBit(unsigned bits) const
Definition: Cluster3D.h:179
void lar_cluster3d::MSTPathFinder::buildConvexHull ( reco::ClusterParameters clusterParameters,
reco::HitPairListPtr hitPairListPtr,
int  level = 0 
) const
private

Definition at line 931 of file MSTPathFinder_tool.cc.

934  {
935  // set an indention string
936  std::string minuses(level / 2, '-');
937  std::string indent(level / 2, ' ');
938 
939  indent += minuses;
940 
941  // The plan is to build the enclosing 2D polygon around the points in the PCA plane of most spread for this cluster
942  // To do so we need to start by building a list of 2D projections onto the plane of most spread...
943  reco::PrincipalComponents& pca = clusterParameters.getFullPCA();
944 
945  // Recover the parameters from the Principal Components Analysis that we need to project and accumulate
946  const Eigen::Vector3f& pcaCenter = pca.getAvePosition();
947  reco::ConvexHull& convexHull = clusterParameters.getConvexHull();
948  reco::ProjectedPointList& pointList = convexHull.getProjectedPointList();
949 
950  // Loop through hits and do projection to plane
951  for (const auto& hit3D : hitPairListPtr) {
952  Eigen::Vector3f pcaToHitVec(hit3D->getPosition()[0] - pcaCenter(0),
953  hit3D->getPosition()[1] - pcaCenter(1),
954  hit3D->getPosition()[2] - pcaCenter(2));
955  Eigen::Vector3f pcaToHit = pca.getEigenVectors() * pcaToHitVec;
956 
957  pointList.emplace_back(pcaToHit(1), pcaToHit(2), hit3D);
958  }
959 
960  // Sort the point vec by increasing x, then increase y
961  pointList.sort([](const auto& left, const auto& right) {
962  return (std::abs(std::get<0>(left) - std::get<0>(right)) >
963  std::numeric_limits<float>::epsilon()) ?
964  std::get<0>(left) < std::get<0>(right) :
965  std::get<1>(left) < std::get<1>(right);
966  });
967 
968  // containers for finding the "best" hull...
969  std::vector<ConvexHull> convexHullVec;
970  std::vector<reco::ProjectedPointList> rejectedListVec;
971  bool increaseDepth(pointList.size() > 3);
972  float lastArea(std::numeric_limits<float>::max());
973 
974  while (increaseDepth) {
975  // Get another convexHull container
976  convexHullVec.push_back(ConvexHull(pointList, fConvexHullKinkAngle, fConvexHullMinSep));
977  rejectedListVec.push_back(reco::ProjectedPointList());
978 
979  const ConvexHull& convexHull = convexHullVec.back();
980  reco::ProjectedPointList& rejectedList = rejectedListVec.back();
981  const reco::ProjectedPointList& convexHullPoints = convexHull.getConvexHull();
982 
983  increaseDepth = false;
984 
985  if (convexHull.getConvexHullArea() > 0.) {
986  if (convexHullVec.size() < 2 || convexHull.getConvexHullArea() < 0.8 * lastArea) {
987  for (auto& point : convexHullPoints) {
988  pointList.remove(point);
989  rejectedList.emplace_back(point);
990  }
991  lastArea = convexHull.getConvexHullArea();
992  // increaseDepth = true;
993  }
994  }
995  }
996 
997  // do we have a valid convexHull?
998  while (!convexHullVec.empty() && convexHullVec.back().getConvexHullArea() < 0.5) {
999  convexHullVec.pop_back();
1000  rejectedListVec.pop_back();
1001  }
1002 
1003  // If we found the convex hull then build edges around the region
1004  if (!convexHullVec.empty()) {
1005  size_t nRejectedTotal(0);
1006  reco::HitPairListPtr locHitPairListPtr = hitPairListPtr;
1007 
1008  for (const auto& rejectedList : rejectedListVec) {
1009  nRejectedTotal += rejectedList.size();
1010 
1011  for (const auto& rejectedPoint : rejectedList) {
1012  if (convexHullVec.back().findNearestDistance(rejectedPoint) > 0.5)
1013  locHitPairListPtr.remove(std::get<2>(rejectedPoint));
1014  }
1015  }
1016 
1017  // Now add "edges" to the cluster to describe the convex hull (for the display)
1018  reco::ProjectedPointList& convexHullPointList = convexHull.getConvexHullPointList();
1019  reco::Hit3DToEdgeMap& edgeMap = convexHull.getConvexHullEdgeMap();
1020  reco::EdgeList& edgeList = convexHull.getConvexHullEdgeList();
1021 
1022  reco::ProjectedPoint lastPoint = convexHullVec.back().getConvexHull().front();
1023 
1024  for (auto& curPoint : convexHullVec.back().getConvexHull()) {
1025  if (curPoint == lastPoint) continue;
1026 
1027  const reco::ClusterHit3D* lastPoint3D = std::get<2>(lastPoint);
1028  const reco::ClusterHit3D* curPoint3D = std::get<2>(curPoint);
1029 
1030  float distBetweenPoints = (curPoint3D->getPosition()[0] - lastPoint3D->getPosition()[0]) *
1031  (curPoint3D->getPosition()[0] - lastPoint3D->getPosition()[0]) +
1032  (curPoint3D->getPosition()[1] - lastPoint3D->getPosition()[1]) *
1033  (curPoint3D->getPosition()[1] - lastPoint3D->getPosition()[1]) +
1034  (curPoint3D->getPosition()[2] - lastPoint3D->getPosition()[2]) *
1035  (curPoint3D->getPosition()[2] - lastPoint3D->getPosition()[2]);
1036 
1037  distBetweenPoints = std::sqrt(distBetweenPoints);
1038 
1039  reco::EdgeTuple edge(lastPoint3D, curPoint3D, distBetweenPoints);
1040 
1041  convexHullPointList.push_back(curPoint);
1042  edgeMap[lastPoint3D].push_back(edge);
1043  edgeMap[curPoint3D].push_back(edge);
1044  edgeList.emplace_back(edge);
1045 
1046  lastPoint = curPoint;
1047  }
1048 
1049  // Store the "extreme" points
1050  const ConvexHull::PointList& extremePoints = convexHullVec.back().getExtremePoints();
1051  reco::ProjectedPointList& extremePointList = convexHull.getConvexHullExtremePoints();
1052 
1053  for (const auto& point : extremePoints)
1054  extremePointList.push_back(point);
1055 
1056  // Store the "kink" points
1057  const reco::ConvexHullKinkTupleList& kinkPoints = convexHullVec.back().getKinkPoints();
1058  reco::ConvexHullKinkTupleList& kinkPointList = convexHull.getConvexHullKinkPoints();
1059 
1060  for (const auto& kink : kinkPoints)
1061  kinkPointList.push_back(kink);
1062  }
1063 
1064  return;
1065  }
const Eigen::Vector3f getPosition() const
Definition: Cluster3D.h:157
std::list< ProjectedPoint > ProjectedPointList
Definition: Cluster3D.h:352
walls no right
Definition: selectors.fcl:105
std::list< Point > PointList
The list of the projected points.
Definition: ConvexHull.h:34
float fConvexHullMinSep
Min hit separation to conisder in convex hull.
T abs(T value)
std::list< EdgeTuple > EdgeList
Definition: Cluster3D.h:344
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:476
Define a container for working with the convex hull.
Definition: Cluster3D.h:359
const Eigen::Vector3f & getAvePosition() const
Definition: Cluster3D.h:247
std::list< ConvexHullKinkTuple > ConvexHullKinkTupleList
Definition: Cluster3D.h:354
std::tuple< const reco::ClusterHit3D *, const reco::ClusterHit3D *, double > EdgeTuple
Definition: Cluster3D.h:343
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:334
walls no left
Definition: selectors.fcl:105
float fConvexHullKinkAngle
Angle to declare a kink in convex hull calc.
reco::ConvexHull & getConvexHull()
Definition: Cluster3D.h:481
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:346
reco::ProjectedPointList & getProjectedPointList()
Definition: Cluster3D.h:382
std::tuple< float, float, const reco::ClusterHit3D * > ProjectedPoint
Projected coordinates and pointer to hit.
Definition: Cluster3D.h:351
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:246
void lar_cluster3d::MSTPathFinder::configure ( fhicl::ParameterSet const &  )
overridevirtual

Interface for configuring the particular algorithm tool.

Parameters
ParameterSetThe input set of parameters for configuration

Implements lar_cluster3d::IClusterModAlg.

Definition at line 205 of file MSTPathFinder_tool.cc.

206  {
207  fEnableMonitoring = pset.get<bool>("EnableMonitoring", true);
208  fMinTinyClusterSize = pset.get<size_t>("MinTinyClusterSize", 40);
209  fConvexHullKinkAngle = pset.get<float>("ConvexHullKinkAgle", 0.95);
210  fConvexHullMinSep = pset.get<float>("ConvexHullMinSep", 0.65);
211 
212  art::ServiceHandle<geo::Geometry const> geometry;
213 
214  fGeometry = &*geometry;
215 
216  fTimeVector.resize(NUMTIMEVALUES, 0.);
217 
218  fClusterBuilder = art::make_tool<lar_cluster3d::IClusterParametersBuilder>(
219  pset.get<fhicl::ParameterSet>("ClusterParamsBuilder"));
220 
221  return;
222  }
size_t fMinTinyClusterSize
Minimum size for a &quot;tiny&quot; cluster.
const geo::GeometryCore * geometry
float fConvexHullMinSep
Min hit separation to conisder in convex hull.
std::unique_ptr< lar_cluster3d::IClusterParametersBuilder > fClusterBuilder
Common cluster builder tool.
float fConvexHullKinkAngle
Angle to declare a kink in convex hull calc.
geo::Geometry const * fGeometry
bool fEnableMonitoring
Data members to follow.
std::vector< float > fTimeVector
reco::HitPairListPtr lar_cluster3d::MSTPathFinder::DepthFirstSearch ( const reco::EdgeTuple curEdge,
const reco::Hit3DToEdgeMap hitToEdgeMap,
float &  bestTreeQuality 
) const
private

a depth first search to find longest branches

Definition at line 806 of file MSTPathFinder_tool.cc.

809  {
810  reco::HitPairListPtr hitPairListPtr;
811  float bestQuality(0.);
812  float curEdgeWeight = std::max(0.3, std::get<2>(curEdge));
813  float curEdgeProj(1. / curEdgeWeight);
814 
815  reco::Hit3DToEdgeMap::const_iterator edgeListItr = hitToEdgeMap.find(std::get<1>(curEdge));
816 
817  if (edgeListItr != hitToEdgeMap.end()) {
818  // The input edge weight has quality factors applied, recalculate just the position difference
819  const Eigen::Vector3f& firstHitPos = std::get<0>(curEdge)->getPosition();
820  const Eigen::Vector3f& secondHitPos = std::get<1>(curEdge)->getPosition();
821  float curEdgeVec[] = {secondHitPos[0] - firstHitPos[0],
822  secondHitPos[1] - firstHitPos[1],
823  secondHitPos[2] - firstHitPos[2]};
824  float curEdgeMag = std::sqrt(curEdgeVec[0] * curEdgeVec[0] + curEdgeVec[1] * curEdgeVec[1] +
825  curEdgeVec[2] * curEdgeVec[2]);
826 
827  curEdgeMag = std::max(float(0.1), curEdgeMag);
828 
829  for (const auto& edge : edgeListItr->second) {
830  // skip the self reference
831  if (std::get<1>(edge) == std::get<0>(curEdge)) continue;
832 
833  float quality(0.);
834 
835  reco::HitPairListPtr tempList = DepthFirstSearch(edge, hitToEdgeMap, quality);
836 
837  if (quality > bestQuality) {
838  hitPairListPtr = tempList;
839  bestQuality = quality;
840  curEdgeProj = 1. / curEdgeMag;
841  }
842  }
843  }
844 
845  hitPairListPtr.push_front(std::get<1>(curEdge));
846 
847  bestTreeQuality += bestQuality + curEdgeProj;
848 
849  return hitPairListPtr;
850  }
reco::HitPairListPtr DepthFirstSearch(const reco::EdgeTuple &, const reco::Hit3DToEdgeMap &, float &) const
a depth first search to find longest branches
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:334
float lar_cluster3d::MSTPathFinder::DistanceBetweenNodes ( const reco::ClusterHit3D node1,
const reco::ClusterHit3D node2 
) const
private

Definition at line 774 of file MSTPathFinder_tool.cc.

776  {
777  const Eigen::Vector3f& node1Pos = node1->getPosition();
778  const Eigen::Vector3f& node2Pos = node2->getPosition();
779  float deltaNode[] = {
780  node1Pos[0] - node2Pos[0], node1Pos[1] - node2Pos[1], node1Pos[2] - node2Pos[2]};
781 
782  // Standard euclidean distance
783  return std::sqrt(deltaNode[0] * deltaNode[0] + deltaNode[1] * deltaNode[1] +
784  deltaNode[2] * deltaNode[2]);
785 
786  // Manhatten distance
787  //return std::fabs(deltaNode[0]) + std::fabs(deltaNode[1]) + std::fabs(deltaNode[2]);
788  /*
789  // Chebyshev distance
790  // We look for maximum distance by wires...
791 
792  // Now go through the hits and compare view by view to look for delta wire and tigher constraint on delta t
793  int wireDeltas[] = {0,0,0};
794 
795  for(size_t idx = 0; idx < 3; idx++)
796  wireDeltas[idx] = std::abs(int(node1->getWireIDs()[idx].Wire) - int(node2->getWireIDs()[idx].Wire));
797 
798  // put wire deltas in order...
799  std::sort(wireDeltas, wireDeltas + 3);
800 
801  return std::sqrt(deltaNode[0]*deltaNode[0] + 0.09 * float(wireDeltas[2]*wireDeltas[2]));
802  */
803  }
const Eigen::Vector3f getPosition() const
Definition: Cluster3D.h:157
void lar_cluster3d::MSTPathFinder::FindBestPathInCluster ( reco::ClusterParameters curCluster) const
private

Algorithm to find the best path through the given cluster.

Definition at line 445 of file MSTPathFinder_tool.cc.

446  {
447  reco::HitPairListPtr longestCluster;
448  float bestQuality(0.);
449  float aveNumEdges(0.);
450  size_t maxNumEdges(0);
451  size_t nIsolatedHits(0);
452 
453  // Now proceed with building the clusters
454  cet::cpu_timer theClockPathFinding;
455 
456  // Start clocks if requested
457  if (fEnableMonitoring) theClockPathFinding.start();
458 
459  reco::HitPairListPtr& hitPairList = curCluster.getHitPairListPtr();
460  reco::Hit3DToEdgeMap& curEdgeMap = curCluster.getHit3DToEdgeMap();
461  reco::EdgeList& bestEdgeList = curCluster.getBestEdgeList();
462 
463  // Do some spelunking...
464  for (const auto& hit : hitPairList) {
465  if (!curEdgeMap[hit].empty() && curEdgeMap[hit].size() == 1) {
466  float quality(0.);
467 
468  reco::HitPairListPtr tempList =
469  DepthFirstSearch(curEdgeMap[hit].front(), curEdgeMap, quality);
470 
471  tempList.push_front(std::get<0>(curEdgeMap[hit].front()));
472 
473  if (quality > bestQuality) {
474  longestCluster = tempList;
475  bestQuality = quality;
476  }
477 
478  nIsolatedHits++;
479  }
480 
481  aveNumEdges += float(curEdgeMap[hit].size());
482  maxNumEdges = std::max(maxNumEdges, curEdgeMap[hit].size());
483  }
484 
485  aveNumEdges /= float(hitPairList.size());
486  std::cout << "----> # isolated hits: " << nIsolatedHits
487  << ", longest branch: " << longestCluster.size()
488  << ", cluster size: " << hitPairList.size() << ", ave # edges: " << aveNumEdges
489  << ", max: " << maxNumEdges << std::endl;
490 
491  if (!longestCluster.empty()) {
492  hitPairList = longestCluster;
493  for (const auto& hit : hitPairList) {
494  for (const auto& edge : curEdgeMap[hit])
495  bestEdgeList.emplace_back(edge);
496  }
497 
498  std::cout << " ====> new cluster size: " << hitPairList.size() << std::endl;
499  }
500 
501  if (fEnableMonitoring) {
502  theClockPathFinding.stop();
503 
504  fTimeVector[PATHFINDING] += theClockPathFinding.accumulated_real_time();
505  }
506 
507  return;
508  }
reco::HitPairListPtr DepthFirstSearch(const reco::EdgeTuple &, const reco::Hit3DToEdgeMap &, float &) const
a depth first search to find longest branches
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
reco::EdgeList & getBestEdgeList()
Definition: Cluster3D.h:480
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
Definition: Cluster3D.h:478
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:475
process_name hit
Definition: cheaterreco.fcl:51
std::list< EdgeTuple > EdgeList
Definition: Cluster3D.h:344
walls no front
Definition: selectors.fcl:105
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:334
bool fEnableMonitoring
Data members to follow.
std::vector< float > fTimeVector
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:346
bool empty(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:555
BEGIN_PROLOG could also be cout
void lar_cluster3d::MSTPathFinder::FindBestPathInCluster ( reco::ClusterParameters clusterParams,
kdTree::KdTreeNode topNode 
) const
private

Alternative version of FindBestPathInCluster utilizing an A* algorithm.

Definition at line 511 of file MSTPathFinder_tool.cc.

513  {
514  // Set up for timing the function
515  cet::cpu_timer theClockPathFinding;
516 
517  // Start clocks if requested
518  if (fEnableMonitoring) theClockPathFinding.start();
519 
520  // Trial A* here
521  if (clusterParams.getHitPairListPtr().size() > 2) {
522  // Do a quick PCA to determine our parameter "alpha"
523  fPCAAlg.PCAAnalysis_3D(clusterParams.getHitPairListPtr(), clusterParams.getFullPCA());
524 
525  // Recover the new fullPCA
526  reco::PrincipalComponents& pca = clusterParams.getFullPCA();
527 
528  // The chances of a failure are remote, still we should check
529  if (pca.getSvdOK()) {
530  // Get references to what we need....
531  reco::HitPairListPtr& curCluster = clusterParams.getHitPairListPtr();
532  reco::Hit3DToEdgeMap& curEdgeMap = clusterParams.getHit3DToEdgeMap();
533  float pcaLen = 3.0 * sqrt(pca.getEigenValues()[2]);
534  float pcaWidth = 3.0 * sqrt(pca.getEigenValues()[1]);
535  float pcaHeight = 3.0 * sqrt(pca.getEigenValues()[0]);
536  const Eigen::Vector3f& pcaCenter = pca.getAvePosition();
537  float alpha = std::min(float(1.), std::max(float(0.001), pcaWidth / pcaLen));
538 
539  // Create a temporary container for the isolated points
540  reco::ProjectedPointList isolatedPointList;
541 
542  // Go through and find the isolated points, for those get the projection to the plane of maximum spread
543  for (const auto& hit3D : curCluster) {
544  // the definition of an isolated hit is that it only has one associated edge
545  if (!curEdgeMap[hit3D].empty() && curEdgeMap[hit3D].size() == 1) {
546  Eigen::Vector3f pcaToHitVec(hit3D->getPosition()[0] - pcaCenter(0),
547  hit3D->getPosition()[1] - pcaCenter(1),
548  hit3D->getPosition()[2] - pcaCenter(2));
549  Eigen::Vector3f pcaToHit = pca.getEigenVectors() * pcaToHitVec;
550 
551  // This sets x,y where x is the longer spread, y the shorter
552  isolatedPointList.emplace_back(pcaToHit(2), pcaToHit(1), hit3D);
553  }
554  }
555 
556  std::cout << "************* Finding best path with A* in cluster *****************"
557  << std::endl;
558  std::cout << "**> There are " << curCluster.size() << " hits, " << isolatedPointList.size()
559  << " isolated hits, the alpha parameter is " << alpha << std::endl;
560  std::cout << "**> PCA len: " << pcaLen << ", wid: " << pcaWidth << ", height: " << pcaHeight
561  << ", ratio: " << pcaHeight / pcaWidth << std::endl;
562 
563  // If no isolated points then nothing to do...
564  if (isolatedPointList.size() > 1) {
565  // Sort the point vec by increasing x, if same then by increasing y.
566  isolatedPointList.sort([](const auto& left, const auto& right) {
567  return (std::abs(std::get<0>(left) - std::get<0>(right)) >
568  std::numeric_limits<float>::epsilon()) ?
569  std::get<0>(left) < std::get<0>(right) :
570  std::get<1>(left) < std::get<1>(right);
571  });
572 
573  // Ok, get the two most distance points...
574  const reco::ClusterHit3D* startHit = std::get<2>(isolatedPointList.front());
575  const reco::ClusterHit3D* stopHit = std::get<2>(isolatedPointList.back());
576 
577  std::cout << "**> Sorted " << isolatedPointList.size()
578  << " hits, longest distance: " << DistanceBetweenNodes(startHit, stopHit)
579  << std::endl;
580 
581  // Call the AStar function to try to find the best path...
582  // AStar(startHit,stopHit,alpha,topNode,clusterParams);
583 
584  float cost(std::numeric_limits<float>::max());
585 
586  LeastCostPath(curEdgeMap[startHit].front(), stopHit, clusterParams, cost);
587 
588  clusterParams.getBestHitPairListPtr().push_front(startHit);
589 
590  std::cout << "**> Best path has " << clusterParams.getBestHitPairListPtr().size()
591  << " hits, " << clusterParams.getBestEdgeList().size() << " edges" << std::endl;
592  }
593 
594  // Recalculate the PCA based on the hits comprisig the path
595  fPCAAlg.PCAAnalysis_3D(clusterParams.getBestHitPairListPtr(), pca);
596 
597  // And now compute the convex hull
598  buildConvexHull(clusterParams, clusterParams.getBestHitPairListPtr());
599  }
600  else {
601  std::cout << "++++++>>> PCA failure! # hits: " << clusterParams.getHitPairListPtr().size()
602  << std::endl;
603  }
604  }
605 
606  if (fEnableMonitoring) {
607  theClockPathFinding.stop();
608 
609  fTimeVector[PATHFINDING] += theClockPathFinding.accumulated_real_time();
610  }
611 
612  return;
613  }
reco::HitPairListPtr & getBestHitPairListPtr()
Definition: Cluster3D.h:479
bool getSvdOK() const
Definition: Cluster3D.h:243
void PCAAnalysis_3D(const reco::HitPairListPtr &hitPairList, reco::PrincipalComponents &pca, bool skeletonOnly=false) const
std::list< ProjectedPoint > ProjectedPointList
Definition: Cluster3D.h:352
walls no right
Definition: selectors.fcl:105
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
reco::EdgeList & getBestEdgeList()
Definition: Cluster3D.h:480
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
Definition: Cluster3D.h:478
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:475
T abs(T value)
walls no front
Definition: selectors.fcl:105
const EigenValues & getEigenValues() const
Definition: Cluster3D.h:245
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:476
void LeastCostPath(const reco::EdgeTuple &, const reco::ClusterHit3D *, reco::ClusterParameters &, float &) const
Find the lowest cost path between two nodes using MST edges.
const Eigen::Vector3f & getAvePosition() const
Definition: Cluster3D.h:247
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:334
walls no left
Definition: selectors.fcl:105
PrincipalComponentsAlg fPCAAlg
float DistanceBetweenNodes(const reco::ClusterHit3D *, const reco::ClusterHit3D *) const
bool fEnableMonitoring
Data members to follow.
std::vector< float > fTimeVector
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:346
void buildConvexHull(reco::ClusterParameters &, reco::HitPairListPtr &, int level=0) const
bool empty(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:555
BEGIN_PROLOG could also be cout
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:246
float lar_cluster3d::MSTPathFinder::findConvexHullEndPoints ( const reco::EdgeList convexHull,
const reco::ClusterHit3D first3D,
const reco::ClusterHit3D last3D 
) const
private

Definition at line 1068 of file MSTPathFinder_tool.cc.

1071  {
1072  float largestDistance(0.);
1073 
1074  // Note that edges are vectors and that the convex hull edge list will be ordered
1075  // The idea is that the maximum distance from a given edge is to the edge just before the edge that "turns back" towards the current edge
1076  // meaning that the dot product of the two edges becomes negative.
1077  reco::EdgeList::const_iterator firstEdgeItr = convexHull.begin();
1078 
1079  while (firstEdgeItr != convexHull.end()) {
1080  reco::EdgeList::const_iterator nextEdgeItr = firstEdgeItr;
1081 
1082  // Eigen::Vector2f firstEdgeVec(std::get<3>(*firstEdgeItr),std::get<);
1083  // Eigen::Vector2f lastPrimaryVec(lastPCA.getEigenVectors()[0][0],lastPCA.getEigenVectors()[0][1],lastPCA.getEigenVectors()[0][2]);
1084  // float cosToLast = newPrimaryVec.dot(lastPrimaryVec);
1085 
1086  while (++nextEdgeItr != convexHull.end()) {}
1087  }
1088 
1089  return largestDistance;
1090  }
float lar_cluster3d::MSTPathFinder::getTimeToExecute ( ) const
inlineoverridevirtual

If monitoring, recover the time to execute a particular function.

Implements lar_cluster3d::IClusterModAlg.

Definition at line 86 of file MSTPathFinder_tool.cc.

87  {
88  return std::accumulate(fTimeVector.begin(), fTimeVector.end(), 0.);
89  }
std::vector< float > fTimeVector
void lar_cluster3d::MSTPathFinder::initializeHistograms ( art::TFileDirectory &  histDir)
overridevirtual

Interface for initializing histograms if they are desired Note that the idea is to put hisgtograms in a subfolder.

Parameters
TFileDirectory- the folder to store the hists in

Implements lar_cluster3d::IClusterModAlg.

Definition at line 225 of file MSTPathFinder_tool.cc.

226  {
227  // It is assumed that the input TFileDirectory has been set up to group histograms into a common
228  // folder at the calling routine's level. Here we create one more level of indirection to keep
229  // histograms made by this tool separate.
230  // fFillHistograms = true;
231  //
232  // std::string dirName = "ConvexHullPath";
233  //
234  // art::TFileDirectory dir = histDir.mkdir(dirName.c_str());
235  //
236  // // Divide into two sets of hists... those for the overall cluster and
237  // // those for the subclusters
238  // fTopNum3DHits = dir.make<TH1F>("TopNum3DHits", "Number 3D Hits", 200, 0., 200.);
239 
240  return;
241  }
void lar_cluster3d::MSTPathFinder::LeastCostPath ( const reco::EdgeTuple curEdge,
const reco::ClusterHit3D goalNode,
reco::ClusterParameters clusterParams,
float &  showMeTheMoney 
) const
private

Find the lowest cost path between two nodes using MST edges.

Definition at line 725 of file MSTPathFinder_tool.cc.

729  {
730  // Recover the mapping between hits and edges
731  reco::Hit3DToEdgeMap& curEdgeMap = clusterParams.getHit3DToEdgeMap();
732 
733  reco::Hit3DToEdgeMap::const_iterator edgeListItr = curEdgeMap.find(std::get<1>(curEdge));
734 
735  showMeTheMoney = std::numeric_limits<float>::max();
736 
737  if (edgeListItr != curEdgeMap.end() && !edgeListItr->second.empty()) {
738  reco::HitPairListPtr& bestNodeList = clusterParams.getBestHitPairListPtr();
739  reco::EdgeList& bestEdgeList = clusterParams.getBestEdgeList();
740 
741  for (const auto& edge : edgeListItr->second) {
742  // skip the self reference
743  if (std::get<1>(edge) == std::get<0>(curEdge)) continue;
744 
745  // Have we found the droid we are looking for?
746  if (std::get<1>(edge) == goalNode) {
747  bestNodeList.push_back(goalNode);
748  bestEdgeList.push_back(edge);
749  showMeTheMoney = std::get<2>(edge);
750  break;
751  }
752 
753  // Keep searching, it is out there somewhere...
754  float currentCost(0.);
755 
756  LeastCostPath(edge, goalNode, clusterParams, currentCost);
757 
758  if (currentCost < std::numeric_limits<float>::max()) {
759  showMeTheMoney = std::get<2>(edge) + currentCost;
760  break;
761  }
762  }
763  }
764 
765  if (showMeTheMoney < std::numeric_limits<float>::max()) {
766  clusterParams.getBestHitPairListPtr().push_front(std::get<1>(curEdge));
767  clusterParams.getBestEdgeList().push_front(curEdge);
768  }
769 
770  return;
771  }
reco::HitPairListPtr & getBestHitPairListPtr()
Definition: Cluster3D.h:479
reco::EdgeList & getBestEdgeList()
Definition: Cluster3D.h:480
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
Definition: Cluster3D.h:478
std::list< EdgeTuple > EdgeList
Definition: Cluster3D.h:344
void LeastCostPath(const reco::EdgeTuple &, const reco::ClusterHit3D *, reco::ClusterParameters &, float &) const
Find the lowest cost path between two nodes using MST edges.
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:334
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:346
void lar_cluster3d::MSTPathFinder::ModifyClusters ( reco::ClusterParametersList clusterParametersList) const
overridevirtual

Scan an input collection of clusters and modify those according to the specific implementing algorithm.

Parameters
clusterParametersListA list of cluster objects (parameters from associated hits)

Top level interface tool for performing deghosting and primary path finding using a minimum spanning tree approach. This is a shell tool, it actually uses the Minimum Spanning Tree clusering tool...

Implements lar_cluster3d::IClusterModAlg.

Definition at line 244 of file MSTPathFinder_tool.cc.

245  {
246  /**
247  * @brief Top level interface tool for performing deghosting and primary path finding
248  * using a minimum spanning tree approach. This is a shell tool, it actually uses the
249  * Minimum Spanning Tree clusering tool...
250  */
251 
252  // Initial clustering is done, now trim the list and get output parameters
253  cet::cpu_timer theClockBuildClusters;
254 
255  // Start clocks if requested
256  if (fEnableMonitoring) theClockBuildClusters.start();
257 
258  // Ok, the idea here is to loop over the input clusters and the process one at a time and then use the MST algorithm
259  // to deghost and try to find the best path.
260  for (auto& clusterParams : clusterParametersList) {
261  // It turns out that computing the convex hull surrounding the points in the 2D projection onto the
262  // plane of largest spread in the PCA is a good way to break up the cluster... and we do it here since
263  // we (currently) want this to be part of the standard output
264  buildConvexHull(clusterParams, clusterParams.getHitPairListPtr());
265 
266  // Make sure our cluster has enough hits...
267  if (clusterParams.getHitPairListPtr().size() > fMinTinyClusterSize) {
268  // DBScan is driven of its "epsilon neighborhood". Computing adjacency within DBScan can be time
269  // consuming so the idea is the prebuild the adjaceny map and then run DBScan.
270  // The following call does this work
271  kdTree::KdTreeNodeList kdTreeNodeContainer;
272  kdTree::KdTreeNode topNode =
273  fkdTree.BuildKdTree(clusterParams.getHitPairListPtr(), kdTreeNodeContainer);
274 
276 
277  // We are making subclusters
278  reco::ClusterParametersList& daughterParametersList = clusterParams.daughterList();
279 
280  // Run DBScan to get candidate clusters
281  RunPrimsAlgorithm(clusterParams.getHitPairListPtr(), topNode, daughterParametersList);
282 
283  // Initial clustering is done, now trim the list and get output parameters
284  cet::cpu_timer theClockBuildClusters;
285 
286  // Start clocks if requested
287  if (fEnableMonitoring) theClockBuildClusters.start();
288 
289  fClusterBuilder->BuildClusterInfo(daughterParametersList);
290 
291  if (fEnableMonitoring) {
292  theClockBuildClusters.stop();
293 
294  fTimeVector[BUILDCLUSTERINFO] = theClockBuildClusters.accumulated_real_time();
295  }
296 
297  // Test run the path finding algorithm
298  for (auto& daughterParams : daughterParametersList)
299  FindBestPathInCluster(daughterParams, topNode);
300  }
301  }
302 
303  if (fEnableMonitoring) {
304  theClockBuildClusters.stop();
305 
306  fTimeVector[BUILDCLUSTERINFO] = theClockBuildClusters.accumulated_real_time();
307  }
308 
309  mf::LogDebug("MSTPathFinder") << ">>>>> Cluster Path finding done" << std::endl;
310 
311  return;
312  }
void RunPrimsAlgorithm(const reco::HitPairListPtr &, kdTree::KdTreeNode &, reco::ClusterParametersList &) const
Driver for Prim&#39;s algorithm.
size_t fMinTinyClusterSize
Minimum size for a &quot;tiny&quot; cluster.
void FindBestPathInCluster(reco::ClusterParameters &) const
Algorithm to find the best path through the given cluster.
std::list< KdTreeNode > KdTreeNodeList
Definition: kdTree.h:67
std::unique_ptr< lar_cluster3d::IClusterParametersBuilder > fClusterBuilder
Common cluster builder tool.
bool fEnableMonitoring
Data members to follow.
std::vector< float > fTimeVector
float getTimeToExecute() const
Definition: kdTree.h:95
void buildConvexHull(reco::ClusterParameters &, reco::HitPairListPtr &, int level=0) const
KdTreeNode & BuildKdTree(Hit3DVec::iterator, Hit3DVec::iterator, KdTreeNodeList &, int depth=0) const
Given an input set of ClusterHit3D objects, build a kd tree structure.
Definition: kdTree.cxx:112
std::list< ClusterParameters > ClusterParametersList
Definition: Cluster3D.h:403
void lar_cluster3d::MSTPathFinder::PruneAmbiguousHits ( reco::ClusterParameters clusterParams,
reco::Hit2DToClusterMap hit2DToClusterMap 
) const
private

Prune the obvious ambiguous hits.

Definition at line 853 of file MSTPathFinder_tool.cc.

855  {
856 
857  // Recover the HitPairListPtr from the input clusterParams (which will be the
858  // only thing that has been provided)
859  reco::HitPairListPtr& hitPairVector = clusterParams.getHitPairListPtr();
860 
861  size_t nStartedWith(hitPairVector.size());
862  size_t nRejectedHits(0);
863 
864  reco::HitPairListPtr goodHits;
865 
866  // Loop through the hits and try to week out the clearly ambiguous ones
867  for (const auto& hit3D : hitPairVector) {
868  // Loop to try to remove ambiguous hits
869  size_t n2DHitsIn3DHit(0);
870  size_t nThisClusterOnly(0);
871  size_t nOtherCluster(0);
872 
873  // reco::ClusterParameters* otherCluster;
874  const std::set<const reco::ClusterHit3D*>* otherClusterHits = 0;
875 
876  for (const auto& hit2D : hit3D->getHits()) {
877  if (!hit2D) continue;
878 
879  n2DHitsIn3DHit++;
880 
881  if (hit2DToClusterMap[hit2D].size() < 2)
882  nThisClusterOnly = hit2DToClusterMap[hit2D][&clusterParams].size();
883  else {
884  for (const auto& clusterHitMap : hit2DToClusterMap[hit2D]) {
885  if (clusterHitMap.first == &clusterParams) continue;
886 
887  if (clusterHitMap.second.size() > nOtherCluster) {
888  nOtherCluster = clusterHitMap.second.size();
889  // otherCluster = clusterHitMap.first;
890  otherClusterHits = &clusterHitMap.second;
891  }
892  }
893  }
894  }
895 
896  if (n2DHitsIn3DHit < 3 && nThisClusterOnly > 1 && nOtherCluster > 0) {
897  bool skip3DHit(false);
898 
899  for (const auto& otherHit3D : *otherClusterHits) {
900  size_t nOther2DHits(0);
901 
902  for (const auto& otherHit2D : otherHit3D->getHits()) {
903  if (!otherHit2D) continue;
904 
905  nOther2DHits++;
906  }
907 
908  if (nOther2DHits > 2) {
909  skip3DHit = true;
910  nRejectedHits++;
911  break;
912  }
913  }
914 
915  if (skip3DHit) continue;
916  }
917 
918  goodHits.emplace_back(hit3D);
919  }
920 
921  std::cout << "###>> Input " << nStartedWith << " hits, rejected: " << nRejectedHits
922  << std::endl;
923 
924  hitPairVector.resize(goodHits.size());
925  std::copy(goodHits.begin(), goodHits.end(), hitPairVector.begin());
926 
927  return;
928  }
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:475
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:334
T copy(T const &v)
BEGIN_PROLOG could also be cout
void lar_cluster3d::MSTPathFinder::ReconstructBestPath ( const reco::ClusterHit3D goalNode,
BestNodeMap bestNodeMap,
reco::HitPairListPtr pathNodeList,
reco::EdgeList bestEdgeList 
) const
private

Definition at line 703 of file MSTPathFinder_tool.cc.

707  {
708  while (std::get<0>(bestNodeMap.at(goalNode)) != goalNode) {
709  const reco::ClusterHit3D* nextNode = std::get<0>(bestNodeMap[goalNode]);
710  reco::EdgeTuple bestEdge =
711  reco::EdgeTuple(goalNode, nextNode, DistanceBetweenNodes(goalNode, nextNode));
712 
713  pathNodeList.push_front(goalNode);
714  bestEdgeList.push_front(bestEdge);
715 
716  goalNode = nextNode;
717  }
718 
719  pathNodeList.push_front(goalNode);
720 
721  return;
722  }
std::tuple< const reco::ClusterHit3D *, const reco::ClusterHit3D *, double > EdgeTuple
Definition: Cluster3D.h:343
float DistanceBetweenNodes(const reco::ClusterHit3D *, const reco::ClusterHit3D *) const
void lar_cluster3d::MSTPathFinder::RunPrimsAlgorithm ( const reco::HitPairListPtr hitPairList,
kdTree::KdTreeNode topNode,
reco::ClusterParametersList clusterParametersList 
) const
private

Driver for Prim's algorithm.

Definition at line 316 of file MSTPathFinder_tool.cc.

319  {
320  // If no hits then no work
321  if (hitPairList.empty()) return;
322 
323  // Now proceed with building the clusters
324  cet::cpu_timer theClockDBScan;
325 
326  // Start clocks if requested
327  if (fEnableMonitoring) theClockDBScan.start();
328 
329  // Initialization
330  size_t clusterIdx(0);
331 
332  // This will contain our list of edges
333  reco::EdgeList curEdgeList;
334 
335  // Get the first point
336  reco::HitPairListPtr::const_iterator freeHitItr = hitPairList.begin();
337  const reco::ClusterHit3D* lastAddedHit = *freeHitItr++;
338 
340 
341  // Make a cluster...
342  clusterParametersList.push_back(reco::ClusterParameters());
343 
344  // Get an iterator to the first cluster
345  reco::ClusterParameters* curCluster = &clusterParametersList.back();
346 
347  // We use pointers here because the objects they point to will change in the loop below
348  reco::Hit3DToEdgeMap* curEdgeMap = &curCluster->getHit3DToEdgeMap();
349  reco::HitPairListPtr* curClusterHitList = &curCluster->getHitPairListPtr();
350 
351  // Loop until all hits have been associated to a cluster
352  while (1) {
353  // and the 3D hit status bits
355 
356  // Purge the current list to get rid of edges which point to hits already in the cluster
357  for (reco::EdgeList::iterator curEdgeItr = curEdgeList.begin();
358  curEdgeItr != curEdgeList.end();) {
359  if (std::get<1>(*curEdgeItr)->getStatusBits() & reco::ClusterHit3D::CLUSTERATTACHED)
360  curEdgeItr = curEdgeList.erase(curEdgeItr);
361  else
362  curEdgeItr++;
363  }
364 
365  // Add the lastUsedHit to the current cluster
366  curClusterHitList->push_back(lastAddedHit);
367 
368  // Set up to find the list of nearest neighbors to the last used hit...
369  kdTree::CandPairList CandPairList;
370  float bestDistance(1.5); //std::numeric_limits<float>::max());
371 
372  // And find them... result will be an unordered list of neigbors
373  fkdTree.FindNearestNeighbors(lastAddedHit, topNode, CandPairList, bestDistance);
374 
375  // Copy edges to the current list (but only for hits not already in a cluster)
376  // for(auto& pair : CandPairList)
377  // if (!(pair.second->getStatusBits() & reco::ClusterHit3D::CLUSTERATTACHED)) curEdgeList.push_back(reco::EdgeTuple(lastAddedHit,pair.second,pair.first));
378  for (auto& pair : CandPairList) {
379  if (!(pair.second->getStatusBits() & reco::ClusterHit3D::CLUSTERATTACHED)) {
380  double edgeWeight =
381  pair.first * lastAddedHit->getHitChiSquare() * pair.second->getHitChiSquare();
382 
383  curEdgeList.push_back(reco::EdgeTuple(lastAddedHit, pair.second, edgeWeight));
384  }
385  }
386 
387  // If the edge list is empty then we have a complete cluster
388  if (curEdgeList.empty()) {
389  std::cout << "-----------------------------------------------------------------------------"
390  "------------"
391  << std::endl;
392  std::cout << "**> Cluster idx: " << clusterIdx++ << " has " << curClusterHitList->size()
393  << " hits" << std::endl;
394 
395  // Look for the next "free" hit
396  freeHitItr = std::find_if(freeHitItr, hitPairList.end(), [](const auto& hit) {
397  return !(hit->getStatusBits() & reco::ClusterHit3D::CLUSTERATTACHED);
398  });
399 
400  // If at end of input list we are done with all hits
401  if (freeHitItr == hitPairList.end()) break;
402 
403  std::cout << "##################################################################>"
404  "Processing another cluster"
405  << std::endl;
406 
407  // Otherwise, get a new cluster and set up
408  clusterParametersList.push_back(reco::ClusterParameters());
409 
410  curCluster = &clusterParametersList.back();
411 
412  curEdgeMap = &curCluster->getHit3DToEdgeMap();
413  curClusterHitList = &curCluster->getHitPairListPtr();
414  lastAddedHit = *freeHitItr++;
415  }
416  // Otherwise we are still processing the current cluster
417  else {
418  // Sort the list of edges by distance
419  curEdgeList.sort([](const auto& left, const auto& right) {
420  return std::get<2>(left) < std::get<2>(right);
421  });
422 
423  // Populate the map with the edges...
424  reco::EdgeTuple& curEdge = curEdgeList.front();
425 
426  (*curEdgeMap)[std::get<0>(curEdge)].push_back(curEdge);
427  (*curEdgeMap)[std::get<1>(curEdge)].push_back(
428  reco::EdgeTuple(std::get<1>(curEdge), std::get<0>(curEdge), std::get<2>(curEdge)));
429 
430  // Update the last hit to be added to the collection
431  lastAddedHit = std::get<1>(curEdge);
432  }
433  }
434 
435  if (fEnableMonitoring) {
436  theClockDBScan.stop();
437 
438  fTimeVector[RUNDBSCAN] = theClockDBScan.accumulated_real_time();
439  }
440 
441  return;
442  }
walls no right
Definition: selectors.fcl:105
size_t FindNearestNeighbors(const reco::ClusterHit3D *, const KdTreeNode &, CandPairList &, float &) const
Definition: kdTree.cxx:170
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
Definition: Cluster3D.h:478
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:475
process_name hit
Definition: cheaterreco.fcl:51
std::list< EdgeTuple > EdgeList
Definition: Cluster3D.h:344
std::tuple< const reco::ClusterHit3D *, const reco::ClusterHit3D *, double > EdgeTuple
Definition: Cluster3D.h:343
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:334
walls no left
Definition: selectors.fcl:105
std::list< CandPair > CandPairList
Definition: kdTree.h:79
bool fEnableMonitoring
Data members to follow.
std::vector< float > fTimeVector
float getHitChiSquare() const
Definition: Cluster3D.h:165
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:346
BEGIN_PROLOG could also be cout
attached to a cluster
Definition: Cluster3D.h:108
void setStatusBit(unsigned bits) const
Definition: Cluster3D.h:179

Member Data Documentation

std::unique_ptr<lar_cluster3d::IClusterParametersBuilder> lar_cluster3d::MSTPathFinder::fClusterBuilder
private

Common cluster builder tool.

Definition at line 188 of file MSTPathFinder_tool.cc.

float lar_cluster3d::MSTPathFinder::fConvexHullKinkAngle
private

Angle to declare a kink in convex hull calc.

Definition at line 177 of file MSTPathFinder_tool.cc.

float lar_cluster3d::MSTPathFinder::fConvexHullMinSep
private

Min hit separation to conisder in convex hull.

Definition at line 178 of file MSTPathFinder_tool.cc.

bool lar_cluster3d::MSTPathFinder::fEnableMonitoring
private

Data members to follow.

Definition at line 175 of file MSTPathFinder_tool.cc.

geo::Geometry const* lar_cluster3d::MSTPathFinder::fGeometry
private

Definition at line 182 of file MSTPathFinder_tool.cc.

kdTree lar_cluster3d::MSTPathFinder::fkdTree
private

Definition at line 185 of file MSTPathFinder_tool.cc.

size_t lar_cluster3d::MSTPathFinder::fMinTinyClusterSize
private

Minimum size for a "tiny" cluster.

Definition at line 176 of file MSTPathFinder_tool.cc.

PrincipalComponentsAlg lar_cluster3d::MSTPathFinder::fPCAAlg
private

Definition at line 184 of file MSTPathFinder_tool.cc.

std::vector<float> lar_cluster3d::MSTPathFinder::fTimeVector
mutableprivate

Definition at line 180 of file MSTPathFinder_tool.cc.


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