22 if(tjs.
allTraj.size() < 2)
return;
25 constexpr
float maxSep = 4;
30 mf::LogVerbatim(
"TC")<<
"MakeJunkVertices: prt set for plane "<<planeID.
Plane<<
" maxSep btw tjs "<<maxSep;
41 junkVx.
ID = USHRT_MAX;
45 junkVx.
PosErr = {{2.0, 2.0}};
50 for(
unsigned short it1 = 0; it1 < tjs.
allTraj.size() - 1; ++it1) {
52 if(tj1.AlgMod[
kKilled])
continue;
53 if(tj1.SSID > 0 || tj1.AlgMod[
kShowerLike])
continue;
54 if(tj1.CTP != inCTP)
continue;
55 if(tj1.AlgMod[
kJunkTj])
continue;
57 if(tj1.MCSMom < 100)
continue;
58 for(
unsigned short end1 = 0; end1 < 2; ++end1) {
60 if(tj1.VtxID[end1] > 0)
continue;
61 auto& tp1 = tj1.Pts[tj1.EndPt[end1]];
64 if(tjlist.empty())
continue;
66 junkVx.
ID = USHRT_MAX;
67 for(
auto tj2id : tjlist) {
68 auto& tj2 = tjs.
allTraj[tj2id - 1];
69 if(tj2.CTP != inCTP)
continue;
70 if(tj2id == tj1.ID)
continue;
71 if(tj2.SSID > 0 || tj2.AlgMod[
kShowerLike])
continue;
73 unsigned short closeEnd = USHRT_MAX;
74 for(
unsigned short end2 = 0; end2 < 2; ++end2) {
75 auto& tp2 = tj2.Pts[tj2.EndPt[end2]];
76 float sep =
PosSep(tp1.Pos, tp2.Pos);
82 if(closeEnd > 1)
continue;
83 auto& tp2 = tj2.Pts[tj2.EndPt[closeEnd]];
85 if(!signalBetween)
continue;
86 if(junkVx.
ID == USHRT_MAX) {
88 junkVx.
ID = tjs.
vtx.size() + 1;
91 tj2.VtxID[closeEnd] = junkVx.
ID;
92 tj1.VtxID[end1] = junkVx.
ID;
94 if(junkVx.
ID == USHRT_MAX)
continue;
98 if(tj.AlgMod[
kKilled])
continue;
99 if(tj.VtxID[0] == junkVx.
ID) tj.VtxID[0] = 0;
100 if(tj.VtxID[1] == junkVx.
ID) tj.VtxID[1] = 0;
107 junkVx.
ID = USHRT_MAX;
135 if(tjs.
allTraj.size() < 2)
return;
146 for(
unsigned short it1 = 0; it1 < tjs.
allTraj.size() - 1; ++it1) {
148 if(tj1.AlgMod[
kKilled])
continue;
149 if(tj1.SSID > 0 || tj1.AlgMod[
kShowerLike])
continue;
150 if(tj1.CTP != inCTP)
continue;
151 bool tj1Short = (
TrajLength(tj1) < maxShortTjLen);
152 for(
unsigned short end1 = 0; end1 < 2; ++end1) {
154 if(tj1.VtxID[end1] > 0)
continue;
157 short endPt1 = tj1.EndPt[end1];
158 float wire1 = tj1.Pts[endPt1].Pos[0];
162 if(tj1.Pts.size() > 6 && tj1.Pts[endPt1].NTPsFit < 4) {
163 if(end1 == 0 && endPt1 <
int(tj1.Pts.size()) - 3) {
165 }
else if (end1 == 1 && endPt1 >=3 ) {
174 endPt1 = tj1.EndPt[end1];
175 short oendPt1 = tj1.EndPt[1-end1];
177 auto& otp1 = tj1.Pts[oendPt1];
178 for(
unsigned short it2 = it1 + 1; it2 < tjs.
allTraj.size(); ++it2) {
180 if(tj2.AlgMod[
kKilled])
continue;
181 if(tj2.SSID > 0 || tj2.AlgMod[
kShowerLike])
continue;
182 if(tj2.CTP != inCTP)
continue;
183 if(tj1.VtxID[end1] > 0)
continue;
185 bool tj2Short = (
TrajLength(tj2) < maxShortTjLen);
187 unsigned short end2 = 0;
188 if(
PosSep2(tj2.Pts[tj2.EndPt[1]].Pos, tp1.
Pos) <
PosSep2(tj2.Pts[tj2.EndPt[0]].Pos, tp1.
Pos)) end2 = 1;
189 if(tj2.VtxID[end2] > 0)
continue;
191 if(tj1.VtxID[1 - end1] > 0 && tj1.VtxID[1 - end1] == tj2.VtxID[1 - end2])
continue;
193 unsigned short oendPt2 = tj2.EndPt[1-end2];
194 auto& otp2 = tj2.Pts[oendPt2];
195 if(
PosSep2(otp1.Pos, otp2.Pos) <
PosSep2(tp1.
Pos, tj2.Pts[tj2.EndPt[end2]].Pos))
continue;
196 short endPt2 = tj2.EndPt[end2];
197 float wire2 = tj2.Pts[endPt2].Pos[0];
198 if(tj2.Pts.size() > 6 && tj2.Pts[endPt2].NTPsFit < 4) {
199 if(end2 == 0 && endPt2 <
int(tj2.Pts.size()) - 3) {
201 }
else if (end2 == 1 && endPt2 >= 3){
209 endPt2 = tj2.EndPt[end2];
213 if(std::abs(tp1.
Pos[0] - tp2.
Pos[0]) > sepCut)
continue;
214 if(std::abs(tp1.
Pos[1] - tp2.
Pos[1]) > sepCut)
continue;
218 if(wint < 0 || wint > tjs.
MaxPos0[planeID.
Plane])
continue;
219 if(tint < 0 || tint > tjs.
MaxPos1[planeID.
Plane])
continue;
230 if(prt && vt1Sep < 200 && vt2Sep < 200) {
232 myprt<<
"F2DV candidate T"<<tj1.ID<<
"_"<<end1<<
"-T"<<tj2.ID<<
"_"<<end2;
234 myprt<<
" dwc1 "<<dwc1<<
" dwc2 "<<dwc2<<
" on dead wire? "<<vtxOnDeadWire;
235 myprt<<
" vt1Sep "<<vt1Sep<<
" vt2Sep "<<vt2Sep<<
" sepCut "<<sepCut;
237 if(vt1Sep > sepCut || vt2Sep > sepCut)
continue;
239 if(
PosSep(vPos, tjs.
allTraj[it1].Pts[oendPt1].Pos) < vt1Sep) {
243 if(
PosSep(vPos, tjs.
allTraj[it2].Pts[oendPt2].Pos) < vt2Sep) {
248 unsigned short closePt1;
249 float doca1 = sepCut;
252 short dpt1 = tjs.
StepDir * (closePt1 - endPt1);
253 if(prt)
mf::LogVerbatim(
"TC")<<
" endPt1 "<<endPt1<<
" closePt1 "<<closePt1<<
" dpt1 "<<dpt1<<
" doca1 "<<doca1;
255 if(dpt1 < -1)
continue;
256 if(tjs.
allTraj[it1].EndPt[1] > 4) {
257 if(dpt1 > 3)
continue;
260 if(dpt1 > 2)
continue;
262 unsigned short closePt2;
263 float doca2 = sepCut;
265 short dpt2 = tjs.
StepDir * (closePt2 - endPt2);
266 if(prt)
mf::LogVerbatim(
"TC")<<
" endPt2 "<<endPt2<<
" closePt2 "<<closePt2<<
" dpt2 "<<dpt2<<
" doca2 "<<doca2;
268 if(dpt2 < -1)
continue;
269 if(tjs.
allTraj[it2].EndPt[1] > 4) {
270 if(dpt2 > 3)
continue;
273 if(dpt2 > 2)
continue;
277 bool signalBetween =
true;
278 bool fixVxPos =
false;
279 short dpt = abs(wint - tp1.
Pos[0]);
282 signalBetween =
false;
284 dpt = abs(wint - tp2.
Pos[0]);
287 signalBetween =
false;
292 unsigned short ipt1, ipt2;
294 bool isClose =
TrajTrajDOCA(tjs, tj1, tj2, ipt1, ipt2, maxSep,
false);
295 if(prt)
mf::LogVerbatim(
"TC")<<
" TrajTrajDOCA close? "<<isClose<<
" minSep "<<maxSep;
318 aVtx.
Pass = tj1.Pass;
320 aVtx.
Topo = 2 * end1;
329 unsigned short newVtxID = tjs.
vtx.size() + 1;
331 tj1.VtxID[end1] = newVtxID;
332 tj2.VtxID[end2] = newVtxID;
340 if(mergeMeWithVx > 0 &&
MergeWithVertex(tjs, aVtx, mergeMeWithVx, prt)) {
341 if(prt)
mf::LogVerbatim(
"TC")<<
" Merged with close vertex "<<mergeMeWithVx;
348 myprt<<
" New vtx 2V"<<aVtx.
ID;
349 myprt<<
" Tjs "<<tj1.ID<<
"_"<<end1<<
"-"<<tj2.ID<<
"_"<<end2;
350 myprt<<
" at "<<std::fixed<<std::setprecision(1)<<aVtx.
Pos[0]<<
":"<<aVtx.
Pos[1]/tjs.
UnitsPerTick;
375 if(tjs.
pfps.size() < 2)
return;
388 std::vector<CandVx> candVxs;
390 for(
unsigned short ip1 = 0; ip1 < tjs.
pfps.size() - 1; ++ip1) {
391 auto& p1 = tjs.
pfps[ip1];
392 if(p1.ID == 0)
continue;
393 if(p1.Tp3s.empty())
continue;
394 if(p1.TPCID != tpcid)
continue;
395 float len1 =
PosSep(p1.XYZ[0], p1.XYZ[1]);
397 for(
unsigned short end1 = 0; end1 < 2; ++end1) {
400 for(
unsigned short ip2 = ip1 + 1; ip2 < tjs.
pfps.size(); ++ip2) {
401 auto& p2 = tjs.
pfps[ip2];
402 if(p2.ID == 0)
continue;
403 if(p2.Tp3s.empty())
continue;
404 if(p2.TPCID != tpcid)
continue;
405 float len2 =
PosSep(p2.XYZ[0], p2.XYZ[1]);
407 for(
unsigned short end2 = 0; end2 < 2; ++end2) {
412 if(!
PointDirIntersect(p1.XYZ[end1], p1.Dir[end1], p2.XYZ[end2], p2.Dir[end2], intersect, vxDOCA))
continue;
413 if(intersect[0] < tjs.
XLo || intersect[0] > tjs.
XHi)
continue;
414 if(intersect[1] < tjs.
YLo || intersect[1] > tjs.
YHi)
continue;
415 if(intersect[2] < tjs.
ZLo || intersect[2] > tjs.
ZHi)
continue;
417 float sep1 =
PosSep(intersect, p1.XYZ[end1]);
418 if(
PosSep(intersect, p1.XYZ[1-end1]) < sep1)
continue;
419 float sep2 =
PosSep(intersect, p2.XYZ[end2]);
420 if(
PosSep(intersect, p2.XYZ[1-end2]) < sep2)
continue;
433 myprt<<
"FNV: P"<<p1.ID<<
"_"<<end1<<
" sep1 "<<std::fixed<<std::setprecision(2)<<sep1;
434 myprt<<
" cfne1 "<<cfne1<<
" cfb1 "<<cfb1;
435 myprt<<
" P"<<p2.ID<<
"_"<<end2<<
" sep2 "<<sep2<<
" cfne2 "<<cfne2<<
" cfb2 "<<cfb2;
436 myprt<<
" intersect "<<intersect[0]<<
" "<<intersect[1]<<
" "<<intersect[2];
437 myprt<<
" vxDOCA "<<vxDOCA;
442 float sepSum = sep1 + sep2;
444 for(
auto& candVx : candVxs) {
445 if(!candVx.isValid)
continue;
446 if(candVx.ip1 != ip1 && candVx.ip2 != ip2)
continue;
448 if(sepSum < candVx.sepSum) {
450 candVx.isValid =
false;
462 candVx.intersect = intersect;
463 candVx.sepSum = sep1 + sep2;
464 candVx.isValid =
true;
465 candVxs.push_back(candVx);
472 if(candVxs.empty())
return;
475 for(
auto& candVx : candVxs) {
476 if(!candVx.isValid)
continue;
478 auto& p1 = tjs.
pfps[candVx.ip1];
479 auto& p2 = tjs.
pfps[candVx.ip2];
481 vx3.
ID = tjs.
vtx3.size() + 1;
483 std::vector<TrajPoint> vxTps;
485 for(
unsigned short plane = 0; plane < tjs.
NumPlanes; ++plane) {
489 auto vtp =
MakeBareTP(tjs, candVx.intersect, dir, inCTP);
490 if(vtp.Pos[0] < 0)
continue;
491 for(
auto tid : p1.TjIDs) {
492 auto& tj = tjs.
allTraj[tid - 1];
493 if(tj.CTP != vtp.CTP)
continue;
495 auto vxTp = tj.Pts[tj.EndPt[
end]];
497 vxTp.AngleCode =
end;
498 vxTps.push_back(vxTp);
500 for(
auto tid : p2.TjIDs) {
501 auto& tj = tjs.
allTraj[tid - 1];
502 if(tj.CTP != vtp.CTP)
continue;
504 auto vxTp = tj.Pts[tj.EndPt[
end]];
506 vxTp.AngleCode =
end;
507 vxTps.push_back(vxTp);
509 if(vxTps.size() < 2)
continue;
517 vx2.
ID = tjs.
vtx.size() + 1;
518 for(
auto& vxTp : vxTps) {
520 auto& tj = tjs.
allTraj[tid - 1];
521 tj.VtxID[vxTp.AngleCode] = vx2.
ID;
532 vx3.
X = candVx.intersect[0];
533 vx3.
Y = candVx.intersect[1];
534 vx3.
Z = candVx.intersect[2];
537 tjs.
vtx3.push_back(vx3);
538 if(prt)
mf::LogVerbatim(
"TC")<<
"FNV: P"<<p1.ID<<
"_"<<candVx.end1<<
" P"<<p2.ID<<
"_"<<candVx.end2<<
" -> 3V"<<vx3.
ID;
554 if(oVxID > tjs.
vtx.size())
return false;
555 auto& oVx = tjs.
vtx[oVxID - 1];
556 if(vx.
CTP != oVx.CTP)
return false;
561 if(tjlist.empty())
return false;
564 if(tmp.empty())
return false;
565 for(
auto tjid : tmp) {
566 if(std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end()) tjlist.push_back(tjid);
568 if(tjlist.size() < 2)
return false;
570 if(tjlist.size() == 2) {
575 for(
auto tjid : tjlist) {
576 auto& tj = tjs.
allTraj[tjid - 1];
577 for(
unsigned short end = 0;
end < 2; ++
end) {
578 if(tj.VtxID[
end] == vx.
ID) tj.VtxID[
end] = oVx.ID;
582 if(prt)
mf::LogVerbatim(
"TC")<<
"MWV: merge failed "<<vx.
ID<<
" and existing "<<oVx.ID;
589 std::vector<SortEntry> sortVec(tjlist.size());
590 for(
unsigned int indx = 0; indx < sortVec.size(); ++indx) {
591 sortVec[indx].index = indx;
592 auto& tj = tjs.
allTraj[tjlist[indx] - 1];
593 sortVec[indx].val = tj.Pts.size();
598 for(
unsigned short ii = 0; ii < sortVec.size(); ++ii) tjlist[ii] = ttl[sortVec[ii].
index];
603 std::vector<TrajPoint> tjpts(tjlist.size());
607 std::array<float, 2> vpos;
608 vpos[0] = 0.5 * (vx.
Pos[0] + oVx.Pos[0]);
609 vpos[1] = 0.5 * (vx.
Pos[1] + oVx.Pos[1]);
610 for(
unsigned short ii = 0; ii < tjpts.size(); ++ii) {
611 auto& tj = tjs.
allTraj[tjlist[ii] - 1];
615 unsigned short endPt = tj.EndPt[
end];
616 if(npwc > 6 && tj.Pts[endPt].NTPsFit < 4) {
624 if(endPt < tj.EndPt[0]) endPt = tj.EndPt[0];
625 if(endPt > tj.EndPt[1]) endPt = tj.EndPt[1];
627 tjpts[ii].CTP = tj.CTP;
628 tjpts[ii].Pos = tj.Pts[endPt].Pos;
629 tjpts[ii].Dir = tj.Pts[endPt].Dir;
630 tjpts[ii].Ang = tj.Pts[endPt].Ang;
631 tjpts[ii].AngErr = tj.Pts[endPt].AngErr;
633 tjpts[ii].Step = endPt;
635 tjpts[ii].AngleCode =
end;
637 tjpts[ii].Hits.resize(1, tj.ID);
641 myprt<<
"MWV: "<<oVxID;
643 for(
unsigned short ii = 0; ii < tjpts.size(); ++ii) {
644 auto& tjpt = tjpts[ii];
645 myprt<<
" "<<tjlist[ii]<<
"_"<<tjpt.Step<<
"_"<<
PrintPos(tjs, tjpt.Pos);
656 bool needsUpdate =
false;
657 for(
unsigned short ii = 2; ii < tjlist.size(); ++ii) {
658 fitpts.push_back(tjpts[ii]);
668 if(needsUpdate)
FitVertex(tjs, aVx, fitpts, prt);
673 if(tj.AlgMod[
kKilled])
continue;
674 if(tj.CTP != vx.
CTP)
continue;
675 for(
unsigned short end = 0;
end < 2; ++
end) {
676 if(tj.VtxID[
end] == vx.
ID) tj.VtxID[
end] = 0;
677 if(tj.VtxID[
end] == oVxID) tj.VtxID[
end] = 0;
681 for(
unsigned short ii = 0; ii < fitpts.size(); ++ii) {
682 auto& tjpt = fitpts[ii];
683 unsigned short end = tjpt.AngleCode;
684 auto& tj = tjs.
allTraj[tjpt.Hits[0] - 1];
685 if(tj.VtxID[end] != 0) {
686 std::cout<<
"MWV: coding error. tj "<<tj.ID<<
" end "<<end<<
" VtxID "<<tj.VtxID[
end]<<
" != 0\n";
689 tj.VtxID[
end] = oVxID;
696 oVx.NTraj = fitpts.size();
703 myprt<<
"MWV: "<<oVxID;
705 for(
unsigned short ii = 0; ii < fitpts.size(); ++ii) {
706 auto& tjpt = fitpts[ii];
707 myprt<<
" "<<tjpt.Hits[0]<<
"_"<<tjpt.AngleCode<<
"_"<<
PrintPos(tjs, tjpt.Pos);
721 for(
unsigned short ivx = 0; ivx < tjs.
vtx.size(); ++ivx) {
722 auto& vx2 = tjs.
vtx[ivx];
723 if(vx2.ID == 0)
continue;
724 if(vx2.CTP != inCTP)
continue;
725 auto vxtjs =
GetAssns(tjs,
"2V", vx2.ID,
"T");
726 if(vxtjs.size() < 2)
continue;
731 unsigned short closeEnd = 0;
732 for(
auto tid : vxtjs) {
733 auto& tj = tjs.
allTraj[tid - 1];
734 unsigned short nearEnd = 1 -
FarEnd(tjs, tj, vx2.Pos);
735 if(tj.VtxID[nearEnd] != vx2.ID)
continue;
736 float sep =
PosSep(tj.Pts[tj.EndPt[nearEnd]].Pos, vx2.Pos);
737 if(sep > close)
continue;
742 if(close > 1.5 && closeID > 0) {
743 auto& closeTj = tjs.
allTraj[closeID - 1];
744 auto& closeTP = closeTj.Pts[closeTj.EndPt[closeEnd]];
746 vx2.Pos = closeTP.Pos;
749 for(
unsigned short it1 = 0; it1 < vxtjs.size() - 1; ++it1) {
750 auto& tj1 = tjs.
allTraj[vxtjs[it1] - 1];
751 if(tj1.AlgMod[
kKilled])
continue;
752 unsigned short end1 = 0;
753 if(tj1.VtxID[1] == vx2.ID) end1 = 1;
754 auto& vtp1 = tj1.Pts[tj1.EndPt[end1]];
755 auto& otp1 = tj1.Pts[tj1.EndPt[1 - end1]];
756 float tj1sep =
PosSep(vtp1.Pos, vx2.Pos);
757 for(
unsigned short it2 = it1 + 1; it2 < vxtjs.size(); ++it2) {
758 auto& tj2 = tjs.
allTraj[vxtjs[it2] - 1];
759 if(tj2.AlgMod[
kKilled])
continue;
760 unsigned short end2 = 0;
761 if(tj2.VtxID[2] == vx2.ID) end2 = 1;
762 auto& vtp2 = tj2.Pts[tj2.EndPt[end2]];
763 auto& otp2 = tj2.Pts[tj2.EndPt[1 - end2]];
764 float tj2sep =
PosSep(vtp2.Pos, vx2.Pos);
765 float otj1tj2 =
PosSep(otp1.Pos, vtp2.Pos);
766 float delta12 =
PointTrajDOCA(tjs, otp1.Pos[0], otp1.Pos[1], vtp2);
767 float dang12 =
DeltaAngle(otp1.Ang, vtp2.Ang);
768 if(otj1tj2 < tj2sep && delta12 < 1 && otj1tj2 < 4) {
771 myprt<<
"CVTjs: "<<vx2.ID<<
" tj1 "<<tj1.ID<<
" tj2 "<<tj2.ID;
772 myprt<<
" otj1tj2 "<<otj1tj2;
773 myprt<<
" delta12 "<<delta12;
774 myprt<<
" dang12 "<<dang12;
775 myprt<<
" Try to merge";
782 if(prt)
mf::LogVerbatim(
"TC")<<
"CVTjs: Merged tjs "<<tj1.ID<<
" and "<<tj2.ID<<
" -> "<<newTj.ID;
789 float tj1otj2 =
PosSep(vtp1.Pos, otp2.Pos);
790 if(tj1otj2 < tj1sep && delta12 < 1 && tj1otj2 < 4) {
796 if(prt)
mf::LogVerbatim(
"TC")<<
"CVTjs: Merged tjs "<<tj1.ID<<
" and "<<tj2.ID<<
" -> "<<newTj.ID;
804 if(vx2.Topo == 1 && vxtjs.size() == 2) {
805 auto& tj1 = tjs.
allTraj[vxtjs[0] - 1];
806 auto& tj2 = tjs.
allTraj[vxtjs[1] - 1];
836 for(
unsigned short it1 = 0; it1 < tjs.
allTraj.size(); ++it1) {
837 if(tjs.
allTraj[it1].CTP != inCTP)
continue;
843 if(numPtsWithCharge1 < 6)
continue;
845 bool didaSplit =
false;
846 for(
unsigned short end1 = 0; end1 < 2; ++end1) {
848 if(tjs.
allTraj[it1].VtxID[end1] > 0)
continue;
849 unsigned short endPt1 = tjs.
allTraj[it1].EndPt[end1];
850 for(
unsigned short it2 = 0; it2 < tjs.
allTraj.size(); ++it2) {
851 if(it1 == it2)
continue;
852 if(tjs.
allTraj[it2].AlgMod[kKilled])
continue;
853 if(tjs.
allTraj[it2].AlgMod[kHamVx])
continue;
854 if(tjs.
allTraj[it2].AlgMod[kHamVx2])
continue;
856 if(tjs.
allTraj[it2].CTP != inCTP)
continue;
858 if(tjs.
allTraj[it2].AlgMod[kJunkTj])
continue;
860 if(numPtsWithCharge2 < 6)
continue;
868 float doca = minDOCA;
869 unsigned short closePt2 = 0;
871 if(doca == minDOCA)
continue;
876 myprt<<
" FHV2 CTP"<<tj1.CTP;
877 myprt<<
" T"<<tj1.ID<<
"_"<<end1<<
" MCSMom "<<tj1.MCSMom<<
" ChgRMS "<<tj1.ChgRMS;
878 myprt<<
" split T"<<tj2.ID<<
"? MCSMom "<<tj2.MCSMom<<
" ChgRMS "<<tj2.ChgRMS;
879 myprt<<
" doca "<<doca<<
" tj2.EndPt[0] "<<tj2.EndPt[0]<<
" closePt2 "<<closePt2;
880 myprt<<
" tj2.EndPt[1] "<<tj2.EndPt[1];
883 if(closePt2 < tjs.
allTraj[it2].EndPt[0] + 3)
continue;
884 if(closePt2 > tjs.
allTraj[it2].EndPt[1] - 3)
continue;
890 if(dang < 0.2)
continue;
893 unsigned short closePt1 = 0;
895 if(closePt1 != endPt1)
continue;
900 unsigned short intPt2;
903 if(doca == minDOCA)
continue;
905 float mcsmom = tjs.
allTraj[it2].MCSMom;
909 if(prt)
mf::LogVerbatim(
"TC")<<
" Check MCSMom after split: mcsmom1 "<<mcsmom1<<
" mcsmom2 "<<mcsmom2;
910 if(mcsmom1 < mcsmom || mcsmom2 < mcsmom)
continue;
914 if(intPt2 < closePt2) dir = -1;
915 unsigned short nit = 0;
916 unsigned short ipt = intPt2;
917 float mostChg = tjs.
allTraj[it2].Pts[ipt].Chg;
921 if(ipt < 3 || ipt > tjs.
allTraj[it2].Pts.size() - 4)
break;
924 float dang = delta / sep;
925 float pull = dang / tjs.
allTraj[it1].Pts[endPt1].DeltaRMS;
927 if(pull < 2 && tjs.
allTraj[it2].Pts[ipt].Chg > mostChg) {
928 mostChg = tjs.
allTraj[it2].Pts[ipt].Chg;
933 float chgPull = (mostChg - tjs.
allTraj[it2].AveChg) / tjs.
allTraj[it2].ChgRMS;
934 if(prt)
mf::LogVerbatim(
"TC")<<
" chgPull at intersection point "<<chgPull;
935 if(chgPull < 10)
continue;
938 if(tjs.
allTraj[it1].Pts[endPt1].Pos[0] < -0.4)
continue;
939 unsigned int fromWire = std::nearbyint(tjs.
allTraj[it1].Pts[endPt1].Pos[0]);
940 if(tjs.
allTraj[it2].Pts[intPt2].Pos[0] < -0.4)
continue;
941 unsigned int toWire = std::nearbyint(tjs.
allTraj[it2].Pts[intPt2].Pos[0]);
942 if(fromWire > toWire) {
943 unsigned int tmp = fromWire;
948 for(
unsigned int wire = fromWire + 1; wire < toWire; ++wire) {
965 aVtx.
ID = tjs.
vtx.size() + 1;
966 unsigned short ivx = tjs.
vtx.size();
968 if(!
SplitTraj(tjs, it2, intPt2, ivx, prt)) {
974 tjs.
allTraj[it1].VtxID[end1] = tjs.
vtx[ivx].ID;
977 unsigned short newTjIndex = tjs.
allTraj.size() - 1;
1010 for(
unsigned short it1 = 0; it1 < tjs.
allTraj.size(); ++it1) {
1011 if(tjs.
allTraj[it1].CTP != inCTP)
continue;
1016 unsigned short tj1len = tjs.
allTraj[it1].EndPt[1] - tjs.
allTraj[it1].EndPt[0];
1017 if(tj1len < 6)
continue;
1019 bool didaSplit =
false;
1020 for(
unsigned short end1 = 0; end1 < 2; ++end1) {
1022 if(tjs.
allTraj[it1].VtxID[end1] > 0)
continue;
1023 unsigned short endPt1 = tjs.
allTraj[it1].EndPt[end1];
1024 for(
unsigned short it2 = 0; it2 < tjs.
allTraj.size(); ++it2) {
1025 if(tjs.
allTraj[it2].CTP != inCTP)
continue;
1026 if(it1 == it2)
continue;
1027 if(tjs.
allTraj[it2].AlgMod[kKilled])
continue;
1028 if(tjs.
allTraj[it2].AlgMod[kJunkTj])
continue;
1030 unsigned short tj2len = tjs.
allTraj[it2].EndPt[1] - tjs.
allTraj[it2].EndPt[0];
1031 if(tj2len < 10)
continue;
1033 if(tj1len < 0.5 * tj2len)
continue;
1035 unsigned short end20 = tjs.
allTraj[it2].EndPt[0];
1036 unsigned short end21 = tjs.
allTraj[it2].EndPt[1];
1039 if(tjs.
allTraj[it2].VtxID[0] > 0 || tjs.
allTraj[it2].VtxID[1] > 0)
continue;
1041 float doca = minDOCA;
1042 unsigned short closePt2 = 0;
1044 if(doca == minDOCA)
continue;
1046 if(prt)
mf::LogVerbatim(
"TC")<<
"FindHammerVertices: Candidate "<<tjs.
allTraj[it1].ID<<
" "<<tjs.
allTraj[it2].ID<<
" doca "<<doca<<
" tj2.EndPt[0] "<<tjs.
allTraj[it2].EndPt[0]<<
" closePt2 "<<closePt2<<
" tj2.EndPt[1] "<<tjs.
allTraj[it2].EndPt[1];
1047 if(closePt2 < tjs.
allTraj[it2].EndPt[0] + 3)
continue;
1048 if(closePt2 > tjs.
allTraj[it2].EndPt[1] - 3)
continue;
1051 if(prt)
mf::LogVerbatim(
"TC")<<
" dang "<<dang<<
" imposing a hard cut of 0.4 for now ";
1052 if(dang < 0.4)
continue;
1056 aVtx.
Pos = tjs.
allTraj[it2].Pts[closePt2].Pos;
1062 aVtx.
ID = tjs.
vtx.size() + 1;
1063 unsigned short ivx = tjs.
vtx.size();
1065 if(!
SplitTraj(tjs, it2, closePt2, ivx, prt)) {
1066 if(prt)
mf::LogVerbatim(
"TC")<<
"FindHammerVertices: Failed to split trajectory";
1070 tjs.
allTraj[it1].VtxID[end1] = tjs.
vtx[ivx].ID;
1073 unsigned short newTjIndex = tjs.
allTraj.size() - 1;
1084 if(didaSplit)
break;
1097 if(tjs.
vtx.empty())
return;
1098 if(tjs.
allTraj.empty())
return;
1100 constexpr
float docaCut = 4;
1103 if(prt)
mf::LogVerbatim(
"TC")<<
"Inside SplitTrajCrossingVertices inCTP "<<inCTP;
1107 unsigned short nTraj = tjs.
allTraj.size();
1108 for(
unsigned short itj = 0; itj < nTraj; ++itj) {
1111 if(tjs.
allTraj[itj].CTP != inCTP)
continue;
1116 if(tjs.
allTraj[itj].EndPt[1] < 6)
continue;
1117 for(
unsigned short iv = 0; iv < tjs.
vtx.size(); ++iv) {
1118 auto& vx2 = tjs.
vtx[iv];
1120 if(vx2.NTraj == 0)
continue;
1122 if(tjs.
allTraj[itj].VtxID[0] == vx2.ID ||
1123 tjs.
allTraj[itj].VtxID[1] == vx2.ID)
continue;
1125 if(tjs.
allTraj[itj].CTP != vx2.CTP)
continue;
1128 float doca = docaCut;
1132 unsigned short closePt = 0;
1139 if(doca > docaCut)
continue;
1140 if(prt)
mf::LogVerbatim(
"TC")<<
" doca "<<doca<<
" btw T"<<tjs.
allTraj[itj].ID<<
" and 2V"<<tjs.
vtx[iv].ID<<
" closePt "<<closePt<<
" in plane "<<planeID.
Plane;
1145 if(vxtjs.empty())
continue;
1146 unsigned short maxPts = 0;
1150 float tjAng = tjs.
allTraj[itj].Pts[closePt].Ang;
1151 for(
auto tjid : vxtjs) {
1152 auto& vtj = tjs.
allTraj[tjid - 1];
1155 if(npwc > maxPts) maxPts = npwc;
1156 unsigned short end = 0;
1157 if(vtj.VtxID[1] == tjs.
vtx[iv].ID) end = 1;
1158 auto& vtp = vtj.Pts[vtj.EndPt[
end]];
1160 if(dang > maxdang) maxdang = dang;
1164 bool skipit =
false;
1166 if(!skipit && maxdang < tjs.
KinkCuts[0]) skipit =
true;
1167 if(prt)
mf::LogVerbatim(
"TC")<<
" maxPts "<<maxPts<<
" vxtjs[0] "<<vxtjs[0]<<
" maxdang "<<maxdang<<
" skipit? "<<skipit;
1178 auto& closeTP = tjs.
allTraj[itj].Pts[closePt];
1179 if(tjs.
allTraj[itj].StepDir > 0 && closePt > tjs.
allTraj[itj].EndPt[0]) {
1180 if(closeTP.Pos[0] > vx2.Pos[0]) --closePt;
1181 }
else if(tjs.
allTraj[itj].StepDir < 0 && closePt < tjs.
allTraj[itj].EndPt[1]) {
1182 if(closeTP.Pos[0] < vx2.Pos[0]) ++closePt;
1188 if ((tjs.
allTraj[itj].Pts[closePt].Pos[0]-vx2.Pos[0])*(tjs.
allTraj[itj].Pts[tjs.
allTraj[itj].EndPt[1]].Pos[0]-vx2.Pos[0]) + (tjs.
allTraj[itj].Pts[closePt].Pos[1]-vx2.Pos[1])*(tjs.
allTraj[itj].Pts[tjs.
allTraj[itj].EndPt[1]].Pos[1]-vx2.Pos[1]) <0 && closePt < tjs.
allTraj[itj].EndPt[1] - 1) ++closePt;
1189 else if ((tjs.
allTraj[itj].Pts[closePt].Pos[0]-vx2.Pos[0])*(tjs.
allTraj[itj].Pts[tjs.
allTraj[itj].EndPt[0]].Pos[0]-vx2.Pos[0]) + (tjs.
allTraj[itj].Pts[closePt].Pos[1]-vx2.Pos[1])*(tjs.
allTraj[itj].Pts[tjs.
allTraj[itj].EndPt[0]].Pos[1]-tjs.
vtx[iv].Pos[1]) <0 && closePt > tjs.
allTraj[itj].EndPt[0] + 1) --closePt;
1194 mf::LogVerbatim(
"TC")<<
"Good doca "<<doca<<
" btw T"<<tjs.
allTraj[itj].ID<<
" and 2V"<<vx2.ID<<
" closePt "<<closePt<<
" in plane "<<planeID.
Plane<<
" CTP "<<tjs.
vtx[iv].CTP;
1198 if(closePt < tjs.
allTraj[itj].EndPt[0] + 3)
continue;
1199 if(closePt > tjs.
allTraj[itj].EndPt[1] - 3)
continue;
1200 if(!
SplitTraj(tjs, itj, closePt, iv, prt)) {
1201 if(prt)
mf::LogVerbatim(
"TC")<<
"SplitTrajCrossingVertices: Failed to split trajectory";
1205 unsigned short newTjIndex = tjs.
allTraj.size() - 1;
1222 if(tjs.
vtx.size() < 2)
return;
1224 const unsigned int cstat = tpcid.
Cryostat;
1225 const unsigned int tpc = tpcid.
TPC;
1228 std::vector<std::vector<unsigned short>> vIndex(3);
1229 for(
unsigned short ivx = 0; ivx < tjs.
vtx.size(); ++ivx) {
1231 if(tjs.
vtx[ivx].ID == 0)
continue;
1233 if(planeID.
TPC != tpc || planeID.
Cryostat != cstat)
continue;
1234 unsigned short plane = planeID.
Plane;
1235 if(plane > 2)
continue;
1236 vIndex[plane].push_back(ivx);
1239 unsigned short vtxInPln = 0;
1240 for(
unsigned short plane = 0; plane < tjs.
NumPlanes; ++plane)
if(vIndex[plane].size() > 0) ++vtxInPln;
1241 if(vtxInPln < 2)
return;
1255 size_t vsize = tjs.
vtx.size();
1257 std::vector<short> vPtr(vsize, -1);
1259 std::vector<float> vX(vsize, -100);
1261 for(
unsigned short ivx = 0; ivx < vsize; ++ivx) {
1262 if(tjs.
vtx[ivx].ID == 0)
continue;
1264 if(planeID.
TPC != tpc || planeID.
Cryostat != cstat)
continue;
1265 int plane = planeID.
Plane;
1266 if(tjs.
vtx[ivx].Pos[0] < -0.4)
continue;
1267 unsigned int wire = std::nearbyint(tjs.
vtx[ivx].Pos[0]);
1275 std::vector<Vtx3Store> v3temp;
1279 constexpr
float maxSep = 4;
1282 for(
unsigned short ipl = 0; ipl < 2; ++ipl) {
1283 for(
unsigned short ii = 0; ii < vIndex[ipl].size(); ++ii) {
1284 unsigned short ivx = vIndex[ipl][ii];
1285 if(vX[ivx] < 0)
continue;
1286 auto& ivx2 = tjs.
vtx[ivx];
1287 if(ivx2.Pos[0] < -0.4)
continue;
1288 unsigned int iWire = std::nearbyint(ivx2.Pos[0]);
1289 for(
unsigned short jpl = ipl + 1; jpl < 3; ++jpl) {
1290 for(
unsigned short jj = 0; jj < vIndex[jpl].size(); ++jj) {
1291 unsigned short jvx = vIndex[jpl][jj];
1292 if(vX[jvx] < 0)
continue;
1293 auto& jvx2 = tjs.
vtx[jvx];
1294 if(jvx2.Pos[0] < -0.4)
continue;
1295 unsigned int jWire = std::nearbyint(jvx2.Pos[0]);
1296 float dX = std::abs(vX[ivx] - vX[jvx]);
1299 mf::LogVerbatim(
"TC")<<
"F3DV: ipl "<<ipl<<
" i2V"<<ivx2.ID<<
" iX "<<vX[ivx]
1300 <<
" jpl "<<jpl<<
" j2V"<<jvx2.ID<<
" jvX "<<vX[jvx]<<
" W:T "<<(int)jvx2.Pos[0]<<
":"<<(
int)jvx2.Pos[1]<<
" dX "<<dX;
1302 double y = -1000,
z = -1000;
1304 if(y < tjs.YLo || y > tjs.
YHi || z < tjs.ZLo || z > tjs.
ZHi)
continue;
1305 unsigned short kpl = 3 - ipl - jpl;
1306 float kX = 0.5 * (vX[ivx] + vX[jvx]);
1310 if(kWire < 0 || (
unsigned int)kWire > tjs.
NumWires[kpl])
continue;
1312 std::array<int, 2> wireWindow;
1313 std::array<float, 2> timeWindow;
1314 wireWindow[0] = kWire - maxSep;
1315 wireWindow[1] = kWire + maxSep;
1317 timeWindow[0] = time - maxSep;
1318 timeWindow[1] = time + maxSep;
1320 std::vector<unsigned int> closeHits =
FindCloseHits(tjs, wireWindow, timeWindow, kpl,
kAllHits,
true, hitsNear);
1323 myprt<<
" Hits near "<<kpl<<
":"<<kWire<<
":"<<(int)(time/tjs.
UnitsPerTick)<<
" = ";
1324 for(
auto iht : closeHits) myprt<<
" "<<
PrintHit(tjs.
fHits[iht]);
1326 if(!hitsNear)
continue;
1348 v3d.
Vx2ID[ipl] = ivx + 1;
1349 v3d.
Vx2ID[jpl] = jvx + 1;
1353 for(
unsigned short i3t = 0; i3t < v3temp.size(); ++i3t) {
1354 if(v3temp[i3t].Vx2ID[0] == v3d.
Vx2ID[0] && v3temp[i3t].Vx2ID[1] == v3d.
Vx2ID[1] && v3temp[i3t].Vx2ID[2] == v3d.
Vx2ID[2]) {
1369 v3temp.push_back(v3d);
1371 if(prt)
mf::LogVerbatim(
"TC")<<
"F3DV: 2 Plane match i2V"<<tjs.
vtx[ivx].ID<<
" P:W:T "<<ipl<<
":"<<(int)tjs.
vtx[ivx].Pos[0]<<
":"<<(
int)tjs.
vtx[ivx].Pos[1]<<
" j2V"<<tjs.
vtx[jvx].ID<<
" P:W:T "<<jpl<<
":"<<(int)tjs.
vtx[jvx].Pos[0]<<
":"<<(
int)tjs.
vtx[jvx].Pos[1]<<
" dX "<<dX;
1376 for(
unsigned short kk = 0; kk < vIndex[kpl].size(); ++kk) {
1377 unsigned short kvx = vIndex[kpl][kk];
1378 if(vX[kvx] < 0)
continue;
1379 float dX = std::abs(vX[kvx] - v3d.
X);
1381 float dW = wirePitch * std::abs(tjs.
vtx[kvx].Pos[0] - kWire);
1383 if(dX > thirdPlanedXCut)
continue;
1386 double y = -1000,
z = -1000;
1388 v3d.
YErr = y - v3d.
Y;
1390 v3d.
Vx2ID[kpl] = kvx + 1;
1397 v3d.
Score = dX * dX + dY * dY + dZ * dZ;
1398 if(v3d.
Score > maxScore) maxScore = v3d.
Score;
1399 v3temp.push_back(v3d);
1406 if(v3temp.empty())
return;
1411 for(
auto& v3 : v3temp)
if(v3.Wire >= 0) v3.Score += maxScore;
1415 for(
auto& v3 : v3temp) {
1416 mf::LogVerbatim(
"TC")<<v3.Vx2ID[0]<<
" "<<v3.Vx2ID[1]<<
" "<<v3.Vx2ID[2]<<
" wire "<<v3.Wire<<
" "<<v3.Score;
1420 std::vector<SortEntry> sortVec(v3temp.size());
1421 for(
unsigned short ivx = 0; ivx < v3temp.size(); ++ivx) {
1423 sEntry.
val = v3temp[ivx].Score;
1424 sortVec[ivx] = sEntry;
1426 if(sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(),
valIncreasing);
1428 std::vector<Vtx3Store> v3sel;
1429 for(
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
1430 unsigned short ivx = sortVec[ii].
index;
1432 bool skipit =
false;
1433 for(
auto& v3 : v3sel) {
1434 for(
unsigned short ipl = 0; ipl < tjs.
NumPlanes; ++ipl) {
1435 if(v3temp[ivx].Vx2ID[ipl] == 0)
continue;
1436 if(v3temp[ivx].Vx2ID[ipl] == v3.Vx2ID[ipl]) {
1443 if(skipit)
continue;
1444 v3sel.push_back(v3temp[ivx]);
1450 for(
auto& v3d : v3sel) {
1451 mf::LogVerbatim(
"TC")<<v3d.Vx2ID[0]<<
" "<<v3d.Vx2ID[1]<<
" "<<v3d.Vx2ID[2]<<
" wire "<<v3d.Wire<<
" "<<v3d.Score;
1456 unsigned short ninc = 0;
1457 for(
auto& vx3 : v3sel) {
1461 if(vx3.Wire >= 0) ++ninc;
1463 vx3.ID = tjs.
vtx3.size() + 1;
1464 if(prt)
mf::LogVerbatim(
"TC")<<
" 3V"<<vx3.ID<<
" 2V"<<vx3.Vx2ID[0]<<
" 2V"<<vx3.Vx2ID[1]<<
" 2V"<<vx3.Vx2ID[2]
1465 <<
" wire "<<vx3.Wire;
1466 tjs.
vtx3.push_back(vx3);
1468 for(
unsigned short ipl = 0; ipl < tjs.
NumPlanes; ++ipl) {
1469 if(vx3.Vx2ID[ipl] == 0)
continue;
1484 if(tj.AlgMod[
kKilled])
continue;
1486 if(planeID.
TPC != tpc || planeID.
Cryostat != cstat)
continue;
1490 for(
auto& vx2 : tjs.
vtx) {
1491 if(vx2.ID == 0)
continue;
1493 if(planeID.
TPC != tpc || planeID.
Cryostat != cstat)
continue;
1497 for(
auto& vx3 : tjs.
vtx3) {
1498 if(vx3.ID == 0)
continue;
1499 if(vx3.TPCID != tpcid)
continue;
1512 if(tjs.
vtx3.empty())
return;
1516 std::vector<SortEntry> sortVec;
1517 for(
unsigned short iv3 = 0; iv3 < tjs.
vtx3.size(); ++iv3) {
1518 auto& vx3 = tjs.
vtx3[iv3];
1519 if(vx3.ID == 0)
continue;
1520 if(vx3.TPCID != tpcid)
continue;
1524 if(v3TjIDs.empty())
continue;
1536 sortVec.push_back(se);
1538 if(sortVec.empty())
return;
1539 if(sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(),
valDecreasing);
1541 for(
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
1542 auto& vx3 = tjs.
vtx3[sortVec[ii].index];
1544 std::vector<int> v3TjIDs =
GetVtxTjIDs(tjs, vx3, score);
1547 myprt<<
"M3DVTj 3V"<<vx3.ID<<
" score "<<score<<
" Tjs";
1548 for(
auto& tjID : v3TjIDs) myprt<<
" T"<<tjID;
1550 for(
unsigned int ims = 0; ims < tjs.
matchVec.size(); ++ims) {
1552 if(ms.Count == 0)
continue;
1553 bool skipit =
false;
1554 for(
auto tjid : ms.TjIDs) {
1555 auto& tj = tjs.
allTraj[tjid - 1];
1556 if(tj.AlgMod[
kMat3D]) skipit =
true;
1557 if(tj.AlgMod[
kKilled]) skipit =
true;
1559 if(skipit)
continue;
1561 if(shared.size() < 2)
continue;
1562 if(prt)
mf::LogVerbatim(
"TC")<<
" ims "<<ims<<
" shared size "<<shared.size();
1564 pfp.
TjIDs = ms.TjIDs;
1565 pfp.
Vx3ID[0] = vx3.ID;
1568 pfp.
XYZ[0] = ms.Pos;
1569 pfp.
Dir[0] = ms.Dir;
1571 if(prt)
mf::LogVerbatim(
"TC")<<
"M3DVTj: pfp P"<<pfp.
ID<<
" 3V"<<vx3.ID<<
" ims "<<ims;
1575 auto saveTjIDs = pfp.
TjIDs;
1576 if(!
DefinePFP(
"M3DVTj1", tjs, pfp, prt))
continue;
1580 if(prt)
PrintPFP(
"M3D", tjs, pfp,
true);
1581 if(!didSplit && shared.size() != ms.TjIDs.size()) {
1588 if(pfp.
TjIDs != saveTjIDs) {
1593 for(
auto tjid :
tmp) {
1594 auto& tj = tjs.
allTraj[tjid - 1];
1595 if(!tj.AlgMod[
kMat3D]) v3TjIDs.push_back(tjid);
1597 if(v3TjIDs.size() < 2)
break;
1603 if(!mfpfp.empty()) allms.Count = 0;
1609 for(
auto tjid : leftover) myprt<<
" T"<<tjid;
1611 if(leftover.size() < 2)
break;
1615 if(v3TjIDs.size() > 1 && v3TjIDs.size() <= tjs.
NumPlanes) {
1619 for(
auto& tjid : v3TjIDs) {
1620 auto& tj = tjs.
allTraj[tjid - 1];
1621 if(tj.AlgMod[
kMat3D])
continue;
1622 if(tj.AlgMod[
kKilled])
continue;
1623 pfp.
TjIDs.push_back(tjid);
1625 if(pfp.
TjIDs.size() < 2)
continue;
1626 pfp.
Vx3ID[0] = vx3.ID;
1627 if(!
DefinePFP(
"M3DVTj2", tjs, pfp, prt))
continue;
1630 if(prt)
PrintPFP(
"left", tjs, pfp,
true);
1640 for(
unsigned short ivx = 0; ivx < tjs.
vtx.size(); ++ivx) {
1641 if(tjs.
vtx[ivx].ID == 0)
continue;
1642 if(tjs.
vtx[ivx].CTP != tp.
CTP)
continue;
1643 if(std::abs(tjs.
vtx[ivx].Pos[0] - tp.
Pos[0]) > 1.2)
continue;
1644 if(std::abs(tjs.
vtx[ivx].Pos[1] - tp.
Pos[1]) > 1.2)
continue;
1653 if(vx3ID >
int(tjs.
vtx3.size()))
return false;
1654 if(pfp.
ID >
int(tjs.
pfps.size()))
return false;
1655 if(pfp.
PDGCode == 22)
return false;
1656 if(end > 1)
return false;
1658 auto& vx3 = tjs.
vtx3[vx3ID - 1];
1663 if(vx3.Wire == -2)
return true;
1666 for(
auto tjid : pfp.
TjIDs) {
1667 auto& tj = tjs.
allTraj[tjid - 1];
1670 if(tj.VtxID[end] == 0) {
1673 if(vx3.Vx2ID[plane] == 0) {
1675 std::array<float, 2> pos;
1692 if(ivx > tjs.
vtx.size() - 1)
return false;
1693 if(tjs.
vtx[ivx].ID == 0)
return false;
1698 unsigned short nadd = 0;
1700 if(tj.AlgMod[
kKilled])
continue;
1701 if(tj.CTP != vx.
CTP)
continue;
1702 if(tj.VtxID[0] == vx.
ID || tj.VtxID[1] == vx.
ID)
continue;
1706 if(nadd == 0)
return false;
1726 if(tj.
CTP != vx.
CTP)
return false;
1736 unsigned short end = 0;
1739 if(sep1 < vtxTjSep2) {
1745 if(tj.
VtxID[end] > 0)
return false;
1748 bool tjShort = (tj.
EndPt[1] - tj.
EndPt[0] < maxShortTjLen);
1749 float closestApproach;
1752 if(vtxTjSep2 > maxSepCutShort2)
return false;
1756 if(vtxTjSep2 > maxSepCutLong2)
return false;
1765 unsigned short closePt;
1779 if(length > 2 && length < closestApproach)
return false;
1785 if(tjShort) pullCut = 10;
1789 myprt<<
"ATTV: 2V"<<vx.
ID;
1790 myprt<<
" NTraj "<<vx.
NTraj;
1792 for(
unsigned short itj = 0; itj < tjs.
allTraj.size(); ++itj) {
1795 if(tj.
CTP != vx.
CTP)
continue;
1796 if(tj.
VtxID[0] == vx.
ID) myprt<<
" "<<tj.
ID<<
"_0";
1797 if(tj.
VtxID[1] == vx.
ID) myprt<<
" "<<tj.
ID<<
"_1";
1799 myprt<<
" +tjID "<<tj.
ID<<
"_"<<end<<
" vtxTjSep "<<sqrt(vtxTjSep2)<<
" tpVxPull "<<tpVxPull<<
" pullCut "<<pullCut<<
" dpt "<<dpt;
1802 if(tpVxPull > pullCut)
return false;
1803 if(dpt > 2)
return true;
1827 if(prt)
mf::LogVerbatim(
"TC")<<
" Poor fit. Keep Tj "<<tj.
ID<<
" with kNoFitToVx";
1858 double vxErrW = vx.
PosErr[0] * tp.
Dir[1];
1859 double vxErrT = vx.
PosErr[1] * tp.
Dir[0];
1860 double vxErr2 = vxErrW * vxErrW + vxErrT * vxErrT;
1866 if(sep2 < 1)
return (
float)(ip/sqrt(vxErr2));
1868 double dang = ip / sqrt(sep2);
1872 double angErr = vxErr2 / sep2;
1875 if(angErr == 0)
return 999;
1876 angErr = sqrt(angErr);
1877 return (
float)(dang / angErr);
1885 double dx = vx1.
X - vx2.
X;
1886 double dy = vx1.
Y - vx2.
Y;
1887 double dz = vx1.
Z - vx2.
Z;
1891 dx = dx * dx / dxErr2;
1892 dy = dy * dy / dyErr2;
1893 dz = dz * dz / dzErr2;
1894 return (
float)(sqrt(dx + dy + dz)/3);
1901 double dw = vx1.
Pos[0] - vx2.
Pos[0];
1902 double dt = vx1.
Pos[1] - vx2.
Pos[1];
1905 dw = dw * dw / dwErr2;
1906 dt = dt * dt / dtErr2;
1907 return (
float)sqrt(dw + dt);
1916 if(vx.
ID !=
int(tjs.
vtx.size() + 1)) {
1917 mf::LogVerbatim(
"TC")<<
"StoreVertex: Invalid ID "<<vx.
ID<<
" It should be "<<tjs.
vtx.size() + 1;
1921 unsigned short nvxtj = 0;
1922 unsigned short nok = 0;
1924 if(tj.AlgMod[
kKilled])
continue;
1925 if(vx.
ID == tj.VtxID[0] || vx.
ID == tj.VtxID[1]) ++nvxtj;
1926 if(vx.
CTP != tj.CTP)
continue;
1927 if(vx.
ID == tj.VtxID[0] || vx.
ID == tj.VtxID[1]) ++nok;
1931 mf::LogVerbatim(
"TC")<<
"StoreVertex: vertex "<<vx.
ID<<
" Topo "<<vx.
Topo<<
" has inconsistent CTP code "<<vx.
CTP<<
" with one or more Tjs\n";
1933 if(tj.AlgMod[
kKilled])
continue;
1934 if(tj.VtxID[0] == vx.
ID) tj.VtxID[0] = 0;
1935 if(tj.VtxID[1] == vx.
ID) tj.VtxID[1] = 0;
1940 tjs.
vtx.push_back(vx);
1962 if(prt)
mf::LogVerbatim(
"TC")<<
" vertex position fixed. No fit allowed";
1968 std::vector<TrajPoint> vxTp;
1970 if(tj.AlgMod[
kKilled])
continue;
1971 if(tj.CTP != vx.
CTP)
continue;
1972 if(tj.AlgMod[
kPhoton])
continue;
1974 if(tj.VtxID[0] == vx.
ID) vxTp.push_back(tj.Pts[tj.EndPt[0]]);
1975 if(tj.VtxID[1] == vx.
ID) vxTp.push_back(tj.Pts[tj.EndPt[1]]);
1978 bool success =
FitVertex(tjs, vx, vxTp, prt);
1980 if(!success)
return false;
2004 vx.
NTraj = vxTp.size();
2006 if(vxTp.size() < 2)
return false;
2015 double sum0 = 0, sum02 = 0;
2016 double sum1 = 0, sum12 = 0;
2024 intTp.
CTP = vxTp[0].CTP;
2025 for(
unsigned short itj = 0; itj < vxTp.size() - 1; ++itj) {
2026 for(
unsigned short jtj = itj + 1; jtj < vxTp.size(); ++jtj) {
2029 intTp.
Pos[0] = p0; intTp.
Pos[1] = p1;
2032 sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2033 sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2039 intTp.
Pos[0] = p0; intTp.
Pos[1] = p1;
2043 sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2044 sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2050 intTp.
Pos[0] = p0; intTp.
Pos[1] = p1;
2052 sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2053 sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2060 intTp.
Pos[0] = p0; intTp.
Pos[1] = p1;
2062 sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2063 sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2069 intTp.
Pos[0] = p0; intTp.
Pos[1] = p1;
2071 sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2072 sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2076 if(sumw == 0)
return false;
2078 double vxP0 = sum0 / sumw;
2079 double vxP1 = sum1 / sumw;
2080 double vxP0rms = sqrt((sum02 - sumw * vxP0 * vxP0) / sumw);
2081 double vxP1rms = sqrt((sum12 - sumw * vxP1 * vxP1) / sumw);
2082 double rootN = sqrt(cnt);
2086 if(vxP0rms < 0.5) vxP0rms = 0.5;
2087 if(vxP1rms < 0.5) vxP1rms = 0.5;
2109 for(
unsigned short itj = 0; itj < vxTp.size(); ++itj) {
2112 vx.
ChiDOF /= (float)vxTp.size();
2117 for(
unsigned short itj = 0; itj < vxTp.size(); ++itj) {
2119 myprt<<
" "<<
PrintPos(tjs, vxTp[itj])<<
" - "<<std::fixed<<std::setprecision(2)<<pull;
2121 myprt<<
" ChiDOF "<<vx.
ChiDOF;
2134 unsigned short plane = planeID.
Plane;
2135 for(
auto& vx2 : tjs.
vtx) {
2136 if(vx2.CTP != inCTP)
continue;
2137 if(vx2.ID == 0)
continue;
2138 if(vx2.Vx3ID == 0)
continue;
2139 if(vx2.Vx3ID >
int(tjs.
vtx3.size())) {
2140 mf::LogVerbatim(
"TC")<<
"ChkVtxAssociations: Invalid vx2.Vx3ID "<<vx2.Vx3ID<<
" in 2D vtx "<<vx2.ID;
2143 auto& vx3 = tjs.
vtx3[vx2.Vx3ID-1];
2145 mf::LogVerbatim(
"TC")<<
"ChkVtxAssociations: 2V"<<vx2.ID<<
" thinks it is matched to 3V"<<vx3.ID<<
" but vx3 is obsolete";
2148 if(vx3.Vx2ID[plane] != vx2.ID) {
2149 mf::LogVerbatim(
"TC")<<
"ChkVtxAssociations: 2V"<<vx2.ID<<
" thinks it is matched to 3V"<<vx3.ID<<
" but vx3 says no!";
2154 for(
auto& vx3 : tjs.
vtx3) {
2155 if(vx3.ID == 0)
continue;
2156 if(vx3.Vx2ID[plane] == 0)
continue;
2157 if(vx3.Vx2ID[plane] > (
int)tjs.
vtx.size()) {
2158 mf::LogVerbatim(
"TC")<<
"ChkVtxAssociations: Invalid vx3.Vx2ID "<<vx3.Vx2ID[plane]<<
" in CTP "<<inCTP;
2161 auto& vx2 = tjs.
vtx[vx3.Vx2ID[plane]-1];
2162 if(vx2.Vx3ID != vx3.ID) {
2163 mf::LogVerbatim(
"TC")<<
"ChkVtxAssociations: 3V"<<vx3.ID<<
" thinks it is matched to 2V"<<vx2.ID<<
" but vx2 says no!";
2170 if(tj.AlgMod[
kKilled])
continue;
2171 for(
unsigned short end = 0;
end < 2; ++
end) {
2172 if(tj.VtxID[
end] == 0)
continue;
2173 if(tj.VtxID[
end] > tjs.
vtx.size()) {
2174 mf::LogVerbatim(
"TC")<<
"ChkVtxAssociations: T"<<tj.ID<<
" thinks it is matched to 2V"<<tj.VtxID[
end]<<
" on end "<<
end<<
" but no vertex exists. Recovering";
2178 unsigned short ivx = tj.VtxID[
end] - 1;
2179 auto& vx2 = tjs.
vtx[ivx];
2181 mf::LogVerbatim(
"TC")<<
"ChkVtxAssociations: T"<<tj.ID<<
" thinks it is matched to 2V"<<tj.VtxID[
end]<<
" on end "<<
end<<
" but the vertex is killed. Fixing the Tj";
2197 unsigned int cstat = tpcid.
Cryostat;
2198 unsigned int tpc = tpcid.
TPC;
2201 for(
auto& vx : tjs.
vtx) {
2202 if(vx.ID == 0)
continue;
2204 if(planeID.
Cryostat != cstat)
continue;
2205 if(planeID.
TPC != tpc)
continue;
2210 if(tj.AlgMod[
kKilled])
continue;
2212 if(planeID.
Cryostat != cstat)
continue;
2213 if(planeID.
TPC != tpc)
continue;
2217 for(
auto& vx : tjs.
vtx) {
2218 if(vx.ID == 0)
continue;
2220 if(planeID.
Cryostat != cstat)
continue;
2221 if(planeID.
TPC != tpc)
continue;
2225 for(
auto& vx3 : tjs.
vtx3) {
2226 if(vx3.ID == 0)
continue;
2227 if(vx3.TPCID != tpcid)
continue;
2236 if(tjs.
vtx.empty())
return;
2237 unsigned int cstat = tpcid.
Cryostat;
2238 unsigned int tpc = tpcid.
TPC;
2239 for(
auto& vx : tjs.
vtx) {
2240 if(vx.ID == 0)
continue;
2242 if(planeID.
Cryostat != cstat)
continue;
2243 if(planeID.
TPC != tpc)
continue;
2246 auto& vx3 = tjs.
vtx3[vx.Vx3ID - 1];
2247 if(vx3.Primary)
continue;
2260 if(vx3.
ID == 0)
return;
2262 for(
unsigned short ipl = 0; ipl < tjs.
NumPlanes; ++ipl) {
2263 if(vx3.
Vx2ID[ipl] <= 0)
continue;
2268 std::vector<int> vxlist;
2273 for(
auto tjid : tjlist) {
2274 auto& tj = tjs.
allTraj[tjid - 1];
2276 for(
unsigned short end = 0;
end < 2; ++
end) {
2277 if(tj.VtxID[
end] == 0)
continue;
2278 auto& vx2 = tjs.
vtx[tj.VtxID[
end] - 1];
2281 vxlist.push_back(vx2.
ID);
2285 if(vxlist.empty())
break;
2287 std::vector<int> newtjlist;
2288 for(
auto vxid : vxlist) {
2289 auto& vx2 = tjs.
vtx[vxid - 1];
2291 for(
auto tjid :
tmp) {
2292 if(std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end()) newtjlist.push_back(tjid);
2295 if(newtjlist.empty())
break;
2308 if(vx3.
ID == 0)
return;
2311 for(
unsigned short ipl = 0; ipl < tjs.
NumPlanes; ++ipl) {
2312 if(vx3.
Vx2ID[ipl] <= 0)
continue;
2325 if(tjs.
vtx.empty())
return;
2326 auto& vx2 = tjs.
vtx[tjs.
vtx.size() - 1];
2334 if(vx2.
ID == 0)
return;
2345 constexpr
float maxChgRMS = 0.25;
2346 constexpr
float momBin = 50;
2350 if(vx2.
ID == 0)
return;
2354 if(vtxTjIDs.empty())
return;
2359 unsigned short m3Dcnt = 0;
2363 unsigned short ivx3 = vx2.
Vx3ID - 1;
2364 if(tjs.
vtx3[ivx3].Wire < 0) m3Dcnt = 2;
2372 std::vector<int> tjids;
2373 std::vector<float> tjwts;
2374 for(
auto tjid : vtxTjIDs) {
2378 unsigned short lenth = tj.
EndPt[1] - tj.
EndPt[0] + 1;
2379 if(lenth < 3)
continue;
2380 float wght = (float)tj.
MCSMom / momBin;
2381 if(wght > 10) wght = 10;
2383 if(tj.
PDGCode == 13) wght *= 2;
2385 if(tj.
ChgRMS < maxChgRMS) ++wght;
2390 tjids.push_back(tjid);
2391 tjwts.push_back(wght);
2394 if(tjids.empty())
return;
2399 for(
unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
2401 float wght1 = tjwts[it1];
2403 unsigned short end1 = 0;
2404 if(tj1.
VtxID[1] == vx2.
ID) end1 = 1;
2405 unsigned short endPt1 = tj1.
EndPt[end1];
2407 unsigned short oend1 = 1 - end1;
2409 float ang1 = tj1.
Pts[endPt1].Ang;
2410 float ang1Err2 = tj1.
Pts[endPt1].AngErr * tj1.
Pts[endPt1].AngErr;
2411 for(
unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
2413 float wght2 = tjwts[it2];
2415 if(tj2.
VtxID[1] == vx2.
ID) end2 = 1;
2417 unsigned short oend2 = 1 - end2;
2418 if(tj2.
StopFlag[oend2][kBragg]) ++wght2;
2419 unsigned short endPt2 = tj2.
EndPt[end2];
2420 float ang2 = tj2.
Pts[endPt2].Ang;
2421 float ang2Err2 = tj2.
Pts[endPt2].AngErr * tj2.
Pts[endPt2].AngErr;
2423 float dangErr = 0.5 * sqrt(ang1Err2 + ang2Err2);
2424 if((dang / dangErr) > 3 && wght1 > 0 && wght2 > 0) {
2425 sum += wght1 + wght2;
2434 vx2.
Score = vpeScore + m3DScore + cfScore + tjScore;
2439 myprt<<
" SVx2W 2V"<<vx2.
ID;
2440 myprt<<
" m3Dcnt "<<m3Dcnt;
2441 myprt<<
" PosErr "<<std::fixed<<std::setprecision(2)<<(vx2.
PosErr[0] + vx2.
PosErr[1]);
2442 myprt<<
" TjChgFrac "<<std::fixed<<std::setprecision(3)<<vx2.
TjChgFrac;
2443 myprt<<
" sum "<<std::fixed<<std::setprecision(1)<<sum;
2444 myprt<<
" cnt "<<(int)cnt;
2445 myprt<<
" Score "<<vx2.
Score;
2456 if(vx3.
ID == 0)
return USHRT_MAX;
2458 std::array<short, 10> cnts;
2460 for(
auto vx2id : vx3.
Vx2ID) {
2461 if(vx2id == 0)
continue;
2462 auto& vx2 = tjs.
vtx[vx2id - 1];
2463 if(vx2.Topo < 0 || vx2.Topo > 9)
continue;
2467 unsigned short theMost = USHRT_MAX;
2468 for(
unsigned short itp = 0; itp < 10; ++itp) {
2469 if(cnts[itp] > most) {
2487 for(
unsigned short iv3 = 0; iv3 < tjs.
vtx3.size(); ++iv3) {
2490 if(vx3.
ID == 0)
continue;
2491 if(vx3.
TPCID != tpcid)
continue;
2493 if(vx3.
Wire < 0)
continue;
2494 unsigned short mPlane = USHRT_MAX;
2495 for(
unsigned short ipl = 0; ipl < tjs.
NumPlanes; ++ipl) {
2496 if(vx3.
Vx2ID[ipl] > 0)
continue;
2500 if(mPlane == USHRT_MAX)
continue;
2505 if(dwc < 5)
continue;
2509 aVtx.
ID = tjs.
vtx.size() + 1;
2517 if(prt)
mf::LogVerbatim(
"TC")<<
"CI3DVIG: Incomplete vertex "<<iv3<<
" in plane "<<mPlane<<
" wire "<<vx3.
Wire<<
" Made 2D vertex ";
2518 std::vector<int> tjIDs;
2519 std::vector<unsigned short> tjEnds;
2520 for(
unsigned short itj = 0; itj < tjs.
allTraj.size(); ++itj) {
2521 if(tjs.
allTraj[itj].CTP != mCTP)
continue;
2523 for(
unsigned short end = 0;
end < 2; ++
end) {
2524 unsigned short ept = tjs.
allTraj[itj].EndPt[
end];
2526 unsigned short oept = tjs.
allTraj[itj].EndPt[1 -
end];
2529 if(std::abs(tp.
Pos[0] - aVtx.
Pos[0]) > std::abs(otp.
Pos[0] - aVtx.
Pos[0]))
continue;
2531 if(doca > 2)
continue;
2534 if(aVtx.
Pos[0] > tp.
Pos[0]) {
2535 ptSep = aVtx.
Pos[0] - tp.
Pos[0] - dwc;
2537 ptSep = tp.
Pos[0] - aVtx.
Pos[0] - dwc;
2540 if(ptSep < -2 || ptSep > 2)
continue;
2542 if(tjs.
allTraj[itj].VtxID[
end] > 0)
continue;
2543 tjIDs.push_back(tjs.
allTraj[itj].ID);
2544 tjEnds.push_back(
end);
2547 if(!tjIDs.empty()) {
2554 for(
unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2555 unsigned short itj = tjIDs[ii] - 1;
2556 tjs.
allTraj[itj].VtxID[tjEnds[ii]] = aVtx.
ID;
2581 if(prt)
mf::LogVerbatim(
"TC")<<
"Inside CI3DV with maxdoca set to "<<maxdoca;
2582 unsigned short ivx3 = 0;
2583 for(
auto& vx3 : tjs.
vtx3) {
2585 if(vx3.ID == 0)
continue;
2586 if(vx3.TPCID != tpcid)
continue;
2588 if(vx3.Wire < 0)
continue;
2589 unsigned short mPlane = USHRT_MAX;
2590 for(
unsigned short plane = 0; plane < tjs.
NumPlanes; ++plane) {
2591 if(vx3.Vx2ID[plane] > 0)
continue;
2594 if(mPlane == USHRT_MAX)
continue;
2595 CTP_t mCTP =
EncodeCTP(vx3.TPCID.Cryostat, vx3.TPCID.TPC, mPlane);
2599 vtp.
Pos[0] = vx3.Wire;
2602 std::vector<int> tjIDs;
2603 std::vector<unsigned short> tjPts;
2605 if(tj.CTP != mCTP)
continue;
2606 if(tj.AlgMod[
kKilled])
continue;
2607 if(tj.Pts.size() < 6)
continue;
2609 float doca = maxdoca;
2611 unsigned short closePt = 0;
2613 if(closePt > tj.EndPt[1])
continue;
2617 if(prt)
mf::LogVerbatim(
"TC")<<
"CI3DV 3V"<<vx3.ID<<
" candidate itj ID "<<tj.ID<<
" vtx pos "<<
PrintPos(tjs, vtp.
Pos)<<
" doca "<<doca;
2618 tjIDs.push_back(tj.ID);
2619 tjPts.push_back(closePt);
2621 if(tjIDs.empty())
continue;
2627 auto vxtjs =
GetAssns(tjs,
"3V", vx3.ID,
"T");
2628 unsigned short maxPts = 0;
2629 for(
auto tjid : vxtjs) {
2630 auto& tj = tjs.
allTraj[tjid - 1];
2632 if(npwc > maxPts) maxPts = npwc;
2636 bool skipit =
false;
2637 for(
auto tjid : tjIDs) {
2638 auto& tj = tjs.
allTraj[tjid - 1];
2641 if(prt)
mf::LogVerbatim(
"TC")<<
" maxPts "<<maxPts<<
" skipit? "<<skipit;
2642 if(skipit)
continue;
2645 unsigned short newVtxIndx = tjs.
vtx.size();
2646 aVtx.
ID = newVtxIndx + 1;
2662 std::array<float, 2> vpos = aVtx.
Pos;
2663 for(
unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2664 unsigned short itj = tjIDs[ii] - 1;
2667 unsigned short closePt = tjPts[ii];
2669 unsigned short end = 1;
2671 if(fabs(closePt - tjs.
allTraj[itj].EndPt[0]) < fabs(closePt - tjs.
allTraj[itj].EndPt[1])) end = 0;
2672 short dpt = fabs(closePt - tjs.
allTraj[itj].EndPt[end]);
2675 if(tjs.
allTraj[itj].VtxID[end] > 0) {
2686 if(
SplitTraj(tjs, itj, closePt, newVtxIndx, prt)) {
2687 if(prt)
mf::LogVerbatim(
"TC")<<
" SplitTraj success 2V"<<tjs.
vtx[newVtxIndx].ID<<
" at closePt "<<closePt;
2702 unsigned short newtj = tjs.
allTraj.size() - 1;
2705 if(newVtx.
NTraj == 0) {
2707 if(prt)
mf::LogVerbatim(
"TC")<<
" Failed. Recover and delete vertex "<<newVtx.
ID;
2711 vx3.Vx2ID[mPlane] = newVtx.
ID;
2712 newVtx.
Vx3ID = vx3.ID;
2715 if(newVtx.
NTraj == 1) {
2723 myprt<<
" Success: new 2V"<<newVtx.
ID<<
" at "<<(int)newVtx.
Pos[0]<<
":"<<(
int)newVtx.
Pos[1]/tjs.
UnitsPerTick;
2724 myprt<<
" points to 3V"<<vx3.ID;
2740 float maxChg = tj.
Pts[nearPt].Chg;
2741 short maxChgPt = nearPt;
2743 for(
short ipt = nearPt - nPtsToChk; ipt < nearPt + nPtsToChk; ++ipt) {
2744 if(ipt < tj.
EndPt[0] || ipt > tj.
EndPt[1])
continue;
2745 auto& tp = tj.
Pts[ipt];
2746 if(tp.Chg > maxChg) {
2750 if(prt)
mf::LogVerbatim(
"TC")<<
"RVP: ipt "<<ipt<<
" Pos "<<tp.CTP<<
":"<<
PrintPos(tjs, tp.Pos)<<
" chg "<<(int)tp.Chg<<
" nhits "<<tp.Hits.size();
2752 if(nearPt == maxChgPt)
return false;
2766 for (
unsigned short iv = 0; iv < tjs.
vtx.size(); ++iv){
2768 if(rvx.
CTP != inCTP)
continue;
2770 if(rvx.
NTraj != 2)
continue;
2772 std::array<unsigned short, 2> tjlist{{0,0}};
2773 for(
unsigned short itj = 0; itj < tjs.
allTraj.size(); ++itj) {
2775 if(tjs.
allTraj[itj].CTP != rvx.
CTP)
continue;
2778 for(
unsigned short end = 0;
end < 2; ++
end) {
2786 if (tjs.
allTraj[tjlist[0]].EndPt[1]<5||
2787 tjs.
allTraj[tjlist[1]].EndPt[1]<5)
continue;
2789 for (
unsigned short i = 0; i<2; ++i){
2794 unsigned short endPt0 = tjs.
allTraj[tjlist[i]].EndPt[i];
2795 unsigned short endPt1 = tjs.
allTraj[tjlist[1-i]].EndPt[1-i];
2798 float w0 = tj0.
Pts[endPt0].Pos[0];
2803 unsigned short j = endPt0;
2804 while (j!=tj0.
EndPt[1-i]){
2807 if (tj0.
Pts[j].Chg){
2809 w1 = tj0.
Pts[j].Pos[0];
2816 float w2 = tj1.
Pts[endPt1].Pos[0];
2819 for (
size_t k = 0; k<tj0.
Pts[endPt0].Hits.size(); ++k){
2820 if (!tj0.
Pts[endPt0].UseHit[k])
continue;
2822 if (this_delta<delta) delta = this_delta;
2826 if (chg0>0&&std::abs((chg0-chg1)/chg0)-std::abs((chg0-chg2)/chg0)>0.2&&delta<1.5&&std::abs(w2-w1)<1.5){
2828 mf::LogVerbatim(
"TC")<<
"chg0 = "<<chg0<<
" chg1 = "<<chg1<<
" chg2 = "<<chg2<<
" delta = "<<delta<<
" w0 = "<<w0<<
" w1 = "<<w1<<
" w2 = "<<w2;
2833 for (
size_t j = 0; j<tp.
Hits.size(); ++j){
2834 if (!tp.
UseHit[j])
continue;
2839 tj1.
Pts.push_back(tp);
2843 tj1.
Pts.insert(tj1.
Pts.begin(), tp);
2848 tj0.
Pts[endPt0].Chg = 0;
2849 for (
size_t j = 0; j<tj0.
Pts[endPt0].Hits.size(); ++j){
2850 tj0.
Pts[endPt0].UseHit[j] =
false;
2860 std::vector<unsigned short> tplist;
2861 while (j!=tj0.
EndPt[1-i]){
2862 if (tj0.
Pts[j].Chg){
2864 for (
size_t k = 0; k<tj0.
Pts[j].Hits.size(); ++k){
2865 if (!tj0.
Pts[j].UseHit[k])
continue;
2867 if (this_delta<delta) delta = this_delta;
2870 if (delta < 0.3 && tj0.
Pts[j].Delta > 1.0 && (j==endPt0 || !tplist.empty())){
2871 tplist.push_back(j);
2880 if (tplist.size()>1){
2881 if (vtxPrt)
mf::LogVerbatim(
"TC")<<
"VHS Moving "<<tplist.size()<<
" TPs from TJ "<<tj0.
ID<<
" to TJ "<<tj1.
ID;
2883 for (
unsigned short j = 0; j<tplist.size(); ++j){
2885 for (
size_t k = 0; k<tp.
Hits.size(); ++k){
2886 if (!tp.
UseHit[k])
continue;
2891 tj1.
Pts.push_back(tp);
2895 tj1.
Pts.insert(tj1.
Pts.begin(), tp);
2901 for (
unsigned short j = 0; j<tplist.size(); ++j){
2902 tj0.
Pts[tplist[j]].Chg = 0;
2903 for (
size_t k = 0; k<tj0.
Pts[tplist[j]].Hits.size(); ++k){
2904 tj0.
Pts[tplist[j]].UseHit[k] =
false;
2922 bool hasHighScoreVx3 = (vx2.
Vx3ID > 0);
2923 if(hasHighScoreVx3 && !forceKill && tjs.
vtx3[vx2.
Vx3ID - 1].Score >= tjs.
Vertex2DCuts[7])
return false;
2929 for(
auto& v3v2id : vx3.Vx2ID)
if(v3v2id == vx2.
ID) v3v2id = 0;
2933 if(tj.AlgMod[
kKilled])
continue;
2934 for(
unsigned short end = 0;
end < 2; ++
end) {
2935 if(tj.VtxID[
end] != vx2id)
continue;
2939 for(
unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
2941 unsigned short ipt = tj.EndPt[0] + ii;
2942 auto& tp = tj.Pts[ipt];
2944 if(ipt == tj.EndPt[1])
break;
2946 unsigned short ipt = tj.EndPt[1] - ii;
2947 auto& tp = tj.Pts[ipt];
2949 if(ipt == tj.EndPt[0])
break;
2954 unsigned short oend = 1 -
end;
2955 if(tj.VtxID[oend] > 0) {
2956 auto& ovx2 = tjs.
vtx[tj.VtxID[oend] - 1];
2963 if(!hasHighScoreVx3)
return true;
2969 unsigned short plane = planeID.
Plane;
2970 if(vx3.
Vx2ID[plane] != vx2id)
return true;
2971 vx3.
Vx2ID[plane] = 0;
2974 unsigned short n2D = 0;
2975 for(
unsigned short plane = 0; plane < tjs.
NumPlanes; ++plane) {
2976 if(vx3.
Vx2ID[plane] > 0) ++n2D;
2988 for(
auto& vx2 : tjs.
vtx) {
2989 if(vx2.
ID == 0)
continue;
2992 for(
auto& pfp : tjs.
pfps) {
2993 for(
unsigned short end = 0;
end < 2; ++
end)
if(pfp.Vx3ID[
end] == vx3.
ID) pfp.Vx3ID[
end] = 0;
3006 if(vx3.
ID == 0)
return true;
3007 if(vx3.
ID >
int(tjs.
vtx3.size()))
return false;
3012 for(
auto vx2id : vx3.
Vx2ID) {
3013 if(vx2id == 0 || vx2id > (
int)tjs.
vtx.size())
continue;
3014 auto& vx2 = tjs.
vtx[vx2id - 1];
3025 std::vector<int>
tmp;
3026 if(vx2.
ID == 0)
return tmp;
3028 if(tj.AlgMod[
kKilled])
continue;
3029 if(tj.CTP != vx2.
CTP)
continue;
3030 for(
unsigned short end = 0;
end < 2; ++
end) {
3031 if(tj.VtxID[
end] == vx2.
ID) tmp.push_back(tj.ID);
3042 std::vector<int>
tmp;
3043 if(vx3.
ID == 0)
return tmp;
3046 for(
auto& vx2 : tjs.
vtx) {
3047 if(vx2.ID == 0)
continue;
3048 if(vx2.Vx3ID != vx3.
ID)
continue;
3050 tmp.insert(tmp.end(), vtxTjID2.begin(), vtxTjID2.end());
3054 if(nvx2 < 1)
return tmp;
3058 std::sort(tmp.begin(), tmp.end());
3067 std::vector<unsigned short>
tmp;
3068 if(pfp.
TjIDs.empty())
return tmp;
3069 for(
auto tjid : pfp.
TjIDs) {
3070 auto& tj = tjs.
allTraj[tjid - 1];
3071 for(
unsigned short end = 0;
end < 2; ++
end) {
3072 if(tj.VtxID[
end] == 0)
continue;
3073 auto& vx2 = tjs.
vtx[tj.VtxID[
end] - 1];
3074 if(vx2.Vx3ID == 0)
continue;
3075 if(std::find(tmp.begin(), tmp.end(), vx2.Vx3ID) != tmp.end())
continue;
3076 tmp.push_back(vx2.Vx3ID);
3098 unsigned short imBest = 0;
3099 for(
auto& vx2 : tjs.
vtx) {
3101 if(pull < minPull) {
3115 unsigned short imBest = 0;
3116 for(
auto& oldvx3 : tjs.
vtx3) {
3117 if(oldvx3.ID == 0)
continue;
3118 if(std::abs(oldvx3.X - vx3.
X) > tjs.
Vertex3DCuts[0])
continue;
3120 if(pull < minPull) {
TPCID()=default
Default constructor: an invalid TPC ID.
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)
void SetVx3Score(TjStuff &tjs, Vtx3Store &vx3, bool prt)
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< unsigned int > FindCloseHits(TjStuff const &tjs, std::array< int, 2 > const &wireWindow, Point2_t const &timeWindow, const unsigned short plane, HitStatus_t hitRequest, bool usePeakTime, bool &hitsNear)
bool ChkVtxAssociations(TjStuff &tjs, const CTP_t &inCTP)
float TrajPointVertexPull(TjStuff &tjs, const TrajPoint &tp, const VtxStore &vx)
std::vector< float > Vertex2DCuts
Max position pull, max Position error rms.
struct of temporary 2D vertices (end points)
static unsigned int kWire
CTP_t CTP
Cryostat, TPC, Plane code.
std::array< double, 3 > Point3_t
void Find3DVertices(TjStuff &tjs, const geo::TPCID &tpcid)
std::bitset< 64 > AlgMod
Bit set if algorithm AlgBit_t modifed the trajectory.
bool RefineVtxPosition(TjStuff &tjs, const Trajectory &tj, unsigned short &nearPt, short nPtsToChk, bool prt)
void CompleteIncomplete3DVertices(TjStuff &tjs, const geo::TPCID &tpcid)
void PrintAllTraj(std::string someText, const TjStuff &tjs, const DebugStuff &debug, unsigned short itj, unsigned short ipt, bool prtVtx)
bool AnalyzePFP(TjStuff &tjs, PFPStruct &pfp, bool prt)
vertex position fixed manually - no fitting done
unsigned short NearestPtWithChg(TjStuff &tjs, Trajectory &tj, unsigned short thePt)
float ChgFracBetween(TjStuff &tjs, Point3_t pos1, Point3_t pos2, geo::TPCID tpcid)
void SplitTrajCrossingVertices(TjStuff &tjs, CTP_t inCTP)
std::vector< float > MaxPos1
float TpSumHitChg(TjStuff &tjs, TrajPoint const &tp)
std::array< std::bitset< 8 >, 2 > StopFlag
bool FitVertex(TjStuff &tjs, VtxStore &vx, bool prt)
Planes which measure X direction.
The data type to uniquely identify a Plane.
std::vector< PFPStruct > pfps
bool valIncreasing(SortEntry c1, SortEntry c2)
matched to a high-score 3D vertex
std::vector< unsigned int > Hits
bool AttachAnyTrajToVertex(TjStuff &tjs, unsigned short ivx, bool prt)
CryostatID_t Cryostat
Index of cryostat.
void ChkVxTjs(TjStuff &tjs, const CTP_t &inCTP, bool prt)
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
bool DefinePFP(std::string inFcnLabel, TjStuff &tjs, PFPStruct &pfp, bool prt)
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
std::array< int, 2 > Vx3ID
float DeadWireCount(const TjStuff &tjs, const TrajPoint &tp1, const TrajPoint &tp2)
bool CompatibleMerge(TjStuff &tjs, std::vector< int > &tjIDs, bool prt)
std::array< double, 2 > Dir
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
unsigned short IsCloseToVertex(TjStuff &tjs, VtxStore &inVx2)
unsigned short FarEnd(const TjStuff &tjs, const PFPStruct &pfp, const Point3_t &pos)
bool SignalAtTp(TjStuff &tjs, const TrajPoint &tp)
std::vector< unsigned short > GetPFPVertices(const TjStuff &tjs, const PFPStruct &pfp)
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
bool SplitTraj(TjStuff &tjs, unsigned short itj, float XPos, bool makeVx2, bool prt)
void SetHighScoreBits(TjStuff &tjs, Vtx3Store &vx3)
bool AttachTrajToVertex(TjStuff &tjs, Trajectory &tj, VtxStore &vx, bool prt)
void FindNeutralVertices(TjStuff &tjs, const geo::TPCID &tpcid)
struct of temporary 3D vertices
bool AttachPFPToVertex(TjStuff &tjs, PFPStruct &pfp, unsigned short end, unsigned short vx3ID, bool prt)
bool MakeVertexObsolete(TjStuff &tjs, VtxStore &vx2, bool forceKill)
std::array< float, 2 > Point2_t
int PDGCodeVote(TjStuff &tjs, std::vector< int > &tjIDs, bool prt)
std::array< Point3_t, 2 > XYZ
const geo::GeometryCore * geom
void MakeJunkVertices(TjStuff &tjs, const CTP_t &inCTP)
CTP_t CTP
Cryostat, TPC, Plane code.
void Match3DVtxTjs(TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
std::vector< VtxStore > vtx
2D vertices
void VtxHitsSwap(TjStuff &tjs, const CTP_t inCTP)
std::vector< TrajPoint > Pts
Trajectory points.
bool SignalBetween(TjStuff &tjs, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction, bool prt)
TrajPoint MakeBareTP(TjStuff &tjs, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
std::vector< float > NeutralVxCuts
void Find2DVertices(TjStuff &tjs, const CTP_t &inCTP)
std::array< Vector3_t, 2 > Dir
unsigned short CloseEnd(TjStuff &tjs, const Trajectory &tj, const Point2_t &pos)
std::vector< int > FindCloseTjs(const TjStuff &tjs, const TrajPoint &fromTp, const TrajPoint &toTp, const float &maxDelta)
float TrajLength(Trajectory &tj)
std::vector< Trajectory > allTraj
vector of all trajectories in each plane
std::bitset< 64 > UseAlg
Allow user to mask off specific algorithms.
void FindHammerVertices2(TjStuff &tjs, const CTP_t &inCTP)
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}
std::vector< float > MaxPos0
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
std::vector< MatchStruct > matchVec
3D matching vector
std::string PrintHit(const TCHit &hit)
float UnitsPerTick
scale factor from Tick to WSE equivalent units
bool PointDirIntersect(Point3_t p1, Vector3_t p1Dir, Point3_t p2, Vector3_t p2Dir, Point3_t &intersect, float &doca)
The data type to uniquely identify a TPC.
PlaneID_t Plane
Index of the plane within its TPC.
bool IntersectionPoint(geo::WireID const &wid1, geo::WireID const &wid2, double &y, double &z) const
Returns the intersection point of two wires.
void ScoreVertices(TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
float PointTrajDOCA(TjStuff const &tjs, unsigned int iht, TrajPoint const &tp)
std::vector< int > GetVtxTjIDs(const TjStuff &tjs, const VtxStore &vx2)
std::array< unsigned short, 2 > VtxID
ID of 2D vertex.
short MCSMom(const TjStuff &tjs, const std::vector< int > &tjIDs)
float ChgFracNearEnd(TjStuff &tjs, PFPStruct &pfp, unsigned short end)
void CompleteIncomplete3DVerticesInGaps(TjStuff &tjs, const geo::TPCID &tpcid)
std::vector< Vtx3Store > vtx3
3D vertices
float ChgFracNearPos(TjStuff &tjs, const Point2_t &pos, const std::vector< int > &tjIDs)
std::bitset< 16 > Stat
Vertex status bits using kVtxBit_t.
std::array< int, 3 > Vx2ID
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
int Tick
Select hit PeakTime for debugging (< 0 for vertex finding)
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
std::vector< float > VertexScoreWeights
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
bool MergeWithVertex(TjStuff &tjs, VtxStore &vx, unsigned short oVxID, bool prt)
std::vector< TCHit > fHits
PFPStruct CreatePFP(const TjStuff &tjs, const geo::TPCID &tpcid)
geo::PlaneID DecodeCTP(CTP_t CTP)
void FindHammerVertices(TjStuff &tjs, const CTP_t &inCTP)
bool Split3DKink(TjStuff &tjs, PFPStruct &pfp, double sep, bool prt)
unsigned short MatchVecIndex
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
void KillPoorVertices(TjStuff &tjs, const geo::TPCID &tpcid)
void SetVx2Score(TjStuff &tjs, bool prt)
void SetEndPoints(TjStuff &tjs, Trajectory &tj)
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
unsigned short NumPtsWithCharge(const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires)
bool MergeAndStore(TjStuff &tjs, unsigned int itj1, unsigned int itj2, bool doPrt)
std::array< double, 3 > Vector3_t
unsigned short TPNearVertex(TjStuff &tjs, const TrajPoint &tp)
void PosInPlane(const TjStuff &tjs, const Vtx3Store &vx3, unsigned short plane, Point2_t &pos)
std::vector< T > SetDifference(const std::vector< T > &set1, const std::vector< T > &set2)
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void PrintPFP(std::string someText, const TjStuff &tjs, const PFPStruct &pfp, bool printHeader)
void SetPDGCode(TjStuff &tjs, unsigned short itj)
void MoveTPToWire(TrajPoint &tp, float wire)
bool StoreVertex(TjStuff &tjs, VtxStore &vx)
unsigned short Vx3Topo(TjStuff &tjs, Vtx3Store &vx3)
std::vector< float > KinkCuts
kink angle, nPts fit, (alternate) kink angle significance
TPCID_t TPC
Index of the TPC within its cryostat.
bool TrajTrajDOCA(const TjStuff &tjs, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
float VertexVertexPull(TjStuff &tjs, const Vtx3Store &vx1, const Vtx3Store &vx2)
void PrintTrajPoint(std::string someText, const TjStuff &tjs, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
std::vector< float > Vertex3DCuts
2D vtx -> 3D vtx matching cuts
void PrintHeader(std::string someText)
float TjChgFrac
Fraction of charge near the vertex that is from hits on the vertex Tjs.
bool StorePFP(TjStuff &tjs, PFPStruct &pfp)
void TrajPointTrajDOCA(TjStuff &tjs, TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
std::vector< int > GetAssns(const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
std::vector< unsigned int > NumWires
short StepDir
the normal user-defined stepping direction = 1 (US -> DS) or -1 (DS -> US)
bool HasWire(geo::WireID const &wireid) const
Returns whether we have the specified wire.
const detinfo::DetectorProperties * detprop