46 dbsPoint(
double X=0.0,
double Y=0.0,
double dX=0.0,
double dY=0.0)
47 :x(
X), y(
Y), dx(dX), dy(dY){};
49 void Expand(
double DX,
double DY){dx+=DX; dy+=DY;};
54 bb.
edges[0].first =
x - std::abs(
dx);
55 bb.
edges[0].second =
x + std::abs(
dx);
57 bb.
edges[1].first =
y - std::abs(
dy);
58 bb.
edges[1].second =
y + std::abs(
dy);
72 Visitor() : count(0), vResult(), sResult(), ContinueVisiting(true) {};
74 vResult.push_back(leaf->
leaf);
75 sResult.insert(leaf->
leaf);
91 double r1,
double r2):m_bound(b),r(),c(){
94 c[0] = (m_bound.
edges[0].second+m_bound.
edges[0].first)/2.0;
95 c[1] = (m_bound.
edges[1].second+m_bound.
edges[1].first)/2.0;
96 d[0] = (m_bound.
edges[0].second-m_bound.
edges[0].first)/2.0;
97 d[1] = (m_bound.
edges[1].second-m_bound.
edges[1].first)/2.0;
101 return m_bound.
overlaps(node->bound);
106 C[0] = (leaf->bound.edges[0].second + leaf->bound.edges[0].first)/2.0;
107 C[1] = (leaf->bound.edges[1].second + leaf->bound.edges[1].first)/2.0;
108 D[0] = (leaf->bound.edges[0].second - leaf->bound.edges[0].first)/2.0;
109 D[1] = (leaf->bound.edges[1].second - leaf->bound.edges[1].first)/2.0;
111 for (
int i=0; i<2; ++i){
114 t += ((c[i]-C[i])*(c[i]-C[i]))/((d[i]+D[i])*(d[i]+D[i]));
122 :m_bound(EmptyBoundingBox),r(),c(){
124 c[0] = (m_bound.
edges[0].second-m_bound.
edges[0].first)/2.0;
125 c[1] = (m_bound.
edges[1].second-m_bound.
edges[1].first)/2.0;
149 double maxWidth,
double wireDist,
150 std::vector< unsigned int > &badWireSum)
151 :fBound(b), fEps(), fMaxWidth(maxWidth), fWireDist(wireDist)
152 ,fBadWireSum(badWireSum)
161 b.
edges[0].second )/2.0;
163 b.
edges[1].second )/2.0;
171 double bCenter0 = center(b).edges[0].first;
172 double bCenter1 = center(b).edges[1].first;
173 double tCenter0 = center().edges[0].first;
174 double tCenter1 = center().edges[1].first;
176 double bWidth = std::abs( b.
edges[1].second - b.
edges[1].first);
177 double tWidth = std::abs(fBound.
edges[1].second - fBound.
edges[1].first);
179 unsigned int wire1 = (
unsigned int) (tCenter0/fWireDist + 0.5);
180 unsigned int wire2 = (
unsigned int) (bCenter0/fWireDist + 0.5);
183 if (wire1 < fBadWireSum.size()) wire1 = fBadWireSum.size();
184 if (wire2 < fBadWireSum.size()) wire2 = fBadWireSum.size();
188 unsigned int wirestobridge =
util::absDiff(fBadWireSum[wire1], fBadWireSum[wire2]);
189 double cmtobridge = wirestobridge*fWireDist;
192 double sim = std::abs(tCenter0 - bCenter0) - cmtobridge;
196 if ( std::abs(tCenter0 - bCenter0) > 1
e-10 ) {
197 cmtobridge *= std::abs((tCenter1-bCenter1)/(tCenter0-bCenter0));
199 double sim2 = std::abs(tCenter1 - bCenter1) - cmtobridge;
208 double WFactor = (exp(4.6*((tWidth*tWidth)+(bWidth*bWidth))))*k;
210 if (WFactor<1.0) WFactor = 1.0;
211 if (WFactor>6.25) WFactor = 6.25;
214 return (((sim )/(fEps[0]*fEps[0]) ) +
215 ((sim2)/(fEps[1]*fEps[1]*(WFactor))) <= 1 );
220 for (
int i=0; i<2; ++i) {
226 }
else if ( b.
edges[0].second < c.
edges[0].first ) {
235 n.
edges[1].first -= fMaxWidth/2.0;
236 n.
edges[1].second += fMaxWidth/2.0;
241 if (fBound.
overlaps(node->bound))
return true;
245 return isNear(nearestPoint(node->bound));
248 return isNear(leaf->bound);
262 this->reconfigure(pset);
273 fEps = p.
get<
double >(
"eps" );
274 fEps2 = p.
get<
double >(
"epstwo");
275 fMinPts = p.
get<
int >(
"minPts");
276 fClusterMethod = p.
get<
int >(
"Method");
277 fDistanceMetric = p.
get<
int >(
"Metric");
282 std::set<uint32_t> badChannels,
283 const std::vector<geo::WireID> & wireids)
285 if (wireids.size()&&wireids.size()!=allhits.size()){
286 throw cet::exception(
"DBScanAlg") <<
"allhits size = "<<allhits.size()<<
" wireids size = "<<wireids.size()<<
" do not match\n";
290 fpointId_to_clusterId.clear();
299 fBadChannels = badChannels;
314 for(
size_t p = 0; p < geom->Nplanes(); ++p)
315 fWirePitch.push_back(geom->WirePitch(p));
319 if (fClusterMethod) {
320 fBadWireSum.resize(geom->Nchannels());
321 unsigned int count=0;
322 for (
unsigned int i=0; i<fBadWireSum.size(); ++i) {
323 count += fBadChannels.count(i);
324 fBadWireSum[i] = count;
331 for (
unsigned int j = 0; j < allhits.size(); ++j){
333 std::vector<double> p(dims);
337 if (!wireids.size()) p[0] = (allhits[j]->WireID().Wire)*fWirePitch[allhits[j]->WireID().Plane];
338 else p[0] = (wireids[j].Wire)*fWirePitch[allhits[j]->WireID().Plane];
339 p[1] = allhits[j]->PeakTime()*tickToDist;
340 p[2] = 2.*allhits[j]->RMS()*tickToDist;
343 if ( p[2] > fMaxWidth ) fMaxWidth = p[2];
347 if (fClusterMethod) {
349 dbsPoint pp(p[0], p[1], 0.0, p[2]/2.0);
350 fRTree.Insert(j, pp.
bounds());
356 fpointId_to_clusterId.resize(fps.size(),
kNO_CLUSTER);
357 fnoise.resize(fps.size(),
false);
358 fvisited.resize(fps.size(),
false);
360 if (fClusterMethod) {
363 mf::LogInfo(
"DBscan") <<
"InitScan: hits RTree loaded with " 364 << visitor.
count <<
" items.";
366 mf::LogInfo(
"DBscan") <<
"InitScan: hits vector size is " << fps.size();
384 double wire_dist = fWirePitch[0];
386 unsigned int wire1=(
unsigned int)(v1[0]/wire_dist+0.5);
387 unsigned int wire2=(
unsigned int)(v2[0]/wire_dist+0.5);
391 unsigned int wire = wire1;
396 for(
unsigned int i=wire1;i<wire2;i++){
397 if(fBadChannels.find(i) != fBadChannels.end())
401 double cmtobridge=wirestobridge*wire_dist;
403 return (( std::abs(v2[0]-v1[0])-cmtobridge)*( std::abs(v2[0]-v1[0])-cmtobridge));
414 double wire_dist = fWirePitch[0];
416 unsigned int wire1=(
unsigned int)(v1[0]/wire_dist+0.5);
417 unsigned int wire2=(
unsigned int)(v2[0]/wire_dist+0.5);
421 unsigned int wire = wire1;
426 for(
unsigned int i=wire1;i<wire2;i++){
427 if(fBadChannels.find(i) != fBadChannels.end())
431 double cmtobridge=wirestobridge*wire_dist;
433 if (std::abs(v2[0]-v1[0])>1
e-10){
434 cmtobridge *= std::abs((v2[1]-v1[1])/(v2[0]-v1[0]));
438 return (( std::abs(v2[1]-v1[1])-cmtobridge)*( std::abs(v2[1]-v1[1])-cmtobridge));
455 double WFactor = (exp(4.6*(( v1[2]*v1[2])+( v2[2]*v2[2]))))*k;
461 if(WFactor < 6.25)
return WFactor;
475 std::vector<unsigned int> ne;
477 for (
int unsigned j=0; j < fsim.size(); j++){
479 && (((fsim[pid][j])/ (threshold*threshold))
480 + ((fsim2[pid][j])/ (threshold2*threshold2*(fsim3[pid][j]))))<1){
491 int size = fps.size();
492 fsim.resize(size, std::vector<double>(size));
493 for (
int i=0; i < size; i++){
494 for (
int j=i+1; j < size; j++){
495 fsim[j] [i] = fsim[i][ j] = getSimilarity(fps[i], fps[j]);
503 int size = fps.size();
504 fsim2.resize(size, std::vector<double>(size));
505 for (
int i=0; i < size; i++){
506 for (
int j=i+1; j < size; j++){
507 fsim2[j] [i] = fsim2[i][ j] = getSimilarity2(fps[i], fps[j]);
515 int size = fps.size();
516 fsim3.resize(size, std::vector<double>(size));
518 for (
int i=0; i < size; i++){
519 for (
int j=i+1; j < size; j++){
520 fsim3[j] [i] = fsim3[i][ j] = getWidthFactor(fps[i], fps[j]);
531 switch(fClusterMethod) {
533 return run_dbscan_cluster();
535 return run_FN_cluster();
538 computeSimilarity2();
539 computeWidthFactor();
540 return run_FN_naive_cluster();
550 unsigned int cid = 0;
552 for (
size_t pid = 0;
pid < fps.size();
pid++){
555 if ( ExpandCluster(
pid,cid) ) {
564 fclusters.resize(cid);
565 for(
size_t y = 0;
y < fpointId_to_clusterId.size(); ++
y){
574 unsigned int c = fpointId_to_clusterId[
y];
577 <<
" when only " << cid
578 <<
" clusters wer found [0-" << cid-1
581 fclusters[c].push_back(
y);
585 << cid <<
" clusters...";
586 for (
unsigned int c = 0; c < cid; ++c){
588 << fclusters[c].size();
590 mf::LogVerbatim(
"DBscan") <<
"\t" <<
"...and " << noise <<
" noise points.";
602 fMaxWidth,fWirePitch[0],
617 fMaxWidth,fWirePitch[0],
621 std::vector<unsigned int> &v = visitor.
vResult;
625 v.erase(std::remove(v.begin(), v.end(), point),v.end());
633 unsigned int clusterID)
637 std::set< unsigned int >
seeds = RegionQuery(point);
640 if (seeds.size() < fMinPts){
645 fpointId_to_clusterId[point]=clusterID;
647 fpointId_to_clusterId[*itr]=clusterID;
650 while (!seeds.empty()) {
651 unsigned int currentP = *(seeds.begin());
652 std::set< unsigned int > result = RegionQuery(currentP);
654 if (result.size() >= fMinPts){
658 unsigned int resultP = *itr;
660 if (fpointId_to_clusterId[resultP] ==
kNO_CLUSTER ||
662 if (fpointId_to_clusterId[resultP] ==
kNO_CLUSTER ) {
663 seeds.insert(resultP);
665 fpointId_to_clusterId[resultP]=clusterID;
669 seeds.erase(currentP);
684 unsigned int cid = 0;
686 for (
size_t pid = 0;
pid < fps.size();
pid++){
690 fvisited[pid] =
true;
693 std::vector<unsigned int> ne = RegionQuery_vector(pid);
696 if (ne.size() < fMinPts){
702 std::vector<unsigned int> c;
705 fpointId_to_clusterId[pid]=cid;
707 for (
size_t i = 0; i < ne.size(); ++i){
708 unsigned int nPid = ne[i];
711 if (!fvisited[nPid]){
712 fvisited[nPid] =
true;
715 std::vector<unsigned int> ne1 = RegionQuery_vector(nPid);
717 if (ne1.size() >= fMinPts){
721 for(
size_t i = 0; i < ne1.size(); ++i){
723 ne.push_back(ne1[i]);
732 fpointId_to_clusterId[nPid]=cid;
736 fclusters.push_back(c);
748 for(
size_t y = 0;
y < fpointId_to_clusterId.size(); ++
y){
752 mf::LogInfo(
"DBscan") <<
"FindNeighbors (R*-tree): Found " 753 << cid <<
" clusters...";
754 for (
unsigned int c = 0; c < cid; ++c){
756 << fclusters[c].size();
758 mf::LogVerbatim(
"DBscan") <<
"\t" <<
"...and " << noise <<
" noise points.";
770 unsigned int cid = 0;
772 for (
size_t pid = 0;
pid < fps.size(); ++
pid){
776 fvisited[pid] =
true;
778 std::vector<unsigned int> ne = findNeighbors(pid, fEps,fEps2);
781 if (ne.size() < fMinPts){
787 std::vector<unsigned int> c;
790 fpointId_to_clusterId[pid] = cid;
792 for (
size_t i = 0; i < ne.size(); ++i){
793 unsigned int nPid = ne[i];
796 if (!fvisited[nPid]){
797 fvisited[nPid] =
true;
799 std::vector<unsigned int> ne1 = findNeighbors(nPid, fEps, fEps2);
801 if (ne1.size() >= fMinPts){
805 for(
unsigned int i=0;i<ne1.size();i++){
807 ne.push_back(ne1[i]);
816 fpointId_to_clusterId[nPid]=cid;
820 fclusters.push_back(c);
832 for(
size_t y = 0;
y < fpointId_to_clusterId.size(); ++
y){
836 mf::LogInfo(
"DBscan") <<
"FindNeighbors (naive): Found " << cid
838 for (
unsigned int c = 0; c < cid; ++c){
840 << fclusters[c].size() <<
" points";
842 mf::LogVerbatim(
"DBscan") <<
"\t" <<
"...and " << noise <<
" noise points.";
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
double getSimilarity(const std::vector< double > v1, const std::vector< double > v2)
const unsigned int kNO_CLUSTER
Functions to help with numbers.
void InitScan(const std::vector< art::Ptr< recob::Hit > > &allhits, std::set< uint32_t > badChannels, const std::vector< geo::WireID > &wireids=std::vector< geo::WireID >())
void computeWidthFactor()
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
bool operator()(const RTree::Leaf *const leaf) const
Declaration of signal hit object.
AcceptFindNeighbors(const BoundingBox &b, double eps, double eps2, double maxWidth, double wireDist, std::vector< unsigned int > &badWireSum)
static const BoundingBox EmptyBoundingBox
virtual double SamplingRate() const =0
Returns the period of the TPC readout electronics clock.
Cluster finding and building.
void run_dbscan_cluster()
std::set< unsigned int > RegionQuery(unsigned int point)
void run_FN_naive_cluster()
bool isNear(const BoundingBox &b) const
void Expand(double DX, double DY)
bool operator()(const RTree::Leaf *const leaf) const
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
const unsigned int kNOISE_CLUSTER
std::vector< unsigned int > vResult
const BoundingBox & fBound
void operator()(const RTree::Leaf *const leaf)
virtual double Temperature() const =0
T get(std::string const &key) const
const BoundingBox & m_bound
BoundingBox center(const BoundingBox &b) const
bool operator()(const RTree::Node *const node) const
DBScanAlg(fhicl::ParameterSet const &pset)
double getWidthFactor(const std::vector< double > v1, const std::vector< double > v2)
std::vector< unsigned int > & fBadWireSum
bool operator()(const RTree::Node *const node) const
constexpr auto absDiff(A const &a, B const &b)
Returns the absolute value of the difference between two values.
Encapsulate the geometry of a wire.
void computeSimilarity2()
std::vector< unsigned int > findNeighbors(unsigned int pid, double threshold, double threshold2)
AcceptEllipse(const BoundingBox &b, double r1, double r2)
std::vector< TrajPoint > seeds
std::vector< unsigned int > RegionQuery_vector(unsigned int point)
bool ExpandCluster(unsigned int point, unsigned int clusterID)
Encapsulate the construction of a single detector plane.
virtual double DriftVelocity(double efield=0., double temperature=0.) const =0
bool overlaps(const RStarBoundingBox< dimensions > &bb) const
void reconfigure(fhicl::ParameterSet const &p)
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::pair< double, double > edges[dimensions]
BoundingBox bounds() const
dbsPoint(double X=0.0, double Y=0.0, double dX=0.0, double dY=0.0)
double getSimilarity2(const std::vector< double > v1, const std::vector< double > v2)
virtual double Efield(unsigned int planegap=0) const =0
Returns the nominal electric field in the specified volume.
BoundingBox center() const
std::set< unsigned int > sResult
cet::coded_exception< error, detail::translate > exception
const bool ContinueVisiting
BoundingBox nearestPoint(const BoundingBox &b) const