11 #include "art_root_io/TFileDirectory.h" 113 const Eigen::Vector3f&,
114 const Eigen::Vector3f&,
115 const Eigen::Vector3f&,
117 Eigen::Vector3f&)
const;
119 using MinMaxPoints = std::pair<reco::ProjectedPoint,reco::ProjectedPoint>;
126 using KinkTuple = std::tuple<int, reco::ConvexHullKinkTuple, HitOrderTupleList, HitOrderTupleList>;
219 art::TFileDirectory
dir = histDir.mkdir(dirName.c_str());
223 fTopNum3DHits = dir.make<TH1F>(
"TopNum3DHits",
"Number 3D Hits", 200, 0., 200.);
224 fTopNumEdges = dir.make<TH1F>(
"TopNumEdges",
"Number Edges", 200, 0., 200.);
225 fTopEigen21Ratio = dir.make<TH1F>(
"TopEigen21Rat",
"Eigen 2/1 Ratio", 100, 0., 1.);
226 fTopEigen20Ratio = dir.make<TH1F>(
"TopEigen20Rat",
"Eigen 2/0 Ratio", 100, 0., 1.);
227 fTopEigen10Ratio = dir.make<TH1F>(
"TopEigen10Rat",
"Eigen 1/0 Ratio", 100, 0., 1.);
228 fTopPrimaryLength = dir.make<TH1F>(
"TopPrimaryLen",
"Primary Length", 200, 0., 200.);
229 fTopExtremeSep = dir.make<TH1F>(
"TopExtremeSep",
"Extreme Dist", 200, 0., 200.);
231 fTopConvexEdgeLen = dir.make<TH1F>(
"TopConvexEdge",
"CH Edge Len", 200, 0., 50.);
233 fSubNum3DHits = dir.make<TH1F>(
"SubNum3DHits",
"Number 3D Hits", 200, 0., 200.);
234 fSubNumEdges = dir.make<TH1F>(
"SubNumEdges",
"Number Edges", 200, 0., 200.);
235 fSubEigen21Ratio = dir.make<TH1F>(
"SubEigen21Rat",
"Eigen 2/1 Ratio", 100, 0., 1.);
236 fSubEigen20Ratio = dir.make<TH1F>(
"SubEigen20Rat",
"Eigen 2/0 Ratio", 100, 0., 1.);
237 fSubEigen10Ratio = dir.make<TH1F>(
"SubEigen10Rat",
"Eigen 1/0 Ratio", 100, 0., 1.);
238 fSubPrimaryLength = dir.make<TH1F>(
"SubPrimaryLen",
"Primary Length", 200, 0., 200.);
239 fSubCosToPrevPCA = dir.make<TH1F>(
"SubCosToPrev",
"Cos(theta)", 101, 0., 1.01);
240 fSubCosExtToPCA = dir.make<TH1F>(
"SubCosExtPCA",
"Cos(theta)", 102, -1.01, 1.01);
242 fSubConvexEdgeLen = dir.make<TH1F>(
"SubConvexEdge",
"CH Edge Len", 200, 0., 50.);
243 fSubMaxDefect = dir.make<TH1F>(
"SubMaxDefect",
"Max Defect", 100, 0., 50.);
244 fSubUsedDefect = dir.make<TH1F>(
"SubUsedDefect",
"Used Defect", 100, 0., 50.);
269 while(clusterParametersListItr != clusterParametersList.end())
288 reclusteredParameters.push_back(clusterParameters);
291 if (!reclusteredParameters.empty())
294 for (
auto&
cluster : reclusteredParameters)
311 std::vector<double> eigenValVec = {3. * std::sqrt(fullPCA.
getEigenValues()[0]),
314 double eigen2To1Ratio = eigenValVec[0] / eigenValVec[1];
315 double eigen1To0Ratio = eigenValVec[1] / eigenValVec[2];
316 double eigen2To0Ratio = eigenValVec[2] / eigenValVec[2];
317 int num3DHits =
cluster.getHitPairListPtr().size();
318 int numEdges =
cluster.getConvexHull().getConvexHullEdgeList().size();
334 clusterParametersListItr++;
339 theClockBuildClusters.
stop();
381 Eigen::Vector3f edgeVec(secondEdgeHit->getPosition()[0] - firstEdgeHit->
getPosition()[0],
382 secondEdgeHit->getPosition()[1] - firstEdgeHit->
getPosition()[1],
383 secondEdgeHit->getPosition()[2] - firstEdgeHit->
getPosition()[2]);
417 std::vector<double> eigenValVec = {3. * std::sqrt(fullPCA.
getEigenValues()[0]),
441 std::vector<double> eigenValVec = {3. * std::sqrt(fullPCA.
getEigenValues()[0]),
455 for(
auto& clusterParams : tempClusterParametersList)
457 size_t curOutputClusterListSize = outputClusterList.size();
459 positionItr =
subDivideCluster(clusterParams, fullPCA, positionItr, outputClusterList, level+4);
463 if (curOutputClusterListSize < outputClusterList.size())
continue;
469 std::set<const reco::ClusterHit2D*> hitSet;
472 for(
const auto& hit3D : clusterParams.getHitPairListPtr())
474 for(
const auto& hit2D : hit3D->getHits())
476 if (hit2D) hitSet.insert(hit2D);
481 for(
const auto& hit2D : hitSet)
484 clusterParams.UpdateParameters(hit2D);
487 positionItr = outputClusterList.insert(positionItr,clusterParams);
492 std::vector<double> eigenValVec = {3. * std::sqrt(fullPCA.
getEigenValues()[0]),
500 Eigen::Vector3f lastPrimaryVec(newFullPCA.getEigenVectors().row(2));
502 int num3DHits = clusterParams.getHitPairListPtr().size();
503 int numEdges = clusterParams.getConvexHull().getConvexHullEdgeList().size();
504 float cosToLast = newPrimaryVec.dot(lastPrimaryVec);
505 double eigen2To1Ratio = eigenValVec[0] / eigenValVec[1];
506 double eigen1To0Ratio = eigenValVec[1] / eigenValVec[2];
507 double eigen2To0Ratio = eigenValVec[0] / eigenValVec[2];
538 hitPairListPtr.resize(
std::distance(firstHitItr,lastHitItr));
541 std::copy(firstHitItr,lastHitItr,hitPairListPtr.begin());
544 bool keepThisCluster(
false);
555 std::vector<double> eigenValVec = {3. * std::sqrt(newFullPCA.
getEigenValues()[0]),
558 double cosNewToLast =
std::abs(primaryPCA.dot(newPrimaryVec));
559 double eigen2To1Ratio = eigenValVec[0] / eigenValVec[1];
560 double eigen1To0Ratio = eigenValVec[1] / eigenValVec[2];
566 keepThisCluster =
true;
570 return keepThisCluster;
583 for(
const auto& tupleVal : orderedList) hitPairListPtr.emplace_back(std::get<2>(std::get<2>(tupleVal)));
586 bool keepThisCluster(
false);
597 std::vector<double> eigenValVec = {3. * std::sqrt(newFullPCA.
getEigenValues()[0]),
600 double cosNewToLast =
std::abs(primaryPCA.dot(newPrimaryVec));
601 double eigen2To1Ratio = eigenValVec[0] / eigenValVec[1];
602 double eigen1To0Ratio = eigenValVec[1] / eigenValVec[2];
606 if (candCluster.
getBestEdgeList().size() > 4 && cosNewToLast > 0.25 && eigen2To1Ratio > 0.01 && eigen2To1Ratio < 0.99 && eigen1To0Ratio < 0.5)
608 keepThisCluster =
true;
612 return keepThisCluster;
624 bool keepThisCluster(
false);
633 if (primaryPCA.dot(newPrimaryVec) < 0.)
635 for(
size_t vecIdx = 0; vecIdx < 3; vecIdx++) newFullPCA.
flipAxis(vecIdx);
644 keepThisCluster =
true;
647 return keepThisCluster;
653 using HitKinkTuple = std::tuple<int, reco::HitPairListPtr::iterator>;
654 using HitKinkTupleVec = std::vector<HitKinkTuple>;
660 HitKinkTupleVec kinkTupleVec;
665 for(
auto& kink : kinkPointList)
671 if (kinkItr == hitList.end())
continue;
675 int minNumHits =
std::min(numStartToKink,numKinkToEnd);
681 if (!kinkTupleVec.empty())
683 std::sort(kinkTupleVec.begin(),kinkTupleVec.end(),[](
const auto&
left,
const auto&
right){
return std::get<0>(
left) > std::get<0>(
right);});
694 Eigen::Vector3f fullPrimaryVec(fullPCA.getEigenVectors().row(2));
712 if (outputClusterList.size() != 2) outputClusterList.clear();
715 return !outputClusterList.empty();
727 for(
auto& kink : kinkPointList)
732 KinkTuple& kinkTuple = kinkTupleVec.back();
734 std::get<1>(kinkTuple) = kink;
737 Eigen::Vector2f firstEdge = -std::get<1>(kink);
745 Eigen::Vector2f secondEdge = std::get<2>(kink);
750 std::get<0>(kinkTuple) =
std::min(firstList.size(),secondList.size());
754 if (firstList.size() + secondList.size() > pointList.size())
759 std::get<0>(kinkTuple) =
std::min(firstList.size(),secondList.size());
766 if (!kinkTupleVec.empty())
769 std::sort(kinkTupleVec.begin(),kinkTupleVec.end(),[](
const auto&
left,
const auto&
right){
return std::get<0>(
left) > std::get<0>(
right);});
772 KinkTuple& kinkTuple = kinkTupleVec.front();
780 Eigen::Vector3f fullPrimaryVec(fullPCA.getEigenVectors().row(2));
798 if (outputClusterList.size() != 2) outputClusterList.clear();
801 return !outputClusterList.empty();
806 const Eigen::Vector2f& edge,
810 Eigen::Vector2f kinkPos(std::get<0>(point),std::get<1>(point));
813 for (
const auto&
hit : hitList)
817 Eigen::Vector2f hitPos(std::get<0>(
hit),std::get<1>(
hit));
820 Eigen::Vector2f hitToKinkVec = hitPos - kinkPos;
823 float arcLenToPoca = hitToKinkVec.dot(edge);
826 if (arcLenToPoca < 0.)
continue;
829 Eigen::Vector2f pocaPos = kinkPos + arcLenToPoca * edge;
832 Eigen::Vector2f pocaPosToHitPos = hitPos - pocaPos;
833 float pocaToAxis = pocaPosToHitPos.norm();
835 std::cout <<
"-- arcLenToPoca: " << arcLenToPoca <<
", doca: " << pocaToAxis <<
std::endl;
837 orderedList.emplace_back(arcLenToPoca,pocaToAxis,
hit);
841 orderedList.sort([](
const auto&
left,
const auto&
right){
return std::get<0>(
left) < std::get<0>(
right);});
851 while(shortItr != shortList.end())
857 HitOrderTupleList::iterator longItr = std::find_if(longList.begin(),longList.end(),[&hit3D](
const auto& elem){
return hit3D == std::get<2>(std::get<2>(elem));});
859 if (longItr != longList.end())
861 if (std::get<1>(*longItr) < std::get<1>(*shortItr))
863 shortItr = shortList.erase(shortItr);
867 longItr = longList.erase(longItr);
881 using DistEdgeTuple = std::tuple<float, const reco::EdgeTuple*>;
882 using DistEdgeTupleVec = std::vector<DistEdgeTuple>;
884 DistEdgeTupleVec distEdgeTupleVec;
890 Eigen::Vector3f edgeVec(secondEdgeHit->getPosition()[0] - firstEdgeHit->
getPosition()[0],
891 secondEdgeHit->getPosition()[1] - firstEdgeHit->
getPosition()[1],
892 secondEdgeHit->getPosition()[2] - firstEdgeHit->
getPosition()[2]);
893 double edgeLen = edgeVec.norm();
909 float hitProjection = hitToEdgeVec.dot(edgeVec);
912 if (hitProjection > 0. && hitProjection < edgeLen)
914 Eigen::Vector3f distToHitVec = hitToEdgeVec - hitProjection * edgeVec;
915 float distToHit = distToHitVec.norm();
917 distEdgeTupleVec.emplace_back(distToHit,&edge);
921 std::sort(distEdgeTupleVec.begin(),distEdgeTupleVec.end(),[](
const auto&
left,
const auto&
right){
return std::get<0>(
left) > std::get<0>(
right);});
924 Eigen::Vector3f fullPrimaryVec(fullPCA.getEigenVectors().row(2));
934 hitList.sort([](
const auto&
left,
const auto&
right){
return left->getArclenToPoca() <
right->getArclenToPoca();});
937 float usedDefectDist(0.);
939 for(
const auto& distEdgeTuple : distEdgeTupleVec)
944 usedDefectDist = std::get<0>(distEdgeTuple);
966 fSubMaxDefect->Fill(std::get<0>(distEdgeTupleVec.front()), 1.);
974 outputClusterList.clear();
977 return !outputClusterList.empty();
983 Eigen::Vector3f fullPrimaryVec(fullPCA.getEigenVectors().row(2));
993 hitList.sort([](
const auto&
left,
const auto&
right){
return left->getArclenToPoca() <
right->getArclenToPoca();});
997 std::advance(vertexItr, hitList.size()/2);
1012 if (outputClusterList.size() != 2) outputClusterList.clear();
1014 return !outputClusterList.empty();
1031 hitList.sort([](
const auto&
left,
const auto&
right){
return left->getArclenToPoca() <
right->getArclenToPoca();});
1035 float biggestGap = 0.;
1041 float currentGap =
std::abs((*hitItr)->getArclenToPoca() - (*lastHitItr)->getArclenToPoca());
1043 if (currentGap > biggestGap)
1045 bigGapHitItr = hitItr;
1046 biggestGap = currentGap;
1049 lastHitItr = hitItr;
1060 Eigen::Vector3f fullPrimaryVec(fullPCA.getEigenVectors().row(2));
1071 if (outputClusterList.size() != 2) outputClusterList.clear();
1074 return !outputClusterList.empty();
1098 Eigen::Vector3f pcaToHitVec(hit3D->getPosition()[0] - pcaCenter(0),
1099 hit3D->getPosition()[1] - pcaCenter(1),
1100 hit3D->getPosition()[2] - pcaCenter(2));
1103 pointList.emplace_back(pcaToHit(1),pcaToHit(2),hit3D);
1107 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);});
1110 std::vector<ConvexHull> convexHullVec;
1111 std::vector<reco::ProjectedPointList> rejectedListVec;
1112 bool increaseDepth(pointList.size() > 3);
1115 while(increaseDepth)
1121 const ConvexHull& convexHull = convexHullVec.back();
1125 increaseDepth =
false;
1129 if (convexHullVec.size() < 2 || convexHull.
getConvexHullArea() < 0.8 * lastArea)
1131 for(
auto& point : convexHullPoints)
1133 pointList.remove(point);
1134 rejectedList.emplace_back(point);
1143 while(!convexHullVec.empty() && convexHullVec.back().getConvexHullArea() < 0.5)
1145 convexHullVec.pop_back();
1146 rejectedListVec.pop_back();
1150 if (!convexHullVec.empty())
1152 size_t nRejectedTotal(0);
1155 for(
const auto& rejectedList : rejectedListVec)
1157 nRejectedTotal += rejectedList.size();
1159 for(
const auto& rejectedPoint : rejectedList)
1161 if (convexHullVec.back().findNearestDistance(rejectedPoint) > 0.5)
1162 hitPairListPtr.remove(std::get<2>(rejectedPoint));
1173 for(
auto& curPoint : convexHullVec.back().getConvexHull())
1175 if (curPoint == lastPoint)
continue;
1180 float distBetweenPoints = (curPoint3D->getPosition()[0] - lastPoint3D->
getPosition()[0]) * (curPoint3D->getPosition()[0] - lastPoint3D->
getPosition()[0])
1181 + (curPoint3D->getPosition()[1] - lastPoint3D->
getPosition()[1]) * (curPoint3D->getPosition()[1] - lastPoint3D->
getPosition()[1])
1182 + (curPoint3D->getPosition()[2] - lastPoint3D->
getPosition()[2]) * (curPoint3D->getPosition()[2] - lastPoint3D->
getPosition()[2]);
1184 distBetweenPoints = std::sqrt(distBetweenPoints);
1188 convexHullPointList.push_back(curPoint);
1189 edgeMap[lastPoint3D].push_back(edge);
1190 edgeMap[curPoint3D].push_back(edge);
1191 edgeList.emplace_back(edge);
1193 lastPoint = curPoint;
1200 for(
const auto& point : extremePoints) extremePointList.push_back(point);
1206 for(
const auto& kink : kinkPoints) kinkPointList.push_back(kink);
1216 if (convexHullPoints.size() > 2)
1221 std::advance(pointItr, convexHullPoints.size() - 2);
1226 pointItr = convexHullPoints.begin();
1229 Eigen::Vector2f lastEdge(std::get<0>(curPoint) - std::get<0>(lastPoint), std::get<1>(curPoint) - std::get<1>(lastPoint));
1231 lastEdge.normalize();
1233 while(pointItr != convexHullPoints.end())
1237 Eigen::Vector2f nextEdge(std::get<0>(nextPoint) - std::get<0>(curPoint), std::get<1>(nextPoint) - std::get<1>(curPoint));
1238 float nextEdgeLen = nextEdge.norm();
1240 nextEdge.normalize();
1242 float cosLastNextEdge = lastEdge.dot(nextEdge);
1257 curPoint = nextPoint;
1265 const Eigen::Vector3f& u0,
1266 const Eigen::Vector3f& P1,
1267 const Eigen::Vector3f& u1,
1268 Eigen::Vector3f& poca0,
1269 Eigen::Vector3f& poca1)
const 1272 Eigen::Vector3f w0 = P0 - P1;
1274 float b(u0.dot(u1));
1276 float d(u0.dot(w0));
1277 float e(u1.dot(w0));
1278 float den(a * c -
b *
b);
1280 float arcLen0 = (b *
e - c *
d) / den;
1281 float arcLen1 = (a *
e - b *
d) / den;
1283 poca0 = P0 + arcLen0 * u0;
1284 poca1 = P1 + arcLen1 * u1;
1286 return (poca0 - poca1).norm();
1291 float largestDistance(0.);
1298 while(firstEdgeItr != convexHull.end())
1306 while(++nextEdgeItr != convexHull.end())
1312 return largestDistance;
size_t fMinTinyClusterSize
Minimum size for a "tiny" cluster.
float fConvexHullMinSep
Min hit separation to conisder in convex hull.
void PCAAnalysis_calc3DDocas(const reco::HitPairListPtr &hitPairVector, const reco::PrincipalComponents &pca) const
~ConvexHullPathFinder()
Destructor.
std::tuple< int, reco::ConvexHullKinkTuple, HitOrderTupleList, HitOrderTupleList > KinkTuple
void PCAAnalysis_3D(const reco::HitPairListPtr &hitPairList, reco::PrincipalComponents &pca, bool skeletonOnly=false) const
void cluster(In first, In last, Out result, Pred *pred)
float getTimeToExecute() const override
If monitoring, recover the time to execute a particular function.
void flipAxis(size_t axis)
bool breakClusterByMaxDefect(reco::ClusterParameters &, reco::ClusterParametersList &, int level) const
const Eigen::Vector3f getPosition() const
std::tuple< float, float, reco::ProjectedPoint > HitOrderTuple
std::list< ProjectedPoint > ProjectedPointList
reco::PrincipalComponents & getSkeletonPCA()
std::list< Point > PointList
The list of the projected points.
reco::ClusterParametersList::iterator subDivideCluster(reco::ClusterParameters &cluster, reco::PrincipalComponents &lastPCA, reco::ClusterParametersList::iterator positionItr, reco::ClusterParametersList &outputClusterList, int level=0) const
Use PCA to try to find path in cluster.
reco::EdgeList & getBestEdgeList()
reco::HitPairListPtr & getHitPairListPtr()
bool fFillHistograms
Histogram definitions.
Cluster finding and building.
void configure(fhicl::ParameterSet const &pset) override
IClusterModAlg interface class definiton.
PrincipalComponentsAlg fPCAAlg
ClusterParametersList & daughterList()
Implements a ConvexHull for use in clustering.
std::list< EdgeTuple > EdgeList
const EigenValues & getEigenValues() const
void fillConvexHullHists(reco::ClusterParameters &, bool) const
reco::PrincipalComponents & getFullPCA()
reco::Hit3DToEdgeMap & getConvexHullEdgeMap()
reco::ProjectedPointList & getConvexHullExtremePoints()
reco::ConvexHullKinkTupleList & getConvexHullKinkPoints()
Define a container for working with the convex hull.
T get(std::string const &key) const
const Eigen::Vector3f & getAvePosition() const
void pruneHitOrderTupleLists(HitOrderTupleList &, HitOrderTupleList &) const
ConvexHullPathFinder(const fhicl::ParameterSet &)
Constructor.
std::list< ConvexHullKinkTuple > ConvexHullKinkTupleList
std::tuple< const reco::ClusterHit3D *, const reco::ClusterHit3D *, double > EdgeTuple
std::list< const reco::ClusterHit3D * > HitPairListPtr
float getConvexHullArea() const
recover the area of the convex hull
This provides an art tool interface definition for 3D Cluster algorithms.
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
static int max(int a, int b)
const PointList & getConvexHull() const
recover the list of convex hull vertices
Detector simulation of raw signals on wires.
ConvexHull class definiton.
void buildConvexHull(reco::ClusterParameters &clusterParameters, int level=0) const
std::vector< KinkTuple > KinkTupleVec
std::unique_ptr< lar_cluster3d::IClusterAlg > fClusterAlg
Tools.
bool breakClusterByKinksTrial(reco::ClusterParameters &, reco::ClusterParametersList &, int level) const
bool makeCandidateCluster(Eigen::Vector3f &, reco::ClusterParameters &, reco::HitPairListPtr::iterator, reco::HitPairListPtr::iterator, int) const
reco::ConvexHull & getConvexHull()
void initializeHistograms(art::TFileDirectory &) override
Interface for initializing histograms if they are desired Note that the idea is to put hisgtograms in...
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
bool breakClusterByKinks(reco::ClusterParameters &, reco::ClusterParametersList &, int level) const
float fMinEigen0To1Ratio
Minimum ratio of eigen 0 to 1 to continue breaking.
float closestApproach(const Eigen::Vector3f &, const Eigen::Vector3f &, const Eigen::Vector3f &, const Eigen::Vector3f &, Eigen::Vector3f &, Eigen::Vector3f &) const
void orderHitsAlongEdge(const reco::ProjectedPointList &, const reco::ProjectedPoint &, const Eigen::Vector2f &, HitOrderTupleList &) const
float fConvexHullKinkAngle
Angle to declare a kink in convex hull calc.
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
This provides an art tool interface definition for 3D Cluster algorithms.
bool breakClusterAtBigGap(reco::ClusterParameters &, reco::ClusterParametersList &, int level) const
bool breakClusterInHalf(reco::ClusterParameters &, reco::ClusterParametersList &, int level) const
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
double accumulated_real_time() const
auto const & get(AssnsNode< L, R, D > const &r)
reco::ProjectedPointList & getConvexHullPointList()
void ModifyClusters(reco::ClusterParametersList &) const override
Scan an input collection of clusters and modify those according to the specific implementing algorith...
reco::ProjectedPointList & getProjectedPointList()
std::pair< MinMaxPoints, MinMaxPoints > MinMaxPointPair
reco::EdgeList & getConvexHullEdgeList()
bool fEnableMonitoring
FHICL parameters.
float findConvexHullEndPoints(const reco::EdgeList &, const reco::ClusterHit3D *, const reco::ClusterHit3D *) const
std::tuple< float, float, const reco::ClusterHit3D * > ProjectedPoint
Projected coordinates and pointer to hit.
std::list< HitOrderTuple > HitOrderTupleList
float fMinGapSize
Minimum gap size to break at gaps.
std::list< ClusterParameters > ClusterParametersList
const EigenVectors & getEigenVectors() const
std::pair< reco::ProjectedPoint, reco::ProjectedPoint > MinMaxPoints
QTextStream & endl(QTextStream &s)
bool completeCandidateCluster(Eigen::Vector3f &, reco::ClusterParameters &, int) const