LArSoft  v09_90_00
Liquid Argon Software toolkit - https://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 &, reco::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 *, 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 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::Geometry const * m_geometry
 
PrincipalComponentsAlg m_pcaAlg
 
kdTree m_kdTree
 
std::unique_ptr< lar_cluster3d::IClusterParametersBuilderm_clusterBuilder
 Common cluster builder tool. More...
 

Detailed Description

Definition at line 43 of file MinSpanTreeAlg_tool.cc.

Member Typedef Documentation

Definition at line 116 of file MinSpanTreeAlg_tool.cc.

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

Definition at line 115 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 138 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 157 of file MinSpanTreeAlg_tool.cc.

References configure().

158  : m_pcaAlg(pset.get<fhicl::ParameterSet>("PrincipalComponentsAlg"))
159  , m_kdTree(pset.get<fhicl::ParameterSet>("kdTree"))
160  {
161  this->configure(pset);
162  }
void configure(fhicl::ParameterSet const &pset) override
lar_cluster3d::MinSpanTreeAlg::~MinSpanTreeAlg ( )

Destructor.

Definition at line 166 of file MinSpanTreeAlg_tool.cc.

166 {}

Member Function Documentation

void lar_cluster3d::MinSpanTreeAlg::AStar ( const reco::ClusterHit3D startNode,
const reco::ClusterHit3D goalNode,
reco::ClusterParameters clusterParams 
) const
private

Algorithm to find shortest path between two 3D hits.

Definition at line 537 of file MinSpanTreeAlg_tool.cc.

References DistanceBetweenNodes(), reco::ClusterParameters::getBestEdgeList(), reco::ClusterParameters::getBestHitPairListPtr(), reco::ClusterParameters::getHit3DToEdgeMap(), reco::ClusterHit3D::getStatusBits(), reco::ClusterHit3D::PATHCHECKED, ReconstructBestPath(), and reco::ClusterHit3D::setStatusBit().

Referenced by getTimeToExecute().

540  {
541  // Recover the list of hits and edges
542  reco::HitPairListPtr& pathNodeList = clusterParams.getBestHitPairListPtr();
543  reco::EdgeList& bestEdgeList = clusterParams.getBestEdgeList();
544  reco::Hit3DToEdgeMap& curEdgeMap = clusterParams.getHit3DToEdgeMap();
545 
546  // Find the shortest path from start to goal using an A* algorithm
547  // Keep track of the nodes which have already been evaluated
548  reco::HitPairListPtr closedList;
549 
550  // Keep track of the nodes that have been "discovered" but yet to be evaluated
551  reco::HitPairListPtr openList = {startNode};
552 
553  // Create a map which, for each node, will tell us the node it can be most efficiencly reached from.
554  BestNodeMap bestNodeMap;
555 
556  bestNodeMap[startNode] =
557  BestNodeTuple(startNode, 0., DistanceBetweenNodes(startNode, goalNode));
558 
559  while (!openList.empty()) {
560  // The list is not empty so by def we will return something
561  reco::HitPairListPtr::iterator currentNodeItr = openList.begin();
562 
563  // If the list contains more than one element then we need to find the one with the smallest total estimated cost to the end
564  if (openList.size() > 1)
565  currentNodeItr = std::min_element(
566  openList.begin(), openList.end(), [bestNodeMap](const auto& next, const auto& best) {
567  return std::get<2>(bestNodeMap.at(next)) < std::get<2>(bestNodeMap.at(best));
568  });
569 
570  // Easier to deal directly with the pointer to the node
571  const reco::ClusterHit3D* currentNode = *currentNodeItr;
572 
573  // Check to see if we have reached the goal and need to evaluate the path
574  if (currentNode == goalNode) {
575  // The path reconstruction will
576  ReconstructBestPath(goalNode, bestNodeMap, pathNodeList, bestEdgeList);
577 
578  break;
579  }
580 
581  // Otherwise need to keep evaluating
582  else {
583  openList.erase(currentNodeItr);
585 
586  // Get tuple values for the current node
587  const BestNodeTuple& currentNodeTuple = bestNodeMap.at(currentNode);
588  float currentNodeScore = std::get<1>(currentNodeTuple);
589 
590  // Recover the edges associated to the current point
591  const reco::EdgeList& curEdgeList = curEdgeMap[currentNode];
592 
593  for (const auto& curEdge : curEdgeList) {
594  const reco::ClusterHit3D* candHit3D = std::get<1>(curEdge);
595 
596  if (candHit3D->getStatusBits() & reco::ClusterHit3D::PATHCHECKED) continue;
597 
598  float tentative_gScore = currentNodeScore + std::get<2>(curEdge);
599 
600  // Have we seen the candidate node before?
601  BestNodeMap::iterator candNodeItr = bestNodeMap.find(candHit3D);
602 
603  if (candNodeItr == bestNodeMap.end()) { openList.push_back(candHit3D); }
604  else if (tentative_gScore > std::get<1>(candNodeItr->second))
605  continue;
606 
607  // Make a guess at score to get to target...
608  float guessToTarget = DistanceBetweenNodes(candHit3D, goalNode) / 0.3;
609 
610  bestNodeMap[candHit3D] =
611  BestNodeTuple(currentNode, tentative_gScore, tentative_gScore + guessToTarget);
612  }
613  }
614  }
615 
616  return;
617  }
reco::HitPairListPtr & getBestHitPairListPtr()
Definition: Cluster3D.h:467
intermediate_table::iterator iterator
std::tuple< const reco::ClusterHit3D *, float, float > BestNodeTuple
reco::EdgeList & getBestEdgeList()
Definition: Cluster3D.h:468
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
Definition: Cluster3D.h:466
float DistanceBetweenNodes(const reco::ClusterHit3D *, const reco::ClusterHit3D *) const
unsigned int getStatusBits() const
Definition: Cluster3D.h:154
std::list< EdgeTuple > EdgeList
Definition: Cluster3D.h:337
std::unordered_map< const reco::ClusterHit3D *, BestNodeTuple > BestNodeMap
Path checking algorithm has seen this hit.
Definition: Cluster3D.h:108
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:326
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:339
void ReconstructBestPath(const reco::ClusterHit3D *, BestNodeMap &, reco::HitPairListPtr &, reco::EdgeList &) const
void setStatusBit(unsigned bits) const
Definition: Cluster3D.h:177
void lar_cluster3d::MinSpanTreeAlg::CheckHitSorting ( reco::ClusterParameters clusterParams) const
private

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

