LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
lar_cluster3d::MinSpanTreeAlg Class Referenceabstract
Inheritance diagram for lar_cluster3d::MinSpanTreeAlg:
lar_cluster3d::IClusterAlg

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

Public Member Functions

 MinSpanTreeAlg (const fhicl::ParameterSet &)
 Constructor. More...
 
 ~MinSpanTreeAlg ()
 Destructor. More...
 
void configure (fhicl::ParameterSet const &pset) override
 
void Cluster3DHits (reco::HitPairList &hitPairList, reco::ClusterParametersList &clusterParametersList) const override
 Given a set of recob hits, run DBscan to form 3D clusters. More...
 
void Cluster3DHits (reco::HitPairListPtr &hitPairList, reco::ClusterParametersList &clusterParametersList) const override
 Given a set of recob hits, run DBscan to form 3D clusters. More...
 
float getTimeToExecute (TimeValues index) const override
 If monitoring, recover the time to execute a particular function. More...
 
virtual void configure (const fhicl::ParameterSet &)=0
 Interface for configuring the particular algorithm tool. More...
 

Private Types

using BestNodeTuple = std::tuple< const reco::ClusterHit3D *, float, float >
 
using BestNodeMap = std::unordered_map< const reco::ClusterHit3D *, BestNodeTuple >
 
using ChannelStatusVec = std::vector< size_t >
 define data structure for keeping track of channel status More...
 
using ChannelStatusByPlaneVec = std::vector< ChannelStatusVec >
 

Private Member Functions

void RunPrimsAlgorithm (reco::HitPairList &, 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::HitPairListPtr &, reco::EdgeList &) 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 *, const reco::Hit3DToEdgeMap &, reco::HitPairListPtr &, reco::EdgeList &, float &) const
 Find the lowest cost path between two nodes using MST edges. More...
 
void CheckHitSorting (reco::ClusterParameters &clusterParams) const
 

Private Attributes

bool m_enableMonitoring
 Data members to follow. More...
 
std::vector< float > m_timeVector
 
std::vector< std::vector< float > > m_wireDir
 
geo::Geometrym_geometry
 
ClusterParamsBuilder m_clusterBuilder
 
PrincipalComponentsAlg m_pcaAlg
 
kdTree m_kdTree
 

Detailed Description

Definition at line 42 of file MinSpanTreeAlg_tool.cc.

Member Typedef Documentation

Definition at line 110 of file MinSpanTreeAlg_tool.cc.

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

Definition at line 109 of file MinSpanTreeAlg_tool.cc.

using lar_cluster3d::MinSpanTreeAlg::ChannelStatusVec = std::vector<size_t>
private

define data structure for keeping track of channel status

Definition at line 131 of file MinSpanTreeAlg_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 61 of file IClusterAlg.h.

Constructor & Destructor Documentation

lar_cluster3d::MinSpanTreeAlg::MinSpanTreeAlg ( const fhicl::ParameterSet )
explicit

Constructor.

Parameters
pset

Definition at line 148 of file MinSpanTreeAlg_tool.cc.

References configure().

148  :
149  m_clusterBuilder(pset.get<fhicl::ParameterSet>("ClusterParamsBuilder")),
150  m_pcaAlg(pset.get<fhicl::ParameterSet>("PrincipalComponentsAlg")),
151  m_kdTree(pset.get<fhicl::ParameterSet>("kdTree"))
152 {
153  this->configure(pset);
154 }
void configure(fhicl::ParameterSet const &pset) override
ClusterParamsBuilder m_clusterBuilder
lar_cluster3d::MinSpanTreeAlg::~MinSpanTreeAlg ( )

Destructor.

Definition at line 158 of file MinSpanTreeAlg_tool.cc.

159 {
160 }

Member Function Documentation

void lar_cluster3d::MinSpanTreeAlg::AStar ( const reco::ClusterHit3D startNode,
const reco::ClusterHit3D goalNode,
float  alpha,
kdTree::KdTreeNode topNode,
reco::HitPairListPtr pathNodeList,
reco::EdgeList bestEdgeList 
) const
private

Algorithm to find shortest path between two 3D hits.

Definition at line 545 of file MinSpanTreeAlg_tool.cc.

References DistanceBetweenNodes(), lar_cluster3d::kdTree::FindNearestNeighbors(), reco::ClusterHit3D::getPosition(), m_kdTree, max, reco::ClusterHit3D::PATHCHECKED, ReconstructBestPath(), and reco::ClusterHit3D::setStatusBit().

Referenced by FindBestPathInCluster(), and getTimeToExecute().

