LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
lar_cluster3d::ConvexHullPathFinder Class Referenceabstract
Inheritance diagram for lar_cluster3d::ConvexHullPathFinder:
lar_cluster3d::IClusterModAlg

Public Member Functions

 ConvexHullPathFinder (const fhicl::ParameterSet &)
 Constructor. More...
 
 ~ConvexHullPathFinder ()
 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 HitOrderTuple = std::tuple< float, float, reco::ProjectedPoint >
 
using HitOrderTupleList = std::list< HitOrderTuple >
 
using MinMaxPoints = std::pair< reco::ProjectedPoint, reco::ProjectedPoint >
 
using MinMaxPointPair = std::pair< MinMaxPoints, MinMaxPoints >
 
using KinkTuple = std::tuple< int, reco::ConvexHullKinkTuple, HitOrderTupleList, HitOrderTupleList >
 
using KinkTupleVec = std::vector< KinkTuple >
 

Private Member Functions

reco::ClusterParametersList::iterator subDivideCluster (reco::ClusterParameters &cluster, 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
 
bool makeCandidateCluster (Eigen::Vector3f &, reco::ClusterParameters &, HitOrderTupleList &, int) const
 
bool completeCandidateCluster (Eigen::Vector3f &, reco::ClusterParameters &, int) const
 
bool breakClusterByKinks (reco::ClusterParameters &, reco::ClusterParametersList &, int level) const
 
bool breakClusterByKinksTrial (reco::ClusterParameters &, reco::ClusterParametersList &, int level) const
 
bool breakClusterByMaxDefect (reco::ClusterParameters &, reco::ClusterParametersList &, int level) const
 
bool breakClusterInHalf (reco::ClusterParameters &, reco::ClusterParametersList &, int level) const
 
bool breakClusterAtBigGap (reco::ClusterParameters &, reco::ClusterParametersList &, int level) 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 orderHitsAlongEdge (const reco::ProjectedPointList &, const reco::ProjectedPoint &, const Eigen::Vector2f &, HitOrderTupleList &) const
 
void pruneHitOrderTupleLists (HitOrderTupleList &, HitOrderTupleList &) const
 
void fillConvexHullHists (reco::ClusterParameters &, bool) const
 

Private Attributes

bool fEnableMonitoring
 FHICL parameters. More...
 
size_t fMinTinyClusterSize
 Minimum size for a "tiny" cluster. More...
 
float fMinGapSize
 Minimum gap size to break at gaps. More...
 
float fMinEigen0To1Ratio
 Minimum ratio of eigen 0 to 1 to continue breaking. More...
 
float fConvexHullKinkAngle
 Angle to declare a kink in convex hull calc. More...
 
float fConvexHullMinSep
 Min hit separation to conisder in convex hull. More...
 
float fTimeToProcess
 
bool fFillHistograms
 Histogram definitions. More...
 
TH1F * fTopNum3DHits
 
TH1F * fTopNumEdges
 
TH1F * fTopEigen21Ratio
 
TH1F * fTopEigen20Ratio
 
TH1F * fTopEigen10Ratio
 
TH1F * fTopPrimaryLength
 
TH1F * fTopExtremeSep
 
TH1F * fTopConvexCosEdge
 
TH1F * fTopConvexEdgeLen
 
TH1F * fSubNum3DHits
 
TH1F * fSubNumEdges
 
TH1F * fSubEigen21Ratio
 
TH1F * fSubEigen20Ratio
 
TH1F * fSubEigen10Ratio
 
TH1F * fSubPrimaryLength
 
TH1F * fSubCosToPrevPCA
 
TH1F * fSubCosExtToPCA
 
TH1F * fSubConvexCosEdge
 
TH1F * fSubConvexEdgeLen
 
TH1F * fSubMaxDefect
 
TH1F * fSubUsedDefect
 
std::unique_ptr< lar_cluster3d::IClusterAlgfClusterAlg
 Tools. More...
 
PrincipalComponentsAlg fPCAAlg
 

Detailed Description

Definition at line 39 of file ConvexHullPathFinder_tool.cc.

Member Typedef Documentation

Definition at line 89 of file ConvexHullPathFinder_tool.cc.

Definition at line 135 of file ConvexHullPathFinder_tool.cc.

Constructor & Destructor Documentation

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

Constructor.

Parameters
pset

Definition at line 193 of file ConvexHullPathFinder_tool.cc.

References configure().

194  : fPCAAlg(pset.get<fhicl::ParameterSet>("PrincipalComponentsAlg"))
195  {
196  this->configure(pset);
197  }
void configure(fhicl::ParameterSet const &pset) override
lar_cluster3d::ConvexHullPathFinder::~ConvexHullPathFinder ( )

Destructor.

Definition at line 201 of file ConvexHullPathFinder_tool.cc.

201 {}

Member Function Documentation

bool lar_cluster3d::ConvexHullPathFinder::breakClusterAtBigGap ( reco::ClusterParameters clusterToBreak,
reco::ClusterParametersList outputClusterList,
int  level 
) const
private

Definition at line 1020 of file ConvexHullPathFinder_tool.cc.

References util::abs(), fMinGapSize, fPCAAlg, reco::ClusterParameters::getFullPCA(), reco::ClusterParameters::getHitPairListPtr(), art::left(), makeCandidateCluster(), lar_cluster3d::PrincipalComponentsAlg::PCAAnalysis_calc3DDocas(), and art::right().

Referenced by subDivideCluster().

1023  {
1024  // Idea here is to scan the input hit list (assumed ordered along the current PCA) and look for "large" gaps
1025  // Here a gap is determined when the hits were ordered by their distance along the primary PCA to their doca to it.
1026  reco::PrincipalComponents& fullPCA(clusterToBreak.getFullPCA());
1027 
1028  // Recover our hits
1029  reco::HitPairListPtr& hitList = clusterToBreak.getHitPairListPtr();
1030 
1031  // Calculate the doca to the PCA primary axis for each 3D hit
1032  // Importantly, this also gives us the arclength along that axis to the hit
1033  fPCAAlg.PCAAnalysis_calc3DDocas(hitList, fullPCA);
1034 
1035  // Sort the hits along the PCA
1036  hitList.sort([](const auto& left, const auto& right) {
1037  return left->getArclenToPoca() < right->getArclenToPoca();
1038  });
1039 
1040  // Loop through the input hit list and keep track of first hit of largest gap
1041  reco::HitPairListPtr::iterator bigGapHitItr = hitList.begin();
1042  float biggestGap = 0.;
1043 
1044  reco::HitPairListPtr::iterator lastHitItr = hitList.begin();
1045 
1046  for (reco::HitPairListPtr::iterator hitItr = hitList.begin(); hitItr != hitList.end();
1047  hitItr++) {
1048  float currentGap = std::abs((*hitItr)->getArclenToPoca() - (*lastHitItr)->getArclenToPoca());
1049 
1050  if (currentGap > biggestGap) {
1051  bigGapHitItr =
1052  hitItr; // Note that this is an iterator and will be the "end" going from begin, and "begin" for second half
1053  biggestGap = currentGap;
1054  }
1055 
1056  lastHitItr = hitItr;
1057  }
1058 
1059  // Require some minimum gap size...
1060  if (biggestGap > fMinGapSize) {
1061  outputClusterList.push_back(reco::ClusterParameters());
1062 
1063  reco::ClusterParameters& clusterParams1 = outputClusterList.back();
1064 
1065  reco::PrincipalComponents& fullPCA(clusterToBreak.getFullPCA());
1066  Eigen::Vector3f fullPrimaryVec(fullPCA.getEigenVectors().row(2));
1067 
1069  fullPrimaryVec, clusterParams1, hitList.begin(), bigGapHitItr, level)) {
1070  outputClusterList.push_back(reco::ClusterParameters());
1071 
1072  reco::ClusterParameters& clusterParams2 = outputClusterList.back();
1073 
1074  makeCandidateCluster(fullPrimaryVec, clusterParams2, bigGapHitItr, hitList.end(), level);
1075  }
1076 
1077  if (outputClusterList.size() != 2) outputClusterList.clear();
1078  }
1079 
1080  return !outputClusterList.empty();
1081  }
intermediate_table::iterator iterator
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:102
constexpr auto abs(T v)
Returns the absolute value of the argument.
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:463
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:464
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:326
bool makeCandidateCluster(Eigen::Vector3f &, reco::ClusterParameters &, reco::HitPairListPtr::iterator, reco::HitPairListPtr::iterator, int) const
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:94
float fMinGapSize
Minimum gap size to break at gaps.
bool lar_cluster3d::ConvexHullPathFinder::breakClusterByKinks ( reco::ClusterParameters clusterToBreak,
reco::ClusterParametersList outputClusterList,
int  level 
) const
private

Definition at line 644 of file ConvexHullPathFinder_tool.cc.

References fFillHistograms, fillConvexHullHists(), fMinTinyClusterSize, reco::ClusterParameters::getConvexHull(), reco::ConvexHull::getConvexHullKinkPoints(), reco::ClusterParameters::getFullPCA(), reco::ClusterParameters::getHitPairListPtr(), art::left(), makeCandidateCluster(), and art::right().

Referenced by subDivideCluster().

