19 #include "canvas/Utilities/Exception.h"
20 #include "fhiclcpp/ParameterSet.h"
21 #include "messagefacility/MessageLogger/MessageLogger.h"
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");
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");
71 fLACrawl = pset.get<std::vector<bool>>(
"LACrawl");
72 fMinAmp = pset.get<std::vector<float>>(
"MinAmp", {5, 5, 5});
79 if (pset.has_key(
"HammerCluster")) {
81 <<
"fcl setting HammerCluster is replaced by FindHammerClusters. Ignoring...";
86 fHitErrFac = pset.get<
float>(
"HitErrFac", 0.2);
87 fHitMinAmp = pset.get<
float>(
"HitMinAmp", 0.2);
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;
123 throw art::Exception(art::errors::Configuration)
124 <<
"ClusterCrawlerAlg: Bad input from fcl file";
140 if (cmp_res != 0)
return cmp_res < 0;
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();
234 for (
unsigned int iht = 0; iht <
inClus.size(); ++iht) {
245 cstat = tpcid.Cryostat;
256 float wirePitch =
geom->WirePitch(
geom->View(channel));
259 fScaleF = tickToDist / wirePitch;
270 VtxMatch(clock_data, det_prop, tpcid);
277 mf::LogVerbatim(
"CC") <<
"Clustering done in TPC ";
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;
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;
325 if ((iwire + 1) < span)
continue;
326 jwire = iwire - span + 1;
328 mf::LogVerbatim(
"CC") <<
"Found debug hit " <<
PrintHit(ihit) <<
" on pass" <<
pass;
333 unsigned int nmissed = 0;
339 mf::LogVerbatim(
"CC")
340 <<
" new jwire " << jwire <<
" dead? " <<
WireHitRange[jwire].first;
345 unsigned int useHit = 0;
346 bool doConstrain =
false;
350 if (jfirsthit >
fHits.size() - 1 || jfirsthit >
fHits.size() - 1)
351 throw art::Exception(art::errors::LogicError)
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)
356 throw art::Exception(art::errors::LogicError)
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;
386 for (kwire = jwire + 1; kwire < iwire; ++kwire) {
392 AddHit(kwire, HitOK, SigOK);
394 mf::LogVerbatim(
"CC") <<
" HitOK " << HitOK <<
" clChisq " <<
clChisq <<
" cut "
409 mf::LogVerbatim(
"CC")
427 for (
unsigned short kk = 0; kk <
fcl2hits.size(); ++kk) {
454 mf::LogError(
"CC") <<
"Failed to store cluster in plane " <<
plane;
459 AllDone = (nHitsUsed ==
fHits.size());
464 if (
prt) mf::LogVerbatim(
"CC") <<
"ClusterLoop: dropped the cluster";
466 if (ClusterAdded || AllDone)
break;
498 mf::LogVerbatim(
"CC") <<
"Clustering done in plane " <<
plane;
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;
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;
658 unsigned short icl, jcl;
661 if (chkprt) mf::LogVerbatim(
"CC") <<
"Inside MergeOverlap using clCTP " <<
clCTP;
663 unsigned short minLen = 6;
664 unsigned short minOvrLap = 2;
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;
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;
692 mf::LogVerbatim(
"CC") <<
"MergeOverlap icl ID " <<
tcl[icl].ID <<
" jcl ID "
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;
699 mf::LogVerbatim(
"CC") <<
" Candidate icl ID " <<
tcl[icl].ID <<
" " <<
tcl[icl].EndWir
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];
711 if (dTick > maxDTick)
continue;
713 mf::LogVerbatim(
"CC") <<
" dTick icl iht time " <<
PrintHit(iht) <<
" jcl EndTim "
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];
720 if (dTick > maxDTick)
continue;
722 mf::LogVerbatim(
"CC") <<
" dTick jcl jht time " <<
PrintHit(jht) <<
" icl BeginTim "
723 <<
tcl[icl].BeginTim <<
" dTick " << dTick;
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];
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];
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;
759 if (
prt) mf::LogVerbatim(
"CC") <<
"hit " <<
PrintHit(iht);
761 if (
fcl2hits.size() < 0.5 * overlapSize)
continue;
766 mf::LogVerbatim(
"CC") <<
" Overlap size " << overlapSize <<
" fit chisq " <<
clChisq
770 std::vector<unsigned int> oHits =
fcl2hits;
774 unsigned short jclNewSize;
775 for (jclNewSize = 0; jclNewSize <
fcl2hits.size(); ++jclNewSize) {
780 mf::LogVerbatim(
"CC") <<
"jcl old size " <<
fcl2hits.size() <<
" newSize " << jclNewSize;
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;
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;
823 tcl[
tcl.size() - 1].BeginVtx =
tcl[jcl].BeginVtx;
824 tcl[
tcl.size() - 1].EndVtx =
tcl[icl].BeginVtx;
827 mf::LogVerbatim(
"CC") <<
"MergeOverlap new long cluster ID " <<
tcl[
tcl.size() - 1].ID
828 <<
" in clCTP " <<
clCTP;
830 if (
tcl[icl].ID < 0)
break;
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)
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)
875 if (nTrim == 0)
return;
880 for (
unsigned short ii = 0; ii < nTrim; ++ii) {
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;
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;
953 unsigned int destHit = 0;
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) {
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);
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;
1026 if (skipit)
continue;
1029 for (ii = 0; ii < 3; ++ii) {
1031 if (
fHits[iht].Multiplicity() > 1) {
1033 if (didMerge) ++nhm;
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;
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()) /
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) {
1085 prtime = time0 + slp;
1087 mf::LogVerbatim(
"CC") <<
"ChkClusterDS: Try to extend " <<
tcl[icl].ID <<
" to W:T "
1088 << wire <<
" hitrms " << hitrms <<
" prevth " << prevth
1089 <<
" prtime " << (int)prtime;
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()) /
1101 thhits = std::atan(
fScaleF * slp);
1103 mf::LogVerbatim(
"CC") <<
" theta " << thhits <<
" prevth " << prevth <<
" cut "
1105 if (
std::abs(thhits - prevth) > dThCut)
continue;
1109 rmsrat =
fHits[ih1].RMS() / hitrms;
1110 ratOK = rmsrat > 0.3 && rmsrat < 3;
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];
1160 mf::LogError(
"CC") <<
"ChkClusterDS TmpStore failed while extending cluster ID "
1164 const size_t newcl =
tcl.size() - 1;
1165 if (
prt) { mf::LogVerbatim(
"CC") <<
" Store " << newcl; }
1166 tcl[newcl].BeginVtx =
tcl[icl].BeginVtx;
1167 tcl[newcl].EndVtx =
tcl[icl].EndVtx;
1180 if (
vtx.size() == 0)
return false;
1181 if (
fcl2hits.size() == 0)
return false;
1183 unsigned int iht =
fcl2hits.size() - 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;
1214 if (
vtx.size() == 0)
return false;
1215 unsigned int iht =
fcl2hits.size() - 1;
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;
1231 unsigned int& useHit,
1237 doConstrain =
false;
1238 if (
vtx.size() == 0)
return;
1240 if (
pass == 0)
return;
1245 mf::LogError(
"CC") <<
"VtxConstraint fed bad jwire " << jwire <<
" WireHitRange size "
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;
1262 float prtime =
clpar[0] +
clpar[1] * (jwire - iwire);
1263 for (
unsigned int jhit = jfirsthit; jhit < jlasthit; ++jhit) {
1264 if (
inClus[jhit] != 0)
continue;
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;
1332 if (
vtxprt) mf::LogVerbatim(
"CC") <<
" to " <<
vtx[iv].Wire;
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) {
1366 tcl[
tcl.size() - 1].EndVtx = iv;
1369 mf::LogVerbatim(
"CC") <<
" modified cluster " <<
tcl[icl].ID <<
" -> "
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();
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();
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;
1439 if (
vtxprt) mf::LogVerbatim(
"CC") <<
"VtxClusterSplit ";
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;
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];
1488 mf::LogVerbatim(
"CC") <<
"Split cluster " <<
tcl[icl].ID <<
" at 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;
1505 if (
vtxprt) mf::LogVerbatim(
"CC") <<
" iclAng " << iclAng;
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) {
1528 if (
vtxprt) mf::LogVerbatim(
"CC") <<
"Split/Chop at pos " << nLop;
1533 for (
unsigned short ii = 0; ii < nLop; ++ii) {
1544 unsigned short newcl =
tcl.size() - 1;
1545 tcl[newcl].BeginVtx =
tcl[icl].BeginVtx;
1546 tcl[newcl].EndVtx = ivx;
1553 tcl[
tcl.size() - 1].ProcCode += 1000;
1554 tcl[
tcl.size() - 2].ProcCode += 1000;
1558 didSomething =
true;
1564 return didSomething;
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;
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;
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;
1678 double arg = (other_hit.
PeakTime() - (double)time) / other_hit.
RMS();
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);
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;
1793 if (
tcl.size() < 2)
return;
1800 mf::LogVerbatim(
"CC") <<
"FindStarVertices";
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;
1855 mf::LogVerbatim(
"CC") <<
"Chk clusters " <<
tcl[it1].ID <<
" " <<
tcl[it2].ID
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) {
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) {
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;
1923 mf::LogVerbatim(
"CC") <<
" new vertex " << ivx <<
" cluster " <<
tcl[it1].ID
1924 <<
" split pos " << pos1;
1926 tcl[
tcl.size() - 1].ProcCode += 1000;
1927 tcl[
tcl.size() - 2].ProcCode += 1000;
1929 mf::LogVerbatim(
"CC") <<
" new vertex " << ivx <<
" cluster " <<
tcl[it2].ID
1930 <<
" split pos " << pos2;
1932 tcl[
tcl.size() - 1].ProcCode += 1000;
1933 tcl[
tcl.size() - 2].ProcCode += 1000;
1939 if (
vtx.size() > vtxSizeIn) {
1948 mf::LogVerbatim(
"CC") <<
"Vertices " <<
vtx.size();
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 "
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);
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) {
2000 mf::LogVerbatim(
"CC") <<
" Attach cluster Begin to vtx? " << iv <<
" sigOK " << sigOK;
2003 mf::LogVerbatim(
"CC") <<
" check ClusterVertexChi " <<
ClusterVertexChi(icl, 0, iv);
2006 tcl[icl].BeginVtx = iv;
2009 tcl[icl].BeginVtx = -99;
2016 if (
tcl[icl].EndVtx < 0 && !bCloser && dwe > -3 && dwe < 3 &&
tcl[icl].BeginVtx != iv) {
2019 mf::LogVerbatim(
"CC") <<
" Attach cluster End to vtx? " << iv <<
" sigOK " << sigOK;
2022 mf::LogVerbatim(
"CC") <<
" check ClusterVertexChi " <<
ClusterVertexChi(icl, 1, iv);
2025 tcl[icl].EndVtx = iv;
2028 tcl[icl].EndVtx = -99;
2042 for (
unsigned short iv = 0; iv <
vtx.size(); ++iv) {
2043 if (
vtx[iv].CTP != inCTP)
continue;
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);
2074 unsigned short vtxSizeIn =
vtx.size();
2078 mf::LogVerbatim(
"CC") <<
"FindVertices plane " <<
plane <<
" pass " <<
pass;
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]; }
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;
2136 mf::LogVerbatim(
"CC")
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) {
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;
2173 mf::LogVerbatim(
"CC")
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) {
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;
2199 mf::LogVerbatim(
"CC")
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) {
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;
2230 mf::LogVerbatim(
"CC")
2231 <<
" vtx wire " << vw <<
" time " << fvt <<
" dth " << dth <<
" dwcut " << dwcut;
2232 if (fvt > 0. && fvt < maxtime) {
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;
2274 for (
unsigned short ivx = 0; ivx <
vtx.size(); ++ivx) {
2275 if (
vtx[ivx].CTP !=
clCTP)
continue;
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;
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;
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;
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);
2349 tcl[it].EndVtx = iv;
2353 mf::LogVerbatim(
"CC") <<
" Add End " <<
tcl[it].ID <<
" to vtx " << iv <<
" NClusters "
2354 <<
vtx[iv].NClusters;
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 "
2375 tcl[it].BeginVtx = iv;
2379 mf::LogVerbatim(
"CC") <<
" Add Begin " <<
tcl[it].ID <<
" to vtx " << iv
2380 <<
" NClusters " <<
vtx[iv].NClusters;
2383 mf::LogVerbatim(
"CC") <<
" Bad fit. ChiDOF " <<
vtx[iv].ChiDOF <<
" WireErr "
2384 <<
vtx[iv].WireErr <<
" Undo it";
2385 tcl[it].BeginVtx = -99;
2409 mf::LogVerbatim(
"CC") <<
" ChkVertex " <<
tcl[it1].EndWir <<
":" << (int)
tcl[it1].EndTim
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];
2441 unsigned short nFitOK = 0;
2442 for (
unsigned short iv = 0; iv <
vtx.size(); ++iv) {
2443 if (
vtx[iv].CTP !=
clCTP)
continue;
2447 mf::LogVerbatim(
"CC") <<
" vtx " << iv <<
" PointVertexChi "
2450 if ((topo == 1 || topo == 2) &&
tcl[it1].EndVtx < 0) {
2453 tcl[it1].EndVtx = iv;
2456 mf::LogVerbatim(
"CC") <<
" FitVtx " << iv <<
" WireErr " <<
vtx[iv].WireErr
2457 <<
" ChiDOF " <<
vtx[iv].ChiDOF;
2461 tcl[it1].EndVtx = -99;
2466 else if ((topo == 3 || topo == 4) &&
tcl[it1].BeginVtx < 0) {
2468 tcl[it1].BeginVtx = iv;
2471 mf::LogVerbatim(
"CC") <<
" FitVtx " << iv <<
" WireErr " <<
vtx[iv].WireErr
2472 <<
" ChiDOF " <<
vtx[iv].ChiDOF;
2476 tcl[it1].BeginVtx = -99;
2481 if ((topo == 1 || topo == 3) &&
tcl[it2].EndVtx < 0) {
2483 tcl[it2].EndVtx = iv;
2486 mf::LogVerbatim(
"CC") <<
" FitVtx " << iv <<
" WireErr " <<
vtx[iv].WireErr
2487 <<
" ChiDOF " <<
vtx[iv].ChiDOF;
2491 tcl[it2].EndVtx = -99;
2496 else if ((topo == 2 || topo == 4) &&
tcl[it2].BeginVtx < 0) {
2498 tcl[it2].BeginVtx = iv;
2501 mf::LogVerbatim(
"CC") <<
" FitVtx " << iv <<
" WireErr " <<
vtx[iv].WireErr
2502 <<
" ChiDOF " <<
vtx[iv].ChiDOF;
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); }
2526 if (topo == 1 || topo == 3) { SigOK =
ChkSignal(vw, fvt,
tcl[it2].EndWir,
tcl[it2].EndTim); }
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;
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;
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;
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);
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};
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;
2670 for (
unsigned int khit = firsthit; khit < lasthit; ++khit) {
2675 if (prTime >
fHits[khit].EndTick())
continue;
2680 if (
fHits[khit].PeakTime() - prTime > 500)
continue;
2683 if (bin > 19)
continue;
2684 if (bin < 0)
continue;
2686 amp +=
fHits[khit].PeakAmplitude() * gausAmp[
bin];
2702 if (
tcl[icl].ID < 0)
return false;
2707 unsigned short ii, iclnew;
2725 for (ii = 0; ii < pos; ++ii) {
2726 iht =
tcl[icl].tclhits[ii];
2730 pass =
tcl[icl].ProcCode - 10 * (
tcl[icl].ProcCode / 10);
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) {
2768 bool didFit =
false;
2769 for (ii = pos; ii <
tcl[icl].tclhits.size(); ++ii) {
2770 iht =
tcl[icl].tclhits[ii];
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 "
2821 if (
tcl.size() < 2)
return;
2827 if (
prt) mf::LogVerbatim(
"CC") <<
"ChkMerge on pass " <<
pass;
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);
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;
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);
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))
2899 mf::LogVerbatim(
"CC") <<
"Chk1 ID1-2 " <<
tcl[it1].ID <<
"-" <<
tcl[it2].ID <<
" " << ew1
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);
2913 mf::LogVerbatim(
"CC") <<
" dtim " << dtim <<
" timecut " << (int)timecut <<
" ec1 "
2914 << ec1 <<
" bc2 " << bc2 <<
" chgrat " << chgrat <<
" chgcut "
2915 << chgcut <<
" es1 " << es1 <<
" ChkSignal "
2917 if (chgrat < chgcut && dtim < timecut) {
2921 tclsize =
tcl.size();
2929 dth = fabs(bth1 - eth2);
2931 dw = ew2 - bw1 - ndead;
2932 if (
prt && bw1 < (ew2 + maxOverlap) && dw < skipcut)
2933 mf::LogVerbatim(
"CC") <<
"Chk2 ID1-2 " <<
tcl[it1].ID <<
"-" <<
tcl[it2].ID <<
" " << bw1
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);
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) {
2956 tclsize =
tcl.size();
2962 if (bw2 < bw1 && ew2 > ew1) {
2965 dth = fabs(eth2 - eth1);
2966 dtim = fabs(et1 + (ew2 - ew1 - 1) * es1 - et2);
2971 short nmiss1 = bw1 - ew1 + 1 -
tcl[it1].tclhits.size();
2973 short nin2 =
tcl[it2].tclhits.size();
2975 mf::LogVerbatim(
"CC") <<
"cl2: " << ew2 <<
":" << (int)et2 <<
" - " << bw2 <<
":"
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);
3000 short nmiss2 = bw2 - ew2 + 1 -
tcl[it2].tclhits.size();
3002 short nin1 =
tcl[it1].tclhits.size();
3004 mf::LogVerbatim(
"CC") <<
"cl1: " << ew1 <<
":" << (int)et1 <<
" - " << bw1 <<
":"
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;
3037 if (
prt) mf::LogVerbatim(
"CC") <<
"ChkMerge12 " <<
tcl[it1].ID <<
" " <<
tcl[it2].ID;
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) {
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;
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);
3107 if (
prt) mf::LogVerbatim(
"CC") <<
"US dtheta " << dth <<
" cut " <<
fKinkAngCut[cpass];
3108 if (dth > fKinkAngCut[cpass])
return;
3111 if (
prt) mf::LogVerbatim(
"CC") <<
"US chgrat " << chgrat <<
" cut " <<
fMergeChgCut[
pass];
3114 SigOK =
ChkSignal(wiron1, timon1, ew2, et2);
3115 if (
prt) mf::LogVerbatim(
"CC") <<
"US SigOK? " << SigOK;
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;
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);
3143 if (
prt) mf::LogVerbatim(
"CC") <<
"DS dtheta " << dth <<
" cut " << fKinkAngCut[cpass];
3144 if (dth > fKinkAngCut[cpass])
return;
3147 if (
prt) mf::LogVerbatim(
"CC") <<
"DS chgrat " << chgrat <<
" cut " << fMergeChgCut[
pass];
3149 SigOK =
ChkSignal(wiron1, timon1, bw2, bt2);
3150 if (
prt) mf::LogVerbatim(
"CC") <<
"DS SigOK? " << SigOK;
3153 if (
prt) mf::LogVerbatim(
"CC") <<
"Merge em";
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;
3221 short del1Vtx = -99;
3222 short del2Vtx = -99;
3272 unsigned short itnew =
tcl.size() - 1;
3274 mf::LogVerbatim(
"CC") <<
"DoMerge " << cl1.
ID <<
" " << cl2.
ID <<
" -> " <<
tcl[itnew].ID;
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;
3290 mf::LogVerbatim myprt(
"CC");
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) {
3299 myprt <<
std::right << std::setw(3) << std::fixed << iv << std::setprecision(1);
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) {
3327 myprt <<
std::right << std::setw(3) << std::fixed << iv << std::setprecision(1);
3329 myprt <<
std::right << std::setw(8) <<
vtx[iv].Wire <<
" +/- ";
3331 myprt <<
std::right << std::setw(8) <<
vtx[iv].Time <<
" +/- ";
3338 for (
unsigned short ii = 0; ii <
tcl.size(); ++ii) {
3340 if (
tcl[ii].ID < 0)
continue;
3341 if (
tcl[ii].BeginVtx == (
short)iv) myprt <<
std::right << std::setw(4) <<
tcl[ii].ID;
3342 if (
tcl[ii].EndVtx == (
short)iv) myprt <<
std::right << std::setw(4) <<
tcl[ii].ID;
3356 mf::LogVerbatim myprt(
"CC");
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) {
3370 myprt <<
std::right << std::setw(5) <<
tcl[ii].tclhits.size();
3373 unsigned int iTime =
tcl[ii].BeginTim;
3374 myprt <<
std::right << std::setw(6) <<
tcl[ii].BeginWir <<
":" << iTime;
3375 if (iTime < 10) { myprt <<
" "; }
3376 else if (iTime < 100) {
3379 else if (iTime < 1000)
3381 myprt <<
std::right << std::setw(7) << std::fixed << std::setprecision(2) <<
tcl[ii].BeginAng;
3383 myprt <<
std::right << std::setw(6) << std::fixed << std::setprecision(2)
3384 <<
tcl[ii].BeginSlp;
3387 myprt <<
std::right << std::setw(6) << (int)
tcl[ii].BeginSlp;
3389 myprt <<
std::right << std::setw(6) << std::fixed << std::setprecision(2)
3390 <<
tcl[ii].BeginSlpErr;
3391 myprt <<
std::right << std::setw(5) << (int)
tcl[ii].BeginChg;
3392 iTime =
tcl[ii].EndTim;
3393 myprt <<
std::right << std::setw(6) <<
tcl[ii].EndWir <<
":" << iTime;
3394 if (iTime < 10) { myprt <<
" "; }
3395 else if (iTime < 100) {
3398 else if (iTime < 1000)
3400 myprt <<
std::right << std::setw(7) << std::fixed << std::setprecision(2) <<
tcl[ii].EndAng;
3402 myprt <<
std::right << std::setw(6) << std::fixed << std::setprecision(2) <<
tcl[ii].EndSlp;
3407 myprt <<
std::right << std::setw(6) << std::fixed << std::setprecision(2)
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();
3419 myprt <<
std::right << std::setw(5) << std::fixed << std::setprecision(1) << aveRMS;
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];
3431 arg = (
fHits[hit0].PeakTime() +
fHits[hit2].PeakTime()) / 2 -
fHits[hit1].PeakTime();
3432 aveRes += arg * arg;
3436 aveRes /= (float)cnt;
3437 aveRes = sqrt(aveRes);
3440 myprt <<
std::right << std::setw(6) << std::fixed << std::setprecision(1) << aveRes;
3441 myprt <<
std::right << std::setw(5) << std::fixed << cnt;
3445 myprt <<
std::right << std::setw(5) << std::fixed << cnt;
3459 if (it1 >
tcl.size())
return;
3486 if (
fcl2hits.size() < 2)
return false;
3489 if (
NClusters == SHRT_MAX)
return false;
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) {
3508 fHits[
hit].WireID().Plane != tPlane) {
3513 if (clProcCode < 900 && it > 0 &&
fHits[hit].
WireID().Wire >= lastWire) {
3517 lastWire =
fHits[
hit].WireID().Wire;
3526 unsigned int ih0 =
fcl2hits.size() - 2;
3569 tcl.push_back(clstr);
3582 short dwir =
fHits[dhit].WireID().Wire;
3589 mf::LogVerbatim myprt(
"CC");
3590 myprt <<
"******************* LACrawlUS PASS " <<
pass <<
" Hits ";
3591 for (
unsigned short ii = 0; ii <
fcl2hits.size(); ++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 "
3614 if (
prt) mf::LogVerbatim(
"CC") <<
"LACrawlUS: stop at vertex";
3619 AddLAHit(nextwire, ChkCharge, HitOK, SigOK);
3621 mf::LogVerbatim(
"CC") <<
"LACrawlUS: HitOK " << HitOK <<
" SigOK " << SigOK
3623 if (SigOK) nmissed = 0;
3626 if (nmissed > fAllowNoHitWire) {
3636 prevWire =
fHits[prevHit].WireID().Wire;
3637 if (prevWire > nextwire + 2) {
3650 for (
unsigned short kk = 0; kk <
fcl2hits.size() - 1; ++kk) {
3661 unsigned short chsiz =
chifits.size() - 1;
3663 if (chsiz < 6)
continue;
3666 mf::LogError(
"CC") <<
"LACrawlUS: chifits size error " <<
chifits.size() <<
" "
3671 mf::LogVerbatim(
"CC") <<
"Kink chk " <<
chifits[chsiz] <<
" " <<
chifits[chsiz - 1] <<
" "
3676 unsigned int ih0 =
fcl2hits.size() - 1;
3678 unsigned int ih2 = ih0 - 2;
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;
3686 unsigned int ih5 = ih3 - 2;
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);
3693 mf::LogVerbatim(
"CC") <<
" Kink angle " << std::setprecision(3) << dth <<
" cut "
3695 if (dth > fKinkAngCut[
pass]) {
3701 if (kinkOnWire > 0) {
3702 if (kinkOnWire - nextwire < 4) {
3704 mf::LogVerbatim(
"CC")
3705 <<
"Hit a second kink. kinkOnWire = " << kinkOnWire <<
" Stopping";
3711 kinkOnWire = nextwire;
3712 if (
prt) mf::LogVerbatim(
"CC") <<
"Removed kink hits";
3720 if (
prt) mf::LogVerbatim(
"CC") <<
"LACrawlUS done. Nhits = " <<
fcl2hits.size();
3733 int dwir =
fHits[dhit].WireID().Wire;
3741 mf::LogVerbatim myprt(
"CC");
3742 myprt <<
"******************* Start CrawlUS on pass " <<
pass <<
" Hits: ";
3743 for (
unsigned short ii = 0; ii <
fcl2hits.size(); ++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 "
3777 if (
prt) mf::LogVerbatim(
"CC") <<
"CrawlUS: stop at vertex";
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;
3801 if ((
int)(
fcl2hits.size() - nHitAfterSkip) < 4) {
3805 if (
prt) mf::LogVerbatim(
"CC") <<
" PostSkip && nmissed = " << nmissed;
3827 mf::LogVerbatim(
"CC")
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];
3844 if (
prt) mf::LogVerbatim(
"CC") <<
"ADD- Bad clChisq " <<
clChisq <<
" dropping hit";
3848 if (nDroppedHit > 4) {
3850 mf::LogVerbatim(
"CC")
3851 <<
" Too many dropped hits: " << nDroppedHit <<
" Stop crawling";
3854 if (
clChisq > fChiCut[pass]) {
3856 mf::LogVerbatim(
"CC")
3857 <<
" Bad clChisq " <<
clChisq <<
" after dropping hit. Stop crawling";
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]
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
3885 mf::LogVerbatim(
"CC")
3886 <<
"******************* Stopped tracking - kink angle " <<
EndKinkAngle() <<
" > "
3902 if (clBeginChg <= 0 && fAveChg > 0) {
3904 if (
prt) mf::LogVerbatim(
"CC") <<
" Set clBeginChg " <<
clBeginChg;
3922 if (
clChisq > fChiCut[pass]) {
3923 if (
prt) mf::LogVerbatim(
"CC") <<
"<<ADD- Bad chisq " <<
clChisq;
3926 unsigned short lopped = 0;
3927 for (
unsigned short nlop = 0; nlop < 4; ++nlop) {
3928 unsigned short cfsize =
chifits.size() - 1;
3931 mf::LogVerbatim(
"CC")
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;
3942 if (
prt) mf::LogVerbatim(
"CC") <<
"Bad fit chisq - short cluster. Break";
3945 if (lopped == 0 &&
fcl2hits.size() > 5) {
3946 if (
prt) mf::LogVerbatim(
"CC") <<
"<<ADD- Bad chisq. remove 1 hit";
3953 mf::LogVerbatim(
"CC") <<
"Bad fit chisq - removed " << lopped <<
" hits. Continue";
3958 mf::LogVerbatim(
"CC") <<
"******************* CrawlUS normal stop. size " <<
fcl2hits.size();
3965 mf::LogVerbatim(
"CC") <<
"EndKinkAngle check " <<
EndKinkAngle() <<
" cut "
3968 if (
prt) mf::LogVerbatim(
"CC") <<
"EndKinkAngle removes 3 hits ";
3977 unsigned int ih0 =
fcl2hits.size() - 1;
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) {
3985 if (nxtwir != uswir + 1)
break;
3992 if (
prt) mf::LogVerbatim(
"CC") <<
"fMinWirAfterSkip removes " << nAdjHit <<
" hits ";
3999 if (!reFit &&
fcl2hits.size() > 3) {
4002 mf::LogVerbatim(
"CC") <<
"Last hit chirat " << chirat <<
" cut " <<
fKinkChiRat[
pass];
4006 if (chirat > fKinkChiRat[
pass]) {
4007 if (
prt) mf::LogVerbatim(
"CC") <<
"<<ADD- at end";
4019 mf::LogVerbatim(
"CC") <<
"******************* CrawlUS done. Size " <<
fcl2hits.size()
4031 unsigned int ih0 =
fcl2hits.size() - 1;
4033 unsigned int ih2 = ih0 - 2;
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;
4041 unsigned int ih5 = ih3 - 2;
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);
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) {
4092 float nhits =
std::count(cHits.begin(), cHits.end(),
true);
4093 float hitFrac = nhits / (float)cHits.size();
4111 mf::LogVerbatim(
"CC") <<
"CheckClusterHitFrac: Poor hit fraction " << hitFrac
4113 <<
" size " <<
fcl2hits.size() <<
" DeadWireCount "
4127 unsigned short nsing = 0;
4128 for (
unsigned short iht = 0; iht <
fcl2hits.size(); ++iht)
4130 hitFrac = (float)nsing / (
float)
fcl2hits.size();
4134 mf::LogVerbatim(
"CC") <<
"CheckClusterHitFrac: Poor short track hit fraction " << hitFrac;
4142 unsigned int iht, nht = 0;
4143 for (
unsigned short ii = 0; ii <
fcl2hits.size(); ++ii) {
4147 if (nht == 8)
break;
4152 unsigned short cnt =
chgNear.size() / 2;
4154 if (
chgNear.size() > 60) cnt = 30;
4157 for (
unsigned short ids = 0; ids < cnt; ++ids) {
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) {
4207 mf::LogError(
"CC") <<
"FitClusterMid bad iht " << iht;
4213 wire0 =
fHits[iht].WireID().Wire;
4217 xwir.push_back((
float)
fHits[iht].
WireID().Wire - wire0);
4218 ytim.push_back(
fHits[iht].PeakTime());
4221 ytimerr2.push_back(terr * terr);
4224 if (hitcnt == usnhit)
break;
4232 for (
auto ii = hitVec.crbegin(); ii != hitVec.crend(); ++ii) {
4234 if (iht >
fHits.size() - 1) {
4235 mf::LogVerbatim(
"CC") <<
"FitClusterMid bad iht " << iht;
4241 wire0 =
fHits[iht].WireID().Wire;
4245 xwir.push_back((
float)
fHits[iht].
WireID().Wire - wire0);
4246 ytim.push_back(
fHits[iht].PeakTime());
4248 ytimerr2.push_back(terr * terr);
4251 if (hitcnt == usnhit)
break;
4257 if (nht < 2)
return;
4263 float intcpterr = 0.;
4264 float slopeerr = 0.;
4266 fLinFitAlg.
LinFit(xwir, ytim, ytimerr2, intcpt, slope, intcpterr, slopeerr, chidof);
4288 mf::LogError(
"CC") <<
"FitCluster called on invalid pass " <<
pass;
4292 unsigned short ii, nht = 0;
4302 if (nht < 2)
return;
4304 std::vector<float> xwir;
4305 std::vector<float> ytim;
4306 std::vector<float> ytimerr2;
4313 float terr, qave = 0, qwt;
4314 for (ii = 0; ii < nht; ++ii) {
4316 qave +=
fHits[ihit].Integral();
4319 for (ii = 0; ii < nht; ++ii) {
4321 wire =
fHits[ihit].WireID().Wire;
4322 xwir.push_back(wire - wire0);
4323 ytim.push_back(
fHits[ihit].PeakTime());
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);
4338 mf::LogVerbatim myprt(
"CC");
4339 myprt <<
"FitCluster W:T ";
4340 unsigned short cnt = 0;
4341 for (std::vector<unsigned int>::reverse_iterator it =
fcl2hits.rbegin();
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;
4372 mf::LogVerbatim(
"CC") <<
"nht " << nht <<
" fitpar " << (int)
clpar[0] <<
"+/-"
4373 << (
int)intcpterr <<
" " <<
clpar[1] <<
"+/-" << slopeerr <<
" clChisq "
4384 if (slp > 15) slp = 15;
4386 float angfac = 1 + 0.03 * slp * slp;
4395 for (
unsigned short ii = 0; ii <
fcl2hits.size(); ++ii)
4408 unsigned int ih0 =
fcl2hits.size() - 1;
4411 mf::LogError(
"CC") <<
"FitClusterChg bad pass " <<
pass;
4425 for (
unsigned short ii = 0; ii < nhave; ++ii) {
4457 else if ((
unsigned short)
fcl2hits.size() > fitLen) {
4459 std::vector<float> xwir;
4460 std::vector<float> ychg;
4461 std::vector<float> ychgerr2;
4465 unsigned short npt = 0;
4466 unsigned short imlast = 0;
4470 for (
unsigned int ii =
fcl2hits.size() - 1; ii > 0; --ii) {
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) {
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);
4502 mf::LogVerbatim(
"CC") <<
"FitClusterChg wire " << wire0 <<
" chidof " << (int)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;
4513 if (ave > 1.3)
return;
4514 if (ave < 0.77)
return;
4531 if (kwire < fFirstWire || kwire >
fLastWire)
return;
4551 unsigned int lastClHit = UINT_MAX;
4554 if (lastClHit == 0) {
4564 float chgrat, hitWidth;
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;
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()
4582 <<
" dT " << std::fixed << std::setprecision(1) << dtime <<
" InClus "
4583 <<
inClus[khit] <<
" mult " <<
fHits[khit].Multiplicity() <<
" width "
4584 << (int)hitWidth <<
" MergeAvail " <<
mergeAvailable[khit] <<
" Chi2 "
4585 << std::fixed << std::setprecision(2) <<
fHits[khit].GoodnessOfFit()
4586 <<
" Charge " << (int)
fHits[khit].Integral() <<
" chgrat "
4587 << std::fixed << std::setprecision(1) << chgrat <<
" index " << khit;
4589 if (
fHits[khit].PeakTime() > chgWinLo &&
fHits[khit].PeakTime() < chgWinHi)
4590 cnear +=
fHits[khit].Integral();
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) {
4608 if (
prt && !HitOK) mf::LogVerbatim(
"CC") <<
" no hit found ";
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;
4629 if (
prt) mf::LogVerbatim(
"CC") <<
" Close to a vertex. Don't merge hits";
4636 unsigned short nused = 0;
4638 float multipletChg = 0.;
4642 for (
size_t jht = MultipletRange.first; jht < MultipletRange.second; ++jht) {
4643 if (
inClus[jht] < 0)
continue;
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();
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();
4669 mf::LogVerbatim(
"CC") <<
" merge hits charge check " << (int)multipletChg
4670 <<
" Previous hit charge " << (
int)
fHits[lastClHit].Integral();
4671 if (chgrat > 2) doMerge =
false;
4690 cnear -=
fHits[imbest].Integral();
4691 if (cnear < 0) cnear = 0;
4693 cnear /=
fHits[imbest].Integral();
4696 hitWidth =
fHits[imbest].EndTick() -
fHits[imbest].StartTick();
4697 mf::LogVerbatim(
"CC") <<
" >>LADD" <<
pass <<
" W:T " <<
PrintHit(imbest) <<
" dT "
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();
4709 if (
prt) mf::LogVerbatim(
"CC") <<
" LADD- Removed bad hit. Stopped tracking";
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;
4744 for (ii = 0; ii < nHitToChk; ++ii) {
4746 mf::LogVerbatim(
"CC") <<
"ClusterHitsOK chk " <<
fHits[
fcl2hits[indx]].WireID().Wire
4747 <<
" start " <<
fHits[
fcl2hits[indx]].StartTick() <<
" peak "
4749 <<
fHits[
fcl2hits[indx]].EndTick() <<
" posSlope " << posSlope;
4754 for (ii = 0; ii < nHitToChk - 1; ++ii) {
4764 if (loEndTick + tol < hiStartTick) {
return false; }
4767 if (loEndTick + tol < hiStartTick) {
return false; }
4786 if (kwire < fFirstWire || kwire >
fLastWire)
return;
4788 unsigned int lastClHit = UINT_MAX;
4792 unsigned int wire0 =
clpar[2];
4815 float dw = (float)kwire - (
float)wire0;
4817 if (prtime < 0 || (
unsigned int)prtime >
fMaxTime)
return;
4824 if (lastClHit != UINT_MAX) hiterr = 3 *
fHitErrFac *
fHits[lastClHit].RMS();
4825 float err = std::sqrt(prtimerr2 + hiterr * hiterr);
4829 float prtimeLo = prtime - hitWin;
4830 float prtimeHi = prtime + hitWin;
4834 mf::LogVerbatim(
"CC") <<
"AddHit: wire " << kwire <<
" prtime Lo " << (int)prtimeLo
4835 <<
" prtime " << (
int)prtime <<
" Hi " << (int)prtimeHi <<
" prtimerr "
4836 << sqrt(prtimerr2) <<
" hiterr " << hiterr <<
" fAveChg "
4837 << (int)
fAveChg <<
" fAveHitWidth " << std::setprecision(3)
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();
4856 mf::LogVerbatim(
"CC") <<
" Chk W:T " <<
PrintHit(khit) <<
" dT " << std::fixed
4857 << std::setprecision(1) << (hitTime - prtime) <<
" InClus "
4858 <<
inClus[khit] <<
" mult " <<
fHits[khit].Multiplicity() <<
" RMS "
4859 << std::fixed << std::setprecision(1) <<
fHits[khit].RMS() <<
" Chi2 "
4860 << std::fixed << std::setprecision(1) <<
fHits[khit].GoodnessOfFit()
4861 <<
" Charge " << (int)
fHits[khit].Integral() <<
" Peak " << std::fixed
4862 << std::setprecision(1) <<
fHits[khit].PeakAmplitude() <<
" LoT "
4863 << (int)hitStartTick <<
" HiT " << (
int)hitEndTick <<
" index "
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;
4887 mf::LogVerbatim(
"CC") <<
" wire0 " << wire0 <<
" kwire " << kwire <<
" max "
4893 if (imbest == INT_MAX)
return;
4898 if (
prt) mf::LogVerbatim(
"CC") <<
" Best hit time " << (int)hit.
PeakTime();
4902 bool didMerge =
false;
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();
4929 if (lastHitChg < 0) lastHitChg =
fHits[lastClHit].Integral();
4932 mf::LogVerbatim(
"CC") <<
" Chk hit merge hitsep " << hitSep <<
" dChg "
4933 <<
std::abs(totChg - lastHitChg) <<
" Cut "
4936 if (
prt) mf::LogVerbatim(
"CC") <<
" Merging hit doublet " << imbest;
4938 if (
prt && !didMerge) mf::LogVerbatim(
"CC") <<
" Hit merge failed ";
4948 if (
prt) mf::LogVerbatim(
"CC") <<
" Chgrat " << std::setprecision(2) << chgrat;
4953 mf::LogVerbatim(
"CC") <<
" fails 3 x high charge cut " <<
fChgCut[
pass] <<
" on pass "
4962 bool lasthitbig =
false;
4963 bool lasthitlow =
false;
4964 if (lastClHit != UINT_MAX &&
util::absDiff(wire0, kwire) == 1) {
4966 lasthitbig = (lastchgrat > bigchgcut);
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. ";
4986 if (best > 2 * err) {
4987 if (
prt) mf::LogVerbatim(
"CC") <<
" high charge && bad dT= " << best <<
" err= " <<
err;
5004 cnear -=
fHits[imbest].Integral();
5005 if (cnear < 0) cnear = 0;
5007 cnear /=
fHits[imbest].Integral();
5014 mf::LogError(
"CC") <<
"AddHit: Bad length";
5019 mf::LogVerbatim(
"CC") <<
" >>ADD" <<
pass <<
" W:T " <<
PrintHit(imbest) <<
" dT " << best
5020 <<
" clChisq " <<
clChisq <<
" Chg " << (int)
fHits[imbest].Integral()
5021 <<
" AveChg " << (int)
fAveChg <<
" fcl2hits size " <<
fcl2hits.size();
5023 if (!fitChg)
return;
5024 if (
prt) mf::LogVerbatim(
"CC") <<
" Fit charge ";
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) {
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();
5086 mf::LogVerbatim(
"CC") <<
"Merging hit doublet " << iht <<
" W:T "
5087 <<
fHits[iht].WireID().Wire <<
":" <<
fHits[iht].PeakTime();
5089 if (didMerge)
hitNear[indx] = -1;
5098 if (prt) mf::LogVerbatim(
"CC") <<
"ChkClusterNearbyHits refit cluster. fAveChg= " <<
fAveChg;
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];
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];
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];
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.;
5213 if (chiDOF > 900)
return;
5216 if (vTime < 0 || vTime >
fMaxTime)
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;
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;
5257 if (
vtx3[ivx].Ptr2D[
plane] >= 0)
continue;
5261 if (thePlane > 2)
continue;
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;
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;
5292 tcl[icl].EndVtx = ivnew;
5293 vclIndex.push_back(icl);
5296 bool goodVtx =
false;
5297 if (vclIndex.size() > 0) {
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;
5329 const unsigned int tpc = tpcid.
TPC;
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;
5358 if (thePlane != lastplane) {
5361 lastplane = thePlane;
5364 std::vector<short> clIDs;
5365 if (theWire >
fFirstWire + 5) { loWire = theWire - 5; }
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) {
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];
5391 if (theTime >
fHits[khit].EndTick() + 20)
continue;
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)
5416 mf::LogVerbatim(
"CC") <<
" clIDs " << clIDs[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];
5444 if (jj > 3) nhitfit = -3;
5446 float doca =
DoCA(-1, 1, theWire, theTime);
5448 mf::LogVerbatim(
"CC")
5449 <<
" cls " << icl <<
" dth " << dth <<
" DoCA " << doca <<
" tErr " << tErr;
5450 if ((doca / tErr) > 2) clIDs[ii] = -1;
5459 mf::LogVerbatim(
"CC") <<
"clIDs after fit " << clIDs.size();
5460 for (ii = 0; ii < clIDs.size(); ++ii)
5461 mf::LogVerbatim(
"CC") <<
" clIDs " << clIDs[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];
5502 tcl[icl].BeginVtx = ivnew;
5503 if (
vtxprt) mf::LogVerbatim(
"CC") <<
"Attach to Begin " << icl;
5505 else if (pos >
tcl[icl].tclhits.size()) {
5507 tcl[icl].EndVtx = ivnew;
5508 if (
vtxprt) mf::LogVerbatim(
"CC") <<
"Attach to End " << icl;
5512 if (
vtxprt) mf::LogVerbatim(
"CC") <<
"Split cluster " << clIDs[ii] <<
" at pos " << pos;
5514 if (
vtxprt) mf::LogVerbatim(
"CC") <<
"SplitCluster failed";
5517 tcl[icl].ProcCode += 10000;
5518 tcl[
tcl.size() - 1].ProcCode += 10000;
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();
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.};
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;
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);
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;
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;
5718 newVtx3.
Ptr2D[kpl] = -1;
5719 double WPos[3] = {0,
y, z};
5726 vtx3.push_back(newVtx3);
5745 const unsigned int tpc = tpcid.
TPC;
5748 double local[3] = {0., 0., 0.};
5749 double world[3] = {0., 0., 0.};
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;
5762 mf::LogVerbatim(
"CC") <<
"Inside VtxMatch";
5770 std::vector<float> vX(
vtx.size());
5771 std::vector<float> vXsigma(
vtx.size());
5773 for (
unsigned short ivx = 0; ivx <
vtx.size(); ++ivx) {
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) {
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) {
5821 mf::LogError(
"CC") <<
"VtxMatch: bad ivx " << ivx;
5825 if (vPtr[ivx] >= 0)
continue;
5826 iWire =
vtx[ivx].Wire;
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) {
5837 mf::LogError(
"CC") <<
"VtxMatch: bad jvx " << jvx;
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;
5849 mf::LogVerbatim(
"CC")
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);
5892 mf::LogVerbatim(
"CC")
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;
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;
5921 mf::LogVerbatim(
"CC")
5922 <<
" kvx " << kvx <<
" kpl " << kpl <<
" wire " << (int)
vtx[kvx].Wire <<
" kTime "
5923 << (
int)
vtx[kvx].Time <<
" kChi " << kChi <<
" best " << best <<
" dW "
5928 mf::LogVerbatim(
"CC") <<
" done best = " << best <<
" fVertex3DCut " <<
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;
5949 mf::LogVerbatim(
"CC")
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) {
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 "
6012 unsigned int wire, iht;
6013 unsigned int nHitInPlane;
6014 std::pair<int, int>
flag;
6024 std::vector<bool> firsthit;
6025 firsthit.resize(nwires + 1,
true);
6026 bool firstwire =
true;
6027 for (iht = 0; iht <
fHits.size(); ++iht) {
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;
6047 art::ServiceHandle<lariov::ChannelStatusService const>()->GetProvider();
6051 unsigned int nbad = 0;
6052 for (wire = 0; wire < nwires; ++wire) {
6055 if (!channelStatus.
IsGood(chan)) {
6056 WireHitRange[wire] =
flag;
6062 throw art::Exception(art::errors::LogicError)
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) {
6076 throw art::Exception(art::errors::LogicError)
6077 <<
"Bad WireHitRange on wire " << wire <<
"\n";
6079 if (
fHits[iht].Multiplicity() > 1) {
6080 peakCut = 0.6 *
fHits[iht].PeakAmplitude();
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());
6096 if (cnt != nHitInPlane)
6097 mf::LogWarning(
"CC") <<
"Bad WireHitRange count " << cnt <<
" " << nHitInPlane <<
"\n";
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) {
6110 if (
fHits[iht].GoodnessOfFit() == 6666)
continue;
6122 if (inWire1 > inWire2) {
6124 unsigned int tmp = inWire1;
6129 unsigned int wire, ndead = 0;
6130 for (wire = inWire1; wire < inWire2; ++wire)
6141 unsigned int wire, ndead = 0;
6143 unsigned int eWire =
fHits[iht].WireID().Wire;
6145 unsigned int bWire =
fHits[iht].WireID().Wire + 1;
6146 for (wire = eWire; wire < bWire; ++wire)
6160 std::pair<size_t, size_t>
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();
6177 std::set<unsigned int> hits;
6179 if (hits.count(
hit)) {
6181 mf::LogProblem log(
"CC");
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;
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);
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;
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;
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;
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?
float fScaleF
scale factor from Tick/Wire to dx/du
std::vector< short > hitNear
bool ClusterHitsOK(short nHitChk)
float fAveChg
average charge at leading edge of cluster
process_name opflash particleana ie ie ie z
std::vector< ClusterStore > tcl
the clusters we are creating
std::vector< std::pair< int, int > > WireHitRange
void FitVtx(unsigned short iv)
Functions to help with numbers.
geo::SigType_t SignalType() const
Signal type for the plane of the hit.
void RemoveObsoleteHits()
Removes obsolete hits from hits, updating the indices.
void FitClusterMid(unsigned short it1, unsigned int iht, short nhit)
bool ChkSignal(unsigned int iht, unsigned int jht)
Utilities related to art service access.
BEGIN_PROLOG true icarus_rawdigitfilter FilterTools FilterPlane1 Plane
std::vector< float > fTimeDelta
max time difference for matching
static unsigned int kWire
Encapsulate the construction of a single cyostat.
process_name opflash particleana ie x
struct of temporary 2D vertices (end points)
float clparerr[2]
cluster parameter errors
then echo unknown compiler flag
static bool areInSameMultiplet(recob::Hit const &first_hit, recob::Hit const &second_hit)
Returns whether the two hits belong to the same multiplet.
std::vector< float > fChgCut
charge difference cut for adding a hit to a cluster
std::vector< Vtx3Store > vtx3
the 3D vertices we are reconstructing
float clBeginChg
begin average charge
std::vector< unsigned short > fMinWirAfterSkip
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.
Declaration of signal hit object.
int fDebugWire
set to the Begin Wire and Hit of a cluster to print
EResult err(const char *call)
Planes which measure X direction.
The data type to uniquely identify a Plane.
void CheckClusterHitFrac(bool prt)
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
float clEndSlp
slope at the end (= US end = low wire number)
static bool SortByMultiplet(recob::Hit const &a, recob::Hit const &b)
Comparison for sorting hits by wire and hit multiplet.
std::vector< unsigned short > fMaxWirSkip
max number of wires that can be skipped while crawling
bool fRefineVertexClusters
int DegreesOfFreedom() const
CryostatID_t Cryostat
Index of cryostat.
std::size_t size(FixedBins< T, C > const &) noexcept
void MergeHits(const unsigned int theHit, bool &didMerge)
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.
void FixMultipletLocalIndices(size_t begin, size_t end, short int multiplicity=-1)
Resets the local index and multiplicity of all the hits in [begin;end[.
std::vector< float > fMinAmp
expected minimum signal in each wire plane
CTP_t clCTP
Cryostat/TPC/Plane code.
then echo echo For and will not be changed by echo further linking echo echo B echo The symbol is in the uninitialized data multiple common symbols may appear with the echo same name If the symbol is defined the common echo symbols are treated as undefined references For more echo details on common see the discussion of warn common echo in *Note Linker see the discussion of warn common echo in *Note Linker such as a global int variable echo as opposed to a large global array echo echo I echo The symbol is an indirect reference to another symbol This echo is a GNU extension to the a out object file format which is echo rarely used echo echo N echo The symbol is a debugging symbol echo echo R echo The symbol is in a read only data section echo echo S echo The symbol is in an uninitialized data section for small echo objects echo echo T echo The symbol is in the the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo W echo The symbol is a weak symbol that has not been specifically echo tagged as a weak object symbol When a weak defined symbol echo is linked with a normal defined the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo echo The symbol is a stabs symbol in an a out object file In echo this the next values printed are the stabs other echo the stabs desc and the stab type Stabs symbols are echo used to hold debugging information For more echo see *Note or object file format specific echo echo For Mac OS X
std::vector< float > fMergeChgCut
max charge ratio for matching
float DoCA(short icl, unsigned short end, float vwire, float vtick)
float fHitErrFac
hit time error = fHitErrFac * hit RMS used for cluster fit
float GoodnessOfFit() const
Degrees of freedom in the determination of the hit signal shape (-1 by default)
void GetHitRange(CTP_t CTP)
float AngleFactor(float slope)
short int Multiplicity() const
How many hits could this one be shared with.
art::ServiceHandle< geo::Geometry const > geom
void AddLAHit(unsigned int kwire, bool &ChkCharge, bool &HitOK, bool &SigOK)
float fKillGarbageClusters
struct of temporary 3D vertices
float fAveHitWidth
average width (EndTick - StartTick) of hits
void FclTrimUS(unsigned short nTrim)
bool CrawlVtxChk(unsigned int kwire)
static geo::PlaneID DecodeCTP(CTP_t CTP)
float PeakAmplitude() const
The estimated amplitude of the hit at its peak, in ADC units.
constexpr details::BinObj< T > bin(T value)
Returns a wrapper to print the specified data in binary format.
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
void DoMerge(unsigned short it1, unsigned short it2, short ProcCode)
float fHitMinAmp
< ignore hits with Amp < this value
int TDCtick_t
Type representing a TDC tick.
int fDebugHit
out detailed information while crawling
std::vector< bool > fLACrawl
Crawl Large Angle clusters on pass?
std::vector< short > inClus
Hit used in cluster (-1 = obsolete, 0 = free)
unsigned int fLastWire
the last wire with a hit
void VtxMatch(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, geo::TPCID const &tpcid)
std::vector< float > fChiCut
stop adding hits to clusters if chisq too high
float ClusterVertexChi(short icl, unsigned short end, unsigned short ivx)
float fChgNearWindow
window (ticks) for finding nearby charge
Access the description of detector geometry.
void LinFit(std::vector< float > &x, std::vector< float > &y, std::vector< float > &ey2, float &Intercept, float &Slope, float &InterceptError, float &SlopeError, float &ChiDOF) const
unsigned short fNumPass
number of passes over the hit collection
Collection of exceptions for Geometry system.
float fMergeOverlapAngCut
angle cut for merging overlapping clusters
process_name opflash particleana ie ie y
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
unsigned int fFirstWire
the first wire with a hit
unsigned int clEndWir
begin wire
float fVertex2DCut
2D vtx -> cluster matching cut (chisq/dof)
void FindHammerClusters(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop)
std::vector< float > fKinkAngCut
kink angle cut made after fKinkChiRat
unsigned short fAllowNoHitWire
float fVertex3DCut
2D vtx -> 3D vtx matching cut (chisq/dof)
auto end(FixedBins< T, C > const &) noexcept
void VtxConstraint(unsigned int iwire, unsigned int ihit, unsigned int jwire, unsigned int &useHit, bool &doConstrain)
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
double ConvertXToTicks(double X, int p, int t, int c) const
void CalculateAveHitWidth()
unsigned int NumberTimeSamples() const
virtual bool IsGood(raw::ChannelID_t channel) const
Returns whether the specified channel is physical and good.
unsigned short fLAClusMaxHitsFit
max hits fitted on a Large Angle cluster
bool SortByLowHit(unsigned int i, unsigned int j)
void MakeClusterObsolete(unsigned short icl)
Marks the cluster as obsolete and frees hits still associated with it.
Class providing information about the quality of channels.
std::vector< float > fKinkChiRat
void RestoreObsoleteCluster(unsigned short icl)
Restores an obsolete cluster.
void TmpGet(unsigned short it1)
double DriftVelocity(double efield=0., double temperature=0.) const
cm/us
std::vector< bool > fFindVertices
run vertexing code after clustering?
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 clBeginSlp
begin slope (= DS end = high wire number)
std::pair< size_t, size_t > FindHitMultiplet(size_t iHit) const
std::vector< unsigned short > fMaxHitsFit
Max number of hits fitted.
float PeakTimeMinusRMS(float sigmas=+1.) const
std::array< short, 3 > Ptr2D
std::string PrintHit(unsigned int iht)
constexpr auto absDiff(A const &a, B const &b)
Returns the absolute value of the difference between two values.
static CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
float clChisq
chisq of the current fit
double ConvertTicksToX(double ticks, int p, int t, int c) const
raw::TDCtick_t EndTick() const
Final tdc tick for hit.
auto begin(FixedBins< T, C > const &) noexcept
bool greaterThan(CluLen c1, CluLen c2)
void CheckHitClusterAssociations()
void KillGarbageClusters()
bool clLA
using Large Angle crawling code
std::vector< recob::Hit > fHits
our version of the hits
float PeakTime() const
Time of the signal peak, in tick units.
std::vector< unsigned short > fMinHits
Min number of hits to make a cluster.
float clEndChg
end average charge
std::vector< float > chifits
fit chisq for monitoring kinks, etc
Contains all timing reference information for the detector.
unsigned int clBeginWir
begin wire
void ClusterVertex(unsigned short it2)
std::vector< unsigned int > tclhits
std::string to_string(WindowPattern const &pattern)
float fLAClusAngleCut
call Large Angle Clustering code if > 0
std::vector< bool > mergeAvailable
set true if hit is with HitMergeChiCut of a neighbor hit
bool SplitCluster(unsigned short icl, unsigned short pos, unsigned short ivx)
void RunCrawler(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, std::vector< recob::Hit > const &srchits)
float fClProjErrFac
cluster projection error factor
float clBeginTim
begin time
float fVertex2DWireErrCut
void Vtx3ClusterSplit(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, geo::TPCID const &tpcid)
void AddHit(unsigned int kwire, bool &HitOK, bool &SigOK)
Interface for experiment-specific channel quality info provider.
unsigned int fFirstHit
first hit used
static double tdiff(const art::Timestamp &ts1, const art::Timestamp &ts2)
float clBeginChgNear
nearby charge
Exception thrown on invalid wire number.
void ChkMerge12(unsigned short it1, unsigned short it2, bool &didit)
float SummedADC() const
The sum of calibrated ADC counts of the hit (0. by default)
std::vector< float > chgNear
charge near a cluster on each wire
std::vector< VtxStore > vtx
the endpoints we are reconstructing
bool fFindHammerClusters
look for hammer type clusters
void FitAllVtx(CTP_t inCTP)
float SigmaPeakTime() const
Uncertainty for the signal peak, in tick units.
2D representation of charge deposited in the TDC/wire plane
bool ChkMergedClusterHitFrac(unsigned short it1, unsigned short it2)
trkf::LinFitAlg fLinFitAlg
float PeakTimePlusRMS(float sigmas=+1.) const
Returns a time sigmas RMS away from the peak time.
float clEndChgNear
nearby charge
std::size_t count(Cont const &cont)
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.
void VertexCluster(unsigned short ivx)
std::vector< unsigned int > fcl2hits
vector of hits used in the cluster
float fChgSlp
slope of the charge vs wire
geo::WireID suggestedWireID() const
Returns a better wire ID.
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
void RefineVertexClusters(unsigned short ivx)
bool empty(FixedBins< T, C > const &) noexcept
raw::ChannelID_t Channel() const
ID of the readout channel the hit was extracted from.
void ChkVertex(float fvw, float fvt, unsigned short it1, unsigned short it2, short topo)
float PointVertexChi(float wire, float tick, unsigned short ivx)
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
unsigned int DeadWireCount()
art framework interface to geometry description
void ChkClusterNearbyHits(bool prt)
std::vector< unsigned short > fNHitsAve
Encapsulate the construction of a single detector plane.
std::vector< bool > fDoMerge
try to merge clusters?
void Vtx3ClusterMatch(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, geo::TPCID const &tpcid)
bool CheckHitDuplicates(std::string location, std::string marker="") const
Returns true if there are no duplicates in the hit list for next cluster.
ClusterCrawlerAlg(fhicl::ParameterSet const &pset)