551 {
552  // Find the shortest path from start to goal using an A* algorithm
553  // Keep track of the nodes which have already been evaluated
554  reco::HitPairListPtr closedList;
555 
556  // Keep track of the nodes that have been "discovered" but yet to be evaluated
557  reco::HitPairListPtr openList = {startNode};
558 
559  // Create a map which, for each node, will tell us the node it can be most efficiencly reached from.
560  BestNodeMap bestNodeMap;
561 
562  bestNodeMap[startNode] = BestNodeTuple(startNode,0.,DistanceBetweenNodes(startNode,goalNode));
563 
564  alpha = 1.; //std::max(0.5,alpha);
565 
566  while(!openList.empty())
567  {
568  // The list is not empty so by def we will return something
569  reco::HitPairListPtr::iterator currentNodeItr = openList.begin();
570 
571  // If the list contains more than one element then we need to find the one with the smallest total estimated cost to the end
572  if (openList.size() > 1)
573  currentNodeItr = std::min_element(openList.begin(),openList.end(),[bestNodeMap](const auto& next, const auto& best){return std::get<2>(bestNodeMap.at(next)) < std::get<2>(bestNodeMap.at(best));});
574 
575  // Easier to deal directly with the pointer to the node
576  const reco::ClusterHit3D* currentNode = *currentNodeItr;
577 
578  // Check to see if we have reached the goal and need to evaluate the path
579  if (currentNode == goalNode)
580  {
581  // The path reconstruction will
582  ReconstructBestPath(goalNode, bestNodeMap, pathNodeList, bestEdgeList);
583 
584 // std::cout << "**> Reconstructed best path... ended with " << openList.size() << " hits in openList" << std::endl;
585 
586  break;
587  }
588 
589  // Otherwise need to keep evaluating
590  else
591  {
592  openList.erase(currentNodeItr);
593 // closedList.push_front(currentNode);
595 
596  // Set up to find the list of nearest neighbors to the last used hit...
597  kdTree::CandPairList CandPairList;
598  float bestDistance(std::numeric_limits<float>::max());
599 
600  // And find them... result will be an unordered list of neigbors
601  m_kdTree.FindNearestNeighbors(currentNode, topNode, CandPairList, bestDistance);
602 
603 // std::cout << "**> found " << CandPairList.size() << " nearest neigbhors, bestDistance: " << bestDistance;
604 // size_t nAdded(0);
605 
606  // Get tuple values for the current node
607  const BestNodeTuple& currentNodeTuple = bestNodeMap.at(currentNode);
608  float currentNodeScore = std::get<1>(currentNodeTuple);
609 
610  for(auto& candPair : CandPairList)
611  {
612  // Ignore those nodes we're already aware of
613  //if (std::find(closedList.begin(),closedList.end(),candPair.second) != closedList.end()) continue;
614  if (candPair.second->getStatusBits() & reco::ClusterHit3D::PATHCHECKED) continue;
615 
616  float tentative_gScore = currentNodeScore + candPair.first;
617 
618  // Have we seen the candidate node before?
619  BestNodeMap::iterator candNodeItr = bestNodeMap.find(candPair.second);
620 
621  if (candNodeItr == bestNodeMap.end())
622  {
623  openList.push_back(candPair.second);
624 // nAdded++;
625  }
626  else if (tentative_gScore > std::get<1>(candNodeItr->second)) continue;
627 
628  // Experiment with modification to cost estimate
629  const float* currentNodePos = currentNode->getPosition();
630  const float* nextNodePos = candPair.second->getPosition();
631  float curNextDelta[] = {nextNodePos[0]-currentNodePos[0], nextNodePos[1]-currentNodePos[1], nextNodePos[2]-currentNodePos[2]};
632 
633  const float* goalNodePos = goalNode->getPosition();
634  float goalNextDelta[] = {goalNodePos[0]-nextNodePos[0], goalNodePos[1]-nextNodePos[1], goalNodePos[2]-nextNodePos[2]};
635 
636  float curNextMag = std::sqrt(curNextDelta[0]*curNextDelta[0] + curNextDelta[1]*curNextDelta[1] + curNextDelta[2]*curNextDelta[2]);
637  float goalNextMag = std::sqrt(goalNextDelta[0]*goalNextDelta[0] + goalNextDelta[1]*goalNextDelta[1] + goalNextDelta[2]*goalNextDelta[2]);
638 
639  float cosTheta = (curNextDelta[0]*goalNextDelta[0] + curNextDelta[1]*goalNextDelta[1] + curNextDelta[2]*goalNextDelta[2]);
640 
641  if (cosTheta > 0. || cosTheta < 0.) cosTheta /= (curNextMag * goalNextMag);
642 
643 // alpha = candPair.second->getMinOverlapFraction();
644  cosTheta = 1.;
645 
646  float hWeight = alpha*goalNextMag/std::max(0.01,0.5*(1.+cosTheta));
647 
648  // update our records
649  bestNodeMap[candPair.second] = BestNodeTuple(currentNode,tentative_gScore, tentative_gScore + hWeight);
650  //bestNodeMap[candPair.second] = BestNodeTuple(currentNode, tentative_gScore, tentative_gScore + alpha*DistanceBetweenNodes(candPair.second,goalNode));
651  }
652 
653 // std::cout << ", added: " << nAdded << ", openList size: " << openList.size() << std::endl;
654  }
655  }
656 
657  return;
658 }
std::tuple< const reco::ClusterHit3D *, float, float > BestNodeTuple
intermediate_table::iterator iterator
size_t FindNearestNeighbors(const reco::ClusterHit3D *, const KdTreeNode &, CandPairList &, float &) const
Definition: kdTree.cxx:178
float DistanceBetweenNodes(const reco::ClusterHit3D *, const reco::ClusterHit3D *) const
Int_t max
Definition: plot.C:27
std::unordered_map< const reco::ClusterHit3D *, BestNodeTuple > BestNodeMap
Path checking algorithm has seen this hit.
Definition: Cluster3D.h:102
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:315
const float * getPosition() const
Definition: Cluster3D.h:145
std::list< CandPair > CandPairList
Definition: kdTree.h:70
void ReconstructBestPath(const reco::ClusterHit3D *, BestNodeMap &, reco::HitPairListPtr &, reco::EdgeList &) const
void setStatusBit(unsigned bits) const
Definition: Cluster3D.h:163
void lar_cluster3d::MinSpanTreeAlg::CheckHitSorting ( reco::ClusterParameters clusterParams) const
private

Definition at line 937 of file MinSpanTreeAlg_tool.cc.

References DEFINE_ART_CLASS_TOOL, reco::PrincipalComponents::getEigenVectors(), reco::ClusterParameters::getHitPairListPtr(), reco::ClusterHit3D::getHits(), reco::PrincipalComponents::getSvdOK(), reco::ClusterHit3D::getWireIDs(), m_pcaAlg, m_wireDir, and lar_cluster3d::PrincipalComponentsAlg::PCAAnalysis_3D().

