53 if (slc.
tjs.size() < 2)
return;
56 constexpr
float maxSep = 4;
62 <<
" maxSep btw tjs " << maxSep;
72 junkVx.
ID = USHRT_MAX;
74 junkVx.
PosErr = {{2.0, 2.0}};
79 for (
unsigned short it1 = 0; it1 < slc.
tjs.size() - 1; ++it1) {
80 auto& tj1 = slc.
tjs[it1];
82 if (tj1.SSID > 0 || tj1.AlgMod[
kShowerLike])
continue;
83 if (tj1.CTP != inCTP)
continue;
84 if (tj1.AlgMod[
kJunkTj])
continue;
86 if (tj1.MCSMom < 100)
continue;
87 for (
unsigned short end1 = 0; end1 < 2; ++end1) {
89 if (tj1.VtxID[end1] > 0)
continue;
90 auto& tp1 = tj1.Pts[tj1.EndPt[end1]];
93 if (tjlist.empty())
continue;
95 junkVx.
ID = USHRT_MAX;
96 for (
auto tj2id : tjlist) {
97 auto& tj2 = slc.
tjs[tj2id - 1];
98 if (tj2.CTP != inCTP)
continue;
99 if (tj2id == tj1.ID)
continue;
100 if (tj2.SSID > 0 || tj2.AlgMod[
kShowerLike])
continue;
101 float close = maxSep;
102 unsigned short closeEnd = USHRT_MAX;
103 for (
unsigned short end2 = 0; end2 < 2; ++end2) {
104 auto& tp2 = tj2.Pts[tj2.EndPt[end2]];
105 float sep =
PosSep(tp1.Pos, tp2.Pos);
111 if (closeEnd > 1)
continue;
112 auto& tp2 = tj2.Pts[tj2.EndPt[closeEnd]];
114 if (!signalBetween)
continue;
115 if (junkVx.
ID == USHRT_MAX) {
117 junkVx.
ID = slc.
vtxs.size() + 1;
118 junkVx.
Pos = tp1.Pos;
120 tj2.VtxID[closeEnd] = junkVx.
ID;
121 tj1.VtxID[end1] = junkVx.
ID;
123 if (junkVx.
ID == USHRT_MAX)
continue;
126 for (
auto& tj : slc.
tjs) {
127 if (tj.AlgMod[
kKilled])
continue;
128 if (tj.VtxID[0] == junkVx.
ID) tj.VtxID[0] = 0;
129 if (tj.VtxID[1] == junkVx.
ID) tj.VtxID[1] = 0;
138 junkVx.
ID = USHRT_MAX;
170 if (slc.
tjs.size() < 2)
return;
172 bool firstPassCuts = (pass == 0);
177 bool requireVtxTjChg =
true;
182 mf::LogVerbatim(
"TC") <<
"prt set for CTP " << inCTP <<
" in Find2DVertices. firstPassCuts? " 183 << firstPassCuts <<
" requireVtxTjChg " << requireVtxTjChg;
188 for (
unsigned short it1 = 0; it1 < slc.
tjs.size() - 1; ++it1) {
189 auto& tj1 = slc.
tjs[it1];
191 if (tj1.SSID > 0 || tj1.AlgMod[
kShowerLike])
continue;
192 if (tj1.CTP != inCTP)
continue;
193 bool tj1Short = (
TrajLength(tj1) < maxShortTjLen);
194 for (
unsigned short end1 = 0; end1 < 2; ++end1) {
196 if (tj1.VtxID[end1] > 0)
continue;
198 if (tj1.PDGCode == 111 && end1 != tj1.StartEnd)
continue;
201 short endPt1 = tj1.EndPt[end1];
202 float wire1 = tj1.Pts[endPt1].Pos[0];
206 if (tj1.Pts.size() > 6 && tj1.Pts[endPt1].NTPsFit < 4) {
207 if (end1 == 0 && endPt1 <
int(tj1.Pts.size()) - 3) { endPt1 += 3; }
208 else if (end1 == 1 && endPt1 >= 3) {
217 endPt1 = tj1.EndPt[end1];
218 short oendPt1 = tj1.EndPt[1 - end1];
220 auto& otp1 = tj1.Pts[oendPt1];
221 for (
unsigned short it2 = it1 + 1; it2 < slc.
tjs.size(); ++it2) {
222 auto& tj2 = slc.
tjs[it2];
224 if (tj2.SSID > 0 || tj2.AlgMod[
kShowerLike])
continue;
225 if (tj2.CTP != inCTP)
continue;
226 if (tj1.VtxID[end1] > 0)
continue;
228 bool tj2Short = (
TrajLength(tj2) < maxShortTjLen);
230 unsigned short end2 = 0;
231 if (
PosSep2(tj2.Pts[tj2.EndPt[1]].Pos, tp1.
Pos) <
234 if (tj2.VtxID[end2] > 0)
continue;
236 if (tj2.PDGCode == 111 && end2 != tj2.StartEnd)
continue;
238 if (tj1.VtxID[1 - end1] > 0 && tj1.VtxID[1 - end1] == tj2.VtxID[1 - end2])
continue;
240 unsigned short oendPt2 = tj2.EndPt[1 - end2];
241 auto& otp2 = tj2.Pts[oendPt2];
242 if (
PosSep2(otp1.Pos, otp2.Pos) <
PosSep2(tp1.
Pos, tj2.Pts[tj2.EndPt[end2]].Pos))
244 short endPt2 = tj2.EndPt[end2];
245 float wire2 = tj2.Pts[endPt2].Pos[0];
246 if (tj2.Pts.size() > 6 && tj2.Pts[endPt2].NTPsFit < 4) {
247 if (end2 == 0 && endPt2 <
int(tj2.Pts.size()) - 3) { endPt2 += 3; }
248 else if (end2 == 1 && endPt2 >= 3) {
256 endPt2 = tj2.EndPt[end2];
268 if (tj1Short || tj2Short) { sepCut =
tcc.
vtx2DCuts[1]; }
282 if (prt && vt1Sep < 200 && vt2Sep < 200) {
284 myprt <<
"F2DV candidate T" << tj1.ID <<
"_" << end1 <<
"-T" << tj2.ID <<
"_" << end2;
287 myprt <<
" dwc1 " << dwc1 <<
" dwc2 " << dwc2 <<
" on dead wire? " << vtxOnDeadWire;
288 myprt <<
" vt1Sep " << vt1Sep <<
" vt2Sep " << vt2Sep <<
" sepCut " << sepCut;
290 if (vt1Sep > sepCut || vt2Sep > sepCut)
continue;
292 if (
PosSep(vPos, slc.
tjs[it1].Pts[oendPt1].Pos) < vt1Sep) {
295 <<
" is closer to the vertex";
298 if (
PosSep(vPos, slc.
tjs[it2].Pts[oendPt2].Pos) < vt2Sep) {
301 <<
" is closer to the vertex";
305 unsigned short closePt1;
306 float doca1 = sepCut;
311 short dpt1 = stepDir * (closePt1 - endPt1);
313 mf::LogVerbatim(
"TC") <<
" endPt1 " << endPt1 <<
" closePt1 " << closePt1 <<
" dpt1 " 314 << dpt1 <<
" doca1 " << doca1;
315 if (dpt1 < -1)
continue;
316 if (slc.
tjs[it1].EndPt[1] > 4) {
317 if (dpt1 > 3)
continue;
321 if (dpt1 > 2)
continue;
323 unsigned short closePt2;
324 float doca2 = sepCut;
326 short dpt2 = stepDir * (closePt2 - endPt2);
328 mf::LogVerbatim(
"TC") <<
" endPt2 " << endPt2 <<
" closePt2 " << closePt2 <<
" dpt2 " 329 << dpt2 <<
" doca2 " << doca2;
330 if (dpt2 < -1)
continue;
331 if (slc.
tjs[it2].EndPt[1] > 4) {
332 if (dpt2 > 3)
continue;
336 if (dpt2 > 2)
continue;
338 bool fixVxPos =
false;
340 if (tj1.EndFlag[end1][
kAtKink]) fixVxPos =
true;
344 if (requireVtxTjChg) {
346 bool signalBetween =
true;
347 short dpt =
abs(wint - tp1.
Pos[0]);
349 if (prt)
mf::LogVerbatim(
"TC") <<
" Fails SignalBetween for tp1 " << dpt;
350 signalBetween =
false;
352 dpt =
abs(wint - tp2.
Pos[0]);
354 if (prt)
mf::LogVerbatim(
"TC") <<
" Fails SignalBetween for tp2 " << dpt;
355 signalBetween =
false;
359 if (!signalBetween) {
360 unsigned short ipt1, ipt2;
362 bool isClose =
TrajTrajDOCA(slc, tj1, tj2, ipt1, ipt2, maxSep,
false);
364 if (isClose) isClose = (
abs(ipt1 - endPt1) < 4 &&
abs(ipt2 - endPt2) < 4);
368 <<
" TrajTrajDOCA are close with minSep " << maxSep <<
" near " 369 <<
PrintPos(slc, tj1.Pts[ipt1].Pos) <<
" " <<
PrintPos(slc, tj2.Pts[ipt2].Pos);
396 aVtx.
Pass = tj1.Pass;
398 aVtx.
Topo = 2 * end1;
407 unsigned short newVtxID = slc.
vtxs.size() + 1;
409 tj1.VtxID[end1] = newVtxID;
410 tj2.VtxID[end2] = newVtxID;
419 if (prt)
mf::LogVerbatim(
"TC") <<
" Merged with close vertex " << mergeMeWithVx;
426 myprt <<
" New vtx 2V" << aVtx.
ID;
427 myprt <<
" Tjs " << tj1.ID <<
"_" << end1 <<
"-" << tj2.ID <<
"_" << end2;
438 if (pass == USHRT_MAX) {
443 if (prt)
PrintAllTraj(detProp,
"F2DVo", slc, USHRT_MAX, USHRT_MAX);
461 if (oVxID > slc.
vtxs.size())
return false;
462 auto& oVx = slc.
vtxs[oVxID - 1];
463 if (vx.
CTP != oVx.CTP)
return false;
467 if (tjlist.empty())
return false;
469 if (tmp.empty())
return false;
470 for (
auto tjid : tmp) {
471 if (std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end()) tjlist.push_back(tjid);
473 if (tjlist.size() < 2)
return false;
475 if (tjlist.size() == 2) {
480 for (
auto tjid : tjlist) {
481 auto& tj = slc.
tjs[tjid - 1];
482 for (
unsigned short end = 0;
end < 2; ++
end) {
483 if (tj.VtxID[
end] == vx.
ID) tj.VtxID[
end] = oVx.ID;
488 mf::LogVerbatim(
"TC") <<
"MWV: merge failed " << vx.
ID <<
" and existing " << oVx.ID;
495 std::vector<SortEntry> sortVec(tjlist.size());
496 for (
unsigned int indx = 0; indx < sortVec.size(); ++indx) {
497 sortVec[indx].index = indx;
498 auto& tj = slc.
tjs[tjlist[indx] - 1];
499 sortVec[indx].val = tj.Pts.size();
504 for (
unsigned short ii = 0; ii < sortVec.size(); ++ii)
505 tjlist[ii] = ttl[sortVec[ii].
index];
510 std::vector<TrajPoint> tjpts(tjlist.size());
514 std::array<float, 2> vpos;
515 vpos[0] = 0.5 * (vx.
Pos[0] + oVx.Pos[0]);
516 vpos[1] = 0.5 * (vx.
Pos[1] + oVx.Pos[1]);
517 for (
unsigned short ii = 0; ii < tjpts.size(); ++ii) {
518 auto& tj = slc.
tjs[tjlist[ii] - 1];
522 unsigned short endPt = tj.EndPt[
end];
523 if (npwc > 6 && tj.Pts[endPt].NTPsFit < 4) {
524 if (end == 0) { endPt += 3; }
530 if (endPt < tj.EndPt[0]) endPt = tj.EndPt[0];
531 if (endPt > tj.EndPt[1]) endPt = tj.EndPt[1];
533 tjpts[ii].CTP = tj.CTP;
534 tjpts[ii].Pos = tj.Pts[endPt].Pos;
535 tjpts[ii].Dir = tj.Pts[endPt].Dir;
536 tjpts[ii].Ang = tj.Pts[endPt].Ang;
537 tjpts[ii].AngErr = tj.Pts[endPt].AngErr;
539 tjpts[ii].Step = endPt;
541 tjpts[ii].AngleCode =
end;
543 tjpts[ii].Hits.resize(1, tj.ID);
547 myprt <<
"MWV: " << oVxID;
549 for (
unsigned short ii = 0; ii < tjpts.size(); ++ii) {
550 auto& tjpt = tjpts[ii];
551 myprt <<
" " << tjlist[ii] <<
"_" << tjpt.Step <<
"_" <<
PrintPos(slc, tjpt.Pos);
562 bool needsUpdate =
false;
563 for (
unsigned short ii = 2; ii < tjlist.size(); ++ii) {
564 fitpts.push_back(tjpts[ii]);
565 if (
FitVertex(slc, aVx, fitpts, prt)) { needsUpdate =
false; }
573 if (needsUpdate)
FitVertex(slc, aVx, fitpts, prt);
574 if (prt)
mf::LogVerbatim(
"TC") <<
"MWV: done " << vx.
ID <<
" and existing " << oVx.ID;
577 for (
auto& tj : slc.
tjs) {
579 if (tj.CTP != vx.
CTP)
continue;
580 for (
unsigned short end = 0;
end < 2; ++
end) {
581 if (tj.VtxID[
end] == vx.
ID) tj.VtxID[
end] = 0;
582 if (tj.VtxID[
end] == oVxID) tj.VtxID[
end] = 0;
586 for (
unsigned short ii = 0; ii < fitpts.size(); ++ii) {
587 auto& tjpt = fitpts[ii];
588 unsigned short end = tjpt.AngleCode;
589 auto& tj = slc.
tjs[tjpt.Hits[0] - 1];
590 if (tj.VtxID[end] != 0)
return false;
591 tj.VtxID[
end] = oVxID;
598 oVx.NTraj = fitpts.size();
605 myprt <<
"MWV: " << oVxID;
606 myprt <<
" Done TPs";
607 for (
unsigned short ii = 0; ii < fitpts.size(); ++ii) {
608 auto& tjpt = fitpts[ii];
609 myprt <<
" " << tjpt.Hits[0] <<
"_" << tjpt.AngleCode <<
"_" <<
PrintPos(slc, tjpt.Pos);
637 for (
unsigned short it1 = 0; it1 < slc.
tjs.size(); ++it1) {
638 if (slc.
tjs[it1].CTP != inCTP)
continue;
640 if (slc.
tjs[it1].AlgMod[
kHamVx])
continue;
643 if (slc.
tjs[it1].PDGCode == 111)
continue;
645 if (numPtsWithCharge1 < 6)
continue;
647 if (slc.
tjs[it1].MCSMom < 200)
continue;
649 bool didaSplit =
false;
650 for (
unsigned short end1 = 0; end1 < 2; ++end1) {
652 if (slc.
tjs[it1].VtxID[end1] > 0)
continue;
653 unsigned short endPt1 = slc.
tjs[it1].EndPt[end1];
654 for (
unsigned short it2 = 0; it2 < slc.
tjs.size(); ++it2) {
655 if (it1 == it2)
continue;
656 if (slc.
tjs[it2].AlgMod[
kKilled] || slc.
tjs[it2].AlgMod[kHaloTj])
continue;
657 if (slc.
tjs[it2].AlgMod[kHamVx])
continue;
658 if (slc.
tjs[it2].AlgMod[kHamVx2])
continue;
660 if (slc.
tjs[it2].CTP != inCTP)
continue;
662 if (slc.
tjs[it2].AlgMod[kJunkTj])
continue;
663 if (slc.
tjs[it2].PDGCode == 111)
continue;
665 if (numPtsWithCharge2 < 6)
continue;
667 if (numPtsWithCharge2 > 100 && slc.
tjs[it2].MCSMom > 500)
continue;
670 float doca = minDOCA;
671 unsigned short closePt2 = 0;
673 if (doca == minDOCA)
continue;
676 auto& tj1 = slc.
tjs[it1];
677 auto& tj2 = slc.
tjs[it2];
678 myprt <<
" FHV2 CTP" << tj1.CTP;
679 myprt <<
" t" << tj1.ID <<
"_" << end1 <<
" MCSMom " << tj1.MCSMom <<
" ChgRMS " 681 myprt <<
" split t" << tj2.ID <<
"? MCSMom " << tj2.MCSMom <<
" ChgRMS " << tj2.ChgRMS;
682 myprt <<
" doca " << doca <<
" tj2.EndPt[0] " << tj2.EndPt[0] <<
" closePt2 " 684 myprt <<
" tj2.EndPt[1] " << tj2.EndPt[1];
687 if (closePt2 < slc.
tjs[it2].EndPt[0] + 3)
continue;
688 if (closePt2 > slc.
tjs[it2].EndPt[1] - 3)
continue;
693 float dang =
DeltaAngle(slc.
tjs[it1].Pts[endPt1].Ang, slc.
tjs[it2].Pts[closePt2].Ang);
694 if (dang < 0.2)
continue;
697 unsigned short closePt1 = 0;
699 if (closePt1 != endPt1)
continue;
706 unsigned short intPt2;
710 <<
PrintPos(slc, slc.
tjs[it2].Pts[intPt2]) <<
" doca " << doca;
711 if (doca == minDOCA)
continue;
713 float mcsmom = slc.
tjs[it2].MCSMom;
714 float mcsmom1 =
MCSMom(slc, slc.
tjs[it2], slc.
tjs[it2].EndPt[0], intPt2);
715 float mcsmom2 =
MCSMom(slc, slc.
tjs[it2], intPt2, slc.
tjs[it2].EndPt[1]);
718 mf::LogVerbatim(
"TC") <<
" Check MCSMom after split: mcsmom1 " << mcsmom1 <<
" mcsmom2 " 720 if (mcsmom1 < mcsmom || mcsmom2 < mcsmom)
continue;
724 if (intPt2 < closePt2) dir = -1;
725 unsigned short nit = 0;
726 unsigned short ipt = intPt2;
727 float mostChg = slc.
tjs[it2].Pts[ipt].Chg;
730 <<
PrintPos(slc, slc.
tjs[it2].Pts[ipt]) <<
" chg " << mostChg;
733 if (ipt < 3 || ipt > slc.
tjs[it2].Pts.size() - 4)
break;
735 slc.
tjs[it2].Pts[ipt].Pos[0],
736 slc.
tjs[it2].Pts[ipt].Pos[1],
737 slc.
tjs[it1].Pts[endPt1]);
738 float sep =
PosSep(slc.
tjs[it2].Pts[ipt].Pos, slc.
tjs[it1].Pts[endPt1].Pos);
739 float dang = delta / sep;
740 float pull = dang / slc.
tjs[it1].Pts[endPt1].DeltaRMS;
741 if (pull < 2 && slc.
tjs[it2].Pts[ipt].Chg > mostChg) {
742 mostChg = slc.
tjs[it2].Pts[ipt].Chg;
747 float chgPull = (mostChg - slc.
tjs[it2].AveChg) / slc.
tjs[it2].ChgRMS;
749 if (chgPull < 10)
continue;
752 if (slc.
tjs[it1].Pts[endPt1].Pos[0] < -0.4)
continue;
753 unsigned int fromWire = std::nearbyint(slc.
tjs[it1].Pts[endPt1].Pos[0]);
754 if (slc.
tjs[it2].Pts[intPt2].Pos[0] < -0.4)
continue;
755 unsigned int toWire = std::nearbyint(slc.
tjs[it2].Pts[intPt2].Pos[0]);
756 if (fromWire > toWire) {
757 unsigned int tmp = fromWire;
762 for (
unsigned int wire = fromWire + 1; wire < toWire; ++wire) {
769 if (skipIt)
continue;
773 aVtx.
Pos = slc.
tjs[it2].Pts[intPt2].Pos;
779 aVtx.
ID = slc.
vtxs.size() + 1;
780 unsigned short ivx = slc.
vtxs.size();
782 if (!
SplitTraj(slc, it2, intPt2, ivx, prt)) {
787 slc.
tjs[it1].VtxID[end1] = slc.
vtxs[ivx].ID;
790 unsigned short newTjIndex = slc.
tjs.size() - 1;
800 << slc.
vtxs[ivx].Score;
804 if (didaSplit)
break;
827 for (
unsigned short it1 = 0; it1 < slc.
tjs.size(); ++it1) {
828 if (slc.
tjs[it1].CTP != inCTP)
continue;
832 if (slc.
tjs[it1].PDGCode == 111)
continue;
834 unsigned short tj1len = slc.
tjs[it1].EndPt[1] - slc.
tjs[it1].EndPt[0] + 1;
835 if (tj1len < 5)
continue;
837 if (slc.
tjs[it1].MCSMom < 50)
continue;
838 if (prt)
mf::LogVerbatim(
"TC") <<
"FHV: intersection T" << slc.
tjs[it1].ID <<
" candidate";
840 bool didaSplit =
false;
841 for (
unsigned short end1 = 0; end1 < 2; ++end1) {
843 if (slc.
tjs[it1].VtxID[end1] > 0)
continue;
844 unsigned short endPt1 = slc.
tjs[it1].EndPt[end1];
845 for (
unsigned short it2 = 0; it2 < slc.
tjs.size(); ++it2) {
846 if (slc.
tjs[it2].CTP != inCTP)
continue;
847 if (it1 == it2)
continue;
848 if (slc.
tjs[it2].AlgMod[
kKilled] || slc.
tjs[it2].AlgMod[kHaloTj])
continue;
849 if (slc.
tjs[it2].AlgMod[kJunkTj])
continue;
850 if (slc.
tjs[it2].PDGCode == 111)
continue;
852 unsigned short tj2len = slc.
tjs[it2].EndPt[1] - slc.
tjs[it2].EndPt[0] + 1;
853 if (tj2len < 6)
continue;
855 if (tj2len > 200 && slc.
tjs[it2].PDGCode == 13 && slc.
tjs[it2].MCSMom > 600)
continue;
857 minDOCA /=
std::abs(slc.
tjs[it1].Pts[endPt1].Dir[0]);
858 float doca = minDOCA;
859 unsigned short closePt2 = 0;
861 if (doca == minDOCA)
continue;
865 << slc.
tjs[it2].ID <<
" doca " << doca <<
" tj2.EndPt[0] " 866 << slc.
tjs[it2].EndPt[0] <<
" closePt2 " << closePt2
867 <<
" tj2.EndPt[1] " << slc.
tjs[it2].EndPt[1];
868 if (closePt2 < slc.
tjs[it2].EndPt[0] + 3)
continue;
869 if (closePt2 > slc.
tjs[it2].EndPt[1] - 3)
continue;
871 float dang =
DeltaAngle(slc.
tjs[it1].Pts[endPt1].Ang, slc.
tjs[it2].Pts[closePt2].Ang);
873 mf::LogVerbatim(
"TC") <<
" dang " << dang <<
" imposing a hard cut of 0.4 for now ";
874 if (dang < 0.4)
continue;
876 std::vector<int> tjids(2);
877 tjids[0] = slc.
tjs[it1].ID;
878 tjids[1] = slc.
tjs[it2].ID;
881 if (chgFrac < 0.9)
continue;
885 slc.
tjs[it1].Pts[endPt1], slc.
tjs[it2].Pts[closePt2], vxpos[0], vxpos[1]);
900 aVtx.
ID = slc.
vtxs.size() + 1;
902 unsigned short ivx = slc.
vtxs.size() - 1;
903 if (!
SplitTraj(slc, it2, closePt2, ivx, prt)) {
908 slc.
tjs[it1].VtxID[end1] = slc.
vtxs[ivx].ID;
911 unsigned short newTjIndex = slc.
tjs.size() - 1;
912 slc.
tjs[newTjIndex].AlgMod[
kHamVx] =
true;
919 auto& vx2 = slc.
vtxs[ivx];
921 myprt <<
" new 2V" << vx2.ID <<
" Score " << vx2.Score <<
" Tjs";
922 auto tjlist =
GetAssns(slc,
"2V", vx2.
ID,
"T");
923 for (
auto tid : tjlist)
924 myprt <<
" t" << tid;
929 if (didaSplit)
break;
943 if (slc.
vtxs.empty())
return;
944 if (slc.
tjs.empty())
return;
946 constexpr
float docaCut = 4;
949 if (prt)
mf::LogVerbatim(
"TC") <<
"Inside SplitTrajCrossingVertices inCTP " << inCTP;
953 unsigned short nTraj = slc.
tjs.size();
954 for (
unsigned short itj = 0; itj < nTraj; ++itj) {
956 if (slc.
tjs[itj].CTP != inCTP)
continue;
962 if (slc.
tjs[itj].EndPt[1] < 6)
continue;
963 for (
unsigned short iv = 0; iv < slc.
vtxs.size(); ++iv) {
964 auto& vx2 = slc.
vtxs[iv];
966 if (vx2.NTraj == 0)
continue;
968 if (slc.
tjs[itj].VtxID[0] == vx2.ID || slc.
tjs[itj].VtxID[1] == vx2.ID)
continue;
970 if (slc.
tjs[itj].CTP != vx2.CTP)
continue;
973 float doca = docaCut;
977 unsigned short closePt = 0;
982 doca =
PointTrajDOCA(slc, vx2.Pos[0], vx2.Pos[1], slc.
tjs[itj].Pts[closePt]);
984 if (doca > docaCut)
continue;
987 << slc.
vtxs[iv].ID <<
" closePt " << closePt <<
" in plane " 993 if (vxtjs.empty())
continue;
994 unsigned short maxPts = 0;
998 float tjAng = slc.
tjs[itj].Pts[closePt].Ang;
999 for (
auto tjid : vxtjs) {
1000 auto& vtj = slc.
tjs[tjid - 1];
1003 if (npwc > maxPts) maxPts = npwc;
1004 unsigned short end = 0;
1005 if (vtj.VtxID[1] == slc.
vtxs[iv].ID) end = 1;
1006 auto& vtp = vtj.Pts[vtj.EndPt[
end]];
1008 if (dang > maxdang) maxdang = dang;
1012 bool skipit =
false;
1014 if (!skipit && maxdang < 0.3) skipit =
true;
1016 mf::LogVerbatim(
"TC") <<
" maxPts " << maxPts <<
" vxtjs[0] " << vxtjs[0] <<
" maxdang " 1017 << maxdang <<
" skipit? " << skipit;
1028 auto& closeTP = slc.
tjs[itj].Pts[closePt];
1029 if (slc.
tjs[itj].StepDir > 0 && closePt > slc.
tjs[itj].EndPt[0]) {
1030 if (closeTP.Pos[0] > vx2.Pos[0]) --closePt;
1032 else if (slc.
tjs[itj].StepDir < 0 && closePt < slc.
tjs[itj].EndPt[1]) {
1033 if (closeTP.Pos[0] < vx2.Pos[0]) ++closePt;
1040 if ((slc.
tjs[itj].Pts[closePt].Pos[0] - vx2.Pos[0]) *
1041 (slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[1]].Pos[0] - vx2.Pos[0]) +
1042 (slc.
tjs[itj].Pts[closePt].Pos[1] - vx2.Pos[1]) *
1043 (slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[1]].Pos[1] - vx2.Pos[1]) <
1045 closePt < slc.
tjs[itj].EndPt[1] - 1)
1047 else if ((slc.
tjs[itj].Pts[closePt].Pos[0] - vx2.Pos[0]) *
1048 (slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[0]].Pos[0] - vx2.Pos[0]) +
1049 (slc.
tjs[itj].Pts[closePt].Pos[1] - vx2.Pos[1]) *
1050 (slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[0]].Pos[1] - slc.
vtxs[iv].Pos[1]) <
1052 closePt > slc.
tjs[itj].EndPt[0] + 1)
1057 mf::LogVerbatim(
"TC") <<
"Good doca " << doca <<
" btw T" << slc.
tjs[itj].ID <<
" and 2V" 1058 << vx2.ID <<
" closePt " << closePt <<
" in plane " << planeID.
Plane 1059 <<
" CTP " << slc.
vtxs[iv].CTP;
1060 PrintTP(
"STCV", slc, closePt, 1, slc.
tjs[itj].Pass, slc.
tjs[itj].Pts[closePt]);
1063 if (closePt < slc.
tjs[itj].EndPt[0] + 3)
continue;
1064 if (closePt > slc.
tjs[itj].EndPt[1] - 3)
continue;
1065 if (!
SplitTraj(slc, itj, closePt, iv, prt)) {
1066 if (prt)
mf::LogVerbatim(
"TC") <<
"SplitTrajCrossingVertices: Failed to split trajectory";
1070 unsigned short newTjIndex = slc.
tjs.size() - 1;
1086 if (slc.
vtxs.empty())
return;
1091 std::vector<std::vector<int>> vx2Cls;
1094 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
1097 for (
unsigned short ii = 0; ii < slc.
vtxs.size() - 1; ++ii) {
1098 auto& i2v = slc.
vtxs[ii];
1099 if (i2v.ID <= 0)
continue;
1101 for (
unsigned short jj = ii + 1; jj < slc.
vtxs.size(); ++jj) {
1102 auto& j2v = slc.
vtxs[jj];
1103 if (j2v.ID <= 0)
continue;
1106 float dp0 =
std::abs(i2v.Pos[0] - j2v.Pos[0]);
1107 if (dp0 > 10)
continue;
1108 float dp1 =
std::abs(i2v.Pos[1] - j2v.Pos[1]);
1109 if (dp1 > 10)
continue;
1111 float err = i2v.PosErr[0];
1112 if (j2v.PosErr[0] > err) err = j2v.PosErr[0];
1113 float dp0Sig = dp0 /
err;
1114 if (dp0Sig > 4)
continue;
1115 err = i2v.PosErr[1];
1116 if (j2v.PosErr[1] > err) err = j2v.PosErr[1];
1117 float dp1Sig = dp1 /
err;
1118 if (dp1Sig > 4)
continue;
1121 for (
auto& vx2cls : vx2Cls) {
1122 bool goti = (std::find(vx2cls.begin(), vx2cls.end(), i2v.ID) != vx2cls.end());
1123 bool gotj = (std::find(vx2cls.begin(), vx2cls.end(), j2v.ID) != vx2cls.end());
1129 vx2cls.push_back(j2v.ID);
1135 vx2cls.push_back(i2v.ID);
1141 std::vector<int> cls(2);
1144 vx2Cls.push_back(cls);
1148 if (vx2Cls.empty())
continue;
1151 myprt <<
"2V clusters in plane " << plane;
1152 for (
auto& vx2cls : vx2Cls) {
1154 for (
auto vx2id : vx2cls)
1155 myprt <<
" 2V" << vx2id;
1158 for (
auto& vx2cls : vx2Cls) {
1165 bool VxEnvironmentNeedsUpdate =
false;
1166 for (
auto& vx : slc.
vtxs) {
1167 if (vx.ID <= 0)
continue;
1168 if (!vx.Stat[
kVxEnvOK]) VxEnvironmentNeedsUpdate =
true;
1183 if (vx2cls.size() < 2)
return false;
1186 std::vector<int> t2vList;
1189 for (
auto vx2id : vx2cls) {
1190 auto& vx2 = slc.
vtxs[vx2id - 1];
1193 if (vx2.ID <= 0)
return true;
1194 auto tlist =
GetAssns(slc,
"2V", vx2.
ID,
"T");
1195 for (
auto tid : tlist)
1196 if (std::find(t2vList.begin(), t2vList.end(), tid) == t2vList.end()) t2vList.push_back(tid);
1198 if (t2vList.size() < 3)
return false;
1203 for (
auto tid : t2vList) {
1204 auto& tj = slc.
tjs[tid - 1];
1205 for (
unsigned short end = 0;
end < 2; ++
end) {
1206 if (tj.VtxID[
end] <= 0)
continue;
1207 if (std::find(vx2cls.begin(), vx2cls.end(), tj.VtxID[
end]) == vx2cls.end())
continue;
1208 auto& vx = slc.
vtxs[tj.VtxID[
end] - 1];
1209 unsigned short nearEnd = 1 -
FarEnd(slc, tj, vx.Pos);
1211 if (fitPt == USHRT_MAX)
return false;
1212 auto& tp = tj.Pts[fitPt];
1220 myprt <<
"R2VTs: cluster:";
1221 for (
auto vid : vx2cls)
1222 myprt <<
" 2V" << vid;
1224 for (
auto tid : t2vList)
1225 myprt <<
" T" << tid;
1234 for (
auto vid : vx2cls) {
1235 auto& vx = slc.
vtxs[vid - 1];
1236 oneVx.
Pos[0] += vx.Pos[0];
1237 oneVx.
Pos[1] += vx.Pos[2];
1239 oneVx.
Pos[0] /= vx2cls.size();
1240 oneVx.
Pos[1] /= vx2cls.size();
1241 std::vector<TrajPoint> oneVxTPs(t2vList.size());
1242 for (
unsigned short itj = 0; itj < t2vList.size(); ++itj) {
1243 auto& tj = slc.
tjs[t2vList[itj] - 1];
1244 unsigned short nearEnd = 1 -
FarEnd(slc, tj, oneVx.
Pos);
1246 if (fitPt == USHRT_MAX)
return false;
1247 oneVxTPs[itj] = tj.Pts[fitPt];
1249 if (oneVxTPs[itj].Environment[
kEnvOverlap]) oneVxTPs[itj].AngErr *= 4;
1250 oneVxTPs[itj].Step = tj.ID;
1252 if (!
FitVertex(slc, oneVx, oneVxTPs, prt))
return false;
1256 auto& vx = slc.
vtxs[vx2cls[0] - 1];
1258 vx.PosErr = oneVx.
PosErr;
1259 vx.NTraj = t2vList.size();
1260 vx.ChiDOF = oneVx.
ChiDOF;
1265 for (
unsigned short ivx = 1; ivx < vx2cls.size(); ++ivx) {
1266 auto& vx = slc.
vtxs[vx2cls[ivx] - 1];
1270 for (
auto tid : t2vList) {
1271 auto& tj = slc.
tjs[tid - 1];
1272 unsigned short nearEnd = 1 -
FarEnd(slc, tj, vx.Pos);
1273 tj.VtxID[nearEnd] = vx.ID;
1289 if (slc.
vtxs.size() < 2)
return;
1292 std::vector<std::vector<unsigned short>> vIndex(3);
1293 for (
unsigned short ivx = 0; ivx < slc.
vtxs.size(); ++ivx) {
1295 if (slc.
vtxs[ivx].ID == 0)
continue;
1298 unsigned short plane = planeID.
Plane;
1299 if (plane > 2)
continue;
1300 vIndex[plane].push_back(ivx);
1303 unsigned short vtxInPln = 0;
1304 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane)
1305 if (vIndex[plane].
size() > 0) ++vtxInPln;
1306 if (vtxInPln < 2)
return;
1312 <<
" thirdPlanedXCut " << thirdPlanedXCut;
1315 size_t vsize = slc.
vtxs.size();
1317 std::vector<short> vPtr(vsize, -1);
1319 std::vector<float> vX(vsize, FLT_MAX);
1321 for (
unsigned short ivx = 0; ivx < vsize; ++ivx) {
1322 if (slc.
vtxs[ivx].ID <= 0)
continue;
1324 if (slc.
vtxs[ivx].Pos[0] < -0.4)
continue;
1332 std::vector<Vtx3Store> v3temp;
1338 constexpr
float maxSep = 4;
1342 for (
unsigned short ipl = 0; ipl < 2; ++ipl) {
1343 for (
unsigned short ii = 0; ii < vIndex[ipl].size(); ++ii) {
1344 unsigned short ivx = vIndex[ipl][ii];
1345 if (vX[ivx] == FLT_MAX)
continue;
1346 auto& ivx2 = slc.
vtxs[ivx];
1347 if (ivx2.Pos[0] < -0.4)
continue;
1348 unsigned int iWire = std::nearbyint(ivx2.Pos[0]);
1349 for (
unsigned short jpl = ipl + 1; jpl < 3; ++jpl) {
1350 for (
unsigned short jj = 0; jj < vIndex[jpl].size(); ++jj) {
1351 unsigned short jvx = vIndex[jpl][jj];
1352 if (vX[jvx] == FLT_MAX)
continue;
1353 auto& jvx2 = slc.
vtxs[jvx];
1354 if (jvx2.Pos[0] < -0.4)
continue;
1355 unsigned int jWire = std::nearbyint(jvx2.Pos[0]);
1356 float dX =
std::abs(vX[ivx] - vX[jvx]);
1360 <<
"F3DV: ipl " << ipl <<
" i2V" << ivx2.ID <<
" iX " << vX[ivx] <<
" jpl " << jpl
1361 <<
" j2V" << jvx2.ID <<
" jvX " << vX[jvx] <<
" W:T " << (
int)jvx2.Pos[0] <<
":" 1362 << (
int)jvx2.Pos[1] <<
" dX " << dX;
1364 double y = -1000,
z = -1000;
1366 if (y < slc.yLo || y > slc.
yHi || z < slc.zLo || z > slc.
zHi)
continue;
1367 unsigned short kpl = 3 - ipl - jpl;
1368 float kX = 0.5 * (vX[ivx] + vX[jvx]);
1372 std::array<int, 2> wireWindow;
1373 std::array<float, 2> timeWindow;
1374 wireWindow[0] = kWire - maxSep;
1375 wireWindow[1] = kWire + maxSep;
1378 timeWindow[0] = time - maxSep;
1379 timeWindow[1] = time + maxSep;
1381 std::vector<unsigned int> closeHits =
1385 myprt <<
" Hits near " << kpl <<
":" << kWire <<
":" 1387 for (
auto iht : closeHits)
1390 if (!hitsNear)
continue;
1397 v3d.
Vx2ID[ipl] = ivx2.ID;
1398 v3d.
Vx2ID[jpl] = jvx2.ID;
1407 float vxScoreWght = 0;
1410 if (posError < 0.5) posError = 0;
1411 v3d.
Score = posError + vxScoreWght;
1414 v3temp.push_back(v3d);
1418 myprt <<
" 2 Plane match i2V";
1419 myprt << slc.
vtxs[ivx].ID <<
" P:W:T " << ipl <<
":" << (
int)slc.
vtxs[ivx].Pos[0]
1420 <<
":" << (
int)slc.
vtxs[ivx].Pos[1];
1421 myprt <<
" j2V" << slc.
vtxs[jvx].ID <<
" P:W:T " << jpl <<
":" 1422 << (
int)slc.
vtxs[jvx].Pos[0] <<
":" << (
int)slc.
vtxs[jvx].Pos[1];
1424 myprt <<
" dX " << dX <<
" posError " << posError <<
" vxScoreWght " << vxScoreWght
1425 <<
" Score " << v3d.
Score;
1428 if (slc.
nPlanes == 2)
continue;
1431 for (
unsigned short kk = 0; kk < vIndex[kpl].size(); ++kk) {
1432 unsigned short kvx = vIndex[kpl][kk];
1436 if (dX > thirdPlanedXCut)
continue;
1439 double y = -1000,
z = -1000;
1441 v3d.
YErr = y - v3d.
Y;
1450 posError = dX * dX + dY * dY + dZ * dZ;
1454 if (posError < 0.5) posError = 0;
1455 v3d.
Score = posError + vxScoreWght;
1456 if (v3d.
Score > maxScore) maxScore = v3d.
Score;
1458 mf::LogVerbatim(
"TC") <<
" k2V" << kvx + 1 <<
" dX " << dX <<
" dW " << dW
1459 <<
" 3D score " << v3d.
Score;
1460 v3temp.push_back(v3d);
1467 if (v3temp.empty())
return;
1472 for (
auto& v3 : v3temp)
1473 if (v3.Wire >= 0) v3.Score += maxScore;
1477 for (
auto& v3 : v3temp) {
1479 mf::LogVerbatim(
"TC") <<
"2V" << v3.Vx2ID[0] <<
" 2V" << v3.Vx2ID[1] <<
" wire " 1480 << v3.Wire <<
" Score " << v3.Score;
1483 mf::LogVerbatim(
"TC") <<
"2V" << v3.Vx2ID[0] <<
" 2V" << v3.Vx2ID[1] <<
" 2V" 1484 << v3.Vx2ID[2] <<
" wire " << v3.Wire <<
" Score " << v3.Score;
1489 std::vector<SortEntry> sortVec(v3temp.size());
1490 for (
unsigned short ivx = 0; ivx < v3temp.size(); ++ivx) {
1492 sEntry.
val = v3temp[ivx].Score;
1493 sortVec[ivx] = sEntry;
1495 if (sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(),
valIncreasing);
1497 std::vector<Vtx3Store> v3sel;
1498 for (
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
1499 unsigned short ivx = sortVec[ii].
index;
1501 bool skipit =
false;
1502 for (
auto& v3 : v3sel) {
1503 for (
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
1504 if (v3temp[ivx].Vx2ID[ipl] == 0)
continue;
1505 if (v3temp[ivx].Vx2ID[ipl] == v3.Vx2ID[ipl]) {
1512 if (skipit)
continue;
1513 v3sel.push_back(v3temp[ivx]);
1519 myprt <<
"v3sel list\n";
1520 for (
auto& v3d : v3sel) {
1521 for (
auto vx2id : v3d.Vx2ID)
1522 if (vx2id > 0) myprt <<
" 2V" << vx2id;
1523 myprt <<
" wire " << v3d.Wire <<
" Score " << v3d.Score;
1529 unsigned short ninc = 0;
1530 for (
auto& vx3 : v3sel) {
1531 if (slc.
nPlanes == 3 && vx3.Wire >= 0) ++ninc;
1532 vx3.ID = slc.
vtx3s.size() + 1;
1537 myprt <<
" 3V" << vx3.ID;
1538 for (
auto v2id : vx3.Vx2ID)
1539 myprt <<
" 2V" << v2id;
1540 myprt <<
" wire " << vx3.Wire;
1542 slc.
vtx3s.push_back(vx3);
1544 for (
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
1545 if (vx3.Vx2ID[ipl] == 0)
continue;
1559 for (
auto& tj : slc.
tjs) {
1562 if (planeID.
TPC != tpc || planeID.
Cryostat != cstat)
continue;
1566 for (
auto& vx2 : slc.
vtxs) {
1567 if (vx2.ID == 0)
continue;
1569 if (planeID.
TPC != tpc || planeID.
Cryostat != cstat)
continue;
1573 for (
auto& vx3 : slc.
vtx3s) {
1574 if (vx3.ID == 0)
continue;
1585 for (
unsigned short ivx = 0; ivx < slc.
vtxs.size(); ++ivx) {
1586 if (slc.
vtxs[ivx].ID == 0)
continue;
1587 if (slc.
vtxs[ivx].CTP != tp.
CTP)
continue;
1601 if (pfp.
ID <= 0)
return false;
1603 float pLen =
Length(pfp);
1604 if (pLen == 0)
return false;
1608 for (
unsigned short end = 0;
end < 2; ++
end)
1610 std::array<Point3_t, 2> endPos;
1614 std::array<float, 2> foms{{100., 100.}};
1615 std::array<int, 2> vtxs{{0}};
1616 for (
auto& vx3 : slc.
vtx3s) {
1617 if (vx3.ID <= 0)
continue;
1618 if (vx3.TPCID != pfp.
TPCID)
continue;
1619 std::array<float, 2> sep;
1620 Point3_t vpos = {{vx3.X, vx3.Y, vx3.Z}};
1621 sep[0] =
PosSep(vpos, endPos[0]);
1622 sep[1] =
PosSep(vpos, endPos[1]);
1623 unsigned short end = 0;
1624 if (sep[1] < sep[0]) end = 1;
1626 if (sep[end] > 100)
continue;
1631 float fom = dotp * sep[
end];
1633 mf::LogVerbatim(
"TC") <<
"ATAV: P" << pfp.
ID <<
" end " << end <<
" 3V" << vx3.ID <<
" sep " 1634 << sep[
end] <<
" fom " << fom <<
" maxSep " << maxSep;
1636 if (sep[end] > maxSep)
continue;
1637 if (fom < foms[end]) {
1643 for (
unsigned short end = 0;
end < 2; ++
end) {
1644 if (vtxs[
end] == 0)
continue;
1658 if (tjID <= 0 || tjID > (
int)slc.
tjs.size())
return false;
1659 if (slc.
vtxs.empty())
return false;
1660 auto& tj = slc.
tjs[tjID - 1];
1661 if (tj.AlgMod[
kKilled])
return false;
1664 unsigned short bestVx = USHRT_MAX;
1668 for (
unsigned short ivx = 0; ivx < slc.
vtxs.size(); ++ivx) {
1669 auto& vx = slc.
vtxs[ivx];
1670 if (vx.ID == 0)
continue;
1671 if (vx.CTP != tj.CTP)
continue;
1673 std::array<float, 2> sep;
1674 sep[0] =
PosSep(vx.Pos, tj.Pts[tj.EndPt[0]].Pos);
1675 sep[1] =
PosSep(vx.Pos, tj.Pts[tj.EndPt[1]].Pos);
1676 unsigned short end = 0;
1677 if (sep[1] < sep[0]) end = 1;
1678 if (sep[end] > 100)
continue;
1679 if (tj.VtxID[end] > 0)
continue;
1680 auto& tp = tj.Pts[tj.EndPt[
end]];
1683 if (fom > bestFOM)
continue;
1685 mf::LogVerbatim(
"TC") <<
"AAVTT: T" << tjID <<
" 2V" << vx.ID <<
" FOM " << fom <<
" cut " 1690 if (bestVx > slc.
vtxs.size() - 1)
return false;
1691 auto& vx = slc.
vtxs[bestVx];
1700 if (ivx > slc.
vtxs.size() - 1)
return false;
1701 if (slc.
vtxs[ivx].ID == 0)
return false;
1706 if (vx.
Topo == 5 || vx.
Topo == 6)
return false;
1708 unsigned short bestTj = USHRT_MAX;
1712 for (
unsigned int itj = 0; itj < slc.
tjs.size(); ++itj) {
1713 auto& tj = slc.
tjs[itj];
1715 if (tj.CTP != vx.
CTP)
continue;
1717 std::array<float, 2> sep;
1718 sep[0] =
PosSep(vx.
Pos, tj.Pts[tj.EndPt[0]].Pos);
1719 sep[1] =
PosSep(vx.
Pos, tj.Pts[tj.EndPt[1]].Pos);
1720 unsigned short end = 0;
1721 if (sep[1] < sep[0]) end = 1;
1722 if (sep[end] > 100)
continue;
1723 if (tj.VtxID[end] > 0)
continue;
1724 auto& tp = tj.Pts[tj.EndPt[
end]];
1727 if (fom > bestFOM)
continue;
1730 <<
" FOM " << fom <<
" cut " << bestFOM;
1735 if (bestTj > slc.
tjs.size() - 1)
return false;
1736 auto& tj = slc.
tjs[bestTj];
1756 if (tj.
CTP != vx.
CTP)
return false;
1766 unsigned short end = 0;
1769 if (sep1 < vtxTjSep2) {
1775 if (tj.
VtxID[end] > 0)
return false;
1778 bool tjShort = (tj.
EndPt[1] - tj.
EndPt[0] < maxShortTjLen);
1780 if (!tjShort && tj.
ChgRMS > 0.5) tjShort =
true;
1781 float closestApproach;
1784 if (vtxTjSep2 > maxSepCutShort2)
return false;
1789 if (vtxTjSep2 > maxSepCutLong2)
return false;
1798 unsigned short closePt;
1804 if (end == 0) { dpt = closePt - tj.
EndPt[
end]; }
1811 if (length > 4 && length < closestApproach)
return false;
1817 if (tjShort) pullCut *= 2;
1821 myprt <<
"ATTV: 2V" << vx.
ID;
1822 myprt <<
" NTraj " << vx.
NTraj;
1824 for (
unsigned short itj = 0; itj < slc.
tjs.size(); ++itj) {
1827 if (tj.
CTP != vx.
CTP)
continue;
1828 if (tj.
VtxID[0] == vx.
ID) myprt <<
" T" << tj.
ID <<
"_0";
1829 if (tj.
VtxID[1] == vx.
ID) myprt <<
" T" << tj.
ID <<
"_1";
1831 myprt <<
" + T" << tj.
ID <<
"_" << end <<
" vtxTjSep " << sqrt(vtxTjSep2) <<
" tpVxPull " 1832 << tpVxPull <<
" pullCut " << pullCut <<
" dpt " << dpt;
1834 if (tpVxPull > pullCut)
return false;
1835 if (dpt > 2)
return true;
1857 <<
" assn with kNoFitVx";
1876 double vxErrW = vx.
PosErr[0] * tp.
Dir[1];
1877 double vxErrT = vx.
PosErr[1] * tp.
Dir[0];
1878 double vxErr2 = vxErrW * vxErrW + vxErrT * vxErrT;
1884 if (sep2 < 1)
return (
float)(ip / sqrt(vxErr2));
1886 double dang = ip / sqrt(sep2);
1890 double angErr = vxErr2 / sep2;
1893 if (angErr == 0)
return 999;
1894 angErr = sqrt(angErr);
1895 return (
float)(dang / angErr);
1904 double dx = vx1.
X - vx2.
X;
1905 double dy = vx1.
Y - vx2.
Y;
1906 double dz = vx1.
Z - vx2.
Z;
1910 dx = dx * dx / dxErr2;
1911 dy = dy * dy / dyErr2;
1912 dz = dz * dz / dzErr2;
1913 return (
float)(sqrt(dx + dy + dz) / 3);
1921 double dw = vx1.
Pos[0] - vx2.
Pos[0];
1922 double dt = vx1.
Pos[1] - vx2.
Pos[1];
1925 dw = dw * dw / dwErr2;
1926 dt = dt * dt / dtErr2;
1927 return (
float)sqrt(dw + dt);
1937 if (vx.
ID !=
int(slc.
vtxs.size() + 1))
return false;
1942 unsigned short nvxtj = 0;
1943 unsigned short nok = 0;
1944 for (
auto& tj : slc.
tjs) {
1945 if (tj.AlgMod[
kKilled])
continue;
1946 if (vx.
ID == tj.VtxID[0] || vx.
ID == tj.VtxID[1]) ++nvxtj;
1947 if (vx.
CTP != tj.CTP)
continue;
1948 if (vx.
ID == tj.VtxID[0] || vx.
ID == tj.VtxID[1]) ++nok;
1953 <<
" has inconsistent CTP code " << vx.
CTP <<
" with one or more Tjs\n";
1954 for (
auto& tj : slc.
tjs) {
1955 if (tj.AlgMod[
kKilled])
continue;
1956 if (tj.VtxID[0] == vx.
ID) tj.VtxID[0] = 0;
1957 if (tj.VtxID[1] == vx.
ID) tj.VtxID[1] = 0;
1962 slc.
vtxs.push_back(vx);
1982 if (prt)
mf::LogVerbatim(
"TC") <<
" vertex position fixed. No fit allowed";
1987 std::vector<TrajPoint> vxTp;
1988 for (
auto& tj : slc.
tjs) {
1990 if (tj.CTP != vx.
CTP)
continue;
1991 if (tj.AlgMod[
kPhoton])
continue;
1993 if (tj.VtxID[0] == vx.
ID && !tj.EndFlag[0][
kNoFitVx]) {
1994 vxTp.push_back(tj.Pts[tj.EndPt[0]]);
1997 if (tj.VtxID[1] == vx.
ID && !tj.EndFlag[1][
kNoFitVx]) {
1998 vxTp.push_back(tj.Pts[tj.EndPt[1]]);
2003 auto& tp = vxTp[vxTp.size() - 1];
2004 if (tj.ID > 0) tp.Step = (
int)tj.ID;
2006 if (tp.NTPsFit < 4) tp.AngErr *= 4;
2010 bool success =
FitVertex(slc, vx, vxTp, prt);
2012 if (!success)
return false;
2027 if (vxTPs.size() < 2)
return false;
2028 if (vxTPs.size() == 2) {
2033 unsigned short npts = vxTPs.size();
2034 TMatrixD
A(npts, 2);
2036 for (
unsigned short itj = 0; itj < vxTPs.size(); ++itj) {
2037 auto& tp = vxTPs[itj];
2038 double dtdw = tp.Dir[1] / tp.Dir[0];
2039 double wt = 1 / (tp.AngErr * tp.AngErr);
2040 A(itj, 0) = -dtdw * wt;
2041 A(itj, 1) = 1. * wt;
2042 b(itj) = (tp.Pos[1] - tp.Pos[0] * dtdw) * wt;
2045 TMatrixD AT(2, npts);
2047 TMatrixD ATA = AT *
A;
2055 if (det == NULL)
return false;
2056 TVectorD vxPos = ATA * AT *
b;
2057 vx.
PosErr[0] = sqrt(ATA[0][0]);
2058 vx.
PosErr[1] = sqrt(ATA[1][1]);
2059 vx.
Pos[0] = vxPos[0];
2060 vx.
Pos[1] = vxPos[1];
2064 if (vxTPs.size() > 2) {
2065 for (
auto& tp : vxTPs) {
2076 for (
auto& tp : vxTPs)
2077 PrintTP(
"FV", slc, 0, 1, 1, tp);
2091 unsigned short plane = planeID.
Plane;
2092 for (
auto& vx2 : slc.
vtxs) {
2093 if (vx2.CTP != inCTP)
continue;
2094 if (vx2.ID == 0)
continue;
2095 if (vx2.Vx3ID == 0)
continue;
2096 if (vx2.Vx3ID >
int(slc.
vtx3s.size())) {
2097 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: Invalid vx2.Vx3ID " << vx2.Vx3ID
2098 <<
" in 2D vtx " << vx2.ID;
2101 auto& vx3 = slc.
vtx3s[vx2.Vx3ID - 1];
2103 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: 2V" << vx2.ID <<
" thinks it is matched to 3V" 2104 << vx3.ID <<
" but vx3 is obsolete";
2107 if (vx3.Vx2ID[plane] != vx2.ID) {
2108 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: 2V" << vx2.ID <<
" thinks it is matched to 3V" 2109 << vx3.ID <<
" but vx3 says no!";
2114 for (
auto& vx3 : slc.
vtx3s) {
2115 if (vx3.ID == 0)
continue;
2116 if (vx3.Vx2ID[plane] == 0)
continue;
2117 if (vx3.Vx2ID[plane] > (
int)slc.
vtxs.size()) {
2118 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: Invalid vx3.Vx2ID " << vx3.Vx2ID[plane]
2119 <<
" in CTP " << inCTP;
2122 auto& vx2 = slc.
vtxs[vx3.Vx2ID[plane] - 1];
2123 if (vx2.Vx3ID != vx3.ID) {
2124 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: 3V" << vx3.ID <<
" thinks it is matched to 2V" 2125 << vx2.ID <<
" but vx2 says no!";
2131 for (
auto& tj : slc.
tjs) {
2133 for (
unsigned short end = 0;
end < 2; ++
end) {
2134 if (tj.VtxID[
end] == 0)
continue;
2135 if (tj.VtxID[
end] > slc.
vtxs.size()) {
2136 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: T" << tj.ID <<
" thinks it is matched to 2V" 2137 << tj.VtxID[
end] <<
" on end " <<
end 2138 <<
" but no vertex exists. Recovering";
2142 unsigned short ivx = tj.VtxID[
end] - 1;
2143 auto& vx2 = slc.
vtxs[ivx];
2145 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: T" << tj.ID <<
" thinks it is matched to 2V" 2146 << tj.VtxID[
end] <<
" on end " <<
end 2147 <<
" but the vertex is killed. Fixing the Tj";
2165 for (
auto& vx : slc.
vtxs) {
2166 if (vx.ID == 0)
continue;
2170 for (
auto& tj : slc.
tjs) {
2175 for (
auto& vx : slc.
vtxs) {
2176 if (vx.ID == 0)
continue;
2180 for (
auto& vx3 : slc.
vtx3s) {
2181 if (vx3.ID == 0)
continue;
2191 if (slc.
vtxs.empty())
return;
2192 for (
auto& vx : slc.
vtxs) {
2193 if (vx.ID == 0)
continue;
2196 auto& vx3 = slc.
vtx3s[vx.Vx3ID - 1];
2197 if (vx3.Primary)
continue;
2211 if (vx3.
ID == 0)
return;
2213 for (
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
2214 if (vx3.
Vx2ID[ipl] <= 0)
continue;
2219 std::vector<int> vxlist;
2224 for (
auto tjid : tjlist) {
2225 auto& tj = slc.
tjs[tjid - 1];
2227 for (
unsigned short end = 0;
end < 2; ++
end) {
2228 if (tj.VtxID[
end] == 0)
continue;
2229 auto& vx2 = slc.
vtxs[tj.VtxID[
end] - 1];
2232 vxlist.push_back(vx2.
ID);
2236 if (vxlist.empty())
break;
2238 std::vector<int> newtjlist;
2239 for (
auto vxid : vxlist) {
2240 auto& vx2 = slc.
vtxs[vxid - 1];
2242 for (
auto tjid :
tmp) {
2243 if (std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end())
2244 newtjlist.push_back(tjid);
2247 if (newtjlist.empty())
break;
2261 if (vx3.
ID == 0)
return;
2264 for (
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
2265 if (vx3.
Vx2ID[ipl] <= 0)
continue;
2281 if (slc.
vtxs.empty())
return;
2282 auto& vx2 = slc.
vtxs[slc.
vtxs.size() - 1];
2291 if (vx2.
ID == 0)
return;
2302 constexpr
float maxChgRMS = 0.25;
2303 constexpr
float momBin = 50;
2307 if (vx2.
ID == 0)
return;
2311 if (vtxTjIDs.empty())
return;
2316 unsigned short m3Dcnt = 0;
2317 if (vx2.
Vx3ID > 0) {
2320 unsigned short ivx3 = vx2.
Vx3ID - 1;
2321 if (slc.
vtx3s[ivx3].Wire < 0) m3Dcnt = 2;
2329 std::vector<int> tjids;
2330 std::vector<float> tjwts;
2331 unsigned short cnt13 = 0;
2332 for (
auto tjid : vtxTjIDs) {
2336 unsigned short lenth = tj.
EndPt[1] - tj.
EndPt[0] + 1;
2337 if (lenth < 3)
continue;
2342 if (cnt13 == 1) wght *= 2;
2345 if (tj.
ChgRMS < maxChgRMS) ++wght;
2350 tjids.push_back(tjid);
2351 tjwts.push_back(wght);
2354 if (tjids.empty())
return;
2359 for (
unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
2361 float wght1 = tjwts[it1];
2363 unsigned short end1 = 0;
2364 if (tj1.
VtxID[1] == vx2.
ID) end1 = 1;
2365 unsigned short endPt1 = tj1.
EndPt[end1];
2367 unsigned short oend1 = 1 - end1;
2369 float ang1 = tj1.
Pts[endPt1].Ang;
2370 float ang1Err2 = tj1.
Pts[endPt1].AngErr * tj1.
Pts[endPt1].AngErr;
2371 for (
unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
2373 float wght2 = tjwts[it2];
2375 if (tj2.
VtxID[1] == vx2.
ID) end2 = 1;
2377 unsigned short oend2 = 1 - end2;
2378 if (tj2.
EndFlag[oend2][kBragg]) ++wght2;
2379 unsigned short endPt2 = tj2.
EndPt[end2];
2380 float ang2 = tj2.
Pts[endPt2].Ang;
2381 float ang2Err2 = tj2.
Pts[endPt2].AngErr * tj2.
Pts[endPt2].AngErr;
2383 float dangErr = 0.5 * sqrt(ang1Err2 + ang2Err2);
2384 if ((dang / dangErr) > 3 && wght1 > 0 && wght2 > 0) {
2385 sum += wght1 + wght2;
2394 vx2.
Score = vpeScore + m3DScore + cfScore + tjScore;
2399 bool printHeader =
true;
2400 Print2V(
"SVx2S", myprt, vx2, printHeader);
2402 myprt <<
" vpeScore " << vpeScore <<
" m3DScore " << m3DScore;
2403 myprt <<
" cfScore " << cfScore <<
" tjScore " << tjScore;
2404 myprt <<
" Score " << vx2.
Score;
2419 for (
unsigned short iv3 = 0; iv3 < slc.
vtx3s.size(); ++iv3) {
2422 if (vx3.
ID == 0)
continue;
2424 if (vx3.
Wire < 0)
continue;
2425 unsigned short mPlane = USHRT_MAX;
2426 for (
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
2427 if (vx3.
Vx2ID[ipl] > 0)
continue;
2431 if (mPlane == USHRT_MAX)
continue;
2435 if (dwc < 5)
continue;
2438 aVtx.
ID = slc.
vtxs.size() + 1;
2448 mf::LogVerbatim(
"TC") <<
"CI3DVIG: Incomplete vertex " << iv3 <<
" in plane " << mPlane
2449 <<
" wire " << vx3.
Wire <<
" Made 2D vertex ";
2450 std::vector<int> tjIDs;
2451 std::vector<unsigned short> tjEnds;
2452 for (
unsigned short itj = 0; itj < slc.
tjs.size(); ++itj) {
2453 if (slc.
tjs[itj].CTP != mCTP)
continue;
2455 for (
unsigned short end = 0;
end < 2; ++
end) {
2456 unsigned short ept = slc.
tjs[itj].EndPt[
end];
2458 unsigned short oept = slc.
tjs[itj].EndPt[1 -
end];
2463 if (doca > 2)
continue;
2466 if (aVtx.
Pos[0] > tp.
Pos[0]) { ptSep = aVtx.
Pos[0] - tp.
Pos[0] - dwc; }
2468 ptSep = tp.
Pos[0] - aVtx.
Pos[0] - dwc;
2472 <<
" ptSep " << ptSep;
2473 if (ptSep < -2 || ptSep > 2)
continue;
2475 if (slc.
tjs[itj].VtxID[
end] > 0)
continue;
2476 tjIDs.push_back(slc.
tjs[itj].ID);
2477 tjEnds.push_back(
end);
2480 if (!tjIDs.empty()) {
2487 for (
unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2488 unsigned short itj = tjIDs[ii] - 1;
2489 slc.
tjs[itj].VtxID[tjEnds[ii]] = aVtx.
ID;
2516 if (prt)
mf::LogVerbatim(
"TC") <<
"Inside CI3DV with maxdoca set to " << maxdoca;
2517 unsigned short ivx3 = 0;
2518 for (
auto& vx3 : slc.
vtx3s) {
2520 if (vx3.ID == 0)
continue;
2522 if (vx3.Wire < 0)
continue;
2523 unsigned short mPlane = USHRT_MAX;
2525 bool indPlnNoChgVtx =
false;
2526 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
2527 if (vx3.Vx2ID[plane] > 0) {
2528 auto& vx2 = slc.
vtxs[vx3.Vx2ID[plane] - 1];
2534 if (mPlane == USHRT_MAX)
continue;
2535 if (indPlnNoChgVtx)
continue;
2536 CTP_t mCTP =
EncodeCTP(vx3.TPCID.Cryostat, vx3.TPCID.TPC, mPlane);
2540 vtp.
Pos[0] = vx3.Wire;
2541 vtp.
Pos[1] = detProp.
ConvertXToTicks(vx3.X, mPlane, vx3.TPCID.TPC, vx3.TPCID.Cryostat) *
2544 mf::LogVerbatim(
"TC") <<
"CI3DV 3V" << vx3.ID <<
" Pos " << mPlane <<
":" 2546 std::vector<int> tjIDs;
2547 std::vector<unsigned short> tjPts;
2548 for (
auto& tj : slc.
tjs) {
2549 if (tj.CTP != mCTP)
continue;
2551 if (tj.Pts.size() < 6)
continue;
2553 float doca = maxdoca;
2555 unsigned short closePt = 0;
2557 if (closePt > tj.EndPt[1])
continue;
2562 mf::LogVerbatim(
"TC") <<
"CI3DV 3V" << vx3.ID <<
" candidate T" << tj.ID <<
" vtx pos " 2563 <<
PrintPos(slc, vtp.
Pos) <<
" doca " << doca <<
" closePt " 2565 tjIDs.push_back(tj.ID);
2566 tjPts.push_back(closePt);
2568 if (tjIDs.empty())
continue;
2572 auto vxtjs =
GetAssns(slc,
"3V", vx3.
ID,
"T");
2573 unsigned short maxPts = 0;
2574 unsigned short minPts = USHRT_MAX;
2575 for (
auto tjid : vxtjs) {
2576 auto& tj = slc.
tjs[tjid - 1];
2578 if (npwc > maxPts) maxPts = npwc;
2579 if (npwc < minPts) minPts = npwc;
2583 bool skipit =
false;
2584 for (
auto tjid : tjIDs) {
2585 auto& tj = slc.
tjs[tjid - 1];
2589 mf::LogVerbatim(
"TC") <<
" maxPts " << maxPts <<
" skipit? " << skipit <<
" minPts " 2591 if (skipit)
continue;
2594 unsigned short newVtxIndx = slc.
vtxs.size();
2595 aVtx.
ID = newVtxIndx + 1;
2613 std::array<float, 2> vpos = aVtx.
Pos;
2614 for (
unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2615 unsigned short itj = tjIDs[ii] - 1;
2616 unsigned short closePt = tjPts[ii];
2618 unsigned short end = 1;
2620 if (fabs(closePt - slc.
tjs[itj].EndPt[0]) < fabs(closePt - slc.
tjs[itj].EndPt[1])) end = 0;
2621 short dpt = fabs(closePt - slc.
tjs[itj].EndPt[end]);
2625 if (slc.
tjs[itj].VtxID[end] > 0) {
2627 auto& oldTj = slc.
tjs[itj];
2628 auto& oldVx = slc.
vtxs[oldTj.VtxID[
end] - 1];
2629 short oldSep = fabs(oldVx.Pos[0] - oldTj.Pts[oldTj.EndPt[end]].Pos[0]);
2632 <<
" T" << slc.
tjs[itj].ID <<
" has vertex 2V" << slc.
tjs[itj].VtxID[
end]
2633 <<
" at end " << end <<
". oldSep " << oldSep;
2639 slc.
tjs[itj].VtxID[
end] = slc.
vtxs[newVtxIndx].ID;
2644 vpos = slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[
end]].Pos;
2648 if (
SplitTraj(slc, itj, closePt, newVtxIndx, prt)) {
2651 <<
" SplitTraj success 2V" << slc.
vtxs[newVtxIndx].ID <<
" at closePt " << closePt;
2667 unsigned short newtj = slc.
tjs.size() - 1;
2670 if (newVtx.
NTraj == 0) {
2672 if (prt)
mf::LogVerbatim(
"TC") <<
" Failed. Recover and delete vertex " << newVtx.
ID;
2677 vx3.Vx2ID[mPlane] = newVtx.
ID;
2678 newVtx.
Vx3ID = vx3.ID;
2681 if (newVtx.
NTraj == 1) {
2689 myprt <<
" Success: new 2V" << newVtx.
ID <<
" at " << (
int)newVtx.
Pos[0] <<
":" 2691 myprt <<
" points to 3V" << vx3.ID;
2693 for (
auto& tjID : tjIDs)
2706 unsigned short& nearPt,
2713 float maxChg = tj.
Pts[nearPt].Chg;
2714 short maxChgPt = nearPt;
2715 unsigned short fromPt = tj.
EndPt[0];
2716 short spt = (short)nearPt - (
short)nPtsToChk;
2717 if (spt > (
short)fromPt) fromPt = nearPt - nPtsToChk;
2718 unsigned short toPt = nearPt + nPtsToChk;
2721 for (
short ipt = fromPt; ipt <= toPt; ++ipt) {
2722 if (ipt < tj.
EndPt[0] || ipt > tj.
EndPt[1])
continue;
2723 auto& tp = tj.
Pts[ipt];
2724 if (tp.Chg > maxChg) {
2729 mf::LogVerbatim(
"TC") <<
"RVP: ipt " << ipt <<
" Pos " << tp.CTP <<
":" 2730 <<
PrintPos(slc, tp.Pos) <<
" chg " << (
int)tp.Chg <<
" nhits " 2733 if (nearPt == maxChgPt)
return false;
2745 bool hasHighScoreVx3 = (vx2.
Vx3ID > 0);
2755 if (vx2.
Vx3ID > 0) {
2757 for (
auto& v3v2id : vx3.Vx2ID)
2758 if (v3v2id == vx2.
ID) v3v2id = 0;
2761 for (
auto& tj : slc.
tjs) {
2763 for (
unsigned short end = 0;
end < 2; ++
end) {
2764 if (tj.VtxID[
end] != vx2id)
continue;
2768 for (
unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
2770 unsigned short ipt = tj.EndPt[0] + ii;
2771 auto& tp = tj.Pts[ipt];
2773 if (ipt == tj.EndPt[1])
break;
2776 unsigned short ipt = tj.EndPt[1] - ii;
2777 auto& tp = tj.Pts[ipt];
2779 if (ipt == tj.EndPt[0])
break;
2784 unsigned short oend = 1 -
end;
2785 if (tj.VtxID[oend] > 0) {
2786 auto& ovx2 = slc.
vtxs[tj.VtxID[oend] - 1];
2793 if (!hasHighScoreVx3)
return true;
2799 unsigned short plane = planeID.
Plane;
2800 if (vx3.
Vx2ID[plane] != vx2id)
return true;
2801 vx3.
Vx2ID[plane] = 0;
2804 unsigned short n2D = 0;
2805 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane)
2806 if (vx3.
Vx2ID[plane] > 0) ++n2D;
2817 for (
auto& vx2 : slc.
vtxs) {
2818 if (vx2.
ID == 0)
continue;
2821 for (
auto& pfp : slc.
pfps) {
2822 for (
unsigned short end = 0;
end < 2; ++
end)
2823 if (pfp.Vx3ID[
end] == vx3.
ID) pfp.Vx3ID[
end] = 0;
2837 if (vx3.
ID <= 0)
return true;
2838 if (vx3.
ID >
int(slc.
vtx3s.size()))
return false;
2840 for (
auto vx2id : vx3.
Vx2ID) {
2841 if (vx2id == 0 || vx2id > (
int)slc.
vtxs.size())
continue;
2842 auto& vx2 = slc.
vtxs[vx2id - 1];
2854 std::vector<int>
tmp;
2855 if (vx2.
ID == 0)
return tmp;
2856 for (
auto& tj : slc.
tjs) {
2857 if (tj.AlgMod[
kKilled])
continue;
2858 if (tj.CTP != vx2.
CTP)
continue;
2859 for (
unsigned short end = 0;
end < 2; ++
end) {
2860 if (tj.VtxID[
end] == vx2.
ID) tmp.push_back(tj.ID);
2871 std::vector<int>
tmp;
2872 if (vx3.
ID == 0)
return tmp;
2875 for (
auto& vx2 : slc.
vtxs) {
2876 if (vx2.ID == 0)
continue;
2877 if (vx2.Vx3ID != vx3.
ID)
continue;
2879 tmp.insert(tmp.end(), vtxTjID2.begin(), vtxTjID2.end());
2883 if (nvx2 < 1)
return tmp;
2887 std::sort(tmp.begin(), tmp.end());
2896 unsigned short plane,
2913 unsigned short imBest = 0;
2914 for (
auto& vx2 : slc.
vtxs) {
2915 if (vx2.CTP != inVx2.
CTP)
continue;
2916 if (vx2.ID <= 0)
continue;
2918 if (pull < minPull) {
2933 unsigned short imBest = 0;
2934 for (
auto& oldvx3 : slc.
vtx3s) {
2935 if (oldvx3.ID == 0)
continue;
2938 if (pull < minPull) {
Expect tracks entering from the front face. Don't create neutrino PFParticles.
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
bool valDecreasing(SortEntry c1, SortEntry c2)
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
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
unsigned short FarEnd(const TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
float Length(const PFPStruct &pfp)
bool MergeWithVertex(TCSlice &slc, VtxStore &vx, unsigned short oVxID)
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
unsigned short CloseEnd(const TCSlice &slc, const Trajectory &tj, const Point2_t &pos)
struct of temporary 2D vertices (end points)
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
static unsigned int kWire
float TrajPointVertexPull(const TCSlice &slc, const TrajPoint &tp, const VtxStore &vx)
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)
void Print2V(std::string someText, mf::LogVerbatim &myprt, VtxStore &vx2, bool &printHeader)
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.
bool valIncreasing(SortEntry c1, SortEntry c2)
matched to a high-score 3D vertex
step from US -> DS (true) or DS -> US (false)
short MCSMom
Normalized RMS using ALL hits. Assume it is 50% to start.
bool RefineVtxPosition(TCSlice &slc, const Trajectory &tj, unsigned short &nearPt, short nPtsToChk, bool prt)
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
CryostatID_t Cryostat
Index of cryostat.
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
void PosInPlane(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const Vtx3Store &vx3, unsigned short plane, Point2_t &pos)
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
std::array< int, 2 > Vx3ID
void SetVx3Score(TCSlice &slc, Vtx3Store &vx3)
tick ticks
Alias for common language habits.
void CompleteIncomplete3DVertices(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc)
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Q_EXPORT QTSManip setprecision(int p)
bool dbg3V
debug 3D vertex finding
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
int close(int)
Closes the file descriptor fd.
struct of temporary 3D vertices
void PrintAllTraj(detinfo::DetectorPropertiesData const &detProp, std::string someText, TCSlice &slc, unsigned short itj, unsigned short ipt, bool prtVtx)
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)
unsigned short NearbyCleanPt(const TCSlice &slc, const Trajectory &tj, unsigned short end)
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
CTP_t CTP
Cryostat, TPC, Plane code.
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)
void TrajPointTrajDOCA(const TCSlice &slc, TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
const geo::GeometryCore * geom
PlaneID_t Plane
Index of the plane within its TPC.
unsigned short NearestPtWithChg(const TCSlice &slc, const Trajectory &tj, unsigned short thePt)
bool IntersectionPoint(geo::WireID const &wid1, geo::WireID const &wid2, double &y, double &z) const
Returns the intersection point of two wires.
Definition of data types for geometry description.
void err(const char *fmt,...)
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 IsCloseToVertex(const TCSlice &slc, const VtxStore &inVx2)
float VertexVertexPull(const TCSlice &slc, const Vtx3Store &vx1, const Vtx3Store &vx2)
std::bitset< 16 > Stat
Vertex status bits using kVtxBit_t.
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.
for(std::string line;std::getline(inFile, line);)
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...)
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)
Access the description of detector geometry.
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)
bool SignalBetween(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction)
void MoveTPToWire(TrajPoint &tp, float wire)
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
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.
master switch for turning on debug mode
std::string to_string(ModuleType const mt)
bool AttachToAnyVertex(TCSlice &slc, PFPStruct &pfp, float maxSep, bool prt)
void PrintTPHeader(std::string someText)
CTP_t CTP
set to an invalid CTP