24 if(tj.
Pts.empty())
return;
28 unsigned short lastPtWithUsedHits = tj.
EndPt[1];
30 unsigned short lastPt = lastPtWithUsedHits;
35 ltp.
Pos = tj.
Pts[lastPt].Pos;
36 ltp.
Dir = tj.
Pts[lastPt].Dir;
44 unsigned short nMissedSteps = 0;
50 tjfs[0].nextForecastUpdate = 6;
52 for(
unsigned short step = 1; step < 10000; ++step) {
62 lastPt = tj.
Pts.size() - 1;
68 for(
unsigned short iwt = 0; iwt < 2; ++iwt) ltp.
Pos[iwt] += ltp.
Dir[iwt] * stepSize;
71 if(ivx != USHRT_MAX) {
82 myprt<<
"StepAway "<<step<<
" Pos "<<tp.
Pos[0]<<
" "<<tp.
Pos[1]<<
" Dir "<<tp.
Dir[0]<<
" "<<tp.
Dir[1]<<
" stepSize "<<stepSize<<
" AngCode "<<tp.
AngleCode<<
" Strategy";
97 lastPt = tj.
Pts.size() - 1;
100 AddHits(slc, tj, lastPt, sigOK);
105 if(tj.
Pts[lastPt].Hits.empty()) {
108 if(tj.
Pts[lastPt].AngleCode == 0 && lastPt == 2)
return;
116 if(tj.
Pts[lastPt].AngleCode > 0 && nMissedSteps > 4 && !
SignalAtTp(slc, ltp)) {
121 unsigned short lastPtWithHits = lastPt - 1;
124 float nMissedWires = tps * std::abs(ltp.
Dir[0]) - dwc;
127 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
" StepAway: no signal at ltp "<<
PrintPos(slc, ltp)<<
" nMissedWires "<<std::fixed<<std::setprecision(1)<<nMissedWires<<
" dead wire count "<<dwc<<
" maxWireSkip "<<maxWireSkip<<
" tj.PDGCode "<<tj.
PDGCode;
128 if(nMissedWires > maxWireSkip) {
132 if(tj.
EndPt[1] < tj.
Pts.size() - 1 && tj.
Pts[tj.
EndPt[1]+1].Hits.size() == 1) {
133 unsigned short lastLonelyPoint = tj.
EndPt[1] + 1;
134 unsigned int iht = tj.
Pts[lastLonelyPoint].Hits[0];
135 if(slc.
slHits[iht].InTraj == 0 && tj.
Pts[lastLonelyPoint].Delta < 3 * tj.
Pts[lastLonelyPoint].DeltaRMS) {
137 tj.
Pts[lastLonelyPoint].UseHit[0] =
true;
154 if(lastPt > 0 &&
PosSep2(tj.
Pts[lastPt].Pos, tj.
Pts[lastPt-1].Pos) < 0.1)
return;
161 if(tj.
Pts[lastPt].Chg == 0) {
166 float nMissedWires = tps * std::abs(ltp.
Dir[0]) - dwc;
167 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;
187 if(tj.
Pts.size() == 3) {
197 if(dang > 0.5) badTj =
false;
200 if(!badTj && tj.
Pts[2].Delta > 2) badTj =
true;
208 ltp.
Pos = tj.
Pts[lastPt].Pos;
209 ltp.
Dir = tj.
Pts[lastPt].Dir;
238 unsigned short killPts = 0;
240 bool keepGoing =
true;
250 if(killPts == 0 && tj.
Pts[lastPt].FitChi >
tcc.
maxChi && useMaxChiCut) {
272 unsigned int onWire = (float)(std::nearbyint(tj.
Pts[lastPt].Pos[0]));
273 float nSteps = (float)(step - tj.
Pts[lastPt - killPts].Step);
274 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
"TRP killing "<<killPts<<
" after "<<nSteps<<
" steps from prev TP. Current tp.Pos "<<tp.
Pos[0]<<
" "<<tp.
Pos[1];
276 tj.
Pts[lastPt].Pos[0] += nSteps * tj.
Pts[lastPt].Dir[0];
277 tj.
Pts[lastPt].Pos[1] += nSteps * tj.
Pts[lastPt].Dir[1];
278 if(tj.
Pts[lastPt].AngleCode == 0) {
280 float dw = onWire - tj.
Pts[lastPt].Pos[0];
281 tj.
Pts[lastPt].Pos[0] = onWire;
282 tj.
Pts[lastPt].Pos[1] += dw * tj.
Pts[lastPt].Dir[1] / tj.
Pts[lastPt].Dir[0];
287 ltp.
Pos = tj.
Pts[lastPt].Pos;
288 ltp.
Dir = tj.
Pts[lastPt].Dir;
290 if(!keepGoing)
break;
306 if(
tjfs.empty())
return;
318 bool tkLike = (tjf.outlook < 1.5);
320 bool shLike = (tjf.outlook > 2 && tjf.chgSlope > 0);
322 if(!shLike) shLike = tjf.showerLikeFraction > 0.4;
324 if(tj.
MCSMom > 0) momRat = (float)tjf.MCSMom / (
float)tj.
MCSMom;
327 myprt<<
"SetStrategy: npwc "<<npwc<<
" outlook "<<tjf.outlook;
328 myprt<<
" tj MCSMom "<<tj.
MCSMom<<
" forecast MCSMom "<<tjf.MCSMom;
329 myprt<<
" momRat "<<std::fixed<<std::setprecision(2)<<momRat;
330 myprt<<
" tkLike? "<<tkLike<<
" showerLike? "<<shLike;
331 myprt<<
" leavesBeforeEnd? "<<tjf.leavesBeforeEnd<<
" endBraggPeak? "<<tjf.endBraggPeak;
333 if(tjf.outlook < 0)
return;
335 if(tkLike && tj.
MCSMom > 200 && tjf.MCSMom > 800 && tjf.nextForecastUpdate > 50 && tjf.chgFitChiDOF < 10) {
342 if(notStiff && !shLike && tj.
MCSMom < 100 && tjf.MCSMom < 100) {
349 if(notStiff && tkLike && tj.
MCSMom < 200 && momRat < 0.7) {
356 if(!tjf.leavesBeforeEnd && tjf.endBraggPeak) {
363 if(npwc > 100 && tkLike && tjf.leavesBeforeEnd) {
367 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
"SetStrategy: Long track-like wandered out of forecast envelope. Reduce NTPsFit to "<<lastTP.NTPsFit;
371 if(tkLike && tjf.MCSMom > 600 && (tjf.foundShower || tjf.chgFitChiDOF > 20)) {
372 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
"SetStrategy: high MCSMom "<<tjf.MCSMom<<
" and a shower ahead. Use the StiffEl strategy";
388 if(tkLike && tjf.MCSMom < 100 && !tjf.leavesBeforeEnd) {
390 float chgSlope, chgSlopeErr, chiDOF;
391 ChgSlope(slc, tj, chgSlope, chgSlopeErr, chiDOF);
394 if(chgSlope > 3 * chgSlopeErr && (tjf.chgSlope > 3 * tjf.chgSlopeErr)) {
399 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
"SetStrategy: Curvy? tj chgSlope "<<chgSlope<<
" +/ "<<chgSlopeErr<<
" forecast chgSlope "<<tjf.chgSlope<<
" +/- "<<tjf.chgSlopeErr<<
" Slowing? "<<tj.
Strategy[
kSlowing];
413 if(tj.
Pts[tj.
EndPt[1]].AngleCode == 2)
return;
419 tjf.nextForecastUpdate = USHRT_MAX;
421 unsigned short minShPts = 3;
424 unsigned short istp = 0;
425 unsigned short nMissed = 0;
434 float minAveChg = 1E6;
435 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
436 if(tj.
Pts[ipt].AveChg <= 0)
continue;
437 if(tj.
Pts[ipt].AveChg > minAveChg)
continue;
438 minAveChg = tj.
Pts[ipt].AveChg;
440 if(minAveChg <= 0 || minAveChg == 1E6)
return;
449 float forecastWin0 = std::abs(tp.Pos[1] - tp.HitPos[1]);
450 if(forecastWin0 < 1) forecastWin0 = 1;
452 double stepSize = std::abs(1/tp.Dir[0]);
453 float window = 10 * stepSize;
455 mf::LogVerbatim(
"TC")<<
"Forecast T"<<tj.
ID<<
" PDGCode "<<tj.
PDGCode<<
" npwc "<<npwc<<
" minAveChg "<<(int)minAveChg<<
" stepSize "<<std::setprecision(2)<<stepSize<<
" window "<<window;
456 mf::LogVerbatim(
"TC")<<
" stp ___Pos____ nTPH Chg ChgPull Delta DRMS chgWid nTkLk nShLk";
462 unsigned short maxChgPt = 0;
463 unsigned short leavesNear = USHRT_MAX;
464 bool leavesBeforeEnd =
false;
465 unsigned short showerStartNear = USHRT_MAX;
466 unsigned short showerEndNear = USHRT_MAX;
467 unsigned short nShLike = 0;
468 unsigned short nTkLike = 0;
469 unsigned short trimPts = 0;
470 for(istp = 0; istp < 1000; ++istp) {
472 for(
unsigned short iwt = 0; iwt < 2; ++iwt) tp.Pos[iwt] += tp.Dir[iwt] * stepSize;
473 unsigned int wire = std::nearbyint(tp.Pos[0]);
475 if(wire > slc.
lastWire[plane]-1)
break;
488 tp.Delta =
PointTrajDOCA(slc, tp.HitPos[0], tp.HitPos[1], tp);
489 tp.DeltaRMS = tp.Delta / window;
490 tp.Environment.reset();
491 totHits += tp.Hits.size();
492 if(tp.Chg > maxChg) {
494 maxChgPt = fctj.
Pts.size();
498 tp.ChgPull = (tp.Chg / minAveChg - 1) / tj.
ChgRMS;
499 if((tp.ChgPull > 3 && tp.Hits.size() > 1) || tp.ChgPull > 10) {
502 if(nShLike > minShPts && nTkLike >= minShPts) {
504 showerStartNear = npwc + fctj.
Pts.size() - minShPts;
511 if(nShLike >= minShPts) nTkLike = 0;
513 if(tp.DeltaRMS > 0.8) {
514 leavesNear = npwc + fctj.
Pts.size();
515 leavesBeforeEnd =
true;
524 if(nTkLike > minShPts && nShLike >= minShPts) {
526 showerEndNear = npwc + fctj.
Pts.size() - minShPts;
533 if(nTkLike >= minShPts) nShLike = 0;
535 if(tp.DeltaRMS > 0.9) {
536 leavesNear = npwc + fctj.
Pts.size();
537 leavesBeforeEnd =
true;
541 fctj.
Pts.push_back(tp);
544 myprt<<std::setw(4)<<npwc + fctj.
Pts.size()<<
" "<<
PrintPos(slc, tp);
545 myprt<<std::setw(5)<<tp.Hits.size();
546 myprt<<std::setw(5)<<(int)tp.Chg;
547 myprt<<std::fixed<<std::setprecision(1);
548 myprt<<std::setw(8)<<tp.ChgPull;
549 myprt<<std::setw(8)<<tp.Delta;
550 myprt<<std::setw(8)<<std::setprecision(2)<<tp.DeltaRMS;
551 myprt<<std::setw(8)<<sqrt(tp.HitPosErr2);
552 myprt<<std::setw(6)<<nTkLike;
553 myprt<<std::setw(6)<<nShLike;
562 if(doPrt)
mf::LogVerbatim(
"TC")<<
"No hits found after 10 steps - break";
569 if(fctj.
Pts.size() < 6)
return;
573 fctj.
Pts.resize(fctj.
Pts.size() - trimPts);
576 for(
auto& tp : fctj.
Pts) fctj.
TotChg += tp.Chg;
581 if(maxChgPt > 0.3 * fctj.
Pts.size() && maxChg > 3 * tj.
AveChg) {
584 ChgSlope(slc, fctj, fctj.
EndPt[0], maxChgPt, tjf.chgSlope, tjf.chgSlopeErr, tjf.chgFitChiDOF);
586 ChgSlope(slc, fctj, tjf.chgSlope, tjf.chgSlopeErr, tjf.chgFitChiDOF);
595 tjf.nextForecastUpdate = npwc + fctj.
Pts.size();
596 tjf.leavesBeforeEnd = leavesBeforeEnd;
597 tjf.foundShower =
false;
598 if(leavesNear < tjf.nextForecastUpdate) {
600 tjf.nextForecastUpdate = leavesNear;
601 }
else if(showerStartNear < tjf.nextForecastUpdate) {
603 tjf.nextForecastUpdate = showerStartNear;
604 tjf.foundShower =
true;
605 }
else if(showerEndNear < tjf.nextForecastUpdate) {
607 tjf.nextForecastUpdate = showerEndNear;
611 tjf.showerLikeFraction = (float)nShLike / (
float)fctj.
Pts.size();
615 myprt<<
"Forecast T"<<tj.
ID<<
" tj.AveChg "<<(int)tj.
AveChg;
617 myprt<<
" last pos "<<
PrintPos(slc, tp);
618 myprt<<
" MCSMom "<<tjf.MCSMom;
619 myprt<<
" outlook "<<std::fixed<<std::setprecision(2)<<tjf.outlook;
620 myprt<<
" chgSlope "<<std::setprecision(1)<<tjf.chgSlope<<
" +/- "<<tjf.chgSlopeErr;
621 myprt<<
" chgRMS "<<std::setprecision(1)<<tjf.chgRMS;
622 myprt<<
" endBraggPeak "<<tjf.endBraggPeak;
623 myprt<<
" chiDOF "<<tjf.chgFitChiDOF;
624 myprt<<
" showerLike fraction "<<tjf.showerLikeFraction;
625 myprt<<
" nextForecastUpdate "<<tjf.nextForecastUpdate;
626 myprt<<
" leavesBeforeEnd? "<<tjf.leavesBeforeEnd;
627 myprt<<
" foundShower? "<<tjf.foundShower;
662 if(tj.
EndPt[1] < 1)
return;
668 unsigned int lastPt = tj.
EndPt[1];
673 unsigned short prevPtWithHits = USHRT_MAX;
674 unsigned short firstFitPt = tj.
EndPt[0];
675 for(
unsigned short ii = 1; ii < tj.
Pts.size(); ++ii) {
676 unsigned short ipt = lastPt - ii;
677 if(tj.
Pts[ipt].Chg > 0) {
678 prevPtWithHits = ipt;
683 if(prevPtWithHits == USHRT_MAX)
return;
689 if(lastPt < 4) minPtsFit = 2;
695 minPtsFit = lastPt / 3;
703 short newMCSMom =
MCSMom(slc, tj);
704 short minMCSMom = 0.6 * tj.
MCSMom;
706 if(lastPt > 10 && newMCSMom < minMCSMom) {
719 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;
751 if(lastPt > 20 && tj.
Pts[prevPtWithHits].FitChi > 1.5 && lastTP.
NTPsFit > minPtsFit) lastTP.
NTPsFit -= 2;
767 unsigned short cnt = 0;
768 for(
unsigned short ii = 0; ii < tj.
Pts.size(); ++ii) {
769 unsigned short ipt = lastPt - ii;
770 if(tj.
Pts[ipt].Chg > 0) {
774 if(cnt == lastTP.
NTPsFit)
break;
779 if(lastTP.
FitChi > 1.5 && tj.
Pts.size() > 6) {
784 if(ndead > 5 && !cleanMuon) {
793 if(prevPtWithHits != USHRT_MAX && tj.
Pts[prevPtWithHits].FitChi > 0) chirat = lastTP.
FitChi / tj.
Pts[prevPtWithHits].FitChi;
823 lastPt = tj.
EndPt[1];
831 unsigned short newNTPSFit = lastTP.
NTPsFit;
834 float prevChi = lastTP.
FitChi;
835 unsigned short ntry = 0;
837 while(lastTP.
FitChi > chiCut && lastTP.
NTPsFit > minPtsFit) {
839 newNTPSFit = 0.7 * newNTPSFit;
840 }
else if(lastTP.
NTPsFit > 4) {
845 if(lastTP.
NTPsFit < 3) newNTPSFit = 2;
846 if(newNTPSFit < minPtsFit) newNTPSFit = minPtsFit;
849 if(newNTPSFit == minPtsFit && tj.
MCSMom < 30) chiCut = 2;
853 if(lastTP.
FitChi > prevChi) {
860 if(lastTP.
NTPsFit == minPtsFit)
break;
869 lastPt = tj.
EndPt[1];
885 float defFrac = 1 / (float)(tj.
EndPt[1]);
886 lastTP.
AngErr = defFrac * tj.
Pts[0].AngErr + (1 - defFrac) * lastTP.
AngErr;
971 bool isVLA = (tj.
Pts[tj.
EndPt[1]].AngleCode == 2);
973 bool isSA = (tj.
Pts[tj.
EndPt[1]].AngleCode == 0);
978 if(tj.
EndPt[1] < tj.
Pts.size() - 1) {
990 if(tj.
Pts.size() < 10) {
992 float minWidth = 999;
993 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
994 if(tj.
Pts[ipt].Chg == 0)
continue;
995 if(tj.
Pts[ipt].HitPosErr2 > maxWidth) maxWidth = tj.
Pts[ipt].HitPosErr2;
996 if(tj.
Pts[ipt].HitPosErr2 < minWidth) minWidth = tj.
Pts[ipt].HitPosErr2;
999 if(maxWidth > 10 * minWidth) {
1000 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
" TP width variation too large: minWidth "<<minWidth<<
" maxWidth "<<maxWidth;
1020 if(tj.
EndPt[1] < 4)
return;
1028 unsigned short newSize = USHRT_MAX;
1029 unsigned short lastPtToChk = tj.
EndPt[1] - 4;
1030 float deltaCut = 2 * tj.
Pts[lastPtToChk].DeltaRMS;
1031 for(
unsigned short ipt = tj.
EndPt[1]; ipt > lastPtToChk; --ipt) {
1033 if(tj.
Pts[ipt].Delta < deltaCut)
break;
1034 float drat = tj.
Pts[ipt].Delta / tj.
Pts[ipt-1].Delta;
1035 if(drat > 1.2) newSize = ipt;
1037 if(newSize != USHRT_MAX) {
1039 for(
unsigned short ipt = newSize; ipt < tj.
Pts.size(); ++ipt)
UnsetUsedHits(slc, tj.
Pts[ipt]);
1048 short nStepBegin = tj.
Pts[2].Step - tj.
Pts[1].Step;
1050 unsigned short lastPt = tj.
Pts.size() - 1;
1051 unsigned short newSize = tj.
Pts.size();
1052 for(
unsigned short ipt = lastPt; ipt > lastPt - 2; --ipt) {
1053 nStepEnd = tj.
Pts[ipt].Step - tj.
Pts[ipt - 1].Step;
1054 if(nStepEnd > 3 * nStepBegin) newSize = ipt;
1057 if(newSize < tj.
Pts.size()) {
1058 for(
unsigned short ipt = newSize; ipt < tj.
Pts.size(); ++ipt)
UnsetUsedHits(slc, tj.
Pts[ipt]);
1061 tj.
Pts.resize(newSize);
1074 float frac = npwc / npts;
1099 if(tj.
Pts.empty())
return;
1100 if(ipt > tj.
Pts.size() - 1)
return;
1103 if(tj.
Pts[ipt].AngleCode == 2) {
1109 std::vector<unsigned int> closeHits;
1110 unsigned int lastPtWithUsedHits = tj.
EndPt[1];
1113 unsigned int wire = std::nearbyint(tp.
Pos[0]);
1120 float dw = tp.
Pos[0] - tj.
Pts[lastPtWithUsedHits].Pos[0];
1121 float dt = tp.
Pos[1] - tj.
Pts[lastPtWithUsedHits].Pos[1];
1122 float dpos = sqrt(dw * dw + dt * dt);
1123 float projErr = dpos * tj.
Pts[lastPtWithUsedHits].AngErr;
1125 float deltaCut = 3 * (projErr + tp.
DeltaRMS);
1129 float minDeltaCut = 1.1 * tj.
Pts[lastPtWithUsedHits].Delta;
1130 if(deltaCut < minDeltaCut) deltaCut = minDeltaCut;
1136 if(deltaCut < 0.5) deltaCut = 0.5;
1137 if(deltaCut > 3) deltaCut = 3;
1143 bool passedDeadWires = (abs(dw) > 20 &&
DeadWireCount(slc, tp.
Pos[0], tj.
Pts[lastPtWithUsedHits].Pos[0], tj.
CTP) > 10);
1144 if(passedDeadWires) deltaCut *= 2;
1149 float bigDelta = 2 * deltaCut;
1150 unsigned int imBig = UINT_MAX;
1151 tp.
Delta = deltaCut;
1153 float maxDeltaCut = 2 * bigDelta;
1163 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);
1166 std::vector<unsigned int> hitsInMultiplet;
1169 unsigned int ipl = planeID.
Plane;
1170 if(wire > slc.
lastWire[ipl])
return;
1172 if(slc.
wireHitRange[ipl][wire].first == -1) sigOK =
true;
1174 unsigned int firstHit = (
unsigned int)slc.
wireHitRange[ipl][wire].first;
1175 unsigned int lastHit = (
unsigned int)slc.
wireHitRange[ipl][wire].second;
1177 for(
unsigned int iht = firstHit; iht < lastHit; ++iht) {
1178 if(slc.
slHits[iht].InTraj == tj.
ID)
continue;
1179 if(slc.
slHits[iht].InTraj == SHRT_MAX)
continue;
1181 if(rawProjTick >
hit.StartTick() && rawProjTick <
hit.EndTick()) sigOK =
true;
1187 if(delta > 3)
continue;
1189 if(delta > maxDeltaCut)
continue;
1191 float dt = std::abs(ftime - tp.
Pos[1]);
1192 unsigned short localIndex = 0;
1194 if(
tcc.
dbgStp && delta < 100 && dt < 100) {
1196 myprt<<
" iht "<<iht;
1198 myprt<<
" delta "<<std::fixed<<std::setprecision(2)<<delta<<
" deltaCut "<<deltaCut<<
" dt "<<dt;
1199 myprt<<
" BB Mult "<<hitsInMultiplet.size()<<
" localIndex "<<localIndex<<
" RMS "<<std::setprecision(1)<<
hit.RMS();
1200 myprt<<
" Chi "<<std::setprecision(1)<<
hit.GoodnessOfFit();
1201 myprt<<
" InTraj "<<slc.
slHits[iht].InTraj;
1202 myprt<<
" Chg "<<(int)
hit.Integral();
1203 myprt<<
" Signal? "<<sigOK;
1205 if(slc.
slHits[iht].InTraj == 0 && delta < bigDelta && hitsInMultiplet.size() < 3 && !tj.
AlgMod[
kRvPrp]) {
1211 if(delta > 3)
continue;
1213 if(delta > deltaCut)
continue;
1216 if(std::find(closeHits.begin(), closeHits.end(), iht) != closeHits.end())
continue;
1217 closeHits.push_back(iht);
1218 if(hitsInMultiplet.size() > 1) {
1220 for(
auto& jht : hitsInMultiplet) {
1221 if(slc.
slHits[jht].InTraj == tj.
ID)
continue;
1222 if(std::find(closeHits.begin(), closeHits.end(), jht) != closeHits.end())
continue;
1223 closeHits.push_back(jht);
1230 myprt<<
"closeHits ";
1232 if(imBig < slc.
slHits.size()) {
1235 myprt<<
" imBig "<<imBig;
1238 if(closeHits.empty() && imBig == UINT_MAX) {
1242 if(imBig < slc.
slHits.size() && closeHits.empty()) {
1243 closeHits.push_back(imBig);
1246 if(!closeHits.empty()) sigOK =
true;
1248 if(closeHits.size() > 16) closeHits.resize(16);
1249 tp.
Hits.insert(tp.
Hits.end(), closeHits.begin(), closeHits.end());
1255 unsigned short nAvailable = 0;
1256 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1258 if(tcHit.InTraj == 0) ++nAvailable;
1260 if(nAvailable == 0) {
1281 if(ipt > tj.
Pts.size() - 1)
return;
1291 std::vector<int> wires(1);
1292 wires[0] = std::nearbyint(tp.
Pos[0]);
1293 if(wires[0] < 0 || wires[0] > (
int)slc.
lastWire[plane]-1)
return;
1303 if(wires[0] < (
int)slc.
lastWire[plane]-1) wires.push_back(wires[0] + 1);
1304 if(wires[0] > 0) wires.push_back(wires[0] - 1);
1306 if(wires[0] > 0) wires.push_back(wires[0] - 1);
1307 if(wires[0] < (
int)slc.
lastWire[plane]-1) wires.push_back(wires[0] + 1);
1313 myprt<<
" AddLAHits: Pos "<<
PrintPos(slc, tp)<<
" tp.AngleCode "<<tp.
AngleCode<<
" Wires under consideration";
1314 for(
auto& wire : wires) myprt<<
" "<<wire;
1323 std::array<int, 2> wireWindow;
1324 std::array<float, 2> timeWindow;
1326 timeWindow[0] = ltp.
Pos[1] - pos1Window;
1327 timeWindow[1] = ltp.
Pos[1] + pos1Window;
1331 for(
unsigned short ii = 0; ii < wires.size(); ++ii) {
1332 int wire = wires[ii];
1333 if(wire < 0 || wire > (
int)slc.
lastWire[plane])
continue;
1335 if(slc.
wireHitRange[plane][wire].first == -1) sigOK =
true;
1337 wireWindow[0] = wire;
1338 wireWindow[1] = wire;
1341 std::vector<unsigned int> closeHits =
FindCloseHits(slc, wireWindow, timeWindow, plane,
kAllHits,
true, hitsNear);
1342 if(hitsNear) sigOK =
true;
1343 for(
auto& iht : closeHits) {
1345 if(slc.
slHits[iht].InTraj == tj.
ID)
continue;
1347 if(std::find(oldHits.begin(), oldHits.end(), iht) != oldHits.end())
continue;
1348 tp.
Hits.push_back(iht);
1359 if(tp.
Hits.empty())
return;
1361 if(tp.
Hits.size() > 16) tp.
Hits.resize(16);
1367 unsigned short nAvailable = 0;
1368 unsigned int otherTjHit = INT_MAX;
1369 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1371 if(tcHit.InTraj == SHRT_MAX)
continue;
1372 if(tcHit.InTraj > 0) {
1373 otherTjHit = tp.
Hits[ii];
1378 if(nAvailable == 0 && otherTjHit != UINT_MAX) {
1380 unsigned short otherTj = slc.
slHits[otherTjHit].InTraj - 1;
1383 unsigned short atPt = USHRT_MAX;
1384 for(
unsigned short ipt = 0; ipt < otj.
Pts.size(); ++ipt) {
1385 for(
auto& iht : otj.
Pts[ipt].Hits) {
1386 if(iht == otherTjHit) {
1391 if(atPt != USHRT_MAX)
break;
1394 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
" Found a VLA merge candidate trajectory "<<otj.
ID<<
". Set StopFlag[kAtTj] and stop stepping";
1401 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1402 unsigned int iht = tp.
Hits[ii];
1403 if(slc.
slHits[iht].InTraj != 0)
continue;
1421 if(tj.
Pts.size() < 6)
return;
1426 if(tj.
Pts[tj.
EndPt[0]].AngleCode == 2)
return;
1430 if(tj.
EndPt[0] > 0) {
1440 unsigned int wire0 = std::nearbyint(tj.
Pts[0].Pos[0]);
1441 unsigned int nextWire = wire0 - tj.
StepDir;
1445 unsigned short ipl = planeID.
Plane;
1450 if(nextWire == slc.
lastWire[ipl] - 1)
return;
1458 float maxDelta = 10 * tj.
Pts[tj.
EndPt[1]].DeltaRMS;
1461 if(tp.
Hits.empty())
return;
1477 auto saveStrategy = tjWork.
Strategy;
1481 unsigned short lastPt = tjWork.
Pts.size() - 1;
1482 if(lastPt < 4)
return;
1486 for(
unsigned short ii = 0; ii < 4; ++ii) {
1487 unsigned short ipt = lastPt - ii;
1488 if(tjWork.
Pts[ipt].Chg == 0)
continue;
1489 chg += tjWork.
Pts[ipt].Chg;
1492 if(cnt == 0)
return;
1493 if(cnt > 1) tjWork.
Pts[lastPt].AveChg = chg / cnt;
1575 unsigned short localIndex;
1580 void GetHitMultiplet(
TCSlice& slc,
unsigned int theHit, std::vector<unsigned int>& hitsInMultiplet,
unsigned short& localIndex)
1582 hitsInMultiplet.clear();
1584 if(theHit > slc.
slHits.size() - 1)
return;
1585 if(slc.
slHits[theHit].InTraj == SHRT_MAX)
return;
1586 hitsInMultiplet.resize(1);
1587 hitsInMultiplet[0] = theHit;
1590 unsigned int theWire =
hit.WireID().Wire;
1591 unsigned short ipl =
hit.WireID().Plane;
1592 float theTime =
hit.PeakTime();
1593 float theRMS =
hit.RMS();
1595 bool theHitIsNarrow = (theRMS < narrowHitCut);
1596 float maxPeak =
hit.PeakAmplitude();
1597 unsigned short imTall = theHit;
1598 unsigned short nNarrow = 0;
1599 if(theHitIsNarrow) nNarrow = 1;
1602 for(
unsigned int iht = theHit - 1; iht != 0; --iht) {
1604 if(
hit.WireID().Wire != theWire)
break;
1605 if(
hit.WireID().Plane != ipl)
break;
1607 float rms =
hit.RMS();
1612 float dTick = std::abs(
hit.PeakTime() - theTime);
1613 if(dTick > hitSep)
break;
1614 hitsInMultiplet.push_back(iht);
1615 if(rms < narrowHitCut) ++nNarrow;
1616 float peakAmp =
hit.PeakAmplitude();
1617 if(peakAmp > maxPeak) {
1621 theTime =
hit.PeakTime();
1625 localIndex = hitsInMultiplet.size() - 1;
1628 if(hitsInMultiplet.size() > 1) std::reverse(hitsInMultiplet.begin(), hitsInMultiplet.end());
1630 theTime =
hit.PeakTime();
1632 for(
unsigned int iht = theHit + 1; iht < slc.
slHits.size(); ++iht) {
1634 if(
hit.WireID().Wire != theWire)
break;
1635 if(
hit.WireID().Plane != ipl)
break;
1636 if(slc.
slHits[iht].InTraj == SHRT_MAX)
continue;
1638 float rms =
hit.RMS();
1643 float dTick = std::abs(
hit.PeakTime() - theTime);
1644 if(dTick > hitSep)
break;
1645 hitsInMultiplet.push_back(iht);
1646 if(rms < narrowHitCut) ++nNarrow;
1647 float peakAmp =
hit.PeakAmplitude();
1648 if(peakAmp > maxPeak) {
1652 theTime =
hit.PeakTime();
1654 if(hitsInMultiplet.size() == 1)
return;
1656 if(hitsInMultiplet.size() > 16) {
1658 hitsInMultiplet.resize(16);
1663 if(nNarrow == hitsInMultiplet.size())
return;
1664 if(nNarrow == 0)
return;
1666 if(theHitIsNarrow && theHit == imTall) {
1669 auto tmp = hitsInMultiplet;
1672 hitsInMultiplet =
tmp;
1677 if(
hit.RMS() < narrowHitCut) {
1678 unsigned short killMe = 0;
1679 for(
unsigned short ii = 0; ii < hitsInMultiplet.size(); ++ii) {
1680 if(hitsInMultiplet[ii] == imTall) {
1685 hitsInMultiplet.erase(hitsInMultiplet.begin() + killMe);
1695 if(iht > slc.
slHits.size() - 1)
return 0;
1704 if(hitVec.empty())
return 0;
1721 unsigned short endPt = tj.
EndPt[1];
1723 if(tj.
Pts[endPt].AngleCode > 1)
return;
1725 if(tj.
Pts.size() - endPt > 10)
return;
1729 unsigned short plane = planeID.
Plane;
1732 unsigned short lastPt = tj.
Pts.size() - 1;
1733 for(lastPt = tj.
Pts.size() - 1; lastPt >= tj.
EndPt[1]; --lastPt)
if(!tj.
Pts[lastPt].Hits.empty())
break;
1734 auto& lastTP = tj.
Pts[lastPt];
1737 mf::LogVerbatim(
"TC")<<
"CSEP: checking "<<tj.
ID<<
" endPt "<<endPt<<
" Pts size "<<tj.
Pts.size()<<
" lastPt Pos "<<
PrintPos(slc, lastTP.Pos);
1743 if(lastTP.NTPsFit > 10 && lastTP.DeltaRMS > 0 && (lastTP.Delta / lastTP.DeltaRMS) > 3 && lastTP.ChgPull > 3) {
1744 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
" Removing last TP with large Delta "<<lastTP.Delta<<
" and large ChgPull "<<lastTP.ChgPull;
1750 if(tp.DeltaRMS > 0 && (tp.Delta / tp.DeltaRMS) > 3 && tp.ChgPull > 3) {
1760 ltp.
Pos = tj.
Pts[endPt].Pos;
1761 ltp.
Dir = tj.
Pts[endPt].Dir;
1762 double stepSize = std::abs(1/ltp.
Dir[0]);
1763 std::array<int, 2> wireWindow;
1764 std::array<float, 2> timeWindow;
1765 std::vector<int> closeHits;
1766 bool isClean =
true;
1767 for(
unsigned short step = 0; step < 10; ++step) {
1768 for(
unsigned short iwt = 0; iwt < 2; ++iwt) ltp.
Pos[iwt] += ltp.
Dir[iwt] * stepSize;
1769 int wire = std::nearbyint(ltp.
Pos[0]);
1770 wireWindow[0] = wire;
1771 wireWindow[1] = wire;
1772 timeWindow[0] = ltp.
Pos[1] - 5;
1773 timeWindow[1] = ltp.
Pos[1] + 5;
1777 for(
auto iht :
tmp)
if(slc.
slHits[iht].InTraj != tj.
ID) closeHits.push_back(iht);
1778 float nWiresPast = 0;
1780 if(ltp.
Dir[0] > 0) {
1782 nWiresPast = ltp.
Pos[0] - lastTP.Pos[0];
1785 nWiresPast = lastTP.Pos[0] - ltp.
Pos[0];
1788 if(nWiresPast > 0.5) {
1789 if(!tmp.empty()) isClean =
false;
1790 if(nWiresPast > 1.5)
break;
1795 unsigned short nAvailable = 0;
1796 for(
auto iht : closeHits)
if(slc.
slHits[iht].InTraj == 0) ++nAvailable;
1802 myprt<<
" nAvailable "<<nAvailable;
1803 myprt<<
" isClean "<<isClean;
1806 if(!isClean || nAvailable != closeHits.size())
return;
1808 unsigned short originalEndPt = tj.
EndPt[1] + 1;
1810 for(
unsigned short ipt = originalEndPt; ipt <= lastPt; ++ipt) {
1811 auto& tp = tj.
Pts[ipt];
1812 bool hitsAdded =
false;
1813 for(
unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1815 if(slc.
slHits[tp.Hits[ii]].InTraj != 0)
continue;
1816 tp.UseHit[ii] =
true;
1817 slc.
slHits[tp.Hits[ii]].InTraj = tj.
ID;
1831 for(
unsigned short ipt = originalEndPt; ipt <= lastPt; ++ipt)
UnsetUsedHits(slc, tj.
Pts[ipt]);
1845 if(tp.
Hits.empty())
return;
1847 unsigned short nused = 0;
1848 unsigned int iht = 0;
1849 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1850 if(!tp.
UseHit[ii])
continue;
1854 if(nused == 0)
return;
1868 float pathInv = std::abs(tp.
Dir[0]);
1869 if(pathInv < 0.05) pathInv = 0.05;
1871 float wireErr = tp.
Dir[1] * 0.289;
1873 tp.
HitPosErr2 = wireErr * wireErr + timeErr * timeErr;
1880 std::vector<unsigned int> hitVec;
1882 std::array<float, 2> newpos;
1887 unsigned int loWire = INT_MAX;
1888 unsigned int hiWire = 0;
1889 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1890 if(!tp.
UseHit[ii])
continue;
1891 unsigned int iht = tp.
Hits[ii];
1893 chg =
hit.Integral();
1894 unsigned int wire =
hit.WireID().Wire;
1895 if(wire < loWire) loWire = wire;
1896 if(wire > hiWire) hiWire = wire;
1897 newpos[0] += chg * wire;
1898 newpos[1] += chg *
hit.PeakTime();
1900 hitVec.push_back(iht);
1903 if(tp.
Chg == 0)
return;
1908 float pathInv = std::abs(tp.
Dir[0]);
1909 if(pathInv < 0.05) pathInv = 0.05;
1913 float dWire = 1 + hiWire - loWire;
1914 float wireErr = tp.
Dir[1] * dWire * 0.289;
1916 tp.
HitPosErr2 = wireErr * wireErr + timeErr2;
1928 if(ipt > tj.
Pts.size() - 1)
return;
1931 if(tp.
Hits.empty())
return;
1946 if(ipt < 5) useChg =
false;
1947 float chgPullCut = 1000;
1951 if(tj.
MCSMom < 30) chgPullCut *= 2;
1953 bool ignoreLongPulseHits =
false;
1954 unsigned short npts = tj.
EndPt[1] - tj.
EndPt[0] + 1;
1959 mf::LogVerbatim(
"TC")<<
"FUH: maxDelta "<<maxDelta<<
" useChg requested "<<useChg<<
" Norm AveChg "<<(int)tp.
AveChg<<
" tj.ChgRMS "<<std::setprecision(2)<<tj.
ChgRMS<<
" chgPullCut "<<chgPullCut<<
" TPHitsRMS "<<(int)
TPHitsRMSTick(slc, tp,
kUnusedHits)<<
" ExpectedHitsRMS "<<(int)expectedHitsRMS<<
" AngCode "<<tp.
AngleCode;
1963 float pathInv = std::abs(tp.
Dir[0]);
1964 if(pathInv < 0.05) pathInv = 0.05;
1967 tp.
Delta = maxDelta;
1969 unsigned short imbest = USHRT_MAX;
1970 std::vector<float> deltas(tp.
Hits.size(), 100);
1972 float bestDelta = maxDelta;
1973 unsigned short nAvailable = 0;
1974 unsigned short firstAvailable = USHRT_MAX;
1975 unsigned short lastAvailable = USHRT_MAX;
1976 unsigned short firstUsed = USHRT_MAX;
1977 unsigned short imBadRecoHit = USHRT_MAX;
1978 bool bestHitLongPulse =
false;
1979 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1981 unsigned int iht = tp.
Hits[ii];
1983 if(delta < bestDelta) bestDelta = delta;
1984 if(slc.
slHits[iht].InTraj > 0) {
1985 if(firstUsed == USHRT_MAX) firstUsed = ii;
1990 if(
hit.GoodnessOfFit() < 0 ||
hit.GoodnessOfFit() > 100) imBadRecoHit = ii;
1991 if(firstAvailable == USHRT_MAX) firstAvailable = ii;
2002 if(delta < tp.
Delta) {
2009 float chgWght = 0.5;
2011 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;
2012 if(imbest == USHRT_MAX || nAvailable == 0)
return;
2013 unsigned int bestDeltaHit = tp.
Hits[imbest];
2017 tp.
UseHit[imbest] =
true;
2018 slc.
slHits[bestDeltaHit].InTraj = tj.
ID;
2023 if(tp.
Hits.size() > 2 && nAvailable > 1 && firstUsed != USHRT_MAX && firstAvailable < firstUsed && lastAvailable > firstUsed) {
2025 tp.
UseHit[imbest] =
true;
2026 slc.
slHits[bestDeltaHit].InTraj = tj.
ID;
2032 std::vector<unsigned int> hitsInMultiplet;
2033 unsigned short localIndex;
2038 myprt<<
" in multiplet:";
2039 for(
auto& iht : hitsInMultiplet) myprt<<
" "<<
PrintHit(slc.
slHits[iht]);
2043 if(imBadRecoHit != USHRT_MAX) {
2044 unsigned int iht = tp.
Hits[imBadRecoHit];
2048 tp.
UseHit[imBadRecoHit] =
true;
2054 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
2055 unsigned int iht = tp.
Hits[ii];
2056 if(slc.
slHits[iht].InTraj > 0)
continue;
2057 if(std::find(hitsInMultiplet.begin(), hitsInMultiplet.end(), iht) == hitsInMultiplet.end())
continue;
2068 if(!useChg || (useChg && (tj.
AveChg <= 0 || tj.
ChgRMS <= 0))) {
2071 tp.
UseHit[imbest] =
true;
2072 slc.
slHits[bestDeltaHit].InTraj = tj.
ID;
2077 if(tj.
PDGCode == 13 && bestDelta < 0.5) {
2079 tp.
UseHit[imbest] =
true;
2080 slc.
slHits[bestDeltaHit].InTraj = tj.
ID;
2085 if(nAvailable == 1 || tp.
AngleCode == 0) {
2087 float aveChg = tp.
AveChg;
2088 if(aveChg <= 0) aveChg = tj.
AveChg;
2089 if(aveChg <= 0) aveChg =
hit.Integral();
2090 float chgRMS = tj.
ChgRMS;
2091 if(chgRMS < 0.2) chgRMS = 0.2;
2092 float bestDeltaHitChgPull = std::abs(
hit.Integral() * pathInv / aveChg - 1) / chgRMS;
2094 if(bestDeltaHitChgPull < chgPullCut || tp.
Delta < 0.1) {
2095 tp.
UseHit[imbest] =
true;
2096 slc.
slHits[bestDeltaHit].InTraj = tj.
ID;
2105 if(nAvailable == 2) {
2107 std::vector<unsigned int> tHits;
2108 unsigned short localIndex;
2112 unsigned short ombest = USHRT_MAX;
2113 unsigned int otherHit = INT_MAX;
2114 if(tHits.size() == 2) {
2115 otherHit = tHits[1 - localIndex];
2117 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
2118 if(slc.
slHits[tp.
Hits[ii]].InTraj > 0)
continue;
2119 if(tp.
Hits[ii] == otherHit) {
2126 mf::LogVerbatim(
"TC")<<
" Doublet: imbest "<<imbest<<
" ombest "<<ombest;
2129 if(ombest < tp.
Hits.size()) {
2131 float bestHitDeltaErr = std::abs(tp.
Dir[1]) * 0.17 + std::abs(tp.
Dir[0]) *
HitTimeErr(slc, bestDeltaHit);
2133 float bestDeltaHitFOM = deltas[imbest] / bestHitDeltaErr;
2134 if(bestDeltaHitFOM < 0.5) bestDeltaHitFOM = 0.5;
2137 float bestDeltaHitChgPull = std::abs(
hit.Integral() * pathInv / tp.
AveChg - 1) / tj.
ChgRMS;
2138 if(bestDeltaHitChgPull > 1) bestDeltaHitFOM *= chgWght * bestDeltaHitChgPull;
2140 float rmsRat =
hit.RMS() / expectedWidth;
2141 if(rmsRat < 1) rmsRat = 1 / rmsRat;
2142 bestDeltaHitFOM *= rmsRat;
2143 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
" bestDeltaHit FOM "<<deltas[imbest]/bestHitDeltaErr<<
" bestDeltaHitChgPull "<<bestDeltaHitChgPull<<
" rmsRat "<<rmsRat<<
" bestDeltaHitFOM "<<bestDeltaHitFOM;
2145 float otherHitDeltaErr = std::abs(tp.
Dir[1]) * 0.17 + std::abs(tp.
Dir[0]) *
HitTimeErr(slc, otherHit);
2146 float otherHitFOM = deltas[ombest] / otherHitDeltaErr;
2147 if(otherHitFOM < 0.5) otherHitFOM = 0.5;
2149 float otherHitChgPull = std::abs(ohit.Integral() * pathInv / tp.
AveChg - 1) / tj.
ChgRMS;
2150 if(otherHitChgPull > 1) otherHitFOM *= chgWght * otherHitChgPull;
2151 rmsRat = ohit.RMS() / expectedWidth;
2152 if(rmsRat < 1) rmsRat = 1 / rmsRat;
2153 otherHitFOM *= rmsRat;
2154 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
" otherHit FOM "<<deltas[ombest]/otherHitDeltaErr<<
" otherHitChgPull "<<otherHitChgPull<<
" rmsRat "<<rmsRat<<
" otherHitFOM "<<otherHitFOM;
2156 float doubletChg =
hit.Integral() + ohit.Integral();
2157 float doubletTime = (
hit.Integral() *
hit.PeakTime() + ohit.Integral() * ohit.PeakTime()) / doubletChg;
2158 doubletChg *= pathInv;
2162 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
" doublet Chg "<<doubletChg<<
" doubletTime "<<doubletTime<<
" doubletRMSTimeErr "<<doubletRMSTimeErr;
2163 float doubletFOM =
PointTrajDOCA(slc, tp.
Pos[0], doubletTime, tp) / doubletRMSTimeErr;
2164 if(doubletFOM < 0.5) doubletFOM = 0.5;
2165 float doubletChgPull = std::abs(doubletChg * pathInv / tp.
AveChg - 1) / tj.
ChgRMS;
2166 if(doubletChgPull > 1) doubletFOM *= chgWght * doubletChgPull;
2167 rmsRat = doubletWidthTick / expectedWidth;
2168 if(rmsRat < 1) rmsRat = 1 / rmsRat;
2169 doubletFOM *= rmsRat;
2170 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
" doublet FOM "<<
PointTrajDOCA(slc, tp.
Pos[0], doubletTime, tp)/doubletRMSTimeErr<<
" doubletChgPull "<<doubletChgPull<<
" rmsRat "<<rmsRat<<
" doubletFOM "<<doubletFOM;
2171 if(doubletFOM < bestDeltaHitFOM && doubletFOM < otherHitFOM) {
2172 tp.
UseHit[imbest] =
true;
2173 slc.
slHits[bestDeltaHit].InTraj = tj.
ID;
2174 tp.
UseHit[ombest] =
true;
2175 slc.
slHits[otherHit].InTraj = tj.
ID;
2178 if(bestDeltaHitFOM < otherHitFOM) {
2179 tp.
UseHit[imbest] =
true;
2180 slc.
slHits[bestDeltaHit].InTraj = tj.
ID;
2182 tp.
UseHit[ombest] =
true;
2183 slc.
slHits[otherHit].InTraj = tj.
ID;
2188 tp.
UseHit[imbest] =
true;
2189 slc.
slHits[bestDeltaHit].InTraj = tj.
ID;
2196 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
" Multiplet: hitsWidth "<<hitsWidth<<
" expectedWidth "<<expectedWidth<<
" tick range "<<(int)minTick<<
" "<<(
int)maxTick;
2198 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
2199 unsigned int iht = tp.
Hits[ii];
2200 if(slc.
slHits[iht].InTraj > 0)
continue;
2202 if(
hit.PeakTime() < minTick)
continue;
2203 if(
hit.PeakTime() > maxTick)
continue;
2218 if(tj.
Pts.size() < 15)
return;
2219 if(tj.
MCSMom < 100)
return;
2228 unsigned short endPt = tj.
EndPt[1];
2229 if(tj.
Pts[endPt].NTPsFit < 5)
return;
2230 if(tj.
Pts[endPt].NTPsFit > endPt)
return;
2232 unsigned short kinkPt = endPt - tj.
Pts[endPt].NTPsFit;
2235 if(kinkPt < 5)
return;
2237 if(tj.
Pts[kinkPt].NTPsFit > 0.5 * kinkPt)
return;
2239 unsigned short maxPtsFit = tj.
Pts[kinkPt].NTPsFit;
2240 unsigned short atPt = kinkPt;
2241 for(
unsigned short ipt = kinkPt; kinkPt > tj.
EndPt[0] + 5; --ipt) {
2242 if(tj.
Pts[ipt].NTPsFit > maxPtsFit) {
2243 maxPtsFit = tj.
Pts[ipt].NTPsFit;
2247 if(tj.
Pts[ipt].NTPsFit < maxPtsFit)
break;
2250 if(atPt < 5)
return;
2252 if(
MCSMom(slc, tj, tj.
EndPt[0], atPt) < 500)
return;
2254 for(
unsigned short ipt = atPt; ipt < tj.
Pts.size(); ++ipt)
UnsetUsedHits(slc, tj.
Pts[ipt]);
2256 tj.
Pts.resize(atPt + 1);
2274 short firstPtWithChg = tj.
EndPt[0];
2278 short minMCSMom = 0.7 * tj.
MCSMom;
2279 while(firstPtWithChg < tj.
EndPt[1]) {
2280 short nextPtWithChg = firstPtWithChg + 1;
2282 for(nextPtWithChg = firstPtWithChg + 1; nextPtWithChg < tj.
EndPt[1]; ++nextPtWithChg) {
2283 if(tj.
Pts[nextPtWithChg].Chg > 0)
break;
2285 if(nextPtWithChg == firstPtWithChg + 1) {
2291 if(nextPtWithChg < (tj.
EndPt[1] - 1) && tj.
Pts[nextPtWithChg + 1].Chg == 0) {
2292 firstPtWithChg = nextPtWithChg;
2298 float chgrat = tj.
Pts[nextPtWithChg].Chg / tj.
Pts[firstPtWithChg].Chg;
2299 if(chgrat < 0.7 || chgrat > 1.4) {
2300 firstPtWithChg = nextPtWithChg;
2320 if(tj.
Pts.size() < 10) {
2323 short chgCutPt = tj.
EndPt[0] + 5;
2324 if(firstPtWithChg < chgCutPt) {
2329 chgCutPt = tj.
EndPt[1] - 5;
2330 if(chgCutPt < tj.
EndPt[0]) chgCutPt = tj.
EndPt[0];
2331 if(nextPtWithChg > chgCutPt) maxChg = 1E6;
2336 for(
unsigned short mpt = firstPtWithChg + 1; mpt < nextPtWithChg; ++mpt) {
2337 if(tj.
Pts[mpt].Chg > 0) {
2338 mf::LogWarning(
"TC")<<
"FillGaps coding error: firstPtWithChg "<<firstPtWithChg<<
" mpt "<<mpt<<
" nextPtWithChg "<<nextPtWithChg;
2342 bool filled =
false;
2344 for(
unsigned short ii = 0; ii < tj.
Pts[mpt].Hits.size(); ++ii) {
2345 unsigned int iht = tj.
Pts[mpt].Hits[ii];
2346 if(slc.
slHits[iht].InTraj > 0)
continue;
2350 if(delta > maxDelta)
continue;
2351 tj.
Pts[mpt].UseHit[ii] =
true;
2353 chg +=
hit.Integral();
2356 if(chg > maxChg ||
MCSMom(slc, tj) < minMCSMom) {
2370 firstPtWithChg = nextPtWithChg;
2388 if(tj.
Pts[tj.
EndPt[1]].AngleCode == 0)
return;
2393 unsigned short ii, stopPt;
2396 unsigned short lastMult1Pt = USHRT_MAX;
2398 unsigned short nHiMultPt = 0;
2400 unsigned short nHiMultPtHits = 0;
2402 unsigned short nHiMultPtUsedHits = 0;
2406 bool doBreak =
false;
2408 for(ii = 1; ii < tj.
Pts.size(); ++ii) {
2409 stopPt = tj.
EndPt[1] - ii;
2410 for(jj = 0; jj < tj.
Pts[stopPt].Hits.size(); ++jj) {
2411 iht = tj.
Pts[stopPt].Hits[jj];
2412 if(slc.
slHits[iht].InTraj > 0) {
2419 if(lastMult1Pt == USHRT_MAX && tj.
Pts[stopPt].Hits.size() == 1 && tj.
Pts[stopPt-1].Hits.size() == 1) lastMult1Pt = stopPt;
2420 if(tj.
Pts[stopPt].Hits.size() > 1) {
2422 nHiMultPtHits += tj.
Pts[stopPt].Hits.size();
2426 if(lastMult1Pt != USHRT_MAX)
break;
2427 if(stopPt == 1)
break;
2430 float fracHiMult = (float)nHiMultPt / (
float)ii;
2431 if(lastMult1Pt != USHRT_MAX) {
2432 float nchk = tj.
EndPt[1] - lastMult1Pt + 1;
2433 fracHiMult = (float)nHiMultPt / nchk;
2435 fracHiMult = (float)nHiMultPt / (
float)ii;
2437 float fracHitsUsed = 0;
2438 if(nHiMultPt > 0 && nHiMultPtHits > 0) fracHitsUsed = (float)nHiMultPtUsedHits / (
float)nHiMultPtHits;
2444 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
"CHMUH: First InTraj stopPt "<<stopPt<<
" fracHiMult "<<fracHiMult<<
" fracHitsUsed "<<fracHitsUsed<<
" lastMult1Pt "<<lastMult1Pt<<
" sortaLargeAngle "<<sortaLargeAngle;
2445 if(fracHiMult < 0.3)
return;
2446 if(fracHitsUsed > 0.98)
return;
2451 mf::LogVerbatim(
"TC")<<
" Pts size "<<tj.
Pts.size()<<
" nHiMultPt "<<nHiMultPt<<
" nHiMultPtHits "<<nHiMultPtHits<<
" nHiMultPtUsedHits "<<nHiMultPtUsedHits<<
" sortaLargeAngle "<<sortaLargeAngle<<
" maxHitDelta "<<maxDelta;
2466 unsigned short killPts;
2469 for(ipt = stopPt + 1; ipt < tj.
Pts.size(); ++ipt) {
2472 for(ii = 0; ii < tj.
Pts[ipt].Hits.size(); ++ii) {
2473 iht = tj.
Pts[ipt].Hits[ii];
2475 if(slc.
slHits[iht].InTraj != 0)
continue;
2477 if(delta > maxDelta)
continue;
2479 tj.
Pts[ipt].UseHit[ii] =
true;
2485 if(tj.
Pts[ipt].Chg == 0)
continue;
2488 if(sortaLargeAngle) tj.
Pts[ipt].NTPsFit = 2;
2493 for(
unsigned short jpt = stopPt + 1; jpt <= ipt; ++jpt) {
2494 for(
unsigned short jj = 0; jj < tj.
Pts[jpt].Hits.size(); ++jj) {
2495 if(tj.
Pts[jpt].UseHit[jj]) slc.
slHits[tj.
Pts[jpt].Hits[jj]].InTraj = 0;
2501 for(
unsigned short jpt = stopPt + 1; jpt <= ipt; ++jpt) {
2502 for(
unsigned short jj = 0; jj < tj.
Pts[jpt].Hits.size(); ++jj) {
2503 if(tj.
Pts[jpt].UseHit[jj]) slc.
slHits[tj.
Pts[jpt].Hits[jj]].InTraj = tj.
ID;
2531 if(tj.
Pts.size() < 10)
return;
2532 if(tj.
Pts[tj.
EndPt[1]].AngleCode == 0)
return;
2534 unsigned short aveMult= 0;
2535 unsigned short ipt, nhalf = tj.
Pts.size() / 2;
2536 unsigned short cnt = 0;
2537 for(
auto& tp : tj.
Pts) {
2538 if(tp.Chg == 0)
continue;
2539 aveMult += tp.Hits.size();
2541 if(cnt == nhalf)
break;
2543 if(cnt == 0)
return;
2545 if(aveMult == 0) aveMult = 1;
2549 for(ipt = tj.
EndPt[1]; ipt > tj.
EndPt[0]; --ipt) {
2550 if(tj.
Pts[ipt].Chg == 0)
continue;
2551 if(tj.
Pts[ipt].Hits.size() > aveMult) {
2576 if(tj.
MCSMom < 100)
return;
2577 if(tj.
Pts.size() < 50)
return;
2579 unsigned short ept = tj.
EndPt[1];
2584 if(lastTp.
FitChi < 1)
return;
2586 unsigned short npts = USHRT_MAX;
2587 float lastDelta = lastTp.
Delta;
2589 for(
unsigned short ii = 1; ii < 20; ++ii) {
2590 unsigned short ipt = ept - ii;
2592 if(tp.
Chg == 0)
continue;
2597 lastDelta = tp.
Delta;
2603 if(npts == USHRT_MAX)
return;
2605 if(npts < 4)
return;
2612 for(
unsigned short ii = 1; ii <= npts; ++ii) {
2613 unsigned short ipt = ept - ii;
2615 if(tp.
Chg == 0)
continue;
2616 tp.
Dir = tj.
Pts[ept].Dir;
2617 tp.
Ang = tj.
Pts[ept].Ang;
2621 float dw = tp.
Pos[0] - tj.
Pts[ept].Pos[0];
2622 if(tp.
Dir[0] != 0) tp.
Pos[1] = tj.
Pts[ept].Pos[1] + dw * tp.
Dir[1] / tp.
Dir[0];
2639 unsigned int lastPt = tj.
EndPt[1];
2642 if(lastTP.
Chg == 0)
return;
2643 if(lastPt < 6)
return;
2645 unsigned short ii, ipt, cnt = 0;
2647 for(ii = 1; ii < tj.
Pts.size(); ++ii) {
2649 if(ipt > tj.
Pts.size() - 1)
break;
2650 if(tj.
Pts[ipt].Chg == 0)
continue;
2653 if(cnt == lastTP.
NTPsFit)
break;
2659 lastTP.
DeltaRMS = 1.2 * sum / (float)cnt;
2675 if(tj.
Pts.size() < 3) {
2680 unsigned short nit = 0;
2682 while(lastTP.
FitChi > maxChi && nit < 3) {
2684 unsigned short imBad = USHRT_MAX;
2685 unsigned short cnt = 0;
2686 for(
unsigned short ii = 1; ii < tj.
Pts.size(); ++ii) {
2687 unsigned short ipt = tj.
Pts.size() - 1 - ii;
2689 if(tp.
Chg == 0)
continue;
2690 if(tp.
Delta > maxDelta) {
2691 maxDelta = tp.
Delta;
2697 if(imBad == USHRT_MAX)
return;
2717 unsigned short lastPt = tj.
Pts.size() - 1;
2718 if(tj.
Pts[lastPt].Chg > 0)
return true;
2719 unsigned short endPt = tj.
EndPt[1];
2722 unsigned short nMasked = 0;
2723 unsigned short nOneHit = 0;
2724 unsigned short nOKChg = 0;
2725 unsigned short nOKDelta = 0;
2727 unsigned short nPosDelta = 0;
2729 unsigned short nDeltaIncreasing = 0;
2731 float prevDelta = tj.
Pts[endPt].Delta;
2732 float maxOKDelta = 10 * tj.
Pts[endPt].DeltaRMS;
2735 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt)
if(tj.
Pts[ipt].Chg > maxOKChg) maxOKChg = tj.
Pts[ipt].Chg;
2736 for(
unsigned short ii = 1; ii < tj.
Pts.size(); ++ii) {
2737 unsigned short ipt = tj.
Pts.size() - ii;
2738 auto& tp = tj.
Pts[ipt];
2739 if(tp.Chg > 0)
break;
2740 unsigned short nUnusedHits = 0;
2742 for(
unsigned short jj = 0; jj < tp.Hits.size(); ++jj) {
2743 unsigned int iht = tp.Hits[jj];
2744 if(slc.
slHits[iht].InTraj != 0)
continue;
2747 chg +=
hit.Integral();
2749 if(chg < maxOKChg) ++nOKChg;
2750 if(nUnusedHits == 1) ++nOneHit;
2751 if(tp.Delta < maxOKDelta) ++nOKDelta;
2753 if(tp.Pos[1] > tp.HitPos[1]) ++nPosDelta;
2755 if(tp.Delta < prevDelta) ++nDeltaIncreasing;
2756 prevDelta = tp.Delta;
2763 bool driftingAway = nMasked > 2 && (nPosDelta == 0 || nPosDelta == nMasked);
2765 if(driftingAway && nDeltaIncreasing < nMasked - 1) driftingAway =
false;
2768 mf::LogVerbatim(
"TC")<<
"MHOK: nMasked "<<nMasked<<
" nOneHit "<<nOneHit<<
" nOKChg "<<nOKChg<<
" nOKDelta "<<nOKDelta<<
" nPosDelta "<<nPosDelta<<
" nDeltaIncreasing "<<nDeltaIncreasing<<
" driftingAway? "<<driftingAway;
2772 if(nMasked < 8 || nOneHit < 8)
return true;
2773 if(nOKDelta != nMasked)
return true;
2774 if(nOKChg != nMasked)
return true;
2781 if(nMasked > tj.
Pts[endPt].NTPsFit)
return false;
2785 unsigned short newNTPSFit;
2787 newNTPSFit = tj.
Pts[endPt].NTPsFit / 2;
2791 for(
unsigned ipt = endPt + 1; ipt < tj.
Pts.size(); ++ipt) {
2793 for(
unsigned short ii = 0; ii < tj.
Pts[ipt].Hits.size(); ++ii) {
2794 unsigned int iht = tp.
Hits[ii];
2795 if(slc.
slHits[iht].InTraj == 0) {
2821 if(tj.
PDGCode == 13)
return false;
2823 if(tj.
Pts.size() > 40 && tj.
MCSMom > 200)
return false;
2825 unsigned short nBadFit = 0;
2826 unsigned short nHiChg = 0;
2827 unsigned short cnt = 0;
2828 for(
unsigned short ipt = tj.
Pts.size() - 1; ipt > tj.
EndPt[1]; --ipt ) {
2829 if(tj.
Pts[ipt].FitChi > 2) ++nBadFit;
2830 if(tj.
Pts[ipt].ChgPull > 3) ++nHiChg;
2836 if(nBadFit > 3 && nHiChg == 0)
return true;
2869 if(npwc < 2 * nPtsFit)
return;
2870 unsigned short lastPt = tj.
EndPt[1];
2871 if(tj.
Pts[lastPt].Chg == 0)
return;
2887 unsigned short kinkPt = 0;
2888 unsigned short cnt = 0;
2890 for(
unsigned short ii = 0; ii < tj.
Pts.size(); ++ii) {
2891 unsigned short ipt = tj.
EndPt[1] - ii - 1;
2894 if(ipt <= tj.
EndPt[0] + 2)
break;
2895 if(tj.
Pts[ipt].Chg <= 0)
continue;
2897 endChg += tj.
Pts[ipt].Chg;
2898 if(cnt == nPtsFit) {
2903 if(kinkPt == 0 || cnt == 0)
return;
2905 unsigned short fitDir = -1;
2907 FitTraj(slc, tj, lastPt, nPtsFit, fitDir, tpFit);
2908 float dang = std::abs(tj.
Pts[kinkPt].Ang - tpFit.
Ang);
2911 float err = tj.
Pts[kinkPt].AngErr;
2914 float kinkSig = dang / err;
2915 float endChgAsym = (endChg - tj.
Pts[kinkPt].AveChg) / (endChg + tj.
Pts[kinkPt].AveChg);
2918 myprt<<
"GottaKink kinkPt "<<
PrintPos(slc, tj.
Pts[kinkPt]);
2919 myprt<<std::setprecision(3);
2920 myprt<<
" Ang before "<<tj.
Pts[kinkPt].Ang<<
" Err "<<tj.
Pts[kinkPt].AngErr;
2921 myprt<<
" AveChg "<<(int)tj.
Pts[kinkPt].AveChg;
2922 myprt<<
" Ang after "<<tpFit.
Ang<<
" Err "<<tpFit.
AngErr;
2923 myprt<<
" endChg "<<endChg;
2924 myprt<<
" dang "<<dang;
2925 myprt<<
" kinkAngCut "<<kinkAngCut;
2926 myprt<<
" kinkSig "<<kinkSig;
2927 myprt<<
" endChgAsym "<<endChgAsym;
2933 bool foundKink = (dang > 0.8 * kinkAngCut && kinkSig > 5);
2950 if(dang < 2 * kinkAngCut && endChgAsym > 0.2)
return;
2958 if(dang > kinkAngCut) {
3001 if(tj.
Pts.size() < 3)
return;
3003 unsigned short atPt = tj.
EndPt[1];
3004 unsigned short maxPtsFit = 0;
3005 for(
unsigned short ipt = tj.
EndPt[0]; ipt < tj.
EndPt[1]; ++ipt) {
3006 if(tj.
Pts[ipt].Chg == 0)
continue;
3007 if(tj.
Pts[ipt].NTPsFit > maxPtsFit) {
3008 maxPtsFit = tj.
Pts[ipt].NTPsFit;
3011 if(maxPtsFit > 20)
break;
3015 unsigned short firstPtFit = tj.
EndPt[0];
3016 unsigned short cnt = 0;
3017 for(
unsigned short ii = 1; ii < tj.
Pts.size(); ++ii) {
3018 if(ii > atPt)
break;
3019 unsigned short ipt = atPt - ii;
3020 if(tj.
Pts[ipt].Chg == 0)
continue;
3022 if(cnt == maxPtsFit) {
3028 bool needsRevProp = firstPtFit > 3;
3046 unsigned int wire = std::nearbyint(tp.
Pos[0]);
3048 needsRevProp = (wire < slc.
nWires[plane] && slc.
wireHitRange[plane][wire].first == -1);
3049 if(
tcc.
dbgStp && needsRevProp)
mf::LogVerbatim(
"TC")<<
"FTB: Previous wire "<<wire<<
" is dead. Call ReversePropagate";
3055 needsRevProp =
true;
3057 mf::LogVerbatim(
"TC")<<
"FTB: Close unused hits found near EndPt[0] "<<tp.
Hits.size()<<
". Call ReversePropagate";
3065 mf::LogVerbatim(
"TC")<<
"FTB: maxPtsFit "<<maxPtsFit<<
" at point "<<atPt<<
" firstPtFit "<<firstPtFit<<
" Needs ReversePropagate? "<<needsRevProp;
3074 for(
unsigned short ipt = 0; ipt <= firstPtFit; ++ipt)
UnsetUsedHits(slc, tj.
Pts[ipt]);
3099 if(npwc < 6)
return;
3101 if(npwc < 10 && tj.
MCSMom < 100)
return;
3110 unsigned short firstPt = tj.
EndPt[0];
3112 if(atPt == tj.
EndPt[0])
return;
3115 float maxDelta = 4 * tj.
Pts[tj.
EndPt[1]].DeltaRMS;
3119 float maxDeltaRMS = 0;
3120 for(
unsigned short ipt = atPt; ipt <= tj.
EndPt[1]; ++ipt) {
3121 if(tj.
Pts[ipt].DeltaRMS > maxDeltaRMS) maxDeltaRMS = tj.
Pts[ipt].DeltaRMS;
3123 maxDelta = 3 * maxDeltaRMS;
3127 mf::LogVerbatim(
"TC")<<
"FixTrajBegin: atPt "<<atPt<<
" firstPt "<<firstPt<<
" Stops at end 0? "<<
PrintStopFlag(tj, 0)<<
" start vertex "<<tj.
VtxID[0]<<
" maxDelta "<<maxDelta;
3132 bool maskedPts =
false;
3133 for(
unsigned short ii = 1; ii < tj.
Pts.size(); ++ii) {
3134 if(ii > atPt)
break;
3135 unsigned int ipt = atPt - ii;
3137 tp.
Dir = tj.
Pts[atPt].Dir;
3138 tp.
Ang = tj.
Pts[atPt].Ang;
3142 float dw = tp.
Pos[0] - tj.
Pts[atPt].Pos[0];
3143 if(tp.
Dir[0] != 0) tp.
Pos[1] = tj.
Pts[atPt].Pos[1] + dw * tp.
Dir[1] / tp.
Dir[0];
3145 tj.
Pts[ipt].DeltaRMS = tj.
Pts[atPt].DeltaRMS;
3146 tj.
Pts[ipt].NTPsFit = tj.
Pts[atPt].NTPsFit;
3147 tj.
Pts[ipt].FitChi = tj.
Pts[atPt].FitChi;
3148 tj.
Pts[ipt].AveChg = tj.
Pts[atPt].AveChg;
3150 bool maskThisPt = (tj.
Pts[ipt].Delta > maxDelta);
3151 if(maskThisPt) maskedPts =
true;
3180 if(npwc < 6)
return;
3182 if(npwc < 10 && tj.
MCSMom < 100)
return;
3194 if(atPt == tj.
EndPt[1])
return;
3197 for(
unsigned short ipt = atPt + 1; ipt <= tj.
EndPt[1]; ++ipt) {
3199 tp.
Dir = tj.
Pts[atPt].Dir;
3200 tp.
Ang = tj.
Pts[atPt].Ang;
3204 float dw = tp.
Pos[0] - tj.
Pts[atPt].Pos[0];
3205 if(tp.
Dir[0] != 0) tp.
Pos[1] = tj.
Pts[atPt].Pos[1] + dw * tp.
Dir[1] / tp.
Dir[0];
3207 tj.
Pts[ipt].DeltaRMS = tj.
Pts[atPt].DeltaRMS;
3208 tj.
Pts[ipt].NTPsFit = tj.
Pts[atPt].NTPsFit;
3209 tj.
Pts[ipt].FitChi = tj.
Pts[atPt].FitChi;
3210 tj.
Pts[ipt].AveChg = tj.
Pts[atPt].AveChg;
3227 if(tj.
ID > 0)
return true;
3230 if(tj.
Pts.size() < 3)
return false;
3234 std::vector<int> tID;
3235 std::vector<unsigned short> tCnt;
3237 unsigned short hitCnt = 0;
3238 unsigned short nAvailable = 0;
3239 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
3240 for(
unsigned short ii = 0; ii < tj.
Pts[ipt].Hits.size(); ++ii) {
3242 if(tj.
Pts[ipt].UseHit[ii]) {
3246 unsigned int iht = tj.
Pts[ipt].Hits[ii];
3247 if(slc.
slHits[iht].InTraj > 0 && (
unsigned int)slc.
slHits[iht].InTraj <= slc.
tjs.size()) {
3248 int tjid = slc.
slHits[iht].InTraj;
3249 unsigned short indx;
3250 for(indx = 0; indx < tID.size(); ++indx)
if(tID[indx] == tjid)
break;
3251 if(indx == tID.size()) {
3252 tID.push_back(tjid);
3265 int oldTjID = INT_MAX;
3269 myprt<<
"IsGhost tj hits size cut "<<hitCnt<<
" tID_tCnt";
3270 for(
unsigned short ii = 0; ii < tCnt.size(); ++ii) myprt<<
" "<<tID[ii]<<
"_"<<tCnt[ii];
3271 myprt<<
"\nAvailable hits "<<nAvailable;
3274 for(
unsigned short ii = 0; ii < tCnt.size(); ++ii) {
3275 if(tCnt[ii] > hitCnt) {
3280 if(oldTjID == INT_MAX)
return false;
3281 int oldTjIndex = oldTjID - 1;
3285 if(oTj.
PDGCode == 13 && hitCnt < 0.1 * oTj.
Pts.size())
return false;
3290 int wire0 = INT_MAX;
3292 for(
auto& otp : oTj.
Pts) {
3293 int wire = std::nearbyint(otp.Pos[0]);
3294 if(wire < wire0) wire0 = wire;
3295 if(wire > wire1) wire1 = wire;
3298 int nwires = wire1 - wire0 + 1;
3299 std::vector<float> oTjPos1(nwires, -1);
3300 unsigned short nMissedWires = 0;
3301 for(
unsigned short ipt = oTj.
EndPt[0]; ipt <= oTj.
EndPt[1]; ++ipt) {
3302 if(oTj.
Pts[ipt].Chg == 0)
continue;
3303 int wire = std::nearbyint(oTj.
Pts[ipt].Pos[0]);
3304 int indx = wire - wire0;
3305 if(indx < 0 || indx > nwires - 1)
continue;
3306 oTjPos1[indx] = oTj.
Pts[ipt].Pos[1];
3310 unsigned short ngh = 0;
3312 unsigned short nghPlus = 0;
3314 unsigned short firstPtInoTj = USHRT_MAX;
3315 unsigned short lastPtInoTj = 0;
3317 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
3318 if(tj.
Pts[ipt].Chg > 0) {
3322 int wire = std::nearbyint(tj.
Pts[ipt].Pos[0]);
3323 int indx = wire - wire0;
3324 if(indx < 0 || indx > nwires - 1)
continue;
3325 if(oTjPos1[indx] > 0) {
3327 bool HitInoTj =
false;
3328 for(
unsigned short ii = 0; ii < tj.
Pts[ipt].Hits.size(); ++ii) {
3329 unsigned int iht = tj.
Pts[ipt].Hits[ii];
3330 if(slc.
slHits[iht].InTraj == oldTjID) HitInoTj =
true;
3335 if(tp.
Pos[1] > oTjPos1[indx]) ++nghPlus;
3336 if(firstPtInoTj == USHRT_MAX) firstPtInoTj = ipt;
3342 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;
3344 if(ngh < 0.2 * nMissedWires)
return false;
3345 if(firstPtInoTj > lastPtInoTj)
return false;
3348 if(!(nghPlus > 0.8 * ngh || nghPlus < 0.2 * ngh) )
return false;
3350 if(
tcc.
dbgStp)
mf::LogVerbatim(
"TC")<<
" Trajectory is a ghost of "<<oldTjID<<
" first point in oTj "<<firstPtInoTj<<
" last point "<<lastPtInoTj;
3353 for(
unsigned short ipt = firstPtInoTj; ipt <= lastPtInoTj; ++ipt) {
3354 if(tj.
Pts[ipt].Chg == 0)
continue;
3360 for(
unsigned short ipt = lastPtInoTj; ipt <= tj.
Pts.size(); ++ipt) {
3361 if(tj.
Pts[ipt].Chg > 0) ++ngh;
3365 for(
unsigned short ipt = lastPtInoTj; ipt <= tj.
EndPt[1]; ++ipt) {
3392 if(tHits.size() < 2)
return false;
3397 std::vector<unsigned int> hitsInMuliplet, nearbyHits;
3398 for(
auto iht : tHits) {
3401 for(
auto mht : hitsInMuliplet) {
3402 if(std::find(nearbyHits.begin(), nearbyHits.end(), mht) == nearbyHits.end()) {
3403 nearbyHits.push_back(mht);
3409 std::vector<unsigned int> tID, tCnt;
3410 for(
auto iht : nearbyHits) {
3411 if(slc.
slHits[iht].InTraj <= 0)
continue;
3412 unsigned int tid = slc.
slHits[iht].InTraj;
3413 unsigned short indx = 0;
3414 for(indx = 0; indx < tID.size(); ++indx)
if(tID[indx] == tid)
break;
3415 if(indx == tID.size()) {
3422 if(tCnt.empty())
return false;
3425 unsigned short tCut = 0.5 * tHits.size();
3430 myprt<<
"IsGhost tHits size "<<tHits.size()<<
" cut fraction "<<tCut<<
" tID_tCnt";
3431 for(
unsigned short ii = 0; ii < tCnt.size(); ++ii) myprt<<
" "<<tID[ii]<<
"_"<<tCnt[ii];
3434 for(
unsigned short ii = 0; ii < tCnt.size(); ++ii) {
3435 if(tCnt[ii] > tCut) {
3440 if(tid > (
int)slc.
tjs.size())
return false;
3445 for(
auto& tp : slc.
tjs[tid - 1].Pts) {
3446 for(
unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3447 unsigned int iht = tp.Hits[ii];
3448 if(slc.
slHits[iht].InTraj != 0)
continue;
3449 for(
unsigned short jj = 0; jj < tHits.size(); ++jj) {
3450 unsigned int tht = tHits[jj];
3451 if(tht != iht)
continue;
3452 tp.UseHit[ii] =
true;
3453 slc.
slHits[iht].InTraj = tid;
3468 if(slc.
tjs.size() < 2)
return;
3472 if(prt)
mf::LogVerbatim(
"TC")<<
"inside EndMerge slice "<<
slices.size()-1<<
" inCTP "<<inCTP<<
" nTjs "<<slc.
tjs.size()<<
" lastPass? "<<lastPass;
3475 short tccStepDir = 1;
3477 for(
auto& tj : slc.
tjs) {
3478 if(tj.AlgMod[
kKilled])
continue;
3479 if(tj.CTP != inCTP)
continue;
3480 if(tj.StepDir != tccStepDir)
ReverseTraj(slc, tj);
3486 std::vector<int> tjlist(2);
3492 bool iterate =
true;
3495 for(
unsigned int it1 = 0; it1 < slc.
tjs.size(); ++it1) {
3496 auto& tj1 = slc.
tjs[it1];
3497 if(tj1.AlgMod[
kKilled])
continue;
3498 if(tj1.CTP != inCTP)
continue;
3500 if(tj1.PDGCode == 111)
continue;
3501 for(
unsigned short end1 = 0; end1 < 2; ++end1) {
3503 if(tj1.VtxID[end1] > 0)
continue;
3505 TrajPoint tp1 = tj1.Pts[tj1.EndPt[end1]];
3507 if(lastPass && tp1.
NTPsFit > 3) {
3509 auto ttj = slc.
tjs[it1];
3510 auto& lastTP = ttj.Pts[ttj.EndPt[end1]];
3514 tp1 = ttj.Pts[ttj.EndPt[end1]];
3518 if(isVLA) bestFOM = 20;
3520 unsigned int imbest = INT_MAX;
3521 for(
unsigned int it2 = 0; it2 < slc.
tjs.size(); ++it2) {
3522 if(it1 == it2)
continue;
3523 auto& tj2 = slc.
tjs[it2];
3525 if(tj1.StepDir != tj2.StepDir)
continue;
3526 if(tj2.AlgMod[
kKilled])
continue;
3527 if(tj2.CTP != inCTP)
continue;
3529 if(tj2.PDGCode == 111)
continue;
3531 if(olf > 0.25)
continue;
3532 unsigned short end2 = 1 - end1;
3534 if(tj2.VtxID[end2] > 0)
continue;
3535 TrajPoint& tp2 = tj2.Pts[tj2.EndPt[end2]];
3536 TrajPoint& tp2OtherEnd = tj2.Pts[tj2.EndPt[end1]];
3538 if(std::abs(tp2OtherEnd.
Pos[0] - tp1.
Pos[0]) < std::abs(tp2.
Pos[0] - tp1.
Pos[0]))
continue;
3540 if(tj1.StepDir > 0) {
3541 if(tp2.
Pos[0] < tp1.
Pos[0] - 2)
continue;
3543 if(tp2.
Pos[0] > tp1.
Pos[0] + 2)
continue;
3555 unsigned short ipt1, ipt2;
3562 float fom = dang * doca;
3570 if(imbest == INT_MAX)
continue;
3573 unsigned int it2 = imbest;
3574 auto& tj2 = slc.
tjs[imbest];
3575 unsigned short end2 = 1 - end1;
3576 bool loMCSMom = (tj1.MCSMom + tj2.MCSMom) < 150;
3578 if(tj1.Pts.size() > 50 && tj1.MCSMom > 100) {
3580 tp1.
Ang = tj1.Pts[tj1.EndPt[0] + 2].Ang;
3582 tp1.
Ang = tj1.Pts[tj1.EndPt[1] - 2].Ang;
3584 }
else if(loMCSMom) {
3586 unsigned short pt1, pt2;
3598 TrajPoint tp2 = tj2.Pts[tj2.EndPt[end2]];
3599 if(tj2.Pts.size() > 50 && tj2.MCSMom > 100) {
3601 tp2.
Ang = tj2.Pts[tj2.EndPt[0] + 2].Ang;
3603 tp2.
Ang = tj2.Pts[tj2.EndPt[1] - 2].Ang;
3605 }
else if(loMCSMom) {
3607 unsigned short pt1, pt2;
3640 unsigned short e0 = tj1.EndPt[0];
3641 unsigned short e1 = tj1.EndPt[1];
3645 thetaRMS1 *= thetaRMS1 / tj1len;
3651 thetaRMS2 *= thetaRMS2 / tj2len;
3652 float dangErr = 0.5 * sqrt(thetaRMS1 + thetaRMS2);
3655 if(isVLA) docaCut = 15;
3668 bool doMerge = bestDOCA < docaCut && dang < dangCut;
3669 bool showerTjs = tj1.PDGCode == 11 || tj2.PDGCode == 11;
3670 bool hiMCSMom = tj1.MCSMom > 200 || tj2.MCSMom > 200;
3672 if(doMerge && !showerTjs && hiMCSMom && chgPull >
tcc.
chargeCuts[0] && !isVLA) doMerge =
false;
3674 if(!doMerge && tj1.MCSMom > 900 && tj2.MCSMom > 900 && dang < 0.1 && bestDOCA < docaCut) doMerge =
true;
3677 if(doMerge && chgPull > 2 * chgPullCut) doMerge =
false;
3683 auto& tp1OtherEnd = tj1.Pts[tj1.EndPt[1 - end1]];
3684 auto& tp2OtherEnd = tj2.Pts[tj2.EndPt[1 - end2]];
3685 float nwires = std::abs(tp1OtherEnd.Pos[0] - tp2OtherEnd.Pos[0]);
3686 if(nwires == 0) nwires = 1;
3687 float hitFrac = npwc / nwires;
3695 if(sep > len1) doMerge =
false;
3697 if(sep > len2) doMerge =
false;
3704 tjlist[0] = slc.
tjs[it1].ID;
3705 tjlist[1] = slc.
tjs[it2].ID;
3707 if(doMerge && bestDOCA > 1 && chgFrac < chgFracCut) doMerge =
false;
3710 if(doMerge && (tj1.StopFlag[end1][
kBragg] || tj2.StopFlag[end2][
kBragg])) doMerge =
false;
3713 float momAsym = std::abs(tj1.MCSMom - tj2.MCSMom) / (float)(tj1.MCSMom + tj2.MCSMom);
3714 if(doMerge && momAsym >
tcc.
vtx2DCuts[9]) doMerge =
false;
3718 myprt<<
"EM: T"<<slc.
tjs[it1].ID<<
"_"<<end1<<
" - T"<<slc.
tjs[it2].ID<<
"_"<<end2<<
" tp1-tp2 "<<
PrintPos(slc, tp1)<<
"-"<<
PrintPos(slc, tp2);
3720 myprt<<
" bestFOM "<<std::fixed<<std::setprecision(2)<<bestFOM;
3721 myprt<<
" bestDOCA "<<std::setprecision(1)<<bestDOCA;
3722 myprt<<
" cut "<<docaCut<<
" isVLA? "<<isVLA;
3723 myprt<<
" dang "<<std::setprecision(2)<<dang<<
" dangCut "<<dangCut;
3724 myprt<<
" chgPull "<<std::setprecision(1)<<chgPull<<
" Cut "<<chgPullCut;
3725 myprt<<
" chgFrac "<<std::setprecision(2)<<chgFrac;
3726 myprt<<
" momAsym "<<momAsym;
3727 myprt<<
" lastPass? "<<lastPass;
3728 myprt<<
" doMerge? "<<doMerge;
3731 if(bestDOCA > docaCut)
continue;
3735 bool didMerge =
false;
3743 tj1.AlgMod[
kMerge] =
true;
3744 tj2.AlgMod[
kMerge] =
true;
3753 aVtx.
CTP = slc.
tjs[it1].CTP;
3754 aVtx.
ID = slc.
vtxs.size() + 1;
3758 aVtx.
Pos[0] = 0.5 * (tp1.
Pos[0] + tp2.
Pos[0]);
3759 aVtx.
Pos[1] = 0.5 * (tp1.
Pos[1] + tp2.
Pos[1]);
3766 bool tj1Short = (slc.
tjs[it1].EndPt[1] - slc.
tjs[it1].EndPt[0] < maxShortTjLen);
3767 bool tj2Short = (slc.
tjs[it2].EndPt[1] - slc.
tjs[it2].EndPt[0] < maxShortTjLen);
3770 float dw = aVtx.
Pos[0] - tp1.
Pos[0];
3771 if(std::abs(dw) > sepCut)
continue;
3772 float dt = aVtx.
Pos[1] - tp1.
Pos[1];
3773 if(std::abs(dt) > sepCut)
continue;
3774 dw = aVtx.
Pos[0] - tp2.
Pos[0];
3775 if(std::abs(dw) > sepCut)
continue;
3776 dt = aVtx.
Pos[1] - tp2.
Pos[1];
3777 if(std::abs(dt) > sepCut)
continue;
3788 if(aVtx.
Pos[0] < tp1.
Pos[0] && aVtx.
Pos[0] < tp2.
Pos[0]) {
3792 if(aVtx.
Pos[0] > tp1.
Pos[0] && aVtx.
Pos[0] > tp2.
Pos[0]) {
3798 slc.
tjs[it1].VtxID[end1] = aVtx.
ID;
3799 slc.
tjs[it2].VtxID[end2] = aVtx.
ID;
3804 slc.
tjs[it1].VtxID[end1] = 0;
3805 slc.
tjs[it2].VtxID[end2] = 0;
3810 aVtx.
Pass = slc.
tjs[it1].Pass;
3811 aVtx.
Topo = end1 + end2;
3812 tj1.AlgMod[
kMerge] =
true;
3813 tj2.AlgMod[
kMerge] =
true;
3816 if(tj1.StopFlag[end1][kBragg] && !tj2.StopFlag[end2][kBragg]) tj1.PDGCode = 211;
3817 if(tj2.StopFlag[end2][kBragg] && !tj1.StopFlag[end1][kBragg]) tj2.PDGCode = 211;
3822 auto& newVx = slc.
vtxs[slc.
vtxs.size() - 1];
3826 auto& newVx2 = slc.
vtxs[slc.
vtxs.size() - 1];
3828 slc.
tjs[it1].VtxID[end1] = 0;
3829 slc.
tjs[it2].VtxID[end2] = 0;
3830 slc.
vtxs.pop_back();
3831 bool didMerge =
false;
3839 tj1.AlgMod[
kMerge] =
true;
3840 tj1.AlgMod[
kMerge] =
true;
3848 if(tj1.AlgMod[
kKilled])
break;
3894 if(tj.
Pts.size() < 3) {
3895 mf::LogError(
"TC")<<
"MaskTrajEndPoints: Trajectory ID "<<tj.
ID<<
" too short to mask hits ";
3899 if(nPts > tj.
Pts.size() - 2) {
3900 mf::LogError(
"TC")<<
"MaskTrajEndPoints: Trying to mask too many points "<<nPts<<
" Pts.size "<<tj.
Pts.size();
3906 unsigned short lastGoodPt = USHRT_MAX ;
3909 for(
unsigned short ii = 0; ii < tj.
Pts.size(); ++ii) {
3910 unsigned short ipt = tj.
EndPt[1] - nPts - ii;
3911 if(tj.
Pts[ipt].Chg > 0) {
3921 if(lastGoodPt == USHRT_MAX)
return;
3922 tj.
EndPt[1] = lastGoodPt;
3925 for(
unsigned short ii = 0; ii < tj.
Pts.size(); ++ii) {
3926 unsigned short ipt = tj.
Pts.size() - 1 - ii;
3927 if (ipt==lastGoodPt)
break;
3930 tj.
Pts[ipt].Dir = tj.
Pts[lastGoodPt].Dir;
3931 if(tj.
Pts[lastGoodPt].AngleCode == 2) {
3934 tj.
Pts[ipt].Pos[0] = tj.
Pts[lastGoodPt].Pos[0] + path * tj.
Pts[ipt].Dir[0];
3935 tj.
Pts[ipt].Pos[1] = tj.
Pts[lastGoodPt].Pos[1] + path * tj.
Pts[ipt].Dir[1];
3938 float dw = tj.
Pts[ipt].Pos[0] - tj.
Pts[lastGoodPt].Pos[0];
3940 float newpos = tj.
Pts[lastGoodPt].Pos[1] + dw * tj.
Pts[ipt].Dir[1] / tj.
Pts[ipt].Dir[0];
3941 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;
3942 tj.
Pts[ipt].Pos[1] = tj.
Pts[lastGoodPt].Pos[1] + dw * tj.
Pts[ipt].Dir[1] / tj.
Pts[ipt].Dir[0];
3967 if(tj.
MCSMom < 30)
return;
3972 if(tj.
Pts[tj.
EndPt[0]].AngleCode == 2 || tj.
Pts[tj.
EndPt[1]].AngleCode == 2)
return;
3975 if(tj.
Pts.size() < 6)
return;
3984 for(
unsigned short end = 0;
end < 2; ++
end) {
3988 unsigned short hiPt = 0;
3990 for(
unsigned short ii = 0; ii < 5; ++ii) {
3992 if(ipt < tj.
EndPt[0] || ipt > tj.
EndPt[1])
break;
4000 if(prt)
mf::LogVerbatim(
"TC")<<
" end "<<
end<<
" wire0 "<<wire0<<
" Chg "<<big<<
" hiPt "<<hiPt;
4001 float prevChg = big;
4005 float chgErr, chiDOF;
4007 Fit2D(0, inPt, chgErr, outVec, outVecErr, chiDOF);
4008 unsigned short cnt = 0;
4009 for(
unsigned short ii = 0; ii < tj.
Pts.size(); ++ii) {
4010 short ipt = hiPt + ii *
dir;
4011 if(ipt < tj.
EndPt[0] || ipt > tj.
EndPt[1])
break;
4013 if(tp.
Chg == 0)
continue;
4015 if(tp.
Chg > 1.5 * prevChg)
continue;
4018 inPt[0] = std::abs(tp.
Pos[0] - wire0);
4021 chgErr = 0.2 * tp.
Chg;
4022 if(!
Fit2D(2, inPt, chgErr, outVec, outVecErr, chiDOF))
break;
4025 if(cnt == nPtsToCheck)
break;
4027 if(cnt < 4)
continue;
4029 if(!
Fit2D(-1, inPt, chgErr, outVec, outVecErr, chiDOF))
continue;
4031 if(chiDOF > 500)
continue;
4034 outVec[1] = -outVec[1];
4040 if(prt)
mf::LogVerbatim(
"TC")<<
" end "<<
end<<
" fit chidof "<<chiDOF<<
" slope "<<outVec[1]<<
" +/- "<<outVecErr[1]<<
" stopping";
4042 if(prt)
mf::LogVerbatim(
"TC")<<
" end "<<
end<<
" fit chidof "<<chiDOF<<
" slope "<<outVec[1]<<
" +/- "<<outVecErr[1]<<
" Not stopping";
4056 unsigned short nmichelhits = 0;
4058 unsigned short nbragghits = 0;
4061 bool isfirsthit =
true;
4062 unsigned short braggpeak = 0;
4064 for(
unsigned short ii = 0; ii < tj.
Pts.size(); ++ii) {
4065 if (ii>tj.
EndPt[1])
continue;
4066 unsigned short ipt = tj.
EndPt[1] - ii;
4067 if (tj.
Pts[ipt].Chg>0){
4070 if (tj.
Pts[ipt].ChgPull<0){
4075 if (tj.
Pts[ipt].ChgPull<0&&nmichelhits&&!nbragghits){
4081 lastChg = tj.
Pts[ipt].Chg;
4084 else if (tj.
Pts[ipt].Chg<lastChg){
4086 lastChg = tj.
Pts[ipt].Chg;
4093 if(prt)
mf::LogVerbatim(
"TC")<<
"ChkMichel Michel hits: "<<nmichelhits<<
" Bragg peak hits: "<<nbragghits;
4094 if (nmichelhits>0&&nbragghits>2){
4095 lastGoodPt = braggpeak;
4110 for(
size_t i = 0; i< slc.
tjs.size(); ++i) {
4111 auto & tj = slc.
tjs[i];
4112 if(tj.CTP != inCTP)
continue;
4113 if(tj.AlgMod[
kKilled])
continue;
4128 if (tj.
EndPt[1]<10)
return;
4132 for(
unsigned short end = 0;
end < 2; ++
end) {
4136 unsigned short nlohits = 0;
4137 unsigned short lastHiTP = USHRT_MAX;
4146 else if (ptchg>0.4*hichg){
4165 if (nlohits>4&&lastHiTP!=USHRT_MAX){
4168 aVtx.
Pos = tj.
Pts[lastHiTP].Pos;
4174 aVtx.
ID = slc.
vtxs.size() + 1;
4182 newTj.
ID = slc.
tjs.size() + 1;
4185 unsigned short tp1 = lastHiTP+1;
4186 if (
end==1) tp1 = lastHiTP-1;
4188 tj.
Pts[ipt].Chg = 0;
4189 for (
unsigned short ii = 0; ii < tj.
Pts[ipt].Hits.size(); ++ii) {
4190 if(!tj.
Pts[ipt].UseHit[ii])
continue;
4191 unsigned int iht = tj.
Pts[ipt].Hits[ii];
4193 if(slc.
slHits[iht].InTraj != tj.
ID)
continue;
4195 tj.
Pts[ipt].UseHit[ii] =
false;
4206 newTj.
Pts[ipt].Chg = 0;
4207 for (
unsigned short ii = 0; ii < newTj.
Pts[ipt].Hits.size(); ++ii) {
4208 newTj.
Pts[ipt].UseHit[ii] =
false;
4214 slc.
tjs.push_back(newTj);
4228 if(tHits.size() < 2)
return false;
4235 unsigned short pass =
tcc.
minPts.size() - 1;
4236 if(!
StartTraj(slc, work, tHits[0], tHits[tHits.size()-1], pass))
return false;
4238 work.
Pts.resize(tHits.size());
4242 float inPtErr = 1, chiDOF;
4244 Fit2D(0, inPt, inPtErr, outVec, outVecErr, chiDOF);
4245 std::vector<Point2_t> fitPts(tHits.size());
4246 for(
unsigned short ii = 0; ii < tHits.size(); ++ii) {
4247 unsigned int iht = tHits[ii];
4248 if(slc.
slHits[iht].InTraj == SHRT_MAX)
return false;
4250 inPt[0] =
hit.WireID().Wire;
4254 Fit2D(1, inPt, inPtErr, outVec, outVecErr, chiDOF);
4256 if(!
Fit2D(-1, inPt, inPtErr, outVec, outVecErr, chiDOF))
return false;
4258 if(prt)
mf::LogVerbatim(
"TC")<<
" tHits line fit Angle "<<atan(outVec[1]);
4260 work.
Pts[0].Ang = atan(outVec[1]);
4261 work.
Pts[0].Dir[0] = cos(work.
Pts[0].Ang);
4262 work.
Pts[0].Dir[1] = sin(work.
Pts[0].Ang);
4265 for(
unsigned short ipt = 1; ipt < work.
Pts.size(); ++ipt) {
4266 auto& tp = work.
Pts[ipt];
4268 tp.Ang = work.
Pts[0].Ang;
4269 tp.Dir = work.
Pts[0].Dir;
4270 tp.AngleCode = work.
Pts[0].AngleCode;
4274 double cs = cos(-work.
Pts[0].Ang);
4275 double sn = sin(-work.
Pts[0].Ang);
4276 float tAlong, minAlong = 1E6, maxAlong = -1E6;
4278 std::vector<SortEntry> sortVec(tHits.size());
4280 for(
unsigned short ii = 0; ii < fitPts.size(); ++ii) {
4281 tAlong = cs * fitPts[ii][0] - sn * fitPts[ii][1];
4282 if(tAlong < minAlong) minAlong = tAlong;
4283 if(tAlong > maxAlong) maxAlong = tAlong;
4284 sortEntry.index = ii;
4285 sortEntry.val = tAlong;
4286 sortVec[ii] = sortEntry;
4290 for(
unsigned short ipt = 0; ipt < work.
Pts.size(); ++ipt) {
4291 auto& tp = work.
Pts[ipt];
4293 tp.Hits[0] = tHits[sortVec[ipt].index];
4294 tp.UseHit[0] =
true;
void PrintTrajectory(std::string someText, TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
float HitsRMSTime(TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
float AveChg
Calculated using ALL hits.
void ReleaseHits(TCSlice &slc, Trajectory &tj)
float HitsRMSTick(TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
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)
bool MakeBareTrajPoint(TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
void FixTrajEnd(TCSlice &slc, Trajectory &tj, unsigned short atPt)
std::vector< float > kinkCuts
kink angle, nPts fit, (alternate) kink angle significance
void FindSoftKink(TCSlice &slc, Trajectory &tj)
bool valsDecreasing(SortEntry c1, SortEntry c2)
struct of temporary 2D vertices (end points)
CTP_t CTP
Cryostat, TPC, Plane code.
std::vector< float > maxPos0
std::vector< unsigned short > minPtsFit
Reconstruct in several passes.
bool FitVertex(TCSlice &slc, VtxStore &vx, bool prt)
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
std::vector< float > qualityCuts
Min points/wire, min consecutive pts after a gap.
void AddHits(TCSlice &slc, Trajectory &tj, unsigned short ipt, bool &sigOK)
std::vector< unsigned int > PutTrajHitsInVector(Trajectory const &tj, HitStatus_t hitRequest)
vertex position fixed manually - no fitting done
std::array< std::bitset< 8 >, 2 > StopFlag
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)
void SetStrategy(TCSlice &slc, Trajectory &tj)
bool StoreTraj(TCSlice &slc, Trajectory &tj)
float TotChg
Total including an estimate for dead wires.
void FillGaps(TCSlice &slc, Trajectory &tj)
float maxWireSkipWithSignal
max number of wires to skip with a signal on them
bool IsGhost(TCSlice &slc, std::vector< unsigned int > &tHits)
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(TrajPoint &tp1, TrajPoint &tp2)
void SetAngleCode(TrajPoint &tp)
bool MakeJunkTraj(TCSlice &slc, std::vector< unsigned int > tHits)
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
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
float DeadWireCount(TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
bool StoreVertex(TCSlice &slc, VtxStore &vx)
bool doForecast
See TCMode_t above.
bool TrajTrajDOCA(TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
unsigned short Pass
the pass on which it was created
void HiEndDelta(TCSlice &slc, Trajectory &tj)
int TDCtick_t
Type representing a TDC tick.
std::vector< std::vector< std::pair< int, int > > > wireHitRange
std::vector< unsigned short > maxAngleCode
max allowed angle code for each pass
float projectionErrFactor
const std::vector< std::string > StrategyBitNames
std::vector< unsigned int > FindCloseHits(TCSlice &slc, std::array< int, 2 > const &wireWindow, Point2_t const &timeWindow, const unsigned short plane, HitStatus_t hitRequest, bool usePeakTime, bool &hitsNear)
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.
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
CTP_t CTP
Cryostat, TPC, Plane code.
bool SignalBetween(TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction)
void SplitHiChgHits(TCSlice &slc, Trajectory &tj)
void CheckStiffEl(TCSlice &slc, Trajectory &tj)
bool dbg2V
debug 2D vertex finding
std::vector< float > aveHitRMS
average RMS of an isolated hit
std::vector< TrajPoint > Pts
Trajectory points.
float TrajLength(Trajectory &tj)
void FixTrajBegin(TCSlice &slc, Trajectory &tj, unsigned short atPt)
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}
bool SignalAtTp(TCSlice &slc, const TrajPoint &tp)
void TagJunkTj(TCSlice &slc, Trajectory &tj, bool prt)
void ChkHiChgHits(TCSlice &slc, CTP_t inCTP)
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)
void SetPDGCode(TCSlice &slc, unsigned short itj, bool tjDone)
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
float TpSumHitChg(TCSlice &slc, TrajPoint const &tp)
PlaneID_t Plane
Index of the plane within its TPC.
void GottaKink(TCSlice &slc, Trajectory &tj, unsigned short &killPts)
std::array< double, 2 > Vector2_t
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)
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)
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
void ChkStop(TCSlice &slc, Trajectory &tj)
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
std::bitset< 16 > modes
number of points to find AveChg
float HitTimeErr(TCSlice &slc, unsigned int iht)
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 ChgFracNearPos(TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
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)
std::vector< TjForecast > tjfs
float MCSThetaRMS(TCSlice &slc, Trajectory &tj)
void AddLAHits(TCSlice &slc, Trajectory &tj, unsigned short ipt, bool &sigOK)
bool AttachTrajToVertex(TCSlice &slc, Trajectory &tj, VtxStore &vx, bool prt)
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
float HitsTimeErr2(TCSlice &slc, const std::vector< unsigned int > &hitVec)
bool HasDuplicateHits(TCSlice &slc, Trajectory const &tj, bool prt)
void CheckHiMultUnusedHits(TCSlice &slc, Trajectory &tj)
void ChgSlope(TCSlice &slc, Trajectory &tj, float &slope, float &slopeErr, float &chiDOF)
std::vector< VtxStore > vtxs
2D vertices
short StepDir
-1 = going US (-> small wire#), 1 = going DS (-> large wire#)
float MaxHitDelta(TCSlice &slc, Trajectory &tj)
std::bitset< 128 > AlgMod
Bit set if algorithm AlgBit_t modifed the trajectory.
std::vector< short > muonTag
min length and min MCSMom for a muon tag
void Forecast(TCSlice &slc, Trajectory &tj)
geo::PlaneID DecodeCTP(CTP_t CTP)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
std::vector< recob::Hit > const * allHits
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
float OverlapFraction(TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2)
float TPHitsRMSTick(TCSlice &slc, TrajPoint &tp, HitStatus_t hitRequest)
std::vector< unsigned int > nWires
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
use the stiff electron strategy
std::vector< float > chkStopCuts
[Min Chg ratio, Chg slope pull cut, Chg fit chi cut]
void EndMerge(TCSlice &slc, CTP_t inCTP, bool lastPass)
unsigned short TPNearVertex(TCSlice &slc, const TrajPoint &tp)
void GetHitMultiplet(TCSlice &slc, unsigned int theHit, std::vector< unsigned int > &hitsInMultiplet, unsigned short &localIndex)
void SetVx2Score(TCSlice &slc)
std::string PrintStopFlag(const Trajectory &tj, unsigned short end)
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
std::bitset< 8 > Strategy
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
float multHitSep
preferentially "merge" hits with < this separation
void MoveTPToWire(TrajPoint &tp, float wire)
void MaskTrajEndPoints(TCSlice &slc, Trajectory &tj, unsigned short nPts)
void UpdateDeltaRMS(TCSlice &slc, Trajectory &tj)
void ChkStopEndPts(TCSlice &slc, Trajectory &tj, bool prt)
void ReversePropagate(TCSlice &slc, Trajectory &tj)
bool NeedsUpdate
Set true when the Tj needs to be updated.
void CheckHiMultEndHits(TCSlice &slc, Trajectory &tj)
void PrintTrajPoint(std::string someText, TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
void ChkVxTjs(TCSlice &slc, const CTP_t &inCTP, bool prt)
CTP_t CTP
set to an invalid CTP
unsigned short AngleRange(TrajPoint const &tp)
use the stiff muon strategy
bool CompatibleMerge(TCSlice &slc, std::vector< int > &tjIDs, bool prt)
bool ChkMichel(TCSlice &slc, Trajectory &tj, unsigned short &lastGoodPt)