938 {
939  reco::HitPairListPtr& curCluster = clusterParams.getHitPairListPtr();
940 
941  // Trial A* here
942  if (curCluster.size() > 2)
943  {
944  // Do a quick PCA to determine our parameter "alpha"
946  m_pcaAlg.PCAAnalysis_3D(curCluster, pca);
947 
948  if (pca.getSvdOK())
949  {
950  const std::vector<float>& pcaAxis = pca.getEigenVectors()[0];
951 
952  std::vector<size_t> closestPlane = {0, 0, 0 };
953  std::vector<float> bestAngle = {0.,0.,0.};
954 
955  for(size_t plane = 0; plane < 3; plane++)
956  {
957  const std::vector<float>& wireDir = m_wireDir[plane];
958 
959  float dotProd = std::fabs(pcaAxis[0]*wireDir[0] + pcaAxis[1]*wireDir[1] + pcaAxis[2]*wireDir[2]);
960 
961  if (dotProd > bestAngle[0])
962  {
963  bestAngle[2] = bestAngle[1];
964  closestPlane[2] = closestPlane[1];
965  bestAngle[1] = bestAngle[0];
966  closestPlane[1] = closestPlane[0];
967  closestPlane[0] = plane;
968  bestAngle[0] = dotProd;
969  }
970  else if (dotProd > bestAngle[1])
971  {
972  bestAngle[2] = bestAngle[1];
973  closestPlane[2] = closestPlane[1];
974  closestPlane[1] = plane;
975  bestAngle[1] = dotProd;
976  }
977  else
978  {
979  closestPlane[2] = plane;
980  bestAngle[2] = dotProd;
981  }
982  }
983 
984  // Get a copy of our 3D hits
985  reco::HitPairListPtr localHitList = curCluster;
986 
987  // Sort the hits
988  localHitList.sort(SetCheckHitOrder(closestPlane));
989 
990  // Ok, let's print it all and take a look
991  std::cout << "********************************************************************************************" << std::endl;
992  std::cout << "**>>>>> longest axis: " << closestPlane[0] << ", best angle: " << bestAngle[0] << std::endl;
993  std::cout << "**>>>>> second axis: " << closestPlane[1] << ", best angle: " << bestAngle[1] << std::endl;
994  std::cout << " " << std::endl;
995 
996  reco::HitPairListPtr::iterator firstHitItr = localHitList.begin();
997  reco::HitPairListPtr::iterator lastHitItr = localHitList.begin();
998 
999  size_t bestPlane = closestPlane[0];
1000 
1001  reco::HitPairListPtr testList;
1002 
1003  while(firstHitItr != localHitList.end())
1004  {
1005  const reco::ClusterHit3D* currentHit = *firstHitItr;
1006 
1007  // Search for the last matching best view hit
1008  while(lastHitItr != localHitList.end())
1009  {
1010  // If a different wire on the best view then we're certainly done
1011  if (currentHit->getWireIDs()[bestPlane] != (*lastHitItr)->getWireIDs()[bestPlane]) break;
1012 
1013  // More subtle test to see if same wire but different hit (being careful of case of no hit)
1014  if (currentHit->getHits()[bestPlane] && (*lastHitItr)->getHits()[bestPlane] && currentHit->getHits()[bestPlane] != (*lastHitItr)->getHits()[bestPlane]) break;
1015 
1016  // Yet event more subtle test...
1017  if ((!(currentHit->getHits()[bestPlane]) && (*lastHitItr)->getHits()[bestPlane]) || (currentHit->getHits()[bestPlane] && !((*lastHitItr)->getHits()[bestPlane]))) break;
1018 
1019  // Not there yet...
1020  lastHitItr++;
1021  }
1022 
1023  // How many hits in this chain?
1024 // size_t numHits(std::distance(firstHitItr,lastHitItr));
1025 // float minOverlapFraction(0.);
1026 
1027 // if (numHits > 1)
1028 // {
1029 // reco::HitPairListPtr::iterator bestMinOverlapItr = std::max_element(firstHitItr,lastHitItr,[](const auto& left, const auto& right){return left->getMinOverlapFraction() < right->getMinOverlapFraction();});
1030 //
1031 // minOverlapFraction = std::min(0.999*(*bestMinOverlapItr)->getMinOverlapFraction(),0.90);
1032 // }
1033 
1034  while(firstHitItr != lastHitItr)
1035  {
1036 // if (currentHit->getMinOverlapFraction() > minOverlapFraction) testList.push_back(currentHit); //currentHit->setStatusBit(reco::ClusterHit3D::SKELETONHIT);
1037 
1038  currentHit = *++firstHitItr;
1039  }
1040 
1041  firstHitItr = lastHitItr;
1042  }
1043 /*
1044  for(const auto& hit : localHitList)
1045  {
1046  std::cout << "- wires: ";
1047 
1048  for(size_t idx = 0; idx < 3; idx++)
1049  {
1050  float viewTime = -1.;
1051 
1052  if (hit->getHits()[closestView[idx]]) viewTime = hit->getHits()[closestView[idx]]->getTimeTicks();
1053 
1054  std::cout << closestView[idx] << ":" << hit->getWireIDs()[closestView[idx]].Wire << " - " << viewTime << ", ";
1055  }
1056 
1057  bool isSkeleton = hit->getStatusBits() & reco::ClusterHit3D::SKELETONHIT;
1058 
1059  std::cout << "ave time: " << hit->getAvePeakTime() << ", min/max overlap: " << hit->getMinOverlapFraction() << "/" << hit->getMaxOverlapFraction() << ", tagged: " << isSkeleton << std::endl;
1060 
1061  if (isSkeleton) testList.push_back(hit);
1062  }
1063 */
1064  curCluster = testList;
1065  }
1066  }
1067 
1068  return;
1069 }
bool getSvdOK() const
Definition: Cluster3D.h:224
std::vector< std::vector< float > > m_wireDir
void PCAAnalysis_3D(const reco::HitPairListPtr &hitPairList, reco::PrincipalComponents &pca, bool skeletonOnly=false) const
intermediate_table::iterator iterator
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:404
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:315
const std::vector< geo::WireID > & getWireIDs() const
Definition: Cluster3D.h:158
const ClusterHit2DVec & getHits() const
Definition: Cluster3D.h:156
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:227
void lar_cluster3d::MinSpanTreeAlg::Cluster3DHits ( reco::HitPairList hitPairList,
reco::ClusterParametersList clusterParametersList 
) const
overridevirtual

Given a set of recob hits, run DBscan to form 3D clusters.

Parameters
hitPairListThe input list of 3D hits to run clustering on
hitPairClusterMapA map of hits that have been clustered
clusterParametersListA list of cluster objects (parameters from associated hits)

Driver for processing input 2D hits, transforming to 3D hits and building lists of associated 3D hits (candidate 3D clusters)

Implements lar_cluster3d::IClusterAlg.

Definition at line 207 of file MinSpanTreeAlg_tool.cc.

References lar_cluster3d::ClusterParamsBuilder::BuildClusterInfo(), lar_cluster3d::IClusterAlg::BUILDCLUSTERINFO, lar_cluster3d::IClusterAlg::BUILDHITTOHITMAP, lar_cluster3d::kdTree::BuildKdTree(), trkf::fill(), FindBestPathInCluster(), lar_cluster3d::kdTree::getTimeToExecute(), m_clusterBuilder, m_enableMonitoring, m_kdTree, m_timeVector, and RunPrimsAlgorithm().

209 {
215  // Zero the time vector
216  if (m_enableMonitoring) std::fill(m_timeVector.begin(),m_timeVector.end(),0.);
217 
218  // DBScan is driven of its "epsilon neighborhood". Computing adjacency within DBScan can be time
219  // consuming so the idea is the prebuild the adjaceny map and then run DBScan.
220  // The following call does this work
221  kdTree::KdTreeNodeList kdTreeNodeContainer;
222  kdTree::KdTreeNode topNode = m_kdTree.BuildKdTree(hitPairList, kdTreeNodeContainer);
223 
225 
226  // Run DBScan to get candidate clusters
227  RunPrimsAlgorithm(hitPairList, topNode, clusterParametersList);
228 
229  // Initial clustering is done, now trim the list and get output parameters
230  cet::cpu_timer theClockBuildClusters;
231 
232  // Start clocks if requested
233  if (m_enableMonitoring) theClockBuildClusters.start();
234 
235  m_clusterBuilder.BuildClusterInfo(clusterParametersList);
236 
237  if (m_enableMonitoring)
238  {
239  theClockBuildClusters.stop();
240 
241  m_timeVector[BUILDCLUSTERINFO] = theClockBuildClusters.accumulated_real_time();
242  }
243 
244  // Test run the path finding algorithm
245  for (auto& clusterParams : clusterParametersList) FindBestPathInCluster(clusterParams, topNode);
246 
247  mf::LogDebug("Cluster3D") << ">>>>> Cluster3DHits done, found " << clusterParametersList.size() << " clusters" << std::endl;
248 
249  return;
250 }
ClusterParamsBuilder m_clusterBuilder
bool m_enableMonitoring
Data members to follow.
std::list< KdTreeNode > KdTreeNodeList
Definition: kdTree.h:58
void BuildClusterInfo(reco::ClusterParametersList &clusterParametersList) const
Given the results of running DBScan, format the clusters so that they can be easily transferred back ...
void RunPrimsAlgorithm(reco::HitPairList &, kdTree::KdTreeNode &, reco::ClusterParametersList &) const
Driver for Prim&#39;s algorithm.
void fill(const art::PtrVector< recob::Hit > &hits, int only_plane)
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
float getTimeToExecute() const
Definition: kdTree.h:86
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:120
void FindBestPathInCluster(reco::ClusterParameters &) const
Algorithm to find the best path through the given cluster.
void lar_cluster3d::MinSpanTreeAlg::Cluster3DHits ( reco::HitPairListPtr hitPairList,
reco::ClusterParametersList clusterParametersList 
) const
inlineoverridevirtual

