LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
lar_cluster3d::VoronoiPathFinder Class Referenceabstract
Inheritance diagram for lar_cluster3d::VoronoiPathFinder:
lar_cluster3d::IClusterModAlg

Public Member Functions

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

Private Types

using Point = std::tuple< float, float, const reco::ClusterHit3D * >
 
using PointList = std::list< Point >
 
using MinMaxPoints = std::pair< Point, Point >
 
using MinMaxPointPair = std::pair< MinMaxPoints, MinMaxPoints >
 

Private Member Functions

reco::ClusterParametersList::iterator breakIntoTinyBits (reco::ClusterParameters &cluster, reco::PrincipalComponents &lastPCA, reco::ClusterParametersList::iterator positionItr, reco::ClusterParametersList &outputClusterList, int level=0) const
 Use PCA to try to find path in cluster. More...
 
reco::ClusterParametersList::iterator subDivideCluster (reco::ClusterParameters &cluster, reco::PrincipalComponents &lastPCA, reco::ClusterParametersList::iterator positionItr, reco::ClusterParametersList &outputClusterList, int level=0) const
 Use PCA to try to find path in cluster. More...
 
bool makeCandidateCluster (Eigen::Vector3f &, reco::ClusterParameters &, reco::HitPairListPtr::iterator, reco::HitPairListPtr::iterator, int) const
 
float closestApproach (const Eigen::Vector3f &, const Eigen::Vector3f &, const Eigen::Vector3f &, const Eigen::Vector3f &, Eigen::Vector3f &, Eigen::Vector3f &) const
 
void buildConvexHull (reco::ClusterParameters &clusterParameters, int level=0) const
 
void buildVoronoiDiagram (reco::ClusterParameters &clusterParameters, int level=0) const
 
float findConvexHullEndPoints (const reco::EdgeList &, const reco::ClusterHit3D *, const reco::ClusterHit3D *) const
 

Private Attributes

bool fEnableMonitoring
 FHICL parameters. More...
 
size_t fMinTinyClusterSize
 Minimum size for a "tiny" cluster. More...
 
float fTimeToProcess
 
bool fFillHistograms
 Histogram definitions. More...
 
TH1F * fTopNum3DHits
 
TH1F * fTopNumEdges
 
TH1F * fTopEigen21Ratio
 
TH1F * fTopEigen20Ratio
 
TH1F * fTopEigen10Ratio
 
TH1F * fTopPrimaryLength
 
TH1F * fSubNum3DHits
 
TH1F * fSubNumEdges
 
TH1F * fSubEigen21Ratio
 
TH1F * fSubEigen20Ratio
 
TH1F * fSubEigen10Ratio
 
TH1F * fSubPrimaryLength
 
TH1F * fSubCosToPrevPCA
 
TH1F * fSubCosExtToPCA
 
TH1F * fSubMaxDefect
 
TH1F * fSubUsedDefect
 
geo::GeometryfGeometry
 Tools. More...
 
std::unique_ptr< lar_cluster3d::IClusterAlgfClusterAlg
 Algorithm to do 3D space point clustering. More...
 
PrincipalComponentsAlg fPCAAlg
 

Detailed Description

Definition at line 50 of file VoronoiPathFinder_tool.cc.

Member Typedef Documentation

Definition at line 129 of file VoronoiPathFinder_tool.cc.

using lar_cluster3d::VoronoiPathFinder::Point = std::tuple<float,float,const reco::ClusterHit3D*>
private

Definition at line 127 of file VoronoiPathFinder_tool.cc.

Definition at line 128 of file VoronoiPathFinder_tool.cc.

Constructor & Destructor Documentation

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

Constructor.

Parameters
pset

Definition at line 175 of file VoronoiPathFinder_tool.cc.

References configure().

175  :
176  fPCAAlg(pset.get<fhicl::ParameterSet>("PrincipalComponentsAlg"))
177 {
178  this->configure(pset);
179 }
void configure(fhicl::ParameterSet const &pset) override
lar_cluster3d::VoronoiPathFinder::~VoronoiPathFinder ( )

Destructor.

Definition at line 183 of file VoronoiPathFinder_tool.cc.

184 {
185 }

Member Function Documentation

reco::ClusterParametersList::iterator lar_cluster3d::VoronoiPathFinder::breakIntoTinyBits ( reco::ClusterParameters cluster,
reco::PrincipalComponents lastPCA,
reco::ClusterParametersList::iterator  positionItr,
reco::ClusterParametersList outputClusterList,
int  level = 0 
) const
private

Use PCA to try to find path in cluster.

Parameters
clusterParametersThe given cluster parameters object to try to split
clusterParametersListThe list of clusters

Definition at line 348 of file VoronoiPathFinder_tool.cc.

References buildConvexHull(), fFillHistograms, fMinTinyClusterSize, fPCAAlg, fSubCosToPrevPCA, fSubEigen10Ratio, fSubEigen20Ratio, fSubEigen21Ratio, fSubNum3DHits, fSubNumEdges, fSubPrimaryLength, reco::PrincipalComponents::getAveHitDoca(), reco::PrincipalComponents::getAvePosition(), reco::ClusterParameters::getBestEdgeList(), reco::ClusterParameters::getConvexHull(), reco::ConvexHull::getConvexHullExtremePoints(), reco::PrincipalComponents::getEigenValues(), reco::PrincipalComponents::getEigenVectors(), reco::ClusterParameters::getFullPCA(), reco::ClusterParameters::getHitPairListPtr(), reco::PrincipalComponents::getNumHitsUsed(), reco::ClusterHit3D::getPosition(), reco::ClusterParameters::getSkeletonPCA(), reco::PrincipalComponents::getSvdOK(), art::detail::indent(), art::left(), min, lar_cluster3d::PrincipalComponentsAlg::PCAAnalysis_3D(), lar_cluster3d::PrincipalComponentsAlg::PCAAnalysis_calc3DDocas(), art::right(), reco::ClusterParameters::UpdateParameters(), and reco::ClusterHit2D::USED.

Referenced by getTimeToExecute().