891  {
892  reco::HitPairListPtr& curCluster = clusterParams.getHitPairListPtr();
893 
894  // Trial A* here
895  if (curCluster.size() > 2) {
896  // Do a quick PCA to determine our parameter "alpha"
898  m_pcaAlg.PCAAnalysis_3D(curCluster, pca);
899 
900  if (pca.getSvdOK()) {
901  const Eigen::Vector3f& pcaAxis = pca.getEigenVectors().row(2);
902 
903  std::vector<size_t> closestPlane = {0, 0, 0};
904  std::vector<float> bestAngle = {0., 0., 0.};
905 
906  for (size_t plane = 0; plane < 3; plane++) {
907  const std::vector<float>& wireDir = m_wireDir[plane];
908 
909  float dotProd =
910  std::fabs(pcaAxis[0] * wireDir[0] + pcaAxis[1] * wireDir[1] + pcaAxis[2] * wireDir[2]);
911 
912  if (dotProd > bestAngle[0]) {
913  bestAngle[2] = bestAngle[1];
914  closestPlane[2] = closestPlane[1];
915  bestAngle[1] = bestAngle[0];
916  closestPlane[1] = closestPlane[0];
917  closestPlane[0] = plane;
918  bestAngle[0] = dotProd;
919  }
920  else if (dotProd > bestAngle[1]) {
921  bestAngle[2] = bestAngle[1];
922  closestPlane[2] = closestPlane[1];
923  closestPlane[1] = plane;
924  bestAngle[1] = dotProd;
925  }
926  else {
927  closestPlane[2] = plane;
928  bestAngle[2] = dotProd;
929  }
930  }
931 
932  // Get a copy of our 3D hits
933  reco::HitPairListPtr localHitList = curCluster;
934 
935  // Sort the hits
936  localHitList.sort(SetCheckHitOrder(closestPlane));
937 
938  // Ok, let's print it all and take a look
939  std::cout << "*****************************************************************************"
940  "***************"
941  << std::endl;
942  std::cout << "**>>>>> longest axis: " << closestPlane[0] << ", best angle: " << bestAngle[0]
943  << std::endl;
944  std::cout << "**>>>>> second axis: " << closestPlane[1] << ", best angle: " << bestAngle[1]
945  << std::endl;
946  std::cout << " " << std::endl;
947 
948  reco::HitPairListPtr::iterator firstHitItr = localHitList.begin();
949  reco::HitPairListPtr::iterator lastHitItr = localHitList.begin();
950 
951  size_t bestPlane = closestPlane[0];
952 
953  reco::HitPairListPtr testList;
954 
955  while (firstHitItr != localHitList.end()) {
956  const reco::ClusterHit3D* currentHit = *firstHitItr;
957 
958  // Search for the last matching best view hit
959  while (lastHitItr != localHitList.end()) {
960  // If a different wire on the best view then we're certainly done
961  if (currentHit->getWireIDs()[bestPlane] != (*lastHitItr)->getWireIDs()[bestPlane])
962  break;
963 
964  // More subtle test to see if same wire but different hit (being careful of case of no hit)
965  if (currentHit->getHits()[bestPlane] && (*lastHitItr)->getHits()[bestPlane] &&
966  currentHit->getHits()[bestPlane] != (*lastHitItr)->getHits()[bestPlane])
967  break;
968 
969  // Yet event more subtle test...
970  if ((!(currentHit->getHits()[bestPlane]) && (*lastHitItr)->getHits()[bestPlane]) ||
971  (currentHit->getHits()[bestPlane] && !((*lastHitItr)->getHits()[bestPlane])))
972  break;
973 
974  // Not there yet...
975  lastHitItr++;
976  }
977 
978  // How many hits in this chain?
979  // size_t numHits(std::distance(firstHitItr,lastHitItr));
980  // float minOverlapFraction(0.);
981 
982  // if (numHits > 1)
983  // {
984  // reco::HitPairListPtr::iterator bestMinOverlapItr = std::max_element(firstHitItr,lastHitItr,[](const auto& left, const auto& right){return left->getMinOverlapFraction() < right->getMinOverlapFraction();});
985  //
986  // minOverlapFraction = std::min(0.999*(*bestMinOverlapItr)->getMinOverlapFraction(),0.90);
987  // }
988 
989  while (firstHitItr != lastHitItr) {
990  // if (currentHit->getMinOverlapFraction() > minOverlapFraction) testList.push_back(currentHit); //currentHit->setStatusBit(reco::ClusterHit3D::SKELETONHIT);
991 
992  currentHit = *++firstHitItr;
993  }
994 
995  firstHitItr = lastHitItr;
996  }
997  /*
998  for(const auto& hit : localHitList)
999  {
1000  std::cout << "- wires: ";
1001 
1002  for(size_t idx = 0; idx < 3; idx++)
1003  {
1004  float viewTime = -1.;
1005 
1006  if (hit->getHits()[closestView[idx]]) viewTime = hit->getHits()[closestView[idx]]->getTimeTicks();
1007 
1008  std::cout << closestView[idx] << ":" << hit->getWireIDs()[closestView[idx]].Wire << " - " << viewTime << ", ";
1009  }
1010 
1011  bool isSkeleton = hit->getStatusBits() & reco::ClusterHit3D::SKELETONHIT;
1012 
1013  std::cout << "ave time: " << hit->getAvePeakTime() << ", min/max overlap: " << hit->getMinOverlapFraction() << "/" << hit->getMaxOverlapFraction() << ", tagged: " << isSkeleton << std::endl;
1014 
1015  if (isSkeleton) testList.push_back(hit);
1016  }
1017 */
1018  curCluster = testList;
1019  }
1020  }
1021 
1022  return;
1023  }
intermediate_table::iterator iterator
bool getSvdOK() const
Definition: Cluster3D.h:240
std::vector< std::vector< float > > m_wireDir
void PCAAnalysis_3D(const reco::HitPairListPtr &hitPairList, reco::PrincipalComponents &pca, bool skeletonOnly=false) const
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:463
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:326
const std::vector< geo::WireID > & getWireIDs() const
Definition: Cluster3D.h:170
const ClusterHit2DVec & getHits() const
Definition: Cluster3D.h:168
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:243
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 202 of file MinSpanTreeAlg_tool.cc.

