58 Visitor() : count(0), vResult(), sResult(), ContinueVisiting(true){};
62 vResult.push_back(leaf->
leaf);
63 sResult.insert(leaf->
leaf);
82 c[0] = (m_bound.
edges[0].second + m_bound.
edges[0].first) / 2.0;
83 c[1] = (m_bound.
edges[1].second + m_bound.
edges[1].first) / 2.0;
84 d[0] = (m_bound.
edges[0].second - m_bound.
edges[0].first) / 2.0;
85 d[1] = (m_bound.
edges[1].second - m_bound.
edges[1].first) / 2.0;
91 return m_bound.
overlaps(node->bound);
98 C[0] = (leaf->bound.edges[0].second + leaf->bound.edges[0].first) / 2.0;
99 C[1] = (leaf->bound.edges[1].second + leaf->bound.edges[1].first) / 2.0;
100 D[0] = (leaf->bound.edges[0].second - leaf->bound.edges[0].first) / 2.0;
101 D[1] = (leaf->bound.edges[1].second - leaf->bound.edges[1].first) / 2.0;
103 for (
int i = 0; i < 2; ++i) {
106 t += ((c[i] - C[i]) * (c[i] - C[i])) / ((d[i] + D[i]) * (d[i] + D[i]));
117 c[0] = (m_bound.
edges[0].second - m_bound.
edges[0].first) / 2.0;
118 c[1] = (m_bound.
edges[1].second - m_bound.
edges[1].first) / 2.0;
146 std::vector<unsigned int>& badWireSum)
147 : fBound(b), fEps(), fMaxWidth(maxWidth), fWireDist(wireDist), fBadWireSum(badWireSum)
172 double bCenter0 =
center(b).edges[0].first;
173 double bCenter1 =
center(b).edges[1].first;
174 double tCenter0 =
center().edges[0].first;
175 double tCenter1 =
center().edges[1].first;
180 unsigned int wire1 = (
unsigned int)(tCenter0 / fWireDist + 0.5);
181 unsigned int wire2 = (
unsigned int)(bCenter0 / fWireDist + 0.5);
184 if (wire1 < fBadWireSum.size()) wire1 = fBadWireSum.size();
185 if (wire2 < fBadWireSum.size()) wire2 = fBadWireSum.size();
189 unsigned int wirestobridge =
util::absDiff(fBadWireSum[wire1], fBadWireSum[wire2]);
190 double cmtobridge = wirestobridge * fWireDist;
192 double sim =
std::abs(tCenter0 - bCenter0) - cmtobridge;
195 if (
std::abs(tCenter0 - bCenter0) > 1
e-10) {
196 cmtobridge *=
std::abs((tCenter1 - bCenter1) / (tCenter0 - bCenter0));
198 double sim2 =
std::abs(tCenter1 - bCenter1) - cmtobridge;
202 double WFactor = (exp(4.6 * ((tWidth * tWidth) + (bWidth * bWidth)))) * k;
204 if (WFactor < 1.0) WFactor = 1.0;
205 if (WFactor > 6.25) WFactor = 6.25;
208 return (((sim) / (fEps[0] * fEps[0])) + ((sim2) / (fEps[1] * fEps[1] * (WFactor))) <= 1);
215 for (
int i = 0; i < 2; ++i) {
222 else if (b.
edges[0].second < c.
edges[0].first) {
232 n.
edges[1].first -= fMaxWidth / 2.0;
233 n.
edges[1].second += fMaxWidth / 2.0;
240 if (fBound.
overlaps(node->bound))
return true;
244 return isNear(nearestPoint(node->bound));
249 return isNear(leaf->bound);
254 const unsigned int kNO_CLUSTER = UINT_MAX;
255 const unsigned int kNOISE_CLUSTER = UINT_MAX - 1;
263 fEps = p.
get<
double>(
"eps");
264 fEps2 = p.
get<
double>(
"epstwo");
265 fMinPts = p.
get<
int>(
"minPts");
266 fClusterMethod = p.
get<
int>(
"Method");
267 fDistanceMetric = p.
get<
int>(
"Metric");
275 std::set<uint32_t> badChannels,
276 const std::vector<geo::WireID>& wireids)
278 if (wireids.size() && wireids.size() != allhits.size()) {
279 throw cet::exception(
"DBScanAlg") <<
"allhits size = " << allhits.size()
280 <<
" wireids size = " << wireids.size() <<
" do not match\n";
284 fpointId_to_clusterId.clear();
293 fBadChannels = badChannels;
311 if (fClusterMethod) {
313 unsigned int count = 0;
314 for (
unsigned int i = 0; i < fBadWireSum.size(); ++i) {
315 count += fBadChannels.count(i);
316 fBadWireSum[i] =
count;
323 for (
unsigned int j = 0; j < allhits.size(); ++j) {
325 std::vector<double>
p(dims);
330 p[0] = (allhits[j]->
WireID().Wire) * fWirePitch[allhits[j]->
WireID().Plane];
332 p[0] = (wireids[j].Wire) * fWirePitch[allhits[j]->
WireID().Plane];
333 p[1] = allhits[j]->PeakTime() * tickToDist;
334 p[2] = 2. * allhits[j]->RMS() * tickToDist;
337 if (p[2] > fMaxWidth) fMaxWidth = p[2];
341 if (fClusterMethod) {
343 dbsPoint pp(p[0], p[1], 0.0, p[2] / 2.0);
344 fRTree.Insert(j, pp.
bounds());
350 fpointId_to_clusterId.resize(fps.size(), kNO_CLUSTER);
351 fnoise.resize(fps.size(),
false);
352 fvisited.resize(fps.size(),
false);
354 if (fClusterMethod) {
356 mf::LogInfo(
"DBscan") <<
"InitScan: hits RTree loaded with " << visitor.
count <<
" items.";
358 mf::LogInfo(
"DBscan") <<
"InitScan: hits vector size is " << fps.size();
377 double wire_dist = fWirePitch[0];
380 (
unsigned int)(v1[0] / wire_dist + 0.5);
381 unsigned int wire2 = (
unsigned int)(v2[0] / wire_dist + 0.5);
382 int wirestobridge = 0;
385 unsigned int wire = wire1;
390 for (
unsigned int i = wire1; i < wire2; i++) {
391 if (fBadChannels.find(i) != fBadChannels.end()) wirestobridge++;
394 double cmtobridge = wirestobridge * wire_dist;
396 return ((
std::abs(v2[0] - v1[0]) - cmtobridge) *
397 (
std::abs(v2[0] - v1[0]) - cmtobridge));
410 double wire_dist = fWirePitch[0];
413 (
unsigned int)(v1[0] / wire_dist + 0.5);
414 unsigned int wire2 = (
unsigned int)(v2[0] / wire_dist + 0.5);
415 int wirestobridge = 0;
418 unsigned int wire = wire1;
423 for (
unsigned int i = wire1; i < wire2; i++) {
424 if (fBadChannels.find(i) != fBadChannels.end()) wirestobridge++;
427 double cmtobridge = wirestobridge * wire_dist;
430 cmtobridge *=
std::abs((v2[1] - v1[1]) / (v2[0] - v1[0]));
435 return ((
std::abs(v2[1] - v1[1]) - cmtobridge) *
436 (
std::abs(v2[1] - v1[1]) - cmtobridge));
452 double WFactor = (exp(4.6 * ((v1[2] * v1[2]) + (v2[2] * v2[2])))) * k;
469 std::vector<unsigned int>
472 std::vector<unsigned int> ne;
474 for (
int unsigned j = 0; j < fsim.size(); j++) {
476 (((fsim[pid][j]) / (threshold * threshold)) +
477 ((fsim2[pid][j]) / (threshold2 * threshold2 * (fsim3[pid][j])))) < 1) {
489 int size = fps.size();
490 fsim.resize(size, std::vector<double>(size));
491 for (
int i = 0; i <
size; i++) {
492 for (
int j = i + 1; j <
size; j++) {
493 fsim[j][i] = fsim[i][j] = getSimilarity(fps[i], fps[j]);
502 int size = fps.size();
503 fsim2.resize(size, std::vector<double>(size));
504 for (
int i = 0; i <
size; i++) {
505 for (
int j = i + 1; j <
size; j++) {
506 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]);
532 switch (fClusterMethod) {
533 case 2:
return run_dbscan_cluster();
534 case 1:
return run_FN_cluster();
537 computeSimilarity2();
538 computeWidthFactor();
539 return run_FN_naive_cluster();
551 unsigned int cid = 0;
553 for (
size_t pid = 0;
pid < fps.size();
pid++) {
555 if (fpointId_to_clusterId[
pid] == kNO_CLUSTER) {
556 if (ExpandCluster(
pid, cid)) { cid++; }
563 fclusters.resize(cid);
564 for (
size_t y = 0;
y < fpointId_to_clusterId.size(); ++
y) {
565 if (fpointId_to_clusterId[
y] == kNO_CLUSTER) {
569 else if (fpointId_to_clusterId[
y] == kNOISE_CLUSTER) {
573 unsigned int c = fpointId_to_clusterId[
y];
575 mf::LogWarning(
"DBscan") <<
"Point in cluster " << c <<
" when only " << cid
576 <<
" clusters wer found [0-" << cid - 1 <<
"]";
578 fclusters[
c].push_back(
y);
581 mf::LogInfo(
"DBscan") <<
"DWM (R*-tree): Found " << cid <<
" clusters...";
582 for (
unsigned int c = 0;
c < cid; ++
c) {
584 <<
"Cluster " <<
c <<
":\t" << fclusters[
c].size();
587 <<
"...and " << noise <<
" noise points.";
592 std::set<unsigned int>
608 std::vector<unsigned int>
620 std::vector<unsigned int>& v = visitor.
vResult;
624 v.erase(
std::remove(v.begin(), v.end(), point), v.end());
634 std::set<unsigned int>
seeds = RegionQuery(point);
637 if (seeds.size() < fMinPts) {
638 fpointId_to_clusterId[point] = kNOISE_CLUSTER;
643 fpointId_to_clusterId[point] = clusterID;
645 fpointId_to_clusterId[*itr] = clusterID;
648 while (!seeds.empty()) {
649 unsigned int currentP = *(seeds.begin());
650 std::set<unsigned int>
result = RegionQuery(currentP);
652 if (result.size() >= fMinPts) {
654 unsigned int resultP = *itr;
656 if (fpointId_to_clusterId[resultP] == kNO_CLUSTER ||
657 fpointId_to_clusterId[resultP] == kNOISE_CLUSTER) {
658 if (fpointId_to_clusterId[resultP] == kNO_CLUSTER) { seeds.insert(resultP); }
659 fpointId_to_clusterId[resultP] = clusterID;
663 seeds.erase(currentP);
679 unsigned int cid = 0;
681 for (
size_t pid = 0;
pid < fps.size();
pid++) {
683 if (!fvisited[
pid]) {
685 fvisited[pid] =
true;
687 std::vector<unsigned int> ne = RegionQuery_vector(pid);
690 if (ne.size() < fMinPts) { fnoise[pid] =
true; }
694 std::vector<unsigned int>
c;
697 fpointId_to_clusterId[pid] = cid;
699 for (
size_t i = 0; i < ne.size(); ++i) {
700 unsigned int nPid = ne[i];
703 if (!fvisited[nPid]) {
704 fvisited[nPid] =
true;
706 std::vector<unsigned int> ne1 = RegionQuery_vector(nPid);
708 if (ne1.size() >= fMinPts) {
712 for (
size_t i = 0; i < ne1.size(); ++i) {
714 ne.push_back(ne1[i]);
720 if (fpointId_to_clusterId[nPid] == kNO_CLUSTER) {
722 fpointId_to_clusterId[nPid] = cid;
726 fclusters.push_back(c);
736 for (
size_t y = 0;
y < fpointId_to_clusterId.size(); ++
y) {
737 if (fpointId_to_clusterId[
y] == kNO_CLUSTER) noise++;
739 mf::LogInfo(
"DBscan") <<
"FindNeighbors (R*-tree): Found " << cid <<
" clusters...";
740 for (
unsigned int c = 0;
c < cid; ++
c) {
742 <<
"Cluster " <<
c <<
":\t" << fclusters[
c].size();
745 <<
"...and " << noise <<
" noise points.";
757 unsigned int cid = 0;
759 for (
size_t pid = 0;
pid < fps.size(); ++
pid) {
761 if (!fvisited[
pid]) {
763 fvisited[pid] =
true;
765 std::vector<unsigned int> ne = findNeighbors(pid, fEps, fEps2);
768 if (ne.size() < fMinPts) { fnoise[pid] =
true; }
772 std::vector<unsigned int>
c;
775 fpointId_to_clusterId[pid] = cid;
777 for (
size_t i = 0; i < ne.size(); ++i) {
778 unsigned int nPid = ne[i];
781 if (!fvisited[nPid]) {
782 fvisited[nPid] =
true;
784 std::vector<unsigned int> ne1 = findNeighbors(nPid, fEps, fEps2);
786 if (ne1.size() >= fMinPts) {
790 for (
unsigned int i = 0; i < ne1.size(); i++) {
792 ne.push_back(ne1[i]);
798 if (fpointId_to_clusterId[nPid] == kNO_CLUSTER) {
800 fpointId_to_clusterId[nPid] = cid;
804 fclusters.push_back(c);
813 for (
size_t y = 0;
y < fpointId_to_clusterId.size(); ++
y) {
814 if (fpointId_to_clusterId[
y] == kNO_CLUSTER) ++noise;
816 mf::LogInfo(
"DBscan") <<
"FindNeighbors (naive): Found " << cid <<
" clusters...";
817 for (
unsigned int c = 0;
c < cid; ++
c) {
819 <<
"Cluster " <<
c <<
":\t" << fclusters[
c].size() <<
" points";
822 <<
"...and " << noise <<
" noise points.";
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
double getSimilarity(const std::vector< double > v1, const std::vector< double > v2)
Functions to help with numbers.
void computeWidthFactor()
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
bool operator()(const RTree::Leaf *const leaf) const
AcceptFindNeighbors(const BoundingBox &b, double eps, double eps2, double maxWidth, double wireDist, std::vector< unsigned int > &badWireSum)
double Temperature() const
In kelvin.
std::vector< unsigned int > & fBadWireSum
static const BoundingBox EmptyBoundingBox
Cluster finding and building.
void run_dbscan_cluster()
std::set< unsigned int > RegionQuery(unsigned int point)
void run_FN_naive_cluster()
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
art framework interface to geometry description
bool isNear(const BoundingBox &b) const
unsigned int Nchannels() const
Returns the number of TPC readout channels in the detector.
double Efield(unsigned int planegap=0) const
kV/cm
bool operator()(const RTree::Leaf *const leaf) const
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
std::set< unsigned int > sResult
const BoundingBox & fBound
void operator()(const RTree::Leaf *const leaf)
BoundingBox bounds() const
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
std::vector< unsigned int > vResult
double DriftVelocity(double efield=0., double temperature=0.) const
cm/us
DBScanAlg(fhicl::ParameterSet const &pset)
Code to link reconstructed objects back to the MC truth information.
double getWidthFactor(const std::vector< double > v1, const std::vector< double > v2)
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.
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)
void InitScan(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, const std::vector< art::Ptr< recob::Hit >> &allhits, std::set< uint32_t > badChannels, const std::vector< geo::WireID > &wireids=std::vector< geo::WireID >())
Declaration of signal hit object.
bool ExpandCluster(unsigned int point, unsigned int clusterID)
Contains all timing reference information for the detector.
bool overlaps(const RStarBoundingBox< dimensions > &bb) const
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::pair< double, double > edges[dimensions]
double getSimilarity2(const std::vector< double > v1, const std::vector< double > v2)
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
BoundingBox center() const
cet::coded_exception< error, detail::translate > exception
const bool ContinueVisiting
BoundingBox nearestPoint(const BoundingBox &b) const