647  {
648  // Set up container to keep track of edges
649  using HitKinkTuple = std::tuple<int, reco::HitPairListPtr::iterator>;
650  using HitKinkTupleVec = std::vector<HitKinkTuple>;
651 
652  // Recover our hits
653  reco::HitPairListPtr& hitList = clusterToBreak.getHitPairListPtr();
654 
655  // Set up container to keep track of edges
656  HitKinkTupleVec kinkTupleVec;
657 
658  reco::ConvexHull& convexHull = clusterToBreak.getConvexHull();
659  reco::ConvexHullKinkTupleList& kinkPointList = convexHull.getConvexHullKinkPoints();
660 
661  for (auto& kink : kinkPointList) {
662  const reco::ClusterHit3D* hit3D = std::get<2>(std::get<0>(kink));
663 
664  reco::HitPairListPtr::iterator kinkItr = std::find(hitList.begin(), hitList.end(), hit3D);
665 
666  if (kinkItr == hitList.end()) continue;
667 
668  int numStartToKink = std::distance(hitList.begin(), kinkItr);
669  int numKinkToEnd = std::distance(kinkItr, hitList.end());
670  int minNumHits = std::min(numStartToKink, numKinkToEnd);
671 
672  if (minNumHits > int(fMinTinyClusterSize)) kinkTupleVec.emplace_back(minNumHits, kinkItr);
673  }
674 
675  // No work if the list is empty
676  if (!kinkTupleVec.empty()) {
677  std::sort(kinkTupleVec.begin(), kinkTupleVec.end(), [](const auto& left, const auto& right) {
678  return std::get<0>(left) > std::get<0>(right);
679  });
680 
681  // Recover the kink point
682  reco::HitPairListPtr::iterator kinkItr = std::get<1>(kinkTupleVec.front());
683 
684  // Set up to split the input cluster
685  outputClusterList.push_back(reco::ClusterParameters());
686 
687  reco::ClusterParameters& clusterParams1 = outputClusterList.back();
688 
689  reco::PrincipalComponents& fullPCA(clusterToBreak.getFullPCA());
690  Eigen::Vector3f fullPrimaryVec(fullPCA.getEigenVectors().row(2));
691 
692  if (makeCandidateCluster(fullPrimaryVec, clusterParams1, hitList.begin(), kinkItr, level)) {
693  outputClusterList.push_back(reco::ClusterParameters());
694 
695  reco::ClusterParameters& clusterParams2 = outputClusterList.back();
696 
697  makeCandidateCluster(fullPrimaryVec, clusterParams2, kinkItr, hitList.end(), level);
698 
699  if (fFillHistograms) {
700  fillConvexHullHists(clusterParams1, false);
701  fillConvexHullHists(clusterParams2, false);
702  }
703  }
704 
705  // If we did not make 2 clusters then be sure to clear the output list
706  if (outputClusterList.size() != 2) outputClusterList.clear();
707  }
708 
709  return !outputClusterList.empty();
710  }
size_t fMinTinyClusterSize
Minimum size for a "tiny" cluster.
intermediate_table::iterator iterator
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:102
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:463
void fillConvexHullHists(reco::ClusterParameters &, bool) const
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:464
reco::ConvexHullKinkTupleList & getConvexHullKinkPoints()
Definition: Cluster3D.h:375
Define a container for working with the convex hull.
Definition: Cluster3D.h:354
std::list< ConvexHullKinkTuple > ConvexHullKinkTupleList
Definition: Cluster3D.h:349
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:326
bool makeCandidateCluster(Eigen::Vector3f &, reco::ClusterParameters &, reco::HitPairListPtr::iterator, reco::HitPairListPtr::iterator, int) const
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:94
reco::ConvexHull & getConvexHull()
Definition: Cluster3D.h:469
bool lar_cluster3d::ConvexHullPathFinder::breakClusterByKinksTrial ( reco::ClusterParameters clusterToBreak,
reco::ClusterParametersList outputClusterList,
int  level 
) const
private

Definition at line 712 of file ConvexHullPathFinder_tool.cc.

References fFillHistograms, fillConvexHullHists(), fMinTinyClusterSize, reco::ClusterParameters::getConvexHull(), reco::ConvexHull::getConvexHullKinkPoints(), reco::ClusterParameters::getFullPCA(), reco::ConvexHull::getProjectedPointList(), art::left(), makeCandidateCluster(), orderHitsAlongEdge(), pruneHitOrderTupleLists(), and art::right().

716  {
717  // Set up container to keep track of edges
718  KinkTupleVec kinkTupleVec;
719 
720  reco::ConvexHull& convexHull = clusterToBreak.getConvexHull();
721  reco::ProjectedPointList& pointList = convexHull.getProjectedPointList();
722  reco::ConvexHullKinkTupleList& kinkPointList = convexHull.getConvexHullKinkPoints();
723 
724  for (auto& kink : kinkPointList) {
725  // Make an instance of the vec value to avoid copying if we can...
726  kinkTupleVec.push_back(KinkTuple());
727 
728  KinkTuple& kinkTuple = kinkTupleVec.back();
729 
730  std::get<1>(kinkTuple) = kink;
731 
732  // Recover vectors, want them pointing away from intersection point
733  Eigen::Vector2f firstEdge = -std::get<1>(kink);
734  HitOrderTupleList& firstList = std::get<2>(kinkTuple);
735  HitOrderTupleList& secondList = std::get<3>(kinkTuple);
736 
737  orderHitsAlongEdge(pointList, std::get<0>(kink), firstEdge, firstList);
738 
739  if (firstList.size() > fMinTinyClusterSize) {
740  Eigen::Vector2f secondEdge = std::get<2>(kink);
741 
742  orderHitsAlongEdge(pointList, std::get<0>(kink), secondEdge, secondList);
743 
744  if (secondList.size() > fMinTinyClusterSize)
745  std::get<0>(kinkTuple) = std::min(firstList.size(), secondList.size());
746  }
747 
748  // Special handling...
749  if (firstList.size() + secondList.size() > pointList.size()) {
750  if (firstList.size() > secondList.size())
751  pruneHitOrderTupleLists(firstList, secondList);
752  else
753  pruneHitOrderTupleLists(secondList, firstList);
754 
755  std::get<0>(kinkTuple) = std::min(firstList.size(), secondList.size());
756  }
757 
758  if (std::get<0>(kinkTuple) < int(fMinTinyClusterSize)) kinkTupleVec.pop_back();
759  }
760 
761  // No work if the list is empty
762  if (!kinkTupleVec.empty()) {
763  // If more than one then want the kink with the most elements both sizes
764  std::sort(kinkTupleVec.begin(), kinkTupleVec.end(), [](const auto& left, const auto& right) {
765  return std::get<0>(left) > std::get<0>(right);
766  });
767 
768  // Recover the kink point
769  KinkTuple& kinkTuple = kinkTupleVec.front();
770 
771  // Set up to split the input cluster
772  outputClusterList.push_back(reco::ClusterParameters());
773 
774  reco::ClusterParameters& clusterParams1 = outputClusterList.back();
775 
776  reco::PrincipalComponents& fullPCA(clusterToBreak.getFullPCA());
777  Eigen::Vector3f fullPrimaryVec(fullPCA.getEigenVectors().row(2));
778 
779  if (makeCandidateCluster(fullPrimaryVec, clusterParams1, std::get<2>(kinkTuple), level)) {
780  outputClusterList.push_back(reco::ClusterParameters());
781 
782  reco::ClusterParameters& clusterParams2 = outputClusterList.back();
783 
784  makeCandidateCluster(fullPrimaryVec, clusterParams2, std::get<3>(kinkTuple), level);
785 
786  if (fFillHistograms) {
787  fillConvexHullHists(clusterParams1, false);
788  fillConvexHullHists(clusterParams2, false);
789  }
790  }
791 
792  // If we did not make 2 clusters then be sure to clear the output list
793  if (outputClusterList.size() != 2) outputClusterList.clear();
794  }
795 
796  return !outputClusterList.empty();
797  }
size_t fMinTinyClusterSize
Minimum size for a "tiny" cluster.
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:102
std::tuple< int, reco::ConvexHullKinkTuple, HitOrderTupleList, HitOrderTupleList > KinkTuple
std::list< ProjectedPoint > ProjectedPointList
Definition: Cluster3D.h:346
void fillConvexHullHists(reco::ClusterParameters &, bool) const
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:464
reco::ConvexHullKinkTupleList & getConvexHullKinkPoints()
Definition: Cluster3D.h:375
Define a container for working with the convex hull.
Definition: Cluster3D.h:354
void pruneHitOrderTupleLists(HitOrderTupleList &, HitOrderTupleList &) const
std::list< ConvexHullKinkTuple > ConvexHullKinkTupleList
Definition: Cluster3D.h:349
bool makeCandidateCluster(Eigen::Vector3f &, reco::ClusterParameters &, reco::HitPairListPtr::iterator, reco::HitPairListPtr::iterator, int) const
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:94
reco::ConvexHull & getConvexHull()
Definition: Cluster3D.h:469
void orderHitsAlongEdge(const reco::ProjectedPointList &, const reco::ProjectedPoint &, const Eigen::Vector2f &, HitOrderTupleList &) const
reco::ProjectedPointList & getProjectedPointList()
Definition: Cluster3D.h:370
bool lar_cluster3d::ConvexHullPathFinder::breakClusterByMaxDefect ( reco::ClusterParameters clusterToBreak,
reco::ClusterParametersList outputClusterList,
int  level 
) const
private

Definition at line 873 of file ConvexHullPathFinder_tool.cc.

References fFillHistograms, fMinTinyClusterSize, fPCAAlg, fSubMaxDefect, fSubUsedDefect, reco::ClusterParameters::getBestEdgeList(), reco::ClusterParameters::getConvexHull(), reco::ConvexHull::getConvexHullExtremePoints(), reco::ClusterParameters::getFullPCA(), reco::ClusterParameters::getHitPairListPtr(), reco::ClusterHit3D::getPosition(), art::left(), makeCandidateCluster(), lar_cluster3d::PrincipalComponentsAlg::PCAAnalysis_calc3DDocas(), and art::right().

Referenced by subDivideCluster().

