Public Member Functions | Private Types | Private Member Functions | Private Attributes | List of all members
lar_cluster3d::MinSpanTreeAlg Class Reference
Inheritance diagram for lar_cluster3d::MinSpanTreeAlg:
lar_cluster3d::IClusterAlg

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...
 
- Public Member Functions inherited from lar_cluster3d::IClusterAlg
virtual ~IClusterAlg () noexcept=default
 Virtual Destructor. 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::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...
 

Additional Inherited Members

- Public Types inherited from lar_cluster3d::IClusterAlg
enum  TimeValues {
  BUILDTHREEDHITS = 0, BUILDHITTOHITMAP = 1, RUNDBSCAN = 2, BUILDCLUSTERINFO = 3,
  PATHFINDING = 4, NUMTIMEVALUES
}
 enumerate the possible values for time checking if monitoring timing More...
 

Detailed Description

Definition at line 43 of file MinSpanTreeAlg_tool.cc.

Member Typedef Documentation

Definition at line 111 of file MinSpanTreeAlg_tool.cc.

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

Definition at line 110 of file MinSpanTreeAlg_tool.cc.

Definition at line 131 of file MinSpanTreeAlg_tool.cc.

define data structure for keeping track of channel status

Definition at line 130 of file MinSpanTreeAlg_tool.cc.

Constructor & Destructor Documentation

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

Constructor.

Parameters
pset

Definition at line 148 of file MinSpanTreeAlg_tool.cc.

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

Destructor.

Definition at line 157 of file MinSpanTreeAlg_tool.cc.

158 {
159 }

Member Function Documentation

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

Algorithm to find shortest path between two 3D hits.

Definition at line 533 of file MinSpanTreeAlg_tool.cc.

538 {
539  // Recover the list of hits and edges
540  reco::HitPairListPtr& pathNodeList = clusterParams.getBestHitPairListPtr();
541  reco::EdgeList& bestEdgeList = clusterParams.getBestEdgeList();
542  reco::Hit3DToEdgeMap& curEdgeMap = clusterParams.getHit3DToEdgeMap();
543 
544  // Find the shortest path from start to goal using an A* algorithm
545  // Keep track of the nodes which have already been evaluated
546  reco::HitPairListPtr closedList;
547 
548  // Keep track of the nodes that have been "discovered" but yet to be evaluated
549  reco::HitPairListPtr openList = {startNode};
550 
551  // Create a map which, for each node, will tell us the node it can be most efficiencly reached from.
552  BestNodeMap bestNodeMap;
553 
554  bestNodeMap[startNode] = BestNodeTuple(startNode,0.,DistanceBetweenNodes(startNode,goalNode));
555 
556  alpha = 1.; //std::max(0.5,alpha);
557 
558  while(!openList.empty())
559  {
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(openList.begin(),openList.end(),[bestNodeMap](const auto& next, const auto& best){return std::get<2>(bestNodeMap.at(next)) < std::get<2>(bestNodeMap.at(best));});
566 
567  // Easier to deal directly with the pointer to the node
568  const reco::ClusterHit3D* currentNode = *currentNodeItr;
569 
570  // Check to see if we have reached the goal and need to evaluate the path
571  if (currentNode == goalNode)
572  {
573  // The path reconstruction will
574  ReconstructBestPath(goalNode, bestNodeMap, pathNodeList, bestEdgeList);
575 
576  break;
577  }
578 
579  // Otherwise need to keep evaluating
580  else
581  {
582  openList.erase(currentNodeItr);
584 
585  // Get tuple values for the current node
586  const BestNodeTuple& currentNodeTuple = bestNodeMap.at(currentNode);
587  float currentNodeScore = std::get<1>(currentNodeTuple);
588 
589  // Recover the edges associated to the current point
590  const reco::EdgeList& curEdgeList = curEdgeMap[currentNode];
591 
592  for(const auto& curEdge : curEdgeList)
593  {
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())
604  {
605  openList.push_back(candHit3D);
606  }
607  else if (tentative_gScore > std::get<1>(candNodeItr->second)) continue;
608 
609  // Make a guess at score to get to target...
610  float guessToTarget = DistanceBetweenNodes(candHit3D,goalNode) / 0.3;
611 
612  bestNodeMap[candHit3D] = BestNodeTuple(currentNode,tentative_gScore, tentative_gScore + guessToTarget);
613  }
614  }
615  }
616 
617  return;
618 }
reco::HitPairListPtr & getBestHitPairListPtr()
Definition: Cluster3D.h:480
intermediate_table::iterator iterator
std::tuple< const reco::ClusterHit3D *, float, float > BestNodeTuple
reco::EdgeList & getBestEdgeList()
Definition: Cluster3D.h:481
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
Definition: Cluster3D.h:479
float DistanceBetweenNodes(const reco::ClusterHit3D *, const reco::ClusterHit3D *) const
unsigned int getStatusBits() const
Definition: Cluster3D.h:157
std::list< EdgeTuple > EdgeList
Definition: Cluster3D.h:345
std::unordered_map< const reco::ClusterHit3D *, BestNodeTuple > BestNodeMap
double alpha
Definition: doAna.cpp:15
Path checking algorithm has seen this hit.
Definition: Cluster3D.h:111
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:335
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:347
void ReconstructBestPath(const reco::ClusterHit3D *, BestNodeMap &, reco::HitPairListPtr &, reco::EdgeList &) const
void setStatusBit(unsigned bits) const
Definition: Cluster3D.h:180
void lar_cluster3d::MinSpanTreeAlg::CheckHitSorting ( reco::ClusterParameters clusterParams) const
private