References 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().

204  {
210  // Zero the time vector
211  if (m_enableMonitoring) std::fill(m_timeVector.begin(), m_timeVector.end(), 0.);
212 
213  // DBScan is driven of its "epsilon neighborhood". Computing adjacency within DBScan can be time
214  // consuming so the idea is the prebuild the adjaceny map and then run DBScan.
215  // The following call does this work
216  kdTree::KdTreeNodeList kdTreeNodeContainer;
217  kdTree::KdTreeNode topNode = m_kdTree.BuildKdTree(hitPairList, kdTreeNodeContainer);
218 
220 
221  // Run DBScan to get candidate clusters
222  RunPrimsAlgorithm(hitPairList, topNode, clusterParametersList);
223 
224  // Initial clustering is done, now trim the list and get output parameters
225  cet::cpu_timer theClockBuildClusters;
226 
227  // Start clocks if requested
228  if (m_enableMonitoring) theClockBuildClusters.start();
229 
230  m_clusterBuilder->BuildClusterInfo(clusterParametersList);
231 
232  if (m_enableMonitoring) {
233  theClockBuildClusters.stop();
234 
235  m_timeVector[BUILDCLUSTERINFO] = theClockBuildClusters.accumulated_real_time();
236  }
237 
238  // Test run the path finding algorithm
239  for (auto& clusterParams : clusterParametersList)
240  FindBestPathInCluster(clusterParams, topNode);
241 
242  mf::LogDebug("MinSpanTreeAlg") << ">>>>> Cluster3DHits done, found "
243  << clusterParametersList.size() << " clusters" << std::endl;
244 
245  return;
246  }
bool m_enableMonitoring
Data members to follow.
std::list< KdTreeNode > KdTreeNodeList
Definition: kdTree.h:69
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)
std::unique_ptr< lar_cluster3d::IClusterParametersBuilder > m_clusterBuilder
Common cluster builder tool.
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
float getTimeToExecute() const
Definition: kdTree.h:104
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:109
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.

