LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
PMAlgVertexing.cxx
Go to the documentation of this file.
1 // Class: PMAlgVertexing
3 // Author: D.Stefan (Dorota.Stefan@ncbj.gov.pl) and R.Sulej (Robert.Sulej@cern.ch), August 2015
5 
7 
10 
12 
13 #include "TMath.h"
14 
16 {
18 
19  fFindKinks = config.FindKinks();
20  fKinkMinDeg = config.KinkMinDeg();
21  fKinkMinStd = config.KinkMinStd();
22 }
23 // ------------------------------------------------------
24 
26 {
27  cleanTracks();
28 }
29 // ------------------------------------------------------
30 
32 {
33  for (auto& t : fOutTracks.tracks())
34  t.DeleteTrack();
35  fOutTracks.clear();
36 
37  for (auto& t : fShortTracks.tracks())
38  t.DeleteTrack();
40 
41  for (auto& t : fEmTracks.tracks())
42  t.DeleteTrack();
43  fEmTracks.clear();
44 
45  for (auto& t : fExcludedTracks.tracks())
46  t.DeleteTrack();
48 }
49 // ------------------------------------------------------
50 
52 {
53  mf::LogVerbatim("pma::PMAlgVertexing") << "clean input: " << result.size() << std::endl;
54  for (auto& t : result.tracks())
55  t.DeleteTrack();
56  result.clear();
57 
58  mf::LogVerbatim("pma::PMAlgVertexing")
59  << "fill input from out: " << fOutTracks.size() << std::endl;
60  for (auto const& t : fOutTracks.tracks())
61  result.push_back(t);
62  fOutTracks.clear();
63 
64  mf::LogVerbatim("pma::PMAlgVertexing")
65  << "fill input from short: " << fShortTracks.size() << std::endl;
66  for (auto const& t : fShortTracks.tracks())
67  result.push_back(t);
69 
70  mf::LogVerbatim("pma::PMAlgVertexing") << "fill input from em: " << fEmTracks.size() << std::endl;
71  for (auto const& t : fEmTracks.tracks())
72  result.push_back(t);
73  fEmTracks.clear();
74 
75  mf::LogVerbatim("pma::PMAlgVertexing")
76  << "copy back excluded tracks: " << fExcludedTracks.size() << std::endl;
77  for (auto const& t : fExcludedTracks.tracks())
78  result.push_back(t);
80 }
81 // ------------------------------------------------------
82 
84 {
85  cleanTracks();
86 
87  for (auto const& t : trk_input.tracks()) {
88  pma::Track3D* copy = new pma::Track3D(*(t.Track()));
89  int key = t.Key();
90 
91  if ((t.Track()->GetT0() != 0) || // do not create vertices on cosmic muons, now track with any
92  // non-zero t0 is a muon,
93  (t.Track()->HasTagFlag(pma::Track3D::kCosmic))) // tag for track recognized as a cosmic ray
94  // is starting to be used
95  {
96  fExcludedTracks.tracks().emplace_back(copy, key);
97  continue;
98  }
99 
100  double l = t.Track()->Length();
101 
102  if (t.Track()->GetTag() == pma::Track3D::kEmLike) {
103  if (l > 2 * fMinTrackLength)
104  fOutTracks.tracks().emplace_back(copy, key);
105  else
106  fEmTracks.tracks().emplace_back(copy, key);
107  }
108  else {
109  if (l > fMinTrackLength)
110  fOutTracks.tracks().emplace_back(copy, key);
111  else
112  fEmTracks.tracks().emplace_back(copy, key);
113  }
114  }
115  mf::LogVerbatim("pma::PMAlgVertexing") << "long tracks: " << fOutTracks.size() << std::endl;
116  mf::LogVerbatim("pma::PMAlgVertexing")
117  << "em and short tracks: " << fEmTracks.size() << std::endl;
118  mf::LogVerbatim("pma::PMAlgVertexing")
119  << "excluded cosmic tracks: " << fExcludedTracks.size() << std::endl;
120 }
121 // ------------------------------------------------------
122 
123 std::vector<pma::VtxCandidate> pma::PMAlgVertexing::firstPassCandidates() const
124 {
125  std::vector<pma::VtxCandidate> candidates;
126  for (size_t t = 0; t < fOutTracks.size() - 1; t++) {
127  for (size_t u = t + 1; u < fOutTracks.size(); u++) {
128  pma::VtxCandidate candidate;
129  if (!candidate.Add(fOutTracks[t])) break; // no segments with length > thr
130 
131  // **************************** try Mse2D / or only Mse ************************************
132  if (candidate.Add(fOutTracks[u]) && (sqrt(candidate.Mse()) < 1.0))
133  //if (candidate.Add(fOutTracks[u]) && (sqrt(candidate.Mse()) < 2.0) && (candidate.Mse2D() < 1.0))
134  {
135  candidates.push_back(candidate);
136  }
137  }
138  }
139  return candidates;
140 }
141 
142 std::vector<pma::VtxCandidate> pma::PMAlgVertexing::secondPassCandidates() const
143 {
144  std::vector<pma::VtxCandidate> candidates;
145  for (size_t t = 0; t < fOutTracks.size(); t++)
146  if (fOutTracks[t].Track()->Length() > fMinTrackLength) {
147  for (size_t u = 0; u < fEmTracks.size(); u++) {
148  pma::VtxCandidate candidate;
149  if (!candidate.Add(fOutTracks[t])) break; // no segments with length > thr
150 
151  if (fOutTracks[t].Track() == fEmTracks[u].Track()) continue;
152 
153  if (candidate.Add(fEmTracks[u]) && (sqrt(candidate.Mse()) < 1.0)) {
154  candidates.push_back(candidate);
155  }
156  }
157  }
158  return candidates;
159 }
160 
162  std::vector<pma::VtxCandidate>& candidates)
163 {
164  bool merged = true;
165  while (merged && (candidates.size() > 1)) {
166  size_t k_best, l_best, k = 0;
167  while (k < candidates.size() - 1) {
168  size_t l = k + 1;
169  while (l < candidates.size()) {
170  if (candidates[l].Has(candidates[k])) {
171  candidates[k] = candidates[l];
172  candidates.erase(candidates.begin() + l);
173  }
174  else if (candidates[k].Has(candidates[l])) {
175  candidates.erase(candidates.begin() + l);
176  }
177  else
178  l++;
179  }
180  k++;
181  }
182 
183  merged = false;
184  double d_thr = 1.0; // 1.0 = max weighted dist. threshold
185  double d, dmin = d_thr;
186 
187  k = 0;
188  while (k < candidates.size() - 1) {
189  size_t l = k + 1;
190  while (l < candidates.size()) {
191  d = candidates[k].Test(candidates[l]);
192  if (d < dmin) {
193  dmin = d;
194  k_best = k;
195  l_best = l;
196  }
197  l++;
198  }
199  k++;
200  }
201  if ((dmin < d_thr) && candidates[k_best].MergeWith(candidates[l_best])) {
202  candidates.erase(candidates.begin() + l_best);
203  merged = true;
204  }
205  }
206 
207  mf::LogVerbatim("pma::PMAlgVertexing") << "*** Vtx candidates: " << candidates.size();
208  std::vector<pma::VtxCandidate> toJoin;
209  bool select = true;
210  while (select) {
211  int s, nmax = 0, c_best = -1;
212  double a, amax = 0.0;
213 
214  for (size_t v = 0; v < candidates.size(); v++) {
215  if (candidates[v].HasLoops()) continue;
216 
217  bool maybeCorrelated = false;
218  for (size_t u = 0; u < toJoin.size(); u++)
219  if (toJoin[u].IsAttached(candidates[v]) || // connected with tracks or close centers
220  (pma::Dist2(toJoin[u].Center(), candidates[v].Center()) < 15.0 * 15.0)) {
221  maybeCorrelated = true;
222  break;
223  }
224  if (maybeCorrelated) continue;
225 
226  s = (int)candidates[v].Size(2 * fMinTrackLength);
227  a = candidates[v].MaxAngle(1.0);
228 
229  if ((s > nmax) || ((s == nmax) && (a > amax))) {
230  nmax = s;
231  amax = a;
232  c_best = v;
233  }
234  /*
235  mf::LogVerbatim("pma::PMAlgVertexing")
236  << "center x:" << candidates[v].Center().X()
237  << " y:" << candidates[v].Center().Y()
238  << " z:" << candidates[v].Center().Z();
239 
240  for (size_t i = 0; i < candidates[v].Size(); i++)
241  mf::LogVerbatim("pma::PMAlgVertexing")
242  << " trk:" << i << " "
243  << candidates[v].Track(i).first->size();
244 
245  mf::LogVerbatim("pma::PMAlgVertexing")
246  << " dist 3D:" << sqrt(candidates[v].Mse())
247  << " 2D:" << sqrt(candidates[v].Mse2D())
248  << " max ang:" << a;
249 */
250  }
251  if (c_best >= 0) {
252  toJoin.push_back(candidates[c_best]);
253  candidates.erase(candidates.begin() + c_best);
254  }
255  else
256  select = false;
257  }
258  mf::LogVerbatim("pma::PMAlgVertexing") << "*** Vtx selected to join: " << toJoin.size();
259 
260  size_t njoined = 0;
261  for (auto& c : toJoin) {
262  if (c.JoinTracks(detProp, fOutTracks, fEmTracks)) njoined++;
263  }
264 
265  return njoined;
266 }
267 // ------------------------------------------------------
268 
270  pma::TrkCandidateColl& trk_input)
271 {
272  if (fFindKinks) findKinksOnTracks(detProp, trk_input);
273 
274  if (trk_input.size() < 2) {
275  mf::LogWarning("pma::PMAlgVertexing") << "need min two source tracks!";
276  return 0;
277  }
278 
279  sortTracks(trk_input); // copy input and split by tag/size
280 
281  size_t nvtx = 0;
282  mf::LogVerbatim("pma::PMAlgVertexing") << "Pass #1:";
283  //std::cout << "Pass #1:" << std::endl;
284  if (fOutTracks.size() > 1) {
285  size_t nfound = 0;
286  do {
287  auto candidates = firstPassCandidates();
288  if (candidates.size()) {
289  nfound = makeVertices(detProp, candidates);
290  nvtx += nfound;
291  }
292  else
293  nfound = 0;
294  } while (nfound > 0);
295  mf::LogVerbatim("pma::PMAlgVertexing") << " " << nvtx << " vertices.";
296  //std::cout << " " << nvtx << " vertices." << std::endl;
297  }
298  else
299  mf::LogVerbatim("pma::PMAlgVertexing") << " ...short tracks only.";
300 
301  mf::LogVerbatim("pma::PMAlgVertexing") << "Pass #2:";
302  //std::cout << "Pass #2:" << std::endl;
303  if (fOutTracks.size() && fEmTracks.size()) {
304  size_t nfound = 1; // just to start
305  while (nfound && fEmTracks.size()) {
306  auto candidates = secondPassCandidates();
307  if (candidates.size()) {
308  nfound = makeVertices(detProp, candidates);
309  nvtx += nfound;
310  }
311  else
312  nfound = 0;
313  }
314  mf::LogVerbatim("pma::PMAlgVertexing") << " " << nvtx << " vertices.";
315  //std::cout << " " << nvtx << " vertices." << std::endl;
316  }
317  else
318  mf::LogVerbatim("pma::PMAlgVertexing") << " ...no tracks.";
319 
320  collectTracks(trk_input);
321 
322  mergeBrokenTracks(trk_input);
323 
324  return nvtx;
325 }
326 // ------------------------------------------------------
327 
329  const std::vector<TVector3>& /* vtx_input */)
330 {
331  sortTracks(trk_input); // copy input and split by tag/size
332 
333  // ....
334 
335  //collectTracks(trk_input); // return output in place of (deleted) input
336 
337  return 0;
338 }
339 // ------------------------------------------------------
340 
341 std::vector<std::pair<double, double>> pma::PMAlgVertexing::getdQdx(const pma::Track3D& trk) const
342 {
343  std::vector<std::pair<double, double>> result;
344 
345  unsigned int view = geo::kZ;
346  unsigned int nhits = trk.NHits(view);
347  unsigned int max = nhits;
348 
349  nhits = trk.NHits(geo::kV);
350  if (nhits > max) {
351  max = nhits;
352  view = geo::kV;
353  }
354 
355  nhits = trk.NHits(geo::kU);
356  if (nhits > max) {
357  max = nhits;
358  view = geo::kU;
359  }
360 
361  if (max >= 16) {
362  std::map<size_t, std::vector<double>> dqdx;
363  trk.GetRawdEdxSequence(dqdx, view);
364 
365  for (size_t i = 0; i < trk.size(); i++) {
366  auto it = dqdx.find(i);
367  if (it != dqdx.end()) {
368  if (it->second[6] > 0.0) // dx > 0
369  {
370  double dvalue = it->second[5] / it->second[6];
371  result.emplace_back(std::pair<double, double>(dvalue, it->second[7]));
372  }
373  }
374  }
375  }
376 
377  return result;
378 }
379 // ------------------------------------------------------
380 
382  size_t len,
383  double* adc,
384  double const* shape) const
385 {
386  size_t half = len >> 1;
387  double v, mean = 0.0, stdev = 0.0;
388  for (size_t i = 0; i < len; i++) {
389  v = adc[idx - half + i];
390  mean += v;
391  stdev += v * v;
392  }
393  mean /= len;
394  stdev /= len;
395  stdev -= mean;
396 
397  double sum = 0.0;
398  for (size_t i = 0; i < len; i++)
399  sum += (adc[idx - half + i] - mean) * shape[i];
400 
401  return sum / sqrt(stdev);
402 }
403 
405 {
406  const double minCos = 0.996194698; // 5 deg (is it ok?)
407  double segCos =
408  trk1->Segments().back()->GetDirection3D().Dot(trk2->Segments().front()->GetDirection3D());
409  if (segCos < minCos) {
410  mf::LogVerbatim("pma::PMAlgVertexing") << " has large angle, cos: " << segCos;
411  return false;
412  }
413 
414  const size_t stepShapeLen = 16;
415  const size_t stepShapeHalf = stepShapeLen >> 1;
416  const double stepShape[stepShapeLen] = {
417  -1., -1., -1., -1., -1., -1., -1., -1., 1., 1., 1., 1., 1., 1., 1., 1.};
418 
419  auto dqdx1 = getdQdx(*trk1);
420  if (dqdx1.size() < stepShapeHalf) return false;
421  auto dqdx2 = getdQdx(*trk2);
422  if (dqdx2.size() < stepShapeHalf) return false;
423 
424  const size_t adcLen =
425  stepShapeLen + 2; // 1 sample before/after to check convolution at 3 points in total
426  const size_t adcHalf = adcLen >> 1;
427 
428  double dqdx[adcLen];
429  for (size_t i = 0; i < adcLen; i++)
430  dqdx[i] = 0.0;
431 
432  bool has_m = true;
433  for (int i = adcHalf - 1, j = dqdx1.size() - 1; i >= 0; i--, j--) {
434  if (j >= 0)
435  dqdx[i] = dqdx1[j].first;
436  else {
437  dqdx[i] = dqdx[i + 1];
438  has_m = false;
439  }
440  }
441  bool has_p = true;
442  for (size_t i = adcHalf, j = 0; i < adcLen; i++, j++) {
443  if (j < dqdx2.size())
444  dqdx[i] = dqdx2[j].first;
445  else {
446  dqdx[i] = dqdx[i - 1];
447  has_p = false;
448  }
449  }
450 
451  double sum_m = 0.0;
452  if (has_m) sum_m = convolute(adcHalf - 1, stepShapeLen, dqdx, stepShape);
453  double sum_0 = convolute(adcHalf, stepShapeLen, dqdx, stepShape);
454  double sum_p = 0.0;
455  if (has_p) sum_p = convolute(adcHalf + 1, stepShapeLen, dqdx, stepShape);
456 
457  const double convMin = 0.8;
458  if ((fabs(sum_m) >= convMin) || (fabs(sum_0) >= convMin) || (fabs(sum_p) >= convMin)) {
459  mf::LogVerbatim("pma::PMAlgVertexing")
460  << " has step in conv.values: " << sum_m << ", " << sum_0 << ", " << sum_p;
461  return false;
462  }
463  else {
464  mf::LogVerbatim("pma::PMAlgVertexing")
465  << " single particle, conv.values: " << sum_m << ", " << sum_0 << ", " << sum_p;
466  return true;
467  }
468 }
469 
471 {
472  if (trk_input.size() < 2) return;
473 
474  mf::LogVerbatim("pma::PMAlgVertexing") << "Find and merge tracks broken by vertices.";
475  bool merged = true;
476  while (merged) {
477  merged = false;
478  for (size_t t = 0; t < trk_input.size(); t++) {
479  pma::Track3D* trk1 = trk_input[t].Track();
480  pma::Track3D* trk2 = 0;
481 
482  pma::Node3D* node = trk1->Nodes().front();
483  if (node->Prev()) {
484  pma::Segment3D* seg = static_cast<pma::Segment3D*>(node->Prev());
485  trk2 = seg->Parent();
486  if ((trk1 != trk2) && isSingleParticle(trk2, trk1)) // note: reverse order
487  {
488  //merged = true;
489  break;
490  }
491  }
492 
493  trk2 = 0;
494  double c, maxc = 0.0;
495  pma::Vector3D dir1 = trk1->Segments().back()->GetDirection3D();
496  node = trk1->Nodes().back();
497  for (size_t n = 0; n < node->NextCount(); n++) {
498  pma::Segment3D* seg = static_cast<pma::Segment3D*>(node->Next(n));
499  pma::Track3D* tst = seg->Parent();
500  if (tst != trk1) // should always be true: the last node of trk1 is tested
501  {
502  c = dir1.Dot(tst->Segments().front()->GetDirection3D());
503  if (c > maxc) {
504  maxc = c;
505  trk2 = tst;
506  }
507  }
508  }
509  if ((trk2) && isSingleParticle(trk1, trk2)) {
510  //merged = true;
511  break;
512  }
513  }
514  }
515  mf::LogVerbatim("pma::PMAlgVertexing") << "-------- done --------";
516 }
517 // ------------------------------------------------------
518 
520 {
521  if (trk_input.size() < 1) return;
522 
523  mf::LogVerbatim("pma::PMAlgVertexing") << "Find missed vtx by dQ/dx steps along merged tracks.";
524  size_t t = 0;
525  while (t < trk_input.size()) {
526  t++;
527  }
528  mf::LogVerbatim("pma::PMAlgVertexing") << "-------- done --------";
529 }
530 // ------------------------------------------------------
531 
533  pma::TrkCandidateColl& trk_input) const
534 {
535  if (trk_input.size() < 1) return;
536 
537  mf::LogVerbatim("pma::PMAlgVertexing")
538  << "Find kinks on tracks, reopt with no penalty on angle where kinks.";
539  for (size_t t = 0; t < trk_input.size(); ++t) {
540  pma::Track3D* trk = trk_input[t].Track();
541  if (trk->Nodes().size() < 5) continue;
542 
543  trk->Optimize(detProp, 0, 1.0e-5, false);
544 
545  std::vector<size_t> tested_nodes;
546  bool kinkFound = true;
547  while (kinkFound) {
548  int kinkIdx = -1, nnodes = 0;
549  double mean = 0.0, stdev = 0.0, min = 1.0, max_a = 0.0;
550  for (size_t n = 1; n < trk->Nodes().size() - 1; ++n) {
551  auto const& node = *(trk->Nodes()[n]);
552 
553  if (node.IsVertex() || node.IsTPCEdge()) continue;
554  nnodes++;
555 
556  double c = -node.SegmentCosTransverse();
557  double a = 180.0 * (1 - std::acos(node.SegmentCosTransverse()) / TMath::Pi());
558  mean += c;
559  stdev += c * c;
560  if ((c < min) && !has(tested_nodes, n)) {
561  if ((n > 1) && (n < trk->Nodes().size() - 2)) kinkIdx = n;
562  min = c;
563  max_a = a;
564  }
565  }
566 
567  kinkFound = false;
568  if ((nnodes > 2) && (kinkIdx > 0) && (max_a > fKinkMinDeg)) {
569  mean /= nnodes;
570  stdev /= nnodes;
571  stdev -= mean * mean;
572 
573  double thr = 1.0 - fKinkMinStd * stdev;
574  if (min < thr) {
575  mf::LogVerbatim("pma::PMAlgVertexing") << " kink a: " << max_a << "deg";
576  trk->Nodes()[kinkIdx]->SetVertex(true);
577  tested_nodes.push_back(kinkIdx);
578  kinkFound = true;
579 
580  trk->Optimize(detProp, 0, 1.0e-5, false, false);
581  double c = -trk->Nodes()[kinkIdx]->SegmentCosTransverse();
582  double a =
583  180.0 * (1 - std::acos(trk->Nodes()[kinkIdx]->SegmentCosTransverse()) / TMath::Pi());
584 
585  if ((a <= fKinkMinDeg) || (c >= thr)) // not a significant kink after precise optimization
586  {
587  mf::LogVerbatim("pma::PMAlgVertexing") << " -> tag removed after reopt";
588  trk->Nodes()[kinkIdx]->SetVertex(
589  false); // kinkIdx is saved in tested_nodes to avoid inf loop
590  }
591  }
592  }
593  }
594 
595  mf::LogVerbatim("pma::PMAlgVertexing") << "-------- done --------";
596  }
597 }
598 // ------------------------------------------------------
599 
600 std::vector<std::pair<TVector3, std::vector<std::pair<size_t, bool>>>>
601 pma::PMAlgVertexing::getVertices(const pma::TrkCandidateColl& tracks, bool onlyBranching) const
602 {
603  std::vector<std::pair<TVector3, std::vector<std::pair<size_t, bool>>>> vsel;
604  std::vector<pma::Node3D const*> bnodes;
605 
606  for (size_t t = 0; t < tracks.size(); ++t) {
607  pma::Track3D const* trk = tracks[t].Track();
608  pma::Node3D const* firstNode = trk->Nodes().front();
609  if (!(onlyBranching || firstNode->IsBranching())) {
610  std::vector<std::pair<size_t, bool>> tidx;
611  tidx.emplace_back(std::pair<size_t, bool>(t, true));
612  vsel.emplace_back(
613  std::pair<TVector3, std::vector<std::pair<size_t, bool>>>(trk->front()->Point3D(), tidx));
614  }
615 
616  bool pri = true;
617  for (auto node : trk->Nodes())
618  if (node->IsBranching()) {
619  bool found = false;
620  for (size_t n = 0; n < bnodes.size(); n++)
621  if (node == bnodes[n]) {
622  vsel[n].second.emplace_back(std::pair<size_t, bool>(t, pri));
623  found = true;
624  break;
625  }
626  if (!found) {
627  std::vector<std::pair<size_t, bool>> tidx;
628  tidx.emplace_back(std::pair<size_t, bool>(t, pri));
629  vsel.emplace_back(
630  std::pair<TVector3, std::vector<std::pair<size_t, bool>>>(node->Point3D(), tidx));
631  bnodes.push_back(node);
632  }
633  pri = false;
634  }
635  }
636 
637  return vsel;
638 }
639 // ------------------------------------------------------
640 
641 std::vector<std::pair<TVector3, size_t>> pma::PMAlgVertexing::getKinks(
642  const pma::TrkCandidateColl& tracks) const
643 {
644  std::vector<std::pair<TVector3, size_t>> ksel;
645  for (size_t t = 0; t < tracks.size(); ++t) {
646  pma::Track3D const* trk = tracks[t].Track();
647  for (size_t n = 1; n < trk->Nodes().size() - 1; ++n) {
648  pma::Node3D const* node = trk->Nodes()[n];
649  if (!node->IsBranching() && node->IsVertex()) {
650  ksel.emplace_back(std::pair<TVector3, size_t>(node->Point3D(), t));
651  }
652  }
653  }
654  return ksel;
655 }
656 // ------------------------------------------------------
pma::TrkCandidateColl fEmTracks
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TVector3 const & Point3D() const
Definition: PmaNode3D.h:44
size_t size() const
pma::TrkCandidateColl fShortTracks
size_t run(const detinfo::DetectorPropertiesData &detProp, pma::TrkCandidateColl &trk_input)
double Dist2(const TVector2 &v1, const TVector2 &v2)
Definition: Utilities.cxx:39
std::vector< pma::VtxCandidate > firstPassCandidates() const
std::vector< std::pair< TVector3, size_t > > getKinks(const pma::TrkCandidateColl &tracks) const
std::vector< pma::VtxCandidate > secondPassCandidates() const
Planes which measure V.
Definition: geo_types.h:136
pma::Hit3D const * front() const
Definition: PmaTrack3D.h:87
Implementation of the Projection Matching Algorithm.
void collectTracks(pma::TrkCandidateColl &result)
virtual unsigned int NextCount(void) const
Definition: SortedObjects.h:84
TVector3 const & Point3D() const
Definition: PmaHit3D.h:50
Planes which measure Z direction.
Definition: geo_types.h:138
fhicl::Atom< double > MinTrackLength
std::vector< std::pair< TVector3, std::vector< std::pair< size_t, bool > > > > getVertices(const pma::TrkCandidateColl &tracks, bool onlyBranching=false) const
double Mse() const
recob::tracking::Vector_t Vector3D
Definition: Utilities.h:34
PMAlgVertexing(const Config &config)
double Optimize(const detinfo::DetectorPropertiesData &detProp, int nNodes=-1, double eps=0.01, bool selAllHits=true, bool setAllNodes=true, size_t selSegHits=0, size_t selVtxHits=0)
Main optimization method.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
Planes which measure U.
Definition: geo_types.h:135
unsigned int NHits(unsigned int view) const
Definition: PmaTrack3D.cxx:421
fhicl::Atom< bool > FindKinks
std::vector< pma::Segment3D * > const & Segments() const noexcept
Definition: PmaTrack3D.h:269
std::vector< std::pair< double, double > > getdQdx(const pma::Track3D &trk) const
Get dQ/dx sequence to detect various features.
Float_t d
Definition: plot.C:235
pma::TrkCandidateColl fOutTracks
fhicl::Atom< double > KinkMinStd
bool IsVertex() const
Check fIsVertex flag.
Definition: PmaNode3D.h:65
pma::TrkCandidateColl fExcludedTracks
size_t makeVertices(detinfo::DetectorPropertiesData const &detProp, std::vector< pma::VtxCandidate > &candidates)
double mean(const std::vector< short > &wf, size_t start, size_t nsample)
Definition: UtilFunc.cxx:13
Implementation of the Projection Matching Algorithm.
double convolute(size_t idx, size_t len, double *adc, double const *shape) const
Get convolution value.
virtual pma::SortedObjectBase * Next(unsigned int index=0) const
Definition: SortedObjects.h:77
double GetRawdEdxSequence(std::map< size_t, std::vector< double >> &dedx, unsigned int view=geo::kZ, unsigned int skip=0, bool inclDisabled=false) const
bool Add(const pma::TrkCandidate &trk)
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
bool IsBranching() const
Belongs to more than one track?
Definition: PmaNode3D.cxx:418
void sortTracks(const pma::TrkCandidateColl &trk_input)
Char_t n[5]
TrackCollectionProxyElement< TrackCollProxy > Track
Proxy to an element of a proxy collection of recob::Track objects.
Definition: Track.h:992
bool isSingleParticle(pma::Track3D *trk1, pma::Track3D *trk2) const
Check if colinear in 3D and dQ/dx with no significant step.
std::vector< pma::Node3D * > const & Nodes() const noexcept
Definition: PmaTrack3D.h:274
void splitMergedTracks(pma::TrkCandidateColl &trk_input) const
Split track and add vertex and reoptimize when dQ/dx step detected.
virtual pma::SortedObjectBase * Prev(void) const
Definition: SortedObjects.h:42
fhicl::Atom< double > KinkMinDeg
Double_t sum
Definition: plot.C:31
Float_t e
Definition: plot.C:35
size_t size() const
Definition: PmaTrack3D.h:89
void findKinksOnTracks(const detinfo::DetectorPropertiesData &detProp, pma::TrkCandidateColl &trk_input) const
Remove penalty on the angle if kink detected and reopt track.
pma::Track3D * Parent(void) const
Definition: PmaSegment3D.h:66
void push_back(const TrkCandidate &trk)
bool has(const std::vector< size_t > &v, size_t idx) const
std::vector< TrkCandidate > const & tracks() const
void mergeBrokenTracks(pma::TrkCandidateColl &trk_input) const