353 {
354  // This needs to be a recursive routine...
355  // Idea is to take the input cluster and order 3D hits by arclength along PCA primary axis
356  // If the cluster is above the minimum number of hits then we divide into two and call ourself
357  // with the two halves. This means we form a new cluster with hits and PCA and then call ourself
358  // If the cluster is below the minimum then we can't break any more, simply add this cluster to
359  // the new output list.
360 
361  // set an indention string
362  std::string pluses(level/2, '+');
363  std::string indent(level/2, ' ');
364 
365  indent += pluses;
366 
367  reco::ClusterParametersList::iterator inputPositionItr = positionItr;
368 
369  // To make best use of this we'll also want the PCA for this cluster... so...
370  // Recover the prime ingredients
371  reco::PrincipalComponents& fullPCA = clusterToBreak.getFullPCA();
372  std::vector<double> eigenValVec = {3. * std::sqrt(fullPCA.getEigenValues()[0]),
373  3. * std::sqrt(fullPCA.getEigenValues()[1]),
374  3. * std::sqrt(fullPCA.getEigenValues()[2])};
375  Eigen::Vector3f fullPrimaryVec(fullPCA.getEigenVectors()[0][0],fullPCA.getEigenVectors()[0][1],fullPCA.getEigenVectors()[0][2]);
376  Eigen::Vector3f lastPrimaryVec(lastPCA.getEigenVectors()[0][0],lastPCA.getEigenVectors()[0][1],lastPCA.getEigenVectors()[0][2]);
377 
378  double cosNewToLast = std::abs(fullPrimaryVec.dot(lastPrimaryVec));
379  double eigen2To1Ratio = eigenValVec[2] / eigenValVec[1];
380  double eigen1To0Ratio = eigenValVec[1] / eigenValVec[0];
381  double eigen2To0Ratio = eigenValVec[2] / eigenValVec[0];
382  double eigen2And1Ave = 0.5 * (eigenValVec[1] + eigenValVec[2]);
383  double eigenAveTo0Ratio = eigen2And1Ave / eigenValVec[0];
384 
385  bool storeCurrentCluster(true);
386  int minimumClusterSize(fMinTinyClusterSize);
387 
388  std::cout << indent << ">>> breakIntoTinyBits with " << clusterToBreak.getHitPairListPtr().size() << " input hits, " << clusterToBreak.getBestEdgeList().size() << " edges, rat21: " << eigen2To1Ratio << ", rat20: " << eigen2To0Ratio << ", rat10: " << eigen1To0Ratio << ", ave0: " << eigenAveTo0Ratio << std::endl;
389  std::cout << indent << " --> eigen 0/1/2: " << eigenValVec[0] << "/" << eigenValVec[1] << "/" << eigenValVec[2] << ", cos: " << cosNewToLast << std::endl;
390 
391  // Create a rough cut intended to tell us when we've reached the land of diminishing returns
392  if (clusterToBreak.getBestEdgeList().size() > 5 && cosNewToLast > 0.25 && eigen2To1Ratio < 0.9 && eigen2To0Ratio > 0.001 &&
393  clusterToBreak.getHitPairListPtr().size() > size_t(2 * minimumClusterSize))
394  {
395  // We want to find the convex hull vertices that lie furthest from the line to/from the extreme points
396  // To find these we:
397  // 1) recover the extreme points
398  // 2) form the vector between them
399  // 3) loop through the vertices and keep track of distance to this vector
400  // 4) Sort the resulting list by furthest points and select the one we want
401  reco::ProjectedPointList::const_iterator extremePointListItr = clusterToBreak.getConvexHull().getConvexHullExtremePoints().begin();
402 
403  const reco::ClusterHit3D* firstEdgeHit = std::get<2>(*extremePointListItr++);
404  const reco::ClusterHit3D* secondEdgeHit = std::get<2>(*extremePointListItr);
405  Eigen::Vector3f edgeVec(secondEdgeHit->getPosition()[0] - firstEdgeHit->getPosition()[0],
406  secondEdgeHit->getPosition()[1] - firstEdgeHit->getPosition()[1],
407  secondEdgeHit->getPosition()[2] - firstEdgeHit->getPosition()[2]);
408  double edgeLen = edgeVec.norm();
409 
410  // normalize it
411  edgeVec.normalize();
412 
413  // Recover the list of 3D hits associated to this cluster
414  reco::HitPairListPtr& clusHitPairVector = clusterToBreak.getHitPairListPtr();
415 
416  // Calculate the doca to the PCA primary axis for each 3D hit
417  // Importantly, this also gives us the arclength along that axis to the hit
418  fPCAAlg.PCAAnalysis_calc3DDocas(clusHitPairVector, fullPCA);
419 
420  // Sort the hits along the PCA
421  clusHitPairVector.sort([](const auto& left, const auto& right){return left->getArclenToPoca() < right->getArclenToPoca();});
422 
423  // Set up container to keep track of edges
424  using DistEdgeTuple = std::tuple<float, const reco::EdgeTuple*>;
425  using DistEdgeTupleVec = std::vector<DistEdgeTuple>;
426 
427  DistEdgeTupleVec distEdgeTupleVec;
428 
429  // Now loop through all the edges and search for the furthers point
430  for(const auto& edge : clusterToBreak.getBestEdgeList())
431  {
432  const reco::ClusterHit3D* nextEdgeHit = std::get<0>(edge); // recover the first point
433 
434  // Create vector to this point from the longest edge
435  Eigen::Vector3f hitToEdgeVec(nextEdgeHit->getPosition()[0] - firstEdgeHit->getPosition()[0],
436  nextEdgeHit->getPosition()[1] - firstEdgeHit->getPosition()[1],
437  nextEdgeHit->getPosition()[2] - firstEdgeHit->getPosition()[2]);
438 
439  // Get projection
440  float hitProjection = hitToEdgeVec.dot(edgeVec);
441 
442  // Require that the point is really "opposite" the longest edge
443  if (hitProjection > 0. && hitProjection < edgeLen)
444  {
445  Eigen::Vector3f distToHitVec = hitToEdgeVec - hitProjection * edgeVec;
446  float distToHit = distToHitVec.norm();
447 
448  distEdgeTupleVec.emplace_back(distToHit,&edge);
449  }
450  }
451 
452  std::sort(distEdgeTupleVec.begin(),distEdgeTupleVec.end(),[](const auto& left,const auto& right){return std::get<0>(left) > std::get<0>(right);});
453 
454  for(const auto& distEdgeTuple : distEdgeTupleVec)
455  {
456  const reco::EdgeTuple& edgeTuple = *std::get<1>(distEdgeTuple);
457  const reco::ClusterHit3D* edgeHit = std::get<0>(edgeTuple);
458 
459  // Now find the hit identified above as furthest away
460  reco::HitPairListPtr::iterator vertexItr = std::find(clusHitPairVector.begin(),clusHitPairVector.end(),edgeHit);
461 
462  // Make sure enough hits either side, otherwise we just keep the current cluster
463  if (vertexItr == clusHitPairVector.end() || std::distance(clusHitPairVector.begin(),vertexItr) < minimumClusterSize || std::distance(vertexItr,clusHitPairVector.end()) < minimumClusterSize) continue;
464 
465  // Now we create a list of pairs of iterators to the start and end of each subcluster
466  using Hit3DItrPair = std::pair<reco::HitPairListPtr::iterator,reco::HitPairListPtr::iterator>;
467  using VertexPairList = std::list<Hit3DItrPair>;
468 
469  VertexPairList vertexPairList;
470 
471  vertexPairList.emplace_back(Hit3DItrPair(clusHitPairVector.begin(),vertexItr));
472  vertexPairList.emplace_back(Hit3DItrPair(vertexItr,clusHitPairVector.end()));
473 
474  storeCurrentCluster = false;
475 
476  // Ok, now loop through our pairs
477  for(auto& hit3DItrPair : vertexPairList)
478  {
479  reco::ClusterParameters clusterParams;
480  reco::HitPairListPtr& hitPairListPtr = clusterParams.getHitPairListPtr();
481 
482  std::cout << indent << "+> -- building new cluster, size: " << std::distance(hit3DItrPair.first,hit3DItrPair.second) << std::endl;
483 
484  // size the container...
485  hitPairListPtr.resize(std::distance(hit3DItrPair.first,hit3DItrPair.second));
486 
487  // and copy the hits into the container
488  std::copy(hit3DItrPair.first,hit3DItrPair.second,hitPairListPtr.begin());
489 
490  // First stage of feature extraction runs here
491  fPCAAlg.PCAAnalysis_3D(hitPairListPtr, clusterParams.getFullPCA());
492 
493  // Recover the new fullPCA
494  reco::PrincipalComponents& newFullPCA = clusterParams.getFullPCA();
495 
496  // Must have a valid pca
497  if (newFullPCA.getSvdOK())
498  {
499  std::cout << indent << "+> -- >> cluster has a valid Full PCA" << std::endl;
500 
501  // Need to check if the PCA direction has been reversed
502  Eigen::Vector3f newPrimaryVec(newFullPCA.getEigenVectors()[0][0],newFullPCA.getEigenVectors()[0][1],newFullPCA.getEigenVectors()[0][2]);
503 
504  // If the PCA's are opposite the flip the axes
505  if (fullPrimaryVec.dot(newPrimaryVec) < 0.)
506  {
508 
509  eigenVectors.resize(3);
510 
511  for(size_t vecIdx = 0; vecIdx < 3; vecIdx++)
512  {
513  eigenVectors[vecIdx].resize(3,0.);
514 
515  eigenVectors[vecIdx][0] = -newFullPCA.getEigenVectors()[vecIdx][0];
516  eigenVectors[vecIdx][1] = -newFullPCA.getEigenVectors()[vecIdx][1];
517  eigenVectors[vecIdx][2] = -newFullPCA.getEigenVectors()[vecIdx][2];
518  }
519 
520  newFullPCA = reco::PrincipalComponents(true,
521  newFullPCA.getNumHitsUsed(),
522  newFullPCA.getEigenValues(),
523  eigenVectors,
524  newFullPCA.getAvePosition(),
525  newFullPCA.getAveHitDoca());
526  }
527 
528  // Set the skeleton PCA to make sure it has some value
529  clusterParams.getSkeletonPCA() = clusterParams.getFullPCA();
530 
531  // Be sure to compute the oonvex hull surrounding the now broken cluster
532  buildConvexHull(clusterParams, level+2);
533 
534  positionItr = breakIntoTinyBits(clusterParams, fullPCA, positionItr, outputClusterList, level+4);
535  }
536  }
537 
538  // If successful in breaking the cluster then we are done, otherwise try to loop
539  // again taking the next furthest hit
540  break;
541  }
542  }
543 
544  // First question, are we done breaking?
545  if (storeCurrentCluster)
546  {
547  // I think this is where we fill out the rest of the parameters?
548  // Start by adding the 2D hits...
549  // See if we can avoid duplicates by temporarily transferring to a set
550  std::set<const reco::ClusterHit2D*> hitSet;
551 
552  // Loop through 3D hits to get a set of unique 2D hits
553  for(const auto& hit3D : clusterToBreak.getHitPairListPtr())
554  {
555  for(const auto& hit2D : hit3D->getHits())
556  {
557  if (hit2D) hitSet.insert(hit2D);
558  }
559  }
560 
561  // Now add these to the new cluster
562  for(const auto& hit2D : hitSet)
563  {
564  hit2D->setStatusBit(reco::ClusterHit2D::USED);
565  clusterToBreak.UpdateParameters(hit2D);
566  }
567 
568  std::cout << indent << "*********>>> storing new subcluster of size " << clusterToBreak.getHitPairListPtr().size() << std::endl;
569 
570  positionItr = outputClusterList.insert(positionItr,clusterToBreak);
571 
572  // Are we filling histograms
573  if (fFillHistograms)
574  {
575  int num3DHits = clusterToBreak.getHitPairListPtr().size();
576  int numEdges = clusterToBreak.getBestEdgeList().size();
577  Eigen::Vector3f newPrimaryVec(fullPCA.getEigenVectors()[0][0],fullPCA.getEigenVectors()[0][1],fullPCA.getEigenVectors()[0][2]);
578  Eigen::Vector3f lastPrimaryVec(lastPCA.getEigenVectors()[0][0],lastPCA.getEigenVectors()[0][1],lastPCA.getEigenVectors()[0][2]);
579  float cosToLast = newPrimaryVec.dot(lastPrimaryVec);
580 
581  fSubNum3DHits->Fill(std::min(num3DHits,199), 1.);
582  fSubNumEdges->Fill(std::min(numEdges,199), 1.);
583  fSubEigen21Ratio->Fill(eigen2To1Ratio, 1.);
584  fSubEigen20Ratio->Fill(eigen2To0Ratio, 1.);
585  fSubEigen10Ratio->Fill(eigen1To0Ratio, 1.);
586  fSubCosToPrevPCA->Fill(cosToLast, 1.);
587  fSubPrimaryLength->Fill(std::min(eigenValVec[0],199.), 1.);
588  }
589 
590  // The above points to the element, want the next element
591  positionItr++;
592  }
593  else if (inputPositionItr != positionItr)
594  {
595  std::cout << indent << "***** DID NOT STORE A CLUSTER *****" << std::endl;
596  }
597 
598  return positionItr;
599 }
void PCAAnalysis_calc3DDocas(const reco::HitPairListPtr &hitPairVector, const reco::PrincipalComponents &pca) const
bool getSvdOK() const
Definition: Cluster3D.h:226
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:112
void PCAAnalysis_3D(const reco::HitPairListPtr &hitPairList, reco::PrincipalComponents &pca, bool skeletonOnly=false) const
intermediate_table::iterator iterator
reco::PrincipalComponents & getSkeletonPCA()
Definition: Cluster3D.h:455
const float * getAvePosition() const
Definition: Cluster3D.h:230
int getNumHitsUsed() const
Definition: Cluster3D.h:227
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:453
intermediate_table::const_iterator const_iterator
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:454
std::string indent(std::size_t const i)
void buildConvexHull(reco::ClusterParameters &clusterParameters, int level=0) const
std::tuple< const reco::ClusterHit3D *, const reco::ClusterHit3D *, double > EdgeTuple
Definition: Cluster3D.h:325
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:317
std::vector< std::vector< float > > EigenVectors
Definition: Cluster3D.h:209
const float * getPosition() const
Definition: Cluster3D.h:147
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:104
const float * getEigenValues() const
Definition: Cluster3D.h:228
reco::ClusterParametersList::iterator breakIntoTinyBits(reco::ClusterParameters &cluster, reco::PrincipalComponents &lastPCA, reco::ClusterParametersList::iterator positionItr, reco::ClusterParametersList &outputClusterList, int level=0) const
Use PCA to try to find path in cluster.
const float getAveHitDoca() const
Definition: Cluster3D.h:231
Int_t min
Definition: plot.C:26
size_t fMinTinyClusterSize
Minimum size for a "tiny" cluster.
bool fFillHistograms
Histogram definitions.
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:229
void lar_cluster3d::VoronoiPathFinder::buildConvexHull ( reco::ClusterParameters clusterParameters,
int  level = 0 
) const
private