Definition at line 901 of file MinSpanTreeAlg_tool.cc.

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

210 {
211  /**
212  * @brief Driver for processing input 2D hits, transforming to 3D hits and building lists
213  * of associated 3D hits (candidate 3D clusters)
214  */
215 
216  // Zero the time vector
217  if (m_enableMonitoring) std::fill(m_timeVector.begin(),m_timeVector.end(),0.);
218 
219  // DBScan is driven of its "epsilon neighborhood". Computing adjacency within DBScan can be time
220  // consuming so the idea is the prebuild the adjaceny map and then run DBScan.
221  // The following call does this work
222  kdTree::KdTreeNodeList kdTreeNodeContainer;
223  kdTree::KdTreeNode topNode = m_kdTree.BuildKdTree(hitPairList, kdTreeNodeContainer);
224 
226 
227  // Run DBScan to get candidate clusters
228  RunPrimsAlgorithm(hitPairList, topNode, clusterParametersList);
229 
230  // Initial clustering is done, now trim the list and get output parameters
231  cet::cpu_timer theClockBuildClusters;
232 
233  // Start clocks if requested
234  if (m_enableMonitoring) theClockBuildClusters.start();
235 
236  m_clusterBuilder->BuildClusterInfo(clusterParametersList);
237 
238  if (m_enableMonitoring)
239  {
240  theClockBuildClusters.stop();
241 
242  m_timeVector[BUILDCLUSTERINFO] = theClockBuildClusters.accumulated_real_time();
243  }
244 
245  // Test run the path finding algorithm
246  for (auto& clusterParams : clusterParametersList) FindBestPathInCluster(clusterParams, topNode);
247 
248  mf::LogDebug("MinSpanTreeAlg") << ">>>>> Cluster3DHits done, found " << clusterParametersList.size() << " clusters" << std::endl;
249 
250  return;
251 }
bool m_enableMonitoring
Data members to follow.
std::list< KdTreeNode > KdTreeNodeList
Definition: kdTree.h:67
void RunPrimsAlgorithm(reco::HitPairList &, kdTree::KdTreeNode &, reco::ClusterParametersList &) const
Driver for Prim&#39;s algorithm.
std::unique_ptr< lar_cluster3d::IClusterParametersBuilder > m_clusterBuilder
Common cluster builder tool.
def fill(s)
Definition: translator.py:93
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
double accumulated_real_time() const
Definition: cpu_timer.cc:66
float getTimeToExecute() const
Definition: kdTree.h:95
KdTreeNode & BuildKdTree(Hit3DVec::iterator, Hit3DVec::iterator, KdTreeNodeList &, int depth=0) const
Given an input set of ClusterHit3D objects, build a kd tree structure.
Definition: kdTree.cxx:112
void start()
Definition: cpu_timer.cc:83
QTextStream & endl(QTextStream &s)
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 70 of file MinSpanTreeAlg_tool.cc.

71  {return;}
void lar_cluster3d::MinSpanTreeAlg::configure ( fhicl::ParameterSet const &  pset)
override

Definition at line 163 of file MinSpanTreeAlg_tool.cc.