876  {
877  // Set up container to keep track of edges
878  using DistEdgeTuple = std::tuple<float, const reco::EdgeTuple*>;
879  using DistEdgeTupleVec = std::vector<DistEdgeTuple>;
880 
881  DistEdgeTupleVec distEdgeTupleVec;
882 
883  reco::ProjectedPointList::const_iterator extremePointListItr =
884  clusterToBreak.getConvexHull().getConvexHullExtremePoints().begin();
885 
886  const reco::ClusterHit3D* firstEdgeHit = std::get<2>(*extremePointListItr++);
887  const reco::ClusterHit3D* secondEdgeHit = std::get<2>(*extremePointListItr);
888  Eigen::Vector3f edgeVec(secondEdgeHit->getPosition()[0] - firstEdgeHit->getPosition()[0],
889  secondEdgeHit->getPosition()[1] - firstEdgeHit->getPosition()[1],
890  secondEdgeHit->getPosition()[2] - firstEdgeHit->getPosition()[2]);
891  double edgeLen = edgeVec.norm();
892 
893  // normalize it
894  edgeVec.normalize();
895 
896  // Now loop through all the edges and search for the furthers point
897  for (const auto& edge : clusterToBreak.getBestEdgeList()) {
898  const reco::ClusterHit3D* nextEdgeHit = std::get<0>(edge); // recover the first point
899 
900  // Create vector to this point from the longest edge
901  Eigen::Vector3f hitToEdgeVec(nextEdgeHit->getPosition()[0] - firstEdgeHit->getPosition()[0],
902  nextEdgeHit->getPosition()[1] - firstEdgeHit->getPosition()[1],
903  nextEdgeHit->getPosition()[2] - firstEdgeHit->getPosition()[2]);
904 
905  // Get projection
906  float hitProjection = hitToEdgeVec.dot(edgeVec);
907 
908  // Require that the point is really "opposite" the longest edge
909  if (hitProjection > 0. && hitProjection < edgeLen) {
910  Eigen::Vector3f distToHitVec = hitToEdgeVec - hitProjection * edgeVec;
911  float distToHit = distToHitVec.norm();
912 
913  distEdgeTupleVec.emplace_back(distToHit, &edge);
914  }
915  }
916 
917  std::sort(
918  distEdgeTupleVec.begin(), distEdgeTupleVec.end(), [](const auto& left, const auto& right) {
919  return std::get<0>(left) > std::get<0>(right);
920  });
921 
922  reco::PrincipalComponents& fullPCA(clusterToBreak.getFullPCA());
923  Eigen::Vector3f fullPrimaryVec(fullPCA.getEigenVectors().row(2));
924 
925  // Recover our hits
926  reco::HitPairListPtr& hitList = clusterToBreak.getHitPairListPtr();
927 
928  // Calculate the doca to the PCA primary axis for each 3D hit
929  // Importantly, this also gives us the arclength along that axis to the hit
930  fPCAAlg.PCAAnalysis_calc3DDocas(hitList, fullPCA);
931 
932  // Sort the hits along the PCA
933  hitList.sort([](const auto& left, const auto& right) {
934  return left->getArclenToPoca() < right->getArclenToPoca();
935  });
936 
937  // Get a temporary container to hol
938  float usedDefectDist(0.);
939 
940  for (const auto& distEdgeTuple : distEdgeTupleVec) {
941  const reco::EdgeTuple& edgeTuple = *std::get<1>(distEdgeTuple);
942  const reco::ClusterHit3D* edgeHit = std::get<0>(edgeTuple);
943 
944  usedDefectDist = std::get<0>(distEdgeTuple);
945 
946  // Now find the hit identified above as furthest away
947  reco::HitPairListPtr::iterator vertexItr = std::find(hitList.begin(), hitList.end(), edgeHit);
948 
949  // Make sure enough hits either side, otherwise we just keep the current cluster
950  if (vertexItr == hitList.end() ||
951  std::distance(hitList.begin(), vertexItr) < int(fMinTinyClusterSize) ||
952  std::distance(vertexItr, hitList.end()) < int(fMinTinyClusterSize))
953  continue;
954 
955  outputClusterList.push_back(reco::ClusterParameters());
956 
957  reco::ClusterParameters& clusterParams1 = outputClusterList.back();
958 
959  if (makeCandidateCluster(fullPrimaryVec, clusterParams1, hitList.begin(), vertexItr, level)) {
960  outputClusterList.push_back(reco::ClusterParameters());
961 
962  reco::ClusterParameters& clusterParams2 = outputClusterList.back();
963 
964  if (makeCandidateCluster(fullPrimaryVec, clusterParams2, vertexItr, hitList.end(), level)) {
965  if (fFillHistograms) {
966  fSubMaxDefect->Fill(std::get<0>(distEdgeTupleVec.front()), 1.);
967  fSubUsedDefect->Fill(usedDefectDist, 1.);
968  }
969  break;
970  }
971  }
972 
973  // If here then we could not make two valid clusters and so we try again
974  outputClusterList.clear();
975  }
976 
977  return !outputClusterList.empty();
978  }
size_t fMinTinyClusterSize
Minimum size for a "tiny" cluster.
intermediate_table::iterator iterator
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:102
const Eigen::Vector3f getPosition() const
Definition: Cluster3D.h:155
reco::EdgeList & getBestEdgeList()
Definition: Cluster3D.h:468
intermediate_table::const_iterator const_iterator
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:463
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:464
std::tuple< const reco::ClusterHit3D *, const reco::ClusterHit3D *, double > EdgeTuple
Definition: Cluster3D.h:336
reco::ProjectedPointList & getConvexHullExtremePoints()
Definition: Cluster3D.h:374
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:326
bool makeCandidateCluster(Eigen::Vector3f &, reco::ClusterParameters &, reco::HitPairListPtr::iterator, reco::HitPairListPtr::iterator, int) const
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:94
reco::ConvexHull & getConvexHull()
Definition: Cluster3D.h:469
bool lar_cluster3d::ConvexHullPathFinder::breakClusterInHalf ( reco::ClusterParameters clusterToBreak,
reco::ClusterParametersList outputClusterList,
int  level 
) const
private

Definition at line 980 of file ConvexHullPathFinder_tool.cc.

References fPCAAlg, reco::ClusterParameters::getFullPCA(), reco::ClusterParameters::getHitPairListPtr(), art::left(), makeCandidateCluster(), lar_cluster3d::PrincipalComponentsAlg::PCAAnalysis_calc3DDocas(), and art::right().

Referenced by subDivideCluster().

983  {
984  reco::PrincipalComponents& fullPCA(clusterToBreak.getFullPCA());
985  Eigen::Vector3f fullPrimaryVec(fullPCA.getEigenVectors().row(2));
986 
987  // Recover our hits
988  reco::HitPairListPtr& hitList = clusterToBreak.getHitPairListPtr();
989 
990  // Calculate the doca to the PCA primary axis for each 3D hit
991  // Importantly, this also gives us the arclength along that axis to the hit
992  fPCAAlg.PCAAnalysis_calc3DDocas(hitList, fullPCA);
993 
994  // Sort the hits along the PCA
995  hitList.sort([](const auto& left, const auto& right) {
996  return left->getArclenToPoca() < right->getArclenToPoca();
997  });
998 
999  reco::HitPairListPtr::iterator vertexItr = hitList.begin();
1000 
1001  std::advance(vertexItr, hitList.size() / 2);
1002 
1003  outputClusterList.push_back(reco::ClusterParameters());
1004 
1005  reco::ClusterParameters& clusterParams1 = outputClusterList.back();
1006 
1007  if (makeCandidateCluster(fullPrimaryVec, clusterParams1, hitList.begin(), vertexItr, level)) {
1008  outputClusterList.push_back(reco::ClusterParameters());
1009 
1010  reco::ClusterParameters& clusterParams2 = outputClusterList.back();
1011 
1012  makeCandidateCluster(fullPrimaryVec, clusterParams2, vertexItr, hitList.end(), level);
1013  }
1014 
1015  if (outputClusterList.size() != 2) outputClusterList.clear();
1016 
1017  return !outputClusterList.empty();
1018  }
intermediate_table::iterator iterator
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:102
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:463
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:464
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:326
bool makeCandidateCluster(Eigen::Vector3f &, reco::ClusterParameters &, reco::HitPairListPtr::iterator, reco::HitPairListPtr::iterator, int) const
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:94
void lar_cluster3d::ConvexHullPathFinder::buildConvexHull ( reco::ClusterParameters clusterParameters,
int  level = 0 
) const
private

Definition at line 1083 of file ConvexHullPathFinder_tool.cc.

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

Referenced by completeCandidateCluster(), and ModifyClusters().

