32 #include "TDecompSVD.h" 53 m_hiThresholdFrac(.05),
54 m_loThresholdFrac(0.85),
58 m_maxLoopsPerCluster(3),
60 m_pcaAlg(pset.get<
fhicl::ParameterSet>(
"PrincipalComponentsAlg")),
108 m_position(position), m_hit3DIterator(itr) {}
132 m_accumulatorValuesVec.push_back(values);
163 size_t peakCountLeft(0);
164 size_t peakCountRight(0);
166 for(
const auto& binIndex : left)
167 peakCountLeft =
std::max(peakCountLeft, m_accMap[binIndex].getAccumulatorValues().size());
168 for(
const auto& binIndex : right)
169 peakCountRight =
std::max(peakCountRight, m_accMap[binIndex].getAccumulatorValues().size());
171 return peakCountLeft > peakCountRight;
184 size_t leftSize = left->second.getAccumulatorValues().size();
185 size_t rightSize = right->second.getAccumulatorValues().size();
187 return leftSize > rightSize;
195 size_t threshold)
const 202 for(
int rhoIdx = curBin.first - 1; rhoIdx <= curBin.first + 1; rhoIdx++)
204 for(
int jdx = curBin.second - 1; jdx <= curBin.second + 1; jdx++)
207 if (rhoIdx == curBin.first && jdx == curBin.second)
continue;
218 if (mapItr != rhoThetaAccumulatorBinMap.end())
220 if (mapItr->second.getAccumulatorValues().size() >= threshold) neighborPts.push_back(binIndex);
232 size_t threshold)
const 239 houghCluster.push_back(curBin);
241 for(
auto& binIndex : neighborPts)
251 HoughRegionQuery(binIndex, rhoThetaAccumulatorBinMap, nextNeighborPts, threshold);
253 if(!nextNeighborPts.empty())
255 for(
auto& neighborIdx : nextNeighborPts)
257 neighborPts.push_back(neighborIdx);
264 houghCluster.push_back(binIndex);
274 return *left < *
right;
289 int planeToCheck = (m_plane + 1) % 3;
291 return left->
getHits()[planeToCheck]->getHit().WireID().Wire < right->
getHits()[planeToCheck]->getHit().WireID().Wire;
301 return left.second < right.second;
322 outputList = inputHitList;
334 std::map<size_t, reco::HitPairListPtr > gapHitListMap;
337 double arcLenLastHit = inputHitList.front()->getArclenToPoca();
340 for(
const auto& hit3D : inputHitList)
343 double arcLen = hit3D->getArclenToPoca();
344 double deltaArcLen = arcLen - arcLenLastHit;
348 gapHitListMap[continuousHitList.size()] = continuousHitList;
349 continuousHitList.clear();
352 continuousHitList.emplace_back(hit3D);
354 arcLenLastHit = arcLen;
357 if (!continuousHitList.empty()) gapHitListMap[continuousHitList.size()] = continuousHitList;
360 std::map<size_t, reco::HitPairListPtr >::reverse_iterator longestListItr = gapHitListMap.rbegin();
362 if (longestListItr != gapHitListMap.rend())
364 size_t nContinuousHits = longestListItr->first;
367 outputList.resize(nContinuousHits);
368 std::copy(longestList.begin(), longestList.end(), outputList.begin());
389 static int histCount(0);
390 const double maxTheta(M_PI);
391 const double thetaBinSize(maxTheta/
double(
m_thetaBins));
401 double maxRho = std::sqrt(eigenVal0*eigenVal0 + eigenVal1*eigenVal1) * 2. / 3.;
402 double rhoBinSize = maxRho / double(
m_rhoBins);
404 if (rhoBinSize < rhoBinSizeMin) rhoBinSize = rhoBinSizeMin;
410 size_t maxBinCount(0);
411 int nAccepted3DHits(0);
415 hit3DItr != hitPairListPtr.end();
427 TVector3 pcaToHitVec = hit3DPosition - pcaCenter;
428 TVector3 pcaToHitPlaneVec(pcaToHitVec.Dot(planeVec0), pcaToHitVec.Dot(planeVec1), 0.);
430 double xPcaToHit = pcaToHitPlaneVec[0];
431 double yPcaToHit = pcaToHitPlaneVec[1];
438 for(
int thetaIdx = 0; thetaIdx <
m_thetaBins; thetaIdx++)
441 double theta = thetaBinSize * double(thetaIdx);
444 double rho = xPcaToHit * std::cos(theta) + yPcaToHit * std::sin(theta);
447 int rhoIdx = std::round(rho / rhoBinSize);
450 BinIndex binIndex(rhoIdx, thetaIdx);
452 rhoThetaAccumulatorBinMap[binIndex].addAccumulatorValue(accValue);
454 if (rhoThetaAccumulatorBinMap[binIndex].getAccumulatorValues().size() > maxBinCount)
455 maxBinCount = rhoThetaAccumulatorBinMap[binIndex].getAccumulatorValues().size();
462 std::ostringstream ostr;
463 ostr <<
"Hough Histogram " << histCount++;
464 m_Canvases.emplace_back(
new TCanvas(ostr.str().c_str(), ostr.str().c_str(), 1000, 1000));
466 std::ostringstream ostr2;
469 m_Canvases.back()->GetFrame()->SetFillColor(46);
478 TPad* p =
new TPad(ostr2.str().c_str(), ostr2.str().c_str(), zmin, xmin, zmax, xmax);
479 p->SetBit(kCanDelete);
480 p->Range(zmin, xmin, zmax, xmax);
481 p->SetFillStyle(4000);
487 for(
const auto& rhoThetaMap : rhoThetaAccumulatorBinMap)
489 houghHist->Fill(rhoThetaMap.first.first, rhoThetaMap.first.second+0.5, rhoThetaMap.second.getAccumulatorValues().size());
492 houghHist->SetBit(kCanDelete);
504 std::list<RhoThetaAccumulatorBinMap::iterator> binIndexList;
507 mapItr != rhoThetaAccumulatorBinMap.end();
509 binIndexList.push_back(mapItr);
513 for(
auto& mapItr : binIndexList)
517 if (mapItr->second.isInCluster())
continue;
524 if (mapItr->second.getAccumulatorValues().size() < thresholdLo)
526 mapItr->second.setNoise();
537 HoughRegionQuery(curBin, rhoThetaAccumulatorBinMap, neighborhood, thresholdHi);
543 expandHoughCluster(curBin, neighborhood, houghCluster, rhoThetaAccumulatorBinMap, thresholdHi);
547 if (!houghClusters.empty()) houghClusters.sort(
SortHoughClusterList(rhoThetaAccumulatorBinMap));
560 if (!seedFullPca.
getSvdOK())
return false;
572 std::set<const reco::ClusterHit2D*> seedHitSet;
587 seedHit3DList.clear();
591 seedHit3DList.push_back(hit3D);
593 for(
const auto&
hit : hit3D->
getHits()) seedHitSet.insert(
hit);
610 if (!seedPca.
getSvdOK())
return false;
620 double arcLen = seedHit3DList.front()->getArclenToPoca();
621 double seedStart[3] = {seedCenter[0]+arcLen*seedDir[0], seedCenter[1]+arcLen*seedDir[1], seedCenter[2]+arcLen*seedDir[2]};
627 if (seedHitSet.size() >= 10)
633 LineFit2DHits(seedHitSet, seedStart[0], newSeedPos, newSeedDir, chiDOF);
638 double cosAng = seedDir[0]*newSeedDir[0]+seedDir[1]*newSeedDir[1]+seedDir[2]*newSeedDir[2];
640 if (cosAng < 0.) newSeedDir *= -1.;
642 seedStart[0] = newSeedPos[0];
643 seedStart[1] = newSeedPos[1];
644 seedStart[2] = newSeedPos[2];
645 seedDir[0] = newSeedDir[0];
646 seedDir[1] = newSeedDir[1];
647 seedDir[2] = newSeedDir[2];
655 if (seed3DHits.size() > 100)
663 size_t numToKeep = seed3DHits.size() - 10;
667 std::advance(endItr, numToKeep);
669 seed3DHits.erase(endItr, seed3DHits.end());
687 typedef std::map<size_t, SeedHitPairListPairVec > SizeToSeedToHitMap;
689 SizeToSeedToHitMap seedHitPairMap;
701 while(!hitPairListPtr.empty())
707 if (eigenVal0 > 5. && eigenVal1 > 0.001)
715 findHoughClusters(hitPairListPtr, pca, nLoops, rhoThetaAccumulatorBinMap, houghClusters);
718 if (houghClusters.empty())
break;
726 std::set<const reco::ClusterHit3D*> masterHitPtrList;
727 std::set<const reco::ClusterHit3D*> peakBinPtrList;
729 size_t firstPeakCount(0);
732 for(
auto& houghCluster : houghClusters)
734 BinIndex peakBin = houghCluster.front();
735 size_t peakCount = 0;
736 size_t totalHits = 0;
739 std::set<const reco::ClusterHit3D*> localHitPtrList;
742 for(
auto& binIndex : houghCluster)
745 std::set<const reco::ClusterHit3D*> tempHitPtrList;
748 for(
auto& hitItr : rhoThetaAccumulatorBinMap[binIndex].getAccumulatorValues())
752 tempHitPtrList.insert(*hit3DItr);
756 totalHits += tempHitPtrList.size();
759 std::set<const reco::ClusterHit3D*> tempHit3DSet;
761 std::set_difference(tempHitPtrList.begin(), tempHitPtrList.end(),
762 masterHitPtrList.begin(), masterHitPtrList.end(),
763 std::inserter(tempHit3DSet, tempHit3DSet.end()) );
765 tempHitPtrList = tempHit3DSet;
767 size_t binCount = tempHitPtrList.size();
769 if (peakCount < binCount)
771 peakCount = binCount;
773 peakBinPtrList = tempHitPtrList;
777 localHitPtrList.insert(tempHitPtrList.begin(),tempHitPtrList.end());
782 if (!firstPeakCount) firstPeakCount = peakCount;
785 if (peakCount < firstPeakCount / 10)
continue;
793 for(
const auto& hit3D : localHitPtrList) allPeakBinHits.push_back(hit3D);
806 seedHitPairMap[peakBinHits.size()].push_back(seedHitPair);
809 if (seedHitPairMap.size() == 1)
811 for(
const auto& hit3D : peakBinHits) hit3D->setStatusBit(0x40000000);
822 masterHitPtrList.insert(peakBinHits.begin(),peakBinHits.end());
824 if (hitPairListPtr.size() - masterHitPtrList.size() <
m_minimum3DHits)
break;
828 if (masterHitPtrList.empty())
break;
834 hitPairListPtr.sort();
837 std::set_difference(hitPairListPtr.begin(), hitPairListPtr.end(),
838 masterHitPtrList.begin(), masterHitPtrList.end(),
839 hitPairListPtr.begin() );
841 hitPairListPtr.erase(newListEnd, hitPairListPtr.end());
861 for(SizeToSeedToHitMap::reverse_iterator seedMapItr = seedHitPairMap.rbegin(); seedMapItr != seedHitPairMap.rend(); seedMapItr++)
863 for(
const auto& seedHitPair : seedMapItr->second)
865 seedHitPairVec.emplace_back(seedHitPair);
891 if (eigenVal0 > 5. && eigenVal1 > 0.001)
899 findHoughClusters(hitPairListPtr, pca, nLoops, rhoThetaAccumulatorBinMap, houghClusters);
907 std::set<const reco::ClusterHit3D*> masterHitPtrList;
908 std::set<const reco::ClusterHit3D*> peakBinPtrList;
910 size_t firstPeakCount(0);
913 for(
auto& houghCluster : houghClusters)
915 BinIndex peakBin = houghCluster.front();
916 size_t peakCount = 0;
917 size_t totalHits = 0;
920 std::set<const reco::ClusterHit3D*> localHitPtrList;
923 for(
auto& binIndex : houghCluster)
926 std::set<const reco::ClusterHit3D*> tempHitPtrList;
929 for(
auto& hitItr : rhoThetaAccumulatorBinMap[binIndex].getAccumulatorValues())
933 tempHitPtrList.insert(*hit3DItr);
937 totalHits += tempHitPtrList.size();
940 std::set<const reco::ClusterHit3D*> tempHit3DSet;
942 std::set_difference(tempHitPtrList.begin(), tempHitPtrList.end(),
943 masterHitPtrList.begin(), masterHitPtrList.end(),
944 std::inserter(tempHit3DSet, tempHit3DSet.end()) );
946 tempHitPtrList = tempHit3DSet;
948 size_t binCount = tempHitPtrList.size();
950 if (peakCount < binCount)
952 peakCount = binCount;
954 peakBinPtrList = tempHitPtrList;
958 localHitPtrList.insert(tempHitPtrList.begin(),tempHitPtrList.end());
963 if (!firstPeakCount) firstPeakCount = peakCount;
966 if (peakCount < firstPeakCount / 10)
continue;
974 hitPairListPtrList.back().resize(localHitPtrList.size());
975 std::copy(localHitPtrList.begin(), localHitPtrList.end(), hitPairListPtrList.back().begin());
978 masterHitPtrList.insert(localHitPtrList.begin(),localHitPtrList.end());
980 if (hitPairListPtr.size() - masterHitPtrList.size() <
m_minimum3DHits)
break;
993 double& ChiDOF)
const 1015 if(hit2DSet.size() < 4)
return;
1017 const unsigned int nvars = 4;
1018 unsigned int npts = hit2DSet.size();
1020 TMatrixD A(npts, nvars);
1023 unsigned short ninpl[3] = {0};
1024 unsigned short nok = 0;
1025 unsigned short iht(0), cstat, tpc, ipl;
1026 double x, cw,
sw, off;
1029 for (
const auto&
hit : hit2DSet)
1046 x =
hit->getXPosition() - XOrigin;
1052 w[iht] = wireID.
Wire - off;
1057 if(ninpl[ipl] == 2) ++nok;
1067 TVectorD tVec = svd.Solve(w, ok);
1072 if(npts <= 4)
return;
1074 double ypr, zpr, diff;
1076 for (
const auto&
hit : hit2DSet)
1086 x =
hit->getXPosition() - XOrigin;
1087 ypr = tVec[0] + tVec[2] *
x;
1088 zpr = tVec[1] + tVec[3] *
x;
1089 diff = ypr * cw + zpr * sw - (wireID.
Wire - off);
1090 ChiDOF += diff * diff;
1096 ChiDOF /= (float)(npts - 4);
1098 double norm = sqrt(1 + tVec[2] * tVec[2] + tVec[3] * tVec[3]);
1100 Dir[1] = tVec[2] /
norm;
1101 Dir[2] = tVec[3] /
norm;
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
void LineFit2DHits(std::set< const reco::ClusterHit2D * > &hitList, double XOrigin, TVector3 &Pos, TVector3 &Dir, double &ChiDOF) const
std::vector< SeedHitPairListPair > SeedHitPairListPairVec
Define a comparator which will sort hits by arc length along a PCA axis.
void PCAAnalysis_calc3DDocas(const reco::HitPairListPtr &hitPairVector, const reco::PrincipalComponents &pca) const
void findHitGaps(reco::HitPairListPtr &inputHitList, reco::HitPairListPtr &outputList) const
Using Principal Components Axis, look for gaps in a list of 3D hits.
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
std::vector< TVirtualPad * > m_Pads
View pads in current canvas.
void reconfigure(fhicl::ParameterSet const &pset)
a handler for the case where the algorithm control parameters are to be reset
Declaration of signal hit object.
std::vector< AccumulatorValues > AccumulatorValuesVec
virtual void reconfigure(fhicl::ParameterSet const &pset)
a handler for the case where the algorithm control parameters are to be reset
CryostatID_t Cryostat
Index of cryostat.
const float * getAvePosition() const
HoughSeedFinderAlg(fhicl::ParameterSet const &pset)
Constructor.
WireID_t Wire
Index of the wire within its plane.
std::list< HitPairListPtr > HitPairListPtrList
void findHoughClusters(const reco::HitPairListPtr &inputHits, reco::PrincipalComponents &pca, int &nLoops, RhoThetaAccumulatorBinMap &rhoThetaMap, HoughClusterList &clusterList) const
unsigned int getStatusBits() const
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
float getDocaToAxis() const
Define a comparator which will sort hits by the absolute value of arc length so hits are ordered clos...
OrderHitsAlongWire(int plane=0)
void expandHoughCluster(BinIndex &curBin, HoughCluster &neighborPts, HoughCluster &houghCluster, RhoThetaAccumulatorBinMap &rhoThetaAccumulatorBinMap, size_t threshold) const
HoughSeedFinderAlg::RhoThetaAccumulatorBinMap & m_accMap
void addAccumulatorValue(AccumulatorValues &value)
This is an algorithm for finding recob::Seed objects in 3D clusters.
void HoughRegionQuery(BinIndex &curBin, RhoThetaAccumulatorBinMap &rhoThetaAccumulatorBinMap, HoughCluster &neighborPts, size_t threshold) const
T get(std::string const &key) const
std::list< HoughCluster > HoughClusterList
const AccumulatorValuesVec & getAccumulatorValues() const
std::list< const reco::ClusterHit3D * > HitPairListPtr
bool operator()(const HoughSeedFinderAlg::HoughCluster &left, const HoughSeedFinderAlg::HoughCluster &right)
PrincipalComponentsAlg m_pcaAlg
bool operator()(const reco::ClusterHit3D *left, const reco::ClusterHit3D *right)
PlaneID_t Plane
Index of the plane within its TPC.
geo::Geometry * m_geometry
bool buildSeed(reco::HitPairListPtr &seed3DHits, SeedHitPairListPair &seedHitPair) const
Given a list of candidate "seed" 3D hits, build the seed and get associated unique 2D hits...
bool operator()(const HoughSeedFinderAlg::RhoThetaAccumulatorBinMap::iterator &left, const HoughSeedFinderAlg::RhoThetaAccumulatorBinMap::iterator &right)
This is used to sort bins in Hough Space.
std::map< BinIndex, AccumulatorBin > RhoThetaAccumulatorBinMap
const float * getPosition() const
Detector simulation of raw signals on wires.
Encapsulate the geometry of a wire.
reco::HitPairListPtr::const_iterator m_hit3DIterator
This will be used to take us back to our 3D hit.
AccumulatorValues(const TVector3 &position, const reco::HitPairListPtr::const_iterator &itr)
virtual bool findTrackHits(reco::HitPairListPtr &hitPairListPtr, reco::PrincipalComponents &inputPCA, reco::HitPairListPtrList &hitPairListPtrList) const
Given the list of hits this will return the sets of hits which belong on the same line...
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
std::string value(boost::any const &)
bool operator()(const std::pair< size_t, size_t > &left, const std::pair< size_t, size_t > &right)
const float * getEigenValues() const
Encapsulate the construction of a single detector plane.
const float getAveHitDoca() const
AccumulatorValuesVec m_accumulatorValuesVec
std::list< BinIndex > HoughCluster
virtual ~HoughSeedFinderAlg()
Destructor.
TVector3 m_position
We really only need the x,y coordinates here but keep all three for now.
std::pair< recob::Seed, reco::HitPairListPtr > SeedHitPairListPair
const TVector3 & getPosition() const
virtual bool findTrackSeeds(reco::HitPairListPtr &hitPairListPtr, reco::PrincipalComponents &inputPCA, SeedHitPairListPairVec &seedHitPairVec) const
Given the list of hits this will search for candidate Seed objects and return them.
SortHoughClusterList(HoughSeedFinderAlg::RhoThetaAccumulatorBinMap &accMap)
This is used to sort "Hough Clusters" by the maximum entries in a bin.
AccumulatorBin(AccumulatorValues &values)
std::pair< int, int > BinIndex
TPCID_t TPC
Index of the TPC within its cryostat.
AccumulatorValues()
A utility class to contain the values of a given "bin" in Hough Space.
AccumulatorBin()
A utility class used to accumulate the above values.
std::vector< std::unique_ptr< TCanvas > > m_Canvases
Graphical trace canvases.
const ClusterHit2DVec & getHits() const
bool Hit3DCompare(const reco::ClusterHit3D *left, const reco::ClusterHit3D *right)
reco::HitPairListPtr::const_iterator getHitIterator() const
art framework interface to geometry description
const EigenVectors & getEigenVectors() const