22 if(slc.
tjs.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 < slc.
tjs.size() - 1; ++it1) {
51 auto& tj1 = slc.
tjs[it1];
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 = slc.
tjs[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 = slc.
vtxs.size() + 1;
91 tj2.VtxID[closeEnd] = junkVx.
ID;
92 tj1.VtxID[end1] = junkVx.
ID;
94 if(junkVx.
ID == USHRT_MAX)
continue;
97 for(
auto& tj : slc.
tjs) {
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(slc.
tjs.size() < 2)
return;
142 bool requireVtxTjChg =
true;
147 mf::LogVerbatim(
"TC")<<
"prt set for plane "<<planeID.
Plane<<
" in Find2DVertices. firstPassCuts? "<<firstPassCuts<<
" requireVtxTjChg "<<requireVtxTjChg;
152 for(
unsigned short it1 = 0; it1 < slc.
tjs.size() - 1; ++it1) {
153 auto& tj1 = slc.
tjs[it1];
155 if(tj1.SSID > 0 || tj1.AlgMod[
kShowerLike])
continue;
156 if(tj1.CTP != inCTP)
continue;
157 bool tj1Short = (
TrajLength(tj1) < maxShortTjLen);
158 for(
unsigned short end1 = 0; end1 < 2; ++end1) {
160 if(tj1.VtxID[end1] > 0)
continue;
162 if(tj1.PDGCode == 111 && end1 != tj1.StartEnd)
continue;
165 short endPt1 = tj1.EndPt[end1];
166 float wire1 = tj1.Pts[endPt1].Pos[0];
170 if(tj1.Pts.size() > 6 && tj1.Pts[endPt1].NTPsFit < 4) {
171 if(end1 == 0 && endPt1 <
int(tj1.Pts.size()) - 3) {
173 }
else if (end1 == 1 && endPt1 >=3 ) {
182 endPt1 = tj1.EndPt[end1];
183 short oendPt1 = tj1.EndPt[1-end1];
185 auto& otp1 = tj1.Pts[oendPt1];
186 for(
unsigned short it2 = it1 + 1; it2 < slc.
tjs.size(); ++it2) {
187 auto& tj2 = slc.
tjs[it2];
189 if(tj2.SSID > 0 || tj2.AlgMod[
kShowerLike])
continue;
190 if(tj2.CTP != inCTP)
continue;
191 if(tj1.VtxID[end1] > 0)
continue;
193 bool tj2Short = (
TrajLength(tj2) < maxShortTjLen);
195 unsigned short end2 = 0;
196 if(
PosSep2(tj2.Pts[tj2.EndPt[1]].Pos, tp1.
Pos) <
PosSep2(tj2.Pts[tj2.EndPt[0]].Pos, tp1.
Pos)) end2 = 1;
197 if(tj2.VtxID[end2] > 0)
continue;
199 if(tj2.PDGCode == 111 && end2 != tj2.StartEnd)
continue;
201 if(tj1.VtxID[1 - end1] > 0 && tj1.VtxID[1 - end1] == tj2.VtxID[1 - end2])
continue;
203 unsigned short oendPt2 = tj2.EndPt[1-end2];
204 auto& otp2 = tj2.Pts[oendPt2];
205 if(
PosSep2(otp1.Pos, otp2.Pos) <
PosSep2(tp1.
Pos, tj2.Pts[tj2.EndPt[end2]].Pos))
continue;
206 short endPt2 = tj2.EndPt[end2];
207 float wire2 = tj2.Pts[endPt2].Pos[0];
208 if(tj2.Pts.size() > 6 && tj2.Pts[endPt2].NTPsFit < 4) {
209 if(end2 == 0 && endPt2 <
int(tj2.Pts.size()) - 3) {
211 }
else if (end2 == 1 && endPt2 >= 3){
219 endPt2 = tj2.EndPt[end2];
223 if(std::abs(tp1.
Pos[0] - tp2.
Pos[0]) > sepCut)
continue;
224 if(std::abs(tp1.
Pos[1] - tp2.
Pos[1]) > sepCut)
continue;
242 if(prt && vt1Sep < 200 && vt2Sep < 200) {
244 myprt<<
"F2DV candidate T"<<tj1.ID<<
"_"<<end1<<
"-T"<<tj2.ID<<
"_"<<end2;
246 myprt<<
" dwc1 "<<dwc1<<
" dwc2 "<<dwc2<<
" on dead wire? "<<vtxOnDeadWire;
247 myprt<<
" vt1Sep "<<vt1Sep<<
" vt2Sep "<<vt2Sep<<
" sepCut "<<sepCut;
249 if(vt1Sep > sepCut || vt2Sep > sepCut)
continue;
251 if(
PosSep(vPos, slc.
tjs[it1].Pts[oendPt1].Pos) < vt1Sep) {
255 if(
PosSep(vPos, slc.
tjs[it2].Pts[oendPt2].Pos) < vt2Sep) {
260 unsigned short closePt1;
261 float doca1 = sepCut;
266 short dpt1 = stepDir * (closePt1 - endPt1);
267 if(prt)
mf::LogVerbatim(
"TC")<<
" endPt1 "<<endPt1<<
" closePt1 "<<closePt1<<
" dpt1 "<<dpt1<<
" doca1 "<<doca1;
269 if(dpt1 < -1)
continue;
270 if(slc.
tjs[it1].EndPt[1] > 4) {
271 if(dpt1 > 3)
continue;
274 if(dpt1 > 2)
continue;
276 unsigned short closePt2;
277 float doca2 = sepCut;
279 short dpt2 = stepDir * (closePt2 - endPt2);
280 if(prt)
mf::LogVerbatim(
"TC")<<
" endPt2 "<<endPt2<<
" closePt2 "<<closePt2<<
" dpt2 "<<dpt2<<
" doca2 "<<doca2;
282 if(dpt2 < -1)
continue;
283 if(slc.
tjs[it2].EndPt[1] > 4) {
284 if(dpt2 > 3)
continue;
287 if(dpt2 > 2)
continue;
290 bool fixVxPos =
false;
291 if(requireVtxTjChg) {
293 bool signalBetween =
true;
294 short dpt = abs(wint - tp1.
Pos[0]);
297 signalBetween =
false;
299 dpt = abs(wint - tp2.
Pos[0]);
302 signalBetween =
false;
307 unsigned short ipt1, ipt2;
309 bool isClose =
TrajTrajDOCA(slc, tj1, tj2, ipt1, ipt2, maxSep,
false);
311 if(isClose) isClose = (abs(ipt1 - endPt1) < 4 && abs(ipt2 - endPt2) < 4);
313 if(prt)
mf::LogVerbatim(
"TC")<<
" TrajTrajDOCA are close with minSep "<<maxSep<<
" near "<<
PrintPos(slc, tj1.Pts[ipt1].Pos)<<
" "<<
PrintPos(slc, tj2.Pts[ipt2].Pos);
336 aVtx.
Pass = tj1.Pass;
338 aVtx.
Topo = 2 * end1;
347 unsigned short newVtxID = slc.
vtxs.size() + 1;
349 tj1.VtxID[end1] = newVtxID;
350 tj2.VtxID[end2] = newVtxID;
359 if(prt)
mf::LogVerbatim(
"TC")<<
" Merged with close vertex "<<mergeMeWithVx;
366 myprt<<
" New vtx 2V"<<aVtx.
ID;
367 myprt<<
" Tjs "<<tj1.ID<<
"_"<<end1<<
"-"<<tj2.ID<<
"_"<<end2;
398 if(pass == USHRT_MAX) {
403 if(prt)
PrintAllTraj(
"F2DVo", slc, USHRT_MAX, USHRT_MAX);
422 std::array<int, 2> wireWindow;
423 std::array<float, 2> timeWindow;
443 unsigned short ipl = planeID.
Plane;
455 if(closeHits.empty())
return;
457 std::vector<SortEntry> sortVec(closeHits.size());
459 for(
unsigned short ii = 0; ii < closeHits.size(); ++ii) {
460 unsigned int iht = closeHits[ii];
462 float dw =
hit.WireID().Wire - vx2.
Pos[0];
464 float d2 = dw * dw + dt * dt;
465 sortEntry.index = ii;
467 sortVec[ii] = sortEntry;
470 unsigned int vWire = std::nearbyint(vx2.
Pos[0]);
473 for(
unsigned short ii = 0; ii < closeHits.size(); ++ii) {
474 unsigned int iht = closeHits[sortVec[ii].index];
475 if(slc.
slHits[iht].InTraj > 0)
continue;
479 if(
hit.WireID().Wire == vWire) {
481 if(abs(
hit.PeakTime() - vTick) < 10)
continue;
483 float toWire =
hit.WireID().Wire;
484 float toTick =
hit.PeakTime();
486 unsigned short pass =
tcc.
minPts.size() - 1;
490 if(tj.
Pts[0].Pos[0] < 0)
continue;
496 tp.
Hits.push_back(iht);
535 if(slc.
pfps.size() < 2)
return;
713 if(oVxID > slc.
vtxs.size())
return false;
714 auto& oVx = slc.
vtxs[oVxID - 1];
715 if(vx.
CTP != oVx.CTP)
return false;
720 if(tjlist.empty())
return false;
723 if(tmp.empty())
return false;
724 for(
auto tjid : tmp) {
725 if(std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end()) tjlist.push_back(tjid);
727 if(tjlist.size() < 2)
return false;
729 if(tjlist.size() == 2) {
734 for(
auto tjid : tjlist) {
735 auto& tj = slc.
tjs[tjid - 1];
736 for(
unsigned short end = 0;
end < 2; ++
end) {
737 if(tj.VtxID[
end] == vx.
ID) tj.VtxID[
end] = oVx.ID;
741 if(prt)
mf::LogVerbatim(
"TC")<<
"MWV: merge failed "<<vx.
ID<<
" and existing "<<oVx.ID;
748 std::vector<SortEntry> sortVec(tjlist.size());
749 for(
unsigned int indx = 0; indx < sortVec.size(); ++indx) {
750 sortVec[indx].index = indx;
751 auto& tj = slc.
tjs[tjlist[indx] - 1];
752 sortVec[indx].val = tj.Pts.size();
757 for(
unsigned short ii = 0; ii < sortVec.size(); ++ii) tjlist[ii] = ttl[sortVec[ii].
index];
762 std::vector<TrajPoint> tjpts(tjlist.size());
766 std::array<float, 2> vpos;
767 vpos[0] = 0.5 * (vx.
Pos[0] + oVx.Pos[0]);
768 vpos[1] = 0.5 * (vx.
Pos[1] + oVx.Pos[1]);
769 for(
unsigned short ii = 0; ii < tjpts.size(); ++ii) {
770 auto& tj = slc.
tjs[tjlist[ii] - 1];
774 unsigned short endPt = tj.EndPt[
end];
775 if(npwc > 6 && tj.Pts[endPt].NTPsFit < 4) {
783 if(endPt < tj.EndPt[0]) endPt = tj.EndPt[0];
784 if(endPt > tj.EndPt[1]) endPt = tj.EndPt[1];
786 tjpts[ii].CTP = tj.CTP;
787 tjpts[ii].Pos = tj.Pts[endPt].Pos;
788 tjpts[ii].Dir = tj.Pts[endPt].Dir;
789 tjpts[ii].Ang = tj.Pts[endPt].Ang;
790 tjpts[ii].AngErr = tj.Pts[endPt].AngErr;
792 tjpts[ii].Step = endPt;
794 tjpts[ii].AngleCode =
end;
796 tjpts[ii].Hits.resize(1, tj.ID);
800 myprt<<
"MWV: "<<oVxID;
802 for(
unsigned short ii = 0; ii < tjpts.size(); ++ii) {
803 auto& tjpt = tjpts[ii];
804 myprt<<
" "<<tjlist[ii]<<
"_"<<tjpt.Step<<
"_"<<
PrintPos(slc, tjpt.Pos);
815 bool needsUpdate =
false;
816 for(
unsigned short ii = 2; ii < tjlist.size(); ++ii) {
817 fitpts.push_back(tjpts[ii]);
827 if(needsUpdate)
FitVertex(slc, aVx, fitpts, prt);
831 for(
auto& tj : slc.
tjs) {
833 if(tj.CTP != vx.
CTP)
continue;
834 for(
unsigned short end = 0;
end < 2; ++
end) {
835 if(tj.VtxID[
end] == vx.
ID) tj.VtxID[
end] = 0;
836 if(tj.VtxID[
end] == oVxID) tj.VtxID[
end] = 0;
840 for(
unsigned short ii = 0; ii < fitpts.size(); ++ii) {
841 auto& tjpt = fitpts[ii];
842 unsigned short end = tjpt.AngleCode;
843 auto& tj = slc.
tjs[tjpt.Hits[0] - 1];
844 if(tj.VtxID[end] != 0) {
845 std::cout<<
"MWV: coding error. tj "<<tj.ID<<
" end "<<end<<
" VtxID "<<tj.VtxID[
end]<<
" != 0\n";
848 tj.VtxID[
end] = oVxID;
855 oVx.NTraj = fitpts.size();
862 myprt<<
"MWV: "<<oVxID;
864 for(
unsigned short ii = 0; ii < fitpts.size(); ++ii) {
865 auto& tjpt = fitpts[ii];
866 myprt<<
" "<<tjpt.Hits[0]<<
"_"<<tjpt.AngleCode<<
"_"<<
PrintPos(slc, tjpt.Pos);
880 for(
unsigned short ivx = 0; ivx < slc.
vtxs.size(); ++ivx) {
881 auto& vx2 = slc.
vtxs[ivx];
882 if(vx2.ID == 0)
continue;
883 if(vx2.CTP != inCTP)
continue;
884 auto vxtjs =
GetAssns(slc,
"2V", vx2.
ID,
"T");
885 if(vxtjs.size() < 2)
continue;
891 unsigned short closeEnd = 0;
892 for(
auto tid : vxtjs) {
893 auto& tj = slc.
tjs[tid - 1];
894 unsigned short nearEnd = 1 -
FarEnd(slc, tj, vx2.Pos);
895 if(tj.VtxID[nearEnd] != vx2.ID)
continue;
896 float sep =
PosSep(tj.Pts[tj.EndPt[nearEnd]].Pos, vx2.Pos);
897 if(sep > close)
continue;
902 if(close > 1.5 && closeID > 0) {
903 auto& closeTj = slc.
tjs[closeID - 1];
904 auto& closeTP = closeTj.Pts[closeTj.EndPt[closeEnd]];
906 vx2.Pos = closeTP.Pos;
909 for(
unsigned short it1 = 0; it1 < vxtjs.size() - 1; ++it1) {
910 auto& tj1 = slc.
tjs[vxtjs[it1] - 1];
912 unsigned short end1 = 0;
913 if(tj1.VtxID[1] == vx2.ID) end1 = 1;
914 auto& vtp1 = tj1.Pts[tj1.EndPt[end1]];
915 auto& otp1 = tj1.Pts[tj1.EndPt[1 - end1]];
916 float tj1sep =
PosSep(vtp1.Pos, vx2.Pos);
917 for(
unsigned short it2 = it1 + 1; it2 < vxtjs.size(); ++it2) {
918 auto& tj2 = slc.
tjs[vxtjs[it2] - 1];
920 unsigned short end2 = 0;
921 if(tj2.VtxID[2] == vx2.ID) end2 = 1;
922 auto& vtp2 = tj2.Pts[tj2.EndPt[end2]];
923 auto& otp2 = tj2.Pts[tj2.EndPt[1 - end2]];
924 float tj2sep =
PosSep(vtp2.Pos, vx2.Pos);
925 float otj1tj2 =
PosSep(otp1.Pos, vtp2.Pos);
926 float delta12 =
PointTrajDOCA(slc, otp1.Pos[0], otp1.Pos[1], vtp2);
927 float dang12 =
DeltaAngle(otp1.Ang, vtp2.Ang);
928 if(otj1tj2 < tj2sep && delta12 < 1 && otj1tj2 < 4) {
931 myprt<<
"CVTjs: "<<vx2.ID<<
" tj1 "<<tj1.ID<<
" tj2 "<<tj2.ID;
932 myprt<<
" otj1tj2 "<<otj1tj2;
933 myprt<<
" delta12 "<<delta12;
934 myprt<<
" dang12 "<<dang12;
935 myprt<<
" Try to merge";
940 auto& newTj = slc.
tjs[slc.
tjs.size()-1];
942 if(prt)
mf::LogVerbatim(
"TC")<<
"CVTjs: Merged tjs "<<tj1.ID<<
" and "<<tj2.ID<<
" -> "<<newTj.ID;
949 float tj1otj2 =
PosSep(vtp1.Pos, otp2.Pos);
950 if(tj1otj2 < tj1sep && delta12 < 1 && tj1otj2 < 4) {
954 auto& newTj = slc.
tjs[slc.
tjs.size()-1];
956 if(prt)
mf::LogVerbatim(
"TC")<<
"CVTjs: Merged tjs "<<tj1.ID<<
" and "<<tj2.ID<<
" -> "<<newTj.ID;
964 if(vx2.Topo == 1 && vxtjs.size() == 2) {
965 auto& tj1 = slc.
tjs[vxtjs[0] - 1];
966 auto& tj2 = slc.
tjs[vxtjs[1] - 1];
996 for(
unsigned short it1 = 0; it1 < slc.
tjs.size(); ++it1) {
997 if(slc.
tjs[it1].CTP != inCTP)
continue;
999 if(slc.
tjs[it1].AlgMod[
kHamVx])
continue;
1002 if(slc.
tjs[it1].PDGCode == 111)
continue;
1004 if(numPtsWithCharge1 < 6)
continue;
1006 bool didaSplit =
false;
1007 for(
unsigned short end1 = 0; end1 < 2; ++end1) {
1009 if(slc.
tjs[it1].VtxID[end1] > 0)
continue;
1010 unsigned short endPt1 = slc.
tjs[it1].EndPt[end1];
1011 for(
unsigned short it2 = 0; it2 < slc.
tjs.size(); ++it2) {
1012 if(it1 == it2)
continue;
1013 if(slc.
tjs[it2].AlgMod[
kKilled] || slc.
tjs[it2].AlgMod[kHaloTj])
continue;
1014 if(slc.
tjs[it2].AlgMod[kHamVx])
continue;
1015 if(slc.
tjs[it2].AlgMod[kHamVx2])
continue;
1017 if(slc.
tjs[it2].CTP != inCTP)
continue;
1019 if(slc.
tjs[it2].AlgMod[kJunkTj])
continue;
1020 if(slc.
tjs[it2].PDGCode == 111)
continue;
1022 if(numPtsWithCharge2 < 6)
continue;
1027 float doca = minDOCA;
1028 unsigned short closePt2 = 0;
1030 if(doca == minDOCA)
continue;
1033 auto& tj1 = slc.
tjs[it1];
1034 auto& tj2 = slc.
tjs[it2];
1035 myprt<<
" FHV2 CTP"<<tj1.CTP;
1036 myprt<<
" t"<<tj1.ID<<
"_"<<end1<<
" MCSMom "<<tj1.MCSMom<<
" ChgRMS "<<tj1.ChgRMS;
1037 myprt<<
" split t"<<tj2.ID<<
"? MCSMom "<<tj2.MCSMom<<
" ChgRMS "<<tj2.ChgRMS;
1038 myprt<<
" doca "<<doca<<
" tj2.EndPt[0] "<<tj2.EndPt[0]<<
" closePt2 "<<closePt2;
1039 myprt<<
" tj2.EndPt[1] "<<tj2.EndPt[1];
1042 if(closePt2 < slc.
tjs[it2].EndPt[0] + 3)
continue;
1043 if(closePt2 > slc.
tjs[it2].EndPt[1] - 3)
continue;
1048 float dang =
DeltaAngle(slc.
tjs[it1].Pts[endPt1].Ang, slc.
tjs[it2].Pts[closePt2].Ang);
1049 if(dang < 0.2)
continue;
1052 unsigned short closePt1 = 0;
1054 if(closePt1 != endPt1)
continue;
1059 unsigned short intPt2;
1061 if(prt)
mf::LogVerbatim(
"TC")<<
" intPt2 on tj2 "<<intPt2<<
" at Pos "<<
PrintPos(slc, slc.
tjs[it2].Pts[intPt2])<<
" doca "<<doca;
1062 if(doca == minDOCA)
continue;
1064 float mcsmom = slc.
tjs[it2].MCSMom;
1065 float mcsmom1 =
MCSMom(slc, slc.
tjs[it2], slc.
tjs[it2].EndPt[0], intPt2);
1066 float mcsmom2 =
MCSMom(slc, slc.
tjs[it2], intPt2, slc.
tjs[it2].EndPt[1]);
1068 if(prt)
mf::LogVerbatim(
"TC")<<
" Check MCSMom after split: mcsmom1 "<<mcsmom1<<
" mcsmom2 "<<mcsmom2;
1069 if(mcsmom1 < mcsmom || mcsmom2 < mcsmom)
continue;
1073 if(intPt2 < closePt2) dir = -1;
1074 unsigned short nit = 0;
1075 unsigned short ipt = intPt2;
1076 float mostChg = slc.
tjs[it2].Pts[ipt].Chg;
1080 if(ipt < 3 || ipt > slc.
tjs[it2].Pts.size() - 4)
break;
1081 float delta =
PointTrajDOCA(slc, slc.
tjs[it2].Pts[ipt].Pos[0], slc.
tjs[it2].Pts[ipt].Pos[1], slc.
tjs[it1].Pts[endPt1]);
1082 float sep =
PosSep(slc.
tjs[it2].Pts[ipt].Pos, slc.
tjs[it1].Pts[endPt1].Pos);
1083 float dang = delta / sep;
1084 float pull = dang / slc.
tjs[it1].Pts[endPt1].DeltaRMS;
1086 if(pull < 2 && slc.
tjs[it2].Pts[ipt].Chg > mostChg) {
1087 mostChg = slc.
tjs[it2].Pts[ipt].Chg;
1092 float chgPull = (mostChg - slc.
tjs[it2].AveChg) / slc.
tjs[it2].ChgRMS;
1093 if(prt)
mf::LogVerbatim(
"TC")<<
" chgPull at intersection point "<<chgPull;
1094 if(chgPull < 10)
continue;
1097 if(slc.
tjs[it1].Pts[endPt1].Pos[0] < -0.4)
continue;
1098 unsigned int fromWire = std::nearbyint(slc.
tjs[it1].Pts[endPt1].Pos[0]);
1099 if(slc.
tjs[it2].Pts[intPt2].Pos[0] < -0.4)
continue;
1100 unsigned int toWire = std::nearbyint(slc.
tjs[it2].Pts[intPt2].Pos[0]);
1101 if(fromWire > toWire) {
1102 unsigned int tmp = fromWire;
1106 bool skipIt =
false;
1107 for(
unsigned int wire = fromWire + 1; wire < toWire; ++wire) {
1114 if(skipIt)
continue;
1118 aVtx.
Pos = slc.
tjs[it2].Pts[intPt2].Pos;
1120 aVtx.
Pass = slc.
tjs[it2].Pass;
1124 aVtx.
ID = slc.
vtxs.size() + 1;
1125 unsigned short ivx = slc.
vtxs.size();
1127 if(!
SplitTraj(slc, it2, intPt2, ivx, prt)) {
1130 slc.
vtxs.pop_back();
1133 slc.
tjs[it1].VtxID[end1] = slc.
vtxs[ivx].ID;
1136 unsigned short newTjIndex = slc.
tjs.size() - 1;
1148 if(didaSplit)
break;
1169 for(
unsigned short it1 = 0; it1 < slc.
tjs.size(); ++it1) {
1170 if(slc.
tjs[it1].CTP != inCTP)
continue;
1174 if(slc.
tjs[it1].PDGCode == 111)
continue;
1176 unsigned short tj1len = slc.
tjs[it1].EndPt[1] - slc.
tjs[it1].EndPt[0] + 1;
1177 if(tj1len < 5)
continue;
1179 bool didaSplit =
false;
1180 for(
unsigned short end1 = 0; end1 < 2; ++end1) {
1182 if(slc.
tjs[it1].VtxID[end1] > 0)
continue;
1183 unsigned short endPt1 = slc.
tjs[it1].EndPt[end1];
1184 for(
unsigned short it2 = 0; it2 < slc.
tjs.size(); ++it2) {
1185 if(slc.
tjs[it2].CTP != inCTP)
continue;
1186 if(it1 == it2)
continue;
1187 if(slc.
tjs[it2].AlgMod[
kKilled] || slc.
tjs[it2].AlgMod[kHaloTj])
continue;
1188 if(slc.
tjs[it2].AlgMod[kJunkTj])
continue;
1189 if(slc.
tjs[it2].PDGCode == 111)
continue;
1191 unsigned short tj2len = slc.
tjs[it2].EndPt[1] - slc.
tjs[it2].EndPt[0] + 1;
1192 if(tj2len < 6)
continue;
1196 unsigned short end20 = slc.
tjs[it2].EndPt[0];
1197 unsigned short end21 = slc.
tjs[it2].EndPt[1];
1199 if(tj2len > 200 && slc.
tjs[it2].PDGCode == 13)
continue;
1201 if(tj2len > 100 &&
DeltaAngle(slc.
tjs[it2].Pts[end20].Ang, slc.
tjs[it2].Pts[end21].Ang) < 0.2)
continue;
1206 float doca = minDOCA;
1207 unsigned short closePt2 = 0;
1209 if(doca == minDOCA)
continue;
1211 if(prt)
mf::LogVerbatim(
"TC")<<
"FHV: Candidate t"<<slc.
tjs[it1].ID<<
" t"<<slc.
tjs[it2].ID<<
" doca "<<doca<<
" tj2.EndPt[0] "<<slc.
tjs[it2].EndPt[0]<<
" closePt2 "<<closePt2<<
" tj2.EndPt[1] "<<slc.
tjs[it2].EndPt[1];
1212 if(closePt2 < slc.
tjs[it2].EndPt[0] + 3)
continue;
1213 if(closePt2 > slc.
tjs[it2].EndPt[1] - 3)
continue;
1215 float dang =
DeltaAngle(slc.
tjs[it1].Pts[endPt1].Ang, slc.
tjs[it2].Pts[closePt2].Ang);
1216 if(prt)
mf::LogVerbatim(
"TC")<<
" dang "<<dang<<
" imposing a hard cut of 0.4 for now ";
1217 if(dang < 0.4)
continue;
1219 std::vector<int> tjids(2);
1220 tjids[0] = slc.
tjs[it1].ID;
1221 tjids[1] = slc.
tjs[it2].ID;
1224 if(chgFrac < 0.9)
continue;
1227 aVtx.
Pos = slc.
tjs[it2].Pts[closePt2].Pos;
1229 aVtx.
Pass = slc.
tjs[it2].Pass;
1233 aVtx.
ID = slc.
vtxs.size() + 1;
1235 unsigned short ivx = slc.
vtxs.size() - 1;
1236 if(!
SplitTraj(slc, it2, closePt2, ivx, prt)) {
1238 slc.
vtxs.pop_back();
1241 slc.
tjs[it1].VtxID[end1] = slc.
vtxs[ivx].ID;
1244 unsigned short newTjIndex = slc.
tjs.size() - 1;
1245 slc.
tjs[newTjIndex].AlgMod[
kHamVx] =
true;
1252 auto& vx2 = slc.
vtxs[ivx];
1254 myprt<<
" new 2V"<<vx2.ID<<
" Score "<<vx2.Score<<
" Tjs";
1255 auto tjlist =
GetAssns(slc,
"2V", vx2.
ID,
"T");
1256 for(
auto tid : tjlist) myprt<<
" t"<<tid;
1261 if(didaSplit)
break;
1274 if(slc.
vtxs.empty())
return;
1275 if(slc.
tjs.empty())
return;
1277 constexpr
float docaCut = 4;
1280 if(prt)
mf::LogVerbatim(
"TC")<<
"Inside SplitTrajCrossingVertices inCTP "<<inCTP;
1284 unsigned short nTraj = slc.
tjs.size();
1285 for(
unsigned short itj = 0; itj < nTraj; ++itj) {
1288 if(slc.
tjs[itj].CTP != inCTP)
continue;
1293 if(slc.
tjs[itj].EndPt[1] < 6)
continue;
1294 for(
unsigned short iv = 0; iv < slc.
vtxs.size(); ++iv) {
1295 auto& vx2 = slc.
vtxs[iv];
1297 if(vx2.NTraj == 0)
continue;
1299 if(slc.
tjs[itj].VtxID[0] == vx2.ID ||
1300 slc.
tjs[itj].VtxID[1] == vx2.ID)
continue;
1302 if(slc.
tjs[itj].CTP != vx2.CTP)
continue;
1305 float doca = docaCut;
1309 unsigned short closePt = 0;
1314 doca =
PointTrajDOCA(slc, vx2.Pos[0], vx2.Pos[1], slc.
tjs[itj].Pts[closePt]);
1316 if(doca > docaCut)
continue;
1317 if(prt)
mf::LogVerbatim(
"TC")<<
" doca "<<doca<<
" btw T"<<slc.
tjs[itj].ID<<
" and 2V"<<slc.
vtxs[iv].ID<<
" closePt "<<closePt<<
" in plane "<<planeID.
Plane;
1322 if(vxtjs.empty())
continue;
1323 unsigned short maxPts = 0;
1327 float tjAng = slc.
tjs[itj].Pts[closePt].Ang;
1328 for(
auto tjid : vxtjs) {
1329 auto& vtj = slc.
tjs[tjid - 1];
1332 if(npwc > maxPts) maxPts = npwc;
1333 unsigned short end = 0;
1334 if(vtj.VtxID[1] == slc.
vtxs[iv].ID) end = 1;
1335 auto& vtp = vtj.Pts[vtj.EndPt[
end]];
1337 if(dang > maxdang) maxdang = dang;
1341 bool skipit =
false;
1343 if(!skipit && maxdang <
tcc.
kinkCuts[0]) skipit =
true;
1344 if(prt)
mf::LogVerbatim(
"TC")<<
" maxPts "<<maxPts<<
" vxtjs[0] "<<vxtjs[0]<<
" maxdang "<<maxdang<<
" skipit? "<<skipit;
1355 auto& closeTP = slc.
tjs[itj].Pts[closePt];
1356 if(slc.
tjs[itj].StepDir > 0 && closePt > slc.
tjs[itj].EndPt[0]) {
1357 if(closeTP.Pos[0] > vx2.Pos[0]) --closePt;
1358 }
else if(slc.
tjs[itj].StepDir < 0 && closePt < slc.
tjs[itj].EndPt[1]) {
1359 if(closeTP.Pos[0] < vx2.Pos[0]) ++closePt;
1365 if ((slc.
tjs[itj].Pts[closePt].Pos[0]-vx2.Pos[0])*(slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[1]].Pos[0]-vx2.Pos[0]) + (slc.
tjs[itj].Pts[closePt].Pos[1]-vx2.Pos[1])*(slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[1]].Pos[1]-vx2.Pos[1]) <0 && closePt < slc.
tjs[itj].EndPt[1] - 1) ++closePt;
1366 else if ((slc.
tjs[itj].Pts[closePt].Pos[0]-vx2.Pos[0])*(slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[0]].Pos[0]-vx2.Pos[0]) + (slc.
tjs[itj].Pts[closePt].Pos[1]-vx2.Pos[1])*(slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[0]].Pos[1]-slc.
vtxs[iv].Pos[1]) <0 && closePt > slc.
tjs[itj].EndPt[0] + 1) --closePt;
1371 mf::LogVerbatim(
"TC")<<
"Good doca "<<doca<<
" btw T"<<slc.
tjs[itj].ID<<
" and 2V"<<vx2.ID<<
" closePt "<<closePt<<
" in plane "<<planeID.
Plane<<
" CTP "<<slc.
vtxs[iv].CTP;
1375 if(closePt < slc.
tjs[itj].EndPt[0] + 3)
continue;
1376 if(closePt > slc.
tjs[itj].EndPt[1] - 3)
continue;
1377 if(!
SplitTraj(slc, itj, closePt, iv, prt)) {
1378 if(prt)
mf::LogVerbatim(
"TC")<<
"SplitTrajCrossingVertices: Failed to split trajectory";
1382 unsigned short newTjIndex = slc.
tjs.size() - 1;
1399 if(slc.
vtxs.size() < 2)
return;
1403 std::vector<std::vector<unsigned short>> vIndex(3);
1404 for(
unsigned short ivx = 0; ivx < slc.
vtxs.size(); ++ivx) {
1406 if(slc.
vtxs[ivx].ID == 0)
continue;
1408 unsigned short plane = planeID.
Plane;
1409 if(plane > 2)
continue;
1410 vIndex[plane].push_back(ivx);
1413 unsigned short vtxInPln = 0;
1414 for(
unsigned short plane = 0; plane < slc.
nPlanes; ++plane)
if(vIndex[plane].size() > 0) ++vtxInPln;
1415 if(vtxInPln < 2)
return;
1424 size_t vsize = slc.
vtxs.size();
1426 std::vector<short> vPtr(vsize, -1);
1428 std::vector<float> vX(vsize, -100);
1430 for(
unsigned short ivx = 0; ivx < vsize; ++ivx) {
1431 if(slc.
vtxs[ivx].ID <= 0)
continue;
1434 if(slc.
vtxs[ivx].Pos[0] < -0.4)
continue;
1435 unsigned int wire = std::nearbyint(slc.
vtxs[ivx].Pos[0]);
1443 std::vector<Vtx3Store> v3temp;
1450 constexpr
float maxSep = 4;
1453 for(
unsigned short ipl = 0; ipl < 2; ++ipl) {
1454 for(
unsigned short ii = 0; ii < vIndex[ipl].size(); ++ii) {
1455 unsigned short ivx = vIndex[ipl][ii];
1456 if(vX[ivx] < 0)
continue;
1457 auto& ivx2 = slc.
vtxs[ivx];
1458 if(ivx2.Pos[0] < -0.4)
continue;
1459 unsigned int iWire = std::nearbyint(ivx2.Pos[0]);
1460 for(
unsigned short jpl = ipl + 1; jpl < 3; ++jpl) {
1461 for(
unsigned short jj = 0; jj < vIndex[jpl].size(); ++jj) {
1462 unsigned short jvx = vIndex[jpl][jj];
1463 if(vX[jvx] < 0)
continue;
1464 auto& jvx2 = slc.
vtxs[jvx];
1465 if(jvx2.Pos[0] < -0.4)
continue;
1466 unsigned int jWire = std::nearbyint(jvx2.Pos[0]);
1467 float dX = std::abs(vX[ivx] - vX[jvx]);
1471 for(
auto& v3t : v3temp) {
1472 unsigned short cnt = 0;
1473 if(std::find(v3t.Vx2ID.begin(), v3t.Vx2ID.end(), ivx2.ID) != v3t.Vx2ID.end()) ++cnt;
1474 if(std::find(v3t.Vx2ID.begin(), v3t.Vx2ID.end(), jvx2.ID) != v3t.Vx2ID.end()) ++cnt;
1481 mf::LogVerbatim(
"TC")<<
"F3DV: ipl "<<ipl<<
" i2V"<<ivx2.ID<<
" iX "<<vX[ivx]
1482 <<
" jpl "<<jpl<<
" j2V"<<jvx2.ID<<
" jvX "<<vX[jvx]<<
" W:T "<<(int)jvx2.Pos[0]<<
":"<<(
int)jvx2.Pos[1]<<
" dX "<<dX;
1484 double y = -1000,
z = -1000;
1486 if(y < slc.yLo || y > slc.
yHi || z < slc.zLo || z > slc.
zHi)
continue;
1487 unsigned short kpl = 3 - ipl - jpl;
1488 float kX = 0.5 * (vX[ivx] + vX[jvx]);
1492 if(kWire < 0 || (
unsigned int)kWire > slc.
nWires[kpl])
continue;
1494 std::array<int, 2> wireWindow;
1495 std::array<float, 2> timeWindow;
1496 wireWindow[0] = kWire - maxSep;
1497 wireWindow[1] = kWire + maxSep;
1499 timeWindow[0] = time - maxSep;
1500 timeWindow[1] = time + maxSep;
1502 std::vector<unsigned int> closeHits =
FindCloseHits(slc, wireWindow, timeWindow, kpl,
kAllHits,
true, hitsNear);
1505 myprt<<
" Hits near "<<kpl<<
":"<<kWire<<
":"<<(int)(time/
tcc.
unitsPerTick)<<
" = ";
1508 if(!hitsNear)
continue;
1515 v3d.
Vx2ID[ipl] = ivx2.ID;
1516 v3d.
Vx2ID[jpl] = jvx2.ID;
1525 float vxScoreWght = 0;
1529 if(posError < 0.5) posError = 0;
1531 v3d.
Score = posError + vxScoreWght;
1534 v3temp.push_back(v3d);
1538 myprt<<
"F3DV: 2 Plane match i2V";
1539 myprt<<slc.
vtxs[ivx].ID<<
" P:W:T "<<ipl<<
":"<<(int)slc.
vtxs[ivx].Pos[0]<<
":"<<(
int)slc.
vtxs[ivx].Pos[1];
1540 myprt<<
" j2V"<<slc.
vtxs[jvx].ID<<
" P:W:T "<<jpl<<
":"<<(int)slc.
vtxs[jvx].Pos[0]<<
":"<<(
int)slc.
vtxs[jvx].Pos[1];
1541 myprt<<std::fixed<<std::setprecision(3);
1542 myprt<<
" dX "<<dX<<
" posError "<<posError<<
" vxScoreWght "<<vxScoreWght<<
" Score "<<v3d.
Score;
1545 if(slc.
nPlanes == 2)
continue;
1548 for(
unsigned short kk = 0; kk < vIndex[kpl].size(); ++kk) {
1549 unsigned short kvx = vIndex[kpl][kk];
1550 if(vX[kvx] < 0)
continue;
1551 float dX = std::abs(vX[kvx] - v3d.
X);
1555 if(dX > thirdPlanedXCut)
continue;
1558 double y = -1000,
z = -1000;
1560 v3d.
YErr = y - v3d.
Y;
1569 posError = dX * dX + dY * dY + dZ * dZ;
1574 if(posError < 0.5) posError = 0;
1576 v3d.
Score = posError + vxScoreWght;
1577 if(v3d.
Score > maxScore) maxScore = v3d.
Score;
1578 v3temp.push_back(v3d);
1585 if(v3temp.empty())
return;
1590 for(
auto& v3 : v3temp)
if(v3.Wire >= 0) v3.Score += maxScore;
1594 for(
auto& v3 : v3temp) {
1596 mf::LogVerbatim(
"TC")<<
"2V"<<v3.Vx2ID[0]<<
" 2V"<<v3.Vx2ID[1]<<
" wire "<<v3.Wire<<
" Score "<<v3.Score;
1598 mf::LogVerbatim(
"TC")<<
"2V"<<v3.Vx2ID[0]<<
" 2V"<<v3.Vx2ID[1]<<
" 2V"<<v3.Vx2ID[2]<<
" wire "<<v3.Wire<<
" Score "<<v3.Score;
1603 std::vector<SortEntry> sortVec(v3temp.size());
1604 for(
unsigned short ivx = 0; ivx < v3temp.size(); ++ivx) {
1606 sEntry.
val = v3temp[ivx].Score;
1607 sortVec[ivx] = sEntry;
1609 if(sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(),
valIncreasing);
1611 std::vector<Vtx3Store> v3sel;
1612 for(
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
1613 unsigned short ivx = sortVec[ii].
index;
1615 bool skipit =
false;
1616 for(
auto& v3 : v3sel) {
1617 for(
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
1618 if(v3temp[ivx].Vx2ID[ipl] == 0)
continue;
1619 if(v3temp[ivx].Vx2ID[ipl] == v3.Vx2ID[ipl]) {
1626 if(skipit)
continue;
1627 v3sel.push_back(v3temp[ivx]);
1633 myprt<<
"v3sel list\n";
1634 for(
auto& v3d : v3sel) {
1635 for(
auto vx2id : v3d.Vx2ID)
if(vx2id > 0) myprt<<
" 2V"<<vx2id;
1636 myprt<<
" wire "<<v3d.Wire<<
" Score "<<v3d.Score;
1642 unsigned short ninc = 0;
1643 for(
auto& vx3 : v3sel) {
1644 if(slc.
nPlanes == 3 && vx3.Wire >= 0) ++ninc;
1645 vx3.ID = slc.
vtx3s.size() + 1;
1650 myprt<<
" 3V"<<vx3.ID;
1651 for(
auto v2id : vx3.Vx2ID) myprt<<
" 2V"<<v2id;
1652 myprt<<
" wire "<<vx3.Wire;
1654 slc.
vtx3s.push_back(vx3);
1656 for(
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
1657 if(vx3.Vx2ID[ipl] == 0)
continue;
1671 for(
auto& tj : slc.
tjs) {
1674 if(planeID.
TPC != tpc || planeID.
Cryostat != cstat)
continue;
1678 for(
auto& vx2 : slc.
vtxs) {
1679 if(vx2.ID == 0)
continue;
1681 if(planeID.
TPC != tpc || planeID.
Cryostat != cstat)
continue;
1685 for(
auto& vx3 : slc.
vtx3s) {
1686 if(vx3.ID == 0)
continue;
1699 if(slc.
vtx3s.empty())
return;
1703 std::vector<SortEntry> sortVec;
1704 for(
unsigned short iv3 = 0; iv3 < slc.
vtx3s.size(); ++iv3) {
1705 auto& vx3 = slc.
vtx3s[iv3];
1706 if(vx3.ID == 0)
continue;
1710 if(v3TjIDs.empty())
continue;
1715 sortVec.push_back(se);
1717 if(sortVec.empty())
return;
1718 if(sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(),
valDecreasing);
1720 for(
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
1721 auto& vx3 = slc.
vtx3s[sortVec[ii].index];
1723 std::vector<int> v3TjIDs =
GetVtxTjIDs(slc, vx3, score);
1726 myprt<<
"M3DVTj 3V"<<vx3.ID<<
" score "<<score<<
" Tjs";
1727 for(
auto& tjID : v3TjIDs) myprt<<
" T"<<tjID;
1729 for(
unsigned int ims = 0; ims < slc.
matchVec.size(); ++ims) {
1731 if(ms.Count == 0)
continue;
1732 bool skipit =
false;
1733 for(
auto tjid : ms.TjIDs) {
1734 auto& tj = slc.
tjs[tjid - 1];
1735 if(tj.AlgMod[
kMat3D]) skipit =
true;
1738 if(skipit)
continue;
1740 if(shared.size() < 2)
continue;
1741 if(prt)
mf::LogVerbatim(
"TC")<<
" ims "<<ims<<
" shared size "<<shared.size();
1743 pfp.
TjIDs = ms.TjIDs;
1744 pfp.
Vx3ID[0] = vx3.ID;
1747 pfp.
XYZ[0] = ms.Pos;
1748 pfp.
Dir[0] = ms.Dir;
1750 if(prt)
mf::LogVerbatim(
"TC")<<
"M3DVTj: pfp P"<<pfp.
ID<<
" 3V"<<vx3.ID<<
" ims "<<ims;
1754 auto saveTjIDs = pfp.
TjIDs;
1755 if(!
DefinePFP(
"M3DVTj1", slc, pfp, prt))
continue;
1759 if(prt)
PrintPFP(
"M3D", slc, pfp,
true);
1760 if(!didSplit && shared.size() != ms.TjIDs.size()) {
1767 if(pfp.
TjIDs != saveTjIDs) {
1772 for(
auto tjid :
tmp) {
1773 auto& tj = slc.
tjs[tjid - 1];
1774 if(!tj.AlgMod[
kMat3D]) v3TjIDs.push_back(tjid);
1776 if(v3TjIDs.size() < 2)
break;
1782 if(!mfpfp.empty()) allms.Count = 0;
1788 for(
auto tjid : leftover) myprt<<
" T"<<tjid;
1790 if(leftover.size() < 2)
break;
1794 if(v3TjIDs.size() > 1 && v3TjIDs.size() <= slc.
nPlanes) {
1798 for(
auto& tjid : v3TjIDs) {
1799 auto& tj = slc.
tjs[tjid - 1];
1800 if(tj.AlgMod[
kMat3D])
continue;
1802 pfp.
TjIDs.push_back(tjid);
1804 if(pfp.
TjIDs.size() < 2)
continue;
1805 pfp.
Vx3ID[0] = vx3.ID;
1806 if(!
DefinePFP(
"M3DVTj2", slc, pfp, prt))
continue;
1809 if(prt)
PrintPFP(
"left", slc, pfp,
true);
1819 for(
unsigned short ivx = 0; ivx < slc.
vtxs.size(); ++ivx) {
1820 if(slc.
vtxs[ivx].ID == 0)
continue;
1821 if(slc.
vtxs[ivx].CTP != tp.
CTP)
continue;
1822 if(std::abs(slc.
vtxs[ivx].Pos[0] - tp.
Pos[0]) > 1.2)
continue;
1823 if(std::abs(slc.
vtxs[ivx].Pos[1] - tp.
Pos[1]) > 1.2)
continue;
1832 if(vx3ID >
int(slc.
vtx3s.size()))
return false;
1833 if(pfp.
ID >
int(slc.
pfps.size()))
return false;
1834 if(pfp.
PDGCode == 22)
return false;
1835 if(end > 1)
return false;
1837 auto& vx3 = slc.
vtx3s[vx3ID - 1];
1842 if(vx3.Wire == -2)
return true;
1845 for(
auto tjid : pfp.
TjIDs) {
1846 auto& tj = slc.
tjs[tjid - 1];
1849 if(tj.VtxID[end] == 0) {
1852 if(vx3.Vx2ID[plane] == 0) {
1854 std::array<float, 2> pos;
1871 if(ivx > slc.
vtxs.size() - 1)
return false;
1872 if(slc.
vtxs[ivx].ID == 0)
return false;
1877 if(vx.
Topo == 5 || vx.
Topo == 6)
return false;
1879 unsigned short nadd = 0;
1880 for(
auto& tj : slc.
tjs) {
1882 if(tj.CTP != vx.
CTP)
continue;
1883 if(tj.VtxID[0] == vx.
ID || tj.VtxID[1] == vx.
ID)
continue;
1887 if(nadd == 0)
return false;
1907 if(tj.
CTP != vx.
CTP)
return false;
1917 unsigned short end = 0;
1920 if(sep1 < vtxTjSep2) {
1926 if(tj.
VtxID[end] > 0)
return false;
1929 bool tjShort = (tj.
EndPt[1] - tj.
EndPt[0] < maxShortTjLen);
1932 float closestApproach;
1935 if(vtxTjSep2 > maxSepCutShort2)
return false;
1939 if(vtxTjSep2 > maxSepCutLong2)
return false;
1948 unsigned short closePt;
1962 if(length > 4 && length < closestApproach)
return false;
1969 if(tjShort) pullCut *= 2;
1971 if(tjShort) pullCut = 10;
1976 myprt<<
"ATTV: 2V"<<vx.
ID;
1977 myprt<<
" NTraj "<<vx.
NTraj;
1979 for(
unsigned short itj = 0; itj < slc.
tjs.size(); ++itj) {
1982 if(tj.
CTP != vx.
CTP)
continue;
1983 if(tj.
VtxID[0] == vx.
ID) myprt<<
" T"<<tj.
ID<<
"_0";
1984 if(tj.
VtxID[1] == vx.
ID) myprt<<
" T"<<tj.
ID<<
"_1";
1986 myprt<<
" + T"<<tj.
ID<<
"_"<<end<<
" vtxTjSep "<<sqrt(vtxTjSep2)<<
" tpVxPull "<<tpVxPull<<
" pullCut "<<pullCut<<
" dpt "<<dpt;
1989 if(tpVxPull > pullCut)
return false;
1990 if(dpt > 2)
return true;
2016 if(prt)
mf::LogVerbatim(
"TC")<<
" Poor fit. Keep short Tj "<<tj.
ID<<
" with kNoFitToVx";
2040 double vxErrW = vx.
PosErr[0] * tp.
Dir[1];
2041 double vxErrT = vx.
PosErr[1] * tp.
Dir[0];
2042 double vxErr2 = vxErrW * vxErrW + vxErrT * vxErrT;
2048 if(sep2 < 1)
return (
float)(ip/sqrt(vxErr2));
2050 double dang = ip / sqrt(sep2);
2054 double angErr = vxErr2 / sep2;
2057 if(angErr == 0)
return 999;
2058 angErr = sqrt(angErr);
2059 return (
float)(dang / angErr);
2067 double dx = vx1.
X - vx2.
X;
2068 double dy = vx1.
Y - vx2.
Y;
2069 double dz = vx1.
Z - vx2.
Z;
2073 dx = dx * dx / dxErr2;
2074 dy = dy * dy / dyErr2;
2075 dz = dz * dz / dzErr2;
2076 return (
float)(sqrt(dx + dy + dz)/3);
2083 double dw = vx1.
Pos[0] - vx2.
Pos[0];
2084 double dt = vx1.
Pos[1] - vx2.
Pos[1];
2087 dw = dw * dw / dwErr2;
2088 dt = dt * dt / dtErr2;
2089 return (
float)sqrt(dw + dt);
2098 if(vx.
ID !=
int(slc.
vtxs.size() + 1)) {
2106 unsigned short nvxtj = 0;
2107 unsigned short nok = 0;
2108 for(
auto& tj : slc.
tjs) {
2109 if(tj.AlgMod[
kKilled])
continue;
2110 if(vx.
ID == tj.VtxID[0] || vx.
ID == tj.VtxID[1]) ++nvxtj;
2111 if(vx.
CTP != tj.CTP)
continue;
2112 if(vx.
ID == tj.VtxID[0] || vx.
ID == tj.VtxID[1]) ++nok;
2116 mf::LogVerbatim(
"TC")<<
"StoreVertex: vertex "<<vx.
ID<<
" Topo "<<vx.
Topo<<
" has inconsistent CTP code "<<vx.
CTP<<
" with one or more Tjs\n";
2117 for(
auto& tj : slc.
tjs) {
2118 if(tj.AlgMod[
kKilled])
continue;
2119 if(tj.VtxID[0] == vx.
ID) tj.VtxID[0] = 0;
2120 if(tj.VtxID[1] == vx.
ID) tj.VtxID[1] = 0;
2125 slc.
vtxs.push_back(vx);
2147 if(prt)
mf::LogVerbatim(
"TC")<<
" vertex position fixed. No fit allowed";
2152 std::vector<TrajPoint> vxTp;
2153 for(
auto& tj : slc.
tjs) {
2155 if(tj.CTP != vx.
CTP)
continue;
2156 if(tj.AlgMod[
kPhoton])
continue;
2159 if(tj.VtxID[0] == vx.
ID) {
2160 vxTp.push_back(tj.Pts[tj.EndPt[0]]);
2163 if(tj.VtxID[1] == vx.
ID) {
2164 vxTp.push_back(tj.Pts[tj.EndPt[1]]);
2169 auto& tp = vxTp[vxTp.size()-1];
2170 if(tj.ID > 0) tp.Step = (int)tj.ID;
2176 bool success =
FitVertex(slc, vx, vxTp, prt);
2178 if(!success)
return false;
2202 vx.
NTraj = vxTp.size();
2204 if(vxTp.size() < 2)
return false;
2213 double sum0 = 0, sum02 = 0;
2214 double sum1 = 0, sum12 = 0;
2222 intTp.
CTP = vxTp[0].CTP;
2223 for(
unsigned short itj = 0; itj < vxTp.size() - 1; ++itj) {
2224 for(
unsigned short jtj = itj + 1; jtj < vxTp.size(); ++jtj) {
2227 intTp.
Pos[0] = p0; intTp.
Pos[1] = p1;
2230 sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2231 sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2237 intTp.
Pos[0] = p0; intTp.
Pos[1] = p1;
2241 sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2242 sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2248 intTp.
Pos[0] = p0; intTp.
Pos[1] = p1;
2250 sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2251 sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2258 intTp.
Pos[0] = p0; intTp.
Pos[1] = p1;
2260 sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2261 sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2267 intTp.
Pos[0] = p0; intTp.
Pos[1] = p1;
2269 sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2270 sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2274 if(sumw == 0)
return false;
2276 double vxP0 = sum0 / sumw;
2277 double vxP1 = sum1 / sumw;
2278 double vxP0rms = sqrt((sum02 - sumw * vxP0 * vxP0) / sumw);
2279 double vxP1rms = sqrt((sum12 - sumw * vxP1 * vxP1) / sumw);
2280 double rootN = sqrt(cnt);
2284 if(vxP0rms < 0.5) vxP0rms = 0.5;
2285 if(vxP1rms < 0.5) vxP1rms = 0.5;
2307 for(
unsigned short itj = 0; itj < vxTp.size(); ++itj) {
2310 vx.
ChiDOF /= (float)vxTp.size();
2315 for(
unsigned short itj = 0; itj < vxTp.size(); ++itj) {
2317 myprt<<
" "<<
PrintPos(slc, vxTp[itj])<<
" - "<<std::fixed<<std::setprecision(2)<<pull;
2319 myprt<<
" ChiDOF "<<vx.
ChiDOF;
2332 unsigned short plane = planeID.
Plane;
2333 for(
auto& vx2 : slc.
vtxs) {
2334 if(vx2.CTP != inCTP)
continue;
2335 if(vx2.ID == 0)
continue;
2336 if(vx2.Vx3ID == 0)
continue;
2337 if(vx2.Vx3ID >
int(slc.
vtx3s.size())) {
2338 mf::LogVerbatim(
"TC")<<
"ChkVtxAssociations: Invalid vx2.Vx3ID "<<vx2.Vx3ID<<
" in 2D vtx "<<vx2.ID;
2341 auto& vx3 = slc.
vtx3s[vx2.Vx3ID-1];
2343 mf::LogVerbatim(
"TC")<<
"ChkVtxAssociations: 2V"<<vx2.ID<<
" thinks it is matched to 3V"<<vx3.ID<<
" but vx3 is obsolete";
2346 if(vx3.Vx2ID[plane] != vx2.ID) {
2347 mf::LogVerbatim(
"TC")<<
"ChkVtxAssociations: 2V"<<vx2.ID<<
" thinks it is matched to 3V"<<vx3.ID<<
" but vx3 says no!";
2352 for(
auto& vx3 : slc.
vtx3s) {
2353 if(vx3.ID == 0)
continue;
2354 if(vx3.Vx2ID[plane] == 0)
continue;
2355 if(vx3.Vx2ID[plane] > (
int)slc.
vtxs.size()) {
2356 mf::LogVerbatim(
"TC")<<
"ChkVtxAssociations: Invalid vx3.Vx2ID "<<vx3.Vx2ID[plane]<<
" in CTP "<<inCTP;
2359 auto& vx2 = slc.
vtxs[vx3.Vx2ID[plane]-1];
2360 if(vx2.Vx3ID != vx3.ID) {
2361 mf::LogVerbatim(
"TC")<<
"ChkVtxAssociations: 3V"<<vx3.ID<<
" thinks it is matched to 2V"<<vx2.ID<<
" but vx2 says no!";
2367 for(
auto& tj : slc.
tjs) {
2369 for(
unsigned short end = 0;
end < 2; ++
end) {
2370 if(tj.VtxID[
end] == 0)
continue;
2371 if(tj.VtxID[
end] > slc.
vtxs.size()) {
2372 mf::LogVerbatim(
"TC")<<
"ChkVtxAssociations: T"<<tj.ID<<
" thinks it is matched to 2V"<<tj.VtxID[
end]<<
" on end "<<
end<<
" but no vertex exists. Recovering";
2376 unsigned short ivx = tj.VtxID[
end] - 1;
2377 auto& vx2 = slc.
vtxs[ivx];
2379 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";
2396 for(
auto& vx : slc.
vtxs) {
2397 if(vx.ID == 0)
continue;
2401 for(
auto& tj : slc.
tjs) {
2406 for(
auto& vx : slc.
vtxs) {
2407 if(vx.ID == 0)
continue;
2411 for(
auto& vx3 : slc.
vtx3s) {
2412 if(vx3.ID == 0)
continue;
2421 if(slc.
vtxs.empty())
return;
2422 for(
auto& vx : slc.
vtxs) {
2423 if(vx.ID == 0)
continue;
2426 auto& vx3 = slc.
vtx3s[vx.Vx3ID - 1];
2427 if(vx3.Primary)
continue;
2440 if(vx3.
ID == 0)
return;
2442 for(
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
2443 if(vx3.
Vx2ID[ipl] <= 0)
continue;
2448 std::vector<int> vxlist;
2453 for(
auto tjid : tjlist) {
2454 auto& tj = slc.
tjs[tjid - 1];
2456 for(
unsigned short end = 0;
end < 2; ++
end) {
2457 if(tj.VtxID[
end] == 0)
continue;
2458 auto& vx2 = slc.
vtxs[tj.VtxID[
end] - 1];
2461 vxlist.push_back(vx2.
ID);
2465 if(vxlist.empty())
break;
2467 std::vector<int> newtjlist;
2468 for(
auto vxid : vxlist) {
2469 auto& vx2 = slc.
vtxs[vxid - 1];
2471 for(
auto tjid :
tmp) {
2472 if(std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end()) newtjlist.push_back(tjid);
2475 if(newtjlist.empty())
break;
2488 if(vx3.
ID == 0)
return;
2491 for(
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
2492 if(vx3.
Vx2ID[ipl] <= 0)
continue;
2507 if(slc.
vtxs.empty())
return;
2508 auto& vx2 = slc.
vtxs[slc.
vtxs.size() - 1];
2516 if(vx2.
ID == 0)
return;
2527 constexpr
float maxChgRMS = 0.25;
2528 constexpr
float momBin = 50;
2532 if(vx2.
ID == 0)
return;
2536 if(vtxTjIDs.empty())
return;
2541 unsigned short m3Dcnt = 0;
2545 unsigned short ivx3 = vx2.
Vx3ID - 1;
2546 if(slc.
vtx3s[ivx3].Wire < 0) m3Dcnt = 2;
2554 std::vector<int> tjids;
2555 std::vector<float> tjwts;
2556 unsigned short cnt13 = 0;
2557 for(
auto tjid : vtxTjIDs) {
2561 unsigned short lenth = tj.
EndPt[1] - tj.
EndPt[0] + 1;
2562 if(lenth < 3)
continue;
2563 float wght = (float)tj.
MCSMom / momBin;
2571 if(tj.
ChgRMS < maxChgRMS) ++wght;
2576 tjids.push_back(tjid);
2577 tjwts.push_back(wght);
2580 if(tjids.empty())
return;
2585 for(
unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
2587 float wght1 = tjwts[it1];
2589 unsigned short end1 = 0;
2590 if(tj1.
VtxID[1] == vx2.
ID) end1 = 1;
2591 unsigned short endPt1 = tj1.
EndPt[end1];
2593 unsigned short oend1 = 1 - end1;
2595 float ang1 = tj1.
Pts[endPt1].Ang;
2596 float ang1Err2 = tj1.
Pts[endPt1].AngErr * tj1.
Pts[endPt1].AngErr;
2597 for(
unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
2599 float wght2 = tjwts[it2];
2601 if(tj2.
VtxID[1] == vx2.
ID) end2 = 1;
2603 unsigned short oend2 = 1 - end2;
2604 if(tj2.
StopFlag[oend2][kBragg]) ++wght2;
2605 unsigned short endPt2 = tj2.
EndPt[end2];
2606 float ang2 = tj2.
Pts[endPt2].Ang;
2607 float ang2Err2 = tj2.
Pts[endPt2].AngErr * tj2.
Pts[endPt2].AngErr;
2609 float dangErr = 0.5 * sqrt(ang1Err2 + ang2Err2);
2610 if((dang / dangErr) > 3 && wght1 > 0 && wght2 > 0) {
2611 sum += wght1 + wght2;
2620 vx2.
Score = vpeScore + m3DScore + cfScore + tjScore;
2625 myprt<<
" SVx2W 2v"<<vx2.
ID;
2633 myprt<<std::fixed<<std::setprecision(1);
2634 myprt<<
" vpeScore "<<vpeScore<<
" m3DScore "<<m3DScore;
2635 myprt<<
" cfScore "<<cfScore<<
" tjScore "<<tjScore;
2636 myprt<<
" Score "<<vx2.
Score;
2647 if(vx3.
ID == 0)
return USHRT_MAX;
2649 std::array<short, 10> cnts;
2651 for(
auto vx2id : vx3.
Vx2ID) {
2652 if(vx2id == 0)
continue;
2653 auto& vx2 = slc.
vtxs[vx2id - 1];
2654 if(vx2.Topo < 0 || vx2.Topo > 9)
continue;
2658 unsigned short theMost = USHRT_MAX;
2659 for(
unsigned short itp = 0; itp < 10; ++itp) {
2660 if(cnts[itp] > most) {
2678 for(
unsigned short iv3 = 0; iv3 < slc.
vtx3s.size(); ++iv3) {
2681 if(vx3.
ID == 0)
continue;
2683 if(vx3.
Wire < 0)
continue;
2684 unsigned short mPlane = USHRT_MAX;
2685 for(
unsigned short ipl = 0; ipl < slc.
nPlanes; ++ipl) {
2686 if(vx3.
Vx2ID[ipl] > 0)
continue;
2690 if(mPlane == USHRT_MAX)
continue;
2695 if(dwc < 5)
continue;
2699 aVtx.
ID = slc.
vtxs.size() + 1;
2707 if(prt)
mf::LogVerbatim(
"TC")<<
"CI3DVIG: Incomplete vertex "<<iv3<<
" in plane "<<mPlane<<
" wire "<<vx3.
Wire<<
" Made 2D vertex ";
2708 std::vector<int> tjIDs;
2709 std::vector<unsigned short> tjEnds;
2710 for(
unsigned short itj = 0; itj < slc.
tjs.size(); ++itj) {
2711 if(slc.
tjs[itj].CTP != mCTP)
continue;
2713 for(
unsigned short end = 0;
end < 2; ++
end) {
2714 unsigned short ept = slc.
tjs[itj].EndPt[
end];
2716 unsigned short oept = slc.
tjs[itj].EndPt[1 -
end];
2719 if(std::abs(tp.
Pos[0] - aVtx.
Pos[0]) > std::abs(otp.
Pos[0] - aVtx.
Pos[0]))
continue;
2721 if(doca > 2)
continue;
2724 if(aVtx.
Pos[0] > tp.
Pos[0]) {
2725 ptSep = aVtx.
Pos[0] - tp.
Pos[0] - dwc;
2727 ptSep = tp.
Pos[0] - aVtx.
Pos[0] - dwc;
2729 if(prt)
mf::LogVerbatim(
"TC")<<
"CI3DVIG: tj ID "<<slc.
tjs[itj].ID<<
" doca "<<doca<<
" ptSep "<<ptSep;
2730 if(ptSep < -2 || ptSep > 2)
continue;
2732 if(slc.
tjs[itj].VtxID[
end] > 0)
continue;
2733 tjIDs.push_back(slc.
tjs[itj].ID);
2734 tjEnds.push_back(
end);
2737 if(!tjIDs.empty()) {
2744 for(
unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2745 unsigned short itj = tjIDs[ii] - 1;
2746 slc.
tjs[itj].VtxID[tjEnds[ii]] = aVtx.
ID;
2771 if(prt)
mf::LogVerbatim(
"TC")<<
"Inside CI3DV with maxdoca set to "<<maxdoca;
2772 unsigned short ivx3 = 0;
2773 for(
auto& vx3 : slc.
vtx3s) {
2775 if(vx3.ID == 0)
continue;
2777 if(vx3.Wire < 0)
continue;
2778 unsigned short mPlane = USHRT_MAX;
2780 bool indPlnNoChgVtx =
false;
2781 for(
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
2782 if(vx3.Vx2ID[plane] > 0) {
2783 auto& vx2 = slc.
vtxs[vx3.Vx2ID[plane] - 1];
2789 if(mPlane == USHRT_MAX)
continue;
2790 if(indPlnNoChgVtx)
continue;
2791 CTP_t mCTP =
EncodeCTP(vx3.TPCID.Cryostat, vx3.TPCID.TPC, mPlane);
2795 vtp.
Pos[0] = vx3.Wire;
2798 std::vector<int> tjIDs;
2799 std::vector<unsigned short> tjPts;
2800 for(
auto& tj : slc.
tjs) {
2801 if(tj.CTP != mCTP)
continue;
2803 if(tj.Pts.size() < 6)
continue;
2805 float doca = maxdoca;
2807 unsigned short closePt = 0;
2809 if(closePt > tj.EndPt[1])
continue;
2813 if(prt)
mf::LogVerbatim(
"TC")<<
"CI3DV 3V"<<vx3.ID<<
" candidate itj ID "<<tj.ID<<
" vtx pos "<<
PrintPos(slc, vtp.
Pos)<<
" doca "<<doca;
2814 tjIDs.push_back(tj.ID);
2815 tjPts.push_back(closePt);
2817 if(tjIDs.empty())
continue;
2823 auto vxtjs =
GetAssns(slc,
"3V", vx3.
ID,
"T");
2824 unsigned short maxPts = 0;
2825 for(
auto tjid : vxtjs) {
2826 auto& tj = slc.
tjs[tjid - 1];
2828 if(npwc > maxPts) maxPts = npwc;
2832 bool skipit =
false;
2833 for(
auto tjid : tjIDs) {
2834 auto& tj = slc.
tjs[tjid - 1];
2837 if(prt)
mf::LogVerbatim(
"TC")<<
" maxPts "<<maxPts<<
" skipit? "<<skipit;
2838 if(skipit)
continue;
2841 unsigned short newVtxIndx = slc.
vtxs.size();
2842 aVtx.
ID = newVtxIndx + 1;
2858 std::array<float, 2> vpos = aVtx.
Pos;
2859 for(
unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2860 unsigned short itj = tjIDs[ii] - 1;
2863 unsigned short closePt = tjPts[ii];
2865 unsigned short end = 1;
2867 if(fabs(closePt - slc.
tjs[itj].EndPt[0]) < fabs(closePt - slc.
tjs[itj].EndPt[1])) end = 0;
2868 short dpt = fabs(closePt - slc.
tjs[itj].EndPt[end]);
2871 if(slc.
tjs[itj].VtxID[end] > 0) {
2873 auto& oldTj = slc.
tjs[itj];
2874 auto& oldVx = slc.
vtxs[oldTj.VtxID[
end] - 1];
2875 short oldSep = fabs(oldVx.Pos[0] - oldTj.Pts[oldTj.EndPt[end]].Pos[0]);
2876 if(prt)
mf::LogVerbatim(
"TC")<<
" T"<<slc.
tjs[itj].ID<<
" has vertex 2V"<<slc.
tjs[itj].VtxID[
end]<<
" at end "<<end<<
". oldSep "<<oldSep;
2883 slc.
tjs[itj].VtxID[
end] = slc.
vtxs[newVtxIndx].ID;
2887 vpos = slc.
tjs[itj].Pts[slc.
tjs[itj].EndPt[
end]].Pos;
2890 if(
SplitTraj(slc, itj, closePt, newVtxIndx, prt)) {
2891 if(prt)
mf::LogVerbatim(
"TC")<<
" SplitTraj success 2V"<<slc.
vtxs[newVtxIndx].ID<<
" at closePt "<<closePt;
2906 unsigned short newtj = slc.
tjs.size() - 1;
2909 if(newVtx.
NTraj == 0) {
2911 if(prt)
mf::LogVerbatim(
"TC")<<
" Failed. Recover and delete vertex "<<newVtx.
ID;
2915 vx3.Vx2ID[mPlane] = newVtx.
ID;
2916 newVtx.
Vx3ID = vx3.ID;
2919 if(newVtx.
NTraj == 1) {
2928 myprt<<
" points to 3V"<<vx3.ID;
2969 for (
unsigned short iv = 0; iv < slc.
vtxs.size(); ++iv){
2971 if(rvx.
CTP != inCTP)
continue;
2973 if(rvx.
NTraj != 2)
continue;
2975 std::array<unsigned short, 2> tjlist{{0,0}};
2976 for(
unsigned short itj = 0; itj < slc.
tjs.size(); ++itj) {
2978 if(slc.
tjs[itj].CTP != rvx.
CTP)
continue;
2981 for(
unsigned short end = 0;
end < 2; ++
end) {
2989 if (slc.
tjs[tjlist[0]].EndPt[1]<5||
2990 slc.
tjs[tjlist[1]].EndPt[1]<5)
continue;
2992 for (
unsigned short i = 0; i<2; ++i){
2997 unsigned short endPt0 = slc.
tjs[tjlist[i]].EndPt[i];
2998 unsigned short endPt1 = slc.
tjs[tjlist[1-i]].EndPt[1-i];
3001 float w0 = tj0.
Pts[endPt0].Pos[0];
3006 unsigned short j = endPt0;
3007 while (j!=tj0.
EndPt[1-i]){
3010 if (tj0.
Pts[j].Chg){
3012 w1 = tj0.
Pts[j].Pos[0];
3019 float w2 = tj1.
Pts[endPt1].Pos[0];
3022 for (
size_t k = 0; k<tj0.
Pts[endPt0].Hits.size(); ++k){
3023 if (!tj0.
Pts[endPt0].UseHit[k])
continue;
3025 if (this_delta<delta) delta = this_delta;
3029 if (chg0>0&&std::abs((chg0-chg1)/chg0)-std::abs((chg0-chg2)/chg0)>0.2&&delta<1.5&&std::abs(w2-w1)<1.5){
3031 mf::LogVerbatim(
"TC")<<
" chg0 = "<<chg0<<
" chg1 = "<<chg1<<
" chg2 = "<<chg2<<
" delta = "<<delta<<
" w0 = "<<w0<<
" w1 = "<<w1<<
" w2 = "<<w2;
3036 for (
size_t j = 0; j<tp.
Hits.size(); ++j){
3037 if (!tp.
UseHit[j])
continue;
3042 tj1.
Pts.push_back(tp);
3046 tj1.
Pts.insert(tj1.
Pts.begin(), tp);
3051 tj0.
Pts[endPt0].Chg = 0;
3052 for (
size_t j = 0; j<tj0.
Pts[endPt0].Hits.size(); ++j){
3053 tj0.
Pts[endPt0].UseHit[j] =
false;
3063 std::vector<unsigned short> tplist;
3064 while (j!=tj0.
EndPt[1-i]){
3065 if (tj0.
Pts[j].Chg){
3067 for (
size_t k = 0; k<tj0.
Pts[j].Hits.size(); ++k){
3068 if (!tj0.
Pts[j].UseHit[k])
continue;
3070 if (this_delta<delta) delta = this_delta;
3073 if (delta < 0.3 && tj0.
Pts[j].Delta > 1.0 && (j==endPt0 || !tplist.empty())){
3074 tplist.push_back(j);
3083 if (tplist.size()>1){
3084 if (prt)
mf::LogVerbatim(
"TC")<<
" Moving "<<tplist.size()<<
" TPs from TJ "<<tj0.
ID<<
" to TJ "<<tj1.
ID;
3086 for (
unsigned short j = 0; j<tplist.size(); ++j){
3088 for (
size_t k = 0; k<tp.
Hits.size(); ++k){
3089 if (!tp.
UseHit[k])
continue;
3094 tj1.
Pts.push_back(tp);
3098 tj1.
Pts.insert(tj1.
Pts.begin(), tp);
3104 for (
unsigned short j = 0; j<tplist.size(); ++j){
3105 tj0.
Pts[tplist[j]].Chg = 0;
3106 for (
size_t k = 0; k<tj0.
Pts[tplist[j]].Hits.size(); ++k){
3107 tj0.
Pts[tplist[j]].UseHit[k] =
false;
3125 bool hasHighScoreVx3 = (vx2.
Vx3ID > 0);
3136 for(
auto& v3v2id : vx3.Vx2ID)
if(v3v2id == vx2.
ID) v3v2id = 0;
3139 for(
auto& tj : slc.
tjs) {
3141 for(
unsigned short end = 0;
end < 2; ++
end) {
3142 if(tj.VtxID[
end] != vx2id)
continue;
3146 for(
unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3148 unsigned short ipt = tj.EndPt[0] + ii;
3149 auto& tp = tj.Pts[ipt];
3151 if(ipt == tj.EndPt[1])
break;
3153 unsigned short ipt = tj.EndPt[1] - ii;
3154 auto& tp = tj.Pts[ipt];
3156 if(ipt == tj.EndPt[0])
break;
3161 unsigned short oend = 1 -
end;
3162 if(tj.VtxID[oend] > 0) {
3163 auto& ovx2 = slc.
vtxs[tj.VtxID[oend] - 1];
3170 if(!hasHighScoreVx3)
return true;
3176 unsigned short plane = planeID.
Plane;
3177 if(vx3.
Vx2ID[plane] != vx2id)
return true;
3178 vx3.
Vx2ID[plane] = 0;
3181 unsigned short n2D = 0;
3182 for(
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
3183 if(vx3.
Vx2ID[plane] > 0) ++n2D;
3195 for(
auto& vx2 : slc.
vtxs) {
3196 if(vx2.
ID == 0)
continue;
3199 for(
auto& pfp : slc.
pfps) {
3200 for(
unsigned short end = 0;
end < 2; ++
end)
if(pfp.Vx3ID[
end] == vx3.
ID) pfp.Vx3ID[
end] = 0;
3213 if(vx3.
ID == 0)
return true;
3214 if(vx3.
ID >
int(slc.
vtx3s.size()))
return false;
3216 for(
auto vx2id : vx3.
Vx2ID) {
3217 if(vx2id == 0 || vx2id > (
int)slc.
vtxs.size())
continue;
3218 auto& vx2 = slc.
vtxs[vx2id - 1];
3229 std::vector<int>
tmp;
3230 if(vx2.
ID == 0)
return tmp;
3231 for(
auto& tj : slc.
tjs) {
3232 if(tj.AlgMod[
kKilled])
continue;
3233 if(tj.CTP != vx2.
CTP)
continue;
3234 for(
unsigned short end = 0;
end < 2; ++
end) {
3235 if(tj.VtxID[
end] == vx2.
ID) tmp.push_back(tj.ID);
3246 std::vector<int>
tmp;
3247 if(vx3.
ID == 0)
return tmp;
3250 for(
auto& vx2 : slc.
vtxs) {
3251 if(vx2.ID == 0)
continue;
3252 if(vx2.Vx3ID != vx3.
ID)
continue;
3254 tmp.insert(tmp.end(), vtxTjID2.begin(), vtxTjID2.end());
3258 if(nvx2 < 1)
return tmp;
3262 std::sort(tmp.begin(), tmp.end());
3271 std::vector<unsigned short>
tmp;
3272 if(pfp.
TjIDs.empty())
return tmp;
3273 for(
auto tjid : pfp.
TjIDs) {
3274 auto& tj = slc.
tjs[tjid - 1];
3275 for(
unsigned short end = 0;
end < 2; ++
end) {
3276 if(tj.VtxID[
end] == 0)
continue;
3277 auto& vx2 = slc.
vtxs[tj.VtxID[
end] - 1];
3278 if(vx2.Vx3ID == 0)
continue;
3279 if(std::find(tmp.begin(), tmp.end(), vx2.Vx3ID) != tmp.end())
continue;
3280 tmp.push_back(vx2.Vx3ID);
3302 unsigned short imBest = 0;
3303 for(
auto& vx2 : slc.
vtxs) {
3304 if(vx2.CTP != inVx2.
CTP)
continue;
3305 if(vx2.ID <= 0)
continue;
3307 if(pull < minPull) {
3321 unsigned short imBest = 0;
3322 for(
auto& oldvx3 : slc.
vtx3s) {
3323 if(oldvx3.ID == 0)
continue;
3326 if(pull < minPull) {
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 ReleaseHits(TCSlice &slc, Trajectory &tj)
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< Trajectory > tjs
vector of all trajectories in each plane
std::vector< Vtx3Store > vtx3s
3D vertices
void StepAway(TCSlice &slc, Trajectory &tj)
void VtxHitsSwap(TCSlice &slc, const CTP_t inCTP)
bool MergeWithVertex(TCSlice &slc, VtxStore &vx, unsigned short oVxID)
int PDGCodeVote(TCSlice &slc, std::vector< int > &tjIDs, bool prt)
void SetEndPoints(Trajectory &tj)
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
std::vector< float > kinkCuts
kink angle, nPts fit, (alternate) kink angle significance
bool InTrajOK(TCSlice &slc, std::string someText)
struct of temporary 2D vertices (end points)
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
FindVtxTraj algorithm tried.
void TrajPointTrajDOCA(TCSlice &slc, TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
static unsigned int kWire
CTP_t CTP
Cryostat, TPC, Plane code.
std::vector< float > maxPos0
bool FitVertex(TCSlice &slc, VtxStore &vx, bool prt)
std::vector< float > vtx3DCuts
2D vtx -> 3D vtx matching cuts
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
void PrintPFP(std::string someText, TCSlice &slc, const PFPStruct &pfp, bool printHeader)
vertex position fixed manually - no fitting done
std::array< std::bitset< 8 >, 2 > StopFlag
void SplitTrajCrossingVertices(TCSlice &slc, CTP_t inCTP)
Planes which measure X direction.
The data type to uniquely identify a Plane.
bool valIncreasing(SortEntry c1, SortEntry c2)
matched to a high-score 3D vertex
std::vector< unsigned int > Hits
step from US -> DS (true) or DS -> US (false)
bool StoreTraj(TCSlice &slc, Trajectory &tj)
float TrajPointVertexPull(TCSlice &slc, const TrajPoint &tp, const VtxStore &vx)
CryostatID_t Cryostat
Index of cryostat.
void PrintAllTraj(std::string someText, TCSlice &slc, unsigned short itj, unsigned short ipt, bool prtVtx)
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
bool AttachAnyTrajToVertex(TCSlice &slc, unsigned short ivx, bool prt)
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
bool dbgSlc
debug only in the user-defined slice? default is all slices
bool StartTraj(TCSlice &slc, Trajectory &tj, unsigned int fromhit, unsigned int tohit, unsigned short pass)
std::array< int, 2 > Vx3ID
void SetVx3Score(TCSlice &slc, Vtx3Store &vx3)
bool AttachPFPToVertex(TCSlice &slc, PFPStruct &pfp, unsigned short end, unsigned short vx3ID, bool prt)
bool IsGood
set false if there is a failure or the Tj fails quality cuts
float DeadWireCount(TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
bool StoreVertex(TCSlice &slc, VtxStore &vx)
bool Split3DKink(TCSlice &slc, PFPStruct &pfp, double sep, bool prt)
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
bool TrajTrajDOCA(TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
unsigned short Pass
the pass on which it was created
bool dbg3V
debug 3D vertex finding
std::vector< unsigned int > FindCloseHits(TCSlice &slc, std::array< int, 2 > const &wireWindow, Point2_t const &timeWindow, const unsigned short plane, HitStatus_t hitRequest, bool usePeakTime, bool &hitsNear)
struct of temporary 3D vertices
std::vector< unsigned short > GetPFPVertices(const TCSlice &slc, const PFPStruct &pfp)
std::array< float, 2 > Point2_t
std::vector< float > maxPos1
float unitsPerTick
scale factor from Tick to WSE equivalent units
std::array< Point3_t, 2 > XYZ
const detinfo::DetectorProperties * detprop
unsigned short NearestPtWithChg(TCSlice &slc, Trajectory &tj, unsigned short thePt)
CTP_t CTP
Cryostat, TPC, Plane code.
bool SignalBetween(TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction)
bool dbg2V
debug 2D vertex finding
std::vector< TrajPoint > Pts
Trajectory points.
bool ChkVtxAssociations(TCSlice &slc, const CTP_t &inCTP)
std::array< Vector3_t, 2 > Dir
bool DefinePFP(std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, bool prt)
std::vector< int > FindCloseTjs(TCSlice &slc, const TrajPoint &fromTp, const TrajPoint &toTp, const float &maxDelta)
float TrajLength(Trajectory &tj)
std::vector< float > neutralVxCuts
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}
bool SignalAtTp(TCSlice &slc, const TrajPoint &tp)
void ScoreVertices(TCSlice &slc)
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
unsigned short CloseEnd(TCSlice &slc, const Trajectory &tj, const Point2_t &pos)
std::string PrintHit(const TCHit &tch)
void SetPDGCode(TCSlice &slc, unsigned short itj, bool tjDone)
const geo::GeometryCore * geom
std::vector< unsigned short > minPts
min number of Pts required to make a trajectory
float TpSumHitChg(TCSlice &slc, TrajPoint const &tp)
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.
unsigned short FarEnd(TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
bool AnalyzePFP(TCSlice &slc, PFPStruct &pfp, bool prt)
vertex quality is suspect - No requirement made on chg btw it and the Tj
int ID
ID that is local to one slice.
void CompleteIncomplete3DVerticesInGaps(TCSlice &slc)
std::array< unsigned short, 2 > VtxID
ID of 2D vertex.
Detector simulation of raw signals on wires.
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
std::bitset< 16 > modes
number of points to find AveChg
std::vector< TCHit > slHits
bool MergeAndStore(TCSlice &slc, unsigned int itj1, unsigned int itj2, bool doPrt)
void FindVtxTjs(TCSlice &slc, VtxStore &vx2)
std::bitset< 16 > Stat
Vertex status bits using kVtxBit_t.
unsigned short IsCloseToVertex(TCSlice &slc, VtxStore &inVx2)
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
float ChgFracNearPos(TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
void CheckTraj(TCSlice &slc, Trajectory &tj)
std::vector< float > vtxScoreWeights
void SetHighScoreBits(TCSlice &slc, Vtx3Store &vx3)
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.
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
PFPStruct CreatePFP(TCSlice &slc)
std::vector< VtxStore > vtxs
2D vertices
short StepDir
-1 = going US (-> small wire#), 1 = going DS (-> large wire#)
std::bitset< 128 > AlgMod
Bit set if algorithm AlgBit_t modifed the trajectory.
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const VtxStore &vx2)
unsigned short MatchVecIndex
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...)
unsigned short Vx3Topo(TCSlice &slc, Vtx3Store &vx3)
std::vector< recob::Hit > const * allHits
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
void Find2DVertices(TCSlice &slc, const CTP_t &inCTP, unsigned short pass)
std::vector< unsigned int > nWires
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
void KillPoorVertices(TCSlice &slc)
int ID
ID of the recob::Slice (not the sub-slice)
unsigned short TPNearVertex(TCSlice &slc, const TrajPoint &tp)
void SetVx2Score(TCSlice &slc)
std::vector< T > SetDifference(const std::vector< T > &set1, const std::vector< T > &set2)
void FindHammerVertices(TCSlice &slc, const CTP_t &inCTP)
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
std::vector< MatchStruct > matchVec
3D matching vector
void CompleteIncomplete3DVertices(TCSlice &slc)
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
std::vector< PFPStruct > pfps
void FindNeutralVertices(TCSlice &slc)
void MoveTPToWire(TrajPoint &tp, float wire)
void PosInPlane(const TCSlice &slc, const Vtx3Store &vx3, unsigned short plane, Point2_t &pos)
float VertexVertexPull(TCSlice &slc, const Vtx3Store &vx1, const Vtx3Store &vx2)
void MakeJunkVertices(TCSlice &slc, const CTP_t &inCTP)
bool SplitTraj(TCSlice &slc, unsigned short itj, float XPos, bool makeVx2, bool prt)
TPCID_t TPC
Index of the TPC within its cryostat.
bool StorePFP(TCSlice &slc, PFPStruct &pfp)
void Find3DVertices(TCSlice &slc)
void PrintHeader(std::string someText)
void FindHammerVertices2(TCSlice &slc, const CTP_t &inCTP)
float TjChgFrac
Fraction of charge near the vertex that is from hits on the vertex Tjs.
master switch for turning on debug mode
void PrintTrajPoint(std::string someText, TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
void ChkVxTjs(TCSlice &slc, const CTP_t &inCTP, bool prt)
bool CompatibleMerge(TCSlice &slc, std::vector< int > &tjIDs, bool prt)
bool HasWire(geo::WireID const &wireid) const
Returns whether we have the specified wire.
void Match3DVtxTjs(TCSlice &slc, bool prt)