Definition at line 917 of file VoronoiPathFinder_tool.cc.

References reco::PrincipalComponents::getAvePosition(), lar_cluster3d::ConvexHull::getConvexHull(), reco::ClusterParameters::getConvexHull(), lar_cluster3d::ConvexHull::getConvexHullArea(), reco::ConvexHull::getConvexHullEdgeList(), reco::ConvexHull::getConvexHullEdgeMap(), reco::ConvexHull::getConvexHullExtremePoints(), reco::PrincipalComponents::getEigenVectors(), reco::ClusterParameters::getFullPCA(), reco::ClusterParameters::getHitPairListPtr(), reco::ClusterHit3D::getPosition(), reco::ConvexHull::getProjectedPointList(), art::detail::indent(), art::left(), max, and art::right().

Referenced by breakIntoTinyBits(), makeCandidateCluster(), and ModifyClusters().

918 {
919  // set an indention string
920  std::string minuses(level/2, '-');
921  std::string indent(level/2, ' ');
922 
923  indent += minuses;
924 
925  // The plan is to build the enclosing 2D polygon around the points in the PCA plane of most spread for this cluster
926  // To do so we need to start by building a list of 2D projections onto the plane of most spread...
927  reco::PrincipalComponents& pca = clusterParameters.getFullPCA();
928 
929  // Recover the parameters from the Principal Components Analysis that we need to project and accumulate
930  Eigen::Vector3f pcaCenter(pca.getAvePosition()[0],pca.getAvePosition()[1],pca.getAvePosition()[2]);
931  Eigen::Vector3f planeVec0(pca.getEigenVectors()[0][0],pca.getEigenVectors()[0][1],pca.getEigenVectors()[0][2]);
932  Eigen::Vector3f planeVec1(pca.getEigenVectors()[1][0],pca.getEigenVectors()[1][1],pca.getEigenVectors()[1][2]);
933  Eigen::Vector3f pcaPlaneNrml(pca.getEigenVectors()[2][0],pca.getEigenVectors()[2][1],pca.getEigenVectors()[2][2]);
934 
935  // Let's get the rotation matrix from the standard coordinate system to the PCA system.
936  Eigen::Matrix3f rotationMatrix;
937 
938  rotationMatrix << planeVec0(0), planeVec0(1), planeVec0(2),
939  planeVec1(0), planeVec1(1), planeVec1(2),
940  pcaPlaneNrml(0), pcaPlaneNrml(1), pcaPlaneNrml(2);
941 
942  //dcel2d::PointList pointList;
943  using Point = std::tuple<float,float,const reco::ClusterHit3D*>;
944  using PointList = std::list<Point>;
945 
946  reco::ConvexHull& convexHull = clusterParameters.getConvexHull();
947  PointList pointList = convexHull.getProjectedPointList();
948 
949  // Loop through hits and do projection to plane
950  for(const auto& hit3D : clusterParameters.getHitPairListPtr())
951  {
952  Eigen::Vector3f pcaToHitVec(hit3D->getPosition()[0] - pcaCenter(0),
953  hit3D->getPosition()[1] - pcaCenter(1),
954  hit3D->getPosition()[2] - pcaCenter(2));
955  Eigen::Vector3f pcaToHit = rotationMatrix * pcaToHitVec;
956 
957  pointList.emplace_back(dcel2d::Point(pcaToHit(0),pcaToHit(1),hit3D));
958  }
959 
960  // Sort the point vec by increasing x, then increase y
961  pointList.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);});
962 
963  // containers for finding the "best" hull...
964  std::vector<ConvexHull> convexHullVec;
965  std::vector<PointList> rejectedListVec;
966  bool increaseDepth(pointList.size() > 5);
967  float lastArea(std::numeric_limits<float>::max());
968 
969  while(increaseDepth)
970  {
971  // Get another convexHull container
972  convexHullVec.push_back(ConvexHull(pointList));
973  rejectedListVec.push_back(PointList());
974 
975  const ConvexHull& convexHull = convexHullVec.back();
976  PointList& rejectedList = rejectedListVec.back();
977  const PointList& convexHullPoints = convexHull.getConvexHull();
978 
979  increaseDepth = false;
980 
981  if (convexHull.getConvexHullArea() > 0.)
982  {
983  std::cout << indent << "-> built convex hull, 3D hits: " << pointList.size() << " with " << convexHullPoints.size() << " vertices" << ", area: " << convexHull.getConvexHullArea() << std::endl;
984  std::cout << indent << "-> -Points:";
985  for(const auto& point : convexHullPoints)
986  std::cout << " (" << std::get<0>(point) << "," << std::get<1>(point) << ")";
987  std::cout << std::endl;
988 
989  if (convexHullVec.size() < 2 || convexHull.getConvexHullArea() < 0.8 * lastArea)
990  {
991  for(auto& point : convexHullPoints)
992  {
993  pointList.remove(point);
994  rejectedList.emplace_back(point);
995  }
996  lastArea = convexHull.getConvexHullArea();
997 // increaseDepth = true;
998  }
999  }
1000  }
1001 
1002  // do we have a valid convexHull?
1003  while(!convexHullVec.empty() && convexHullVec.back().getConvexHullArea() < 0.5)
1004  {
1005  convexHullVec.pop_back();
1006  rejectedListVec.pop_back();
1007  }
1008 
1009  // If we found the convex hull then build edges around the region
1010  if (!convexHullVec.empty())
1011  {
1012  size_t nRejectedTotal(0);
1013  reco::HitPairListPtr hitPairListPtr = clusterParameters.getHitPairListPtr();
1014 
1015  for(const auto& rejectedList : rejectedListVec)
1016  {
1017  nRejectedTotal += rejectedList.size();
1018 
1019  for(const auto& rejectedPoint : rejectedList)
1020  {
1021  std::cout << indent << "-> -- Point is " << convexHullVec.back().findNearestDistance(rejectedPoint) << " from nearest edge" << std::endl;
1022 
1023  if (convexHullVec.back().findNearestDistance(rejectedPoint) > 0.5)
1024  hitPairListPtr.remove(std::get<2>(rejectedPoint));
1025  }
1026  }
1027 
1028  std::cout << indent << "-> Removed " << nRejectedTotal << " leaving " << pointList.size() << "/" << hitPairListPtr.size() << " points" << std::endl;
1029 
1030  // Now add "edges" to the cluster to describe the convex hull (for the display)
1031  reco::Hit3DToEdgeMap& edgeMap = convexHull.getConvexHullEdgeMap();
1032  reco::EdgeList& bestEdgeList = convexHull.getConvexHullEdgeList();
1033 
1034  Point lastPoint = convexHullVec.back().getConvexHull().front();
1035 
1036  for(auto& curPoint : convexHullVec.back().getConvexHull())
1037  {
1038  if (curPoint == lastPoint) continue;
1039 
1040  const reco::ClusterHit3D* lastPoint3D = std::get<2>(lastPoint);
1041  const reco::ClusterHit3D* curPoint3D = std::get<2>(curPoint);
1042 
1043  float distBetweenPoints = (curPoint3D->getPosition()[0] - lastPoint3D->getPosition()[0]) * (curPoint3D->getPosition()[0] - lastPoint3D->getPosition()[0])
1044  + (curPoint3D->getPosition()[1] - lastPoint3D->getPosition()[1]) * (curPoint3D->getPosition()[1] - lastPoint3D->getPosition()[1])
1045  + (curPoint3D->getPosition()[2] - lastPoint3D->getPosition()[2]) * (curPoint3D->getPosition()[2] - lastPoint3D->getPosition()[2]);
1046 
1047  distBetweenPoints = std::sqrt(distBetweenPoints);
1048 
1049  reco::EdgeTuple edge(lastPoint3D,curPoint3D,distBetweenPoints);
1050 
1051  edgeMap[lastPoint3D].push_back(edge);
1052  edgeMap[curPoint3D].push_back(edge);
1053  bestEdgeList.emplace_back(edge);
1054 
1055  lastPoint = curPoint;
1056  }
1057 
1058  // Store the "extreme" points
1059  const ConvexHull::PointList& extremePoints = convexHullVec.back().getExtremePoints();
1060  reco::ProjectedPointList& extremePointList = convexHull.getConvexHullExtremePoints();
1061 
1062  for(const auto& point : extremePoints) extremePointList.push_back(point);
1063  }
1064 
1065  return;
1066 }
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:112
std::list< ProjectedPoint > ProjectedPointList
Definition: Cluster3D.h:334
std::list< Point > PointList
The list of the projected points.
Definition: ConvexHull.h:32
const float * getAvePosition() const
Definition: Cluster3D.h:230
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:453
std::list< EdgeTuple > EdgeList
Definition: Cluster3D.h:326
Int_t max
Definition: plot.C:27
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:454
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:34
Define a container for working with the convex hull.
Definition: Cluster3D.h:341
std::tuple< float, float, const reco::ClusterHit3D * > Point
std::string indent(std::size_t const i)
std::tuple< const reco::ClusterHit3D *, const reco::ClusterHit3D *, double > EdgeTuple
Definition: Cluster3D.h:325
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:317
const float * getPosition() const
Definition: Cluster3D.h:147
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:104
reco::ConvexHull & getConvexHull()
Definition: Cluster3D.h:459
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:328
reco::ProjectedPointList & getProjectedPointList()
Definition: Cluster3D.h:362
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:229
void lar_cluster3d::VoronoiPathFinder::buildVoronoiDiagram ( reco::ClusterParameters clusterParameters,
int  level = 0 
) const
private

