test_rayclustering.cxx
Go to the documentation of this file.
4 #include "WireCellUtil/Testing.h"
5 #include "WireCellUtil/Logging.h"
6 
7 
8 #include <math.h>
9 
10 #include <random>
11 #include <fstream>
12 #include <string>
13 
14 using namespace WireCell;
15 using namespace WireCell::Waveform;
16 using namespace WireCell::RayGrid;
17 using namespace std;
18 using spdlog::debug;
19 using spdlog::info;
20 using spdlog::warn;
21 
22 const int ndepos = 10;
23 const int neles = 10;
24 const double pitch_magnitude = 5;
25 const double gaussian = 3;
26 const double border = 10;
27 const double width = 100;
28 const double height = 100;
29 
30 // local helper codes
31 #include "raygrid.h"
32 
33 #include "raygrid_dump.h"
34 
35 static
36 std::vector<Point> make_points(std::default_random_engine& generator, double x)
37 {
38  std::vector<Point> points;
39  std::uniform_real_distribution<double> position(0,std::max(width,height));
40  std::normal_distribution<double> spread(0.0, gaussian);
41  for (int idepo=0;idepo<ndepos;++idepo) {
42  Point cp(0, position(generator), position(generator));
43  for (int iele=0; iele<neles; ++iele) {
44  const Point delta(x, spread(generator), spread(generator));
45  const Point pt = cp + delta;
46  if (pt.y() < -border or pt.y() > height+border or
47  pt.z() < -border or pt.z() > width+border) {
48  warn("Rejecting far away point: {} + {}" , cp, delta);
49  continue;
50  }
51  points.push_back(cp+delta);
52  }
53  }
54  return points;
55 }
56 
57 
58 typedef std::vector<Activity::value_t> measure_t;
59 
60 static
61 std::vector<measure_t> make_measures(Coordinates& coords, const std::vector<Point>& points)
62 {
63  int nlayers = coords.nlayers();
64  std::vector<measure_t> measures(nlayers);
65  const auto& pitches = coords.pitch_dirs();
66  const auto& centers = coords.centers();
67  const auto& pitch_mags = coords.pitch_mags();
68 
69  for (size_t ipt=0; ipt<points.size(); ++ipt ) {
70  const auto& p = points[ipt];
71  for (int ilayer = 0; ilayer<nlayers; ++ilayer) {
72  const auto& pit = pitches[ilayer];
73  const auto& cen = centers[ilayer];
74  const auto rel = p-cen;
75  const int pit_ind = pit.dot(rel)/pitch_mags[ilayer];
76  if (pit_ind < 0) {
77  warn("Negative pitch indices not allowed, got {} from ilayer {} ipt {} for point {}",
78  pit_ind, ilayer, ipt, p);
79  continue;
80  }
81  if (ilayer <= 1) {
82  if (pit_ind >= 1 or pit_ind < 0) {
83  debug("mm: pit_ind={} with ipt={}", pit_ind, ipt);
84  if (pit_ind == 1) {
85  debug("\tpit={} cen={} rel={}", pit, cen, rel);
86  }
87  continue;
88  }
89  }
90  measure_t& m = measures[ilayer];
91  if ((int)m.size() <= pit_ind) {
92  debug("resize for ipt {} ilayer {} from {} to {}", ipt, ilayer, m.size(), pit_ind+1);
93  m.resize(pit_ind+1, 0.0);
94  debug("done");
95  }
96 
97  debug("adding to pit_ind {} ilayer {} ipt {}", pit_ind, ilayer, ipt);
98  m[pit_ind] += 1.0;
99  debug("valud: {}", m[pit_ind]);
100  }
101  }
102 
103  return measures;
104 }
105 
106 static
107 activities_t make_activities(Coordinates& coords, std::vector<measure_t>& measures)
108 {
109  int nlayers = coords.nlayers();
110  activities_t activities;
111  for (int ilayer = 0; ilayer<nlayers; ++ilayer) {
112  auto& m = measures[ilayer];
113  info("Make activity for layer: {}: {}", ilayer, m.size());
114  Activity activity(ilayer, {m.begin(), m.end()});
115  Assert(!activity.empty());
116  activities.push_back(activity);
117  }
118  return activities;
119 }
120 
121 struct Chirp {
122  const blobs_t& one;
123  const blobs_t& two;
125 
126  typedef typename std::unordered_set<std::size_t> indices_t;
127  indices_t *sel1;
128  indices_t *sel2;
129 
130  Chirp(const blobs_t& one, const blobs_t& two,
131  Coordinates& coords, JsonEvent& dumper)
132  : one(one)
133  , two(two)
134  , coords(coords)
135  , sel1(new indices_t)
136  , sel2(new indices_t)
137  {}
138 
139  bool in(const blobref_t& a, const blobref_t& b) {
140  if (surrounding(a, b)) {
141  return true;
142  }
143 
144  const auto& astrips = a->strips();
145  const int nlayers = astrips.size();
146 
147  // if at least one corner of b is in side a, return true
148  for (const auto& c : b->corners()) {
149  int found = 0;
150  // go through each layer of blob a
151  for (layer_index_t layer = 0; layer < nlayers; ++layer) {
152  const auto& astrip = astrips[layer];
153  if (layer == c.first.layer) {
154  info("L{} A: {} {}", layer, astrip, c);
155  if (astrip.on(c.first.grid)) {
156  info("\ton with found={} nlayers={}", found, nlayers);
157  ++found;
158  continue;
159  }
160  info("\toff with found={} nlayers={}", found, nlayers);
161  break;
162  }
163  if (layer == c.second.layer) {
164  info("L{} A: {} {}", layer, astrip, c);
165  if (astrip.on(c.second.grid)) {
166  info("\ton with found={} nlayers={}", found, nlayers);
167  ++found;
168  continue;
169  }
170  info("\toff with found={} nlayers={}",found, nlayers);
171  break;
172  }
173  const double ploc = coords.pitch_location(c.first, c.second, layer);
174  const int pind = coords.pitch_index(ploc, layer);
175 
176  info("L{} A: {} pind={} ploc={} {}", layer, astrip, pind, ploc, c);
177 
178  if (astrip.in(pind)) {
179  info("\tin with found={} nlayers={}", found, nlayers);
180  ++found;
181  }
182  else {
183  info("\tout with found={} nlayers={}", found, nlayers);
184  break;
185  }
186  }
187  if (found == nlayers) {
188  return true;
189  }
190  }
191  return false;
192  }
193 
194  void operator()(const blobref_t& a, const blobref_t& b) {
195 
196 
197  const std::size_t d1 = a-one.begin();
198  const std::size_t d2 = b-two.begin();
199 
200  info("overlap: a{} and b{}", d1, d2);
201  info("\tblob a #{}: {}", d1, a->as_string());
202  info("\tblob b #{}: {}", d2, b->as_string());
203 
204  if (!this->in(a,b)) {
205  warn("NO CONTAINED CORNERS");
206  //Assert(this->in(a,b));
207  }
208 
209  sel1->insert(d1);
210  sel2->insert(d2);
211  }
212 
213  void dump(JsonEvent& dumper) {
214  int number = 0;
215  for (const auto ind : *sel1) {
216  const auto& br = one[ind];
217  dumper(br, 10.0, 1.0, 1, ind);
218  ++number;
219  }
220  number = 0;
221  for (const auto ind : *sel2) {
222  const auto& br = two[ind];
223  dumper(br, 20.0, 1.0, 2, ind);
224  ++number;
225  }
226 
227  return;
228  }
229 };
230 
231 static
233 {
234  for (const auto& blob : blobs) {
235  const auto& strips = blob.strips();
236  Assert(strips[0].bounds.first == 0);
237  Assert(strips[0].bounds.second == 1);
238  Assert(strips[1].bounds.first == 0);
239  Assert(strips[1].bounds.second == 1);
240  }
241 }
242 
243 
244 int main(int argc, char* argv[])
245 {
246  auto raypairs = make_raypairs(width, height, pitch_magnitude);
247 
248  Coordinates coords(raypairs);
249 
250  Tiling tiling(coords);
251 
252  std::default_random_engine generator;
253  std::vector<Point> pts1 = make_points(generator, 10.0);
254  std::vector<Point> pts2 = make_points(generator, 20.0);
255 
256  std::vector<measure_t> meas1 = make_measures(coords, pts1);
257  std::vector<measure_t> meas2 = make_measures(coords, pts2);
258 
259  auto act1 = make_activities(coords, meas1);
260  auto act2 = make_activities(coords, meas2);
261 
262  auto blobs1 = make_blobs(coords, act1);
263  auto blobs2 = make_blobs(coords, act2);
264 
265  test_blobs(blobs1);
266  test_blobs(blobs2);
267 
268  // fixme: blobs are missing these features:
269  // - sort corners
270  // - apply X offset
271  // - assign some value
272  // this is maybe best done converting from Blob to another rep
273 
274  JsonEvent dumper(coords);
275  for (const auto& pt : pts1) { dumper(pt); }
276  for (const auto& pt : pts2) { dumper(pt); }
277  Chirp chirp(blobs1, blobs2, coords, dumper);
278  associator_t chirpf = chirp;
279  associate(blobs1, blobs2, chirpf);
280 
281  chirp.dump(dumper);
282 
283  std::string fout = argv[0];
284  fout += ".json";
285  dumper.dump(fout);
286 
287  return 0;
288 }
289 
static const double m
Definition: Units.h:79
void dump(JsonEvent &dumper)
indices_t * sel2
std::vector< Activity::value_t > measure_t
const double width
void dump(const std::string &filename)
Definition: raygrid_dump.h:52
const double gaussian
void info(const char *fmt, const Args &...args)
Definition: spdlog.h:189
D3Vector< double > Point
A 3D Cartesian point in double precision.
Definition: Point.h:15
std::string string
Definition: nybbler.cc:12
double pitch_location(const coordinate_t &one, const coordinate_t &two, layer_index_t other) const
Definition: RayGrid.cxx:133
STL namespace.
const double height
const int neles
static std::vector< Point > make_points(std::default_random_engine &generator, double x)
std::unordered_set< std::size_t > indices_t
def blobs(cm, hist)
Definition: plots.py:79
const double pitch_magnitude
const vector_array1d_t & pitch_dirs() const
Definition: RayGrid.h:88
#define Assert
Definition: Testing.h:7
const blobs_t & two
std::function< void(blobref_t &a, blobref_t &b)> associator_t
Definition: RayClustering.h:44
def activity(output, slices, slice_line, cluster_tap_file)
Definition: main.py:144
int pitch_index(double pitch, layer_index_t layer) const
Definition: RayGrid.h:82
static std::vector< measure_t > make_measures(Coordinates &coords, const std::vector< Point > &points)
blobs_t::const_iterator blobref_t
Definition: RayClustering.h:13
const vector_array1d_t & centers() const
Definition: RayGrid.h:89
const std::vector< double > & pitch_mags() const
Definition: RayGrid.h:87
Chirp(const blobs_t &one, const blobs_t &two, Coordinates &coords, JsonEvent &dumper)
static int max(int a, int b)
const double border
generator
Definition: train.py:468
void warn(const char *fmt, const Args &...args)
Definition: spdlog.h:195
BoundingBox bounds(int x, int y, int w, int h)
Definition: main.cpp:37
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
Definition: Main.h:22
static activities_t make_activities(Coordinates &coords, std::vector< measure_t > &measures)
p
Definition: test.py:223
std::vector< Blob > blobs_t
Definition: RayTiling.h:134
static void test_blobs(const blobs_t &blobs)
int main(int argc, char *argv[])
Coordinates & coords
const blobs_t & one
bool in(const blobref_t &a, const blobref_t &b)
void debug(const char *fmt, const Args &...args)
Definition: spdlog.h:183
static bool * b
Definition: config.cpp:1043
blobs_t make_blobs(const Coordinates &coords, const activities_t &activities)
Definition: RayTiling.cxx:371
indices_t * sel1
bool associate(const std::string &classname, WireCell::INamedFactory *factory)
Associate a factory with the type it makes.
Definition: NamedFactory.h:210
list x
Definition: train.py:276
std::vector< Activity > activities_t
Definition: RayTiling.h:105
const int ndepos
ray_pair_vector_t make_raypairs(double width=100, double height=100, double pitch_mag=3, double angle=60.0 *M_PI/180.0)
Definition: raygrid.h:5
bool surrounding(const blobref_t &a, const blobref_t &b)
def points(jdat)
Definition: rendertvtk.py:105
void operator()(const blobref_t &a, const blobref_t &b)