11 #include "cetlib/cpu_timer.h" 87 const Eigen::Vector3f&,
88 const Eigen::Vector3f&,
89 const Eigen::Vector3f&,
91 Eigen::Vector3f&)
const;
93 using Point = std::tuple<float, float, const reco::ClusterHit3D*>;
107 std::unique_ptr<lar_cluster3d::IClusterAlg>
151 cet::cpu_timer theClockBuildClusters;
156 int countClusters(0);
163 while (clusterParametersListItr != clusterParametersList.end()) {
167 std::cout <<
"**> Looking at Cluster " << countClusters++ << std::endl;
182 std::cout <<
">>>>>>>>>>> Reclustered to " << reclusteredParameters.size()
183 <<
" Clusters <<<<<<<<<<<<<<<" << std::endl;
186 if (!reclusteredParameters.empty()) {
188 for (
auto&
cluster : reclusteredParameters) {
189 std::cout <<
"****> Calling breakIntoTinyBits" << std::endl;
194 std::cout <<
"****> Broke Cluster with " <<
cluster.getHitPairListPtr().size()
195 <<
" into " <<
cluster.daughterList().size() <<
" sub clusters";
196 for (
auto& clus :
cluster.daughterList())
197 std::cout <<
", " << clus.getHitPairListPtr().size();
198 std::cout << std::endl;
208 clusterParametersListItr++;
212 theClockBuildClusters.stop();
217 mf::LogDebug(
"Cluster3D") <<
">>>>> Cluster Path finding done" << std::endl;
236 std::string pluses(level / 2,
'+');
237 std::string
indent(level / 2,
' ');
247 std::cout << indent <<
">>> breakIntoTinyBits with " 255 bool storeCurrentCluster(
true);
269 clusHitPairVector.sort([](
const auto&
left,
const auto&
right) {
270 return left->getArclenToPoca() <
right->getArclenToPoca();
275 std::vector<const reco::ClusterHit3D*> vertexHitVec;
277 std::cout << indent <<
"+> Breaking cluster, convex hull has " << bestEdgeList.size()
278 <<
" edges to work with" << std::endl;
280 for (
const auto& edge : bestEdgeList) {
281 vertexHitVec.push_back(std::get<0>(edge));
282 vertexHitVec.push_back(std::get<1>(edge));
286 std::sort(vertexHitVec.begin(), vertexHitVec.end(), [](
const auto&
left,
const auto&
right) {
287 return left->getArclenToPoca() <
right->getArclenToPoca();
292 std::pair<reco::HitPairListPtr::iterator, reco::HitPairListPtr::iterator>;
293 using VertexPairList = std::list<Hit3DItrPair>;
295 VertexPairList vertexPairList;
298 for (
const auto& hit3D : vertexHitVec) {
300 std::find(firstHitItr, clusHitPairVector.end(), hit3D);
302 if (vertexItr == clusHitPairVector.end()) {
305 <<
">>>>>>>>>>>>>>>>> Hit not found in input list, cannot happen? <<<<<<<<<<<<<<<<<<<" 310 std::cout << indent <<
"+> -- Distance from first to current vertex point: " 311 << std::distance(firstHitItr, vertexItr) <<
" first: " << *firstHitItr
312 <<
", vertex: " << *vertexItr;
315 if (std::distance(firstHitItr, vertexItr) > minimumClusterSize) {
316 vertexPairList.emplace_back(Hit3DItrPair(firstHitItr, vertexItr));
317 firstHitItr = vertexItr;
319 std::cout <<
" ++ made pair ";
322 std::cout << std::endl;
326 if (std::distance(firstHitItr, clusHitPairVector.end()) > 0) {
327 std::cout << indent <<
"+> loop over vertices done, remant distance: " 328 << std::distance(firstHitItr, clusHitPairVector.end()) << std::endl;
331 if (!vertexPairList.empty() &&
332 std::distance(firstHitItr, clusHitPairVector.end()) < minimumClusterSize)
333 vertexPairList.back().second = clusHitPairVector.end();
335 vertexPairList.emplace_back(Hit3DItrPair(firstHitItr, clusHitPairVector.end()));
338 std::cout << indent <<
"+> ---> breaking cluster into " << vertexPairList.size()
339 <<
" subclusters" << std::endl;
341 if (vertexPairList.size() > 1) {
342 storeCurrentCluster =
false;
345 for (
auto& hit3DItrPair : vertexPairList) {
349 std::cout << indent <<
"+> -- building new cluster, size: " 350 << std::distance(hit3DItrPair.first, hit3DItrPair.second) << std::endl;
353 hitPairListPtr.resize(std::distance(hit3DItrPair.first, hit3DItrPair.second));
356 std::copy(hit3DItrPair.first, hit3DItrPair.second, hitPairListPtr.begin());
366 std::cout << indent <<
"+> -- >> cluster has a valid Full PCA" << std::endl;
373 if (fullPrimaryVec.dot(newPrimaryVec) < 0.) {
374 for (
size_t vecIdx = 0; vecIdx < 3; vecIdx++)
389 if (storeCurrentCluster) {
393 std::set<const reco::ClusterHit2D*> hitSet;
397 for (
const auto& hit2D : hit3D->getHits()) {
398 if (hit2D) hitSet.insert(hit2D);
403 for (
const auto& hit2D : hitSet) {
408 std::cout << indent <<
"*********>>> storing new subcluster of size " 411 positionItr = outputClusterList.insert(positionItr, clusterToBreak);
416 else if (inputPositionItr == positionItr)
417 std::cout << indent <<
"***** DID NOT STORE A CLUSTER *****" << std::endl;
426 std::string minuses(level / 2,
'-');
427 std::string
indent(level / 2,
' ');
439 using Point = std::tuple<float, float, const reco::ClusterHit3D*>;
445 Eigen::Vector3f pcaToHitVec(hit3D->getPosition()[0] - pcaCenter(0),
446 hit3D->getPosition()[1] - pcaCenter(1),
447 hit3D->getPosition()[2] - pcaCenter(2));
450 pointList.emplace_back(
dcel2d::Point(pcaToHit(1), pcaToHit(2), hit3D));
454 pointList.sort([](
const auto&
left,
const auto&
right) {
456 std::numeric_limits<float>::epsilon()) ?
462 std::vector<ConvexHull> convexHullVec;
463 std::vector<PointList> rejectedListVec;
464 bool increaseDepth(pointList.size() > 5);
465 float lastArea(std::numeric_limits<float>::max());
467 while (increaseDepth) {
469 convexHullVec.push_back(
ConvexHull(pointList));
472 const ConvexHull& convexHull = convexHullVec.back();
473 PointList& rejectedList = rejectedListVec.back();
476 increaseDepth =
false;
479 std::cout << indent <<
"-> built convex hull, 3D hits: " << pointList.size() <<
" with " 480 << convexHullPoints.size() <<
" vertices" 482 std::cout << indent <<
"-> -Points:";
483 for (
const auto& point : convexHullPoints)
484 std::cout <<
" (" << std::get<0>(point) <<
"," << std::get<1>(point) <<
")";
485 std::cout << std::endl;
487 if (convexHullVec.size() < 2 || convexHull.
getConvexHullArea() < 0.8 * lastArea) {
488 for (
auto& point : convexHullPoints) {
489 pointList.remove(point);
490 rejectedList.emplace_back(point);
499 while (!convexHullVec.empty() && convexHullVec.back().getConvexHullArea() < 0.5) {
500 convexHullVec.pop_back();
501 rejectedListVec.pop_back();
505 if (!convexHullVec.empty()) {
506 size_t nRejectedTotal(0);
509 for (
const auto& rejectedList : rejectedListVec) {
510 nRejectedTotal += rejectedList.size();
512 for (
const auto& rejectedPoint : rejectedList) {
513 std::cout << indent <<
"-> -- Point is " 514 << convexHullVec.back().findNearestDistance(rejectedPoint)
515 <<
" from nearest edge" << std::endl;
517 if (convexHullVec.back().findNearestDistance(rejectedPoint) > 0.5)
518 hitPairListPtr.remove(std::get<2>(rejectedPoint));
522 std::cout << indent <<
"-> Removed " << nRejectedTotal <<
" leaving " << pointList.size()
523 <<
"/" << hitPairListPtr.size() <<
" points" << std::endl;
529 Point lastPoint = convexHullVec.back().getConvexHull().front();
531 for (
auto& curPoint : convexHullVec.back().getConvexHull()) {
532 if (curPoint == lastPoint)
continue;
537 float distBetweenPoints = (curPoint3D->getPosition()[0] - lastPoint3D->
getPosition()[0]) *
538 (curPoint3D->getPosition()[0] - lastPoint3D->
getPosition()[0]) +
539 (curPoint3D->getPosition()[1] - lastPoint3D->
getPosition()[1]) *
540 (curPoint3D->getPosition()[1] - lastPoint3D->
getPosition()[1]) +
541 (curPoint3D->getPosition()[2] - lastPoint3D->
getPosition()[2]) *
542 (curPoint3D->getPosition()[2] - lastPoint3D->
getPosition()[2]);
544 distBetweenPoints = std::sqrt(distBetweenPoints);
548 edgeMap[lastPoint3D].push_back(edge);
549 edgeMap[curPoint3D].push_back(edge);
550 bestEdgeList.emplace_back(edge);
552 lastPoint = curPoint;
571 Eigen::Vector3f pcaToHitVec(hit3D->getPosition()[0] - pcaCenter(0),
572 hit3D->getPosition()[1] - pcaCenter(1),
573 hit3D->getPosition()[2] - pcaCenter(2));
576 pointList.emplace_back(
dcel2d::Point(pcaToHit(1), pcaToHit(2), hit3D));
580 pointList.sort([](
const auto&
left,
const auto&
right) {
582 std::numeric_limits<float>::epsilon()) ?
603 for (
auto&
vertex : vertexList) {
604 Eigen::Vector3f coords = rotationMatrixInv *
vertex.getCoords();
628 dcel2d::Point lastPoint = voronoiDiagram.getConvexHull().front();
633 for (
auto& curPoint : voronoiDiagram.getConvexHull()) {
634 if (curPoint == lastPoint)
continue;
639 float distBetweenPoints = (curPoint3D->getPosition()[0] - lastPoint3D->
getPosition()[0]) *
640 (curPoint3D->getPosition()[0] - lastPoint3D->
getPosition()[0]) +
641 (curPoint3D->getPosition()[1] - lastPoint3D->
getPosition()[1]) *
642 (curPoint3D->getPosition()[1] - lastPoint3D->
getPosition()[1]) +
643 (curPoint3D->getPosition()[2] - lastPoint3D->
getPosition()[2]) *
644 (curPoint3D->getPosition()[2] - lastPoint3D->
getPosition()[2]);
646 distBetweenPoints = std::sqrt(distBetweenPoints);
650 edgeMap[lastPoint3D].push_back(edge);
651 edgeMap[curPoint3D].push_back(edge);
652 bestEdgeList.emplace_back(edge);
654 lastPoint = curPoint;
657 std::cout <<
"****> vertexList containted " << vertexList.size() <<
" vertices" << std::endl;
663 const Eigen::Vector3f& u0,
664 const Eigen::Vector3f& P1,
665 const Eigen::Vector3f& u1,
666 Eigen::Vector3f& poca0,
667 Eigen::Vector3f& poca1)
const 670 Eigen::Vector3f w0 = P0 - P1;
676 float den(a * c - b * b);
678 float arcLen0 = (b *
e - c *
d) / den;
679 float arcLen1 = (a *
e - b *
d) / den;
681 poca0 = P0 + arcLen0 * u0;
682 poca1 = P1 + arcLen1 * u1;
684 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
void flipAxis(size_t axis)
const Eigen::Vector3f getPosition() const
std::tuple< float, float, const reco::ClusterHit3D * > Point
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.
constexpr auto abs(T v)
Returns the absolute value of the argument.
void buildVoronoiDiagram(reco::ClusterParameters &clusterParameters) const
reco::EdgeList & getBestEdgeList()
float closestApproach(const Eigen::Vector3f &, const Eigen::Vector3f &, const Eigen::Vector3f &, const Eigen::Vector3f &, Eigen::Vector3f &, Eigen::Vector3f &) const
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
reco::HitPairListPtr & getHitPairListPtr()
Cluster finding and building.
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::pair< Point, Point > MinMaxPoints
std::tuple< const reco::ClusterHit3D *, const reco::ClusterHit3D *, double > EdgeTuple
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)
const Eigen::Vector3f & getAvePosition() const
size_t m_minTinyClusterSize
Minimum size for a "tiny" cluster.
std::pair< MinMaxPoints, MinMaxPoints > MinMaxPointPair
std::list< const reco::ClusterHit3D * > HitPairListPtr
void UpdateParameters(const reco::ClusterHit2D *hit)
float getConvexHullArea() const
recover the area of the convex hull
This provides an art tool interface definition for 3D Cluster algorithms.
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.
ConvexHull class definiton.
This header file defines the interface to a principal components analysis designed to be used within ...
bool m_enableMonitoring
Data members to follow.
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
decltype(auto) get(T &&obj)
ADL-aware version of std::to_string.
PrincipalComponentsAlg m_pcaAlg
dcel2d::FaceList & getFaceList()
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
This provides an art tool interface definition for 3D Cluster algorithms.
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
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
ClusterPathFinder(const fhicl::ParameterSet &)
Constructor.
dcel2d::HalfEdgeList & getHalfEdgeList()
std::list< Vertex > VertexList
std::list< ClusterParameters > ClusterParametersList
const EigenVectors & getEigenVectors() const
dcel2d::VertexList & getVertexList()