LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
DBScan3DAlg.cxx
Go to the documentation of this file.
4 #include "larcorealg/CoreUtils/NumericUtils.h" // util::absDiff()
5 #include "larevt/CalibrationDBI/Interface/ChannelStatusService.h"
6 #include "larevt/CalibrationDBI/Interface/ChannelStatusProvider.h"
7 
8 #include <limits.h>
9 #include <math.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 
14  : epsilon(pset.get< float >("epsilon"))
15  , minpts(pset.get<unsigned int>("minpts"))
16  , badchannelweight(pset.get<double>("badchannelweight"))
17  , neighbors(pset.get<unsigned int>("neighbors"))
18 {
19  // square epsilon to eliminate the use of sqrt later on
20  epsilon *= epsilon;
21 }
22 
23 //----------------------------------------------------------
25 {
26 }
27 
28 //----------------------------------------------------------
30 {
31 
32  if (badchannelmap.empty()){
33  lariov::ChannelStatusProvider const& channelStatus = art::ServiceHandle<lariov::ChannelStatusService>()->GetProvider();
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) {
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  }
172  return return_value;
173 }
174 
175 int cluster::DBScan3DAlg::spread(unsigned int index,
177  unsigned int cluster_id)
178 {
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) {
194  return FAILURE;
195  }
196  }
197  d->cluster_id = cluster_id;
198  }
199  n = n->next;
200  }
201  }
202 
204  return SUCCESS;
205 }
206 
208 {
209  float dx = a->sp->XYZ()[0] - b->sp->XYZ()[0];
210  float dy = a->sp->XYZ()[1] - b->sp->XYZ()[1];
211  float dz = a->sp->XYZ()[2] - b->sp->XYZ()[2];
212  float dist = dx*dx + dy*dy + dz*dz - (a->nbadchannels + b->nbadchannels)*(a->nbadchannels + b->nbadchannels)*badchannelweight*badchannelweight;
213  //std::cout<<dx*dx + dy*dy + dz*dz<<" "<<(a->nbadchannels + b->nbadchannels)*(a->nbadchannels + b->nbadchannels)*badchannelweight*badchannelweight<<std::endl;
214  if ( dist < 0 ) dist = 0;
215  return dist;
216 }
std::map< geo::WireID, int > badchannelmap
Definition: DBScan3DAlg.h:94
unsigned int minpts
Definition: DBScan3DAlg.h:91
Functions to help with numbers.
art::Ptr< recob::SpacePoint > sp
Definition: DBScan3DAlg.h:55
unsigned int index
Definition: DBScan3DAlg.h:62
node_t * next
Definition: DBScan3DAlg.h:63
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:68
float dist(point_t *a, point_t *b)
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.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
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.
void hits()
Definition: readHits.C:15
int cluster_id
Definition: DBScan3DAlg.h:57
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:237
int expand(unsigned int index, unsigned int cluster_id)
const Double32_t * XYZ() const
Definition: SpacePoint.h:65
#define NOT_CORE_POINT
Definition: DBScan3DAlg.h:37
Description of geometry of one entire detector.
Detector simulation of raw signals on wires.
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:11
#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:13
Char_t n[5]
unsigned int neighbors
Definition: DBScan3DAlg.h:93
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:56
#define NOISE
Definition: DBScan3DAlg.h:34
void destroy_epsilon_neighbours(epsilon_neighbours_t *en)
#define SUCCESS
Definition: DBScan3DAlg.h:39