LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
Segmentation2D.cxx
Go to the documentation of this file.
1 
9 #include "Segmentation2D.h"
10 
13 
15 {
16  fRadiusMin = p.get< double >("RadiusMin");
17  fRadiusMax = p.get< double >("RadiusMax");
18  fMaxLineDist = p.get< double >("MaxLineDist");
19 
20  fDenseVtxRadius = p.get< double >("DenseVtxRadius");
21  fDenseMinN = p.get< unsigned int >("DenseMinNVtx");
22 
23  fDenseHitRadius = p.get< double >("DenseHitRadius");
24  fDenseMinH = p.get< unsigned int >("DenseMinNHits");
25 }
26 
27 std::vector< tss::Cluster2D > tss::Segmentation2D::run(tss::Cluster2D & inp) const
28 {
29  std::vector< tss::Cluster2D > result;
30  while (inp.size() > 1)
31  {
32  size_t idx;
33  const tss::Hit2D* hFirst = inp.outermost(idx);
34  if (!hFirst) break;
35 
36  std::vector< TVector2 > centers;
37  centers.emplace_back(hFirst->Point2D());
38 
39  while (centers.size())
40  {
41  run(inp, result, centers);
42  }
43  }
44 
45  tagDenseEnds(result);
46  mergeDenseParts(result);
47 
48  return result;
49 }
50 // ------------------------------------------------------
51 
53  tss::Cluster2D & inp,
54  std::vector< tss::Cluster2D > & result,
55  std::vector< TVector2 > & centers) const
56 {
57  if (!centers.size()) return;
58 
59  TVector2 center(centers.front());
60  centers.erase(centers.begin());
61 
62  size_t idx;
63  const tss::Hit2D* hFirst = inp.closest(center, idx);
64 
65  const double dmax2 = 0.5 * 0.5; // does not look like startpoint selected before
66  if (!hFirst || (pma::Dist2(hFirst->Point2D(), center) > dmax2)) return;
67  center = hFirst->Point2D();
68 
69  tss::Cluster2D ring = selectRing(inp, center);
70  if (ring.size())
71  {
72  std::vector< tss::Cluster2D > seeds = fSimpleClustering.run(ring);
73  while (seeds.size())
74  {
75  size_t seedIdx = 0, hitIdx, h;
76  double d2, min_d2 = seeds.front().dist2(center, hitIdx);
77  for (size_t i = 1; i < seeds.size(); i++)
78  {
79  d2 = seeds[i].dist2(center, h);
80  if (d2 < min_d2) { min_d2 = d2; seedIdx = i; hitIdx = h; }
81  }
82 
83  tss::Cluster2D segment = buildSegment(inp, center, seeds[seedIdx][hitIdx].Point2D());
84  if (segment.size())
85  {
86  result.emplace_back(segment);
87  if (segment.size() > 1)
88  {
89  const tss::Hit2D* hEnd = segment.end();
90  if (hEnd) centers.emplace_back(hEnd->Point2D());
91  }
92  }
93 
94  seeds.erase(seeds.begin() + seedIdx);
95  }
96  }
97  else
98  {
99  result.emplace_back(tss::Cluster2D());
100  result.back().push_back(hFirst);
101  inp.release(hFirst);
102  }
103 }
104 // ------------------------------------------------------
105 
107 {
108  const double max_d2 = fMaxLineDist * fMaxLineDist;
109  TVector2 segDir = end - center;
110 
111  double dc, min_dc = 1.0e9;
112  size_t firstIdx = 0;
113 
114  tss::Cluster2D candidates;
115  for (auto h : inp.hits())
116  {
117  TVector2 proj = pma::GetProjectionToSegment(h->Point2D(), center, end);
118  if (pma::Dist2(h->Point2D(), proj) < max_d2)
119  {
120  TVector2 hDir = h->Point2D() - center;
121  dc = hDir.Mod();
122  if ((hDir * segDir >= 0.0) || (dc < 0.1))
123  {
124  candidates.push_back(h);
125  if (dc < min_dc)
126  {
127  min_dc = dc; firstIdx = candidates.size() - 1;
128  }
129  }
130  }
131  }
132  if (candidates.size() > 1)
133  {
134  const tss::Hit2D* hFirst = candidates.hits()[firstIdx];
135  candidates.hits()[firstIdx] = candidates.hits()[0];
136  candidates.hits()[0] = hFirst;
137  candidates.sort();
138  }
139 
140  tss::Cluster2D segment;
141  if (candidates.size())
142  {
143  segment.push_back(candidates.start());
144  if (!inp.release(segment.start()))
145  {
146  mf::LogError("Segmentation2D") << "Hit not found in the input cluster.";
147  }
148 
149  size_t i = 1;
150  while ((i < candidates.size()) &&
151  fSimpleClustering.hitsTouching(segment, candidates[i]))
152  {
153  segment.push_back(candidates.hits()[i++]);
154  if (!inp.release(segment.end()))
155  {
156  mf::LogError("Segmentation2D") << "Hit not found in the input cluster.";
157  }
158  }
159  }
160 
161  return segment;
162 }
163 // ------------------------------------------------------
164 
166 {
167  double d2_min = fRadiusMin * fRadiusMin;
168  double d2_max = fRadiusMax * fRadiusMax;
169 
170  tss::Cluster2D ring;
171  for (size_t h = 0; h < inp.size(); h++)
172  {
173  double d2 = pma::Dist2(center, inp[h].Point2D());
174  if ((d2 >= d2_min) && (d2 <= d2_max))
175  ring.push_back(inp.hits()[h]);
176  }
177  return ring;
178 }
179 // ------------------------------------------------------
180 
181 void tss::Segmentation2D::tagDenseEnds(std::vector< tss::Cluster2D > & group) const
182 {
183  const double rad2 = fDenseVtxRadius * fDenseVtxRadius;
184 
185  for (size_t i = 0; i < group.size(); i++)
186  {
187  bool denseStart = false, denseEnd = false;
188  TVector2 start0(group[i].start()->Point2D()), end0(group[i].end()->Point2D());
189 
190  for (size_t j = 0; j < group.size(); j++)
191  {
192  if (i == j) continue;
193 
194  TVector2 start1(group[j].start()->Point2D()), end1(group[j].end()->Point2D());
195 
196  if (!group[j].isDenseStart())
197  {
198 
199  if (pma::Dist2(start1, start0) < rad2)
200  {
201  group[j].tagDenseStart(true);
202  denseStart = true;
203  }
204  if (pma::Dist2(start1, end0) < rad2)
205  {
206  group[j].tagDenseStart(true);
207  denseEnd = true;
208  }
209  }
210 
211  if (!group[j].isDenseEnd())
212  {
213  if (pma::Dist2(end1, start0) < rad2)
214  {
215  group[j].tagDenseEnd(true);
216  denseStart = true;
217  }
218  if (pma::Dist2(end1, end0) < rad2)
219  {
220  group[j].tagDenseEnd(true);
221  denseEnd = true;
222  }
223  }
224  }
225 
226  if (denseStart) group[i].tagDenseStart(true);
227  if (denseEnd) group[i].tagDenseEnd(true);
228 
229  }
230 }
231 // ------------------------------------------------------
232 
233 void tss::Segmentation2D::mergeDenseParts(std::vector< tss::Cluster2D > & group) const
234 {
235  const double rad2 = fDenseVtxRadius * fDenseVtxRadius;
236 
237  bool merged = true;
238  while (merged)
239  {
240  merged = false;
241 
242  size_t maxS = fDenseMinN, maxE = fDenseMinN;
243  std::vector< size_t > toMergeS, toMergeE;
244  int idxMaxS = -1, idxMaxE = -1;
245 
246  for (size_t i = 0; i < group.size(); i++)
247  {
248 
249  if (group[i].isEM()) continue;
250 
251  if (group[i].isDenseStart())
252  {
253 
254  size_t ns = 0;
255  std::vector< size_t > toMerge;
256  TVector2 start0(group[i].start()->Point2D());
257  for (size_t j = 0; j < group.size(); j++)
258  {
259  if (group[j].isEM()) continue;
260 
261  if (i == j)
262  {
263  if ((group[j].size() > 1) &&
264  (group[j].length2() < rad2)) ns++;
265  }
266  else
267  {
268  bool tagged = false;
269  if (pma::Dist2(start0, group[j].start()->Point2D()) < rad2)
270  {
271  ns++; toMerge.push_back(j); tagged = true;
272  }
273  if ((group[j].size() > 1) && (pma::Dist2(start0, group[j].end()->Point2D()) < rad2))
274  {
275  ns++; if (!tagged) toMerge.push_back(j);
276  }
277  }
278  }
279  if (ns > maxS) { maxS = ns; idxMaxS = i; toMergeS = toMerge; }
280  }
281 
282  if ((group[i].size() > 1) && group[i].isDenseEnd())
283  {
284  size_t ne = 0;
285  std::vector< size_t > toMerge;
286  TVector2 end0(group[i].end()->Point2D());
287  for (size_t j = 0; j < group.size(); j++)
288  {
289  if (group[j].isEM()) continue;
290 
291  if (i == j)
292  {
293  if ((group[j].size() > 1) &&
294  (group[j].length2() < rad2)) ne++;
295  }
296  else
297  {
298  bool tagged = false;
299  if (pma::Dist2(end0, group[j].start()->Point2D()) < rad2)
300  {
301  ne++; toMerge.push_back(j); tagged = true;
302  }
303  if ((group[j].size() > 1) && (pma::Dist2(end0, group[j].end()->Point2D()) < rad2))
304  {
305  ne++; if (!tagged) toMerge.push_back(j);
306  }
307  }
308  }
309  if (ne > maxE) { maxE = ne; idxMaxE = i; toMergeE = toMerge; }
310  }
311  }
312 
313  int idx = idxMaxS;
314  std::vector< size_t > toMergeIdxs = toMergeS;
315  if (idxMaxE > idx) { idx = idxMaxE; toMergeIdxs = toMergeE; }
316  if (idx > -1)
317  {
318  toMergeIdxs.push_back(idx);
319  idx = mergeClusters(group, toMergeIdxs);
320 
321  if (idx > -1) group[idx].tagEM(true);
322 
323  merged = true;
324  }
325  }
326 }
327 // ------------------------------------------------------
328 
329 int tss::Segmentation2D::mergeClusters(std::vector< tss::Cluster2D > & group, const std::vector< size_t > & idxs) const
330 {
331  if (idxs.size() < 2) return 0;
332 
333  for (const auto i : idxs)
334  {
335  if (i < group.size()) group[i].setTag(true);
336  else
337  {
338  mf::LogError("Segmentation2D") << "Merging index out of group range.";
339  return -1;
340  }
341  }
342 
343  size_t k = idxs.front(), i = idxs.front() + 1;
344  while (i < group.size())
345  {
346  if (group[i].isTagged())
347  {
348  group[k].merge(group[i]);
349  group.erase(group.begin() + i);
350  }
351  else ++i;
352  }
353  group[k].setTag(false);
354 
355  return k;
356 }
357 // ------------------------------------------------------
358 
360  const std::vector< tss::Cluster2D > & inp,
361  std::vector< const tss::Hit2D* > & trackHits,
362  std::vector< const tss::Hit2D* > & emHits) const
363 {
364 
365  trackHits.clear();
366  emHits.clear();
367 
368  for (const auto & cx : inp)
369  {
370  if (!cx.size()) continue;
371 
372  if (cx.isEM())
373  {
374  for (auto h : cx.hits()) emHits.push_back(h);
375  }
376  else
377  {
378  for (auto h : cx.hits()) trackHits.push_back(h);
379  }
380  }
381 
382 }
383 // ------------------------------------------------------
384 
386  const tss::Cluster2D & inp,
387  std::vector< const tss::Hit2D* > & trackHits,
388  std::vector< const tss::Hit2D* > & emHits) const
389 {
390  const double rad2 = fDenseHitRadius * fDenseHitRadius;
391 
392  trackHits.clear();
393  emHits.clear();
394 
395  for (const auto hx : inp.hits())
396  {
397  size_t n = 0;
398  for (const auto hy : inp.hits())
399  {
400  if (hx->Hit2DPtr() == hy->Hit2DPtr()) continue;
401 
402  if (pma::Dist2(hx->Point2D(), hy->Point2D()) < rad2) n++;
403  }
404 
405  if (n > fDenseMinH)
406  {
407  emHits.push_back(hx);
408  }
409  else
410  {
411  trackHits.push_back(hx);
412  }
413  }
414 }
415 // ------------------------------------------------------
416 
418  const std::vector< tss::Cluster2D > & inp,
419  std::vector< const tss::Hit2D* > & trackHits,
420  std::vector< const tss::Hit2D* > & emHits) const
421 {
422  const double rad2 = fDenseHitRadius * fDenseHitRadius;
423 
424  trackHits.clear();
425  emHits.clear();
426 
427  for (const auto & cx : inp)
428  {
429  if (!cx.size()) continue;
430 
431  for (const auto hx : cx.hits())
432  {
433  size_t n = 0;
434  for (const auto & cy : inp)
435  {
436  if (!cy.size()) continue;
437 
438  for (const auto hy : cy.hits())
439  {
440  if (hx->Hit2DPtr() == hy->Hit2DPtr()) continue;
441 
442  if (pma::Dist2(hx->Point2D(), hy->Point2D()) < rad2) n++;
443  }
444  }
445 
446  if (n > fDenseMinH)
447  {
448  emHits.push_back(hx);
449  }
450  else
451  {
452  trackHits.push_back(hx);
453  }
454  }
455  }
456 }
457 // ------------------------------------------------------
458 
459 // ------------------------------------------------------
460 
462 {
463  bool clover = false; bool clunder = false;
464  bool clleft = false; bool clright = false;
465 
466  if (cl2.isEM()) return false;
467 
468  float shift = 5; // shift!
469 
470  TVector2 point((cl2.max()).X(), (cl2.min()).Y());
471  float width = (cl2.max()).X() - (cl2.min()).X();
472  float height = (cl2.max()).Y() - (cl2.min()).Y();
473 
474  for (unsigned int h = 0; h < cl1.size(); h++)
475  {
476  float wire = cl1[h].Point2D().X(); float drift = cl1[h].Point2D().Y();
477 
478  if ( (wire <= (point.X() + shift)) && (wire >= (point.X() - width - shift)) )
479  {
480  if (drift < point.Y())
481  {
482  clover = true;
483  }
484  else if (drift > (point.Y() + height))
485  {
486  clunder = true;
487  }
488 
489  if (wire > point.X())
490  {
491  clleft = true;
492  }
493  else if (wire < (point.X() - width))
494  {
495  clright = true;
496  }
497  }
498  }
499 
500  if (clover && clunder && clleft && clright) return true;
501  else return false;
502 }
503 
int mergeClusters(std::vector< tss::Cluster2D > &group, const std::vector< size_t > &idxs) const
TVector2 const & Point2D(void) const
Definition: TssHit2D.h:37
double Dist2(const TVector2 &v1, const TVector2 &v2)
Definition: Utilities.cxx:19
const tss::Hit2D * start(void) const
void mergeDenseParts(std::vector< tss::Cluster2D > &group) const
void push_back(const tss::Hit2D *hit)
Float_t Y
Definition: plot.C:39
void splitHitsNaive(const tss::Cluster2D &inp, std::vector< const tss::Hit2D * > &trackHits, std::vector< const tss::Hit2D * > &emHits) const
Split into linear clusters.
const Hit2D * outermost(size_t &idx) const
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
const Hit2D * closest(const TVector2 &p2d, size_t &idx) const
tss::Cluster2D selectRing(const tss::Cluster2D &inp, TVector2 center) const
void reconfigure(const fhicl::ParameterSet &p)
const std::vector< const tss::Hit2D * > & hits(void) const
TVector2 GetProjectionToSegment(const TVector2 &p, const TVector2 &p0, const TVector2 &p1)
Definition: Utilities.cxx:167
bool Cl2InsideCl1(tss::Cluster2D &cl1, tss::Cluster2D &cl2) const
T get(std::string const &key) const
Definition: ParameterSet.h:231
std::vector< tss::Cluster2D > run(const std::vector< tss::Hit2D > &inp) const
const tss::Hit2D * end(void) const
std::vector< tss::Cluster2D > run(tss::Cluster2D &inp) const
tss::Cluster2D buildSegment(tss::Cluster2D &inp, TVector2 center, TVector2 end) const
bool isEM(void) const
bool hitsTouching(const tss::Hit2D &h1, const tss::Hit2D &h2) const
Implementation of the Projection Matching Algorithm.
void tagDenseEnds(std::vector< tss::Cluster2D > &group) const
bool release(const tss::Hit2D *hit)
const TVector2 max(void) const
Float_t proj
Definition: plot.C:34
const TVector2 min(void) const
tss::SimpleClustering fSimpleClustering
Char_t n[5]
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
double maxE
Definition: plot_hist.C:8
Float_t X
Definition: plot.C:39
size_t size(void) const
void splitHits(const std::vector< tss::Cluster2D > &inp, std::vector< const tss::Hit2D * > &trackHits, std::vector< const tss::Hit2D * > &emHits) const