18 #include "lardata/RecoObjects/Cluster3D.h" 74 epsVecItr->second.first.setInCluster();
75 curCluster.push_back(epsVecItr->first);
81 while(!epsNeighborhoodList.empty())
89 std::advance(curPtEpsVecItr, neighborPtr->
getID());
92 if (!curPtEpsVecItr->second.first.visited())
94 curPtEpsVecItr->second.first.setVisited();
97 if (curPtEpsVecItr->second.first.getCount() >= minPts)
107 epsNeighborhoodList.push_back(*hitItr);
113 if (!curPtEpsVecItr->second.first.inCluster())
115 curPtEpsVecItr->second.first.setInCluster();
116 curCluster.push_back(curPtEpsVecItr->first);
119 epsNeighborhoodList.pop_front();
129 if (left->
getHits().back()->getHit().WireID().Wire == right->
getHits().back()->getHit().WireID().Wire)
133 if (left->
getHits().front()->getHit().WireID().Wire == right->
getHits().front()->getHit().WireID().Wire)
136 return left->
getX() < right->
getX();
139 return left->
getHits().front()->getHit().WireID().Wire > right->
getHits().front()->getHit().WireID().Wire;
142 return left->
getHits().back()->getHit().WireID().Wire < right->
getHits().back()->getHit().WireID().Wire;
151 if( left->
getZ() == right->
getZ() ){
152 if( left->
getY() == right->
getY() ){
153 return left->
getX() < right->
getX();
155 return left->
getY() < right->
getY();
157 return left->
getZ() < right->
getZ();
166 if( left->
getX() == right->
getX() ){
167 if( left->
getZ() == right->
getZ() ){
168 return left->
getY() < right->
getY();
170 return left->
getZ() < right->
getZ();
172 return left->
getX() < right->
getX();
180 if( left->
getY() == right->
getY() ){
181 if( left->
getZ() == right->
getZ() ){
182 return left->
getX() < right->
getX();
184 return left->
getZ() < right->
getZ();
186 return left->
getY() < right->
getY();
193 return (*left)->getAvePeakTime() < (*right)->getAvePeakTime();
201 if (left->second.size() == right->second.size())
202 return left->first < right->first;
204 return left->second.size() > right->second.size();
228 size_t numHitPairs =
BuildHitPairMap(viewToHitVectorMap, viewToWiretoHitSetMap, hitPairList);
233 theClockMakeHits.
stop();
234 theClockBuildNeighborhood.
start();
249 theClockBuildNeighborhood.
stop();
250 theClockDBScan.
start();
254 int pairClusterIdx(0);
257 hitPairClusterMap.clear();
262 epsPairVecItr != epsPairNeighborhoodMapVec.end();
266 if (!epsPairVecItr->first)
continue;
269 if (epsPairVecItr->second.first.visited())
continue;
272 epsPairVecItr->second.first.setVisited();
275 if (epsPairVecItr->second.first.getCount() <
m_minPairPts)
277 epsPairVecItr->second.first.setNoise();
292 theClockDBScan.
stop();
299 mf::LogDebug(
"Cluster3D") <<
">>>>> DBScan done, found " << hitPairClusterMap.size() <<
" clusters" <<
std::endl;
320 size_t totalNumHits(0);
321 size_t hitPairCntr(0);
322 double minCharge[] = {0., 0., 0.};
329 if (mapItrU != viewToHitVectorMap.end())
333 totalNumHits += hitVectorU.size();
337 if (mapItrW != viewToHitVectorMap.end())
341 totalNumHits += hitVectorW.size();
343 if (viewToHitVectorMap.find(
geo::kV) != viewToHitVectorMap.end())
344 totalNumHits += viewToHitVectorMap[
geo::kV].
size();
351 for (
HitVector::iterator hitItrU = hitVectorU.begin(); hitItrU != hitVectorU.end(); hitItrU++)
363 for (
HitVector::iterator hitItrW = hitVectorWStartItr; hitItrW != hitVectorW.end(); hitItrW++)
385 hitVectorWStartItr++;
405 size_t thePlane = 9999;
407 if( (*(hitVect_iter))->getHit().WireID().TPC == hitPtrW->
getHit().
WireID().
TPC ){
408 thePlane = (*(hitVect_iter))->getHit().WireID().Plane;
420 std::cout <<
"TPC of third (nearest) wire is not the same as the TPC of the first two." <<
std::endl;
422 std::cout <<
"TPC of wire 1 is not TPC of wire 2." <<
std::endl;
428 if (wireToHitSetMapVItr != viewToWireToHitSetMap[
geo::kV].
end())
443 triplet.
setID(hitPairCntr++);
444 hitPairList.emplace_back(std::unique_ptr<reco::ClusterHit3D>(
new reco::ClusterHit3D(triplet)));
459 return hitPairList.size();
472 size_t consistentPairsCnt = 0;
473 size_t pairsChecked = 0;
478 const size_t hitPairOID = hitPairO->
getID();
481 epsPairNeighborhoodMapVec[hitPairOID].first = hitPairO;
488 std::map<int, std::pair<double, const reco::ClusterHit3D*> > bestTripletMap;
499 while (++pairItrI != hitPairList.end())
519 if( pairI_Z - pairO_Z > maxDist )
break;
523 pow(pairO_X-pairI_X,2) +
524 pow(pairO_Y-pairI_Y,2) +
525 pow(pairO_Z-pairI_Z,2),0.5);
528 if( distance > maxDist )
continue;
535 double bestDist = 10000.;
537 if (bestTripletMap.find(bestBin) != bestTripletMap.end())
539 bestDist = bestTripletMap[bestBin].first;
542 double newDist = fabs(hitPairI->
getX() - hitPairO->
getX());
545 if (hitPairI->
getHits().size() < 3) newDist += 25.;
547 if (newDist < bestDist) bestTripletMap[bestBin] = std::pair<double, const reco::ClusterHit3D*>(newDist, hitPairI);
551 bestTripletMap[
distance] = std::pair<double,const reco::ClusterHit3D*>(
distance,hitPairI);
555 for(
const auto& bestMapItr : bestTripletMap)
559 hitPairOPair.first.incrementCount();
560 hitPairOPair.second.emplace_back(hitPairI);
562 epsPairNeighborhoodMapVec[hitPairI->
getID()].second.first.incrementCount();
563 epsPairNeighborhoodMapVec[hitPairI->
getID()].second.second.emplace_back(hitPairO);
565 consistentPairsCnt++;
569 mf::LogDebug(
"Cluster3D") <<
"Consistent pairs: " << consistentPairsCnt <<
" of " << pairsChecked <<
" checked." <<
std::endl;
571 return consistentPairsCnt;
581 bool consistent(
false);
591 std::vector<bool> matchedHits = {
false,
false,
false};
592 double maxDeltaT(0.);
593 double maxAllowedDeltaT(0.);
598 int maxDeltaWires = pair1->
getHits().size() < pair2->
getHits().size()
600 :
int(pair2->
getHits().size());
602 int pair1UWire = pair1UHit.WireID().Wire;
603 double pair1UPeakTime = pair1UHit.PeakTime();
604 double pair1ULimit = pair1UHit.RMS() * 2.;
606 int pair2UWire = pair2UHit.WireID().Wire;
607 double pair2UPeakTime = pair2UHit.PeakTime();
608 double pair2ULimit = pair2UHit.RMS() * 2.;
610 int deltaUWire = fabs(pair1UWire - pair2UWire);
611 double limitTotalU = pair1ULimit + pair2ULimit;
614 limitTotalU =
std::min(limitTotalU, 100.);
617 if (deltaUWire == 0) limitTotalU *= 1.5;
618 else if (deltaUWire > 1) limitTotalU *= 3.;
621 if (deltaUWire < maxDeltaWires && fabs(pair1UPeakTime - pair2UPeakTime) < limitTotalU) matchedHits[0] =
true;
623 maxDeltaT =
std::max(maxDeltaT, fabs(pair1UPeakTime - pair2UPeakTime));
624 maxAllowedDeltaT =
std::max(maxAllowedDeltaT, limitTotalU);
626 if (deltaUWire < maxDeltaWires)
633 double pair1WPeakTime = pair1WHit.PeakTime();
634 double pair1WLimit = pair1WHit.RMS() * 2.;
636 int pair2WWire = pair2WHit.WireID().Wire;
637 double pair2WPeakTime = pair2WHit.PeakTime();
638 double pair2WLimit = pair2WHit.RMS() * 2.;
640 int deltaWWire = fabs(pair1WWire - pair2WWire);
641 double limitTotalW = pair1WLimit + pair2WLimit;
644 limitTotalW =
std::min(limitTotalW, 100.);
647 if (deltaWWire == 0) limitTotalW *= 1.5;
648 else if (deltaWWire > 1) limitTotalW *= 3.0;
651 if (deltaWWire < maxDeltaWires && fabs(pair1WPeakTime - pair2WPeakTime) < limitTotalW) matchedHits[1] =
true;
653 maxDeltaT =
std::max(maxDeltaT, fabs(pair1WPeakTime - pair2WPeakTime));
654 maxAllowedDeltaT =
std::max(maxAllowedDeltaT, limitTotalW);
656 if (deltaWWire < maxDeltaWires)
666 double pair1VPeakTime = pair1VHit.PeakTime();
667 double pair1VLimit = pair1VHit.RMS() * 2.;
669 int pair2VWire = pair2VHit.WireID().Wire;
670 double pair2VPeakTime = pair2VHit.PeakTime();
671 double pair2VLimit = pair2VHit.RMS() * 2.;
673 int deltaVWire = fabs(pair1VWire - pair2VWire);
674 double limitTotalV = pair1VLimit + pair2VLimit;
677 limitTotalV =
std::min(limitTotalV, 100.);
680 if (deltaVWire == 0) limitTotalV *= 2.;
681 else if (deltaVWire > 1) limitTotalV *= 4.;
684 if (deltaVWire < maxDeltaWires)
686 if (fabs(pair1VPeakTime - pair2VPeakTime) < limitTotalV) matchedHits[2] =
true;
688 maxDeltaT =
std::max(maxDeltaT, fabs(pair1VPeakTime - pair2VPeakTime));
689 maxAllowedDeltaT =
std::max(maxAllowedDeltaT, limitTotalV);
694 matchedHits[0] =
false;
695 matchedHits[1] =
false;
702 int numMatches =
std::count(matchedHits.begin(), matchedHits.end(),
true);
704 if (numMatches > 2) consistent =
true;
705 else if (numMatches > 1)
707 maxAllowedDeltaT =
std::min(5.*maxAllowedDeltaT, 50.);
709 if (maxDeltaT < maxAllowedDeltaT) consistent =
true;
718 double hitWidthSclFctr,
719 size_t hitPairCntr)
const 722 unsigned statusBits(0);
724 double totalCharge(0.);
725 double avePeakTime(0.);
726 double deltaPeakTime(0.);
727 double sigmaPeakTime(0.);
728 double overlapFraction(0.);
729 double hitDocaToAxis(9999.);
730 double hitArclenToPoca(0.);
732 std::vector<const reco::ClusterHit2D*> hitVector;
734 hitVector.push_back(hit1);
735 hitVector.push_back(hit2);
754 double hit1Sigma = hit1->
getHit().
RMS() * 2. / 2.355;
757 double hit2Sigma = hit2->
getHit().
RMS() * 2. / 2.355;
761 double hit1Width = hitWidthSclFctr * hit1->
getHit().
RMS() * 2.;
762 double hit2Width = hitWidthSclFctr * hit2->
getHit().
RMS() * 2.;
765 if (fabs(hit1Peak - hit2Peak) <= (hit1Width + hit2Width))
767 double maxUpper =
std::min(hit1Peak+hit1Width,hit2Peak+hit2Width);
768 double minLower =
std::max(hit1Peak-hit1Width,hit2Peak-hit2Width);
769 double overlap = maxUpper - minLower;
771 overlapFraction = 0.5 * overlap /
std::min(hit1Width,hit2Width);
773 if (overlapFraction > 0.)
775 avePeakTime = 0.5 * (hit1Peak + hit2Peak);
776 deltaPeakTime = fabs(hit1Peak - hit2Peak);
777 sigmaPeakTime = sqrt(hit1Sigma*hit1Sigma + hit2Sigma*hit2Sigma);
780 sigmaPeakTime =
std::max(sigmaPeakTime, 0.1);
784 double xPosition = 0.5 * (xPositionHit1 + xPositionHit2);
786 position[0] = xPosition;
787 position[1] = widIntersect.
y;
788 position[2] = widIntersect.
z;
817 unsigned statusBits(0x8);
819 double totalCharge(0.);
820 double avePeakTime(0.);
821 double deltaPeakTime(1000.);
822 double sigmaPeakTime(0.);
823 double overlapFraction(0.);
824 double hitDocaToAxis(9999.);
825 double hitArclenToPoca(0.);
827 std::vector<const reco::ClusterHit2D*> hitVector;
837 double uwDeltaT = 1.;
839 double vSigma = 2. * hitV->
getHit().
RMS();
852 double numGoodPairs(1.);
899 position[0] /= numGoodPairs;
900 position[1] /= numGoodPairs;
901 position[2] /= numGoodPairs;
902 avePeakTime /= numGoodPairs;
903 sigmaPeakTime = sqrt(sigmaPeakTime);
906 hitVector.push_back(hitU);
907 hitVector.push_back(hitV);
908 hitVector.push_back(hitW);
931 static const double minCharge(0.);
938 for (
const auto& hit2D : hit2DSet)
940 if (hit2D->getHit().Integral() < minCharge)
continue;
942 double hitVPeakTime(hit2D->getTimeTicks());
943 double deltaPeakTime(pairAvePeakTime-hitVPeakTime);
945 if (deltaPeakTime > pairDeltaTimeLimits)
continue;
949 if (deltaPeakTime < -pairDeltaTimeLimits)
continue;
951 pairDeltaTimeLimits = fabs(deltaPeakTime);
960 static const double minCharge(0.);
962 int numberInRange(0);
966 for (
const auto& hit2D : hit2DSet)
968 if (hit2D->getHit().Integral() < minCharge)
continue;
970 double hitVPeakTime(hit2D->getTimeTicks());
971 double deltaPeakTime(pairAvePeakTime-hitVPeakTime);
973 if (deltaPeakTime > range)
continue;
975 if (deltaPeakTime < -range)
break;
980 return numberInRange;
995 mf::LogWarning(
"Cluster3D") <<
"Exception caught finding nearest wire, position - " << exc.what() <<
std::endl;
1017 mf::LogWarning(
"Cluster3D") <<
"Exception caught finding nearest wire, position - " << exc.what() <<
std::endl;
1018 std::cout <<
"Exception caught finding nearest wire." <<
std::endl;
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
std::map< int, HitPairListPtr > HitPairClusterMap
double z
z position of intersection
std::vector< EpsPairNeighborhoodMapPair > EpsPairNeighborhoodMapVec
float getTimeTicks() const
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
const Eigen::Vector3f getPosition() const
geo::WireID WireID() const
float RMS() const
RMS of the hit shape, in tick units.
void ClusterHitsDBScan(ViewToHitVectorMap &viewToHitVectorMap, ViewToWireToHitSetMap &viewToWiretoHitSetMap, HitPairList &hitPairList, reco::HitPairClusterMap &hitPairClusterMap)
Given a set of recob hits, run DBscan to form 3D clusters.
The data type to uniquely identify a Plane.
std::map< geo::View_t, WireToHitSetMap > ViewToWireToHitSetMap
size_t BuildNeighborhoodMap(HitPairList &hitPairList, EpsPairNeighborhoodMapVec &epsPairNeighborhoodMapVec) const
Given an input HitPairList, build out the map of nearest neighbors.
CryostatID_t Cryostat
Index of cryostat.
float getTotalCharge() const
float Integral() const
Integral under the calibrated signal waveform of the hit, in tick x ADC units.
geo::View_t View() const
View for the plane of the hit.
WireID_t Wire
Index of the wire within its plane.
float getSigmaPeakTime() const
std::pair< DBScanParams, EpsPairNeighborhoodList > EpsPairNeighborhoodPair
reco::ClusterHit3D makeHitPair(const reco::ClusterHit2D *hit1, const reco::ClusterHit2D *hit2, double hitWidthSclFctr=1., size_t hitPairCntr=0) const
Make a HitPair object by checking two hits.
float getOverlapFraction() const
bool SetPeakHitPairIteratorOrder(const HitPairList::iterator &left, const HitPairList::iterator &right)
unsigned int Nwires(unsigned int p, unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wires in the specified plane.
art framework interface to geometry description
const recob::Hit * getHit() const
bool SetPositionOrderY(const std::unique_ptr< reco::ClusterHit3D > &left, const std::unique_ptr< reco::ClusterHit3D > &right)
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
float getAvePeakTime() const
const reco::ClusterHit2D * FindBestMatchingHit(const Hit2DSet &hit2DSet, const reco::ClusterHit3D &pair, double pairDeltaTimeLimits) const
A utility routine for finding a 2D hit closest in time to the given pair.
geo::WireID NearestWireID(const double *position, const geo::View_t &view) const
Jacket the calls to finding the nearest wire in order to intercept the exceptions if out of range...
reco::ClusterHit3D makeHitTriplet(const reco::ClusterHit3D &pair, const reco::ClusterHit2D *hit2) const
Make a HitPair object by checking two hits.
bool SetPositionOrderZ(const std::unique_ptr< reco::ClusterHit3D > &left, const std::unique_ptr< reco::ClusterHit3D > &right)
std::map< geo::View_t, HitVector > ViewToHitVectorMap
std::list< std::unique_ptr< reco::ClusterHit3D > > HitPairList
T get(std::string const &key) const
size_t BuildHitPairMap(ViewToHitVectorMap &viewToHitVectorMap, ViewToWireToHitSetMap &viewToWiretoHitSetMap, HitPairList &hitPairList) const
Given the ClusterHit2D objects, build the HitPairMap.
geo::Length_t DetLength(geo::TPCID const &tpcid) const
Returns the length of the active volume of the specified TPC.
std::list< const reco::ClusterHit3D * > HitPairListPtr
float getXPosition() const
This algorithm will create and then cluster 3D hits using DBScan.
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
static int max(int a, int b)
PlaneID_t Plane
Index of the plane within its TPC.
size_t m_minPairPts
Data members to follow.
Encapsulate the geometry of a wire.
std::set< const reco::ClusterHit2D *, Hit2DSetCompare > Hit2DSet
std::vector< reco::ClusterHit2D * > HitVector
What follows are several highly useful typedefs which we want to expose to the outside world...
bool WireIDsIntersect(WireID const &wid1, WireID const &wid2, geo::Point_t &intersection) const
Computes the intersection between two wires.
bool operator()(const reco::HitPairClusterMap::iterator &left, const reco::HitPairClusterMap::iterator &right)
std::vector< float > m_timeVector
float PeakTime() const
Time of the signal peak, in tick units.
Declaration of signal hit object.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
void setID(const size_t &id) const
Encapsulate the construction of a single detector plane.
void reconfigure(fhicl::ParameterSet const &pset)
double y
y position of intersection
bool SetPositionOrderX(const std::unique_ptr< reco::ClusterHit3D > &left, const std::unique_ptr< reco::ClusterHit3D > &right)
DBScanAlg_DUNE35t(fhicl::ParameterSet const &pset)
Constructor.
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
bool SetPositionOrder(const std::unique_ptr< reco::ClusterHit3D > &left, const std::unique_ptr< reco::ClusterHit3D > &right)
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::pair< const reco::ClusterHit3D *, EpsPairNeighborhoodPair > EpsPairNeighborhoodMapPair
void expandCluster(EpsPairNeighborhoodMapVec &nMap, EpsPairNeighborhoodMapVec::iterator vecItr, reco::HitPairListPtr &cluster, size_t minPts) const
the main routine for DBScan
float getDeltaPeakTime() const
geo::WireID NearestWireID(geo::Point_t const &point, geo::PlaneID const &planeid) const
Returns the ID of wire closest to position in the specified TPC.
Access the description of detector geometry.
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Planes which measure W (third view for Bo, MicroBooNE, etc).
2D representation of charge deposited in the TDC/wire plane
int FindNumberInRange(const Hit2DSet &hit2DSet, const reco::ClusterHit3D &pair, double range) const
A utility routine for returning the number of 2D hits from the list in a given range.
double accumulated_real_time() const
double m_numSigmaPeakTime
TPCID_t TPC
Index of the TPC within its cryostat.
geo::Geometry * m_geometry
second_as<> second
Type of time stored in seconds, in double precision.
virtual ~DBScanAlg_DUNE35t()
Destructor.
const ClusterHit2DVec & getHits() const
geo::WireID NearestWireID_mod(const double *position, const geo::PlaneID &thePlaneID) const
cet::coded_exception< error, detail::translate > exception
QTextStream & endl(QTextStream &s)
Encapsulate the construction of a single detector plane.
std::list< const reco::ClusterHit3D * > EpsPairNeighborhoodList
bool consistentPairs(const reco::ClusterHit3D *pair1, const reco::ClusterHit3D *pair2) const
The bigger question: are two pairs of hits consistent?