All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
KalmanFilterFinalTrackFitter_module.cc
Go to the documentation of this file.
1 /// \class KalmanFilterFinalTrackFitter
2 ///
3 /// \brief Producer for fitting Trajectories and TrackTrajectories using TrackKalmanFitter.
4 ///
5 /// \author G. Cerati
6 ///
7 
8 #include "art/Framework/Core/EDProducer.h"
9 #include "art/Framework/Core/ModuleMacros.h"
10 #include "art/Framework/Principal/Event.h"
11 #include "art/Framework/Principal/Handle.h"
12 
13 #include "canvas/Persistency/Common/FindManyP.h"
14 #include "canvas/Utilities/InputTag.h"
15 #include "fhiclcpp/types/Atom.h"
16 #include "fhiclcpp/types/Sequence.h"
17 #include "fhiclcpp/types/Table.h"
18 
30 
36 
37 #include <memory>
38 
39 namespace trkf {
40 
41  class KalmanFilterFinalTrackFitter : public art::EDProducer {
42  public:
43  struct Inputs {
44  using Name = fhicl::Name;
45  using Comment = fhicl::Comment;
46  fhicl::Atom<art::InputTag> inputPFParticleLabel{
47  Name("inputPFParticleLabel"),
48  Comment("Label of recob::PFParticle Collection to be fit")};
49  fhicl::Atom<art::InputTag> inputTracksLabel{
50  Name("inputTracksLabel"),
51  Comment("Label of recob::Track Collection to be fit")};
52  fhicl::Atom<art::InputTag> inputShowersLabel{
53  Name("inputShowersLabel"),
54  Comment("Label of recob::Shower Collection (associated to PFParticles) to be fit")};
55  fhicl::Atom<art::InputTag> inputCaloLabel{
56  Name("inputCaloLabel"),
57  Comment("Label of anab::Calorimetry Collection, matching inputTracksLabel, to be used for "
58  "initial momentum estimate. Used only if momFromCalo is set to true.")};
59  fhicl::Atom<art::InputTag> inputMCLabel{
60  Name("inputMCLabel"),
61  Comment("Label of sim::MCTrack Collection to be used for initial momentum estimate. Used "
62  "only if momFromMC is set to true.")};
63  fhicl::Atom<art::InputTag> inputPidLabel{
64  Name("inputPidLabel"),
65  Comment("Label of anab::ParticleID Collection, matching inputTracksLabel, to be used for "
66  "particle Id.")};
67  };
68 
69  struct Options {
70  using Name = fhicl::Name;
71  using Comment = fhicl::Comment;
72  fhicl::Atom<bool> trackFromPF{Name("trackFromPF"),
73  Comment("If true extract tracks from inputPFParticleLabel "
74  "collection, if false from inputTracksLabel.")};
75  fhicl::Atom<bool> showerFromPF{
76  Name("showerFromPF"),
77  Comment("If true extract showers from inputPFParticleLabel collection.")};
78  fhicl::Atom<bool> pFromMSChi2{
79  Name("momFromMSChi2"),
80  Comment("Flag used to get initial momentum estimate from "
81  "trkf::TrackMomentumCalculator::GetMomentumMultiScatterChi2().")};
82  fhicl::Atom<bool> pFromLength{Name("momFromLength"),
83  Comment("Flag used to get initial momentum estimate from "
84  "trkf::TrackMomentumCalculator::GetTrackMomentum().")};
85  fhicl::Atom<bool> pFromCalo{
86  Name("momFromCalo"),
87  Comment("Flag used to get initial momentum estimate from inputCaloLabel collection.")};
88  fhicl::Atom<bool> pFromMC{
89  Name("momFromMC"),
90  Comment("Flag used to get initial momentum estimate from inputMCLabel collection.")};
91  fhicl::Atom<double> pval{
92  Name("momentumInGeV"),
93  Comment("Fixed momentum estimate value, to be used when momFromCalo, momFromMSChi2, "
94  "momFromLength and momFromMC are all false, or if the estimate is not available.")};
95  fhicl::Atom<bool> idFromPF{Name("idFromPF"),
96  Comment("Flag used to get particle ID estimate from corresponding "
97  "PFParticle. Needs trackFromPF=true.")};
98  fhicl::Atom<bool> idFromCollection{
99  Name("idFromCollection"),
100  Comment("Flag used to get particle ID estimate from inputPidLabel collection.")};
101  fhicl::Atom<int> pdgId{
102  Name("pdgId"),
103  Comment("Default particle id hypothesis in case no valid id is provided either via "
104  "PFParticle or in the ParticleId collection.")};
105  fhicl::Atom<bool> dirFromVtxPF{
106  Name("dirFromVtxPF"),
107  Comment("Assume track direction from Vertex in PFParticle. Needs trackFromPF=true.")};
108  fhicl::Atom<bool> dirFromMC{Name("dirFromMC"), Comment("Assume track direction from MC.")};
109  fhicl::Atom<bool> dirFromVec{Name("dirFromVec"),
110  Comment("Assume track direction from as the one giving positive "
111  "dot product with vector specified by dirVec.")};
112  fhicl::Sequence<float, 3u> dirVec{Name("dirVec"),
113  Comment("Fhicl sequence defining the vector used when "
114  "dirFromVec=true. It must have 3 elements.")};
115  fhicl::Atom<bool> alwaysInvertDir{
116  Name("alwaysInvertDir"),
117  Comment("If true, fit all tracks from end to vertex assuming inverted direction.")};
118  fhicl::Atom<bool> produceTrackFitHitInfo{
119  Name("produceTrackFitHitInfo"),
120  Comment("Option to produce (or not) the detailed TrackFitHitInfo.")};
121  fhicl::Atom<bool> produceSpacePoints{
122  Name("produceSpacePoints"),
123  Comment("Option to produce (or not) the associated SpacePoints.")};
124  fhicl::Atom<bool> keepInputTrajectoryPoints{
125  Name("keepInputTrajectoryPoints"),
126  Comment("Option to keep positions and directions from input trajectory/track. The fit will "
127  "provide only covariance matrices, chi2, ndof, particle Id and absolute momentum. "
128  "It may also modify the trajectory point flags. In order to avoid inconsistencies, "
129  "it has to be used with the following fitter options all set to false: "
130  "sortHitsByPlane, sortOutputHitsMinLength, skipNegProp.")};
131  };
132 
133  struct Config {
134  using Name = fhicl::Name;
135  fhicl::Table<KalmanFilterFinalTrackFitter::Inputs> inputs{
136  Name("inputs"),
137  };
138  fhicl::Table<KalmanFilterFinalTrackFitter::Options> options{Name("options")};
139  fhicl::Table<TrackStatePropagator::Config> propagator{Name("propagator")};
140  fhicl::Table<TrackKalmanFitter::Config> fitter{Name("fitter")};
141  };
142  using Parameters = art::EDProducer::Table<Config>;
143 
144  explicit KalmanFilterFinalTrackFitter(Parameters const& p);
145 
146  // Plugins should not be copied or assigned.
151 
152  private:
153  void produce(art::Event& e) override;
154 
160 
161  art::InputTag pfParticleInputTag;
162  art::InputTag trackInputTag;
163  art::InputTag showerInputTag;
164  art::InputTag caloInputTag;
165  art::InputTag pidInputTag;
166  art::InputTag simTrackInputTag;
167 
168  std::unique_ptr<art::FindManyP<anab::Calorimetry>> trackCalo;
169  std::unique_ptr<art::FindManyP<anab::ParticleID>> trackId;
170  std::unique_ptr<art::FindManyP<recob::Track>> assocTracks;
171  std::unique_ptr<art::FindManyP<recob::Shower>> assocShowers;
172  std::unique_ptr<art::FindManyP<recob::Vertex>> assocVertices;
173 
174  double setMomValue(art::Ptr<recob::Track> ptrack,
175  const std::unique_ptr<art::FindManyP<anab::Calorimetry>>& trackCalo,
176  const double pMC,
177  const int pId) const;
178  int setPId(const unsigned int iTrack,
179  const std::unique_ptr<art::FindManyP<anab::ParticleID>>& trackId,
180  const int pfPid = 0) const;
181  bool setDirFlip(const recob::Track& track,
182  TVector3& mcdir,
183  const std::vector<art::Ptr<recob::Vertex>>* vertices = 0) const;
184 
186  const std::vector<art::Ptr<recob::Hit>>& inHits,
187  recob::Track& outTrack,
188  std::vector<art::Ptr<recob::Hit>>& outHits) const;
189  };
190 }
191 
194  : EDProducer{p}
195  , p_(p)
196  , prop{p_().propagator}
197  , kalmanFitter{&prop, p_().fitter}
198  , inputFromPF{p_().options().trackFromPF() || p_().options().showerFromPF()}
199 {
200 
201  if (inputFromPF) {
202  pfParticleInputTag = art::InputTag(p_().inputs().inputPFParticleLabel());
203  if (p_().options().showerFromPF())
204  showerInputTag = art::InputTag(p_().inputs().inputShowersLabel());
205  }
206  else {
207  trackInputTag = art::InputTag(p_().inputs().inputTracksLabel());
208  if (p_().options().idFromCollection())
209  pidInputTag = art::InputTag(p_().inputs().inputPidLabel());
210  }
211  if (p_().options().pFromCalo()) caloInputTag = art::InputTag(p_().inputs().inputCaloLabel());
212  if (p_().options().pFromMC() || p_().options().dirFromMC())
213  simTrackInputTag = art::InputTag(p_().inputs().inputMCLabel());
214 
215  produces<std::vector<recob::Track>>();
216  produces<art::Assns<recob::Track, recob::Hit, recob::TrackHitMeta>>();
217  produces<art::Assns<recob::Track, recob::Hit>>();
218  if (inputFromPF) { produces<art::Assns<recob::PFParticle, recob::Track>>(); }
219  if (p_().options().produceTrackFitHitInfo()) {
220  produces<std::vector<std::vector<recob::TrackFitHitInfo>>>();
221  }
222  if (p_().options().produceSpacePoints()) {
223  produces<std::vector<recob::SpacePoint>>();
224  produces<art::Assns<recob::Hit, recob::SpacePoint>>();
225  }
226 
227  //throw expections to avoid possible silent failures due to incompatible configuration options
228  if (p_().options().trackFromPF() == 0 && p_().options().idFromPF())
229  throw cet::exception("KalmanFilterFinalTrackFitter")
230  << "Incompatible configuration parameters: cannot use idFromPF=true with trackFromPF=false."
231  << "\n";
232  if (p_().options().trackFromPF() == 0 && p_().options().dirFromVtxPF())
233  throw cet::exception("KalmanFilterFinalTrackFitter")
234  << "Incompatible configuration parameters: cannot use dirFromVtxPF=true with "
235  "trackFromPF=false."
236  << "\n";
237 
238  unsigned int nIds = 0;
239  if (p_().options().idFromPF()) nIds++;
240  if (p_().options().idFromCollection()) nIds++;
241  if (nIds > 1) {
242  throw cet::exception("KalmanFilterFinalTrackFitter")
243  << "Incompatible configuration parameters: only at most one can be set to true among "
244  "idFromPF and idFromCollection."
245  << "\n";
246  }
247 
248  unsigned int nDirs = 0;
249  if (p_().options().dirFromVtxPF()) nDirs++;
250  if (p_().options().dirFromMC()) nDirs++;
251  if (p_().options().dirFromVec()) nDirs++;
252  if (p_().options().alwaysInvertDir()) nDirs++;
253  if (nDirs > 1) {
254  throw cet::exception("KalmanFilterFinalTrackFitter")
255  << "Incompatible configuration parameters: only at most one can be set to true among "
256  "dirFromVtxPF, dirFromMC, dirFromVec, and alwaysInvertDir."
257  << "\n";
258  }
259 
260  unsigned int nPFroms = 0;
261  if (p_().options().pFromCalo()) nPFroms++;
262  if (p_().options().pFromMSChi2()) nPFroms++;
263  if (p_().options().pFromLength()) nPFroms++;
264  if (p_().options().pFromMC()) nPFroms++;
265  if (nPFroms > 1) {
266  throw cet::exception("KalmanFilterFinalTrackFitter")
267  << "Incompatible configuration parameters: only at most one can be set to true among "
268  "pFromCalo, pFromMSChi2, pFromLength, and pFromMC."
269  << "\n";
270  }
271 
272  if (p_().options().keepInputTrajectoryPoints()) {
273  if (p_().fitter().sortHitsByPlane() || p_().fitter().sortOutputHitsMinLength() ||
274  p_().fitter().skipNegProp()) {
275  throw cet::exception("KalmanFilterTrajectoryFitter")
276  << "Incompatible configuration parameters: keepInputTrajectoryPoints needs the following "
277  "fitter options all set to false: sortHitsByPlane, sortOutputHitsMinLength, skipNegProp."
278  << "\n";
279  }
280  }
281 
282  if (p_().options().showerFromPF()) {
283  if (nPFroms > 0 || nIds > 0 || nDirs > 0) {
284  throw cet::exception("KalmanFilterTrajectoryFitter")
285  << "Incompatible configuration parameters: showerFromPF currently does not support "
286  "optional momentum values, particle hypotheses and directions."
287  << "\n";
288  }
289  }
290 }
291 
292 void
294 {
295  auto outputTracks = std::make_unique<std::vector<recob::Track>>();
296  auto outputHitsMeta =
297  std::make_unique<art::Assns<recob::Track, recob::Hit, recob::TrackHitMeta>>();
298  auto outputHits = std::make_unique<art::Assns<recob::Track, recob::Hit>>();
299  auto outputHitInfo = std::make_unique<std::vector<std::vector<recob::TrackFitHitInfo>>>();
300 
301  auto const tid = e.getProductID<std::vector<recob::Track>>();
302  auto const tidgetter = e.productGetter(tid);
303 
304  auto outputSpacePoints = std::make_unique<std::vector<recob::SpacePoint>>();
305  auto outputHitSpacePointAssn = std::make_unique<art::Assns<recob::Hit, recob::SpacePoint>>();
306  auto const spid = e.getProductID<std::vector<recob::SpacePoint>>();
307  auto const spidgetter = e.productGetter(spid);
308 
309  //FIXME, eventually remove this (ok only for single particle MC)
310  double pMC = -1.;
311  TVector3 mcdir;
312  if (p_().options().pFromMC() || p_().options().dirFromMC()) {
313  art::ValidHandle<std::vector<sim::MCTrack>> simTracks =
314  e.getValidHandle<std::vector<sim::MCTrack>>(simTrackInputTag);
315  for (unsigned int iMC = 0; iMC < simTracks->size(); ++iMC) {
316  const sim::MCTrack& mctrack = simTracks->at(iMC);
317  //fiducial cuts on MC tracks
318  if (mctrack.PdgCode() != 13) continue;
319  if (mctrack.Process() != "primary") continue;
320  pMC = mctrack.Start().Momentum().P() * 0.001;
321  mcdir = TVector3(mctrack.Start().Momentum().X() * 0.001 / pMC,
322  mctrack.Start().Momentum().Y() * 0.001 / pMC,
323  mctrack.Start().Momentum().Z() * 0.001 / pMC);
324  break;
325  }
326  }
327 
328  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(e);
329 
330  if (inputFromPF) {
331 
332  auto outputPFAssn = std::make_unique<art::Assns<recob::PFParticle, recob::Track>>();
333 
334  auto inputPFParticle = e.getValidHandle<std::vector<recob::PFParticle>>(pfParticleInputTag);
335  if (p_().options().trackFromPF())
336  assocTracks =
337  std::make_unique<art::FindManyP<recob::Track>>(inputPFParticle, e, pfParticleInputTag);
338  if (p_().options().showerFromPF())
339  assocShowers =
340  std::make_unique<art::FindManyP<recob::Shower>>(inputPFParticle, e, showerInputTag);
341  assocVertices =
342  std::make_unique<art::FindManyP<recob::Vertex>>(inputPFParticle, e, pfParticleInputTag);
343 
344  for (unsigned int iPF = 0; iPF < inputPFParticle->size(); ++iPF) {
345 
346  if (p_().options().trackFromPF()) {
347  const std::vector<art::Ptr<recob::Track>>& tracks = assocTracks->at(iPF);
348  auto const& tkHitsAssn =
349  *e.getValidHandle<art::Assns<recob::Track, recob::Hit>>(pfParticleInputTag);
350  const std::vector<art::Ptr<recob::Vertex>>& vertices = assocVertices->at(iPF);
351 
352  if (p_().options().pFromCalo()) {
353  trackCalo = std::make_unique<art::FindManyP<anab::Calorimetry>>(tracks, e, caloInputTag);
354  }
355 
356  for (unsigned int iTrack = 0; iTrack < tracks.size(); ++iTrack) {
357 
358  const recob::Track& track = *tracks[iTrack];
359  art::Ptr<recob::Track> ptrack = tracks[iTrack];
360  const int pId = setPId(iTrack, trackId, inputPFParticle->at(iPF).PdgCode());
361  const double mom = setMomValue(ptrack, trackCalo, pMC, pId);
362  const bool flipDir = setDirFlip(track, mcdir, &vertices);
363 
364  //this is not computationally optimal, but at least preserves the order unlike FindManyP
365  std::vector<art::Ptr<recob::Hit>> inHits;
366  for (auto it = tkHitsAssn.begin(); it != tkHitsAssn.end(); ++it) {
367  if (it->first == ptrack)
368  inHits.push_back(it->second);
369  else if (inHits.size() > 0)
370  break;
371  }
372 
373  recob::Track outTrack;
374  std::vector<art::Ptr<recob::Hit>> outHits;
375  trkmkr::OptionalOutputs optionals;
376  if (p_().options().produceTrackFitHitInfo()) optionals.initTrackFitInfos();
377  bool fitok = kalmanFitter.fitTrack(detProp,
378  track.Trajectory(),
379  track.ID(),
380  track.VertexCovarianceLocal5D(),
381  track.EndCovarianceLocal5D(),
382  inHits,
383  mom,
384  pId,
385  flipDir,
386  outTrack,
387  outHits,
388  optionals);
389  if (!fitok) continue;
390 
391  if (p_().options().keepInputTrajectoryPoints()) {
392  restoreInputPoints(track.Trajectory().Trajectory(), inHits, outTrack, outHits);
393  }
394 
395  outputTracks->emplace_back(std::move(outTrack));
396  art::Ptr<recob::Track> aptr(tid, outputTracks->size() - 1, tidgetter);
397  unsigned int ip = 0;
398  for (auto const& trhit : outHits) {
399  //the fitter produces collections with 1-1 match between hits and point
400  recob::TrackHitMeta metadata(ip, -1);
401  outputHitsMeta->addSingle(aptr, trhit, metadata);
402  outputHits->addSingle(aptr, trhit);
403  ip++;
404  }
405  outputPFAssn->addSingle(art::Ptr<recob::PFParticle>(inputPFParticle, iPF), aptr);
406  outputHitInfo->emplace_back(optionals.trackFitHitInfos());
407  }
408  }
409 
410  if (p_().options().showerFromPF()) {
411  art::Ptr<recob::PFParticle> pPF(inputPFParticle, iPF);
412  const std::vector<art::Ptr<recob::Shower>>& showers = assocShowers->at(iPF);
413  if (showers.size() == 0) continue;
414  auto const& pfClustersAssn =
415  *e.getValidHandle<art::Assns<recob::PFParticle, recob::Cluster>>(showerInputTag);
416  auto const& clHitsAssn =
417  *e.getValidHandle<art::Assns<recob::Cluster, recob::Hit>>(showerInputTag);
418  std::vector<art::Ptr<recob::Hit>> inHits;
419  for (auto itpf = pfClustersAssn.begin(); itpf != pfClustersAssn.end(); ++itpf) {
420  if (itpf->first == pPF) {
421  art::Ptr<recob::Cluster> clust = itpf->second;
422  for (auto it = clHitsAssn.begin(); it != clHitsAssn.end(); ++it) {
423  if (it->first == clust) inHits.push_back(it->second);
424  }
425  }
426  else if (inHits.size() > 0)
427  break;
428  }
429  for (unsigned int iShower = 0; iShower < showers.size(); ++iShower) {
430  const recob::Shower& shower = *showers[iShower];
431  recob::Track outTrack;
432  std::vector<art::Ptr<recob::Hit>> outHits;
433  trkmkr::OptionalOutputs optionals;
434  if (p_().options().produceTrackFitHitInfo()) optionals.initTrackFitInfos();
435  Point_t pos(shower.ShowerStart().X(), shower.ShowerStart().Y(), shower.ShowerStart().Z());
436  Vector_t dir(shower.Direction().X(), shower.Direction().Y(), shower.Direction().Z());
437  auto cov = SMatrixSym55();
438  auto pid = p_().options().pdgId();
439  auto mom = p_().options().pval();
440  bool fitok = kalmanFitter.fitTrack(detProp,
441  pos,
442  dir,
443  cov,
444  inHits,
445  std::vector<recob::TrajectoryPointFlags>(),
446  shower.ID(),
447  mom,
448  pid,
449  outTrack,
450  outHits,
451  optionals);
452  if (!fitok) continue;
453 
454  outputTracks->emplace_back(std::move(outTrack));
455  art::Ptr<recob::Track> aptr(tid, outputTracks->size() - 1, tidgetter);
456  unsigned int ip = 0;
457  for (auto const& trhit : outHits) {
458  // the fitter produces collections with 1-1 match between hits and point
459  recob::TrackHitMeta metadata(ip, -1);
460  outputHitsMeta->addSingle(aptr, trhit, metadata);
461  outputHits->addSingle(aptr, trhit);
462  if (p_().options().produceSpacePoints() && outputTracks->back().HasValidPoint(ip)) {
463  auto& tp = outputTracks->back().Trajectory().LocationAtPoint(ip);
464  double fXYZ[3] = {tp.X(), tp.Y(), tp.Z()};
465  double fErrXYZ[6] = {0};
466  recob::SpacePoint sp(fXYZ, fErrXYZ, -1.);
467  outputSpacePoints->emplace_back(std::move(sp));
468  art::Ptr<recob::SpacePoint> apsp(spid, outputSpacePoints->size() - 1, spidgetter);
469  outputHitSpacePointAssn->addSingle(trhit, apsp);
470  }
471  ip++;
472  }
473  outputPFAssn->addSingle(art::Ptr<recob::PFParticle>(inputPFParticle, iPF), aptr);
474  outputHitInfo->emplace_back(optionals.trackFitHitInfos());
475  }
476  }
477  }
478  e.put(std::move(outputTracks));
479  e.put(std::move(outputHitsMeta));
480  e.put(std::move(outputHits));
481  e.put(std::move(outputPFAssn));
482  if (p_().options().produceTrackFitHitInfo()) { e.put(std::move(outputHitInfo)); }
483  if (p_().options().produceSpacePoints()) {
484  e.put(std::move(outputSpacePoints));
485  e.put(std::move(outputHitSpacePointAssn));
486  }
487  }
488  else {
489 
490  art::ValidHandle<std::vector<recob::Track>> inputTracks =
491  e.getValidHandle<std::vector<recob::Track>>(trackInputTag);
492  auto const& tkHitsAssn = *e.getValidHandle<art::Assns<recob::Track, recob::Hit>>(trackInputTag);
493 
494  if (p_().options().pFromCalo()) {
495  trackCalo = std::make_unique<art::FindManyP<anab::Calorimetry>>(inputTracks, e, caloInputTag);
496  }
497 
498  if (p_().options().idFromCollection()) {
499  trackId = std::make_unique<art::FindManyP<anab::ParticleID>>(inputTracks, e, pidInputTag);
500  }
501 
502  for (unsigned int iTrack = 0; iTrack < inputTracks->size(); ++iTrack) {
503 
504  const recob::Track& track = inputTracks->at(iTrack);
505  art::Ptr<recob::Track> ptrack(inputTracks, iTrack);
506  const int pId = setPId(iTrack, trackId);
507  const double mom = setMomValue(ptrack, trackCalo, pMC, pId);
508  const bool flipDir = setDirFlip(track, mcdir);
509 
510  //this is not computationally optimal, but at least preserves the order unlike FindManyP
511  std::vector<art::Ptr<recob::Hit>> inHits;
512  for (auto it = tkHitsAssn.begin(); it != tkHitsAssn.end(); ++it) {
513  if (it->first == ptrack)
514  inHits.push_back(it->second);
515  else if (inHits.size() > 0)
516  break;
517  }
518 
519  recob::Track outTrack;
520  std::vector<art::Ptr<recob::Hit>> outHits;
521  trkmkr::OptionalOutputs optionals;
522  if (p_().options().produceTrackFitHitInfo()) optionals.initTrackFitInfos();
523  bool fitok = kalmanFitter.fitTrack(detProp,
524  track.Trajectory(),
525  track.ID(),
526  track.VertexCovarianceLocal5D(),
527  track.EndCovarianceLocal5D(),
528  inHits,
529  mom,
530  pId,
531  flipDir,
532  outTrack,
533  outHits,
534  optionals);
535  if (!fitok) continue;
536 
537  if (p_().options().keepInputTrajectoryPoints()) {
538  restoreInputPoints(track.Trajectory().Trajectory(), inHits, outTrack, outHits);
539  }
540 
541  outputTracks->emplace_back(std::move(outTrack));
542  art::Ptr<recob::Track> aptr(tid, outputTracks->size() - 1, tidgetter);
543  unsigned int ip = 0;
544  for (auto const& trhit : outHits) {
545  //the fitter produces collections with 1-1 match between hits and point
546  recob::TrackHitMeta metadata(ip, -1);
547  outputHitsMeta->addSingle(aptr, trhit, metadata);
548  outputHits->addSingle(aptr, trhit);
549  if (p_().options().produceSpacePoints() && outputTracks->back().HasValidPoint(ip)) {
550  auto& tp = outputTracks->back().Trajectory().LocationAtPoint(ip);
551  double fXYZ[3] = {tp.X(), tp.Y(), tp.Z()};
552  double fErrXYZ[6] = {0};
553  recob::SpacePoint sp(fXYZ, fErrXYZ, -1.);
554  outputSpacePoints->emplace_back(std::move(sp));
555  art::Ptr<recob::SpacePoint> apsp(spid, outputSpacePoints->size() - 1, spidgetter);
556  outputHitSpacePointAssn->addSingle(trhit, apsp);
557  }
558  ip++;
559  }
560  outputHitInfo->emplace_back(optionals.trackFitHitInfos());
561  }
562  e.put(std::move(outputTracks));
563  e.put(std::move(outputHitsMeta));
564  e.put(std::move(outputHits));
565  if (p_().options().produceTrackFitHitInfo()) { e.put(std::move(outputHitInfo)); }
566  if (p_().options().produceSpacePoints()) {
567  e.put(std::move(outputSpacePoints));
568  e.put(std::move(outputHitSpacePointAssn));
569  }
570  }
571 }
572 
573 void
575  const recob::Trajectory& track,
576  const std::vector<art::Ptr<recob::Hit>>& inHits,
577  recob::Track& outTrack,
578  std::vector<art::Ptr<recob::Hit>>& outHits) const
579 {
580  const auto np = outTrack.NumberTrajectoryPoints();
581  std::vector<Point_t> positions(np);
582  std::vector<Vector_t> momenta(np);
583  std::vector<recob::TrajectoryPointFlags> outFlags(np);
584  //
585  for (unsigned int p = 0; p < np; ++p) {
586  auto flag = outTrack.FlagsAtPoint(p);
587  auto mom = outTrack.VertexMomentum();
588  auto op = flag.fromHit();
589  positions[op] = track.LocationAtPoint(op);
590  momenta[op] = mom * track.DirectionAtPoint(op);
591  auto mask = flag.mask();
594  outFlags[op] = recob::TrajectoryPointFlags(op, mask);
595  }
596  auto covs = outTrack.Covariances();
597  outTrack = recob::Track(
598  recob::TrackTrajectory(std::move(positions), std::move(momenta), std::move(outFlags), true),
599  outTrack.ParticleId(),
600  outTrack.Chi2(),
601  outTrack.Ndof(),
602  std::move(covs.first),
603  std::move(covs.second),
604  outTrack.ID());
605  //
606  outHits.clear();
607  for (auto h : inHits)
608  outHits.push_back(h);
609 }
610 
611 double
613  art::Ptr<recob::Track> ptrack,
614  const std::unique_ptr<art::FindManyP<anab::Calorimetry>>& trackCalo,
615  const double pMC,
616  const int pId) const
617 {
618  double result = p_().options().pval();
619  if (p_().options().pFromMSChi2()) { result = tmc.GetMomentumMultiScatterChi2(ptrack); }
620  else if (p_().options().pFromLength()) {
621  result = tmc.GetTrackMomentum(ptrack->Length(), pId);
622  }
623  else if (p_().options().pFromCalo()) {
624  //take average energy from available views
625  const std::vector<art::Ptr<anab::Calorimetry>>& calo = trackCalo->at(ptrack.key());
626  double sumenergy = 0.;
627  int nviews = 0.;
628  for (auto caloit : calo) {
629  if (caloit->KineticEnergy() > 0.) {
630  sumenergy += caloit->KineticEnergy();
631  nviews += 1;
632  }
633  }
634  if (nviews != 0 && sumenergy != 0.) {
635  //protect against problematic cases
636  result = sumenergy / (nviews * 1000.);
637  }
638  }
639  else if (p_().options().pFromMC() && pMC > 0.) {
640  result = pMC;
641  }
642  return result;
643 }
644 
645 int
647  const unsigned int iTrack,
648  const std::unique_ptr<art::FindManyP<anab::ParticleID>>& trackId,
649  const int pfPid) const
650 {
651  /*
652  int result = p_().options().pdgId();
653  if (p_().options().trackFromPF() && p_().options().idFromPF()) { result = pfPid; }
654  else if (p_().options().idFromCollection()) {
655  //take the pdgId corresponding to the minimum chi2 (should we give preference to the majority? fixme)
656  double minChi2 = -1.;
657  for (auto idit : trackId->at(iTrack)) {
658  if (idit->MinChi2() > 0. && (minChi2 < 0. || idit->MinChi2() < minChi2)) {
659  result = idit->Pdg();
660  minChi2 = idit->MinChi2();
661  }
662  }
663  }
664  */
665  return -1;
666 }
667 
668 bool
670  const recob::Track& track,
671  TVector3& mcdir,
672  const std::vector<art::Ptr<recob::Vertex>>* vertices) const
673 {
674  bool result = false;
675  if (p_().options().alwaysInvertDir()) { return true; }
676  else if (p_().options().dirFromMC()) {
677  auto tdir = track.VertexDirection();
678  if ((mcdir.X() * tdir.X() + mcdir.Y() * tdir.Y() + mcdir.Z() * tdir.Z()) < 0.) result = true;
679  }
680  else if (p_().options().dirFromVec()) {
681  std::array<float, 3> dir = p_().options().dirVec();
682  auto tdir = track.VertexDirection();
683  if ((dir[0] * tdir.X() + dir[1] * tdir.Y() + dir[2] * tdir.Z()) < 0.) result = true;
684  }
685  else if (p_().options().trackFromPF() && p_().options().dirFromVtxPF() && vertices->size() > 0) {
686  //if track end is closer to first vertex then track vertex, flip direction
687  double xyz[3];
688  (*vertices)[0]->XYZ(xyz);
689  auto& tv = track.Trajectory().Vertex();
690  auto& te = track.Trajectory().End();
691  if (((xyz[0] - te.X()) * (xyz[0] - te.X()) + (xyz[1] - te.Y()) * (xyz[1] - te.Y()) +
692  (xyz[2] - te.Z()) * (xyz[2] - te.Z())) >
693  ((xyz[0] - tv.X()) * (xyz[0] - tv.X()) + (xyz[1] - tv.Y()) * (xyz[1] - tv.Y()) +
694  (xyz[2] - tv.Z()) * (xyz[2] - tv.Z())))
695  result = true;
696  }
697  return result;
698 }
699 
700 DEFINE_ART_MODULE(trkf::KalmanFilterFinalTrackFitter)
double VertexMomentum() const
Trajectory_t const & Trajectory() const
Returns the plain trajectory of this object.
Fit tracks using Kalman Filter fit+smooth.
void initTrackFitInfos()
initialize the output vector of TrackFitHitInfos
Definition: TrackMaker.h:161
ClusterModuleLabel join with tracks
static constexpr Flag_t NoPoint
The trajectory point is not defined.
fhicl::Table< TrackStatePropagator::Config > propagator
then echo unknown compiler flag
recob::tracking::Point_t Point_t
Definition: TrackState.h:18
recob::tracking::Vector_t Vector_t
Definition: TrackState.h:19
const recob::TrackTrajectory & Trajectory() const
Access to the stored recob::TrackTrajectory.
const TVector3 & Direction() const
Definition: Shower.h:189
Declaration of signal hit object.
pdgs p
Definition: selectors.fcl:22
recob::tracking::SMatrixSym55 SMatrixSym55
Definition: TrackState.h:15
size_t NumberTrajectoryPoints() const
Various functions related to the presence and the number of (valid) points.
Class to keep data related to recob::Hit associated with recob::Track.
Vector_t VertexDirection() const
Class for propagation of a trkf::TrackState to a recob::tracking::Plane.
process_name use argoneut_mc_hitfinder track
Data related to recob::Hit associated with recob::Track.The purpose is to collect several variables t...
Definition: TrackHitMeta.h:43
std::pair< SMatrixSym55, SMatrixSym55 > Covariances() const
process_name shower
Definition: cheaterreco.fcl:51
std::unique_ptr< art::FindManyP< recob::Vertex > > assocVertices
Vector_t DirectionAtPoint(size_t i) const
Computes and returns the direction of the trajectory at a point.
Definition: Trajectory.cxx:117
fhicl::Table< KalmanFilterFinalTrackFitter::Options > options
while getopts h
fhicl::Table< KalmanFilterFinalTrackFitter::Inputs > inputs
process_name can override from command line with o or output calo
Definition: pid.fcl:40
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
double setMomValue(art::Ptr< recob::Track > ptrack, const std::unique_ptr< art::FindManyP< anab::Calorimetry >> &trackCalo, const double pMC, const int pId) const
constexpr mask_t< EnumType > mask(EnumType bit, OtherBits...otherBits)
Returns a mask with all specified bits set.
A trajectory in space reconstructed from hits.
int setPId(const unsigned int iTrack, const std::unique_ptr< art::FindManyP< anab::ParticleID >> &trackId, const int pfPid=0) const
Point_t const & LocationAtPoint(size_t i) const
Returns the position at the specified trajectory point.
Definition: Trajectory.h:236
BEGIN_PROLOG vertical distance to the surface Name
std::unique_ptr< art::FindManyP< anab::ParticleID > > trackId
Declaration of cluster object.
Class def header for mctrack data container.
Provides recob::Track data product.
Point_t const & Vertex() const
Returns the position of the first valid point of the trajectory [cm].
int PdgCode() const
Definition: MCTrack.h:41
const TLorentzVector & Momentum() const
Definition: MCStep.h:38
tuple dir
Definition: dropbox.py:28
A trajectory in space reconstructed from hits.
Definition: Trajectory.h:67
KalmanFilterFinalTrackFitter & operator=(KalmanFilterFinalTrackFitter const &)=delete
int ID() const
Definition: Shower.h:187
const SMatrixSym55 & EndCovarianceLocal5D() const
std::vector< recob::TrackFitHitInfo > trackFitHitInfos()
get the output vector of TrackFitHitInfos by releasing and moving
Definition: TrackMaker.h:185
std::unique_ptr< art::FindManyP< anab::Calorimetry > > trackCalo
std::unique_ptr< art::FindManyP< recob::Shower > > assocShowers
Point_t const & End() const
Returns the position of the last valid point of the trajectory [cm].
const std::string & Process() const
Definition: MCTrack.h:43
then echo echo For and will not be changed by echo further linking echo echo B echo The symbol is in the uninitialized data multiple common symbols may appear with the echo same name If the symbol is defined the common echo symbols are treated as undefined references For more echo details on common see the discussion of warn common echo in *Note Linker options
do i e
const TVector3 & ShowerStart() const
Definition: Shower.h:192
PointFlags_t const & FlagsAtPoint(size_t i) const
const MCStep & Start() const
Definition: MCTrack.h:44
TrackCollectionProxyElement< TrackCollProxy > Track
Proxy to an element of a proxy collection of recob::Track objects.
const SMatrixSym55 & VertexCovarianceLocal5D() const
bool setDirFlip(const recob::Track &track, TVector3 &mcdir, const std::vector< art::Ptr< recob::Vertex >> *vertices=0) const
Struct holding optional TrackMaker outputs.
Definition: TrackMaker.h:125
Set of flags pertaining a point of the track.
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:
std::unique_ptr< art::FindManyP< recob::Track > > assocTracks
void restoreInputPoints(const recob::Trajectory &track, const std::vector< art::Ptr< recob::Hit >> &inHits, recob::Track &outTrack, std::vector< art::Ptr< recob::Hit >> &outHits) const