RayTiling.cxx
Go to the documentation of this file.
2 #include "WireCellUtil/Logging.h"
3 
4 #include <algorithm>
5 #include <sstream>
6 
7 
8 using namespace WireCell;
9 using namespace WireCell::RayGrid;
10 
12  : m_span{}
13  , m_layer(layer)
14  , m_offset(0)
15  , m_threshold(0)
16 {
17 }
18 
20  int offset, double threshold)
21  : m_span(span, value)
22  , m_layer(layer)
23  , m_offset(offset)
24  , m_threshold(threshold)
25 {
26 }
27 
29  double threshold)
30  : m_span{}
31  , m_layer(layer)
32  , m_offset(offset)
33  , m_threshold(threshold)
34 {
35  if (span.first == span.second) {
36  return;
37  }
38  iterator_t b = span.first;
39  while (b != span.second and *b <= m_threshold) {
40  ++b;
41  ++m_offset;
42  }
43  iterator_t e = span.second;
44  while (e > b and *(e-1) <= m_threshold) {
45  --e;
46  }
47  m_span.insert(m_span.begin(), b,e);
48 }
49 
51 {
52  return m_span.begin();
53 }
54 
56 {
57  return m_span.end();
58 }
59 
60 bool Activity::empty() const
61 {
62  return m_span.empty();
63 }
64 
65 int Activity::pitch_index(const iterator_t& it) const
66 {
67  return m_offset + it-m_span.begin();
68 }
69 // Produce a subspan activity between pitch indices [pi1, pi2)
70 Activity Activity::subspan(int abs_beg, int abs_end) const
71 {
72  const int rel_beg = abs_beg-m_offset;
73  const int rel_end = abs_end-m_offset;
74 
75  if (rel_beg < 0 or rel_beg >= rel_end or rel_end > (int)m_span.size()) {
76  spdlog::debug("activity::subspan bogus absolute:[{},{}] m_offset={} span.size={}",
77  abs_beg, abs_end, m_offset, m_span.size());
78  return Activity(m_layer);
79  }
80 
81  return Activity(m_layer, {begin()+rel_beg, begin()+rel_end}, abs_beg);
82 }
83 
84 
85 Strip
87 {
88  return Strip{m_layer, std::make_pair(pitch_index(r.first),
89  pitch_index(r.second))};
90 }
91 
93 {
94  strips_t ret;
95  for (const auto& ar : active_ranges()) {
96  ret.push_back(make_strip(ar));
97  }
98  return ret;
99 }
100 
101 
103 {
104  ranges_t ret;
105  range_t current{end(), end()};
106 
107  for (auto it = begin(); it != end(); ++it) {
108  // entering active range
109  if (current.first == end() and *it > m_threshold) {
110  current.first = it;
111  continue;
112  }
113  // exiting active range
114  if (current.first != end() and *it <= 0.0) {
115  current.second = it;
116  ret.push_back(current);
117  current.first = end();
118  }
119  }
120  if (current.first != end()) {
121  current.second = end();
122  ret.push_back(current);
123  }
124  return ret;
125 }
126 
127 /*********************************/
128 
129 static
130 crossings_t find_corners(const Strip& one, const Strip& two)
131 {
132  crossings_t ret;
133 
134  const auto a = one.addresses(), b = two.addresses();
135 
136  ret.push_back(std::make_pair(a.first, b.first));
137  ret.push_back(std::make_pair(a.first, b.second));
138  ret.push_back(std::make_pair(a.second, b.first));
139  ret.push_back(std::make_pair(a.second, b.second));
140  return ret;
141 }
142 
143 
144 
145 
146 void Blob::add(const Coordinates& coords, const Strip& strip)
147 {
148  const size_t nstrips = m_strips.size();
149 
150  if (nstrips == 0) { // special case
151  m_strips.push_back(strip);
152  return;
153  }
154 
155  if (nstrips == 1) { // special case
156  m_strips.push_back(strip);
157  m_corners = find_corners(m_strips.front(), m_strips.back());
158  return;
159  }
160 
161  crossings_t surviving;
162 
163  // See what old corners are inside the new strip
164  for (const auto& c : m_corners) {
165  const double pitch = coords.pitch_location(c.first, c.second, strip.layer);
166  const int pind = coords.pitch_index(pitch, strip.layer);
167 
168 
169  if (strip.in(pind)) {
170  surviving.push_back(c);
171  }
172  }
173 
174  // see what new corners are inside all old strips;
175  for (size_t si1 = 0; si1 < nstrips; ++si1) {
176  auto corners = find_corners(m_strips[si1], strip);
177  for (const auto& c : corners) {
178 
179  // check each corner if inside all other strips
180  bool miss = false;
181  for (size_t si2 = 0; si2 < nstrips; ++si2) {
182  if (si1 == si2) { continue; }
183  const auto& s2 = m_strips[si2];
184  double pitch = coords.pitch_location(c.first, c.second, s2.layer);
185  const int pind = coords.pitch_index(pitch, s2.layer);
186  if (s2.in(pind)) {
187  continue;
188  }
189 
190  miss = true;
191  break;
192  }
193  if (!miss) {
194  surviving.push_back(c);
195  }
196  }
197  }
198  m_corners = surviving;
199  m_strips.push_back(strip);
200 }
201 
203 {
204  return m_corners;
205 }
206 
207 
208 
210  : m_coords(coords)
211 {
212 }
213 
214 
215 
217 {
218  auto strips = activity.make_strips();
219  const size_t nstrips = strips.size();
220  blobs_t ret(nstrips);
221  for (size_t ind=0; ind<nstrips; ++ind) {
222  ret[ind].add(m_coords, strips[ind]);
223  }
224  return ret;
225 }
226 
228 {
229  // special case. A single layer blob effectively extends to
230  // infinity along the ray direction so any possible activity
231  // projects.
232  if (blob.strips().size() == 1) {
233  return activity;
234  }
235 
236  const double pitch_mag = m_coords.pitch_mags()[activity.layer()];
237 
238  // find extreme pitches
239  std::vector<double> pitches;
240  const auto corners = blob.corners();
241  if (corners.empty()) {
242  return Activity(activity.layer());
243  }
244  for (const auto& c : blob.corners()) {
245  const double p = m_coords.pitch_location(c.first, c.second, activity.layer());
246  pitches.push_back(p);
247  }
248  if (pitches.empty()) {
249  return Activity(activity.layer());
250  }
251 
252  auto pbeg = pitches.begin();
253  auto pend = pitches.end();
254 
255  const auto mm = std::minmax_element(pbeg, pend);
256  int pind1 = std::floor((*mm.first)/pitch_mag);
257  int pind2 = std::ceil((*mm.second)/pitch_mag);
258 
259  const int apind1 = activity.pitch_index(activity.begin());
260  const int apind2 = activity.pitch_index(activity.end());
261 
262  if (pind2 <= apind1 or pind1 >= apind2) {
263  return Activity(activity.layer());
264  }
265 
266  pind1 = std::max(pind1, activity.pitch_index(activity.begin()));
267  pind2 = std::min(pind2, activity.pitch_index(activity.end()));
268 
269  Activity ret = activity.subspan(pind1, pind2);
270  return ret;
271 }
272 
273 
275 {
276  std::stringstream ss;
277  ss << *this << "\n";
278  const auto& strips = this->strips();
279  ss << "\tstrips (" << strips.size() << "):\n";
280  for (const auto& s : strips) {
281  ss << "\t\t" << s << "\n";
282  }
283  const auto corners = this->corners();
284  ss << "\tcorners (" << corners.size() << "):\n";
285  for (const auto& c : corners) {
286  ss << "\t\t" << c << "\n";
287  }
288  return ss.str();
289 }
290 
292 {
293  std::stringstream ss;
294  ss << *this << "\n";
295  for (auto strip: make_strips()) {
296  ss << "\t" << strip << "\n";
297  }
298  return ss.str();
299 }
300 
301 blobs_t Tiling::operator()(const blobs_t& prior_blobs,
302  const Activity& activity)
303 {
304  blobs_t ret;
305 
306  for (const auto& blob : prior_blobs) {
307  Activity proj = projection(blob, activity);
308  if (proj.empty()) {
309  continue;
310  }
311  auto strips = proj.make_strips();
312  for (auto strip : strips) {
313  Blob newblob = blob; // copy
314  newblob.add(m_coords, strip);
315  if (newblob.corners().empty()) {
316  continue;
317  }
318  ret.push_back(newblob);
319  }
320  }
321 
322  return ret;
323 }
324 
326 {
327  const auto end = std::partition(blobs.begin(), blobs.end(),
328  [](const Blob& b) { return b.valid(); });
329  const size_t dropped = blobs.end() - end;
330  blobs.resize(end - blobs.begin());
331  return dropped;
332 }
333 
335 {
336  for (auto & blob: blobs) {
337 
338  auto& strips = blob.strips();
339  const int nlayers = strips.size();
340  std::vector< std::vector<grid_index_t> > mms(nlayers);
341  for (const auto& corner : blob.corners()) {
342  // fixme off by one bugs here? Adding the two rays making
343  // up a corner adds a pitch-bin-edge. Adding the ray
344  // crossing point measured in the 3rd layer pitch adds a
345  // bin pitch-bin-content which should be either floor()'ed
346  // or ceil()'ed (or both?)
347 
348  mms[corner.first.layer].push_back(corner.first.grid);
349  mms[corner.second.layer].push_back(corner.second.grid);
350 
351  // Check every layer not forming the corner
352  for (int layer=0; layer<nlayers; ++layer) {
353  if (corner.first.layer == layer or corner.second.layer == layer) {
354  continue;
355  }
356  const double ploc = coords.pitch_location(corner.first, corner.second, layer);
357  const int pind = coords.pitch_index(ploc, layer);
358  mms[layer].push_back(pind);
359  mms[layer].push_back(pind+1);
360  }
361  }
362 
363  for (int layer=0; layer<nlayers; ++layer) {
364  auto mm = std::minmax_element(mms[layer].begin(), mms[layer].end());
365  strips[layer].bounds.first = *mm.first;
366  strips[layer].bounds.second = *mm.second;
367  }
368  }
369 }
370 
372 {
373  Tiling rc(coords);
374  blobs_t blobs;
375 
376  for (const auto& activity : activities) {
377  if (blobs.empty()) {
378  blobs = rc(activity);
379  }
380  else {
381  blobs = rc(blobs, activity);
382  if (blobs.empty()) {
383  spdlog::trace("RayGrid::make_blobs: lost blobs with {}", activity);
384  return blobs_t{};
385  }
386  }
387  drop_invalid(blobs);
388  }
389  prune(coords, blobs);
390  return blobs;
391 }
392 
layer_index_t layer
Definition: RayTiling.h:24
ranges_t active_ranges() const
Definition: RayTiling.cxx:102
span(IterB &&b, IterE &&e, Adaptor &&adaptor) -> span< decltype(adaptor(std::forward< IterB >(b))), decltype(adaptor(std::forward< IterE >(e))) >
std::string string
Definition: nybbler.cc:12
bool in(grid_index_t pitch_index) const
Definition: RayTiling.h:34
double pitch_location(const coordinate_t &one, const coordinate_t &two, layer_index_t other) const
Definition: RayGrid.cxx:133
iterator_t begin() const
Definition: RayTiling.cxx:50
strips_t make_strips() const
Definition: RayTiling.cxx:92
void prune(const Coordinates &coords, blobs_t &blobs)
Definition: RayTiling.cxx:334
std::vector< Strip > strips_t
Definition: RayTiling.h:42
Strip make_strip(const range_t &subspan) const
Definition: RayTiling.cxx:86
std::vector< range_t > ranges_t
Definition: RayTiling.h:57
def blobs(cm, hist)
Definition: plots.py:79
vector_t::const_iterator iterator_t
Definition: RayTiling.h:55
constexpr ProductStatus dropped() noexcept
Definition: ProductStatus.h:20
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:72
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
int pitch_index(double pitch, layer_index_t layer) const
Definition: RayGrid.h:82
blobs_t operator()(const Activity &activity)
Definition: RayTiling.cxx:216
const double e
Activity projection(const Blob &blob, const Activity &activity)
Definition: RayTiling.cxx:227
Activity subspan(int pi_begin, int pi_end) const
Definition: RayTiling.cxx:70
Activity(layer_index_t layer)
Definition: RayTiling.cxx:11
std::string as_string() const
Definition: RayTiling.cxx:291
int pitch_index(const iterator_t &it) const
Definition: RayTiling.cxx:65
const std::vector< double > & pitch_mags() const
Definition: RayGrid.h:87
static Entry * current
layer_index_t layer() const
Definition: RayTiling.h:75
static int max(int a, int b)
const strips_t & strips() const
Definition: RayTiling.h:111
static crossings_t find_corners(const Strip &one, const Strip &two)
Definition: RayTiling.cxx:130
const Coordinates & m_coords
Definition: RayTiling.h:152
static const double mm
Definition: Units.h:73
std::vector< crossing_t > crossings_t
Definition: RayGrid.h:62
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
Definition: Main.h:22
p
Definition: test.py:223
std::vector< Blob > blobs_t
Definition: RayTiling.h:134
Tiling(const Coordinates &coords)
Definition: RayTiling.cxx:209
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
std::string as_string() const
Definition: RayTiling.cxx:274
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225
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
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:67
void add(const Coordinates &coords, const Strip &strip)
Definition: RayTiling.cxx:146
const crossings_t & corners() const
Definition: RayTiling.cxx:202
std::vector< Activity > activities_t
Definition: RayTiling.h:105
std::pair< iterator_t, iterator_t > range_t
Definition: RayTiling.h:56
crossing_t addresses() const
Definition: RayTiling.h:29
static QCString * s
Definition: config.cpp:1042
void trace(const char *fmt, const Args &...args)
Definition: spdlog.h:177
iterator_t end() const
Definition: RayTiling.cxx:55