2 #include "cetlib/search_path.h" 27 #include "TMVA/Reader.h" 31 using namespace detail;
38 cet::search_path sp(
"FW_SEARCH_PATH");
40 std::string fullFileSpec;
41 sp.find_file(fMVAShowerParentWeights, fullFileSpec);
42 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;
162 bool noShowers =
true;
163 for (
auto& ss3 : slc.
showers) {
164 if (ss3.ID == 0)
continue;
167 if (noShowers)
return;
174 for (
auto& ss3 : slc.
showers) {
175 if (ss3.ID == 0)
continue;
176 if (ss3.PFPIndex != USHRT_MAX)
continue;
178 showerPFP.TjIDs.resize(ss3.CotIDs.size());
179 for (
unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) {
180 unsigned short cid = ss3.CotIDs[ii];
181 if (cid == 0 || cid > slc.
cots.size())
return;
182 auto& ss = slc.
cots[cid - 1];
183 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
184 showerPFP.TjIDs[ii] = stj.ID;
186 showerPFP.PDGCode = 1111;
187 auto& sf = showerPFP.SectionFits[0];
190 sf.DirErr = ss3.DirErr;
191 showerPFP.Vx3ID[0] = ss3.Vx3ID;
194 for (
auto cid : ss3.CotIDs) {
195 auto& ss = slc.
cots[cid - 1];
197 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
198 showerPFP.dEdx[0][plane] = stj.dEdx[0];
199 showerPFP.dEdxErr[0][plane] = 0.3 * stj.dEdx[0];
201 ss3.PFPIndex = slc.
pfps.size();
202 if (ss3.ParentID > 0) {
204 auto& dtrPFP = slc.
pfps[ss3.ParentID - 1];
205 if (dtrPFP.ParentUID > 0) {
208 auto& parPFP =
slices[slcIndx.first].pfps[slcIndx.second];
209 showerPFP.ParentUID = parPFP.UID;
210 std::replace(parPFP.DtrUIDs.begin(), parPFP.DtrUIDs.end(), dtrPFP.UID, showerPFP.UID);
211 dtrPFP.ParentUID = 0;
214 slc.
pfps.push_back(showerPFP);
222 for (
auto& ss3 : slc.
showers) {
223 if (ss3.ID == 0)
continue;
224 for (
unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) {
225 unsigned short cid = ss3.CotIDs[ii];
226 auto& ss = slc.
cots[cid - 1];
227 for (
auto tjid : ss.TjIDs) {
230 ss3.Hits.insert(ss3.Hits.end(), tjHits.begin(), tjHits.end());
232 for (
unsigned short end = 0;
end < 2; ++
end) {
235 if (vx2.Vx3ID <= 0) {
242 auto& vx3 = slc.
vtx3s[vx2.Vx3ID - 1];
243 if (vx3.Neutrino)
continue;
251 if (!slc.
pfps.empty()) {
252 for (
auto& pfp : slc.
pfps) {
253 if (pfp.ID == 0)
continue;
254 if (pfp.TjIDs.empty())
continue;
255 unsigned short ndead = 0;
256 for (
auto tjid : pfp.TjIDs) {
257 auto& tj = slc.
tjs[tjid - 1];
258 if (tj.AlgMod[
kKilled]) ++ndead;
260 if (ndead == 0)
continue;
266 for (
auto& vx2 : slc.
vtxs) {
267 if (vx2.ID == 0)
continue;
268 auto vxtjs =
GetAssns(slc,
"2V", vx2.
ID,
"T");
269 if (vxtjs.empty()) vx2.ID = 0;
273 for (
auto& vx3 : slc.
vtx3s) {
274 if (vx3.ID == 0)
continue;
275 auto vxtjs =
GetAssns(slc,
"3V", vx3.
ID,
"T");
291 if (!reconstruct)
return false;
296 std::string fcnLabel =
"FS";
300 for (
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane) {
302 for (
auto& ss : slc.
cots)
303 if (ss.CTP == inCTP)
return false;
312 std::vector<std::vector<std::vector<int>>> bigList(slc.
nPlanes);
313 for (
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane) {
314 std::vector<std::vector<int>> tjList;
318 if (tjList.empty())
continue;
319 bigList[plane] = tjList;
321 unsigned short nPlanesWithShowers = 0;
322 for (
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane)
323 if (!bigList.empty()) ++nPlanesWithShowers;
324 if (nPlanesWithShowers < 2)
return false;
325 for (
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane) {
328 bool prtCTP = (prt2S && inCTP ==
debug.
CTP);
330 for (
auto& tjl : bigList[plane]) {
331 if (tjl.empty())
continue;
334 myprt <<
"Plane " << plane <<
" tjList";
335 for (
auto& tjID : tjl)
336 myprt <<
" " << tjID;
339 if (ss.ID == 0)
continue;
348 if (inCTP == UINT_MAX)
continue;
349 if (slc.
cots.empty())
continue;
365 bool tryMerge =
false;
366 for (
unsigned short ii = 0; ii < slc.
cots.size(); ++ii) {
367 auto& ss = slc.
cots[ii];
368 if (ss.ID == 0)
continue;
369 if (ss.CTP != inCTP)
continue;
377 if (slc.
cots.empty())
return false;
385 for (
auto& ss3 : slc.
showers) {
386 if (ss3.ID == 0)
continue;
387 FindParent(detProp, fcnLabel, slc, ss3, prt3S);
395 for (
auto& ss3 : slc.
showers) {
396 if (ss3.ID == 0)
continue;
402 for (
auto& ss : slc.
cots) {
403 if (ss.ID == 0)
continue;
404 if (ss.SS3ID > 0)
continue;
405 bool killMe = (ss.TjIDs.size() == 1 || ss.Energy <
tcc.
showerTag[3]);
411 unsigned short nNewShowers = 0;
412 for (
auto& ss : slc.
cots) {
413 if (ss.ID == 0)
continue;
414 if (ss.TjIDs.empty())
continue;
419 return (nNewShowers > 0);
428 std::string fcnLabel = inFcnLabel +
".R3D2";
434 for (
unsigned short ii = 0; ii < slc.
showers.size() - 1; ++ii) {
436 if (iss3.ID == 0)
continue;
437 auto iPInSS3 =
GetAssns(slc,
"3S", iss3.
ID,
"P");
440 myprt << fcnLabel <<
" 3S" << iss3.ID <<
" ->";
441 for (
auto pid : iPInSS3)
442 myprt <<
" P" <<
pid;
444 for (
unsigned short jj = ii + 1; jj < slc.
showers.size(); ++jj) {
446 if (jss3.ID == 0)
continue;
447 auto jPInSS3 =
GetAssns(slc,
"3S", jss3.
ID,
"P");
449 if (shared.empty())
continue;
452 myprt << fcnLabel <<
" Conflict i3S" << iss3.ID <<
" and j3S" << jss3.ID <<
" share";
453 for (
auto pid : shared)
454 myprt <<
" P" <<
pid;
457 for (
auto pid : shared) {
463 << fcnLabel <<
" i3S" << iss3.ID <<
" prob " << std::setprecision(3) << iProb
464 <<
" j3S" << jss3.ID <<
" prob " << jProb;
467 RemovePFP(fcnLabel, slc, pfp, jss3,
true, prt);
469 AddPFP(fcnLabel, slc, pfp.
ID, iss3,
true, prt);
472 RemovePFP(fcnLabel, slc, pfp, iss3,
true, prt);
473 AddPFP(fcnLabel, slc, pfp.
ID, jss3,
true, prt);
482 if (parentSearchDone) {
483 for (
auto& ss3 : slc.
showers) {
484 if (ss3.ID == 0)
continue;
485 auto PIn3S =
GetAssns(slc,
"3S", ss3.
ID,
"P");
486 for (
auto pid : PIn3S) {
487 if (
pid == ss3.ParentID)
continue;
489 for (
unsigned short end = 0;
end < 2; ++
end) {
490 if (pfp.Vx3ID[
end] <= 0)
continue;
493 myprt << fcnLabel <<
" Detach 3S" << ss3.ID <<
" -> P" << pfp.ID <<
"_" <<
end 494 <<
" -> 3V" << pfp.Vx3ID[
end];
495 if (pfp.ParentUID > 0) myprt <<
" ->Parent P" << pfp.ParentUID;
499 if (pfp.ParentUID > 0) {
501 auto& parentPFP =
slices[slcIndx.first].pfps[slcIndx.second];
502 std::vector<int> newDtrUIDs;
503 for (
auto did : parentPFP.DtrUIDs)
504 if (did != pfp.UID) newDtrUIDs.push_back(did);
505 parentPFP.DtrUIDs = newDtrUIDs;
514 for (
auto& ss : slc.
cots) {
515 if (ss.ID == 0)
continue;
516 if (ss.SS3ID > 0)
continue;
517 std::vector<int> matchedTjs;
518 for (
auto tid : ss.TjIDs)
519 if (slc.
tjs[tid - 1].AlgMod[
kMat3D]) matchedTjs.push_back(tid);
520 if (matchedTjs.empty())
continue;
524 bool isCompatible =
true;
525 for (
auto tid : matchedTjs) {
526 auto TInP =
GetAssns(slc,
"T", tid,
"P");
527 if (TInP.empty())
continue;
530 auto PIn3S =
GetAssns(slc,
"P", TInP[0],
"3S");
531 for (
auto sid : PIn3S) {
533 auto& ss3 = slc.
showers[sid - 1];
535 if (mergeWith3S == 0) mergeWith3S = sid;
536 if (mergeWith3S > 0 && mergeWith3S != sid) isCompatible =
false;
541 myprt << fcnLabel <<
" 2S" << ss.ID <<
" is not 3D-matched but has 3D-matched Tjs:";
542 for (
auto tid : matchedTjs) {
543 myprt <<
" T" << tid;
544 auto TInP =
GetAssns(slc,
"T", tid,
"P");
545 if (!TInP.empty()) { myprt <<
"->P" << TInP[0]; }
548 if (mergeWith3S == 0 && ss.Energy < 50) {
552 else if (mergeWith3S > 0 && isCompatible) {
553 auto& ss3 = slc.
showers[mergeWith3S - 1];
554 for (
auto cid : ss3.CotIDs) {
555 auto& oss = slc.
cots[cid - 1];
556 if (oss.CTP != ss.CTP)
continue;
557 if (!
UpdateShower(fcnLabel, slc, ss3, prt))
return false;
574 if (ss3.
ID == 0)
return false;
576 if (ss3.
CotIDs.size() < 3)
return true;
577 std::string fcnLabel = inFcnLabel +
".R3D";
583 std::vector<ShowerStruct> oldSS(ss3.
CotIDs.size());
584 for (
unsigned short ii = 0; ii < ss3.
CotIDs.size(); ++ii) {
588 std::vector<std::vector<int>> plist(ss3.
CotIDs.size());
589 for (
unsigned short ci = 0; ci < ss3.
CotIDs.size(); ++ci) {
591 for (
auto tid : ss.TjIDs) {
592 auto tToP =
GetAssns(slc,
"T", tid,
"P");
593 if (tToP.empty())
continue;
596 if (std::find(plist[ci].
begin(), plist[ci].
end(), pid) == plist[ci].end())
597 plist[ci].push_back(pid);
601 std::vector<std::array<int, 2>> p_cnt;
602 for (
auto& pl : plist) {
603 for (
auto pid : pl) {
604 unsigned short indx = 0;
605 for (indx = 0; indx < p_cnt.size(); ++indx)
606 if (p_cnt[indx][0] ==
pid)
break;
607 if (indx == p_cnt.size()) {
609 p_cnt.push_back(std::array<int, 2>{{
pid, 1}});
618 myprt << fcnLabel <<
" 3S" << ss3.
ID <<
"\n";
619 for (
unsigned short ci = 0; ci < ss3.
CotIDs.size(); ++ci) {
620 myprt <<
" -> 2S" << ss3.
CotIDs[ci] <<
" ->";
621 for (
auto pid : plist[ci])
622 myprt <<
" P" <<
pid;
625 myprt <<
" P<ID>_count:";
626 for (
auto& pc : p_cnt)
627 myprt <<
" P" << pc[0] <<
"_" << pc[1];
630 for (
auto& pc : p_cnt) {
632 if (pc[1] == (
int)ss3.
CotIDs.size())
continue;
635 auto& pfp = slc.
pfps[pc[0] - 1];
636 if (pfp.TjIDs.size() > 2) {
638 auto PIn2S =
GetAssns(slc,
"P", pfp.
ID,
"2S");
640 if (!sDiff.empty() &&
645 myprt << fcnLabel <<
" 3S" << ss3.
ID <<
" P" << pfp.ID <<
" ->";
646 for (
auto sid : PIn2S)
647 myprt <<
" 2S" << sid;
649 for (
auto sid : sDiff)
650 myprt <<
" 2S" << sid;
653 if (
AddPFP(fcnLabel, slc, pfp.
ID, ss3,
true, prt)) {
656 if (ss3.
CotIDs.size() != oldSS.size())
return false;
657 for (
unsigned short ii = 0; ii < ss3.
CotIDs.size(); ++ii)
663 for (
unsigned short ii = 0; ii < oldSS.size(); ++ii) {
664 auto& ss = oldSS[ii];
665 slc.
cots[ss.ID - 1] = ss;
672 auto& pfp = slc.
pfps[pc[0] - 1];
679 myprt << fcnLabel <<
" one occurrence: P" << pfp.ID <<
"_" << nearEnd
680 <<
" closest to ChgPos";
681 myprt <<
" ChgPos " << std::fixed << std::setprecision(1) << ss3.
ChgPos[0] <<
" " 683 myprt <<
" sep " << sep;
684 myprt <<
" InShowerProb " << prob;
686 if (sep < 30 && prob > 0.3 &&
AddPFP(fcnLabel, slc, pfp.
ID, ss3,
true, prt)) {
689 else if (!
RemovePFP(fcnLabel, slc, pfp, ss3,
true, prt)) {
695 if (!
UpdateShower(fcnLabel, slc, ss3, prt))
return false;
707 if (ss.
ID == 0)
return;
709 std::string fcnLabel = inFcnLabel +
".KVIS";
711 for (
auto& vx2 : slc.
vtxs) {
712 if (vx2.ID == 0)
continue;
713 if (vx2.CTP != ss.
CTP)
continue;
715 if (vx2.Vx3ID > 0 && slc.
vtx3s[vx2.Vx3ID - 1].Neutrino)
continue;
718 mf::LogVerbatim(
"TC") << fcnLabel <<
" Clobber 2V" << vx2.ID <<
" -> 3V" << vx2.Vx3ID
719 <<
" inside 2S" << ss.
ID;
722 if (dc.TjIDs[0] == 0)
continue;
723 if (dc.Vx2ID != vx2.ID)
continue;
725 mf::LogVerbatim(
"TC") << fcnLabel <<
" Remove T" << dc.TjIDs[0] <<
"-T" << dc.TjIDs[0]
726 <<
" in dontCluster";
731 auto TIn3V =
GetAssns(slc,
"3V", vx2.Vx3ID,
"T");
732 for (
auto tid : TIn3V)
734 auto& vx3 = slc.
vtx3s[vx2.Vx3ID - 1];
738 auto TIn2V =
GetAssns(slc,
"2V", vx2.
ID,
"T");
739 for (
auto tid : TIn2V)
753 if (slc.
nPlanes != 3)
return false;
754 if (ss3.
CotIDs.size() != 2)
return false;
758 std::string fcnLabel = inFcnLabel +
".CIS";
764 std::vector<int> iplist;
765 for (
auto tid : iss.TjIDs) {
766 auto plist =
GetAssns(slc,
"T", tid,
"P");
767 if (!plist.empty()) iplist.insert(iplist.end(), plist.begin(), plist.end());
769 std::vector<int> jplist;
770 for (
auto tid : jss.TjIDs) {
771 auto plist =
GetAssns(slc,
"T", tid,
"P");
772 if (!plist.empty()) jplist.insert(jplist.end(), plist.begin(), plist.end());
776 if (shared.empty())
return false;
778 std::vector<int> flat = iss.TjIDs;
779 flat.insert(flat.end(), jss.TjIDs.begin(), jss.TjIDs.end());
782 std::vector<int> ktlist;
783 for (
auto pid : shared) {
785 for (
auto tid : pfp.TjIDs) {
787 if (std::find(flat.begin(), flat.end(), tid) != flat.end())
continue;
788 if (std::find(ktlist.begin(), ktlist.end(), tid) == ktlist.end()) ktlist.push_back(tid);
790 auto& tj = slc.
tjs[tid - 1];
791 for (
unsigned short end = 0;
end < 2; ++
end) {
792 if (tj.VtxID[
end] <= 0)
continue;
793 auto& vx2 = slc.
vtxs[tj.VtxID[
end] - 1];
794 auto TIn2V =
GetAssns(slc,
"2V", vx2.
ID,
"T");
795 for (
auto vtid : TIn2V) {
796 if (std::find(ktlist.begin(), ktlist.end(), vtid) == ktlist.end())
797 ktlist.push_back(vtid);
802 if (ktlist.empty())
return false;
804 std::vector<int> ksslist;
805 for (
auto tid : ktlist) {
806 auto& tj = slc.
tjs[tid - 1];
807 if (tj.SSID == 0)
continue;
809 auto& ss = slc.
cots[tj.SSID - 1];
812 mf::LogVerbatim(
"TC") << fcnLabel <<
" Found existing T" << tid <<
" -> 2S" << ss.ID
813 <<
" -> 3S" << ss.SS3ID <<
" assn. Give up";
816 if (std::find(ksslist.begin(), ksslist.end(), ss.ID) == ksslist.end())
817 ksslist.push_back(ss.ID);
823 myprt << fcnLabel <<
" 3S" << ss3.
ID <<
"\n";
824 myprt <<
" -> i2S" << iss.ID <<
" ->";
825 for (
auto pid : iplist)
826 myprt <<
" P" <<
pid;
828 myprt <<
" -> j2S" << jss.ID <<
" ->";
829 for (
auto pid : jplist)
830 myprt <<
" P" << pid;
834 unsigned short kplane = 3 - iPlaneID.
Plane - jPlaneID.
Plane;
835 myprt <<
" kplane " << kplane <<
" ktlist:";
836 for (
auto tid : ktlist)
837 myprt <<
" T" << tid;
838 myprt <<
" ktlistEnergy " << ktlistEnergy;
839 if (ksslist.empty()) { myprt <<
"\n No matching showers in kplane"; }
842 myprt <<
" Candidate showers:";
843 for (
auto ssid : ksslist) {
844 myprt <<
" 2S" << ssid;
845 auto& sst = slc.
cots[ssid - 1];
846 if (sst.SS3ID > 0) myprt <<
"_3S" << sst.SS3ID;
850 if (ksslist.size() > 1) {
853 <<
" Found more than 1 shower. Need some better code here";
859 <<
" ktlistEnergy exceeds 2 * ss3 energy. Need some better code here";
863 if (ksslist.empty()) {
866 if (kss.ID == 0)
return false;
869 mf::LogVerbatim(
"TC") << fcnLabel <<
" 3S" << ss3.
ID <<
" create new 2S" << kss.ID
872 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" UpdateShower failed 2S" << kss.ID;
881 ss3.
CotIDs.push_back(kss.ID);
882 auto& stj = slc.
tjs[kss.ShowerTjID - 1];
889 auto& ss = slc.
cots[ksslist[0] - 1];
891 mf::LogVerbatim(
"TC") << fcnLabel <<
" 3S" << ss3.
ID <<
" found pfp-matched 2S" << ss.ID;
893 ss3.
CotIDs.push_back(ss.ID);
894 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
913 if (ss.
ID == 0)
return false;
914 if (ss.
TjIDs.empty())
return false;
918 if (stj.Pts.size() != 3)
return false;
920 std::string fcnLabel = inFcnLabel +
".U2S";
932 for (
auto& stp : stj.Pts) {
934 stp.Pos = {{0.0, 0.0}};
936 stp.HitPos = {{0.0, 0.0}};
938 stp.Dir = {{0.0, 0.0}};
948 for (
auto tjid : ss.
TjIDs) {
949 if (tjid <= 0 || tjid > (
int)slc.
tjs.size())
return false;
950 auto& tj = slc.
tjs[tjid - 1];
951 if (tj.CTP != ss.
CTP)
return false;
953 for (
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
955 for (
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
956 if (!tp.
UseHit[ii])
continue;
957 unsigned int iht = tp.
Hits[ii];
959 if (
hit.Integral() <= 0)
continue;
963 shpt.
Chg =
hit.Integral();
964 shpt.
Pos[0] =
hit.WireID().Wire;
966 ss.
ShPts.push_back(shpt);
972 if (ss.
ShPts.size() < 3)
return false;
975 auto& stp1 = stj.Pts[1];
976 for (
auto& shpt : ss.
ShPts) {
977 stp1.Pos[0] += shpt.Chg * shpt.Pos[0];
978 stp1.Pos[1] += shpt.Chg * shpt.Pos[1];
979 stj.TotChg += shpt.Chg;
981 if (stj.TotChg <= 0)
return false;
982 stp1.Pos[0] /= stj.TotChg;
983 stp1.Pos[1] /= stj.TotChg;
987 <<
" Energy " << (int)ss.
Energy <<
" MeV";
994 unsigned short pend =
FarEnd(ptj, stp1.Pos);
995 auto& ptp = ptj.Pts[ptj.EndPt[pend]];
997 stp1.Ang = atan2(stp1.Dir[1], stp1.Dir[0]);
1006 for (
auto& shpt : ss.
ShPts) {
1008 double xx = shpt.Pos[0] - stp1.Pos[0];
1009 double yy = shpt.Pos[1] - stp1.Pos[1];
1010 sumx += shpt.Chg *
xx;
1011 sumy += shpt.Chg * yy;
1012 sumxy += shpt.Chg * xx * yy;
1013 sumx2 += shpt.Chg * xx *
xx;
1015 double delta = sum * sumx2 - sumx * sumx;
1016 if (delta == 0)
return false;
1020 double B = (sumxy * sum - sumx * sumy) / delta;
1022 stp1.Dir[0] = cos(stp1.Ang);
1023 stp1.Dir[1] = sin(stp1.Ang);
1027 ss.
Angle = stp1.Ang;
1030 << std::setprecision(2) << stp1.Dir[0] <<
" " << stp1.Dir[1]
1031 <<
" Angle " << stp1.Ang;
1032 for (
unsigned short ipt = 0; ipt < 3; ++ipt) {
1033 if (ipt == 1)
continue;
1034 stj.Pts[ipt].Dir = stp1.Dir;
1035 stj.Pts[ipt].Ang = stp1.Ang;
1039 std::vector<SortEntry> sortVec(ss.
ShPts.size());
1040 unsigned short indx = 0;
1041 double cs = cos(-stp1.Ang);
1042 double sn = sin(-stp1.Ang);
1043 for (
auto& shpt : ss.
ShPts) {
1044 double xx = shpt.Pos[0] - stp1.Pos[0];
1045 double yy = shpt.Pos[1] - stp1.Pos[1];
1046 shpt.RotPos[0] = cs * xx - sn * yy;
1047 shpt.RotPos[1] = sn * xx + cs * yy;
1048 sortVec[indx].index = indx;
1049 sortVec[indx].val = shpt.RotPos[0];
1054 auto tPts = ss.
ShPts;
1055 for (
unsigned short ii = 0; ii < ss.
ShPts.size(); ++ii)
1056 ss.
ShPts[ii] = tPts[sortVec[ii].index];
1060 for (
auto& shpt : ss.ShPts) {
1061 alongTrans[0] += shpt.Chg *
std::abs(shpt.RotPos[0]);
1062 alongTrans[1] += shpt.Chg *
std::abs(shpt.RotPos[1]);
1064 alongTrans[0] /= stj.TotChg;
1065 alongTrans[1] /= stj.TotChg;
1066 if (alongTrans[1] == 0)
return false;
1067 ss.AspectRatio = alongTrans[1] / alongTrans[0];
1069 mf::LogVerbatim(
"TC") << fcnLabel <<
" 2S" << ss.ID <<
" AspectRatio " << ss.AspectRatio;
1075 if (ss.ParentID > 0) {
1078 auto& ptj = slc.tjs[ss.ParentID - 1];
1080 unsigned short pend =
FarEnd(ptj, stp1.Pos);
1081 auto& ptp = ptj.Pts[ptj.EndPt[pend]];
1082 auto& firstShPt = ss.ShPts[0];
1083 auto& lastShPt = ss.ShPts[ss.ShPts.size() - 1];
1084 if (
PosSep2(ptp.Pos, lastShPt.Pos) <
PosSep2(ptp.Pos, firstShPt.Pos))
1086 stj.Pts[0].Pos = ptp.Pos;
1090 if (stj.Pts[2].DeltaRMS < stj.Pts[0].DeltaRMS)
ReverseShower(fcnLabel, slc, ss, prt);
1091 stj.Pts[0].Pos = ss.ShPts[0].Pos;
1094 if (stj.Pts[2].DeltaRMS > 0) ss.DirectionFOM = stj.Pts[0].DeltaRMS / stj.Pts[2].DeltaRMS;
1096 stj.Pts[2].Pos = ss.ShPts[ss.ShPts.size() - 1].Pos;
1099 ss.NeedsUpdate =
false;
1100 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" 2S" << ss.ID <<
" updated";
1111 if (ss3.
ID == 0)
return false;
1112 if (ss3.
CotIDs.size() < 2)
return false;
1114 std::string fcnLabel = inFcnLabel +
".U3S";
1117 for (
auto cid : ss3.
CotIDs) {
1118 auto& ss = slc.
cots[cid - 1];
1119 if (ss.NeedsUpdate && prt)
1120 std::cout << fcnLabel <<
" ********* 3S" << ss3.
ID <<
" 2S" << ss.ID
1121 <<
" needs an update...\n";
1129 if (pfp.Vx3ID[pend] != ss3.
Vx3ID) {
1131 std::cout << fcnLabel <<
" ********* 3S" << ss3.
ID <<
" has parent P" << ss3.
ParentID 1132 <<
" with a vertex that is not attached the shower\n";
1137 std::array<Point3_t, 3> pos;
1140 std::array<double, 3> chg;
1141 for (
unsigned short ipt = 0; ipt < 3; ++ipt) {
1143 for (
unsigned short xyz = 0; xyz < 3; ++xyz) {
1148 unsigned short nok = 0;
1149 for (
unsigned short ipt = 0; ipt < 3; ++ipt) {
1150 if (chg[ipt] == 0)
continue;
1151 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
1152 pos[ipt][xyz] /= chg[ipt];
1157 if (nok != 3)
return false;
1177 for (
auto cid : ss3.
CotIDs) {
1178 auto& ss = slc.
cots[cid - 1];
1179 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
1181 ss3.
Energy[plane] = ss.Energy;
1187 ss3.
dEdx[plane] = stj.dEdx[0];
1188 ss3.
dEdxErr[plane] = 0.3 * stj.dEdx[0];
1199 std::string inFcnLabel,
1206 for (
unsigned short ii = 0; ii < ss3.
CotIDs.size() - 1; ++ii) {
1207 unsigned short icid = ss3.
CotIDs[ii];
1208 for (
unsigned short jj = ii + 1; jj < ss3.
CotIDs.size(); ++jj) {
1209 unsigned short jcid = ss3.
CotIDs[jj];
1210 fom +=
Match3DFOM(detProp, inFcnLabel, slc, icid, jcid, prt);
1214 if (cnt == 0)
return 100;
1220 std::string inFcnLabel,
1227 if (icid == 0 || icid > (
int)slc.
cots.size())
return 100;
1228 if (jcid == 0 || jcid > (
int)slc.
cots.size())
return 100;
1229 if (kcid == 0 || kcid > (
int)slc.
cots.size())
return 100;
1231 float ijfom =
Match3DFOM(detProp, inFcnLabel, slc, icid, jcid, prt);
1232 float jkfom =
Match3DFOM(detProp, inFcnLabel, slc, jcid, kcid, prt);
1234 return 0.5 * (ijfom + jkfom);
1240 std::string inFcnLabel,
1247 if (icid == 0 || icid > (
int)slc.
cots.size())
return 100;
1248 if (jcid == 0 || jcid > (
int)slc.
cots.size())
return 100;
1250 auto& iss = slc.
cots[icid - 1];
1251 auto& istj = slc.
tjs[iss.ShowerTjID - 1];
1252 auto& jss = slc.
cots[jcid - 1];
1253 auto& jstj = slc.
tjs[jss.ShowerTjID - 1];
1255 if (iss.CTP == jss.CTP)
return 100;
1257 std::string fcnLabel = inFcnLabel +
".MFOM";
1259 float energyAsym =
std::abs(iss.Energy - jss.Energy) / (iss.Energy + jss.Energy);
1262 if ((iss.Energy > 200 || jss.Energy > 200) && energyAsym > 0.5)
return 50;
1270 float pos1fom =
std::abs(ix - jx) / 10;
1272 float mfom = energyAsym * pos1fom;
1276 myprt << fcnLabel <<
" i2S" << iss.ID <<
" j2S" << jss.ID;
1277 myprt << std::fixed << std::setprecision(2);
1278 myprt <<
" pos1fom " << pos1fom;
1279 myprt <<
" energyAsym " << energyAsym;
1280 myprt <<
" mfom " << mfom;
1291 if (tjList.size() < 2)
return;
1293 bool didMerge =
true;
1296 for (
unsigned short itl = 0; itl < tjList.size() - 1; ++itl) {
1297 if (tjList[itl].
empty())
continue;
1298 for (
unsigned short jtl = itl + 1; jtl < tjList.size(); ++jtl) {
1299 if (tjList[itl].
empty())
continue;
1300 auto& itList = tjList[itl];
1301 auto& jtList = tjList[jtl];
1303 bool jtjInItjList =
false;
1304 for (
auto& jtj : jtList) {
1305 if (std::find(itList.begin(), itList.end(), jtj) != itList.end()) {
1306 jtjInItjList =
true;
1309 if (jtjInItjList)
break;
1313 itList.insert(itList.end(), jtList.begin(), jtList.end());
1323 unsigned short imEmpty = 0;
1324 while (imEmpty < tjList.size()) {
1325 for (imEmpty = 0; imEmpty < tjList.size(); ++imEmpty)
1326 if (tjList[imEmpty].
empty())
break;
1327 if (imEmpty < tjList.size()) tjList.erase(tjList.begin() + imEmpty);
1331 for (
auto& tjl : tjList) {
1332 std::sort(tjl.begin(), tjl.end());
1333 auto last = std::unique(tjl.begin(), tjl.end());
1334 tjl.erase(last, tjl.end());
1350 if (pfp.
ID == 0 || ss3.
ID == 0)
return false;
1352 std::string fcnLabel = inFcnLabel +
".RemP";
1353 for (
auto tid : pfp.
TjIDs) {
1354 for (
auto cid : ss3.
CotIDs) {
1355 auto& ss = slc.
cots[cid - 1];
1356 if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tid) == ss.TjIDs.end())
continue;
1357 if (!
RemoveTj(fcnLabel, slc, tid, ss, doUpdate, prt))
return false;
1379 std::string fcnLabel = inFcnLabel +
".AddP";
1381 if (pID <= 0 || pID > (
int)slc.
pfps.size())
return false;
1382 auto& pfp = slc.
pfps[pID - 1];
1384 if (pfp.TPCID != ss3.
TPCID) {
1385 mf::LogVerbatim(
"TC") << fcnLabel <<
" P" << pID <<
" is in the wrong TPC for 3S" << ss3.
ID;
1389 for (
auto tid : pfp.TjIDs) {
1390 auto& tj = slc.
tjs[tid - 1];
1393 auto& ss = slc.
cots[tj.SSID - 1];
1394 if (ss.SS3ID > 0 && ss.SS3ID != ss3.
ID) {
1396 mf::LogVerbatim(
"TC") << fcnLabel <<
" Conflict: 3S" << ss3.
ID <<
" adding P" << pfp.ID
1397 <<
" -> T" << tid <<
" is in 2S" << tj.SSID <<
" that is in 3S" 1398 << ss.SS3ID <<
" that is not this shower";
1403 mf::LogVerbatim(
"TC") << fcnLabel <<
" 3S" << ss3.
ID <<
" adding P" << pfp.ID <<
" -> T" 1404 << tid <<
" is in the correct shower 2S" << tj.SSID;
1409 myprt << fcnLabel <<
" 3S" << ss3.
ID <<
" adding P" << pfp.ID <<
" -> T" << tid;
1410 myprt <<
" tj.SSID 2S" << tj.SSID;
1413 for (
auto& cid : ss3.
CotIDs) {
1414 auto& ss = slc.
cots[cid - 1];
1415 if (ss.CTP != tj.CTP)
continue;
1417 AddTj(fcnLabel, slc, tid, ss, doUpdate, prt);
1438 if (tjID <= 0 || tjID > (
int)slc.
tjs.size())
return false;
1440 std::string fcnLabel = inFcnLabel +
".AddT";
1445 mf::LogVerbatim(
"TC") << fcnLabel <<
" T" << tjID <<
" is in the wrong CTP for 2S" << ss.
ID;
1451 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" T" << tjID <<
" is already in 2S" << ss.
ID;
1456 mf::LogVerbatim(
"TC") << fcnLabel <<
" Can't add T" << tjID <<
" to 2S" << ss.
ID 1457 <<
". it is already used in 2S" << tj.
SSID;
1462 ss.
TjIDs.push_back(tjID);
1466 for (
unsigned short ii = 0; ii < ss.
NearTjIDs.size(); ++ii) {
1470 unsigned short cnt = 0;
1471 for (
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
1473 if (tp.
Chg == 0)
continue;
1474 for (
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii)
1475 if (tp.
UseHit[ii]) ++cnt;
1477 unsigned short newSize = ss.
ShPts.size() + cnt;
1478 cnt = ss.
ShPts.size();
1479 ss.
ShPts.resize(newSize);
1481 for (
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
1483 if (tp.
Chg == 0)
continue;
1484 for (
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1486 unsigned int iht = tp.
Hits[ii];
1487 ss.
ShPts[cnt].HitIndex = iht;
1490 ss.
ShPts[cnt].Chg =
hit.Integral();
1491 ss.
ShPts[cnt].Pos[0] =
hit.WireID().Wire;
1500 if (doUpdate)
return UpdateShower(fcnLabel, slc, ss, prt);
1515 if (TjID > (
int)slc.
tjs.size())
return false;
1517 std::string fcnLabel = inFcnLabel +
".RTj";
1524 mf::LogVerbatim(
"TC") << fcnLabel <<
" Can't Remove T" << TjID <<
" from 2S" << ss.
ID 1525 <<
" because it's not in this shower";
1532 for (
unsigned short ii = 0; ii < ss.
TjIDs.size(); ++ii) {
1533 if (TjID == ss.
TjIDs[ii]) {
1539 if (!gotit)
return false;
1544 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" Remove T" << TjID <<
" from 2S" << ss.
ID;
1546 if (ss.
TjIDs.empty()) {
1547 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" Removed the last Tj. Killing 2S" << ss.
ID;
1562 std::string inFcnLabel,
1575 if (ss3.
ID == 0)
return false;
1576 if (ss3.
CotIDs.size() < 2)
return false;
1582 std::string fcnLabel = inFcnLabel +
".FPar";
1588 double shMaxAlong, along95;
1591 mf::LogVerbatim(
"TC") << fcnLabel <<
" 3S" << ss3.
ID <<
" Estimated energy " << (int)energy
1592 <<
" MeV shMaxAlong " << shMaxAlong <<
" along95 " << along95
1593 <<
" truPFP " << truPFP;
1614 std::array<int, 2> parID{{0, 0}};
1615 std::array<float, 2> parFOM{{-1E6, -1E6}};
1618 std::vector<bool> isParent(slc.
pfps.size() + 1,
false);
1619 for (
auto& oldSS3 : slc.
showers) {
1620 if (oldSS3.ID == 0)
continue;
1621 isParent[oldSS3.ParentID] =
true;
1625 auto TjsInSS3 =
GetAssns(slc,
"3S", ss3.
ID,
"T");
1626 if (TjsInSS3.empty())
return false;
1628 for (
auto& pfp : slc.
pfps) {
1629 if (pfp.ID == 0)
continue;
1630 bool dprt = (pfp.ID == truPFP);
1631 if (pfp.TPCID != ss3.
TPCID)
continue;
1633 if (pfp.PDGCode == 14 || pfp.PDGCode == 14)
continue;
1635 if (pfp.PDGCode == 1111)
continue;
1637 if (isParent[pfp.ID])
continue;
1639 if (
DontCluster(slc, pfp.TjIDs, TjsInSS3))
continue;
1641 float pfpEnergy = 0;
1642 float minEnergy = 1E6;
1643 for (
auto tid : pfp.TjIDs) {
1644 auto& tj = slc.
tjs[tid - 1];
1645 float energy =
ChgToMeV(tj.TotChg);
1647 if (energy < minEnergy) minEnergy =
energy;
1649 pfpEnergy -= minEnergy;
1650 pfpEnergy /= (float)(pfp.TjIDs.size() - 1);
1654 if (pfpEnergy > energy)
continue;
1660 if (costh1 < 0.4)
continue;
1668 mf::LogVerbatim(
"TC") << fcnLabel <<
" 3S" << ss3.
ID <<
" P" << pfp.ID <<
"_" << pEnd
1669 <<
" distToStart " << sqrt(distToStart2) <<
" distToChgPos " 1670 << sqrt(distToChgPos2) <<
" distToEnd " << sqrt(distToEnd2);
1672 unsigned short shEnd = 0;
1673 if (distToEnd2 < distToStart2) shEnd = 1;
1675 if (shEnd == 0 && distToChgPos2 < distToStart2)
continue;
1676 if (shEnd == 1 && distToChgPos2 < distToEnd2)
continue;
1678 mf::LogVerbatim(
"TC") << fcnLabel <<
" 3S" << ss3.
ID <<
"_" << shEnd <<
" P" << pfp.ID
1679 <<
"_" << pEnd <<
" costh1 " << costh1;
1685 mf::LogVerbatim(
"TC") << fcnLabel <<
" alongTrans " << alongTrans[0] <<
" " 1690 float distToShowerMax = shMaxAlong -
std::abs(alongTrans[0]);
1693 if (prob < 0.1)
continue;
1698 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
1701 for (
auto cid : ss3.
CotIDs) {
1702 auto& ss = slc.
cots[cid - 1];
1703 if (ss.CTP != inCTP)
continue;
1707 if (ssid == 0)
continue;
1708 auto tpFrom =
MakeBareTP(detProp, pos, pToS, inCTP);
1709 auto& ss = slc.
cots[ssid - 1];
1710 auto& stp1 = slc.
tjs[ss.ShowerTjID - 1].Pts[1];
1711 float sep =
PosSep(tpFrom.Pos, stp1.Pos);
1712 float toPos = tpFrom.Pos[0] + 0.5 * tpFrom.Dir[0] * sep;
1716 chgFrac += sep * cf;
1718 if (totSep > 0) chgFrac /= totSep;
1736 myprt <<
" 3S" << ss3.
ID <<
"_" << shEnd;
1737 myprt <<
" P" << pfp.ID <<
"_" << pEnd <<
" ParentVars";
1739 myprt <<
" " << std::fixed << std::setprecision(2) << var;
1740 myprt <<
" candParFOM " << candParFOM;
1742 if (candParFOM > parFOM[shEnd]) {
1743 parFOM[shEnd] = candParFOM;
1744 parID[shEnd] = pfp.ID;
1748 if (parID[0] == 0 && parID[1] == 0)
return true;
1753 float aveDirFOM = 0;
1755 for (
auto cid : ss3.
CotIDs)
1756 aveDirFOM += slc.
cots[cid - 1].DirectionFOM;
1757 aveDirFOM /= (float)ss3.
CotIDs.size();
1759 mf::LogVerbatim(
"TC") << fcnLabel <<
" 3S" << ss3.
ID <<
" parID[0] " << parID[0] <<
" fom " 1760 << parFOM[0] <<
" parID[1] " << parID[1] <<
" fom " << parFOM[1]
1761 <<
" aveDirFOM " << aveDirFOM;
1763 if (parID[0] > 0 && parID[1] > 0 && aveDirFOM > 0.3) {
1768 if (parFOM[1] > parFOM[0]) {
1773 else if (parID[0] > 0) {
1781 if (bestPFP == 0)
return true;
1785 <<
" as the parent " << fom3D;
1789 std::vector<ShowerStruct> oldSS(ss3.
CotIDs.size());
1790 for (
unsigned short ii = 0; ii < ss3.
CotIDs.size(); ++ii) {
1795 auto& pfp = slc.
pfps[bestPFP - 1];
1797 ss3.
Vx3ID = pfp.Vx3ID[pend];
1800 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" 3S" << ss3.
ID <<
" successful update";
1804 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" 3S" << ss3.
ID <<
" Failed. Recovering...";
1806 for (
unsigned short ii = 0; ii < oldSS.size(); ++ii) {
1807 auto& ss = oldSS[ii];
1808 slc.
cots[ss.ID - 1] = ss;
1816 std::string inFcnLabel,
1823 if (pfp.
ID == 0 || ss3.
ID == 0)
return false;
1824 if (ss3.
CotIDs.empty())
return false;
1826 std::string fcnLabel = inFcnLabel +
".SP";
1828 for (
auto cid : ss3.
CotIDs) {
1829 auto& ss = slc.
cots[cid - 1];
1830 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
1832 if (ss.ParentID > 0) {
1833 auto& oldParent = slc.
tjs[ss.ParentID - 1];
1839 for (
auto tjid : pfp.
TjIDs) {
1840 auto& tj = slc.
tjs[tjid - 1];
1841 if (tj.CTP != ss.CTP)
continue;
1842 if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tjid) == ss.TjIDs.end()) {
1844 if (!
AddTj(fcnLabel, slc, tjid, ss,
false, prt))
return false;
1850 unsigned short npts = tj.EndPt[1] - tj.EndPt[0] + 1;
1851 if (tp.Delta > 0.5 || npts > 20) {
1854 << tjid <<
" -> 2S" << ss.ID <<
" parent";
1859 << tjid <<
" low projection in plane " << tp.Delta
1860 <<
". Not a parent";
1864 ss.NeedsUpdate =
true;
1866 if (ss3.
Vx3ID > 0) {
1868 auto v2list =
GetAssns(slc,
"3V", vx3.
ID,
"2V");
1869 for (
unsigned short end = 0;
end < 2; ++
end) {
1870 if (tj.VtxID[
end] <= 0)
continue;
1871 if (std::find(v2list.begin(), v2list.end(), tj.VtxID[
end]) != v2list.end())
1872 stj.VtxID[0] = tj.VtxID[
end];
1876 if (!
UpdateShower(fcnLabel, slc, ss, prt))
return false;
1883 float fom3D =
ParentFOM(fcnLabel, slc, pfp, ss3, prt);
1884 for (
auto cid : ss3.
CotIDs)
1885 slc.
cots[cid - 1].ParentFOM = fom3D;
1894 if (TjIDs.empty())
return false;
1895 unsigned short cnt = 0;
1896 for (
auto tid : TjIDs) {
1897 if (tid <= 0 || tid > (
int)slc.
tjs.size())
continue;
1904 void ShowerParams(
double showerEnergy,
double& shMaxAlong,
double& along95)
1910 if (showerEnergy < 10) {
1915 shMaxAlong = 16 * log(showerEnergy / 15);
1917 double scale = 2.75 - 9.29E-4 * showerEnergy;
1918 if (scale < 2) scale = 2;
1919 along95 = scale * shMaxAlong;
1926 double shMaxAlong, shE95Along;
1928 if (shMaxAlong <= 0)
return 0;
1929 double tau = (along + shMaxAlong) / shMaxAlong;
1931 double rms = -0.4 + 2.5 * tau;
1932 if (rms < 0.5) rms = 0.5;
1942 if (showerEnergy < 10)
return 0;
1944 double shMaxAlong, shE95Along;
1951 double tau = (along + shMaxAlong) / shMaxAlong;
1952 if (tau < -1 || tau > 4)
return 0;
1954 double tauHalf, width;
1966 double prob = 1 / (1 + exp((tau - tauHalf) / width));
1977 if (showerEnergy < 10)
return 0;
1980 double prob = exp(-0.5 * trans / rms);
1996 if (ss3.
ID == 0 || pfp.
ID == 0)
return 0;
1999 for (
auto cid : ss3.
CotIDs) {
2000 auto& ss = slc.
cots[cid - 1];
2001 if (ss.ID == 0)
continue;
2002 for (
auto tid : pfp.
TjIDs) {
2003 auto& tj = slc.
tjs[tid - 1];
2004 if (tj.CTP != ss.CTP)
continue;
2009 if (cnt == 0)
return 0;
2019 if (ss.
ID == 0 || tj.
ID == 0)
return 0;
2020 if (ss.
CTP != tj.
CTP)
return 0;
2023 if (stj.Pts.size() != 3)
return 0;
2024 unsigned short closePt1, closePt2;
2027 if (doca == 1E6)
return 0;
2028 float showerLen =
PosSep(stj.Pts[0].Pos, stj.Pts[2].Pos);
2030 if (doca > 5 * showerLen)
return 0.01;
2031 auto& stp = stj.Pts[closePt1];
2032 if (stp.DeltaRMS == 0)
return 0;
2033 auto& ttp = tj.
Pts[closePt2];
2036 float rms = stp.DeltaRMS;
2037 if (rms < 1) rms = 1;
2038 float arg = alongTrans[1] / rms;
2039 float radProb = exp(-0.5 * arg * arg);
2042 arg = alongTrans[0] / rms;
2043 float longProb = exp(-0.5 * arg * arg);
2045 float prob = radProb * longProb * costh;
2058 if (ss3.
ID == 0)
return 1000;
2061 std::string fcnLabel = inFcnLabel +
".P3FOM";
2063 for (
auto cid : ss3.
CotIDs) {
2064 auto& ss = slc.
cots[cid - 1];
2065 if (ss.ID == 0)
continue;
2068 for (
auto tid : pfp.
TjIDs) {
2069 auto& tj = slc.
tjs[tid - 1];
2070 if (tj.ID == 0)
continue;
2071 if (tj.CTP == ss.CTP) tjid = tid;
2073 if (tjid == 0)
continue;
2074 auto& ptj = slc.
tjs[tjid - 1];
2075 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
2077 unsigned short ptjEnd =
FarEnd(ptj, stj.Pts[1].Pos);
2078 auto& farTP = ptj.Pts[ptj.EndPt[ptjEnd]];
2079 float chgCtrSep2 =
PosSep2(farTP.Pos, stj.Pts[1].Pos);
2080 if (chgCtrSep2 <
PosSep2(farTP.Pos, stj.Pts[0].Pos) &&
2081 chgCtrSep2 <
PosSep2(farTP.Pos, stj.Pts[2].Pos))
2083 float fom =
ParentFOM(fcnLabel, slc, ptj, ptjEnd, ss, dum1, dum2, prt);
2085 if (fom > 50)
continue;
2088 if (ss.AspectRatio > 0) wt = 1 / ss.AspectRatio;
2092 if (wsum == 0)
return 100;
2093 float fom = sum / wsum;
2096 << std::fixed << std::setprecision(3) << fom;
2104 unsigned short& tjEnd,
2116 if (tjEnd > 1)
return 1000;
2117 if (ss.
Energy == 0)
return 1000;
2119 if (ss.
ID == 0)
return 1000;
2120 if (ss.
TjIDs.empty())
return 1000;
2123 std::string fcnLabel = inFcnLabel +
".PFOM";
2151 double shMaxAlong, shE95Along;
2157 if (prob < 0.05)
return 100;
2160 if (alongTrans[1] > shMaxAlong)
return 100;
2162 float longFOM =
std::abs(alongcm + shMaxAlong) / 14;
2166 float transFOM = -1;
2168 transFOM = alongTrans[1] / stp0.
DeltaRMS;
2178 float dang1FOM = dang1 / 0.1;
2182 float dang2FOM = dang1 / 0.1;
2186 std::vector<int> tjlist(1);
2193 if (tj.
VtxID[tjEnd] > 0) {
2196 vx2Score = vx2.
Score;
2198 vxFOM =
std::abs(shMaxAlong - vx2Sep) / 20;
2203 float chgFracFOM = (1 - chgFrac) / 0.1;
2208 float chgFrcBtwFOM = (1 - chgFrac) / 0.05;
2209 fom += chgFrcBtwFOM;
2220 myprt <<
" 2S" << ss.
ID;
2221 myprt <<
" T" << tj.
ID <<
"_" << tjEnd <<
" Pos " <<
PrintPos(ptp);
2222 myprt << std::fixed << std::setprecision(2);
2223 myprt <<
" along " << std::fixed << std::setprecision(1) << alongTrans[0] <<
" fom " 2225 myprt <<
" trans " << alongTrans[1] <<
" fom " << transFOM;
2226 myprt <<
" prob " << prob;
2227 myprt <<
" dang1 " << dang1 <<
" fom " << dang1FOM;
2228 myprt <<
" dang2 " << dang2 <<
" fom " << dang2FOM;
2229 myprt <<
" vx2Score " << vx2Score <<
" fom " << vxFOM;
2230 myprt <<
" chgFrac " << chgFrac <<
" fom " << chgFracFOM;
2231 myprt <<
" chgFracBtw " << chgFracBtw <<
" fom " << chgFrcBtwFOM;
2232 myprt <<
" FOM " << fom;
2242 unsigned short tjEnd,
2260 if (tjEnd > 1)
return false;
2262 std::string fcnLabel = inFcnLabel +
".WSTj";
2265 unsigned short otherEnd = 1 - tjEnd;
2267 if (tj.
VtxID[otherEnd] == 0)
return false;
2268 unsigned short ivx = tj.
VtxID[otherEnd] - 1;
2270 if (slc.
vtxs[ivx].Topo != 8 && slc.
vtxs[ivx].Topo != 10)
return false;
2273 <<
" was split by a 3D vertex";
2282 if (slc.
cots.empty())
return;
2284 std::string fcnLabel = inFcnLabel +
".MNS";
2288 myprt << fcnLabel <<
" list";
2289 for (
auto& ss : slc.
cots) {
2290 if (ss.CTP != inCTP)
continue;
2291 if (ss.ID == 0)
continue;
2292 myprt <<
" ss.ID " << ss.ID <<
" NearTjs";
2293 for (
auto&
id : ss.NearTjIDs)
2299 bool keepMerging =
true;
2300 while (keepMerging) {
2301 keepMerging =
false;
2302 for (
unsigned short ci1 = 0; ci1 < slc.
cots.size() - 1; ++ci1) {
2304 if (ss1.
CTP != inCTP)
continue;
2305 if (ss1.
ID == 0)
continue;
2306 if (ss1.
TjIDs.empty())
continue;
2308 std::vector<int> ss1list = ss1.
TjIDs;
2310 for (
unsigned short ci2 = ci1 + 1; ci2 < slc.
cots.size(); ++ci2) {
2312 if (ss2.
CTP != inCTP)
continue;
2313 if (ss2.
ID == 0)
continue;
2314 if (ss2.
TjIDs.empty())
continue;
2316 std::vector<int> ss2list = ss2.
TjIDs;
2319 if (shared.empty())
continue;
2322 myprt << fcnLabel <<
" Merge 2S" << ss2.
ID <<
" into 2S" << ss1.
ID 2323 <<
"? shared nearby:";
2324 for (
auto tjid : shared)
2325 myprt <<
" T" << tjid;
2328 bool doMerge =
false;
2329 for (
auto& tjID : shared) {
2330 bool inSS1 = (std::find(ss1.
TjIDs.begin(), ss1.
TjIDs.end(), tjID) != ss1.
TjIDs.end());
2331 bool inSS2 = (std::find(ss2.
TjIDs.begin(), ss2.
TjIDs.end(), tjID) != ss2.
TjIDs.end());
2332 if (inSS1 && !inSS2) doMerge =
true;
2333 if (!inSS1 && inSS2) doMerge =
true;
2335 if (inSS1 || inSS2)
continue;
2336 auto& tj = slc.
tjs[tjID - 1];
2338 if (tj.PDGCode == 13 && tj.Pts.size() > 100 && tj.ChgRMS < 0.5) {
2341 << fcnLabel <<
" T" << tj.ID <<
" looks like a muon. Don't add it";
2347 if (!TInP.empty()) {
2348 auto& pfp = slc.
pfps[TInP[0] - 1];
2349 if (pfp.PDGCode == 13 &&
MCSMom(slc, pfp.TjIDs) > 500)
continue;
2352 if (
AddTj(fcnLabel, slc, tjID, ss1,
false, prt)) doMerge =
true;
2354 if (!doMerge)
continue;
2392 if (slc.
cots.empty())
return;
2394 std::string fcnLabel = inFcnLabel +
".MO";
2403 bool didMerge =
true;
2407 for (
unsigned short ict = 0; ict < slc.
cots.size() - 1; ++ict) {
2408 auto& iss = slc.
cots[ict];
2409 if (iss.ID == 0)
continue;
2410 if (iss.TjIDs.empty())
continue;
2411 if (iss.CTP != inCTP)
continue;
2412 for (
unsigned short jct = ict + 1; jct < slc.
cots.size(); ++jct) {
2413 auto& jss = slc.
cots[jct];
2414 if (jss.ID == 0)
continue;
2415 if (jss.TjIDs.empty())
continue;
2416 if (jss.CTP != iss.CTP)
continue;
2417 if (
DontCluster(slc, iss.TjIDs, jss.TjIDs))
continue;
2418 bool doMerge =
false;
2419 for (
auto& ivx : iss.Envelope) {
2424 for (
auto& jvx : jss.Envelope) {
2431 for (
auto& ivx : iss.Envelope) {
2432 for (
auto& jvx : jss.Envelope) {
2433 if (
PosSep2(ivx, jvx) < sepCut2) {
2436 << fcnLabel <<
" Envelopes 2S" << iss.ID <<
" 2S" << jss.ID <<
" are close " 2445 if (!doMerge)
continue;
2449 unsigned short iClosePt = 0;
2450 unsigned short jClosePt = 0;
2452 auto& istj = slc.
tjs[iss.ShowerTjID - 1];
2453 auto& jstj = slc.
tjs[jss.ShowerTjID - 1];
2454 for (
unsigned short ipt = 0; ipt < 3; ++ipt) {
2455 for (
unsigned short jpt = 0; jpt < 3; ++jpt) {
2456 float sep =
PosSep2(istj.Pts[ipt].Pos, jstj.Pts[jpt].Pos);
2464 float costh =
DotProd(istj.Pts[0].Dir, jstj.Pts[0].Dir);
2465 if (iClosePt == 0 && jClosePt == 0 && costh < 0.955) {
2468 << fcnLabel <<
" showers are close at the start points with costh " << costh
2472 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" Merge " << iss.ID <<
" and " << jss.ID;
2497 std::string fcnLabel = inFcnLabel +
".MSC";
2499 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
": MergeShowerChain inCTP " << inCTP;
2501 std::vector<int> sids;
2502 std::vector<TrajPoint> tpList;
2503 for (
unsigned short ict = 0; ict < slc.
cots.size(); ++ict) {
2505 if (iss.
ID == 0)
continue;
2506 if (iss.
TjIDs.empty())
continue;
2507 if (iss.
CTP != inCTP)
continue;
2509 if (iss.
Energy < 50)
continue;
2511 sids.push_back(iss.
ID);
2515 if (sids.size() < 3)
return;
2518 std::vector<SortEntry> sortVec(sids.size());
2519 for (
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
2520 sortVec[ii].index = ii;
2521 sortVec[ii].val = tpList[ii].Pos[0];
2525 auto ttpList = tpList;
2526 for (
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
2527 unsigned short indx = sortVec[ii].index;
2528 sids[ii] = tsids[indx];
2529 tpList[ii] = ttpList[indx];
2534 float maxDelta = 30;
2535 for (
unsigned short ii = 0; ii < sids.size() - 2; ++ii) {
2536 auto& iss = slc.
cots[sids[ii] - 1];
2537 if (iss.ID == 0)
continue;
2538 unsigned short jj = ii + 1;
2539 auto& jss = slc.
cots[sids[jj] - 1];
2540 if (jss.ID == 0)
continue;
2541 std::vector<int> chain;
2542 float sepij =
PosSep(tpList[ii].Pos, tpList[jj].Pos);
2543 if (sepij > minSep)
continue;
2544 bool skipit =
DontCluster(slc, iss.TjIDs, jss.TjIDs);
2547 <<
" j2S" << jss.ID <<
" " <<
PrintPos(tpList[jj].Pos) <<
" sepij " 2548 << sepij <<
" skipit? " << skipit;
2549 if (skipit)
continue;
2553 for (
unsigned short kk = jj + 1; kk < sids.size(); ++kk) {
2554 auto& kss = slc.
cots[sids[kk] - 1];
2555 if (kss.ID == 0)
continue;
2556 if (
DontCluster(slc, iss.TjIDs, kss.TjIDs))
continue;
2557 if (
DontCluster(slc, jss.TjIDs, kss.TjIDs))
continue;
2558 float sepjk =
PosSep(tpList[jj].Pos, tpList[kk].Pos);
2559 float delta =
PointTrajDOCA(tpList[kk].Pos[0], tpList[kk].Pos[1], tp);
2562 myprt << fcnLabel <<
" k2S" << kss.ID <<
" " <<
PrintPos(tpList[kk].Pos) <<
" sepjk " 2563 << sepjk <<
" delta " << delta;
2564 if (sepjk > minSep || delta > maxDelta) {
2565 myprt <<
" failed separation " << minSep <<
" or delta cut " << maxDelta;
2568 myprt <<
" add to the chain";
2571 if (sepjk > minSep || delta > maxDelta) {
2573 if (chain.size() > 2) {
2578 myprt << fcnLabel <<
" merged chain";
2579 for (
auto ssID : chain)
2580 myprt <<
" 2S" << ssID;
2581 myprt <<
" -> 2S" << newID;
2589 if (chain.empty()) {
2591 chain[0] = sids[ii];
2592 chain[1] = sids[jj];
2593 chain[2] = sids[kk];
2596 chain.push_back(sids[kk]);
2603 if (chain.size() > 2) {
2607 myprt << fcnLabel <<
" merged chain";
2608 for (
auto ssID : chain)
2609 myprt <<
" " << ssID;
2610 myprt <<
" -> new ssID " << newID;
2627 std::string fcnLabel = inFcnLabel +
".MSSTj";
2634 std::vector<TjSS> tjss;
2637 std::vector<int> tjid(1);
2638 for (
auto& ss : slc.
cots) {
2639 if (ss.ID == 0)
continue;
2640 if (ss.CTP != inCTP)
continue;
2642 if (ss.Energy > 300)
continue;
2643 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
2644 auto stp0 = stj.Pts[0];
2645 float bestDang = 0.3;
2648 for (
auto& tj : slc.
tjs) {
2649 if (tj.AlgMod[
kKilled])
continue;
2650 if (tj.AlgMod[
kHaloTj])
continue;
2651 if (tj.CTP != ss.CTP)
continue;
2653 if (tj.SSID > 0)
continue;
2661 float tjEnergy =
ChgToMeV(tj.TotChg);
2663 unsigned short farEnd =
FarEnd(tj, stj.Pts[1].Pos);
2665 unsigned short midpt = 0.5 * (tj.EndPt[0] + tj.EndPt[1]);
2666 float mom1 =
MCSMom(slc, tj, tj.EndPt[farEnd], midpt);
2667 float mom2 =
MCSMom(slc, tj, tj.EndPt[1 - farEnd], midpt);
2668 float asym = (mom1 - mom2) / (mom1 + mom2);
2669 auto& farTP = tj.Pts[tj.EndPt[farEnd]];
2671 float doca =
PointTrajDOCA(stp0.Pos[0], stp0.Pos[1], farTP);
2672 float sep =
PosSep(farTP.Pos, stp0.Pos);
2673 float dang = doca / sep;
2676 myprt << fcnLabel <<
" Candidate 2S" << ss.ID <<
" T" << tj.ID <<
"_" << farEnd;
2677 myprt <<
" ShEnergy " << (int)ss.Energy <<
" tjEnergy " << (
int)tjEnergy;
2678 myprt <<
" doca " << doca <<
" sep " << sep <<
" dang " << dang <<
" asym " << asym;
2680 if (tjEnergy < ss.Energy)
continue;
2681 if (asym < 0.5)
continue;
2684 if (sep > 100)
continue;
2685 if (dang > bestDang)
continue;
2689 if (bestTj == 0)
continue;
2692 match.tjID = bestTj;
2693 match.dang = bestDang;
2694 tjss.push_back(match);
2697 if (tjss.empty())
return;
2700 bool keepGoing =
true;
2703 float bestDang = 0.3;
2705 for (
unsigned short mat = 0;
mat < tjss.size(); ++
mat) {
2706 auto& match = tjss[
mat];
2708 if (match.dang < 0)
continue;
2709 if (match.dang < bestDang) bestMatch =
mat;
2711 if (bestMatch > 0) {
2712 auto& match = tjss[bestMatch];
2713 auto& ss = slc.
cots[match.ssID - 1];
2714 if (!
AddTj(fcnLabel, slc, match.tjID, ss,
true, prt)) {
2720 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
2737 std::string fcnLabel = inFcnLabel +
".MSS";
2739 constexpr
float radLen = 14 / 0.3;
2743 mf::LogVerbatim(
"TC") << fcnLabel <<
" MergeSubShowers checking using ShowerParams";
2747 <<
" MergeSubShowers checking using radiation length cut ";
2751 bool keepMerging =
true;
2752 while (keepMerging) {
2753 keepMerging =
false;
2755 std::vector<SortEntry> sortVec;
2756 for (
auto& ss : slc.
cots) {
2757 if (ss.ID == 0)
continue;
2758 if (ss.CTP != inCTP)
continue;
2760 se.
index = ss.ID - 1;
2762 sortVec.push_back(se);
2764 if (sortVec.size() < 2)
return;
2766 for (
unsigned short ii = 0; ii < sortVec.size() - 1; ++ii) {
2768 if (iss.
ID == 0)
continue;
2772 double shMaxAlong, along95;
2775 along95 -= shMaxAlong;
2778 for (
unsigned short jj = ii + 1; jj < sortVec.size(); ++jj) {
2780 if (jss.
ID == 0)
continue;
2789 if (alongTrans[0] < 0)
continue;
2791 float alongCut = along95;
2797 myprt << fcnLabel <<
" Candidate i2S" << iss.
ID <<
" E = " << (int)iss.
Energy 2798 <<
" j2S" << jss.
ID <<
" E = " << (
int)jss.
Energy;
2799 myprt <<
" along " << std::fixed << std::setprecision(1) << alongTrans[0] <<
" trans " 2801 myprt <<
" alongCut " << alongCut <<
" probLong " << probLong <<
" probTran " 2804 if (alongTrans[0] > alongCut)
continue;
2805 if (alongTrans[1] > alongTrans[0])
continue;
2810 float trad = sep / radLen;
2820 float dang = delta / sep;
2823 <<
" separation " << (int)sep <<
" radiation lengths " << trad
2824 <<
" delta " << delta <<
" dang " << dang;
2825 if (trad > 3)
continue;
2827 if (dang > 0.3)
continue;
2830 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" Merge them. Re-find shower center, etc";
2838 if (keepMerging)
break;
2852 std::string fcnLabel = inFcnLabel +
".MS";
2853 if (ssIDs.size() < 2)
return 0;
2855 for (
auto ssID : ssIDs)
2856 if (ssID <= 0 || ssID > (
int)slc.
cots.size())
return 0;
2859 auto& ss0 = slc.
cots[ssIDs[0] - 1];
2860 std::vector<int> tjl;
2861 for (
auto ssID : ssIDs) {
2862 auto& ss = slc.
cots[ssID - 1];
2863 if (ss.CTP != ss0.CTP)
return 0;
2864 tjl.insert(tjl.end(), ss.TjIDs.begin(), ss.TjIDs.end());
2865 if (ss.SS3ID > 0 && ss3Assn == 0) ss3Assn = ss.SS3ID;
2866 if (ss.SS3ID > 0 && ss.SS3ID != ss3Assn)
return 0;
2869 for (
auto tjID : tjl) {
2870 auto& tj = slc.
tjs[tjID - 1];
2871 if (tj.CTP != ss0.CTP || tj.AlgMod[
kKilled])
return 0;
2875 for (
auto ssID : ssIDs) {
2876 auto& ss = slc.
cots[ssID - 1];
2879 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
2885 if (newss.ID == 0)
return 0;
2887 for (
auto tid : tjl) {
2888 auto& tj = slc.
tjs[tid - 1];
2891 newss.SS3ID = ss3Assn;
2914 if (icotID <= 0 || icotID > (
int)slc.
cots.size())
return false;
2916 if (iss.
ID == 0)
return false;
2917 if (iss.
TjIDs.empty())
return false;
2920 if (jcotID <= 0 || jcotID > (
int)slc.
cots.size())
return false;
2922 if (jss.
TjIDs.empty())
return false;
2923 if (jss.
ID == 0)
return false;
2926 if (iss.
CTP != jss.
CTP)
return false;
2928 std::string fcnLabel = inFcnLabel +
".MSAS";
2934 if (!itj.
Pts[1].Hits.empty() || !jtj.
Pts[1].Hits.empty())
return false;
2939 ktj.
ID = slc.
tjs.size() + 1;
2941 slc.
tjs.push_back(ktj);
2954 std::sort(iss.
TjIDs.begin(), iss.
TjIDs.end());
2956 for (
auto tid : iss.
TjIDs) {
2957 auto& tj = slc.
tjs[tid - 1];
2985 if (istj > slc.
tjs.size() - 1)
return false;
2986 if (jstj > slc.
tjs.size() - 1)
return false;
2991 std::string fcnLabel =
"MSTJ";
2994 mf::LogVerbatim(
"TC") << fcnLabel <<
" MergeShowerTjsAndStore Tj IDs " << itj.
ID <<
" " 3007 if (icotID == 0)
return false;
3009 if (iss.
ID == 0)
return false;
3010 if (iss.
TjIDs.empty())
return false;
3012 if (jcotID == 0)
return false;
3014 if (jss.
ID == 0)
return false;
3015 if (jss.
TjIDs.empty())
return false;
3029 if (ss.
ID == 0)
return false;
3030 if (ss.
ShPts.empty())
return false;
3032 if (stj.
Pts.size() != 3)
return false;
3034 std::string fcnLabel = inFcnLabel +
".ARP";
3036 for (
auto& tp : stj.
Pts) {
3040 tp.HitPos = {{0.0, 0.0}};
3043 float minAlong = ss.
ShPts[0].RotPos[0];
3044 float maxAlong = ss.
ShPts[ss.
ShPts.size() - 1].RotPos[0];
3045 float sectionLength = (maxAlong - minAlong) / 3;
3046 float sec0 = minAlong + sectionLength;
3047 float sec2 = maxAlong - sectionLength;
3049 for (
auto& spt : ss.
ShPts) {
3051 unsigned short ipt = 0;
3052 if (spt.RotPos[0] < sec0) {
3056 else if (spt.RotPos[0] > sec2) {
3064 stj.
Pts[ipt].Chg += spt.Chg;
3069 stj.
Pts[ipt].DeltaRMS += spt.Chg *
std::abs(spt.RotPos[1]);
3070 ++stj.
Pts[ipt].NTPsFit;
3072 stj.
Pts[ipt].HitPos[0] += spt.Chg * spt.Pos[0];
3073 stj.
Pts[ipt].HitPos[1] += spt.Chg * spt.Pos[1];
3076 for (
auto& tp : stj.
Pts) {
3078 tp.DeltaRMS /= tp.Chg;
3079 tp.HitPos[0] /= tp.Chg;
3080 tp.HitPos[1] /= tp.Chg;
3086 if (stj.
Pts[0].Chg == 0 || stj.
Pts[2].Chg == 0)
return false;
3089 if (stj.
Pts[1].Chg == 0) {
3091 stj.
Pts[1].HitPos[0] = 0.5 * (stj.
Pts[0].HitPos[0] + stj.
Pts[2].HitPos[0]);
3092 stj.
Pts[1].HitPos[1] = 0.5 * (stj.
Pts[0].HitPos[1] + stj.
Pts[2].HitPos[1]);
3100 myprt << fcnLabel <<
" 2S" << ss.
ID;
3101 myprt <<
" HitPos[0] " << std::fixed << std::setprecision(1);
3102 myprt << stj.
Pts[1].HitPos[0] <<
" " << stj.
Pts[1].HitPos[1] <<
" " << stj.
Pts[1].HitPos[2];
3103 myprt <<
" DeltaRMS " << std::setprecision(2);
3104 myprt << stj.
Pts[0].DeltaRMS <<
" " << stj.
Pts[1].DeltaRMS <<
" " << stj.
Pts[2].DeltaRMS;
3105 myprt <<
" DirectionFOM " << std::fixed << std::setprecision(2) << ss.
DirectionFOM;
3116 if (ss.
ID == 0)
return;
3117 if (ss.
TjIDs.empty())
return;
3119 std::string fcnLabel = inFcnLabel +
".RevSh";
3121 std::reverse(ss.
ShPts.begin(), ss.
ShPts.end());
3123 for (
auto& sspt : ss.
ShPts) {
3124 sspt.RotPos[0] = -sspt.RotPos[0];
3125 sspt.RotPos[1] = -sspt.RotPos[1];
3144 if (cotID > (
int)slc.
cots.size())
return;
3146 if (ss.
ID == 0)
return;
3155 for (
auto cid : ss3.
CotIDs) {
3156 if (cid == 0 || (
unsigned short)cid > slc.
cots.size())
continue;
3157 auto& ss = slc.
cots[cid - 1];
3158 if (ss.SS3ID > 0 && ss.SS3ID != ss3.
ID)
continue;
3162 std::string fcnLabel = inFcnLabel +
".MSO";
3173 if (ss.
ID == 0)
return;
3175 std::string fcnLabel = inFcnLabel +
".MSO";
3178 if (!stp1.Hits.empty())
return;
3183 std::vector<int> newCIDs;
3184 for (
auto cid : ss3.CotIDs) {
3185 if (cid != ss.
ID) newCIDs.push_back(cid);
3187 ss3.CotIDs = newCIDs;
3195 for (
auto& tjID : ss.
TjIDs) {
3214 const std::vector<int>& tjlist1,
3215 const std::vector<int>& tjlist2)
3218 if (tjlist1.empty() || tjlist2.empty())
return false;
3220 for (
auto tid1 : tjlist1) {
3221 for (
auto tid2 : tjlist2) {
3223 if (ttid1 > tid2) std::swap(ttid1, tid2);
3225 if (dc.TjIDs[0] == ttid1 && dc.TjIDs[1] == tid2)
return true;
3238 if (slc.
tjs.size() > 20000)
return;
3244 std::vector<std::vector<int>> tjLists;
3245 std::vector<int> tjids;
3246 for (
auto& tj : slc.
tjs) {
3247 if (tj.CTP != inCTP)
continue;
3248 if (tj.AlgMod[
kKilled])
continue;
3249 if (tj.AlgMod[
kHaloTj])
continue;
3253 bool skipit =
false;
3254 for (
unsigned short end = 0;
end < 2; ++
end)
3255 if (tj.EndFlag[
end][
kBragg]) skipit =
true;
3256 if (skipit)
continue;
3260 if (npwc > 100)
continue;
3267 if (tj.ChgRMS > typicalChgRMS) momCut *= tj.ChgRMS / typicalChgRMS;
3268 if (tj.MCSMom > momCut)
continue;
3270 tjids.push_back(tj.ID);
3273 if (tjids.size() < 2)
return;
3275 for (
unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
3277 for (
unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
3279 unsigned short ipt1, ipt2;
3286 bool inlist =
false;
3287 for (
unsigned short it = 0; it < tjLists.size(); ++it) {
3289 (std::find(tjLists[it].
begin(), tjLists[it].
end(), tj1.
ID) != tjLists[it].end());
3291 (std::find(tjLists[it].
begin(), tjLists[it].
end(), tj2.
ID) != tjLists[it].end());
3292 if (tj1InList || tj2InList) {
3294 if (!tj1InList) tjLists[it].push_back(tj1.
ID);
3295 if (!tj2InList) tjLists[it].push_back(tj2.
ID);
3303 std::vector<int> newlist(2);
3304 newlist[0] = tj1.
ID;
3305 newlist[1] = tj2.
ID;
3306 tjLists.push_back(newlist);
3310 if (tjLists.empty())
return;
3313 for (
auto& tjl : tjLists) {
3315 if (tjl.size() < 3)
continue;
3316 for (
auto& tjID : tjl) {
3317 auto& tj = slc.
tjs[tjID - 1];
3323 unsigned short nsh = 0;
3324 for (
auto& tjl : tjLists) {
3325 for (
auto& tjID : tjl) {
3326 auto& tj = slc.
tjs[tjID - 1];
3330 mf::LogVerbatim(
"TC") <<
"TagShowerLike tagged " << nsh <<
" Tjs vertices in CTP " << inCTP;
3344 std::string fcnLabel = inFcnLabel +
".FNTj";
3346 std::vector<int> ntj;
3349 constexpr
float fiveRadLen = 200;
3352 for (
auto vx : slc.
vtxs) {
3353 if (vx.CTP != ss.
CTP)
continue;
3354 if (vx.ID == 0)
continue;
3356 auto vxTjIDs =
GetAssns(slc,
"2V", vx.
ID,
"T");
3357 for (
auto tjID : vxTjIDs) {
3359 if (std::find(ss.
TjIDs.begin(), ss.
TjIDs.end(), tjID) != ss.
TjIDs.end())
continue;
3361 if (std::find(ntj.begin(), ntj.end(), tjID) != ntj.end())
continue;
3362 ntj.push_back(tjID);
3367 for (
auto& tj : slc.
tjs) {
3368 if (tj.CTP != ss.
CTP)
continue;
3369 if (tj.AlgMod[
kKilled])
continue;
3373 if (std::find(ss.
TjIDs.begin(), ss.
TjIDs.end(), tj.ID) != ss.
TjIDs.end())
continue;
3375 if (std::find(ntj.begin(), ntj.end(), tj.ID) != ntj.end())
continue;
3377 if (tj.Pts.size() > 40 && tj.MCSMom > 200) {
3378 float delta =
PointTrajDOCA(stj.Pts[1].Pos[0], stj.Pts[1].Pos[1], tj.Pts[tj.EndPt[0]]);
3381 float doca = fiveRadLen;
3382 unsigned short spt = 0, ipt = 0;
3384 if (doca < fiveRadLen) {
3385 ntj.push_back(tj.ID);
3391 bool isInside =
false;
3392 for (
unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ipt += 3) {
3400 unsigned short ipt = tj.EndPt[1];
3403 if (isInside) ntj.push_back(tj.ID);
3405 if (ntj.size() > 1) std::sort(ntj.begin(), ntj.end());
3407 mf::LogVerbatim(
"TC") << fcnLabel <<
" Found " << ntj.size() <<
" Tjs near ss.ID " << ss.
ID;
3417 if (itj > slc.
tjs.size() - 1)
return;
3422 for (
auto& tp : slc.
tjs[itj].Pts) {
3423 for (
unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3425 if (tp.UseHit[ii])
continue;
3426 unsigned int iht = tp.Hits[ii];
3428 if (slc.
slHits[iht].InTraj <= 0)
continue;
3429 if ((
unsigned int)slc.
slHits[iht].InTraj > slc.
tjs.size())
continue;
3432 if (tj.
MCSMom > maxMom)
continue;
3435 if (std::find(list.begin(), list.end(), slc.
slHits[iht].InTraj) != list.end())
continue;
3436 list.push_back(slc.
slHits[iht].InTraj);
3445 if (ss.
ID == 0)
return;
3446 if (ss.
TjIDs.empty())
return;
3449 if (stj.
Pts[0].Pos[0] == 0)
return;
3451 std::string fcnLabel = inFcnLabel +
".DE";
3478 float cs = cos(stp1.
Ang);
3479 float sn = sin(stp1.
Ang);
3482 float pos0 = cs * vtx[0] - sn * vtx[1];
3483 float pos1 = sn * vtx[0] + cs * vtx[1];
3485 vtx[0] = pos0 + stp1.
Pos[0];
3486 vtx[1] = pos1 + stp1.
Pos[1];
3492 myprt << fcnLabel <<
" 2S" << ss.
ID <<
" Envelope";
3494 myprt <<
" " << (int)vtx[0] <<
":" << (
int)(vtx[1] /
tcc.
unitsPerTick);
3507 if (ss.
Envelope.empty())
return false;
3508 if (ss.
ID == 0)
return false;
3509 if (ss.
TjIDs.empty())
return false;
3511 std::string fcnLabel = inFcnLabel +
".ATIE";
3515 std::vector<int>
tmp(1);
3516 unsigned short nadd = 0;
3517 for (
auto& tj : slc.
tjs) {
3518 if (tj.CTP != ss.
CTP)
continue;
3519 if (tj.AlgMod[
kKilled])
continue;
3520 if (tj.SSID > 0)
continue;
3523 if (tj.ParentID == 0)
continue;
3525 if (neutPrimTj > 0 && neutPrimTj != tj.ID) {
3532 if (std::find(ss.
TjIDs.begin(), ss.
TjIDs.end(), tj.ID) != ss.
TjIDs.end())
continue;
3539 if (!end0Inside && !end1Inside)
continue;
3540 if (end0Inside && end1Inside) {
3542 if (
AddTj(fcnLabel, slc, tj.
ID, ss,
false, prt)) ++nadd;
3549 if (tj.MCSMom > 200) {
3550 float tjAngle = tj.Pts[tj.EndPt[0]].Ang;
3553 mf::LogVerbatim(
"TC") << fcnLabel <<
" high MCSMom " << tj.MCSMom <<
" dangPull " 3555 if (dangPull > 2)
continue;
3557 if (
AddTj(fcnLabel, slc, tj.
ID, ss,
false, prt)) { ++nadd; }
3559 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" AddTj failed to add T" << tj.ID;
3564 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" Added " << nadd <<
" trajectories ";
3570 if (prt)
mf::LogVerbatim(
"TC") << fcnLabel <<
" No new trajectories added to envelope ";
3585 if (ss.
Envelope.empty())
return false;
3586 if (ss.
ID == 0)
return false;
3587 if (ss.
TjIDs.empty())
return false;
3590 unsigned short ipl = planeID.
Plane;
3595 std::vector<unsigned int> newHits;
3598 float fLoWire = 1E6;
3604 if (vtx[0] < fLoWire) fLoWire = vtx[0];
3605 if (vtx[0] > fHiWire) fHiWire = vtx[0];
3606 if (vtx[1] < loTick) loTick = vtx[1];
3607 if (vtx[1] > hiTick) hiTick = vtx[1];
3611 unsigned int loWire = std::nearbyint(fLoWire);
3612 unsigned int hiWire = std::nearbyint(fHiWire) + 1;
3614 std::array<float, 2> point;
3615 for (
unsigned int wire = loWire; wire < hiWire; ++wire) {
3617 if (slc.
wireHitRange[ipl][wire].first == UINT_MAX)
continue;
3618 unsigned int firstHit = slc.
wireHitRange[ipl][wire].first;
3619 unsigned int lastHit = slc.
wireHitRange[ipl][wire].second;
3620 for (
unsigned int iht = firstHit; iht < lastHit; ++iht) {
3622 if (slc.
slHits[iht].InTraj != 0)
continue;
3625 if (
hit.PeakTime() < loTick)
continue;
3627 if (
hit.PeakTime() > hiTick)
break;
3629 point[0] =
hit.WireID().Wire;
3632 newHits.push_back(iht);
3637 if (newHits.empty()) {
3643 stp0.
Hits.insert(stp0.
Hits.end(), newHits.begin(), newHits.end());
3644 for (
auto& iht : newHits)
3658 if (cotID > (
int)slc.
cots.size())
return;
3661 if (ss.
ID == 0)
return;
3662 if (ss.
TjIDs.empty())
return;
3667 std::string fcnLabel = inFcnLabel +
".FSC";
3673 mf::LogVerbatim(
"TC") << fcnLabel <<
" Not possible due to poor AspectRatio " 3680 if (schg.empty())
return;
3684 unsigned short startPt = USHRT_MAX;
3686 for (
unsigned short ii = 0; ii < schg.size() - 1; ++ii) {
3687 if (schg[ii] > 0 && schg[ii + 1] > 0) {
3693 if (startPt == USHRT_MAX)
return;
3699 for (
unsigned short ii = startPt; ii < schg.size() - 1; ++ii) {
3701 rms += schg[ii] * schg[ii];
3705 rms = rms - cnt * ave * ave;
3706 if (rms < 0)
return;
3707 rms = sqrt(rms / (cnt - 1));
3711 myprt << fcnLabel <<
" schg:";
3712 for (
unsigned short ii = 0; ii < 20; ++ii)
3713 myprt <<
" " << (
int)schg[ii];
3714 myprt <<
"\n First guess at the charge " << (int)chg <<
" average charge of all bins " 3715 << (
int)ave <<
" rms " << (int)rms;
3721 unsigned short nBinsAverage = 5;
3722 double maxChg = 2 * chg;
3723 for (
unsigned short nit = 0; nit < 2; ++nit) {
3727 for (
unsigned short ii = startPt; ii < schg.size() - 1; ++ii) {
3729 if (schg[ii] > maxChg && schg[ii + 1] > maxChg)
break;
3731 if (schg[ii] == 0 && schg[ii + 1] == 0)
break;
3732 if (schg[ii] > maxChg)
continue;
3734 sum2 += schg[ii] * schg[ii];
3736 if (cnt == nBinsAverage)
break;
3742 <<
" is too low. sum " << (int)sum <<
" maxChg " << (
int)maxChg;
3745 chg = schg[startPt];
3751 double arg = sum2 - cnt * chg * chg;
3753 rms = sqrt(arg / (cnt - 1));
3755 double maxrms = 0.5 *
sum;
3756 if (rms > maxrms) rms = maxrms;
3757 maxChg = chg + 2 * rms;
3759 mf::LogVerbatim(
"TC") << fcnLabel <<
" nit " << nit <<
" cnt " << cnt <<
" chg " << (int)chg
3760 <<
" rms " << (
int)rms <<
" maxChg " << (int)maxChg
3761 <<
" nBinsAverage " << nBinsAverage;
3768 mf::LogVerbatim(
"TC") << fcnLabel <<
" 2S" << cotID <<
" Starting charge " << (int)stp0.AveChg
3769 <<
" startPt " << startPt;
3779 constexpr
unsigned short nbins = 20;
3780 std::vector<float> schg(nbins);
3781 if (ss.
ID == 0)
return schg;
3782 if (ss.
TjIDs.empty())
return schg;
3787 float minAlong = ss.
ShPts[0].RotPos[0] - 2;
3792 float cs = cos(-ss.
Angle);
3794 std::array<float, 2> chgPos;
3797 for (
auto& sspt : ss.
ShPts) {
3798 unsigned short indx = (
unsigned short)((sspt.RotPos[0] - minAlong));
3799 if (indx > nbins - 1)
break;
3801 if (
std::abs(sspt.RotPos[1]) > maxTrans)
continue;
3802 unsigned int iht = sspt.HitIndex;
3804 float peakTime =
hit.PeakTime();
3805 float amp =
hit.PeakAmplitude();
3806 float rms =
hit.RMS();
3807 chgPos[0] =
hit.WireID().Wire - stp1.
Pos[0];
3808 for (
float time = peakTime - 2.5 * rms; time < peakTime + 2.5 * rms; ++time) {
3810 along = cs * chgPos[0] - sn * chgPos[1];
3811 if (along < minAlong)
continue;
3812 indx = (
unsigned short)(along - minAlong);
3813 if (indx > nbins - 1)
continue;
3814 arg = (time - peakTime) / rms;
3815 schg[indx] += amp * exp(-0.5 * arg * arg);
3829 if (cotID > (
int)slc.
cots.size())
return;
3832 if (ss.
ID == 0)
return;
3833 if (ss.
TjIDs.empty())
return;
3834 std::cout <<
"PTS Pos0 Pos1 RPos0 RPos1 Chg TID\n";
3836 std::cout <<
"PTS " << std::fixed << std::setprecision(1) <<
pt.Pos[0] <<
" " <<
pt.Pos[1]
3837 <<
" " <<
pt.RotPos[0] <<
" " <<
pt.RotPos[1];
3838 std::cout <<
" " << (int)
pt.Chg <<
" " <<
pt.TID;
3849 bool newShowers =
false;
3850 for (
auto& ss : slc.
cots) {
3851 if (ss.ID == 0)
continue;
3852 if (ss.ShowerTjID == 0)
continue;
3855 if (!stj.
Pts[1].Hits.empty()) {
3856 std::cout <<
"TTjH: ShowerTj T" << stj.
ID <<
" already has " << stj.
Pts[1].Hits.size()
3861 for (
auto& tjID : ss.TjIDs) {
3862 unsigned short itj = tjID - 1;
3864 std::cout <<
"TTjH: Coding error. T" << tjID <<
" is a ShowerTj but is in TjIDs\n";
3867 if (slc.
tjs[itj].SSID <= 0) {
3868 std::cout <<
"TTjH: Coding error. Trying to transfer T" << tjID
3869 <<
" hits but it isn't an InShower Tj\n";
3874 stj.
Pts[1].Hits.insert(stj.
Pts[1].Hits.end(), thits.begin(), thits.end());
3879 for (
auto& iht : stj.
Pts[1].Hits)
3891 for (
unsigned short ii = 0; ii < slc.
cots.size(); ++ii) {
3892 if (ShowerTjID == slc.
cots[ii].ShowerTjID)
return ii + 1;
3901 if (ss3.
ID == 0)
return 0;
3902 if (ss3.
Energy.empty())
return 0;
3907 ave /= ss3.
Energy.size();
3915 if (tjIDs.empty())
return 0;
3917 for (
auto tid : tjIDs) {
3918 auto& tj = slc.
tjs[tid - 1];
3938 std::string fcnLabel = inFcnLabel +
".S3S";
3940 std::cout << fcnLabel <<
" Invalid ID";
3943 if (ss3.
CotIDs.size() < 2) {
3944 std::cout << fcnLabel <<
" not enough CotIDs";
3949 for (
auto& ss : slc.
cots) {
3950 if (ss.ID == 0)
continue;
3951 if (ss.SS3ID == ss3.
ID &&
3953 std::cout << fcnLabel <<
" Bad assn: 2S" << ss.ID <<
" -> 3S" << ss3.
ID 3954 <<
" but it's not inCotIDs.\n";
3960 for (
auto cid : ss3.
CotIDs) {
3961 if (cid <= 0 || cid > (
int)slc.
cots.size())
return false;
3962 auto& ss = slc.
cots[cid - 1];
3963 if (ss.SS3ID > 0 && ss.SS3ID != ss3.
ID) {
3964 std::cout << fcnLabel <<
" Bad assn: 3S" << ss3.
ID <<
" -> 2S" << cid <<
" but 2S -> 3S" 3965 << ss.SS3ID <<
"\n";
3971 for (
auto cid : ss3.
CotIDs)
3972 slc.
cots[cid - 1].SS3ID = ss3.
ID;
3986 std::string fcnLabel = inFcnLabel +
".S2S";
3988 std::cout << fcnLabel <<
" Invalid ID";
3991 if (ss.
TjIDs.empty()) {
3992 std::cout << fcnLabel <<
" Fail: No TjIDs in 2S" << ss.
ID <<
"\n";
3997 std::cout << fcnLabel <<
" Fail: 2S" << ss.
ID <<
" has an invalid ParentID T" << ss.
ParentID 4002 std::cout << fcnLabel <<
" Fail: 2S" << ss.
ID <<
" ParentID is not in TjIDs.\n";
4008 if (ss.
ID != (
int)slc.
cots.size() + 1) {
4009 std::cout << fcnLabel <<
" Correcting the ID 2S" << ss.
ID <<
" -> 2S" << slc.
cots.size() + 1;
4010 ss.
ID = slc.
cots.size() + 1;
4014 for (
auto& tjID : ss.
TjIDs) {
4024 slc.
cots.push_back(ss);
4058 stj.
CTP = slc.
tjs[tjl[0] - 1].CTP;
4062 for (
auto& stp : stj.
Pts) {
4069 stj.
ID = slc.
tjs.size() + 1;
4073 slc.
tjs.push_back(stj);
4075 ss.
ID = slc.
cots.size() + 1;
4080 for (
auto tjid : tjl) {
4081 auto& tj = slc.
tjs[tjid - 1];
4082 if (tj.CTP != stj.
CTP) {
4099 std::string fcnLabel = inFcnLabel +
".ChkAssns";
4100 for (
auto& ss : slc.
cots) {
4101 if (ss.ID == 0)
continue;
4102 for (
auto tid : ss.TjIDs) {
4103 auto& tj = slc.
tjs[tid - 1];
4104 if (tj.SSID != ss.ID) {
4105 std::cout << fcnLabel <<
" ***** Error: 2S" << ss.ID <<
" -> TjIDs T" << tid
4106 <<
" != tj.SSID 2S" << tj.SSID <<
"\n";
4111 if (ss.SS3ID > 0 && ss.SS3ID <= (
int)slc.
showers.size()) {
4112 auto& ss3 = slc.
showers[ss.SS3ID - 1];
4113 if (std::find(ss3.CotIDs.begin(), ss3.CotIDs.end(), ss.ID) == ss3.CotIDs.end()) {
4114 std::cout << fcnLabel <<
" ***** Error: 2S" << ss.ID <<
" -> 3S" << ss.SS3ID
4115 <<
" but the shower says no\n";
4120 for (
auto& tj : slc.
tjs) {
4121 if (tj.AlgMod[
kKilled])
continue;
4123 std::cout << fcnLabel <<
" ***** Error: T" << tj.ID <<
" tj.SSID is fubar\n";
4127 if (tj.SSID == 0)
continue;
4128 auto& ss = slc.
cots[tj.SSID - 1];
4129 if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tj.ID) != ss.TjIDs.end())
continue;
4130 std::cout << fcnLabel <<
" ***** Error: T" << tj.ID <<
" tj.SSID = 2S" << tj.SSID
4131 <<
" but the shower says no\n";
4135 for (
auto& ss3 : slc.
showers) {
4136 if (ss3.ID == 0)
continue;
4137 for (
auto cid : ss3.CotIDs) {
4138 auto& ss = slc.
cots[cid - 1];
4139 if (ss.SS3ID != ss3.ID) {
4140 std::cout << fcnLabel <<
" ***** Error: 3S" << ss3.ID <<
" -> 2S" << cid
4141 <<
" but it thinks it belongs to 3S" << ss.SS3ID <<
"\n";
4151 std::string fcnLabel,
4154 if (slc.
showers.empty())
return;
4156 myprt << fcnLabel <<
" 3D showers \n";
4157 for (
auto& ss3 : slc.
showers) {
4158 myprt << fcnLabel <<
" 3S" << ss3.ID <<
" 3V" << ss3.Vx3ID;
4159 myprt <<
" parentID " << ss3.ParentID;
4160 myprt <<
" ChgPos" << std::fixed;
4161 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
4162 myprt <<
" " << std::setprecision(0) << ss3.ChgPos[xyz];
4164 for (
unsigned short xyz = 0; xyz < 3; ++xyz)
4165 myprt <<
" " << std::setprecision(2) << ss3.Dir[xyz];
4166 myprt <<
" posInPlane";
4167 std::vector<float> projInPlane(slc.
nPlanes);
4168 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
4169 CTP_t inCTP =
EncodeCTP(ss3.TPCID.Cryostat, ss3.TPCID.TPC, plane);
4170 auto tp =
MakeBareTP(detProp, ss3.ChgPos, ss3.Dir, inCTP);
4172 projInPlane[plane] = tp.Delta;
4174 myprt <<
" projInPlane";
4175 for (
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
4176 myprt <<
" " << std::fixed << std::setprecision(2) << projInPlane[plane];
4178 for (
auto cid : ss3.CotIDs) {
4179 auto& ss = slc.
cots[cid - 1];
4180 myprt <<
"\n 2S" << ss.ID;
4181 auto& stj = slc.
tjs[ss.ShowerTjID - 1];
4182 myprt <<
" ST" << stj.ID;
4183 myprt <<
" " <<
PrintPos(stj.Pts[stj.EndPt[0]].Pos) <<
" - " 4184 <<
PrintPos(stj.Pts[stj.EndPt[1]].Pos);
4186 if (ss3.NeedsUpdate) myprt <<
" *** Needs update";
4195 bool printKilledShowers)
4198 if (slc.
cots.empty())
return;
4203 bool printAllCTP = (inCTP == USHRT_MAX);
4205 unsigned short nlines = 0;
4206 for (
const auto& ss : slc.
cots) {
4207 if (!printAllCTP && ss.CTP != inCTP)
continue;
4208 if (!printKilledShowers && ss.ID == 0)
continue;
4212 myprt << someText <<
" Print2DShowers: Nothing to print";
4217 bool printHeader =
true;
4218 bool printExtras =
false;
4219 for (
unsigned short ict = 0; ict < slc.
cots.size(); ++ict) {
4220 const auto& ss = slc.
cots[ict];
4221 if (!printAllCTP && ss.CTP != inCTP)
continue;
4222 if (!printKilledShowers && ss.ID == 0)
continue;
4223 PrintShower(someText, slc, ss, printHeader, printExtras);
4224 printHeader =
false;
4227 for (
unsigned short ict = 0; ict < slc.
cots.size(); ++ict) {
4228 const auto& ss = slc.
cots[ict];
4229 if (!printAllCTP && ss.CTP != inCTP)
continue;
4230 if (!printKilledShowers && ss.ID == 0)
continue;
4231 myprt << someText << std::fixed;
4233 myprt << std::setw(5) << sid;
4235 for (
auto id : ss.TjIDs)
4236 myprt <<
" T" << id;
4240 for (
unsigned short ict = 0; ict < slc.
cots.size(); ++ict) {
4241 const auto& ss = slc.
cots[ict];
4242 if (!printAllCTP && ss.CTP != inCTP)
continue;
4243 if (!printKilledShowers && ss.ID == 0)
continue;
4244 myprt << someText << std::fixed;
4246 myprt << std::setw(5) << sid;
4247 myprt <<
" Envelope";
4248 for (
auto& vtx : ss.Envelope)
4249 myprt <<
" " << (int)vtx[0] <<
":" << (
int)(vtx[1] /
tcc.
unitsPerTick);
4253 for (
unsigned short ict = 0; ict < slc.
cots.size(); ++ict) {
4254 const auto& ss = slc.
cots[ict];
4255 if (!printAllCTP && ss.CTP != inCTP)
continue;
4256 if (!printKilledShowers && ss.ID == 0)
continue;
4257 myprt << someText << std::fixed;
4259 myprt << std::setw(5) << sid;
4261 for (
auto id : ss.NearTjIDs)
4262 myprt <<
" T" << id;
4266 myprt <<
"DontCluster";
4268 if (dc.TjIDs[0] > 0) myprt <<
" T" << dc.TjIDs[0] <<
"-T" << dc.TjIDs[1];
4270 myprt <<
"\nDontCluster";
4271 for (
unsigned short ict = 0; ict < slc.
cots.size(); ++ict) {
4272 const auto& iss = slc.
cots[ict];
4273 if (iss.ID == 0)
continue;
4274 for (
unsigned short jct = ict + 1; jct < slc.
cots.size(); ++jct) {
4275 const auto& jss = slc.
cots[jct];
4276 if (jss.ID == 0)
continue;
4277 if (
DontCluster(slc, iss.TjIDs, jss.TjIDs)) myprt <<
" 2S" << iss.ID <<
"-2S" << jss.ID;
4294 <<
" ID CTP ParID ParFOM TruParID Energy nTjs dFOM AspRat stj vx0 __Pos0___ " 4295 "Chg(k) dRMS __Pos1___ Chg(k) dRMS __Pos2___ Chg(k) dRMS Angle SS3ID PFPID\n";
4298 myprt << someText << std::fixed;
4300 myprt << std::setw(5) << sid;
4301 myprt << std::setw(6) << ss.
CTP;
4304 myprt << std::setw(7) << sid;
4305 myprt << std::setw(7) << std::setprecision(2) << ss.
ParentFOM;
4307 myprt << std::setw(7) << (int)ss.
Energy;
4308 myprt << std::setw(5) << ss.
TjIDs.size();
4309 myprt << std::setw(6) << std::setprecision(2) << ss.
DirectionFOM;
4310 myprt << std::setw(7) << std::setprecision(2) << ss.
AspectRatio;
4313 myprt << std::setw(5) << tid;
4314 std::string vid =
"NA";
4316 myprt << std::setw(5) << vid;
4317 for (
auto& spt : stj.Pts) {
4318 myprt << std::setw(10) <<
PrintPos(spt.Pos);
4319 myprt << std::setw(7) << std::fixed << std::setprecision(1) << spt.Chg / 1000;
4321 myprt << std::setw(5) << std::setprecision(1) << spt.DeltaRMS;
4323 myprt << std::setw(6) << std::setprecision(2) << stj.Pts[1].Ang;
4324 std::string sss =
"NA";
4326 myprt << std::setw(6) << sss;
4329 if (ss3.PFPIndex < slc.
pfps.size()) {
4331 myprt << std::setw(6) << pid;
4334 myprt << std::setw(6) <<
"NA";
4338 myprt << std::setw(6) <<
"NA";
4342 if (!printExtras)
return;
4345 myprt << someText << std::fixed;
4347 myprt << std::setw(5) << sid;
4349 for (
auto id : ss.
TjIDs)
4350 myprt <<
" T" << id;
4352 myprt << someText << std::fixed;
4354 myprt << std::setw(5) << sid;
4355 myprt <<
" Envelope";
4357 myprt <<
" " << (int)vtx[0] <<
":" << (
int)(vtx[1] /
tcc.
unitsPerTick);
4359 myprt << someText << std::fixed;
4361 myprt << std::setw(5) << sid;
4364 myprt <<
" T" << id;
bool AddTj(std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
bool TransferTjHits(TCSlice &slc, bool prt)
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
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< 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 InShowerProbLong(double showerEnergy, double along)
bool WrongSplitTj(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, unsigned short tjEnd, bool prt)
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
std::vector< int > NearTjIDs
std::vector< ShowerStruct3D > showers
ShowerStruct3D CreateSS3(TCSlice &slc)
std::vector< Point2_t > Envelope
void PrintShowers(detinfo::DetectorPropertiesData const &detProp, std::string fcnLabel, TCSlice const &slc)
unsigned int Nplanes() const
Number of planes in this tpc.
Declaration of signal hit object.
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.
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.
bool IsShowerLike(TCSlice const &slc, std::vector< int > const &TjIDs)
constexpr auto abs(T v)
Returns the absolute value of the argument.
bool DontCluster(TCSlice const &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
CryostatID_t Cryostat
Index of cryostat.
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)
void TagShowerLike(TCSlice &slc, const CTP_t &inCTP)
std::vector< unsigned int > lastWire
the last wire with a hit
std::array< int, 2 > Vx3ID
void PrintPFPs(std::string someText, TCSlice const &slc)
std::vector< int > CotIDs
std::string PrintPos(const TrajPoint &tp)
double InShowerProbTrans(double showerEnergy, double along, double trans)
std::vector< ShowerPoint > ShPts
bool FindShowerStart(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
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)
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)
TPCGeo const & TPC(TPCID const &tpcid=tpc_zero) const
Returns the specified TPC.
double ShowerParamTransRMS(double showerEnergy, double along)
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
void AddCloseTjsToList(TCSlice &slc, unsigned short itj, std::vector< int > list)
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Access the description of detector geometry.
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 NeutrinoPrimaryTjID(const TCSlice &slc, const Trajectory &tj)
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)
CTP_t CTP
Cryostat, TPC, Plane code.
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
float InShowerProb(TCSlice &slc, const ShowerStruct3D &ss3, const PFPStruct &pfp)
bool MergeShowerTjsAndStore(TCSlice &slc, unsigned short istj, unsigned short jstj, bool prt)
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)
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const Point3_t &pos, CTP_t inCTP)
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 valsIncreasing(const SortEntry &c1, const SortEntry &c2)
bool SetMag(Vector3_t &v1, double mag)
Definition of data types for geometry description.
bool AddPFP(std::string inFcnLabel, TCSlice &slc, int pID, ShowerStruct3D &ss3, bool doUpdate, bool prt)
unsigned short FarEnd(const PFPStruct &pfp, const Point3_t &pos)
int ID
ID that is local to one slice.
std::vector< TCSlice > slices
std::array< unsigned short, 2 > VtxID
ID of 2D vertex.
Detector simulation of raw signals on wires.
float ParentFOM(std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, ShowerStruct3D &ss3, bool prt)
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< int > GetAssns(TCSlice const &slc, std::string type1Name, int id, std::string type2Name)
std::vector< float > StartChgVec(TCSlice &slc, int cotID)
std::vector< double > EnergyErr
std::vector< double > MIPEnergyErr
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.
std::vector< double > Energy
void PrintShower(std::string someText, TCSlice const &slc, const ShowerStruct &ss, bool printHeader, bool printExtras)
geo::PlaneID DecodeCTP(CTP_t CTP)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
std::vector< recob::Hit > const * allHits
bool valsDecreasing(const SortEntry &c1, const SortEntry &c2)
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
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)
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)
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)
void PrintAllTraj(detinfo::DetectorPropertiesData const &detProp, std::string someText, TCSlice const &slc, unsigned short itj, unsigned short ipt, bool prtVtx)
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)
void Print2DShowers(std::string someText, TCSlice const &slc, CTP_t inCTP, bool printKilledShowers)
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)
bool CompleteIncompleteShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
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 StoreShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3)
bool Reconcile3D(std::string inFcnLabel, TCSlice &slc, bool parentSearchDone, bool prt)
void ReverseTraj(Trajectory &tj)