Definition at line 1069 of file VoronoiPathFinder_tool.cc.

References voronoi2d::VoronoiDiagram::buildVoronoiDiagram(), reco::PrincipalComponents::getAvePosition(), reco::ClusterParameters::getBestEdgeList(), reco::PrincipalComponents::getEigenVectors(), reco::ClusterParameters::getFaceList(), reco::ClusterParameters::getFullPCA(), reco::ClusterParameters::getHalfEdgeList(), reco::ClusterParameters::getHit3DToEdgeMap(), reco::ClusterParameters::getHitPairListPtr(), reco::ClusterHit3D::getPosition(), reco::ClusterParameters::getVertexList(), art::left(), and art::right().

Referenced by ModifyClusters().

1070 {
1071  // The plan is to build the enclosing 2D polygon around the points in the PCA plane of most spread for this cluster
1072  // To do so we need to start by building a list of 2D projections onto the plane of most spread...
1073  reco::PrincipalComponents& pca = clusterParameters.getFullPCA();
1074 
1075  // Recover the parameters from the Principal Components Analysis that we need to project and accumulate
1076  Eigen::Vector3f pcaCenter(pca.getAvePosition()[0],pca.getAvePosition()[1],pca.getAvePosition()[2]);
1077  Eigen::Vector3f planeVec0(pca.getEigenVectors()[0][0],pca.getEigenVectors()[0][1],pca.getEigenVectors()[0][2]);
1078  Eigen::Vector3f planeVec1(pca.getEigenVectors()[1][0],pca.getEigenVectors()[1][1],pca.getEigenVectors()[1][2]);
1079  Eigen::Vector3f pcaPlaneNrml(pca.getEigenVectors()[2][0],pca.getEigenVectors()[2][1],pca.getEigenVectors()[2][2]);
1080 
1081  // Leave the following code bits as an example of a more complicated way to do what we are trying to do here
1082  // (but in case I want to use quaternions again!)
1083  //
1084  //Eigen::Vector3f unitVecX(1.,0.,0.);
1085  //
1086  //Eigen::Quaternionf rotationMatrix = Eigen::Quaternionf::FromTwoVectors(planeVec0,unitVecX);
1087  //
1088  //Eigen::Matrix3f Rmatrix = rotationMatrix.toRotationMatrix();
1089  //Eigen::Matrix3f RInvMatrix = rotationMatrix.inverse().toRotationMatrix();
1090 
1091  // Let's get the rotation matrix from the standard coordinate system to the PCA system.
1092  Eigen::Matrix3f rotationMatrix;
1093 
1094  rotationMatrix << planeVec0(0), planeVec0(1), planeVec0(2),
1095  planeVec1(0), planeVec1(1), planeVec1(2),
1096  pcaPlaneNrml(0), pcaPlaneNrml(1), pcaPlaneNrml(2);
1097 
1098  dcel2d::PointList pointList;
1099 
1100  // Loop through hits and do projection to plane
1101  for(const auto& hit3D : clusterParameters.getHitPairListPtr())
1102  {
1103  Eigen::Vector3f pcaToHitVec(hit3D->getPosition()[0] - pcaCenter(0),
1104  hit3D->getPosition()[1] - pcaCenter(1),
1105  hit3D->getPosition()[2] - pcaCenter(2));
1106  Eigen::Vector3f pcaToHit = rotationMatrix * pcaToHitVec;
1107 
1108  pointList.emplace_back(dcel2d::Point(pcaToHit(0),pcaToHit(1),hit3D));
1109  }
1110 
1111  // Sort the point vec by increasing x, then increase y
1112  pointList.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);});
1113 
1114  std::cout << " ==> Build V diagram, sorted point list contains " << pointList.size() << " hits" << std::endl;
1115 
1116  // Set up the voronoi diagram builder
1117  voronoi2d::VoronoiDiagram voronoiDiagram(clusterParameters.getHalfEdgeList(),clusterParameters.getVertexList(),clusterParameters.getFaceList());
1118 
1119  // And make the diagram
1120  voronoiDiagram.buildVoronoiDiagram(pointList);
1121 
1122  // Recover the voronoi diagram vertex list and the container to store them in
1123  dcel2d::VertexList& vertexList = clusterParameters.getVertexList();
1124 
1125  // Now get the inverse of the rotation matrix so we can get the vertex positions,
1126  // which lie in the plane of the two largest PCA axes, in the standard coordinate system
1127  Eigen::Matrix3f rotationMatrixInv = rotationMatrix.inverse();
1128 
1129  // Translate and fill
1130  for(auto& vertex : vertexList)
1131  {
1132  Eigen::Vector3f coords = rotationMatrixInv * vertex.getCoords();
1133 
1134  coords += pcaCenter;
1135 
1136  vertex.setCoords(coords);
1137  }
1138 
1139  // Now do the Convex Hull
1140  // Now add "edges" to the cluster to describe the convex hull (for the display)
1141  reco::Hit3DToEdgeMap& edgeMap = clusterParameters.getHit3DToEdgeMap();
1142  reco::EdgeList& bestEdgeList = clusterParameters.getBestEdgeList();
1143 
1144 // const dcel2d::PointList& edgePoints = voronoiDiagram.getConvexHull();
1145 // PointList localList;
1146 //
1147 // for(const auto& edgePoint : edgePoints) localList.emplace_back(std::get<0>(edgePoint),std::get<1>(edgePoint),std::get<2>(edgePoint));
1148 //
1149 // // Sort the point vec by increasing x, then increase y
1150 // localList.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);});
1151 //
1152 // // Why do I need to do this?
1153 // ConvexHull convexHull(localList);
1154 //
1155 // Point lastPoint = convexHull.getConvexHull().front();
1156  dcel2d::Point lastPoint = voronoiDiagram.getConvexHull().front();
1157 
1158 // std::cout << "@@@@>> Build convex hull, voronoi handed " << edgePoints.size() << " points, convexHull cut to " << convexHull.getConvexHull().size() << std::endl;
1159 
1160 // for(auto& curPoint : convexHull.getConvexHull())
1161  for(auto& curPoint : voronoiDiagram.getConvexHull())
1162  {
1163  if (curPoint == lastPoint) continue;
1164 
1165  const reco::ClusterHit3D* lastPoint3D = std::get<2>(lastPoint);
1166  const reco::ClusterHit3D* curPoint3D = std::get<2>(curPoint);
1167 
1168  float distBetweenPoints = (curPoint3D->getPosition()[0] - lastPoint3D->getPosition()[0]) * (curPoint3D->getPosition()[0] - lastPoint3D->getPosition()[0])
1169  + (curPoint3D->getPosition()[1] - lastPoint3D->getPosition()[1]) * (curPoint3D->getPosition()[1] - lastPoint3D->getPosition()[1])
1170  + (curPoint3D->getPosition()[2] - lastPoint3D->getPosition()[2]) * (curPoint3D->getPosition()[2] - lastPoint3D->getPosition()[2]);
1171 
1172  distBetweenPoints = std::sqrt(distBetweenPoints);
1173 
1174  reco::EdgeTuple edge(lastPoint3D,curPoint3D,distBetweenPoints);
1175 
1176  edgeMap[lastPoint3D].push_back(edge);
1177  edgeMap[curPoint3D].push_back(edge);
1178  bestEdgeList.emplace_back(edge);
1179 
1180  lastPoint = curPoint;
1181  }
1182 
1183  std::cout << "****> vertexList containted " << vertexList.size() << " vertices for " << clusterParameters.getHitPairListPtr().size() << " hits" << std::endl;
1184 
1185  return;
1186 }
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:112
reco::EdgeList & getBestEdgeList()
Definition: Cluster3D.h:458
const float * getAvePosition() const
Definition: Cluster3D.h:230
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
Definition: Cluster3D.h:456
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:453
std::list< EdgeTuple > EdgeList
Definition: Cluster3D.h:326
VoronoiDiagram class definiton.
Definition: Voronoi.h:33
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:454
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:34
void buildVoronoiDiagram(const dcel2d::PointList &)
Given an input set of 2D points construct a 2D voronoi diagram.
Definition: Voronoi.cxx:135
std::tuple< const reco::ClusterHit3D *, const reco::ClusterHit3D *, double > EdgeTuple
Definition: Cluster3D.h:325
const float * getPosition() const
Definition: Cluster3D.h:147
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:104
dcel2d::FaceList & getFaceList()
Definition: Cluster3D.h:460
std::list< Point > PointList
Definition: DCEL.h:35
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:328
dcel2d::HalfEdgeList & getHalfEdgeList()
Definition: Cluster3D.h:462
std::list< Vertex > VertexList
Definition: DCEL.h:178
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:229
dcel2d::VertexList & getVertexList()
Definition: Cluster3D.h:461
vertex reconstruction
float lar_cluster3d::VoronoiPathFinder::closestApproach ( const Eigen::Vector3f &  P0,
const Eigen::Vector3f &  u0,
const Eigen::Vector3f &  P1,
const Eigen::Vector3f &  u1,
Eigen::Vector3f &  poca0,
Eigen::Vector3f &  poca1 
) const
private