71  {}
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 170 of file MinSpanTreeAlg_tool.cc.

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

Referenced by MinSpanTreeAlg().

171  {
172  m_enableMonitoring = pset.get<bool>("EnableMonitoring", true);
173 
175 
176  m_geometry = &*geometry;
177 
178  m_timeVector.resize(NUMTIMEVALUES, 0.);
179 
180  // Determine the unit directon and normal vectors to the wires
181  m_wireDir.resize(3);
182 
183  raw::ChannelID_t uChannel(0);
184  std::vector<geo::WireID> uWireID = m_geometry->ChannelToWire(uChannel);
185  const geo::WireGeo* uWireGeo = m_geometry->WirePtr(uWireID[0]);
186 
187  auto const uWireDir = uWireGeo->Direction();
188  m_wireDir[0] = {(float)uWireDir.X(), (float)-uWireDir.Z(), (float)uWireDir.Y()};
189 
190  raw::ChannelID_t vChannel(2400);
191  std::vector<geo::WireID> vWireID = m_geometry->ChannelToWire(vChannel);
192  const geo::WireGeo* vWireGeo = m_geometry->WirePtr(vWireID[0]);
193 
194  auto const vWireDir = vWireGeo->Direction();
195  m_wireDir[1] = {(float)vWireDir.X(), (float)-vWireDir.Z(), (float)vWireDir.Y()};
196  m_wireDir[2] = {0., 0., 1.};
197 
198  m_clusterBuilder = art::make_tool<lar_cluster3d::IClusterParametersBuilder>(
199  pset.get<fhicl::ParameterSet>("ClusterParamsBuilder"));
200  }
Geometry description of a TPC wireThe wire is a single straight segment on a wire plane...
Definition: WireGeo.h:114
std::vector< std::vector< float > > m_wireDir
std::vector< WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
bool m_enableMonitoring
Data members to follow.
Vector_t Direction() const
Definition: WireGeo.h:289
std::unique_ptr< lar_cluster3d::IClusterParametersBuilder > m_clusterBuilder
Common cluster builder tool.
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
WireGeo const * WirePtr(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 719 of file MinSpanTreeAlg_tool.cc.

Referenced by FindBestPathInCluster(), and getTimeToExecute().

722  {
723  reco::HitPairListPtr hitPairListPtr;
724  float bestQuality(0.);
725  float curEdgeWeight = std::max(0.3, std::get<2>(curEdge));
726  float curEdgeProj(1. / curEdgeWeight);
727 
728  reco::Hit3DToEdgeMap::const_iterator edgeListItr = hitToEdgeMap.find(std::get<1>(curEdge));
729 
730  if (edgeListItr != hitToEdgeMap.end()) {
731  // The input edge weight has quality factors applied, recalculate just the position difference
732  const Eigen::Vector3f& firstHitPos = std::get<0>(curEdge)->getPosition();
733  const Eigen::Vector3f& secondHitPos = std::get<1>(curEdge)->getPosition();
734  float curEdgeVec[] = {secondHitPos[0] - firstHitPos[0],
735  secondHitPos[1] - firstHitPos[1],
736  secondHitPos[2] - firstHitPos[2]};
737  float curEdgeMag = std::sqrt(curEdgeVec[0] * curEdgeVec[0] + curEdgeVec[1] * curEdgeVec[1] +
738  curEdgeVec[2] * curEdgeVec[2]);
739 
740  curEdgeMag = std::max(float(0.1), curEdgeMag);
741 
742  for (const auto& edge : edgeListItr->second) {
743  // skip the self reference
744  if (std::get<1>(edge) == std::get<0>(curEdge)) continue;
745 
746  float quality(0.);
747 
748  reco::HitPairListPtr tempList = DepthFirstSearch(edge, hitToEdgeMap, quality);
749 
750  if (quality > bestQuality) {
751  hitPairListPtr = tempList;
752  bestQuality = quality;
753  curEdgeProj = 1. / curEdgeMag;
754  }
755  }
756  }
757 
758  hitPairListPtr.push_front(std::get<1>(curEdge));
759 
760  bestTreeQuality += bestQuality + curEdgeProj;
761 
762  return hitPairListPtr;
763  }
intermediate_table::const_iterator const_iterator
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:326
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 688 of file MinSpanTreeAlg_tool.cc.

References reco::ClusterHit3D::getPosition().

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

690  {
691  const Eigen::Vector3f& node1Pos = node1->getPosition();
692  const Eigen::Vector3f& node2Pos = node2->getPosition();
693  float deltaNode[] = {
694  node1Pos[0] - node2Pos[0], node1Pos[1] - node2Pos[1], node1Pos[2] - node2Pos[2]};
695 
696  // Standard euclidean distance
697  return std::sqrt(deltaNode[0] * deltaNode[0] + deltaNode[1] * deltaNode[1] +
698  deltaNode[2] * deltaNode[2]);
699 
700  // Manhatten distance
701  //return std::fabs(deltaNode[0]) + std::fabs(deltaNode[1]) + std::fabs(deltaNode[2]);
702  /*
703  // Chebyshev distance
704  // We look for maximum distance by wires...
705 
706  // Now go through the hits and compare view by view to look for delta wire and tigher constraint on delta t
707  int wireDeltas[] = {0,0,0};
708 
709  for(size_t idx = 0; idx < 3; idx++)
710  wireDeltas[idx] = std::abs(int(node1->getWireIDs()[idx].Wire) - int(node2->getWireIDs()[idx].Wire));
711 
712  // put wire deltas in order...
713  std::sort(wireDeltas, wireDeltas + 3);
714 
715  return std::sqrt(deltaNode[0]*deltaNode[0] + 0.09 * float(wireDeltas[2]*wireDeltas[2]));
716  */
717  }
const Eigen::Vector3f getPosition() const
Definition: Cluster3D.h:155
void lar_cluster3d::MinSpanTreeAlg::FindBestPathInCluster ( reco::ClusterParameters curCluster) const
private

Algorithm to find the best path through the given cluster.

Definition at line 376 of file MinSpanTreeAlg_tool.cc.

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

Referenced by Cluster3DHits(), and getTimeToExecute().

377  {
378  reco::HitPairListPtr longestCluster;
379  float bestQuality(0.);
380  float aveNumEdges(0.);
381  size_t maxNumEdges(0);
382  size_t nIsolatedHits(0);
383 
384  // Now proceed with building the clusters
385  cet::cpu_timer theClockPathFinding;
386 
387  // Start clocks if requested
388  if (m_enableMonitoring) theClockPathFinding.start();
389 
390  reco::HitPairListPtr& hitPairList = curCluster.getHitPairListPtr();
391  reco::Hit3DToEdgeMap& curEdgeMap = curCluster.getHit3DToEdgeMap();
392  reco::EdgeList& bestEdgeList = curCluster.getBestEdgeList();
393 
394  // Do some spelunking...
395  for (const auto& hit : hitPairList) {
396  if (!curEdgeMap[hit].empty() && curEdgeMap[hit].size() == 1) {
397  float quality(0.);
398 
399  reco::HitPairListPtr tempList =
400  DepthFirstSearch(curEdgeMap[hit].front(), curEdgeMap, quality);
401 
402  tempList.push_front(std::get<0>(curEdgeMap[hit].front()));
403 
404  if (quality > bestQuality) {
405  longestCluster = tempList;
406  bestQuality = quality;
407  }
408 
409  nIsolatedHits++;
410  }
411 
412  aveNumEdges += float(curEdgeMap[hit].size());
413  maxNumEdges = std::max(maxNumEdges, curEdgeMap[hit].size());
414  }
415 
416  aveNumEdges /= float(hitPairList.size());
417  std::cout << "----> # isolated hits: " << nIsolatedHits
418  << ", longest branch: " << longestCluster.size()
419  << ", cluster size: " << hitPairList.size() << ", ave # edges: " << aveNumEdges
420  << ", max: " << maxNumEdges << std::endl;
421 
422  if (!longestCluster.empty()) {
423  hitPairList = longestCluster;
424  for (const auto& hit : hitPairList) {
425  for (const auto& edge : curEdgeMap[hit])
426  bestEdgeList.emplace_back(edge);
427  }
428 
429  std::cout << " ====> new cluster size: " << hitPairList.size() << std::endl;
430  }
431 
432  if (m_enableMonitoring) {
433  theClockPathFinding.stop();
434 
435  m_timeVector[PATHFINDING] += theClockPathFinding.accumulated_real_time();
436  }
437 
438  return;
439  }
bool m_enableMonitoring
Data members to follow.
reco::EdgeList & getBestEdgeList()
Definition: Cluster3D.h:468
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
Definition: Cluster3D.h:466
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:463
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
std::list< EdgeTuple > EdgeList
Definition: Cluster3D.h:337
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:326
Detector simulation of raw signals on wires.
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:339
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:109
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  
) const
private

