37 if(tj.
Pts.empty())
return;
41 unsigned short lastPtWithUsedHits = tj.
EndPt[1];
43 unsigned short lastPt = lastPtWithUsedHits;
48 ltp.
Pos = tj.
Pts[lastPt].Pos;
49 ltp.
Dir = tj.
Pts[lastPt].Dir;
57 unsigned short nMissedSteps = 0;
63 tjfs[0].nextForecastUpdate = 6;
76 lastPt = tj.
Pts.size() - 1;
82 for(
unsigned short iwt = 0; iwt < 2; ++iwt) ltp.
Pos[iwt] += ltp.
Dir[iwt] * stepSize;
88 myprt<<
"StepAway "<<
step<<
" Pos "<<tp.
Pos[0]<<
" "<<tp.
Pos[1]<<
" Dir "<<tp.
Dir[0]<<
" "<<tp.
Dir[1]<<
" stepSize "<<stepSize<<
" AngCode "<<tp.
AngleCode<<
" Strategy";
101 unsigned int wire = std::nearbyint(tp.
Pos[0]);
104 tj.
Pts.push_back(tp);
106 lastPt = tj.
Pts.size() - 1;
109 AddHits(slc, tj, lastPt, sigOK);
117 if(tj.
Pts[lastPt].AngleCode == 0 && lastPt == 2)
return;
127 if(tj.
Pts[lastPt].AngleCode > 0 && nMissedSteps > 4 && !sigOK)
break;
129 unsigned short lastPtWithHits = lastPt - 1;
132 float nMissedWires = tps *
std::abs(ltp.
Dir[0]) - dwc;
137 <<
" dead wire count "<<dwc<<
" maxWireSkip "<<maxWireSkip<<
" tj.PDGCode "<<tj.
PDGCode;
138 if(nMissedWires > maxWireSkip) {
142 if(tj.
EndPt[1] < tj.
Pts.size() - 1 && tj.
Pts[tj.
EndPt[1]+1].Hits.size() == 1) {
143 unsigned short lastLonelyPoint = tj.
EndPt[1] + 1;
144 unsigned int iht = tj.
Pts[lastLonelyPoint].Hits[0];
145 if(slc.
slHits[iht].InTraj == 0 && tj.
Pts[lastLonelyPoint].Delta < 3 * tj.
Pts[lastLonelyPoint].DeltaRMS) {
147 tj.
Pts[lastLonelyPoint].UseHit[0] =
true;
164 if(lastPt > 0 &&
PosSep2(tj.
Pts[lastPt].Pos, tj.
Pts[lastPt-1].Pos) < 0.1)
return;
171 if(tj.
Pts[lastPt].Chg == 0) {
176 float nMissedWires = tps *
std::abs(ltp.
Dir[0]) - dwc;
177 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
" Hits exist on the trajectory but are not used. Missed wires "<<std::nearbyint(nMissedWires)<<
" dead wire count "<<(
int)dwc;
197 if(tj.
Pts.size() == 3) {
207 if(dang > 0.5) badTj =
false;
210 if(!badTj && tj.
Pts[2].Delta > 2) badTj =
true;
218 ltp.
Pos = tj.
Pts[lastPt].Pos;
219 ltp.
Dir = tj.
Pts[lastPt].Dir;
253 if(tj.
Pts[lastPt].FitChi >
tcc.
maxChi && useMaxChiCut) {
289 if(npwc > 10)
return false;
295 myprt<<
" ChiDOF "<<chgFit.
ChiDOF;
296 myprt<<
" chg0 "<<chgFit.
Par0<<
" +/- "<<chgFit.
ParErr;
302 if(chgFit.
ChiDOF < 2)
return false;
303 if(chgFit.
ParSlp > -20)
return false;
308 unsigned short lastHiPt = 0;
309 for(
unsigned short ipt = 0; ipt < tj.
Pts.size(); ++ipt) {
310 auto& tp = tj.
Pts[ipt];
311 if(tp.Chg <= 0)
continue;
317 if(cnt < 3)
return false;
321 unsigned short firstLoPt = lastHiPt + 1;
322 for(
unsigned short ipt = lastHiPt + 1; ipt < tj.
Pts.size(); ++ipt) {
323 auto& tp = tj.
Pts[ipt];
324 if(tp.Chg <= 0 || tp.Chg > 0.5 * aveChg)
continue;
341 if(
tjfs.empty())
return;
358 bool tkLike = (tjf.outlook < 1.5);
360 bool chgIncreasing = (tjf.chgSlope > 0);
362 bool shLike = (tjf.outlook > 2 && chgIncreasing);
363 if(!shLike) shLike = tjf.showerLikeFraction > 0.5;
368 myprt<<
"SetStrategy: npwc "<<npwc<<
" outlook "<<tjf.outlook;
369 myprt<<
" tj MCSMom "<<tj.
MCSMom<<
" forecast MCSMom "<<tjf.MCSMom;
371 myprt<<
" tkLike? "<<tkLike<<
" shLike? "<<shLike;
372 myprt<<
" chgIncreasing? "<<chgIncreasing;
373 myprt<<
" leavesBeforeEnd? "<<tjf.leavesBeforeEnd<<
" endBraggPeak? "<<tjf.endBraggPeak;
374 myprt<<
" nextForecastUpdate "<<tjf.nextForecastUpdate;
376 if(tjf.outlook < 0)
return;
378 bool stiffMu = (tkLike && tjf.MCSMom > 600 && tjf.nextForecastUpdate > 100);
386 if(notStiff && !shLike && tj.
MCSMom < 100 && tjf.MCSMom < 100 && chgIncreasing) {
393 if(notStiff && !shLike && tj.
MCSMom < 200 && momRat < 0.7 && chgIncreasing) {
400 if(!tjf.leavesBeforeEnd && tjf.endBraggPeak) {
407 if(tkLike && tjf.nextForecastUpdate > 100 && tjf.leavesBeforeEnd && tjf.MCSMom < 500) {
411 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
"SetStrategy: Long track-like wandered out of forecast envelope. Reduce NTPsFit to "<<lastTP.NTPsFit;
415 if(tkLike && tjf.MCSMom > 600 && (tjf.foundShower || tjf.chgFitChiDOF > 20)) {
416 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
"SetStrategy: high MCSMom "<<tjf.MCSMom<<
" and a shower ahead. Use the StiffEl strategy";
423 if(shLike && !tjf.leavesBeforeEnd) {
443 if(tj.
Pts[tj.
EndPt[1]].AngleCode == 2)
return;
450 tjf.nextForecastUpdate = USHRT_MAX;
453 unsigned short istp = 0;
454 unsigned short nMissed = 0;
463 float minAveChg = 1E6;
464 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
465 if(tj.
Pts[ipt].AveChg <= 0)
continue;
466 if(tj.
Pts[ipt].AveChg > minAveChg)
continue;
467 minAveChg = tj.
Pts[ipt].AveChg;
469 if(minAveChg <= 0 || minAveChg == 1E6)
return;
478 float forecastWin0 =
std::abs(ltp.Pos[1] - ltp.HitPos[1]);
479 if(forecastWin0 < 1) forecastWin0 = 1;
480 ltp.Pos = ltp.HitPos;
481 double stepSize =
std::abs(1/ltp.Dir[0]);
485 mf::LogVerbatim(
"TC")<<
" stp ___Pos____ nTPH Chg ChgPull Delta DRMS chgWid nTkLk nShLk";
491 unsigned short maxChgPt = 0;
492 unsigned short leavesNear = USHRT_MAX;
493 bool leavesBeforeEnd =
false;
494 unsigned short showerStartNear = USHRT_MAX;
495 unsigned short showerEndNear = USHRT_MAX;
498 unsigned short trimPts = 0;
499 for(istp = 0; istp < 1000; ++istp) {
501 for(
unsigned short iwt = 0; iwt < 2; ++iwt) ltp.Pos[iwt] += ltp.Dir[iwt] * stepSize;
502 unsigned int wire = std::nearbyint(ltp.Pos[0]);
504 if(wire > slc.
lastWire[plane]-1)
break;
517 ltp.Delta =
PointTrajDOCA(slc, ltp.HitPos[0], ltp.HitPos[1], ltp);
518 ltp.DeltaRMS = ltp.Delta / window;
519 ltp.Environment.reset();
520 totHits += ltp.Hits.size();
521 if(ltp.Chg > maxChg) {
523 maxChgPt = fctj.
Pts.size();
527 ltp.ChgPull = (ltp.Chg / minAveChg - 1) / tj.
ChgRMS;
528 if((ltp.ChgPull > 3 && ltp.Hits.size() > 1) || ltp.ChgPull > 10) {
533 ltp.HitPosErr2 = 100;
538 if(fctj.
Pts.size() > 10) {
539 float shFrac = nShLike / (nShLike + nTkLike);
546 if(ltp.DeltaRMS > 0.8) {
547 leavesNear = npwc + fctj.
Pts.size();
549 leavesBeforeEnd =
true;
552 fctj.
Pts.push_back(ltp);
562 myprt<<
std::setw(8)<<sqrt(ltp.HitPosErr2);
571 if(doPrt)
mf::LogVerbatim(
"TC")<<
"No hits found after 10 steps - break";
578 if(fctj.
Pts.size() < 3)
return;
582 fctj.
Pts.resize(fctj.
Pts.size() - trimPts);
585 for(
auto& tp : fctj.
Pts) fctj.
TotChg += tp.Chg;
591 if(maxChgPt > 0.3 * fctj.
Pts.size() && maxChg > 3 * tj.
AveChg) {
594 FitPar(slc, fctj, 0, maxChgPt, 1, chgFit, 1);
596 FitPar(slc, fctj, 0, fctj.
Pts.size(), 1, chgFit, 1);
598 tjf.chgSlope = chgFit.
ParSlp;
600 tjf.chgFitChiDOF = chgFit.
ChiDOF;
608 tjf.nextForecastUpdate = npwc + fctj.
Pts.size();
609 tjf.leavesBeforeEnd = leavesBeforeEnd;
610 tjf.foundShower =
false;
611 if(leavesNear < tjf.nextForecastUpdate) {
613 tjf.nextForecastUpdate = leavesNear;
614 }
else if(showerStartNear < tjf.nextForecastUpdate) {
616 tjf.nextForecastUpdate = showerStartNear;
617 tjf.foundShower =
true;
618 }
else if(showerEndNear < tjf.nextForecastUpdate) {
620 tjf.nextForecastUpdate = showerEndNear;
624 tjf.showerLikeFraction = (
float)nShLike / (
float)fctj.
Pts.size();
628 myprt<<
"Forecast T"<<tj.
ID<<
" tj.AveChg "<<(
int)tj.
AveChg;
630 myprt<<
" last pos "<<
PrintPos(slc, ltp);
631 myprt<<
" MCSMom "<<tjf.MCSMom;
633 myprt<<
" chgSlope "<<
std::setprecision(1)<<tjf.chgSlope<<
" +/- "<<tjf.chgSlopeErr;
635 myprt<<
" endBraggPeak "<<tjf.endBraggPeak;
636 myprt<<
" chiDOF "<<tjf.chgFitChiDOF;
637 myprt<<
" showerLike fraction "<<tjf.showerLikeFraction;
638 myprt<<
" nextForecastUpdate "<<tjf.nextForecastUpdate;
639 myprt<<
" leavesBeforeEnd? "<<tjf.leavesBeforeEnd;
640 myprt<<
" foundShower? "<<tjf.foundShower;
674 if(tj.
EndPt[1] < 1)
return;
680 unsigned int lastPt = tj.
EndPt[1];
691 unsigned short prevPtWithHits = USHRT_MAX;
692 unsigned short firstFitPt = tj.
EndPt[0];
693 for(
unsigned short ii = 1; ii < tj.
Pts.size(); ++ii) {
694 unsigned short ipt = lastPt - ii;
695 if(tj.
Pts[ipt].Chg > 0) {
696 prevPtWithHits = ipt;
701 if(prevPtWithHits == USHRT_MAX)
return;
707 if(lastPt < 4) minPtsFit = 2;
713 minPtsFit = lastPt / 3;
721 short newMCSMom =
MCSMom(slc, tj);
722 short minMCSMom = 0.5 * tj.
MCSMom;
723 if(lastPt > 10 && newMCSMom < minMCSMom) {
735 mf::LogVerbatim(
"TC")<<
"UT: 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;
767 if(lastPt > 20 && tj.
Pts[prevPtWithHits].FitChi > 1.5 && lastTP.
NTPsFit > minPtsFit) lastTP.
NTPsFit -= 2;
769 if(cleanMuon && lastPt > 200 && tj.
Pts[prevPtWithHits].FitChi > 1.0) lastTP.
NTPsFit -= 2;
782 unsigned short cnt = 0;
783 for(
unsigned short ii = 0; ii < tj.
Pts.size(); ++ii) {
784 unsigned short ipt = lastPt - ii;
785 if(tj.
Pts[ipt].Chg > 0) {
789 if(cnt == lastTP.
NTPsFit)
break;
794 if(lastTP.
FitChi > 1.5 && tj.
Pts.size() > 6) {
799 if(ndead > 5 && !cleanMuon) {
808 if(prevPtWithHits != USHRT_MAX && tj.
Pts[prevPtWithHits].FitChi > 0) chirat = lastTP.
FitChi / tj.
Pts[prevPtWithHits].FitChi;
838 lastPt = tj.
EndPt[1];
846 unsigned short newNTPSFit = lastTP.
NTPsFit;
849 float prevChi = lastTP.
FitChi;
850 unsigned short ntry = 0;
853 while(lastTP.
FitChi > chiCut && lastTP.
NTPsFit > minPtsFit) {
855 newNTPSFit = 0.7 * newNTPSFit;
856 }
else if(lastTP.
NTPsFit > 4) {
861 if(lastTP.
NTPsFit < 3) newNTPSFit = 2;
862 if(newNTPSFit < minPtsFit) newNTPSFit = minPtsFit;
865 if(newNTPSFit == minPtsFit && tj.
MCSMom < 30) chiCut = 2;
869 if(lastTP.
FitChi > prevChi) {
876 if(lastTP.
NTPsFit == minPtsFit)
break;
885 lastPt = tj.
EndPt[1];
902 lastTP.
AngErr = defFrac * tj.
Pts[0].AngErr + (1 - defFrac) * lastTP.
AngErr;
990 bool isVLA = (tj.
Pts[tj.
EndPt[1]].AngleCode == 2);
1015 if(tj.
EndPt[1] < 4)
return;
1020 float frac = npwc / npts;
1024 mf::LogVerbatim(
"TC")<<
"CheckTraj: fraction of points with charge "<<frac<<
" good traj? "<<tj.
IsGood;
1045 if(tj.
Pts.empty())
return;
1046 if(ipt > tj.
Pts.size() - 1)
return;
1049 if(tj.
Pts[ipt].AngleCode == 2) {
1055 std::vector<unsigned int> closeHits;
1056 unsigned int lastPtWithUsedHits = tj.
EndPt[1];
1059 unsigned int wire = std::nearbyint(tp.
Pos[0]);
1066 float dw = tp.
Pos[0] - tj.
Pts[lastPtWithUsedHits].Pos[0];
1067 float dt = tp.
Pos[1] - tj.
Pts[lastPtWithUsedHits].Pos[1];
1068 float dpos = sqrt(dw * dw + dt * dt);
1069 float projErr = dpos * tj.
Pts[lastPtWithUsedHits].AngErr;
1071 float deltaCut = 3 * (projErr + tp.
DeltaRMS);
1074 float minDeltaCut = 1.1 * tj.
Pts[lastPtWithUsedHits].Delta;
1075 if(deltaCut < minDeltaCut) deltaCut = minDeltaCut;
1080 if(deltaCut < 0.5) deltaCut = 0.5;
1081 if(deltaCut > 3) deltaCut = 3;
1088 if(passedDeadWires) deltaCut *= 2;
1093 float bigDelta = 2 * deltaCut;
1094 unsigned int imBig = UINT_MAX;
1095 tp.
Delta = deltaCut;
1097 float maxDeltaCut = 2 * bigDelta;
1099 if(!passedDeadWires && maxDeltaCut > 3) {
1107 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(slc, tp);
1110 std::vector<unsigned int> hitsInMultiplet;
1113 unsigned int ipl = planeID.
Plane;
1114 if(wire > slc.
lastWire[ipl])
return;
1117 if(slc.
wireHitRange[ipl][wire].first == UINT_MAX)
return;
1118 unsigned int firstHit = slc.
wireHitRange[ipl][wire].first;
1119 unsigned int lastHit = slc.
wireHitRange[ipl][wire].second;
1121 for(
unsigned int iht = firstHit; iht <= lastHit; ++iht) {
1122 if(slc.
slHits[iht].InTraj == tj.
ID)
continue;
1123 if(slc.
slHits[iht].InTraj == SHRT_MAX)
continue;
1125 if(rawProjTick >
hit.StartTick() && rawProjTick <
hit.EndTick()) sigOK =
true;
1131 if(delta > 3)
continue;
1133 if(delta > maxDeltaCut)
continue;
1137 if(
tcc.
dbgStp && delta < 100 && dt < 100) {
1139 myprt<<
" iht "<<iht;
1141 myprt<<
" delta "<<std::fixed<<
std::setprecision(2)<<delta<<
" deltaCut "<<deltaCut<<
" dt "<<dt;
1144 myprt<<
" InTraj "<<slc.
slHits[iht].InTraj;
1145 myprt<<
" Chg "<<(
int)
hit.Integral();
1146 myprt<<
" Signal? "<<sigOK;
1148 if(slc.
slHits[iht].InTraj == 0 && delta < bigDelta && hitsInMultiplet.size() < 3 && !tj.
AlgMod[
kRvPrp]) {
1154 if(delta > 3)
continue;
1156 if(delta > deltaCut)
continue;
1159 if(std::find(closeHits.begin(), closeHits.end(), iht) != closeHits.end())
continue;
1160 closeHits.push_back(iht);
1161 if(hitsInMultiplet.size() > 1) {
1163 for(
auto& jht : hitsInMultiplet) {
1164 if(slc.
slHits[jht].InTraj == tj.
ID)
continue;
1165 if(std::find(closeHits.begin(), closeHits.end(), jht) != closeHits.end())
continue;
1166 closeHits.push_back(jht);
1173 myprt<<
"closeHits ";
1175 if(imBig < slc.
slHits.size()) {
1178 myprt<<
" imBig "<<imBig;
1184 bool nearSrcHit =
false;
1185 if(!sigOK) nearSrcHit =
NearbySrcHit(planeID, wire, (
float)rawProjTick, (
float)rawProjTick);
1186 sigOK = sigOK || !closeHits.empty() || nearSrcHit;
1192 if(imBig < slc.
slHits.size() && closeHits.empty()) {
1193 closeHits.push_back(imBig);
1196 if(closeHits.size() > 16) closeHits.resize(16);
1198 tp.
Hits.insert(tp.
Hits.end(), closeHits.begin(), closeHits.end());
1218 if(ipt > tj.
Pts.size() - 1)
return;
1228 std::vector<int> wires(1);
1229 wires[0] = std::nearbyint(tp.
Pos[0]);
1230 if(wires[0] < 0 || wires[0] > (
int)slc.
lastWire[plane]-1)
return;
1240 if(wires[0] < (
int)slc.
lastWire[plane]-1) wires.push_back(wires[0] + 1);
1241 if(wires[0] > 0) wires.push_back(wires[0] - 1);
1243 if(wires[0] > 0) wires.push_back(wires[0] - 1);
1244 if(wires[0] < (
int)slc.
lastWire[plane]-1) wires.push_back(wires[0] + 1);
1250 myprt<<
" AddLAHits: Pos "<<
PrintPos(slc, tp)<<
" tp.AngleCode "<<tp.
AngleCode<<
" Wires under consideration";
1251 for(
auto& wire : wires) myprt<<
" "<<wire;
1260 std::array<int, 2> wireWindow;
1261 std::array<float, 2> timeWindow;
1263 timeWindow[0] = ltp.
Pos[1] - pos1Window;
1264 timeWindow[1] = ltp.
Pos[1] + pos1Window;
1268 for(
unsigned short ii = 0; ii < wires.size(); ++ii) {
1269 int wire = wires[ii];
1270 if(wire < 0 || wire > (
int)slc.
lastWire[plane])
continue;
1272 if(slc.
wireHitRange[plane][wire].first == UINT_MAX) sigOK =
true;
1273 if(slc.
wireHitRange[plane][wire].first == UINT_MAX)
continue;
1274 wireWindow[0] = wire;
1275 wireWindow[1] = wire;
1278 std::vector<unsigned int> closeHits =
FindCloseHits(slc, wireWindow, timeWindow, plane,
kAllHits,
true, hitsNear);
1279 if(hitsNear) sigOK =
true;
1280 for(
auto& iht : closeHits) {
1282 if(slc.
slHits[iht].InTraj == tj.
ID)
continue;
1284 if(std::find(oldHits.begin(), oldHits.end(), iht) != oldHits.end())
continue;
1285 tp.
Hits.push_back(iht);
1296 if(tp.
Hits.empty())
return;
1298 if(tp.
Hits.size() > 16) tp.
Hits.resize(16);
1301 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1302 unsigned int iht = tp.
Hits[ii];
1303 if(slc.
slHits[iht].InTraj != 0)
continue;
1321 if(tj.
Pts.size() < 6)
return;
1326 if(tj.
Pts[tj.
EndPt[0]].AngleCode == 2)
return;
1331 if(tj.
EndPt[0] > 0) {
1341 unsigned int wire0 = std::nearbyint(tj.
Pts[0].Pos[0]);
1342 unsigned int nextWire = wire0 - tj.
StepDir;
1346 unsigned short ipl = planeID.
Plane;
1351 if(nextWire == slc.
lastWire[ipl] - 1)
return;
1359 float maxDelta = 10 * tj.
Pts[tj.
EndPt[1]].DeltaRMS;
1362 if(tp.
Hits.empty())
return;
1378 auto saveStrategy = tjWork.
Strategy;
1382 unsigned short lastPt = tjWork.
Pts.size() - 1;
1383 if(lastPt < 4)
return;
1387 for(
unsigned short ii = 0; ii < 4; ++ii) {
1388 unsigned short ipt = lastPt - ii;
1389 if(tjWork.
Pts[ipt].Chg == 0)
continue;
1390 chg += tjWork.
Pts[ipt].Chg;
1393 if(cnt == 0)
return;
1394 if(cnt > 1) tjWork.
Pts[lastPt].AveChg = chg / cnt;
1413 void GetHitMultiplet(
const TCSlice& slc,
unsigned int theHit, std::vector<unsigned int>& hitsInMultiplet,
bool useLongPulseHits)
1422 hitsInMultiplet.clear();
1424 if(theHit >= slc.
slHits.size())
return;
1425 if(slc.
slHits[theHit].InTraj == INT_MAX)
return;
1432 short int hitMult =
hit.Multiplicity();
1433 unsigned int lIndex =
hit.LocalIndex();
1434 unsigned int firstHit = 0;
1435 if(lIndex < theHit) firstHit = theHit - lIndex;
1436 for(
unsigned int ii = firstHit; ii < firstHit + hitMult; ++ii) {
1437 if(ii >= slc.
slHits.size())
break;
1439 if(
tmp.Multiplicity() == hitMult) hitsInMultiplet.push_back(ii);
1444 hitsInMultiplet.resize(1);
1445 hitsInMultiplet[0] = theHit;
1446 unsigned int theWire =
hit.WireID().Wire;
1447 unsigned short ipl =
hit.WireID().Plane;
1449 float theTime =
hit.PeakTime();
1450 float theRMS =
hit.RMS();
1452 bool theHitIsNarrow = (theRMS < narrowHitCut);
1453 float maxPeak =
hit.PeakAmplitude();
1454 unsigned int imTall = theHit;
1455 unsigned short nNarrow = 0;
1456 if(theHitIsNarrow) nNarrow = 1;
1459 for(
unsigned int iht = theHit - 1; iht != 0; --iht) {
1461 if(
hit.WireID().Wire != theWire)
break;
1462 if(
hit.WireID().Plane != ipl)
break;
1470 if(dTick > hitSep)
break;
1471 hitsInMultiplet.push_back(iht);
1472 if(rms < narrowHitCut) ++nNarrow;
1473 float peakAmp =
hit.PeakAmplitude();
1474 if(peakAmp > maxPeak) {
1478 theTime =
hit.PeakTime();
1484 if(hitsInMultiplet.size() > 1)
std::reverse(hitsInMultiplet.begin(), hitsInMultiplet.end());
1486 theTime =
hit.PeakTime();
1488 for(
unsigned int iht = theHit + 1; iht < slc.
slHits.size(); ++iht) {
1490 if(
hit.WireID().Wire != theWire)
break;
1491 if(
hit.WireID().Plane != ipl)
break;
1492 if(slc.
slHits[iht].InTraj == INT_MAX)
continue;
1500 if(dTick > hitSep)
break;
1501 hitsInMultiplet.push_back(iht);
1502 if(rms < narrowHitCut) ++nNarrow;
1503 float peakAmp =
hit.PeakAmplitude();
1504 if(peakAmp > maxPeak) {
1508 theTime =
hit.PeakTime();
1510 if(hitsInMultiplet.size() == 1)
return;
1513 if(nNarrow == hitsInMultiplet.size())
return;
1514 if(nNarrow == 0)
return;
1516 if(theHitIsNarrow && theHit == imTall) {
1519 auto tmp = hitsInMultiplet;
1522 hitsInMultiplet =
tmp;
1527 if(
hit.RMS() < narrowHitCut) {
1528 unsigned short killMe = 0;
1529 for(
unsigned short ii = 0; ii < hitsInMultiplet.size(); ++ii) {
1530 if(hitsInMultiplet[ii] == imTall) {
1535 hitsInMultiplet.erase(hitsInMultiplet.begin() + killMe);
1544 if(iht > slc.
slHits.size() - 1)
return 0;
1553 if(hitVec.empty())
return 0;
1570 unsigned short endPt = tj.
EndPt[1];
1572 if(tj.
Pts[endPt].AngleCode > 1)
return;
1574 if(tj.
Pts.size() - endPt > 10)
return;
1578 unsigned short plane = planeID.
Plane;
1581 unsigned short lastPt = tj.
Pts.size() - 1;
1582 for(lastPt = tj.
Pts.size() - 1; lastPt >= tj.
EndPt[1]; --lastPt)
if(!tj.
Pts[lastPt].Hits.empty())
break;
1583 auto& lastTP = tj.
Pts[lastPt];
1586 mf::LogVerbatim(
"TC")<<
"CSEP: checking "<<tj.
ID<<
" endPt "<<endPt<<
" Pts size "<<tj.
Pts.size()<<
" lastPt Pos "<<
PrintPos(slc, lastTP.Pos);
1590 ltp.
Pos = tj.
Pts[endPt].Pos;
1591 ltp.
Dir = tj.
Pts[endPt].Dir;
1593 std::array<int, 2> wireWindow;
1594 std::array<float, 2> timeWindow;
1595 std::vector<int> closeHits;
1596 bool isClean =
true;
1598 for(
unsigned short iwt = 0; iwt < 2; ++iwt) ltp.
Pos[iwt] += ltp.
Dir[iwt] * stepSize;
1599 int wire = std::nearbyint(ltp.
Pos[0]);
1600 wireWindow[0] = wire;
1601 wireWindow[1] = wire;
1602 timeWindow[0] = ltp.
Pos[1] - 5;
1603 timeWindow[1] = ltp.
Pos[1] + 5;
1607 for(
auto iht :
tmp)
if(slc.
slHits[iht].InTraj != tj.
ID) closeHits.push_back(iht);
1608 float nWiresPast = 0;
1610 if(ltp.
Dir[0] > 0) {
1612 nWiresPast = ltp.
Pos[0] - lastTP.Pos[0];
1615 nWiresPast = lastTP.Pos[0] - ltp.
Pos[0];
1618 if(nWiresPast > 0.5) {
1619 if(!tmp.empty()) isClean =
false;
1620 if(nWiresPast > 1.5)
break;
1625 unsigned short nAvailable = 0;
1626 for(
auto iht : closeHits)
if(slc.
slHits[iht].InTraj == 0) ++nAvailable;
1632 myprt<<
" nAvailable "<<nAvailable;
1633 myprt<<
" isClean "<<isClean;
1636 if(!isClean || nAvailable != closeHits.size())
return;
1638 unsigned short originalEndPt = tj.
EndPt[1] + 1;
1640 for(
unsigned short ipt = originalEndPt; ipt <= lastPt; ++ipt) {
1641 auto& tp = tj.
Pts[ipt];
1642 bool hitsAdded =
false;
1643 for(
unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1645 if(slc.
slHits[tp.Hits[ii]].InTraj != 0)
continue;
1646 tp.UseHit[ii] =
true;
1647 slc.
slHits[tp.Hits[ii]].InTraj = tj.
ID;
1661 for(
unsigned short ipt = originalEndPt; ipt <= lastPt; ++ipt)
UnsetUsedHits(slc, tj.
Pts[ipt]);
1675 if(tp.
Hits.empty())
return;
1677 unsigned short nused = 0;
1678 unsigned int iht = 0;
1679 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1680 if(!tp.
UseHit[ii])
continue;
1683 if(iht >= slc.
slHits.size())
return;
1686 if(nused == 0)
return;
1701 if(pathInv < 0.05) pathInv = 0.05;
1703 float wireErr = tp.
Dir[1] * 0.289;
1705 tp.
HitPosErr2 = wireErr * wireErr + timeErr * timeErr;
1712 std::vector<unsigned int> hitVec;
1714 std::array<float, 2> newpos;
1719 unsigned int loWire = INT_MAX;
1720 unsigned int hiWire = 0;
1721 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1722 if(!tp.
UseHit[ii])
continue;
1723 unsigned int iht = tp.
Hits[ii];
1725 chg =
hit.Integral();
1726 unsigned int wire =
hit.WireID().Wire;
1727 if(wire < loWire) loWire = wire;
1728 if(wire > hiWire) hiWire = wire;
1729 newpos[0] += chg * wire;
1730 newpos[1] += chg *
hit.PeakTime();
1732 hitVec.push_back(iht);
1735 if(tp.
Chg == 0)
return;
1741 if(pathInv < 0.05) pathInv = 0.05;
1745 float dWire = 1 + hiWire - loWire;
1746 float wireErr = tp.
Dir[1] * dWire * 0.289;
1748 tp.
HitPosErr2 = wireErr * wireErr + timeErr2;
1760 if(ipt > tj.
Pts.size() - 1)
return;
1763 if(tp.
Hits.empty())
return;
1765 if(ipt < 5) useChg =
false;
1766 float chgPullCut = 1000;
1770 if(tj.
MCSMom < 30) chgPullCut *= 2;
1772 bool ignoreLongPulseHits =
false;
1773 unsigned short npts = tj.
EndPt[1] - tj.
EndPt[0] + 1;
1774 if(npts < 10 || tj.
AlgMod[
kRvPrp]) ignoreLongPulseHits =
true;
1782 if(pathInv < 0.05) pathInv = 0.05;
1785 tp.
Delta = maxDelta;
1787 unsigned short imbest = USHRT_MAX;
1788 std::vector<float> deltas(tp.
Hits.size(), 100);
1790 float bestDelta = maxDelta;
1791 unsigned short nAvailable = 0;
1792 unsigned short firstAvailable = USHRT_MAX;
1793 unsigned short lastAvailable = USHRT_MAX;
1794 unsigned short firstUsed = USHRT_MAX;
1795 unsigned short imBadRecoHit = USHRT_MAX;
1796 bool bestHitLongPulse =
false;
1797 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1799 unsigned int iht = tp.
Hits[ii];
1800 if(iht >= slc.
slHits.size())
continue;
1803 if(delta < bestDelta) bestDelta = delta;
1804 if(slc.
slHits[iht].InTraj > 0) {
1805 if(firstUsed == USHRT_MAX) firstUsed = ii;
1810 if(
hit.GoodnessOfFit() < 0 ||
hit.GoodnessOfFit() > 100) imBadRecoHit = ii;
1811 if(firstAvailable == USHRT_MAX) firstAvailable = ii;
1822 if(delta < tp.
Delta) {
1829 float chgWght = 0.5;
1831 if(
tcc.
dbgStp)
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;
1832 if(imbest == USHRT_MAX || nAvailable == 0)
return;
1833 unsigned int bestDeltaHit = tp.
Hits[imbest];
1837 tp.
UseHit[imbest] =
true;
1838 slc.
slHits[bestDeltaHit].InTraj = tj.
ID;
1843 if(tp.
Hits.size() > 2 && nAvailable > 1 && firstUsed != USHRT_MAX && firstAvailable < firstUsed && lastAvailable > firstUsed) {
1845 tp.
UseHit[imbest] =
true;
1846 slc.
slHits[bestDeltaHit].InTraj = tj.
ID;
1852 std::vector<unsigned int> hitsInMultiplet;
1857 myprt<<
" in multiplet:";
1858 for(
auto& iht : hitsInMultiplet) myprt<<
" "<<
PrintHit(slc.
slHits[iht]);
1862 if(imBadRecoHit != USHRT_MAX) {
1863 unsigned int iht = tp.
Hits[imBadRecoHit];
1867 tp.
UseHit[imBadRecoHit] =
true;
1873 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1874 unsigned int iht = tp.
Hits[ii];
1875 if(slc.
slHits[iht].InTraj > 0)
continue;
1876 if(std::find(hitsInMultiplet.begin(), hitsInMultiplet.end(), iht) == hitsInMultiplet.end())
continue;
1887 if(!useChg || (useChg && (tj.
AveChg <= 0 || tj.
ChgRMS <= 0))) {
1890 tp.
UseHit[imbest] =
true;
1891 slc.
slHits[bestDeltaHit].InTraj = tj.
ID;
1896 if(tj.
PDGCode == 13 && bestDelta < 0.5) {
1898 tp.
UseHit[imbest] =
true;
1899 slc.
slHits[bestDeltaHit].InTraj = tj.
ID;
1904 if(nAvailable == 1 || tp.
AngleCode == 0) {
1906 float aveChg = tp.
AveChg;
1907 if(aveChg <= 0) aveChg = tj.
AveChg;
1908 if(aveChg <= 0) aveChg =
hit.Integral();
1909 float chgRMS = tj.
ChgRMS;
1910 if(chgRMS < 0.2) chgRMS = 0.2;
1911 float bestDeltaHitChgPull =
std::abs(
hit.Integral() * pathInv / aveChg - 1) / chgRMS;
1913 if(bestDeltaHitChgPull < chgPullCut || tp.
Delta < 0.1) {
1914 tp.
UseHit[imbest] =
true;
1915 slc.
slHits[bestDeltaHit].InTraj = tj.
ID;
1924 if(nAvailable == 2) {
1926 std::vector<unsigned int> tHits;
1930 unsigned short ombest = USHRT_MAX;
1931 unsigned int otherHit = INT_MAX;
1932 if(tHits.size() == 2) {
1933 unsigned short localIndex = 0;
1934 if(tHits[0] == bestDeltaHit) localIndex = 1;
1935 otherHit = tHits[1 - localIndex];
1937 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1938 if(slc.
slHits[tp.
Hits[ii]].InTraj > 0)
continue;
1939 if(tp.
Hits[ii] == otherHit) {
1946 mf::LogVerbatim(
"TC")<<
" Doublet: imbest "<<imbest<<
" ombest "<<ombest;
1949 if(ombest < tp.
Hits.size()) {
1953 float bestDeltaHitFOM = deltas[imbest] / bestHitDeltaErr;
1954 if(bestDeltaHitFOM < 0.5) bestDeltaHitFOM = 0.5;
1958 if(bestDeltaHitChgPull > 1) bestDeltaHitFOM *= chgWght * bestDeltaHitChgPull;
1960 float rmsRat =
hit.RMS() / expectedWidth;
1961 if(rmsRat < 1) rmsRat = 1 / rmsRat;
1962 bestDeltaHitFOM *= rmsRat;
1963 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
" bestDeltaHit FOM "<<deltas[imbest]/bestHitDeltaErr<<
" bestDeltaHitChgPull "<<bestDeltaHitChgPull<<
" rmsRat "<<rmsRat<<
" bestDeltaHitFOM "<<bestDeltaHitFOM;
1966 float otherHitFOM = deltas[ombest] / otherHitDeltaErr;
1967 if(otherHitFOM < 0.5) otherHitFOM = 0.5;
1970 if(otherHitChgPull > 1) otherHitFOM *= chgWght * otherHitChgPull;
1971 rmsRat = ohit.RMS() / expectedWidth;
1972 if(rmsRat < 1) rmsRat = 1 / rmsRat;
1973 otherHitFOM *= rmsRat;
1974 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
" otherHit FOM "<<deltas[ombest]/otherHitDeltaErr<<
" otherHitChgPull "<<otherHitChgPull<<
" rmsRat "<<rmsRat<<
" otherHitFOM "<<otherHitFOM;
1976 float doubletChg =
hit.Integral() + ohit.Integral();
1977 float doubletTime = (
hit.Integral() *
hit.PeakTime() + ohit.Integral() * ohit.PeakTime()) / doubletChg;
1978 doubletChg *= pathInv;
1982 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
" doublet Chg "<<doubletChg<<
" doubletTime "<<doubletTime<<
" doubletRMSTimeErr "<<doubletRMSTimeErr;
1983 float doubletFOM =
PointTrajDOCA(slc, tp.
Pos[0], doubletTime, tp) / doubletRMSTimeErr;
1984 if(doubletFOM < 0.5) doubletFOM = 0.5;
1986 if(doubletChgPull > 1) doubletFOM *= chgWght * doubletChgPull;
1987 rmsRat = doubletWidthTick / expectedWidth;
1988 if(rmsRat < 1) rmsRat = 1 / rmsRat;
1989 doubletFOM *= rmsRat;
1990 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
" doublet FOM "<<
PointTrajDOCA(slc, tp.
Pos[0], doubletTime, tp)/doubletRMSTimeErr<<
" doubletChgPull "<<doubletChgPull<<
" rmsRat "<<rmsRat<<
" doubletFOM "<<doubletFOM;
1991 if(doubletFOM < bestDeltaHitFOM && doubletFOM < otherHitFOM) {
1992 tp.
UseHit[imbest] =
true;
1993 slc.
slHits[bestDeltaHit].InTraj = tj.
ID;
1994 tp.
UseHit[ombest] =
true;
1995 slc.
slHits[otherHit].InTraj = tj.
ID;
1998 if(bestDeltaHitFOM < otherHitFOM) {
1999 tp.
UseHit[imbest] =
true;
2000 slc.
slHits[bestDeltaHit].InTraj = tj.
ID;
2002 tp.
UseHit[ombest] =
true;
2003 slc.
slHits[otherHit].InTraj = tj.
ID;
2008 tp.
UseHit[imbest] =
true;
2009 slc.
slHits[bestDeltaHit].InTraj = tj.
ID;
2016 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
" Multiplet: hitsWidth "<<hitsWidth<<
" expectedWidth "<<expectedWidth<<
" tick range "<<(
int)minTick<<
" "<<(
int)maxTick;
2018 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
2019 unsigned int iht = tp.
Hits[ii];
2020 if(slc.
slHits[iht].InTraj > 0)
continue;
2022 if(
hit.PeakTime() < minTick)
continue;
2023 if(
hit.PeakTime() > maxTick)
continue;
2037 if(tj.
ChgRMS <= 0)
return;
2040 if(npwc < 8)
return;
2043 unsigned short toPt = tj.
EndPt[1] - 2;
2047 unsigned short cnt = 0;
2048 for(
unsigned short ipt = tj.
EndPt[1] - 2; ipt > tj.
EndPt[0]; --ipt) {
2049 auto& tp = tj.
Pts[ipt];
2052 for(
unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2053 unsigned int iht = tp.Hits[ii];
2055 chg +=
hit.Integral();
2071 short firstPtWithChg = tj.
EndPt[0];
2075 short minMCSMom = 0.7 * tj.
MCSMom;
2076 while(firstPtWithChg < toPt) {
2077 short nextPtWithChg = firstPtWithChg + 1;
2079 for(nextPtWithChg = firstPtWithChg + 1; nextPtWithChg < tj.
EndPt[1]; ++nextPtWithChg) {
2080 if(tj.
Pts[nextPtWithChg].Chg > 0)
break;
2082 if(nextPtWithChg == firstPtWithChg + 1) {
2088 if(nextPtWithChg < (tj.
EndPt[1] - 1) && tj.
Pts[nextPtWithChg + 1].Chg == 0) {
2089 firstPtWithChg = nextPtWithChg;
2107 if(tj.
Pts.size() < 10) {
2110 short chgCutPt = tj.
EndPt[0] + 5;
2111 if(firstPtWithChg < chgCutPt) {
2116 chgCutPt = tj.
EndPt[1] - 5;
2117 if(chgCutPt < tj.
EndPt[0]) chgCutPt = tj.
EndPt[0];
2118 if(nextPtWithChg > chgCutPt) maxChg = 1E6;
2123 for(
unsigned short mpt = firstPtWithChg + 1; mpt < nextPtWithChg; ++mpt) {
2124 if(tj.
Pts[mpt].Chg > 0) {
2125 mf::LogVerbatim(
"TC")<<
"FillGaps coding error: firstPtWithChg "<<firstPtWithChg<<
" mpt "<<mpt<<
" nextPtWithChg "<<nextPtWithChg;
2129 bool filled =
false;
2131 for(
unsigned short ii = 0; ii < tj.
Pts[mpt].Hits.size(); ++ii) {
2132 unsigned int iht = tj.
Pts[mpt].Hits[ii];
2133 if(slc.
slHits[iht].InTraj > 0)
continue;
2137 if(delta > maxDelta)
continue;
2138 tj.
Pts[mpt].UseHit[ii] =
true;
2140 chg +=
hit.Integral();
2143 if(chg > maxChg ||
MCSMom(slc, tj) < minMCSMom) {
2157 firstPtWithChg = nextPtWithChg;
2175 if(tj.
Pts[tj.
EndPt[1]].AngleCode == 0)
return;
2180 unsigned short ii, stopPt;
2183 unsigned short lastMult1Pt = USHRT_MAX;
2185 unsigned short nHiMultPt = 0;
2187 unsigned short nHiMultPtHits = 0;
2189 unsigned short nHiMultPtUsedHits = 0;
2193 bool doBreak =
false;
2195 for(ii = 1; ii < tj.
Pts.size(); ++ii) {
2196 stopPt = tj.
EndPt[1] - ii;
2197 for(jj = 0; jj < tj.
Pts[stopPt].Hits.size(); ++jj) {
2198 iht = tj.
Pts[stopPt].Hits[jj];
2199 if(slc.
slHits[iht].InTraj > 0) {
2206 if(lastMult1Pt == USHRT_MAX && tj.
Pts[stopPt].Hits.size() == 1 && tj.
Pts[stopPt-1].Hits.size() == 1) lastMult1Pt = stopPt;
2207 if(tj.
Pts[stopPt].Hits.size() > 1) {
2209 nHiMultPtHits += tj.
Pts[stopPt].Hits.size();
2213 if(lastMult1Pt != USHRT_MAX)
break;
2214 if(stopPt == 1)
break;
2217 float fracHiMult = (
float)nHiMultPt / (
float)ii;
2218 if(lastMult1Pt != USHRT_MAX) {
2219 float nchk = tj.
EndPt[1] - lastMult1Pt + 1;
2220 fracHiMult = (
float)nHiMultPt / nchk;
2222 fracHiMult = (
float)nHiMultPt / (
float)ii;
2224 float fracHitsUsed = 0;
2225 if(nHiMultPt > 0 && nHiMultPtHits > 0) fracHitsUsed = (
float)nHiMultPtUsedHits / (
float)nHiMultPtHits;
2231 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
"CHMUH: First InTraj stopPt "<<stopPt<<
" fracHiMult "<<fracHiMult<<
" fracHitsUsed "<<fracHitsUsed<<
" lastMult1Pt "<<lastMult1Pt<<
" sortaLargeAngle "<<sortaLargeAngle;
2232 if(fracHiMult < 0.3)
return;
2233 if(fracHitsUsed > 0.98)
return;
2238 mf::LogVerbatim(
"TC")<<
" Pts size "<<tj.
Pts.size()<<
" nHiMultPt "<<nHiMultPt<<
" nHiMultPtHits "<<nHiMultPtHits<<
" nHiMultPtUsedHits "<<nHiMultPtUsedHits<<
" sortaLargeAngle "<<sortaLargeAngle<<
" maxHitDelta "<<maxDelta;
2255 for(ipt = stopPt + 1; ipt < tj.
Pts.size(); ++ipt) {
2258 for(ii = 0; ii < tj.
Pts[ipt].Hits.size(); ++ii) {
2259 iht = tj.
Pts[ipt].Hits[ii];
2261 if(slc.
slHits[iht].InTraj != 0)
continue;
2263 if(delta > maxDelta)
continue;
2265 tj.
Pts[ipt].UseHit[ii] =
true;
2271 if(tj.
Pts[ipt].Chg == 0)
continue;
2274 if(sortaLargeAngle) tj.
Pts[ipt].NTPsFit = 2;
2279 for(
unsigned short jpt = stopPt + 1; jpt <= ipt; ++jpt) {
2280 for(
unsigned short jj = 0; jj < tj.
Pts[jpt].Hits.size(); ++jj) {
2281 if(tj.
Pts[jpt].UseHit[jj]) slc.
slHits[tj.
Pts[jpt].Hits[jj]].InTraj = 0;
2287 for(
unsigned short jpt = stopPt + 1; jpt <= ipt; ++jpt) {
2288 for(
unsigned short jj = 0; jj < tj.
Pts[jpt].Hits.size(); ++jj) {
2289 if(tj.
Pts[jpt].UseHit[jj]) slc.
slHits[tj.
Pts[jpt].Hits[jj]].InTraj = tj.
ID;
2312 if(tj.
Pts.size() < 10)
return;
2313 if(tj.
Pts[tj.
EndPt[1]].AngleCode == 0)
return;
2315 unsigned short aveMult= 0;
2316 unsigned short ipt, nhalf = tj.
Pts.size() / 2;
2317 unsigned short cnt = 0;
2318 for(
auto& tp : tj.
Pts) {
2319 if(tp.Chg == 0)
continue;
2320 aveMult += tp.Hits.size();
2322 if(cnt == nhalf)
break;
2324 if(cnt == 0)
return;
2326 if(aveMult == 0) aveMult = 1;
2330 for(ipt = tj.
EndPt[1]; ipt > tj.
EndPt[0]; --ipt) {
2331 if(tj.
Pts[ipt].Chg == 0)
continue;
2332 if(tj.
Pts[ipt].Hits.size() > aveMult) {
2351 unsigned int lastPt = tj.
EndPt[1];
2354 if(lastTP.
Chg == 0)
return;
2355 if(lastPt < 6)
return;
2357 unsigned short ii, ipt, cnt = 0;
2359 for(ii = 1; ii < tj.
Pts.size(); ++ii) {
2361 if(ipt > tj.
Pts.size() - 1)
break;
2362 if(tj.
Pts[ipt].Chg == 0)
continue;
2365 if(cnt == lastTP.
NTPsFit)
break;
2387 if(tj.
Pts.size() < 3) {
2392 unsigned short nit = 0;
2394 while(lastTP.
FitChi > maxChi && nit < 3) {
2396 unsigned short imBad = USHRT_MAX;
2397 unsigned short cnt = 0;
2398 for(
unsigned short ii = 1; ii < tj.
Pts.size(); ++ii) {
2399 unsigned short ipt = tj.
Pts.size() - 1 - ii;
2401 if(tp.
Chg == 0)
continue;
2402 if(tp.
Delta > maxDelta) {
2403 maxDelta = tp.
Delta;
2409 if(imBad == USHRT_MAX)
return;
2429 unsigned short lastPt = tj.
Pts.size() - 1;
2430 if(tj.
Pts[lastPt].Chg > 0)
return true;
2431 unsigned short endPt = tj.
EndPt[1];
2434 unsigned short nMasked = 0;
2435 unsigned short nOneHit = 0;
2436 unsigned short nOKChg = 0;
2437 unsigned short nOKDelta = 0;
2439 unsigned short nPosDelta = 0;
2441 unsigned short nDeltaIncreasing = 0;
2443 float prevDelta = tj.
Pts[endPt].Delta;
2444 float maxOKDelta = 10 * tj.
Pts[endPt].DeltaRMS;
2447 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt)
if(tj.
Pts[ipt].Chg > maxOKChg) maxOKChg = tj.
Pts[ipt].Chg;
2448 for(
unsigned short ii = 1; ii < tj.
Pts.size(); ++ii) {
2449 unsigned short ipt = tj.
Pts.size() - ii;
2450 auto& tp = tj.
Pts[ipt];
2451 if(tp.Chg > 0)
break;
2452 unsigned short nUnusedHits = 0;
2454 for(
unsigned short jj = 0; jj < tp.Hits.size(); ++jj) {
2455 unsigned int iht = tp.Hits[jj];
2456 if(slc.
slHits[iht].InTraj != 0)
continue;
2459 chg +=
hit.Integral();
2461 if(chg < maxOKChg) ++nOKChg;
2462 if(nUnusedHits == 1) ++nOneHit;
2463 if(tp.Delta < maxOKDelta) ++nOKDelta;
2465 if(tp.Pos[1] > tp.HitPos[1]) ++nPosDelta;
2467 if(tp.Delta < prevDelta) ++nDeltaIncreasing;
2468 prevDelta = tp.Delta;
2475 bool driftingAway = nMasked > 2 && (nPosDelta == 0 || nPosDelta == nMasked);
2477 if(driftingAway && nDeltaIncreasing < nMasked - 1) driftingAway =
false;
2480 mf::LogVerbatim(
"TC")<<
"MHOK: nMasked "<<nMasked<<
" nOneHit "<<nOneHit<<
" nOKChg "<<nOKChg<<
" nOKDelta "<<nOKDelta<<
" nPosDelta "<<nPosDelta<<
" nDeltaIncreasing "<<nDeltaIncreasing<<
" driftingAway? "<<driftingAway;
2484 if(nMasked < 8 || nOneHit < 8)
return true;
2485 if(nOKDelta != nMasked)
return true;
2486 if(nOKChg != nMasked)
return true;
2493 if(nMasked > tj.
Pts[endPt].NTPsFit)
return false;
2497 unsigned short newNTPSFit;
2499 newNTPSFit = tj.
Pts[endPt].NTPsFit / 2;
2503 for(
unsigned ipt = endPt + 1; ipt < tj.
Pts.size(); ++ipt) {
2505 for(
unsigned short ii = 0; ii < tj.
Pts[ipt].Hits.size(); ++ii) {
2506 unsigned int iht = tp.
Hits[ii];
2507 if(slc.
slHits[iht].InTraj == 0) {
2533 if(tj.
PDGCode == 13)
return false;
2535 if(tj.
Pts.size() > 40 && tj.
MCSMom > 200)
return false;
2537 unsigned short nBadFit = 0;
2538 unsigned short nHiChg = 0;
2539 unsigned short cnt = 0;
2540 for(
unsigned short ipt = tj.
Pts.size() - 1; ipt > tj.
EndPt[1]; --ipt ) {
2541 if(tj.
Pts[ipt].FitChi > 2) ++nBadFit;
2542 if(tj.
Pts[ipt].ChgPull > 3) ++nHiChg;
2548 if(nBadFit > 3 && nHiChg == 0)
return true;
2574 if(npwc < 2 * nPtsFit)
return false;
2579 unsigned short fitPt = USHRT_MAX;
2580 unsigned short cnt = 0;
2581 for(
unsigned short ii = 0; ii < tj.
Pts.size(); ++ii) {
2582 unsigned short ipt = tj.
EndPt[1] - ii - 1;
2585 if(ipt <= tj.
EndPt[0] + 2)
break;
2586 if(tj.
Pts[ipt].Chg <= 0)
continue;
2595 if(fitPt == USHRT_MAX) {
2598 myprt<<
"GKv2 fitPt not valid. Counted "<<cnt<<
" points. Need "<<nPtsFit;
2606 bool prevPtHasKink = (tj.
Pts[fitPt - 1].KinkSig >
tcc.
kinkCuts[1]);
2609 myprt<<
"GKv2 fitPt "<<fitPt<<
" "<<
PrintPos(slc, tj.
Pts[fitPt]);
2612 myprt<<
" prevPt significance "<<tj.
Pts[fitPt - 1].KinkSig;
2613 if(!thisPtHasKink && !prevPtHasKink) myprt<<
" no kink";
2614 if(thisPtHasKink && !prevPtHasKink) myprt<<
" -> Start kink region";
2615 if(thisPtHasKink && prevPtHasKink) myprt<<
" -> Inside kink region";
2616 if(!thisPtHasKink && prevPtHasKink) myprt<<
" -> End kink region";
2621 if(thisPtHasKink)
return false;
2623 if(!prevPtHasKink)
return false;
2628 unsigned short kinkRegionLength = 0;
2629 unsigned short maxKinkPt = USHRT_MAX;
2630 for(
unsigned short ipt = fitPt - 1; ipt > tj.
EndPt[0]; --ipt) {
2631 auto& tp = tj.
Pts[ipt];
2632 if(tp.KinkSig < 0)
continue;
2633 if(tp.KinkSig > maxSig) {
2635 maxSig = tp.KinkSig;
2642 if(maxKinkPt == USHRT_MAX)
return false;
2645 unsigned short kinkRegionLengthMin = 1 + nPtsFit / 5;
2647 if(kinkRegionLength < kinkRegionLengthMin) {
2648 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
"GKv2: kink region too short "<<kinkRegionLength<<
" Min "<<kinkRegionLengthMin;
2653 if(!doTrim)
return true;
2658 float lastChg = tj.
Pts[tj.
EndPt[1]].Chg;
2659 float prevChg = tj.
Pts[tj.
EndPt[1] - 1].Chg;
2660 float chgAsym =
std::abs(lastChg - prevChg) / (lastChg + prevChg);
2685 if(tj.
Pts.size() < 3)
return;
2687 unsigned short atPt = tj.
EndPt[1];
2688 unsigned short maxPtsFit = 0;
2689 unsigned short firstGoodChgPullPt = USHRT_MAX;
2690 for(
unsigned short ipt = tj.
EndPt[0]; ipt < tj.
EndPt[1]; ++ipt) {
2691 auto& tp = tj.
Pts[ipt];
2692 if(tp.Chg == 0)
continue;
2693 if(tp.AveChg > 0 && firstGoodChgPullPt == USHRT_MAX) {
2696 if(tp.NTPsFit > maxPtsFit) {
2697 maxPtsFit = tp.NTPsFit;
2700 if(maxPtsFit > 20)
break;
2704 unsigned short firstPtFit = tj.
EndPt[0];
2705 unsigned short cnt = 0;
2706 for(
unsigned short ii = 1; ii < tj.
Pts.size(); ++ii) {
2707 if(ii > atPt)
break;
2708 unsigned short ipt = atPt - ii;
2709 if(tj.
Pts[ipt].Chg == 0)
continue;
2711 if(cnt == maxPtsFit) {
2717 bool needsRevProp = firstPtFit > 3;
2720 needsRevProp = (nPtsLeft > 5);
2724 myprt<<
"CB: firstPtFit "<<firstPtFit<<
" at "<<
PrintPos(slc, tj.
Pts[firstPtFit].Pos);
2726 myprt<<
" nPts with charge "<<nPtsLeft;
2727 myprt<<
" firstGoodChgPullPt "<<firstGoodChgPullPt;
2728 if(firstGoodChgPullPt != USHRT_MAX) myprt<<
" at "<<
PrintPos(slc,tj.
Pts[firstGoodChgPullPt]);
2729 myprt<<
" needsRevProp? "<<needsRevProp;
2732 if(!needsRevProp && firstGoodChgPullPt == USHRT_MAX) {
2744 unsigned int wire = std::nearbyint(tp.
Pos[0]);
2747 if(
tcc.
dbgStp && needsRevProp)
mf::LogVerbatim(
"TC")<<
"CB: Previous wire "<<wire<<
" is dead. Call ReversePropagate";
2748 if(!needsRevProp && firstGoodChgPullPt != USHRT_MAX) {
2754 unsigned short nused = 0;
2755 for(
auto iht : tp.
Hits)
if(slc.
slHits[iht].InTraj > 0) ++nused;
2757 needsRevProp =
true;
2759 mf::LogVerbatim(
"TC")<<
"CB: Found "<<tp.
Hits.size()-nused<<
" close unused hits found near EndPt[0] "<<
PrintPos(slc, tp)<<
". Call ReversePropagate";
2767 mf::LogVerbatim(
"TC")<<
"CB: maxPtsFit "<<maxPtsFit<<
" at point "<<atPt<<
" firstPtFit "<<firstPtFit<<
" Needs ReversePropagate? "<<needsRevProp;
2776 for(
unsigned short ipt = 0; ipt <= firstPtFit; ++ipt)
UnsetUsedHits(slc, tj.
Pts[ipt]);
2788 if(firstGoodChgPullPt != USHRT_MAX && firstGoodChgPullPt > atPt) atPt = firstGoodChgPullPt;
2802 if(npwc < 6)
return;
2807 unsigned short firstPt = tj.
EndPt[0];
2809 if(atPt == tj.
EndPt[0])
return;
2812 float maxDelta = 4 * tj.
Pts[tj.
EndPt[1]].DeltaRMS;
2815 float maxDeltaRMS = 0;
2816 for(
unsigned short ipt = atPt; ipt <= tj.
EndPt[1]; ++ipt) {
2817 if(tj.
Pts[ipt].DeltaRMS > maxDeltaRMS) maxDeltaRMS = tj.
Pts[ipt].DeltaRMS;
2819 maxDelta = 3 * maxDeltaRMS;
2822 mf::LogVerbatim(
"TC")<<
"FB: atPt "<<atPt<<
" firstPt "<<firstPt<<
" Stops at end 0? "<<
PrintEndFlag(tj, 0)<<
" start vertex "<<tj.
VtxID[0]<<
" maxDelta "<<maxDelta;
2827 bool maskedPts =
false;
2828 for(
unsigned short ii = 1; ii < tj.
Pts.size(); ++ii) {
2829 if(ii > atPt)
break;
2830 unsigned int ipt = atPt - ii;
2832 tp.
Dir = tj.
Pts[atPt].Dir;
2833 tp.
Ang = tj.
Pts[atPt].Ang;
2837 float dw = tp.
Pos[0] - tj.
Pts[atPt].Pos[0];
2838 if(tp.
Dir[0] != 0) tp.
Pos[1] = tj.
Pts[atPt].Pos[1] + dw * tp.
Dir[1] / tp.
Dir[0];
2840 tj.
Pts[ipt].DeltaRMS = tj.
Pts[atPt].DeltaRMS;
2841 tj.
Pts[ipt].NTPsFit = tj.
Pts[atPt].NTPsFit;
2842 tj.
Pts[ipt].FitChi = tj.
Pts[atPt].FitChi;
2843 tj.
Pts[ipt].AveChg = tj.
Pts[atPt].AveChg;
2846 bool maskThisPt = (tj.
Pts[ipt].Delta > maxDelta || badChg);
2853 myprt<<
" Point "<<
PrintPos(slc, tj.
Pts[ipt].Pos)<<
" Delta "<<tj.
Pts[ipt].Delta<<
" ChgPull "<<tj.
Pts[ipt].ChgPull<<
" maskThisPt? "<<maskThisPt;
2869 if(tj.
ID > 0)
return true;
2872 if(tj.
Pts.size() < 3)
return false;
2876 std::vector<int> tID;
2877 std::vector<unsigned short> tCnt;
2879 unsigned short hitCnt = 0;
2880 unsigned short nAvailable = 0;
2881 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
2882 for(
unsigned short ii = 0; ii < tj.
Pts[ipt].Hits.size(); ++ii) {
2884 if(tj.
Pts[ipt].UseHit[ii]) {
2888 unsigned int iht = tj.
Pts[ipt].Hits[ii];
2889 if(slc.
slHits[iht].InTraj > 0 && (
unsigned int)slc.
slHits[iht].InTraj <= slc.
tjs.size()) {
2890 int tjid = slc.
slHits[iht].InTraj;
2891 unsigned short indx;
2892 for(indx = 0; indx < tID.size(); ++indx)
if(tID[indx] == tjid)
break;
2893 if(indx == tID.size()) {
2894 tID.push_back(tjid);
2907 int oldTjID = INT_MAX;
2911 myprt<<
"IsGhost tj hits size cut "<<hitCnt<<
" tID_tCnt";
2912 for(
unsigned short ii = 0; ii < tCnt.size(); ++ii) myprt<<
" "<<tID[ii]<<
"_"<<tCnt[ii];
2913 myprt<<
"\nAvailable hits "<<nAvailable;
2916 for(
unsigned short ii = 0; ii < tCnt.size(); ++ii) {
2917 if(tCnt[ii] > hitCnt) {
2922 if(oldTjID == INT_MAX)
return false;
2923 int oldTjIndex = oldTjID - 1;
2927 if(oTj.
PDGCode == 13 && hitCnt < 0.1 * oTj.
Pts.size())
return false;
2932 int wire0 = INT_MAX;
2934 for(
auto& otp : oTj.
Pts) {
2935 int wire = std::nearbyint(otp.Pos[0]);
2936 if(wire < wire0) wire0 = wire;
2937 if(wire > wire1) wire1 = wire;
2940 int nwires = wire1 - wire0 + 1;
2941 std::vector<float> oTjPos1(nwires, -1);
2942 unsigned short nMissedWires = 0;
2943 for(
unsigned short ipt = oTj.
EndPt[0]; ipt <= oTj.
EndPt[1]; ++ipt) {
2944 if(oTj.
Pts[ipt].Chg == 0)
continue;
2945 int wire = std::nearbyint(oTj.
Pts[ipt].Pos[0]);
2946 int indx = wire - wire0;
2947 if(indx < 0 || indx > nwires - 1)
continue;
2948 oTjPos1[indx] = oTj.
Pts[ipt].Pos[1];
2952 unsigned short ngh = 0;
2954 unsigned short nghPlus = 0;
2956 unsigned short firstPtInoTj = USHRT_MAX;
2957 unsigned short lastPtInoTj = 0;
2959 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
2960 if(tj.
Pts[ipt].Chg > 0) {
2964 int wire = std::nearbyint(tj.
Pts[ipt].Pos[0]);
2965 int indx = wire - wire0;
2966 if(indx < 0 || indx > nwires - 1)
continue;
2967 if(oTjPos1[indx] > 0) {
2969 bool HitInoTj =
false;
2970 for(
unsigned short ii = 0; ii < tj.
Pts[ipt].Hits.size(); ++ii) {
2971 unsigned int iht = tj.
Pts[ipt].Hits[ii];
2972 if(slc.
slHits[iht].InTraj == oldTjID) HitInoTj =
true;
2977 if(tp.
Pos[1] > oTjPos1[indx]) ++nghPlus;
2978 if(firstPtInoTj == USHRT_MAX) firstPtInoTj = ipt;
2984 if(
tcc.
dbgStp)
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;
2986 if(ngh < 0.2 * nMissedWires)
return false;
2987 if(firstPtInoTj > lastPtInoTj)
return false;
2990 if(!(nghPlus > 0.8 * ngh || nghPlus < 0.2 * ngh) )
return false;
2992 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
" Trajectory is a ghost of "<<oldTjID<<
" first point in oTj "<<firstPtInoTj<<
" last point "<<lastPtInoTj;
2995 for(
unsigned short ipt = firstPtInoTj; ipt <= lastPtInoTj; ++ipt) {
2996 if(tj.
Pts[ipt].Chg == 0)
continue;
3002 for(
unsigned short ipt = lastPtInoTj; ipt <= tj.
EndPt[1]; ++ipt) {
3003 if(tj.
Pts[ipt].Chg > 0) ++ngh;
3007 for(
unsigned short ipt = lastPtInoTj; ipt <= tj.
EndPt[1]; ++ipt) {
3034 if(tHits.size() < 2)
return false;
3039 std::vector<unsigned int> hitsInMuliplet, nearbyHits;
3040 for(
auto iht : tHits) {
3043 for(
auto mht : hitsInMuliplet) {
3044 if(std::find(nearbyHits.begin(), nearbyHits.end(), mht) == nearbyHits.end()) {
3045 nearbyHits.push_back(mht);
3051 std::vector<unsigned int> tID, tCnt;
3052 for(
auto iht : nearbyHits) {
3053 if(slc.
slHits[iht].InTraj <= 0)
continue;
3054 unsigned int tid = slc.
slHits[iht].InTraj;
3055 unsigned short indx = 0;
3056 for(indx = 0; indx < tID.size(); ++indx)
if(tID[indx] == tid)
break;
3057 if(indx == tID.size()) {
3064 if(tCnt.empty())
return false;
3067 unsigned short tCut = 0.5 * tHits.size();
3072 myprt<<
"IsGhost tHits size "<<tHits.size()<<
" cut fraction "<<tCut<<
" tID_tCnt";
3073 for(
unsigned short ii = 0; ii < tCnt.size(); ++ii) myprt<<
" "<<tID[ii]<<
"_"<<tCnt[ii];
3076 for(
unsigned short ii = 0; ii < tCnt.size(); ++ii) {
3077 if(tCnt[ii] > tCut) {
3082 if(tid > (
int)slc.
tjs.size())
return false;
3087 for(
auto& tp : slc.
tjs[tid - 1].Pts) {
3088 for(
unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3089 unsigned int iht = tp.Hits[ii];
3090 if(slc.
slHits[iht].InTraj != 0)
continue;
3091 for(
unsigned short jj = 0; jj < tHits.size(); ++jj) {
3092 unsigned int tht = tHits[jj];
3093 if(tht != iht)
continue;
3094 tp.UseHit[ii] =
true;
3095 slc.
slHits[iht].InTraj = tid;
3110 if(slc.
tjs.size() < 2)
return;
3116 std::vector<TrajPoint> tjTP;
3117 for(
auto& tj : slc.
tjs) {
3118 if(tj.AlgMod[
kKilled])
continue;
3119 if(tj.CTP != inCTP)
continue;
3120 if(tj.Pts.size() < 10)
continue;
3121 if(tj.MCSMom < 100)
continue;
3123 if(tjtp.Chg < 0)
continue;
3124 tjTP.push_back(tjtp);
3126 if(tjTP.size() < 2)
return;
3130 myprt<<
"inside LastEndMerge slice "<<
slices.size()-1<<
" inCTP "<<inCTP<<
" tjTPs";
3131 for(
auto& tjtp : tjTP) myprt<<
" T"<<tjtp.Step;
3134 for(
unsigned short pt1 = 0; pt1 < tjTP.size() - 1; ++pt1) {
3135 auto& tp1 = tjTP[pt1];
3136 auto& tj1 = slc.
tjs[tp1.Step - 1];
3137 if(tj1.AlgMod[
kKilled])
continue;
3138 for(
unsigned short pt2 = pt1 + 1; pt2 < tjTP.size(); ++pt2) {
3139 auto& tp2 = tjTP[pt2];
3140 auto& tj2 = slc.
tjs[tp2.Step - 1];
3141 if(tj2.AlgMod[
kKilled])
continue;
3144 if(prt && dang < 0.5)
mf::LogVerbatim(
"TC")<<
" T"<<tj1.ID<<
" T"<<tj2.ID<<
" dang "<<dang;
3145 if(dang > 0.2)
continue;
3147 unsigned short ipt1, ipt2;
3148 float ip12 =
PointTrajDOCA(slc, tp1.Pos[0], tp1.Pos[1], tp2);
3149 float ip21 =
PointTrajDOCA(slc, tp2.Pos[0], tp2.Pos[1], tp1);
3151 if(ip12 > 15 && ip21 > 15)
continue;
3154 TrajTrajDOCA(slc, tj1, tj2, ipt1, ipt2, minSep,
false);
3155 if(minSep == 100)
continue;
3156 if(ipt1 >= tj1.Pts.size() || ipt2 >= tj2.Pts.size())
continue;
3157 float dwc =
DeadWireCount(slc, tj1.Pts[ipt1], tj2.Pts[ipt2]);
3160 if(minSep > 5)
continue;
3162 float sep10 =
PosSep(tj1.Pts[ipt1].Pos, tj1.Pts[tj1.EndPt[0]].Pos);
3163 float sep11 =
PosSep(tj1.Pts[ipt1].Pos, tj1.Pts[tj1.EndPt[1]].Pos);
3164 if(sep10 > 5 && sep11 > 5)
continue;
3165 unsigned short end1 = 0;
3166 if(sep11 < sep10) end1 = 1;
3167 float sep20 =
PosSep(tj2.Pts[ipt2].Pos, tj2.Pts[tj2.EndPt[0]].Pos);
3168 float sep21 =
PosSep(tj2.Pts[ipt2].Pos, tj2.Pts[tj2.EndPt[1]].Pos);
3169 if(sep20 > 5 && sep21 > 5)
continue;
3170 unsigned short end2 = 0;
3171 if(sep21 < sep20) end2 = 1;
3173 if(tj1.EndFlag[end1][
kAtKink] || tj2.EndFlag[end2][
kAtKink])
continue;
3176 myprt<<
"LEM: T"<<tj1.ID<<
"_"<<
PrintPos(slc, tp1);
3177 if(tj1.VtxID[end1] > 0) myprt<<
"->2V"<<tj1.VtxID[end1];
3178 myprt<<
" T"<<tj2.ID<<
"_"<<
PrintPos(slc, tp2);
3179 if(tj2.VtxID[end2] > 0) myprt<<
"->2V"<<tj2.VtxID[end2];
3181 myprt<<
" ip21 "<<ip21;
3182 myprt<<
" minSep "<<minSep;
3183 myprt<<
" end sep1 "<<sep10<<
" "<<sep11;
3184 myprt<<
" end sep2 "<<sep20<<
" "<<sep21;
3186 if(tj1.VtxID[end1] > 0) {
3187 auto& vx2 = slc.
vtxs[tj1.VtxID[end1] - 1];
3190 if(tj2.VtxID[end2] > 0 && tj2.VtxID[end2] != tj1.VtxID[end1]) {
3191 auto& vx2 = slc.
vtxs[tj2.VtxID[end2] - 1];
3195 tj1.EndFlag[end1][
kBragg] =
false;
3196 tj2.EndFlag[end2][
kBragg] =
false;
3197 unsigned int it1 = tj1.ID - 1;
3198 unsigned int it2 = tj2.ID - 1;
3201 auto& ntj = slc.
tjs[slc.
tjs.size() - 1];
3205 if(tjtp.Chg < 0)
continue;
3206 if(prt)
mf::LogVerbatim(
"TC")<<
" added T"<<ntj.ID<<
" to the merge list";
3207 tjTP.push_back(tjtp);
3231 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
3232 auto& tp = tj.
Pts[ipt];
3233 if(tp.Chg <= 0)
continue;
3234 tjtp.
Pos[0] += tp.Pos[0];
3235 tjtp.
Pos[1] += tp.Pos[1];
3236 tjtp.
Dir[1] += tp.Dir[1];
3242 double arg = 1 - tjtp.
Dir[1] * tjtp.
Dir[1];
3243 if(arg < 0) arg = 0;
3244 tjtp.
Dir[0] = sqrt(arg);
3245 tjtp.
Ang = atan2(tjtp.
Dir[1], tjtp.
Dir[0]);
3255 if(slc.
tjs.size() < 2)
return;
3259 if(prt)
mf::LogVerbatim(
"TC")<<
"inside EndMerge slice "<<
slices.size()-1<<
" inCTP "<<inCTP<<
" nTjs "<<slc.
tjs.size()<<
" lastPass? "<<lastPass;
3262 short tccStepDir = 1;
3264 for(
auto& tj : slc.
tjs) {
3265 if(tj.AlgMod[
kKilled])
continue;
3266 if(tj.CTP != inCTP)
continue;
3267 if(tj.StepDir != tccStepDir)
ReverseTraj(slc, tj);
3273 std::vector<int> tjlist(2);
3279 bool iterate =
true;
3282 for(
unsigned int it1 = 0; it1 < slc.
tjs.size(); ++it1) {
3283 auto& tj1 = slc.
tjs[it1];
3284 if(tj1.AlgMod[
kKilled])
continue;
3285 if(tj1.CTP != inCTP)
continue;
3287 if(tj1.PDGCode == 111)
continue;
3288 for(
unsigned short end1 = 0; end1 < 2; ++end1) {
3290 if(tj1.VtxID[end1] > 0)
continue;
3292 TrajPoint tp1 = tj1.Pts[tj1.EndPt[end1]];
3294 if(lastPass && tp1.
NTPsFit > 3) {
3296 auto ttj = slc.
tjs[it1];
3297 auto& lastTP = ttj.Pts[ttj.EndPt[end1]];
3301 tp1 = ttj.Pts[ttj.EndPt[end1]];
3305 if(isVLA) bestFOM = 20;
3307 unsigned int imbest = UINT_MAX;
3308 for(
unsigned int it2 = 0; it2 < slc.
tjs.size(); ++it2) {
3309 if(it1 == it2)
continue;
3310 auto& tj2 = slc.
tjs[it2];
3312 if(tj1.StepDir != tj2.StepDir)
continue;
3313 if(tj2.AlgMod[
kKilled])
continue;
3314 if(tj2.CTP != inCTP)
continue;
3316 if(tj2.PDGCode == 111)
continue;
3318 if(olf > 0.25)
continue;
3319 unsigned short end2 = 1 - end1;
3321 if(tj2.VtxID[end2] > 0)
continue;
3322 TrajPoint& tp2 = tj2.Pts[tj2.EndPt[end2]];
3323 TrajPoint& tp2OtherEnd = tj2.Pts[tj2.EndPt[end1]];
3327 if(tj1.StepDir > 0) {
3328 if(tp2.
Pos[0] < tp1.
Pos[0] - 2)
continue;
3330 if(tp2.
Pos[0] > tp1.
Pos[0] + 2)
continue;
3342 unsigned short ipt1, ipt2;
3349 float fom = dang * doca;
3357 if(imbest == UINT_MAX)
continue;
3360 unsigned int it2 = imbest;
3361 auto& tj2 = slc.
tjs[imbest];
3362 unsigned short end2 = 1 - end1;
3363 bool loMCSMom = (tj1.MCSMom + tj2.MCSMom) < 150;
3365 if(tj1.Pts.size() > 50 && tj1.MCSMom > 100) {
3367 tp1.
Ang = tj1.Pts[tj1.EndPt[0] + 2].Ang;
3369 tp1.
Ang = tj1.Pts[tj1.EndPt[1] - 2].Ang;
3371 }
else if(loMCSMom) {
3373 unsigned short pt1, pt2;
3385 TrajPoint tp2 = tj2.Pts[tj2.EndPt[end2]];
3386 if(tj2.Pts.size() > 50 && tj2.MCSMom > 100) {
3388 tp2.
Ang = tj2.Pts[tj2.EndPt[0] + 2].Ang;
3390 tp2.
Ang = tj2.Pts[tj2.EndPt[1] - 2].Ang;
3392 }
else if(loMCSMom) {
3394 unsigned short pt1, pt2;
3415 if(len1 < len2 && sep > 3 * len1)
continue;
3416 if(len2 < len1 && sep > 3 * len2)
continue;
3425 kinkSig =
KinkSignificance(slc, tj1, end1, tj2, end2, nPtsFit, useChg, prt);
3428 if(isVLA) docaCut = 15;
3445 bool doMerge = bestDOCA < docaCut && dang < dangCut;
3446 bool showerTjs = tj1.PDGCode == 11 || tj2.PDGCode == 11;
3447 bool hiMCSMom = tj1.MCSMom > 200 || tj2.MCSMom > 200;
3449 if(doMerge && !showerTjs && hiMCSMom && chgPull >
tcc.
chargeCuts[0] && !isVLA) doMerge =
false;
3451 if(!doMerge && tj1.MCSMom > 900 && tj2.MCSMom > 900 && dang < 0.1 && bestDOCA < docaCut) doMerge =
true;
3454 if(doMerge && chgPull > 2 * chgPullCut) doMerge =
false;
3461 auto& tp1OtherEnd = tj1.Pts[tj1.EndPt[1 - end1]];
3462 auto& tp2OtherEnd = tj2.Pts[tj2.EndPt[1 - end2]];
3463 float nwires =
std::abs(tp1OtherEnd.Pos[0] - tp2OtherEnd.Pos[0]);
3464 if(nwires == 0) nwires = 1;
3465 float hitFrac = npwc /
nwires;
3470 if(sep > len1) doMerge =
false;
3472 if(sep > len2) doMerge =
false;
3474 if(prt)
mf::LogVerbatim(
"TC")<<
" merge check sep "<<sep<<
" len1 "<<len1<<
" len2 "<<len2<<
" dead wire count "<<dwc<<
" Merge? "<<doMerge;
3479 tjlist[0] = slc.
tjs[it1].ID;
3480 tjlist[1] = slc.
tjs[it2].ID;
3482 if(doMerge && bestDOCA > 1 && chgFrac < chgFracCut) doMerge =
false;
3485 float momAsym =
std::abs(tj1.MCSMom - tj2.MCSMom) / (
float)(tj1.MCSMom + tj2.MCSMom);
3486 if(doMerge && momAsym >
tcc.
vtx2DCuts[9]) doMerge =
false;
3487 if(doMerge && (tj1.EndFlag[end1][
kAtKink] || tj2.EndFlag[end2][
kAtKink])) {
3489 if(len1 < 40 && len2 < 40) doMerge =
false;
3491 if(tj1.EndFlag[end1][kAtKink] && tj2.EndFlag[1-end2][
kBragg]) doMerge =
false;
3492 if(tj1.EndFlag[1-end1][kBragg] && tj2.EndFlag[end2][kAtKink]) doMerge =
false;
3501 doVtx = (kinkSig > 0.5 *
tcc.
kinkCuts[1] && sep < 2);
3506 myprt<<
" EM: T"<<slc.
tjs[it1].ID<<
"_"<<end1<<
" - T"<<slc.
tjs[it2].ID<<
"_"<<end2<<
" tp1-tp2 "<<
PrintPos(slc, tp1)<<
"-"<<
PrintPos(slc, tp2);
3509 myprt<<
" cut "<<docaCut<<
" isVLA? "<<isVLA;
3513 myprt<<
" momAsym "<<momAsym;
3515 myprt<<
" doMerge? "<<doMerge;
3516 myprt<<
" doVtx? "<<doVtx;
3519 if(bestDOCA > docaCut)
continue;
3523 bool didMerge =
false;
3531 tj1.AlgMod[
kMerge] =
true;
3532 tj2.AlgMod[
kMerge] =
true;
3541 aVtx.
CTP = slc.
tjs[it1].CTP;
3542 aVtx.
ID = slc.
vtxs.size() + 1;
3548 bool fix2V = (
PosSep(tp1.
Pos, tp2.
Pos) < 3 || dang < 0.1);
3550 aVtx.
Pos[0] = 0.5 * (tp1.
Pos[0] + tp2.
Pos[0]);
3551 aVtx.
Pos[1] = 0.5 * (tp1.
Pos[1] + tp2.
Pos[1]);
3557 bool tj1Short = (slc.
tjs[it1].EndPt[1] - slc.
tjs[it1].EndPt[0] < maxShortTjLen);
3558 bool tj2Short = (slc.
tjs[it2].EndPt[1] - slc.
tjs[it2].EndPt[0] < maxShortTjLen);
3561 float dw = aVtx.
Pos[0] - tp1.
Pos[0];
3562 if(
std::abs(dw) > sepCut)
continue;
3563 float dt = aVtx.
Pos[1] - tp1.
Pos[1];
3564 if(
std::abs(dt) > sepCut)
continue;
3565 dw = aVtx.
Pos[0] - tp2.
Pos[0];
3566 if(
std::abs(dw) > sepCut)
continue;
3567 dt = aVtx.
Pos[1] - tp2.
Pos[1];
3568 if(
std::abs(dt) > sepCut)
continue;
3571 if(tj1Short && len1 > 4) {
3575 if(tj2Short && len2 > 4) {
3580 if(aVtx.
Pos[0] < tp1.
Pos[0] && aVtx.
Pos[0] < tp2.
Pos[0]) {
3584 if(aVtx.
Pos[0] > tp1.
Pos[0] && aVtx.
Pos[0] > tp2.
Pos[0]) {
3590 slc.
tjs[it1].VtxID[end1] = aVtx.
ID;
3591 slc.
tjs[it2].VtxID[end2] = aVtx.
ID;
3594 slc.
tjs[it1].VtxID[end1] = 0;
3595 slc.
tjs[it2].VtxID[end2] = 0;
3600 aVtx.
Pass = slc.
tjs[it1].Pass;
3601 aVtx.
Topo = end1 + end2;
3602 tj1.AlgMod[
kMerge] =
true;
3603 tj2.AlgMod[
kMerge] =
true;
3607 auto& newVx = slc.
vtxs[slc.
vtxs.size() - 1];
3613 auto& newVx2 = slc.
vtxs[slc.
vtxs.size() - 1];
3617 myprt<<
" Bad vertex: Bad score? "<<(newVx2.Score <
tcc.
vtx2DCuts[7]);
3621 slc.
tjs[it1].VtxID[end1] = 0;
3622 slc.
tjs[it2].VtxID[end2] = 0;
3624 bool didMerge =
false;
3632 tj1.AlgMod[
kMerge] =
true;
3633 tj1.AlgMod[
kMerge] =
true;
3641 if(tj1.AlgMod[
kKilled])
break;
3657 if(tj.
Pts.size() < 3) {
3658 mf::LogError(
"TC")<<
"MaskTrajEndPoints: Trajectory ID "<<tj.
ID<<
" too short to mask hits ";
3661 if(nPts > tj.
Pts.size() - 2) {
3662 mf::LogError(
"TC")<<
"MaskTrajEndPoints: Trying to mask too many points "<<nPts<<
" Pts.size "<<tj.
Pts.size();
3667 unsigned short lastGoodPt = USHRT_MAX ;
3672 if(lastGoodPt == USHRT_MAX)
return;
3673 tj.
EndPt[1] = lastGoodPt;
3676 for(
unsigned short ii = 0; ii < tj.
Pts.size(); ++ii) {
3677 unsigned short ipt = tj.
Pts.size() - 1 - ii;
3678 if (ipt==lastGoodPt)
break;
3681 tj.
Pts[ipt].Dir = tj.
Pts[lastGoodPt].Dir;
3682 if(tj.
Pts[lastGoodPt].AngleCode == 2) {
3685 tj.
Pts[ipt].Pos[0] = tj.
Pts[lastGoodPt].Pos[0] + path * tj.
Pts[ipt].Dir[0];
3686 tj.
Pts[ipt].Pos[1] = tj.
Pts[lastGoodPt].Pos[1] + path * tj.
Pts[ipt].Dir[1];
3689 float dw = tj.
Pts[ipt].Pos[0] - tj.
Pts[lastGoodPt].Pos[0];
3691 float newpos = tj.
Pts[lastGoodPt].Pos[1] + dw * tj.
Pts[ipt].Dir[1] / tj.
Pts[ipt].Dir[0];
3692 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
"MTEP: ipt "<<ipt<<
" Pos[0] "<<tj.
Pts[ipt].Pos[0]<<
". Move Pos[1] from "<<tj.
Pts[ipt].Pos[1]<<
" to "<<newpos;
3693 tj.
Pts[ipt].Pos[1] = tj.
Pts[lastGoodPt].Pos[1] + dw * tj.
Pts[ipt].Dir[1] / tj.
Pts[ipt].Dir[0];
3720 if(tj.
Pts[tj.
EndPt[0]].AngleCode == 2 || tj.
Pts[tj.
EndPt[1]].AngleCode == 2)
return;
3723 if(tj.
Pts.size() < 6)
return;
3732 for(
unsigned short end = 0;
end < 2; ++
end) {
3736 if(endTP.Hits.size() > 2)
continue;
3741 unsigned short hiPt = 0;
3743 for(
unsigned short ii = 0; ii < 5; ++ii) {
3745 if(ipt < tj.
EndPt[0] || ipt > tj.
EndPt[1])
break;
3755 short dpt0 = hiPt - tj.
EndPt[0];
3756 short dpt1 = tj.
EndPt[1] - hiPt;
3757 if(
end == 0 && dpt1 <= dpt0)
continue;
3758 if(
end == 1 && dpt0 <= dpt1)
continue;
3759 if(prt)
mf::LogVerbatim(
"TC")<<
" end "<<
end<<
" wire0 "<<wire0<<
" Chg "<<big<<
" hiPt "<<hiPt;
3760 float prevChg = big;
3764 float chgErr, chiDOF;
3766 Fit2D(0, inPt, chgErr, outVec, outVecErr, chiDOF);
3767 unsigned short cnt = 0;
3768 for(
unsigned short ii = 0; ii < tj.
Pts.size(); ++ii) {
3769 short ipt = hiPt + ii *
dir;
3770 if(ipt < tj.
EndPt[0] || ipt > tj.
EndPt[1])
break;
3772 if(tp.
Chg == 0)
continue;
3774 if(tp.
Chg > 1.5 * prevChg)
continue;
3780 chgErr = 0.2 * tp.
Chg;
3781 if(!
Fit2D(2, inPt, chgErr, outVec, outVecErr, chiDOF))
break;
3783 if(cnt == nPtsToCheck)
break;
3785 if(cnt < nPtsToCheck)
continue;
3787 if(!
Fit2D(-1, inPt, chgErr, outVec, outVecErr, chiDOF))
continue;
3789 if(chiDOF > 500)
continue;
3792 outVec[1] = -outVec[1];
3800 if(prt)
mf::LogVerbatim(
"TC")<<
" end "<<
end<<
" fit chidof "<<chiDOF<<
" slope "<<outVec[1]<<
" +/- "<<outVecErr[1]<<
" stopping";
3802 if(prt)
mf::LogVerbatim(
"TC")<<
" end "<<
end<<
" fit chidof "<<chiDOF<<
" slope "<<outVec[1]<<
" +/- "<<outVecErr[1]<<
" Not stopping";
3817 unsigned short nmichelhits = 0;
3819 unsigned short nbragghits = 0;
3822 bool isfirsthit =
true;
3823 unsigned short braggpeak = 0;
3825 for(
unsigned short ii = 0; ii < tj.
Pts.size(); ++ii) {
3826 if (ii>tj.
EndPt[1])
continue;
3827 unsigned short ipt = tj.
EndPt[1] - ii;
3828 if (tj.
Pts[ipt].Chg>0){
3831 if (tj.
Pts[ipt].ChgPull<0){
3836 if (tj.
Pts[ipt].ChgPull<0&&nmichelhits&&!nbragghits){
3842 lastChg = tj.
Pts[ipt].Chg;
3845 else if (tj.
Pts[ipt].Chg<lastChg){
3847 lastChg = tj.
Pts[ipt].Chg;
3854 if(prt)
mf::LogVerbatim(
"TC")<<
"ChkMichel Michel hits: "<<nmichelhits<<
" Bragg peak hits: "<<nbragghits;
3855 if (nmichelhits>0&&nbragghits>2){
3856 lastGoodPt = braggpeak;
3871 if(tHits.size() < 2)
return false;
3875 for(
unsigned short ii = 0; ii < tHits.size(); ++ii) {
3881 if(prt) std::cout<<
"MakeJunkTraj found debug hit\n";
3888 if(!
StartTraj(slc, work, tHits[0], tHits[tHits.size()-1],
pass))
return false;
3890 work.
Pts.resize(tHits.size());
3892 for(
unsigned short ii = 0; ii < tHits.size(); ++ii) {
3893 auto& tp = work.
Pts[ii];
3894 unsigned int iht = tHits[ii];
3897 if(tp.CTP != work.
CTP)
return false;
3898 tp.Hits.push_back(iht);
3899 tp.UseHit[0] =
true;
3902 tp.HitPos[0] =
hit.WireID().Wire;
3904 tp.HitPosErr2 = 100;
3905 tp.Chg =
hit.Integral();
3907 tp.NTPsFit = tHits.size();
3912 work.
EndPt[1] = tHits.size() - 1;
3915 auto& lastTP = work.
Pts.back();
3920 for(
auto& tp : work.
Pts) {
3924 sum2 += at[1] * at[1];
3928 if(tp.Step != lastTP.Step) {
3929 tp.FitChi = lastTP.FitChi;
3930 tp.Dir = lastTP.Dir;
3931 tp.Ang = lastTP.Ang;
3932 tp.Pos[0] = lastTP.Pos[0] + at[0] * lastTP.Dir[0];
3933 tp.Pos[1] = lastTP.Pos[1] + at[0] * lastTP.Dir[1];
3936 double npts = tHits.size();
3938 double arg = sum2 - npts * sum * sum;
3939 if(arg <= 0)
return false;
3940 float rms = sqrt(arg) / (npts - 1);
3942 float transCut = sum + 3 *
rms;
3943 std::vector<SortEntry> sortVec;
3947 for(
auto& tp : work.
Pts) {
3954 sortVec.push_back(se);
3958 if(sortVec.size() < 3)
return false;
3960 std::vector<TrajPoint> ntps(sortVec.size());
3961 for(
unsigned short ipt = 0; ipt < sortVec.size(); ++ipt) ntps[ipt] = work.
Pts[sortVec[ipt].index];
3963 sum = work.
TotChg / (
double)ntps.size();
3965 work.
EndPt[1] = work.
Pts.size() - 1;
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
void Forecast(TCSlice &slc, const Trajectory &tj)
float AveChg
Calculated using ALL hits.
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< Trajectory > tjs
vector of all trajectories in each plane
void StepAway(TCSlice &slc, Trajectory &tj)
bool MaskedHitsOK(TCSlice &slc, Trajectory &tj)
void SetEndPoints(Trajectory &tj)
void UpdateTraj(TCSlice &slc, Trajectory &tj)
void FitPar(const TCSlice &slc, const Trajectory &tj, unsigned short originPt, unsigned short npts, short fitDir, ParFit &pFit, unsigned short usePar)
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
std::vector< float > kinkCuts
kink finder algorithm
bool IsGhost(TCSlice &slc, Trajectory &tj)
struct of temporary 2D vertices (end points)
std::vector< unsigned int > PutTrajHitsInVector(const Trajectory &tj, HitStatus_t hitRequest)
CTP_t CTP
Cryostat, TPC, Plane code.
double rms(sqlite3 *db, std::string const &table_name, std::string const &column_name)
std::vector< float > maxPos0
std::vector< unsigned short > minPtsFit
Reconstruct in several passes.
bool SignalAtTp(TrajPoint &tp)
bool FitVertex(TCSlice &slc, VtxStore &vx, bool prt)
std::vector< float > qualityCuts
Min points/wire, min consecutive pts after a gap.
void SetPDGCode(TCSlice &slc, unsigned short itj)
void AddHits(TCSlice &slc, Trajectory &tj, unsigned short ipt, bool &sigOK)
vertex position fixed manually - no fitting done
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
void PrintTP(std::string someText, const TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, const TrajPoint &tp)
std::vector< std::vector< std::pair< unsigned int, unsigned int > > > wireHitRange
The data type to uniquely identify a Plane.
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
std::vector< unsigned int > Hits
step from US -> DS (true) or DS -> US (false)
std::string PrintEndFlag(const PFPStruct &pfp, unsigned short end)
bool StopShort(TCSlice &slc, Trajectory &tj, bool prt)
void SetStrategy(TCSlice &slc, Trajectory &tj)
bool StoreTraj(TCSlice &slc, Trajectory &tj)
float TotChg
Total including an estimate for dead wires.
short MCSMom
Normalized RMS using ALL hits. Assume it is 50% to start.
void FillGaps(TCSlice &slc, Trajectory &tj)
float HitTimeErr(const TCSlice &slc, unsigned int iht)
void ChkBegin(TCSlice &slc, Trajectory &tj)
float maxWireSkipWithSignal
max number of wires to skip with a signal on them
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
void FindUseHits(TCSlice &slc, Trajectory &tj, unsigned short ipt, float maxDelta, bool useChg)
void ChkChgAsymmetry(TCSlice &slc, Trajectory &tj, bool prt)
float ExpectedHitsRMS(TCSlice &slc, const TrajPoint &tp)
float TrajPointSeparation(const TrajPoint &tp1, const TrajPoint &tp2)
void SetAngleCode(TrajPoint &tp)
bool MakeJunkTraj(TCSlice &slc, std::vector< unsigned int > tHits)
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
bool dbgSlc
debug only in the user-defined slice? default is all slices
bool StartTraj(TCSlice &slc, Trajectory &tj, unsigned int fromhit, unsigned int tohit, unsigned short pass)
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
std::vector< unsigned int > lastWire
the last wire with a hit
bool LongPulseHit(const recob::Hit &hit)
bool IsGood
set false if there is a failure or the Tj fails quality cuts
bool StoreVertex(TCSlice &slc, VtxStore &vx)
bool doForecast
See TCMode_t above.
Q_EXPORT QTSManip setprecision(int p)
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
unsigned short Pass
the pass on which it was created
int TDCtick_t
Type representing a TDC tick.
TrajPoint CreateTPFromTj(TCSlice &slc, const Trajectory &tj)
std::vector< unsigned short > maxAngleCode
max allowed angle code for each pass
float OverlapFraction(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2)
float projectionErrFactor
float HitsRMSTime(const TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
unsigned int Hit
set to the hit index in evt.allHits if a Plane:Wire:Tick match is found
bool CompatibleMerge(const TCSlice &slc, std::vector< int > &tjIDs, bool prt)
const std::vector< std::string > StrategyBitNames
float HitsTimeErr2(const TCSlice &slc, const std::vector< unsigned int > &hitVec)
float HitsRMSTick(const TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
std::array< float, 2 > Point2_t
std::vector< float > maxPos1
float unitsPerTick
scale factor from Tick to WSE equivalent units
use the slowing-down strategy
bool TrajIsClean(TCSlice &slc, Trajectory &tj, bool prt)
std::vector< short > minMCSMom
Min MCSMom for each pass.
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
TP is near a hit in the srcHit collection but no allHit hit exists (DUNE disambiguation error) ...
CTP_t CTP
Cryostat, TPC, Plane code.
void CheckStiffEl(TCSlice &slc, Trajectory &tj)
void GetHitMultiplet(const TCSlice &slc, unsigned int theHit, std::vector< unsigned int > &hitsInMultiplet, bool useLongPulseHits)
std::vector< float > aveHitRMS
average RMS of an isolated hit
std::vector< TrajPoint > Pts
Trajectory points.
float KinkSignificance(TCSlice &slc, Trajectory &tj1, unsigned short end1, Trajectory &tj2, unsigned short end2, unsigned short nPtsFit, bool useChg, bool prt)
std::vector< std::vector< bool > > goodWire
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
std::vector< unsigned int > FindCloseHits(const TCSlice &slc, std::array< int, 2 > const &wireWindow, Point2_t const &timeWindow, const unsigned short plane, HitStatus_t hitRequest, bool usePeakTime, bool &hitsNear)
std::vector< VtxStore > vtxs
2D vertices
std::array< unsigned short, 2 > EndPt
First and last point in the trajectory that has charge.
unsigned short PDGCode
shower-like or track-like {default is track-like}
void TagJunkTj(TCSlice &slc, Trajectory &tj, bool prt)
short StartEnd
The starting end (-1 = don't know)
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
void FitTraj(TCSlice &slc, Trajectory &tj)
std::string PrintHit(const TCHit &tch)
bool Fit2D(short mode, Point2_t inPt, float &inPtErr, Vector2_t &outVec, Vector2_t &outVecErr, float &chiDOF)
std::vector< unsigned short > minPts
min number of Pts required to make a trajectory
static int max(int a, int b)
PlaneID_t Plane
Index of the plane within its TPC.
void FixBegin(TCSlice &slc, Trajectory &tj, unsigned short atPt)
std::array< double, 2 > Vector2_t
Definition of data types for geometry description.
void ReverseTraj(TCSlice &slc, Trajectory &tj)
unsigned short NumHitsInTP(const TrajPoint &tp, HitStatus_t hitRequest)
void TrimEndPts(std::string fcnLabel, TCSlice &slc, Trajectory &tj, const std::vector< float > &fQualityCuts, bool prt)
void err(const char *fmt,...)
std::vector< unsigned int > firstWire
the first wire with a hit
int ID
ID that is local to one slice.
std::vector< TCSlice > slices
std::array< unsigned short, 2 > VtxID
ID of 2D vertex.
Detector simulation of raw signals on wires.
void UpdateStiffEl(TCSlice &slc, Trajectory &tj)
Q_EXPORT QTSManip setw(int w)
void ChkStop(TCSlice &slc, Trajectory &tj)
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
std::bitset< 16 > modes
number of points to find AveChg
std::vector< TCHit > slHits
std::vector< float > chargeCuts
bool StopIfBadFits(TCSlice &slc, Trajectory &tj)
bool MergeAndStore(TCSlice &slc, unsigned int itj1, unsigned int itj2, bool doPrt)
void MaskBadTPs(TCSlice &slc, Trajectory &tj, float const &maxChi)
std::bitset< 16 > Stat
Vertex status bits using kVtxBit_t.
std::vector< TrajPoint > seeds
float maxWireSkipNoSignal
max number of wires to skip w/o a signal on them
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
void CheckTraj(TCSlice &slc, Trajectory &tj)
Declaration of signal hit object.
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
std::vector< TjForecast > tjfs
void AddLAHits(TCSlice &slc, Trajectory &tj, unsigned short ipt, bool &sigOK)
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
void CheckHiMultUnusedHits(TCSlice &slc, Trajectory &tj)
short StepDir
-1 = going US (-> small wire#), 1 = going DS (-> large wire#)
float MaxHitDelta(TCSlice &slc, Trajectory &tj)
float TrajLength(const Trajectory &tj)
std::bitset< 128 > AlgMod
Bit set if algorithm AlgBit_t modifed the trajectory.
static unsigned int reverse(QString &chars, unsigned char *level, unsigned int a, unsigned int b)
void LastEndMerge(TCSlice &slc, CTP_t inCTP)
std::vector< short > muonTag
geo::PlaneID DecodeCTP(CTP_t CTP)
bool GottaKink(TCSlice &slc, Trajectory &tj, bool doTrim)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
void TrimHiChgEndPts(TCSlice &slc, Trajectory &tj, bool prt)
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
std::bitset< 8 > Environment
std::vector< recob::Hit > const * allHits
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
std::vector< unsigned int > nWires
use the stiff electron strategy
std::array< std::bitset< 8 >, 2 > EndFlag
std::vector< float > chkStopCuts
Bragg peak finder configuration.
void EndMerge(TCSlice &slc, CTP_t inCTP, bool lastPass)
void SetVx2Score(TCSlice &slc)
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
std::bitset< 8 > Strategy
bool NearbySrcHit(geo::PlaneID plnID, unsigned int wire, float loTick, float hiTick)
bool SignalBetween(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction)
float multHitSep
preferentially "merge" hits with < this separation
void MoveTPToWire(TrajPoint &tp, float wire)
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
void MaskTrajEndPoints(TCSlice &slc, Trajectory &tj, unsigned short nPts)
void UpdateDeltaRMS(TCSlice &slc, Trajectory &tj)
void ChkStopEndPts(TCSlice &slc, Trajectory &tj, bool prt)
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
void ReversePropagate(TCSlice &slc, Trajectory &tj)
bool NeedsUpdate
Set true when the Tj needs to be updated.
void CheckHiMultEndHits(TCSlice &slc, Trajectory &tj)
float TPHitsRMSTick(const TCSlice &slc, const TrajPoint &tp, HitStatus_t hitRequest)
CTP_t CTP
set to an invalid CTP
unsigned short AngleRange(TrajPoint const &tp)
use the stiff muon strategy
bool valsDecreasing(const SortEntry &c1, const SortEntry &c2)
bool HasDuplicateHits(const TCSlice &slc, Trajectory const &tj, bool prt)
bool ChkMichel(TCSlice &slc, Trajectory &tj, unsigned short &lastGoodPt)