5 #include "TDecompSVD.h" 45 if (
slices.size() < 2)
return;
57 bool printHeader =
true;
58 for (
size_t isl = 0; isl <
slices.size(); ++isl) {
61 if (slc.pfps.empty())
continue;
62 for (
auto& pfp : slc.pfps)
63 PrintP(fcnLabel, myprt, pfp, printHeader);
68 std::vector<std::vector<int>> stLists;
69 for (std::size_t sl1 = 0; sl1 <
slices.size() - 1; ++sl1) {
71 for (std::size_t sl2 = sl1 + 1; sl2 <
slices.size(); ++sl2) {
74 if (slc1.ID != slc2.ID)
continue;
75 for (
auto& p1 : slc1.pfps) {
76 if (p1.ID <= 0)
continue;
78 if (p1.PDGCode == 1111)
continue;
79 for (
auto& p2 : slc2.pfps) {
80 if (p2.ID <= 0)
continue;
82 if (p2.PDGCode == 1111)
continue;
86 for (
unsigned short e1 = 0; e1 < 2; ++e1) {
89 if (
InsideFV(slc1, p1, e1))
continue;
91 for (
unsigned short e2 = 0; e2 < 2; ++e2) {
94 if (
InsideFV(slc2, p2, e2))
continue;
96 float sep =
PosSep2(pos1, pos2);
97 if (sep > maxSep2)
continue;
99 if (cth < maxCth)
continue;
105 if (!gotit)
continue;
108 myprt <<
"Stitch slice " << slc1.ID <<
" P" << p1.UID <<
" TPC " << p1.TPCID.TPC;
109 myprt <<
" and P" << p2.UID <<
" TPC " << p2.TPCID.TPC;
110 myprt <<
" sep " << sqrt(maxSep2) <<
" maxCth " << maxCth;
114 for (
auto&
pm : stLists) {
115 bool p1InList = (std::find(
pm.begin(),
pm.end(), p1.UID) !=
pm.end());
116 bool p2InList = (std::find(
pm.begin(),
pm.end(), p2.UID) !=
pm.end());
117 if (p1InList || p2InList) {
118 if (p1InList)
pm.push_back(p2.UID);
119 if (p2InList)
pm.push_back(p1.UID);
125 std::vector<int>
tmp(2);
128 stLists.push_back(tmp);
134 if (stLists.empty())
return;
136 for (
auto& stl : stLists) {
139 std::pair<unsigned short, unsigned short> minZIndx;
140 unsigned short minZEnd = 2;
141 for (
auto puid : stl) {
143 if (slcIndex.first == USHRT_MAX)
continue;
144 auto& pfp =
slices[slcIndex.first].pfps[slcIndex.second];
145 for (
unsigned short end = 0;
end < 2; ++
end) {
154 if (minZEnd > 1)
continue;
156 auto& pfp =
slices[minZIndx.first].pfps[minZIndx.second];
159 for (
auto puid : stl) {
160 if (puid == pfp.UID)
continue;
162 if (sIndx.first == USHRT_MAX)
continue;
163 auto& opfp =
slices[sIndx.first].pfps[sIndx.second];
165 pfp.TjUIDs.insert(pfp.TjUIDs.end(), opfp.TjUIDs.begin(), opfp.TjUIDs.end());
168 if (opfp.ParentUID > 0) {
170 if (pSlcIndx.first <
slices.size()) {
171 auto& parpfp =
slices[pSlcIndx.first].pfps[pSlcIndx.second];
172 std::replace(parpfp.DtrUIDs.begin(), parpfp.DtrUIDs.begin(), opfp.UID, pfp.UID);
175 for (
auto dtruid : opfp.DtrUIDs) {
177 if (dSlcIndx.first <
slices.size()) {
178 auto& dtrpfp =
slices[dSlcIndx.first].pfps[dSlcIndx.second];
179 dtrpfp.ParentUID = pfp.UID;
201 for (
auto& tj : slc.
tjs) {
202 for (
auto& tp : tj.Pts)
209 std::vector<MatchStruct> matVec;
216 unsigned short maxNit = 2;
217 if (slc.
nPlanes == 2) maxNit = 1;
221 for (
unsigned short nit = 0; nit < maxNit; ++nit) {
223 if (slc.
nPlanes == 3 && nit == 0) {
231 if (matVec.empty())
continue;
234 myprt <<
"nit " << nit <<
" MVI Count Tjs\n";
235 for (
unsigned int indx = 0; indx < matVec.size(); ++indx) {
236 auto&
ms = matVec[indx];
238 for (
auto tid :
ms.TjIDs)
239 myprt <<
" T" << tid;
242 for (
auto tid :
ms.TjIDs) {
243 auto& tj = slc.
tjs[tid - 1];
246 float frac =
ms.Count / tpCnt;
256 for (
auto& pfp : slc.
pfps)
258 PrintTP3Ds(clockData, detProp,
"FPFP", slc, pfp, -1);
270 std::vector<MatchStruct> matVec,
271 unsigned short matVec_Iter)
274 if (matVec.empty())
return;
279 for (std::size_t indx = 0; indx < matVec.size(); ++indx) {
282 if (foundMVI) prt =
true;
283 auto&
ms = matVec[indx];
285 std::cout <<
"found MVI " << indx <<
" in MakePFParticles ms.Count = " <<
ms.Count <<
"\n";
288 if (
ms.Count == 0)
continue;
291 for (std::size_t itj = 0; itj <
ms.TjIDs.size(); ++itj) {
292 auto& tj = slc.
tjs[
ms.TjIDs[itj] - 1];
293 for (
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt)
294 if (tj.Pts[ipt].InPFP == 0) ++npts;
297 std::vector<PFPStruct> pfpVec(1);
300 pfpVec[0].TjIDs =
ms.TjIDs;
301 pfpVec[0].MVI = indx;
304 if (!
MakeTP3Ds(detProp, slc, pfpVec[0], foundMVI)) {
305 if (foundMVI)
mf::LogVerbatim(
"TC") <<
" MakeTP3Ds failed. Too many points already used ";
309 if (!
FitSection(clockData, detProp, slc, pfpVec[0], 0))
continue;
310 if (pfpVec[0].SectionFits[0].ChiDOF > 500 && !pfpVec[0].Flags[
kSmallAngle]) {
313 << pfpVec[0].SectionFits[0].ChiDOF <<
"\n";
314 Recover(clockData, detProp, slc, pfpVec[0], foundMVI);
322 npts = pfpVec[0].TP3Ds.size();
323 pfpVec[0].AlgMod[
kJunk3D] = (npts < 20 &&
MCSMom(slc, pfpVec[0].TjIDs) < 50) || (npts < 10);
325 auto& pfp = pfpVec[0];
327 myprt <<
" indx " << matVec_Iter <<
"/" << indx <<
" Count " <<
std::setw(5)
329 myprt <<
" P" << pfpVec[0].ID;
331 for (
auto& tjid : pfp.TjIDs)
332 myprt <<
" T" << tjid;
333 myprt <<
" projInPlane";
334 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
335 CTP_t inCTP =
EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
336 auto tp =
MakeBareTP(detProp, slc, pfp.SectionFits[0].Pos, pfp.SectionFits[0].Dir, inCTP);
339 myprt <<
" maxTjLen " << (
int)
MaxTjLen(slc, pfp.TjIDs);
340 myprt <<
" MCSMom " <<
MCSMom(slc, pfp.TjIDs);
341 myprt <<
" PDGCodeVote " <<
PDGCodeVote(clockData, detProp, slc, pfp);
342 myprt <<
" nTP3Ds " << pfp.TP3Ds.size();
343 myprt <<
" Reco3DRange " 346 if (foundMVI) {
PrintTP3Ds(clockData, detProp,
"FF", slc, pfpVec[0], -1); }
347 for (
unsigned short ip = 0; ip < pfpVec.size(); ++ip) {
348 auto& pfp = pfpVec[ip];
351 for (
unsigned short end = 0;
end < 2; ++
end) {
353 pfp.EndFlag[
end].reset();
359 pfp.EndFlag[0][
kAtKink] =
true;
362 vx3.
X = pfp.TP3Ds[0].Pos[0];
363 vx3.
Y = pfp.TP3Ds[0].Pos[1];
364 vx3.
Z = pfp.TP3Ds[0].Pos[2];
373 slc.
vtx3s.push_back(vx3);
374 pfp.Vx3ID[0] = vx3.
ID;
375 auto& prevPFP = slc.
pfps[slc.
pfps.size() - 1];
376 prevPFP.Vx3ID[1] = vx3.
ID;
381 if (pfp.TjIDs.size() == 2 && slc.
nPlanes == 3 && pfp.TP3Ds.size() > 20 &&
396 if (!
ReSection(clockData, detProp, slc, pfp, foundMVI))
continue;
398 if (foundMVI) {
PrintTP3Ds(clockData, detProp,
"RS", slc, pfp, -1); }
403 FillGaps3D(clockData, detProp, slc, pfp, foundMVI);
409 for (
auto& tp3d : pfp.TP3Ds) {
411 auto& tp = slc.
tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
414 FilldEdx(clockData, detProp, slc, pfp);
415 pfp.PDGCode =
PDGCodeVote(clockData, detProp, slc, pfp);
417 PrintTP3Ds(clockData, detProp,
"STORE", slc, pfp, -1);
435 if (pfp.
TjIDs.empty())
return false;
436 if (pfp.
TP3Ds.empty())
return false;
437 if (pfp.
ID <= 0)
return false;
440 std::vector<std::pair<int, float>> tjTPCnt;
441 for (
auto& tp3d : pfp.
TP3Ds) {
443 if (tp3d.TjID <= 0)
return false;
445 auto& tp = slc.
tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
446 if (tp.InPFP > 0 && tp.InPFP != pfp.
ID)
return false;
448 unsigned short indx = 0;
449 for (indx = 0; indx < tjTPCnt.size(); ++indx)
450 if (tjTPCnt[indx].first == tp3d.TjID)
break;
451 if (indx == tjTPCnt.size()) tjTPCnt.push_back(std::make_pair(tp3d.TjID, 0));
452 ++tjTPCnt[indx].second;
457 std::vector<int> nTjIDs;
458 for (
auto& tjtpcnt : tjTPCnt) {
459 auto& tj = slc.
tjs[tjtpcnt.first - 1];
461 if (tjtpcnt.second > 0.8 * npwc) nTjIDs.push_back(tjtpcnt.first);
463 if (prt) {
mf::LogVerbatim(
"TC") <<
"RTPs3D: P" << pfp.
ID <<
" nTjIDs " << nTjIDs.size(); }
465 if (nTjIDs.size() < 2) {
return false; }
485 std::vector<int> TinP;
486 for (
auto& pfp : slc.
pfps) {
487 if (pfp.ID <= 0)
continue;
489 for (std::size_t ipt = 0; ipt < pfp.TP3Ds.size(); ++ipt) {
490 auto& tp3d = pfp.TP3Ds[ipt];
491 if (tp3d.TjID <= 0)
continue;
492 if (std::find(TinP.begin(), TinP.end(), tp3d.TjID) == TinP.end()) TinP.push_back(tp3d.TjID);
493 auto& tp = slc.
tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
520 std::vector<int> killme;
521 for (
auto& pfp : slc.
pfps) {
522 if (pfp.ID <= 0)
continue;
523 for (
auto& tp3d : pfp.TP3Ds) {
524 if (tp3d.TjID <= 0)
continue;
526 if (std::find(killme.begin(), killme.end(), tp3d.TjID) == killme.end())
527 killme.push_back(tp3d.TjID);
533 for (
auto tid : killme)
538 std::vector<Trajectory> ptjs(slc.
nPlanes);
540 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
541 ptjs[plane].Pass = 0;
544 ptjs[plane].StepDir = 0;
548 ptjs[plane].AlgMod[
kMat3D] =
true;
552 for (
auto& pfp : slc.
pfps) {
553 if (pfp.ID <= 0)
continue;
555 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
556 ptjs[plane].Pts.clear();
564 for (
auto& tp3d : pfp.TP3Ds) {
565 if (tp3d.TjID <= 0)
continue;
568 auto tp = slc.
tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
569 if (tp.InPFP > 0 && tp.InPFP != pfp.ID)
continue;
575 ptjs[plane].Pts.push_back(tp);
579 std::vector<int> tids(ptjs.size(), 0);
580 for (
unsigned short plane = 0; plane < ptjs.size(); ++plane) {
581 auto& tj = ptjs[plane];
582 if (tj.Pts.size() < 2)
continue;
583 tj.PDGCode = pfp.PDGCode;
584 tj.MCSMom =
MCSMom(slc, tj);
587 auto& newTj = slc.
tjs.back();
588 pfp.TjIDs.push_back(newTj.ID);
589 tids[plane] = newTj.ID;
592 for(
unsigned short end = 0;
end < 2; ++
end) {
593 if(pfp.Vx3ID[
end] <= 0)
continue;
594 auto& vx3 = slc.
vtx3s[pfp.Vx3ID[
end] - 1];
595 for(
unsigned short plane = 0; plane < ptjs.size(); ++plane) {
596 if(tids[plane] == 0)
continue;
597 if(vx3.Vx2ID[plane] <= 0)
continue;
598 auto& vx2 = slc.
vtxs[vx3.Vx2ID[plane] - 1];
599 auto& tj = slc.
tjs[tids[plane] - 1];
600 auto tend =
CloseEnd(slc, tj, vx2.Pos);
601 tj.VtxID[tend] = vx2.ID;
602 if(prt)
mf::LogVerbatim(
"TC") <<
"MPFPTjs: 3V" << vx3.ID <<
" -> 2V" << vx2.ID
603 <<
" -> T" << tj.ID <<
"_" << tend <<
" in plane " << plane;
623 unsigned int maxWire = slc.
nWires[0];
624 for (
auto nw : slc.
nWires)
625 if (nw < maxWire) maxWire = nw;
627 unsigned int firstWire = maxWire / 2;
630 std::vector<std::pair<unsigned short, unsigned short>> pln1pln2;
631 for (
unsigned short pln1 = 0; pln1 < slc.
nPlanes - 1; ++pln1) {
632 for (
unsigned short pln2 = pln1 + 1; pln2 < slc.
nPlanes; ++pln2) {
633 auto p1p2 = std::make_pair(pln1, pln2);
634 if (std::find(pln1pln2.begin(), pln1pln2.end(), p1p2) != pln1pln2.end())
continue;
636 for (
unsigned int wire = firstWire; wire < maxWire; ++wire) {
655 tcwi.
dydw1 = (y10 - y00) / 10;
656 tcwi.
dzdw1 = (z10 - z00) / 10;
657 tcwi.
dydw2 = (y01 - y00) / 10;
658 tcwi.
dzdw2 = (z01 - z00) / 10;
678 if (pln1 == pln2)
return false;
686 if (wi.pln1 != pln1)
continue;
687 if (wi.pln2 != pln2)
continue;
689 double dw1 = wir1 - wi.wir1;
690 double dw2 = wir2 - wi.wir2;
691 y = (
float)(wi.y + dw1 * wi.dydw1 + dw2 * wi.dydw2);
692 z = (
float)(wi.z + dw1 * wi.dzdw1 + dw2 * wi.dzdw2);
706 std::vector<int> inTraj((*
evt.
allHits).size(), 0);
707 for (
auto& tch : slc.
slHits)
708 inTraj[tch.allHitsIndex] = tch.InTraj;
711 std::array<int, 3> tIDs;
713 std::vector<std::array<int, 3>> mtIDs;
715 std::vector<unsigned short> mCnt;
717 unsigned short maxCnt = USHRT_MAX;
720 std::vector<unsigned short> tMaxed;
725 if (sptHits.size() != 3)
continue;
727 if (!
SptInTPC(sptHits, tpc))
continue;
728 unsigned short cnt = 0;
729 for (
unsigned short plane = 0; plane < 3; ++plane) {
730 unsigned int iht = sptHits[plane];
731 if (iht == UINT_MAX)
continue;
732 if (inTraj[iht] <= 0)
continue;
733 tIDs[plane] = inTraj[iht];
736 if (cnt != 3)
continue;
738 unsigned short indx = 0;
739 for (indx = 0; indx < mtIDs.size(); ++indx)
740 if (tIDs == mtIDs[indx])
break;
741 if (indx == mtIDs.size()) {
743 mtIDs.push_back(tIDs);
747 if (mCnt[indx] == maxCnt) {
749 tMaxed.insert(tMaxed.end(), tIDs[0]);
750 tMaxed.insert(tMaxed.end(), tIDs[1]);
751 tMaxed.insert(tMaxed.end(), tIDs[2]);
757 std::vector<SortEntry> sortVec;
758 for (
unsigned short indx = 0; indx < mCnt.size(); ++indx) {
759 auto& tIDs = mtIDs[indx];
761 float minTPCnt = USHRT_MAX;
762 for (
auto tid : tIDs) {
763 auto& tj = slc.
tjs[tid - 1];
765 if (tpcnt < minTPCnt) minTPCnt = tpcnt;
767 float frac = (
float)mCnt[indx] / minTPCnt;
769 if (frac < 0.05)
continue;
773 sortVec.push_back(se);
775 if (sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(),
valsDecreasing);
777 matVec.resize(sortVec.size());
779 for (
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
780 unsigned short indx = sortVec[ii].index;
781 auto&
ms = matVec[ii];
782 ms.Count = mCnt[indx];
784 for (
unsigned short plane = 0; plane < 3; ++plane)
785 ms.TjIDs[plane] = mtIDs[indx][plane];
792 SptInTPC(
const std::array<unsigned int, 3>& sptHits,
unsigned int tpc)
797 unsigned int ahi = UINT_MAX;
798 for (
auto ii : sptHits)
799 if (ii != UINT_MAX) {
803 if (ahi >= (*
evt.
allHits).size())
return false;
806 if (
hit.WireID().TPC == tpc)
return true;
830 std::array<unsigned short, 3> tIDs;
832 std::vector<std::array<unsigned short, 3>> mtIDs;
834 std::vector<unsigned short> mCnt;
836 unsigned short maxCnt = USHRT_MAX;
839 std::vector<unsigned short> tMaxed;
841 for (std::size_t ipt = 0; ipt < slc.
mallTraj.size() - 1; ++ipt) {
844 if (std::find(tMaxed.begin(), tMaxed.end(), iTjPt.id) != tMaxed.end())
continue;
845 auto& itp = slc.
tjs[iTjPt.id - 1].Pts[iTjPt.ipt];
846 unsigned int iPlane = iTjPt.plane;
847 unsigned int iWire = std::nearbyint(itp.Pos[0]);
848 tIDs[iPlane] = iTjPt.id;
849 bool hitMaxCnt =
false;
850 for (std::size_t jpt = ipt + 1; jpt < slc.
mallTraj.size() - 1; ++jpt) {
853 if (jTjPt.plane == iTjPt.plane)
continue;
855 if (jTjPt.xlo > iTjPt.xhi)
continue;
857 if (jTjPt.xlo > iTjPt.xhi + xcut)
break;
859 if (std::find(tMaxed.begin(), tMaxed.end(), jTjPt.id) != tMaxed.end())
continue;
860 auto& jtp = slc.
tjs[jTjPt.id - 1].Pts[jTjPt.ipt];
861 unsigned short jPlane = jTjPt.plane;
862 unsigned int jWire = jtp.Pos[0];
865 tIDs[jPlane] = jTjPt.id;
866 for (std::size_t kpt = jpt + 1; kpt < slc.
mallTraj.size(); ++kpt) {
869 if (kTjPt.plane == iTjPt.plane || kTjPt.plane == jTjPt.plane)
continue;
870 if (kTjPt.xlo > iTjPt.xhi)
continue;
872 if (kTjPt.xlo > iTjPt.xhi + xcut)
break;
874 if (std::find(tMaxed.begin(), tMaxed.end(), kTjPt.id) != tMaxed.end())
continue;
875 auto& ktp = slc.
tjs[kTjPt.id - 1].Pts[kTjPt.ipt];
876 unsigned short kPlane = kTjPt.plane;
877 unsigned int kWire = ktp.Pos[0];
880 if (
std::abs(ijPos[0] - ikPos[0]) > yzcut)
continue;
881 if (
std::abs(ijPos[1] - ikPos[1]) > yzcut)
continue;
885 unsigned int indx = 0;
886 for (indx = 0; indx < mtIDs.size(); ++indx)
887 if (tIDs == mtIDs[indx])
break;
888 if (indx == mtIDs.size()) {
890 mtIDs.push_back(tIDs);
894 if (mCnt[indx] == maxCnt) {
896 tMaxed.insert(tMaxed.end(), tIDs[0]);
897 tMaxed.insert(tMaxed.end(), tIDs[1]);
898 tMaxed.insert(tMaxed.end(), tIDs[2]);
903 if (hitMaxCnt)
break;
907 if (mCnt.empty())
return;
909 std::vector<SortEntry> sortVec;
910 for (std::size_t indx = 0; indx < mCnt.size(); ++indx) {
911 auto& tIDs = mtIDs[indx];
914 for (
auto tid : tIDs) {
915 auto& tj = slc.
tjs[tid - 1];
918 float frac = mCnt[indx] / tpCnt;
921 if (frac < 0.05)
continue;
925 sortVec.push_back(se);
927 if (sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(),
valsDecreasing);
929 matVec.resize(sortVec.size());
931 for (std::size_t ii = 0; ii < sortVec.size(); ++ii) {
932 unsigned short indx = sortVec[ii].index;
933 auto&
ms = matVec[ii];
934 ms.Count = mCnt[indx];
936 for (
unsigned short plane = 0; plane < 3; ++plane)
937 ms.TjIDs[plane] = (
int)mtIDs[indx][plane];
957 std::array<unsigned short, 2> tIDs;
959 std::vector<std::array<unsigned short, 2>> mtIDs;
961 std::vector<unsigned short> mCnt;
963 unsigned short maxCnt = USHRT_MAX;
966 std::vector<unsigned short> tMaxed;
968 for (std::size_t ipt = 0; ipt < slc.
mallTraj.size() - 1; ++ipt) {
971 if (std::find(tMaxed.begin(), tMaxed.end(), iTjPt.id) != tMaxed.end())
continue;
972 auto& itp = slc.
tjs[iTjPt.id - 1].Pts[iTjPt.ipt];
973 unsigned short iPlane = iTjPt.plane;
974 unsigned int iWire = itp.Pos[0];
975 bool hitMaxCnt =
false;
976 for (std::size_t jpt = ipt + 1; jpt < slc.
mallTraj.size() - 1; ++jpt) {
979 if (jTjPt.plane == iTjPt.plane)
continue;
981 if (jTjPt.xlo > iTjPt.xhi)
continue;
983 if (jTjPt.xlo > iTjPt.xhi + xcut)
break;
985 if (std::find(tMaxed.begin(), tMaxed.end(), jTjPt.id) != tMaxed.end())
continue;
986 auto& jtp = slc.
tjs[jTjPt.id - 1].Pts[jTjPt.ipt];
987 unsigned short jPlane = jTjPt.plane;
988 unsigned int jWire = jtp.Pos[0];
990 ijPos[0] = itp.Pos[0];
992 iWire, jWire, iPlane, jPlane, cstat, tpc, ijPos[1], ijPos[2]))
997 if (tIDs[0] > tIDs[1])
std::swap(tIDs[0], tIDs[1]);
999 std::size_t indx = 0;
1000 for (indx = 0; indx < mtIDs.size(); ++indx)
1001 if (tIDs == mtIDs[indx])
break;
1002 if (indx == mtIDs.size()) {
1004 mtIDs.push_back(tIDs);
1008 if (mCnt[indx] == maxCnt) {
1010 tMaxed.insert(tMaxed.end(), tIDs[0]);
1011 tMaxed.insert(tMaxed.end(), tIDs[1]);
1015 if (hitMaxCnt)
break;
1019 if (mCnt.empty())
return;
1021 std::vector<SortEntry> sortVec;
1022 for (std::size_t indx = 0; indx < mCnt.size(); ++indx) {
1023 auto& tIDs = mtIDs[indx];
1026 for (
auto tid : tIDs) {
1027 auto& tj = slc.
tjs[tid - 1];
1030 float frac = mCnt[indx] / tpCnt;
1033 if (frac < 0.05)
continue;
1036 se.
val = mCnt[indx];
1037 sortVec.push_back(se);
1039 if (sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(),
valsDecreasing);
1041 matVec.resize(sortVec.size());
1043 for (std::size_t ii = 0; ii < sortVec.size(); ++ii) {
1044 unsigned short indx = sortVec[ii].index;
1045 auto&
ms = matVec[ii];
1046 ms.Count = mCnt[indx];
1048 for (
unsigned short plane = 0; plane < 2; ++plane)
1049 ms.TjIDs[plane] = (
int)mtIDs[indx][plane];
1068 for(
unsigned short sfi = 0; sfi < pfp.
SectionFits.size(); ++sfi) {
1070 if (!sf.NeedsUpdate)
continue;
1074 for(
unsigned short ipt = 0; ipt < pfp.
TP3Ds.size(); ++ipt) {
1075 auto& tp3d = pfp.
TP3Ds[ipt];
1076 if(tp3d.SFIndex < sfi)
continue;
1077 if(tp3d.SFIndex > sfi)
break;
1079 double delta = tp3d.Pos[0] - tp3d.TPX;
1080 sf.ChiDOF += delta * delta / tp3d.TPXErr2;
1085 sf.ChiDOF /= (
float)(sf.NPts - 4);
1087 sf.NeedsUpdate =
false;
1093 for (std::size_t sfi = 0; sfi < pfp.
SectionFits.size(); ++sfi) {
1095 if (!sf.NeedsUpdate)
continue;
1096 if (!
FitSection(clockData, detProp, slc, pfp, sfi))
return false;
1098 sf.NeedsUpdate =
false;
1102 for (
auto& tp3d : pfp.
TP3Ds) {
1126 if (pfp.
TP3Ds.size() < 12) {
1142 for (
auto& tp3d : pfp.
TP3Ds) {
1147 if (!
FitSection(clockData, detProp, slc, pfp, 0)) {
return false; }
1153 unsigned short min2DPts = 3;
1154 unsigned short fromPt = 0;
1156 for (
auto& tp3d : pfp.
TP3Ds)
1157 tp3d.SFIndex = USHRT_MAX;
1159 unsigned short nPtsToAdd = pfp.
TP3Ds.size() / 4;
1161 unsigned short nPts = nPtsToAdd;
1163 unsigned short nPtsMin =
Find3DRecoRange(slc, pfp, fromPt, min2DPts, 1) - fromPt + 1;
1164 if (nPtsMin >= pfp.
TP3Ds.size()) {
1169 if (nPts < nPtsMin) nPts = nPtsMin;
1171 if (pfp.
TP3Ds.size() > 100) {
1172 unsigned short nhalf = pfp.
TP3Ds.size() / 2;
1173 FitTP3Ds(detProp, slc, pfp, fromPt, nhalf, USHRT_MAX, chiDOF);
1176 bool lastSection =
false;
1177 for (
unsigned short sfIndex = 0; sfIndex < 20; ++sfIndex) {
1179 float chiDOFPrev = 0;
1181 for (
unsigned short nit = 0; nit < 10; ++nit) {
1183 unsigned short nPtsNext = nPts;
1184 if (!
FitTP3Ds(detProp, slc, pfp, fromPt, nPts, USHRT_MAX, chiDOF)) {
1185 nPtsNext += 1.5 * nPtsToAdd;
1187 else if (chiDOF < chiLo) {
1194 nPtsNext += nPtsToAdd;
1198 else if (chiDOF > chiHi) {
1207 short npnext = (short)nPts - nHiChi * 5;
1210 if (npnext > nPtsMin) nPtsNext = npnext;
1218 if (fromPt + nPtsNext >= pfp.
TP3Ds.size()) {
1219 nPtsNext = pfp.
TP3Ds.size() - fromPt;
1224 myprt <<
" RS: P" << pfp.
ID <<
" sfi/nit/npts " << sfIndex <<
"/" << nit <<
"/" << nPts;
1226 myprt <<
" fromPt " << fromPt;
1227 myprt <<
" nPtsNext " << nPtsNext;
1228 myprt <<
" nHiChi " << nHiChi;
1229 myprt <<
" lastSection? " << lastSection;
1231 if (nPtsNext == 0)
break;
1233 if (lastSection)
break;
1234 if (chiDOF == chiDOFPrev) {
1239 chiDOFPrev = chiDOF;
1242 unsigned short toPt = fromPt + nPts;
1243 if (toPt > pfp.
TP3Ds.size()) toPt = pfp.
TP3Ds.size();
1244 for (
unsigned short ipt = fromPt; ipt < toPt; ++ipt)
1245 pfp.
TP3Ds[ipt].SFIndex = sfIndex;
1250 unsigned short nextFromPt = fromPt + nPts;
1252 unsigned short nextToPtMin =
Find3DRecoRange(slc, pfp, nextFromPt, min2DPts, 1);
1253 if (nextToPtMin == USHRT_MAX) {
1257 for (std::size_t ipt = nextFromPt; ipt < pfp.
TP3Ds.size(); ++ipt)
1258 pfp.
TP3Ds[ipt].SFIndex = sfIndex;
1262 FitSection(clockData, detProp, slc, pfp, sfIndex);
1264 if (lastSection)
break;
1266 fromPt = fromPt + nPts;
1268 nPtsMin =
Find3DRecoRange(slc, pfp, fromPt, min2DPts, 1) - fromPt + 1;
1269 if (nPtsMin >= pfp.
TP3Ds.size())
break;
1276 unsigned short badSFI = pfp.
SectionFits.size() - 1;
1279 for (std::size_t ipt = pfp.
TP3Ds.size() - 1; ipt > 0; --ipt) {
1280 auto& tp3d = pfp.
TP3Ds[ipt];
1281 if (tp3d.SFIndex < badSFI)
break;
1288 for (std::size_t ipt = pfp.
TP3Ds.size() - 1; ipt > 0; --ipt) {
1289 auto& tp3d = pfp.
TP3Ds[ipt];
1296 Update(clockData, detProp, slc, pfp, prt);
1310 unsigned short fromPt,
1311 unsigned short toPt,
1312 unsigned short& nBadPts,
1313 unsigned short& firstBadPt)
1316 firstBadPt = USHRT_MAX;
1318 if (fromPt > pfp.
TP3Ds.size() - 1) {
1319 nBadPts = USHRT_MAX;
1322 if (toPt > pfp.
TP3Ds.size()) toPt = pfp.
TP3Ds.size();
1324 for (
unsigned short ipt = fromPt; ipt < toPt; ++ipt) {
1325 auto& tp3d = pfp.
TP3Ds[ipt];
1329 auto& tp = slc.
tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
1348 if (pfp.
TP3Ds.size() < 12)
return false;
1350 if (toPt > pfp.
TP3Ds.size())
return false;
1352 if (nextToPt > pfp.
TP3Ds.size())
return false;
1360 unsigned short fromPt,
1361 unsigned short min2DPts,
1367 if (fromPt > pfp.
TP3Ds.size() - 1)
return USHRT_MAX;
1368 if (pfp.
TP3Ds.size() < 2 * min2DPts)
return USHRT_MAX;
1369 if (dir == 0)
return USHRT_MAX;
1371 std::vector<unsigned short> cntInPln(slc.
nPlanes);
1372 for (std::size_t ii = 0; ii < pfp.
TP3Ds.size(); ++ii) {
1373 unsigned short ipt = fromPt + ii;
1374 if (dir < 0) ipt = fromPt - ii;
1375 if (ipt >= pfp.
TP3Ds.size())
break;
1376 auto& tp3d = pfp.
TP3Ds[ipt];
1380 unsigned short enufInPlane = 0;
1381 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane)
1382 if (cntInPln[plane] >= min2DPts) ++enufInPlane;
1383 if (enufInPlane > 1)
return ipt + 1;
1384 if (dir < 0 && ipt == 0)
break;
1392 unsigned short sfIndex,
1393 unsigned short& fromPt,
1394 unsigned short& npts)
1398 if (pfp.
TP3Ds.empty())
return;
1402 for (std::size_t ipt = 0; ipt < pfp.
TP3Ds.size(); ++ipt) {
1403 auto& tp3d = pfp.
TP3Ds[ipt];
1404 if (tp3d.SFIndex < sfIndex)
continue;
1405 if (tp3d.SFIndex > sfIndex)
break;
1406 if (fromPt == USHRT_MAX) fromPt = ipt;
1417 unsigned short sfIndex)
1421 if (pfp.
TP3Ds.size() < 4)
return false;
1422 if (sfIndex >= pfp.
SectionFits.size())
return false;
1426 unsigned short fromPt = USHRT_MAX;
1427 unsigned short npts = 0;
1428 GetRange(pfp, sfIndex, fromPt, npts);
1429 if (fromPt == USHRT_MAX)
return false;
1430 if (npts < 4)
return false;
1433 for (
unsigned short ipt = fromPt; ipt < fromPt + npts; ++ipt) {
1434 auto& tp3d = pfp.
TP3Ds[ipt];
1435 if (tp3d.SFIndex != sfIndex)
return false;
1440 return FitTP3Ds(detProp, slc, pfp, fromPt, npts, sfIndex, chiDOF);
1448 const std::vector<TP3D>& tp3ds,
1449 unsigned short fromPt,
1451 unsigned short nPtsFit)
1458 if (nPtsFit < 5)
return sf;
1459 if (!(fitDir == -1 || fitDir == 1))
return sf;
1460 if (fitDir == 1 && fromPt + nPtsFit > tp3ds.size())
return sf;
1461 if (fitDir == -1 && fromPt < 3)
return sf;
1464 std::vector<std::array<double, 3>> ocs(slc.
nPlanes);
1465 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
1475 const unsigned int nvars = 4;
1476 unsigned int npts = 0;
1479 std::vector<unsigned short> cntInPln(slc.
nPlanes, 0);
1482 for (
short ii = 0; ii < nPtsFit; ++ii) {
1483 short ipt = fromPt + fitDir * ii;
1484 if (ipt < 0 || ipt >= (
short)tp3ds.size())
break;
1485 auto& tp3d = tp3ds[ipt];
1487 if (tp3d.TPXErr2 < 0.0001)
return sf;
1493 if (npts < 6)
return sf;
1495 unsigned short enufInPlane = 0;
1496 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane)
1497 if (cntInPln[plane] > 2) ++enufInPlane;
1498 if (enufInPlane < 2)
return sf;
1502 TMatrixD
A(npts, nvars);
1505 unsigned short cnt = 0;
1507 for (
short ii = 0; ii < nPtsFit; ++ii) {
1508 short ipt = fromPt + fitDir * ii;
1509 auto& tp3d = tp3ds[ipt];
1512 double x = tp3d.TPX - x0;
1513 A[cnt][0] = weight * ocs[plane][1];
1514 A[cnt][1] = weight * ocs[plane][2];
1515 A[cnt][2] = weight * ocs[plane][1] *
x;
1516 A[cnt][3] = weight * ocs[plane][2] *
x;
1517 w[cnt] = weight * (tp3d.Wire - ocs[plane][0]);
1523 TVectorD tVec = svd.Solve(w, ok);
1525 double norm = sqrt(1 + tVec[2] * tVec[2] + tVec[3] * tVec[3]);
1533 sf.
Pos[1] = tVec[0];
1534 sf.
Pos[2] = tVec[1];
1539 TMatrixD AT(nvars, npts);
1541 TMatrixD ATA = AT *
A;
1543 try{ ATA.Invert(det); }
1544 catch(...) {
return sf; }
1551 std::vector<TrajPoint> plnTP(slc.
nPlanes);
1552 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
1559 for (
short ii = 0; ii < nPtsFit; ++ii) {
1560 short ipt = fromPt + fitDir * ii;
1561 auto& tp3d = tp3ds[ipt];
1564 double dw = tp3d.Wire - plnTP[plane].Pos[0];
1566 double t = dw * plnTP[plane].DeltaRMS;
1567 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
1568 pos[xyz] = sf.
Pos[xyz] + t * sf.
Dir[xyz];
1572 double delta = pos[0] - tp3d.TPX;
1573 sf.
ChiDOF += delta * delta / tp3d.TPXErr2;
1575 double dangErr = delta / dw;
1576 sf.
DirErr[0] += dangErr * dangErr;
1589 unsigned short fromPt,
1590 unsigned short nPtsFit,
1591 unsigned short sfIndex,
1598 if (nPtsFit < 5)
return false;
1599 if (fromPt + nPtsFit > pfp.
TP3Ds.size())
return false;
1601 auto sf =
FitTP3Ds(detProp, slc, pfp.
TP3Ds, fromPt, 1, nPtsFit);
1602 if (sf.ChiDOF > 900)
return false;
1605 if (sfIndex >= pfp.
SectionFits.size())
return true;
1611 std::vector<TrajPoint> plnTP(slc.
nPlanes);
1612 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
1614 plnTP[plane] =
MakeBareTP(detProp, slc, sf.Pos, sf.Dir, inCTP);
1617 bool needsSort =
false;
1618 double prevAlong = 0;
1619 for (
unsigned short ipt = fromPt; ipt < fromPt + nPtsFit; ++ipt) {
1620 auto& tp3d = pfp.
TP3Ds[ipt];
1622 double dw = tp3d.Wire - plnTP[plane].Pos[0];
1624 double t = dw * plnTP[plane].DeltaRMS;
1625 if (ipt == fromPt) { prevAlong =
t; }
1627 if (t < prevAlong) needsSort =
true;
1630 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
1631 pos[xyz] = sf.Pos[xyz] + t * sf.Dir[xyz];
1635 double delta = pos[0] - tp3d.TPX;
1639 if (tp3d.Flags[
kTP3DGood]) sf.ChiDOF += delta * delta / tp3d.TPXErr2;
1660 if (pfp.
TP3Ds.empty())
return;
1665 std::vector<int> tjList;
1666 for (
auto& tp3d : pfp.
TP3Ds) {
1669 if (tp3d.TjID <= 0)
continue;
1670 if (std::find(tjList.begin(), tjList.end(), tp3d.TjID) == tjList.end())
1671 tjList.push_back(tp3d.TjID);
1675 std::vector<int> vx2List, vx3List;
1676 for (
auto tid : tjList) {
1677 auto& tj = slc.
tjs[tid - 1];
1678 for (
unsigned short end = 0;
end < 2; ++
end) {
1679 if (tj.VtxID[
end] <= 0)
continue;
1680 auto& vx2 = slc.
vtxs[tj.VtxID[
end] - 1];
1681 if (vx2.Vx3ID > 0) {
1682 if (std::find(vx3List.begin(), vx3List.end(), vx2.Vx3ID) == vx3List.end())
1683 vx3List.push_back(vx2.Vx3ID);
1688 if (std::find(vx2List.begin(), vx2List.end(), tj.VtxID[
end]) == vx2List.end())
1689 vx2List.push_back(tj.VtxID[
end]);
1694 if (vx2List.empty() && vx3List.empty())
return;
1697 myprt <<
"RV: P" << pfp.
ID <<
" ->";
1698 for (
auto tid : tjList)
1699 myprt <<
" T" << tid;
1701 for (
auto vid : vx3List)
1702 myprt <<
" 3V" << vid;
1703 if (!vx2List.empty()) {
1705 for (
auto vid : vx2List)
1706 myprt <<
" 2V" << vid;
1714 for (
auto vid : vx2List) {
1715 auto& vx2 = slc.
vtxs[vid - 1];
1724 if (!slc.
pfps.empty()) {
1725 auto& npfp = slc.
pfps[0];
1726 bool neutrinoPFP = (npfp.PDGCode == 12 || npfp.PDGCode == 14);
1727 if (neutrinoPFP) neutrinoVx = npfp.Vx3ID[0];
1729 unsigned short neutrinoVxEnd = 2;
1730 for (
unsigned short end = 0;
end < 2; ++
end) {
1733 if (pfp.
Vx3ID[
end] == neutrinoVx) neutrinoVxEnd =
end;
1735 if (std::find(vx3List.begin(), vx3List.end(), pfp.
Vx3ID[
end]) != vx3List.end())
continue;
1737 if (neutrinoVxEnd < 2 && neutrinoVxEnd != 0)
Reverse(slc, pfp);
1755 if (pfp.
ID <= 0)
return;
1756 if (pfp.
TP3Ds.empty())
return;
1768 unsigned short nPtsAdded = 0;
1769 unsigned short fromPt = 0;
1770 unsigned short toPt = pWork.
TP3Ds.size();
1771 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
1772 CTP_t inCTP =
EncodeCTP(pWork.TPCID.Cryostat, pWork.TPCID.TPC, plane);
1773 unsigned short nWires, nAdd;
1788 if (prt)
mf::LogVerbatim(
"TC") <<
"FG3D P" << pWork.ID <<
" added " << nPtsAdded <<
" points";
1789 if (pWork.Flags[
kNeedsUpdate] && !
Update(clockData, detProp, slc, pWork, prt))
return;
1803 if (pfp.
TjIDs.size() != 2)
return false;
1804 if (slc.
nPlanes != 3)
return false;
1805 if (pfp.
TP3Ds.empty())
return false;
1808 std::vector<unsigned short> planes;
1809 for (
auto tid : pfp.
TjIDs)
1811 unsigned short thirdPlane = 3 - planes[0] - planes[1];
1815 unsigned int wire0 = 0;
1816 if (tp.Pos[0] > 0) wire0 = std::nearbyint(tp.Pos[0]);
1817 if (wire0 > slc.
nWires[thirdPlane]) wire0 = slc.
nWires[thirdPlane];
1819 unsigned short lastPt = pfp.
TP3Ds.size() - 1;
1821 unsigned int wire1 = 0;
1822 if (tp.Pos[0] > 0) wire1 = std::nearbyint(tp.Pos[0]);
1823 if (wire1 > slc.
nWires[thirdPlane]) wire1 = slc.
nWires[thirdPlane];
1824 if (wire0 == wire1)
return !
evt.
goodWire[thirdPlane][wire0];
1825 if (wire1 < wire0)
std::swap(wire0, wire1);
1828 int wires = wire1 - wire0;
1829 for (
unsigned int wire = wire0; wire < wire1; ++wire)
1832 return (dead > 0.8 * wires);
1841 unsigned short fromPt,
1842 unsigned short toPt,
1845 unsigned short& nWires,
1846 unsigned short& nAdd,
1855 if (fromPt > toPt)
return;
1856 if (toPt >= pfp.
TP3Ds.size()) toPt = pfp.
TP3Ds.size() - 1;
1861 Average_dEdX(clockData, detProp, slc, pfp, dEdXAve, dEdXRms);
1862 float dEdxMin = 0.5, dEdxMax = 50.;
1863 if (dEdXAve > 0.5) {
1864 dEdxMin = dEdXAve - maxPull * dEdXRms;
1865 if (dEdxMin < 0.5) dEdxMin = 0.5;
1866 dEdxMax = dEdXAve + maxPull * dEdXRms;
1867 if (dEdxMax > 50.) dEdxMax = 50.;
1872 std::vector<TrajPoint> sfTPs;
1874 std::vector<std::pair<int, unsigned short>> tpUsed;
1875 for (
auto& tp3d : pfp.
TP3Ds) {
1876 if (tp3d.CTP != inCTP)
continue;
1877 tpUsed.push_back(std::make_pair(tp3d.TjID, tp3d.TPIndex));
1879 unsigned int toWire = 0;
1880 unsigned int fromWire = UINT_MAX;
1882 unsigned short inSF = USHRT_MAX;
1884 for (
unsigned short ipt = 0; ipt < pfp.
TP3Ds.size(); ++ipt) {
1885 auto& tp3d = pfp.
TP3Ds[ipt];
1887 if (ipt < pfp.
TP3Ds.size() - 1 && tp3d.SFIndex == inSF)
continue;
1889 if (tp3d.CTP == inCTP) {
1891 auto& tp = slc.
tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
1892 sfTPs.push_back(tp);
1893 wire = std::nearbyint(tp.Pos[0]);
1894 if (wire >= slc.
nWires[pln])
break;
1899 auto tp =
MakeBareTP(detProp, slc, tp3d.Pos, tp3d.Dir, inCTP);
1900 wire = std::nearbyint(tp.Pos[0]);
1901 if (wire >= slc.
nWires[pln])
break;
1902 sfTPs.push_back(tp);
1904 if (wire < fromWire) fromWire = wire;
1905 if (wire > toWire) toWire = wire;
1906 inSF = tp3d.SFIndex;
1908 if (sfTPs.empty())
return;
1910 if (sfTPs.size() > 1 && sfTPs[0].Pos[0] > sfTPs.back().Pos[0]) {
1918 mf::LogVerbatim(
"TC") <<
"APIR: inCTP " << inCTP <<
" fromWire " << fromWire <<
" toWire " 1922 for (
unsigned short subr = 0; subr < sfTPs.size(); ++subr) {
1923 auto& fromTP = sfTPs[subr];
1924 unsigned int toWireInSF = toWire;
1925 if (subr < sfTPs.size() - 1) toWireInSF = std::nearbyint(sfTPs[subr + 1].Pos[0]);
1927 unsigned int fromWire = std::nearbyint(fromTP.Pos[0]);
1928 if (fromWire > toWire)
continue;
1930 mf::LogVerbatim(
"TC") <<
" inCTP " << inCTP <<
" subr " << subr <<
" fromWire " << fromWire
1931 <<
" toWireInSF " << toWireInSF;
1932 for (
unsigned int wire = fromWire; wire <= toWireInSF; ++wire) {
1936 float bestPull = maxPull;
1938 for (
auto iht : fromTP.Hits) {
1939 if (slc.
slHits[iht].InTraj <= 0)
continue;
1941 auto& utj = slc.
tjs[slc.
slHits[iht].InTraj - 1];
1942 unsigned short tpIndex = 0;
1943 for (tpIndex = utj.EndPt[0]; tpIndex <= utj.EndPt[1]; ++tpIndex) {
1944 auto& utp = utj.Pts[tpIndex];
1945 if (utp.Chg <= 0)
continue;
1947 if (std::find(utp.Hits.begin(), utp.Hits.end(), iht) != utp.Hits.end())
break;
1949 if (tpIndex > utj.EndPt[1])
continue;
1951 std::pair<int, unsigned short> tppr = std::make_pair(utj.ID, tpIndex);
1952 if (std::find(tpUsed.begin(), tpUsed.end(), tppr) != tpUsed.end())
continue;
1953 tpUsed.push_back(tppr);
1954 auto& utp = utj.Pts[tpIndex];
1956 if (utp.InPFP > 0)
continue;
1959 auto newTP3D =
CreateTP3D(detProp, slc, utj.
ID, tpIndex);
1960 if (!
SetSection(detProp, slc, pfp, newTP3D))
continue;
1962 newTP3D.Dir = pfp.
SectionFits[newTP3D.SFIndex].Dir;
1964 float dedx =
dEdx(clockData, detProp, slc, newTP3D);
1966 bool useIt = (pull < bestPull && dedx > dEdxMin && dedx < dEdxMax);
1967 if (!useIt)
continue;
1971 if (bestPull < maxPull) {
1972 if (prt && bestPull < 10) {
1975 myprt <<
"APIR: P" << pfp.
ID <<
" added TP " <<
PrintPos(slc, tp);
1977 myprt <<
" dx " << bestTP3D.
TPX - bestTP3D.
Pos[0] <<
" in section " << bestTP3D.
SFIndex;
1979 if (
InsertTP3D(pfp, bestTP3D) == USHRT_MAX)
continue;
1993 std::size_t ipt = 0;
1994 for (ipt = 0; ipt < pfp.
TP3Ds.size(); ++ipt)
1996 if (ipt == pfp.
TP3Ds.size())
return USHRT_MAX;
1998 auto lastTP3D = pfp.
TP3Ds.back();
1999 if (ipt == 0 && tp3d.
along < pfp.
TP3Ds[0].along) {
2002 else if (tp3d.
SFIndex == lastTP3D.SFIndex && tp3d.
along > lastTP3D.along) {
2004 pfp.
TP3Ds.push_back(tp3d);
2007 return pfp.
TP3Ds.size() - 1;
2010 for (std::size_t iipt = ipt; iipt < pfp.
TP3Ds.size() - 1; ++iipt) {
2012 if (pfp.
TP3Ds[iipt + 1].SFIndex != tp3d.
SFIndex)
break;
2019 pfp.
TP3Ds.insert(pfp.
TP3Ds.begin() + ipt, tp3d);
2031 if (sfIndex > pfp.
SectionFits.size() - 1)
return false;
2033 if (sf.Pos[0] == 0.0 && sf.Pos[1] == 0.0 && sf.Pos[2] == 0.0)
return false;
2036 std::vector<TP3D>
temp;
2038 std::vector<unsigned short> indx;
2040 float prevAlong = 0;
2042 bool needsSort =
false;
2043 for (std::size_t ii = 0; ii < pfp.
TP3Ds.size(); ++ii) {
2044 auto& tp3d = pfp.
TP3Ds[ii];
2045 if (tp3d.SFIndex != sfIndex)
continue;
2048 prevAlong = tp3d.along;
2051 if (tp3d.along < prevAlong) needsSort =
true;
2052 prevAlong = tp3d.along;
2054 temp.push_back(tp3d);
2057 if (temp.empty())
return false;
2059 if (temp.size() == 1)
return true;
2061 sf.NeedsUpdate =
false;
2065 bool contiguous =
true;
2066 for (std::size_t ipt = 1; ipt < indx.size(); ++ipt) {
2067 if (indx[ipt] != indx[ipt - 1] + 1) contiguous =
false;
2069 if (!contiguous) {
return false; }
2071 std::vector<SortEntry> sortVec(temp.size());
2072 for (std::size_t ii = 0; ii < temp.size(); ++ii) {
2073 sortVec[ii].index = ii;
2074 sortVec[ii].val = temp[ii].along;
2077 for (std::size_t ii = 0; ii < temp.size(); ++ii) {
2079 auto& tp3d = pfp.
TP3Ds[indx[ii]];
2080 tp3d = temp[sortVec[ii].index];
2082 sf.NeedsUpdate =
false;
2095 if(pfp.
TP3Ds.size() < 20)
return;
2102 unsigned short halfPt = p2.TP3Ds.size() / 2;
2103 for(
unsigned short ipt = halfPt; ipt < p2.TP3Ds.size(); ++ipt) p2.TP3Ds[ipt].SFIndex = 1;
2106 if(toPt > p2.TP3Ds.size())
return;
2108 if(toPt > p2.TP3Ds.size())
return;
2109 if(!
FitSection(clockData, detProp, slc, p2, 0) || !
FitSection(clockData, detProp, slc, p2, 1)) {
2112 myprt <<
"Recover failed MVI " << p2.MVI <<
" in TPC " << p2.TPCID.TPC;
2113 for(
auto tid : p2.TjIDs) myprt <<
" T" << tid;
2142 unsigned short nJunk = 0;
2143 unsigned short nSA = 0;
2144 for(
unsigned short itj = 0; itj < pfp.
TjIDs.size(); ++itj) {
2145 auto& tj = slc.
tjs[pfp.
TjIDs[itj] - 1];
2146 if(tj.AlgMod[
kJunkTj]) ++nJunk;
2148 unsigned short iptMin = USHRT_MAX;
2149 float posMax = -1E6;
2150 unsigned short iptMax = USHRT_MAX;
2153 for(
unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ++ipt) {
2154 auto& tp = tj.Pts[ipt];
2155 if(tp.Chg <= 0)
continue;
2157 if (tp.InPFP > 0)
continue;
2159 if(tp.Pos[1] > posMax) { posMax = tp.Pos[1]; iptMax = ipt; }
2160 if(tp.Pos[1] < posMin) { posMin = tp.Pos[1]; iptMin = ipt; }
2164 if(npwc == 0)
continue;
2168 if(iptMin > tj.EndPt[0] + 4 && iptMin < tj.EndPt[1] - 4) pfp.
TjUIDs[itj] = iptMin;
2169 if(iptMax > tj.EndPt[0] + 4 && iptMax < tj.EndPt[1] - 4) pfp.
TjUIDs[itj] = iptMax;
2171 if(avail < 0.8 * cnt)
return false;
2179 for (
auto tid : pfp.
TjIDs) {
2180 auto& tj = slc.
tjs[tid - 1];
2182 if(nJunk == 1 && tj.AlgMod[
kJunkTj])
continue;
2185 bool isJunk = tj.AlgMod[
kJunkTj];
2186 for(
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2187 auto& tp = tj.Pts[ipt];
2188 if (tp.Chg <= 0)
continue;
2189 if (tp.InPFP > 0)
continue;
2191 auto tp3d =
CreateTP3D(detProp, slc, tid, ipt);
2194 if(isJunk) tp3d.TPXErr2 *= 4;
2197 pfp.
TP3Ds.push_back(tp3d);
2215 if(pfp.
TjIDs.size() < 2)
return false;
2217 std::vector<SortEntry> sortVec(pfp.
TjIDs.size());
2218 unsigned short sbCnt = 0;
2219 for (
unsigned short itj = 0; itj < pfp.
TjIDs.size(); ++itj) {
2220 sortVec[itj].index = itj;
2221 auto& tj = slc.
tjs[pfp.
TjIDs[itj] - 1];
2223 if(pfp.
TjUIDs[itj] > 0) ++sbCnt;
2229 unsigned short tlIndex = sortVec[0].index;
2230 unsigned short nlIndex = sortVec[1].index;
2231 auto& tlong = slc.
tjs[pfp.
TjIDs[tlIndex] - 1];
2232 auto& nlong = slc.
tjs[pfp.
TjIDs[nlIndex] - 1];
2233 bool twoSections = (sbCnt > 1 && pfp.
TjUIDs[tlIndex] > 0 && pfp.
TjUIDs[nlIndex] > 0);
2234 unsigned short tStartPt = tlong.EndPt[0];
2235 unsigned short tEndPt = tlong.EndPt[1];
2236 unsigned short nStartPt = nlong.EndPt[0];
2237 unsigned short nEndPt = nlong.EndPt[1];
2240 tEndPt = pfp.
TjUIDs[tlIndex];
2241 nEndPt = pfp.
TjUIDs[nlIndex];
2244 myprt<<
"MakeSmallAnglePFP: creating two sections using points";
2245 myprt<<
" T"<<tlong.ID<<
"_"<<tEndPt;
2246 myprt<<
" T"<<nlong.ID<<
"_"<<nEndPt;
2249 std::vector<Point3_t> sfEndPos;
2250 for(
unsigned short isf = 0; isf < pfp.
SectionFits.size(); ++isf) {
2252 auto& ltp0 = tlong.Pts[tStartPt];
2253 auto& ltp1 = tlong.Pts[tEndPt];
2254 auto& ntp0 = nlong.Pts[nStartPt];
2255 auto& ntp1 = nlong.Pts[nEndPt];
2257 auto start =
MakeTP3D(detProp, slc, ltp0, ntp0);
2260 std::cout<<
" Start/end fail in section "<<isf<<
". Add recovery code\n";
2264 mf::LogVerbatim(
"TC")<<
" Start is outside the TPC "<<start.Pos[0]<<
" "<<start.Pos[1]<<
" "<<start.Pos[2];
2269 if(isf == 0) sfEndPos.push_back(start.Pos);
2270 sfEndPos.push_back(
end.Pos);
2273 for(
unsigned short xyz = 0; xyz < 3; ++xyz) {
2274 sf.Dir[xyz] =
end.Pos[xyz] - start.Pos[xyz];
2275 sf.Pos[xyz] = (
end.Pos[xyz] + start.Pos[xyz]) / 2.;
2281 tStartPt = tEndPt + 1; tEndPt = tlong.EndPt[1];
2282 nStartPt = nEndPt + 1; nEndPt = nlong.EndPt[1];
2286 std::vector<TP3D> sf2pts;
2287 for(
unsigned short itj = 0; itj < sortVec.size(); ++itj) {
2288 int tid = pfp.
TjIDs[sortVec[itj].index];
2291 if(twoSections && pfp.
TjUIDs[sortVec[itj].index] < 0)
continue;
2292 auto& tj = slc.
tjs[tid - 1];
2293 unsigned short sb = tj.EndPt[1];
2294 if(twoSections && pfp.
TjUIDs[sortVec[itj].index] > 0) sb = pfp.
TjUIDs[sortVec[itj].index];
2296 std::vector<double> npwc(pfp.
SectionFits.size(), 0);
2297 for(
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2298 auto& tp = tj.Pts[ipt];
2299 if(tp.Chg <= 0)
continue;
2300 if(ipt > sb) { ++npwc[1]; }
else { ++npwc[0]; }
2302 double length =
PosSep(sfEndPos[0], sfEndPos[1]);
2303 double step = length / npwc[0];
2304 double along = -length / 2;
2305 unsigned short sfi = 0;
2306 for(
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2307 auto& tp = tj.Pts[ipt];
2308 if(tp.Chg <= 0)
continue;
2309 auto tp3d =
CreateTP3D(detProp, slc, tid, ipt);
2313 length =
PosSep(sfEndPos[1], sfEndPos[2]);
2314 step = length / npwc[1];
2315 along = -length / 2;
2321 for(
unsigned short xyz = 0; xyz < 3; ++xyz) tp3d.Pos[xyz] = sf.Pos[xyz] + along * sf.Dir[xyz];
2324 double delta = tp3d.Pos[0] - tp3d.TPX;
2325 sf.ChiDOF += delta * delta / tp3d.TPXErr2;
2329 pfp.
TP3Ds.push_back(tp3d);
2331 sf2pts.push_back(tp3d);
2335 if(pfp.
TP3Ds.size() < 4)
return false;
2337 if(sf.NPts < 5)
return false;
2338 sf.ChiDOF /= (
float)(sf.NPts - 4);
2341 if(!sf2pts.empty()) {
2343 pfp.
TP3Ds.insert(pfp.
TP3Ds.end(), sf2pts.begin(), sf2pts.end());
2350 <<
" with "<<pfp.
TP3Ds.size()
2351 <<
" points in "<<pfp.
SectionFits.size()<<
" sections\n";
2364 for (std::size_t sfi = 0; sfi < pfp.
SectionFits.size(); ++sfi) {
2367 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
2371 for (
auto& tp3d : pfp.
TP3Ds)
2392 unsigned short cnt = 0;
2398 for (
auto& tj : slc.
tjs) {
2401 if (tj.AlgMod[
kMat3D])
continue;
2403 if ((
int)planeID.
Cryostat != cstat)
continue;
2404 if ((
int)planeID.
TPC != tpc)
continue;
2405 int plane = planeID.
Plane;
2406 if (tj.ID <= 0)
continue;
2407 unsigned short tjID = tj.ID;
2408 for (
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2409 auto& tp = tj.Pts[ipt];
2410 if (tp.Chg <= 0)
continue;
2411 if (tp.Pos[0] < -0.4)
continue;
2413 if (tp.InPFP > 0)
continue;
2414 if (muFuzzCut && tp.Environment[
kEnvNearMuon])
continue;
2415 tj2pt.
wire = std::nearbyint(tp.Pos[0]);
2422 tj2pt.
plane = plane;
2425 tj2pt.
npts = tj.EndPt[1] - tj.EndPt[0] + 1;
2431 std::vector<SortEntry> sortVec(slc.
mallTraj.size());
2432 for (std::size_t ipt = 0; ipt < slc.
mallTraj.size(); ++ipt) {
2434 sortVec[ipt].index = ipt;
2435 sortVec[ipt].val = slc.
mallTraj[ipt].xlo;
2441 for (std::size_t ii = 0; ii < sortVec.size(); ++ii)
2442 slc.
mallTraj[ii] = tallTraj[sortVec[ii].index];
2458 tp3d.
Dir = {{0.0, 0.0, 1.0}};
2459 tp3d.
Pos = {{999.0, 999.0, 999.0}};
2462 if(iPlnID == jPlnID)
return tp3d;
2469 if(dx > 20)
return tp3d;
2470 tp3d.
Pos[0] = (ix + jx) / 2;
2485 double den = isn * jcs - ics * jsn;
2486 if(den == 0)
return tp3d;
2487 double iPos0 = itp.
Pos[0];
2488 double jPos0 = jtp.
Pos[0];
2490 tp3d.
Pos[2] = (jcs * (iPos0 - iw0) - ics * (jPos0 - jw0)) / den;
2494 tp3d.
Pos[1] = (iPos0 - iw0 - isn * tp3d.
Pos[2]) / ics;
2496 tp3d.
Pos[1] = (jPos0 - jw0 - jsn * tp3d.
Pos[2]) / jcs;
2500 if(jtp.
Dir[1] == 0) {
2502 if(jtp.
Dir[0] > 0) { tp3d.
Dir[0] = 1; }
else { tp3d.
Dir[0] = -1; }
2511 double itp2_0 = itp.
Pos[0] + 100;
2512 double itp2_1 = itp.
Pos[1];
2521 double jtp2Pos0 = (jtp2Pos1 - jtp.
Pos[1]) * (jtp.
Dir[0] / jtp.
Dir[1]) + jtp.
Pos[0];
2523 pos2[2] = (jcs * (itp2_0 - iw0) - ics * (jtp2Pos0 - jw0)) / den;
2525 pos2[1] = (itp2_0 - iw0 - isn * pos2[2]) / ics;
2527 pos2[1] = (jtp2Pos0 - jw0 - jsn * pos2[2]) / jcs;
2530 if(sep == 0)
return tp3d;
2531 for(
unsigned short ixyz = 0; ixyz < 3; ++ixyz) tp3d.
Dir[ixyz] = (pos2[ixyz] - tp3d.
Pos[ixyz]) /sep;
2541 if (v1[0] == v2[0] && v1[1] == v2[1] && v1[2] == v2[2])
return 0;
2551 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
2552 dir[xyz] = p2[xyz] - p1[xyz];
2553 if (dir[0] == 0 && dir[1] == 0 && dir[2] == 0)
return dir;
2566 return sqrt(
PosSep2(pos1, pos2));
2574 double d0 = pos1[0] - pos2[0];
2575 double d1 = pos1[1] - pos2[1];
2576 double d2 = pos1[2] - pos2[2];
2577 return d0 * d0 + d1 * d1 + d2 * d2;
2584 double den = v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2];
2585 if (den == 0)
return false;
2604 unsigned short numEnds = 2;
2605 if (pfp.
PDGCode == 1111) numEnds = 1;
2608 for (
unsigned short end = 0;
end < numEnds; ++
end) {
2609 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane)
2617 for (
unsigned short end = 0;
end < numEnds; ++
end) {
2618 std::vector<float> cnt(slc.
nPlanes);
2621 for (std::size_t ii = 0; ii < pfp.
TP3Ds.size(); ++ii) {
2623 if (dir > 0) { ipt = ii; }
2625 ipt = pfp.
TP3Ds.size() - ii - 1;
2627 if (ipt >= pfp.
TP3Ds.size())
break;
2628 auto& tp3d = pfp.
TP3Ds[ipt];
2629 if (tp3d.Flags[
kTP3DBad])
continue;
2630 if (
PosSep2(tp3d.Pos, endPos) > maxSep2)
break;
2633 float dedx =
dEdx(clockData, detProp, slc, tp3d);
2634 if (dedx < 0.5)
continue;
2639 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
2640 if (cnt[plane] == 0)
continue;
2641 pfp.
dEdx[
end][plane] /= cnt[plane];
2664 for (
auto& tp3d : pfp.
TP3Ds) {
2666 double dedx =
dEdx(clockData, detProp, slc, tp3d);
2667 if (dedx < 0.5 || dedx > 80.)
continue;
2669 sum2 += dedx * dedx;
2672 if (cnt < 3)
return;
2673 dEdXAve = sum / cnt;
2675 dEdXRms = 0.3 * dEdXAve;
2676 double arg = sum2 - cnt * dEdXAve * dEdXAve;
2677 if (arg < 0)
return;
2678 dEdXRms = sqrt(arg) / (cnt - 1);
2680 double minRms = 0.05 * dEdXAve;
2681 if (dEdXRms < minRms) dEdXRms = minRms;
2692 if (tp3d.
TjID > (
int)slc.
slHits.size())
return 0;
2693 if (tp3d.
TjID <= 0)
return 0;
2700 for (
unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2701 if (!tp.UseHit[ii])
continue;
2703 dQ +=
hit.Integral();
2707 if (dQ == 0)
return 0;
2710 std::abs(std::sin(angleToVert) * tp3d.
Dir[1] + std::cos(angleToVert) * tp3d.
Dir[2]);
2711 if (cosgamma < 1.
E-5)
return 0;
2713 double dQdx = dQ / dx;
2716 if (std::isinf(dedx)) dedx = 0;
2725 unsigned short tpIndex)
2733 if (tjID <= 0 || tjID > (
int)slc.
tjs.size())
return tp3d;
2734 auto& tj = slc.
tjs[tjID - 1];
2735 if (tpIndex < tj.EndPt[0] || tpIndex > tj.EndPt[1])
return tp3d;
2738 auto& tp2 = tj.Pts[tp3d.
TPIndex];
2746 if (tp2.AngleCode == 1) rms *= 2;
2748 if (tp2.AngleCode > 1) {
2749 std::vector<unsigned int> hitMultiplet;
2750 for (std::size_t ii = 0; ii < tp2.Hits.size(); ++ii) {
2751 if (!tp2.UseHit[ii])
continue;
2753 if (hitMultiplet.size() > 1)
break;
2760 tp3d.
Wire = tp2.Pos[0];
2777 if (tp3d.
Wire < 0)
return false;
2779 if (pfp.
SectionFits[0].Pos[0] == -10.0)
return false;
2788 for (std::size_t sfi = 0; sfi < pfp.
SectionFits.size(); ++sfi) {
2799 auto plnTP =
MakeBareTP(detProp, slc, sf.Pos, sf.Dir, tp3d.
CTP);
2801 double dw = tp3d.
Wire - plnTP.Pos[0];
2803 double t = dw * plnTP.DeltaRMS;
2805 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
2806 tp3d.
Pos[xyz] = sf.Pos[xyz] + t * sf.Dir[xyz];
2827 pfp.
ID = slc.
pfps.size() + 1;
2849 if (slc.
pfps.empty())
return;
2851 for (
auto& pfp : slc.
pfps) {
2852 if (pfp.ID == 0)
continue;
2853 if (pfp.Vx3ID[0] > 0)
continue;
2854 if (pfp.SectionFits.empty())
continue;
2861 if (pfp.TP3Ds.empty()) {
2863 startPos = pfp.SectionFits[0].Pos;
2865 else if (!pfp.TP3Ds.empty()) {
2867 startPos = pfp.TP3Ds[0].Pos;
2869 vx3.
X = startPos[0];
2870 vx3.
Y = startPos[1];
2871 vx3.
Z = startPos[2];
2872 vx3.
ID = slc.
vtx3s.size() + 1;
2876 slc.
vtx3s.push_back(vx3);
2877 pfp.Vx3ID[0] = vx3.
ID;
2919 if (slc.
pfps.empty())
return;
2922 int neutrinoPFPID = 0;
2923 for (
auto& pfp : slc.
pfps) {
2924 if (pfp.ID == 0)
continue;
2925 if (!
tcc.
modes[
kTestBeam] && neutrinoPFPID == 0 && (pfp.PDGCode == 12 || pfp.PDGCode == 14)) {
2926 neutrinoPFPID = pfp.ID;
2932 constexpr
unsigned short end1 = 1;
2933 for (
auto& pfp : slc.
pfps) {
2934 if (pfp.ID == 0)
continue;
2936 if (pfp.Vx3ID[end1] > 0)
continue;
2940 unsigned short cnt3 = 0;
2941 unsigned short vx3id = 0;
2943 std::vector<int> vx2ids;
2944 for (
auto tjid : pfp.TjIDs) {
2945 auto& tj = slc.
tjs[tjid - 1];
2946 if (tj.VtxID[end1] == 0)
continue;
2947 auto& vx2 = slc.
vtxs[tj.VtxID[end1] - 1];
2948 if (vx2.Vx3ID == 0) {
2949 if (vx2.Topo == 1 && vx2.NTraj == 2) vx2ids.push_back(vx2.ID);
2952 if (vx3id == 0) vx3id = vx2.Vx3ID;
2953 if (vx2.Vx3ID == vx3id) ++cnt3;
2957 if (pfp.Vx3ID[1 - end1] == vx3id)
continue;
2958 pfp.Vx3ID[end1] = vx3id;
2963 for (
auto& pfp : slc.
pfps) {
2964 if (pfp.ID == 0)
continue;
2966 if (pfp.PDGCode == 12 || pfp.PDGCode == 14 || pfp.PDGCode == 22)
continue;
2969 int pfpParentID = INT_MAX;
2970 unsigned short nParent = 0;
2971 for (
auto tjid : pfp.TjIDs) {
2972 auto& tj = slc.
tjs[tjid - 1];
2973 if (tj.ParentID <= 0)
continue;
2974 auto parPFP =
GetAssns(slc,
"T", tj.ParentID,
"P");
2975 if (parPFP.empty())
continue;
2976 if (pfpParentID == INT_MAX) pfpParentID = parPFP[0];
2977 if (parPFP[0] == pfpParentID) ++nParent;
2980 auto& ppfp = slc.
pfps[pfpParentID - 1];
2982 pfp.ParentUID = ppfp.UID;
2984 ppfp.DtrUIDs.push_back(pfp.UID);
2988 if (neutrinoPFPID > 0) {
2989 auto& neutrinoPFP = slc.
pfps[neutrinoPFPID - 1];
2990 int vx3id = neutrinoPFP.Vx3ID[1];
2991 for (
auto& pfp : slc.
pfps) {
2992 if (pfp.ID == 0 || pfp.ID == neutrinoPFPID)
continue;
2993 if (pfp.Vx3ID[0] != vx3id)
continue;
2994 pfp.ParentUID = (size_t)neutrinoPFPID;
2995 neutrinoPFP.DtrUIDs.push_back(pfp.ID);
2996 if (pfp.PDGCode == 111) neutrinoPFP.PDGCode = 12;
3008 if (pfp.
TjIDs.empty())
return false;
3009 if (pfp.
PDGCode != 1111 && pfp.
TP3Ds.size() < 2)
return false;
3014 for(
auto& tp3d : pfp.
TP3Ds) {
3015 if(tp3d.TPIndex != USHRT_MAX) slc.
tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex].InPFP = pfp.
ID;
3020 unsigned short nNotSet = 0;
3021 for (
auto& tp3d : pfp.
TP3Ds) {
3022 if (tp3d.Flags[
kTP3DBad])
continue;
3023 auto& tp = slc.
tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
3024 if (tp.InPFP != pfp.
ID) ++nNotSet;
3026 if (nNotSet > 0)
return false;
3028 if (pfp.
ID != (
int)slc.
pfps.size() + 1) pfp.
ID = slc.
pfps.size() + 1;
3033 for (
auto tjid : pfp.
TjIDs) {
3034 auto& tj = slc.
tjs[tjid - 1];
3035 tj.AlgMod[
kMat3D] =
true;
3038 slc.
pfps.push_back(pfp);
3047 if (pfp.
ID <= 0)
return false;
3048 if (end > 1)
return false;
3057 if (neutrinoPFP) { pos = pfp.
SectionFits[0].Pos; }
3058 else if (end == 0) {
3059 pos = pfp.
TP3Ds[0].Pos;
3064 return (pos[0] > slc.
xLo + abit && pos[0] < slc.
xHi - abit && pos[1] > slc.
yLo + abit &&
3065 pos[1] < slc.
yHi - abit && pos[2] > slc.
zLo + abit && pos[2] < slc.
zHi - abit);
3078 double local[3] = {0., 0., 0.};
3079 double world[3] = {0., 0., 0.};
3101 if (pos1[0] == pos2[0] && pos1[1] == pos2[1] && pos1[2] == pos2[2])
return;
3104 double costh =
DotProd(dir1, ptDir);
3105 if (costh > 1) costh = 1;
3106 double sep =
PosSep(pos1, pos2);
3107 alongTrans[0] = costh * sep;
3108 double sinth = sqrt(1 - costh * costh);
3109 alongTrans[1] = sinth * sep;
3123 for (
unsigned short xyz = 0; xyz < 3; ++xyz) {
3124 p1End[xyz] = p1[xyz] + 10 * p1Dir[xyz];
3125 p2End[xyz] = p2[xyz] + 10 * p2Dir[xyz];
3149 double d1343, d4321, d1321, d4343, d2121;
3150 double numer, denom;
3153 p13[0] = p1[0] - p3[0];
3154 p13[1] = p1[1] - p3[1];
3155 p13[2] = p1[2] - p3[2];
3156 p43[0] = p4[0] - p3[0];
3157 p43[1] = p4[1] - p3[1];
3158 p43[2] = p4[2] - p3[2];
3160 p21[0] = p2[0] - p1[0];
3161 p21[1] = p2[1] - p1[1];
3162 p21[2] = p2[2] - p1[2];
3165 d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2];
3166 d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2];
3167 d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2];
3168 d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2];
3169 d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2];
3171 denom = d2121 * d4343 - d4321 * d4321;
3172 if (
std::abs(denom) < EPS)
return (
false);
3173 numer = d1343 * d4321 - d1321 * d4343;
3175 double mua = numer / denom;
3176 double mub = (d1343 + d4321 * mua) / d4343;
3178 intersect[0] = p1[0] + mua * p21[0];
3179 intersect[1] = p1[1] + mua * p21[1];
3180 intersect[2] = p1[2] + mua * p21[2];
3182 pb[0] = p3[0] + mub * p43[0];
3183 pb[1] = p3[1] + mub * p43[1];
3184 pb[2] = p3[2] + mub * p43[2];
3185 doca =
PosSep(intersect, pb);
3187 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
3188 intersect[xyz] += pb[xyz];
3189 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
3190 intersect[xyz] /= 2;
3205 float sep =
PosSep(pos1, pos2);
3206 if (sep == 0)
return -1;
3213 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
3215 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
3225 if (cnt == 0)
return -1;
3238 if (pfp.
ID == 0)
return 0;
3239 if (pfp.
TjIDs.empty())
return 0;
3240 if (end < 0 || end > 1)
return 0;
3250 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
3252 std::vector<int> tjids(1);
3253 for (
auto tjid : pfp.
TjIDs) {
3254 auto& tj = slc.
tjs[tjid - 1];
3255 if (tj.CTP != inCTP)
continue;
3260 if (pos2[0] < -0.4)
continue;
3262 unsigned int wire = std::nearbyint(pos2[0]);
3263 if (wire > slc.
nWires[plane])
continue;
3264 if (slc.
wireHitRange[plane][wire].first == UINT_MAX)
continue;
3267 if (cf < lo) lo = cf;
3268 if (cf > hi) hi = cf;
3273 if (cnt == 0)
return 0;
3274 if (cnt > 1 && lo < 0.3 && hi > 0.8) {
3285 if (end > 1 || pfp.
SectionFits.empty())
return {{0., 0., 0.}};
3294 if (end > 1 || pfp.
SectionFits.empty())
return {{0., 0., 0.}};
3297 if (end == 0)
return pfp.
TP3Ds[0].Pos;
3305 if (pfp.
TP3Ds.empty())
return 0;
3312 unsigned short sfIndex,
3313 unsigned short& startPt,
3314 unsigned short& endPt)
3317 startPt = USHRT_MAX;
3319 if (sfIndex >= pfp.
SectionFits.size())
return false;
3322 for (std::size_t ipt = 0; ipt < pfp.
TP3Ds.size(); ++ipt) {
3323 auto& tp3d = pfp.
TP3Ds[ipt];
3324 if (tp3d.SFIndex < sfIndex)
continue;
3329 if (tp3d.SFIndex > sfIndex)
break;
3341 if (pfp.
ID == 0)
return 0;
3342 if (pfp.
TP3Ds.empty())
return 0;
3343 auto& pos0 = pfp.
TP3Ds[0].Pos;
3344 auto& pos1 = pfp.
TP3Ds[pfp.
TP3Ds.size() - 1].Pos;
3358 if (pfp.
TP3Ds.empty())
return -1;
3363 Average_dEdX(clockData, detProp, slc, pfp, dEdXAve, dEdXRms);
3364 if (dEdXAve < 0)
return 0;
3367 float length =
Length(pfp);
3371 for (
auto tjid : pfp.
TjIDs) {
3372 auto& tj = slc.
tjs[tjid - 1];
3374 if (el <= 0)
continue;
3375 mcsmom +=
MCSMom(slc, tj);
3376 chgrms += tj.ChgRMS;
3379 if (cnt < 2)
return 0;
3384 if (length > 150) vote = 13;
3386 if (vote == 0 && length > 50 && dEdXAve < 2.5 && mcsmom > 500) vote = 13;
3388 if (vote == 0 && dEdXAve > 3.0 && mcsmom > 200 && chgrms < 0.4) vote = 2212;
3390 if (vote == 0 && mcsmom < 50 && chgrms > 0.4) vote = 11;
3403 if (pfp.
TP3Ds.empty())
return;
3405 myprt << someText <<
" pfp P" << pfp.
ID <<
" MVI " << pfp.
MVI;
3406 for (
auto tid : pfp.
TjIDs)
3407 myprt <<
" T" << tid;
3411 for (
unsigned short ib = 0; ib <
pAlgModSize; ++ib) {
3417 <<
" SFI ________Pos________ ________Dir_______ _____EndPos________ ChiDOF NPts " 3419 for (std::size_t sfi = 0; sfi < pfp.
SectionFits.size(); ++sfi) {
3420 myprt << someText <<
std::setw(4) << sfi;
3423 unsigned short startPt = 0, endPt = 0;
3425 auto& start = pfp.
TP3Ds[startPt].Pos;
3429 myprt <<
" Invalid";
3435 if (endPt < pfp.
TP3Ds.size()) {
3440 myprt <<
" Invalid";
3444 myprt <<
std::setw(6) << sf.NeedsUpdate;
3450 myprt<<someText<<
" Note: GBH = TP3D Flags. G = Good, B = Bad, H = High dE/dx \n";
3451 myprt<<someText<<
" ipt SFI ________Pos________ Delta Pull GBH Path along dE/dx S? T_ipt_P:W:T\n";
3453 unsigned short fromPt = 0;
3454 unsigned short toPt = pfp.
TP3Ds.size() - 1;
3455 if (printPts >= 0) fromPt = toPt;
3457 std::vector<float> dang(pfp.
TP3Ds.size(), -1);
3458 for (
unsigned short ipt = fromPt; ipt <= toPt; ++ipt) {
3459 auto tp3d = pfp.
TP3Ds[ipt];
3460 myprt << someText <<
std::setw(4) << ipt;
3474 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
3476 auto tp =
MakeBareTP(detProp, slc, tp3d.Pos, inCTP);
3479 if (tp3d.TjID > 0) {
3480 auto& tp = slc.
tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
3481 myprt <<
" T" << tp3d.TjID <<
"_" << tp3d.TPIndex <<
"_" <<
PrintPos(slc, tp) <<
" " 3485 myprt <<
" UNDEFINED";
Expect tracks entering from the front face. Don't create neutrino PFParticles.
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.
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
code to link reconstructed objects back to the MC truth information
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< Trajectory > tjs
vector of all trajectories in each plane
void Recover(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, PFPStruct &pfp, bool prt)
unsigned short FarEnd(const TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
float Length(const PFPStruct &pfp)
bool dbgStitch
debug PFParticle stitching
void Average_dEdX(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, float &dEdXAve, float &dEdXRms)
void MakePFParticles(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, std::vector< MatchStruct > matVec, unsigned short matVec_Iter)
std::array< std::vector< float >, 2 > dEdxErr
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
int TjID
ID of the trajectory -> TP3D assn.
bool ReconcileTPs(TCSlice &slc, PFPStruct &pfp, bool prt)
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.
bool InsideFV(const TCSlice &slc, const PFPStruct &pfp, unsigned short end)
unsigned short CloseEnd(const TCSlice &slc, const Trajectory &tj, const Point2_t &pos)
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
static unsigned int kWire
const std::vector< std::string > AlgBitNames
bool SetSection(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, TP3D &tp3d)
CTP_t CTP
Cryostat, TPC, Plane code.
double rms(sqlite3 *db, std::string const &table_name, std::string const &column_name)
bool InsideTPC(const Point3_t &pos, geo::TPCID &inTPCID)
std::array< double, 3 > Point3_t
bool SignalAtTp(TrajPoint &tp)
std::vector< float > vtx3DCuts
2D vtx -> 3D vtx matching cuts
bool SortSection(PFPStruct &pfp, unsigned short sfIndex)
void Reverse(TCSlice &slc, PFPStruct &pfp)
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
std::bitset< pAlgModSize > AlgMod
std::vector< std::vector< std::pair< unsigned int, unsigned int > > > wireHitRange
The data type to uniquely identify a Plane.
Geometry information for a single TPC.
Point3_t Pos
center position of this section
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)
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
CryostatID_t Cryostat
Index of cryostat.
static unsigned int kPlane
void SetAngleCode(TrajPoint &tp)
void PrintP(std::string someText, mf::LogVerbatim &myprt, PFPStruct &pfp, bool &printHeader)
PFPStruct CreatePFP(const TCSlice &slc)
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
bool dbgSlc
debug only in the user-defined slice? default is all slices
void Match2Planes(TCSlice &slc, std::vector< MatchStruct > &matVec)
bool CanSection(const TCSlice &slc, const PFPStruct &pfp)
std::array< int, 2 > Vx3ID
float TPHitsRMSTime(const TCSlice &slc, const TrajPoint &tp, HitStatus_t hitRequest)
unsigned int MVI
MatchVec Index for detailed 3D matching.
bool IsShowerLike(TCSlice &slc, const std::vector< int > TjIDs)
void FilldEdx(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp)
void ReconcileVertices(TCSlice &slc, PFPStruct &pfp, bool prt)
std::string TPEnvString(const TrajPoint &tp)
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
std::vector< std::array< unsigned int, 3 > > sptHits
SpacePoint -> Hits assns by plane.
Q_EXPORT QTSManip setprecision(int p)
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.
float MaxTjLen(const TCSlice &slc, std::vector< int > &tjIDs)
void MakePFPTjs(TCSlice &slc)
unsigned short Find3DRecoRange(const TCSlice &slc, const PFPStruct &pfp, unsigned short fromPt, unsigned short min2DPts, short dir)
bool MakeSmallAnglePFP(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, PFPStruct &pfp, bool prt)
Vector3_t DirErr
and direction error
static constexpr double ms
double ThetaZ() const
Angle of the wires from positive z axis; .
void AddPointsInRange(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, PFPStruct &pfp, unsigned short fromPt, unsigned short toPt, CTP_t inCTP, float maxPull, unsigned short &nWires, unsigned short &nAdd, bool prt)
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const Point3_t &pos, CTP_t inCTP)
float HitsRMSTime(const TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
std::vector< int > TjUIDs
bool ReSection(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, bool prt)
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.
Vector3_t Dir
and direction
std::vector< Tj2Pt > mallTraj
vector of trajectory points ordered by increasing X
void FillGaps3D(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, PFPStruct &pfp, bool prt)
std::array< float, 2 > Point2_t
int PDGCodeVote(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp)
float unitsPerTick
scale factor from Tick to WSE equivalent units
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
void swap(Handle< T > &a, Handle< T > &b)
void FillWireIntersections(TCSlice &slc)
bool MakeTP3Ds(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, PFPStruct &pfp, bool prt)
unsigned short TPIndex
and the TP index
void Match3Planes(TCSlice &slc, std::vector< MatchStruct > &matVec)
void GetHitMultiplet(const TCSlice &slc, unsigned int theHit, std::vector< unsigned int > &hitsInMultiplet, bool useLongPulseHits)
bool TCIntersectionPoint(unsigned int wir1, unsigned int wir2, unsigned int pln1, unsigned int pln2, float &y, float &z)
float ElectronLikelihood(const TCSlice &slc, const Trajectory &tj)
std::vector< std::vector< bool > > goodWire
Point3_t Pos
position of the trajectory
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
std::vector< unsigned int > FindCloseHits(const TCSlice &slc, std::array< int, 2 > const &wireWindow, Point2_t const &timeWindow, const unsigned short plane, HitStatus_t hitRequest, bool usePeakTime, bool &hitsNear)
float ChgFracBetween(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, Point3_t pos1, Point3_t pos2)
bool FitSection(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, unsigned short sfIndex)
std::vector< VtxStore > vtxs
2D vertices
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
double ConvertXToTicks(double X, int p, int t, int c) const
void CountBadPoints(const TCSlice &slc, const PFPStruct &pfp, unsigned short fromPt, unsigned short toPt, unsigned short &nBadPts, unsigned short &firstBadPt)
std::vector< float > match3DCuts
3D matching cuts
std::vector< SectionFit > SectionFits
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)
double TPXErr2
(X position error)^2
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
const geo::GeometryCore * geom
bool SectionStartEnd(const PFPStruct &pfp, unsigned short sfIndex, unsigned short &startPt, unsigned short &endPt)
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.
constexpr unsigned int pAlgModSize
bool IntersectionPoint(geo::WireID const &wid1, geo::WireID const &wid2, double &y, double &z) const
Returns the intersection point of two wires.
bool SetMag(Vector3_t &v1, double mag)
Definition of data types for geometry description.
float dEdx(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, TP3D &tp3d)
bool valsIncreasing(const SortEntry &c1, const SortEntry &c2)
auto norm(Vector const &v)
Return norm of the specified vector.
std::vector< TCSlice > slices
Detector simulation of raw signals on wires.
void GetRange(const PFPStruct &pfp, unsigned short sfIndex, unsigned short &fromPt, unsigned short &npts)
Q_EXPORT QTSManip setw(int w)
unsigned short InsertTP3D(PFPStruct &pfp, TP3D &tp3d)
SectionFit FitTP3Ds(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const std::vector< TP3D > &tp3ds, unsigned short fromPt, short fitDir, unsigned short nPtsFit)
double ConvertTicksToX(double ticks, int p, int t, int c) const
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
float PointPull(const PFPStruct &pfp, const TP3D &tp3d)
TP3D CreateTP3D(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, int tjID, unsigned short tpIndex)
Declaration of signal hit object.
bool ValidTwoPlaneMatch(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const PFPStruct &pfp)
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
std::vector< Vtx3Store > vtx3s
3D vertices
void FillmAllTraj(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc)
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Encapsulate the construction of a single detector plane.
Contains all timing reference information for the detector.
std::vector< float > pfpStitchCuts
cuts for stitching between TPCs
for(std::string line;std::getline(inFile, line);)
static unsigned int reverse(QString &chars, unsigned char *level, unsigned int a, unsigned int b)
geo::PlaneID DecodeCTP(CTP_t CTP)
float along
distance from the start Pos of the section
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
std::vector< TCWireIntersection > wireIntersections
std::vector< recob::Hit > const * allHits
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
double dEdx_AREA(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, recob::Hit const &hit, double pitch, double T0=0) const
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
unsigned short MVI_Iter
MVI iteration - see FindPFParticles.
std::vector< unsigned int > nWires
std::array< double, 3 > Vector3_t
std::vector< TP3D > TP3Ds
int ID
ID of the recob::Slice (not the sub-slice)
std::array< std::vector< float >, 2 > dEdx
void Match3PlanesSpt(TCSlice &slc, std::vector< MatchStruct > &matVec)
Access the description of detector geometry.
detail::Node< FrameID, bool > PlaneID
static constexpr double pb
void DefinePFPParents(TCSlice &slc, bool prt)
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
void FindPFParticles(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, TCSlice &slc)
std::vector< PFPStruct > pfps
void MoveTPToWire(TrajPoint &tp, float wire)
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
double TPX
X position of the TP or the single hit.
TPCID_t TPC
Index of the TPC within its cryostat.
bool StorePFP(TCSlice &slc, PFPStruct &pfp)
Collection of Physical constants used in LArSoft.
float ChgFracNearEnd(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const PFPStruct &pfp, unsigned short end)
void PrintTP3Ds(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, std::string someText, const TCSlice &slc, const PFPStruct &pfp, short printPts)
Vector3_t DirAtEnd(const PFPStruct &pfp, unsigned short end)
TP3D MakeTP3D(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, const TrajPoint &itp, const TrajPoint &jtp)
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
bool AttachToAnyVertex(TCSlice &slc, PFPStruct &pfp, float maxSep, bool prt)
constexpr TPCID()=default
Default constructor: an invalid TPC ID.
bool Update(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, bool prt)
Encapsulate the construction of a single detector plane.
std::array< std::bitset< 8 >, 2 > EndFlag
bool SptInTPC(const std::array< unsigned int, 3 > &sptHits, unsigned int tpc)
bool valsDecreasing(const SortEntry &c1, const SortEntry &c2)
bool HasWire(geo::WireID const &wireid) const
Returns whether we have the specified wire.
unsigned short SFIndex
and the section fit index