1085  {
1086  // set an indention string
1087  std::string minuses(level / 2, '-');
1088  std::string indent(level / 2, ' ');
1089 
1090  indent += minuses;
1091 
1092  // The plan is to build the enclosing 2D polygon around the points in the PCA plane of most spread for this cluster
1093  // To do so we need to start by building a list of 2D projections onto the plane of most spread...
1094  reco::PrincipalComponents& pca = clusterParameters.getFullPCA();
1095 
1096  // Recover the parameters from the Principal Components Analysis that we need to project and accumulate
1097  const Eigen::Vector3f& pcaCenter = pca.getAvePosition();
1098  reco::ConvexHull& convexHull = clusterParameters.getConvexHull();
1099  reco::ProjectedPointList& pointList = convexHull.getProjectedPointList();
1100 
1101  // Loop through hits and do projection to plane
1102  for (const auto& hit3D : clusterParameters.getHitPairListPtr()) {
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 = pca.getEigenVectors() * pcaToHitVec;
1107 
1108  pointList.emplace_back(pcaToHit(1), pcaToHit(2), hit3D);
1109  }
1110 
1111  // Sort the point vec by increasing x, then increase y
1112  pointList.sort([](const auto& left, const auto& right) {
1113  return (std::abs(std::get<0>(left) - std::get<0>(right)) >
1114  std::numeric_limits<float>::epsilon()) ?
1115  std::get<0>(left) < std::get<0>(right) :
1116  std::get<1>(left) < std::get<1>(right);
1117  });
1118 
1119  // containers for finding the "best" hull...
1120  std::vector<ConvexHull> convexHullVec;
1121  std::vector<reco::ProjectedPointList> rejectedListVec;
1122  bool increaseDepth(pointList.size() > 3);
1123  float lastArea(std::numeric_limits<float>::max());
1124 
1125  while (increaseDepth) {
1126  // Get another convexHull container
1127  convexHullVec.push_back(ConvexHull(pointList, fConvexHullKinkAngle, fConvexHullMinSep));
1128  rejectedListVec.push_back(reco::ProjectedPointList());
1129 
1130  const ConvexHull& convexHull = convexHullVec.back();
1131  reco::ProjectedPointList& rejectedList = rejectedListVec.back();
1132  const reco::ProjectedPointList& convexHullPoints = convexHull.getConvexHull();
1133 
1134  increaseDepth = false;
1135 
1136  if (convexHull.getConvexHullArea() > 0.) {
1137  if (convexHullVec.size() < 2 || convexHull.getConvexHullArea() < 0.8 * lastArea) {
1138  for (auto& point : convexHullPoints) {
1139  pointList.remove(point);
1140  rejectedList.emplace_back(point);
1141  }
1142  lastArea = convexHull.getConvexHullArea();
1143  // increaseDepth = true;
1144  }
1145  }
1146  }
1147 
1148  // do we have a valid convexHull?
1149  while (!convexHullVec.empty() && convexHullVec.back().getConvexHullArea() < 0.5) {
1150  convexHullVec.pop_back();
1151  rejectedListVec.pop_back();
1152  }
1153 
1154  // If we found the convex hull then build edges around the region
1155  if (!convexHullVec.empty()) {
1156  reco::HitPairListPtr hitPairListPtr = clusterParameters.getHitPairListPtr();
1157 
1158  for (const auto& rejectedList : rejectedListVec) {
1159  for (const auto& rejectedPoint : rejectedList) {
1160  if (convexHullVec.back().findNearestDistance(rejectedPoint) > 0.5)
1161  hitPairListPtr.remove(std::get<2>(rejectedPoint));
1162  }
1163  }
1164 
1165  // Now add "edges" to the cluster to describe the convex hull (for the display)
1166  reco::ProjectedPointList& convexHullPointList = convexHull.getConvexHullPointList();
1167  reco::Hit3DToEdgeMap& edgeMap = convexHull.getConvexHullEdgeMap();
1168  reco::EdgeList& edgeList = convexHull.getConvexHullEdgeList();
1169 
1170  reco::ProjectedPoint lastPoint = convexHullVec.back().getConvexHull().front();
1171 
1172  for (auto& curPoint : convexHullVec.back().getConvexHull()) {
1173  if (curPoint == lastPoint) continue;
1174 
1175  const reco::ClusterHit3D* lastPoint3D = std::get<2>(lastPoint);
1176  const reco::ClusterHit3D* curPoint3D = std::get<2>(curPoint);
1177 
1178  float distBetweenPoints = (curPoint3D->getPosition()[0] - lastPoint3D->getPosition()[0]) *
1179  (curPoint3D->getPosition()[0] - lastPoint3D->getPosition()[0]) +
1180  (curPoint3D->getPosition()[1] - lastPoint3D->getPosition()[1]) *
1181  (curPoint3D->getPosition()[1] - lastPoint3D->getPosition()[1]) +
1182  (curPoint3D->getPosition()[2] - lastPoint3D->getPosition()[2]) *
1183  (curPoint3D->getPosition()[2] - lastPoint3D->getPosition()[2]);
1184 
1185  distBetweenPoints = std::sqrt(distBetweenPoints);
1186 
1187  reco::EdgeTuple edge(lastPoint3D, curPoint3D, distBetweenPoints);
1188 
1189  convexHullPointList.push_back(curPoint);
1190  edgeMap[lastPoint3D].push_back(edge);
1191  edgeMap[curPoint3D].push_back(edge);
1192  edgeList.emplace_back(edge);
1193 
1194  lastPoint = curPoint;
1195  }
1196 
1197  // Store the "extreme" points
1198  const ConvexHull::PointList& extremePoints = convexHullVec.back().getExtremePoints();
1199  reco::ProjectedPointList& extremePointList = convexHull.getConvexHullExtremePoints();
1200 
1201  for (const auto& point : extremePoints)
1202  extremePointList.push_back(point);
1203 
1204  // Store the "kink" points
1205  const reco::ConvexHullKinkTupleList& kinkPoints = convexHullVec.back().getKinkPoints();
1206  reco::ConvexHullKinkTupleList& kinkPointList = convexHull.getConvexHullKinkPoints();
1207 
1208  for (const auto& kink : kinkPoints)
1209  kinkPointList.push_back(kink);
1210  }
1211 
1212  return;
1213  }
float fConvexHullMinSep
Min hit separation to conisder in convex hull.
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:102
std::tuple< float, float, const reco::ClusterHit3D * > ProjectedPoint
Projected coordinates and pointer to hit.
Definition: Cluster3D.h:345
const Eigen::Vector3f getPosition() const
Definition: Cluster3D.h:155
std::list< ProjectedPoint > ProjectedPointList
Definition: Cluster3D.h:346
std::list< Point > PointList
The list of the projected points.
Definition: ConvexHull.h:33
constexpr auto abs(T v)
Returns the absolute value of the argument.
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:463
std::list< EdgeTuple > EdgeList
Definition: Cluster3D.h:337
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:464
std::tuple< const reco::ClusterHit3D *, const reco::ClusterHit3D *, double > EdgeTuple
Definition: Cluster3D.h:336
Define a container for working with the convex hull.
Definition: Cluster3D.h:354
std::string indent(std::size_t const i)
const Eigen::Vector3f & getAvePosition() const
Definition: Cluster3D.h:244
std::list< ConvexHullKinkTuple > ConvexHullKinkTupleList
Definition: Cluster3D.h:349
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:326
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:94
reco::ConvexHull & getConvexHull()
Definition: Cluster3D.h:469
float fConvexHullKinkAngle
Angle to declare a kink in convex hull calc.
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
Definition: Cluster3D.h:339
reco::ProjectedPointList & getProjectedPointList()
Definition: Cluster3D.h:370
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:243
float lar_cluster3d::ConvexHullPathFinder::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 1267 of file ConvexHullPathFinder_tool.cc.

References d, DEFINE_ART_CLASS_TOOL, den, and e.

1273  {
1274  // Technique is to compute the arclength to each point of closest approach
1275  Eigen::Vector3f w0 = P0 - P1;
1276  float a(1.);
1277  float b(u0.dot(u1));
1278  float c(1.);
1279  float d(u0.dot(w0));
1280  float e(u1.dot(w0));
1281  float den(a * c - b * b);
1282 
1283  float arcLen0 = (b * e - c * d) / den;
1284  float arcLen1 = (a * e - b * d) / den;
1285 
1286  poca0 = P0 + arcLen0 * u0;
1287  poca1 = P1 + arcLen1 * u1;
1288 
1289  return (poca0 - poca1).norm();
1290  }
Float_t den
Definition: plot.C:35
Float_t d
Definition: plot.C:235
Float_t e
Definition: plot.C:35
bool lar_cluster3d::ConvexHullPathFinder::completeCandidateCluster ( Eigen::Vector3f &  primaryPCA,
reco::ClusterParameters candCluster,
int  level 
) const
private

Definition at line 608 of file ConvexHullPathFinder_tool.cc.

References buildConvexHull(), reco::PrincipalComponents::flipAxis(), fPCAAlg, reco::PrincipalComponents::getEigenVectors(), reco::ClusterParameters::getFullPCA(), reco::ClusterParameters::getHitPairListPtr(), reco::ClusterParameters::getSkeletonPCA(), reco::PrincipalComponents::getSvdOK(), and lar_cluster3d::PrincipalComponentsAlg::PCAAnalysis_3D().

Referenced by makeCandidateCluster().

611  {
612  // First stage of feature extraction runs here
613  fPCAAlg.PCAAnalysis_3D(candCluster.getHitPairListPtr(), candCluster.getFullPCA());
614 
615  // Recover the new fullPCA
616  reco::PrincipalComponents& newFullPCA = candCluster.getFullPCA();
617 
618  // Will we want to store this cluster?
619  bool keepThisCluster(false);
620 
621  // Must have a valid pca
622  if (newFullPCA.getSvdOK()) {
623  // Need to check if the PCA direction has been reversed
624  Eigen::Vector3f newPrimaryVec(newFullPCA.getEigenVectors().row(2));
625 
626  // If the PCA's are opposite the flip the axes
627  if (primaryPCA.dot(newPrimaryVec) < 0.) {
628  for (size_t vecIdx = 0; vecIdx < 3; vecIdx++)
629  newFullPCA.flipAxis(vecIdx);
630  }
631 
632  // Set the skeleton PCA to make sure it has some value
633  candCluster.getSkeletonPCA() = candCluster.getFullPCA();
634 
635  // Be sure to compute the oonvex hull surrounding the now broken cluster
636  buildConvexHull(candCluster, level + 2);
637 
638  keepThisCluster = true;
639  }
640 
641  return keepThisCluster;
642  }
bool getSvdOK() const
Definition: Cluster3D.h:240
void PCAAnalysis_3D(const reco::HitPairListPtr &hitPairList, reco::PrincipalComponents &pca, bool skeletonOnly=false) const
void flipAxis(size_t axis)
Definition: Cluster3D.cxx:232
reco::PrincipalComponents & getSkeletonPCA()
Definition: Cluster3D.h:465
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:463
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:464
void buildConvexHull(reco::ClusterParameters &clusterParameters, int level=0) const
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:243
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::ConvexHullPathFinder::configure ( fhicl::ParameterSet const &  pset)
override

Definition at line 205 of file ConvexHullPathFinder_tool.cc.

References fClusterAlg, fConvexHullKinkAngle, fConvexHullMinSep, fEnableMonitoring, fMinEigen0To1Ratio, fMinGapSize, fMinTinyClusterSize, fTimeToProcess, and fhicl::ParameterSet::get().

Referenced by ConvexHullPathFinder().

206  {
207  fEnableMonitoring = pset.get<bool>("EnableMonitoring", true);
208  fMinTinyClusterSize = pset.get<size_t>("MinTinyClusterSize", 40);
209  fMinGapSize = pset.get<float>("MinClusterGapSize", 2.0);
210  fMinEigen0To1Ratio = pset.get<float>("MinEigen0To1Ratio", 10.0);
211  fConvexHullKinkAngle = pset.get<float>("ConvexHullKinkAgle", 0.95);
212  fConvexHullMinSep = pset.get<float>("ConvexHullMinSep", 0.65);
213  fClusterAlg =
214  art::make_tool<lar_cluster3d::IClusterAlg>(pset.get<fhicl::ParameterSet>("ClusterAlg"));
215 
216  fTimeToProcess = 0.;
217 
218  return;
219  }
size_t fMinTinyClusterSize
Minimum size for a "tiny" cluster.
float fConvexHullMinSep
Min hit separation to conisder in convex hull.
std::unique_ptr< lar_cluster3d::IClusterAlg > fClusterAlg
Tools.
float fMinEigen0To1Ratio
Minimum ratio of eigen 0 to 1 to continue breaking.
float fConvexHullKinkAngle
Angle to declare a kink in convex hull calc.
float fMinGapSize
Minimum gap size to break at gaps.
void lar_cluster3d::ConvexHullPathFinder::fillConvexHullHists ( reco::ClusterParameters clusterParameters,
bool  top 
) const
private

