LArSoft  v10_04_05
Liquid Argon Software toolkit - https://larsoft.org/
DBScan3DAlg.cxx
Go to the documentation of this file.
3 #include "larcorealg/CoreUtils/NumericUtils.h" // util::absDiff()
6 #include "larevt/CalibrationDBI/Interface/ChannelStatusProvider.h"
7 #include "larevt/CalibrationDBI/Interface/ChannelStatusService.h"
8 
10 #include "cetlib/pow.h"
11 #include "fhiclcpp/ParameterSet.h"
12 
13 #include <algorithm>
14 #include <stdio.h>
15 #include <stdlib.h>
16 
18  : epsilon(pset.get<float>("epsilon"))
19  , minpts(pset.get<unsigned int>("minpts"))
20  , badchannelweight(pset.get<double>("badchannelweight"))
21  , neighbors(pset.get<unsigned int>("neighbors"))
22 {
23  // square epsilon to eliminate the use of sqrt later on
24  epsilon *= epsilon;
25 }
26 
27 //----------------------------------------------------------
29  art::FindManyP<recob::Hit>& hitFromSp)
30 {
31  if (badchannelmap.empty()) {
32  lariov::ChannelStatusProvider const& channelStatus =
34  geo::WireReadoutGeom const& wireReadoutGeom =
36  // build a map to count bad channels around each wire ID
37  for (auto& pid : wireReadoutGeom.Iterate<geo::PlaneID>()) {
38  for (auto& wid1 : wireReadoutGeom.Iterate<geo::WireID>(pid)) {
39  unsigned int nbadchs = 0;
40  for (auto& wid2 : wireReadoutGeom.Iterate<geo::WireID>(pid)) {
41  if (wid1 == wid2) continue;
42  if (lar::util::absDiff(wid1.Wire, wid2.Wire) < neighbors &&
43  !channelStatus.IsGood(wireReadoutGeom.PlaneWireToChannel(wid2)))
44  ++nbadchs;
45  }
46  badchannelmap[wid1] = nbadchs;
47  }
48  }
49  std::cout << "Done building bad channel map." << std::endl;
50  }
51 
52  points.clear();
53  for (auto& spt : sps) {
54  point_t point;
55  point.sp = spt;
56  point.cluster_id = UNCLASSIFIED;
57  // count bad channels
58  point.nbadchannels = 0;
59  auto& hits = hitFromSp.at(spt.key());
60  for (auto& hit : hits) {
61  point.nbadchannels += badchannelmap[hit->WireID()];
62  }
63  points.push_back(point);
64  }
65 }
66 
68 {
69  node_t* n = (node_t*)calloc(1, sizeof(node_t));
70  if (n == nullptr)
71  perror("Failed to allocate node.");
72  else {
73  n->index = index;
74  n->next = nullptr;
75  }
76  return n;
77 }
78 
80 {
81  node_t* n = create_node(index);
82  if (n == nullptr) {
83  free(en);
84  return FAILURE;
85  }
86  if (en->head == nullptr) {
87  en->head = n;
88  en->tail = n;
89  }
90  else {
91  en->tail->next = n;
92  en->tail = n;
93  }
94  ++(en->num_members);
95  return SUCCESS;
96 }
97 
99 {
101  if (en == nullptr) {
102  perror("Failed to allocate epsilon neighbours.");
103  return en;
104  }
105  for (unsigned int i = 0; i < points.size(); ++i) {
106  if (i == index) continue;
107  if (dist(&points[index], &points[i]) > epsilon)
108  continue;
109  else {
110  if (append_at_end(i, en) == FAILURE) {
112  en = nullptr;
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) ++cluster_id;
139  }
140  }
141 }
142 
143 int cluster::DBScan3DAlg::expand(unsigned int index, unsigned int cluster_id)
144 {
145  int return_value = NOT_CORE_POINT;
147  if (seeds == nullptr) return FAILURE;
148 
149  if (seeds->num_members < minpts)
150  points[index].cluster_id = NOISE;
151  else {
152  points[index].cluster_id = cluster_id;
153  node_t* h = seeds->head;
154  while (h) {
155  points[h->index].cluster_id = cluster_id;
156  h = h->next;
157  }
158 
159  h = seeds->head;
160  while (h) {
161  spread(h->index, seeds, cluster_id);
162  h = h->next;
163  }
164 
165  return_value = CORE_POINT;
166  }
168  return return_value;
169 }
170 
171 int cluster::DBScan3DAlg::spread(unsigned int index,
173  unsigned int cluster_id)
174 {
176  if (spread == nullptr) return FAILURE;
177  if (spread->num_members >= minpts) {
178  node_t* n = spread->head;
179  point_t* d;
180  while (n) {
181  d = &points[n->index];
182  if (d->cluster_id == NOISE || d->cluster_id == UNCLASSIFIED) {
183  if (d->cluster_id == UNCLASSIFIED) {
184  if (append_at_end(n->index, seeds) == FAILURE) {
186  return FAILURE;
187  }
188  }
189  d->cluster_id = cluster_id;
190  }
191  n = n->next;
192  }
193  }
194 
196  return SUCCESS;
197 }
198 
200 {
201  Double32_t const* a_xyz = a->sp->XYZ();
202  Double32_t const* b_xyz = b->sp->XYZ();
203  auto const nbadchannels = a->nbadchannels + b->nbadchannels;
204  float const dx = a_xyz[0] - b_xyz[0];
205  float const dy = a_xyz[1] - b_xyz[1];
206  float const dz = a_xyz[2] - b_xyz[2];
207  float const dist = cet::sum_of_squares(dx, dy, dz) - cet::square(nbadchannels * badchannelweight);
208  // Do not return a distance smaller than 0.
209  return std::max(dist, 0.f);
210 }
std::map< geo::WireID, int > badchannelmap
Definition: DBScan3DAlg.h:93
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:364
epsilon_neighbours_t * get_epsilon_neighbours(unsigned int index)
Definition: DBScan3DAlg.cxx:98
unsigned int num_members
Definition: DBScan3DAlg.h:71
cout<< "Opened file "<< fin<< " ixs= "<< ixs<< endl;if(ixs==0) hhh=(TH1F *) fff-> Get("h1")
Definition: AddMC.C:8
TFile f
Definition: plotHisto.C:6
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
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:28
Interface for a class providing readout channel mapping to geometry.
#define UNCLASSIFIED
Definition: DBScan3DAlg.h:33
Float_t d
Definition: plot.C:235
float dist(point_t *a, point_t *b) const
virtual raw::ChannelID_t PlaneWireToChannel(WireID const &wireID) const =0
Returns the channel ID a wire is connected to.
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
Detector simulation of raw signals on wires.
node_t * create_node(unsigned int index)
Definition: DBScan3DAlg.cxx:67
#define CORE_POINT
Definition: DBScan3DAlg.h:36
int append_at_end(unsigned int index, epsilon_neighbours_t *en)
Definition: DBScan3DAlg.cxx:79
std::vector< TrajPoint > seeds
Definition: DataStructs.cxx:14
#define FAILURE
Definition: DBScan3DAlg.h:40
decltype(auto) get(T &&obj)
ADL-aware version of std::to_string.
Definition: StdUtils.h:120
DBScan3DAlg(fhicl::ParameterSet const &pset)
Definition: DBScan3DAlg.cxx:17
constexpr auto absDiff(A const &a, B const &b)
Returns the absolute value of the difference between two values.
Definition: NumericUtils.h:69
range_type< T > Iterate() const
Definition: Iterable.h:121
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
void destroy_epsilon_neighbours(epsilon_neighbours_t *en)
#define SUCCESS
Definition: DBScan3DAlg.h:39