30 std::vector<tss::Cluster2D> result;
31 while (inp.
size() > 1) {
36 std::vector<TVector2> centers;
37 centers.emplace_back(hFirst->
Point2D());
39 while (centers.size()) {
40 run(inp, result, centers);
52 std::vector<tss::Cluster2D>& result,
53 std::vector<TVector2>& centers)
const 55 if (!centers.size())
return;
57 TVector2 center(centers.front());
58 centers.erase(centers.begin());
63 const double dmax2 = 0.5 * 0.5;
70 while (seeds.size()) {
71 size_t seedIdx = 0, hitIdx, h;
72 double d2, min_d2 = seeds.front().dist2(center, hitIdx);
73 for (
size_t i = 1; i < seeds.size(); i++) {
74 d2 = seeds[i].dist2(center, h);
84 result.emplace_back(segment);
85 if (segment.
size() > 1) {
87 if (hEnd) centers.emplace_back(hEnd->
Point2D());
91 seeds.erase(seeds.begin() + seedIdx);
96 result.back().push_back(hFirst);
107 TVector2 segDir = end - center;
109 double dc, min_dc = 1.0e9;
113 for (
auto h : inp.
hits()) {
116 TVector2 hDir = h->Point2D() - center;
118 if ((hDir * segDir >= 0.0) || (dc < 0.1)) {
122 firstIdx = candidates.
size() - 1;
127 if (candidates.
size() > 1) {
129 candidates.
hits()[firstIdx] = candidates.
hits()[0];
130 candidates.
hits()[0] = hFirst;
135 if (candidates.
size()) {
138 mf::LogError(
"Segmentation2D") <<
"Hit not found in the input cluster.";
145 mf::LogError(
"Segmentation2D") <<
"Hit not found in the input cluster.";
160 for (
size_t h = 0; h < inp.
size(); h++) {
161 double d2 =
pma::Dist2(center, inp[h].Point2D());
162 if ((d2 >= d2_min) && (d2 <= d2_max)) ring.
push_back(inp.
hits()[h]);
172 for (
size_t i = 0; i < group.size(); i++) {
173 bool denseStart =
false, denseEnd =
false;
174 TVector2 start0(group[i].start()->Point2D()), end0(group[i].
end()->Point2D());
176 for (
size_t j = 0; j < group.size(); j++) {
177 if (i == j)
continue;
179 TVector2 start1(group[j].start()->Point2D()), end1(group[j].
end()->Point2D());
181 if (!group[j].isDenseStart()) {
184 group[j].tagDenseStart(
true);
188 group[j].tagDenseStart(
true);
193 if (!group[j].isDenseEnd()) {
195 group[j].tagDenseEnd(
true);
199 group[j].tagDenseEnd(
true);
205 if (denseStart) group[i].tagDenseStart(
true);
206 if (denseEnd) group[i].tagDenseEnd(
true);
220 std::vector<size_t> toMergeS, toMergeE;
221 int idxMaxS = -1, idxMaxE = -1;
223 for (
size_t i = 0; i < group.size(); i++) {
225 if (group[i].isEM())
continue;
227 if (group[i].isDenseStart()) {
230 std::vector<size_t> toMerge;
231 TVector2 start0(group[i].start()->Point2D());
232 for (
size_t j = 0; j < group.size(); j++) {
233 if (group[j].isEM())
continue;
236 if ((group[j].
size() > 1) && (group[j].length2() < rad2)) ns++;
240 if (
pma::Dist2(start0, group[j].start()->Point2D()) < rad2) {
242 toMerge.push_back(j);
245 if ((group[j].
size() > 1) && (
pma::Dist2(start0, group[j].
end()->Point2D()) < rad2)) {
247 if (!tagged) toMerge.push_back(j);
258 if ((group[i].
size() > 1) && group[i].isDenseEnd()) {
260 std::vector<size_t> toMerge;
261 TVector2 end0(group[i].
end()->Point2D());
262 for (
size_t j = 0; j < group.size(); j++) {
263 if (group[j].isEM())
continue;
266 if ((group[j].
size() > 1) && (group[j].length2() < rad2)) ne++;
270 if (
pma::Dist2(end0, group[j].start()->Point2D()) < rad2) {
272 toMerge.push_back(j);
275 if ((group[j].
size() > 1) && (
pma::Dist2(end0, group[j].
end()->Point2D()) < rad2)) {
277 if (!tagged) toMerge.push_back(j);
290 std::vector<size_t> toMergeIdxs = toMergeS;
293 toMergeIdxs = toMergeE;
296 toMergeIdxs.push_back(idx);
299 if (idx > -1) group[idx].tagEM(
true);
308 const std::vector<size_t>& idxs)
const 310 if (idxs.size() < 2)
return 0;
312 for (
const auto i : idxs) {
313 if (i < group.size())
314 group[i].setTag(
true);
316 mf::LogError(
"Segmentation2D") <<
"Merging index out of group range.";
321 size_t k = idxs.front(), i = idxs.front() + 1;
322 while (i < group.size()) {
323 if (group[i].isTagged()) {
324 group[k].merge(group[i]);
325 group.erase(group.begin() + i);
330 group[k].setTag(
false);
337 std::vector<const tss::Hit2D*>& trackHits,
338 std::vector<const tss::Hit2D*>& emHits)
const 344 for (
const auto& cx : inp) {
345 if (!cx.size())
continue;
348 for (
auto h : cx.hits())
352 for (
auto h : cx.hits())
353 trackHits.push_back(h);
360 std::vector<const tss::Hit2D*>& trackHits,
361 std::vector<const tss::Hit2D*>& emHits)
const 368 for (
const auto hx : inp.
hits()) {
370 for (
const auto hy : inp.
hits()) {
371 if (hx->Hit2DPtr() == hy->Hit2DPtr())
continue;
373 if (
pma::Dist2(hx->Point2D(), hy->Point2D()) < rad2) n++;
378 trackHits.push_back(hx);
385 std::vector<const tss::Hit2D*>& trackHits,
386 std::vector<const tss::Hit2D*>& emHits)
const 393 for (
const auto& cx : inp) {
394 if (!cx.size())
continue;
396 for (
const auto hx : cx.hits()) {
398 for (
const auto& cy : inp) {
399 if (!cy.size())
continue;
401 for (
const auto hy : cy.hits()) {
402 if (hx->Hit2DPtr() == hy->Hit2DPtr())
continue;
404 if (
pma::Dist2(hx->Point2D(), hy->Point2D()) < rad2) n++;
410 trackHits.push_back(hx);
422 bool clunder =
false;
424 bool clright =
false;
426 if (cl2.
isEM())
return false;
430 TVector2 point((cl2.
max()).
X(), (cl2.
min()).
Y());
431 float width = (cl2.
max()).
X() - (cl2.
min()).
X();
432 float height = (cl2.
max()).
Y() - (cl2.
min()).
Y();
434 for (
unsigned int h = 0; h < cl1.
size(); h++) {
435 float wire = cl1[h].Point2D().X();
436 float drift = cl1[h].Point2D().Y();
438 if ((wire <= (point.X() + shift)) && (wire >= (point.X() - width - shift))) {
439 if (drift < point.Y()) { clover =
true; }
440 else if (drift > (point.Y() + height)) {
444 if (wire > point.X()) { clleft =
true; }
445 else if (wire < (point.X() - width)) {
451 if (clover && clunder && clleft && clright)
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)
const std::vector< const tss::Hit2D * > & hits(void) const
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)
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
TVector2 GetProjectionToSegment(const TVector2 &p, const TVector2 &p0, const TVector2 &p1)
bool Cl2InsideCl1(tss::Cluster2D &cl1, tss::Cluster2D &cl2) const
T get(std::string const &key) const
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
std::vector< TrajPoint > seeds
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
const TVector2 min(void) const
tss::SimpleClustering fSimpleClustering
void splitHits(const std::vector< tss::Cluster2D > &inp, std::vector< const tss::Hit2D * > &trackHits, std::vector< const tss::Hit2D * > &emHits) const