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 = slc.
cots[cid - 1];
70 auto& stj = slc.
tjs[
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 = slc.
cots[useCID - 1];
99 auto& stj = slc.
tjs[
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];
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];
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.PFPIndex != USHRT_MAX) {
155 std::cout<<
"Finish3DShowers 3S"<<ss3.ID<<
" already has a pfp associated with it...\n";
159 showerPFP.TjIDs.resize(ss3.CotIDs.size());
160 for(
unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) {
161 unsigned short cid = ss3.CotIDs[ii];
162 if(cid == 0 || cid > slc.
cots.size()) {
163 std::cout<<
"Finish3DShowers 3S"<<ss3.ID<<
" has an invalid cots ID"<<cid<<
"\n";
166 auto&
ss = slc.
cots[cid - 1];
167 auto& stj = slc.
tjs[
ss.ShowerTjID - 1];
168 showerPFP.TjIDs[ii] = stj.ID;
170 showerPFP.PDGCode = 1111;
171 showerPFP.XYZ[0] = ss3.Start;
172 showerPFP.Dir[0] = ss3.Dir;
173 showerPFP.DirErr[0] = ss3.DirErr;
174 showerPFP.Vx3ID[0] = ss3.Vx3ID;
175 showerPFP.XYZ[1] = ss3.End;
176 showerPFP.Dir[1] = ss3.Dir;
178 for(
auto cid : ss3.CotIDs) {
179 auto&
ss = slc.
cots[cid - 1];
181 auto& stj = slc.
tjs[
ss.ShowerTjID - 1];
182 showerPFP.dEdx[0][plane] = stj.dEdx[0];
183 showerPFP.dEdxErr[0][plane] = 0.3 * stj.dEdx[0];
185 ss3.PFPIndex = slc.
pfps.size();
186 if(ss3.ParentID > 0) {
188 auto& dtrPFP = slc.
pfps[ss3.ParentID - 1];
189 if(dtrPFP.ParentUID > 0) {
192 auto& parPFP =
slices[slcIndx.first].pfps[slcIndx.second];
193 showerPFP.ParentUID = parPFP.UID;
194 std::replace(parPFP.DtrUIDs.begin(), parPFP.DtrUIDs.end(), dtrPFP.UID, showerPFP.UID);
195 dtrPFP.ParentUID = 0;
198 slc.
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 = slc.
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 = slc.
vtx3s[vx2.Vx3ID - 1];
227 if(vx3.Neutrino)
continue;
235 if(!slc.
pfps.empty()) {
236 for(
auto& pfp : slc.
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 = slc.
tjs[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 = slc.
tjs[tid - 1];
249 std::cout<<
" T"<<tid<<
" dead? "<<tj.AlgMod[
kKilled];
258 for(
auto& vx2 : slc.
vtxs) {
259 if(vx2.ID == 0)
continue;
260 auto vxtjs =
GetAssns(slc,
"2V", vx2.
ID,
"T");
261 if(vxtjs.empty()) vx2.ID = 0;
265 for(
auto& vx3 : slc.
vtx3s) {
266 if(vx3.ID == 0)
continue;
267 auto vxtjs =
GetAssns(slc,
"3V", vx3.
ID,
"T");
275 for(
auto& pfp : slc.
pfps) {
276 if(pfp.ID == 0)
continue;
277 if(pfp.PDGCode != 1111)
continue;
278 if(pfp.Vx3ID[0] > 0 && slc.
vtx3s[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;
297 std::string fcnLabel =
"FS";
301 for(
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane) {
303 for(
auto&
ss : slc.
cots)
if(
ss.CTP == inCTP)
return false;
316 std::vector<std::vector<std::vector<int>>> bigList(slc.
nPlanes);
317 for(
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane) {
319 std::vector<std::vector<int>> tjList;
321 FindCots(fcnLabel, slc, inCTP, tjList, prt2S);
323 if(tjList.empty())
continue;
324 bigList[plane] = tjList;
326 unsigned short nPlanesWithShowers = 0;
327 for(
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane)
if(!bigList.empty()) ++nPlanesWithShowers;
328 if(nPlanesWithShowers < 2)
return false;
329 for(
unsigned short plane = 0; plane < TPC.
Nplanes(); ++plane) {
332 bool prtCTP = (prt2S && inCTP ==
debug.
CTP);
334 for(
auto& tjl : bigList[plane]) {
335 if(tjl.empty())
continue;
338 myprt<<
"Plane "<<plane<<
" tjList";
339 for(
auto& tjID : tjl) myprt<<
" "<<tjID;
342 if(
ss.ID == 0)
continue;
348 std::cout<<fcnLabel<<
" StoreShower failed 2S"<<
ss.ID<<
"\n";
354 if(inCTP == UINT_MAX)
continue;
355 if(slc.
cots.empty())
continue;
371 bool tryMerge =
false;
372 for(
unsigned short ii = 0; ii < slc.
cots.size(); ++ii) {
374 if(
ss.ID == 0)
continue;
375 if(
ss.CTP != inCTP)
continue;
383 if(slc.
cots.empty())
return false;
393 if(ss3.ID == 0)
continue;
403 if(ss3.ID == 0)
continue;
409 for(
auto&
ss : slc.
cots) {
410 if(
ss.ID == 0)
continue;
411 if(
ss.SS3ID > 0)
continue;
418 unsigned short nNewShowers = 0;
419 for(
auto&
ss : slc.
cots) {
420 if(
ss.ID == 0)
continue;
421 if(
ss.TjIDs.empty())
continue;
426 return (nNewShowers > 0);
435 std::string fcnLabel = inFcnLabel +
".R3D2";
441 for(
unsigned short ii = 0; ii < slc.
showers.size() - 1; ++ii) {
443 if(iss3.ID == 0)
continue;
444 auto iPInSS3 =
GetAssns(slc,
"3S", iss3.
ID,
"P");
447 myprt<<fcnLabel<<
" 3S"<<iss3.ID<<
" ->";
448 for(
auto pid : iPInSS3) myprt<<
" P"<<
pid;
450 for(
unsigned short jj = ii + 1; jj < slc.
showers.size(); ++jj) {
452 if(jss3.ID == 0)
continue;
453 auto jPInSS3 =
GetAssns(slc,
"3S", jss3.
ID,
"P");
455 if(shared.empty())
continue;
458 myprt<<fcnLabel<<
" Conflict i3S"<<iss3.ID<<
" and j3S"<<jss3.ID<<
" share";
459 for(
auto pid : shared) myprt<<
" P"<<
pid;
462 for(
auto pid : shared) {
466 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" i3S"<<iss3.ID<<
" prob "<<std::setprecision(3)<<iProb<<
" j3S"<<jss3.ID<<
" prob "<<jProb;
469 RemovePFP(fcnLabel, slc, pfp, jss3,
true, prt);
471 AddPFP(fcnLabel, slc, pfp.
ID, iss3,
true, prt);
473 RemovePFP(fcnLabel, slc, pfp, iss3,
true, prt);
474 AddPFP(fcnLabel, slc, pfp.
ID, jss3,
true, prt);
483 if(parentSearchDone) {
485 if(ss3.ID == 0)
continue;
486 auto PIn3S =
GetAssns(slc,
"3S", ss3.
ID,
"P");
487 for(
auto pid : PIn3S) {
488 if(
pid == ss3.ParentID)
continue;
490 for(
unsigned short end = 0;
end < 2; ++
end) {
491 if(pfp.Vx3ID[
end] <= 0)
continue;
494 myprt<<fcnLabel<<
" Detach 3S"<<ss3.ID<<
" -> P"<<pfp.ID<<
"_"<<
end<<
" -> 3V"<<pfp.Vx3ID[
end];
495 if(pfp.ParentUID > 0) myprt<<
" ->Parent P"<<pfp.ParentUID;
499 if(pfp.ParentUID > 0) {
501 auto& parentPFP =
slices[slcIndx.first].pfps[slcIndx.second];
502 std::vector<int> newDtrUIDs;
503 for(
auto did : parentPFP.DtrUIDs)
if(did != pfp.UID) newDtrUIDs.push_back(did);
504 parentPFP.DtrUIDs = newDtrUIDs;
513 for(
auto&
ss : slc.
cots) {
514 if(
ss.ID == 0)
continue;
515 if(
ss.SS3ID > 0)
continue;
516 std::vector<int> matchedTjs;
517 for(
auto tid :
ss.TjIDs)
if(slc.
tjs[tid - 1].AlgMod[
kMat3D]) matchedTjs.push_back(tid);
518 if(matchedTjs.empty())
continue;
522 bool isCompatible =
true;
523 for(
auto tid : matchedTjs) {
524 auto TInP =
GetAssns(slc,
"T", tid,
"P");
525 if(TInP.empty())
continue;
528 auto PIn3S =
GetAssns(slc,
"P", TInP[0],
"3S");
529 for(
auto sid : PIn3S) {
531 auto& ss3 = slc.
showers[sid - 1];
533 if(mergeWith3S == 0) mergeWith3S = sid;
534 if(mergeWith3S > 0 && mergeWith3S != sid) isCompatible =
false;
539 myprt<<fcnLabel<<
" 2S"<<
ss.ID<<
" is not 3D-matched but has 3D-matched Tjs:";
540 for(
auto tid : matchedTjs) {
542 auto TInP =
GetAssns(slc,
"T", tid,
"P");
544 myprt<<
"->P"<<TInP[0];
548 if(mergeWith3S == 0 &&
ss.Energy < 50) {
551 }
else if(mergeWith3S > 0 && isCompatible) {
552 auto& ss3 = slc.
showers[mergeWith3S - 1];
553 for(
auto cid : ss3.CotIDs) {
554 auto& oss = slc.
cots[cid - 1];
555 if(oss.CTP !=
ss.CTP)
continue;
557 std::cout<<fcnLabel<<
" Merge failed\n";
560 std::cout<<fcnLabel<<
" UpdateShower failed\n";
562 ss3.NeedsUpdate =
true;
564 std::cout<<fcnLabel<<
" UpdateShower failed\n";
583 if(ss3.
ID == 0)
return false;
585 if(ss3.
CotIDs.size() < 3)
return true;
586 std::string fcnLabel = inFcnLabel +
".R3D";
592 std::vector<ShowerStruct> oldSS(ss3.
CotIDs.size());
593 for(
unsigned short ii = 0; ii < ss3.
CotIDs.size(); ++ii) {
597 std::vector<std::vector<int>> plist(ss3.
CotIDs.size());
598 for(
unsigned short ci = 0; ci < ss3.
CotIDs.size(); ++ci) {
600 for(
auto tid :
ss.TjIDs) {
601 auto tToP =
GetAssns(slc,
"T", tid,
"P");
602 if(tToP.empty())
continue;
605 if(std::find(plist[ci].
begin(), plist[ci].
end(), pid) == plist[ci].end()) plist[ci].push_back(pid);
609 std::vector<std::array<int, 2>> p_cnt;
610 for(
auto& pl : plist) {
612 unsigned short indx = 0;
613 for(indx = 0; indx < p_cnt.size(); ++indx)
if(p_cnt[indx][0] ==
pid)
break;
614 if(indx == p_cnt.size()) {
616 p_cnt.push_back(std::array<int,2> {{
pid, 1}});
624 myprt<<fcnLabel<<
" 3S"<<ss3.
ID<<
"\n";
625 for(
unsigned short ci = 0; ci < ss3.
CotIDs.size(); ++ci) {
626 myprt<<
" -> 2S"<<ss3.
CotIDs[ci]<<
" ->";
627 for(
auto pid : plist[ci]) myprt<<
" P"<<
pid;
630 myprt<<
" P<ID>_count:";
631 for(
auto& pc : p_cnt) myprt<<
" P"<<pc[0]<<
"_"<<pc[1];
634 for(
auto& pc : p_cnt) {
636 if(pc[1] == (
int)ss3.
CotIDs.size())
continue;
639 auto& pfp = slc.
pfps[pc[0] - 1];
640 if(pfp.TjIDs.size() > 2) {
642 auto PIn2S =
GetAssns(slc,
"P", pfp.
ID,
"2S");
646 if(!sDiff.empty() && std::find(ss3.
CotIDs.begin(), ss3.
CotIDs.end(), sDiff[0]) == ss3.
CotIDs.end())
continue;
649 myprt<<fcnLabel<<
" 3S"<<ss3.
ID<<
" P"<<pfp.ID<<
" ->";
650 for(
auto sid : PIn2S) myprt<<
" 2S"<<sid;
652 for(
auto sid : sDiff) myprt<<
" 2S"<<sid;
655 if(
AddPFP(fcnLabel, slc, pfp.
ID, ss3,
true, prt)) {
658 if(ss3.
CotIDs.size() != oldSS.size()) {
659 std::cout<<fcnLabel<<
" Major failure...";
662 for(
unsigned short ii = 0; ii < ss3.
CotIDs.size(); ++ii) oldSS[ii] = slc.
cots[ss3.
CotIDs[ii] - 1];
666 for(
unsigned short ii = 0; ii < oldSS.size(); ++ii) {
667 auto&
ss = oldSS[ii];
674 auto& pfp = slc.
pfps[pc[0] - 1];
675 unsigned short nearEnd = 1 -
FarEnd(slc, pfp, ss3.
ChgPos);
680 myprt<<fcnLabel<<
" one occurrence: P"<<pfp.ID<<
"_"<<nearEnd<<
" closest to ChgPos";
681 myprt<<
" ChgPos "<<std::fixed<<std::setprecision(1)<<ss3.
ChgPos[0]<<
" "<<ss3.
ChgPos[1]<<
" "<<ss3.
ChgPos[2];
683 myprt<<
" InShowerProb "<<prob;
685 if(sep < 30 && prob > 0.3 &&
AddPFP(fcnLabel, slc, pfp.
ID, ss3,
true, prt)) {
687 }
else if(!
RemovePFP(fcnLabel, slc, pfp, ss3,
true, prt)) {
688 std::cout<<
"RemovePFP failed \n";
693 if(!
UpdateShower(fcnLabel, slc, ss3, prt))
return false;
705 if(ss.
ID == 0)
return;
707 std::string fcnLabel = inFcnLabel +
".KVIS";
709 for(
auto& vx2 : slc.
vtxs) {
710 if(vx2.ID == 0)
continue;
711 if(vx2.CTP != ss.
CTP)
continue;
713 if(vx2.Vx3ID > 0 && slc.
vtx3s[vx2.Vx3ID - 1].Neutrino)
continue;
715 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Clobber 2V"<<vx2.ID<<
" -> 3V"<<vx2.Vx3ID<<
" inside 2S"<<ss.
ID;
718 if(dc.TjIDs[0] == 0)
continue;
719 if(dc.Vx2ID != vx2.ID)
continue;
720 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Remove T"<<dc.TjIDs[0]<<
"-T"<<dc.TjIDs[0]<<
" in dontCluster";
725 auto TIn3V =
GetAssns(slc,
"3V", vx2.Vx3ID,
"T");
727 auto& vx3 = slc.
vtx3s[vx2.Vx3ID - 1];
730 auto TIn2V =
GetAssns(slc,
"2V", vx2.
ID,
"T");
744 if(slc.
nPlanes != 3)
return false;
745 if(ss3.
CotIDs.size() != 2)
return false;
749 std::string fcnLabel = inFcnLabel +
".CIS";
755 std::vector<int> iplist;
756 for(
auto tid : iss.TjIDs) {
757 auto plist =
GetAssns(slc,
"T", tid,
"P");
758 if(!plist.empty()) iplist.insert(iplist.end(), plist.begin(), plist.end());
760 std::vector<int> jplist;
761 for(
auto tid : jss.TjIDs) {
762 auto plist =
GetAssns(slc,
"T", tid,
"P");
763 if(!plist.empty()) jplist.insert(jplist.end(), plist.begin(), plist.end());
767 if(shared.empty())
return false;
769 std::vector<int> flat = iss.TjIDs;
770 flat.insert(flat.end(), jss.TjIDs.begin(), jss.TjIDs.end());
773 std::vector<int> ktlist;
774 for(
auto pid : shared) {
776 for(
auto tid : pfp.TjIDs) {
778 if(std::find(flat.begin(), flat.end(), tid) != flat.end())
continue;
779 if(std::find(ktlist.begin(), ktlist.end(), tid) == ktlist.end()) ktlist.push_back(tid);
781 auto& tj = slc.
tjs[tid - 1];
782 for(
unsigned short end = 0;
end < 2; ++
end) {
783 if(tj.VtxID[
end] <= 0)
continue;
784 auto& vx2 = slc.
vtxs[tj.VtxID[
end] - 1];
785 auto TIn2V =
GetAssns(slc,
"2V", vx2.
ID,
"T");
786 for(
auto vtid : TIn2V) {
787 if(std::find(ktlist.begin(), ktlist.end(), vtid) == ktlist.end()) ktlist.push_back(vtid);
792 if(ktlist.empty())
return false;
794 std::vector<int> ksslist;
795 for(
auto tid : ktlist) {
796 auto& tj = slc.
tjs[tid - 1];
797 if(tj.SSID == 0)
continue;
799 auto&
ss = slc.
cots[tj.SSID - 1];
801 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Found existing T"<<tid<<
" -> 2S"<<
ss.ID<<
" -> 3S"<<
ss.SS3ID<<
" assn. Give up";
804 if(std::find(ksslist.begin(), ksslist.end(),
ss.ID) == ksslist.end()) ksslist.push_back(
ss.ID);
810 myprt<<fcnLabel<<
" 3S"<<ss3.
ID<<
"\n";
811 myprt<<
" -> i2S"<<iss.ID<<
" ->";
812 for(
auto pid : iplist) myprt<<
" P"<<
pid;
814 myprt<<
" -> j2S"<<jss.ID<<
" ->";
815 for(
auto pid : jplist) myprt<<
" P"<<pid;
819 unsigned short kplane = 3 - iPlaneID.
Plane - jPlaneID.
Plane;
820 myprt<<
" kplane "<<kplane<<
" ktlist:";
821 for(
auto tid : ktlist) myprt<<
" T"<<tid;
822 myprt<<
" ktlistEnergy "<<ktlistEnergy;
823 if(ksslist.empty()) {
824 myprt<<
"\n No matching showers in kplane";
827 myprt<<
" Candidate showers:";
828 for(
auto ssid : ksslist) {
830 auto& sst = slc.
cots[ssid - 1];
831 if(sst.SS3ID > 0) myprt<<
"_3S"<<sst.SS3ID;
835 if(ksslist.size() > 1) {
836 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Found more than 1 shower. Need some better code here";
840 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" ktlistEnergy exceeds 2 * ss3 energy. Need some better code here";
844 if(ksslist.empty()) {
847 if(kss.ID == 0)
return false;
849 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" create new 2S"<<kss.ID<<
" from ktlist";
851 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" UpdateShower failed 2S"<<kss.ID;
860 ss3.
CotIDs.push_back(kss.ID);
861 auto& stj = slc.
tjs[kss.ShowerTjID - 1];
868 auto&
ss = slc.
cots[ksslist[0] - 1];
872 auto& stj = slc.
tjs[
ss.ShowerTjID - 1];
886 std::string fcnLabel = inFcnLabel +
".M2DS";
895 std::vector<SortEntry> sortVec;
896 for(
unsigned short indx = 0; indx < slc.
cots.size(); ++indx) {
897 auto&
ss = slc.
cots[indx];
898 if(
ss.ID == 0)
continue;
900 if(
ss.SS3ID > 0)
continue;
901 if(
ss.TjIDs.empty())
continue;
904 se.length =
ss.Energy /
ss.AspectRatio;
905 sortVec.push_back(se);
907 if(sortVec.size() < 2)
return;
908 std::sort(sortVec.begin(), sortVec.end(),
greaterThan);
911 for(
unsigned short ii = 0; ii < sortVec.size() - 1; ++ii) {
912 unsigned short iIndx = sortVec[ii].index;
913 auto& iss = slc.
cots[iIndx];
915 if(iss.SS3ID > 0)
continue;
918 for(
unsigned short jj = 0; jj < sortVec.size(); ++jj) {
919 if(iss.SS3ID > 0)
break;
920 unsigned short jIndx = sortVec[jj].index;
923 if(iss.SS3ID > 0)
break;
924 if(jss.
SS3ID > 0)
continue;
925 if(jss.
CTP == iss.CTP)
continue;
928 if(!
MakeTp3(slc, istj.
Pts[1], jstj.
Pts[1], tp3,
true))
continue;
930 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" i2S"<<iss.ID<<
" j2S"<<jss.
ID<<
" fomij "<<fomij<<
" fomCut "<<fomCut;
931 if(fomij > fomCut)
continue;
941 ss3.
Energy[0] = iss.Energy;
946 if(prt)
mf::LogVerbatim(
"TC")<<
" new 2-plane TPC 3S"<<ss3.
ID<<
" with fomij "<<fomij;
949 float bestFOM = fomCut;
950 unsigned short bestck = USHRT_MAX;
951 for(
unsigned short ck = 0; ck < slc.
cots.size(); ++ck) {
953 if(kss.
ID == iss.ID || kss.
ID == jss.
ID)
continue;
954 if(kss.
CTP == iss.CTP || kss.
CTP == jss.
CTP)
continue;
955 if(kss.
ID == 0)
continue;
956 if(kss.
TjIDs.empty())
continue;
957 if(kss.
SS3ID > 0)
continue;
962 if(fomik > bestFOM)
continue;
965 if(prt)
mf::LogVerbatim(
"TC")<<
" 2S"<<iss.ID<<
" 2S"<<jss.
ID<<
" 2S"<<kss.
ID<<
" Large stp[1] point separation "<<(int)sep;
977 if(bestck == USHRT_MAX) {
984 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";
991 unsigned short ck = bestck;
1001 slc.
cots[ck].SS3ID = ss3.
ID;
1004 ss3.
MatchFOM = 0.5 * (fomij + bestFOM);
1014 if(nss3.NeedsUpdate)
UpdateShower(fcnLabel, slc, nss3, prt);
1020 if(nss3.NeedsUpdate)
UpdateShower(fcnLabel, slc, nss3, prt);
1042 if(ss.
ID == 0)
return false;
1043 if(ss.
TjIDs.empty())
return false;
1047 if(stj.Pts.size() != 3)
return false;
1049 std::string fcnLabel = inFcnLabel +
".U2S";
1064 for(
auto& stp : stj.Pts) {
1066 stp.Pos = {{0.0, 0.0}};
1068 stp.HitPos = {{0.0, 0.0}};
1070 stp.Dir = {{0.0, 0.0}};
1080 for(
auto tjid : ss.
TjIDs) {
1081 if(tjid <= 0 || tjid > (
int)slc.
tjs.size())
return false;
1082 auto& tj = slc.
tjs[tjid - 1];
1083 if(tj.CTP != ss.
CTP)
return false;
1085 for(
unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1087 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1088 if(!tp.
UseHit[ii])
continue;
1089 unsigned int iht = tp.
Hits[ii];
1091 if(
hit.Integral() <= 0)
continue;
1095 shpt.
Chg =
hit.Integral();
1096 shpt.
Pos[0] =
hit.WireID().Wire;
1098 ss.
ShPts.push_back(shpt);
1104 if(ss.
ShPts.size() < 3)
return false;
1107 auto& stp1 = stj.Pts[1];
1108 for(
auto& shpt : ss.
ShPts) {
1109 stp1.Pos[0] += shpt.Chg * shpt.Pos[0];
1110 stp1.Pos[1] += shpt.Chg * shpt.Pos[1];
1111 stj.TotChg += shpt.Chg;
1113 if(stj.TotChg <= 0)
return false;
1114 stp1.Pos[0] /= stj.TotChg;
1115 stp1.Pos[1] /= stj.TotChg;
1124 unsigned short pend =
FarEnd(slc, ptj, stp1.Pos);
1125 auto& ptp = ptj.Pts[ptj.EndPt[pend]];
1127 stp1.Ang = atan2(stp1.Dir[1], stp1.Dir[0]);
1136 for(
auto& shpt : ss.
ShPts) {
1138 double xx = shpt.Pos[0] - stp1.Pos[0];
1139 double yy = shpt.Pos[1] - stp1.Pos[1];
1140 sumx += shpt.Chg *
xx;
1141 sumy += shpt.Chg * yy;
1142 sumxy += shpt.Chg * xx * yy;
1143 sumx2 += shpt.Chg * xx *
xx;
1144 sumy2 += shpt.Chg * yy * yy;
1146 double delta = sum * sumx2 - sumx * sumx;
1147 if(delta == 0)
return false;
1151 double B = (sumxy * sum - sumx * sumy) / delta;
1153 stp1.Dir[0] = cos(stp1.Ang);
1154 stp1.Dir[1] = sin(stp1.Ang);
1158 ss.
Angle = stp1.Ang;
1159 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 2S"<<ss.
ID<<
" dir "<<std::fixed<<std::setprecision(2)<<stp1.Dir[0]<<
" "<<stp1.Dir[1]<<
" Angle "<<stp1.Ang;
1160 for(
unsigned short ipt = 0; ipt < 3; ++ipt) {
1161 if(ipt == 1)
continue;
1162 stj.Pts[ipt].Dir = stp1.Dir;
1163 stj.Pts[ipt].Ang = stp1.Ang;
1167 std::vector<SortEntry> sortVec(ss.
ShPts.size());
1168 unsigned short indx = 0;
1169 double cs = cos(-stp1.Ang);
1170 double sn = sin(-stp1.Ang);
1171 for(
auto& shpt : ss.
ShPts) {
1172 double xx = shpt.Pos[0] - stp1.Pos[0];
1173 double yy = shpt.Pos[1] - stp1.Pos[1];
1174 shpt.RotPos[0] = cs * xx - sn * yy;
1175 shpt.RotPos[1] = sn * xx + cs * yy;
1176 sortVec[indx].index = indx;
1177 sortVec[indx].length = shpt.RotPos[0];
1180 std::sort(sortVec.begin(), sortVec.end(),
lessThan);
1182 auto tPts = ss.
ShPts;
1183 for(
unsigned short ii = 0; ii < ss.
ShPts.size(); ++ii) ss.
ShPts[ii] = tPts[sortVec[ii].index];
1187 for(
auto& shpt :
ss.ShPts) {
1188 alongTrans[0] += shpt.Chg * std::abs(shpt.RotPos[0]);
1189 alongTrans[1] += shpt.Chg * std::abs(shpt.RotPos[1]);
1191 alongTrans[0] /= stj.TotChg;
1192 alongTrans[1] /= stj.TotChg;
1193 if(alongTrans[1] == 0)
return false;
1194 ss.AspectRatio = alongTrans[1] / alongTrans[0];
1201 if(
ss.ParentID > 0) {
1204 auto& ptj = slc.tjs[
ss.ParentID - 1];
1206 unsigned short pend =
FarEnd(slc, ptj, stp1.Pos);
1207 auto& ptp = ptj.Pts[ptj.EndPt[pend]];
1208 auto& firstShPt =
ss.ShPts[0];
1209 auto& lastShPt =
ss.ShPts[
ss.ShPts.size() - 1];
1211 stj.Pts[0].Pos = ptp.Pos;
1214 if(stj.Pts[2].DeltaRMS < stj.Pts[0].DeltaRMS)
ReverseShower(fcnLabel, slc,
ss, prt);
1215 stj.Pts[0].Pos =
ss.ShPts[0].Pos;
1218 if(stj.Pts[2].DeltaRMS > 0)
ss.DirectionFOM = stj.Pts[0].DeltaRMS / stj.Pts[2].DeltaRMS;
1220 stj.Pts[2].Pos =
ss.ShPts[
ss.ShPts.size() - 1].Pos;
1223 ss.NeedsUpdate =
false;
1235 if(ss3.
ID == 0)
return false;
1236 if(ss3.
CotIDs.size() < 2)
return false;
1238 std::string fcnLabel = inFcnLabel +
".U3S";
1241 for(
auto cid : ss3.
CotIDs) {
1242 auto&
ss = slc.
cots[cid - 1];
1243 if(
ss.NeedsUpdate && prt) std::cout<<fcnLabel<<
" ********* 3S"<<ss3.
ID<<
" 2S"<<
ss.ID<<
" needs an update...\n";
1251 if(pfp.Vx3ID[pend] != ss3.
Vx3ID) {
1252 if(prt) std::cout<<fcnLabel<<
" ********* 3S"<<ss3.
ID<<
" has parent P"<<ss3.
ParentID<<
" with a vertex that is not attached the shower\n";
1257 std::array<Point3_t, 3> pos;
1260 std::array<double, 3> chg;
1261 for(
unsigned short ipt = 0; ipt < 3; ++ipt) {
1263 for(
unsigned short xyz = 0; xyz < 3; ++xyz) {
1269 for(
unsigned short ii = 0; ii < ss3.
CotIDs.size() - 1; ++ii) {
1270 unsigned short ciid = ss3.
CotIDs[ii];
1271 auto& iss = slc.
cots[ciid - 1];
1273 auto istj = slc.
tjs[iss.ShowerTjID - 1];
1274 for(
auto& tp : istj.Pts) tp.Pos = tp.HitPos;
1275 for(
unsigned short jj = ii + 1; jj < ss3.
CotIDs.size(); ++jj) {
1276 unsigned short cjid = ss3.
CotIDs[jj];
1277 auto& jss = slc.
cots[cjid - 1];
1278 auto jstj = slc.
tjs[jss.ShowerTjID - 1];
1279 for(
auto& tp : jstj.Pts) tp.Pos = tp.HitPos;
1281 for(
unsigned short ipt = 0; ipt < 3; ++ipt) {
1282 if(!
MakeTp3(slc, istj.Pts[ipt], jstj.Pts[ipt], tp3,
true))
continue;
1283 double ptchg = 0.5 * (istj.Pts[ipt].Chg + jstj.Pts[ipt].Chg);
1285 for(
unsigned short xyz = 0; xyz < 3; ++xyz) {
1286 pos[ipt][xyz] += ptchg * tp3.
Pos[xyz];
1287 dir[xyz] += ptchg * tp3.
Dir[xyz];
1293 unsigned short nok = 0;
1294 for(
unsigned short ipt = 0; ipt < 3; ++ipt) {
1295 if(chg[ipt] == 0)
continue;
1296 for(
unsigned short xyz = 0; xyz < 3; ++xyz) pos[ipt][xyz] /= chg[ipt];
1312 ss3.
Start = pfp.XYZ[pend];
1324 for(
auto cid : ss3.
CotIDs) {
1325 auto&
ss = slc.
cots[cid - 1];
1326 auto& stj = slc.
tjs[
ss.ShowerTjID - 1];
1334 ss3.
dEdx[plane] = stj.dEdx[0];
1335 ss3.
dEdxErr[plane] = 0.3 * stj.dEdx[0];
1349 for(
unsigned short ii = 0; ii < ss3.
CotIDs.size() - 1; ++ii) {
1350 unsigned short icid = ss3.
CotIDs[ii];
1351 for(
unsigned short jj = ii + 1; jj < ss3.
CotIDs.size(); ++jj) {
1352 unsigned short jcid = ss3.
CotIDs[jj];
1353 fom +=
Match3DFOM(inFcnLabel, slc, icid, jcid, prt);
1357 if(cnt == 0)
return 100;
1363 int icid,
int jcid,
int kcid,
bool prt)
1365 if(icid == 0 || icid > (
int)slc.
cots.size())
return 100;
1366 if(jcid == 0 || jcid > (
int)slc.
cots.size())
return 100;
1367 if(kcid == 0 || kcid > (
int)slc.
cots.size())
return 100;
1369 float ijfom =
Match3DFOM(inFcnLabel, slc, icid, jcid, prt);
1370 float jkfom =
Match3DFOM(inFcnLabel, slc, jcid, kcid, prt);
1372 return 0.5 * (ijfom + jkfom);
1380 if(icid == 0 || icid > (
int)slc.
cots.size())
return 100;
1381 if(jcid == 0 || jcid > (
int)slc.
cots.size())
return 100;
1383 auto& iss = slc.
cots[icid - 1];
1384 auto& istj = slc.
tjs[iss.ShowerTjID - 1];
1385 auto& jss = slc.
cots[jcid - 1];
1386 auto& jstj = slc.
tjs[jss.ShowerTjID - 1];
1388 if(iss.CTP == jss.CTP)
return 100;
1390 std::string fcnLabel = inFcnLabel +
".MFOM";
1392 float energyAsym = std::abs(iss.Energy - jss.Energy) / (iss.Energy + jss.Energy);
1395 if((iss.Energy > 200 || jss.Energy > 200) && energyAsym > 0.5)
return 50;
1403 float pos1fom = std::abs(ix - jx) / 10;
1405 float mfom = energyAsym * pos1fom;
1409 myprt<<fcnLabel<<
" i2S"<<iss.ID<<
" j2S"<<jss.ID;
1410 myprt<<std::fixed<<std::setprecision(2);
1412 myprt<<
" pos1fom "<<pos1fom;
1414 myprt<<
" energyAsym "<<energyAsym;
1415 myprt<<
" mfom "<<mfom;
1426 if(tjList.size() < 2)
return;
1428 bool didMerge =
true;
1431 for(
unsigned short itl = 0; itl < tjList.size() - 1; ++itl) {
1432 if(tjList[itl].empty())
continue;
1433 for(
unsigned short jtl = itl + 1; jtl < tjList.size(); ++jtl) {
1434 if(tjList[itl].empty())
continue;
1435 auto& itList = tjList[itl];
1436 auto& jtList = tjList[jtl];
1438 bool jtjInItjList =
false;
1439 for(
auto& jtj : jtList) {
1440 if(std::find(itList.begin(), itList.end(), jtj) != itList.end()) {
1441 jtjInItjList =
true;
1444 if(jtjInItjList)
break;
1448 itList.insert(itList.end(), jtList.begin(), jtList.end());
1458 unsigned short imEmpty = 0;
1459 while(imEmpty < tjList.size()) {
1460 for(imEmpty = 0; imEmpty < tjList.size(); ++imEmpty)
if(tjList[imEmpty].empty())
break;
1461 if(imEmpty < tjList.size()) tjList.erase(tjList.begin() + imEmpty);
1465 for(
auto& tjl : tjList) {
1466 std::sort(tjl.begin(), tjl.end());
1467 auto last = std::unique(tjl.begin(), tjl.end());
1468 tjl.erase(last, tjl.end());
1480 if(pfp.
ID == 0 || ss3.
ID == 0)
return false;
1482 std::string fcnLabel = inFcnLabel +
".RemP";
1483 for(
auto tid : pfp.
TjIDs) {
1484 for(
auto cid : ss3.
CotIDs) {
1485 auto&
ss = slc.
cots[cid - 1];
1486 if(std::find(
ss.TjIDs.begin(),
ss.TjIDs.end(), tid) ==
ss.TjIDs.end())
continue;
1487 if(!
RemoveTj(fcnLabel, slc, tid,
ss, doUpdate, prt))
return false;
1504 std::string fcnLabel = inFcnLabel +
".AddP";
1506 if(pID <= 0 || pID > (
int)slc.
pfps.size())
return false;
1507 auto& pfp = slc.
pfps[pID - 1];
1509 if(pfp.TPCID != ss3.
TPCID) {
1510 mf::LogVerbatim(
"TC")<<fcnLabel<<
" P"<<pID<<
" is in the wrong TPC for 3S"<<ss3.
ID;
1514 for(
auto tid : pfp.TjIDs) {
1515 auto& tj = slc.
tjs[tid - 1];
1518 auto&
ss = slc.
cots[tj.SSID - 1];
1519 if(
ss.SS3ID > 0 &&
ss.SS3ID != ss3.
ID) {
1520 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";
1524 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" adding P"<<pfp.ID<<
" -> T"<<tid<<
" is in the correct shower 2S"<<tj.SSID;
1529 myprt<<fcnLabel<<
" 3S"<<ss3.
ID<<
" adding P"<<pfp.ID<<
" -> T"<<tid;
1530 for(
unsigned short ii = 0; ii < pfp.TjIDs.size(); ++ii) {
1531 if(pfp.TjIDs[ii] == tid) myprt<<
" pfp TjCompleteness "<<std::fixed<<std::setprecision(2)<<pfp.TjCompleteness[ii];
1533 myprt<<
" tj.SSID 2S"<<tj.SSID;
1536 for(
auto& cid : ss3.
CotIDs) {
1537 auto&
ss = slc.
cots[cid - 1];
1538 if(
ss.CTP != tj.CTP)
continue;
1540 AddTj(fcnLabel, slc, tid,
ss, doUpdate, prt);
1556 if(tjID <= 0 || tjID > (
int)slc.
tjs.size())
return false;
1558 std::string fcnLabel = inFcnLabel +
".AddT";
1563 mf::LogVerbatim(
"TC")<<fcnLabel<<
" T"<<tjID<<
" is in the wrong CTP for 2S"<<ss.
ID;
1569 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" T"<<tjID<<
" is already in 2S"<<ss.
ID;
1572 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Can't add T"<<tjID<<
" to 2S"<<ss.
ID<<
". it is already used in 2S"<<tj.
SSID;
1577 ss.
TjIDs.push_back(tjID);
1581 for(
unsigned short ii = 0; ii < ss.
NearTjIDs.size(); ++ii) {
1585 unsigned short cnt = 0;
1586 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
1588 if(tp.
Chg == 0)
continue;
1589 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii)
if(tp.
UseHit[ii]) ++cnt;
1591 unsigned short newSize = ss.
ShPts.size() + cnt;
1592 cnt = ss.
ShPts.size();
1593 ss.
ShPts.resize(newSize);
1595 for(
unsigned short ipt = tj.
EndPt[0]; ipt <= tj.
EndPt[1]; ++ipt) {
1597 if(tp.
Chg == 0)
continue;
1598 for(
unsigned short ii = 0; ii < tp.
Hits.size(); ++ii) {
1600 unsigned int iht = tp.
Hits[ii];
1601 ss.
ShPts[cnt].HitIndex = iht;
1604 ss.
ShPts[cnt].Chg =
hit.Integral();
1605 ss.
ShPts[cnt].Pos[0] =
hit.WireID().Wire;
1614 if(doUpdate)
return UpdateShower(fcnLabel, slc, ss, prt);
1624 if(TjID > (
int)slc.
tjs.size())
return false;
1626 std::string fcnLabel = inFcnLabel +
".RTj";
1632 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Can't Remove T"<<TjID<<
" from 2S"<<ss.
ID<<
" because it's not in this shower";
1639 for(
unsigned short ii = 0; ii < ss.
TjIDs.size(); ++ii) {
1640 if(TjID == ss.
TjIDs[ii]) {
1646 if(!gotit)
return false;
1653 if(ss.
TjIDs.empty()) {
1654 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Removed the last Tj. Killing 2S"<<ss.
ID;
1678 if(ss3.
ID == 0)
return false;
1679 if(ss3.
CotIDs.size() < 2)
return false;
1686 std::string fcnLabel = inFcnLabel +
".FPar";
1695 double shMaxAlong, along95;
1697 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" Estimated energy "<<(int)energy<<
" MeV shMaxAlong "<<shMaxAlong<<
" along95 "<<along95<<
" truPFP "<<truPFP;
1718 std::array<int, 2> parID {{0, 0}};
1719 std::array<float, 2> parFOM {{-1E6, -1E6}};
1722 std::vector<bool> isParent(slc.
pfps.size() + 1,
false);
1723 for(
auto& oldSS3 : slc.
showers) {
1724 if(oldSS3.ID == 0)
continue;
1725 isParent[oldSS3.ParentID] =
true;
1729 auto TjsInSS3 =
GetAssns(slc,
"3S", ss3.
ID,
"T");
1730 if(TjsInSS3.empty())
return false;
1732 for(
auto& pfp : slc.
pfps) {
1733 if(pfp.ID == 0)
continue;
1734 bool dprt = (pfp.ID == truPFP);
1735 if(pfp.TPCID != ss3.
TPCID)
continue;
1737 if(pfp.PDGCode == 14 || pfp.PDGCode == 14)
continue;
1739 if(pfp.PDGCode == 1111)
continue;
1741 if(isParent[pfp.ID])
continue;
1743 if(
DontCluster(slc, pfp.TjIDs, TjsInSS3))
continue;
1745 float pfpEnergy = 0;
1746 float minEnergy = 1E6;
1747 for(
auto tid : pfp.TjIDs) {
1748 auto& tj = slc.
tjs[tid - 1];
1749 float energy =
ChgToMeV(tj.TotChg);
1751 if(energy < minEnergy) minEnergy =
energy;
1753 pfpEnergy -= minEnergy;
1754 pfpEnergy /= (float)(pfp.TjIDs.size() - 1);
1755 if(dprt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" P"<<pfp.ID<<
" E "<<pfpEnergy;
1756 if(pfpEnergy > energy)
continue;
1760 double costh1 = std::abs(
DotProd(pToS, ss3.
Dir));
1761 if(costh1 < 0.4)
continue;
1762 float costh2 =
DotProd(pToS, pfp.Dir[pEnd]);
1764 float distToStart2 =
PosSep2(pfp.XYZ[pEnd], ss3.
Start);
1766 float distToEnd2 =
PosSep2(pfp.XYZ[pEnd], ss3.
End);
1767 if(dprt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" P"<<pfp.ID<<
"_"<<pEnd<<
" distToStart "<<sqrt(distToStart2)<<
" distToChgPos "<<sqrt(distToChgPos2)<<
" distToEnd "<<sqrt(distToEnd2);
1769 unsigned short shEnd = 0;
1770 if(distToEnd2 < distToStart2) shEnd = 1;
1772 if(shEnd == 0 && distToChgPos2 < distToStart2)
continue;
1773 if(shEnd == 1 && distToChgPos2 < distToEnd2)
continue;
1774 if(dprt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
"_"<<shEnd<<
" P"<<pfp.ID<<
"_"<<pEnd<<
" costh1 "<<costh1;
1779 if(dprt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" alongTrans "<<alongTrans[0]<<
" "<<alongTrans[1];
1783 float distToShowerMax = shMaxAlong - std::abs(alongTrans[0]);
1786 if(prob < 0.1)
continue;
1791 for(
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
1794 for(
auto cid : ss3.
CotIDs) {
1795 auto&
ss = slc.
cots[cid - 1];
1796 if(
ss.CTP != inCTP)
continue;
1800 if(ssid == 0)
continue;
1801 auto tpFrom =
MakeBareTP(slc, pfp.XYZ[pEnd], pToS, inCTP);
1802 auto&
ss = slc.
cots[ssid - 1];
1803 auto& stp1 = slc.
tjs[
ss.ShowerTjID - 1].Pts[1];
1804 float sep =
PosSep(tpFrom.Pos, stp1.Pos);
1805 float toPos = tpFrom.Pos[0] + 0.5 * tpFrom.Dir[0] * sep;
1809 chgFrac += sep * cf;
1811 if(totSep > 0) chgFrac /= totSep;
1848 myprt<<
" 3S"<<ss3.
ID<<
"_"<<shEnd;
1849 myprt<<
" P"<<pfp.ID<<
"_"<<pEnd<<
" ParentVars";
1851 myprt<<
" candParFOM "<<candParFOM;
1853 if(candParFOM > parFOM[shEnd]) {
1854 parFOM[shEnd] = candParFOM;
1855 parID[shEnd] = pfp.ID;
1859 if(parID[0] == 0 && parID[1] == 0)
return true;
1864 float aveDirFOM = 0;
1866 for(
auto cid : ss3.
CotIDs) aveDirFOM += slc.
cots[cid - 1].DirectionFOM;
1867 aveDirFOM /= (float)ss3.
CotIDs.size();
1869 mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" parID[0] "<<parID[0]<<
" fom "<<parFOM[0]<<
" parID[1] "<<parID[1]<<
" fom "<<parFOM[1]<<
" aveDirFOM "<<aveDirFOM;
1871 if(parID[0] > 0 && parID[1] > 0 && aveDirFOM > 0.3) {
1876 if(parFOM[1] > parFOM[0]) {
1880 }
else if(parID[0] > 0) {
1887 if(bestPFP == 0)
return true;
1889 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" setting P"<<bestPFP<<
" as the parent "<<fom3D;
1893 std::vector<ShowerStruct> oldSS(ss3.
CotIDs.size());
1894 for(
unsigned short ii = 0; ii < ss3.
CotIDs.size(); ++ii) {
1899 auto& pfp = slc.
pfps[bestPFP - 1];
1901 ss3.
Vx3ID = pfp.Vx3ID[pend];
1908 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" Failed. Recovering...";
1910 for(
unsigned short ii = 0; ii < oldSS.size(); ++ii) {
1911 auto&
ss = oldSS[ii];
1922 if(pfp.
ID == 0 || ss3.
ID == 0)
return false;
1923 if(ss3.
CotIDs.empty())
return false;
1925 std::string fcnLabel = inFcnLabel +
".SP";
1927 for(
auto cid : ss3.
CotIDs) {
1928 auto&
ss = slc.
cots[cid - 1];
1929 auto& stj = slc.
tjs[
ss.ShowerTjID - 1];
1931 if(
ss.ParentID > 0) {
1932 auto& oldParent = slc.
tjs[
ss.ParentID - 1];
1938 for(
auto tjid : pfp.
TjIDs) {
1939 auto& tj = slc.
tjs[tjid - 1];
1940 if(tj.CTP !=
ss.CTP)
continue;
1941 if(std::find(
ss.TjIDs.begin(),
ss.TjIDs.end(), tjid) ==
ss.TjIDs.end()) {
1943 if(!
AddTj(fcnLabel, slc, tjid,
ss,
false, prt))
return false;
1948 unsigned short npts = tj.EndPt[1] - tj.EndPt[0] + 1;
1949 if(tp.Delta > 0.5 || npts > 20) {
1950 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" parent P"<<pfp.
ID<<
" -> T"<<tjid<<
" -> 2S"<<
ss.ID<<
" parent";
1952 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" parent P"<<pfp.
ID<<
" -> T"<<tjid<<
" low projection in plane "<<tp.Delta<<
". Not a parent";
1956 ss.NeedsUpdate =
true;
1960 auto v2list =
GetAssns(slc,
"3V", vx3.
ID,
"2V");
1961 for(
unsigned short end = 0;
end < 2; ++
end) {
1962 if(tj.VtxID[
end] <= 0)
continue;
1963 if(std::find(v2list.begin(), v2list.end(), tj.VtxID[
end]) != v2list.end()) stj.VtxID[0] = tj.VtxID[
end];
1974 float fom3D =
ParentFOM(fcnLabel, slc, pfp, pEnd, ss3, prt);
1975 for(
auto cid : ss3.
CotIDs) slc.
cots[cid - 1].ParentFOM = fom3D;
1986 pfp.XYZ[0] = ss3.
Start;
1987 pfp.Dir[0] = ss3.
Dir;
1988 pfp.XYZ[1] = ss3.
End;
1989 pfp.Dir[1] = ss3.
Dir;
1991 unsigned short npts = ss3.
Len;
1992 if(npts < 2)
return pfp;
1993 pfp.Tp3s.resize(npts);
1994 pfp.Tp3s[0].Pos = ss3.
Start;
1995 for(
unsigned short ipt = 1; ipt < npts; ++ipt) {
1996 for(
unsigned short xyz = 0; xyz < 3; ++xyz) pfp.Tp3s[ipt].Pos[xyz] = pfp.Tp3s[ipt-1].Pos[xyz] + pfp.Dir[0][xyz];
2005 if(TjIDs.empty())
return false;
2006 unsigned short cnt = 0;
2007 for(
auto tid : TjIDs) {
2008 if(tid <= 0 || tid > (
int)slc.
tjs.size())
continue;
2015 void ShowerParams(
double showerEnergy,
double& shMaxAlong,
double& along95)
2021 if(showerEnergy < 10) {
2027 shMaxAlong = 16 * log(showerEnergy / 15);
2029 double scale = 2.75 - 9.29E-4 * showerEnergy;
2030 if(scale < 2) scale = 2;
2031 along95 = scale * shMaxAlong;
2038 double shMaxAlong, shE95Along;
2040 if(shMaxAlong <= 0)
return 0;
2041 double tau = (along + shMaxAlong) / shMaxAlong;
2043 double rms = -0.4 + 2.5 * tau;
2044 if(rms < 0.5) rms = 0.5;
2054 if(showerEnergy < 10)
return 0;
2056 double shMaxAlong, shE95Along;
2063 double tau = (along + shMaxAlong) / shMaxAlong;
2064 if(tau < -1 || tau > 4)
return 0;
2066 double tauHalf, width;
2077 double prob = 1 / (1 + exp((tau - tauHalf)/width));
2088 if(showerEnergy < 10)
return 0;
2090 trans = std::abs(trans);
2091 double prob = exp(-0.5 * trans / rms);
2107 if(ss3.
ID == 0 || pfp.
ID == 0)
return 0;
2110 for(
auto cid : ss3.
CotIDs) {
2111 auto&
ss = slc.
cots[cid - 1];
2112 if(
ss.ID == 0)
continue;
2113 for(
auto tid : pfp.
TjIDs) {
2114 auto& tj = slc.
tjs[tid - 1];
2115 if(tj.CTP !=
ss.CTP)
continue;
2121 if(cnt == 0)
return 0;
2131 if(ss.
ID == 0 || tj.
ID == 0)
return 0;
2132 if(ss.
CTP != tj.
CTP)
return 0;
2135 if(stj.Pts.size() != 3)
return 0;
2136 unsigned short closePt1, closePt2;
2139 if(doca == 1E6)
return 0;
2140 float showerLen =
PosSep(stj.Pts[0].Pos, stj.Pts[2].Pos);
2142 if(doca > 5 * showerLen)
return 0.01;
2143 auto& stp = stj.Pts[closePt1];
2144 if(stp.DeltaRMS == 0)
return 0;
2145 auto& ttp = tj.
Pts[closePt2];
2150 float rms = stp.DeltaRMS;
2151 if(rms < 1) rms = 1;
2152 float arg = alongTrans[1] / rms;
2153 float radProb = exp(-0.5 * arg * arg);
2157 arg = alongTrans[0] / rms;
2158 float longProb = exp(-0.5 * arg * arg);
2160 float costh = std::abs(
DotProd(stp.Dir, ttp.Dir));
2162 float prob = radProb * longProb * costh;
2172 if(ss3.
ID == 0)
return 1000;
2175 std::string fcnLabel = inFcnLabel +
".P3FOM";
2177 for(
auto cid : ss3.
CotIDs) {
2178 auto&
ss = slc.
cots[cid - 1];
2179 if(
ss.ID == 0)
continue;
2182 for(
auto tid : pfp.
TjIDs) {
2183 auto& tj = slc.
tjs[tid - 1];
2184 if(tj.ID == 0)
continue;
2185 if(tj.CTP ==
ss.CTP) tjid = tid;
2187 if(tjid == 0)
continue;
2188 auto& ptj = slc.
tjs[tjid - 1];
2189 auto& stj = slc.
tjs[
ss.ShowerTjID - 1];
2191 unsigned short ptjEnd =
FarEnd(slc, ptj, stj.Pts[1].Pos);
2192 auto& farTP = ptj.Pts[ptj.EndPt[ptjEnd]];
2193 float chgCtrSep2 =
PosSep2(farTP.Pos, stj.Pts[1].Pos);
2194 if(chgCtrSep2 <
PosSep2(farTP.Pos, stj.Pts[0].Pos) && chgCtrSep2 <
PosSep2(farTP.Pos, stj.Pts[2].Pos))
continue;
2195 float fom =
ParentFOM(fcnLabel, slc, ptj, ptjEnd,
ss, dum1, dum2, prt);
2197 if(fom > 50)
continue;
2200 if(
ss.AspectRatio > 0) wt = 1 /
ss.AspectRatio;
2204 if(wsum == 0)
return 100;
2205 float fom = sum / wsum;
2206 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 3S"<<ss3.
ID<<
" P"<<pfp.
ID<<
" fom "<<std::fixed<<std::setprecision(3)<<fom;
2219 if(tjEnd > 1)
return 1000;
2220 if(ss.
Energy == 0)
return 1000;
2222 if(ss.
ID == 0)
return 1000;
2223 if(ss.
TjIDs.empty())
return 1000;
2226 std::string fcnLabel = inFcnLabel +
".PFOM";
2250 tp1Sep = std::abs(alongTrans[0]);
2252 double shMaxAlong, shE95Along;
2258 if(prob < 0.05)
return 100;
2261 if(alongTrans[1] > shMaxAlong)
return 100;
2263 float longFOM = std::abs(alongcm + shMaxAlong) / 14;
2267 float transFOM = -1;
2269 transFOM = alongTrans[1] / stp0.
DeltaRMS;
2279 float dang1FOM = dang1 / 0.1;
2283 float dang2FOM = dang1 / 0.1;
2287 std::vector<int> tjlist(1);
2294 if(tj.
VtxID[tjEnd] > 0) {
2297 vx2Score = vx2.
Score;
2300 vxFOM = std::abs(shMaxAlong - vx2Sep) / 20;
2305 float chgFracFOM = (1 - chgFrac) / 0.1;
2310 float chgFrcBtwFOM = (1 - chgFrac) / 0.05;
2311 fom += chgFrcBtwFOM;
2322 myprt<<
" 2S"<<ss.
ID;
2323 myprt<<
" T"<<tj.
ID<<
"_"<<tjEnd<<
" Pos "<<
PrintPos(slc, ptp);
2324 myprt<<std::fixed<<std::setprecision(2);
2325 myprt<<
" along "<<std::fixed<<std::setprecision(1)<<alongTrans[0]<<
" fom "<<longFOM;
2326 myprt<<
" trans "<<alongTrans[1]<<
" fom "<<transFOM;
2327 myprt<<
" prob "<<prob;
2328 myprt<<
" dang1 "<<dang1<<
" fom "<<dang1FOM;
2329 myprt<<
" dang2 "<<dang2<<
" fom "<<dang2FOM;
2330 myprt<<
" vx2Score "<<vx2Score<<
" fom "<<vxFOM;
2331 myprt<<
" chgFrac "<<chgFrac<<
" fom "<<chgFracFOM;
2332 myprt<<
" chgFracBtw "<<chgFracBtw<<
" fom "<<chgFrcBtwFOM;
2333 myprt<<
" FOM "<<fom;
2357 if(tjEnd > 1)
return false;
2359 std::string fcnLabel = inFcnLabel +
".WSTj";
2362 unsigned short otherEnd = 1 - tjEnd;
2364 if(tj.
VtxID[otherEnd] == 0)
return false;
2365 unsigned short ivx = tj.
VtxID[otherEnd] - 1;
2367 if(slc.
vtxs[ivx].Topo != 8 && slc.
vtxs[ivx].Topo != 10)
return false;
2368 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Primary candidate "<<tj.
ID<<
" was split by a 3D vertex";
2377 if(slc.
cots.empty())
return;
2379 std::string fcnLabel = inFcnLabel +
".MNS";
2383 myprt<<fcnLabel<<
" list";
2384 for(
auto&
ss : slc.
cots) {
2385 if(
ss.CTP != inCTP)
continue;
2386 if(
ss.ID == 0)
continue;
2387 myprt<<
" ss.ID "<<
ss.ID<<
" NearTjs";
2388 for(
auto&
id :
ss.NearTjIDs) myprt<<
" "<<id;
2393 bool keepMerging =
true;
2394 while(keepMerging) {
2395 keepMerging =
false;
2396 for(
unsigned short ci1 = 0; ci1 < slc.
cots.size() - 1; ++ci1) {
2398 if(ss1.
CTP != inCTP)
continue;
2399 if(ss1.
ID == 0)
continue;
2400 if(ss1.
TjIDs.empty())
continue;
2402 std::vector<int> ss1list = ss1.
TjIDs;
2404 for(
unsigned short ci2 = ci1 + 1; ci2 < slc.
cots.size(); ++ci2) {
2406 if(ss2.
CTP != inCTP)
continue;
2407 if(ss2.
ID == 0)
continue;
2408 if(ss2.
TjIDs.empty())
continue;
2410 std::vector<int> ss2list = ss2.
TjIDs;
2413 if(shared.empty())
continue;
2416 myprt<<fcnLabel<<
" Merge 2S"<<ss2.
ID<<
" into 2S"<<ss1.
ID<<
"? shared nearby:";
2417 for(
auto tjid : shared) myprt<<
" T"<<tjid;
2420 bool doMerge =
false;
2421 for(
auto& tjID : shared) {
2422 bool inSS1 = (std::find(ss1.
TjIDs.begin(), ss1.
TjIDs.end(), tjID) != ss1.
TjIDs.end());
2423 bool inSS2 = (std::find(ss2.
TjIDs.begin(), ss2.
TjIDs.end(), tjID) != ss2.
TjIDs.end());
2424 if(inSS1 && !inSS2) doMerge =
true;
2425 if(!inSS1 && inSS2) doMerge =
true;
2427 if(inSS1 || inSS2)
continue;
2428 auto& tj = slc.
tjs[tjID - 1];
2430 if(tj.PDGCode == 13 && tj.Pts.size() > 100 && tj.ChgRMS < 0.5) {
2431 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" T"<<tj.ID<<
" looks like a muon. Don't add it";
2438 auto& pfp = slc.
pfps[TInP[0] - 1];
2439 if(pfp.PDGCode == 13 &&
MCSMom(slc, pfp.TjIDs) > 500)
continue;
2442 if(
AddTj(fcnLabel, slc, tjID, ss1,
false, prt)) doMerge =
true;
2444 if(!doMerge)
continue;
2482 if(slc.
cots.empty())
return;
2484 std::string fcnLabel = inFcnLabel +
".MO";
2492 bool didMerge =
true;
2496 for(
unsigned short ict = 0; ict < slc.
cots.size() - 1; ++ict) {
2497 auto& iss = slc.
cots[ict];
2498 if(iss.ID == 0)
continue;
2499 if(iss.TjIDs.empty())
continue;
2500 if(iss.CTP != inCTP)
continue;
2501 for(
unsigned short jct = ict + 1; jct < slc.
cots.size(); ++jct) {
2502 auto& jss = slc.
cots[jct];
2503 if(jss.ID == 0)
continue;
2504 if(jss.TjIDs.empty())
continue;
2505 if(jss.CTP != iss.CTP)
continue;
2506 if(
DontCluster(slc, iss.TjIDs, jss.TjIDs))
continue;
2507 bool doMerge =
false;
2508 for(
auto& ivx : iss.Envelope) {
2513 for(
auto& jvx : jss.Envelope) {
2520 for(
auto& ivx : iss.Envelope) {
2521 for(
auto& jvx : jss.Envelope) {
2522 if(
PosSep2(ivx, jvx) < sepCut2) {
2531 if(!doMerge)
continue;
2535 unsigned short iClosePt = 0;
2536 unsigned short jClosePt = 0;
2538 auto& istj = slc.
tjs[iss.ShowerTjID - 1];
2539 auto& jstj = slc.
tjs[jss.ShowerTjID - 1];
2540 for(
unsigned short ipt = 0; ipt < 3; ++ipt) {
2541 for(
unsigned short jpt = 0; jpt < 3; ++jpt) {
2542 float sep =
PosSep2(istj.Pts[ipt].Pos, jstj.Pts[jpt].Pos);
2550 float costh =
DotProd(istj.Pts[0].Dir, jstj.Pts[0].Dir);
2551 if(iClosePt == 0 && jClosePt == 0 && costh < 0.955) {
2552 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" showers are close at the start points with costh "<<costh<<
". Don't merge";
2555 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Merge "<<iss.ID<<
" and "<<jss.ID;
2579 std::string fcnLabel = inFcnLabel +
".MSC";
2581 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
": MergeShowerChain inCTP "<<inCTP;
2583 std::vector<int> sids;
2584 std::vector<TrajPoint> tpList;
2585 for(
unsigned short ict = 0; ict < slc.
cots.size(); ++ict) {
2587 if(iss.
ID == 0)
continue;
2588 if(iss.
TjIDs.empty())
continue;
2589 if(iss.
CTP != inCTP)
continue;
2591 if(iss.
Energy < 50)
continue;
2593 sids.push_back(iss.
ID);
2597 if(sids.size() < 3)
return;
2600 std::vector<SortEntry> sortVec(sids.size());
2601 for(
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
2602 sortVec[ii].index = ii;
2603 sortVec[ii].length = tpList[ii].Pos[0];
2605 std::sort(sortVec.begin(), sortVec.end(),
lessThan);
2607 auto ttpList = tpList;
2608 for(
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
2609 unsigned short indx = sortVec[ii].index;
2610 sids[ii] = tsids[indx];
2611 tpList[ii] = ttpList[indx];
2616 float maxDelta = 30;
2617 for(
unsigned short ii = 0; ii < sids.size() - 2; ++ii) {
2618 auto& iss = slc.
cots[sids[ii] - 1];
2619 if(iss.ID == 0)
continue;
2620 unsigned short jj = ii + 1;
2621 auto& jss = slc.
cots[sids[jj] - 1];
2622 if(jss.ID == 0)
continue;
2623 std::vector<int> chain;
2624 float sepij =
PosSep(tpList[ii].Pos, tpList[jj].Pos);
2625 if(sepij > minSep)
continue;
2626 bool skipit =
DontCluster(slc, iss.TjIDs, jss.TjIDs);
2627 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" i2S"<<iss.ID<<
" "<<
PrintPos(slc, tpList[ii].Pos)<<
" j2S"<<jss.ID<<
" "<<
PrintPos(slc, tpList[jj].Pos)<<
" sepij "<<sepij<<
" skipit? "<<skipit;
2628 if(skipit)
continue;
2633 for(
unsigned short kk = jj + 1; kk < sids.size(); ++kk) {
2634 auto& kss = slc.
cots[sids[kk] - 1];
2635 if(kss.ID == 0)
continue;
2636 if(
DontCluster(slc, iss.TjIDs, kss.TjIDs))
continue;
2637 if(
DontCluster(slc, jss.TjIDs, kss.TjIDs))
continue;
2638 float sepjk =
PosSep(tpList[jj].Pos, tpList[kk].Pos);
2639 float delta =
PointTrajDOCA(slc, tpList[kk].Pos[0], tpList[kk].Pos[1], tp);
2642 myprt<<fcnLabel<<
" k2S"<<kss.ID<<
" "<<
PrintPos(slc, tpList[kk].Pos)<<
" sepjk "<<sepjk<<
" delta "<<delta;
2643 if(sepjk > minSep || delta > maxDelta) {
2644 myprt<<
" failed separation "<<minSep<<
" or delta cut "<<maxDelta;
2646 myprt<<
" add to the chain";
2649 if(sepjk > minSep || delta > maxDelta) {
2651 if(chain.size() > 2) {
2656 myprt<<fcnLabel<<
" merged chain";
2657 for(
auto ssID : chain) myprt<<
" 2S"<<ssID;
2658 myprt<<
" -> 2S"<<newID;
2667 chain[0] = sids[ii]; chain[1] = sids[jj]; chain[2] = sids[kk];
2669 chain.push_back(sids[kk]);
2677 if(chain.size() > 2) {
2687 myprt<<fcnLabel<<
" merged chain";
2688 for(
auto ssID : chain) myprt<<
" "<<ssID;
2689 myprt<<
" -> new ssID "<<newID;
2706 std::string fcnLabel = inFcnLabel +
".MSSTj";
2713 std::vector<TjSS> tjss;
2716 std::vector<int> tjid(1);
2717 for(
auto&
ss : slc.
cots) {
2718 if(
ss.ID == 0)
continue;
2719 if(
ss.CTP != inCTP)
continue;
2721 if(
ss.Energy > 300)
continue;
2722 auto& stj = slc.
tjs[
ss.ShowerTjID - 1];
2723 auto stp0 = stj.Pts[0];
2724 float bestDang = 0.3;
2727 for(
auto& tj : slc.
tjs) {
2728 if(tj.AlgMod[
kKilled])
continue;
2729 if(tj.AlgMod[
kHaloTj])
continue;
2730 if(tj.CTP !=
ss.CTP)
continue;
2732 if(tj.SSID > 0)
continue;
2740 float tjEnergy =
ChgToMeV(tj.TotChg);
2742 unsigned short farEnd =
FarEnd(slc, tj, stj.Pts[1].Pos);
2744 unsigned short midpt = 0.5 * (tj.EndPt[0] + tj.EndPt[1]);
2745 float mom1 =
MCSMom(slc, tj, tj.EndPt[farEnd], midpt);
2746 float mom2 =
MCSMom(slc, tj, tj.EndPt[1 - farEnd], midpt);
2747 float asym = (mom1 - mom2) / (mom1 + mom2);
2748 auto& farTP = tj.Pts[tj.EndPt[farEnd]];
2750 float doca =
PointTrajDOCA(slc, stp0.Pos[0], stp0.Pos[1], farTP);
2751 float sep =
PosSep(farTP.Pos, stp0.Pos);
2752 float dang = doca / sep;
2755 myprt<<fcnLabel<<
" Candidate 2S"<<
ss.ID<<
" T"<<tj.ID<<
"_"<<farEnd;
2756 myprt<<
" ShEnergy "<<(int)
ss.Energy<<
" tjEnergy "<<(
int)tjEnergy;
2757 myprt<<
" doca "<<doca<<
" sep "<<sep<<
" dang "<<dang<<
" asym "<<asym;
2759 if(tjEnergy <
ss.Energy)
continue;
2760 if(asym < 0.5)
continue;
2763 if(sep > 100)
continue;
2764 if(dang > bestDang)
continue;
2768 if(bestTj == 0)
continue;
2771 match.tjID = bestTj;
2772 match.dang = bestDang;
2773 tjss.push_back(match);
2776 if(tjss.empty())
return;
2779 bool keepGoing =
true;
2782 float bestDang = 0.3;
2784 for(
unsigned short mat = 0;
mat < tjss.size(); ++
mat) {
2785 auto& match = tjss[
mat];
2787 if(match.dang < 0)
continue;
2788 if(match.dang < bestDang) bestMatch =
mat;
2791 auto& match = tjss[bestMatch];
2792 auto&
ss = slc.
cots[match.ssID - 1];
2793 if(!
AddTj(fcnLabel, slc, match.tjID,
ss,
true, prt)) {
2799 auto& stj = slc.
tjs[
ss.ShowerTjID - 1];
2816 std::string fcnLabel = inFcnLabel +
".MSS";
2818 constexpr
float radLen = 14 / 0.3;
2822 mf::LogVerbatim(
"TC")<<fcnLabel<<
" MergeSubShowers checking using ShowerParams";
2824 mf::LogVerbatim(
"TC")<<fcnLabel<<
" MergeSubShowers checking using radiation length cut ";
2828 bool keepMerging =
true;
2829 while(keepMerging) {
2830 keepMerging =
false;
2832 std::vector<SortEntry> sortVec;
2833 for(
auto&
ss : slc.
cots) {
2834 if(
ss.ID == 0)
continue;
2835 if(
ss.CTP != inCTP)
continue;
2838 se.length =
ss.Energy;
2839 sortVec.push_back(se);
2841 if(sortVec.size() < 2)
return;
2842 std::sort(sortVec.begin(), sortVec.end(),
greaterThan);
2843 for(
unsigned short ii = 0; ii < sortVec.size() - 1; ++ii) {
2845 if(iss.
ID == 0)
continue;
2849 double shMaxAlong, along95;
2852 along95 -= shMaxAlong;
2855 for(
unsigned short jj = ii + 1; jj < sortVec.size(); ++jj) {
2857 if(jss.
ID == 0)
continue;
2866 if(alongTrans[0] < 0)
continue;
2868 float alongCut = along95;
2874 myprt<<fcnLabel<<
" Candidate i2S"<<iss.
ID<<
" E = "<<(int)iss.
Energy<<
" j2S"<<jss.
ID<<
" E = "<<(
int)jss.
Energy;
2875 myprt<<
" along "<<std::fixed<<std::setprecision(1)<<alongTrans[0]<<
" trans "<<alongTrans[1];
2876 myprt<<
" alongCut "<<alongCut<<
" probLong "<<probLong<<
" probTran "<<probTran;
2879 if(alongTrans[0] > alongCut)
continue;
2880 if(alongTrans[1] > alongTrans[0])
continue;
2884 float trad = sep / radLen;
2893 float dang = delta / sep;
2894 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Candidate i2S"<<iss.
ID<<
" j2S"<<jss.
ID<<
" separation "<<(int)sep<<
" radiation lengths "<<trad<<
" delta "<<delta<<
" dang "<<dang;
2895 if(trad > 3)
continue;
2897 if(dang > 0.3)
continue;
2900 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Merge them. Re-find shower center, etc";
2908 if(keepMerging)
break;
2922 std::string fcnLabel = inFcnLabel +
".MS";
2923 if(ssIDs.size() < 2)
return 0;
2925 for(
auto ssID : ssIDs)
if(ssID <= 0 || ssID > (
int)slc.
cots.size())
return 0;
2928 auto& ss0 = slc.
cots[ssIDs[0] - 1];
2929 std::vector<int> tjl;
2930 for(
auto ssID : ssIDs) {
2931 auto&
ss = slc.
cots[ssID - 1];
2932 if(
ss.CTP != ss0.CTP)
return 0;
2933 tjl.insert(tjl.end(),
ss.TjIDs.begin(),
ss.TjIDs.end());
2934 if(
ss.SS3ID > 0 && ss3Assn == 0) ss3Assn =
ss.SS3ID;
2935 if(
ss.SS3ID > 0 &&
ss.SS3ID != ss3Assn) {
2936 std::cout<<fcnLabel<<
" Assn conflict \n";
2941 for(
auto tjID : tjl) {
2942 auto& tj = slc.
tjs[tjID - 1];
2943 if(tj.CTP != ss0.CTP || tj.AlgMod[
kKilled]) {
2944 std::cout<<fcnLabel<<
" bad InShower T"<<tjID<<
"\n";
2950 for(
auto ssID : ssIDs) {
2951 auto&
ss = slc.
cots[ssID - 1];
2954 auto& stj = slc.
tjs[
ss.ShowerTjID - 1];
2960 if(newss.ID == 0)
return 0;
2962 for(
auto tid : tjl) {
2963 auto& tj = slc.
tjs[tid - 1];
2966 newss.SS3ID = ss3Assn;
2970 std::cout<<fcnLabel<<
" UpdateShower failed\n";
2976 std::cout<<fcnLabel<<
" StoreShower failed\n";
2991 if(icotID <= 0 || icotID > (
int)slc.
cots.size())
return false;
2993 if(iss.
ID == 0)
return false;
2994 if(iss.
TjIDs.empty())
return false;
2997 if(jcotID <= 0 || jcotID > (
int)slc.
cots.size())
return false;
2999 if(jss.
TjIDs.empty())
return false;
3000 if(jss.
ID == 0)
return false;
3003 if(iss.
CTP != jss.
CTP)
return false;
3005 std::string fcnLabel = inFcnLabel +
".MSAS";
3008 std::cout<<fcnLabel<<
" Error: 2S"<<iss.
ID<<
" and S"<<jss.
ID<<
" have different 2S -> 3S assns\n";
3014 if(!itj.
Pts[1].Hits.empty() || !jtj.
Pts[1].Hits.empty()) {
3015 std::cout<<fcnLabel<<
" Error: These shower Tjs have hits! T"<<itj.
ID<<
" T"<<jtj.
ID<<
"\n";
3022 ktj.
ID = slc.
tjs.size() + 1;
3024 slc.
tjs.push_back(ktj);
3035 std::sort(iss.
TjIDs.begin(), iss.
TjIDs.end());
3037 for(
auto tid : iss.
TjIDs) {
3038 auto& tj = slc.
tjs[tid - 1];
3067 if(istj > slc.
tjs.size() - 1)
return false;
3068 if(jstj > slc.
tjs.size() - 1)
return false;
3073 std::string fcnLabel =
"MSTJ";
3075 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" MergeShowerTjsAndStore Tj IDs "<<itj.
ID<<
" "<<jtj.
ID;
3087 if(icotID == 0)
return false;
3089 if(iss.
ID == 0)
return false;
3090 if(iss.
TjIDs.empty())
return false;
3092 if(jcotID == 0)
return false;
3094 if(jss.
ID == 0)
return false;
3095 if(jss.
TjIDs.empty())
return false;
3109 if(ss.
ID == 0)
return false;
3110 if(ss.
ShPts.empty())
return false;
3112 if(stj.
Pts.size() != 3)
return false;
3114 std::string fcnLabel = inFcnLabel +
".ARP";
3116 for(
auto& tp : stj.
Pts) {
3120 tp.HitPos = {{0.0, 0.0}};
3123 float minAlong = ss.
ShPts[0].RotPos[0];
3124 float maxAlong = ss.
ShPts[ss.
ShPts.size()-1].RotPos[0];
3125 float sectionLength = (maxAlong - minAlong) / 3;
3126 float sec0 = minAlong + sectionLength;
3127 float sec2 = maxAlong - sectionLength;
3129 for(
auto& spt : ss.
ShPts) {
3131 unsigned short ipt = 0;
3132 if(spt.RotPos[0] < sec0) {
3135 }
else if(spt.RotPos[0] > sec2) {
3142 stj.
Pts[ipt].Chg += spt.Chg;
3157 stj.
Pts[ipt].DeltaRMS += spt.Chg * std::abs(spt.RotPos[1]);
3158 ++stj.
Pts[ipt].NTPsFit;
3160 stj.
Pts[ipt].HitPos[0] += spt.Chg * spt.Pos[0];
3161 stj.
Pts[ipt].HitPos[1] += spt.Chg * spt.Pos[1];
3164 for(
auto& tp : stj.
Pts) {
3166 tp.DeltaRMS /= tp.Chg;
3167 tp.HitPos[0] /= tp.Chg;
3168 tp.HitPos[1] /= tp.Chg;
3174 if(stj.
Pts[0].Chg == 0 || stj.
Pts[2].Chg == 0)
return false;
3177 if(stj.
Pts[1].Chg == 0) {
3179 stj.
Pts[1].HitPos[0] = 0.5 * (stj.
Pts[0].HitPos[0] + stj.
Pts[2].HitPos[0]);
3180 stj.
Pts[1].HitPos[1] = 0.5 * (stj.
Pts[0].HitPos[1] + stj.
Pts[2].HitPos[1]);
3182 if(stj.
Pts[2].DeltaRMS > 0) {
3189 myprt<<fcnLabel<<
" 2S"<<ss.
ID;
3190 myprt<<
" HitPos[0] "<<std::fixed<<std::setprecision(1);
3191 myprt<<stj.
Pts[1].HitPos[0]<<
" "<<stj.
Pts[1].HitPos[1]<<
" "<<stj.
Pts[1].HitPos[2];
3192 myprt<<
" DeltaRMS "<<std::setprecision(2);
3193 myprt<<stj.
Pts[0].DeltaRMS<<
" "<<stj.
Pts[1].DeltaRMS<<
" "<<stj.
Pts[2].DeltaRMS;
3194 myprt<<
" DirectionFOM "<<std::fixed<<std::setprecision(2)<<ss.
DirectionFOM;
3205 if(ss.
ID == 0)
return;
3206 if(ss.
TjIDs.empty())
return;
3208 std::string fcnLabel = inFcnLabel +
".RevSh";
3210 std::reverse(ss.
ShPts.begin(), ss.
ShPts.end());
3212 for(
auto& sspt : ss.
ShPts) {
3213 sspt.RotPos[0] = -sspt.RotPos[0];
3214 sspt.RotPos[1] = -sspt.RotPos[1];
3234 if(cotID > (
int)slc.
cots.size())
return;
3236 if(ss.
ID == 0)
return;
3246 for(
auto cid : ss3.
CotIDs) {
3247 if(cid == 0 || (
unsigned short)cid > slc.
cots.size())
continue;
3248 auto&
ss = slc.
cots[cid - 1];
3249 if(
ss.SS3ID > 0 &&
ss.SS3ID != ss3.
ID) {
3250 std::cout<<
"MakeShowerObsolete: 3S"<<ss3.
ID<<
" -> 2S"<<
ss.ID<<
" SS3ID 3S"<<
ss.SS3ID<<
" != "<<ss3.
ID<<
"\n";
3256 std::string fcnLabel = inFcnLabel +
".MSO";
3260 std::cout<<
"MakeShowerObsolete: 3S"<<ss3.
ID<<
" -> P"<<ss3.
PFPIndex+1<<
" assn exists but maybe shouldn't...";
3270 if(ss.
ID == 0)
return;
3272 std::string fcnLabel = inFcnLabel +
".MSO";
3275 if(!stp1.Hits.empty()) {
3276 std::cout<<fcnLabel<<
" Trying to kill shower "<<ss.
ID<<
" that has hits associated with it. Don't do this...\n";
3282 std::vector<int> newCIDs;
3283 for(
auto cid : ss3.CotIDs) {
3284 if(cid != ss.
ID) newCIDs.push_back(cid);
3286 ss3.CotIDs = newCIDs;
3294 for(
auto& tjID : ss.
TjIDs) {
3316 if(tjlist1.empty() || tjlist2.empty())
return false;
3318 for(
auto tid1 : tjlist1) {
3319 for(
auto tid2 : tjlist2) {
3321 if(ttid1 > tid2) std::swap(ttid1, tid2);
3322 for(
auto& dc : slc.
dontCluster)
if(dc.TjIDs[0] == ttid1 && dc.TjIDs[1] == tid2)
return true;
3338 for(
auto& vx3 : slc.
vtx3s) {
3339 if(vx3.ID == 0)
continue;
3340 if(!vx3.Neutrino)
continue;
3341 auto PIn3V =
GetAssns(slc,
"3V", vx3.
ID,
"P");
3342 if(PIn3V.size() < 2)
continue;
3343 Point3_t v3pos = {{vx3.X, vx3.Y, vx3.Z}};
3344 for(
unsigned short ip1 = 0; ip1 < PIn3V.size() - 1; ++ip1) {
3345 auto& p1 = slc.
pfps[PIn3V[ip1] - 1];
3347 if(p1.TjIDs.empty())
continue;
3348 unsigned short p1End = 0;
3349 if(p1.Vx3ID[1] == vx3.ID) p1End = 1;
3354 float p1Sep =
PosSep(p1.XYZ[p1End], v3pos);
3355 for(
unsigned short ip2 = ip1 + 1; ip2 < PIn3V.size(); ++ip2) {
3356 auto& p2 = slc.
pfps[PIn3V[ip2] - 1];
3357 if(p2.TjIDs.empty())
continue;
3358 unsigned short p2End = 0;
3359 if(p2.Vx3ID[1] == vx3.ID) p2End = 1;
3361 float p2Sep =
PosSep(p2.XYZ[p2End], v3pos);
3374 if(p1ShowerLike && p2ShowerLike)
continue;
3376 float costh =
DotProd(p1Dir, p2Dir);
3377 if(costh < 0.92)
continue;
3378 unsigned short closePt1, closePt2;
3379 float doca =
PFPDOCA(p1, p2, closePt1, closePt2);
3380 float minSep = p1Sep;
3381 if(p1Sep < minSep) minSep = p2Sep;
3382 bool allowCluster = (doca < minSep);
3385 std::cout<<
"DDC: P"<<p1.ID<<
" p1ShowerLike "<<p1ShowerLike;
3386 std::cout<<
" P"<<p2.ID<<
" p2ShowerLike "<<p2ShowerLike;
3387 std::cout<<
" costh "<<costh;
3388 std::cout<<
" doca "<<doca;
3389 std::cout<<
" minSep "<<minSep;
3390 std::cout<<
" allowCluster? "<<allowCluster;
3393 if(!allowCluster)
continue;
3396 for(
auto tid1 : p1.TjIDs) {
3397 auto&
t1 = slc.
tjs[tid1 - 1];
3398 for(
auto tid2 : p2.TjIDs) {
3399 auto&
t2 = slc.
tjs[tid2 - 1];
3400 if(
t1.CTP !=
t2.CTP)
continue;
3426 std::vector<int> tjids;
3427 for(
auto& tj : slc.
tjs) {
3428 if(tj.CTP != inCTP)
continue;
3435 if(npwc > 100)
continue;
3442 if(tj.ChgRMS > typicalChgRMS) momCut *= tj.ChgRMS / typicalChgRMS;
3443 if(tj.MCSMom > momCut)
continue;
3449 auto& pfp = slc.
pfps[TInP[0] - 1];
3450 if(pfp.PDGCode == 13 &&
MCSMom(slc, pfp.TjIDs) > 500)
continue;
3453 tjids.push_back(tj.ID);
3456 if(tjids.size() < 2)
return;
3462 unsigned short closePt1;
3463 unsigned short closePt2;
3467 std::vector<ClosePair> cps;
3469 std::vector<int> closeTjs;
3470 for(
unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
3474 for(
unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
3478 if(t1TrackLike && t2TrackLike)
continue;
3479 unsigned short ipt1, ipt2;
3485 if(!T1InP.empty()) {
3487 if(!T2InP.empty()) {
3488 auto& p1 = slc.
pfps[T1InP[0] - 1];
3489 auto& p2 = slc.
pfps[T2InP[0] - 1];
3490 unsigned short closePt1, closePt2;
3491 float doca =
PFPDOCA(p1, p2, closePt1, closePt2);
3507 if(std::find(closeTjs.begin(), closeTjs.end(), t1.
ID) == closeTjs.end()) closeTjs.push_back(t1.
ID);
3508 if(std::find(closeTjs.begin(), closeTjs.end(), t2.
ID) == closeTjs.end()) closeTjs.push_back(t2.
ID);
3512 if(cps.empty())
return;
3515 std::vector<SortEntry> sortVec(closeTjs.size());
3516 for(
unsigned short ii = 0; ii < closeTjs.size(); ++ii) {
3517 sortVec[ii].index = ii;
3518 auto& tj = slc.
tjs[closeTjs[ii] - 1];
3519 sortVec[ii].length =
PosSep(tj.Pts[tj.EndPt[0]].Pos, tj.Pts[tj.EndPt[1]].Pos);
3521 std::sort(sortVec.begin(), sortVec.end(),
greaterThan);
3526 std::vector<int>
tmp(1);
3527 for(
unsigned short ii = 0; ii < sortVec.size(); ++ii) {
3528 unsigned short indx = sortVec[ii].index;
3529 auto&
t1 = slc.
tjs[closeTjs[indx] - 1];
3536 std::vector<int> tlist;
3537 tlist.push_back(
t1.ID);
3542 for(
auto& cp : cps) {
3543 if(cp.used)
continue;
3545 bool isID1 = (std::find(tlist.begin(), tlist.end(), cp.id1) != tlist.end());
3546 bool isID2 = (std::find(tlist.begin(), tlist.end(), cp.id2) != tlist.end());
3547 if(!(isID1 || isID2))
continue;
3549 unsigned short t2id = cp.id1;
3550 if(isID1) t2id = cp.id2;
3551 auto&
t2 = slc.
tjs[t2id - 1];
3557 bool isCloser =
false;
3558 for(
auto& pcp : cps) {
3559 if(
t1.ID == pcp.id1 ||
t1.ID == pcp.id2)
continue;
3560 if(!(
t2.ID == pcp.id1 ||
t2.ID == pcp.id2))
continue;
3561 unsigned short oid = pcp.id1;
3562 if(oid ==
t2.ID) oid = pcp.id2;
3563 auto otj = slc.
tjs[oid - 1];
3564 float otjLen =
PosSep(otj.Pts[otj.EndPt[0]].Pos, otj.Pts[otj.EndPt[1]].Pos);
3566 if(pcp.doca < cp.doca && otjLen > 10) isCloser =
true;
3568 if(isCloser)
continue;
3569 if(std::find(tlist.begin(), tlist.end(),
t2.ID) != tlist.end())
continue;
3571 tlist.push_back(
t2.ID);
3577 if(tlist.size() > 1) {
3579 for(
auto tjid : tlist) {
3580 auto& tj = slc.
tjs[tjid - 1];
3585 tjLists.push_back(tlist);
3600 if(tjLists.size() < 2)
return;
3602 for(
unsigned short ip = 0; ip < tjLists.size() - 1; ++ip) {
3603 auto& ilist = tjLists[ip];
3604 for(
unsigned short jp = ip + 1; jp < tjLists.size(); ++jp) {
3605 auto& jlist = tjLists[jp];
3608 std::cout<<
"******** FindCots conflict:";
3609 for(
auto tid : sij) std::cout<<
" T"<<tid;
3610 std::cout<<
" appears in multiple lists\n";
3637 if(slc.
tjs.size() > 20000)
return;
3645 std::vector<std::vector<int>> tjLists;
3646 std::vector<int> tjids;
3647 for(
auto& tj : slc.
tjs) {
3648 if(tj.CTP != inCTP)
continue;
3649 if(tj.AlgMod[
kKilled])
continue;
3650 if(tj.AlgMod[
kHaloTj])
continue;
3654 bool skipit =
false;
3655 for(
unsigned short end = 0;
end < 2; ++
end)
if(tj.StopFlag[
end][
kBragg]) skipit =
true;
3656 if(skipit)
continue;
3662 if(npwc > 100)
continue;
3669 if(tj.ChgRMS > typicalChgRMS) momCut *= tj.ChgRMS / typicalChgRMS;
3670 if(tj.MCSMom > momCut)
continue;
3673 if(npwc < 3)
continue;
3676 tjids.push_back(tj.ID);
3679 if(tjids.size() < 2)
return;
3681 for(
unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
3684 for(
unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
3686 unsigned short ipt1, ipt2;
3694 if(len1 < len2 && len1 < doca) {
3695 if(len1 < doca)
continue;
3697 if(len2 < doca)
continue;
3701 bool inlist =
false;
3702 for(
unsigned short it = 0; it < tjLists.size(); ++it) {
3703 bool tj1InList = (std::find(tjLists[it].
begin(), tjLists[it].
end(), tj1.
ID) != tjLists[it].end());
3704 bool tj2InList = (std::find(tjLists[it].
begin(), tjLists[it].
end(), tj2.
ID) != tjLists[it].end());
3705 if(tj1InList || tj2InList) {
3707 if(!tj1InList) tjLists[it].push_back(tj1.
ID);
3708 if(!tj2InList) tjLists[it].push_back(tj2.
ID);
3716 std::vector<int> newlist(2);
3717 newlist[0] = tj1.
ID;
3718 newlist[1] = tj2.
ID;
3719 tjLists.push_back(newlist);
3723 if(tjLists.empty())
return;
3726 unsigned short nsh = 0;
3727 for(
auto& tjl : tjLists) {
3729 for(
auto& tjID : tjl) {
3730 auto& tj = slc.
tjs[tjID - 1];
3737 unsigned short nkill = 0;
3738 for(
auto& vx2 : slc.
vtxs) {
3739 if(vx2.ID == 0)
continue;
3740 if(vx2.CTP != inCTP)
continue;
3741 auto TInV2 =
GetAssns(slc,
"2V", vx2.
ID,
"T");
3742 unsigned short nsl = 0;
3743 bool has111 =
false;
3744 for(
auto tid : TInV2) {
3745 auto& tj = slc.
tjs[tid - 1];
3746 if(tj.PDGCode == 111) has111 =
true;
3748 unsigned short nearEnd = 1 -
FarEnd(slc, tj, vx2.Pos);
3749 if(
PosSep(tj.Pts[tj.EndPt[nearEnd]].Pos, vx2.Pos) < 6) ++nsl;
3752 if(nsl < 2)
continue;
3753 if(has111)
continue;
3757 if(prt)
mf::LogVerbatim(
"TC")<<
"TagShowerLike tagged "<<nsh<<
" Tjs and killed "<<nkill<<
" vertices in CTP "<<inCTP;
3771 std::string fcnLabel = inFcnLabel +
".FNTj";
3773 std::vector<int> ntj;
3776 constexpr
float fiveRadLen = 200;
3779 for(
auto vx : slc.
vtxs) {
3780 if(vx.CTP != ss.
CTP)
continue;
3781 if(vx.ID == 0)
continue;
3784 auto vxTjIDs =
GetAssns(slc,
"2V", vx.
ID,
"T");
3785 for(
auto tjID : vxTjIDs) {
3787 if(std::find(ss.
TjIDs.begin(), ss.
TjIDs.end(), tjID) != ss.
TjIDs.end())
continue;
3789 if(std::find(ntj.begin(), ntj.end(), tjID) != ntj.end())
continue;
3790 ntj.push_back(tjID);
3795 for(
auto& tj : slc.
tjs) {
3796 if(tj.CTP != ss.
CTP)
continue;
3797 if(tj.AlgMod[
kKilled])
continue;
3801 if(std::find(ss.
TjIDs.begin(), ss.
TjIDs.end(), tj.ID) != ss.
TjIDs.end())
continue;
3803 if(std::find(ntj.begin(), ntj.end(), tj.ID) != ntj.end())
continue;
3805 if(tj.Pts.size() > 40 && tj.MCSMom > 200) {
3806 float delta =
PointTrajDOCA(slc, stj.Pts[1].Pos[0], stj.Pts[1].Pos[1], tj.Pts[tj.EndPt[0]]);
3809 float doca = fiveRadLen;
3810 unsigned short spt = 0, ipt = 0;
3812 if(doca < fiveRadLen) {
3813 ntj.push_back(tj.ID);
3819 bool isInside =
false;
3820 for(
unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ipt += 3) {
3828 unsigned short ipt = tj.EndPt[1];
3831 if(isInside) ntj.push_back(tj.ID);
3833 if(ntj.size() > 1) std::sort(ntj.begin(), ntj.end());
3834 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Found "<<ntj.size()<<
" Tjs near ss.ID "<<ss.
ID;
3844 if(itj > slc.
tjs.size() - 1)
return;
3849 for(
auto& tp : slc.
tjs[itj].Pts) {
3850 for(
unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3852 if(tp.UseHit[ii])
continue;
3853 unsigned int iht = tp.Hits[ii];
3855 if(slc.
slHits[iht].InTraj <= 0)
continue;
3856 if((
unsigned int)slc.
slHits[iht].InTraj > slc.
tjs.size())
continue;
3859 if(tj.
MCSMom > maxMom)
continue;
3862 if(std::find(list.begin(), list.end(), slc.
slHits[iht].InTraj) != list.end())
continue;
3863 list.push_back(slc.
slHits[iht].InTraj);
3872 if(ss.
ID == 0)
return;
3873 if(ss.
TjIDs.empty())
return;
3876 if(stj.
Pts[0].Pos[0] == 0)
return;
3878 std::string fcnLabel = inFcnLabel +
".DE";
3905 float cs = cos(stp1.
Ang);
3906 float sn = sin(stp1.
Ang);
3909 float pos0 = cs * vtx[0] - sn * vtx[1];
3910 float pos1 = sn * vtx[0] + cs * vtx[1];
3912 vtx[0] = pos0 + stp1.
Pos[0];
3913 vtx[1] = pos1 + stp1.
Pos[1];
3919 myprt<<fcnLabel<<
" 2S"<<ss.
ID<<
" Envelope";
3933 if(ss.
Envelope.empty())
return false;
3934 if(ss.
ID == 0)
return false;
3935 if(ss.
TjIDs.empty())
return false;
3937 std::string fcnLabel = inFcnLabel +
".ATIE";
3941 std::vector<int>
tmp(1);
3942 unsigned short nadd = 0;
3943 for(
auto& tj : slc.
tjs) {
3944 if(tj.CTP != ss.
CTP)
continue;
3945 if(tj.AlgMod[
kKilled])
continue;
3946 if(tj.SSID > 0)
continue;
3949 if(tj.ParentID == 0)
continue;
3951 if(neutPrimTj > 0 && neutPrimTj != tj.ID) {
3958 if(std::find(ss.
TjIDs.begin(), ss.
TjIDs.end(), tj.ID) != ss.
TjIDs.end())
continue;
3965 if(!end0Inside && !end1Inside)
continue;
3966 if(end0Inside && end1Inside) {
3968 if(
AddTj(fcnLabel, slc, tj.
ID, ss,
false, prt)) ++nadd;
3975 if(tj.MCSMom > 200) {
3976 float tjAngle = tj.Pts[tj.EndPt[0]].Ang;
3978 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" high MCSMom "<<tj.MCSMom<<
" dangPull "<<dangPull;
3979 if(dangPull > 2)
continue;
3981 if(
AddTj(fcnLabel, slc, tj.
ID, ss,
false, prt)) {
3984 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" AddTj failed to add T"<<tj.ID;
3989 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" Added "<<nadd<<
" trajectories ";
3994 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" No new trajectories added to envelope ";
4009 if(ss.
Envelope.empty())
return false;
4010 if(ss.
ID == 0)
return false;
4011 if(ss.
TjIDs.empty())
return false;
4014 unsigned short ipl = planeID.
Plane;
4019 std::vector<unsigned int> newHits;
4022 float fLoWire = 1E6;
4028 if(vtx[0] < fLoWire) fLoWire = vtx[0];
4029 if(vtx[0] > fHiWire) fHiWire = vtx[0];
4030 if(vtx[1] < loTick) loTick = vtx[1];
4031 if(vtx[1] > hiTick) hiTick = vtx[1];
4035 unsigned int loWire = std::nearbyint(fLoWire);
4036 unsigned int hiWire = std::nearbyint(fHiWire) + 1;
4038 std::array<float, 2> point;
4039 for(
unsigned int wire = loWire; wire < hiWire; ++wire) {
4042 unsigned int firstHit = (
unsigned int)slc.
wireHitRange[ipl][wire].first;
4043 unsigned int lastHit = (
unsigned int)slc.
wireHitRange[ipl][wire].second;
4044 for(
unsigned int iht = firstHit; iht < lastHit; ++iht) {
4046 if(slc.
slHits[iht].InTraj != 0)
continue;
4049 if(
hit.PeakTime() < loTick)
continue;
4051 if(
hit.PeakTime() > hiTick)
break;
4053 point[0] =
hit.WireID().Wire;
4056 newHits.push_back(iht);
4061 if(newHits.empty()) {
4067 stp0.
Hits.insert(stp0.
Hits.end(), newHits.begin(), newHits.end());
4068 for(
auto& iht: newHits) slc.
slHits[iht].InTraj = stj.
ID;
4080 if(cotID > (
int)slc.
cots.size())
return;
4083 if(ss.
ID == 0)
return;
4084 if(ss.
TjIDs.empty())
return;
4089 std::string fcnLabel = inFcnLabel +
".FSC";
4100 if(schg.empty())
return;
4104 unsigned short startPt = USHRT_MAX;
4106 for(
unsigned short ii = 0; ii < schg.size() - 1; ++ii) {
4107 if(schg[ii] > 0 && schg[ii + 1] > 0) {
4113 if(startPt == USHRT_MAX)
return;
4119 for(
unsigned short ii = startPt; ii < schg.size() - 1; ++ii) {
4121 rms += schg[ii] * schg[ii];
4125 rms = rms - cnt * ave * ave;
4127 rms = sqrt(rms / (cnt - 1));
4131 myprt<<fcnLabel<<
" schg:";
4132 for(
unsigned short ii = 0; ii < 20; ++ii) myprt<<
" "<<(
int)schg[ii];
4133 myprt<<
"\n First guess at the charge "<<(int)chg<<
" average charge of all bins "<<(
int)ave<<
" rms "<<(int)rms;
4142 unsigned short nBinsAverage = 5;
4143 double maxChg = 2 * chg;
4144 for(
unsigned short nit = 0; nit < 2; ++nit) {
4148 for(
unsigned short ii = startPt; ii < schg.size() - 1; ++ii) {
4150 if(schg[ii] > maxChg && schg[ii + 1] > maxChg)
break;
4152 if(schg[ii] == 0 && schg[ii + 1] == 0)
break;
4153 if(schg[ii] > maxChg)
continue;
4155 sum2 += schg[ii] * schg[ii];
4157 if(cnt == nBinsAverage)
break;
4161 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" nit "<<nit<<
" cnt "<<cnt<<
" is too low. sum "<<(int)sum<<
" maxChg "<<(
int)maxChg;
4164 chg = schg[startPt];
4170 double arg = sum2 - cnt * chg * chg;
4172 rms = sqrt(arg / (cnt - 1));
4174 double maxrms = 0.5 * sum;
4175 if(rms > maxrms) rms = maxrms;
4176 maxChg = chg + 2 * rms;
4177 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" nit "<<nit<<
" cnt "<<cnt<<
" chg "<<(int)chg<<
" rms "<<(
int)rms<<
" maxChg "<<(int)maxChg<<
" nBinsAverage "<<nBinsAverage;
4183 if(prt)
mf::LogVerbatim(
"TC")<<fcnLabel<<
" 2S"<<cotID<<
" Starting charge "<<(int)stp0.AveChg<<
" startPt "<<startPt;
4193 constexpr
unsigned short nbins = 20;
4194 std::vector<float> schg(nbins);
4195 if(ss.
ID == 0)
return schg;
4196 if(ss.
TjIDs.empty())
return schg;
4201 float minAlong = ss.
ShPts[0].RotPos[0] - 2;
4206 float cs = cos(-ss.
Angle);
4207 float sn = sin(-ss.
Angle);
4208 std::array<float, 2> chgPos;
4211 for(
auto& sspt : ss.
ShPts) {
4212 unsigned short indx = (
unsigned short)((sspt.RotPos[0] - minAlong));
4213 if(indx > nbins - 1)
break;
4215 if(std::abs(sspt.RotPos[1]) > maxTrans)
continue;
4216 unsigned int iht = sspt.HitIndex;
4218 float peakTime =
hit.PeakTime();
4219 float amp =
hit.PeakAmplitude();
4220 float rms =
hit.RMS();
4221 chgPos[0] =
hit.WireID().Wire - stp1.
Pos[0];
4222 for(
float time = peakTime - 2.5 * rms; time < peakTime + 2.5 * rms; ++time) {
4224 along = cs * chgPos[0] - sn * chgPos[1];
4225 if(along < minAlong)
continue;
4226 indx = (
unsigned short)(along - minAlong);
4227 if(indx > nbins - 1)
continue;
4228 arg = (time - peakTime) / rms;
4229 schg[indx] += amp * exp(-0.5 * arg * arg);
4243 if(cotID > (
int)slc.
cots.size())
return;
4246 if(ss.
ID == 0)
return;
4247 if(ss.
TjIDs.empty())
return;
4248 std::cout<<
"PTS Pos0 Pos1 RPos0 RPos1 Chg TID\n";
4250 std::cout<<
"PTS "<<std::fixed<<std::setprecision(1)<<
pt.Pos[0]<<
" "<<
pt.Pos[1]<<
" "<<
pt.RotPos[0]<<
" "<<
pt.RotPos[1];
4251 std::cout<<
" "<<(int)
pt.Chg<<
" "<<
pt.TID;
4322 bool newShowers =
false;
4323 for(
auto&
ss : slc.
cots) {
4324 if(
ss.ID == 0)
continue;
4325 if(
ss.ShowerTjID == 0)
continue;
4328 if(!stj.
Pts[1].Hits.empty()) {
4329 std::cout<<
"TTjH: ShowerTj T"<<stj.
ID<<
" already has "<<stj.
Pts[1].Hits.size()<<
" hits\n";
4333 for(
auto& tjID :
ss.TjIDs) {
4334 unsigned short itj = tjID - 1;
4336 std::cout<<
"TTjH: Coding error. T"<<tjID<<
" is a ShowerTj but is in TjIDs\n";
4339 if(slc.
tjs[itj].SSID <= 0) {
4340 std::cout<<
"TTjH: Coding error. Trying to transfer T"<<tjID<<
" hits but it isn't an InShower Tj\n";
4345 stj.
Pts[1].Hits.insert(stj.
Pts[1].Hits.end(), thits.begin(), thits.end());
4350 for(
auto& iht : stj.
Pts[1].Hits) slc.
slHits[iht].InTraj = stj.
ID;
4361 for(
unsigned short ii = 0; ii < slc.
cots.size(); ++ii) {
4362 if(ShowerTjID == slc.
cots[ii].ShowerTjID)
return ii + 1;
4371 if(ss3.
ID == 0)
return 0;
4372 if(ss3.
Energy.empty())
return 0;
4377 ave /= ss3.
Energy.size();
4385 if(tjIDs.empty())
return 0;
4387 for(
auto tid : tjIDs) {
4388 auto& tj = slc.
tjs[tid - 1];
4408 std::string fcnLabel = inFcnLabel +
".S3S";
4410 std::cout<<fcnLabel<<
" Invalid ID";
4413 if(ss3.
CotIDs.size() < 2) {
4414 std::cout<<fcnLabel<<
" not enough CotIDs";
4419 for(
auto&
ss : slc.
cots) {
4420 if(
ss.ID == 0)
continue;
4422 std::cout<<fcnLabel<<
" Bad assn: 2S"<<
ss.ID<<
" -> 3S"<<ss3.
ID<<
" but it's not inCotIDs.\n";
4428 for(
auto cid : ss3.
CotIDs) {
4429 if(cid <= 0 || cid > (
int)slc.
cots.size())
return false;
4430 auto&
ss = slc.
cots[cid - 1];
4431 if(
ss.SS3ID > 0 &&
ss.SS3ID != ss3.
ID) {
4432 std::cout<<fcnLabel<<
" Bad assn: 3S"<<ss3.
ID<<
" -> 2S"<<cid<<
" but 2S -> 3S"<<
ss.SS3ID<<
"\n";
4438 for(
auto cid : ss3.
CotIDs) slc.
cots[cid - 1].SS3ID = ss3.
ID;
4452 std::string fcnLabel = inFcnLabel +
".S2S";
4454 std::cout<<fcnLabel<<
" Invalid ID";
4457 if(ss.
TjIDs.empty()) {
4458 std::cout<<fcnLabel<<
" Fail: No TjIDs in 2S"<<ss.
ID<<
"\n";
4463 std::cout<<fcnLabel<<
" Fail: 2S"<<ss.
ID<<
" has an invalid ParentID T"<<ss.
ParentID<<
"\n";
4467 std::cout<<fcnLabel<<
" Fail: 2S"<<ss.
ID<<
" ParentID is not in TjIDs.\n";
4473 if(ss.
ID != (
int)slc.
cots.size() + 1) {
4474 std::cout<<fcnLabel<<
" Correcting the ID 2S"<<ss.
ID<<
" -> 2S"<<slc.
cots.size() + 1;
4475 ss.
ID = slc.
cots.size() + 1;
4479 for(
auto& tjID : ss.
TjIDs) {
4489 slc.
cots.push_back(ss);
4523 stj.
CTP = slc.
tjs[tjl[0]-1].CTP;
4527 for(
auto& stp : stj.
Pts) {
4534 stj.
ID = slc.
tjs.size() + 1;
4538 slc.
tjs.push_back(stj);
4540 ss.
ID = slc.
cots.size() + 1;
4545 for(
auto tjid : tjl) {
4546 auto& tj = slc.
tjs[tjid - 1];
4547 if(tj.CTP != stj.
CTP) {
4564 std::string fcnLabel = inFcnLabel +
".ChkAssns";
4565 for(
auto&
ss : slc.
cots) {
4566 if(
ss.ID == 0)
continue;
4567 for(
auto tid :
ss.TjIDs) {
4568 auto& tj = slc.
tjs[tid - 1];
4569 if(tj.SSID !=
ss.ID) {
4570 std::cout<<fcnLabel<<
" ***** Error: 2S"<<
ss.ID<<
" -> TjIDs T"<<tid<<
" != tj.SSID 2S"<<tj.SSID<<
"\n";
4575 if(
ss.SS3ID > 0 &&
ss.SS3ID <= (
int)slc.
showers.size()) {
4577 if(std::find(ss3.CotIDs.begin(), ss3.CotIDs.end(),
ss.ID) == ss3.CotIDs.end()) {
4578 std::cout<<fcnLabel<<
" ***** Error: 2S"<<
ss.ID<<
" -> 3S"<<
ss.SS3ID<<
" but the shower says no\n";
4583 for(
auto& tj : slc.
tjs) {
4584 if(tj.AlgMod[
kKilled])
continue;
4586 std::cout<<fcnLabel<<
" ***** Error: T"<<tj.ID<<
" tj.SSID is fubar\n";
4590 if(tj.SSID == 0)
continue;
4591 auto&
ss = slc.
cots[tj.SSID - 1];
4592 if(std::find(
ss.TjIDs.begin(),
ss.TjIDs.end(), tj.ID) !=
ss.TjIDs.end())
continue;
4593 std::cout<<fcnLabel<<
" ***** Error: T"<<tj.ID<<
" tj.SSID = 2S"<<tj.SSID<<
" but the shower says no\n";
4597 for(
auto& ss3 : slc.
showers) {
4598 if(ss3.ID == 0)
continue;
4599 for(
auto cid : ss3.CotIDs) {
4600 auto&
ss = slc.
cots[cid - 1];
4601 if(
ss.SS3ID != ss3.ID) {
4602 std::cout<<fcnLabel<<
" ***** Error: 3S"<<ss3.ID<<
" -> 2S"<<cid<<
" but it thinks it belongs to 3S"<<
ss.SS3ID<<
"\n";
4613 if(slc.
showers.empty())
return;
4615 myprt<<fcnLabel<<
" 3D showers \n";
4616 for(
auto& ss3 : slc.
showers) {
4617 myprt<<fcnLabel<<
" 3S"<<ss3.ID<<
" 3V"<<ss3.Vx3ID;
4618 myprt<<
" parentID "<<ss3.ParentID;
4619 myprt<<
" ChgPos"<<std::fixed;
4620 for(
unsigned short xyz = 0; xyz < 3; ++xyz) myprt<<
" "<<std::setprecision(0)<<ss3.ChgPos[xyz];
4622 for(
unsigned short xyz = 0; xyz < 3; ++xyz) myprt<<
" "<<std::setprecision(2)<<ss3.Dir[xyz];
4623 myprt<<
" posInPlane";
4624 std::vector<float> projInPlane(slc.
nPlanes);
4625 for(
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
4626 CTP_t inCTP =
EncodeCTP(ss3.TPCID.Cryostat, ss3.TPCID.TPC, plane);
4627 auto tp =
MakeBareTP(slc, ss3.ChgPos, ss3.Dir, inCTP);
4629 projInPlane[plane] = tp.Delta;
4631 myprt<<
" projInPlane";
4632 for(
unsigned short plane = 0; plane < slc.
nPlanes; ++plane) {
4633 myprt<<
" "<<std::fixed<<std::setprecision(2)<<projInPlane[plane];
4635 for(
auto cid : ss3.CotIDs) {
4636 auto&
ss = slc.
cots[cid - 1];
4637 myprt<<
"\n 2S"<<
ss.ID;
4638 auto& stj = slc.
tjs[
ss.ShowerTjID - 1];
4639 myprt<<
" ST"<<stj.ID;
4640 myprt<<
" "<<
PrintPos(slc, stj.Pts[stj.EndPt[0]].Pos)<<
" - "<<
PrintPos(slc, stj.Pts[stj.EndPt[1]].Pos);
4642 if(ss3.NeedsUpdate) myprt<<
" *** Needs update";
4651 if(slc.
cots.empty())
return;
4656 bool printAllCTP = (inCTP == USHRT_MAX);
4658 unsigned short nlines = 0;
4659 for(
const auto&
ss : slc.
cots) {
4660 if(!printAllCTP &&
ss.CTP != inCTP)
continue;
4661 if(!printKilledShowers &&
ss.ID == 0)
continue;
4665 myprt<<someText<<
" Print2DShowers: Nothing to print";
4670 bool printHeader =
true;
4671 bool printExtras =
false;
4672 for(
unsigned short ict = 0; ict < slc.
cots.size(); ++ict) {
4673 const auto&
ss = slc.
cots[ict];
4674 if(!printAllCTP &&
ss.CTP != inCTP)
continue;
4675 if(!printKilledShowers &&
ss.ID == 0)
continue;
4677 printHeader =
false;
4680 for(
unsigned short ict = 0; ict < slc.
cots.size(); ++ict) {
4681 const auto&
ss = slc.
cots[ict];
4682 if(!printAllCTP &&
ss.CTP != inCTP)
continue;
4683 if(!printKilledShowers &&
ss.ID == 0)
continue;
4684 myprt<<someText<<std::fixed;
4686 myprt<<std::setw(5)<<sid;
4688 for(
auto id :
ss.TjIDs) myprt<<
" T"<<id;
4692 for(
unsigned short ict = 0; ict < slc.
cots.size(); ++ict) {
4693 const auto&
ss = slc.
cots[ict];
4694 if(!printAllCTP &&
ss.CTP != inCTP)
continue;
4695 if(!printKilledShowers &&
ss.ID == 0)
continue;
4696 myprt<<someText<<std::fixed;
4698 myprt<<std::setw(5)<<sid;
4700 for(
auto& vtx :
ss.Envelope) myprt<<
" "<<(int)vtx[0]<<
":"<<(
int)(vtx[1]/
tcc.
unitsPerTick);
4704 for(
unsigned short ict = 0; ict < slc.
cots.size(); ++ict) {
4705 const auto&
ss = slc.
cots[ict];
4706 if(!printAllCTP &&
ss.CTP != inCTP)
continue;
4707 if(!printKilledShowers &&
ss.ID == 0)
continue;
4708 myprt<<someText<<std::fixed;
4710 myprt<<std::setw(5)<<sid;
4712 for(
auto id :
ss.NearTjIDs) myprt<<
" T"<<id;
4716 myprt<<
"DontCluster";
4718 if(dc.TjIDs[0] > 0) myprt<<
" T"<<dc.TjIDs[0]<<
"-T"<<dc.TjIDs[1];
4720 myprt<<
"\nDontCluster";
4721 for(
unsigned short ict = 0; ict < slc.
cots.size(); ++ict) {
4722 const auto& iss = slc.
cots[ict];
4723 if(iss.ID == 0)
continue;
4724 for(
unsigned short jct = ict + 1; jct < slc.
cots.size(); ++jct) {
4725 const auto& jss = slc.
cots[jct];
4726 if(jss.ID == 0)
continue;
4727 if(
DontCluster(slc, iss.TjIDs, jss.TjIDs)) myprt<<
" 2S"<<iss.ID<<
"-2S"<<jss.ID;
4739 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";
4742 myprt<<someText<<std::fixed;
4744 myprt<<std::setw(5)<<sid;
4745 myprt<<std::setw(6)<<ss.
CTP;
4748 myprt<<std::setw(7)<<sid;
4749 myprt<<std::setw(7)<<std::setprecision(2)<<ss.
ParentFOM;
4751 myprt<<std::setw(7)<<(int)ss.
Energy;
4752 myprt<<std::setw(5)<<ss.
TjIDs.size();
4753 myprt<<std::setw(6)<<std::setprecision(2)<<ss.
DirectionFOM;
4754 myprt<<std::setw(7)<<std::setprecision(2)<<ss.
AspectRatio;
4757 myprt<<std::setw(5)<<tid;
4758 std::string vid =
"NA";
4760 myprt<<std::setw(5)<<vid;
4761 for(
auto& spt : stj.Pts) {
4762 myprt<<std::setw(10)<<
PrintPos(slc, spt.Pos);
4763 myprt<<std::setw(7)<<std::fixed<<std::setprecision(1)<<spt.Chg/1000;
4765 myprt<<std::setw(5)<<std::setprecision(1)<<spt.DeltaRMS;
4767 myprt<<std::setw(6)<<std::setprecision(2)<<stj.Pts[1].Ang;
4768 std::string sss =
"NA";
4770 myprt<<std::setw(6)<<sss;
4773 if(ss3.PFPIndex >= 0 && ss3.PFPIndex < slc.
pfps.size()) {
4775 myprt<<std::setw(6)<<pid;
4777 myprt<<std::setw(6)<<
"NA";
4780 myprt<<std::setw(6)<<
"NA";
4784 if(!printExtras)
return;
4787 myprt<<someText<<std::fixed;
4789 myprt<<std::setw(5)<<sid;
4791 for(
auto id : ss.
TjIDs) myprt<<
" T"<<id;
4793 myprt<<someText<<std::fixed;
4795 myprt<<std::setw(5)<<sid;
4799 myprt<<someText<<std::fixed;
4801 myprt<<std::setw(5)<<sid;
4803 for(
auto id : ss.
NearTjIDs) myprt<<
" T"<<id;
bool AddTj(std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
bool TransferTjHits(TCSlice &slc, bool prt)
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< Trajectory > tjs
vector of all trajectories in each plane
std::vector< Vtx3Store > vtx3s
3D vertices
void MergeNearby2DShowers(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
void ConfigureMVA(TCConfig &tcc, std::string fMVAShowerParentWeights)
bool MakeBareTrajPoint(TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
bool greaterThan(SortEntry c1, SortEntry c2)
struct of temporary 2D vertices (end points)
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
std::vector< ShowerStruct > cots
void MergeShowerChain(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
std::vector< double > dEdxErr
double InShowerProbLong(double showerEnergy, double along)
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
std::vector< int > NearTjIDs
std::array< double, 3 > Point3_t
std::vector< ShowerStruct3D > showers
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
ShowerStruct3D CreateSS3(TCSlice &slc)
std::array< int, 2 > TjIDs
std::vector< Point2_t > Envelope
void ReverseShower(std::string inFcnLabel, TCSlice &slc, int cotID, bool prt)
unsigned int Nplanes() const
Number of planes in this tpc.
std::vector< unsigned int > PutTrajHitsInVector(Trajectory const &tj, HitStatus_t hitRequest)
void PrintShowers(std::string fcnLabel, TCSlice &slc)
int NeutrinoPrimaryTjID(TCSlice &slc, const Trajectory &tj)
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)
bool MakeTp3(TCSlice &slc, const TrajPoint &itp, const TrajPoint &jtp, TrajPoint3 &tp3, bool findDirection)
The data type to uniquely identify a Plane.
Geometry information for a single TPC.
std::vector< unsigned int > Hits
std::vector< double > MIPEnergy
int GetCotID(TCSlice &slc, int ShowerTjID)
void PrintShower(std::string someText, TCSlice &slc, const ShowerStruct &ss, bool printHeader, bool printExtras)
CryostatID_t Cryostat
Index of cryostat.
void PrintAllTraj(std::string someText, TCSlice &slc, unsigned short itj, unsigned short ipt, bool prtVtx)
bool Reconcile3D(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
bool WrongSplitTj(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, unsigned short tjEnd, ShowerStruct &ss, bool prt)
void KillVerticesInShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
void SaveAllCots(TCSlice &slc, const CTP_t &inCTP, std::string someText)
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
bool dbgSlc
debug only in the user-defined slice? default is all slices
std::vector< unsigned int > lastWire
the last wire with a hit
std::array< int, 2 > Vx3ID
bool IsShowerLike(TCSlice &slc, const std::vector< int > TjIDs)
std::vector< int > CotIDs
double InShowerProbTrans(double showerEnergy, double along, double trans)
std::vector< ShowerPoint > ShPts
void PrintPFPs(std::string someText, TCSlice &slc)
ShowerStruct CreateSS(TCSlice &slc, const std::vector< int > &tjl)
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
bool AddLooseHits(TCSlice &slc, int cotID, bool prt)
bool SetParent(std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, ShowerStruct3D &ss3, bool prt)
bool DontCluster(TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
bool TrajTrajDOCA(TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
void MergeTjList(std::vector< std::vector< int >> &tjList)
std::vector< float > showerTag
[min MCSMom, max separation, min # Tj < separation] for a shower tag
double InShowerProbParam(double showerEnergy, double along, double trans)
TrajPoint MakeBareTP(TCSlice &slc, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
double ShowerParamTransRMS(double showerEnergy, double along)
void AddCloseTjsToList(TCSlice &slc, unsigned short itj, std::vector< int > list)
std::vector< std::vector< std::pair< int, int > > > wireHitRange
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
void DefineEnvelope(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
void FindCots(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, std::vector< std::vector< int >> &tjLists, bool prt)
void MergeSubShowersTj(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
std::vector< DontClusterStruct > dontCluster
void MakeShowerObsolete(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
std::array< float, 2 > Point2_t
float unitsPerTick
scale factor from Tick to WSE equivalent units
std::array< Point3_t, 2 > XYZ
const detinfo::DetectorProperties * detprop
void DumpShowerPts(TCSlice &slc, int cotID)
float ShowerEnergy(TCSlice &slc, const std::vector< int > tjIDs)
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
CTP_t CTP
Cryostat, TPC, Plane code.
bool MergeShowerTjsAndStore(TCSlice &slc, unsigned short istj, unsigned short jstj, bool prt)
void TagShowerLike(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP)
std::vector< TrajPoint > Pts
Trajectory points.
TMVA::Reader * showerParentReader
float Match3DFOM(std::string inFcnLabel, TCSlice &slc, int icid, int jcid, bool prt)
std::vector< evd::details::RawDigitInfo_t >::const_iterator begin(RawDigitCacheDataClass const &cache)
std::array< Vector3_t, 2 > Dir
float ParentFOM(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, unsigned short &tjEnd, ShowerStruct &ss, float &tp1Sep, float &vx2Score, bool prt)
std::vector< float > showerParentVars
void SaveTjInfo(TCSlice &slc, std::vector< std::vector< int >> &tjList, std::string stageName)
void FindNearbyTjs(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
std::array< unsigned short, 2 > EndPt
First and last point in the trajectory that has charge.
unsigned short PDGCode
shower-like or track-like {default is track-like}
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
void MergeOverlap(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
void MakeTrajectoryObsolete(TCSlice &slc, unsigned int itj)
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
PFPStruct CreateFakePFP(TCSlice &slc, const ShowerStruct3D &ss3)
const geo::GeometryCore * geom
PlaneID_t Plane
Index of the plane within its TPC.
float InShowerProb(TCSlice &slc, const ShowerStruct &ss, const Trajectory &tj)
unsigned short FarEnd(TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
bool SetMag(Vector3_t &v1, double mag)
void ReverseTraj(TCSlice &slc, Trajectory &tj)
bool AddPFP(std::string inFcnLabel, TCSlice &slc, int pID, ShowerStruct3D &ss3, bool doUpdate, bool prt)
int ID
ID that is local to one slice.
std::vector< float > StartChgVec(TCSlice &slc, int cotID, bool prt)
std::vector< TCSlice > slices
std::array< unsigned short, 2 > VtxID
ID of 2D vertex.
Detector simulation of raw signals on wires.
bool lessThan(SortEntry c1, SortEntry c2)
bool AddTjsInsideEnvelope(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
bool StoreShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss)
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
std::bitset< 16 > modes
number of points to find AveChg
std::vector< TCHit > slHits
std::vector< float > chargeCuts
bool FindParent(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
float ChgFracNearPos(TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
bool MergeShowersAndStore(std::string inFcnLabel, TCSlice &slc, int icotID, int jcotID, bool prt)
std::vector< double > EnergyErr
std::vector< double > MIPEnergyErr
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
bool RemoveTj(std::string inFcnLabel, TCSlice &slc, int TjID, ShowerStruct &ss, bool doUpdate, bool prt)
bool FindShowers3D(TCSlice &slc)
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
int MergeShowers(std::string inFcnLabel, TCSlice &slc, std::vector< int > ssIDs, bool prt)
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
PFPStruct CreatePFP(TCSlice &slc)
std::vector< VtxStore > vtxs
2D vertices
std::bitset< 128 > AlgMod
Bit set if algorithm AlgBit_t modifed the trajectory.
std::vector< double > Energy
bool FindShowerStart(TCSlice &slc, ShowerStruct3D &ss3, bool prt)
geo::PlaneID DecodeCTP(CTP_t CTP)
void Match2DShowers(std::string inFcnLabel, TCSlice &slc, bool prt)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
std::vector< recob::Hit > const * allHits
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
std::array< double, 3 > Vector3_t
void DefineDontCluster(TCSlice &slc, bool prt)
int ID
ID of the recob::Slice (not the sub-slice)
bool RemovePFP(std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, ShowerStruct3D &ss3, bool doUpdate, bool prt)
std::vector< T > SetDifference(const std::vector< T > &set1, const std::vector< T > &set2)
void MergeSubShowers(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
void FindStartChg(std::string inFcnLabel, TCSlice &slc, int cotID, bool prt)
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void Finish3DShowers(TCSlice &slc)
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.
std::vector< PFPStruct > pfps
bool AnalyzeRotPos(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
float ChgToMeV(float chg)
float ChgFracBetween(TCSlice &slc, Point3_t pos1, Point3_t pos2)
TPCID_t TPC
Index of the TPC within its cryostat.
std::vector< double > dEdx
void Print2DShowers(std::string someText, TCSlice &slc, CTP_t inCTP, bool printKilledShowers)
bool CompleteIncompleteShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
master switch for turning on debug mode
CTP_t CTP
set to an invalid CTP