16 #include "messagefacility/MessageLogger/MessageLogger.h"
27 std::vector<Point_t> positions;
28 positions.reserve(src.
size());
29 std::vector<Vector_t> momenta;
30 momenta.reserve(src.
size());
31 std::vector<recob::TrajectoryPointFlags> outFlags;
32 outFlags.reserve(src.
size());
34 for (
size_t i = 0,
h = 0; i < src.
size(); i++)
35 if (src[i]->IsEnabled()) {
36 auto const& point3d = src[i]->Point3D();
37 positions.emplace_back(point3d.X(), point3d.Y(), point3d.Z());
60 : fProjectionMatchingAlg(pmalgConfig), fPMAlgVertexing(pmvtxConfig)
62 unsigned int cryo, tpc, view;
63 for (
auto const&
h : allhitlist) {
64 cryo =
h->WireID().Cryostat;
65 tpc =
h->WireID().TPC;
66 view =
h->WireID().Plane;
68 fHitMap[cryo][tpc][view].push_back(
h);
75 for (
auto t : fResult.tracks())
84 for (
auto const& t : tracks.
tracks()) {
85 auto& trk = *(t.Track());
87 unsigned int tpc = trk.FrontTPC(), cryo = trk.FrontCryo();
88 if ((tpc == trk.BackTPC()) && (cryo == trk.BackCryo())) {
89 fProjectionMatchingAlg.guideEndpoints(detProp, trk, fHitMap[cryo][tpc]);
92 fProjectionMatchingAlg.guideEndpoints(
94 fProjectionMatchingAlg.guideEndpoints(
104 const std::vector<recob::Cluster>& clusters,
105 const std::vector<recob::PFParticle>& pfparticles,
106 const art::FindManyP<recob::Hit>& hitsFromClusters,
107 const art::FindManyP<recob::Cluster>& clusFromPfps,
108 const art::FindManyP<recob::Vertex>& vtxFromPfps,
113 , fTrackingOnlyPdg(pmalgFitterConfig.TrackingOnlyPdg())
114 , fTrackingSkipPdg(pmalgFitterConfig.TrackingSkipPdg())
117 mf::LogVerbatim(
"PMAlgFitter") <<
"Found " << allhitlist.size() <<
"hits in the event.";
118 mf::LogVerbatim(
"PMAlgFitter") <<
"Sort hits by clusters assigned to PFParticles...";
121 for (
size_t i = 0; i < pfparticles.size(); ++i) {
124 auto cv = clusFromPfps.at(i);
125 for (
const auto& c : cv) {
128 auto hv = hitsFromClusters.at(c.key());
129 fCluHits[c.key()].reserve(hv.size());
130 for (
auto const&
h : hv)
135 if (vtxFromPfps.isValid() && vtxFromPfps.at(i).size()) {
137 vtxFromPfps.at(i).front()->XYZ(xyz);
142 mf::LogVerbatim(
"PMAlgFitter") <<
"...done, " <<
fCluHits.size() <<
" clusters from "
143 <<
fPfpClusters.size() <<
" pfparticles for 3D tracking.";
152 if (!fPfpClusters.empty() && !fCluHits.empty()) {
154 buildTracks(detProp);
157 guideEndpoints(detProp, fResult);
159 if (fRunVertexing) fPMAlgVertexing.run(detProp, fResult);
162 buildShowers(detProp);
165 mf::LogWarning(
"PMAlgFitter") <<
"no clusters, no pfparticles";
169 return fResult.size();
178 if (!fTrackingSkipPdg.empty() && (fTrackingSkipPdg.front() == 0)) skipPdg =
false;
180 bool selectPdg =
true;
181 if (!fTrackingOnlyPdg.empty() && (fTrackingOnlyPdg.front() == 0)) selectPdg =
false;
183 for (
const auto& pfpCluEntry : fPfpClusters) {
184 int pfPartIdx = pfpCluEntry.first;
185 int pdg = fPfpPdgCodes[pfPartIdx];
188 if (skipPdg && has(fTrackingSkipPdg, pdg))
continue;
189 if (selectPdg && !has(fTrackingOnlyPdg, pdg))
continue;
191 mf::LogVerbatim(
"PMAlgFitter") <<
"Process clusters from PFP:" << pfPartIdx <<
", pdg:" <<
pdg;
193 std::vector<art::Ptr<recob::Hit>> allHits;
196 std::unordered_map<geo::View_t, size_t> clu_count;
197 for (
const auto& c : pfpCluEntry.second) {
198 if (c->NHits() == 0) {
continue; }
200 candidate.
Clusters().push_back(c.key());
201 clu_count[c->View()]++;
203 allHits.reserve(allHits.size() + fCluHits.at(c.key()).
size());
204 for (
const auto&
h : fCluHits.at(c.key())) {
205 allHits.push_back(
h);
208 if (clu_count.size() > 1)
210 candidate.
SetKey(pfpCluEntry.first);
212 candidate.
SetTrack(fProjectionMatchingAlg.buildMultiTPCTrack(detProp, allHits));
216 if (!std::isnan(candidate.
Track()->
Length())) { fResult.push_back(candidate); }
218 mf::LogError(
"PMAlgFitter") <<
"Trajectory fit lenght is nan.";
234 if (!fTrackingSkipPdg.empty() && (fTrackingSkipPdg.front() == 0)) skipPdg =
false;
236 bool selectPdg =
true;
237 if (!fTrackingOnlyPdg.empty() && (fTrackingOnlyPdg.front() == 0)) selectPdg =
false;
239 for (
const auto& pfpCluEntry : fPfpClusters) {
240 int pfPartIdx = pfpCluEntry.first;
241 int pdg = fPfpPdgCodes[pfPartIdx];
243 if (pdg != 11)
continue;
244 if (skipPdg && has(fTrackingSkipPdg, pdg))
continue;
245 if (selectPdg && !has(fTrackingOnlyPdg, pdg))
continue;
247 mf::LogVerbatim(
"PMAlgFitter") <<
"Process clusters from PFP:" << pfPartIdx <<
", pdg:" <<
pdg;
249 std::vector<art::Ptr<recob::Hit>> allHits;
252 std::unordered_map<geo::View_t, size_t> clu_count;
253 for (
const auto& c : pfpCluEntry.second) {
254 if (c->NHits() == 0) {
continue; }
256 candidate.
Clusters().push_back(c.key());
257 clu_count[c->View()]++;
259 allHits.reserve(allHits.size() + fCluHits.at(c.key()).
size());
260 for (
const auto&
h : fCluHits.at(c.key()))
261 allHits.push_back(
h);
263 if (clu_count.size() > 1)
265 candidate.
SetKey(pfpCluEntry.first);
267 mf::LogVerbatim(
"PMAlgFitter") <<
"building..."
270 auto search = fPfpVtx.find(pfPartIdx);
271 if (search != fPfpVtx.end()) {
272 candidate.
SetTrack(fProjectionMatchingAlg.buildShowerSeg(detProp, allHits, search->second));
276 fResult.push_back(candidate);
290 const std::vector<recob::Wire>& wires,
297 const std::vector<TH1F*>& hpassing,
298 const std::vector<TH1F*>& hrejected)
301 , fMinSeedSize1stPass(pmalgTrackerConfig.MinSeedSize1stPass())
302 , fMinSeedSize2ndPass(pmalgTrackerConfig.MinSeedSize2ndPass())
303 , fTrackLikeThreshold(pmalgTrackerConfig.TrackLikeThreshold())
304 , fMinTwoViewFraction(pmalgConfig.MinTwoViewFraction())
305 , fFlipToBeam(pmalgTrackerConfig.
FlipToBeam())
306 , fFlipDownward(pmalgTrackerConfig.FlipDownward())
307 , fFlipToX(pmalgTrackerConfig.FlipToX())
308 , fAutoFlip_dQdx(pmalgTrackerConfig.AutoFlip_dQdx())
310 , fMergeTransverseShift(pmalgTrackerConfig.MergeTransverseShift())
311 , fMergeAngle(pmalgTrackerConfig.MergeAngle())
312 , fCosmicTagger(pmtaggerConfig)
313 , fTagCosmicTracks(fCosmicTagger.tagAny())
314 , fStitchBetweenTPCs(pmalgTrackerConfig.StitchBetweenTPCs())
315 , fStitchDistToWall(pmalgTrackerConfig.StitchDistToWall())
316 , fStitchTransverseShift(pmalgTrackerConfig.StitchTransverseShift())
317 , fStitchAngle(pmalgTrackerConfig.StitchAngle())
318 , fMatchT0inAPACrossing(pmalgTrackerConfig.MatchT0inAPACrossing())
319 , fMatchT0inCPACrossing(pmalgTrackerConfig.MatchT0inCPACrossing())
320 , fStitcher(pmstitchConfig)
322 , fAdcInPassingPoints(hpassing)
323 , fAdcInRejectedPoints(hrejected)
324 ,
fGeom(&*(art::ServiceHandle<geo::Geometry
const>()))
331 mf::LogVerbatim(
"PMAlgTracker") <<
"Using views in the following order:";
333 mf::LogInfo(
"PMAlgTracker") <<
" " << v;
337 mf::LogVerbatim(
"PMAlgTracker") <<
"Validation mode in config: "
341 for (
size_t p = 0;
p < nplanes; ++
p) {
346 else if (pmalgTrackerConfig.
Validation() ==
"adc") {
349 else if (pmalgTrackerConfig.
Validation() ==
"calib") {
353 throw cet::exception(
"pma::PMAlgTracker") <<
"validation name not supported" << std::endl;
357 mf::LogWarning(
"PMAlgTracker")
358 <<
"Not enough planes to perform validation, switch mode to hits.";
364 mf::LogVerbatim(
"PMAlgTracker") <<
"Validation ADC thresholds per plane:";
366 mf::LogVerbatim(
"PMAlgTracker") <<
" " << thr;
375 mf::LogVerbatim(
"PMAlgTracker") <<
"Sort hits by clusters...";
377 fCluHits.reserve(hitsFromClusters.size());
379 fCluWeights.reserve(fCluHits.size());
380 for (
size_t i = 0; i < hitsFromClusters.size(); ++i) {
381 auto v = hitsFromClusters.at(i);
382 fCluHits.push_back(
std::vector<art::Ptr<recob::Hit>>());
383 for (
auto const&
h : v)
384 fCluHits.back().push_back(
h);
385 fCluWeights.push_back(1);
387 mf::LogVerbatim(
"PMAlgTracker") <<
"...done, " << fCluHits.size() <<
" clusters for 3D tracking.";
393 const std::vector<float>& trackLike)
395 mf::LogVerbatim(
"PMAlgTracker") <<
"Filter track-like clusters using likelihood values...";
397 fCluHits.reserve(hitsFromClusters.size());
399 fCluWeights.reserve(fCluHits.size());
400 for (
size_t i = 0; i < hitsFromClusters.size(); ++i) {
401 auto v = hitsFromClusters.at(i);
402 fCluHits.push_back(
std::vector<art::Ptr<recob::Hit>>());
403 for (
auto const&
h : v)
404 fCluHits.back().push_back(
h);
405 fCluWeights.push_back(trackLike[i]);
412 const art::FindManyP<recob::Hit>& hitsFromEmParts)
414 mf::LogVerbatim(
"PMAlgTracker") <<
"Filter track-like clusters...";
416 fCluHits.reserve(hitsFromClusters.size());
418 fCluWeights.reserve(fCluHits.size());
420 for (
size_t i = 0; i < hitsFromClusters.size(); ++i) {
421 auto v = hitsFromClusters.at(i);
422 fCluHits.push_back(
std::vector<art::Ptr<recob::Hit>>());
423 for (
auto const&
h : v) {
425 for (
size_t j = 0; j < hitsFromEmParts.size(); ++j) {
426 auto u = hitsFromEmParts.at(j);
427 for (
auto const&
g : u)
429 if (
g.key() ==
h.key()) {
436 if (trkLike) fCluHits.back().push_back(
h);
438 if (!fCluHits.back().empty()) {
439 fCluWeights.push_back(1);
443 fCluWeights.push_back(0);
446 mf::LogVerbatim(
"PMAlgTracker") <<
"...done, " << n <<
" clusters for 3D tracking.";
453 unsigned int testView)
456 mf::LogVerbatim(
"PMAlgTracker") <<
"first or last node too far out of its initial TPC";
461 mf::LogVerbatim(
"PMAlgTracker") <<
"validation in plane: " << testView;
468 auto const& channelStatus = art::ServiceHandle<lariov::ChannelStatusService const> {}
470 switch (fValidation) {
472 v = fProjectionMatchingAlg.validate_on_adc(
473 detProp, channelStatus, trk, fAdcImages[testView], fAdcValidationThr[testView]);
477 v = fProjectionMatchingAlg.validate(
478 detProp, channelStatus, trk, fHitMap[trk.
FrontCryo()][trk.
FrontTPC()][testView]);
482 v = fProjectionMatchingAlg.validate_on_adc_test(
486 fAdcImages[testView],
488 fAdcInPassingPoints[testView],
489 fAdcInRejectedPoints[testView]);
493 throw cet::exception(
"pma::PMAlgTracker") <<
"validation mode not supported" << std::endl;
511 if ((hits.size() > 1) || (dist2 > 1.0))
515 size_t best_u = 0, n_max = 0;
516 for (
size_t u = 0; u < tracks.
size(); u++)
519 size_t n = fProjectionMatchingAlg.testHits(detProp, *trk2, hits);
527 if (best_trk && (n_max >= hits.size() / 3))
529 mf::LogVerbatim(
"PMAlgTrackMaker") <<
" Reassign(v1) " << n_max <<
" hits." << std::endl;
535 pma::Track3D* ext = fProjectionMatchingAlg.extendTrack(detProp, *best_trk, hits,
false);
538 if (fProjectionMatchingAlg.isContained(*ext)) {
539 tracks[best_u].SetTrack(ext);
545 else if (hits.size() >= fMinSeedSize2ndPass) {
546 size_t minSizeCompl = hits.
size() / 8;
547 if (minSizeCompl < 3) minSizeCompl = 3;
550 unsigned int tpc = hits.front()->WireID().TPC;
551 unsigned int cryo = hits.front()->WireID().Cryostat;
554 matchCluster(detProp, -1, hits, minSizeCompl, tpc, cryo, first_view);
557 mf::LogVerbatim(
"PMAlgTrackMaker")
558 <<
" Add new track, cut hits from source track." << std::endl;
567 else if ((hits.size() == 1) || (dist2 > 2.25))
569 mf::LogVerbatim(
"PMAlgTrackMaker") <<
" Cut single-view isolated hit." << std::endl;
582 while ((idx < trk.
size() - 1) && !(trk[idx]->IsEnabled())) {
583 hits.push_back(trk[idx++]->Hit2DPtr());
588 if ((idx < trk.
size() - 1) && (trk[idx]->View2D() == trk[idx - 1]->View2D())) {
591 if (dprev < dnext) { hits.push_back(trk[idx++]->Hit2DPtr()); }
602 size_t idx = trk.
size() - 1;
603 while ((idx > 0) && !(trk[idx]->IsEnabled())) {
604 hits.push_back(trk[idx--]->Hit2DPtr());
608 if (idx < trk.
size() - 1) {
609 if ((idx > 0) && (trk[idx]->View2D() == trk[idx + 1]->View2D())) {
612 if (dprev < dnext) { hits.push_back(trk[idx--]->Hit2DPtr()); }
624 for (
size_t t = 0; t < tracks.
size(); t++) {
626 if (trk.
size() < 6)
continue;
630 std::vector<art::Ptr<recob::Hit>> hits;
632 double d2 = collectSingleViewEnd(trk, hits);
633 result |= reassignHits_1(detProp, hits, tracks, t, d2);
637 d2 = collectSingleViewFront(trk, hits);
638 result |= reassignHits_1(detProp, hits, tracks, t, d2);
657 double l1 = trk1->
Length();
658 double l2 = trk2->
Length();
665 double d = lmax * distThr;
666 if (d < distThrMin) d = distThrMin;
709 default: mf::LogError(
"PMAlgTracker") <<
"Should never happen.";
714 reverseOrder =
false;
716 size_t nodeEndIdx = trk1->
Nodes().size() - 1;
719 TVector3 trk2front0 = trk2->
Nodes()[0]->Point3D();
720 TVector3 trk2front1 = trk2->
Nodes()[1]->Point3D();
722 double distProj1 = sqrt(
pma::Dist2(endpoint1, proj1));
725 TVector3 trk1back0 = trk1->
Nodes()[nodeEndIdx]->Point3D();
726 TVector3 trk1back1 = trk1->
Nodes()[nodeEndIdx - 1]->Point3D();
728 double distProj2 = sqrt(
pma::Dist2(endpoint2, proj2));
733 cos3d = dir1.Dot(dir2);
735 if ((cos3d > cosThr) && (distProj1 < distProjThr) && (distProj2 < distProjThr))
739 const double maxCosXZ = 0.996195;
742 dir1_xz *= 1.0 / dir1_xz.R();
745 dir2_xz *= 1.0 / dir2_xz.R();
747 if ((fabs(dir1_xz.Z()) > maxCosXZ) && (fabs(dir2_xz.Z()) > maxCosXZ)) {
752 distProj1 = sqrt(
pma::Dist2(endpoint1, proj1));
758 distProj2 = sqrt(
pma::Dist2(endpoint2, proj2));
760 double cosThrXZ = cos(0.5 * acos(cosThr));
761 double distProjThrXZ = 0.5 * distProjThr;
762 double cosXZ = dir1_xz.Dot(dir2_xz);
763 if ((cosXZ > cosThrXZ) && (distProj1 < distProjThrXZ) && (distProj2 < distProjThrXZ))
776 double distThr = 0.25;
777 double distThrMin = 0.5;
779 double distProjThr = fMergeTransverseShift;
780 double cosThr = cos(TMath::Pi() * fMergeAngle / 180.0);
782 bool foundMerge =
false;
787 double d, dmin, c, cmax, l, lbest;
789 while (t < tracks.
size()) {
798 for (u = t + 1; u < tracks.
size(); u++) {
799 trk2 = tracks[u].Track();
800 if (areCoLinear(trk1, trk2, d, c, r, distThr, distThrMin, distProjThr, cosThr)) {
802 if (((c > cmax) && (d < dmin + 0.5 * lbest)) || ((d < dmin) && (l > 1.5 * lbest))) {
815 mf::LogVerbatim(
"PMAlgTracker")
816 <<
"Merge track (" << trk1->
size() <<
") with track (" << trk2->
size() <<
")";
818 fProjectionMatchingAlg.mergeTracks(detProp, *trk2, *trk1,
true);
819 tracks[t].SetTrack(trk2);
822 fProjectionMatchingAlg.mergeTracks(detProp, *trk1, *trk2,
true);
823 tracks[ubest].DeleteTrack();
839 for (
auto const& trk : tracks.
tracks())
840 for (
auto node : trk.Track()->Nodes())
841 if (node->IsBranching()) node->SetFrozen(
true);
846 for (
auto const& trk : tracks.
tracks())
847 for (
auto node : trk.Track()->Nodes())
848 node->SetFrozen(
false);
856 double distThr = 0.25;
857 double distThrMin = 2.5;
859 double distProjThr = fStitchTransverseShift;
860 double cosThr = cos(TMath::Pi() * fStitchAngle / 180.0);
862 double wallDistThr = fStitchDistToWall;
863 double dfront1, dback1, dfront2, dback2;
865 for (
auto& tpc_entry1 : tracks) {
866 unsigned int tpc1 = tpc_entry1.first;
870 while (t < tracks1.
size()) {
871 bool r, reverse =
false;
872 double l, lbest = 0, d, dmin = 1.0e12, c, cmax = 0.0;
874 unsigned int best_tpc = 0;
878 dfront1 = trk1->
Nodes().front()->GetDistToWall();
879 dback1 = trk1->
Nodes().back()->GetDistToWall();
880 if ((dfront1 < wallDistThr) || (dback1 < wallDistThr)) {
881 for (
auto& tpc_entry2 : tracks) {
882 unsigned int tpc2 = tpc_entry2.first;
883 if (tpc2 == tpc1)
continue;
887 for (
size_t u = 0; u < tracks2.
size(); u++) {
889 dfront2 = trk2->
Nodes().front()->GetDistToWall();
890 dback2 = trk2->
Nodes().back()->GetDistToWall();
891 if ((dfront2 < wallDistThr) || (dback2 < wallDistThr)) {
892 if (areCoLinear(trk1, trk2, d, c, r, distThr, distThrMin, distProjThr, cosThr)) {
894 if (((c > cmax) && (d < dmin + 0.5 * lbest)) || (0.75 * l < dmin)) {
910 mf::LogVerbatim(
"PMAlgTracker")
911 <<
"Merge track (" << tpc1 <<
":" << tracks1.
size() <<
":" << trk1->
size()
912 <<
") with track (" << best_tpc <<
":" << tracks[best_tpc].size() <<
":"
913 << best_trk2->
size() <<
")";
914 auto const* geom = lar::providerFrom<geo::Geometry>();
916 geom->TPC(trk1->
Nodes().front()->TPC(), trk1->
Nodes().front()->Cryo());
918 geom->TPC(best_trk2->
Nodes().front()->TPC(), best_trk2->
Nodes().front()->Cryo());
920 fProjectionMatchingAlg.mergeTracks(detProp, *best_trk2, *trk1,
true);
926 tracks1[t].SetTrack(best_trk2);
929 fProjectionMatchingAlg.mergeTracks(detProp, *trk1, *best_trk2,
true);
935 tracks[best_tpc][best_idx].DeleteTrack();
937 tracks[best_tpc].erase_at(best_idx);
951 const std::vector<art::Ptr<recob::Hit>>& hits)
const
954 for (
auto const& t : tracks.
tracks()) {
955 size_t n = fProjectionMatchingAlg.testHits(detProp, *(t.Track()), hits);
956 if (n > max_hits) { max_hits =
n; }
967 fInitialClusters.clear();
968 fTriedClusters.clear();
969 fUsedClusters.clear();
971 size_t nplanes =
fGeom->MaxPlanes();
975 for (
auto tpc_iter =
fGeom->begin_TPC_id(); tpc_iter !=
fGeom->end_TPC_id(); tpc_iter++) {
976 mf::LogVerbatim(
"PMAlgTracker") <<
"Reconstruct tracks within Cryo:" << tpc_iter->Cryostat
977 <<
" / TPC:" << tpc_iter->TPC <<
".";
982 mf::LogVerbatim(
"PMAlgTracker") <<
"Prepare validation ADC images...";
984 for (
size_t p = 0;
p < nplanes; ++
p) {
985 ok &= fAdcImages[
p].setWireDriftData(
986 clockData, detProp, fWires,
p, tpc_iter->TPC, tpc_iter->Cryostat);
988 if (ok) { mf::LogVerbatim(
"PMAlgTracker") <<
" ...done."; }
990 mf::LogVerbatim(
"PMAlgTracker") <<
" ...failed.";
997 detProp, tracks[tpc_iter->TPC], fMinSeedSize1stPass, tpc_iter->TPC, tpc_iter->Cryostat);
1000 detProp, tracks[tpc_iter->TPC], fMinSeedSize2ndPass, tpc_iter->TPC, tpc_iter->Cryostat);
1004 mf::LogVerbatim(
"PMAlgTracker") <<
"Found tracks: " << tracks[tpc_iter->TPC].size();
1005 if (tracks[tpc_iter->TPC].empty()) {
continue; }
1008 guideEndpoints(detProp, tracks[tpc_iter->TPC]);
1011 reassignSingleViewEnds_1(detProp, tracks[tpc_iter->TPC]);
1013 if (fMergeWithinTPC) {
1014 mf::LogVerbatim(
"PMAlgTracker")
1015 <<
"Merge co-linear tracks within TPC " << tpc_iter->TPC <<
".";
1016 while (mergeCoLinear(clockData, detProp, tracks[tpc_iter->TPC])) {
1017 mf::LogVerbatim(
"PMAlgTracker") <<
" found co-linear tracks";
1022 if (fStitchBetweenTPCs) {
1023 mf::LogVerbatim(
"PMAlgTracker") <<
"Stitch co-linear tracks between TPCs.";
1024 mergeCoLinear(clockData, detProp, tracks);
1027 for (
auto& tpc_entry : tracks)
1028 for (
auto& trk : tpc_entry.second.tracks()) {
1029 if (trk.Track()->HasTwoViews() && (trk.Track()->Nodes().size() > 1)) {
1030 fResult.push_back(trk);
1037 if (fTagCosmicTracks) {
1038 mf::LogVerbatim(
"PMAlgTracker") <<
"Tag cosmic tracks activity.";
1039 fCosmicTagger.tag(clockData, fResult);
1042 if (fRunVertexing) {
1043 mf::LogVerbatim(
"PMAlgTracker") <<
"Vertex finding / track-vertex reoptimization.";
1044 fPMAlgVertexing.run(detProp, fResult);
1047 fResult.setTreeIds();
1049 if (fMatchT0inCPACrossing) {
1050 mf::LogVerbatim(
"PMAlgTracker") <<
"Find co-linear CPA-crossing tracks with any T0.";
1051 fStitcher.StitchTracksCPA(clockData, detProp, fResult);
1054 if (fMatchT0inAPACrossing) {
1055 mf::LogVerbatim(
"PMAlgTracker") <<
"Find co-linear APA-crossing tracks with any T0.";
1056 fStitcher.StitchTracksAPA(clockData, detProp, fResult);
1059 if (fTagCosmicTracks) {
1060 mf::LogVerbatim(
"PMAlgTracker") <<
"Second pass cosmic tagging for stitched tracks";
1061 fCosmicTagger.tag(clockData, fResult);
1065 fResult.flipTreesToCoordinate(detProp,
1067 else if (fFlipDownward)
1068 fResult.flipTreesToCoordinate(detProp,
1071 fResult.flipTreesToCoordinate(detProp,
1076 fResult.flipTreesByDQdx();
1078 fResult.setParentDaughterConnections();
1080 listUsedClusters(detProp);
1081 return fResult.size();
1089 size_t minBuildSize,
1093 fInitialClusters.clear();
1095 size_t minSizeCompl = minBuildSize / 8;
1096 if (minSizeCompl < 2) minSizeCompl = 2;
1098 int max_first_idx = 0;
1099 while (max_first_idx >= 0)
1101 mf::LogVerbatim(
"PMAlgTracker") <<
"Find max cluster...";
1104 if ((max_first_idx >= 0) && !fCluHits[max_first_idx].
empty()) {
1105 geo::View_t first_view = fCluHits[max_first_idx].front()->View();
1108 matchCluster(detProp, max_first_idx, minSizeCompl, tpc, cryo, first_view);
1113 mf::LogVerbatim(
"PMAlgTracker") <<
"small clusters only";
1116 fInitialClusters.clear();
1123 const std::vector<art::Ptr<recob::Hit>>& first_hits,
1124 size_t minSizeCompl,
1131 for (
auto av : fAvailableViews) {
1132 fTriedClusters[av].clear();
1135 if (first_clu_idx >= 0) {
1136 fTriedClusters[first_view].push_back((
size_t)first_clu_idx);
1137 fInitialClusters.push_back((
size_t)first_clu_idx);
1140 unsigned int nFirstHits = first_hits.size(), first_plane_idx = first_hits.front()->WireID().Plane;
1141 mf::LogVerbatim(
"PMAlgTracker") << std::endl <<
"--- start new candidate ---";
1142 mf::LogVerbatim(
"PMAlgTracker") <<
"use view *** " << first_view <<
" *** plane idx "
1143 << first_plane_idx <<
" *** size: " << nFirstHits;
1145 float xmax = detProp.
ConvertTicksToX(first_hits.front()->PeakTime(), first_plane_idx, tpc, cryo);
1147 for (
size_t j = 1; j < first_hits.size(); ++j) {
1148 float x = detProp.
ConvertTicksToX(first_hits[j]->PeakTime(), first_plane_idx, tpc, cryo);
1149 if (x > xmax) { xmax =
x; }
1150 if (x < xmin) { xmin =
x; }
1157 bool try_build =
true;
1161 if (first_clu_idx >= 0) candidate.
Clusters().push_back((
size_t)first_clu_idx);
1164 int idx = -1, av_idx = -1;
1165 unsigned int nMaxHits = 0, nHits = 0;
1167 for (
auto av : fAvailableViews) {
1168 if (av == first_view)
continue;
1171 maxCluster(detProp, first_clu_idx, candidates, xmin, xmax, minSizeCompl, av, tpc, cryo);
1173 nHits = fCluHits[av_idx].size();
1174 if ((nHits > nMaxHits) && (nHits >= minSizeCompl)) {
1178 fTriedClusters[av].push_back(idx);
1183 for (
auto av : fAvailableViews) {
1184 if ((av != first_view) && (av != bestView)) {
1191 mf::LogVerbatim(
"PMAlgTracker") <<
"--> " << imatch++ <<
" match with:";
1192 mf::LogVerbatim(
"PMAlgTracker")
1193 <<
" cluster in view *** " << bestView <<
" *** size: " << nMaxHits;
1195 if (!
fGeom->TPC(tpc, cryo).HasPlane(testView)) {
1196 mf::LogVerbatim(
"PMAlgTracker") <<
" no validation plane *** ";
1200 mf::LogVerbatim(
"PMAlgTracker") <<
" validation plane *** " << testView <<
" ***";
1203 double m0 = 0.0, v0 = 0.0;
1204 double mseThr = 0.15, validThr = 0.7;
1206 candidate.
Clusters().push_back(idx);
1207 candidate.
SetTrack(fProjectionMatchingAlg.buildTrack(detProp, first_hits, fCluHits[idx]));
1210 fProjectionMatchingAlg.isContained(*(candidate.
Track()), 2.0
F))
1215 v0 = validate(detProp, *(candidate.
Track()), testView);
1219 if (candidate.
Track() && (m0 < mseThr) && (v0 > validThr))
1221 mf::LogVerbatim(
"PMAlgTracker") <<
" good track candidate, MSE = " << m0 <<
", v = " << v0;
1228 double fraction = 0.5;
1234 matchCluster(detProp, candidate, minSize, fraction,
geo::kUnknown, testView, tpc, cryo);
1238 if (extendTrack(detProp, candidate, fCluHits[idx], testView,
true)) {
1239 candidate.
Clusters().push_back(idx);
1246 mf::LogVerbatim(
"PMAlgTracker") <<
"merge clusters from the validation plane";
1250 bool extended =
false;
1251 while ((idx >= 0) &&
1256 matchCluster(detProp, candidate, minSize, fraction, testView,
geo::kUnknown, tpc, cryo);
1259 if (extendTrack(detProp, candidate, fCluHits[idx],
geo::kUnknown,
false)) {
1260 candidate.
Clusters().push_back(idx);
1269 if (extended) candidate.
SetValidation(validate(detProp, *(candidate.
Track()), testView));
1272 mf::LogVerbatim(
"PMAlgTracker") <<
"track REJECTED, MSE = " << m0 <<
"; v = " << v0;
1279 mf::LogVerbatim(
"PMAlgTracker") <<
"no matching clusters";
1283 if (!candidates.
empty())
1286 double f, max_f = 0., min_mse = 10., max_v = 0.;
1287 for (
size_t t = 0; t < candidates.
size(); t++)
1288 if (candidates[t].IsGood() && (candidates[t].Track()->Nodes().
size() > 1) &&
1289 candidates[t].
Track()->HasTwoViews()) {
1290 f = fProjectionMatchingAlg.twoViewFraction(*(candidates[t].
Track()));
1292 if ((f > max_f) || ((f == max_f) && ((candidates[t].Validation() > max_v) ||
1293 (candidates[t].Mse() < min_mse)))) {
1295 min_mse = candidates[t].Mse();
1296 max_v = candidates[t].Validation();
1301 if ((best_trk > -1) && candidates[best_trk].IsGood() && (max_f > fMinTwoViewFraction)) {
1302 candidates[best_trk].Track()->ShiftEndsToHits();
1304 for (
auto c : candidates[best_trk].Clusters())
1307 result = candidates[best_trk];
1310 for (
size_t t = 0; t < candidates.
size(); t++) {
1311 if (
int(t) != best_trk) candidates[t].DeleteTrack();
1323 unsigned int testView,
1326 double m_max = 2.0 * candidate.
Mse();
1327 if (m_max < 0.05) m_max = 0.05;
1329 double v_min1 = 0.98 * candidate.
Validation();
1330 double v_min2 = 0.9 * candidate.
Validation();
1333 fProjectionMatchingAlg.extendTrack(detProp, *(candidate.
Track()), hits, add_nodes);
1334 double m1 = copy->
GetMse();
1335 double v1 = validate(detProp, *copy, testView);
1337 if (((m1 < candidate.
Mse()) && (v1 >= v_min2)) ||
1338 ((m1 < 0.5) && (m1 <= m_max) && (v1 >= v_min1))) {
1339 mf::LogVerbatim(
"PMAlgTracker") <<
" track EXTENDED, MSE = " << m1 <<
", v = " << v1;
1349 mf::LogVerbatim(
"PMAlgTracker") <<
" track NOT extended, MSE = " << m1 <<
", v = " << v1;
1361 unsigned int preferedView,
1362 unsigned int testView,
1364 unsigned int cryo)
const
1366 double f, fmax = 0.0;
1367 unsigned int n, max = 0;
1369 for (
size_t i = 0; i < fCluHits.size(); ++i) {
1370 if (fCluHits[i].
empty())
continue;
1372 unsigned int view = fCluHits[i].front()->View();
1373 unsigned int nhits = fCluHits[i].size();
1375 if (has(fUsedClusters, i) ||
1377 (view == testView) ||
1379 (view != preferedView)) ||
1383 n = fProjectionMatchingAlg.testHits(detProp, *(trk.
Track()), fCluHits[i]);
1384 f = n / (double)nhits;
1385 if ((f > fraction) && (n > max)) {
1393 mf::LogVerbatim(
"PMAlgTracker") <<
"max matching hits: " << max <<
" (" << fmax <<
")";
1395 mf::LogVerbatim(
"PMAlgTracker") <<
"no clusters to extend the track";
1407 size_t min_clu_size,
1410 unsigned int cryo)
const
1413 size_t s_max = 0,
s;
1414 double fraction = 0.0;
1417 size_t first_idx = 0;
1418 bool has_first =
false;
1419 if (first_idx_tag >= 0) {
1420 first_idx = (size_t)first_idx_tag;
1424 for (
size_t i = 0; i < fCluHits.size(); ++i) {
1425 if ((fCluHits[i].
size() < min_clu_size) || (fCluHits[i].front()->View() != view) ||
1426 has(fUsedClusters, i) || has(fInitialClusters, i) || has(fTriedClusters[view], i))
1429 bool pair_checked =
false;
1430 for (
auto const& c : candidates.
tracks())
1431 if (has_first && has(c.Clusters(), first_idx) && has(c.Clusters(), i)) {
1432 pair_checked =
true;
1435 if (pair_checked)
continue;
1437 const auto& v = fCluHits[i];
1439 if ((v.front()->WireID().TPC == tpc) && (v.front()->WireID().Cryostat == cryo)) {
1441 for (
size_t j = 0; j < v.size(); ++j) {
1443 if ((x >= xmin) && (x <= xmax))
s++;
1449 fraction =
s / (double)v.size();
1453 if (fraction > 0.4)
return idx;
1463 unsigned int cryo)
const
1468 for (
size_t i = 0; i < fCluHits.size(); ++i) {
1469 const auto& v = fCluHits[i];
1471 if (v.empty() || (fCluWeights[i] < fTrackLikeThreshold) || has(fUsedClusters, i) ||
1472 has(fInitialClusters, i) || has(fTriedClusters[view], i) ||
1476 if ((v.front()->WireID().TPC == tpc) && (v.front()->WireID().Cryostat == cryo)) {
1477 size_t s = v.size();
1478 if ((s >= min_clu_size) && (s > s_max)) {
1492 mf::LogVerbatim(
"PMAlgTracker") << std::endl <<
"----------- matched clusters: -----------";
1493 for (
size_t i = 0; i < fCluHits.size(); ++i) {
1494 if (!fCluHits[i].
empty() && has(fUsedClusters, i)) {
1495 mf::LogVerbatim(
"PMAlgTracker")
1496 <<
" tpc: " << fCluHits[i].front()->WireID().TPC
1497 <<
";\tview: " << fCluHits[i].front()->View() <<
";\tsize: " << fCluHits[i].size()
1498 <<
";\tweight: " << fCluWeights[i];
1502 mf::LogVerbatim(
"PMAlgTracker") <<
"--------- not matched clusters: ---------";
1503 size_t nsingles = 0;
1504 for (
size_t i = 0; i < fCluHits.size(); ++i) {
1505 if (!fCluHits[i].
empty() && !has(fUsedClusters, i)) {
1506 if (fCluHits[i].
size() == 1) { nsingles++; }
1508 mf::LogVerbatim(
"PMAlgTracker")
1509 <<
" tpc: " << fCluHits[i].front()->WireID().TPC
1510 <<
";\tview: " << fCluHits[i].front()->View() <<
";\tsize: " << fCluHits[i].size()
1511 <<
";\tweight: " << fCluWeights[i]
1512 <<
";\tmatch: " << matchTrack(detProp, fResult, fCluHits[i]);
1516 mf::LogVerbatim(
"PMAlgTracker") <<
" single hits: " << nsingles;
1517 mf::LogVerbatim(
"PMAlgTracker") <<
"-----------------------------------------";
bool SelectHits(float fraction=1.0F)
pma::TrkCandidate matchCluster(detinfo::DetectorPropertiesData const &detProp, int first_clu_idx, const std::vector< art::Ptr< recob::Hit >> &first_hits, size_t minSizeCompl, unsigned int tpc, unsigned int cryo, geo::View_t first_view)
std::map< int, pma::Vector3D > fPfpVtx
void guideEndpoints(detinfo::DetectorPropertiesData const &detProp, pma::TrkCandidateColl &tracks)
bool areCoLinear(pma::Track3D *trk1, pma::Track3D *trk2, double &dist, double &cos3d, bool &reverseOrder, double distThr, double distThrMin, double distProjThr, double cosThr) const
double GetMse(unsigned int view=geo::kUnknown) const
MSE of hits weighted with hit amplidudes and wire plane coefficients.
BEGIN_PROLOG true icarus_rawdigitfilter FilterTools FilterPlane1 Plane
ClusterModuleLabel join with tracks
static constexpr Mask_t makeMask(Flags...flags)
Returns a bit mask with only the specified bit set.
void SetKey(int key)
Set key of an external object associated to this track candidate.
recob::Track convertFrom(const pma::Track3D &src, unsigned int tidx, int pdg=0)
process_name opflash particleana ie x
geo::GeometryCore const * fGeom
size_t matchTrack(detinfo::DetectorPropertiesData const &detProp, const pma::TrkCandidateColl &tracks, const std::vector< art::Ptr< recob::Hit >> &hits) const
double Dist2(const TVector2 &v1, const TVector2 &v2)
void buildTracks(detinfo::DetectorPropertiesData const &detProp)
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
ROOT::Math::SMatrix< Double32_t, 5, 5, ROOT::Math::MatRepSym< Double32_t, 5 > > SMatrixSym55
void ApplyDriftShiftInTree(const detinfo::DetectorClocksData &clockData, detinfo::DetectorPropertiesData const &detProp, double dx, bool skipFirst=false)
double validate(detinfo::DetectorPropertiesData const &detProp, pma::Track3D &trk, unsigned int testView)
pma::Hit3D const * front() const
bool reassignHits_1(detinfo::DetectorPropertiesData const &detProp, const std::vector< art::Ptr< recob::Hit >> &hits, pma::TrkCandidateColl &tracks, size_t trk_idx, double dist2)
void erase_at(size_t pos)
std::set< geo::View_t > const & Views() const
Returns a list of possible views in the detector.
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.
bool reassignSingleViewEnds_1(detinfo::DetectorPropertiesData const &detProp, pma::TrkCandidateColl &tracks)
std::map< size_t, pma::TrkCandidateColl > tpc_track_map
fhicl::Atom< std::string > Validation
std::vector< pma::Node3D * > const & Nodes() const noexcept
TVector3 const & Point3D() const
std::size_t size(FixedBins< T, C > const &) noexcept
PMAlgTracker(const std::vector< art::Ptr< recob::Hit >> &allhitlist, const std::vector< recob::Wire > &wires, const pma::ProjectionMatchingAlg::Config &pmalgConfig, const pma::PMAlgTracker::Config &pmalgTrackerConfig, const pma::PMAlgVertexing::Config &pmvtxConfig, const pma::PMAlgStitching::Config &pmstitchConfig, const pma::PMAlgCosmicTagger::Config &pmtaggerConfig, const std::vector< TH1F * > &hpassing, const std::vector< TH1F * > &hrejected)
void SetValidation(double v)
void SetTrack(pma::Track3D *trk)
std::map< int, std::vector< art::Ptr< recob::Cluster > > > fPfpClusters
double Validation() const
int maxCluster(detinfo::DetectorPropertiesData const &detProp, int first_idx_tag, const pma::TrkCandidateColl &candidates, float xmin, float xmax, size_t min_clu_size, geo::View_t view, unsigned int tpc, unsigned int cryo) const
recob::tracking::Vector_t Vector3D
pma::Vector3D GetDirection3D(size_t index) const
Get trajectory direction at given hit index.
recob::tracking::Point_t Point_t
bool mergeCoLinear(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, pma::TrkCandidateColl &tracks) const
process_name pandoraGausCryo1 vertexChargeCryo1 vertexStubCryo1 xmin
std::vector< double > fAdcValidationThr
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
int build(detinfo::DetectorPropertiesData const &detProp)
double GetDistToWall() const
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< Coord_t >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space. See recob::tracking::Coord_t for more details on the ...
fhicl::Sequence< double > AdcValidationThr
double collectSingleViewEnd(pma::Track3D &trk, std::vector< art::Ptr< recob::Hit >> &hits) const
unsigned int MaxPlanes() const
Returns the largest number of planes among all TPCs in this detector.
pma::Node3D * FirstElement() const
std::map< int, int > fPfpPdgCodes
std::vector< pma::Segment3D * > const & Segments() const noexcept
pma::Node3D * LastElement() const
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
TVector2 GetProjectionToSegment(const TVector2 &p, const TVector2 &p0, const TVector2 &p1)
A trajectory in space reconstructed from hits.
PMAlgTrackingBase(const std::vector< art::Ptr< recob::Hit >> &allhitlist, const pma::ProjectionMatchingAlg::Config &pmalgConfig, const pma::PMAlgVertexing::Config &pmvtxConfig)
void RemoveHits(const std::vector< art::Ptr< recob::Hit >> &hits)
Remove hits; removes also hit->node/seg assignments.
void fromMaxCluster_tpc(detinfo::DetectorPropertiesData const &detProp, pma::TrkCandidateColl &result, size_t minBuildSize, unsigned int tpc, unsigned int cryo)
unsigned int FrontTPC() const
unsigned int FrontCryo() const
unsigned int DisableSingleViewEnds()
PMAlgFitter(const std::vector< art::Ptr< recob::Hit >> &allhitlist, const std::vector< recob::Cluster > &clusters, const std::vector< recob::PFParticle > &pfparticles, const art::FindManyP< recob::Hit > &hitsFromClusters, const art::FindManyP< recob::Cluster > &clusFromPfps, const art::FindManyP< recob::Vertex > &vtxFromPfps, const pma::ProjectionMatchingAlg::Config &pmalgConfig, const pma::PMAlgFitter::Config &pmalgFitterConfig, const pma::PMAlgVertexing::Config &pmvtxConfig)
std::vector< std::vector< art::Ptr< recob::Hit > > > fCluHits
ClusterModuleLabel join with reoptimize track vertex structure MergeWithinTPC
double ConvertTicksToX(double ticks, int p, int t, int c) const
fhicl::Table< img::DataProviderAlg::Config > AdcImageAlg
bool HasTwoViews(size_t nmin=1) const
recob::tracking::SMatrixSym55 SMatrixSym55
void CleanupTails()
Cut out tails with no hits assigned.
double Length(size_t step=1) const
void freezeBranchingNodes(pma::TrkCandidateColl &tracks) const
Contains all timing reference information for the detector.
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
void init(const art::FindManyP< recob::Hit > &hitsFromClusters)
short int DetectDriftDirection() const
Returns the expected drift direction based on geometry.
then echo File list $list not found else cat $list while read file do echo $file sed s
double collectSingleViewFront(pma::Track3D &trk, std::vector< art::Ptr< recob::Hit >> &hits) const
const std::vector< size_t > & Clusters() const
pma::Hit3D const * back() const
void listUsedClusters(detinfo::DetectorPropertiesData const &detProp) const
int build(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp)
std::vector< geo::View_t > fAvailableViews
void releaseAllNodes(pma::TrkCandidateColl &tracks) const
TrackCollectionProxyElement< TrackCollProxy > Track
Proxy to an element of a proxy collection of recob::Track objects.
bool extendTrack(detinfo::DetectorPropertiesData const &detProp, pma::TrkCandidate &candidate, const std::vector< art::Ptr< recob::Hit >> &hits, unsigned int testView, bool add_nodes)
bool Flip(const detinfo::DetectorPropertiesData &detProp, std::vector< pma::Track3D * > &allTracks)
Interface for experiment-specific service for channel quality info.
EValidationMode fValidation
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< Coord_t >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space. See recob::tracking::Coord_t for more detai...
pma::Track3D * Track() const
bool empty(FixedBins< T, C > const &) noexcept
recob::tracking::Vector_t Vector_t
ClusterModuleLabel RunVertexing
void push_back(const TrkCandidate &trk)
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track:
std::vector< TrkCandidate > const & tracks() const
pma::cryo_tpc_view_hitmap fHitMap
ClusterModuleLabel join with reoptimize track vertex structure FlipToBeam
std::vector< img::DataProviderAlg > fAdcImages
void buildShowers(detinfo::DetectorPropertiesData const &detProp)