27 using namespace detail;
38 if (slc.
tjs.size() < 2)
return;
41 constexpr
float maxSep = 4;
47 <<
" maxSep btw tjs " << maxSep;
57 junkVx.
ID = USHRT_MAX;
59 junkVx.
PosErr = {{2.0, 2.0}};
64 for (
unsigned short it1 = 0; it1 < slc.
tjs.size() - 1; ++it1) {
65 auto& tj1 = slc.
tjs[it1];
67 if (tj1.SSID > 0 || tj1.AlgMod[
kShowerLike])
continue;
68 if (tj1.CTP != inCTP)
continue;
69 if (tj1.AlgMod[
kJunkTj])
continue;
71 if (tj1.MCSMom < 100)
continue;
72 for (
unsigned short end1 = 0; end1 < 2; ++end1) {
74 if (tj1.VtxID[end1] > 0)
continue;
75 auto& tp1 = tj1.Pts[tj1.EndPt[end1]];
78 if (tjlist.empty())
continue;
80 junkVx.
ID = USHRT_MAX;
81 for (
auto tj2id : tjlist) {
82 auto& tj2 = slc.
tjs[tj2id - 1];
83 if (tj2.CTP != inCTP)
continue;
84 if (tj2id == tj1.ID)
continue;
85 if (tj2.SSID > 0 || tj2.AlgMod[
kShowerLike])
continue;
87 unsigned short closeEnd = USHRT_MAX;
88 for (
unsigned short end2 = 0; end2 < 2; ++end2) {
89 auto& tp2 = tj2.Pts[tj2.EndPt[end2]];
90 float sep =
PosSep(tp1.Pos, tp2.Pos);
96 if (closeEnd > 1)
continue;
97 auto& tp2 = tj2.Pts[tj2.EndPt[closeEnd]];
99 if (!signalBetween)
continue;
100 if (junkVx.
ID == USHRT_MAX) {
102 junkVx.
ID = slc.
vtxs.size() + 1;
103 junkVx.
Pos = tp1.Pos;
105 tj2.VtxID[closeEnd] = junkVx.
ID;
106 tj1.VtxID[end1] = junkVx.
ID;
108 if (junkVx.
ID == USHRT_MAX)
continue;
111 for (
auto& tj : slc.
tjs) {
112 if (tj.AlgMod[
kKilled])
continue;
113 if (tj.VtxID[0] == junkVx.
ID) tj.VtxID[0] = 0;
114 if (tj.VtxID[1] == junkVx.
ID) tj.VtxID[1] = 0;
120 << std::setprecision(1) << junkVx.
Pos[0] <<
":" 123 junkVx.
ID = USHRT_MAX;
154 if (slc.
tjs.size() < 2)
return;
156 bool firstPassCuts = (pass == 0);
161 bool requireVtxTjChg =
true;
166 mf::LogVerbatim(
"TC") <<
"prt set for CTP " << inCTP <<
" in Find2DVertices. firstPassCuts? " 167 << firstPassCuts <<
" requireVtxTjChg " << requireVtxTjChg;
172 for (
unsigned short it1 = 0; it1 < slc.
tjs.size() - 1; ++it1) {
173 auto& tj1 = slc.
tjs[it1];
175 if (tj1.SSID > 0 || tj1.AlgMod[
kShowerLike])
continue;
176 if (tj1.CTP != inCTP)
continue;
177 bool tj1Short = (
TrajLength(tj1) < maxShortTjLen);
178 for (
unsigned short end1 = 0; end1 < 2; ++end1) {
180 if (tj1.VtxID[end1] > 0)
continue;
182 if (tj1.PDGCode == 111 && end1 != tj1.StartEnd)
continue;
185 short endPt1 = tj1.EndPt[end1];
186 float wire1 = tj1.Pts[endPt1].Pos[0];
190 if (tj1.Pts.size() > 6 && tj1.Pts[endPt1].NTPsFit < 4) {
191 if (end1 == 0 && endPt1 <
int(tj1.Pts.size()) - 3) { endPt1 += 3; }
192 else if (end1 == 1 && endPt1 >= 3) {
201 endPt1 = tj1.EndPt[end1];
202 short oendPt1 = tj1.EndPt[1 - end1];
204 auto& otp1 = tj1.Pts[oendPt1];
205 for (
unsigned short it2 = it1 + 1; it2 < slc.
tjs.size(); ++it2) {
206 auto& tj2 = slc.
tjs[it2];
208 if (tj2.SSID > 0 || tj2.AlgMod[
kShowerLike])
continue;
209 if (tj2.CTP != inCTP)
continue;
210 if (tj1.VtxID[end1] > 0)
continue;
212 bool tj2Short = (
TrajLength(tj2) < maxShortTjLen);
214 unsigned short end2 = 0;
215 if (
PosSep2(tj2.Pts[tj2.EndPt[1]].Pos, tp1.
Pos) <
218 if (tj2.VtxID[end2] > 0)
continue;
220 if (tj2.PDGCode == 111 && end2 != tj2.StartEnd)
continue;
222 if (tj1.VtxID[1 - end1] > 0 && tj1.VtxID[1 - end1] == tj2.VtxID[1 - end2])
continue;
224 unsigned short oendPt2 = tj2.EndPt[1 - end2];
225 auto& otp2 = tj2.Pts[oendPt2];
226 if (
PosSep2(otp1.Pos, otp2.Pos) <
PosSep2(tp1.
Pos, tj2.Pts[tj2.EndPt[end2]].Pos))
228 short endPt2 = tj2.EndPt[end2];
229 float wire2 = tj2.Pts[endPt2].Pos[0];
230 if (tj2.Pts.size() > 6 && tj2.Pts[endPt2].NTPsFit < 4) {
231 if (end2 == 0 && endPt2 <
int(tj2.Pts.size()) - 3) { endPt2 += 3; }
232 else if (end2 == 1 && endPt2 >= 3) {
240 endPt2 = tj2.EndPt[end2];
252 if (tj1Short || tj2Short) { sepCut =
tcc.
vtx2DCuts[1]; }
266 if (prt && vt1Sep < 200 && vt2Sep < 200) {
268 myprt <<
"F2DV candidate T" << tj1.ID <<
"_" << end1 <<
"-T" << tj2.ID <<
"_" << end2;
269 myprt <<
" vtx pos " << (int)wint <<
":" << (
int)(tint /
tcc.
unitsPerTick) <<
" tp1 " 271 myprt <<
" dwc1 " << dwc1 <<
" dwc2 " << dwc2 <<
" on dead wire? " << vtxOnDeadWire;
272 myprt <<
" vt1Sep " << vt1Sep <<
" vt2Sep " << vt2Sep <<
" sepCut " << sepCut;
274 if (vt1Sep > sepCut || vt2Sep > sepCut)
continue;
276 if (
PosSep(vPos, slc.
tjs[it1].Pts[oendPt1].Pos) < vt1Sep) {
279 <<
" tj1 other end " <<
PrintPos(tj1.Pts[oendPt1]) <<
" is closer to the vertex";
282 if (
PosSep(vPos, slc.
tjs[it2].Pts[oendPt2].Pos) < vt2Sep) {
285 <<
" tj2 other end " <<
PrintPos(tj2.Pts[oendPt2]) <<
" is closer to the vertex";
289 unsigned short closePt1;
290 float doca1 = sepCut;
295 short dpt1 = stepDir * (closePt1 - endPt1);
297 mf::LogVerbatim(
"TC") <<
" endPt1 " << endPt1 <<
" closePt1 " << closePt1 <<
" dpt1 " 298 << dpt1 <<
" doca1 " << doca1;
299 if (dpt1 < -1)
continue;
300 if (slc.
tjs[it1].EndPt[1] > 4) {
301 if (dpt1 > 3)
continue;
305 if (dpt1 > 2)
continue;
307 unsigned short closePt2;
308 float doca2 = sepCut;
310 short dpt2 = stepDir * (closePt2 - endPt2);
312 mf::LogVerbatim(
"TC") <<
" endPt2 " << endPt2 <<
" closePt2 " << closePt2 <<
" dpt2 " 313 << dpt2 <<
" doca2 " << doca2;
314 if (dpt2 < -1)
continue;
315 if (slc.
tjs[it2].EndPt[1] > 4) {
316 if (dpt2 > 3)
continue;
320 if (dpt2 > 2)
continue;
322 bool fixVxPos =
false;
324 if (tj1.EndFlag[end1][
kAtKink]) fixVxPos =
true;
328 if (requireVtxTjChg) {
330 bool signalBetween =
true;
331 short dpt =
abs(wint - tp1.
Pos[0]);
333 if (prt)
mf::LogVerbatim(
"TC") <<
" Fails SignalBetween for tp1 " << dpt;
334 signalBetween =
false;
336 dpt =
abs(wint - tp2.
Pos[0]);
338 if (prt)
mf::LogVerbatim(
"TC") <<
" Fails SignalBetween for tp2 " << dpt;
339 signalBetween =
false;
343 if (!signalBetween) {
344 unsigned short ipt1, ipt2;
346 bool isClose =
TrajTrajDOCA(slc, tj1, tj2, ipt1, ipt2, maxSep,
false);
348 if (isClose) isClose = (
abs(ipt1 - endPt1) < 4 &&
abs(ipt2 - endPt2) < 4);
352 <<
" TrajTrajDOCA are close with minSep " << maxSep <<
" near " 367 <<
" new wint:tint " << (int)wint <<
":" << (
int)(tint /
tcc.
unitsPerTick);
380 aVtx.
Pass = tj1.Pass;
382 aVtx.
Topo = 2 * end1;
391 unsigned short newVtxID = slc.
vtxs.size() + 1;
393 tj1.VtxID[end1] = newVtxID;
394 tj2.VtxID[end2] = newVtxID;
403 if (prt)
mf::LogVerbatim(
"TC") <<
" Merged with close vertex " << mergeMeWithVx;
410 myprt <<
" New vtx 2V" << aVtx.
ID;
411 myprt <<
" Tjs " << tj1.ID <<
"_" << end1 <<
"-" << tj2.ID <<
"_" << end2;
412 myprt <<
" at " << std::fixed << std::setprecision(1) << aVtx.
Pos[0] <<
":" 422 if (pass == USHRT_MAX) {
427 if (prt)
PrintAllTraj(detProp,
"F2DVo", slc, USHRT_MAX, USHRT_MAX);
444 if (oVxID > slc.
vtxs.size())
return false;
445 auto& oVx = slc.
vtxs[oVxID - 1];
446 if (vx.
CTP != oVx.CTP)
return false;
450 if (tjlist.empty())
return false;
452 if (tmp.empty())
return false;
453 for (
auto tjid : tmp) {
454 if (std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end()) tjlist.push_back(tjid);
456 if (tjlist.size() < 2)
return false;
458 if (tjlist.size() == 2) {
463 for (
auto tjid : tjlist) {
464 auto& tj = slc.
tjs[tjid - 1];
465 for (
unsigned short end = 0;
end < 2; ++
end) {
466 if (tj.VtxID[
end] == vx.
ID) tj.VtxID[
end] = oVx.ID;
471 mf::LogVerbatim(
"TC") <<
"MWV: merge failed " << vx.
ID <<
" and existing " << oVx.ID;
478 std::vector<SortEntry> sortVec(tjlist.size());
479 for (
unsigned int indx = 0; indx < sortVec.size(); ++indx) {
480 sortVec[indx].index = indx;
481 auto& tj = slc.
tjs[tjlist[indx] - 1];
482 sortVec[indx].val = tj.Pts.size();
487 for (
unsigned short ii = 0; ii < sortVec.size(); ++ii)
488 tjlist[ii] = ttl[sortVec[ii].index];
493 std::vector<TrajPoint> tjpts(tjlist.size());
497 std::array<float, 2> vpos;
498 vpos[0] = 0.5 * (vx.
Pos[0] + oVx.Pos[0]);
499 vpos[1] = 0.5 * (vx.
Pos[1] + oVx.Pos[1]);
500 for (
unsigned short ii = 0; ii < tjpts.size(); ++ii) {
501 auto& tj = slc.
tjs[tjlist[ii] - 1];
505 unsigned short endPt = tj.EndPt[
end];
506 if (npwc > 6 && tj.Pts[endPt].NTPsFit < 4) {
507 if (end == 0) { endPt += 3; }
513 if (endPt < tj.EndPt[0]) endPt = tj.EndPt[0];
514 if (endPt > tj.EndPt[1]) endPt = tj.EndPt[1];
516 tjpts[ii].CTP = tj.CTP;
517 tjpts[ii].Pos = tj.Pts[endPt].Pos;
518 tjpts[ii].Dir = tj.Pts[endPt].Dir;
519 tjpts[ii].Ang = tj.Pts[endPt].Ang;
520 tjpts[ii].AngErr = tj.Pts[endPt].AngErr;
522 tjpts[ii].Step = endPt;
524 tjpts[ii].AngleCode =
end;
526 tjpts[ii].Hits.resize(1, tj.ID);
530 myprt <<
"MWV: " << oVxID;
532 for (
unsigned short ii = 0; ii < tjpts.size(); ++ii) {
533 auto& tjpt = tjpts[ii];
534 myprt <<
" " << tjlist[ii] <<
"_" << tjpt.Step <<
"_" <<
PrintPos(tjpt.Pos);
545 bool needsUpdate =
false;
546 for (
unsigned short ii = 2; ii < tjlist.size(); ++ii) {
547 fitpts.push_back(tjpts[ii]);
548 if (
FitVertex(slc, aVx, fitpts, prt)) { needsUpdate =
false; }
556 if (needsUpdate)
FitVertex(slc, aVx, fitpts, prt);
557 if (prt)
mf::LogVerbatim(
"TC") <<
"MWV: done " << vx.
ID <<
" and existing " << oVx.ID;
560 for (
auto& tj : slc.
tjs) {
562 if (tj.CTP != vx.
CTP)
continue;
563 for (
unsigned short end = 0;
end < 2; ++
end) {
564 if (tj.VtxID[
end] == vx.
ID) tj.VtxID[
end] = 0;
565 if (tj.VtxID[
end] == oVxID) tj.VtxID[
end] = 0;
569 for (
unsigned short ii = 0; ii < fitpts.size(); ++ii) {
570 auto& tjpt = fitpts[ii];
571 unsigned short end = tjpt.AngleCode;
572 auto& tj = slc.
tjs[tjpt.Hits[0] - 1];
573 if (tj.VtxID[end] != 0)
return false;
574 tj.VtxID[
end] = oVxID;
581 oVx.NTraj = fitpts.size();
588 myprt <<
"MWV: " << oVxID;
589 myprt <<
" Done TPs";
590 for (
unsigned short ii = 0; ii < fitpts.size(); ++ii) {
591 auto& tjpt = fitpts[ii];
592 myprt <<
" " << tjpt.Hits[0] <<
"_" << tjpt.AngleCode <<
"_" <<
PrintPos(tjpt.Pos);
619 for (
unsigned short it1 = 0; it1 < slc.
tjs.size(); ++it1) {
620 if (slc.
tjs[it1].CTP != inCTP)
continue;
622 if (slc.
tjs[it1].AlgMod[
kHamVx])
continue;
625 if (slc.
tjs[it1].PDGCode == 111)
continue;
627 if (numPtsWithCharge1 < 6)
continue;
629 if (slc.
tjs[it1].MCSMom < 200)
continue;
631 bool didaSplit =
false;
632 for (
unsigned short end1 = 0; end1 < 2; ++end1) {
634 if (slc.
tjs[it1].VtxID[end1] > 0)
continue;
635 unsigned short endPt1 = slc.
tjs[it1].EndPt[end1];
636 for (
unsigned short it2 = 0; it2 < slc.
tjs.size(); ++it2) {
637 if (it1 == it2)
continue;
638 if (slc.
tjs[it2].AlgMod[
kKilled] || slc.
tjs[it2].AlgMod[kHaloTj])
continue;
639 if (slc.
tjs[it2].AlgMod[kHamVx])
continue;
640 if (slc.
tjs[it2].AlgMod[kHamVx2])
continue;
642 if (slc.
tjs[it2].CTP != inCTP)
continue;
644 if (slc.
tjs[it2].AlgMod[kJunkTj])
continue;
645 if (slc.
tjs[it2].PDGCode == 111)
continue;
647 if (numPtsWithCharge2 < 6)
continue;
649 if (numPtsWithCharge2 > 100 && slc.
tjs[it2].MCSMom > 500)
continue;
652 float doca = minDOCA;
653 unsigned short closePt2 = 0;
655 if (doca == minDOCA)
continue;
658 auto& tj1 = slc.
tjs[it1];
659 auto& tj2 = slc.
tjs[it2];
660 myprt <<
" FHV2 CTP" << tj1.CTP;
661 myprt <<
" t" << tj1.ID <<
"_" << end1 <<
" MCSMom " << tj1.MCSMom <<
" ChgRMS " 663 myprt <<
" split t" << tj2.ID <<
"? MCSMom " << tj2.MCSMom <<
" ChgRMS " << tj2.ChgRMS;
664 myprt <<
" doca " << doca <<
" tj2.EndPt[0] " << tj2.EndPt[0] <<
" closePt2 " 666 myprt <<
" tj2.EndPt[1] " << tj2.EndPt[1];
669 if (closePt2 < slc.
tjs[it2].EndPt[0] + 3)
continue;
670 if (closePt2 > slc.
tjs[it2].EndPt[1] - 3)
continue;
675 float dang =
DeltaAngle(slc.
tjs[it1].Pts[endPt1].Ang, slc.
tjs[it2].Pts[closePt2].Ang);
676 if (dang < 0.2)
continue;
679 unsigned short closePt1 = 0;
681 if (closePt1 != endPt1)
continue;
688 unsigned short intPt2;
692 <<
PrintPos(slc.
tjs[it2].Pts[intPt2]) <<
" doca " << doca;
693 if (doca == minDOCA)
continue;
695 float mcsmom = slc.
tjs[it2].MCSMom;
696 float mcsmom1 =
MCSMom(slc, slc.
tjs[it2], slc.
tjs[it2].EndPt[0], intPt2);
697 float mcsmom2 =
MCSMom(slc, slc.
tjs[it2], intPt2, slc.
tjs[it2].EndPt[1]);
700 mf::LogVerbatim(
"TC") <<
" Check MCSMom after split: mcsmom1 " << mcsmom1 <<
" mcsmom2 " 702 if (mcsmom1 < mcsmom || mcsmom2 < mcsmom)
continue;
706 if (intPt2 < closePt2) dir = -1;
707 unsigned short nit = 0;
708 unsigned short ipt = intPt2;
709 float mostChg = slc.
tjs[it2].Pts[ipt].Chg;
712 <<
" chg " << mostChg;
715 if (ipt < 3 || ipt > slc.
tjs[it2].Pts.size() - 4)
break;
717 slc.
tjs[it2].Pts[ipt].Pos[0], slc.
tjs[it2].Pts[ipt].Pos[1], slc.
tjs[it1].Pts[endPt1]);
718 float sep =
PosSep(slc.
tjs[it2].Pts[ipt].Pos, slc.
tjs[it1].Pts[endPt1].Pos);
719 float dang = delta / sep;
720 float pull = dang / slc.
tjs[it1].Pts[endPt1].DeltaRMS;
721 if (pull < 2 && slc.
tjs[it2].Pts[ipt].Chg > mostChg) {
722 mostChg = slc.
tjs[it2].Pts[ipt].Chg;
727 float chgPull = (mostChg - slc.
tjs[it2].AveChg) / slc.
tjs[it2].ChgRMS;
729 if (chgPull < 10)
continue;
732 if (slc.
tjs[it1].Pts[endPt1].Pos[0] < -0.4)
continue;
733 unsigned int fromWire = std::nearbyint(slc.
tjs[it1].Pts[endPt1].Pos[0]);
734 if (slc.
tjs[it2].Pts[intPt2].Pos[0] < -0.4)
continue;
735 unsigned int toWire = std::nearbyint(slc.
tjs[it2].Pts[intPt2].Pos[0]);
736 if (fromWire > toWire) {
737 unsigned int tmp = fromWire;
742 for (
unsigned int wire = fromWire + 1; wire < toWire; ++wire) {
749 if (skipIt)
continue;
753 aVtx.
Pos = slc.
tjs[it2].Pts[intPt2].Pos;
759 aVtx.
ID = slc.
vtxs.size() + 1;
760 unsigned short ivx = slc.
vtxs.size();
762 if (!
SplitTraj(slc, it2, intPt2, ivx, prt)) {
767 slc.
tjs[it1].VtxID[end1] = slc.
vtxs[ivx].ID;
770 unsigned short newTjIndex = slc.
tjs.size() - 1;
780 << slc.
vtxs[ivx].Score;
784 if (didaSplit)
break;
806 for (
unsigned short it1 = 0; it1 < slc.
tjs.size(); ++it1) {
807 if (slc.
tjs[it1].CTP != inCTP)
continue;
811 if (slc.
tjs[it1].PDGCode == 111)
continue;
813 unsigned short tj1len = slc.
tjs[it1].EndPt[1] - slc.
tjs[it1].EndPt[0] + 1;
814 if (tj1len < 5)
continue;
816 if (slc.
tjs[it1].MCSMom < 50)
continue;
817 if (prt)
mf::LogVerbatim(
"TC") <<
"FHV: intersection T" << slc.
tjs[it1].ID <<
" candidate";
819 bool didaSplit =
false;
820 for (
unsigned short end1 = 0; end1 < 2; ++end1) {
822 if (slc.
tjs[it1].VtxID[end1] > 0)
continue;
823 unsigned short endPt1 = slc.
tjs[it1].EndPt[end1];
824 for (
unsigned short it2 = 0; it2 < slc.
tjs.size(); ++it2) {
825 if (slc.
tjs[it2].CTP != inCTP)
continue;
826 if (it1 == it2)
continue;
827 if (slc.
tjs[it2].AlgMod[
kKilled] || slc.
tjs[it2].AlgMod[kHaloTj])
continue;
828 if (slc.
tjs[it2].AlgMod[kJunkTj])
continue;
829 if (slc.
tjs[it2].PDGCode == 111)
continue;
831 unsigned short tj2len = slc.
tjs[it2].EndPt[1] - slc.
tjs[it2].EndPt[0] + 1;
832 if (tj2len < 6)
continue;
834 if (tj2len > 200 && slc.
tjs[it2].PDGCode == 13 && slc.
tjs[it2].MCSMom > 600)
continue;
836 minDOCA /=
std::abs(slc.
tjs[it1].Pts[endPt1].Dir[0]);
837 float doca = minDOCA;
838 unsigned short closePt2 = 0;
840 if (doca == minDOCA)
continue;
844 << slc.
tjs[it2].ID <<
" doca " << doca <<
" tj2.EndPt[0] " 845 << slc.
tjs[it2].EndPt[0] <<
" closePt2 " << closePt2
846 <<
" tj2.EndPt[1] " << slc.
tjs[it2].EndPt[1];
847 if (closePt2 < slc.
tjs[it2].EndPt[0] + 3)
continue;
848 if (closePt2 > slc.
tjs[it2].EndPt[1] - 3)
continue;
850 float dang =
DeltaAngle(slc.
tjs[it1].Pts[endPt1].Ang, slc.
tjs[it2].Pts[closePt2].Ang);
852 mf::LogVerbatim(
"TC") <<
" dang " << dang <<
" imposing a hard cut of 0.4 for now ";
853 if (dang < 0.4)
continue;
855 std::vector<int> tjids(2);
856 tjids[0] = slc.
tjs[it1].ID;
857 tjids[1] = slc.
tjs[it2].ID;
860 if (chgFrac < 0.9)
continue;
864 slc.
tjs[it1].Pts[endPt1], slc.
tjs[it2].Pts[closePt2], vxpos[0], vxpos[1]);
879 aVtx.
ID = slc.
vtxs.size() + 1;
881 unsigned short ivx = slc.
vtxs.size() - 1;
882 if (!
SplitTraj(slc, it2, closePt2, ivx, prt)) {
887 slc.
tjs[it1].VtxID[end1] = slc.
vtxs[ivx].ID;
890 unsigned short newTjIndex = slc.
tjs.size() - 1;
891 slc.
tjs[newTjIndex].AlgMod[
kHamVx] =
true;
898 auto& vx2 = slc.
vtxs[ivx];
900 myprt <<
" new 2V" << vx2.ID <<
" Score " << vx2.Score <<
" Tjs";
901 auto tjlist =
GetAssns(slc,
"2V", vx2.
ID,
"T");
902 for (
auto tid : tjlist)
903 myprt <<
" t" << tid;
908 if (didaSplit)
break;
921 if (slc.
vtxs.empty())
return;
922 if (slc.
tjs.empty())
return;
924 constexpr
float docaCut = 4;
927 if (prt)
mf::LogVerbatim(
"TC") <<
"Inside SplitTrajCrossingVertices inCTP " << inCTP;
931 unsigned short nTraj = slc.
tjs.size();
932 for (
unsigned short itj = 0; itj < nTraj; ++itj) {
934 if (slc.
tjs[itj].CTP != inCTP)
continue;
940 if (slc.
tjs[itj].EndPt[1] < 6)
continue;
941 for (
unsigned short iv = 0; iv < slc.
vtxs.size(); ++iv) {
942 auto& vx2 = slc.
vtxs[iv];
944 if (vx2.NTraj == 0)
continue;
946 if (slc.
tjs[itj].VtxID[0] == vx2.ID || slc.
tjs[itj].VtxID[1] == vx2.ID)
continue;
948 if (slc.
tjs[itj].CTP != vx2.CTP)
continue;
951 float doca = docaCut;
955 unsigned short closePt = 0;
962 if (doca > docaCut)
continue;
965 << slc.
vtxs[iv].ID <<
" closePt " << closePt <<
" in plane " 971 if (vxtjs.empty())
continue;
972 unsigned short maxPts = 0;
976 float tjAng = slc.
tjs[itj].Pts[closePt].Ang;
977 for (
auto tjid : vxtjs) {
978 auto& vtj = slc.
tjs[tjid - 1];
981 if (npwc > maxPts) maxPts = npwc;
982 unsigned short end = 0;
983 if (vtj.VtxID[1] == slc.
vtxs[iv].ID) end = 1;
984 auto& vtp = vtj.Pts[vtj.EndPt[
end]];
986 if (dang > maxdang) maxdang = dang;
992 if (!skipit && maxdang < 0.3) skipit =
true;
994 mf::LogVerbatim(
"TC") <<
" maxPts " << maxPts <<
" vxtjs[0] " << vxtjs[0] <<
" maxdang " 995 << maxdang <<
" skipit? " << skipit;
1006 auto& closeTP = slc.
tjs[itj].Pts[closePt];
1007 if (slc.
tjs[itj].StepDir > 0 && closePt > slc.
tjs[itj].EndPt[0]) {
1008 if (closeTP.Pos[0] > vx2.Pos[0]) --closePt;
1010 else if (slc.
tjs[itj].StepDir < 0 && closePt < slc.
tjs[itj].EndPt[1]) {
1011 if (closeTP.Pos[0] < vx2.Pos[0]) ++closePt;
1018 if ((slc.
tjs[itj].Pts[closePt].Pos[0] - vx2.Pos[0]) *
1019 (slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[1]].Pos[0] - vx2.Pos[0]) +
1020 (slc.
tjs[itj].Pts[closePt].Pos[1] - vx2.Pos[1]) *
1021 (slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[1]].Pos[1] - vx2.Pos[1]) <
1023 closePt < slc.
tjs[itj].EndPt[1] - 1)
1025 else if ((slc.
tjs[itj].Pts[closePt].Pos[0] - vx2.Pos[0]) *
1026 (slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[0]].Pos[0] - vx2.Pos[0]) +
1027 (slc.
tjs[itj].Pts[closePt].Pos[1] - vx2.Pos[1]) *
1028 (slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[0]].Pos[1] - slc.
vtxs[iv].Pos[1]) <
1030 closePt > slc.
tjs[itj].EndPt[0] + 1)
1035 mf::LogVerbatim(
"TC") <<
"Good doca " << doca <<
" btw T" << slc.
tjs[itj].ID <<
" and 2V" 1036 << vx2.ID <<
" closePt " << closePt <<
" in plane " << planeID.
Plane 1037 <<
" CTP " << slc.
vtxs[iv].CTP;
1038 PrintTP(
"STCV", slc, closePt, 1, slc.
tjs[itj].Pass, slc.
tjs[itj].Pts[closePt]);
1041 if (closePt < slc.
tjs[itj].EndPt[0] + 3)
continue;
1042 if (closePt > slc.
tjs[itj].EndPt[1] - 3)
continue;
1043 if (!
SplitTraj(slc, itj, closePt, iv, prt)) {
1044 if (prt)
mf::LogVerbatim(
"TC") <<
"SplitTrajCrossingVertices: Failed to split trajectory";
1048 unsigned short newTjIndex = slc.
tjs.size() - 1;
1063 if (slc.
vtxs.empty())
return;
1068 std::vector<std::vector<int>> vx2Cls;
1071 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
1074 for (
unsigned short ii = 0; ii < slc.
vtxs.size() - 1; ++ii) {
1075 auto& i2v = slc.
vtxs[ii];
1076 if (i2v.ID <= 0)
continue;
1078 for (
unsigned short jj = ii + 1; jj < slc.
vtxs.size(); ++jj) {
1079 auto& j2v = slc.
vtxs[jj];
1080 if (j2v.ID <= 0)
continue;
1083 float dp0 =
std::abs(i2v.Pos[0] - j2v.Pos[0]);
1084 if (dp0 > 10)
continue;
1085 float dp1 =
std::abs(i2v.Pos[1] - j2v.Pos[1]);
1086 if (dp1 > 10)
continue;
1088 float err = i2v.PosErr[0];
1089 if (j2v.PosErr[0] > err) err = j2v.PosErr[0];
1090 float dp0Sig = dp0 / err;
1091 if (dp0Sig > 4)
continue;
1092 err = i2v.PosErr[1];
1093 if (j2v.PosErr[1] > err) err = j2v.PosErr[1];
1094 float dp1Sig = dp1 / err;
1095 if (dp1Sig > 4)
continue;
1098 for (
auto& vx2cls : vx2Cls) {
1099 bool goti = (std::find(vx2cls.begin(), vx2cls.end(), i2v.ID) != vx2cls.end());
1100 bool gotj = (std::find(vx2cls.begin(), vx2cls.end(), j2v.ID) != vx2cls.end());
1106 vx2cls.push_back(j2v.ID);
1112 vx2cls.push_back(i2v.ID);
1118 std::vector<int> cls(2);
1121 vx2Cls.push_back(cls);
1125 if (vx2Cls.empty())
continue;
1128 myprt <<
"2V clusters in plane " << plane;
1129 for (
auto& vx2cls : vx2Cls) {
1131 for (
auto vx2id : vx2cls)
1132 myprt <<
" 2V" << vx2id;
1135 for (
auto& vx2cls : vx2Cls) {
1142 bool VxEnvironmentNeedsUpdate =
false;
1143 for (
auto& vx : slc.
vtxs) {
1144 if (vx.ID <= 0)
continue;
1145 if (!vx.Stat[
kVxEnvOK]) VxEnvironmentNeedsUpdate =
true;
1159 if (vx2cls.size() < 2)
return false;
1162 std::vector<int> t2vList;
1165 for (
auto vx2id : vx2cls) {
1166 auto& vx2 = slc.
vtxs[vx2id - 1];
1169 if (vx2.ID <= 0)
return true;
1170 auto tlist =
GetAssns(slc,
"2V", vx2.
ID,
"T");
1171 for (
auto tid : tlist)
1172 if (std::find(t2vList.begin(), t2vList.end(), tid) == t2vList.end()) t2vList.push_back(tid);
1174 if (t2vList.size() < 3)
return false;
1179 for (
auto tid : t2vList) {
1180 auto& tj = slc.
tjs[tid - 1];
1181 for (
unsigned short end = 0;
end < 2; ++
end) {
1182 if (tj.VtxID[
end] <= 0)
continue;
1183 if (std::find(vx2cls.begin(), vx2cls.end(), tj.VtxID[
end]) == vx2cls.end())
continue;
1184 auto& vx = slc.
vtxs[tj.VtxID[
end] - 1];
1185 unsigned short nearEnd = 1 -
FarEnd(tj, vx.Pos);
1187 if (fitPt == USHRT_MAX)
return false;
1188 auto& tp = tj.Pts[fitPt];
1196 myprt <<
"R2VTs: cluster:";
1197 for (
auto vid : vx2cls)
1198 myprt <<
" 2V" << vid;
1200 for (
auto tid : t2vList)
1201 myprt <<
" T" << tid;
1202 myprt <<
" sumPulls " << std::setprecision(2) << sumPulls <<
" cnt " << cnt;
1210 for (
auto vid : vx2cls) {
1211 auto& vx = slc.
vtxs[vid - 1];
1212 oneVx.
Pos[0] += vx.Pos[0];
1213 oneVx.
Pos[1] += vx.Pos[2];
1215 oneVx.
Pos[0] /= vx2cls.size();
1216 oneVx.
Pos[1] /= vx2cls.size();
1217 std::vector<TrajPoint> oneVxTPs(t2vList.size());
1218 for (
unsigned short itj = 0; itj < t2vList.size(); ++itj) {
1219 auto& tj = slc.
tjs[t2vList[itj] - 1];
1220 unsigned short nearEnd = 1 -
FarEnd(tj, oneVx.
Pos);
1222 if (fitPt == USHRT_MAX)
return false;
1223 oneVxTPs[itj] = tj.Pts[fitPt];
1225 if (oneVxTPs[itj].Environment[
kEnvOverlap]) oneVxTPs[itj].AngErr *= 4;
1226 oneVxTPs[itj].Step = tj.ID;
1228 if (!
FitVertex(slc, oneVx, oneVxTPs, prt))
return false;
1232 auto& vx = slc.
vtxs[vx2cls[0] - 1];
1234 vx.PosErr = oneVx.
PosErr;
1235 vx.NTraj = t2vList.size();
1236 vx.ChiDOF = oneVx.
ChiDOF;
1241 for (
unsigned short ivx = 1; ivx < vx2cls.size(); ++ivx) {
1242 auto& vx = slc.
vtxs[vx2cls[ivx] - 1];
1246 for (
auto tid : t2vList) {
1247 auto& tj = slc.
tjs[tid - 1];
1248 unsigned short nearEnd = 1 -
FarEnd(tj, vx.Pos);
1249 tj.VtxID[nearEnd] = vx.ID;
1264 if (slc.
vtxs.size() < 2)
return;
1267 std::vector<std::vector<unsigned short>> vIndex(3);
1268 for (
unsigned short ivx = 0; ivx < slc.
vtxs.size(); ++ivx) {
1270 if (slc.
vtxs[ivx].ID == 0)
continue;
1273 unsigned short plane = planeID.
Plane;
1274 if (plane > 2)
continue;
1275 vIndex[plane].push_back(ivx);
1278 unsigned short vtxInPln = 0;
1279 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane)
1280 if (vIndex[plane].
size() > 0) ++vtxInPln;
1281 if (vtxInPln < 2)
return;
1287 <<
" thirdPlanedXCut " << thirdPlanedXCut;
1290 size_t vsize = slc.
vtxs.size();
1292 std::vector<short> vPtr(vsize, -1);
1294 std::vector<float> vX(vsize, FLT_MAX);
1296 for (
unsigned short ivx = 0; ivx < vsize; ++ivx) {
1297 if (slc.
vtxs[ivx].ID <= 0)
continue;
1299 if (slc.
vtxs[ivx].Pos[0] < -0.4)
continue;
1307 std::vector<Vtx3Store> v3temp;
1313 constexpr
float maxSep = 4;
1317 for (
unsigned short ipl = 0; ipl < 2; ++ipl) {
1318 for (
unsigned short ii = 0; ii < vIndex[ipl].size(); ++ii) {
1319 unsigned short ivx = vIndex[ipl][ii];
1320 if (vX[ivx] == FLT_MAX)
continue;
1321 auto& ivx2 = slc.
vtxs[ivx];
1322 if (ivx2.Pos[0] < -0.4)
continue;
1323 unsigned int iWire = std::nearbyint(ivx2.Pos[0]);
1324 for (
unsigned short jpl = ipl + 1; jpl < 3; ++jpl) {
1325 for (
unsigned short jj = 0; jj < vIndex[jpl].size(); ++jj) {
1326 unsigned short jvx = vIndex[jpl][jj];
1327 if (vX[jvx] == FLT_MAX)
continue;
1328 auto& jvx2 = slc.
vtxs[jvx];
1329 if (jvx2.Pos[0] < -0.4)
continue;
1330 unsigned int jWire = std::nearbyint(jvx2.Pos[0]);
1331 float dX =
std::abs(vX[ivx] - vX[jvx]);
1335 <<
"F3DV: ipl " << ipl <<
" i2V" << ivx2.ID <<
" iX " << vX[ivx] <<
" jpl " << jpl
1336 <<
" j2V" << jvx2.ID <<
" jvX " << vX[jvx] <<
" W:T " << (int)jvx2.Pos[0] <<
":" 1337 << (
int)jvx2.Pos[1] <<
" dX " << dX;
1339 double y = -1000,
z = -1000;
1342 if (y < slc.yLo || y > slc.
yHi || z < slc.zLo || z > slc.
zHi)
continue;
1343 unsigned short kpl = 3 - ipl - jpl;
1344 float kX = 0.5 * (vX[ivx] + vX[jvx]);
1348 std::array<int, 2> wireWindow;
1349 std::array<float, 2> timeWindow;
1350 wireWindow[0] = kWire - maxSep;
1351 wireWindow[1] = kWire + maxSep;
1354 timeWindow[0] = time - maxSep;
1355 timeWindow[1] = time + maxSep;
1357 std::vector<unsigned int> closeHits =
1361 myprt <<
" Hits near " << kpl <<
":" << kWire <<
":" 1363 for (
auto iht : closeHits)
1366 if (!hitsNear)
continue;
1373 v3d.
Vx2ID[ipl] = ivx2.ID;
1374 v3d.
Vx2ID[jpl] = jvx2.ID;
1383 float vxScoreWght = 0;
1386 if (posError < 0.5) posError = 0;
1387 v3d.
Score = posError + vxScoreWght;
1390 v3temp.push_back(v3d);
1394 myprt <<
" 2 Plane match i2V";
1395 myprt << slc.
vtxs[ivx].ID <<
" P:W:T " << ipl <<
":" << (int)slc.
vtxs[ivx].Pos[0]
1396 <<
":" << (
int)slc.
vtxs[ivx].Pos[1];
1397 myprt <<
" j2V" << slc.
vtxs[jvx].ID <<
" P:W:T " << jpl <<
":" 1398 << (int)slc.
vtxs[jvx].Pos[0] <<
":" << (
int)slc.
vtxs[jvx].Pos[1];
1399 myprt << std::fixed << std::setprecision(3);
1400 myprt <<
" dX " << dX <<
" posError " << posError <<
" vxScoreWght " << vxScoreWght
1401 <<
" Score " << v3d.
Score;
1404 if (slc.
nPlanes == 2)
continue;
1407 for (
unsigned short kk = 0; kk < vIndex[kpl].size(); ++kk) {
1408 unsigned short kvx = vIndex[kpl][kk];
1412 if (dX > thirdPlanedXCut)
continue;
1415 double y = -1000,
z = -1000;
1418 v3d.
YErr = y - v3d.
Y;
1427 posError = dX * dX + dY * dY + dZ * dZ;
1431 if (posError < 0.5) posError = 0;
1432 v3d.
Score = posError + vxScoreWght;
1433 if (v3d.
Score > maxScore) maxScore = v3d.
Score;
1435 mf::LogVerbatim(
"TC") <<
" k2V" << kvx + 1 <<
" dX " << dX <<
" dW " << dW
1436 <<
" 3D score " << v3d.
Score;
1437 v3temp.push_back(v3d);
1444 if (v3temp.empty())
return;
1449 for (
auto& v3 : v3temp)
1450 if (v3.Wire >= 0) v3.Score += maxScore;
1454 for (
auto& v3 : v3temp) {
1456 mf::LogVerbatim(
"TC") <<
"2V" << v3.Vx2ID[0] <<
" 2V" << v3.Vx2ID[1] <<
" wire " 1457 << v3.Wire <<
" Score " << v3.Score;
1460 mf::LogVerbatim(
"TC") <<
"2V" << v3.Vx2ID[0] <<
" 2V" << v3.Vx2ID[1] <<
" 2V" 1461 << v3.Vx2ID[2] <<
" wire " << v3.Wire <<
" Score " << v3.Score;
1466 std::vector<SortEntry> sortVec(v3temp.size());
1467 for (
unsigned short ivx = 0; ivx < v3temp.size(); ++ivx) {
1469 sEntry.
val = v3temp[ivx].Score;
1470 sortVec[ivx] = sEntry;
1472 if (sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(),
valsIncreasing);
1474 std::vector<Vtx3Store> v3sel;
1475 for (
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
1476 unsigned short ivx = sortVec[ii].
index;
1478 bool skipit =
false;
1479 for (
auto& v3 : v3sel) {
1480 for (
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
1481 if (v3temp[ivx].Vx2ID[ipl] == 0)
continue;
1482 if (v3temp[ivx].Vx2ID[ipl] == v3.Vx2ID[ipl]) {
1489 if (skipit)
continue;
1490 v3sel.push_back(v3temp[ivx]);
1496 myprt <<
"v3sel list\n";
1497 for (
auto& v3d : v3sel) {
1498 for (
auto vx2id : v3d.Vx2ID)
1499 if (vx2id > 0) myprt <<
" 2V" << vx2id;
1500 myprt <<
" wire " << v3d.Wire <<
" Score " << v3d.Score;
1506 unsigned short ninc = 0;
1507 for (
auto& vx3 : v3sel) {
1508 if (slc.
nPlanes == 3 && vx3.Wire >= 0) ++ninc;
1509 vx3.ID = slc.
vtx3s.size() + 1;
1514 myprt <<
" 3V" << vx3.ID;
1515 for (
auto v2id : vx3.Vx2ID)
1516 myprt <<
" 2V" << v2id;
1517 myprt <<
" wire " << vx3.Wire;
1519 slc.
vtx3s.push_back(vx3);
1521 for (
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
1522 if (vx3.Vx2ID[ipl] == 0)
continue;
1536 for (
auto& tj : slc.
tjs) {
1539 if (planeID.
TPC != tpc || planeID.
Cryostat != cstat)
continue;
1543 for (
auto& vx2 : slc.
vtxs) {
1544 if (vx2.ID == 0)
continue;
1546 if (planeID.
TPC != tpc || planeID.
Cryostat != cstat)
continue;
1550 for (
auto& vx3 : slc.
vtx3s) {
1551 if (vx3.ID == 0)
continue;
1561 for (
unsigned short ivx = 0; ivx < slc.
vtxs.size(); ++ivx) {
1562 if (slc.
vtxs[ivx].ID == 0)
continue;
1563 if (slc.
vtxs[ivx].CTP != tp.
CTP)
continue;
1576 if (pfp.
ID <= 0)
return false;
1578 float pLen =
Length(pfp);
1579 if (pLen == 0)
return false;
1583 for (
unsigned short end = 0;
end < 2; ++
end)
1585 std::array<Point3_t, 2> endPos;
1589 std::array<float, 2> foms{{100., 100.}};
1590 std::array<int, 2> vtxs{{0}};
1591 for (
auto& vx3 : slc.
vtx3s) {
1592 if (vx3.ID <= 0)
continue;
1593 if (vx3.TPCID != pfp.
TPCID)
continue;
1594 std::array<float, 2> sep;
1595 Point3_t vpos = {{vx3.X, vx3.Y, vx3.Z}};
1596 sep[0] =
PosSep(vpos, endPos[0]);
1597 sep[1] =
PosSep(vpos, endPos[1]);
1598 unsigned short end = 0;
1599 if (sep[1] < sep[0]) end = 1;
1601 if (sep[end] > 100)
continue;
1606 float fom = dotp * sep[
end];
1608 mf::LogVerbatim(
"TC") <<
"ATAV: P" << pfp.
ID <<
" end " << end <<
" 3V" << vx3.ID <<
" sep " 1609 << sep[
end] <<
" fom " << fom <<
" maxSep " << maxSep;
1611 if (sep[end] > maxSep)
continue;
1612 if (fom < foms[end]) {
1618 for (
unsigned short end = 0;
end < 2; ++
end) {
1619 if (vtxs[
end] == 0)
continue;
1632 if (tjID <= 0 || tjID > (
int)slc.
tjs.size())
return false;
1633 if (slc.
vtxs.empty())
return false;
1634 auto& tj = slc.
tjs[tjID - 1];
1635 if (tj.AlgMod[
kKilled])
return false;
1638 unsigned short bestVx = USHRT_MAX;
1642 for (
unsigned short ivx = 0; ivx < slc.
vtxs.size(); ++ivx) {
1643 auto& vx = slc.
vtxs[ivx];
1644 if (vx.ID == 0)
continue;
1645 if (vx.CTP != tj.CTP)
continue;
1647 std::array<float, 2> sep;
1648 sep[0] =
PosSep(vx.Pos, tj.Pts[tj.EndPt[0]].Pos);
1649 sep[1] =
PosSep(vx.Pos, tj.Pts[tj.EndPt[1]].Pos);
1650 unsigned short end = 0;
1651 if (sep[1] < sep[0]) end = 1;
1652 if (sep[end] > 100)
continue;
1653 if (tj.VtxID[end] > 0)
continue;
1654 auto& tp = tj.Pts[tj.EndPt[
end]];
1657 if (fom > bestFOM)
continue;
1659 mf::LogVerbatim(
"TC") <<
"AAVTT: T" << tjID <<
" 2V" << vx.ID <<
" FOM " << fom <<
" cut " 1664 if (bestVx > slc.
vtxs.size() - 1)
return false;
1665 auto& vx = slc.
vtxs[bestVx];
1673 if (ivx > slc.
vtxs.size() - 1)
return false;
1674 if (slc.
vtxs[ivx].ID == 0)
return false;
1679 if (vx.
Topo == 5 || vx.
Topo == 6)
return false;
1681 unsigned short bestTj = USHRT_MAX;
1685 for (
unsigned int itj = 0; itj < slc.
tjs.size(); ++itj) {
1686 auto& tj = slc.
tjs[itj];
1688 if (tj.CTP != vx.
CTP)
continue;
1690 std::array<float, 2> sep;
1691 sep[0] =
PosSep(vx.
Pos, tj.Pts[tj.EndPt[0]].Pos);
1692 sep[1] =
PosSep(vx.
Pos, tj.Pts[tj.EndPt[1]].Pos);
1693 unsigned short end = 0;
1694 if (sep[1] < sep[0]) end = 1;
1695 if (sep[end] > 100)
continue;
1696 if (tj.VtxID[end] > 0)
continue;
1697 auto& tp = tj.Pts[tj.EndPt[
end]];
1700 if (fom > bestFOM)
continue;
1703 <<
" FOM " << fom <<
" cut " << bestFOM;
1708 if (bestTj > slc.
tjs.size() - 1)
return false;
1709 auto& tj = slc.
tjs[bestTj];
1728 if (tj.
CTP != vx.
CTP)
return false;
1738 unsigned short end = 0;
1741 if (sep1 < vtxTjSep2) {
1747 if (tj.
VtxID[end] > 0)
return false;
1750 bool tjShort = (tj.
EndPt[1] - tj.
EndPt[0] < maxShortTjLen);
1752 if (!tjShort && tj.
ChgRMS > 0.5) tjShort =
true;
1753 float closestApproach;
1756 if (vtxTjSep2 > maxSepCutShort2)
return false;
1761 if (vtxTjSep2 > maxSepCutLong2)
return false;
1770 unsigned short closePt;
1776 if (end == 0) { dpt = closePt - tj.
EndPt[
end]; }
1783 if (length > 4 && length < closestApproach)
return false;
1789 if (tjShort) pullCut *= 2;
1793 myprt <<
"ATTV: 2V" << vx.
ID;
1794 myprt <<
" NTraj " << vx.
NTraj;
1796 for (
unsigned short itj = 0; itj < slc.
tjs.size(); ++itj) {
1799 if (tj.
CTP != vx.
CTP)
continue;
1800 if (tj.
VtxID[0] == vx.
ID) myprt <<
" T" << tj.
ID <<
"_0";
1801 if (tj.
VtxID[1] == vx.
ID) myprt <<
" T" << tj.
ID <<
"_1";
1803 myprt <<
" + T" << tj.
ID <<
"_" << end <<
" vtxTjSep " << sqrt(vtxTjSep2) <<
" tpVxPull " 1804 << tpVxPull <<
" pullCut " << pullCut <<
" dpt " << dpt;
1806 if (tpVxPull > pullCut)
return false;
1807 if (dpt > 2)
return true;
1829 <<
" assn with kNoFitVx";
1847 double vxErrW = vx.
PosErr[0] * tp.
Dir[1];
1848 double vxErrT = vx.
PosErr[1] * tp.
Dir[0];
1849 double vxErr2 = vxErrW * vxErrW + vxErrT * vxErrT;
1855 if (sep2 < 1)
return (
float)(ip / sqrt(vxErr2));
1857 double dang = ip / sqrt(sep2);
1861 double angErr = vxErr2 / sep2;
1864 if (angErr == 0)
return 999;
1865 angErr = sqrt(angErr);
1866 return (
float)(dang / angErr);
1874 double dx = vx1.
X - vx2.
X;
1875 double dy = vx1.
Y - vx2.
Y;
1876 double dz = vx1.
Z - vx2.
Z;
1880 dx = dx * dx / dxErr2;
1881 dy = dy * dy / dyErr2;
1882 dz = dz * dz / dzErr2;
1883 return (
float)(sqrt(dx + dy + dz) / 3);
1890 double dw = vx1.
Pos[0] - vx2.
Pos[0];
1891 double dt = vx1.
Pos[1] - vx2.
Pos[1];
1894 dw = dw * dw / dwErr2;
1895 dt = dt * dt / dtErr2;
1896 return (
float)sqrt(dw + dt);
1905 if (vx.
ID !=
int(slc.
vtxs.size() + 1))
return false;
1910 unsigned short nvxtj = 0;
1911 unsigned short nok = 0;
1912 for (
auto& tj : slc.
tjs) {
1913 if (tj.AlgMod[
kKilled])
continue;
1914 if (vx.
ID == tj.VtxID[0] || vx.
ID == tj.VtxID[1]) ++nvxtj;
1915 if (vx.
CTP != tj.CTP)
continue;
1916 if (vx.
ID == tj.VtxID[0] || vx.
ID == tj.VtxID[1]) ++nok;
1921 <<
" has inconsistent CTP code " << vx.
CTP <<
" with one or more Tjs\n";
1922 for (
auto& tj : slc.
tjs) {
1923 if (tj.AlgMod[
kKilled])
continue;
1924 if (tj.VtxID[0] == vx.
ID) tj.VtxID[0] = 0;
1925 if (tj.VtxID[1] == vx.
ID) tj.VtxID[1] = 0;
1930 slc.
vtxs.push_back(vx);
1949 if (prt)
mf::LogVerbatim(
"TC") <<
" vertex position fixed. No fit allowed";
1954 std::vector<TrajPoint> vxTp;
1955 for (
auto& tj : slc.
tjs) {
1957 if (tj.CTP != vx.
CTP)
continue;
1958 if (tj.AlgMod[
kPhoton])
continue;
1960 if (tj.VtxID[0] == vx.
ID && !tj.EndFlag[0][
kNoFitVx]) {
1961 vxTp.push_back(tj.Pts[tj.EndPt[0]]);
1964 if (tj.VtxID[1] == vx.
ID && !tj.EndFlag[1][
kNoFitVx]) {
1965 vxTp.push_back(tj.Pts[tj.EndPt[1]]);
1970 auto& tp = vxTp[vxTp.size() - 1];
1971 if (tj.ID > 0) tp.Step = (int)tj.ID;
1973 if (tp.NTPsFit < 4) tp.AngErr *= 4;
1977 bool success =
FitVertex(slc, vx, vxTp, prt);
1979 if (!success)
return false;
1993 if (vxTPs.size() < 2)
return false;
1994 if (vxTPs.size() == 2) {
1999 unsigned short npts = vxTPs.size();
2000 TMatrixD A(npts, 2);
2002 for (
unsigned short itj = 0; itj < vxTPs.size(); ++itj) {
2003 auto& tp = vxTPs[itj];
2004 double dtdw = tp.Dir[1] / tp.Dir[0];
2005 double wt = 1 / (tp.AngErr * tp.AngErr);
2006 A(itj, 0) = -dtdw * wt;
2007 A(itj, 1) = 1. * wt;
2008 b(itj) = (tp.Pos[1] - tp.Pos[0] * dtdw) * wt;
2011 TMatrixD AT(2, npts);
2013 TMatrixD ATA = AT * A;
2021 if (det == NULL)
return false;
2022 TVectorD vxPos = ATA * AT * b;
2023 vx.
PosErr[0] = sqrt(ATA[0][0]);
2024 vx.
PosErr[1] = sqrt(ATA[1][1]);
2025 vx.
Pos[0] = vxPos[0];
2026 vx.
Pos[1] = vxPos[1];
2030 if (vxTPs.size() > 2) {
2031 for (
auto& tp : vxTPs) {
2036 vx.
ChiDOF /= (float)(vxTPs.size() - 2);
2042 for (
auto& tp : vxTPs)
2043 PrintTP(
"FV", slc, 0, 1, 1, tp);
2056 unsigned short plane = planeID.
Plane;
2057 for (
auto& vx2 : slc.
vtxs) {
2058 if (vx2.CTP != inCTP)
continue;
2059 if (vx2.ID == 0)
continue;
2060 if (vx2.Vx3ID == 0)
continue;
2061 if (vx2.Vx3ID >
int(slc.
vtx3s.size())) {
2062 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: Invalid vx2.Vx3ID " << vx2.Vx3ID
2063 <<
" in 2D vtx " << vx2.ID;
2066 auto& vx3 = slc.
vtx3s[vx2.Vx3ID - 1];
2068 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: 2V" << vx2.ID <<
" thinks it is matched to 3V" 2069 << vx3.ID <<
" but vx3 is obsolete";
2072 if (vx3.Vx2ID[plane] != vx2.ID) {
2073 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: 2V" << vx2.ID <<
" thinks it is matched to 3V" 2074 << vx3.ID <<
" but vx3 says no!";
2079 for (
auto& vx3 : slc.
vtx3s) {
2080 if (vx3.ID == 0)
continue;
2081 if (vx3.Vx2ID[plane] == 0)
continue;
2082 if (vx3.Vx2ID[plane] > (
int)slc.
vtxs.size()) {
2083 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: Invalid vx3.Vx2ID " << vx3.Vx2ID[plane]
2084 <<
" in CTP " << inCTP;
2087 auto& vx2 = slc.
vtxs[vx3.Vx2ID[plane] - 1];
2088 if (vx2.Vx3ID != vx3.ID) {
2089 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: 3V" << vx3.ID <<
" thinks it is matched to 2V" 2090 << vx2.ID <<
" but vx2 says no!";
2096 for (
auto& tj : slc.
tjs) {
2098 for (
unsigned short end = 0;
end < 2; ++
end) {
2099 if (tj.VtxID[
end] == 0)
continue;
2100 if (tj.VtxID[
end] > slc.
vtxs.size()) {
2101 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: T" << tj.ID <<
" thinks it is matched to 2V" 2102 << tj.VtxID[
end] <<
" on end " <<
end 2103 <<
" but no vertex exists. Recovering";
2107 unsigned short ivx = tj.VtxID[
end] - 1;
2108 auto& vx2 = slc.
vtxs[ivx];
2110 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: T" << tj.ID <<
" thinks it is matched to 2V" 2111 << tj.VtxID[
end] <<
" on end " <<
end 2112 <<
" but the vertex is killed. Fixing the Tj";
2129 for (
auto& vx : slc.
vtxs) {
2130 if (vx.ID == 0)
continue;
2134 for (
auto& tj : slc.
tjs) {
2139 for (
auto& vx : slc.
vtxs) {
2140 if (vx.ID == 0)
continue;
2144 for (
auto& vx3 : slc.
vtx3s) {
2145 if (vx3.ID == 0)
continue;
2154 if (slc.
vtxs.empty())
return;
2155 for (
auto& vx : slc.
vtxs) {
2156 if (vx.ID == 0)
continue;
2159 auto& vx3 = slc.
vtx3s[vx.Vx3ID - 1];
2160 if (vx3.Primary)
continue;
2173 if (vx3.
ID == 0)
return;
2175 for (
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
2176 if (vx3.
Vx2ID[ipl] <= 0)
continue;
2181 std::vector<int> vxlist;
2186 for (
auto tjid : tjlist) {
2187 auto& tj = slc.
tjs[tjid - 1];
2189 for (
unsigned short end = 0;
end < 2; ++
end) {
2190 if (tj.VtxID[
end] == 0)
continue;
2191 auto& vx2 = slc.
vtxs[tj.VtxID[
end] - 1];
2194 vxlist.push_back(vx2.
ID);
2198 if (vxlist.empty())
break;
2200 std::vector<int> newtjlist;
2201 for (
auto vxid : vxlist) {
2202 auto& vx2 = slc.
vtxs[vxid - 1];
2204 for (
auto tjid :
tmp) {
2205 if (std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end())
2206 newtjlist.push_back(tjid);
2209 if (newtjlist.empty())
break;
2222 if (vx3.
ID == 0)
return;
2225 for (
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
2226 if (vx3.
Vx2ID[ipl] <= 0)
continue;
2241 if (slc.
vtxs.empty())
return;
2242 auto& vx2 = slc.
vtxs[slc.
vtxs.size() - 1];
2250 if (vx2.
ID == 0)
return;
2261 constexpr
float maxChgRMS = 0.25;
2262 constexpr
float momBin = 50;
2266 if (vx2.
ID == 0)
return;
2270 if (vtxTjIDs.empty())
return;
2275 unsigned short m3Dcnt = 0;
2276 if (vx2.
Vx3ID > 0) {
2279 unsigned short ivx3 = vx2.
Vx3ID - 1;
2280 if (slc.
vtx3s[ivx3].Wire < 0) m3Dcnt = 2;
2288 std::vector<int> tjids;
2289 std::vector<float> tjwts;
2290 unsigned short cnt13 = 0;
2291 for (
auto tjid : vtxTjIDs) {
2295 unsigned short lenth = tj.
EndPt[1] - tj.
EndPt[0] + 1;
2296 if (lenth < 3)
continue;
2297 float wght = (float)tj.
MCSMom / momBin;
2301 if (cnt13 == 1) wght *= 2;
2304 if (tj.
ChgRMS < maxChgRMS) ++wght;
2309 tjids.push_back(tjid);
2310 tjwts.push_back(wght);
2313 if (tjids.empty())
return;
2318 for (
unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
2320 float wght1 = tjwts[it1];
2322 unsigned short end1 = 0;
2323 if (tj1.
VtxID[1] == vx2.
ID) end1 = 1;
2324 unsigned short endPt1 = tj1.
EndPt[end1];
2326 unsigned short oend1 = 1 - end1;
2328 float ang1 = tj1.
Pts[endPt1].Ang;
2329 float ang1Err2 = tj1.
Pts[endPt1].AngErr * tj1.
Pts[endPt1].AngErr;
2330 for (
unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
2332 float wght2 = tjwts[it2];
2334 if (tj2.
VtxID[1] == vx2.
ID) end2 = 1;
2336 unsigned short oend2 = 1 - end2;
2337 if (tj2.
EndFlag[oend2][kBragg]) ++wght2;
2338 unsigned short endPt2 = tj2.
EndPt[end2];
2339 float ang2 = tj2.
Pts[endPt2].Ang;
2340 float ang2Err2 = tj2.
Pts[endPt2].AngErr * tj2.
Pts[endPt2].AngErr;
2342 float dangErr = 0.5 * sqrt(ang1Err2 + ang2Err2);
2343 if ((dang / dangErr) > 3 && wght1 > 0 && wght2 > 0) {
2344 sum += wght1 + wght2;
2353 vx2.
Score = vpeScore + m3DScore + cfScore + tjScore;
2358 bool printHeader =
true;
2359 Print2V(myprt, vx2, printHeader);
2360 myprt << std::fixed << std::setprecision(1);
2361 myprt <<
" vpeScore " << vpeScore <<
" m3DScore " << m3DScore;
2362 myprt <<
" cfScore " << cfScore <<
" tjScore " << tjScore;
2363 myprt <<
" Score " << vx2.
Score;
2378 for (
unsigned short iv3 = 0; iv3 < slc.
vtx3s.size(); ++iv3) {
2381 if (vx3.
ID == 0)
continue;
2383 if (vx3.
Wire < 0)
continue;
2384 unsigned short mPlane = USHRT_MAX;
2385 for (
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
2386 if (vx3.
Vx2ID[ipl] > 0)
continue;
2390 if (mPlane == USHRT_MAX)
continue;
2394 if (dwc < 5)
continue;
2397 aVtx.
ID = slc.
vtxs.size() + 1;
2407 mf::LogVerbatim(
"TC") <<
"CI3DVIG: Incomplete vertex " << iv3 <<
" in plane " << mPlane
2408 <<
" wire " << vx3.
Wire <<
" Made 2D vertex ";
2409 std::vector<int> tjIDs;
2410 std::vector<unsigned short> tjEnds;
2411 for (
unsigned short itj = 0; itj < slc.
tjs.size(); ++itj) {
2412 if (slc.
tjs[itj].CTP != mCTP)
continue;
2414 for (
unsigned short end = 0;
end < 2; ++
end) {
2415 unsigned short ept = slc.
tjs[itj].EndPt[
end];
2417 unsigned short oept = slc.
tjs[itj].EndPt[1 -
end];
2422 if (doca > 2)
continue;
2425 if (aVtx.
Pos[0] > tp.
Pos[0]) { ptSep = aVtx.
Pos[0] - tp.
Pos[0] - dwc; }
2427 ptSep = tp.
Pos[0] - aVtx.
Pos[0] - dwc;
2431 <<
" ptSep " << ptSep;
2432 if (ptSep < -2 || ptSep > 2)
continue;
2434 if (slc.
tjs[itj].VtxID[
end] > 0)
continue;
2435 tjIDs.push_back(slc.
tjs[itj].ID);
2436 tjEnds.push_back(
end);
2439 if (!tjIDs.empty()) {
2446 for (
unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2447 unsigned short itj = tjIDs[ii] - 1;
2448 slc.
tjs[itj].VtxID[tjEnds[ii]] = aVtx.
ID;
2474 if (prt)
mf::LogVerbatim(
"TC") <<
"Inside CI3DV with maxdoca set to " << maxdoca;
2475 unsigned short ivx3 = 0;
2476 for (
auto& vx3 : slc.
vtx3s) {
2478 if (vx3.ID == 0)
continue;
2480 if (vx3.Wire < 0)
continue;
2481 unsigned short mPlane = USHRT_MAX;
2483 bool indPlnNoChgVtx =
false;
2484 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
2485 if (vx3.Vx2ID[plane] > 0) {
2486 auto& vx2 = slc.
vtxs[vx3.Vx2ID[plane] - 1];
2492 if (mPlane == USHRT_MAX)
continue;
2493 if (indPlnNoChgVtx)
continue;
2494 CTP_t mCTP =
EncodeCTP(vx3.TPCID.Cryostat, vx3.TPCID.TPC, mPlane);
2498 vtp.
Pos[0] = vx3.Wire;
2499 vtp.
Pos[1] = detProp.
ConvertXToTicks(vx3.X, mPlane, vx3.TPCID.TPC, vx3.TPCID.Cryostat) *
2502 mf::LogVerbatim(
"TC") <<
"CI3DV 3V" << vx3.ID <<
" Pos " << mPlane <<
":" 2504 std::vector<int> tjIDs;
2505 std::vector<unsigned short> tjPts;
2506 for (
auto& tj : slc.
tjs) {
2507 if (tj.CTP != mCTP)
continue;
2509 if (tj.Pts.size() < 6)
continue;
2511 float doca = maxdoca;
2513 unsigned short closePt = 0;
2515 if (closePt > tj.EndPt[1])
continue;
2520 mf::LogVerbatim(
"TC") <<
"CI3DV 3V" << vx3.ID <<
" candidate T" << tj.ID <<
" vtx pos " 2521 <<
PrintPos(vtp.
Pos) <<
" doca " << doca <<
" closePt " << closePt;
2522 tjIDs.push_back(tj.ID);
2523 tjPts.push_back(closePt);
2525 if (tjIDs.empty())
continue;
2529 auto vxtjs =
GetAssns(slc,
"3V", vx3.
ID,
"T");
2530 unsigned short maxPts = 0;
2531 unsigned short minPts = USHRT_MAX;
2532 for (
auto tjid : vxtjs) {
2533 auto& tj = slc.
tjs[tjid - 1];
2535 if (npwc > maxPts) maxPts = npwc;
2536 if (npwc < minPts) minPts = npwc;
2540 bool skipit =
false;
2541 for (
auto tjid : tjIDs) {
2542 auto& tj = slc.
tjs[tjid - 1];
2546 mf::LogVerbatim(
"TC") <<
" maxPts " << maxPts <<
" skipit? " << skipit <<
" minPts " 2548 if (skipit)
continue;
2551 unsigned short newVtxIndx = slc.
vtxs.size();
2552 aVtx.
ID = newVtxIndx + 1;
2570 std::array<float, 2> vpos = aVtx.
Pos;
2571 for (
unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2572 unsigned short itj = tjIDs[ii] - 1;
2573 unsigned short closePt = tjPts[ii];
2575 unsigned short end = 1;
2577 if (fabs(closePt - slc.
tjs[itj].EndPt[0]) < fabs(closePt - slc.
tjs[itj].EndPt[1])) end = 0;
2578 short dpt = fabs(closePt - slc.
tjs[itj].EndPt[end]);
2582 if (slc.
tjs[itj].VtxID[end] > 0) {
2584 auto& oldTj = slc.
tjs[itj];
2585 auto& oldVx = slc.
vtxs[oldTj.VtxID[
end] - 1];
2586 short oldSep = fabs(oldVx.Pos[0] - oldTj.Pts[oldTj.EndPt[end]].Pos[0]);
2589 <<
" T" << slc.
tjs[itj].ID <<
" has vertex 2V" << slc.
tjs[itj].VtxID[
end]
2590 <<
" at end " << end <<
". oldSep " << oldSep;
2596 slc.
tjs[itj].VtxID[
end] = slc.
vtxs[newVtxIndx].ID;
2601 vpos = slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[
end]].Pos;
2605 if (
SplitTraj(slc, itj, closePt, newVtxIndx, prt)) {
2608 <<
" SplitTraj success 2V" << slc.
vtxs[newVtxIndx].ID <<
" at closePt " << closePt;
2624 unsigned short newtj = slc.
tjs.size() - 1;
2627 if (newVtx.
NTraj == 0) {
2629 if (prt)
mf::LogVerbatim(
"TC") <<
" Failed. Recover and delete vertex " << newVtx.
ID;
2634 vx3.Vx2ID[mPlane] = newVtx.
ID;
2635 newVtx.
Vx3ID = vx3.ID;
2638 if (newVtx.
NTraj == 1) {
2646 myprt <<
" Success: new 2V" << newVtx.
ID <<
" at " << (int)newVtx.
Pos[0] <<
":" 2648 myprt <<
" points to 3V" << vx3.ID;
2650 for (
auto& tjID : tjIDs)
2665 float maxChg = tj.
Pts[nearPt].Chg;
2666 short maxChgPt = nearPt;
2667 unsigned short fromPt = tj.
EndPt[0];
2668 short spt = (short)nearPt - (
short)nPtsToChk;
2669 if (spt > (
short)fromPt) fromPt = nearPt - nPtsToChk;
2670 unsigned short toPt = nearPt + nPtsToChk;
2673 for (
short ipt = fromPt; ipt <= toPt; ++ipt) {
2674 if (ipt < tj.
EndPt[0] || ipt > tj.
EndPt[1])
continue;
2675 auto& tp = tj.
Pts[ipt];
2676 if (tp.Chg > maxChg) {
2682 <<
" chg " << (int)tp.Chg <<
" nhits " << tp.Hits.size();
2684 if (nearPt == maxChgPt)
return false;
2695 bool hasHighScoreVx3 = (vx2.
Vx3ID > 0);
2705 if (vx2.
Vx3ID > 0) {
2707 for (
auto& v3v2id : vx3.Vx2ID)
2708 if (v3v2id == vx2.
ID) v3v2id = 0;
2711 for (
auto& tj : slc.
tjs) {
2713 for (
unsigned short end = 0;
end < 2; ++
end) {
2714 if (tj.VtxID[
end] != vx2id)
continue;
2718 for (
unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
2720 unsigned short ipt = tj.EndPt[0] + ii;
2721 auto& tp = tj.Pts[ipt];
2723 if (ipt == tj.EndPt[1])
break;
2726 unsigned short ipt = tj.EndPt[1] - ii;
2727 auto& tp = tj.Pts[ipt];
2729 if (ipt == tj.EndPt[0])
break;
2734 unsigned short oend = 1 -
end;
2735 if (tj.VtxID[oend] > 0) {
2736 auto& ovx2 = slc.
vtxs[tj.VtxID[oend] - 1];
2743 if (!hasHighScoreVx3)
return true;
2749 unsigned short plane = planeID.
Plane;
2750 if (vx3.
Vx2ID[plane] != vx2id)
return true;
2751 vx3.
Vx2ID[plane] = 0;
2754 unsigned short n2D = 0;
2755 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane)
2756 if (vx3.
Vx2ID[plane] > 0) ++n2D;
2767 for (
auto& vx2 : slc.
vtxs) {
2768 if (vx2.
ID == 0)
continue;
2771 for (
auto& pfp : slc.
pfps) {
2772 for (
unsigned short end = 0;
end < 2; ++
end)
2773 if (pfp.Vx3ID[
end] == vx3.
ID) pfp.Vx3ID[
end] = 0;
2786 if (vx3.
ID <= 0)
return true;
2787 if (vx3.
ID >
int(slc.
vtx3s.size()))
return false;
2789 for (
auto vx2id : vx3.
Vx2ID) {
2790 if (vx2id == 0 || vx2id > (
int)slc.
vtxs.size())
continue;
2791 auto& vx2 = slc.
vtxs[vx2id - 1];
2802 std::vector<int>
tmp;
2803 if (vx2.
ID == 0)
return tmp;
2804 for (
auto& tj : slc.
tjs) {
2805 if (tj.AlgMod[
kKilled])
continue;
2806 if (tj.CTP != vx2.
CTP)
continue;
2807 for (
unsigned short end = 0;
end < 2; ++
end) {
2808 if (tj.VtxID[
end] == vx2.
ID) tmp.push_back(tj.ID);
2818 std::vector<int>
tmp;
2819 if (vx3.
ID == 0)
return tmp;
2822 for (
auto& vx2 : slc.
vtxs) {
2823 if (vx2.ID == 0)
continue;
2824 if (vx2.Vx3ID != vx3.
ID)
continue;
2826 tmp.insert(tmp.end(), vtxTjID2.begin(), vtxTjID2.end());
2830 if (nvx2 < 1)
return tmp;
2834 std::sort(tmp.begin(), tmp.end());
2841 unsigned short plane,
2857 unsigned short imBest = 0;
2858 for (
auto& vx2 : slc.
vtxs) {
2859 if (vx2.CTP != inVx2.
CTP)
continue;
2860 if (vx2.ID <= 0)
continue;
2862 if (pull < minPull) {
2876 unsigned short imBest = 0;
2877 for (
auto& oldvx3 : slc.
vtx3s) {
2878 if (oldvx3.ID == 0)
continue;
2881 if (pull < minPull) {
Expect tracks entering from the front face. Don't create neutrino PFParticles.
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< Trajectory > tjs
vector of all trajectories in each plane
float Length(const PFPStruct &pfp)
bool MergeWithVertex(TCSlice &slc, VtxStore &vx, unsigned short oVxID)
Length_t WireCoordinate(Point_t const &pos, PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
struct of temporary 2D vertices (end points)
static unsigned int kWire
bool AttachAnyVertexToTraj(TCSlice &slc, int tjID, bool prt)
CTP_t CTP
Cryostat, TPC, Plane code.
std::vector< float > maxPos0
void CompleteIncomplete3DVerticesInGaps(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc)
std::array< double, 3 > Point3_t
bool SignalAtTp(TrajPoint &tp)
bool FitVertex(TCSlice &slc, VtxStore &vx, bool prt)
std::vector< float > vtx3DCuts
2D vtx -> 3D vtx matching cuts
void SetPDGCode(TCSlice &slc, unsigned short itj)
void Find3DVertices(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc)
vertex position fixed manually - no fitting done
void SplitTrajCrossingVertices(TCSlice &slc, CTP_t inCTP)
void PrintTP(std::string someText, const TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, const TrajPoint &tp)
void Reconcile2Vs(TCSlice &slc)
Planes which measure X direction.
The data type to uniquely identify a Plane.
matched to a high-score 3D vertex
step from US -> DS (true) or DS -> US (false)
float VertexVertexPull(const Vtx3Store &vx1, const Vtx3Store &vx2)
short MCSMom
Normalized RMS using ALL hits. Assume it is 50% to start.
constexpr auto abs(T v)
Returns the absolute value of the argument.
CryostatID_t Cryostat
Index of cryostat.
for(Int_t i=0;i< nentries;i++)
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
bool AttachAnyTrajToVertex(TCSlice &slc, unsigned short ivx, bool prt)
unsigned short TPNearVertex(const TCSlice &slc, const TrajPoint &tp)
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
bool dbgSlc
debug only in the user-defined slice? default is all slices
void Print2V(mf::LogVerbatim &myprt, VtxStore const &vx2, bool &printHeader)
std::array< int, 2 > Vx3ID
void SetVx3Score(TCSlice &slc, Vtx3Store &vx3)
tick ticks
Alias for common language habits.
std::string PrintPos(const TrajPoint &tp)
void CompleteIncomplete3DVertices(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc)
bool StoreVertex(TCSlice &slc, VtxStore &vx)
bool dbg3V
debug 3D vertex finding
bool SignalBetween(const TrajPoint &tp1, const TrajPoint &tp2, const float MinWireSignalFraction)
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Access the description of detector geometry.
struct of temporary 3D vertices
unsigned short NearestPtWithChg(const Trajectory &tj, unsigned short thePt)
std::array< float, 2 > Point2_t
std::vector< float > maxPos1
float unitsPerTick
scale factor from Tick to WSE equivalent units
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
CTP_t CTP
Cryostat, TPC, Plane code.
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
the environment near the vertex was checked - See UpdateVxEnvironment
bool dbg2V
debug 2D vertex finding
std::vector< TrajPoint > Pts
Trajectory points.
bool ChkVtxAssociations(TCSlice &slc, const CTP_t &inCTP)
bool Reconcile2VTs(TCSlice &slc, std::vector< int > &vx2cls, bool prt)
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
std::vector< unsigned int > FindCloseHits(const TCSlice &slc, std::array< int, 2 > const &wireWindow, Point2_t const &timeWindow, const unsigned short plane, HitStatus_t hitRequest, bool usePeakTime, bool &hitsNear)
std::vector< VtxStore > vtxs
2D vertices
std::array< unsigned short, 2 > EndPt
First and last point in the trajectory that has charge.
unsigned short PDGCode
shower-like or track-like {default is track-like}
double ConvertXToTicks(double X, int p, int t, int c) const
void ScoreVertices(TCSlice &slc)
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
std::string PrintHit(const TCHit &tch)
bool SplitTraj(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, unsigned short itj, float XPos, bool makeVx2, bool prt)
const geo::GeometryCore * geom
PlaneID_t Plane
Index of the plane within its TPC.
bool valsIncreasing(const SortEntry &c1, const SortEntry &c2)
Definition of data types for geometry description.
unsigned short FarEnd(const PFPStruct &pfp, const Point3_t &pos)
int ID
ID that is local to one slice.
std::array< unsigned short, 2 > VtxID
ID of 2D vertex.
vertex quality is suspect - No requirement made on chg btw it and the Tj
double ConvertTicksToX(double ticks, int p, int t, int c) const
std::bitset< 16 > modes
number of points to find AveChg
std::vector< TCHit > slHits
unsigned short NearbyCleanPt(const Trajectory &tj, unsigned short end)
unsigned short IsCloseToVertex(const TCSlice &slc, const VtxStore &inVx2)
std::bitset< 16 > Stat
Vertex status bits using kVtxBit_t.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
std::vector< int > GetAssns(TCSlice const &slc, std::string type1Name, int id, std::string type2Name)
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
std::vector< float > vtxScoreWeights
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
void SetHighScoreBits(TCSlice &slc, Vtx3Store &vx3)
std::vector< Vtx3Store > vtx3s
3D vertices
bool AttachTrajToVertex(TCSlice &slc, Trajectory &tj, VtxStore &vx, bool prt)
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
float TrajLength(const Trajectory &tj)
std::bitset< 128 > AlgMod
Bit set if algorithm AlgBit_t modifed the trajectory.
void UpdateVxEnvironment(TCSlice &slc)
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const VtxStore &vx2)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
bool valsDecreasing(const SortEntry &c1, const SortEntry &c2)
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
void KillPoorVertices(TCSlice &slc)
std::array< std::bitset< 8 >, 2 > EndFlag
int ID
ID of the recob::Slice (not the sub-slice)
void SetVx2Score(TCSlice &slc)
void FindHammerVertices(TCSlice &slc, const CTP_t &inCTP)
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
std::vector< PFPStruct > pfps
std::vector< int > FindCloseTjs(const TCSlice &slc, const TrajPoint &fromTp, const TrajPoint &toTp, const float &maxDelta)
void PrintAllTraj(detinfo::DetectorPropertiesData const &detProp, std::string someText, TCSlice const &slc, unsigned short itj, unsigned short ipt, bool prtVtx)
void MoveTPToWire(TrajPoint &tp, float wire)
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
bool IntersectionPoint(WireID const &wid1, WireID const &wid2, double &y, double &z) const
Returns the intersection point of two wires.
unsigned short CloseEnd(const Trajectory &tj, const Point2_t &pos)
float TrajPointVertexPull(const TrajPoint &tp, const VtxStore &vx)
void MakeJunkVertices(TCSlice &slc, const CTP_t &inCTP)
void Find2DVertices(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, const CTP_t &inCTP, unsigned short pass)
TPCID_t TPC
Index of the TPC within its cryostat.
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Vector3_t DirAtEnd(const PFPStruct &pfp, unsigned short end)
void FindHammerVertices2(TCSlice &slc, const CTP_t &inCTP)
float TjChgFrac
Fraction of charge near the vertex that is from hits on the vertex Tjs.
void TrajPointTrajDOCA(TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
master switch for turning on debug mode
bool AttachToAnyVertex(TCSlice &slc, PFPStruct &pfp, float maxSep, bool prt)
void PrintTPHeader(std::string someText)
CTP_t CTP
set to an invalid CTP
void PosInPlane(detinfo::DetectorPropertiesData const &detProp, const Vtx3Store &vx3, unsigned short plane, Point2_t &pos)
bool RefineVtxPosition(const Trajectory &tj, unsigned short &nearPt, short nPtsToChk, bool prt)