28 using namespace detail;
39 if (slc.
tjs.size() < 2)
return;
42 constexpr
float maxSep = 4;
48 <<
" maxSep btw tjs " << maxSep;
58 junkVx.
ID = USHRT_MAX;
60 junkVx.
PosErr = {{2.0, 2.0}};
65 for (
unsigned short it1 = 0; it1 < slc.
tjs.size() - 1; ++it1) {
66 auto& tj1 = slc.
tjs[it1];
68 if (tj1.SSID > 0 || tj1.AlgMod[
kShowerLike])
continue;
69 if (tj1.CTP != inCTP)
continue;
70 if (tj1.AlgMod[
kJunkTj])
continue;
72 if (tj1.MCSMom < 100)
continue;
73 for (
unsigned short end1 = 0; end1 < 2; ++end1) {
75 if (tj1.VtxID[end1] > 0)
continue;
76 auto& tp1 = tj1.Pts[tj1.EndPt[end1]];
79 if (tjlist.empty())
continue;
81 junkVx.
ID = USHRT_MAX;
82 for (
auto tj2id : tjlist) {
83 auto& tj2 = slc.
tjs[tj2id - 1];
84 if (tj2.CTP != inCTP)
continue;
85 if (tj2id == tj1.ID)
continue;
86 if (tj2.SSID > 0 || tj2.AlgMod[
kShowerLike])
continue;
88 unsigned short closeEnd = USHRT_MAX;
89 for (
unsigned short end2 = 0; end2 < 2; ++end2) {
90 auto& tp2 = tj2.Pts[tj2.EndPt[end2]];
91 float sep =
PosSep(tp1.Pos, tp2.Pos);
97 if (closeEnd > 1)
continue;
98 auto& tp2 = tj2.Pts[tj2.EndPt[closeEnd]];
100 if (!signalBetween)
continue;
101 if (junkVx.
ID == USHRT_MAX) {
103 junkVx.
ID = slc.
vtxs.size() + 1;
104 junkVx.
Pos = tp1.Pos;
106 tj2.VtxID[closeEnd] = junkVx.
ID;
107 tj1.VtxID[end1] = junkVx.
ID;
109 if (junkVx.
ID == USHRT_MAX)
continue;
112 for (
auto& tj : slc.
tjs) {
113 if (tj.AlgMod[
kKilled])
continue;
114 if (tj.VtxID[0] == junkVx.
ID) tj.VtxID[0] = 0;
115 if (tj.VtxID[1] == junkVx.
ID) tj.VtxID[1] = 0;
121 << std::setprecision(1) << junkVx.
Pos[0] <<
":" 124 junkVx.
ID = USHRT_MAX;
155 if (slc.
tjs.size() < 2)
return;
157 bool firstPassCuts = (pass == 0);
162 bool requireVtxTjChg =
true;
167 mf::LogVerbatim(
"TC") <<
"prt set for CTP " << inCTP <<
" in Find2DVertices. firstPassCuts? " 168 << firstPassCuts <<
" requireVtxTjChg " << requireVtxTjChg;
173 for (
unsigned short it1 = 0; it1 < slc.
tjs.size() - 1; ++it1) {
174 auto& tj1 = slc.
tjs[it1];
176 if (tj1.SSID > 0 || tj1.AlgMod[
kShowerLike])
continue;
177 if (tj1.CTP != inCTP)
continue;
178 bool tj1Short = (
TrajLength(tj1) < maxShortTjLen);
179 for (
unsigned short end1 = 0; end1 < 2; ++end1) {
181 if (tj1.VtxID[end1] > 0)
continue;
183 if (tj1.PDGCode == 111 && end1 != tj1.StartEnd)
continue;
186 short endPt1 = tj1.EndPt[end1];
187 float wire1 = tj1.Pts[endPt1].Pos[0];
191 if (tj1.Pts.size() > 6 && tj1.Pts[endPt1].NTPsFit < 4) {
192 if (end1 == 0 && endPt1 <
int(tj1.Pts.size()) - 3) { endPt1 += 3; }
193 else if (end1 == 1 && endPt1 >= 3) {
202 endPt1 = tj1.EndPt[end1];
203 short oendPt1 = tj1.EndPt[1 - end1];
205 auto& otp1 = tj1.Pts[oendPt1];
206 for (
unsigned short it2 = it1 + 1; it2 < slc.
tjs.size(); ++it2) {
207 auto& tj2 = slc.
tjs[it2];
209 if (tj2.SSID > 0 || tj2.AlgMod[
kShowerLike])
continue;
210 if (tj2.CTP != inCTP)
continue;
211 if (tj1.VtxID[end1] > 0)
continue;
213 bool tj2Short = (
TrajLength(tj2) < maxShortTjLen);
215 unsigned short end2 = 0;
216 if (
PosSep2(tj2.Pts[tj2.EndPt[1]].Pos, tp1.
Pos) <
219 if (tj2.VtxID[end2] > 0)
continue;
221 if (tj2.PDGCode == 111 && end2 != tj2.StartEnd)
continue;
223 if (tj1.VtxID[1 - end1] > 0 && tj1.VtxID[1 - end1] == tj2.VtxID[1 - end2])
continue;
225 unsigned short oendPt2 = tj2.EndPt[1 - end2];
226 auto& otp2 = tj2.Pts[oendPt2];
227 if (
PosSep2(otp1.Pos, otp2.Pos) <
PosSep2(tp1.
Pos, tj2.Pts[tj2.EndPt[end2]].Pos))
229 short endPt2 = tj2.EndPt[end2];
230 float wire2 = tj2.Pts[endPt2].Pos[0];
231 if (tj2.Pts.size() > 6 && tj2.Pts[endPt2].NTPsFit < 4) {
232 if (end2 == 0 && endPt2 <
int(tj2.Pts.size()) - 3) { endPt2 += 3; }
233 else if (end2 == 1 && endPt2 >= 3) {
241 endPt2 = tj2.EndPt[end2];
253 if (tj1Short || tj2Short) { sepCut =
tcc.
vtx2DCuts[1]; }
267 if (prt && vt1Sep < 200 && vt2Sep < 200) {
269 myprt <<
"F2DV candidate T" << tj1.ID <<
"_" << end1 <<
"-T" << tj2.ID <<
"_" << end2;
270 myprt <<
" vtx pos " << (int)wint <<
":" << (
int)(tint /
tcc.
unitsPerTick) <<
" tp1 " 272 myprt <<
" dwc1 " << dwc1 <<
" dwc2 " << dwc2 <<
" on dead wire? " << vtxOnDeadWire;
273 myprt <<
" vt1Sep " << vt1Sep <<
" vt2Sep " << vt2Sep <<
" sepCut " << sepCut;
275 if (vt1Sep > sepCut || vt2Sep > sepCut)
continue;
277 if (
PosSep(vPos, slc.
tjs[it1].Pts[oendPt1].Pos) < vt1Sep) {
280 <<
" tj1 other end " <<
PrintPos(tj1.Pts[oendPt1]) <<
" is closer to the vertex";
283 if (
PosSep(vPos, slc.
tjs[it2].Pts[oendPt2].Pos) < vt2Sep) {
286 <<
" tj2 other end " <<
PrintPos(tj2.Pts[oendPt2]) <<
" is closer to the vertex";
290 unsigned short closePt1;
291 float doca1 = sepCut;
296 short dpt1 = stepDir * (closePt1 - endPt1);
298 mf::LogVerbatim(
"TC") <<
" endPt1 " << endPt1 <<
" closePt1 " << closePt1 <<
" dpt1 " 299 << dpt1 <<
" doca1 " << doca1;
300 if (dpt1 < -1)
continue;
301 if (slc.
tjs[it1].EndPt[1] > 4) {
302 if (dpt1 > 3)
continue;
306 if (dpt1 > 2)
continue;
308 unsigned short closePt2;
309 float doca2 = sepCut;
311 short dpt2 = stepDir * (closePt2 - endPt2);
313 mf::LogVerbatim(
"TC") <<
" endPt2 " << endPt2 <<
" closePt2 " << closePt2 <<
" dpt2 " 314 << dpt2 <<
" doca2 " << doca2;
315 if (dpt2 < -1)
continue;
316 if (slc.
tjs[it2].EndPt[1] > 4) {
317 if (dpt2 > 3)
continue;
321 if (dpt2 > 2)
continue;
323 bool fixVxPos =
false;
325 if (tj1.EndFlag[end1][
kAtKink]) fixVxPos =
true;
329 if (requireVtxTjChg) {
331 bool signalBetween =
true;
332 short dpt =
abs(wint - tp1.
Pos[0]);
334 if (prt)
mf::LogVerbatim(
"TC") <<
" Fails SignalBetween for tp1 " << dpt;
335 signalBetween =
false;
337 dpt =
abs(wint - tp2.
Pos[0]);
339 if (prt)
mf::LogVerbatim(
"TC") <<
" Fails SignalBetween for tp2 " << dpt;
340 signalBetween =
false;
344 if (!signalBetween) {
345 unsigned short ipt1, ipt2;
347 bool isClose =
TrajTrajDOCA(slc, tj1, tj2, ipt1, ipt2, maxSep,
false);
349 if (isClose) isClose = (
abs(ipt1 - endPt1) < 4 &&
abs(ipt2 - endPt2) < 4);
353 <<
" TrajTrajDOCA are close with minSep " << maxSep <<
" near " 368 <<
" new wint:tint " << (int)wint <<
":" << (
int)(tint /
tcc.
unitsPerTick);
381 aVtx.
Pass = tj1.Pass;
383 aVtx.
Topo = 2 * end1;
392 unsigned short newVtxID = slc.
vtxs.size() + 1;
394 tj1.VtxID[end1] = newVtxID;
395 tj2.VtxID[end2] = newVtxID;
404 if (prt)
mf::LogVerbatim(
"TC") <<
" Merged with close vertex " << mergeMeWithVx;
411 myprt <<
" New vtx 2V" << aVtx.
ID;
412 myprt <<
" Tjs " << tj1.ID <<
"_" << end1 <<
"-" << tj2.ID <<
"_" << end2;
413 myprt <<
" at " << std::fixed << std::setprecision(1) << aVtx.
Pos[0] <<
":" 423 if (pass == USHRT_MAX) {
428 if (prt)
PrintAllTraj(detProp,
"F2DVo", slc, USHRT_MAX, USHRT_MAX);
445 if (oVxID > slc.
vtxs.size())
return false;
446 auto& oVx = slc.
vtxs[oVxID - 1];
447 if (vx.
CTP != oVx.CTP)
return false;
451 if (tjlist.empty())
return false;
453 if (tmp.empty())
return false;
454 for (
auto tjid : tmp) {
455 if (std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end()) tjlist.push_back(tjid);
457 if (tjlist.size() < 2)
return false;
459 if (tjlist.size() == 2) {
464 for (
auto tjid : tjlist) {
465 auto& tj = slc.
tjs[tjid - 1];
466 for (
unsigned short end = 0;
end < 2; ++
end) {
467 if (tj.VtxID[
end] == vx.
ID) tj.VtxID[
end] = oVx.ID;
472 mf::LogVerbatim(
"TC") <<
"MWV: merge failed " << vx.
ID <<
" and existing " << oVx.ID;
479 std::vector<SortEntry> sortVec(tjlist.size());
480 for (
unsigned int indx = 0; indx < sortVec.size(); ++indx) {
481 sortVec[indx].index = indx;
482 auto& tj = slc.
tjs[tjlist[indx] - 1];
483 sortVec[indx].val = tj.Pts.size();
488 for (
unsigned short ii = 0; ii < sortVec.size(); ++ii)
489 tjlist[ii] = ttl[sortVec[ii].index];
494 std::vector<TrajPoint> tjpts(tjlist.size());
498 std::array<float, 2> vpos;
499 vpos[0] = 0.5 * (vx.
Pos[0] + oVx.Pos[0]);
500 vpos[1] = 0.5 * (vx.
Pos[1] + oVx.Pos[1]);
501 for (
unsigned short ii = 0; ii < tjpts.size(); ++ii) {
502 auto& tj = slc.
tjs[tjlist[ii] - 1];
506 unsigned short endPt = tj.EndPt[
end];
507 if (npwc > 6 && tj.Pts[endPt].NTPsFit < 4) {
508 if (end == 0) { endPt += 3; }
514 if (endPt < tj.EndPt[0]) endPt = tj.EndPt[0];
515 if (endPt > tj.EndPt[1]) endPt = tj.EndPt[1];
517 tjpts[ii].CTP = tj.CTP;
518 tjpts[ii].Pos = tj.Pts[endPt].Pos;
519 tjpts[ii].Dir = tj.Pts[endPt].Dir;
520 tjpts[ii].Ang = tj.Pts[endPt].Ang;
521 tjpts[ii].AngErr = tj.Pts[endPt].AngErr;
523 tjpts[ii].Step = endPt;
525 tjpts[ii].AngleCode =
end;
527 tjpts[ii].Hits.resize(1, tj.ID);
531 myprt <<
"MWV: " << oVxID;
533 for (
unsigned short ii = 0; ii < tjpts.size(); ++ii) {
534 auto& tjpt = tjpts[ii];
535 myprt <<
" " << tjlist[ii] <<
"_" << tjpt.Step <<
"_" <<
PrintPos(tjpt.Pos);
546 bool needsUpdate =
false;
547 for (
unsigned short ii = 2; ii < tjlist.size(); ++ii) {
548 fitpts.push_back(tjpts[ii]);
549 if (
FitVertex(slc, aVx, fitpts, prt)) { needsUpdate =
false; }
557 if (needsUpdate)
FitVertex(slc, aVx, fitpts, prt);
558 if (prt)
mf::LogVerbatim(
"TC") <<
"MWV: done " << vx.
ID <<
" and existing " << oVx.ID;
561 for (
auto& tj : slc.
tjs) {
563 if (tj.CTP != vx.
CTP)
continue;
564 for (
unsigned short end = 0;
end < 2; ++
end) {
565 if (tj.VtxID[
end] == vx.
ID) tj.VtxID[
end] = 0;
566 if (tj.VtxID[
end] == oVxID) tj.VtxID[
end] = 0;
570 for (
unsigned short ii = 0; ii < fitpts.size(); ++ii) {
571 auto& tjpt = fitpts[ii];
572 unsigned short end = tjpt.AngleCode;
573 auto& tj = slc.
tjs[tjpt.Hits[0] - 1];
574 if (tj.VtxID[end] != 0)
return false;
575 tj.VtxID[
end] = oVxID;
582 oVx.NTraj = fitpts.size();
589 myprt <<
"MWV: " << oVxID;
590 myprt <<
" Done TPs";
591 for (
unsigned short ii = 0; ii < fitpts.size(); ++ii) {
592 auto& tjpt = fitpts[ii];
593 myprt <<
" " << tjpt.Hits[0] <<
"_" << tjpt.AngleCode <<
"_" <<
PrintPos(tjpt.Pos);
620 for (
unsigned short it1 = 0; it1 < slc.
tjs.size(); ++it1) {
621 if (slc.
tjs[it1].CTP != inCTP)
continue;
623 if (slc.
tjs[it1].AlgMod[
kHamVx])
continue;
626 if (slc.
tjs[it1].PDGCode == 111)
continue;
628 if (numPtsWithCharge1 < 6)
continue;
630 if (slc.
tjs[it1].MCSMom < 200)
continue;
632 bool didaSplit =
false;
633 for (
unsigned short end1 = 0; end1 < 2; ++end1) {
635 if (slc.
tjs[it1].VtxID[end1] > 0)
continue;
636 unsigned short endPt1 = slc.
tjs[it1].EndPt[end1];
637 for (
unsigned short it2 = 0; it2 < slc.
tjs.size(); ++it2) {
638 if (it1 == it2)
continue;
639 if (slc.
tjs[it2].AlgMod[
kKilled] || slc.
tjs[it2].AlgMod[kHaloTj])
continue;
640 if (slc.
tjs[it2].AlgMod[kHamVx])
continue;
641 if (slc.
tjs[it2].AlgMod[kHamVx2])
continue;
643 if (slc.
tjs[it2].CTP != inCTP)
continue;
645 if (slc.
tjs[it2].AlgMod[kJunkTj])
continue;
646 if (slc.
tjs[it2].PDGCode == 111)
continue;
648 if (numPtsWithCharge2 < 6)
continue;
650 if (numPtsWithCharge2 > 100 && slc.
tjs[it2].MCSMom > 500)
continue;
653 float doca = minDOCA;
654 unsigned short closePt2 = 0;
656 if (doca == minDOCA)
continue;
659 auto& tj1 = slc.
tjs[it1];
660 auto& tj2 = slc.
tjs[it2];
661 myprt <<
" FHV2 CTP" << tj1.CTP;
662 myprt <<
" t" << tj1.ID <<
"_" << end1 <<
" MCSMom " << tj1.MCSMom <<
" ChgRMS " 664 myprt <<
" split t" << tj2.ID <<
"? MCSMom " << tj2.MCSMom <<
" ChgRMS " << tj2.ChgRMS;
665 myprt <<
" doca " << doca <<
" tj2.EndPt[0] " << tj2.EndPt[0] <<
" closePt2 " 667 myprt <<
" tj2.EndPt[1] " << tj2.EndPt[1];
670 if (closePt2 < slc.
tjs[it2].EndPt[0] + 3)
continue;
671 if (closePt2 > slc.
tjs[it2].EndPt[1] - 3)
continue;
676 float dang =
DeltaAngle(slc.
tjs[it1].Pts[endPt1].Ang, slc.
tjs[it2].Pts[closePt2].Ang);
677 if (dang < 0.2)
continue;
680 unsigned short closePt1 = 0;
682 if (closePt1 != endPt1)
continue;
689 unsigned short intPt2;
693 <<
PrintPos(slc.
tjs[it2].Pts[intPt2]) <<
" doca " << doca;
694 if (doca == minDOCA)
continue;
696 float mcsmom = slc.
tjs[it2].MCSMom;
697 float mcsmom1 =
MCSMom(slc, slc.
tjs[it2], slc.
tjs[it2].EndPt[0], intPt2);
698 float mcsmom2 =
MCSMom(slc, slc.
tjs[it2], intPt2, slc.
tjs[it2].EndPt[1]);
701 mf::LogVerbatim(
"TC") <<
" Check MCSMom after split: mcsmom1 " << mcsmom1 <<
" mcsmom2 " 703 if (mcsmom1 < mcsmom || mcsmom2 < mcsmom)
continue;
707 if (intPt2 < closePt2) dir = -1;
708 unsigned short nit = 0;
709 unsigned short ipt = intPt2;
710 float mostChg = slc.
tjs[it2].Pts[ipt].Chg;
713 <<
" chg " << mostChg;
716 if (ipt < 3 || ipt > slc.
tjs[it2].Pts.size() - 4)
break;
718 slc.
tjs[it2].Pts[ipt].Pos[0], slc.
tjs[it2].Pts[ipt].Pos[1], slc.
tjs[it1].Pts[endPt1]);
719 float sep =
PosSep(slc.
tjs[it2].Pts[ipt].Pos, slc.
tjs[it1].Pts[endPt1].Pos);
720 float dang = delta / sep;
721 float pull = dang / slc.
tjs[it1].Pts[endPt1].DeltaRMS;
722 if (pull < 2 && slc.
tjs[it2].Pts[ipt].Chg > mostChg) {
723 mostChg = slc.
tjs[it2].Pts[ipt].Chg;
728 float chgPull = (mostChg - slc.
tjs[it2].AveChg) / slc.
tjs[it2].ChgRMS;
730 if (chgPull < 10)
continue;
733 if (slc.
tjs[it1].Pts[endPt1].Pos[0] < -0.4)
continue;
734 unsigned int fromWire = std::nearbyint(slc.
tjs[it1].Pts[endPt1].Pos[0]);
735 if (slc.
tjs[it2].Pts[intPt2].Pos[0] < -0.4)
continue;
736 unsigned int toWire = std::nearbyint(slc.
tjs[it2].Pts[intPt2].Pos[0]);
737 if (fromWire > toWire) {
738 unsigned int tmp = fromWire;
743 for (
unsigned int wire = fromWire + 1; wire < toWire; ++wire) {
750 if (skipIt)
continue;
754 aVtx.
Pos = slc.
tjs[it2].Pts[intPt2].Pos;
760 aVtx.
ID = slc.
vtxs.size() + 1;
761 unsigned short ivx = slc.
vtxs.size();
763 if (!
SplitTraj(slc, it2, intPt2, ivx, prt)) {
768 slc.
tjs[it1].VtxID[end1] = slc.
vtxs[ivx].ID;
771 unsigned short newTjIndex = slc.
tjs.size() - 1;
781 << slc.
vtxs[ivx].Score;
785 if (didaSplit)
break;
807 for (
unsigned short it1 = 0; it1 < slc.
tjs.size(); ++it1) {
808 if (slc.
tjs[it1].CTP != inCTP)
continue;
812 if (slc.
tjs[it1].PDGCode == 111)
continue;
814 unsigned short tj1len = slc.
tjs[it1].EndPt[1] - slc.
tjs[it1].EndPt[0] + 1;
815 if (tj1len < 5)
continue;
817 if (slc.
tjs[it1].MCSMom < 50)
continue;
818 if (prt)
mf::LogVerbatim(
"TC") <<
"FHV: intersection T" << slc.
tjs[it1].ID <<
" candidate";
820 bool didaSplit =
false;
821 for (
unsigned short end1 = 0; end1 < 2; ++end1) {
823 if (slc.
tjs[it1].VtxID[end1] > 0)
continue;
824 unsigned short endPt1 = slc.
tjs[it1].EndPt[end1];
825 for (
unsigned short it2 = 0; it2 < slc.
tjs.size(); ++it2) {
826 if (slc.
tjs[it2].CTP != inCTP)
continue;
827 if (it1 == it2)
continue;
828 if (slc.
tjs[it2].AlgMod[
kKilled] || slc.
tjs[it2].AlgMod[kHaloTj])
continue;
829 if (slc.
tjs[it2].AlgMod[kJunkTj])
continue;
830 if (slc.
tjs[it2].PDGCode == 111)
continue;
832 unsigned short tj2len = slc.
tjs[it2].EndPt[1] - slc.
tjs[it2].EndPt[0] + 1;
833 if (tj2len < 6)
continue;
835 if (tj2len > 200 && slc.
tjs[it2].PDGCode == 13 && slc.
tjs[it2].MCSMom > 600)
continue;
837 minDOCA /=
std::abs(slc.
tjs[it1].Pts[endPt1].Dir[0]);
838 float doca = minDOCA;
839 unsigned short closePt2 = 0;
841 if (doca == minDOCA)
continue;
845 << slc.
tjs[it2].ID <<
" doca " << doca <<
" tj2.EndPt[0] " 846 << slc.
tjs[it2].EndPt[0] <<
" closePt2 " << closePt2
847 <<
" tj2.EndPt[1] " << slc.
tjs[it2].EndPt[1];
848 if (closePt2 < slc.
tjs[it2].EndPt[0] + 3)
continue;
849 if (closePt2 > slc.
tjs[it2].EndPt[1] - 3)
continue;
851 float dang =
DeltaAngle(slc.
tjs[it1].Pts[endPt1].Ang, slc.
tjs[it2].Pts[closePt2].Ang);
853 mf::LogVerbatim(
"TC") <<
" dang " << dang <<
" imposing a hard cut of 0.4 for now ";
854 if (dang < 0.4)
continue;
856 std::vector<int> tjids(2);
857 tjids[0] = slc.
tjs[it1].ID;
858 tjids[1] = slc.
tjs[it2].ID;
861 if (chgFrac < 0.9)
continue;
865 slc.
tjs[it1].Pts[endPt1], slc.
tjs[it2].Pts[closePt2], vxpos[0], vxpos[1]);
880 aVtx.
ID = slc.
vtxs.size() + 1;
882 unsigned short ivx = slc.
vtxs.size() - 1;
883 if (!
SplitTraj(slc, it2, closePt2, ivx, prt)) {
888 slc.
tjs[it1].VtxID[end1] = slc.
vtxs[ivx].ID;
891 unsigned short newTjIndex = slc.
tjs.size() - 1;
892 slc.
tjs[newTjIndex].AlgMod[
kHamVx] =
true;
899 auto& vx2 = slc.
vtxs[ivx];
901 myprt <<
" new 2V" << vx2.ID <<
" Score " << vx2.Score <<
" Tjs";
902 auto tjlist =
GetAssns(slc,
"2V", vx2.
ID,
"T");
903 for (
auto tid : tjlist)
904 myprt <<
" t" << tid;
909 if (didaSplit)
break;
922 if (slc.
vtxs.empty())
return;
923 if (slc.
tjs.empty())
return;
925 constexpr
float docaCut = 4;
928 if (prt)
mf::LogVerbatim(
"TC") <<
"Inside SplitTrajCrossingVertices inCTP " << inCTP;
932 unsigned short nTraj = slc.
tjs.size();
933 for (
unsigned short itj = 0; itj < nTraj; ++itj) {
935 if (slc.
tjs[itj].CTP != inCTP)
continue;
941 if (slc.
tjs[itj].EndPt[1] < 6)
continue;
942 for (
unsigned short iv = 0; iv < slc.
vtxs.size(); ++iv) {
943 auto& vx2 = slc.
vtxs[iv];
945 if (vx2.NTraj == 0)
continue;
947 if (slc.
tjs[itj].VtxID[0] == vx2.ID || slc.
tjs[itj].VtxID[1] == vx2.ID)
continue;
949 if (slc.
tjs[itj].CTP != vx2.CTP)
continue;
952 float doca = docaCut;
956 unsigned short closePt = 0;
963 if (doca > docaCut)
continue;
966 << slc.
vtxs[iv].ID <<
" closePt " << closePt <<
" in plane " 972 if (vxtjs.empty())
continue;
973 unsigned short maxPts = 0;
977 float tjAng = slc.
tjs[itj].Pts[closePt].Ang;
978 for (
auto tjid : vxtjs) {
979 auto& vtj = slc.
tjs[tjid - 1];
982 if (npwc > maxPts) maxPts = npwc;
983 unsigned short end = 0;
984 if (vtj.VtxID[1] == slc.
vtxs[iv].ID) end = 1;
985 auto& vtp = vtj.Pts[vtj.EndPt[
end]];
987 if (dang > maxdang) maxdang = dang;
993 if (!skipit && maxdang < 0.3) skipit =
true;
995 mf::LogVerbatim(
"TC") <<
" maxPts " << maxPts <<
" vxtjs[0] " << vxtjs[0] <<
" maxdang " 996 << maxdang <<
" skipit? " << skipit;
1007 auto& closeTP = slc.
tjs[itj].Pts[closePt];
1008 if (slc.
tjs[itj].StepDir > 0 && closePt > slc.
tjs[itj].EndPt[0]) {
1009 if (closeTP.Pos[0] > vx2.Pos[0]) --closePt;
1011 else if (slc.
tjs[itj].StepDir < 0 && closePt < slc.
tjs[itj].EndPt[1]) {
1012 if (closeTP.Pos[0] < vx2.Pos[0]) ++closePt;
1019 if ((slc.
tjs[itj].Pts[closePt].Pos[0] - vx2.Pos[0]) *
1020 (slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[1]].Pos[0] - vx2.Pos[0]) +
1021 (slc.
tjs[itj].Pts[closePt].Pos[1] - vx2.Pos[1]) *
1022 (slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[1]].Pos[1] - vx2.Pos[1]) <
1024 closePt < slc.
tjs[itj].EndPt[1] - 1)
1026 else if ((slc.
tjs[itj].Pts[closePt].Pos[0] - vx2.Pos[0]) *
1027 (slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[0]].Pos[0] - vx2.Pos[0]) +
1028 (slc.
tjs[itj].Pts[closePt].Pos[1] - vx2.Pos[1]) *
1029 (slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[0]].Pos[1] - slc.
vtxs[iv].Pos[1]) <
1031 closePt > slc.
tjs[itj].EndPt[0] + 1)
1036 mf::LogVerbatim(
"TC") <<
"Good doca " << doca <<
" btw T" << slc.
tjs[itj].ID <<
" and 2V" 1037 << vx2.ID <<
" closePt " << closePt <<
" in plane " << planeID.
Plane 1038 <<
" CTP " << slc.
vtxs[iv].CTP;
1039 PrintTP(
"STCV", slc, closePt, 1, slc.
tjs[itj].Pass, slc.
tjs[itj].Pts[closePt]);
1042 if (closePt < slc.
tjs[itj].EndPt[0] + 3)
continue;
1043 if (closePt > slc.
tjs[itj].EndPt[1] - 3)
continue;
1044 if (!
SplitTraj(slc, itj, closePt, iv, prt)) {
1045 if (prt)
mf::LogVerbatim(
"TC") <<
"SplitTrajCrossingVertices: Failed to split trajectory";
1049 unsigned short newTjIndex = slc.
tjs.size() - 1;
1064 if (slc.
vtxs.empty())
return;
1069 std::vector<std::vector<int>> vx2Cls;
1072 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
1075 for (
unsigned short ii = 0; ii < slc.
vtxs.size() - 1; ++ii) {
1076 auto& i2v = slc.
vtxs[ii];
1077 if (i2v.ID <= 0)
continue;
1079 for (
unsigned short jj = ii + 1; jj < slc.
vtxs.size(); ++jj) {
1080 auto& j2v = slc.
vtxs[jj];
1081 if (j2v.ID <= 0)
continue;
1084 float dp0 =
std::abs(i2v.Pos[0] - j2v.Pos[0]);
1085 if (dp0 > 10)
continue;
1086 float dp1 =
std::abs(i2v.Pos[1] - j2v.Pos[1]);
1087 if (dp1 > 10)
continue;
1089 float err = i2v.PosErr[0];
1090 if (j2v.PosErr[0] > err) err = j2v.PosErr[0];
1091 float dp0Sig = dp0 / err;
1092 if (dp0Sig > 4)
continue;
1093 err = i2v.PosErr[1];
1094 if (j2v.PosErr[1] > err) err = j2v.PosErr[1];
1095 float dp1Sig = dp1 / err;
1096 if (dp1Sig > 4)
continue;
1099 for (
auto& vx2cls : vx2Cls) {
1100 bool goti = (std::find(vx2cls.begin(), vx2cls.end(), i2v.ID) != vx2cls.end());
1101 bool gotj = (std::find(vx2cls.begin(), vx2cls.end(), j2v.ID) != vx2cls.end());
1107 vx2cls.push_back(j2v.ID);
1113 vx2cls.push_back(i2v.ID);
1119 std::vector<int> cls(2);
1122 vx2Cls.push_back(cls);
1126 if (vx2Cls.empty())
continue;
1129 myprt <<
"2V clusters in plane " << plane;
1130 for (
auto& vx2cls : vx2Cls) {
1132 for (
auto vx2id : vx2cls)
1133 myprt <<
" 2V" << vx2id;
1136 for (
auto& vx2cls : vx2Cls) {
1143 bool VxEnvironmentNeedsUpdate =
false;
1144 for (
auto& vx : slc.
vtxs) {
1145 if (vx.ID <= 0)
continue;
1146 if (!vx.Stat[
kVxEnvOK]) VxEnvironmentNeedsUpdate =
true;
1160 if (vx2cls.size() < 2)
return false;
1163 std::vector<int> t2vList;
1166 for (
auto vx2id : vx2cls) {
1167 auto& vx2 = slc.
vtxs[vx2id - 1];
1170 if (vx2.ID <= 0)
return true;
1171 auto tlist =
GetAssns(slc,
"2V", vx2.
ID,
"T");
1172 for (
auto tid : tlist)
1173 if (std::find(t2vList.begin(), t2vList.end(), tid) == t2vList.end()) t2vList.push_back(tid);
1175 if (t2vList.size() < 3)
return false;
1180 for (
auto tid : t2vList) {
1181 auto& tj = slc.
tjs[tid - 1];
1182 for (
unsigned short end = 0;
end < 2; ++
end) {
1183 if (tj.VtxID[
end] <= 0)
continue;
1184 if (std::find(vx2cls.begin(), vx2cls.end(), tj.VtxID[
end]) == vx2cls.end())
continue;
1185 auto& vx = slc.
vtxs[tj.VtxID[
end] - 1];
1186 unsigned short nearEnd = 1 -
FarEnd(tj, vx.Pos);
1188 if (fitPt == USHRT_MAX)
return false;
1189 auto& tp = tj.Pts[fitPt];
1197 myprt <<
"R2VTs: cluster:";
1198 for (
auto vid : vx2cls)
1199 myprt <<
" 2V" << vid;
1201 for (
auto tid : t2vList)
1202 myprt <<
" T" << tid;
1203 myprt <<
" sumPulls " << std::setprecision(2) << sumPulls <<
" cnt " << cnt;
1211 for (
auto vid : vx2cls) {
1212 auto& vx = slc.
vtxs[vid - 1];
1213 oneVx.
Pos[0] += vx.Pos[0];
1214 oneVx.
Pos[1] += vx.Pos[2];
1216 oneVx.
Pos[0] /= vx2cls.size();
1217 oneVx.
Pos[1] /= vx2cls.size();
1218 std::vector<TrajPoint> oneVxTPs(t2vList.size());
1219 for (
unsigned short itj = 0; itj < t2vList.size(); ++itj) {
1220 auto& tj = slc.
tjs[t2vList[itj] - 1];
1221 unsigned short nearEnd = 1 -
FarEnd(tj, oneVx.
Pos);
1223 if (fitPt == USHRT_MAX)
return false;
1224 oneVxTPs[itj] = tj.Pts[fitPt];
1226 if (oneVxTPs[itj].Environment[
kEnvOverlap]) oneVxTPs[itj].AngErr *= 4;
1227 oneVxTPs[itj].Step = tj.ID;
1229 if (!
FitVertex(slc, oneVx, oneVxTPs, prt))
return false;
1233 auto& vx = slc.
vtxs[vx2cls[0] - 1];
1235 vx.PosErr = oneVx.
PosErr;
1236 vx.NTraj = t2vList.size();
1237 vx.ChiDOF = oneVx.
ChiDOF;
1242 for (
unsigned short ivx = 1; ivx < vx2cls.size(); ++ivx) {
1243 auto& vx = slc.
vtxs[vx2cls[ivx] - 1];
1247 for (
auto tid : t2vList) {
1248 auto& tj = slc.
tjs[tid - 1];
1249 unsigned short nearEnd = 1 -
FarEnd(tj, vx.Pos);
1250 tj.VtxID[nearEnd] = vx.ID;
1265 if (slc.
vtxs.size() < 2)
return;
1268 std::vector<std::vector<unsigned short>> vIndex(3);
1269 for (
unsigned short ivx = 0; ivx < slc.
vtxs.size(); ++ivx) {
1271 if (slc.
vtxs[ivx].ID == 0)
continue;
1274 unsigned short plane = planeID.
Plane;
1275 if (plane > 2)
continue;
1276 vIndex[plane].push_back(ivx);
1279 unsigned short vtxInPln = 0;
1280 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane)
1281 if (vIndex[plane].
size() > 0) ++vtxInPln;
1282 if (vtxInPln < 2)
return;
1288 <<
" thirdPlanedXCut " << thirdPlanedXCut;
1291 size_t vsize = slc.
vtxs.size();
1293 std::vector<short> vPtr(vsize, -1);
1295 std::vector<float> vX(vsize, FLT_MAX);
1297 for (
unsigned short ivx = 0; ivx < vsize; ++ivx) {
1298 if (slc.
vtxs[ivx].ID <= 0)
continue;
1300 if (slc.
vtxs[ivx].Pos[0] < -0.4)
continue;
1308 std::vector<Vtx3Store> v3temp;
1314 constexpr
float maxSep = 4;
1318 for (
unsigned short ipl = 0; ipl < 2; ++ipl) {
1319 for (
unsigned short ii = 0; ii < vIndex[ipl].size(); ++ii) {
1320 unsigned short ivx = vIndex[ipl][ii];
1321 if (vX[ivx] == FLT_MAX)
continue;
1322 auto& ivx2 = slc.
vtxs[ivx];
1323 if (ivx2.Pos[0] < -0.4)
continue;
1324 unsigned int iWire = std::nearbyint(ivx2.Pos[0]);
1325 for (
unsigned short jpl = ipl + 1; jpl < 3; ++jpl) {
1326 for (
unsigned short jj = 0; jj < vIndex[jpl].size(); ++jj) {
1327 unsigned short jvx = vIndex[jpl][jj];
1328 if (vX[jvx] == FLT_MAX)
continue;
1329 auto& jvx2 = slc.
vtxs[jvx];
1330 if (jvx2.Pos[0] < -0.4)
continue;
1331 unsigned int jWire = std::nearbyint(jvx2.Pos[0]);
1332 float dX =
std::abs(vX[ivx] - vX[jvx]);
1336 <<
"F3DV: ipl " << ipl <<
" i2V" << ivx2.ID <<
" iX " << vX[ivx] <<
" jpl " << jpl
1337 <<
" j2V" << jvx2.ID <<
" jvX " << vX[jvx] <<
" W:T " << (int)jvx2.Pos[0] <<
":" 1338 << (
int)jvx2.Pos[1] <<
" dX " << dX;
1340 double y = -1000,
z = -1000;
1343 y = intersection->y;
1344 z = intersection->z;
1346 if (y < slc.yLo || y > slc.
yHi || z < slc.zLo || z > slc.
zHi)
continue;
1347 unsigned short kpl = 3 - ipl - jpl;
1348 float kX = 0.5 * (vX[ivx] + vX[jvx]);
1353 std::array<int, 2> wireWindow;
1354 std::array<float, 2> timeWindow;
1355 wireWindow[0] = kWire - maxSep;
1356 wireWindow[1] = kWire + maxSep;
1359 timeWindow[0] = time - maxSep;
1360 timeWindow[1] = time + maxSep;
1362 std::vector<unsigned int> closeHits =
1366 myprt <<
" Hits near " << kpl <<
":" << kWire <<
":" 1368 for (
auto iht : closeHits)
1371 if (!hitsNear)
continue;
1378 v3d.
Vx2ID[ipl] = ivx2.ID;
1379 v3d.
Vx2ID[jpl] = jvx2.ID;
1388 float vxScoreWght = 0;
1391 if (posError < 0.5) posError = 0;
1392 v3d.
Score = posError + vxScoreWght;
1395 v3temp.push_back(v3d);
1399 myprt <<
" 2 Plane match i2V";
1400 myprt << slc.
vtxs[ivx].ID <<
" P:W:T " << ipl <<
":" << (int)slc.
vtxs[ivx].Pos[0]
1401 <<
":" << (
int)slc.
vtxs[ivx].Pos[1];
1402 myprt <<
" j2V" << slc.
vtxs[jvx].ID <<
" P:W:T " << jpl <<
":" 1403 << (int)slc.
vtxs[jvx].Pos[0] <<
":" << (
int)slc.
vtxs[jvx].Pos[1];
1404 myprt << std::fixed << std::setprecision(3);
1405 myprt <<
" dX " << dX <<
" posError " << posError <<
" vxScoreWght " << vxScoreWght
1406 <<
" Score " << v3d.
Score;
1409 if (slc.
nPlanes == 2)
continue;
1412 for (
unsigned short kk = 0; kk < vIndex[kpl].size(); ++kk) {
1413 unsigned short kvx = vIndex[kpl][kk];
1417 if (dX > thirdPlanedXCut)
continue;
1420 double y = -1000,
z = -1000;
1423 y = intersection->y;
1424 z = intersection->z;
1426 v3d.
YErr = y - v3d.
Y;
1435 posError = dX * dX + dY * dY + dZ * dZ;
1439 if (posError < 0.5) posError = 0;
1440 v3d.
Score = posError + vxScoreWght;
1441 if (v3d.
Score > maxScore) maxScore = v3d.
Score;
1443 mf::LogVerbatim(
"TC") <<
" k2V" << kvx + 1 <<
" dX " << dX <<
" dW " << dW
1444 <<
" 3D score " << v3d.
Score;
1445 v3temp.push_back(v3d);
1452 if (v3temp.empty())
return;
1457 for (
auto& v3 : v3temp)
1458 if (v3.Wire >= 0) v3.Score += maxScore;
1462 for (
auto& v3 : v3temp) {
1464 mf::LogVerbatim(
"TC") <<
"2V" << v3.Vx2ID[0] <<
" 2V" << v3.Vx2ID[1] <<
" wire " 1465 << v3.Wire <<
" Score " << v3.Score;
1468 mf::LogVerbatim(
"TC") <<
"2V" << v3.Vx2ID[0] <<
" 2V" << v3.Vx2ID[1] <<
" 2V" 1469 << v3.Vx2ID[2] <<
" wire " << v3.Wire <<
" Score " << v3.Score;
1474 std::vector<SortEntry> sortVec(v3temp.size());
1475 for (
unsigned short ivx = 0; ivx < v3temp.size(); ++ivx) {
1477 sEntry.
val = v3temp[ivx].Score;
1478 sortVec[ivx] = sEntry;
1480 if (sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(),
valsIncreasing);
1482 std::vector<Vtx3Store> v3sel;
1483 for (
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
1484 unsigned short ivx = sortVec[ii].
index;
1486 bool skipit =
false;
1487 for (
auto& v3 : v3sel) {
1488 for (
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
1489 if (v3temp[ivx].Vx2ID[ipl] == 0)
continue;
1490 if (v3temp[ivx].Vx2ID[ipl] == v3.Vx2ID[ipl]) {
1497 if (skipit)
continue;
1498 v3sel.push_back(v3temp[ivx]);
1504 myprt <<
"v3sel list\n";
1505 for (
auto& v3d : v3sel) {
1506 for (
auto vx2id : v3d.Vx2ID)
1507 if (vx2id > 0) myprt <<
" 2V" << vx2id;
1508 myprt <<
" wire " << v3d.Wire <<
" Score " << v3d.Score;
1514 unsigned short ninc = 0;
1515 for (
auto& vx3 : v3sel) {
1516 if (slc.
nPlanes == 3 && vx3.Wire >= 0) ++ninc;
1517 vx3.ID = slc.
vtx3s.size() + 1;
1522 myprt <<
" 3V" << vx3.ID;
1523 for (
auto v2id : vx3.Vx2ID)
1524 myprt <<
" 2V" << v2id;
1525 myprt <<
" wire " << vx3.Wire;
1527 slc.
vtx3s.push_back(vx3);
1529 for (
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
1530 if (vx3.Vx2ID[ipl] == 0)
continue;
1544 for (
auto& tj : slc.
tjs) {
1547 if (planeID.
TPC != tpc || planeID.
Cryostat != cstat)
continue;
1551 for (
auto& vx2 : slc.
vtxs) {
1552 if (vx2.ID == 0)
continue;
1554 if (planeID.
TPC != tpc || planeID.
Cryostat != cstat)
continue;
1558 for (
auto& vx3 : slc.
vtx3s) {
1559 if (vx3.ID == 0)
continue;
1569 for (
unsigned short ivx = 0; ivx < slc.
vtxs.size(); ++ivx) {
1570 if (slc.
vtxs[ivx].ID == 0)
continue;
1571 if (slc.
vtxs[ivx].CTP != tp.
CTP)
continue;
1584 if (pfp.
ID <= 0)
return false;
1586 float pLen =
Length(pfp);
1587 if (pLen == 0)
return false;
1591 for (
unsigned short end = 0;
end < 2; ++
end)
1593 std::array<Point3_t, 2> endPos;
1597 std::array<float, 2> foms{{100., 100.}};
1598 std::array<int, 2> vtxs{{0}};
1599 for (
auto& vx3 : slc.
vtx3s) {
1600 if (vx3.ID <= 0)
continue;
1601 if (vx3.TPCID != pfp.
TPCID)
continue;
1602 std::array<float, 2> sep;
1603 Point3_t vpos = {{vx3.X, vx3.Y, vx3.Z}};
1604 sep[0] =
PosSep(vpos, endPos[0]);
1605 sep[1] =
PosSep(vpos, endPos[1]);
1606 unsigned short end = 0;
1607 if (sep[1] < sep[0]) end = 1;
1609 if (sep[end] > 100)
continue;
1614 float fom = dotp * sep[
end];
1616 mf::LogVerbatim(
"TC") <<
"ATAV: P" << pfp.
ID <<
" end " << end <<
" 3V" << vx3.ID <<
" sep " 1617 << sep[
end] <<
" fom " << fom <<
" maxSep " << maxSep;
1619 if (sep[end] > maxSep)
continue;
1620 if (fom < foms[end]) {
1626 for (
unsigned short end = 0;
end < 2; ++
end) {
1627 if (vtxs[
end] == 0)
continue;
1640 if (tjID <= 0 || tjID > (
int)slc.
tjs.size())
return false;
1641 if (slc.
vtxs.empty())
return false;
1642 auto& tj = slc.
tjs[tjID - 1];
1643 if (tj.AlgMod[
kKilled])
return false;
1646 unsigned short bestVx = USHRT_MAX;
1650 for (
unsigned short ivx = 0; ivx < slc.
vtxs.size(); ++ivx) {
1651 auto& vx = slc.
vtxs[ivx];
1652 if (vx.ID == 0)
continue;
1653 if (vx.CTP != tj.CTP)
continue;
1655 std::array<float, 2> sep;
1656 sep[0] =
PosSep(vx.Pos, tj.Pts[tj.EndPt[0]].Pos);
1657 sep[1] =
PosSep(vx.Pos, tj.Pts[tj.EndPt[1]].Pos);
1658 unsigned short end = 0;
1659 if (sep[1] < sep[0]) end = 1;
1660 if (sep[end] > 100)
continue;
1661 if (tj.VtxID[end] > 0)
continue;
1662 auto& tp = tj.Pts[tj.EndPt[
end]];
1665 if (fom > bestFOM)
continue;
1667 mf::LogVerbatim(
"TC") <<
"AAVTT: T" << tjID <<
" 2V" << vx.ID <<
" FOM " << fom <<
" cut " 1672 if (bestVx > slc.
vtxs.size() - 1)
return false;
1673 auto& vx = slc.
vtxs[bestVx];
1681 if (ivx > slc.
vtxs.size() - 1)
return false;
1682 if (slc.
vtxs[ivx].ID == 0)
return false;
1687 if (vx.
Topo == 5 || vx.
Topo == 6)
return false;
1689 unsigned short bestTj = USHRT_MAX;
1693 for (
unsigned int itj = 0; itj < slc.
tjs.size(); ++itj) {
1694 auto& tj = slc.
tjs[itj];
1696 if (tj.CTP != vx.
CTP)
continue;
1698 std::array<float, 2> sep;
1699 sep[0] =
PosSep(vx.
Pos, tj.Pts[tj.EndPt[0]].Pos);
1700 sep[1] =
PosSep(vx.
Pos, tj.Pts[tj.EndPt[1]].Pos);
1701 unsigned short end = 0;
1702 if (sep[1] < sep[0]) end = 1;
1703 if (sep[end] > 100)
continue;
1704 if (tj.VtxID[end] > 0)
continue;
1705 auto& tp = tj.Pts[tj.EndPt[
end]];
1708 if (fom > bestFOM)
continue;
1711 <<
" FOM " << fom <<
" cut " << bestFOM;
1716 if (bestTj > slc.
tjs.size() - 1)
return false;
1717 auto& tj = slc.
tjs[bestTj];
1736 if (tj.
CTP != vx.
CTP)
return false;
1746 unsigned short end = 0;
1749 if (sep1 < vtxTjSep2) {
1755 if (tj.
VtxID[end] > 0)
return false;
1758 bool tjShort = (tj.
EndPt[1] - tj.
EndPt[0] < maxShortTjLen);
1760 if (!tjShort && tj.
ChgRMS > 0.5) tjShort =
true;
1761 float closestApproach;
1764 if (vtxTjSep2 > maxSepCutShort2)
return false;
1769 if (vtxTjSep2 > maxSepCutLong2)
return false;
1778 unsigned short closePt;
1784 if (end == 0) { dpt = closePt - tj.
EndPt[
end]; }
1791 if (length > 4 && length < closestApproach)
return false;
1797 if (tjShort) pullCut *= 2;
1801 myprt <<
"ATTV: 2V" << vx.
ID;
1802 myprt <<
" NTraj " << vx.
NTraj;
1804 for (
unsigned short itj = 0; itj < slc.
tjs.size(); ++itj) {
1807 if (tj.
CTP != vx.
CTP)
continue;
1808 if (tj.
VtxID[0] == vx.
ID) myprt <<
" T" << tj.
ID <<
"_0";
1809 if (tj.
VtxID[1] == vx.
ID) myprt <<
" T" << tj.
ID <<
"_1";
1811 myprt <<
" + T" << tj.
ID <<
"_" << end <<
" vtxTjSep " << sqrt(vtxTjSep2) <<
" tpVxPull " 1812 << tpVxPull <<
" pullCut " << pullCut <<
" dpt " << dpt;
1814 if (tpVxPull > pullCut)
return false;
1815 if (dpt > 2)
return true;
1837 <<
" assn with kNoFitVx";
1855 double vxErrW = vx.
PosErr[0] * tp.
Dir[1];
1856 double vxErrT = vx.
PosErr[1] * tp.
Dir[0];
1857 double vxErr2 = vxErrW * vxErrW + vxErrT * vxErrT;
1863 if (sep2 < 1)
return (
float)(ip / sqrt(vxErr2));
1865 double dang = ip / sqrt(sep2);
1869 double angErr = vxErr2 / sep2;
1872 if (angErr == 0)
return 999;
1873 angErr = sqrt(angErr);
1874 return (
float)(dang / angErr);
1882 double dx = vx1.
X - vx2.
X;
1883 double dy = vx1.
Y - vx2.
Y;
1884 double dz = vx1.
Z - vx2.
Z;
1888 dx = dx * dx / dxErr2;
1889 dy = dy * dy / dyErr2;
1890 dz = dz * dz / dzErr2;
1891 return (
float)(sqrt(dx + dy + dz) / 3);
1898 double dw = vx1.
Pos[0] - vx2.
Pos[0];
1899 double dt = vx1.
Pos[1] - vx2.
Pos[1];
1902 dw = dw * dw / dwErr2;
1903 dt = dt * dt / dtErr2;
1904 return (
float)sqrt(dw + dt);
1913 if (vx.
ID !=
int(slc.
vtxs.size() + 1))
return false;
1918 unsigned short nvxtj = 0;
1919 unsigned short nok = 0;
1920 for (
auto& tj : slc.
tjs) {
1921 if (tj.AlgMod[
kKilled])
continue;
1922 if (vx.
ID == tj.VtxID[0] || vx.
ID == tj.VtxID[1]) ++nvxtj;
1923 if (vx.
CTP != tj.CTP)
continue;
1924 if (vx.
ID == tj.VtxID[0] || vx.
ID == tj.VtxID[1]) ++nok;
1929 <<
" has inconsistent CTP code " << vx.
CTP <<
" with one or more Tjs\n";
1930 for (
auto& tj : slc.
tjs) {
1931 if (tj.AlgMod[
kKilled])
continue;
1932 if (tj.VtxID[0] == vx.
ID) tj.VtxID[0] = 0;
1933 if (tj.VtxID[1] == vx.
ID) tj.VtxID[1] = 0;
1938 slc.
vtxs.push_back(vx);
1957 if (prt)
mf::LogVerbatim(
"TC") <<
" vertex position fixed. No fit allowed";
1962 std::vector<TrajPoint> vxTp;
1963 for (
auto& tj : slc.
tjs) {
1965 if (tj.CTP != vx.
CTP)
continue;
1966 if (tj.AlgMod[
kPhoton])
continue;
1968 if (tj.VtxID[0] == vx.
ID && !tj.EndFlag[0][
kNoFitVx]) {
1969 vxTp.push_back(tj.Pts[tj.EndPt[0]]);
1972 if (tj.VtxID[1] == vx.
ID && !tj.EndFlag[1][
kNoFitVx]) {
1973 vxTp.push_back(tj.Pts[tj.EndPt[1]]);
1978 auto& tp = vxTp[vxTp.size() - 1];
1979 if (tj.ID > 0) tp.Step = (int)tj.ID;
1981 if (tp.NTPsFit < 4) tp.AngErr *= 4;
1985 bool success =
FitVertex(slc, vx, vxTp, prt);
1987 if (!success)
return false;
2001 if (vxTPs.size() < 2)
return false;
2002 if (vxTPs.size() == 2) {
2007 unsigned short npts = vxTPs.size();
2008 TMatrixD A(npts, 2);
2010 for (
unsigned short itj = 0; itj < vxTPs.size(); ++itj) {
2011 auto& tp = vxTPs[itj];
2012 double dtdw = tp.Dir[1] / tp.Dir[0];
2013 double wt = 1 / (tp.AngErr * tp.AngErr);
2014 A(itj, 0) = -dtdw * wt;
2015 A(itj, 1) = 1. * wt;
2016 b(itj) = (tp.Pos[1] - tp.Pos[0] * dtdw) * wt;
2019 TMatrixD AT(2, npts);
2021 TMatrixD ATA = AT * A;
2029 if (det == NULL)
return false;
2030 TVectorD vxPos = ATA * AT * b;
2031 vx.
PosErr[0] = sqrt(ATA[0][0]);
2032 vx.
PosErr[1] = sqrt(ATA[1][1]);
2033 vx.
Pos[0] = vxPos[0];
2034 vx.
Pos[1] = vxPos[1];
2038 if (vxTPs.size() > 2) {
2039 for (
auto& tp : vxTPs) {
2044 vx.
ChiDOF /= (float)(vxTPs.size() - 2);
2050 for (
auto& tp : vxTPs)
2051 PrintTP(
"FV", slc, 0, 1, 1, tp);
2064 unsigned short plane = planeID.
Plane;
2065 for (
auto& vx2 : slc.
vtxs) {
2066 if (vx2.CTP != inCTP)
continue;
2067 if (vx2.ID == 0)
continue;
2068 if (vx2.Vx3ID == 0)
continue;
2069 if (vx2.Vx3ID >
int(slc.
vtx3s.size())) {
2070 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: Invalid vx2.Vx3ID " << vx2.Vx3ID
2071 <<
" in 2D vtx " << vx2.ID;
2074 auto& vx3 = slc.
vtx3s[vx2.Vx3ID - 1];
2076 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: 2V" << vx2.ID <<
" thinks it is matched to 3V" 2077 << vx3.ID <<
" but vx3 is obsolete";
2080 if (vx3.Vx2ID[plane] != vx2.ID) {
2081 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: 2V" << vx2.ID <<
" thinks it is matched to 3V" 2082 << vx3.ID <<
" but vx3 says no!";
2087 for (
auto& vx3 : slc.
vtx3s) {
2088 if (vx3.ID == 0)
continue;
2089 if (vx3.Vx2ID[plane] == 0)
continue;
2090 if (vx3.Vx2ID[plane] > (
int)slc.
vtxs.size()) {
2091 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: Invalid vx3.Vx2ID " << vx3.Vx2ID[plane]
2092 <<
" in CTP " << inCTP;
2095 auto& vx2 = slc.
vtxs[vx3.Vx2ID[plane] - 1];
2096 if (vx2.Vx3ID != vx3.ID) {
2097 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: 3V" << vx3.ID <<
" thinks it is matched to 2V" 2098 << vx2.ID <<
" but vx2 says no!";
2104 for (
auto& tj : slc.
tjs) {
2106 for (
unsigned short end = 0;
end < 2; ++
end) {
2107 if (tj.VtxID[
end] == 0)
continue;
2108 if (tj.VtxID[
end] > slc.
vtxs.size()) {
2109 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: T" << tj.ID <<
" thinks it is matched to 2V" 2110 << tj.VtxID[
end] <<
" on end " <<
end 2111 <<
" but no vertex exists. Recovering";
2115 unsigned short ivx = tj.VtxID[
end] - 1;
2116 auto& vx2 = slc.
vtxs[ivx];
2118 mf::LogVerbatim(
"TC") <<
"ChkVtxAssociations: T" << tj.ID <<
" thinks it is matched to 2V" 2119 << tj.VtxID[
end] <<
" on end " <<
end 2120 <<
" but the vertex is killed. Fixing the Tj";
2137 for (
auto& vx : slc.
vtxs) {
2138 if (vx.ID == 0)
continue;
2142 for (
auto& tj : slc.
tjs) {
2147 for (
auto& vx : slc.
vtxs) {
2148 if (vx.ID == 0)
continue;
2152 for (
auto& vx3 : slc.
vtx3s) {
2153 if (vx3.ID == 0)
continue;
2162 if (slc.
vtxs.empty())
return;
2163 for (
auto& vx : slc.
vtxs) {
2164 if (vx.ID == 0)
continue;
2167 auto& vx3 = slc.
vtx3s[vx.Vx3ID - 1];
2168 if (vx3.Primary)
continue;
2181 if (vx3.
ID == 0)
return;
2183 for (
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
2184 if (vx3.
Vx2ID[ipl] <= 0)
continue;
2189 std::vector<int> vxlist;
2194 for (
auto tjid : tjlist) {
2195 auto& tj = slc.
tjs[tjid - 1];
2197 for (
unsigned short end = 0;
end < 2; ++
end) {
2198 if (tj.VtxID[
end] == 0)
continue;
2199 auto& vx2 = slc.
vtxs[tj.VtxID[
end] - 1];
2202 vxlist.push_back(vx2.
ID);
2206 if (vxlist.empty())
break;
2208 std::vector<int> newtjlist;
2209 for (
auto vxid : vxlist) {
2210 auto& vx2 = slc.
vtxs[vxid - 1];
2212 for (
auto tjid :
tmp) {
2213 if (std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end())
2214 newtjlist.push_back(tjid);
2217 if (newtjlist.empty())
break;
2230 if (vx3.
ID == 0)
return;
2233 for (
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
2234 if (vx3.
Vx2ID[ipl] <= 0)
continue;
2249 if (slc.
vtxs.empty())
return;
2250 auto& vx2 = slc.
vtxs[slc.
vtxs.size() - 1];
2258 if (vx2.
ID == 0)
return;
2269 constexpr
float maxChgRMS = 0.25;
2270 constexpr
float momBin = 50;
2274 if (vx2.
ID == 0)
return;
2278 if (vtxTjIDs.empty())
return;
2283 unsigned short m3Dcnt = 0;
2284 if (vx2.
Vx3ID > 0) {
2287 unsigned short ivx3 = vx2.
Vx3ID - 1;
2288 if (slc.
vtx3s[ivx3].Wire < 0) m3Dcnt = 2;
2296 std::vector<int> tjids;
2297 std::vector<float> tjwts;
2298 unsigned short cnt13 = 0;
2299 for (
auto tjid : vtxTjIDs) {
2303 unsigned short lenth = tj.
EndPt[1] - tj.
EndPt[0] + 1;
2304 if (lenth < 3)
continue;
2305 float wght = (float)tj.
MCSMom / momBin;
2309 if (cnt13 == 1) wght *= 2;
2312 if (tj.
ChgRMS < maxChgRMS) ++wght;
2317 tjids.push_back(tjid);
2318 tjwts.push_back(wght);
2321 if (tjids.empty())
return;
2326 for (
unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
2328 float wght1 = tjwts[it1];
2330 unsigned short end1 = 0;
2331 if (tj1.
VtxID[1] == vx2.
ID) end1 = 1;
2332 unsigned short endPt1 = tj1.
EndPt[end1];
2334 unsigned short oend1 = 1 - end1;
2336 float ang1 = tj1.
Pts[endPt1].Ang;
2337 float ang1Err2 = tj1.
Pts[endPt1].AngErr * tj1.
Pts[endPt1].AngErr;
2338 for (
unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
2340 float wght2 = tjwts[it2];
2342 if (tj2.
VtxID[1] == vx2.
ID) end2 = 1;
2344 unsigned short oend2 = 1 - end2;
2345 if (tj2.
EndFlag[oend2][kBragg]) ++wght2;
2346 unsigned short endPt2 = tj2.
EndPt[end2];
2347 float ang2 = tj2.
Pts[endPt2].Ang;
2348 float ang2Err2 = tj2.
Pts[endPt2].AngErr * tj2.
Pts[endPt2].AngErr;
2350 float dangErr = 0.5 * sqrt(ang1Err2 + ang2Err2);
2351 if ((dang / dangErr) > 3 && wght1 > 0 && wght2 > 0) {
2352 sum += wght1 + wght2;
2361 vx2.
Score = vpeScore + m3DScore + cfScore + tjScore;
2366 bool printHeader =
true;
2367 Print2V(myprt, vx2, printHeader);
2368 myprt << std::fixed << std::setprecision(1);
2369 myprt <<
" vpeScore " << vpeScore <<
" m3DScore " << m3DScore;
2370 myprt <<
" cfScore " << cfScore <<
" tjScore " << tjScore;
2371 myprt <<
" Score " << vx2.
Score;
2386 for (
unsigned short iv3 = 0; iv3 < slc.
vtx3s.size(); ++iv3) {
2389 if (vx3.
ID == 0)
continue;
2391 if (vx3.
Wire < 0)
continue;
2392 unsigned short mPlane = USHRT_MAX;
2393 for (
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
2394 if (vx3.
Vx2ID[ipl] > 0)
continue;
2398 if (mPlane == USHRT_MAX)
continue;
2402 if (dwc < 5)
continue;
2405 aVtx.
ID = slc.
vtxs.size() + 1;
2415 mf::LogVerbatim(
"TC") <<
"CI3DVIG: Incomplete vertex " << iv3 <<
" in plane " << mPlane
2416 <<
" wire " << vx3.
Wire <<
" Made 2D vertex ";
2417 std::vector<int> tjIDs;
2418 std::vector<unsigned short> tjEnds;
2419 for (
unsigned short itj = 0; itj < slc.
tjs.size(); ++itj) {
2420 if (slc.
tjs[itj].CTP != mCTP)
continue;
2422 for (
unsigned short end = 0;
end < 2; ++
end) {
2423 unsigned short ept = slc.
tjs[itj].EndPt[
end];
2425 unsigned short oept = slc.
tjs[itj].EndPt[1 -
end];
2430 if (doca > 2)
continue;
2433 if (aVtx.
Pos[0] > tp.
Pos[0]) { ptSep = aVtx.
Pos[0] - tp.
Pos[0] - dwc; }
2435 ptSep = tp.
Pos[0] - aVtx.
Pos[0] - dwc;
2439 <<
" ptSep " << ptSep;
2440 if (ptSep < -2 || ptSep > 2)
continue;
2442 if (slc.
tjs[itj].VtxID[
end] > 0)
continue;
2443 tjIDs.push_back(slc.
tjs[itj].ID);
2444 tjEnds.push_back(
end);
2447 if (!tjIDs.empty()) {
2454 for (
unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2455 unsigned short itj = tjIDs[ii] - 1;
2456 slc.
tjs[itj].VtxID[tjEnds[ii]] = aVtx.
ID;
2482 if (prt)
mf::LogVerbatim(
"TC") <<
"Inside CI3DV with maxdoca set to " << maxdoca;
2483 unsigned short ivx3 = 0;
2484 for (
auto& vx3 : slc.
vtx3s) {
2486 if (vx3.ID == 0)
continue;
2488 if (vx3.Wire < 0)
continue;
2489 unsigned short mPlane = USHRT_MAX;
2491 bool indPlnNoChgVtx =
false;
2492 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
2493 if (vx3.Vx2ID[plane] > 0) {
2494 auto& vx2 = slc.
vtxs[vx3.Vx2ID[plane] - 1];
2500 if (mPlane == USHRT_MAX)
continue;
2501 if (indPlnNoChgVtx)
continue;
2502 CTP_t mCTP =
EncodeCTP(vx3.TPCID.Cryostat, vx3.TPCID.TPC, mPlane);
2506 vtp.
Pos[0] = vx3.Wire;
2507 vtp.
Pos[1] = detProp.
ConvertXToTicks(vx3.X, mPlane, vx3.TPCID.TPC, vx3.TPCID.Cryostat) *
2510 mf::LogVerbatim(
"TC") <<
"CI3DV 3V" << vx3.ID <<
" Pos " << mPlane <<
":" 2512 std::vector<int> tjIDs;
2513 std::vector<unsigned short> tjPts;
2514 for (
auto& tj : slc.
tjs) {
2515 if (tj.CTP != mCTP)
continue;
2517 if (tj.Pts.size() < 6)
continue;
2519 float doca = maxdoca;
2521 unsigned short closePt = 0;
2523 if (closePt > tj.EndPt[1])
continue;
2528 mf::LogVerbatim(
"TC") <<
"CI3DV 3V" << vx3.ID <<
" candidate T" << tj.ID <<
" vtx pos " 2529 <<
PrintPos(vtp.
Pos) <<
" doca " << doca <<
" closePt " << closePt;
2530 tjIDs.push_back(tj.ID);
2531 tjPts.push_back(closePt);
2533 if (tjIDs.empty())
continue;
2537 auto vxtjs =
GetAssns(slc,
"3V", vx3.
ID,
"T");
2538 unsigned short maxPts = 0;
2539 unsigned short minPts = USHRT_MAX;
2540 for (
auto tjid : vxtjs) {
2541 auto& tj = slc.
tjs[tjid - 1];
2543 if (npwc > maxPts) maxPts = npwc;
2544 if (npwc < minPts) minPts = npwc;
2548 bool skipit =
false;
2549 for (
auto tjid : tjIDs) {
2550 auto& tj = slc.
tjs[tjid - 1];
2554 mf::LogVerbatim(
"TC") <<
" maxPts " << maxPts <<
" skipit? " << skipit <<
" minPts " 2556 if (skipit)
continue;
2559 unsigned short newVtxIndx = slc.
vtxs.size();
2560 aVtx.
ID = newVtxIndx + 1;
2578 std::array<float, 2> vpos = aVtx.
Pos;
2579 for (
unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2580 unsigned short itj = tjIDs[ii] - 1;
2581 unsigned short closePt = tjPts[ii];
2583 unsigned short end = 1;
2585 if (fabs(closePt - slc.
tjs[itj].EndPt[0]) < fabs(closePt - slc.
tjs[itj].EndPt[1])) end = 0;
2586 short dpt = fabs(closePt - slc.
tjs[itj].EndPt[end]);
2590 if (slc.
tjs[itj].VtxID[end] > 0) {
2592 auto& oldTj = slc.
tjs[itj];
2593 auto& oldVx = slc.
vtxs[oldTj.VtxID[
end] - 1];
2594 short oldSep = fabs(oldVx.Pos[0] - oldTj.Pts[oldTj.EndPt[end]].Pos[0]);
2597 <<
" T" << slc.
tjs[itj].ID <<
" has vertex 2V" << slc.
tjs[itj].VtxID[
end]
2598 <<
" at end " << end <<
". oldSep " << oldSep;
2604 slc.
tjs[itj].VtxID[
end] = slc.
vtxs[newVtxIndx].ID;
2609 vpos = slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[
end]].Pos;
2613 if (
SplitTraj(slc, itj, closePt, newVtxIndx, prt)) {
2616 <<
" SplitTraj success 2V" << slc.
vtxs[newVtxIndx].ID <<
" at closePt " << closePt;
2632 unsigned short newtj = slc.
tjs.size() - 1;
2635 if (newVtx.
NTraj == 0) {
2637 if (prt)
mf::LogVerbatim(
"TC") <<
" Failed. Recover and delete vertex " << newVtx.
ID;
2642 vx3.Vx2ID[mPlane] = newVtx.
ID;
2643 newVtx.
Vx3ID = vx3.ID;
2646 if (newVtx.
NTraj == 1) {
2654 myprt <<
" Success: new 2V" << newVtx.
ID <<
" at " << (int)newVtx.
Pos[0] <<
":" 2656 myprt <<
" points to 3V" << vx3.ID;
2658 for (
auto& tjID : tjIDs)
2673 float maxChg = tj.
Pts[nearPt].Chg;
2674 short maxChgPt = nearPt;
2675 unsigned short fromPt = tj.
EndPt[0];
2676 short spt = (short)nearPt - (
short)nPtsToChk;
2677 if (spt > (
short)fromPt) fromPt = nearPt - nPtsToChk;
2678 unsigned short toPt = nearPt + nPtsToChk;
2681 for (
short ipt = fromPt; ipt <= toPt; ++ipt) {
2682 if (ipt < tj.
EndPt[0] || ipt > tj.
EndPt[1])
continue;
2683 auto& tp = tj.
Pts[ipt];
2684 if (tp.Chg > maxChg) {
2690 <<
" chg " << (int)tp.Chg <<
" nhits " << tp.Hits.size();
2692 if (nearPt == maxChgPt)
return false;
2703 bool hasHighScoreVx3 = (vx2.
Vx3ID > 0);
2713 if (vx2.
Vx3ID > 0) {
2715 for (
auto& v3v2id : vx3.Vx2ID)
2716 if (v3v2id == vx2.
ID) v3v2id = 0;
2719 for (
auto& tj : slc.
tjs) {
2721 for (
unsigned short end = 0;
end < 2; ++
end) {
2722 if (tj.VtxID[
end] != vx2id)
continue;
2726 for (
unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
2728 unsigned short ipt = tj.EndPt[0] + ii;
2729 auto& tp = tj.Pts[ipt];
2731 if (ipt == tj.EndPt[1])
break;
2734 unsigned short ipt = tj.EndPt[1] - ii;
2735 auto& tp = tj.Pts[ipt];
2737 if (ipt == tj.EndPt[0])
break;
2742 unsigned short oend = 1 -
end;
2743 if (tj.VtxID[oend] > 0) {
2744 auto& ovx2 = slc.
vtxs[tj.VtxID[oend] - 1];
2751 if (!hasHighScoreVx3)
return true;
2757 unsigned short plane = planeID.
Plane;
2758 if (vx3.
Vx2ID[plane] != vx2id)
return true;
2759 vx3.
Vx2ID[plane] = 0;
2762 unsigned short n2D = 0;
2763 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane)
2764 if (vx3.
Vx2ID[plane] > 0) ++n2D;
2775 for (
auto& vx2 : slc.
vtxs) {
2776 if (vx2.
ID == 0)
continue;
2779 for (
auto& pfp : slc.
pfps) {
2780 for (
unsigned short end = 0;
end < 2; ++
end)
2781 if (pfp.Vx3ID[
end] == vx3.
ID) pfp.Vx3ID[
end] = 0;
2794 if (vx3.
ID <= 0)
return true;
2795 if (vx3.
ID >
int(slc.
vtx3s.size()))
return false;
2797 for (
auto vx2id : vx3.
Vx2ID) {
2798 if (vx2id == 0 || vx2id > (
int)slc.
vtxs.size())
continue;
2799 auto& vx2 = slc.
vtxs[vx2id - 1];
2810 std::vector<int>
tmp;
2811 if (vx2.
ID == 0)
return tmp;
2812 for (
auto& tj : slc.
tjs) {
2813 if (tj.AlgMod[
kKilled])
continue;
2814 if (tj.CTP != vx2.
CTP)
continue;
2815 for (
unsigned short end = 0;
end < 2; ++
end) {
2816 if (tj.VtxID[
end] == vx2.
ID) tmp.push_back(tj.ID);
2826 std::vector<int>
tmp;
2827 if (vx3.
ID == 0)
return tmp;
2830 for (
auto& vx2 : slc.
vtxs) {
2831 if (vx2.ID == 0)
continue;
2832 if (vx2.Vx3ID != vx3.
ID)
continue;
2834 tmp.insert(tmp.end(), vtxTjID2.begin(), vtxTjID2.end());
2838 if (nvx2 < 1)
return tmp;
2842 std::sort(tmp.begin(), tmp.end());
2849 unsigned short plane,
2864 unsigned short imBest = 0;
2865 for (
auto& vx2 : slc.
vtxs) {
2866 if (vx2.CTP != inVx2.
CTP)
continue;
2867 if (vx2.ID <= 0)
continue;
2869 if (pull < minPull) {
2883 unsigned short imBest = 0;
2884 for (
auto& oldvx3 : slc.
vtx3s) {
2885 if (oldvx3.ID == 0)
continue;
2888 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)
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)
const geo::WireReadoutGeom * wireReadoutGeom
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)
double WireCoordinate(Point_t const &point) const
Returns the coordinate of the point on the plane, in wire units.
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 the physical 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)
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.
bool WireIDsIntersect(WireID const &wid1, WireID const &wid2, Point_t &intersection) const
Computes the intersection between two wires.
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)
unsigned short CloseEnd(const Trajectory &tj, const Point2_t &pos)
PlaneGeo const & Plane(TPCID const &tpcid, View_t view) const
Returns the specified wire.
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)
Interface to geometry for wire readouts .
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)