Given a set of recob hits, run DBscan to form 3D clusters.

Parameters
hitPairListPtrThe input list of 3D hits to run clustering on
clusterParametersListA list of cluster objects (parameters from associated hits)

Implements lar_cluster3d::IClusterAlg.

Definition at line 69 of file MinSpanTreeAlg_tool.cc.

70  {return;}
virtual void lar_cluster3d::IClusterAlg::configure ( const fhicl::ParameterSet )
pure virtualinherited

Interface for configuring the particular algorithm tool.

Parameters
ParameterSetThe input set of parameters for configuration

Implemented in lar_cluster3d::DBScanAlg.

void lar_cluster3d::MinSpanTreeAlg::configure ( fhicl::ParameterSet const &  pset)
override

Definition at line 164 of file MinSpanTreeAlg_tool.cc.

References geo::GeometryCore::ChannelToWire(), geo::WireGeo::Direction(), fhicl::ParameterSet::get(), m_enableMonitoring, m_geometry, m_timeVector, m_wireDir, lar_cluster3d::IClusterAlg::NUMTIMEVALUES, and geo::GeometryCore::WirePtr().

Referenced by MinSpanTreeAlg().

165 {
166  m_enableMonitoring = pset.get<bool> ("EnableMonitoring", true );
167 
169 
170  m_geometry = &*geometry;
171 
172  m_timeVector.resize(NUMTIMEVALUES, 0.);
173 
174  // Determine the unit directon and normal vectors to the wires
175  m_wireDir.resize(3);
176 
177  raw::ChannelID_t uChannel(0);
178  std::vector<geo::WireID> uWireID = m_geometry->ChannelToWire(uChannel);
179  const geo::WireGeo* uWireGeo = m_geometry->WirePtr(uWireID[0]);
180 
181  TVector3 uWireDir = uWireGeo->Direction();
182 
183  m_wireDir[0].resize(3);
184  m_wireDir[0][0] = uWireDir[0];
185  m_wireDir[0][1] = -uWireDir[2];
186  m_wireDir[0][2] = uWireDir[1];
187 
188  raw::ChannelID_t vChannel(2400);
189  std::vector<geo::WireID> vWireID = m_geometry->ChannelToWire(vChannel);
190  const geo::WireGeo* vWireGeo = m_geometry->WirePtr(vWireID[0]);
191 
192  TVector3 vWireDir = vWireGeo->Direction();
193 
194  m_wireDir[1].resize(3);
195  m_wireDir[1][0] = vWireDir[0];
196  m_wireDir[1][1] = -vWireDir[2];
197  m_wireDir[1][2] = vWireDir[1];
198 
199  m_wireDir[2].resize(3);
200  m_wireDir[2][0] = 0.;
201  m_wireDir[2][1] = 0.;
202  m_wireDir[2][2] = 1.;
203 
204  return;
205 }
Geometry description of a TPC wireThe wire is a single straight segment on a wire plane...
Definition: WireGeo.h:61
std::vector< std::vector< float > > m_wireDir
bool m_enableMonitoring
Data members to follow.
std::vector< geo::WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
Vector Direction() const
Returns the wire direction as a norm-one vector.
Definition: WireGeo.h:377
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:27
WireGeo const * WirePtr(geo::WireID const &wireid) const
Returns the specified wire.
reco::HitPairListPtr lar_cluster3d::MinSpanTreeAlg::DepthFirstSearch ( const reco::EdgeTuple curEdge,
const reco::Hit3DToEdgeMap hitToEdgeMap,
float &  bestTreeQuality 
) const
private

a depth first search to find longest branches

Definition at line 758 of file MinSpanTreeAlg_tool.cc.

References max.

Referenced by FindBestPathInCluster(), and getTimeToExecute().

761 {
762  reco::HitPairListPtr hitPairListPtr;
763  float bestQuality(0.);
764  float curEdgeWeight = std::max(0.3,std::get<2>(curEdge));
765  float curEdgeProj(1./curEdgeWeight);
766 
767  reco::Hit3DToEdgeMap::const_iterator edgeListItr = hitToEdgeMap.find(std::get<1>(curEdge));
768 
769  if (edgeListItr != hitToEdgeMap.end())
770  {
771  // The input edge weight has quality factors applied, recalculate just the position difference
772  const float* firstHitPos = std::get<0>(curEdge)->getPosition();
773  const float* secondHitPos = std::get<1>(curEdge)->getPosition();
774  float curEdgeVec[] = {secondHitPos[0]-firstHitPos[0],secondHitPos[1]-firstHitPos[1],secondHitPos[2]-firstHitPos[2]};
775  float curEdgeMag = std::sqrt(curEdgeVec[0]*curEdgeVec[0]+curEdgeVec[1]*curEdgeVec[1]+curEdgeVec[2]*curEdgeVec[2]);
776 
777  curEdgeMag = std::max(float(0.1),curEdgeMag);
778 
779  for(const auto& edge : edgeListItr->second)
780  {
781  // skip the self reference
782  if (std::get<1>(edge) == std::get<0>(curEdge)) continue;
783 
784  float quality(0.);
785 
786  reco::HitPairListPtr tempList = DepthFirstSearch(edge,hitToEdgeMap,quality);
787 
788  if (quality > bestQuality)
789  {
790  hitPairListPtr = tempList;
791  bestQuality = quality;
792  curEdgeProj = 1./curEdgeMag;
793  }
794  }
795  }
796 
797  hitPairListPtr.push_front(std::get<1>(curEdge));
798 
799  bestTreeQuality += bestQuality + curEdgeProj;
800 
801  return hitPairListPtr;
802 }
Int_t max
Definition: plot.C:27
intermediate_table::const_iterator const_iterator
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:315
reco::HitPairListPtr DepthFirstSearch(const reco::EdgeTuple &, const reco::Hit3DToEdgeMap &, float &) const
a depth first search to find longest branches
float lar_cluster3d::MinSpanTreeAlg::DistanceBetweenNodes ( const reco::ClusterHit3D node1,
const reco::ClusterHit3D node2 
) const
private

Definition at line 730 of file MinSpanTreeAlg_tool.cc.

References reco::ClusterHit3D::getPosition().

Referenced by AStar(), FindBestPathInCluster(), and ReconstructBestPath().

