48 return c1.length > c2.length;
57 fNumPass = pset.
get<
unsigned short>(
"NumPass", 0);
58 fMaxHitsFit = pset.
get<std::vector<unsigned short>>(
"MaxHitsFit");
59 fMinHits = pset.
get<std::vector<unsigned short>>(
"MinHits");
60 fNHitsAve = pset.
get<std::vector<unsigned short>>(
"NHitsAve");
61 fChgCut = pset.
get<std::vector<float>>(
"ChgCut");
62 fChiCut = pset.
get<std::vector<float>>(
"ChiCut");
63 fMaxWirSkip = pset.
get<std::vector<unsigned short>>(
"MaxWirSkip");
64 fMinWirAfterSkip = pset.
get<std::vector<unsigned short>>(
"MinWirAfterSkip");
65 fKinkChiRat = pset.
get<std::vector<float>>(
"KinkChiRat");
66 fKinkAngCut = pset.
get<std::vector<float>>(
"KinkAngCut");
67 fDoMerge = pset.
get<std::vector<bool>>(
"DoMerge");
68 fTimeDelta = pset.
get<std::vector<float>>(
"TimeDelta");
69 fMergeChgCut = pset.
get<std::vector<float>>(
"MergeChgCut");
70 fFindVertices = pset.
get<std::vector<bool>>(
"FindVertices");
71 fLACrawl = pset.
get<std::vector<bool>>(
"LACrawl");
72 fMinAmp = pset.
get<std::vector<float>>(
"MinAmp", {5, 5, 5});
73 fChgNearWindow = pset.
get<
float>(
"ChgNearWindow");
74 fChgNearCut = pset.
get<
float>(
"ChgNearCut");
76 fChkClusterDS = pset.
get<
bool>(
"ChkClusterDS",
false);
77 fVtxClusterSplit = pset.
get<
bool>(
"VtxClusterSplit",
false);
78 fFindStarVertices = pset.
get<
bool>(
"FindStarVertices",
false);
79 if (pset.
has_key(
"HammerCluster")) {
81 <<
"fcl setting HammerCluster is replaced by FindHammerClusters. Ignoring...";
83 fFindHammerClusters = pset.
get<
bool>(
"FindHammerClusters",
false);
84 fKillGarbageClusters = pset.
get<
float>(
"KillGarbageClusters", 0);
85 fRefineVertexClusters = pset.
get<
bool>(
"RefineVertexClusters",
false);
86 fHitErrFac = pset.
get<
float>(
"HitErrFac", 0.2);
87 fHitMinAmp = pset.
get<
float>(
"HitMinAmp", 0.2);
88 fClProjErrFac = pset.
get<
float>(
"ClProjErrFac", 4);
89 fMinHitFrac = pset.
get<
float>(
"MinHitFrac", 0.6);
91 fLAClusAngleCut = pset.
get<
float>(
"LAClusAngleCut", 45);
92 fLAClusMaxHitsFit = pset.
get<
unsigned short>(
"LAClusMaxHitsFit");
93 fMergeAllHits = pset.
get<
bool>(
"MergeAllHits",
false);
94 fHitMergeChiCut = pset.
get<
float>(
"HitMergeChiCut", 2.5);
95 fMergeOverlapAngCut = pset.
get<
float>(
"MergeOverlapAngCut");
96 fAllowNoHitWire = pset.
get<
unsigned short>(
"AllowNoHitWire", 0);
97 fVertex2DCut = pset.
get<
float>(
"Vertex2DCut", 5);
98 fVertex2DWireErrCut = pset.
get<
float>(
"Vertex2DWireErrCut", 5);
99 fVertex3DCut = pset.
get<
float>(
"Vertex3DCut", 5);
101 fDebugPlane = pset.
get<
int>(
"DebugPlane", -1);
102 fDebugWire = pset.
get<
int>(
"DebugWire", -1);
103 fDebugHit = pset.
get<
int>(
"DebugHit", -1);
106 bool badinput =
false;
107 if (fNumPass > fMaxHitsFit.size()) badinput =
true;
108 if (fNumPass > fMinHits.size()) badinput =
true;
109 if (fNumPass > fNHitsAve.size()) badinput =
true;
110 if (fNumPass > fChgCut.size()) badinput =
true;
111 if (fNumPass > fChiCut.size()) badinput =
true;
112 if (fNumPass > fMaxWirSkip.size()) badinput =
true;
113 if (fNumPass > fMinWirAfterSkip.size()) badinput =
true;
114 if (fNumPass > fKinkChiRat.size()) badinput =
true;
115 if (fNumPass > fKinkAngCut.size()) badinput =
true;
116 if (fNumPass > fDoMerge.size()) badinput =
true;
117 if (fNumPass > fTimeDelta.size()) badinput =
true;
118 if (fNumPass > fMergeChgCut.size()) badinput =
true;
119 if (fNumPass > fFindVertices.size()) badinput =
true;
120 if (fNumPass > fLACrawl.size()) badinput =
true;
124 <<
"ClusterCrawlerAlg: Bad input from fcl file";
140 if (cmp_res != 0)
return cmp_res < 0;
149 ClusterCrawlerAlg::ClearResults()
160 ClusterCrawlerAlg::CrawlInit()
186 WireHitRange.clear();
193 ClusterCrawlerAlg::ClusterInit()
210 std::vector<recob::Hit>
const& srchits)
218 if (fHits.size() < 3)
return;
219 if (fHits.size() > UINT_MAX) {
220 mf::LogWarning(
"CC") <<
"Too many hits for ClusterCrawler " << fHits.size();
225 if (fNumPass == 0)
return;
230 std::sort(fHits.begin(), fHits.end(), &SortByMultiplet);
232 inClus.resize(fHits.size());
233 mergeAvailable.resize(fHits.size());
234 for (
unsigned int iht = 0; iht < inClus.size(); ++iht) {
236 mergeAvailable[iht] =
false;
239 for (
geo::TPCID const& tpcid : geom->IterateTPCIDs()) {
241 for (plane = 0; plane < TPC.
Nplanes(); ++plane) {
242 WireHitRange.clear();
244 clCTP =
EncodeCTP(tpcid.Cryostat, tpcid.TPC, plane);
245 cstat = tpcid.Cryostat;
252 if (WireHitRange.empty() || (fFirstWire == fLastWire))
continue;
256 float wirePitch = geom->WirePitch(geom->View(channel));
259 fScaleF = tickToDist / wirePitch;
261 if (fLAClusAngleCut > 0)
262 fLAClusSlopeCut = std::tan(3.142 * fLAClusAngleCut / 180.) / fScaleF;
264 fNumWires = geom->Nwires(plane, tpc, cstat);
266 if (fNumPass > 0) ClusterLoop();
268 if (fVertex3DCut > 0) {
270 VtxMatch(clock_data, det_prop, tpcid);
271 Vtx3ClusterMatch(clock_data, det_prop, tpcid);
272 if (fFindHammerClusters) FindHammerClusters(clock_data, det_prop);
274 Vtx3ClusterSplit(clock_data, det_prop, tpcid);
276 if (fDebugPlane >= 0) {
283 WireHitRange.clear();
290 RemoveObsoleteHits();
296 ClusterCrawlerAlg::ClusterLoop()
300 unsigned int nHitsUsed = 0, iwire, jwire, kwire;
301 bool AllDone =
false, SigOK =
false, HitOK =
false;
302 unsigned int ihit, jhit;
303 for (
unsigned short thispass = 0; thispass < fNumPass; ++thispass) {
306 unsigned int span = 3;
307 if (fMinHits[
pass] < span) span = fMinHits[
pass];
308 for (iwire = fLastWire; iwire > fFirstWire +
span; --iwire) {
310 if (WireHitRange[iwire].first < 0)
continue;
311 auto ifirsthit = (
unsigned int)WireHitRange[iwire].first;
312 auto ilasthit = (
unsigned int)WireHitRange[iwire].
second;
313 for (ihit = ifirsthit; ihit < ilasthit; ++ihit) {
314 bool ClusterAdded =
false;
317 if (ihit > fHits.size() - 1) {
318 mf::LogError(
"CC") <<
"ClusterLoop bad ihit " << ihit <<
" fHits size " << fHits.size();
322 if (inClus[ihit] != 0)
continue;
324 if (fHits[ihit].PeakAmplitude() < fHitMinAmp)
continue;
325 if ((iwire + 1) < span)
continue;
326 jwire = iwire - span + 1;
330 if (WireHitRange[jwire].first == -2)
continue;
331 if (WireHitRange[jwire].first == -1) {
333 unsigned int nmissed = 0;
334 while (WireHitRange[jwire].first == -1 && jwire > 1 && nmissed < fMaxWirSkip[
pass]) {
340 <<
" new jwire " << jwire <<
" dead? " << WireHitRange[jwire].first;
341 if (WireHitRange[jwire].first < 0)
continue;
345 unsigned int useHit = 0;
346 bool doConstrain =
false;
347 VtxConstraint(iwire, ihit, jwire, useHit, doConstrain);
348 unsigned int jfirsthit = (
unsigned int)WireHitRange[jwire].first;
349 unsigned int jlasthit = (
unsigned int)WireHitRange[jwire].
second;
350 if (jfirsthit > fHits.size() - 1 || jfirsthit > fHits.size() - 1)
352 <<
"ClusterLoop jwire " << jwire <<
" bad firsthit " << jfirsthit <<
" lasthit " 353 << jlasthit <<
" fhits size " << fHits.size();
354 for (jhit = jfirsthit; jhit < jlasthit; ++jhit) {
355 if (jhit > fHits.size() - 1)
357 <<
"ClusterLoop bad jhit " << jhit <<
" firsthit " << jfirsthit <<
" lasthit " 358 << jlasthit <<
" fhits size" << fHits.size();
360 if (doConstrain && jhit != useHit)
continue;
363 if (inClus[jhit] != 0)
continue;
365 if (fHits[jhit].PeakAmplitude() < fHitMinAmp)
continue;
368 fcl2hits.push_back(ihit);
369 chifits.push_back(0.);
370 hitNear.push_back(0);
371 chgNear.push_back(0);
373 fcl2hits.push_back(jhit);
374 chifits.push_back(0.);
375 hitNear.push_back(0);
376 chgNear.push_back(0);
381 clparerr[1] = 0.2 *
std::abs(clpar[1]);
382 clpar[2] = fHits[jhit].WireID().Wire;
386 for (kwire = jwire + 1; kwire < iwire; ++kwire) {
388 if (CrawlVtxChk(kwire)) {
392 AddHit(kwire, HitOK, SigOK);
394 mf::LogVerbatim(
"CC") <<
" HitOK " << HitOK <<
" clChisq " << clChisq <<
" cut " 395 << fChiCut[
pass] <<
" ClusterHitsOK " << ClusterHitsOK(-1);
399 if (clChisq > 2)
break;
401 if (!ClusterHitsOK(-1))
continue;
406 prt = (fDebugPlane == (
int)plane && (
int)iwire == fDebugWire &&
410 <<
"ADD >>>>> Starting cluster with hits " <<
PrintHit(fcl2hits[0]) <<
" " 415 clBeginSlp = clpar[1];
418 if (!fLACrawl[
pass] &&
std::abs(clBeginSlp) > fLAClusSlopeCut)
continue;
421 if (CrawlVtxChk2())
continue;
422 clBeginSlpErr = clparerr[1];
427 for (
unsigned short kk = 0; kk < fcl2hits.size(); ++kk) {
428 fAveHitWidth += fHits[fcl2hits[kk]].EndTick() - fHits[fcl2hits[kk]].StartTick();
429 chg += fHits[fcl2hits[kk]].Integral();
431 fAveHitWidth /= (
float)fcl2hits.size();
437 if (fLACrawl[
pass] && fLAClusSlopeCut > 0) {
439 if (
std::abs(clBeginSlp) > fLAClusSlopeCut) { LACrawlUS(); }
448 if (fcl2hits.size() >= fMinHits[
pass]) {
451 clEndSlpErr = clparerr[1];
454 mf::LogError(
"CC") <<
"Failed to store cluster in plane " << plane;
458 nHitsUsed += fcl2hits.size();
459 AllDone = (nHitsUsed == fHits.size());
466 if (ClusterAdded || AllDone)
break;
474 if (fDoMerge[
pass]) ChkMerge();
476 if (fFindVertices[pass]) FindVertices();
483 if (fKillGarbageClusters > 0 && !
tcl.empty()) KillGarbageClusters();
487 if (fChkClusterDS) ChkClusterDS();
489 if (fVtxClusterSplit) {
490 bool didSomething = VtxClusterSplit();
492 if (didSomething) VtxClusterSplit();
495 if (fFindStarVertices) FindStarVertices();
497 if (fDebugPlane == (
int)plane) {
502 CheckHitClusterAssociations();
508 ClusterCrawlerAlg::KillGarbageClusters()
512 if (
tcl.size() < 2)
return;
514 unsigned short icl, jcl;
517 std::vector<float> iHits, jHits;
521 float sepcut = 0, iFrac, jFrac;
523 unsigned short iLoIndx, jLoIndx, olapSize, iop, ii, jj;
524 unsigned short nclose;
527 std::vector<unsigned short> killMe;
529 for (icl = 0; icl <
tcl.size() - 1; ++icl) {
530 if (
tcl[icl].
ID < 0)
continue;
531 if (
tcl[icl].CTP != clCTP)
continue;
535 iHits.resize(
tcl[icl].BeginWir -
tcl[icl].EndWir + 1, 1000);
537 for (
auto iht :
tcl[icl].tclhits) {
538 indx = fHits[iht].WireID().Wire -
tcl[icl].EndWir;
539 if (indx > iHits.size() - 1) {
540 mf::LogWarning(
"CC") <<
"KillGarbageClusters: icl ID " <<
tcl[icl].ID <<
" Bad indx " 541 << indx <<
" " << iHits.size() <<
"\n";
544 iHits[indx] = fHits[iht].PeakTime();
545 iChg += fHits[iht].Integral();
546 if (first) sepcut += fHits[iht].RMS();
549 sepcut /= (
float)
tcl[icl].tclhits.size();
555 for (jcl = icl + 1; jcl <
tcl.size(); ++jcl) {
556 if (
tcl[jcl].
ID < 0)
continue;
557 if (
tcl[jcl].CTP != clCTP)
continue;
559 if (
tcl[icl].BeginWir <
tcl[jcl].EndWir)
continue;
560 if (
tcl[icl].EndWir >
tcl[jcl].BeginWir)
continue;
562 if (
std::abs(
tcl[icl].BeginAng -
tcl[jcl].BeginAng) > fKillGarbageClusters)
continue;
564 if (
tcl[icl].EndWir <
tcl[jcl].EndWir) {
568 iLoIndx =
tcl[jcl].EndWir -
tcl[icl].EndWir;
570 if (
tcl[icl].BeginWir <
tcl[jcl].BeginWir) {
574 olapSize =
tcl[icl].BeginWir -
tcl[jcl].EndWir + 1;
580 olapSize =
tcl[jcl].BeginWir -
tcl[jcl].EndWir + 1;
588 jLoIndx =
tcl[icl].EndWir -
tcl[icl].EndWir;
589 if (
tcl[icl].BeginWir <
tcl[jcl].BeginWir) {
593 olapSize =
tcl[icl].BeginWir -
tcl[icl].EndWir + 1;
599 olapSize =
tcl[jcl].BeginWir -
tcl[icl].EndWir + 1;
604 jHits.resize(
tcl[jcl].BeginWir -
tcl[jcl].EndWir + 1, -1000);
606 for (
auto jht :
tcl[jcl].tclhits) {
607 indx = fHits[jht].WireID().Wire -
tcl[jcl].EndWir;
608 if (indx > jHits.size() - 1) {
609 mf::LogWarning(
"CC") <<
"KillGarbageClusters: jcl ID " <<
tcl[jcl].ID <<
" Bad indx " 610 << indx <<
" " << jHits.size() <<
"\n";
613 jHits[indx] = fHits[jht].PeakTime();
614 jChg += fHits[jht].Integral();
618 for (iop = 0; iop < olapSize; ++iop) {
620 if (ii > iHits.size() - 1)
continue;
622 if (jj > jHits.size() - 1)
continue;
623 if (
std::abs(iHits[ii] - jHits[jj]) < sepcut) ++nclose;
625 iFrac = (
float)nclose / (
float)iHits.size();
626 jFrac = (
float)nclose / (
float)jHits.size();
627 if (iFrac < 0.5 && jFrac < 0.5)
continue;
628 doKill = (iFrac < jFrac && iChg > jChg);
629 if (doKill) killMe.push_back(jcl);
633 if (killMe.size() == 0)
return;
634 for (
auto icl : killMe) {
636 if (
tcl[icl].
ID < 0)
continue;
637 tcl[icl].ProcCode = 666;
638 MakeClusterObsolete(icl);
658 unsigned short icl, jcl;
660 bool chkprt = (fDebugWire == 666);
661 if (chkprt)
mf::LogVerbatim(
"CC") <<
"Inside MergeOverlap using clCTP " << clCTP;
663 unsigned short minLen = 6;
664 unsigned short minOvrLap = 2;
667 float maxDTick = fTimeDelta[fTimeDelta.size() - 1];
669 unsigned int overlapSize, ii, indx, bWire, eWire;
670 unsigned int iht, jht;
671 float dang, prtime, dTick;
672 for (icl = 0; icl <
tcl.size(); ++icl) {
673 if (
tcl[icl].
ID < 0)
continue;
674 if (
tcl[icl].CTP != clCTP)
continue;
675 prt = chkprt && fDebugPlane == (
int)clCTP;
676 if (
tcl[icl].BeginVtx >= 0)
continue;
677 if (
tcl[icl].tclhits.size() < minLen)
continue;
678 for (jcl = 0; jcl <
tcl.size(); ++jcl) {
679 if (icl == jcl)
continue;
680 if (
tcl[jcl].
ID < 0)
continue;
681 if (
tcl[jcl].CTP != clCTP)
continue;
682 if (
tcl[jcl].EndVtx >= 0)
continue;
683 if (
tcl[jcl].tclhits.size() < minLen)
continue;
685 if (
tcl[icl].BeginWir <
tcl[jcl].EndWir + minOvrLap)
continue;
687 if (
tcl[icl].BeginWir >
tcl[jcl].BeginWir - minOvrLap)
continue;
689 if (
tcl[jcl].EndWir <
tcl[icl].EndWir + minOvrLap)
continue;
693 <<
tcl[jcl].ID <<
" dang " << dang;
694 if (dang > 0.5)
continue;
695 overlapSize =
tcl[icl].BeginWir -
tcl[jcl].EndWir + 1;
696 eWire =
tcl[jcl].EndWir;
697 bWire =
tcl[icl].BeginWir;
700 <<
"-" <<
tcl[icl].BeginWir <<
" jcl ID " <<
tcl[jcl].ID <<
" " 701 <<
tcl[jcl].EndWir <<
"-" <<
tcl[jcl].BeginWir <<
" overlapSize " 702 << overlapSize <<
" bWire " << bWire <<
" eWire " << eWire;
705 for (ii = 0; ii <
tcl[icl].tclhits.size(); ++ii) {
706 iht =
tcl[icl].tclhits[ii];
707 if (fHits[iht].
WireID().Wire < eWire)
break;
710 dTick =
std::abs(fHits[iht].PeakTime() -
tcl[jcl].EndTim);
711 if (dTick > maxDTick)
continue;
714 <<
tcl[jcl].EndTim <<
" dTick " << dTick;
715 for (ii = 0; ii <
tcl[jcl].tclhits.size(); ++ii) {
716 jht =
tcl[jcl].tclhits[
tcl[jcl].tclhits.size() - ii - 1];
719 dTick =
std::abs(fHits[jht].PeakTime() -
tcl[icl].BeginTim);
720 if (dTick > maxDTick)
continue;
723 <<
tcl[icl].BeginTim <<
" dTick " << dTick;
725 clpar[0] = fHits[iht].PeakTime();
726 clpar[2] = fHits[iht].WireID().Wire;
727 clpar[1] = (fHits[jht].PeakTime() - fHits[iht].PeakTime()) /
728 ((
float)fHits[jht].WireID().Wire - clpar[2]);
730 std::vector<unsigned int> oWireHits(overlapSize, INT_MAX);
731 std::vector<float> delta(overlapSize, maxDTick);
732 for (ii = 0; ii <
tcl[icl].tclhits.size(); ++ii) {
733 iht =
tcl[icl].tclhits[ii];
734 if (fHits[iht].
WireID().Wire < eWire)
break;
735 prtime = clpar[0] + clpar[1] * ((
float)fHits[iht].
WireID().Wire - clpar[2]);
736 dTick =
std::abs(fHits[iht].PeakTime() - prtime);
737 indx = fHits[iht].WireID().Wire - eWire;
738 if (dTick > delta[indx])
continue;
740 oWireHits[indx] = iht;
743 for (ii = 0; ii <
tcl[jcl].tclhits.size(); ++ii) {
744 jht =
tcl[jcl].tclhits[
tcl[jcl].tclhits.size() - ii - 1];
746 prtime = clpar[0] + clpar[1] * ((
float)fHits[jht].
WireID().Wire - clpar[2]);
747 dTick =
std::abs(fHits[jht].PeakTime() - prtime);
748 indx = fHits[jht].WireID().Wire - eWire;
749 if (dTick > delta[indx])
continue;
751 oWireHits[indx] = jht;
755 for (ii = 0; ii < oWireHits.size(); ++ii) {
756 if (oWireHits[ii] == INT_MAX)
continue;
758 fcl2hits.push_back(iht);
761 if (fcl2hits.size() < 0.5 * overlapSize)
continue;
762 if (fcl2hits.size() < 3)
continue;
763 std::sort(fcl2hits.begin(), fcl2hits.end(),
SortByLowHit);
766 mf::LogVerbatim(
"CC") <<
" Overlap size " << overlapSize <<
" fit chisq " << clChisq
767 <<
" nhits " << fcl2hits.size();
768 if (clChisq > 20)
continue;
770 std::vector<unsigned int> oHits = fcl2hits;
774 unsigned short jclNewSize;
775 for (jclNewSize = 0; jclNewSize < fcl2hits.size(); ++jclNewSize) {
776 iht = fcl2hits[jclNewSize];
777 if (fHits[iht].
WireID().Wire <= bWire)
break;
780 mf::LogVerbatim(
"CC") <<
"jcl old size " << fcl2hits.size() <<
" newSize " << jclNewSize;
781 iht = fcl2hits[fcl2hits.size() - 1];
782 unsigned int iiht = fcl2hits[jclNewSize - 1];
783 mf::LogVerbatim(
"CC") <<
"jcl old last wire " << fHits[iht].WireID().Wire
784 <<
" After resize last wire " << fHits[iiht].WireID().Wire;
786 fcl2hits.resize(jclNewSize);
788 fcl2hits.insert(fcl2hits.end(), oHits.begin(), oHits.end());
790 for (ii = 0; ii <
tcl[icl].tclhits.size(); ++ii) {
791 iht =
tcl[icl].tclhits[ii];
792 if ((
unsigned int)fHits[iht].WireID().Wire >= eWire)
continue;
793 fcl2hits.insert(fcl2hits.end(),
tcl[icl].tclhits.begin() + ii,
tcl[icl].tclhits.end());
796 clBeginSlp =
tcl[jcl].BeginSlp;
797 clBeginSlpErr =
tcl[jcl].BeginSlpErr;
798 clBeginAng =
tcl[jcl].BeginAng;
799 clBeginWir =
tcl[jcl].BeginWir;
800 clBeginTim =
tcl[jcl].BeginTim;
801 clBeginChg =
tcl[jcl].BeginChg;
802 clBeginChgNear =
tcl[jcl].BeginChgNear;
804 clEndSlp =
tcl[icl].EndSlp;
805 clEndSlpErr =
tcl[icl].EndSlpErr;
806 clEndAng =
tcl[icl].EndAng;
807 clEndWir =
tcl[icl].EndWir;
808 clEndTim =
tcl[icl].EndTim;
809 clEndChg =
tcl[icl].EndChg;
810 clEndChgNear =
tcl[icl].EndChgNear;
811 clStopCode =
tcl[icl].StopCode;
812 clProcCode =
tcl[icl].ProcCode + 500;
813 MakeClusterObsolete(icl);
814 MakeClusterObsolete(jcl);
817 RestoreObsoleteCluster(icl);
818 RestoreObsoleteCluster(jcl);
819 CheckHitClusterAssociations();
822 CheckHitClusterAssociations();
823 tcl[
tcl.size() - 1].BeginVtx =
tcl[jcl].BeginVtx;
824 tcl[
tcl.size() - 1].EndVtx =
tcl[icl].BeginVtx;
828 <<
" in clCTP " << clCTP;
830 if (
tcl[icl].
ID < 0)
break;
838 ClusterCrawlerAlg::MakeClusterObsolete(
unsigned short icl)
840 short&
ID =
tcl[icl].ID;
842 mf::LogError(
"CC") <<
"Trying to make already-obsolete cluster obsolete ID = " <<
ID;
848 for (
unsigned int iht = 0; iht <
tcl[icl].tclhits.size(); ++iht)
849 inClus[
tcl[icl].tclhits[iht]] = 0;
855 ClusterCrawlerAlg::RestoreObsoleteCluster(
unsigned short icl)
857 short&
ID =
tcl[icl].ID;
859 mf::LogError(
"CC") <<
"Trying to restore non-obsolete cluster ID = " <<
ID;
864 for (
unsigned short iht = 0; iht <
tcl[icl].tclhits.size(); ++iht)
865 inClus[
tcl[icl].tclhits[iht]] = ID;
871 ClusterCrawlerAlg::FclTrimUS(
unsigned short nTrim)
875 if (nTrim == 0)
return;
877 if (nTrim >= fcl2hits.size()) nTrim = fcl2hits.size();
880 for (
unsigned short ii = 0; ii < nTrim; ++ii) {
891 ClusterCrawlerAlg::CheckHitClusterAssociations()
895 if (fHits.size() != inClus.size()) {
896 mf::LogError(
"CC") <<
"CHCA: Sizes wrong " << fHits.size() <<
" " << inClus.size();
900 unsigned int iht, nErr = 0;
904 for (
unsigned short icl = 0; icl <
tcl.size(); ++icl) {
905 if (
tcl[icl].
ID < 0)
continue;
907 for (
unsigned short ii = 0; ii <
tcl[icl].tclhits.size(); ++ii) {
908 iht =
tcl[icl].tclhits[ii];
909 if (iht > fHits.size() - 1) {
910 mf::LogError(
"CC") <<
"CHCA: Bad tclhits index " << iht <<
" fHits size " << fHits.size();
913 if (inClus[iht] != clID) {
914 mf::LogError(
"CC") <<
"CHCA: Bad cluster -> hit association. clID " << clID
915 <<
" hit inClus " << inClus[iht] <<
" ProcCode " <<
tcl[icl].ProcCode
916 <<
" CTP " <<
tcl[icl].CTP;
918 if (nErr > 10)
return;
925 for (iht = 0; iht < fHits.size(); ++iht) {
926 if (inClus[iht] <= 0)
continue;
927 icl = inClus[iht] - 1;
929 if (
tcl[icl].
ID < 0) {
930 mf::LogError(
"CC") <<
"CHCA: Hit associated with an obsolete cluster. hit W:T " 931 << fHits[iht].WireID().Wire <<
":" << (
int)fHits[iht].PeakTime()
932 <<
" tcl[icl].ID " <<
tcl[icl].ID;
934 if (nErr > 10)
return;
936 if (std::find(
tcl[icl].tclhits.begin(),
tcl[icl].tclhits.end(), iht) ==
937 tcl[icl].tclhits.end()) {
938 mf::LogError(
"CC") <<
"CHCA: Bad hit -> cluster association. hit index " << iht <<
" W:T " 939 << fHits[iht].WireID().Wire <<
":" << (
int)fHits[iht].PeakTime()
940 <<
" inClus " << inClus[iht];
942 if (nErr > 10)
return;
950 ClusterCrawlerAlg::RemoveObsoleteHits()
953 unsigned int destHit = 0;
955 if (fHits.size() != inClus.size()) {
956 mf::LogError(
"CC") <<
"RemoveObsoleteHits size mis-match " << fHits.size() <<
" " 962 for (
unsigned int srcHit = 0; srcHit < fHits.size(); ++srcHit) {
963 if (inClus[srcHit] < 0)
continue;
964 if (srcHit != destHit) {
965 fHits[destHit] =
std::move(fHits[srcHit]);
966 inClus[destHit] = inClus[srcHit];
967 if (inClus[destHit] > 0) {
969 icl = inClus[destHit] - 1;
970 auto& hits =
tcl[icl].tclhits;
971 auto iHitIndex = std::find(hits.begin(), hits.end(), srcHit);
972 if (iHitIndex == hits.end()) {
973 mf::LogError(
"CC") <<
"RemoveObsoleteHits: Hit #" << srcHit
974 <<
" not found in cluster ID " << inClus[destHit];
977 *iHitIndex = destHit;
984 fHits.resize(destHit);
985 inClus.resize(destHit);
991 ClusterCrawlerAlg::ChkClusterDS()
998 prt = (fDebugPlane == 3);
1001 float dThCut = fKinkAngCut[fNumPass - 1];
1004 mf::LogVerbatim(
"CC") <<
"ChkClusterDS clCTP " << clCTP <<
" kink angle cut " << dThCut;
1006 const unsigned short tclsize =
tcl.size();
1007 bool didMerge, skipit;
1008 unsigned short icl, ii, nhm, iv;
1012 for (icl = 0; icl < tclsize; ++icl) {
1013 if (
tcl[icl].
ID < 0)
continue;
1014 if (
tcl[icl].CTP != clCTP)
continue;
1016 if (
tcl[icl].BeginVtx >= 0)
continue;
1019 for (
unsigned short iv = 0; iv < vtx.size(); ++iv) {
1020 if (vtx[iv].CTP != clCTP)
continue;
1022 if (
std::abs(vtx[iv].Time -
tcl[icl].BeginTim) > 20)
continue;
1026 if (skipit)
continue;
1029 for (ii = 0; ii < 3; ++ii) {
1031 if (fHits[iht].Multiplicity() > 1) {
1032 MergeHits(iht, didMerge);
1033 if (didMerge) ++nhm;
1038 FitClusterMid(icl, 0, 3);
1039 tcl[icl].BeginTim = clpar[0];
1040 tcl[icl].BeginSlp = clpar[1];
1041 tcl[icl].BeginAng = atan(fScaleF * clpar[1]);
1042 tcl[icl].BeginSlpErr = clparerr[1];
1043 tcl[icl].BeginChg = fAveChg;
1044 tcl[icl].ProcCode += 5000;
1045 if (prt)
mf::LogVerbatim(
"CC") <<
"ChkClusterDS: Merge hits on cluster " <<
tcl[icl].ID;
1049 float thhits, prevth, hitrms, rmsrat;
1051 std::vector<unsigned int> dshits;
1052 for (icl = 0; icl < tclsize; ++icl) {
1053 if (
tcl[icl].
ID < 0)
continue;
1054 if (
tcl[icl].CTP != clCTP)
continue;
1056 if (
tcl[icl].BeginVtx >= 0)
continue;
1059 for (iv = 0; iv < vtx.size(); ++iv) {
1060 if (vtx[iv].CTP != clCTP)
continue;
1062 if (
std::abs(vtx[iv].Time -
tcl[icl].BeginTim) > 20)
continue;
1066 if (skipit)
continue;
1068 unsigned int ih0 =
tcl[icl].tclhits[1];
1069 unsigned int ih1 =
tcl[icl].tclhits[0];
1070 const float slp = (fHits[ih1].PeakTime() - fHits[ih0].PeakTime()) /
1071 (fHits[ih1].
WireID().Wire - fHits[ih0].WireID().Wire);
1072 prevth = std::atan(fScaleF * slp);
1075 unsigned int wire = fHits[ih0].WireID().Wire;
1076 hitrms = fHits[ih0].RMS();
1077 float time0 = fHits[ih0].PeakTime();
1082 for (ii = 0; ii < 4; ++ii) {
1084 if (wire > fLastWire)
break;
1085 prtime = time0 + slp;
1088 << wire <<
" hitrms " << hitrms <<
" prevth " << prevth
1089 <<
" prtime " << (
int)prtime;
1091 if (WireHitRange[wire].first == -2)
break;
1092 unsigned int firsthit = WireHitRange[wire].first;
1093 unsigned int lasthit = WireHitRange[wire].second;
1094 bool hitAdded =
false;
1095 for (ih1 = firsthit; ih1 < lasthit; ++ih1) {
1096 if (inClus[ih1] != 0)
continue;
1097 if (prtime < fHits[ih1].PeakTimeMinusRMS(5))
continue;
1098 if (prtime > fHits[ih1].PeakTimePlusRMS(5))
continue;
1099 const float slp = (fHits[ih1].PeakTime() - fHits[ih0].PeakTime()) /
1100 (fHits[ih1].
WireID().Wire - fHits[ih0].WireID().Wire);
1101 thhits = std::atan(fScaleF * slp);
1103 mf::LogVerbatim(
"CC") <<
" theta " << thhits <<
" prevth " << prevth <<
" cut " 1105 if (
std::abs(thhits - prevth) > dThCut)
continue;
1108 if (
std::abs(slp) < fLAClusSlopeCut) {
1109 rmsrat = fHits[ih1].RMS() / hitrms;
1110 ratOK = rmsrat > 0.3 && rmsrat < 3;
1115 MergeHits(ih1, didMerge);
1117 if (prt)
mf::LogVerbatim(
"CC") <<
" rmsrat " << rmsrat <<
" OK? " << ratOK;
1122 dshits.push_back(ih1);
1127 mf::LogVerbatim(
"CC") <<
" Add hit " << fHits[ih1].WireID().Wire <<
":" 1128 << (
int)fHits[ih1].PeakTime() <<
" rmsrat " << rmsrat;
1133 if (!hitAdded)
break;
1136 if (dshits.size() > 0) {
1142 if (dshits.size() > 1) std::sort(dshits.begin(), dshits.end(),
SortByLowHit);
1146 for (ii = 0; ii <
tcl[icl].tclhits.size(); ++ii) {
1148 iht =
tcl[icl].tclhits[ii];
1150 fcl2hits.push_back(iht);
1153 pass = fNumPass - 1;
1155 clBeginChg = fAveChg;
1157 MakeClusterObsolete(icl);
1160 mf::LogError(
"CC") <<
"ChkClusterDS TmpStore failed while extending cluster ID " 1164 const size_t newcl =
tcl.size() - 1;
1166 tcl[newcl].BeginVtx =
tcl[icl].BeginVtx;
1167 tcl[newcl].EndVtx =
tcl[icl].EndVtx;
1174 ClusterCrawlerAlg::CrawlVtxChk2()
1180 if (vtx.size() == 0)
return false;
1181 if (fcl2hits.size() == 0)
return false;
1183 unsigned int iht = fcl2hits.size() - 1;
1185 float wire0 = (0.5 + fHits[fcl2hits[iht]].WireID().Wire);
1187 float thclus = std::atan(fScaleF * clpar[1]);
1189 for (
unsigned short iv = 0; iv < vtx.size(); ++iv) {
1190 if (vtx[iv].CTP != clCTP)
continue;
1191 if (wire0 < vtx[iv].
Wire)
continue;
1192 if (wire0 > vtx[iv].Wire + 10)
continue;
1193 dt = clpar[0] + (vtx[iv].Wire - wire0) * clpar[1] - vtx[iv].Time;
1197 for (icl = 0; icl <
tcl.size(); ++icl) {
1198 if (
tcl[icl].CTP != clCTP)
continue;
1199 if (
tcl[icl].EndVtx != iv)
continue;
1200 if (
std::abs(
tcl[icl].EndAng - thclus) < fKinkAngCut[
pass])
return true;
1210 ClusterCrawlerAlg::CrawlVtxChk(
unsigned int kwire)
1214 if (vtx.size() == 0)
return false;
1215 unsigned int iht = fcl2hits.size() - 1;
1216 float wire0 = (0.5 + fHits[fcl2hits[iht]].WireID().Wire);
1217 float prtime = clpar[0] + (kwire - wire0) * clpar[1];
1218 for (
unsigned short iv = 0; iv < vtx.size(); ++iv) {
1219 if (vtx[iv].CTP != clCTP)
continue;
1220 if ((
unsigned int)(0.5 + vtx[iv].Wire) != kwire)
continue;
1221 if (
std::abs(prtime - vtx[iv].Time) < 10)
return true;
1228 ClusterCrawlerAlg::VtxConstraint(
unsigned int iwire,
1231 unsigned int& useHit,
1237 doConstrain =
false;
1238 if (vtx.size() == 0)
return;
1240 if (
pass == 0)
return;
1242 if (!fFindVertices[
pass - 1])
return;
1244 if (jwire > WireHitRange.size() - 1) {
1245 mf::LogError(
"CC") <<
"VtxConstraint fed bad jwire " << jwire <<
" WireHitRange size " 1246 << WireHitRange.size();
1250 unsigned int jfirsthit = WireHitRange[jwire].first;
1251 unsigned int jlasthit = WireHitRange[jwire].second;
1252 for (
unsigned short iv = 0; iv < vtx.size(); ++iv) {
1253 if (vtx[iv].CTP != clCTP)
continue;
1255 if (vtx[iv].
Wire > jwire)
continue;
1257 if (vtx[iv].
Wire < jwire - 10)
continue;
1260 clpar[1] = (vtx[iv].Time - hit.
PeakTime()) / (vtx[iv].
Wire - iwire);
1262 float prtime = clpar[0] + clpar[1] * (jwire - iwire);
1263 for (
unsigned int jhit = jfirsthit; jhit < jlasthit; ++jhit) {
1264 if (inClus[jhit] != 0)
continue;
1265 const float tdiff =
std::abs(fHits[jhit].TimeDistanceAsRMS(prtime));
1278 ClusterCrawlerAlg::RefineVertexClusters(
unsigned short iv)
1283 std::vector<unsigned short> begClusters;
1284 std::vector<short> begdW;
1285 std::vector<unsigned short> endClusters;
1286 std::vector<short> enddW;
1288 unsigned int vWire = (
unsigned int)(vtx[iv].
Wire + 0.5);
1289 unsigned int vWireErr = (
unsigned int)(2 * vtx[iv].WireErr);
1290 unsigned int vWireLo = vWire - vWireErr;
1291 unsigned int vWireHi = vWire + vWireErr;
1293 unsigned short icl, ii;
1295 bool needsWork =
false;
1298 for (icl = 0; icl <
tcl.size(); ++icl) {
1299 if (
tcl[icl].
ID < 0)
continue;
1300 if (
tcl[icl].CTP != vtx[iv].CTP)
continue;
1301 if (
tcl[icl].BeginVtx == iv) {
1302 dW = vWire -
tcl[icl].BeginWir;
1303 if (dW > maxdW) maxdW = dW;
1304 if (dW < mindW) mindW = dW;
1305 if (
std::abs(dW) > 1) needsWork =
true;
1307 begClusters.push_back(icl);
1308 begdW.push_back(dW);
1310 if (
tcl[icl].EndVtx == iv) {
1311 dW = vWire -
tcl[icl].EndWir;
1312 if (dW > maxdW) maxdW = dW;
1313 if (dW < mindW) mindW = dW;
1314 if (
std::abs(dW) > 1) needsWork =
true;
1315 endClusters.push_back(icl);
1316 enddW.push_back(dW);
1321 mf::LogVerbatim(
"CC") <<
"RefineVertexClusters: vertex " << iv <<
" needsWork " << needsWork
1322 <<
" mindW " << mindW <<
" maxdW " << maxdW <<
" vWireErr " << vWireErr;
1324 if (!needsWork)
return;
1328 if (((
unsigned int)
std::abs(mindW) < vWireErr) && ((
unsigned int)
std::abs(maxdW) < vWireErr) &&
1330 if (vtxprt)
mf::LogVerbatim(
"CC") <<
" Move vtx wire " << vtx[iv].Wire;
1331 vtx[iv].Wire -= (
float)(maxdW + mindW) / 2;
1334 vtx[iv].Fixed =
true;
1341 unsigned short newSize;
1342 for (ii = 0; ii < endClusters.size(); ++ii) {
1343 icl = endClusters[ii];
1345 mf::LogVerbatim(
"CC") <<
" endCluster " <<
tcl[icl].ID <<
" dW " << enddW[ii] <<
" vWire " 1347 if (
tcl[icl].EndWir < vWire) {
1350 newSize = fcl2hits.size();
1351 for (
auto hiter = fcl2hits.rbegin(); hiter < fcl2hits.rend(); ++hiter) {
1352 if (fHits[*hiter].
WireID().Wire > vWire)
break;
1356 for (
auto hiter = fcl2hits.begin(); hiter < fcl2hits.end(); ++hiter)
1359 fcl2hits.resize(newSize);
1360 MakeClusterObsolete(icl);
1366 tcl[
tcl.size() - 1].EndVtx = iv;
1370 <<
tcl[
tcl.size() - 1].ID;
1372 else if (
tcl[icl].EndWir > vWire) {
1373 mf::LogVerbatim(
"CC") <<
"RefineVertexClusters: Write some EndVtx code";
1377 if (begClusters.size() > 0)
1378 mf::LogVerbatim(
"CC") <<
"RefineVertexClusters: Write some BeginVtx code";
1380 if (mindW < 0 && maxdW > 0) {
1385 unsigned short clsBigChg = 0;
1390 for (ii = 0; ii < begClusters.size(); ++ii) {
1391 icl = begClusters[ii];
1392 for (iht = 0; iht <
tcl[icl].tclhits.size(); ++iht) {
1393 ihit =
tcl[icl].tclhits[iht];
1394 if (fHits[ihit].Integral() > bigChg) {
1395 bigChg = fHits[ihit].Integral();
1399 if (fHits[ihit].
WireID().
Wire < vWireLo)
break;
1403 for (ii = 0; ii < endClusters.size(); ++ii) {
1404 icl = endClusters[ii];
1405 for (iht = 0; iht <
tcl[icl].tclhits.size(); ++iht) {
1406 ihit =
tcl[icl].tclhits[
tcl[icl].tclhits.size() - 1 - iht];
1407 if (fHits[ihit].Integral() > bigChg) {
1408 bigChg = fHits[ihit].Integral();
1412 if (fHits[ihit].
WireID().
Wire > vWireHi)
break;
1417 mf::LogVerbatim(
"CC") <<
" moving vertex location to hit " << fHits[vtxHit].WireID().Wire
1418 <<
":" << (
int)fHits[vtxHit].PeakTime() <<
" on cluster " 1419 <<
tcl[clsBigChg].ID;
1420 vtx[iv].Wire = fHits[vtxHit].WireID().Wire;
1421 vtx[iv].Time = fHits[vtxHit].PeakTime();
1422 vtx[iv].Fixed =
true;
1432 ClusterCrawlerAlg::VtxClusterSplit()
1437 vtxprt = (fDebugPlane >= 0 && fDebugWire == 5555);
1441 if (vtx.size() == 0)
return false;
1442 unsigned short tclsize =
tcl.size();
1443 if (tclsize < 2)
return false;
1446 bool didSomething =
false;
1448 for (
unsigned short icl = 0; icl < tclsize; ++icl) {
1449 if (
tcl[icl].
ID < 0)
continue;
1450 if (
tcl[icl].CTP != clCTP)
continue;
1452 if (
tcl[icl].tclhits.size() < 5)
continue;
1455 for (
unsigned short ivx = 0; ivx < vtx.size(); ++ivx) {
1456 if (vtx[ivx].CTP != clCTP)
continue;
1458 if (vtx[ivx].NClusters == 0)
continue;
1460 if (
tcl[icl].BeginVtx == ivx)
continue;
1461 if (
tcl[icl].EndVtx == ivx)
continue;
1463 if (vtx[ivx].
Wire <
tcl[icl].EndWir)
continue;
1464 if (vtx[ivx].
Wire >
tcl[icl].BeginWir)
continue;
1466 float hiTime =
tcl[icl].BeginTim;
1467 if (
tcl[icl].EndTim > hiTime) hiTime =
tcl[icl].EndTim;
1468 if (vtx[ivx].Time > hiTime + 5)
continue;
1469 float loTime =
tcl[icl].BeginTim;
1470 if (
tcl[icl].EndTim < loTime) loTime =
tcl[icl].EndTim;
1471 if (vtx[ivx].Time < loTime - 5)
continue;
1475 mf::LogVerbatim(
"CC") <<
" Chk cluster ID " <<
tcl[icl].ID <<
" with vertex " << ivx;
1479 unsigned short nSplit = 0;
1480 unsigned short nLop = 0;
1482 for (
unsigned short ii =
tcl[icl].tclhits.size() - 1; ii > 0; --ii) {
1483 iht =
tcl[icl].tclhits[ii];
1485 if (fHits[iht].
WireID().Wire >= vtx[ivx].Wire) {
1489 << fHits[iht].WireID().Wire <<
" nSplit " << nSplit;
1495 if (ihvx < 0)
continue;
1496 if (fabs(fHits[ihvx].PeakTime() - vtx[ivx].Time) > 10)
continue;
1501 if (nSplit >
tcl[icl].tclhits.size() / 2) { iclAng =
tcl[icl].EndAng; }
1503 iclAng =
tcl[icl].BeginAng;
1508 for (
unsigned short jcl = 0; jcl < tclsize; ++jcl) {
1509 if (
tcl[jcl].
ID < 0)
continue;
1510 if (
tcl[jcl].CTP != clCTP)
continue;
1511 if (
tcl[jcl].BeginVtx == ivx) {
1512 if (fabs(
tcl[jcl].BeginAng - iclAng) > 0.4) {
1518 if (
tcl[jcl].EndVtx == ivx) {
1519 if (fabs(
tcl[jcl].EndAng - iclAng) > 0.4) {
1533 for (
unsigned short ii = 0; ii < nLop; ++ii) {
1534 unsigned int iht = fcl2hits[fcl2hits.size() - 1];
1536 fcl2hits.pop_back();
1541 MakeClusterObsolete(icl);
1543 if (!TmpStore())
continue;
1544 unsigned short newcl =
tcl.size() - 1;
1545 tcl[newcl].BeginVtx =
tcl[icl].BeginVtx;
1546 tcl[newcl].EndVtx = ivx;
1552 if (SplitCluster(icl, nSplit, ivx)) {
1553 tcl[
tcl.size() - 1].ProcCode += 1000;
1554 tcl[
tcl.size() - 2].ProcCode += 1000;
1558 didSomething =
true;
1564 return didSomething;
1570 ClusterCrawlerAlg::MergeHits(
const unsigned int theHit,
bool& didMerge)
1584 if (theHit > fHits.size() - 1) {
return; }
1589 if (fHits[theHit].GoodnessOfFit() == 6666) {
1591 mf::LogVerbatim(
"CC") <<
"MergeHits Trying to merge already merged hit " 1594 <<
" theHit " << theHit;
1599 if (!mergeAvailable[theHit]) {
return; }
1604 std::pair<size_t, size_t> MultipletRange = FindHitMultiplet(theHit);
1607 if (MultipletRange.second <= MultipletRange.first)
return;
1610 unsigned short nAvailable = 0;
1611 unsigned short nInClus = 0;
1612 for (
size_t jht = MultipletRange.first; jht < MultipletRange.second; ++jht) {
1613 if (jht == theHit)
continue;
1614 if (fHits[jht].GoodnessOfFit() == 6666)
continue;
1615 if (inClus[jht] != 0) {
1621 if (nAvailable == 0)
return;
1623 if (nInClus > 0)
return;
1629 short loTime = 9999;
1631 unsigned short nGaus = 1;
1634 unsigned short nclose = 0;
1636 for (
size_t jht = MultipletRange.first; jht < MultipletRange.second; ++jht) {
1637 if (inClus[jht] < 0)
continue;
1645 if (inClus[jht] != 0)
continue;
1647 if (arg < loTime) loTime = arg;
1649 if (arg > hiTime) hiTime = arg;
1650 if (jht != theHit) ++nGaus;
1652 if (jht != theHit && hitSep < 3) ++nclose;
1655 if (nGaus < 2)
return;
1658 const short int NewMultiplicity = hit.
Multiplicity() + 1 - nGaus;
1660 if (loTime < 0) loTime = 0;
1663 std::vector<double> signal(hiTime - loTime, 0.);
1666 for (
size_t jht = MultipletRange.first; jht < MultipletRange.second; ++jht) {
1668 if (jht != theHit) {
1670 if (inClus[jht] != 0)
continue;
1676 for (
unsigned short time = loTime;
time < hiTime; ++
time) {
1677 unsigned short indx =
time - loTime;
1679 signal[indx] += other_hit.
PeakAmplitude() * exp(-0.5 * arg * arg);
1684 double sigsumt = 0.;
1685 for (
unsigned short time = loTime;
time < hiTime; ++
time) {
1686 sigsum += signal[
time - loTime];
1687 sigsumt += signal[
time - loTime] *
time;
1693 double aveTime = sigsumt / sigsum;
1696 for (
unsigned short time = loTime;
time < hiTime; ++
time) {
1697 double dtime =
time - aveTime;
1698 sigsumt += signal[
time - loTime] * dtime * dtime;
1700 const float RMS = std::sqrt(sigsumt / sigsum);
1702 const float amplitude = chgsum * chgNorm / (2.507 * RMS);
1723 FixMultipletLocalIndices(MultipletRange.first, MultipletRange.second);
1730 ClusterCrawlerAlg::FixMultipletLocalIndices(
size_t begin,
1732 short int multiplicity )
1744 if (multiplicity < 0) {
1746 for (
size_t iHit = begin; iHit <
end; ++iHit) {
1747 if (inClus[iHit] < 0)
continue;
1753 short int local_index = 0;
1754 for (
size_t iHit = begin; iHit <
end; ++iHit) {
1755 if (inClus[iHit] < 0)
continue;
1786 ClusterCrawlerAlg::FindStarVertices()
1793 if (
tcl.size() < 2)
return;
1798 vtxprt = (fDebugPlane == (
int)plane && fDebugHit < 0);
1804 unsigned short vtxSizeIn = vtx.size();
1808 float dsl = 0, dth = 0;
1809 float es1 = 0, es2 = 0;
1810 float eth1 = 0, eth2 = 0;
1811 float bt1 = 0, bt2 = 0;
1812 float et1 = 0, et2 = 0;
1813 float bw1 = 0, bw2 = 0;
1814 float ew1 = 0, ew2 = 0;
1815 float lotime = 0, hitime = 0, nwirecut = 0;
1816 unsigned short tclsize =
tcl.size();
1817 for (
unsigned short it1 = 0; it1 < tclsize - 1; ++it1) {
1819 if (
tcl[it1].
ID < 0)
continue;
1820 if (
tcl[it1].CTP != clCTP)
continue;
1822 if (
tcl[it1].tclhits.size() > 100) {
1823 dth =
tcl[it1].BeginAng -
tcl[it1].EndAng;
1826 es1 =
tcl[it1].EndSlp;
1827 eth1 =
tcl[it1].EndAng;
1828 ew1 =
tcl[it1].EndWir;
1829 et1 =
tcl[it1].EndTim;
1830 bw1 =
tcl[it1].BeginWir;
1831 bt1 =
tcl[it1].BeginTim;
1832 for (
unsigned short it2 = it1 + 1; it2 < tclsize; ++it2) {
1833 if (
tcl[it2].
ID < 0)
continue;
1834 if (
tcl[it2].CTP != clCTP)
continue;
1836 if (
tcl[it2].tclhits.size() > 100) {
1837 dth =
tcl[it2].BeginAng -
tcl[it2].EndAng;
1838 if (
std::abs(dth) < 0.05)
continue;
1840 es2 =
tcl[it2].EndSlp;
1841 eth2 =
tcl[it2].EndAng;
1842 ew2 =
tcl[it2].EndWir;
1843 et2 =
tcl[it2].EndTim;
1844 bw2 =
tcl[it2].BeginWir;
1845 bt2 =
tcl[it2].BeginTim;
1848 if (dth < 0.3)
continue;
1850 fvw = (et1 - ew1 * es1 - et2 + ew2 * es2) / dsl;
1852 if (fvw < ew1 || fvw > bw1)
continue;
1853 if (fvw < ew2 || fvw > bw2)
continue;
1856 <<
" topo5 vtx wire " << fvw;
1859 if (
tcl[it1].tclhits.size() >
tcl[it2].tclhits.size()) {
1860 if (
tcl[it1].tclhits.size() > 20) {
1861 nwirecut = 0.5 *
tcl[it1].tclhits.size();
1862 if ((fvw - ew1) > nwirecut)
continue;
1866 if (
tcl[it2].tclhits.size() > 20) {
1867 nwirecut = 0.5 *
tcl[it2].tclhits.size();
1868 if ((fvw - ew2) > nwirecut)
continue;
1871 fvt = et1 + (fvw - ew1) * es1;
1874 if (et1 < lotime) lotime = et1;
1875 if (bt1 < lotime) lotime = bt1;
1876 if (et2 < lotime) lotime = et2;
1877 if (bt2 < lotime) lotime = bt2;
1879 if (et1 > hitime) hitime = et1;
1880 if (bt1 > hitime) hitime = bt1;
1881 if (et2 > hitime) hitime = et2;
1882 if (bt2 > hitime) hitime = bt2;
1883 if (fvt < lotime || fvt > hitime)
continue;
1885 mf::LogVerbatim(
"CC") <<
" vertex time " << fvt <<
" lotime " << lotime <<
" hitime " 1887 unsigned int vw = (0.5 + fvw);
1889 unsigned int pos1 = 0;
1890 for (
unsigned short ii = 0; ii <
tcl[it1].tclhits.size(); ++ii) {
1891 if (fHits[
tcl[it1].tclhits[ii]].
WireID().Wire <= vw) {
1892 if (
std::abs(
int(fHits[
tcl[it1].tclhits[ii]].PeakTime() - fvt)) < 10) pos1 = ii;
1897 if (pos1 == 0)
continue;
1898 unsigned short pos2 = 0;
1899 for (
unsigned short ii = 0; ii <
tcl[it2].tclhits.size(); ++ii) {
1900 if (fHits[
tcl[it2].tclhits[ii]].
WireID().Wire <= vw) {
1901 if (
std::abs(
int(fHits[
tcl[it2].tclhits[ii]].PeakTime() - fvt)) < 10) pos2 = ii;
1906 if (pos2 == 0)
continue;
1908 for (
unsigned short iv = 0; iv < vtx.size(); ++iv) {
1919 newvx.
Fixed =
false;
1920 vtx.push_back(newvx);
1921 unsigned short ivx = vtx.size() - 1;
1924 <<
" split pos " << pos1;
1925 if (!SplitCluster(it1, pos1, ivx))
continue;
1926 tcl[
tcl.size() - 1].ProcCode += 1000;
1927 tcl[
tcl.size() - 2].ProcCode += 1000;
1930 <<
" split pos " << pos2;
1931 if (!SplitCluster(it2, pos2, ivx))
continue;
1932 tcl[
tcl.size() - 1].ProcCode += 1000;
1933 tcl[
tcl.size() - 2].ProcCode += 1000;
1939 if (vtx.size() > vtxSizeIn) {
1943 VertexCluster(vtx.size() - 1);
1949 for (
unsigned short iv = 0; iv < vtx.size(); ++iv) {
1950 if (vtx[iv].CTP != clCTP)
continue;
1951 mf::LogVerbatim(
"CC") <<
"vtx " << iv <<
" wire " << vtx[iv].Wire <<
" time " 1952 << (
int)vtx[iv].Time <<
" NClusters " << vtx[iv].NClusters <<
" topo " 1962 ClusterCrawlerAlg::VertexCluster(
unsigned short iv)
1965 if (vtx[iv].NClusters == 0)
return;
1967 short dwb, dwe, dtb, dte;
1970 for (
unsigned short icl = 0; icl <
tcl.size(); ++icl) {
1971 if (
tcl[icl].
ID < 0)
continue;
1972 if (
tcl[icl].CTP != vtx[iv].CTP)
continue;
1974 dwb = vtx[iv].Wire -
tcl[icl].BeginWir;
1975 dtb = vtx[iv].Time -
tcl[icl].BeginTim;
1976 dwe = vtx[iv].Wire -
tcl[icl].EndWir;
1977 dte = vtx[iv].Time -
tcl[icl].EndTim;
1979 float drb = dwb * dwb + dtb * dtb;
1980 float dre = dwe * dwe + dte * dte;
1982 bool bCloser = (drb < dre);
1986 if (
tcl[icl].BeginChgNear > fChgNearCut)
continue;
1989 if (
tcl[icl].EndChgNear > fChgNearCut)
continue;
1993 mf::LogVerbatim(
"CC") <<
"VertexCluster: Try icl ID " <<
tcl[icl].ID <<
" w vtx " << iv
1994 <<
" dwb " << dwb <<
" dwe " << dwe <<
" drb " << drb <<
" dre " 1995 << dre <<
" Begin closer? " << bCloser;
1997 if (
tcl[icl].BeginVtx < 0 && bCloser && dwb > -3 && dwb < 3 &&
tcl[icl].EndVtx != iv) {
1998 sigOK = ChkSignal(
tcl[icl].BeginWir,
tcl[icl].BeginTim, vtx[iv].
Wire, vtx[iv].Time);
2000 mf::LogVerbatim(
"CC") <<
" Attach cluster Begin to vtx? " << iv <<
" sigOK " << sigOK;
2003 mf::LogVerbatim(
"CC") <<
" check ClusterVertexChi " << ClusterVertexChi(icl, 0, iv);
2004 if (ClusterVertexChi(icl, 0, iv) < fVertex2DCut) {
2006 tcl[icl].BeginVtx = iv;
2008 if (vtx[iv].ChiDOF > fVertex2DCut || vtx[iv].WireErr > fVertex2DWireErrCut) {
2009 tcl[icl].BeginVtx = -99;
2016 if (
tcl[icl].EndVtx < 0 && !bCloser && dwe > -3 && dwe < 3 &&
tcl[icl].BeginVtx != iv) {
2017 sigOK = ChkSignal(
tcl[icl].EndWir,
tcl[icl].EndTim, vtx[iv].
Wire, vtx[iv].Time);
2019 mf::LogVerbatim(
"CC") <<
" Attach cluster End to vtx? " << iv <<
" sigOK " << sigOK;
2022 mf::LogVerbatim(
"CC") <<
" check ClusterVertexChi " << ClusterVertexChi(icl, 1, iv);
2023 if (ClusterVertexChi(icl, 1, iv) < 3) {
2025 tcl[icl].EndVtx = iv;
2027 if (vtx[iv].ChiDOF > fVertex2DCut || vtx[iv].WireErr > fVertex2DWireErrCut) {
2028 tcl[icl].EndVtx = -99;
2039 ClusterCrawlerAlg::FitAllVtx(
CTP_t inCTP)
2042 for (
unsigned short iv = 0; iv < vtx.size(); ++iv) {
2043 if (vtx[iv].CTP != inCTP)
continue;
2051 ClusterCrawlerAlg::FindVertices()
2055 if (
tcl.size() < 2)
return;
2058 std::vector<CluLen> clulens;
2060 for (
unsigned short icl = 0; icl <
tcl.size(); ++icl) {
2061 if (
tcl[icl].
ID < 0)
continue;
2062 if (
tcl[icl].CTP != clCTP)
continue;
2063 if (
tcl[icl].BeginVtx >= 0 &&
tcl[icl].EndVtx >= 0)
continue;
2065 clulen.length =
tcl[icl].tclhits.size();
2066 clulens.push_back(clulen);
2068 if (
empty(clulens))
return;
2069 std::sort(clulens.begin(), clulens.end(),
greaterThan);
2071 float nwires = fNumWires;
2072 float maxtime = fMaxTime;
2074 unsigned short vtxSizeIn = vtx.size();
2076 vtxprt = (fDebugPlane == (short)plane && fDebugHit < 0);
2082 float es1 = 0, eth1 = 0, ew1 = 0, et1 = 0;
2083 float bs1 = 0, bth1 = 0, bw1 = 0, bt1 = 0;
2084 float es2 = 0, eth2 = 0, ew2 = 0, et2 = 0;
2085 float bs2 = 0, bth2 = 0, bw2 = 0, bt2 = 0;
2086 float dth = 0, dsl = 0, fvw = 0, fvt = 0;
2088 unsigned int vw = 0, pass1, pass2, ii1, it1, ii2, it2;
2090 for (ii1 = 0; ii1 < clulens.size() - 1; ++ii1) {
2091 it1 = clulens[ii1].index;
2092 es1 =
tcl[it1].EndSlp;
2093 eth1 =
tcl[it1].EndAng;
2094 ew1 =
tcl[it1].EndWir;
2095 et1 =
tcl[it1].EndTim;
2096 bs1 =
tcl[it1].BeginSlp;
2097 bth1 =
tcl[it1].BeginAng;
2098 bw1 =
tcl[it1].BeginWir;
2099 bt1 =
tcl[it1].BeginTim;
2100 pass1 =
tcl[it1].ProcCode - 10 * (
tcl[it1].ProcCode / 10);
2101 for (ii2 = ii1 + 1; ii2 < clulens.size(); ++ii2) {
2102 it2 = clulens[ii2].index;
2106 if (
tcl[it1].tclhits.size() < 5 &&
tcl[it2].tclhits.size() < 5)
continue;
2107 es2 =
tcl[it2].EndSlp;
2108 eth2 =
tcl[it2].EndAng;
2109 ew2 =
tcl[it2].EndWir;
2110 et2 =
tcl[it2].EndTim;
2111 bs2 =
tcl[it2].BeginSlp;
2112 bth2 =
tcl[it2].BeginAng;
2113 bw2 =
tcl[it2].BeginWir;
2114 bt2 =
tcl[it2].BeginTim;
2115 pass2 =
tcl[it2].ProcCode - 10 * (
tcl[it2].ProcCode / 10);
2116 if (pass1 < pass2) { angcut = fKinkAngCut[pass2]; }
2118 angcut = fKinkAngCut[pass1];
2121 dth = fabs(eth1 - eth2);
2122 if (
tcl[it1].EndVtx < 0 &&
tcl[it2].EndVtx < 0 && dth > 0.1) {
2125 fvw = (et1 - ew1 * es1 - et2 + ew2 * es2) / dsl;
2127 if (fvw > 0. && fvw < nwires) {
2132 if (vw >= fFirstWire - 1 && fvw <= ew1 + 3 && fvw <= ew2 + 3 && fvw > (ew1 - 10) &&
2134 fvt = et1 + (fvw - ew1) * es1;
2137 <<
"Chk clusters topo1 " <<
tcl[it1].ID <<
" " <<
tcl[it2].ID <<
" vtx wire " 2138 << vw <<
" time " << (
int)fvt <<
" dth " << dth;
2139 if (fvt > 0 && fvt < maxtime) {
2143 SigOK = ChkSignal(vw, fvt, vw, fvt);
2147 SigOK = ChkSignal(vw, fvt, vw, fvt);
2150 if (SigOK) ChkVertex(fvw, fvt, it1, it2, 1);
2157 if (
tcl[it1].EndVtx < 0 &&
tcl[it2].BeginVtx < 0 && dth > angcut) {
2159 if (fabs(ew1 - bw2) < 3 && fabs(et1 - bt2) < 500) { fvw = 0.5 * (ew1 + bw2); }
2161 fvw = (et1 - ew1 * es1 - bt2 + bw2 * bs2) / dsl;
2163 if (fvw > 0 && fvw < nwires) {
2168 if (fvw <= ew1 + 2 && fvw >= bw2 - 2) {
2169 fvt = et1 + (vw - ew1) * es1;
2170 fvt += bt2 + (vw - bw2) * bs2;
2174 <<
"Chk clusters topo2 " <<
tcl[it1].ID <<
" " <<
tcl[it2].ID <<
" vtx wire " 2175 << vw <<
" time " << (
int)fvt <<
" dth " << dth;
2176 if (fvt > 0. && fvt < maxtime) {
2177 ChkVertex(fvw, fvt, it1, it2, 2);
2184 if (
tcl[it1].BeginVtx < 0 &&
tcl[it2].EndVtx < 0 && dth > angcut) {
2186 if (fabs(bw1 - ew2) < 3 && fabs(bt1 - et2) < 500) { fvw = 0.5 * (bw1 + ew2); }
2188 fvw = (et2 - ew2 * es2 - bt1 + bw1 * bs1) / dsl;
2190 if (fvw > 0 && fvw < nwires) {
2194 if (fvw <= ew2 + 2 && fvw >= bw1 - 2) {
2195 fvt = et2 + (fvw - ew2) * es2;
2196 fvt += bt1 + (fvw - bw1) * es1;
2200 <<
"Chk clusters topo3 " <<
tcl[it1].ID <<
" " <<
tcl[it2].ID <<
" vtx wire " 2201 << vw <<
" time " << (
int)fvt <<
" dth " << dth;
2202 if (fvt > 0. && fvt < maxtime) {
2203 ChkVertex(fvw, fvt, it1, it2, 3);
2210 if (
tcl[it1].BeginVtx < 0 &&
tcl[it2].BeginVtx < 0 && dth > 0.1) {
2214 fvw = (bt1 - bw1 * bs1 - bt2 + bw2 * bs2) / dsl;
2216 mf::LogVerbatim(
"CC") <<
"Chk clusters topo4 " << bw1 <<
":" << (
int)bt1 <<
" " << bw2
2217 <<
":" << (
int)bt2 <<
" fvw " << fvw <<
" nwires " <<
nwires;
2218 if (fvw > 0 && fvw < nwires) {
2224 if (
tcl[it1].tclhits.size() < 2 * dwcut) dwcut =
tcl[it1].tclhits.size() / 2;
2225 if (
tcl[it2].tclhits.size() < 2 * dwcut) dwcut =
tcl[it2].tclhits.size() / 2;
2226 if (fvw <= fLastWire + 1 && fvw >= bw1 - dwcut && fvw <= bw1 + dwcut &&
2227 fvw >= bw2 - dwcut && fvw <= bw1 + dwcut) {
2228 fvt = bt1 + (fvw - bw1) * bs1;
2231 <<
" vtx wire " << vw <<
" time " << fvt <<
" dth " << dth <<
" dwcut " << dwcut;
2232 if (fvt > 0. && fvt < maxtime) {
2236 SigOK = ChkSignal(vw, fvt, vw, fvt);
2240 SigOK = ChkSignal(vw, fvt, vw, fvt);
2243 if (SigOK) ChkVertex(fvw, fvt, it1, it2, 4);
2253 for (
unsigned short it = 0; it <
tcl.size(); ++it) {
2254 if (
tcl[it].
ID < 0)
continue;
2255 if (
tcl[it].CTP != clCTP)
continue;
2256 if (
tcl[it].BeginVtx > -1 &&
tcl[it].BeginVtx ==
tcl[it].EndVtx) {
2257 unsigned short iv =
tcl[it].BeginVtx;
2258 float dwir =
tcl[it].BeginWir - vtx[iv].Wire;
2259 float dtim =
tcl[it].BeginTim - vtx[iv].Time;
2260 float rbeg = dwir * dwir + dtim * dtim;
2261 dwir =
tcl[it].EndWir - vtx[iv].Wire;
2262 dtim =
tcl[it].EndTim - vtx[iv].Time;
2263 float rend = dwir * dwir + dtim * dtim;
2264 if (rend < rbeg) {
tcl[it].EndVtx = -99; }
2266 tcl[it].BeginVtx = -99;
2271 if (vtx.size() > vtxSizeIn) FitAllVtx(clCTP);
2274 for (
unsigned short ivx = 0; ivx < vtx.size(); ++ivx) {
2275 if (vtx[ivx].CTP != clCTP)
continue;
2276 if (vtx[ivx].NClusters == 1) {
2277 vtx[ivx].NClusters = 0;
2278 for (
unsigned short icl = 0; icl <
tcl.size(); ++icl) {
2279 if (
tcl[icl].CTP != clCTP)
continue;
2280 if (
tcl[icl].BeginVtx == ivx) {
2281 tcl[icl].BeginVtx = -99;
2284 if (
tcl[icl].EndVtx == ivx) {
2285 tcl[icl].EndVtx = -99;
2296 ClusterCrawlerAlg::ClusterVertex(
unsigned short it)
2300 if (vtx.size() == 0)
return;
2302 unsigned short iv, jv;
2303 short dwib, dwjb, dwie, dwje;
2304 bool matchEnd, matchBegin;
2306 for (iv = 0; iv < vtx.size(); ++iv) {
2308 if (vtx[iv].CTP != clCTP)
continue;
2310 if (vtx[iv].NClusters == 0)
continue;
2314 if (
tcl[it].tclhits.size() < 6) {
2317 if (dwib > 2) dwib = 2;
2319 if (dwie > 2) dwie = 2;
2322 for (jv = 0; jv < vtx.size(); ++jv) {
2323 if (iv == jv)
continue;
2324 if (
std::abs(vtx[jv].Time -
tcl[it].BeginTim) < 50) {
2328 if (
std::abs(vtx[jv].Time -
tcl[it].EndTim) < 50) {
2333 matchEnd =
tcl[it].EndVtx != iv && dwie < 3 && dwie < dwje && dwie < dwib;
2334 matchBegin =
tcl[it].BeginVtx != iv && dwib < 3 && dwib < dwjb && dwib < dwie;
2337 matchEnd =
tcl[it].EndVtx < 0 && vtx[iv].Wire <=
tcl[it].EndWir + 2;
2338 matchBegin =
tcl[it].BeginVtx < 0 && vtx[iv].Wire >=
tcl[it].BeginWir - 2;
2342 mf::LogVerbatim(
"CC") <<
" Match End chi " << ClusterVertexChi(it, 1, iv) <<
" to vtx " 2343 << iv <<
" signalOK " 2345 vtx[iv].
Wire, vtx[iv].Time,
tcl[it].EndWir,
tcl[it].EndTim);
2346 if (ClusterVertexChi(it, 1, iv) < fVertex2DCut &&
2347 ChkSignal(vtx[iv].Wire, vtx[iv].Time,
tcl[it].EndWir,
tcl[it].EndTim)) {
2349 tcl[it].EndVtx = iv;
2353 mf::LogVerbatim(
"CC") <<
" Add End " <<
tcl[it].ID <<
" to vtx " << iv <<
" NClusters " 2354 << vtx[iv].NClusters;
2355 if (vtx[iv].ChiDOF < fVertex2DCut && vtx[iv].WireErr < fVertex2DWireErrCut)
return;
2357 mf::LogVerbatim(
"CC") <<
" Bad fit. ChiDOF " << vtx[iv].ChiDOF <<
" WireErr " 2358 << vtx[iv].WireErr <<
" Undo it";
2359 tcl[it].EndVtx = -99;
2366 mf::LogVerbatim(
"CC") <<
" Match Begin chi " << ClusterVertexChi(it, 0, iv) <<
" to vtx " 2367 << iv <<
" signalOK " 2368 << ChkSignal(vtx[iv].
Wire,
2372 if (ClusterVertexChi(it, 0, iv) < fVertex2DCut &&
2373 ChkSignal(vtx[iv].Wire, vtx[iv].Time,
tcl[it].BeginWir,
tcl[it].BeginTim)) {
2375 tcl[it].BeginVtx = iv;
2380 <<
" NClusters " << vtx[iv].NClusters;
2381 if (vtx[iv].ChiDOF < fVertex2DCut && vtx[iv].WireErr < fVertex2DWireErrCut)
return;
2383 mf::LogVerbatim(
"CC") <<
" Bad fit. ChiDOF " << vtx[iv].ChiDOF <<
" WireErr " 2384 << vtx[iv].WireErr <<
" Undo it";
2385 tcl[it].BeginVtx = -99;
2394 ClusterCrawlerAlg::ChkVertex(
float fvw,
2410 <<
" - " <<
tcl[it1].BeginWir <<
":" << (
int)
tcl[it1].BeginTim
2411 <<
" and " <<
tcl[it2].EndWir <<
":" << (
int)
tcl[it2].EndTim <<
" - " 2412 <<
tcl[it2].BeginWir <<
":" << (
int)
tcl[it2].BeginTim <<
" topo " 2413 << topo <<
" fvw " << fvw <<
" fvt " << fvt;
2415 unsigned int vw = (
unsigned int)(0.5 + fvw);
2421 if (
tcl[it1].tclhits.size() < 10 &&
tcl[it2].tclhits.size() < 10) {
2422 for (
unsigned short it = 0; it <
tcl.size(); ++it) {
2423 if (it == it1 || it == it2)
continue;
2424 if (
tcl[it].
ID < 0)
continue;
2425 if (
tcl[it].CTP != clCTP)
continue;
2426 if (
tcl[it].tclhits.size() < 100)
continue;
2429 if (vw <
tcl[it].EndWir + 5)
continue;
2430 if (vw >
tcl[it].BeginWir - 5)
continue;
2431 for (
unsigned short ii = 0; ii <
tcl[it].tclhits.size(); ++ii) {
2432 iht =
tcl[it].tclhits[ii];
2433 if (fHits[iht].
WireID().Wire <= vw) {
2434 if (
std::abs(fHits[iht].PeakTime() - fvt) < 60)
return;
2441 unsigned short nFitOK = 0;
2442 for (
unsigned short iv = 0; iv < vtx.size(); ++iv) {
2443 if (vtx[iv].CTP != clCTP)
continue;
2445 if (PointVertexChi(fvw, fvt, iv) > 300)
continue;
2448 << PointVertexChi(fvw, fvt, iv);
2450 if ((topo == 1 || topo == 2) &&
tcl[it1].EndVtx < 0) {
2451 if (ChkSignal(vw, fvt,
tcl[it1].EndWir,
tcl[it1].EndTim)) {
2453 tcl[it1].EndVtx = iv;
2456 mf::LogVerbatim(
"CC") <<
" FitVtx " << iv <<
" WireErr " << vtx[iv].WireErr
2457 <<
" ChiDOF " << vtx[iv].ChiDOF;
2458 if (vtx[iv].WireErr < fVertex2DWireErrCut && vtx[iv].ChiDOF < 5) { ++nFitOK; }
2461 tcl[it1].EndVtx = -99;
2466 else if ((topo == 3 || topo == 4) &&
tcl[it1].BeginVtx < 0) {
2467 if (ChkSignal(vw, fvt,
tcl[it1].BeginWir,
tcl[it1].BeginTim)) {
2468 tcl[it1].BeginVtx = iv;
2471 mf::LogVerbatim(
"CC") <<
" FitVtx " << iv <<
" WireErr " << vtx[iv].WireErr
2472 <<
" ChiDOF " << vtx[iv].ChiDOF;
2473 if (vtx[iv].WireErr < fVertex2DWireErrCut && vtx[iv].ChiDOF < 5) { ++nFitOK; }
2476 tcl[it1].BeginVtx = -99;
2481 if ((topo == 1 || topo == 3) &&
tcl[it2].EndVtx < 0) {
2482 if (ChkSignal(vw, fvt,
tcl[it2].EndWir,
tcl[it2].EndTim)) {
2483 tcl[it2].EndVtx = iv;
2486 mf::LogVerbatim(
"CC") <<
" FitVtx " << iv <<
" WireErr " << vtx[iv].WireErr
2487 <<
" ChiDOF " << vtx[iv].ChiDOF;
2488 if (vtx[iv].WireErr < fVertex2DWireErrCut && vtx[iv].ChiDOF < 5) { ++nFitOK; }
2491 tcl[it2].EndVtx = -99;
2496 else if ((topo == 2 || topo == 4) &&
tcl[it2].BeginVtx < 0) {
2497 if (ChkSignal(vw, fvt,
tcl[it2].BeginWir,
tcl[it2].BeginTim)) {
2498 tcl[it2].BeginVtx = iv;
2501 mf::LogVerbatim(
"CC") <<
" FitVtx " << iv <<
" WireErr " << vtx[iv].WireErr
2502 <<
" ChiDOF " << vtx[iv].ChiDOF;
2503 if (vtx[iv].WireErr < fVertex2DWireErrCut && vtx[iv].ChiDOF < 5) { ++nFitOK; }
2506 tcl[it2].BeginVtx = -99;
2512 if (vtxprt)
mf::LogVerbatim(
"CC") <<
" Attached " << nFitOK <<
" clusters to vertex " << iv;
2520 if (topo == 1 || topo == 2) { SigOK = ChkSignal(vw, fvt,
tcl[it1].EndWir,
tcl[it1].EndTim); }
2522 SigOK = ChkSignal(vw, fvt,
tcl[it1].BeginWir,
tcl[it1].BeginTim);
2526 if (topo == 1 || topo == 3) { SigOK = ChkSignal(vw, fvt,
tcl[it2].EndWir,
tcl[it2].EndTim); }
2528 SigOK = ChkSignal(vw, fvt,
tcl[it2].BeginWir,
tcl[it2].BeginTim);
2537 newvx.
Fixed =
false;
2538 vtx.push_back(newvx);
2539 unsigned short iv = vtx.size() - 1;
2540 if (topo == 1 || topo == 2) {
2541 if (
tcl[it1].EndVtx >= 0) {
2545 tcl[it1].EndVtx = iv;
2548 if (
tcl[it1].BeginVtx >= 0) {
2552 tcl[it1].BeginVtx = iv;
2554 if (topo == 1 || topo == 3) {
2555 if (
tcl[it2].EndVtx >= 0) {
2559 tcl[it2].EndVtx = iv;
2562 if (
tcl[it2].BeginVtx >= 0) {
2566 tcl[it2].BeginVtx = iv;
2571 if (vtx[iv].ChiDOF < 5 && vtx[iv].WireErr < fVertex2DWireErrCut && vtx[iv].TimeErr < 20) {
2573 mf::LogVerbatim(
"CC") <<
" New vtx " << iv <<
" in plane " << plane <<
" topo " << topo
2574 <<
" cls " <<
tcl[it1].ID <<
" " <<
tcl[it2].ID <<
" W:T " << (
int)vw
2575 <<
":" << (
int)fvt <<
" NClusters " << vtx[iv].NClusters;
2577 if (fRefineVertexClusters) RefineVertexClusters(iv);
2581 mf::LogVerbatim(
"CC") <<
" Bad vtx fit " << vtx[iv].ChiDOF <<
" wire err " 2582 << vtx[iv].WireErr <<
" TimeErr " << vtx[iv].TimeErr;
2585 if (
tcl[it1].BeginVtx == iv)
tcl[it1].BeginVtx = -99;
2586 if (
tcl[it1].EndVtx == iv)
tcl[it1].EndVtx = -99;
2587 if (
tcl[it2].BeginVtx == iv)
tcl[it2].BeginVtx = -99;
2588 if (
tcl[it2].EndVtx == iv)
tcl[it2].EndVtx = -99;
2595 ClusterCrawlerAlg::ChkSignal(
unsigned int iht,
unsigned int jht)
2597 if (iht > fHits.size() - 1)
return false;
2598 if (jht > fHits.size() - 1)
return false;
2599 unsigned int wire1 = fHits[iht].WireID().Wire;
2600 float time1 = fHits[iht].PeakTime();
2601 unsigned int wire2 = fHits[jht].WireID().Wire;
2602 float time2 = fHits[jht].PeakTime();
2603 return ChkSignal(wire1, time1, wire2, time2);
2608 ClusterCrawlerAlg::ChkSignal(
unsigned int wire1,
float time1,
unsigned int wire2,
float time2)
2615 const float gausAmp[20] = {1, 0.99, 0.96, 0.90, 0.84, 0.75, 0.67, 0.58, 0.49, 0.40,
2616 0.32, 0.26, 0.20, 0.15, 0.11, 0.08, 0.06, 0.04, 0.03, 0.02};
2619 if (fMinAmp[plane] <= 0)
return true;
2622 unsigned int wireb = wire1;
2623 float timeb = time1;
2624 unsigned int wiree = wire2;
2625 float timee = time2;
2627 if (wiree > wireb) {
2633 if (wiree < fFirstWire || wiree > fLastWire)
return false;
2634 if (wireb < fFirstWire || wireb > fLastWire)
return false;
2639 bool oneWire =
false;
2640 float prTime, prTimeLo = 0, prTimeHi = 0;
2641 if (wireb == wiree) {
2643 if (time1 < time2) {
2653 slope = (timeb - timee) / (wireb - wiree);
2657 unsigned short nmissed = 0;
2658 for (
unsigned int wire = wiree; wire < wireb + 1; ++wire) {
2659 if (oneWire) { prTime = (prTimeLo + prTimeHi) / 2; }
2661 prTime = timee + (wire - wire0) * slope;
2664 if (WireHitRange[wire].first == -1)
continue;
2666 if (WireHitRange[wire].first == -2) ++nmissed;
2667 unsigned int firsthit = WireHitRange[wire].first;
2668 unsigned int lasthit = WireHitRange[wire].second;
2670 for (
unsigned int khit = firsthit; khit < lasthit; ++khit) {
2674 if (prTime < fHits[khit].StartTick())
continue;
2675 if (prTime > fHits[khit].EndTick())
continue;
2680 if (fHits[khit].PeakTime() - prTime > 500)
continue;
2681 bin =
std::abs(fHits[khit].PeakTime() - prTime) / fHits[khit].RMS();
2683 if (bin > 19)
continue;
2684 if (bin < 0)
continue;
2686 amp += fHits[khit].PeakAmplitude() * gausAmp[
bin];
2689 if (amp < fMinAmp[plane]) ++nmissed;
2691 if (nmissed > fAllowNoHitWire)
return false;
2698 ClusterCrawlerAlg::SplitCluster(
unsigned short icl,
unsigned short pos,
unsigned short ivx)
2702 if (
tcl[icl].
ID < 0)
return false;
2705 MakeClusterObsolete(icl);
2707 unsigned short ii, iclnew;
2713 clBeginSlp =
tcl[icl].BeginSlp;
2714 clBeginSlpErr =
tcl[icl].BeginSlpErr;
2715 clBeginAng =
tcl[icl].BeginAng;
2716 clBeginWir =
tcl[icl].BeginWir;
2717 clBeginTim =
tcl[icl].BeginTim;
2718 clBeginChg =
tcl[icl].BeginChg;
2720 clProcCode =
tcl[icl].ProcCode;
2725 for (ii = 0; ii <
pos; ++ii) {
2726 iht =
tcl[icl].tclhits[ii];
2727 fcl2hits.push_back(iht);
2730 pass =
tcl[icl].ProcCode - 10 * (
tcl[icl].ProcCode / 10);
2731 if (
pass > fNumPass - 1)
pass = fNumPass - 1;
2734 clEndSlp = clpar[1];
2735 clEndSlpErr = clparerr[1];
2736 clEndAng = std::atan(fScaleF * clEndSlp);
2741 RestoreObsoleteCluster(icl);
2745 iclnew =
tcl.size() - 1;
2746 tcl[iclnew].EndVtx = ivx;
2747 tcl[iclnew].BeginVtx =
tcl[icl].BeginVtx;
2749 mf::LogVerbatim(
"CC") <<
"SplitCluster made cluster " << iclnew <<
" attached to Begin vtx " 2753 if (pos <
tcl[icl].tclhits.size() - 3) {
2756 clEndSlp =
tcl[icl].EndSlp;
2757 clEndSlpErr =
tcl[icl].EndSlpErr;
2758 clEndAng = std::atan(fScaleF * clEndSlp);
2759 clEndWir =
tcl[icl].EndWir;
2760 clEndTim =
tcl[icl].EndTim;
2761 clEndChg =
tcl[icl].EndChg;
2763 clProcCode =
tcl[icl].ProcCode;
2768 bool didFit =
false;
2769 for (ii = pos; ii <
tcl[icl].tclhits.size(); ++ii) {
2770 iht =
tcl[icl].tclhits[ii];
2771 if (inClus[iht] != 0) {
2772 RestoreObsoleteCluster(icl);
2775 fcl2hits.push_back(iht);
2777 if (fcl2hits.size() == fMaxHitsFit[
pass] || fcl2hits.size() == fMinHits[
pass]) {
2779 clBeginSlp = clpar[1];
2780 clBeginAng = std::atan(fScaleF * clBeginSlp);
2781 clBeginSlpErr = clparerr[1];
2784 if ((
unsigned short)fcl2hits.size() == fNHitsAve[
pass] + 1) {
2786 clBeginChg = fAveChg;
2794 clBeginChg = fAveChg;
2798 MakeClusterObsolete(
tcl.size() - 1);
2799 RestoreObsoleteCluster(icl);
2803 iclnew =
tcl.size() - 1;
2804 tcl[iclnew].BeginVtx = ivx;
2805 tcl[iclnew].EndVtx =
tcl[icl].EndVtx;
2807 mf::LogVerbatim(
"CC") <<
"SplitCluster made cluster " << iclnew <<
" attached to End vtx " 2816 ClusterCrawlerAlg::ChkMerge()
2821 if (
tcl.size() < 2)
return;
2826 prt = (fDebugPlane == (short)plane && fDebugWire < 0);
2829 unsigned short it1, it2, nh1, pass1, pass2;
2830 float bs1, bth1, bt1, bc1, es1, eth1, et1, ec1;
2831 float bs2, bth2, bt2, bc2, es2, eth2, et2, ec2;
2832 int bw1, ew1, bw2, ew2, ndead;
2833 float dth, dw, angcut, chgrat, chgcut, dtim, timecut, bigslp;
2834 bool bothLong, NoVtx;
2836 int skipcut, tclsize =
tcl.size();
2839 for (it1 = 0; it1 < tclsize - 1; ++it1) {
2841 if (
tcl[it1].
ID < 0)
continue;
2842 if (
tcl[it1].CTP != clCTP)
continue;
2843 bs1 =
tcl[it1].BeginSlp;
2845 bth1 = std::atan(fScaleF * bs1);
2847 bw1 =
tcl[it1].BeginWir;
2848 bt1 =
tcl[it1].BeginTim;
2849 bc1 =
tcl[it1].BeginChg;
2850 es1 =
tcl[it1].EndSlp;
2851 eth1 =
tcl[it1].EndAng;
2852 ew1 =
tcl[it1].EndWir;
2853 et1 =
tcl[it1].EndTim;
2854 ec1 =
tcl[it1].EndChg;
2855 nh1 =
tcl[it1].tclhits.size();
2856 pass1 =
tcl[it1].ProcCode - 10 * (
tcl[it1].ProcCode / 10);
2857 if (pass1 > fNumPass) pass1 = fNumPass;
2858 for (it2 = it1 + 1; it2 < tclsize; ++it2) {
2860 if (
tcl[it1].
ID < 0)
continue;
2861 if (
tcl[it2].
ID < 0)
continue;
2863 if (
tcl[it2].CTP != clCTP)
continue;
2866 if (!ChkMergedClusterHitFrac(it1, it2)) {
continue; }
2867 bs2 =
tcl[it2].BeginSlp;
2868 bth2 = std::atan(fScaleF * bs2);
2869 bw2 =
tcl[it2].BeginWir;
2870 bt2 =
tcl[it2].BeginTim;
2871 bc2 =
tcl[it2].BeginChg;
2872 es2 =
tcl[it2].EndSlp;
2873 eth2 =
tcl[it2].EndAng;
2874 ew2 =
tcl[it2].EndWir;
2875 et2 =
tcl[it2].EndTim;
2876 ec2 =
tcl[it2].EndChg;
2877 pass2 =
tcl[it2].ProcCode - 10 * (
tcl[it2].ProcCode / 10);
2878 if (pass2 > fNumPass) pass2 = fNumPass;
2880 angcut = fKinkAngCut[pass1];
2881 if (fKinkAngCut[pass2] > angcut) angcut = fKinkAngCut[pass2];
2882 skipcut = fMaxWirSkip[pass1];
2883 if (fMaxWirSkip[pass2] > skipcut) skipcut = fMaxWirSkip[pass2];
2884 chgcut = fMergeChgCut[pass1];
2885 if (fMergeChgCut[pass2] > chgcut) chgcut = fMergeChgCut[pass2];
2887 bothLong = (nh1 > 100 &&
tcl[it2].tclhits.size() > 100);
2895 dw = ew1 - bw2 - ndead;
2897 NoVtx = (
tcl[it1].EndVtx < 0) && (
tcl[it2].BeginVtx < 0);
2898 if (prt && bw2 < (ew1 + maxOverlap))
2900 <<
":" << (
int)et1 <<
" " << bw2 <<
":" << (
int)bt2 <<
" dw " << dw
2901 <<
" ndead " << ndead <<
" skipcut " << skipcut <<
" dth " << dth
2902 <<
" angcut " << angcut;
2903 if (NoVtx && bw2 < (ew1 + maxOverlap) && dw < skipcut && dth < angcut) {
2904 chgrat = 2 * fabs(bc2 - ec1) / (bc2 + ec1);
2906 if (bothLong && dth < 0.05) chgrat = 0.;
2908 dtim = fabs(bt2 + (ew1 - bw2) * bs2 - et1);
2911 timecut = fTimeDelta[pass2] * AngleFactor(bigslp);
2914 << ec1 <<
" bc2 " << bc2 <<
" chgrat " << chgrat <<
" chgcut " 2915 << chgcut <<
" es1 " << es1 <<
" ChkSignal " 2916 << ChkSignal(ew1, et1, bw2, bt2);
2917 if (chgrat < chgcut && dtim < timecut) {
2919 if (ChkSignal(ew1, et1, bw2, bt2)) {
2920 DoMerge(it2, it1, 10);
2921 tclsize =
tcl.size();
2929 dth = fabs(bth1 - eth2);
2931 dw = ew2 - bw1 - ndead;
2932 if (prt && bw1 < (ew2 + maxOverlap) && dw < skipcut)
2934 <<
":" << (
int)bt1 <<
" " << bw2 <<
":" << (
int)et2 <<
" dw " << dw
2935 <<
" ndead " << ndead <<
" skipcut " << skipcut <<
" dth " << dth
2936 <<
" angcut " << angcut;
2938 NoVtx = (
tcl[it2].EndVtx < 0) && (
tcl[it1].BeginVtx < 0);
2939 if (NoVtx && bw1 < (ew2 + maxOverlap) && dw < skipcut && dth < angcut) {
2940 chgrat = 2 * fabs((bc1 - ec2) / (bc1 + ec2));
2942 if (bothLong && dth < 0.05) chgrat = 0.;
2944 dtim =
std::abs(bt1 + (ew2 - bw1) * bs1 - et2);
2947 timecut = fTimeDelta[pass2] * AngleFactor(bigslp);
2949 mf::LogVerbatim(
"CC") <<
" dtim " << dtim <<
" err " << dtim <<
" timecut " 2950 << (
int)timecut <<
" chgrat " << chgrat <<
" chgcut " << chgcut
2951 <<
" ChkSignal " << ChkSignal(bw1, bt1, ew2, et2);
2953 if (chgrat < chgcut && dtim < timecut) {
2954 if (ChkSignal(bw1, bt1, ew2, et2)) {
2955 DoMerge(it1, it2, 10);
2956 tclsize =
tcl.size();
2962 if (bw2 < bw1 && ew2 > ew1) {
2965 dth = fabs(eth2 - eth1);
2966 dtim = fabs(et1 + (ew2 - ew1 - 1) * es1 - et2);
2969 timecut = fTimeDelta[pass2] * AngleFactor(bigslp);
2971 short nmiss1 = bw1 - ew1 + 1 -
tcl[it1].tclhits.size();
2973 short nin2 =
tcl[it2].tclhits.size();
2976 << (
int)bt2 <<
" within cl1 " << ew1 <<
":" << (
int)et1 <<
" - " 2977 << bw1 <<
":" << (
int)bt1 <<
" ? dth " << dth <<
" dtim " << dtim
2978 <<
" nmissed " << nmiss1 <<
" timecut " << timecut
2979 <<
" FIX THIS CODE";
2984 if (dth < 1 && dtim < timecut && nmiss1 >= nin2) ChkMerge12(it1, it2, didit);
2986 tclsize =
tcl.size();
2991 if (bw1 < bw2 && ew1 > ew2) {
2995 dtim =
std::abs(et2 + (ew1 - ew2 - 1) * es2 - et1);
2998 timecut = fTimeDelta[pass2] * AngleFactor(bigslp);
3000 short nmiss2 = bw2 - ew2 + 1 -
tcl[it2].tclhits.size();
3002 short nin1 =
tcl[it1].tclhits.size();
3005 << (
int)bt1 <<
" within cl2 " << ew2 <<
":" << (
int)et2 <<
" - " 3006 << bw2 <<
":" << (
int)bt2 <<
" ? dth " << dth <<
" dtim " << dtim
3007 <<
" nmissed " << nmiss2 <<
" timecut " << timecut
3008 <<
" FIX THIS CODE";
3012 if (dth < 1 && dtim < timecut && nmiss2 >= nin1) ChkMerge12(it2, it1, didit);
3014 tclsize =
tcl.size();
3019 if (
tcl[it1].
ID < 0)
break;
3021 if (
tcl[it1].
ID < 0)
continue;
3027 ClusterCrawlerAlg::ChkMerge12(
unsigned short it1,
unsigned short it2,
bool& didit)
3042 int ew1 =
tcl[it1].EndWir;
3043 int bw1 =
tcl[it1].BeginWir;
3044 unsigned int iht,
hit;
3046 std::vector<unsigned int> cl1hits(bw1 + 1 - ew1);
3048 for (iht = 0; iht < cl1.
tclhits.size(); ++iht) {
3050 wire = fHits[
hit].WireID().Wire;
3051 if (wire - ew1 < 0 || wire - ew1 > (
int)cl1hits.size()) {
return; }
3052 cl1hits[wire - ew1] =
hit;
3054 unsigned int ew2 =
tcl[it2].EndWir;
3055 float et2 =
tcl[it2].EndTim;
3057 unsigned int wiron1 = 0;
3060 for (wire = ew2 - 1; wire > ew1; --wire) {
3061 if (cl1hits[wire - ew1] > 0) {
3067 if (prt)
mf::LogVerbatim(
"CC") <<
"chk next US wire " << wiron1 <<
" missed " << nmiss;
3068 if (wiron1 == 0)
return;
3069 if (nmiss > fMaxWirSkip[
pass])
return;
3073 unsigned int hiton2;
3075 unsigned short nfit = 0;
3076 for (iht = 0; iht <
tcl[it2].tclhits.size(); ++iht) {
3077 hiton2 =
tcl[it2].tclhits[iht];
3078 wiron2 = fHits[hiton2].WireID().Wire;
3079 if (wiron2 < ew1 || wiron2 > bw1)
return;
3080 if (cl1hits[wiron2 - ew1] == 0) ++nfit;
3083 if (nfit <
tcl[it2].tclhits.size())
return;
3086 unsigned short pass1 =
tcl[it1].ProcCode - 10 * (
tcl[it1].ProcCode / 10);
3087 unsigned short pass2 =
tcl[it2].ProcCode - 10 * (
tcl[it2].ProcCode / 10);
3088 unsigned short cpass = pass1;
3090 if (pass2 < pass1) cpass = pass2;
3093 if ((
int)wiron1 - ew1 < 0)
return;
3094 unsigned int hiton1 = cl1hits[wiron1 - ew1];
3095 if (hiton1 > fHits.size() - 1) {
return; }
3097 float timon1 = fHits[hiton1].PeakTime();
3098 float dtim =
std::abs(et2 + (wiron1 - ew2) *
tcl[it2].EndSlp - timon1);
3099 if (dtim > fTimeDelta[cpass])
return;
3102 FitClusterMid(it1, hiton1, 3);
3103 if (clChisq > 20.)
return;
3106 float dth =
std::abs(std::atan(fScaleF * clpar[1]) - std::atan(fScaleF *
tcl[it2].EndSlp));
3107 if (prt)
mf::LogVerbatim(
"CC") <<
"US dtheta " << dth <<
" cut " << fKinkAngCut[cpass];
3108 if (dth > fKinkAngCut[cpass])
return;
3110 float chgrat = 2 *
std::abs(fAveChg -
tcl[it2].EndChg) / (fAveChg +
tcl[it2].EndChg);
3111 if (prt)
mf::LogVerbatim(
"CC") <<
"US chgrat " << chgrat <<
" cut " << fMergeChgCut[
pass];
3114 SigOK = ChkSignal(wiron1, timon1, ew2, et2);
3119 unsigned int bw2 =
tcl[it2].BeginWir;
3120 float bt2 =
tcl[it2].BeginTim;
3123 for (wire = bw2 + 1; wire < bw1; ++wire) {
3124 if (cl1hits[wire - ew1] > 0) {
3130 if (wiron1 == 0)
return;
3131 if (nmiss > fMaxWirSkip[pass])
return;
3134 hiton1 = cl1hits[wiron1 - ew1];
3135 if (hiton1 > fHits.size() - 1) {
return; }
3136 timon1 = fHits[hiton1].PeakTime();
3137 dtim =
std::abs(bt2 - (wiron1 - bw2) *
tcl[it2].BeginSlp - timon1);
3138 if (dtim > fTimeDelta[cpass])
return;
3139 FitClusterMid(it1, hiton1, -3);
3140 if (clChisq > 20.)
return;
3142 dth =
std::abs(std::atan(fScaleF * clpar[1]) - std::atan(fScaleF *
tcl[it2].BeginSlp));
3143 if (prt)
mf::LogVerbatim(
"CC") <<
"DS dtheta " << dth <<
" cut " << fKinkAngCut[cpass];
3144 if (dth > fKinkAngCut[cpass])
return;
3146 chgrat = 2 *
std::abs(fAveChg -
tcl[it2].BeginChg) / (fAveChg +
tcl[it2].BeginChg);
3147 if (prt)
mf::LogVerbatim(
"CC") <<
"DS chgrat " << chgrat <<
" cut " << fMergeChgCut[
pass];
3149 SigOK = ChkSignal(wiron1, timon1, bw2, bt2);
3155 DoMerge(it1, it2, 100);
3161 ClusterCrawlerAlg::DoMerge(
unsigned short it1,
unsigned short it2,
short inProcCode)
3168 if (cl1.
tclhits.size() < 3)
return;
3169 if (cl2.
tclhits.size() < 3)
return;
3171 unsigned int lowire, hiwire, whsize, ii, iht, indx;
3174 unsigned int fithit;
3189 whsize = hiwire + 2 - lowire;
3190 std::vector<int> wirehit(whsize, -1);
3192 for (ii = 0; ii < cl2.
tclhits.size(); ++ii) {
3194 indx = fHits[iht].WireID().Wire - lowire;
3195 wirehit[indx] = iht;
3198 for (ii = 0; ii < cl1.
tclhits.size(); ++ii) {
3200 indx = fHits[iht].WireID().Wire - lowire;
3201 wirehit[indx] = iht;
3205 for (std::vector<int>::reverse_iterator rit = wirehit.rbegin(); rit != wirehit.rend(); ++rit) {
3206 if (*rit < 0)
continue;
3207 fcl2hits.push_back(*rit);
3212 FitClusterMid(fcl2hits, fithit, nhitfit);
3213 if (clChisq > 5)
return;
3216 MakeClusterObsolete(it1);
3217 MakeClusterObsolete(it2);
3221 short del1Vtx = -99;
3222 short del2Vtx = -99;
3271 if (!TmpStore())
return;
3272 unsigned short itnew =
tcl.size() - 1;
3276 tcl[itnew].ProcCode = inProcCode +
pass;
3279 if (del1Vtx >= 0 && del1Vtx == del2Vtx) vtx[del1Vtx].NClusters = 0;
3281 tcl[itnew].BeginVtx = begVtx;
3282 tcl[itnew].EndVtx = endVtx;
3287 ClusterCrawlerAlg::PrintVertices()
3292 if (vtx3.size() > 0) {
3295 <<
"****** 3D vertices ******************************************__2DVtx_Indx__*******\n";
3297 <<
"Vtx Cstat TPC Proc X Y Z XEr YEr ZEr pln0 pln1 pln2 Wire\n";
3298 for (
unsigned short iv = 0; iv < vtx3.size(); ++iv) {
3313 if (vtx3[iv].
Wire < 0) { myprt <<
" Matched in all planes"; }
3315 myprt <<
" Incomplete";
3321 if (vtx.size() > 0) {
3323 myprt <<
"************ 2D vertices ************\n";
3324 myprt <<
"Vtx CTP wire error tick error ChiDOF NCl topo cluster IDs\n";
3325 for (
unsigned short iv = 0; iv < vtx.size(); ++iv) {
3326 if (fDebugPlane < 3 && fDebugPlane != (
int)vtx[iv].CTP)
continue;
3338 for (
unsigned short ii = 0; ii <
tcl.size(); ++ii) {
3339 if (fDebugPlane < 3 && fDebugPlane != (
int)
tcl[ii].CTP)
continue;
3340 if (
tcl[ii].
ID < 0)
continue;
3360 float aveRMS, aveRes;
3361 myprt <<
"*************************************** Clusters " 3362 "*********************************************************************\n";
3363 myprt <<
" ID CTP nht Stop Proc beg_W:T bAng bSlp Err bChg end_W:T eAng eSlp " 3364 "Err eChg bVx eVx aveRMS Qual cnt\n";
3365 for (
unsigned short ii = 0; ii <
tcl.size(); ++ii) {
3367 if (fDebugPlane < 3 && fDebugPlane != (
int)
tcl[ii].CTP)
continue;
3373 unsigned int iTime =
tcl[ii].BeginTim;
3375 if (iTime < 10) { myprt <<
" "; }
3376 else if (iTime < 100) {
3379 else if (iTime < 1000)
3384 <<
tcl[ii].BeginSlp;
3390 <<
tcl[ii].BeginSlpErr;
3392 iTime =
tcl[ii].EndTim;
3394 if (iTime < 10) { myprt <<
" "; }
3395 else if (iTime < 100) {
3398 else if (iTime < 1000)
3408 <<
tcl[ii].EndSlpErr;
3413 unsigned int iht = 0;
3414 for (
unsigned short jj = 0; jj <
tcl[ii].tclhits.size(); ++jj) {
3415 iht =
tcl[ii].tclhits[jj];
3416 aveRMS += fHits[iht].RMS();
3418 aveRMS /= (
float)
tcl[ii].tclhits.size();
3422 unsigned int hit0, hit1, hit2, cnt = 0;
3424 for (
unsigned short iht = 1; iht <
tcl[ii].tclhits.size() - 1; ++iht) {
3425 hit1 =
tcl[ii].tclhits[iht];
3426 hit0 =
tcl[ii].tclhits[iht - 1];
3427 hit2 =
tcl[ii].tclhits[iht + 1];
3429 if (fHits[hit1].
WireID().Wire + 1 != fHits[hit0].WireID().Wire)
continue;
3430 if (fHits[hit2].
WireID().Wire + 1 != fHits[hit1].WireID().Wire)
continue;
3431 arg = (fHits[hit0].PeakTime() + fHits[hit2].PeakTime()) / 2 - fHits[hit1].PeakTime();
3432 aveRes += arg * arg;
3436 aveRes /= (
float)cnt;
3437 aveRes = sqrt(aveRes);
3439 aveRes /= (aveRMS * fHitErrFac);
3454 ClusterCrawlerAlg::TmpGet(
unsigned short it1)
3459 if (it1 >
tcl.size())
return;
3461 clBeginSlp =
tcl[it1].BeginSlp;
3462 clBeginSlpErr =
tcl[it1].BeginSlpErr;
3463 clBeginAng =
tcl[it1].BeginAng;
3464 clBeginWir =
tcl[it1].BeginWir;
3465 clBeginTim =
tcl[it1].BeginTim;
3466 clBeginChg =
tcl[it1].BeginChg;
3467 clBeginChgNear =
tcl[it1].BeginChgNear;
3468 clEndSlp =
tcl[it1].EndSlp;
3469 clEndSlpErr =
tcl[it1].EndSlpErr;
3470 clEndAng =
tcl[it1].EndAng;
3471 clEndWir =
tcl[it1].EndWir;
3472 clEndTim =
tcl[it1].EndTim;
3473 clEndChg =
tcl[it1].EndChg;
3474 clEndChgNear =
tcl[it1].EndChgNear;
3475 clStopCode =
tcl[it1].StopCode;
3476 clProcCode =
tcl[it1].ProcCode;
3477 clCTP =
tcl[it1].CTP;
3478 fcl2hits =
tcl[it1].tclhits;
3483 ClusterCrawlerAlg::TmpStore()
3486 if (fcl2hits.size() < 2)
return false;
3487 if (fcl2hits.size() > fHits.size())
return false;
3489 if (NClusters == SHRT_MAX)
return false;
3493 unsigned int hit0 = fcl2hits[0];
3495 unsigned int tCST = fHits[hit0].WireID().Cryostat;
3496 unsigned int tTPC = fHits[hit0].WireID().TPC;
3497 unsigned int tPlane = fHits[hit0].WireID().Plane;
3498 unsigned int lastWire = 0;
3500 for (
unsigned short it = 0; it < fcl2hits.size(); ++it) {
3502 if (inClus[hit] != 0) {
3507 if (fHits[hit].
WireID().Cryostat != tCST || fHits[
hit].WireID().TPC != tTPC ||
3508 fHits[
hit].WireID().Plane != tPlane) {
3513 if (clProcCode < 900 && it > 0 && fHits[hit].
WireID().Wire >= lastWire) {
3517 lastWire = fHits[
hit].WireID().Wire;
3518 inClus[
hit] = NClusters;
3524 if (clEndChg <= 0) {
3526 unsigned int ih0 = fcl2hits.size() - 2;
3527 hit = fcl2hits[ih0];
3528 clEndChg = fHits[
hit].Integral();
3529 hit = fcl2hits[ih0 - 1];
3530 clEndChg += fHits[
hit].Integral();
3531 clEndChg = clEndChg / 2.;
3533 if (clBeginChg <= 0) {
3536 clBeginChg = fHits[
hit].Integral();
3538 clBeginChg += fHits[
hit].Integral();
3539 clBeginChg = clBeginChg / 2.;
3543 hit = fcl2hits[fcl2hits.size() - 1];
3548 clstr.
ID = NClusters;
3551 clstr.
BeginAng = std::atan(fScaleF * clBeginSlp);
3552 clstr.
BeginWir = fHits[hit0].WireID().Wire;
3553 clstr.
BeginTim = fHits[hit0].PeakTime();
3558 clstr.
EndAng = std::atan(fScaleF * clEndSlp);
3559 clstr.
EndWir = fHits[
hit].WireID().Wire;
3569 tcl.push_back(clstr);
3576 ClusterCrawlerAlg::LACrawlUS()
3581 unsigned int dhit = fcl2hits[0];
3582 short dwir = fHits[dhit].WireID().Wire;
3585 if (fDebugPlane == (
short)plane && dwir == fDebugWire && fDebugHit > 0)
3586 prt =
std::abs(fHits[dhit].PeakTime() - fDebugHit) < 40;
3590 myprt <<
"******************* LACrawlUS PASS " <<
pass <<
" Hits ";
3591 for (
unsigned short ii = 0; ii < fcl2hits.size(); ++ii) {
3592 unsigned int iht = fcl2hits[fcl2hits.size() - 1 - ii];
3593 myprt << fHits[iht].WireID().Wire <<
":" << (
int)fHits[iht].PeakTime() <<
" ";
3602 unsigned short kinkOnWire = 0;
3603 unsigned int it = fcl2hits.size() - 1;
3604 unsigned int lasthit = fcl2hits[it];
3605 unsigned int lastwire = fHits[lasthit].WireID().Wire;
3606 unsigned int prevHit, prevWire;
3607 bool ChkCharge =
false;
3608 for (
unsigned int nextwire = lastwire - 1; nextwire >= fFirstWire; --nextwire) {
3610 mf::LogVerbatim(
"CC") <<
"LACrawlUS: next wire " << nextwire <<
" HitRange " 3611 << WireHitRange[nextwire].first;
3613 if (CrawlVtxChk(nextwire)) {
3619 AddLAHit(nextwire, ChkCharge, HitOK, SigOK);
3621 mf::LogVerbatim(
"CC") <<
"LACrawlUS: HitOK " << HitOK <<
" SigOK " << SigOK
3622 <<
" nmissed SigOK " << nmissed <<
" cut " << fAllowNoHitWire;
3623 if (SigOK) nmissed = 0;
3626 if (nmissed > fAllowNoHitWire) {
3635 prevHit = fcl2hits[fcl2hits.size() - 2];
3636 prevWire = fHits[prevHit].WireID().Wire;
3637 if (prevWire > nextwire + 2) {
3638 if (!ChkSignal(fcl2hits[fcl2hits.size() - 1], fcl2hits[fcl2hits.size() - 2])) {
3648 if (fcl2hits.size() == 4) {
3650 for (
unsigned short kk = 0; kk < fcl2hits.size() - 1; ++kk) {
3651 unsigned int hit = fcl2hits[kk];
3652 if (mergeAvailable[hit]) MergeHits(hit, didMerge);
3656 clBeginSlp = clpar[1];
3661 unsigned short chsiz = chifits.size() - 1;
3663 if (chsiz < 6)
continue;
3664 if (fKinkChiRat[
pass] <= 0)
continue;
3665 if (chifits.size() != fcl2hits.size()) {
3666 mf::LogError(
"CC") <<
"LACrawlUS: chifits size error " << chifits.size() <<
" " 3671 mf::LogVerbatim(
"CC") <<
"Kink chk " << chifits[chsiz] <<
" " << chifits[chsiz - 1] <<
" " 3672 << chifits[chsiz - 2] <<
" " << chifits[chsiz - 3];
3673 if (chifits[chsiz - 1] > fKinkChiRat[
pass] * chifits[chsiz - 2] &&
3674 chifits[chsiz] > fKinkChiRat[
pass] * chifits[chsiz - 1]) {
3676 unsigned int ih0 = fcl2hits.size() - 1;
3677 unsigned int hit0 = fcl2hits[ih0];
3678 unsigned int ih2 = ih0 - 2;
3679 unsigned int hit2 = fcl2hits[ih2];
3680 float dt02 = fHits[hit2].PeakTime() - fHits[hit0].PeakTime();
3681 float dw02 = fHits[hit2].WireID().Wire - fHits[hit0].WireID().Wire;
3682 float th02 = std::atan(fScaleF * dt02 / dw02);
3684 unsigned int ih3 = ih2 - 1;
3685 unsigned int hit3 = fcl2hits[ih3];
3686 unsigned int ih5 = ih3 - 2;
3687 unsigned int hit5 = fcl2hits[ih5];
3688 float dt35 = fHits[hit5].PeakTime() - fHits[hit3].PeakTime();
3689 float dw35 = fHits[hit5].WireID().Wire - fHits[hit3].WireID().Wire;
3690 float th35 = std::atan(fScaleF * dt35 / dw35);
3694 << fKinkAngCut[
pass];
3695 if (dth > fKinkAngCut[
pass]) {
3701 if (kinkOnWire > 0) {
3702 if (kinkOnWire - nextwire < 4) {
3705 <<
"Hit a second kink. kinkOnWire = " << kinkOnWire <<
" Stopping";
3711 kinkOnWire = nextwire;
3717 CheckClusterHitFrac(prt);
3720 if (prt)
mf::LogVerbatim(
"CC") <<
"LACrawlUS done. Nhits = " << fcl2hits.size();
3726 ClusterCrawlerAlg::CrawlUS()
3730 if (fcl2hits.size() < 2)
return;
3732 unsigned int dhit = fcl2hits[0];
3733 int dwir = fHits[dhit].WireID().Wire;
3737 if (fDebugPlane == (
short)plane && dwir == fDebugWire && fDebugHit > 0)
3738 prt =
std::abs(fHits[dhit].PeakTime() - fDebugHit) < 20;
3742 myprt <<
"******************* Start CrawlUS on pass " <<
pass <<
" Hits: ";
3743 for (
unsigned short ii = 0; ii < fcl2hits.size(); ++ii) {
3744 unsigned int iht = fcl2hits[fcl2hits.size() - 1 - ii];
3745 myprt << fHits[iht].WireID().Wire <<
":" << (
int)fHits[iht].PeakTime() <<
" ";
3756 short nHitAfterSkip = 0;
3757 bool DidaSkip =
false;
3758 bool PostSkip =
false;
3759 unsigned int it = fcl2hits.size() - 1;
3760 unsigned int lasthit = fcl2hits[it];
3761 if (lasthit > fHits.size() - 1) {
3762 mf::LogError(
"CC") <<
"CrawlUS bad lasthit " << lasthit;
3765 unsigned int lastwire = fHits[lasthit].WireID().Wire;
3766 if (prt)
mf::LogVerbatim(
"CC") <<
"CrawlUS: last wire " << lastwire <<
" hit " << lasthit;
3768 unsigned int lastWireWithSignal = lastwire;
3769 unsigned short nDroppedHit = 0;
3771 for (
unsigned int nextwire = lastwire - 1; nextwire > fFirstWire; --nextwire) {
3773 mf::LogVerbatim(
"CC") <<
"CrawlUS: next wire " << nextwire <<
" HitRange " 3774 << WireHitRange[nextwire].first;
3776 if (CrawlVtxChk(nextwire)) {
3782 if (
std::abs(clpar[1]) > fLAClusSlopeCut) {
3783 if (prt)
mf::LogVerbatim(
"CC") <<
">>>>> CrawlUS: Switching to LACrawlUS";
3788 AddHit(nextwire, HitOK, SigOK);
3790 mf::LogVerbatim(
"CC") <<
"CrawlUS: HitOK " << HitOK <<
" SigOK " << SigOK <<
" nmissed " 3792 if (SigOK) lastWireWithSignal = nextwire;
3799 if (PostSkip && nmissed > fMinWirAfterSkip[
pass]) {
3801 if ((
int)(fcl2hits.size() - nHitAfterSkip) < 4) {
3805 if (prt)
mf::LogVerbatim(
"CC") <<
" PostSkip && nmissed = " << nmissed;
3807 FclTrimUS(nHitAfterSkip);
3809 if (clChisq > 90.) {
3824 lasthit = fcl2hits[fcl2hits.size() - 1];
3825 if ((lastWireWithSignal - nextwire) > fAllowNoHitWire) {
3828 <<
"No hit or signal on wire " << nextwire <<
" last wire with signal " 3829 << lastWireWithSignal <<
" exceeding fAllowNoHitWire " << fAllowNoHitWire
3837 mf::LogVerbatim(
"CC") <<
" CrawlUS check clChisq " << clChisq <<
" cut " << fChiCut[
pass];
3838 if (clChisq > fChiCut[
pass]) {
3839 if (fcl2hits.size() < 3) {
3844 if (prt)
mf::LogVerbatim(
"CC") <<
"ADD- Bad clChisq " << clChisq <<
" dropping hit";
3848 if (nDroppedHit > 4) {
3851 <<
" Too many dropped hits: " << nDroppedHit <<
" Stop crawling";
3854 if (clChisq > fChiCut[pass]) {
3857 <<
" Bad clChisq " << clChisq <<
" after dropping hit. Stop crawling";
3865 if (chifits.size() > 5 && fKinkChiRat[
pass] > 0) {
3866 if (chifits.size() != fcl2hits.size()) {
3867 mf::LogError(
"CC") <<
"CrawlUS: chifits size error " << chifits.size() <<
" " 3871 unsigned short chsiz = chifits.size() - 1;
3873 mf::LogVerbatim(
"CC") <<
"Kink chk " << chifits[chsiz] <<
" " << chifits[chsiz - 1]
3874 <<
" " << chifits[chsiz - 2] <<
" " << chifits[chsiz - 3];
3875 if (chifits[chsiz - 1] > fKinkChiRat[pass] * chifits[chsiz - 2] &&
3876 chifits[chsiz] > fKinkChiRat[pass] * chifits[chsiz - 1]) {
3877 if (fcl2hits.size() != chifits.size()) {
3878 mf::LogError(
"CC") <<
"bad kink check size " << chifits.size() <<
" " 3879 << fcl2hits.size() <<
" plane " << plane <<
" cluster " << dwir
3883 if (EndKinkAngle() > fKinkAngCut[pass]) {
3886 <<
"******************* Stopped tracking - kink angle " << EndKinkAngle() <<
" > " 3887 << fKinkAngCut[
pass] <<
" Removing 3 hits";
3897 if (fcl2hits.size() == fMaxHitsFit[
pass] || fcl2hits.size() == fMinHits[
pass]) {
3898 clBeginSlp = clpar[1];
3899 clBeginSlpErr = clparerr[1];
3902 if (clBeginChg <= 0 && fAveChg > 0) {
3903 clBeginChg = fAveChg;
3919 if (nHitAfterSkip == fMinWirAfterSkip[pass]) PostSkip =
false;
3922 if (clChisq > fChiCut[pass]) {
3926 unsigned short lopped = 0;
3927 for (
unsigned short nlop = 0; nlop < 4; ++nlop) {
3928 unsigned short cfsize = chifits.size() - 1;
3929 chirat = chifits[cfsize] / chifits[cfsize - 1];
3932 <<
"chirat " << chirat <<
" last hit " << fcl2hits[fcl2hits.size() - 1];
3933 if (chirat < 1.2)
break;
3934 if (prt)
mf::LogVerbatim(
"CC") <<
"<<ADD- Bad chisq. Bad chirat " << chirat;
3937 if (fcl2hits.size() < 6)
break;
3938 if (chifits.size() < 6)
break;
3940 if (fcl2hits.size() < 6) {
3942 if (prt)
mf::LogVerbatim(
"CC") <<
"Bad fit chisq - short cluster. Break";
3945 if (lopped == 0 && fcl2hits.size() > 5) {
3953 mf::LogVerbatim(
"CC") <<
"Bad fit chisq - removed " << lopped <<
" hits. Continue";
3958 mf::LogVerbatim(
"CC") <<
"******************* CrawlUS normal stop. size " << fcl2hits.size();
3962 if (fcl2hits.size() > 5) {
3965 mf::LogVerbatim(
"CC") <<
"EndKinkAngle check " << EndKinkAngle() <<
" cut " 3966 << fKinkAngCut[
pass];
3967 if (EndKinkAngle() > fKinkAngCut[
pass]) {
3976 if ((
unsigned short)fcl2hits.size() > fMinWirAfterSkip[
pass] + 3) {
3977 unsigned int ih0 = fcl2hits.size() - 1;
3978 unsigned int hit0 = fcl2hits[ih0];
3979 unsigned int uswir = fHits[hit0].WireID().Wire;
3980 unsigned int nxtwir;
3981 unsigned short nAdjHit = 0;
3982 for (
unsigned short ii = ih0 - 1; ii > 0; --ii) {
3983 nxtwir = fHits[fcl2hits[ii]].WireID().Wire;
3985 if (nxtwir != uswir + 1)
break;
3987 if (nAdjHit == fMinWirAfterSkip[
pass])
break;
3991 if (nAdjHit < fMinWirAfterSkip[
pass]) {
3992 if (prt)
mf::LogVerbatim(
"CC") <<
"fMinWirAfterSkip removes " << nAdjHit <<
" hits ";
3999 if (!reFit && fcl2hits.size() > 3) {
4000 float chirat = chifits[chifits.size() - 1] / chifits[chifits.size() - 2];
4004 mf::LogVerbatim(
"CC") <<
"Check " << clChisq <<
" " << chifits[chifits.size() - 1] <<
" " 4005 << chifits[chifits.size() - 2];
4006 if (chirat > fKinkChiRat[
pass]) {
4017 CheckClusterHitFrac(prt);
4019 mf::LogVerbatim(
"CC") <<
"******************* CrawlUS done. Size " << fcl2hits.size()
4020 <<
" min length for this pass " << fMinHits[
pass];
4027 ClusterCrawlerAlg::EndKinkAngle()
4031 unsigned int ih0 = fcl2hits.size() - 1;
4032 unsigned int hit0 = fcl2hits[ih0];
4033 unsigned int ih2 = ih0 - 2;
4034 unsigned int hit2 = fcl2hits[ih2];
4035 float dt02 = fHits[hit2].PeakTime() - fHits[hit0].PeakTime();
4036 float dw02 = fHits[hit2].WireID().Wire - fHits[hit0].WireID().Wire;
4037 float th02 = std::atan(fScaleF * dt02 / dw02);
4039 unsigned int ih3 = ih2 - 1;
4040 unsigned int hit3 = fcl2hits[ih3];
4041 unsigned int ih5 = ih3 - 2;
4042 unsigned int hit5 = fcl2hits[ih5];
4043 float dt35 = fHits[hit5].PeakTime() - fHits[hit3].PeakTime();
4044 float dw35 = fHits[hit5].WireID().Wire - fHits[hit3].WireID().Wire;
4045 float th35 = std::atan(fScaleF * dt35 / dw35);
4051 ClusterCrawlerAlg::ChkMergedClusterHitFrac(
unsigned short it1,
unsigned short it2)
4055 if (it1 >
tcl.size() - 1)
return false;
4056 if (it2 >
tcl.size() - 1)
return false;
4057 unsigned int eWire = 99999;
4058 unsigned int bWire = 0, wire;
4059 if (
tcl[it1].BeginWir > bWire) bWire =
tcl[it1].BeginWir;
4060 if (
tcl[it2].BeginWir > bWire) bWire =
tcl[it2].BeginWir;
4061 if (
tcl[it1].EndWir < eWire) eWire =
tcl[it1].EndWir;
4062 if (
tcl[it2].EndWir < eWire) eWire =
tcl[it2].EndWir;
4063 unsigned int mergedClusterLength = bWire - eWire + 1;
4065 std::vector<bool> cHits(mergedClusterLength,
false);
4067 unsigned int ii, iht, indx;
4068 for (ii = 0; ii <
tcl[it1].tclhits.size(); ++ii) {
4069 iht =
tcl[it1].tclhits[ii];
4070 if (iht > fHits.size() - 1) {
4071 mf::LogError(
"CC") <<
"ChkMergedClusterHitFrac bad iht ";
4074 indx = fHits[iht].WireID().Wire - eWire;
4077 for (ii = 0; ii <
tcl[it2].tclhits.size(); ++ii) {
4078 iht =
tcl[it2].tclhits[ii];
4079 if (iht > fHits.size() - 1) {
4080 mf::LogError(
"CC") <<
"ChkMergedClusterHitFrac bad iht ";
4083 indx = fHits[iht].WireID().Wire - eWire;
4087 for (ii = 0; ii < cHits.size(); ++ii) {
4089 if (WireHitRange[wire].first == -1) cHits[ii] =
true;
4092 float nhits =
std::count(cHits.begin(), cHits.end(),
true);
4093 float hitFrac = nhits / (
float)cHits.size();
4094 return (hitFrac > fMinHitFrac);
4099 ClusterCrawlerAlg::CheckClusterHitFrac(
bool prt)
4104 unsigned int iht = fcl2hits[fcl2hits.size() - 1];
4105 clEndWir = fHits[iht].WireID().Wire;
4106 clBeginWir = fHits[fcl2hits[0]].WireID().Wire;
4107 float hitFrac = (
float)(fcl2hits.size() +
DeadWireCount()) / (
float)(clBeginWir - clEndWir + 1);
4109 if (hitFrac < fMinHitFrac) {
4111 mf::LogVerbatim(
"CC") <<
"CheckClusterHitFrac: Poor hit fraction " << hitFrac
4112 <<
" clBeginWir " << clBeginWir <<
" clEndWir " << clEndWir
4113 <<
" size " << fcl2hits.size() <<
" DeadWireCount " 4126 if (fcl2hits.size() < 5) {
4127 unsigned short nsing = 0;
4128 for (
unsigned short iht = 0; iht < fcl2hits.size(); ++iht)
4129 if (fHits[fcl2hits[iht]].Multiplicity() == 1) ++nsing;
4130 hitFrac = (
float)nsing / (
float)fcl2hits.size();
4131 if (hitFrac < fMinHitFrac) {
4134 mf::LogVerbatim(
"CC") <<
"CheckClusterHitFrac: Poor short track hit fraction " << hitFrac;
4141 if (clBeginChg <= 0) {
4142 unsigned int iht, nht = 0;
4143 for (
unsigned short ii = 0; ii < fcl2hits.size(); ++ii) {
4145 clBeginChg += fHits[iht].Integral();
4147 if (nht == 8)
break;
4149 clBeginChg /= (
float)nht;
4152 unsigned short cnt = chgNear.size() / 2;
4154 if (chgNear.size() > 60) cnt = 30;
4157 for (
unsigned short ids = 0; ids < cnt; ++ids) {
4158 clBeginChgNear += chgNear[ids];
4159 clEndChgNear += chgNear[chgNear.size() - 1 - ids];
4161 clBeginChgNear /= (
float)cnt;
4162 clEndChgNear /= (
float)cnt;
4168 ClusterCrawlerAlg::FitClusterMid(
unsigned short it1,
unsigned int ihtin,
short nhit)
4170 FitClusterMid(
tcl[it1].tclhits, ihtin, nhit);
4175 ClusterCrawlerAlg::FitClusterMid(std::vector<unsigned int>& hitVec,
4188 if (hitVec.size() < 3)
return;
4190 std::vector<float> xwir;
4191 std::vector<float> ytim;
4192 std::vector<float> ytimerr2;
4194 unsigned short ii, hitcnt = 0, nht = 0, usnhit;
4204 for (ii = 0; ii < hitVec.size(); ++ii) {
4206 if (iht > fHits.size() - 1) {
4213 wire0 = fHits[iht].WireID().Wire;
4217 xwir.push_back((
float)fHits[iht].
WireID().
Wire - wire0);
4218 ytim.push_back(fHits[iht].PeakTime());
4220 float terr = fHitErrFac * fHits[iht].RMS();
4221 ytimerr2.push_back(terr * terr);
4222 fAveChg += fHits[iht].Integral();
4224 if (hitcnt == usnhit)
break;
4232 for (
auto ii = hitVec.crbegin(); ii != hitVec.crend(); ++ii) {
4234 if (iht > fHits.size() - 1) {
4241 wire0 = fHits[iht].WireID().Wire;
4245 xwir.push_back((
float)fHits[iht].
WireID().
Wire - wire0);
4246 ytim.push_back(fHits[iht].PeakTime());
4247 float terr = fHitErrFac * fHits[iht].RMS();
4248 ytimerr2.push_back(terr * terr);
4249 fAveChg += fHits[iht].Integral();
4251 if (hitcnt == usnhit)
break;
4257 if (nht < 2)
return;
4258 fAveChg = fAveChg / (
float)nht;
4263 float intcpterr = 0.;
4264 float slopeerr = 0.;
4266 fLinFitAlg.LinFit(xwir, ytim, ytimerr2, intcpt, slope, intcpterr, slopeerr, chidof);
4268 if (clChisq > fChiCut[0])
return;
4272 clparerr[0] = intcpterr;
4273 clparerr[1] = slopeerr;
4278 ClusterCrawlerAlg::FitCluster()
4287 if (
pass > fNumPass - 1) {
4292 unsigned short ii, nht = 0;
4294 nht = fcl2hits.size();
4297 if (nht > fLAClusMaxHitsFit) nht = fLAClusMaxHitsFit;
4300 if (nht > fMaxHitsFit[
pass]) nht = fMaxHitsFit[
pass];
4302 if (nht < 2)
return;
4304 std::vector<float> xwir;
4305 std::vector<float> ytim;
4306 std::vector<float> ytimerr2;
4308 float angfactor = AngleFactor(clpar[1]);
4311 unsigned int wire0 = fHits[fcl2hits[fcl2hits.size() - 1]].WireID().Wire;
4313 float terr, qave = 0, qwt;
4314 for (ii = 0; ii < nht; ++ii) {
4315 ihit = fcl2hits[fcl2hits.size() - 1 - ii];
4316 qave += fHits[ihit].Integral();
4319 for (ii = 0; ii < nht; ++ii) {
4320 ihit = fcl2hits[fcl2hits.size() - 1 - ii];
4321 wire = fHits[ihit].WireID().Wire;
4322 xwir.push_back(wire - wire0);
4323 ytim.push_back(fHits[ihit].PeakTime());
4326 terr = fHitErrFac * fHits[ihit].RMS() * fHits[ihit].Multiplicity();
4329 qwt = (fHits[ihit].Integral() / qave) - 1;
4330 if (qwt < 1) qwt = 1;
4333 if (terr < 0.01) terr = 0.01;
4334 ytimerr2.push_back(angfactor * terr * terr);
4336 CalculateAveHitWidth();
4339 myprt <<
"FitCluster W:T ";
4340 unsigned short cnt = 0;
4341 for (std::vector<unsigned int>::reverse_iterator it = fcl2hits.rbegin();
4342 it != fcl2hits.rend();
4344 unsigned int ihit = *it;
4345 unsigned short wire = fHits[ihit].WireID().Wire;
4346 myprt << wire <<
":" << (short)fHits[ihit].PeakTime() <<
" ";
4355 if (xwir.size() < 2)
return;
4359 float intcpterr = 0.;
4360 float slopeerr = 0.;
4362 fLinFitAlg.LinFit(xwir, ytim, ytimerr2, intcpt, slope, intcpterr, slopeerr, chidof);
4364 if (chidof > fChiCut[0])
return;
4368 clparerr[0] = intcpterr;
4369 clparerr[1] = slopeerr;
4373 << (
int)intcpterr <<
" " << clpar[1] <<
"+/-" << slopeerr <<
" clChisq " 4378 ClusterCrawlerAlg::AngleFactor(
float slope)
4384 if (slp > 15) slp = 15;
4386 float angfac = 1 + 0.03 * slp * slp;
4392 ClusterCrawlerAlg::CalculateAveHitWidth()
4395 for (
unsigned short ii = 0; ii < fcl2hits.size(); ++ii)
4396 fAveHitWidth += fHits[fcl2hits[ii]].EndTick() - fHits[fcl2hits[ii]].StartTick();
4397 fAveHitWidth /= (
float)fcl2hits.size();
4402 ClusterCrawlerAlg::FitClusterChg()
4407 if (fcl2hits.size() == 0)
return;
4408 unsigned int ih0 = fcl2hits.size() - 1;
4410 if (
pass >= fNumPass) {
4419 unsigned short nhave = fLAClusMaxHitsFit;
4420 if (nhave > fcl2hits.size()) nhave = fcl2hits.size();
4425 for (
unsigned short ii = 0; ii < nhave; ++ii) {
4426 iht = fcl2hits[fcl2hits.size() - 1 - ii];
4427 fAveChg += fHits[iht].Integral();
4428 fAveHitWidth += (fHits[iht].EndTick() - fHits[iht].StartTick());
4430 fAveChg /= (
float)fcl2hits.size();
4431 fAveHitWidth /= (
float)fcl2hits.size();
4436 unsigned short fitLen = fNHitsAve[
pass];
4440 fcl2hits.size() > 5 &&
4441 fcl2hits.size() < fitLen)
4445 if (fNHitsAve[
pass] < 1)
return;
4447 if (fNHitsAve[
pass] == 1) {
4449 fAveChg = fHits[fcl2hits[ih0]].Integral();
4452 else if (fNHitsAve[
pass] == 2) {
4454 fAveChg = (fHits[fcl2hits[ih0]].Integral() + fHits[fcl2hits[ih0 - 1]].Integral()) / 2.;
4457 else if ((
unsigned short)fcl2hits.size() > fitLen) {
4459 std::vector<float> xwir;
4460 std::vector<float> ychg;
4461 std::vector<float> ychgerr2;
4463 unsigned int wire0 = fHits[fcl2hits[fcl2hits.size() - 1]].WireID().Wire;
4465 unsigned short npt = 0;
4466 unsigned short imlast = 0;
4470 for (
unsigned int ii = fcl2hits.size() - 1; ii > 0; --ii) {
4472 float chg = fHits[fcl2hits[ii]].Integral();
4475 if (npt == fitLen) {
4482 rms = std::sqrt((rms - fnpt * ave * ave) / (fnpt - 1));
4483 float chgcut = ave +
rms;
4486 for (
unsigned short ii = fcl2hits.size() - 1; ii > imlast; --ii) {
4487 wire = fHits[fcl2hits[ii]].WireID().Wire;
4488 chg = fHits[fcl2hits[ii]].Integral();
4489 if (chg > chgcut)
continue;
4490 xwir.push_back((
float)(wire - wire0));
4491 ychg.push_back(chg);
4492 ychgerr2.push_back(chg);
4494 if (ychg.size() < 3)
return;
4500 fLinFitAlg.LinFit(xwir, ychg, ychgerr2, intcpt, slope, intcpterr, slopeerr, chidof);
4503 <<
" npt " << xwir.size() <<
" charge = " << (
int)intcpt
4504 <<
" slope = " << (
int)slope <<
" first ave " << (
int)ave <<
" rms " 4506 if (chidof > 100.)
return;
4509 if (intcpt > ave)
return;
4512 ave = intcpt / fAveChg;
4513 if (ave > 1.3)
return;
4514 if (ave < 0.77)
return;
4523 ClusterCrawlerAlg::AddLAHit(
unsigned int kwire,
bool& ChkCharge,
bool& HitOK,
bool& SigOK)
4531 if (kwire < fFirstWire || kwire > fLastWire)
return;
4533 if (fcl2hits.size() == 0)
return;
4536 if (WireHitRange[kwire].first == -1) {
4541 if (WireHitRange[kwire].first == -2)
return;
4543 unsigned int firsthit = WireHitRange[kwire].first;
4544 unsigned int lasthit = WireHitRange[kwire].second;
4547 float timeDiff = 40 * AngleFactor(clpar[1]);
4551 unsigned int lastClHit = UINT_MAX;
4552 if (fcl2hits.size() > 0) {
4553 lastClHit = fcl2hits[fcl2hits.size() - 1];
4554 if (lastClHit == 0) {
4555 fAveChg = fHits[lastClHit].Integral();
4556 fAveHitWidth = fHits[lastClHit].EndTick() - fHits[lastClHit].StartTick();
4561 float prtime = clpar[0] + ((
float)kwire - clpar[2]) * clpar[1];
4562 float chgWinLo = prtime - fChgNearWindow;
4563 float chgWinHi = prtime + fChgNearWindow;
4564 float chgrat, hitWidth;
4565 float hitWidthCut = 0.5 * fAveHitWidth;
4569 mf::LogVerbatim(
"CC") <<
"AddLAHit: wire " << kwire <<
" prtime " << prtime
4570 <<
" max timeDiff " << timeDiff <<
" fAveChg " << fAveChg;
4571 unsigned int imbest = 0;
4573 for (khit = firsthit; khit < lasthit; ++khit) {
4575 if (inClus[khit] < 0)
continue;
4576 dtime =
std::abs(fHits[khit].PeakTime() - prtime);
4577 hitWidth = fHits[khit].EndTick() - fHits[khit].StartTick();
4579 if (ChkCharge && fAveChg > 0) { chgrat = fHits[khit].Integral() / fAveChg; }
4581 mf::LogVerbatim(
"CC") <<
" Chk W:T " << kwire <<
":" << (short)fHits[khit].PeakTime()
4583 << inClus[khit] <<
" mult " << fHits[khit].Multiplicity() <<
" width " 4584 << (
int)hitWidth <<
" MergeAvail " << mergeAvailable[khit] <<
" Chi2 " 4586 <<
" Charge " << (
int)fHits[khit].Integral() <<
" chgrat " 4589 if (fHits[khit].PeakTime() > chgWinLo && fHits[khit].PeakTime() < chgWinHi)
4590 cnear += fHits[khit].Integral();
4592 if (prtime < fHits[khit].StartTick() - timeDiff)
continue;
4593 if (prtime > fHits[khit].EndTick() + timeDiff)
continue;
4596 if (inClus[khit] > 0)
continue;
4598 if (hitWidth < hitWidthCut)
continue;
4600 if (chgrat < 0.1)
continue;
4601 if (dtime < timeDiff) {
4613 mf::LogVerbatim(
"CC") <<
" Pick hit time " << (
int)fHits[imbest].PeakTime() <<
" hit index " 4618 if (lastClHit != UINT_MAX && fHits[imbest].Multiplicity() > 1) {
4619 bool doMerge =
true;
4622 for (
unsigned short ivx = 0; ivx < vtx.size(); ++ivx) {
4623 if (vtx[ivx].CTP != clCTP)
continue;
4625 mf::LogVerbatim(
"CC") <<
" close vtx chk W:T " << vtx[ivx].Wire <<
":" 4626 << (
int)vtx[ivx].Time;
4628 std::abs(
int(fHits[imbest].PeakTime() - vtx[ivx].Time)) < 20) {
4629 if (prt)
mf::LogVerbatim(
"CC") <<
" Close to a vertex. Don't merge hits";
4636 unsigned short nused = 0;
4638 float multipletChg = 0.;
4639 float chicut = AngleFactor(clpar[1]) * fHitMergeChiCut * fHits[lastClHit].RMS();
4641 std::pair<size_t, size_t> MultipletRange = FindHitMultiplet(imbest);
4642 for (
size_t jht = MultipletRange.first; jht < MultipletRange.second; ++jht) {
4643 if (inClus[jht] < 0)
continue;
4644 if (inClus[jht] == 0)
4645 multipletChg += fHits[jht].Integral();
4649 if (jht > MultipletRange.first) {
4651 float hitRMS = fHits[jht].RMS();
4652 if (fHits[jht - 1].RMS() > hitRMS) hitRMS = fHits[jht - 1].RMS();
4654 std::abs(fHits[jht].PeakTime() - fHits[jht - 1].PeakTime()) / hitRMS;
4655 if (prt)
mf::LogVerbatim(
"CC") <<
" Hit RMS chisq " << tdiff <<
" chicut " << chicut;
4656 if (tdiff > chicut) doMerge =
false;
4660 if (!doMerge)
mf::LogVerbatim(
"CC") <<
" Hits are well separated. Don't merge them ";
4662 if (doMerge && nused == 0) {
4667 float chgrat = multipletChg / fHits[lastClHit].Integral();
4670 <<
" Previous hit charge " << (
int)fHits[lastClHit].Integral();
4671 if (chgrat > 2) doMerge =
false;
4679 MergeHits(imbest, didMerge);
4684 fcl2hits.push_back(imbest);
4687 chifits.push_back(clChisq);
4688 hitNear.push_back(hnear);
4690 cnear -= fHits[imbest].Integral();
4691 if (cnear < 0) cnear = 0;
4693 cnear /= fHits[imbest].Integral();
4694 chgNear.push_back(cnear);
4696 hitWidth = fHits[imbest].EndTick() - fHits[imbest].StartTick();
4698 << timeDiff <<
" clChisq " << clChisq <<
" Chg " 4699 << (
int)fHits[imbest].Integral() <<
" AveChg " << (
int)fAveChg
4700 <<
" width " << (
int)hitWidth <<
" AveWidth " << (
int)fAveHitWidth
4701 <<
" fcl2hits size " << fcl2hits.size();
4704 if (clChisq > fChiCut[
pass]) {
4709 if (prt)
mf::LogVerbatim(
"CC") <<
" LADD- Removed bad hit. Stopped tracking";
4715 ClusterCrawlerAlg::ClusterHitsOK(
short nHitChk)
4728 if (fcl2hits.size() == 0)
return true;
4730 unsigned short nHitToChk = fcl2hits.size();
4731 if (nHitChk > 0) nHitToChk = nHitChk + 1;
4732 unsigned short ii, indx;
4738 if (plane < geom->Cryostat(cstat).
TPC(tpc).Nplanes() - 1) tol = 40;
4741 (fHits[fcl2hits[0]].PeakTime() > fHits[fcl2hits[fcl2hits.size() - 1]].PeakTime());
4744 for (ii = 0; ii < nHitToChk; ++ii) {
4745 indx = fcl2hits.size() - 1 - ii;
4746 mf::LogVerbatim(
"CC") <<
"ClusterHitsOK chk " << fHits[fcl2hits[indx]].WireID().Wire
4747 <<
" start " << fHits[fcl2hits[indx]].StartTick() <<
" peak " 4748 << fHits[fcl2hits[indx]].PeakTime() <<
" end " 4749 << fHits[fcl2hits[indx]].EndTick() <<
" posSlope " << posSlope;
4754 for (ii = 0; ii < nHitToChk - 1; ++ii) {
4755 indx = fcl2hits.size() - 1 - ii;
4758 fHits[fcl2hits[indx - 1]].
WireID().
Wire) > 1)
4761 std::max(fHits[fcl2hits[indx]].StartTick(), fHits[fcl2hits[indx - 1]].StartTick());
4762 loEndTick =
std::min(fHits[fcl2hits[indx]].EndTick(), fHits[fcl2hits[indx - 1]].EndTick());
4764 if (loEndTick + tol < hiStartTick) {
return false; }
4767 if (loEndTick + tol < hiStartTick) {
return false; }
4775 ClusterCrawlerAlg::AddHit(
unsigned int kwire,
bool& HitOK,
bool& SigOK)
4786 if (kwire < fFirstWire || kwire > fLastWire)
return;
4788 unsigned int lastClHit = UINT_MAX;
4789 if (fcl2hits.size() > 0) lastClHit = fcl2hits[fcl2hits.size() - 1];
4792 unsigned int wire0 = clpar[2];
4795 if (fAllowNoHitWire == 0) {
4796 if (WireHitRange[kwire].first == -2)
return;
4800 if (WireHitRange[kwire].first == -2 && (wire0 - kwire) > fAllowNoHitWire) {
4806 if (WireHitRange[kwire].first == -1) {
4811 unsigned int firsthit = WireHitRange[kwire].first;
4812 unsigned int lasthit = WireHitRange[kwire].second;
4815 float dw = (
float)kwire - (
float)wire0;
4816 float prtime = clpar[0] + dw * clpar[1];
4817 if (prtime < 0 || (
unsigned int)prtime > fMaxTime)
return;
4820 float prtimerr2 =
std::abs(dw) * clparerr[1] * clparerr[1];
4824 if (lastClHit != UINT_MAX) hiterr = 3 * fHitErrFac * fHits[lastClHit].RMS();
4825 float err = std::sqrt(prtimerr2 + hiterr * hiterr);
4827 float hitWin = fClProjErrFac *
err;
4829 float prtimeLo = prtime - hitWin;
4830 float prtimeHi = prtime + hitWin;
4831 float chgWinLo = prtime - fChgNearWindow;
4832 float chgWinHi = prtime + fChgNearWindow;
4835 <<
" prtime " << (
int)prtime <<
" Hi " << (
int)prtimeHi <<
" prtimerr " 4836 << sqrt(prtimerr2) <<
" hiterr " << hiterr <<
" fAveChg " 4841 unsigned int imbest = INT_MAX;
4842 float best = 9999., dtime;
4844 float hitTime, hitChg, hitStartTick, hitEndTick;
4845 for (
unsigned int khit = firsthit; khit < lasthit; ++khit) {
4847 if (inClus[khit] < 0)
continue;
4848 hitTime = fHits[khit].PeakTime();
4849 dtime =
std::abs(hitTime - prtime);
4850 if (dtime > 1000)
continue;
4851 hitStartTick = fHits[khit].StartTick();
4852 hitEndTick = fHits[khit].EndTick();
4854 if (fAveChg > 0) dtime *=
std::abs(fHits[khit].Integral() - fAveChg) / fAveChg;
4855 if (prt &&
std::abs(dtime) < 100) {
4858 << inClus[khit] <<
" mult " << fHits[khit].Multiplicity() <<
" RMS " 4861 <<
" Charge " << (
int)fHits[khit].Integral() <<
" Peak " << std::fixed
4863 << (
int)hitStartTick <<
" HiT " << (
int)hitEndTick <<
" index " 4867 if (fHits[khit].StartTick() > chgWinLo && fHits[khit].EndTick() < chgWinHi)
4868 cnear += fHits[khit].Integral();
4870 if (prtimeHi < hitStartTick)
continue;
4871 if (prtimeLo > hitEndTick)
continue;
4874 if (hitTime < prtimeLo)
continue;
4875 if (hitTime > prtimeHi)
continue;
4877 if (inClus[khit] > 0)
continue;
4885 if (fAllowNoHitWire == 0)
return;
4887 mf::LogVerbatim(
"CC") <<
" wire0 " << wire0 <<
" kwire " << kwire <<
" max " 4888 << fAllowNoHitWire <<
" imbest " << imbest;
4889 if ((wire0 - kwire) > fAllowNoHitWire)
return;
4893 if (imbest == INT_MAX)
return;
4902 bool didMerge =
false;
4903 if (lastClHit != UINT_MAX && fAveHitWidth > 0 && fHitMergeChiCut > 0 &&
4905 bool doMerge =
true;
4906 for (
unsigned short ivx = 0; ivx < vtx.size(); ++ivx) {
4914 if (hit.
LocalIndex() != 0 && imbest == 0) doMerge =
false;
4918 if (hit.
LocalIndex() == 0) { oht = imbest + 1; }
4925 hitSep /= hit.
RMS();
4927 float totChg = hitChg + other_hit.
Integral();
4928 float lastHitChg = fAveChg;
4929 if (lastHitChg < 0) lastHitChg = fHits[lastClHit].Integral();
4932 mf::LogVerbatim(
"CC") <<
" Chk hit merge hitsep " << hitSep <<
" dChg " 4933 <<
std::abs(totChg - lastHitChg) <<
" Cut " 4935 if (inClus[oht] == 0 && hitSep < fHitMergeChiCut) {
4937 MergeHits(imbest, didMerge);
4947 float chgrat = (hitChg - fAveChg) / fAveChg;
4951 if (chgrat > 3 * fChgCut[
pass]) {
4961 float bigchgcut = 1.5 * fChgCut[
pass];
4962 bool lasthitbig =
false;
4963 bool lasthitlow =
false;
4964 if (lastClHit != UINT_MAX &&
util::absDiff(wire0, kwire) == 1) {
4965 float lastchgrat = (fHits[lastClHit].Integral() - fAveChg) / fAveChg;
4966 lasthitbig = (lastchgrat > bigchgcut);
4967 lasthitlow = (lastchgrat < -fChgCut[
pass]);
4971 if (lasthitlow && chgrat < -fChgCut[pass]) {
4972 if (prt)
mf::LogVerbatim(
"CC") <<
" fails low charge cut. Stop crawling.";
4978 if (lasthitbig && chgrat > fChgCut[pass]) {
4980 mf::LogVerbatim(
"CC") <<
" fails 2nd hit high charge cut. Last hit was high also. ";
4985 if (chgrat > fChgCut[pass]) {
4986 if (best > 2 * err) {
4987 if (prt)
mf::LogVerbatim(
"CC") <<
" high charge && bad dT= " << best <<
" err= " <<
err;
4993 fitChg = (chgrat <
std::abs(fChgCut[pass]));
4997 fcl2hits.push_back(imbest);
4999 if (fcl2hits.size() == 3) std::sort(fcl2hits.begin(), fcl2hits.end(),
SortByLowHit);
5001 chifits.push_back(clChisq);
5002 hitNear.push_back(hnear);
5004 cnear -= fHits[imbest].Integral();
5005 if (cnear < 0) cnear = 0;
5007 cnear /= fHits[imbest].Integral();
5008 chgNear.push_back(cnear);
5013 if (chgNear.size() != fcl2hits.size()) {
5020 <<
" clChisq " << clChisq <<
" Chg " << (
int)fHits[imbest].Integral()
5021 <<
" AveChg " << (
int)fAveChg <<
" fcl2hits size " << fcl2hits.size();
5023 if (!fitChg)
return;
5030 ClusterCrawlerAlg::ChkClusterNearbyHits(
bool prt)
5037 if (fHitMergeChiCut <= 0)
return;
5039 if (hitNear.size() != fcl2hits.size()) {
5040 mf::LogWarning(
"CC") <<
"Coding error: hitNear size != fcl2hits";
5045 if (hitNear.size() < 12)
return;
5048 unsigned short ii, indx;
5049 unsigned short merged = 0;
5050 unsigned short notmerged = 0;
5051 for (ii = 0; ii < 6; ++ii) {
5052 indx = hitNear.size() - 1 - ii;
5053 if (hitNear[indx] > 0) ++notmerged;
5054 if (hitNear[indx] < 0) ++merged;
5058 mf::LogVerbatim(
"CC") <<
"ChkClusterNearbyHits: nearby hits merged " << merged
5059 <<
" not merged " << notmerged;
5061 if (notmerged < 2)
return;
5067 for (ii = 0; ii < 6; ++ii) {
5068 indx = fcl2hits.size() - 1 - ii;
5069 const unsigned int iht = fcl2hits[indx];
5073 if (hit.
LocalIndex() != 0 && iht == 0)
continue;
5076 if (hit.
LocalIndex() == 0) { oht = iht + 1; }
5083 hitSep /= hit.
RMS();
5084 if (hitSep < fHitMergeChiCut && inClus[oht] == 0) {
5087 << fHits[iht].WireID().Wire <<
":" << fHits[iht].PeakTime();
5088 MergeHits(iht, didMerge);
5089 if (didMerge) hitNear[indx] = -1;
5098 if (prt)
mf::LogVerbatim(
"CC") <<
"ChkClusterNearbyHits refit cluster. fAveChg= " << fAveChg;
5104 ClusterCrawlerAlg::FitVtx(
unsigned short iv)
5106 std::vector<float>
x;
5107 std::vector<float>
y;
5108 std::vector<float> ey2;
5112 if (vtx[iv].Fixed)
return;
5115 vtx[iv].ChiDOF = 99;
5119 std::vector<unsigned short> vcl;
5120 for (icl = 0; icl <
tcl.size(); ++icl) {
5121 if (
tcl[icl].
ID < 0)
continue;
5122 if (
tcl[icl].CTP != vtx[iv].CTP)
continue;
5123 if (
tcl[icl].EndVtx == iv) vcl.push_back(icl);
5124 if (
tcl[icl].BeginVtx == iv) vcl.push_back(icl);
5127 vtx[iv].NClusters = vcl.size();
5129 if (vcl.size() == 0)
return;
5135 unsigned short indx =
tcl[icl].tclhits.size() - 1;
5136 unsigned int hit =
tcl[icl].tclhits[indx];
5137 float minTimeErr = fHitErrFac * fHits[
hit].RMS() * fHits[
hit].Multiplicity();
5139 if (vcl.size() == 1) {
5142 if (
tcl[icl].EndVtx == iv) {
5143 vtx[iv].Wire =
tcl[icl].EndWir;
5144 vtx[iv].WireErr = 1;
5145 vtx[iv].Time =
tcl[icl].EndTim;
5147 indx =
tcl[icl].tclhits.size() - 1;
5148 hit =
tcl[icl].tclhits[indx];
5149 vtx[iv].TimeErr = fHitErrFac * fHits[
hit].RMS() * fHits[
hit].Multiplicity();
5152 if (
tcl[icl].BeginVtx == iv) {
5153 vtx[iv].Wire =
tcl[icl].BeginWir;
5154 vtx[iv].WireErr = 1;
5155 vtx[iv].Time =
tcl[icl].BeginTim;
5157 hit =
tcl[icl].tclhits[0];
5158 vtx[iv].TimeErr = fHitErrFac * fHits[
hit].RMS() * fHits[
hit].Multiplicity();
5164 std::vector<double> slps;
5165 std::vector<double> slperrs;
5166 for (
unsigned short ii = 0; ii < vcl.size(); ++ii) {
5168 if (
tcl[icl].EndVtx == iv) {
5169 x.push_back(
tcl[icl].EndSlp);
5170 slps.push_back(
tcl[icl].EndSlp);
5171 slperrs.push_back(
tcl[icl].EndSlpErr);
5172 arg =
tcl[icl].EndSlp *
tcl[icl].EndWir -
tcl[icl].EndTim;
5174 if (
tcl[icl].EndSlpErr > 0.) { arg =
tcl[icl].EndSlpErr *
tcl[icl].EndWir; }
5176 arg = .1 *
tcl[icl].EndWir;
5178 ey2.push_back(arg * arg);
5180 else if (
tcl[icl].BeginVtx == iv) {
5181 x.push_back(
tcl[icl].BeginSlp);
5182 slps.push_back(
tcl[icl].BeginSlp);
5183 slperrs.push_back(
tcl[icl].BeginSlpErr);
5184 arg =
tcl[icl].BeginSlp *
tcl[icl].BeginWir -
tcl[icl].BeginTim;
5186 if (
tcl[icl].BeginSlpErr > 0.) { arg =
tcl[icl].BeginSlpErr *
tcl[icl].BeginWir; }
5188 arg = .1 *
tcl[icl].BeginWir;
5190 ey2.push_back(arg * arg);
5193 if (x.size() < 2)
return;
5196 double sumerr = 0, cnt = 0;
5197 for (
unsigned short ii = 0; ii < slps.size() - 1; ++ii) {
5198 for (
unsigned short jj = ii + 1; jj < slps.size(); ++jj) {
5199 arg =
std::min(slperrs[ii], slperrs[jj]);
5200 arg /= (slps[ii] - slps[jj]);
5201 sumerr += arg * arg;
5208 float vTimeErr = 0.;
5210 float vWireErr = 0.;
5212 fLinFitAlg.LinFit(x, y, ey2, vTime, vWire, vTimeErr, vWireErr, chiDOF);
5213 if (chiDOF > 900)
return;
5216 if (vTime < 0 || vTime > fMaxTime)
return;
5219 if (vWire < 0 || vWire > geom->Nwires(iplID.
Plane, iplID.
TPC, iplID.
Cryostat))
return;
5220 vtx[iv].ChiDOF = chiDOF;
5221 vtx[iv].Wire = vWire;
5222 vtx[iv].Time = vTime;
5223 vtx[iv].WireErr = vWire * sqrt(sumerr);
5224 vtx[iv].TimeErr = vTime * fabs(sumerr);
5226 if (vtx[iv].WireErr < 1) vtx[iv].WireErr = 2;
5228 if (vtx[iv].TimeErr < minTimeErr) vtx[iv].TimeErr = minTimeErr;
5240 if (
empty(vtx3))
return;
5242 const unsigned int cstat = tpcid.
Cryostat;
5243 const unsigned int tpc = tpcid.
TPC;
5245 unsigned int thePlane, theWire;
5249 for (
unsigned short ivx = 0; ivx < vtx3.size(); ++ivx) {
5251 if (vtx3[ivx].
Wire < 0)
continue;
5252 if (vtx3[ivx].CStat != cstat || vtx3[ivx].
TPC != tpc)
continue;
5255 theWire = vtx3[ivx].Wire;
5256 for (plane = 0; plane < 3; ++plane) {
5257 if (vtx3[ivx].Ptr2D[plane] >= 0)
continue;
5261 if (thePlane > 2)
continue;
5263 clCTP =
EncodeCTP(cstat, tpc, thePlane);
5266 vnew.
Wire = theWire;
5267 vnew.
Time = theTime;
5271 vtx.push_back(vnew);
5272 unsigned short ivnew = vtx.size() - 1;
5273 std::vector<short> vclIndex;
5274 for (
unsigned short icl = 0; icl <
tcl.size(); ++icl) {
5275 if (
tcl[icl].
ID < 0)
continue;
5276 if (
tcl[icl].CTP != clCTP)
continue;
5280 if (dwb > 10 && dwe > 10)
continue;
5281 if (dwb < dwe && dwb < 10 &&
tcl[icl].BeginVtx < 0) {
5283 if (theWire <
tcl[icl].BeginWir + 5)
continue;
5284 if (ClusterVertexChi(icl, 0, ivnew) > fVertex3DCut)
continue;
5285 tcl[icl].BeginVtx = ivnew;
5286 vclIndex.push_back(icl);
5288 else if (dwe < 10 &&
tcl[icl].EndVtx < 0) {
5290 if (theWire >
tcl[icl].EndWir - 5)
continue;
5291 if (ClusterVertexChi(icl, 1, ivnew) > fVertex3DCut)
continue;
5292 tcl[icl].EndVtx = ivnew;
5293 vclIndex.push_back(icl);
5296 bool goodVtx =
false;
5297 if (vclIndex.size() > 0) {
5299 goodVtx = (vtx[ivnew].ChiDOF < fVertex3DCut);
5300 vtx3[ivx].Ptr2D[thePlane] = ivnew;
5303 vtx3[ivx].Ptr2D[thePlane] = ivnew;
5304 vtx3[ivx].Wire = -1;
5309 for (
unsigned short ii = 0; ii < vclIndex.size(); ++ii) {
5310 unsigned short icl = vclIndex[ii];
5311 if (
tcl[icl].BeginVtx == ivnew)
tcl[icl].BeginVtx = -99;
5312 if (
tcl[icl].EndVtx == ivnew)
tcl[icl].EndVtx = -99;
5326 if (
empty(vtx3))
return;
5328 const unsigned int cstat = tpcid.
Cryostat;
5329 const unsigned int tpc = tpcid.
TPC;
5331 vtxprt = (fDebugPlane >= 0) && (fDebugHit == 6666);
5333 unsigned int lastplane = 5, kcl, kclID;
5335 unsigned int thePlane, theWire, plane;
5336 unsigned int loWire, hiWire;
5338 for (
unsigned short ivx = 0; ivx < vtx3.size(); ++ivx) {
5339 if (vtx3[ivx].CStat != cstat || vtx3[ivx].
TPC != tpc)
continue;
5342 mf::LogVerbatim(
"CC") <<
"Vtx3ClusterSplit ivx " << ivx <<
" Ptr2D " << vtx3[ivx].Ptr2D[0]
5343 <<
" " << vtx3[ivx].Ptr2D[1] <<
" " << vtx3[ivx].Ptr2D[2] <<
" wire " 5345 if (vtx3[ivx].
Wire < 0)
continue;
5348 theWire = vtx3[ivx].Wire;
5349 for (plane = 0; plane < 3; ++plane) {
5350 if (vtx3[ivx].Ptr2D[plane] >= 0)
continue;
5354 if (thePlane > 2)
continue;
5356 (
double)vtx3[ivx].
X, (
int)thePlane, (
int)tpcid.
TPC, (
int)tpcid.
Cryostat);
5358 if (thePlane != lastplane) {
5361 lastplane = thePlane;
5364 std::vector<short> clIDs;
5365 if (theWire > fFirstWire + 5) { loWire = theWire - 5; }
5367 loWire = fFirstWire;
5369 if (theWire < fLastWire - 5) { hiWire = theWire + 5; }
5374 mf::LogVerbatim(
"CC") <<
"3DVtx " << ivx <<
" look for cluster hits near P:W:T " << thePlane
5375 <<
":" << theWire <<
":" << (
int)theTime <<
" Wire range " << loWire
5376 <<
" to " << hiWire;
5377 for (
unsigned int wire = loWire; wire < hiWire; ++wire) {
5379 if (WireHitRange[wire].first < 0)
continue;
5380 unsigned int firsthit = WireHitRange[wire].first;
5381 unsigned int lasthit = WireHitRange[wire].second;
5382 for (
unsigned int khit = firsthit; khit < lasthit; ++khit) {
5384 if (inClus[khit] <= 0)
continue;
5385 if ((
unsigned int)inClus[khit] >
tcl.size() + 1) {
5386 mf::LogError(
"CC") <<
"Invalid hit InClus. " << khit <<
" " << inClus[khit];
5390 if (theTime < fHits[khit].StartTick() - 20)
continue;
5391 if (theTime > fHits[khit].EndTick() + 20)
continue;
5392 kclID = inClus[khit];
5395 if (
tcl[kcl].
ID < 0)
continue;
5397 if (
tcl[kcl].tclhits.size() < 6)
continue;
5399 if (
tcl[kcl].tclhits.size() > 100 &&
std::abs(
tcl[kcl].BeginAng -
tcl[kcl].EndAng) < 0.1)
5403 mf::LogVerbatim(
"CC") <<
"Bingo " << ivx <<
" plane " << thePlane <<
" wire " << wire
5404 <<
" hit " << fHits[khit].WireID().Wire <<
":" 5405 << (
int)fHits[khit].PeakTime() <<
" inClus " << inClus[khit]
5406 <<
" P:W:T " << thePlane <<
":" <<
tcl[kcl].BeginWir <<
":" 5407 << (
int)
tcl[kcl].BeginTim;
5408 if (std::find(clIDs.begin(), clIDs.end(), kclID) == clIDs.end()) {
5409 clIDs.push_back(kclID);
5413 if (clIDs.size() == 0)
continue;
5415 for (
unsigned int ii = 0; ii < clIDs.size(); ++ii)
5418 unsigned short ii, icl, jj;
5425 unsigned short i2Dvx = 0;
5426 for (ii = 0; ii < 3; ++ii) {
5427 if (ii == thePlane)
continue;
5428 i2Dvx = vtx3[ivx].Ptr2D[ii];
5429 if (i2Dvx > vtx.size() - 1) {
5430 mf::LogError(
"CC") <<
"Vtx3ClusterSplit: Coding error";
5433 if (vtx[i2Dvx].TimeErr > tErr) tErr = vtx[i2Dvx].TimeErr;
5437 for (ii = 0; ii < clIDs.size(); ++ii) {
5438 icl = clIDs[ii] - 1;
5440 for (jj = 0; jj <
tcl[icl].tclhits.size(); ++jj) {
5441 iht =
tcl[icl].tclhits[jj];
5442 if (fHits[iht].
WireID().Wire < theWire) {
5444 if (jj > 3) nhitfit = -3;
5445 FitClusterMid(icl, iht, nhitfit);
5446 float doca = DoCA(-1, 1, theWire, theTime);
5449 <<
" cls " << icl <<
" dth " << dth <<
" DoCA " << doca <<
" tErr " << tErr;
5450 if ((doca / tErr) > 2) clIDs[ii] = -1;
5460 for (ii = 0; ii < clIDs.size(); ++ii)
5465 unsigned short nok = 0;
5466 for (ii = 0; ii < clIDs.size(); ++ii)
5467 if (clIDs[ii] >= 0) ++nok;
5468 if (nok == 0)
continue;
5472 vnew.
Wire = theWire;
5474 vnew.
Time = theTime;
5479 vtx.push_back(vnew);
5481 unsigned short ivnew = vtx.size() - 1;
5483 mf::LogVerbatim(
"CC") <<
"Make new 2D vtx " << ivnew <<
" in plane " << thePlane
5484 <<
" from 3D vtx " << ivx;
5485 vtx3[ivx].Ptr2D[thePlane] = ivnew;
5487 for (ii = 0; ii < clIDs.size(); ++ii) {
5488 if (clIDs[ii] < 0)
continue;
5489 icl = clIDs[ii] - 1;
5492 unsigned short pos = 0;
5493 for (
unsigned short jj = 0; jj <
tcl[icl].tclhits.size(); ++jj) {
5494 iht =
tcl[icl].tclhits[jj];
5495 if (fHits[iht].
WireID().Wire < theWire) {
5502 tcl[icl].BeginVtx = ivnew;
5505 else if (pos >
tcl[icl].tclhits.size()) {
5507 tcl[icl].EndVtx = ivnew;
5512 if (vtxprt)
mf::LogVerbatim(
"CC") <<
"Split cluster " << clIDs[ii] <<
" at pos " <<
pos;
5513 if (!SplitCluster(icl, pos, ivnew)) {
5517 tcl[icl].ProcCode += 10000;
5518 tcl[
tcl.size() - 1].ProcCode += 10000;
5523 if (vtx[ivnew].ChiDOF < 5 && vtx[ivnew].WireErr < fVertex2DWireErrCut) {
5525 vtx3[ivx].Wire = -1;
5529 mf::LogVerbatim(
"CC") <<
"Bad vtx fit " << ivnew <<
" ChiDOF " << vtx[ivnew].ChiDOF
5530 <<
" WireErr " << vtx[ivnew].WireErr;
5533 vtx3[ivx].Ptr2D[thePlane] = -1;
5535 for (jj = 0; jj <
tcl.size(); ++jj) {
5536 if (
tcl[jj].BeginVtx == ivnew)
tcl[jj].BeginVtx = -99;
5537 if (
tcl[jj].EndVtx == ivnew)
tcl[jj].EndVtx = -99;
5554 unsigned int nPln = geom->Cryostat(cstat).TPC(tpc).Nplanes();
5555 if (nPln != 3)
return;
5557 float ew1, ew2, bw2, fvw;
5564 unsigned short longClIndex;
5565 unsigned short shortClIndex;
5566 unsigned short splitPos;
5568 std::array<std::vector<Hammer>, 3> hamrVec;
5572 for (ipl = 0; ipl < 3; ++ipl) {
5574 for (
unsigned short ic1 = 0; ic1 <
tcl.size(); ++ic1) {
5575 if (
tcl[ic1].
ID < 0)
continue;
5577 if (
tcl[ic1].tclhits.size() < 20)
continue;
5578 if (
tcl[ic1].CTP != clCTP)
continue;
5580 if (
tcl[ic1].EndVtx >= 0)
continue;
5581 ew1 =
tcl[ic1].EndWir;
5582 for (
unsigned short ic2 = 0; ic2 <
tcl.size(); ++ic2) {
5583 if (
tcl[ic2].
ID < 0)
continue;
5585 if (
tcl[ic2].tclhits.size() > 20)
continue;
5587 if (
tcl[ic2].tclhits.size() < 6)
continue;
5588 if (
tcl[ic2].CTP != clCTP)
continue;
5589 ew2 =
tcl[ic2].EndWir;
5590 bw2 =
tcl[ic2].BeginWir;
5593 if (ew1 < ew2 || ew1 > bw2)
continue;
5597 unsigned short spos = 0;
5598 for (
unsigned short ii = 0; ii <
tcl[ic2].tclhits.size(); ++ii) {
5599 unsigned int iht =
tcl[ic2].tclhits[ii];
5600 float dw = fHits[iht].WireID().Wire -
tcl[ic1].EndWir;
5601 float dt = fabs(fHits[iht].PeakTime() -
tcl[ic1].EndTim -
tcl[ic1].EndSlp * dw);
5608 if (ibst < 0)
continue;
5609 fvw = 0.5 + fHits[ibst].WireID().Wire;
5612 aHam.Wire = (0.5 + fvw);
5613 aHam.Tick = fHits[ibst].PeakTime();
5614 aHam.X = det_prop.
ConvertTicksToX((
double)aHam.Tick, (
int)ipl, (
int)tpc, (
int)cstat);
5615 aHam.longClIndex = ic1;
5616 aHam.shortClIndex = ic2;
5617 aHam.splitPos = spos;
5618 unsigned short indx = hamrVec[ipl].size();
5619 hamrVec[ipl].resize(indx + 1);
5620 hamrVec[ipl][indx] = aHam;
5627 unsigned short noham = 0;
5628 for (ipl = 0; ipl < 3; ++ipl)
5629 if (hamrVec[ipl].
size() == 0) ++noham;
5630 if (noham > 1)
return;
5633 double local[3] = {0., 0., 0.};
5634 double world[3] = {0., 0., 0.};
5636 const geo::TPCGeo& thetpc = geom->TPC(tpc, cstat);
5638 float YLo = world[1] - geom->DetHalfHeight(tpc, cstat) + 1;
5639 float YHi = world[1] + geom->DetHalfHeight(tpc, cstat) - 1;
5640 float ZLo = world[2] - geom->DetLength(tpc, cstat) / 2 + 1;
5641 float ZHi = world[2] + geom->DetLength(tpc, cstat) / 2 - 1;
5646 unsigned short icl, jpl, jcl, kpl, splitPos;
5647 for (ipl = 0; ipl < 3; ++ipl) {
5648 if (hamrVec[ipl].
size() == 0)
continue;
5649 jpl = (ipl + 1) % nPln;
5650 kpl = (jpl + 1) % nPln;
5651 for (
unsigned short ii = 0; ii < hamrVec[ipl].size(); ++ii) {
5652 if (hamrVec[ipl][ii].Used)
continue;
5653 for (
unsigned short jj = 0; jj < hamrVec[jpl].size(); ++jj) {
5654 if (hamrVec[jpl][jj].Used)
continue;
5655 dX = hamrVec[ipl][ii].X - hamrVec[jpl][jj].X;
5656 if (fabs(dX) > fVertex3DCut)
continue;
5657 geom->IntersectionPoint(
5658 hamrVec[ipl][ii].
Wire, hamrVec[jpl][jj].Wire, ipl, jpl, cstat, tpc, y, z);
5659 if (y < YLo || y > YHi || z < ZLo || z > ZHi)
continue;
5661 hamrVec[ipl][ii].Used =
true;
5662 hamrVec[jpl][jj].Used =
true;
5666 newVtx3.
X = 0.5 * (hamrVec[ipl][ii].X + hamrVec[jpl][jj].X);
5668 newVtx3.
XErr = fabs(hamrVec[ipl][ii].
X - hamrVec[jpl][jj].
X);
5673 newVtx3.
CStat = cstat;
5678 newVtx2.
Wire = hamrVec[ipl][ii].Wire;
5680 newVtx2.
Time = hamrVec[ipl][ii].Tick;
5683 newVtx2.
Fixed =
false;
5684 icl = hamrVec[ipl][ii].longClIndex;
5685 newVtx2.
CTP =
tcl[icl].CTP;
5686 vtx.push_back(newVtx2);
5687 unsigned short ivnew = vtx.size() - 1;
5689 tcl[icl].EndVtx = ivnew;
5692 newVtx3.
Ptr2D[ipl] = (short)ivnew;
5694 icl = hamrVec[ipl][ii].shortClIndex;
5695 splitPos = hamrVec[ipl][ii].splitPos;
5696 if (!SplitCluster(icl, splitPos, ivnew))
return;
5699 newVtx2.
Wire = hamrVec[jpl][jj].Wire;
5700 newVtx2.
Time = hamrVec[jpl][jj].Tick;
5702 jcl = hamrVec[jpl][jj].longClIndex;
5703 newVtx2.
CTP =
tcl[jcl].CTP;
5704 vtx.push_back(newVtx2);
5705 ivnew = vtx.size() - 1;
5707 tcl[jcl].EndVtx = ivnew;
5709 newVtx3.
Ptr2D[jpl] = (short)(vtx.size() - 1);
5712 jcl = hamrVec[jpl][jj].shortClIndex;
5713 splitPos = hamrVec[jpl][jj].splitPos;
5714 if (!SplitCluster(jcl, splitPos, vtx.size() - 1))
return;
5718 newVtx3.
Ptr2D[kpl] = -1;
5719 double WPos[3] = {0,
y, z};
5721 newVtx3.
Wire = geom->NearestWire(WPos, kpl, tpc, cstat);
5726 vtx3.push_back(newVtx3);
5744 const unsigned int cstat = tpcid.
Cryostat;
5745 const unsigned int tpc = tpcid.
TPC;
5748 double local[3] = {0., 0., 0.};
5749 double world[3] = {0., 0., 0.};
5751 const geo::TPCGeo& thetpc = geom->TPC(tpc, cstat);
5754 float YLo = world[1] - geom->DetHalfHeight(tpc, cstat) + 1;
5755 float YHi = world[1] + geom->DetHalfHeight(tpc, cstat) - 1;
5756 float ZLo = world[2] - geom->DetLength(tpc, cstat) / 2 + 1;
5757 float ZHi = world[2] + geom->DetLength(tpc, cstat) / 2 - 1;
5759 vtxprt = (fDebugPlane >= 0) && (fDebugHit == 6666);
5767 float wirePitch = geom->WirePitch(0, tpcid.
TPC, tpcid.
Cryostat);
5770 std::vector<float> vX(vtx.size());
5771 std::vector<float> vXsigma(vtx.size());
5773 for (
unsigned short ivx = 0; ivx < vtx.size(); ++ivx) {
5774 if (vtx[ivx].NClusters == 0)
continue;
5776 if (iplID.
TPC != tpc || iplID.
Cryostat != cstat)
continue;
5781 (
double)(vtx[ivx].Time + vtx[ivx].TimeErr), (
int)iplID.
Plane, (
int)tpc, (
int)cstat);
5782 vXsigma[ivx] = fabs(vXp - vX[ivx]);
5786 std::array<std::vector<unsigned short>, 3> vIndex;
5787 unsigned short indx, ipl;
5788 for (
unsigned short ivx = 0; ivx < vtx.size(); ++ivx) {
5789 if (vtx[ivx].NClusters == 0)
continue;
5791 if (iplID.
TPC != tpc || iplID.
Cryostat != cstat)
continue;
5793 if (ipl > 2)
continue;
5794 indx = vIndex[ipl].size();
5795 vIndex[ipl].resize(indx + 1);
5796 vIndex[ipl][indx] = ivx;
5800 std::vector<short> vPtr;
5801 for (
unsigned short ii = 0; ii < vtx.size(); ++ii)
5805 std::vector<Vtx3Store> v3temp;
5807 double y = 0,
z = 0;
5808 TVector3 WPos = {0, 0, 0};
5810 unsigned short ii, jpl, jj, kpl, kk, ivx, jvx, kvx;
5811 unsigned int iWire, jWire;
5812 unsigned short v3dBest = 0;
5813 float xbest = 0, ybest = 0, zbest = 0;
5817 for (ipl = 0; ipl < 2; ++ipl) {
5818 for (ii = 0; ii < vIndex[ipl].size(); ++ii) {
5819 ivx = vIndex[ipl][ii];
5820 if (ivx > vtx.size() - 1) {
5825 if (vPtr[ivx] >= 0)
continue;
5826 iWire = vtx[ivx].Wire;
5827 float best = fVertex3DCut;
5831 std::array<short, 3> t2dIndex = {{-1, -1, -1}};
5832 std::array<short, 3> tmpIndex = {{-1, -1, -1}};
5833 for (jpl = ipl + 1; jpl < 3; ++jpl) {
5834 for (jj = 0; jj < vIndex[jpl].size(); ++jj) {
5835 jvx = vIndex[jpl][jj];
5836 if (jvx > vtx.size() - 1) {
5841 if (vPtr[jvx] >= 0)
continue;
5842 jWire = vtx[jvx].Wire;
5844 float dX = fabs(vX[ivx] - vX[jvx]);
5845 float dXSigma = sqrt(vXsigma[ivx] * vXsigma[ivx] + vXsigma[jvx] * vXsigma[jvx]);
5846 float dXChi = dX / dXSigma;
5850 <<
"VtxMatch: ipl " << ipl <<
" ivx " << ivx <<
" ivX " << vX[ivx] <<
" jpl " << jpl
5851 <<
" jvx " << jvx <<
" jvX " << vX[jvx] <<
" W:T " << (
int)vtx[jvx].
Wire <<
":" 5852 << (
int)vtx[jvx].Time <<
" dXChi " << dXChi <<
" fVertex3DCut " << fVertex3DCut;
5854 if (dXChi > fVertex3DCut)
continue;
5855 geom->IntersectionPoint(iWire, jWire, ipl, jpl, cstat, tpc, y,
z);
5856 if (y < YLo || y > YHi || z < ZLo || z > ZHi)
continue;
5859 kpl = 3 - ipl - jpl;
5860 kX = 0.5 * (vX[ivx] + vX[jvx]);
5864 kWire = geom->NearestWire(WPos, kpl, tpc, cstat);
5870 kpl = 3 - ipl - jpl;
5874 tmpIndex[ipl] = ivx;
5875 tmpIndex[jpl] = jvx;
5877 v3d.
Ptr2D = tmpIndex;
5881 float yzSigma = wirePitch * sqrt(vtx[ivx].WireErr * vtx[ivx].WireErr +
5882 vtx[jvx].WireErr * vtx[jvx].WireErr);
5889 v3temp.push_back(v3d);
5893 <<
"VtxMatch: 2 Plane match ivx " << ivx <<
" P:W:T " << ipl <<
":" 5894 << (
int)vtx[ivx].
Wire <<
":" << (
int)vtx[ivx].Time <<
" jvx " << jvx <<
" P:W:T " 5895 << jpl <<
":" << (
int)vtx[jvx].
Wire <<
":" << (
int)vtx[jvx].Time <<
" dXChi " 5896 << dXChi <<
" yzSigma " << yzSigma;
5898 if (TPC.
Nplanes() == 2)
continue;
5900 best = fVertex3DCut;
5901 for (kk = 0; kk < vIndex[kpl].size(); ++kk) {
5902 kvx = vIndex[kpl][kk];
5903 if (vPtr[kvx] >= 0)
continue;
5905 float dW = wirePitch * (vtx[kvx].Wire -
kWire) / yzSigma;
5907 float dX = (vX[kvx] -
kX) / dXSigma;
5908 float kChi = 0.5 * sqrt(dW * dW + dX * dX);
5911 xbest = (vX[kvx] + 2 *
kX) / 3;
5914 t2dIndex[ipl] = ivx;
5915 t2dIndex[jpl] = jvx;
5916 t2dIndex[kpl] = kvx;
5917 v3dBest = v3temp.size() - 1;
5922 <<
" kvx " << kvx <<
" kpl " << kpl <<
" wire " << (
int)vtx[kvx].
Wire <<
" kTime " 5923 << (
int)vtx[kvx].Time <<
" kChi " << kChi <<
" best " << best <<
" dW " 5924 << vtx[kvx].Wire -
kWire;
5928 mf::LogVerbatim(
"CC") <<
" done best = " << best <<
" fVertex3DCut " << fVertex3DCut;
5929 if (TPC.
Nplanes() > 2 && best < fVertex3DCut) {
5931 if (v3dBest > v3temp.size() - 1) {
5932 mf::LogError(
"CC") <<
"VtxMatch: bad v3dBest " << v3dBest;
5936 v3d.
Ptr2D = t2dIndex;
5942 vtx3.push_back(v3d);
5945 for (
unsigned short jj = 0; jj < 3; ++jj)
5946 if (t2dIndex[jj] >= 0) vPtr[t2dIndex[jj]] = vtx3.size() - 1;
5950 <<
"New 3D vtx " << vtx3.size() <<
" X " << v3d.
X <<
" Y " << v3d.
Y <<
" Z " 5951 << v3d.
Z <<
" t2dIndex " << t2dIndex[0] <<
" " << t2dIndex[1] <<
" " 5952 << t2dIndex[2] <<
" best Chi " << best;
5964 unsigned short vsize = vtx3.size();
5965 for (
unsigned short it = 0; it < v3temp.size(); ++it) {
5967 for (
unsigned short i3d = 0; i3d < vsize; ++i3d) {
5968 for (
unsigned short plane = 0; plane < 3; ++plane) {
5969 if (v3temp[it].Ptr2D[plane] == vtx3[i3d].Ptr2D[plane]) {
5977 if (keepit) vtx3.push_back(v3temp[it]);
5982 for (
unsigned short iv3 = 0; iv3 < vtx3.size(); ++iv3) {
5983 vtx3[iv3].Ptr2D[2] = 666;
5988 for (
unsigned short it = 0; it < vtx3.size(); ++it) {
5989 mf::LogVerbatim(
"CC") <<
"vtx3 " << it <<
" Ptr2D " << vtx3[it].Ptr2D[0] <<
" " 5990 << vtx3[it].Ptr2D[1] <<
" " << vtx3[it].Ptr2D[2] <<
" wire " 5999 ClusterCrawlerAlg::GetHitRange(
CTP_t CTP)
6006 WireHitRange.resize(nwires + 1);
6012 unsigned int wire, iht;
6013 unsigned int nHitInPlane;
6014 std::pair<int, int> flag;
6019 for (
auto& apair : WireHitRange)
6024 std::vector<bool> firsthit;
6025 firsthit.resize(nwires + 1,
true);
6026 bool firstwire =
true;
6027 for (iht = 0; iht < fHits.size(); ++iht) {
6028 if (fHits[iht].
WireID().TPC != planeID.
TPC)
continue;
6030 if (fHits[iht].
WireID().Plane != planeID.
Plane)
continue;
6031 wire = fHits[iht].WireID().Wire;
6033 if (firsthit[wire]) {
6034 WireHitRange[wire].first = iht;
6035 firsthit[wire] =
false;
6041 WireHitRange[wire].second = iht + 1;
6042 fLastWire = wire + 1;
6051 unsigned int nbad = 0;
6052 for (wire = 0; wire <
nwires; ++wire) {
6055 if (!channelStatus.
IsGood(chan)) {
6056 WireHitRange[wire] = flag;
6061 if (mergeAvailable.size() < fHits.size())
6063 <<
"GetHitRange: Invalid mergeAvailable vector size " << mergeAvailable.size()
6065 unsigned int firstHit, lastHit;
6068 float maxRMS, chiSep, peakCut;
6069 for (wire = 0; wire <
nwires; ++wire) {
6071 if (WireHitRange[wire].first < 0)
continue;
6072 firstHit = WireHitRange[wire].first;
6073 lastHit = WireHitRange[wire].second;
6074 for (iht = firstHit; iht < lastHit; ++iht) {
6077 <<
"Bad WireHitRange on wire " << wire <<
"\n";
6079 if (fHits[iht].Multiplicity() > 1) {
6080 peakCut = 0.6 * fHits[iht].PeakAmplitude();
6081 std::pair<size_t, size_t> MultipletRange = FindHitMultiplet(iht);
6082 for (
size_t jht = MultipletRange.first; jht < MultipletRange.second; ++jht) {
6083 if (jht == iht)
continue;
6085 if (fHits[jht].PeakAmplitude() < peakCut)
continue;
6086 maxRMS =
std::max(fHits[iht].RMS(), fHits[jht].RMS());
6087 chiSep =
std::abs(fHits[iht].PeakTime() - fHits[jht].PeakTime()) / maxRMS;
6088 if (chiSep < fHitMergeChiCut) {
6089 mergeAvailable[iht] =
true;
6096 if (cnt != nHitInPlane)
6097 mf::LogWarning(
"CC") <<
"Bad WireHitRange count " << cnt <<
" " << nHitInPlane <<
"\n";
6099 if (!fMergeAllHits)
return;
6103 for (wire = 0; wire <
nwires; ++wire) {
6104 if (WireHitRange[wire].first < 0)
continue;
6105 firstHit = WireHitRange[wire].first;
6106 lastHit = WireHitRange[wire].second;
6107 for (iht = firstHit; iht < lastHit; ++iht) {
6108 if (!mergeAvailable[iht])
continue;
6110 if (fHits[iht].GoodnessOfFit() == 6666)
continue;
6111 MergeHits(iht, didMerge);
6112 mergeAvailable[iht] =
false;
6122 if (inWire1 > inWire2) {
6124 unsigned int tmp = inWire1;
6129 unsigned int wire, ndead = 0;
6130 for (wire = inWire1; wire < inWire2; ++wire)
6131 if (WireHitRange[wire].first == -1) ++ndead;
6140 if (fcl2hits.size() < 2)
return 0;
6141 unsigned int wire, ndead = 0;
6142 unsigned int iht = fcl2hits[fcl2hits.size() - 1];
6143 unsigned int eWire = fHits[iht].WireID().Wire;
6145 unsigned int bWire = fHits[iht].WireID().Wire + 1;
6146 for (wire = eWire; wire < bWire; ++wire)
6147 if (WireHitRange[wire].first == -1) ++ndead;
6160 std::pair<size_t, size_t>
6161 ClusterCrawlerAlg::FindHitMultiplet(
size_t iHit)
const 6163 std::pair<size_t, size_t> range{iHit, iHit};
6165 range.first = iHit - fHits[iHit].LocalIndex();
6166 range.second = range.first + fHits[iHit].Multiplicity();
6176 unsigned int nDuplicates = 0;
6177 std::set<unsigned int> hits;
6178 for (
unsigned int hit : fcl2hits) {
6179 if (hits.count(
hit)) {
6182 log <<
"Hit #" <<
hit 6183 <<
" being included twice in the future cluster (ID=" << (
tcl.size() + 1)
6184 <<
"?) at location: " << location;
6185 if (!marker.empty()) log <<
" (marker: '" << marker <<
"')";
6189 return nDuplicates > 0;
6194 ClusterCrawlerAlg::DoCA(
short icl,
unsigned short end,
float vwire,
float vtick)
6199 if (icl > (
short)
tcl.size())
return 9999;
6201 float cwire, cslp, ctick;
6204 if (fcl2hits.size() == 0)
return 9999;
6220 cwire =
tcl[icl].BeginWir;
6221 cslp =
tcl[icl].BeginSlp;
6222 ctick =
tcl[icl].BeginTim;
6225 cwire =
tcl[icl].EndWir;
6226 cslp =
tcl[icl].EndSlp;
6227 ctick =
tcl[icl].EndTim;
6232 float docaW = (vwire + cslp * (vtick - ctick) + cwire * cslp * cslp) / (1 + cslp * cslp);
6233 float dW = docaW - vwire;
6234 float dT = ctick + (vwire - cwire) * cslp - vtick;
6235 return sqrt(dW * dW + dT * dT);
6241 ClusterCrawlerAlg::ClusterVertexChi(
short icl,
unsigned short end,
unsigned short ivx)
6245 if (icl > (
short)
tcl.size())
return 9999;
6246 if (ivx > vtx.size())
return 9999;
6248 float cwire, cslp, cslpErr, ctick;
6251 if (fcl2hits.size() == 0)
return 9999;
6256 cslpErr = clBeginSlpErr;
6262 cslpErr = clparerr[1];
6269 cwire =
tcl[icl].BeginWir;
6270 cslp =
tcl[icl].BeginSlp;
6271 cslpErr =
tcl[icl].BeginSlpErr;
6272 ctick =
tcl[icl].BeginTim;
6275 cwire =
tcl[icl].EndWir;
6276 cslp =
tcl[icl].EndSlp;
6277 cslpErr =
tcl[icl].EndSlpErr;
6278 ctick =
tcl[icl].EndTim;
6284 (vtx[ivx].Wire + cslp * (vtx[ivx].Time - ctick) + cwire * cslp * cslp) / (1 + cslp * cslp);
6285 float dW = docaW - vtx[ivx].Wire;
6286 float chi = dW / vtx[ivx].WireErr;
6287 float totChi = chi * chi;
6288 dW = vtx[ivx].Wire - cwire;
6289 float dT = ctick + dW * cslp - vtx[ivx].Time;
6290 if (cslpErr < 1
E-3) cslpErr = 1
E-3;
6292 cslpErr *= AngleFactor(cslp);
6294 float dTErr = dW * cslpErr;
6298 dTErr += vtx[ivx].TimeErr * vtx[ivx].TimeErr;
6299 if (dTErr < 1
E-3) dTErr = 1
E-3;
6300 totChi += dT * dT / dTErr;
6309 ClusterCrawlerAlg::PointVertexChi(
float wire,
float tick,
unsigned short ivx)
6313 if (ivx > vtx.size())
return 9999;
6315 float dW = wire - vtx[ivx].Wire;
6316 float chi = dW / vtx[ivx].WireErr;
6317 float totChi = chi * chi;
6318 float dT = tick - vtx[ivx].Time;
6319 chi = dT / vtx[ivx].TimeErr;
6320 totChi += chi * chi;
6331 if (iht > fHits.size() - 1)
return "Bad Hit";
short int LocalIndex() const
How well do we believe we know this hit?
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
span(IterB &&b, IterE &&e, Adaptor &&adaptor) -> span< decltype(adaptor(std::forward< IterB >(b))), decltype(adaptor(std::forward< IterE >(e))) >
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Functions to help with numbers.
geo::SigType_t SignalType() const
Signal type for the plane of the hit.
static unsigned int kWire
Encapsulate the construction of a single cyostat.
double rms(sqlite3 *db, std::string const &table_name, std::string const &column_name)
struct of temporary 2D vertices (end points)
geo::WireID WireID() const
unsigned int Nplanes() const
Number of planes in this tpc.
float RMS() const
RMS of the hit shape, in tick units.
Planes which measure X direction.
The data type to uniquely identify a Plane.
Geometry information for a single TPC.
double Temperature() const
In kelvin.
float SigmaPeakAmplitude() const
Uncertainty on estimated amplitude of the hit at its peak, in ADC units.
float SigmaIntegral() const
int DegreesOfFreedom() const
CryostatID_t Cryostat
Index of cryostat.
float Integral() const
Integral under the calibrated signal waveform of the hit, in tick x ADC units.
struct of temporary clusters
geo::View_t View() const
View for the plane of the hit.
WireID_t Wire
Index of the wire within its plane.
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
Cluster finding and building.
float GoodnessOfFit() const
Degrees of freedom in the determination of the hit signal shape (-1 by default)
short int Multiplicity() const
How many hits could this one be shared with.
struct of temporary 3D vertices
Q_EXPORT QTSManip setprecision(int p)
art framework interface to geometry description
float PeakAmplitude() const
The estimated amplitude of the hit at its peak, in ADC units.
constexpr int cmp(WireID const &other) const
Returns < 0 if this is smaller than tpcid, 0 if equal, > 0 if larger.
double Efield(unsigned int planegap=0) const
kV/cm
int TDCtick_t
Type representing a TDC tick.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Collection of exceptions for Geometry system.
T get(std::string const &key) const
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
double ConvertXToTicks(double X, int p, int t, int c) const
void MergeOverlap(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
unsigned int NumberTimeSamples() const
virtual bool IsGood(raw::ChannelID_t channel) const
Returns whether the specified channel is physical and good.
std::string PrintHit(const TCHit &tch)
bool SortByLowHit(unsigned int i, unsigned int j)
Class providing information about the quality of channels.
bool has_key(std::string const &key) const
static int max(int a, int b)
double DriftVelocity(double efield=0., double temperature=0.) const
cm/us
The data type to uniquely identify a TPC.
PlaneID_t Plane
Index of the plane within its TPC.
raw::TDCtick_t StartTick() const
Initial tdc tick for hit.
float PeakTimeMinusRMS(float sigmas=+1.) const
std::array< short, 3 > Ptr2D
void err(const char *fmt,...)
Detector simulation of raw signals on wires.
constexpr auto absDiff(A const &a, B const &b)
Returns the absolute value of the difference between two values.
Q_EXPORT QTSManip setw(int w)
double ConvertTicksToX(double ticks, int p, int t, int c) const
raw::TDCtick_t EndTick() const
Final tdc tick for hit.
bool greaterThan(CluLen c1, CluLen c2)
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
float PeakTime() const
Time of the signal peak, in tick units.
Declaration of signal hit object.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Contains all timing reference information for the detector.
std::vector< unsigned int > tclhits
geo::PlaneID DecodeCTP(CTP_t CTP)
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
QTextStream & bin(QTextStream &s)
Interface for experiment-specific channel quality info provider.
static double tdiff(const art::Timestamp &ts1, const art::Timestamp &ts2)
Exception thrown on invalid wire number.
float SummedADC() const
The sum of calibrated ADC counts of the hit (0. by default)
Access the description of detector geometry.
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
float SigmaPeakTime() const
Uncertainty for the signal peak, in tick units.
2D representation of charge deposited in the TDC/wire plane
float PeakTimePlusRMS(float sigmas=+1.) const
Returns a time sigmas RMS away from the peak time.
unsigned int ChannelID_t
Type representing the ID of a readout channel.
TPCID_t TPC
Index of the TPC within its cryostat.
Interface for experiment-specific service for channel quality info.
second_as<> second
Type of time stored in seconds, in double precision.
geo::WireID suggestedWireID() const
Returns a better wire ID.
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
recob::tracking::Plane Plane
raw::ChannelID_t Channel() const
ID of the readout channel the hit was extracted from.
std::string to_string(ModuleType const mt)
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Encapsulate the construction of a single detector plane.