Definition at line 1215 of file ConvexHullPathFinder_tool.cc.

References fConvexHullMinSep, fSubConvexCosEdge, fSubConvexEdgeLen, fTopConvexCosEdge, fTopConvexEdgeLen, reco::ClusterParameters::getConvexHull(), and reco::ConvexHull::getConvexHullPointList().

Referenced by breakClusterByKinks(), breakClusterByKinksTrial(), and ModifyClusters().

1217  {
1218  reco::ProjectedPointList& convexHullPoints =
1219  clusterParameters.getConvexHull().getConvexHullPointList();
1220 
1221  if (convexHullPoints.size() > 2) {
1222  reco::ProjectedPointList::iterator pointItr = convexHullPoints.begin();
1223 
1224  // Advance to the second to last element
1225  std::advance(pointItr, convexHullPoints.size() - 2);
1226 
1227  reco::ProjectedPoint lastPoint = *pointItr++;
1228 
1229  // Reset pointer to the first element
1230  pointItr = convexHullPoints.begin();
1231 
1232  reco::ProjectedPoint curPoint = *pointItr++;
1233  Eigen::Vector2f lastEdge(std::get<0>(curPoint) - std::get<0>(lastPoint),
1234  std::get<1>(curPoint) - std::get<1>(lastPoint));
1235 
1236  lastEdge.normalize();
1237 
1238  while (pointItr != convexHullPoints.end()) {
1239  reco::ProjectedPoint& nextPoint = *pointItr++;
1240 
1241  Eigen::Vector2f nextEdge(std::get<0>(nextPoint) - std::get<0>(curPoint),
1242  std::get<1>(nextPoint) - std::get<1>(curPoint));
1243  float nextEdgeLen = nextEdge.norm();
1244 
1245  nextEdge.normalize();
1246 
1247  float cosLastNextEdge = lastEdge.dot(nextEdge);
1248 
1249  if (top) {
1250  fTopConvexCosEdge->Fill(cosLastNextEdge, 1.);
1251  fTopConvexEdgeLen->Fill(std::min(nextEdgeLen, float(49.9)), 1.);
1252  }
1253  else {
1254  fSubConvexCosEdge->Fill(cosLastNextEdge, 1.);
1255  fSubConvexEdgeLen->Fill(std::min(nextEdgeLen, float(49.9)), 1.);
1256  }
1257 
1258  if (nextEdgeLen > fConvexHullMinSep) lastEdge = nextEdge;
1259 
1260  curPoint = nextPoint;
1261  }
1262  }
1263 
1264  return;
1265  }
float fConvexHullMinSep
Min hit separation to conisder in convex hull.
intermediate_table::iterator iterator
std::tuple< float, float, const reco::ClusterHit3D * > ProjectedPoint
Projected coordinates and pointer to hit.
Definition: Cluster3D.h:345
std::list< ProjectedPoint > ProjectedPointList
Definition: Cluster3D.h:346
reco::ConvexHull & getConvexHull()
Definition: Cluster3D.h:469
reco::ProjectedPointList & getConvexHullPointList()
Definition: Cluster3D.h:371
float lar_cluster3d::ConvexHullPathFinder::getTimeToExecute ( ) const
inlineoverridevirtual

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

Implements lar_cluster3d::IClusterModAlg.

Definition at line 74 of file ConvexHullPathFinder_tool.cc.

References fTimeToProcess, and subDivideCluster().

void lar_cluster3d::ConvexHullPathFinder::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 221 of file ConvexHullPathFinder_tool.cc.

References dir, fFillHistograms, fSubConvexCosEdge, fSubConvexEdgeLen, fSubCosExtToPCA, fSubCosToPrevPCA, fSubEigen10Ratio, fSubEigen20Ratio, fSubEigen21Ratio, fSubMaxDefect, fSubNum3DHits, fSubNumEdges, fSubPrimaryLength, fSubUsedDefect, fTopConvexCosEdge, fTopConvexEdgeLen, fTopEigen10Ratio, fTopEigen20Ratio, fTopEigen21Ratio, fTopExtremeSep, fTopNum3DHits, fTopNumEdges, and fTopPrimaryLength.

222  {
223  // It is assumed that the input TFileDirectory has been set up to group histograms into a common
224  // folder at the calling routine's level. Here we create one more level of indirection to keep
225  // histograms made by this tool separate.
226  fFillHistograms = true;
227 
228  std::string dirName = "ConvexHullPath";
229 
230  art::TFileDirectory dir = histDir.mkdir(dirName.c_str());
231 
232  // Divide into two sets of hists... those for the overall cluster and
233  // those for the subclusters
234  fTopNum3DHits = dir.make<TH1F>("TopNum3DHits", "Number 3D Hits", 200, 0., 200.);
235  fTopNumEdges = dir.make<TH1F>("TopNumEdges", "Number Edges", 200, 0., 200.);
236  fTopEigen21Ratio = dir.make<TH1F>("TopEigen21Rat", "Eigen 2/1 Ratio", 100, 0., 1.);
237  fTopEigen20Ratio = dir.make<TH1F>("TopEigen20Rat", "Eigen 2/0 Ratio", 100, 0., 1.);
238  fTopEigen10Ratio = dir.make<TH1F>("TopEigen10Rat", "Eigen 1/0 Ratio", 100, 0., 1.);
239  fTopPrimaryLength = dir.make<TH1F>("TopPrimaryLen", "Primary Length", 200, 0., 200.);
240  fTopExtremeSep = dir.make<TH1F>("TopExtremeSep", "Extreme Dist", 200, 0., 200.);
241  fTopConvexCosEdge = dir.make<TH1F>("TopConvexCos", "CH Edge Cos", 100, -1., 1.);
242  fTopConvexEdgeLen = dir.make<TH1F>("TopConvexEdge", "CH Edge Len", 200, 0., 50.);
243 
244  fSubNum3DHits = dir.make<TH1F>("SubNum3DHits", "Number 3D Hits", 200, 0., 200.);
245  fSubNumEdges = dir.make<TH1F>("SubNumEdges", "Number Edges", 200, 0., 200.);
246  fSubEigen21Ratio = dir.make<TH1F>("SubEigen21Rat", "Eigen 2/1 Ratio", 100, 0., 1.);
247  fSubEigen20Ratio = dir.make<TH1F>("SubEigen20Rat", "Eigen 2/0 Ratio", 100, 0., 1.);
248  fSubEigen10Ratio = dir.make<TH1F>("SubEigen10Rat", "Eigen 1/0 Ratio", 100, 0., 1.);
249  fSubPrimaryLength = dir.make<TH1F>("SubPrimaryLen", "Primary Length", 200, 0., 200.);
250  fSubCosToPrevPCA = dir.make<TH1F>("SubCosToPrev", "Cos(theta)", 101, 0., 1.01);
251  fSubCosExtToPCA = dir.make<TH1F>("SubCosExtPCA", "Cos(theta)", 102, -1.01, 1.01);
252  fSubConvexCosEdge = dir.make<TH1F>("SubConvexCos", "CH Edge Cos", 100, -1., 1.);
253  fSubConvexEdgeLen = dir.make<TH1F>("SubConvexEdge", "CH Edge Len", 200, 0., 50.);
254  fSubMaxDefect = dir.make<TH1F>("SubMaxDefect", "Max Defect", 100, 0., 50.);
255  fSubUsedDefect = dir.make<TH1F>("SubUsedDefect", "Used Defect", 100, 0., 50.);
256 
257  return;
258  }
TDirectory * dir
Definition: macro.C:5
bool lar_cluster3d::ConvexHullPathFinder::makeCandidateCluster ( Eigen::Vector3f &  primaryPCA,
reco::ClusterParameters candCluster,
reco::HitPairListPtr::iterator  firstHitItr,
reco::HitPairListPtr::iterator  lastHitItr,
int  level 
) const
private

Definition at line 521 of file ConvexHullPathFinder_tool.cc.

References util::abs(), completeCandidateCluster(), reco::ClusterParameters::getConvexHull(), reco::ConvexHull::getConvexHullEdgeList(), reco::PrincipalComponents::getEigenValues(), reco::PrincipalComponents::getEigenVectors(), reco::ClusterParameters::getFullPCA(), reco::ClusterParameters::getHitPairListPtr(), and art::detail::indent().

Referenced by breakClusterAtBigGap(), breakClusterByKinks(), breakClusterByKinksTrial(), breakClusterByMaxDefect(), and breakClusterInHalf().

