11 #include "cetlib/search_path.h" 12 #include "cetlib/cpu_timer.h" 28 #include <boost/range/adaptor/reversed.hpp> 31 #include <Eigen/Dense> 88 const Eigen::Vector3f&,
89 const Eigen::Vector3f&,
90 const Eigen::Vector3f&,
92 Eigen::Vector3f&)
const;
94 using Point = std::tuple<float,float,const reco::ClusterHit3D*>;
115 m_pcaAlg(pset.get<
fhicl::ParameterSet>(
"PrincipalComponentsAlg"))
153 cet::cpu_timer theClockBuildClusters;
158 int countClusters(0);
165 while(clusterParametersListItr != clusterParametersList.end())
170 std::cout <<
"**> Looking at Cluster " << countClusters++ << std::endl;
186 std::cout <<
">>>>>>>>>>> Reclustered to " << reclusteredParameters.size() <<
" Clusters <<<<<<<<<<<<<<<" << std::endl;
189 if (!reclusteredParameters.empty())
192 for (
auto&
cluster : reclusteredParameters)
194 std::cout <<
"****> Calling breakIntoTinyBits" << std::endl;
199 std::cout <<
"****> Broke Cluster with " <<
cluster.getHitPairListPtr().size() <<
" into " <<
cluster.daughterList().size() <<
" sub clusters";
200 for(
auto& clus :
cluster.daughterList()) std::cout <<
", " << clus.getHitPairListPtr().size();
201 std::cout << std::endl;
210 clusterParametersListItr++;
215 theClockBuildClusters.stop();
220 mf::LogDebug(
"Cluster3D") <<
">>>>> Cluster Path finding done" << std::endl;
238 std::string pluses(level/2,
'+');
239 std::string
indent(level/2,
' ');
248 std::vector<double> eigenValVec = {3. * std::sqrt(fullPCA.
getEigenValues()[0]),
252 std::cout << indent <<
">>> breakIntoTinyBits with " << clusterToBreak.
getHitPairListPtr().size() <<
" input hits " << std::endl;
259 bool storeCurrentCluster(
true);
274 const reco::EdgeTuple& longEdge = *std::max_element(bestEdgeList.begin(),bestEdgeList.end(),[](
const auto& first,
const auto& second){
return std::get<2>(first) < std::get<2>(second);});
279 double edgeLen = std::get<2>(longEdge);
280 Eigen::Vector3f edgeVec(secondEdgeHit->getPosition()[0] - firstEdgeHit->getPosition()[0],
281 secondEdgeHit->getPosition()[1] - firstEdgeHit->getPosition()[1],
282 secondEdgeHit->getPosition()[2] - firstEdgeHit->getPosition()[2]);
289 float furthestDistance(0.);
292 for(
const auto& edge : bestEdgeList)
297 Eigen::Vector3f hitToEdgeVec(nextEdgeHit->
getPosition()[0] - firstEdgeHit->getPosition()[0],
298 nextEdgeHit->
getPosition()[1] - firstEdgeHit->getPosition()[1],
299 nextEdgeHit->
getPosition()[2] - firstEdgeHit->getPosition()[2]);
302 float hitProjection = hitToEdgeVec.dot(edgeVec);
305 if (hitProjection > 0. && hitProjection < edgeLen)
307 Eigen::Vector3f distToHitVec = hitToEdgeVec - hitProjection * edgeVec;
308 float distToHit = distToHitVec.norm();
310 if (distToHit > furthestDistance)
312 furthestDistance = distToHit;
313 furthestHit = nextEdgeHit;
329 clusHitPairVector.sort([](
const auto&
left,
const auto&
right){
return left->getArclenToPoca() <
right->getArclenToPoca();});
335 using Hit3DItrPair = std::pair<reco::HitPairListPtr::iterator,reco::HitPairListPtr::iterator>;
336 using VertexPairList = std::list<Hit3DItrPair>;
338 VertexPairList vertexPairList;
341 if (std::distance(clusHitPairVector.begin(),vertexItr) > minimumClusterSize && std::distance(vertexItr,clusHitPairVector.end()) > minimumClusterSize)
343 vertexPairList.emplace_back(Hit3DItrPair(clusHitPairVector.begin(),vertexItr));
344 vertexPairList.emplace_back(Hit3DItrPair(vertexItr,clusHitPairVector.end()));
347 storeCurrentCluster =
false;
350 for(
auto& hit3DItrPair : vertexPairList)
355 std::cout << indent <<
"+> -- building new cluster, size: " << std::distance(hit3DItrPair.first,hit3DItrPair.second) << std::endl;
358 hitPairListPtr.resize(std::distance(hit3DItrPair.first,hit3DItrPair.second));
361 std::copy(hit3DItrPair.first,hit3DItrPair.second,hitPairListPtr.begin());
372 std::cout << indent <<
"+> -- >> cluster has a valid Full PCA" << std::endl;
379 if (fullPrimaryVec.dot(newPrimaryVec) < 0.)
383 eigenVectors.resize(3);
385 for(
size_t vecIdx = 0; vecIdx < 3; vecIdx++)
387 eigenVectors[vecIdx].resize(3,0.);
405 positionItr =
breakIntoTinyBits(clusterParams, positionItr, outputClusterList, level+4);
412 if (storeCurrentCluster)
417 std::set<const reco::ClusterHit2D*> hitSet;
422 for(
const auto& hit2D : hit3D->getHits())
424 if (hit2D) hitSet.insert(hit2D);
429 for(
const auto& hit2D : hitSet)
435 std::cout << indent <<
"*********>>> storing new subcluster of size " << clusterToBreak.
getHitPairListPtr().size() << std::endl;
437 positionItr = outputClusterList.insert(positionItr,clusterToBreak);
442 else if (inputPositionItr == positionItr) std::cout << indent <<
"***** DID NOT STORE A CLUSTER *****" << std::endl;
450 std::string minuses(level/2,
'-');
451 std::string
indent(level/2,
' ');
466 Eigen::Matrix3f rotationMatrix;
468 rotationMatrix << planeVec0(0), planeVec0(1), planeVec0(2),
469 planeVec1(0), planeVec1(1), planeVec1(2),
470 pcaPlaneNrml(0), pcaPlaneNrml(1), pcaPlaneNrml(2);
473 using Point = std::tuple<float,float,const reco::ClusterHit3D*>;
480 Eigen::Vector3f pcaToHitVec(hit3D->getPosition()[0] - pcaCenter(0),
481 hit3D->getPosition()[1] - pcaCenter(1),
482 hit3D->getPosition()[2] - pcaCenter(2));
483 Eigen::Vector3f pcaToHit = rotationMatrix * pcaToHitVec;
485 pointList.emplace_back(
dcel2d::Point(pcaToHit(0),pcaToHit(1),hit3D));
489 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);});
492 std::vector<ConvexHull> convexHullVec;
493 std::vector<PointList> rejectedListVec;
494 bool increaseDepth(pointList.size() > 5);
500 convexHullVec.push_back(
ConvexHull(pointList));
503 const ConvexHull& convexHull = convexHullVec.back();
504 PointList& rejectedList = rejectedListVec.back();
507 increaseDepth =
false;
511 std::cout << indent <<
"-> built convex hull, 3D hits: " << pointList.size() <<
" with " << convexHullPoints.size() <<
" vertices" <<
", area: " << convexHull.
getConvexHullArea() << std::endl;
512 std::cout << indent <<
"-> -Points:";
513 for(
const auto& point : convexHullPoints)
514 std::cout <<
" (" << std::get<0>(point) <<
"," << std::get<1>(point) <<
")";
515 std::cout << std::endl;
519 for(
auto& point : convexHullPoints)
521 pointList.remove(point);
522 rejectedList.emplace_back(point);
531 while(!convexHullVec.empty() && convexHullVec.back().getConvexHullArea() < 0.5)
533 convexHullVec.pop_back();
534 rejectedListVec.pop_back();
538 if (!convexHullVec.empty())
540 size_t nRejectedTotal(0);
543 for(
const auto& rejectedList : rejectedListVec)
545 nRejectedTotal += rejectedList.size();
547 for(
const auto& rejectedPoint : rejectedList)
549 std::cout << indent <<
"-> -- Point is " << convexHullVec.back().findNearestDistance(rejectedPoint) <<
" from nearest edge" << std::endl;
551 if (convexHullVec.back().findNearestDistance(rejectedPoint) > 0.5)
552 hitPairListPtr.remove(std::get<2>(rejectedPoint));
556 std::cout << indent <<
"-> Removed " << nRejectedTotal <<
" leaving " << pointList.size() <<
"/" << hitPairListPtr.size() <<
" points" << std::endl;
562 Point lastPoint = convexHullVec.back().getConvexHull().front();
564 for(
auto& curPoint : convexHullVec.back().getConvexHull())
566 if (curPoint == lastPoint)
continue;
571 float distBetweenPoints = (curPoint3D->getPosition()[0] - lastPoint3D->
getPosition()[0]) * (curPoint3D->getPosition()[0] - lastPoint3D->
getPosition()[0])
572 + (curPoint3D->getPosition()[1] - lastPoint3D->
getPosition()[1]) * (curPoint3D->getPosition()[1] - lastPoint3D->
getPosition()[1])
573 + (curPoint3D->getPosition()[2] - lastPoint3D->
getPosition()[2]) * (curPoint3D->getPosition()[2] - lastPoint3D->
getPosition()[2]);
575 distBetweenPoints = std::sqrt(distBetweenPoints);
579 edgeMap[lastPoint3D].push_back(edge);
580 edgeMap[curPoint3D].push_back(edge);
581 bestEdgeList.emplace_back(edge);
583 lastPoint = curPoint;
614 Eigen::Matrix3f rotationMatrix;
616 rotationMatrix << planeVec0(0), planeVec0(1), planeVec0(2),
617 planeVec1(0), planeVec1(1), planeVec1(2),
618 pcaPlaneNrml(0), pcaPlaneNrml(1), pcaPlaneNrml(2);
625 Eigen::Vector3f pcaToHitVec(hit3D->getPosition()[0] - pcaCenter(0),
626 hit3D->getPosition()[1] - pcaCenter(1),
627 hit3D->getPosition()[2] - pcaCenter(2));
628 Eigen::Vector3f pcaToHit = rotationMatrix * pcaToHitVec;
630 pointList.emplace_back(
dcel2d::Point(pcaToHit(0),pcaToHit(1),hit3D));
634 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);});
647 Eigen::Matrix3f rotationMatrixInv = rotationMatrix.inverse();
650 for(
auto&
vertex : vertexList)
652 Eigen::Vector3f coords = rotationMatrixInv *
vertex.getCoords();
676 dcel2d::Point lastPoint = voronoiDiagram.getConvexHull().front();
681 for(
auto& curPoint : voronoiDiagram.getConvexHull())
683 if (curPoint == lastPoint)
continue;
688 float distBetweenPoints = (curPoint3D->getPosition()[0] - lastPoint3D->
getPosition()[0]) * (curPoint3D->getPosition()[0] - lastPoint3D->
getPosition()[0])
689 + (curPoint3D->getPosition()[1] - lastPoint3D->
getPosition()[1]) * (curPoint3D->getPosition()[1] - lastPoint3D->
getPosition()[1])
690 + (curPoint3D->getPosition()[2] - lastPoint3D->
getPosition()[2]) * (curPoint3D->getPosition()[2] - lastPoint3D->
getPosition()[2]);
692 distBetweenPoints = std::sqrt(distBetweenPoints);
696 edgeMap[lastPoint3D].push_back(edge);
697 edgeMap[curPoint3D].push_back(edge);
698 bestEdgeList.emplace_back(edge);
700 lastPoint = curPoint;
703 std::cout <<
"****> vertexList containted " << vertexList.size() <<
" vertices" << std::endl;
710 const Eigen::Vector3f& u0,
711 const Eigen::Vector3f& P1,
712 const Eigen::Vector3f& u1,
713 Eigen::Vector3f& poca0,
714 Eigen::Vector3f& poca1)
const 717 Eigen::Vector3f w0 = P0 - P1;
723 float den(a * c - b * b);
725 float arcLen0 = (b *
e - c *
d) / den;
726 float arcLen1 = (a *
e - b *
d) / den;
728 poca0 = P0 + arcLen0 * u0;
729 poca1 = P1 + arcLen1 * u1;
731 return (poca0 - poca1).norm();
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)
void PCAAnalysis_3D(const reco::HitPairListPtr &hitPairList, reco::PrincipalComponents &pca, bool skeletonOnly=false) const
float getTimeToExecute() const override
If monitoring, recover the time to execute a particular function.
reco::ClusterParametersList::iterator breakIntoTinyBits(reco::ClusterParameters &cluster, reco::ClusterParametersList::iterator positionItr, reco::ClusterParametersList &outputClusterList, int level=0) const
Use PCA to try to find path in cluster.
Declaration of signal hit object.
float closestApproach(const Eigen::Vector3f &, const Eigen::Vector3f &, const Eigen::Vector3f &, const Eigen::Vector3f &, Eigen::Vector3f &, Eigen::Vector3f &) const
reco::PrincipalComponents & getSkeletonPCA()
reco::EdgeList & getBestEdgeList()
std::pair< Point, Point > MinMaxPoints
const float * getAvePosition() const
int getNumHitsUsed() const
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
reco::HitPairListPtr & getHitPairListPtr()
Cluster finding and building.
~VoronoiPathFinder()
Destructor.
IClusterModAlg interface class definiton.
bool m_enableMonitoring
Data members to follow.
ClusterParametersList & daughterList()
Implements a ConvexHull for use in clustering.
std::list< EdgeTuple > EdgeList
VoronoiDiagram class definiton.
reco::PrincipalComponents & getFullPCA()
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
void buildVoronoiDiagram(const dcel2d::PointList &)
Given an input set of 2D points construct a 2D voronoi diagram.
void ModifyClusters(reco::ClusterParametersList &) const override
Scan an input collection of clusters and modify those according to the specific implementing algorith...
T get(std::string const &key) const
std::tuple< float, float, const reco::ClusterHit3D * > Point
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
std::list< const reco::ClusterHit3D * > HitPairListPtr
void UpdateParameters(const reco::ClusterHit2D *hit)
float getConvexHullArea() const
recover the area of the convex hull
std::vector< std::vector< float > > EigenVectors
This provides an art tool interface definition for 3D Cluster algorithms.
The geometry of one entire detector, as served by art.
const PointList & getConvexHull() const
recover the list of convex hull vertices
const float * getPosition() const
ConvexHull class definiton.
This header file defines the interface to a principal components analysis designed to be used within ...
Encapsulate the geometry of a wire.
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
std::unique_ptr< lar_cluster3d::IClusterAlg > m_clusterAlg
Algorithm to do 3D space point clustering.
Utility object to perform functions of association.
const float * getEigenValues() const
Encapsulate the construction of a single detector plane.
const float getAveHitDoca() const
dcel2d::FaceList & getFaceList()
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
This provides an art tool interface definition for 3D Cluster algorithms.
size_t m_minTinyClusterSize
Minimum size for a "tiny" cluster.
void buildVoronoiDiagram(reco::ClusterParameters &clusterParameters, int level=0) const
std::list< Point > PointList
std::list< Point > PointList
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
std::pair< MinMaxPoints, MinMaxPoints > MinMaxPointPair
PrincipalComponentsAlg m_pcaAlg
dcel2d::HalfEdgeList & getHalfEdgeList()
std::list< Vertex > VertexList
geo::Geometry * m_geometry
art framework interface to geometry description
std::list< ClusterParameters > ClusterParametersList
VoronoiPathFinder(const fhicl::ParameterSet &)
Constructor.
const EigenVectors & getEigenVectors() const
dcel2d::VertexList & getVertexList()
void configure(fhicl::ParameterSet const &pset) override