All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TrackKalmanFitter.cxx
Go to the documentation of this file.
1 #include "TrackKalmanFitter.h"
2 
3 #include "canvas/Persistency/Common/Ptr.h"
4 #include "messagefacility/MessageLogger/MessageLogger.h"
5 
6 #include <algorithm>
7 #include <cassert>
8 #include <cmath>
9 #include <float.h>
10 #include <iostream>
11 #include <stddef.h>
12 #include <string>
13 
14 #include "Math/BinaryOperators.h"
15 #include "Math/Expression.h"
16 #include "Math/GenVector/Cartesian3D.h"
17 #include "Math/GenVector/DisplacementVector3D.h"
18 #include "Math/GenVector/PositionVector3D.h"
19 #include "Math/MatrixRepresentationsStatic.h"
20 #include "Math/SMatrix.h"
21 
35 
36 bool
38  const recob::TrackTrajectory& traj,
39  const int tkID,
40  const SMatrixSym55& covVtx,
41  const SMatrixSym55& covEnd,
42  const std::vector<art::Ptr<recob::Hit>>& hits,
43  const double pval,
44  const int pdgid,
45  const bool flipDirection,
46  recob::Track& outTrack,
47  std::vector<art::Ptr<recob::Hit>>& outHits,
48  trkmkr::OptionalOutputs& optionals) const
49 {
50  auto position = traj.Vertex();
51  auto direction = traj.VertexDirection();
52 
53  if (tryBothDirs_) {
54  recob::Track fwdTrack;
55  std::vector<art::Ptr<recob::Hit>> fwdHits;
56  trkmkr::OptionalOutputs fwdoptionals;
57  SMatrixSym55 fwdcov = covVtx;
58  bool okfwd = fitTrack(detProp,
59  position,
60  direction,
61  fwdcov,
62  hits,
63  traj.Flags(),
64  tkID,
65  pval,
66  pdgid,
67  fwdTrack,
68  fwdHits,
69  fwdoptionals);
70 
71  recob::Track bwdTrack;
72  std::vector<art::Ptr<recob::Hit>> bwdHits;
73  trkmkr::OptionalOutputs bwdoptionals;
74  SMatrixSym55 bwdcov = covEnd;
75  bool okbwd = fitTrack(detProp,
76  position,
77  -direction,
78  bwdcov,
79  hits,
80  traj.Flags(),
81  tkID,
82  pval,
83  pdgid,
84  bwdTrack,
85  bwdHits,
86  bwdoptionals);
87 
88  if (okfwd == false && okbwd == false) { return false; }
89  else if (okfwd == true && okbwd == true) {
90  if ((fwdTrack.CountValidPoints() / (fwdTrack.Length() * fwdTrack.Chi2PerNdof())) >=
91  (bwdTrack.CountValidPoints() / (bwdTrack.Length() * bwdTrack.Chi2PerNdof()))) {
92  outTrack = fwdTrack;
93  outHits = fwdHits;
94  optionals = std::move(fwdoptionals);
95  }
96  else {
97  outTrack = bwdTrack;
98  outHits = bwdHits;
99  optionals = std::move(bwdoptionals);
100  }
101  }
102  else if (okfwd == true) {
103  outTrack = fwdTrack;
104  outHits = fwdHits;
105  optionals = std::move(fwdoptionals);
106  }
107  else {
108  outTrack = bwdTrack;
109  outHits = bwdHits;
110  optionals = std::move(bwdoptionals);
111  }
112  return true;
113  }
114  else {
115  if (flipDirection) {
116  position = traj.End();
117  direction = -traj.EndDirection();
118  }
119 
120  auto trackStateCov = (flipDirection ? covEnd : covVtx);
121 
122  return fitTrack(detProp,
123  position,
124  direction,
125  trackStateCov,
126  hits,
127  traj.Flags(),
128  tkID,
129  pval,
130  pdgid,
131  outTrack,
132  outHits,
133  optionals);
134  }
135 }
136 
137 bool
139  const Point_t& position,
140  const Vector_t& direction,
141  SMatrixSym55& trackStateCov,
142  const std::vector<art::Ptr<recob::Hit>>& hits,
143  const std::vector<recob::TrajectoryPointFlags>& flags,
144  const int tkID,
145  const double pval,
146  const int pdgid,
147  recob::Track& outTrack,
148  std::vector<art::Ptr<recob::Hit>>& outHits,
149  trkmkr::OptionalOutputs& optionals) const
150 {
151  if (dumpLevel_ > 1)
152  std::cout << "Fitting track with tkID=" << tkID << " start pos=" << position
153  << " dir=" << direction << " nHits=" << hits.size() << " mom=" << pval
154  << " pdg=" << pdgid << std::endl;
155  if (hits.size() < 4) {
156  mf::LogWarning("TrackKalmanFitter") << "Fit failure at " << __FILE__ << " " << __LINE__;
157  return false;
158  }
159 
160  // setup the KFTrackState we'll use throughout the fit
161  KFTrackState trackState = setupInitialTrackState(position, direction, trackStateCov, pval, pdgid);
162 
163  // setup vector of HitStates and flags, with either same or inverse order as input hit vector
164  // this is what we'll loop over during the fit
165  std::vector<HitState> hitstatev;
166  std::vector<recob::TrajectoryPointFlags::Mask_t> hitflagsv;
167  bool inputok = setupInputStates(detProp, hits, flags, trackState, hitstatev, hitflagsv);
168  if (!inputok) return false;
169 
170  // track and index vectors we use to store the fit results
171  std::vector<KFTrackState> fwdPrdTkState;
172  std::vector<KFTrackState> fwdUpdTkState;
173  std::vector<unsigned int> hitstateidx;
174  std::vector<unsigned int> rejectedhsidx;
175  std::vector<unsigned int> sortedtksidx;
176 
177  // do the actual fit
178  bool fitok = doFitWork(trackState,
179  detProp,
180  hitstatev,
181  hitflagsv,
182  fwdPrdTkState,
183  fwdUpdTkState,
184  hitstateidx,
185  rejectedhsidx,
186  sortedtksidx);
187  if (!fitok && (skipNegProp_ || cleanZigzag_) && tryNoSkipWhenFails_) {
188  mf::LogWarning("TrackKalmanFitter")
189  << "Trying to recover with skipNegProp = false and cleanZigzag = false\n";
190  fitok = doFitWork(trackState,
191  detProp,
192  hitstatev,
193  hitflagsv,
194  fwdPrdTkState,
195  fwdUpdTkState,
196  hitstateidx,
197  rejectedhsidx,
198  sortedtksidx,
199  false);
200  }
201  if (!fitok) {
202  mf::LogWarning("TrackKalmanFitter") << "Fit failed for track with ID=" << tkID << "\n";
203  return false;
204  }
205 
206  // fill the track, the output hit vector, and the optional output products
207  bool fillok = fillResult(hits,
208  tkID,
209  pdgid,
210  hitstatev,
211  hitflagsv,
212  fwdPrdTkState,
213  fwdUpdTkState,
214  hitstateidx,
215  rejectedhsidx,
216  sortedtksidx,
217  outTrack,
218  outHits,
219  optionals);
220  return fillok;
221 }
222 
225  const Vector_t& direction,
226  SMatrixSym55& trackStateCov,
227  const double pval,
228  const int pdgid) const
229 {
230  //start from large enough covariance matrix so that the fit is not biased
231  if (trackStateCov == SMatrixSym55()) {
232  trackStateCov(0, 0) = 1000.;
233  trackStateCov(1, 1) = 1000.;
234  trackStateCov(2, 2) = 0.25;
235  trackStateCov(3, 3) = 0.25;
236  trackStateCov(4, 4) = 10.;
237  }
238  else
239  trackStateCov *= 100.;
240  // build vector of parameters on plane with point on the track and direction normal to the plane parallel to the track (so the first four parameters are zero by construction)
241  SVector5 trackStatePar(0., 0., 0., 0., 1. / pval);
242  return KFTrackState(trackStatePar,
243  trackStateCov,
244  Plane(position, direction),
245  true,
246  pdgid); //along direction by definition
247 }
248 
249 bool
252  const std::vector<art::Ptr<recob::Hit>>& hits,
253  const std::vector<recob::TrajectoryPointFlags>& flags,
254  const KFTrackState& trackState,
255  std::vector<HitState>& hitstatev,
256  std::vector<recob::TrajectoryPointFlags::Mask_t>& hitflagsv) const
257 {
258  if (dumpLevel_ > 1)
259  std::cout << "flags.size()=" << flags.size() << " hits.size()=" << hits.size() << std::endl;
260 
261  // setup vector of HitStates and flags, with either same or inverse order as input hit vector
262  // this is what we'll loop over during the fit
263  const size_t fsize = flags.size();
264  for (size_t ihit = 0; ihit != hits.size(); ihit++) {
265  const auto& hit = hits[ihit];
266  double t = hit->PeakTime();
267  double terr = (useRMS_ ? hit->RMS() : hit->SigmaPeakTime());
268  double x =
269  detProp.ConvertTicksToX(t, hit->WireID().Plane, hit->WireID().TPC, hit->WireID().Cryostat);
270  double xerr = terr * detProp.GetXTicksCoefficient();
271  hitstatev.emplace_back(
272  x, hitErr2ScaleFact_ * xerr * xerr, hit->WireID(), geom->WireIDToWireGeo(hit->WireID()));
273  //
274  if (fsize > 0 && ihit < fsize)
275  hitflagsv.push_back(flags[ihit].mask());
276  else
277  hitflagsv.push_back(recob::TrajectoryPointFlags::DefaultFlagsMask());
278  //
279  if (rejectHighMultHits_ && hit->Multiplicity() > 1) {
280  hitflagsv.back().set(recob::TrajectoryPointFlagTraits::Merged);
282  }
283  if (rejectHitsNegativeGOF_ && hit->GoodnessOfFit() < 0) {
284  hitflagsv.back().set(recob::TrajectoryPointFlagTraits::Suspicious);
286  }
287  //
288  if (dumpLevel_ > 2)
289  std::cout << "pushed flag mask=" << hitflagsv.back()
290  << " merged=" << hitflagsv.back().isSet(recob::TrajectoryPointFlagTraits::Merged)
291  << " suspicious="
292  << hitflagsv.back().isSet(recob::TrajectoryPointFlagTraits::Suspicious)
293  << " nopoint=" << hitflagsv.back().isSet(recob::TrajectoryPointFlagTraits::NoPoint)
294  << std::endl;
295  }
296  if (dumpLevel_ > 2) assert(hits.size() == hitstatev.size());
297  return true;
298 }
299 
300 bool
303  std::vector<HitState>& hitstatev,
304  std::vector<recob::TrajectoryPointFlags::Mask_t>& hitflagsv,
305  std::vector<KFTrackState>& fwdPrdTkState,
306  std::vector<KFTrackState>& fwdUpdTkState,
307  std::vector<unsigned int>& hitstateidx,
308  std::vector<unsigned int>& rejectedhsidx,
309  std::vector<unsigned int>& sortedtksidx,
310  bool applySkipClean) const
311 {
312  fwdPrdTkState.clear();
313  fwdUpdTkState.clear();
314  hitstateidx.clear();
315  rejectedhsidx.clear();
316  sortedtksidx.clear();
317  // these three vectors are aligned
318  fwdPrdTkState.reserve(hitstatev.size());
319  fwdUpdTkState.reserve(hitstatev.size());
320  hitstateidx.reserve(hitstatev.size());
321 
322  // keep a copy in case first propagation fails
323  KFTrackState startState = trackState;
324 
325  if (sortHitsByPlane_) {
326  //array of hit indices in planes, keeping the original sorting by plane
327  const unsigned int nplanes = geom->MaxPlanes();
328  std::vector<std::vector<unsigned int>> hitsInPlanes(nplanes);
329  for (unsigned int ihit = 0; ihit < hitstatev.size(); ihit++) {
330  hitsInPlanes[hitstatev[ihit].wireId().Plane].push_back(ihit);
331  }
332  if (sortHitsByWire_) {
333  for (unsigned int iplane = 0; iplane < nplanes; ++iplane) {
334  if (geom->Plane(iplane).GetIncreasingWireDirection<Vector_t>().Dot(trackState.momentum()) >
335  0) {
336  std::sort(hitsInPlanes[iplane].begin(),
337  hitsInPlanes[iplane].end(),
338  [hitstatev](const unsigned int& a, const unsigned int& b) -> bool {
339  return hitstatev[a].wireId().Wire < hitstatev[b].wireId().Wire;
340  });
341  }
342  else {
343  std::sort(hitsInPlanes[iplane].begin(),
344  hitsInPlanes[iplane].end(),
345  [hitstatev](const unsigned int& a, const unsigned int& b) -> bool {
346  return hitstatev[a].wireId().Wire > hitstatev[b].wireId().Wire;
347  });
348  }
349  }
350  }
351 
352  //dump hits sorted in each plane
353  if (dumpLevel_ > 1) {
354  int ch = 0;
355  for (auto p : hitsInPlanes) {
356  for (auto h : p) {
357  std::cout << "hit #/Plane/Wire/x/mask: " << ch++ << " " << hitstatev[h].wireId().Plane
358  << " " << hitstatev[h].wireId().Wire << " " << hitstatev[h].hitMeas() << " "
359  << hitflagsv[h] << std::endl;
360  }
361  }
362  }
363 
364  //array of indices, where iterHitsInPlanes[i] is the iterator over hitsInPlanes[i]
365  std::vector<unsigned int> iterHitsInPlanes(nplanes, 0);
366  for (unsigned int p = 0; p < hitstatev.size(); ++p) {
367  if (dumpLevel_ > 1) std::cout << std::endl << "processing hit #" << p << std::endl;
368  if (dumpLevel_ > 1)
369  std::cout << "hit sizes: rej=" << rejectedhsidx.size() << " good=" << hitstateidx.size()
370  << " input=" << hitstatev.size() << std::endl;
371  if (dumpLevel_ > 1) {
372  std::cout << "compute distance from state=" << std::endl;
373  trackState.dump();
374  }
375  int min_plane = -1;
376  double min_dist = DBL_MAX;
377  //find the closest hit according to the sorting in each plane
378  for (unsigned int iplane = 0; iplane < nplanes; ++iplane) {
379  //note: ih is a reference, so when 'continue' we increment iterHitsInPlanes[iplane] and the hit is effectively rejected
380  if (dumpLevel_ > 1)
381  std::cout << "iplane=" << iplane << " nplanes=" << nplanes
382  << " iterHitsInPlanes[iplane]=" << iterHitsInPlanes[iplane]
383  << " hitsInPlanes[iplane].size()=" << hitsInPlanes[iplane].size() << std::endl;
384  for (unsigned int& ih = iterHitsInPlanes[iplane]; ih < hitsInPlanes[iplane].size(); ++ih) {
385  //
386  unsigned int ihit = hitsInPlanes[iplane][ih];
387  if (dumpLevel_ > 1)
388  std::cout << "ih=" << ih << " ihit=" << ihit << " size=" << hitsInPlanes[iplane].size()
389  << std::endl;
390  const auto& hitstate = hitstatev[ihit];
391  const auto& hitflags = hitflagsv[ihit];
392  if (hitflags.isSet(recob::TrajectoryPointFlagTraits::NoPoint) ||
395  if (dumpLevel_ > 1)
396  std::cout << "rejecting hit flags="
397  << hitflags.isSet(recob::TrajectoryPointFlagTraits::NoPoint) << ", "
398  << hitflags.isSet(recob::TrajectoryPointFlagTraits::ExcludedFromFit) << ", "
399  << hitflags.isSet(recob::TrajectoryPointFlagTraits::Rejected) << " "
400  << hitflags << std::endl;
401  rejectedhsidx.push_back(ihit);
402  continue;
403  }
404  //get distance to measurement surface
405  bool success = true;
406  const double dist =
407  propagator->distanceToPlane(success, trackState.trackState(), hitstate.plane());
408  if (dumpLevel_ > 1)
409  std::cout << "distance to plane " << iplane << " wire=" << hitstate.wireId().Wire
410  << " = " << dist << ", min_dist=" << std::min(min_dist, 999.)
411  << " min_plane=" << min_plane << " success=" << success
412  << " wirepo=" << hitstate.plane().position() << std::endl;
413  if (!success) {
414  rejectedhsidx.push_back(ihit);
415  continue;
416  }
417  if (applySkipClean && skipNegProp_ && fwdUpdTkState.size() > 0 &&
418  dist < negDistTolerance_) {
419  rejectedhsidx.push_back(ihit);
420  continue;
421  }
422  if (dist < min_dist) {
423  min_plane = iplane;
424  min_dist = dist;
425  }
426  break;
427  }
428  }
429  if (dumpLevel_ > 1)
430  std::cout
431  << "pick min_dist=" << min_dist << " min_plane=" << min_plane << " wire="
432  << (min_plane < 0 ?
433  -1 :
434  hitstatev[hitsInPlanes[min_plane][iterHitsInPlanes[min_plane]]].wireId().Wire)
435  << std::endl;
436  //
437  //now we know which is the closest wire: get the hitstate and increment the iterator
438  if (min_plane < 0) {
439  if (rejectedhsidx.size() + hitstateidx.size() == hitstatev.size())
440  break;
441  else
442  continue;
443  }
444  unsigned int ihit = hitsInPlanes[min_plane][iterHitsInPlanes[min_plane]];
445  const auto* hitstate = &hitstatev[ihit];
446  iterHitsInPlanes[min_plane]++;
447  //
448  //propagate to measurement surface
449  bool propok = true;
450  trackState = propagator->propagateToPlane(propok,
451  detProp,
452  trackState.trackState(),
453  hitstate->plane(),
454  true,
455  true,
457  if (!propok && !(applySkipClean && fwdUpdTkState.size() > 0 && skipNegProp_)) {
458  if (dumpLevel_ > 1) std::cout << "attempt backward prop" << std::endl;
459  trackState = propagator->propagateToPlane(propok,
460  detProp,
461  trackState.trackState(),
462  hitstate->plane(),
463  true,
464  true,
466  }
467  if (dumpLevel_ > 1) {
468  std::cout << "hit state " << std::endl;
469  hitstate->dump();
470  std::cout << "propagation result=" << propok << std::endl;
471  std::cout << "propagated state " << std::endl;
472  trackState.dump();
473  std::cout << "propagated planarity="
474  << hitstate->plane().direction().Dot(hitstate->plane().position() -
475  trackState.position())
476  << std::endl;
477  std::cout << "residual=" << trackState.residual(*hitstate)
478  << " chi2=" << trackState.chi2(*hitstate) << std::endl;
479  }
480  if (propok) {
481 
482  //reject the first hit if its residue is too large (due to e.g. spurious hit or bad hit sorting)
483  if (applySkipClean && fwdUpdTkState.size() == 0 &&
484  std::abs(trackState.residual(*hitstate)) > maxResidueFirstHit_) {
485  if (dumpLevel_ > 1)
486  std::cout << "rejecting first hit with residual=" << trackState.residual(*hitstate)
487  << std::endl;
488  rejectedhsidx.push_back(ihit);
489  trackState = startState;
490  continue;
491  }
492 
493  //if there is >1 consecutive hit on the same wire, choose the one with best chi2 and exclude the others (should this be optional?)
494  if (pickBestHitOnWire_) {
495  auto wire = hitstate->wireId().Wire;
496  float min_chi2_wire = trackState.chi2(*hitstate);
497  for (unsigned int jh = iterHitsInPlanes[min_plane]; jh < hitsInPlanes[min_plane].size();
498  ++jh) {
499  const unsigned int jhit = hitsInPlanes[min_plane][jh];
500  const auto& jhitstate = hitstatev[jhit];
501  if (jhitstate.wireId().Wire != wire) break;
502  if (ihit != jhit) iterHitsInPlanes[min_plane]++;
503  float chi2 = trackState.chi2(jhitstate);
504  if (dumpLevel_ > 1 && ihit != jhit)
505  std::cout << "additional hit on the same wire with jhit=" << jhit << " chi2=" << chi2
506  << " ihit=" << ihit << " min_chi2_wire=" << min_chi2_wire << std::endl;
507  if (chi2 < min_chi2_wire) {
508  min_chi2_wire = chi2;
509  if (dumpLevel_ > 1 && ihit != jhit) {
510  std::cout << "\tnow using ";
511  jhitstate.dump();
512  }
513  if (ihit != jhit) rejectedhsidx.push_back(ihit);
514  ihit = jhit;
515  }
516  else {
517  rejectedhsidx.push_back(jhit);
518  }
519  }
520  }
521 
522  hitstate = &hitstatev[ihit];
523  auto& hitflags = hitflagsv[ihit];
524 
525  //reject hits failing maxResidue, maxChi2, or maxDist cuts
526  if (fwdUpdTkState.size() > 0 && applySkipClean &&
527  (std::abs(trackState.residual(*hitstate)) > maxResidue_ ||
528  trackState.chi2(*hitstate) > maxChi2_ || min_dist > maxDist_)) {
529  //
530  if (dumpLevel_ > 1)
531  std::cout << "rejecting hit with res=" << std::abs(trackState.residual(*hitstate))
532  << " chi2=" << trackState.chi2(*hitstate) << " dist=" << min_dist
533  << std::endl;
534  // reset the current state, do not update the hit, and mark as excluded from the fit
535  if (fwdUpdTkState.size() > 0)
536  trackState = fwdUpdTkState.back();
537  else
538  trackState = startState;
539  rejectedhsidx.push_back(ihit);
541  hitflags.set(
543  NoPoint); //fixme: this is only for event display, also needed by current definition of ValidPoint
544  continue;
545  }
546 
547  hitstateidx.push_back(ihit);
548  fwdPrdTkState.push_back(trackState);
549 
550  //hits with problematic flags are kept but not used for update and flagged as excluded from fit
551  if (hitflags.isSet(recob::TrajectoryPointFlagTraits::HitIgnored) ||
557  //
558  // reset the current state, do not update the hit, and mark as excluded from the fit
559  if (fwdUpdTkState.size() > 0)
560  trackState = fwdUpdTkState.back();
561  else
562  trackState = startState;
563  fwdUpdTkState.push_back(trackState);
565  hitflags.set(
567  NoPoint); //fixme: this is only for event display, also needed by current definition of ValidPoint
568  continue;
569  }
570  //now update the forward fitted track
571  bool upok = trackState.updateWithHitState(*hitstate);
572  if (upok == 0) {
573  mf::LogWarning("TrackKalmanFitter") << "Fit failure at " << __FILE__ << " " << __LINE__;
574  return false;
575  }
576  if (dumpLevel_ > 1) {
577  std::cout << "updated state " << std::endl;
578  trackState.dump();
579  }
580  fwdUpdTkState.push_back(trackState);
581  }
582  else {
583  if (dumpLevel_ > 0)
584  std::cout << "WARNING: forward propagation failed. Skip this hit..." << std::endl;
585  // restore the last successful propagation
586  if (fwdPrdTkState.size() > 0)
587  trackState = fwdPrdTkState.back();
588  else
589  trackState = startState;
590  rejectedhsidx.push_back(ihit);
591  continue;
592  }
593  if (rejectedhsidx.size() + hitstateidx.size() == hitstatev.size()) break;
594  }
595  }
596  else {
597  for (unsigned int ihit = 0; ihit < hitstatev.size(); ++ihit) {
598  const auto& hitstate = hitstatev[ihit];
599  if (dumpLevel_ > 1) {
600  std::cout << std::endl << "processing hit #" << ihit << std::endl;
601  hitstate.dump();
602  }
603  auto& hitflags = hitflagsv[ihit];
606  rejectedhsidx.push_back(ihit);
607  continue;
608  }
609  bool success = true;
610  const double dist =
611  propagator->distanceToPlane(success, trackState.trackState(), hitstate.plane());
612  if (applySkipClean && fwdUpdTkState.size() > 0 && skipNegProp_) {
613  if (dist < 0. || success == false) {
614  if (dumpLevel_ > 0)
615  std::cout << "WARNING: negative propagation distance. Skip this hit..." << std::endl;
616  ;
617  rejectedhsidx.push_back(ihit);
618  continue;
619  }
620  }
621  //propagate to measurement surface
622  bool propok = true;
623  trackState = propagator->propagateToPlane(propok,
624  detProp,
625  trackState.trackState(),
626  hitstate.plane(),
627  true,
628  true,
630  if (!propok && !(applySkipClean && skipNegProp_))
631  trackState = propagator->propagateToPlane(propok,
632  detProp,
633  trackState.trackState(),
634  hitstate.plane(),
635  true,
636  true,
638  if (propok) {
639  hitstateidx.push_back(ihit);
640  fwdPrdTkState.push_back(trackState);
641  //
642  if (hitflags.isSet(recob::TrajectoryPointFlagTraits::HitIgnored) ||
648  (fwdUpdTkState.size() > 0 && applySkipClean &&
649  (std::abs(trackState.residual(hitstate)) > maxResidue_ ||
650  trackState.chi2(hitstate) > maxChi2_ || dist > maxDist_))) {
651  if (dumpLevel_ > 1)
652  std::cout << "rejecting hit with res=" << std::abs(trackState.residual(hitstate))
653  << " chi2=" << trackState.chi2(hitstate) << " dist=" << dist << std::endl;
654  // reset the current state, do not update the hit, mark as excluded from the fit
655  if (fwdUpdTkState.size() > 0)
656  trackState = fwdUpdTkState.back();
657  else
658  trackState = startState;
659  fwdUpdTkState.push_back(trackState);
661  hitflags.set(
663  NoPoint); //fixme: this is only for event display, also needed by current definition of ValidPoint
664  continue;
665  }
666  //
667  bool upok = trackState.updateWithHitState(hitstate);
668  if (upok == 0) {
669  mf::LogWarning("TrackKalmanFitter") << "Fit failure at " << __FILE__ << " " << __LINE__;
670  return false;
671  }
672  fwdUpdTkState.push_back(trackState);
673  }
674  else {
675  if (dumpLevel_ > 0)
676  std::cout << "WARNING: forward propagation failed. Skip this hit..." << std::endl;
677  ;
678  // restore the last successful propagation
679  if (fwdPrdTkState.size() > 0)
680  trackState = fwdPrdTkState.back();
681  else
682  trackState = startState;
683  rejectedhsidx.push_back(ihit);
684  continue;
685  }
686  } //for (auto hitstate : hitstatev)
687  }
688 
689  if (dumpLevel_ > 2) assert(rejectedhsidx.size() + hitstateidx.size() == hitstatev.size());
690  if (dumpLevel_ > 0) {
691  std::cout << "TRACK AFTER FWD" << std::endl;
692  std::cout << "hit sizes=" << rejectedhsidx.size() << " " << hitstateidx.size() << " "
693  << hitstatev.size() << std::endl;
694  trackState.dump();
695  }
696 
697  //reinitialize trf for backward fit, scale the error to avoid biasing the backward fit
698  trackState.setCovariance(100. * trackState.covariance());
699 
700  startState = trackState;
701 
702  //backward loop over track states and hits in fwdUpdTracks: use hits for backward fit and fwd track states for smoothing
703  int nvalidhits = 0;
704  for (int itk = fwdPrdTkState.size() - 1; itk >= 0; itk--) {
705  auto& fwdPrdTrackState = fwdPrdTkState[itk];
706  auto& fwdUpdTrackState = fwdUpdTkState[itk];
707  const auto& hitstate = hitstatev[hitstateidx[itk]];
708  auto& hitflags = hitflagsv[hitstateidx[itk]];
709  if (dumpLevel_ > 1) {
710  std::cout << std::endl << "processing backward hit #" << itk << std::endl;
711  hitstate.dump();
712  }
713  bool propok = true;
714  trackState = propagator->propagateToPlane(propok,
715  detProp,
716  trackState.trackState(),
717  hitstate.plane(),
718  true,
719  true,
721  if (!propok)
722  trackState = propagator->propagateToPlane(propok,
723  detProp,
724  trackState.trackState(),
725  hitstate.plane(),
726  true,
727  true,
728  TrackStatePropagator::FORWARD); //do we want this?
729  //
730  if (dumpLevel_ > 1) {
731  std::cout << "propagation result=" << propok << std::endl;
732  std::cout << "propagated state " << std::endl;
733  trackState.dump();
734  std::cout << "propagated planarity="
735  << hitstate.plane().direction().Dot(hitstate.plane().position() -
736  trackState.position())
737  << std::endl;
738  }
739  if (propok) {
740  //combine forward predicted and backward predicted
741  bool pcombok = fwdPrdTrackState.combineWithTrackState(trackState.trackState());
742  if (pcombok == 0) {
743  mf::LogWarning("TrackKalmanFitter") << "Fit failure at " << __FILE__ << " " << __LINE__;
744  return false;
745  }
746  if (dumpLevel_ > 1) {
747  std::cout << "combined prd state " << std::endl;
748  fwdPrdTrackState.dump();
749  }
750  // combine forward updated and backward predicted and update backward predicted, only if the hit was not excluded
751  if (hitflags.isSet(recob::TrajectoryPointFlagTraits::ExcludedFromFit) == 0) {
752  bool ucombok = fwdUpdTrackState.combineWithTrackState(trackState.trackState());
753  if (ucombok == 0) {
754  mf::LogWarning("TrackKalmanFitter") << "Fit failure at " << __FILE__ << " " << __LINE__;
755  return false;
756  }
757  if (dumpLevel_ > 1) {
758  std::cout << "combined upd state " << std::endl;
759  fwdUpdTrackState.dump();
760  }
761  bool upok = trackState.updateWithHitState(hitstate);
762  if (upok == 0) {
763  mf::LogWarning("TrackKalmanFitter") << "Fit failure at " << __FILE__ << " " << __LINE__;
764  return false;
765  }
766  if (dumpLevel_ > 1) {
767  std::cout << "updated state " << std::endl;
768  trackState.dump();
769  }
770  // Keep a copy in case a future propagation fails
771  startState = trackState;
772  //
773  nvalidhits++;
774  }
775  else {
776  fwdUpdTrackState = fwdPrdTrackState;
777  }
778  }
779  else {
780  // ok, if the backward propagation failed we exclude this point from the rest of the fit,
781  // but we can still use its position from the forward fit, so just mark it as ExcludedFromFit
783  hitflags.set(
784  recob::TrajectoryPointFlagTraits::NoPoint); // fixme: this is only for event display, also
785  // needed by current definition of ValidPoint
786  if (dumpLevel_ > 0)
787  std::cout << "WARNING: backward propagation failed. Skip this hit... hitstateidx[itk]="
788  << hitstateidx[itk] << " itk=" << itk << std::endl;
789  ;
790  // restore the last successful propagation
791  trackState = startState;
792  continue;
793  }
794  } //for (unsigned int itk = fwdPrdTkState.size()-1; itk>=0; itk--) {
795 
796  if (nvalidhits < 4) {
797  mf::LogWarning("TrackKalmanFitter") << "Fit failure at " << __FILE__ << " " << __LINE__ << " ";
798  return false;
799  }
800 
801  if (dumpLevel_ > 1) std::cout << "sort output with nvalidhits=" << nvalidhits << std::endl;
802 
803  // sort output states
804  sortOutput(
805  hitstatev, fwdUpdTkState, hitstateidx, rejectedhsidx, sortedtksidx, hitflagsv, applySkipClean);
806  size_t nsortvalid = 0;
807  for (auto& idx : sortedtksidx) {
808  auto& hitflags = hitflagsv[hitstateidx[idx]];
809  if (hitflags.isSet(recob::TrajectoryPointFlagTraits::ExcludedFromFit) == 0) nsortvalid++;
810  }
811  if (nsortvalid < 4) {
812  mf::LogWarning("TrackKalmanFitter") << "Fit failure at " << __FILE__ << " " << __LINE__ << " ";
813  return false;
814  }
815 
816  if (dumpLevel_ > 2) assert(rejectedhsidx.size() + sortedtksidx.size() == hitstatev.size());
817  return true;
818 }
819 
820 void
821 trkf::TrackKalmanFitter::sortOutput(std::vector<HitState>& hitstatev,
822  std::vector<KFTrackState>& fwdUpdTkState,
823  std::vector<unsigned int>& hitstateidx,
824  std::vector<unsigned int>& rejectedhsidx,
825  std::vector<unsigned int>& sortedtksidx,
826  std::vector<recob::TrajectoryPointFlags::Mask_t>& hitflagsv,
827  bool applySkipClean) const
828 {
829  //
830  if (sortOutputHitsMinLength_) {
831  //sort hits keeping fixed the order on planes and picking the closest next plane
832  const unsigned int nplanes = geom->MaxPlanes();
833  std::vector<std::vector<unsigned int>> tracksInPlanes(nplanes);
834  for (unsigned int p = 0; p < hitstateidx.size(); ++p) {
835  const auto& hitstate = hitstatev[hitstateidx[p]];
836  tracksInPlanes[hitstate.wireId().Plane].push_back(p);
837  }
838  if (dumpLevel_ > 2) {
839  for (auto s : fwdUpdTkState) {
840  std::cout << "state pos=" << s.position() << std::endl;
841  }
842  }
843  //find good starting point
844  std::vector<unsigned int> iterTracksInPlanes;
845  for (auto it : tracksInPlanes)
846  iterTracksInPlanes.push_back(0);
847  auto pos = fwdUpdTkState.front().position();
848  auto dir = fwdUpdTkState.front().momentum();
849  unsigned int p = 0;
850  for (; p < fwdUpdTkState.size(); ++p) {
851  if (hitflagsv[hitstateidx[p]].isSet(recob::TrajectoryPointFlagTraits::ExcludedFromFit) == 0) {
852  pos = fwdUpdTkState[p].position();
853  dir = fwdUpdTkState[p].momentum();
854  if (dumpLevel_ > 2)
855  std::cout << "sort output found point not excluded with p=" << p
856  << " hitstateidx[p]=" << hitstateidx[p] << " pos=" << pos << std::endl;
857  break;
858  }
859  else {
860  rejectedhsidx.push_back(hitstateidx[p]);
861  }
862  }
863  if (dumpLevel_ > 1)
864  std::cout << "sort output init with pos=" << pos << " dir=" << dir << std::endl;
865  //pick hits based on minimum dot product with respect to position and direction at previous hit
866  for (; p < fwdUpdTkState.size(); ++p) {
867  int min_plane = -1;
868  double min_dotp = DBL_MAX;
869  for (unsigned int iplane = 0; iplane < iterTracksInPlanes.size(); ++iplane) {
870  for (unsigned int& itk = iterTracksInPlanes[iplane]; itk < tracksInPlanes[iplane].size();
871  ++itk) {
872  auto& trackstate = fwdUpdTkState[tracksInPlanes[iplane][iterTracksInPlanes[iplane]]];
873  auto& tmppos = trackstate.position();
874  const double dotp = dir.Dot(tmppos - pos);
875  if (dumpLevel_ > 2)
876  std::cout << "iplane=" << iplane << " tmppos=" << tmppos << " tmpdir=" << tmppos - pos
877  << " dotp=" << dotp << std::endl;
878  if (dotp < min_dotp) {
879  min_plane = iplane;
880  min_dotp = dotp;
881  }
882  break;
883  }
884  }
885  if (min_plane < 0) continue;
886  const unsigned int ihit = tracksInPlanes[min_plane][iterTracksInPlanes[min_plane]];
887  if (applySkipClean && skipNegProp_ && min_dotp < negDistTolerance_ &&
888  sortedtksidx.size() > 0) {
889  if (dumpLevel_ > 2)
890  std::cout << "sort output rejecting hit #" << ihit << " plane=" << min_plane
891  << " with min_dotp=" << min_dotp << std::endl;
892  rejectedhsidx.push_back(hitstateidx[ihit]);
893  iterTracksInPlanes[min_plane]++;
894  continue;
895  }
896  if (dumpLevel_ > 2)
897  std::cout << "sort output picking hit #" << ihit << " plane=" << min_plane
898  << " with min_dotp=" << min_dotp << std::endl;
899  auto& trackstate = fwdUpdTkState[ihit];
900  pos = trackstate.position();
901  dir = trackstate.momentum();
902  //
903  sortedtksidx.push_back(ihit);
904  iterTracksInPlanes[min_plane]++;
905  }
906  }
907  else {
908  for (unsigned int p = 0; p < fwdUpdTkState.size(); ++p) {
909  sortedtksidx.push_back(p);
910  }
911  }
912  //
913  if (applySkipClean && cleanZigzag_) {
914  std::vector<unsigned int> itoerase;
915  bool clean = false;
916  while (!clean) {
917  bool broken = false;
918  auto pos0 = fwdUpdTkState[sortedtksidx[0]].position();
919  unsigned int i = 1;
920  unsigned int end = sortedtksidx.size() - 1;
921  for (; i < end; ++i) {
922  auto dir0 = fwdUpdTkState[sortedtksidx[i]].position() - pos0;
923  auto dir2 =
924  fwdUpdTkState[sortedtksidx[i + 1]].position() - fwdUpdTkState[sortedtksidx[i]].position();
925  dir0 /= dir0.R();
926  dir2 /= dir2.R();
927  if (dir2.Dot(dir0) < 0.) {
928  broken = true;
929  end--;
930  break;
931  }
932  else
933  pos0 = fwdUpdTkState[sortedtksidx[i]].position();
934  }
935  if (!broken) { clean = true; }
936  else {
937  rejectedhsidx.push_back(hitstateidx[sortedtksidx[i]]);
938  sortedtksidx.erase(sortedtksidx.begin() + i);
939  }
940  }
941  }
942  //
943 }
944 
945 bool
946 trkf::TrackKalmanFitter::fillResult(const std::vector<art::Ptr<recob::Hit>>& inHits,
947  const int tkID,
948  const int pdgid,
949  std::vector<HitState>& hitstatev,
950  std::vector<recob::TrajectoryPointFlags::Mask_t>& hitflagsv,
951  std::vector<KFTrackState>& fwdPrdTkState,
952  std::vector<KFTrackState>& fwdUpdTkState,
953  std::vector<unsigned int>& hitstateidx,
954  std::vector<unsigned int>& rejectedhsidx,
955  std::vector<unsigned int>& sortedtksidx,
956  recob::Track& outTrack,
957  std::vector<art::Ptr<recob::Hit>>& outHits,
958  trkmkr::OptionalOutputs& optionals) const
959 {
960  // fill output trajectory objects with smoothed track and its hits
961  int nvalidhits = 0;
962  trkmkr::TrackCreationBookKeeper tcbk(outHits, optionals, tkID, pdgid, true);
963  for (unsigned int p : sortedtksidx) {
964  const auto& trackstate = fwdUpdTkState[p];
965  const auto& hitflags = hitflagsv[hitstateidx[p]];
966  const unsigned int originalPos = hitstateidx[p];
967  if (dumpLevel_ > 2) assert(originalPos >= 0 && originalPos < hitstatev.size());
968  //
969  const auto& prdtrack = fwdPrdTkState[p];
970  const auto& hitstate = hitstatev[hitstateidx[p]];
971  if (dumpLevel_ > 2) assert(hitstate.wireId().Plane == inHits[originalPos]->WireID().Plane);
972  //
973  float chi2 =
975  prdtrack.chi2(hitstate));
976  if (hitflags.isSet(recob::TrajectoryPointFlagTraits::NoPoint) == false) nvalidhits++;
977  //
979  if (optionals.isTrackFitInfosInit()) {
980  ope.setTrackFitHitInfo(recob::TrackFitHitInfo(hitstate.hitMeas(),
981  hitstate.hitMeasErr2(),
982  prdtrack.parameters(),
983  prdtrack.covariance(),
984  hitstate.wireId()));
985  }
986  tcbk.addPoint(trackstate.position(),
987  trackstate.momentum(),
988  inHits[originalPos],
989  recob::TrajectoryPointFlags(originalPos, hitflags),
990  chi2,
991  ope);
992  }
993  if (dumpLevel_ > 0) std::cout << "fillResult nvalidhits=" << nvalidhits << std::endl;
994 
995  // fill also with rejected hits information
996  SMatrixSym55 fakeCov55;
997  for (int i = 0; i < 5; i++)
998  for (int j = i; j < 5; j++)
999  fakeCov55(i, j) = util::kBogusD;
1000  for (unsigned int rejidx = 0; rejidx < rejectedhsidx.size(); ++rejidx) {
1001  const unsigned int originalPos = rejectedhsidx[rejidx];
1002  auto& mask = hitflagsv[rejectedhsidx[rejidx]];
1007  //
1008  const auto& hitstate = hitstatev[rejectedhsidx[rejidx]];
1009  if (dumpLevel_ > 2) assert(hitstate.wireId().Plane == inHits[originalPos]->WireID().Plane);
1011  if (optionals.isTrackFitInfosInit()) {
1013  hitstate.hitMeas(),
1014  hitstate.hitMeasErr2(),
1016  fakeCov55,
1017  hitstate.wireId()));
1018  }
1021  inHits[originalPos],
1022  recob::TrajectoryPointFlags(originalPos, mask),
1023  -1.,
1024  ope);
1025  }
1026 
1027  if (dumpLevel_ > 0)
1028  std::cout << "outHits.size()=" << outHits.size() << " inHits.size()=" << inHits.size()
1029  << std::endl;
1030  if (dumpLevel_ > 2) assert(outHits.size() == inHits.size());
1031 
1032  bool propok = true;
1033  KFTrackState resultF =
1034  propagator->rotateToPlane(propok,
1035  fwdUpdTkState[sortedtksidx.front()].trackState(),
1036  Plane(fwdUpdTkState[sortedtksidx.front()].position(),
1037  fwdUpdTkState[sortedtksidx.front()].momentum()));
1038  KFTrackState resultB =
1039  propagator->rotateToPlane(propok,
1040  fwdUpdTkState[sortedtksidx.back()].trackState(),
1041  Plane(fwdUpdTkState[sortedtksidx.back()].position(),
1042  fwdUpdTkState[sortedtksidx.back()].momentum()));
1043 
1044  outTrack =
1045  tcbk.finalizeTrack(SMatrixSym55(resultF.covariance()), SMatrixSym55(resultB.covariance()));
1046 
1047  //if there are points with zero momentum return false
1048  size_t point = 0;
1049  while (outTrack.HasValidPoint(point)) {
1050  if (outTrack.MomentumAtPoint(outTrack.NextValidPoint(point++)) <= 1.0e-9) {
1051  mf::LogWarning("TrackKalmanFitter") << "found point with zero momentum!" << std::endl;
1052  return false;
1053  }
1054  }
1055 
1056  if (dumpLevel_ > 0) {
1057  std::cout << "outTrack vertex=" << outTrack.Start() << "\ndir=" << outTrack.StartDirection()
1058  << "\ncov=\n"
1059  << outTrack.StartCovariance() << "\nlength=" << outTrack.Length()
1060  << "\nchi2/ndof=" << outTrack.Chi2PerNdof() << std::endl;
1061  }
1062 
1063  return true;
1064 }
static constexpr Flag_t Merged
The hit might have contribution from particles other than this.
void addPoint(const Point_t &point, const Vector_t &vect, art::Ptr< recob::Hit > hit, const PointFlags_t &flag, double chi2)
Add a single point; different version of the functions are provided using const references or rvalue ...
const TrackState & trackState() const
Get the (const reference to the) TrackState.
Definition: KFTrackState.h:36
static constexpr Flag_t Suspicious
The point reconstruction is somehow questionable.
Flags_t const & Flags() const
Returns all flags.
process_name opflash particleana ie x
static constexpr Flag_t NoPoint
The trajectory point is not defined.
bool doFitWork(KFTrackState &trackState, detinfo::DetectorPropertiesData const &detProp, std::vector< HitState > &hitstatev, std::vector< recob::TrajectoryPointFlags::Mask_t > &hitflagsv, std::vector< KFTrackState > &fwdPrdTkState, std::vector< KFTrackState > &fwdUpdTkState, std::vector< unsigned int > &hitstateidx, std::vector< unsigned int > &rejectedhsidx, std::vector< unsigned int > &sortedtksidx, bool applySkipClean=true) const
Function where the core of the fit is performed.
double GetXTicksCoefficient(int t, int c) const
recob::tracking::Point_t Point_t
Definition: TrackState.h:18
recob::tracking::Vector_t Vector_t
Definition: TrackState.h:19
static constexpr Mask_t DefaultFlagsMask()
Flags used in default construction.
Declaration of signal hit object.
Class holding flags.
pdgs p
Definition: selectors.fcl:22
recob::tracking::SMatrixSym55 SMatrixSym55
Definition: TrackState.h:15
bool HasValidPoint(size_t i) const
Namespace for the trajectory point flags.
bool fitTrack(detinfo::DetectorPropertiesData const &detProp, const recob::TrackTrajectory &traj, int tkID, const SMatrixSym55 &covVtx, const SMatrixSym55 &covEnd, const std::vector< art::Ptr< recob::Hit >> &hits, const double pval, const int pdgid, const bool flipDirection, recob::Track &outTrack, std::vector< art::Ptr< recob::Hit >> &outHits, trkmkr::OptionalOutputs &optionals) const
Fit track starting from TrackTrajectory.
bool setupInputStates(detinfo::DetectorPropertiesData const &detProp, const std::vector< art::Ptr< recob::Hit >> &hits, const std::vector< recob::TrajectoryPointFlags > &flags, const KFTrackState &trackState, std::vector< HitState > &hitstatev, std::vector< recob::TrajectoryPointFlags::Mask_t > &hitflagsv) const
Setup vectors of HitState and Masks to be used during the fit.
process_name hit
Definition: cheaterreco.fcl:51
double chi2(const HitState &hitstate) const
Definition: KFTrackState.h:55
double MomentumAtPoint(unsigned int p) const
void setCovariance(const SMatrixSym55 &trackStateCov)
Definition: KFTrackState.h:57
void sortOutput(std::vector< HitState > &hitstatev, std::vector< KFTrackState > &fwdUpdTkState, std::vector< unsigned int > &hitstateidx, std::vector< unsigned int > &rejectedhsidx, std::vector< unsigned int > &sortedtksidx, std::vector< recob::TrajectoryPointFlags::Mask_t > &hitflagsv, bool applySkipClean=true) const
Sort the output states.
const Point_t & position() const
Definition: KFTrackState.h:45
process_name gaushit a
while getopts h
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
Vector_t VertexDirection() const
Returns the direction of the trajectory at the first point.
T abs(T value)
Extension of a TrackState to perform KalmanFilter calculations.
Definition: KFTrackState.h:21
Vector_t StartDirection() const
Access to track direction at different points.
double Length(size_t p=0) const
Access to various track properties.
double residual(const HitState &hitstate) const
Definition: KFTrackState.h:52
recob::tracking::SVector5 SVector5
Definition: TrackState.h:12
constexpr mask_t< EnumType > mask(EnumType bit, OtherBits...otherBits)
Returns a mask with all specified bits set.
Point_t const & Start() const
Access to track position at different points.
const SMatrixSym55 & covariance() const
Definition: KFTrackState.h:43
bool fillResult(const std::vector< art::Ptr< recob::Hit >> &inHits, const int tkID, const int pdgid, std::vector< HitState > &hitstatev, std::vector< recob::TrajectoryPointFlags::Mask_t > &hitflagsv, std::vector< KFTrackState > &fwdPrdTkState, std::vector< KFTrackState > &fwdUpdTkState, std::vector< unsigned int > &hitstateidx, std::vector< unsigned int > &rejectedhsidx, std::vector< unsigned int > &sortedtksidx, recob::Track &outTrack, std::vector< art::Ptr< recob::Hit >> &outHits, trkmkr::OptionalOutputs &optionals) const
Fill the output objects.
A trajectory in space reconstructed from hits.
Object storing per-hit information from a track fit.
Struct holding point-by-point elements used in OptionalOutputs.
Definition: TrackMaker.h:47
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
bool updateWithHitState(const HitState &hitstate)
Update the TrackState given a HitState (they need to be on the same plane)
Definition: KFTrackState.cxx:5
Data product for reconstructed trajectory in space.
static constexpr Flag_t HitIgnored
Hit was not included for the computation of the trajectory.
Definition of data types for geometry description.
Provides recob::Track data product.
Point_t const & Vertex() const
Returns the position of the first valid point of the trajectory [cm].
static constexpr Flag_t Rejected
The hit is extraneous to this track.
tuple dir
Definition: dropbox.py:28
static constexpr Flag_t ExcludedFromFit
double ConvertTicksToX(double ticks, int p, int t, int c) const
auto begin(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:573
Vector_t EndDirection() const
Returns the direction of the trajectory at the last point.
KFTrackState setupInitialTrackState(const Point_t &position, const Vector_t &direction, SMatrixSym55 &trackStateCov, const double pval, const int pdgid) const
Return track state from intial position, direction, and covariance.
size_t NextValidPoint(size_t index) const
Encapsulate the construction of a single detector plane.
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
then echo File list $list not found else cat $list while read file do echo $file sed s
Definition: file_to_url.sh:60
Point_t const & End() const
Returns the position of the last valid point of the trajectory [cm].
Helper class to aid the creation of a recob::Track, keeping data vectors in sync. ...
do i e
static constexpr Flag_t DetectorIssue
The hit is associated to a problematic channel.
bool isTrackFitInfosInit()
check initialization of the output vector of TrackFitHitInfos
Definition: TrackMaker.h:173
recob::Track finalizeTrack(const recob::tracking::SMatrixSym55 &covStart, const recob::tracking::SMatrixSym55 &covEnd)
Get the finalized recob::Track; needs the start and end covariance matrices.
static constexpr Flag_t DeltaRay
The hit might have contribution from a δ ray.
constexpr double kBogusD
obviously bogus double value
const Vector_t & momentum() const
Definition: KFTrackState.h:46
std::ostream & dump(std::ostream &out=std::cout) const
Printout information.
Definition: KFTrackState.h:62
void setTrackFitHitInfo(recob::TrackFitHitInfo &&aTrackFitHitInfo)
set the recob::TrackFitHitInfo unique_ptr
Definition: TrackMaker.h:51
Collection of Physical constants used in LArSoft.
const Plane & plane() const
plane where the parameters are defined
Definition: TrackState.h:94
recob::tracking::Plane Plane
Definition: TrackState.h:17
static constexpr Flag_t Shared
The hit is known to be associated also to another trajectory.
Struct holding optional TrackMaker outputs.
Definition: TrackMaker.h:125
Set of flags pertaining a point of the track.
BEGIN_PROLOG could also be cout
auto const detProp
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a &quot;fitted&quot; track:
const SMatrixSym55 & StartCovariance() const
Access to covariance matrices.