3 #include "messagefacility/MessageLogger/MessageLogger.h"
5 #include "TDecompSVD.h"
38 using namespace detail;
46 if (
slices.size() < 2)
return;
54 mf::LogVerbatim myprt(
"TC");
55 std::string fcnLabel =
"SP";
58 bool printHeader =
true;
59 for (
size_t isl = 0; isl <
slices.size(); ++isl) {
62 if (slc.pfps.empty())
continue;
63 for (
auto& pfp : slc.pfps)
64 PrintP(fcnLabel, myprt, pfp, printHeader);
69 std::vector<std::vector<int>> stLists;
70 for (std::size_t sl1 = 0; sl1 <
slices.size() - 1; ++sl1) {
72 for (std::size_t sl2 = sl1 + 1; sl2 <
slices.size(); ++sl2) {
75 if (slc1.ID != slc2.ID)
continue;
76 for (
auto&
p1 : slc1.pfps) {
77 if (
p1.ID <= 0)
continue;
79 if (
p1.PDGCode == 1111)
continue;
80 for (
auto& p2 : slc2.pfps) {
81 if (p2.ID <= 0)
continue;
83 if (p2.PDGCode == 1111)
continue;
87 for (
unsigned short e1 = 0;
e1 < 2; ++
e1) {
92 for (
unsigned short e2 = 0; e2 < 2; ++e2) {
95 if (
InsideFV(slc2, p2, e2))
continue;
97 float sep =
PosSep2(pos1, pos2);
98 if (sep > maxSep2)
continue;
100 if (cth < maxCth)
continue;
106 if (!gotit)
continue;
108 mf::LogVerbatim myprt(
"TC");
109 myprt <<
"Stitch slice " << slc1.ID <<
" P" <<
p1.UID <<
" TPC " <<
p1.TPCID.TPC;
110 myprt <<
" and P" << p2.UID <<
" TPC " << p2.TPCID.TPC;
111 myprt <<
" sep " << sqrt(maxSep2) <<
" maxCth " << maxCth;
115 for (
auto& pm : stLists) {
116 bool p1InList = (std::find(pm.begin(), pm.end(),
p1.UID) != pm.end());
117 bool p2InList = (std::find(pm.begin(), pm.end(), p2.UID) != pm.end());
118 if (p1InList || p2InList) {
119 if (p1InList) pm.push_back(p2.UID);
120 if (p2InList) pm.push_back(
p1.UID);
126 std::vector<int> tmp(2);
129 stLists.push_back(tmp);
135 if (stLists.empty())
return;
137 for (
auto& stl : stLists) {
140 std::pair<unsigned short, unsigned short> minZIndx;
141 unsigned short minZEnd = 2;
142 for (
auto puid : stl) {
144 if (slcIndex.first == USHRT_MAX)
continue;
145 auto& pfp =
slices[slcIndex.first].pfps[slcIndex.second];
146 for (
unsigned short end = 0;
end < 2; ++
end) {
155 if (minZEnd > 1)
continue;
157 auto& pfp =
slices[minZIndx.first].pfps[minZIndx.second];
158 if (prt) mf::LogVerbatim(
"TC") <<
"SP: P" << pfp.UID;
160 for (
auto puid : stl) {
161 if (puid == pfp.UID)
continue;
163 if (sIndx.first == USHRT_MAX)
continue;
164 auto& opfp =
slices[sIndx.first].pfps[sIndx.second];
165 if (prt) mf::LogVerbatim(
"TC") <<
" +P" << opfp.UID;
166 pfp.TjUIDs.insert(pfp.TjUIDs.end(), opfp.TjUIDs.begin(), opfp.TjUIDs.end());
167 if (prt) mf::LogVerbatim();
169 if (opfp.ParentUID > 0) {
171 if (pSlcIndx.first <
slices.size()) {
172 auto& parpfp =
slices[pSlcIndx.first].pfps[pSlcIndx.second];
173 std::replace(parpfp.DtrUIDs.begin(), parpfp.DtrUIDs.begin(), opfp.UID, pfp.UID);
176 for (
auto dtruid : opfp.DtrUIDs) {
178 if (dSlcIndx.first <
slices.size()) {
179 auto& dtrpfp =
slices[dSlcIndx.first].pfps[dSlcIndx.second];
180 dtrpfp.ParentUID = pfp.UID;
202 for (
auto& tj : slc.
tjs) {
203 for (
auto& tp : tj.Pts)
210 std::vector<MatchStruct> matVec;
217 unsigned short maxNit = 2;
218 if (slc.
nPlanes == 2) maxNit = 1;
222 for (
unsigned short nit = 0; nit < maxNit; ++nit) {
224 if (slc.
nPlanes == 3 && nit == 0) {
232 if (matVec.empty())
continue;
234 mf::LogVerbatim myprt(
"TC");
235 myprt <<
"nit " << nit <<
" MVI Count Tjs\n";
236 for (
unsigned int indx = 0; indx < matVec.size(); ++indx) {
237 auto& ms = matVec[indx];
238 myprt << std::setw(5) << indx << std::setw(6) << (int)ms.Count;
239 for (
auto tid : ms.TjIDs)
240 myprt <<
" T" << tid;
243 for (
auto tid : ms.TjIDs) {
244 auto& tj = slc.
tjs[tid - 1];
247 float frac = ms.Count / tpCnt;
248 myprt <<
" matFrac " << std::fixed << std::setprecision(3) << frac;
257 for (
auto& pfp : slc.
pfps)
259 PrintTP3Ds(clockData, detProp,
"FPFP", slc, pfp, -1);
271 std::vector<MatchStruct> matVec,
272 unsigned short matVec_Iter)
275 if (matVec.empty())
return;
280 for (std::size_t indx = 0; indx < matVec.size(); ++indx) {
283 if (foundMVI) prt =
true;
284 auto& ms = matVec[indx];
286 std::cout <<
"found MVI " << indx <<
" in MakePFParticles ms.Count = " << ms.Count <<
"\n";
289 if (ms.Count == 0)
continue;
292 for (std::size_t itj = 0; itj < ms.TjIDs.size(); ++itj) {
293 auto& tj = slc.
tjs[ms.TjIDs[itj] - 1];
294 for (
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt)
295 if (tj.Pts[ipt].InPFP == 0) ++npts;
298 std::vector<PFPStruct> pfpVec(1);
301 pfpVec[0].TjIDs = ms.TjIDs;
302 pfpVec[0].MVI = indx;
305 if (!
MakeTP3Ds(detProp, slc, pfpVec[0], foundMVI)) {
306 if (foundMVI) mf::LogVerbatim(
"TC") <<
" MakeTP3Ds failed. Too many points already used ";
310 if (!
FitSection(clockData, detProp, slc, pfpVec[0], 0))
continue;
311 if (pfpVec[0].SectionFits[0].ChiDOF > 500 && !pfpVec[0].Flags[
kSmallAngle]) {
313 mf::LogVerbatim(
"TC") <<
" crazy high ChiDOF P" << pfpVec[0].ID <<
" "
314 << pfpVec[0].SectionFits[0].ChiDOF <<
"\n";
315 Recover(clockData, detProp, slc, pfpVec[0], foundMVI);
323 npts = pfpVec[0].TP3Ds.size();
324 pfpVec[0].AlgMod[
kJunk3D] = (npts < 20 &&
MCSMom(slc, pfpVec[0].TjIDs) < 50) || (npts < 10);
326 auto& pfp = pfpVec[0];
327 mf::LogVerbatim myprt(
"TC");
328 myprt <<
" indx " << matVec_Iter <<
"/" << indx <<
" Count " << std::setw(5)
330 myprt <<
" P" << pfpVec[0].ID;
332 for (
auto& tjid : pfp.TjIDs)
333 myprt <<
" T" << tjid;
334 myprt <<
" projInPlane";
335 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
336 CTP_t inCTP =
EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
337 auto tp =
MakeBareTP(detProp, slc, pfp.SectionFits[0].Pos, pfp.SectionFits[0].Dir, inCTP);
338 myprt <<
" " << std::setprecision(2) << tp.Delta;
340 myprt <<
" maxTjLen " << (int)
MaxTjLen(slc, pfp.TjIDs);
341 myprt <<
" MCSMom " <<
MCSMom(slc, pfp.TjIDs);
342 myprt <<
" PDGCodeVote " <<
PDGCodeVote(clockData, detProp, slc, pfp);
343 myprt <<
" nTP3Ds " << pfp.TP3Ds.size();
344 myprt <<
" Reco3DRange "
347 if (foundMVI) {
PrintTP3Ds(clockData, detProp,
"FF", slc, pfpVec[0], -1); }
348 for (
unsigned short ip = 0; ip < pfpVec.size(); ++ip) {
349 auto& pfp = pfpVec[ip];
352 for (
unsigned short end = 0;
end < 2; ++
end) {
354 pfp.EndFlag[
end].reset();
360 pfp.EndFlag[0][
kAtKink] =
true;
363 vx3.
X = pfp.TP3Ds[0].Pos[0];
364 vx3.
Y = pfp.TP3Ds[0].Pos[1];
365 vx3.
Z = pfp.TP3Ds[0].Pos[2];
374 slc.
vtx3s.push_back(vx3);
375 pfp.Vx3ID[0] = vx3.
ID;
376 auto& prevPFP = slc.
pfps[slc.
pfps.size() - 1];
377 prevPFP.Vx3ID[1] = vx3.
ID;
382 if (pfp.TjIDs.size() == 2 && slc.
nPlanes == 3 && pfp.TP3Ds.size() > 20 &&
397 if (!
ReSection(clockData, detProp, slc, pfp, foundMVI))
continue;
399 if (foundMVI) {
PrintTP3Ds(clockData, detProp,
"RS", slc, pfp, -1); }
404 FillGaps3D(clockData, detProp, slc, pfp, foundMVI);
410 for (
auto& tp3d : pfp.TP3Ds) {
412 auto& tp = slc.
tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
415 FilldEdx(clockData, detProp, slc, pfp);
416 pfp.PDGCode =
PDGCodeVote(clockData, detProp, slc, pfp);
418 PrintTP3Ds(clockData, detProp,
"STORE", slc, pfp, -1);
436 if (pfp.
TjIDs.empty())
return false;
437 if (pfp.
TP3Ds.empty())
return false;
438 if (pfp.
ID <= 0)
return false;
441 std::vector<std::pair<int, float>> tjTPCnt;
442 for (
auto& tp3d : pfp.
TP3Ds) {
444 if (tp3d.TjID <= 0)
return false;
446 auto& tp = slc.
tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
447 if (tp.InPFP > 0 && tp.InPFP != pfp.
ID)
return false;
449 unsigned short indx = 0;
450 for (indx = 0; indx < tjTPCnt.size(); ++indx)
451 if (tjTPCnt[indx].
first == tp3d.TjID)
break;
452 if (indx == tjTPCnt.size()) tjTPCnt.push_back(std::make_pair(tp3d.TjID, 0));
453 ++tjTPCnt[indx].second;
458 std::vector<int> nTjIDs;
459 for (
auto& tjtpcnt : tjTPCnt) {
460 auto& tj = slc.
tjs[tjtpcnt.first - 1];
462 if (tjtpcnt.second > 0.8 * npwc) nTjIDs.push_back(tjtpcnt.first);
464 if (prt) { mf::LogVerbatim(
"TC") <<
"RTPs3D: P" << pfp.
ID <<
" nTjIDs " << nTjIDs.size(); }
466 if (nTjIDs.size() < 2) {
return false; }
486 std::vector<int> TinP;
487 for (
auto& pfp : slc.
pfps) {
488 if (pfp.ID <= 0)
continue;
490 for (std::size_t ipt = 0; ipt < pfp.TP3Ds.size(); ++ipt) {
491 auto& tp3d = pfp.TP3Ds[ipt];
492 if (tp3d.TjID <= 0)
continue;
493 if (std::find(TinP.begin(), TinP.end(), tp3d.TjID) == TinP.end()) TinP.push_back(tp3d.TjID);
494 auto& tp = slc.
tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
521 std::vector<int> killme;
522 for (
auto& pfp : slc.
pfps) {
523 if (pfp.ID <= 0)
continue;
524 for (
auto& tp3d : pfp.TP3Ds) {
525 if (tp3d.TjID <= 0)
continue;
527 if (std::find(killme.begin(), killme.end(), tp3d.TjID) == killme.end())
528 killme.push_back(tp3d.TjID);
534 for (
auto tid : killme)
539 std::vector<Trajectory> ptjs(slc.
nPlanes);
541 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
542 ptjs[plane].Pass = 0;
545 ptjs[plane].StepDir = 0;
549 ptjs[plane].AlgMod[
kMat3D] =
true;
553 for (
auto& pfp : slc.
pfps) {
554 if (pfp.ID <= 0)
continue;
556 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
557 ptjs[plane].Pts.clear();
565 for (
auto& tp3d : pfp.TP3Ds) {
566 if (tp3d.TjID <= 0)
continue;
569 auto tp = slc.
tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
570 if (tp.InPFP > 0 && tp.InPFP != pfp.ID)
continue;
576 ptjs[plane].Pts.push_back(tp);
580 std::vector<int> tids(ptjs.size(), 0);
581 for (
unsigned short plane = 0; plane < ptjs.size(); ++plane) {
582 auto& tj = ptjs[plane];
583 if (tj.Pts.size() < 2)
continue;
584 tj.PDGCode = pfp.PDGCode;
585 tj.MCSMom =
MCSMom(slc, tj);
588 auto& newTj = slc.
tjs.back();
589 pfp.TjIDs.push_back(newTj.ID);
590 tids[plane] = newTj.ID;
593 for(
unsigned short end = 0;
end < 2; ++
end) {
594 if(pfp.Vx3ID[
end] <= 0)
continue;
595 auto& vx3 = slc.
vtx3s[pfp.Vx3ID[
end] - 1];
596 for(
unsigned short plane = 0; plane < ptjs.size(); ++plane) {
597 if(tids[plane] == 0)
continue;
598 if(vx3.Vx2ID[plane] <= 0)
continue;
599 auto& vx2 = slc.
vtxs[vx3.Vx2ID[plane] - 1];
600 auto& tj = slc.
tjs[tids[plane] - 1];
601 auto tend =
CloseEnd(slc, tj, vx2.Pos);
602 tj.VtxID[tend] = vx2.ID;
603 if(prt) mf::LogVerbatim(
"TC") <<
"MPFPTjs: 3V" << vx3.ID <<
" -> 2V" << vx2.ID
604 <<
" -> T" << tj.ID <<
"_" << tend <<
" in plane " << plane;
624 unsigned int maxWire = slc.
nWires[0];
625 for (
auto nw : slc.
nWires)
626 if (nw < maxWire) maxWire = nw;
628 unsigned int firstWire = maxWire / 2;
631 std::vector<std::pair<unsigned short, unsigned short>> pln1pln2;
632 for (
unsigned short pln1 = 0; pln1 < slc.
nPlanes - 1; ++pln1) {
633 for (
unsigned short pln2 = pln1 + 1; pln2 < slc.
nPlanes; ++pln2) {
634 auto p1p2 = std::make_pair(pln1, pln2);
635 if (std::find(pln1pln2.begin(), pln1pln2.end(), p1p2) != pln1pln2.end())
continue;
637 for (
unsigned int wire = firstWire; wire < maxWire; ++wire) {
656 tcwi.
dydw1 = (y10 - y00) / 10;
657 tcwi.
dzdw1 = (z10 - z00) / 10;
658 tcwi.
dydw2 = (y01 - y00) / 10;
659 tcwi.
dzdw2 = (z01 - z00) / 10;
679 if (pln1 == pln2)
return false;
682 std::swap(pln1, pln2);
683 std::swap(wir1, wir2);
687 if (wi.pln1 != pln1)
continue;
688 if (wi.pln2 != pln2)
continue;
690 double dw1 = wir1 - wi.wir1;
691 double dw2 = wir2 - wi.wir2;
692 y = (float)(wi.y + dw1 * wi.dydw1 + dw2 * wi.dydw2);
693 z = (float)(wi.z + dw1 * wi.dzdw1 + dw2 * wi.dzdw2);
707 std::vector<int> inTraj((*
evt.
allHits).size(), 0);
708 for (
auto& tch : slc.
slHits)
709 inTraj[tch.allHitsIndex] = tch.InTraj;
712 std::array<int, 3> tIDs;
714 std::vector<std::array<int, 3>> mtIDs;
716 std::vector<unsigned short> mCnt;
718 unsigned short maxCnt = USHRT_MAX;
721 std::vector<unsigned short> tMaxed;
726 if (sptHits.size() != 3)
continue;
728 if (!
SptInTPC(sptHits, tpc))
continue;
729 unsigned short cnt = 0;
730 for (
unsigned short plane = 0; plane < 3; ++plane) {
731 unsigned int iht = sptHits[plane];
732 if (iht == UINT_MAX)
continue;
733 if (inTraj[iht] <= 0)
continue;
734 tIDs[plane] = inTraj[iht];
737 if (cnt != 3)
continue;
739 unsigned short indx = 0;
740 for (indx = 0; indx < mtIDs.size(); ++indx)
741 if (tIDs == mtIDs[indx])
break;
742 if (indx == mtIDs.size()) {
744 mtIDs.push_back(tIDs);
748 if (mCnt[indx] == maxCnt) {
750 tMaxed.insert(tMaxed.end(), tIDs[0]);
751 tMaxed.insert(tMaxed.end(), tIDs[1]);
752 tMaxed.insert(tMaxed.end(), tIDs[2]);
758 std::vector<SortEntry> sortVec;
759 for (
unsigned short indx = 0; indx < mCnt.size(); ++indx) {
760 auto& tIDs = mtIDs[indx];
762 float minTPCnt = USHRT_MAX;
763 for (
auto tid : tIDs) {
764 auto& tj = slc.
tjs[tid - 1];
766 if (tpcnt < minTPCnt) minTPCnt = tpcnt;
768 float frac = (float)mCnt[indx] / minTPCnt;
770 if (frac < 0.05)
continue;
774 sortVec.push_back(se);
776 if (sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(),
valsDecreasing);
778 matVec.resize(sortVec.size());
780 for (
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
781 unsigned short indx = sortVec[ii].index;
782 auto& ms = matVec[ii];
783 ms.Count = mCnt[indx];
785 for (
unsigned short plane = 0; plane < 3; ++plane)
786 ms.TjIDs[plane] = mtIDs[indx][plane];
793 SptInTPC(
const std::array<unsigned int, 3>& sptHits,
unsigned int tpc)
798 unsigned int ahi = UINT_MAX;
799 for (
auto ii : sptHits)
800 if (ii != UINT_MAX) {
804 if (ahi >= (*
evt.
allHits).size())
return false;
807 if (
hit.WireID().TPC == tpc)
return true;
831 std::array<unsigned short, 3> tIDs;
833 std::vector<std::array<unsigned short, 3>> mtIDs;
835 std::vector<unsigned short> mCnt;
837 unsigned short maxCnt = USHRT_MAX;
840 std::vector<unsigned short> tMaxed;
842 for (std::size_t ipt = 0; ipt < slc.
mallTraj.size() - 1; ++ipt) {
845 if (std::find(tMaxed.begin(), tMaxed.end(), iTjPt.id) != tMaxed.end())
continue;
846 auto& itp = slc.
tjs[iTjPt.id - 1].Pts[iTjPt.ipt];
847 unsigned int iPlane = iTjPt.plane;
848 unsigned int iWire = std::nearbyint(itp.Pos[0]);
849 tIDs[iPlane] = iTjPt.id;
850 bool hitMaxCnt =
false;
851 for (std::size_t jpt = ipt + 1; jpt < slc.
mallTraj.size() - 1; ++jpt) {
854 if (jTjPt.plane == iTjPt.plane)
continue;
856 if (jTjPt.xlo > iTjPt.xhi)
continue;
858 if (jTjPt.xlo > iTjPt.xhi + xcut)
break;
860 if (std::find(tMaxed.begin(), tMaxed.end(), jTjPt.id) != tMaxed.end())
continue;
861 auto& jtp = slc.
tjs[jTjPt.id - 1].Pts[jTjPt.ipt];
862 unsigned short jPlane = jTjPt.plane;
863 unsigned int jWire = jtp.Pos[0];
866 tIDs[jPlane] = jTjPt.id;
867 for (std::size_t kpt = jpt + 1; kpt < slc.
mallTraj.size(); ++kpt) {
870 if (kTjPt.plane == iTjPt.plane || kTjPt.plane == jTjPt.plane)
continue;
871 if (kTjPt.xlo > iTjPt.xhi)
continue;
873 if (kTjPt.xlo > iTjPt.xhi + xcut)
break;
875 if (std::find(tMaxed.begin(), tMaxed.end(), kTjPt.id) != tMaxed.end())
continue;
876 auto& ktp = slc.
tjs[kTjPt.id - 1].Pts[kTjPt.ipt];
877 unsigned short kPlane = kTjPt.plane;
878 unsigned int kWire = ktp.Pos[0];
881 if (
std::abs(ijPos[0] - ikPos[0]) > yzcut)
continue;
882 if (
std::abs(ijPos[1] - ikPos[1]) > yzcut)
continue;
886 unsigned int indx = 0;
887 for (indx = 0; indx < mtIDs.size(); ++indx)
888 if (tIDs == mtIDs[indx])
break;
889 if (indx == mtIDs.size()) {
891 mtIDs.push_back(tIDs);
895 if (mCnt[indx] == maxCnt) {
897 tMaxed.insert(tMaxed.end(), tIDs[0]);
898 tMaxed.insert(tMaxed.end(), tIDs[1]);
899 tMaxed.insert(tMaxed.end(), tIDs[2]);
904 if (hitMaxCnt)
break;
908 if (mCnt.empty())
return;
910 std::vector<SortEntry> sortVec;
911 for (std::size_t indx = 0; indx < mCnt.size(); ++indx) {
912 auto& tIDs = mtIDs[indx];
915 for (
auto tid : tIDs) {
916 auto& tj = slc.
tjs[tid - 1];
919 float frac = mCnt[indx] / tpCnt;
922 if (frac < 0.05)
continue;
926 sortVec.push_back(se);
928 if (sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(),
valsDecreasing);
930 matVec.resize(sortVec.size());
932 for (std::size_t ii = 0; ii < sortVec.size(); ++ii) {
933 unsigned short indx = sortVec[ii].index;
934 auto& ms = matVec[ii];
935 ms.Count = mCnt[indx];
937 for (
unsigned short plane = 0; plane < 3; ++plane)
938 ms.TjIDs[plane] = (
int)mtIDs[indx][plane];
958 std::array<unsigned short, 2> tIDs;
960 std::vector<std::array<unsigned short, 2>> mtIDs;
962 std::vector<unsigned short> mCnt;
964 unsigned short maxCnt = USHRT_MAX;
967 std::vector<unsigned short> tMaxed;
969 for (std::size_t ipt = 0; ipt < slc.
mallTraj.size() - 1; ++ipt) {
972 if (std::find(tMaxed.begin(), tMaxed.end(), iTjPt.id) != tMaxed.end())
continue;
973 auto& itp = slc.
tjs[iTjPt.id - 1].Pts[iTjPt.ipt];
974 unsigned short iPlane = iTjPt.plane;
975 unsigned int iWire = itp.Pos[0];
976 bool hitMaxCnt =
false;
977 for (std::size_t jpt = ipt + 1; jpt < slc.
mallTraj.size() - 1; ++jpt) {
980 if (jTjPt.plane == iTjPt.plane)
continue;
982 if (jTjPt.xlo > iTjPt.xhi)
continue;
984 if (jTjPt.xlo > iTjPt.xhi + xcut)
break;
986 if (std::find(tMaxed.begin(), tMaxed.end(), jTjPt.id) != tMaxed.end())
continue;
987 auto& jtp = slc.
tjs[jTjPt.id - 1].Pts[jTjPt.ipt];
988 unsigned short jPlane = jTjPt.plane;
989 unsigned int jWire = jtp.Pos[0];
991 ijPos[0] = itp.Pos[0];
993 iWire, jWire, iPlane, jPlane, cstat, tpc, ijPos[1], ijPos[2]))
998 if (tIDs[0] > tIDs[1]) std::swap(tIDs[0], tIDs[1]);
1000 std::size_t indx = 0;
1001 for (indx = 0; indx < mtIDs.size(); ++indx)
1002 if (tIDs == mtIDs[indx])
break;
1003 if (indx == mtIDs.size()) {
1005 mtIDs.push_back(tIDs);
1009 if (mCnt[indx] == maxCnt) {
1011 tMaxed.insert(tMaxed.end(), tIDs[0]);
1012 tMaxed.insert(tMaxed.end(), tIDs[1]);
1016 if (hitMaxCnt)
break;
1020 if (mCnt.empty())
return;
1022 std::vector<SortEntry> sortVec;
1023 for (std::size_t indx = 0; indx < mCnt.size(); ++indx) {
1024 auto& tIDs = mtIDs[indx];
1027 for (
auto tid : tIDs) {
1028 auto& tj = slc.
tjs[tid - 1];
1031 float frac = mCnt[indx] / tpCnt;
1034 if (frac < 0.05)
continue;
1037 se.
val = mCnt[indx];
1038 sortVec.push_back(se);
1040 if (sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(),
valsDecreasing);
1042 matVec.resize(sortVec.size());
1044 for (std::size_t ii = 0; ii < sortVec.size(); ++ii) {
1045 unsigned short indx = sortVec[ii].index;
1046 auto& ms = matVec[ii];
1047 ms.Count = mCnt[indx];
1049 for (
unsigned short plane = 0; plane < 2; ++plane)
1050 ms.TjIDs[plane] = (
int)mtIDs[indx][plane];
1069 for(
unsigned short sfi = 0; sfi < pfp.
SectionFits.size(); ++sfi) {
1071 if (!sf.NeedsUpdate)
continue;
1075 for(
unsigned short ipt = 0; ipt < pfp.
TP3Ds.size(); ++ipt) {
1076 auto& tp3d = pfp.
TP3Ds[ipt];
1077 if(tp3d.SFIndex < sfi)
continue;
1078 if(tp3d.SFIndex > sfi)
break;
1080 double delta = tp3d.Pos[0] - tp3d.TPX;
1081 sf.ChiDOF += delta * delta / tp3d.TPXErr2;
1086 sf.ChiDOF /= (float)(sf.NPts - 4);
1088 sf.NeedsUpdate =
false;
1094 for (std::size_t sfi = 0; sfi < pfp.
SectionFits.size(); ++sfi) {
1096 if (!sf.NeedsUpdate)
continue;
1097 if (!
FitSection(clockData, detProp, slc, pfp, sfi))
return false;
1099 sf.NeedsUpdate =
false;
1103 for (
auto& tp3d : pfp.
TP3Ds) {
1127 if (pfp.
TP3Ds.size() < 12) {
1143 for (
auto& tp3d : pfp.
TP3Ds) {
1148 if (!
FitSection(clockData, detProp, slc, pfp, 0)) {
return false; }
1154 unsigned short min2DPts = 3;
1155 unsigned short fromPt = 0;
1157 for (
auto& tp3d : pfp.
TP3Ds)
1158 tp3d.SFIndex = USHRT_MAX;
1160 unsigned short nPtsToAdd = pfp.
TP3Ds.size() / 4;
1162 unsigned short nPts = nPtsToAdd;
1164 unsigned short nPtsMin =
Find3DRecoRange(slc, pfp, fromPt, min2DPts, 1) - fromPt + 1;
1165 if (nPtsMin >= pfp.
TP3Ds.size()) {
1170 if (nPts < nPtsMin) nPts = nPtsMin;
1172 if (pfp.
TP3Ds.size() > 100) {
1173 unsigned short nhalf = pfp.
TP3Ds.size() / 2;
1174 FitTP3Ds(detProp, slc, pfp, fromPt, nhalf, USHRT_MAX, chiDOF);
1177 bool lastSection =
false;
1178 for (
unsigned short sfIndex = 0; sfIndex < 20; ++sfIndex) {
1180 float chiDOFPrev = 0;
1182 for (
unsigned short nit = 0; nit < 10; ++nit) {
1184 unsigned short nPtsNext = nPts;
1185 if (!
FitTP3Ds(detProp, slc, pfp, fromPt, nPts, USHRT_MAX, chiDOF)) {
1186 nPtsNext += 1.5 * nPtsToAdd;
1188 else if (chiDOF < chiLo) {
1195 nPtsNext += nPtsToAdd;
1199 else if (chiDOF > chiHi) {
1208 short npnext = (short)nPts - nHiChi * 5;
1211 if (npnext > nPtsMin) nPtsNext = npnext;
1219 if (fromPt + nPtsNext >= pfp.
TP3Ds.size()) {
1220 nPtsNext = pfp.
TP3Ds.size() - fromPt;
1224 mf::LogVerbatim myprt(
"TC");
1225 myprt <<
" RS: P" << pfp.
ID <<
" sfi/nit/npts " << sfIndex <<
"/" << nit <<
"/" << nPts;
1226 myprt << std::fixed << std::setprecision(1) <<
" chiDOF " << chiDOF;
1227 myprt <<
" fromPt " << fromPt;
1228 myprt <<
" nPtsNext " << nPtsNext;
1229 myprt <<
" nHiChi " << nHiChi;
1230 myprt <<
" lastSection? " << lastSection;
1232 if (nPtsNext == 0)
break;
1234 if (lastSection)
break;
1235 if (chiDOF == chiDOFPrev) {
1236 if (prt) mf::LogVerbatim(
"TC") <<
" MVI " << pfp.
MVI <<
" chiDOF not changing\n";
1240 chiDOFPrev = chiDOF;
1243 unsigned short toPt = fromPt + nPts;
1244 if (toPt > pfp.
TP3Ds.size()) toPt = pfp.
TP3Ds.size();
1245 for (
unsigned short ipt = fromPt; ipt < toPt; ++ipt)
1246 pfp.
TP3Ds[ipt].SFIndex = sfIndex;
1251 unsigned short nextFromPt = fromPt + nPts;
1253 unsigned short nextToPtMin =
Find3DRecoRange(slc, pfp, nextFromPt, min2DPts, 1);
1254 if (nextToPtMin == USHRT_MAX) {
1258 for (std::size_t ipt = nextFromPt; ipt < pfp.
TP3Ds.size(); ++ipt)
1259 pfp.
TP3Ds[ipt].SFIndex = sfIndex;
1263 FitSection(clockData, detProp, slc, pfp, sfIndex);
1265 if (lastSection)
break;
1267 fromPt = fromPt + nPts;
1269 nPtsMin =
Find3DRecoRange(slc, pfp, fromPt, min2DPts, 1) - fromPt + 1;
1270 if (nPtsMin >= pfp.
TP3Ds.size())
break;
1277 unsigned short badSFI = pfp.
SectionFits.size() - 1;
1280 for (std::size_t ipt = pfp.
TP3Ds.size() - 1; ipt > 0; --ipt) {
1281 auto& tp3d = pfp.
TP3Ds[ipt];
1282 if (tp3d.SFIndex < badSFI)
break;
1289 for (std::size_t ipt = pfp.
TP3Ds.size() - 1; ipt > 0; --ipt) {
1290 auto& tp3d = pfp.
TP3Ds[ipt];
1297 Update(clockData, detProp, slc, pfp, prt);
1311 unsigned short fromPt,
1312 unsigned short toPt,
1313 unsigned short& nBadPts,
1314 unsigned short& firstBadPt)
1317 firstBadPt = USHRT_MAX;
1319 if (fromPt > pfp.
TP3Ds.size() - 1) {
1320 nBadPts = USHRT_MAX;
1323 if (toPt > pfp.
TP3Ds.size()) toPt = pfp.
TP3Ds.size();
1325 for (
unsigned short ipt = fromPt; ipt < toPt; ++ipt) {
1326 auto& tp3d = pfp.
TP3Ds[ipt];
1330 auto& tp = slc.
tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
1349 if (pfp.
TP3Ds.size() < 12)
return false;
1351 if (toPt > pfp.
TP3Ds.size())
return false;
1353 if (nextToPt > pfp.
TP3Ds.size())
return false;
1361 unsigned short fromPt,
1362 unsigned short min2DPts,
1368 if (fromPt > pfp.
TP3Ds.size() - 1)
return USHRT_MAX;
1369 if (pfp.
TP3Ds.size() < 2 * min2DPts)
return USHRT_MAX;
1370 if (dir == 0)
return USHRT_MAX;
1372 std::vector<unsigned short> cntInPln(slc.
nPlanes);
1373 for (std::size_t ii = 0; ii < pfp.
TP3Ds.size(); ++ii) {
1374 unsigned short ipt = fromPt + ii;
1375 if (dir < 0) ipt = fromPt - ii;
1376 if (ipt >= pfp.
TP3Ds.size())
break;
1377 auto& tp3d = pfp.
TP3Ds[ipt];
1381 unsigned short enufInPlane = 0;
1382 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane)
1383 if (cntInPln[plane] >= min2DPts) ++enufInPlane;
1384 if (enufInPlane > 1)
return ipt + 1;
1385 if (dir < 0 && ipt == 0)
break;
1393 unsigned short sfIndex,
1394 unsigned short& fromPt,
1395 unsigned short& npts)
1399 if (pfp.
TP3Ds.empty())
return;
1403 for (std::size_t ipt = 0; ipt < pfp.
TP3Ds.size(); ++ipt) {
1404 auto& tp3d = pfp.
TP3Ds[ipt];
1405 if (tp3d.SFIndex < sfIndex)
continue;
1406 if (tp3d.SFIndex > sfIndex)
break;
1407 if (fromPt == USHRT_MAX) fromPt = ipt;
1418 unsigned short sfIndex)
1422 if (pfp.
TP3Ds.size() < 4)
return false;
1423 if (sfIndex >= pfp.
SectionFits.size())
return false;
1427 unsigned short fromPt = USHRT_MAX;
1428 unsigned short npts = 0;
1429 GetRange(pfp, sfIndex, fromPt, npts);
1430 if (fromPt == USHRT_MAX)
return false;
1431 if (npts < 4)
return false;
1434 for (
unsigned short ipt = fromPt; ipt < fromPt + npts; ++ipt) {
1435 auto& tp3d = pfp.
TP3Ds[ipt];
1436 if (tp3d.SFIndex != sfIndex)
return false;
1441 return FitTP3Ds(detProp, slc, pfp, fromPt, npts, sfIndex, chiDOF);
1449 const std::vector<TP3D>& tp3ds,
1450 unsigned short fromPt,
1452 unsigned short nPtsFit)
1459 if (nPtsFit < 5)
return sf;
1460 if (!(fitDir == -1 || fitDir == 1))
return sf;
1461 if (fitDir == 1 && fromPt + nPtsFit > tp3ds.size())
return sf;
1462 if (fitDir == -1 && fromPt < 3)
return sf;
1465 std::vector<std::array<double, 3>> ocs(slc.
nPlanes);
1466 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
1476 const unsigned int nvars = 4;
1477 unsigned int npts = 0;
1480 std::vector<unsigned short> cntInPln(slc.
nPlanes, 0);
1483 for (
short ii = 0; ii < nPtsFit; ++ii) {
1484 short ipt = fromPt + fitDir * ii;
1485 if (ipt < 0 || ipt >= (
short)tp3ds.size())
break;
1486 auto& tp3d = tp3ds[ipt];
1488 if (tp3d.TPXErr2 < 0.0001)
return sf;
1494 if (npts < 6)
return sf;
1496 unsigned short enufInPlane = 0;
1497 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane)
1498 if (cntInPln[plane] > 2) ++enufInPlane;
1499 if (enufInPlane < 2)
return sf;
1503 TMatrixD
A(npts, nvars);
1506 unsigned short cnt = 0;
1508 for (
short ii = 0; ii < nPtsFit; ++ii) {
1509 short ipt = fromPt + fitDir * ii;
1510 auto& tp3d = tp3ds[ipt];
1513 double x = tp3d.TPX - x0;
1514 A[cnt][0] = weight * ocs[plane][1];
1515 A[cnt][1] = weight * ocs[plane][2];
1516 A[cnt][2] = weight * ocs[plane][1] *
x;
1517 A[cnt][3] = weight * ocs[plane][2] *
x;
1518 w[cnt] = weight * (tp3d.Wire - ocs[plane][0]);
1524 TVectorD tVec = svd.Solve(w, ok);
1526 double norm = sqrt(1 + tVec[2] * tVec[2] + tVec[3] * tVec[3]);
1534 sf.
Pos[1] = tVec[0];
1535 sf.
Pos[2] = tVec[1];
1540 TMatrixD AT(nvars, npts);
1542 TMatrixD ATA = AT *
A;
1544 try{ ATA.Invert(det); }
1545 catch(...) {
return sf; }
1552 std::vector<TrajPoint> plnTP(slc.
nPlanes);
1553 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
1560 for (
short ii = 0; ii < nPtsFit; ++ii) {
1561 short ipt = fromPt + fitDir * ii;
1562 auto& tp3d = tp3ds[ipt];
1565 double dw = tp3d.Wire - plnTP[plane].Pos[0];
1567 double t = dw * plnTP[plane].DeltaRMS;
1568 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
1569 pos[xyz] = sf.
Pos[xyz] + t * sf.
Dir[xyz];
1573 double delta = pos[0] - tp3d.TPX;
1574 sf.
ChiDOF += delta * delta / tp3d.TPXErr2;
1576 double dangErr = delta / dw;
1577 sf.
DirErr[0] += dangErr * dangErr;
1580 sf.
ChiDOF /= (float)(npts - 4);
1590 unsigned short fromPt,
1591 unsigned short nPtsFit,
1592 unsigned short sfIndex,
1599 if (nPtsFit < 5)
return false;
1600 if (fromPt + nPtsFit > pfp.
TP3Ds.size())
return false;
1602 auto sf =
FitTP3Ds(detProp, slc, pfp.
TP3Ds, fromPt, 1, nPtsFit);
1603 if (sf.ChiDOF > 900)
return false;
1606 if (sfIndex >= pfp.
SectionFits.size())
return true;
1612 std::vector<TrajPoint> plnTP(slc.
nPlanes);
1613 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
1615 plnTP[plane] =
MakeBareTP(detProp, slc, sf.Pos, sf.Dir, inCTP);
1618 bool needsSort =
false;
1619 double prevAlong = 0;
1620 for (
unsigned short ipt = fromPt; ipt < fromPt + nPtsFit; ++ipt) {
1621 auto& tp3d = pfp.
TP3Ds[ipt];
1623 double dw = tp3d.Wire - plnTP[plane].Pos[0];
1625 double t = dw * plnTP[plane].DeltaRMS;
1626 if (ipt == fromPt) { prevAlong = t; }
1628 if (t < prevAlong) needsSort =
true;
1631 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
1632 pos[xyz] = sf.Pos[xyz] + t * sf.Dir[xyz];
1636 double delta = pos[0] - tp3d.TPX;
1640 if (tp3d.Flags[
kTP3DGood]) sf.ChiDOF += delta * delta / tp3d.TPXErr2;
1661 if (pfp.
TP3Ds.empty())
return;
1666 std::vector<int> tjList;
1667 for (
auto& tp3d : pfp.
TP3Ds) {
1670 if (tp3d.TjID <= 0)
continue;
1671 if (std::find(tjList.begin(), tjList.end(), tp3d.TjID) == tjList.end())
1672 tjList.push_back(tp3d.TjID);
1676 std::vector<int> vx2List, vx3List;
1677 for (
auto tid : tjList) {
1678 auto& tj = slc.
tjs[tid - 1];
1679 for (
unsigned short end = 0;
end < 2; ++
end) {
1680 if (tj.VtxID[
end] <= 0)
continue;
1681 auto& vx2 = slc.
vtxs[tj.VtxID[
end] - 1];
1682 if (vx2.Vx3ID > 0) {
1683 if (std::find(vx3List.begin(), vx3List.end(), vx2.Vx3ID) == vx3List.end())
1684 vx3List.push_back(vx2.Vx3ID);
1689 if (std::find(vx2List.begin(), vx2List.end(), tj.VtxID[
end]) == vx2List.end())
1690 vx2List.push_back(tj.VtxID[
end]);
1695 if (vx2List.empty() && vx3List.empty())
return;
1697 mf::LogVerbatim myprt(
"TC");
1698 myprt <<
"RV: P" << pfp.
ID <<
" ->";
1699 for (
auto tid : tjList)
1700 myprt <<
" T" << tid;
1702 for (
auto vid : vx3List)
1703 myprt <<
" 3V" << vid;
1704 if (!vx2List.empty()) {
1706 for (
auto vid : vx2List)
1707 myprt <<
" 2V" << vid;
1715 for (
auto vid : vx2List) {
1716 auto& vx2 = slc.
vtxs[vid - 1];
1725 if (!slc.
pfps.empty()) {
1726 auto& npfp = slc.
pfps[0];
1727 bool neutrinoPFP = (npfp.PDGCode == 12 || npfp.PDGCode == 14);
1728 if (neutrinoPFP) neutrinoVx = npfp.Vx3ID[0];
1730 unsigned short neutrinoVxEnd = 2;
1731 for (
unsigned short end = 0;
end < 2; ++
end) {
1734 if (pfp.
Vx3ID[
end] == neutrinoVx) neutrinoVxEnd =
end;
1736 if (std::find(vx3List.begin(), vx3List.end(), pfp.
Vx3ID[
end]) != vx3List.end())
continue;
1738 if (neutrinoVxEnd < 2 && neutrinoVxEnd != 0)
Reverse(slc, pfp);
1756 if (pfp.
ID <= 0)
return;
1757 if (pfp.
TP3Ds.empty())
return;
1769 unsigned short nPtsAdded = 0;
1770 unsigned short fromPt = 0;
1771 unsigned short toPt = pWork.
TP3Ds.size();
1772 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
1773 CTP_t inCTP =
EncodeCTP(pWork.TPCID.Cryostat, pWork.TPCID.TPC, plane);
1774 unsigned short nWires, nAdd;
1789 if (prt) mf::LogVerbatim(
"TC") <<
"FG3D P" << pWork.ID <<
" added " << nPtsAdded <<
" points";
1790 if (pWork.Flags[
kNeedsUpdate] && !
Update(clockData, detProp, slc, pWork, prt))
return;
1804 if (pfp.
TjIDs.size() != 2)
return false;
1805 if (slc.
nPlanes != 3)
return false;
1806 if (pfp.
TP3Ds.empty())
return false;
1809 std::vector<unsigned short>
planes;
1810 for (
auto tid : pfp.
TjIDs)
1812 unsigned short thirdPlane = 3 - planes[0] - planes[1];
1816 unsigned int wire0 = 0;
1817 if (tp.Pos[0] > 0) wire0 = std::nearbyint(tp.Pos[0]);
1818 if (wire0 > slc.
nWires[thirdPlane]) wire0 = slc.
nWires[thirdPlane];
1820 unsigned short lastPt = pfp.
TP3Ds.size() - 1;
1822 unsigned int wire1 = 0;
1823 if (tp.Pos[0] > 0) wire1 = std::nearbyint(tp.Pos[0]);
1824 if (wire1 > slc.
nWires[thirdPlane]) wire1 = slc.
nWires[thirdPlane];
1825 if (wire0 == wire1)
return !
evt.
goodWire[thirdPlane][wire0];
1826 if (wire1 < wire0) std::swap(wire0, wire1);
1829 int wires = wire1 - wire0;
1830 for (
unsigned int wire = wire0; wire < wire1; ++wire)
1833 return (dead > 0.8 * wires);
1842 unsigned short fromPt,
1843 unsigned short toPt,
1846 unsigned short& nWires,
1847 unsigned short& nAdd,
1856 if (fromPt > toPt)
return;
1857 if (toPt >= pfp.
TP3Ds.size()) toPt = pfp.
TP3Ds.size() - 1;
1862 Average_dEdX(clockData, detProp, slc, pfp, dEdXAve, dEdXRms);
1863 float dEdxMin = 0.5, dEdxMax = 50.;
1864 if (dEdXAve > 0.5) {
1865 dEdxMin = dEdXAve - maxPull * dEdXRms;
1866 if (dEdxMin < 0.5) dEdxMin = 0.5;
1867 dEdxMax = dEdXAve + maxPull * dEdXRms;
1868 if (dEdxMax > 50.) dEdxMax = 50.;
1873 std::vector<TrajPoint> sfTPs;
1875 std::vector<std::pair<int, unsigned short>> tpUsed;
1876 for (
auto& tp3d : pfp.
TP3Ds) {
1877 if (tp3d.CTP != inCTP)
continue;
1878 tpUsed.push_back(std::make_pair(tp3d.TjID, tp3d.TPIndex));
1880 unsigned int toWire = 0;
1881 unsigned int fromWire = UINT_MAX;
1883 unsigned short inSF = USHRT_MAX;
1885 for (
unsigned short ipt = 0; ipt < pfp.
TP3Ds.size(); ++ipt) {
1886 auto& tp3d = pfp.
TP3Ds[ipt];
1888 if (ipt < pfp.
TP3Ds.size() - 1 && tp3d.SFIndex == inSF)
continue;
1890 if (tp3d.CTP == inCTP) {
1892 auto& tp = slc.
tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
1893 sfTPs.push_back(tp);
1894 wire = std::nearbyint(tp.Pos[0]);
1895 if (wire >= slc.
nWires[pln])
break;
1900 auto tp =
MakeBareTP(detProp, slc, tp3d.Pos, tp3d.Dir, inCTP);
1901 wire = std::nearbyint(tp.Pos[0]);
1902 if (wire >= slc.
nWires[pln])
break;
1903 sfTPs.push_back(tp);
1905 if (wire < fromWire) fromWire = wire;
1906 if (wire > toWire) toWire = wire;
1907 inSF = tp3d.SFIndex;
1909 if (sfTPs.empty())
return;
1911 if (sfTPs.size() > 1 && sfTPs[0].Pos[0] > sfTPs.back().Pos[0]) {
1912 std::reverse(sfTPs.begin(), sfTPs.end());
1919 mf::LogVerbatim(
"TC") <<
"APIR: inCTP " << inCTP <<
" fromWire " << fromWire <<
" toWire "
1923 for (
unsigned short subr = 0; subr < sfTPs.size(); ++subr) {
1924 auto& fromTP = sfTPs[subr];
1925 unsigned int toWireInSF = toWire;
1926 if (subr < sfTPs.size() - 1) toWireInSF = std::nearbyint(sfTPs[subr + 1].Pos[0]);
1928 unsigned int fromWire = std::nearbyint(fromTP.Pos[0]);
1929 if (fromWire > toWire)
continue;
1931 mf::LogVerbatim(
"TC") <<
" inCTP " << inCTP <<
" subr " << subr <<
" fromWire " << fromWire
1932 <<
" toWireInSF " << toWireInSF;
1933 for (
unsigned int wire = fromWire; wire <= toWireInSF; ++wire) {
1937 float bestPull = maxPull;
1939 for (
auto iht : fromTP.Hits) {
1940 if (slc.
slHits[iht].InTraj <= 0)
continue;
1942 auto& utj = slc.
tjs[slc.
slHits[iht].InTraj - 1];
1943 unsigned short tpIndex = 0;
1944 for (tpIndex = utj.EndPt[0]; tpIndex <= utj.EndPt[1]; ++tpIndex) {
1945 auto& utp = utj.Pts[tpIndex];
1946 if (utp.Chg <= 0)
continue;
1948 if (std::find(utp.Hits.begin(), utp.Hits.end(), iht) != utp.Hits.end())
break;
1950 if (tpIndex > utj.EndPt[1])
continue;
1952 std::pair<int, unsigned short> tppr = std::make_pair(utj.ID, tpIndex);
1953 if (std::find(tpUsed.begin(), tpUsed.end(), tppr) != tpUsed.end())
continue;
1954 tpUsed.push_back(tppr);
1955 auto& utp = utj.Pts[tpIndex];
1957 if (utp.InPFP > 0)
continue;
1960 auto newTP3D =
CreateTP3D(detProp, slc, utj.
ID, tpIndex);
1961 if (!
SetSection(detProp, slc, pfp, newTP3D))
continue;
1963 newTP3D.Dir = pfp.
SectionFits[newTP3D.SFIndex].Dir;
1965 float dedx =
dEdx(clockData, detProp, slc, newTP3D);
1967 bool useIt = (pull < bestPull && dedx > dEdxMin && dedx < dEdxMax);
1968 if (!useIt)
continue;
1972 if (bestPull < maxPull) {
1973 if (prt && bestPull < 10) {
1974 mf::LogVerbatim myprt(
"TC");
1976 myprt <<
"APIR: P" << pfp.
ID <<
" added TP " <<
PrintPos(slc, tp);
1977 myprt <<
" pull " << std::fixed << std::setprecision(2) << bestPull;
1978 myprt <<
" dx " << bestTP3D.
TPX - bestTP3D.
Pos[0] <<
" in section " << bestTP3D.
SFIndex;
1980 if (
InsertTP3D(pfp, bestTP3D) == USHRT_MAX)
continue;
1994 std::size_t ipt = 0;
1995 for (ipt = 0; ipt < pfp.
TP3Ds.size(); ++ipt)
1997 if (ipt == pfp.
TP3Ds.size())
return USHRT_MAX;
1999 auto lastTP3D = pfp.
TP3Ds.back();
2000 if (ipt == 0 && tp3d.
along < pfp.
TP3Ds[0].along) {
2003 else if (tp3d.
SFIndex == lastTP3D.SFIndex && tp3d.
along > lastTP3D.along) {
2005 pfp.
TP3Ds.push_back(tp3d);
2008 return pfp.
TP3Ds.size() - 1;
2011 for (std::size_t iipt = ipt; iipt < pfp.
TP3Ds.size() - 1; ++iipt) {
2013 if (pfp.
TP3Ds[iipt + 1].SFIndex != tp3d.
SFIndex)
break;
2020 pfp.
TP3Ds.insert(pfp.
TP3Ds.begin() + ipt, tp3d);
2032 if (sfIndex > pfp.
SectionFits.size() - 1)
return false;
2034 if (sf.Pos[0] == 0.0 && sf.Pos[1] == 0.0 && sf.Pos[2] == 0.0)
return false;
2037 std::vector<TP3D> temp;
2039 std::vector<unsigned short> indx;
2041 float prevAlong = 0;
2043 bool needsSort =
false;
2044 for (std::size_t ii = 0; ii < pfp.
TP3Ds.size(); ++ii) {
2045 auto& tp3d = pfp.
TP3Ds[ii];
2046 if (tp3d.SFIndex != sfIndex)
continue;
2049 prevAlong = tp3d.along;
2052 if (tp3d.along < prevAlong) needsSort =
true;
2053 prevAlong = tp3d.along;
2055 temp.push_back(tp3d);
2058 if (temp.empty())
return false;
2060 if (temp.size() == 1)
return true;
2062 sf.NeedsUpdate =
false;
2066 bool contiguous =
true;
2067 for (std::size_t ipt = 1; ipt < indx.size(); ++ipt) {
2068 if (indx[ipt] != indx[ipt - 1] + 1) contiguous =
false;
2070 if (!contiguous) {
return false; }
2072 std::vector<SortEntry> sortVec(temp.size());
2073 for (std::size_t ii = 0; ii < temp.size(); ++ii) {
2074 sortVec[ii].index = ii;
2075 sortVec[ii].val = temp[ii].along;
2078 for (std::size_t ii = 0; ii < temp.size(); ++ii) {
2080 auto& tp3d = pfp.
TP3Ds[indx[ii]];
2081 tp3d = temp[sortVec[ii].index];
2083 sf.NeedsUpdate =
false;
2096 if(pfp.
TP3Ds.size() < 20)
return;
2103 unsigned short halfPt = p2.TP3Ds.size() / 2;
2104 for(
unsigned short ipt = halfPt; ipt < p2.TP3Ds.size(); ++ipt) p2.TP3Ds[ipt].SFIndex = 1;
2107 if(toPt > p2.TP3Ds.size())
return;
2109 if(toPt > p2.TP3Ds.size())
return;
2110 if(!
FitSection(clockData, detProp, slc, p2, 0) || !
FitSection(clockData, detProp, slc, p2, 1)) {
2112 mf::LogVerbatim myprt(
"TC");
2113 myprt <<
"Recover failed MVI " << p2.MVI <<
" in TPC " << p2.TPCID.TPC;
2114 for(
auto tid : p2.TjIDs) myprt <<
" T" << tid;
2118 if(prt) mf::LogVerbatim(
"TC")<<
"Recover: P" << pfp.
ID <<
" success";
2143 unsigned short nJunk = 0;
2144 unsigned short nSA = 0;
2145 for(
unsigned short itj = 0; itj < pfp.
TjIDs.size(); ++itj) {
2146 auto& tj = slc.
tjs[pfp.
TjIDs[itj] - 1];
2147 if(tj.AlgMod[
kJunkTj]) ++nJunk;
2149 unsigned short iptMin = USHRT_MAX;
2150 float posMax = -1E6;
2151 unsigned short iptMax = USHRT_MAX;
2154 for(
unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ++ipt) {
2155 auto& tp = tj.Pts[ipt];
2156 if(tp.Chg <= 0)
continue;
2158 if (tp.InPFP > 0)
continue;
2160 if(tp.Pos[1] > posMax) { posMax = tp.Pos[1]; iptMax = ipt; }
2161 if(tp.Pos[1] < posMin) { posMin = tp.Pos[1]; iptMin = ipt; }
2165 if(npwc == 0)
continue;
2169 if(iptMin > tj.EndPt[0] + 4 && iptMin < tj.EndPt[1] - 4) pfp.
TjUIDs[itj] = iptMin;
2170 if(iptMax > tj.EndPt[0] + 4 && iptMax < tj.EndPt[1] - 4) pfp.
TjUIDs[itj] = iptMax;
2172 if(avail < 0.8 * cnt)
return false;
2175 if(prt) mf::LogVerbatim(
"TC")<<
" P"<<pfp.
ID<<
" MVI "<<pfp.
MVI<<
" nJunkTj "<<nJunk<<
" SmallAngle? "<<pfp.
AlgMod[
kSmallAngle];
2180 for (
auto tid : pfp.
TjIDs) {
2181 auto& tj = slc.
tjs[tid - 1];
2183 if(nJunk == 1 && tj.AlgMod[
kJunkTj])
continue;
2186 bool isJunk = tj.AlgMod[
kJunkTj];
2187 for(
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2188 auto& tp = tj.Pts[ipt];
2189 if (tp.Chg <= 0)
continue;
2190 if (tp.InPFP > 0)
continue;
2192 auto tp3d =
CreateTP3D(detProp, slc, tid, ipt);
2195 if(isJunk) tp3d.TPXErr2 *= 4;
2198 pfp.
TP3Ds.push_back(tp3d);
2201 if(prt) mf::LogVerbatim(
"TC")<<
" has "<<pfp.
TP3Ds.size()<<
" TP3Ds";
2216 if(pfp.
TjIDs.size() < 2)
return false;
2218 std::vector<SortEntry> sortVec(pfp.
TjIDs.size());
2219 unsigned short sbCnt = 0;
2220 for (
unsigned short itj = 0; itj < pfp.
TjIDs.size(); ++itj) {
2221 sortVec[itj].index = itj;
2222 auto& tj = slc.
tjs[pfp.
TjIDs[itj] - 1];
2224 if(pfp.
TjUIDs[itj] > 0) ++sbCnt;
2230 unsigned short tlIndex = sortVec[0].index;
2231 unsigned short nlIndex = sortVec[1].index;
2232 auto& tlong = slc.
tjs[pfp.
TjIDs[tlIndex] - 1];
2233 auto& nlong = slc.
tjs[pfp.
TjIDs[nlIndex] - 1];
2234 bool twoSections = (sbCnt > 1 && pfp.
TjUIDs[tlIndex] > 0 && pfp.
TjUIDs[nlIndex] > 0);
2235 unsigned short tStartPt = tlong.EndPt[0];
2236 unsigned short tEndPt = tlong.EndPt[1];
2237 unsigned short nStartPt = nlong.EndPt[0];
2238 unsigned short nEndPt = nlong.EndPt[1];
2241 tEndPt = pfp.
TjUIDs[tlIndex];
2242 nEndPt = pfp.
TjUIDs[nlIndex];
2244 mf::LogVerbatim myprt(
"TC");
2245 myprt<<
"MakeSmallAnglePFP: creating two sections using points";
2246 myprt<<
" T"<<tlong.ID<<
"_"<<tEndPt;
2247 myprt<<
" T"<<nlong.ID<<
"_"<<nEndPt;
2250 std::vector<Point3_t> sfEndPos;
2251 for(
unsigned short isf = 0; isf < pfp.
SectionFits.size(); ++isf) {
2253 auto& ltp0 = tlong.Pts[tStartPt];
2254 auto& ltp1 = tlong.Pts[tEndPt];
2255 auto& ntp0 = nlong.Pts[nStartPt];
2256 auto& ntp1 = nlong.Pts[nEndPt];
2258 auto start =
MakeTP3D(detProp, slc, ltp0, ntp0);
2261 std::cout<<
" Start/end fail in section "<<isf<<
". Add recovery code\n";
2265 mf::LogVerbatim(
"TC")<<
" Start is outside the TPC "<<start.Pos[0]<<
" "<<start.Pos[1]<<
" "<<start.Pos[2];
2268 mf::LogVerbatim(
"TC")<<
" End is outside the TPC "<<
end.Pos[0]<<
" "<<
end.Pos[1]<<
" "<<
end.Pos[2];
2270 if(isf == 0) sfEndPos.push_back(start.Pos);
2271 sfEndPos.push_back(
end.Pos);
2274 for(
unsigned short xyz = 0; xyz < 3; ++xyz) {
2275 sf.Dir[xyz] =
end.Pos[xyz] - start.Pos[xyz];
2276 sf.Pos[xyz] = (
end.Pos[xyz] + start.Pos[xyz]) / 2.;
2282 tStartPt = tEndPt + 1; tEndPt = tlong.EndPt[1];
2283 nStartPt = nEndPt + 1; nEndPt = nlong.EndPt[1];
2287 std::vector<TP3D> sf2pts;
2288 for(
unsigned short itj = 0; itj < sortVec.size(); ++itj) {
2289 int tid = pfp.
TjIDs[sortVec[itj].index];
2292 if(twoSections && pfp.
TjUIDs[sortVec[itj].index] < 0)
continue;
2293 auto& tj = slc.
tjs[tid - 1];
2294 unsigned short sb = tj.EndPt[1];
2295 if(twoSections && pfp.
TjUIDs[sortVec[itj].index] > 0) sb = pfp.
TjUIDs[sortVec[itj].index];
2297 std::vector<double> npwc(pfp.
SectionFits.size(), 0);
2298 for(
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2299 auto& tp = tj.Pts[ipt];
2300 if(tp.Chg <= 0)
continue;
2301 if(ipt > sb) { ++npwc[1]; }
else { ++npwc[0]; }
2303 double length =
PosSep(sfEndPos[0], sfEndPos[1]);
2304 double step = length / npwc[0];
2305 double along = -length / 2;
2306 unsigned short sfi = 0;
2307 for(
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2308 auto& tp = tj.Pts[ipt];
2309 if(tp.Chg <= 0)
continue;
2310 auto tp3d =
CreateTP3D(detProp, slc, tid, ipt);
2314 length =
PosSep(sfEndPos[1], sfEndPos[2]);
2315 step = length / npwc[1];
2316 along = -length / 2;
2322 for(
unsigned short xyz = 0; xyz < 3; ++xyz) tp3d.Pos[xyz] = sf.Pos[xyz] + along * sf.Dir[xyz];
2325 double delta = tp3d.Pos[0] - tp3d.TPX;
2326 sf.ChiDOF += delta * delta / tp3d.TPXErr2;
2330 pfp.
TP3Ds.push_back(tp3d);
2332 sf2pts.push_back(tp3d);
2336 if(pfp.
TP3Ds.size() < 4)
return false;
2338 if(sf.NPts < 5)
return false;
2339 sf.ChiDOF /= (float)(sf.NPts - 4);
2342 if(!sf2pts.empty()) {
2344 pfp.
TP3Ds.insert(pfp.
TP3Ds.end(), sf2pts.begin(), sf2pts.end());
2350 mf::LogVerbatim(
"TC")<<
"Created SmallAngle P"<<pfp.
ID
2351 <<
" with "<<pfp.
TP3Ds.size()
2352 <<
" points in "<<pfp.
SectionFits.size()<<
" sections\n";
2363 std::reverse(pfp.
TP3Ds.begin(), pfp.
TP3Ds.end());
2365 for (std::size_t sfi = 0; sfi < pfp.
SectionFits.size(); ++sfi) {
2368 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
2372 for (
auto& tp3d : pfp.
TP3Ds)
2374 std::swap(pfp.
dEdx[0], pfp.
dEdx[1]);
2393 unsigned short cnt = 0;
2399 for (
auto& tj : slc.
tjs) {
2402 if (tj.AlgMod[
kMat3D])
continue;
2404 if ((
int)planeID.
Cryostat != cstat)
continue;
2405 if ((
int)planeID.
TPC != tpc)
continue;
2406 int plane = planeID.
Plane;
2407 if (tj.ID <= 0)
continue;
2408 unsigned short tjID = tj.ID;
2409 for (
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2410 auto& tp = tj.Pts[ipt];
2411 if (tp.Chg <= 0)
continue;
2412 if (tp.Pos[0] < -0.4)
continue;
2414 if (tp.InPFP > 0)
continue;
2415 if (muFuzzCut && tp.Environment[
kEnvNearMuon])
continue;
2416 tj2pt.
wire = std::nearbyint(tp.Pos[0]);
2421 tj2pt.
xlo = xpos - rms;
2422 tj2pt.
xhi = xpos + rms;
2423 tj2pt.
plane = plane;
2426 tj2pt.
npts = tj.EndPt[1] - tj.EndPt[0] + 1;
2432 std::vector<SortEntry> sortVec(slc.
mallTraj.size());
2433 for (std::size_t ipt = 0; ipt < slc.
mallTraj.size(); ++ipt) {
2435 sortVec[ipt].index = ipt;
2436 sortVec[ipt].val = slc.
mallTraj[ipt].xlo;
2442 for (std::size_t ii = 0; ii < sortVec.size(); ++ii)
2443 slc.
mallTraj[ii] = tallTraj[sortVec[ii].index];
2459 tp3d.
Dir = {{0.0, 0.0, 1.0}};
2460 tp3d.
Pos = {{999.0, 999.0, 999.0}};
2463 if(iPlnID == jPlnID)
return tp3d;
2470 if(dx > 20)
return tp3d;
2471 tp3d.
Pos[0] = (ix + jx) / 2;
2486 double den = isn * jcs - ics * jsn;
2487 if(den == 0)
return tp3d;
2488 double iPos0 = itp.
Pos[0];
2489 double jPos0 = jtp.
Pos[0];
2491 tp3d.
Pos[2] = (jcs * (iPos0 - iw0) - ics * (jPos0 - jw0)) / den;
2495 tp3d.
Pos[1] = (iPos0 - iw0 - isn * tp3d.
Pos[2]) / ics;
2497 tp3d.
Pos[1] = (jPos0 - jw0 - jsn * tp3d.
Pos[2]) / jcs;
2501 if(jtp.
Dir[1] == 0) {
2503 if(jtp.
Dir[0] > 0) { tp3d.
Dir[0] = 1; }
else { tp3d.
Dir[0] = -1; }
2512 double itp2_0 = itp.
Pos[0] + 100;
2513 double itp2_1 = itp.
Pos[1];
2522 double jtp2Pos0 = (jtp2Pos1 - jtp.
Pos[1]) * (jtp.
Dir[0] / jtp.
Dir[1]) + jtp.
Pos[0];
2524 pos2[2] = (jcs * (itp2_0 - iw0) - ics * (jtp2Pos0 - jw0)) / den;
2526 pos2[1] = (itp2_0 - iw0 - isn * pos2[2]) / ics;
2528 pos2[1] = (jtp2Pos0 - jw0 - jsn * pos2[2]) / jcs;
2531 if(sep == 0)
return tp3d;
2532 for(
unsigned short ixyz = 0; ixyz < 3; ++ixyz) tp3d.
Dir[ixyz] = (pos2[ixyz] - tp3d.
Pos[ixyz]) /sep;
2542 if (v1[0] == v2[0] && v1[1] == v2[1] && v1[2] == v2[2])
return 0;
2552 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
2553 dir[xyz] = p2[xyz] - p1[xyz];
2554 if (dir[0] == 0 && dir[1] == 0 && dir[2] == 0)
return dir;
2567 return sqrt(
PosSep2(pos1, pos2));
2575 double d0 = pos1[0] - pos2[0];
2576 double d1 = pos1[1] - pos2[1];
2577 double d2 = pos1[2] - pos2[2];
2578 return d0 * d0 + d1 * d1 + d2 * d2;
2585 double den = v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2];
2586 if (den == 0)
return false;
2605 unsigned short numEnds = 2;
2606 if (pfp.
PDGCode == 1111) numEnds = 1;
2609 for (
unsigned short end = 0;
end < numEnds; ++
end) {
2610 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane)
2618 for (
unsigned short end = 0;
end < numEnds; ++
end) {
2619 std::vector<float> cnt(slc.
nPlanes);
2622 for (std::size_t ii = 0; ii < pfp.
TP3Ds.size(); ++ii) {
2624 if (dir > 0) { ipt = ii; }
2626 ipt = pfp.
TP3Ds.size() - ii - 1;
2628 if (ipt >= pfp.
TP3Ds.size())
break;
2629 auto& tp3d = pfp.
TP3Ds[ipt];
2630 if (tp3d.Flags[
kTP3DBad])
continue;
2631 if (
PosSep2(tp3d.Pos, endPos) > maxSep2)
break;
2634 float dedx =
dEdx(clockData, detProp, slc, tp3d);
2635 if (dedx < 0.5)
continue;
2640 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
2641 if (cnt[plane] == 0)
continue;
2642 pfp.
dEdx[
end][plane] /= cnt[plane];
2665 for (
auto& tp3d : pfp.
TP3Ds) {
2667 double dedx =
dEdx(clockData, detProp, slc, tp3d);
2668 if (dedx < 0.5 || dedx > 80.)
continue;
2670 sum2 += dedx * dedx;
2673 if (cnt < 3)
return;
2674 dEdXAve = sum / cnt;
2676 dEdXRms = 0.3 * dEdXAve;
2677 double arg = sum2 - cnt * dEdXAve * dEdXAve;
2678 if (arg < 0)
return;
2679 dEdXRms = sqrt(arg) / (cnt - 1);
2681 double minRms = 0.05 * dEdXAve;
2682 if (dEdXRms < minRms) dEdXRms = minRms;
2693 if (tp3d.
TjID > (
int)slc.
slHits.size())
return 0;
2694 if (tp3d.
TjID <= 0)
return 0;
2701 for (
unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2702 if (!tp.UseHit[ii])
continue;
2704 dQ +=
hit.Integral();
2708 if (dQ == 0)
return 0;
2711 std::abs(std::sin(angleToVert) * tp3d.
Dir[1] + std::cos(angleToVert) * tp3d.
Dir[2]);
2712 if (cosgamma < 1.
E-5)
return 0;
2714 double dQdx = dQ / dx;
2717 if (std::isinf(dedx)) dedx = 0;
2726 unsigned short tpIndex)
2734 if (tjID <= 0 || tjID > (
int)slc.
tjs.size())
return tp3d;
2735 auto& tj = slc.
tjs[tjID - 1];
2736 if (tpIndex < tj.EndPt[0] || tpIndex > tj.EndPt[1])
return tp3d;
2739 auto& tp2 = tj.Pts[tp3d.
TPIndex];
2747 if (tp2.AngleCode == 1) rms *= 2;
2749 if (tp2.AngleCode > 1) {
2750 std::vector<unsigned int> hitMultiplet;
2751 for (std::size_t ii = 0; ii < tp2.Hits.size(); ++ii) {
2752 if (!tp2.UseHit[ii])
continue;
2754 if (hitMultiplet.size() > 1)
break;
2761 tp3d.
Wire = tp2.Pos[0];
2778 if (tp3d.
Wire < 0)
return false;
2780 if (pfp.
SectionFits[0].Pos[0] == -10.0)
return false;
2789 for (std::size_t sfi = 0; sfi < pfp.
SectionFits.size(); ++sfi) {
2800 auto plnTP =
MakeBareTP(detProp, slc, sf.Pos, sf.Dir, tp3d.
CTP);
2802 double dw = tp3d.
Wire - plnTP.Pos[0];
2804 double t = dw * plnTP.DeltaRMS;
2806 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
2807 tp3d.
Pos[xyz] = sf.Pos[xyz] + t * sf.Dir[xyz];
2828 pfp.
ID = slc.
pfps.size() + 1;
2850 if (slc.
pfps.empty())
return;
2852 for (
auto& pfp : slc.
pfps) {
2853 if (pfp.ID == 0)
continue;
2854 if (pfp.Vx3ID[0] > 0)
continue;
2855 if (pfp.SectionFits.empty())
continue;
2862 if (pfp.TP3Ds.empty()) {
2864 startPos = pfp.SectionFits[0].Pos;
2866 else if (!pfp.TP3Ds.empty()) {
2868 startPos = pfp.TP3Ds[0].Pos;
2870 vx3.
X = startPos[0];
2871 vx3.
Y = startPos[1];
2872 vx3.
Z = startPos[2];
2873 vx3.
ID = slc.
vtx3s.size() + 1;
2877 slc.
vtx3s.push_back(vx3);
2878 pfp.Vx3ID[0] = vx3.
ID;
2920 if (slc.
pfps.empty())
return;
2923 int neutrinoPFPID = 0;
2924 for (
auto& pfp : slc.
pfps) {
2925 if (pfp.ID == 0)
continue;
2926 if (!
tcc.
modes[
kTestBeam] && neutrinoPFPID == 0 && (pfp.PDGCode == 12 || pfp.PDGCode == 14)) {
2927 neutrinoPFPID = pfp.ID;
2933 constexpr
unsigned short end1 = 1;
2934 for (
auto& pfp : slc.
pfps) {
2935 if (pfp.ID == 0)
continue;
2937 if (pfp.Vx3ID[end1] > 0)
continue;
2941 unsigned short cnt3 = 0;
2942 unsigned short vx3id = 0;
2944 std::vector<int> vx2ids;
2945 for (
auto tjid : pfp.TjIDs) {
2946 auto& tj = slc.
tjs[tjid - 1];
2947 if (tj.VtxID[end1] == 0)
continue;
2948 auto& vx2 = slc.
vtxs[tj.VtxID[end1] - 1];
2949 if (vx2.Vx3ID == 0) {
2950 if (vx2.Topo == 1 && vx2.NTraj == 2) vx2ids.push_back(vx2.ID);
2953 if (vx3id == 0) vx3id = vx2.Vx3ID;
2954 if (vx2.Vx3ID == vx3id) ++cnt3;
2958 if (pfp.Vx3ID[1 - end1] == vx3id)
continue;
2959 pfp.Vx3ID[end1] = vx3id;
2964 for (
auto& pfp : slc.
pfps) {
2965 if (pfp.ID == 0)
continue;
2967 if (pfp.PDGCode == 12 || pfp.PDGCode == 14 || pfp.PDGCode == 22)
continue;
2970 int pfpParentID = INT_MAX;
2971 unsigned short nParent = 0;
2972 for (
auto tjid : pfp.TjIDs) {
2973 auto& tj = slc.
tjs[tjid - 1];
2974 if (tj.ParentID <= 0)
continue;
2975 auto parPFP =
GetAssns(slc,
"T", tj.ParentID,
"P");
2976 if (parPFP.empty())
continue;
2977 if (pfpParentID == INT_MAX) pfpParentID = parPFP[0];
2978 if (parPFP[0] == pfpParentID) ++nParent;
2981 auto& ppfp = slc.
pfps[pfpParentID - 1];
2983 pfp.ParentUID = ppfp.UID;
2985 ppfp.DtrUIDs.push_back(pfp.UID);
2989 if (neutrinoPFPID > 0) {
2990 auto& neutrinoPFP = slc.
pfps[neutrinoPFPID - 1];
2991 int vx3id = neutrinoPFP.Vx3ID[1];
2992 for (
auto& pfp : slc.
pfps) {
2993 if (pfp.ID == 0 || pfp.ID == neutrinoPFPID)
continue;
2994 if (pfp.Vx3ID[0] != vx3id)
continue;
2995 pfp.ParentUID = (size_t)neutrinoPFPID;
2996 neutrinoPFP.DtrUIDs.push_back(pfp.ID);
2997 if (pfp.PDGCode == 111) neutrinoPFP.PDGCode = 12;
3009 if (pfp.
TjIDs.empty())
return false;
3010 if (pfp.
PDGCode != 1111 && pfp.
TP3Ds.size() < 2)
return false;
3015 for(
auto& tp3d : pfp.
TP3Ds) {
3016 if(tp3d.TPIndex != USHRT_MAX) slc.
tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex].InPFP = pfp.
ID;
3021 unsigned short nNotSet = 0;
3022 for (
auto& tp3d : pfp.
TP3Ds) {
3023 if (tp3d.Flags[
kTP3DBad])
continue;
3024 auto& tp = slc.
tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
3025 if (tp.InPFP != pfp.
ID) ++nNotSet;
3027 if (nNotSet > 0)
return false;
3029 if (pfp.
ID != (
int)slc.
pfps.size() + 1) pfp.
ID = slc.
pfps.size() + 1;
3034 for (
auto tjid : pfp.
TjIDs) {
3035 auto& tj = slc.
tjs[tjid - 1];
3036 tj.AlgMod[
kMat3D] =
true;
3039 slc.
pfps.push_back(pfp);
3048 if (pfp.
ID <= 0)
return false;
3049 if (end > 1)
return false;
3058 if (neutrinoPFP) { pos = pfp.
SectionFits[0].Pos; }
3059 else if (end == 0) {
3060 pos = pfp.
TP3Ds[0].Pos;
3065 return (pos[0] > slc.
xLo + abit && pos[0] < slc.
xHi - abit && pos[1] > slc.
yLo + abit &&
3066 pos[1] < slc.
yHi - abit && pos[2] > slc.
zLo + abit && pos[2] < slc.
zHi - abit);
3079 double local[3] = {0., 0., 0.};
3080 double world[3] = {0., 0., 0.};
3102 if (pos1[0] == pos2[0] && pos1[1] == pos2[1] && pos1[2] == pos2[2])
return;
3105 double costh =
DotProd(dir1, ptDir);
3106 if (costh > 1) costh = 1;
3107 double sep =
PosSep(pos1, pos2);
3108 alongTrans[0] = costh * sep;
3109 double sinth = sqrt(1 - costh * costh);
3110 alongTrans[1] = sinth * sep;
3124 for (
unsigned short xyz = 0; xyz < 3; ++xyz) {
3125 p1End[xyz] = p1[xyz] + 10 * p1Dir[xyz];
3126 p2End[xyz] = p2[xyz] + 10 * p2Dir[xyz];
3150 double d1343, d4321, d1321, d4343, d2121;
3151 double numer, denom;
3152 constexpr
double EPS = std::numeric_limits<double>::min();
3154 p13[0] = p1[0] - p3[0];
3155 p13[1] = p1[1] - p3[1];
3156 p13[2] = p1[2] - p3[2];
3157 p43[0] = p4[0] - p3[0];
3158 p43[1] = p4[1] - p3[1];
3159 p43[2] = p4[2] - p3[2];
3161 p21[0] = p2[0] - p1[0];
3162 p21[1] = p2[1] - p1[1];
3163 p21[2] = p2[2] - p1[2];
3166 d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2];
3167 d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2];
3168 d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2];
3169 d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2];
3170 d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2];
3172 denom = d2121 * d4343 - d4321 * d4321;
3173 if (
std::abs(denom) < EPS)
return (
false);
3174 numer = d1343 * d4321 - d1321 * d4343;
3176 double mua = numer / denom;
3177 double mub = (d1343 + d4321 * mua) / d4343;
3179 intersect[0] = p1[0] + mua * p21[0];
3180 intersect[1] = p1[1] + mua * p21[1];
3181 intersect[2] = p1[2] + mua * p21[2];
3183 pb[0] = p3[0] + mub * p43[0];
3184 pb[1] = p3[1] + mub * p43[1];
3185 pb[2] = p3[2] + mub * p43[2];
3186 doca =
PosSep(intersect, pb);
3188 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
3189 intersect[xyz] += pb[xyz];
3190 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
3191 intersect[xyz] /= 2;
3206 float sep =
PosSep(pos1, pos2);
3207 if (sep == 0)
return -1;
3213 for (
unsigned short step = 0; step < nstep; ++step) {
3214 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
3216 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
3226 if (cnt == 0)
return -1;
3239 if (pfp.
ID == 0)
return 0;
3240 if (pfp.
TjIDs.empty())
return 0;
3241 if (end < 0 || end > 1)
return 0;
3251 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
3253 std::vector<int> tjids(1);
3254 for (
auto tjid : pfp.
TjIDs) {
3255 auto& tj = slc.
tjs[tjid - 1];
3256 if (tj.CTP != inCTP)
continue;
3261 if (pos2[0] < -0.4)
continue;
3263 unsigned int wire = std::nearbyint(pos2[0]);
3264 if (wire > slc.
nWires[plane])
continue;
3265 if (slc.
wireHitRange[plane][wire].first == UINT_MAX)
continue;
3268 if (cf < lo) lo = cf;
3269 if (cf > hi) hi = cf;
3274 if (cnt == 0)
return 0;
3275 if (cnt > 1 && lo < 0.3 && hi > 0.8) {
3286 if (end > 1 || pfp.
SectionFits.empty())
return {{0., 0., 0.}};
3295 if (end > 1 || pfp.
SectionFits.empty())
return {{0., 0., 0.}};
3298 if (end == 0)
return pfp.
TP3Ds[0].Pos;
3306 if (pfp.
TP3Ds.empty())
return 0;
3313 unsigned short sfIndex,
3314 unsigned short& startPt,
3315 unsigned short& endPt)
3318 startPt = USHRT_MAX;
3320 if (sfIndex >= pfp.
SectionFits.size())
return false;
3323 for (std::size_t ipt = 0; ipt < pfp.
TP3Ds.size(); ++ipt) {
3324 auto& tp3d = pfp.
TP3Ds[ipt];
3325 if (tp3d.SFIndex < sfIndex)
continue;
3330 if (tp3d.SFIndex > sfIndex)
break;
3342 if (pfp.
ID == 0)
return 0;
3343 if (pfp.
TP3Ds.empty())
return 0;
3344 auto& pos0 = pfp.
TP3Ds[0].Pos;
3345 auto& pos1 = pfp.
TP3Ds[pfp.
TP3Ds.size() - 1].Pos;
3359 if (pfp.
TP3Ds.empty())
return -1;
3364 Average_dEdX(clockData, detProp, slc, pfp, dEdXAve, dEdXRms);
3365 if (dEdXAve < 0)
return 0;
3368 float length =
Length(pfp);
3372 for (
auto tjid : pfp.
TjIDs) {
3373 auto& tj = slc.
tjs[tjid - 1];
3375 if (el <= 0)
continue;
3376 mcsmom +=
MCSMom(slc, tj);
3377 chgrms += tj.ChgRMS;
3380 if (cnt < 2)
return 0;
3385 if (length > 150) vote = 13;
3387 if (vote == 0 && length > 50 && dEdXAve < 2.5 && mcsmom > 500) vote = 13;
3389 if (vote == 0 && dEdXAve > 3.0 && mcsmom > 200 && chgrms < 0.4) vote = 2212;
3391 if (vote == 0 && mcsmom < 50 && chgrms > 0.4) vote = 11;
3399 std::string someText,
3404 if (pfp.
TP3Ds.empty())
return;
3405 mf::LogVerbatim myprt(
"TC");
3406 myprt << someText <<
" pfp P" << pfp.
ID <<
" MVI " << pfp.
MVI;
3407 for (
auto tid : pfp.
TjIDs)
3408 myprt <<
" T" << tid;
3412 for (
unsigned short ib = 0; ib <
pAlgModSize; ++ib) {
3418 <<
" SFI ________Pos________ ________Dir_______ _____EndPos________ ChiDOF NPts "
3420 for (std::size_t sfi = 0; sfi < pfp.
SectionFits.size(); ++sfi) {
3421 myprt << someText << std::setw(4) << sfi;
3423 myprt << std::fixed << std::setprecision(1);
3424 unsigned short startPt = 0, endPt = 0;
3426 auto& start = pfp.
TP3Ds[startPt].Pos;
3427 myprt << std::setw(7) << start[0] << std::setw(7) << start[1] << std::setw(7) << start[2];
3430 myprt <<
" Invalid";
3432 myprt << std::fixed << std::setprecision(2);
3433 myprt << std::setw(7) << sf.Dir[0] << std::setw(7) << sf.Dir[1] << std::setw(7)
3435 myprt << std::fixed << std::setprecision(1);
3436 if (endPt < pfp.
TP3Ds.size()) {
3438 myprt << std::setw(7) <<
end[0] << std::setw(7) <<
end[1] << std::setw(7) <<
end[2];
3441 myprt <<
" Invalid";
3443 myprt << std::setprecision(1) << std::setw(6) << sf.ChiDOF;
3444 myprt << std::setw(6) << sf.NPts;
3445 myprt << std::setw(6) << sf.NeedsUpdate;
3451 myprt<<someText<<
" Note: GBH = TP3D Flags. G = Good, B = Bad, H = High dE/dx \n";
3452 myprt<<someText<<
" ipt SFI ________Pos________ Delta Pull GBH Path along dE/dx S? T_ipt_P:W:T\n";
3454 unsigned short fromPt = 0;
3455 unsigned short toPt = pfp.
TP3Ds.size() - 1;
3456 if (printPts >= 0) fromPt = toPt;
3458 std::vector<float> dang(pfp.
TP3Ds.size(), -1);
3459 for (
unsigned short ipt = fromPt; ipt <= toPt; ++ipt) {
3460 auto tp3d = pfp.
TP3Ds[ipt];
3461 myprt << someText << std::setw(4) << ipt;
3462 myprt << std::setw(4) << tp3d.SFIndex;
3463 myprt << std::fixed << std::setprecision(1);
3464 myprt << std::setw(7) << tp3d.Pos[0] << std::setw(7) << tp3d.Pos[1] << std::setw(7)
3466 myprt << std::setprecision(1) << std::setw(6) << (tp3d.Pos[0] - tp3d.TPX);
3468 myprt << std::setprecision(1) << std::setw(6) << pull;
3470 myprt << std::setw(7) << std::setprecision(1) <<
PosSep(tp3d.Pos, pfp.
TP3Ds[0].Pos);
3471 myprt << std::setw(7) << std::setprecision(1) << tp3d.along;
3472 myprt << std::setw(6) << std::setprecision(2) <<
dEdx(clockData, detProp, slc, tp3d);
3475 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
3477 auto tp =
MakeBareTP(detProp, slc, tp3d.Pos, inCTP);
3480 if (tp3d.TjID > 0) {
3481 auto& tp = slc.
tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
3482 myprt <<
" T" << tp3d.TjID <<
"_" << tp3d.TPIndex <<
"_" <<
PrintPos(slc, tp) <<
" "
3486 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.
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
process_name opflash particleana ie ie ie z
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
then if[["$THISISATEST"==1]]
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.
process_name opflash particleana ie x
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)
Declaration of signal hit object.
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.
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
IDparameter< geo::PlaneID > PlaneID
Member type of validated geo::PlaneID parameter.
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)
Access the description of detector geometry.
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
process_name opflash particleana ie ie y
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 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
for($it=0;$it< $RaceTrack_number;$it++)
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)
auto end(FixedBins< T, C > const &) noexcept
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 valsIncreasing(const SortEntry &c1, const SortEntry &c2)
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)
auto norm(Vector const &v)
Return norm of the specified vector.
std::vector< TCSlice > slices
void GetRange(const PFPStruct &pfp, unsigned short sfIndex, unsigned short &fromPt, unsigned short &npts)
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)
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.
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
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
bool valsDecreasing(const SortEntry &c1, const SortEntry &c2)
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)
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)
physics associatedGroupsWithLeft p1
constexpr TPCID()=default
Default constructor: an invalid TPC ID.
BEGIN_PROLOG could also be cout
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 HasWire(geo::WireID const &wireid) const
Returns whether we have the specified wire.
unsigned short SFIndex
and the section fit index