Definition at line 1189 of file VoronoiPathFinder_tool.cc.

References d, den, and e.

Referenced by getTimeToExecute().

1195 {
1196  // Technique is to compute the arclength to each point of closest approach
1197  Eigen::Vector3f w0 = P0 - P1;
1198  float a(1.);
1199  float b(u0.dot(u1));
1200  float c(1.);
1201  float d(u0.dot(w0));
1202  float e(u1.dot(w0));
1203  float den(a * c - b * b);
1204 
1205  float arcLen0 = (b * e - c * d) / den;
1206  float arcLen1 = (a * e - b * d) / den;
1207 
1208  poca0 = P0 + arcLen0 * u0;
1209  poca1 = P1 + arcLen1 * u1;
1210 
1211  return (poca0 - poca1).norm();
1212 }
Float_t den
Definition: plot.C:37
Float_t d
Definition: plot.C:237
Float_t e
Definition: plot.C:34
virtual void lar_cluster3d::IClusterModAlg::configure ( const fhicl::ParameterSet )
pure virtualinherited

Interface for configuring the particular algorithm tool.

Parameters
ParameterSetThe input set of parameters for configuration
void lar_cluster3d::VoronoiPathFinder::configure ( fhicl::ParameterSet const &  pset)
override

Definition at line 189 of file VoronoiPathFinder_tool.cc.

References fClusterAlg, fEnableMonitoring, fGeometry, fMinTinyClusterSize, fTimeToProcess, and fhicl::ParameterSet::get().

Referenced by VoronoiPathFinder().

190 {
191  fEnableMonitoring = pset.get<bool> ("EnableMonitoring", true );
192  fMinTinyClusterSize = pset.get<size_t>("MinTinyClusterSize",40);
193  fClusterAlg = art::make_tool<lar_cluster3d::IClusterAlg>(pset.get<fhicl::ParameterSet>("ClusterAlg"));
194 
196 
197  fGeometry = &*geometry;
198 
199  fTimeToProcess = 0.;
200 
201  return;
202 }
std::unique_ptr< lar_cluster3d::IClusterAlg > fClusterAlg
Algorithm to do 3D space point clustering.
size_t fMinTinyClusterSize
Minimum size for a "tiny" cluster.
float lar_cluster3d::VoronoiPathFinder::findConvexHullEndPoints ( const reco::EdgeList convexHull,
const reco::ClusterHit3D first3D,
const reco::ClusterHit3D last3D 
) const
private

Definition at line 1214 of file VoronoiPathFinder_tool.cc.

References DEFINE_ART_CLASS_TOOL.

1215 {
1216  float largestDistance(0.);
1217 
1218  // Note that edges are vectors and that the convex hull edge list will be ordered
1219  // The idea is that the maximum distance from a given edge is to the edge just before the edge that "turns back" towards the current edge
1220  // meaning that the dot product of the two edges becomes negative.
1221  reco::EdgeList::const_iterator firstEdgeItr = convexHull.begin();
1222 
1223  while(firstEdgeItr != convexHull.end())
1224  {
1225  reco::EdgeList::const_iterator nextEdgeItr = firstEdgeItr;
1226 
1227 // Eigen::Vector2f firstEdgeVec(std::get<3>(*firstEdgeItr),std::get<);
1228 // Eigen::Vector2f lastPrimaryVec(lastPCA.getEigenVectors()[0][0],lastPCA.getEigenVectors()[0][1],lastPCA.getEigenVectors()[0][2]);
1229 // float cosToLast = newPrimaryVec.dot(lastPrimaryVec);
1230 
1231  while(++nextEdgeItr != convexHull.end())
1232  {
1233 
1234  }
1235  }
1236 
1237  return largestDistance;
1238 }
intermediate_table::const_iterator const_iterator
float lar_cluster3d::VoronoiPathFinder::getTimeToExecute ( ) const
inlineoverridevirtual

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

Implements lar_cluster3d::IClusterModAlg.

Definition at line 86 of file VoronoiPathFinder_tool.cc.

References breakIntoTinyBits(), closestApproach(), fTimeToProcess, makeCandidateCluster(), and subDivideCluster().

void lar_cluster3d::VoronoiPathFinder::initializeHistograms ( art::TFileDirectory histDir)
overridevirtual

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

Parameters
TFileDirectory- the folder to store the hists in

Implements lar_cluster3d::IClusterModAlg.

Definition at line 204 of file VoronoiPathFinder_tool.cc.

References dir, fFillHistograms, fSubCosExtToPCA, fSubCosToPrevPCA, fSubEigen10Ratio, fSubEigen20Ratio, fSubEigen21Ratio, fSubMaxDefect, fSubNum3DHits, fSubNumEdges, fSubPrimaryLength, fSubUsedDefect, fTopEigen10Ratio, fTopEigen20Ratio, fTopEigen21Ratio, fTopNum3DHits, fTopNumEdges, fTopPrimaryLength, art::TFileDirectory::make(), and art::TFileDirectory::mkdir().

205 {
206  // It is assumed that the input TFileDirectory has been set up to group histograms into a common
207  // folder at the calling routine's level. Here we create one more level of indirection to keep
208  // histograms made by this tool separate.
209  fFillHistograms = true;
210 
211  std::string dirName = "VoronoiPath";
212 
213  art::TFileDirectory dir = histDir.mkdir(dirName.c_str());
214 
215  // Divide into two sets of hists... those for the overall cluster and
216  // those for the subclusters
217  fTopNum3DHits = dir.make<TH1F>("TopNum3DHits", "Number 3D Hits", 200, 0., 200.);
218  fTopNumEdges = dir.make<TH1F>("TopNumEdges", "Number Edges", 200, 0., 200.);
219  fTopEigen21Ratio = dir.make<TH1F>("TopEigen21Rat", "Eigen 2/1 Ratio", 100, 0., 1.);
220  fTopEigen20Ratio = dir.make<TH1F>("TopEigen20Rat", "Eigen 2/0 Ratio", 100, 0., 1.);
221  fTopEigen10Ratio = dir.make<TH1F>("TopEigen10Rat", "Eigen 1/0 Ratio", 100, 0., 1.);
222  fTopPrimaryLength = dir.make<TH1F>("TopPrimaryLen", "Primary Length", 200, 0., 200.);
223 
224  fSubNum3DHits = dir.make<TH1F>("SubNum3DHits", "Number 3D Hits", 200, 0., 200.);
225  fSubNumEdges = dir.make<TH1F>("SubNumEdges", "Number Edges", 200, 0., 200.);
226  fSubEigen21Ratio = dir.make<TH1F>("SubEigen21Rat", "Eigen 2/1 Ratio", 100, 0., 1.);
227  fSubEigen20Ratio = dir.make<TH1F>("SubEigen20Rat", "Eigen 2/0 Ratio", 100, 0., 1.);
228  fSubEigen10Ratio = dir.make<TH1F>("SubEigen10Rat", "Eigen 1/0 Ratio", 100, 0., 1.);
229  fSubPrimaryLength = dir.make<TH1F>("SubPrimaryLen", "Primary Length", 200, 0., 200.);
230  fSubCosToPrevPCA = dir.make<TH1F>("SubCosToPrev", "Cos(theta)", 101, 0., 1.01);
231  fSubCosExtToPCA = dir.make<TH1F>("SubCosExtPCA", "Cos(theta)", 102, -1.01, 1.01);
232  fSubMaxDefect = dir.make<TH1F>("SubMaxDefect", "Max Defect", 100, 0., 50.);
233  fSubUsedDefect = dir.make<TH1F>("SubUsedDefect", "Used Defect", 100, 0., 50.);
234 
235  return;
236 }
TFileDirectory mkdir(std::string const &dir, std::string const &descr="")
T * make(ARGS...args) const
TDirectory * dir
Definition: macro.C:5
bool fFillHistograms
Histogram definitions.
bool lar_cluster3d::VoronoiPathFinder::makeCandidateCluster ( Eigen::Vector3f &  primaryPCA,
reco::ClusterParameters candCluster,
reco::HitPairListPtr::iterator  firstHitItr,
reco::HitPairListPtr::iterator  lastHitItr,
int  level 
) const
private

Definition at line 825 of file VoronoiPathFinder_tool.cc.

References buildConvexHull(), fPCAAlg, reco::PrincipalComponents::getAveHitDoca(), reco::PrincipalComponents::getAvePosition(), reco::ClusterParameters::getBestEdgeList(), reco::PrincipalComponents::getEigenValues(), reco::PrincipalComponents::getEigenVectors(), reco::ClusterParameters::getFullPCA(), reco::ClusterParameters::getHitPairListPtr(), reco::PrincipalComponents::getNumHitsUsed(), reco::ClusterParameters::getSkeletonPCA(), reco::PrincipalComponents::getSvdOK(), art::detail::indent(), and lar_cluster3d::PrincipalComponentsAlg::PCAAnalysis_3D().

Referenced by getTimeToExecute(), and subDivideCluster().

