35 bool TrajClusterAlg::SortByMultiplet(
TCHit const& a,
TCHit const& b)
39 if (cmp_res != 0)
return cmp_res < 0;
49 :fCaloAlg(pset.get<
fhicl::ParameterSet>(
"CaloAlg")), fMVAReader(
"Silent")
63 bool badinput =
false;
67 fMode = pset.
get<
short >(
"Mode", 1);
72 fMinPtsFit = pset.
get< std::vector<unsigned short >>(
"MinPtsFit");
73 fMinPts = pset.
get< std::vector<unsigned short >>(
"MinPts");
78 tjs.
ChargeCuts = pset.
get< std::vector<float >>(
"ChargeCuts", {3, 0.15, 0.25});
80 tjs.
KinkCuts = pset.
get< std::vector<float >>(
"KinkCuts", {0.4, 1.5, 4});
88 std::vector<std::string> skipAlgsVec = pset.
get< std::vector<std::string> >(
"SkipAlgs");
90 std::vector<std::string> specialAlgsVec;
91 if(pset.
has_key(
"SpecialAlgs")) specialAlgsVec = pset.
get< std::vector<std::string> >(
"SpecialAlgs");
94 tjs.
MuonTag = pset.
get< std::vector<short>>(
"MuonTag", {-1, -1, -1, - 1});
95 tjs.
ShowerTag = pset.
get< std::vector<float>>(
"ShowerTag", {-1, -1, -1, -1, -1, -1});
96 std::string fMVAShowerParentWeights =
"NA";
97 pset.
get_if_present<std::string>(
"MVAShowerParentWeights", fMVAShowerParentWeights);
102 fChkStopCuts = pset.
get< std::vector<float>>(
"ChkStopCuts", {-1, -1, -1});
107 tjs.
MatchTruth = pset.
get< std::vector<float> >(
"MatchTruth", {-1, -1, -1, -1});
108 tjs.
Vertex2DCuts = pset.
get< std::vector<float >>(
"Vertex2DCuts", {-1, -1, -1, -1, -1, -1, -1});
111 tjs.
Match3DCuts = pset.
get< std::vector<float >>(
"Match3DCuts", {-1, -1, -1, -1, -1});
128 if(fMinPtsFit.size() != fMinPts.size()) badinput =
true;
129 if(fMaxAngleCode.size() != fMinPts.size()) badinput =
true;
130 if(fMinMCSMom.size() != fMinPts.size()) badinput =
true;
131 if(badinput)
throw art::Exception(
art::errors::Configuration)<<
"Bad input from fcl file. Vector lengths for MinPtsFit, MaxAngleRange and MinMCSMom should be defined for each reconstruction pass";
133 if(
tjs.
Vertex2DCuts.size() < 10)
throw art::Exception(
art::errors::Configuration)<<
"Vertex2DCuts must be size 10\n 0 = Max length definition for short TJs\n 1 = Max vtx-TJ sep short TJs\n 2 = Max vtx-TJ sep long TJs\n 3 = Max position pull for >2 TJs\n 4 = Max vtx position error\n 5 = Min MCSMom for one of two TJs\n 6 = Min fraction of wires hit btw vtx and Tjs\n 7 = Min Score\n 8 = min ChgFrac at a vtx or merge point\n 9 = max MCSMom asymmetry";
143 std::cout<<
"ShowerTag must be size 13\n 0 = Mode\n 1 = max MCSMom\n 2 = max separation (WSE units)\n 3 = Max angle diff\n 4 = Factor * rms width\n 5 = Min half width\n 6 = min total Tps\n 7 = Min Tjs\n 8 = max parent FOM\n 9 = max direction FOM 10 = max AspectRatio\n 11 = min Score to preserve a vertex\n 12 = Debug showers in CTP\n";
144 std::cout<<
" Fixing this problem...";
152 std::cout<<
">>>>>>>> Match3DCuts has been expanded to size 7. Please update your fcl file\n";
155 if(oldsize < 5) std::cout<<
" Setting Match3DCuts[4] = 2000 combinations\n";
156 if(oldsize < 6) std::cout<<
" Setting Match3DCuts[5] = 1, which disables charge asymmetry checking\n";
166 mf::LogVerbatim(
"TC")<<
"Last element of AngleRange != 90 degrees. Fixing it\n";
176 tjs.
DebugMode = (debugTj || debugMerge || debugVtx || debugWorkID);
178 std::cout<<
"**************** Debug mode: debug.CTP "<<
debug.
CTP<<
" ****************\n";
180 std::cout<<
"Pass MinPts MinPtsFit Max Angle\n";
181 for(
unsigned short pass = 0; pass < fMinPts.size(); ++pass) {
182 unsigned short ir = fMaxAngleCode[pass];
184 std::cout<<std::setw(3)<<pass;
185 std::cout<<std::setw(7)<<fMinPts[pass];
186 std::cout<<std::setw(7)<<fMinPtsFit[pass];
189 std::cout<<
"Max angle ranges\n range degrees radians\n";
191 std::cout<<std::setw(3)<<ir;
193 std::cout<<std::setw(8)<<std::setprecision(3)<<
tjs.
AngleRanges[ir] * M_PI / 180;
211 bool gotit, printHelp =
false;
220 for(
auto strng : skipAlgsVec) {
228 for(
unsigned short ib = 0; ib <
AlgBitNames.size(); ++ib) {
236 std::cout<<
"******* Unknown SkipAlgs input string '"<<strng<<
"'\n";
241 std::cout<<
"Valid AlgNames:";
242 for(
auto strng :
AlgBitNames) std::cout<<
" "<<strng;
244 std::cout<<
"Or specify All to turn all algs off\n";
248 for(
auto strng : specialAlgsVec) {
250 for(
unsigned short ib = 0; ib <
AlgBitNames.size(); ++ib) {
258 std::cout<<
"******* Unknown SpecialAlgs input string '"<<strng<<
"'\n";
263 std::cout<<
"Valid AlgNames:";
264 for(
auto strng :
AlgBitNames) std::cout<<
" "<<strng;
266 std::cout<<
"Or specify All to turn all algs off\n";
274 std::cout<<
"Using algs:";
275 for(
unsigned short ib = 0; ib <
AlgBitNames.size(); ++ib) {
276 if(ib % 10 == 0) std::cout<<
"\n";
280 std::cout<<
"Skipping algs:";
320 tjs.
detprop = lar::providerFrom<detinfo::DetectorPropertiesService>();
321 tjs.
geom = lar::providerFrom<geo::Geometry>();
327 if(
fMode == 0)
return;
332 std::cout<<
"Look for hit near Cryo:TPC:Pln:Wire:Tick "<<
debug.
Cryostat;
334 for(
unsigned int iht = 0; iht <
tjs.
fHits.size(); ++iht) {
337 if((
int)
hit.ArtPtr->WireID().Wire !=
debug.
Wire)
continue;
342 std::cout<<
" Amp "<<(int)
tjs.
fHits[iht].PeakAmplitude;
343 std::cout<<
" RMS "<<std::fixed<<std::setprecision(1)<<
tjs.
fHits[iht].RMS;
344 std::cout<<
" Chisq "<<std::fixed<<std::setprecision(1)<<
tjs.
fHits[iht].GoodnessOfFit;
345 std::cout<<
" Mult "<<
tjs.
fHits[iht].Multiplicity;
349 if(
debug.
Hit == UINT_MAX) std::cout<<
" not found\n";
370 if(
fMode == 4) std::cout<<
"RTCA: fMode set to 4 for debugging\n";
377 for(
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane) {
407 for(
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane) {
410 std::cout<<
"RTC: ChkVtxAssociations found an error\n";
421 if(pfp.ID == 0)
continue;
422 if(pfp.TPCID != tpcid)
continue;
434 std::cout <<
"SHOWER TREE STAGE NUM SIZE: " <<
tjs.
stv.
StageNum.size() << std::endl;
479 unsigned short ntj = 0;
480 unsigned short nsh = 0;
482 if(tj.AlgMod[
kKilled])
continue;
513 for(
unsigned short pass = 0; pass <
fMinPtsFit.size(); ++pass) {
514 for(
unsigned int ii = 0; ii < nwires; ++ii) {
516 unsigned int iwire = 0;
517 unsigned int jwire = 0;
532 unsigned int ifirsthit = (
unsigned int)
tjs.
WireHitRange[plane][iwire].first;
533 unsigned int ilasthit = (
unsigned int)
tjs.
WireHitRange[plane][iwire].second;
534 unsigned int jfirsthit = (
unsigned int)
tjs.
WireHitRange[plane][jwire].first;
535 unsigned int jlasthit = (
unsigned int)
tjs.
WireHitRange[plane][jwire].second;
536 for(
unsigned int iht = ifirsthit; iht < ilasthit; ++iht) {
543 if(
tjs.
fHits[iht].InTraj != 0)
continue;
546 unsigned int fromWire =
tjs.
fHits[iht].ArtPtr->WireID().Wire;
547 float fromTick =
tjs.
fHits[iht].PeakTime;
548 float iqtot =
tjs.
fHits[iht].Integral;
549 float hitsRMSTick =
tjs.
fHits[iht].RMS;
550 std::vector<unsigned int> iHitsInMultiplet;
553 iHitsInMultiplet.resize(1);
554 iHitsInMultiplet[0] = iht;
558 if(iHitsInMultiplet.size() > 4)
continue;
560 if(iHitsInMultiplet.size() > 1) {
564 if(hitsRMSTick == 0)
continue;
565 bool fatIHit = (hitsRMSTick > maxHitsRMS);
566 if(
prt)
mf::LogVerbatim(
"TC")<<
" hit RMS "<<
tjs.
fHits[iht].RMS<<
" BB Multiplicity "<<iHitsInMultiplet.size()<<
" AveHitRMS["<<plane<<
"] "<<
tjs.
AveHitRMS[plane]<<
" HitsRMSTick "<<hitsRMSTick<<
" fatIHit "<<fatIHit;
567 for(
unsigned int jht = jfirsthit; jht < jlasthit; ++jht) {
569 if(
tjs.
fHits[iht].InTraj != 0)
continue;
570 if(
tjs.
fHits[jht].InTraj != 0)
continue;
579 unsigned int toWire = jwire;
580 float toTick =
tjs.
fHits[jht].PeakTime;
581 float jqtot =
tjs.
fHits[jht].Integral;
582 std::vector<unsigned int> jHitsInMultiplet;
585 jHitsInMultiplet.resize(1);
586 jHitsInMultiplet[0] = jht;
590 if(jHitsInMultiplet.size() > 4)
continue;
593 if(hitsRMSTick == 0)
continue;
594 bool fatJHit = (hitsRMSTick > maxHitsRMS);
597 if((fatIHit && !fatJHit) || (!fatIHit && fatJHit)) {
605 bool hitsOK =
TrajHitsOK(
tjs, iHitsInMultiplet, jHitsInMultiplet);
607 mf::LogVerbatim(
"TC")<<
"+++++++ checking TrajHitsOK with jht "<<plane<<
":"<<
PrintHit(
tjs.
fHits[jht])<<
" BB Multiplicity "<<jHitsInMultiplet.size()<<
" HitsRMSTick "<<
HitsRMSTick(
tjs, jHitsInMultiplet,
kUnusedHits)<<
" fatJhit "<<fatJHit<<
" setting toTick to "<<(int)toTick<<
" TrajHitsOK "<<hitsOK;
610 if(!hitsOK)
continue;
613 if(!
StartTraj(work, fromWire, fromTick, toWire, toTick, inCTP, pass))
continue;
617 if(work.
Pts.empty()) {
623 if(
prt)
mf::LogVerbatim(
"TC")<<
"ReconstructAllTraj: Wrong angle code "<<work.
Pts[0].AngleCode<<
" for this pass "<<work.
Pass;
636 if(!sigOK || work.
Pts[0].Chg == 0) {
642 work.
Pts[0].Pos = work.
Pts[0].HitPos;
665 if(fTryWithNextPass) {
706 if(tj.AlgMod[
kKilled])
continue;
707 if(tj.CTP != inCTP)
continue;
716 bool lastPass = (pass ==
fMinPtsFit.size() - 1);
754 for(
unsigned short ivx = 0; ivx <
tjs.
vtx.size(); ++ivx) {
756 if(vx2.ID == 0)
continue;
757 if(vx2.CTP != inCTP)
continue;
764 std::cout<<
"RAT: ChkVtxAssociations found an error\n";
782 float maxPosSep2 = 0.25;
784 if(
fMode == 2) maxPosSep2 = 1;
786 std::vector<unsigned int> hitsInMultiplet;
787 for(
unsigned short itj = 0; itj <
tjs.
allTraj.size(); ++itj) {
791 unsigned short firstPt = tj.
EndPt[0];
792 unsigned short lastPt = tj.
EndPt[1];
793 for(
unsigned short ipt = firstPt; ipt <= lastPt; ++ipt) {
796 if(tp.
Hits.empty())
continue;
797 bool hitsAdded =
false;
798 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
799 if(!tp.
UseHit[ii])
continue;
800 unsigned int iht = tp.
Hits[ii];
802 if(hitsInMultiplet.size() > 1) {
803 for(
unsigned short jj = ii + 1; jj < tp.
Hits.size(); ++jj) {
804 if(!tp.
UseHit[jj])
continue;
805 if(std::find(hitsInMultiplet.begin(), hitsInMultiplet.end(), tp.
Hits[jj]) != hitsInMultiplet.end()) {
815 std::array<float, 2> oldHitPos = tp.
HitPos;
818 if(
PosSep2(tj.
Pts[ipt].HitPos, oldHitPos) < maxPosSep2) {
838 if(tj.
Pts.size() < 6)
return;
843 if(tj.
Pts[tj.
EndPt[0]].AngleCode == 2)
return;
845 if(tj.
EndPt[0] > 0) {
855 unsigned int wire0 = std::nearbyint(tj.
Pts[0].Pos[0]);
856 unsigned int nextWire = wire0 - tj.
StepDir;
860 unsigned short ipl = planeID.
Plane;
873 float maxDelta = 10 * tj.
Pts[tj.
EndPt[1]].DeltaRMS;
876 if(tp.
Hits.empty())
return;
893 unsigned short lastPt = tjWork.
Pts.size() - 1;
894 if(lastPt < 4)
return;
898 for(
unsigned short ii = 0; ii < 4; ++ii) {
899 unsigned short ipt = lastPt - ii;
900 if(tjWork.
Pts[ipt].Chg == 0)
continue;
901 chg += tjWork.
Pts[ipt].Chg;
905 if(cnt > 1) tjWork.
Pts[lastPt].AveChg = chg / cnt;
931 for(
unsigned int iht = 0; iht <
tjs.
fHits.size(); ++iht) {
938 std::vector<unsigned int> tHits;
943 unsigned int jwire = iwire + 1;
945 unsigned int ifirsthit = (
unsigned int)
tjs.
WireHitRange[plane][iwire].first;
946 unsigned int ilasthit = (
unsigned int)
tjs.
WireHitRange[plane][iwire].second;
947 unsigned int jfirsthit = (
unsigned int)
tjs.
WireHitRange[plane][jwire].first;
948 unsigned int jlasthit = (
unsigned int)
tjs.
WireHitRange[plane][jwire].second;
949 for(
unsigned int iht = ifirsthit; iht < ilasthit; ++iht) {
954 if(
tjs.
fHits[iht].InTraj != 0)
continue;
955 std::vector<unsigned int> iHits;
957 for(
unsigned int jht = jfirsthit; jht < jlasthit; ++jht) {
958 if(
tjs.
fHits[jht].InTraj != 0)
continue;
961 std::vector<unsigned int> jHits;
967 for(
auto iht : iHits)
if(
tjs.
fHits[iht].InTraj == 0) tHits.push_back(iht);
968 for(
auto jht : jHits)
if(
tjs.
fHits[jht].InTraj == 0) tHits.push_back(jht);
969 for(
auto tht : tHits)
tjs.
fHits[tht].InTraj = -4;
970 unsigned int loWire, hiWire;
971 if(iwire != 0) { loWire = iwire - 1; }
else { loWire = 0; }
973 bool hitsAdded =
true;
974 unsigned short nit = 0;
975 while(hitsAdded && nit < 100) {
977 for(
unsigned int kwire = loWire; kwire < hiWire + 1; ++kwire) {
979 unsigned int kfirsthit = (
unsigned int)
tjs.
WireHitRange[plane][kwire].first;
980 unsigned int klasthit = (
unsigned int)
tjs.
WireHitRange[plane][kwire].second;
981 for(
unsigned int kht = kfirsthit; kht < klasthit; ++kht) {
982 if(
tjs.
fHits[kht].InTraj != 0)
continue;
984 if(std::find(tHits.begin(), tHits.end(), kht) != tHits.end())
continue;
989 for(
auto jht : jHits) {
990 if(
tjs.
fHits[jht].InTraj != 0)
continue;
991 tHits.push_back(jht);
993 if(kwire > hiWire) hiWire = kwire;
994 if(kwire < loWire) loWire = kwire;
1003 for(
auto iht : tHits)
tjs.
fHits[iht].InTraj = 0;
1006 myprt<<
"FJT: tHits";
1011 unsigned short ofTraj = USHRT_MAX;
1020 if(
tjs.
fHits[jht].InTraj > 0)
break;
1033 if(tHits.size() < 2)
return false;
1035 std::vector<std::vector<unsigned int>> tpHits;
1036 unsigned short ii, iht, ipt;
1041 unsigned short pass =
fMinPts.size() - 1;
1042 if(!
StartTraj(work, tHits[0], tHits[tHits.size()-1], pass))
return false;
1045 constexpr
float pointSize = 1;
1049 if(tHits.size() > 6) {
1051 std::vector<float>
x(tHits.size()),
y(tHits.size()), yerr2(tHits.size(), 1000.);
1052 float intcpt, slope, intcpterr, slopeerr, chidof;
1054 for(ii = 0; ii < tHits.size(); ++ii) {
1056 if(
tjs.
fHits[iht].InTraj == INT_MAX)
return false;
1057 x[ii] =
tjs.
fHits[iht].ArtPtr->WireID().Wire;
1062 if(jtPrt)
mf::LogVerbatim(
"TC")<<
" tHits line fit chidof "<<chidof<<
" Angle "<<atan(slope);
1064 if(chidof == 999.)
return false;
1066 work.
Pts[0].Ang = atan(slope);
1067 work.
Pts[0].Dir[0] = cos(work.
Pts[0].Ang);
1068 work.
Pts[0].Dir[1] = sin(work.
Pts[0].Ang);
1072 double cs = cos(-work.
Pts[0].Ang);
1073 double sn = sin(-work.
Pts[0].Ang);
1074 float tAlong, minAlong = 1E6, maxAlong = -1E6;
1076 std::vector<SortEntry> sortVec(tHits.size());
1078 for(ii = 0; ii < x.size(); ++ii) {
1079 tAlong = cs * x[ii] - sn *
y[ii];
1080 if(tAlong < minAlong) minAlong = tAlong;
1081 if(tAlong > maxAlong) maxAlong = tAlong;
1082 sortEntry.index = ii;
1083 sortEntry.val = tAlong;
1084 sortVec[ii] = sortEntry;
1088 std::vector<unsigned int>
tmp(sortVec.size());
1090 for(ii = 0; ii < sortVec.size(); ++ii)
tmp[ii] = tHits[sortVec[ii].index];
1093 unsigned short npts = (
unsigned short)((maxAlong - minAlong) / pointSize);
1095 if(jtPrt)
mf::LogVerbatim(
"TC")<<
" minAlong "<<minAlong<<
" maxAlong "<<maxAlong<<
" work.Pts[0].Ang "<<work.
Pts[0].Ang<<
" npts "<<npts;
1096 if(npts < 2) npts = 2;
1097 tpHits.resize(npts);
1098 for(ii = 0; ii < tHits.size(); ++ii) {
1099 ipt = (
unsigned short)((sortVec[ii].val - minAlong) / pointSize);
1100 if(ipt > npts - 1) ipt = npts - 1;
1102 if(tpHits[ipt].size() < 16) tpHits[ipt].push_back(tHits[ii]);
1107 tpHits.resize(tHits.size());
1108 for(ii = 0; ii < tHits.size(); ++ii) {
1109 tpHits[ii].push_back(tHits[ii]);
1114 work.
Pts[0].Hits = tpHits[0];
1115 for(
auto iht : tpHits[0])
tjs.
fHits[iht].InTraj = work.
ID;
1117 work.
Pts[0].UseHit.set();
1119 work.
Pts[0].Pos = work.
Pts[0].HitPos;
1124 for(ipt = 1; ipt < tpHits.size(); ++ipt) {
1125 if(tpHits[ipt].empty())
continue;
1127 unsigned short lastPt = work.
Pts.size() - 1;
1130 tp.
Hits = tpHits[ipt];
1131 for(
auto iht : tpHits[ipt])
tjs.
fHits[iht].InTraj = work.
ID;
1138 for(
auto iht : tpHits[ipt])
tjs.
fHits[iht].InTraj = 0;
1141 work.
Pts.push_back(tp);
1171 if(ipt > tj.
Pts.size() - 1)
return;
1181 std::vector<int> wires(1);
1182 wires[0] = std::nearbyint(tp.
Pos[0]);
1183 if(wires[0] < 0 || wires[0] > (
int)
tjs.
LastWire[plane]-1)
return;
1193 if(wires[0] < (
int)
tjs.
LastWire[plane]-1) wires.push_back(wires[0] + 1);
1194 if(wires[0] > 0) wires.push_back(wires[0] - 1);
1196 if(wires[0] > 0) wires.push_back(wires[0] - 1);
1197 if(wires[0] < (
int)
tjs.
LastWire[plane]-1) wires.push_back(wires[0] + 1);
1203 myprt<<
" AddLAHits: Pos "<<
PrintPos(
tjs, tp)<<
" tp.AngleCode "<<tp.
AngleCode<<
" Wires under consideration";
1204 for(
auto& wire : wires) myprt<<
" "<<wire;
1213 std::array<int, 2> wireWindow;
1214 std::array<float, 2> timeWindow;
1216 timeWindow[0] = ltp.
Pos[1] - pos1Window;
1217 timeWindow[1] = ltp.
Pos[1] + pos1Window;
1221 for(
unsigned short ii = 0; ii < wires.size(); ++ii) {
1222 int wire = wires[ii];
1223 if(wire < 0 || wire > (
int)
tjs.
LastWire[plane])
continue;
1227 wireWindow[0] = wire;
1228 wireWindow[1] = wire;
1232 if(hitsNear) sigOK =
true;
1233 for(
auto& iht : closeHits) {
1237 if(std::find(oldHits.begin(), oldHits.end(), iht) != oldHits.end())
continue;
1238 tp.
Hits.push_back(iht);
1249 if(tp.
Hits.empty())
return;
1251 if(tp.
Hits.size() > 16) tp.
Hits.resize(16);
1257 unsigned short nAvailable = 0;
1258 unsigned int otherTjHit = INT_MAX;
1259 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1261 if(
hit.InTraj == INT_MAX)
continue;
1262 if(
hit.InTraj > 0) {
1263 otherTjHit = tp.
Hits[ii];
1268 if(nAvailable == 0 && otherTjHit != UINT_MAX) {
1270 unsigned short otherTj =
tjs.
fHits[otherTjHit].InTraj - 1;
1273 unsigned short atPt = USHRT_MAX;
1274 for(
unsigned short ipt = 0; ipt < otj.
Pts.size(); ++ipt) {
1275 for(
auto& iht : otj.
Pts[ipt].Hits) {
1276 if(iht == otherTjHit) {
1281 if(atPt != USHRT_MAX)
break;
1284 if(
prt)
mf::LogVerbatim(
"TC")<<
" Found a VLA merge candidate trajectory "<<otj.
ID<<
". Set StopFlag[kAtTj] and stop stepping";
1291 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1292 unsigned int iht = tp.
Hits[ii];
1293 if(
tjs.
fHits[iht].InTraj != 0)
continue;
1314 if(tj.
Pts.empty())
return;
1315 if(ipt > tj.
Pts.size() - 1)
return;
1318 if(tj.
Pts[ipt].AngleCode == 2) {
1322 std::vector<unsigned int> closeHits;
1324 unsigned int lastPtWithUsedHits = tj.
EndPt[1];
1327 unsigned int wire = std::nearbyint(tp.
Pos[0]);
1334 float dw = tp.
Pos[0] - tj.
Pts[lastPtWithUsedHits].Pos[0];
1335 float dt = tp.
Pos[1] - tj.
Pts[lastPtWithUsedHits].Pos[1];
1336 float dpos = sqrt(dw * dw + dt * dt);
1337 float projErr = dpos * tj.
Pts[lastPtWithUsedHits].AngErr;
1339 float deltaCut = 3 * (projErr + tp.
DeltaRMS);
1346 if(deltaCut < 0.5) deltaCut = 0.5;
1347 if(deltaCut > 3) deltaCut = 3;
1356 float bigDelta = 2 * deltaCut;
1357 unsigned int imBig = UINT_MAX;
1358 tp.
Delta = deltaCut;
1360 float maxDeltaCut = 2 * bigDelta;
1365 mf::LogVerbatim(
"TC")<<
" AddHits: wire "<<wire<<
" tp.Pos[0] "<<tp.
Pos[0]<<
" projTick "<<rawProjTick<<
" deltaRMS "<<tp.
DeltaRMS<<
" tp.Dir[0] "<<tp.
Dir[0]<<
" deltaCut "<<deltaCut<<
" dpos "<<dpos<<
" projErr "<<projErr<<
" ExpectedHitsRMS "<<
ExpectedHitsRMS(
tjs, tp);
1368 std::vector<unsigned int> hitsInMultiplet;
1371 unsigned int ipl = planeID.
Plane;
1376 unsigned int firstHit = (
unsigned int)
tjs.
WireHitRange[ipl][wire].first;
1377 unsigned int lastHit = (
unsigned int)
tjs.
WireHitRange[ipl][wire].second;
1379 for(
unsigned int iht = firstHit; iht < lastHit; ++iht) {
1381 if(
hit.InTraj == tj.
ID)
continue;
1382 if(
hit.InTraj == INT_MAX)
continue;
1383 if(rawProjTick >
hit.StartTick && rawProjTick <
hit.EndTick) sigOK =
true;
1386 if(delta > maxDeltaCut)
continue;
1387 float dt = std::abs(ftime - tp.
Pos[1]);
1388 unsigned short localIndex = 0;
1390 if(
prt && delta < 100 && dt < 100) {
1392 myprt<<
" iht "<<iht;
1394 myprt<<
" delta "<<std::fixed<<std::setprecision(2)<<delta<<
" deltaCut "<<deltaCut<<
" dt "<<dt;
1395 myprt<<
" BB Mult "<<hitsInMultiplet.size()<<
" localIndex "<<localIndex<<
" RMS "<<std::setprecision(1)<<
hit.RMS;
1396 myprt<<
" Chi "<<std::setprecision(1)<<
hit.GoodnessOfFit;
1397 myprt<<
" InTraj "<<
hit.InTraj;
1398 myprt<<
" Chg "<<(int)
hit.Integral;
1399 myprt<<
" mcpIndex "<<
hit.MCPartListIndex;
1400 myprt<<
" Signal? "<<sigOK;
1402 if(
hit.InTraj == 0 && delta < bigDelta && hitsInMultiplet.size() < 3 && !tj.
AlgMod[
kRvPrp]) {
1407 if(delta > deltaCut)
continue;
1408 if(std::find(closeHits.begin(), closeHits.end(), iht) != closeHits.end())
continue;
1409 closeHits.push_back(iht);
1410 if(hitsInMultiplet.size() > 1) {
1412 for(
auto& jht : hitsInMultiplet) {
1414 if(std::find(closeHits.begin(), closeHits.end(), jht) != closeHits.end())
continue;
1415 closeHits.push_back(jht);
1422 myprt<<
"closeHits ";
1427 myprt<<
" imBig "<<imBig;
1430 if(closeHits.empty() && imBig == UINT_MAX) {
1434 if(imBig <
tjs.
fHits.size() && closeHits.empty()) {
1435 closeHits.push_back(imBig);
1438 if(!closeHits.empty()) sigOK =
true;
1440 tp.
Hits.insert(tp.
Hits.end(), closeHits.begin(), closeHits.end());
1441 if(tp.
Hits.size() > 16) {
1464 if(ipt > tj.
Pts.size() - 1)
return;
1467 if(tp.
Hits.empty())
return;
1471 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1472 unsigned int iht = tp.
Hits[ii];
1473 if(
tjs.
fHits[iht].InTraj > 0)
continue;
1477 if(
prt)
mf::LogVerbatim(
"TC")<<
"FUH: Using all hits on seed trajectory on the last pass";
1482 if(ipt < 5) useChg =
false;
1483 float chgPullCut = 1000;
1488 if(tj.
MCSMom < 30) chgPullCut *= 2;
1495 float pathInv = std::abs(tp.
Dir[0]);
1496 if(pathInv < 0.05) pathInv = 0.05;
1499 tp.
Delta = maxDelta;
1501 unsigned short imbest = USHRT_MAX;
1502 std::vector<float> deltas(tp.
Hits.size(), 100);
1504 float bestDelta = maxDelta;
1505 unsigned short nAvailable = 0;
1506 unsigned short firstAvailable = USHRT_MAX;
1507 unsigned short lastAvailable = USHRT_MAX;
1508 unsigned short firstUsed = USHRT_MAX;
1509 unsigned short imBadRecoHit = USHRT_MAX;
1510 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1512 unsigned int iht = tp.
Hits[ii];
1514 if(delta < bestDelta) bestDelta = delta;
1516 if(firstUsed == USHRT_MAX) firstUsed = ii;
1519 if(
tjs.
fHits[iht].GoodnessOfFit < 0 ||
tjs.
fHits[iht].GoodnessOfFit > 100) imBadRecoHit = ii;
1520 if(firstAvailable == USHRT_MAX) firstAvailable = ii;
1531 if(delta < tp.
Delta) {
1537 float chgWght = 0.5;
1539 if(
prt)
mf::LogVerbatim(
"TC")<<
" firstAvailable "<<firstAvailable<<
" lastAvailable "<<lastAvailable<<
" firstUsed "<<firstUsed<<
" imbest "<<imbest<<
" single hit. tp.Delta "<<std::setprecision(2)<<tp.
Delta<<
" bestDelta "<<bestDelta<<
" path length "<<1 / pathInv<<
" imBadRecoHit "<<imBadRecoHit;
1540 if(imbest == USHRT_MAX || nAvailable == 0)
return;
1541 unsigned int bestDeltaHit = tp.
Hits[imbest];
1545 if(tp.
Hits.size() > 2 && nAvailable > 1 && firstUsed != USHRT_MAX && firstAvailable < firstUsed && lastAvailable > firstUsed) {
1546 if(
prt)
mf::LogVerbatim(
"TC")<<
" A hit in the middle of the multiplet is used. Use only the best hit";
1547 tp.
UseHit[imbest] =
true;
1554 std::vector<unsigned int> hitsInMultiplet;
1555 unsigned short localIndex;
1560 myprt<<
" in multiplet:";
1565 if(imBadRecoHit != USHRT_MAX) {
1566 unsigned int iht = tp.
Hits[imBadRecoHit];
1569 tp.
UseHit[imBadRecoHit] =
true;
1575 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1576 unsigned int iht = tp.
Hits[ii];
1577 if(
tjs.
fHits[iht].InTraj > 0)
continue;
1590 if(!useChg || (useChg && (tj.
AveChg <= 0 || tj.
ChgRMS <= 0))) {
1593 tp.
UseHit[imbest] =
true;
1599 if(tj.
PDGCode == 13 && bestDelta < 0.5) {
1601 tp.
UseHit[imbest] =
true;
1607 if(nAvailable == 1 || tp.
AngleCode == 0) {
1608 float bestDeltaHitChgPull = std::abs(
tjs.
fHits[bestDeltaHit].Integral * pathInv / tp.
AveChg - 1) / tj.
ChgRMS;
1609 if(
prt)
mf::LogVerbatim(
"TC")<<
" bestDeltaHitChgPull "<<bestDeltaHitChgPull<<
" chgPullCut "<<chgPullCut;
1610 if(bestDeltaHitChgPull < chgPullCut || tp.
Delta < 0.1) {
1611 tp.
UseHit[imbest] =
true;
1621 if(nAvailable == 2) {
1623 std::vector<unsigned int> tHits;
1624 unsigned short localIndex;
1628 unsigned short ombest = USHRT_MAX;
1629 unsigned int otherHit = INT_MAX;
1630 if(tHits.size() == 2) {
1631 otherHit = tHits[1 - localIndex];
1633 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1635 if(tp.
Hits[ii] == otherHit) {
1642 mf::LogVerbatim(
"TC")<<
" Doublet: imbest "<<imbest<<
" ombest "<<ombest;
1645 if(ombest < tp.
Hits.size()) {
1647 float bestHitDeltaErr = std::abs(tp.
Dir[1]) * 0.17 + std::abs(tp.
Dir[0]) *
HitTimeErr(bestDeltaHit);
1649 float bestDeltaHitFOM = deltas[imbest] / bestHitDeltaErr;
1650 if(bestDeltaHitFOM < 0.5) bestDeltaHitFOM = 0.5;
1652 float bestDeltaHitChgPull = std::abs(
tjs.
fHits[bestDeltaHit].Integral * pathInv / tp.
AveChg - 1) / tj.
ChgRMS;
1653 if(bestDeltaHitChgPull > 1) bestDeltaHitFOM *= chgWght * bestDeltaHitChgPull;
1655 float rmsRat =
tjs.
fHits[bestDeltaHit].RMS / expectedWidth;
1656 if(rmsRat < 1) rmsRat = 1 / rmsRat;
1657 bestDeltaHitFOM *= rmsRat;
1658 if(
prt)
mf::LogVerbatim(
"TC")<<
" bestDeltaHit FOM "<<deltas[imbest]/bestHitDeltaErr<<
" bestDeltaHitChgPull "<<bestDeltaHitChgPull<<
" rmsRat "<<rmsRat<<
" bestDeltaHitFOM "<<bestDeltaHitFOM;
1660 float otherHitDeltaErr = std::abs(tp.
Dir[1]) * 0.17 + std::abs(tp.
Dir[0]) *
HitTimeErr(otherHit);
1661 float otherHitFOM = deltas[ombest] / otherHitDeltaErr;
1662 if(otherHitFOM < 0.5) otherHitFOM = 0.5;
1663 float otherHitChgPull = std::abs(
tjs.
fHits[otherHit].Integral * pathInv / tp.
AveChg - 1) / tj.
ChgRMS;
1664 if(otherHitChgPull > 1) otherHitFOM *= chgWght * otherHitChgPull;
1665 rmsRat =
tjs.
fHits[otherHit].RMS / expectedWidth;
1666 if(rmsRat < 1) rmsRat = 1 / rmsRat;
1667 otherHitFOM *= rmsRat;
1668 if(
prt)
mf::LogVerbatim(
"TC")<<
" otherHit FOM "<<deltas[ombest]/otherHitDeltaErr<<
" otherHitChgPull "<<otherHitChgPull<<
" rmsRat "<<rmsRat<<
" otherHitFOM "<<otherHitFOM;
1670 float doubletChg =
tjs.
fHits[bestDeltaHit].Integral +
tjs.
fHits[otherHit].Integral;
1671 float doubletTime = (
tjs.
fHits[bestDeltaHit].Integral *
tjs.
fHits[bestDeltaHit].PeakTime +
tjs.
fHits[otherHit].Integral *
tjs.
fHits[otherHit].PeakTime) / doubletChg;
1672 doubletChg *= pathInv;
1676 if(
prt)
mf::LogVerbatim(
"TC")<<
" doublet Chg "<<doubletChg<<
" doubletTime "<<doubletTime<<
" doubletRMSTimeErr "<<doubletRMSTimeErr;
1678 if(doubletFOM < 0.5) doubletFOM = 0.5;
1679 float doubletChgPull = std::abs(doubletChg * pathInv / tp.
AveChg - 1) / tj.
ChgRMS;
1680 if(doubletChgPull > 1) doubletFOM *= chgWght * doubletChgPull;
1681 rmsRat = doubletWidthTick / expectedWidth;
1682 if(rmsRat < 1) rmsRat = 1 / rmsRat;
1683 doubletFOM *= rmsRat;
1684 if(
prt)
mf::LogVerbatim(
"TC")<<
" doublet FOM "<<
PointTrajDOCA(
tjs, tp.
Pos[0], doubletTime, tp)/doubletRMSTimeErr<<
" doubletChgPull "<<doubletChgPull<<
" rmsRat "<<rmsRat<<
" doubletFOM "<<doubletFOM;
1685 if(doubletFOM < bestDeltaHitFOM && doubletFOM < otherHitFOM) {
1686 tp.
UseHit[imbest] =
true;
1688 tp.
UseHit[ombest] =
true;
1692 if(bestDeltaHitFOM < otherHitFOM) {
1693 tp.
UseHit[imbest] =
true;
1696 tp.
UseHit[ombest] =
true;
1702 tp.
UseHit[imbest] =
true;
1711 if(nAvailable == tp.
Hits.size()) {
1714 unsigned short cnt = 0;
1715 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1716 unsigned int iht = tp.
Hits[ii];
1717 if(iht -
tjs.
fHits[iht].LocalIndex == hit0) ++cnt;
1720 if(cnt == tp.
Hits.size()) {
1721 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1722 unsigned int iht = tp.
Hits[ii];
1723 if(
tjs.
fHits[iht].InTraj > 0)
continue;
1734 if(
prt)
mf::LogVerbatim(
"TC")<<
" Multiplet: hitsWidth "<<hitsWidth<<
" expectedWidth "<<expectedWidth<<
" tick range "<<(int)minTick<<
" "<<(
int)maxTick;
1736 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1737 unsigned int iht = tp.
Hits[ii];
1738 if(
tjs.
fHits[iht].InTraj > 0)
continue;
1739 if(
tjs.
fHits[iht].PeakTime < minTick)
continue;
1740 if(
tjs.
fHits[iht].PeakTime > maxTick)
continue;
1757 unsigned short endPt = tj.
EndPt[1];
1759 if(tj.
Pts[endPt].AngleCode > 1)
return;
1761 if(tj.
Pts.size() - endPt > 10)
return;
1765 unsigned short plane = planeID.
Plane;
1768 unsigned short lastPt = tj.
Pts.size() - 1;
1769 for(lastPt = tj.
Pts.size() - 1; lastPt >= tj.
EndPt[1]; --lastPt)
if(!tj.
Pts[lastPt].Hits.empty())
break;
1770 auto& lastTP = tj.
Pts[lastPt];
1777 if(lastTP.NTPsFit > 10 && lastTP.DeltaRMS > 0 && (lastTP.Delta / lastTP.DeltaRMS) > 3 && lastTP.ChgPull > 3) {
1778 if(prt)
mf::LogVerbatim(
"TC")<<
" Removing last TP with large Delta "<<lastTP.Delta<<
" and large ChgPull "<<lastTP.ChgPull;
1784 if(tp.DeltaRMS > 0 && (tp.Delta / tp.DeltaRMS) > 3 && tp.ChgPull > 3) {
1793 ltp.
Pos = tj.
Pts[endPt].Pos;
1794 ltp.
Dir = tj.
Pts[endPt].Dir;
1795 double stepSize = std::abs(1/ltp.
Dir[0]);
1796 std::array<int, 2> wireWindow;
1797 std::array<float, 2> timeWindow;
1798 std::vector<int> closeHits;
1799 bool isClean =
true;
1800 for(
unsigned short step = 0; step < 10; ++step) {
1801 for(
unsigned short iwt = 0; iwt < 2; ++iwt) ltp.
Pos[iwt] += ltp.
Dir[iwt] * stepSize;
1802 int wire = std::nearbyint(ltp.
Pos[0]);
1803 wireWindow[0] = wire;
1804 wireWindow[1] = wire;
1805 timeWindow[0] = ltp.
Pos[1] - 5;
1806 timeWindow[1] = ltp.
Pos[1] + 5;
1810 for(
auto iht :
tmp)
if(
tjs.
fHits[iht].InTraj != tj.
ID) closeHits.push_back(iht);
1811 float nWiresPast = 0;
1813 if(ltp.
Dir[0] > 0) {
1815 nWiresPast = ltp.
Pos[0] - lastTP.Pos[0];
1818 nWiresPast = lastTP.Pos[0] - ltp.
Pos[0];
1821 if(nWiresPast > 0.5) {
1822 if(!tmp.empty()) isClean =
false;
1823 if(nWiresPast > 1.5)
break;
1828 unsigned short nAvailable = 0;
1829 for(
auto iht : closeHits)
if(
tjs.
fHits[iht].InTraj == 0) ++nAvailable;
1835 myprt<<
" nAvailable "<<nAvailable;
1836 myprt<<
" isClean "<<isClean;
1839 if(!isClean || nAvailable != closeHits.size())
return;
1841 unsigned short originalEndPt = tj.
EndPt[1] + 1;
1843 for(
unsigned short ipt = originalEndPt; ipt <= lastPt; ++ipt) {
1844 auto& tp = tj.
Pts[ipt];
1845 bool hitsAdded =
false;
1846 for(
unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1848 if(
tjs.
fHits[tp.Hits[ii]].InTraj != 0)
continue;
1849 tp.UseHit[ii] =
true;
1864 for(
unsigned short ipt = originalEndPt; ipt <= lastPt; ++ipt)
UnsetUsedHits(
tjs, tj.
Pts[ipt]);
1878 if(tp.
Hits.empty())
return;
1880 unsigned short nused = 0;
1881 unsigned int iht = 0;
1882 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1888 if(nused == 0)
return;
1895 float pathInv = std::abs(tp.
Dir[0]);
1896 if(pathInv < 0.05) pathInv = 0.05;
1900 float wireErr = tp.
Dir[1] * 0.289;
1902 tp.
HitPosErr2 = wireErr * wireErr + timeErr * timeErr;
1908 std::vector<unsigned int> hitVec;
1910 std::array<float, 2> newpos;
1915 unsigned int loWire = INT_MAX;
1916 unsigned int hiWire = 0;
1917 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1918 if(!tp.
UseHit[ii])
continue;
1919 unsigned int iht = tp.
Hits[ii];
1921 unsigned int wire =
tjs.
fHits[iht].ArtPtr->WireID().Wire;
1922 if(wire < loWire) loWire = wire;
1923 if(wire > hiWire) hiWire = wire;
1924 newpos[0] += chg * wire;
1925 newpos[1] += chg *
tjs.
fHits[iht].PeakTime;
1927 hitVec.push_back(iht);
1930 if(tp.
Chg == 0)
return;
1935 float pathInv = std::abs(tp.
Dir[0]);
1936 if(pathInv < 0.05) pathInv = 0.05;
1940 float dWire = 1 + hiWire - loWire;
1941 float wireErr = tp.
Dir[1] * dWire * 0.289;
1943 tp.
HitPosErr2 = wireErr * wireErr + timeErr2;
1958 if(hitVec.empty())
return 0;
1976 if(tj.AlgMod[
kKilled])
continue;
1977 if(tj.CTP != inCTP)
continue;
1984 std::vector<int> tjlist(2);
1990 bool iterate =
true;
1993 for(
unsigned int it1 = 0; it1 <
tjs.
allTraj.size(); ++it1) {
1997 for(
unsigned short end1 = 0; end1 < 2; ++end1) {
1999 if(tj1.VtxID[end1] > 0)
continue;
2001 TrajPoint tp1 = tj1.Pts[tj1.EndPt[end1]];
2003 if(lastPass && tp1.
NTPsFit > 3) {
2006 auto& lastTP = ttj.Pts[ttj.EndPt[end1]];
2010 tp1 = ttj.Pts[ttj.EndPt[end1]];
2014 if(isVLA) bestFOM = 20;
2016 unsigned int imbest = INT_MAX;
2017 for(
unsigned int it2 = 0; it2 <
tjs.
allTraj.size(); ++it2) {
2018 if(it1 == it2)
continue;
2021 if(tj1.StepDir != tj2.StepDir)
continue;
2022 if(tj2.AlgMod[kKilled])
continue;
2023 if(tj2.CTP != inCTP)
continue;
2027 if(olf > 0.25)
continue;
2028 unsigned short end2 = 1 - end1;
2030 if(tj2.VtxID[end2] > 0)
continue;
2031 TrajPoint& tp2 = tj2.Pts[tj2.EndPt[end2]];
2032 TrajPoint& tp2OtherEnd = tj2.Pts[tj2.EndPt[end1]];
2034 if(std::abs(tp2OtherEnd.
Pos[0] - tp1.
Pos[0]) < std::abs(tp2.
Pos[0] - tp1.
Pos[0]))
continue;
2037 if(tp2.
Pos[0] < tp1.
Pos[0] - 2)
continue;
2039 if(tp2.
Pos[0] > tp1.
Pos[0] + 2)
continue;
2052 unsigned short ipt1, ipt2;
2059 float fom = dang * doca;
2067 if(imbest == INT_MAX)
continue;
2070 unsigned int it2 = imbest;
2072 unsigned short end2 = 1 - end1;
2073 bool loMCSMom = (tj1.MCSMom + tj2.MCSMom) < 150;
2075 if(tj1.Pts.size() > 50 && tj1.MCSMom > 100) {
2077 tp1.
Ang = tj1.Pts[tj1.EndPt[0] + 2].Ang;
2079 tp1.
Ang = tj1.Pts[tj1.EndPt[1] - 2].Ang;
2081 }
else if(loMCSMom) {
2083 unsigned short pt1, pt2;
2095 TrajPoint tp2 = tj2.Pts[tj2.EndPt[end2]];
2096 if(tj2.Pts.size() > 50 && tj2.MCSMom > 100) {
2098 tp2.
Ang = tj2.Pts[tj2.EndPt[0] + 2].Ang;
2100 tp2.
Ang = tj2.Pts[tj2.EndPt[1] - 2].Ang;
2102 }
else if(loMCSMom) {
2104 unsigned short pt1, pt2;
2137 unsigned short e0 = tj1.EndPt[0];
2138 unsigned short e1 = tj1.EndPt[1];
2142 thetaRMS1 *= thetaRMS1 / tj1len;
2148 thetaRMS2 *= thetaRMS2 / tj2len;
2149 float dangErr = 0.5 * sqrt(thetaRMS1 + thetaRMS2);
2152 if(isVLA) docaCut = 15;
2165 bool doMerge = bestDOCA < docaCut && dang < dangCut;
2166 bool showerTjs = tj1.PDGCode == 11 || tj2.PDGCode == 11;
2167 bool hiMCSMom = tj1.MCSMom > 200 || tj2.MCSMom > 200;
2169 if(doMerge && !showerTjs && hiMCSMom && chgPull >
tjs.
ChargeCuts[0] && !isVLA) doMerge =
false;
2171 if(!doMerge && tj1.MCSMom > 900 && tj2.MCSMom > 900 && dang < 0.1 && bestDOCA < docaCut) doMerge =
true;
2174 if(doMerge && chgPull > 2 * chgPullCut) doMerge =
false;
2180 auto& tp1OtherEnd = tj1.Pts[tj1.EndPt[1 - end1]];
2181 auto& tp2OtherEnd = tj2.Pts[tj2.EndPt[1 - end2]];
2182 float nwires = std::abs(tp1OtherEnd.Pos[0] - tp2OtherEnd.Pos[0]);
2183 if(nwires == 0) nwires = 1;
2184 float hitFrac = npwc / nwires;
2192 if(sep > len1) doMerge =
false;
2194 if(sep > len2) doMerge =
false;
2196 if(
prt)
mf::LogVerbatim(
"TC")<<
" merge check sep "<<sep<<
" len1 "<<len1<<
" len2 "<<len2<<
" Merge? "<<doMerge;
2204 if(doMerge && bestDOCA > 1 && chgFrac < chgFracCut) doMerge =
false;
2207 if(doMerge && (tj1.StopFlag[end1][
kBragg] || tj2.StopFlag[end2][
kBragg])) doMerge =
false;
2210 float momAsym = std::abs(tj1.MCSMom - tj2.MCSMom) / (float)(tj1.MCSMom + tj2.MCSMom);
2221 myprt<<
" bestFOM "<<std::fixed<<std::setprecision(2)<<bestFOM;
2222 myprt<<
" bestDOCA "<<std::setprecision(1)<<bestDOCA;
2223 myprt<<
" cut "<<docaCut<<
" isVLA? "<<isVLA;
2224 myprt<<
" dang "<<std::setprecision(2)<<dang<<
" dangCut "<<dangCut;
2225 myprt<<
" chgPull "<<std::setprecision(1)<<chgPull<<
" Cut "<<chgPullCut;
2226 myprt<<
" chgFrac "<<std::setprecision(2)<<chgFrac;
2227 myprt<<
" momAsym "<<momAsym;
2228 myprt<<
" lastPass? "<<lastPass;
2229 myprt<<
" doMerge? "<<doMerge;
2232 if(bestDOCA > docaCut)
continue;
2236 bool didMerge =
false;
2244 tj1.AlgMod[
kMerge] =
true;
2245 tj1.AlgMod[
kMerge] =
true;
2259 aVtx.
Pos[0] = 0.5 * (tp1.
Pos[0] + tp2.
Pos[0]);
2260 aVtx.
Pos[1] = 0.5 * (tp1.
Pos[1] + tp2.
Pos[1]);
2271 float dw = aVtx.
Pos[0] - tp1.
Pos[0];
2272 if(std::abs(dw) > sepCut)
continue;
2273 float dt = aVtx.
Pos[1] - tp1.
Pos[1];
2274 if(std::abs(dt) > sepCut)
continue;
2275 dw = aVtx.
Pos[0] - tp2.
Pos[0];
2276 if(std::abs(dw) > sepCut)
continue;
2277 dt = aVtx.
Pos[1] - tp2.
Pos[1];
2278 if(std::abs(dt) > sepCut)
continue;
2289 if(aVtx.
Pos[0] < tp1.
Pos[0] && aVtx.
Pos[0] < tp2.
Pos[0]) {
2293 if(aVtx.
Pos[0] > tp1.
Pos[0] && aVtx.
Pos[0] > tp2.
Pos[0]) {
2312 aVtx.
Topo = end1 + end2;
2313 tj1.AlgMod[
kMerge] =
true;
2314 tj2.AlgMod[
kMerge] =
true;
2316 if(tj1.StopFlag[end1][kBragg] && !tj2.StopFlag[end2][kBragg]) tj1.PDGCode = 211;
2317 if(tj2.StopFlag[end2][kBragg] && !tj1.StopFlag[end1][kBragg]) tj2.PDGCode = 211;
2330 bool didMerge =
false;
2338 tj1.AlgMod[
kMerge] =
true;
2339 tj1.AlgMod[
kMerge] =
true;
2347 if(tj1.AlgMod[kKilled])
break;
2396 if(tj.
Pts.empty())
return;
2400 unsigned short plane = planeID.
Plane;
2402 unsigned short lastPtWithUsedHits = tj.
EndPt[1];
2404 unsigned short lastPt = lastPtWithUsedHits;
2409 ltp.
Pos = tj.
Pts[lastPt].Pos;
2410 ltp.
Dir = tj.
Pts[lastPt].Dir;
2418 unsigned short nMissedSteps = 0;
2420 for(
unsigned short step = 1; step < 10000; ++step) {
2422 lastPt = tj.
Pts.size() - 1;
2423 tp = tj.
Pts[lastPt];
2426 if(tp.
AngleCode < 2) stepSize = std::abs(1/ltp.
Dir[0]);
2428 for(
unsigned short iwt = 0; iwt < 2; ++iwt) ltp.
Pos[iwt] += ltp.
Dir[iwt] * stepSize;
2431 if(ivx != USHRT_MAX) {
2454 tj.
Pts.push_back(tp);
2456 lastPt = tj.
Pts.size() - 1;
2464 if(tj.
Pts[lastPt].Hits.empty()) {
2467 if(tj.
Pts[lastPt].AngleCode == 0 && lastPt == 2)
return;
2475 if(tj.
Pts[lastPt].AngleCode > 0 && nMissedSteps > 4 && !
SignalAtTp(
tjs, ltp)) {
2480 unsigned short lastPtWithHits = lastPt - 1;
2483 float nMissedWires = tps * std::abs(ltp.
Dir[0]) - dwc;
2486 if(
prt)
mf::LogVerbatim(
"TC")<<
" StepCrawl: no signal at ltp "<<
PrintPos(
tjs, ltp)<<
" nMissedWires "<<std::fixed<<std::setprecision(1)<<nMissedWires<<
" dead wire count "<<dwc<<
" maxWireSkip "<<maxWireSkip<<
" tj.PGDCode "<<tj.
PDGCode;
2487 if(nMissedWires > maxWireSkip) {
2491 if(tj.
EndPt[1] < tj.
Pts.size() - 1 && tj.
Pts[tj.
EndPt[1]+1].Hits.size() == 1) {
2492 unsigned short lastLonelyPoint = tj.
EndPt[1] + 1;
2493 unsigned int iht = tj.
Pts[lastLonelyPoint].Hits[0];
2494 if(
tjs.
fHits[iht].InTraj == 0 && tj.
Pts[lastLonelyPoint].Delta < 3 * tj.
Pts[lastLonelyPoint].DeltaRMS) {
2496 tj.
Pts[lastLonelyPoint].UseHit[0] =
true;
2513 if(lastPt > 0 &&
PosSep2(tj.
Pts[lastPt].Pos, tj.
Pts[lastPt-1].Pos) < 0.1)
return;
2520 if(tj.
Pts[lastPt].Chg == 0) {
2525 float nMissedWires = tps * std::abs(ltp.
Dir[0]) - dwc;
2526 if(
prt)
mf::LogVerbatim(
"TC")<<
" Hits exist on the trajectory but are not used. Missed wires "<<std::nearbyint(nMissedWires)<<
" dead wire count "<<(int)dwc;
2546 if(tj.
Pts.size() == 3) {
2556 if(dang > 0.5) badTj =
false;
2559 if(!badTj && tj.
Pts[2].Delta > 2) badTj =
true;
2567 ltp.
Pos = tj.
Pts[lastPt].Pos;
2568 ltp.
Dir = tj.
Pts[lastPt].Dir;
2597 unsigned short killPts = 0;
2599 bool keepGoing =
true;
2623 unsigned int onWire = (float)(std::nearbyint(tj.
Pts[lastPt].Pos[0]));
2624 float nSteps = (float)(step - tj.
Pts[lastPt - killPts].Step);
2625 if(
prt)
mf::LogVerbatim(
"TC")<<
"TRP killing "<<killPts<<
" after "<<nSteps<<
" steps from prev TP. Current tp.Pos "<<tp.
Pos[0]<<
" "<<tp.
Pos[1];
2627 tj.
Pts[lastPt].Pos[0] += nSteps * tj.
Pts[lastPt].Dir[0];
2628 tj.
Pts[lastPt].Pos[1] += nSteps * tj.
Pts[lastPt].Dir[1];
2629 if(tj.
Pts[lastPt].AngleCode == 0) {
2631 float dw = onWire - tj.
Pts[lastPt].Pos[0];
2632 tj.
Pts[lastPt].Pos[0] = onWire;
2633 tj.
Pts[lastPt].Pos[1] += dw * tj.
Pts[lastPt].Dir[1] / tj.
Pts[lastPt].Dir[0];
2638 ltp.
Pos = tj.
Pts[lastPt].Pos;
2639 ltp.
Dir = tj.
Pts[lastPt].Dir;
2641 if(!keepGoing)
break;
2656 if(tj.
ID > 0)
return true;
2659 if(tj.
Pts.size() < 3)
return false;
2662 std::vector<int> tID;
2663 std::vector<unsigned short> tCnt;
2665 unsigned short hitCnt = 0;
2666 unsigned short nAvailable = 0;
2667 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
2668 for(
unsigned short ii = 0; ii < tj.
Pts[ipt].Hits.size(); ++ii) {
2670 if(tj.
Pts[ipt].UseHit[ii]) {
2674 unsigned int iht = tj.
Pts[ipt].Hits[ii];
2677 unsigned short indx;
2678 for(indx = 0; indx < tID.size(); ++indx)
if(tID[indx] == tjid)
break;
2679 if(indx == tID.size()) {
2680 tID.push_back(tjid);
2693 int oldTjID = INT_MAX;
2697 myprt<<
"IsGhost tj hits size cut "<<hitCnt<<
" tID_tCnt";
2698 for(
unsigned short ii = 0; ii < tCnt.size(); ++ii) myprt<<
" "<<tID[ii]<<
"_"<<tCnt[ii];
2699 myprt<<
"\nAvailable hits "<<nAvailable;
2702 for(
unsigned short ii = 0; ii < tCnt.size(); ++ii) {
2703 if(tCnt[ii] > hitCnt) {
2708 if(oldTjID == INT_MAX)
return false;
2709 int oldTjIndex = oldTjID - 1;
2713 if(oTj.
PDGCode == 13 && hitCnt < 0.1 * oTj.
Pts.size())
return false;
2718 int wire0 = INT_MAX;
2720 for(
auto& otp : oTj.
Pts) {
2721 int wire = std::nearbyint(otp.Pos[0]);
2722 if(wire < wire0) wire0 = wire;
2723 if(wire > wire1) wire1 = wire;
2726 int nwires = wire1 - wire0 + 1;
2727 std::vector<float> oTjPos1(nwires, -1);
2728 unsigned short nMissedWires = 0;
2729 for(
unsigned short ipt = oTj.
EndPt[0]; ipt <= oTj.
EndPt[1]; ++ipt) {
2730 if(oTj.
Pts[ipt].Chg == 0)
continue;
2731 int wire = std::nearbyint(oTj.
Pts[ipt].Pos[0]);
2732 int indx = wire - wire0;
2733 if(indx < 0 || indx > nwires - 1)
continue;
2734 oTjPos1[indx] = oTj.
Pts[ipt].Pos[1];
2738 unsigned short ngh = 0;
2740 unsigned short nghPlus = 0;
2742 unsigned short firstPtInoTj = USHRT_MAX;
2743 unsigned short lastPtInoTj = 0;
2745 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
2746 if(tj.
Pts[ipt].Chg > 0) {
2750 int wire = std::nearbyint(tj.
Pts[ipt].Pos[0]);
2751 int indx = wire - wire0;
2752 if(indx < 0 || indx > nwires - 1)
continue;
2753 if(oTjPos1[indx] > 0) {
2755 bool HitInoTj =
false;
2756 for(
unsigned short ii = 0; ii < tj.
Pts[ipt].Hits.size(); ++ii) {
2757 unsigned int iht = tj.
Pts[ipt].Hits[ii];
2758 if(
tjs.
fHits[iht].InTraj == oldTjID) HitInoTj =
true;
2763 if(tp.
Pos[1] > oTjPos1[indx]) ++nghPlus;
2764 if(firstPtInoTj == USHRT_MAX) firstPtInoTj = ipt;
2770 if(
prt)
mf::LogVerbatim(
"TC")<<
" Number of missed wires in oTj gaps "<<nMissedWires<<
" Number of ghost hits in these gaps "<<ngh<<
" nghPlus "<<nghPlus<<
" cut "<<0.2 * nMissedWires;
2772 if(ngh < 0.2 * nMissedWires)
return false;
2773 if(firstPtInoTj > lastPtInoTj)
return false;
2776 if(!(nghPlus > 0.8 * ngh || nghPlus < 0.2 * ngh) )
return false;
2778 if(
prt)
mf::LogVerbatim(
"TC")<<
" Trajectory is a ghost of "<<oldTjID<<
" first point in oTj "<<firstPtInoTj<<
" last point "<<lastPtInoTj;
2781 for(
unsigned short ipt = firstPtInoTj; ipt <= lastPtInoTj; ++ipt) {
2782 if(tj.
Pts[ipt].Chg == 0)
continue;
2788 for(
unsigned short ipt = lastPtInoTj; ipt <= tj.
Pts.size(); ++ipt) {
2789 if(tj.
Pts[ipt].Chg > 0) ++ngh;
2793 for(
unsigned short ipt = lastPtInoTj; ipt <= tj.
EndPt[1]; ++ipt) {
2822 if(tHits.size() < 2)
return false;
2824 std::vector<unsigned int> hitsInMuliplet, nearbyHits;
2825 for(
auto iht : tHits) {
2828 for(
auto mht : hitsInMuliplet) {
2829 if(std::find(nearbyHits.begin(), nearbyHits.end(), mht) == nearbyHits.end()) {
2830 nearbyHits.push_back(mht);
2836 std::vector<unsigned short> tID, tCnt;
2837 unsigned short itj, indx;
2838 for(
auto iht : nearbyHits) {
2839 if(
tjs.
fHits[iht].InTraj <= 0)
continue;
2841 for(indx = 0; indx < tID.size(); ++indx)
if(tID[indx] == itj)
break;
2842 if(indx == tID.size()) {
2849 if(tCnt.empty())
return false;
2852 unsigned short tCut = 0.5 * tHits.size();
2853 unsigned short ii, jj;
2858 myprt<<
"IsGhost tHits size "<<tHits.size()<<
" cut fraction "<<tCut<<
" tID_tCnt";
2859 for(ii = 0; ii < tCnt.size(); ++ii) myprt<<
" "<<tID[ii]<<
"_"<<tCnt[ii];
2862 for(ii = 0; ii < tCnt.size(); ++ii) {
2863 if(tCnt[ii] > tCut) {
2868 if(itj >
tjs.
allTraj.size() - 1)
return false;
2873 unsigned int iht, tht;
2875 for(ii = 0; ii < tp.Hits.size(); ++ii) {
2877 if(
tjs.
fHits[iht].InTraj != 0)
continue;
2878 for(jj = 0; jj < tHits.size(); ++jj) {
2880 if(tht != iht)
continue;
2881 tp.UseHit[ii] =
true;
2951 bool isVLA = (tj.
Pts[tj.
EndPt[1]].AngleCode == 2);
2953 bool isSA = (tj.
Pts[tj.
EndPt[1]].AngleCode == 0);
2958 if(tj.
EndPt[1] < tj.
Pts.size() - 1) {
2970 if(tj.
Pts.size() < 10) {
2972 float minWidth = 999;
2973 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
2974 if(tj.
Pts[ipt].Chg == 0)
continue;
2975 if(tj.
Pts[ipt].HitPosErr2 > maxWidth) maxWidth = tj.
Pts[ipt].HitPosErr2;
2976 if(tj.
Pts[ipt].HitPosErr2 < minWidth) minWidth = tj.
Pts[ipt].HitPosErr2;
2979 if(maxWidth > 10 * minWidth) {
2980 if(
prt)
mf::LogVerbatim(
"TC")<<
" TP width variation too large: minWidth "<<minWidth<<
" maxWidth "<<maxWidth;
3000 if(tj.
EndPt[1] < 4)
return;
3008 unsigned short newSize = USHRT_MAX;
3009 unsigned short lastPtToChk = tj.
EndPt[1] - 4;
3010 float deltaCut = 2 * tj.
Pts[lastPtToChk].DeltaRMS;
3011 for(
unsigned short ipt = tj.
EndPt[1]; ipt > lastPtToChk; --ipt) {
3013 if(tj.
Pts[ipt].Delta < deltaCut)
break;
3014 float drat = tj.
Pts[ipt].Delta / tj.
Pts[ipt-1].Delta;
3015 if(drat > 1.2) newSize = ipt;
3017 if(newSize != USHRT_MAX) {
3028 short nStepBegin = tj.
Pts[2].Step - tj.
Pts[1].Step;
3030 unsigned short lastPt = tj.
Pts.size() - 1;
3031 unsigned short newSize = tj.
Pts.size();
3032 for(
unsigned short ipt = lastPt; ipt > lastPt - 2; --ipt) {
3033 nStepEnd = tj.
Pts[ipt].Step - tj.
Pts[ipt - 1].Step;
3034 if(nStepEnd > 3 * nStepBegin) newSize = ipt;
3036 if(
prt)
mf::LogVerbatim(
"TC")<<
"CTStepChk: check number of steps. newSize "<<newSize<<
" tj.Pts.size() "<<tj.
Pts.size();
3037 if(newSize < tj.
Pts.size()) {
3041 tj.
Pts.resize(newSize);
3054 float frac = npwc / npts;
3076 if(tj.
Pts.size() < 15)
return;
3077 if(tj.
MCSMom < 100)
return;
3086 unsigned short endPt = tj.
EndPt[1];
3087 if(tj.
Pts[endPt].NTPsFit < 5)
return;
3088 if(tj.
Pts[endPt].NTPsFit > endPt)
return;
3090 unsigned short kinkPt = endPt - tj.
Pts[endPt].NTPsFit;
3092 if(
prt)
mf::LogVerbatim(
"TC")<<
" kinkPt "<<kinkPt<<
" NTPsFit at kinkPt "<<tj.
Pts[kinkPt].NTPsFit<<
" max "<<0.5 * kinkPt;
3093 if(kinkPt < 5)
return;
3095 if(tj.
Pts[kinkPt].NTPsFit > 0.5 * kinkPt)
return;
3097 unsigned short maxPtsFit = tj.
Pts[kinkPt].NTPsFit;
3098 unsigned short atPt = kinkPt;
3099 for(
unsigned short ipt = kinkPt; kinkPt > tj.
EndPt[0] + 5; --ipt) {
3100 if(tj.
Pts[ipt].NTPsFit > maxPtsFit) {
3101 maxPtsFit = tj.
Pts[ipt].NTPsFit;
3105 if(tj.
Pts[ipt].NTPsFit < maxPtsFit)
break;
3108 if(atPt < 5)
return;
3114 tj.
Pts.resize(atPt + 1);
3135 if(tj.
Pts.size() < 3)
return;
3137 unsigned short lastPtToChk = 10;
3140 unsigned short atPt = tj.
EndPt[1];
3141 unsigned short maxPtsFit = 0;
3142 for(
unsigned short ipt = tj.
EndPt[0]; ipt < lastPtToChk; ++ipt) {
3143 if(tj.
Pts[ipt].Chg == 0)
continue;
3144 if(tj.
Pts[ipt].NTPsFit >= maxPtsFit) {
3145 maxPtsFit = tj.
Pts[ipt].NTPsFit;
3148 if(maxPtsFit > 20)
break;
3152 unsigned short firstPtFit = tj.
EndPt[0];
3153 unsigned short cnt = 0;
3154 for(
unsigned short ii = 1; ii < tj.
Pts.size(); ++ii) {
3155 if(ii > atPt)
break;
3156 unsigned short ipt = atPt - ii;
3157 if(tj.
Pts[ipt].Chg == 0)
continue;
3159 if(cnt == maxPtsFit) {
3165 bool needsRevProp = firstPtFit > 3;
3181 needsRevProp =
true;
3183 mf::LogVerbatim(
"TC")<<
"FTB: Close unused hits found near EndPt[0] "<<tp.
Hits.size()<<
" or dead wire. Call ReversePropagate";
3190 mf::LogVerbatim(
"TC")<<
"FTB: maxPtsFit "<<maxPtsFit<<
" at point "<<atPt<<
" firstPtFit "<<firstPtFit<<
" Needs ReversePropagate? "<<needsRevProp;
3221 if(npwc < 6)
return;
3223 if(npwc < 10 && tj.
MCSMom < 100)
return;
3232 unsigned short firstPt = tj.
EndPt[0];
3237 if(atPt == tj.
EndPt[0])
return;
3239 float maxDelta = 4 * tj.
Pts[tj.
EndPt[1]].DeltaRMS;
3243 bool maskPts =
false;
3244 for(
unsigned short ii = 1; ii < tj.
Pts.size(); ++ii) {
3245 if(ii > atPt)
break;
3246 unsigned int ipt = atPt - ii;
3248 tp.
Dir = tj.
Pts[atPt].Dir;
3249 tp.
Ang = tj.
Pts[atPt].Ang;
3253 float dw = tp.
Pos[0] - tj.
Pts[atPt].Pos[0];
3254 if(tp.
Dir[0] != 0) tp.
Pos[1] = tj.
Pts[atPt].Pos[1] + dw * tp.
Dir[1] / tp.
Dir[0];
3255 bool newHits =
false;
3257 tj.
Pts[ipt].DeltaRMS = tj.
Pts[atPt].DeltaRMS;
3258 tj.
Pts[ipt].NTPsFit = tj.
Pts[atPt].NTPsFit;
3259 tj.
Pts[ipt].FitChi = tj.
Pts[atPt].FitChi;
3260 tj.
Pts[ipt].AveChg = tj.
Pts[atPt].AveChg;
3262 if(tj.
Pts[ipt].Delta > maxDelta) maskPts =
true;
3287 if(npwc < 6)
return;
3289 if(npwc < 10 && tj.
MCSMom < 100)
return;
3301 if(atPt == tj.
EndPt[1])
return;
3304 for(
unsigned short ipt = atPt + 1; ipt <= tj.
EndPt[1]; ++ipt) {
3306 tp.
Dir = tj.
Pts[atPt].Dir;
3307 tp.
Ang = tj.
Pts[atPt].Ang;
3311 float dw = tp.
Pos[0] - tj.
Pts[atPt].Pos[0];
3312 if(tp.
Dir[0] != 0) tp.
Pos[1] = tj.
Pts[atPt].Pos[1] + dw * tp.
Dir[1] / tp.
Dir[0];
3314 tj.
Pts[ipt].DeltaRMS = tj.
Pts[atPt].DeltaRMS;
3315 tj.
Pts[ipt].NTPsFit = tj.
Pts[atPt].NTPsFit;
3316 tj.
Pts[ipt].FitChi = tj.
Pts[atPt].FitChi;
3317 tj.
Pts[ipt].AveChg = tj.
Pts[atPt].AveChg;
3338 short firstPtWithChg = tj.
EndPt[0];
3342 short minMCSMom = 0.7 * tj.
MCSMom;
3343 while(firstPtWithChg < tj.
EndPt[1]) {
3344 short nextPtWithChg = firstPtWithChg + 1;
3346 for(nextPtWithChg = firstPtWithChg + 1; nextPtWithChg < tj.
EndPt[1]; ++nextPtWithChg) {
3347 if(tj.
Pts[nextPtWithChg].Chg > 0)
break;
3349 if(nextPtWithChg == firstPtWithChg + 1) {
3355 if(nextPtWithChg < (tj.
EndPt[1] - 1) && tj.
Pts[nextPtWithChg + 1].Chg == 0) {
3356 firstPtWithChg = nextPtWithChg;
3360 if(tj.
Pts[firstPtWithChg].Chg > 0) {
3361 float chgrat = tj.
Pts[nextPtWithChg].Chg / tj.
Pts[firstPtWithChg].Chg;
3362 if(chgrat < 0.7 || chgrat > 1.4) {
3363 firstPtWithChg = nextPtWithChg;
3383 if(tj.
Pts.size() < 10) {
3386 short chgCutPt = tj.
EndPt[0] + 5;
3387 if(firstPtWithChg < chgCutPt) {
3392 chgCutPt = tj.
EndPt[1] - 5;
3393 if(chgCutPt < tj.
EndPt[0]) chgCutPt = tj.
EndPt[0];
3394 if(nextPtWithChg > chgCutPt) maxChg = 1E6;
3399 for(
unsigned short mpt = firstPtWithChg + 1; mpt < nextPtWithChg; ++mpt) {
3400 if(tj.
Pts[mpt].Chg > 0) {
3401 mf::LogWarning(
"TC")<<
"FillGaps coding error: firstPtWithChg "<<firstPtWithChg<<
" mpt "<<mpt<<
" nextPtWithChg "<<nextPtWithChg;
3405 bool filled =
false;
3407 for(
unsigned short ii = 0; ii < tj.
Pts[mpt].Hits.size(); ++ii) {
3408 unsigned int iht = tj.
Pts[mpt].Hits[ii];
3409 if(
tjs.
fHits[iht].InTraj > 0)
continue;
3412 if(delta > maxDelta)
continue;
3413 tj.
Pts[mpt].UseHit[ii] =
true;
3418 if(chg > maxChg ||
MCSMom(
tjs, tj) < minMCSMom) {
3432 firstPtWithChg = nextPtWithChg;
3449 if(tj.
MCSMom < 100)
return;
3450 if(tj.
Pts.size() < 50)
return;
3452 unsigned short ept = tj.
EndPt[1];
3457 if(lastTp.
FitChi < 1)
return;
3459 unsigned short npts = USHRT_MAX;
3460 float lastDelta = lastTp.
Delta;
3462 for(
unsigned short ii = 1; ii < 20; ++ii) {
3463 unsigned short ipt = ept - ii;
3465 if(tp.
Chg == 0)
continue;
3470 lastDelta = tp.
Delta;
3476 if(npts == USHRT_MAX)
return;
3478 if(npts < 4)
return;
3485 for(
unsigned short ii = 1; ii <= npts; ++ii) {
3486 unsigned short ipt = ept - ii;
3488 if(tp.
Chg == 0)
continue;
3489 tp.
Dir = tj.
Pts[ept].Dir;
3490 tp.
Ang = tj.
Pts[ept].Ang;
3494 float dw = tp.
Pos[0] - tj.
Pts[ept].Pos[0];
3495 if(tp.
Dir[0] != 0) tp.
Pos[1] = tj.
Pts[ept].Pos[1] + dw * tp.
Dir[1] / tp.
Dir[0];
3518 if(tj.
Pts[tj.
EndPt[1]].AngleCode == 0)
return;
3523 unsigned short ii, stopPt;
3526 unsigned short lastMult1Pt = USHRT_MAX;
3528 unsigned short nHiMultPt = 0;
3530 unsigned short nHiMultPtHits = 0;
3532 unsigned short nHiMultPtUsedHits = 0;
3536 bool doBreak =
false;
3538 for(ii = 1; ii < tj.
Pts.size(); ++ii) {
3539 stopPt = tj.
EndPt[1] - ii;
3540 for(jj = 0; jj < tj.
Pts[stopPt].Hits.size(); ++jj) {
3541 iht = tj.
Pts[stopPt].Hits[jj];
3549 if(lastMult1Pt == USHRT_MAX && tj.
Pts[stopPt].Hits.size() == 1 && tj.
Pts[stopPt-1].Hits.size() == 1) lastMult1Pt = stopPt;
3550 if(tj.
Pts[stopPt].Hits.size() > 1) {
3552 nHiMultPtHits += tj.
Pts[stopPt].Hits.size();
3556 if(lastMult1Pt != USHRT_MAX)
break;
3557 if(stopPt == 1)
break;
3560 float fracHiMult = (float)nHiMultPt / (
float)ii;
3561 if(lastMult1Pt != USHRT_MAX) {
3562 float nchk = tj.
EndPt[1] - lastMult1Pt + 1;
3563 fracHiMult = (float)nHiMultPt / nchk;
3565 fracHiMult = (float)nHiMultPt / (
float)ii;
3567 float fracHitsUsed = 0;
3568 if(nHiMultPt > 0 && nHiMultPtHits > 0) fracHitsUsed = (float)nHiMultPtUsedHits / (
float)nHiMultPtHits;
3574 if(
prt)
mf::LogVerbatim(
"TC")<<
"CHMUH: First InTraj stopPt "<<stopPt<<
" fracHiMult "<<fracHiMult<<
" fracHitsUsed "<<fracHitsUsed<<
" lastMult1Pt "<<lastMult1Pt<<
" sortaLargeAngle "<<sortaLargeAngle;
3575 if(fracHiMult < 0.3)
return;
3576 if(fracHitsUsed > 0.98)
return;
3581 mf::LogVerbatim(
"TC")<<
" Pts size "<<tj.
Pts.size()<<
" nHiMultPt "<<nHiMultPt<<
" nHiMultPtHits "<<nHiMultPtHits<<
" nHiMultPtUsedHits "<<nHiMultPtUsedHits<<
" sortaLargeAngle "<<sortaLargeAngle<<
" maxHitDelta "<<maxDelta;
3596 unsigned short killPts;
3599 for(ipt = stopPt + 1; ipt < tj.
Pts.size(); ++ipt) {
3602 for(ii = 0; ii < tj.
Pts[ipt].Hits.size(); ++ii) {
3603 iht = tj.
Pts[ipt].Hits[ii];
3605 if(
tjs.
fHits[iht].InTraj != 0)
continue;
3607 if(delta > maxDelta)
continue;
3609 tj.
Pts[ipt].UseHit[ii] =
true;
3615 if(tj.
Pts[ipt].Chg == 0)
continue;
3618 if(sortaLargeAngle) tj.
Pts[ipt].NTPsFit = 2;
3623 for(
unsigned short jpt = stopPt + 1; jpt <= ipt; ++jpt) {
3624 for(
unsigned short jj = 0; jj < tj.
Pts[jpt].Hits.size(); ++jj) {
3625 if(tj.
Pts[jpt].UseHit[jj])
tjs.
fHits[tj.
Pts[jpt].Hits[jj]].InTraj = 0;
3631 for(
unsigned short jpt = stopPt + 1; jpt <= ipt; ++jpt) {
3632 for(
unsigned short jj = 0; jj < tj.
Pts[jpt].Hits.size(); ++jj) {
3662 if(tj.
Pts.size() < 10)
return;
3663 if(tj.
Pts[tj.
EndPt[1]].AngleCode == 0)
return;
3665 unsigned short aveMult= 0;
3666 unsigned short ipt, nhalf = tj.
Pts.size() / 2;
3667 unsigned short cnt = 0;
3668 for(
auto& tp : tj.
Pts) {
3669 if(tp.Chg == 0)
continue;
3670 aveMult += tp.Hits.size();
3672 if(cnt == nhalf)
break;
3674 if(cnt == 0)
return;
3676 if(aveMult == 0) aveMult = 1;
3680 for(ipt = tj.
EndPt[1]; ipt > tj.
EndPt[0]; --ipt) {
3681 if(tj.
Pts[ipt].Chg == 0)
continue;
3682 if(tj.
Pts[ipt].Hits.size() > aveMult) {
3689 if(
prt)
mf::LogVerbatim(
"TC")<<
"CHMEH multiplicity cut "<<aveMult<<
" number of TPs masked off "<<cnt;
3703 if(tj.
PDGCode == 13)
return false;
3705 if(tj.
Pts.size() > 40 && tj.
MCSMom > 200)
return false;
3707 unsigned short nBadFit = 0;
3708 unsigned short nHiChg = 0;
3709 unsigned short cnt = 0;
3710 for(
unsigned short ipt = tj.
Pts.size() - 1; ipt > tj.
EndPt[1]; --ipt ) {
3711 if(tj.
Pts[ipt].FitChi > 2) ++nBadFit;
3712 if(tj.
Pts[ipt].ChgPull > 3) ++nHiChg;
3717 if(
prt)
mf::LogVerbatim(
"TC")<<
"StopIfBadFits: nBadFit "<<nBadFit<<
" nHiChg "<<nHiChg;
3718 if(nBadFit > 3 && nHiChg == 0)
return true;
3732 unsigned short lastPt = tj.
Pts.size() - 1;
3733 if(tj.
Pts[lastPt].Chg > 0)
return true;
3734 unsigned short endPt = tj.
EndPt[1];
3737 unsigned short nMasked = 0;
3738 unsigned short nOneHit = 0;
3739 unsigned short nOKChg = 0;
3740 unsigned short nOKDelta = 0;
3742 unsigned short nPosDelta = 0;
3744 unsigned short nDeltaIncreasing = 0;
3746 float prevDelta = tj.
Pts[endPt].Delta;
3747 float maxOKDelta = 10 * tj.
Pts[endPt].DeltaRMS;
3750 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt)
if(tj.
Pts[ipt].Chg > maxOKChg) maxOKChg = tj.
Pts[ipt].Chg;
3751 for(
unsigned short ii = 1; ii < tj.
Pts.size(); ++ii) {
3752 unsigned short ipt = tj.
Pts.size() - ii;
3753 auto& tp = tj.
Pts[ipt];
3754 if(tp.Chg > 0)
break;
3755 unsigned short nUnusedHits = 0;
3757 for(
unsigned short jj = 0; jj < tp.Hits.size(); ++jj) {
3758 unsigned int iht = tp.Hits[jj];
3759 if(
tjs.
fHits[iht].InTraj != 0)
continue;
3763 if(chg < maxOKChg) ++nOKChg;
3764 if(nUnusedHits == 1) ++nOneHit;
3765 if(tp.Delta < maxOKDelta) ++nOKDelta;
3767 if(tp.Pos[1] > tp.HitPos[1]) ++nPosDelta;
3769 if(tp.Delta < prevDelta) ++nDeltaIncreasing;
3770 prevDelta = tp.Delta;
3777 bool driftingAway = nMasked > 2 && (nPosDelta == 0 || nPosDelta == nMasked);
3779 if(driftingAway && nDeltaIncreasing < nMasked - 1) driftingAway =
false;
3782 mf::LogVerbatim(
"TC")<<
"MHOK: nMasked "<<nMasked<<
" nOneHit "<<nOneHit<<
" nOKChg "<<nOKChg<<
" nOKDelta "<<nOKDelta<<
" nPosDelta "<<nPosDelta<<
" nDeltaIncreasing "<<nDeltaIncreasing<<
" driftingAway? "<<driftingAway;
3786 if(nMasked < 8 || nOneHit < 8)
return true;
3787 if(nOKDelta != nMasked)
return true;
3788 if(nOKChg != nMasked)
return true;
3795 if(nMasked > tj.
Pts[endPt].NTPsFit)
return false;
3799 unsigned short newNTPSFit;
3801 newNTPSFit = tj.
Pts[endPt].NTPsFit / 2;
3805 for(
unsigned ipt = endPt + 1; ipt < tj.
Pts.size(); ++ipt) {
3807 for(
unsigned short ii = 0; ii < tj.
Pts[ipt].Hits.size(); ++ii) {
3808 unsigned int iht = tp.
Hits[ii];
3840 unsigned short lastPt = tj.
Pts.size() - 1;
3842 if(tj.
Pts[lastPt].FitChi < 1.5) {
3847 unsigned short newNTPSFit = lastTP.
NTPsFit;
3849 unsigned short nit = 0;
3852 if(lastTP.
NTPsFit > 3) newNTPSFit -= 2;
3853 else if(lastTP.
NTPsFit == 3) newNTPSFit = 2;
3862 if(lastTP.
FitChi > 2)
return;
3887 unsigned short lastPt = tj.
EndPt[1];
3888 if(lastPt < 5)
return;
3889 if(tj.
Pts[lastPt].Chg == 0)
return;
3899 if(tj.
Pts[lastPt].NTPsFit < 6 && tj.
Pts.size() < 20) {
3900 unsigned short ii, prevPtWithHits = USHRT_MAX;
3902 for(ii = 1; ii < tj.
Pts.size(); ++ii) {
3904 if(tj.
Pts[ipt].Chg > 0) {
3905 prevPtWithHits = ipt;
3910 if(prevPtWithHits == USHRT_MAX)
return;
3914 if(dang > kinkAngCut) {
3923 if(std::abs(tj.
Pts[lastPt-1].Pos[0] - tj.
Pts[lastPt].Pos[0]) > 3) {
3932 if(
prt)
mf::LogVerbatim(
"TC")<<
"GottaKink Simple check after gap lastPt "<<lastPt<<
" prevPtWithHits "<<prevPtWithHits<<
" dang "<<dang<<
" cut "<<kinkAngCut;
3933 if(dang > 1.5 * kinkAngCut) {
3941 if(tj.
EndPt[1] < 10)
return;
3943 unsigned short kinkPt = USHRT_MAX;
3946 unsigned short cnt = 0;
3948 unsigned short nHiMultPt = 0;
3949 unsigned short nHiChg = 0;
3951 for(
unsigned short ii = 1; ii < lastPt; ++ii) {
3952 unsigned short ipt = lastPt - ii;
3953 if(tj.
Pts[ipt].Chg == 0)
continue;
3955 if(tj.
Pts[ipt].Hits.size() > 1) ++nHiMultPt;
3956 if(tj.
Pts[ipt].ChgPull > 1.5) ++nHiChg;
3957 if(cnt == nPtsFit) {
3963 if(kinkPt == USHRT_MAX)
return;
3966 unsigned short npts = 4;
3967 unsigned short fitDir = -1;
3968 FitTraj(
tjs, tj, lastPt, npts, fitDir, tpFit);
3969 if(tpFit.
FitChi > 1)
return;
3973 if(dang > kinkAngCut) {
4002 if(
prt)
mf::LogVerbatim(
"TC")<<
"GottaKink "<<kinkPt<<
" Pos "<<
PrintPos(
tjs, tj.
Pts[kinkPt])<<
" dang "<<std::fixed<<std::setprecision(2)<<dang<<
" cut "<<kinkAngCut<<
" tpFit chi "<<tpFit.
FitChi<<
" killPts "<<killPts<<
" GottaKink? "<<tj.
StopFlag[1][
kAtKink]<<
" MCSMom "<<tj.
MCSMom<<
" thetaRMS "<<thetaRMS;
4014 if(tj.
EndPt[1] < 1)
return;
4015 unsigned int lastPt = tj.
EndPt[1];
4019 unsigned short prevPtWithHits = USHRT_MAX;
4020 unsigned short firstFitPt = tj.
EndPt[0];
4021 for(
unsigned short ii = 1; ii < tj.
Pts.size(); ++ii) {
4022 unsigned short ipt = lastPt - ii;
4023 if(tj.
Pts[ipt].Chg > 0) {
4024 prevPtWithHits = ipt;
4029 if(prevPtWithHits == USHRT_MAX)
return;
4035 if(lastPt < 4) minPtsFit = 2;
4040 minPtsFit = lastPt / 3;
4048 if(lastPt > 10 && newMCSMom < 0.6 * tj.
MCSMom) {
4059 mf::LogVerbatim(
"TC")<<
"UpdateTraj: lastPt "<<lastPt<<
" lastTP.Delta "<<lastTP.
Delta<<
" previous point with hits "<<prevPtWithHits<<
" tj.Pts size "<<tj.
Pts.size()<<
" AngleCode "<<lastTP.
AngleCode<<
" PDGCode "<<tj.
PDGCode<<
" maxChi "<<maxChi<<
" minPtsFit "<<minPtsFit<<
" MCSMom "<<tj.
MCSMom;
4071 if(
prt)
mf::LogVerbatim(
"TC")<<
"UpdateTraj: Second traj point pos "<<lastTP.
Pos[0]<<
" "<<lastTP.
Pos[1]<<
" dir "<<lastTP.
Dir[0]<<
" "<<lastTP.
Dir[1];
4089 if(tj.
Pts[prevPtWithHits].FitChi < 1) lastTP.
NTPsFit += 1;
4091 if(lastPt > 20 && tj.
Pts[prevPtWithHits].FitChi > 1.5 && lastTP.
NTPsFit > minPtsFit) lastTP.
NTPsFit -= 2;
4105 unsigned short cnt = 0;
4106 for(
unsigned short ii = 0; ii < tj.
Pts.size(); ++ii) {
4107 unsigned short ipt = lastPt - ii;
4108 if(tj.
Pts[ipt].Chg > 0) {
4112 if(cnt == lastTP.
NTPsFit)
break;
4118 if(lastTP.
FitChi > 1.5 && tj.
Pts.size() > 6) {
4132 if(prevPtWithHits != USHRT_MAX && tj.
Pts[prevPtWithHits].FitChi > 0) chirat = lastTP.
FitChi / tj.
Pts[prevPtWithHits].FitChi;
4162 lastPt = tj.
EndPt[1];
4170 unsigned short newNTPSFit = lastTP.
NTPsFit;
4173 float prevChi = lastTP.
FitChi;
4174 unsigned short ntry = 0;
4176 while(lastTP.
FitChi > chiCut && lastTP.
NTPsFit > minPtsFit) {
4178 newNTPSFit = 0.7 * newNTPSFit;
4179 }
else if(lastTP.
NTPsFit > 4) {
4184 if(lastTP.
NTPsFit < 3) newNTPSFit = 2;
4185 if(newNTPSFit < minPtsFit) newNTPSFit = minPtsFit;
4188 if(newNTPSFit == minPtsFit && tj.
MCSMom < 30) chiCut = 2;
4192 if(lastTP.
FitChi > prevChi) {
4196 if(ntry == 2)
break;
4199 if(lastTP.
NTPsFit == minPtsFit)
break;
4209 lastPt = tj.
EndPt[1];
4211 fMaskedLastTP =
true;
4225 float defFrac = 1 / (float)(tj.
EndPt[1]);
4226 lastTP.
AngErr = defFrac * tj.
Pts[0].AngErr + (1 - defFrac) * lastTP.
AngErr;
4242 unsigned int lastPt = tj.
EndPt[1];
4245 if(lastTP.
Chg == 0)
return;
4246 if(lastPt < 6)
return;
4248 unsigned short ii, ipt, cnt = 0;
4250 for(ii = 1; ii < tj.
Pts.size(); ++ii) {
4252 if(ipt > tj.
Pts.size() - 1)
break;
4253 if(tj.
Pts[ipt].Chg == 0)
continue;
4256 if(cnt == lastTP.
NTPsFit)
break;
4262 lastTP.
DeltaRMS = 1.2 * sum / (float)cnt;
4271 float fromWire =
tjs.
fHits[fromHit].ArtPtr->WireID().Wire;
4272 float fromTick =
tjs.
fHits[fromHit].PeakTime;
4273 float toWire =
tjs.
fHits[toHit].ArtPtr->WireID().Wire;
4274 float toTick =
tjs.
fHits[toHit].PeakTime;
4276 return StartTraj(tj, fromWire, fromTick, toWire, toTick, tCTP, pass);
4291 int fWire = std::nearbyint(fromWire);
4292 int tWire = std::nearbyint(toWire);
4295 }
else if(tWire == fWire) {
4297 if(toTick < fromTick) stepdir = -1;
4306 mf::LogVerbatim(
"TC")<<
"StartTraj: Failure from MakeBareTrajPoint fromWire "<<fromWire<<
" fromTick "<<fromTick<<
" toWire "<<toWire<<
" toTick "<<toTick;
4316 tj.
Pts.push_back(tp);
4332 unsigned short itj = 0;
4333 std::vector<unsigned int> tHits;
4334 std::vector<unsigned int> atHits;
4337 if(tj.AlgMod[
kKilled])
continue;
4339 for(
auto& tp : tj.Pts) {
4340 if(tp.Hits.size() > 16) {
4342 mf::LogWarning(
"TC")<<
"ChkInTraj: More than 16 hits created a UseHit bitset overflow\n";
4348 std::cout<<someText<<
" ChkInTraj hit size mis-match in tj ID "<<tj.ID<<
" AlgBitNames";
4349 for(
unsigned short ib = 0; ib <
AlgBitNames.size(); ++ib)
if(tj.AlgMod[ib]) std::cout<<
" "<<
AlgBitNames[ib];
4354 if(tHits.size() < 2) {
4355 mf::LogVerbatim(
"TC")<<someText<<
" ChkInTraj: Insufficient hits in traj "<<tj.ID<<
" it";
4360 std::sort(tHits.begin(), tHits.end());
4362 for(iht = 0; iht <
tjs.
fHits.size(); ++iht) {
4363 if(
tjs.
fHits[iht].InTraj == tID) atHits.push_back(iht);
4365 if(atHits.size() < 2) {
4366 mf::LogVerbatim(
"TC")<<someText<<
" ChkInTraj: Insufficient hits in atHits in traj "<<tj.ID<<
" Killing it";
4370 if(!std::equal(tHits.begin(), tHits.end(), atHits.begin())) {
4372 myprt<<someText<<
" ChkInTraj failed: inTraj - UseHit mis-match for tj ID "<<tID<<
" tj.WorkID "<<tj.WorkID<<
" atHits size "<<atHits.size()<<
" tHits size "<<tHits.size()<<
" in CTP "<<tj.CTP<<
"\n";
4376 myprt<<
"index inTraj UseHit \n";
4377 for(iht = 0; iht < atHits.size(); ++iht) {
4380 if(atHits[iht] != tHits[iht]) myprt<<
" <<< "<<atHits[iht]<<
" != "<<tHits[iht];
4384 if(tHits.size() > atHits.size()) {
4385 for(iht = atHits.size(); iht < atHits.size(); ++iht) {
4392 for(
unsigned short end = 0;
end < 2; ++
end) {
4395 std::cout<<someText<<
" ChkInTraj: Bad VtxID "<<tj.ID<<
" vtx size "<<
tjs.
vtx.size()<<
"\n";
4429 unsigned short itj, endPt0, endPt1;
4433 for(itj = 0; itj <
tjs.
allTraj.size(); ++itj) {
4440 mf::LogWarning(
"TC")<<
"MakeAllTrajClusters: No hits found in trajectory "<<itj<<
" so skip it";
4446 std::vector<SortEntry> sortVec(tHits.size());
4448 std::array<float, 2> hpos;
4449 for(
unsigned short ii = 0; ii < tHits.size(); ++ii) {
4450 unsigned int iht = tHits[ii];
4451 hpos[0] =
tjs.
fHits[iht].ArtPtr->WireID().Wire;
4453 sortEntry.index = ii;
4454 sortEntry.val =
PosSep2(hpos, tj.
Pts[0].Pos);
4455 sortVec[ii] = sortEntry;
4459 std::vector<unsigned int>
tmp(sortVec.size());
4461 for(
unsigned short ii = 0; ii < sortVec.size(); ++ii)
tmp[ii] = tHits[sortVec[ii].index];
4472 endPt0 = tj.
EndPt[0];
4478 endPt1 = tj.
EndPt[1];
4504 for(
unsigned short iv3 = 0; iv3 <
tjs.
vtx3.size(); ++iv3) {
4507 if(vx3.
ID == 0)
continue;
4508 if(vx3.
TPCID != tpcid)
continue;
4510 if(vx3.
Wire < 0)
continue;
4511 unsigned short mPlane = USHRT_MAX;
4512 unsigned short ntj_1stPlane = USHRT_MAX;
4513 unsigned short ntj_2ndPlane = USHRT_MAX;
4514 for(
unsigned short plane = 0; plane <
tjs.
NumPlanes; ++plane) {
4515 if(vx3.
Vx2ID[plane] > 0) {
4517 if(ntj_1stPlane == USHRT_MAX) {
4518 ntj_1stPlane = vx2.NTraj;
4520 ntj_2ndPlane = vx2.NTraj;
4526 if(mPlane == USHRT_MAX)
continue;
4533 std::vector<int> tjIDs;
4534 std::vector<unsigned short> tj2Pts;
4535 for(
unsigned short itj = 0; itj <
tjs.
allTraj.size(); ++itj) {
4538 if(
tjs.
allTraj[itj].Pts.size() < 6)
continue;
4540 float doca = maxdoca;
4542 unsigned short closePt = 0;
4544 if(closePt >
tjs.
allTraj[itj].EndPt[1])
continue;
4547 tj2Pts.push_back(closePt);
4551 if(tjIDs.empty())
continue;
4552 if(prt)
mf::LogVerbatim(
"TC")<<
" 3V"<<vx3.
ID<<
" mPlane "<<mPlane<<
" ntj_1stPlane "<<ntj_1stPlane<<
" ntj_2ndPlane "<<ntj_2ndPlane;
4562 for(
auto& vx2 :
tjs.
vtx) {
4563 if(vx2.ID == 0)
continue;
4564 if(vx2.CTP != inCTP)
continue;
4583 std::array<int, 2> wireWindow;
4584 std::array<float, 2> timeWindow;
4600 timeWindow[0] = vx2.
Pos[1] - 5;
4601 timeWindow[1] = vx2.
Pos[1] + 5;
4604 unsigned short ipl = planeID.
Plane;
4606 if(
prt)
mf::LogVerbatim(
"TC")<<
"inside FindVtxTraj "<<vx2.
ID<<
" Window "<<wireWindow[0]<<
" "<<wireWindow[1]<<
" "<<timeWindow[0]<<
" "<<timeWindow[1]<<
" in plane "<<ipl;
4611 if(closeHits.empty())
return;
4618 std::vector<SortEntry> sortVec(closeHits.size());
4620 for(
unsigned short ii = 0; ii < closeHits.size(); ++ii) {
4621 unsigned int iht = closeHits[ii];
4622 float dw =
tjs.
fHits[iht].ArtPtr->WireID().Wire - vx2.
Pos[0];
4624 float d2 = dw * dw + dt * dt;
4625 sortEntry.index = ii;
4627 sortVec[ii] = sortEntry;
4630 unsigned int vWire = std::nearbyint(vx2.
Pos[0]);
4633 for(
unsigned short ii = 0; ii < closeHits.size(); ++ii) {
4634 unsigned int iht = closeHits[sortVec[ii].index];
4635 if(
tjs.
fHits[iht].InTraj > 0)
continue;
4638 if(
tjs.
fHits[iht].ArtPtr->WireID().Wire == vWire) {
4640 if(abs(
tjs.
fHits[iht].PeakTime - vTick) < 10)
continue;
4642 float toWire =
tjs.
fHits[iht].ArtPtr->WireID().Wire;
4643 float toTick =
tjs.
fHits[iht].PeakTime;
4645 unsigned short pass =
fMinPts.size() - 1;
4649 if(tj.
Pts[0].Pos[0] < 0)
continue;
4656 tp.
Hits.push_back(iht);
4692 unsigned short localIndex;
4699 hitsInMultiplet.clear();
4701 if(theHit >
tjs.
fHits.size() - 1)
return;
4702 if(
tjs.
fHits[theHit].InTraj == INT_MAX)
return;
4703 hitsInMultiplet.resize(1);
4704 hitsInMultiplet[0] = theHit;
4706 unsigned int theWire =
tjs.
fHits[theHit].ArtPtr->WireID().Wire;
4707 unsigned short ipl =
tjs.
fHits[theHit].ArtPtr->WireID().Plane;
4708 float theTime =
tjs.
fHits[theHit].PeakTime;
4709 float theRMS =
tjs.
fHits[theHit].RMS;
4711 bool theHitIsNarrow = (theRMS < narrowHitCut);
4712 float maxPeak =
tjs.
fHits[theHit].PeakAmplitude;
4713 unsigned short imTall = theHit;
4714 unsigned short nNarrow = 0;
4715 if(theHitIsNarrow) nNarrow = 1;
4724 for(
unsigned int iht = theHit - 1; iht != 0; --iht) {
4725 if(
tjs.
fHits[iht].ArtPtr->WireID().Wire != theWire)
break;
4726 if(
tjs.
fHits[iht].ArtPtr->WireID().Plane != ipl)
break;
4732 float dTick = std::abs(
tjs.
fHits[iht].PeakTime - theTime);
4733 if(dTick > hitSep)
break;
4735 hitsInMultiplet.push_back(iht);
4736 if(
tjs.
fHits[iht].RMS < narrowHitCut) ++nNarrow;
4737 if(
tjs.
fHits[iht].PeakAmplitude > maxPeak) {
4738 maxPeak =
tjs.
fHits[iht].PeakAmplitude;
4745 localIndex = hitsInMultiplet.size() - 1;
4748 if(hitsInMultiplet.size() > 1) std::reverse(hitsInMultiplet.begin(), hitsInMultiplet.end());
4750 theTime =
tjs.
fHits[theHit].PeakTime;
4752 for(
unsigned int iht = theHit + 1; iht <
tjs.
fHits.size(); ++iht) {
4753 if(
tjs.
fHits[iht].ArtPtr->WireID().Wire != theWire)
break;
4754 if(
tjs.
fHits[iht].ArtPtr->WireID().Plane != ipl)
break;
4755 if(
tjs.
fHits[iht].InTraj == INT_MAX)
continue;
4761 float dTick = std::abs(
tjs.
fHits[iht].PeakTime - theTime);
4762 if(dTick > hitSep)
break;
4764 hitsInMultiplet.push_back(iht);
4765 if(
tjs.
fHits[iht].RMS < narrowHitCut) ++nNarrow;
4766 if(
tjs.
fHits[iht].PeakAmplitude > maxPeak) {
4767 maxPeak =
tjs.
fHits[iht].PeakAmplitude;
4779 if(hitsInMultiplet.size() == 1)
return;
4781 if(hitsInMultiplet.size() > 16) {
4783 hitsInMultiplet.resize(16);
4788 if(nNarrow == hitsInMultiplet.size())
return;
4789 if(nNarrow == 0)
return;
4791 if(theHitIsNarrow && theHit == imTall) {
4795 auto tmp = hitsInMultiplet;
4798 hitsInMultiplet =
tmp;
4803 if(
tjs.
fHits[imTall].RMS < narrowHitCut) {
4804 unsigned short killMe = 0;
4805 for(
unsigned short ii = 0; ii < hitsInMultiplet.size(); ++ii) {
4806 if(hitsInMultiplet[ii] == imTall) {
4811 hitsInMultiplet.erase(hitsInMultiplet.begin() + killMe);
4821 std::vector<recob::Hit>
tmp;
4824 geo::PlaneID planeID =
geo::PlaneID(tcHit.ArtPtr->WireID().Cryostat, tcHit.ArtPtr->WireID().TPC, tcHit.ArtPtr->WireID().Plane);
4826 tmp.emplace_back(channel,
4827 tcHit.StartTick, tcHit.EndTick,
4828 tcHit.PeakTime, tcHit.SigmaPeakTime,
4830 tcHit.PeakAmplitude, tcHit.SigmaPeakAmp,
4831 tcHit.Integral, tcHit.Integral, tcHit.SigmaIntegral,
4832 tcHit.Multiplicity, tcHit.LocalIndex,
4833 tcHit.GoodnessOfFit, tcHit.NDOF,
4836 tcHit.ArtPtr->WireID()
4846 if(delHit >
tjs.
fHits.size() - 1) {
4853 int idelHit = delHit;
4854 for(
unsigned short ipl = 0; ipl <
tjs.
NumPlanes; ++ipl) {
4863 if(lastHit <= firstHit) {
4880 unsigned short killPt = USHRT_MAX;
4881 for(
unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
4883 unsigned short killii = USHRT_MAX;
4884 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
4885 if(tp.
Hits[ii] == delHit) {
4888 }
else if(tp.
Hits[ii] > delHit) {
4893 if(killii != USHRT_MAX) {
4895 tp.
Hits.erase(tp.
Hits.begin() + killii);
4897 unsigned short maxSize = tp.
Hits.size();
4898 if(maxSize == 16) maxSize = 15;
4899 for(
unsigned short ii = killii; ii < maxSize; ++ii) tp.
UseHit[ii] = tp.
UseHit[ii + 1];
4901 if(tp.
Hits.empty()) killPt = ipt;
4905 if(killPt != USHRT_MAX) {
4906 tj.Pts.erase(tj.Pts.begin() + killPt);
4931 if(
tjs.
WireHitRange[newHitPlane][newHitWire].first == -1)
return UINT_MAX;
4934 unsigned int newHitIndex = UINT_MAX;
4938 for(
unsigned int wire = newHitWire + 1; wire <
tjs.
NumWires[newHitPlane]; ++wire) {
4945 if(newHitIndex == UINT_MAX) {
4946 for(
unsigned short ipl = newHitPlane + 1; ipl <
tjs.
NumPlanes; ++ipl) {
4953 if(newHitIndex != UINT_MAX)
break;
4958 unsigned int firstHit =
tjs.
WireHitRange[newHitPlane][newHitWire].first;
4959 unsigned int lastHit =
tjs.
WireHitRange[newHitPlane][newHitWire].second - 1;
4962 newHitIndex = firstHit;
4965 newHitIndex = lastHit + 1;
4968 for(
unsigned int iht = firstHit; iht < lastHit; ++iht) {
4971 newHitIndex = iht + 1;
4979 if(newHitIndex == UINT_MAX) {
4999 for(
unsigned int wire = newHitWire + 1; wire <
tjs.
LastWire[newHitPlane]; ++wire) {
5022 for(
unsigned short ipl = newHitPlane + 1; ipl <
tjs.
NumPlanes; ++ipl) {
5030 if(
tjs.
fHits[firstHit].ArtPtr->WireID().Plane != ipl ||
tjs.
fHits[firstHit].ArtPtr->WireID().Wire != wire) {
5031 std::cout<<
"WireHitRange2 screwup on firstHit "<<
tjs.
fHits[firstHit].ArtPtr->WireID().Plane<<
":"<<
tjs.
fHits[firstHit].ArtPtr->WireID().Wire;
5032 std::cout<<
" != "<<ipl<<
":"<<wire<<
"\n";
5035 if(
tjs.
fHits[lastHit].ArtPtr->WireID().Plane != ipl ||
tjs.
fHits[lastHit].ArtPtr->WireID().Wire != wire) {
5036 std::cout<<
"WireHitRange2 screwup on lastHit "<<
tjs.
fHits[lastHit].ArtPtr->WireID().Plane<<
":"<<
tjs.
fHits[lastHit].ArtPtr->WireID().Wire;
5037 std::cout<<
" != "<<ipl<<
":"<<wire<<
"\n";
5048 for(
auto& tp : tj.Pts) {
5049 for(
unsigned short iht = 0; iht < tp.Hits.size(); ++iht) {
5050 if(tp.Hits[iht] >= newHitIndex) ++tp.Hits[iht];
5072 std::vector<unsigned int> delHits;
5073 for(
unsigned short itj = 0; itj <
tjs.
allTraj.size(); ++itj) {
5078 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
5082 std::vector<unsigned int> oldHits;
5089 float mSigmaPeakAmp = 0;
5090 float mSigmaPeakTime = 0;
5091 float mSigmaIntegral = 0;
5092 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
5093 if(!tp.
UseHit[ii])
continue;
5094 unsigned int iht = tp.
Hits[ii];
5095 oldHits.push_back(iht);
5105 if(mTick < 0) mTick = 0;
5106 mSigmaPeakAmp /= mChg;
5107 mSigmaPeakTime /= mChg;
5108 mSigmaIntegral /= mChg;
5110 std::vector<float> signal(hiTick - loTick, 0);
5112 for(
auto& iht : oldHits) {
5113 float& peakTime =
tjs.
fHits[iht].PeakTime;
5114 float& amp =
tjs.
fHits[iht].PeakAmplitude;
5117 short loTime = (short)(peakTime - 3 * rms);
5118 if(loTime < loTick) loTime = loTick;
5119 short hiTime = (short)(peakTime + 3 * rms);
5120 if(hiTime > hiTick) hiTime = hiTick;
5121 for(
short time = loTime; time < hiTime; ++time) {
5122 unsigned short indx = time - loTick;
5123 if(indx > signal.size() - 1)
continue;
5124 float arg = (time - peakTime) / rms;
5125 signal[indx] += amp * exp(-0.5 * arg * arg);
5129 float aveIndx = (mTick - loTick);
5132 for(
unsigned short indx = 0; indx < signal.size(); ++indx) {
5133 float dindx = indx - aveIndx;
5134 mRMS += signal[indx] * dindx * dindx;
5136 mRMS = std::sqrt(mRMS / mChg);
5138 unsigned int mht = oldHits[0];
5140 tjs.
fHits[mht].SigmaPeakTime = mSigmaPeakTime;
5141 tjs.
fHits[mht].PeakAmplitude = mChg / (2.5066 * mRMS);
5142 tjs.
fHits[mht].SigmaPeakAmp = mSigmaPeakAmp;
5144 tjs.
fHits[mht].SigmaIntegral = mSigmaIntegral;
5151 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
5152 for(
unsigned short jj = 1; jj < oldHits.size(); ++jj) {
5153 if (tp.
Hits[ii]==oldHits[jj]){
5156 delHits.push_back(tp.
Hits[ii]);
5159 tp.
Hits[ii] = INT_MAX;
5168 if(delHits.size() > 1) std::sort(delHits.begin(), delHits.end(), std::greater<unsigned int>());
5170 for(
auto& delHit : delHits)
EraseHit(delHit);
5183 if(tj.
Pts.size() < 3) {
5184 mf::LogError(
"TC")<<
"MaskBadTPs: Trajectory ID "<<tj.
ID<<
" too short to mask hits ";
5188 unsigned short nit = 0;
5190 while(lastTP.
FitChi > maxChi && nit < 3) {
5192 unsigned short imBad = USHRT_MAX;
5193 unsigned short cnt = 0;
5194 for(
unsigned short ii = 1; ii < tj.
Pts.size(); ++ii) {
5195 unsigned short ipt = tj.
Pts.size() - 1 - ii;
5197 if(tp.
Chg == 0)
continue;
5198 if(tp.
Delta > maxDelta) {
5199 maxDelta = tp.
Delta;
5205 if(imBad == USHRT_MAX)
return;
5226 if(tj.
Pts.size() < 3) {
5227 mf::LogError(
"TC")<<
"MaskTrajEndPoints: Trajectory ID "<<tj.
ID<<
" too short to mask hits ";
5231 if(nPts > tj.
Pts.size() - 2) {
5232 mf::LogError(
"TC")<<
"MaskTrajEndPoints: Trying to mask too many points "<<nPts<<
" Pts.size "<<tj.
Pts.size();
5238 unsigned short lastGoodPt = USHRT_MAX ;
5241 for(
unsigned short ii = 0; ii < tj.
Pts.size(); ++ii) {
5242 unsigned short ipt = tj.
EndPt[1] - nPts - ii;
5243 if(tj.
Pts[ipt].Chg > 0) {
5253 if(lastGoodPt == USHRT_MAX)
return;
5254 tj.
EndPt[1] = lastGoodPt;
5257 for(
unsigned short ii = 0; ii < tj.
Pts.size(); ++ii) {
5258 unsigned short ipt = tj.
Pts.size() - 1 - ii;
5259 if (ipt==lastGoodPt)
break;
5262 tj.
Pts[ipt].Dir = tj.
Pts[lastGoodPt].Dir;
5263 if(tj.
Pts[lastGoodPt].AngleCode == 2) {
5266 tj.
Pts[ipt].Pos[0] = tj.
Pts[lastGoodPt].Pos[0] + path * tj.
Pts[ipt].Dir[0];
5267 tj.
Pts[ipt].Pos[1] = tj.
Pts[lastGoodPt].Pos[1] + path * tj.
Pts[ipt].Dir[1];
5270 float dw = tj.
Pts[ipt].Pos[0] - tj.
Pts[lastGoodPt].Pos[0];
5272 float newpos = tj.
Pts[lastGoodPt].Pos[1] + dw * tj.
Pts[ipt].Dir[1] / tj.
Pts[ipt].Dir[0];
5273 if(
prt)
mf::LogVerbatim(
"TC")<<
"MTEP: ipt "<<ipt<<
" Pos[0] "<<tj.
Pts[ipt].Pos[0]<<
". Move Pos[1] from "<<tj.
Pts[ipt].Pos[1]<<
" to "<<newpos;
5274 tj.
Pts[ipt].Pos[1] = tj.
Pts[lastGoodPt].Pos[1] + dw * tj.
Pts[ipt].Dir[1] / tj.
Pts[ipt].Dir[0];
5299 if(tj.
MCSMom < 30)
return;
5302 if(tj.
Pts[tj.
EndPt[0]].AngleCode == 2 || tj.
Pts[tj.
EndPt[1]].AngleCode == 2)
return;
5305 if(tj.
Pts.size() < nPtsToCheck)
return;
5310 for(
unsigned short end = 0;
end < 2; ++
end) {
5314 unsigned short hiPt = 0;
5316 for(
unsigned short ii = 0; ii < 4; ++ii) {
5318 if(ipt < tj.
EndPt[0] || ipt > tj.
EndPt[1])
break;
5327 std::vector<float>
x,
y, yerr2;
5328 float intcpt, intcpterr;
5329 float slope, slopeerr, chidof;
5330 float prevChg = big;
5331 for(
unsigned short ii = 0; ii < tj.
Pts.size(); ++ii) {
5332 short ipt = hiPt + ii *
dir;
5333 if(ipt < tj.
EndPt[0] || ipt > tj.
EndPt[1])
break;
5335 if(tp.
Chg == 0)
continue;
5337 if(tp.
Chg > 1.5 * prevChg)
break;
5339 x.push_back(std::abs(tp.
Pos[0] - wire0));
5340 y.push_back(tp.
Chg);
5342 float err = 0.1 * tp.
Chg;
5344 yerr2.push_back(err * err);
5345 if(x.size() == nPtsToCheck)
break;
5347 if(x.size() < 4)
continue;
5348 fLinFitAlg.
LinFit(x, y, yerr2, intcpt, slope, intcpterr, slopeerr, chidof);
5350 if(chidof > 100)
continue;
5351 unsigned short endPt = tj.
EndPt[
end];
5352 if(tj.
Pts[endPt].AveChg > 0 && intcpt / tj.
Pts[endPt].AveChg > 3) {
5359 if(slope > fChkStopCuts[0] && chidof < fChkStopCuts[2] && slope > 2 * slopeerr) {
5363 tj.
Pts[endPt].AveChg = intcpt;
5365 std::vector<int> tjlist(1, tj.
ID);
5367 if(chgFrac > 0.9) tj.
PDGCode = 2212;
5370 if(
prt)
mf::LogVerbatim(
"TC")<<
" end "<<
end<<
" fit chidof "<<chidof<<
" slope "<<slope<<
" +/- "<<slopeerr<<
" Not stopping";
5381 unsigned short nmichelhits = 0;
5383 unsigned short nbragghits = 0;
5386 bool isfirsthit =
true;
5387 unsigned short braggpeak = 0;
5389 for(
unsigned short ii = 0; ii < tj.
Pts.size(); ++ii) {
5390 if (ii>tj.
EndPt[1])
continue;
5391 unsigned short ipt = tj.
EndPt[1] - ii;
5392 if (tj.
Pts[ipt].Chg>0){
5395 if (tj.
Pts[ipt].ChgPull<0){
5400 if (tj.
Pts[ipt].ChgPull<0&&nmichelhits&&!nbragghits){
5406 lastChg = tj.
Pts[ipt].Chg;
5409 else if (tj.
Pts[ipt].Chg<lastChg){
5411 lastChg = tj.
Pts[ipt].Chg;
5418 if(
prt)
mf::LogVerbatim(
"TC")<<
"ChkMichel Michel hits: "<<nmichelhits<<
" Bragg peak hits: "<<nbragghits;
5419 if (nmichelhits>0&&nbragghits>2){
5420 lastGoodPt = braggpeak;
5435 for(
size_t i = 0; i<
tjs.
allTraj.size(); ++i) {
5437 if(tj.CTP != inCTP)
continue;
5438 if(tj.AlgMod[
kKilled])
continue;
5455 if (tj.
EndPt[1]<10)
return;
5456 for(
unsigned short end = 0;
end < 2; ++
end) {
5460 unsigned short nlohits = 0;
5461 unsigned short lastHiTP = USHRT_MAX;
5470 else if (ptchg>0.4*hichg){
5489 if (nlohits>4&&lastHiTP!=USHRT_MAX){
5492 aVtx.
Pos = tj.
Pts[lastHiTP].Pos;
5509 unsigned short tp1 = lastHiTP+1;
5510 if (
end==1) tp1 = lastHiTP-1;
5512 tj.
Pts[ipt].Chg = 0;
5513 for (
unsigned short ii = 0; ii < tj.
Pts[ipt].Hits.size(); ++ii) {
5514 if(!tj.
Pts[ipt].UseHit[ii])
continue;
5515 unsigned int iht = tj.
Pts[ipt].Hits[ii];
5519 tj.
Pts[ipt].UseHit[ii] =
false;
5530 newTj.
Pts[ipt].Chg = 0;
5531 for (
unsigned short ii = 0; ii < newTj.
Pts[ipt].Hits.size(); ++ii) {
5532 newTj.
Pts[ipt].UseHit[ii] =
false;
5606 if(hitVecHandle->size() < 2)
return;
5607 tjs.
fHits.reserve(hitVecHandle->size());
5609 for(
unsigned int iht = 0; iht < hitVecHandle->size(); ++iht) {
5613 localHit.EndTick = hit->
EndTick();
5614 localHit.PeakTime = hit->
PeakTime();
5618 localHit.Integral = hit->
Integral();
5620 localHit.RMS = hit->
RMS();
5625 localHit.ArtPtr = hit;
5635 unsigned short nerr = 0;
5636 for(
unsigned int iht = 0; iht <
tjs.
fHits.size(); ++iht) {
5637 if(
tjs.
fHits[iht].Multiplicity < 2)
continue;
5639 bool badHit =
false;
5640 unsigned int fromIndex = iht - iHit.LocalIndex;
5641 unsigned short indx = 0;
5642 for(
unsigned int jht = fromIndex; jht < fromIndex + iHit.Multiplicity; ++jht) {
5644 if(iHit.Multiplicity != jHit.Multiplicity) badHit =
true;
5645 if(iHit.LocalIndex != indx) badHit =
true;
5650 for(
unsigned int jht = fromIndex; jht < fromIndex + iHit.Multiplicity; ++jht) {
5652 jHit.Multiplicity = 1;
5653 jHit.LocalIndex = 0;
5670 std::vector<art::Handle<std::vector<simb::MCTruth>>> mctcol;
5672 std::vector<const simb::MCTruth*> mcvec;
5673 for(
size_t mctc = 0; mctc < mctcol.size(); ++mctc) {
5675 for(
size_t i = 0; i < mclistHandle->size(); ++i){
5676 mcvec.push_back(&(mclistHandle->at(i)));
5679 std::cout<<
"MCtruth Part TrkID PDGCode KE Mother Process\n";
5680 for(
unsigned int i = 0; i < mcvec.size(); ++i) {
5681 if(!anySource && mcvec[i]->Origin() !=
origin)
continue;
5683 for(
int ii = 0; ii < mcvec[i]->NParticles(); ++ii) {
5684 auto& p = mcvec[i]->GetParticle(ii);
5685 if(!(p.StatusCode() == 0 || p.StatusCode() == 1))
continue;
5686 int KE = 1000 * (p.E() - p.Mass());
5687 std::cout<<std::setw(6)<<i<<std::setw(6)<<ii;
5688 std::cout<<std::setw(6)<<p.TrackId();
5689 std::cout<<std::setw(12)<<p.PdgCode();
5690 std::cout<<std::setw(7)<<KE;
5691 std::cout<<std::setw(6)<<p.Mother();
5692 std::cout<<
" "<<p.Process();
5701 if(plist.
empty())
return;
5704 auto& p = (*ipart).second;
5707 int KE = 1000 * (p->E() - p->Mass());
5708 if(!anySource && theTruth->
Origin() !=
origin)
continue;
5710 std::cout<<
"GHC: mcp Origin "<<theTruth->
Origin()
5711 <<std::setw(8)<<p->TrackId()
5712 <<
" pdg "<<p->PdgCode()
5713 <<std::setw(7)<<KE<<
" mom "<<p->Mother()
5728 std::vector<art::Ptr<simb::MCParticle>> particle_vec;
5729 std::vector<anab::BackTrackerHitMatchingData const*> match_vec;
5730 unsigned int nMatHits = 0;
5732 bool prthit =
false;
5734 for(
unsigned int iht = 0; iht <
tjs.
fHits.size(); ++iht) {
5735 particle_vec.clear(); match_vec.clear();
5739 try{ particles_per_hit.
get(
tjs.
fHits[iht].ArtPtr.key(), particle_vec, match_vec); }
5741 std::cout<<
"BackTrackerHitMatchingData not found using "<<
fHitTruthModuleLabel<<
". Try to use the old backtracker\n";
5746 if(particle_vec.empty())
continue;
5748 for(
unsigned short im = 0; im < match_vec.size(); ++im) {
5749 if(prthit) std::cout<<
" im "<<im<<
" trackID "<<particle_vec[im]->TrackId()<<
" ideFraction "<<match_vec[im]->ideFraction<<
"\n";
5750 if(match_vec[im]->ideFraction > 0.5) {
5751 trackID = particle_vec[im]->TrackId();
5755 if(trackID == 0)
continue;
5758 auto& p = (*ipart).second;
5759 if(p->TrackId() != trackID)
continue;
5761 std::cout<<
"hit "<<
PrintHit(
tjs.
fHits[iht])<<
" -> trackID "<<trackID<<
" Origin "<<theTruth->
Origin()<<
" pdg "<<p->PdgCode()<<
" E "<<1000 * p->E()<<
" Process "<<p->Process()<<
"\n";
5767 if(mcp->TrackId() != trackID)
continue;
5778 std::cout<<
"MatchTrueHits: Ignoring hits not matched to MC particles\n";
5780 if(
hit.MCPartListIndex == UINT_MAX)
hit.InTraj = INT_MAX;
5785 std::cout<<
"GetHitCollection loaded "<<
tjs.
MCPartList.size()<<
" MCParticles using MCTruth Origin "<<
origin;
5786 std::cout<<
". Matched "<<nMatHits<<
" hits to MCParticles out of "<<
tjs.
fHits.size()<<
" total hits";
short int LocalIndex() const
How well do we believe we know this hit?
bool fMakeNewHits
label of module producing input hits
void ClearResults()
Deletes all the results.
bool valDecreasing(SortEntry c1, SortEntry c2)
don't mess with this line
float AveChg
Calculated using ALL hits.
std::vector< int > EnvStage
void UpdateDeltaRMS(Trajectory &tj)
label of module producing input hits
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< unsigned int > FindCloseHits(TjStuff const &tjs, std::array< int, 2 > const &wireWindow, Point2_t const &timeWindow, const unsigned short plane, HitStatus_t hitRequest, bool usePeakTime, bool &hitsNear)
std::vector< int > IsShowerParent
bool ChkVtxAssociations(TjStuff &tjs, const CTP_t &inCTP)
SubRunNumber_t subRun() const
float fMaxChi
label of module producing input hits
bool SelectEvent
number of points to find AveChg
std::vector< float > cr_pfpyzmindis
float fHitErrFac
hit time error = fHitErrFac * hit RMS used for cluster fit
void ChkInTraj(std::string someText)
label of module producing input hits
std::vector< unsigned int > tclhits
void MergeTPHits()
label of module producing input hits
std::vector< float > Vertex2DCuts
Max position pull, max Position error rms.
void ChkChgAsymmetry(TjStuff &tjs, Trajectory &tj, bool prt)
void ChkStopEndPts(Trajectory &tj, bool prt)
label of module producing input hits
std::vector< float > ChargeCuts
std::vector< float > EndWir
float fMaxWireSkipNoSignal
max number of wires to skip w/o a signal on them
struct of temporary 2D vertices (end points)
void PrintTrajectory(std::string someText, const TjStuff &tjs, const Trajectory &tj, unsigned short tPoint)
FindVtxTraj algorithm tried.
std::vector< float > EndAng
float OverlapFraction(TjStuff &tjs, const Trajectory &tj1, const Trajectory &tj2)
const std::vector< std::string > AlgBitNames
void Print2DShowers(std::string someText, const TjStuff &tjs, CTP_t inCTP, bool printKilledShowers)
CTP_t CTP
Cryostat, TPC, Plane code.
std::vector< unsigned short > fMinPtsFit
StepCrawl mode (0 = turn off)
void ChkStop(Trajectory &tj)
label of module producing input hits
float HitSep2(TjStuff &tjs, unsigned int iht, unsigned int jht)
art::Ptr< recob::Hit > ArtPtr
bool ChkMichel(Trajectory &tj, unsigned short &lastGoodPt)
label of module producing input hits
void PrepareForNextPass(Trajectory &tj)
label of module producing input hits
std::vector< float > cr_pfpxmax
void ChkHiChgHits(CTP_t inCTP)
label of module producing input hits
TjStuff tjs
label of module producing input hits
void Find3DVertices(TjStuff &tjs, const geo::TPCID &tpcid)
std::bitset< 64 > AlgMod
Bit set if algorithm AlgBit_t modifed the trajectory.
void UpdateVxEnvironment(std::string inFcnLabel, TjStuff &tjs, VtxStore &vx2, bool prt)
const key_type & TrackId(const size_type) const
void MakeAllTrajClusters()
label of module producing input hits
std::vector< float > BeginTim
unsigned short AngleRange(TjStuff &tjs, TrajPoint const &tp)
void FindVtxTraj(VtxStore &theVtx)
label of module producing input hits
void PrintAllTraj(std::string someText, const TjStuff &tjs, const DebugStuff &debug, unsigned short itj, unsigned short ipt, bool prtVtx)
TruthMatcher tm
label of module producing input hits
bool HasDuplicateHits(TjStuff const &tjs, Trajectory const &tj, bool prt)
geo::WireID WireID() const
Initial tdc tick for hit.
unsigned int Nplanes() const
Number of planes in this tpc.
float RMS() const
RMS of the hit shape, in tick units.
std::vector< unsigned int > PutTrajHitsInVector(Trajectory const &tj, HitStatus_t hitRequest)
void TagJunkTj(TjStuff const &tjs, Trajectory &tj, bool prt)
vertex position fixed manually - no fitting done
std::vector< float > AveHitRMS
average RMS of an isolated hit
std::vector< float > BeginAng
void SplitTrajCrossingVertices(TjStuff &tjs, CTP_t inCTP)
std::vector< float > MaxPos1
float TpSumHitChg(TjStuff &tjs, TrajPoint const &tp)
std::array< std::bitset< 8 >, 2 > StopFlag
void FindJunkTraj(CTP_t inCTP)
label of module producing input hits
bool FitVertex(TjStuff &tjs, VtxStore &vx, bool prt)
void DefineHitPos(TrajPoint &tp)
label of module producing input hits
list_type::const_iterator const_iterator
simb::Origin_t Origin() const
bool mrgPrt
label of module producing input hits
art::InputTag fHitFinderModuleLabel
label of module producing input hits
The data type to uniquely identify a Plane.
Geometry information for a single TPC.
std::vector< PFPStruct > pfps
enum simb::_ev_origin Origin_t
event origin types
float fProjectionErrFactor
label of module producing input hits
int ParentID
ID of the parent, or the ID of the Tj this one was merged with if it is killed.
std::vector< unsigned int > Hits
void UpdateTraj(Trajectory &tj)
label of module producing input hits
void ClearShowerTree(ShowerTreeVars &stv)
float SigmaPeakAmplitude() const
Uncertainty on estimated amplitude of the hit at its peak, in ADC units.
void CreateHists(art::TFileService &tfs)
float SigmaIntegral() const
Initial tdc tick for hit.
bool AttachAnyTrajToVertex(TjStuff &tjs, unsigned short ivx, bool prt)
float HitsTimeErr2(const std::vector< unsigned int > &hitVec)
label of module producing input hits
calo::CalorimetryAlg fCaloAlg
label of module producing input hits
void ConfigureMVA(TjStuff &tjs, std::string fMVAShowerParentWeights)
bool TrajHitsOK(TjStuff &tjs, const std::vector< unsigned int > &iHitsInMultiplet, const std::vector< unsigned int > &jHitsInMultiplet)
float HitsRMSTime(TjStuff &tjs, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
int DegreesOfFreedom() const
Initial tdc tick for hit.
float HitsRMSTick(TjStuff &tjs, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
CryostatID_t Cryostat
Index of cryostat.
void ChkVxTjs(TjStuff &tjs, const CTP_t &inCTP, bool prt)
void CheckHiMultUnusedHits(Trajectory &tj)
label of module producing input hits
void TrimEndPts(std::string fcnLabel, TjStuff &tjs, Trajectory &tj, const std::vector< float > &fQualityCuts, bool prt)
float TrajPointSeparation(TrajPoint &tp1, TrajPoint &tp2)
float Integral() const
Integral under the calibrated signal waveform of the hit, in tick x ADC units.
std::vector< float > fChkStopCuts
[Min Chg ratio, Chg slope pull cut, Chg fit chi cut]
float fMaxTrajSep
max trajectory point separation for making showers
WireID_t Wire
Index of the wire within its plane.
std::vector< ShowerStruct3D > showers
void AddHits(Trajectory &tj, unsigned short ipt, bool &sigOK)
label of module producing input hits
void SetAngleCode(TjStuff &tjs, TrajPoint &tp)
std::vector< unsigned short > fMinPts
min number of Pts required to make a trajectory
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
short fMode
label of module producing input hits
SigType_t SignalType(geo::PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
unsigned int ClusterIndex
Index not the ID...
float GoodnessOfFit() const
Degrees of freedom in the determination of the hit signal shape (-1 by default)
void GetHitMultiplet(unsigned int theHit, std::vector< unsigned int > &hitsInMultiplet)
label of module producing input hits
short int Multiplicity() const
How many hits could this one be shared with.
float DeadWireCount(const TjStuff &tjs, const TrajPoint &tp1, const TrajPoint &tp2)
bool valDecreasing(SortEntry c1, SortEntry c2)
bool CompatibleMerge(TjStuff &tjs, std::vector< int > &tjIDs, bool prt)
std::array< double, 2 > Dir
float fVLAStepSize
label of module producing input hits
void CheckTraj(Trajectory &tj)
label of module producing input hits
void FindSoftKink(Trajectory &tj)
label of module producing input hits
IteratorBox< TPC_id_iterator,&GeometryCore::begin_TPC_id,&GeometryCore::end_TPC_id > IterateTPCIDs() const
Enables ranged-for loops on all TPC IDs of the detector.
bool StartTraj(Trajectory &tj, const unsigned int &fromHit, const unsigned int &toHit, const unsigned short &pass)
label of module producing input hits
void StudyShowerParents(HistStuff &hist)
void FillGaps(Trajectory &tj)
label of module producing input hits
bool SignalAtTp(TjStuff &tjs, const TrajPoint &tp)
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
float PeakAmplitude() const
The estimated amplitude of the hit at its peak, in ADC units.
calo::CalorimetryAlg * caloAlg
void FindPFParticles(TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
unsigned short Pass
the pass on which it was created
void TagDeltaRays(TjStuff &tjs, const CTP_t &inCTP)
void CheckTrajBeginChg(TjStuff &tjs, unsigned short itj, bool prt)
int TDCtick_t
Type representing a TDC tick.
bool TrajIsClean(TjStuff &tjs, Trajectory &tj, bool prt)
bool fUseOldBackTracker
label of module producing input hits
std::vector< float > EndTim
std::vector< int > ShowerID
void ReleaseHits(TjStuff &tjs, Trajectory &tj)
TMVA::Reader * ShowerParentReader
void ReverseTraj(TjStuff &tjs, Trajectory &tj)
void DefineShTree(TTree *t)
label of module producing input hits
std::vector< unsigned int > fAlgModCount
label of module producing input hits
unsigned int Hit
set to the hit index in fHits if a Plane:Wire:Tick match is found
std::vector< ShowerStruct > cots
std::vector< float > ShowerTag
[min MCSMom, max separation, min # Tj < separation] for a shower tag
int cmp(WireID const &other) const
Returns < 0 if this is smaller than tpcid, 0 if equal, > 0 if larger.
std::vector< std::string > StageName
bool AttachTrajToVertex(TjStuff &tjs, Trajectory &tj, VtxStore &vx, bool prt)
static bool SortByMultiplet(TCHit const &a, TCHit const &b)
label of module producing input hits
int Cryostat
Select Cryostat.
void FindNeutralVertices(TjStuff &tjs, const geo::TPCID &tpcid)
struct of temporary 3D vertices
void HiEndDelta(Trajectory &tj)
label of module producing input hits
unsigned int EventsProcessed
bool StopIfBadFits(Trajectory &tj)
label of module producing input hits
bool CheckWireHitRange(const TjStuff &tjs)
int Wire
Select hit Wire for debugging.
int WorkID
Select the StartWorkID for debugging.
const geo::GeometryCore * geom
std::vector< short > BeginVtx
void FindUseHits(Trajectory &tj, unsigned short ipt, float maxDelta, bool useChg)
label of module producing input hits
void MakeJunkVertices(TjStuff &tjs, const CTP_t &inCTP)
CTP_t CTP
Cryostat, TPC, Plane code.
void UpdateTjChgProperties(std::string inFcnLabel, TjStuff &tjs, Trajectory &tj, bool prt)
void GetHitCollection(const art::Event &evt)
label of module producing input hits
std::vector< unsigned int > LastWire
the last wire with a hit
void RunTrajClusterAlg(const art::Event &evt)
label of module producing input hits
std::vector< VtxStore > vtx
2D vertices
bool MakeJunkTraj(std::vector< unsigned int > tHits, bool prt)
label of module producing input hits
const std::vector< std::string > StopFlagNames
void VtxHitsSwap(TjStuff &tjs, const CTP_t inCTP)
std::vector< TrajPoint > Pts
Trajectory points.
bool SignalBetween(TjStuff &tjs, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction, bool prt)
std::vector< float > NeutralVxCuts
unsigned int CreateHit(TCHit tcHit)
label of module producing input hits
void Find2DVertices(TjStuff &tjs, const CTP_t &inCTP)
T get(std::string const &key) const
std::vector< short > fMinMCSMom
Min MCSMom for each pass.
std::vector< unsigned short > fMaxAngleCode
max allowed angle code for each pass
float TrajLength(Trajectory &tj)
std::vector< Trajectory > allTraj
vector of all trajectories in each plane
std::vector< short > EndVtx
void PFPVertexCheck(TjStuff &tjs)
void StepCrawl(Trajectory &tj)
label of module producing input hits
std::bitset< 64 > UseAlg
Allow user to mask off specific algorithms.
unsigned short LocalIndex
std::array< unsigned short, 2 > EndPt
First and last point in the trajectory that has charge.
void DefineCRTree(TTree *t)
label of module producing input hits
unsigned short PDGCode
shower-like or track-like {default is track-like}
float HitTimeErr(const unsigned int iht)
label of module producing input hits
void getManyByType(std::vector< Handle< PROD >> &results) const
std::vector< int > cr_origin
virtual void reconfigure(fhicl::ParameterSet const &pset)
label of module producing input hits
std::vector< recob::Hit > YieldHits()
Returns (and loses) the art::Ptr collection of previously reconstructed hits (e.g. gaushit)
void SaveCRInfo(TjStuff &tjs, PFPStruct &pfp, bool prt, bool fIsRealData)
std::vector< float > MaxPos0
void DefineTjParents(TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
void FillmAllTraj(TjStuff &tjs, const geo::TPCID &tpcid)
trkf::LinFitAlg fLinFitAlg
label of module producing input hits
bool get_if_present(std::string const &key, T &value) const
std::vector< unsigned int > FirstWire
the first wire with a hit
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
bool fStudyMode
study cuts
std::vector< float > Envelope
std::vector< float > fQualityCuts
Min points/wire, min consecutive pts after a gap.
void AddLAHits(Trajectory &tj, unsigned short ipt, bool &sigOK)
label of module producing input hits
EventNumber_t event() const
bool MakeBareTrajPoint(const TjStuff &tjs, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
std::vector< MatchStruct > matchVec
3D matching vector
bool TestBeam
Expect tracks entering from the front face. Don't create neutrino PFParticles.
std::string PrintHit(const TCHit &hit)
void ReconstructAllTraj(CTP_t inCTP)
label of module producing input hits
TMVA::Reader fMVAReader
label of module producing input hits
float UnitsPerTick
scale factor from Tick to WSE equivalent units
bool has_key(std::string const &key) const
The data type to uniquely identify a TPC.
PlaneID_t Plane
Index of the plane within its TPC.
void MatchTruth(const HistStuff &hist, bool fStudyMode)
raw::TDCtick_t StartTick() const
Initial tdc tick for hit.
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
unsigned short NumHitsInTP(const TrajPoint &tp, HitStatus_t hitRequest)
void TagMuonDirections(TjStuff &tjs, short debugWorkID)
bool fIsRealData
label of module producing input hits
void ScoreVertices(TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
float PointTrajDOCA(TjStuff const &tjs, unsigned int iht, TrajPoint const &tp)
bool fQuitAlg
label of module producing input hits
std::vector< float > BeginChg
bool didPrt
label of module producing input hits
std::vector< float > MatchTruth
Match to MC truth.
std::array< unsigned short, 2 > VtxID
ID of 2D vertex.
Detector simulation of raw signals on wires.
short MCSMom(const TjStuff &tjs, const std::vector< int > &tjIDs)
void MaskTrajEndPoints(Trajectory &tj, unsigned short nPts)
label of module producing input hits
std::vector< DontClusterStruct > dontCluster
std::vector< Vtx3Store > vtx3
3D vertices
raw::TDCtick_t EndTick() const
Final tdc tick for hit.
float ChgFracNearPos(TjStuff &tjs, const Point2_t &pos, const std::vector< int > &tjIDs)
void CheckHiMultEndHits(Trajectory &tj)
label of module producing input hits
void DefineHit(TCHit &tcHit, CTP_t &hitCTP, unsigned int &hitWire)
label of module producing input hits
void EndMerge(CTP_t inCTP, bool lastPass)
label of module producing input hits
float fMinAmp
min amplitude required for declaring a wire signal is present
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
std::bitset< 16 > Stat
Vertex status bits using kVtxBit_t.
std::vector< int > EnvPlane
std::array< int, 3 > Vx2ID
void ReversePropagate(Trajectory &tj)
label of module producing input hits
void SplitHiChgHits(Trajectory &tj)
label of module producing input hits
std::vector< short > MCSMom
int Tick
Select hit PeakTime for debugging (< 0 for vertex finding)
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
float PeakTime() const
Time of the signal peak, in tick units.
std::vector< short > MuonTag
min length and min MCSMom for a muon tag
void FixTrajBegin(Trajectory &tj)
label of module producing input hits
std::vector< float > VertexScoreWeights
bool fMaskedLastTP
label of module producing input hits
std::vector< int > StageNum
bool InTrajOK(TjStuff &tjs, std::string someText)
std::vector< std::vector< std::pair< int, int > > > WireHitRange
bool FillWireHitRange(TjStuff &tjs, const geo::TPCID &tpcid)
std::vector< TCHit > fHits
bool fTryWithNextPass
label of module producing input hits
bool fGoodTraj
label of module producing input hits
void PrintShowers(std::string fcnLabel, TjStuff &tjs)
short StepDir
-1 = going US (-> small wire#), 1 = going DS (-> large wire#)
int TJPrt
label of module producing input hits
std::vector< float > BeginWir
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< float > Match3DCuts
3D matching cuts
float ExpectedHitsRMS(TjStuff &tjs, const TrajPoint &tp)
TTree * showertree
label of module producing input hits
std::vector< float > EndChg
void LinFit(std::vector< float > &x, std::vector< float > &y, std::vector< float > &ey2, float &Intercept, float &Slope, float &InterceptError, float &SlopeError, float &ChiDOF)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
void FindMissedVxTjs(const geo::TPCID &tpcid)
label of module producing input hits
void KillPoorVertices(TjStuff &tjs, const geo::TPCID &tpcid)
bool prt
label of module producing input hits
void SetVx2Score(TjStuff &tjs, bool prt)
void SetEndPoints(TjStuff &tjs, Trajectory &tj)
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
unsigned short NumPtsWithCharge(const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires)
std::vector< simb::MCParticle * > MCPartList
bool MergeAndStore(TjStuff &tjs, unsigned int itj1, unsigned int itj2, bool doPrt)
void Finish3DShowers(TjStuff &tjs)
std::vector< ClusterStore > tcl
the clusters we are creating
float MaxHitDelta(TjStuff &tjs, Trajectory &tj)
unsigned short TPNearVertex(TjStuff &tjs, const TrajPoint &tp)
HistStuff hist
label of module producing input hits
std::vector< float > cr_pfpxmin
std::string PrintStopFlag(const Trajectory &tj, unsigned short end)
std::vector< short > DeltaRayTag
min length, min MCSMom and min separation (WSE) for a delta ray tag
const sim::ParticleList & ParticleList()
std::vector< Tj2Pt > mallTraj
vector of trajectory points ordered by increasing X
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
float SigmaPeakTime() const
Uncertainty for the signal peak, in tick units.
size_type get(size_type i, reference item, data_reference data) const
void PrintPFPs(std::string someText, const TjStuff &tjs)
void UnsetUsedHits(TjStuff &tjs, TrajPoint &tp)
void SetPDGCode(TjStuff &tjs, unsigned short itj)
float fMultHitSep
preferentially "merge" hits with < this separation
std::vector< float > AngleRanges
list of max angles for each angle range
float HitsPosTick(TjStuff &tjs, const std::vector< unsigned int > &hitsInMultiplet, float &sum, HitStatus_t hitRequest)
bool EraseHit(const unsigned int &delHit)
label of module producing input hits
void MoveTPToWire(TrajPoint &tp, float wire)
std::vector< int > EnvShowerID
bool StoreVertex(TjStuff &tjs, VtxStore &vx)
void MaskBadTPs(Trajectory &tj, float const &maxChi)
label of module producing input hits
std::vector< float > KinkCuts
kink angle, nPts fit, (alternate) kink angle significance
float MCSThetaRMS(TjStuff &tjs, Trajectory &tj)
void FixTrajEnd(Trajectory &tj, unsigned short atPt)
label of module producing input hits
unsigned int ChannelID_t
Type representing the ID of a readout channel.
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
TPCID_t TPC
Index of the TPC within its cryostat.
float fJTMaxHitSep2
label of module producing input hits
bool TrajTrajDOCA(const TjStuff &tjs, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
bool StoreTraj(TjStuff &tjs, Trajectory &tj)
float TPHitsRMSTick(TjStuff &tjs, TrajPoint &tp, HitStatus_t hitRequest)
std::vector< int > IsShowerTj
void ClearCRInfo(TjStuff &tjs)
void PrintTrajPoint(std::string someText, const TjStuff &tjs, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
std::vector< float > Vertex3DCuts
2D vtx -> 3D vtx matching cuts
std::vector< short > PlaneNum
bool MaskedHitsOK(Trajectory &tj)
label of module producing input hits
void GottaKink(Trajectory &tj, unsigned short &killPts)
label of module producing input hits
void FindVtxTjs(CTP_t inCTP)
label of module producing input hits
void DefinePFPParents(TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
void PrintResults(int eventNum) const
float fMaxWireSkipWithSignal
max number of wires to skip with a signal on them
void PrintHeader(std::string someText)
void UseUnusedHits()
label of module producing input hits
bool NeedsUpdate
Set true when the Tj needs to be updated (only for the TP Environment right now)
void TrajPointTrajDOCA(TjStuff &tjs, TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
art::InputTag fHitTruthModuleLabel
label of module producing MCParticle -> hit associations
bool DebugMode
print additional info when in debug mode
std::vector< unsigned int > NumWires
bool FindShowers3D(TjStuff &tjs, const geo::TPCID &tpcid)
don't mess with this line
short StepDir
the normal user-defined stepping direction = 1 (US -> DS) or -1 (DS -> US)
CTP_t CTP
set to an invalid CTP
TTree * crtree
label of module producing input hits
constexpr Point origin()
Returns a origin position with a point of the specified type.
bool IsGhost(std::vector< unsigned int > &tHits, unsigned short &ofTraj)
label of module producing input hits
bool valIncreasing(SortEntry c1, SortEntry c2)
const art::Ptr< simb::MCTruth > & TrackIdToMCTruth_P(int const &id)
void FitTraj(TjStuff &tjs, Trajectory &tj)
void TagShowerLike(std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP)
struct of temporary clusters
int fWorkID
label of module producing input hits
const detinfo::DetectorProperties * detprop