22 if(oldTj <= 0 || oldTj > (
int)tjs.
allTraj.size())
return;
23 if(newTj <= 0 || newTj > (
int)tjs.
allTraj.size())
return;
29 auto& ntj = tjs.
allTraj[newTj - 1];
30 unsigned short npts = ntj.EndPt[1] - ntj.EndPt[0] + 1;
32 std::vector<float> xpos(ntj.Pts.size());
34 for(
unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
35 auto& ntp = ntj.Pts[npt];
36 if(ntp.Chg <= 0)
continue;
41 for(
unsigned int ipt = 0; ipt < tjs.
mallTraj.size(); ++ipt) {
43 if(tj2pt.id > tjs.
allTraj.size())
continue;
44 if(tj2pt.id != oldtjid)
continue;
46 for(
unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
47 auto& ntp = ntj.Pts[npt];
48 if(ntp.Chg <= 0)
continue;
49 if(std::nearbyint(ntp.Pos[0]) == tj2pt.wire && xpos[npt] > tj2pt.xlo && xpos[npt] < tj2pt.xhi) {
60 if(!tjs.
pfps.empty()) {
61 for(
auto& pfp : tjs.
pfps) {
62 for(
auto& tp3 : pfp.Tp3s) {
64 for(
auto& tj2pt : tp3.Tj2Pts) {
65 if(tj2pt.id > tjs.
allTraj.size())
continue;
66 if(tj2pt.id != oldtjid)
continue;
68 for(
unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
69 auto& ntp = ntj.Pts[npt];
70 if(std::nearbyint(ntp.Pos[0]) == tj2pt.wire && xpos[npt] > tj2pt.xlo && xpos[npt] < tj2pt.xhi) {
88 if(oldTj <= 0 || oldTj > (
int)tjs.
allTraj.size())
return;
89 if(newTj <= 0 || newTj > (
int)tjs.
allTraj.size())
return;
93 unsigned short oldtjid = oldTj;
94 unsigned short newtjid = newTj;
95 auto& ntj = tjs.
allTraj[newTj - 1];
96 unsigned short npts = ntj.EndPt[1] - ntj.EndPt[0] + 1;
98 std::vector<float> xpos(ntj.Pts.size());
100 for(
unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
101 auto& ntp = ntj.Pts[npt];
102 if(ntp.Chg <= 0)
continue;
106 for(
auto& tp3 : pfp.
Tp3s) {
108 for(
auto& tj2pt : tp3.Tj2Pts) {
109 if(tj2pt.id > tjs.
allTraj.size())
continue;
110 if(tj2pt.id != oldtjid)
continue;
112 for(
unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
113 auto& ntp = ntj.Pts[npt];
114 if(std::nearbyint(ntp.Pos[0]) == tj2pt.wire && xpos[npt] > tj2pt.xlo && xpos[npt] < tj2pt.xhi) {
137 unsigned int ntp = 0;
139 if(tj.AlgMod[
kKilled])
continue;
140 if(tj.ID <= 0)
continue;
142 if((
int)planeID.
Cryostat != cstat)
continue;
143 if((
int)planeID.
TPC != tpc)
continue;
145 tj.AlgMod[
kMat3D] =
false;
152 unsigned int icnt = 0;
154 if(tj.AlgMod[
kKilled])
continue;
156 if((
int)planeID.
Cryostat != cstat)
continue;
157 if((
int)planeID.
TPC != tpc)
continue;
158 int plane = planeID.
Plane;
160 if(tjID <= 0)
continue;
163 for(
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
164 auto& tp = tj.Pts[ipt];
165 if(tp.Chg == 0)
continue;
166 if(icnt > tjs.
mallTraj.size() - 1)
break;
167 if(tp.Pos[0] < -0.4)
continue;
168 tjs.
mallTraj[icnt].wire = std::nearbyint(tp.Pos[0]);
171 if(!hasWire)
continue;
176 if(icnt == tjs.
mallTraj.size())
break;
177 tjs.
mallTraj[icnt].xlo = xpos - rms;
178 tjs.
mallTraj[icnt].xhi = xpos + rms;
183 tjs.
mallTraj[icnt].npts = tj.EndPt[1] - tj.EndPt[0] + 1;
192 std::vector<SortEntry> sortVec(tjs.
mallTraj.size());
193 for(
unsigned int ipt = 0; ipt < tjs.
mallTraj.size(); ++ipt) {
195 sortVec[ipt].index = ipt;
196 sortVec[ipt].val = tjs.
mallTraj[ipt].xlo;
202 for(
unsigned int ii = 0; ii < sortVec.size(); ++ii) tjs.
mallTraj[ii] = tallTraj[sortVec[ii].index];
215 if(pfp.
ID <= 0 || pfp.
TjIDs.empty())
return false;
216 if(pfp.
Tp3s.size() < 2)
return false;
220 float minAlong = 1E6;
221 unsigned short minPt = 0;
222 float maxAlong = -1E6;
223 unsigned short maxPt = 0;
224 std::vector<SortEntry> sortVec(pfp.
Tp3s.size());
225 for(
unsigned short ipt = 0; ipt < pfp.
Tp3s.size(); ++ipt) {
226 auto& tp3 = pfp.
Tp3s[ipt];
227 sortVec[ipt].index = ipt;
228 sortVec[ipt].val = tp3.AlongTrans[0];
230 if(tp3.AlongTrans[0] < minAlong) {
231 minAlong = tp3.AlongTrans[0];
234 if(tp3.AlongTrans[0] > maxAlong) {
235 maxAlong = tp3.AlongTrans[0];
240 pfp.
XYZ[0] = pfp.
Tp3s[minPt].Pos;
241 pfp.
XYZ[1] = pfp.
Tp3s[maxPt].Pos;
244 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];
251 std::vector<TrajPoint3> temp;
252 for(
unsigned short ii = 0; ii < sortVec.size(); ++ii) temp.push_back(pfp.
Tp3s[sortVec[ii].index]);
266 if(pfp.
Tp3s.size() < 2)
return;
268 unsigned short startPt = 0;
269 unsigned short endPt = pfp.
Tp3s.size() - 1;
272 constexpr
float sectionLen = 5;
273 float endAlong = pfp.
Tp3s[0].AlongTrans[0] + sectionLen;
274 std::vector<Vector3_t> sectionPos;
275 sectionPos.push_back(pfp.
Tp3s[0].Pos);
276 std::vector<unsigned short> sectionPt;
277 sectionPt.push_back(0);
278 for(
unsigned short section = 0; section < 100; ++section) {
282 unsigned short cnt = 0;
283 for(
unsigned short ipt = startPt; ipt < endPt; ++ipt) {
284 auto& tp3 = pfp.
Tp3s[ipt];
288 if(tp3.AlongTrans[1] > 2)
continue;
289 if(tp3.AlongTrans[0] < endAlong) {
291 for(
unsigned short xyz = 0; xyz < 3; ++xyz) {
292 avePos[xyz] += tp3.Pos[xyz];
293 aveDir[xyz] += tp3.Dir[xyz];
299 if(cnt == 0)
continue;
301 for(
unsigned short xyz = 0; xyz < 3; ++xyz) avePos[xyz] /= cnt;
308 sectionPos.push_back(avePos);
309 sectionPt.push_back(ipt);
311 endAlong += sectionLen;
315 sectionPos.push_back(pfp.
Tp3s[endPt].Pos);
316 sectionPt.push_back(pfp.
Tp3s.size() - 1);
324 for(
auto tjid : pfp.
TjIDs) {
325 auto& tj = tjs.
allTraj[tjid - 1];
326 for(
auto& tp : tj.Pts) tp.Environment[
kEnvFlag] =
false;
329 for(
auto tj2pt : pfp.
Tp3s[0].Tj2Pts) {
333 std::vector<TrajPoint3> ntp3;
334 ntp3.push_back(pfp.
Tp3s[0]);
337 std::vector<Point2_t> startPos2D(tjs.
NumPlanes);
339 unsigned short lastPtAdded = 0;
340 for(
unsigned short section = 1; section < sectionPt.size(); ++section) {
341 Point3_t startPos = sectionPos[section - 1];
342 Point3_t endPos = sectionPos[section];
345 if(section == 1) pfp.
Dir[0] = startDir;
347 pfp.
Dir[1] = startDir;
350 for(
unsigned short plane = 0; plane < tjs.
NumPlanes; ++plane) {
352 startPos2D[plane][0] = tjs.
geom->
WireCoordinate(sectionPos[section - 1][1], sectionPos[section - 1][2], planeID);
355 for(
unsigned short ipt = sectionPt[section - 1]; ipt < sectionPt[section]; ++ipt) {
356 auto& tp3 = pfp.
Tp3s[ipt];
358 unsigned short nused = 0;
359 bool big2DSep =
false;
360 for(
auto tj2pt : pfp.
Tp3s[ipt].Tj2Pts) {
361 auto& tp = tjs.
allTraj[tj2pt.id - 1].Pts[tj2pt.ipt];
362 if(tp.Environment[
kEnvFlag]) ++nused;
365 if(sep2D > sectionLen) big2DSep =
true;
367 if(big2DSep || nused > 1)
continue;
370 if(alongTrans[1] > 0.5)
continue;
376 tp3.AlongTrans = alongTrans;
381 for(
auto tj2pt : tp3.Tj2Pts) tjs.
allTraj[tj2pt.id - 1].Pts[tj2pt.ipt].Environment[
kEnvFlag] =
true;
386 if(lastPtAdded != endPt) ntp3.push_back(pfp.
Tp3s[endPt]);
389 float len =
PosSep(ntp3[0].Pos, ntp3[ntp3.size()-1].Pos);
390 mf::LogVerbatim(
"TC")<<
"FollowTp3s: Tp3s size in "<<pfp.
Tp3s.size()<<
" size out "<<ntp3.size()<<
" len "<<std::fixed<<std::setprecision(2)<<len;
394 if(pfp.
Vx3ID[0] > 0) {
396 Point3_t vpos = {{vx3.X, vx3.Y, vx3.Z}};
397 auto& firstTp3Pos = ntp3[0].Pos;
398 auto& lastTp3Pos = ntp3[ntp3.size() - 1].Pos;
399 if(
PosSep2(lastTp3Pos, vpos) <
PosSep2(firstTp3Pos, vpos)) std::reverse(ntp3.begin(), ntp3.end());
406 pfp.
XYZ[0] = ntp3[0].Pos;
407 pfp.
XYZ[1] = ntp3[ntp3.size()-1].Pos;
414 return FitTp3s(tjs, tp3s, 0, tp3s.size(), pos,
dir, rCorr);
421 if(tp3s.size() < 3)
return false;
422 if(fromPt >= toPt)
return false;
423 if(toPt > tp3s.size())
return false;
426 std::vector<unsigned short> useID;
427 std::vector<unsigned short> useIpt;
428 std::vector<unsigned short> cntInPln(tjs.
NumPlanes);
429 for(
unsigned short ipt = fromPt; ipt < toPt; ++ipt) {
430 auto& tp3 = tp3s[ipt];
431 for(
auto& tj2pt : tp3.Tj2Pts) {
433 for(
unsigned short ii = 0; ii < useID.size(); ++ii) {
434 if(tj2pt.id == useID[ii] && tj2pt.ipt == useIpt[ii]) isUsed =
true;
438 useID.push_back(tj2pt.id);
439 useIpt.push_back(tj2pt.ipt);
440 auto& tj = tjs.
allTraj[tj2pt.id - 1];
445 unsigned short enufInPlane = 0;
446 for(
unsigned short plane = 0; plane < tjs.
NumPlanes; ++plane)
if(cntInPln[plane] > 1) ++enufInPlane;
447 if(enufInPlane < 2)
return false;
449 const unsigned int nvars = 4;
450 unsigned int npts = useID.size();
451 TMatrixD A(npts, nvars);
457 for(
unsigned short ipt = 0; ipt < useID.size(); ++ipt) {
458 auto& tp = tjs.
allTraj[useID[ipt] - 1].Pts[useIpt[ipt]];
462 x0 /= (double)useID.size();
465 for(
unsigned short ipt = 0; ipt < useID.size(); ++ipt) {
466 auto& tp = tjs.
allTraj[useID[ipt] - 1].Pts[useIpt[ipt]];
468 unsigned int cstat = planeID.
Cryostat;
469 unsigned int tpc = planeID.
TPC;
470 unsigned int plane = planeID.
Plane;
478 A[ipt][0] = wght * cw;
479 A[ipt][1] = wght *
sw;
480 A[ipt][2] = wght * cw *
x;
481 A[ipt][3] = wght * sw *
x;
482 w[ipt] = wght * (tp.Pos[0] - off);
487 TVectorD tVec = svd.Solve(w, ok);
488 double norm = sqrt(1 + tVec[2] * tVec[2] + tVec[3] * tVec[3]);
490 dir[1] = tVec[2] /
norm;
491 dir[2] = tVec[3] /
norm;
496 std::cout<<
"FTP3s: "<<useID.size()<<
" cntInPln "<<cntInPln[0]<<
" "<<cntInPln[1]<<
" "<<cntInPln[2]<<
"\n";
509 if(tj2pts.size() < 4)
return false;
511 const unsigned int nvars = 4;
512 unsigned int npts = tj2pts.size();
513 TMatrixD A(npts, nvars);
518 for(
auto& tj2pt : tj2pts) {
519 auto& tp = tjs.
allTraj[tj2pt.id - 1].Pts[tj2pt.ipt];
523 x0 /= (double)tj2pts.size();
525 unsigned short ninpl[3] = {0};
526 unsigned short nok = 0;
528 for(
unsigned short ipt = 0; ipt < tj2pts.size(); ++ipt) {
529 auto& tj2pt = tj2pts[ipt];
530 auto& tp = tjs.
allTraj[tj2pt.id - 1].Pts[tj2pt.ipt];
532 unsigned int cstat = planeID.
Cryostat;
533 unsigned int tpc = planeID.
TPC;
534 unsigned int plane = planeID.
Plane;
542 A[ipt][0] = wght * cw;
543 A[ipt][1] = wght *
sw;
544 A[ipt][2] = wght * cw *
x;
545 A[ipt][3] = wght * sw *
x;
546 w[ipt] = wght * (tp.Pos[0] - off);
549 if(ninpl[plane] == 2) ++nok;
553 if(nok < 2)
return false;
557 TVectorD tVec = svd.Solve(w, ok);
563 double norm = sqrt(1 + tVec[2] * tVec[2] + tVec[3] * tVec[3]);
564 fitDir[0] = 1 /
norm;
565 fitDir[1] = tVec[2] /
norm;
566 fitDir[2] = tVec[3] /
norm;
573 if(tp3.
Pos[2] != 0) {
574 double dz = tp3.
Pos[2] - fitPos[2];
575 fitPos[0] += dz * fitDir[0] / fitDir[2];
576 fitPos[1] += dz * fitDir[1] / fitDir[2];
581 std::cout<<
"Crazy fitPos "<<
PosSep(fitPos, tp3.
Pos)<<
"\n";
601 if(pfp.
TjIDs.size() < 2)
return;
608 if(fillTp3s) pfp.
Tp3s.clear();
611 bool twoTjs = (pfp.
TjIDs.size() == 2);
613 bool smallAngle =
false;
615 smallAngle = (pfp.
Dir[0][0] != 0 && std::abs(pfp.
Dir[0][0]) < 0.1);
623 if(doFit)
Fit3D(0, point, dir, point, dir);
627 std::vector<unsigned short> tjids(pfp.
TjIDs.size());
629 std::vector<std::vector<bool>> tjptMat3;
631 std::vector<std::vector<bool>> tjptMat2;
633 std::vector<unsigned short> tjplane;
635 unsigned int maxTp3Size = 10000;
637 for(
unsigned short itj = 0; itj < pfp.
TjIDs.size(); ++itj) {
638 if(pfp.
TjIDs[itj] <= 0) {
639 std::cout<<
"FindCompleteness: Bad tjid "<<pfp.
TjIDs[itj]<<
"\n";
642 tjids[itj] = pfp.
TjIDs[itj];
644 std::vector<bool>
tmp(tj.Pts.size(),
false);
645 tjptMat2.push_back(
tmp);
646 if(!twoPlanes) tjptMat3.push_back(
tmp);
650 for(
unsigned int ipt = 0; ipt < tjs.
mallTraj.size() - 1; ++ipt) {
652 unsigned short indx = 0;
653 for(indx = 0; indx < tjids.size(); ++indx)
if(iTjPt.id == tjids[indx])
break;
655 if(indx == tjids.size())
continue;
656 auto& itj = tjs.
allTraj[iTjPt.id - 1];
658 auto& itp = itj.Pts[iTjPt.ipt];
662 for(
unsigned int jpt = ipt + 1; jpt < tjs.
mallTraj.size() - 1; ++jpt) {
665 if(jTjPt.ctp == iTjPt.ctp)
continue;
666 unsigned short jndx = 0;
667 for(jndx = 0; jndx < tjids.size(); ++jndx)
if(jTjPt.id == tjids[jndx])
break;
669 if(jndx == tjids.size())
continue;
671 if(jTjPt.xlo > iTjPt.xhi)
continue;
673 if(jTjPt.xlo > iTjPt.xhi + 5)
break;
674 auto& jtj = tjs.
allTraj[jTjPt.id - 1];
676 auto& jtp = jtj.Pts[jTjPt.ipt];
678 if(!
MakeTp3(tjs, itp, jtp, ijtp3,
true))
continue;
683 tjptMat2[indx][iTjPt.ipt] =
true;
684 tjptMat2[jndx][jTjPt.ipt] =
true;
686 if(fillTp3s && pfp.
Tp3s.size() < maxTp3Size) {
690 if(smallAngle) saveIt = ijtp3.
AlongTrans[1] < 1;
691 if(saveIt) pfp.
Tp3s.push_back(ijtp3);
693 if(doFit)
Fit3D(1, ijtp3.
Pos, ijtp3.
Dir, point, dir);
698 unsigned short kplane = 3 - iplane - jplane;
700 if(fwire < -0.4)
continue;
701 unsigned int kwire = std::nearbyint(fwire);
704 if(doFit)
Fit3D(1, ijtp3.
Pos, ijtp3.
Dir, point, dir);
706 if(fillTp3s && pfp.
Tp3s.size() < maxTp3Size) {
709 if(smallAngle) saveIt = ijtp3.
AlongTrans[1] < 1;
710 if(saveIt) pfp.
Tp3s.push_back(ijtp3);
714 for(
unsigned int kpt = jpt + 1; kpt < tjs.
mallTraj.size(); ++kpt) {
717 if(kTjPt.ctp == iTjPt.ctp || kTjPt.ctp == jTjPt.ctp)
continue;
719 unsigned short kndx = 0;
720 for(kndx = 0; kndx < tjids.size(); ++kndx)
if(kTjPt.id == tjids[kndx])
break;
722 if(!fillTp3s && kndx == tjids.size())
continue;
723 if(kTjPt.xlo > iTjPt.xhi)
continue;
725 if(kTjPt.xlo > iTjPt.xhi + 5)
break;
726 auto& ktj = tjs.
allTraj[kTjPt.id - 1];
728 auto& ktp = ktj.Pts[kTjPt.ipt];
730 if(!
MakeTp3(tjs, itp, ktp, iktp3,
true))
continue;
731 if(std::abs(ijtp3.
Pos[1] - iktp3.
Pos[1]) > yzcut)
continue;
732 if(std::abs(ijtp3.
Pos[2] - iktp3.
Pos[2]) > yzcut)
continue;
736 ijktp3.
Tj2Pts.push_back(kTjPt);
738 if(doFit)
Fit3D(1, iktp3.
Pos, iktp3.
Dir, point, dir);
740 if(fillTp3s && pfp.
Tp3s.size() < maxTp3Size) {
742 ijktp3.dEdx = (2 * ijktp3.dEdx + ktp.Chg) / 3;
745 if(smallAngle) saveIt = ijktp3.AlongTrans[1] < 1;
746 if(saveIt) pfp.
Tp3s.push_back(ijktp3);
749 if(kndx == tjids.size())
continue;
750 tjptMat3[indx][iTjPt.ipt] =
true;
751 tjptMat3[jndx][jTjPt.ipt] =
true;
752 tjptMat3[kndx][kTjPt.ipt] =
true;
760 myprt<<
"FC: P"<<pfp.
ID<<
" fit pos "<<std::fixed<<std::setprecision(1)<<pfp.
XYZ[0][0]<<
" "<<pfp.
XYZ[0][1]<<
" "<<pfp.
XYZ[0][2];
761 myprt<<
" fit dir "<<std::setprecision(2)<<pfp.
Dir[0][0]<<
" "<<pfp.
Dir[0][1]<<
" "<<pfp.
Dir[0][2];
762 myprt<<
" Note: fit pos is the average position of all Tp3s - not the start or end.";
771 for(
unsigned short itj = 0; itj < tjids.size(); ++itj) {
772 auto& tj = tjs.
allTraj[tjids[itj] - 1];
777 for(
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
778 if(tj.Pts[ipt].Chg <= 0)
continue;
780 if(tjptMat2[itj][ipt]) ++cnt2;
781 if(!twoPlanes && tjptMat3[itj][ipt]) ++cnt3;
793 myprt<<
"FC: P"<<pfp.
ID<<
" T"<<tj.ID<<
" npwc "<<npwc<<
" cnt2 "<<cnt2<<
" cnt3 "<<cnt3<<
" PDGCode "<<tj.PDGCode;
794 myprt<<
" MCSMom "<<tj.MCSMom<<
" InShower? "<<tj.SSID;
795 myprt<<
" TjCompleteness "<<std::setprecision(2)<<pfp.
TjCompleteness[itj];
799 pfp.
EffPur = tcnt2 / tnpwc;
801 pfp.
EffPur = tcnt3 / tnpwc;
813 if(pfp.
TjIDs.empty() || pfp.
Tp3s.empty())
return;
817 std::vector<float> projInPlane(tjs.
NumPlanes);
818 for(
unsigned short plane = 0; plane < tjs.
NumPlanes; ++plane) {
821 projInPlane[plane] = tp.Delta;
824 std::vector<unsigned short> pfpTjs;
825 std::vector<unsigned short> usMissTjs;
826 std::vector<std::vector<bool>> misTjPtMat;
827 for(
auto tjid : pfp.
TjIDs) pfpTjs.push_back((
unsigned short)tjid);
828 for(
auto& tp3 : pfp.
Tp3s) {
829 for(
auto& tj2pt : tp3.Tj2Pts) {
830 if(std::find(pfpTjs.begin(), pfpTjs.end(), tj2pt.id) != pfpTjs.end())
continue;
832 unsigned short mtjIndx = 0;
833 for(mtjIndx = 0; mtjIndx < usMissTjs.size(); ++mtjIndx)
if(tj2pt.id == usMissTjs[mtjIndx])
break;
834 if(mtjIndx == usMissTjs.size()) {
836 auto& mtj = tjs.
allTraj[tj2pt.id - 1];
839 usMissTjs.push_back(tj2pt.id);
841 std::vector<bool> ptMat(mtj.Pts.size(),
false);
842 ptMat[tj2pt.ipt] =
true;
843 misTjPtMat.push_back(ptMat);
845 if(tj2pt.ipt < misTjPtMat[mtjIndx].size()) misTjPtMat[mtjIndx][tj2pt.ipt] =
true;
849 for(
unsigned short im = 0; im < usMissTjs.size(); ++im) {
850 int mtjid = usMissTjs[im];
854 auto& mtj = tjs.
allTraj[mtjid - 1];
857 for(
unsigned short ipt = mtj.EndPt[0]; ipt <= mtj.EndPt[1]; ++ipt) {
858 auto& mtp = mtj.Pts[ipt];
859 if(mtp.Chg <= 0)
continue;
861 if(misTjPtMat[im][ipt]) ++
mat;
863 float frac = mat / cnt;
865 if(frac < 0.1)
continue;
867 float lenInPlane = 0;
868 for(
auto tjid : pfp.
TjIDs) {
869 auto& tj = tjs.
allTraj[tjid - 1];
870 if(tj.CTP != mtj.CTP)
continue;
871 float len =
PosSep(tj.Pts[tj.EndPt[0]].Pos, tj.Pts[tj.EndPt[1]].Pos);
872 if(len > lenInPlane) lenInPlane = len;
874 if(cnt < 0.05 * lenInPlane)
continue;
877 missTjs.push_back(mtjid);
878 missFrac.push_back(frac);
887 for(
unsigned short end = 0;
end < 2; ++
end) {
893 if(!shared.empty())
return true;
905 static double fSum, fSumx, fSumy, fSumz;
908 static double fSumDir0, fSumDir1, fSumDir2;
911 fSum = 0; fSumx = 0; fSumy = 0; fSumz = 0;
913 fSumDir0 = 0; fSumDir1 = 0; fSumDir2 = 0;
937 fitPos[0] = fSumx / fSum;
938 fitPos[1] = fSumy / fSum;
939 fitPos[2] = fSumz / fSum;
941 fitDir = {{fSumDir0, fSumDir1, fSumDir2}};
1064 if(tjids.empty())
return 0;
1067 float fLoWire = 1E6;
1068 float fHiWire = -1E6;
1069 for(
auto tjid : tjids) {
1070 auto& tj = tjs.
allTraj[tjid - 1];
1071 if(tj.CTP != inCTP)
continue;
1072 for(
unsigned short end = 0;
end < 2; ++
end) {
1073 float endWire = tj.Pts[tj.EndPt[
end]].Pos[0];
1074 if(endWire < -0.4)
continue;
1075 if(endWire < fLoWire) fLoWire = endWire;
1076 if(endWire > fHiWire) fHiWire = endWire;
1079 if(fLoWire >= fHiWire)
return 0;
1080 unsigned int loWire = std::nearbyint(fLoWire);
1081 unsigned short nWires = std::nearbyint(fHiWire) - loWire + 1;
1082 std::vector<bool> ptOnWire(nWires,
false);
1086 for(
auto tjid : tjids) {
1087 auto& tj = tjs.
allTraj[tjid - 1];
1088 if(tj.CTP != inCTP)
continue;
1089 for(
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1090 auto& tp = tj.Pts[ipt];
1091 if(tp.Chg <= 0)
continue;
1092 if(tp.Pos[0] < -0.4)
continue;
1094 unsigned short indx = std::nearbyint(tp.Pos[0]) - loWire;
1095 if(indx < nWires) ptOnWire[indx] =
true;
1098 if(npwc == 0)
return 0;
1100 for(
unsigned short indx = 0; indx < nWires; ++indx)
if(!ptOnWire[indx]) ++nskip;
1101 return (nskip / npwc);
1109 if(tjids.empty())
return 0;
1111 std::vector<Point2_t> endPos;
1112 for(
auto tjid : tjids) {
1113 auto& tj = tjs.
allTraj[tjid - 1];
1114 if(tj.CTP != inCTP)
continue;
1115 endPos.push_back(tj.Pts[tj.EndPt[0]].Pos);
1116 endPos.push_back(tj.Pts[tj.EndPt[1]].Pos);
1118 if(endPos.size() < 2)
return 0;
1120 for(
unsigned short pt1 = 0; pt1 < endPos.size() - 1; ++pt1) {
1121 for(
unsigned short pt2 = pt1 + 1; pt2 < endPos.size(); ++pt2) {
1122 float sep =
PosSep2(endPos[pt1], endPos[pt2]);
1123 if(sep > extent) extent = sep;
1126 return sqrt(extent);
1135 if(itj > pfp.
TjIDs.size() - 1)
return false;
1136 if(tjs.
matchVec.empty())
return false;
1138 int theTj = pfp.
TjIDs[itj];
1141 unsigned short oldSize = pfp.
TjIDs.size();
1143 for(
unsigned int ims = 0; ims < tjs.
matchVec.size(); ++ims) {
1146 unsigned short tjIndex = 0;
1147 for(tjIndex = 0; tjIndex < ms.TjIDs.size(); ++tjIndex)
if(ms.TjIDs[tjIndex] == theTj)
break;
1148 if(tjIndex == ms.TjIDs.size())
continue;
1150 if(shared.empty())
continue;
1153 bool isWorse = (ms.TjCompleteness[tjIndex] < pfp.
TjCompleteness[itj]);
1154 if(shared.size() < 2 && isWorse)
continue;
1157 if(shared.size() < 2)
continue;
1160 for(
auto tjid : ms.TjIDs) {
1161 if(std::find(pfp.
TjIDs.begin(), pfp.
TjIDs.end(), tjid) != pfp.
TjIDs.end())
continue;
1162 pfp.
TjIDs.push_back(tjid);
1169 if(pfp.
TjIDs.size() > oldSize)
return true;
1179 if(pfp.
TjIDs.empty())
return false;
1180 if(pfp.
Tp3s.empty())
return false;
1183 unsigned short nplanes = TPC.
Nplanes();
1186 std::vector<unsigned short> cntInPln(nplanes);
1188 for(
auto tjid : pfp.
TjIDs) {
1189 auto& tj = tjs.
allTraj[tjid - 1];
1192 if(cntInPln[plane] > 1) itsOK =
false;
1194 if(itsOK)
return true;
1197 std::vector<int> newTjIDs;
1201 myprt<<
"MergePFPTjs: P"<<pfp.
ID<<
" in";
1202 for(
auto tjid : pfp.
TjIDs) myprt<<
" T"<<tjid;
1205 for(
unsigned short plane = 0; plane < nplanes; ++plane) {
1208 std::vector<unsigned short> tjids;
1209 for(
auto tjid : pfp.
TjIDs)
if(tjs.
allTraj[tjid - 1].CTP == inCTP) tjids.push_back((
unsigned short)tjid);
1211 if(tjids.size() == 1) {
1212 newTjIDs.push_back((
int)tjids[0]);
1216 if(tjids.size() == 0)
continue;
1223 std::vector<std::array<unsigned short, 2>> firstPts;
1224 for(
unsigned short itp3 = 0; itp3 < pfp.
Tp3s.size(); ++itp3) {
1225 auto& tp3 = pfp.
Tp3s[itp3];
1226 for(
auto& tj2pt : tp3.Tj2Pts) {
1227 unsigned short tjIndx = 0;
1228 for(tjIndx = 0; tjIndx < tjids.size(); ++tjIndx)
if(tj2pt.id == tjids[tjIndx])
break;
1229 if(tjIndx == tjids.size())
continue;
1231 unsigned short firstPtsIndx = 0;
1232 for(firstPtsIndx = 0; firstPtsIndx < firstPts.size(); ++firstPtsIndx)
if(tj2pt.id == firstPts[firstPtsIndx][0])
break;
1233 if(firstPtsIndx == firstPts.size()) {
1235 std::array<unsigned short, 2> firstPt {{tj2pt.id, tj2pt.ipt}};
1236 firstPts.push_back(firstPt);
1240 if(firstPts.empty())
continue;
1248 for(
auto firstPt : firstPts) {
1250 auto tj = tjs.
allTraj[firstPt[0] - 1];
1251 unsigned short midPt = 0.5 * (tj.EndPt[0] + tj.EndPt[1]);
1256 mtj.
VtxID[0] = tj.VtxID[0];
1258 mtj.
VtxID[1] = tj.VtxID[1];
1260 for(
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1261 auto& tp = tj.Pts[ipt];
1262 if(tp.Chg <= 0)
continue;
1263 mtj.
Pts.push_back(tp);
1272 myprt<<
" P"<<pfp.
ID<<
" try to merge";
1273 for(
auto tjid : tjids) {
1274 auto& tj = tjs.
allTraj[tjid - 1];
1275 myprt<<
" T"<<tjid<<
" MCSMom "<<tj.MCSMom;
1277 myprt<<
" -> T"<<tjs.
allTraj.size() + 1;
1278 myprt<<
" MCSMom "<<mtj.
MCSMom;
1281 for(
auto tjid : tjids) {
1282 auto& tj = tjs.
allTraj[tjid - 1];
1283 if(tj.SSID > 0) mtj.
SSID = tj.SSID;
1288 std::cout<<
"MergePFPTjs: StoreTraj failed P"<<pfp.
ID<<
" EventsProcessed "<<tjs.
EventsProcessed<<
"\n";
1291 int newTjID = tjs.
allTraj.size();
1292 newTjIDs.push_back(newTjID);
1294 std::vector<unsigned short> vxlist;
1295 for(
auto tjid : tjids) {
1300 auto& tj = tjs.
allTraj[tjid - 1];
1301 for(
unsigned short end = 0;
end < 2; ++
end) {
1302 if(tj.VtxID[
end] == 0)
continue;
1303 if(std::find(vxlist.begin(), vxlist.end(), tj.VtxID[
end]) != vxlist.end()) {
1304 auto& vx2 = tjs.
vtx[tj.VtxID[
end] - 1];
1308 vxlist.push_back(tj.VtxID[
end]);
1314 pfp.
TjIDs = newTjIDs;
1318 myprt<<
"MergePFPTjs: P"<<pfp.
ID<<
" out";
1319 for(
auto tjid : pfp.
TjIDs) myprt<<
" T"<<tjid;
1326 void FindXMatches(
TjStuff& tjs,
unsigned short numPlanes,
short maxScore, std::vector<MatchStruct>& matVec,
bool prt)
1333 if(numPlanes < 2)
return;
1337 constexpr
float twopi = 2 * M_PI;
1338 constexpr
float piOver2 = M_PI / 2;
1341 auto inMatVec = matVec;
1342 std::vector<MatchStruct> temp;
1345 unsigned short minPts = 2;
1350 unsigned int nAvailable = 0;
1352 if(nAvailable == 0 || nAvailable > tjs.
Match3DCuts[4])
return;
1356 double yzcut = 1.5 * xcut;
1357 for(
unsigned int ipt = 0; ipt < tjs.
mallTraj.size() - 1; ++ipt) {
1360 if(iTjPt.npts < minPts)
continue;
1362 if(iTjPt.score < 0 || iTjPt.score > maxScore)
continue;
1363 auto& itp = tjs.
allTraj[iTjPt.id - 1].Pts[iTjPt.ipt];
1365 for(
unsigned int jpt = ipt + 1; jpt < tjs.
mallTraj.size() - 1; ++jpt) {
1368 if(jTjPt.ctp == iTjPt.ctp)
continue;
1370 if(jTjPt.npts < minPts)
continue;
1372 if(jTjPt.score < 0 || jTjPt.score > maxScore)
continue;
1374 if(jTjPt.xlo > iTjPt.xhi)
continue;
1376 if(jTjPt.xlo > iTjPt.xhi + 5)
break;
1377 auto& jtp = tjs.
allTraj[jTjPt.id - 1].Pts[jTjPt.ipt];
1380 if(!
MakeTp3(tjs, itp, jtp, tp3,
false))
continue;
1383 if(numPlanes == 3) {
1385 for(
unsigned int kpt = jpt + 1; kpt < tjs.
mallTraj.size(); ++kpt) {
1388 if(kTjPt.ctp == iTjPt.ctp || kTjPt.ctp == jTjPt.ctp)
continue;
1389 if(kTjPt.score < 0 || kTjPt.score > maxScore)
continue;
1390 if(kTjPt.xlo > iTjPt.xhi)
continue;
1392 if(kTjPt.xlo > iTjPt.xhi + 5)
break;
1393 auto& ktp = tjs.
allTraj[kTjPt.id - 1].Pts[kTjPt.ipt];
1396 if(!
MakeTp3(tjs, itp, ktp, iktp3,
false))
continue;
1397 if(std::abs(tp3.
Pos[1] - iktp3.
Pos[1]) > yzcut)
continue;
1398 if(std::abs(tp3.
Pos[2] - iktp3.
Pos[2]) > yzcut)
continue;
1402 while(dang > M_PI) dang -= twopi;
1403 if(dang > piOver2) dang = M_PI - dang;
1404 float mcsmom = tjs.
allTraj[iTjPt.id - 1].MCSMom + tjs.
allTraj[jTjPt.id - 1].MCSMom + tjs.
allTraj[kTjPt.id - 1].MCSMom;
1406 if(mcsmom > 150 && dang > tjs.
Match3DCuts[1])
continue;
1412 for(
auto& ms : inMatVec) {
1413 if(ms.TjIDs.size() != 3)
continue;
1414 if(iTjPt.id == ms.TjIDs[iplane] && jTjPt.id == ms.TjIDs[jplane] && kTjPt.id == ms.TjIDs[kplane]) {
1422 if(cntWght <= 0)
continue;
1424 unsigned short indx = 0;
1425 for(indx = 0; indx < temp.size(); ++indx) {
1426 auto& ms = temp[indx];
1427 if(iTjPt.id != ms.TjIDs[iplane])
continue;
1428 if(jTjPt.id != ms.TjIDs[jplane])
continue;
1429 if(kTjPt.id != ms.TjIDs[kplane])
continue;
1430 ms.Count += cntWght;
1433 if(indx == temp.size()) {
1439 ms.
TjIDs[iplane] = iTjPt.id;
1440 ms.
TjIDs[jplane] = jTjPt.id;
1441 ms.
TjIDs[kplane] = kTjPt.id;
1445 if(temp.size() > nAvailable)
break;
1453 unsigned short kplane = 3 - iplane - jplane;
1455 if(fkwire < 0 || fkwire > tjs.
MaxPos0[kplane])
continue;
1458 tpk.
Pos[0] = fkwire;
1459 float xp = 0.5 * (iTjPt.xlo + iTjPt.xhi);
1466 for(
auto& ms : inMatVec) {
1467 if(std::find(ms.TjIDs.begin(), ms.TjIDs.end(), iTjPt.id) != ms.TjIDs.end() &&
1468 std::find(ms.TjIDs.begin(), ms.TjIDs.end(), jTjPt.id) != ms.TjIDs.end()) {
1474 unsigned short indx = 0;
1475 for(indx = 0; indx < temp.size(); ++indx) {
1476 auto& ms = temp[indx];
1477 if(std::find(ms.TjIDs.begin(), ms.TjIDs.end(), iTjPt.id) != ms.TjIDs.end() &&
1478 std::find(ms.TjIDs.begin(), ms.TjIDs.end(), jTjPt.id) != ms.TjIDs.end())
break;
1480 if(indx == temp.size()) {
1484 ms.
TjIDs[0] = iTjPt.id;
1485 ms.
TjIDs[1] = jTjPt.id;
1494 if(temp.size() > nAvailable)
break;
1497 if(temp.size() > nAvailable)
break;
1502 if(temp.empty())
return;
1504 if(temp.size() == 1) {
1505 matVec.push_back(temp[0]);
1508 std::vector<SortEntry> sortVec(temp.size());
1509 for(
unsigned int indx = 0; indx < sortVec.size(); ++indx) {
1510 sortVec[indx].index = indx;
1511 sortVec[indx].val = temp[indx].Count;
1516 for(
unsigned int ii = 0; ii < sortVec.size(); ++ii) temp[ii] = tmpVec[sortVec[ii].
index];
1518 matVec.insert(matVec.end(), temp.begin(), temp.end());
1521 if(prt)
mf::LogVerbatim(
"TC")<<
"FindXMatches: Found "<<temp.size()<<
" matches";
1529 tp3.
Dir = {{999.0, 999.0, 999.0}};
1530 tp3.
Pos = {{999.0, 999.0, 999.0}};
1538 if(std::abs(ix - jx) > 20)
return false;
1539 tp3.
Pos[0] = 0.5 * (ix + jx);
1551 double den = isn * jcs - ics * jsn;
1552 if(den == 0)
return false;
1553 double iPos0 = itp.
Pos[0];
1554 double jPos0 = jtp.
Pos[0];
1556 tp3.
Pos[2] = (jcs * (iPos0 - iw0) - ics * (jPos0 - jw0)) / den;
1558 bool useI = std::abs(ics) > std::abs(jcs);
1560 tp3.
Pos[1] = (iPos0 - iw0 - isn * tp3.
Pos[2]) / ics;
1562 tp3.
Pos[1] = (jPos0 - jw0 - jsn * tp3.
Pos[2]) / jcs;
1566 if(jtp.
Dir[1] == 0) {
1568 if(jtp.
Dir[0] > 0) { tp3.
Dir[0] = 1; }
else { tp3.
Dir[0] = -1; }
1577 if(!findDirection)
return true;
1580 double itp2_0 = itp.
Pos[0] + 100;
1581 double itp2_1 = itp.
Pos[1];
1582 if(std::abs(itp.
Dir[0]) > 0.01) itp2_1 += 100 * itp.
Dir[1] / itp.
Dir[0];
1590 double jtp2Pos0 = (jtp2Pos1 - jtp.
Pos[1]) * (jtp.
Dir[0] / jtp.
Dir[1]) + jtp.
Pos[0];
1592 pos2[2] = (jcs * (itp2_0 - iw0) - ics * (jtp2Pos0 - jw0)) / den;
1594 pos2[1] = (itp2_0 - iw0 - isn * pos2[2]) / ics;
1596 pos2[1] = (jtp2Pos0 - jw0 - jsn * pos2[2]) / jcs;
1599 if(sep == 0)
return false;
1600 for(
unsigned short ixyz = 0; ixyz < 3; ++ixyz) tp3.
Dir[ixyz] = (pos2[ixyz] - tp3.
Pos[ixyz]) /sep;
1609 if(v1[0] == v2[0] && v1[1] == v2[1] && v1[2] == v2[2])
return 0;
1618 for(
unsigned short xyz = 0; xyz < 3; ++xyz) dir[xyz] = p2[xyz] - p1[xyz];
1619 if(dir[0] == 0 && dir[1] == 0 && dir[2] == 0)
return dir;
1620 if(!
SetMag(dir, 1)) { dir[0] = 0; dir[1] = 0; dir[3] = 0; }
1627 return sqrt(
PosSep2(pos1, pos2));
1634 double d0 = pos1[0] - pos2[0];
1635 double d1 = pos1[1] - pos2[1];
1636 double d2 = pos1[2] - pos2[2];
1637 return d0*d0 + d1*d1 + d2*d2;
1643 double den = v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2];
1644 if(den == 0)
return false;
1658 if(pfp.
ID == 0)
return;
1660 bool notgood =
false;
1661 for(
unsigned short startend = 0; startend < 2; ++startend) {
1662 if(pfp.
dEdx[startend].size() != tjs.
NumPlanes) notgood =
true;
1672 unsigned short numEnds = 2;
1674 if(pfp.
PDGCode == 1111) numEnds = 1;
1676 unsigned short maxlen = 0;
1677 for(
auto tjID : pfp.
TjIDs) {
1681 double angleToVert = tjs.
geom->
Plane(planeID).
ThetaZ() - 0.5 * ::util::pi<>();
1682 for(
unsigned short startend = 0; startend < numEnds; ++startend) {
1684 tj.
dEdx[startend] = 0;
1685 double cosgamma = std::abs(std::sin(angleToVert) * pfp.
Dir[startend][1] + std::cos(angleToVert) * pfp.
Dir[startend][2]);
1686 if(cosgamma == 0)
continue;
1688 if(dx == 0)
continue;
1689 double dQ = tj.
Pts[tj.
EndPt[startend]].AveChg;
1690 if(dQ == 0)
continue;
1695 if(dedx > 999) dedx = 999;
1696 pfp.
dEdx[startend][planeID.
Plane] = dedx;
1697 tj.
dEdx[startend] = dedx;
1704 if(tj.
Pts.size() > maxlen) {
1705 maxlen = tj.
Pts.size();
1718 if(tp3.
Tj2Pts.empty())
return;
1723 for(
auto& tj2pt : tp3.
Tj2Pts) {
1724 auto& tp = tjs.
allTraj[tj2pt.id - 1].Pts[tj2pt.ipt];
1725 if(tp.Chg <= 0)
continue;
1727 double angleToVert = tjs.
geom->
Plane(planeID).
ThetaZ() - 0.5 * ::util::pi<>();
1728 double cosgamma = std::abs(std::sin(angleToVert) * tp3.
Dir[1] + std::cos(angleToVert) * tp3.
Dir[2]);
1729 if(cosgamma == 0)
continue;
1733 for(
unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1734 if(!tp.UseHit[ii])
continue;
1735 unsigned int iht = tp.Hits[ii];
1736 chg += tjs.
fHits[iht].Integral;
1738 double dQ = chg / dx;
1741 if(dedx > 200)
continue;
1743 sum2 += dedx * dedx;
1746 if(cnt == 0)
return;
1747 tp3.
dEdx = sum / cnt;
1766 float minSep2 = 1E8;
1767 for(
unsigned short ipt1 = 0; ipt1 < pfp1.
Tp3s.size(); ++ipt1) {
1768 auto& tp1 = pfp1.
Tp3s[ipt1];
1769 for(
unsigned short ipt2 = 0; ipt2 < pfp2.
Tp3s.size(); ++ipt2) {
1770 auto& tp2 = pfp2.
Tp3s[ipt2];
1771 float sep2 =
PosSep2(tp1.Pos, tp2.Pos);
1772 if(sep2 > minSep2)
continue;
1778 return sqrt(minSep2);
1785 if(pfp.
Tp3s.empty())
return false;
1788 auto kinkPts =
FindKinks(tjs, pfp, sep, prt);
1789 if(kinkPts.empty())
return false;
1790 if(prt)
mf::LogVerbatim(
"TC")<<
"Split3DKink found a kink at Tp3s point "<<kinkPts[0];
1794 unsigned short kpt = 0;
1795 for(
auto ipt : kinkPts) {
1802 if(kpt < 1 || kpt > pfp.
Tp3s.size() - 1)
return false;
1804 std::vector<unsigned short> tjids;
1805 std::vector<unsigned short> vx2ids;
1807 for(
unsigned short ipt = kpt; ipt < kpt + 2; ++ipt) {
1808 auto& tp3 = pfp.
Tp3s[ipt];
1809 for(
auto& tp2 : tp3.Tj2Pts) {
1811 if(std::find(tjids.begin(), tjids.end(), tp2.id) != tjids.end())
continue;
1813 if(std::find(pfp.
TjIDs.begin(), pfp.
TjIDs.end(), tp2.id) == pfp.
TjIDs.end())
continue;
1814 tjids.push_back(tp2.id);
1815 auto& tj = tjs.
allTraj[tp2.id - 1];
1816 auto& tp = tj.Pts[tp2.ipt];
1817 unsigned short closeEnd = USHRT_MAX;
1818 if(tp2.ipt < tj.EndPt[0] + 2) closeEnd = 0;
1819 if(tp2.ipt > tj.EndPt[1] - 2) closeEnd = 1;
1823 if(tj.VtxID[closeEnd] == 0) {
1827 vx2ids.push_back(tj.VtxID[closeEnd]);
1828 if(prt)
mf::LogVerbatim(
"TC")<<
" tj "<<tj.ID<<
" use existing 2V"<<tj.VtxID[closeEnd];
1832 vx2.
ID = tjs.
vtx.size() + 1;
1837 if(!
SplitTraj(tjs, tp2.id - 1, tp2.ipt, tjs.
vtx.size() - 1, prt))
return false;
1838 vx2ids.push_back(vx2.
ID);
1851 vx3.
ID = tjs.
vtx3.size() + 1;
1852 vx3.
X = pfp.
Tp3s[kpt].Pos[0];
1853 vx3.
Y = pfp.
Tp3s[kpt].Pos[1];
1854 vx3.
Z = pfp.
Tp3s[kpt].Pos[2];
1855 for(
auto vx2id : vx2ids) {
1856 if(vx2id == 0)
continue;
1857 auto& vx2 = tjs.
vtx[vx2id - 1];
1859 vx3.
Vx2ID[plane] = vx2id;
1862 std::cout<<
"Split3DKink add 3V"<<vx3.
ID<<
"\n";
1863 tjs.
vtx3.push_back(vx3);
1874 std::vector<unsigned short> kinkPts;
1877 double angCut = 0.3;
1879 unsigned short kStart = USHRT_MAX;
1881 bool foundKink =
false;
1882 double kinkSep2 = 2 * sep * sep;
1883 for(
unsigned short ipt = 1; ipt < pfp.
Tp3s.size(); ++ipt) {
1887 unsigned short kpt = kinkPts[kinkPts.size() - 1];
1888 if(foundKink &&
PosSep2(pfp.
Tp3s[ipt].Pos, pfp.
Tp3s[kpt].Pos) < kinkSep2)
continue;
1892 if(dang < angCut && kStart == USHRT_MAX)
continue;
1894 if(kStart == USHRT_MAX) {
1900 unsigned short klen = ipt - kStart;
1901 if(prt)
mf::LogVerbatim(
"TC")<<
" findKinks: kink angle "<<kang<<
" at point "<<ipt<<
" klen "<<klen;
1902 kinkPts.push_back(ipt - 1);
1913 double KinkAngle(
const TjStuff& tjs,
const std::vector<TrajPoint3>& tp3s,
unsigned short atPt,
double sep)
1916 if(tp3s.empty())
return -1;
1917 if(atPt < 1 || atPt > tp3s.size() - 2)
return -1;
1918 double sep2 = sep * sep;
1919 unsigned short pt1 = USHRT_MAX;
1920 for(
unsigned short ii = 1; ii < tp3s.size(); ++ii) {
1921 unsigned short ipt = atPt - ii;
1922 if(
PosSep2(tp3s[atPt].Pos, tp3s[ipt].Pos) > sep2) {
1928 if(pt1 == USHRT_MAX)
return -1;
1929 unsigned short pt2 = USHRT_MAX;
1930 for(
unsigned short ii = 1; ii < tp3s.size(); ++ii) {
1931 unsigned short ipt = atPt + ii;
1932 if(ipt == tp3s.size())
break;
1933 if(
PosSep2(tp3s[atPt].Pos, tp3s[ipt].Pos) > sep2) {
1938 if(pt2 == USHRT_MAX)
return -1;
1939 return DeltaAngle(tp3s[pt1].Dir, tp3s[pt2].Dir);
1947 pfp.
ID = tjs.
pfps.size() + 1;
1957 for(
unsigned short startend = 0; startend < 2; ++startend) {
1960 pfp.
Dir[startend] = {{0.0, 0.0, 0.0}};
1961 pfp.
DirErr[startend] = {{0.0, 0.0, 0.0}};
1962 pfp.
XYZ[startend] = {{0.0, 0.0, 0.0}};
1980 for(
auto& tp : tj.Pts) tp.Environment[
kEnvFlag] =
false;
1984 std::vector<MatchStruct> matVec;
1988 for(
short maxScore = 0; maxScore < 2; ++maxScore)
FindXMatches(tjs, 3, maxScore, matVec, prt);
1994 for(
short maxScore = 0; maxScore < 2; ++maxScore)
FindXMatches(tjs, 2, maxScore, matVec, prt);
2001 if(matVec.empty())
return;
2004 if(matVec.size() > 1) {
2006 std::vector<int> dum1;
2007 std::vector<float> dum2;
2008 std::vector<SortEntry> sortVec(matVec.size());
2009 for(
unsigned int ii = 0; ii < matVec.size(); ++ii) {
2010 sortVec[ii].index = ii;
2011 auto& ms = matVec[ii];
2012 sortVec[ii].val = ms.Count;
2014 if(ms.TjIDs.size() == 2) sortVec[ii].
val /= 2;
2017 std::vector<MatchStruct> tmpVec;
2018 tmpVec.reserve(matVec.size());
2019 for(
unsigned int ii = 0; ii < matVec.size(); ++ii) {
2020 tmpVec.push_back(matVec[sortVec[ii].
index]);
2027 for(
auto& ms : matVec) {
2028 if(ms.Count < 2)
continue;
2030 bool skipit =
false;
2032 if(ms.TjIDs == oms.TjIDs) {
2037 if(skipit)
continue;
2039 pfp.
TjIDs = ms.TjIDs;
2043 ms.Pos = pfp.
XYZ[0];
2044 ms.Dir = pfp.
Dir[0];
2051 myprt<<
"FPFP: tjs.matchVec\n";
2052 unsigned short cnt = 0;
2054 std::vector<int> dum1;
2055 std::vector<float> dum2;
2056 for(
unsigned int ii = 0; ii < tjs.
matchVec.size(); ++ii) {
2058 if(ms.Count == 0)
continue;
2059 myprt<<std::setw(4)<<ii<<
" Count "<<std::setw(5)<<(int)ms.Count;
2061 for(
auto& tjid : ms.TjIDs) myprt<<
" T"<<tjid;
2063 for(
unsigned short itj = 0; itj < ms.TjCompleteness.size(); ++itj) {
2064 myprt<<std::setprecision(2)<<std::setw(6)<<ms.TjCompleteness[itj];
2066 myprt<<
" Pos ("<<std::setprecision(0)<<std::fixed;
2067 myprt<<ms.Pos[0]<<
", "<<ms.Pos[1]<<
", "<<ms.Pos[2];
2068 myprt<<
") Dir "<<std::setprecision(2)<<std::setw(6)<<ms.Dir[0]<<std::setw(6)<<ms.Dir[1]<<std::setw(6)<<ms.Dir[2];
2069 myprt<<
" projInPlane";
2070 for(
unsigned short plane = 0; plane < tjs.
NumPlanes; ++plane) {
2072 auto tp =
MakeBareTP(tjs, ms.Pos, ms.Dir, inCTP);
2073 myprt<<
" "<<std::setprecision(2)<<tp.Delta;
2075 myprt<<
" maxTjLen "<<(int)
MaxTjLen(tjs, ms.TjIDs);
2076 myprt<<
" MCSMom "<<
MCSMom(tjs, ms.TjIDs);
2077 myprt<<
" PDGCodeVote "<<
PDGCodeVote(tjs, ms.TjIDs,
false);
2080 if(cnt == 1000 || ms.Count < 2) {
2081 myprt<<
"...stopped printing after 500 entries or Count < 2";
2094 for(
unsigned int indx = 0; indx < tjs.
matchVec.size(); ++indx) {
2097 if(ms.Count == 0)
continue;
2099 bool skipit =
false;
2103 for(
unsigned short itj = 0; itj < ms.TjIDs.size(); ++itj) {
2104 if(ms.TjIDs[itj] <= 0 || ms.TjIDs[itj] > (
int)tjs.
allTraj.size()) {
2105 std::cout<<
"FindPFParticles: bogus ms TjID "<<ms.TjIDs[itj]<<
"\n";
2108 auto& tj = tjs.
allTraj[ms.TjIDs[itj] - 1];
2111 if(ms.TjCompleteness.empty()) {
2112 std::cout<<
"FindPFParticles: ms.TjCompleteness is empty\n";
2115 if(ms.TjCompleteness[itj] < 0.1) skipit =
true;
2116 if(tj.PDGCode == 13) has13 =
true;
2117 if(tj.PDGCode == 11) has11 =
true;
2119 if(skipit)
continue;
2120 if(has13 && has11)
continue;
2123 pfp.
TjIDs = ms.TjIDs;
2126 pfp.
XYZ[0] = ms.Pos;
2127 pfp.
Dir[0] = ms.Dir;
2144 if(prt) std::cout<<
" StorePFP failed P"<<pfp.
ID<<
"\n";
2151 if(!shared.empty()) allms.Count = 0;
2164 if(pfp.
PDGCode == 1111)
return false;
2165 if(pfp.
TjIDs.size() < 2)
return false;
2167 std::string fcnLabel = inFcnLabel +
".DPFP";
2170 std::vector<unsigned short> nInPln(tjs.
NumPlanes);
2171 for(
auto tjid : pfp.
TjIDs) {
2172 auto& tj = tjs.
allTraj[tjid - 1];
2175 std::cout<<fcnLabel<<
" P"<<pfp.
ID<<
" uses T"<<tj.ID<<
" but kMat3D is set true\n";
2179 unsigned short npl = 0;
2180 for(
unsigned short plane = 0; plane < tjs.
NumPlanes; ++plane)
if(nInPln[plane] > 0) ++npl;
2181 if(npl < 2)
return false;
2184 std::cout<<fcnLabel<<
" P"<<pfp.
ID<<
" end 1 has a vertex but end 0 doesn't. No endpoints defined\n";
2197 myprt<<fcnLabel<<
" pfp P"<<pfp.
ID;
2198 myprt<<
" Vx3ID 3V"<<pfp.
Vx3ID[0]<<
" 3V"<<pfp.
Vx3ID[1];
2200 for(
auto id : pfp.
TjIDs) myprt<<
" T"<<id;
2204 myprt<<
" pfpTrackLike? "<<pfpTrackLike;
2210 for(
unsigned short ims = 0; ims < pfp.
MatchVecIndex + 10; ++ims) {
2211 if(ims >= tjs.
matchVec.size())
break;
2213 if(ms.Count == 0)
continue;
2215 if(shared.size() < 2)
continue;
2219 for(
auto tjid : ms.TjIDs) {
2220 if(std::find(shared.begin(), shared.end(), tjid) != shared.end())
continue;
2221 auto& tj = tjs.
allTraj[tjid - 1];
2222 if(tj.AlgMod[
kKilled])
continue;
2223 if(tj.AlgMod[
kMat3D])
continue;
2225 if(pfp.
PDGCode == 13 && tj.PDGCode == 11)
continue;
2226 if(pfp.
PDGCode == 11 && tj.PDGCode == 13)
continue;
2229 float len =
PosSep(tj.Pts[tj.EndPt[0]].Pos, tj.Pts[tj.EndPt[1]].Pos);
2232 bool skipit =
false;
2233 for(
auto tjid : pfp.
TjIDs) {
2234 auto& ptj = tjs.
allTraj[tjid - 1];
2235 if(ptj.CTP != tj.CTP)
continue;
2241 if(skipit)
continue;
2242 if(prt)
mf::LogVerbatim(
"TC")<<
" add T"<<tjid<<
" MCSMom "<<tj.MCSMom<<
" length "<<len;
2243 pfp.
TjIDs.push_back(tjid);
2261 if(pfp.
Tp3s.empty())
return false;
2271 myprt<<fcnLabel<<
" pfp P"<<pfp.
ID;
2272 myprt<<
" Vx3ID 3V"<<pfp.
Vx3ID[0]<<
" 3V"<<pfp.
Vx3ID[1];
2274 for(
auto id : pfp.
TjIDs) myprt<<
" T"<<id;
2275 myprt<<
" Tp3s size "<<pfp.
Tp3s.size();
2289 if(pfp.
ID == 0)
return true;
2290 if(pfp.
TjIDs.empty())
return true;
2291 if(pfp.
Vx3ID[0] == 0)
return true;
2294 std::vector<int> killMe;
2295 for(
auto vx2id : vx3.Vx2ID) {
2296 if(vx2id == 0)
continue;
2297 if(vx2id == 666)
continue;
2298 auto& vx2 = tjs.
vtx[vx2id - 1];
2308 if(setInt.size() < 2)
continue;
2311 unsigned short lenth = 0;
2312 for(
auto tid : setInt) {
2313 auto& tj = tjs.
allTraj[tid - 1];
2314 unsigned short npts = tj.EndPt[1] - tj.EndPt[0] + 1;
2315 if(npts < lenth)
continue;
2319 if(imLong == 0)
continue;
2321 for(
auto tid : setInt)
if(tid != imLong) killMe.push_back(tid);
2323 if(killMe.empty())
return true;
2326 myprt<<
"PVTC: P"<<pfp.
ID<<
" removing short tjs attached to a vertex:";
2327 for(
auto tid : killMe) myprt<<
" T"<<tid;
2330 std::vector<int>
tmp;
2331 for(
auto tid : pfp.
TjIDs) {
2332 if(std::find(killMe.begin(), killMe.end(), tid) == killMe.end()) tmp.push_back(tid);
2342 if(pfp.
ID == 0)
return false;
2343 if(pfp.
TjIDs.empty())
return false;
2344 if(pfp.
Tp3s.empty())
return false;
2348 if(prt)
mf::LogVerbatim(
"TC")<<
"AnalyzePFP: P"<<pfp.
ID<<
" needs to be updated. Skip analysis ";
2353 float minCompleteness = 0.95;
2354 for(
auto tjc : pfp.
TjCompleteness)
if(tjc < minCompleteness) minCompleteness = tjc;
2355 if(prt)
mf::LogVerbatim(
"TC")<<
"inside AnalyzePFP P"<<pfp.
ID<<
" minCompleteness "<<minCompleteness;
2356 if(minCompleteness == 0.95)
return true;
2359 std::vector<int> tjIDs;
2360 std::vector<unsigned short> tjCnt;
2361 for(
auto& tp3 : pfp.
Tp3s) {
2362 for(
auto& tp2 : tp3.Tj2Pts) {
2365 unsigned short indx = 0;
2366 for(indx = 0; indx < tjIDs.size(); ++indx)
if(tjIDs[indx] == tp2.id)
break;
2367 if(indx == tjIDs.size()) {
2368 tjIDs.push_back(itjID);
2377 for(
unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2378 if(std::find(pfp.
TjIDs.begin(), pfp.
TjIDs.end(), tjIDs[ii]) != pfp.
TjIDs.end())
continue;
2379 auto& missTj = tjs.
allTraj[tjIDs[ii] - 1];
2380 if(missTj.AlgMod[
kMat3D])
continue;
2382 if(prt)
mf::LogVerbatim(
"TC")<<
" missed T"<<missTj.ID<<
" npwc "<<npwc<<
" tjCnt "<<tjCnt[ii];
2383 if(tjCnt[ii] < 0.5 * npwc)
continue;
2386 bool skipit =
false;
2387 for(
auto tid : pfp.
TjIDs) {
2388 auto& tj = tjs.
allTraj[tid - 1];
2389 if(tj.CTP == missTj.CTP) skipit =
true;
2391 if(skipit)
continue;
2393 pfp.
TjIDs.push_back(missTj.ID);
2401 myprt<<
"APFP: Tjs in pfp\n";
2402 for(
auto tjid : pfp.
TjIDs) {
2403 auto& tj = tjs.
allTraj[tjid - 1];
2405 unsigned short indx = 0;
2406 for(indx = 0; indx < tjIDs.size(); ++indx)
if(tjIDs[indx] == tjid)
break;
2407 if(indx == tjIDs.size()) {
2408 myprt<<
" not found in P"<<pfp.
ID<<
"\n";
2411 myprt<<
" nTp3 "<<tjCnt[indx]<<
"\n";
2422 for(
auto& pfp : tjs.
pfps) {
2423 if(pfp.ID == 0)
continue;
2424 if(pfp.Vx3ID[0] > 0)
continue;
2429 vx3.
X = pfp.XYZ[0][0];
2430 vx3.
Y = pfp.XYZ[0][1];
2431 vx3.
Z = pfp.XYZ[0][2];
2432 vx3.
ID = tjs.
vtx3.size() + 1;
2434 tjs.
vtx3.push_back(vx3);
2436 pfp.Vx3ID[0] = vx3.
ID;
2477 if(tjs.
pfps.empty())
return;
2478 int neutrinoPFPID = 0;
2479 for(
auto& pfp : tjs.
pfps) {
2480 if(pfp.ID == 0)
continue;
2481 if(pfp.TPCID != tpcid)
continue;
2482 if(!tjs.
TestBeam && neutrinoPFPID == 0 && (pfp.PDGCode == 12 || pfp.PDGCode == 14)) {
2483 neutrinoPFPID = pfp.ID;
2489 constexpr
unsigned short end1 = 1;
2490 for(
auto& pfp : tjs.
pfps) {
2491 if(pfp.ID == 0)
continue;
2492 if(pfp.TPCID != tpcid)
continue;
2494 if(pfp.Vx3ID[end1] > 0)
continue;
2498 unsigned short cnt3 = 0;
2499 unsigned short vx3id = 0;
2501 std::vector<int> vx2ids;
2502 for(
auto tjid : pfp.TjIDs) {
2503 auto& tj = tjs.
allTraj[tjid - 1];
2504 if(tj.VtxID[end1] == 0)
continue;
2505 auto& vx2 = tjs.
vtx[tj.VtxID[end1] - 1];
2506 if(vx2.Vx3ID == 0) {
2507 if(vx2.Topo == 1 && vx2.NTraj == 2) vx2ids.push_back(vx2.ID);
2510 if(vx3id == 0) vx3id = vx2.Vx3ID;
2511 if(vx2.Vx3ID == vx3id) ++cnt3;
2515 if(pfp.Vx3ID[1 - end1] == vx3id)
continue;
2516 pfp.Vx3ID[end1] = vx3id;
2518 std::cout<<
"DPFPR: Missed an end vertex for PFP "<<pfp.ID<<
" Write some code\n";
2524 for(
auto& pfp : tjs.
pfps) {
2525 if(pfp.ID == 0)
continue;
2526 if(pfp.TPCID != tpcid)
continue;
2528 if(pfp.PDGCode == 12 || pfp.PDGCode == 14 || pfp.PDGCode == 22)
continue;
2531 int pfpParentID = INT_MAX;
2532 unsigned short nParent = 0;
2533 for(
auto tjid : pfp.TjIDs) {
2534 auto& tj = tjs.
allTraj[tjid - 1];
2535 if(tj.ParentID == 0)
continue;
2536 unsigned short ppindex =
GetPFPIndex(tjs, tj.ParentID);
2537 if(ppindex == USHRT_MAX)
continue;
2538 int ppid = ppindex + 1;
2539 if(pfpParentID == INT_MAX) pfpParentID = ppid;
2540 if(ppid == pfpParentID) ++nParent;
2544 pfp.ParentID = (size_t)pfpParentID;
2545 auto& parpfp = tjs.
pfps[pfpParentID - 1];
2546 parpfp.DtrIDs.push_back(pfp.ID);
2557 if(neutrinoPFPID > 0) {
2558 auto& neutrinoPFP = tjs.
pfps[neutrinoPFPID - 1];
2559 int vx3id = neutrinoPFP.Vx3ID[1];
2560 for(
auto& pfp : tjs.
pfps) {
2561 if(pfp.ID == 0 || pfp.ID == neutrinoPFPID)
continue;
2562 if(pfp.TPCID != tpcid)
continue;
2563 if(pfp.Vx3ID[0] != vx3id)
continue;
2564 pfp.ParentID = (size_t)neutrinoPFPID;
2566 neutrinoPFP.DtrIDs.push_back(pfp.ID);
2583 std::vector<std::pair<unsigned short, unsigned short>> pardtr;
2587 double fidZCut = tjs.
ZLo + 2;
2588 for(
auto& parPFP : tjs.
pfps) {
2589 if(parPFP.ID == 0)
continue;
2590 parPFP.Primary =
false;
2591 if(parPFP.XYZ[0][2] > fidZCut)
continue;
2592 parPFP.Primary =
true;
2594 if(prt)
mf::LogVerbatim(
"TC")<<
"DPFPTestBeam: parent "<<parPFP.ID<<
" end1 vtx "<<parPFP.Vx3ID[1];
2595 if(parPFP.Vx3ID[1] == 0)
continue;
2599 auto& vx3 = tjs.
vtx3[parPFP.Vx3ID[1] - 1];
2601 if(vx3.ID == 0)
continue;
2604 if(vx3TjList.empty())
continue;
2610 for(
auto dtjID : dtrTjlist) myprt<<
" "<<dtjID<<
"_"<<
GetPFPIndex(tjs, dtjID);
2613 for(
auto dtjID : dtrTjlist) {
2614 unsigned short pfpIndex =
GetPFPIndex(tjs, dtjID);
2615 if(pfpIndex > tjs.
pfps.size() - 1)
continue;
2616 unsigned short dtrID = pfpIndex + 1;
2618 bool duplicate =
false;
2619 for(
auto& pd : pardtr)
if(parPFP.ID == pd.first && dtrID == pd.second) duplicate =
true;
2620 if(!duplicate) pardtr.push_back(std::make_pair(parPFP.ID, dtrID));
2626 for(
unsigned short nit = 0; nit < 100; ++nit) {
2627 if(pardtr.empty())
break;
2628 auto lastPair = pardtr[pardtr.size() - 1];
2629 auto& dtr = tjs.
pfps[lastPair.second - 1];
2630 auto& par = tjs.
pfps[lastPair.first - 1];
2631 dtr.ParentID = par.ID;
2632 par.DtrIDs.push_back(dtr.ID);
2637 unsigned short dtrEnd = USHRT_MAX;
2638 for(
unsigned short ep = 0; ep < 2; ++ep) {
2639 if(par.Vx3ID[ep] == 0)
continue;
2640 for(
unsigned short ed = 0; ed < 2; ++ed)
if(dtr.Vx3ID[ed] == par.Vx3ID[ep]) dtrEnd = ed;
2642 if(dtrEnd > 1)
continue;
2644 dtrEnd = 1 - dtrEnd;
2646 if(dtr.Vx3ID[dtrEnd] == 0)
continue;
2648 auto& vx3 = tjs.
vtx3[dtr.Vx3ID[dtrEnd] - 1];
2651 if(vx3TjList.empty())
continue;
2655 for(
auto tjid : dtrTjlist) pardtr.push_back(std::make_pair(dtr.ID, tjid));
2663 if(pfp.
ID <
int(tjs.
pfps.size()))
return false;
2666 if(pfp.
TjIDs.empty())
return false;
2667 if(pfp.
PDGCode != 1111 && pfp.
Tp3s.size() < 2)
return false;
2670 if(pfp.
ID != (
int)tjs.
pfps.size() + 1) pfp.
ID = tjs.
pfps.size() + 1;
2672 for(
auto tjid : pfp.
TjIDs) {
2673 auto& tj = tjs.
allTraj[tjid - 1];
2674 if(tj.AlgMod[
kMat3D])
return false;
2675 tj.AlgMod[
kMat3D] =
true;
2678 if(!pfp.
Tp3s.empty()) {
2681 std::vector<int> tjids;
2683 std::vector<short> firstIpt;
2684 std::vector<short> lastIpt;
2685 for(
auto& Tp3 : pfp.
Tp3s) {
2686 for(
auto& tj2pt : Tp3.Tj2Pts) {
2687 int tjid = tj2pt.id;
2689 unsigned short ii = 0;
2690 for(ii = 0; ii < tjids.size(); ++ii)
if(tjid == tjids[ii])
break;
2691 if(ii < tjids.size()) {
2693 lastIpt[ii] = tj2pt.ipt;
2696 tjids.push_back(tjid);
2697 firstIpt.push_back((
short)tj2pt.ipt);
2698 lastIpt.push_back((
short)tj2pt.ipt);
2702 for(
unsigned short ii = 0; ii < tjids.size(); ++ii) {
2704 if(std::find(pfp.
TjIDs.begin(), pfp.
TjIDs.end(), tjids[ii]) == pfp.
TjIDs.end())
continue;
2705 auto& tj = tjs.
allTraj[tjids[ii] - 1];
2706 if(lastIpt[ii] < firstIpt[ii]) {
2718 if(pfp.
NeedsUpdate) std::cout<<
"StorePFP: stored P"<<pfp.
ID<<
" but NeedsUpdate is true...\n";
2720 tjs.
pfps.push_back(pfp);
2732 double local[3] = {0.,0.,0.};
2733 double world[3] = {0.,0.,0.};
2735 unsigned int cstat = tpcid.Cryostat;
2736 unsigned int tpc = tpcid.TPC;
2742 if(pos[2] < world[2]-tjs.
geom->
DetLength(tpc,cstat)/2 + abit)
continue;
2743 if(pos[2] > world[2]+tjs.
geom->
DetLength(tpc,cstat)/2 - abit)
continue;
2756 if(pos1[0] == pos2[0] && pos1[1] == pos2[1] && pos1[2] == pos2[2])
return;
2759 double costh =
DotProd(dir1, ptDir);
2760 if(costh > 1)
return;
2761 double sep =
PosSep(pos1, pos2);
2762 if(sep < 1
E-6)
return;
2763 alongTrans[0] = costh * sep;
2764 double sinth = sqrt(1 - costh * costh);
2765 alongTrans[1] = sinth * sep;
2773 for(
unsigned short xyz = 0; xyz < 3; ++xyz) {
2774 p1End[xyz] = p1[xyz] + 10 * p1Dir[xyz];
2775 p2End[xyz] = p2[xyz] + 10 * p2Dir[xyz];
2793 double d1343,d4321,d1321,d4343,d2121;
2797 p13[0] = p1[0] - p3[0];
2798 p13[1] = p1[1] - p3[1];
2799 p13[2] = p1[2] - p3[2];
2800 p43[0] = p4[0] - p3[0];
2801 p43[1] = p4[1] - p3[1];
2802 p43[2] = p4[2] - p3[2];
2803 if (std::abs(p43[0]) < EPS && std::abs(p43[1]) < EPS && std::abs(p43[2]) < EPS)
return(
false);
2804 p21[0] = p2[0] - p1[0];
2805 p21[1] = p2[1] - p1[1];
2806 p21[2] = p2[2] - p1[2];
2807 if (std::abs(p21[0]) < EPS && std::abs(p21[1]) < EPS && std::abs(p21[2]) < EPS)
return(
false);
2809 d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2];
2810 d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2];
2811 d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2];
2812 d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2];
2813 d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2];
2815 denom = d2121 * d4343 - d4321 * d4321;
2816 if (std::abs(denom) < EPS)
return(
false);
2817 numer = d1343 * d4321 - d1321 * d4343;
2819 double mua = numer / denom;
2820 double mub = (d1343 + d4321 * mua) / d4343;
2822 intersect[0] = p1[0] + mua * p21[0];
2823 intersect[1] = p1[1] + mua * p21[1];
2824 intersect[2] = p1[2] + mua * p21[2];
2826 pb[0] = p3[0] + mub * p43[0];
2827 pb[1] = p3[1] + mub * p43[1];
2828 pb[2] = p3[2] + mub * p43[2];
2829 doca =
PosSep(intersect, pb);
2831 for(
unsigned short xyz = 0; xyz < 3; ++xyz) intersect[xyz] += pb[xyz];
2832 for(
unsigned short xyz = 0; xyz < 3; ++xyz) intersect[xyz] /= 2;
2839 std::swap(pfp.
XYZ[0], pfp.
XYZ[1]);
2840 std::swap(pfp.
Dir[0], pfp.
Dir[1]);
2841 for(
unsigned short xyz = 0; xyz < 3; ++xyz) {
2842 pfp.
Dir[0][xyz] *= -1;
2843 pfp.
Dir[1][xyz] *= -1;
2846 std::swap(pfp.
dEdx[0], pfp.
dEdx[1]);
2850 std::reverse(pfp.
Tp3s.begin(), pfp.
Tp3s.end());
2851 for(
auto& tp3 : pfp.
Tp3s) {
2852 for(
unsigned short xyz = 0; xyz < 3; ++xyz) {
2866 if(tpcid != tjs.
TPCID)
return -1;
2867 float sep =
PosSep(pos1, pos2);
2868 if(sep == 0)
return -1;
2869 unsigned short nstep = sep / tjs.
WirePitch;
2874 for(
unsigned short step = 0; step < nstep; ++step) {
2875 for(
unsigned short xyz = 0; xyz < 3; ++xyz) pos1[xyz] += tjs.
WirePitch *
dir[xyz];
2876 for(
unsigned short plane = 0; plane < tjs.
NumPlanes; ++plane) {
2884 if(cnt == 0)
return -1;
2894 if(pfp.
ID == 0)
return 0;
2895 if(pfp.
TjIDs.empty())
return 0;
2896 if(end < 0 || end > 1)
return 0;
2904 for(
unsigned short plane = 0; plane < tjs.
NumPlanes; ++plane) {
2906 std::vector<int> tjids(1);
2907 for(
auto tjid : pfp.
TjIDs) {
2908 auto& tj = tjs.
allTraj[tjid - 1];
2909 if(tj.CTP != inCTP)
continue;
2914 if(pos[0] < -0.4)
continue;
2916 unsigned int wire = std::nearbyint(pos[0]);
2917 if(wire > tjs.
NumWires[plane])
continue;
2918 if(tjs.
WireHitRange[plane][wire].first == -1)
continue;
2921 if(cf < lo) lo = cf;
2922 if(cf > hi) hi = cf;
2927 if(cnt == 0)
return 0;
2928 if(cnt > 1 && lo < 0.3 && hi > 0.8) {
2939 if(pfp.
ID == 0)
return 0;
2948 myprt<<someText<<
" Pos"<<std::fixed<<std::setprecision(1);
2949 myprt<<std::setw(6)<<tp3.
Pos[0]<<std::setw(6)<<tp3.
Pos[1]<<std::setw(6)<<tp3.
Pos[2];
2950 myprt<<
" Dir"<<std::fixed<<std::setprecision(3);
2951 myprt<<std::setw(7)<<tp3.
Dir[0]<<std::setw(7)<<tp3.
Dir[1]<<std::setw(7)<<tp3.
Dir[2];
2953 for(
auto tj2pt : tp3.
Tj2Pts) {
2954 auto& tj = tjs.
allTraj[tj2pt.id - 1];
2955 auto& tp = tj.Pts[tj2pt.ipt];
2956 myprt<<
" "<<tj.ID<<
"_"<<
PrintPos(tjs, tp);
2963 if(pfp.
Tp3s.empty())
return;
2967 myprt<<someText<<
" pfp P"<<pfp.
ID<<
"\n";
2968 myprt<<someText<<
" ipt ________Pos________ Path ________Dir_______ along trans dang Kink Tj_ipt \n";
2971 myprt<<someText<<
" ";
2972 myprt<<std::fixed<<std::setprecision(1);
2973 myprt<<std::setw(7)<<pfp.
XYZ[0][0]<<std::setw(7)<<pfp.
XYZ[0][1]<<std::setw(7)<<pfp.
XYZ[0][2];
2975 myprt<<std::fixed<<std::setprecision(2);
2976 myprt<<std::setw(7)<<pfp.
Dir[0][0]<<std::setw(7)<<pfp.
Dir[0][1]<<std::setw(7)<<pfp.
Dir[0][2];
2977 myprt<<
" <--- pfp.XYZ[0] \n";
2979 unsigned short fromPt = 0;
2980 unsigned short toPt = pfp.
Tp3s.size() - 1;
2981 if(printPts >= 0) fromPt = toPt;
2983 for(
unsigned short ipt = fromPt; ipt <= toPt; ++ipt) {
2984 auto tp3 = pfp.
Tp3s[ipt];
2985 myprt<<someText<<std::setw(4)<<ipt;
2986 myprt<<std::fixed<<std::setprecision(1);
2987 myprt<<std::setw(7)<<tp3.Pos[0]<<std::setw(7)<<tp3.Pos[1]<<std::setw(7)<<tp3.Pos[2];
2988 myprt<<std::setprecision(1)<<std::setw(5)<<
PosSep(tp3.Pos, pfp.
XYZ[0]);
2989 myprt<<std::setprecision(2)<<std::setw(7)<<tp3.Dir[0]<<std::setw(7)<<tp3.Dir[1]<<std::setw(7)<<tp3.Dir[2];
2990 myprt<<std::setprecision(1)<<std::setw(6)<<tp3.AlongTrans[0];
2991 myprt<<std::setprecision(1)<<std::setw(6)<<tp3.AlongTrans[1];
2992 myprt<<std::setprecision(2)<<std::setw(7)<<
DeltaAngle(prevDir, tp3.Dir);
2997 myprt<<std::setprecision(2)<<std::setw(7)<<
KinkAngle(tjs, pfp.
Tp3s, ipt, sep);
2998 for(
auto tj2pt : tp3.Tj2Pts) {
2999 auto& tj = tjs.
allTraj[tj2pt.id - 1];
3000 auto& tp = tj.Pts[tj2pt.ipt];
3001 myprt<<
" "<<tj.ID<<
"_"<<tj2pt.ipt<<
"_"<<
PrintPos(tjs, tp);
3006 myprt<<someText<<
" ";
3007 myprt<<std::fixed<<std::setprecision(1);
3008 myprt<<std::setw(7)<<pfp.
XYZ[1][0]<<std::setw(7)<<pfp.
XYZ[1][1]<<std::setw(7)<<pfp.
XYZ[1][2];
3010 myprt<<std::fixed<<std::setprecision(2);
3011 myprt<<std::setw(7)<<pfp.
Dir[1][0]<<std::setw(7)<<pfp.
Dir[1][1]<<std::setw(7)<<pfp.
Dir[1][2];
3012 myprt<<
" <--- pfp.XYZ[1]. Length "<<
PosSep(pfp.
XYZ[0], pfp.
XYZ[1])<<
"\n";
TPCID()=default
Default constructor: an invalid TPC ID.
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
bool SetStart(TjStuff &tjs, PFPStruct &pfp, bool prt)
void PrintTp3s(std::string someText, const TjStuff &tjs, const PFPStruct &pfp, short printPts)
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)
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
unsigned short WiresSkippedInCTP(TjStuff &tjs, std::vector< int > &tjids, CTP_t inCTP)
Point2_t dEdx
dE/dx for 3D matched trajectories
std::array< std::vector< float >, 2 > dEdxErr
float TPHitsRMSTime(TjStuff &tjs, TrajPoint &tp, HitStatus_t hitRequest)
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.
struct of temporary 2D vertices (end points)
void FindMissedTjsInTp3s(TjStuff &tjs, PFPStruct &pfp, std::vector< int > &missTjs, std::vector< float > &missFrac)
bool AddMissedTj(TjStuff &tjs, PFPStruct &pfp, unsigned short itj, bool looseCuts, bool prt)
CTP_t CTP
Cryostat, TPC, Plane code.
bool valIncreasings(SortEntry c1, SortEntry c2)
void FollowTp3s(TjStuff &tjs, PFPStruct &pfp, bool prt)
std::array< double, 3 > Point3_t
double dEdx_AREA(art::Ptr< recob::Hit > hit, double pitch, double T0=0) const
std::bitset< 64 > AlgMod
Bit set if algorithm AlgBit_t modifed the trajectory.
unsigned int Nplanes() const
Number of planes in this tpc.
bool AnalyzePFP(TjStuff &tjs, PFPStruct &pfp, bool prt)
float ChgFracBetween(TjStuff &tjs, Point3_t pos1, Point3_t pos2, geo::TPCID tpcid)
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)
std::vector< float > TjCompleteness
The data type to uniquely identify a Plane.
Geometry information for a single TPC.
std::vector< PFPStruct > pfps
matched to a high-score 3D vertex
bool LineLineIntersect(Point3_t p1, Point3_t p2, Point3_t p3, Point3_t p4, Point3_t &intersect, float &doca)
bool AttachAnyTrajToVertex(TjStuff &tjs, unsigned short ivx, bool prt)
CryostatID_t Cryostat
Index of cryostat.
bool DefinePFP(std::string inFcnLabel, TjStuff &tjs, PFPStruct &pfp, bool prt)
void ReversePFP(TjStuff &tjs, PFPStruct &pfp)
std::vector< Tj2Pt > Tj2Pts
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
a general purpose flag bit used in 3D matching
bool MakeTp3(TjStuff &tjs, const TrajPoint &itp, const TrajPoint &jtp, TrajPoint3 &tp3, bool findDirection)
bool SharesHighScoreVx(TjStuff &tjs, const PFPStruct &pfp, const Trajectory &tj)
std::array< std::bitset< 8 >, 2 > StopFlag
std::array< int, 2 > Vx3ID
void UpdateTp3s(TjStuff &tjs, PFPStruct &pfp, int oldTj, int newTj)
bool CompatibleMerge(TjStuff &tjs, std::vector< int > &tjIDs, bool prt)
std::array< double, 2 > Dir
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
std::vector< 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.
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
unsigned short FarEnd(const TjStuff &tjs, const PFPStruct &pfp, const Point3_t &pos)
bool SignalAtTp(TjStuff &tjs, const TrajPoint &tp)
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
calo::CalorimetryAlg * caloAlg
void FindPFParticles(TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
double ThetaZ() const
Angle of the wires from positive z axis; .
void ReverseTraj(TjStuff &tjs, Trajectory &tj)
bool IsShowerLike(const TjStuff &tjs, const std::vector< int > TjIDs)
bool SplitTraj(TjStuff &tjs, unsigned short itj, float XPos, bool makeVx2, bool prt)
struct of temporary 3D vertices
unsigned int EventsProcessed
geo::Length_t DetHalfHeight(geo::TPCID const &tpcid) const
Returns the half height of the active volume of the specified TPC.
bool MakeVertexObsolete(TjStuff &tjs, VtxStore &vx2, bool forceKill)
std::array< float, 2 > Point2_t
int PDGCodeVote(TjStuff &tjs, std::vector< int > &tjIDs, bool prt)
std::array< Point3_t, 2 > XYZ
const geo::GeometryCore * geom
void DefinePFPParentsTestBeam(TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
void Match3DVtxTjs(TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
CTP_t CTP
Cryostat, TPC, Plane code.
bool FitTp3(TjStuff &tjs, TrajPoint3 &tp3, const std::vector< Tj2Pt > &tj2pts)
std::array< Vector3_t, 2 > DirErr
std::vector< VtxStore > vtx
2D vertices
void UpdateMatchStructs(TjStuff &tjs, int oldTj, int newTj)
std::vector< TrajPoint > Pts
Trajectory points.
TrajPoint MakeBareTP(TjStuff &tjs, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
std::array< Vector3_t, 2 > Dir
float MaxTjLen(TjStuff const &tjs, std::vector< int > &tjIDs)
bool valDecreasings(SortEntry c1, SortEntry c2)
std::vector< Trajectory > allTraj
vector of all trajectories in each plane
void PFPVertexCheck(TjStuff &tjs)
std::bitset< 64 > UseAlg
Allow user to mask off specific algorithms.
std::array< unsigned short, 2 > EndPt
First and last point in the trajectory that has charge.
std::vector< float > MaxPos0
geo::Length_t DetLength(geo::TPCID const &tpcid) const
Returns the length of the active volume of the specified TPC.
void FillmAllTraj(TjStuff &tjs, const geo::TPCID &tpcid)
void fill(const art::PtrVector< recob::Hit > &hits, int only_plane)
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
double KinkAngle(const TjStuff &tjs, const std::vector< TrajPoint3 > &tp3s, unsigned short atPt, double sep)
std::vector< MatchStruct > matchVec
3D matching vector
bool TestBeam
Expect tracks entering from the front face. Don't create neutrino PFParticles.
float UnitsPerTick
scale factor from Tick to WSE equivalent units
bool PointDirIntersect(Point3_t p1, Vector3_t p1Dir, Point3_t p2, Vector3_t p2Dir, Point3_t &intersect, float &doca)
The data type to uniquely identify a TPC.
PlaneID_t Plane
Index of the plane within its TPC.
float EffPur
Efficiency * Purity.
bool PFPVxTjOK(TjStuff &tjs, PFPStruct &pfp, bool prt)
bool SetMag(Vector3_t &v1, double mag)
std::vector< int > GetVtxTjIDs(const TjStuff &tjs, const VtxStore &vx2)
std::array< unsigned short, 2 > VtxID
ID of 2D vertex.
short MCSMom(const TjStuff &tjs, const std::vector< int > &tjIDs)
float ChgFracNearEnd(TjStuff &tjs, PFPStruct &pfp, unsigned short end)
std::vector< Vtx3Store > vtx3
3D vertices
float ChgFracNearPos(TjStuff &tjs, const Point2_t &pos, const std::vector< int > &tjIDs)
void PrintTp3(std::string someText, const TjStuff &tjs, const TrajPoint3 &tp3)
std::array< int, 3 > Vx2ID
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
std::vector< unsigned short > FindKinks(const TjStuff &tjs, PFPStruct &pfp, double sep, bool prt)
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
std::vector< std::vector< std::pair< int, int > > > WireHitRange
std::vector< TCHit > fHits
PFPStruct CreatePFP(const TjStuff &tjs, const geo::TPCID &tpcid)
short StepDir
-1 = going US (-> small wire#), 1 = going DS (-> large wire#)
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< float > Match3DCuts
3D matching cuts
bool Split3DKink(TjStuff &tjs, PFPStruct &pfp, double sep, bool prt)
unsigned short MatchVecIndex
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
void SetEndPoints(TjStuff &tjs, Trajectory &tj)
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
unsigned short NumPtsWithCharge(const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires)
std::array< double, 3 > Vector3_t
float LengthInCTP(TjStuff &tjs, std::vector< int > &tjids, CTP_t inCTP)
std::array< std::vector< float >, 2 > dEdx
unsigned short GetPFPIndex(const TjStuff &tjs, int tjID)
std::vector< T > SetDifference(const std::vector< T > &set1, const std::vector< T > &set2)
std::vector< Tj2Pt > mallTraj
vector of trajectory points ordered by increasing X
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void MakeTrajectoryObsolete(TjStuff &tjs, unsigned int itj)
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
void PrintPFP(std::string someText, const TjStuff &tjs, const PFPStruct &pfp, bool printHeader)
int SSID
ID of a 2D shower struct that this tj is in.
void FindXMatches(TjStuff &tjs, unsigned short numPlanes, short maxScore, std::vector< MatchStruct > &matVec, bool prt)
void SetPDGCode(TjStuff &tjs, unsigned short itj)
bool InsideTPC(const TjStuff &tjs, Point3_t &pos, geo::TPCID &inTPCID)
bool StoreVertex(TjStuff &tjs, VtxStore &vx)
TPCID_t TPC
Index of the TPC within its cryostat.
bool StoreTraj(TjStuff &tjs, Trajectory &tj)
void FindCompleteness(TjStuff &tjs, PFPStruct &pfp, bool doFit, bool fillTp3s, bool prt)
bool MergePFPTjs(TjStuff &tjs, PFPStruct &pfp, bool prt)
void DefinePFPParents(TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
bool StorePFP(TjStuff &tjs, PFPStruct &pfp)
bool DebugMode
print additional info when in debug mode
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
std::vector< unsigned int > NumWires
bool FitTp3s(TjStuff &tjs, const std::vector< TrajPoint3 > &tp3s, Point3_t &pos, Vector3_t &dir, float &rCorr)
void FilldEdx(TjStuff &tjs, PFPStruct &pfp)
bool HasWire(geo::WireID const &wireid) const
Returns whether we have the specified wire.
const detinfo::DetectorProperties * detprop