31 #include "larevt/CalibrationDBI/Interface/ChannelStatusService.h" 32 #include "larevt/CalibrationDBI/Interface/ChannelStatusProvider.h" 54 fNumPass = pset.
get<
unsigned short >(
"NumPass", 0);
55 fMaxHitsFit = pset.
get< std::vector<unsigned short> >(
"MaxHitsFit");
56 fMinHits = pset.
get< std::vector<unsigned short> >(
"MinHits");
57 fNHitsAve = pset.
get< std::vector<unsigned short> >(
"NHitsAve");
58 fChgCut = pset.
get< std::vector<float> >(
"ChgCut");
59 fChiCut = pset.
get< std::vector<float> >(
"ChiCut");
60 fMaxWirSkip = pset.
get< std::vector<unsigned short> >(
"MaxWirSkip");
61 fMinWirAfterSkip = pset.
get< std::vector<unsigned short> >(
"MinWirAfterSkip");
62 fKinkChiRat = pset.
get< std::vector<float> >(
"KinkChiRat");
63 fKinkAngCut = pset.
get< std::vector<float> >(
"KinkAngCut");
64 fDoMerge = pset.
get< std::vector<bool> >(
"DoMerge");
65 fTimeDelta = pset.
get< std::vector<float> >(
"TimeDelta");
66 fMergeChgCut = pset.
get< std::vector<float> >(
"MergeChgCut");
67 fFindVertices = pset.
get< std::vector<bool> >(
"FindVertices");
68 fLACrawl = pset.
get< std::vector<bool> >(
"LACrawl");
69 fMinAmp = pset.
get< std::vector<float> >(
"MinAmp", {5, 5, 5});
70 fChgNearWindow = pset.
get<
float >(
"ChgNearWindow");
71 fChgNearCut = pset.
get<
float >(
"ChgNearCut");
73 fChkClusterDS = pset.
get<
bool >(
"ChkClusterDS",
false);
74 fVtxClusterSplit = pset.
get<
bool >(
"VtxClusterSplit",
false);
75 fFindStarVertices = pset.
get<
bool >(
"FindStarVertices",
false);
76 if(pset.
has_key(
"HammerCluster")) {
77 mf::LogWarning(
"CC")<<
"fcl setting HammerCluster is replaced by FindHammerClusters. Ignoring...";
79 fFindHammerClusters = pset.
get<
bool >(
"FindHammerClusters",
false);
80 fKillGarbageClusters = pset.
get<
float >(
"KillGarbageClusters", 0);
81 fRefineVertexClusters = pset.
get<
bool >(
"RefineVertexClusters",
false);
82 fHitErrFac = pset.
get<
float >(
"HitErrFac", 0.2);
83 fHitMinAmp = pset.
get<
float >(
"HitMinAmp", 0.2);
84 fClProjErrFac = pset.
get<
float >(
"ClProjErrFac", 4);
85 fMinHitFrac = pset.
get<
float >(
"MinHitFrac", 0.6);
87 fLAClusAngleCut = pset.
get<
float >(
"LAClusAngleCut", 45);
88 fLAClusMaxHitsFit = pset.
get<
unsigned short>(
"LAClusMaxHitsFit");
89 fMergeAllHits = pset.
get<
bool >(
"MergeAllHits",
false);
90 fHitMergeChiCut = pset.
get<
float >(
"HitMergeChiCut", 2.5);
91 fMergeOverlapAngCut = pset.
get<
float >(
"MergeOverlapAngCut");
92 fAllowNoHitWire = pset.
get<
unsigned short >(
"AllowNoHitWire", 0);
93 fVertex2DCut = pset.
get<
float >(
"Vertex2DCut", 5);
94 fVertex2DWireErrCut = pset.
get<
float >(
"Vertex2DWireErrCut", 5);
95 fVertex3DCut = pset.
get<
float >(
"Vertex3DCut", 5);
97 fDebugPlane = pset.
get<
int >(
"DebugPlane", -1);
98 fDebugWire = pset.
get<
int >(
"DebugWire", -1);
99 fDebugHit = pset.
get<
int >(
"DebugHit", -1);
103 bool badinput =
false;
104 if(fNumPass > fMaxHitsFit.size()) badinput =
true;
105 if(fNumPass > fMinHits.size()) badinput =
true;
106 if(fNumPass > fNHitsAve.size()) badinput =
true;
107 if(fNumPass > fChgCut.size()) badinput =
true;
108 if(fNumPass > fChiCut.size()) badinput =
true;
109 if(fNumPass > fMaxWirSkip.size()) badinput =
true;
110 if(fNumPass > fMinWirAfterSkip.size()) badinput =
true;
111 if(fNumPass > fKinkChiRat.size()) badinput =
true;
112 if(fNumPass > fKinkAngCut.size()) badinput =
true;
113 if(fNumPass > fDoMerge.size()) badinput =
true;
114 if(fNumPass > fTimeDelta.size()) badinput =
true;
115 if(fNumPass > fMergeChgCut.size()) badinput =
true;
116 if(fNumPass > fFindVertices.size()) badinput =
true;
117 if(fNumPass > fLACrawl.size()) badinput =
true;
120 <<
"ClusterCrawlerAlg: Bad input from fcl file";
133 if (cmp_res != 0)
return cmp_res < 0;
142 void ClusterCrawlerAlg::ClearResults() {
152 void ClusterCrawlerAlg::CrawlInit() {
153 prt =
false; vtxprt =
false;
154 NClusters = 0; clBeginSlp = 0; clBeginSlpErr = 0; clBeginTim = 0;
155 clBeginWir = 0; clBeginChg = 0; clBeginChgNear = 0; clEndSlp = 0; clEndSlpErr = 0;
156 clEndTim = 0; clEndWir = 0; clEndChg = 0; clEndChgNear = 0; clChisq = 0;
157 clStopCode = 0; clProcCode = 0; fFirstWire = 0;
158 fLastWire = 0; fAveChg = 0.; fChgSlp = 0.; pass = 0;
159 fScaleF = 0; WireHitRange.clear();
166 void ClusterCrawlerAlg::ClusterInit()
181 void ClusterCrawlerAlg::RunCrawler(std::vector<recob::Hit>
const& srchits)
189 if(fHits.size() < 3)
return;
190 if(fHits.size() > UINT_MAX) {
191 mf::LogWarning(
"CC")<<
"Too many hits for ClusterCrawler "<<fHits.size();
196 if(fNumPass == 0)
return;
201 std::sort(fHits.begin(), fHits.end(), &SortByMultiplet);
203 inClus.resize(fHits.size());
204 mergeAvailable.resize(fHits.size());
205 for(
unsigned int iht = 0; iht < inClus.size(); ++iht) {
207 mergeAvailable[iht] =
false;
212 for (
geo::TPCID const& tpcid: geom->IterateTPCIDs()) {
214 for(plane = 0; plane < TPC.
Nplanes(); ++plane){
215 WireHitRange.clear();
217 clCTP =
EncodeCTP(tpcid.Cryostat, tpcid.TPC, plane);
218 cstat = tpcid.Cryostat;
250 if (WireHitRange.empty()||(fFirstWire == fLastWire))
continue;
254 float wirePitch = geom->WirePitch(geom->View(channel));
257 fScaleF = tickToDist / wirePitch;
259 if(fLAClusAngleCut > 0)
260 fLAClusSlopeCut = std::tan(3.142 * fLAClusAngleCut / 180.) / fScaleF;
262 fNumWires = geom->Nwires(plane, tpc, cstat);
264 if(fNumPass > 0) ClusterLoop();
266 if(fVertex3DCut > 0) {
269 Vtx3ClusterMatch(tpcid);
270 if(fFindHammerClusters) FindHammerClusters();
272 Vtx3ClusterSplit(tpcid);
274 if(fDebugPlane >= 0) {
281 WireHitRange.clear();
324 RemoveObsoleteHits();
329 void ClusterCrawlerAlg::ClusterLoop()
333 unsigned int nHitsUsed = 0, iwire, jwire, kwire;
334 bool AllDone =
false, SigOK =
false, HitOK =
false;
335 unsigned int ihit, jhit;
336 for(
unsigned short thispass = 0; thispass < fNumPass; ++thispass) {
339 unsigned int span = 3;
340 if(fMinHits[pass] < span) span = fMinHits[pass];
341 for(iwire = fLastWire; iwire > fFirstWire + span; --iwire) {
343 if(WireHitRange[iwire].first < 0)
continue;
344 auto ifirsthit = (
unsigned int)WireHitRange[iwire].first;
345 auto ilasthit = (
unsigned int)WireHitRange[iwire].second;
346 for(ihit = ifirsthit; ihit < ilasthit; ++ihit) {
347 bool ClusterAdded =
false;
350 if(ihit > fHits.size()-1) {
351 mf::LogError(
"CC")<<
"ClusterLoop bad ihit "<<ihit<<
" fHits size "<<fHits.size();
355 if(inClus[ihit] != 0)
continue;
357 if(fHits[ihit].PeakAmplitude() < fHitMinAmp)
continue;
359 if((iwire + 1) < span)
continue;
360 jwire = iwire - span + 1;
363 if(WireHitRange[jwire].first == -2)
continue;
364 if(WireHitRange[jwire].first == -1) {
366 unsigned int nmissed = 0;
367 while(WireHitRange[jwire].first == -1 && jwire > 1 && nmissed < fMaxWirSkip[pass]) {
371 if(prt)
mf::LogVerbatim(
"CC")<<
" new jwire "<<jwire<<
" dead? "<<WireHitRange[jwire].first;
372 if(WireHitRange[jwire].first < 0)
continue;
376 unsigned int useHit = 0;
377 bool doConstrain =
false;
378 VtxConstraint(iwire, ihit, jwire, useHit, doConstrain);
379 unsigned int jfirsthit = (
unsigned int)WireHitRange[jwire].first;
380 unsigned int jlasthit = (
unsigned int)WireHitRange[jwire].second;
382 <<
"ClusterLoop jwire "<<jwire<<
" bad firsthit "<<jfirsthit<<
" lasthit "<<jlasthit<<
" fhits size "<<fHits.size();
384 for(jhit = jfirsthit; jhit < jlasthit; ++jhit) {
386 <<
"ClusterLoop bad jhit "<<jhit<<
" firsthit "<<jfirsthit<<
" lasthit "<<jlasthit<<
" fhits size"<<fHits.size();
388 if(doConstrain && jhit != useHit)
continue;
391 if(inClus[jhit] != 0)
continue;
393 if(fHits[jhit].PeakAmplitude() < fHitMinAmp)
continue;
396 fcl2hits.push_back(ihit);
397 chifits.push_back(0.);
398 hitNear.push_back(0);
399 chgNear.push_back(0);
401 fcl2hits.push_back(jhit);
402 chifits.push_back(0.);
403 hitNear.push_back(0);
404 chgNear.push_back(0);
409 clparerr[1] = 0.2 * std::abs(clpar[1]);
410 clpar[2] = fHits[jhit].WireID().Wire;
414 for(kwire = jwire+1; kwire < iwire; ++kwire) {
416 if(CrawlVtxChk(kwire)) {
420 AddHit(kwire, HitOK, SigOK);
421 if(prt)
mf::LogVerbatim(
"CC")<<
" HitOK "<<HitOK<<
" clChisq "<<clChisq<<
" cut "<<fChiCut[pass]<<
" ClusterHitsOK "<<ClusterHitsOK(-1);
425 if(clChisq > 2)
break;
427 if(!ClusterHitsOK(-1))
continue;
432 prt = (fDebugPlane == (int)plane && (
int)iwire == fDebugWire && std::abs((
int)hit.
PeakTime() - fDebugHit) < 20);
437 clBeginSlp = clpar[1];
440 if(!fLACrawl[pass] && std::abs(clBeginSlp) > fLAClusSlopeCut)
continue;
443 if(CrawlVtxChk2())
continue;
444 clBeginSlpErr = clparerr[1];
449 for(
unsigned short kk = 0; kk < fcl2hits.size(); ++kk) {
450 fAveHitWidth += fHits[fcl2hits[kk]].EndTick() - fHits[fcl2hits[kk]].StartTick();
451 chg += fHits[fcl2hits[kk]].Integral();
453 fAveHitWidth /= (float)fcl2hits.size();
459 if(fLACrawl[pass] && fLAClusSlopeCut > 0) {
461 if(std::abs(clBeginSlp) > fLAClusSlopeCut) {
470 if(fcl2hits.size() >= fMinHits[pass]) {
473 clEndSlpErr = clparerr[1];
476 mf::LogError(
"CC")<<
"Failed to store cluster in plane "<<plane;
480 nHitsUsed += fcl2hits.size();
481 AllDone = (nHitsUsed == fHits.size());
487 if(ClusterAdded || AllDone)
break;
495 if(fDoMerge[pass]) ChkMerge();
497 if(fFindVertices[pass]) FindVertices();
504 if(fKillGarbageClusters > 0 && !tcl.empty()) KillGarbageClusters();
508 if(fChkClusterDS) ChkClusterDS();
510 if(fVtxClusterSplit) {
511 bool didSomething = VtxClusterSplit();
513 if(didSomething) VtxClusterSplit();
516 if(fFindStarVertices) FindStarVertices();
518 if(fDebugPlane == (
int)plane) {
525 CheckHitClusterAssociations();
530 void ClusterCrawlerAlg::KillGarbageClusters()
534 if(tcl.size() < 2)
return;
536 unsigned short icl, jcl;
539 std::vector<float> iHits, jHits;
543 float sepcut = 0, iFrac, jFrac;
545 unsigned short iLoIndx, jLoIndx, olapSize, iop, ii, jj;
546 unsigned short nclose;
549 std::vector<unsigned short> killMe;
551 for(icl = 0; icl < tcl.size() - 1; ++icl) {
552 if(tcl[icl].ID < 0)
continue;
553 if(tcl[icl].CTP != clCTP)
continue;
558 iHits.resize(tcl[icl].BeginWir - tcl[icl].EndWir + 1, 1000);
560 for(
auto iht : tcl[icl].tclhits) {
561 indx = fHits[iht].WireID().Wire - tcl[icl].EndWir;
562 if(indx > iHits.size() - 1) {
563 mf::LogWarning(
"CC")<<
"KillGarbageClusters: icl ID "<<tcl[icl].ID<<
" Bad indx "<<indx<<
" "<<iHits.size()<<
"\n";
566 iHits[indx] = fHits[iht].PeakTime();
567 iChg += fHits[iht].Integral();
568 if(first) sepcut += fHits[iht].RMS();
571 sepcut /= (float)tcl[icl].tclhits.size();
577 for(jcl = icl + 1; jcl < tcl.size(); ++jcl) {
578 if(tcl[jcl].ID < 0)
continue;
579 if(tcl[jcl].CTP != clCTP)
continue;
582 if(tcl[icl].BeginWir < tcl[jcl].EndWir)
continue;
583 if(tcl[icl].EndWir > tcl[jcl].BeginWir)
continue;
585 if(std::abs(tcl[icl].BeginAng - tcl[jcl].BeginAng) > fKillGarbageClusters)
continue;
587 if(tcl[icl].EndWir < tcl[jcl].EndWir) {
591 iLoIndx = tcl[jcl].EndWir - tcl[icl].EndWir;
593 if(tcl[icl].BeginWir < tcl[jcl].BeginWir) {
597 olapSize = tcl[icl].BeginWir - tcl[jcl].EndWir + 1;
602 olapSize = tcl[jcl].BeginWir - tcl[jcl].EndWir + 1;
610 jLoIndx = tcl[icl].EndWir - tcl[icl].EndWir;
611 if(tcl[icl].BeginWir < tcl[jcl].BeginWir) {
615 olapSize = tcl[icl].BeginWir - tcl[icl].EndWir + 1;
620 olapSize = tcl[jcl].BeginWir - tcl[icl].EndWir + 1;
625 jHits.resize(tcl[jcl].BeginWir - tcl[jcl].EndWir + 1, -1000);
627 for(
auto jht : tcl[jcl].tclhits) {
628 indx = fHits[jht].WireID().Wire - tcl[jcl].EndWir;
629 if(indx > jHits.size() - 1) {
630 mf::LogWarning(
"CC")<<
"KillGarbageClusters: jcl ID "<<tcl[jcl].ID<<
" Bad indx "<<indx<<
" "<<jHits.size()<<
"\n";
633 jHits[indx] = fHits[jht].PeakTime();
634 jChg += fHits[jht].Integral();
646 for(iop = 0; iop < olapSize; ++iop) {
648 if(ii > iHits.size() - 1)
continue;
650 if(jj > jHits.size() - 1)
continue;
651 if(std::abs(iHits[ii] - jHits[jj]) < sepcut) ++nclose;
653 iFrac = (float)nclose / (
float)iHits.size();
654 jFrac = (float)nclose / (
float)jHits.size();
655 if(iFrac < 0.5 && jFrac < 0.5)
continue;
656 doKill = (iFrac < jFrac && iChg > jChg);
662 if(doKill) killMe.push_back(jcl);
666 if(killMe.size() == 0)
return;
667 for(
auto icl : killMe) {
669 if(tcl[icl].ID < 0)
continue;
670 tcl[icl].ProcCode = 666;
671 MakeClusterObsolete(icl);
692 unsigned short icl, jcl;
694 bool chkprt = (fDebugWire == 666);
695 if(chkprt)
mf::LogVerbatim(
"CC")<<
"Inside MergeOverlap using clCTP "<<clCTP;
697 unsigned short minLen = 6;
698 unsigned short minOvrLap = 2;
701 float maxDTick = fTimeDelta[fTimeDelta.size() - 1];
703 unsigned int overlapSize, ii, indx, bWire, eWire;
704 unsigned int iht, jht;
705 float dang, prtime, dTick;
706 for(icl = 0; icl < tcl.size(); ++icl) {
707 if(tcl[icl].ID < 0)
continue;
708 if(tcl[icl].CTP != clCTP)
continue;
709 prt = chkprt && fDebugPlane == (int)clCTP;
710 if(tcl[icl].BeginVtx >= 0)
continue;
711 if(tcl[icl].tclhits.size() < minLen)
continue;
712 for(jcl = 0; jcl < tcl.size(); ++jcl) {
713 if(icl == jcl)
continue;
714 if(tcl[jcl].ID < 0)
continue;
715 if(tcl[jcl].CTP != clCTP)
continue;
716 if(tcl[jcl].EndVtx >= 0)
continue;
717 if(tcl[jcl].tclhits.size() < minLen)
continue;
719 if(tcl[icl].BeginWir < tcl[jcl].EndWir + minOvrLap)
continue;
721 if(tcl[icl].BeginWir > tcl[jcl].BeginWir - minOvrLap)
continue;
723 if(tcl[jcl].EndWir < tcl[icl].EndWir + minOvrLap)
continue;
724 dang = std::abs(tcl[icl].BeginAng - tcl[jcl].EndAng);
725 if(prt)
mf::LogVerbatim(
"CC")<<
"MergeOverlap icl ID "<<tcl[icl].ID<<
" jcl ID "<<tcl[jcl].ID<<
" dang "<<dang;
726 if(dang > 0.5)
continue;
727 overlapSize = tcl[icl].BeginWir - tcl[jcl].EndWir + 1;
728 eWire = tcl[jcl].EndWir;
729 bWire = tcl[icl].BeginWir;
730 if(prt)
mf::LogVerbatim(
"CC")<<
" Candidate icl ID "<<tcl[icl].ID<<
" "<<tcl[icl].EndWir<<
"-"<<tcl[icl].BeginWir<<
" jcl ID "<<tcl[jcl].ID<<
" "<<tcl[jcl].EndWir<<
"-"<<tcl[jcl].BeginWir<<
" overlapSize "<<overlapSize<<
" bWire "<<bWire<<
" eWire "<<eWire;
732 for(ii = 0; ii < tcl[icl].tclhits.size(); ++ii) {
733 iht = tcl[icl].tclhits[ii];
734 if(fHits[iht].WireID().Wire < eWire)
break;
737 dTick = std::abs(fHits[iht].PeakTime() - tcl[jcl].EndTim);
738 if(dTick > maxDTick)
continue;
739 if(prt)
mf::LogVerbatim(
"CC")<<
" dTick icl iht time "<<
PrintHit(iht)<<
" jcl EndTim "<<tcl[jcl].EndTim<<
" dTick "<<dTick;
740 for(ii = 0; ii < tcl[jcl].tclhits.size(); ++ii) {
741 jht = tcl[jcl].tclhits[tcl[jcl].tclhits.size() - ii - 1];
742 if(fHits[jht].WireID().Wire > bWire)
break;
744 dTick = std::abs(fHits[jht].PeakTime() - tcl[icl].BeginTim);
745 if(dTick > maxDTick)
continue;
746 if(prt)
mf::LogVerbatim(
"CC")<<
" dTick jcl jht time "<<
PrintHit(jht)<<
" icl BeginTim "<<tcl[icl].BeginTim<<
" dTick "<<dTick;
748 clpar[0] = fHits[iht].PeakTime();
749 clpar[2] = fHits[iht].WireID().Wire;
750 clpar[1] = (fHits[jht].PeakTime() - fHits[iht].PeakTime()) / ((
float)fHits[jht].WireID().Wire - clpar[2]);
752 std::vector<unsigned int> oWireHits(overlapSize, INT_MAX);
753 std::vector<float> delta(overlapSize, maxDTick);
754 for(ii = 0; ii < tcl[icl].tclhits.size(); ++ii) {
755 iht = tcl[icl].tclhits[ii];
756 if(fHits[iht].WireID().Wire < eWire)
break;
757 prtime = clpar[0] + clpar[1] * ((float)fHits[iht].WireID().Wire - clpar[2]);
758 dTick = std::abs(fHits[iht].PeakTime() - prtime);
759 indx = fHits[iht].WireID().Wire - eWire;
760 if(dTick > delta[indx])
continue;
762 oWireHits[indx] = iht;
765 for(ii = 0; ii < tcl[jcl].tclhits.size(); ++ii) {
766 jht = tcl[jcl].tclhits[tcl[jcl].tclhits.size() - ii - 1];
767 if(fHits[jht].WireID().Wire > bWire)
break;
768 prtime = clpar[0] + clpar[1] * ((float)fHits[jht].WireID().Wire - clpar[2]);
769 dTick = std::abs(fHits[jht].PeakTime() - prtime);
770 indx = fHits[jht].WireID().Wire - eWire;
771 if(dTick > delta[indx])
continue;
773 oWireHits[indx] = jht;
777 for(ii = 0; ii < oWireHits.size(); ++ii) {
778 if(oWireHits[ii] == INT_MAX)
continue;
780 fcl2hits.push_back(iht);
783 if(fcl2hits.size() < 0.5 * overlapSize)
continue;
784 if(fcl2hits.size() < 3)
continue;
785 std::sort(fcl2hits.begin(), fcl2hits.end(),
SortByLowHit);
787 if(prt)
mf::LogVerbatim(
"CC")<<
" Overlap size "<<overlapSize<<
" fit chisq "<<clChisq<<
" nhits "<<fcl2hits.size();
788 if(clChisq > 20)
continue;
790 std::vector<unsigned int> oHits = fcl2hits;
794 unsigned short jclNewSize;
795 for(jclNewSize = 0; jclNewSize < fcl2hits.size(); ++jclNewSize) {
796 iht = fcl2hits[jclNewSize];
797 if(fHits[iht].WireID().Wire <= bWire)
break;
800 mf::LogVerbatim(
"CC")<<
"jcl old size "<<fcl2hits.size()<<
" newSize "<<jclNewSize;
801 iht = fcl2hits[fcl2hits.size()-1];
802 unsigned int iiht = fcl2hits[jclNewSize-1];
803 mf::LogVerbatim(
"CC")<<
"jcl old last wire "<<fHits[iht].WireID().Wire<<
" After resize last wire "<<fHits[iiht].WireID().Wire;
805 fcl2hits.resize(jclNewSize);
807 fcl2hits.insert(fcl2hits.end(), oHits.begin(), oHits.end());
809 for(ii = 0; ii < tcl[icl].tclhits.size(); ++ii) {
810 iht = tcl[icl].tclhits[ii];
811 if((
unsigned int)fHits[iht].WireID().Wire >= eWire)
continue;
812 fcl2hits.insert(fcl2hits.end(),tcl[icl].tclhits.begin()+ii, tcl[icl].tclhits.end());
815 clBeginSlp = tcl[jcl].BeginSlp;
816 clBeginSlpErr = tcl[jcl].BeginSlpErr;
817 clBeginAng = tcl[jcl].BeginAng;
818 clBeginWir = tcl[jcl].BeginWir;
819 clBeginTim = tcl[jcl].BeginTim;
820 clBeginChg = tcl[jcl].BeginChg;
821 clBeginChgNear = tcl[jcl].BeginChgNear;
823 clEndSlp = tcl[icl].EndSlp;
824 clEndSlpErr = tcl[icl].EndSlpErr;
825 clEndAng = tcl[icl].EndAng;
826 clEndWir = tcl[icl].EndWir;
827 clEndTim = tcl[icl].EndTim;
828 clEndChg = tcl[icl].EndChg;
829 clEndChgNear = tcl[icl].EndChgNear;
830 clStopCode = tcl[icl].StopCode;
831 clProcCode = tcl[icl].ProcCode + 500;
832 MakeClusterObsolete(icl);
833 MakeClusterObsolete(jcl);
836 RestoreObsoleteCluster(icl);
837 RestoreObsoleteCluster(jcl);
838 CheckHitClusterAssociations();
841 CheckHitClusterAssociations();
842 tcl[tcl.size() - 1].BeginVtx = tcl[jcl].BeginVtx;
843 tcl[tcl.size() - 1].EndVtx = tcl[icl].BeginVtx;
845 if(prt)
mf::LogVerbatim(
"CC")<<
"MergeOverlap new long cluster ID "<<tcl[tcl.size()-1].ID<<
" in clCTP "<<clCTP;
847 if(tcl[icl].ID < 0)
break;
854 void ClusterCrawlerAlg::MakeClusterObsolete(
unsigned short icl) {
855 short& ID = tcl[icl].ID;
857 mf::LogError(
"CC")<<
"Trying to make already-obsolete cluster obsolete ID = "<<ID;
863 for(
unsigned int iht = 0; iht < tcl[icl].tclhits.size(); ++iht) inClus[tcl[icl].tclhits[iht]] = 0;
868 void ClusterCrawlerAlg::RestoreObsoleteCluster(
unsigned short icl) {
869 short& ID = tcl[icl].ID;
871 mf::LogError(
"CC")<<
"Trying to restore non-obsolete cluster ID = "<<ID;
876 for(
unsigned short iht = 0; iht < tcl[icl].tclhits.size(); ++iht) inClus[tcl[icl].tclhits[iht]] = ID;
882 void ClusterCrawlerAlg::FclTrimUS(
unsigned short nTrim)
886 if(nTrim == 0)
return;
888 if(nTrim >= fcl2hits.size()) nTrim = fcl2hits.size();
891 for(
unsigned short ii = 0; ii < nTrim; ++ii) {
1006 void ClusterCrawlerAlg::CheckHitClusterAssociations()
1010 if(fHits.size() != inClus.size()) {
1011 mf::LogError(
"CC")<<
"CHCA: Sizes wrong "<<fHits.size()<<
" "<<inClus.size();
1015 unsigned int iht, nErr = 0;
1019 for(
unsigned short icl = 0; icl < tcl.size(); ++icl) {
1020 if(tcl[icl].ID < 0)
continue;
1022 for(
unsigned short ii = 0; ii < tcl[icl].tclhits.size(); ++ii) {
1023 iht = tcl[icl].tclhits[ii];
1024 if(iht > fHits.size() - 1) {
1025 mf::LogError(
"CC")<<
"CHCA: Bad tclhits index "<<iht<<
" fHits size "<<fHits.size();
1028 if(inClus[iht] != clID) {
1029 mf::LogError(
"CC")<<
"CHCA: Bad cluster -> hit association. clID "<<clID<<
" hit inClus "<<inClus[iht]<<
" ProcCode "<<tcl[icl].ProcCode<<
" CTP "<<tcl[icl].CTP;
1031 if(nErr > 10)
return;
1038 for(iht = 0; iht < fHits.size(); ++iht) {
1039 if(inClus[iht] <= 0)
continue;
1040 icl = inClus[iht] - 1;
1042 if(tcl[icl].ID < 0) {
1043 mf::LogError(
"CC")<<
"CHCA: Hit associated with an obsolete cluster. hit W:T "<<fHits[iht].WireID().Wire<<
":"<<(int)fHits[iht].PeakTime()
1044 <<
" tcl[icl].ID "<<tcl[icl].ID;
1046 if(nErr > 10)
return;
1048 if (std::find(tcl[icl].tclhits.begin(), tcl[icl].tclhits.end(), iht) == tcl[icl].tclhits.end()) {
1049 mf::LogError(
"CC")<<
"CHCA: Bad hit -> cluster association. hit index "<<iht
1050 <<
" W:T "<<fHits[iht].WireID().Wire<<
":"<<(int)fHits[iht].PeakTime()<<
" inClus "<<inClus[iht];
1052 if(nErr > 10)
return;
1059 void ClusterCrawlerAlg::RemoveObsoleteHits() {
1061 unsigned int destHit = 0;
1063 if(fHits.size() != inClus.size()) {
1064 mf::LogError(
"CC")<<
"RemoveObsoleteHits size mis-match "<<fHits.size()<<
" "<<inClus.size();
1069 for(
unsigned int srcHit = 0; srcHit < fHits.size(); ++srcHit) {
1070 if(inClus[srcHit] < 0)
continue;
1071 if(srcHit != destHit) {
1072 fHits[destHit] = std::move(fHits[srcHit]);
1073 inClus[destHit] = inClus[srcHit];
1074 if(inClus[destHit] > 0) {
1076 icl = inClus[destHit] - 1;
1077 auto&
hits = tcl[icl].tclhits;
1078 auto iHitIndex = std::find(
hits.begin(),
hits.end(), srcHit);
1079 if (iHitIndex ==
hits.end()) {
1080 mf::LogError(
"CC")<<
"RemoveObsoleteHits: Hit #" << srcHit <<
" not found in cluster ID "<< inClus[destHit];
1082 *iHitIndex = destHit;
1089 fHits.resize(destHit);
1090 inClus.resize(destHit);
1095 void ClusterCrawlerAlg::ChkClusterDS() {
1101 prt = (fDebugPlane == 3);
1104 float dThCut = fKinkAngCut[fNumPass - 1];
1106 if(prt)
mf::LogVerbatim(
"CC")<<
"ChkClusterDS clCTP "<<clCTP<<
" kink angle cut "<<dThCut;
1108 const unsigned short tclsize = tcl.size();
1109 bool didMerge, skipit;
1110 unsigned short icl, ii, nhm, iv;
1114 for(icl = 0; icl < tclsize; ++icl) {
1115 if(tcl[icl].ID < 0)
continue;
1116 if(tcl[icl].CTP != clCTP)
continue;
1118 if(tcl[icl].BeginVtx >= 0)
continue;
1121 for(
unsigned short iv = 0; iv < vtx.size(); ++iv) {
1122 if(vtx[iv].CTP != clCTP)
continue;
1123 if(std::abs(vtx[iv].Wire - tcl[icl].BeginWir) > 4)
continue;
1124 if(std::abs(vtx[iv].Time - tcl[icl].BeginTim) > 20)
continue;
1128 if(skipit)
continue;
1131 for(ii = 0; ii < 3; ++ii) {
1133 if(fHits[iht].Multiplicity() > 1) {
1134 MergeHits(iht, didMerge);
1140 FitClusterMid(icl, 0, 3);
1141 tcl[icl].BeginTim = clpar[0];
1142 tcl[icl].BeginSlp = clpar[1];
1143 tcl[icl].BeginAng = atan(fScaleF * clpar[1]);
1144 tcl[icl].BeginSlpErr = clparerr[1];
1145 tcl[icl].BeginChg = fAveChg;
1146 tcl[icl].ProcCode += 5000;
1147 if(prt)
mf::LogVerbatim(
"CC")<<
"ChkClusterDS: Merge hits on cluster "<<tcl[icl].ID;
1151 float thhits, prevth, hitrms, rmsrat;
1153 std::vector<unsigned int> dshits;
1154 for(icl = 0; icl < tclsize; ++icl) {
1155 if(tcl[icl].ID < 0)
continue;
1156 if(tcl[icl].CTP != clCTP)
continue;
1158 if(tcl[icl].BeginVtx >= 0)
continue;
1161 for(iv = 0; iv < vtx.size(); ++iv) {
1162 if(vtx[iv].CTP != clCTP)
continue;
1163 if(std::abs(vtx[iv].Wire - tcl[icl].BeginWir) > 4)
continue;
1164 if(std::abs(vtx[iv].Time - tcl[icl].BeginTim) > 20)
continue;
1168 if(skipit)
continue;
1172 unsigned int ih0 = tcl[icl].tclhits[1];
1173 unsigned int ih1 = tcl[icl].tclhits[0];
1174 const float slp = (fHits[ih1].PeakTime() - fHits[ih0].PeakTime()) /
1175 (fHits[ih1].WireID().Wire - fHits[ih0].WireID().Wire);
1176 prevth = std::atan(fScaleF * slp);
1179 unsigned int wire = fHits[ih0].WireID().Wire;
1180 hitrms = fHits[ih0].RMS();
1181 float time0 = fHits[ih0].PeakTime();
1186 for(ii = 0; ii < 4; ++ii) {
1188 if(wire > fLastWire)
break;
1189 prtime = time0 + slp;
1191 <<tcl[icl].ID<<
" to W:T "<<wire<<
" hitrms "<<hitrms<<
" prevth "<<prevth<<
" prtime "<<(int)prtime;
1193 if(WireHitRange[wire].first == -2)
break;
1194 unsigned int firsthit = WireHitRange[wire].first;
1195 unsigned int lasthit = WireHitRange[wire].second;
1196 bool hitAdded =
false;
1197 for(ih1 = firsthit; ih1 < lasthit; ++ih1) {
1198 if(inClus[ih1] != 0)
continue;
1199 if(prtime < fHits[ih1].PeakTimeMinusRMS(5))
continue;
1200 if(prtime > fHits[ih1].PeakTimePlusRMS(5))
continue;
1201 const float slp = (fHits[ih1].PeakTime() - fHits[ih0].PeakTime()) /
1202 (fHits[ih1].WireID().Wire - fHits[ih0].WireID().Wire);
1203 thhits = std::atan(fScaleF * slp);
1204 if(prt)
mf::LogVerbatim(
"CC")<<
" theta "<<thhits<<
" prevth "<<prevth<<
" cut "<<dThCut;
1205 if(std::abs(thhits - prevth) > dThCut)
continue;
1208 if(std::abs(slp) < fLAClusSlopeCut) {
1209 rmsrat = fHits[ih1].RMS() / hitrms;
1210 ratOK = rmsrat > 0.3 && rmsrat < 3;
1214 MergeHits(ih1, didMerge);
1221 dshits.push_back(ih1);
1226 <<
":"<<(int)fHits[ih1].PeakTime()<<
" rmsrat "<<rmsrat;
1231 if(!hitAdded)
break;
1234 if(dshits.size() > 0) {
1240 if(dshits.size() > 1) std::sort(dshits.begin(), dshits.end(),
SortByLowHit);
1244 for(ii = 0; ii < tcl[icl].tclhits.size(); ++ii) {
1246 iht = tcl[icl].tclhits[ii];
1248 fcl2hits.push_back(iht);
1251 pass = fNumPass - 1;
1253 clBeginChg = fAveChg;
1255 MakeClusterObsolete(icl);
1258 mf::LogError(
"CC")<<
"ChkClusterDS TmpStore failed while extending cluster ID "<<tcl[icl].ID;
1261 const size_t newcl = tcl.size() -1;
1263 tcl[newcl].BeginVtx = tcl[icl].BeginVtx;
1264 tcl[newcl].EndVtx = tcl[icl].EndVtx;
1271 bool ClusterCrawlerAlg::CrawlVtxChk2()
1277 if(vtx.size() == 0)
return false;
1278 if(fcl2hits.size() == 0)
return false;
1280 unsigned int iht = fcl2hits.size() - 1;
1282 float wire0 = (0.5 + fHits[fcl2hits[iht]].WireID().Wire);
1284 float thclus = std::atan(fScaleF * clpar[1]);
1286 for(
unsigned short iv = 0; iv < vtx.size(); ++iv) {
1287 if(vtx[iv].CTP != clCTP)
continue;
1288 if(wire0 < vtx[iv].Wire)
continue;
1289 if(wire0 > vtx[iv].Wire + 10)
continue;
1290 dt = clpar[0] + (vtx[iv].Wire - wire0) * clpar[1] - vtx[iv].Time;
1291 if(std::abs(dt) > 10)
continue;
1294 for(icl = 0; icl < tcl.size(); ++icl) {
1295 if(tcl[icl].CTP != clCTP)
continue;
1296 if(tcl[icl].EndVtx != iv)
continue;
1297 if(std::abs(tcl[icl].EndAng - thclus) < fKinkAngCut[pass])
return true;
1306 bool ClusterCrawlerAlg::CrawlVtxChk(
unsigned int kwire)
1310 if(vtx.size() == 0)
return false;
1311 unsigned int iht = fcl2hits.size() - 1;
1312 float wire0 = (0.5 + fHits[fcl2hits[iht]].WireID().Wire);
1313 float prtime = clpar[0] + (kwire - wire0) * clpar[1];
1314 for(
unsigned short iv = 0; iv < vtx.size(); ++iv) {
1315 if(vtx[iv].CTP != clCTP)
continue;
1316 if((
unsigned int)(0.5 + vtx[iv].Wire) != kwire)
continue;
1317 if(std::abs(prtime - vtx[iv].Time) < 10)
return true;
1322 void ClusterCrawlerAlg::VtxConstraint(
unsigned int iwire,
unsigned int ihit,
unsigned int jwire,
unsigned int& useHit,
bool& doConstrain)
1327 doConstrain =
false;
1328 if(vtx.size() == 0)
return;
1330 if(pass == 0)
return;
1332 if( !fFindVertices[pass - 1] )
return;
1334 if(jwire > WireHitRange.size() - 1) {
1335 mf::LogError(
"CC")<<
"VtxConstraint fed bad jwire "<<jwire<<
" WireHitRange size "<<WireHitRange.size();
1339 unsigned int jfirsthit = WireHitRange[jwire].first;
1340 unsigned int jlasthit = WireHitRange[jwire].second;
1341 for(
unsigned short iv = 0; iv < vtx.size(); ++iv) {
1342 if(vtx[iv].CTP != clCTP)
continue;
1344 if(vtx[iv].Wire > jwire)
continue;
1346 if(vtx[iv].Wire < jwire - 10)
continue;
1349 clpar[1] = (vtx[iv].Time - hit.
PeakTime()) / (vtx[iv].Wire - iwire);
1351 float prtime = clpar[0] + clpar[1] * (jwire - iwire);
1352 for(
unsigned int jhit = jfirsthit; jhit < jlasthit; ++jhit) {
1353 if(inClus[jhit] != 0)
continue;
1354 const float tdiff = std::abs(fHits[jhit].TimeDistanceAsRMS(prtime));
1366 void ClusterCrawlerAlg::RefineVertexClusters(
unsigned short iv)
1371 std::vector<unsigned short> begClusters;
1372 std::vector<short> begdW;
1373 std::vector<unsigned short> endClusters;
1374 std::vector<short> enddW;
1376 unsigned int vWire = (
unsigned int)(vtx[iv].Wire + 0.5);
1377 unsigned int vWireErr = (
unsigned int)(2 * vtx[iv].WireErr);
1378 unsigned int vWireLo = vWire - vWireErr;
1379 unsigned int vWireHi = vWire + vWireErr;
1381 unsigned short icl, ii;
1383 bool needsWork =
false;
1386 for(icl = 0; icl < tcl.size(); ++icl) {
1387 if(tcl[icl].ID < 0)
continue;
1388 if(tcl[icl].CTP != vtx[iv].CTP)
continue;
1389 if(tcl[icl].BeginVtx == iv) {
1390 dW = vWire - tcl[icl].BeginWir;
1391 if(dW > maxdW) maxdW = dW;
1392 if(dW < mindW) mindW = dW;
1393 if(std::abs(dW) > 1) needsWork =
true;
1395 begClusters.push_back(icl);
1396 begdW.push_back(dW);
1398 if(tcl[icl].EndVtx == iv) {
1399 dW = vWire - tcl[icl].EndWir;
1400 if(dW > maxdW) maxdW = dW;
1401 if(dW < mindW) mindW = dW;
1402 if(std::abs(dW) > 1) needsWork =
true;
1403 endClusters.push_back(icl);
1404 enddW.push_back(dW);
1408 if(vtxprt)
mf::LogVerbatim(
"CC")<<
"RefineVertexClusters: vertex "<<iv<<
" needsWork "<<needsWork
1409 <<
" mindW "<<mindW<<
" maxdW "<<maxdW<<
" vWireErr "<<vWireErr;
1411 if(!needsWork)
return;
1415 if( ((
unsigned int)std::abs(mindW) < vWireErr) && ((
unsigned int)std::abs(maxdW) < vWireErr) && std::abs(maxdW - mindW) < 2) {
1417 vtx[iv].Wire -= (float)(maxdW + mindW)/2;
1420 vtx[iv].Fixed =
true;
1427 unsigned short newSize;
1428 for(ii = 0; ii < endClusters.size(); ++ii) {
1429 icl = endClusters[ii];
1430 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" endCluster "<<tcl[icl].ID<<
" dW "<<enddW[ii]<<
" vWire "<<vWire;
1431 if(tcl[icl].EndWir < vWire) {
1434 newSize = fcl2hits.size();
1435 for(
auto hiter = fcl2hits.rbegin(); hiter < fcl2hits.rend(); ++hiter) {
1436 if(fHits[*hiter].WireID().Wire > vWire)
break;
1440 for(
auto hiter = fcl2hits.begin(); hiter < fcl2hits.end(); ++hiter) inClus[*hiter] = 0;
1442 fcl2hits.resize(newSize);
1443 MakeClusterObsolete(icl);
1449 tcl[tcl.size()-1].EndVtx = iv;
1451 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" modified cluster "<<tcl[icl].ID<<
" -> "<<tcl[tcl.size()-1].ID;
1453 else if(tcl[icl].EndWir > vWire) {
1454 mf::LogVerbatim(
"CC")<<
"RefineVertexClusters: Write some EndVtx code";
1458 if(begClusters.size() > 0)
mf::LogVerbatim(
"CC")<<
"RefineVertexClusters: Write some BeginVtx code";
1460 if(mindW < 0 && maxdW > 0) {
1465 unsigned short clsBigChg = 0;
1470 for(ii = 0; ii < begClusters.size(); ++ii) {
1471 icl = begClusters[ii];
1472 for(iht = 0; iht < tcl[icl].tclhits.size(); ++iht) {
1473 ihit = tcl[icl].tclhits[iht];
1474 if(fHits[ihit].Integral() > bigChg) {
1475 bigChg = fHits[ihit].Integral();
1479 if(fHits[ihit].WireID().Wire < vWireLo)
break;
1483 for(ii = 0; ii < endClusters.size(); ++ii) {
1484 icl = endClusters[ii];
1485 for(iht = 0; iht < tcl[icl].tclhits.size(); ++iht) {
1486 ihit = tcl[icl].tclhits[tcl[icl].tclhits.size() - 1 - iht];
1487 if(fHits[ihit].Integral() > bigChg) {
1488 bigChg = fHits[ihit].Integral();
1492 if(fHits[ihit].WireID().Wire > vWireHi)
break;
1497 <<fHits[vtxHit].WireID().Wire<<
":"<<(int)fHits[vtxHit].PeakTime()<<
" on cluster "<<tcl[clsBigChg].ID;
1498 vtx[iv].Wire = fHits[vtxHit].WireID().Wire;
1499 vtx[iv].Time = fHits[vtxHit].PeakTime();
1500 vtx[iv].Fixed =
true;
1509 bool ClusterCrawlerAlg::VtxClusterSplit()
1514 vtxprt = (fDebugPlane >= 0 && fDebugWire == 5555);
1518 if(vtx.size() == 0)
return false;
1519 unsigned short tclsize = tcl.size();
1520 if(tclsize < 2)
return false;
1524 bool didSomething =
false;
1526 for(
unsigned short icl = 0; icl < tclsize; ++icl) {
1527 if(tcl[icl].ID < 0)
continue;
1528 if(tcl[icl].CTP != clCTP)
continue;
1530 if(tcl[icl].tclhits.size() < 5)
continue;
1533 for(
unsigned short ivx = 0; ivx < vtx.size(); ++ivx) {
1534 if(vtx[ivx].CTP != clCTP)
continue;
1536 if(vtx[ivx].NClusters == 0)
continue;
1538 if(tcl[icl].BeginVtx == ivx)
continue;
1539 if(tcl[icl].EndVtx == ivx)
continue;
1548 if(vtx[ivx].Wire < tcl[icl].EndWir)
continue;
1549 if(vtx[ivx].Wire > tcl[icl].BeginWir)
continue;
1551 float hiTime = tcl[icl].BeginTim;
1552 if(tcl[icl].EndTim > hiTime) hiTime = tcl[icl].EndTim;
1553 if(vtx[ivx].Time > hiTime + 5)
continue;
1554 float loTime = tcl[icl].BeginTim;
1555 if(tcl[icl].EndTim < loTime) loTime = tcl[icl].EndTim;
1556 if(vtx[ivx].Time < loTime - 5)
continue;
1559 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" Chk cluster ID "<<tcl[icl].ID<<
" with vertex "<<ivx;
1563 unsigned short nSplit = 0;
1564 unsigned short nLop = 0;
1566 for(
unsigned short ii = tcl[icl].tclhits.size()-1; ii > 0 ; --ii) {
1567 iht = tcl[icl].tclhits[ii];
1569 if(fHits[iht].WireID().Wire >= vtx[ivx].Wire) {
1571 if(vtxprt)
mf::LogVerbatim(
"CC")<<
"Split cluster "<<tcl[icl].ID<<
" at wire "<<fHits[iht].WireID().Wire
1572 <<
" nSplit "<<nSplit;
1578 if(ihvx < 0)
continue;
1581 if(fabs(fHits[ihvx].PeakTime() - vtx[ivx].Time) > 10)
continue;
1586 if(nSplit > tcl[icl].tclhits.size() / 2) {
1587 iclAng = tcl[icl].EndAng;
1589 iclAng = tcl[icl].BeginAng;
1594 for(
unsigned short jcl = 0; jcl < tclsize; ++jcl) {
1595 if(tcl[jcl].ID < 0)
continue;
1596 if(tcl[jcl].CTP != clCTP)
continue;
1597 if(tcl[jcl].BeginVtx == ivx) {
1598 if(fabs(tcl[jcl].BeginAng - iclAng) > 0.4) {
1604 if(tcl[jcl].EndVtx == ivx) {
1605 if(fabs(tcl[jcl].EndAng - iclAng) > 0.4) {
1619 for(
unsigned short ii = 0; ii < nLop; ++ii) {
1620 unsigned int iht = fcl2hits[fcl2hits.size()-1];
1622 fcl2hits.pop_back();
1627 MakeClusterObsolete(icl);
1629 if(!TmpStore())
continue;
1630 unsigned short newcl = tcl.size() - 1;
1631 tcl[newcl].BeginVtx = tcl[icl].BeginVtx;
1632 tcl[newcl].EndVtx = ivx;
1637 if(SplitCluster(icl, nSplit, ivx)) {
1638 tcl[tcl.size()-1].ProcCode += 1000;
1639 tcl[tcl.size()-2].ProcCode += 1000;
1643 didSomething =
true;
1649 return didSomething;
1654 void ClusterCrawlerAlg::MergeHits(
const unsigned int theHit,
bool& didMerge) {
1667 if(theHit > fHits.size() - 1) {
1675 if(fHits[theHit].GoodnessOfFit() == 6666) {
1676 if(prt)
mf::LogVerbatim(
"CC")<<
"MergeHits Trying to merge already merged hit " 1678 <<
" Multiplicity "<<hit.
Multiplicity()<<
" theHit "<<theHit;
1683 if(!mergeAvailable[theHit]) {
1694 std::pair<size_t, size_t> MultipletRange = FindHitMultiplet(theHit);
1697 if (MultipletRange.second <= MultipletRange.first)
return;
1700 unsigned short nAvailable = 0;
1701 unsigned short nInClus = 0;
1702 for(
size_t jht = MultipletRange.first; jht < MultipletRange.second; ++jht) {
1703 if(jht == theHit)
continue;
1704 if(fHits[jht].GoodnessOfFit() == 6666)
continue;
1705 if(inClus[jht] != 0) {
1711 if(nAvailable == 0)
return;
1713 if(nInClus > 0)
return;
1719 short loTime = 9999;
1721 unsigned short nGaus = 1;
1724 unsigned short nclose = 0;
1726 for(
size_t jht = MultipletRange.first; jht < MultipletRange.second; ++jht) {
1727 if(inClus[jht] < 0)
continue;
1764 if(inClus[jht] != 0)
continue;
1766 if(arg < loTime) loTime = arg;
1768 if(arg > hiTime) hiTime = arg;
1769 if(jht != theHit) ++nGaus;
1771 if(jht != theHit && hitSep < 3) ++nclose;
1774 if(nGaus < 2)
return;
1777 const short int NewMultiplicity = hit.
Multiplicity() + 1 - nGaus;
1779 if(loTime < 0) loTime = 0;
1782 std::vector<double> signal(hiTime - loTime, 0.);
1785 for(
size_t jht = MultipletRange.first; jht < MultipletRange.second; ++jht) {
1789 if(inClus[jht] != 0)
continue;
1795 for(
unsigned short time = loTime; time < hiTime; ++time) {
1796 unsigned short indx = time - loTime;
1797 double arg = (other_hit.
PeakTime() - (double)time) / other_hit.
RMS();
1798 signal[indx] += other_hit.
PeakAmplitude() * exp(-0.5 * arg * arg);
1803 double sigsumt = 0.;
1804 for(
unsigned short time = loTime; time < hiTime; ++time) {
1805 sigsum += signal[time - loTime];
1806 sigsumt += signal[time - loTime] * time;
1812 double aveTime = sigsumt / sigsum;
1815 for(
unsigned short time = loTime; time < hiTime; ++time) {
1816 double dtime = time - aveTime;
1817 sigsumt += signal[time - loTime] * dtime * dtime;
1819 const float RMS = std::sqrt(sigsumt / sigsum);
1821 const float amplitude = chgsum * chgNorm/ (2.507 * RMS);
1852 FixMultipletLocalIndices(MultipletRange.first, MultipletRange.second);
1858 void ClusterCrawlerAlg::FixMultipletLocalIndices
1871 if (multiplicity < 0) {
1873 for (
size_t iHit = begin; iHit <
end; ++iHit) {
1874 if(inClus[iHit] < 0)
continue;
1881 short int local_index = 0;
1882 for (
size_t iHit = begin; iHit <
end; ++iHit) {
1883 if(inClus[iHit] < 0)
continue;
1916 void ClusterCrawlerAlg::FindStarVertices()
1923 if(tcl.size() < 2)
return;
1928 vtxprt = (fDebugPlane == (int)plane && fDebugHit < 0);
1934 unsigned short vtxSizeIn = vtx.size();
1938 float dsl = 0, dth = 0;
1939 float es1 = 0, es2 = 0;
1940 float eth1 = 0, eth2 = 0;
1941 float bt1 = 0, bt2 = 0;
1942 float et1 = 0, et2 = 0;
1943 float bw1 = 0, bw2 = 0;
1944 float ew1 = 0, ew2 = 0;
1945 float lotime = 0, hitime = 0, nwirecut = 0;
1946 unsigned short tclsize = tcl.size();
1947 for(
unsigned short it1 = 0; it1 < tclsize - 1; ++it1) {
1949 if(tcl[it1].ID < 0)
continue;
1950 if(tcl[it1].CTP != clCTP)
continue;
1952 if(tcl[it1].tclhits.size() > 100) {
1953 dth = tcl[it1].BeginAng - tcl[it1].EndAng;
1954 if(std::abs(dth) < 0.1)
continue;
1956 es1 = tcl[it1].EndSlp;
1957 eth1 = tcl[it1].EndAng;
1958 ew1 = tcl[it1].EndWir;
1959 et1 = tcl[it1].EndTim;
1960 bw1 = tcl[it1].BeginWir;
1961 bt1 = tcl[it1].BeginTim;
1962 for(
unsigned short it2 = it1 + 1; it2 < tclsize; ++it2) {
1963 if(tcl[it2].ID < 0)
continue;
1964 if(tcl[it2].CTP != clCTP)
continue;
1966 if(tcl[it2].tclhits.size() > 100) {
1967 dth = tcl[it2].BeginAng - tcl[it2].EndAng;
1968 if(std::abs(dth) < 0.05)
continue;
1970 es2 = tcl[it2].EndSlp;
1971 eth2 = tcl[it2].EndAng;
1972 ew2 = tcl[it2].EndWir;
1973 et2 = tcl[it2].EndTim;
1974 bw2 = tcl[it2].BeginWir;
1975 bt2 = tcl[it2].BeginTim;
1977 dth = std::abs(eth1 - eth2);
1978 if(dth < 0.3)
continue;
1980 fvw = (et1 - ew1 * es1 - et2 + ew2 * es2) / dsl;
1982 if(fvw < ew1 || fvw > bw1)
continue;
1983 if(fvw < ew2 || fvw > bw2)
continue;
1984 if(vtxprt)
mf::LogVerbatim(
"CC")<<
"Chk clusters "<<tcl[it1].ID<<
" "<<tcl[it2].ID<<
" topo5 vtx wire "<<fvw;
1987 if(tcl[it1].tclhits.size() > tcl[it2].tclhits.size()) {
1988 if(tcl[it1].tclhits.size() > 20) {
1989 nwirecut = 0.5 * tcl[it1].tclhits.size();
1990 if((fvw - ew1) > nwirecut)
continue;
1993 if(tcl[it2].tclhits.size() > 20) {
1994 nwirecut = 0.5 * tcl[it2].tclhits.size();
1995 if((fvw - ew2) > nwirecut)
continue;
1998 fvt = et1 + (fvw - ew1) * es1;
2001 if(et1 < lotime) lotime = et1;
2002 if(bt1 < lotime) lotime = bt1;
2003 if(et2 < lotime) lotime = et2;
2004 if(bt2 < lotime) lotime = bt2;
2006 if(et1 > hitime) hitime = et1;
2007 if(bt1 > hitime) hitime = bt1;
2008 if(et2 > hitime) hitime = et2;
2009 if(bt2 > hitime) hitime = bt2;
2010 if(fvt < lotime || fvt > hitime)
continue;
2011 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" vertex time "<<fvt<<
" lotime "<<lotime<<
" hitime "<<hitime;
2012 unsigned int vw = (0.5 + fvw);
2014 unsigned int pos1 = 0;
2015 for(
unsigned short ii = 0; ii < tcl[it1].tclhits.size(); ++ii) {
2016 if(fHits[tcl[it1].tclhits[ii]].WireID().Wire <= vw) {
2017 if(std::abs(
int(fHits[tcl[it1].tclhits[ii]].PeakTime() - fvt)) < 10) pos1 = ii;
2022 if(pos1 == 0)
continue;
2023 unsigned short pos2 = 0;
2024 for(
unsigned short ii = 0; ii < tcl[it2].tclhits.size(); ++ii) {
2025 if(fHits[tcl[it2].tclhits[ii]].WireID().Wire <= vw) {
2026 if(std::abs(
int(fHits[tcl[it2].tclhits[ii]].PeakTime() - fvt)) < 10) pos2 = ii;
2031 if(pos2 == 0)
continue;
2033 for(
unsigned short iv = 0; iv < vtx.size(); ++iv) {
2034 if(std::abs(fvw - vtx[iv].Wire) < 2 &&
2035 std::abs(fvt - vtx[iv].Time) < 10)
continue;
2045 newvx.
Fixed =
false;
2046 vtx.push_back(newvx);
2047 unsigned short ivx = vtx.size() - 1;
2048 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" new vertex "<<ivx<<
" cluster "<<tcl[it1].ID<<
" split pos "<<pos1;
2049 if(!SplitCluster(it1, pos1, ivx))
continue;
2050 tcl[tcl.size()-1].ProcCode += 1000;
2051 tcl[tcl.size()-2].ProcCode += 1000;
2052 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" new vertex "<<ivx<<
" cluster "<<tcl[it2].ID<<
" split pos "<<pos2;
2053 if(!SplitCluster(it2, pos2, ivx))
continue;
2054 tcl[tcl.size()-1].ProcCode += 1000;
2055 tcl[tcl.size()-2].ProcCode += 1000;
2061 if(vtx.size() > vtxSizeIn) {
2065 VertexCluster(vtx.size() - 1);
2071 for(
unsigned short iv = 0; iv < vtx.size(); ++iv) {
2072 if(vtx[iv].CTP != clCTP)
continue;
2074 <<
"vtx "<<iv<<
" wire "<<vtx[iv].Wire<<
" time "<<(int)vtx[iv].Time
2075 <<
" NClusters "<<vtx[iv].NClusters<<
" topo "<<vtx[iv].Topo;
2083 void ClusterCrawlerAlg::VertexCluster(
unsigned short iv)
2086 if(vtx[iv].NClusters == 0)
return;
2088 short dwb, dwe, dtb, dte;
2093 for(
unsigned short icl = 0; icl < tcl.size(); ++icl) {
2094 if(tcl[icl].ID < 0)
continue;
2095 if(tcl[icl].CTP != vtx[iv].CTP)
continue;
2097 dwb = vtx[iv].Wire - tcl[icl].BeginWir;
2098 dtb = vtx[iv].Time - tcl[icl].BeginTim;
2099 dwe = vtx[iv].Wire - tcl[icl].EndWir;
2100 dte = vtx[iv].Time - tcl[icl].EndTim;
2102 float drb = dwb * dwb + dtb * dtb;
2103 float dre = dwe * dwe + dte * dte;
2105 bool bCloser = (drb < dre);
2109 if(tcl[icl].BeginChgNear > fChgNearCut)
continue;
2111 if(tcl[icl].EndChgNear > fChgNearCut)
continue;
2114 if(vtxprt)
mf::LogVerbatim(
"CC")<<
"VertexCluster: Try icl ID "<<tcl[icl].ID<<
" w vtx "<<iv<<
" dwb "<<dwb<<
" dwe "<<dwe<<
" drb "<<drb<<
" dre "<<dre<<
" Begin closer? "<<bCloser;
2116 if(tcl[icl].BeginVtx < 0 && bCloser && dwb > -3 && dwb < 3 && tcl[icl].EndVtx != iv) {
2117 sigOK = ChkSignal(tcl[icl].BeginWir, tcl[icl].BeginTim, vtx[iv].Wire, vtx[iv].Time);
2118 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" Attach cluster Begin to vtx? "<<iv<<
" sigOK "<<sigOK;
2120 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" check ClusterVertexChi "<<ClusterVertexChi(icl, 0, iv);
2121 if(ClusterVertexChi(icl, 0, iv) < fVertex2DCut) {
2123 tcl[icl].BeginVtx = iv;
2125 if(vtx[iv].ChiDOF > fVertex2DCut || vtx[iv].WireErr > fVertex2DWireErrCut) {
2126 tcl[icl].BeginVtx = -99;
2133 if(tcl[icl].EndVtx < 0 && !bCloser && dwe > -3 && dwe < 3 && tcl[icl].BeginVtx != iv) {
2134 sigOK = ChkSignal(tcl[icl].EndWir, tcl[icl].EndTim, vtx[iv].Wire, vtx[iv].Time);
2135 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" Attach cluster End to vtx? "<<iv<<
" sigOK "<<sigOK;
2137 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" check ClusterVertexChi "<<ClusterVertexChi(icl, 1, iv);
2138 if(ClusterVertexChi(icl, 1, iv) < 3) {
2140 tcl[icl].EndVtx = iv;
2142 if(vtx[iv].ChiDOF > fVertex2DCut || vtx[iv].WireErr > fVertex2DWireErrCut) {
2143 tcl[icl].EndVtx = -99;
2153 void ClusterCrawlerAlg::FitAllVtx(
CTP_t inCTP)
2156 for(
unsigned short iv = 0; iv < vtx.size(); ++iv) {
2157 if(vtx[iv].CTP != inCTP)
continue;
2217 void ClusterCrawlerAlg::FindVertices()
2221 if(tcl.size() < 2)
return;
2224 std::vector<CluLen> clulens;
2226 for(
unsigned short icl = 0; icl < tcl.size(); ++icl) {
2227 if(tcl[icl].ID < 0)
continue;
2228 if(tcl[icl].CTP != clCTP)
continue;
2229 if(tcl[icl].BeginVtx >= 0 && tcl[icl].EndVtx >= 0)
continue;
2231 clulen.
length = tcl[icl].tclhits.size();
2232 clulens.push_back(clulen);
2234 if(clulens.size() == 0)
return;
2235 std::sort (clulens.begin(),clulens.end(),
greaterThan);
2237 float nwires = fNumWires;
2238 float maxtime = fMaxTime;
2240 unsigned short vtxSizeIn = vtx.size();
2242 vtxprt = (fDebugPlane == (short)plane && fDebugHit < 0);
2248 float es1 = 0, eth1 = 0, ew1 = 0, et1 = 0;
2249 float bs1 = 0, bth1 = 0, bw1 = 0, bt1 = 0;
2250 float es2 = 0, eth2 = 0, ew2 = 0, et2 = 0;
2251 float bs2 = 0, bth2 = 0, bw2 = 0, bt2 = 0;
2252 float dth = 0, dsl = 0, fvw = 0, fvt = 0;
2254 unsigned int vw = 0, pass1, pass2, ii1, it1, ii2, it2;
2256 for(ii1 = 0; ii1 < clulens.size() - 1; ++ii1) {
2257 it1 = clulens[ii1].index;
2258 es1 = tcl[it1].EndSlp;
2259 eth1 = tcl[it1].EndAng;
2260 ew1 = tcl[it1].EndWir;
2261 et1 = tcl[it1].EndTim;
2262 bs1 = tcl[it1].BeginSlp;
2263 bth1 = tcl[it1].BeginAng;
2264 bw1 = tcl[it1].BeginWir;
2265 bt1 = tcl[it1].BeginTim;
2266 pass1 = tcl[it1].ProcCode - 10 *(tcl[it1].ProcCode / 10);
2267 for(ii2 = ii1 + 1; ii2 < clulens.size(); ++ii2) {
2268 it2 = clulens[ii2].index;
2272 if(tcl[it1].tclhits.size() < 5 &&
2273 tcl[it2].tclhits.size() < 5)
continue;
2274 es2 = tcl[it2].EndSlp;
2275 eth2 = tcl[it2].EndAng;
2276 ew2 = tcl[it2].EndWir;
2277 et2 = tcl[it2].EndTim;
2278 bs2 = tcl[it2].BeginSlp;
2279 bth2 = tcl[it2].BeginAng;
2280 bw2 = tcl[it2].BeginWir;
2281 bt2 = tcl[it2].BeginTim;
2282 pass2 = tcl[it2].ProcCode - 10 *(tcl[it2].ProcCode / 10);
2284 angcut = fKinkAngCut[pass2];
2286 angcut = fKinkAngCut[pass1];
2289 dth = fabs(eth1 - eth2);
2290 if(tcl[it1].EndVtx < 0 && tcl[it2].EndVtx < 0 && dth > 0.1) {
2293 fvw = (et1 - ew1 * es1 - et2 + ew2 * es2) / dsl;
2295 if(fvw > 0. && fvw < nwires) {
2300 if(vw >= fFirstWire - 1 &&
2301 fvw <= ew1 + 3 && fvw <= ew2 + 3 &&
2302 fvw > (ew1 - 10) && fvw > (ew2 - 10) ) {
2303 fvt = et1 + (fvw - ew1) * es1;
2304 if(vtxprt)
mf::LogVerbatim(
"CC")<<
"Chk clusters topo1 "<<tcl[it1].ID<<
" "<<tcl[it2].ID<<
" vtx wire "<<vw<<
" time "<<(int)fvt<<
" dth "<<dth;
2305 if(fvt > 0 && fvt < maxtime) {
2309 SigOK = ChkSignal(vw, fvt, vw, fvt);
2313 SigOK = ChkSignal(vw, fvt, vw, fvt);
2316 if(SigOK) ChkVertex(fvw, fvt, it1, it2, 1);
2322 dth = std::abs(eth1 - bth2);
2323 if(tcl[it1].EndVtx < 0 && tcl[it2].BeginVtx < 0 && dth > angcut) {
2325 if(fabs(ew1 - bw2) < 3 && fabs(et1 - bt2) < 500) {
2326 fvw = 0.5 * (ew1 + bw2);
2328 fvw = (et1 - ew1 * es1 - bt2 + bw2 * bs2) / dsl;
2330 if(fvw > 0 && fvw < nwires) {
2335 if(fvw <= ew1 + 2 && fvw >= bw2 - 2) {
2336 fvt = et1 + (vw - ew1) * es1;
2337 fvt += bt2 + (vw - bw2) * bs2;
2339 if(vtxprt)
mf::LogVerbatim(
"CC")<<
"Chk clusters topo2 "<<tcl[it1].ID<<
" "<<tcl[it2].ID<<
" vtx wire "<<vw<<
" time "<<(int)fvt<<
" dth "<<dth;
2340 if(fvt > 0. && fvt < maxtime) {
2341 ChkVertex(fvw, fvt, it1, it2, 2);
2347 dth = std::abs(bth1 - eth2);
2348 if(tcl[it1].BeginVtx < 0 && tcl[it2].EndVtx < 0 && dth > angcut) {
2350 if(fabs(bw1 - ew2) < 3 && fabs(bt1 - et2) < 500) {
2351 fvw = 0.5 * (bw1 + ew2);
2353 fvw = (et2 - ew2 * es2 - bt1 + bw1 * bs1) / dsl;
2355 if(fvw > 0 && fvw < nwires) {
2359 if(fvw <= ew2 + 2 && fvw >= bw1 - 2) {
2360 fvt = et2 + (fvw - ew2) * es2;
2361 fvt += bt1 + (fvw - bw1) * es1;
2363 if(vtxprt)
mf::LogVerbatim(
"CC")<<
"Chk clusters topo3 "<<tcl[it1].ID<<
" "<<tcl[it2].ID<<
" vtx wire "<<vw<<
" time "<<(int)fvt<<
" dth "<<dth;
2364 if(fvt > 0. && fvt < maxtime) {
2365 ChkVertex(fvw, fvt, it1, it2, 3);
2371 dth = std::abs(bth1 - bth2);
2372 if(tcl[it1].BeginVtx < 0 && tcl[it2].BeginVtx < 0 && dth > 0.1) {
2376 fvw = (bt1 - bw1 * bs1 - bt2 + bw2 * bs2) / dsl;
2377 if(vtxprt)
mf::LogVerbatim(
"CC")<<
"Chk clusters topo4 "<<bw1<<
":"<<(int)bt1<<
" "<<bw2<<
":"<<(
int)bt2<<
" fvw "<<fvw<<
" nwires "<<nwires;
2378 if(fvw > 0 && fvw < nwires) {
2384 if(tcl[it1].tclhits.size() < 2 * dwcut) dwcut = tcl[it1].tclhits.size()/2;
2385 if(tcl[it2].tclhits.size() < 2 * dwcut) dwcut = tcl[it2].tclhits.size()/2;
2386 if(fvw <= fLastWire + 1 &&
2387 fvw >= bw1 - dwcut && fvw <= bw1 + dwcut &&
2388 fvw >= bw2 - dwcut && fvw <= bw1 + dwcut) {
2389 fvt = bt1 + (fvw - bw1) * bs1;
2390 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" vtx wire "<<vw<<
" time "<<fvt<<
" dth "<<dth<<
" dwcut "<<dwcut;
2391 if(fvt > 0. && fvt < maxtime) {
2395 SigOK = ChkSignal(vw, fvt, vw, fvt);
2399 SigOK = ChkSignal(vw, fvt, vw, fvt);
2402 if(SigOK) ChkVertex(fvw, fvt, it1, it2, 4);
2412 for(
unsigned short it = 0; it < tcl.size(); ++it) {
2413 if(tcl[it].ID < 0)
continue;
2414 if(tcl[it].CTP != clCTP)
continue;
2415 if(tcl[it].BeginVtx > -1 && tcl[it].BeginVtx == tcl[it].EndVtx ) {
2416 unsigned short iv = tcl[it].BeginVtx;
2417 float dwir = tcl[it].BeginWir - vtx[iv].Wire;
2418 float dtim = tcl[it].BeginTim - vtx[iv].Time;
2419 float rbeg = dwir * dwir + dtim * dtim;
2420 dwir = tcl[it].EndWir - vtx[iv].Wire;
2421 dtim = tcl[it].EndTim - vtx[iv].Time;
2422 float rend = dwir * dwir + dtim * dtim;
2424 tcl[it].EndVtx = -99;
2426 tcl[it].BeginVtx = -99;
2431 if(vtx.size() > vtxSizeIn) FitAllVtx(clCTP);
2434 for(
unsigned short ivx = 0; ivx < vtx.size(); ++ivx) {
2435 if(vtx[ivx].CTP != clCTP)
continue;
2436 if(vtx[ivx].NClusters == 1) {
2437 vtx[ivx].NClusters = 0;
2438 for(
unsigned short icl = 0; icl < tcl.size(); ++icl) {
2439 if(tcl[icl].CTP != clCTP)
continue;
2440 if(tcl[icl].BeginVtx == ivx) {
2441 tcl[icl].BeginVtx = -99;
2444 if(tcl[icl].EndVtx == ivx) {
2445 tcl[icl].EndVtx = -99;
2456 void ClusterCrawlerAlg::ClusterVertex(
unsigned short it)
2460 if(vtx.size() == 0)
return;
2462 unsigned short iv, jv;
2463 short dwib, dwjb, dwie, dwje;
2464 bool matchEnd, matchBegin;
2468 for(iv = 0; iv < vtx.size(); ++iv) {
2470 if(vtx[iv].CTP != clCTP)
continue;
2472 if(vtx[iv].NClusters == 0)
continue;
2474 matchEnd =
false; matchBegin =
false;
2475 if(tcl[it].tclhits.size() < 6) {
2477 dwib = std::abs(vtx[iv].Wire - tcl[it].BeginWir);
2478 if(dwib > 2) dwib = 2;
2479 dwie = std::abs(vtx[iv].Wire - tcl[it].EndWir);
2480 if(dwie > 2) dwie = 2;
2481 dwjb = 999; dwje = 999;
2482 for(jv = 0; jv < vtx.size(); ++jv) {
2483 if(iv == jv)
continue;
2484 if(std::abs(vtx[jv].Time - tcl[it].BeginTim) < 50) {
2485 if(std::abs(vtx[jv].Wire - tcl[it].BeginWir) < dwjb)
2486 dwjb = std::abs(vtx[jv].Wire - tcl[it].BeginWir);
2488 if(std::abs(vtx[jv].Time - tcl[it].EndTim) < 50) {
2489 if(std::abs(vtx[jv].Wire - tcl[it].EndWir) < dwje)
2490 dwje = std::abs(vtx[jv].Wire - tcl[it].EndWir);
2493 matchEnd = tcl[it].EndVtx != iv &&
2494 dwie < 3 && dwie < dwje && dwie < dwib;
2495 matchBegin = tcl[it].BeginVtx != iv &&
2496 dwib < 3 && dwib < dwjb && dwib < dwie;
2499 matchEnd = tcl[it].EndVtx < 0 && vtx[iv].Wire <= tcl[it].EndWir + 2;
2500 matchBegin = tcl[it].BeginVtx < 0 && vtx[iv].Wire >= tcl[it].BeginWir - 2;
2503 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" Match End chi "<<ClusterVertexChi(it, 1, iv)<<
" to vtx "<<iv
2504 <<
" signalOK "<<ChkSignal(vtx[iv].Wire, vtx[iv].Time, tcl[it].EndWir, tcl[it].EndTim);
2505 if(ClusterVertexChi(it, 1, iv) < fVertex2DCut && ChkSignal(vtx[iv].Wire, vtx[iv].Time, tcl[it].EndWir, tcl[it].EndTim)) {
2507 tcl[it].EndVtx = iv;
2510 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" Add End "<<tcl[it].ID<<
" to vtx "<<iv<<
" NClusters "<<vtx[iv].NClusters;
2511 if(vtx[iv].ChiDOF < fVertex2DCut && vtx[iv].WireErr < fVertex2DWireErrCut)
return;
2512 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" Bad fit. ChiDOF "<<vtx[iv].ChiDOF<<
" WireErr "<<vtx[iv].WireErr<<
" Undo it";
2513 tcl[it].EndVtx = -99;
2519 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" Match Begin chi "<<ClusterVertexChi(it, 0, iv)<<
" to vtx "<<iv
2520 <<
" signalOK "<<ChkSignal(vtx[iv].Wire, vtx[iv].Time, tcl[it].BeginWir, tcl[it].BeginTim);
2521 if(ClusterVertexChi(it, 0, iv) < fVertex2DCut && ChkSignal(vtx[iv].Wire, vtx[iv].Time, tcl[it].BeginWir, tcl[it].BeginTim)) {
2523 tcl[it].BeginVtx = iv;
2526 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" Add Begin "<<tcl[it].ID<<
" to vtx "<<iv<<
" NClusters "<<vtx[iv].NClusters;
2527 if(vtx[iv].ChiDOF < fVertex2DCut && vtx[iv].WireErr < fVertex2DWireErrCut)
return;
2528 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" Bad fit. ChiDOF "<<vtx[iv].ChiDOF<<
" WireErr "<<vtx[iv].WireErr<<
" Undo it";
2529 tcl[it].BeginVtx = -99;
2539 void ClusterCrawlerAlg::ChkVertex(
float fvw,
float fvt,
unsigned short it1,
unsigned short it2,
short topo)
2550 <<tcl[it1].EndWir<<
":"<<(int)tcl[it1].EndTim<<
" - "<<tcl[it1].BeginWir<<
":"<<(
int)tcl[it1].BeginTim<<
" and " 2551 <<tcl[it2].EndWir<<
":"<<(int)tcl[it2].EndTim<<
" - "<<tcl[it2].BeginWir<<
":"<<(
int)tcl[it2].BeginTim
2552 <<
" topo "<<topo<<
" fvw "<<fvw<<
" fvt "<<fvt;
2554 unsigned int vw = (
unsigned int)(0.5 + fvw);
2560 if(tcl[it1].tclhits.size() < 10 && tcl[it2].tclhits.size() < 10) {
2561 for(
unsigned short it = 0; it < tcl.size(); ++it) {
2562 if(it == it1 || it == it2)
continue;
2563 if(tcl[it].ID < 0)
continue;
2564 if(tcl[it].CTP != clCTP)
continue;
2565 if(tcl[it].tclhits.size() < 100)
continue;
2566 if(std::abs(tcl[it].BeginAng - tcl[it].EndAng) > 0.1)
continue;
2568 if(vw < tcl[it].EndWir + 5)
continue;
2569 if(vw > tcl[it].BeginWir - 5)
continue;
2570 for(
unsigned short ii = 0; ii < tcl[it].tclhits.size(); ++ii) {
2571 iht = tcl[it].tclhits[ii];
2572 if(fHits[iht].WireID().Wire <= vw) {
2573 if(std::abs(fHits[iht].PeakTime() - fvt) < 60)
return;
2582 unsigned short nFitOK = 0;
2583 for(
unsigned short iv = 0; iv < vtx.size(); ++iv) {
2584 if(vtx[iv].CTP != clCTP)
continue;
2586 if(PointVertexChi(fvw, fvt, iv) > 300)
continue;
2587 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" vtx "<<iv<<
" PointVertexChi "<<PointVertexChi(fvw, fvt, iv);
2589 if( (topo == 1 || topo == 2) && tcl[it1].EndVtx < 0) {
2590 if(ChkSignal(vw, fvt, tcl[it1].EndWir, tcl[it1].EndTim)) {
2592 tcl[it1].EndVtx = iv;
2594 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" FitVtx "<<iv<<
" WireErr "<<vtx[iv].WireErr<<
" ChiDOF "<<vtx[iv].ChiDOF;
2595 if(vtx[iv].WireErr < fVertex2DWireErrCut && vtx[iv].ChiDOF < 5) {
2599 tcl[it1].EndVtx = -99;
2604 }
else if( (topo == 3 || topo == 4) && tcl[it1].BeginVtx < 0) {
2605 if(ChkSignal(vw, fvt, tcl[it1].BeginWir, tcl[it1].BeginTim)) {
2606 tcl[it1].BeginVtx = iv;
2608 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" FitVtx "<<iv<<
" WireErr "<<vtx[iv].WireErr<<
" ChiDOF "<<vtx[iv].ChiDOF;
2609 if(vtx[iv].WireErr < fVertex2DWireErrCut && vtx[iv].ChiDOF < 5) {
2613 tcl[it1].BeginVtx = -99;
2619 if( (topo == 1 || topo == 3) && tcl[it2].EndVtx < 0) {
2620 if(ChkSignal(vw, fvt, tcl[it2].EndWir, tcl[it2].EndTim)) {
2621 tcl[it2].EndVtx = iv;
2623 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" FitVtx "<<iv<<
" WireErr "<<vtx[iv].WireErr<<
" ChiDOF "<<vtx[iv].ChiDOF;
2624 if(vtx[iv].WireErr < fVertex2DWireErrCut && vtx[iv].ChiDOF < 5) {
2628 tcl[it2].EndVtx = -99;
2632 }
else if( (topo == 2 || topo == 4) && tcl[it2].BeginVtx < 0) {
2633 if(ChkSignal(vw, fvt, tcl[it2].BeginWir, tcl[it2].BeginTim)) {
2634 tcl[it2].BeginVtx = iv;
2636 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" FitVtx "<<iv<<
" WireErr "<<vtx[iv].WireErr<<
" ChiDOF "<<vtx[iv].ChiDOF;
2637 if(vtx[iv].WireErr < fVertex2DWireErrCut && vtx[iv].ChiDOF < 5) {
2641 tcl[it2].BeginVtx = -99;
2647 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" Attached "<<nFitOK<<
" clusters to vertex "<<iv;
2657 if(topo == 1 || topo == 2) {
2658 SigOK = ChkSignal(vw, fvt, tcl[it1].EndWir, tcl[it1].EndTim);
2661 SigOK = ChkSignal(vw, fvt, tcl[it1].BeginWir, tcl[it1].BeginTim);
2667 if(topo == 1 || topo == 3) {
2668 SigOK = ChkSignal(vw, fvt, tcl[it2].EndWir, tcl[it2].EndTim);
2671 SigOK = ChkSignal(vw, fvt, tcl[it2].BeginWir, tcl[it2].BeginTim);
2682 newvx.
Fixed =
false;
2683 vtx.push_back(newvx);
2684 unsigned short iv = vtx.size() - 1;
2685 if(topo == 1 || topo == 2) {
2686 if(tcl[it1].EndVtx >= 0) {
2691 tcl[it1].EndVtx = iv;
2693 if(tcl[it1].BeginVtx >= 0) {
2698 tcl[it1].BeginVtx = iv;
2700 if(topo == 1 || topo == 3) {
2701 if(tcl[it2].EndVtx >= 0) {
2706 tcl[it2].EndVtx = iv;
2708 if(tcl[it2].BeginVtx >= 0) {
2713 tcl[it2].BeginVtx = iv;
2718 if(vtx[iv].ChiDOF < 5 && vtx[iv].WireErr < fVertex2DWireErrCut && vtx[iv].TimeErr < 20) {
2719 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" New vtx "<<iv<<
" in plane "<<plane<<
" topo "<<topo<<
" cls "<<tcl[it1].ID<<
" "<<tcl[it2].ID<<
" W:T "<<(int)vw<<
":"<<(
int)fvt<<
" NClusters "<<vtx[iv].NClusters;
2721 if(fRefineVertexClusters) RefineVertexClusters(iv);
2723 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" Bad vtx fit "<<vtx[iv].ChiDOF<<
" wire err "<<vtx[iv].WireErr<<
" TimeErr "<<vtx[iv].TimeErr;
2726 if(tcl[it1].BeginVtx == iv) tcl[it1].BeginVtx = -99;
2727 if(tcl[it1].EndVtx == iv) tcl[it1].EndVtx = -99;
2728 if(tcl[it2].BeginVtx == iv) tcl[it2].BeginVtx = -99;
2729 if(tcl[it2].EndVtx == iv) tcl[it2].EndVtx = -99;
2735 bool ClusterCrawlerAlg::ChkSignal(
unsigned int iht,
unsigned int jht)
2737 if(iht > fHits.size() - 1)
return false;
2738 if(jht > fHits.size() - 1)
return false;
2739 unsigned int wire1 = fHits[iht].WireID().Wire;
2740 float time1 = fHits[iht].PeakTime();
2741 unsigned int wire2 = fHits[jht].WireID().Wire;
2742 float time2 = fHits[jht].PeakTime();
2743 return ChkSignal(wire1, time1, wire2, time2);
2747 bool ClusterCrawlerAlg::ChkSignal(
unsigned int wire1,
float time1,
unsigned int wire2,
float time2)
2754 const float gausAmp[20] = {1, 0.99, 0.96, 0.90, 0.84, 0.75, 0.67, 0.58, 0.49, 0.40, 0.32, 0.26, 0.20, 0.15, 0.11, 0.08, 0.06, 0.04, 0.03, 0.02};
2757 if(fMinAmp[plane] <= 0)
return true;
2760 unsigned int wireb = wire1;
2761 float timeb = time1;
2762 unsigned int wiree = wire2;
2763 float timee = time2;
2771 if(wiree < fFirstWire || wiree > fLastWire)
return false;
2772 if(wireb < fFirstWire || wireb > fLastWire)
return false;
2777 bool oneWire =
false;
2778 float prTime, prTimeLo = 0, prTimeHi = 0;
2779 if(wireb == wiree) {
2789 slope = (timeb - timee) / (wireb - wiree);
2793 unsigned short nmissed = 0;
2794 for(
unsigned int wire = wiree; wire < wireb + 1; ++wire) {
2796 prTime = (prTimeLo + prTimeHi) / 2;
2798 prTime = timee + (wire - wire0) * slope;
2801 if(WireHitRange[wire].first == -1)
continue;
2803 if(WireHitRange[wire].first == -2) ++nmissed;
2804 unsigned int firsthit = WireHitRange[wire].first;
2805 unsigned int lasthit = WireHitRange[wire].second;
2808 for(
unsigned int khit = firsthit; khit < lasthit; ++khit) {
2815 if(prTime < fHits[khit].StartTick())
continue;
2816 if(prTime > fHits[khit].EndTick())
continue;
2820 if(fHits[khit].PeakTime() - prTime > 500)
continue;
2821 bin = std::abs(fHits[khit].PeakTime() - prTime) / fHits[khit].RMS();
2823 if(bin > 19)
continue;
2824 if(bin < 0)
continue;
2827 amp += fHits[khit].PeakAmplitude() * gausAmp[
bin];
2830 if(amp < fMinAmp[plane]) ++nmissed;
2832 if(nmissed > fAllowNoHitWire)
return false;
2838 bool ClusterCrawlerAlg::SplitCluster(
unsigned short icl,
unsigned short pos,
unsigned short ivx)
2842 if(tcl[icl].ID < 0)
return false;
2847 MakeClusterObsolete(icl);
2849 unsigned short ii, iclnew;
2855 clBeginSlp = tcl[icl].BeginSlp;
2856 clBeginSlpErr = tcl[icl].BeginSlpErr;
2857 clBeginAng = tcl[icl].BeginAng;
2858 clBeginWir = tcl[icl].BeginWir;
2859 clBeginTim = tcl[icl].BeginTim;
2860 clBeginChg = tcl[icl].BeginChg;
2862 clProcCode = tcl[icl].ProcCode;
2867 for(ii = 0; ii < pos; ++ii) {
2868 iht = tcl[icl].tclhits[ii];
2869 fcl2hits.push_back(iht);
2872 pass = tcl[icl].ProcCode - 10 * (tcl[icl].ProcCode / 10);
2873 if(pass > fNumPass-1) pass = fNumPass-1;
2876 clEndSlp = clpar[1];
2877 clEndSlpErr = clparerr[1];
2878 clEndAng = std::atan(fScaleF * clEndSlp);
2883 RestoreObsoleteCluster(icl);
2887 iclnew = tcl.size() - 1;
2888 tcl[iclnew].EndVtx = ivx;
2889 tcl[iclnew].BeginVtx = tcl[icl].BeginVtx;
2890 if(vtxprt)
mf::LogVerbatim(
"CC")<<
"SplitCluster made cluster "<<iclnew<<
" attached to Begin vtx "<<ivx;
2893 if(pos < tcl[icl].tclhits.size() - 3) {
2896 clEndSlp = tcl[icl].EndSlp;
2897 clEndSlpErr = tcl[icl].EndSlpErr;
2898 clEndAng = std::atan(fScaleF * clEndSlp);
2899 clEndWir = tcl[icl].EndWir;
2900 clEndTim = tcl[icl].EndTim;
2901 clEndChg = tcl[icl].EndChg;
2903 clProcCode = tcl[icl].ProcCode;
2908 bool didFit =
false;
2909 for(ii = pos; ii < tcl[icl].tclhits.size(); ++ii) {
2910 iht = tcl[icl].tclhits[ii];
2911 if(inClus[iht] != 0) {
2912 RestoreObsoleteCluster(icl);
2915 fcl2hits.push_back(iht);
2917 if(fcl2hits.size() == fMaxHitsFit[pass] ||
2918 fcl2hits.size() == fMinHits[pass]) {
2920 clBeginSlp = clpar[1];
2921 clBeginAng = std::atan(fScaleF * clBeginSlp);
2922 clBeginSlpErr = clparerr[1];
2925 if((
unsigned short)fcl2hits.size() == fNHitsAve[pass] + 1) {
2927 clBeginChg = fAveChg;
2935 clBeginChg = fAveChg;
2939 MakeClusterObsolete(tcl.size() - 1);
2940 RestoreObsoleteCluster(icl);
2944 iclnew = tcl.size() - 1;
2945 tcl[iclnew].BeginVtx = ivx;
2946 tcl[iclnew].EndVtx = tcl[icl].EndVtx;
2947 if(vtxprt)
mf::LogVerbatim(
"CC")<<
"SplitCluster made cluster "<<iclnew<<
" attached to End vtx "<<ivx;
2954 void ClusterCrawlerAlg::ChkMerge()
2959 if(tcl.size() < 2)
return;
2964 prt = (fDebugPlane == (short)plane && fDebugWire < 0);
2967 unsigned short it1, it2, nh1, pass1, pass2;
2968 float bs1, bth1, bt1, bc1, es1, eth1, et1, ec1;
2969 float bs2, bth2, bt2, bc2, es2, eth2, et2, ec2;
2970 int bw1, ew1, bw2, ew2, ndead;
2971 float dth, dw, angcut, chgrat, chgcut, dtim, timecut, bigslp;
2972 bool bothLong, NoVtx;
2974 int skipcut, tclsize = tcl.size();
2977 for(it1 = 0; it1 < tclsize - 1; ++it1) {
2979 if(tcl[it1].ID < 0)
continue;
2980 if(tcl[it1].CTP != clCTP)
continue;
2981 bs1 = tcl[it1].BeginSlp;
2983 bth1 = std::atan(fScaleF * bs1);
2985 bw1 = tcl[it1].BeginWir;
2986 bt1 = tcl[it1].BeginTim;
2987 bc1 = tcl[it1].BeginChg;
2988 es1 = tcl[it1].EndSlp;
2989 eth1 = tcl[it1].EndAng;
2990 ew1 = tcl[it1].EndWir;
2991 et1 = tcl[it1].EndTim;
2992 ec1 = tcl[it1].EndChg;
2993 nh1 = tcl[it1].tclhits.size();
2994 pass1 = tcl[it1].ProcCode - 10 * (tcl[it1].ProcCode / 10);
2995 if(pass1 > fNumPass) pass1 = fNumPass;
2996 for(it2 = it1 + 1; it2 < tclsize; ++it2) {
2998 if(tcl[it1].ID < 0)
continue;
2999 if(tcl[it2].ID < 0)
continue;
3001 if(tcl[it2].CTP != clCTP)
continue;
3004 if(!ChkMergedClusterHitFrac(it1, it2)) {
3008 bs2 = tcl[it2].BeginSlp;
3009 bth2 = std::atan(fScaleF * bs2);
3010 bw2 = tcl[it2].BeginWir;
3011 bt2 = tcl[it2].BeginTim;
3012 bc2 = tcl[it2].BeginChg;
3013 es2 = tcl[it2].EndSlp;
3014 eth2 = tcl[it2].EndAng;
3015 ew2 = tcl[it2].EndWir;
3016 et2 = tcl[it2].EndTim;
3017 ec2 = tcl[it2].EndChg;
3018 pass2 = tcl[it2].ProcCode - 10 * (tcl[it2].ProcCode / 10);
3019 if(pass2 > fNumPass) pass2 = fNumPass;
3021 angcut = fKinkAngCut[pass1];
3022 if(fKinkAngCut[pass2] > angcut) angcut = fKinkAngCut[pass2];
3023 skipcut = fMaxWirSkip[pass1];
3024 if(fMaxWirSkip[pass2] > skipcut) skipcut = fMaxWirSkip[pass2];
3025 chgcut = fMergeChgCut[pass1];
3026 if(fMergeChgCut[pass2] > chgcut) chgcut = fMergeChgCut[pass2];
3034 bothLong = (nh1 > 100 && tcl[it2].tclhits.size() > 100);
3040 dth = std::abs(bth2 - eth1);
3042 dw = ew1 - bw2 - ndead;
3044 NoVtx = (tcl[it1].EndVtx < 0) && (tcl[it2].BeginVtx < 0);
3045 if(prt && bw2 < (ew1 + maxOverlap) )
mf::LogVerbatim(
"CC")<<
"Chk1 ID1-2 "<<tcl[it1].ID<<
"-"<<tcl[it2].ID<<
" "<<ew1<<
":"<<(int)et1<<
" "<<bw2<<
":"<<(
int)bt2<<
" dw "<<dw<<
" ndead "<<ndead<<
" skipcut "<<skipcut<<
" dth "<<dth<<
" angcut "<<angcut;
3046 if(NoVtx && bw2 < (ew1 + maxOverlap) && dw < skipcut && dth < angcut) {
3047 chgrat = 2 * fabs(bc2 - ec1) / (bc2 + ec1);
3049 if(bothLong && dth < 0.05) chgrat = 0.;
3051 dtim = fabs(bt2 + (ew1-bw2)*bs2 - et1);
3052 bigslp = std::abs(bs2);
3053 if(std::abs(es1) > bigslp) bigslp = std::abs(es1);
3054 timecut = fTimeDelta[pass2] * AngleFactor(bigslp);
3055 if(prt)
mf::LogVerbatim(
"CC")<<
" dtim "<<dtim<<
" timecut "<<(int)timecut<<
" ec1 "<<ec1<<
" bc2 "<<bc2<<
" chgrat "<<chgrat<<
" chgcut "<<chgcut<<
" es1 "<<es1<<
" ChkSignal "<<ChkSignal(ew1, et1, bw2, bt2);
3056 if(chgrat < chgcut && dtim < timecut) {
3058 if(ChkSignal(ew1, et1, bw2, bt2)) {
3059 DoMerge(it2, it1, 10);
3060 tclsize = tcl.size();
3068 dth = fabs(bth1 - eth2);
3070 dw = ew2 - bw1 - ndead;
3071 if(prt && bw1 < (ew2 + maxOverlap) && dw < skipcut)
mf::LogVerbatim(
"CC")<<
"Chk2 ID1-2 "<<tcl[it1].ID<<
"-"<<tcl[it2].ID<<
" "<<bw1<<
":"<<(int)bt1<<
" "<<bw2<<
":"<<(
int)et2<<
" dw "<<dw<<
" ndead "<<ndead<<
" skipcut "<<skipcut<<
" dth "<<dth<<
" angcut "<<angcut;
3073 NoVtx = (tcl[it2].EndVtx < 0) && (tcl[it1].BeginVtx < 0);
3074 if(NoVtx && bw1 < (ew2 + maxOverlap) && dw < skipcut && dth < angcut ) {
3075 chgrat = 2 * fabs((bc1 - ec2) / (bc1 + ec2));
3077 if(bothLong && dth < 0.05) chgrat = 0.;
3079 dtim = std::abs(bt1 + (ew2-bw1)*bs1 - et2);
3080 bigslp = std::abs(bs1);
3081 if(std::abs(bs2) > bigslp) bigslp = std::abs(bs2);
3082 timecut = fTimeDelta[pass2] * AngleFactor(bigslp);
3083 if(prt)
mf::LogVerbatim(
"CC")<<
" dtim "<<dtim<<
" err "<<dtim<<
" timecut "<<(int)timecut<<
" chgrat "<<chgrat<<
" chgcut "<<chgcut<<
" ChkSignal "<<ChkSignal(bw1, bt1, ew2, et2);
3085 if(chgrat < chgcut && dtim < timecut) {
3086 if(ChkSignal(bw1, bt1, ew2, et2)) {
3087 DoMerge(it1, it2, 10);
3088 tclsize = tcl.size();
3094 if(bw2 < bw1 && ew2 > ew1) {
3097 dth = fabs(eth2 - eth1);
3098 dtim = fabs(et1 +(ew2 - ew1 - 1)*es1 - et2);
3099 bigslp = std::abs(es1);
3100 if(std::abs(es1) > bigslp) bigslp = std::abs(es1);
3101 timecut = fTimeDelta[pass2] * AngleFactor(bigslp);
3103 short nmiss1 = bw1 - ew1 + 1 - tcl[it1].tclhits.size();
3105 short nin2 = tcl[it2].tclhits.size();
3106 if(prt)
mf::LogVerbatim(
"CC")<<
"cl2: "<<ew2<<
":"<<(int)et2<<
" - "<<bw2<<
":"<<(
int)bt2
3107 <<
" within cl1 "<<ew1<<
":"<<(int)et1<<
" - "<<bw1<<
":"<<(
int)bt1
3108 <<
" ? dth "<<dth<<
" dtim "<<dtim<<
" nmissed "<<nmiss1<<
" timecut "<<timecut<<
" FIX THIS CODE";
3113 if(dth < 1 && dtim < timecut && nmiss1 >= nin2)
3114 ChkMerge12(it1, it2, didit);
3116 tclsize = tcl.size();
3121 if(bw1 < bw2 && ew1 > ew2) {
3124 dth = std::abs(eth2 - eth1);
3125 dtim = std::abs(et2 +(ew1 - ew2 - 1)*es2 - et1);
3126 bigslp = std::abs(es1);
3127 if(std::abs(es1) > bigslp) bigslp = std::abs(es1);
3128 timecut = fTimeDelta[pass2] * AngleFactor(bigslp);
3130 short nmiss2 = bw2 - ew2 + 1 - tcl[it2].tclhits.size();
3132 short nin1 = tcl[it1].tclhits.size();
3133 if(prt)
mf::LogVerbatim(
"CC")<<
"cl1: "<<ew1<<
":"<<(int)et1<<
" - "<<bw1<<
":"<<(
int)bt1
3134 <<
" within cl2 "<<ew2<<
":"<<(int)et2<<
" - "<<bw2<<
":"<<(
int)bt2
3135 <<
" ? dth "<<dth<<
" dtim "<<dtim<<
" nmissed "<<nmiss2<<
" timecut "<<timecut<<
" FIX THIS CODE";
3139 if(dth < 1 && dtim < timecut && nmiss2 >= nin1) ChkMerge12(it2, it1, didit);
3141 tclsize = tcl.size();
3146 if(tcl[it1].ID < 0)
break;
3148 if(tcl[it1].ID < 0)
continue;
3153 void ClusterCrawlerAlg::ChkMerge12(
unsigned short it1,
unsigned short it2,
bool& didit)
3163 if(prt)
mf::LogVerbatim(
"CC")<<
"ChkMerge12 "<<tcl[it1].ID<<
" "<<tcl[it2].ID;
3167 int ew1 = tcl[it1].
EndWir;
3168 int bw1 = tcl[it1].BeginWir;
3169 unsigned int iht,
hit;
3171 std::vector<unsigned int> cl1hits(bw1+1-ew1);
3179 for(iht = 0; iht < cl1.
tclhits.size(); ++iht) {
3181 wire = fHits[hit].WireID().Wire;
3182 if(wire - ew1 < 0 || wire - ew1 > (
int)cl1hits.size()) {
3186 cl1hits[wire - ew1] = hit;
3188 unsigned int ew2 = tcl[it2].EndWir;
3189 float et2 = tcl[it2].EndTim;
3191 unsigned int wiron1 = 0;
3194 for(wire = ew2 - 1; wire > ew1; --wire) {
3195 if(cl1hits[wire - ew1] > 0) {
3201 if(prt)
mf::LogVerbatim(
"CC")<<
"chk next US wire "<<wiron1<<
" missed "<<nmiss;
3202 if(wiron1 == 0)
return;
3203 if(nmiss > fMaxWirSkip[pass])
return;
3207 unsigned int hiton2;
3209 unsigned short nfit = 0;
3210 for(iht = 0; iht < tcl[it2].tclhits.size(); ++iht) {
3211 hiton2 = tcl[it2].tclhits[iht];
3212 wiron2 = fHits[hiton2].WireID().Wire;
3213 if(wiron2 < ew1 || wiron2 > bw1)
return;
3214 if(cl1hits[wiron2 - ew1] == 0) ++nfit;
3217 if(nfit < tcl[it2].tclhits.size())
return;
3220 unsigned short pass1 = tcl[it1].ProcCode - 10 * (tcl[it1].ProcCode / 10);
3221 unsigned short pass2 = tcl[it2].ProcCode - 10 * (tcl[it2].ProcCode / 10);
3222 unsigned short cpass = pass1;
3224 if(pass2 < pass1) cpass = pass2;
3227 if((
int) wiron1 - ew1 < 0)
return;
3228 unsigned int hiton1 = cl1hits[wiron1 - ew1];
3229 if(hiton1 > fHits.size() - 1) {
3234 float timon1 = fHits[hiton1].PeakTime();
3235 float dtim = std::abs(et2 + (wiron1 - ew2) * tcl[it2].EndSlp - timon1);
3236 if(dtim > fTimeDelta[cpass])
return;
3239 FitClusterMid(it1, hiton1, 3);
3240 if(clChisq > 20.)
return;
3243 float dth = std::abs(std::atan(fScaleF * clpar[1]) - std::atan(fScaleF * tcl[it2].EndSlp));
3244 if(prt)
mf::LogVerbatim(
"CC")<<
"US dtheta "<<dth<<
" cut "<<fKinkAngCut[cpass];
3245 if(dth > fKinkAngCut[cpass])
return;
3247 float chgrat = 2 * std::abs(fAveChg - tcl[it2].EndChg) / (fAveChg + tcl[it2].EndChg);
3248 if(prt)
mf::LogVerbatim(
"CC")<<
"US chgrat "<<chgrat<<
" cut "<<fMergeChgCut[pass];
3251 SigOK = ChkSignal(wiron1, timon1, ew2, et2);
3253 if( !SigOK )
return;
3257 unsigned int bw2 = tcl[it2].BeginWir;
3258 float bt2 = tcl[it2].BeginTim;
3261 for(wire = bw2 + 1; wire < bw1; ++wire) {
3262 if(cl1hits[wire - ew1] > 0) {
3268 if(wiron1 == 0)
return;
3269 if(nmiss > fMaxWirSkip[pass])
return;
3272 hiton1 = cl1hits[wiron1 - ew1];
3273 if(hiton1 > fHits.size() - 1) {
3277 timon1 = fHits[hiton1].PeakTime();
3278 dtim = std::abs(bt2 - (wiron1 - bw2) *tcl[it2].BeginSlp - timon1);
3279 if(dtim > fTimeDelta[cpass])
return;
3280 FitClusterMid(it1, hiton1, -3);
3281 if(clChisq > 20.)
return;
3283 dth = std::abs(std::atan(fScaleF * clpar[1]) - std::atan(fScaleF * tcl[it2].BeginSlp));
3285 <<
"DS dtheta "<<dth<<
" cut "<<fKinkAngCut[cpass];
3286 if(dth > fKinkAngCut[cpass])
return;
3288 chgrat = 2 * std::abs(fAveChg - tcl[it2].BeginChg) / (fAveChg + tcl[it2].BeginChg);
3290 <<
"DS chgrat "<<chgrat<<
" cut "<<fMergeChgCut[pass];
3292 SigOK = ChkSignal(wiron1, timon1, bw2, bt2);
3294 if( !SigOK )
return;
3298 DoMerge(it1, it2, 100);
3303 void ClusterCrawlerAlg::DoMerge(
unsigned short it1,
unsigned short it2,
short inProcCode)
3310 if(cl1.
tclhits.size() < 3)
return;
3311 if(cl2.
tclhits.size() < 3)
return;
3317 unsigned int lowire, hiwire, whsize, ii, iht, indx;
3320 unsigned int fithit;
3335 whsize = hiwire + 2 - lowire;
3336 std::vector<int> wirehit(whsize, -1);
3338 for(ii = 0; ii < cl2.
tclhits.size(); ++ii) {
3340 indx = fHits[iht].WireID().Wire - lowire;
3341 wirehit[indx] = iht;
3344 for(ii = 0; ii < cl1.
tclhits.size(); ++ii) {
3346 indx = fHits[iht].WireID().Wire - lowire;
3347 wirehit[indx] = iht;
3356 for(std::vector<int>::reverse_iterator rit = wirehit.rbegin(); rit != wirehit.rend(); ++rit) {
3357 if(*rit < 0)
continue;
3358 fcl2hits.push_back(*rit);
3363 FitClusterMid(fcl2hits, fithit, nhitfit);
3365 if(clChisq > 5)
return;
3368 MakeClusterObsolete(it1);
3369 MakeClusterObsolete(it2);
3373 short del1Vtx = -99;
3374 short del2Vtx = -99;
3422 if(!TmpStore())
return;
3423 unsigned short itnew = tcl.size()-1;
3426 tcl[itnew].ProcCode = inProcCode + pass;
3429 if(del1Vtx >= 0 && del1Vtx == del2Vtx) vtx[del1Vtx].NClusters = 0;
3431 tcl[itnew].BeginVtx = begVtx;
3432 tcl[itnew].EndVtx = endVtx;
3436 void ClusterCrawlerAlg::PrintVertices()
3441 if(vtx3.size() > 0) {
3443 myprt<<
"****** 3D vertices ******************************************__2DVtx_Indx__*******\n";
3444 myprt<<
"Vtx Cstat TPC Proc X Y Z XEr YEr ZEr pln0 pln1 pln2 Wire\n";
3445 for(
unsigned short iv = 0; iv < vtx3.size(); ++iv) {
3446 myprt<<
std::right<<std::setw(3)<<std::fixed<<iv<<std::setprecision(1);
3447 myprt<<
std::right<<std::setw(7)<<vtx3[iv].CStat;
3448 myprt<<
std::right<<std::setw(5)<<vtx3[iv].TPC;
3449 myprt<<
std::right<<std::setw(5)<<vtx3[iv].ProcCode;
3453 myprt<<
std::right<<std::setw(5)<<vtx3[iv].XErr;
3454 myprt<<
std::right<<std::setw(5)<<vtx3[iv].YErr;
3455 myprt<<
std::right<<std::setw(5)<<vtx3[iv].ZErr;
3456 myprt<<
std::right<<std::setw(5)<<vtx3[iv].Ptr2D[0];
3457 myprt<<
std::right<<std::setw(5)<<vtx3[iv].Ptr2D[1];
3458 myprt<<
std::right<<std::setw(5)<<vtx3[iv].Ptr2D[2];
3459 myprt<<
std::right<<std::setw(5)<<vtx3[iv].Wire;
3460 if(vtx3[iv].Wire < 0) {
3461 myprt<<
" Matched in all planes";
3463 myprt<<
" Incomplete";
3469 if(vtx.size() > 0) {
3471 myprt<<
"************ 2D vertices ************\n";
3472 myprt<<
"Vtx CTP wire error tick error ChiDOF NCl topo cluster IDs\n";
3473 for(
unsigned short iv = 0; iv < vtx.size(); ++iv) {
3474 if(fDebugPlane < 3 && fDebugPlane != (
int)vtx[iv].CTP)
continue;
3475 myprt<<
std::right<<std::setw(3)<<std::fixed<<iv<<std::setprecision(1);
3476 myprt<<
std::right<<std::setw(6)<<vtx[iv].CTP;
3477 myprt<<
std::right<<std::setw(8)<<vtx[iv].Wire<<
" +/- ";
3478 myprt<<
std::right<<std::setw(4)<<vtx[iv].WireErr;
3479 myprt<<
std::right<<std::setw(8)<<vtx[iv].Time<<
" +/- ";
3480 myprt<<
std::right<<std::setw(4)<<vtx[iv].TimeErr;
3481 myprt<<
std::right<<std::setw(8)<<vtx[iv].ChiDOF;
3482 myprt<<
std::right<<std::setw(5)<<vtx[iv].NClusters;
3483 myprt<<
std::right<<std::setw(6)<<vtx[iv].Topo;
3486 for(
unsigned short ii = 0; ii < tcl.size(); ++ii) {
3487 if(fDebugPlane < 3 && fDebugPlane != (
int)tcl[ii].CTP)
continue;
3488 if(tcl[ii].ID < 0)
continue;
3489 if(tcl[ii].BeginVtx == (
short)iv) myprt<<
std::right<<std::setw(4)<<tcl[ii].ID;
3490 if(tcl[ii].EndVtx == (
short)iv) myprt<<
std::right<<std::setw(4)<<tcl[ii].ID;
3507 float aveRMS, aveRes;
3508 myprt<<
"*************************************** Clusters *********************************************************************\n";
3509 myprt<<
" ID CTP nht Stop Proc beg_W:T bAng bSlp Err bChg end_W:T eAng eSlp Err eChg bVx eVx aveRMS Qual cnt\n";
3510 for(
unsigned short ii = 0; ii < tcl.size(); ++ii) {
3512 if(fDebugPlane < 3 && fDebugPlane != (
int)tcl[ii].CTP)
continue;
3514 myprt<<
std::right<<std::setw(3)<<tcl[ii].CTP;
3515 myprt<<
std::right<<std::setw(5)<<tcl[ii].tclhits.size();
3516 myprt<<
std::right<<std::setw(4)<<tcl[ii].StopCode;
3517 myprt<<
std::right<<std::setw(6)<<tcl[ii].ProcCode;
3518 unsigned int iTime = tcl[ii].BeginTim;
3519 myprt<<
std::right<<std::setw(6)<<tcl[ii].BeginWir<<
":"<<iTime;
3522 }
else if(iTime < 100) {
3524 }
else if(iTime < 1000) myprt<<
" ";
3525 myprt<<
std::right<<std::setw(7)<<std::fixed<<std::setprecision(2)<<tcl[ii].BeginAng;
3526 if(std::abs(tcl[ii].BeginSlp) < 100) {
3527 myprt<<
std::right<<std::setw(6)<<std::fixed<<std::setprecision(2)<<tcl[ii].BeginSlp;
3529 myprt<<
std::right<<std::setw(6)<<(int)tcl[ii].BeginSlp;
3531 myprt<<
std::right<<std::setw(6)<<std::fixed<<std::setprecision(2)<<tcl[ii].BeginSlpErr;
3532 myprt<<
std::right<<std::setw(5)<<(int)tcl[ii].BeginChg;
3534 iTime = tcl[ii].EndTim;
3535 myprt<<
std::right<<std::setw(6)<<tcl[ii].EndWir<<
":"<<iTime;
3538 }
else if(iTime < 100) {
3540 }
else if(iTime < 1000) myprt<<
" ";
3541 myprt<<
std::right<<std::setw(7)<<std::fixed<<std::setprecision(2)<<tcl[ii].EndAng;
3542 if(std::abs(tcl[ii].EndSlp) < 100) {
3543 myprt<<
std::right<<std::setw(6)<<std::fixed<<std::setprecision(2)<<tcl[ii].EndSlp;
3545 myprt<<
std::right<<std::setw(6)<<(int)tcl[ii].EndSlp;
3547 myprt<<
std::right<<std::setw(6)<<std::fixed<<std::setprecision(2)<<tcl[ii].EndSlpErr;
3548 myprt<<
std::right<<std::setw(5)<<(int)tcl[ii].EndChg;
3550 myprt<<
std::right<<std::setw(5)<<tcl[ii].BeginVtx;
3551 myprt<<
std::right<<std::setw(5)<<tcl[ii].EndVtx;
3553 unsigned int iht = 0;
3554 for(
unsigned short jj = 0; jj < tcl[ii].tclhits.size(); ++jj) {
3555 iht = tcl[ii].tclhits[jj];
3556 aveRMS += fHits[iht].RMS();
3558 aveRMS /= (float)tcl[ii].tclhits.size();
3559 myprt<<
std::right<<std::setw(5)<<std::fixed<<std::setprecision(1)<<aveRMS;
3562 unsigned int hit0, hit1, hit2, cnt = 0;
3564 for(
unsigned short iht = 1; iht < tcl[ii].tclhits.size()-1; ++iht) {
3565 hit1 = tcl[ii].tclhits[iht];
3566 hit0 = tcl[ii].tclhits[iht-1];
3567 hit2 = tcl[ii].tclhits[iht+1];
3569 if(fHits[hit1].WireID().Wire + 1 != fHits[hit0].WireID().Wire)
continue;
3570 if(fHits[hit2].WireID().Wire + 1 != fHits[hit1].WireID().Wire)
continue;
3571 arg = (fHits[hit0].PeakTime() + fHits[hit2].PeakTime())/2 - fHits[hit1].PeakTime();
3572 aveRes += arg * arg;
3576 aveRes /= (float)cnt;
3577 aveRes = sqrt(aveRes);
3579 aveRes /= (aveRMS * fHitErrFac);
3580 myprt<<
std::right<<std::setw(6)<<std::fixed<<std::setprecision(1)<<aveRes;
3581 myprt<<
std::right<<std::setw(5)<<std::fixed<<cnt;
3584 myprt<<
std::right<<std::setw(5)<<std::fixed<<cnt;
3595 void ClusterCrawlerAlg::TmpGet(
unsigned short it1)
3600 if(it1 > tcl.size())
return;
3603 clBeginSlp = tcl[it1].BeginSlp;
3604 clBeginSlpErr = tcl[it1].BeginSlpErr;
3605 clBeginAng = tcl[it1].BeginAng;
3606 clBeginWir = tcl[it1].BeginWir;
3607 clBeginTim = tcl[it1].BeginTim;
3608 clBeginChg = tcl[it1].BeginChg;
3609 clBeginChgNear = tcl[it1].BeginChgNear;
3610 clEndSlp = tcl[it1].EndSlp;
3611 clEndSlpErr = tcl[it1].EndSlpErr;
3612 clEndAng = tcl[it1].EndAng;
3613 clEndWir = tcl[it1].EndWir;
3614 clEndTim = tcl[it1].EndTim;
3615 clEndChg = tcl[it1].EndChg;
3616 clEndChgNear = tcl[it1].EndChgNear;
3617 clStopCode = tcl[it1].StopCode;
3618 clProcCode = tcl[it1].ProcCode;
3619 clCTP = tcl[it1].CTP;
3620 fcl2hits = tcl[it1].tclhits;
3625 bool ClusterCrawlerAlg::TmpStore()
3628 if(fcl2hits.size() < 2)
return false;
3629 if(fcl2hits.size() > fHits.size())
return false;
3631 if(NClusters == SHRT_MAX)
return false;
3635 unsigned int hit0 = fcl2hits[0];
3637 unsigned int tCST = fHits[hit0].WireID().Cryostat;
3638 unsigned int tTPC = fHits[hit0].WireID().TPC;
3639 unsigned int tPlane = fHits[hit0].WireID().Plane;
3640 unsigned int lastWire = 0;
3642 for(
unsigned short it = 0; it < fcl2hits.size(); ++it) {
3644 if(inClus[hit] != 0) {
3654 if(fHits[hit].WireID().Cryostat != tCST || fHits[hit].WireID().TPC != tTPC || fHits[hit].WireID().Plane != tPlane) {
3664 if(clProcCode < 900 && it > 0 && fHits[hit].WireID().Wire >= lastWire) {
3678 lastWire = fHits[hit].WireID().Wire;
3679 inClus[hit] = NClusters;
3687 unsigned int ih0 = fcl2hits.size() - 2;
3688 hit = fcl2hits[ih0];
3689 clEndChg = fHits[hit].Integral();
3690 hit = fcl2hits[ih0 - 1];
3691 clEndChg += fHits[hit].Integral();
3692 clEndChg = clEndChg / 2.;
3694 if(clBeginChg <= 0) {
3697 clBeginChg = fHits[hit].Integral();
3699 clBeginChg += fHits[hit].Integral();
3700 clBeginChg = clBeginChg / 2.;
3704 hit = fcl2hits[fcl2hits.size()-1];
3709 clstr.
ID = NClusters;
3712 clstr.
BeginAng = std::atan(fScaleF * clBeginSlp);
3713 clstr.
BeginWir = fHits[hit0].WireID().Wire;
3714 clstr.
BeginTim = fHits[hit0].PeakTime();
3719 clstr.
EndAng = std::atan(fScaleF * clEndSlp);
3720 clstr.
EndWir = fHits[hit].WireID().Wire;
3721 clstr.
EndTim = fHits[hit].PeakTime();
3730 tcl.push_back(clstr);
3736 void ClusterCrawlerAlg::LACrawlUS() {
3741 unsigned int dhit = fcl2hits[0];
3742 short dwir = fHits[dhit].WireID().Wire;
3745 if(fDebugPlane == (
short)plane && dwir == fDebugWire && fDebugHit > 0)
3746 prt = std::abs(fHits[dhit].PeakTime() - fDebugHit) < 40;
3750 myprt<<
"******************* LACrawlUS PASS "<<pass<<
" Hits ";
3751 for(
unsigned short ii = 0; ii < fcl2hits.size(); ++ii) {
3752 unsigned int iht = fcl2hits[fcl2hits.size() - 1 - ii];
3753 myprt<<fHits[iht].WireID().Wire<<
":"<<(int)fHits[iht].PeakTime()<<
" ";
3762 unsigned short kinkOnWire = 0;
3763 unsigned int it = fcl2hits.size() - 1;
3764 unsigned int lasthit = fcl2hits[it];
3765 unsigned int lastwire = fHits[lasthit].WireID().Wire;
3766 unsigned int prevHit, prevWire;
3767 bool ChkCharge =
false;
3768 for(
unsigned int nextwire = lastwire-1; nextwire >= fFirstWire; --nextwire) {
3769 if(prt)
mf::LogVerbatim(
"CC")<<
"LACrawlUS: next wire "<<nextwire<<
" HitRange "<<WireHitRange[nextwire].first;
3771 if(CrawlVtxChk(nextwire)) {
3777 AddLAHit(nextwire, ChkCharge, HitOK, SigOK);
3778 if(prt)
mf::LogVerbatim(
"CC")<<
"LACrawlUS: HitOK "<<HitOK<<
" SigOK "<<SigOK<<
" nmissed SigOK "<<nmissed<<
" cut "<<fAllowNoHitWire;
3779 if(SigOK) nmissed = 0;
3782 if(nmissed > fAllowNoHitWire) {
3791 prevHit = fcl2hits[fcl2hits.size() - 2];
3792 prevWire = fHits[prevHit].WireID().Wire;
3793 if(prevWire > nextwire + 2) {
3794 if(!ChkSignal(fcl2hits[fcl2hits.size()-1], fcl2hits[fcl2hits.size()-2])) {
3804 if(fcl2hits.size() == 4) {
3806 for(
unsigned short kk = 0; kk< fcl2hits.size()-1; ++kk) {
3807 unsigned int hit = fcl2hits[kk];
3808 if(mergeAvailable[hit]) MergeHits(hit, didMerge);
3812 clBeginSlp = clpar[1];
3817 unsigned short chsiz = chifits.size()-1;
3819 if(chsiz < 6)
continue;
3820 if(fKinkChiRat[pass] <= 0)
continue;
3821 if(chifits.size() != fcl2hits.size()) {
3823 <<
"LACrawlUS: chifits size error "<<chifits.size()<<
" "<<fcl2hits.size();
3826 if(prt)
mf::LogVerbatim(
"CC") <<
"Kink chk "<<chifits[chsiz]<<
" "<<chifits[chsiz-1]
3827 <<
" "<<chifits[chsiz-2]<<
" "<<chifits[chsiz-3];
3828 if( chifits[chsiz-1] > fKinkChiRat[pass] * chifits[chsiz-2] &&
3829 chifits[chsiz] > fKinkChiRat[pass] * chifits[chsiz-1]) {
3831 unsigned int ih0 = fcl2hits.size() - 1;
3832 unsigned int hit0 = fcl2hits[ih0];
3833 unsigned int ih2 = ih0 - 2;
3834 unsigned int hit2 = fcl2hits[ih2];
3835 float dt02 = fHits[hit2].PeakTime() - fHits[hit0].PeakTime();
3836 float dw02 = fHits[hit2].WireID().Wire - fHits[hit0].WireID().Wire;
3837 float th02 = std::atan( fScaleF * dt02 / dw02);
3839 unsigned int ih3 = ih2 - 1;
3840 unsigned int hit3 = fcl2hits[ih3];
3841 unsigned int ih5 = ih3 - 2;
3842 unsigned int hit5 = fcl2hits[ih5];
3843 float dt35 = fHits[hit5].PeakTime() - fHits[hit3].PeakTime();
3844 float dw35 = fHits[hit5].WireID().Wire - fHits[hit3].WireID().Wire;
3845 float th35 = std::atan(fScaleF * dt35 / dw35);
3846 float dth = std::abs(th02 - th35);
3847 if(prt)
mf::LogVerbatim(
"CC")<<
" Kink angle "<<std::setprecision(3)<<dth<<
" cut "<<fKinkAngCut[pass];
3848 if(dth > fKinkAngCut[pass]) {
3854 if(kinkOnWire > 0) {
3855 if(kinkOnWire - nextwire < 4) {
3856 if(prt)
mf::LogVerbatim(
"CC") <<
"Hit a second kink. kinkOnWire = "<<kinkOnWire<<
" Stopping";
3862 kinkOnWire = nextwire;
3868 CheckClusterHitFrac(prt);
3871 if(prt)
mf::LogVerbatim(
"CC")<<
"LACrawlUS done. Nhits = "<<fcl2hits.size();
3876 void ClusterCrawlerAlg::CrawlUS()
3880 if(fcl2hits.size() < 2)
return;
3882 unsigned int dhit = fcl2hits[0];
3883 int dwir = fHits[dhit].WireID().Wire;
3887 if(fDebugPlane == (
short)plane && dwir == fDebugWire && fDebugHit > 0)
3888 prt = std::abs(fHits[dhit].PeakTime() - fDebugHit) < 20;
3892 myprt<<
"******************* Start CrawlUS on pass "<<pass<<
" Hits: ";
3893 for(
unsigned short ii = 0; ii < fcl2hits.size(); ++ii) {
3894 unsigned int iht = fcl2hits[fcl2hits.size() - 1 - ii];
3895 myprt<<fHits[iht].WireID().Wire<<
":"<<(int)fHits[iht].PeakTime()<<
" ";
3906 short nHitAfterSkip = 0;
3907 bool DidaSkip =
false;
3908 bool PostSkip =
false;
3909 unsigned int it = fcl2hits.size() - 1;
3910 unsigned int lasthit = fcl2hits[it];
3911 if(lasthit > fHits.size() - 1) {
3915 unsigned int lastwire = fHits[lasthit].WireID().Wire;
3916 if(prt)
mf::LogVerbatim(
"CC")<<
"CrawlUS: last wire "<<lastwire<<
" hit "<<lasthit;
3918 unsigned int lastWireWithSignal = lastwire;
3919 unsigned short nDroppedHit = 0;
3921 for(
unsigned int nextwire = lastwire-1; nextwire > fFirstWire; --nextwire) {
3922 if(prt)
mf::LogVerbatim(
"CC")<<
"CrawlUS: next wire "<<nextwire<<
" HitRange "<<WireHitRange[nextwire].first;
3924 if(CrawlVtxChk(nextwire)) {
3930 if(std::abs(clpar[1]) > fLAClusSlopeCut) {
3931 if(prt)
mf::LogVerbatim(
"CC")<<
">>>>> CrawlUS: Switching to LACrawlUS";
3936 AddHit(nextwire, HitOK, SigOK);
3937 if(prt)
mf::LogVerbatim(
"CC")<<
"CrawlUS: HitOK "<<HitOK<<
" SigOK "<<SigOK<<
" nmissed "<<nmissed;
3938 if(SigOK) lastWireWithSignal = nextwire;
3953 if(PostSkip && nmissed > fMinWirAfterSkip[pass]) {
3955 if((
int)(fcl2hits.size() - nHitAfterSkip) < 4) {
3962 FclTrimUS(nHitAfterSkip);
3980 lasthit = fcl2hits[fcl2hits.size() - 1];
3981 if((lastWireWithSignal - nextwire) > fAllowNoHitWire) {
3982 if(prt)
mf::LogVerbatim(
"CC")<<
"No hit or signal on wire "<<nextwire<<
" last wire with signal "<<lastWireWithSignal<<
" exceeding fAllowNoHitWire "<<fAllowNoHitWire<<
" Break!";
3988 if(prt)
mf::LogVerbatim(
"CC")<<
" CrawlUS check clChisq "<<clChisq<<
" cut "<<fChiCut[pass];
3989 if(clChisq > fChiCut[pass]) {
3990 if(fcl2hits.size() < 3) {
3995 if(prt)
mf::LogVerbatim(
"CC")<<
"ADD- Bad clChisq "<<clChisq<<
" dropping hit";
3999 if(nDroppedHit > 4) {
4000 if(prt)
mf::LogVerbatim(
"CC")<<
" Too many dropped hits: "<<nDroppedHit<<
" Stop crawling";
4003 if(clChisq > fChiCut[pass]) {
4004 if(prt)
mf::LogVerbatim(
"CC")<<
" Bad clChisq "<<clChisq<<
" after dropping hit. Stop crawling";
4020 if(chifits.size() > 5 && fKinkChiRat[pass] > 0) {
4021 if(chifits.size() != fcl2hits.size()) {
4022 mf::LogError(
"CC")<<
"CrawlUS: chifits size error "<<chifits.size()<<
" "<<fcl2hits.size();
4025 unsigned short chsiz = chifits.size()-1;
4026 if(prt)
mf::LogVerbatim(
"CC")<<
"Kink chk "<<chifits[chsiz]<<
" "<<chifits[chsiz-1]<<
" "<<chifits[chsiz-2]<<
" "<<chifits[chsiz-3];
4027 if( chifits[chsiz-1] > fKinkChiRat[pass] * chifits[chsiz-2] &&
4028 chifits[chsiz] > fKinkChiRat[pass] * chifits[chsiz-1]) {
4029 if(fcl2hits.size() != chifits.size()) {
4030 mf::LogError(
"CC")<<
"bad kink check size "<<chifits.size()<<
" "<<fcl2hits.size()<<
" plane "<<plane<<
" cluster "<<dwir<<
":"<<dhit;
4033 if(EndKinkAngle() > fKinkAngCut[pass]) {
4034 if(prt)
mf::LogVerbatim(
"CC")<<
"******************* Stopped tracking - kink angle "<<EndKinkAngle()
4035 <<
" > "<<fKinkAngCut[pass]<<
" Removing 3 hits";
4048 if(fcl2hits.size() == fMaxHitsFit[pass] ||
4049 fcl2hits.size() == fMinHits[pass]) {
4050 clBeginSlp = clpar[1];
4051 clBeginSlpErr = clparerr[1];
4054 if(clBeginChg <= 0 && fAveChg > 0) {
4055 clBeginChg = fAveChg;
4071 if(nHitAfterSkip == fMinWirAfterSkip[pass]) PostSkip =
false;
4074 if(clChisq > fChiCut[pass]) {
4078 unsigned short lopped = 0;
4079 for(
unsigned short nlop = 0; nlop < 4; ++nlop) {
4080 unsigned short cfsize = chifits.size() - 1;
4081 chirat = chifits[cfsize] / chifits[cfsize - 1];
4082 if(prt)
mf::LogVerbatim(
"CC")<<
"chirat "<<chirat<<
" last hit "<<fcl2hits[fcl2hits.size()-1];
4083 if(chirat < 1.2)
break;
4084 if(prt)
mf::LogVerbatim(
"CC")<<
"<<ADD- Bad chisq. Bad chirat "<<chirat;
4087 if(fcl2hits.size() < 6)
break;
4088 if(chifits.size() < 6)
break;
4090 if(fcl2hits.size() < 6) {
4092 if(prt)
mf::LogVerbatim(
"CC")<<
"Bad fit chisq - short cluster. Break";
4095 if(lopped == 0 && fcl2hits.size() > 5) {
4102 if(prt)
mf::LogVerbatim(
"CC")<<
"Bad fit chisq - removed "<<lopped<<
" hits. Continue";
4106 if(prt)
mf::LogVerbatim(
"CC")<<
"******************* CrawlUS normal stop. size "<<fcl2hits.size();
4110 if(fcl2hits.size() > 5) {
4112 if(prt)
mf::LogVerbatim(
"CC")<<
"EndKinkAngle check "<<EndKinkAngle()<<
" cut "<<fKinkAngCut[pass];
4113 if(EndKinkAngle() > fKinkAngCut[pass]) {
4122 if((
unsigned short)fcl2hits.size() > fMinWirAfterSkip[pass] + 3) {
4123 unsigned int ih0 = fcl2hits.size() - 1;
4124 unsigned int hit0 = fcl2hits[ih0];
4125 unsigned int uswir = fHits[hit0].WireID().Wire;
4126 unsigned int nxtwir;
4127 unsigned short nAdjHit = 0;
4128 for(
unsigned short ii = ih0 - 1; ii > 0; --ii) {
4129 nxtwir = fHits[ fcl2hits[ii] ].WireID().Wire;
4131 if(nxtwir != uswir + 1)
break;
4133 if( nAdjHit == fMinWirAfterSkip[pass] )
break;
4137 if(nAdjHit < fMinWirAfterSkip[pass]) {
4138 if(prt)
mf::LogVerbatim(
"CC")<<
"fMinWirAfterSkip removes "<<nAdjHit<<
" hits ";
4145 if(!reFit && fcl2hits.size() > 3) {
4146 float chirat = chifits[chifits.size()-1] / chifits[chifits.size()-2];
4147 if(prt)
mf::LogVerbatim(
"CC")<<
"Last hit chirat "<<chirat<<
" cut "<<fKinkChiRat[pass];
4148 if(prt)
mf::LogVerbatim(
"CC")<<
"Check "<<clChisq<<
" "<<chifits[chifits.size()-1]<<
" "<<chifits[chifits.size()-2];
4149 if(chirat > fKinkChiRat[pass]) {
4160 CheckClusterHitFrac(prt);
4161 if(prt)
mf::LogVerbatim(
"CC")<<
"******************* CrawlUS done. Size " 4162 <<fcl2hits.size()<<
" min length for this pass "<<fMinHits[pass];
4168 float ClusterCrawlerAlg::EndKinkAngle()
4172 unsigned int ih0 = fcl2hits.size() - 1;
4173 unsigned int hit0 = fcl2hits[ih0];
4174 unsigned int ih2 = ih0 - 2;
4175 unsigned int hit2 = fcl2hits[ih2];
4176 float dt02 = fHits[hit2].PeakTime() - fHits[hit0].PeakTime();
4177 float dw02 = fHits[hit2].WireID().Wire - fHits[hit0].WireID().Wire;
4178 float th02 = std::atan( fScaleF * dt02 / dw02);
4180 unsigned int ih3 = ih2 - 1;
4181 unsigned int hit3 = fcl2hits[ih3];
4182 unsigned int ih5 = ih3 - 2;
4183 unsigned int hit5 = fcl2hits[ih5];
4184 float dt35 = fHits[hit5].PeakTime() - fHits[hit3].PeakTime();
4185 float dw35 = fHits[hit5].WireID().Wire - fHits[hit3].WireID().Wire;
4186 float th35 = std::atan(fScaleF * dt35 / dw35);
4187 return std::abs(th02 - th35);
4191 bool ClusterCrawlerAlg::ChkMergedClusterHitFrac(
unsigned short it1,
unsigned short it2)
4195 if(it1 > tcl.size()-1)
return false;
4196 if(it2 > tcl.size()-1)
return false;
4197 unsigned int eWire = 99999;
4198 unsigned int bWire = 0, wire;
4199 if(tcl[it1].BeginWir > bWire) bWire = tcl[it1].BeginWir;
4200 if(tcl[it2].BeginWir > bWire) bWire = tcl[it2].BeginWir;
4201 if(tcl[it1].EndWir < eWire) eWire = tcl[it1].EndWir;
4202 if(tcl[it2].EndWir < eWire) eWire = tcl[it2].EndWir;
4203 unsigned int mergedClusterLength = bWire - eWire + 1;
4205 std::vector<bool> cHits(mergedClusterLength,
false);
4207 unsigned int ii, iht, indx;
4208 for(ii = 0; ii < tcl[it1].tclhits.size(); ++ii) {
4209 iht = tcl[it1].tclhits[ii];
4210 if(iht > fHits.size()-1) {
4211 mf::LogError(
"CC")<<
"ChkMergedClusterHitFrac bad iht ";
4214 indx = fHits[iht].WireID().Wire - eWire;
4217 for(ii = 0; ii < tcl[it2].tclhits.size(); ++ii) {
4218 iht = tcl[it2].tclhits[ii];
4219 if(iht > fHits.size()-1) {
4220 mf::LogError(
"CC")<<
"ChkMergedClusterHitFrac bad iht ";
4223 indx = fHits[iht].WireID().Wire - eWire;
4227 for(ii = 0; ii < cHits.size(); ++ii) {
4229 if(WireHitRange[wire].first == -1) cHits[ii] =
true;
4232 float nhits = std::count(cHits.begin(), cHits.end(),
true);
4233 float hitFrac = nhits / (float)cHits.size();
4234 return (hitFrac > fMinHitFrac);
4238 void ClusterCrawlerAlg::CheckClusterHitFrac(
bool prt)
4244 unsigned int iht = fcl2hits[fcl2hits.size() - 1];
4245 clEndWir = fHits[iht].WireID().Wire;
4246 clBeginWir = fHits[fcl2hits[0]].WireID().Wire;
4247 float hitFrac = (float)(fcl2hits.size() +
DeadWireCount()) / (
float)(clBeginWir - clEndWir + 1);
4249 if(hitFrac < fMinHitFrac) {
4251 if(prt)
mf::LogVerbatim(
"CC")<<
"CheckClusterHitFrac: Poor hit fraction "<<hitFrac<<
" clBeginWir "<<clBeginWir
4252 <<
" clEndWir "<<clEndWir<<
" size "<<fcl2hits.size()<<
" DeadWireCount "<<
DeadWireCount();
4264 if(fcl2hits.size() < 5) {
4265 unsigned short nsing = 0;
4266 for(
unsigned short iht = 0; iht < fcl2hits.size(); ++iht)
if(fHits[fcl2hits[iht]].Multiplicity() == 1) ++nsing;
4267 hitFrac = (float)nsing / (
float)fcl2hits.size();
4268 if(hitFrac < fMinHitFrac) {
4271 if(prt)
mf::LogVerbatim(
"CC")<<
"CheckClusterHitFrac: Poor short track hit fraction "<<hitFrac;
4278 if(clBeginChg <= 0) {
4279 unsigned int iht, nht = 0;
4280 for(
unsigned short ii = 0; ii < fcl2hits.size(); ++ii) {
4282 clBeginChg += fHits[iht].Integral();
4286 clBeginChg /= (float)nht;
4289 unsigned short cnt = chgNear.size()/2;
4291 if(chgNear.size() > 60) cnt = 30;
4294 for(
unsigned short ids = 0; ids < cnt; ++ids) {
4295 clBeginChgNear += chgNear[ids];
4296 clEndChgNear += chgNear[chgNear.size() - 1 - ids];
4298 clBeginChgNear /= (float)cnt;
4299 clEndChgNear /= (float)cnt;
4304 void ClusterCrawlerAlg::FitClusterMid(
unsigned short it1,
unsigned int ihtin,
short nhit)
4306 FitClusterMid(tcl[it1].tclhits, ihtin, nhit);
4310 void ClusterCrawlerAlg::FitClusterMid(std::vector<unsigned int>& hitVec,
unsigned int ihtin,
short nhit)
4322 if(hitVec.size() < 3)
return;
4324 std::vector<float> xwir;
4325 std::vector<float> ytim;
4326 std::vector<float> ytimerr2;
4328 unsigned short ii, hitcnt = 0, nht = 0, usnhit;
4338 for(ii = 0; ii < hitVec.size(); ++ii) {
4340 if(iht > fHits.size()-1) {
4347 wire0 = fHits[iht].WireID().Wire;
4351 xwir.push_back((
float)fHits[iht].WireID().Wire - wire0);
4352 ytim.push_back(fHits[iht].PeakTime());
4354 float terr = fHitErrFac * fHits[iht].RMS();
4355 ytimerr2.push_back(terr * terr);
4356 fAveChg += fHits[iht].Integral();
4358 if(hitcnt == usnhit)
break;
4365 for(
auto ii = hitVec.crbegin(); ii != hitVec.crend(); ++ii) {
4367 if(iht > fHits.size()-1) {
4374 wire0 = fHits[iht].WireID().Wire;
4378 xwir.push_back((
float)fHits[iht].WireID().Wire - wire0);
4379 ytim.push_back(fHits[iht].PeakTime());
4380 float terr = fHitErrFac * fHits[iht].RMS();
4381 ytimerr2.push_back(terr * terr);
4382 fAveChg += fHits[iht].Integral();
4384 if(hitcnt == usnhit)
break;
4391 fAveChg = fAveChg / (float)nht;
4396 float intcpterr = 0.;
4397 float slopeerr = 0.;
4399 fLinFitAlg.LinFit(xwir, ytim, ytimerr2, intcpt, slope, intcpterr, slopeerr, chidof);
4401 if(clChisq > fChiCut[0])
return;
4405 clparerr[0] = intcpterr;
4406 clparerr[1] = slopeerr;
4410 void ClusterCrawlerAlg::FitCluster()
4420 if(pass > fNumPass - 1) {
4421 mf::LogError(
"CC")<<
"FitCluster called on invalid pass "<<pass;
4425 unsigned short ii, nht = 0;
4427 nht = fcl2hits.size();
4430 if(nht > fLAClusMaxHitsFit) nht = fLAClusMaxHitsFit;
4432 if(nht > fMaxHitsFit[pass]) nht = fMaxHitsFit[pass];
4436 std::vector<float> xwir;
4437 std::vector<float> ytim;
4438 std::vector<float> ytimerr2;
4440 float angfactor = AngleFactor(clpar[1]);
4443 unsigned int wire0 = fHits[fcl2hits[fcl2hits.size()-1]].WireID().Wire;
4445 float terr, qave = 0, qwt;
4446 for(ii = 0; ii < nht; ++ii) {
4447 ihit = fcl2hits[fcl2hits.size() - 1 - ii];
4448 qave += fHits[ihit].Integral();
4451 for(ii = 0; ii < nht; ++ii) {
4452 ihit = fcl2hits[fcl2hits.size() - 1 - ii];
4453 wire = fHits[ihit].WireID().Wire;
4454 xwir.push_back(wire - wire0);
4455 ytim.push_back(fHits[ihit].PeakTime());
4458 terr = fHitErrFac * fHits[ihit].RMS() * fHits[ihit].Multiplicity();
4461 qwt = (fHits[ihit].Integral() / qave) - 1;
4462 if(qwt < 1) qwt = 1;
4465 if(terr < 0.01) terr = 0.01;
4466 ytimerr2.push_back(angfactor * terr * terr);
4468 CalculateAveHitWidth();
4471 myprt<<
"FitCluster W:T ";
4472 unsigned short cnt = 0;
4473 for(std::vector<unsigned int>::reverse_iterator it = fcl2hits.rbegin(); it != fcl2hits.rend(); ++it) {
4474 unsigned int ihit = *it;
4475 unsigned short wire = fHits[ihit].WireID().Wire;
4476 myprt<<wire<<
":"<<(short)fHits[ihit].PeakTime()<<
" ";
4485 if(xwir.size() < 2)
return;
4489 float intcpterr = 0.;
4490 float slopeerr = 0.;
4492 fLinFitAlg.LinFit(xwir, ytim, ytimerr2, intcpt, slope, intcpterr, slopeerr, chidof);
4494 if(chidof > fChiCut[0])
return;
4498 clparerr[0] = intcpterr;
4499 clparerr[1] = slopeerr;
4501 if(prt)
mf::LogVerbatim(
"CC")<<
"nht "<<nht<<
" fitpar "<<(int)clpar[0]<<
"+/-"<<(
int)intcpterr
4502 <<
" "<<clpar[1]<<
"+/-"<<slopeerr<<
" clChisq "<<clChisq;
4506 float ClusterCrawlerAlg::AngleFactor(
float slope)
4511 float slp = std::abs(slope);
4512 if(slp > 15) slp = 15;
4514 float angfac = 1 + 0.03 * slp * slp;
4519 void ClusterCrawlerAlg::CalculateAveHitWidth()
4522 for(
unsigned short ii = 0; ii < fcl2hits.size(); ++ii)
4523 fAveHitWidth += fHits[fcl2hits[ii]].EndTick() - fHits[fcl2hits[ii]].StartTick();
4524 fAveHitWidth /= (float)fcl2hits.size();
4528 void ClusterCrawlerAlg::FitClusterChg()
4533 if(fcl2hits.size() == 0)
return;
4534 unsigned int ih0 = fcl2hits.size() - 1;
4536 if(pass >= fNumPass) {
4545 unsigned short nhave = fLAClusMaxHitsFit;
4546 if(nhave > fcl2hits.size()) nhave = fcl2hits.size();
4551 for(
unsigned short ii = 0; ii < nhave; ++ii) {
4552 iht = fcl2hits[fcl2hits.size() - 1 - ii];
4553 fAveChg += fHits[iht].Integral();
4554 fAveHitWidth += (fHits[iht].EndTick() - fHits[iht].StartTick());
4556 fAveChg /= (float)fcl2hits.size();
4557 fAveHitWidth /= (float)fcl2hits.size();
4562 unsigned short fitLen = fNHitsAve[pass];
4566 fcl2hits.size() > 5 &&
4567 fcl2hits.size() < fitLen)
4571 if(fNHitsAve[pass] < 1)
return;
4573 if(fNHitsAve[pass] == 1) {
4575 fAveChg = fHits[fcl2hits[ih0]].Integral();
4577 }
else if(fNHitsAve[pass] == 2) {
4579 fAveChg = (fHits[fcl2hits[ih0]].Integral() +
4580 fHits[fcl2hits[ih0 - 1]].Integral()) / 2.;
4582 }
else if((
unsigned short)fcl2hits.size() > fitLen){
4584 std::vector<float> xwir;
4585 std::vector<float> ychg;
4586 std::vector<float> ychgerr2;
4588 unsigned int wire0 = fHits[fcl2hits[fcl2hits.size()-1]].WireID().Wire;
4590 unsigned short npt = 0;
4591 unsigned short imlast = 0;
4595 for(
unsigned int ii = fcl2hits.size() - 1; ii > 0; --ii) {
4597 float chg = fHits[fcl2hits[ii]].Integral();
4607 rms = std::sqrt((rms - fnpt * ave * ave) / (fnpt - 1));
4608 float chgcut = ave + rms;
4611 for(
unsigned short ii = fcl2hits.size() - 1; ii > imlast; --ii) {
4612 wire = fHits[fcl2hits[ii]].WireID().Wire;
4613 chg = fHits[fcl2hits[ii]].Integral();
4614 if(chg > chgcut)
continue;
4615 xwir.push_back((
float)(wire - wire0));
4616 ychg.push_back(chg);
4617 ychgerr2.push_back(chg);
4619 if(ychg.size() < 3)
return;
4620 float intcpt;
float slope;
float intcpterr;
4621 float slopeerr;
float chidof;
4622 fLinFitAlg.LinFit(xwir, ychg, ychgerr2, intcpt, slope, intcpterr, slopeerr, chidof);
4624 <<
" chidof "<<(int)chidof<<
" npt "<<xwir.size()
4625 <<
" charge = "<<(int)intcpt<<
" slope = "<<(
int)slope
4626 <<
" first ave "<<(int)ave<<
" rms "<<(
int)rms;
4627 if(chidof > 100.)
return;
4630 if(intcpt > ave)
return;
4633 ave = intcpt / fAveChg;
4634 if(ave > 1.3)
return;
4635 if(ave < 0.77)
return;
4643 void ClusterCrawlerAlg::AddLAHit(
unsigned int kwire,
bool& ChkCharge,
bool& HitOK,
bool& SigOK)
4651 if(kwire < fFirstWire || kwire > fLastWire)
return;
4653 if(fcl2hits.size() == 0)
return;
4656 if(WireHitRange[kwire].first == -1) {
4661 if(WireHitRange[kwire].first == -2)
return;
4663 unsigned int firsthit = WireHitRange[kwire].first;
4664 unsigned int lasthit = WireHitRange[kwire].second;
4667 float timeDiff = 40 * AngleFactor(clpar[1]);
4671 unsigned int lastClHit = UINT_MAX;
4672 if(fcl2hits.size() > 0) {
4673 lastClHit = fcl2hits[fcl2hits.size()-1];
4674 if(lastClHit == 0) {
4675 fAveChg = fHits[lastClHit].Integral();
4676 fAveHitWidth = fHits[lastClHit].EndTick() - fHits[lastClHit].StartTick();
4681 float prtime = clpar[0] + ((float)kwire - clpar[2]) * clpar[1];
4682 float chgWinLo = prtime - fChgNearWindow;
4683 float chgWinHi = prtime + fChgNearWindow;
4684 float chgrat, hitWidth;
4685 float hitWidthCut = 0.5 * fAveHitWidth;
4688 if(prt)
mf::LogVerbatim(
"CC")<<
"AddLAHit: wire "<<kwire<<
" prtime "<<prtime<<
" max timeDiff "<<timeDiff<<
" fAveChg "<<fAveChg;
4689 unsigned int imbest = 0;
4691 for(khit = firsthit; khit < lasthit; ++khit) {
4693 if(inClus[khit] < 0)
continue;
4694 dtime = std::abs(fHits[khit].PeakTime() - prtime);
4696 hitWidth = fHits[khit].EndTick() - fHits[khit].StartTick();
4698 if(ChkCharge && fAveChg > 0) {
4699 chgrat = fHits[khit].Integral() / fAveChg;
4704 <<
" Chk W:T "<<kwire<<
":"<<(short)fHits[khit].PeakTime()
4705 <<
" dT "<<std::fixed<<std::setprecision(1)<<dtime
4706 <<
" InClus "<<inClus[khit]
4707 <<
" mult "<<fHits[khit].Multiplicity()
4708 <<
" width "<<(int)hitWidth
4709 <<
" MergeAvail "<<mergeAvailable[khit]
4710 <<
" Chi2 "<<std::fixed<<std::setprecision(2)<<fHits[khit].GoodnessOfFit()
4711 <<
" Charge "<<(int)fHits[khit].Integral()
4712 <<
" chgrat "<<std::fixed<<std::setprecision(1)<<chgrat
4718 if(fHits[khit].PeakTime() > chgWinLo && fHits[khit].PeakTime() < chgWinHi) cnear += fHits[khit].Integral();
4720 if(prtime < fHits[khit].StartTick() - timeDiff)
continue;
4721 if(prtime > fHits[khit].EndTick() + timeDiff)
continue;
4724 if(inClus[khit] > 0)
continue;
4726 if(hitWidth < hitWidthCut)
continue;
4728 if(chgrat < 0.1)
continue;
4730 if(dtime < timeDiff) {
4741 if(prt)
mf::LogVerbatim(
"CC")<<
" Pick hit time "<<(int)fHits[imbest].PeakTime()<<
" hit index "<<imbest;
4745 if(lastClHit != UINT_MAX && fHits[imbest].Multiplicity() > 1) {
4746 bool doMerge =
true;
4749 for(
unsigned short ivx = 0; ivx < vtx.size(); ++ivx) {
4750 if(vtx[ivx].CTP != clCTP)
continue;
4751 if(prt)
mf::LogVerbatim(
"CC")<<
" close vtx chk W:T "<<vtx[ivx].Wire<<
":"<<(int)vtx[ivx].Time;
4752 if(std::abs(kwire - vtx[ivx].Wire) < 5 && std::abs(
int(fHits[imbest].PeakTime() - vtx[ivx].Time)) < 20 ) {
4753 if(prt)
mf::LogVerbatim(
"CC")<<
" Close to a vertex. Don't merge hits";
4760 unsigned short nused = 0;
4762 float multipletChg = 0.;
4763 float chicut = AngleFactor(clpar[1]) * fHitMergeChiCut * fHits[lastClHit].RMS();
4765 std::pair<size_t, size_t> MultipletRange = FindHitMultiplet(imbest);
4766 for(
size_t jht = MultipletRange.first; jht < MultipletRange.second; ++jht) {
4767 if(inClus[jht] < 0)
continue;
4768 if(inClus[jht] == 0) multipletChg += fHits[jht].Integral();
4771 if(jht > MultipletRange.first) {
4773 float hitRMS = fHits[jht].RMS();
4774 if(fHits[jht - 1].RMS() > hitRMS) hitRMS = fHits[jht-1].RMS();
4775 const float tdiff = std::abs(fHits[jht].PeakTime() - fHits[jht-1].PeakTime()) / hitRMS;
4776 if(prt)
mf::LogVerbatim(
"CC")<<
" Hit RMS chisq "<<tdiff<<
" chicut "<<chicut;
4777 if(tdiff > chicut) doMerge =
false;
4782 <<
" Hits are well separated. Don't merge them ";
4784 if(doMerge && nused == 0) {
4789 float chgrat = multipletChg / fHits[lastClHit].Integral();
4791 <<(int)multipletChg<<
" Previous hit charge "<<(
int)fHits[lastClHit].Integral();
4792 if(chgrat > 2) doMerge =
false;
4800 MergeHits(imbest, didMerge);
4805 fcl2hits.push_back(imbest);
4808 chifits.push_back(clChisq);
4809 hitNear.push_back(hnear);
4811 cnear -= fHits[imbest].Integral();
4812 if(cnear < 0) cnear = 0;
4814 cnear /= fHits[imbest].Integral();
4815 chgNear.push_back(cnear);
4817 hitWidth = fHits[imbest].EndTick() - fHits[imbest].StartTick();
4819 <<
" >>LADD"<<pass<<
" W:T "<<
PrintHit(imbest)
4821 <<
" clChisq "<<clChisq
4822 <<
" Chg "<<(int)fHits[imbest].Integral()
4823 <<
" AveChg "<<(int)fAveChg
4824 <<
" width "<<(
int)hitWidth
4825 <<
" AveWidth "<<(int)fAveHitWidth
4826 <<
" fcl2hits size "<<fcl2hits.size();
4829 if(clChisq > fChiCut[pass]) {
4835 if(prt)
mf::LogVerbatim(
"CC")<<
" LADD- Removed bad hit. Stopped tracking";
4847 bool ClusterCrawlerAlg::ClusterHitsOK(
short nHitChk)
4860 if(fcl2hits.size() == 0)
return true;
4863 unsigned short nHitToChk = fcl2hits.size();
4864 if(nHitChk > 0) nHitToChk = nHitChk + 1;
4865 unsigned short ii, indx;
4871 if(plane < geom->Cryostat(cstat).TPC(tpc).Nplanes()-1) tol = 40;
4873 bool posSlope = (fHits[fcl2hits[0]].PeakTime() > fHits[fcl2hits[fcl2hits.size() - 1]].PeakTime());
4876 for(ii = 0; ii < nHitToChk; ++ii) {
4877 indx = fcl2hits.size() - 1 - ii;
4878 mf::LogVerbatim(
"CC")<<
"ClusterHitsOK chk "<<fHits[fcl2hits[indx]].WireID().Wire<<
" start "<<fHits[fcl2hits[indx]].StartTick()<<
" peak "<<fHits[fcl2hits[indx]].PeakTime()<<
" end "<<fHits[fcl2hits[indx]].EndTick()<<
" posSlope "<<posSlope;
4883 for(ii = 0; ii < nHitToChk - 1; ++ii) {
4884 indx = fcl2hits.size() - 1 - ii;
4886 if(
util::absDiff(fHits[fcl2hits[indx]].WireID().Wire, fHits[fcl2hits[indx-1]].WireID().Wire) > 1)
continue;
4887 hiStartTick =
std::max(fHits[fcl2hits[indx]].StartTick(), fHits[fcl2hits[indx-1]].StartTick());
4888 loEndTick =
std::min(fHits[fcl2hits[indx]].EndTick(), fHits[fcl2hits[indx-1]].EndTick());
4890 if(loEndTick + tol < hiStartTick) {
4895 if(loEndTick + tol < hiStartTick) {
4907 void ClusterCrawlerAlg::AddHit(
unsigned int kwire,
bool& HitOK,
bool& SigOK)
4918 if(kwire < fFirstWire || kwire > fLastWire)
return;
4920 unsigned int lastClHit = UINT_MAX;
4921 if(fcl2hits.size() > 0) lastClHit = fcl2hits[fcl2hits.size()-1];
4924 unsigned int wire0 = clpar[2];
4927 if(fAllowNoHitWire == 0) {
4928 if(WireHitRange[kwire].first == -2)
return;
4931 if(WireHitRange[kwire].first == -2 &&
4932 (wire0 - kwire) > fAllowNoHitWire) {
4938 if(WireHitRange[kwire].first == -1) {
4943 unsigned int firsthit = WireHitRange[kwire].first;
4944 unsigned int lasthit = WireHitRange[kwire].second;
4947 float dw = (float)kwire - (
float)wire0;
4948 float prtime = clpar[0] + dw * clpar[1];
4949 if(prtime < 0 || (
unsigned int)prtime > fMaxTime)
return;
4952 float prtimerr2 = std::abs(dw)*clparerr[1]*clparerr[1];
4956 if(lastClHit != UINT_MAX) hiterr = 3 * fHitErrFac * fHits[lastClHit].RMS();
4957 float err = std::sqrt(prtimerr2 + hiterr * hiterr);
4959 float hitWin = fClProjErrFac * err;
4961 float prtimeLo = prtime - hitWin;
4962 float prtimeHi = prtime + hitWin;
4963 float chgWinLo = prtime - fChgNearWindow;
4964 float chgWinHi = prtime + fChgNearWindow;
4966 mf::LogVerbatim(
"CC")<<
"AddHit: wire "<<kwire<<
" prtime Lo "<<(int)prtimeLo<<
" prtime "<<(
int)prtime<<
" Hi "<<(int)prtimeHi<<
" prtimerr "<<sqrt(prtimerr2)<<
" hiterr "<<hiterr<<
" fAveChg "<<(int)fAveChg<<
" fAveHitWidth "<<std::setprecision(3)<<fAveHitWidth;
4969 unsigned int imbest = INT_MAX;
4970 float best = 9999., dtime;
4972 float hitTime, hitChg, hitStartTick, hitEndTick;
4973 for(
unsigned int khit = firsthit; khit < lasthit; ++khit) {
4975 if(inClus[khit] < 0)
continue;
4976 hitTime = fHits[khit].PeakTime();
4977 dtime = std::abs(hitTime - prtime);
4978 if(dtime > 1000)
continue;
4979 hitStartTick = fHits[khit].StartTick();
4980 hitEndTick = fHits[khit].EndTick();
4982 if(fAveChg > 0) dtime *= std::abs(fHits[khit].Integral() - fAveChg) / fAveChg;
4983 if(prt && std::abs(dtime) < 100) {
4986 <<
" dT "<<std::fixed<<std::setprecision(1)<<(hitTime - prtime)
4987 <<
" InClus "<<inClus[khit]
4988 <<
" mult "<<fHits[khit].Multiplicity()
4989 <<
" RMS "<<std::fixed<<std::setprecision(1)<<fHits[khit].RMS()
4990 <<
" Chi2 "<<std::fixed<<std::setprecision(1)<<fHits[khit].GoodnessOfFit()
4991 <<
" Charge "<<(int)fHits[khit].Integral()
4992 <<
" Peak "<<std::fixed<<std::setprecision(1)<<fHits[khit].PeakAmplitude()
4993 <<
" LoT "<<(int)hitStartTick
4994 <<
" HiT "<<(
int)hitEndTick
4995 <<
" index " << khit;
4998 if(fHits[khit].StartTick() > chgWinLo && fHits[khit].EndTick() < chgWinHi) cnear += fHits[khit].Integral();
5000 if(prtimeHi < hitStartTick)
continue;
5001 if(prtimeLo > hitEndTick)
continue;
5004 if(hitTime < prtimeLo)
continue;
5005 if(hitTime > prtimeHi)
continue;
5007 if(inClus[khit] > 0)
continue;
5015 if(fAllowNoHitWire == 0)
return;
5016 if(prt)
mf::LogVerbatim(
"CC")<<
" wire0 "<<wire0<<
" kwire "<<kwire<<
" max "<<fAllowNoHitWire<<
" imbest "<<imbest;
5017 if((wire0 - kwire) > fAllowNoHitWire)
return;
5021 if(imbest == INT_MAX)
return;
5030 bool didMerge =
false;
5031 if(lastClHit != UINT_MAX && fAveHitWidth > 0 && fHitMergeChiCut > 0 && hit.
Multiplicity() == 2) {
5032 bool doMerge =
true;
5033 for(
unsigned short ivx = 0; ivx < vtx.size(); ++ivx) {
5034 if(std::abs(kwire - vtx[ivx].Wire) < 10 &&
5035 std::abs(
int(hit.
PeakTime() - vtx[ivx].Time)) < 20 )
5042 if (hit.
LocalIndex() != 0 && imbest == 0) doMerge =
false;
5054 hitSep /= hit.
RMS();
5056 float totChg = hitChg + other_hit.
Integral();
5057 float lastHitChg = fAveChg;
5058 if(lastHitChg < 0) lastHitChg = fHits[lastClHit].Integral();
5060 if(prt)
mf::LogVerbatim(
"CC")<<
" Chk hit merge hitsep "<<hitSep<<
" dChg "<<std::abs(totChg - lastHitChg)<<
" Cut "<<std::abs(hit.
Integral() - lastHitChg);
5062 if(inClus[oht] == 0 && hitSep < fHitMergeChiCut) {
5064 MergeHits(imbest, didMerge);
5074 float chgrat = (hitChg - fAveChg) / fAveChg;
5075 if(prt)
mf::LogVerbatim(
"CC")<<
" Chgrat "<<std::setprecision(2)<<chgrat;
5078 if(chgrat > 3 * fChgCut[pass]) {
5079 if(prt)
mf::LogVerbatim(
"CC")<<
" fails 3 x high charge cut "<<fChgCut[pass]<<
" on pass "<<pass;
5086 float bigchgcut = 1.5 * fChgCut[pass];
5087 bool lasthitbig =
false;
5088 bool lasthitlow =
false;
5089 if(lastClHit != UINT_MAX &&
util::absDiff(wire0, kwire) == 1) {
5090 float lastchgrat = (fHits[lastClHit].Integral() - fAveChg) / fAveChg;
5091 lasthitbig = ( lastchgrat > bigchgcut);
5092 lasthitlow = ( lastchgrat < -fChgCut[pass]);
5096 if(lasthitlow && chgrat < -fChgCut[pass]) {
5097 if(prt)
mf::LogVerbatim(
"CC")<<
" fails low charge cut. Stop crawling.";
5103 if(lasthitbig && chgrat > fChgCut[pass]) {
5104 if(prt)
mf::LogVerbatim(
"CC")<<
" fails 2nd hit high charge cut. Last hit was high also. ";
5110 if(chgrat > fChgCut[pass]) {
5111 if(best > 2 * err) {
5112 if(prt)
mf::LogVerbatim(
"CC")<<
" high charge && bad dT= "<<best<<
" err= "<<err;
5118 fitChg = (chgrat < std::abs(fChgCut[pass]) );
5122 fcl2hits.push_back(imbest);
5124 if(fcl2hits.size() == 3) std::sort(fcl2hits.begin(), fcl2hits.end(),
SortByLowHit);
5126 chifits.push_back(clChisq);
5127 hitNear.push_back(hnear);
5129 cnear -= fHits[imbest].Integral();
5130 if(cnear < 0) cnear = 0;
5132 cnear /= fHits[imbest].Integral();
5133 chgNear.push_back(cnear);
5138 if(chgNear.size() != fcl2hits.size()) {
5145 <<
" dT "<<best<<
" clChisq "<<clChisq
5146 <<
" Chg "<<(int)fHits[imbest].Integral()
5147 <<
" AveChg "<<(int)fAveChg
5149 <<
" fcl2hits size "<<fcl2hits.size();
5158 void ClusterCrawlerAlg::ChkClusterNearbyHits(
bool prt)
5165 if(fHitMergeChiCut <= 0)
return;
5167 if(hitNear.size() != fcl2hits.size()) {
5173 if(hitNear.size() < 12)
return;
5176 unsigned short ii, indx;
5177 unsigned short merged = 0;
5178 unsigned short notmerged = 0;
5179 for(ii = 0; ii < 6; ++ii) {
5180 indx = hitNear.size() - 1 - ii;
5181 if(hitNear[indx] > 0) ++notmerged;
5182 if(hitNear[indx] < 0) ++merged;
5185 if(prt)
mf::LogVerbatim(
"CC")<<
"ChkClusterNearbyHits: nearby hits merged "<<merged<<
" not merged "<<notmerged;
5187 if(notmerged < 2)
return;
5193 for(ii = 0; ii < 6; ++ii) {
5194 indx = fcl2hits.size() - 1 - ii;
5195 const unsigned int iht = fcl2hits[indx];
5199 if (hit.
LocalIndex() != 0 && iht == 0)
continue;
5210 hitSep /= hit.
RMS();
5211 if(hitSep < fHitMergeChiCut && inClus[oht] == 0) {
5213 <<iht<<
" W:T "<<fHits[iht].WireID().Wire<<
":"<<fHits[iht].PeakTime();
5214 MergeHits(iht, didMerge);
5215 if(didMerge) hitNear[indx] = -1;
5224 if(prt)
mf::LogVerbatim(
"CC")<<
"ChkClusterNearbyHits refit cluster. fAveChg= "<<fAveChg;
5229 void ClusterCrawlerAlg::FitVtx(
unsigned short iv)
5231 std::vector<float>
x;
5232 std::vector<float>
y;
5233 std::vector<float> ey2;
5237 if(vtx[iv].Fixed)
return;
5240 vtx[iv].ChiDOF = 99;
5244 std::vector<unsigned short> vcl;
5245 for(icl = 0; icl < tcl.size(); ++icl) {
5246 if(tcl[icl].ID < 0)
continue;
5247 if(tcl[icl].CTP != vtx[iv].CTP)
continue;
5248 if(tcl[icl].EndVtx == iv) vcl.push_back(icl);
5249 if(tcl[icl].BeginVtx == iv) vcl.push_back(icl);
5252 vtx[iv].NClusters = vcl.size();
5254 if(vcl.size() == 0)
return;
5260 unsigned short indx = tcl[icl].tclhits.size() - 1;
5261 unsigned int hit = tcl[icl].tclhits[indx];
5262 float minTimeErr = fHitErrFac * fHits[hit].RMS() * fHits[hit].Multiplicity();
5264 if(vcl.size() == 1) {
5267 if(tcl[icl].EndVtx == iv) {
5268 vtx[iv].Wire = tcl[icl].EndWir;
5269 vtx[iv].WireErr = 1;
5270 vtx[iv].Time = tcl[icl].EndTim;
5272 indx = tcl[icl].tclhits.size() - 1;
5273 hit = tcl[icl].tclhits[indx];
5274 vtx[iv].TimeErr = fHitErrFac * fHits[hit].RMS() * fHits[hit].Multiplicity();
5277 if(tcl[icl].BeginVtx == iv) {
5278 vtx[iv].Wire = tcl[icl].BeginWir;
5279 vtx[iv].WireErr = 1;
5280 vtx[iv].Time = tcl[icl].BeginTim;
5282 hit = tcl[icl].tclhits[0];
5283 vtx[iv].TimeErr = fHitErrFac * fHits[hit].RMS() * fHits[hit].Multiplicity();
5289 std::vector<double> slps;
5290 std::vector<double> slperrs;
5291 for(
unsigned short ii = 0; ii < vcl.size(); ++ii) {
5293 if(tcl[icl].EndVtx == iv) {
5294 x.push_back(tcl[icl].EndSlp);
5295 slps.push_back(tcl[icl].EndSlp);
5296 slperrs.push_back(tcl[icl].EndSlpErr);
5297 arg = tcl[icl].EndSlp * tcl[icl].EndWir - tcl[icl].EndTim;
5299 if(tcl[icl].EndSlpErr > 0.) {
5300 arg = tcl[icl].EndSlpErr * tcl[icl].EndWir;
5302 arg = .1 * tcl[icl].EndWir;
5304 ey2.push_back(arg * arg);
5305 }
else if(tcl[icl].BeginVtx == iv) {
5306 x.push_back(tcl[icl].BeginSlp);
5307 slps.push_back(tcl[icl].BeginSlp);
5308 slperrs.push_back(tcl[icl].BeginSlpErr);
5309 arg = tcl[icl].BeginSlp * tcl[icl].BeginWir - tcl[icl].BeginTim;
5311 if(tcl[icl].BeginSlpErr > 0.) {
5312 arg = tcl[icl].BeginSlpErr * tcl[icl].BeginWir;
5314 arg = .1 * tcl[icl].BeginWir;
5316 ey2.push_back(arg * arg);
5319 if(x.size() < 2)
return;
5322 double sumerr = 0, cnt = 0;
5323 for(
unsigned short ii = 0; ii < slps.size() - 1; ++ii) {
5324 for(
unsigned short jj = ii + 1; jj < slps.size(); ++jj) {
5325 arg =
std::min(slperrs[ii], slperrs[jj]);
5326 arg /= (slps[ii] - slps[jj]);
5327 sumerr += arg * arg;
5334 float vTimeErr = 0.;
5336 float vWireErr = 0.;
5338 fLinFitAlg.LinFit(x, y, ey2, vTime, vWire, vTimeErr, vWireErr, chiDOF);
5339 if(chiDOF > 900)
return;
5342 if(vTime < 0 || vTime > fMaxTime)
return;
5345 if(vWire < 0 || vWire > geom->Nwires(iplID.
Plane, iplID.
TPC, iplID.
Cryostat))
return;
5346 vtx[iv].ChiDOF = chiDOF;
5347 vtx[iv].Wire = vWire;
5348 vtx[iv].Time = vTime;
5349 vtx[iv].WireErr = vWire * sqrt(sumerr);
5350 vtx[iv].TimeErr = vTime * fabs(sumerr);
5354 if(vtx[iv].WireErr < 1) vtx[iv].WireErr = 2;
5356 if(vtx[iv].TimeErr < minTimeErr) vtx[iv].TimeErr = minTimeErr;
5361 void ClusterCrawlerAlg::Vtx3ClusterMatch(
geo::TPCID const& tpcid)
5365 if(vtx3.size() == 0)
return;
5367 const unsigned int cstat = tpcid.
Cryostat;
5368 const unsigned int tpc = tpcid.
TPC;
5370 unsigned int thePlane, theWire;
5376 for(
unsigned short ivx = 0; ivx < vtx3.size(); ++ivx) {
5378 if(vtx3[ivx].Wire < 0)
continue;
5379 if(vtx3[ivx].CStat != cstat || vtx3[ivx].TPC != tpc)
continue;
5382 theWire = vtx3[ivx].Wire;
5383 for(plane = 0; plane < 3; ++plane) {
5384 if(vtx3[ivx].Ptr2D[plane] >= 0)
continue;
5388 if(thePlane > 2)
continue;
5390 clCTP =
EncodeCTP(cstat, tpc, thePlane);
5393 vnew.
Wire = theWire;
5394 vnew.
Time = theTime;
5398 vtx.push_back(vnew);
5399 unsigned short ivnew = vtx.size() -1;
5400 std::vector<short> vclIndex;
5401 for(
unsigned short icl = 0; icl < tcl.size(); ++icl) {
5402 if(tcl[icl].ID < 0)
continue;
5403 if(tcl[icl].CTP != clCTP)
continue;
5407 if(dwb > 10 && dwe > 10)
continue;
5408 if(dwb < dwe && dwb < 10 && tcl[icl].BeginVtx < 0) {
5410 if(theWire < tcl[icl].BeginWir + 5)
continue;
5411 if(ClusterVertexChi(icl, 0, ivnew) > fVertex3DCut)
continue;
5412 tcl[icl].BeginVtx = ivnew;
5413 vclIndex.push_back(icl);
5414 }
else if(dwe < 10 && tcl[icl].EndVtx < 0) {
5416 if(theWire > tcl[icl].EndWir - 5)
continue;
5417 if(ClusterVertexChi(icl, 1, ivnew) > fVertex3DCut)
continue;
5418 tcl[icl].EndVtx = ivnew;
5419 vclIndex.push_back(icl);
5422 bool goodVtx =
false;
5423 if(vclIndex.size() > 0) {
5425 goodVtx = (vtx[ivnew].ChiDOF < fVertex3DCut);
5426 vtx3[ivx].Ptr2D[thePlane] = ivnew;
5429 vtx3[ivx].Ptr2D[thePlane] = ivnew;
5430 vtx3[ivx].Wire = -1;
5434 for(
unsigned short ii = 0; ii < vclIndex.size(); ++ii) {
5435 unsigned short icl = vclIndex[ii];
5436 if(tcl[icl].BeginVtx == ivnew) tcl[icl].BeginVtx = -99;
5437 if(tcl[icl].EndVtx == ivnew) tcl[icl].EndVtx = -99;
5444 void ClusterCrawlerAlg::Vtx3ClusterSplit(
geo::TPCID const& tpcid)
5448 if(vtx3.size() == 0)
return;
5449 const unsigned int cstat = tpcid.
Cryostat;
5450 const unsigned int tpc = tpcid.
TPC;
5452 vtxprt = (fDebugPlane >= 0) && (fDebugHit == 6666);
5454 unsigned int lastplane = 5, kcl, kclID;
5456 unsigned int thePlane, theWire, plane;
5457 unsigned int loWire, hiWire;
5461 for(
unsigned short ivx = 0; ivx < vtx3.size(); ++ivx) {
5462 if(vtx3[ivx].CStat != cstat || vtx3[ivx].TPC != tpc)
continue;
5464 if(vtxprt)
mf::LogVerbatim(
"CC")<<
"Vtx3ClusterSplit ivx "<<ivx<<
" Ptr2D "<<vtx3[ivx].Ptr2D[0]<<
" "<<vtx3[ivx].Ptr2D[1]<<
" "<<vtx3[ivx].Ptr2D[2]<<
" wire "<<vtx3[ivx].Wire;
5465 if(vtx3[ivx].Wire < 0)
continue;
5468 theWire = vtx3[ivx].Wire;
5469 for(plane = 0; plane < 3; ++plane) {
5470 if(vtx3[ivx].Ptr2D[plane] >= 0)
continue;
5474 if(thePlane > 2)
continue;
5476 (
int)thePlane, (
int)tpcid.
TPC, (
int)tpcid.
Cryostat);
5478 if(thePlane != lastplane) {
5481 lastplane = thePlane;
5484 std::vector<short> clIDs;
5485 if(theWire > fFirstWire + 5) { loWire = theWire - 5; }
else { loWire = fFirstWire; }
5486 if(theWire < fLastWire - 5) { hiWire = theWire + 5; }
else { hiWire = fLastWire; }
5487 if(vtxprt)
mf::LogVerbatim(
"CC")<<
"3DVtx "<<ivx<<
" look for cluster hits near P:W:T "<<thePlane<<
":"<<theWire<<
":"<<(int)theTime<<
" Wire range "<<loWire<<
" to "<<hiWire;
5488 for(
unsigned int wire = loWire; wire < hiWire; ++wire) {
5490 if(WireHitRange[wire].first < 0)
continue;
5491 unsigned int firsthit = WireHitRange[wire].first;
5492 unsigned int lasthit = WireHitRange[wire].second;
5493 for(
unsigned int khit = firsthit; khit < lasthit; ++khit) {
5495 if(inClus[khit] <= 0)
continue;
5496 if((
unsigned int)inClus[khit] > tcl.size() + 1) {
5497 mf::LogError(
"CC")<<
"Invalid hit InClus. "<<khit<<
" "<<inClus[khit];
5501 if(theTime < fHits[khit].StartTick() - 20)
continue;
5502 if(theTime > fHits[khit].EndTick() + 20)
continue;
5503 kclID = inClus[khit];
5506 if(tcl[kcl].ID < 0)
continue;
5508 if(tcl[kcl].tclhits.size() < 6)
continue;
5510 if(tcl[kcl].tclhits.size() > 100 && std::abs(tcl[kcl].BeginAng - tcl[kcl].EndAng) < 0.1)
continue;
5512 if(vtxprt)
mf::LogVerbatim(
"CC")<<
"Bingo "<<ivx<<
" plane "<<thePlane<<
" wire "<<wire<<
" hit "<<fHits[khit].WireID().Wire<<
":"<<(int)fHits[khit].PeakTime()<<
" inClus "<<inClus[khit]<<
" P:W:T "<<thePlane<<
":"<<tcl[kcl].BeginWir<<
":"<<(int)tcl[kcl].BeginTim;
5513 if(std::find(clIDs.begin(), clIDs.end(), kclID) == clIDs.end()) {
5514 clIDs.push_back(kclID);
5518 if(clIDs.size() == 0)
continue;
5519 if(vtxprt)
for(
unsigned int ii = 0; ii < clIDs.size(); ++ii)
mf::LogVerbatim(
"CC")<<
" clIDs "<<clIDs[ii];
5521 unsigned short ii, icl, jj;
5528 unsigned short i2Dvx = 0;
5529 for(ii = 0; ii < 3; ++ii) {
5530 if(ii == thePlane)
continue;
5531 i2Dvx = vtx3[ivx].Ptr2D[ii];
5532 if(i2Dvx > vtx.size() - 1) {
5536 if(vtx[i2Dvx].TimeErr > tErr) tErr = vtx[i2Dvx].TimeErr;
5540 for(ii = 0; ii < clIDs.size(); ++ii) {
5541 icl = clIDs[ii] - 1;
5543 for(jj = 0; jj < tcl[icl].tclhits.size(); ++jj) {
5544 iht = tcl[icl].tclhits[jj];
5545 if(fHits[iht].WireID().Wire < theWire) {
5547 if(jj > 3) nhitfit = -3;
5548 FitClusterMid(icl, iht, nhitfit);
5549 float doca = DoCA(-1, 1, theWire, theTime);
5550 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" cls "<<icl<<
" dth "<<dth<<
" DoCA "<<doca<<
" tErr "<<tErr;
5551 if((doca / tErr) > 2) clIDs[ii] = -1;
5561 for(ii = 0; ii < clIDs.size(); ++ii)
mf::LogVerbatim(
"CC")<<
" clIDs "<<clIDs[ii];
5565 unsigned short nok = 0;
5566 for(ii = 0; ii < clIDs.size(); ++ii)
if(clIDs[ii] >= 0) ++nok;
5567 if(nok == 0)
continue;
5571 vnew.
Wire = theWire;
5573 vnew.
Time = theTime;
5578 vtx.push_back(vnew);
5580 unsigned short ivnew = vtx.size() - 1;
5581 if(vtxprt)
mf::LogVerbatim(
"CC")<<
"Make new 2D vtx "<<ivnew<<
" in plane "<<thePlane<<
" from 3D vtx "<<ivx;
5582 vtx3[ivx].Ptr2D[thePlane] = ivnew;
5584 for(ii = 0; ii < clIDs.size(); ++ii) {
5585 if(clIDs[ii] < 0)
continue;
5586 icl = clIDs[ii] - 1;
5589 unsigned short pos = 0;
5590 for(
unsigned short jj = 0; jj < tcl[icl].tclhits.size(); ++jj) {
5591 iht = tcl[icl].tclhits[jj];
5592 if(fHits[iht].WireID().Wire < theWire) {
5599 tcl[icl].BeginVtx = ivnew;
5601 }
else if(pos > tcl[icl].tclhits.size()) {
5603 tcl[icl].EndVtx = ivnew;
5607 if(vtxprt)
mf::LogVerbatim(
"CC")<<
"Split cluster "<<clIDs[ii]<<
" at pos "<<pos;
5608 if(!SplitCluster(icl, pos, ivnew)) {
5612 tcl[icl].ProcCode += 10000;
5613 tcl[tcl.size()-1].ProcCode += 10000;
5618 if(vtx[ivnew].ChiDOF < 5 && vtx[ivnew].WireErr < fVertex2DWireErrCut) {
5620 vtx3[ivx].Wire = -1;
5622 if(vtxprt)
mf::LogVerbatim(
"CC")<<
"Bad vtx fit "<<ivnew<<
" ChiDOF "<<vtx[ivnew].ChiDOF<<
" WireErr "<<vtx[ivnew].WireErr;
5625 vtx3[ivx].Ptr2D[thePlane] = -1;
5627 for(jj = 0; jj < tcl.size(); ++jj) {
5628 if(tcl[jj].BeginVtx == ivnew) tcl[jj].BeginVtx = -99;
5629 if(tcl[jj].EndVtx == ivnew) tcl[jj].EndVtx = -99;
5638 void ClusterCrawlerAlg::FindHammerClusters()
5645 unsigned int nPln = geom->Cryostat(cstat).TPC(tpc).Nplanes();
5646 if(nPln != 3)
return;
5648 float ew1, ew2, bw2, fvw;
5655 unsigned short longClIndex;
5656 unsigned short shortClIndex;
5657 unsigned short splitPos;
5659 std::array< std::vector<Hammer>, 3> hamrVec;
5665 for(ipl = 0; ipl < 3; ++ipl) {
5667 for(
unsigned short ic1 = 0; ic1 < tcl.size(); ++ic1) {
5668 if(tcl[ic1].ID < 0)
continue;
5670 if(tcl[ic1].tclhits.size() < 20)
continue;
5671 if(tcl[ic1].CTP != clCTP)
continue;
5673 if(tcl[ic1].EndVtx >= 0)
continue;
5674 ew1 = tcl[ic1].EndWir;
5675 for(
unsigned short ic2 = 0; ic2 < tcl.size(); ++ic2) {
5676 if(tcl[ic2].ID < 0)
continue;
5678 if(tcl[ic2].tclhits.size() > 20)
continue;
5680 if(tcl[ic2].tclhits.size() < 6)
continue;
5681 if(tcl[ic2].CTP != clCTP)
continue;
5682 ew2 = tcl[ic2].EndWir;
5683 bw2 = tcl[ic2].BeginWir;
5686 if(ew1 < ew2 || ew1 > bw2 )
continue;
5690 unsigned short spos = 0;
5691 for(
unsigned short ii = 0; ii < tcl[ic2].tclhits.size(); ++ii) {
5692 unsigned int iht = tcl[ic2].tclhits[ii];
5693 float dw = fHits[iht].WireID().Wire - tcl[ic1].EndWir;
5694 float dt = fabs(fHits[iht].PeakTime() - tcl[ic1].EndTim - tcl[ic1].EndSlp * dw);
5701 if(ibst < 0)
continue;
5702 fvw = 0.5 + fHits[ibst].WireID().Wire;
5705 aHam.Wire = (0.5 + fvw);
5706 aHam.Tick = fHits[ibst].PeakTime();
5707 aHam.X = detprop->
ConvertTicksToX((
double)aHam.Tick, (
int)ipl, (
int)tpc, (
int)cstat);
5709 aHam.longClIndex = ic1;
5710 aHam.shortClIndex = ic2;
5711 aHam.splitPos = spos;
5712 unsigned short indx = hamrVec[ipl].size();
5713 hamrVec[ipl].resize(indx + 1);
5714 hamrVec[ipl][indx] = aHam;
5722 unsigned short noham = 0;
5723 for(ipl = 0; ipl < 3; ++ipl)
if(hamrVec[ipl].size() == 0) ++noham;
5724 if(noham > 1)
return;
5727 double local[3] = {0.,0.,0.};
5728 double world[3] = {0.,0.,0.};
5730 const geo::TPCGeo &thetpc = geom->TPC(tpc, cstat);
5732 float YLo = world[1]-geom->DetHalfHeight(tpc,cstat) + 1;
5733 float YHi = world[1]+geom->DetHalfHeight(tpc,cstat) - 1;
5734 float ZLo = world[2]-geom->DetLength(tpc,cstat)/2 + 1;
5735 float ZHi = world[2]+geom->DetLength(tpc,cstat)/2 - 1;
5740 unsigned short icl, jpl, jcl, kpl, splitPos;
5741 for(ipl = 0; ipl < 3; ++ipl) {
5742 if(hamrVec[ipl].size() == 0)
continue;
5743 jpl = (ipl + 1) % nPln;
5744 kpl = (jpl + 1) % nPln;
5745 for(
unsigned short ii = 0; ii < hamrVec[ipl].size(); ++ii) {
5746 if(hamrVec[ipl][ii].Used)
continue;
5747 for(
unsigned short jj = 0; jj < hamrVec[jpl].size(); ++jj) {
5748 if(hamrVec[jpl][jj].Used)
continue;
5749 dX = hamrVec[ipl][ii].X - hamrVec[jpl][jj].X;
5750 if(fabs(dX) > fVertex3DCut)
continue;
5751 geom->IntersectionPoint(hamrVec[ipl][ii].Wire, hamrVec[jpl][jj].Wire, ipl, jpl, cstat, tpc, y, z);
5752 if(y < YLo || y > YHi || z < ZLo || z > ZHi)
continue;
5754 hamrVec[ipl][ii].Used =
true;
5755 hamrVec[jpl][jj].Used =
true;
5759 newVtx3.
X = 0.5 * (hamrVec[ipl][ii].X + hamrVec[jpl][jj].X);
5761 newVtx3.
XErr = fabs(hamrVec[ipl][ii].
X - hamrVec[jpl][jj].
X);
5766 newVtx3.
CStat = cstat;
5771 newVtx2.
Wire = hamrVec[ipl][ii].Wire;
5773 newVtx2.
Time = hamrVec[ipl][ii].Tick;
5776 newVtx2.
Fixed =
false;
5777 icl = hamrVec[ipl][ii].longClIndex;
5778 newVtx2.
CTP = tcl[icl].CTP;
5779 vtx.push_back(newVtx2);
5780 unsigned short ivnew = vtx.size() - 1;
5782 tcl[icl].EndVtx = ivnew;
5785 newVtx3.
Ptr2D[ipl] = (short)ivnew;
5787 icl = hamrVec[ipl][ii].shortClIndex;
5788 splitPos = hamrVec[ipl][ii].splitPos;
5789 if(!SplitCluster(icl, splitPos, ivnew))
return;
5792 newVtx2.
Wire = hamrVec[jpl][jj].Wire;
5793 newVtx2.
Time = hamrVec[jpl][jj].Tick;
5795 jcl = hamrVec[jpl][jj].longClIndex;
5796 newVtx2.
CTP = tcl[jcl].CTP;
5797 vtx.push_back(newVtx2);
5798 ivnew = vtx.size() - 1;
5801 tcl[jcl].EndVtx = ivnew;
5803 newVtx3.
Ptr2D[jpl] = (short)(vtx.size() - 1);
5805 jcl = hamrVec[jpl][jj].shortClIndex;
5806 splitPos = hamrVec[jpl][jj].splitPos;
5807 if(!SplitCluster(jcl, splitPos, vtx.size() - 1))
return;
5812 newVtx3.
Ptr2D[kpl] = -1;
5813 double WPos[3] = {0,
y, z};
5815 newVtx3.
Wire = geom->NearestWire(WPos, kpl, tpc, cstat);
5821 vtx3.push_back(newVtx3);
5839 const unsigned int cstat = tpcid.
Cryostat;
5840 const unsigned int tpc = tpcid.
TPC;
5843 double local[3] = {0.,0.,0.};
5844 double world[3] = {0.,0.,0.};
5846 const geo::TPCGeo &thetpc = geom->TPC(tpc, cstat);
5849 float YLo = world[1]-geom->DetHalfHeight(tpc,cstat) + 1;
5850 float YHi = world[1]+geom->DetHalfHeight(tpc,cstat) - 1;
5851 float ZLo = world[2]-geom->DetLength(tpc,cstat)/2 + 1;
5852 float ZHi = world[2]+geom->DetLength(tpc,cstat)/2 - 1;
5854 vtxprt = (fDebugPlane >= 0) && (fDebugHit == 6666);
5862 float wirePitch = geom->WirePitch(0, tpcid.
TPC, tpcid.
Cryostat);
5865 std::vector<float> vX(vtx.size());
5866 std::vector<float> vXsigma(vtx.size());
5868 for(
unsigned short ivx = 0; ivx < vtx.size(); ++ivx) {
5869 if(vtx[ivx].NClusters == 0)
continue;
5871 if(iplID.
TPC != tpc || iplID.
Cryostat != cstat)
continue;
5873 vX[ivx] = detprop->
ConvertTicksToX((
double)vtx[ivx].Time, (
int)iplID.
Plane, (
int)tpc, (
int)cstat);
5874 vXp = detprop->
ConvertTicksToX((
double)(vtx[ivx].Time + vtx[ivx].TimeErr), (
int)iplID.
Plane, (
int)tpc, (
int)cstat);
5875 vXsigma[ivx] = fabs(vXp - vX[ivx]);
5879 std::array<std::vector<unsigned short>, 3> vIndex;
5880 unsigned short indx, ipl;
5881 for(
unsigned short ivx = 0; ivx < vtx.size(); ++ivx) {
5882 if(vtx[ivx].NClusters == 0)
continue;
5884 if(iplID.
TPC != tpc || iplID.
Cryostat != cstat)
continue;
5886 if(ipl > 2)
continue;
5887 indx = vIndex[ipl].size();
5888 vIndex[ipl].resize(indx + 1);
5889 vIndex[ipl][indx] = ivx;
5893 std::vector<short> vPtr;
5894 for(
unsigned short ii = 0; ii < vtx.size(); ++ii) vPtr.push_back(-1);
5897 std::vector<Vtx3Store> v3temp;
5899 double y = 0,
z = 0;
5900 TVector3 WPos = {0, 0, 0};
5902 unsigned short ii, jpl, jj, kpl, kk, ivx, jvx, kvx;
5903 unsigned int iWire, jWire;
5904 unsigned short v3dBest = 0;
5905 float xbest = 0, ybest = 0, zbest = 0;
5909 for(ipl = 0; ipl < 2; ++ipl) {
5910 for(ii = 0; ii < vIndex[ipl].size(); ++ii) {
5911 ivx = vIndex[ipl][ii];
5912 if(ivx > vtx.size() - 1) {
5917 if(vPtr[ivx] >= 0)
continue;
5918 iWire = vtx[ivx].Wire;
5919 float best = fVertex3DCut;
5923 std::array<short, 3> t2dIndex = {{-1, -1, -1}};
5924 std::array<short, 3> tmpIndex = {{-1, -1, -1}};
5925 for(jpl = ipl + 1; jpl < 3; ++jpl) {
5926 for(jj = 0; jj < vIndex[jpl].size(); ++jj) {
5927 jvx = vIndex[jpl][jj];
5928 if(jvx > vtx.size() - 1) {
5933 if(vPtr[jvx] >= 0)
continue;
5934 jWire = vtx[jvx].Wire;
5936 float dX = fabs(vX[ivx] - vX[jvx]);
5937 float dXSigma = sqrt(vXsigma[ivx] * vXsigma[ivx] + vXsigma[jvx] * vXsigma[jvx]);
5938 float dXChi = dX / dXSigma;
5940 if(vtxprt)
mf::LogVerbatim(
"CC")<<
"VtxMatch: ipl "<<ipl<<
" ivx "<<ivx<<
" ivX "<<vX[ivx]
5941 <<
" jpl "<<jpl<<
" jvx "<<jvx<<
" jvX "<<vX[jvx]<<
" W:T "<<(int)vtx[jvx].Wire<<
":"<<(
int)vtx[jvx].Time<<
" dXChi "<<dXChi<<
" fVertex3DCut "<<fVertex3DCut;
5943 if(dXChi > fVertex3DCut)
continue;
5944 geom->IntersectionPoint(iWire, jWire, ipl, jpl, cstat, tpc, y,
z);
5945 if(y < YLo || y > YHi || z < ZLo || z > ZHi)
continue;
5948 kpl = 3 - ipl - jpl;
5949 kX = 0.5 * (vX[ivx] + vX[jvx]);
5953 kWire = geom->NearestWire(WPos, kpl, tpc, cstat);
5959 kpl = 3 - ipl - jpl;
5963 tmpIndex[ipl] = ivx;
5964 tmpIndex[jpl] = jvx;
5966 v3d.
Ptr2D = tmpIndex;
5970 float yzSigma = wirePitch * sqrt(vtx[ivx].WireErr * vtx[ivx].WireErr + vtx[jvx].WireErr * vtx[jvx].WireErr);
5977 v3temp.push_back(v3d);
5980 <<
"VtxMatch: 2 Plane match ivx "<<ivx<<
" P:W:T "<<ipl<<
":"<<(int)vtx[ivx].Wire<<
":"<<(
int)vtx[ivx].Time
5981 <<
" jvx "<<jvx<<
" P:W:T "<<jpl<<
":"<<(int)vtx[jvx].Wire<<
":"<<(
int)vtx[jvx].Time<<
" dXChi "<<dXChi<<
" yzSigma "<<yzSigma;
5983 if(TPC.
Nplanes() == 2)
continue;
5985 best = fVertex3DCut;
5986 for(kk = 0; kk < vIndex[kpl].size(); ++kk) {
5987 kvx = vIndex[kpl][kk];
5988 if(vPtr[kvx] >= 0)
continue;
5991 float dW = wirePitch * (vtx[kvx].Wire -
kWire) / yzSigma;
5993 float dX = (vX[kvx] -
kX) / dXSigma;
5994 float kChi = 0.5 * sqrt(dW * dW + dX * dX);
5997 xbest = (vX[kvx] + 2 *
kX) / 3;
6000 t2dIndex[ipl] = ivx;
6001 t2dIndex[jpl] = jvx;
6002 t2dIndex[kpl] = kvx;
6003 v3dBest = v3temp.size() - 1;
6007 <<
" wire "<<(int)vtx[kvx].Wire<<
" kTime "<<(
int)vtx[kvx].Time<<
" kChi "<<kChi<<
" best "<<best<<
" dW "<<vtx[kvx].Wire -
kWire;
6010 if(vtxprt)
mf::LogVerbatim(
"CC")<<
" done best = "<<best<<
" fVertex3DCut "<<fVertex3DCut;
6011 if(TPC.
Nplanes() > 2 && best < fVertex3DCut) {
6013 if(v3dBest > v3temp.size() - 1) {
6018 v3d.
Ptr2D = t2dIndex;
6024 vtx3.push_back(v3d);
6027 for(
unsigned short jj = 0; jj < 3; ++jj) if(t2dIndex[jj] >= 0) vPtr[t2dIndex[jj]] = vtx3.size() - 1;
6029 if(vtxprt)
mf::LogVerbatim(
"CC")<<
"New 3D vtx "<<vtx3.size()<<
" X "<<v3d.
X<<
" Y "<<v3d.
Y<<
" Z "<<v3d.
Z 6030 <<
" t2dIndex "<<t2dIndex[0]<<
" "<<t2dIndex[1]<<
" "<<t2dIndex[2]<<
" best Chi "<<best;
6042 unsigned short vsize = vtx3.size();
6043 for(
unsigned short it = 0; it < v3temp.size(); ++it) {
6045 for(
unsigned short i3d = 0; i3d < vsize; ++i3d) {
6046 for(
unsigned short plane = 0; plane < 3; ++plane) {
6047 if(v3temp[it].Ptr2D[plane] == vtx3[i3d].Ptr2D[plane]) {
6055 if(keepit) vtx3.push_back(v3temp[it]);
6060 for(
unsigned short iv3 = 0; iv3 < vtx3.size(); ++iv3) {
6061 vtx3[iv3].Ptr2D[2] = 666;
6066 for(
unsigned short it = 0; it < vtx3.size(); ++it) {
6067 mf::LogVerbatim(
"CC")<<
"vtx3 "<<it<<
" Ptr2D "<<vtx3[it].Ptr2D[0]<<
" "<<vtx3[it].Ptr2D[1]<<
" "<<vtx3[it].Ptr2D[2]
6068 <<
" wire "<<vtx3[it].Wire;
6075 void ClusterCrawlerAlg::GetHitRange(
CTP_t CTP)
6081 unsigned int nwires = geom->Nwires(planeID.
Plane, planeID.
TPC, planeID.
Cryostat);
6082 WireHitRange.resize(nwires + 1);
6088 unsigned int wire, iht;
6089 unsigned int nHitInPlane;
6090 std::pair<int, int> flag;
6093 flag.first = -2; flag.second = -2;
6094 for(
auto& apair : WireHitRange) apair = flag;
6098 std::vector<bool> firsthit;
6099 firsthit.resize(nwires+1,
true);
6100 bool firstwire =
true;
6101 for(iht = 0; iht < fHits.size(); ++iht) {
6102 if(fHits[iht].WireID().TPC != planeID.
TPC)
continue;
6103 if(fHits[iht].WireID().Cryostat != planeID.
Cryostat)
continue;
6104 if(fHits[iht].WireID().Plane != planeID.
Plane)
continue;
6105 wire = fHits[iht].WireID().Wire;
6107 if(firsthit[wire]) {
6108 WireHitRange[wire].first = iht;
6109 firsthit[wire] =
false;
6115 WireHitRange[wire].second = iht+1;
6120 lariov::ChannelStatusProvider
const& channelStatus
6123 flag.first = -1; flag.second = -1;
6124 unsigned int nbad = 0;
6125 for(wire = 0; wire < nwires; ++wire) {
6127 if(!channelStatus.IsGood(chan)) {
6128 WireHitRange[wire] = flag;
6136 <<
"GetHitRange: Invalid mergeAvailable vector size "<<mergeAvailable.size()<<fHits.size();
6137 unsigned int firstHit, lastHit;
6140 float maxRMS, chiSep, peakCut;
6141 for(wire = 0; wire < nwires; ++wire) {
6143 if(WireHitRange[wire].first < 0)
continue;
6144 firstHit = WireHitRange[wire].first;
6145 lastHit = WireHitRange[wire].second;
6146 for(iht = firstHit; iht < lastHit; ++iht) {
6147 if(fHits[iht].WireID().Wire != wire)
6150 if(fHits[iht].Multiplicity() > 1) {
6151 peakCut = 0.6 * fHits[iht].PeakAmplitude();
6152 std::pair<size_t, size_t> MultipletRange = FindHitMultiplet(iht);
6153 for(
size_t jht = MultipletRange.first; jht < MultipletRange.second; ++jht) {
6154 if(jht == iht)
continue;
6156 if(fHits[jht].PeakAmplitude() < peakCut)
continue;
6157 maxRMS =
std::max(fHits[iht].RMS(), fHits[jht].RMS());
6158 chiSep = std::abs(fHits[iht].PeakTime() - fHits[jht].PeakTime()) / maxRMS;
6159 if(chiSep < fHitMergeChiCut) {
6160 mergeAvailable[iht] =
true;
6167 if(cnt != nHitInPlane)
mf::LogWarning(
"CC")<<
"Bad WireHitRange count "<<cnt<<
" "<<nHitInPlane<<
"\n";
6169 if(!fMergeAllHits)
return;
6173 for(wire = 0; wire < nwires; ++wire) {
6174 if(WireHitRange[wire].first < 0)
continue;
6175 firstHit = WireHitRange[wire].first;
6176 lastHit = WireHitRange[wire].second;
6177 for(iht = firstHit; iht < lastHit; ++iht) {
6178 if(!mergeAvailable[iht])
continue;
6180 if(fHits[iht].GoodnessOfFit() == 6666)
continue;
6181 MergeHits(iht, didMerge);
6182 mergeAvailable[iht] =
false;
6191 if(inWire1 > inWire2) {
6193 unsigned int tmp = inWire1;
6198 unsigned int wire, ndead = 0;
6199 for(wire = inWire1; wire < inWire2; ++wire)
if(WireHitRange[wire].first == -1) ++ndead;
6207 if(fcl2hits.size() < 2)
return 0;
6208 unsigned int wire, ndead = 0;
6209 unsigned int iht = fcl2hits[fcl2hits.size()-1];
6210 unsigned int eWire = fHits[iht].WireID().Wire;
6212 unsigned int bWire = fHits[iht].WireID().Wire + 1;
6213 for(wire = eWire; wire < bWire; ++wire)
if(WireHitRange[wire].first == -1) ++ndead;
6218 bool ClusterCrawlerAlg::areInSameMultiplet
6227 std::pair<size_t, size_t> ClusterCrawlerAlg::FindHitMultiplet(
size_t iHit)
const 6229 std::pair<size_t, size_t> range{ iHit, iHit };
6231 range.first = iHit - fHits[iHit].LocalIndex();
6232 range.second = range.first + fHits[iHit].Multiplicity();
6256 bool ClusterCrawlerAlg::CheckHitDuplicates
6257 (std::string location, std::string marker )
const 6260 unsigned int nDuplicates = 0;
6261 std::set<unsigned int>
hits;
6262 for (
unsigned int hit: fcl2hits) {
6263 if (hits.count(
hit)) {
6266 log <<
"Hit #" <<
hit 6267 <<
" being included twice in the future cluster (ID=" 6268 << (tcl.size() + 1) <<
"?) at location: " << location;
6269 if (!marker.empty()) log <<
" (marker: '" << marker <<
"')";
6273 return nDuplicates > 0;
6277 float ClusterCrawlerAlg::DoCA(
short icl,
unsigned short end,
float vwire,
float vtick)
6282 if(icl > (
short)tcl.size())
return 9999;
6284 float cwire, cslp, ctick;
6287 if(fcl2hits.size() == 0)
return 9999;
6301 cwire = tcl[icl].BeginWir;
6302 cslp = tcl[icl].BeginSlp;
6303 ctick = tcl[icl].BeginTim;
6305 cwire = tcl[icl].EndWir;
6306 cslp = tcl[icl].EndSlp;
6307 ctick = tcl[icl].EndTim;
6312 float docaW = (vwire + cslp * (vtick - ctick) + cwire * cslp * cslp) / (1 + cslp * cslp);
6313 float dW = docaW - vwire;
6314 float dT = ctick + (vwire - cwire) * cslp - vtick;
6315 return sqrt(dW * dW + dT * dT);
6320 float ClusterCrawlerAlg::ClusterVertexChi(
short icl,
unsigned short end,
unsigned short ivx)
6324 if(icl > (
short)tcl.size())
return 9999;
6325 if(ivx > vtx.size())
return 9999;
6327 float cwire, cslp, cslpErr, ctick;
6330 if(fcl2hits.size() == 0)
return 9999;
6335 cslpErr = clBeginSlpErr;
6340 cslpErr = clparerr[1];
6346 cwire = tcl[icl].BeginWir;
6347 cslp = tcl[icl].BeginSlp;
6348 cslpErr = tcl[icl].BeginSlpErr;
6349 ctick = tcl[icl].BeginTim;
6351 cwire = tcl[icl].EndWir;
6352 cslp = tcl[icl].EndSlp;
6353 cslpErr = tcl[icl].EndSlpErr;
6354 ctick = tcl[icl].EndTim;
6359 float docaW = (vtx[ivx].Wire + cslp * (vtx[ivx].Time - ctick) + cwire * cslp * cslp) / (1 + cslp * cslp);
6360 float dW = docaW - vtx[ivx].Wire;
6361 float chi = dW / vtx[ivx].WireErr;
6362 float totChi = chi * chi;
6363 dW = vtx[ivx].Wire - cwire;
6364 float dT = ctick + dW * cslp - vtx[ivx].Time;
6365 if(cslpErr < 1
E-3) cslpErr = 1
E-3;
6367 cslpErr *= AngleFactor(cslp);
6369 float dTErr = dW * cslpErr;
6373 dTErr += vtx[ivx].TimeErr * vtx[ivx].TimeErr;
6374 if(dTErr < 1
E-3) dTErr = 1
E-3;
6375 totChi += dT * dT / dTErr;
6383 float ClusterCrawlerAlg::PointVertexChi(
float wire,
float tick,
unsigned short ivx)
6387 if(ivx > vtx.size())
return 9999;
6389 float dW = wire - vtx[ivx].Wire;
6390 float chi = dW / vtx[ivx].WireErr;
6391 float totChi = chi * chi;
6392 float dT = tick - vtx[ivx].Time;
6393 chi = dT / vtx[ivx].TimeErr;
6394 totChi += chi * chi;
6405 if(iht > fHits.size() - 1)
return "Bad Hit";
short int LocalIndex() const
How well do we believe we know this hit?
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Functions to help with numbers.
geo::SigType_t SignalType() const
Signal type for the plane of the hit.
void MergeOverlap(std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, bool prt)
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
static unsigned int kWire
struct of temporary 2D vertices (end points)
geo::WireID WireID() const
Initial tdc tick for hit.
unsigned int Nplanes() const
Number of planes in this tpc.
float RMS() const
RMS of the hit shape, in tick units.
Declaration of signal hit object.
Planes which measure X direction.
The data type to uniquely identify a Plane.
Geometry information for a single TPC.
float SigmaPeakAmplitude() const
Uncertainty on estimated amplitude of the hit at its peak, in ADC units.
float SigmaIntegral() const
Initial tdc tick for hit.
int DegreesOfFreedom() const
Initial tdc tick for hit.
virtual double SamplingRate() const =0
Returns the period of the TPC readout electronics clock.
CryostatID_t Cryostat
Index of cryostat.
float Integral() const
Integral under the calibrated signal waveform of the hit, in tick x ADC units.
struct of temporary clusters
geo::View_t View() const
View for the plane of the hit.
WireID_t Wire
Index of the wire within its plane.
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
Cluster finding and building.
float GoodnessOfFit() const
Degrees of freedom in the determination of the hit signal shape (-1 by default)
short int Multiplicity() const
How many hits could this one be shared with.
float DeadWireCount(const TjStuff &tjs, const TrajPoint &tp1, const TrajPoint &tp2)
struct of temporary 3D vertices
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
float PeakAmplitude() const
The estimated amplitude of the hit at its peak, in ADC units.
int TDCtick_t
Type representing a TDC tick.
int cmp(WireID const &other) const
Returns < 0 if this is smaller than tpcid, 0 if equal, > 0 if larger.
virtual double Temperature() const =0
bool lessThan(CluLen c1, CluLen c2)
T get(std::string const &key) const
std::vector< evd::details::RawDigitInfo_t >::const_iterator begin(RawDigitCacheDataClass const &cache)
bool SortByLowHit(unsigned int i, unsigned int j)
std::string PrintHit(const TCHit &hit)
bool has_key(std::string const &key) const
virtual unsigned int NumberTimeSamples() const =0
The data type to uniquely identify a TPC.
PlaneID_t Plane
Index of the plane within its TPC.
Declaration of cluster object.
raw::TDCtick_t StartTick() const
Initial tdc tick for hit.
float PeakTimeMinusRMS(float sigmas=+1.) const
Returns a time sigmas RMS away from the peak time.
std::array< short, 3 > Ptr2D
bool greaterThan(CluLen c1, CluLen c2)
Detector simulation of raw signals on wires.
constexpr auto absDiff(A const &a, B const &b)
Returns the absolute value of the difference between two values.
raw::TDCtick_t EndTick() const
Final tdc tick for hit.
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
float PeakTime() const
Time of the signal peak, in tick units.
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
virtual double DriftVelocity(double efield=0., double temperature=0.) const =0
std::vector< unsigned int > tclhits
geo::PlaneID DecodeCTP(CTP_t CTP)
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Exception thrown on invalid wire number.
float SummedADC() const
The sum of calibrated ADC counts of the hit (0. by default)
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
float SigmaPeakTime() const
Uncertainty for the signal peak, in tick units.
2D representation of charge deposited in the TDC/wire plane
float PeakTimePlusRMS(float sigmas=+1.) const
Returns a time sigmas RMS away from the peak time.
virtual double Efield(unsigned int planegap=0) const =0
Returns the nominal electric field in the specified volume.
unsigned int ChannelID_t
Type representing the ID of a readout channel.
TPCID_t TPC
Index of the TPC within its cryostat.
geo::WireID suggestedWireID() const
Returns a better wire ID.
recob::tracking::Plane Plane
raw::ChannelID_t Channel() const
ID of the readout channel the hit was extracted from.
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
art framework interface to geometry description
Encapsulate the construction of a single detector plane.