830 {
831  std::string indent(level/2, ' ');
832 
833  reco::HitPairListPtr& hitPairListPtr = candCluster.getHitPairListPtr();
834 
835  std::cout << indent << "+> -- building new cluster, size: " << std::distance(firstHitItr,lastHitItr) << std::endl;
836 
837  // size the container...
838  hitPairListPtr.resize(std::distance(firstHitItr,lastHitItr));
839 
840  // and copy the hits into the container
841  std::copy(firstHitItr,lastHitItr,hitPairListPtr.begin());
842 
843  // First stage of feature extraction runs here
844  fPCAAlg.PCAAnalysis_3D(hitPairListPtr, candCluster.getFullPCA());
845 
846  // Recover the new fullPCA
847  reco::PrincipalComponents& newFullPCA = candCluster.getFullPCA();
848 
849  // Will we want to store this cluster?
850  bool keepThisCluster(false);
851 
852  // Must have a valid pca
853  if (newFullPCA.getSvdOK())
854  {
855  std::cout << indent << "+> -- >> cluster has a valid Full PCA" << std::endl;
856 
857  // Need to check if the PCA direction has been reversed
858  Eigen::Vector3f newPrimaryVec(newFullPCA.getEigenVectors()[0][0],newFullPCA.getEigenVectors()[0][1],newFullPCA.getEigenVectors()[0][2]);
859 
860  // If the PCA's are opposite the flip the axes
861  if (primaryPCA.dot(newPrimaryVec) < 0.)
862  {
864 
865  eigenVectors.resize(3);
866 
867  for(size_t vecIdx = 0; vecIdx < 3; vecIdx++)
868  {
869  eigenVectors[vecIdx].resize(3,0.);
870 
871  eigenVectors[vecIdx][0] = -newFullPCA.getEigenVectors()[vecIdx][0];
872  eigenVectors[vecIdx][1] = -newFullPCA.getEigenVectors()[vecIdx][1];
873  eigenVectors[vecIdx][2] = -newFullPCA.getEigenVectors()[vecIdx][2];
874  }
875 
876  newFullPCA = reco::PrincipalComponents(true,
877  newFullPCA.getNumHitsUsed(),
878  newFullPCA.getEigenValues(),
879  eigenVectors,
880  newFullPCA.getAvePosition(),
881  newFullPCA.getAveHitDoca());
882 
883  newPrimaryVec = Eigen::Vector3f(newFullPCA.getEigenVectors()[0][0],newFullPCA.getEigenVectors()[0][1],newFullPCA.getEigenVectors()[0][2]);
884  }
885 
886  // Set the skeleton PCA to make sure it has some value
887  candCluster.getSkeletonPCA() = candCluster.getFullPCA();
888 
889  // Be sure to compute the oonvex hull surrounding the now broken cluster
890  buildConvexHull(candCluster, level+2);
891 
892  std::vector<double> eigenValVec = {3. * std::sqrt(newFullPCA.getEigenValues()[0]),
893  3. * std::sqrt(newFullPCA.getEigenValues()[1]),
894  3. * std::sqrt(newFullPCA.getEigenValues()[2])};
895  double cosNewToLast = std::abs(primaryPCA.dot(newPrimaryVec));
896  double eigen2To1Ratio = eigenValVec[2] / eigenValVec[1];
897  double eigen1To0Ratio = eigenValVec[1] / eigenValVec[0];
898  double eigen2To0Ratio = eigenValVec[2] / eigenValVec[0];
899  double eigen2And1Ave = 0.5 * (eigenValVec[1] + eigenValVec[2]);
900  double eigenAveTo0Ratio = eigen2And1Ave / eigenValVec[0];
901 
902  std::cout << indent << ">>> subDivideClusters with " << candCluster.getHitPairListPtr().size() << " input hits, " << candCluster.getBestEdgeList().size() << " edges, rat21: " << eigen2To1Ratio << ", rat20: " << eigen2To0Ratio << ", rat10: " << eigen1To0Ratio << ", ave0: " << eigenAveTo0Ratio << std::endl;
903  std::cout << indent << " --> eigen 0/1/2: " << eigenValVec[0] << "/" << eigenValVec[1] << "/" << eigenValVec[2] << ", cos: " << cosNewToLast << std::endl;
904 
905  // Create a rough cut intended to tell us when we've reached the land of diminishing returns
906 // if (candCluster.getBestEdgeList().size() > 4 && cosNewToLast > 0.25 && eigen2To1Ratio < 0.9 && eigen2To0Ratio > 0.001)
907  if (candCluster.getBestEdgeList().size() > 4 && cosNewToLast > 0.25 && eigen2To1Ratio > 0.01 && eigen2To1Ratio < 0.99 && eigen1To0Ratio < 0.5)
908  {
909  keepThisCluster = true;
910  }
911  }
912 
913  return keepThisCluster;
914 }
bool getSvdOK() const
Definition: Cluster3D.h:226
void PCAAnalysis_3D(const reco::HitPairListPtr &hitPairList, reco::PrincipalComponents &pca, bool skeletonOnly=false) const
reco::PrincipalComponents & getSkeletonPCA()
Definition: Cluster3D.h:455
reco::EdgeList & getBestEdgeList()
Definition: Cluster3D.h:458
const float * getAvePosition() const
Definition: Cluster3D.h:230
int getNumHitsUsed() const
Definition: Cluster3D.h:227
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:453
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:454
std::string indent(std::size_t const i)
void buildConvexHull(reco::ClusterParameters &clusterParameters, int level=0) const
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:317
std::vector< std::vector< float > > EigenVectors
Definition: Cluster3D.h:209
const float * getEigenValues() const
Definition: Cluster3D.h:228
const float getAveHitDoca() const
Definition: Cluster3D.h:231
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:229
void lar_cluster3d::VoronoiPathFinder::ModifyClusters ( reco::ClusterParametersList clusterParametersList) const
overridevirtual

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

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

Top level interface for algorithm to consider pairs of clusters from the input list and determine if they are consistent with each other and, therefore, should be merged. This is done by looking at the PCA for each cluster and looking at the projection of the primary axis along the vector connecting their centers.

Implements lar_cluster3d::IClusterModAlg.

Definition at line 238 of file VoronoiPathFinder_tool.cc.

References buildConvexHull(), buildVoronoiDiagram(), reco::ClusterParameters::daughterList(), fEnableMonitoring, fFillHistograms, fMinTinyClusterSize, fTimeToProcess, fTopEigen10Ratio, fTopEigen20Ratio, fTopEigen21Ratio, fTopNum3DHits, fTopNumEdges, fTopPrimaryLength, reco::PrincipalComponents::getEigenValues(), reco::ClusterParameters::getHitPairListPtr(), min, and subDivideCluster().

239 {
247  // Initial clustering is done, now trim the list and get output parameters
248  cet::cpu_timer theClockBuildClusters;
249 
250  // Start clocks if requested
251  if (fEnableMonitoring) theClockBuildClusters.start();
252 
253  int countClusters(0);
254 
255  // This is the loop over candidate 3D clusters
256  // Note that it might be that the list of candidate clusters is modified by splitting
257  // So we use the following construct to make sure we get all of them
258  reco::ClusterParametersList::iterator clusterParametersListItr = clusterParametersList.begin();
259 
260  while(clusterParametersListItr != clusterParametersList.end())
261  {
262  // Dereference to get the cluster paramters
263  reco::ClusterParameters& clusterParameters = *clusterParametersListItr;
264 
265  std::cout << "**> Looking at Cluster " << countClusters++ << ", # hits: " << clusterParameters.getHitPairListPtr().size() << std::endl;
266 
267  // It turns out that computing the convex hull surrounding the points in the 2D projection onto the
268  // plane of largest spread in the PCA is a good way to break up the cluster... and we do it here since
269  // we (currently) want this to be part of the standard output
270  buildVoronoiDiagram(clusterParameters);
271 
272  // Make sure our cluster has enough hits...
273  if (clusterParameters.getHitPairListPtr().size() > fMinTinyClusterSize)
274  {
275  // Get an interim cluster list
276  reco::ClusterParametersList reclusteredParameters;
277 
278  // Call the main workhorse algorithm for building the local version of candidate 3D clusters
279  //******** Remind me why we need to call this at this point when the same hits will be used? ********
280  //fClusterAlg->Cluster3DHits(clusterParameters.getHitPairListPtr(), reclusteredParameters);
281  reclusteredParameters.push_back(clusterParameters);
282 
283  std::cout << ">>>>>>>>>>> Reclustered to " << reclusteredParameters.size() << " Clusters <<<<<<<<<<<<<<<" << std::endl;
284 
285  // Only process non-empty results
286  if (!reclusteredParameters.empty())
287  {
288  // Loop over the reclustered set
289  for (auto& cluster : reclusteredParameters)
290  {
291  std::cout << "****> Calling breakIntoTinyBits with " << cluster.getHitPairListPtr().size() << " hits" << std::endl;
292 
293  // It turns out that computing the convex hull surrounding the points in the 2D projection onto the
294  // plane of largest spread in the PCA is a good way to break up the cluster... and we do it here since
295  // we (currently) want this to be part of the standard output
297 
298  // Break our cluster into smaller elements...
299  subDivideCluster(cluster, cluster.getFullPCA(), cluster.daughterList().end(), cluster.daughterList(), 4);
300 
301  std::cout << "****> Broke Cluster with " << cluster.getHitPairListPtr().size() << " into " << cluster.daughterList().size() << " sub clusters";
302  for(auto& clus : cluster.daughterList()) std::cout << ", " << clus.getHitPairListPtr().size();
303  std::cout << std::endl;
304 
305  // Add the daughters to the cluster
306  clusterParameters.daughterList().insert(clusterParameters.daughterList().end(),cluster);
307 
308  // If filling histograms we do the main cluster here
309  if (fFillHistograms)
310  {
311  reco::PrincipalComponents& fullPCA = cluster.getFullPCA();
312  std::vector<double> eigenValVec = {3. * std::sqrt(fullPCA.getEigenValues()[0]),
313  3. * std::sqrt(fullPCA.getEigenValues()[1]),
314  3. * std::sqrt(fullPCA.getEigenValues()[2])};
315  double eigen2To1Ratio = eigenValVec[2] / eigenValVec[1];
316  double eigen1To0Ratio = eigenValVec[1] / eigenValVec[0];
317  double eigen2To0Ratio = eigenValVec[2] / eigenValVec[0];
318  int num3DHits = cluster.getHitPairListPtr().size();
319  int numEdges = cluster.getBestEdgeList().size();
320 
321  fTopNum3DHits->Fill(std::min(num3DHits,199), 1.);
322  fTopNumEdges->Fill(std::min(numEdges,199), 1.);
323  fTopEigen21Ratio->Fill(eigen2To1Ratio, 1.);
324  fTopEigen20Ratio->Fill(eigen2To0Ratio, 1.);
325  fTopEigen10Ratio->Fill(eigen1To0Ratio, 1.);
326  fTopPrimaryLength->Fill(std::min(eigenValVec[0],199.), 1.);
327  }
328  }
329  }
330  }
331 
332  // Go to next cluster parameters object
333  clusterParametersListItr++;
334  }
335 
336  if (fEnableMonitoring)
337  {
338  theClockBuildClusters.stop();
339 
340  fTimeToProcess = theClockBuildClusters.accumulated_real_time();
341  }
342 
343  mf::LogDebug("Cluster3D") << ">>>>> Cluster Path finding done" << std::endl;
344 
345  return;
346 }
intermediate_table::iterator iterator
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:453
Cluster finding and building.
ClusterParametersList & daughterList()
Definition: Cluster3D.h:427
void buildConvexHull(reco::ClusterParameters &clusterParameters, int level=0) const
reco::ClusterParametersList::iterator subDivideCluster(reco::ClusterParameters &cluster, reco::PrincipalComponents &lastPCA, reco::ClusterParametersList::iterator positionItr, reco::ClusterParametersList &outputClusterList, int level=0) const
Use PCA to try to find path in cluster.
const float * getEigenValues() const
Definition: Cluster3D.h:228
Int_t min
Definition: plot.C:26
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
void buildVoronoiDiagram(reco::ClusterParameters &clusterParameters, int level=0) const
size_t fMinTinyClusterSize
Minimum size for a "tiny" cluster.
bool fFillHistograms
Histogram definitions.
std::list< ClusterParameters > ClusterParametersList
Definition: Cluster3D.h:381
reco::ClusterParametersList::iterator lar_cluster3d::VoronoiPathFinder::subDivideCluster ( reco::ClusterParameters cluster,
reco::PrincipalComponents lastPCA,
reco::ClusterParametersList::iterator  positionItr,
reco::ClusterParametersList outputClusterList,
int  level = 0 
) const
private