Alternative version of FindBestPathInCluster utilizing an A* algorithm.

Definition at line 441 of file MinSpanTreeAlg_tool.cc.

References util::abs(), DistanceBetweenNodes(), util::empty(), reco::PrincipalComponents::getAvePosition(), reco::ClusterParameters::getBestEdgeList(), reco::ClusterParameters::getBestHitPairListPtr(), reco::PrincipalComponents::getEigenValues(), reco::PrincipalComponents::getEigenVectors(), reco::ClusterParameters::getHit3DToEdgeMap(), reco::ClusterParameters::getHitPairListPtr(), reco::PrincipalComponents::getSvdOK(), LeastCostPath(), art::left(), m_enableMonitoring, m_pcaAlg, m_timeVector, lar_cluster3d::IClusterAlg::PATHFINDING, lar_cluster3d::PrincipalComponentsAlg::PCAAnalysis_3D(), art::right(), and util::size().

443  {
444  // Set up for timing the function
445  cet::cpu_timer theClockPathFinding;
446 
447  // Start clocks if requested
448  if (m_enableMonitoring) theClockPathFinding.start();
449 
450  // Trial A* here
451  if (clusterParams.getHitPairListPtr().size() > 2) {
452  // Get references to what we need....
453  reco::HitPairListPtr& curCluster = clusterParams.getHitPairListPtr();
454  reco::Hit3DToEdgeMap& curEdgeMap = clusterParams.getHit3DToEdgeMap();
455 
456  // Do a quick PCA to determine our parameter "alpha"
458  m_pcaAlg.PCAAnalysis_3D(curCluster, pca);
459 
460  // The chances of a failure are remote, still we should check
461  if (pca.getSvdOK()) {
462  float pcaLen = 3.0 * sqrt(pca.getEigenValues()[2]);
463  float pcaWidth = 3.0 * sqrt(pca.getEigenValues()[1]);
464  float pcaHeight = 3.0 * sqrt(pca.getEigenValues()[0]);
465  const Eigen::Vector3f& pcaCenter = pca.getAvePosition();
466  float alpha = std::min(float(1.), std::max(float(0.001), pcaWidth / pcaLen));
467 
468  // Create a temporary container for the isolated points
469  reco::ProjectedPointList isolatedPointList;
470 
471  // Go through and find the isolated points, for those get the projection to the plane of maximum spread
472  for (const auto& hit3D : curCluster) {
473  // the definition of an isolated hit is that it only has one associated edge
474  if (!curEdgeMap[hit3D].empty() && curEdgeMap[hit3D].size() == 1) {
475  Eigen::Vector3f pcaToHitVec(hit3D->getPosition()[0] - pcaCenter(0),
476  hit3D->getPosition()[1] - pcaCenter(1),
477  hit3D->getPosition()[2] - pcaCenter(2));
478  Eigen::Vector3f pcaToHit = pca.getEigenVectors() * pcaToHitVec;
479 
480  // This sets x,y where x is the longer spread, y the shorter
481  isolatedPointList.emplace_back(pcaToHit(2), pcaToHit(1), hit3D);
482  }
483  }
484 
485  std::cout << "************* Finding best path with A* in cluster *****************"
486  << std::endl;
487  std::cout << "**> There are " << curCluster.size() << " hits, " << isolatedPointList.size()
488  << " isolated hits, the alpha parameter is " << alpha << std::endl;
489  std::cout << "**> PCA len: " << pcaLen << ", wid: " << pcaWidth << ", height: " << pcaHeight
490  << ", ratio: " << pcaHeight / pcaWidth << std::endl;
491 
492  // If no isolated points then nothing to do...
493  if (isolatedPointList.size() > 1) {
494  // Sort the point vec by increasing x, if same then by increasing y.
495  isolatedPointList.sort([](const auto& left, const auto& right) {
496  return (std::abs(std::get<0>(left) - std::get<0>(right)) >
497  std::numeric_limits<float>::epsilon()) ?
498  std::get<0>(left) < std::get<0>(right) :
499  std::get<1>(left) < std::get<1>(right);
500  });
501 
502  // Ok, get the two most distance points...
503  const reco::ClusterHit3D* startHit = std::get<2>(isolatedPointList.front());
504  const reco::ClusterHit3D* stopHit = std::get<2>(isolatedPointList.back());
505 
506  std::cout << "**> Sorted " << isolatedPointList.size()
507  << " hits, longest distance: " << DistanceBetweenNodes(startHit, stopHit)
508  << std::endl;
509 
510  // Call the AStar function to try to find the best path...
511  // AStar(startHit,stopHit,alpha,topNode,clusterParams);
512 
513  float cost(std::numeric_limits<float>::max());
514 
515  LeastCostPath(curEdgeMap[startHit].front(), stopHit, clusterParams, cost);
516 
517  clusterParams.getBestHitPairListPtr().push_front(startHit);
518 
519  std::cout << "**> Best path has " << clusterParams.getBestHitPairListPtr().size()
520  << " hits, " << clusterParams.getBestEdgeList().size() << " edges" << std::endl;
521  }
522  }
523  else {
524  std::cout << "++++++>>> PCA failure! # hits: " << curCluster.size() << std::endl;
525  }
526  }
527 
528  if (m_enableMonitoring) {
529  theClockPathFinding.stop();
530 
531  m_timeVector[PATHFINDING] += theClockPathFinding.accumulated_real_time();
532  }
533 
534  return;
535  }
reco::HitPairListPtr & getBestHitPairListPtr()
Definition: Cluster3D.h:467
bool getSvdOK() const
Definition: Cluster3D.h:240
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:102
void LeastCostPath(const reco::EdgeTuple &, const reco::ClusterHit3D *, reco::ClusterParameters &, float &) const
Find the lowest cost path between two nodes using MST edges.
void PCAAnalysis_3D(const reco::HitPairListPtr &hitPairList, reco::PrincipalComponents &pca, bool skeletonOnly=false) const
bool m_enableMonitoring
Data members to follow.
std::list< ProjectedPoint > ProjectedPointList
Definition: Cluster3D.h:346
constexpr auto abs(T v)
Returns the absolute value of the argument.
reco::EdgeList & getBestEdgeList()
Definition: Cluster3D.h:468
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
Definition: Cluster3D.h:466
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:463
float DistanceBetweenNodes(const reco::ClusterHit3D *, const reco::ClusterHit3D *) const
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
const EigenValues & getEigenValues() const
Definition: Cluster3D.h:242
const Eigen::Vector3f & getAvePosition() const
Definition: Cluster3D.h:244
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:326
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:94
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:339
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:109
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:243
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 76 of file MinSpanTreeAlg_tool.cc.

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

