LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
DBScan3DAlg.cxx
Go to the documentation of this file.
3 #include "larcorealg/CoreUtils/NumericUtils.h" // util::absDiff()
7 #include "larevt/CalibrationDBI/Interface/ChannelStatusProvider.h"
8 #include "larevt/CalibrationDBI/Interface/ChannelStatusService.h"
9 
11 #include "cetlib/pow.h"
12 #include "fhiclcpp/ParameterSet.h"
13 
14 #include <algorithm>
15 #include <stdio.h>
16 #include <stdlib.h>
17 
19  : epsilon(pset.get<float>("epsilon"))
20  , minpts(pset.get<unsigned int>("minpts"))
21  , badchannelweight(pset.get<double>("badchannelweight"))
22  , neighbors(pset.get<unsigned int>("neighbors"))
23 {
24  // square epsilon to eliminate the use of sqrt later on
25  epsilon *= epsilon;
26 }
27 
28 //----------------------------------------------------------
30  art::FindManyP<recob::Hit>& hitFromSp)
31 {
32 
33  if (badchannelmap.empty()) {
34  lariov::ChannelStatusProvider const& channelStatus =
37  // build a map to count bad channels around each wire ID
38  for (auto& pid : geom->Iterate<geo::PlaneID>()) {
39  for (auto& wid1 : geom->Iterate<geo::WireID>(pid)) {
40  unsigned int nbadchs = 0;
41  for (auto& wid2 : geom->Iterate<geo::WireID>(pid)) {
42  if (wid1 == wid2) continue;
43  if (lar::util::absDiff(wid1.Wire, wid2.Wire) < neighbors &&
44  !channelStatus.IsGood(geom->PlaneWireToChannel(wid2)))
45  ++nbadchs;
46  }
47  badchannelmap[wid1] = nbadchs;
48  }
49  }
50  std::cout << "Done building bad channel map." << std::endl;
51  }
52 
53  points.clear();
54  for (auto& spt : sps) {
55  point_t point;
56  point.sp = spt;
57  point.cluster_id = UNCLASSIFIED;
58  // count bad channels
59  point.nbadchannels = 0;
60  auto& hits = hitFromSp.at(spt.key());
61  for (auto& hit : hits) {
62  point.nbadchannels += badchannelmap[hit->WireID()];
63  }
64  points.push_back(point);
65  }
66 }
67 
69 {
70  node_t* n = (node_t*)calloc(1, sizeof(node_t));
71  if (n == NULL)
72  perror("Failed to allocate node.");
73  else {
74  n->index = index;
75  n->next = NULL;
76  }
77  return n;
78 }
79 
81 {
82  node_t* n = create_node(index);
83  if (n == NULL) {
84  free(en);
85  return FAILURE;
86  }
87  if (en->head == NULL) {
88  en->head = n;
89  en->tail = n;
90  }
91  else {
92  en->tail->next = n;
93  en->tail = n;
94  }
95  ++(en->num_members);
96  return SUCCESS;
97 }
98 
100 {
102  if (en == NULL) {
103  perror("Failed to allocate epsilon neighbours.");
104  return en;
105  }
106  for (unsigned int i = 0; i < points.size(); ++i) {
107  if (i == index) continue;
108  if (dist(&points[index], &points[i]) > epsilon)
109  continue;
110  else {
111  if (append_at_end(i, en) == FAILURE) {
113  en = NULL;
114  break;
115  }
116  }
117  }
118  return en;
119 }
120 
122 {
123  if (en) {
124  node_t *t, *h = en->head;
125  while (h) {
126  t = h->next;
127  free(h);
128  h = t;
129  }
130  free(en);
131  }
132 }
133 
135 {
136  unsigned int i, cluster_id = 0;
137  for (i = 0; i < points.size(); ++i) {
138  if (points[i].cluster_id == UNCLASSIFIED) {
139  if (expand(i, cluster_id) == CORE_POINT) ++cluster_id;
140  }
141  }
142 }
143 
144 int cluster::DBScan3DAlg::expand(unsigned int index, unsigned int cluster_id)
145 {
146  int return_value = NOT_CORE_POINT;
148  if (seeds == NULL) return FAILURE;
149 
150  if (seeds->num_members < minpts)
151  points[index].cluster_id = NOISE;
152  else {
153  points[index].cluster_id = cluster_id;
154  node_t* h = seeds->head;
155  while (h) {
156  points[h->index].cluster_id = cluster_id;
157  h = h->next;
158  }
159 
160  h = seeds->head;
161  while (h) {
162  spread(h->index, seeds, cluster_id);
163  h = h->next;
164  }
165 
166  return_value = CORE_POINT;
167  }
169  return return_value;
170 }
171 
172 int cluster::DBScan3DAlg::spread(unsigned int index,
174  unsigned int cluster_id)
175 {
177  if (spread == NULL) return FAILURE;
178  if (spread->num_members >= minpts) {
179  node_t* n = spread->head;
180  point_t* d;
181  while (n) {
182  d = &points[n->index];
183  if (d->cluster_id == NOISE || d->cluster_id == UNCLASSIFIED) {
184  if (d->cluster_id == UNCLASSIFIED) {
185  if (append_at_end(n->index, seeds) == FAILURE) {
187  return FAILURE;
188  }
189  }
190  d->cluster_id = cluster_id;
191  }
192  n = n->next;
193  }
194  }
195 
197  return SUCCESS;
198 }
199 
201 {
202  Double32_t const* a_xyz = a->sp->XYZ();
203  Double32_t const* b_xyz = b->sp->XYZ();
204  auto const nbadchannels = a->nbadchannels + b->nbadchannels;
205  float const dx = a_xyz[0] - b_xyz[0];
206  float const dy = a_xyz[1] - b_xyz[1];
207  float const dz = a_xyz[2] - b_xyz[2];
208  float const dist = cet::sum_of_squares(dx, dy, dz) - cet::square(nbadchannels * badchannelweight);
209  // Do not return a distance smaller than 0.
210  return std::max(dist, 0.f);
211 }
std::map< geo::WireID, int > badchannelmap
Definition: DBScan3DAlg.h:93
details::range_type< T > Iterate() const
Initializes the specified ID with the ID of the first cryostat.
Definition: GeometryCore.h:541
unsigned int minpts
Definition: DBScan3DAlg.h:90
Functions to help with numbers.
art::Ptr< recob::SpacePoint > sp
Definition: DBScan3DAlg.h:58
unsigned int index
Definition: DBScan3DAlg.h:65
node_t * next
Definition: DBScan3DAlg.h:66
Declaration of signal hit object.
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
epsilon_neighbours_t * get_epsilon_neighbours(unsigned int index)
Definition: DBScan3DAlg.cxx:99
unsigned int num_members
Definition: DBScan3DAlg.h:71
TFile f
Definition: plotHisto.C:6
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
Access the description of detector geometry.
void hits()
Definition: readHits.C:15
int cluster_id
Definition: DBScan3DAlg.h:60
void init(const std::vector< art::Ptr< recob::SpacePoint >> &sps, art::FindManyP< recob::Hit > &hitFromSp)
Definition: DBScan3DAlg.cxx:29
#define UNCLASSIFIED
Definition: DBScan3DAlg.h:33
Float_t d
Definition: plot.C:235
float dist(point_t *a, point_t *b) const
int expand(unsigned int index, unsigned int cluster_id)
const Double32_t * XYZ() const
Definition: SpacePoint.h:78
#define NOT_CORE_POINT
Definition: DBScan3DAlg.h:37
Description of geometry of one entire detector.
Definition: GeometryCore.h:119
Detector simulation of raw signals on wires.
node_t * create_node(unsigned int index)
Definition: DBScan3DAlg.cxx:68
#define CORE_POINT
Definition: DBScan3DAlg.h:36
int append_at_end(unsigned int index, epsilon_neighbours_t *en)
Definition: DBScan3DAlg.cxx:80
std::vector< TrajPoint > seeds
Definition: DataStructs.cxx:14
#define FAILURE
Definition: DBScan3DAlg.h:40
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
decltype(auto) get(T &&obj)
ADL-aware version of std::to_string.
Definition: StdUtils.h:120
DBScan3DAlg(fhicl::ParameterSet const &pset)
Definition: DBScan3DAlg.cxx:18
constexpr auto absDiff(A const &a, B const &b)
Returns the absolute value of the difference between two values.
Definition: NumericUtils.h:69
Char_t n[5]
unsigned int neighbors
Definition: DBScan3DAlg.h:92
std::vector< point_t > points
Definition: DBScan3DAlg.h:82
int spread(unsigned int index, epsilon_neighbours_t *seeds, unsigned int cluster_id)
unsigned int nbadchannels
Definition: DBScan3DAlg.h:59
#define NOISE
Definition: DBScan3DAlg.h:34
art framework interface to geometry description
void destroy_epsilon_neighbours(epsilon_neighbours_t *en)
#define SUCCESS
Definition: DBScan3DAlg.h:39