Use PCA to try to find path in cluster.

Parameters
clusterParametersThe given cluster parameters object to try to split
clusterParametersListThe list of clusters

Definition at line 601 of file VoronoiPathFinder_tool.cc.

References fFillHistograms, fMinTinyClusterSize, fPCAAlg, fSubCosExtToPCA, fSubCosToPrevPCA, fSubEigen10Ratio, fSubEigen20Ratio, fSubEigen21Ratio, fSubMaxDefect, fSubNum3DHits, fSubNumEdges, fSubPrimaryLength, fSubUsedDefect, reco::ClusterParameters::getBestEdgeList(), reco::ClusterParameters::getConvexHull(), reco::ConvexHull::getConvexHullExtremePoints(), reco::PrincipalComponents::getEigenValues(), reco::PrincipalComponents::getEigenVectors(), reco::ClusterParameters::getFullPCA(), reco::ClusterParameters::getHitPairListPtr(), reco::ClusterHit3D::getPosition(), art::detail::indent(), art::left(), makeCandidateCluster(), min, lar_cluster3d::PrincipalComponentsAlg::PCAAnalysis_calc3DDocas(), art::right(), and reco::ClusterHit2D::USED.

Referenced by getTimeToExecute(), and ModifyClusters().

606 {
607  // This is a recursive routine to divide an input cluster, according to the maximum defect point of
608  // the convex hull until we reach the point of no further improvement.
609  // The assumption is that the input cluster is fully formed already, this routine then simply
610  // divides, if successful division into two pieces it then stores the results
611 
612  // No point in doing anything if we don't have enough space points
613  if (clusterToBreak.getHitPairListPtr().size() > size_t(2 * fMinTinyClusterSize))
614  {
615  // set an indention string
616  std::string pluses(level/2, '+');
617  std::string indent(level/2, ' ');
618 
619  indent += pluses;
620 
621  // To make best use of this we'll also want the PCA for this cluster... so...
622  // Recover the prime ingredients
623  reco::PrincipalComponents& fullPCA = clusterToBreak.getFullPCA();
624  std::vector<double> eigenValVec = {3. * std::sqrt(fullPCA.getEigenValues()[0]),
625  3. * std::sqrt(fullPCA.getEigenValues()[1]),
626  3. * std::sqrt(fullPCA.getEigenValues()[2])};
627  Eigen::Vector3f fullPrimaryVec(fullPCA.getEigenVectors()[0][0],fullPCA.getEigenVectors()[0][1],fullPCA.getEigenVectors()[0][2]);
628 
629  // We want to find the convex hull vertices that lie furthest from the line to/from the extreme points
630  // To find these we:
631  // 1) recover the extreme points
632  // 2) form the vector between them
633  // 3) loop through the vertices and keep track of distance to this vector
634  // 4) Sort the resulting list by furthest points and select the one we want
635  reco::ProjectedPointList::const_iterator extremePointListItr = clusterToBreak.getConvexHull().getConvexHullExtremePoints().begin();
636 
637  const reco::ClusterHit3D* firstEdgeHit = std::get<2>(*extremePointListItr++);
638  const reco::ClusterHit3D* secondEdgeHit = std::get<2>(*extremePointListItr);
639  Eigen::Vector3f edgeVec(secondEdgeHit->getPosition()[0] - firstEdgeHit->getPosition()[0],
640  secondEdgeHit->getPosition()[1] - firstEdgeHit->getPosition()[1],
641  secondEdgeHit->getPosition()[2] - firstEdgeHit->getPosition()[2]);
642  double edgeLen = edgeVec.norm();
643 
644  // normalize it
645  edgeVec.normalize();
646 
647  // Recover the list of 3D hits associated to this cluster
648  reco::HitPairListPtr& clusHitPairVector = clusterToBreak.getHitPairListPtr();
649 
650  // Calculate the doca to the PCA primary axis for each 3D hit
651  // Importantly, this also gives us the arclength along that axis to the hit
652  fPCAAlg.PCAAnalysis_calc3DDocas(clusHitPairVector, fullPCA);
653 
654  // Sort the hits along the PCA
655  clusHitPairVector.sort([](const auto& left, const auto& right){return left->getArclenToPoca() < right->getArclenToPoca();});
656 
657  // Set up container to keep track of edges
658  using DistEdgeTuple = std::tuple<float, const reco::EdgeTuple*>;
659  using DistEdgeTupleVec = std::vector<DistEdgeTuple>;
660 
661  DistEdgeTupleVec distEdgeTupleVec;
662 
663  // Now loop through all the edges and search for the furthers point
664  for(const auto& edge : clusterToBreak.getBestEdgeList())
665  {
666  const reco::ClusterHit3D* nextEdgeHit = std::get<0>(edge); // recover the first point
667 
668  // Create vector to this point from the longest edge
669  Eigen::Vector3f hitToEdgeVec(nextEdgeHit->getPosition()[0] - firstEdgeHit->getPosition()[0],
670  nextEdgeHit->getPosition()[1] - firstEdgeHit->getPosition()[1],
671  nextEdgeHit->getPosition()[2] - firstEdgeHit->getPosition()[2]);
672 
673  // Get projection
674  float hitProjection = hitToEdgeVec.dot(edgeVec);
675 
676  // Require that the point is really "opposite" the longest edge
677  if (hitProjection > 0. && hitProjection < edgeLen)
678  {
679  Eigen::Vector3f distToHitVec = hitToEdgeVec - hitProjection * edgeVec;
680  float distToHit = distToHitVec.norm();
681 
682  distEdgeTupleVec.emplace_back(distToHit,&edge);
683  }
684  }
685 
686  std::sort(distEdgeTupleVec.begin(),distEdgeTupleVec.end(),[](const auto& left,const auto& right){return std::get<0>(left) > std::get<0>(right);});
687 
688  // Get a temporary container to hol
689  reco::ClusterParametersList tempClusterParametersList;
690  float usedDefectDist(0.);
691 
692  for(const auto& distEdgeTuple : distEdgeTupleVec)
693  {
694  const reco::EdgeTuple& edgeTuple = *std::get<1>(distEdgeTuple);
695  const reco::ClusterHit3D* edgeHit = std::get<0>(edgeTuple);
696 
697  usedDefectDist = std::get<0>(distEdgeTuple);
698 
699  // Now find the hit identified above as furthest away
700  reco::HitPairListPtr::iterator vertexItr = std::find(clusHitPairVector.begin(),clusHitPairVector.end(),edgeHit);
701 
702  // Make sure enough hits either side, otherwise we just keep the current cluster
703  if (vertexItr == clusHitPairVector.end() || std::distance(clusHitPairVector.begin(),vertexItr) < int(fMinTinyClusterSize) || std::distance(vertexItr,clusHitPairVector.end()) < int(fMinTinyClusterSize)) continue;
704 
705  tempClusterParametersList.push_back(reco::ClusterParameters());
706 
707  reco::ClusterParameters& clusterParams1 = tempClusterParametersList.back();
708 
709  if (makeCandidateCluster(fullPrimaryVec, clusterParams1, clusHitPairVector.begin(), vertexItr, level))
710  {
711  tempClusterParametersList.push_back(reco::ClusterParameters());
712 
713  reco::ClusterParameters& clusterParams2 = tempClusterParametersList.back();
714 
715  if (makeCandidateCluster(fullPrimaryVec, clusterParams2, vertexItr, clusHitPairVector.end(), level)) break;
716  }
717 
718  // If here then we could not make two valid clusters and so we try again
719  tempClusterParametersList.clear();
720  }
721 
722  // Fallback in the event of still large clusters but not defect points
723  if (tempClusterParametersList.empty())
724  {
725  std::cout << indent << "===> no cluster cands, edgeLen: " << edgeLen << ", # hits: " << clusHitPairVector.size() << ", max defect: " << std::get<0>(distEdgeTupleVec.front()) << std::endl;
726 
727  usedDefectDist = 0.;
728 
729  if (edgeLen > 20.)
730  {
731  reco::HitPairListPtr::iterator vertexItr = clusHitPairVector.begin();
732 
733  std::advance(vertexItr, clusHitPairVector.size()/2);
734 
735  tempClusterParametersList.push_back(reco::ClusterParameters());
736 
737  reco::ClusterParameters& clusterParams1 = tempClusterParametersList.back();
738 
739  if (makeCandidateCluster(fullPrimaryVec, clusterParams1, clusHitPairVector.begin(), vertexItr, level))
740  {
741  tempClusterParametersList.push_back(reco::ClusterParameters());
742 
743  reco::ClusterParameters& clusterParams2 = tempClusterParametersList.back();
744 
745  if (!makeCandidateCluster(fullPrimaryVec, clusterParams2, vertexItr, clusHitPairVector.end(), level))
746  tempClusterParametersList.clear();
747  }
748  }
749  }
750 
751  // Can only end with no candidate clusters or two so don't
752  for(auto& clusterParams : tempClusterParametersList)
753  {
754  size_t curOutputClusterListSize = outputClusterList.size();
755 
756  positionItr = subDivideCluster(clusterParams, fullPCA, positionItr, outputClusterList, level+4);
757 
758  std::cout << indent << "Output cluster list prev: " << curOutputClusterListSize << ", now: " << outputClusterList.size() << std::endl;
759 
760  // If the cluster we sent in was successfully broken then the position iterator will be shifted
761  // This means we don't want to restore the current cluster here
762  if (curOutputClusterListSize < outputClusterList.size()) continue;
763 
764  // I think this is where we fill out the rest of the parameters?
765  // Start by adding the 2D hits...
766  // See if we can avoid duplicates by temporarily transferring to a set
767  std::set<const reco::ClusterHit2D*> hitSet;
768 
769  // Loop through 3D hits to get a set of unique 2D hits
770  for(const auto& hit3D : clusterParams.getHitPairListPtr())
771  {
772  for(const auto& hit2D : hit3D->getHits())
773  {
774  if (hit2D) hitSet.insert(hit2D);
775  }
776  }
777 
778  // Now add these to the new cluster
779  for(const auto& hit2D : hitSet)
780  {
781  hit2D->setStatusBit(reco::ClusterHit2D::USED);
782  clusterParams.UpdateParameters(hit2D);
783  }
784 
785  std::cout << indent << "*********>>> storing new subcluster of size " << clusterParams.getHitPairListPtr().size() << std::endl;
786 
787  positionItr = outputClusterList.insert(positionItr,clusterParams);
788 
789  // Are we filling histograms
790  if (fFillHistograms)
791  {
792  // Recover the new fullPCA
793  reco::PrincipalComponents& newFullPCA = clusterParams.getFullPCA();
794 
795  Eigen::Vector3f newPrimaryVec(fullPCA.getEigenVectors()[0][0],fullPCA.getEigenVectors()[0][1],fullPCA.getEigenVectors()[0][2]);
796  Eigen::Vector3f lastPrimaryVec(newFullPCA.getEigenVectors()[0][0],newFullPCA.getEigenVectors()[0][1],newFullPCA.getEigenVectors()[0][2]);
797 
798  int num3DHits = clusterParams.getHitPairListPtr().size();
799  int numEdges = clusterParams.getBestEdgeList().size();
800  float cosToLast = newPrimaryVec.dot(lastPrimaryVec);
801  double eigen2To1Ratio = eigenValVec[2] / eigenValVec[1];
802  double eigen1To0Ratio = eigenValVec[1] / eigenValVec[0];
803  double eigen2To0Ratio = eigenValVec[2] / eigenValVec[0];
804 
805  fSubNum3DHits->Fill(std::min(num3DHits,199), 1.);
806  fSubNumEdges->Fill(std::min(numEdges,199), 1.);
807  fSubEigen21Ratio->Fill(eigen2To1Ratio, 1.);
808  fSubEigen20Ratio->Fill(eigen2To0Ratio, 1.);
809  fSubEigen10Ratio->Fill(eigen1To0Ratio, 1.);
810  fSubCosToPrevPCA->Fill(cosToLast, 1.);
811  fSubPrimaryLength->Fill(std::min(eigenValVec[0],199.), 1.);
812  fSubCosExtToPCA->Fill(fullPrimaryVec.dot(edgeVec), 1.);
813  fSubMaxDefect->Fill(std::get<0>(distEdgeTupleVec.front()), 1.);
814  fSubUsedDefect->Fill(usedDefectDist, 1.);
815  }
816 
817  // The above points to the element, want the next element
818  positionItr++;
819  }
820  }
821 
822  return positionItr;
823 }
void PCAAnalysis_calc3DDocas(const reco::HitPairListPtr &hitPairVector, const reco::PrincipalComponents &pca) const
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:112
intermediate_table::iterator iterator
intermediate_table::const_iterator const_iterator
std::string indent(std::size_t const i)
reco::ClusterParametersList::iterator subDivideCluster(reco::ClusterParameters &cluster, reco::PrincipalComponents &lastPCA, reco::ClusterParametersList::iterator positionItr, reco::ClusterParametersList &outputClusterList, int level=0) const
Use PCA to try to find path in cluster.
std::tuple< const reco::ClusterHit3D *, const reco::ClusterHit3D *, double > EdgeTuple
Definition: Cluster3D.h:325
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:317
const float * getPosition() const
Definition: Cluster3D.h:147
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:104
const float * getEigenValues() const
Definition: Cluster3D.h:228
Int_t min
Definition: plot.C:26
bool makeCandidateCluster(Eigen::Vector3f &, reco::ClusterParameters &, reco::HitPairListPtr::iterator, reco::HitPairListPtr::iterator, int) const
size_t fMinTinyClusterSize
Minimum size for a "tiny" cluster.
bool fFillHistograms
Histogram definitions.
std::list< ClusterParameters > ClusterParametersList
Definition: Cluster3D.h:381
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:229

