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 clusHitPairVector.sort([](
const auto&
left,
const auto&
right){
return left->getArclenToPoca() <
right->getArclenToPoca();});
278 std::vector<const reco::ClusterHit3D*> vertexHitVec;
280 std::cout << indent <<
"+> Breaking cluster, convex hull has " << bestEdgeList.size() <<
" edges to work with" << std::endl;
282 for(
const auto& edge : bestEdgeList)
284 vertexHitVec.push_back(std::get<0>(edge));
285 vertexHitVec.push_back(std::get<1>(edge));
289 std::sort(vertexHitVec.begin(),vertexHitVec.end(),[](
const auto&
left,
const auto&
right){
return left->getArclenToPoca() <
right->getArclenToPoca();});
292 using Hit3DItrPair = std::pair<reco::HitPairListPtr::iterator,reco::HitPairListPtr::iterator>;
293 using VertexPairList = std::list<Hit3DItrPair>;
295 VertexPairList vertexPairList;
298 for(
const auto& hit3D : vertexHitVec)
302 if (vertexItr == clusHitPairVector.end())
304 std::cout << indent <<
">>>>>>>>>>>>>>>>> Hit not found in input list, cannot happen? <<<<<<<<<<<<<<<<<<<" << std::endl;
308 std::cout << indent <<
"+> -- Distance from first to current vertex point: " << std::distance(firstHitItr,vertexItr) <<
" first: " << *firstHitItr <<
", vertex: " << *vertexItr;
311 if (std::distance(firstHitItr,vertexItr) > minimumClusterSize)
313 vertexPairList.emplace_back(Hit3DItrPair(firstHitItr,vertexItr));
314 firstHitItr = vertexItr;
316 std::cout <<
" ++ made pair ";
319 std::cout << std::endl;
323 if (std::distance(firstHitItr,clusHitPairVector.end()) > 0)
325 std::cout << indent <<
"+> loop over vertices done, remant distance: " << std::distance(firstHitItr,clusHitPairVector.end()) << std::endl;
328 if (!vertexPairList.empty() && std::distance(firstHitItr,clusHitPairVector.end()) < minimumClusterSize)
329 vertexPairList.back().second = clusHitPairVector.end();
331 vertexPairList.emplace_back(Hit3DItrPair(firstHitItr,clusHitPairVector.end()));
334 std::cout << indent <<
"+> ---> breaking cluster into " << vertexPairList.size() <<
" subclusters" << std::endl;
336 if (vertexPairList.size() > 1)
338 storeCurrentCluster =
false;
341 for(
auto& hit3DItrPair : vertexPairList)
346 std::cout << indent <<
"+> -- building new cluster, size: " << std::distance(hit3DItrPair.first,hit3DItrPair.second) << std::endl;
349 hitPairListPtr.resize(std::distance(hit3DItrPair.first,hit3DItrPair.second));
352 std::copy(hit3DItrPair.first,hit3DItrPair.second,hitPairListPtr.begin());
363 std::cout << indent <<
"+> -- >> cluster has a valid Full PCA" << std::endl;
370 if (fullPrimaryVec.dot(newPrimaryVec) < 0.)
374 eigenVectors.resize(3);
376 for(
size_t vecIdx = 0; vecIdx < 3; vecIdx++)
378 eigenVectors[vecIdx].resize(3,0.);
396 positionItr =
breakIntoTinyBits(clusterParams, positionItr, outputClusterList, level+4);
403 if (storeCurrentCluster)
408 std::set<const reco::ClusterHit2D*> hitSet;
413 for(
const auto& hit2D : hit3D->getHits())
415 if (hit2D) hitSet.insert(hit2D);
420 for(
const auto& hit2D : hitSet)
426 std::cout << indent <<
"*********>>> storing new subcluster of size " << clusterToBreak.
getHitPairListPtr().size() << std::endl;
428 positionItr = outputClusterList.insert(positionItr,clusterToBreak);
433 else if (inputPositionItr == positionItr) std::cout << indent <<
"***** DID NOT STORE A CLUSTER *****" << std::endl;
441 std::string minuses(level/2,
'-');
442 std::string
indent(level/2,
' ');
457 Eigen::Matrix3f rotationMatrix;
459 rotationMatrix << planeVec0(0), planeVec0(1), planeVec0(2),
460 planeVec1(0), planeVec1(1), planeVec1(2),
461 pcaPlaneNrml(0), pcaPlaneNrml(1), pcaPlaneNrml(2);
464 using Point = std::tuple<float,float,const reco::ClusterHit3D*>;
471 Eigen::Vector3f pcaToHitVec(hit3D->getPosition()[0] - pcaCenter(0),
472 hit3D->getPosition()[1] - pcaCenter(1),
473 hit3D->getPosition()[2] - pcaCenter(2));
474 Eigen::Vector3f pcaToHit = rotationMatrix * pcaToHitVec;
476 pointList.emplace_back(
dcel2d::Point(pcaToHit(0),pcaToHit(1),hit3D));
480 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);});
483 std::vector<ConvexHull> convexHullVec;
484 std::vector<PointList> rejectedListVec;
485 bool increaseDepth(pointList.size() > 5);
491 convexHullVec.push_back(
ConvexHull(pointList));
494 const ConvexHull& convexHull = convexHullVec.back();
495 PointList& rejectedList = rejectedListVec.back();
498 increaseDepth =
false;
502 std::cout << indent <<
"-> built convex hull, 3D hits: " << pointList.size() <<
" with " << convexHullPoints.size() <<
" vertices" <<
", area: " << convexHull.
getConvexHullArea() << std::endl;
503 std::cout << indent <<
"-> -Points:";
504 for(
const auto& point : convexHullPoints)
505 std::cout <<
" (" << std::get<0>(point) <<
"," << std::get<1>(point) <<
")";
506 std::cout << std::endl;
510 for(
auto& point : convexHullPoints)
512 pointList.remove(point);
513 rejectedList.emplace_back(point);
522 while(!convexHullVec.empty() && convexHullVec.back().getConvexHullArea() < 0.5)
524 convexHullVec.pop_back();
525 rejectedListVec.pop_back();
529 if (!convexHullVec.empty())
531 size_t nRejectedTotal(0);
534 for(
const auto& rejectedList : rejectedListVec)
536 nRejectedTotal += rejectedList.size();
538 for(
const auto& rejectedPoint : rejectedList)
540 std::cout << indent <<
"-> -- Point is " << convexHullVec.back().findNearestDistance(rejectedPoint) <<
" from nearest edge" << std::endl;
542 if (convexHullVec.back().findNearestDistance(rejectedPoint) > 0.5)
543 hitPairListPtr.remove(std::get<2>(rejectedPoint));
547 std::cout << indent <<
"-> Removed " << nRejectedTotal <<
" leaving " << pointList.size() <<
"/" << hitPairListPtr.size() <<
" points" << std::endl;
553 Point lastPoint = convexHullVec.back().getConvexHull().front();
555 for(
auto& curPoint : convexHullVec.back().getConvexHull())
557 if (curPoint == lastPoint)
continue;
562 float distBetweenPoints = (curPoint3D->getPosition()[0] - lastPoint3D->
getPosition()[0]) * (curPoint3D->getPosition()[0] - lastPoint3D->
getPosition()[0])
563 + (curPoint3D->getPosition()[1] - lastPoint3D->
getPosition()[1]) * (curPoint3D->getPosition()[1] - lastPoint3D->
getPosition()[1])
564 + (curPoint3D->getPosition()[2] - lastPoint3D->
getPosition()[2]) * (curPoint3D->getPosition()[2] - lastPoint3D->
getPosition()[2]);
566 distBetweenPoints = std::sqrt(distBetweenPoints);
570 edgeMap[lastPoint3D].push_back(edge);
571 edgeMap[curPoint3D].push_back(edge);
572 bestEdgeList.emplace_back(edge);
574 lastPoint = curPoint;
605 Eigen::Matrix3f rotationMatrix;
607 rotationMatrix << planeVec0(0), planeVec0(1), planeVec0(2),
608 planeVec1(0), planeVec1(1), planeVec1(2),
609 pcaPlaneNrml(0), pcaPlaneNrml(1), pcaPlaneNrml(2);
616 Eigen::Vector3f pcaToHitVec(hit3D->getPosition()[0] - pcaCenter(0),
617 hit3D->getPosition()[1] - pcaCenter(1),
618 hit3D->getPosition()[2] - pcaCenter(2));
619 Eigen::Vector3f pcaToHit = rotationMatrix * pcaToHitVec;
621 pointList.emplace_back(
dcel2d::Point(pcaToHit(0),pcaToHit(1),hit3D));
625 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);});
638 Eigen::Matrix3f rotationMatrixInv = rotationMatrix.inverse();
641 for(
auto&
vertex : vertexList)
643 Eigen::Vector3f coords = rotationMatrixInv *
vertex.getCoords();
667 dcel2d::Point lastPoint = voronoiDiagram.getConvexHull().front();
672 for(
auto& curPoint : voronoiDiagram.getConvexHull())
674 if (curPoint == lastPoint)
continue;
679 float distBetweenPoints = (curPoint3D->getPosition()[0] - lastPoint3D->
getPosition()[0]) * (curPoint3D->getPosition()[0] - lastPoint3D->
getPosition()[0])
680 + (curPoint3D->getPosition()[1] - lastPoint3D->
getPosition()[1]) * (curPoint3D->getPosition()[1] - lastPoint3D->
getPosition()[1])
681 + (curPoint3D->getPosition()[2] - lastPoint3D->
getPosition()[2]) * (curPoint3D->getPosition()[2] - lastPoint3D->
getPosition()[2]);
683 distBetweenPoints = std::sqrt(distBetweenPoints);
687 edgeMap[lastPoint3D].push_back(edge);
688 edgeMap[curPoint3D].push_back(edge);
689 bestEdgeList.emplace_back(edge);
691 lastPoint = curPoint;
694 std::cout <<
"****> vertexList containted " << vertexList.size() <<
" vertices" << std::endl;
701 const Eigen::Vector3f& u0,
702 const Eigen::Vector3f& P1,
703 const Eigen::Vector3f& u1,
704 Eigen::Vector3f& poca0,
705 Eigen::Vector3f& poca1)
const 708 Eigen::Vector3f w0 = P0 - P1;
714 float den(a * c - b * b);
716 float arcLen0 = (b *
e - c *
d) / den;
717 float arcLen1 = (a *
e - b *
d) / den;
719 poca0 = P0 + arcLen0 * u0;
720 poca1 = P1 + arcLen1 * u1;
722 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
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()