LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
PMAlgTracking.cxx
Go to the documentation of this file.
1 // Class: PMAlgTracking
3 // Author: D.Stefan (Dorota.Stefan@ncbj.gov.pl),
4 // R.Sulej (Robert.Sulej@cern.ch),
5 // L.Whitehead (leigh.howard.whitehead@cern.ch), June 2016
7 
10 
12 
14 
15 #include "TMath.h"
16 
20 
21 recob::Track pma::convertFrom(const pma::Track3D& src, unsigned int tidx, int pdg)
22 {
23  std::vector<Point_t> positions; positions.reserve(src.size());
24  std::vector<Vector_t> momenta; momenta.reserve(src.size());
25  std::vector<recob::TrajectoryPointFlags> outFlags; outFlags.reserve(src.size());
26 
27  for (size_t i = 0, h = 0; i < src.size(); i++)
28  if (src[i]->IsEnabled())
29  {
30  auto const & point3d = src[i]->Point3D();
31  positions.emplace_back(point3d.X(), point3d.Y(), point3d.Z());
32  momenta.push_back(src.GetDirection3D(i));
33  outFlags.emplace_back(h++, recob::TrajectoryPointFlags::makeMask());
34  }
35 
36  int ndof = 0;
37  float totChi2 = 0;
38 
39  SMatrixSym55 covStart, covEnd;
40  return recob::Track(
41  recob::TrackTrajectory(std::move(positions), std::move(momenta), std::move(outFlags), false),
42  pdg, totChi2, ndof, covStart, covEnd, tidx);
43 }
44 // ------------------------------------------------------
45 
47  const pma::ProjectionMatchingAlg::Config& pmalgConfig,
48  const pma::PMAlgVertexing::Config& pmvtxConfig) :
49  fProjectionMatchingAlg(pmalgConfig),
50  fPMAlgVertexing(pmvtxConfig)
51 {
52  unsigned int cryo, tpc, view;
53  for (auto const& h : allhitlist)
54  {
55  cryo = h->WireID().Cryostat;
56  tpc = h->WireID().TPC;
57  view = h->WireID().Plane;
58 
59  fHitMap[cryo][tpc][view].push_back(h);
60  }
61 }
62 // ------------------------------------------------------
63 
65 {
66  for (auto t : fResult.tracks()) t.DeleteTrack();
67 }
68 // ------------------------------------------------------
69 
71 {
72  for (auto const & t : tracks.tracks())
73  {
74  auto & trk = *(t.Track());
75 
76  unsigned int tpc = trk.FrontTPC(), cryo = trk.FrontCryo();
77  if ((tpc == trk.BackTPC()) && (cryo == trk.BackCryo()))
78  {
80  }
81  else
82  {
84  fHitMap[trk.FrontCryo()][trk.FrontTPC()]);
86  fHitMap[trk.BackCryo()][trk.BackTPC()]);
87  }
88  }
89 }
90 // ------------------------------------------------------
91 // ------------------------------------------------------
92 // ------------------------------------------------------
93 
95  const std::vector< recob::Cluster > & clusters,
96  const std::vector< recob::PFParticle > & pfparticles,
97  const art::FindManyP< recob::Hit > & hitsFromClusters,
98  const art::FindManyP< recob::Cluster > & clusFromPfps,
99  const art::FindManyP< recob::Vertex > & vtxFromPfps,
100  const pma::ProjectionMatchingAlg::Config& pmalgConfig,
101  const pma::PMAlgFitter::Config& pmalgFitterConfig,
102  const pma::PMAlgVertexing::Config& pmvtxConfig) :
103  PMAlgTrackingBase(allhitlist, pmalgConfig, pmvtxConfig),
104  fTrackingOnlyPdg(pmalgFitterConfig.TrackingOnlyPdg()),
105  fTrackingSkipPdg(pmalgFitterConfig.TrackingSkipPdg()),
106  fRunVertexing(pmalgFitterConfig.RunVertexing())
107 {
108  mf::LogVerbatim("PMAlgFitter") << "Found " << allhitlist.size() << "hits in the event.";
109  mf::LogVerbatim("PMAlgFitter") << "Sort hits by clusters assigned to PFParticles...";
110 
111  fCluHits.resize(clusters.size());
112  for (size_t i = 0; i < pfparticles.size(); ++i)
113  {
114  fPfpPdgCodes[i] = pfparticles[i].PdgCode();
115 
116  auto cv = clusFromPfps.at(i);
117  for (const auto & c : cv)
118  {
119  fPfpClusters[i].push_back(c);
120  if (fCluHits[c.key()].empty())
121  {
122  auto hv = hitsFromClusters.at(c.key());
123  fCluHits[c.key()].reserve(hv.size());
124  for (auto const & h : hv) fCluHits[c.key()].push_back(h);
125  }
126  }
127 
128  if (vtxFromPfps.isValid() && vtxFromPfps.at(i).size())
129  {
130  double xyz[3];
131  vtxFromPfps.at(i).front()->XYZ(xyz);
132  fPfpVtx[i] = pma::Vector3D(xyz[0], xyz[1], xyz[2]);
133  }
134  }
135 
136  mf::LogVerbatim("PMAlgFitter") << "...done, "
137  << fCluHits.size() << " clusters from "
138  << fPfpClusters.size() << " pfparticles for 3D tracking.";
139 }
140 // ------------------------------------------------------
141 
142 // ------------------------------------------------------
143 // ------------------------------------------------------
145 {
146  if (!fPfpClusters.empty() && !fCluHits.empty())
147  {
148  // build pm tracks
149  buildTracks();
150 
151  // add 3D ref.points for clean endpoints of wire-plae parallel tracks
153 
155 
156  // build segment of shower
157  buildShowers();
158  }
159  else
160  {
161  mf::LogWarning("PMAlgFitter") << "no clusters, no pfparticles";
162  return -1;
163  }
164 
165  return fResult.size();
166 }
167 // ------------------------------------------------------
168 // ------------------------------------------------------
169 
171 {
172  bool skipPdg = true;
173  if (!fTrackingSkipPdg.empty() && (fTrackingSkipPdg.front() == 0)) skipPdg = false;
174 
175  bool selectPdg = true;
176  if (!fTrackingOnlyPdg.empty() && (fTrackingOnlyPdg.front() == 0)) selectPdg = false;
177 
178  for (const auto & pfpCluEntry : fPfpClusters)
179  {
180  int pfPartIdx = pfpCluEntry.first;
181  int pdg = fPfpPdgCodes[pfPartIdx];
182 
183  //if (pdg == 11) continue;
184  if (skipPdg && has(fTrackingSkipPdg, pdg)) continue;
185  if (selectPdg && !has(fTrackingOnlyPdg, pdg)) continue;
186 
187  mf::LogVerbatim("PMAlgFitter") << "Process clusters from PFP:" << pfPartIdx << ", pdg:" << pdg;
188 
189  std::vector< art::Ptr<recob::Hit> > allHits;
190 
191  pma::TrkCandidate candidate;
192  std::unordered_map<geo::View_t, size_t> clu_count;
193  for (const auto & c : pfpCluEntry.second)
194  {
195  if (c->NHits() == 0) { continue; }
196 
197  candidate.Clusters().push_back(c.key());
198  clu_count[c->View()]++;
199 
200  allHits.reserve(allHits.size() + fCluHits.at(c.key()).size());
201  for (const auto & h : fCluHits.at(c.key()))
202  {
203  allHits.push_back(h);
204  }
205  }
206  if (clu_count.size() > 1) // try building only if there are clusters from multiple views
207  {
208  candidate.SetKey(pfpCluEntry.first);
209 
211 
212  if (candidate.IsValid() &&
213  candidate.Track()->HasTwoViews() &&
214  (candidate.Track()->Nodes().size() > 1))
215  {
216  if (!std::isnan(candidate.Track()->Length())) { fResult.push_back(candidate); }
217  else
218  {
219  mf::LogError("PMAlgFitter") << "Trajectory fit lenght is nan.";
220  candidate.DeleteTrack();
221  }
222  }
223  else { candidate.DeleteTrack(); }
224  }
225  }
226 }
227 // ------------------------------------------------------
228 
230 {
231  bool skipPdg = true;
232  if (!fTrackingSkipPdg.empty() && (fTrackingSkipPdg.front() == 0))
233  skipPdg = false;
234 
235  bool selectPdg = true;
236  if (!fTrackingOnlyPdg.empty() && (fTrackingOnlyPdg.front() == 0))
237  selectPdg = false;
238 
239  for (const auto & pfpCluEntry : fPfpClusters)
240  {
241  int pfPartIdx = pfpCluEntry.first;
242  int pdg = fPfpPdgCodes[pfPartIdx];
243 
244  if (pdg != 11) continue;
245  if (skipPdg && has(fTrackingSkipPdg, pdg)) continue;
246  if (selectPdg && !has(fTrackingOnlyPdg, pdg)) continue;
247 
248  mf::LogVerbatim("PMAlgFitter") << "Process clusters from PFP:" << pfPartIdx << ", pdg:" << pdg;
249 
250  std::vector< art::Ptr<recob::Hit> > allHits;
251 
252  pma::TrkCandidate candidate;
253  std::unordered_map<geo::View_t, size_t> clu_count;
254  for (const auto & c : pfpCluEntry.second)
255  {
256  if (c->NHits() == 0) { continue; }
257 
258  candidate.Clusters().push_back(c.key());
259  clu_count[c->View()]++;
260 
261  allHits.reserve(allHits.size() + fCluHits.at(c.key()).size());
262  for (const auto & h : fCluHits.at(c.key()))
263  allHits.push_back(h);
264  }
265  if (clu_count.size() > 1) // try building only if there are clusters from multiple views
266  {
267  candidate.SetKey(pfpCluEntry.first);
268 
269  mf::LogVerbatim("PMAlgFitter") << "building..." << ", pdg:" << pdg;
270 
271  auto search = fPfpVtx.find(pfPartIdx);
272  if (search != fPfpVtx.end())
273  {
274  candidate.SetTrack(fProjectionMatchingAlg.buildShowerSeg(allHits, search->second));
275 
276  if (candidate.IsValid()
277  && candidate.Track()->HasTwoViews()
278  && (candidate.Track()->Nodes().size() > 1)
279  && !std::isnan(candidate.Track()->Length()))
280  {
281  fResult.push_back(candidate);
282  }
283  else { candidate.DeleteTrack(); }
284  }
285  }
286  }
287 }
288 // ------------------------------------------------------
289 // ------------------------------------------------------
290 // ------------------------------------------------------
291 
292 pma::PMAlgTracker::PMAlgTracker(const std::vector< art::Ptr<recob::Hit> > & allhitlist, const std::vector<recob::Wire> & wires,
293  const pma::ProjectionMatchingAlg::Config& pmalgConfig,
294  const pma::PMAlgTracker::Config& pmalgTrackerConfig,
295  const pma::PMAlgVertexing::Config& pmvtxConfig,
296  const pma::PMAlgStitching::Config& pmstitchConfig,
297  const pma::PMAlgCosmicTagger::Config& pmtaggerConfig,
298 
299  const std::vector< TH1F* > & hpassing, const std::vector< TH1F* > & hrejected) :
300 
301  PMAlgTrackingBase(allhitlist, pmalgConfig, pmvtxConfig),
302 
303  fWires(wires),
304 
305  fMinSeedSize1stPass(pmalgTrackerConfig.MinSeedSize1stPass()),
306  fMinSeedSize2ndPass(pmalgTrackerConfig.MinSeedSize2ndPass()),
307  fTrackLikeThreshold(pmalgTrackerConfig.TrackLikeThreshold()),
308 
309  fMinTwoViewFraction(pmalgConfig.MinTwoViewFraction()),
310 
311  fFlipToBeam(pmalgTrackerConfig.FlipToBeam()),
312  fFlipDownward(pmalgTrackerConfig.FlipDownward()),
313  fFlipToX(pmalgTrackerConfig.FlipToX()),
314  fAutoFlip_dQdx(pmalgTrackerConfig.AutoFlip_dQdx()),
315 
316  fMergeWithinTPC(pmalgTrackerConfig.MergeWithinTPC()),
317  fMergeTransverseShift(pmalgTrackerConfig.MergeTransverseShift()),
318  fMergeAngle(pmalgTrackerConfig.MergeAngle()),
319 
320  fCosmicTagger(pmtaggerConfig),
321  fTagCosmicTracks(fCosmicTagger.tagAny()),
322 
323  fStitchBetweenTPCs(pmalgTrackerConfig.StitchBetweenTPCs()),
324  fStitchDistToWall(pmalgTrackerConfig.StitchDistToWall()),
325  fStitchTransverseShift(pmalgTrackerConfig.StitchTransverseShift()),
326  fStitchAngle(pmalgTrackerConfig.StitchAngle()),
327 
328  fMatchT0inAPACrossing(pmalgTrackerConfig.MatchT0inAPACrossing()),
329  fMatchT0inCPACrossing(pmalgTrackerConfig.MatchT0inCPACrossing()),
330  fStitcher(pmstitchConfig),
331 
332  fRunVertexing(pmalgTrackerConfig.RunVertexing()),
333 
334  fAdcInPassingPoints(hpassing), fAdcInRejectedPoints(hrejected),
335 
336  fGeom(&*(art::ServiceHandle<geo::Geometry>())),
337  fDetProp(lar::providerFrom<detinfo::DetectorPropertiesService>())
338 {
339  for (const auto v : fGeom->Views()) { fAvailableViews.push_back(v); }
340  std::reverse(fAvailableViews.begin(), fAvailableViews.end());
341 
342  mf::LogVerbatim("PMAlgTracker") << "Using views in the following order:";
343  for (const auto v : fAvailableViews) { mf::LogInfo("PMAlgTracker") << " " << v; }
344 
345  // ************************* track validation settings: **************************
346  mf::LogVerbatim("PMAlgTracker") << "Validation mode in config: " << pmalgTrackerConfig.Validation();
347 
348  size_t nplanes = fGeom->MaxPlanes();
349  for (size_t p = 0; p < nplanes; ++p) { fAdcImages.emplace_back(pmalgTrackerConfig.AdcImageAlg()); }
350 
351  if (pmalgTrackerConfig.Validation() == "hits") { fValidation = pma::PMAlgTracker::kHits; }
352  else if (pmalgTrackerConfig.Validation() == "adc") { fValidation = pma::PMAlgTracker::kAdc; }
353  else if (pmalgTrackerConfig.Validation() == "calib") { fValidation = pma::PMAlgTracker::kCalib; }
354  else { throw cet::exception("pma::PMAlgTracker") << "validation name not supported" << std::endl; }
355 
356  if ((nplanes < 3) && (fValidation != pma::PMAlgTracker::kHits))
357  {
358  mf::LogWarning("PMAlgTracker") << "Not enough planes to perform validation, switch mode to hits.";
360  }
361 
362  fAdcValidationThr = pmalgTrackerConfig.AdcValidationThr();
364  {
365  mf::LogVerbatim("PMAlgTracker") << "Validation ADC thresholds per plane:";
366  for (auto thr : fAdcValidationThr) { mf::LogVerbatim("PMAlgTracker") << " " << thr; }
367  }
368 }
369 // ------------------------------------------------------
370 
372 {
373  mf::LogVerbatim("PMAlgTracker") << "Sort hits by clusters...";
374  fCluHits.clear(); fCluHits.reserve(hitsFromClusters.size());
375  fCluWeights.clear(); fCluWeights.reserve(fCluHits.size());
376  for (size_t i = 0; i < hitsFromClusters.size(); ++i)
377  {
378  auto v = hitsFromClusters.at(i);
379  fCluHits.push_back(std::vector< art::Ptr<recob::Hit> >());
380  for (auto const & h : v) fCluHits.back().push_back(h);
381  fCluWeights.push_back(1);
382  }
383  mf::LogVerbatim("PMAlgTracker") << "...done, " << fCluHits.size() << " clusters for 3D tracking.";
384 }
385 // ------------------------------------------------------
386 
388  const std::vector< float > & trackLike)
389 {
390  mf::LogVerbatim("PMAlgTracker") << "Filter track-like clusters using likelihood values...";
391  fCluHits.clear(); fCluHits.reserve(hitsFromClusters.size());
392  fCluWeights.clear(); fCluWeights.reserve(fCluHits.size());
393  for (size_t i = 0; i < hitsFromClusters.size(); ++i)
394  {
395  auto v = hitsFromClusters.at(i);
396  fCluHits.push_back(std::vector< art::Ptr<recob::Hit> >());
397  for (auto const & h : v) fCluHits.back().push_back(h);
398  fCluWeights.push_back(trackLike[i]);
399  }
400 }
401 // ------------------------------------------------------
402 
404  const art::FindManyP< recob::Hit > & hitsFromEmParts)
405 {
406  mf::LogVerbatim("PMAlgTracker") << "Filter track-like clusters...";
407  fCluHits.clear(); fCluHits.reserve(hitsFromClusters.size());
408  fCluWeights.clear(); fCluWeights.reserve(fCluHits.size());
409  size_t n = 0; // count not-empty clusters
410  for (size_t i = 0; i < hitsFromClusters.size(); ++i)
411  {
412  auto v = hitsFromClusters.at(i);
413  fCluHits.push_back(std::vector< art::Ptr<recob::Hit> >());
414  for (auto const & h : v)
415  {
416  bool trkLike = true;
417  for (size_t j = 0; j < hitsFromEmParts.size(); ++j)
418  {
419  auto u = hitsFromEmParts.at(j);
420  for (auto const & g : u) // is hit clustered in one of em-like?
421  {
422  if (g.key() == h.key()) { trkLike = false; break; }
423  }
424  if (!trkLike) break;
425  }
426  if (trkLike) fCluHits.back().push_back(h);
427  }
428  if (!fCluHits.back().empty()) { fCluWeights.push_back(1); ++n; }
429  else { fCluWeights.push_back(0); }
430  }
431  mf::LogVerbatim("PMAlgTracker") << "...done, " << n << " clusters for 3D tracking.";
432 }
433 // ------------------------------------------------------
434 
435 double pma::PMAlgTracker::validate(pma::Track3D& trk, unsigned int testView)
436 {
437  if ((trk.FirstElement()->GetDistToWall() < -3.0) ||
438  (trk.LastElement()->GetDistToWall() < -3.0))
439  {
440  mf::LogVerbatim("PMAlgTracker") << "first or last node too far out of its initial TPC";
441  return 0.0;
442  }
443 
444  if (testView != geo::kUnknown) { mf::LogVerbatim("PMAlgTracker") << "validation in plane: " << testView; }
445  else { return 1.0; }
446 
447  double v = 0;
448  switch (fValidation)
449  {
452  break;
453 
455  v = fProjectionMatchingAlg.validate(trk, fHitMap[trk.FrontCryo()][trk.FrontTPC()][testView]);
456  break;
457 
460  trk, fAdcImages[testView], fHitMap[trk.FrontCryo()][trk.FrontTPC()][testView],
461  fAdcInPassingPoints[testView], fAdcInRejectedPoints[testView]);
462  break;
463 
464  default: throw cet::exception("pma::PMAlgTracker") << "validation mode not supported" << std::endl; break;
465  }
466 
467  return v;
468 }
469 // ------------------------------------------------------
470 
472  pma::TrkCandidateColl & tracks, size_t trk_idx, double dist2)
473 {
474  pma::Track3D* trk1 = tracks[trk_idx].Track();
475 
476  bool result = false;
477  if ((hits.size() > 1) || (dist2 > 1.0)) // min. 2 hits or single hit separated from the rest
478  {
479  pma::Track3D* best_trk = 0;
480 
481  size_t best_u = 0, n_max = 0;
482  for (size_t u = 0; u < tracks.size(); u++)
483  if (trk_idx != u)
484  {
485  pma::Track3D* trk2 = tracks[u].Track();
486  size_t n = fProjectionMatchingAlg.testHits(*trk2, hits);
487  if (n > n_max) { n_max = n; best_u = u; best_trk = trk2; }
488  }
489 
490  if (best_trk && (n_max >= hits.size() / 3)) // /2
491  {
492  mf::LogVerbatim("PMAlgTrackMaker") << " Reassign(v1) " << n_max << " hits." << std::endl;
493 
494  trk1->RemoveHits(hits);
495  trk1->CleanupTails();
496  trk1->ShiftEndsToHits();
497 
498  pma::Track3D* ext = fProjectionMatchingAlg.extendTrack(*best_trk, hits, false);
499  ext->SortHits(); ext->ShiftEndsToHits();
501  {
502  tracks[best_u].SetTrack(ext); // and this deletes best_trk stored at best_u
503  result = true;
504  }
505  else delete ext;
506  }
507  else if (hits.size() >= fMinSeedSize2ndPass)
508  {
509  size_t minSizeCompl = hits.size() / 8; // much smaller minimum required in complementary views
510  if (minSizeCompl < 3) minSizeCompl = 3; // but at least three hits!
511 
512  geo::View_t first_view = (geo::View_t)hits.front()->WireID().Plane;
513  unsigned int tpc = hits.front()->WireID().TPC;
514  unsigned int cryo = hits.front()->WireID().Cryostat;
515 
516  pma::TrkCandidate candidate = matchCluster(-1, hits, minSizeCompl, tpc, cryo, first_view);
517 
518  if (candidate.IsGood())
519  {
520  mf::LogVerbatim("PMAlgTrackMaker") << " Add new track, cut hits from source track." << std::endl;
521  tracks.push_back(candidate);
522 
523  trk1->RemoveHits(hits);
524  trk1->CleanupTails();
525  trk1->ShiftEndsToHits();
526  }
527  }
528  }
529  else if ((hits.size() == 1) || (dist2 > 2.25)) // dist > 1.5cm
530  {
531  mf::LogVerbatim("PMAlgTrackMaker") << " Cut single-view isolated hit." << std::endl;
532  trk1->RemoveHits(hits);
533  trk1->CleanupTails();
534  trk1->ShiftEndsToHits();
535  }
536  return result;
537 }
538 
541 {
542  size_t idx = 0;
543  while ((idx < trk.size() - 1) && !(trk[idx]->IsEnabled()))
544  {
545  hits.push_back(trk[idx++]->Hit2DPtr());
546  }
547 
548  double d2 = 0.0;
549  if (idx > 0)
550  {
551  if ((idx < trk.size() - 1) &&
552  (trk[idx]->View2D() == trk[idx - 1]->View2D()))
553  {
554  double dprev = pma::Dist2(trk[idx]->Point3D(), trk[idx - 1]->Point3D());
555  double dnext = pma::Dist2(trk[idx]->Point3D(), trk[idx + 1]->Point3D());
556  if (dprev < dnext)
557  {
558  hits.push_back(trk[idx++]->Hit2DPtr());
559  }
560  }
561  d2 = pma::Dist2(trk[idx]->Point3D(), trk[idx - 1]->Point3D());
562  }
563  return d2;
564 }
565 
568 {
569  size_t idx = trk.size() - 1;
570  while ((idx > 0) && !(trk[idx]->IsEnabled()))
571  {
572  hits.push_back(trk[idx--]->Hit2DPtr());
573  }
574 
575  double d2 = 0.0;
576  if (idx < trk.size() - 1)
577  {
578  if ((idx > 0) &&
579  (trk[idx]->View2D() == trk[idx + 1]->View2D()))
580  {
581  double dprev = pma::Dist2(trk[idx]->Point3D(), trk[idx + 1]->Point3D());
582  double dnext = pma::Dist2(trk[idx]->Point3D(), trk[idx - 1]->Point3D());
583  if (dprev < dnext)
584  {
585  hits.push_back(trk[idx--]->Hit2DPtr());
586  }
587  }
588  d2 = pma::Dist2(trk[idx]->Point3D(), trk[idx + 1]->Point3D());
589  }
590  return d2;
591 }
592 
594 {
595  bool result = false;
596  for (size_t t = 0; t < tracks.size(); t++)
597  {
598  pma::Track3D & trk = *(tracks[t].Track());
599  if (trk.size() < 6) continue;
600 
601  trk.DisableSingleViewEnds();
602 
603  std::vector< art::Ptr<recob::Hit> > hits;
604 
605  double d2 = collectSingleViewEnd(trk, hits);
606  result |= reassignHits_1(hits, tracks, t, d2);
607 
608  hits.clear();
609 
610  d2 = collectSingleViewFront(trk, hits);
611  result |= reassignHits_1(hits, tracks, t, d2);
612 
613  trk.SelectHits();
614  }
615  return result;
616 }
617 // ------------------------------------------------------
618 
620  pma::TrkCandidateColl & tracks, size_t trk_idx, double dist2)
621 {
622  pma::Track3D* trk1 = tracks[trk_idx].Track();
623 
624  bool result = false;
625  if ((hits.size() > 1) || (dist2 > 1.0)) // min. 2 hits or single hit separated from the rest
626  {
627  pma::Track3D* best_trk = 0;
628 
629  size_t n_max = 0;
630  for (size_t u = 0; u < tracks.size(); u++)
631  if (trk_idx != u)
632  {
633  pma::Track3D* trk2 = tracks[u].Track();
634  size_t n = fProjectionMatchingAlg.testHits(*trk2, hits, 0.5);
635  if (n > n_max) { n_max = n; best_trk = trk2; }
636  }
637 
638  if (best_trk && (n_max >= (size_t)(0.8 * hits.size()))) // most hits!
639  {
640  mf::LogVerbatim("PMAlgTrackMaker") << " Reassign(v2) " << n_max << " hits." << std::endl;
641 
642  trk1->RemoveHits(hits);
643  trk1->CleanupTails();
644  trk1->ShiftEndsToHits();
645 
646  best_trk->AddHits(hits);
647 
648  result = true;
649  }
650  }
651  else if ((hits.size() == 1) || (dist2 > 2.25)) // dist > 1.5cm
652  {
653  mf::LogVerbatim("PMAlgTrackMaker") << " Cut single-view isolated hit." << std::endl;
654  trk1->RemoveHits(hits);
655  trk1->CleanupTails();
656  trk1->ShiftEndsToHits();
657 
658  result = true;
659  }
660 
661  if (result)
662  {
663  // reopt trees
664  }
665 
666  return result;
667 }
668 
670 {
671  bool result = false;
672  for (size_t t = 0; t < tracks.size(); t++)
673  {
674  pma::Track3D & trk = *(tracks[t].Track());
675  if (trk.size() < 6) continue;
676 
677  trk.DisableSingleViewEnds();
678 
679  std::vector< art::Ptr<recob::Hit> > hits;
680 
681  double d2 = collectSingleViewEnd(trk, hits);
682  result |= reassignHits_2(hits, tracks, t, d2);
683 
684  hits.clear();
685 
686  d2 = collectSingleViewFront(trk, hits);
687  result |= reassignHits_2(hits, tracks, t, d2);
688 
689  trk.SelectHits();
690  }
691  return result;
692 }
693 // ------------------------------------------------------
694 
696  double& dist, double& cos3d, bool& reverseOrder,
697  double distThr, double distThrMin,
698  double distProjThr,
699  double cosThr)
700 {
701  double lmax;
702  double l1 = trk1->Length();
703  double l2 = trk2->Length();
704 
705  if (l1 > l2) lmax = l1;
706  else lmax = l2;
707 
708  double d = lmax * distThr;
709  if (d < distThrMin) d = distThrMin;
710 
711  unsigned int k = 0;
712  double distFF = pma::Dist2(trk1->front()->Point3D(), trk2->front()->Point3D());
713  dist = distFF;
714 
715  double distFB = pma::Dist2(trk1->front()->Point3D(), trk2->back()->Point3D());
716  if (distFB < dist) { k = 1; dist = distFB; }
717 
718  double distBF = pma::Dist2(trk1->back()->Point3D(), trk2->front()->Point3D());
719  if (distBF < dist) { k = 2; dist = distBF; }
720 
721  double distBB = pma::Dist2(trk1->back()->Point3D(), trk2->back()->Point3D());
722  if (distBB < dist) { k = 3; dist = distBB; }
723 
724  dist = sqrt(dist);
725  cos3d = 0.0;
726 
727  if (dist < d)
728  {
729  pma::Track3D* tmp = 0;
730  switch (k) // swap or flip to get trk1 end before trk2 start
731  {
732  case 0: trk1->Flip(); break;
733  case 1: tmp = trk1; trk1 = trk2; trk2 = tmp; break;
734  case 2: break;
735  case 3: trk2->Flip(); break;
736  default: mf::LogError("PMAlgTracker") << "Should never happen.";
737  }
738  if (k == 1) reverseOrder = true;
739  else reverseOrder = false;
740 
741  size_t nodeEndIdx = trk1->Nodes().size() - 1;
742 
743  TVector3 endpoint1 = trk1->back()->Point3D();
744  TVector3 trk2front0 = trk2->Nodes()[0]->Point3D();
745  TVector3 trk2front1 = trk2->Nodes()[1]->Point3D();
746  TVector3 proj1 = pma::GetProjectionToSegment(endpoint1, trk2front0, trk2front1);
747  double distProj1 = sqrt( pma::Dist2(endpoint1, proj1) );
748 
749  TVector3 endpoint2 = trk2->front()->Point3D();
750  TVector3 trk1back0 = trk1->Nodes()[nodeEndIdx]->Point3D();
751  TVector3 trk1back1 = trk1->Nodes()[nodeEndIdx - 1]->Point3D();
752  TVector3 proj2 = pma::GetProjectionToSegment(endpoint2, trk1back1, trk1back0);
753  double distProj2 = sqrt( pma::Dist2(endpoint2, proj2) );
754 
755  pma::Vector3D dir1 = trk1->Segments().back()->GetDirection3D();
756  pma::Vector3D dir2 = trk2->Segments().front()->GetDirection3D();
757 
758  cos3d = dir1.Dot(dir2);
759 
760  if ((cos3d > cosThr) && (distProj1 < distProjThr) && (distProj2 < distProjThr))
761  return true;
762  else // check if parallel to wires & colinear in 2D
763  {
764  const double maxCosXZ = 0.996195; // 5 deg
765 
766  pma::Vector3D dir1_xz(dir1.X(), 0., dir1.Z());
767  dir1_xz *= 1.0 / dir1_xz.R();
768 
769  pma::Vector3D dir2_xz(dir2.X(), 0., dir2.Z());
770  dir2_xz *= 1.0 / dir2_xz.R();
771 
772  if ((fabs(dir1_xz.Z()) > maxCosXZ) && (fabs(dir2_xz.Z()) > maxCosXZ))
773  {
774  endpoint1.SetY(0.);
775  trk2front0.SetY(0.);
776  trk2front1.SetY(0.);
777  proj1 = pma::GetProjectionToSegment(endpoint1, trk2front0, trk2front1);
778  distProj1 = sqrt( pma::Dist2(endpoint1, proj1) );
779 
780  endpoint2.SetY(0.);
781  trk1back0.SetY(0.);
782  trk1back1.SetY(0.);
783  proj2 = pma::GetProjectionToSegment(endpoint2, trk1back1, trk1back0);
784  distProj2 = sqrt( pma::Dist2(endpoint2, proj2) );
785 
786  double cosThrXZ = cos(0.5 * acos(cosThr));
787  double distProjThrXZ = 0.5 * distProjThr;
788  double cosXZ = dir1_xz.Dot(dir2_xz);
789  if ((cosXZ > cosThrXZ) && (distProj1 < distProjThrXZ) && (distProj2 < distProjThrXZ))
790  return true;
791  }
792  }
793  }
794  return false;
795 }
796 
798 {
799  double distThr = 0.25; // max gap as a fraction of the longer track length
800  double distThrMin = 0.5; // lower limit of max gap threshold [cm]
801 
802  double distProjThr = fMergeTransverseShift;
803  double cosThr = cos(TMath::Pi() * fMergeAngle / 180.0);
804 
805  bool foundMerge = false;
806 
807  std::sort(tracks.tracks().begin(), tracks.tracks().end(), pma::bTrack3DLonger());
808 
809  bool r;
810  double d, dmin, c, cmax, l, lbest;
811  size_t t = 0, u = 0;
812  while (t < tracks.size())
813  {
814  pma::Track3D* trk1 = tracks[t].Track();
815 
816  pma::Track3D* trk2 = 0;
817  pma::Track3D* best_trk2 = 0;
818  dmin = 1.0e12; cmax = 0; lbest = 0;
819  for (u = t + 1; u < tracks.size(); u++)
820  {
821  trk2 = tracks[u].Track();
822  if (areCoLinear(trk1, trk2, d, c, r, distThr, distThrMin, distProjThr, cosThr))
823  {
824  l = std::sqrt(pma::Dist2(trk2->front()->Point3D(), trk2->back()->Point3D()));
825  if (((c > cmax) && (d < dmin + 0.5 * lbest)) ||
826  ((d < dmin) && (l > 1.5 * lbest)))
827  {
828  cmax = c; dmin = d;
829  best_trk2 = trk2;
830  lbest = l;
831  }
832  }
833  trk2 = 0;
834  }
835  trk2 = best_trk2;
836 
837  if (trk2)
838  {
839  mf::LogVerbatim("PMAlgTracker") << "Merge track ("
840  << trk1->size() << ") with track (" << trk2->size() << ")";
841  if (r)
842  {
843  fProjectionMatchingAlg.mergeTracks(*trk2, *trk1, true);
844  tracks[t].SetTrack(trk2); // deletes old trk1
845  }
846  else
847  {
848  fProjectionMatchingAlg.mergeTracks(*trk1, *trk2, true);
849  tracks[u].DeleteTrack();
850  }
851  tracks.erase_at(u);
852  foundMerge = true;
853  }
854  else t++;
855  }
856 
857  return foundMerge;
858 }
859 // ------------------------------------------------------
860 
861 
863 {
864  for (auto const & trk : tracks.tracks())
865  for (auto node : trk.Track()->Nodes())
866  if (node->IsBranching()) node->SetFrozen(true);
867 }
869 {
870  for (auto const & trk : tracks.tracks())
871  for (auto node : trk.Track()->Nodes())
872  node->SetFrozen(false);
873 }
874 
876 {
877  double distThr = 0.25; // max gap as a fraction of the longer track length
878  double distThrMin = 2.5; // lower limit of max gap threshold [cm]
879 
880  double distProjThr = fStitchTransverseShift;
881  double cosThr = cos(TMath::Pi() * fStitchAngle / 180.0);
882 
883  double wallDistThr = fStitchDistToWall;
884  double dfront1, dback1, dfront2, dback2;
885 
886  //for (auto & tpc_entry : tracks) freezeBranchingNodes(tpc_entry.second);
887 
888  for (auto & tpc_entry1 : tracks)
889  {
890  unsigned int tpc1 = tpc_entry1.first;
891  pma::TrkCandidateColl & tracks1 = tpc_entry1.second;
892 
893  size_t t = 0;
894  while (t < tracks1.size())
895  {
896  bool r, reverse = false;
897  double l, lbest = 0, d, dmin = 1.0e12, c, cmax = 0.0;
898  pma::Track3D* best_trk2 = 0;
899  unsigned int best_tpc = 0;
900  size_t best_idx = 0;
901 
902  pma::Track3D* trk1 = tracks1[t].Track();
903  dfront1 = trk1->Nodes().front()->GetDistToWall();
904  dback1 = trk1->Nodes().back()->GetDistToWall();
905  if ((dfront1 < wallDistThr) || (dback1 < wallDistThr))
906  {
907  for (auto & tpc_entry2 : tracks)
908  {
909  unsigned int tpc2 = tpc_entry2.first;
910  if (tpc2 == tpc1) continue;
911 
912  pma::TrkCandidateColl & tracks2 = tpc_entry2.second;
913 
914  for (size_t u = 0; u < tracks2.size(); u++)
915  {
916  pma::Track3D* trk2 = tracks2[u].Track();
917  dfront2 = trk2->Nodes().front()->GetDistToWall();
918  dback2 = trk2->Nodes().back()->GetDistToWall();
919  if ((dfront2 < wallDistThr) || (dback2 < wallDistThr))
920  {
921  if (areCoLinear(trk1, trk2, d, c, r, distThr, distThrMin, distProjThr, cosThr))
922  {
923  l = std::sqrt(pma::Dist2(trk2->front()->Point3D(), trk2->back()->Point3D()));
924  if (((c > cmax) && (d < dmin + 0.5 * lbest)) || (0.75 * l < dmin))
925  {
926  cmax = c; dmin = d; lbest = l;
927  best_trk2 = trk2;
928  best_tpc = tpc2;
929  best_idx = u;
930  reverse = r;
931  }
932  }
933  }
934  }
935  }
936  }
937 
938  if (best_trk2)
939  {
940  mf::LogVerbatim("PMAlgTracker") << "Merge track ("
941  << tpc1 << ":" << tracks1.size() << ":" << trk1->size() << ") with track ("
942  << best_tpc << ":" << tracks[best_tpc].size() << ":" << best_trk2->size() << ")";
943  auto const* geom = lar::providerFrom<geo::Geometry>();
944  const geo::TPCGeo &tpc1 = geom->TPC(trk1->Nodes().front()->TPC(),trk1->Nodes().front()->Cryo());
945  const geo::TPCGeo &tpc2 = geom->TPC(best_trk2->Nodes().front()->TPC(),best_trk2->Nodes().front()->Cryo());
946  if (reverse)
947  {
948  fProjectionMatchingAlg.mergeTracks(*best_trk2, *trk1, true);
949  // This track will have a shift in x equal to zero. This will
950  // properly set the track T0
951  if(tpc1.DetectDriftDirection() * tpc2.DetectDriftDirection() < 0){
952  best_trk2->ApplyDriftShiftInTree(0.0);
953  }
954  tracks1[t].SetTrack(best_trk2);
955  }
956  else
957  {
958  fProjectionMatchingAlg.mergeTracks(*trk1, *best_trk2, true);
959  // This track will have a shift in x equal to zero. This will
960  // properly set the track T0
961  if(tpc1.DetectDriftDirection() * tpc2.DetectDriftDirection() < 0){
962  trk1->ApplyDriftShiftInTree(0.0);
963  }
964  tracks[best_tpc][best_idx].DeleteTrack();
965  }
966  tracks[best_tpc].erase_at(best_idx);
967  }
968  else t++;
969  }
970  }
971 
972  //for (auto & tpc_entry : tracks) releaseAllNodes(tpc_entry.second);
973 }
974 // ------------------------------------------------------
975 
977 {
978  size_t max_hits = 0;
979  for (auto const & t : tracks.tracks())
980  {
981  size_t n = fProjectionMatchingAlg.testHits(*(t.Track()), hits);
982  if (n > max_hits) { max_hits = n; }
983  }
984  return max_hits;
985 }
986 
987 // ------------------------------------------------------
988 // ------------------------------------------------------
990 {
991  fInitialClusters.clear();
992  fTriedClusters.clear();
993  fUsedClusters.clear();
994 
995  size_t nplanes = fGeom->MaxPlanes();
996 
997  pma::tpc_track_map tracks; // track parts in tpc's
998 
999  for (auto tpc_iter = fGeom->begin_TPC_id();
1000  tpc_iter != fGeom->end_TPC_id();
1001  tpc_iter++)
1002  {
1003  mf::LogVerbatim("PMAlgTracker")
1004  << "Reconstruct tracks within Cryo:" << tpc_iter->Cryostat
1005  << " / TPC:" << tpc_iter->TPC << ".";
1006 
1007  if (fValidation != pma::PMAlgTracker::kHits) // initialize ADC images for all planes in this TPC (in "adc" and "calib")
1008  {
1009  mf::LogVerbatim("PMAlgTracker") << "Prepare validation ADC images...";
1010  bool ok = true;
1011  for (size_t p = 0; p < nplanes; ++p) { ok &= fAdcImages[p].setWireDriftData(fWires, p, tpc_iter->TPC, tpc_iter->Cryostat); }
1012  if (ok) { mf::LogVerbatim("PMAlgTracker") << " ...done."; }
1013  else { mf::LogVerbatim("PMAlgTracker") << " ...failed."; continue; }
1014  }
1015 
1016  // find reasonably large parts
1017  fromMaxCluster_tpc(tracks[tpc_iter->TPC], fMinSeedSize1stPass, tpc_iter->TPC, tpc_iter->Cryostat);
1018  // loop again to find small things
1019  fromMaxCluster_tpc(tracks[tpc_iter->TPC], fMinSeedSize2ndPass, tpc_iter->TPC, tpc_iter->Cryostat);
1020 
1021  //tryClusterLeftovers();
1022 
1023  mf::LogVerbatim("PMAlgTracker") << "Found tracks: " << tracks[tpc_iter->TPC].size();
1024  if (tracks[tpc_iter->TPC].empty()) { continue; }
1025 
1026  // add 3D ref.points for clean endpoints of wire-plane parallel track
1027  guideEndpoints(tracks[tpc_iter->TPC]);
1028  // try correcting single-view sections spuriously merged on 2D clusters level
1029  reassignSingleViewEnds_1(tracks[tpc_iter->TPC]);
1030 
1031  if (fMergeWithinTPC)
1032  {
1033  mf::LogVerbatim("PMAlgTracker") << "Merge co-linear tracks within TPC " << tpc_iter->TPC << ".";
1034  while (mergeCoLinear(tracks[tpc_iter->TPC]))
1035  {
1036  mf::LogVerbatim("PMAlgTracker") << " found co-linear tracks";
1037  }
1038  }
1039  }
1040 
1041  if (fStitchBetweenTPCs)
1042  {
1043  mf::LogVerbatim("PMAlgTracker") << "Stitch co-linear tracks between TPCs.";
1044  mergeCoLinear(tracks);
1045  }
1046 
1047  for (auto & tpc_entry : tracks) // put tracks in the single collection
1048  for (auto & trk : tpc_entry.second.tracks())
1049  {
1050  if (trk.Track()->HasTwoViews() && (trk.Track()->Nodes().size() > 1)) { fResult.push_back(trk); }
1051  else { trk.DeleteTrack(); }
1052  }
1053 
1054  if (fTagCosmicTracks)
1055  {
1056  mf::LogVerbatim("PMAlgTracker") << "Tag cosmic tracks activity.";
1058  }
1059 
1060  if (fRunVertexing)
1061  {
1062  mf::LogVerbatim("PMAlgTracker") << "Vertex finding / track-vertex reoptimization.";
1064 
1065  //reassignSingleViewEnds(result); // final check for correct hit-track assignments
1066  }
1067 
1068  fResult.setTreeIds();
1069 
1071  {
1072  mf::LogVerbatim("PMAlgTracker") << "Find co-linear CPA-crossing tracks with any T0.";
1074  }
1075 
1077  {
1078  mf::LogVerbatim("PMAlgTracker") << "Find co-linear APA-crossing tracks with any T0.";
1080  }
1081 
1082  if (fTagCosmicTracks)
1083  {
1084  mf::LogVerbatim("PMAlgTracker") << "Second pass cosmic tagging for stitched tracks";
1086  }
1087 
1088  //double dQdxFlipThr = 0.0;
1089  //if (fFlipToBeam) dQdxFlipThr = 0.4;
1090  if (fFlipToBeam) fResult.flipTreesToCoordinate(2); // flip the tracks / trees to the beam direction (Z)
1091  else if (fFlipDownward) fResult.flipTreesToCoordinate(1); // flip the tracks / trees to point downward (-Y)
1092  else if (fFlipToX) fResult.flipTreesToCoordinate(0); // flip the tracks / trees to point in -X direction (downwards for dual phase)
1093 
1094  if (fAutoFlip_dQdx) fResult.flipTreesByDQdx(); // flip the tracks / trees to get best dQ/dx sequences
1095 
1097 
1098  listUsedClusters();
1099  return fResult.size();
1100 }
1101 // ------------------------------------------------------
1102 // ------------------------------------------------------
1103 
1105  size_t minBuildSize, unsigned int tpc, unsigned int cryo)
1106 {
1107  fInitialClusters.clear();
1108 
1109  size_t minSizeCompl = minBuildSize / 8; // smaller minimum required in complementary views
1110  if (minSizeCompl < 2) minSizeCompl = 2; // but at least two hits!
1111 
1112  int max_first_idx = 0;
1113  while (max_first_idx >= 0) // loop over clusters, any view, starting from the largest
1114  {
1115  mf::LogVerbatim("PMAlgTracker") << "Find max cluster...";
1116  max_first_idx = maxCluster(minBuildSize, geo::kUnknown, tpc, cryo); // any view, but must be track-like
1117  if ((max_first_idx >= 0) && !fCluHits[max_first_idx].empty())
1118  {
1119  geo::View_t first_view = fCluHits[max_first_idx].front()->View();
1120 
1121  pma::TrkCandidate candidate = matchCluster(max_first_idx,
1122  minSizeCompl, tpc, cryo, first_view);
1123 
1124  if (candidate.IsGood()) result.push_back(candidate);
1125  }
1126  else mf::LogVerbatim("PMAlgTracker") << "small clusters only";
1127  }
1128 
1129  fInitialClusters.clear();
1130 }
1131 // ------------------------------------------------------
1132 
1134  int first_clu_idx, const std::vector< art::Ptr<recob::Hit> > & first_hits,
1135  size_t minSizeCompl, unsigned int tpc, unsigned int cryo, geo::View_t first_view)
1136 {
1138 
1139  for (auto av : fAvailableViews) { fTriedClusters[av].clear(); }
1140 
1141  if (first_clu_idx >= 0)
1142  {
1143  fTriedClusters[first_view].push_back((size_t)first_clu_idx);
1144  fInitialClusters.push_back((size_t)first_clu_idx);
1145  }
1146 
1147  unsigned int nFirstHits = first_hits.size(), first_plane_idx = first_hits.front()->WireID().Plane;
1148  mf::LogVerbatim("PMAlgTracker") << std::endl << "--- start new candidate ---";
1149  mf::LogVerbatim("PMAlgTracker") << "use view *** " << first_view << " *** plane idx " << first_plane_idx << " *** size: " << nFirstHits;
1150 
1151  float x, xmax = fDetProp->ConvertTicksToX(first_hits.front()->PeakTime(), first_plane_idx, tpc, cryo), xmin = xmax;
1152  //mf::LogVerbatim("PMAlgTracker") << " *** x max0: " << xmax;
1153  for (size_t j = 1; j < first_hits.size(); ++j)
1154  {
1155  x = fDetProp->ConvertTicksToX(first_hits[j]->PeakTime(), first_plane_idx, tpc, cryo);
1156  if (x > xmax) { xmax = x; }
1157  if (x < xmin) { xmin = x; }
1158  }
1159  //mf::LogVerbatim("PMAlgTracker") << " *** x max: " << xmax << " min:" << xmin;
1160 
1161  pma::TrkCandidateColl candidates; // possible solutions of the selected cluster and clusters in complementary views
1162 
1163  size_t imatch = 0;
1164  bool try_build = true;
1165  while (try_build) // loop over complementary views
1166  {
1167  pma::TrkCandidate candidate;
1168  if (first_clu_idx >= 0) candidate.Clusters().push_back((size_t)first_clu_idx);
1169 
1170  try_build = false;
1171  int idx = -1, av_idx = -1;
1172  unsigned int nMaxHits = 0, nHits = 0;
1173  unsigned int testView = geo::kUnknown, bestView = geo::kUnknown;
1174  for (auto av : fAvailableViews)
1175  {
1176  if (av == first_view) continue;
1177 
1178  av_idx = maxCluster(first_clu_idx, candidates, xmin, xmax, minSizeCompl, av, tpc, cryo);
1179  if (av_idx >= 0)
1180  {
1181  nHits = fCluHits[av_idx].size();
1182  if ((nHits > nMaxHits) && (nHits >= minSizeCompl))
1183  {
1184  nMaxHits = nHits; idx = av_idx; bestView = av;
1185  fTriedClusters[av].push_back(idx);
1186  try_build = true;
1187  }
1188  }
1189  }
1190  for (auto av : fAvailableViews)
1191  {
1192  if ((av != first_view) && (av != bestView)) { testView = av; break; }
1193  }
1194 
1195  if (try_build)
1196  {
1197  mf::LogVerbatim("PMAlgTracker") << "--> " << imatch++ << " match with:";
1198  mf::LogVerbatim("PMAlgTracker") << " cluster in view *** " << bestView << " *** size: " << nMaxHits;
1199 
1200  if (!fGeom->TPC(tpc, cryo).HasPlane(testView)) { mf::LogVerbatim("PMAlgTracker") << " no validation plane *** "; testView = geo::kUnknown; }
1201  else { mf::LogVerbatim("PMAlgTracker") << " validation plane *** " << testView << " ***"; }
1202 
1203  double m0 = 0.0, v0 = 0.0;
1204  double mseThr = 0.15, validThr = 0.7; // cuts for a good track candidate
1205 
1206  candidate.Clusters().push_back(idx);
1207  candidate.SetTrack(fProjectionMatchingAlg.buildTrack(first_hits, fCluHits[idx]));
1208 
1209  if (candidate.IsValid() && // no track if hits from 2 views do not alternate
1210  fProjectionMatchingAlg.isContained(*(candidate.Track()), 2.0F)) // sticks out of TPC's?
1211  {
1212  m0 = candidate.Track()->GetMse();
1213  if (m0 < mseThr) // check validation only if MSE is OK - thanks for Tracy for noticing this
1214  { v0 = validate(*(candidate.Track()), testView); }
1215  }
1216 
1217  if (candidate.Track() && (m0 < mseThr) && (v0 > validThr)) // good candidate, try to extend it
1218  {
1219  mf::LogVerbatim("PMAlgTracker") << " good track candidate, MSE = " << m0 << ", v = " << v0;
1220 
1221  candidate.SetMse(m0);
1222  candidate.SetValidation(v0);
1223  candidate.SetGood(true);
1224 
1225  size_t minSize = 5; // min size for clusters matching
1226  double fraction = 0.5; // min fraction of close hits
1227 
1228  idx = 0;
1229  while (idx >= 0) // try to collect matching clusters, use **any** plane except validation
1230  {
1231  idx = matchCluster(candidate, minSize, fraction, geo::kUnknown, testView, tpc, cryo);
1232  if (idx >= 0)
1233  {
1234  // try building extended copy:
1235  // src, hits, valid.plane, add nodes
1236  if (extendTrack(candidate, fCluHits[idx], testView, true))
1237  {
1238  candidate.Clusters().push_back(idx);
1239  }
1240  else idx = -1;
1241  }
1242  }
1243 
1244  mf::LogVerbatim("PMAlgTracker") << "merge clusters from the validation plane";
1245  fraction = 0.7; // only well matching the existing track
1246 
1247  idx = 0;
1248  bool extended = false;
1249  while ((idx >= 0) && (testView != geo::kUnknown))
1250  { // match clusters from the plane used previously for the validation
1251  idx = matchCluster(candidate, minSize, fraction, testView, geo::kUnknown, tpc, cryo);
1252  if (idx >= 0)
1253  {
1254  // validation not checked here, no new nodes:
1255  if (extendTrack(candidate, fCluHits[idx], geo::kUnknown, false))
1256  {
1257  candidate.Clusters().push_back(idx);
1258  extended = true;
1259  }
1260  else idx = -1;
1261  }
1262  }
1263  // need to calculate again only if trk was extended w/o checking validation:
1264  if (extended) candidate.SetValidation(validate(*(candidate.Track()), testView));
1265  }
1266  else
1267  {
1268  mf::LogVerbatim("PMAlgTracker") << "track REJECTED, MSE = " << m0 << "; v = " << v0;
1269  candidate.SetGood(false); // save also bad matches to avoid trying again the same pair of clusters
1270  }
1271  candidates.push_back(candidate);
1272  }
1273  else
1274  {
1275  mf::LogVerbatim("PMAlgTracker") << "no matching clusters";
1276  }
1277  } // end loop over complementary views
1278 
1279  if (!candidates.empty()) // return best candidate, release other tracks and clusters
1280  {
1281  int best_trk = -1;
1282  double f, max_f = 0., min_mse = 10., max_v = 0.;
1283  for (size_t t = 0; t < candidates.size(); t++)
1284  if (candidates[t].IsGood() &&
1285  (candidates[t].Track()->Nodes().size() > 1) &&
1286  candidates[t].Track()->HasTwoViews())
1287  {
1288  f = fProjectionMatchingAlg.twoViewFraction(*(candidates[t].Track()));
1289 
1290  if ((f > max_f) || ((f == max_f) &&
1291  ((candidates[t].Validation() > max_v) || (candidates[t].Mse() < min_mse))))
1292  {
1293  max_f = f;
1294  min_mse = candidates[t].Mse();
1295  max_v = candidates[t].Validation();
1296  best_trk = t;
1297  }
1298  }
1299 
1300  if ((best_trk > -1) && candidates[best_trk].IsGood() && (max_f > fMinTwoViewFraction))
1301  {
1302  candidates[best_trk].Track()->ShiftEndsToHits();
1303 
1304  for (auto c : candidates[best_trk].Clusters())
1305  fUsedClusters.push_back(c);
1306 
1307  result = candidates[best_trk];
1308  }
1309 
1310  for (size_t t = 0; t < candidates.size(); t++)
1311  {
1312  if (int(t) != best_trk) candidates[t].DeleteTrack();
1313  }
1314  }
1315 
1316  return result;
1317 }
1318 // ------------------------------------------------------
1319 
1322  unsigned int testView, bool add_nodes)
1323 {
1324  double m_max = 2.0 * candidate.Mse(); // max acceptable MSE value
1325  if (m_max < 0.05) m_max = 0.05; // this is still good, low MSE value
1326 
1327  double v_min1 = 0.98 * candidate.Validation();
1328  double v_min2 = 0.9 * candidate.Validation();
1329 
1330  pma::Track3D* copy = fProjectionMatchingAlg.extendTrack(*(candidate.Track()), hits, add_nodes);
1331  double m1 = copy->GetMse();
1332  double v1 = validate(*copy, testView);
1333 
1334  if (((m1 < candidate.Mse()) && (v1 >= v_min2)) ||
1335  ((m1 < 0.5) && (m1 <= m_max) && (v1 >= v_min1)))
1336  {
1337  mf::LogVerbatim("PMAlgTracker")
1338  << " track EXTENDED, MSE = " << m1 << ", v = " << v1;
1339  candidate.SetTrack(copy); // replace with the new track (deletes old one)
1340  copy->SortHits(); // sort hits in the new track
1341 
1342  candidate.SetMse(m1); // save info
1343  candidate.SetValidation(v1);
1344 
1345  return true;
1346  }
1347  else
1348  {
1349  mf::LogVerbatim("PMAlgTracker")
1350  << " track NOT extended, MSE = " << m1 << ", v = " << v1;
1351  delete copy;
1352  return false;
1353  }
1354 }
1355 // ------------------------------------------------------
1356 
1358  size_t minSize, double fraction,
1359  unsigned int preferedView, unsigned int testView,
1360  unsigned int tpc, unsigned int cryo) const
1361 {
1362  double f, fmax = 0.0;
1363  unsigned int n, max = 0;
1364  int idx = -1;
1365  for (size_t i = 0; i < fCluHits.size(); ++i)
1366  {
1367  if (fCluHits[i].empty()) continue;
1368 
1369  unsigned int view = fCluHits[i].front()->View();
1370  unsigned int nhits = fCluHits[i].size();
1371 
1372  if (has(fUsedClusters, i) || // don't try already used clusters
1373  has(trk.Clusters(), i) || // don't try clusters from this candidate
1374  (view == testView) || // don't use clusters from validation view
1375  ((preferedView != geo::kUnknown)&&(view != preferedView)) || // only prefered view if specified
1376  (nhits < minSize)) // skip small clusters
1377  continue;
1378 
1379  n = fProjectionMatchingAlg.testHits(*(trk.Track()), fCluHits[i]);
1380  f = n / (double)nhits;
1381  if ((f > fraction) && (n > max))
1382  {
1383  max = n; fmax = f; idx = i;
1384  }
1385  }
1386 
1387  if (idx >= 0) mf::LogVerbatim("PMAlgTracker") << "max matching hits: " << max << " (" << fmax << ")";
1388  else mf::LogVerbatim("PMAlgTracker") << "no clusters to extend the track";
1389 
1390  return idx;
1391 }
1392 // ------------------------------------------------------
1393 
1394 int pma::PMAlgTracker::maxCluster(int first_idx_tag,
1395  const pma::TrkCandidateColl & candidates,
1396  float xmin, float xmax, size_t min_clu_size,
1397  geo::View_t view, unsigned int tpc, unsigned int cryo) const
1398 {
1399  int idx = -1;
1400  size_t s_max = 0, s;
1401  double fraction = 0.0;
1402  float x;
1403 
1404  size_t first_idx = 0;
1405  bool has_first = false;
1406  if (first_idx_tag >= 0)
1407  {
1408  first_idx = (size_t)first_idx_tag;
1409  has_first = true;
1410  }
1411 
1412  for (size_t i = 0; i < fCluHits.size(); ++i)
1413  {
1414  if ((fCluHits[i].size() < min_clu_size) || (fCluHits[i].front()->View() != view) ||
1415  has(fUsedClusters, i) || has(fInitialClusters, i) || has(fTriedClusters[view], i))
1416  continue;
1417 
1418  bool pair_checked = false;
1419  for (auto const & c : candidates.tracks())
1420  if (has_first && has(c.Clusters(), first_idx) && has(c.Clusters(), i))
1421  {
1422  pair_checked = true; break;
1423  }
1424  if (pair_checked) continue;
1425 
1426  const auto & v = fCluHits[i];
1427 
1428  if ((v.front()->WireID().TPC == tpc) &&
1429  (v.front()->WireID().Cryostat == cryo))
1430  {
1431  s = 0;
1432  for (size_t j = 0; j < v.size(); ++j)
1433  {
1434  x = fDetProp->ConvertTicksToX(v[j]->PeakTime(), v[j]->WireID().Plane, tpc, cryo);
1435  if ((x >= xmin) && (x <= xmax)) s++;
1436  }
1437 
1438  if (s > s_max)
1439  {
1440  s_max = s; idx = i; fraction = s / (double)v.size();
1441  }
1442  }
1443  }
1444  if (fraction > 0.4) return idx;
1445  else return -1;
1446 }
1447 // ------------------------------------------------------
1448 
1449 int pma::PMAlgTracker::maxCluster(size_t min_clu_size,
1450  geo::View_t view, unsigned int tpc, unsigned int cryo) const
1451 {
1452  int idx = -1;
1453  size_t s_max = 0, s;
1454 
1455  for (size_t i = 0; i < fCluHits.size(); ++i)
1456  {
1457  const auto & v = fCluHits[i];
1458 
1459  if (v.empty() || (fCluWeights[i] < fTrackLikeThreshold) ||
1460  has(fUsedClusters, i) || has(fInitialClusters, i) || has(fTriedClusters[view], i) ||
1461  ((view != geo::kUnknown) && (v.front()->View() != view)))
1462  continue;
1463 
1464  if ((v.front()->WireID().TPC == tpc) &&
1465  (v.front()->WireID().Cryostat == cryo))
1466  {
1467  s = v.size();
1468  if ((s >= min_clu_size) && (s > s_max))
1469  {
1470  s_max = s; idx = i;
1471  }
1472  }
1473  }
1474  return idx;
1475 }
1476 // ------------------------------------------------------
1477 // ------------------------------------------------------
1478 
1480 {
1481  //std::ofstream hits_file("pma_event_hits.prn");
1482 
1483  mf::LogVerbatim("PMAlgTracker") << std::endl << "----------- matched clusters: -----------";
1484  for (size_t i = 0; i < fCluHits.size(); ++i)
1485  {
1486  if (!fCluHits[i].empty() && has(fUsedClusters, i))
1487  {
1488  mf::LogVerbatim("PMAlgTracker")
1489  << " tpc: " << fCluHits[i].front()->WireID().TPC
1490  << ";\tview: " << fCluHits[i].front()->View()
1491  << ";\tsize: " << fCluHits[i].size()
1492  << ";\tweight: " << fCluWeights[i];
1493  //for (const auto & h : fCluHits[i])
1494  //{
1495  // hits_file << h->WireID().TPC << " " << h->View() << " "
1496  // << h->WireID().Wire << " " << h->PeakTime() << " " << h->Integral() << " "
1497  // << fCluHits[i].size() << " " << i << " "
1498  // << fCluWeights[i] << " -1" << std::endl;
1499  //}
1500  }
1501  }
1502 
1503  mf::LogVerbatim("PMAlgTracker") << "--------- not matched clusters: ---------";
1504  size_t nsingles = 0;
1505  for (size_t i = 0; i < fCluHits.size(); ++i)
1506  {
1507  if (!fCluHits[i].empty() && !has(fUsedClusters, i))
1508  {
1509  if (fCluHits[i].size() == 1) { nsingles++; }
1510  else
1511  {
1512  mf::LogVerbatim("PMAlgTracker")
1513  << " tpc: " << fCluHits[i].front()->WireID().TPC
1514  << ";\tview: " << fCluHits[i].front()->View()
1515  << ";\tsize: " << fCluHits[i].size()
1516  << ";\tweight: " << fCluWeights[i]
1517  << ";\tmatch: " << matchTrack(fResult, fCluHits[i]);
1518  }
1519  //for (const auto & h : fCluHits[i])
1520  //{
1521  // hits_file << h->WireID().TPC << " " << h->View() << " "
1522  // << h->WireID().Wire << " " << h->PeakTime() << " " << h->Integral() << " "
1523  // << fCluHits[i].size() << " " << i << " "
1524  // << fCluWeights[i] << " " << matchTrack(fResult, fCluHits[i])/(float)fCluHits[i].size()
1525  // << std::endl;
1526  //}
1527  }
1528  }
1529  //hits_file.close();
1530  mf::LogVerbatim("PMAlgTracker") << " single hits: " << nsingles;
1531  mf::LogVerbatim("PMAlgTracker") << "-----------------------------------------";
1532 }
1533 // ------------------------------------------------------
1534 // ------------------------------------------------------
1535 
Float_t x
Definition: compare.C:6
unsigned int testHits(const pma::Track3D &trk, const std::vector< art::Ptr< recob::Hit > > &hits, double eps=1.0) const
Count the number of hits that are closer than eps * fHitTestingDist2D to the track 2D projection...
double collectSingleViewFront(pma::Track3D &trk, std::vector< art::Ptr< recob::Hit > > &hits)
bool SelectHits(float fraction=1.0F)
pma::Track3D * buildShowerSeg(const std::vector< art::Ptr< recob::Hit > > &hits, const pma::Vector3D &vtx) const
Build a shower segment from sets of hits and attached to the provided vertex.
Float_t s
Definition: plot.C:23
const std::vector< size_t > & Clusters(void) const
std::vector< std::vector< art::Ptr< recob::Hit > > > fCluHits
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool HasPlane(unsigned int iplane) const
Returns whether a plane with index iplane is present in this TPC.
Definition: TPCGeo.h:155
bool mergeCoLinear(pma::TrkCandidateColl &tracks)
pma::Node3D * LastElement(void) const
Definition: PmaTrack3D.h:234
void tag(pma::TrkCandidateColl &tracks)
void CleanupTails(void)
Cut out tails with no hits assigned.
void buildTracks(void)
double Mse(void) const
double GetMse(unsigned int view=geo::kUnknown) const
MSE of hits weighted with hit amplidudes and wire plane coefficients.
TPC_id_iterator begin_TPC_id() const
Returns an iterator pointing to the first TPC ID in the detector.
static constexpr Mask_t makeMask(Flags...flags)
Returns a bit mask with only the specified bit set.
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 guideEndpoints(pma::Track3D &trk, const std::map< unsigned int, std::vector< art::Ptr< recob::Hit > > > &hits) const
Add 3D reference points to clean endpoints of a track (both need to be in the same TPC)...
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)
geo::GeometryCore const * fGeom
double Dist2(const TVector2 &v1, const TVector2 &v2)
Definition: Utilities.cxx:19
unsigned int FrontTPC(void) const
Definition: PmaTrack3D.h:104
bool Flip(std::vector< pma::Track3D * > &allTracks)
Definition: PmaTrack3D.cxx:499
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
Definition: TrackingTypes.h:85
T::provider_type const * providerFrom()
Returns a constant pointer to the provider of specified service.
Definition: ServiceUtil.h:77
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
void flipTreesToCoordinate(size_t coordinate)
size_t fMinSeedSize2ndPass
Unknown view.
Definition: geo_types.h:83
void erase_at(size_t pos)
bool IsGood(void) const
std::set< geo::View_t > const & Views() const
Returns a list of possible views in the detector.
::fhicl::TupleAs< Point(::geo::Length_t,::geo::Length_t,::geo::Length_t)> Point3D
Atom object for reading a 3D point or vector (centimeters).
bool reassignHits_2(const std::vector< art::Ptr< recob::Hit > > &hits, pma::TrkCandidateColl &tracks, size_t trk_idx, double dist2)
void setParentDaughterConnections(void)
Geometry information for a single TPC.
Definition: TPCGeo.h:37
std::vector< pma::Node3D * > const & Nodes(void) const
Definition: PmaTrack3D.h:232
double fMinTwoViewFraction
bool reassignHits_1(const std::vector< art::Ptr< recob::Hit > > &hits, pma::TrkCandidateColl &tracks, size_t trk_idx, double dist2)
fhicl::Atom< std::string > Validation
void SetGood(bool b)
const detinfo::DetectorProperties * fDetProp
std::vector< std::vector< art::Ptr< recob::Hit > > > fCluHits
std::vector< TrkCandidate > const & tracks(void) const
Float_t tmp
Definition: plot.C:37
pma::PMAlgCosmicTagger fCosmicTagger
void SetValidation(double v)
void SetTrack(pma::Track3D *trk)
double GetDistToWall(void) const
Definition: PmaNode3D.cxx:64
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
bool areCoLinear(pma::Track3D *trk1, pma::Track3D *trk2, double &dist, double &cos3d, bool &reverseOrder, double distThr, double distThrMin, double distProjThr, double cosThr)
double fStitchTransverseShift
void listUsedClusters(void) const
std::vector< pma::Segment3D * > const & Segments(void) const
Definition: PmaTrack3D.h:227
void RemoveHits(const std::vector< art::Ptr< recob::Hit > > &hits)
Remove hits; removes also hit->node/seg assignments.
Definition: PmaTrack3D.cxx:399
recob::tracking::Vector_t Vector3D
Definition: Utilities.h:29
std::map< int, pma::Vector3D > fPfpVtx
pma::Vector3D GetDirection3D(size_t index) const
Get trajectory direction at given hit index.
Definition: PmaTrack3D.cxx:373
pma::Track3D * buildMultiTPCTrack(const std::vector< art::Ptr< recob::Hit > > &hits) const
as far as hits origin from at least two wire planes.
pma::TrkCandidate matchCluster(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)
bool IsValid(void) const
void freezeBranchingNodes(pma::TrkCandidateColl &tracks)
recob::tracking::Point_t Point_t
bool ShiftEndsToHits(void)
TFile f
Definition: plotHisto.C:6
void StitchTracksCPA(pma::TrkCandidateColl &tracks)
std::vector< double > fAdcValidationThr
size_t size(void) const
std::vector< int > fTrackingOnlyPdg
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
size_t matchTrack(const pma::TrkCandidateColl &tracks, const std::vector< art::Ptr< recob::Hit > > &hits) const
std::vector< float > fCluWeights
pma::PMAlgStitching fStitcher
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 ...
Definition: TrackingTypes.h:29
Int_t max
Definition: plot.C:27
fhicl::Sequence< double > AdcValidationThr
void hits()
Definition: readHits.C:15
unsigned int MaxPlanes() const
Returns the largest number of planes among all TPCs in this detector.
bool isContained(const pma::Track3D &trk, float margin=0.0F) const
TVector2 GetProjectionToSegment(const TVector2 &p, const TVector2 &p0, const TVector2 &p1)
Definition: Utilities.cxx:156
A trajectory in space reconstructed from hits.
double validate(pma::Track3D &trk, unsigned int testView)
std::vector< int > fTrackingSkipPdg
bool reassignSingleViewEnds_2(pma::TrkCandidateColl &tracks)
pma::Track3D * buildTrack(const std::vector< art::Ptr< recob::Hit > > &hits_1, const std::vector< art::Ptr< recob::Hit > > &hits_2=std::vector< art::Ptr< recob::Hit > >()) const
wire planes; number of segments used to create the track depends on the number of hits...
const std::vector< recob::Wire > & fWires
bool has(const std::vector< size_t > &v, size_t idx) const
pma::Hit3D *& back()
Definition: PmaTrack3D.h:74
Float_t d
Definition: plot.C:237
pma::ProjectionMatchingAlg fProjectionMatchingAlg
Definition: PMAlgTracking.h:79
double fMergeTransverseShift
void SetMse(double m)
double collectSingleViewEnd(pma::Track3D &trk, std::vector< art::Ptr< recob::Hit > > &hits)
std::map< int, int > fPfpPdgCodes
General LArSoft Utilities.
bool extendTrack(pma::TrkCandidate &candidate, const std::vector< art::Ptr< recob::Hit > > &hits, unsigned int testView, bool add_nodes)
unsigned int FrontCryo(void) const
Definition: PmaTrack3D.h:105
TPC_id_iterator end_TPC_id() const
Returns an iterator pointing after the last TPC ID in the detector.
bool has(const std::vector< int > &v, int i) const
unsigned int DisableSingleViewEnds(void)
std::vector< size_t > fInitialClusters
double validate_on_adc_test(const pma::Track3D &trk, const img::DataProviderAlg &adcImage, const std::vector< art::Ptr< recob::Hit > > &hits, TH1F *histoPassing, TH1F *histoRejected) const
bool reassignSingleViewEnds_1(pma::TrkCandidateColl &tracks)
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
TVector3 const & Point3D(void) const
Definition: PmaHit3D.h:48
double validate_on_adc(const pma::Track3D &trk, const img::DataProviderAlg &adcImage, float thr) const
fhicl::Table< img::DataProviderAlg::Config > AdcImageAlg
bool HasTwoViews(size_t nmin=1) const
Definition: PmaTrack3D.cxx:428
recob::tracking::SMatrixSym55 SMatrixSym55
Implementation of the Projection Matching Algorithm.
double Validation(void) const
double Length(size_t step=1) const
Definition: PmaTrack3D.h:81
std::vector< img::DataProviderAlg > fAdcImages
LArSoft-specific namespace.
void init(const art::FindManyP< recob::Hit > &hitsFromClusters)
short int DetectDriftDirection() const
Returns the expected drift direction based on geometry.
Definition: TPCGeo.cxx:182
void StitchTracksAPA(pma::TrkCandidateColl &tracks)
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::map< unsigned int, std::vector< size_t > > fTriedClusters
pma::Track3D * extendTrack(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.
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
void guideEndpoints(pma::TrkCandidateColl &tracks)
std::map< size_t, pma::TrkCandidateColl > tpc_track_map
Definition: PMAlgTracking.h:46
int maxCluster(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
bool empty(void) const
HLT enums.
void buildShowers(void)
std::vector< geo::View_t > fAvailableViews
Char_t n[5]
TrackCollectionProxyElement< TrackCollProxy > Track
Proxy to an element of a proxy collection of recob::Track objects.
Definition: Track.h:1035
PMAlgTrackingBase(const std::vector< art::Ptr< recob::Hit > > &allhitlist, const pma::ProjectionMatchingAlg::Config &pmalgConfig, const pma::PMAlgVertexing::Config &pmvtxConfig)
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
const pma::TrkCandidateColl & result(void)
Definition: PMAlgTracking.h:59
size_t fMinSeedSize1stPass
void SortHits(void)
pma::TrkCandidateColl fResult
Definition: PMAlgTracking.h:82
std::vector< size_t > fUsedClusters
EValidationMode fValidation
size_t size() const
Definition: PmaTrack3D.h:76
recob::tracking::Plane Plane
Definition: TrackState.h:17
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...
Definition: TrackingTypes.h:26
Namespace collecting geometry-related classes utilities.
double twoViewFraction(pma::Track3D &trk) const
void releaseAllNodes(pma::TrkCandidateColl &tracks)
size_t run(pma::TrkCandidateColl &trk_input)
const std::vector< TH1F * > & fAdcInPassingPoints
recob::tracking::Vector_t Vector_t
pma::Hit3D *& front()
Definition: PmaTrack3D.h:72
double validate(const pma::Track3D &trk, const std::vector< art::Ptr< recob::Hit > > &hits) const
const std::vector< TH1F * > & fAdcInRejectedPoints
pma::Node3D * FirstElement(void) const
Definition: PmaTrack3D.h:233
void push_back(const TrkCandidate &trk)
void fromMaxCluster_tpc(pma::TrkCandidateColl &result, size_t minBuildSize, unsigned int tpc, unsigned int cryo)
pma::PMAlgVertexing fPMAlgVertexing
Definition: PMAlgTracking.h:80
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track:
Definition: Track.h:52
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
void ApplyDriftShiftInTree(double dx, bool skipFirst=false)
Adjust track tree position in the drift direction (when T0 is being corrected).
pma::cryo_tpc_view_hitmap fHitMap
Definition: PMAlgTracking.h:77
void mergeTracks(pma::Track3D &dst, pma::Track3D &src, bool reopt) const
pma::Track3D * Track(void) const
void AddHits(const std::vector< art::Ptr< recob::Hit > > &hits)
Definition: PmaTrack3D.cxx:393
std::map< int, std::vector< art::Ptr< recob::Cluster > > > fPfpClusters