11 #include "fhiclcpp/ParameterSet.h"
12 #include "messagefacility/MessageLogger/MessageLogger.h"
22 fDenseMinN = p.get<
unsigned int >(
"DenseMinNVtx");
25 fDenseMinH = p.get<
unsigned int >(
"DenseMinNHits");
30 std::vector< tss::Cluster2D > result;
31 while (inp.
size() > 1)
37 std::vector< TVector2 > centers;
38 centers.emplace_back(hFirst->
Point2D());
40 while (centers.size())
42 run(inp, result, centers);
47 mergeDenseParts(result);
55 std::vector< tss::Cluster2D > & result,
56 std::vector< TVector2 > & centers)
const
58 if (!centers.size())
return;
60 TVector2 center(centers.front());
61 centers.erase(centers.begin());
66 const double dmax2 = 0.5 * 0.5;
73 std::vector< tss::Cluster2D >
seeds = fSimpleClustering.run(ring);
76 size_t seedIdx = 0, hitIdx,
h;
77 double d2, min_d2 = seeds.front().dist2(center, hitIdx);
78 for (
size_t i = 1; i < seeds.size(); i++)
80 d2 = seeds[i].dist2(center, h);
81 if (d2 < min_d2) { min_d2 = d2; seedIdx = i; hitIdx =
h; }
84 tss::Cluster2D segment = buildSegment(inp, center, seeds[seedIdx][hitIdx].Point2D());
87 result.emplace_back(segment);
88 if (segment.
size() > 1)
91 if (hEnd) centers.emplace_back(hEnd->
Point2D());
95 seeds.erase(seeds.begin() + seedIdx);
101 result.back().push_back(hFirst);
109 const double max_d2 = fMaxLineDist * fMaxLineDist;
110 TVector2 segDir = end - center;
112 double dc, min_dc = 1.0e9;
116 for (
auto h : inp.
hits())
121 TVector2 hDir =
h->Point2D() - center;
123 if ((hDir * segDir >= 0.0) || (dc < 0.1))
128 min_dc = dc; firstIdx = candidates.
size() - 1;
133 if (candidates.
size() > 1)
136 candidates.
hits()[firstIdx] = candidates.
hits()[0];
137 candidates.
hits()[0] = hFirst;
142 if (candidates.
size())
147 mf::LogError(
"Segmentation2D") <<
"Hit not found in the input cluster.";
151 while ((i < candidates.
size()) &&
152 fSimpleClustering.hitsTouching(segment, candidates[i]))
157 mf::LogError(
"Segmentation2D") <<
"Hit not found in the input cluster.";
168 double d2_min = fRadiusMin * fRadiusMin;
169 double d2_max = fRadiusMax * fRadiusMax;
172 for (
size_t h = 0;
h < inp.
size();
h++)
175 if ((d2 >= d2_min) && (d2 <= d2_max))
184 const double rad2 = fDenseVtxRadius * fDenseVtxRadius;
186 for (
size_t i = 0; i < group.size(); i++)
188 bool denseStart =
false, denseEnd =
false;
189 TVector2 start0(group[i].start()->Point2D()), end0(group[i].
end()->Point2D());
191 for (
size_t j = 0; j < group.size(); j++)
193 if (i == j)
continue;
195 TVector2 start1(group[j].start()->Point2D()), end1(group[j].
end()->Point2D());
197 if (!group[j].isDenseStart())
202 group[j].tagDenseStart(
true);
207 group[j].tagDenseStart(
true);
212 if (!group[j].isDenseEnd())
216 group[j].tagDenseEnd(
true);
221 group[j].tagDenseEnd(
true);
227 if (denseStart) group[i].tagDenseStart(
true);
228 if (denseEnd) group[i].tagDenseEnd(
true);
236 const double rad2 = fDenseVtxRadius * fDenseVtxRadius;
243 size_t maxS = fDenseMinN, maxE = fDenseMinN;
244 std::vector< size_t > toMergeS, toMergeE;
245 int idxMaxS = -1, idxMaxE = -1;
247 for (
size_t i = 0; i < group.size(); i++)
250 if (group[i].isEM())
continue;
252 if (group[i].isDenseStart())
256 std::vector< size_t > toMerge;
257 TVector2 start0(group[i].start()->Point2D());
258 for (
size_t j = 0; j < group.size(); j++)
260 if (group[j].isEM())
continue;
264 if ((group[j].
size() > 1) &&
265 (group[j].length2() < rad2)) ns++;
270 if (
pma::Dist2(start0, group[j].start()->Point2D()) < rad2)
272 ns++; toMerge.push_back(j); tagged =
true;
274 if ((group[j].
size() > 1) && (
pma::Dist2(start0, group[j].
end()->Point2D()) < rad2))
276 ns++;
if (!tagged) toMerge.push_back(j);
280 if (ns > maxS) { maxS = ns; idxMaxS = i; toMergeS = toMerge; }
283 if ((group[i].
size() > 1) && group[i].isDenseEnd())
286 std::vector< size_t > toMerge;
287 TVector2 end0(group[i].
end()->Point2D());
288 for (
size_t j = 0; j < group.size(); j++)
290 if (group[j].isEM())
continue;
294 if ((group[j].
size() > 1) &&
295 (group[j].length2() < rad2)) ne++;
300 if (
pma::Dist2(end0, group[j].start()->Point2D()) < rad2)
302 ne++; toMerge.push_back(j); tagged =
true;
304 if ((group[j].
size() > 1) && (
pma::Dist2(end0, group[j].
end()->Point2D()) < rad2))
306 ne++;
if (!tagged) toMerge.push_back(j);
310 if (ne > maxE) { maxE = ne; idxMaxE = i; toMergeE = toMerge; }
315 std::vector< size_t > toMergeIdxs = toMergeS;
316 if (idxMaxE > idx) { idx = idxMaxE; toMergeIdxs = toMergeE; }
319 toMergeIdxs.push_back(idx);
320 idx = mergeClusters(group, toMergeIdxs);
322 if (idx > -1) group[idx].tagEM(
true);
332 if (idxs.size() < 2)
return 0;
334 for (
const auto i : idxs)
336 if (i < group.size()) group[i].setTag(
true);
339 mf::LogError(
"Segmentation2D") <<
"Merging index out of group range.";
344 size_t k = idxs.front(), i = idxs.front() + 1;
345 while (i < group.size())
347 if (group[i].isTagged())
349 group[
k].merge(group[i]);
350 group.erase(group.begin() + i);
354 group[
k].setTag(
false);
361 const std::vector< tss::Cluster2D > & inp,
362 std::vector< const tss::Hit2D* > & trackHits,
363 std::vector< const tss::Hit2D* > & emHits)
const
369 for (
const auto & cx : inp)
371 if (!cx.size())
continue;
375 for (
auto h : cx.hits()) emHits.push_back(
h);
379 for (
auto h : cx.hits()) trackHits.push_back(
h);
388 std::vector< const tss::Hit2D* > & trackHits,
389 std::vector< const tss::Hit2D* > & emHits)
const
391 const double rad2 = fDenseHitRadius * fDenseHitRadius;
396 for (
const auto hx : inp.
hits())
399 for (
const auto hy : inp.
hits())
401 if (hx->Hit2DPtr() == hy->Hit2DPtr())
continue;
403 if (
pma::Dist2(hx->Point2D(), hy->Point2D()) < rad2) n++;
408 emHits.push_back(hx);
412 trackHits.push_back(hx);
419 const std::vector< tss::Cluster2D > & inp,
420 std::vector< const tss::Hit2D* > & trackHits,
421 std::vector< const tss::Hit2D* > & emHits)
const
423 const double rad2 = fDenseHitRadius * fDenseHitRadius;
428 for (
const auto & cx : inp)
430 if (!cx.size())
continue;
432 for (
const auto hx : cx.hits())
435 for (
const auto & cy : inp)
437 if (!cy.size())
continue;
439 for (
const auto hy : cy.hits())
441 if (hx->Hit2DPtr() == hy->Hit2DPtr())
continue;
443 if (
pma::Dist2(hx->Point2D(), hy->Point2D()) < rad2) n++;
449 emHits.push_back(hx);
453 trackHits.push_back(hx);
464 bool clover =
false;
bool clunder =
false;
465 bool clleft =
false;
bool clright =
false;
467 if (cl2.
isEM())
return false;
471 TVector2 point((cl2.
max()).
X(), (cl2.
min()).Y());
472 float width = (cl2.
max()).
X() - (cl2.
min()).
X();
473 float height = (cl2.
max()).Y() - (cl2.
min()).Y();
475 for (
unsigned int h = 0;
h < cl1.
size();
h++)
477 float wire = cl1[
h].Point2D().X();
float drift = cl1[
h].Point2D().Y();
479 if ( (wire <= (point.X() +
shift)) && (wire >= (point.X() - width -
shift)) )
481 if (drift < point.Y())
485 else if (drift > (point.Y() + height))
490 if (wire > point.X())
494 else if (wire < (point.X() - width))
501 if (clover && clunder && clleft && clright)
return true;
TVector2 const & Point2D() const
int mergeClusters(std::vector< tss::Cluster2D > &group, const std::vector< size_t > &idxs) const
double Dist2(const TVector2 &v1, const TVector2 &v2)
const tss::Hit2D * start(void) const
void mergeDenseParts(std::vector< tss::Cluster2D > &group) const
void push_back(const tss::Hit2D *hit)
std::size_t size(FixedBins< T, C > const &) noexcept
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
then echo echo For and will not be changed by echo further linking echo echo B echo The symbol is in the uninitialized data multiple common symbols may appear with the echo same name If the symbol is defined the common echo symbols are treated as undefined references For more echo details on common see the discussion of warn common echo in *Note Linker see the discussion of warn common echo in *Note Linker such as a global int variable echo as opposed to a large global array echo echo I echo The symbol is an indirect reference to another symbol This echo is a GNU extension to the a out object file format which is echo rarely used echo echo N echo The symbol is a debugging symbol echo echo R echo The symbol is in a read only data section echo echo S echo The symbol is in an uninitialized data section for small echo objects echo echo T echo The symbol is in the the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo W echo The symbol is a weak symbol that has not been specifically echo tagged as a weak object symbol When a weak defined symbol echo is linked with a normal defined the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo echo The symbol is a stabs symbol in an a out object file In echo this the next values printed are the stabs other echo the stabs desc and the stab type Stabs symbols are echo used to hold debugging information For more echo see *Note or object file format specific echo echo For Mac OS X
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)
bool Cl2InsideCl1(tss::Cluster2D &cl1, tss::Cluster2D &cl2) const
auto end(FixedBins< T, C > const &) noexcept
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
std::vector< TrajPoint > seeds
void tagDenseEnds(std::vector< tss::Cluster2D > &group) const
bool release(const tss::Hit2D *hit)
const TVector2 max(void) const
const TVector2 min(void) const
void splitHits(const std::vector< tss::Cluster2D > &inp, std::vector< const tss::Hit2D * > &trackHits, std::vector< const tss::Hit2D * > &emHits) const