11 #include "art_root_io/TFileDirectory.h" 12 #include "art_root_io/TFileService.h" 13 #include "cetlib/cpu_timer.h" 77 const Eigen::Vector3f&,
78 const Eigen::Vector3f&,
79 const Eigen::Vector3f&,
82 Eigen::Vector3f&)
const;
85 const Eigen::Vector3f&,
89 const Eigen::Vector3f&,
163 art::TFileDirectory
dir = tfs->mkdir(
"MergeClusters");
168 std::vector<float> maxValsVec = {20., 50., 250.};
170 for (
size_t idx : {0, 1, 2}) {
172 dir.make<TH1F>(Form(
"FEigen1st%1zu", idx),
"Eigen Val", 200, 0., maxValsVec[idx]);
174 dir.make<TH1F>(Form(
"FEigen2nd%1zu", idx),
"Eigen Val", 200, 0., maxValsVec[idx]);
177 fNumMergedClusters = dir.make<TH1F>(
"NumMergedClus",
"Number Merged", 200, 0., 1000.);
180 dir.make<TH1F>(
"1stTo2ndPosLen",
"Distance between Clusters", 250, 0., 1000.);
182 fRMaxFirstHist = dir.make<TH1F>(
"rMaxFirst",
"Radius of First Cluster", 200, 0., 100.);
183 fCosMaxFirstHist = dir.make<TH1F>(
"CosMaxFirst",
"Cos Angle First Cyl/Axis", 200, 0., 1.);
184 fCosFirstAxisHist = dir.make<TH1F>(
"CosFirstAxis",
"Cos Angle First Next/Axis", 200, 0., 1.);
186 dir.make<TH1F>(
"1stTo2ndProjEigen",
"Projected Distance First", 200, 0., 200.);
188 fRMaxNextHist = dir.make<TH1F>(
"rMaxNext",
"Radius of Next Cluster", 200, 0., 100.);
189 fCosMaxNextHist = dir.make<TH1F>(
"CosMaxNext",
"Cos Angle Next Cyl/Axis", 200, 0., 1.);
190 fCosNextAxisHist = dir.make<TH1F>(
"CosNextAxis",
"Cos Angle Next Next/Axis", 200, 0., 1.);
192 dir.make<TH1F>(
"2ndTo1stProjEigen",
"Projected Distance Next", 200, 0., 200.);
194 fGapBetweenClusHist = dir.make<TH1F>(
"ClusterGap",
"Gap Between Clusters", 400, -200., 200.);
195 fGapRatToLenHist = dir.make<TH1F>(
"GapRatToLen",
"Ratio Gap to Distance", 100, -8., 2.);
197 dir.make<TH1F>(
"ProjEndPointLen",
"Projected End Point Len", 200, -100., 100.);
199 dir.make<TH1F>(
"ProjEndPointRat",
"Projected End Point Ratio", 100, 0., 1.);
201 fAxesDocaHist = dir.make<TH1F>(
"AxesDocaHist",
"DOCA", 200, 0., 25.);
202 f1stDocaArcLRatHist = dir.make<TH1F>(
"ALenPOCA1Hist",
"Arc Len to POCA 1", 400, -50., 50.);
203 f2ndDocaArcLRatHist = dir.make<TH1F>(
"ALenPOCA2Hist",
"Arc Len to POCA 2", 400, -50., 50.);
206 dir.make<TH1F>(
"1stTo2ndPosLenRat",
"Ratio clus dist to eigen", 200., 0., 20.);
207 fGapRatHist = dir.make<TH1F>(
"GapRat",
"Ratio Gap to Next Eigen", 400, -20., 20.);
228 cet::cpu_timer theClockBuildClusters;
234 clusterParametersList.sort([](
auto&
left,
auto&
right) {
235 return left.getFullPCA().getEigenValues()[2] >
right.getFullPCA().getEigenValues()[2];
241 size_t lastClusterListCount = clusterParametersList.size() + 1;
244 int numMergedClusters(0);
245 int nOutsideLoops(0);
247 while (clusterParametersList.size() != lastClusterListCount) {
249 lastClusterListCount = clusterParametersList.size();
255 while (firstClusterItr != clusterParametersList.end()) {
263 Eigen::Vector3f firstEigenVals(
270 for (
size_t idx = 0; idx < 3; idx++)
277 while (++nextClusterItr != clusterParametersList.end()) {
285 nextClusterItr = clusterParametersList.erase(nextClusterItr);
292 while (biggestItr-- != clusterParametersList.begin()) {
295 if ((*biggestItr).getFullPCA().getEigenValues()[2] >
296 (*firstClusterItr).getFullPCA().getEigenValues()[2]) {
299 if (++biggestItr != firstClusterItr)
300 clusterParametersList.splice(
301 biggestItr, clusterParametersList, firstClusterItr);
308 nextClusterItr = firstClusterItr;
321 std::cout <<
"==> # merged: " << numMergedClusters <<
", in " << nOutsideLoops
322 <<
" outside loops " << std::endl;
327 theClockBuildClusters.stop();
332 mf::LogDebug(
"Cluster3D") <<
">>>>> Merge clusters done, found " << clusterParametersList.size()
333 <<
" clusters" << std::endl;
342 bool consistent(
false);
357 Eigen::Vector3f firstPosToNextPosVec = nextCenter - firstCenter;
358 Eigen::Vector3f firstPosToNextPosUnit = firstPosToNextPosVec.normalized();
359 float firstPosToNextPosLen = firstPosToNextPosVec.norm();
367 float arcLenToNextDoca = firstPosToNextPosVec.dot(firstAxis2);
371 if (arcLenToNextDoca < 0.) {
372 firstAxis0 = -firstAxis0;
373 firstAxis1 = -firstAxis1;
374 firstAxis2 = -firstAxis2;
375 arcLenToNextDoca = -arcLenToNextDoca;
379 Eigen::Vector3f firstEigenVals(
386 Eigen::Vector2f firstProj01Unit =
387 Eigen::Vector2f(firstPosToNextPosUnit.dot(firstAxis0), firstPosToNextPosUnit.dot(firstAxis1))
389 float firstEigen0Proj = firstEigenVals[0] * firstProj01Unit[0];
390 float firstEigen1Proj = firstEigenVals[1] * firstProj01Unit[1];
392 std::sqrt(firstEigen0Proj * firstEigen0Proj + firstEigen1Proj * firstEigen1Proj);
394 firstEigenVals[2] / std::sqrt(firstEigenVals[2] * firstEigenVals[2] + rMaxFirst * rMaxFirst);
395 float cosFirstAxis = firstAxis2.dot(firstPosToNextPosUnit);
398 float firstEigenVal2 = firstEigenVals[2];
399 float firstToNextProjEigen = firstEigenVal2;
402 if (cosFirstAxis < cosMaxFirst) {
404 float sinFirstAxis = std::sqrt(1. - cosFirstAxis * cosFirstAxis);
407 firstToNextProjEigen = rMaxFirst / sinFirstAxis;
410 firstToNextProjEigen /= cosFirstAxis;
413 float firstPosToNextPosScaleFactor = 8.;
425 if (firstPosToNextPosLen < firstPosToNextPosScaleFactor * firstToNextProjEigen) {
432 float cosFirstNextAxis = firstAxis2.dot(nextAxis2);
436 if (cosFirstNextAxis < 0.) {
437 nextAxis0 = -nextAxis0;
438 nextAxis1 = -nextAxis1;
439 nextAxis2 = -nextAxis2;
440 cosFirstNextAxis = -cosFirstNextAxis;
444 Eigen::Vector3f nextEigenVals(
450 Eigen::Vector2f nextProj01Unit =
451 Eigen::Vector2f(firstPosToNextPosUnit.dot(nextAxis0), firstPosToNextPosUnit.dot(nextAxis1))
453 float nextEigen0Proj = nextEigenVals[0] * nextProj01Unit[0];
454 float nextEigen1Proj = nextEigenVals[1] * nextProj01Unit[1];
455 float rMaxNext = std::sqrt(nextEigen0Proj * nextEigen0Proj + nextEigen1Proj * nextEigen1Proj);
457 nextEigenVals[2] / std::sqrt(nextEigenVals[2] * nextEigenVals[2] + rMaxNext * rMaxNext);
458 float cosNextAxis =
std::abs(nextAxis2.dot(firstPosToNextPosUnit));
461 float nextToFirstProjEigen = nextEigenVals[2];
464 if (cosNextAxis < cosMaxNext) {
466 float sinNextAxis = std::sqrt(1. - cosNextAxis * cosNextAxis);
469 nextToFirstProjEigen = rMaxNext / sinNextAxis;
472 nextToFirstProjEigen /= cosNextAxis;
476 float nextToFirstScaleFactor = 8. * cosFirstNextAxis;
480 float gapFirstToNext = firstPosToNextPosLen - firstToNextProjEigen - nextToFirstProjEigen;
483 Eigen::Vector3f firstEndPoint = firstCenter + firstEigenVals[2] * firstAxis2;
484 Eigen::Vector3f nextTailPoint = nextCenter - nextEigenVals[2] * nextAxis2;
485 Eigen::Vector3f endToTailVec = nextTailPoint - firstEndPoint;
488 float endPointProjection = endToTailVec.dot(firstPosToNextPosUnit);
489 float endToTailLen = endToTailVec.norm();
493 for (
size_t idx = 0; idx < 3; idx++)
507 if (gapFirstToNext < nextToFirstScaleFactor * nextToFirstProjEigen ||
508 (
std::abs(endPointProjection) < nextToFirstProjEigen &&
509 endToTailLen < nextEigenVals[2])) {
512 Eigen::Vector3f firstPoca;
513 Eigen::Vector3f nextPoca;
514 Eigen::Vector3f firstToNextUnit;
518 firstCenter, firstAxis2, nextCenter, nextAxis2, firstPoca, nextPoca, firstToNextUnit);
521 Eigen::Vector3f firstPOCAProjUnit = Eigen::Vector3f(firstToNextUnit.dot(firstAxis0),
522 firstToNextUnit.dot(firstAxis1),
523 firstToNextUnit.dot(firstAxis1))
525 float firstPOCAVecProjEigen =
526 std::sqrt(std::pow(firstEigenVals[0] * firstPOCAProjUnit[0], 2) +
527 std::pow(firstEigenVals[1] * firstPOCAProjUnit[1], 2) +
528 std::pow(firstEigenVals[2] * firstPOCAProjUnit[2], 2));
531 Eigen::Vector3f nextPOCAProjUnit = Eigen::Vector3f(firstToNextUnit.dot(firstAxis0),
532 firstToNextUnit.dot(firstAxis1),
533 firstToNextUnit.dot(firstAxis1))
535 float nextPOCAVecProjEigen = std::sqrt(std::pow(nextEigenVals[0] * nextPOCAProjUnit[0], 2) +
536 std::pow(nextEigenVals[1] * nextPOCAProjUnit[1], 2) +
537 std::pow(nextEigenVals[2] * nextPOCAProjUnit[2], 2));
541 float arcLenToFirstPoca = (firstPoca - firstCenter).
dot(firstAxis2);
542 float arcLenToNextPoca = (nextPoca - nextCenter).
dot(nextAxis2);
550 float rMaxScaleFactor = 1.2;
552 if (lineDoca < rMaxScaleFactor * (firstPOCAVecProjEigen + nextPOCAVecProjEigen)) {
576 hitPairListPtr.push_back(
hit);
578 for (
const auto* hit2D :
hit->getHits())
591 for (
const auto& pair : nextEdgeMap)
592 firstEdgeMap[pair.first] = pair.second;
607 const Eigen::Vector3f& u0,
608 const Eigen::Vector3f& P1,
609 const Eigen::Vector3f& u1,
610 Eigen::Vector3f& poca0,
611 Eigen::Vector3f& poca1,
612 Eigen::Vector3f& firstNextUnit)
const 615 Eigen::Vector3f w0 = P0 - P1;
621 float den(a * c - b * b);
624 if (
std::abs(den) > 10. * std::numeric_limits<float>::epsilon()) {
625 float arcLen0 = (b *
e - c *
d) / den;
626 float arcLen1 = (a *
e - b *
d) / den;
628 poca0 = P0 + arcLen0 * u0;
629 poca1 = P1 + arcLen1 * u1;
633 float arcLenToNextPoint = w0.dot(u0);
635 poca0 = P0 + arcLenToNextPoint * u0;
639 firstNextUnit = poca1 - poca0;
641 float docaDist = firstNextUnit.norm();
643 firstNextUnit = firstNextUnit.normalized();
649 const Eigen::Vector3f& refPoint,
650 const Eigen::Vector3f& refVector,
654 float closest(std::numeric_limits<float>::max());
656 for (
const auto& hit3D : hitList) {
657 Eigen::Vector3f refToHitVec = hit3D->getPosition() - refPoint;
658 float arcLenToHit = refToHitVec.dot(refVector);
660 if (arcLenToHit < closest) {
661 nearestHit3D = hit3D;
662 closest = arcLenToHit;
670 const Eigen::Vector3f& refPoint,
671 const Eigen::Vector3f& refVector,
675 float furthest(-std::numeric_limits<float>::max());
677 for (
const auto& hit3D : hitList) {
678 Eigen::Vector3f refToHitVec = hit3D->getPosition() - refPoint;
679 float arcLenToHit = refToHitVec.dot(refVector);
681 if (arcLenToHit > furthest) {
682 nearestHit3D = hit3D;
683 furthest = arcLenToHit;
void ModifyClusters(reco::ClusterParametersList &) const override
Scan an input collection of clusters and modify those according to the specific implementing algorith...
std::vector< TH1F * > fNextEigenValueHists
Next Cluster eigen value.
std::vector< TH1F * > fFirstEigenValueHists
First Cluster eigen value.
void configure(fhicl::ParameterSet const &pset) override
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 closestApproach(const Eigen::Vector3f &, const Eigen::Vector3f &, const Eigen::Vector3f &, const Eigen::Vector3f &, Eigen::Vector3f &, Eigen::Vector3f &, Eigen::Vector3f &) const
~ClusterMergeAlg()
Destructor.
TH1F * fCosMaxFirstHist
Cos angle beteeen cylinder axis and edge.
void initializeHistograms(art::TFileDirectory &) override
Interface for initializing histograms if they are desired Note that the idea is to put hisgtograms in...
PrincipalComponentsAlg fPCAAlg
TNtupleSim Fill(f1, f2, f3, f4)
reco::PrincipalComponents & getSkeletonPCA()
float fTimeToProcess
Keep track of how long it took to run this algorithm.
constexpr auto abs(T v)
Returns the absolute value of the argument.
TH1F * f2ndDocaArcLRatHist
arc length to POCA for DOCA second cluster
bool fOutputHistograms
Take the time to create and fill some histograms for diagnostics.
reco::Hit3DToEdgeMap & getHit3DToEdgeMap()
reco::HitPairListPtr & getHitPairListPtr()
TH1F * fRMaxFirstHist
radius of "cylinder" first cluster
TH1F * fGapRatHist
Ratio of gap and next proj eigen.
IClusterModAlg interface class definiton.
TH1F * fCosFirstAxisHist
Cos angle between vector between centers and first axis.
TH1F * fProjEndPointRatHist
Ratio of projection to vector length.
float fMinEigenToProcess
Don't look anymore at clusters below this size.
const EigenValues & getEigenValues() const
bool mergeClusters(reco::ClusterParameters &, reco::ClusterParameters &) const
float getTimeToExecute() const override
If monitoring, recover the time to execute a particular function.
reco::PrincipalComponents & getFullPCA()
TH1F * fCosNextAxisHist
Cos angle between vector between centers and next axis.
const reco::ClusterHit3D * findFurthestHit3D(const Eigen::Vector3f &, const Eigen::Vector3f &, const reco::HitPairListPtr &) const
TH1F * f2ndTo1stProjEigenHist
arc length along vector between centers from next center to cylinder
T get(std::string const &key) const
TH1F * f1stTo2ndPosLenRatHist
Ratio of distance between centers and first proj eigen.
const Eigen::Vector3f & getAvePosition() const
ClusterMergeAlg(const fhicl::ParameterSet &)
Constructor.
TH1F * fRMaxNextHist
radius of "cylinder" next cluster
std::list< const reco::ClusterHit3D * > HitPairListPtr
void UpdateParameters(const reco::ClusterHit2D *hit)
bool fEnableMonitoring
Data members to follow.
TH1F * f1stTo2ndProjEigenHist
arc length along vector between centers from first center to cylinder
const reco::ClusterHit3D * findClosestHit3D(const Eigen::Vector3f &, const Eigen::Vector3f &, const reco::HitPairListPtr &) const
constexpr auto dot(Vector const &a, OtherVector const &b)
Return cross product of two vectors.
TH1F * fNumMergedClusters
How many clusters were merged?
Detector simulation of raw signals on wires.
TH1F * fProjEndPointLenHist
Projection of vector between the endpoints.
This header file defines the interface to a principal components analysis designed to be used within ...
bool linearClusters(reco::ClusterParameters &, reco::ClusterParameters &) const
float fMinTransEigenVal
Set a mininum allowed value for the transverse eigen values.
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.
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
This provides an art tool interface definition for 3D Cluster algorithms.
TH1F * fAxesDocaHist
Closest distance between two primary axes.
TH1F * fGapRatToLenHist
Ratio of gap to distance between centers.
TH1F * fCosMaxNextHist
Cos angle beteeen cylinder axis and edge.
std::unordered_map< const reco::ClusterHit3D *, reco::EdgeList > Hit3DToEdgeMap
TH1F * fGapBetweenClusHist
Gap between clusters.
TH1F * f1stDocaArcLRatHist
arc length to POCA for DOCA first cluster
TH1F * f1stTo2ndPosLenHist
Distance between cluster centers.
std::list< ClusterParameters > ClusterParametersList
const EigenVectors & getEigenVectors() const