17 #include "art/Framework/Services/Registry/ServiceHandle.h"
18 #include "fhiclcpp/ParameterSet.h"
19 #include "messagefacility/MessageLogger/MessageLogger.h"
27 #include "RStarTree/RStarBoundingBox.h"
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]));
146 std::vector<unsigned int>& badWireSum)
157 c.edges[0].first = c.edges[0].second = (b.edges[0].first + b.edges[0].second) / 2.0;
158 c.edges[1].first = c.edges[1].second = (b.edges[1].first + b.edges[1].second) / 2.0;
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;
177 double bWidth =
std::abs(b.edges[1].second - b.edges[1].first);
180 unsigned int wire1 = (
unsigned int)(tCenter0 /
fWireDist + 0.5);
181 unsigned int wire2 = (
unsigned int)(bCenter0 /
fWireDist + 0.5);
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) {
218 if (b.edges[i].first > c.edges[i].second) {
220 n.edges[i].first = n.edges[i].second = b.edges[i].first;
222 else if (b.edges[0].second < c.edges[0].first) {
224 n.edges[i].first = n.edges[i].second = b.edges[i].second;
228 n.edges[i].first = n.edges[i].second = c.edges[i].first;
240 if (
fBound.overlaps(node->bound))
return true;
249 return isNear(leaf->bound);
263 fEps = p.get<
double>(
"eps");
264 fEps2 = p.get<
double>(
"epstwo");
265 fMinPts = p.get<
int>(
"minPts");
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;
297 fRTree.Remove(RTree::AcceptAny(), RTree::RemoveLeaf());
305 art::ServiceHandle<geo::Geometry const> geom;
307 for (
size_t p = 0;
p < geom->Nplanes(); ++
p)
308 fWirePitch.push_back(geom->WirePitch(
p));
311 if (fClusterMethod) {
312 fBadWireSum.resize(geom->Nchannels());
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++) {
556 if (ExpandCluster(pid, cid)) { cid++; }
563 fclusters.resize(cid);
564 for (
size_t y = 0;
y < fpointId_to_clusterId.size(); ++
y) {
567 mf::LogWarning(
"DBscan") <<
"Unclassified point!";
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) {
583 mf::LogVerbatim(
"DBscan") <<
"\t"
584 <<
"Cluster " << c <<
":\t" << fclusters[c].size();
586 mf::LogVerbatim(
"DBscan") <<
"\t"
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) {
643 fpointId_to_clusterId[point] = clusterID;
644 for (std::set<unsigned int>::iterator itr = seeds.begin(); itr != seeds.end(); itr++) {
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) {
653 for (std::set<unsigned int>::iterator itr = result.begin(); itr != result.end(); itr++) {
654 unsigned int resultP = *itr;
656 if (fpointId_to_clusterId[resultP] ==
kNO_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]);
722 fpointId_to_clusterId[nPid] = cid;
726 fclusters.push_back(c);
736 for (
size_t y = 0;
y < fpointId_to_clusterId.size(); ++
y) {
739 mf::LogInfo(
"DBscan") <<
"FindNeighbors (R*-tree): Found " << cid <<
" clusters...";
740 for (
unsigned int c = 0; c < cid; ++c) {
741 mf::LogVerbatim(
"DBscan") <<
"\t"
742 <<
"Cluster " << c <<
":\t" << fclusters[c].size();
744 mf::LogVerbatim(
"DBscan") <<
"\t"
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]);
800 fpointId_to_clusterId[nPid] = cid;
804 fclusters.push_back(c);
813 for (
size_t y = 0;
y < fpointId_to_clusterId.size(); ++
y) {
816 mf::LogInfo(
"DBscan") <<
"FindNeighbors (naive): Found " << cid <<
" clusters...";
817 for (
unsigned int c = 0; c < cid; ++c) {
818 mf::LogVerbatim(
"DBscan") <<
"\t"
819 <<
"Cluster " << c <<
":\t" << fclusters[c].size() <<
" points";
821 mf::LogVerbatim(
"DBscan") <<
"\t"
822 <<
"...and " << noise <<
" noise points.";
double getSimilarity(const std::vector< double > v1, const std::vector< double > v2)
const unsigned int kNO_CLUSTER
Functions to help with numbers.
Utilities related to art service access.
void computeWidthFactor()
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)
double Temperature() const
In kelvin.
std::vector< unsigned int > & fBadWireSum
static const BoundingBox EmptyBoundingBox
std::size_t size(FixedBins< T, C > const &) noexcept
void run_dbscan_cluster()
std::set< unsigned int > RegionQuery(unsigned int point)
void run_FN_naive_cluster()
bool isNear(const BoundingBox &b) const
double Efield(unsigned int planegap=0) const
kV/cm
bool operator()(const RTree::Leaf *const leaf) const
double c[2]
center of the bounding box
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
const unsigned int kNOISE_CLUSTER
process_name opflash particleana ie ie y
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
unsigned int fClusterMethod
Which clustering method to use.
RTree::BoundingBox BoundingBox
std::set< unsigned int > sResult
const BoundingBox & fBound
void operator()(const RTree::Leaf *const leaf)
BoundingBox bounds() 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)
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 >())
bool ExpandCluster(unsigned int point, unsigned int clusterID)
Contains all timing reference information for the detector.
double getSimilarity2(const std::vector< double > v1, const std::vector< double > v2)
std::size_t count(Cont const &cont)
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
BoundingBox center() const
BEGIN_PROLOG don t mess with this pandoraTrackGausCryoW true
art framework interface to geometry description
const bool ContinueVisiting
unsigned int fDistanceMetric
Which distance metric to use.
BoundingBox nearestPoint(const BoundingBox &b) const