164 {
165  m_enableMonitoring = pset.get<bool> ("EnableMonitoring", true );
166 
168 
169  m_geometry = &*geometry;
170 
171  m_timeVector.resize(NUMTIMEVALUES, 0.);
172 
173  // Determine the unit directon and normal vectors to the wires
174  m_wireDir.resize(3);
175 
176  raw::ChannelID_t uChannel(0);
177  std::vector<geo::WireID> uWireID = m_geometry->ChannelToWire(uChannel);
178  const geo::WireGeo* uWireGeo = m_geometry->WirePtr(uWireID[0]);
179 
180  TVector3 uWireDir = uWireGeo->Direction();
181 
182  m_wireDir[0].resize(3);
183  m_wireDir[0][0] = uWireDir[0];
184  m_wireDir[0][1] = -uWireDir[2];
185  m_wireDir[0][2] = uWireDir[1];
186 
187  raw::ChannelID_t vChannel(2400);
188  std::vector<geo::WireID> vWireID = m_geometry->ChannelToWire(vChannel);
189  const geo::WireGeo* vWireGeo = m_geometry->WirePtr(vWireID[0]);
190 
191  TVector3 vWireDir = vWireGeo->Direction();
192 
193  m_wireDir[1].resize(3);
194  m_wireDir[1][0] = vWireDir[0];
195  m_wireDir[1][1] = -vWireDir[2];
196  m_wireDir[1][2] = vWireDir[1];
197 
198  m_wireDir[2].resize(3);
199  m_wireDir[2][0] = 0.;
200  m_wireDir[2][1] = 0.;
201  m_wireDir[2][2] = 1.;
202 
203  m_clusterBuilder = art::make_tool<lar_cluster3d::IClusterParametersBuilder>(pset.get<fhicl::ParameterSet>("ClusterParamsBuilder"));
204 
205  return;
206 }
Geometry description of a TPC wireThe wire is a single straight segment on a wire plane...
Definition: WireGeo.h:65
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.
std::unique_ptr< lar_cluster3d::IClusterParametersBuilder > m_clusterBuilder
Common cluster builder tool.
Vector Direction() const
Definition: WireGeo.h:587
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
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 722 of file MinSpanTreeAlg_tool.cc.

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

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

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  {
397  if (!curEdgeMap[hit].empty() && curEdgeMap[hit].size() == 1)
398  {
399  float quality(0.);
400 
401  reco::HitPairListPtr tempList = DepthFirstSearch(curEdgeMap[hit].front(), curEdgeMap, quality);
402 
403  tempList.push_front(std::get<0>(curEdgeMap[hit].front()));
404 
405  if (quality > bestQuality)
406  {
407  longestCluster = tempList;
408  bestQuality = quality;
409  }
410 
411  nIsolatedHits++;
412  }
413 
414  aveNumEdges += float(curEdgeMap[hit].size());
415  maxNumEdges = std::max(maxNumEdges,curEdgeMap[hit].size());
416  }
417 
418  aveNumEdges /= float(hitPairList.size());
419  std::cout << "----> # isolated hits: " << nIsolatedHits << ", longest branch: " << longestCluster.size() << ", cluster size: " << hitPairList.size() << ", ave # edges: " << aveNumEdges << ", max: " << maxNumEdges << std::endl;
420 
421  if (!longestCluster.empty())
422  {
423  hitPairList = longestCluster;
424  for(const auto& hit : hitPairList)
425  {
426  for(const auto& edge : curEdgeMap[hit]) bestEdgeList.emplace_back(edge);
427  }
428 
429  std::cout << " ====> new cluster size: " << hitPairList.size() << std::endl;
430  }
431 
432  if (m_enableMonitoring)
433  {
434  theClockPathFinding.stop();
435 
436  m_timeVector[PATHFINDING] += theClockPathFinding.accumulated_real_time();
437  }
438 
439  return;
440 }
bool m_enableMonitoring
Data members to follow.
reco::EdgeList & getBestEdgeList()
Definition: Cluster3D.h:481
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
Definition: Cluster3D.h:479
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:476
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
std::list< EdgeTuple > EdgeList
Definition: Cluster3D.h:345
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:335
static int max(int a, int b)
Detector simulation of raw signals on wires.
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:347
double accumulated_real_time() const
Definition: cpu_timer.cc:66
void start()
Definition: cpu_timer.cc:83
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:97
QTextStream & endl(QTextStream &s)
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 442 of file MinSpanTreeAlg_tool.cc.

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  {
453  // Get references to what we need....
454  reco::HitPairListPtr& curCluster = clusterParams.getHitPairListPtr();
455  reco::Hit3DToEdgeMap& curEdgeMap = clusterParams.getHit3DToEdgeMap();
456 
457  // Do a quick PCA to determine our parameter "alpha"
459  m_pcaAlg.PCAAnalysis_3D(curCluster, pca);
460 
461  // The chances of a failure are remote, still we should check
462  if (pca.getSvdOK())
463  {
464  float pcaLen = 3.0*sqrt(pca.getEigenValues()[2]);
465  float pcaWidth = 3.0*sqrt(pca.getEigenValues()[1]);
466  float pcaHeight = 3.0*sqrt(pca.getEigenValues()[0]);
467  const Eigen::Vector3f& pcaCenter = pca.getAvePosition();
468  float alpha = std::min(float(1.),std::max(float(0.001),pcaWidth/pcaLen));
469 
470  // Create a temporary container for the isolated points
471  reco::ProjectedPointList isolatedPointList;
472 
473  // Go through and find the isolated points, for those get the projection to the plane of maximum spread
474  for(const auto& hit3D : curCluster)
475  {
476  // the definition of an isolated hit is that it only has one associated edge
477  if (!curEdgeMap[hit3D].empty() && curEdgeMap[hit3D].size() == 1)
478  {
479  Eigen::Vector3f pcaToHitVec(hit3D->getPosition()[0] - pcaCenter(0),
480  hit3D->getPosition()[1] - pcaCenter(1),
481  hit3D->getPosition()[2] - pcaCenter(2));
482  Eigen::Vector3f pcaToHit = pca.getEigenVectors() * pcaToHitVec;
483 
484  // This sets x,y where x is the longer spread, y the shorter
485  isolatedPointList.emplace_back(pcaToHit(2),pcaToHit(1),hit3D);
486  }
487  }
488 
489  std::cout << "************* Finding best path with A* in cluster *****************" << std::endl;
490  std::cout << "**> There are " << curCluster.size() << " hits, " << isolatedPointList.size() << " isolated hits, the alpha parameter is " << alpha << std::endl;
491  std::cout << "**> PCA len: " << pcaLen << ", wid: " << pcaWidth << ", height: " << pcaHeight << ", ratio: " << pcaHeight/pcaWidth << std::endl;
492 
493  // If no isolated points then nothing to do...
494  if (isolatedPointList.size() > 1)
495  {
496  // Sort the point vec by increasing x, if same then by increasing y.
497  isolatedPointList.sort([](const auto& left, const auto& right){return (std::abs(std::get<0>(left) - std::get<0>(right)) > std::numeric_limits<float>::epsilon()) ? std::get<0>(left) < std::get<0>(right) : std::get<1>(left) < std::get<1>(right);});
498 
499  // Ok, get the two most distance points...
500  const reco::ClusterHit3D* startHit = std::get<2>(isolatedPointList.front());
501  const reco::ClusterHit3D* stopHit = std::get<2>(isolatedPointList.back());
502 
503  std::cout << "**> Sorted " << isolatedPointList.size() << " hits, longest distance: " << DistanceBetweenNodes(startHit,stopHit) << std::endl;
504 
505  // Call the AStar function to try to find the best path...
506 // AStar(startHit,stopHit,alpha,topNode,clusterParams);
507 
508  float cost(std::numeric_limits<float>::max());
509 
510  LeastCostPath(curEdgeMap[startHit].front(),stopHit,clusterParams,cost);
511 
512  clusterParams.getBestHitPairListPtr().push_front(startHit);
513 
514  std::cout << "**> Best path has " << clusterParams.getBestHitPairListPtr().size() << " hits, " << clusterParams.getBestEdgeList().size() << " edges" << std::endl;
515  }
516  }
517  else
518  {
519  std::cout << "++++++>>> PCA failure! # hits: " << curCluster.size() << std::endl;
520  }
521  }
522 
523  if (m_enableMonitoring)
524  {
525  theClockPathFinding.stop();
526 
527  m_timeVector[PATHFINDING] += theClockPathFinding.accumulated_real_time();
528  }
529 
530  return;
531 }
reco::HitPairListPtr & getBestHitPairListPtr()
Definition: Cluster3D.h:480
bool getSvdOK() const
Definition: Cluster3D.h:244
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:353
reco::EdgeList & getBestEdgeList()
Definition: Cluster3D.h:481
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
Definition: Cluster3D.h:479
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:476
float DistanceBetweenNodes(const reco::ClusterHit3D *, const reco::ClusterHit3D *) const
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
T abs(T value)
const EigenValues & getEigenValues() const
Definition: Cluster3D.h:246
const Eigen::Vector3f & getAvePosition() const
Definition: Cluster3D.h:248
double alpha
Definition: doAna.cpp:15
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:335
static int max(int a, int b)
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:347
double accumulated_real_time() const
Definition: cpu_timer.cc:66
void start()
Definition: cpu_timer.cc:83
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:97
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:247
QTextStream & endl(QTextStream &s)
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.

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 641 of file MinSpanTreeAlg_tool.cc.