731 {
732  const float* node1Pos = node1->getPosition();
733  const float* node2Pos = node2->getPosition();
734  float deltaNode[] = {node1Pos[0]-node2Pos[0], node1Pos[1]-node2Pos[1], node1Pos[2]-node2Pos[2]};
735 
736  // Standard euclidean distance
737  return std::sqrt(deltaNode[0]*deltaNode[0]+deltaNode[1]*deltaNode[1]+deltaNode[2]*deltaNode[2]);
738 
739  // Manhatten distance
740  //return std::fabs(deltaNode[0]) + std::fabs(deltaNode[1]) + std::fabs(deltaNode[2]);
741 /*
742  // Chebyshev distance
743  // We look for maximum distance by wires...
744 
745  // Now go through the hits and compare view by view to look for delta wire and tigher constraint on delta t
746  int wireDeltas[] = {0,0,0};
747 
748  for(size_t idx = 0; idx < 3; idx++)
749  wireDeltas[idx] = std::abs(int(node1->getWireIDs()[idx].Wire) - int(node2->getWireIDs()[idx].Wire));
750 
751  // put wire deltas in order...
752  std::sort(wireDeltas, wireDeltas + 3);
753 
754  return std::sqrt(deltaNode[0]*deltaNode[0] + 0.09 * float(wireDeltas[2]*wireDeltas[2]));
755  */
756 }
const float * getPosition() const
Definition: Cluster3D.h:145
void lar_cluster3d::MinSpanTreeAlg::FindBestPathInCluster ( reco::ClusterParameters curCluster) const
private

Algorithm to find the best path through the given cluster.

Definition at line 366 of file MinSpanTreeAlg_tool.cc.

References DepthFirstSearch(), reco::ClusterParameters::getBestEdgeList(), reco::ClusterParameters::getHit3DToEdgeMap(), reco::ClusterParameters::getHitPairListPtr(), m_enableMonitoring, m_timeVector, max, and lar_cluster3d::IClusterAlg::PATHFINDING.

Referenced by Cluster3DHits(), and getTimeToExecute().

367 {
368  reco::HitPairListPtr longestCluster;
369  float bestQuality(0.);
370  float aveNumEdges(0.);
371  size_t maxNumEdges(0);
372  size_t nIsolatedHits(0);
373 
374  // Now proceed with building the clusters
375  cet::cpu_timer theClockPathFinding;
376 
377  // Start clocks if requested
378  if (m_enableMonitoring) theClockPathFinding.start();
379 
380  reco::HitPairListPtr& hitPairList = curCluster.getHitPairListPtr();
381  reco::Hit3DToEdgeMap& curEdgeMap = curCluster.getHit3DToEdgeMap();
382  reco::EdgeList& bestEdgeList = curCluster.getBestEdgeList();
383 
384  // Do some spelunking...
385  for(const auto& hit : hitPairList)
386  {
387  if (!curEdgeMap[hit].empty() && curEdgeMap[hit].size() == 1)
388  {
389  float quality(0.);
390 
391  reco::HitPairListPtr tempList = DepthFirstSearch(curEdgeMap[hit].front(), curEdgeMap, quality);
392 
393  tempList.push_front(std::get<0>(curEdgeMap[hit].front()));
394 
395  if (quality > bestQuality)
396  {
397  longestCluster = tempList;
398  bestQuality = quality;
399  }
400 
401  nIsolatedHits++;
402  }
403 
404  aveNumEdges += float(curEdgeMap[hit].size());
405  maxNumEdges = std::max(maxNumEdges,curEdgeMap[hit].size());
406  }
407 
408  aveNumEdges /= float(hitPairList.size());
409  std::cout << "----> # isolated hits: " << nIsolatedHits << ", longest branch: " << longestCluster.size() << ", cluster size: " << hitPairList.size() << ", ave # edges: " << aveNumEdges << ", max: " << maxNumEdges << std::endl;
410 
411  if (!longestCluster.empty())
412  {
413  hitPairList = longestCluster;
414  for(const auto& hit : hitPairList)
415  {
416  for(const auto& edge : curEdgeMap[hit]) bestEdgeList.emplace_back(edge);
417  }
418 
419  std::cout << " ====> new cluster size: " << hitPairList.size() << std::endl;
420  }
421 
422  if (m_enableMonitoring)
423  {
424  theClockPathFinding.stop();
425 
426  m_timeVector[PATHFINDING] += theClockPathFinding.accumulated_real_time();
427  }
428 
429  return;
430 }
bool m_enableMonitoring
Data members to follow.
reco::EdgeList & getBestEdgeList()
Definition: Cluster3D.h:409
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
Definition: Cluster3D.h:407
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:404
std::list< EdgeTuple > EdgeList
Definition: Cluster3D.h:324
Int_t max
Definition: plot.C:27
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:315
Detector simulation of raw signals on wires.
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:326
reco::HitPairListPtr DepthFirstSearch(const reco::EdgeTuple &, const reco::Hit3DToEdgeMap &, float &) const
a depth first search to find longest branches
void lar_cluster3d::MinSpanTreeAlg::FindBestPathInCluster ( reco::ClusterParameters clusterParams,
kdTree::KdTreeNode topNode 
) const
private

Alternative version of FindBestPathInCluster utilizing an A* algorithm.

Definition at line 432 of file MinSpanTreeAlg_tool.cc.

References AStar(), DistanceBetweenNodes(), reco::PrincipalComponents::getAvePosition(), reco::ClusterParameters::getBestEdgeList(), reco::ClusterParameters::getBestHitPairListPtr(), reco::PrincipalComponents::getEigenValues(), reco::PrincipalComponents::getEigenVectors(), reco::ClusterParameters::getHit3DToEdgeMap(), reco::ClusterParameters::getHitPairListPtr(), reco::ClusterHit3D::getPosition(), reco::PrincipalComponents::getSvdOK(), art::left(), m_enableMonitoring, m_pcaAlg, m_timeVector, max, min, lar_cluster3d::IClusterAlg::PATHFINDING, lar_cluster3d::PrincipalComponentsAlg::PCAAnalysis_3D(), and art::right().

