17 #include "messagefacility/MessageLogger/MessageLogger.h"
21 #include "range/v3/view.hpp"
24 using namespace ranges;
27 constexpr
double step{0.3};
32 , fFineTuningEps{config.FineTuningEps()}
33 , fTrkValidationDist2D{config.TrkValidationDist2D()}
34 , fHitTestingDist2D{config.HitTestingDist2D()}
35 , fMinTwoViewFraction{config.MinTwoViewFraction()}
36 ,
fGeom{lar::providerFrom<geo::Geometry>()}
51 float const thr)
const
53 unsigned int nAll = 0, nPassed = 0;
54 unsigned int testPlane = adcImage.
Plane();
56 std::vector<unsigned int> trkTPCs = trk.
TPCs();
57 std::vector<unsigned int> trkCryos = trk.
Cryos();
63 for (
auto const* seg : trk.
Segments()) {
74 unsigned tpc = seg->
TPC();
75 unsigned cryo = seg->Cryo();
80 while ((f < 1.0) && node->
SameTPC(
p)) {
82 geo::WireID wireID(cryo, tpc, testPlane, (
int)p2d.X());
84 int widx = (int)p2d.X();
87 if (
fGeom->HasWire(wireID)) {
89 if (channelStatus.
IsGood(ch)) {
90 float max_adc = adcImage.
poolMax(widx, didx, 2);
91 if (max_adc > thr) nPassed++;
106 double v = nPassed / (double)nAll;
107 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
" trk fraction ok: " << v;
115 struct hits_on_plane {
121 unsigned int const plane_;
134 TH1F* histoRejected)
const
136 double max_d = fTrkValidationDist2D;
137 double d2, max_d2 = max_d * max_d;
138 unsigned int nAll = 0, nPassed = 0;
139 unsigned int testPlane = adcImage.
Plane();
141 std::vector<unsigned int> trkTPCs = trk.
TPCs();
142 std::vector<unsigned int> trkCryos = trk.
Cryos();
143 std::map<std::pair<unsigned int, unsigned int>, std::pair<TVector2, TVector2>> ranges;
144 std::map<std::pair<unsigned int, unsigned int>,
double> wirePitch;
145 for (
auto const& [t, c] : views::cartesian_product(trkTPCs, trkCryos)) {
147 wirePitch[{t, c}] =
fGeom->TPC(t, c).Plane(testPlane).WirePitch();
150 unsigned int tpc, cryo;
151 std::map<std::pair<unsigned int, unsigned int>, std::vector<pma::Vector2D>> all_close_points;
155 tpc =
h.WireID().TPC;
156 cryo =
h.WireID().Cryostat;
157 std::pair<unsigned int, unsigned int> tpc_cryo(tpc, cryo);
158 std::pair<TVector2, TVector2> rect = ranges[tpc_cryo];
160 if ((
h.WireID().Wire > rect.first.X() - 10) &&
161 (
h.WireID().Wire < rect.second.X() + 10) &&
162 (
h.PeakTime() > rect.first.Y() - 100) &&
163 (
h.PeakTime() < rect.second.Y() + 100)) {
164 TVector2 p2d(wirePitch[tpc_cryo] *
h.WireID().Wire,
167 d2 = trk.
Dist2(p2d, testPlane, tpc, cryo);
169 if (d2 < max_d2) { all_close_points[tpc_cryo].emplace_back(p2d.X(), p2d.Y()); }
178 for (
auto const* seg : trk.
Segments()) {
194 auto const& points = all_close_points[{tpc, cryo}];
198 double wirepitch =
fGeom->TPC(tpc, cryo).Plane(testPlane).WirePitch();
199 while ((f < 1.0) && node->
SameTPC(
p)) {
201 geo::WireID wireID(cryo, tpc, testPlane, (
int)p2d.X());
203 int widx = (int)p2d.X();
204 int didx = (int)detProp.
ConvertXToTicks(p2d.Y(), testPlane, tpc, cryo);
206 if (
fGeom->HasWire(wireID)) {
208 if (channelStatus.
IsGood(ch)) {
209 bool is_close =
false;
210 float max_adc = adcImage.
poolMax(widx, didx, 2);
213 p2d.SetX(wirepitch * p2d.X());
214 for (
const auto&
h : points) {
227 if (histoPassing) histoPassing->Fill(max_adc);
230 if (histoRejected) histoRejected->Fill(max_adc);
244 double v = nPassed / (double)nAll;
245 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
" trk fraction ok: " << v;
258 const std::vector<art::Ptr<recob::Hit>>& hits)
const
260 if (hits.empty()) {
return 0; }
262 double max_d = fTrkValidationDist2D;
263 double d2, max_d2 = max_d * max_d;
264 unsigned int nAll = 0, nPassed = 0;
265 unsigned int testPlane = hits.front()->WireID().Plane;
267 std::vector<unsigned int> trkTPCs = trk.
TPCs();
268 std::vector<unsigned int> trkCryos = trk.
Cryos();
269 std::map<std::pair<unsigned int, unsigned int>, std::pair<TVector2, TVector2>> ranges;
270 std::map<std::pair<unsigned int, unsigned int>,
double> wirePitch;
271 for (
auto const& [t, c] : views::cartesian_product(trkTPCs, trkCryos)) {
273 wirePitch[{t, c}] =
fGeom->TPC(t, c).Plane(testPlane).WirePitch();
276 unsigned int tpc, cryo;
277 std::map<std::pair<unsigned int, unsigned int>, std::vector<pma::Vector2D>> all_close_points;
281 tpc =
h.WireID().TPC;
282 cryo =
h.WireID().Cryostat;
283 std::pair<unsigned int, unsigned int> tpc_cryo(tpc, cryo);
284 std::pair<TVector2, TVector2> rect = ranges[tpc_cryo];
286 if ((
h.WireID().Wire > rect.first.X() - 10) &&
287 (
h.WireID().Wire < rect.second.X() + 10) &&
288 (
h.PeakTime() > rect.first.Y() - 100) &&
289 (
h.PeakTime() < rect.second.Y() + 100)) {
290 TVector2 p2d(wirePitch[tpc_cryo] *
h.WireID().Wire,
293 d2 = trk.
Dist2(p2d, testPlane, tpc, cryo);
295 if (d2 < max_d2) all_close_points[tpc_cryo].emplace_back(p2d.X(), p2d.Y());
304 for (
auto const* seg : trk.
Segments()) {
320 auto const& points = all_close_points[{tpc, cryo}];
324 double wirepitch =
fGeom->TPC(tpc, cryo).Plane(testPlane).WirePitch();
325 while ((f < 1.0) && node->
SameTPC(
p)) {
327 geo::WireID wireID(cryo, tpc, testPlane, (
int)p2d.X());
328 if (
fGeom->HasWire(wireID)) {
330 if (channelStatus.
IsGood(ch)) {
332 p2d.SetX(wirepitch * p2d.X());
333 for (
const auto&
h : points) {
354 double v = nPassed / (double)nAll;
355 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
" trk fraction ok: " << v;
369 unsigned int testPlane,
371 unsigned int cryo)
const
373 double max_d = fTrkValidationDist2D;
374 double d2, max_d2 = max_d * max_d;
375 unsigned int nAll = 0, nPassed = 0;
380 dc *= step / dc.Mag();
383 double wirepitch =
fGeom->TPC(tpc, cryo).Plane(testPlane).WirePitch();
385 TVector2 p2d(
fGeom->WireCoordinate(p.Y(), p.Z(), testPlane, tpc, cryo), p.X());
386 geo::WireID wireID(cryo, tpc, testPlane, (
int)p2d.X());
387 if (
fGeom->HasWire(wireID)) {
389 if (channelStatus.
IsGood(ch)) {
390 p2d.Set(wirepitch * p2d.X(), p2d.Y());
391 for (
const auto&
h : hits)
392 if ((
h->WireID().Plane == testPlane) && (
h->WireID().TPC == tpc) &&
393 (
h->WireID().Cryostat == cryo)) {
412 double v = nPassed / (double)nAll;
413 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
" segment fraction ok: " << v;
428 while ((idx < trk.
size() - 1) && !trk[idx]->IsEnabled())
430 double l0 = trk.
Length(0, idx + 1);
432 idx = trk.
size() - 1;
433 while ((idx > 1) && !trk[idx]->IsEnabled())
435 double l1 = trk.
Length(idx - 1, trk.
size() - 1);
439 return 1.0 - (l0 + l1) / trk.
Length();
446 int const nSegments = 0.8 * trk_size / sqrt(trk_size);
447 return std::max(
size_t{1},
static_cast<size_t>(nSegments));
454 const std::vector<art::Ptr<recob::Hit>>& hits_2)
const
460 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
"track size: " << trk->
size();
461 std::vector<unsigned int> tpcs = trk->
TPCs();
462 for (
size_t t = 0; t < tpcs.size(); ++t) {
463 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
" tpc:" << tpcs[t];
465 mf::LogVerbatim(
"ProjectionMatchingAlg")
469 size_t nSegments = getSegCount_(trk->
size());
470 size_t nNodes = (size_t)(nSegments - 1);
472 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
" initialize trk";
474 mf::LogWarning(
"ProjectionMatchingAlg") <<
" initialization failed, delete trk";
479 double f = twoViewFraction(*trk);
480 if (f > fMinTwoViewFraction) {
482 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
" optimize trk (" << nSegments <<
" seg)";
484 g = trk->
Optimize(detProp, nNodes, fOptimizationEps,
false,
true, 25,
486 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
" nodes done, g = " <<
g;
489 g = trk->
Optimize(detProp, 0, fFineTuningEps);
490 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
" tune done, g = " <<
g;
497 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
" clusters do not match, f = " << f;
506 const std::vector<art::Ptr<recob::Hit>>& hits)
const
508 std::map<unsigned int, std::vector<art::Ptr<recob::Hit>>> hits_by_tpc;
509 for (
auto const&
h : hits) {
510 hits_by_tpc[
h->WireID().TPC].push_back(
h);
513 std::vector<pma::Track3D*>
tracks;
514 for (
auto const& hsel : hits_by_tpc) {
516 if (trk) tracks.push_back(trk);
519 bool need_reopt =
false;
520 while (tracks.size() > 1) {
525 double d, dmin = 1.0e12;
526 size_t t_best = 0, cfg = 0;
527 for (
size_t t = 1; t < tracks.size(); ++t) {
567 mergeTracks(detProp, *best, *first,
false);
574 mergeTracks(detProp, *first, *best,
false);
578 tracks.erase(tracks.begin() + t_best);
585 if (!tracks.empty()) {
586 trk = tracks.front();
588 double g = trk->
Optimize(detProp, 0, fOptimizationEps);
589 mf::LogVerbatim(
"ProjectionMatchingAlg")
590 <<
" reopt after merging initial tpc segments: done, g = " <<
g;
593 int nSegments = getSegCount_(trk->
size()) - trk->
Segments().size() + 1;
597 size_t nNodes = (size_t)(nSegments - 1);
599 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
" optimize trk (add " << nSegments <<
" seg)";
601 g = trk->
Optimize(detProp, nNodes, fOptimizationEps,
false,
true, 25,
603 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
" nodes done, g = " <<
g;
606 g = trk->
Optimize(detProp, 0, fFineTuningEps);
607 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
" tune done, g = " <<
g;
621 double vtxarray[3]{vtx.X(), vtx.Y(), vtx.Z()};
623 if (!
fGeom->HasTPC(
fGeom->FindTPCAtPosition(vtxarray)))
return 0;
625 TVector3 vtxv3(vtx.X(), vtx.Y(), vtx.Z());
627 const size_t tpc =
fGeom->FindTPCAtPosition(vtxarray).TPC;
628 const size_t cryo =
fGeom->FindCryostatAtPosition(vtxarray);
632 std::vector<art::Ptr<recob::Hit>> hitstpc;
633 for (
size_t h = 0;
h < hits.size(); ++
h)
634 if (hits[
h]->
WireID().TPC == tpc) hitstpc.push_back(hits[
h]);
636 if (!hitstpc.size())
return 0;
638 std::vector<art::Ptr<recob::Hit>> hitstrk;
640 size_t countviews = 0;
642 mf::LogVerbatim(
"ProjectionMatchinAlg") <<
"collecting hits from view: " << view;
649 std::vector<art::Ptr<recob::Hit>> hitsview;
650 for (
size_t h = 0; h < hitstpc.size(); ++
h)
651 if (hitstpc[h]->
WireID().Plane == view) hitsview.push_back(hitstpc[h]);
652 if (!hitsview.size()) {
658 std::vector<art::Ptr<recob::Hit>> hitsfilter;
661 mf::LogVerbatim(
"ProjectionMatchinAlg") <<
"start filter out: ";
662 FilterOutSmallParts(detProp, 2.0, hitsview, hitsfilter, proj_pr);
663 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
"after filter out";
665 for (
size_t h = 0; h < hitsfilter.size(); ++
h)
666 hitstrk.push_back(hitsfilter[h]);
668 if (hitsfilter.size() >= 5) countviews++;
673 if (!hitstrk.size() || (countviews < 2)) {
674 mf::LogWarning(
"ProjectionMatchinAlg") <<
"too few hits, segment not built";
681 trk = buildSegment(detProp, hitstrk, vtxv3);
684 ShortenSeg_(detProp, *trk, tpcgeom);
686 if (trk->
size() < 10) {
687 mf::LogWarning(
"ProjectionMatchingAlg") <<
"too short segment, delete segment";
702 const TVector2& vtx2d)
const
704 size_t min_size = hits_in.size() / 5;
705 if (min_size < 3) min_size = 3;
707 std::vector<size_t> used;
708 std::vector<std::vector<art::Ptr<recob::Hit>>> sub_groups;
709 std::vector<art::Ptr<recob::Hit>> close_hits;
711 float mindist2 = 99999.99;
712 size_t id_sub_groups_save = 0;
714 while (GetCloseHits_(detProp, r2d, hits_in, used, close_hits)) {
716 sub_groups.emplace_back(close_hits);
718 for (
size_t h = 0;
h < close_hits.size(); ++
h) {
721 close_hits[
h]->PeakTime(),
724 close_hits[
h]->
WireID().Cryostat);
727 if (dist2 < mindist2) {
728 id_sub_groups_save = id;
736 for (
size_t i = 0; i < sub_groups.size(); ++i) {
737 if (i == id_sub_groups_save) {
738 for (
auto h : sub_groups[i])
739 hits_out.push_back(
h);
743 for (
size_t i = 0; i < sub_groups.size(); ++i) {
744 if ((i != id_sub_groups_save) && (hits_out.size() < 10) && (sub_groups[i].
size() > min_size))
745 for (
auto h : sub_groups[i])
746 hits_out.push_back(
h);
756 std::vector<size_t>& used,
761 const double gapMargin = 5.0;
764 while ((idx < hits_in.size()) && Has_(used, idx))
767 if (idx < hits_in.size()) {
768 hits_out.push_back(hits_in[idx]);
771 unsigned int tpc = hits_in[idx]->WireID().TPC;
772 unsigned int cryo = hits_in[idx]->WireID().Cryostat;
773 unsigned int view = hits_in[idx]->WireID().Plane;
774 double wirePitch =
fGeom->TPC(tpc, cryo).Plane(view).WirePitch();
777 double r2d2 = r2d * r2d;
778 double gapMargin2 = sqrt(2 * gapMargin * gapMargin);
779 gapMargin2 = (gapMargin2 + r2d) * (gapMargin2 + r2d);
784 for (
size_t i = 0; i < hits_in.size(); i++)
785 if (!Has_(used, i)) {
786 art::Ptr<recob::Hit>
const& hi = hits_in[i];
787 TVector2 hi_cm(wirePitch * hi->WireID().Wire, driftPitch * hi->PeakTime());
791 for (
auto const& ho : hits_out) {
793 TVector2 ho_cm(wirePitch * ho->WireID().Wire, driftPitch * ho->PeakTime());
803 hits_out.push_back(hi);
821 double mse = trk.
GetMse();
822 mf::LogWarning(
"ProjectionMatchingAlg") <<
"initial value of mse: " << mse;
823 while ((mse > 0.5) && TestTrk_(trk, tpcgeom)) {
825 for (
size_t h = 0;
h < trk.
size(); ++
h)
827 trk[
h]->SetEnabled(
false);
829 RemoveNotEnabledHits(trk);
832 trk.
Optimize(detProp, 0, 0.0001,
false);
835 mf::LogWarning(
"ProjectionMatchingAlg") <<
" mse: " << mse;
836 if (mse == trk.
GetMse())
break;
841 RemoveNotEnabledHits(trk);
862 for (
size_t h = 0;
h < trk.
size(); ++
h) {
863 if (!trk[
h]->IsEnabled())
break;
867 mf::LogWarning(
"ProjectionMatchingAlg") <<
"length of segment: " << length;
868 if (length < 3.0) test =
false;
879 if (c == idx)
return true;
889 while (h < trk.
size()) {
890 if (trk[h]->IsEnabled())
902 const std::vector<art::Ptr<recob::Hit>>& hits_2)
const
912 mf::LogWarning(
"ProjectionMatchingAlg") <<
"initialization failed, delete segment";
916 trk->
Optimize(detProp, 0, fFineTuningEps);
922 mf::LogWarning(
"ProjectionMatchingAlg") <<
"need at least two views in single tpc";
933 const TVector3& point)
const
935 pma::Track3D* trk = buildSegment(detProp, hits_1, hits_2);
940 if (dfront > dback) trk->
Flip();
942 trk->
Nodes().front()->SetPoint3D(point);
943 trk->
Nodes().front()->SetFrozen(
true);
944 trk->
Optimize(detProp, 0, fFineTuningEps);
955 const TVector3& point)
const
962 if (dfront > dback) trk->
Flip();
964 trk->
Nodes().front()->SetPoint3D(point);
965 trk->
Nodes().front()->SetFrozen(
true);
966 trk->
Optimize(detProp, 0, fFineTuningEps);
978 bool add_nodes)
const
983 mf::LogVerbatim(
"ProjectionMatchingAlg")
988 size_t nSegments = getSegCount_(copy->
size());
989 int nNodes = nSegments - copy->
Nodes().size() + 1;
990 if (nNodes < 0) nNodes = 0;
993 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
" add " << nNodes <<
" nodes";
994 copy->
Optimize(detProp, nNodes, fOptimizationEps);
997 double g = copy->
Optimize(detProp, 0, fFineTuningEps);
998 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
" reopt done, g = " <<
g;
1013 const std::vector<art::Ptr<recob::Hit>>& hits)
const
1015 size_t nCloseHits = 0;
1016 int forwWires = 3, backWires = -1;
1017 double xMargin = 0.4;
1019 if ((view == (
int)
h->WireID().Plane) && (tpc ==
h->WireID().TPC) &&
1020 (cryo ==
h->WireID().Cryostat)) {
1022 for (
size_t ht = 0; ht < trk.
size(); ht++)
1023 if (trk[ht]->Hit2DPtr().key() ==
h.key()) {
1027 if (found)
continue;
1029 int dw = wdir * (
h->WireID().Wire - wire);
1030 if ((dw <= forwWires) && (dw >= backWires)) {
1032 if (fabs(x - drift_x) < xMargin) nCloseHits++;
1045 const std::map<
unsigned int,
std::vector<art::Ptr<recob::Hit>>>& hits,
1046 std::pair<int, int>
const* wires,
1049 unsigned int cryo)
const
1051 double x = 0.0,
y = 0.0,
z = 0.0;
1052 std::vector<std::pair<int, unsigned int>> wire_view;
1053 for (
unsigned int i = 0; i < 3; i++)
1054 if (wires[i].
first >= 0) {
1055 const auto hiter = hits.find(i);
1056 if (hiter != hits.end()) {
1057 if (chkEndpointHits_(detProp,
1067 wire_view.emplace_back(wires[i].first, i);
1071 if (wire_view.size() > 1) {
1072 x /= wire_view.size();
1076 wire_view[1].second,
1082 mf::LogVerbatim(
"ProjectionMatchingAlg")
1083 <<
"trk tpc:" << tpc <<
" size:" << trk.
size() <<
" add ref.point (" << x <<
"; " <<
y <<
"; "
1088 mf::LogVerbatim(
"ProjectionMatchingAlg")
1089 <<
"trk tpc:" << tpc <<
" size:" << trk.
size()
1090 <<
" wire-plane-parallel track, but need two clean views of endpoint";
1099 const std::map<
unsigned int,
std::vector<art::Ptr<recob::Hit>>>& hits)
const
1103 mf::LogWarning(
"ProjectionMatchingAlg") <<
"Please, apply before TPC stitching.";
1107 const double maxCosXZ = 0.992546;
1112 if ((segFront->
Length() < 0.8) && (segFront1->
Length() > 5.0)) segFront = segFront1;
1116 dirFrontXZ *= 1.0 / dirFrontXZ.R();
1121 if ((segBack->
Length() < 0.8) && (segBack1->
Length() > 5.0)) segBack = segBack1;
1125 dirBackXZ *= 1.0 / dirBackXZ.R();
1127 if ((fabs(dirFrontXZ.Z()) < maxCosXZ) && (fabs(dirBackXZ.Z()) < maxCosXZ)) {
1131 unsigned int nPlanesFront = 0, nPlanesBack = 0;
1132 std::pair<int, int> wiresFront[3], wiresBack[3];
1133 double xFront[3], xBack[3];
1135 for (
unsigned int i = 0; i < 3; i++) {
1136 bool frontPresent =
false, backPresent =
false;
1137 if (
fGeom->TPC(tpc, cryo).HasPlane(i)) {
1138 int idxFront0 = trk.
NextHit(-1, i);
1140 if ((idxFront0 >= 0) && (idxFront0 < (int)trk.
size()) && (idxBack0 >= 0) &&
1141 (idxBack0 < (int)trk.
size())) {
1142 int idxFront1 = trk.
NextHit(idxFront0, i);
1143 int idxBack1 = trk.
PrevHit(idxBack0, i);
1144 if ((idxFront1 >= 0) && (idxFront1 < (
int)trk.
size()) && (idxBack1 >= 0) &&
1145 (idxBack1 < (int)trk.
size())) {
1146 int wFront0 = trk[idxFront0]->Wire();
1147 int wBack0 = trk[idxBack0]->Wire();
1149 int wFront1 = trk[idxFront1]->Wire();
1150 int wBack1 = trk[idxBack1]->Wire();
1152 wiresFront[i].first = wFront0;
1153 wiresFront[i].second = wFront0 - wFront1;
1154 xFront[i] = detProp.
ConvertTicksToX(trk[idxFront0]->PeakTime(), i, tpc, cryo);
1156 wiresBack[i].first = wBack0;
1157 wiresBack[i].second = wBack0 - wBack1;
1158 xBack[i] = detProp.
ConvertTicksToX(trk[idxBack0]->PeakTime(), i, tpc, cryo);
1160 if (wiresFront[i].
second) {
1161 if (wiresFront[i].second > 0)
1162 wiresFront[i].second = 1;
1164 wiresFront[i].second = -1;
1166 frontPresent =
true;
1170 if (wiresBack[i].second) {
1171 if (wiresBack[i].second > 0)
1172 wiresBack[i].second = 1;
1174 wiresBack[i].second = -1;
1182 if (!frontPresent) { wiresFront[i].first = -1; }
1183 if (!backPresent) { wiresBack[i].first = -1; }
1186 bool refAdded =
false;
1187 if ((nPlanesFront > 1) && (fabs(dirFrontXZ.Z()) >= maxCosXZ)) {
1188 refAdded |= addEndpointRef_(detProp, trk, hits, wiresFront, xFront, tpc, cryo);
1191 if ((nPlanesBack > 1) && (fabs(dirBackXZ.Z()) >= maxCosXZ)) {
1192 refAdded |= addEndpointRef_(detProp, trk, hits, wiresBack, xBack, tpc, cryo);
1195 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
"guide wire-plane-parallel track endpoints";
1196 double g = trk.
Optimize(detProp, 0, 0.1 * fFineTuningEps);
1197 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
" done, g = " <<
g;
1207 const std::map<
unsigned int,
std::vector<art::Ptr<recob::Hit>>>& hits)
const
1209 const double maxCosXZ = 0.992546;
1211 unsigned int tpc, cryo;
1225 if (seg1 && (seg0->
Length() < 0.8) && (seg1->
Length() > 5.0)) { seg0 = seg1; }
1228 dir0XZ *= 1.0 / dir0XZ.R();
1230 if (fabs(dir0XZ.Z()) < maxCosXZ) {
return; }
1232 unsigned int nPlanes = 0;
1233 std::pair<int, int> wires[3];
1236 for (
unsigned int i = 0; i < 3; i++) {
1237 bool present =
false;
1238 if (
fGeom->TPC(tpc, cryo).HasPlane(i)) {
1239 int idx0 = -1, idx1 = -1;
1245 if ((idx0 >= 0) && (idx0 < (int)trk.
size()) && (trk[idx0]->
TPC() == tpc) &&
1246 (trk[idx0]->Cryo() == cryo)) {
1252 if ((idx1 >= 0) && (idx1 < (
int)trk.
size()) && (trk[idx1]->
TPC() == tpc) &&
1253 (trk[idx1]->Cryo() == cryo)) {
1254 int w0 = trk[idx0]->Wire();
1255 int w1 = trk[idx1]->Wire();
1257 wires[i].first = w0;
1258 wires[i].second = w0 - w1;
1262 if (wires[i].second > 0)
1263 wires[i].second = 1;
1265 wires[i].second = -1;
1273 if (!present) { wires[i].first = -1; }
1276 if ((nPlanes > 1) && (fabs(dir0XZ.Z()) >= maxCosXZ) &&
1277 addEndpointRef_(detProp, trk, hits, wires, x0, tpc, cryo)) {
1278 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
"guide wire-plane-parallel track endpoint";
1279 double g = trk.
Optimize(detProp, 0, 0.1 * fFineTuningEps);
1280 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
" done, g = " <<
g;
1285 std::vector<pma::Hit3D*>
1297 double dist = distFF;
1300 if (distFB < dist) {
1306 if (distBF < dist) {
1312 if (distBB < dist) {
1322 case 1: mf::LogError(
"PMAlgTrackMaker") <<
"Tracks in reversed order.";
return false;
1328 throw cet::exception(
"pma::ProjectionMatchingAlg")
1329 <<
"alignTracks: should never happen." << std::endl;
1338 bool const reopt)
const
1340 if (!alignTracks(dst, src))
return;
1344 double lmean = dst.
Length() / (dst.
Nodes().size() - 1);
1345 if ((
pma::Dist2(dst.
Nodes().back()->Point3D(), src.
Nodes().front()->Point3D()) > 0.5 * lmean) ||
1347 dst.
AddNode(detProp, src.
Nodes().front()->Point3D(), tpc, cryo);
1348 if (src.
Nodes().front()->IsFrozen()) dst.
Nodes().back()->SetFrozen(
true);
1350 for (
size_t n = 1;
n < src.
Nodes().size();
n++) {
1357 for (
size_t h = 0;
h < src.
size();
h++) {
1361 double g = dst.
Optimize(detProp, 0, fFineTuningEps);
1362 mf::LogVerbatim(
"ProjectionMatchingAlg") <<
" reopt after merging done, g = " <<
g;
1379 unsigned int* nused)
const
1381 for (
size_t i = 0; i < trk.
size(); i++) {
1383 if (hit->
View2D() == view) {
1392 unsigned int nhits = 0;
1393 double last_x, dx = 0.0, last_q, dq = 0.0, dqdx = 0.0;
1394 int ih = trk.
NextHit(-1, view);
1399 if ((ih >= 0) && (ih < (
int)trk.
size())) {
1403 while ((dx < 2.5) && (ih >= 0) && (ih < (
int)trk.
size())) {
1410 if (dx + last_x < 3.0) {
1421 while ((ih >= 0) && (ih < (
int)trk.
size())) {
1428 mf::LogError(
"ProjectionMatchingAlg") <<
"Initial part selection failed.";
1432 mf::LogError(
"ProjectionMatchingAlg") <<
"Initial part too short to select useful hits.";
1435 if (dx > 0.0) dqdx = dq / dx;
1437 if (nused) (*nused) = nhits;
bool SelectHits(float fraction=1.0F)
void AddHits(detinfo::DetectorPropertiesData const &detProp, const std::vector< art::Ptr< recob::Hit >> &hits)
pma::Track3D * buildTrack(const detinfo::DetectorPropertiesData &detProp, const std::vector< art::Ptr< recob::Hit >> &hits_1, const std::vector< art::Ptr< recob::Hit >> &hits_2={}) const
process_name opflash particleana ie ie ie z
bool HasPlane(unsigned int iplane) const
Returns whether a plane with index iplane is present in this TPC.
bool addEndpointRef_(const detinfo::DetectorPropertiesData &detProp, pma::Track3D &trk, const std::map< unsigned int, std::vector< art::Ptr< recob::Hit >>> &hits, std::pair< int, int > const *wires, double const *xPos, unsigned int tpc, unsigned int cryo) const
Functions to help with numbers.
Utilities related to art service access.
double GetMse(unsigned int view=geo::kUnknown) const
MSE of hits weighted with hit amplidudes and wire plane coefficients.
constexpr to_element_t to_element
BEGIN_PROLOG true icarus_rawdigitfilter FilterTools FilterPlane1 Plane
ClusterModuleLabel join with tracks
bool Has_(const std::vector< size_t > &v, size_t idx) const
double Dist2(const TVector2 &p2d, unsigned int view, unsigned int tpc, unsigned int cryo) const
process_name opflash particleana ie x
double Dist2(const TVector2 &v1, const TVector2 &v2)
int PrevHit(int index, unsigned int view=geo::kZ, bool inclDisabled=false) const
double GetXTicksCoefficient(int t, int c) const
pma::Track3D * extendTrack(const detinfo::DetectorPropertiesData &clockData, const pma::Track3D &trk, const std::vector< art::Ptr< recob::Hit >> &hits, bool add_nodes) const
Add more hits to an existing track, reoptimize, optionally add more nodes.
static void SetOptFactor(unsigned int view, float value)
geo::WireID WireID() const
pma::Hit3D const * front() const
float GetSegFraction() const noexcept
Implementation of the Projection Matching Algorithm.
::fhicl::TupleAs< Point(::geo::Length_t,::geo::Length_t,::geo::Length_t)> Point3D
Atom object for reading a 3D point or vector (centimeters).
Geometry information for a single TPC.
std::vector< pma::Node3D * > const & Nodes() const noexcept
TVector3 const & Point3D() const
bool Initialize(detinfo::DetectorPropertiesData const &detProp, float initEndSegW=0.05F)
std::size_t size(FixedBins< T, C > const &) noexcept
Planes which measure Z direction.
void TagOutlier(bool state) noexcept
TVector2 WireDriftToCm(detinfo::DetectorPropertiesData const &detProp, unsigned int wire, float drift, unsigned int plane, unsigned int tpc, unsigned int cryo)
std::vector< unsigned int > TPCs() const
static void SetMargin(double m)
Set allowed node position margin around TPC.
static size_t getSegCount_(size_t trk_size)
unsigned int Plane() const
unsigned int BackTPC() const
recob::tracking::Vector_t Vector3D
double Optimize(const detinfo::DetectorPropertiesData &detProp, int nNodes=-1, double eps=0.01, bool selAllHits=true, bool setAllNodes=true, size_t selSegHits=0, size_t selVtxHits=0)
Main optimization method.
void AddRefPoint(const TVector3 &p)
bool GetCloseHits_(const detinfo::DetectorPropertiesData &detProp, double r2d, const std::vector< art::Ptr< recob::Hit >> &hits_in, std::vector< size_t > &used, std::vector< art::Ptr< recob::Hit >> &hits_out) const
unsigned int NEnabledHits(unsigned int view=geo::kUnknown) const
int TPC(void) const
TPC index or -1 if out of any TPC.
std::vector< unsigned int > Cryos() const
unsigned int BackCryo() const
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
double selectInitialHits(pma::Track3D &trk, unsigned int view=geo::kZ, unsigned int *nused=0) const
void AddNode(pma::Node3D *node)
pma::Hit3D * release_at(size_t index)
unsigned int NHits(unsigned int view) const
process_name opflash particleana ie ie y
std::vector< pma::Segment3D * > const & Segments() const noexcept
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
bool alignTracks(pma::Track3D &first, pma::Track3D &second) const
void SetEndSegWeight(float value) noexcept
unsigned int View2D() const noexcept
double validate_on_adc_test(const detinfo::DetectorPropertiesData &detProp, const lariov::ChannelStatusProvider &channelStatus, const pma::Track3D &trk, const img::DataProviderAlg &adcImage, const std::vector< art::Ptr< recob::Hit >> &hits, TH1F *histoPassing, TH1F *histoRejected) const
void FilterOutSmallParts(const detinfo::DetectorPropertiesData &detProp, double r2d, const std::vector< art::Ptr< recob::Hit >> &hits_in, std::vector< art::Ptr< recob::Hit >> &hits_out, const TVector2 &vtx2d) const
double ConvertXToTicks(double X, int p, int t, int c) const
virtual bool IsGood(raw::ChannelID_t channel) const
Returns whether the specified channel is physical and good.
Class providing information about the quality of channels.
bool SameTPC(const TVector3 &p3d, float margin=0.0F) const
Check if p3d is in the same TPC as the node.
unsigned int FrontTPC() const
unsigned int FrontCryo() const
pma::Track3D * buildSegment(const detinfo::DetectorPropertiesData &clockData, const std::vector< art::Ptr< recob::Hit >> &hits_1, const std::vector< art::Ptr< recob::Hit >> &hits_2={}) const
PlaneID_t Plane
Index of the plane within its TPC.
unsigned int DisableSingleViewEnds()
constexpr auto absDiff(A const &a, B const &b)
Returns the absolute value of the difference between two values.
double ConvertTicksToX(double ticks, int p, int t, int c) const
void push_back(pma::Hit3D *hit)
bool HasTwoViews(size_t nmin=1) const
int Cryo(void) const
Cryostat index or -1 if out of any cryostat.
double Length(size_t step=1) const
bool IsFrozen(void) const
Check if the vertex 3D position is fixed.
double validate(const detinfo::DetectorPropertiesData &detProp, const lariov::ChannelStatusProvider &channelStatus, const pma::Track3D &trk, const std::vector< art::Ptr< recob::Hit >> &hits) const
void ShortenSeg_(const detinfo::DetectorPropertiesData &detProp, pma::Track3D &trk, const geo::TPCGeo &tpcgeom) const
bool chkEndpointHits_(const detinfo::DetectorPropertiesData &detProp, int wire, int wdir, double drift_x, int view, unsigned int tpc, unsigned int cryo, const pma::Track3D &trk, const std::vector< art::Ptr< recob::Hit >> &hits) const
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
pma::Track3D * buildShowerSeg(const detinfo::DetectorPropertiesData &detProp, const std::vector< art::Ptr< recob::Hit >> &hits, const pma::Vector3D &vtx) const
double GetSegmentProjVector(const TVector2 &p, const TVector2 &p0, const TVector2 &p1)
void mergeTracks(const detinfo::DetectorPropertiesData &detProp, pma::Track3D &dst, pma::Track3D &src, bool reopt) const
double GetDistToProj() const
TVector2 GetProjectionToPlane(const TVector3 &p, unsigned int plane, unsigned int tpc, unsigned int cryo)
ProjectionMatchingAlg(const Config &config)
ROOT::Math::DisplacementVector2D< ROOT::Math::Cartesian2D< double > > Vector2D
int NextHit(int index, unsigned int view=geo::kZ, bool inclDisabled=false) const
void guideEndpoints(const detinfo::DetectorPropertiesData &clockData, pma::Track3D &trk, const std::map< unsigned int, std::vector< art::Ptr< recob::Hit >>> &hits) const
Interface for experiment-specific channel quality info provider.
pma::Hit3D const * back() const
std::vector< pma::Hit3D * > trimTrackToVolume(pma::Track3D &trk, TVector3 p0, TVector3 p1) const
double HitDxByView(size_t index, unsigned int view) const
unsigned int Wire() const noexcept
2D representation of charge deposited in the TDC/wire plane
fhicl::Atom< double > OptimizationEps
BEGIN_PROLOG hitmakerfive clustermakerfour pfparticlemakerthree showermakertwo END_PROLOG hitmakerfive clustermakerfour pfparticlemakerthree sequence::inline_paths sequence::inline_paths sequence::inline_paths showermakers test
unsigned int ChannelID_t
Type representing the ID of a readout channel.
bool Flip(const detinfo::DetectorPropertiesData &detProp, std::vector< pma::Track3D * > &allTracks)
float poolMax(int wire, int drift, size_t r=0) const
Pool max value in a patch around the wire/drift pixel.
Interface for experiment-specific service for channel quality info.
void RemoveNotEnabledHits(pma::Track3D &trk) const
double twoViewFraction(pma::Track3D &trk) const
double Length(void) const
physics associatedGroupsWithLeft p1
bool TestTrk_(pma::Track3D &trk, const geo::TPCGeo &tpcgeom) const
art framework interface to geometry description
std::pair< TVector2, TVector2 > WireDriftRange(detinfo::DetectorPropertiesData const &detProp, unsigned int view, unsigned int tpc, unsigned int cryo) const
pma::Track3D * buildMultiTPCTrack(const detinfo::DetectorPropertiesData &clockData, const std::vector< art::Ptr< recob::Hit >> &hits) const
float SummedADC() const noexcept
pma::Vector3D GetDirection3D(void) const override
Get 3D direction cosines of this segment.