All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DBScan3DAlg.cxx
Go to the documentation of this file.
6 #include "larcorealg/CoreUtils/NumericUtils.h" // util::absDiff()
9 
10 #include "art/Framework/Services/Registry/ServiceHandle.h"
11 #include "cetlib/pow.h"
12 #include "fhiclcpp/ParameterSet.h"
13 
14 #include <algorithm>
15 #include <stdio.h>
16 #include <stdlib.h>
17 
18 cluster::DBScan3DAlg::DBScan3DAlg(fhicl::ParameterSet const& pset)
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 //----------------------------------------------------------
29 void cluster::DBScan3DAlg::init(const std::vector<art::Ptr<recob::SpacePoint>>& sps, art::FindManyP<recob::Hit>& hitFromSp)
30 {
31 
32  if (badchannelmap.empty()){
33  lariov::ChannelStatusProvider const& channelStatus = art::ServiceHandle<lariov::ChannelStatusService const>()->GetProvider();
34  geo::GeometryCore const* geom = &*(art::ServiceHandle<geo::Geometry const>());
35  // build a map to count bad channels around each wire ID
36  for (auto &pid : geom->IteratePlaneIDs()){
37  for (auto& wid1: geom->IterateWireIDs(pid)) {
38  unsigned int nbadchs = 0;
39  for (auto& wid2: geom->IterateWireIDs(pid)) {
40  if (wid1==wid2) continue;
41  if (util::absDiff(wid1.Wire,wid2.Wire)<neighbors &&
42  !channelStatus.IsGood(geom->PlaneWireToChannel(wid2))) ++nbadchs;
43  }
44  badchannelmap[wid1] = nbadchs;
45  }
46  }
47  std::cout<<"Done building bad channel map."<<std::endl;
48  }
49 
50  points.clear();
51  for (auto& spt : sps){
52  point_t point;
53  point.sp = spt;
54  point.cluster_id = UNCLASSIFIED;
55  // count bad channels
56  point.nbadchannels = 0;
57  auto &hits = hitFromSp.at(spt.key());
58  for (auto & hit : hits){
59  point.nbadchannels += badchannelmap[hit->WireID()];
60  }
61  points.push_back(point);
62  }
63 }
64 
66 {
67  node_t *n = (node_t *) calloc(1, sizeof(node_t));
68  if (n == NULL)
69  perror("Failed to allocate node.");
70  else {
71  n->index = index;
72  n->next = NULL;
73  }
74  return n;
75 }
76 
77 int cluster::DBScan3DAlg::append_at_end(unsigned int index,
79 {
80  node_t *n = create_node(index);
81  if (n == NULL) {
82  free(en);
83  return FAILURE;
84  }
85  if (en->head == NULL) {
86  en->head = n;
87  en->tail = n;
88  } else {
89  en->tail->next = n;
90  en->tail = n;
91  }
92  ++(en->num_members);
93  return SUCCESS;
94 }
95 
97 {
99  calloc(1, sizeof(epsilon_neighbours_t));
100  if (en == NULL) {
101  perror("Failed to allocate epsilon neighbours.");
102  return en;
103  }
104  for (unsigned int i = 0; i < points.size(); ++i) {
105  if (i == index)
106  continue;
107  if (dist(&points[index], &points[i]) > epsilon)
108  continue;
109  else {
110  if (append_at_end(i, en) == FAILURE) {
111  destroy_epsilon_neighbours(en);
112  en = NULL;
113  break;
114  }
115  }
116  }
117  return en;
118 }
119 
121 {
122  if (en) {
123  node_t *t, *h = en->head;
124  while (h) {
125  t = h->next;
126  free(h);
127  h = t;
128  }
129  free(en);
130  }
131 }
132 
134 {
135  unsigned int i, cluster_id = 0;
136  for (i = 0; i < points.size(); ++i) {
137  if (points[i].cluster_id == UNCLASSIFIED) {
138  if (expand(i, cluster_id) == CORE_POINT)
139  ++cluster_id;
140  }
141  }
142 }
143 
144 int cluster::DBScan3DAlg::expand(unsigned int index,
145  unsigned int cluster_id)
146 {
147  int return_value = NOT_CORE_POINT;
149  get_epsilon_neighbours(index);
150  if (seeds == NULL)
151  return FAILURE;
152 
153  if (seeds->num_members < minpts)
154  points[index].cluster_id = NOISE;
155  else {
156  points[index].cluster_id = cluster_id;
157  node_t *h = seeds->head;
158  while (h) {
159  points[h->index].cluster_id = cluster_id;
160  h = h->next;
161  }
162 
163  h = seeds->head;
164  while (h) {
165  spread(h->index, seeds, cluster_id);
166  h = h->next;
167  }
168 
169  return_value = CORE_POINT;
170  }
171  destroy_epsilon_neighbours(seeds);
172  return return_value;
173 }
174 
175 int cluster::DBScan3DAlg::spread(unsigned int index,
177  unsigned int cluster_id)
178 {
179  epsilon_neighbours_t *spread =
180  get_epsilon_neighbours(index);
181  if (spread == NULL)
182  return FAILURE;
183  if (spread->num_members >= minpts) {
184  node_t *n = spread->head;
185  point_t *d;
186  while (n) {
187  d = &points[n->index];
188  if (d->cluster_id == NOISE ||
189  d->cluster_id == UNCLASSIFIED) {
190  if (d->cluster_id == UNCLASSIFIED) {
191  if (append_at_end(n->index, seeds)
192  == FAILURE) {
193  destroy_epsilon_neighbours(spread);
194  return FAILURE;
195  }
196  }
197  d->cluster_id = cluster_id;
198  }
199  n = n->next;
200  }
201  }
202 
203  destroy_epsilon_neighbours(spread);
204  return SUCCESS;
205 }
206 
208 {
209  Double32_t const* a_xyz = a->sp->XYZ();
210  Double32_t const* b_xyz = b->sp->XYZ();
211  auto const nbadchannels = a->nbadchannels + b->nbadchannels;
212  float const dx = a_xyz[0] - b_xyz[0];
213  float const dy = a_xyz[1] - b_xyz[1];
214  float const dz = a_xyz[2] - b_xyz[2];
215  float const dist = cet::sum_of_squares(dx, dy, dz) - cet::square(nbadchannels * badchannelweight);
216  // Do not return a distance smaller than 0.
217  return std::max(dist, 0.f);
218 }
Functions to help with numbers.
art::Ptr< recob::SpacePoint > sp
Definition: DBScan3DAlg.h:56
unsigned int index
Definition: DBScan3DAlg.h:63
node_t * next
Definition: DBScan3DAlg.h:64
Declaration of signal hit object.
epsilon_neighbours_t * get_epsilon_neighbours(unsigned int index)
Definition: DBScan3DAlg.cxx:96
unsigned int num_members
Definition: DBScan3DAlg.h:69
process_name hit
Definition: cheaterreco.fcl:51
process_name gaushit a
IteratorBox< plane_id_iterator,&GeometryCore::begin_plane_id,&GeometryCore::end_plane_id > IteratePlaneIDs() const
Enables ranged-for loops on all plane IDs of the detector.
while getopts h
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
Access the description of detector geometry.
IteratorBox< wire_id_iterator,&GeometryCore::begin_wire_id,&GeometryCore::end_wire_id > IterateWireIDs() const
Enables ranged-for loops on all wire IDs of the detector.
int cluster_id
Definition: DBScan3DAlg.h:58
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 dist(point_t *a, point_t *b) const
virtual bool IsGood(raw::ChannelID_t channel) const
Returns whether the specified channel is physical and good.
int expand(unsigned int index, unsigned int cluster_id)
#define NOT_CORE_POINT
Definition: DBScan3DAlg.h:37
Class providing information about the quality of channels.
Description of geometry of one entire detector.
constexpr auto absDiff(A const &a, B const &b)
Returns the absolute value of the difference between two values.
Definition: NumericUtils.h:43
node_t * create_node(unsigned int index)
Definition: DBScan3DAlg.cxx:65
#define CORE_POINT
Definition: DBScan3DAlg.h:36
int append_at_end(unsigned int index, epsilon_neighbours_t *en)
Definition: DBScan3DAlg.cxx:77
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.
DBScan3DAlg(fhicl::ParameterSet const &pset)
Definition: DBScan3DAlg.cxx:18
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
Interface for experiment-specific channel quality info provider.
int spread(unsigned int index, epsilon_neighbours_t *seeds, unsigned int cluster_id)
Interface for experiment-specific service for channel quality info.
unsigned int nbadchannels
Definition: DBScan3DAlg.h:57
#define NOISE
Definition: DBScan3DAlg.h:34
art framework interface to geometry description
BEGIN_PROLOG could also be cout
void destroy_epsilon_neighbours(epsilon_neighbours_t *en)
#define SUCCESS
Definition: DBScan3DAlg.h:39