test_raytiling.cxx
Go to the documentation of this file.
4 #include "WireCellUtil/Logging.h"
5 
6 #include "TCanvas.h"
7 #include "TMarker.h"
8 #include "TText.h"
9 #include "TLatex.h"
10 #include "TLine.h"
11 #include "TPolyLine.h"
12 #include "TArrow.h"
13 #include "TH1F.h"
14 
15 #include <boost/graph/graphviz.hpp>
16 
17 #include <math.h>
18 
19 #include <random>
20 
21 using namespace WireCell;
22 using namespace WireCell::Waveform;
23 using namespace WireCell::RayGrid;
24 using namespace std;
25 using spdlog::info;
26 using spdlog::warn;
27 
28 const int ndepos = 10;
29 const int neles = 10;
30 const double pitch_magnitude = 5;
31 const double gaussian = 3;
32 const double border = 10;
33 const double width = 100;
34 const double height = 100;
35 
36 // local helper codes
37 #include "raygrid.h"
38 #include "raygrid_draw.h"
39 
40 
41 
42 // Invent a channel and wire map. Note, in this test, this mapping is
43 // used identically for both "channels" and "wires" and it is wholly
44 // innappropraite for real detectors. Do not copy-paste.
45 Grouping::ident_t make_ident(int index, int layer, int face = 0) {
46  return (1+face)*10000 + (1+layer)*1000 + index;
47 }
48 
49 
50 
51 int main(int argc, char* argv[])
52 {
53  Printer print(argv[0]);
54 
55  auto raypairs = make_raypairs(width, height, pitch_magnitude);
56  const int nlayers = raypairs.size();
57 
58  Coordinates coords(raypairs);
59 
60  draw_raygrid(print, coords, raypairs);
61 
62  const auto& pitches = coords.pitch_dirs();
63  const auto& centers = coords.centers();
64  const auto& pitch_mags = coords.pitch_mags();
65 
66  Tiling tiling(coords);
67 
68  std::vector< std::vector<Activity::value_t> > measures(nlayers);
69 
70  std::default_random_engine generator;
71  std::uniform_real_distribution<double> position(0,std::max(width,height));
72  std::normal_distribution<double> spread(0.0, gaussian);
73  std::vector<Point> points;
74  for (int idepo=0;idepo<ndepos;++idepo) {
75  Point cp(0, position(generator), position(generator));
76  for (int iele=0; iele<neles; ++iele) {
77  Point delta(0, spread(generator), spread(generator));
78  points.push_back(cp+delta);
79  }
80  }
81 
82  draw_frame(print.canvas, "Points and Activity");
83  for (size_t ipt=0; ipt<points.size(); ++ipt ) {
84  const auto& p = points[ipt];
85  draw_point(p, 1, 24, ipt+1);
86  for (int ilayer = 0; ilayer<nlayers; ++ilayer) {
87  // pimpos normally would help here to find pitch location of arb point
88  const auto& pit = pitches[ilayer];
89  const auto& cen = centers[ilayer];
90  const auto rel = p-cen;
91  const int pit_ind = pit.dot(rel)/pitch_mags[ilayer];
92  auto& m = measures[ilayer];
93  if ((int)m.size() <= pit_ind) {
94  m.resize(pit_ind+1, 0.0);
95  }
96 
97  m[pit_ind] += 1.0;
98 
99  }
100  }
101  for (int ilayer=0; ilayer<nlayers; ++ilayer) {
102  draw_layer(coords, ilayer, pitch_mags[ilayer],
103  pitches[ilayer], centers[ilayer], measures[ilayer]);
104  }
105  print();
106 
107  blobs_t blobs;
108 
109  draw_frame(print.canvas, "Points and Strips");
110  for (size_t ipt=0; ipt<points.size(); ++ipt ) {
111  const auto& p = points[ipt];
112  draw_point(p, 1, 24, ipt+1);
113  }
114  activities_t activities;
115  for (int ilayer = 0; ilayer<nlayers; ++ilayer) {
116  auto& m = measures[ilayer];
117 
118  for (size_t ind=0; ind<m.size(); ++ind) {
119  if (m[ind] <= 0.0) { continue; }
120  info("L{} [{}] {}", ilayer, ind, m[ind]);
121  }
122 
123  Activity activity(ilayer, {m.begin(), m.end()});
124 
125  auto strips = activity.make_strips();
126  draw_strips(coords, strips);
127  activities.push_back(activity);
128 
129  auto tot = std::accumulate(m.begin(), m.end(), 0.0);
130  info("L{} activity={} in: {} strips", activity.layer(), tot, strips.size());
131  }
132  print();
133 
134  for (int ilayer = 0; ilayer<nlayers; ++ilayer) {
135  const auto& activity = activities[ilayer];
136  info("Tiling layer {} with {} blobs: {}",
137  ilayer, blobs.size(), activity.as_string());
138  if (blobs.empty()) {
139  blobs = tiling(activity);
140  }
141  else {
142  blobs = tiling(blobs, activity);
143  if (blobs.empty()) {
144  warn("lost m'blobs!");
145  return -1;
146  }
147  }
148  drop_invalid(blobs);
149  dump(blobs);
150  draw_points_blobs(coords, print, points, blobs);
151  print();
152  }
153 
154  draw_points_blobs(coords, print, points, blobs);
155  for (const auto& activity: activities) {
156  auto strips = activity.make_strips();
157  draw_strips(coords, strips, false);
158  }
159  print();
160 
161 
162 
163 
164  // now test solving
165  Solving solving;
166 
167 
168  // Skip the first two horiz/vert layers bounding sensitivity. In
169  // principle, they can be included but just add fully degenerate
170  // terms.
171  for (int ilayer = 2; ilayer<nlayers; ++ilayer) {
172  Grouping grouping;
173  auto& m = measures[ilayer];
174 
175  // Load up the "channels" and their associated "wires". In
176  // this test we have a simple one-to-one mapping between both
177  // based on a common index.
178  for (size_t mind=0; mind < m.size(); ++mind) {
179  const float meas = m[mind];
180  if (meas <= 0) { continue; }
181  Grouping::ident_t ident = make_ident(mind, ilayer);
182  info("ilayer:{} mind:{} indent:{} meas:{}", ilayer, mind, ident, meas);
183  grouping.add('m', ident, { ident }, meas);
184  }
185 
186  // Load up the "blobs" and their associated "wires" for the current layer
187  for (size_t bind = 0; bind < blobs.size(); ++bind) {
188  const auto& blob = blobs[bind];
189  std::vector<Grouping::ident_t> wids;
190  for (const auto& strip : blob.strips()) {
191  if (strip.layer != ilayer) {
192  continue;
193  }
194  for (auto wind = strip.bounds.first; wind < strip.bounds.second; ++wind) {
195  wids.push_back(make_ident(wind, ilayer));
196  }
197  }
198  // note, blob ident must NOT inculde ilayer information
199  const float blob_value = 0.0;
200  const float blob_weight = 1.0;
201  grouping.add('s', bind, wids, blob_value, blob_weight);
202  }
203 
204  const auto& g = grouping.graph();
205  auto labels = [&](std::ostream& out, const auto& vtx) {
206  char typ = g[vtx].ntype;
207  int lid = g[vtx].ident % 1000; // l'il ID, erase face and layer
208  if (typ == 's') {
209  out << "[label=\"s" << lid << "\"]";
210  }
211  if (typ == 'm') {
212  out << "[label=\"m" << lid << "=" << g[vtx].value << "\"]";
213  }
214  if (typ == 'w') {
215  out << "[label=\"w" << lid << "\"]";
216  }
217  };
218 
219  std::string dotfilename = Form("%s-layer%d.dot", argv[0], ilayer);
220  std::ofstream dotfile (dotfilename.c_str());
221  boost::write_graphviz(dotfile, g, labels);
222  cerr << dotfilename << "\n";
223 
224  auto clusters = grouping.clusters();
225  solving.add(clusters);
226  }
227 
228  auto solution = solving.solve();
229 
230  for (const auto& it : solution) {
231  std::cerr << it.first << ": " << it.second << std::endl;
232  }
233 
234  const auto& g = solving.graph();
235  auto labels = [&](std::ostream& out, const auto& vtx) {
236  char typ = g[vtx].ntype;
237  if (typ == 's') {
238  out << "[label=\"s" << g[vtx].ident << "=" << Form("%.1f", g[vtx].value) << "\"]";
239  }
240  if (typ == 'm') {
241  out << "[label=\"m" << "=" << g[vtx].value << "\"]";
242  }
243  };
244 
245  std::string dotfilename = Form("%s-solution.dot", argv[0]);
246  std::ofstream dotfile (dotfilename.c_str());
247  boost::write_graphviz(dotfile, g, labels);
248  cerr << dotfilename << "\n";
249 
250  // plot something
251 
252  draw_points_blobs_solved(coords, print, points, blobs, solution);
253  print();
254 
255  return 0;
256 }
257 
258 
static const double m
Definition: Units.h:79
void draw_points_blobs_solved(Coordinates &coords, Printer &print, const std::vector< Point > &points, const blobs_t &blobs, const std::unordered_map< size_t, float > &blob_charge)
Definition: raygrid_draw.h:210
int main(int argc, char *argv[])
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
STL namespace.
static const double g
Definition: Units.h:145
const double pitch_magnitude
def blobs(cm, hist)
Definition: plots.py:79
const int neles
const vector_array1d_t & pitch_dirs() const
Definition: RayGrid.h:88
const double width
void draw_raygrid(Printer &print, const Coordinates &coords, const ray_pair_vector_t &raypairs)
Definition: raygrid_draw.h:257
size_t drop_invalid(blobs_t &blobs)
free functions
Definition: RayTiling.cxx:325
def activity(output, slices, slice_line, cluster_tap_file)
Definition: main.py:144
const double border
const double gaussian
void draw_strips(Coordinates &coords, const strips_t &strips, bool outline=true)
Definition: raygrid_draw.h:108
std::enable_if< internal::is_string< String >::value >::type print(std::FILE *f, const text_style &ts, const String &format_str, const Args &...args)
Definition: color.h:549
const int ndepos
virtual void add(char ntype, ident_t chid, std::vector< ident_t > wids, float value, float weight=1.0)
Definition: RaySolving.cxx:21
TCanvas canvas
Definition: raygrid_draw.h:170
const vector_array1d_t & centers() const
Definition: RayGrid.h:89
const std::vector< double > & pitch_mags() const
Definition: RayGrid.h:87
const double height
static int max(int a, int b)
generator
Definition: train.py:468
void warn(const char *fmt, const Args &...args)
Definition: spdlog.h:195
void draw_points_blobs(Coordinates &coords, Printer &print, const std::vector< Point > &points, const blobs_t &blobs)
Definition: raygrid_draw.h:190
TH1F * draw_frame(TCanvas &canvas, std::string title)
Definition: raygrid_draw.h:52
Definition: Main.h:22
p
Definition: test.py:223
std::vector< Blob > blobs_t
Definition: RayTiling.h:134
void draw_layer(Coordinates &coords, int ilayer, double pitch_mag, const Point &pitch, const Point &center, const std::vector< double > &measure)
Definition: raygrid_draw.h:87
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225
Grouping::ident_t make_ident(int index, int layer, int face=0)
static double blob_weight(IBlob::pointer iblob, ISlice::pointer islice, const cluster_indexed_graph_t &grind)
Definition: BlobSolving.cxx:53
std::vector< Activity > activities_t
Definition: RayTiling.h:105
void draw_point(const Point &p, float size=1, int style=20, int color=1)
Definition: raygrid_draw.h:26
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
void dump(const IFrame::pointer frame)
Definition: Fourdee.cxx:120
void add(const Grouping::clusterset_t &cset)
Definition: RaySolving.cxx:88
def points(jdat)
Definition: rendertvtk.py:105
QTextStream & endl(QTextStream &s)