76 { return m_timeVector.at(index); }
void lar_cluster3d::MinSpanTreeAlg::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 640 of file MinSpanTreeAlg_tool.cc.

References reco::ClusterParameters::getBestEdgeList(), reco::ClusterParameters::getBestHitPairListPtr(), and reco::ClusterParameters::getHit3DToEdgeMap().

Referenced by FindBestPathInCluster().

644  {
645  // Recover the mapping between hits and edges
646  reco::Hit3DToEdgeMap& curEdgeMap = clusterParams.getHit3DToEdgeMap();
647 
648  reco::Hit3DToEdgeMap::const_iterator edgeListItr = curEdgeMap.find(std::get<1>(curEdge));
649 
650  showMeTheMoney = std::numeric_limits<float>::max();
651 
652  if (edgeListItr != curEdgeMap.end() && !edgeListItr->second.empty()) {
653  reco::HitPairListPtr& bestNodeList = clusterParams.getBestHitPairListPtr();
654  reco::EdgeList& bestEdgeList = clusterParams.getBestEdgeList();
655 
656  for (const auto& edge : edgeListItr->second) {
657  // skip the self reference
658  if (std::get<1>(edge) == std::get<0>(curEdge)) continue;
659 
660  // Have we found the droid we are looking for?
661  if (std::get<1>(edge) == goalNode) {
662  bestNodeList.push_back(goalNode);
663  bestEdgeList.push_back(edge);
664  showMeTheMoney = std::get<2>(edge);
665  break;
666  }
667 
668  // Keep searching, it is out there somewhere...
669  float currentCost(0.);
670 
671  LeastCostPath(edge, goalNode, clusterParams, currentCost);
672 
673  if (currentCost < std::numeric_limits<float>::max()) {
674  showMeTheMoney = std::get<2>(edge) + currentCost;
675  break;
676  }
677  }
678  }
679 
680  if (showMeTheMoney < std::numeric_limits<float>::max()) {
681  clusterParams.getBestHitPairListPtr().push_front(std::get<1>(curEdge));
682  clusterParams.getBestEdgeList().push_front(curEdge);
683  }
684 
685  return;
686  }
reco::HitPairListPtr & getBestHitPairListPtr()
Definition: Cluster3D.h:467
void LeastCostPath(const reco::EdgeTuple &, const reco::ClusterHit3D *, reco::ClusterParameters &, float &) const
Find the lowest cost path between two nodes using MST edges.
reco::EdgeList & getBestEdgeList()
Definition: Cluster3D.h:468
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
Definition: Cluster3D.h:466
intermediate_table::const_iterator const_iterator
std::list< EdgeTuple > EdgeList
Definition: Cluster3D.h:337
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:326
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:339
void lar_cluster3d::MinSpanTreeAlg::PruneAmbiguousHits ( reco::ClusterParameters clusterParams,
reco::Hit2DToClusterMap hit2DToClusterMap 
) const
private