645 {
646  // Recover the mapping between hits and edges
647  reco::Hit3DToEdgeMap& curEdgeMap = clusterParams.getHit3DToEdgeMap();
648 
649  reco::Hit3DToEdgeMap::const_iterator edgeListItr = curEdgeMap.find(std::get<1>(curEdge));
650 
651  showMeTheMoney = std::numeric_limits<float>::max();
652 
653  if (edgeListItr != curEdgeMap.end() && !edgeListItr->second.empty())
654  {
655  reco::HitPairListPtr& bestNodeList = clusterParams.getBestHitPairListPtr();
656  reco::EdgeList& bestEdgeList = clusterParams.getBestEdgeList();
657 
658  for(const auto& edge : edgeListItr->second)
659  {
660  // skip the self reference
661  if (std::get<1>(edge) == std::get<0>(curEdge)) continue;
662 
663  // Have we found the droid we are looking for?
664  if (std::get<1>(edge) == goalNode)
665  {
666  bestNodeList.push_back(goalNode);
667  bestEdgeList.push_back(edge);
668  showMeTheMoney = std::get<2>(edge);
669  break;
670  }
671 
672  // Keep searching, it is out there somewhere...
673  float currentCost(0.);
674 
675  LeastCostPath(edge,goalNode,clusterParams,currentCost);
676 
677  if (currentCost < std::numeric_limits<float>::max())
678  {
679  showMeTheMoney = std::get<2>(edge) + currentCost;
680  break;
681  }
682  }
683  }
684 
685  if (showMeTheMoney < std::numeric_limits<float>::max())
686  {
687  clusterParams.getBestHitPairListPtr().push_front(std::get<1>(curEdge));
688  clusterParams.getBestEdgeList().push_front(curEdge);
689  }
690 
691  return;
692 }
reco::HitPairListPtr & getBestHitPairListPtr()
Definition: Cluster3D.h:480
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:481
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
Definition: Cluster3D.h:479
intermediate_table::const_iterator const_iterator
std::list< EdgeTuple > EdgeList
Definition: Cluster3D.h:345
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:335
static int max(int a, int b)
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:347
void lar_cluster3d::MinSpanTreeAlg::PruneAmbiguousHits ( reco::ClusterParameters clusterParams,
reco::Hit2DToClusterMap hit2DToClusterMap 
) const
private

Prune the obvious ambiguous hits.

Definition at line 768 of file MinSpanTreeAlg_tool.cc.

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

Definition at line 620 of file MinSpanTreeAlg_tool.cc.

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

Driver for Prim's algorithm.

Definition at line 254 of file MinSpanTreeAlg_tool.cc.

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

Member Data Documentation

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

Common cluster builder tool.

Definition at line 145 of file MinSpanTreeAlg_tool.cc.

bool lar_cluster3d::MinSpanTreeAlg::m_enableMonitoring
private

Data members to follow.

Definition at line 136 of file MinSpanTreeAlg_tool.cc.

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

Definition at line 140 of file MinSpanTreeAlg_tool.cc.

kdTree lar_cluster3d::MinSpanTreeAlg::m_kdTree
private

Definition at line 143 of file MinSpanTreeAlg_tool.cc.

PrincipalComponentsAlg lar_cluster3d::MinSpanTreeAlg::m_pcaAlg
private

Definition at line 142 of file MinSpanTreeAlg_tool.cc.

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

Definition at line 137 of file MinSpanTreeAlg_tool.cc.

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

Definition at line 138 of file MinSpanTreeAlg_tool.cc.


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