2 #include "cetlib/search_path.h" 19 cet::search_path sp(
"FW_SEARCH_PATH");
21 std::cout<<
"its not defined\n";
24 std::string fullFileSpec;
25 sp.find_file(fMVAShowerParentWeights, fullFileSpec);
26 if(fullFileSpec ==
"") {
27 std::cout<<
"ConfigureMVA: weights file "<<fMVAShowerParentWeights<<
" not found in path\n";
49 if(ss3.
ID == 0)
return false;
53 myprt<<
"Inside FSS: 3S"<<ss3.
ID<<
" ->";
54 for(
auto cid : ss3.
CotIDs) myprt<<
" 2S"<<cid;
55 myprt<<
" Vx 3V"<<ss3.
Vx3ID;
60 unsigned short useParentCID = 0;
61 float maxParentSep = 0;
62 unsigned short usePtSepCID = 0;
67 for(
auto cid : ss3.
CotIDs) {
68 auto&
ss = tjs.
cots[cid - 1];
70 auto& stj = tjs.
allTraj[
ss.ShowerTjID - 1];
73 if(chgCtrTP.Delta < 0.5)
continue;
74 auto& startTP = stj.Pts[0];
75 float sep =
PosSep(startTP.Pos, chgCtrTP.Pos);
77 if(sep > maxParentSep) {
81 }
else if(sep > maxPtSep) {
85 float costh =
DotProd(chgCtrTP.Dir, startTP.Dir);
86 if(costh < 0) dirOK =
false;
89 if(useParentCID == 0 && usePtSepCID == 0)
return false;
91 unsigned short useCID = useParentCID;
98 auto&
ss = tjs.
cots[useCID - 1];
99 auto& stj = tjs.
allTraj[
ss.ShowerTjID - 1];
104 ss3.
Start[0] = vx3.X;
105 ss3.
Start[1] = vx3.Y;
106 ss3.
Start[2] = vx3.Z;
109 auto& startTP = stj.Pts[0];
113 float sep = tjs.
WirePitch *
PosSep(startTP.Pos, stj.Pts[1].Pos) / chgCtrTP.Delta;
115 for(
unsigned short xyz = 0; xyz < 3; ++xyz) ss3.
Start[xyz] = ss3.
ChgPos[xyz] - sep * ss3.
Dir[xyz];
118 auto& endTP = stj.Pts[2];
119 float sep = tjs.
WirePitch *
PosSep(endTP.Pos, chgCtrTP.Pos) / chgCtrTP.Delta;
120 for(
unsigned short xyz = 0; xyz < 3; ++xyz) ss3.
End[xyz] = ss3.
ChgPos[xyz] + sep * ss3.
Dir[xyz];
122 auto& startTP = stj.Pts[0];
123 sep =
PosSep(startTP.Pos, endTP.Pos);
124 ss3.
OpenAngle = (endTP.DeltaRMS - startTP.DeltaRMS) / sep;
140 bool noShowers =
true;
142 if(ss3.ID == 0)
continue;
145 if(noShowers)
return;
153 if(ss3.ID == 0)
continue;
154 if(ss3.Cheat)
continue;
155 if(ss3.PFPIndex != USHRT_MAX) {
156 std::cout<<
"Finish3DShowers 3S"<<ss3.ID<<
" already has a pfp associated with it...\n";
160 showerPFP.TjIDs.resize(ss3.CotIDs.size());
161 for(
unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) {
162 unsigned short cid = ss3.CotIDs[ii];
163 if(cid == 0 || cid > tjs.
cots.size()) {
164 std::cout<<
"Finish3DShowers 3S"<<ss3.ID<<
" has an invalid cots ID"<<cid<<
"\n";
167 auto&
ss = tjs.
cots[cid - 1];
168 auto& stj = tjs.
allTraj[
ss.ShowerTjID - 1];
169 showerPFP.TjIDs[ii] = stj.ID;
171 showerPFP.PDGCode = 1111;
172 showerPFP.XYZ[0] = ss3.Start;
173 showerPFP.Dir[0] = ss3.Dir;
174 showerPFP.DirErr[0] = ss3.DirErr;
175 showerPFP.Vx3ID[0] = ss3.Vx3ID;
176 showerPFP.XYZ[1] = ss3.End;
177 showerPFP.Dir[1] = ss3.Dir;
179 for(
auto cid : ss3.CotIDs) {
180 auto&
ss = tjs.
cots[cid - 1];
182 auto& stj = tjs.
allTraj[
ss.ShowerTjID - 1];
183 showerPFP.dEdx[0][plane] = stj.dEdx[0];
184 showerPFP.dEdxErr[0][plane] = 0.3 * stj.dEdx[0];
186 ss3.PFPIndex = tjs.
pfps.size();
187 if(ss3.ParentID > 0) {
189 auto& dtrPFP = tjs.
pfps[ss3.ParentID - 1];
190 if(dtrPFP.ParentID > 0) {
192 auto& parPFP = tjs.
pfps[dtrPFP.ParentID - 1];
193 showerPFP.ParentID = parPFP.ID;
194 std::replace(parPFP.DtrIDs.begin(), parPFP.DtrIDs.end(), dtrPFP.ID, showerPFP.ID);
198 tjs.
pfps.push_back(showerPFP);
207 if(ss3.ID == 0)
continue;
208 for(
unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) {
209 unsigned short cid = ss3.CotIDs[ii];
210 auto&
ss = tjs.
cots[cid - 1];
211 for(
auto tjid :
ss.TjIDs) {
214 ss3.Hits.insert(ss3.Hits.end(), tjHits.begin(), tjHits.end());
216 for(
unsigned short end = 0;
end < 2; ++
end) {
226 auto& vx3 = tjs.
vtx3[vx2.Vx3ID - 1];
227 if(vx3.Neutrino)
continue;
235 if(!tjs.
pfps.empty()) {
236 for(
auto& pfp : tjs.
pfps) {
237 if(pfp.ID == 0)
continue;
238 if(pfp.TjIDs.empty())
continue;
239 unsigned short ndead = 0;
240 for(
auto tjid : pfp.TjIDs) {
241 auto& tj = tjs.
allTraj[tjid - 1];
242 if(tj.AlgMod[
kKilled]) ++ndead;
244 if(ndead == 0)
continue;
245 if(ndead != pfp.TjIDs.size()) {
246 std::cout<<
"Finish3DShowers: Not all Tjs in P"<<pfp.ID<<
" are killed";
247 for(
auto tid : pfp.TjIDs) {
248 auto& tj = tjs.
allTraj[tid - 1];
249 std::cout<<
" T"<<tid<<
" dead? "<<tj.AlgMod[
kKilled];
258 for(
auto& vx2 : tjs.
vtx) {
259 if(vx2.ID == 0)
continue;
260 auto vxtjs =
GetAssns(tjs,
"2V", vx2.ID,
"T");
261 if(vxtjs.empty()) vx2.ID = 0;
265 for(
auto& vx3 : tjs.
vtx3) {
266 if(vx3.ID == 0)
continue;
267 auto vxtjs =
GetAssns(tjs,
"3V", vx3.ID,
"T");
275 for(
auto& pfp : tjs.
pfps) {
276 if(pfp.ID == 0)
continue;
277 if(pfp.PDGCode != 1111)
continue;
278 if(pfp.Vx3ID[0] > 0 && tjs.
vtx3[pfp.Vx3ID[0] - 1].ID == 0) {
279 std::cout<<
"Finish3DShowers shower P"<<pfp.ID<<
" has Vx3ID[0] = "<<pfp.Vx3ID[0]<<
" but the vertex is killed\n";
292 if(!reconstruct)
return false;
296 short dbgPlane = ((int)tjs.
ShowerTag[12] % 10);
297 CTP_t dbgCTP = UINT_MAX;
300 std::string fcnLabel =
"FS";
304 for(
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane) {
306 for(
auto&
ss : tjs.
cots)
if(
ss.CTP == inCTP)
return false;
322 std::vector<std::vector<std::vector<int>>> bigList(tjs.
NumPlanes);
323 for(
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane) {
325 std::vector<std::vector<int>> tjList;
327 FindCots(fcnLabel, tjs, inCTP, tjList, prt);
329 if(tjList.empty())
continue;
330 bigList[plane] = tjList;
332 unsigned short nPlanesWithShowers = 0;
333 for(
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane)
if(!bigList.empty()) ++nPlanesWithShowers;
334 if(nPlanesWithShowers < 2)
return false;
335 for(
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane) {
338 prt = (inCTP == dbgCTP);
340 for(
auto& tjl : bigList[plane]) {
341 if(tjl.empty())
continue;
344 myprt<<
"Plane "<<plane<<
" tjList";
345 for(
auto& tjID : tjl) myprt<<
" "<<tjID;
348 if(
ss.ID == 0)
continue;
354 std::cout<<fcnLabel<<
" StoreShower failed 2S"<<
ss.ID<<
"\n";
360 if(inCTP == UINT_MAX)
continue;
361 if(tjs.
cots.empty())
continue;
362 prt = (inCTP == dbgCTP || dbgPlane == 3);
378 bool tryMerge =
false;
379 for(
unsigned short ii = 0; ii < tjs.
cots.size(); ++ii) {
381 if(
ss.ID == 0)
continue;
382 if(
ss.CTP != inCTP)
continue;
390 if(tjs.
cots.empty())
return false;
391 prt = (dbgPlane > 2);
401 if(ss3.ID == 0)
continue;
402 if(ss3.TPCID != tpcid)
continue;
412 if(ss3.ID == 0)
continue;
413 if(ss3.TPCID != tpcid)
continue;
419 for(
auto&
ss : tjs.
cots) {
420 if(
ss.ID == 0)
continue;
421 if(
ss.SS3ID > 0)
continue;
422 bool killMe = (
ss.TjIDs.size() == 1 ||
ss.Energy < tjs.
ShowerTag[3]);
424 if(
ss.AspectRatio < tjs.
ShowerTag[10]) killMe =
true;
428 unsigned short nNewShowers = 0;
429 for(
auto&
ss : tjs.
cots) {
430 if(
ss.ID == 0)
continue;
431 if(
ss.TjIDs.empty())
continue;
434 if(planeID.
TPC != tpcid.
TPC)
continue;
443 for(
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane) {
445 int truElectronTID = mcpu.PrimaryElectronTjID(inCTP);
446 std::cout<<
"Plane "<<plane<<
" trueElectron T"<<truElectronTID;
447 for(
auto&
ss : tjs.
cots) {
448 if(
ss.ID == 0)
continue;
449 if(
ss.CTP != inCTP)
continue;
450 if(std::find(
ss.TjIDs.begin(),
ss.TjIDs.end(), truElectronTID) ==
ss.TjIDs.end())
continue;
451 std::cout<<
" in 2S"<<
ss.ID<<
" with Parent T"<<
ss.ParentID;
452 if(
ss.SS3ID > 0) std::cout<<
" -> 3S"<<
ss.SS3ID;
459 if(mcpu.PrimaryElectronStart(truStart, truDir, truE)) {
465 if(energy < big)
continue;
470 auto& ss3 = tjs.
showers[imBig - 1];
471 float shMaxSep =
PosSep(truStart, ss3.ChgPos);
472 float dang = acos(
DotProd(truDir, ss3.Dir));
474 std::cout<<
"Big 3S"<<ss3.ID<<
" E "<<(int)energy<<
" truE "<<(
int)truE;
475 std::cout<<
" truStart "<<std::fixed<<std::setprecision(1)<<truStart[0]<<
" "<<truStart[1]<<
" "<<truStart[2];
476 std::cout<<
" tru P"<<mcpu.PrimaryElectronPFPID(tpcid);
477 std::cout<<
" rec P"<<ss3.ParentID;
478 std::cout<<
" shMax "<<(int)shMaxSep<<
" cm.";
479 std::cout<<
" dang "<<std::fixed<<std::setprecision(2)<<dang<<
"\n";
486 return (nNewShowers > 0);
495 std::string fcnLabel = inFcnLabel +
".R3D2";
501 for(
unsigned short ii = 0; ii < tjs.
showers.size() - 1; ++ii) {
503 if(iss3.ID == 0)
continue;
504 if(iss3.TPCID != tpcid)
continue;
505 auto iPInSS3 =
GetAssns(tjs,
"3S", iss3.ID,
"P");
508 myprt<<fcnLabel<<
" 3S"<<iss3.ID<<
" ->";
509 for(
auto pid : iPInSS3) myprt<<
" P"<<
pid;
511 for(
unsigned short jj = ii + 1; jj < tjs.
showers.size(); ++jj) {
513 if(jss3.ID == 0)
continue;
514 auto jPInSS3 =
GetAssns(tjs,
"3S", jss3.ID,
"P");
516 if(shared.empty())
continue;
519 myprt<<fcnLabel<<
" Conflict i3S"<<iss3.ID<<
" and j3S"<<jss3.ID<<
" share";
520 for(
auto pid : shared) myprt<<
" P"<<
pid;
523 for(
auto pid : shared) {
527 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" i3S"<<iss3.ID<<
" prob "<<std::setprecision(3)<<iProb<<
" j3S"<<jss3.ID<<
" prob "<<jProb;
530 RemovePFP(fcnLabel, tjs, pfp, jss3,
true, prt);
532 AddPFP(fcnLabel, tjs, pfp.ID, iss3,
true, prt);
534 RemovePFP(fcnLabel, tjs, pfp, iss3,
true, prt);
535 AddPFP(fcnLabel, tjs, pfp.ID, jss3,
true, prt);
544 if(parentSearchDone) {
546 if(ss3.ID == 0)
continue;
547 if(ss3.TPCID != tpcid)
continue;
548 auto PIn3S =
GetAssns(tjs,
"3S", ss3.ID,
"P");
549 for(
auto pid : PIn3S) {
550 if(
pid == ss3.ParentID)
continue;
552 for(
unsigned short end = 0;
end < 2; ++
end) {
553 if(pfp.Vx3ID[
end] <= 0)
continue;
556 myprt<<fcnLabel<<
" Detach 3S"<<ss3.ID<<
" -> P"<<pfp.ID<<
"_"<<
end<<
" -> 3V"<<pfp.Vx3ID[
end];
557 if(pfp.ParentID > 0) myprt<<
" ->Parent P"<<pfp.ParentID;
561 if(pfp.ParentID > 0) {
562 auto& parentPFP = tjs.
pfps[pfp.ParentID - 1];
563 std::vector<int> newDtrIDs;
564 for(
auto did : parentPFP.DtrIDs)
if(did != pfp.ID) newDtrIDs.push_back(did);
565 parentPFP.DtrIDs = newDtrIDs;
572 unsigned int cstat = tpcid.
Cryostat;
573 unsigned int tpc = tpcid.
TPC;
576 for(
auto&
ss : tjs.
cots) {
577 if(
ss.ID == 0)
continue;
578 if(
ss.SS3ID > 0)
continue;
581 std::vector<int> matchedTjs;
582 for(
auto tid :
ss.TjIDs)
if(tjs.
allTraj[tid - 1].AlgMod[
kMat3D]) matchedTjs.push_back(tid);
583 if(matchedTjs.empty())
continue;
587 bool isCompatible =
true;
588 for(
auto tid : matchedTjs) {
589 auto TInP =
GetAssns(tjs,
"T", tid,
"P");
590 if(TInP.empty())
continue;
593 auto PIn3S =
GetAssns(tjs,
"P", TInP[0],
"3S");
594 for(
auto sid : PIn3S) {
596 auto& ss3 = tjs.
showers[sid - 1];
598 if(mergeWith3S == 0) mergeWith3S = sid;
599 if(mergeWith3S > 0 && mergeWith3S != sid) isCompatible =
false;
604 myprt<<fcnLabel<<
" 2S"<<
ss.ID<<
" is not 3D-matched but has 3D-matched Tjs:";
605 for(
auto tid : matchedTjs) {
607 auto TInP =
GetAssns(tjs,
"T", tid,
"P");
609 myprt<<
"->P"<<TInP[0];
613 if(mergeWith3S == 0 &&
ss.Energy < 50) {
616 }
else if(mergeWith3S > 0 && isCompatible) {
617 auto& ss3 = tjs.
showers[mergeWith3S - 1];
618 for(
auto cid : ss3.CotIDs) {
619 auto& oss = tjs.
cots[cid - 1];
620 if(oss.CTP !=
ss.CTP)
continue;
622 std::cout<<fcnLabel<<
" Merge failed\n";
625 std::cout<<fcnLabel<<
" UpdateShower failed\n";
627 ss3.NeedsUpdate =
true;
629 std::cout<<fcnLabel<<
" UpdateShower failed\n";
648 if(ss3.
ID == 0)
return false;
650 if(ss3.
CotIDs.size() < 3)
return true;
651 std::string fcnLabel = inFcnLabel +
".R3D";
657 std::vector<ShowerStruct> oldSS(ss3.
CotIDs.size());
658 for(
unsigned short ii = 0; ii < ss3.
CotIDs.size(); ++ii) {
662 std::vector<std::vector<int>> plist(ss3.
CotIDs.size());
663 for(
unsigned short ci = 0; ci < ss3.
CotIDs.size(); ++ci) {
665 for(
auto tid :
ss.TjIDs) {
666 auto tToP =
GetAssns(tjs,
"T", tid,
"P");
667 if(tToP.empty())
continue;
670 if(std::find(plist[ci].
begin(), plist[ci].
end(), pid) == plist[ci].end()) plist[ci].push_back(pid);
674 std::vector<std::array<int, 2>> p_cnt;
675 for(
auto& pl : plist) {
677 unsigned short indx = 0;
678 for(indx = 0; indx < p_cnt.size(); ++indx)
if(p_cnt[indx][0] ==
pid)
break;
679 if(indx == p_cnt.size()) {
681 p_cnt.push_back(std::array<int,2> {{
pid, 1}});
689 myprt<<fcnLabel<<
" 3S"<<ss3.
ID<<
"\n";
690 for(
unsigned short ci = 0; ci < ss3.
CotIDs.size(); ++ci) {
691 myprt<<
" -> 2S"<<ss3.
CotIDs[ci]<<
" ->";
692 for(
auto pid : plist[ci]) myprt<<
" P"<<
pid;
695 myprt<<
" P<ID>_count:";
696 for(
auto& pc : p_cnt) myprt<<
" P"<<pc[0]<<
"_"<<pc[1];
699 for(
auto& pc : p_cnt) {
701 if(pc[1] == (
int)ss3.
CotIDs.size())
continue;
704 auto& pfp = tjs.
pfps[pc[0] - 1];
705 if(pfp.TjIDs.size() > 2) {
707 auto PIn2S =
GetAssns(tjs,
"P", pfp.ID,
"2S");
711 if(!sDiff.empty() && std::find(ss3.
CotIDs.begin(), ss3.
CotIDs.end(), sDiff[0]) == ss3.
CotIDs.end())
continue;
714 myprt<<fcnLabel<<
" 3S"<<ss3.
ID<<
" P"<<pfp.ID<<
" ->";
715 for(
auto sid : PIn2S) myprt<<
" 2S"<<sid;
717 for(
auto sid : sDiff) myprt<<
" 2S"<<sid;
720 if(
AddPFP(fcnLabel, tjs, pfp.ID, ss3,
true, prt)) {
723 if(ss3.
CotIDs.size() != oldSS.size()) {
724 std::cout<<fcnLabel<<
" Major failure...";
727 for(
unsigned short ii = 0; ii < ss3.
CotIDs.size(); ++ii) oldSS[ii] = tjs.
cots[ss3.
CotIDs[ii] - 1];
731 for(
unsigned short ii = 0; ii < oldSS.size(); ++ii) {
732 auto&
ss = oldSS[ii];
739 auto& pfp = tjs.
pfps[pc[0] - 1];
740 unsigned short nearEnd = 1 -
FarEnd(tjs, pfp, ss3.
ChgPos);
745 myprt<<fcnLabel<<
" one occurrence: P"<<pfp.ID<<
"_"<<nearEnd<<
" closest to ChgPos";
746 myprt<<
" ChgPos "<<std::fixed<<std::setprecision(1)<<ss3.
ChgPos[0]<<
" "<<ss3.
ChgPos[1]<<
" "<<ss3.
ChgPos[2];
748 myprt<<
" InShowerProb "<<prob;
750 if(sep < 30 && prob > 0.3 &&
AddPFP(fcnLabel, tjs, pfp.ID, ss3,
true, prt)) {
752 }
else if(!
RemovePFP(fcnLabel, tjs, pfp, ss3,
true, prt)) {
753 std::cout<<
"RemovePFP failed \n";
758 if(!
UpdateShower(fcnLabel, tjs, ss3, prt))
return false;
770 if(ss.
ID == 0)
return;
772 std::string fcnLabel = inFcnLabel +
".KVIS";
774 for(
auto& vx2 : tjs.
vtx) {
775 if(vx2.ID == 0)
continue;
776 if(vx2.CTP != ss.
CTP)
continue;
778 if(vx2.Vx3ID > 0 && tjs.
vtx3[vx2.Vx3ID - 1].Neutrino)
continue;
780 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Clobber 2V"<<vx2.ID<<
" -> 3V"<<vx2.Vx3ID<<
" inside 2S"<<ss.
ID;
783 if(dc.TjIDs[0] == 0)
continue;
784 if(dc.Vx2ID != vx2.ID)
continue;
785 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Remove T"<<dc.TjIDs[0]<<
"-T"<<dc.TjIDs[0]<<
" in dontCluster";
790 auto TIn3V =
GetAssns(tjs,
"3V", vx2.Vx3ID,
"T");
792 auto& vx3 = tjs.
vtx3[vx2.Vx3ID - 1];
795 auto TIn2V =
GetAssns(tjs,
"2V", vx2.ID,
"T");
810 if(ss3.
CotIDs.size() != 2)
return false;
814 std::string fcnLabel = inFcnLabel +
".CIS";
820 std::vector<int> iplist;
821 for(
auto tid : iss.TjIDs) {
822 auto plist =
GetAssns(tjs,
"T", tid,
"P");
823 if(!plist.empty()) iplist.insert(iplist.end(), plist.begin(), plist.end());
825 std::vector<int> jplist;
826 for(
auto tid : jss.TjIDs) {
827 auto plist =
GetAssns(tjs,
"T", tid,
"P");
828 if(!plist.empty()) jplist.insert(jplist.end(), plist.begin(), plist.end());
832 if(shared.empty())
return false;
834 std::vector<int> flat = iss.TjIDs;
835 flat.insert(flat.end(), jss.TjIDs.begin(), jss.TjIDs.end());
838 std::vector<int> ktlist;
839 for(
auto pid : shared) {
841 for(
auto tid : pfp.TjIDs) {
843 if(std::find(flat.begin(), flat.end(), tid) != flat.end())
continue;
844 if(std::find(ktlist.begin(), ktlist.end(), tid) == ktlist.end()) ktlist.push_back(tid);
846 auto& tj = tjs.
allTraj[tid - 1];
847 for(
unsigned short end = 0;
end < 2; ++
end) {
848 if(tj.VtxID[
end] <= 0)
continue;
849 auto& vx2 = tjs.
vtx[tj.VtxID[
end] - 1];
850 auto TIn2V =
GetAssns(tjs,
"2V", vx2.ID,
"T");
851 for(
auto vtid : TIn2V) {
852 if(std::find(ktlist.begin(), ktlist.end(), vtid) == ktlist.end()) ktlist.push_back(vtid);
857 if(ktlist.empty())
return false;
859 std::vector<int> ksslist;
860 for(
auto tid : ktlist) {
861 auto& tj = tjs.
allTraj[tid - 1];
862 if(tj.SSID == 0)
continue;
864 auto&
ss = tjs.
cots[tj.SSID - 1];
866 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Found existing T"<<tid<<
" -> 2S"<<
ss.ID<<
" -> 3S"<<
ss.SS3ID<<
" assn. Give up";
869 if(std::find(ksslist.begin(), ksslist.end(),
ss.ID) == ksslist.end()) ksslist.push_back(
ss.ID);
875 myprt<<fcnLabel<<
" 3S"<<ss3.
ID<<
"\n";
876 myprt<<
" -> i2S"<<iss.ID<<
" ->";
877 for(
auto pid : iplist) myprt<<
" P"<<
pid;
879 myprt<<
" -> j2S"<<jss.ID<<
" ->";
880 for(
auto pid : jplist) myprt<<
" P"<<pid;
884 unsigned short kplane = 3 - iPlaneID.
Plane - jPlaneID.
Plane;
885 myprt<<
" kplane "<<kplane<<
" ktlist:";
886 for(
auto tid : ktlist) myprt<<
" T"<<tid;
887 myprt<<
" ktlistEnergy "<<ktlistEnergy;
888 if(ksslist.empty()) {
889 myprt<<
"\n No matching showers in kplane";
892 myprt<<
" Candidate showers:";
893 for(
auto ssid : ksslist) {
895 auto& sst = tjs.
cots[ssid - 1];
896 if(sst.SS3ID > 0) myprt<<
"_3S"<<sst.SS3ID;
900 if(ksslist.size() > 1) {
901 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Found more than 1 shower. Need some better code here";
905 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" ktlistEnergy exceeds 2 * ss3 energy. Need some better code here";
909 if(ksslist.empty()) {
911 auto kss =
CreateSS(tjs, 0, ktlist);
912 if(kss.ID == 0)
return false;
914 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" create new 2S"<<kss.ID<<
" from ktlist";
916 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" UpdateShower failed 2S"<<kss.ID;
925 ss3.
CotIDs.push_back(kss.ID);
926 auto& stj = tjs.
allTraj[kss.ShowerTjID - 1];
933 auto&
ss = tjs.
cots[ksslist[0] - 1];
937 auto& stj = tjs.
allTraj[
ss.ShowerTjID - 1];
951 std::string fcnLabel = inFcnLabel +
".M2DS";
960 std::vector<SortEntry> sortVec;
961 for(
unsigned short indx = 0; indx < tjs.
cots.size(); ++indx) {
962 auto&
ss = tjs.
cots[indx];
963 if(
ss.ID == 0)
continue;
965 if(
ss.SS3ID > 0)
continue;
966 if(
ss.TjIDs.empty())
continue;
969 if(planeID.
TPC != tpcid.
TPC)
continue;
972 se.length =
ss.Energy /
ss.AspectRatio;
973 sortVec.push_back(se);
975 if(sortVec.size() < 2)
return;
976 std::sort(sortVec.begin(), sortVec.end(),
greaterThan);
979 for(
unsigned short ii = 0; ii < sortVec.size() - 1; ++ii) {
980 unsigned short iIndx = sortVec[ii].index;
981 auto& iss = tjs.
cots[iIndx];
983 if(iss.SS3ID > 0)
continue;
986 for(
unsigned short jj = 0; jj < sortVec.size(); ++jj) {
987 if(iss.SS3ID > 0)
break;
988 unsigned short jIndx = sortVec[jj].index;
991 if(iss.SS3ID > 0)
break;
992 if(jss.
SS3ID > 0)
continue;
993 if(jss.
CTP == iss.CTP)
continue;
996 if(!
MakeTp3(tjs, istj.
Pts[1], jstj.
Pts[1], tp3,
true))
continue;
997 float fomij =
Match3DFOM(fcnLabel, tjs, iss.ID, jss.
ID, prt);
998 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" i2S"<<iss.ID<<
" j2S"<<jss.
ID<<
" fomij "<<fomij<<
" fomCut "<<fomCut;
999 if(fomij > fomCut)
continue;
1009 ss3.
Energy[0] = iss.Energy;
1014 if(prt)
mf::LogVerbatim(
"TC")<<
" new 2-plane TPC 3S"<<ss3.
ID<<
" with fomij "<<fomij;
1017 float bestFOM = fomCut;
1018 unsigned short bestck = USHRT_MAX;
1019 for(
unsigned short ck = 0; ck < tjs.
cots.size(); ++ck) {
1021 if(kss.
ID == iss.ID || kss.
ID == jss.
ID)
continue;
1022 if(kss.
CTP == iss.CTP || kss.
CTP == jss.
CTP)
continue;
1023 if(kss.
ID == 0)
continue;
1024 if(kss.
TjIDs.empty())
continue;
1025 if(kss.
SS3ID > 0)
continue;
1028 if(kplaneID.
TPC != tpcid.
TPC)
continue;
1032 float fomik =
Match3DFOM(fcnLabel, tjs, iss.ID, kss.
ID, prt);
1033 if(fomik > bestFOM)
continue;
1036 if(prt)
mf::LogVerbatim(
"TC")<<
" 2S"<<iss.ID<<
" 2S"<<jss.
ID<<
" 2S"<<kss.
ID<<
" Large stp[1] point separation "<<(int)sep;
1048 if(bestck == USHRT_MAX) {
1055 if(prt)
mf::LogVerbatim(
"TC")<<
" new 2-plane 3S"<<ss3.
ID<<
" using 2S"<<iss.ID<<
" 2S"<<jss.
ID<<
" with FOM "<<ss3.
MatchFOM<<
" try to complete it";
1062 unsigned short ck = bestck;
1072 tjs.
cots[ck].SS3ID = ss3.
ID;
1075 ss3.
MatchFOM = 0.5 * (fomij + bestFOM);
1085 if(nss3.NeedsUpdate)
UpdateShower(fcnLabel, tjs, nss3, prt);
1091 if(nss3.NeedsUpdate)
UpdateShower(fcnLabel, tjs, nss3, prt);
1113 if(ss.
ID == 0)
return false;
1114 if(!ss.
Cheat && ss.
TjIDs.empty())
return false;
1118 if(stj.Pts.size() != 3)
return false;
1120 std::string fcnLabel = inFcnLabel +
".U2S";
1135 for(
auto& stp : stj.Pts) {
1137 stp.Pos = {{0.0, 0.0}};
1139 stp.HitPos = {{0.0, 0.0}};
1141 stp.Dir = {{0.0, 0.0}};
1152 for(
auto tjid : ss.
TjIDs) {
1153 if(tjid <= 0 || tjid > (
int)tjs.
allTraj.size())
return false;
1154 auto& tj = tjs.
allTraj[tjid - 1];
1155 if(tj.CTP != ss.
CTP)
return false;
1157 for(
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1159 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1160 if(!tp.
UseHit[ii])
continue;
1161 unsigned int iht = tp.
Hits[ii];
1162 if(tjs.
fHits[iht].Integral <= 0)
continue;
1166 shpt.
Chg = tjs.
fHits[iht].Integral;
1167 shpt.
Pos[0] = tjs.
fHits[iht].ArtPtr->WireID().Wire;
1169 ss.
ShPts.push_back(shpt);
1176 if(ss.
ShPts.size() < 3)
return false;
1179 auto& stp1 = stj.Pts[1];
1180 for(
auto& shpt : ss.
ShPts) {
1181 stp1.Pos[0] += shpt.Chg * shpt.Pos[0];
1182 stp1.Pos[1] += shpt.Chg * shpt.Pos[1];
1183 stj.TotChg += shpt.Chg;
1185 if(stj.TotChg <= 0)
return false;
1186 stp1.Pos[0] /= stj.TotChg;
1187 stp1.Pos[1] /= stj.TotChg;
1196 unsigned short pend =
FarEnd(tjs, ptj, stp1.Pos);
1197 auto& ptp = ptj.Pts[ptj.EndPt[pend]];
1199 stp1.Ang = atan2(stp1.Dir[1], stp1.Dir[0]);
1208 for(
auto& shpt : ss.
ShPts) {
1210 double xx = shpt.Pos[0] - stp1.Pos[0];
1211 double yy = shpt.Pos[1] - stp1.Pos[1];
1212 sumx += shpt.Chg *
xx;
1213 sumy += shpt.Chg * yy;
1214 sumxy += shpt.Chg * xx * yy;
1215 sumx2 += shpt.Chg * xx *
xx;
1216 sumy2 += shpt.Chg * yy * yy;
1218 double delta = sum * sumx2 - sumx * sumx;
1219 if(delta == 0)
return false;
1223 double B = (sumxy * sum - sumx * sumy) / delta;
1225 stp1.Dir[0] = cos(stp1.Ang);
1226 stp1.Dir[1] = sin(stp1.Ang);
1230 ss.
Angle = stp1.Ang;
1231 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 2S"<<ss.
ID<<
" dir "<<std::fixed<<std::setprecision(2)<<stp1.Dir[0]<<
" "<<stp1.Dir[1]<<
" Angle "<<stp1.Ang;
1232 for(
unsigned short ipt = 0; ipt < 3; ++ipt) {
1233 if(ipt == 1)
continue;
1234 stj.Pts[ipt].Dir = stp1.Dir;
1235 stj.Pts[ipt].Ang = stp1.Ang;
1239 std::vector<SortEntry> sortVec(ss.
ShPts.size());
1240 unsigned short indx = 0;
1241 double cs = cos(-stp1.Ang);
1242 double sn = sin(-stp1.Ang);
1243 for(
auto& shpt : ss.
ShPts) {
1244 double xx = shpt.Pos[0] - stp1.Pos[0];
1245 double yy = shpt.Pos[1] - stp1.Pos[1];
1246 shpt.RotPos[0] = cs * xx - sn * yy;
1247 shpt.RotPos[1] = sn * xx + cs * yy;
1248 sortVec[indx].index = indx;
1249 sortVec[indx].length = shpt.RotPos[0];
1252 std::sort(sortVec.begin(), sortVec.end(),
lessThan);
1254 auto tPts = ss.
ShPts;
1255 for(
unsigned short ii = 0; ii < ss.
ShPts.size(); ++ii) ss.
ShPts[ii] = tPts[sortVec[ii].index];
1259 for(
auto& shpt :
ss.ShPts) {
1260 alongTrans[0] += shpt.Chg * std::abs(shpt.RotPos[0]);
1261 alongTrans[1] += shpt.Chg * std::abs(shpt.RotPos[1]);
1263 alongTrans[0] /= stj.TotChg;
1264 alongTrans[1] /= stj.TotChg;
1265 if(alongTrans[1] == 0)
return false;
1266 ss.AspectRatio = alongTrans[1] / alongTrans[0];
1273 if(
ss.ParentID > 0) {
1276 auto& ptj = tjs.allTraj[
ss.ParentID - 1];
1278 unsigned short pend =
FarEnd(tjs, ptj, stp1.Pos);
1279 auto& ptp = ptj.Pts[ptj.EndPt[pend]];
1280 auto& firstShPt =
ss.ShPts[0];
1281 auto& lastShPt =
ss.ShPts[
ss.ShPts.size() - 1];
1283 stj.Pts[0].Pos = ptp.Pos;
1286 if(stj.Pts[2].DeltaRMS < stj.Pts[0].DeltaRMS)
ReverseShower(fcnLabel, tjs,
ss, prt);
1287 stj.Pts[0].Pos =
ss.ShPts[0].Pos;
1290 if(stj.Pts[2].DeltaRMS > 0)
ss.DirectionFOM = stj.Pts[0].DeltaRMS / stj.Pts[2].DeltaRMS;
1292 stj.Pts[2].Pos =
ss.ShPts[
ss.ShPts.size() - 1].Pos;
1295 ss.NeedsUpdate =
false;
1307 if(ss3.
ID == 0)
return false;
1308 if(ss3.
CotIDs.size() < 2)
return false;
1310 std::string fcnLabel = inFcnLabel +
".U3S";
1313 for(
auto cid : ss3.
CotIDs) {
1314 auto&
ss = tjs.
cots[cid - 1];
1315 if(
ss.NeedsUpdate && prt) std::cout<<fcnLabel<<
" ********* 3S"<<ss3.
ID<<
" 2S"<<
ss.ID<<
" needs an update...\n";
1323 if(pfp.Vx3ID[pend] != ss3.
Vx3ID) {
1324 if(prt) std::cout<<fcnLabel<<
" ********* 3S"<<ss3.
ID<<
" has parent P"<<ss3.
ParentID<<
" with a vertex that is not attached the shower\n";
1329 std::array<Point3_t, 3> pos;
1332 std::array<double, 3> chg;
1333 for(
unsigned short ipt = 0; ipt < 3; ++ipt) {
1335 for(
unsigned short xyz = 0; xyz < 3; ++xyz) {
1341 for(
unsigned short ii = 0; ii < ss3.
CotIDs.size() - 1; ++ii) {
1342 unsigned short ciid = ss3.
CotIDs[ii];
1343 auto& iss = tjs.
cots[ciid - 1];
1345 auto istj = tjs.
allTraj[iss.ShowerTjID - 1];
1346 for(
auto& tp : istj.Pts) tp.Pos = tp.HitPos;
1347 for(
unsigned short jj = ii + 1; jj < ss3.
CotIDs.size(); ++jj) {
1348 unsigned short cjid = ss3.
CotIDs[jj];
1349 auto& jss = tjs.
cots[cjid - 1];
1350 auto jstj = tjs.
allTraj[jss.ShowerTjID - 1];
1351 for(
auto& tp : jstj.Pts) tp.Pos = tp.HitPos;
1353 for(
unsigned short ipt = 0; ipt < 3; ++ipt) {
1354 if(!
MakeTp3(tjs, istj.Pts[ipt], jstj.Pts[ipt], tp3,
true))
continue;
1355 double ptchg = 0.5 * (istj.Pts[ipt].Chg + jstj.Pts[ipt].Chg);
1357 for(
unsigned short xyz = 0; xyz < 3; ++xyz) {
1358 pos[ipt][xyz] += ptchg * tp3.
Pos[xyz];
1359 dir[xyz] += ptchg * tp3.
Dir[xyz];
1365 unsigned short nok = 0;
1366 for(
unsigned short ipt = 0; ipt < 3; ++ipt) {
1367 if(chg[ipt] == 0)
continue;
1368 for(
unsigned short xyz = 0; xyz < 3; ++xyz) pos[ipt][xyz] /= chg[ipt];
1384 ss3.
Start = pfp.XYZ[pend];
1396 for(
auto cid : ss3.
CotIDs) {
1397 auto&
ss = tjs.
cots[cid - 1];
1398 auto& stj = tjs.
allTraj[
ss.ShowerTjID - 1];
1406 ss3.
dEdx[plane] = stj.dEdx[0];
1407 ss3.
dEdxErr[plane] = 0.3 * stj.dEdx[0];
1421 for(
unsigned short ii = 0; ii < ss3.
CotIDs.size() - 1; ++ii) {
1422 unsigned short icid = ss3.
CotIDs[ii];
1423 for(
unsigned short jj = ii + 1; jj < ss3.
CotIDs.size(); ++jj) {
1424 unsigned short jcid = ss3.
CotIDs[jj];
1425 fom +=
Match3DFOM(inFcnLabel, tjs, icid, jcid, prt);
1429 if(cnt == 0)
return 100;
1435 int icid,
int jcid,
int kcid,
bool prt)
1437 if(icid == 0 || icid > (
int)tjs.
cots.size())
return 100;
1438 if(jcid == 0 || jcid > (
int)tjs.
cots.size())
return 100;
1439 if(kcid == 0 || kcid > (
int)tjs.
cots.size())
return 100;
1441 float ijfom =
Match3DFOM(inFcnLabel, tjs, icid, jcid, prt);
1442 float jkfom =
Match3DFOM(inFcnLabel, tjs, jcid, kcid, prt);
1444 return 0.5 * (ijfom + jkfom);
1452 if(icid == 0 || icid > (
int)tjs.
cots.size())
return 100;
1453 if(jcid == 0 || jcid > (
int)tjs.
cots.size())
return 100;
1455 auto& iss = tjs.
cots[icid - 1];
1456 auto& istj = tjs.
allTraj[iss.ShowerTjID - 1];
1457 auto& jss = tjs.
cots[jcid - 1];
1458 auto& jstj = tjs.
allTraj[jss.ShowerTjID - 1];
1460 if(iss.CTP == jss.CTP)
return 100;
1462 std::string fcnLabel = inFcnLabel +
".MFOM";
1464 float energyAsym = std::abs(iss.Energy - jss.Energy) / (iss.Energy + jss.Energy);
1467 if((iss.Energy > 200 || jss.Energy > 200) && energyAsym > 0.5)
return 50;
1475 float pos1fom = std::abs(ix - jx) / 10;
1477 float mfom = energyAsym * pos1fom;
1481 myprt<<fcnLabel<<
" i2S"<<iss.ID<<
" j2S"<<jss.ID;
1482 myprt<<std::fixed<<std::setprecision(2);
1484 myprt<<
" pos1fom "<<pos1fom;
1486 myprt<<
" energyAsym "<<energyAsym;
1487 myprt<<
" mfom "<<mfom;
1498 if(tjList.size() < 2)
return;
1500 bool didMerge =
true;
1503 for(
unsigned short itl = 0; itl < tjList.size() - 1; ++itl) {
1504 if(tjList[itl].empty())
continue;
1505 for(
unsigned short jtl = itl + 1; jtl < tjList.size(); ++jtl) {
1506 if(tjList[itl].empty())
continue;
1507 auto& itList = tjList[itl];
1508 auto& jtList = tjList[jtl];
1510 bool jtjInItjList =
false;
1511 for(
auto& jtj : jtList) {
1512 if(std::find(itList.begin(), itList.end(), jtj) != itList.end()) {
1513 jtjInItjList =
true;
1516 if(jtjInItjList)
break;
1520 itList.insert(itList.end(), jtList.begin(), jtList.end());
1530 unsigned short imEmpty = 0;
1531 while(imEmpty < tjList.size()) {
1532 for(imEmpty = 0; imEmpty < tjList.size(); ++imEmpty)
if(tjList[imEmpty].empty())
break;
1533 if(imEmpty < tjList.size()) tjList.erase(tjList.begin() + imEmpty);
1537 for(
auto& tjl : tjList) {
1538 std::sort(tjl.begin(), tjl.end());
1539 auto last = std::unique(tjl.begin(), tjl.end());
1540 tjl.erase(last, tjl.end());
1552 if(pfp.
ID == 0 || ss3.
ID == 0)
return false;
1554 std::string fcnLabel = inFcnLabel +
".RemP";
1555 for(
auto tid : pfp.
TjIDs) {
1556 for(
auto cid : ss3.
CotIDs) {
1557 auto&
ss = tjs.
cots[cid - 1];
1558 if(std::find(
ss.TjIDs.begin(),
ss.TjIDs.end(), tid) ==
ss.TjIDs.end())
continue;
1559 if(!
RemoveTj(fcnLabel, tjs, tid,
ss, doUpdate, prt))
return false;
1576 std::string fcnLabel = inFcnLabel +
".AddP";
1578 if(pID <= 0 || pID > (
int)tjs.
pfps.size())
return false;
1579 auto& pfp = tjs.
pfps[pID - 1];
1581 if(pfp.TPCID != ss3.
TPCID) {
1582 mf::LogVerbatim(
"TC")<<fcnLabel<<
" P"<<pID<<
" is in the wrong TPC for 3S"<<ss3.
ID;
1586 for(
auto tid : pfp.TjIDs) {
1587 auto& tj = tjs.
allTraj[tid - 1];
1590 auto&
ss = tjs.
cots[tj.SSID - 1];
1591 if(
ss.SS3ID > 0 &&
ss.SS3ID != ss3.
ID) {
1592 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Conflict: 3S"<<ss3.
ID<<
" adding P"<<pfp.ID<<
" -> T"<<tid<<
" is in 2S"<<tj.SSID<<
" that is in 3S"<<
ss.SS3ID<<
" that is not this shower";
1596 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" adding P"<<pfp.ID<<
" -> T"<<tid<<
" is in the correct shower 2S"<<tj.SSID;
1601 myprt<<fcnLabel<<
" 3S"<<ss3.
ID<<
" adding P"<<pfp.ID<<
" -> T"<<tid;
1602 for(
unsigned short ii = 0; ii < pfp.TjIDs.size(); ++ii) {
1603 if(pfp.TjIDs[ii] == tid) myprt<<
" pfp TjCompleteness "<<std::fixed<<std::setprecision(2)<<pfp.TjCompleteness[ii];
1605 myprt<<
" tj.SSID 2S"<<tj.SSID;
1608 for(
auto& cid : ss3.
CotIDs) {
1609 auto&
ss = tjs.
cots[cid - 1];
1610 if(
ss.CTP != tj.CTP)
continue;
1612 AddTj(fcnLabel, tjs, tid,
ss, doUpdate, prt);
1628 if(tjID <= 0 || tjID > (
int)tjs.
allTraj.size())
return false;
1630 std::string fcnLabel = inFcnLabel +
".AddT";
1635 mf::LogVerbatim(
"TC")<<fcnLabel<<
" T"<<tjID<<
" is in the wrong CTP for 2S"<<ss.
ID;
1641 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" T"<<tjID<<
" is already in 2S"<<ss.
ID;
1644 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Can't add T"<<tjID<<
" to 2S"<<ss.
ID<<
". it is already used in 2S"<<tj.
SSID;
1649 ss.
TjIDs.push_back(tjID);
1653 for(
unsigned short ii = 0; ii < ss.
NearTjIDs.size(); ++ii) {
1657 unsigned short cnt = 0;
1658 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
1660 if(tp.
Chg == 0)
continue;
1661 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii)
if(tp.
UseHit[ii]) ++cnt;
1663 unsigned short newSize = ss.
ShPts.size() + cnt;
1664 cnt = ss.
ShPts.size();
1665 ss.
ShPts.resize(newSize);
1667 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
1669 if(tp.
Chg == 0)
continue;
1670 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1672 unsigned int iht = tp.
Hits[ii];
1673 ss.
ShPts[cnt].HitIndex = iht;
1676 ss.
ShPts[cnt].Pos[0] = tjs.
fHits[iht].ArtPtr->WireID().Wire;
1685 if(doUpdate)
return UpdateShower(fcnLabel, tjs, ss, prt);
1695 if(TjID > (
int)tjs.
allTraj.size())
return false;
1697 std::string fcnLabel = inFcnLabel +
".RTj";
1703 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Can't Remove T"<<TjID<<
" from 2S"<<ss.
ID<<
" because it's not in this shower";
1710 for(
unsigned short ii = 0; ii < ss.
TjIDs.size(); ++ii) {
1711 if(TjID == ss.
TjIDs[ii]) {
1717 if(!gotit)
return false;
1724 if(ss.
TjIDs.empty()) {
1725 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Removed the last Tj. Killing 2S"<<ss.
ID;
1749 if(ss3.
ID == 0)
return false;
1750 if(ss3.
CotIDs.size() < 2)
return false;
1757 std::string fcnLabel = inFcnLabel +
".FPar";
1759 int truPFP = mcpu.PrimaryElectronPFPID(ss3.
TPCID);
1764 double shMaxAlong, along95;
1766 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" Estimated energy "<<(int)energy<<
" MeV shMaxAlong "<<shMaxAlong<<
" along95 "<<along95<<
" truPFP "<<truPFP;
1787 std::array<int, 2> parID {{0, 0}};
1788 std::array<float, 2> parFOM {{-1E6, -1E6}};
1791 std::vector<bool> isParent(tjs.
pfps.size() + 1,
false);
1792 for(
auto& oldSS3 : tjs.
showers) {
1793 if(oldSS3.ID == 0)
continue;
1794 isParent[oldSS3.ParentID] =
true;
1798 auto TjsInSS3 =
GetAssns(tjs,
"3S", ss3.
ID,
"T");
1799 if(TjsInSS3.empty())
return false;
1801 for(
auto& pfp : tjs.
pfps) {
1802 if(pfp.ID == 0)
continue;
1803 bool dprt = (pfp.ID == truPFP);
1804 if(pfp.TPCID != ss3.
TPCID)
continue;
1806 if(pfp.PDGCode == 14 || pfp.PDGCode == 14)
continue;
1808 if(pfp.PDGCode == 1111)
continue;
1810 if(isParent[pfp.ID])
continue;
1812 if(
DontCluster(tjs, pfp.TjIDs, TjsInSS3))
continue;
1814 float pfpEnergy = 0;
1815 float minEnergy = 1E6;
1816 for(
auto tid : pfp.TjIDs) {
1817 auto& tj = tjs.
allTraj[tid - 1];
1818 float energy =
ChgToMeV(tj.TotChg);
1820 if(energy < minEnergy) minEnergy =
energy;
1822 pfpEnergy -= minEnergy;
1823 pfpEnergy /= (float)(pfp.TjIDs.size() - 1);
1824 if(dprt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" P"<<pfp.ID<<
" E "<<pfpEnergy;
1825 if(pfpEnergy > energy)
continue;
1829 double costh1 = std::abs(
DotProd(pToS, ss3.
Dir));
1830 if(costh1 < 0.4)
continue;
1831 float costh2 =
DotProd(pToS, pfp.Dir[pEnd]);
1833 float distToStart2 =
PosSep2(pfp.XYZ[pEnd], ss3.
Start);
1835 float distToEnd2 =
PosSep2(pfp.XYZ[pEnd], ss3.
End);
1836 if(dprt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" P"<<pfp.ID<<
"_"<<pEnd<<
" distToStart "<<sqrt(distToStart2)<<
" distToChgPos "<<sqrt(distToChgPos2)<<
" distToEnd "<<sqrt(distToEnd2);
1838 unsigned short shEnd = 0;
1839 if(distToEnd2 < distToStart2) shEnd = 1;
1841 if(shEnd == 0 && distToChgPos2 < distToStart2)
continue;
1842 if(shEnd == 1 && distToChgPos2 < distToEnd2)
continue;
1843 if(dprt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
"_"<<shEnd<<
" P"<<pfp.ID<<
"_"<<pEnd<<
" costh1 "<<costh1;
1848 if(dprt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" alongTrans "<<alongTrans[0]<<
" "<<alongTrans[1];
1852 float distToShowerMax = shMaxAlong - std::abs(alongTrans[0]);
1855 if(prob < 0.1)
continue;
1860 for(
unsigned short plane = 0; plane < tjs.
NumPlanes; ++plane) {
1863 for(
auto cid : ss3.
CotIDs) {
1864 auto&
ss = tjs.
cots[cid - 1];
1865 if(
ss.CTP != inCTP)
continue;
1869 if(ssid == 0)
continue;
1870 auto tpFrom =
MakeBareTP(tjs, pfp.XYZ[pEnd], pToS, inCTP);
1871 auto&
ss = tjs.
cots[ssid - 1];
1872 auto& stp1 = tjs.
allTraj[
ss.ShowerTjID - 1].Pts[1];
1873 float sep =
PosSep(tpFrom.Pos, stp1.Pos);
1874 float toPos = tpFrom.Pos[0] + 0.5 * tpFrom.Dir[0] * sep;
1878 chgFrac += sep * cf;
1880 if(totSep > 0) chgFrac /= totSep;
1917 myprt<<
" 3S"<<ss3.
ID<<
"_"<<shEnd;
1918 myprt<<
" P"<<pfp.ID<<
"_"<<pEnd<<
" ParentVars";
1919 for(
auto var : tjs.
ShowerParentVars) myprt<<
" "<<std::fixed<<std::setprecision(2)<<var;
1920 myprt<<
" candParFOM "<<candParFOM;
1922 if(candParFOM > parFOM[shEnd]) {
1923 parFOM[shEnd] = candParFOM;
1924 parID[shEnd] = pfp.ID;
1928 if(parID[0] == 0 && parID[1] == 0)
return true;
1933 float aveDirFOM = 0;
1935 for(
auto cid : ss3.
CotIDs) aveDirFOM += tjs.
cots[cid - 1].DirectionFOM;
1936 aveDirFOM /= (float)ss3.
CotIDs.size();
1938 mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" parID[0] "<<parID[0]<<
" fom "<<parFOM[0]<<
" parID[1] "<<parID[1]<<
" fom "<<parFOM[1]<<
" aveDirFOM "<<aveDirFOM;
1940 if(parID[0] > 0 && parID[1] > 0 && aveDirFOM > 0.3) {
1945 if(parFOM[1] > parFOM[0]) {
1949 }
else if(parID[0] > 0) {
1956 if(bestPFP == 0)
return true;
1958 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" setting P"<<bestPFP<<
" as the parent "<<fom3D;
1962 std::vector<ShowerStruct> oldSS(ss3.
CotIDs.size());
1963 for(
unsigned short ii = 0; ii < ss3.
CotIDs.size(); ++ii) {
1968 auto& pfp = tjs.
pfps[bestPFP - 1];
1970 ss3.
Vx3ID = pfp.Vx3ID[pend];
1977 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" Failed. Recovering...";
1979 for(
unsigned short ii = 0; ii < oldSS.size(); ++ii) {
1980 auto&
ss = oldSS[ii];
1991 if(pfp.
ID == 0 || ss3.
ID == 0)
return false;
1992 if(ss3.
CotIDs.empty())
return false;
1994 std::string fcnLabel = inFcnLabel +
".SP";
1996 for(
auto cid : ss3.
CotIDs) {
1997 auto&
ss = tjs.
cots[cid - 1];
1998 auto& stj = tjs.
allTraj[
ss.ShowerTjID - 1];
2000 if(
ss.ParentID > 0) {
2001 auto& oldParent = tjs.
allTraj[
ss.ParentID - 1];
2007 for(
auto tjid : pfp.
TjIDs) {
2008 auto& tj = tjs.
allTraj[tjid - 1];
2009 if(tj.CTP !=
ss.CTP)
continue;
2010 if(std::find(
ss.TjIDs.begin(),
ss.TjIDs.end(), tjid) ==
ss.TjIDs.end()) {
2012 if(!
AddTj(fcnLabel, tjs, tjid,
ss,
false, prt))
return false;
2017 unsigned short npts = tj.EndPt[1] - tj.EndPt[0] + 1;
2018 if(tp.Delta > 0.5 || npts > 20) {
2019 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" parent P"<<pfp.
ID<<
" -> T"<<tjid<<
" -> 2S"<<
ss.ID<<
" parent";
2021 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" parent P"<<pfp.
ID<<
" -> T"<<tjid<<
" low projection in plane "<<tp.Delta<<
". Not a parent";
2025 ss.NeedsUpdate =
true;
2029 auto v2list =
GetAssns(tjs,
"3V", vx3.ID,
"2V");
2030 for(
unsigned short end = 0;
end < 2; ++
end) {
2031 if(tj.VtxID[
end] <= 0)
continue;
2032 if(std::find(v2list.begin(), v2list.end(), tj.VtxID[
end]) != v2list.end()) stj.VtxID[0] = tj.VtxID[
end];
2043 float fom3D =
ParentFOM(fcnLabel, tjs, pfp, pEnd, ss3, prt);
2044 for(
auto cid : ss3.
CotIDs) tjs.
cots[cid - 1].ParentFOM = fom3D;
2055 pfp.XYZ[0] = ss3.
Start;
2056 pfp.Dir[0] = ss3.
Dir;
2057 pfp.XYZ[1] = ss3.
End;
2058 pfp.Dir[1] = ss3.
Dir;
2060 unsigned short npts = ss3.
Len;
2061 if(npts < 2)
return pfp;
2062 pfp.Tp3s.resize(npts);
2063 pfp.Tp3s[0].Pos = ss3.
Start;
2064 for(
unsigned short ipt = 1; ipt < npts; ++ipt) {
2065 for(
unsigned short xyz = 0; xyz < 3; ++xyz) pfp.Tp3s[ipt].Pos[xyz] = pfp.Tp3s[ipt-1].Pos[xyz] + pfp.Dir[0][xyz];
2074 if(TjIDs.empty())
return false;
2075 unsigned short cnt = 0;
2076 for(
auto tid : TjIDs) {
2077 if(tid <= 0 || tid > (
int)tjs.
allTraj.size())
continue;
2084 void ShowerParams(
double showerEnergy,
double& shMaxAlong,
double& along95)
2090 if(showerEnergy < 10) {
2096 shMaxAlong = 16 * log(showerEnergy / 15);
2098 double scale = 2.75 - 9.29E-4 * showerEnergy;
2099 if(scale < 2) scale = 2;
2100 along95 = scale * shMaxAlong;
2107 double shMaxAlong, shE95Along;
2109 if(shMaxAlong <= 0)
return 0;
2110 double tau = (along + shMaxAlong) / shMaxAlong;
2112 double rms = -0.4 + 2.5 * tau;
2113 if(rms < 0.5) rms = 0.5;
2123 if(showerEnergy < 10)
return 0;
2125 double shMaxAlong, shE95Along;
2132 double tau = (along + shMaxAlong) / shMaxAlong;
2133 if(tau < -1 || tau > 4)
return 0;
2135 double tauHalf, width;
2146 double prob = 1 / (1 + exp((tau - tauHalf)/width));
2157 if(showerEnergy < 10)
return 0;
2159 trans = std::abs(trans);
2160 double prob = exp(-0.5 * trans / rms);
2176 if(ss3.
ID == 0 || pfp.
ID == 0)
return 0;
2179 for(
auto cid : ss3.
CotIDs) {
2180 auto&
ss = tjs.
cots[cid - 1];
2181 if(
ss.ID == 0)
continue;
2182 for(
auto tid : pfp.
TjIDs) {
2183 auto& tj = tjs.
allTraj[tid - 1];
2184 if(tj.CTP !=
ss.CTP)
continue;
2190 if(cnt == 0)
return 0;
2200 if(ss.
ID == 0 || tj.
ID == 0)
return 0;
2201 if(ss.
CTP != tj.
CTP)
return 0;
2204 if(stj.Pts.size() != 3)
return 0;
2205 unsigned short closePt1, closePt2;
2208 if(doca == 1E6)
return 0;
2209 float showerLen =
PosSep(stj.Pts[0].Pos, stj.Pts[2].Pos);
2211 if(doca > 5 * showerLen)
return 0.01;
2212 auto& stp = stj.Pts[closePt1];
2213 if(stp.DeltaRMS == 0)
return 0;
2214 auto& ttp = tj.
Pts[closePt2];
2219 float rms = stp.DeltaRMS;
2220 if(rms < 1) rms = 1;
2221 float arg = alongTrans[1] / rms;
2222 float radProb = exp(-0.5 * arg * arg);
2226 arg = alongTrans[0] / rms;
2227 float longProb = exp(-0.5 * arg * arg);
2229 float costh = std::abs(
DotProd(stp.Dir, ttp.Dir));
2231 float prob = radProb * longProb * costh;
2241 if(ss3.
ID == 0)
return 1000;
2244 std::string fcnLabel = inFcnLabel +
".P3FOM";
2246 for(
auto cid : ss3.
CotIDs) {
2247 auto&
ss = tjs.
cots[cid - 1];
2248 if(
ss.ID == 0)
continue;
2251 for(
auto tid : pfp.
TjIDs) {
2252 auto& tj = tjs.
allTraj[tid - 1];
2253 if(tj.ID == 0)
continue;
2254 if(tj.CTP ==
ss.CTP) tjid = tid;
2256 if(tjid == 0)
continue;
2257 auto& ptj = tjs.
allTraj[tjid - 1];
2258 auto& stj = tjs.
allTraj[
ss.ShowerTjID - 1];
2260 unsigned short ptjEnd =
FarEnd(tjs, ptj, stj.Pts[1].Pos);
2261 auto& farTP = ptj.Pts[ptj.EndPt[ptjEnd]];
2262 float chgCtrSep2 =
PosSep2(farTP.Pos, stj.Pts[1].Pos);
2263 if(chgCtrSep2 <
PosSep2(farTP.Pos, stj.Pts[0].Pos) && chgCtrSep2 <
PosSep2(farTP.Pos, stj.Pts[2].Pos))
continue;
2264 float fom =
ParentFOM(fcnLabel, tjs, ptj, ptjEnd,
ss, dum1, dum2, prt);
2266 if(fom > 50)
continue;
2269 if(
ss.AspectRatio > 0) wt = 1 /
ss.AspectRatio;
2273 if(wsum == 0)
return 100;
2274 float fom = sum / wsum;
2275 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" P"<<pfp.
ID<<
" fom "<<std::fixed<<std::setprecision(3)<<fom;
2288 if(tjEnd > 1)
return 1000;
2289 if(ss.
Energy == 0)
return 1000;
2291 if(ss.
ID == 0)
return 1000;
2292 if(ss.
TjIDs.empty())
return 1000;
2295 std::string fcnLabel = inFcnLabel +
".PFOM";
2319 tp1Sep = std::abs(alongTrans[0]);
2321 double shMaxAlong, shE95Along;
2323 double alongcm = tjs.
WirePitch * tp1Sep;
2327 if(prob < 0.05)
return 100;
2330 if(alongTrans[1] > shMaxAlong)
return 100;
2332 float longFOM = std::abs(alongcm + shMaxAlong) / 14;
2336 float transFOM = -1;
2338 transFOM = alongTrans[1] / stp0.
DeltaRMS;
2348 float dang1FOM = dang1 / 0.1;
2352 float dang2FOM = dang1 / 0.1;
2356 std::vector<int> tjlist(1);
2363 if(tj.
VtxID[tjEnd] > 0) {
2366 vx2Score = vx2.
Score;
2369 vxFOM = std::abs(shMaxAlong - vx2Sep) / 20;
2374 float chgFracFOM = (1 - chgFrac) / 0.1;
2379 float chgFrcBtwFOM = (1 - chgFrac) / 0.05;
2380 fom += chgFrcBtwFOM;
2391 myprt<<
" 2S"<<ss.
ID;
2392 myprt<<
" T"<<tj.
ID<<
"_"<<tjEnd<<
" Pos "<<
PrintPos(tjs, ptp);
2393 myprt<<std::fixed<<std::setprecision(2);
2394 myprt<<
" along "<<std::fixed<<std::setprecision(1)<<alongTrans[0]<<
" fom "<<longFOM;
2395 myprt<<
" trans "<<alongTrans[1]<<
" fom "<<transFOM;
2396 myprt<<
" prob "<<prob;
2397 myprt<<
" dang1 "<<dang1<<
" fom "<<dang1FOM;
2398 myprt<<
" dang2 "<<dang2<<
" fom "<<dang2FOM;
2399 myprt<<
" vx2Score "<<vx2Score<<
" fom "<<vxFOM;
2400 myprt<<
" chgFrac "<<chgFrac<<
" fom "<<chgFracFOM;
2401 myprt<<
" chgFracBtw "<<chgFracBtw<<
" fom "<<chgFrcBtwFOM;
2402 myprt<<
" FOM "<<fom;
2426 if(tjEnd > 1)
return false;
2428 std::string fcnLabel = inFcnLabel +
".WSTj";
2431 unsigned short otherEnd = 1 - tjEnd;
2433 if(tj.
VtxID[otherEnd] == 0)
return false;
2434 unsigned short ivx = tj.
VtxID[otherEnd] - 1;
2436 if(tjs.
vtx[ivx].Topo != 8 && tjs.
vtx[ivx].Topo != 10)
return false;
2437 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Primary candidate "<<tj.
ID<<
" was split by a 3D vertex";
2446 if(tjs.
cots.empty())
return;
2448 std::string fcnLabel = inFcnLabel +
".MNS";
2452 myprt<<fcnLabel<<
" list";
2453 for(
auto&
ss : tjs.
cots) {
2454 if(
ss.CTP != inCTP)
continue;
2455 if(
ss.ID == 0)
continue;
2456 myprt<<
" ss.ID "<<
ss.ID<<
" NearTjs";
2457 for(
auto&
id :
ss.NearTjIDs) myprt<<
" "<<id;
2462 bool keepMerging =
true;
2463 while(keepMerging) {
2464 keepMerging =
false;
2465 for(
unsigned short ci1 = 0; ci1 < tjs.
cots.size() - 1; ++ci1) {
2467 if(ss1.
CTP != inCTP)
continue;
2468 if(ss1.
ID == 0)
continue;
2469 if(ss1.
TjIDs.empty())
continue;
2471 std::vector<int> ss1list = ss1.
TjIDs;
2473 for(
unsigned short ci2 = ci1 + 1; ci2 < tjs.
cots.size(); ++ci2) {
2475 if(ss2.
CTP != inCTP)
continue;
2476 if(ss2.
ID == 0)
continue;
2477 if(ss2.
TjIDs.empty())
continue;
2479 std::vector<int> ss2list = ss2.
TjIDs;
2482 if(shared.empty())
continue;
2485 myprt<<fcnLabel<<
" Merge 2S"<<ss2.
ID<<
" into 2S"<<ss1.
ID<<
"? shared nearby:";
2486 for(
auto tjid : shared) myprt<<
" T"<<tjid;
2489 bool doMerge =
false;
2490 for(
auto& tjID : shared) {
2491 bool inSS1 = (std::find(ss1.
TjIDs.begin(), ss1.
TjIDs.end(), tjID) != ss1.
TjIDs.end());
2492 bool inSS2 = (std::find(ss2.
TjIDs.begin(), ss2.
TjIDs.end(), tjID) != ss2.
TjIDs.end());
2493 if(inSS1 && !inSS2) doMerge =
true;
2494 if(!inSS1 && inSS2) doMerge =
true;
2496 if(inSS1 || inSS2)
continue;
2497 auto& tj = tjs.
allTraj[tjID - 1];
2499 if(tj.PDGCode == 13 && tj.Pts.size() > 100 && tj.ChgRMS < 0.5) {
2500 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" T"<<tj.ID<<
" looks like a muon. Don't add it";
2505 auto TInP =
GetAssns(tjs,
"T", tj.ID,
"P");
2507 auto& pfp = tjs.
pfps[TInP[0] - 1];
2508 if(pfp.PDGCode == 13 &&
MCSMom(tjs, pfp.TjIDs) > 500)
continue;
2511 if(
AddTj(fcnLabel, tjs, tjID, ss1,
false, prt)) doMerge =
true;
2513 if(!doMerge)
continue;
2551 if(tjs.
cots.empty())
return;
2553 std::string fcnLabel = inFcnLabel +
".MO";
2561 bool didMerge =
true;
2565 for(
unsigned short ict = 0; ict < tjs.
cots.size() - 1; ++ict) {
2566 auto& iss = tjs.
cots[ict];
2567 if(iss.ID == 0)
continue;
2568 if(iss.TjIDs.empty())
continue;
2569 if(iss.CTP != inCTP)
continue;
2570 for(
unsigned short jct = ict + 1; jct < tjs.
cots.size(); ++jct) {
2571 auto& jss = tjs.
cots[jct];
2572 if(jss.ID == 0)
continue;
2573 if(jss.TjIDs.empty())
continue;
2574 if(jss.CTP != iss.CTP)
continue;
2575 if(
DontCluster(tjs, iss.TjIDs, jss.TjIDs))
continue;
2576 bool doMerge =
false;
2577 for(
auto& ivx : iss.Envelope) {
2582 for(
auto& jvx : jss.Envelope) {
2589 for(
auto& ivx : iss.Envelope) {
2590 for(
auto& jvx : jss.Envelope) {
2591 if(
PosSep2(ivx, jvx) < sepCut2) {
2600 if(!doMerge)
continue;
2604 unsigned short iClosePt = 0;
2605 unsigned short jClosePt = 0;
2607 auto& istj = tjs.
allTraj[iss.ShowerTjID - 1];
2608 auto& jstj = tjs.
allTraj[jss.ShowerTjID - 1];
2609 for(
unsigned short ipt = 0; ipt < 3; ++ipt) {
2610 for(
unsigned short jpt = 0; jpt < 3; ++jpt) {
2611 float sep =
PosSep2(istj.Pts[ipt].Pos, jstj.Pts[jpt].Pos);
2619 float costh =
DotProd(istj.Pts[0].Dir, jstj.Pts[0].Dir);
2620 if(iClosePt == 0 && jClosePt == 0 && costh < 0.955) {
2621 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" showers are close at the start points with costh "<<costh<<
". Don't merge";
2624 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Merge "<<iss.ID<<
" and "<<jss.ID;
2648 std::string fcnLabel = inFcnLabel +
".MSC";
2650 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
": MergeShowerChain inCTP "<<inCTP;
2652 std::vector<int> sids;
2653 std::vector<TrajPoint> tpList;
2654 for(
unsigned short ict = 0; ict < tjs.
cots.size(); ++ict) {
2656 if(iss.
ID == 0)
continue;
2657 if(iss.
TjIDs.empty())
continue;
2658 if(iss.
CTP != inCTP)
continue;
2660 if(iss.
Energy < 50)
continue;
2662 sids.push_back(iss.
ID);
2666 if(sids.size() < 3)
return;
2669 std::vector<SortEntry> sortVec(sids.size());
2670 for(
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
2671 sortVec[ii].index = ii;
2672 sortVec[ii].length = tpList[ii].Pos[0];
2674 std::sort(sortVec.begin(), sortVec.end(),
lessThan);
2676 auto ttpList = tpList;
2677 for(
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
2678 unsigned short indx = sortVec[ii].index;
2679 sids[ii] = tsids[indx];
2680 tpList[ii] = ttpList[indx];
2685 float maxDelta = 30;
2686 for(
unsigned short ii = 0; ii < sids.size() - 2; ++ii) {
2687 auto& iss = tjs.
cots[sids[ii] - 1];
2688 if(iss.ID == 0)
continue;
2689 unsigned short jj = ii + 1;
2690 auto& jss = tjs.
cots[sids[jj] - 1];
2691 if(jss.ID == 0)
continue;
2692 std::vector<int> chain;
2693 float sepij =
PosSep(tpList[ii].Pos, tpList[jj].Pos);
2694 if(sepij > minSep)
continue;
2695 bool skipit =
DontCluster(tjs, iss.TjIDs, jss.TjIDs);
2696 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" i2S"<<iss.ID<<
" "<<
PrintPos(tjs, tpList[ii].Pos)<<
" j2S"<<jss.ID<<
" "<<
PrintPos(tjs, tpList[jj].Pos)<<
" sepij "<<sepij<<
" skipit? "<<skipit;
2697 if(skipit)
continue;
2702 for(
unsigned short kk = jj + 1; kk < sids.size(); ++kk) {
2703 auto& kss = tjs.
cots[sids[kk] - 1];
2704 if(kss.ID == 0)
continue;
2705 if(
DontCluster(tjs, iss.TjIDs, kss.TjIDs))
continue;
2706 if(
DontCluster(tjs, jss.TjIDs, kss.TjIDs))
continue;
2707 float sepjk =
PosSep(tpList[jj].Pos, tpList[kk].Pos);
2708 float delta =
PointTrajDOCA(tjs, tpList[kk].Pos[0], tpList[kk].Pos[1], tp);
2711 myprt<<fcnLabel<<
" k2S"<<kss.ID<<
" "<<
PrintPos(tjs, tpList[kk].Pos)<<
" sepjk "<<sepjk<<
" delta "<<delta;
2712 if(sepjk > minSep || delta > maxDelta) {
2713 myprt<<
" failed separation "<<minSep<<
" or delta cut "<<maxDelta;
2715 myprt<<
" add to the chain";
2718 if(sepjk > minSep || delta > maxDelta) {
2720 if(chain.size() > 2) {
2725 myprt<<fcnLabel<<
" merged chain";
2726 for(
auto ssID : chain) myprt<<
" 2S"<<ssID;
2727 myprt<<
" -> 2S"<<newID;
2736 chain[0] = sids[ii]; chain[1] = sids[jj]; chain[2] = sids[kk];
2738 chain.push_back(sids[kk]);
2746 if(chain.size() > 2) {
2756 myprt<<fcnLabel<<
" merged chain";
2757 for(
auto ssID : chain) myprt<<
" "<<ssID;
2758 myprt<<
" -> new ssID "<<newID;
2775 std::string fcnLabel = inFcnLabel +
".MSSTj";
2782 std::vector<TjSS> tjss;
2785 std::vector<int> tjid(1);
2786 for(
auto&
ss : tjs.
cots) {
2787 if(
ss.ID == 0)
continue;
2788 if(
ss.CTP != inCTP)
continue;
2790 if(
ss.Energy > 300)
continue;
2791 auto& stj = tjs.
allTraj[
ss.ShowerTjID - 1];
2792 auto stp0 = stj.Pts[0];
2793 float bestDang = 0.3;
2797 if(tj.AlgMod[
kKilled])
continue;
2798 if(tj.CTP !=
ss.CTP)
continue;
2800 if(tj.SSID > 0)
continue;
2804 if(tj.MCSMom > tjs.
ShowerTag[1])
continue;
2808 float tjEnergy =
ChgToMeV(tj.TotChg);
2810 unsigned short farEnd =
FarEnd(tjs, tj, stj.Pts[1].Pos);
2812 unsigned short midpt = 0.5 * (tj.EndPt[0] + tj.EndPt[1]);
2813 float mom1 =
MCSMom(tjs, tj, tj.EndPt[farEnd], midpt);
2814 float mom2 =
MCSMom(tjs, tj, tj.EndPt[1 - farEnd], midpt);
2815 float asym = (mom1 - mom2) / (mom1 + mom2);
2816 auto& farTP = tj.Pts[tj.EndPt[farEnd]];
2818 float doca =
PointTrajDOCA(tjs, stp0.Pos[0], stp0.Pos[1], farTP);
2819 float sep =
PosSep(farTP.Pos, stp0.Pos);
2820 float dang = doca / sep;
2823 myprt<<fcnLabel<<
" Candidate 2S"<<
ss.ID<<
" T"<<tj.ID<<
"_"<<farEnd;
2824 myprt<<
" ShEnergy "<<(int)
ss.Energy<<
" tjEnergy "<<(
int)tjEnergy;
2825 myprt<<
" doca "<<doca<<
" sep "<<sep<<
" dang "<<dang<<
" asym "<<asym;
2827 if(tjEnergy <
ss.Energy)
continue;
2828 if(asym < 0.5)
continue;
2831 if(sep > 100)
continue;
2832 if(dang > bestDang)
continue;
2836 if(bestTj == 0)
continue;
2839 match.tjID = bestTj;
2840 match.dang = bestDang;
2841 tjss.push_back(match);
2844 if(tjss.empty())
return;
2847 bool keepGoing =
true;
2850 float bestDang = 0.3;
2852 for(
unsigned short mat = 0;
mat < tjss.size(); ++
mat) {
2853 auto& match = tjss[
mat];
2855 if(match.dang < 0)
continue;
2856 if(match.dang < bestDang) bestMatch =
mat;
2859 auto& match = tjss[bestMatch];
2860 auto&
ss = tjs.
cots[match.ssID - 1];
2861 if(!
AddTj(fcnLabel, tjs, match.tjID,
ss,
true, prt)) {
2867 auto& stj = tjs.
allTraj[
ss.ShowerTjID - 1];
2884 std::string fcnLabel = inFcnLabel +
".MSS";
2886 constexpr
float radLen = 14 / 0.3;
2890 mf::LogVerbatim(
"TC")<<fcnLabel<<
" MergeSubShowers checking using ShowerParams";
2892 mf::LogVerbatim(
"TC")<<fcnLabel<<
" MergeSubShowers checking using radiation length cut ";
2896 bool keepMerging =
true;
2897 while(keepMerging) {
2898 keepMerging =
false;
2900 std::vector<SortEntry> sortVec;
2901 for(
auto&
ss : tjs.
cots) {
2902 if(
ss.ID == 0)
continue;
2903 if(
ss.CTP != inCTP)
continue;
2906 se.length =
ss.Energy;
2907 sortVec.push_back(se);
2909 if(sortVec.size() < 2)
return;
2910 std::sort(sortVec.begin(), sortVec.end(),
greaterThan);
2911 for(
unsigned short ii = 0; ii < sortVec.size() - 1; ++ii) {
2913 if(iss.
ID == 0)
continue;
2917 double shMaxAlong, along95;
2920 along95 -= shMaxAlong;
2923 for(
unsigned short jj = ii + 1; jj < sortVec.size(); ++jj) {
2925 if(jss.
ID == 0)
continue;
2934 if(alongTrans[0] < 0)
continue;
2936 float alongCut = along95;
2942 myprt<<fcnLabel<<
" Candidate i2S"<<iss.
ID<<
" E = "<<(int)iss.
Energy<<
" j2S"<<jss.
ID<<
" E = "<<(
int)jss.
Energy;
2943 myprt<<
" along "<<std::fixed<<std::setprecision(1)<<alongTrans[0]<<
" trans "<<alongTrans[1];
2944 myprt<<
" alongCut "<<alongCut<<
" probLong "<<probLong<<
" probTran "<<probTran;
2947 if(alongTrans[0] > alongCut)
continue;
2948 if(alongTrans[1] > alongTrans[0])
continue;
2952 float trad = sep / radLen;
2961 float dang = delta / sep;
2962 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Candidate i2S"<<iss.
ID<<
" j2S"<<jss.
ID<<
" separation "<<(int)sep<<
" radiation lengths "<<trad<<
" delta "<<delta<<
" dang "<<dang;
2963 if(trad > 3)
continue;
2965 if(dang > 0.3)
continue;
2968 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Merge them. Re-find shower center, etc";
2976 if(keepMerging)
break;
2990 std::string fcnLabel = inFcnLabel +
".MS";
2991 if(ssIDs.size() < 2)
return 0;
2993 for(
auto ssID : ssIDs)
if(ssID <= 0 || ssID > (
int)tjs.
cots.size())
return 0;
2996 auto& ss0 = tjs.
cots[ssIDs[0] - 1];
2997 std::vector<int> tjl;
2998 for(
auto ssID : ssIDs) {
2999 auto&
ss = tjs.
cots[ssID - 1];
3000 if(
ss.CTP != ss0.CTP)
return 0;
3001 tjl.insert(tjl.end(),
ss.TjIDs.begin(),
ss.TjIDs.end());
3002 if(
ss.SS3ID > 0 && ss3Assn == 0) ss3Assn =
ss.SS3ID;
3003 if(
ss.SS3ID > 0 &&
ss.SS3ID != ss3Assn) {
3004 std::cout<<fcnLabel<<
" Assn conflict \n";
3009 for(
auto tjID : tjl) {
3010 auto& tj = tjs.
allTraj[tjID - 1];
3011 if(tj.CTP != ss0.CTP || tj.AlgMod[
kKilled]) {
3012 std::cout<<fcnLabel<<
" bad InShower T"<<tjID<<
"\n";
3018 for(
auto ssID : ssIDs) {
3019 auto&
ss = tjs.
cots[ssID - 1];
3022 auto& stj = tjs.
allTraj[
ss.ShowerTjID - 1];
3027 auto newss =
CreateSS(tjs, 0, tjl);
3028 if(newss.ID == 0)
return 0;
3030 for(
auto tid : tjl) {
3031 auto& tj = tjs.
allTraj[tid - 1];
3034 newss.SS3ID = ss3Assn;
3038 std::cout<<fcnLabel<<
" UpdateShower failed\n";
3044 std::cout<<fcnLabel<<
" StoreShower failed\n";
3059 if(icotID <= 0 || icotID > (
int)tjs.
cots.size())
return false;
3061 if(iss.
ID == 0)
return false;
3062 if(iss.
TjIDs.empty())
return false;
3065 if(jcotID <= 0 || jcotID > (
int)tjs.
cots.size())
return false;
3067 if(jss.
TjIDs.empty())
return false;
3068 if(jss.
ID == 0)
return false;
3071 if(iss.
CTP != jss.
CTP)
return false;
3073 std::string fcnLabel = inFcnLabel +
".MSAS";
3076 std::cout<<fcnLabel<<
" Error: 2S"<<iss.
ID<<
" and S"<<jss.
ID<<
" have different 2S -> 3S assns\n";
3082 if(!itj.
Pts[1].Hits.empty() || !jtj.
Pts[1].Hits.empty()) {
3083 std::cout<<fcnLabel<<
" Error: These shower Tjs have hits! T"<<itj.
ID<<
" T"<<jtj.
ID<<
"\n";
3103 std::sort(iss.
TjIDs.begin(), iss.
TjIDs.end());
3105 for(
auto tid : iss.
TjIDs) {
3106 auto& tj = tjs.
allTraj[tid - 1];
3135 if(istj > tjs.
allTraj.size() - 1)
return false;
3136 if(jstj > tjs.
allTraj.size() - 1)
return false;
3141 std::string fcnLabel =
"MSTJ";
3143 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" MergeShowerTjsAndStore Tj IDs "<<itj.
ID<<
" "<<jtj.
ID;
3155 if(icotID == 0)
return false;
3157 if(iss.
ID == 0)
return false;
3158 if(iss.
TjIDs.empty())
return false;
3160 if(jcotID == 0)
return false;
3162 if(jss.
ID == 0)
return false;
3163 if(jss.
TjIDs.empty())
return false;
3177 if(ss.
ID == 0)
return false;
3178 if(ss.
ShPts.empty())
return false;
3180 if(stj.
Pts.size() != 3)
return false;
3182 std::string fcnLabel = inFcnLabel +
".ARP";
3184 for(
auto& tp : stj.
Pts) {
3188 tp.HitPos = {{0.0, 0.0}};
3191 float minAlong = ss.
ShPts[0].RotPos[0];
3192 float maxAlong = ss.
ShPts[ss.
ShPts.size()-1].RotPos[0];
3193 float sectionLength = (maxAlong - minAlong) / 3;
3194 float sec0 = minAlong + sectionLength;
3195 float sec2 = maxAlong - sectionLength;
3197 for(
auto& spt : ss.
ShPts) {
3199 unsigned short ipt = 0;
3200 if(spt.RotPos[0] < sec0) {
3203 }
else if(spt.RotPos[0] > sec2) {
3210 stj.
Pts[ipt].Chg += spt.Chg;
3225 stj.
Pts[ipt].DeltaRMS += spt.Chg * std::abs(spt.RotPos[1]);
3226 ++stj.
Pts[ipt].NTPsFit;
3228 stj.
Pts[ipt].HitPos[0] += spt.Chg * spt.Pos[0];
3229 stj.
Pts[ipt].HitPos[1] += spt.Chg * spt.Pos[1];
3232 for(
auto& tp : stj.
Pts) {
3234 tp.DeltaRMS /= tp.Chg;
3235 tp.HitPos[0] /= tp.Chg;
3236 tp.HitPos[1] /= tp.Chg;
3242 if(stj.
Pts[0].Chg == 0 || stj.
Pts[2].Chg == 0)
return false;
3245 if(stj.
Pts[1].Chg == 0) {
3247 stj.
Pts[1].HitPos[0] = 0.5 * (stj.
Pts[0].HitPos[0] + stj.
Pts[2].HitPos[0]);
3248 stj.
Pts[1].HitPos[1] = 0.5 * (stj.
Pts[0].HitPos[1] + stj.
Pts[2].HitPos[1]);
3250 if(stj.
Pts[2].DeltaRMS > 0) {
3257 myprt<<fcnLabel<<
" 2S"<<ss.
ID;
3258 myprt<<
" HitPos[0] "<<std::fixed<<std::setprecision(1);
3259 myprt<<stj.
Pts[1].HitPos[0]<<
" "<<stj.
Pts[1].HitPos[1]<<
" "<<stj.
Pts[1].HitPos[2];
3260 myprt<<
" DeltaRMS "<<std::setprecision(2);
3261 myprt<<stj.
Pts[0].DeltaRMS<<
" "<<stj.
Pts[1].DeltaRMS<<
" "<<stj.
Pts[2].DeltaRMS;
3262 myprt<<
" DirectionFOM "<<std::fixed<<std::setprecision(2)<<ss.
DirectionFOM;
3273 if(ss.
ID == 0)
return;
3274 if(ss.
TjIDs.empty())
return;
3276 std::string fcnLabel = inFcnLabel +
".RevSh";
3278 std::reverse(ss.
ShPts.begin(), ss.
ShPts.end());
3280 for(
auto& sspt : ss.
ShPts) {
3281 sspt.RotPos[0] = -sspt.RotPos[0];
3282 sspt.RotPos[1] = -sspt.RotPos[1];
3302 if(cotID > (
int)tjs.
cots.size())
return;
3304 if(ss.
ID == 0)
return;
3314 for(
auto cid : ss3.
CotIDs) {
3315 if(cid == 0 || (
unsigned short)cid > tjs.
cots.size())
continue;
3316 auto&
ss = tjs.
cots[cid - 1];
3317 if(
ss.SS3ID > 0 &&
ss.SS3ID != ss3.
ID) {
3318 std::cout<<
"MakeShowerObsolete: 3S"<<ss3.
ID<<
" -> 2S"<<
ss.ID<<
" SS3ID 3S"<<
ss.SS3ID<<
" != "<<ss3.
ID<<
"\n";
3324 std::string fcnLabel = inFcnLabel +
".MSO";
3328 std::cout<<
"MakeShowerObsolete: 3S"<<ss3.
ID<<
" -> P"<<ss3.
PFPIndex+1<<
" assn exists but maybe shouldn't...";
3338 if(ss.
ID == 0)
return;
3340 std::string fcnLabel = inFcnLabel +
".MSO";
3343 if(!stp1.Hits.empty()) {
3344 std::cout<<fcnLabel<<
" Trying to kill shower "<<ss.
ID<<
" that has hits associated with it. Don't do this...\n";
3350 std::vector<int> newCIDs;
3351 for(
auto cid : ss3.CotIDs) {
3352 if(cid != ss.
ID) newCIDs.push_back(cid);
3354 ss3.CotIDs = newCIDs;
3362 for(
auto& tjID : ss.
TjIDs) {
3384 if(tjlist1.empty() || tjlist2.empty())
return false;
3386 for(
auto tid1 : tjlist1) {
3387 for(
auto tid2 : tjlist2) {
3389 if(ttid1 > tid2) std::swap(ttid1, tid2);
3390 for(
auto& dc : tjs.
dontCluster)
if(dc.TjIDs[0] == ttid1 && dc.TjIDs[1] == tid2)
return true;
3406 for(
auto& vx3 : tjs.
vtx3) {
3407 if(vx3.ID == 0)
continue;
3408 if(vx3.TPCID != tpcid)
continue;
3409 if(!vx3.Neutrino)
continue;
3410 auto PIn3V =
GetAssns(tjs,
"3V", vx3.ID,
"P");
3411 if(PIn3V.size() < 2)
continue;
3412 Point3_t v3pos = {{vx3.X, vx3.Y, vx3.Z}};
3413 for(
unsigned short ip1 = 0; ip1 < PIn3V.size() - 1; ++ip1) {
3414 auto& p1 = tjs.
pfps[PIn3V[ip1] - 1];
3416 if(p1.TjIDs.empty())
continue;
3417 unsigned short p1End = 0;
3418 if(p1.Vx3ID[1] == vx3.ID) p1End = 1;
3423 float p1Sep =
PosSep(p1.XYZ[p1End], v3pos);
3424 for(
unsigned short ip2 = ip1 + 1; ip2 < PIn3V.size(); ++ip2) {
3425 auto& p2 = tjs.
pfps[PIn3V[ip2] - 1];
3426 if(p2.TjIDs.empty())
continue;
3427 unsigned short p2End = 0;
3428 if(p2.Vx3ID[1] == vx3.ID) p2End = 1;
3430 float p2Sep =
PosSep(p2.XYZ[p2End], v3pos);
3443 if(p1ShowerLike && p2ShowerLike)
continue;
3445 float costh =
DotProd(p1Dir, p2Dir);
3446 if(costh < 0.92)
continue;
3447 unsigned short closePt1, closePt2;
3448 float doca =
PFPDOCA(p1, p2, closePt1, closePt2);
3449 float minSep = p1Sep;
3450 if(p1Sep < minSep) minSep = p2Sep;
3451 bool allowCluster = (doca < minSep);
3454 std::cout<<
"DDC: P"<<p1.ID<<
" p1ShowerLike "<<p1ShowerLike;
3455 std::cout<<
" P"<<p2.ID<<
" p2ShowerLike "<<p2ShowerLike;
3456 std::cout<<
" costh "<<costh;
3457 std::cout<<
" doca "<<doca;
3458 std::cout<<
" minSep "<<minSep;
3459 std::cout<<
" allowCluster? "<<allowCluster;
3462 if(!allowCluster)
continue;
3465 for(
auto tid1 : p1.TjIDs) {
3467 for(
auto tid2 : p2.TjIDs) {
3469 if(
t1.CTP !=
t2.CTP)
continue;
3495 std::vector<int> tjids;
3497 if(tj.CTP != inCTP)
continue;
3498 if(tj.AlgMod[
kKilled])
continue;
3504 if(npwc > 100)
continue;
3511 if(tj.ChgRMS > typicalChgRMS) momCut *= tj.ChgRMS / typicalChgRMS;
3512 if(tj.MCSMom > momCut)
continue;
3516 auto TInP =
GetAssns(tjs,
"T", tj.ID,
"P");
3518 auto& pfp = tjs.
pfps[TInP[0] - 1];
3519 if(pfp.PDGCode == 13 &&
MCSMom(tjs, pfp.TjIDs) > 500)
continue;
3522 tjids.push_back(tj.ID);
3525 if(tjids.size() < 2)
return;
3531 unsigned short closePt1;
3532 unsigned short closePt2;
3536 std::vector<ClosePair> cps;
3538 std::vector<int> closeTjs;
3539 for(
unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
3543 for(
unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
3547 if(t1TrackLike && t2TrackLike)
continue;
3548 unsigned short ipt1, ipt2;
3554 if(!T1InP.empty()) {
3556 if(!T2InP.empty()) {
3557 auto& p1 = tjs.
pfps[T1InP[0] - 1];
3558 auto& p2 = tjs.
pfps[T2InP[0] - 1];
3559 unsigned short closePt1, closePt2;
3560 float doca =
PFPDOCA(p1, p2, closePt1, closePt2);
3576 if(std::find(closeTjs.begin(), closeTjs.end(), t1.
ID) == closeTjs.end()) closeTjs.push_back(t1.
ID);
3577 if(std::find(closeTjs.begin(), closeTjs.end(), t2.
ID) == closeTjs.end()) closeTjs.push_back(t2.
ID);
3581 if(cps.empty())
return;
3584 std::vector<SortEntry> sortVec(closeTjs.size());
3585 for(
unsigned short ii = 0; ii < closeTjs.size(); ++ii) {
3586 sortVec[ii].index = ii;
3587 auto& tj = tjs.
allTraj[closeTjs[ii] - 1];
3588 sortVec[ii].length =
PosSep(tj.Pts[tj.EndPt[0]].Pos, tj.Pts[tj.EndPt[1]].Pos);
3590 std::sort(sortVec.begin(), sortVec.end(),
greaterThan);
3595 std::vector<int>
tmp(1);
3596 for(
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
3597 unsigned short indx = sortVec[ii].index;
3598 auto&
t1 = tjs.
allTraj[closeTjs[indx] - 1];
3605 std::vector<int> tlist;
3606 tlist.push_back(
t1.ID);
3611 for(
auto& cp : cps) {
3612 if(cp.used)
continue;
3614 bool isID1 = (std::find(tlist.begin(), tlist.end(), cp.id1) != tlist.end());
3615 bool isID2 = (std::find(tlist.begin(), tlist.end(), cp.id2) != tlist.end());
3616 if(!(isID1 || isID2))
continue;
3618 unsigned short t2id = cp.id1;
3619 if(isID1) t2id = cp.id2;
3626 bool isCloser =
false;
3627 for(
auto& pcp : cps) {
3628 if(
t1.ID == pcp.id1 ||
t1.ID == pcp.id2)
continue;
3629 if(!(
t2.ID == pcp.id1 ||
t2.ID == pcp.id2))
continue;
3630 unsigned short oid = pcp.id1;
3631 if(oid ==
t2.ID) oid = pcp.id2;
3632 auto otj = tjs.
allTraj[oid - 1];
3633 float otjLen =
PosSep(otj.Pts[otj.EndPt[0]].Pos, otj.Pts[otj.EndPt[1]].Pos);
3635 if(pcp.doca < cp.doca && otjLen > 10) isCloser =
true;
3637 if(isCloser)
continue;
3638 if(std::find(tlist.begin(), tlist.end(),
t2.ID) != tlist.end())
continue;
3640 tlist.push_back(
t2.ID);
3646 if(tlist.size() > 1) {
3648 for(
auto tjid : tlist) {
3649 auto& tj = tjs.
allTraj[tjid - 1];
3654 tjLists.push_back(tlist);
3669 if(tjLists.size() < 2)
return;
3671 for(
unsigned short ip = 0; ip < tjLists.size() - 1; ++ip) {
3672 auto& ilist = tjLists[ip];
3673 for(
unsigned short jp = ip + 1; jp < tjLists.size(); ++jp) {
3674 auto& jlist = tjLists[jp];
3677 std::cout<<
"******** FindCots conflict:";
3678 for(
auto tid : sij) std::cout<<
" T"<<tid;
3679 std::cout<<
" appears in multiple lists\n";
3707 if(tjs.
allTraj.size() > 20000)
return;
3714 std::vector<std::vector<int>> tjLists;
3715 std::vector<int> tjids;
3717 if(tj.CTP != inCTP)
continue;
3718 if(tj.AlgMod[
kKilled])
continue;
3722 bool skipit =
false;
3723 for(
unsigned short end = 0;
end < 2; ++
end)
if(tj.StopFlag[
end][
kBragg]) skipit =
true;
3724 if(skipit)
continue;
3730 if(npwc > 100)
continue;
3737 if(tj.ChgRMS > typicalChgRMS) momCut *= tj.ChgRMS / typicalChgRMS;
3738 if(tj.MCSMom > momCut)
continue;
3741 if(npwc < 3)
continue;
3742 if(npwc > 4 && tj.MCSMom > tjs.
ShowerTag[1])
continue;
3744 tjids.push_back(tj.ID);
3747 if(tjids.size() < 2)
return;
3749 for(
unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
3752 for(
unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
3754 unsigned short ipt1, ipt2;
3762 if(len1 < len2 && len1 < doca) {
3763 if(len1 < doca)
continue;
3765 if(len2 < doca)
continue;
3769 bool inlist =
false;
3770 for(
unsigned short it = 0; it < tjLists.size(); ++it) {
3771 bool tj1InList = (std::find(tjLists[it].
begin(), tjLists[it].
end(), tj1.
ID) != tjLists[it].end());
3772 bool tj2InList = (std::find(tjLists[it].
begin(), tjLists[it].
end(), tj2.
ID) != tjLists[it].end());
3773 if(tj1InList || tj2InList) {
3775 if(!tj1InList) tjLists[it].push_back(tj1.
ID);
3776 if(!tj2InList) tjLists[it].push_back(tj2.
ID);
3784 std::vector<int> newlist(2);
3785 newlist[0] = tj1.
ID;
3786 newlist[1] = tj2.
ID;
3787 tjLists.push_back(newlist);
3791 if(tjLists.empty())
return;
3794 unsigned short nsh = 0;
3795 for(
auto& tjl : tjLists) {
3797 for(
auto& tjID : tjl) {
3798 auto& tj = tjs.
allTraj[tjID - 1];
3807 unsigned short nkill = 0;
3808 for(
auto& vx2 : tjs.
vtx) {
3809 if(vx2.ID == 0)
continue;
3810 if(vx2.CTP != inCTP)
continue;
3811 auto TInV2 =
GetAssns(tjs,
"2V", vx2.ID,
"T");
3812 unsigned short nsl = 0;
3813 for(
auto tid : TInV2) {
3814 auto& tj = tjs.
allTraj[tid - 1];
3816 unsigned short nearEnd = 1 -
FarEnd(tjs, tj, vx2.Pos);
3817 if(
PosSep(tj.Pts[tj.EndPt[nearEnd]].Pos, vx2.Pos) < 6) ++nsl;
3820 if(nsl < 2)
continue;
3824 if(tjs.
ShowerTag[12] >= 0)
mf::LogVerbatim(
"TC")<<
"TagShowerLike tagged "<<nsh<<
" Tjs and killed "<<nkill<<
" vertices in CTP "<<inCTP;
3838 std::string fcnLabel = inFcnLabel +
".FNTj";
3840 std::vector<int> ntj;
3843 constexpr
float fiveRadLen = 200;
3846 for(
auto vx : tjs.
vtx) {
3847 if(vx.CTP != ss.
CTP)
continue;
3848 if(vx.ID == 0)
continue;
3851 auto vxTjIDs =
GetAssns(tjs,
"2V", vx.ID,
"T");
3852 for(
auto tjID : vxTjIDs) {
3854 if(std::find(ss.
TjIDs.begin(), ss.
TjIDs.end(), tjID) != ss.
TjIDs.end())
continue;
3856 if(std::find(ntj.begin(), ntj.end(), tjID) != ntj.end())
continue;
3857 ntj.push_back(tjID);
3863 if(tj.CTP != ss.
CTP)
continue;
3864 if(tj.AlgMod[
kKilled])
continue;
3868 if(std::find(ss.
TjIDs.begin(), ss.
TjIDs.end(), tj.ID) != ss.
TjIDs.end())
continue;
3870 if(std::find(ntj.begin(), ntj.end(), tj.ID) != ntj.end())
continue;
3872 if(tj.Pts.size() > 40 && tj.MCSMom > 200) {
3873 float delta =
PointTrajDOCA(tjs, stj.Pts[1].Pos[0], stj.Pts[1].Pos[1], tj.Pts[tj.EndPt[0]]);
3876 float doca = fiveRadLen;
3877 unsigned short spt = 0, ipt = 0;
3879 if(doca < fiveRadLen) {
3880 ntj.push_back(tj.ID);
3886 bool isInside =
false;
3887 for(
unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ipt += 3) {
3895 unsigned short ipt = tj.EndPt[1];
3898 if(isInside) ntj.push_back(tj.ID);
3900 if(ntj.size() > 1) std::sort(ntj.begin(), ntj.end());
3901 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Found "<<ntj.size()<<
" Tjs near ss.ID "<<ss.
ID;
3911 if(itj > tjs.
allTraj.size() - 1)
return;
3916 for(
auto& tp : tjs.
allTraj[itj].Pts) {
3917 for(
unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3919 if(tp.UseHit[ii])
continue;
3920 unsigned int iht = tp.Hits[ii];
3922 if(tjs.
fHits[iht].InTraj <= 0)
continue;
3923 if((
unsigned int)tjs.
fHits[iht].InTraj > tjs.
allTraj.size())
continue;
3926 if(tj.
MCSMom > maxMom)
continue;
3929 if(std::find(list.begin(), list.end(), tjs.
fHits[iht].InTraj) != list.end())
continue;
3930 list.push_back(tjs.
fHits[iht].InTraj);
3939 if(ss.
ID == 0)
return;
3940 if(ss.
TjIDs.empty())
return;
3943 if(stj.
Pts[0].Pos[0] == 0)
return;
3945 std::string fcnLabel = inFcnLabel +
".DE";
3972 float cs = cos(stp1.
Ang);
3973 float sn = sin(stp1.
Ang);
3976 float pos0 = cs * vtx[0] - sn * vtx[1];
3977 float pos1 = sn * vtx[0] + cs * vtx[1];
3979 vtx[0] = pos0 + stp1.
Pos[0];
3980 vtx[1] = pos1 + stp1.
Pos[1];
3986 myprt<<fcnLabel<<
" 2S"<<ss.
ID<<
" Envelope";
4000 if(ss.
Envelope.empty())
return false;
4001 if(ss.
ID == 0)
return false;
4002 if(ss.
TjIDs.empty())
return false;
4004 std::string fcnLabel = inFcnLabel +
".ATIE";
4008 std::vector<int>
tmp(1);
4009 unsigned short nadd = 0;
4011 if(tj.CTP != ss.
CTP)
continue;
4012 if(tj.AlgMod[
kKilled])
continue;
4013 if(tj.SSID > 0)
continue;
4016 if(tj.ParentID == 0)
continue;
4018 if(neutPrimTj > 0 && neutPrimTj != tj.ID) {
4025 if(std::find(ss.
TjIDs.begin(), ss.
TjIDs.end(), tj.ID) != ss.
TjIDs.end())
continue;
4032 if(!end0Inside && !end1Inside)
continue;
4033 if(end0Inside && end1Inside) {
4035 if(
AddTj(fcnLabel, tjs, tj.ID, ss,
false, prt)) ++nadd;
4042 if(tj.MCSMom > 200) {
4043 float tjAngle = tj.Pts[tj.EndPt[0]].Ang;
4045 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" high MCSMom "<<tj.MCSMom<<
" dangPull "<<dangPull;
4046 if(dangPull > 2)
continue;
4048 if(
AddTj(fcnLabel, tjs, tj.ID, ss,
false, prt)) {
4051 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" AddTj failed to add T"<<tj.ID;
4056 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Added "<<nadd<<
" trajectories ";
4061 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" No new trajectories added to envelope ";
4076 if(ss.
Envelope.empty())
return false;
4077 if(ss.
ID == 0)
return false;
4078 if(ss.
TjIDs.empty())
return false;
4081 unsigned short ipl = planeID.
Plane;
4086 std::vector<unsigned int> newHits;
4089 float fLoWire = 1E6;
4095 if(vtx[0] < fLoWire) fLoWire = vtx[0];
4096 if(vtx[0] > fHiWire) fHiWire = vtx[0];
4097 if(vtx[1] < loTick) loTick = vtx[1];
4098 if(vtx[1] > hiTick) hiTick = vtx[1];
4102 unsigned int loWire = std::nearbyint(fLoWire);
4103 unsigned int hiWire = std::nearbyint(fHiWire) + 1;
4105 std::array<float, 2> point;
4106 for(
unsigned int wire = loWire; wire < hiWire; ++wire) {
4109 unsigned int firstHit = (
unsigned int)tjs.
WireHitRange[ipl][wire].first;
4110 unsigned int lastHit = (
unsigned int)tjs.
WireHitRange[ipl][wire].second;
4111 for(
unsigned int iht = firstHit; iht < lastHit; ++iht) {
4113 if(tjs.
fHits[iht].InTraj != 0)
continue;
4115 if(tjs.
fHits[iht].PeakTime < loTick)
continue;
4117 if(tjs.
fHits[iht].PeakTime > hiTick)
break;
4119 point[0] = tjs.
fHits[iht].ArtPtr->WireID().Wire;
4122 newHits.push_back(iht);
4127 if(newHits.empty()) {
4133 stp0.
Hits.insert(stp0.
Hits.end(), newHits.begin(), newHits.end());
4134 for(
auto& iht: newHits) tjs.
fHits[iht].InTraj = stj.
ID;
4146 if(cotID > (
int)tjs.
cots.size())
return;
4149 if(ss.
ID == 0)
return;
4150 if(ss.
TjIDs.empty())
return;
4155 std::string fcnLabel = inFcnLabel +
".FSC";
4166 if(schg.empty())
return;
4170 unsigned short startPt = USHRT_MAX;
4172 for(
unsigned short ii = 0; ii < schg.size() - 1; ++ii) {
4173 if(schg[ii] > 0 && schg[ii + 1] > 0) {
4179 if(startPt == USHRT_MAX)
return;
4185 for(
unsigned short ii = startPt; ii < schg.size() - 1; ++ii) {
4187 rms += schg[ii] * schg[ii];
4191 rms = rms - cnt * ave * ave;
4193 rms = sqrt(rms / (cnt - 1));
4197 myprt<<fcnLabel<<
" schg:";
4198 for(
unsigned short ii = 0; ii < 20; ++ii) myprt<<
" "<<(
int)schg[ii];
4199 myprt<<
"\n First guess at the charge "<<(int)chg<<
" average charge of all bins "<<(
int)ave<<
" rms "<<(int)rms;
4208 unsigned short nBinsAverage = 5;
4209 double maxChg = 2 * chg;
4210 for(
unsigned short nit = 0; nit < 2; ++nit) {
4214 for(
unsigned short ii = startPt; ii < schg.size() - 1; ++ii) {
4216 if(schg[ii] > maxChg && schg[ii + 1] > maxChg)
break;
4218 if(schg[ii] == 0 && schg[ii + 1] == 0)
break;
4219 if(schg[ii] > maxChg)
continue;
4221 sum2 += schg[ii] * schg[ii];
4223 if(cnt == nBinsAverage)
break;
4227 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" nit "<<nit<<
" cnt "<<cnt<<
" is too low. sum "<<(int)sum<<
" maxChg "<<(
int)maxChg;
4230 chg = schg[startPt];
4236 double arg = sum2 - cnt * chg * chg;
4238 rms = sqrt(arg / (cnt - 1));
4240 double maxrms = 0.5 * sum;
4241 if(rms > maxrms) rms = maxrms;
4242 maxChg = chg + 2 * rms;
4243 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" nit "<<nit<<
" cnt "<<cnt<<
" chg "<<(int)chg<<
" rms "<<(
int)rms<<
" maxChg "<<(int)maxChg<<
" nBinsAverage "<<nBinsAverage;
4249 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 2S"<<cotID<<
" Starting charge "<<(int)stp0.AveChg<<
" startPt "<<startPt;
4259 constexpr
unsigned short nbins = 20;
4260 std::vector<float> schg(nbins);
4261 if(ss.
ID == 0)
return schg;
4262 if(ss.
TjIDs.empty())
return schg;
4267 float minAlong = ss.
ShPts[0].RotPos[0] - 2;
4272 float cs = cos(-ss.
Angle);
4273 float sn = sin(-ss.
Angle);
4274 std::array<float, 2> chgPos;
4277 for(
auto& sspt : ss.
ShPts) {
4278 unsigned short indx = (
unsigned short)((sspt.RotPos[0] - minAlong));
4279 if(indx > nbins - 1)
break;
4281 if(std::abs(sspt.RotPos[1]) > maxTrans)
continue;
4282 unsigned int iht = sspt.HitIndex;
4283 float& peakTime = tjs.
fHits[iht].PeakTime;
4284 float& amp = tjs.
fHits[iht].PeakAmplitude;
4285 float& rms = tjs.
fHits[iht].RMS;
4286 chgPos[0] = tjs.
fHits[iht].ArtPtr->WireID().Wire - stp1.
Pos[0];
4287 for(
float time = peakTime - 2.5 * rms; time < peakTime + 2.5 * rms; ++time) {
4289 along = cs * chgPos[0] - sn * chgPos[1];
4290 if(along < minAlong)
continue;
4291 indx = (
unsigned short)(along - minAlong);
4292 if(indx > nbins - 1)
continue;
4293 arg = (time - peakTime) / rms;
4294 schg[indx] += amp * exp(-0.5 * arg * arg);
4308 if(cotID > (
int)tjs.
cots.size())
return;
4311 if(ss.
ID == 0)
return;
4312 if(ss.
TjIDs.empty())
return;
4313 std::cout<<
"PTS Pos0 Pos1 RPos0 RPos1 Chg TID\n";
4315 std::cout<<
"PTS "<<std::fixed<<std::setprecision(1)<<
pt.Pos[0]<<
" "<<
pt.Pos[1]<<
" "<<
pt.RotPos[0]<<
" "<<
pt.RotPos[1];
4316 std::cout<<
" "<<(int)
pt.Chg<<
" "<<
pt.TID;
4387 bool newShowers =
false;
4388 for(
auto&
ss : tjs.
cots) {
4389 if(
ss.ID == 0)
continue;
4390 if(
ss.ShowerTjID == 0)
continue;
4393 if(!stj.
Pts[1].Hits.empty()) {
4394 std::cout<<
"TTjH: ShowerTj T"<<stj.
ID<<
" already has "<<stj.
Pts[1].Hits.size()<<
" hits\n";
4398 for(
auto& tjID :
ss.TjIDs) {
4399 unsigned short itj = tjID - 1;
4401 std::cout<<
"TTjH: Coding error. T"<<tjID<<
" is a ShowerTj but is in TjIDs\n";
4404 if(tjs.
allTraj[itj].SSID <= 0) {
4405 std::cout<<
"TTjH: Coding error. Trying to transfer T"<<tjID<<
" hits but it isn't an InShower Tj\n";
4410 stj.
Pts[1].Hits.insert(stj.
Pts[1].Hits.end(), thits.begin(), thits.end());
4415 for(
auto& iht : stj.
Pts[1].Hits) tjs.
fHits[iht].InTraj = stj.
ID;
4426 for(
unsigned short ii = 0; ii < tjs.
cots.size(); ++ii) {
4427 if(ShowerTjID == tjs.
cots[ii].ShowerTjID)
return ii + 1;
4436 if(ss3.
ID == 0)
return 0;
4437 if(ss3.
Energy.empty())
return 0;
4442 ave /= ss3.
Energy.size();
4450 if(tjIDs.empty())
return 0;
4452 for(
auto tid : tjIDs) {
4453 auto& tj = tjs.
allTraj[tid - 1];
4473 std::string fcnLabel = inFcnLabel +
".S3S";
4475 std::cout<<fcnLabel<<
" Invalid ID";
4478 if(ss3.
CotIDs.size() < 2) {
4479 std::cout<<fcnLabel<<
" not enough CotIDs";
4484 for(
auto&
ss : tjs.
cots) {
4485 if(
ss.ID == 0)
continue;
4487 std::cout<<fcnLabel<<
" Bad assn: 2S"<<
ss.ID<<
" -> 3S"<<ss3.
ID<<
" but it's not inCotIDs.\n";
4493 for(
auto cid : ss3.
CotIDs) {
4494 if(cid <= 0 || cid > (
int)tjs.
cots.size())
return false;
4495 auto&
ss = tjs.
cots[cid - 1];
4496 if(
ss.SS3ID > 0 &&
ss.SS3ID != ss3.
ID) {
4497 std::cout<<fcnLabel<<
" Bad assn: 3S"<<ss3.
ID<<
" -> 2S"<<cid<<
" but 2S -> 3S"<<
ss.SS3ID<<
"\n";
4503 for(
auto cid : ss3.
CotIDs) tjs.
cots[cid - 1].SS3ID = ss3.
ID;
4514 std::string fcnLabel = inFcnLabel +
".S2S";
4516 std::cout<<fcnLabel<<
" Invalid ID";
4520 std::cout<<fcnLabel<<
" Fail: No TjIDs in 2S"<<ss.
ID<<
"\n";
4525 std::cout<<fcnLabel<<
" Fail: 2S"<<ss.
ID<<
" has an invalid ParentID T"<<ss.
ParentID<<
"\n";
4529 std::cout<<fcnLabel<<
" Fail: 2S"<<ss.
ID<<
" ParentID is not in TjIDs.\n";
4535 if(ss.
ID != (
int)tjs.
cots.size() + 1) {
4536 std::cout<<fcnLabel<<
" Correcting the ID 2S"<<ss.
ID<<
" -> 2S"<<tjs.
cots.size() + 1;
4537 ss.
ID = tjs.
cots.size() + 1;
4541 for(
auto& tjID : ss.
TjIDs) {
4547 tjs.
cots.push_back(ss);
4579 if(tjl.empty()) ss.
Cheat =
true;
4586 stj.CTP = tjs.
allTraj[tjl[0]-1].CTP;
4590 for(
auto& stp : stj.Pts) {
4597 stj.ID = tjs.
allTraj.size() + 1;
4605 ss.
ID = tjs.
cots.size() + 1;
4610 for(
auto tjid : tjl) {
4611 auto& tj = tjs.
allTraj[tjid - 1];
4612 if(tj.CTP != stj.CTP) {
4629 std::string fcnLabel = inFcnLabel +
".ChkAssns";
4630 for(
auto&
ss : tjs.
cots) {
4631 if(
ss.ID == 0)
continue;
4632 for(
auto tid :
ss.TjIDs) {
4633 auto& tj = tjs.
allTraj[tid - 1];
4634 if(tj.SSID !=
ss.ID) {
4635 std::cout<<fcnLabel<<
" ***** Error: 2S"<<
ss.ID<<
" -> TjIDs T"<<tid<<
" != tj.SSID 2S"<<tj.SSID<<
"\n";
4640 if(
ss.SS3ID > 0 &&
ss.SS3ID <= (
int)tjs.
showers.size()) {
4642 if(std::find(ss3.CotIDs.begin(), ss3.CotIDs.end(),
ss.ID) == ss3.CotIDs.end()) {
4643 std::cout<<fcnLabel<<
" ***** Error: 2S"<<
ss.ID<<
" -> 3S"<<
ss.SS3ID<<
" but the shower says no\n";
4649 if(tj.AlgMod[
kKilled])
continue;
4651 std::cout<<fcnLabel<<
" ***** Error: T"<<tj.ID<<
" tj.SSID is fubar\n";
4655 if(tj.SSID == 0)
continue;
4656 auto&
ss = tjs.
cots[tj.SSID - 1];
4657 if(std::find(
ss.TjIDs.begin(),
ss.TjIDs.end(), tj.ID) !=
ss.TjIDs.end())
continue;
4658 std::cout<<fcnLabel<<
" ***** Error: T"<<tj.ID<<
" tj.SSID = 2S"<<tj.SSID<<
" but the shower says no\n";
4662 for(
auto& ss3 : tjs.
showers) {
4663 if(ss3.ID == 0)
continue;
4664 for(
auto cid : ss3.CotIDs) {
4665 auto&
ss = tjs.
cots[cid - 1];
4666 if(
ss.SS3ID != ss3.ID) {
4667 std::cout<<fcnLabel<<
" ***** Error: 3S"<<ss3.ID<<
" -> 2S"<<cid<<
" but it thinks it belongs to 3S"<<
ss.SS3ID<<
"\n";
4678 if(tjs.
showers.empty())
return;
4680 myprt<<fcnLabel<<
" 3D showers \n";
4681 for(
auto& ss3 : tjs.
showers) {
4682 myprt<<fcnLabel<<
" 3S"<<ss3.ID<<
" 3V"<<ss3.Vx3ID;
4683 myprt<<
" parentID "<<ss3.ParentID;
4684 myprt<<
" ChgPos"<<std::fixed;
4685 for(
unsigned short xyz = 0; xyz < 3; ++xyz) myprt<<
" "<<std::setprecision(0)<<ss3.ChgPos[xyz];
4687 for(
unsigned short xyz = 0; xyz < 3; ++xyz) myprt<<
" "<<std::setprecision(2)<<ss3.Dir[xyz];
4688 myprt<<
" posInPlane";
4689 std::vector<float> projInPlane(tjs.
NumPlanes);
4690 for(
unsigned short plane = 0; plane < tjs.
NumPlanes; ++plane) {
4691 CTP_t inCTP =
EncodeCTP(ss3.TPCID.Cryostat, ss3.TPCID.TPC, plane);
4692 auto tp =
MakeBareTP(tjs, ss3.ChgPos, ss3.Dir, inCTP);
4694 projInPlane[plane] = tp.Delta;
4696 myprt<<
" projInPlane";
4697 for(
unsigned short plane = 0; plane < tjs.
NumPlanes; ++plane) {
4698 myprt<<
" "<<std::fixed<<std::setprecision(2)<<projInPlane[plane];
4700 for(
auto cid : ss3.CotIDs) {
4701 auto&
ss = tjs.
cots[cid - 1];
4702 myprt<<
"\n 2S"<<
ss.ID;
4703 auto& stj = tjs.
allTraj[
ss.ShowerTjID - 1];
4704 myprt<<
" ST"<<stj.ID;
4705 myprt<<
" "<<
PrintPos(tjs, stj.Pts[stj.EndPt[0]].Pos)<<
" - "<<
PrintPos(tjs, stj.Pts[stj.EndPt[1]].Pos);
4707 if(ss3.NeedsUpdate) myprt<<
" *** Needs update";
4716 if(tjs.
cots.empty())
return;
4721 bool printAllCTP = (inCTP == USHRT_MAX);
4723 unsigned short nlines = 0;
4724 for(
const auto&
ss : tjs.
cots) {
4725 if(!printAllCTP &&
ss.CTP != inCTP)
continue;
4726 if(!printKilledShowers &&
ss.ID == 0)
continue;
4730 myprt<<someText<<
" Print2DShowers: Nothing to print";
4735 bool printHeader =
true;
4736 bool printExtras =
false;
4737 for(
unsigned short ict = 0; ict < tjs.
cots.size(); ++ict) {
4738 const auto&
ss = tjs.
cots[ict];
4739 if(!printAllCTP &&
ss.CTP != inCTP)
continue;
4740 if(!printKilledShowers &&
ss.ID == 0)
continue;
4742 printHeader =
false;
4746 for(
unsigned short ict = 0; ict < tjs.
cots.size(); ++ict) {
4747 const auto&
ss = tjs.
cots[ict];
4748 if(!printAllCTP &&
ss.CTP != inCTP)
continue;
4749 if(!printKilledShowers &&
ss.ID == 0)
continue;
4750 myprt<<someText<<std::fixed;
4752 myprt<<std::setw(5)<<sid;
4754 for(
auto id :
ss.TjIDs) myprt<<
" T"<<id;
4760 for(
unsigned short ict = 0; ict < tjs.
cots.size(); ++ict) {
4761 const auto&
ss = tjs.
cots[ict];
4762 if(!printAllCTP &&
ss.CTP != inCTP)
continue;
4763 if(!printKilledShowers &&
ss.ID == 0)
continue;
4764 myprt<<someText<<std::fixed;
4766 myprt<<std::setw(5)<<sid;
4768 for(
auto& vtx :
ss.Envelope) myprt<<
" "<<(int)vtx[0]<<
":"<<(
int)(vtx[1]/tjs.
UnitsPerTick);
4772 for(
unsigned short ict = 0; ict < tjs.
cots.size(); ++ict) {
4773 const auto&
ss = tjs.
cots[ict];
4774 if(!printAllCTP &&
ss.CTP != inCTP)
continue;
4775 if(!printKilledShowers &&
ss.ID == 0)
continue;
4776 myprt<<someText<<std::fixed;
4778 myprt<<std::setw(5)<<sid;
4780 for(
auto id :
ss.NearTjIDs) myprt<<
" T"<<id;
4784 myprt<<
"DontCluster";
4786 if(dc.TjIDs[0] > 0) myprt<<
" T"<<dc.TjIDs[0]<<
"-T"<<dc.TjIDs[1];
4788 myprt<<
"\nDontCluster";
4789 for(
unsigned short ict = 0; ict < tjs.
cots.size(); ++ict) {
4790 const auto& iss = tjs.
cots[ict];
4791 if(iss.ID == 0)
continue;
4792 for(
unsigned short jct = ict + 1; jct < tjs.
cots.size(); ++jct) {
4793 const auto& jss = tjs.
cots[jct];
4794 if(jss.ID == 0)
continue;
4795 if(
DontCluster(tjs, iss.TjIDs, jss.TjIDs)) myprt<<
" 2S"<<iss.ID<<
"-2S"<<jss.ID;
4807 myprt<<someText<<
" ID CTP ParID ParFOM TruParID Energy nTjs dFOM AspRat stj vx0 __Pos0___ Chg(k) dRMS __Pos1___ Chg(k) dRMS __Pos2___ Chg(k) dRMS Angle SS3ID PFPID\n";
4810 myprt<<someText<<std::fixed;
4812 myprt<<std::setw(5)<<sid;
4813 myprt<<std::setw(6)<<ss.
CTP;
4816 myprt<<std::setw(7)<<sid;
4817 myprt<<std::setw(7)<<std::setprecision(2)<<ss.
ParentFOM;
4819 myprt<<std::setw(7)<<(int)ss.
Energy;
4820 myprt<<std::setw(5)<<ss.
TjIDs.size();
4821 myprt<<std::setw(6)<<std::setprecision(2)<<ss.
DirectionFOM;
4822 myprt<<std::setw(7)<<std::setprecision(2)<<ss.
AspectRatio;
4825 myprt<<std::setw(5)<<tid;
4826 std::string vid =
"NA";
4828 myprt<<std::setw(5)<<vid;
4829 for(
auto& spt : stj.Pts) {
4830 myprt<<std::setw(10)<<
PrintPos(tjs, spt.Pos);
4831 myprt<<std::setw(7)<<std::fixed<<std::setprecision(1)<<spt.Chg/1000;
4833 myprt<<std::setw(5)<<std::setprecision(1)<<spt.DeltaRMS;
4835 myprt<<std::setw(6)<<std::setprecision(2)<<stj.Pts[1].Ang;
4836 std::string sss =
"NA";
4838 myprt<<std::setw(6)<<sss;
4841 if(ss3.PFPIndex >= 0 && ss3.PFPIndex < tjs.
pfps.size()) {
4843 myprt<<std::setw(6)<<pid;
4845 myprt<<std::setw(6)<<
"NA";
4848 myprt<<std::setw(6)<<
"NA";
4852 if(!printExtras)
return;
4855 myprt<<someText<<std::fixed;
4857 myprt<<std::setw(5)<<sid;
4859 for(
auto id : ss.
TjIDs) myprt<<
" T"<<id;
4861 myprt<<someText<<std::fixed;
4863 myprt<<std::setw(5)<<sid;
4867 myprt<<someText<<std::fixed;
4869 myprt<<std::setw(5)<<sid;
4871 for(
auto id : ss.
NearTjIDs) myprt<<
" T"<<id;
bool TransferTjHits(TjStuff &tjs, bool prt)
bool FindParent(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float ParentFOM(std::string inFcnLabel, TjStuff &tjs, Trajectory &tj, unsigned short &tjEnd, ShowerStruct &ss, float &tp1Sep, float &vx2Score, bool prt)
void MakeShowerObsolete(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
bool AddPFP(std::string inFcnLabel, TjStuff &tjs, int pID, ShowerStruct3D &ss3, bool doUpdate, bool prt)
void MergeShowerChain(std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, bool prt)
bool AddTjsInsideEnvelope(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
void MergeOverlap(std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, bool prt)
bool AddTj(std::string inFcnLabel, TjStuff &tjs, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
bool greaterThan(SortEntry c1, SortEntry c2)
std::vector< float > ChargeCuts
void MergeNearby2DShowers(std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, bool prt)
bool MergeShowersAndStore(std::string inFcnLabel, TjStuff &tjs, int icotID, int jcotID, bool prt)
struct of temporary 2D vertices (end points)
void Print2DShowers(std::string someText, const TjStuff &tjs, CTP_t inCTP, bool printKilledShowers)
std::vector< double > dEdxErr
double InShowerProbLong(double showerEnergy, double along)
std::vector< float > StartChgVec(TjStuff &tjs, int cotID, bool prt)
bool RemovePFP(std::string inFcnLabel, TjStuff &tjs, PFPStruct &pfp, ShowerStruct3D &ss3, bool doUpdate, bool prt)
std::vector< int > NearTjIDs
std::array< double, 3 > Point3_t
std::bitset< 64 > AlgMod
Bit set if algorithm AlgBit_t modifed the trajectory.
std::array< int, 2 > TjIDs
std::vector< Point2_t > Envelope
void PrintAllTraj(std::string someText, const TjStuff &tjs, const DebugStuff &debug, unsigned short itj, unsigned short ipt, bool prtVtx)
unsigned int Nplanes() const
Number of planes in this tpc.
std::vector< float > ShowerParentVars
std::vector< unsigned int > PutTrajHitsInVector(Trajectory const &tj, HitStatus_t hitRequest)
bool ChkAssns(std::string inFcnLabel, TjStuff &tjs)
float ChgFracBetween(TjStuff &tjs, Point3_t pos1, Point3_t pos2, geo::TPCID tpcid)
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
float PFPDOCA(const PFPStruct &pfp1, const PFPStruct &pfp2, unsigned short &close1, unsigned short &close2)
The data type to uniquely identify a Plane.
Geometry information for a single TPC.
std::vector< PFPStruct > pfps
std::vector< unsigned int > Hits
std::vector< double > MIPEnergy
void ConfigureMVA(TjStuff &tjs, std::string fMVAShowerParentWeights)
CryostatID_t Cryostat
Index of cryostat.
std::vector< ShowerStruct3D > showers
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
bool SetParent(std::string inFcnLabel, TjStuff &tjs, PFPStruct &pfp, ShowerStruct3D &ss3, bool prt)
bool MakeTp3(TjStuff &tjs, const TrajPoint &itp, const TrajPoint &jtp, TrajPoint3 &tp3, bool findDirection)
void KillVerticesInShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
std::array< int, 2 > Vx3ID
std::vector< int > CotIDs
bool FindShowerStart(TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
std::array< double, 2 > Dir
double InShowerProbTrans(double showerEnergy, double along, double trans)
std::vector< ShowerPoint > ShPts
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
unsigned short FarEnd(const TjStuff &tjs, const PFPStruct &pfp, const Point3_t &pos)
void MergeTjList(std::vector< std::vector< int >> &tjList)
double InShowerProbParam(double showerEnergy, double along, double trans)
double ShowerParamTransRMS(double showerEnergy, double along)
TMVA::Reader * ShowerParentReader
void ReverseTraj(TjStuff &tjs, Trajectory &tj)
bool IsShowerLike(const TjStuff &tjs, const std::vector< int > TjIDs)
bool WrongSplitTj(std::string inFcnLabel, TjStuff &tjs, Trajectory &tj, unsigned short tjEnd, ShowerStruct &ss, bool prt)
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
std::vector< ShowerStruct > cots
std::vector< float > ShowerTag
[min MCSMom, max separation, min # Tj < separation] for a shower tag
void DefineEnvelope(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
bool Reconcile3D(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
bool RemoveTj(std::string inFcnLabel, TjStuff &tjs, int TjID, ShowerStruct &ss, bool doUpdate, bool prt)
void FindCots(std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, std::vector< std::vector< int >> &tjLists, bool prt)
bool MakeVertexObsolete(TjStuff &tjs, VtxStore &vx2, bool forceKill)
std::array< float, 2 > Point2_t
std::array< Point3_t, 2 > XYZ
const geo::GeometryCore * geom
void MergeSubShowers(std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, bool prt)
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
CTP_t CTP
Cryostat, TPC, Plane code.
std::vector< unsigned int > LastWire
the last wire with a hit
std::vector< VtxStore > vtx
2D vertices
std::vector< TrajPoint > Pts
Trajectory points.
PFPStruct CreateFakePFP(const TjStuff &tjs, const ShowerStruct3D &ss3)
TrajPoint MakeBareTP(TjStuff &tjs, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
std::vector< evd::details::RawDigitInfo_t >::const_iterator begin(RawDigitCacheDataClass const &cache)
std::array< Vector3_t, 2 > Dir
std::vector< Trajectory > allTraj
vector of all trajectories in each plane
std::bitset< 64 > UseAlg
Allow user to mask off specific algorithms.
std::array< unsigned short, 2 > EndPt
First and last point in the trajectory that has charge.
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
void SaveTjInfo(TjStuff &tjs, std::vector< std::vector< int >> &tjList, std::string stageName)
bool MakeBareTrajPoint(const TjStuff &tjs, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
float UnitsPerTick
scale factor from Tick to WSE equivalent units
void DefineDontCluster(TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
int GetCotID(TjStuff &tjs, int ShowerTjID)
void PrintShower(std::string someText, const TjStuff &tjs, const ShowerStruct &ss, bool printHeader, bool printExtras)
The data type to uniquely identify a TPC.
bool DontCluster(const TjStuff &tjs, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
PlaneID_t Plane
Index of the plane within its TPC.
bool SetMag(Vector3_t &v1, double mag)
float ShowerEnergy(const TjStuff &tjs, const std::vector< int > tjIDs)
float PointTrajDOCA(TjStuff const &tjs, unsigned int iht, TrajPoint const &tp)
std::array< unsigned short, 2 > VtxID
ID of 2D vertex.
bool lessThan(SortEntry c1, SortEntry c2)
short MCSMom(const TjStuff &tjs, const std::vector< int > &tjIDs)
std::vector< DontClusterStruct > dontCluster
std::vector< Vtx3Store > vtx3
3D vertices
float ChgFracNearPos(TjStuff &tjs, const Point2_t &pos, const std::vector< int > &tjIDs)
bool MergeShowerTjsAndStore(TjStuff &tjs, unsigned short istj, unsigned short jstj, bool prt)
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
ShowerStruct3D CreateSS3(TjStuff &tjs, const geo::TPCID &tpcid)
std::vector< double > EnergyErr
std::vector< double > MIPEnergyErr
void SaveAllCots(TjStuff &tjs, const CTP_t &inCTP, std::string someText)
float Match3DFOM(std::string inFcnLabel, TjStuff &tjs, int icid, int jcid, bool prt)
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
void FindNearbyTjs(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
std::vector< std::vector< std::pair< int, int > > > WireHitRange
int NeutrinoPrimaryTjID(const TjStuff &tjs, const Trajectory &tj)
bool FillWireHitRange(TjStuff &tjs, const geo::TPCID &tpcid)
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
std::vector< TCHit > fHits
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
PFPStruct CreatePFP(const TjStuff &tjs, const geo::TPCID &tpcid)
void PrintShowers(std::string fcnLabel, TjStuff &tjs)
bool StoreShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss)
std::vector< double > Energy
geo::PlaneID DecodeCTP(CTP_t CTP)
void DumpShowerPts(TjStuff &tjs, int cotID)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
unsigned short NumPtsWithCharge(const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires)
bool AddLooseHits(TjStuff &tjs, int cotID, bool prt)
std::vector< simb::MCParticle * > MCPartList
void Finish3DShowers(TjStuff &tjs)
std::array< double, 3 > Vector3_t
ShowerStruct CreateSS(TjStuff &tjs, CTP_t inCTP, const std::vector< int > &tjl)
std::vector< T > SetDifference(const std::vector< T > &set1, const std::vector< T > &set2)
bool CompleteIncompleteShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void MakeTrajectoryObsolete(TjStuff &tjs, unsigned int itj)
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
int SSID
ID of a 2D shower struct that this tj is in.
void PrintPFPs(std::string someText, const TjStuff &tjs)
float InShowerProb(const TjStuff &tjs, const ShowerStruct &ss, const Trajectory &tj)
float ChgToMeV(float chg)
void Match2DShowers(std::string inFcnLabel, TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
TPCID_t TPC
Index of the TPC within its cryostat.
bool TrajTrajDOCA(const TjStuff &tjs, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
std::vector< double > dEdx
int MergeShowers(std::string inFcnLabel, TjStuff &tjs, std::vector< int > ssIDs, bool prt)
void MergeSubShowersTj(std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, bool prt)
bool AnalyzeRotPos(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
void FindStartChg(std::string inFcnLabel, TjStuff &tjs, int cotID, bool prt)
bool DebugMode
print additional info when in debug mode
std::vector< int > GetAssns(const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
bool FindShowers3D(TjStuff &tjs, const geo::TPCID &tpcid)
bool UpdateShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
void ReverseShower(std::string inFcnLabel, TjStuff &tjs, int cotID, bool prt)
void TagShowerLike(std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP)
void AddCloseTjsToList(TjStuff &tjs, unsigned short itj, std::vector< int > list)
const detinfo::DetectorProperties * detprop