526  {
527  std::string indent(level / 2, ' ');
528 
529  reco::HitPairListPtr& hitPairListPtr = candCluster.getHitPairListPtr();
530 
531  // size the container...
532  hitPairListPtr.resize(std::distance(firstHitItr, lastHitItr));
533 
534  // and copy the hits into the container
535  std::copy(firstHitItr, lastHitItr, hitPairListPtr.begin());
536 
537  // Will we want to store this cluster?
538  bool keepThisCluster(false);
539 
540  // Must have a valid pca
541  if (completeCandidateCluster(primaryPCA, candCluster, level)) {
542  // Recover the new fullPCA
543  reco::PrincipalComponents& newFullPCA = candCluster.getFullPCA();
544 
545  // Need to check if the PCA direction has been reversed
546  Eigen::Vector3f newPrimaryVec(newFullPCA.getEigenVectors().row(2));
547 
548  std::vector<double> eigenValVec = {3. * std::sqrt(newFullPCA.getEigenValues()[0]),
549  3. * std::sqrt(newFullPCA.getEigenValues()[1]),
550  3. * std::sqrt(newFullPCA.getEigenValues()[2])};
551  double cosNewToLast = std::abs(primaryPCA.dot(newPrimaryVec));
552  double eigen2To1Ratio = eigenValVec[0] / eigenValVec[1];
553  double eigen1To0Ratio = eigenValVec[1] / eigenValVec[2];
554 
555  // Create a rough cut intended to tell us when we've reached the land of diminishing returns
556  // if (candCluster.getBestEdgeList().size() > 4 && cosNewToLast > 0.25 && eigen2To1Ratio < 0.9 && eigen2To0Ratio > 0.001)
557  if (candCluster.getConvexHull().getConvexHullEdgeList().size() > 4 && cosNewToLast > 0.25 &&
558  eigen2To1Ratio > 0.01 && eigen2To1Ratio < 0.99 && eigen1To0Ratio < 0.5) {
559  keepThisCluster = true;
560  }
561  }
562 
563  return keepThisCluster;
564  }
constexpr auto abs(T v)
Returns the absolute value of the argument.
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:463
const EigenValues & getEigenValues() const
Definition: Cluster3D.h:242
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:464
std::string indent(std::size_t const i)
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:326
reco::ConvexHull & getConvexHull()
Definition: Cluster3D.h:469
reco::EdgeList & getConvexHullEdgeList()
Definition: Cluster3D.h:373
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:243
bool completeCandidateCluster(Eigen::Vector3f &, reco::ClusterParameters &, int) const
bool lar_cluster3d::ConvexHullPathFinder::makeCandidateCluster ( Eigen::Vector3f &  primaryPCA,
reco::ClusterParameters candCluster,
HitOrderTupleList orderedList,
int  level 
) const
private

Definition at line 566 of file ConvexHullPathFinder_tool.cc.

References util::abs(), completeCandidateCluster(), reco::ClusterParameters::getBestEdgeList(), reco::PrincipalComponents::getEigenValues(), reco::PrincipalComponents::getEigenVectors(), reco::ClusterParameters::getFullPCA(), reco::ClusterParameters::getHitPairListPtr(), and art::detail::indent().

570  {
571  std::string indent(level / 2, ' ');
572 
573  reco::HitPairListPtr& hitPairListPtr = candCluster.getHitPairListPtr();
574 
575  // Fill the list the old fashioned way...
576  for (const auto& tupleVal : orderedList)
577  hitPairListPtr.emplace_back(std::get<2>(std::get<2>(tupleVal)));
578 
579  // Will we want to store this cluster?
580  bool keepThisCluster(false);
581 
582  // Must have a valid pca
583  if (completeCandidateCluster(primaryPCA, candCluster, level)) {
584  // Recover the new fullPCA
585  reco::PrincipalComponents& newFullPCA = candCluster.getFullPCA();
586 
587  // Need to check if the PCA direction has been reversed
588  Eigen::Vector3f newPrimaryVec(newFullPCA.getEigenVectors().row(2));
589 
590  std::vector<double> eigenValVec = {3. * std::sqrt(newFullPCA.getEigenValues()[0]),
591  3. * std::sqrt(newFullPCA.getEigenValues()[1]),
592  3. * std::sqrt(newFullPCA.getEigenValues()[2])};
593  double cosNewToLast = std::abs(primaryPCA.dot(newPrimaryVec));
594  double eigen2To1Ratio = eigenValVec[0] / eigenValVec[1];
595  double eigen1To0Ratio = eigenValVec[1] / eigenValVec[2];
596 
597  // Create a rough cut intended to tell us when we've reached the land of diminishing returns
598  // if (candCluster.getBestEdgeList().size() > 4 && cosNewToLast > 0.25 && eigen2To1Ratio < 0.9 && eigen2To0Ratio > 0.001)
599  if (candCluster.getBestEdgeList().size() > 4 && cosNewToLast > 0.25 &&
600  eigen2To1Ratio > 0.01 && eigen2To1Ratio < 0.99 && eigen1To0Ratio < 0.5) {
601  keepThisCluster = true;
602  }
603  }
604 
605  return keepThisCluster;
606  }
constexpr auto abs(T v)
Returns the absolute value of the argument.
reco::EdgeList & getBestEdgeList()
Definition: Cluster3D.h:468
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:463
const EigenValues & getEigenValues() const
Definition: Cluster3D.h:242
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:464
std::string indent(std::size_t const i)
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:326
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:243
bool completeCandidateCluster(Eigen::Vector3f &, reco::ClusterParameters &, int) const
void lar_cluster3d::ConvexHullPathFinder::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 260 of file ConvexHullPathFinder_tool.cc.

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

262  {
270  // Initial clustering is done, now trim the list and get output parameters
271  cet::cpu_timer theClockBuildClusters;
272 
273  // Start clocks if requested
274  if (fEnableMonitoring) theClockBuildClusters.start();
275 
276  // This is the loop over candidate 3D clusters
277  // Note that it might be that the list of candidate clusters is modified by splitting
278  // So we use the following construct to make sure we get all of them
279  reco::ClusterParametersList::iterator clusterParametersListItr = clusterParametersList.begin();
280 
281  while (clusterParametersListItr != clusterParametersList.end()) {
282  // Dereference to get the cluster paramters
283  reco::ClusterParameters& clusterParameters = *clusterParametersListItr;
284 
285  // It turns out that computing the convex hull surrounding the points in the 2D projection onto the
286  // plane of largest spread in the PCA is a good way to break up the cluster... and we do it here since
287  // we (currently) want this to be part of the standard output
288  buildConvexHull(clusterParameters);
289 
290  // Make sure our cluster has enough hits...
291  if (clusterParameters.getHitPairListPtr().size() > fMinTinyClusterSize) {
292  // Get an interim cluster list
293  reco::ClusterParametersList reclusteredParameters;
294 
295  // Call the main workhorse algorithm for building the local version of candidate 3D clusters
296  //******** Remind me why we need to call this at this point when the same hits will be used? ********
297  //fClusterAlg->Cluster3DHits(clusterParameters.getHitPairListPtr(), reclusteredParameters);
298  reclusteredParameters.push_back(clusterParameters);
299 
300  // Only process non-empty results
301  if (!reclusteredParameters.empty()) {
302  // Loop over the reclustered set
303  for (auto& cluster : reclusteredParameters) {
304  // It turns out that computing the convex hull surrounding the points in the 2D projection onto the
305  // plane of largest spread in the PCA is a good way to break up the cluster... and we do it here since
306  // we (currently) want this to be part of the standard output
308 
309  // Break our cluster into smaller elements...
310  subDivideCluster(cluster, cluster.daughterList().end(), cluster.daughterList(), 0);
311 
312  // Add the daughters to the cluster
313  clusterParameters.daughterList().insert(clusterParameters.daughterList().end(),
314  cluster);
315 
316  // If filling histograms we do the main cluster here
317  if (fFillHistograms) {
318  reco::PrincipalComponents& fullPCA = cluster.getFullPCA();
319  std::vector<double> eigenValVec = {3. * std::sqrt(fullPCA.getEigenValues()[0]),
320  3. * std::sqrt(fullPCA.getEigenValues()[1]),
321  3. * std::sqrt(fullPCA.getEigenValues()[2])};
322  double eigen2To1Ratio = eigenValVec[0] / eigenValVec[1];
323  double eigen1To0Ratio = eigenValVec[1] / eigenValVec[2];
324  double eigen2To0Ratio = eigenValVec[2] / eigenValVec[2];
325  int num3DHits = cluster.getHitPairListPtr().size();
326  int numEdges = cluster.getConvexHull().getConvexHullEdgeList().size();
327 
328  fTopNum3DHits->Fill(std::min(num3DHits, 199), 1.);
329  fTopNumEdges->Fill(std::min(numEdges, 199), 1.);
330  fTopEigen21Ratio->Fill(eigen2To1Ratio, 1.);
331  fTopEigen20Ratio->Fill(eigen2To0Ratio, 1.);
332  fTopEigen10Ratio->Fill(eigen1To0Ratio, 1.);
333  fTopPrimaryLength->Fill(std::min(eigenValVec[2], 199.), 1.);
334  // fTopExtremeSep->Fill(std::min(edgeLen,199.), 1.);
335  fillConvexHullHists(clusterParameters, true);
336  }
337  }
338  }
339  }
340 
341  // Go to next cluster parameters object
342  clusterParametersListItr++;
343  }
344 
345  if (fEnableMonitoring) {
346  theClockBuildClusters.stop();
347 
348  fTimeToProcess = theClockBuildClusters.accumulated_real_time();
349  }
350 
351  mf::LogDebug("Cluster3D") << ">>>>> Cluster Path finding done" << std::endl;
352 
353  return;
354  }
size_t fMinTinyClusterSize
Minimum size for a "tiny" cluster.
intermediate_table::iterator iterator
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:463
Cluster finding and building.
reco::ClusterParametersList::iterator subDivideCluster(reco::ClusterParameters &cluster, reco::ClusterParametersList::iterator positionItr, reco::ClusterParametersList &outputClusterList, int level=0) const
Use PCA to try to find path in cluster.
ClusterParametersList & daughterList()
Definition: Cluster3D.h:438
const EigenValues & getEigenValues() const
Definition: Cluster3D.h:242
void fillConvexHullHists(reco::ClusterParameters &, bool) const
void buildConvexHull(reco::ClusterParameters &clusterParameters, int level=0) const
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
std::list< ClusterParameters > ClusterParametersList
Definition: Cluster3D.h:393
void lar_cluster3d::ConvexHullPathFinder::orderHitsAlongEdge ( const reco::ProjectedPointList hitList,
const reco::ProjectedPoint point,
const Eigen::Vector2f &  edge,
HitOrderTupleList orderedList 
) const
private

Definition at line 799 of file ConvexHullPathFinder_tool.cc.

References art::left(), and art::right().

Referenced by breakClusterByKinksTrial().

