27 #include "TMVA/Reader.h" 40 sp.
find_file(fMVAShowerParentWeights, fullFileSpec);
41 if (fullFileSpec ==
"") {
67 if (ss3.
ID == 0)
return false;
71 myprt <<
"Inside FSS: 3S" << ss3.
ID <<
" ->";
72 for (
auto cid : ss3.
CotIDs)
73 myprt <<
" 2S" << cid;
74 myprt <<
" Vx 3V" << ss3.
Vx3ID;
79 unsigned short useParentCID = 0;
80 float maxParentSep = 0;
81 unsigned short usePtSepCID = 0;
86 for (
auto cid : ss3.
CotIDs) {
87 auto& ss = slc.
cots[cid - 1];
89 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
92 if (chgCtrTP.Delta < 0.5)
continue;
93 auto& startTP = stj.Pts[0];
94 float sep =
PosSep(startTP.Pos, chgCtrTP.Pos);
95 if (ss.ParentID > 0) {
96 if (sep > maxParentSep) {
101 else if (sep > maxPtSep) {
105 float costh =
DotProd(chgCtrTP.Dir, startTP.Dir);
106 if (costh < 0) dirOK =
false;
109 if (useParentCID == 0 && usePtSepCID == 0)
return false;
111 unsigned short useCID = useParentCID;
113 useCID = usePtSepCID;
118 auto& ss = slc.
cots[useCID - 1];
119 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
124 ss3.
Start[0] = vx3.X;
125 ss3.
Start[1] = vx3.Y;
126 ss3.
Start[2] = vx3.Z;
130 auto& startTP = stj.Pts[0];
135 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
139 auto& endTP = stj.Pts[2];
141 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
144 auto& startTP = stj.Pts[0];
145 sep =
PosSep(startTP.Pos, endTP.Pos);
146 ss3.
OpenAngle = (endTP.DeltaRMS - startTP.DeltaRMS) / sep;
163 bool noShowers =
true;
164 for (
auto& ss3 : slc.
showers) {
165 if (ss3.ID == 0)
continue;
168 if (noShowers)
return;
175 for (
auto& ss3 : slc.
showers) {
176 if (ss3.ID == 0)
continue;
177 if (ss3.PFPIndex != USHRT_MAX)
continue;
179 showerPFP.TjIDs.resize(ss3.CotIDs.size());
180 for (
unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) {
181 unsigned short cid = ss3.CotIDs[ii];
182 if (cid == 0 || cid > slc.
cots.size())
return;
183 auto& ss = slc.
cots[cid - 1];
184 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
185 showerPFP.TjIDs[ii] = stj.ID;
187 showerPFP.PDGCode = 1111;
188 auto& sf = showerPFP.SectionFits[0];
191 sf.DirErr = ss3.DirErr;
192 showerPFP.Vx3ID[0] = ss3.Vx3ID;
195 for (
auto cid : ss3.CotIDs) {
196 auto& ss = slc.
cots[cid - 1];
198 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
199 showerPFP.dEdx[0][plane] = stj.dEdx[0];
200 showerPFP.dEdxErr[0][plane] = 0.3 * stj.dEdx[0];
202 ss3.PFPIndex = slc.
pfps.size();
203 if (ss3.ParentID > 0) {
205 auto& dtrPFP = slc.
pfps[ss3.ParentID - 1];
206 if (dtrPFP.ParentUID > 0) {
209 auto& parPFP =
slices[slcIndx.first].pfps[slcIndx.second];
210 showerPFP.ParentUID = parPFP.UID;
211 std::replace(parPFP.DtrUIDs.begin(), parPFP.DtrUIDs.end(), dtrPFP.UID, showerPFP.UID);
212 dtrPFP.ParentUID = 0;
215 slc.
pfps.push_back(showerPFP);
223 for (
auto& ss3 : slc.
showers) {
224 if (ss3.ID == 0)
continue;
225 for (
unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) {
226 unsigned short cid = ss3.CotIDs[ii];
227 auto& ss = slc.
cots[cid - 1];
228 for (
auto tjid : ss.TjIDs) {
231 ss3.Hits.insert(ss3.Hits.end(), tjHits.begin(), tjHits.end());
233 for (
unsigned short end = 0;
end < 2; ++
end) {
236 if (vx2.Vx3ID <= 0) {
243 auto& vx3 = slc.
vtx3s[vx2.Vx3ID - 1];
244 if (vx3.Neutrino)
continue;
252 if (!slc.
pfps.empty()) {
253 for (
auto& pfp : slc.
pfps) {
254 if (pfp.ID == 0)
continue;
255 if (pfp.TjIDs.empty())
continue;
256 unsigned short ndead = 0;
257 for (
auto tjid : pfp.TjIDs) {
258 auto& tj = slc.
tjs[tjid - 1];
259 if (tj.AlgMod[
kKilled]) ++ndead;
261 if (ndead == 0)
continue;
267 for (
auto& vx2 : slc.
vtxs) {
268 if (vx2.ID == 0)
continue;
269 auto vxtjs =
GetAssns(slc,
"2V", vx2.
ID,
"T");
270 if (vxtjs.empty()) vx2.ID = 0;
274 for (
auto& vx3 : slc.
vtx3s) {
275 if (vx3.ID == 0)
continue;
276 auto vxtjs =
GetAssns(slc,
"3V", vx3.
ID,
"T");
293 if (!reconstruct)
return false;
302 for (
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane) {
304 for (
auto& ss : slc.
cots)
305 if (ss.CTP == inCTP)
return false;
314 std::vector<std::vector<std::vector<int>>> bigList(slc.
nPlanes);
315 for (
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane) {
316 std::vector<std::vector<int>> tjList;
320 if (tjList.empty())
continue;
321 bigList[plane] = tjList;
323 unsigned short nPlanesWithShowers = 0;
324 for (
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane)
325 if (!bigList.empty()) ++nPlanesWithShowers;
326 if (nPlanesWithShowers < 2)
return false;
327 for (
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane) {
330 bool prtCTP = (prt2S && inCTP ==
debug.
CTP);
332 for (
auto& tjl : bigList[plane]) {
333 if (tjl.empty())
continue;
336 myprt <<
"Plane " << plane <<
" tjList";
337 for (
auto& tjID : tjl)
338 myprt <<
" " << tjID;
341 if (ss.ID == 0)
continue;
350 if (inCTP == UINT_MAX)
continue;
351 if (slc.
cots.empty())
continue;
367 bool tryMerge =
false;
368 for (
unsigned short ii = 0; ii < slc.
cots.size(); ++ii) {
369 auto& ss = slc.
cots[ii];
370 if (ss.ID == 0)
continue;
371 if (ss.CTP != inCTP)
continue;
379 if (slc.
cots.empty())
return false;
387 for (
auto& ss3 : slc.
showers) {
388 if (ss3.ID == 0)
continue;
389 FindParent(detProp, fcnLabel, slc, ss3, prt3S);
397 for (
auto& ss3 : slc.
showers) {
398 if (ss3.ID == 0)
continue;
404 for (
auto& ss : slc.
cots) {
405 if (ss.ID == 0)
continue;
406 if (ss.SS3ID > 0)
continue;
407 bool killMe = (ss.TjIDs.size() == 1 || ss.Energy <
tcc.
showerTag[3]);
413 unsigned short nNewShowers = 0;
414 for (
auto& ss : slc.
cots) {
415 if (ss.ID == 0)
continue;
416 if (ss.TjIDs.empty())
continue;
421 return (nNewShowers > 0);
437 for (
unsigned short ii = 0; ii < slc.
showers.size() - 1; ++ii) {
439 if (iss3.ID == 0)
continue;
440 auto iPInSS3 =
GetAssns(slc,
"3S", iss3.
ID,
"P");
443 myprt << fcnLabel <<
" 3S" << iss3.ID <<
" ->";
444 for (
auto pid : iPInSS3)
445 myprt <<
" P" <<
pid;
447 for (
unsigned short jj = ii + 1; jj < slc.
showers.size(); ++jj) {
449 if (jss3.ID == 0)
continue;
450 auto jPInSS3 =
GetAssns(slc,
"3S", jss3.
ID,
"P");
452 if (shared.empty())
continue;
455 myprt << fcnLabel <<
" Conflict i3S" << iss3.ID <<
" and j3S" << jss3.ID <<
" share";
456 for (
auto pid : shared)
457 myprt <<
" P" <<
pid;
460 for (
auto pid : shared) {
467 <<
" j3S" << jss3.ID <<
" prob " << jProb;
470 RemovePFP(fcnLabel, slc, pfp, jss3,
true, prt);
472 AddPFP(fcnLabel, slc, pfp.
ID, iss3,
true, prt);
475 RemovePFP(fcnLabel, slc, pfp, iss3,
true, prt);
476 AddPFP(fcnLabel, slc, pfp.
ID, jss3,
true, prt);
485 if (parentSearchDone) {
486 for (
auto& ss3 : slc.
showers) {
487 if (ss3.ID == 0)
continue;
488 auto PIn3S =
GetAssns(slc,
"3S", ss3.
ID,
"P");
489 for (
auto pid : PIn3S) {
490 if (
pid == ss3.ParentID)
continue;
492 for (
unsigned short end = 0;
end < 2; ++
end) {
493 if (pfp.Vx3ID[
end] <= 0)
continue;
496 myprt << fcnLabel <<
" Detach 3S" << ss3.ID <<
" -> P" << pfp.ID <<
"_" <<
end 497 <<
" -> 3V" << pfp.Vx3ID[
end];
498 if (pfp.ParentUID > 0) myprt <<
" ->Parent P" << pfp.ParentUID;
502 if (pfp.ParentUID > 0) {
504 auto& parentPFP =
slices[slcIndx.first].pfps[slcIndx.second];
505 std::vector<int> newDtrUIDs;
506 for (
auto did : parentPFP.DtrUIDs)
507 if (did != pfp.UID) newDtrUIDs.push_back(did);
508 parentPFP.DtrUIDs = newDtrUIDs;
517 for (
auto& ss : slc.
cots) {
518 if (ss.ID == 0)
continue;
519 if (ss.SS3ID > 0)
continue;
520 std::vector<int> matchedTjs;
521 for (
auto tid : ss.TjIDs)
522 if (slc.
tjs[tid - 1].AlgMod[
kMat3D]) matchedTjs.push_back(tid);
523 if (matchedTjs.empty())
continue;
527 bool isCompatible =
true;
528 for (
auto tid : matchedTjs) {
529 auto TInP =
GetAssns(slc,
"T", tid,
"P");
530 if (TInP.empty())
continue;
533 auto PIn3S =
GetAssns(slc,
"P", TInP[0],
"3S");
534 for (
auto sid : PIn3S) {
536 auto& ss3 = slc.
showers[sid - 1];
538 if (mergeWith3S == 0) mergeWith3S = sid;
539 if (mergeWith3S > 0 && mergeWith3S != sid) isCompatible =
false;
544 myprt << fcnLabel <<
" 2S" << ss.ID <<
" is not 3D-matched but has 3D-matched Tjs:";
545 for (
auto tid : matchedTjs) {
546 myprt <<
" T" << tid;
547 auto TInP =
GetAssns(slc,
"T", tid,
"P");
548 if (!TInP.empty()) { myprt <<
"->P" << TInP[0]; }
551 if (mergeWith3S == 0 && ss.Energy < 50) {
555 else if (mergeWith3S > 0 && isCompatible) {
556 auto& ss3 = slc.
showers[mergeWith3S - 1];
557 for (
auto cid : ss3.CotIDs) {
558 auto& oss = slc.
cots[cid - 1];
559 if (oss.CTP != ss.CTP)
continue;
560 if (!
UpdateShower(fcnLabel, slc, ss3, prt))
return false;
578 if (ss3.
ID == 0)
return false;
580 if (ss3.
CotIDs.size() < 3)
return true;
587 std::vector<ShowerStruct> oldSS(ss3.
CotIDs.size());
588 for (
unsigned short ii = 0; ii < ss3.
CotIDs.size(); ++ii) {
592 std::vector<std::vector<int>> plist(ss3.
CotIDs.size());
593 for (
unsigned short ci = 0; ci < ss3.
CotIDs.size(); ++ci) {
595 for (
auto tid : ss.TjIDs) {
596 auto tToP =
GetAssns(slc,
"T", tid,
"P");
597 if (tToP.empty())
continue;
600 if (std::find(plist[ci].
begin(), plist[ci].
end(), pid) == plist[ci].end())
605 std::vector<std::array<int, 2>> p_cnt;
606 for (
auto& pl : plist) {
607 for (
auto pid : pl) {
608 unsigned short indx = 0;
609 for (indx = 0; indx < p_cnt.size(); ++indx)
610 if (p_cnt[indx][0] ==
pid)
break;
611 if (indx == p_cnt.size()) {
613 p_cnt.push_back(std::array<int, 2>{{
pid, 1}});
622 myprt << fcnLabel <<
" 3S" << ss3.
ID <<
"\n";
623 for (
unsigned short ci = 0; ci < ss3.
CotIDs.size(); ++ci) {
624 myprt <<
" -> 2S" << ss3.
CotIDs[ci] <<
" ->";
625 for (
auto pid : plist[ci])
626 myprt <<
" P" <<
pid;
629 myprt <<
" P<ID>_count:";
630 for (
auto&
pc : p_cnt)
631 myprt <<
" P" <<
pc[0] <<
"_" <<
pc[1];
634 for (
auto&
pc : p_cnt) {
636 if (
pc[1] == (
int)ss3.
CotIDs.size())
continue;
639 auto& pfp = slc.
pfps[
pc[0] - 1];
640 if (pfp.TjIDs.size() > 2) {
642 auto PIn2S =
GetAssns(slc,
"P", pfp.
ID,
"2S");
644 if (!sDiff.empty() &&
649 myprt << fcnLabel <<
" 3S" << ss3.
ID <<
" P" << pfp.ID <<
" ->";
650 for (
auto sid : PIn2S)
651 myprt <<
" 2S" << sid;
653 for (
auto sid : sDiff)
654 myprt <<
" 2S" << sid;
657 if (
AddPFP(fcnLabel, slc, pfp.
ID, ss3,
true, prt)) {
660 if (ss3.
CotIDs.size() != oldSS.size())
return false;
661 for (
unsigned short ii = 0; ii < ss3.
CotIDs.size(); ++ii)
667 for (
unsigned short ii = 0; ii < oldSS.size(); ++ii) {
668 auto& ss = oldSS[ii];
669 slc.
cots[ss.ID - 1] = ss;
676 auto& pfp = slc.
pfps[
pc[0] - 1];
677 unsigned short nearEnd = 1 -
FarEnd(slc, pfp, ss3.
ChgPos);
683 myprt << fcnLabel <<
" one occurrence: P" << pfp.ID <<
"_" << nearEnd
684 <<
" closest to ChgPos";
687 myprt <<
" sep " << sep;
688 myprt <<
" InShowerProb " << prob;
690 if (sep < 30 && prob > 0.3 &&
AddPFP(fcnLabel, slc, pfp.
ID, ss3,
true, prt)) {
693 else if (!
RemovePFP(fcnLabel, slc, pfp, ss3,
true, prt)) {
699 if (!
UpdateShower(fcnLabel, slc, ss3, prt))
return false;
712 if (ss.
ID == 0)
return;
716 for (
auto& vx2 : slc.
vtxs) {
717 if (vx2.ID == 0)
continue;
718 if (vx2.CTP != ss.
CTP)
continue;
720 if (vx2.Vx3ID > 0 && slc.
vtx3s[vx2.Vx3ID - 1].Neutrino)
continue;
723 mf::LogVerbatim(
"TC") << fcnLabel <<
" Clobber 2V" << vx2.ID <<
" -> 3V" << vx2.Vx3ID
724 <<
" inside 2S" << ss.
ID;
727 if (dc.TjIDs[0] == 0)
continue;
728 if (dc.Vx2ID != vx2.ID)
continue;
730 mf::LogVerbatim(
"TC") << fcnLabel <<
" Remove T" << dc.TjIDs[0] <<
"-T" << dc.TjIDs[0]
731 <<
" in dontCluster";
736 auto TIn3V =
GetAssns(slc,
"3V", vx2.Vx3ID,
"T");
737 for (
auto tid : TIn3V)
739 auto& vx3 = slc.
vtx3s[vx2.Vx3ID - 1];
743 auto TIn2V =
GetAssns(slc,
"2V", vx2.
ID,
"T");
744 for (
auto tid : TIn2V)
759 if (slc.
nPlanes != 3)
return false;
760 if (ss3.
CotIDs.size() != 2)
return false;
770 std::vector<int> iplist;
771 for (
auto tid : iss.TjIDs) {
772 auto plist =
GetAssns(slc,
"T", tid,
"P");
773 if (!plist.empty()) iplist.insert(iplist.end(), plist.begin(), plist.end());
775 std::vector<int> jplist;
776 for (
auto tid : jss.TjIDs) {
777 auto plist =
GetAssns(slc,
"T", tid,
"P");
778 if (!plist.empty()) jplist.insert(jplist.end(), plist.begin(), plist.end());
782 if (shared.empty())
return false;
784 std::vector<int>
flat = iss.TjIDs;
785 flat.insert(flat.end(), jss.TjIDs.begin(), jss.TjIDs.end());
788 std::vector<int> ktlist;
789 for (
auto pid : shared) {
791 for (
auto tid : pfp.TjIDs) {
793 if (std::find(flat.begin(), flat.end(), tid) != flat.end())
continue;
794 if (std::find(ktlist.begin(), ktlist.end(), tid) == ktlist.end()) ktlist.push_back(tid);
796 auto& tj = slc.
tjs[tid - 1];
797 for (
unsigned short end = 0;
end < 2; ++
end) {
798 if (tj.VtxID[
end] <= 0)
continue;
799 auto& vx2 = slc.
vtxs[tj.VtxID[
end] - 1];
800 auto TIn2V =
GetAssns(slc,
"2V", vx2.
ID,
"T");
801 for (
auto vtid : TIn2V) {
802 if (std::find(ktlist.begin(), ktlist.end(), vtid) == ktlist.end())
803 ktlist.push_back(vtid);
808 if (ktlist.empty())
return false;
810 std::vector<int> ksslist;
811 for (
auto tid : ktlist) {
812 auto& tj = slc.
tjs[tid - 1];
813 if (tj.SSID == 0)
continue;
815 auto& ss = slc.
cots[tj.SSID - 1];
818 mf::LogVerbatim(
"TC") << fcnLabel <<
" Found existing T" << tid <<
" -> 2S" << ss.ID
819 <<
" -> 3S" << ss.SS3ID <<
" assn. Give up";
822 if (std::find(ksslist.begin(), ksslist.end(), ss.ID) == ksslist.end())
823 ksslist.push_back(ss.ID);
829 myprt << fcnLabel <<
" 3S" << ss3.
ID <<
"\n";
830 myprt <<
" -> i2S" << iss.ID <<
" ->";
831 for (
auto pid : iplist)
832 myprt <<
" P" <<
pid;
834 myprt <<
" -> j2S" << jss.ID <<
" ->";
835 for (
auto pid : jplist)
836 myprt <<
" P" << pid;
840 unsigned short kplane = 3 - iPlaneID.
Plane - jPlaneID.
Plane;
841 myprt <<
" kplane " << kplane <<
" ktlist:";
842 for (
auto tid : ktlist)
843 myprt <<
" T" << tid;
844 myprt <<
" ktlistEnergy " << ktlistEnergy;
845 if (ksslist.empty()) { myprt <<
"\n No matching showers in kplane"; }
848 myprt <<
" Candidate showers:";
849 for (
auto ssid : ksslist) {
850 myprt <<
" 2S" << ssid;
851 auto& sst = slc.
cots[ssid - 1];
852 if (sst.SS3ID > 0) myprt <<
"_3S" << sst.SS3ID;
856 if (ksslist.size() > 1) {
859 <<
" Found more than 1 shower. Need some better code here";
865 <<
" ktlistEnergy exceeds 2 * ss3 energy. Need some better code here";
869 if (ksslist.empty()) {
872 if (kss.ID == 0)
return false;
875 mf::LogVerbatim(
"TC") << fcnLabel <<
" 3S" << ss3.
ID <<
" create new 2S" << kss.ID
878 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" UpdateShower failed 2S" << kss.ID;
887 ss3.
CotIDs.push_back(kss.ID);
888 auto& stj = slc.
tjs[kss.ShowerTjID - 1];
895 auto& ss = slc.
cots[ksslist[0] - 1];
897 mf::LogVerbatim(
"TC") << fcnLabel <<
" 3S" << ss3.
ID <<
" found pfp-matched 2S" << ss.ID;
899 ss3.
CotIDs.push_back(ss.ID);
900 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
920 if (ss.
ID == 0)
return false;
921 if (ss.
TjIDs.empty())
return false;
925 if (stj.Pts.size() != 3)
return false;
939 for (
auto& stp : stj.Pts) {
941 stp.Pos = {{0.0, 0.0}};
943 stp.HitPos = {{0.0, 0.0}};
945 stp.Dir = {{0.0, 0.0}};
955 for (
auto tjid : ss.
TjIDs) {
956 if (tjid <= 0 || tjid > (
int)slc.
tjs.size())
return false;
957 auto& tj = slc.
tjs[tjid - 1];
958 if (tj.CTP != ss.
CTP)
return false;
960 for (
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
962 for (
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
963 if (!tp.
UseHit[ii])
continue;
964 unsigned int iht = tp.
Hits[ii];
966 if (
hit.Integral() <= 0)
continue;
970 shpt.
Chg =
hit.Integral();
971 shpt.
Pos[0] =
hit.WireID().Wire;
973 ss.
ShPts.push_back(shpt);
979 if (ss.
ShPts.size() < 3)
return false;
982 auto& stp1 = stj.Pts[1];
983 for (
auto& shpt : ss.
ShPts) {
984 stp1.Pos[0] += shpt.Chg * shpt.Pos[0];
985 stp1.Pos[1] += shpt.Chg * shpt.Pos[1];
986 stj.TotChg += shpt.Chg;
988 if (stj.TotChg <= 0)
return false;
989 stp1.Pos[0] /= stj.TotChg;
990 stp1.Pos[1] /= stj.TotChg;
994 <<
" Energy " << (
int)ss.
Energy <<
" MeV";
1001 unsigned short pend =
FarEnd(slc, ptj, stp1.Pos);
1002 auto& ptp = ptj.Pts[ptj.EndPt[pend]];
1004 stp1.Ang = atan2(stp1.Dir[1], stp1.Dir[0]);
1014 for (
auto& shpt : ss.
ShPts) {
1016 double xx = shpt.Pos[0] - stp1.Pos[0];
1017 double yy = shpt.Pos[1] - stp1.Pos[1];
1018 sumx += shpt.Chg * xx;
1019 sumy += shpt.Chg * yy;
1020 sumxy += shpt.Chg * xx * yy;
1021 sumx2 += shpt.Chg * xx * xx;
1022 sumy2 += shpt.Chg * yy * yy;
1024 double delta = sum * sumx2 - sumx * sumx;
1025 if (delta == 0)
return false;
1029 double B = (sumxy * sum - sumx * sumy) / delta;
1031 stp1.Dir[0] = cos(stp1.Ang);
1032 stp1.Dir[1] = sin(stp1.Ang);
1036 ss.
Angle = stp1.Ang;
1040 <<
" Angle " << stp1.Ang;
1041 for (
unsigned short ipt = 0; ipt < 3; ++ipt) {
1042 if (ipt == 1)
continue;
1043 stj.Pts[ipt].Dir = stp1.Dir;
1044 stj.Pts[ipt].Ang = stp1.Ang;
1048 std::vector<SortEntry> sortVec(ss.
ShPts.size());
1049 unsigned short indx = 0;
1050 double cs = cos(-stp1.Ang);
1051 double sn = sin(-stp1.Ang);
1052 for (
auto& shpt : ss.
ShPts) {
1053 double xx = shpt.Pos[0] - stp1.Pos[0];
1054 double yy = shpt.Pos[1] - stp1.Pos[1];
1055 shpt.RotPos[0] = cs * xx - sn * yy;
1056 shpt.RotPos[1] = sn * xx + cs * yy;
1057 sortVec[indx].index = indx;
1058 sortVec[indx].val = shpt.RotPos[0];
1063 auto tPts = ss.
ShPts;
1064 for (
unsigned short ii = 0; ii < ss.
ShPts.size(); ++ii)
1065 ss.
ShPts[ii] = tPts[sortVec[ii].index];
1069 for (
auto& shpt : ss.ShPts) {
1070 alongTrans[0] += shpt.Chg *
std::abs(shpt.RotPos[0]);
1071 alongTrans[1] += shpt.Chg *
std::abs(shpt.RotPos[1]);
1073 alongTrans[0] /= stj.TotChg;
1074 alongTrans[1] /= stj.TotChg;
1075 if (alongTrans[1] == 0)
return false;
1076 ss.AspectRatio = alongTrans[1] / alongTrans[0];
1078 mf::LogVerbatim(
"TC") << fcnLabel <<
" 2S" << ss.ID <<
" AspectRatio " << ss.AspectRatio;
1084 if (ss.ParentID > 0) {
1087 auto& ptj = slc.tjs[ss.ParentID - 1];
1089 unsigned short pend =
FarEnd(slc, ptj, stp1.Pos);
1090 auto& ptp = ptj.Pts[ptj.EndPt[pend]];
1091 auto& firstShPt = ss.ShPts[0];
1092 auto& lastShPt = ss.ShPts[ss.ShPts.size() - 1];
1093 if (
PosSep2(ptp.Pos, lastShPt.Pos) <
PosSep2(ptp.Pos, firstShPt.Pos))
1095 stj.Pts[0].Pos = ptp.Pos;
1099 if (stj.Pts[2].DeltaRMS < stj.Pts[0].DeltaRMS)
ReverseShower(fcnLabel, slc, ss, prt);
1100 stj.Pts[0].Pos = ss.ShPts[0].Pos;
1103 if (stj.Pts[2].DeltaRMS > 0) ss.DirectionFOM = stj.Pts[0].DeltaRMS / stj.Pts[2].DeltaRMS;
1105 stj.Pts[2].Pos = ss.ShPts[ss.ShPts.size() - 1].Pos;
1108 ss.NeedsUpdate =
false;
1109 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" 2S" << ss.ID <<
" updated";
1121 if (ss3.
ID == 0)
return false;
1122 if (ss3.
CotIDs.size() < 2)
return false;
1127 for (
auto cid : ss3.
CotIDs) {
1128 auto& ss = slc.
cots[cid - 1];
1129 if (ss.NeedsUpdate && prt)
1130 std::cout << fcnLabel <<
" ********* 3S" << ss3.
ID <<
" 2S" << ss.ID
1131 <<
" needs an update...\n";
1139 if (pfp.Vx3ID[pend] != ss3.
Vx3ID) {
1141 std::cout << fcnLabel <<
" ********* 3S" << ss3.
ID <<
" has parent P" << ss3.
ParentID 1142 <<
" with a vertex that is not attached the shower\n";
1147 std::array<Point3_t, 3>
pos;
1150 std::array<double, 3> chg;
1151 for (
unsigned short ipt = 0; ipt < 3; ++ipt) {
1153 for (
unsigned short xyz = 0; xyz < 3; ++xyz) {
1158 unsigned short nok = 0;
1159 for (
unsigned short ipt = 0; ipt < 3; ++ipt) {
1160 if (chg[ipt] == 0)
continue;
1161 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
1162 pos[ipt][xyz] /= chg[ipt];
1167 if (nok != 3)
return false;
1187 for (
auto cid : ss3.
CotIDs) {
1188 auto& ss = slc.
cots[cid - 1];
1189 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
1191 ss3.
Energy[plane] = ss.Energy;
1197 ss3.
dEdx[plane] = stj.dEdx[0];
1198 ss3.
dEdxErr[plane] = 0.3 * stj.dEdx[0];
1217 for (
unsigned short ii = 0; ii < ss3.
CotIDs.size() - 1; ++ii) {
1218 unsigned short icid = ss3.
CotIDs[ii];
1219 for (
unsigned short jj = ii + 1; jj < ss3.
CotIDs.size(); ++jj) {
1220 unsigned short jcid = ss3.
CotIDs[jj];
1221 fom +=
Match3DFOM(detProp, inFcnLabel, slc, icid, jcid, prt);
1225 if (cnt == 0)
return 100;
1239 if (icid == 0 || icid > (
int)slc.
cots.size())
return 100;
1240 if (jcid == 0 || jcid > (
int)slc.
cots.size())
return 100;
1241 if (kcid == 0 || kcid > (
int)slc.
cots.size())
return 100;
1243 float ijfom =
Match3DFOM(detProp, inFcnLabel, slc, icid, jcid, prt);
1244 float jkfom =
Match3DFOM(detProp, inFcnLabel, slc, jcid, kcid, prt);
1246 return 0.5 * (ijfom + jkfom);
1260 if (icid == 0 || icid > (
int)slc.
cots.size())
return 100;
1261 if (jcid == 0 || jcid > (
int)slc.
cots.size())
return 100;
1263 auto& iss = slc.
cots[icid - 1];
1264 auto& istj = slc.
tjs[iss.ShowerTjID - 1];
1265 auto& jss = slc.
cots[jcid - 1];
1266 auto& jstj = slc.
tjs[jss.ShowerTjID - 1];
1268 if (iss.CTP == jss.CTP)
return 100;
1272 float energyAsym =
std::abs(iss.Energy - jss.Energy) / (iss.Energy + jss.Energy);
1275 if ((iss.Energy > 200 || jss.Energy > 200) && energyAsym > 0.5)
return 50;
1283 float pos1fom =
std::abs(ix - jx) / 10;
1285 float mfom = energyAsym * pos1fom;
1289 myprt << fcnLabel <<
" i2S" << iss.ID <<
" j2S" << jss.ID;
1291 myprt <<
" pos1fom " << pos1fom;
1292 myprt <<
" energyAsym " << energyAsym;
1293 myprt <<
" mfom " << mfom;
1305 if (tjList.size() < 2)
return;
1307 bool didMerge =
true;
1310 for (
unsigned short itl = 0; itl < tjList.size() - 1; ++itl) {
1311 if (tjList[itl].
empty())
continue;
1312 for (
unsigned short jtl = itl + 1; jtl < tjList.size(); ++jtl) {
1313 if (tjList[itl].
empty())
continue;
1314 auto& itList = tjList[itl];
1315 auto& jtList = tjList[jtl];
1317 bool jtjInItjList =
false;
1318 for (
auto& jtj : jtList) {
1319 if (std::find(itList.begin(), itList.end(), jtj) != itList.end()) {
1320 jtjInItjList =
true;
1323 if (jtjInItjList)
break;
1327 itList.insert(itList.end(), jtList.begin(), jtList.end());
1337 unsigned short imEmpty = 0;
1338 while (imEmpty < tjList.size()) {
1339 for (imEmpty = 0; imEmpty < tjList.size(); ++imEmpty)
1340 if (tjList[imEmpty].
empty())
break;
1341 if (imEmpty < tjList.size()) tjList.erase(tjList.begin() + imEmpty);
1345 for (
auto& tjl : tjList) {
1346 std::sort(tjl.begin(), tjl.end());
1347 auto last = std::unique(tjl.begin(), tjl.end());
1348 tjl.erase(last, tjl.end());
1365 if (pfp.
ID == 0 || ss3.
ID == 0)
return false;
1368 for (
auto tid : pfp.
TjIDs) {
1369 for (
auto cid : ss3.
CotIDs) {
1370 auto& ss = slc.
cots[cid - 1];
1371 if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tid) == ss.TjIDs.end())
continue;
1372 if (!
RemoveTj(fcnLabel, slc, tid, ss, doUpdate, prt))
return false;
1397 if (pID <= 0 || pID > (
int)slc.
pfps.size())
return false;
1398 auto& pfp = slc.
pfps[pID - 1];
1400 if (pfp.TPCID != ss3.
TPCID) {
1401 mf::LogVerbatim(
"TC") << fcnLabel <<
" P" << pID <<
" is in the wrong TPC for 3S" << ss3.
ID;
1405 for (
auto tid : pfp.TjIDs) {
1406 auto& tj = slc.
tjs[tid - 1];
1409 auto& ss = slc.
cots[tj.SSID - 1];
1410 if (ss.SS3ID > 0 && ss.SS3ID != ss3.
ID) {
1412 mf::LogVerbatim(
"TC") << fcnLabel <<
" Conflict: 3S" << ss3.
ID <<
" adding P" << pfp.ID
1413 <<
" -> T" << tid <<
" is in 2S" << tj.SSID <<
" that is in 3S" 1414 << ss.SS3ID <<
" that is not this shower";
1419 mf::LogVerbatim(
"TC") << fcnLabel <<
" 3S" << ss3.
ID <<
" adding P" << pfp.ID <<
" -> T" 1420 << tid <<
" is in the correct shower 2S" << tj.SSID;
1425 myprt << fcnLabel <<
" 3S" << ss3.
ID <<
" adding P" << pfp.ID <<
" -> T" << tid;
1426 myprt <<
" tj.SSID 2S" << tj.SSID;
1429 for (
auto& cid : ss3.
CotIDs) {
1430 auto& ss = slc.
cots[cid - 1];
1431 if (ss.CTP != tj.CTP)
continue;
1433 AddTj(fcnLabel, slc, tid, ss, doUpdate, prt);
1450 if (tjID <= 0 || tjID > (
int)slc.
tjs.size())
return false;
1457 mf::LogVerbatim(
"TC") << fcnLabel <<
" T" << tjID <<
" is in the wrong CTP for 2S" << ss.
ID;
1463 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" T" << tjID <<
" is already in 2S" << ss.
ID;
1468 mf::LogVerbatim(
"TC") << fcnLabel <<
" Can't add T" << tjID <<
" to 2S" << ss.
ID 1469 <<
". it is already used in 2S" << tj.
SSID;
1474 ss.
TjIDs.push_back(tjID);
1478 for (
unsigned short ii = 0; ii < ss.
NearTjIDs.size(); ++ii) {
1482 unsigned short cnt = 0;
1483 for (
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
1485 if (tp.
Chg == 0)
continue;
1486 for (
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii)
1487 if (tp.
UseHit[ii]) ++cnt;
1489 unsigned short newSize = ss.
ShPts.size() + cnt;
1490 cnt = ss.
ShPts.size();
1491 ss.
ShPts.resize(newSize);
1493 for (
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
1495 if (tp.
Chg == 0)
continue;
1496 for (
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1498 unsigned int iht = tp.
Hits[ii];
1499 ss.
ShPts[cnt].HitIndex = iht;
1502 ss.
ShPts[cnt].Chg =
hit.Integral();
1503 ss.
ShPts[cnt].Pos[0] =
hit.WireID().Wire;
1512 if (doUpdate)
return UpdateShower(fcnLabel, slc, ss, prt);
1528 if (TjID > (
int)slc.
tjs.size())
return false;
1537 mf::LogVerbatim(
"TC") << fcnLabel <<
" Can't Remove T" << TjID <<
" from 2S" << ss.
ID 1538 <<
" because it's not in this shower";
1545 for (
unsigned short ii = 0; ii < ss.
TjIDs.size(); ++ii) {
1546 if (TjID == ss.
TjIDs[ii]) {
1552 if (!gotit)
return false;
1557 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" Remove T" << TjID <<
" from 2S" << ss.
ID;
1559 if (ss.
TjIDs.empty()) {
1560 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" Removed the last Tj. Killing 2S" << ss.
ID;
1589 if (ss3.
ID == 0)
return false;
1590 if (ss3.
CotIDs.size() < 2)
return false;
1602 double shMaxAlong, along95;
1606 <<
" MeV shMaxAlong " << shMaxAlong <<
" along95 " << along95
1607 <<
" truPFP " << truPFP;
1628 std::array<int, 2> parID{{0, 0}};
1629 std::array<float, 2> parFOM{{-1E6, -1E6}};
1632 std::vector<bool> isParent(slc.
pfps.size() + 1,
false);
1633 for (
auto& oldSS3 : slc.
showers) {
1634 if (oldSS3.ID == 0)
continue;
1635 isParent[oldSS3.ParentID] =
true;
1639 auto TjsInSS3 =
GetAssns(slc,
"3S", ss3.
ID,
"T");
1640 if (TjsInSS3.empty())
return false;
1642 for (
auto& pfp : slc.
pfps) {
1643 if (pfp.ID == 0)
continue;
1644 bool dprt = (pfp.ID == truPFP);
1645 if (pfp.TPCID != ss3.
TPCID)
continue;
1647 if (pfp.PDGCode == 14 || pfp.PDGCode == 14)
continue;
1649 if (pfp.PDGCode == 1111)
continue;
1651 if (isParent[pfp.ID])
continue;
1653 if (
DontCluster(slc, pfp.TjIDs, TjsInSS3))
continue;
1655 float pfpEnergy = 0;
1656 float minEnergy = 1E6;
1657 for (
auto tid : pfp.TjIDs) {
1658 auto& tj = slc.
tjs[tid - 1];
1659 float energy =
ChgToMeV(tj.TotChg);
1661 if (energy < minEnergy) minEnergy =
energy;
1663 pfpEnergy -= minEnergy;
1664 pfpEnergy /= (
float)(pfp.TjIDs.size() - 1);
1668 if (pfpEnergy > energy)
continue;
1674 if (costh1 < 0.4)
continue;
1682 mf::LogVerbatim(
"TC") << fcnLabel <<
" 3S" << ss3.
ID <<
" P" << pfp.ID <<
"_" << pEnd
1683 <<
" distToStart " << sqrt(distToStart2) <<
" distToChgPos " 1684 << sqrt(distToChgPos2) <<
" distToEnd " << sqrt(distToEnd2);
1686 unsigned short shEnd = 0;
1687 if (distToEnd2 < distToStart2) shEnd = 1;
1689 if (shEnd == 0 && distToChgPos2 < distToStart2)
continue;
1690 if (shEnd == 1 && distToChgPos2 < distToEnd2)
continue;
1692 mf::LogVerbatim(
"TC") << fcnLabel <<
" 3S" << ss3.
ID <<
"_" << shEnd <<
" P" << pfp.ID
1693 <<
"_" << pEnd <<
" costh1 " << costh1;
1699 mf::LogVerbatim(
"TC") << fcnLabel <<
" alongTrans " << alongTrans[0] <<
" " 1704 float distToShowerMax = shMaxAlong -
std::abs(alongTrans[0]);
1707 if (prob < 0.1)
continue;
1712 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
1715 for (
auto cid : ss3.
CotIDs) {
1716 auto& ss = slc.
cots[cid - 1];
1717 if (ss.CTP != inCTP)
continue;
1721 if (ssid == 0)
continue;
1723 auto& ss = slc.
cots[ssid - 1];
1724 auto& stp1 = slc.
tjs[ss.ShowerTjID - 1].Pts[1];
1725 float sep =
PosSep(tpFrom.Pos, stp1.Pos);
1726 float toPos = tpFrom.Pos[0] + 0.5 * tpFrom.Dir[0] * sep;
1730 chgFrac += sep * cf;
1732 if (totSep > 0) chgFrac /= totSep;
1750 myprt <<
" 3S" << ss3.
ID <<
"_" << shEnd;
1751 myprt <<
" P" << pfp.ID <<
"_" << pEnd <<
" ParentVars";
1754 myprt <<
" candParFOM " << candParFOM;
1756 if (candParFOM > parFOM[shEnd]) {
1757 parFOM[shEnd] = candParFOM;
1758 parID[shEnd] = pfp.ID;
1762 if (parID[0] == 0 && parID[1] == 0)
return true;
1767 float aveDirFOM = 0;
1769 for (
auto cid : ss3.
CotIDs)
1770 aveDirFOM += slc.
cots[cid - 1].DirectionFOM;
1773 mf::LogVerbatim(
"TC") << fcnLabel <<
" 3S" << ss3.
ID <<
" parID[0] " << parID[0] <<
" fom " 1774 << parFOM[0] <<
" parID[1] " << parID[1] <<
" fom " << parFOM[1]
1775 <<
" aveDirFOM " << aveDirFOM;
1777 if (parID[0] > 0 && parID[1] > 0 && aveDirFOM > 0.3) {
1782 if (parFOM[1] > parFOM[0]) {
1787 else if (parID[0] > 0) {
1795 if (bestPFP == 0)
return true;
1799 <<
" as the parent " << fom3D;
1803 std::vector<ShowerStruct> oldSS(ss3.
CotIDs.size());
1804 for (
unsigned short ii = 0; ii < ss3.
CotIDs.size(); ++ii) {
1809 auto& pfp = slc.
pfps[bestPFP - 1];
1811 ss3.
Vx3ID = pfp.Vx3ID[pend];
1814 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" 3S" << ss3.
ID <<
" successful update";
1818 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" 3S" << ss3.
ID <<
" Failed. Recovering...";
1820 for (
unsigned short ii = 0; ii < oldSS.size(); ++ii) {
1821 auto& ss = oldSS[ii];
1822 slc.
cots[ss.ID - 1] = ss;
1838 if (pfp.
ID == 0 || ss3.
ID == 0)
return false;
1839 if (ss3.
CotIDs.empty())
return false;
1843 for (
auto cid : ss3.
CotIDs) {
1844 auto& ss = slc.
cots[cid - 1];
1845 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
1847 if (ss.ParentID > 0) {
1848 auto& oldParent = slc.
tjs[ss.ParentID - 1];
1854 for (
auto tjid : pfp.
TjIDs) {
1855 auto& tj = slc.
tjs[tjid - 1];
1856 if (tj.CTP != ss.CTP)
continue;
1857 if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tjid) == ss.TjIDs.end()) {
1859 if (!
AddTj(fcnLabel, slc, tjid, ss,
false, prt))
return false;
1865 unsigned short npts = tj.EndPt[1] - tj.EndPt[0] + 1;
1866 if (tp.Delta > 0.5 || npts > 20) {
1869 << tjid <<
" -> 2S" << ss.ID <<
" parent";
1874 << tjid <<
" low projection in plane " << tp.Delta
1875 <<
". Not a parent";
1879 ss.NeedsUpdate =
true;
1881 if (ss3.
Vx3ID > 0) {
1883 auto v2list =
GetAssns(slc,
"3V", vx3.
ID,
"2V");
1884 for (
unsigned short end = 0;
end < 2; ++
end) {
1885 if (tj.VtxID[
end] <= 0)
continue;
1886 if (std::find(v2list.begin(), v2list.end(), tj.VtxID[
end]) != v2list.end())
1887 stj.VtxID[0] = tj.VtxID[
end];
1891 if (!
UpdateShower(fcnLabel, slc, ss, prt))
return false;
1898 float fom3D =
ParentFOM(fcnLabel, slc, pfp, pEnd, ss3, prt);
1899 for (
auto cid : ss3.
CotIDs)
1900 slc.
cots[cid - 1].ParentFOM = fom3D;
1910 if (TjIDs.empty())
return false;
1911 unsigned short cnt = 0;
1912 for (
auto tid : TjIDs) {
1913 if (tid <= 0 || tid > (
int)slc.
tjs.size())
continue;
1927 if (showerEnergy < 10) {
1932 shMaxAlong = 16 * log(showerEnergy / 15);
1934 double scale = 2.75 - 9.29E-4 * showerEnergy;
1935 if (scale < 2) scale = 2;
1936 along95 = scale * shMaxAlong;
1944 double shMaxAlong, shE95Along;
1946 if (shMaxAlong <= 0)
return 0;
1947 double tau = (along + shMaxAlong) / shMaxAlong;
1949 double rms = -0.4 + 2.5 * tau;
1950 if (rms < 0.5) rms = 0.5;
1961 if (showerEnergy < 10)
return 0;
1963 double shMaxAlong, shE95Along;
1970 double tau = (along + shMaxAlong) / shMaxAlong;
1971 if (tau < -1 || tau > 4)
return 0;
1973 double tauHalf, width;
1985 double prob = 1 / (1 + exp((tau - tauHalf) / width));
1997 if (showerEnergy < 10)
return 0;
2000 double prob = exp(-0.5 * trans / rms);
2018 if (ss3.
ID == 0 || pfp.
ID == 0)
return 0;
2021 for (
auto cid : ss3.
CotIDs) {
2022 auto& ss = slc.
cots[cid - 1];
2023 if (ss.ID == 0)
continue;
2024 for (
auto tid : pfp.
TjIDs) {
2025 auto& tj = slc.
tjs[tid - 1];
2026 if (tj.CTP != ss.CTP)
continue;
2031 if (cnt == 0)
return 0;
2042 if (ss.
ID == 0 || tj.
ID == 0)
return 0;
2043 if (ss.
CTP != tj.
CTP)
return 0;
2046 if (stj.Pts.size() != 3)
return 0;
2047 unsigned short closePt1, closePt2;
2050 if (doca == 1E6)
return 0;
2051 float showerLen =
PosSep(stj.Pts[0].Pos, stj.Pts[2].Pos);
2053 if (doca > 5 * showerLen)
return 0.01;
2054 auto& stp = stj.Pts[closePt1];
2055 if (stp.DeltaRMS == 0)
return 0;
2056 auto& ttp = tj.
Pts[closePt2];
2059 float rms = stp.DeltaRMS;
2060 if (rms < 1) rms = 1;
2061 float arg = alongTrans[1] /
rms;
2062 float radProb = exp(-0.5 * arg * arg);
2065 arg = alongTrans[0] /
rms;
2066 float longProb = exp(-0.5 * arg * arg);
2068 float prob = radProb * longProb * costh;
2078 unsigned short pend,
2083 if (ss3.
ID == 0)
return 1000;
2088 for (
auto cid : ss3.
CotIDs) {
2089 auto& ss = slc.
cots[cid - 1];
2090 if (ss.ID == 0)
continue;
2093 for (
auto tid : pfp.
TjIDs) {
2094 auto& tj = slc.
tjs[tid - 1];
2095 if (tj.ID == 0)
continue;
2096 if (tj.CTP == ss.CTP) tjid = tid;
2098 if (tjid == 0)
continue;
2099 auto& ptj = slc.
tjs[tjid - 1];
2100 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
2102 unsigned short ptjEnd =
FarEnd(slc, ptj, stj.Pts[1].Pos);
2103 auto& farTP = ptj.Pts[ptj.EndPt[ptjEnd]];
2104 float chgCtrSep2 =
PosSep2(farTP.Pos, stj.Pts[1].Pos);
2105 if (chgCtrSep2 <
PosSep2(farTP.Pos, stj.Pts[0].Pos) &&
2106 chgCtrSep2 <
PosSep2(farTP.Pos, stj.Pts[2].Pos))
2108 float fom =
ParentFOM(fcnLabel, slc, ptj, ptjEnd, ss, dum1, dum2, prt);
2110 if (fom > 50)
continue;
2113 if (ss.AspectRatio > 0) wt = 1 / ss.AspectRatio;
2117 if (wsum == 0)
return 100;
2118 float fom = sum / wsum;
2130 unsigned short& tjEnd,
2142 if (tjEnd > 1)
return 1000;
2143 if (ss.
Energy == 0)
return 1000;
2145 if (ss.
ID == 0)
return 1000;
2146 if (ss.
TjIDs.empty())
return 1000;
2177 double shMaxAlong, shE95Along;
2183 if (prob < 0.05)
return 100;
2186 if (alongTrans[1] > shMaxAlong)
return 100;
2188 float longFOM =
std::abs(alongcm + shMaxAlong) / 14;
2192 float transFOM = -1;
2194 transFOM = alongTrans[1] / stp0.
DeltaRMS;
2204 float dang1FOM = dang1 / 0.1;
2208 float dang2FOM = dang1 / 0.1;
2212 std::vector<int> tjlist(1);
2219 if (tj.
VtxID[tjEnd] > 0) {
2222 vx2Score = vx2.
Score;
2224 vxFOM =
std::abs(shMaxAlong - vx2Sep) / 20;
2229 float chgFracFOM = (1 - chgFrac) / 0.1;
2234 float chgFrcBtwFOM = (1 - chgFrac) / 0.05;
2235 fom += chgFrcBtwFOM;
2246 myprt <<
" 2S" << ss.
ID;
2247 myprt <<
" T" << tj.
ID <<
"_" << tjEnd <<
" Pos " <<
PrintPos(slc, ptp);
2249 myprt <<
" along " << std::fixed <<
std::setprecision(1) << alongTrans[0] <<
" fom " 2251 myprt <<
" trans " << alongTrans[1] <<
" fom " << transFOM;
2252 myprt <<
" prob " << prob;
2253 myprt <<
" dang1 " << dang1 <<
" fom " << dang1FOM;
2254 myprt <<
" dang2 " << dang2 <<
" fom " << dang2FOM;
2255 myprt <<
" vx2Score " << vx2Score <<
" fom " << vxFOM;
2256 myprt <<
" chgFrac " << chgFrac <<
" fom " << chgFracFOM;
2257 myprt <<
" chgFracBtw " << chgFracBtw <<
" fom " << chgFrcBtwFOM;
2258 myprt <<
" FOM " << fom;
2269 unsigned short tjEnd,
2288 if (tjEnd > 1)
return false;
2293 unsigned short otherEnd = 1 - tjEnd;
2295 if (tj.
VtxID[otherEnd] == 0)
return false;
2296 unsigned short ivx = tj.
VtxID[otherEnd] - 1;
2298 if (slc.
vtxs[ivx].Topo != 8 && slc.
vtxs[ivx].Topo != 10)
return false;
2301 <<
" was split by a 3D vertex";
2311 if (slc.
cots.empty())
return;
2317 myprt << fcnLabel <<
" list";
2318 for (
auto& ss : slc.
cots) {
2319 if (ss.CTP != inCTP)
continue;
2320 if (ss.ID == 0)
continue;
2321 myprt <<
" ss.ID " << ss.ID <<
" NearTjs";
2322 for (
auto&
id : ss.NearTjIDs)
2328 bool keepMerging =
true;
2329 while (keepMerging) {
2330 keepMerging =
false;
2331 for (
unsigned short ci1 = 0; ci1 < slc.
cots.size() - 1; ++ci1) {
2333 if (ss1.
CTP != inCTP)
continue;
2334 if (ss1.
ID == 0)
continue;
2335 if (ss1.
TjIDs.empty())
continue;
2337 std::vector<int> ss1list = ss1.
TjIDs;
2339 for (
unsigned short ci2 = ci1 + 1; ci2 < slc.
cots.size(); ++ci2) {
2341 if (ss2.
CTP != inCTP)
continue;
2342 if (ss2.
ID == 0)
continue;
2343 if (ss2.
TjIDs.empty())
continue;
2345 std::vector<int> ss2list = ss2.
TjIDs;
2348 if (shared.empty())
continue;
2351 myprt << fcnLabel <<
" Merge 2S" << ss2.
ID <<
" into 2S" << ss1.
ID 2352 <<
"? shared nearby:";
2353 for (
auto tjid : shared)
2354 myprt <<
" T" << tjid;
2357 bool doMerge =
false;
2358 for (
auto& tjID : shared) {
2359 bool inSS1 = (std::find(ss1.
TjIDs.begin(), ss1.
TjIDs.end(), tjID) != ss1.
TjIDs.end());
2360 bool inSS2 = (std::find(ss2.
TjIDs.begin(), ss2.
TjIDs.end(), tjID) != ss2.
TjIDs.end());
2361 if (inSS1 && !inSS2) doMerge =
true;
2362 if (!inSS1 && inSS2) doMerge =
true;
2364 if (inSS1 || inSS2)
continue;
2365 auto& tj = slc.
tjs[tjID - 1];
2367 if (tj.PDGCode == 13 && tj.Pts.size() > 100 && tj.ChgRMS < 0.5) {
2370 << fcnLabel <<
" T" << tj.ID <<
" looks like a muon. Don't add it";
2376 if (!TInP.empty()) {
2377 auto& pfp = slc.
pfps[TInP[0] - 1];
2378 if (pfp.PDGCode == 13 &&
MCSMom(slc, pfp.TjIDs) > 500)
continue;
2381 if (
AddTj(fcnLabel, slc, tjID, ss1,
false, prt)) doMerge =
true;
2383 if (!doMerge)
continue;
2422 if (slc.
cots.empty())
return;
2433 bool didMerge =
true;
2437 for (
unsigned short ict = 0; ict < slc.
cots.size() - 1; ++ict) {
2438 auto& iss = slc.
cots[ict];
2439 if (iss.ID == 0)
continue;
2440 if (iss.TjIDs.empty())
continue;
2441 if (iss.CTP != inCTP)
continue;
2442 for (
unsigned short jct = ict + 1; jct < slc.
cots.size(); ++jct) {
2443 auto& jss = slc.
cots[jct];
2444 if (jss.ID == 0)
continue;
2445 if (jss.TjIDs.empty())
continue;
2446 if (jss.CTP != iss.CTP)
continue;
2447 if (
DontCluster(slc, iss.TjIDs, jss.TjIDs))
continue;
2448 bool doMerge =
false;
2449 for (
auto& ivx : iss.Envelope) {
2454 for (
auto& jvx : jss.Envelope) {
2461 for (
auto& ivx : iss.Envelope) {
2462 for (
auto& jvx : jss.Envelope) {
2463 if (
PosSep2(ivx, jvx) < sepCut2) {
2466 << fcnLabel <<
" Envelopes 2S" << iss.ID <<
" 2S" << jss.ID <<
" are close " 2475 if (!doMerge)
continue;
2479 unsigned short iClosePt = 0;
2480 unsigned short jClosePt = 0;
2482 auto& istj = slc.
tjs[iss.ShowerTjID - 1];
2483 auto& jstj = slc.
tjs[jss.ShowerTjID - 1];
2484 for (
unsigned short ipt = 0; ipt < 3; ++ipt) {
2485 for (
unsigned short jpt = 0; jpt < 3; ++jpt) {
2486 float sep =
PosSep2(istj.Pts[ipt].Pos, jstj.Pts[jpt].Pos);
2494 float costh =
DotProd(istj.Pts[0].Dir, jstj.Pts[0].Dir);
2495 if (iClosePt == 0 && jClosePt == 0 && costh < 0.955) {
2498 << fcnLabel <<
" showers are close at the start points with costh " << costh
2502 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" Merge " << iss.ID <<
" and " << jss.ID;
2530 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
": MergeShowerChain inCTP " << inCTP;
2532 std::vector<int> sids;
2533 std::vector<TrajPoint> tpList;
2534 for (
unsigned short ict = 0; ict < slc.
cots.size(); ++ict) {
2536 if (iss.
ID == 0)
continue;
2537 if (iss.
TjIDs.empty())
continue;
2538 if (iss.
CTP != inCTP)
continue;
2540 if (iss.
Energy < 50)
continue;
2542 sids.push_back(iss.
ID);
2546 if (sids.size() < 3)
return;
2549 std::vector<SortEntry> sortVec(sids.size());
2550 for (
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
2551 sortVec[ii].index = ii;
2552 sortVec[ii].val = tpList[ii].Pos[0];
2556 auto ttpList = tpList;
2557 for (
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
2558 unsigned short indx = sortVec[ii].index;
2559 sids[ii] = tsids[indx];
2560 tpList[ii] = ttpList[indx];
2565 float maxDelta = 30;
2566 for (
unsigned short ii = 0; ii < sids.size() - 2; ++ii) {
2567 auto& iss = slc.
cots[sids[ii] - 1];
2568 if (iss.ID == 0)
continue;
2569 unsigned short jj = ii + 1;
2570 auto& jss = slc.
cots[sids[jj] - 1];
2571 if (jss.ID == 0)
continue;
2572 std::vector<int> chain;
2573 float sepij =
PosSep(tpList[ii].Pos, tpList[jj].Pos);
2574 if (sepij > minSep)
continue;
2575 bool skipit =
DontCluster(slc, iss.TjIDs, jss.TjIDs);
2578 <<
PrintPos(slc, tpList[ii].Pos) <<
" j2S" << jss.ID <<
" " 2579 <<
PrintPos(slc, tpList[jj].Pos) <<
" sepij " << sepij <<
" skipit? " 2581 if (skipit)
continue;
2585 for (
unsigned short kk = jj + 1; kk < sids.size(); ++kk) {
2586 auto& kss = slc.
cots[sids[kk] - 1];
2587 if (kss.ID == 0)
continue;
2588 if (
DontCluster(slc, iss.TjIDs, kss.TjIDs))
continue;
2589 if (
DontCluster(slc, jss.TjIDs, kss.TjIDs))
continue;
2590 float sepjk =
PosSep(tpList[jj].Pos, tpList[kk].Pos);
2591 float delta =
PointTrajDOCA(slc, tpList[kk].Pos[0], tpList[kk].Pos[1], tp);
2594 myprt << fcnLabel <<
" k2S" << kss.ID <<
" " <<
PrintPos(slc, tpList[kk].Pos)
2595 <<
" sepjk " << sepjk <<
" delta " << delta;
2596 if (sepjk > minSep || delta > maxDelta) {
2597 myprt <<
" failed separation " << minSep <<
" or delta cut " << maxDelta;
2600 myprt <<
" add to the chain";
2603 if (sepjk > minSep || delta > maxDelta) {
2605 if (chain.size() > 2) {
2610 myprt << fcnLabel <<
" merged chain";
2611 for (
auto ssID : chain)
2612 myprt <<
" 2S" << ssID;
2613 myprt <<
" -> 2S" << newID;
2621 if (chain.empty()) {
2623 chain[0] = sids[ii];
2624 chain[1] = sids[jj];
2625 chain[2] = sids[kk];
2628 chain.push_back(sids[kk]);
2635 if (chain.size() > 2) {
2639 myprt << fcnLabel <<
" merged chain";
2640 for (
auto ssID : chain)
2641 myprt <<
" " << ssID;
2642 myprt <<
" -> new ssID " << newID;
2667 std::vector<TjSS> tjss;
2670 std::vector<int> tjid(1);
2671 for (
auto& ss : slc.
cots) {
2672 if (ss.ID == 0)
continue;
2673 if (ss.CTP != inCTP)
continue;
2675 if (ss.Energy > 300)
continue;
2676 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
2677 auto stp0 = stj.Pts[0];
2678 float bestDang = 0.3;
2681 for (
auto& tj : slc.
tjs) {
2682 if (tj.AlgMod[
kKilled])
continue;
2683 if (tj.AlgMod[
kHaloTj])
continue;
2684 if (tj.CTP != ss.CTP)
continue;
2686 if (tj.SSID > 0)
continue;
2694 float tjEnergy =
ChgToMeV(tj.TotChg);
2696 unsigned short farEnd =
FarEnd(slc, tj, stj.Pts[1].Pos);
2698 unsigned short midpt = 0.5 * (tj.EndPt[0] + tj.EndPt[1]);
2699 float mom1 =
MCSMom(slc, tj, tj.EndPt[farEnd], midpt);
2700 float mom2 =
MCSMom(slc, tj, tj.EndPt[1 - farEnd], midpt);
2701 float asym = (mom1 - mom2) / (mom1 + mom2);
2702 auto& farTP = tj.Pts[tj.EndPt[farEnd]];
2704 float doca =
PointTrajDOCA(slc, stp0.Pos[0], stp0.Pos[1], farTP);
2705 float sep =
PosSep(farTP.Pos, stp0.Pos);
2706 float dang = doca / sep;
2709 myprt << fcnLabel <<
" Candidate 2S" << ss.ID <<
" T" << tj.ID <<
"_" << farEnd;
2710 myprt <<
" ShEnergy " << (
int)ss.Energy <<
" tjEnergy " << (
int)tjEnergy;
2711 myprt <<
" doca " << doca <<
" sep " << sep <<
" dang " << dang <<
" asym " << asym;
2713 if (tjEnergy < ss.Energy)
continue;
2714 if (asym < 0.5)
continue;
2717 if (sep > 100)
continue;
2718 if (dang > bestDang)
continue;
2722 if (bestTj == 0)
continue;
2725 match.tjID = bestTj;
2726 match.dang = bestDang;
2727 tjss.push_back(match);
2730 if (tjss.empty())
return;
2733 bool keepGoing =
true;
2736 float bestDang = 0.3;
2738 for (
unsigned short mat = 0; mat < tjss.size(); ++mat) {
2739 auto& match = tjss[mat];
2741 if (match.dang < 0)
continue;
2742 if (match.dang < bestDang) bestMatch = mat;
2744 if (bestMatch > 0) {
2745 auto& match = tjss[bestMatch];
2746 auto& ss = slc.
cots[match.ssID - 1];
2747 if (!
AddTj(fcnLabel, slc, match.tjID, ss,
true, prt)) {
2753 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
2773 constexpr
float radLen = 14 / 0.3;
2777 mf::LogVerbatim(
"TC") << fcnLabel <<
" MergeSubShowers checking using ShowerParams";
2781 <<
" MergeSubShowers checking using radiation length cut ";
2785 bool keepMerging =
true;
2786 while (keepMerging) {
2787 keepMerging =
false;
2789 std::vector<SortEntry> sortVec;
2790 for (
auto& ss : slc.
cots) {
2791 if (ss.ID == 0)
continue;
2792 if (ss.CTP != inCTP)
continue;
2794 se.
index = ss.ID - 1;
2796 sortVec.push_back(se);
2798 if (sortVec.size() < 2)
return;
2800 for (
unsigned short ii = 0; ii < sortVec.size() - 1; ++ii) {
2802 if (iss.
ID == 0)
continue;
2806 double shMaxAlong, along95;
2809 along95 -= shMaxAlong;
2812 for (
unsigned short jj = ii + 1; jj < sortVec.size(); ++jj) {
2814 if (jss.
ID == 0)
continue;
2823 if (alongTrans[0] < 0)
continue;
2825 float alongCut = along95;
2831 myprt << fcnLabel <<
" Candidate i2S" << iss.
ID <<
" E = " << (
int)iss.
Energy 2832 <<
" j2S" << jss.
ID <<
" E = " << (
int)jss.
Energy;
2833 myprt <<
" along " << std::fixed <<
std::setprecision(1) << alongTrans[0] <<
" trans " 2835 myprt <<
" alongCut " << alongCut <<
" probLong " << probLong <<
" probTran " 2838 if (alongTrans[0] > alongCut)
continue;
2839 if (alongTrans[1] > alongTrans[0])
continue;
2844 float trad = sep / radLen;
2854 float dang = delta / sep;
2857 <<
" separation " << (
int)sep <<
" radiation lengths " << trad
2858 <<
" delta " << delta <<
" dang " << dang;
2859 if (trad > 3)
continue;
2861 if (dang > 0.3)
continue;
2864 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" Merge them. Re-find shower center, etc";
2872 if (keepMerging)
break;
2888 if (ssIDs.size() < 2)
return 0;
2890 for (
auto ssID : ssIDs)
2891 if (ssID <= 0 || ssID > (
int)slc.
cots.size())
return 0;
2894 auto& ss0 = slc.
cots[ssIDs[0] - 1];
2895 std::vector<int> tjl;
2896 for (
auto ssID : ssIDs) {
2897 auto& ss = slc.
cots[ssID - 1];
2898 if (ss.CTP != ss0.CTP)
return 0;
2899 tjl.insert(tjl.end(), ss.TjIDs.begin(), ss.TjIDs.end());
2900 if (ss.SS3ID > 0 && ss3Assn == 0) ss3Assn = ss.SS3ID;
2901 if (ss.SS3ID > 0 && ss.SS3ID != ss3Assn)
return 0;
2904 for (
auto tjID : tjl) {
2905 auto& tj = slc.
tjs[tjID - 1];
2906 if (tj.CTP != ss0.CTP || tj.AlgMod[
kKilled])
return 0;
2910 for (
auto ssID : ssIDs) {
2911 auto& ss = slc.
cots[ssID - 1];
2914 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
2920 if (newss.ID == 0)
return 0;
2922 for (
auto tid : tjl) {
2923 auto& tj = slc.
tjs[tid - 1];
2926 newss.SS3ID = ss3Assn;
2950 if (icotID <= 0 || icotID > (
int)slc.
cots.size())
return false;
2952 if (iss.
ID == 0)
return false;
2953 if (iss.
TjIDs.empty())
return false;
2956 if (jcotID <= 0 || jcotID > (
int)slc.
cots.size())
return false;
2958 if (jss.
TjIDs.empty())
return false;
2959 if (jss.
ID == 0)
return false;
2962 if (iss.
CTP != jss.
CTP)
return false;
2970 if (!itj.
Pts[1].Hits.empty() || !jtj.
Pts[1].Hits.empty())
return false;
2975 ktj.
ID = slc.
tjs.size() + 1;
2977 slc.
tjs.push_back(ktj);
2990 std::sort(iss.
TjIDs.begin(), iss.
TjIDs.end());
2992 for (
auto tid : iss.
TjIDs) {
2993 auto& tj = slc.
tjs[tid - 1];
3022 if (istj > slc.
tjs.size() - 1)
return false;
3023 if (jstj > slc.
tjs.size() - 1)
return false;
3031 mf::LogVerbatim(
"TC") << fcnLabel <<
" MergeShowerTjsAndStore Tj IDs " << itj.
ID <<
" " 3044 if (icotID == 0)
return false;
3046 if (iss.
ID == 0)
return false;
3047 if (iss.
TjIDs.empty())
return false;
3049 if (jcotID == 0)
return false;
3051 if (jss.
ID == 0)
return false;
3052 if (jss.
TjIDs.empty())
return false;
3067 if (ss.
ID == 0)
return false;
3068 if (ss.
ShPts.empty())
return false;
3070 if (stj.
Pts.size() != 3)
return false;
3074 for (
auto& tp : stj.
Pts) {
3078 tp.HitPos = {{0.0, 0.0}};
3081 float minAlong = ss.
ShPts[0].RotPos[0];
3082 float maxAlong = ss.
ShPts[ss.
ShPts.size() - 1].RotPos[0];
3083 float sectionLength = (maxAlong - minAlong) / 3;
3084 float sec0 = minAlong + sectionLength;
3085 float sec2 = maxAlong - sectionLength;
3087 for (
auto& spt : ss.
ShPts) {
3089 unsigned short ipt = 0;
3090 if (spt.RotPos[0] < sec0) {
3094 else if (spt.RotPos[0] > sec2) {
3102 stj.
Pts[ipt].Chg += spt.Chg;
3107 stj.
Pts[ipt].DeltaRMS += spt.Chg *
std::abs(spt.RotPos[1]);
3108 ++stj.
Pts[ipt].NTPsFit;
3110 stj.
Pts[ipt].HitPos[0] += spt.Chg * spt.Pos[0];
3111 stj.
Pts[ipt].HitPos[1] += spt.Chg * spt.Pos[1];
3114 for (
auto& tp : stj.
Pts) {
3116 tp.DeltaRMS /= tp.Chg;
3117 tp.HitPos[0] /= tp.Chg;
3118 tp.HitPos[1] /= tp.Chg;
3124 if (stj.
Pts[0].Chg == 0 || stj.
Pts[2].Chg == 0)
return false;
3127 if (stj.
Pts[1].Chg == 0) {
3129 stj.
Pts[1].HitPos[0] = 0.5 * (stj.
Pts[0].HitPos[0] + stj.
Pts[2].HitPos[0]);
3130 stj.
Pts[1].HitPos[1] = 0.5 * (stj.
Pts[0].HitPos[1] + stj.
Pts[2].HitPos[1]);
3138 myprt << fcnLabel <<
" 2S" << ss.
ID;
3140 myprt << stj.
Pts[1].HitPos[0] <<
" " << stj.
Pts[1].HitPos[1] <<
" " << stj.
Pts[1].HitPos[2];
3142 myprt << stj.
Pts[0].DeltaRMS <<
" " << stj.
Pts[1].DeltaRMS <<
" " << stj.
Pts[2].DeltaRMS;
3155 if (ss.
ID == 0)
return;
3156 if (ss.
TjIDs.empty())
return;
3162 for (
auto& sspt : ss.
ShPts) {
3163 sspt.RotPos[0] = -sspt.RotPos[0];
3164 sspt.RotPos[1] = -sspt.RotPos[1];
3184 if (cotID > (
int)slc.
cots.size())
return;
3186 if (ss.
ID == 0)
return;
3196 for (
auto cid : ss3.
CotIDs) {
3197 if (cid == 0 || (
unsigned short)cid > slc.
cots.size())
continue;
3198 auto& ss = slc.
cots[cid - 1];
3199 if (ss.SS3ID > 0 && ss.SS3ID != ss3.
ID)
continue;
3215 if (ss.
ID == 0)
return;
3220 if (!stp1.Hits.empty())
return;
3225 std::vector<int> newCIDs;
3226 for (
auto cid : ss3.CotIDs) {
3227 if (cid != ss.
ID) newCIDs.push_back(cid);
3229 ss3.CotIDs = newCIDs;
3237 for (
auto& tjID : ss.
TjIDs) {
3259 if (tjlist1.empty() || tjlist2.empty())
return false;
3261 for (
auto tid1 : tjlist1) {
3262 for (
auto tid2 : tjlist2) {
3264 if (ttid1 > tid2)
std::swap(ttid1, tid2);
3266 if (dc.TjIDs[0] == ttid1 && dc.TjIDs[1] == tid2)
return true;
3280 if (slc.
tjs.size() > 20000)
return;
3286 std::vector<std::vector<int>> tjLists;
3287 std::vector<int> tjids;
3288 for (
auto& tj : slc.
tjs) {
3289 if (tj.CTP != inCTP)
continue;
3290 if (tj.AlgMod[
kKilled])
continue;
3291 if (tj.AlgMod[
kHaloTj])
continue;
3295 bool skipit =
false;
3296 for (
unsigned short end = 0;
end < 2; ++
end)
3297 if (tj.EndFlag[
end][
kBragg]) skipit =
true;
3298 if (skipit)
continue;
3302 if (npwc > 100)
continue;
3309 if (tj.ChgRMS > typicalChgRMS) momCut *= tj.ChgRMS / typicalChgRMS;
3310 if (tj.MCSMom > momCut)
continue;
3312 tjids.push_back(tj.ID);
3315 if (tjids.size() < 2)
return;
3317 for (
unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
3319 for (
unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
3321 unsigned short ipt1, ipt2;
3328 bool inlist =
false;
3329 for (
unsigned short it = 0; it < tjLists.size(); ++it) {
3331 (std::find(tjLists[it].
begin(), tjLists[it].
end(), tj1.
ID) != tjLists[it].end());
3333 (std::find(tjLists[it].
begin(), tjLists[it].
end(), tj2.
ID) != tjLists[it].end());
3334 if (tj1InList || tj2InList) {
3336 if (!tj1InList) tjLists[it].push_back(tj1.
ID);
3337 if (!tj2InList) tjLists[it].push_back(tj2.
ID);
3345 std::vector<int> newlist(2);
3346 newlist[0] = tj1.
ID;
3347 newlist[1] = tj2.
ID;
3348 tjLists.push_back(newlist);
3352 if (tjLists.empty())
return;
3355 for (
auto& tjl : tjLists) {
3357 if (tjl.size() < 3)
continue;
3358 for (
auto& tjID : tjl) {
3359 auto& tj = slc.
tjs[tjID - 1];
3365 unsigned short nsh = 0;
3366 for (
auto& tjl : tjLists) {
3367 for (
auto& tjID : tjl) {
3368 auto& tj = slc.
tjs[tjID - 1];
3372 mf::LogVerbatim(
"TC") <<
"TagShowerLike tagged " << nsh <<
" Tjs vertices in CTP " << inCTP;
3389 std::vector<int> ntj;
3392 constexpr
float fiveRadLen = 200;
3395 for (
auto vx : slc.
vtxs) {
3396 if (vx.CTP != ss.
CTP)
continue;
3397 if (vx.ID == 0)
continue;
3399 auto vxTjIDs =
GetAssns(slc,
"2V", vx.
ID,
"T");
3400 for (
auto tjID : vxTjIDs) {
3402 if (std::find(ss.
TjIDs.begin(), ss.
TjIDs.end(), tjID) != ss.
TjIDs.end())
continue;
3404 if (std::find(ntj.begin(), ntj.end(), tjID) != ntj.end())
continue;
3405 ntj.push_back(tjID);
3410 for (
auto& tj : slc.
tjs) {
3411 if (tj.CTP != ss.
CTP)
continue;
3412 if (tj.AlgMod[
kKilled])
continue;
3416 if (std::find(ss.
TjIDs.begin(), ss.
TjIDs.end(), tj.ID) != ss.
TjIDs.end())
continue;
3418 if (std::find(ntj.begin(), ntj.end(), tj.ID) != ntj.end())
continue;
3420 if (tj.Pts.size() > 40 && tj.MCSMom > 200) {
3421 float delta =
PointTrajDOCA(slc, stj.Pts[1].Pos[0], stj.Pts[1].Pos[1], tj.Pts[tj.EndPt[0]]);
3424 float doca = fiveRadLen;
3425 unsigned short spt = 0, ipt = 0;
3427 if (doca < fiveRadLen) {
3428 ntj.push_back(tj.ID);
3434 bool isInside =
false;
3435 for (
unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ipt += 3) {
3443 unsigned short ipt = tj.EndPt[1];
3446 if (isInside) ntj.push_back(tj.ID);
3448 if (ntj.size() > 1) std::sort(ntj.begin(), ntj.end());
3450 mf::LogVerbatim(
"TC") << fcnLabel <<
" Found " << ntj.size() <<
" Tjs near ss.ID " << ss.
ID;
3461 if (itj > slc.
tjs.size() - 1)
return;
3466 for (
auto& tp : slc.
tjs[itj].Pts) {
3467 for (
unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3469 if (tp.UseHit[ii])
continue;
3470 unsigned int iht = tp.Hits[ii];
3472 if (slc.
slHits[iht].InTraj <= 0)
continue;
3473 if ((
unsigned int)slc.
slHits[iht].InTraj > slc.
tjs.size())
continue;
3476 if (tj.
MCSMom > maxMom)
continue;
3479 if (std::find(list.begin(), list.end(), slc.
slHits[iht].InTraj) != list.end())
continue;
3480 list.push_back(slc.
slHits[iht].InTraj);
3490 if (ss.
ID == 0)
return;
3491 if (ss.
TjIDs.empty())
return;
3494 if (stj.
Pts[0].Pos[0] == 0)
return;
3523 float cs = cos(stp1.
Ang);
3524 float sn = sin(stp1.
Ang);
3527 float pos0 = cs * vtx[0] - sn * vtx[1];
3528 float pos1 = sn * vtx[0] + cs * vtx[1];
3530 vtx[0] = pos0 + stp1.
Pos[0];
3531 vtx[1] = pos1 + stp1.
Pos[1];
3537 myprt << fcnLabel <<
" 2S" << ss.
ID <<
" Envelope";
3553 if (ss.
Envelope.empty())
return false;
3554 if (ss.
ID == 0)
return false;
3555 if (ss.
TjIDs.empty())
return false;
3561 std::vector<int>
tmp(1);
3562 unsigned short nadd = 0;
3563 for (
auto& tj : slc.
tjs) {
3564 if (tj.CTP != ss.
CTP)
continue;
3565 if (tj.AlgMod[
kKilled])
continue;
3566 if (tj.SSID > 0)
continue;
3569 if (tj.ParentID == 0)
continue;
3571 if (neutPrimTj > 0 && neutPrimTj != tj.ID) {
3578 if (std::find(ss.
TjIDs.begin(), ss.
TjIDs.end(), tj.ID) != ss.
TjIDs.end())
continue;
3585 if (!end0Inside && !end1Inside)
continue;
3586 if (end0Inside && end1Inside) {
3588 if (
AddTj(fcnLabel, slc, tj.
ID, ss,
false, prt)) ++nadd;
3595 if (tj.MCSMom > 200) {
3596 float tjAngle = tj.Pts[tj.EndPt[0]].Ang;
3599 mf::LogVerbatim(
"TC") << fcnLabel <<
" high MCSMom " << tj.MCSMom <<
" dangPull " 3601 if (dangPull > 2)
continue;
3603 if (
AddTj(fcnLabel, slc, tj.
ID, ss,
false, prt)) { ++nadd; }
3605 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" AddTj failed to add T" << tj.ID;
3610 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" Added " << nadd <<
" trajectories ";
3616 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" No new trajectories added to envelope ";
3632 if (ss.
Envelope.empty())
return false;
3633 if (ss.
ID == 0)
return false;
3634 if (ss.
TjIDs.empty())
return false;
3637 unsigned short ipl = planeID.
Plane;
3642 std::vector<unsigned int> newHits;
3645 float fLoWire = 1E6;
3651 if (vtx[0] < fLoWire) fLoWire = vtx[0];
3652 if (vtx[0] > fHiWire) fHiWire = vtx[0];
3653 if (vtx[1] < loTick) loTick = vtx[1];
3654 if (vtx[1] > hiTick) hiTick = vtx[1];
3658 unsigned int loWire = std::nearbyint(fLoWire);
3659 unsigned int hiWire = std::nearbyint(fHiWire) + 1;
3661 std::array<float, 2> point;
3662 for (
unsigned int wire = loWire; wire < hiWire; ++wire) {
3664 if (slc.
wireHitRange[ipl][wire].first == UINT_MAX)
continue;
3665 unsigned int firstHit = slc.
wireHitRange[ipl][wire].first;
3666 unsigned int lastHit = slc.
wireHitRange[ipl][wire].second;
3667 for (
unsigned int iht = firstHit; iht < lastHit; ++iht) {
3669 if (slc.
slHits[iht].InTraj != 0)
continue;
3672 if (
hit.PeakTime() < loTick)
continue;
3674 if (
hit.PeakTime() > hiTick)
break;
3676 point[0] =
hit.WireID().Wire;
3679 newHits.push_back(iht);
3684 if (newHits.empty()) {
3690 stp0.
Hits.insert(stp0.
Hits.end(), newHits.begin(), newHits.end());
3691 for (
auto& iht : newHits)
3706 if (cotID > (
int)slc.
cots.size())
return;
3709 if (ss.
ID == 0)
return;
3710 if (ss.
TjIDs.empty())
return;
3721 mf::LogVerbatim(
"TC") << fcnLabel <<
" Not possible due to poor AspectRatio " 3728 if (schg.empty())
return;
3732 unsigned short startPt = USHRT_MAX;
3734 for (
unsigned short ii = 0; ii < schg.size() - 1; ++ii) {
3735 if (schg[ii] > 0 && schg[ii + 1] > 0) {
3741 if (startPt == USHRT_MAX)
return;
3747 for (
unsigned short ii = startPt; ii < schg.size() - 1; ++ii) {
3749 rms += schg[ii] * schg[ii];
3753 rms = rms - cnt * ave * ave;
3754 if (rms < 0)
return;
3755 rms = sqrt(rms / (cnt - 1));
3759 myprt << fcnLabel <<
" schg:";
3760 for (
unsigned short ii = 0; ii < 20; ++ii)
3761 myprt <<
" " << (
int)schg[ii];
3762 myprt <<
"\n First guess at the charge " << (
int)chg <<
" average charge of all bins " 3763 << (
int)ave <<
" rms " << (
int)rms;
3769 unsigned short nBinsAverage = 5;
3770 double maxChg = 2 * chg;
3771 for (
unsigned short nit = 0; nit < 2; ++nit) {
3775 for (
unsigned short ii = startPt; ii < schg.size() - 1; ++ii) {
3777 if (schg[ii] > maxChg && schg[ii + 1] > maxChg)
break;
3779 if (schg[ii] == 0 && schg[ii + 1] == 0)
break;
3780 if (schg[ii] > maxChg)
continue;
3782 sum2 += schg[ii] * schg[ii];
3784 if (cnt == nBinsAverage)
break;
3790 <<
" is too low. sum " << (
int)sum <<
" maxChg " << (
int)maxChg;
3793 chg = schg[startPt];
3799 double arg = sum2 - cnt * chg * chg;
3801 rms = sqrt(arg / (cnt - 1));
3803 double maxrms = 0.5 * sum;
3804 if (rms > maxrms) rms = maxrms;
3805 maxChg = chg + 2 *
rms;
3807 mf::LogVerbatim(
"TC") << fcnLabel <<
" nit " << nit <<
" cnt " << cnt <<
" chg " << (
int)chg
3808 <<
" rms " << (
int)rms <<
" maxChg " << (
int)maxChg
3809 <<
" nBinsAverage " << nBinsAverage;
3816 mf::LogVerbatim(
"TC") << fcnLabel <<
" 2S" << cotID <<
" Starting charge " << (
int)stp0.AveChg
3817 <<
" startPt " << startPt;
3828 constexpr
unsigned short nbins = 20;
3829 std::vector<float> schg(nbins);
3830 if (ss.
ID == 0)
return schg;
3831 if (ss.
TjIDs.empty())
return schg;
3836 float minAlong = ss.
ShPts[0].RotPos[0] - 2;
3843 std::array<float, 2> chgPos;
3846 for (
auto& sspt : ss.
ShPts) {
3847 unsigned short indx = (
unsigned short)((sspt.RotPos[0] - minAlong));
3848 if (indx > nbins - 1)
break;
3850 if (
std::abs(sspt.RotPos[1]) > maxTrans)
continue;
3851 unsigned int iht = sspt.HitIndex;
3853 float peakTime =
hit.PeakTime();
3854 float amp =
hit.PeakAmplitude();
3856 chgPos[0] =
hit.WireID().Wire - stp1.
Pos[0];
3857 for (
float time = peakTime - 2.5 * rms;
time < peakTime + 2.5 *
rms; ++
time) {
3859 along = cs * chgPos[0] - sn * chgPos[1];
3860 if (along < minAlong)
continue;
3861 indx = (
unsigned short)(along - minAlong);
3862 if (indx > nbins - 1)
continue;
3863 arg = (
time - peakTime) / rms;
3864 schg[indx] += amp * exp(-0.5 * arg * arg);
3879 if (cotID > (
int)slc.
cots.size())
return;
3882 if (ss.
ID == 0)
return;
3883 if (ss.
TjIDs.empty())
return;
3884 std::cout <<
"PTS Pos0 Pos1 RPos0 RPos1 Chg TID\n";
3885 for (
auto& pt : ss.
ShPts) {
3886 std::cout <<
"PTS " << std::fixed <<
std::setprecision(1) << pt.Pos[0] <<
" " << pt.Pos[1]
3887 <<
" " << pt.RotPos[0] <<
" " << pt.RotPos[1];
3888 std::cout <<
" " << (
int)pt.Chg <<
" " << pt.TID;
3900 bool newShowers =
false;
3901 for (
auto& ss : slc.
cots) {
3902 if (ss.ID == 0)
continue;
3903 if (ss.ShowerTjID == 0)
continue;
3906 if (!stj.
Pts[1].Hits.empty()) {
3907 std::cout <<
"TTjH: ShowerTj T" << stj.
ID <<
" already has " << stj.
Pts[1].Hits.size()
3912 for (
auto& tjID : ss.TjIDs) {
3913 unsigned short itj = tjID - 1;
3915 std::cout <<
"TTjH: Coding error. T" << tjID <<
" is a ShowerTj but is in TjIDs\n";
3918 if (slc.
tjs[itj].SSID <= 0) {
3919 std::cout <<
"TTjH: Coding error. Trying to transfer T" << tjID
3920 <<
" hits but it isn't an InShower Tj\n";
3925 stj.
Pts[1].Hits.insert(stj.
Pts[1].Hits.end(), thits.begin(), thits.end());
3930 for (
auto& iht : stj.
Pts[1].Hits)
3943 for (
unsigned short ii = 0; ii < slc.
cots.size(); ++ii) {
3944 if (ShowerTjID == slc.
cots[ii].ShowerTjID)
return ii + 1;
3954 if (ss3.
ID == 0)
return 0;
3955 if (ss3.
Energy.empty())
return 0;
3960 ave /= ss3.
Energy.size();
3969 if (tjIDs.empty())
return 0;
3971 for (
auto tid : tjIDs) {
3972 auto& tj = slc.
tjs[tid - 1];
3996 std::cout << fcnLabel <<
" Invalid ID";
3999 if (ss3.
CotIDs.size() < 2) {
4000 std::cout << fcnLabel <<
" not enough CotIDs";
4005 for (
auto& ss : slc.
cots) {
4006 if (ss.ID == 0)
continue;
4007 if (ss.SS3ID == ss3.
ID &&
4009 std::cout << fcnLabel <<
" Bad assn: 2S" << ss.ID <<
" -> 3S" << ss3.
ID 4010 <<
" but it's not inCotIDs.\n";
4016 for (
auto cid : ss3.
CotIDs) {
4017 if (cid <= 0 || cid > (
int)slc.
cots.size())
return false;
4018 auto& ss = slc.
cots[cid - 1];
4019 if (ss.SS3ID > 0 && ss.SS3ID != ss3.
ID) {
4020 std::cout << fcnLabel <<
" Bad assn: 3S" << ss3.
ID <<
" -> 2S" << cid <<
" but 2S -> 3S" 4021 << ss.SS3ID <<
"\n";
4027 for (
auto cid : ss3.
CotIDs)
4028 slc.
cots[cid - 1].SS3ID = ss3.
ID;
4045 std::cout << fcnLabel <<
" Invalid ID";
4048 if (ss.
TjIDs.empty()) {
4049 std::cout << fcnLabel <<
" Fail: No TjIDs in 2S" << ss.
ID <<
"\n";
4054 std::cout << fcnLabel <<
" Fail: 2S" << ss.
ID <<
" has an invalid ParentID T" << ss.
ParentID 4059 std::cout << fcnLabel <<
" Fail: 2S" << ss.
ID <<
" ParentID is not in TjIDs.\n";
4065 if (ss.
ID != (
int)slc.
cots.size() + 1) {
4066 std::cout << fcnLabel <<
" Correcting the ID 2S" << ss.
ID <<
" -> 2S" << slc.
cots.size() + 1;
4067 ss.
ID = slc.
cots.size() + 1;
4071 for (
auto& tjID : ss.
TjIDs) {
4081 slc.
cots.push_back(ss);
4117 stj.
CTP = slc.
tjs[tjl[0] - 1].CTP;
4121 for (
auto& stp : stj.
Pts) {
4128 stj.
ID = slc.
tjs.size() + 1;
4132 slc.
tjs.push_back(stj);
4134 ss.
ID = slc.
cots.size() + 1;
4139 for (
auto tjid : tjl) {
4140 auto& tj = slc.
tjs[tjid - 1];
4141 if (tj.CTP != stj.
CTP) {
4160 for (
auto& ss : slc.
cots) {
4161 if (ss.ID == 0)
continue;
4162 for (
auto tid : ss.TjIDs) {
4163 auto& tj = slc.
tjs[tid - 1];
4164 if (tj.SSID != ss.ID) {
4165 std::cout << fcnLabel <<
" ***** Error: 2S" << ss.ID <<
" -> TjIDs T" << tid
4166 <<
" != tj.SSID 2S" << tj.SSID <<
"\n";
4171 if (ss.SS3ID > 0 && ss.SS3ID <= (
int)slc.
showers.size()) {
4172 auto& ss3 = slc.
showers[ss.SS3ID - 1];
4173 if (std::find(ss3.CotIDs.begin(), ss3.CotIDs.end(), ss.ID) == ss3.CotIDs.end()) {
4174 std::cout << fcnLabel <<
" ***** Error: 2S" << ss.ID <<
" -> 3S" << ss.SS3ID
4175 <<
" but the shower says no\n";
4180 for (
auto& tj : slc.
tjs) {
4181 if (tj.AlgMod[
kKilled])
continue;
4183 std::cout << fcnLabel <<
" ***** Error: T" << tj.ID <<
" tj.SSID is fubar\n";
4187 if (tj.SSID == 0)
continue;
4188 auto& ss = slc.
cots[tj.SSID - 1];
4189 if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tj.ID) != ss.TjIDs.end())
continue;
4190 std::cout << fcnLabel <<
" ***** Error: T" << tj.ID <<
" tj.SSID = 2S" << tj.SSID
4191 <<
" but the shower says no\n";
4195 for (
auto& ss3 : slc.
showers) {
4196 if (ss3.ID == 0)
continue;
4197 for (
auto cid : ss3.CotIDs) {
4198 auto& ss = slc.
cots[cid - 1];
4199 if (ss.SS3ID != ss3.ID) {
4200 std::cout << fcnLabel <<
" ***** Error: 3S" << ss3.ID <<
" -> 2S" << cid
4201 <<
" but it thinks it belongs to 3S" << ss.SS3ID <<
"\n";
4213 if (slc.
showers.empty())
return;
4215 myprt << fcnLabel <<
" 3D showers \n";
4216 for (
auto& ss3 : slc.
showers) {
4217 myprt << fcnLabel <<
" 3S" << ss3.ID <<
" 3V" << ss3.Vx3ID;
4218 myprt <<
" parentID " << ss3.ParentID;
4219 myprt <<
" ChgPos" << std::fixed;
4220 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
4223 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
4225 myprt <<
" posInPlane";
4226 std::vector<float> projInPlane(slc.
nPlanes);
4227 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
4228 CTP_t inCTP =
EncodeCTP(ss3.TPCID.Cryostat, ss3.TPCID.TPC, plane);
4229 auto tp =
MakeBareTP(detProp, slc, ss3.ChgPos, ss3.Dir, inCTP);
4230 myprt <<
" " <<
PrintPos(slc, tp.Pos);
4231 projInPlane[plane] = tp.Delta;
4233 myprt <<
" projInPlane";
4234 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
4237 for (
auto cid : ss3.CotIDs) {
4238 auto& ss = slc.
cots[cid - 1];
4239 myprt <<
"\n 2S" << ss.ID;
4240 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
4241 myprt <<
" ST" << stj.ID;
4242 myprt <<
" " <<
PrintPos(slc, stj.Pts[stj.EndPt[0]].Pos) <<
" - " 4243 <<
PrintPos(slc, stj.Pts[stj.EndPt[1]].Pos);
4245 if (ss3.NeedsUpdate) myprt <<
" *** Needs update";
4255 if (slc.
cots.empty())
return;
4260 bool printAllCTP = (inCTP == USHRT_MAX);
4262 unsigned short nlines = 0;
4263 for (
const auto& ss : slc.
cots) {
4264 if (!printAllCTP && ss.CTP != inCTP)
continue;
4265 if (!printKilledShowers && ss.ID == 0)
continue;
4269 myprt << someText <<
" Print2DShowers: Nothing to print";
4274 bool printHeader =
true;
4275 bool printExtras =
false;
4276 for (
unsigned short ict = 0; ict < slc.
cots.size(); ++ict) {
4277 const auto& ss = slc.
cots[ict];
4278 if (!printAllCTP && ss.CTP != inCTP)
continue;
4279 if (!printKilledShowers && ss.ID == 0)
continue;
4280 PrintShower(someText, slc, ss, printHeader, printExtras);
4281 printHeader =
false;
4284 for (
unsigned short ict = 0; ict < slc.
cots.size(); ++ict) {
4285 const auto& ss = slc.
cots[ict];
4286 if (!printAllCTP && ss.CTP != inCTP)
continue;
4287 if (!printKilledShowers && ss.ID == 0)
continue;
4288 myprt << someText << std::fixed;
4292 for (
auto id : ss.TjIDs)
4293 myprt <<
" T" << id;
4297 for (
unsigned short ict = 0; ict < slc.
cots.size(); ++ict) {
4298 const auto& ss = slc.
cots[ict];
4299 if (!printAllCTP && ss.CTP != inCTP)
continue;
4300 if (!printKilledShowers && ss.ID == 0)
continue;
4301 myprt << someText << std::fixed;
4304 myprt <<
" Envelope";
4305 for (
auto& vtx : ss.Envelope)
4310 for (
unsigned short ict = 0; ict < slc.
cots.size(); ++ict) {
4311 const auto& ss = slc.
cots[ict];
4312 if (!printAllCTP && ss.CTP != inCTP)
continue;
4313 if (!printKilledShowers && ss.ID == 0)
continue;
4314 myprt << someText << std::fixed;
4318 for (
auto id : ss.NearTjIDs)
4319 myprt <<
" T" << id;
4323 myprt <<
"DontCluster";
4325 if (dc.TjIDs[0] > 0) myprt <<
" T" << dc.TjIDs[0] <<
"-T" << dc.TjIDs[1];
4327 myprt <<
"\nDontCluster";
4328 for (
unsigned short ict = 0; ict < slc.
cots.size(); ++ict) {
4329 const auto& iss = slc.
cots[ict];
4330 if (iss.ID == 0)
continue;
4331 for (
unsigned short jct = ict + 1; jct < slc.
cots.size(); ++jct) {
4332 const auto& jss = slc.
cots[jct];
4333 if (jss.ID == 0)
continue;
4334 if (
DontCluster(slc, iss.TjIDs, jss.TjIDs)) myprt <<
" 2S" << iss.ID <<
"-2S" << jss.ID;
4352 <<
" ID CTP ParID ParFOM TruParID Energy nTjs dFOM AspRat stj vx0 __Pos0___ " 4353 "Chg(k) dRMS __Pos1___ Chg(k) dRMS __Pos2___ Chg(k) dRMS Angle SS3ID PFPID\n";
4356 myprt << someText << std::fixed;
4375 for (
auto& spt : stj.Pts) {
4387 if (ss3.PFPIndex >= 0 && ss3.PFPIndex < slc.
pfps.size()) {
4400 if (!printExtras)
return;
4403 myprt << someText << std::fixed;
4407 for (
auto id : ss.
TjIDs)
4408 myprt <<
" T" << id;
4410 myprt << someText << std::fixed;
4413 myprt <<
" Envelope";
4417 myprt << someText << std::fixed;
4422 myprt <<
" T" << id;
bool AddTj(std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
bool TransferTjHits(TCSlice &slc, bool prt)
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< Trajectory > tjs
vector of all trajectories in each plane
unsigned short FarEnd(const TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
void MergeNearby2DShowers(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
void ConfigureMVA(TCConfig &tcc, std::string fMVAShowerParentWeights)
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
bool FindParent(detinfo::DetectorPropertiesData const &detProp, std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
void ReverseShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
struct of temporary 2D vertices (end points)
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
std::vector< unsigned int > PutTrajHitsInVector(const Trajectory &tj, HitStatus_t hitRequest)
std::vector< ShowerStruct > cots
void MergeShowerChain(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
std::vector< double > dEdxErr
double rms(sqlite3 *db, std::string const &table_name, std::string const &column_name)
double InShowerProbLong(double showerEnergy, double along)
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
std::vector< int > NearTjIDs
std::vector< ShowerStruct3D > showers
ShowerStruct3D CreateSS3(TCSlice &slc)
std::vector< Point2_t > Envelope
unsigned int Nplanes() const
Number of planes in this tpc.
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
std::vector< std::vector< std::pair< unsigned int, unsigned int > > > wireHitRange
The data type to uniquely identify a Plane.
void PrintShowers(detinfo::DetectorPropertiesData const &detProp, std::string fcnLabel, TCSlice &slc)
Geometry information for a single TPC.
std::vector< unsigned int > Hits
std::vector< double > MIPEnergy
int GetCotID(TCSlice &slc, int ShowerTjID)
short MCSMom
Normalized RMS using ALL hits. Assume it is 50% to start.
void PrintShower(std::string someText, TCSlice &slc, const ShowerStruct &ss, bool printHeader, bool printExtras)
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
CryostatID_t Cryostat
Index of cryostat.
bool WrongSplitTj(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, unsigned short tjEnd, ShowerStruct &ss, bool prt)
PFPStruct CreatePFP(const TCSlice &slc)
void KillVerticesInShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
void SaveAllCots(TCSlice &slc, const CTP_t &inCTP, std::string someText)
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
bool FindShowers3D(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc)
double ShowerEnergy(const ShowerStruct3D &ss3)
bool dbgSlc
debug only in the user-defined slice? default is all slices
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
float ParentFOM(std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, unsigned short pend, ShowerStruct3D &ss3, bool prt)
std::vector< unsigned int > lastWire
the last wire with a hit
std::array< int, 2 > Vx3ID
bool IsShowerLike(TCSlice &slc, const std::vector< int > TjIDs)
std::vector< int > CotIDs
double InShowerProbTrans(double showerEnergy, double along, double trans)
std::vector< ShowerPoint > ShPts
void PrintPFPs(std::string someText, TCSlice &slc)
bool FindShowerStart(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Q_EXPORT QTSManip setprecision(int p)
ShowerStruct CreateSS(TCSlice &slc, const std::vector< int > &tjl)
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
bool AddLooseHits(TCSlice &slc, int cotID, bool prt)
bool DontCluster(TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
void MergeTjList(std::vector< std::vector< int >> &tjList)
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
double InShowerProbParam(double showerEnergy, double along, double trans)
double ShowerParamTransRMS(double showerEnergy, double along)
void AddCloseTjsToList(TCSlice &slc, unsigned short itj, std::vector< int > list)
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const Point3_t &pos, CTP_t inCTP)
void DefineEnvelope(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
void MergeSubShowersTj(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
std::vector< DontClusterStruct > dontCluster
int close(int)
Closes the file descriptor fd.
int NeutrinoPrimaryTjID(const TCSlice &slc, const Trajectory &tj)
fInnerVessel push_back(Point(-578.400000, 0.000000, 0.000000))
void PrintAllTraj(detinfo::DetectorPropertiesData const &detProp, std::string someText, TCSlice &slc, unsigned short itj, unsigned short ipt, bool prtVtx)
std::array< float, 2 > Point2_t
float unitsPerTick
scale factor from Tick to WSE equivalent units
void DumpShowerPts(TCSlice &slc, int cotID)
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
void swap(Handle< T > &a, Handle< T > &b)
CTP_t CTP
Cryostat, TPC, Plane code.
float InShowerProb(TCSlice &slc, const ShowerStruct3D &ss3, const PFPStruct &pfp)
bool MergeShowerTjsAndStore(TCSlice &slc, unsigned short istj, unsigned short jstj, bool prt)
void TagShowerLike(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP)
std::vector< TrajPoint > Pts
Trajectory points.
TMVA::Reader * showerParentReader
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
std::vector< float > showerParentVars
float ChgFracBetween(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, Point3_t pos1, Point3_t pos2)
void SaveTjInfo(TCSlice &slc, std::vector< std::vector< int >> &tjList, std::string stageName)
void FindNearbyTjs(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
std::vector< VtxStore > vtxs
2D vertices
std::array< unsigned short, 2 > EndPt
First and last point in the trajectory that has charge.
unsigned short PDGCode
shower-like or track-like {default is track-like}
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
void MergeOverlap(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
void MakeTrajectoryObsolete(TCSlice &slc, unsigned int itj)
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
const geo::GeometryCore * geom
PlaneID_t Plane
Index of the plane within its TPC.
bool SetMag(Vector3_t &v1, double mag)
Definition of data types for geometry description.
void ReverseTraj(TCSlice &slc, Trajectory &tj)
bool AddPFP(std::string inFcnLabel, TCSlice &slc, int pID, ShowerStruct3D &ss3, bool doUpdate, bool prt)
bool valsIncreasing(const SortEntry &c1, const SortEntry &c2)
int ID
ID that is local to one slice.
std::vector< float > StartChgVec(TCSlice &slc, int cotID, bool prt)
std::vector< TCSlice > slices
std::array< unsigned short, 2 > VtxID
ID of 2D vertex.
Detector simulation of raw signals on wires.
Q_EXPORT QTSManip setw(int w)
bool AddTjsInsideEnvelope(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
double ConvertTicksToX(double ticks, int p, int t, int c) const
std::bitset< 16 > modes
number of points to find AveChg
std::vector< TCHit > slHits
std::vector< float > chargeCuts
bool MergeShowersAndStore(std::string inFcnLabel, TCSlice &slc, int icotID, int jcotID, bool prt)
std::vector< double > EnergyErr
std::vector< double > MIPEnergyErr
Declaration of signal hit object.
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
std::vector< Vtx3Store > vtx3s
3D vertices
bool RemoveTj(std::string inFcnLabel, TCSlice &slc, int TjID, ShowerStruct &ss, bool doUpdate, bool prt)
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
int MergeShowers(std::string inFcnLabel, TCSlice &slc, std::vector< int > ssIDs, bool prt)
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
std::bitset< 128 > AlgMod
Bit set if algorithm AlgBit_t modifed the trajectory.
static unsigned int reverse(QString &chars, unsigned char *level, unsigned int a, unsigned int b)
std::vector< double > Energy
geo::PlaneID DecodeCTP(CTP_t CTP)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
std::vector< recob::Hit > const * allHits
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
std::string find_file(std::string const &filename) const
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
std::array< double, 3 > Vector3_t
int ID
ID of the recob::Slice (not the sub-slice)
bool RemovePFP(std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, ShowerStruct3D &ss3, bool doUpdate, bool prt)
Access the description of detector geometry.
std::vector< T > SetDifference(const std::vector< T > &set1, const std::vector< T > &set2)
void MergeSubShowers(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
void FindStartChg(std::string inFcnLabel, TCSlice &slc, int cotID, bool prt)
void Finish3DShowers(TCSlice &slc)
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
int SSID
ID of a 2D shower struct that this tj is in.
std::vector< PFPStruct > pfps
bool AnalyzeRotPos(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
float Match3DFOM(detinfo::DetectorPropertiesData const &detProp, std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
float ChgToMeV(float chg)
TPCID_t TPC
Index of the TPC within its cryostat.
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
std::vector< double > dEdx
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Vector3_t DirAtEnd(const PFPStruct &pfp, unsigned short end)
void Print2DShowers(std::string someText, TCSlice &slc, CTP_t inCTP, bool printKilledShowers)
bool CompleteIncompleteShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
std::string to_string(ModuleType const mt)
bool SetParent(detinfo::DetectorPropertiesData const &detProp, std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, ShowerStruct3D &ss3, bool prt)
CTP_t CTP
set to an invalid CTP
void MakeShowerObsolete(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Encapsulate the construction of a single detector plane.
bool valsDecreasing(const SortEntry &c1, const SortEntry &c2)
bool StoreShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3)
bool Reconcile3D(std::string inFcnLabel, TCSlice &slc, bool parentSearchDone, bool prt)