24 fMaxSegStopFactor(8.0F),
26 fSegStopValue(2), fMinSegStop(2), fMaxSegStop(2),
66 for (
auto const& node : src.
fNodes)
fNodes.push_back(
new pma::Node3D(node->Point3D(), node->TPC(), node->Cryo(), node->IsVertex(), node->GetDriftShift()));
76 for (
size_t i = 0; i <
fHits.size(); i++)
delete fHits[i];
80 for (
size_t i = 0; i <
fNodes.size(); i++)
88 mf::LogError(
"pma::Track3D") <<
"Need min. 2 hits per view, at least two views.";
95 mf::LogError(
"pma::Track3D") <<
"Only one cryostat for now, please.";
98 int cryo = cryos.front();
103 mf::LogError(
"pma::Track3D") <<
"Only one TPC, please.";
107 int tpc = tpcs.front();
122 for (
size_t i = 0; i <
fNodes.size(); i++)
delete fNodes[i];
128 auto const* detprop = lar::providerFrom<detinfo::DetectorPropertiesService>();
135 TVector3 v3d_1(0., 0., 0.), v3d_2(0., 0., 0.);
145 float minX = detprop->ConvertTicksToX(hit0_a->
PeakTime(), hit0_a->
View2D(), tpc, cryo);
146 float maxX = detprop->ConvertTicksToX(hit1_a->
PeakTime(), hit1_a->
View2D(), tpc, cryo);
147 for (
size_t i = 1; i <
size(); i++)
150 x = detprop->ConvertTicksToX(hit->
PeakTime(), hit->
View2D(), tpc, cryo);
151 if (x < minX) { minX =
x; hit0_a = hit; }
152 if (x > maxX) { maxX =
x; hit1_a = hit; }
155 float diff, minDiff0 = 5000, minDiff1 = 5000;
156 for (
size_t i = 0; i <
size(); i++)
159 x = detprop->ConvertTicksToX(hit->
PeakTime(), hit->
View2D(), tpc, cryo);
160 diff = fabs(x - minX);
161 if ((diff < minDiff0) && (hit->
View2D() != hit0_a->
View2D()))
163 minDiff0 = diff; hit0_b = hit;
165 diff = fabs(x - maxX);
166 if ((diff < minDiff1) && (hit->
View2D() != hit1_a->
View2D()))
168 minDiff1 = diff; hit1_b = hit;
172 if (hit0_a && hit0_b && hit1_a && hit1_b)
175 detprop->ConvertTicksToX(hit0_a->
PeakTime(), hit0_a->
View2D(), tpc, cryo) +
176 detprop->ConvertTicksToX(hit0_b->
PeakTime(), hit0_b->
View2D(), tpc, cryo));
177 geom->IntersectionPoint(hit0_a->
Wire(), hit0_b->
Wire(),
179 v3d_1.SetXYZ(x, y, z);
182 detprop->ConvertTicksToX(hit1_a->
PeakTime(), hit1_a->
View2D(), tpc, cryo) +
183 detprop->ConvertTicksToX(hit1_b->
PeakTime(), hit1_b->
View2D(), tpc, cryo));
184 geom->IntersectionPoint(hit1_a->
Wire(), hit1_b->
Wire(),
186 v3d_2.SetXYZ(x, y, z);
194 Optimize(0, 0.01F,
false,
true, 100);
221 TVector3
mean(0., 0., 0.), stdev(0., 0., 0.), p(0., 0., 0.);
226 p.SetXYZ( p.X()*p.X(), p.Y()*p.Y(), p.Z()*p.Z() );
232 p.SetXYZ( p.X()*p.X(), p.Y()*p.Y(), p.Z()*p.Z() );
235 double sx = stdev.X(), sy = stdev.Y(), sz = stdev.Z();
236 if (sx >= 0.0) sx = sqrt(sx);
238 if (sy >= 0.0) sy = sqrt(sy);
240 if (sz >= 0.0) sz = sqrt(sz);
242 stdev.SetXYZ(sx, sy, sz);
244 double scale = 2.0 * stdev.Mag();
245 double iscale = 1.0 /
scale;
247 size_t max_index = 0;
248 double norm2, max_norm2 = 0.0;
249 std::vector< TVector3 > data;
256 if (norm2 > max_norm2)
264 double y = 0.0, kappa = 1.0, prev_kappa, kchg = 1.0;
265 TVector3
w(data[max_index]);
267 while (kchg > 0.0001)
268 for (
size_t i = 0; i < data.size(); i++)
271 w += (y/kappa) * (data[i] - y*w);
275 kchg = fabs((kappa - prev_kappa) / prev_kappa);
279 TVector3 v1(w), v2(w);
293 Optimize(0, 0.01F,
false,
true, 100);
303 const auto& tpcGeo = geom->
TPC(tpc, cryo);
305 double minX = tpcGeo.
MinX(), maxX = tpcGeo.MaxX();
306 double minY = tpcGeo.MinY(),
maxY = tpcGeo.MaxY();
307 double minZ = tpcGeo.MinZ(), maxZ = tpcGeo.MaxZ();
309 TVector3 v3d_1(0.5 * (minX + maxX), 0.5 * (minY +
maxY), 0.5 * (minZ + maxZ));
310 TVector3 v3d_2(v3d_1);
312 TVector3 shift(5.0, 5.0, 5.0);
328 for (
size_t i = 0; i <
fNodes.size(); ++i)
329 if (
fNodes[i] == n)
return (
int)i;
335 for (
size_t i = 0; i <
size(); i++)
336 if (
fHits[i] == hit)
return (
int)i;
349 for (
auto const& trk_hit :
fHits)
351 if (trk_hit->fHit == hit)
return false;
361 for (
size_t i = 0; i <
size(); i++)
363 if (hit ==
fHits[i]->fHit)
367 delete h3d;
return true;
377 for (
auto s :
fSegments) {
if (
s->HasHit(h))
return s->GetDirection3D(); }
378 for (
auto n :
fNodes) {
if (
n->HasHit(h))
return n->GetDirection3D(); }
383 mf::LogWarning(
"pma::Track3D") <<
"GetDirection3D(): had to update hit assignment to segment/node.";
388 throw cet::exception(
"pma::Track3D") <<
"GetDirection3D(): direction of a not assigned hit " 389 << index <<
" (size: " <<
fHits.size() <<
")" << std::endl;
409 for (
size_t i = 0; i <
fHits.size(); i++)
411 if (
fHits[i]->View2D() == view) n++;
419 for (
size_t i = 0; i <
size(); i++)
430 unsigned int nviews = 0;
439 std::vector< unsigned int > tpc_idxs;
440 for (
size_t i = 0; i <
size(); i++)
442 unsigned int tpc =
fHits[i]->TPC();
445 for (
size_t j = 0; j < tpc_idxs.size(); j++)
446 if (tpc_idxs[j] == tpc) { found =
true;
break; }
448 if (!found) tpc_idxs.push_back(tpc);
455 std::vector< unsigned int > cryo_idxs;
456 for (
size_t i = 0; i <
size(); i++)
458 unsigned int cryo =
fHits[i]->Cryo();
461 for (
size_t j = 0; j < cryo_idxs.size(); j++)
462 if (cryo_idxs[j] == cryo) { found =
true;
break; }
464 if (!found) cryo_idxs.push_back(cryo);
471 std::pair< TVector2, TVector2 > range(TVector2(0., 0.), TVector2(0., 0.));
474 while ((n0 <
fNodes.size()) && (
fNodes[n0]->TPC() != (int)tpc)) n0++;
479 while ((n1 <
fNodes.size()) && (
fNodes[n1]->TPC() == (int)tpc)) n1++;
482 if (n1 ==
fNodes.size()) n1--;
484 TVector2 p0 =
fNodes[n0]->Projection2D(view);
487 TVector2 p1 =
fNodes[n1]->Projection2D(view);
490 if (p0.X() > p1.X()) {
double tmp = p0.X(); p0.Set(p1.X(), p0.Y()); p1.Set(tmp, p1.Y()); }
491 if (p0.Y() > p1.Y()) {
double tmp = p0.Y(); p0.Set(p0.X(), p1.Y()); p1.Set(p1.X(),
tmp); }
501 if (
fNodes.size() < 2) {
return true; }
503 std::vector< pma::Track3D* > toSort;
519 allTracks.push_back(u);
520 if (u->
Flip(allTracks))
523 toSort.push_back(
this);
527 mf::LogWarning(
"pma::Track3D") <<
"Flip(): Could not flip after split (but new track is preserved!!).";
531 else {
return false; }
533 else {
throw cet::exception(
"pma::Track3D") <<
"Node not found." << std::endl; }
537 if (t->
Flip(allTracks))
540 toSort.push_back(
this);
542 else {
return false; }
548 toSort.push_back(
this);
551 for (
size_t t = 0; t < toSort.size(); t++)
554 for (
size_t u = 0; u < t; u++)
555 if (toSort[u] == toSort[t]) { sorted =
true;
break; }
558 toSort[t]->MakeProjection();
559 toSort[t]->SortHits();
567 for (
size_t i = 0; i <
fNodes.size() - 1; i++)
568 if (
fNodes[i]->NextCount() > 1)
570 for (
size_t j = 0; j <
fNodes[i]->NextCount(); j++)
577 if (
fNodes.back()->NextCount())
578 for (
size_t j = 0; j <
fNodes.back()->NextCount(); j++)
581 toSort.push_back(s->
Parent());
584 if (
fNodes.front()->Prev())
587 toSort.push_back(s->
Parent());
592 toSort.push_back(
this);
598 std::vector< pma::Track3D* > toSort;
600 toSort.push_back(
this);
602 for (
size_t t = 0; t < toSort.size(); t++)
605 for (
size_t u = 0; u < t; u++)
606 if (toSort[u] == toSort[t]) { sorted =
true;
break; }
609 toSort[t]->MakeProjection();
610 toSort[t]->SortHits();
617 if (!
fNodes.size()) {
return false; }
627 else {
return true; }
632 unsigned int nViews = 3;
634 for (
unsigned int i = 0; i < nViews; i++)
638 unsigned int bestView = 2;
639 if (dedxInViews[0].
size() > 2 * dedxInViews[2].
size()) bestView = 0;
640 if (dedxInViews[1].
size() > 2 * dedxInViews[2].
size()) bestView = 1;
642 std::vector< std::vector<double> > dedx;
643 for (
size_t i = 0; i <
size(); i++)
645 auto it = dedxInViews[bestView].find(i);
646 if (it != dedxInViews[bestView].
end())
648 dedx.push_back(it->second);
651 if (!dedx.empty()) dedx.pop_back();
653 float dEdxStart = 0.0F, dEdxStop = 0.0F;
654 float dEStart = 0.0F, dxStart = 0.0F;
655 float dEStop = 0.0F, dxStop = 0.0F;
660 if (dedx.size() > 30) n = 12;
661 else if (dedx.size() > 20) n = 8;
662 else if (dedx.size() > 10) n = 4;
666 size_t k = (dedx.size() - 2) >> 1;
669 for (
size_t i = 1, j = 0; j <
n; i++, j++)
671 dEStart += dedx[i][5]; dxStart += dedx[i][6];
673 if (dxStart > 0.0F) dEdxStart = dEStart / dxStart;
675 for (
size_t i = dedx.size() - 2, j = 0; j <
n; i--, j++)
677 dEStop += dedx[i][5]; dxStop += dedx[i][6];
679 if (dxStop > 0.0F) dEdxStop = dEStop / dxStop;
681 else if (dedx.size() == 4)
683 dEStart = dedx[0][5] + dedx[1][5]; dxStart = dedx[0][6] + dedx[1][6];
684 dEStop = dedx[2][5] + dedx[3][5]; dxStop = dedx[2][6] + dedx[3][6];
685 if (dxStart > 0.0F) dEdxStart = dEStart / dxStart;
686 if (dxStop > 0.0F) dEdxStop = dEStop / dxStop;
689 else if (dedx.size() > 1)
691 if (dedx.front()[2] > 0.0F) dEdxStart = dedx.front()[5] / dedx.front()[6];
692 if (dedx.back()[2] > 0.0F) dEdxStop = dedx.back()[5] / dedx.back()[6];
698 mf::LogVerbatim(
"pma::Track3D") <<
"Auto-flip fired (1), thr: " << (1.0+thr) <<
", value: " << dEdxStart/dEdxStop;
703 mf::LogVerbatim(
"pma::Track3D") <<
"Auto-flip fired (2), thr: " << (1.0+thr) <<
", value: " << dEdxStop/dEdxStart;
710 unsigned int nViews = 3;
712 for (
unsigned int i = 0; i < nViews; i++)
716 unsigned int bestView = 2;
717 if (dedxInViews[0].
size() > 2 * dedxInViews[2].
size()) bestView = 0;
718 if (dedxInViews[1].
size() > 2 * dedxInViews[2].
size()) bestView = 1;
720 std::vector< std::vector<double> > dedx;
721 for (
size_t i = 0; i <
size(); i++)
723 auto it = dedxInViews[bestView].find(i);
724 if (it != dedxInViews[bestView].
end())
726 dedx.push_back(it->second);
729 if (!dedx.empty()) dedx.pop_back();
731 float dEdxStart = 0.0F, dEdxStop = 0.0F;
732 float dEStart = 0.0F, dxStart = 0.0F;
733 float dEStop = 0.0F, dxStop = 0.0F;
738 if (dedx.size() > 30) n = 12;
739 else if (dedx.size() > 20) n = 8;
740 else if (dedx.size() > 10) n = 4;
744 size_t k = (dedx.size() - 2) >> 1;
747 for (
size_t i = 1, j = 0; j <
n; i++, j++)
749 dEStart += dedx[i][5]; dxStart += dedx[i][6];
751 if (dxStart > 0.0F) dEdxStart = dEStart / dxStart;
753 for (
size_t i = dedx.size() - 2, j = 0; j <
n; i--, j++)
755 dEStop += dedx[i][5]; dxStop += dedx[i][6];
757 if (dxStop > 0.0F) dEdxStop = dEStop / dxStop;
759 else if (dedx.size() == 4)
761 dEStart = dedx[0][5] + dedx[1][5]; dxStart = dedx[0][6] + dedx[1][6];
762 dEStop = dedx[2][5] + dedx[3][5]; dxStop = dedx[2][6] + dedx[3][6];
763 if (dxStart > 0.0F) dEdxStart = dEStart / dxStart;
764 if (dxStop > 0.0F) dEdxStop = dEStop / dxStop;
767 else if (dedx.size() > 1)
769 if (dedx.front()[2] > 0.0F) dEdxStart = dedx.front()[5] / dedx.front()[6];
770 if (dedx.back()[2] > 0.0F) dEdxStop = dedx.back()[5] / dedx.back()[6];
777 mf::LogVerbatim(
"pma::Track3D") <<
"Auto-flip fired (1), thr: " << (1.0+thr) <<
", value: " << dEdxStart/dEdxStop;
778 done =
Flip(allTracks);
782 mf::LogVerbatim(
"pma::Track3D") <<
"Auto-flip fired (2), thr: " << (1.0+thr) <<
", value: " << dEdxStop/dEdxStart;
783 done =
Flip(allTracks);
792 mf::LogWarning(
"pma::Track3D") <<
"TestHitsMse(): Empty cluster.";
797 for (
auto const & h :
hits)
799 unsigned int cryo = h->WireID().Cryostat;
800 unsigned int tpc = h->WireID().TPC;
801 unsigned int view = h->WireID().Plane;
802 unsigned int wire = h->WireID().Wire;
803 float drift = h->PeakTime();
807 if (normalized)
return mse / hits.size();
820 double tst, d2 = dist * dist;
821 unsigned int nhits = 0;
822 for (
auto const & h :
hits)
825 if (tst < d2) nhits++;
833 if (
size() < 2)
return 0.0;
837 size_t tmp = stop; stop = start; start =
tmp;
839 if (start >=
size() - 1)
return 0.0;
840 if (stop >=
size()) stop =
size() - 1;
846 size_t i = start + step;
864 if (index < -1) index = -1;
865 while (++index < (
int)
size())
868 if (hit->
View2D() == view)
870 if (inclDisabled)
break;
880 if (index > (
int)
size()) index = (int)
size();
884 if (hit->
View2D() == view)
886 if (inclDisabled)
break;
899 if (hit->
View2D() != view)
901 mf::LogWarning(
"pma::Track3D") <<
"Function used with the hit not matching specified view.";
905 bool hitFound =
false;
910 while (!hitFound && (++i < (
int)
size()))
915 if (nexthit->
View2D() == view) hitFound =
true;
916 else hitFound =
false;
928 while (!hitFound && (--i >= 0))
933 if (nexthit->
View2D() == view) hitFound =
true;
934 else hitFound =
false;
961 mf::LogError(
"pma::Track3D") <<
"Hit index out of range.";
974 if (seg && (seg->
Parent() ==
this))
return seg;
985 if (seg->
Parent() ==
this)
return seg;
991 std::map<
size_t, std::vector<double> > & dedx,
992 unsigned int view,
unsigned int skip,
993 bool inclDisabled)
const 997 if (!
size())
return 0.0;
1003 double rv, dr, dR, dq, dEq, qSkipped = 0.0;
1005 size_t j =
NextHit(-1, view, inclDisabled),
s = skip;
1006 if (j >=
size())
return 0.0F;
1011 if (
s) { qSkipped += dq;
s--; }
1014 j =
NextHit(j, view, inclDisabled);
1017 size_t jmax =
PrevHit(
size(), view, inclDisabled);
1019 std::vector< size_t > indexes;
1020 TVector3 p0(0., 0., 0.), p1(0., 0., 0.);
1021 TVector2 c0(0., 0.),
c1(0., 0.);
1026 indexes.push_back(j);
1043 while (((m < step) || (dR < 0.1) || (dr == 0.0)) && (j <= jmax))
1046 if (j > jmax)
break;
1051 if (dr == 0.0)
continue;
1054 indexes.push_back(j);
1070 p0 += p1; p0 *= 0.5;
1071 c0 +=
c1; c0 *= 0.5;
1073 double range =
Length(0, j);
1075 std::vector<double> trk_section;
1076 trk_section.push_back(c0.X());
1077 trk_section.push_back(c0.Y());
1078 trk_section.push_back(p0.X());
1079 trk_section.push_back(p0.Y());
1080 trk_section.push_back(p0.Z());
1081 trk_section.push_back(dEq);
1082 trk_section.push_back(dR);
1083 trk_section.push_back(range);
1085 for (
auto const idx : indexes) dedx[idx] = trk_section;
1087 j =
NextHit(j, view, inclDisabled);
1095 std::vector<float> drifts;
1096 for (
size_t i = 0; i <
fNodes.size() - 1; i++)
1099 if ((tpc !=
fNodes[i + 1]->TPC()) || (cryo !=
fNodes[i + 1]->Cryo()))
continue;
1102 fNodes[i]->Projection2D(view).
X(),
fNodes[i]->Projection2D(view).
Y(),
1105 fNodes[i + 1]->Projection2D(view).
X(),
fNodes[i + 1]->Projection2D(view).
Y(),
1108 if ((p0.X() - wire) * (p1.X() - wire) <= 0.0)
1110 double frac_w = (wire - p0.X()) / (p1.X() - p0.X());
1111 double d = p0.Y() + frac_w * (p1.Y() - p0.Y());
1112 drifts.push_back((
float)d);
1120 int dPrev, dw,
w, wx, wPrev, i =
NextHit(-1, view);
1126 std::vector< pma::Hit3D* > missHits;
1128 while (i < (
int)
size())
1137 if (hit->
View2D() == view)
1144 wPrev = hitPrev->
Wire();
1146 if (abs(w - wPrev) > 1)
1148 if (w > wPrev) dw = 1;
1155 unsigned int iWire = wx;
1159 peakTime = drifts[0];
1160 for (
size_t d = 1;
d < drifts.size();
d++)
1161 if (fabs(drifts[
d] - dPrev) < fabs(peakTime - dPrev))
1162 peakTime = drifts[
d];
1167 <<
"Track does not intersect with the wire " << wx;
1171 iWire, view, hit->
TPC(), hit->
Cryo(), peakTime, 1.0, 1.0);
1172 missHits.push_back(hmiss);
1181 while ((i < (
int)
size()) && (hit->
TPC() !=
fHits[i]->TPC()))
1183 hitPrev = hit; hit =
fHits[i];
1188 if (missHits.size())
1190 for (
size_t hi = 0; hi < missHits.size(); hi++)
1200 return missHits.size();
1224 if (!maxSeg)
return false;
1226 unsigned int nHitsByView[3];
1227 unsigned int nHits, maxHits = 0;
1228 unsigned int vIndex = 0, segHits, maxSegHits = 0;
1229 float segLength, maxLength = maxSeg->
Length();
1230 for (
unsigned int i = si + 1; i <
fNodes.size(); i++)
1238 segHits = nHitsByView[0] + nHitsByView[1] + nHitsByView[2];
1242 if ((nHitsByView[0] == 0) && ((nHitsByView[1] < 4) || (nHitsByView[2] < 4)))
continue;
1243 if ((nHitsByView[1] == 0) && ((nHitsByView[0] < 4) || (nHitsByView[2] < 4)))
continue;
1244 if ((nHitsByView[2] == 0) && ((nHitsByView[0] < 4) || (nHitsByView[1] < 4)))
continue;
1249 if (nHits > maxHits)
1252 maxLength = seg->
Length();
1253 maxSegHits = segHits;
1257 else if (nHits == maxHits)
1259 segLength = seg->
Length();
1260 if (segLength > maxLength)
1262 maxLength = segLength;
1263 maxSegHits = segHits;
1279 unsigned int maxViewIdx = 2, midViewIdx = 2;
1280 if ((nHitsByView[2] >= nHitsByView[1]) && (nHitsByView[1] >= nHitsByView[0])) { maxViewIdx = 2; midViewIdx = 1; }
1281 else if ((nHitsByView[1] >= nHitsByView[2]) && (nHitsByView[2] >= nHitsByView[0])) { maxViewIdx = 1; midViewIdx = 2; }
1282 else if ((nHitsByView[0] >= nHitsByView[2]) && (nHitsByView[2] >= nHitsByView[1])) { maxViewIdx = 0; midViewIdx = 2; }
1283 else if ((nHitsByView[2] >= nHitsByView[0]) && (nHitsByView[0] >= nHitsByView[1])) { maxViewIdx = 2; midViewIdx = 0; }
1284 else if ((nHitsByView[0] >= nHitsByView[1]) && (nHitsByView[1] >= nHitsByView[2])) { maxViewIdx = 0; midViewIdx = 1; }
1285 else if ((nHitsByView[1] >= nHitsByView[0]) && (nHitsByView[0] >= nHitsByView[2])) { maxViewIdx = 1; midViewIdx = 0; }
1286 if (nHitsByView[midViewIdx] < 2) midViewIdx = maxViewIdx;
1288 if (nHitsByView[midViewIdx] < 2) {
mf::LogVerbatim(
"pma::Track3D") <<
"AddNode(): too few hits.";
return false; }
1290 unsigned int mHits[3] = { 0, 0, 0 };
1291 unsigned int halfIndex = (nHitsByView[midViewIdx] >> 1) - 1;
1292 unsigned int n = 0, i = 0, i0 = 0, i1 = 0;
1293 while (i < maxSeg->
NHits() - 1)
1298 if (maxSeg->
Hit(i).
View2D() == midViewIdx)
1300 if (n == halfIndex)
break;
1314 if (!nHitsByView[0])
1316 if (nHitsByView[1] && (mHits[1] < 2)) {
mf::LogVerbatim(
"pma::Track3D") <<
"AddNode(): low Ind2 hits.";
return false; }
1317 if (nHitsByView[2] && (mHits[2] < 2)) {
mf::LogVerbatim(
"pma::Track3D") <<
"AddNode(): low Coll hits.";
return false; }
1323 unsigned int tpc = maxSeg->
Hit(i0).
TPC();
1324 unsigned int cryo = maxSeg->
Hit(i0).
Cryo();
1343 TVector3
const & p3d,
size_t at_idx,
1344 unsigned int tpc,
unsigned int cryo)
1372 if (!idx || (idx + 1 >=
fNodes.size()))
return 0;
1378 for (
size_t i = 0; i < idx; ++i)
1387 while (k < n->NextCount())
1407 unsigned int view = h3d->
View2D(), tpc = h3d->
TPC(), cryo = h3d->
Cryo();
1408 double dist2D_old =
Dist2(h3d->
Point2D(), view, tpc, cryo);
1409 double dist2D_new = t0->
Dist2(h3d->
Point2D(), view, tpc, cryo);
1419 if (try_start_at_idx && t0->
CanFlip())
1421 mf::LogVerbatim(
"pma::Track3D") <<
" attach new t0 and this trk to a common start node";
1427 mf::LogVerbatim(
"pma::Track3D") <<
" attach this trk to the new t0 end node";
1442 for (
size_t i = 0; i < idx; ++i)
1460 if (vtx == vStart)
return true;
1487 for (
auto n :
fNodes)
if (
n == vStart) {
mf::LogError(
"pma::Track3D") <<
"Don't create loops!";
return false; }
1489 if ( !noFlip &&
CanFlip() && (vStart->
TPC() == fNodes.back()->TPC()) &&
1491 (fNodes.back()->NextCount() == 0) )
1493 mf::LogError(
"pma::Track3D") <<
"Flip, endpoint closer to vStart.";
1504 if (
fNodes.front()->Prev())
return false;
1555 mf::LogError(
"pma::Track3D") <<
"Flips in vtx and vStart not possible, cannot attach.";
1581 throw cet::exception(
"pma::Track3D") <<
"Something is still using disconnected vertex.";
1591 if (vtx == vStart)
return true;
1618 for (
auto n :
fNodes)
if (
n == vStart) {
mf::LogError(
"pma::Track3D") <<
"Don't create loops!";
return false; }
1626 if (vStart->
Prev())
return false;
1630 fNodes.push_back(vStart);
1632 size_t idx =
fNodes.size() - 1;
1648 mf::LogError(
"pma::Track3D") <<
"Cannot attach back to inner node of other track.";
1656 mf::LogError(
"pma::Track3D") <<
"Flip not possible, cannot attach.";
1677 throw cet::exception(
"pma::Track3D") <<
"Something is still using disconnected vertex." << std::endl;
1686 if (src->
fNodes.front()->Prev())
1688 throw cet::exception(
"pma::Track3D") <<
"Cant extend with a track being a daughter of another track." << std::endl;
1692 for (
size_t i = 0; i < src->
fNodes.size(); ++i)
1696 size_t idx =
fNodes.size() - 1;
1720 if (!trk) trk =
this;
1722 else throw cet::exception(
"pma::Track3D") <<
"Broken track, no nodes.";
1729 for (
auto trk : branches)
if (
trk ==
this)
1737 branches.push_back(
this);
1740 if (skipFirst) i0 = 1;
1742 for (
size_t i = i0; i <
fNodes.size(); ++i)
1743 for (
size_t n = 0;
n <
fNodes[i]->NextCount();
n++)
1754 if (trk ==
this)
return true;
1756 std::vector< pma::Track3D const * > branchesThis, branchesTrk;
1761 for (
auto bThis : branchesThis)
1762 for (
auto bTrk : branchesTrk)
1763 if (bThis == bTrk)
return true;
1770 if (point == p)
return true;
1776 double sumMse = 0.0;
1777 unsigned int nEnabledHits = 0;
1780 sumMse +=
n->SumDist2(view);
1781 nEnabledHits +=
n->NEnabledHits(view);
1785 sumMse +=
s->SumDist2(view);
1786 nEnabledHits +=
s->NEnabledHits(view);
1789 if (nEnabledHits)
return sumMse / nEnabledHits;
1797 for (
size_t i = 0; i <
fNodes.size(); i++)
1801 return sum /
fNodes.size();
1804 double pma::Track3D::Optimize(
int nNodes,
double eps,
bool selAllHits,
bool setAllNodes,
size_t selSegHits,
size_t selVtxHits)
1806 if (!
fNodes.size()) {
mf::LogError(
"pma::Track3D") <<
"Track not initialized.";
return 0.0; }
1810 if (g0 == 0.0)
return g0;
1816 for (
auto n :
fNodes)
n->SetVertexToBranching(setAllNodes);
1823 if (selSegHits || selVtxHits)
SelectRndHits(selSegHits, selVtxHits);
1825 bool stepDone =
true;
1826 unsigned int stepIter = 0;
1830 unsigned int iter = 0;
1831 while ((gstep > eps) && (iter < 1000))
1844 gstep = fabs(g0 - g1) / g0;
1849 if (fNodes.size() > 2)
1854 }
while (!stepDone && (stepIter < 5));
1866 case 0: stop =
true;
break;
1885 else {
mf::LogVerbatim(
"pma::Track3D") <<
"stop (3)"; stop =
true;
break; }
1893 else if (nNodes > 4)
1896 else {
mf::LogVerbatim(
"pma::Track3D") <<
"stop (2)"; stop =
true;
break; }
1903 else {
mf::LogVerbatim(
"pma::Track3D") <<
"stop (1)"; stop =
true;
break; }
1917 const size_t maxTreeDepth = 100;
1918 static size_t depth;
1931 if (++depth > maxTreeDepth)
1933 mf::LogError(
"pma::Track3D") <<
"Tree depth above allowed max.";
1942 for (
size_t i = 0; i < vtx->
NextCount(); i++)
1977 for (
size_t i = 0; i < vtx->
NextCount(); i++)
1991 const TVector3& p3d_cm,
double& dist,
bool skipFirst)
2004 dist = sqrt(
Dist2(p3d_cm) );
2012 for (
size_t i = 0; i < vtx->
NextCount(); i++)
2018 if (d < dist) { dist =
d; result = candidate; }
2030 const TVector2& p2d_cm,
unsigned view,
unsigned int tpc,
unsigned int cryo,
2031 double& dist,
bool skipFirst)
2044 dist =
Dist2(p2d_cm, view, tpc, cryo);
2052 for (
size_t i = 0; i < vtx->
NextCount(); i++)
2058 if (d < dist) { dist =
d; result = candidate; }
2073 if (trkRoot) skipFirst =
true;
2074 else { trkRoot =
this; skipFirst =
false; }
2090 for (
size_t i = 0; i < vtx->
NextCount(); i++)
2110 if ((nearestTrk !=
this) && (dmin < 0.5 * d0))
2113 mf::LogVerbatim(
"pma::Track3D") <<
"*** hit moved to another track ***";
2119 mf::LogError(
"pma::Track3D") <<
"ALL hits moved to other tracks.";
2139 for (
size_t i = 0; i < vtx->
NextCount(); i++)
2168 for (
size_t i = 0; i < vtx->
NextCount(); i++)
2198 for (
size_t i = 0; i < vtx->
NextCount(); i++)
2215 mf::LogError(
"pma::Track3D") <<
"TuneFullTree failed.";
2222 mf::LogError(
"pma::Track3D") <<
"Infinifte value of g.";
2232 if (g0 == 0.0)
return g0;
2236 unsigned int stepIter = 0;
2240 unsigned int iter = 0;
2241 while ((gstep > eps) && (iter < 60))
2251 if (g0 == 0.0F)
break;
2253 gstep = fabs(g0 - g1) / g0;
2259 }
while (stepIter < 5);
2266 if (g0 >= 0) {
mf::LogVerbatim(
"pma::Track3D") <<
" done, g = " << g0; }
2267 else {
mf::LogError(
"pma::Track3D") <<
"TuneFullTree failed."; }
2288 for (
size_t i = 0; i < node->
NextCount(); i++)
2303 double newdx =
fNodes.front()->GetDriftShift();
2312 auto const* detprop = lar::providerFrom<detinfo::DetectorPropertiesService>();
2313 auto const* detclock = lar::providerFrom<detinfo::DetectorClocksService>();
2314 auto const* geom = lar::providerFrom<geo::Geometry>();
2319 double correctedSign = 0;
2320 if(tpcGeo.DetectDriftDirection() > 0){
2322 correctedSign = 1.0;
2325 correctedSign = -1.0;
2330 correctedSign = -1.0;
2333 correctedSign = 1.0;
2338 double dxInTicks = fabs(dx / detprop->GetXTicksCoefficient());
2340 dxInTicks = dxInTicks * correctedSign;
2342 double dxInTime = dxInTicks * detclock->TPCClock().TickPeriod();
2346 mf::LogDebug(
"pma::Track3D") << dx <<
", " << dxInTicks <<
", " << correctedSign
2347 <<
", " <<
fT0 <<
", " << tpcGeo.DetectDriftDirection() <<
" :: " 2348 << detclock->TriggerTime() <<
", " << detclock->TriggerOffsetTPC() << std::endl;
2370 for (
size_t i = 1; i <
fNodes.size(); i++)
2378 unsigned int nhits = 0;
2379 while (!nhits && (
fNodes.size() > 2) && !
fNodes.front()->IsBranching())
2382 nhits = vtx->
NHits();
2385 nhits += seg->
NHits();
2400 while (!nhits && (
fNodes.size() > 2) && !
fNodes.back()->IsBranching())
2403 nhits = vtx->
NHits();
2406 nhits += seg->
NHits();
2427 if (!(
fNodes.front()->Prev()))
2436 mf::LogWarning(
"pma::Track3D") <<
"First hit is projected to inner node.";
2447 double l0 = seg->
Length();
2454 mf::LogWarning(
"pma::Track3D") <<
"ShiftEndsToHits(): Short start segment, node removed.";
2465 mf::LogWarning(
"pma::Track3D") <<
"Branching node, not removed.";
2472 mf::LogWarning(
"pma::Track3D") <<
"First hit is projected to inner segment.";
2479 if (!(
fNodes.back()->NextCount()))
2488 mf::LogWarning(
"pma::Track3D") <<
"First hit is projected to inner node.";
2499 double l0 = seg->
Length();
2503 size_t idx =
fNodes.size() - 2;
2507 mf::LogWarning(
"pma::Track3D") <<
"ShiftEndsToHits(): Short end segment, node removed.";
2518 mf::LogWarning(
"pma::Track3D") <<
"Branching node, not removed.";
2525 mf::LogWarning(
"pma::Track3D") <<
"First hit is projected to inner segment.";
2537 double dist, min_dist = 1.0e12;
2539 int t = (int)tpc, c = (
int)cryo;
2540 auto n0 =
fNodes.front();
2541 if ((n0->TPC() == t) && (n0->Cryo() == c))
2543 dist = n0->GetDistance2To(p2d, view);
2544 if (dist < min_dist) min_dist = dist;
2547 if ((n1->TPC() == t) && (n1->Cryo() == c))
2549 dist = n1->GetDistance2To(p2d, view);
2550 if (dist < min_dist) min_dist = dist;
2554 if ((
s->TPC() == t) && (
s->Cryo() == c))
2556 dist =
s->GetDistance2To(p2d, view);
2557 if (dist < min_dist) min_dist = dist;
2564 double dist, min_dist =
fSegments.front()->GetDistance2To(p3d);
2565 for (
size_t i = 1; i <
fSegments.size(); i++)
2567 dist =
fSegments[i]->GetDistance2To(p3d);
2568 if (dist < min_dist) min_dist = dist;
2574 const TVector2& p2d,
unsigned int view,
int tpc,
2575 bool skipFrontVtx,
bool skipBackVtx)
const 2577 if (
fSegments.front()->TPC() < 0) skipFrontVtx =
false;
2578 if (
fSegments.back()->TPC() < 0) skipBackVtx =
false;
2580 if (skipFrontVtx && skipBackVtx && (
fSegments.size() == 1))
2583 size_t v0 = 0, v1 =
fNodes.size();
2584 if (skipFrontVtx) v0 = 1;
2585 if (skipBackVtx) --v1;
2588 double dist, min_dist = 1.0e9;
2589 for (
size_t i = v0; i < v1; i++)
2591 if (
fNodes[i]->TPC() == tpc)
2593 dist =
fNodes[i]->GetDistance2To(p2d, view);
2594 if (dist < min_dist)
2596 min_dist = dist; pe_min =
fNodes[i];
2599 for (
size_t i = 0; i <
fSegments.size(); i++)
2605 dist =
fSegments[i]->GetDistance2To(p2d, view);
2606 if (dist < min_dist)
2611 if (!pe_min)
throw cet::exception(
"pma::Track3D") <<
"Nearest element not found." << std::endl;
2619 for (
size_t i = 1; i <
fNodes.size(); i++)
2621 dist =
fNodes[i]->GetDistance2To(p3d);
2622 if (dist < min_dist)
2624 min_dist = dist; pe_min =
fNodes[i];
2627 for (
size_t i = 0; i <
fSegments.size(); i++)
2629 dist =
fSegments[i]->GetDistance2To(p3d);
2630 if (dist < min_dist)
2645 double d2, min_d2 = 1.0e100;
2648 for (
size_t i = 0; i <
fSegments.size(); i++)
2650 if (
fSegments[i]->TPC() != tpc)
continue;
2652 d2 =
fSegments[i]->GetDistance2To(p2d, view);
2660 p3d = seg->GetUnconstrainedProj3D(p2d, view);
2672 std::vector< pma::Hit3D* > hits_tmp;
2673 hits_tmp.reserve(
size());
2680 for (
size_t i = 0; i < vtx->
NHits(); i++)
2683 if (h3d->
fParent ==
this) hits_tmp.push_back(h3d);
2689 for (
size_t i = 0; i < seg->
NHits(); i++)
2692 if (h3d->
fParent ==
this) hits_tmp.push_back(h3d);
2701 if (
size() == hits_tmp.size())
2703 for (
size_t i = 0; i <
size(); i++)
2705 fHits[i] = hits_tmp[i];
2708 else mf::LogError(
"pma::Track3D") <<
"Hit sorting problem.";
2715 unsigned int nDisabled = 0;
2722 bool rebuild =
false, stop =
false;
2724 hasHits[0] = hasHits[1] = hasHits[2] = hasHits[3] = 0;
2733 for (
size_t i = 0; i < vtx->
NHits(); i++)
2736 if ((hitIndex >= 0) && (hitIndex + 1 < (
int)
size())) nextHit =
fHits[hitIndex + 1];
2741 nViews = hasHits[0] + hasHits[1] + hasHits[2] + hasHits[3];
2751 for (
size_t i = 0; i < seg->
NHits(); i++)
2754 if ((hitIndex >= 0) && (hitIndex + 1 < (
int)
size())) nextHit =
fHits[hitIndex + 1];
2759 nViews = hasHits[0] + hasHits[1] + hasHits[2] + hasHits[3];
2770 if (
fNodes.size() < 3)
break;
2772 nViews = hasHits[1] + hasHits[2] + hasHits[3];
2773 if (hasHits[0] || (nViews > 1)) stop =
true;
2774 else if (!
fNodes.front()->IsBranching())
2786 hasHits[0] = hasHits[1] = hasHits[2] = hasHits[3] = 0;
2795 for (
int i = vtx->
NHits() - 1; i >= 0; i--)
2798 if ((hitIndex >= 0) && (hitIndex - 1 >= 0)) nextHit =
fHits[hitIndex - 1];
2803 nViews = hasHits[0] + hasHits[1] + hasHits[2] + hasHits[3];
2813 for (
int i = seg->
NHits() - 1; i >= 0; i--)
2816 if ((hitIndex >= 0) && (hitIndex - 1 >= 0)) nextHit =
fHits[hitIndex - 1];
2821 nViews = hasHits[0] + hasHits[1] + hasHits[2] + hasHits[3];
2832 if (
fNodes.size() < 3)
break;
2834 nViews = hasHits[1] + hasHits[2] + hasHits[3];
2835 if (hasHits[0] || (nViews > 1)) stop =
true;
2836 else if (!
fNodes.back()->IsBranching())
2857 if (fraction < 0.0F) fraction = 0.0F;
2858 if (fraction > 1.0F) fraction = 1.0F;
2861 size_t nHitsColl = (size_t)(fraction *
NHits(
geo::kZ));
2862 size_t nHitsInd2 = (size_t)(fraction *
NHits(
geo::kV));
2863 size_t nHitsInd1 = (size_t)(fraction *
NHits(
geo::kU));
2864 size_t coll = 0, ind2 = 0, ind1 = 0;
2866 bool b, changed =
false;
2867 for (
auto h :
fHits)
2870 if (fraction < 1.0F)
2872 h->SetEnabled(
false);
2873 switch (h->View2D())
2875 case geo::kZ:
if (coll++ < nHitsColl) h->SetEnabled(
true);
break;
2876 case geo::kV:
if (ind2++ < nHitsInd2) h->SetEnabled(
true);
break;
2877 case geo::kU:
if (ind1++ < nHitsInd1) h->SetEnabled(
true);
break;
2880 else h->SetEnabled(
true);
2882 changed |= (b != h->IsEnabled());
2885 if (fraction < 1.0F)
2895 bool changed =
false;
2896 for (
auto n :
fNodes) changed |=
n->SelectRndHits(vtxmax);
2897 for (
auto s :
fSegments) changed |=
s->SelectRndHits(segmax);
2903 bool changed =
false;
2904 for (
auto h :
fHits)
2906 changed |= !(h->IsEnabled());
2907 h->SetEnabled(
true);
2914 for (
auto n :
fNodes)
n->ClearAssigned(
this);
2919 bool skipFrontVtx =
false, skipBackVtx =
false;
2922 if (!(fNodes.front()->IsFrozen()) &&
2923 !(fNodes.front()->Prev()) &&
2924 (fNodes.front()->NextCount() == 1))
2926 skipFrontVtx =
true;
2928 if (!(fNodes.front()->IsFrozen()) &&
2929 (fNodes.back()->NextCount() == 0))
2934 for (
auto h :
fHits)
2936 pe =
GetNearestElement(h->Point2D(), h->View2D(), h->TPC(), skipFrontVtx, skipBackVtx);
2946 for (
auto n : fNodes)
n->UpdateHitParams();
2947 for (
auto s : fSegments)
s->UpdateHitParams();
2952 std::vector< std::pair< pma::Hit3D*, pma::Element3D* > > assignments;
2953 assignments.reserve(
fHits.size());
2955 for (
auto hi :
fHits)
2961 for (
size_t j = 0; j <
s->NHits(); ++j)
2962 if (hi ==
s->Hits()[j])
2965 double d2, min_d2 =
s->GetDistance2To(hi->Point2D(), hi->View2D());
2966 int tpc = hi->TPC();
2969 if (nnext->
TPC() == tpc)
2972 if (d2 < min_d2) { min_d2 = d2; pe = nnext; }
2975 if (snext && (snext->
TPC() == tpc))
2978 if (d2 < min_d2) { min_d2 = d2; pe = snext; }
2981 if (nnext->
TPC() == tpc)
2984 if (d2 < min_d2) { min_d2 = d2; pe = nnext; }
2990 if (nprev->
TPC() == tpc)
2993 if (d2 < min_d2) { min_d2 = d2; pe = nprev; }
2996 if (sprev && (sprev->
TPC() == tpc))
2999 if (d2 < min_d2) { min_d2 = d2; pe = sprev; }
3002 if (nprev->
TPC() == tpc)
3005 if (d2 < min_d2) { min_d2 = d2; pe = nprev; }
3010 s->RemoveHitAt(j);
break;
3015 if (!pe)
for (
auto n :
fNodes)
3017 for (
size_t j = 0; j <
n->NHits(); ++j)
3018 if (hi ==
n->Hits()[j])
3021 double d2, min_d2 =
n->GetDistance2To(hi->Point2D(), hi->View2D());
3022 int tpc = hi->TPC();
3025 if (snext && (snext->
TPC() == tpc))
3028 if (d2 < min_d2) { min_d2 = d2; pe = snext; }
3031 if (nnext->
TPC() == tpc)
3034 if (d2 < min_d2) { min_d2 = d2; pe = nnext; }
3037 if (snext && (snext->
TPC() == tpc))
3040 if (d2 < min_d2) { min_d2 = d2; pe = snext; }
3046 if (sprev && (sprev->
TPC() == tpc))
3049 if (d2 < min_d2) { min_d2 = d2; pe = sprev; }
3052 if (nprev->
TPC() == tpc)
3055 if (d2 < min_d2) { min_d2 = d2; pe = nprev; }
3058 if (sprev && (sprev->
TPC() == tpc))
3061 if (d2 < min_d2) { min_d2 = d2; pe = sprev; }
3066 n->RemoveHitAt(j);
break;
3071 if (pe) assignments.emplace_back(hi, pe);
3072 else mf::LogWarning(
"pma::Track3D") <<
"Hit was not assigned to any element.";
3075 for (
auto const & a : assignments) a.second->AddHit(a.first);
3077 for (
auto n :
fNodes)
n->UpdateHitParams();
3083 for (
auto n :
fNodes)
n->UpdateProjection();
3090 unsigned int count = 0;
3094 sum +=
n->SumDist2();
3095 count +=
n->NEnabledHits();
3100 sum +=
s->SumDist2();
3101 count +=
s->NEnabledHits();
3104 if (count) {
return sum / count; }
3107 mf::LogError(
"pma::Track3D") <<
"0 enabled hits in AverageDist2 calculation.";
3122 float nCubeRoot = pow((
double)n, 1.0/3.0);
3124 if (avgDist2Root > 0)
3142 if (v0 == v1)
return false;
3157 fNodes[v1]->RemoveNext(nextSeg);
3165 fNodes[v0]->AddNext(midSeg);
3167 if (nextSeg)
fNodes[v1]->AddNext(nextSeg);
3182 unsigned int v1, v2;
3186 if (
fSegments.front()->IsFrozen())
return false;
3187 if (
fNodes.front()->NextCount() > 1)
return false;
3188 v1 = 0; v2 = 1;
break;
3190 if (
fSegments.back()->IsFrozen())
return false;
3191 if (
fNodes.back()->NextCount() > 1)
return false;
3195 default:
return false;
3197 if (
fNodes[v1]->TPC() !=
fNodes[v2]->TPC())
return false;
3216 std::vector< pma::Hit3D* > hitsColl, hitsInd1, hitsInd2;
3217 for (
size_t i = 0; i <
size(); i++)
3222 case geo::kZ: hitsColl.push_back(hit);
break;
3223 case geo::kV: hitsInd2.push_back(hit);
break;
3224 case geo::kU: hitsInd1.push_back(hit);
break;
unsigned int TestHits(const std::vector< art::Ptr< recob::Hit > > &hits, double dist=0.4) const
Count close 2D hits.
bool SelectHits(float fraction=1.0F)
void ApplyDriftShift(double dx)
code to link reconstructed objects back to the MC truth information
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< pma::Segment3D * > fSegments
unsigned int TPC(void) const
pma::Node3D * LastElement(void) const
std::vector< unsigned int > TPCs(void) const
void AutoFlip(pma::Track3D::EDirection dir, double thr=0.0, unsigned int n=0)
void CleanupTails(void)
Cut out tails with no hits assigned.
bool InitFromHits(int tpc, int cryo, float initEndSegW=0.05F)
bool HasTPC(int tpc) const
double GetDistToProj(void) const
virtual bool AddNext(pma::SortedObjectBase *nextElement)
std::vector< float > DriftsOfWireIntersection(unsigned int wire, unsigned int view) const
double GetMse(unsigned int view=geo::kUnknown) const
MSE of hits weighted with hit amplidudes and wire plane coefficients.
void SortHitsInTree(bool skipFirst=false)
bool AttachTo(pma::Node3D *vStart, bool noFlip=false)
double GetHitsRadius2D(const std::vector< pma::Hit3D * > &hits, bool exact=false)
void UpdateProjection(void)
double Dist2(const TVector2 &p2d, unsigned int view, unsigned int tpc, unsigned int cryo) const
unsigned int Cryo(void) const
Implementation of the Projection Matching Algorithm.
void InsertNode(TVector3 const &p3d, size_t at_idx, unsigned int tpc, unsigned int cryo)
bool IsAttachedTo(pma::Track3D const *trk) const
unsigned int View2D(void) const
double Dist2(const TVector2 &v1, const TVector2 &v2)
int PrevHit(int index, unsigned int view=geo::kZ, bool inclDisabled=false) const
bool Flip(std::vector< pma::Track3D * > &allTracks)
TVector3 const & Point3D(void) const
bool IsEnabled(void) const
geo::WireID WireID() const
Initial tdc tick for hit.
void ClearAssigned(pma::Track3D *trk=0) override
void AddPoint(TVector3 *p)
virtual int RemoveNext(pma::SortedObjectBase *nextElement)
::fhicl::TupleAs< Point(::geo::Length_t,::geo::Length_t,::geo::Length_t)> Point3D
Atom object for reading a 3D point or vector (centimeters).
double MinX() const
Returns the world x coordinate of the start of the box.
Geometry information for a single TPC.
int index_of(const pma::Hit3D *hit) const
double GetDistance2To(const TVector3 &p3d) const override
Distance [cm] from the 3D point to the point 3D.
bool AttachBackToSameTPC(pma::Node3D *vStart)
bool GetBranches(std::vector< pma::Track3D const * > &branches, bool skipFirst=false) const
virtual unsigned int NextCount(void) const
bool AttachToOtherTPC(pma::Node3D *vStart)
bool CheckEndSegment(pma::Track3D::ETrackEnd endCode)
double GetObjFunction(float penaltyFactor=1.0F) const
Objective function optimized in track reconstruction.
CryostatID_t Cryostat
Index of cryostat.
void Optimize(float penaltyValue, float endSegWeight)
bool GetUnconstrainedProj3D(art::Ptr< recob::Hit > hit, TVector3 &p3d, double &dist2) const
Planes which measure Z direction.
WireID_t Wire
Index of the wire within its plane.
void DeleteSegments(void)
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
pma::Track3D * Split(size_t idx, bool try_start_at_idx=true)
bool AttachBackToOtherTPC(pma::Node3D *vStart)
void RemoveHits(const std::vector< art::Ptr< recob::Hit > > &hits)
Remove hits; removes also hit->node/seg assignments.
unsigned int Wire(void) const
recob::tracking::Vector_t Vector3D
double TuneFullTree(double eps=0.001, double gmax=50.0)
pma::Vector3D GetDirection3D(size_t index) const
Get trajectory direction at given hit index.
double TuneSinglePass(bool skipFirst=false)
double AverageDist2(void) const
unsigned int NEnabledHits(unsigned int view=geo::kUnknown) const
int TPC(void) const
TPC index or -1 if out of any TPC.
bool ShiftEndsToHits(void)
unsigned int fMaxHitsPerSeg
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
std::pair< TVector2, TVector2 > WireDriftRange(unsigned int view, unsigned int tpc, unsigned int cryo) const
size_t NPoints(void) const
unsigned int fSegStopValue
void ExtendWith(pma::Track3D *src)
Extend the track with everything from src, delete the src;.
pma::Hit3D * release_at(size_t index)
bool isfinite(Vector const &v)
Returns whether all components of the vector are finite.
unsigned int NHits(unsigned int view) const
virtual int RemoveNext(pma::SortedObjectBase *nextElement)
void MakeFastProjection(void)
void InitFromMiddle(int tpc, int cryo)
bool HasRefPoint(TVector3 *p) const
bool CanFlip(void) const
Check if the track can be flipped without breaking any other track.
size_t CompleteMissingWires(unsigned int view)
pma::Hit3D & Hit(size_t index)
void SetEnabled(bool state)
double Optimize(int nNodes=-1, double eps=0.01, bool selAllHits=true, bool setAllNodes=true, size_t selSegHits=0, size_t selVtxHits=0)
Main optimization method.
void UpdateHitsRadius(void)
bool SameTPC(const TVector3 &p3d, float margin=0.0F) const
Check if p3d is in the same TPC as the node.
float SummedADC(void) const
double GetObjFnInTree(bool skipFirst=false)
void InternalFlip(std::vector< pma::Track3D * > &toSort)
bool erase(const art::Ptr< recob::Hit > &hit)
PlaneID_t Plane
Index of the plane within its TPC.
TVector2 const & Point2D(void) const
bool AttachToSameTPC(pma::Node3D *vStart)
double GetDriftShift(void) const
std::vector< unsigned int > Cryos(void) const
void RebuildSegments(void)
Detector simulation of raw signals on wires.
bool SelectRndHits(size_t segmax, size_t vtxmax)
double TestHitsMse(const std::vector< art::Ptr< recob::Hit > > &hits, bool normalized=true) const
MSE of 2D hits.
unsigned int DisableSingleViewEnds(void)
void push_back(pma::Hit3D *hit)
TVector3 const & Point3D(void) const
bool HasTwoViews(size_t nmin=1) const
int Cryo(void) const
Cryostat index or -1 if out of any cryostat.
double mean(const std::vector< short > &wf, size_t start, size_t nsample)
Implementation of the Projection Matching Algorithm.
float PeakTime() const
Time of the signal peak, in tick units.
void MakeProjectionInTree(bool skipFirst=false)
pma::Track3D * GetRoot(void)
virtual pma::SortedObjectBase * Next(unsigned int index=0) const
double Length(size_t step=1) const
bool IsFrozen(void) const
Check if the vertex 3D position is fixed.
bool UpdateParamsInTree(bool skipFirst=false)
pma::Segment3D * PrevSegment(pma::Node3D *vtx) const
bool RemoveNode(size_t idx)
void ReassignHitsInTree(pma::Track3D *plRoot=0)
TVector2 WireDriftToCm(unsigned int wire, float drift, unsigned int plane, unsigned int tpc, unsigned int cryo)
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
bool Initialize(float initEndSegW=0.05F)
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
int NextHit(int index, unsigned int view=geo::kZ, bool inclDisabled=false) const
virtual double GetDistance2To(const TVector3 &p3d) const =0
Distance [cm] from the 3D point to the object 3D.
void MakeProjection(void)
void SetT0FromDx(double dx)
Function to convert dx into dT0.
double GetRawdEdxSequence(std::map< size_t, std::vector< double > > &dedx, unsigned int view=geo::kZ, unsigned int skip=0, bool inclDisabled=false) const
std::vector< pma::Node3D * > fNodes
double HitDxByView(size_t index, unsigned int view) const
TVector2 CmToWireDrift(float xw, float yd, unsigned int plane, unsigned int tpc, unsigned int cryo)
double GetDistance2To(const TVector3 &p3d) const override
Distance [cm] from the 3D segment to the point 3D.
void AddHit(pma::Hit3D *h)
bool SwapVertices(size_t v0, size_t v1)
float PeakTime(void) const
virtual void Disconnect(void)
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
std::map< size_t, std::vector< double > > dedx_map
pma::Track3D * GetNearestTrkInTree(const TVector3 &p3d_cm, double &dist, bool skipFirst=false)
virtual bool AddNext(pma::SortedObjectBase *nextElement)
virtual pma::SortedObjectBase * Prev(void) const
TPCID_t TPC
Index of the TPC within its cryostat.
pma::Track3D * Parent(void) const
std::vector< pma::Hit3D * > fHits
virtual pma::SortedObjectBase * Next(unsigned int index=0) const
bool AttachBackTo(pma::Node3D *vStart)
pma::Node3D * FirstElement(void) const
void SetProjection(pma::Hit3D &h) const override
Set hit 3D position and its 2D projection to the vertex.
pma::Element3D * GetNearestElement(const TVector2 &p2d, unsigned int view, int tpc=-1, bool skipFrontVtx=false, bool skipBackVtx=false) const
pma::Segment3D * NextSegment(pma::Node3D *vtx) const
double Length(void) const
art framework interface to geometry description
size_t NEnabledHits(unsigned int view=geo::kUnknown) const
cet::coded_exception< error, detail::translate > exception
void ApplyDriftShiftInTree(double dx, bool skipFirst=false)
Adjust track tree position in the drift direction (when T0 is being corrected).
std::vector< TVector3 * > fAssignedPoints
void AddHits(const std::vector< art::Ptr< recob::Hit > > &hits)
bool InitFromRefPoints(int tpc, int cryo)