20 if(
slices.size() < 2)
return;
29 std::string fcnLabel =
"SP";
31 bool printHeader =
true;
32 for(
size_t isl = 0; isl <
slices.size(); ++isl) {
35 if(slc.pfps.empty())
continue;
36 for(
auto& pfp : slc.pfps)
PrintP(fcnLabel, myprt, pfp, printHeader);
41 std::vector<std::vector<int>> stLists;
42 for(
unsigned short sl1 = 0; sl1 <
slices.size() - 1; ++sl1) {
44 for(
unsigned short sl2 = sl1 + 1; sl2 <
slices.size(); ++sl2) {
47 if(slc1.ID != slc2.ID)
continue;
48 for(
auto& p1 : slc1.pfps) {
49 if(p1.ID <= 0)
continue;
51 if(p1.PDGCode == 1111)
continue;
52 for(
auto& p2 : slc2.pfps) {
53 if(p2.ID <= 0)
continue;
55 if(p2.PDGCode == 1111)
continue;
59 for(
unsigned short e1 = 0; e1 < 2; ++e1) {
60 auto& pos1 = p1.XYZ[e1];
63 auto& dir1 = p1.Dir[e1];
64 for(
unsigned short e2 = 0; e2 < 2; ++e2) {
65 auto& pos2 = p2.XYZ[e2];
68 auto& dir2 = p2.Dir[e2];
69 float sep =
PosSep2(pos1, pos2);
70 if(sep > maxSep2)
continue;
71 float cth = std::abs(
DotProd(dir1, dir2));
72 if(cth < maxCth)
continue;
81 myprt<<
"Stitch slice "<<slc1.ID<<
" P"<<p1.UID<<
" TPC "<<p1.TPCID.TPC;
82 myprt<<
" and P"<<p2.UID<<
" TPC "<<p2.TPCID.TPC;
83 myprt<<
" sep "<<sqrt(maxSep2)<<
" maxCth "<<maxCth;
87 for(
auto& pm : stLists) {
88 bool p1InList = (std::find(pm.begin(), pm.end(), p1.UID) != pm.end());
89 bool p2InList = (std::find(pm.begin(), pm.end(), p2.UID) != pm.end());
90 if(p1InList || p2InList) {
91 if(p1InList) pm.push_back(p2.UID);
92 if(p2InList) pm.push_back(p1.UID);
98 std::vector<int>
tmp(2);
101 stLists.push_back(tmp);
107 if(stLists.empty())
return;
109 for(
auto& stl : stLists) {
112 std::pair<unsigned short, unsigned short> minZIndx;
113 unsigned short minZEnd = 2;
114 for(
auto puid : stl) {
116 if(slcIndex.first == USHRT_MAX)
continue;
117 auto& pfp =
slices[slcIndex.first].pfps[slcIndex.second];
118 for(
unsigned short end = 0;
end < 2; ++
end) {
119 if(pfp.XYZ[
end][2] < minZ) { minZ = pfp.XYZ[
end][2]; minZIndx = slcIndex; minZEnd =
end; }
122 if(minZEnd > 1)
continue;
124 auto& pfp =
slices[minZIndx.first].pfps[minZIndx.second];
129 for(
auto puid : stl) {
130 if(puid == pfp.UID)
continue;
132 if(sIndx.first == USHRT_MAX)
continue;
133 auto& opfp =
slices[sIndx.first].pfps[sIndx.second];
135 pfp.TjUIDs.insert(pfp.TjUIDs.end(), opfp.TjUIDs.begin(), opfp.TjUIDs.end());
138 if(opfp.ParentUID > 0) {
140 if(pSlcIndx.first <
slices.size()) {
141 auto& parpfp =
slices[pSlcIndx.first].pfps[pSlcIndx.second];
142 std::replace(parpfp.DtrUIDs.begin(), parpfp.DtrUIDs.begin(), opfp.UID, pfp.UID);
145 for(
auto dtruid : opfp.DtrUIDs) {
147 if(dSlcIndx.first <
slices.size()) {
148 auto& dtrpfp =
slices[dSlcIndx.first].pfps[dSlcIndx.second];
149 dtrpfp.ParentUID = pfp.UID;
166 if(oldTj <= 0 || oldTj > (
int)slc.
tjs.size())
return;
167 if(newTj <= 0 || newTj > (
int)slc.
tjs.size())
return;
173 auto& ntj = slc.
tjs[newTj - 1];
174 unsigned short npts = ntj.EndPt[1] - ntj.EndPt[0] + 1;
176 std::vector<float> xpos(ntj.Pts.size());
178 for(
unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
179 auto& ntp = ntj.Pts[npt];
180 if(ntp.Chg <= 0)
continue;
185 for(
unsigned int ipt = 0; ipt < slc.
mallTraj.size(); ++ipt) {
187 if(tj2pt.id > slc.
tjs.size())
continue;
188 if(tj2pt.id != oldtjid)
continue;
190 for(
unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
191 auto& ntp = ntj.Pts[npt];
192 if(ntp.Chg <= 0)
continue;
193 if(std::nearbyint(ntp.Pos[0]) == tj2pt.wire && xpos[npt] > tj2pt.xlo && xpos[npt] < tj2pt.xhi) {
204 if(!slc.
pfps.empty()) {
205 for(
auto& pfp : slc.
pfps) {
206 for(
auto& tp3 : pfp.Tp3s) {
208 for(
auto& tj2pt : tp3.Tj2Pts) {
209 if(tj2pt.id > slc.
tjs.size())
continue;
210 if(tj2pt.id != oldtjid)
continue;
212 for(
unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
213 auto& ntp = ntj.Pts[npt];
214 if(std::nearbyint(ntp.Pos[0]) == tj2pt.wire && xpos[npt] > tj2pt.xlo && xpos[npt] < tj2pt.xhi) {
232 if(oldTj <= 0 || oldTj > (
int)slc.
tjs.size())
return;
233 if(newTj <= 0 || newTj > (
int)slc.
tjs.size())
return;
237 unsigned short oldtjid = oldTj;
238 unsigned short newtjid = newTj;
239 auto& ntj = slc.
tjs[newTj - 1];
240 unsigned short npts = ntj.EndPt[1] - ntj.EndPt[0] + 1;
242 std::vector<float> xpos(ntj.Pts.size());
244 for(
unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
245 auto& ntp = ntj.Pts[npt];
246 if(ntp.Chg <= 0)
continue;
250 for(
auto& tp3 : pfp.
Tp3s) {
252 for(
auto& tj2pt : tp3.Tj2Pts) {
253 if(tj2pt.id > slc.
tjs.size())
continue;
254 if(tj2pt.id != oldtjid)
continue;
256 for(
unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
257 auto& ntp = ntj.Pts[npt];
258 if(std::nearbyint(ntp.Pos[0]) == tj2pt.wire && xpos[npt] > tj2pt.xlo && xpos[npt] < tj2pt.xhi) {
281 unsigned int ntp = 0;
282 for(
auto& tj : slc.
tjs) {
284 if(tj.ID <= 0)
continue;
286 if((
int)planeID.
Cryostat != cstat)
continue;
287 if((
int)planeID.
TPC != tpc)
continue;
289 tj.AlgMod[
kMat3D] =
false;
296 unsigned int icnt = 0;
297 for(
auto& tj : slc.
tjs) {
300 if((
int)planeID.
Cryostat != cstat)
continue;
301 if((
int)planeID.
TPC != tpc)
continue;
302 int plane = planeID.
Plane;
304 if(tjID <= 0)
continue;
307 for(
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
308 auto& tp = tj.Pts[ipt];
309 if(tp.Chg == 0)
continue;
310 if(icnt > slc.
mallTraj.size() - 1)
break;
311 if(tp.Pos[0] < -0.4)
continue;
312 slc.
mallTraj[icnt].wire = std::nearbyint(tp.Pos[0]);
315 if(!hasWire)
continue;
320 if(icnt == slc.
mallTraj.size())
break;
321 slc.
mallTraj[icnt].xlo = xpos - rms;
322 slc.
mallTraj[icnt].xhi = xpos + rms;
327 slc.
mallTraj[icnt].npts = tj.EndPt[1] - tj.EndPt[0] + 1;
336 std::vector<SortEntry> sortVec(slc.
mallTraj.size());
337 for(
unsigned int ipt = 0; ipt < slc.
mallTraj.size(); ++ipt) {
339 sortVec[ipt].index = ipt;
340 sortVec[ipt].val = slc.
mallTraj[ipt].xlo;
346 for(
unsigned int ii = 0; ii < sortVec.size(); ++ii) slc.
mallTraj[ii] = tallTraj[sortVec[ii].index];
359 if(pfp.
ID <= 0 || pfp.
TjIDs.empty())
return false;
360 if(pfp.
Tp3s.size() < 2)
return false;
364 float minAlong = 1E6;
365 unsigned short minPt = 0;
366 float maxAlong = -1E6;
367 unsigned short maxPt = 0;
368 std::vector<SortEntry> sortVec(pfp.
Tp3s.size());
369 for(
unsigned short ipt = 0; ipt < pfp.
Tp3s.size(); ++ipt) {
370 auto& tp3 = pfp.
Tp3s[ipt];
371 sortVec[ipt].index = ipt;
372 sortVec[ipt].val = tp3.AlongTrans[0];
374 if(tp3.AlongTrans[0] < minAlong) {
375 minAlong = tp3.AlongTrans[0];
378 if(tp3.AlongTrans[0] > maxAlong) {
379 maxAlong = tp3.AlongTrans[0];
384 pfp.
XYZ[0] = pfp.
Tp3s[minPt].Pos;
385 pfp.
XYZ[1] = pfp.
Tp3s[maxPt].Pos;
388 mf::LogVerbatim(
"TC")<<
"SNS: P"<<pfp.
ID<<
" minPt "<<minPt<<
" maxPt "<<maxPt<<
" dir "<<std::fixed<<std::setprecision(2)<<pfp.
Dir[0][0]<<
" "<<pfp.
Dir[0][1]<<
" "<<pfp.
Dir[0][2];
395 std::vector<TrajPoint3> temp;
396 for(
unsigned short ii = 0; ii < sortVec.size(); ++ii) temp.push_back(pfp.
Tp3s[sortVec[ii].index]);
410 if(pfp.
Tp3s.size() < 2)
return;
412 unsigned short startPt = 0;
413 unsigned short endPt = pfp.
Tp3s.size() - 1;
416 constexpr
float sectionLen = 5;
417 float endAlong = pfp.
Tp3s[0].AlongTrans[0] + sectionLen;
418 std::vector<Vector3_t> sectionPos;
419 sectionPos.push_back(pfp.
Tp3s[0].Pos);
420 std::vector<unsigned short> sectionPt;
421 sectionPt.push_back(0);
422 for(
unsigned short section = 0; section < 100; ++section) {
426 unsigned short cnt = 0;
427 for(
unsigned short ipt = startPt; ipt < endPt; ++ipt) {
428 auto& tp3 = pfp.
Tp3s[ipt];
432 if(tp3.AlongTrans[1] > 2)
continue;
433 if(tp3.AlongTrans[0] < endAlong) {
435 for(
unsigned short xyz = 0; xyz < 3; ++xyz) {
436 avePos[xyz] += tp3.Pos[xyz];
437 aveDir[xyz] += tp3.Dir[xyz];
443 if(cnt == 0)
continue;
445 for(
unsigned short xyz = 0; xyz < 3; ++xyz) avePos[xyz] /= cnt;
452 sectionPos.push_back(avePos);
453 sectionPt.push_back(ipt);
455 endAlong += sectionLen;
459 sectionPos.push_back(pfp.
Tp3s[endPt].Pos);
460 sectionPt.push_back(pfp.
Tp3s.size() - 1);
468 for(
auto tjid : pfp.
TjIDs) {
469 auto& tj = slc.
tjs[tjid - 1];
470 for(
auto& tp : tj.Pts) tp.Environment[
kEnvFlag] =
false;
473 for(
auto tj2pt : pfp.
Tp3s[0].Tj2Pts) {
474 slc.
tjs[tj2pt.id - 1].Pts[tj2pt.ipt].Environment[
kEnvFlag] =
true;
477 std::vector<TrajPoint3> ntp3;
478 ntp3.push_back(pfp.
Tp3s[0]);
481 std::vector<Point2_t> startPos2D(slc.
nPlanes);
483 unsigned short lastPtAdded = 0;
484 for(
unsigned short section = 1; section < sectionPt.size(); ++section) {
485 Point3_t startPos = sectionPos[section - 1];
486 Point3_t endPos = sectionPos[section];
489 if(section == 1) pfp.
Dir[0] = startDir;
491 pfp.
Dir[1] = startDir;
494 for(
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
496 startPos2D[plane][0] =
tcc.
geom->
WireCoordinate(sectionPos[section - 1][1], sectionPos[section - 1][2], planeID);
499 for(
unsigned short ipt = sectionPt[section - 1]; ipt < sectionPt[section]; ++ipt) {
500 auto& tp3 = pfp.
Tp3s[ipt];
502 unsigned short nused = 0;
503 bool big2DSep =
false;
504 for(
auto tj2pt : pfp.
Tp3s[ipt].Tj2Pts) {
505 auto& tp = slc.
tjs[tj2pt.id - 1].Pts[tj2pt.ipt];
506 if(tp.Environment[
kEnvFlag]) ++nused;
509 if(sep2D > sectionLen) big2DSep =
true;
511 if(big2DSep || nused > 1)
continue;
514 if(alongTrans[1] > 0.5)
continue;
520 tp3.AlongTrans = alongTrans;
525 for(
auto tj2pt : tp3.Tj2Pts) slc.
tjs[tj2pt.id - 1].Pts[tj2pt.ipt].Environment[
kEnvFlag] =
true;
530 if(lastPtAdded != endPt) ntp3.push_back(pfp.
Tp3s[endPt]);
533 float len =
PosSep(ntp3[0].Pos, ntp3[ntp3.size()-1].Pos);
534 mf::LogVerbatim(
"TC")<<
"FollowTp3s: Tp3s size in "<<pfp.
Tp3s.size()<<
" size out "<<ntp3.size()<<
" len "<<std::fixed<<std::setprecision(2)<<len;
538 if(pfp.
Vx3ID[0] > 0) {
540 Point3_t vpos = {{vx3.X, vx3.Y, vx3.Z}};
541 auto& firstTp3Pos = ntp3[0].Pos;
542 auto& lastTp3Pos = ntp3[ntp3.size() - 1].Pos;
543 if(
PosSep2(lastTp3Pos, vpos) <
PosSep2(firstTp3Pos, vpos)) std::reverse(ntp3.begin(), ntp3.end());
550 pfp.
XYZ[0] = ntp3[0].Pos;
551 pfp.
XYZ[1] = ntp3[ntp3.size()-1].Pos;
558 return FitTp3s(slc, tp3s, 0, tp3s.size(), pos,
dir, rCorr);
565 if(tp3s.size() < 3)
return false;
566 if(fromPt >= toPt)
return false;
567 if(toPt > tp3s.size())
return false;
570 std::vector<unsigned short> useID;
571 std::vector<unsigned short> useIpt;
572 std::vector<unsigned short> cntInPln(slc.
nPlanes);
573 for(
unsigned short ipt = fromPt; ipt < toPt; ++ipt) {
574 auto& tp3 = tp3s[ipt];
575 for(
auto& tj2pt : tp3.Tj2Pts) {
577 for(
unsigned short ii = 0; ii < useID.size(); ++ii) {
578 if(tj2pt.id == useID[ii] && tj2pt.ipt == useIpt[ii]) isUsed =
true;
582 useID.push_back(tj2pt.id);
583 useIpt.push_back(tj2pt.ipt);
584 auto& tj = slc.
tjs[tj2pt.id - 1];
589 unsigned short enufInPlane = 0;
590 for(
unsigned short plane = 0; plane < slc.
nPlanes; ++plane)
if(cntInPln[plane] > 1) ++enufInPlane;
591 if(enufInPlane < 2)
return false;
593 const unsigned int nvars = 4;
594 unsigned int npts = useID.size();
595 TMatrixD A(npts, nvars);
601 for(
unsigned short ipt = 0; ipt < useID.size(); ++ipt) {
602 auto& tp = slc.
tjs[useID[ipt] - 1].Pts[useIpt[ipt]];
606 x0 /= (double)useID.size();
609 for(
unsigned short ipt = 0; ipt < useID.size(); ++ipt) {
610 auto& tp = slc.
tjs[useID[ipt] - 1].Pts[useIpt[ipt]];
612 unsigned int cstat = planeID.
Cryostat;
613 unsigned int tpc = planeID.
TPC;
614 unsigned int plane = planeID.
Plane;
622 A[ipt][0] = wght * cw;
623 A[ipt][1] = wght *
sw;
624 A[ipt][2] = wght * cw *
x;
625 A[ipt][3] = wght * sw *
x;
626 w[ipt] = wght * (tp.Pos[0] - off);
631 TVectorD tVec = svd.Solve(w, ok);
632 double norm = sqrt(1 + tVec[2] * tVec[2] + tVec[3] * tVec[3]);
634 dir[1] = tVec[2] /
norm;
635 dir[2] = tVec[3] /
norm;
653 if(tj2pts.size() < 4)
return false;
655 const unsigned int nvars = 4;
656 unsigned int npts = tj2pts.size();
657 TMatrixD A(npts, nvars);
662 for(
auto& tj2pt : tj2pts) {
663 auto& tp = slc.
tjs[tj2pt.id - 1].Pts[tj2pt.ipt];
667 x0 /= (double)tj2pts.size();
669 unsigned short ninpl[3] = {0};
670 unsigned short nok = 0;
672 for(
unsigned short ipt = 0; ipt < tj2pts.size(); ++ipt) {
673 auto& tj2pt = tj2pts[ipt];
674 auto& tp = slc.
tjs[tj2pt.id - 1].Pts[tj2pt.ipt];
676 unsigned int cstat = planeID.
Cryostat;
677 unsigned int tpc = planeID.
TPC;
678 unsigned int plane = planeID.
Plane;
686 A[ipt][0] = wght * cw;
687 A[ipt][1] = wght *
sw;
688 A[ipt][2] = wght * cw *
x;
689 A[ipt][3] = wght * sw *
x;
690 w[ipt] = wght * (tp.Pos[0] - off);
693 if(ninpl[plane] == 2) ++nok;
697 if(nok < 2)
return false;
701 TVectorD tVec = svd.Solve(w, ok);
707 double norm = sqrt(1 + tVec[2] * tVec[2] + tVec[3] * tVec[3]);
708 fitDir[0] = 1 /
norm;
709 fitDir[1] = tVec[2] /
norm;
710 fitDir[2] = tVec[3] /
norm;
717 if(tp3.
Pos[2] != 0) {
718 double dz = tp3.
Pos[2] - fitPos[2];
719 fitPos[0] += dz * fitDir[0] / fitDir[2];
720 fitPos[1] += dz * fitDir[1] / fitDir[2];
725 std::cout<<
"Crazy fitPos "<<
PosSep(fitPos, tp3.
Pos)<<
"\n";
744 if(pfp.
TjIDs.size() < 2)
return;
751 if(fillTp3s) pfp.
Tp3s.clear();
753 bool twoPlanes = (slc.
nPlanes == 2);
754 bool twoTjs = (pfp.
TjIDs.size() == 2);
756 bool smallAngle =
false;
758 smallAngle = (pfp.
Dir[0][0] != 0 && std::abs(pfp.
Dir[0][0]) < 0.1);
766 if(doFit)
Fit3D(0, point, dir, point, dir);
770 std::vector<unsigned short> tjids(pfp.
TjIDs.size());
772 std::vector<std::vector<bool>> tjptMat3;
774 std::vector<std::vector<bool>> tjptMat2;
776 std::vector<unsigned short> tjplane;
778 unsigned int maxTp3Size = 10000;
780 for(
unsigned short itj = 0; itj < pfp.
TjIDs.size(); ++itj) {
781 if(pfp.
TjIDs[itj] <= 0) {
782 std::cout<<
"FindCompleteness: Bad tjid "<<pfp.
TjIDs[itj]<<
"\n";
785 tjids[itj] = pfp.
TjIDs[itj];
786 auto& tj = slc.
tjs[pfp.
TjIDs[itj] - 1];
787 std::vector<bool>
tmp(tj.Pts.size(),
false);
788 tjptMat2.push_back(
tmp);
789 if(!twoPlanes) tjptMat3.push_back(
tmp);
793 for(
unsigned int ipt = 0; ipt < slc.
mallTraj.size() - 1; ++ipt) {
795 unsigned short indx = 0;
796 for(indx = 0; indx < tjids.size(); ++indx)
if(iTjPt.id == tjids[indx])
break;
798 if(indx == tjids.size())
continue;
799 auto& itj = slc.
tjs[iTjPt.id - 1];
801 auto& itp = itj.Pts[iTjPt.ipt];
805 for(
unsigned int jpt = ipt + 1; jpt < slc.
mallTraj.size() - 1; ++jpt) {
808 if(jTjPt.ctp == iTjPt.ctp)
continue;
809 unsigned short jndx = 0;
810 for(jndx = 0; jndx < tjids.size(); ++jndx)
if(jTjPt.id == tjids[jndx])
break;
812 if(jndx == tjids.size())
continue;
814 if(jTjPt.xlo > iTjPt.xhi)
continue;
816 if(jTjPt.xlo > iTjPt.xhi + 5)
break;
817 auto& jtj = slc.
tjs[jTjPt.id - 1];
819 auto& jtp = jtj.Pts[jTjPt.ipt];
821 if(!
MakeTp3(slc, itp, jtp, ijtp3,
true))
continue;
826 tjptMat2[indx][iTjPt.ipt] =
true;
827 tjptMat2[jndx][jTjPt.ipt] =
true;
829 if(fillTp3s && pfp.
Tp3s.size() < maxTp3Size) {
833 if(smallAngle) saveIt = ijtp3.
AlongTrans[1] < 1;
834 if(saveIt) pfp.
Tp3s.push_back(ijtp3);
836 if(doFit)
Fit3D(1, ijtp3.
Pos, ijtp3.
Dir, point, dir);
841 unsigned short kplane = 3 - iplane - jplane;
843 if(fwire < -0.4)
continue;
844 unsigned int kwire = std::nearbyint(fwire);
847 if(doFit)
Fit3D(1, ijtp3.
Pos, ijtp3.
Dir, point, dir);
849 if(fillTp3s && pfp.
Tp3s.size() < maxTp3Size) {
852 if(smallAngle) saveIt = ijtp3.
AlongTrans[1] < 1;
853 if(saveIt) pfp.
Tp3s.push_back(ijtp3);
857 for(
unsigned int kpt = jpt + 1; kpt < slc.
mallTraj.size(); ++kpt) {
860 if(kTjPt.ctp == iTjPt.ctp || kTjPt.ctp == jTjPt.ctp)
continue;
862 unsigned short kndx = 0;
863 for(kndx = 0; kndx < tjids.size(); ++kndx)
if(kTjPt.id == tjids[kndx])
break;
865 if(!fillTp3s && kndx == tjids.size())
continue;
866 if(kTjPt.xlo > iTjPt.xhi)
continue;
868 if(kTjPt.xlo > iTjPt.xhi + 5)
break;
869 auto& ktj = slc.
tjs[kTjPt.id - 1];
871 auto& ktp = ktj.Pts[kTjPt.ipt];
873 if(!
MakeTp3(slc, itp, ktp, iktp3,
true))
continue;
874 if(std::abs(ijtp3.
Pos[1] - iktp3.
Pos[1]) > yzcut)
continue;
875 if(std::abs(ijtp3.
Pos[2] - iktp3.
Pos[2]) > yzcut)
continue;
879 ijktp3.
Tj2Pts.push_back(kTjPt);
881 if(doFit)
Fit3D(1, iktp3.
Pos, iktp3.
Dir, point, dir);
883 if(fillTp3s && pfp.
Tp3s.size() < maxTp3Size) {
885 ijktp3.dEdx = (2 * ijktp3.dEdx + ktp.Chg) / 3;
888 if(smallAngle) saveIt = ijktp3.AlongTrans[1] < 1;
889 if(saveIt) pfp.
Tp3s.push_back(ijktp3);
892 if(kndx == tjids.size())
continue;
893 tjptMat3[indx][iTjPt.ipt] =
true;
894 tjptMat3[jndx][jTjPt.ipt] =
true;
895 tjptMat3[kndx][kTjPt.ipt] =
true;
903 myprt<<
"FC: P"<<pfp.
ID<<
" fit pos "<<std::fixed<<std::setprecision(1)<<pfp.
XYZ[0][0]<<
" "<<pfp.
XYZ[0][1]<<
" "<<pfp.
XYZ[0][2];
904 myprt<<
" fit dir "<<std::setprecision(2)<<pfp.
Dir[0][0]<<
" "<<pfp.
Dir[0][1]<<
" "<<pfp.
Dir[0][2];
905 myprt<<
" Note: fit pos is the average position of all Tp3s - not the start or end.";
914 for(
unsigned short itj = 0; itj < tjids.size(); ++itj) {
915 auto& tj = slc.
tjs[tjids[itj] - 1];
920 for(
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
921 if(tj.Pts[ipt].Chg <= 0)
continue;
923 if(tjptMat2[itj][ipt]) ++cnt2;
924 if(!twoPlanes && tjptMat3[itj][ipt]) ++cnt3;
936 myprt<<
"FC: P"<<pfp.
ID<<
" T"<<tj.ID<<
" npwc "<<npwc<<
" cnt2 "<<cnt2<<
" cnt3 "<<cnt3<<
" PDGCode "<<tj.PDGCode;
937 myprt<<
" MCSMom "<<tj.MCSMom<<
" InShower? "<<tj.SSID;
938 myprt<<
" TjCompleteness "<<std::setprecision(2)<<pfp.
TjCompleteness[itj];
942 pfp.
EffPur = tcnt2 / tnpwc;
944 pfp.
EffPur = tcnt3 / tnpwc;
956 if(pfp.
TjIDs.empty() || pfp.
Tp3s.empty())
return;
960 std::vector<float> projInPlane(slc.
nPlanes);
961 for(
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
964 projInPlane[plane] = tp.Delta;
967 std::vector<unsigned short> pfpTjs;
968 std::vector<unsigned short> usMissTjs;
969 std::vector<std::vector<bool>> misTjPtMat;
970 for(
auto tjid : pfp.
TjIDs) pfpTjs.push_back((
unsigned short)tjid);
971 for(
auto& tp3 : pfp.
Tp3s) {
972 for(
auto& tj2pt : tp3.Tj2Pts) {
973 if(std::find(pfpTjs.begin(), pfpTjs.end(), tj2pt.id) != pfpTjs.end())
continue;
975 unsigned short mtjIndx = 0;
976 for(mtjIndx = 0; mtjIndx < usMissTjs.size(); ++mtjIndx)
if(tj2pt.id == usMissTjs[mtjIndx])
break;
977 if(mtjIndx == usMissTjs.size()) {
979 auto& mtj = slc.
tjs[tj2pt.id - 1];
982 usMissTjs.push_back(tj2pt.id);
984 std::vector<bool> ptMat(mtj.Pts.size(),
false);
985 ptMat[tj2pt.ipt] =
true;
986 misTjPtMat.push_back(ptMat);
988 if(tj2pt.ipt < misTjPtMat[mtjIndx].size()) misTjPtMat[mtjIndx][tj2pt.ipt] =
true;
992 for(
unsigned short im = 0; im < usMissTjs.size(); ++im) {
993 int mtjid = usMissTjs[im];
997 auto& mtj = slc.
tjs[mtjid - 1];
1000 for(
unsigned short ipt = mtj.EndPt[0]; ipt <= mtj.EndPt[1]; ++ipt) {
1001 auto& mtp = mtj.Pts[ipt];
1002 if(mtp.Chg <= 0)
continue;
1004 if(misTjPtMat[im][ipt]) ++
mat;
1006 float frac = mat / cnt;
1008 if(frac < 0.1)
continue;
1010 float lenInPlane = 0;
1011 for(
auto tjid : pfp.
TjIDs) {
1012 auto& tj = slc.
tjs[tjid - 1];
1013 if(tj.CTP != mtj.CTP)
continue;
1014 float len =
PosSep(tj.Pts[tj.EndPt[0]].Pos, tj.Pts[tj.EndPt[1]].Pos);
1015 if(len > lenInPlane) lenInPlane = len;
1017 if(cnt < 0.05 * lenInPlane)
continue;
1020 missTjs.push_back(mtjid);
1021 missFrac.push_back(frac);
1030 for(
unsigned short end = 0;
end < 2; ++
end) {
1036 if(!shared.empty())
return true;
1048 static double fSum, fSumx, fSumy, fSumz;
1051 static double fSumDir0, fSumDir1, fSumDir2;
1054 fSum = 0; fSumx = 0; fSumy = 0; fSumz = 0;
1056 fSumDir0 = 0; fSumDir1 = 0; fSumDir2 = 0;
1078 if(fSum < 2)
return;
1080 fitPos[0] = fSumx / fSum;
1081 fitPos[1] = fSumy / fSum;
1082 fitPos[2] = fSumz / fSum;
1084 fitDir = {{fSumDir0, fSumDir1, fSumDir2}};
1093 if(tjids.empty())
return 0;
1096 float fLoWire = 1E6;
1097 float fHiWire = -1E6;
1098 for(
auto tjid : tjids) {
1099 auto& tj = slc.
tjs[tjid - 1];
1100 if(tj.CTP != inCTP)
continue;
1101 for(
unsigned short end = 0;
end < 2; ++
end) {
1102 float endWire = tj.Pts[tj.EndPt[
end]].Pos[0];
1103 if(endWire < -0.4)
continue;
1104 if(endWire < fLoWire) fLoWire = endWire;
1105 if(endWire > fHiWire) fHiWire = endWire;
1108 if(fLoWire >= fHiWire)
return 0;
1109 unsigned int loWire = std::nearbyint(fLoWire);
1110 unsigned short nWires = std::nearbyint(fHiWire) - loWire + 1;
1111 std::vector<bool> ptOnWire(nWires,
false);
1115 for(
auto tjid : tjids) {
1116 auto& tj = slc.
tjs[tjid - 1];
1117 if(tj.CTP != inCTP)
continue;
1118 for(
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1119 auto& tp = tj.Pts[ipt];
1120 if(tp.Chg <= 0)
continue;
1121 if(tp.Pos[0] < -0.4)
continue;
1123 unsigned short indx = std::nearbyint(tp.Pos[0]) - loWire;
1124 if(indx < nWires) ptOnWire[indx] =
true;
1127 if(npwc == 0)
return 0;
1129 for(
unsigned short indx = 0; indx < nWires; ++indx)
if(!ptOnWire[indx]) ++nskip;
1130 return (nskip / npwc);
1138 if(tjids.empty())
return 0;
1140 std::vector<Point2_t> endPos;
1141 for(
auto tjid : tjids) {
1142 auto& tj = slc.
tjs[tjid - 1];
1143 if(tj.CTP != inCTP)
continue;
1144 endPos.push_back(tj.Pts[tj.EndPt[0]].Pos);
1145 endPos.push_back(tj.Pts[tj.EndPt[1]].Pos);
1147 if(endPos.size() < 2)
return 0;
1149 for(
unsigned short pt1 = 0; pt1 < endPos.size() - 1; ++pt1) {
1150 for(
unsigned short pt2 = pt1 + 1; pt2 < endPos.size(); ++pt2) {
1151 float sep =
PosSep2(endPos[pt1], endPos[pt2]);
1152 if(sep > extent) extent = sep;
1155 return sqrt(extent);
1164 if(itj > pfp.
TjIDs.size() - 1)
return false;
1165 if(slc.
matchVec.empty())
return false;
1167 int theTj = pfp.
TjIDs[itj];
1170 unsigned short oldSize = pfp.
TjIDs.size();
1172 for(
unsigned int ims = 0; ims < slc.
matchVec.size(); ++ims) {
1175 unsigned short tjIndex = 0;
1176 for(tjIndex = 0; tjIndex < ms.TjIDs.size(); ++tjIndex)
if(ms.TjIDs[tjIndex] == theTj)
break;
1177 if(tjIndex == ms.TjIDs.size())
continue;
1179 if(shared.empty())
continue;
1182 bool isWorse = (ms.TjCompleteness[tjIndex] < pfp.
TjCompleteness[itj]);
1183 if(shared.size() < 2 && isWorse)
continue;
1186 if(shared.size() < 2)
continue;
1189 for(
auto tjid : ms.TjIDs) {
1190 if(std::find(pfp.
TjIDs.begin(), pfp.
TjIDs.end(), tjid) != pfp.
TjIDs.end())
continue;
1191 pfp.
TjIDs.push_back(tjid);
1198 if(pfp.
TjIDs.size() > oldSize)
return true;
1208 if(pfp.
TjIDs.empty())
return false;
1209 if(pfp.
Tp3s.empty())
return false;
1212 unsigned short nplanes = TPC.
Nplanes();
1215 std::vector<unsigned short> cntInPln(nplanes);
1217 for(
auto tjid : pfp.
TjIDs) {
1218 auto& tj = slc.
tjs[tjid - 1];
1221 if(cntInPln[plane] > 1) itsOK =
false;
1223 if(itsOK)
return true;
1226 std::vector<int> newTjIDs;
1230 myprt<<
"MergePFPTjs: P"<<pfp.
ID<<
" in";
1231 for(
auto tjid : pfp.
TjIDs) myprt<<
" T"<<tjid;
1234 for(
unsigned short plane = 0; plane < nplanes; ++plane) {
1237 std::vector<unsigned short> tjids;
1238 for(
auto tjid : pfp.
TjIDs)
if(slc.
tjs[tjid - 1].CTP == inCTP) tjids.push_back((
unsigned short)tjid);
1240 if(tjids.size() == 1) {
1241 newTjIDs.push_back((
int)tjids[0]);
1245 if(tjids.size() == 0)
continue;
1252 std::vector<std::array<unsigned short, 2>> firstPts;
1253 for(
unsigned short itp3 = 0; itp3 < pfp.
Tp3s.size(); ++itp3) {
1254 auto& tp3 = pfp.
Tp3s[itp3];
1255 for(
auto& tj2pt : tp3.Tj2Pts) {
1256 unsigned short tjIndx = 0;
1257 for(tjIndx = 0; tjIndx < tjids.size(); ++tjIndx)
if(tj2pt.id == tjids[tjIndx])
break;
1258 if(tjIndx == tjids.size())
continue;
1260 unsigned short firstPtsIndx = 0;
1261 for(firstPtsIndx = 0; firstPtsIndx < firstPts.size(); ++firstPtsIndx)
if(tj2pt.id == firstPts[firstPtsIndx][0])
break;
1262 if(firstPtsIndx == firstPts.size()) {
1264 std::array<unsigned short, 2> firstPt {{tj2pt.id, tj2pt.ipt}};
1265 firstPts.push_back(firstPt);
1269 if(firstPts.empty())
continue;
1277 for(
auto firstPt : firstPts) {
1279 auto tj = slc.
tjs[firstPt[0] - 1];
1280 unsigned short midPt = 0.5 * (tj.EndPt[0] + tj.EndPt[1]);
1285 mtj.
VtxID[0] = tj.VtxID[0];
1287 mtj.
VtxID[1] = tj.VtxID[1];
1289 for(
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1290 auto& tp = tj.Pts[ipt];
1291 if(tp.Chg <= 0)
continue;
1292 mtj.
Pts.push_back(tp);
1301 myprt<<
" P"<<pfp.
ID<<
" try to merge";
1302 for(
auto tjid : tjids) {
1303 auto& tj = slc.
tjs[tjid - 1];
1304 myprt<<
" T"<<tjid<<
" MCSMom "<<tj.MCSMom;
1306 myprt<<
" -> T"<<slc.
tjs.size() + 1;
1307 myprt<<
" MCSMom "<<mtj.
MCSMom;
1310 for(
auto tjid : tjids) {
1311 auto& tj = slc.
tjs[tjid - 1];
1312 if(tj.SSID > 0) mtj.
SSID = tj.SSID;
1317 std::cout<<
"MergePFPTjs: StoreTraj failed P"<<pfp.
ID<<
"\n";
1320 int newTjID = slc.
tjs.size();
1321 newTjIDs.push_back(newTjID);
1323 std::vector<unsigned short> vxlist;
1324 for(
auto tjid : tjids) {
1329 auto& tj = slc.
tjs[tjid - 1];
1330 for(
unsigned short end = 0;
end < 2; ++
end) {
1331 if(tj.VtxID[
end] == 0)
continue;
1332 if(std::find(vxlist.begin(), vxlist.end(), tj.VtxID[
end]) != vxlist.end()) {
1333 auto& vx2 = slc.
vtxs[tj.VtxID[
end] - 1];
1337 vxlist.push_back(tj.VtxID[
end]);
1343 pfp.
TjIDs = newTjIDs;
1347 myprt<<
"MergePFPTjs: P"<<pfp.
ID<<
" out";
1348 for(
auto tjid : pfp.
TjIDs) myprt<<
" T"<<tjid;
1355 void FindXMatches(
TCSlice& slc,
unsigned short numPlanes,
short maxScore, std::vector<MatchStruct>& matVec,
bool prt)
1362 if(numPlanes < 2)
return;
1366 constexpr
float twopi = 2 * M_PI;
1367 constexpr
float piOver2 = M_PI / 2;
1370 auto inMatVec = matVec;
1371 std::vector<MatchStruct> temp;
1374 unsigned short minPts = 2;
1379 unsigned int nAvailable = 0;
1385 double yzcut = 1.5 * xcut;
1386 for(
unsigned int ipt = 0; ipt < slc.
mallTraj.size() - 1; ++ipt) {
1389 if(iTjPt.npts < minPts)
continue;
1391 if(iTjPt.score < 0 || iTjPt.score > maxScore)
continue;
1392 auto& itp = slc.
tjs[iTjPt.id - 1].Pts[iTjPt.ipt];
1394 for(
unsigned int jpt = ipt + 1; jpt < slc.
mallTraj.size() - 1; ++jpt) {
1397 if(jTjPt.ctp == iTjPt.ctp)
continue;
1399 if(jTjPt.npts < minPts)
continue;
1401 if(jTjPt.score < 0 || jTjPt.score > maxScore)
continue;
1403 if(jTjPt.xlo > iTjPt.xhi)
continue;
1405 if(jTjPt.xlo > iTjPt.xhi + 5)
break;
1406 auto& jtp = slc.
tjs[jTjPt.id - 1].Pts[jTjPt.ipt];
1409 if(!
MakeTp3(slc, itp, jtp, tp3,
false))
continue;
1412 if(numPlanes == 3) {
1414 for(
unsigned int kpt = jpt + 1; kpt < slc.
mallTraj.size(); ++kpt) {
1417 if(kTjPt.ctp == iTjPt.ctp || kTjPt.ctp == jTjPt.ctp)
continue;
1418 if(kTjPt.score < 0 || kTjPt.score > maxScore)
continue;
1419 if(kTjPt.xlo > iTjPt.xhi)
continue;
1421 if(kTjPt.xlo > iTjPt.xhi + 5)
break;
1422 auto& ktp = slc.
tjs[kTjPt.id - 1].Pts[kTjPt.ipt];
1425 if(!
MakeTp3(slc, itp, ktp, iktp3,
false))
continue;
1426 if(std::abs(tp3.
Pos[1] - iktp3.
Pos[1]) > yzcut)
continue;
1427 if(std::abs(tp3.
Pos[2] - iktp3.
Pos[2]) > yzcut)
continue;
1431 while(dang > M_PI) dang -= twopi;
1432 if(dang > piOver2) dang = M_PI - dang;
1433 float mcsmom = slc.
tjs[iTjPt.id - 1].MCSMom + slc.
tjs[jTjPt.id - 1].MCSMom + slc.
tjs[kTjPt.id - 1].MCSMom;
1441 for(
auto& ms : inMatVec) {
1442 if(ms.TjIDs.size() != 3)
continue;
1443 if(iTjPt.id == ms.TjIDs[iplane] && jTjPt.id == ms.TjIDs[jplane] && kTjPt.id == ms.TjIDs[kplane]) {
1451 if(cntWght <= 0)
continue;
1453 unsigned short indx = 0;
1454 for(indx = 0; indx < temp.size(); ++indx) {
1455 auto& ms = temp[indx];
1456 if(iTjPt.id != ms.TjIDs[iplane])
continue;
1457 if(jTjPt.id != ms.TjIDs[jplane])
continue;
1458 if(kTjPt.id != ms.TjIDs[kplane])
continue;
1459 ms.Count += cntWght;
1462 if(indx == temp.size()) {
1468 ms.
TjIDs[iplane] = iTjPt.id;
1469 ms.
TjIDs[jplane] = jTjPt.id;
1470 ms.
TjIDs[kplane] = kTjPt.id;
1474 if(temp.size() > nAvailable)
break;
1482 unsigned short kplane = 3 - iplane - jplane;
1484 if(fkwire < 0 || fkwire >
tcc.
maxPos0[kplane])
continue;
1487 tpk.
Pos[0] = fkwire;
1488 float xp = 0.5 * (iTjPt.xlo + iTjPt.xhi);
1495 for(
auto& ms : inMatVec) {
1496 if(std::find(ms.TjIDs.begin(), ms.TjIDs.end(), iTjPt.id) != ms.TjIDs.end() &&
1497 std::find(ms.TjIDs.begin(), ms.TjIDs.end(), jTjPt.id) != ms.TjIDs.end()) {
1503 unsigned short indx = 0;
1504 for(indx = 0; indx < temp.size(); ++indx) {
1505 auto& ms = temp[indx];
1506 if(std::find(ms.TjIDs.begin(), ms.TjIDs.end(), iTjPt.id) != ms.TjIDs.end() &&
1507 std::find(ms.TjIDs.begin(), ms.TjIDs.end(), jTjPt.id) != ms.TjIDs.end())
break;
1509 if(indx == temp.size()) {
1513 ms.
TjIDs[0] = iTjPt.id;
1514 ms.
TjIDs[1] = jTjPt.id;
1523 if(temp.size() > nAvailable)
break;
1526 if(temp.size() > nAvailable)
break;
1531 if(temp.empty())
return;
1533 if(temp.size() == 1) {
1534 matVec.push_back(temp[0]);
1537 std::vector<SortEntry> sortVec(temp.size());
1538 for(
unsigned int indx = 0; indx < sortVec.size(); ++indx) {
1539 sortVec[indx].index = indx;
1540 sortVec[indx].val = temp[indx].Count;
1545 for(
unsigned int ii = 0; ii < sortVec.size(); ++ii) temp[ii] = tmpVec[sortVec[ii].
index];
1547 matVec.insert(matVec.end(), temp.begin(), temp.end());
1550 if(prt)
mf::LogVerbatim(
"TC")<<
"FindXMatches: Found "<<temp.size()<<
" matches";
1558 tp3.
Dir = {{999.0, 999.0, 999.0}};
1559 tp3.
Pos = {{999.0, 999.0, 999.0}};
1567 if(std::abs(ix - jx) > 20)
return false;
1568 tp3.
Pos[0] = 0.5 * (ix + jx);
1580 double den = isn * jcs - ics * jsn;
1581 if(den == 0)
return false;
1582 double iPos0 = itp.
Pos[0];
1583 double jPos0 = jtp.
Pos[0];
1585 tp3.
Pos[2] = (jcs * (iPos0 - iw0) - ics * (jPos0 - jw0)) / den;
1587 bool useI = std::abs(ics) > std::abs(jcs);
1589 tp3.
Pos[1] = (iPos0 - iw0 - isn * tp3.
Pos[2]) / ics;
1591 tp3.
Pos[1] = (jPos0 - jw0 - jsn * tp3.
Pos[2]) / jcs;
1595 if(jtp.
Dir[1] == 0) {
1597 if(jtp.
Dir[0] > 0) { tp3.
Dir[0] = 1; }
else { tp3.
Dir[0] = -1; }
1606 if(!findDirection)
return true;
1609 double itp2_0 = itp.
Pos[0] + 100;
1610 double itp2_1 = itp.
Pos[1];
1611 if(std::abs(itp.
Dir[0]) > 0.01) itp2_1 += 100 * itp.
Dir[1] / itp.
Dir[0];
1619 double jtp2Pos0 = (jtp2Pos1 - jtp.
Pos[1]) * (jtp.
Dir[0] / jtp.
Dir[1]) + jtp.
Pos[0];
1621 pos2[2] = (jcs * (itp2_0 - iw0) - ics * (jtp2Pos0 - jw0)) / den;
1623 pos2[1] = (itp2_0 - iw0 - isn * pos2[2]) / ics;
1625 pos2[1] = (jtp2Pos0 - jw0 - jsn * pos2[2]) / jcs;
1628 if(sep == 0)
return false;
1629 for(
unsigned short ixyz = 0; ixyz < 3; ++ixyz) tp3.
Dir[ixyz] = (pos2[ixyz] - tp3.
Pos[ixyz]) /sep;
1638 if(v1[0] == v2[0] && v1[1] == v2[1] && v1[2] == v2[2])
return 0;
1647 for(
unsigned short xyz = 0; xyz < 3; ++xyz) dir[xyz] = p2[xyz] - p1[xyz];
1648 if(dir[0] == 0 && dir[1] == 0 && dir[2] == 0)
return dir;
1649 if(!
SetMag(dir, 1)) { dir[0] = 0; dir[1] = 0; dir[3] = 0; }
1656 return sqrt(
PosSep2(pos1, pos2));
1663 double d0 = pos1[0] - pos2[0];
1664 double d1 = pos1[1] - pos2[1];
1665 double d2 = pos1[2] - pos2[2];
1666 return d0*d0 + d1*d1 + d2*d2;
1672 double den = v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2];
1673 if(den == 0)
return false;
1687 if(pfp.
ID == 0)
return;
1689 bool notgood =
false;
1690 for(
unsigned short end = 0;
end < 2; ++
end) {
1702 unsigned short numEnds = 2;
1703 if(pfp.
PDGCode == 1111) numEnds = 1;
1705 unsigned short maxlen = 0;
1706 for(
auto tjID : pfp.
TjIDs) {
1711 for(
unsigned short end = 0;
end < numEnds; ++
end) {
1714 double cosgamma = std::abs(std::sin(angleToVert) * pfp.
Dir[
end][1] + std::cos(angleToVert) * pfp.
Dir[
end][2]);
1715 if(cosgamma == 0)
continue;
1717 if(dx == 0)
continue;
1719 if(dQ == 0)
continue;
1724 if(dedx > 999) dedx = -1;
1733 if(tj.
Pts.size() > maxlen) {
1734 maxlen = tj.
Pts.size();
1747 if(tp3.
Tj2Pts.empty())
return;
1752 for(
auto& tj2pt : tp3.
Tj2Pts) {
1753 auto& tp = slc.
tjs[tj2pt.id - 1].Pts[tj2pt.ipt];
1754 if(tp.Chg <= 0)
continue;
1757 double cosgamma = std::abs(std::sin(angleToVert) * tp3.
Dir[1] + std::cos(angleToVert) * tp3.
Dir[2]);
1758 if(cosgamma == 0)
continue;
1762 for(
unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1763 if(!tp.UseHit[ii])
continue;
1764 unsigned int iht = tp.Hits[ii];
1767 double dQ = chg / dx;
1770 if(dedx > 200)
continue;
1772 sum2 += dedx * dedx;
1775 if(cnt == 0)
return;
1776 tp3.
dEdx = sum / cnt;
1795 float minSep2 = 1E8;
1796 for(
unsigned short ipt1 = 0; ipt1 < pfp1.
Tp3s.size(); ++ipt1) {
1797 auto& tp1 = pfp1.
Tp3s[ipt1];
1798 for(
unsigned short ipt2 = 0; ipt2 < pfp2.
Tp3s.size(); ++ipt2) {
1799 auto& tp2 = pfp2.
Tp3s[ipt2];
1800 float sep2 =
PosSep2(tp1.Pos, tp2.Pos);
1801 if(sep2 > minSep2)
continue;
1807 return sqrt(minSep2);
1814 if(pfp.
Tp3s.empty())
return false;
1817 auto kinkPts =
FindKinks(slc, pfp, sep, prt);
1818 if(kinkPts.empty())
return false;
1819 if(prt)
mf::LogVerbatim(
"TC")<<
"Split3DKink found a kink at Tp3s point "<<kinkPts[0];
1823 unsigned short kpt = 0;
1824 for(
auto ipt : kinkPts) {
1831 if(kpt < 1 || kpt > pfp.
Tp3s.size() - 1)
return false;
1833 std::vector<unsigned short> tjids;
1834 std::vector<unsigned short> vx2ids;
1836 for(
unsigned short ipt = kpt; ipt < kpt + 2; ++ipt) {
1837 auto& tp3 = pfp.
Tp3s[ipt];
1838 for(
auto& tp2 : tp3.Tj2Pts) {
1840 if(std::find(tjids.begin(), tjids.end(), tp2.id) != tjids.end())
continue;
1842 if(std::find(pfp.
TjIDs.begin(), pfp.
TjIDs.end(), tp2.id) == pfp.
TjIDs.end())
continue;
1843 tjids.push_back(tp2.id);
1844 auto& tj = slc.
tjs[tp2.id - 1];
1845 auto& tp = tj.Pts[tp2.ipt];
1846 unsigned short closeEnd = USHRT_MAX;
1847 if(tp2.ipt < tj.EndPt[0] + 2) closeEnd = 0;
1848 if(tp2.ipt > tj.EndPt[1] - 2) closeEnd = 1;
1852 if(tj.VtxID[closeEnd] == 0) {
1856 vx2ids.push_back(tj.VtxID[closeEnd]);
1857 if(prt)
mf::LogVerbatim(
"TC")<<
" tj "<<tj.ID<<
" use existing 2V"<<tj.VtxID[closeEnd];
1861 vx2.
ID = slc.
vtxs.size() + 1;
1866 if(!
SplitTraj(slc, tp2.id - 1, tp2.ipt, slc.
vtxs.size() - 1, prt))
return false;
1867 vx2ids.push_back(vx2.
ID);
1874 if(vx2ids.size() != slc.
nPlanes) {
1881 vx3.
ID = slc.
vtx3s.size() + 1;
1882 vx3.
X = pfp.
Tp3s[kpt].Pos[0];
1883 vx3.
Y = pfp.
Tp3s[kpt].Pos[1];
1884 vx3.
Z = pfp.
Tp3s[kpt].Pos[2];
1885 for(
auto vx2id : vx2ids) {
1886 if(vx2id == 0)
continue;
1887 auto& vx2 = slc.
vtxs[vx2id - 1];
1889 vx3.
Vx2ID[plane] = vx2id;
1894 slc.
vtx3s.push_back(vx3);
1905 std::vector<unsigned short> kinkPts;
1907 double angCut = 0.3;
1909 unsigned short kStart = USHRT_MAX;
1911 bool foundKink =
false;
1912 double kinkSep2 = 2 * sep * sep;
1913 for(
unsigned short ipt = 1; ipt < pfp.
Tp3s.size(); ++ipt) {
1917 unsigned short kpt = kinkPts[kinkPts.size() - 1];
1918 if(foundKink &&
PosSep2(pfp.
Tp3s[ipt].Pos, pfp.
Tp3s[kpt].Pos) < kinkSep2)
continue;
1922 if(dang < angCut && kStart == USHRT_MAX)
continue;
1924 if(kStart == USHRT_MAX) {
1930 unsigned short klen = ipt - kStart;
1931 if(prt)
mf::LogVerbatim(
"TC")<<
" findKinks: kink angle "<<kang<<
" at point "<<ipt<<
" klen "<<klen;
1932 kinkPts.push_back(ipt - 1);
1943 double KinkAngle(
TCSlice& slc,
const std::vector<TrajPoint3>& tp3s,
unsigned short atPt,
double sep)
1946 if(tp3s.empty())
return -1;
1947 if(atPt < 1 || atPt > tp3s.size() - 2)
return -1;
1948 double sep2 = sep * sep;
1949 unsigned short pt1 = USHRT_MAX;
1950 for(
unsigned short ii = 1; ii < tp3s.size(); ++ii) {
1951 unsigned short ipt = atPt - ii;
1952 if(
PosSep2(tp3s[atPt].Pos, tp3s[ipt].Pos) > sep2) {
1958 if(pt1 == USHRT_MAX)
return -1;
1959 unsigned short pt2 = USHRT_MAX;
1960 for(
unsigned short ii = 1; ii < tp3s.size(); ++ii) {
1961 unsigned short ipt = atPt + ii;
1962 if(ipt == tp3s.size())
break;
1963 if(
PosSep2(tp3s[atPt].Pos, tp3s[ipt].Pos) > sep2) {
1968 if(pt2 == USHRT_MAX)
return -1;
1969 return DeltaAngle(tp3s[pt1].Dir, tp3s[pt2].Dir);
1977 pfp.
ID = slc.
pfps.size() + 1;
1987 for(
unsigned short end = 0;
end < 2; ++
end) {
1990 pfp.
Dir[
end] = {{0.0, 0.0, 0.0}};
1992 pfp.
XYZ[
end] = {{0.0, 0.0, 0.0}};
2011 for(
auto& tj : slc.
tjs) {
2012 for(
auto& tp : tj.Pts) tp.Environment[
kEnvFlag] =
false;
2016 std::vector<MatchStruct> matVec;
2020 for(
short maxScore = 0; maxScore < 2; ++maxScore)
FindXMatches(slc, 3, maxScore, matVec, prt);
2026 for(
short maxScore = 0; maxScore < 2; ++maxScore)
FindXMatches(slc, 2, maxScore, matVec, prt);
2033 if(matVec.empty())
return;
2036 if(matVec.size() > 1) {
2038 std::vector<int> dum1;
2039 std::vector<float> dum2;
2040 std::vector<SortEntry> sortVec(matVec.size());
2041 for(
unsigned int ii = 0; ii < matVec.size(); ++ii) {
2042 sortVec[ii].index = ii;
2043 auto& ms = matVec[ii];
2044 sortVec[ii].val = ms.Count;
2046 if(ms.TjIDs.size() == 2) sortVec[ii].
val /= 2;
2049 std::vector<MatchStruct> tmpVec;
2050 tmpVec.reserve(matVec.size());
2051 for(
unsigned int ii = 0; ii < matVec.size(); ++ii) {
2052 tmpVec.push_back(matVec[sortVec[ii].
index]);
2059 for(
auto& ms : matVec) {
2060 if(ms.Count < 2)
continue;
2062 bool skipit =
false;
2064 if(ms.TjIDs == oms.TjIDs) {
2069 if(skipit)
continue;
2071 pfp.
TjIDs = ms.TjIDs;
2075 ms.Pos = pfp.
XYZ[0];
2076 ms.Dir = pfp.
Dir[0];
2083 myprt<<
"FPFP: slc.matchVec\n";
2084 unsigned short cnt = 0;
2086 std::vector<int> dum1;
2087 std::vector<float> dum2;
2088 for(
unsigned int ii = 0; ii < slc.
matchVec.size(); ++ii) {
2090 if(ms.Count == 0)
continue;
2091 myprt<<std::setw(4)<<ii<<
" Count "<<std::setw(5)<<(int)ms.Count;
2092 myprt<<
" Tj ID-UID:";
2093 for(
auto& tjid : ms.TjIDs) {
2094 myprt<<
" t"<<tjid<<
"-T"<<slc.
tjs[tjid-1].UID;
2097 for(
unsigned short itj = 0; itj < ms.TjCompleteness.size(); ++itj) {
2098 myprt<<std::setprecision(2)<<std::setw(6)<<ms.TjCompleteness[itj];
2100 myprt<<
" Pos ("<<std::setprecision(0)<<std::fixed;
2101 myprt<<ms.Pos[0]<<
", "<<ms.Pos[1]<<
", "<<ms.Pos[2];
2102 myprt<<
") Dir "<<std::setprecision(2)<<std::setw(6)<<ms.Dir[0]<<std::setw(6)<<ms.Dir[1]<<std::setw(6)<<ms.Dir[2];
2103 myprt<<
" projInPlane";
2104 for(
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
2106 auto tp =
MakeBareTP(slc, ms.Pos, ms.Dir, inCTP);
2107 myprt<<
" "<<std::setprecision(2)<<tp.Delta;
2109 myprt<<
" maxTjLen "<<(int)
MaxTjLen(slc, ms.TjIDs);
2110 myprt<<
" MCSMom "<<
MCSMom(slc, ms.TjIDs);
2111 myprt<<
" PDGCodeVote "<<
PDGCodeVote(slc, ms.TjIDs,
false);
2114 if(cnt == 500 || ms.Count < 2) {
2115 myprt<<
"...stopped printing after 500 entries or Count < 2";
2128 for(
auto tid : ms.TjIDs) {
2129 auto& tj = slc.
tjs[tid - 1];
2130 if(tj.VtxID[0] > 0 || tj.VtxID[1] > 0) hasVx =
true;
2132 if(pdgCode != 0 && !hasVx) {
2133 float minCompleteness = 1;
2134 for(
unsigned short itj = 0; itj < ms.TjCompleteness.size(); ++itj) {
2135 if(ms.TjCompleteness[itj] < minCompleteness) minCompleteness = ms.TjCompleteness[itj];
2137 if(minCompleteness > 0.5) {
2139 pfp.
TjIDs = ms.TjIDs;
2142 pfp.
XYZ[0] = ms.Pos;
2143 pfp.
Dir[0] = ms.Dir;
2152 if(!shared.empty()) allms.Count = 0;
2168 for(
unsigned int indx = 0; indx < slc.
matchVec.size(); ++indx) {
2171 if(ms.Count == 0)
continue;
2173 bool skipit =
false;
2177 for(
unsigned short itj = 0; itj < ms.TjIDs.size(); ++itj) {
2178 if(ms.TjIDs[itj] <= 0 || ms.TjIDs[itj] > (
int)slc.
tjs.size()) {
2179 std::cout<<
"FindPFParticles: bogus ms TjID "<<ms.TjIDs[itj]<<
"\n";
2182 auto& tj = slc.
tjs[ms.TjIDs[itj] - 1];
2185 if(ms.TjCompleteness.empty()) {
2186 std::cout<<
"FindPFParticles: ms.TjCompleteness is empty\n";
2189 if(ms.TjCompleteness[itj] < 0.1) skipit =
true;
2190 if(tj.PDGCode == 13) has13 =
true;
2191 if(tj.PDGCode == 11) has11 =
true;
2193 if(skipit)
continue;
2194 if(has13 && has11)
continue;
2197 pfp.
TjIDs = ms.TjIDs;
2200 pfp.
XYZ[0] = ms.Pos;
2201 pfp.
Dir[0] = ms.Dir;
2224 if(!shared.empty()) allms.Count = 0;
2238 if(pfp.
PDGCode == 1111)
return false;
2239 if(pfp.
TjIDs.size() < 2)
return false;
2241 std::string fcnLabel = inFcnLabel +
".DPFP";
2244 std::vector<unsigned short> nInPln(slc.
nPlanes);
2245 for(
auto tjid : pfp.
TjIDs) {
2246 auto& tj = slc.
tjs[tjid - 1];
2249 std::cout<<fcnLabel<<
" P"<<pfp.
ID<<
" uses T"<<tj.ID<<
" but kMat3D is set true\n";
2253 unsigned short npl = 0;
2254 for(
unsigned short plane = 0; plane < slc.
nPlanes; ++plane)
if(nInPln[plane] > 0) ++npl;
2255 if(npl < 2)
return false;
2257 for(
unsigned short end = 0;
end < 2; ++
end) {
2259 std::cout<<fcnLabel<<
" P"<<pfp.
ID<<
" end "<<
end<<
" is invalid\n";
2265 std::cout<<fcnLabel<<
" P"<<pfp.
ID<<
" end 1 has a vertex but end 0 doesn't. No endpoints defined\n";
2276 if(pfp.
PDGCode == 111) pfpTrackLike =
false;
2280 myprt<<fcnLabel<<
" pfp P"<<pfp.
ID;
2281 myprt<<
" Vx3ID 3V"<<pfp.
Vx3ID[0]<<
" 3V"<<pfp.
Vx3ID[1];
2283 for(
auto id : pfp.
TjIDs) myprt<<
" T"<<id;
2287 myprt<<
" pfpTrackLike? "<<pfpTrackLike;
2293 for(
unsigned short ims = 0; ims < pfp.
MatchVecIndex + 10; ++ims) {
2294 if(ims >= slc.
matchVec.size())
break;
2296 if(ms.Count == 0)
continue;
2298 if(shared.size() < 2)
continue;
2302 for(
auto tjid : ms.TjIDs) {
2303 if(std::find(shared.begin(), shared.end(), tjid) != shared.end())
continue;
2304 auto& tj = slc.
tjs[tjid - 1];
2306 if(tj.AlgMod[
kMat3D])
continue;
2308 if(pfp.
PDGCode == 13 && tj.PDGCode == 11)
continue;
2309 if(pfp.
PDGCode == 11 && tj.PDGCode == 13)
continue;
2312 float len =
PosSep(tj.Pts[tj.EndPt[0]].Pos, tj.Pts[tj.EndPt[1]].Pos);
2315 bool skipit =
false;
2316 for(
auto tjid : pfp.
TjIDs) {
2317 auto& ptj = slc.
tjs[tjid - 1];
2318 if(ptj.CTP != tj.CTP)
continue;
2324 if(skipit)
continue;
2325 if(prt)
mf::LogVerbatim(
"TC")<<
" add T"<<tjid<<
" MCSMom "<<tj.MCSMom<<
" length "<<len;
2326 pfp.
TjIDs.push_back(tjid);
2344 if(pfp.
Tp3s.empty())
return false;
2354 myprt<<fcnLabel<<
" pfp P"<<pfp.
ID;
2355 myprt<<
" Vx3ID 3V"<<pfp.
Vx3ID[0]<<
" 3V"<<pfp.
Vx3ID[1];
2357 for(
auto id : pfp.
TjIDs) myprt<<
" T"<<id;
2358 myprt<<
" Tp3s size "<<pfp.
Tp3s.size();
2372 if(pfp.
ID == 0)
return true;
2373 if(pfp.
TjIDs.empty())
return true;
2374 if(pfp.
Vx3ID[0] <= 0 || pfp.
Vx3ID[0] > (
int)slc.
vtx3s.size())
return true;
2377 std::vector<int> killMe;
2378 for(
auto vx2id : vx3.Vx2ID) {
2379 if(vx2id == 0)
continue;
2380 auto& vx2 = slc.
vtxs[vx2id - 1];
2390 if(setInt.size() < 2)
continue;
2393 unsigned short lenth = 0;
2394 for(
auto tid : setInt) {
2395 auto& tj = slc.
tjs[tid - 1];
2396 unsigned short npts = tj.EndPt[1] - tj.EndPt[0] + 1;
2397 if(npts < lenth)
continue;
2401 if(imLong == 0)
continue;
2403 for(
auto tid : setInt)
if(tid != imLong) killMe.push_back(tid);
2405 if(killMe.empty())
return true;
2408 myprt<<
"PVTC: P"<<pfp.
ID<<
" removing short tjs attached to a vertex:";
2409 for(
auto tid : killMe) myprt<<
" T"<<tid;
2412 std::vector<int>
tmp;
2413 for(
auto tid : pfp.
TjIDs) {
2414 if(std::find(killMe.begin(), killMe.end(), tid) == killMe.end()) tmp.push_back(tid);
2424 if(pfp.
ID == 0)
return false;
2425 if(pfp.
TjIDs.empty())
return false;
2426 if(pfp.
Tp3s.empty())
return false;
2430 if(prt)
mf::LogVerbatim(
"TC")<<
"AnalyzePFP: P"<<pfp.
ID<<
" needs to be updated. Skip analysis ";
2435 float minCompleteness = 0.95;
2436 for(
auto tjc : pfp.
TjCompleteness)
if(tjc < minCompleteness) minCompleteness = tjc;
2437 if(prt)
mf::LogVerbatim(
"TC")<<
"inside AnalyzePFP P"<<pfp.
ID<<
" minCompleteness "<<minCompleteness;
2438 if(minCompleteness == 0.95)
return true;
2440 if(pfp.
PDGCode == 111)
return true;
2443 std::vector<int> tjIDs;
2444 std::vector<unsigned short> tjCnt;
2445 for(
auto& tp3 : pfp.
Tp3s) {
2446 for(
auto& tp2 : tp3.Tj2Pts) {
2449 unsigned short indx = 0;
2450 for(indx = 0; indx < tjIDs.size(); ++indx)
if(tjIDs[indx] == tp2.id)
break;
2451 if(indx == tjIDs.size()) {
2452 tjIDs.push_back(itjID);
2461 for(
unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2462 if(std::find(pfp.
TjIDs.begin(), pfp.
TjIDs.end(), tjIDs[ii]) != pfp.
TjIDs.end())
continue;
2463 auto& missTj = slc.
tjs[tjIDs[ii] - 1];
2464 if(missTj.AlgMod[
kMat3D])
continue;
2466 if(prt)
mf::LogVerbatim(
"TC")<<
" missed T"<<missTj.ID<<
" npwc "<<npwc<<
" tjCnt "<<tjCnt[ii];
2467 if(tjCnt[ii] < 0.5 * npwc)
continue;
2470 bool skipit =
false;
2471 for(
auto tid : pfp.
TjIDs) {
2472 auto& tj = slc.
tjs[tid - 1];
2473 if(tj.CTP == missTj.CTP) skipit =
true;
2475 if(skipit)
continue;
2477 pfp.
TjIDs.push_back(missTj.ID);
2485 myprt<<
"APFP: Tjs in pfp\n";
2486 for(
auto tjid : pfp.
TjIDs) {
2487 auto& tj = slc.
tjs[tjid - 1];
2489 unsigned short indx = 0;
2490 for(indx = 0; indx < tjIDs.size(); ++indx)
if(tjIDs[indx] == tjid)
break;
2491 if(indx == tjIDs.size()) {
2492 myprt<<
" not found in P"<<pfp.
ID<<
"\n";
2495 myprt<<
" nTp3 "<<tjCnt[indx]<<
"\n";
2508 for(
auto& pfp : slc.
pfps) {
2509 if(pfp.ID == 0)
continue;
2510 if(pfp.Vx3ID[0] > 0)
continue;
2516 vx3.
X = pfp.XYZ[0][0];
2517 vx3.
Y = pfp.XYZ[0][1];
2518 vx3.
Z = pfp.XYZ[0][2];
2519 vx3.
ID = slc.
vtx3s.size() + 1;
2523 slc.
vtx3s.push_back(vx3);
2525 pfp.Vx3ID[0] = vx3.
ID;
2566 if(slc.
pfps.empty())
return;
2569 int neutrinoPFPID = 0;
2570 for(
auto& pfp : slc.
pfps) {
2571 if(pfp.ID == 0)
continue;
2572 if(!
tcc.
modes[
kTestBeam] && neutrinoPFPID == 0 && (pfp.PDGCode == 12 || pfp.PDGCode == 14)) {
2573 neutrinoPFPID = pfp.ID;
2579 constexpr
unsigned short end1 = 1;
2580 for(
auto& pfp : slc.
pfps) {
2581 if(pfp.ID == 0)
continue;
2583 if(pfp.Vx3ID[end1] > 0)
continue;
2587 unsigned short cnt3 = 0;
2588 unsigned short vx3id = 0;
2590 std::vector<int> vx2ids;
2591 for(
auto tjid : pfp.TjIDs) {
2592 auto& tj = slc.
tjs[tjid - 1];
2593 if(tj.VtxID[end1] == 0)
continue;
2594 auto& vx2 = slc.
vtxs[tj.VtxID[end1] - 1];
2595 if(vx2.Vx3ID == 0) {
2596 if(vx2.Topo == 1 && vx2.NTraj == 2) vx2ids.push_back(vx2.ID);
2599 if(vx3id == 0) vx3id = vx2.Vx3ID;
2600 if(vx2.Vx3ID == vx3id) ++cnt3;
2604 if(pfp.Vx3ID[1 - end1] == vx3id)
continue;
2605 pfp.Vx3ID[end1] = vx3id;
2607 std::cout<<
"DPFPR: Missed an end vertex for PFP "<<pfp.ID<<
" Write some code\n";
2613 for(
auto& pfp : slc.
pfps) {
2614 if(pfp.ID == 0)
continue;
2616 if(pfp.PDGCode == 12 || pfp.PDGCode == 14 || pfp.PDGCode == 22)
continue;
2620 int pfpParentID = INT_MAX;
2621 unsigned short nParent = 0;
2622 for(
auto tjid : pfp.TjIDs) {
2623 auto& tj = slc.
tjs[tjid - 1];
2624 if(tj.ParentID <= 0)
continue;
2625 auto parPFP =
GetAssns(slc,
"T", tj.ParentID,
"P");
2626 if(parPFP.empty())
continue;
2627 if(pfpParentID == INT_MAX) pfpParentID = parPFP[0];
2628 if(parPFP[0] == pfpParentID) ++nParent;
2631 auto& ppfp = slc.
pfps[pfpParentID - 1];
2633 pfp.ParentUID = ppfp.UID;
2635 ppfp.DtrUIDs.push_back(pfp.UID);
2646 if(neutrinoPFPID > 0) {
2647 auto& neutrinoPFP = slc.
pfps[neutrinoPFPID - 1];
2648 int vx3id = neutrinoPFP.Vx3ID[1];
2649 for(
auto& pfp : slc.
pfps) {
2650 if(pfp.ID == 0 || pfp.ID == neutrinoPFPID)
continue;
2651 if(pfp.Vx3ID[0] != vx3id)
continue;
2652 pfp.ParentUID = (size_t)neutrinoPFPID;
2654 neutrinoPFP.DtrUIDs.push_back(pfp.ID);
2655 if(pfp.PDGCode == 111) neutrinoPFP.PDGCode = 12;
2672 std::vector<std::pair<unsigned short, unsigned short>> pardtr;
2676 double fidZCut = slc.
zLo + 2;
2677 for(
auto& parPFP : slc.
pfps) {
2678 if(parPFP.ID == 0)
continue;
2679 parPFP.Primary =
false;
2680 if(parPFP.XYZ[0][2] > fidZCut)
continue;
2681 parPFP.Primary =
true;
2683 if(prt)
mf::LogVerbatim(
"TC")<<
"DPFPTestBeam: parent "<<parPFP.ID<<
" end1 vtx "<<parPFP.Vx3ID[1];
2684 if(parPFP.Vx3ID[1] == 0)
continue;
2688 auto& vx3 = slc.
vtx3s[parPFP.Vx3ID[1] - 1];
2690 if(vx3.ID == 0)
continue;
2693 if(vx3TjList.empty())
continue;
2699 for(
auto dtjID : dtrTjlist) myprt<<
" "<<dtjID<<
"_"<<
GetPFPIndex(slc, dtjID);
2702 for(
auto dtjID : dtrTjlist) {
2703 unsigned short pfpIndex =
GetPFPIndex(slc, dtjID);
2704 if(pfpIndex > slc.
pfps.size() - 1)
continue;
2705 unsigned short dtrID = pfpIndex + 1;
2707 bool duplicate =
false;
2708 for(
auto& pd : pardtr)
if(parPFP.ID == pd.first && dtrID == pd.second) duplicate =
true;
2709 if(!duplicate) pardtr.push_back(std::make_pair(parPFP.ID, dtrID));
2715 for(
unsigned short nit = 0; nit < 100; ++nit) {
2716 if(pardtr.empty())
break;
2717 auto lastPair = pardtr[pardtr.size() - 1];
2718 auto& dtr = slc.
pfps[lastPair.second - 1];
2719 auto& par = slc.
pfps[lastPair.first - 1];
2720 dtr.ParentUID = par.UID;
2721 par.DtrUIDs.push_back(dtr.UID);
2726 unsigned short dtrEnd = USHRT_MAX;
2727 for(
unsigned short ep = 0; ep < 2; ++ep) {
2728 if(par.Vx3ID[ep] == 0)
continue;
2729 for(
unsigned short ed = 0; ed < 2; ++ed)
if(dtr.Vx3ID[ed] == par.Vx3ID[ep]) dtrEnd = ed;
2731 if(dtrEnd > 1)
continue;
2733 dtrEnd = 1 - dtrEnd;
2735 if(dtr.Vx3ID[dtrEnd] == 0)
continue;
2737 auto& vx3 = slc.
vtx3s[dtr.Vx3ID[dtrEnd] - 1];
2740 if(vx3TjList.empty())
continue;
2744 for(
auto tjid : dtrTjlist) pardtr.push_back(std::make_pair(dtr.ID, tjid));
2752 if(pfp.
ID <
int(slc.
pfps.size()))
return false;
2755 if(pfp.
TjIDs.empty())
return false;
2756 if(pfp.
PDGCode != 1111 && pfp.
Tp3s.size() < 2)
return false;
2759 if(pfp.
ID != (
int)slc.
pfps.size() + 1) pfp.
ID = slc.
pfps.size() + 1;
2763 for(
auto tjid : pfp.
TjIDs) {
2764 auto& tj = slc.
tjs[tjid - 1];
2765 if(tj.AlgMod[
kMat3D])
return false;
2766 tj.AlgMod[
kMat3D] =
true;
2769 if(!pfp.
Tp3s.empty()) {
2772 std::vector<int> tjids;
2774 std::vector<short> firstIpt;
2775 std::vector<short> lastIpt;
2776 for(
auto& Tp3 : pfp.
Tp3s) {
2777 for(
auto& tj2pt : Tp3.Tj2Pts) {
2778 int tjid = tj2pt.id;
2780 unsigned short ii = 0;
2781 for(ii = 0; ii < tjids.size(); ++ii)
if(tjid == tjids[ii])
break;
2782 if(ii < tjids.size()) {
2784 lastIpt[ii] = tj2pt.ipt;
2787 tjids.push_back(tjid);
2788 firstIpt.push_back((
short)tj2pt.ipt);
2789 lastIpt.push_back((
short)tj2pt.ipt);
2793 for(
unsigned short ii = 0; ii < tjids.size(); ++ii) {
2795 if(std::find(pfp.
TjIDs.begin(), pfp.
TjIDs.end(), tjids[ii]) == pfp.
TjIDs.end())
continue;
2796 auto& tj = slc.
tjs[tjids[ii] - 1];
2797 if(lastIpt[ii] < firstIpt[ii])
ReverseTraj(slc, tj);
2803 if(pfp.
NeedsUpdate) std::cout<<
"StorePFP: stored P"<<pfp.
ID<<
" but NeedsUpdate is true...\n";
2805 slc.
pfps.push_back(pfp);
2813 if(pfp.
ID <= 0)
return false;
2814 if(end > 1)
return false;
2817 auto& pos1 = pfp.
XYZ[
end];
2818 return (pos1[0] > slc.
xLo + abit && pos1[0] < slc.
xHi - abit &&
2819 pos1[1] > slc.
yLo + abit && pos1[1] < slc.
yHi - abit &&
2820 pos1[2] > slc.
zLo + abit && pos1[2] < slc.
zHi - abit);
2832 double local[3] = {0.,0.,0.};
2833 double world[3] = {0.,0.,0.};
2854 if(pos1[0] == pos2[0] && pos1[1] == pos2[1] && pos1[2] == pos2[2])
return;
2857 double costh =
DotProd(dir1, ptDir);
2858 if(costh > 1)
return;
2859 double sep =
PosSep(pos1, pos2);
2860 if(sep < 1
E-6)
return;
2861 alongTrans[0] = costh * sep;
2862 double sinth = sqrt(1 - costh * costh);
2863 alongTrans[1] = sinth * sep;
2871 for(
unsigned short xyz = 0; xyz < 3; ++xyz) {
2872 p1End[xyz] = p1[xyz] + 10 * p1Dir[xyz];
2873 p2End[xyz] = p2[xyz] + 10 * p2Dir[xyz];
2891 double d1343,d4321,d1321,d4343,d2121;
2895 p13[0] = p1[0] - p3[0];
2896 p13[1] = p1[1] - p3[1];
2897 p13[2] = p1[2] - p3[2];
2898 p43[0] = p4[0] - p3[0];
2899 p43[1] = p4[1] - p3[1];
2900 p43[2] = p4[2] - p3[2];
2901 if (std::abs(p43[0]) < EPS && std::abs(p43[1]) < EPS && std::abs(p43[2]) < EPS)
return(
false);
2902 p21[0] = p2[0] - p1[0];
2903 p21[1] = p2[1] - p1[1];
2904 p21[2] = p2[2] - p1[2];
2905 if (std::abs(p21[0]) < EPS && std::abs(p21[1]) < EPS && std::abs(p21[2]) < EPS)
return(
false);
2907 d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2];
2908 d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2];
2909 d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2];
2910 d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2];
2911 d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2];
2913 denom = d2121 * d4343 - d4321 * d4321;
2914 if (std::abs(denom) < EPS)
return(
false);
2915 numer = d1343 * d4321 - d1321 * d4343;
2917 double mua = numer / denom;
2918 double mub = (d1343 + d4321 * mua) / d4343;
2920 intersect[0] = p1[0] + mua * p21[0];
2921 intersect[1] = p1[1] + mua * p21[1];
2922 intersect[2] = p1[2] + mua * p21[2];
2924 pb[0] = p3[0] + mub * p43[0];
2925 pb[1] = p3[1] + mub * p43[1];
2926 pb[2] = p3[2] + mub * p43[2];
2927 doca =
PosSep(intersect, pb);
2929 for(
unsigned short xyz = 0; xyz < 3; ++xyz) intersect[xyz] += pb[xyz];
2930 for(
unsigned short xyz = 0; xyz < 3; ++xyz) intersect[xyz] /= 2;
2937 std::swap(pfp.
XYZ[0], pfp.
XYZ[1]);
2938 std::swap(pfp.
Dir[0], pfp.
Dir[1]);
2939 for(
unsigned short xyz = 0; xyz < 3; ++xyz) {
2940 pfp.
Dir[0][xyz] *= -1;
2941 pfp.
Dir[1][xyz] *= -1;
2944 std::swap(pfp.
dEdx[0], pfp.
dEdx[1]);
2947 std::reverse(pfp.
Tp3s.begin(), pfp.
Tp3s.end());
2948 for(
auto& tp3 : pfp.
Tp3s) {
2949 for(
unsigned short xyz = 0; xyz < 3; ++xyz) {
2963 float sep =
PosSep(pos1, pos2);
2964 if(sep == 0)
return -1;
2970 for(
unsigned short step = 0; step < nstep; ++step) {
2971 for(
unsigned short xyz = 0; xyz < 3; ++xyz) pos1[xyz] +=
tcc.
wirePitch *
dir[xyz];
2972 for(
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
2980 if(cnt == 0)
return -1;
2990 if(pfp.
ID == 0)
return 0;
2991 if(pfp.
TjIDs.empty())
return 0;
2992 if(end < 0 || end > 1)
return 0;
3000 for(
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
3002 std::vector<int> tjids(1);
3003 for(
auto tjid : pfp.
TjIDs) {
3004 auto& tj = slc.
tjs[tjid - 1];
3005 if(tj.CTP != inCTP)
continue;
3010 if(pos[0] < -0.4)
continue;
3012 unsigned int wire = std::nearbyint(pos[0]);
3013 if(wire > slc.
nWires[plane])
continue;
3014 if(slc.
wireHitRange[plane][wire].first == -1)
continue;
3017 if(cf < lo) lo = cf;
3018 if(cf > hi) hi = cf;
3023 if(cnt == 0)
return 0;
3024 if(cnt > 1 && lo < 0.3 && hi > 0.8) {
3035 if(pfp.
ID == 0)
return 0;
3044 myprt<<someText<<
" Pos"<<std::fixed<<std::setprecision(1);
3045 myprt<<std::setw(6)<<tp3.
Pos[0]<<std::setw(6)<<tp3.
Pos[1]<<std::setw(6)<<tp3.
Pos[2];
3046 myprt<<
" Dir"<<std::fixed<<std::setprecision(3);
3047 myprt<<std::setw(7)<<tp3.
Dir[0]<<std::setw(7)<<tp3.
Dir[1]<<std::setw(7)<<tp3.
Dir[2];
3049 for(
auto tj2pt : tp3.
Tj2Pts) {
3050 auto& tj = slc.
tjs[tj2pt.id - 1];
3051 auto& tp = tj.Pts[tj2pt.ipt];
3052 myprt<<
" "<<tj.ID<<
"_"<<
PrintPos(slc, tp);
3059 if(pfp.
Tp3s.empty())
return;
3063 myprt<<someText<<
" pfp P"<<pfp.
ID<<
"\n";
3064 myprt<<someText<<
" ipt ________Pos________ Path ________Dir_______ along trans dang Kink Tj_ipt \n";
3067 myprt<<someText<<
" ";
3068 myprt<<std::fixed<<std::setprecision(1);
3069 myprt<<std::setw(7)<<pfp.
XYZ[0][0]<<std::setw(7)<<pfp.
XYZ[0][1]<<std::setw(7)<<pfp.
XYZ[0][2];
3071 myprt<<std::fixed<<std::setprecision(2);
3072 myprt<<std::setw(7)<<pfp.
Dir[0][0]<<std::setw(7)<<pfp.
Dir[0][1]<<std::setw(7)<<pfp.
Dir[0][2];
3073 myprt<<
" <--- pfp.XYZ[0] \n";
3075 unsigned short fromPt = 0;
3076 unsigned short toPt = pfp.
Tp3s.size() - 1;
3077 if(printPts >= 0) fromPt = toPt;
3079 for(
unsigned short ipt = fromPt; ipt <= toPt; ++ipt) {
3080 auto tp3 = pfp.
Tp3s[ipt];
3081 myprt<<someText<<std::setw(4)<<ipt;
3082 myprt<<std::fixed<<std::setprecision(1);
3083 myprt<<std::setw(7)<<tp3.Pos[0]<<std::setw(7)<<tp3.Pos[1]<<std::setw(7)<<tp3.Pos[2];
3084 myprt<<std::setprecision(1)<<std::setw(5)<<
PosSep(tp3.Pos, pfp.
XYZ[0]);
3085 myprt<<std::setprecision(2)<<std::setw(7)<<tp3.Dir[0]<<std::setw(7)<<tp3.Dir[1]<<std::setw(7)<<tp3.Dir[2];
3086 myprt<<std::setprecision(1)<<std::setw(6)<<tp3.AlongTrans[0];
3087 myprt<<std::setprecision(1)<<std::setw(6)<<tp3.AlongTrans[1];
3088 myprt<<std::setprecision(2)<<std::setw(7)<<
DeltaAngle(prevDir, tp3.Dir);
3093 myprt<<std::setprecision(2)<<std::setw(7)<<
KinkAngle(slc, pfp.
Tp3s, ipt, sep);
3094 for(
auto tj2pt : tp3.Tj2Pts) {
3095 auto& tj = slc.
tjs[tj2pt.id - 1];
3096 auto& tp = tj.Pts[tj2pt.ipt];
3097 myprt<<
" "<<tj.ID<<
"_"<<tj2pt.ipt<<
"_"<<
PrintPos(slc, tp);
3102 myprt<<someText<<
" ";
3103 myprt<<std::fixed<<std::setprecision(1);
3104 myprt<<std::setw(7)<<pfp.
XYZ[1][0]<<std::setw(7)<<pfp.
XYZ[1][1]<<std::setw(7)<<pfp.
XYZ[1][2];
3106 myprt<<std::fixed<<std::setprecision(2);
3107 myprt<<std::setw(7)<<pfp.
Dir[1][0]<<std::setw(7)<<pfp.
Dir[1][1]<<std::setw(7)<<pfp.
Dir[1][2];
3108 myprt<<
" <--- pfp.XYZ[1]. Length "<<
PosSep(pfp.
XYZ[0], pfp.
XYZ[1])<<
"\n";
Expect tracks entering from the front face. Don't create neutrino PFParticles.
TPCID()=default
Default constructor: an invalid TPC ID.
calo::CalorimetryAlg * caloAlg
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
code to link reconstructed objects back to the MC truth information
void Fit3D(unsigned short mode, Point3_t point, Vector3_t dir, Point3_t &fitPos, Vector3_t &fitDir)
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< Trajectory > tjs
vector of all trajectories in each plane
std::vector< Vtx3Store > vtx3s
3D vertices
Point2_t dEdx
dE/dx for 3D matched trajectories
bool dbgStitch
debug PFParticle stitching
int PDGCodeVote(TCSlice &slc, std::vector< int > &tjIDs, bool prt)
void SetEndPoints(Trajectory &tj)
std::array< std::vector< float >, 2 > dEdxErr
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
PlaneGeo const & Plane(unsigned int const p, unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified wire.
geo::Length_t DetHalfWidth(geo::TPCID const &tpcid) const
Returns the half width of the active volume of the specified TPC.
void PrintTp3(std::string someText, TCSlice &slc, const TrajPoint3 &tp3)
struct of temporary 2D vertices (end points)
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
void FindCompleteness(TCSlice &slc, PFPStruct &pfp, bool doFit, bool fillTp3s, bool prt)
CTP_t CTP
Cryostat, TPC, Plane code.
std::vector< float > maxPos0
bool valIncreasings(SortEntry c1, SortEntry c2)
bool InsideTPC(const Point3_t &pos, geo::TPCID &inTPCID)
bool FitTp3(TCSlice &slc, TrajPoint3 &tp3, const std::vector< Tj2Pt > &tj2pts)
std::array< double, 3 > Point3_t
double dEdx_AREA(art::Ptr< recob::Hit > hit, double pitch, double T0=0) const
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
unsigned int Nplanes() const
Number of planes in this tpc.
void PrintPFP(std::string someText, TCSlice &slc, const PFPStruct &pfp, bool printHeader)
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
float PFPDOCA(const PFPStruct &pfp1, const PFPStruct &pfp2, unsigned short &close1, unsigned short &close2)
unsigned short WiresSkippedInCTP(TCSlice &slc, std::vector< int > &tjids, CTP_t inCTP)
bool MakeTp3(TCSlice &slc, const TrajPoint &itp, const TrajPoint &jtp, TrajPoint3 &tp3, bool findDirection)
std::vector< float > TjCompleteness
The data type to uniquely identify a Plane.
Geometry information for a single TPC.
matched to a high-score 3D vertex
bool StoreTraj(TCSlice &slc, Trajectory &tj)
bool LineLineIntersect(Point3_t p1, Point3_t p2, Point3_t p3, Point3_t p4, Point3_t &intersect, float &doca)
void FindXMatches(TCSlice &slc, unsigned short numPlanes, short maxScore, std::vector< MatchStruct > &matVec, bool prt)
bool MergePFPTjs(TCSlice &slc, PFPStruct &pfp, bool prt)
CryostatID_t Cryostat
Index of cryostat.
bool AttachAnyTrajToVertex(TCSlice &slc, unsigned short ivx, bool prt)
void PrintP(std::string someText, mf::LogVerbatim &myprt, PFPStruct &pfp, bool &printHeader)
std::vector< Tj2Pt > Tj2Pts
float LengthInCTP(TCSlice &slc, std::vector< int > &tjids, CTP_t inCTP)
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
a general purpose flag bit used in 3D matching
std::vector< unsigned short > FindKinks(TCSlice &slc, PFPStruct &pfp, double sep, bool prt)
bool dbgSlc
debug only in the user-defined slice? default is all slices
std::array< int, 2 > Vx3ID
bool IsShowerLike(TCSlice &slc, const std::vector< int > TjIDs)
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
bool StoreVertex(TCSlice &slc, VtxStore &vx)
std::vector< TrajPoint3 > Tp3s
IteratorBox< TPC_id_iterator,&GeometryCore::begin_TPC_id,&GeometryCore::end_TPC_id > IterateTPCIDs() const
Enables ranged-for loops on all TPC IDs of the detector.
bool Split3DKink(TCSlice &slc, PFPStruct &pfp, double sep, bool prt)
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
void PrintTp3s(std::string someText, TCSlice &slc, const PFPStruct &pfp, short printPts)
void UpdateTp3s(TCSlice &slc, PFPStruct &pfp, int oldTj, int newTj)
double ThetaZ() const
Angle of the wires from positive z axis; .
TrajPoint MakeBareTP(TCSlice &slc, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
std::vector< std::vector< std::pair< int, int > > > wireHitRange
float MaxTjLen(TCSlice &slc, std::vector< int > &tjIDs)
struct of temporary 3D vertices
void PFPVertexCheck(TCSlice &slc)
geo::Length_t DetHalfHeight(geo::TPCID const &tpcid) const
Returns the half height of the active volume of the specified TPC.
std::vector< Tj2Pt > mallTraj
vector of trajectory points ordered by increasing X
std::array< float, 2 > Point2_t
float unitsPerTick
scale factor from Tick to WSE equivalent units
std::array< Point3_t, 2 > XYZ
const detinfo::DetectorProperties * detprop
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
CTP_t CTP
Cryostat, TPC, Plane code.
std::array< Vector3_t, 2 > DirErr
std::vector< TrajPoint > Pts
Trajectory points.
unsigned short GetPFPIndex(TCSlice &slc, int tjID)
std::array< Vector3_t, 2 > Dir
bool DefinePFP(std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, bool prt)
bool valDecreasings(SortEntry c1, SortEntry c2)
std::array< unsigned short, 2 > EndPt
First and last point in the trajectory that has charge.
bool SignalAtTp(TCSlice &slc, const TrajPoint &tp)
std::vector< float > match3DCuts
3D matching cuts
void UpdateMatchStructs(TCSlice &slc, int oldTj, int newTj)
geo::Length_t DetLength(geo::TPCID const &tpcid) const
Returns the length of the active volume of the specified TPC.
void MakeTrajectoryObsolete(TCSlice &slc, unsigned int itj)
void fill(const art::PtrVector< recob::Hit > &hits, int only_plane)
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
void SetPDGCode(TCSlice &slc, unsigned short itj, bool tjDone)
void FollowTp3s(TCSlice &slc, PFPStruct &pfp, bool prt)
const geo::GeometryCore * geom
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.
void FindMissedTjsInTp3s(TCSlice &slc, PFPStruct &pfp, std::vector< int > &missTjs, std::vector< float > &missFrac)
float EffPur
Efficiency * Purity.
unsigned short FarEnd(TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
bool SetMag(Vector3_t &v1, double mag)
void ReverseTraj(TCSlice &slc, Trajectory &tj)
float TPHitsRMSTime(TCSlice &slc, TrajPoint &tp, HitStatus_t hitRequest)
bool AnalyzePFP(TCSlice &slc, PFPStruct &pfp, bool prt)
int ID
ID that is local to one slice.
std::vector< TCSlice > slices
std::array< unsigned short, 2 > VtxID
ID of 2D vertex.
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
std::bitset< 16 > modes
number of points to find AveChg
unsigned int NTPC(unsigned int cstat=0) const
Returns the total number of TPCs in the specified cryostat.
std::vector< TCHit > slHits
void FindPFParticles(TCSlice &slc)
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 FilldEdx(TCSlice &slc, PFPStruct &pfp)
bool InsideFV(TCSlice &slc, PFPStruct &pfp, unsigned short end)
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
std::vector< float > pfpStitchCuts
cuts for stitching between TPCs
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)
void ReversePFP(TCSlice &slc, PFPStruct &pfp)
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const VtxStore &vx2)
unsigned short MatchVecIndex
bool SetStart(TCSlice &slc, PFPStruct &pfp, bool prt)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
bool FitTp3s(TCSlice &slc, const std::vector< TrajPoint3 > &tp3s, Point3_t &pos, Vector3_t &dir, float &rCorr)
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)
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
std::vector< unsigned int > nWires
double KinkAngle(TCSlice &slc, const std::vector< TrajPoint3 > &tp3s, unsigned short atPt, double sep)
void FillmAllTraj(TCSlice &slc)
std::array< double, 3 > Vector3_t
bool SharesHighScoreVx(TCSlice &slc, const PFPStruct &pfp, const Trajectory &tj)
std::array< std::vector< float >, 2 > dEdx
bool PFPVxTjOK(TCSlice &slc, PFPStruct &pfp, bool prt)
bool AddMissedTj(TCSlice &slc, PFPStruct &pfp, unsigned short itj, bool looseCuts, bool prt)
std::vector< T > SetDifference(const std::vector< T > &set1, const std::vector< T > &set2)
void DefinePFPParents(TCSlice &slc, bool prt)
std::vector< MatchStruct > matchVec
3D matching vector
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
int SSID
ID of a 2D shower struct that this tj is in.
std::vector< PFPStruct > pfps
float ChgFracBetween(TCSlice &slc, Point3_t pos1, Point3_t pos2)
bool SplitTraj(TCSlice &slc, unsigned short itj, float XPos, bool makeVx2, bool prt)
float ChgFracNearEnd(TCSlice &slc, PFPStruct &pfp, unsigned short end)
TPCID_t TPC
Index of the TPC within its cryostat.
bool StorePFP(TCSlice &slc, PFPStruct &pfp)
master switch for turning on debug mode
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
void DefinePFPParentsTestBeam(TCSlice &slc, 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)