Member Data Documentation

std::unique_ptr<lar_cluster3d::IClusterAlg> lar_cluster3d::VoronoiPathFinder::fClusterAlg
private

Algorithm to do 3D space point clustering.

Definition at line 171 of file VoronoiPathFinder_tool.cc.

Referenced by configure().

bool lar_cluster3d::VoronoiPathFinder::fEnableMonitoring
private

FHICL parameters.

Definition at line 139 of file VoronoiPathFinder_tool.cc.

Referenced by configure(), and ModifyClusters().

bool lar_cluster3d::VoronoiPathFinder::fFillHistograms
private

Histogram definitions.

Definition at line 146 of file VoronoiPathFinder_tool.cc.

Referenced by breakIntoTinyBits(), initializeHistograms(), ModifyClusters(), and subDivideCluster().

geo::Geometry* lar_cluster3d::VoronoiPathFinder::fGeometry
private

Tools.

Definition at line 169 of file VoronoiPathFinder_tool.cc.

Referenced by configure().

size_t lar_cluster3d::VoronoiPathFinder::fMinTinyClusterSize
private

Minimum size for a "tiny" cluster.

Definition at line 140 of file VoronoiPathFinder_tool.cc.

Referenced by breakIntoTinyBits(), configure(), ModifyClusters(), and subDivideCluster().

PrincipalComponentsAlg lar_cluster3d::VoronoiPathFinder::fPCAAlg
private
TH1F* lar_cluster3d::VoronoiPathFinder::fSubCosExtToPCA
private

Definition at line 162 of file VoronoiPathFinder_tool.cc.

Referenced by initializeHistograms(), and subDivideCluster().

TH1F* lar_cluster3d::VoronoiPathFinder::fSubCosToPrevPCA
private
TH1F* lar_cluster3d::VoronoiPathFinder::fSubEigen10Ratio
private
TH1F* lar_cluster3d::VoronoiPathFinder::fSubEigen20Ratio
private
TH1F* lar_cluster3d::VoronoiPathFinder::fSubEigen21Ratio
private
TH1F* lar_cluster3d::VoronoiPathFinder::fSubMaxDefect
private

Definition at line 163 of file VoronoiPathFinder_tool.cc.

Referenced by initializeHistograms(), and subDivideCluster().

TH1F* lar_cluster3d::VoronoiPathFinder::fSubNum3DHits
private
TH1F* lar_cluster3d::VoronoiPathFinder::fSubNumEdges
private
TH1F* lar_cluster3d::VoronoiPathFinder::fSubPrimaryLength
private
TH1F* lar_cluster3d::VoronoiPathFinder::fSubUsedDefect
private

Definition at line 164 of file VoronoiPathFinder_tool.cc.

Referenced by initializeHistograms(), and subDivideCluster().

float lar_cluster3d::VoronoiPathFinder::fTimeToProcess
mutableprivate

Definition at line 141 of file VoronoiPathFinder_tool.cc.

Referenced by configure(), getTimeToExecute(), and ModifyClusters().

TH1F* lar_cluster3d::VoronoiPathFinder::fTopEigen10Ratio
private

Definition at line 152 of file VoronoiPathFinder_tool.cc.

Referenced by initializeHistograms(), and ModifyClusters().

TH1F* lar_cluster3d::VoronoiPathFinder::fTopEigen20Ratio
private

Definition at line 151 of file VoronoiPathFinder_tool.cc.

Referenced by initializeHistograms(), and ModifyClusters().

TH1F* lar_cluster3d::VoronoiPathFinder::fTopEigen21Ratio
private

Definition at line 150 of file VoronoiPathFinder_tool.cc.

Referenced by initializeHistograms(), and ModifyClusters().

TH1F* lar_cluster3d::VoronoiPathFinder::fTopNum3DHits
private

Definition at line 148 of file VoronoiPathFinder_tool.cc.

Referenced by initializeHistograms(), and ModifyClusters().

TH1F* lar_cluster3d::VoronoiPathFinder::fTopNumEdges
private

Definition at line 149 of file VoronoiPathFinder_tool.cc.

Referenced by initializeHistograms(), and ModifyClusters().

TH1F* lar_cluster3d::VoronoiPathFinder::fTopPrimaryLength
private

Definition at line 153 of file VoronoiPathFinder_tool.cc.

Referenced by initializeHistograms(), and ModifyClusters().


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