12 #include "cetlib/search_path.h" 13 #include "cetlib/cpu_timer.h" 29 #include <boost/range/adaptor/reversed.hpp> 32 #include <Eigen/Dense> 97 const Eigen::Vector3f&,
98 const Eigen::Vector3f&,
99 const Eigen::Vector3f&,
101 Eigen::Vector3f&)
const;
103 using Point = std::tuple<float,float,const reco::ClusterHit3D*>;
124 m_pcaAlg(pset.get<
fhicl::ParameterSet>(
"PrincipalComponentsAlg"))
167 cet::cpu_timer theClockBuildClusters;
172 int countClusters(0);
179 while(clusterParametersListItr != clusterParametersList.end())
184 std::cout <<
"**> Looking at Cluster " << countClusters++ << std::endl;
200 std::cout <<
">>>>>>>>>>> Reclustered to " << reclusteredParameters.size() <<
" Clusters <<<<<<<<<<<<<<<" << std::endl;
203 if (!reclusteredParameters.empty())
206 for (
auto&
cluster : reclusteredParameters)
208 std::cout <<
"****> Calling breakIntoTinyBits" << std::endl;
213 std::cout <<
"****> Broke Cluster with " <<
cluster.getHitPairListPtr().size() <<
" into " <<
cluster.daughterList().size() <<
" sub clusters";
214 for(
auto& clus :
cluster.daughterList()) std::cout <<
", " << clus.getHitPairListPtr().size();
215 std::cout << std::endl;
224 clusterParametersListItr++;
229 theClockBuildClusters.stop();
234 mf::LogDebug(
"Cluster3D") <<
">>>>> Cluster Path finding done" << std::endl;
252 std::string pluses(level/2,
'+');
253 std::string
indent(level/2,
' ');
262 std::vector<double> eigenValVec = {3. * std::sqrt(fullPCA.
getEigenValues()[0]),
266 std::cout << indent <<
">>> breakIntoTinyBits with " << clusterToBreak.
getHitPairListPtr().size() <<
" input hits " << std::endl;
273 bool storeCurrentCluster(
true);
288 clusHitPairVector.sort([](
const auto&
left,
const auto&
right){
return left->getArclenToPoca() <
right->getArclenToPoca();});
292 std::vector<const reco::ClusterHit3D*> vertexHitVec;
294 std::cout << indent <<
"+> Breaking cluster, convex hull has " << bestEdgeList.size() <<
" edges to work with" << std::endl;
296 for(
const auto& edge : bestEdgeList)
298 vertexHitVec.push_back(std::get<0>(edge));
299 vertexHitVec.push_back(std::get<1>(edge));
303 std::sort(vertexHitVec.begin(),vertexHitVec.end(),[](
const auto&
left,
const auto&
right){
return left->getArclenToPoca() <
right->getArclenToPoca();});
306 using Hit3DItrPair = std::pair<reco::HitPairListPtr::iterator,reco::HitPairListPtr::iterator>;
307 using VertexPairList = std::list<Hit3DItrPair>;
309 VertexPairList vertexPairList;
312 for(
const auto& hit3D : vertexHitVec)
316 if (vertexItr == clusHitPairVector.end())
318 std::cout << indent <<
">>>>>>>>>>>>>>>>> Hit not found in input list, cannot happen? <<<<<<<<<<<<<<<<<<<" << std::endl;
322 std::cout << indent <<
"+> -- Distance from first to current vertex point: " << std::distance(firstHitItr,vertexItr) <<
" first: " << *firstHitItr <<
", vertex: " << *vertexItr;
325 if (std::distance(firstHitItr,vertexItr) > minimumClusterSize)
327 vertexPairList.emplace_back(Hit3DItrPair(firstHitItr,vertexItr));
328 firstHitItr = vertexItr;
330 std::cout <<
" ++ made pair ";
333 std::cout << std::endl;
337 if (std::distance(firstHitItr,clusHitPairVector.end()) > 0)
339 std::cout << indent <<
"+> loop over vertices done, remant distance: " << std::distance(firstHitItr,clusHitPairVector.end()) << std::endl;
342 if (!vertexPairList.empty() && std::distance(firstHitItr,clusHitPairVector.end()) < minimumClusterSize)
343 vertexPairList.back().second = clusHitPairVector.end();
345 vertexPairList.emplace_back(Hit3DItrPair(firstHitItr,clusHitPairVector.end()));
348 std::cout << indent <<
"+> ---> breaking cluster into " << vertexPairList.size() <<
" subclusters" << std::endl;
350 if (vertexPairList.size() > 1)
352 storeCurrentCluster =
false;
355 for(
auto& hit3DItrPair : vertexPairList)
360 std::cout << indent <<
"+> -- building new cluster, size: " << std::distance(hit3DItrPair.first,hit3DItrPair.second) << std::endl;
363 hitPairListPtr.resize(std::distance(hit3DItrPair.first,hit3DItrPair.second));
366 std::copy(hit3DItrPair.first,hit3DItrPair.second,hitPairListPtr.begin());
377 std::cout << indent <<
"+> -- >> cluster has a valid Full PCA" << std::endl;
384 if (fullPrimaryVec.dot(newPrimaryVec) < 0.)
388 eigenVectors.resize(3);
390 for(
size_t vecIdx = 0; vecIdx < 3; vecIdx++)
392 eigenVectors[vecIdx].resize(3,0.);
410 positionItr =
breakIntoTinyBits(clusterParams, positionItr, outputClusterList, level+4);
417 if (storeCurrentCluster)
422 std::set<const reco::ClusterHit2D*> hitSet;
427 for(
const auto& hit2D : hit3D->getHits())
429 if (hit2D) hitSet.insert(hit2D);
434 for(
const auto& hit2D : hitSet)
440 std::cout << indent <<
"*********>>> storing new subcluster of size " << clusterToBreak.
getHitPairListPtr().size() << std::endl;
442 positionItr = outputClusterList.insert(positionItr,clusterToBreak);
447 else if (inputPositionItr == positionItr) std::cout << indent <<
"***** DID NOT STORE A CLUSTER *****" << std::endl;
455 std::string minuses(level/2,
'-');
456 std::string
indent(level/2,
' ');
471 Eigen::Matrix3f rotationMatrix;
473 rotationMatrix << planeVec0(0), planeVec0(1), planeVec0(2),
474 planeVec1(0), planeVec1(1), planeVec1(2),
475 pcaPlaneNrml(0), pcaPlaneNrml(1), pcaPlaneNrml(2);
478 using Point = std::tuple<float,float,const reco::ClusterHit3D*>;
485 Eigen::Vector3f pcaToHitVec(hit3D->getPosition()[0] - pcaCenter(0),
486 hit3D->getPosition()[1] - pcaCenter(1),
487 hit3D->getPosition()[2] - pcaCenter(2));
488 Eigen::Vector3f pcaToHit = rotationMatrix * pcaToHitVec;
490 pointList.emplace_back(
dcel2d::Point(pcaToHit(0),pcaToHit(1),hit3D));
494 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);});
497 std::vector<ConvexHull> convexHullVec;
498 std::vector<PointList> rejectedListVec;
499 bool increaseDepth(pointList.size() > 5);
505 convexHullVec.push_back(
ConvexHull(pointList));
508 const ConvexHull& convexHull = convexHullVec.back();
509 PointList& rejectedList = rejectedListVec.back();
512 increaseDepth =
false;
516 std::cout << indent <<
"-> built convex hull, 3D hits: " << pointList.size() <<
" with " << convexHullPoints.size() <<
" vertices" <<
", area: " << convexHull.
getConvexHullArea() << std::endl;
517 std::cout << indent <<
"-> -Points:";
518 for(
const auto& point : convexHullPoints)
519 std::cout <<
" (" << std::get<0>(point) <<
"," << std::get<1>(point) <<
")";
520 std::cout << std::endl;
524 for(
auto& point : convexHullPoints)
526 pointList.remove(point);
527 rejectedList.emplace_back(point);
536 while(!convexHullVec.empty() && convexHullVec.back().getConvexHullArea() < 0.5)
538 convexHullVec.pop_back();
539 rejectedListVec.pop_back();
543 if (!convexHullVec.empty())
545 size_t nRejectedTotal(0);
548 for(
const auto& rejectedList : rejectedListVec)
550 nRejectedTotal += rejectedList.size();
552 for(
const auto& rejectedPoint : rejectedList)
554 std::cout << indent <<
"-> -- Point is " << convexHullVec.back().findNearestDistance(rejectedPoint) <<
" from nearest edge" << std::endl;
556 if (convexHullVec.back().findNearestDistance(rejectedPoint) > 0.5)
557 hitPairListPtr.remove(std::get<2>(rejectedPoint));
561 std::cout << indent <<
"-> Removed " << nRejectedTotal <<
" leaving " << pointList.size() <<
"/" << hitPairListPtr.size() <<
" points" << std::endl;
567 Point lastPoint = convexHullVec.back().getConvexHull().front();
569 for(
auto& curPoint : convexHullVec.back().getConvexHull())
571 if (curPoint == lastPoint)
continue;
576 float distBetweenPoints = (curPoint3D->getPosition()[0] - lastPoint3D->
getPosition()[0]) * (curPoint3D->getPosition()[0] - lastPoint3D->
getPosition()[0])
577 + (curPoint3D->getPosition()[1] - lastPoint3D->
getPosition()[1]) * (curPoint3D->getPosition()[1] - lastPoint3D->
getPosition()[1])
578 + (curPoint3D->getPosition()[2] - lastPoint3D->
getPosition()[2]) * (curPoint3D->getPosition()[2] - lastPoint3D->
getPosition()[2]);
580 distBetweenPoints = std::sqrt(distBetweenPoints);
584 edgeMap[lastPoint3D].push_back(edge);
585 edgeMap[curPoint3D].push_back(edge);
586 bestEdgeList.emplace_back(edge);
588 lastPoint = curPoint;
619 Eigen::Matrix3f rotationMatrix;
621 rotationMatrix << planeVec0(0), planeVec0(1), planeVec0(2),
622 planeVec1(0), planeVec1(1), planeVec1(2),
623 pcaPlaneNrml(0), pcaPlaneNrml(1), pcaPlaneNrml(2);
630 Eigen::Vector3f pcaToHitVec(hit3D->getPosition()[0] - pcaCenter(0),
631 hit3D->getPosition()[1] - pcaCenter(1),
632 hit3D->getPosition()[2] - pcaCenter(2));
633 Eigen::Vector3f pcaToHit = rotationMatrix * pcaToHitVec;
635 pointList.emplace_back(
dcel2d::Point(pcaToHit(0),pcaToHit(1),hit3D));
639 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);});
652 Eigen::Matrix3f rotationMatrixInv = rotationMatrix.inverse();
655 for(
auto&
vertex : vertexList)
657 Eigen::Vector3f coords = rotationMatrixInv *
vertex.getCoords();
681 dcel2d::Point lastPoint = voronoiDiagram.getConvexHull().front();
686 for(
auto& curPoint : voronoiDiagram.getConvexHull())
688 if (curPoint == lastPoint)
continue;
693 float distBetweenPoints = (curPoint3D->getPosition()[0] - lastPoint3D->
getPosition()[0]) * (curPoint3D->getPosition()[0] - lastPoint3D->
getPosition()[0])
694 + (curPoint3D->getPosition()[1] - lastPoint3D->
getPosition()[1]) * (curPoint3D->getPosition()[1] - lastPoint3D->
getPosition()[1])
695 + (curPoint3D->getPosition()[2] - lastPoint3D->
getPosition()[2]) * (curPoint3D->getPosition()[2] - lastPoint3D->
getPosition()[2]);
697 distBetweenPoints = std::sqrt(distBetweenPoints);
701 edgeMap[lastPoint3D].push_back(edge);
702 edgeMap[curPoint3D].push_back(edge);
703 bestEdgeList.emplace_back(edge);
705 lastPoint = curPoint;
708 std::cout <<
"****> vertexList containted " << vertexList.size() <<
" vertices" << std::endl;
715 const Eigen::Vector3f& u0,
716 const Eigen::Vector3f& P1,
717 const Eigen::Vector3f& u1,
718 Eigen::Vector3f& poca0,
719 Eigen::Vector3f& poca1)
const 722 Eigen::Vector3f w0 = P0 - P1;
728 float den(a * c - b * b);
730 float arcLen0 = (b *
e - c *
d) / den;
731 float arcLen1 = (a *
e - b *
d) / den;
733 poca0 = P0 + arcLen0 * u0;
734 poca1 = P1 + arcLen1 * u1;
736 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
Declaration of signal hit object.
void configure(fhicl::ParameterSet const &pset) override
reco::PrincipalComponents & getSkeletonPCA()
~ClusterPathFinder()
Destructor.
std::unique_ptr< lar_cluster3d::IClusterAlg > m_clusterAlg
Algorithm to do 3D space point clustering.
reco::EdgeList & getBestEdgeList()
float closestApproach(const Eigen::Vector3f &, const Eigen::Vector3f &, const Eigen::Vector3f &, const Eigen::Vector3f &, Eigen::Vector3f &, Eigen::Vector3f &) const
const float * getAvePosition() const
int getNumHitsUsed() const
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
reco::HitPairListPtr & getHitPairListPtr()
Cluster finding and building.
std::tuple< float, float, const reco::ClusterHit3D * > Point
std::pair< MinMaxPoints, MinMaxPoints > MinMaxPointPair
float getTimeToExecute() const override
If monitoring, recover the time to execute a particular function.
IClusterModAlg interface class definiton.
ClusterParametersList & daughterList()
Implements a ConvexHull for use in clustering.
std::list< EdgeTuple > EdgeList
void buildConvexHull(reco::ClusterParameters &clusterParameters, int level=0) const
std::list< Point > PointList
void initializeHistograms(art::TFileDirectory &) override
Interface for initializing histograms if they are desired Note that the idea is to put hisgtograms in...
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.
T get(std::string const &key) const
std::string indent(std::size_t const i)
size_t m_minTinyClusterSize
Minimum size for a "tiny" cluster.
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
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.
const float * getPosition() const
std::pair< Point, Point > MinMaxPoints
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.
bool m_enableMonitoring
Data members to follow.
void buildVoronoiDiagram(reco::ClusterParameters &clusterParameters, int level=0) const
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
PrincipalComponentsAlg m_pcaAlg
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.
void ModifyClusters(reco::ClusterParametersList &) const override
Scan an input collection of clusters and modify those according to the specific implementing algorith...
std::list< Point > PointList
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
geo::Geometry * m_geometry
ClusterPathFinder(const fhicl::ParameterSet &)
Constructor.
dcel2d::HalfEdgeList & getHalfEdgeList()
std::list< Vertex > VertexList
art framework interface to geometry description
std::list< ClusterParameters > ClusterParametersList
const EigenVectors & getEigenVectors() const
dcel2d::VertexList & getVertexList()