Prune the obvious ambiguous hits.

Definition at line 765 of file MinSpanTreeAlg_tool.cc.

References reco::ClusterParameters::getHitPairListPtr(), and util::size().

Referenced by getTimeToExecute().

767  {
768 
769  // Recover the HitPairListPtr from the input clusterParams (which will be the
770  // only thing that has been provided)
771  reco::HitPairListPtr& hitPairVector = clusterParams.getHitPairListPtr();
772 
773  size_t nStartedWith(hitPairVector.size());
774  size_t nRejectedHits(0);
775 
776  reco::HitPairListPtr goodHits;
777 
778  // Loop through the hits and try to week out the clearly ambiguous ones
779  for (const auto& hit3D : hitPairVector) {
780  // Loop to try to remove ambiguous hits
781  size_t n2DHitsIn3DHit(0);
782  size_t nThisClusterOnly(0);
783  size_t nOtherCluster(0);
784 
785  // reco::ClusterParameters* otherCluster;
786  const std::set<const reco::ClusterHit3D*>* otherClusterHits = 0;
787 
788  for (const auto& hit2D : hit3D->getHits()) {
789  if (!hit2D) continue;
790 
791  n2DHitsIn3DHit++;
792 
793  if (hit2DToClusterMap[hit2D].size() < 2)
794  nThisClusterOnly = hit2DToClusterMap[hit2D][&clusterParams].size();
795  else {
796  for (const auto& clusterHitMap : hit2DToClusterMap[hit2D]) {
797  if (clusterHitMap.first == &clusterParams) continue;
798 
799  if (clusterHitMap.second.size() > nOtherCluster) {
800  nOtherCluster = clusterHitMap.second.size();
801  // otherCluster = clusterHitMap.first;
802  otherClusterHits = &clusterHitMap.second;
803  }
804  }
805  }
806  }
807 
808  if (n2DHitsIn3DHit < 3 && nThisClusterOnly > 1 && nOtherCluster > 0) {
809  bool skip3DHit(false);
810 
811  for (const auto& otherHit3D : *otherClusterHits) {
812  size_t nOther2DHits(0);
813 
814  for (const auto& otherHit2D : otherHit3D->getHits()) {
815  if (!otherHit2D) continue;
816 
817  nOther2DHits++;
818  }
819 
820  if (nOther2DHits > 2) {
821  skip3DHit = true;
822  nRejectedHits++;
823  break;
824  }
825  }
826 
827  if (skip3DHit) continue;
828  }
829 
830  goodHits.emplace_back(hit3D);
831  }
832 
833  std::cout << "###>> Input " << nStartedWith << " hits, rejected: " << nRejectedHits
834  << std::endl;
835 
836  hitPairVector.resize(goodHits.size());
837  std::copy(goodHits.begin(), goodHits.end(), hitPairVector.begin());
838 
839  return;
840  }
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:463
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:326
void lar_cluster3d::MinSpanTreeAlg::ReconstructBestPath ( const reco::ClusterHit3D goalNode,
BestNodeMap bestNodeMap,
reco::HitPairListPtr pathNodeList,
reco::EdgeList bestEdgeList 
) const
private