433 {
434  // Set up for timing the function
435  cet::cpu_timer theClockPathFinding;
436 
437  // Start clocks if requested
438  if (m_enableMonitoring) theClockPathFinding.start();
439 
440  reco::HitPairListPtr& curCluster = clusterParams.getHitPairListPtr();
441  reco::Hit3DToEdgeMap& curEdgeMap = clusterParams.getHit3DToEdgeMap();
442 
443  // Trial A* here
444  if (curCluster.size() > 2)
445  {
446  // Do a quick PCA to determine our parameter "alpha"
448  m_pcaAlg.PCAAnalysis_3D(curCluster, pca);
449 
450  if (pca.getSvdOK())
451  {
452  const std::vector<float>& pcaAxis = pca.getEigenVectors()[0];
453  float pcaLen = 1.5*sqrt(pca.getEigenValues()[0]);
454  float pcaWidth = 1.5*sqrt(pca.getEigenValues()[1]);
455  float pcaHeight = 1.5*sqrt(pca.getEigenValues()[2]);
456  const float* pcaPos = pca.getAvePosition();
457  float alpha = std::min(float(1.),std::max(float(0.001),pcaWidth/pcaLen));
458 
459  // The first task is to find the list of hits which are "isolated"
460  reco::HitPairListPtr isolatedHitList;
461  for(const auto& hit : curCluster)
462  if (!curEdgeMap[hit].empty() && curEdgeMap[hit].size() == 1)
463  isolatedHitList.emplace_back(std::get<0>(curEdgeMap[hit].front()));
464 
465  std::cout << "************* Finding best path with A* in cluster *****************" << std::endl;
466  std::cout << "**> There are " << curCluster.size() << " hits, " << isolatedHitList.size() << " isolated hits, the alpha parameter is " << alpha << std::endl;
467  std::cout << "**> PCA len: " << pcaLen << ", wid: " << pcaWidth << ", height: " << pcaHeight << ", ratio: " << pcaHeight/pcaWidth << std::endl;
468 
469  // Goal is to now find separated pairs of isolated hits
470  reco::EdgeList edgeList;
471  reco::HitPairListPtr::iterator firstItr = isolatedHitList.begin();
472  while(firstItr != isolatedHitList.end())
473  {
474  const reco::ClusterHit3D* firstHit = *firstItr++;
475 
476  const float* firstPos = firstHit->getPosition();
477  float delta1stPca[] = {firstPos[0]-pcaPos[0],firstPos[1]-pcaPos[1],firstPos[2]-pcaPos[2]};
478  float firstPcaProj = std::fabs(delta1stPca[0]*pcaAxis[0] + delta1stPca[1]*pcaAxis[1] + delta1stPca[2]*pcaAxis[2]);
479 
480  if (firstPcaProj < 0.75 * pcaLen) continue;
481 
482  for(reco::HitPairListPtr::iterator secondItr = firstItr; secondItr != isolatedHitList.end(); secondItr++)
483  {
484  const float* secondPos = (*secondItr)->getPosition();
485  float delta2ndPca[] = {secondPos[0]-pcaPos[0],secondPos[1]-pcaPos[1],secondPos[2]-pcaPos[2]};
486  float secondPcaProj = std::fabs(delta2ndPca[0]*pcaAxis[0] + delta2ndPca[1]*pcaAxis[1] + delta2ndPca[2]*pcaAxis[2]);
487 
488  if (secondPcaProj < 0.75 * pcaLen) continue;
489 
490  float deltaPos[] = {secondPos[0]-firstPos[0],secondPos[1]-firstPos[1],secondPos[2]-firstPos[2]};
491  float projection = std::fabs(deltaPos[0]*pcaAxis[0]+deltaPos[1]*pcaAxis[1]+deltaPos[2]*pcaAxis[2]);
492 
493  edgeList.emplace_back(firstHit,*secondItr,projection);
494  //edgeList.emplace_back(reco::EdgeTuple(firstHit,*secondItr,DistanceBetweenNodes(firstHit,*secondItr)));
495  }
496  }
497 
498  if (edgeList.empty())
499  {
500  if (isolatedHitList.size() > 20)
501  {
502  std::cout << "!!!! What happened???? " << std::endl;
503  }
504  }
505 
506  if (!edgeList.empty())
507  {
508  edgeList.sort([](const auto& left,const auto& right){return std::get<2>(left) > std::get<2>(right);});
509 
510  // Ok, trial the algorithm by simply looking for the path between the hits at the front of the list
511  reco::EdgeTuple& bestEdge = edgeList.front();
512 
513  std::cout << "**> Sorted " << edgeList.size() << " edges, longest distance: " << DistanceBetweenNodes(std::get<0>(bestEdge),std::get<1>(bestEdge)) << std::endl;
514 
515  reco::HitPairListPtr& bestHitPairListPtr = clusterParams.getBestHitPairListPtr();
516  reco::EdgeList& bestEdgeList = clusterParams.getBestEdgeList();
517 
518  AStar(std::get<0>(bestEdge),std::get<1>(bestEdge),alpha,topNode,bestHitPairListPtr,bestEdgeList);
519 
520 // float cost(std::numeric_limits<float>::max());
521 
522 // LeastCostPath(curEdgeMap[std::get<0>(bestEdge)].front(),std::get<1>(bestEdge),curEdgeMap,bestPathHitList,bestEdgeList,cost);
523 
524 // bestPathHitList.push_front(std::get<0>(bestEdge));
525 
526  std::cout << "**> Best path has " << bestHitPairListPtr.size() << " hits, " << bestEdgeList.size() << " edges" << std::endl;
527  }
528  }
529  else
530  {
531  std::cout << "++++++>>> PCA failure! # hits: " << curCluster.size() << std::endl;
532  }
533  }
534 
535  if (m_enableMonitoring)
536  {
537  theClockPathFinding.stop();
538 
539  m_timeVector[PATHFINDING] += theClockPathFinding.accumulated_real_time();
540  }
541 
542  return;
543 }
reco::HitPairListPtr & getBestHitPairListPtr()
Definition: Cluster3D.h:408
bool getSvdOK() const
Definition: Cluster3D.h:224
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:112
void PCAAnalysis_3D(const reco::HitPairListPtr &hitPairList, reco::PrincipalComponents &pca, bool skeletonOnly=false) const
bool m_enableMonitoring
Data members to follow.
intermediate_table::iterator iterator
reco::EdgeList & getBestEdgeList()
Definition: Cluster3D.h:409
const float * getAvePosition() const
Definition: Cluster3D.h:228
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
Definition: Cluster3D.h:407
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:404
float DistanceBetweenNodes(const reco::ClusterHit3D *, const reco::ClusterHit3D *) const
std::list< EdgeTuple > EdgeList
Definition: Cluster3D.h:324
Int_t max
Definition: plot.C:27
std::tuple< const reco::ClusterHit3D *, const reco::ClusterHit3D *, double > EdgeTuple
Definition: Cluster3D.h:323
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:315
const float * getPosition() const
Definition: Cluster3D.h:145
Detector simulation of raw signals on wires.
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:104
const float * getEigenValues() const
Definition: Cluster3D.h:226
Int_t min
Definition: plot.C:26
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:326
void AStar(const reco::ClusterHit3D *, const reco::ClusterHit3D *, float alpha, kdTree::KdTreeNode &, reco::HitPairListPtr &, reco::EdgeList &) const
Algorithm to find shortest path between two 3D hits.
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:227
float lar_cluster3d::MinSpanTreeAlg::getTimeToExecute ( TimeValues  index) const
inlineoverridevirtual

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

Implements lar_cluster3d::IClusterAlg.

Definition at line 75 of file MinSpanTreeAlg_tool.cc.

References AStar(), DepthFirstSearch(), FindBestPathInCluster(), m_timeVector, PruneAmbiguousHits(), and RunPrimsAlgorithm().

75 {return m_timeVector.at(index);}
void lar_cluster3d::MinSpanTreeAlg::LeastCostPath ( const reco::EdgeTuple curEdge,
const reco::ClusterHit3D goalNode,
const reco::Hit3DToEdgeMap hitToEdgeMap,
reco::HitPairListPtr bestNodeList,
reco::EdgeList bestEdgeList,
float &  showMeTheMoney 
) const
private

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