803  {
804  // Use the input kink point as the start point of the edge
805  Eigen::Vector2f kinkPos(std::get<0>(point), std::get<1>(point));
806 
807  // Loop over the input hits
808  for (const auto& hit : hitList) {
809  // Now we need to calculate the doca and poca...
810  // Start by getting this hits position
811  Eigen::Vector2f hitPos(std::get<0>(hit), std::get<1>(hit));
812 
813  // Form a TVector from this to the cluster average position
814  Eigen::Vector2f hitToKinkVec = hitPos - kinkPos;
815 
816  // With this we can get the arclength to the doca point
817  float arcLenToPoca = hitToKinkVec.dot(edge);
818 
819  // Require the hit to not be past the kink point
820  if (arcLenToPoca < 0.) continue;
821 
822  // Get the coordinates along the axis for this point
823  Eigen::Vector2f pocaPos = kinkPos + arcLenToPoca * edge;
824 
825  // Now get doca and poca
826  Eigen::Vector2f pocaPosToHitPos = hitPos - pocaPos;
827  float pocaToAxis = pocaPosToHitPos.norm();
828 
829  std::cout << "-- arcLenToPoca: " << arcLenToPoca << ", doca: " << pocaToAxis << std::endl;
830 
831  orderedList.emplace_back(arcLenToPoca, pocaToAxis, hit);
832  }
833 
834  // Sort the list in order of ascending distance from the kink point
835  orderedList.sort(
836  [](const auto& left, const auto& right) { return std::get<0>(left) < std::get<0>(right); });
837 
838  return;
839  }
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:102
Detector simulation of raw signals on wires.
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:94
void lar_cluster3d::ConvexHullPathFinder::pruneHitOrderTupleLists ( HitOrderTupleList shortList,
HitOrderTupleList longList 
) const
private

Definition at line 841 of file ConvexHullPathFinder_tool.cc.

Referenced by breakClusterByKinksTrial().