Definition at line 619 of file MinSpanTreeAlg_tool.cc.

References DistanceBetweenNodes().

Referenced by AStar().

623  {
624  while (std::get<0>(bestNodeMap.at(goalNode)) != goalNode) {
625  const reco::ClusterHit3D* nextNode = std::get<0>(bestNodeMap[goalNode]);
626  reco::EdgeTuple bestEdge =
627  reco::EdgeTuple(goalNode, nextNode, DistanceBetweenNodes(goalNode, nextNode));
628 
629  pathNodeList.push_front(goalNode);
630  bestEdgeList.push_front(bestEdge);
631 
632  goalNode = nextNode;
633  }
634 
635  pathNodeList.push_front(goalNode);
636 
637  return;
638  }
float DistanceBetweenNodes(const reco::ClusterHit3D *, const reco::ClusterHit3D *) const
std::tuple< const reco::ClusterHit3D *, const reco::ClusterHit3D *, double > EdgeTuple
Definition: Cluster3D.h:336
void lar_cluster3d::MinSpanTreeAlg::RunPrimsAlgorithm ( reco::HitPairList hitPairList,
kdTree::KdTreeNode topNode,
reco::ClusterParametersList clusterParametersList 
) const
private

Driver for Prim's algorithm.

Definition at line 249 of file MinSpanTreeAlg_tool.cc.

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

Referenced by Cluster3DHits(), and getTimeToExecute().

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

Member Data Documentation

std::unique_ptr<lar_cluster3d::IClusterParametersBuilder> lar_cluster3d::MinSpanTreeAlg::m_clusterBuilder
private

Common cluster builder tool.

Definition at line 154 of file MinSpanTreeAlg_tool.cc.

Referenced by Cluster3DHits(), and configure().

bool lar_cluster3d::MinSpanTreeAlg::m_enableMonitoring
private

Data members to follow.

Definition at line 144 of file MinSpanTreeAlg_tool.cc.

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

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

Definition at line 148 of file MinSpanTreeAlg_tool.cc.

Referenced by configure().

kdTree lar_cluster3d::MinSpanTreeAlg::m_kdTree
private

Definition at line 151 of file MinSpanTreeAlg_tool.cc.

Referenced by Cluster3DHits(), and RunPrimsAlgorithm().

PrincipalComponentsAlg lar_cluster3d::MinSpanTreeAlg::m_pcaAlg
private

Definition at line 150 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 146 of file MinSpanTreeAlg_tool.cc.

Referenced by CheckHitSorting(), and configure().


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