Definition at line 681 of file MinSpanTreeAlg_tool.cc.

References max.

687 {
688  reco::Hit3DToEdgeMap::const_iterator edgeListItr = hitToEdgeMap.find(std::get<1>(curEdge));
689 
690  showMeTheMoney = std::numeric_limits<float>::max();
691 
692  if (edgeListItr != hitToEdgeMap.end())
693  {
694  for(const auto& edge : edgeListItr->second)
695  {
696  // skip the self reference
697  if (std::get<1>(edge) == std::get<0>(curEdge)) continue;
698 
699  // Have we found the droid we are looking for?
700  if (std::get<1>(edge) == goalNode)
701  {
702  bestNodeList.push_back(goalNode);
703  bestEdgeList.push_back(edge);
704  showMeTheMoney = std::get<2>(edge);
705  break;
706  }
707 
708  // Keep searching, it is out there somewhere...
709  float currentCost(0.);
710 
711  LeastCostPath(edge,goalNode,hitToEdgeMap,bestNodeList,bestEdgeList,currentCost);
712 
713  if (currentCost < std::numeric_limits<float>::max())
714  {
715  showMeTheMoney = std::get<2>(edge) + currentCost;
716  break;
717  }
718  }
719  }
720 
721  if (showMeTheMoney < std::numeric_limits<float>::max())
722  {
723  bestNodeList.push_front(std::get<1>(curEdge));
724  bestEdgeList.push_front(curEdge);
725  }
726 
727  return;
728 }
Int_t max
Definition: plot.C:27
intermediate_table::const_iterator const_iterator
void LeastCostPath(const reco::EdgeTuple &, const reco::ClusterHit3D *, const reco::Hit3DToEdgeMap &, reco::HitPairListPtr &, reco::EdgeList &, float &) const
Find the lowest cost path between two nodes using MST edges.
void lar_cluster3d::MinSpanTreeAlg::PruneAmbiguousHits ( reco::ClusterParameters clusterParams,
reco::Hit2DToClusterMap hit2DToClusterMap 
) const
private

Prune the obvious ambiguous hits.

Definition at line 804 of file MinSpanTreeAlg_tool.cc.

References reco::ClusterParameters::getHitPairListPtr().

Referenced by getTimeToExecute().

805 {
806 
807  // Recover the HitPairListPtr from the input clusterParams (which will be the
808  // only thing that has been provided)
809  reco::HitPairListPtr& hitPairVector = clusterParams.getHitPairListPtr();
810 
811  size_t nStartedWith(hitPairVector.size());
812  size_t nRejectedHits(0);
813 
814  reco::HitPairListPtr goodHits;
815 
816  // Loop through the hits and try to week out the clearly ambiguous ones
817  for(const auto& hit3D : hitPairVector)
818  {
819  // Loop to try to remove ambiguous hits
820  size_t n2DHitsIn3DHit(0);
821  size_t nThisClusterOnly(0);
822  size_t nOtherCluster(0);
823 
824  // reco::ClusterParameters* otherCluster;
825  const std::set<const reco::ClusterHit3D*>* otherClusterHits = 0;
826 
827  for(const auto& hit2D : hit3D->getHits())
828  {
829  if (!hit2D) continue;
830 
831  n2DHitsIn3DHit++;
832 
833  if (hit2DToClusterMap[hit2D].size() < 2) nThisClusterOnly = hit2DToClusterMap[hit2D][&clusterParams].size();
834  else
835  {
836  for(const auto& clusterHitMap : hit2DToClusterMap[hit2D])
837  {
838  if (clusterHitMap.first == &clusterParams) continue;
839 
840  if (clusterHitMap.second.size() > nOtherCluster)
841  {
842  nOtherCluster = clusterHitMap.second.size();
843  // otherCluster = clusterHitMap.first;
844  otherClusterHits = &clusterHitMap.second;
845  }
846  }
847  }
848  }
849 
850  if (n2DHitsIn3DHit < 3 && nThisClusterOnly > 1 && nOtherCluster > 0)
851  {
852  bool skip3DHit(false);
853 
854  for(const auto& otherHit3D : *otherClusterHits)
855  {
856  size_t nOther2DHits(0);
857 
858  for(const auto& otherHit2D : otherHit3D->getHits())
859  {
860  if (!otherHit2D) continue;
861 
862  nOther2DHits++;
863  }
864 
865  if (nOther2DHits > 2)
866  {
867  skip3DHit = true;
868  nRejectedHits++;
869  break;
870  }
871  }
872 
873  if (skip3DHit) continue;
874 
875  }
876 
877  goodHits.emplace_back(hit3D);
878  }
879 
880  std::cout << "###>> Input " << nStartedWith << " hits, rejected: " << nRejectedHits << std::endl;
881 
882  hitPairVector.resize(goodHits.size());
883  std::copy(goodHits.begin(),goodHits.end(),hitPairVector.begin());
884 
885  return;
886 }
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:404
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:315
void lar_cluster3d::MinSpanTreeAlg::ReconstructBestPath ( const reco::ClusterHit3D goalNode,
BestNodeMap bestNodeMap,
reco::HitPairListPtr pathNodeList,
reco::EdgeList bestEdgeList 
) const
private

Definition at line 660 of file MinSpanTreeAlg_tool.cc.

References DistanceBetweenNodes().

Referenced by AStar().

664 {
665  while(std::get<0>(bestNodeMap.at(goalNode)) != goalNode)
666  {
667  const reco::ClusterHit3D* nextNode = std::get<0>(bestNodeMap[goalNode]);
668  reco::EdgeTuple bestEdge = reco::EdgeTuple(goalNode,nextNode,DistanceBetweenNodes(goalNode,nextNode));
669 
670  pathNodeList.push_front(goalNode);
671  bestEdgeList.push_front(bestEdge);
672 
673  goalNode = nextNode;
674  }
675 
676  pathNodeList.push_front(goalNode);
677 
678  return;
679 }
float DistanceBetweenNodes(const reco::ClusterHit3D *, const reco::ClusterHit3D *) const
std::tuple< const reco::ClusterHit3D *, const reco::ClusterHit3D *, double > EdgeTuple
Definition: Cluster3D.h:323
void lar_cluster3d::MinSpanTreeAlg::RunPrimsAlgorithm ( reco::HitPairList hitPairList,
kdTree::KdTreeNode topNode,
reco::ClusterParametersList clusterParametersList 
) const
private

Driver for Prim's algorithm.

Definition at line 253 of file MinSpanTreeAlg_tool.cc.

References reco::ClusterHit3D::CLUSTERATTACHED, lar_cluster3d::kdTree::FindNearestNeighbors(), art::left(), m_enableMonitoring, m_kdTree, m_timeVector, art::right(), lar_cluster3d::IClusterAlg::RUNDBSCAN, and reco::ClusterHit3D::setStatusBit().

Referenced by Cluster3DHits(), and getTimeToExecute().