843  {
844  // Assume the first list is the short one, so we loop through the elements of that list..
845  HitOrderTupleList::iterator shortItr = shortList.begin();
846 
847  while (shortItr != shortList.end()) {
848  // Recover the search key
849  const reco::ClusterHit3D* hit3D = std::get<2>(std::get<2>(*shortItr));
850 
851  // Ok, find the corresponding point in the other list...
853  std::find_if(longList.begin(), longList.end(), [&hit3D](const auto& elem) {
854  return hit3D == std::get<2>(std::get<2>(elem));
855  });
856 
857  if (longItr != longList.end()) {
858  if (std::get<1>(*longItr) < std::get<1>(*shortItr)) {
859  shortItr = shortList.erase(shortItr);
860  }
861  else {
862  longItr = longList.erase(longItr);
863  shortItr++;
864  }
865  }
866  else
867  shortItr++;
868  }
869 
870  return;
871  }
intermediate_table::iterator iterator
reco::ClusterParametersList::iterator lar_cluster3d::ConvexHullPathFinder::subDivideCluster ( reco::ClusterParameters cluster,
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 356 of file ConvexHullPathFinder_tool.cc.

References breakClusterAtBigGap(), breakClusterByKinks(), breakClusterByMaxDefect(), breakClusterInHalf(), fFillHistograms, fMinEigen0To1Ratio, fMinTinyClusterSize, fSubCosExtToPCA, fSubCosToPrevPCA, fSubEigen10Ratio, fSubEigen20Ratio, fSubEigen21Ratio, fSubNum3DHits, fSubNumEdges, fSubPrimaryLength, reco::ClusterParameters::getConvexHull(), reco::ConvexHull::getConvexHullExtremePoints(), reco::PrincipalComponents::getEigenValues(), reco::PrincipalComponents::getEigenVectors(), reco::ClusterParameters::getFullPCA(), reco::ClusterParameters::getHitPairListPtr(), reco::ClusterHit3D::getPosition(), and reco::ClusterHit2D::USED.

Referenced by getTimeToExecute(), and ModifyClusters().

361  {
362  // This is a recursive routine to divide an input cluster, according to the maximum defect point of
363  // the convex hull until we reach the point of no further improvement.
364  // The assumption is that the input cluster is fully formed already, this routine then simply
365  // divides, if successful division into two pieces it then stores the results
366 
367  // No point in doing anything if we don't have enough space points
368  if (clusterToBreak.getHitPairListPtr().size() > size_t(2 * fMinTinyClusterSize)) {
369  // set an indention string
370  // std::string pluses(level/2, '+');
371  // std::string indent(level/2, ' ');
372  //
373  // indent += pluses;
374 
375  // We want to find the convex hull vertices that lie furthest from the line to/from the extreme points
376  // To find these we:
377  // 1) recover the extreme points
378  // 2) form the vector between them
379  // 3) loop through the vertices and keep track of distance to this vector
380  // 4) Sort the resulting list by furthest points and select the one we want
381  reco::ConvexHull& convexHull = clusterToBreak.getConvexHull();
382 
383  reco::ProjectedPointList::const_iterator extremePointListItr =
384  convexHull.getConvexHullExtremePoints().begin();
385 
386  const reco::ClusterHit3D* firstEdgeHit = std::get<2>(*extremePointListItr++);
387  const reco::ClusterHit3D* secondEdgeHit = std::get<2>(*extremePointListItr);
388  Eigen::Vector3f edgeVec(secondEdgeHit->getPosition()[0] - firstEdgeHit->getPosition()[0],
389  secondEdgeHit->getPosition()[1] - firstEdgeHit->getPosition()[1],
390  secondEdgeHit->getPosition()[2] - firstEdgeHit->getPosition()[2]);
391  // double edgeLen = edgeVec.norm();
392 
393  // normalize it
394  edgeVec.normalize();
395 
396  // Recover the PCA for the input cluster
397  reco::PrincipalComponents& fullPCA = clusterToBreak.getFullPCA();
398  Eigen::Vector3f fullPrimaryVec(fullPCA.getEigenVectors().row(2));
399 
400  // Calculate the doca to the PCA primary axis for each 3D hit
401  // Importantly, this also gives us the arclength along that axis to the hit
402  // fPCAAlg.PCAAnalysis_calc3DDocas(clusHitPairVector, fullPCA);
403 
404  // Sort the hits along the PCA
405  // clusHitPairVector.sort([](const auto& left, const auto& right){return left->getArclenToPoca() < right->getArclenToPoca();});
406 
407  // Get a temporary container to hol
408  reco::ClusterParametersList tempClusterParametersList;
409 
410  // Try breaking clusters by finding the "maximum defect" point.
411  // If this fails the fallback in the event of still large clusters is to split in half
412  // If starting with the top level cluster then we first try to break at the kinks
413  if (level == 0) {
414  // if (!breakClusterByMaxDefect(clusterToBreak, clusHitPairVector, tempClusterParametersList, level))
415  if (!breakClusterByKinks(clusterToBreak, tempClusterParametersList, level)) {
416  // Look to see if we can break at a gap
417  if (!breakClusterAtBigGap(clusterToBreak, tempClusterParametersList, level)) {
418  // It might be that we have a large deviation in the convex hull...
419  if (!breakClusterByMaxDefect(clusterToBreak, tempClusterParametersList, level)) {
420  std::vector<double> eigenValVec = {3. * std::sqrt(fullPCA.getEigenValues()[0]),
421  3. * std::sqrt(fullPCA.getEigenValues()[1]),
422  3. * std::sqrt(fullPCA.getEigenValues()[2])};
423 
424  // Well, we don't want "flippers" so make sure the edge has some teeth to it
425  //if (edgeLen > 10.) breakClusterInHalf(clusterToBreak, clusHitPairVector, tempClusterParametersList, level);
426  if (eigenValVec[2] > fMinEigen0To1Ratio * eigenValVec[1])
427  breakClusterInHalf(clusterToBreak, tempClusterParametersList, level);
428  }
429  }
430  }
431  }
432  // Otherwise, change the order
433  else {
434  // if (!breakClusterByMaxDefect(clusterToBreak, clusHitPairVector, tempClusterParametersList, level))
435  if (!breakClusterAtBigGap(clusterToBreak, tempClusterParametersList, level)) {
436  // Look to see if we can break at a gap
437  if (!breakClusterByKinks(clusterToBreak, tempClusterParametersList, level)) {
438  // It might be that we have a large deviation in the convex hull...
439  if (!breakClusterByMaxDefect(clusterToBreak, tempClusterParametersList, level)) {
440  std::vector<double> eigenValVec = {3. * std::sqrt(fullPCA.getEigenValues()[0]),
441  3. * std::sqrt(fullPCA.getEigenValues()[1]),
442  3. * std::sqrt(fullPCA.getEigenValues()[2])};
443 
444  // Well, we don't want "flippers" so make sure the edge has some teeth to it
445  //if (edgeLen > 10.) breakClusterInHalf(clusterToBreak, clusHitPairVector, tempClusterParametersList, level);
446  if (eigenValVec[2] > fMinEigen0To1Ratio * eigenValVec[1])
447  breakClusterInHalf(clusterToBreak, tempClusterParametersList, level);
448  }
449  }
450  }
451  }
452 
453  // Can only end with no candidate clusters or two so don't
454  for (auto& clusterParams : tempClusterParametersList) {
455  size_t curOutputClusterListSize = outputClusterList.size();
456 
457  positionItr = subDivideCluster(clusterParams, positionItr, outputClusterList, level + 4);
458 
459  // If the cluster we sent in was successfully broken then the position iterator will be shifted
460  // This means we don't want to restore the current cluster here
461  if (curOutputClusterListSize < outputClusterList.size()) continue;
462 
463  // The current cluster was not further subdivided so we store its info here
464  // I think this is where we fill out the rest of the parameters?
465  // Start by adding the 2D hits...
466  // See if we can avoid duplicates by temporarily transferring to a set
467  std::set<const reco::ClusterHit2D*> hitSet;
468 
469  // Loop through 3D hits to get a set of unique 2D hits
470  for (const auto& hit3D : clusterParams.getHitPairListPtr()) {
471  for (const auto& hit2D : hit3D->getHits()) {
472  if (hit2D) hitSet.insert(hit2D);
473  }
474  }
475 
476  // Now add these to the new cluster
477  for (const auto& hit2D : hitSet) {
478  hit2D->setStatusBit(reco::ClusterHit2D::USED);
479  clusterParams.UpdateParameters(hit2D);
480  }
481 
482  positionItr = outputClusterList.insert(positionItr, clusterParams);
483 
484  // Are we filling histograms
485  if (fFillHistograms) {
486  std::vector<double> eigenValVec = {3. * std::sqrt(fullPCA.getEigenValues()[0]),
487  3. * std::sqrt(fullPCA.getEigenValues()[1]),
488  3. * std::sqrt(fullPCA.getEigenValues()[2])};
489 
490  // Recover the new fullPCA
491  reco::PrincipalComponents& newFullPCA = clusterParams.getFullPCA();
492 
493  Eigen::Vector3f newPrimaryVec(fullPCA.getEigenVectors().row(2));
494  Eigen::Vector3f lastPrimaryVec(newFullPCA.getEigenVectors().row(2));
495 
496  int num3DHits = clusterParams.getHitPairListPtr().size();
497  int numEdges = clusterParams.getConvexHull().getConvexHullEdgeList().size();
498  float cosToLast = newPrimaryVec.dot(lastPrimaryVec);
499  double eigen2To1Ratio = eigenValVec[0] / eigenValVec[1];
500  double eigen1To0Ratio = eigenValVec[1] / eigenValVec[2];
501  double eigen2To0Ratio = eigenValVec[0] / eigenValVec[2];
502 
503  fSubNum3DHits->Fill(std::min(num3DHits, 199), 1.);
504  fSubNumEdges->Fill(std::min(numEdges, 199), 1.);
505  fSubEigen21Ratio->Fill(eigen2To1Ratio, 1.);
506  fSubEigen20Ratio->Fill(eigen2To0Ratio, 1.);
507  fSubEigen10Ratio->Fill(eigen1To0Ratio, 1.);
508  fSubCosToPrevPCA->Fill(cosToLast, 1.);
509  fSubPrimaryLength->Fill(std::min(eigenValVec[2], 199.), 1.);
510  fSubCosExtToPCA->Fill(fullPrimaryVec.dot(edgeVec), 1.);
511  }
512 
513  // The above points to the element, want the next element
514  positionItr++;
515  }
516  }
517 
518  return positionItr;
519  }
size_t fMinTinyClusterSize
Minimum size for a "tiny" cluster.
bool breakClusterByMaxDefect(reco::ClusterParameters &, reco::ClusterParametersList &, int level) const
const Eigen::Vector3f getPosition() const
Definition: Cluster3D.h:155
intermediate_table::const_iterator const_iterator
reco::ClusterParametersList::iterator subDivideCluster(reco::ClusterParameters &cluster, reco::ClusterParametersList::iterator positionItr, reco::ClusterParametersList &outputClusterList, int level=0) const
Use PCA to try to find path in cluster.
const EigenValues & getEigenValues() const
Definition: Cluster3D.h:242
reco::ProjectedPointList & getConvexHullExtremePoints()
Definition: Cluster3D.h:374
Define a container for working with the convex hull.
Definition: Cluster3D.h:354
bool breakClusterByKinks(reco::ClusterParameters &, reco::ClusterParametersList &, int level) const
float fMinEigen0To1Ratio
Minimum ratio of eigen 0 to 1 to continue breaking.
bool breakClusterAtBigGap(reco::ClusterParameters &, reco::ClusterParametersList &, int level) const
bool breakClusterInHalf(reco::ClusterParameters &, reco::ClusterParametersList &, int level) const
std::list< ClusterParameters > ClusterParametersList
Definition: Cluster3D.h:393
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:243

Member Data Documentation

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

Tools.

Algorithm to do 3D space point clustering

Definition at line 189 of file ConvexHullPathFinder_tool.cc.

Referenced by configure().

float lar_cluster3d::ConvexHullPathFinder::fConvexHullKinkAngle
private

Angle to declare a kink in convex hull calc.

Definition at line 153 of file ConvexHullPathFinder_tool.cc.

Referenced by buildConvexHull(), and configure().

float lar_cluster3d::ConvexHullPathFinder::fConvexHullMinSep
private

Min hit separation to conisder in convex hull.

Definition at line 154 of file ConvexHullPathFinder_tool.cc.

Referenced by buildConvexHull(), configure(), and fillConvexHullHists().

bool lar_cluster3d::ConvexHullPathFinder::fEnableMonitoring
private

FHICL parameters.

Definition at line 149 of file ConvexHullPathFinder_tool.cc.

Referenced by configure(), and ModifyClusters().

bool lar_cluster3d::ConvexHullPathFinder::fFillHistograms
private
float lar_cluster3d::ConvexHullPathFinder::fMinEigen0To1Ratio
private

Minimum ratio of eigen 0 to 1 to continue breaking.

Definition at line 152 of file ConvexHullPathFinder_tool.cc.

Referenced by configure(), and subDivideCluster().

float lar_cluster3d::ConvexHullPathFinder::fMinGapSize
private

Minimum gap size to break at gaps.

Definition at line 151 of file ConvexHullPathFinder_tool.cc.

Referenced by breakClusterAtBigGap(), and configure().

size_t lar_cluster3d::ConvexHullPathFinder::fMinTinyClusterSize
private
PrincipalComponentsAlg lar_cluster3d::ConvexHullPathFinder::fPCAAlg
private
TH1F* lar_cluster3d::ConvexHullPathFinder::fSubConvexCosEdge
private

Definition at line 180 of file ConvexHullPathFinder_tool.cc.

Referenced by fillConvexHullHists(), and initializeHistograms().

TH1F* lar_cluster3d::ConvexHullPathFinder::fSubConvexEdgeLen
private

Definition at line 181 of file ConvexHullPathFinder_tool.cc.

Referenced by fillConvexHullHists(), and initializeHistograms().

TH1F* lar_cluster3d::ConvexHullPathFinder::fSubCosExtToPCA
private

Definition at line 179 of file ConvexHullPathFinder_tool.cc.

Referenced by initializeHistograms(), and subDivideCluster().

TH1F* lar_cluster3d::ConvexHullPathFinder::fSubCosToPrevPCA
private

Definition at line 178 of file ConvexHullPathFinder_tool.cc.

Referenced by initializeHistograms(), and subDivideCluster().

TH1F* lar_cluster3d::ConvexHullPathFinder::fSubEigen10Ratio
private

Definition at line 176 of file ConvexHullPathFinder_tool.cc.

Referenced by initializeHistograms(), and subDivideCluster().

TH1F* lar_cluster3d::ConvexHullPathFinder::fSubEigen20Ratio
private

Definition at line 175 of file ConvexHullPathFinder_tool.cc.

Referenced by initializeHistograms(), and subDivideCluster().

TH1F* lar_cluster3d::ConvexHullPathFinder::fSubEigen21Ratio
private

Definition at line 174 of file ConvexHullPathFinder_tool.cc.

Referenced by initializeHistograms(), and subDivideCluster().

TH1F* lar_cluster3d::ConvexHullPathFinder::fSubMaxDefect
private

Definition at line 182 of file ConvexHullPathFinder_tool.cc.

Referenced by breakClusterByMaxDefect(), and initializeHistograms().

TH1F* lar_cluster3d::ConvexHullPathFinder::fSubNum3DHits
private

Definition at line 172 of file ConvexHullPathFinder_tool.cc.

Referenced by initializeHistograms(), and subDivideCluster().

TH1F* lar_cluster3d::ConvexHullPathFinder::fSubNumEdges
private

Definition at line 173 of file ConvexHullPathFinder_tool.cc.

Referenced by initializeHistograms(), and subDivideCluster().

TH1F* lar_cluster3d::ConvexHullPathFinder::fSubPrimaryLength
private

Definition at line 177 of file ConvexHullPathFinder_tool.cc.

Referenced by initializeHistograms(), and subDivideCluster().

TH1F* lar_cluster3d::ConvexHullPathFinder::fSubUsedDefect
private

Definition at line 183 of file ConvexHullPathFinder_tool.cc.

Referenced by breakClusterByMaxDefect(), and initializeHistograms().

float lar_cluster3d::ConvexHullPathFinder::fTimeToProcess
mutableprivate

Definition at line 155 of file ConvexHullPathFinder_tool.cc.

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

TH1F* lar_cluster3d::ConvexHullPathFinder::fTopConvexCosEdge
private

Definition at line 169 of file ConvexHullPathFinder_tool.cc.

Referenced by fillConvexHullHists(), and initializeHistograms().

TH1F* lar_cluster3d::ConvexHullPathFinder::fTopConvexEdgeLen
private

Definition at line 170 of file ConvexHullPathFinder_tool.cc.

Referenced by fillConvexHullHists(), and initializeHistograms().

TH1F* lar_cluster3d::ConvexHullPathFinder::fTopEigen10Ratio
private

Definition at line 166 of file ConvexHullPathFinder_tool.cc.

Referenced by initializeHistograms(), and ModifyClusters().

TH1F* lar_cluster3d::ConvexHullPathFinder::fTopEigen20Ratio
private

Definition at line 165 of file ConvexHullPathFinder_tool.cc.

Referenced by initializeHistograms(), and ModifyClusters().

TH1F* lar_cluster3d::ConvexHullPathFinder::fTopEigen21Ratio
private

Definition at line 164 of file ConvexHullPathFinder_tool.cc.

Referenced by initializeHistograms(), and ModifyClusters().

TH1F* lar_cluster3d::ConvexHullPathFinder::fTopExtremeSep
private

Definition at line 168 of file ConvexHullPathFinder_tool.cc.

Referenced by initializeHistograms().

TH1F* lar_cluster3d::ConvexHullPathFinder::fTopNum3DHits
private

Definition at line 162 of file ConvexHullPathFinder_tool.cc.

Referenced by initializeHistograms(), and ModifyClusters().

TH1F* lar_cluster3d::ConvexHullPathFinder::fTopNumEdges
private

Definition at line 163 of file ConvexHullPathFinder_tool.cc.

Referenced by initializeHistograms(), and ModifyClusters().

TH1F* lar_cluster3d::ConvexHullPathFinder::fTopPrimaryLength
private

Definition at line 167 of file ConvexHullPathFinder_tool.cc.

Referenced by initializeHistograms(), and ModifyClusters().


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