LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
TrackKalmanFitter.cxx
Go to the documentation of this file.
1 #include "TrackKalmanFitter.h"
2 
6 
8 
9 bool trkf::TrackKalmanFitter::fitTrack(const recob::TrackTrajectory& traj, const int tkID, const SMatrixSym55& covVtx, const SMatrixSym55& covEnd,
10  const std::vector<art::Ptr<recob::Hit> >& hits, const double pval, const int pdgid, const bool flipDirection,
11  recob::Track& outTrack, std::vector<art::Ptr<recob::Hit> >& outHits, trkmkr::OptionalOutputs& optionals) const {
12  auto position = traj.Vertex();
13  auto direction = traj.VertexDirection();
14 
15  if (flipDirection) {
16  position = traj.End();
17  direction = -traj.EndDirection();
18  }
19 
20  auto trackStateCov = (flipDirection ? covEnd : covVtx );
21 
22  return fitTrack(position, direction, trackStateCov, hits, traj.Flags(), tkID, pval, pdgid, outTrack, outHits, optionals);
23 }
24 
25 bool trkf::TrackKalmanFitter::fitTrack(const Point_t& position, const Vector_t& direction, SMatrixSym55& trackStateCov,
26  const std::vector<art::Ptr<recob::Hit> >& hits, const std::vector<recob::TrajectoryPointFlags>& flags,
27  const int tkID, const double pval, const int pdgid,
28  recob::Track& outTrack, std::vector<art::Ptr<recob::Hit> >& outHits, trkmkr::OptionalOutputs& optionals) const {
29  if (hits.size()<4) {
30  mf::LogWarning("TrackKalmanFitter") << "Fit failure at " << __FILE__ << " " << __LINE__;
31  return false;
32  }
33 
34  // setup the KFTrackState we'll use throughout the fit
35  KFTrackState trackState = setupInitialTrackState(position, direction, trackStateCov, pval, pdgid);
36 
37  // setup vector of HitStates and flags, with either same or inverse order as input hit vector
38  // this is what we'll loop over during the fit
39  bool reverseHits = false;
40  std::vector<HitState> hitstatev;
41  std::vector<recob::TrajectoryPointFlags::Mask_t> hitflagsv;
42  bool inputok = setupInputStates(hits, flags, trackState, reverseHits, hitstatev, hitflagsv);
43  if (!inputok) return false;
44 
45  // track and index vectors we use to store the fit results
46  std::vector<KFTrackState> fwdPrdTkState;
47  std::vector<KFTrackState> fwdUpdTkState;
48  std::vector<unsigned int> hitstateidx;
49  std::vector<unsigned int> rejectedhsidx;
50  std::vector<unsigned int> sortedtksidx;
51 
52  // do the actual fit
53  bool fitok = doFitWork(trackState, hitstatev, hitflagsv, fwdPrdTkState, fwdUpdTkState, hitstateidx, rejectedhsidx, sortedtksidx);
54  if (!fitok && (skipNegProp_ || cleanZigzag_) && tryNoSkipWhenFails_) {
55  mf::LogWarning("TrackKalmanFitter") << "Trying to recover with skipNegProp = false and cleanZigzag = false\n";
56  fitok = doFitWork(trackState, hitstatev, hitflagsv, fwdPrdTkState, fwdUpdTkState, hitstateidx, rejectedhsidx, sortedtksidx, false);
57  }
58  if (!fitok) {
59  mf::LogWarning("TrackKalmanFitter") << "Fit failed for track with ID=" << tkID << "\n";
60  return false;
61  }
62 
63  // fill the track, the output hit vector, and the optional output products
64  bool fillok = fillResult(hits, tkID, pdgid, reverseHits, hitstatev, hitflagsv, fwdPrdTkState, fwdUpdTkState, hitstateidx, rejectedhsidx, sortedtksidx, outTrack, outHits, optionals);
65  return fillok;
66 }
67 
69  const double pval, const int pdgid) const {
70  //start from large enough covariance matrix so that the fit is not biased
71  if (trackStateCov==SMatrixSym55()) {
72  trackStateCov(0, 0) = 1000.;
73  trackStateCov(1, 1) = 1000.;
74  trackStateCov(2, 2) = 0.25;
75  trackStateCov(3, 3) = 0.25;
76  trackStateCov(4, 4) = 10.;
77  } else trackStateCov*=100.;
78  // 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)
79  SVector5 trackStatePar(0.,0.,0.,0.,1./pval);
80  return KFTrackState(trackStatePar, trackStateCov, Plane(position,direction), true, pdgid);//along direction by definition
81 }
82 
83 bool trkf::TrackKalmanFitter::setupInputStates(const std::vector<art::Ptr<recob::Hit> >& hits, const std::vector<recob::TrajectoryPointFlags>& flags,
84  const KFTrackState& trackState, bool& reverseHits,
85  std::vector<HitState>& hitstatev, std::vector<recob::TrajectoryPointFlags::Mask_t>& hitflagsv) const {
86  // figure out hit sorting based on minimum distance to first or last hit
87  // (to be removed once there is a clear convention for hit sorting)
88  geo::WireGeo const& wgeomF = geom->WireIDToWireGeo(hits.front()->WireID());
89  geo::WireGeo const& wgeomB = geom->WireIDToWireGeo(hits.back()->WireID());
90  Plane pF = recob::tracking::makePlane(wgeomF);
91  Plane pB = recob::tracking::makePlane(wgeomB);
92  bool success = true;
93  double distF = propagator->distanceToPlane(success, trackState.trackState(), pF);
94  double distB = propagator->distanceToPlane(success, trackState.trackState(), pB);
95  if (dumpLevel_>1) std::cout << "distF=" << distF << " distB=" << distB << std::endl;
96  if (!success) {
97  mf::LogWarning("TrackKalmanFitter") << "Fit failure at " << __FILE__ << " " << __LINE__;
98  return false;
99  }
100  reverseHits = distB<distF;
101 
102  if (dumpLevel_>1) std::cout << "flags.size()=" << flags.size() << " hits.size()=" << hits.size() << " reverseHits=" << reverseHits << std::endl;
103 
104  // setup vector of HitStates and flags, with either same or inverse order as input hit vector
105  // this is what we'll loop over during the fit
106  const int fsize = flags.size();
107  const int beg = (reverseHits ? hits.size()-1 : 0);
108  const int end = (reverseHits ? -1 : hits.size());
109  for (int ihit = beg; ihit!=end; (reverseHits ? ihit-- : ihit++)) {
110  const auto& hit = hits[ihit];
111  double t = hit->PeakTime();
112  double terr = (useRMS_ ? hit->RMS() : hit->SigmaPeakTime() );
113  double x = detprop->ConvertTicksToX(t, hit->WireID().Plane, hit->WireID().TPC, hit->WireID().Cryostat);
114  double xerr = terr * detprop->GetXTicksCoefficient();
115  hitstatev.emplace_back( x,hitErr2ScaleFact_*xerr*xerr,hit->WireID(),geom->WireIDToWireGeo(hit->WireID()) );
116  //
117  if (fsize>0 && ihit<fsize) hitflagsv.push_back( flags[ihit].mask() );
118  else hitflagsv.push_back(recob::TrajectoryPointFlags::DefaultFlagsMask());
119  //
120  if (dumpLevel_>2) std::cout << "pushed flag mask=" << hitflagsv.back() << std::endl;
121  //
122  if (rejectHighMultHits_ && hit->Multiplicity()>1) {
123  hitflagsv.back().set(recob::TrajectoryPointFlagTraits::Merged);
125  }
126  if (rejectHitsNegativeGOF_ && hit->GoodnessOfFit()<0) {
127  hitflagsv.back().set(recob::TrajectoryPointFlagTraits::Suspicious);
129  }
130  }
131  if (dumpLevel_>2) assert(hits.size()==hitstatev.size());
132  return true;
133 }
134 
135 bool trkf::TrackKalmanFitter::doFitWork(KFTrackState& trackState, std::vector<HitState>& hitstatev, std::vector<recob::TrajectoryPointFlags::Mask_t>& hitflagsv,
136  std::vector<KFTrackState>& fwdPrdTkState, std::vector<KFTrackState>& fwdUpdTkState,
137  std::vector<unsigned int>& hitstateidx, std::vector<unsigned int>& rejectedhsidx, std::vector<unsigned int>& sortedtksidx,
138  bool applySkipClean) const {
139 
140  fwdPrdTkState.clear();
141  fwdUpdTkState.clear();
142  hitstateidx.clear();
143  rejectedhsidx.clear();
144  sortedtksidx.clear();
145  // these three vectors are aligned
146  fwdPrdTkState.reserve(hitstatev.size());
147  fwdUpdTkState.reserve(hitstatev.size());
148  hitstateidx.reserve(hitstatev.size());
149 
150  if (sortHitsByPlane_) {
151  //array of hit indices in planes, keeping the original sorting by plane
152  const unsigned int nplanes = geom->MaxPlanes();
153  std::vector<std::vector<unsigned int> > hitsInPlanes(nplanes);
154  for (unsigned int ihit = 0; ihit<hitstatev.size(); ihit++) {
155  hitsInPlanes[hitstatev[ihit].wireId().Plane].push_back(ihit);
156  }
157  //array of indices, where iterHitsInPlanes[i] is the iterator over hitsInPlanes[i]
158  std::vector<unsigned int> iterHitsInPlanes(nplanes,0);
159  for (unsigned int p = 0; p<hitstatev.size(); ++p) {
160  if (dumpLevel_>1) std::cout << std::endl << "processing hit #" << p << std::endl;
161  if (dumpLevel_>1) {
162  std::cout << "compute distance from state=" << std::endl; trackState.dump();
163  }
164  int min_plane = -1;
165  double min_dist = DBL_MAX;
166  //find the closest hit according to the sorting in each plane
167  for (unsigned int iplane = 0; iplane<nplanes; ++iplane) {
168  //note: ih is a reference, so when 'continue' we increment iterHitsInPlanes[iplane] and the hit is effectively rejected
169  for (unsigned int& ih = iterHitsInPlanes[iplane]; ih<hitsInPlanes[iplane].size(); ++ih) {
170  if (dumpLevel_>1) std::cout << "iplane=" << iplane << " nplanes=" << nplanes << " iterHitsInPlanes[iplane]=" << iterHitsInPlanes[iplane] << " hitsInPlanes[iplane].size()=" << hitsInPlanes[iplane].size() << std::endl;
171  unsigned int ihit = hitsInPlanes[iplane][ih];
172  const auto& hitstate = hitstatev[ihit];
173  const auto& hitflags = hitflagsv[ihit];
174  if (hitflags.isSet(recob::TrajectoryPointFlagTraits::NoPoint ) ||
177  if (dumpLevel_>1) std::cout << "rejecting hit flags=" << hitflags.isSet(recob::TrajectoryPointFlagTraits::NoPoint ) << ", " << hitflags.isSet(recob::TrajectoryPointFlagTraits::ExcludedFromFit) << ", " << hitflags.isSet(recob::TrajectoryPointFlagTraits::Rejected ) << std::endl;
178  rejectedhsidx.push_back(ihit);
179  continue;
180  }
181  //get distance to measurement surface
182  bool success = true;
183  const double dist = propagator->distanceToPlane(success, trackState.trackState(), hitstate.plane());
184  if (dumpLevel_>1) std::cout << "distance to plane " << iplane << " wire=" << hitstate.wireId().Wire << " = " << dist << ", min_dist=" << std::min(min_dist,999.) << " min_plane=" << min_plane << " success=" << success << std::endl;
185  if (!success) {
186  rejectedhsidx.push_back(ihit);
187  continue;
188  }
189  if (applySkipClean && skipNegProp_ && dist<0.) {
190  rejectedhsidx.push_back(ihit);
191  continue;
192  }
193  if (dist<min_dist) {
194  min_plane = iplane;
195  min_dist = dist;
196  }
197  break;
198  }
199  }
200  if (dumpLevel_>1) std::cout << "pick min_dist=" << min_dist << " min_plane=" << min_plane << std::endl;
201  //now we know which is the closest wire: get the hitstate and increment the iterator
202  if (min_plane<0) continue;
203  const unsigned int ihit = hitsInPlanes[min_plane][iterHitsInPlanes[min_plane]];
204  const auto& hitstate = hitstatev[ihit];
205  if (dumpLevel_>1) hitstate.dump();
206  auto& hitflags = hitflagsv[ihit];
207  iterHitsInPlanes[min_plane]++;
208  //propagate to measurement surface
209  bool propok = true;
210  trackState = propagator->propagateToPlane(propok, trackState.trackState(), hitstate.plane(), true, true, TrackStatePropagator::FORWARD);
211  if (!propok && !(applySkipClean && skipNegProp_)) {
212  if (dumpLevel_>1) std::cout << "attempt backward prop" << std::endl;
213  trackState = propagator->propagateToPlane(propok, trackState.trackState(), hitstate.plane(), true, true, TrackStatePropagator::BACKWARD);
214  }
215  if (dumpLevel_>1) {
216  std::cout << "hit state " << std::endl; hitstate.dump();
217  std::cout << "propagation result=" << propok << std::endl;
218  std::cout << "propagated state " << std::endl; trackState.dump();
219  std::cout << "propagated planarity=" << hitstate.plane().direction().Dot(hitstate.plane().position()-trackState.position()) << std::endl;
220  }
221  if (propok) {
222  hitstateidx.push_back(ihit);
223  fwdPrdTkState.push_back(trackState);
224  //
225  if (hitflags.isSet(recob::TrajectoryPointFlagTraits::HitIgnored ) ||
226  hitflags.isSet(recob::TrajectoryPointFlagTraits::Merged ) ||
227  hitflags.isSet(recob::TrajectoryPointFlagTraits::Shared ) ||
231  //do not update the hit, mark as excluded from the fit
232  fwdUpdTkState.push_back(trackState);
234  continue;
235  }
236  //now update the forward fitted track
237  bool upok = trackState.updateWithHitState(hitstate);
238  if (upok==0) {
239  mf::LogWarning("TrackKalmanFitter") << "Fit failure at " << __FILE__ << " " << __LINE__;
240  return false;
241  }
242  if (dumpLevel_>1) {
243  std::cout << "updated state " << std::endl; trackState.dump();
244  }
245  fwdUpdTkState.push_back(trackState);
246  } else {
247  if (dumpLevel_>0) std::cout << "WARNING: forward propagation failed. Skip this hit..." << std::endl;
248  rejectedhsidx.push_back(ihit);
249  continue;
250  }
251  }
252  } else {
253  for (unsigned int ihit=0; ihit<hitstatev.size(); ++ihit) {
254  const auto& hitstate = hitstatev[ihit];
255  if (dumpLevel_>1) {
256  std::cout << std::endl << "processing hit #" << ihit << std::endl;
257  hitstate.dump();
258  }
259  auto& hitflags = hitflagsv[ihit];
262  rejectedhsidx.push_back(ihit);
263  continue;
264  }
265  if (applySkipClean && skipNegProp_) {
266  bool success = true;
267  const double dist = propagator->distanceToPlane(success, trackState.trackState(), hitstate.plane());
268  if (dist<0. || success==false) {
269  if (dumpLevel_>0) std::cout << "WARNING: negative propagation distance. Skip this hit..." << std::endl;;
270  rejectedhsidx.push_back(ihit);
271  continue;
272  }
273  }
274  //propagate to measurement surface
275  bool propok = true;
276  trackState = propagator->propagateToPlane(propok, trackState.trackState(), hitstate.plane(), true, true, TrackStatePropagator::FORWARD);
277  if (!propok && !(applySkipClean && skipNegProp_)) trackState = propagator->propagateToPlane(propok, trackState.trackState(), hitstate.plane(), true, true, TrackStatePropagator::BACKWARD);
278  if (propok) {
279  hitstateidx.push_back(ihit);
280  fwdPrdTkState.push_back(trackState);
281  //
282  if (hitflags.isSet(recob::TrajectoryPointFlagTraits::HitIgnored ) ||
283  hitflags.isSet(recob::TrajectoryPointFlagTraits::Merged ) ||
284  hitflags.isSet(recob::TrajectoryPointFlagTraits::Shared ) ||
288  //do not update the hit, mark as excluded from the fit
289  fwdUpdTkState.push_back(trackState);
291  continue;
292  }
293  //
294  bool upok = trackState.updateWithHitState(hitstate);
295  if (upok==0) {
296  mf::LogWarning("TrackKalmanFitter") << "Fit failure at " << __FILE__ << " " << __LINE__;
297  return false;
298  }
299  fwdUpdTkState.push_back(trackState);
300  } else {
301  if (dumpLevel_>0) std::cout << "WARNING: forward propagation failed. Skip this hit..." << std::endl;;
302  rejectedhsidx.push_back(ihit);
303  continue;
304  }
305  }//for (auto hitstate : hitstatev)
306  }
307 
308  if (dumpLevel_>2) assert( rejectedhsidx.size()+hitstateidx.size() == hitstatev.size() );
309  if (dumpLevel_>0) {
310  std::cout << "TRACK AFTER FWD" << std::endl;
311  trackState.dump();
312  }
313 
314  //reinitialize trf for backward fit, scale the error to avoid biasing the backward fit
315  trackState.setCovariance(100.*trackState.covariance());
316 
317  //backward loop over track states and hits in fwdUpdTracks: use hits for backward fit and fwd track states for smoothing
318  int nvalidhits = 0;
319  for (int itk = fwdPrdTkState.size()-1; itk>=0; itk--) {
320  auto& fwdPrdTrackState = fwdPrdTkState[itk];
321  auto& fwdUpdTrackState = fwdUpdTkState[itk];
322  const auto& hitstate = hitstatev[hitstateidx[itk]];
323  auto& hitflags = hitflagsv[hitstateidx[itk]];
324  if (dumpLevel_>1) {
325  std::cout << std::endl << "processing backward hit #" << itk << std::endl;
326  hitstate.dump();
327  }
328  bool propok = true;
329  trackState = propagator->propagateToPlane(propok, trackState.trackState(), hitstate.plane(), true, true, TrackStatePropagator::BACKWARD);
330  if (!propok) trackState = propagator->propagateToPlane(propok, trackState.trackState(), hitstate.plane(), true, true, TrackStatePropagator::FORWARD);//do we want this?
331  //
332  if (dumpLevel_>1) {
333  std::cout << "propagation result=" << propok << std::endl;
334  std::cout << "propagated state " << std::endl; trackState.dump();
335  std::cout << "propagated planarity=" << hitstate.plane().direction().Dot(hitstate.plane().position()-trackState.position()) << std::endl;
336  }
337  if (propok) {
338  //combine forward predicted and backward predicted
339  bool pcombok = fwdPrdTrackState.combineWithTrackState(trackState.trackState());
340  if (pcombok==0) {
341  mf::LogWarning("TrackKalmanFitter") << "Fit failure at " << __FILE__ << " " << __LINE__;
342  return false;
343  }
344  if (dumpLevel_>1) {
345  std::cout << "combined prd state " << std::endl; fwdPrdTrackState.dump();
346  }
347  //combine forward updated and backward predicted
348  bool ucombok = fwdUpdTrackState.combineWithTrackState(trackState.trackState());
349  if (ucombok==0) {
350  mf::LogWarning("TrackKalmanFitter") << "Fit failure at " << __FILE__ << " " << __LINE__;
351  return false;
352  }
353  if (dumpLevel_>1) {
354  std::cout << "combined upd state " << std::endl; fwdUpdTrackState.dump();
355  }
356  //update backward predicted, only if the hit was not excluded
357  if (hitflags.isSet(recob::TrajectoryPointFlagTraits::ExcludedFromFit)==0) {
358  bool upok = trackState.updateWithHitState(hitstate);
359  if (upok==0) {
360  mf::LogWarning("TrackKalmanFitter") << "Fit failure at " << __FILE__ << " " << __LINE__;
361  return false;
362  }
363  if (dumpLevel_>1) {
364  std::cout << "updated state " << std::endl; trackState.dump();
365  }
366  //
367  nvalidhits++;
368  }
369  } else {
370  // ok, if the backward propagation failed we exclude this point from the rest of the fit,
371  // but we can still use its position from the forward fit, so just mark it as ExcludedFromFit
373  if (dumpLevel_>0) std::cout << "WARNING: backward propagation failed. Skip this hit..." << std::endl;;
374  continue;
375  }
376  }//for (unsigned int itk = fwdPrdTkState.size()-1; itk>=0; itk--) {
377 
378  if (nvalidhits<4) {
379  mf::LogWarning("TrackKalmanFitter") << "Fit failure at " << __FILE__ << " " << __LINE__ << " ";
380  return false;
381  }
382 
383  // sort output states
384  sortOutput(hitstatev, fwdUpdTkState, hitstateidx, rejectedhsidx, sortedtksidx, applySkipClean);
385  if (sortedtksidx.size()<4) {
386  mf::LogWarning("TrackKalmanFitter") << "Fit failure at " << __FILE__ << " " << __LINE__ << " ";
387  return false;
388  }
389 
390  if (dumpLevel_>2) assert( rejectedhsidx.size()+sortedtksidx.size() == hitstatev.size() );
391  return true;
392 }
393 
394 void trkf::TrackKalmanFitter::sortOutput(std::vector<HitState>& hitstatev, std::vector<KFTrackState>& fwdUpdTkState,
395  std::vector<unsigned int>& hitstateidx, std::vector<unsigned int>& rejectedhsidx,
396  std::vector<unsigned int>& sortedtksidx, bool applySkipClean) const {
397  //
399  //try to sort fixing wires order on planes and picking the closest next plane
400  const unsigned int nplanes = geom->MaxPlanes();
401  std::vector<std::vector<unsigned int> > tracksInPlanes(nplanes);
402  for (unsigned int p = 0; p<hitstateidx.size(); ++p) {
403  const auto& hitstate = hitstatev[hitstateidx[p]];
404  tracksInPlanes[hitstate.wireId().Plane].push_back(p);
405  }
406  //this assumes that the first hit/state is a good one, may want to check if that's the case
407  std::vector<unsigned int> iterTracksInPlanes;
408  for (auto it : tracksInPlanes) iterTracksInPlanes.push_back(0);
409  auto pos = fwdUpdTkState.front().position();
410  auto dir = fwdUpdTkState.front().momentum();
411  for (unsigned int p = 0; p<fwdUpdTkState.size(); ++p) {
412  int min_plane = -1;
413  double min_dotp = DBL_MAX;
414  for (unsigned int iplane = 0; iplane<iterTracksInPlanes.size(); ++iplane) {
415  for (unsigned int& itk = iterTracksInPlanes[iplane]; itk<tracksInPlanes[iplane].size(); ++itk) {
416  auto& trackstate = fwdUpdTkState[tracksInPlanes[iplane][iterTracksInPlanes[iplane]]];
417  auto& tmppos = trackstate.position();
418  const double dotp = dir.Dot(tmppos-pos);
419  if (dotp<min_dotp) {
420  min_plane = iplane;
421  min_dotp = dotp;
422  }
423  break;
424  }
425  }
426  if (min_plane<0) continue;
427  const unsigned int ihit = tracksInPlanes[min_plane][iterTracksInPlanes[min_plane]];
428  if (applySkipClean && skipNegProp_ && min_dotp<0.) {
429  rejectedhsidx.push_back(hitstateidx[ihit]);
430  iterTracksInPlanes[min_plane]++;
431  continue;
432  }
433  auto& trackstate = fwdUpdTkState[ihit];
434  pos = trackstate.position();
435  dir = trackstate.momentum();
436  //
437  sortedtksidx.push_back(ihit);
438  iterTracksInPlanes[min_plane]++;
439  }
440  } else {
441  for (unsigned int p = 0; p<fwdUpdTkState.size(); ++p) {
442  sortedtksidx.push_back(p);
443  }
444  }
445  //
446  if (applySkipClean && cleanZigzag_) {
447  std::vector<unsigned int> itoerase;
448  bool clean = false;
449  while (!clean) {
450  bool broken = false;
451  auto pos0 = fwdUpdTkState[sortedtksidx[0]].position();
452  unsigned int i=1;
453  unsigned int end=sortedtksidx.size()-1;
454  for (;i<end;++i) {
455  auto dir0 = fwdUpdTkState[sortedtksidx[i]].position()-pos0;
456  auto dir2 = fwdUpdTkState[sortedtksidx[i+1]].position()-fwdUpdTkState[sortedtksidx[i]].position();
457  dir0/=dir0.R();
458  dir2/=dir2.R();
459  if (dir2.Dot(dir0)<0.) {
460  broken = true;
461  end--;
462  break;
463  } else pos0 = fwdUpdTkState[sortedtksidx[i]].position();
464  }
465  if (!broken) {
466  clean = true;
467  } else {
468  rejectedhsidx.push_back(hitstateidx[sortedtksidx[i]]);
469  sortedtksidx.erase(sortedtksidx.begin()+i);
470  }
471  }
472  }
473  //
474 }
475 
476 
477 bool trkf::TrackKalmanFitter::fillResult(const std::vector<art::Ptr<recob::Hit> >& inHits, const int tkID, const int pdgid, const bool reverseHits,
478  std::vector<HitState>& hitstatev, std::vector<recob::TrajectoryPointFlags::Mask_t>& hitflagsv,
479  std::vector<KFTrackState>& fwdPrdTkState, std::vector<KFTrackState>& fwdUpdTkState,
480  std::vector<unsigned int>& hitstateidx, std::vector<unsigned int>& rejectedhsidx, std::vector<unsigned int>& sortedtksidx,
481  recob::Track& outTrack, std::vector<art::Ptr<recob::Hit> >& outHits, trkmkr::OptionalOutputs& optionals) const {
482  // fill output trajectory objects with smoothed track and its hits
483  trkmkr::TrackCreationBookKeeper tcbk(outHits, optionals, tkID, pdgid, true);
484  for (unsigned int p : sortedtksidx) {
485  const auto& trackstate = fwdUpdTkState[p];
486  const auto& hitflags = hitflagsv[hitstateidx[p]];
487  const unsigned int originalPos = (reverseHits ? hitstatev.size()-hitstateidx[p]-1 : hitstateidx[p]);
488  if (dumpLevel_>2) assert(originalPos>=0 && originalPos<hitstatev.size());
489  //
490  const auto& prdtrack = fwdPrdTkState[p];
491  const auto& hitstate = hitstatev[hitstateidx[p]];
492  if (dumpLevel_>2) assert(hitstate.wireId().Plane == inHits[originalPos]->WireID().Plane);
493  //
495  if (optionals.isTrackFitInfosInit()) {
496  ope.setTrackFitHitInfo(recob::TrackFitHitInfo(hitstate.hitMeas(),hitstate.hitMeasErr2(),prdtrack.parameters(),prdtrack.covariance(),hitstate.wireId()));
497  }
498  tcbk.addPoint(trackstate.position(), trackstate.momentum(), inHits[originalPos],
499  recob::TrajectoryPointFlags(originalPos,hitflags), prdtrack.chi2(hitstate), ope);
500  }
501 
502  // fill also with rejected hits information
503  SMatrixSym55 fakeCov55;
504  for (int i=0;i<5;i++) for (int j=i;j<5;j++) fakeCov55(i,j) = util::kBogusD;
505  for (unsigned int rejidx = 0; rejidx<rejectedhsidx.size(); ++rejidx) {
506  const unsigned int originalPos = (reverseHits ? hitstatev.size()-rejectedhsidx[rejidx]-1 : rejectedhsidx[rejidx]);
507  auto& mask = hitflagsv[rejectedhsidx[rejidx]];
510  //
511  const auto& hitstate = hitstatev[rejectedhsidx[rejidx]];
512  if (dumpLevel_>2) assert(hitstate.wireId().Plane == inHits[originalPos]->WireID().Plane);
514  if (optionals.isTrackFitInfosInit()) {
515  ope.setTrackFitHitInfo( recob::TrackFitHitInfo(hitstate.hitMeas(),hitstate.hitMeasErr2(),
517  }
519  recob::TrajectoryPointFlags(originalPos,mask), 0, ope);
520  }
521 
522  if (dumpLevel_>1) std::cout << "outHits.size()=" << outHits.size() << " inHits.size()=" << inHits.size() << std::endl;
523  if (dumpLevel_>2) assert(outHits.size()==inHits.size());
524 
525  bool propok = true;
526  KFTrackState resultF = propagator->rotateToPlane(propok, fwdUpdTkState[sortedtksidx.front()].trackState(),
527  Plane(fwdUpdTkState[sortedtksidx.front()].position(),fwdUpdTkState[sortedtksidx.front()].momentum()));
528  KFTrackState resultB = propagator->rotateToPlane(propok, fwdUpdTkState[sortedtksidx.back()].trackState(),
529  Plane(fwdUpdTkState[sortedtksidx.back()].position(),fwdUpdTkState[sortedtksidx.back()].momentum()));
530 
531  outTrack = tcbk.finalizeTrack(SMatrixSym55(resultF.covariance()),SMatrixSym55(resultB.covariance()));
532 
533  //if there are points with zero momentum return false
534  size_t point = 0;
535  while (outTrack.HasValidPoint(point)) {
536  if (outTrack.MomentumAtPoint( outTrack.NextValidPoint(point++) ) <= 1.0e-9) return false;
537  }
538 
539  if (dumpLevel_>0) {
540  std::cout << "outTrack vertex=" << outTrack.Start()
541  << "\ndir=" << outTrack.StartDirection()
542  << "\ncov=\n" << outTrack.StartCovariance()
543  << "\nlength=" << outTrack.Length() //<< " inLenght=" << track.Length()
544  << std::endl;
545  }
546 
547  return true;
548 }
Float_t x
Definition: compare.C:6
Geometry description of a TPC wireThe wire is a single straight segment on a wire plane...
Definition: WireGeo.h:61
bool setupInputStates(const std::vector< art::Ptr< recob::Hit > > &hits, const std::vector< recob::TrajectoryPointFlags > &flags, const KFTrackState &trackState, bool &reverseHits, std::vector< HitState > &hitstatev, std::vector< recob::TrajectoryPointFlags::Mask_t > &hitflagsv) const
Setup vectors of HitState and Masks to be used during the fit.
static constexpr Flag_t Merged
The hit might have contribution from particles other than this.
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.
static constexpr Flag_t NoPoint
The trajectory point is not defined.
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.
const SMatrixSym55 & StartCovariance() const
Access to covariance matrices.
Definition: Track.h:156
Declaration of signal hit object.
recob::tracking::SMatrixSym55 SMatrixSym55
Definition: TrackState.h:15
bool HasValidPoint(size_t i) const
Various functions related to the presence and the number of (valid) points.
Definition: Track.h:114
bool fitTrack(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.
double distanceToPlane(bool &success, const Point_t &origpos, const Vector_t &origdir, const Plane &target) const
Distance of a TrackState (Point and Vector) to a Plane, along the TrackState direction.
double MomentumAtPoint(unsigned int p) const
Definition: Track.h:144
const detinfo::DetectorProperties * detprop
void setCovariance(const SMatrixSym55 &trackStateCov)
This function calls the homonymous function of the stored TrackState.
Definition: KFTrackState.h:57
const Point_t & position() const
This function calls the homonymous function of the stored TrackState.
Definition: KFTrackState.h:45
void addPoint(const Point_t &point, const Vector_t &vect, art::Ptr< Hit > hit, const PointFlags_t &flag, double chi2)
Add a single point; different version of the functions are provided using const references or rvalue ...
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.
Track finalizeTrack(const tracking::SMatrixSym55 &covStart, const tracking::SMatrixSym55 &covEnd)
Get the finalized recob::Track; needs the start and end covariance matrices.
Extension of a TrackState to perform KalmanFilter calculations.
Definition: KFTrackState.h:21
void hits()
Definition: readHits.C:15
Vector_t StartDirection() const
Access to track direction at different points.
Definition: Track.h:134
unsigned int MaxPlanes() const
Returns the largest number of planes among all TPCs in this detector.
double Length(size_t p=0) const
Access to various track properties.
Definition: Track.h:170
recob::tracking::SVector5 SVector5
Definition: TrackState.h:12
Point_t const & Start() const
Access to track position at different points.
Definition: Track.h:126
const SMatrixSym55 & covariance() const
This function calls the homonymous function of the stored TrackState.
Definition: KFTrackState.h:43
A trajectory in space reconstructed from hits.
Object storing per-hit information from a track fit.
virtual double GetXTicksCoefficient(int t, int c) const =0
Struct holding point-by-point elements used in OptionalOutputs.
Definition: TrackMaker.h:32
TrackState rotateToPlane(bool &success, const TrackState &origin, const Plane &target) const
Rotation of a TrackState to a Plane (zero distance propagation)
Plane makePlane(recob::tracking::Point_t const &pos, recob::tracking::Vector_t const &dir)
helper function to construct a recob::tracking::Plane from a Point_t and a Vector_t; the point is on ...
const TrackStatePropagator * propagator
bool updateWithHitState(const HitState &hitstate)
Update the TrackState given a HitState (they need to be on the same plane)
Definition: KFTrackState.cxx:5
art::ServiceHandle< geo::Geometry > geom
static constexpr Flag_t HitIgnored
Hit was not included for the computation of the trajectory.
Point_t const & Vertex() const
Returns the position of the first valid point of the trajectory [cm].
Detector simulation of raw signals on wires.
Class defining a plane for tracking. It provides various functionalities to convert track parameters ...
Definition: TrackingPlane.h:37
static constexpr Flag_t Rejected
The hit is extraneous to this track.
static constexpr Flag_t ExcludedFromFit
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.
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
size_t NextValidPoint(size_t index) const
Various functions related to the presence and the number of (valid) points.
Definition: Track.h:110
TDirectory * dir
Definition: macro.C:5
Int_t min
Definition: plot.C:26
Point_t const & End() const
Returns the position of the last valid point of the trajectory [cm].
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
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, bool applySkipClean=true) const
Sort the output states.
Helper class to aid the creation of a recob::Track, keeping data vectors in sync. ...
std::ostream & dump(std::ostream &out=std::cout) const
Printout information.
Definition: TrackState.h:119
TrackState propagateToPlane(bool &success, const TrackState &origin, const Plane &target, bool dodedx, bool domcs, PropDirection dir=FORWARD) const
Main function for propagation of a TrackState to a Plane.
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:110
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
static constexpr Flag_t DeltaRay
The hit might have contribution from a δ ray.
constexpr double kBogusD
obviously bogus double value
bool doFitWork(KFTrackState &trackState, 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.
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:35
Float_t e
Definition: plot.C:34
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:73
Set of flags pertaining a point of the track.
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
bool fillResult(const std::vector< art::Ptr< recob::Hit > > &inHits, const int tkID, const int pdgid, const bool reverseHits, 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.
WireGeo const & WireIDToWireGeo(geo::WireID const &wireid) const
Returns the specified wire.