256 {
257  // If no hits then no work
258  if (hitPairList.empty()) return;
259 
260  // Now proceed with building the clusters
261  cet::cpu_timer theClockDBScan;
262 
263  // Start clocks if requested
264  if (m_enableMonitoring) theClockDBScan.start();
265 
266  // Initialization
267  size_t clusterIdx(0);
268 
269  // This will contain our list of edges
270  reco::EdgeList curEdgeList;
271 
272  // Get the first point
273  reco::HitPairList::iterator freeHitItr = hitPairList.begin();
274  const reco::ClusterHit3D* lastAddedHit = (*freeHitItr++).get();
275 
277 
278  // Make a cluster...
279  clusterParametersList.push_back(reco::ClusterParameters());
280 
281  // Get an iterator to the first cluster
282  reco::ClusterParametersList::iterator curClusterItr = --clusterParametersList.end();
283 
284  // We use pointers here because the objects they point to will change in the loop below
285  reco::Hit3DToEdgeMap* curEdgeMap = &(*curClusterItr).getHit3DToEdgeMap();
286  reco::HitPairListPtr* curCluster = &(*curClusterItr).getHitPairListPtr();
287 
288  // Loop until all hits have been associated to a cluster
289  while(1)
290  {
291  // and the 3D hit status bits
293 
294  // Purge the current list to get rid of edges which point to hits already in the cluster
295  for(reco::EdgeList::iterator curEdgeItr = curEdgeList.begin(); curEdgeItr != curEdgeList.end();)
296  {
297  if (std::get<1>(*curEdgeItr)->getStatusBits() & reco::ClusterHit3D::CLUSTERATTACHED)
298  curEdgeItr = curEdgeList.erase(curEdgeItr);
299  else curEdgeItr++;
300  }
301 
302  // Add the lastUsedHit to the current cluster
303  curCluster->push_back(lastAddedHit);
304 
305  // Set up to find the list of nearest neighbors to the last used hit...
306  kdTree::CandPairList CandPairList;
307  float bestDistance(1.5); //std::numeric_limits<float>::max());
308 
309  // And find them... result will be an unordered list of neigbors
310  m_kdTree.FindNearestNeighbors(lastAddedHit, topNode, CandPairList, bestDistance);
311 
312  // Copy edges to the current list (but only for hits not already in a cluster)
313  for(auto& pair : CandPairList)
314  if (!(pair.second->getStatusBits() & reco::ClusterHit3D::CLUSTERATTACHED)) curEdgeList.push_back(reco::EdgeTuple(lastAddedHit,pair.second,pair.first));
315 
316  // If the edge list is empty then we have a complete cluster
317  if (curEdgeList.empty())
318  {
319  std::cout << "-----------------------------------------------------------------------------------------" << std::endl;
320  std::cout << "**> Cluster idx: " << clusterIdx++ << " has " << curCluster->size() << " hits" << std::endl;
321 
322  // Look for the next "free" hit
323  freeHitItr = std::find_if(freeHitItr,hitPairList.end(),[](const auto& hit){return !(hit->getStatusBits() & reco::ClusterHit3D::CLUSTERATTACHED);});
324 
325  // If at end of input list we are done with all hits
326  if (freeHitItr == hitPairList.end()) break;
327 
328  std::cout << "##################################################################>Processing another cluster" << std::endl;
329 
330  // Otherwise, get a new cluster and set up
331  clusterParametersList.push_back(reco::ClusterParameters());
332 
333  curClusterItr = --clusterParametersList.end();
334 
335  curEdgeMap = &(*curClusterItr).getHit3DToEdgeMap();
336  curCluster = &(*curClusterItr).getHitPairListPtr();
337  lastAddedHit = (*freeHitItr++).get();
338  }
339  // Otherwise we are still processing the current cluster
340  else
341  {
342  // Sort the list of edges by distance
343  curEdgeList.sort([](const auto& left,const auto& right){return std::get<2>(left) < std::get<2>(right);});
344 
345  // Populate the map with the edges...
346  reco::EdgeTuple& curEdge = curEdgeList.front();
347 
348  (*curEdgeMap)[std::get<0>(curEdge)].push_back(curEdge);
349  (*curEdgeMap)[std::get<1>(curEdge)].push_back(reco::EdgeTuple(std::get<1>(curEdge),std::get<0>(curEdge),std::get<2>(curEdge)));
350 
351  // Update the last hit to be added to the collection
352  lastAddedHit = std::get<1>(curEdge);
353  }
354  }
355 
356  if (m_enableMonitoring)
357  {
358  theClockDBScan.stop();
359 
360  m_timeVector[RUNDBSCAN] = theClockDBScan.accumulated_real_time();
361  }
362 
363  return;
364 }
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:112
bool m_enableMonitoring
Data members to follow.
intermediate_table::iterator iterator
size_t FindNearestNeighbors(const reco::ClusterHit3D *, const KdTreeNode &, CandPairList &, float &) const
Definition: kdTree.cxx:178
std::list< EdgeTuple > EdgeList
Definition: Cluster3D.h:324
std::tuple< const reco::ClusterHit3D *, const reco::ClusterHit3D *, double > EdgeTuple
Definition: Cluster3D.h:323
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:315
Detector simulation of raw signals on wires.
std::list< CandPair > CandPairList
Definition: kdTree.h:70
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:104
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:326
attached to a cluster
Definition: Cluster3D.h:100
void setStatusBit(unsigned bits) const
Definition: Cluster3D.h:163

Member Data Documentation

ClusterParamsBuilder lar_cluster3d::MinSpanTreeAlg::m_clusterBuilder
private

Definition at line 143 of file MinSpanTreeAlg_tool.cc.

Referenced by Cluster3DHits().

bool lar_cluster3d::MinSpanTreeAlg::m_enableMonitoring
private

Data members to follow.

Definition at line 137 of file MinSpanTreeAlg_tool.cc.

Referenced by Cluster3DHits(), configure(), FindBestPathInCluster(), and RunPrimsAlgorithm().

geo::Geometry* lar_cluster3d::MinSpanTreeAlg::m_geometry
private

Definition at line 141 of file MinSpanTreeAlg_tool.cc.

Referenced by configure().

kdTree lar_cluster3d::MinSpanTreeAlg::m_kdTree
private

Definition at line 145 of file MinSpanTreeAlg_tool.cc.

Referenced by AStar(), Cluster3DHits(), and RunPrimsAlgorithm().

PrincipalComponentsAlg lar_cluster3d::MinSpanTreeAlg::m_pcaAlg
private

Definition at line 144 of file MinSpanTreeAlg_tool.cc.

Referenced by CheckHitSorting(), and FindBestPathInCluster().

std::vector<float> lar_cluster3d::MinSpanTreeAlg::m_timeVector
mutableprivate
std::vector<std::vector<float> > lar_cluster3d::MinSpanTreeAlg::m_wireDir
private

Definition at line 139 of file MinSpanTreeAlg_tool.cc.

Referenced by CheckHitSorting(), and configure().


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