LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
PMAlgTrajFitter_module.cc
Go to the documentation of this file.
1 // Class: PMAlgTrajFitter
3 // Module Type: producer
4 // File: PMAlgTrajFitter_module.cc
5 // Author: D.Stefan (Dorota.Stefan@ncbj.gov.pl) and R.Sulej (Robert.Sulej@cern.ch), May 2015
6 //
7 // Creates 3D tracks using Projection Matching Algorithm, please see
8 // RecoAlg/ProjectionMatchingAlg.h for basics of the PMA algorithm and its settings.
9 //
10 // Progress:
11 // July 2016: fit-only module separated from PMAlgTrackMaker_module, common tracking
12 // functionality moved to algorithm class;
13 // note, that some part of vertexing can be still reasonable in this module:
14 // - use hierarchy of input PFP's to create vertices, join tracks, reoptimize
15 // - detect vertices/kinks on fitted trajectories
16 //
18 
25 #include "fhiclcpp/types/Atom.h"
26 #include "fhiclcpp/types/Table.h"
29 
30 // LArSoft includes
44 //#include "art/Persistency/Common/PtrMaker.h"
45 
48 
49 #include <memory>
50 
51 namespace trkf {
52 
54 public:
55 
56  struct Config {
57  using Name = fhicl::Name;
59 
61  Name("ProjectionMatchingAlg")
62  };
63 
65  Name("PMAlgFitting")
66  };
67 
69  Name("PMAlgVertexing")
70  };
71 
73  Name("HitModuleLabel"),
74  Comment("tag of unclustered hits, which were used to produce PFPs and clusters")
75  };
76 
78  Name("PfpModuleLabel"),
79  Comment("tag of the input PFParticles and associated clusters")
80  };
81 
83  Name("SaveOnlyBranchingVtx"),
84  Comment("use true to save only vertices interconnecting many tracks, otherwise vertex is added to the front of each track")
85  };
86 
88  Name("SavePmaNodes"),
89  Comment("save track nodes (only for algorithm development purposes)")
90  };
91  };
93 
94  explicit PMAlgTrajFitter(Parameters const& config);
95 
96  PMAlgTrajFitter(PMAlgTrajFitter const &) = delete;
97  PMAlgTrajFitter(PMAlgTrajFitter &&) = delete;
98  PMAlgTrajFitter & operator = (PMAlgTrajFitter const &) = delete;
100 
101  void produce(art::Event & e) override;
102 
103 private:
104  // ******************** fcl parameters ***********************
105  art::InputTag fHitModuleLabel; // tag for unclustered hit collection
106  art::InputTag fPfpModuleLabel; // tag for PFParticle and cluster collections
107 
111 
112  bool fSaveOnlyBranchingVtx; // for debugging, save only vertices which connect many tracks
113  bool fSavePmaNodes; // for debugging, save only track nodes
114 
115  // ********** instance names (collections, assns) ************
116  static const std::string kKinksName; // kinks on tracks
117  static const std::string kNodesName; // pma nodes
118 
119  // *********************** geometry **************************
121 };
122 // -------------------------------------------------------------
123 const std::string PMAlgTrajFitter::kKinksName = "kink";
124 const std::string PMAlgTrajFitter::kNodesName = "node";
125 // -------------------------------------------------------------
126 
128  fHitModuleLabel(config().HitModuleLabel()),
129  fPfpModuleLabel(config().PfpModuleLabel()),
130 
131  fPmaConfig(config().ProjectionMatchingAlg()),
132  fPmaFitterConfig(config().PMAlgFitting()),
133  fPmaVtxConfig(config().PMAlgVertexing()),
134 
136  fSavePmaNodes(config().SavePmaNodes())
137 {
138  produces< std::vector<recob::Track> >();
139  produces< std::vector<recob::SpacePoint> >();
140  produces< std::vector<recob::Vertex> >(); // no instance name for interaction vertices
141  produces< std::vector<recob::Vertex> >(kKinksName); // collection of kinks on tracks
142  produces< std::vector<recob::Vertex> >(kNodesName); // collection of pma nodes
143 
144  produces< art::Assns<recob::Track, recob::Hit> >(); // ****** REMEMBER to remove when FindMany improved ******
145  produces< art::Assns<recob::Track, recob::Hit, recob::TrackHitMeta> >();
146 
147  produces< art::Assns<recob::Track, recob::SpacePoint> >();
148  produces< art::Assns<recob::SpacePoint, recob::Hit> >();
149  produces< art::Assns<recob::Vertex, recob::Track> >(); // no instance name for assns of tracks to interaction vertices
150  produces< art::Assns<recob::Track, recob::Vertex> >(kKinksName); // assns of kinks to tracks
151 
152  produces< art::Assns<recob::PFParticle, recob::Track> >();
153 }
154 // ------------------------------------------------------
155 
157 {
158  // ---------------- Create data products ------------------
159  auto tracks = std::make_unique< std::vector<recob::Track> >();
160  auto allsp = std::make_unique< std::vector<recob::SpacePoint> >();
161  auto vtxs = std::make_unique< std::vector<recob::Vertex> >(); // interaction vertices
162  auto kinks = std::make_unique< std::vector<recob::Vertex> >(); // kinks on tracks (no new particles start in kinks)
163  auto nodes = std::make_unique< std::vector<recob::Vertex> >(); // pma nodes
164 
165  auto trk2hit_oldway = std::make_unique< art::Assns<recob::Track, recob::Hit> >(); // ****** REMEMBER to remove when FindMany improved ******
166  auto trk2hit = std::make_unique< art::Assns<recob::Track, recob::Hit, recob::TrackHitMeta> >();
167 
168  auto trk2sp = std::make_unique< art::Assns<recob::Track, recob::SpacePoint> >();
169 
170  auto sp2hit = std::make_unique< art::Assns<recob::SpacePoint, recob::Hit> >();
171  auto vtx2trk = std::make_unique< art::Assns<recob::Vertex, recob::Track> >(); // one or more tracks (particles) start in the vertex
172  auto trk2kink = std::make_unique< art::Assns<recob::Track, recob::Vertex> >(); // one or more kinks on the track
173 
174  auto pfp2trk = std::make_unique< art::Assns< recob::PFParticle, recob::Track> >();
175 
176  // ------------------- Collect inputs ---------------------
177  art::Handle< std::vector<recob::Hit> > allHitListHandle;
180  std::vector< art::Ptr<recob::Hit> > allhitlist;
181  if (!(evt.getByLabel(fHitModuleLabel, allHitListHandle) && // all hits used to make clusters and PFParticles
182  evt.getByLabel(fPfpModuleLabel, cluListHandle) && // clusters associated to PFParticles
183  evt.getByLabel(fPfpModuleLabel, pfparticleHandle))) // and finally PFParticles
184  {
185  throw cet::exception("PMAlgTrajFitter") << "Not all required data products found in the event." << std::endl;
186  }
187 
188  art::fill_ptr_vector(allhitlist, allHitListHandle);
189 
190  art::FindManyP< recob::Hit > hitsFromClusters(cluListHandle, evt, fPfpModuleLabel);
191  art::FindManyP< recob::Cluster > clustersFromPfps(pfparticleHandle, evt, fPfpModuleLabel);
192  art::FindManyP< recob::Vertex > vtxFromPfps(pfparticleHandle, evt, fPfpModuleLabel);
193 
194  // -------------- PMA Fitter for this event ---------------
195  auto pmalgFitter = pma::PMAlgFitter(allhitlist,
196  *cluListHandle, *pfparticleHandle,
197  hitsFromClusters, clustersFromPfps, vtxFromPfps,
199 
200  // ------------------ Do the job here: --------------------
201  int retCode = pmalgFitter.build();
202  // --------------------------------------------------------
203  switch (retCode)
204  {
205  case -2: mf::LogError("Summary") << "problem"; break;
206  case -1: mf::LogWarning("Summary") << "no input"; break;
207  case 0: mf::LogVerbatim("Summary") << "no tracks done"; break;
208  default:
209  if (retCode < 0) mf::LogVerbatim("Summary") << "unknown result";
210  else if (retCode == 1) mf::LogVerbatim("Summary") << retCode << " track ready";
211  else mf::LogVerbatim("Summary") << retCode << " tracks ready";
212  break;
213  }
214 
215  // ---------- Translate output to data products: ----------
216  auto const & result = pmalgFitter.result();
217  if (!result.empty()) // ok, there is something to save
218  {
219  size_t spStart = 0, spEnd = 0;
220  double sp_pos[3], sp_err[6];
221  for (size_t i = 0; i < 3; i++) sp_pos[i] = 1.0;
222  for (size_t i = 0; i < 6; i++) sp_err[i] = 1.0;
223 
224  // use the following to create PFParticle <--> Track associations;
225  std::map< size_t, std::vector< art::Ptr<recob::Track> > > pfPartToTrackVecMap;
226 
227  //auto const make_trkptr = art::PtrMaker<recob::Track>(evt, *this); // PtrMaker Step #1
228 
229  tracks->reserve(result.size());
230  for (size_t trkIndex = 0; trkIndex < result.size(); ++trkIndex)
231  {
232  pma::Track3D* trk = result[trkIndex].Track();
233 
234  trk->SelectHits(); // just in case, set all to enabled
235  unsigned int itpc = trk->FrontTPC(), icryo = trk->FrontCryo();
236  if (fGeom->TPC(itpc, icryo).HasPlane(geo::kU)) trk->CompleteMissingWires(geo::kU);
237  if (fGeom->TPC(itpc, icryo).HasPlane(geo::kV)) trk->CompleteMissingWires(geo::kV);
238  if (fGeom->TPC(itpc, icryo).HasPlane(geo::kZ)) trk->CompleteMissingWires(geo::kZ);
239 
240  //gc: make sure no tracks are created with less than 2 points
241  if (trk->size()<2) continue;
242 
243  tracks->push_back(pma::convertFrom(*trk, trkIndex));
244 
245  //auto const trkPtr = make_trkptr(tracks->size() - 1); // PtrMaker Step #2
246 
247  size_t trkIdx = tracks->size() - 1; // stuff for assns:
248  art::ProductID trkId = getProductID< std::vector<recob::Track> >();
249  art::Ptr<recob::Track> trkPtr(trkId, trkIdx, evt.productGetter(trkId));
250 
251  //gc: save associated hits in the same order as trajectory points
252  for (size_t h = 0, cnt = 0; h < trk->size(); h++)
253  {
254  pma::Hit3D* h3d = (*trk)[h];
255  if (!h3d->IsEnabled()) continue;
256 
257  recob::TrackHitMeta metadata(cnt++, h3d->Dx());
258  trk2hit->addSingle(trkPtr, h3d->Hit2DPtr(), metadata);
259  trk2hit_oldway->addSingle(trkPtr, h3d->Hit2DPtr()); // ****** REMEMBER to remove when FindMany improved ******
260  }
261 
263  spStart = allsp->size();
264  for (size_t h = 0; h < trk->size(); ++h)
265  {
266  pma::Hit3D* h3d = (*trk)[h];
267  if (!h3d->IsEnabled()) continue;
268 
269  double hx = h3d->Point3D().X();
270  double hy = h3d->Point3D().Y();
271  double hz = h3d->Point3D().Z();
272 
273  if ((h == 0) ||
274  (std::fabs(sp_pos[0] - hx) > 1.0e-5) ||
275  (std::fabs(sp_pos[1] - hy) > 1.0e-5) ||
276  (std::fabs(sp_pos[2] - hz) > 1.0e-5))
277  {
278  if (sp_hits.size()) // hits assigned to the previous sp
279  {
280  util::CreateAssn(*this, evt, *allsp, sp_hits, *sp2hit);
281  sp_hits.clear();
282  }
283  sp_pos[0] = hx; sp_pos[1] = hy; sp_pos[2] = hz;
284  allsp->push_back(recob::SpacePoint(sp_pos, sp_err, 1.0));
285  }
286  sp_hits.push_back(h3d->Hit2DPtr());
287  }
288 
289  if (sp_hits.size()) // hits assigned to the last sp
290  {
291  util::CreateAssn(*this, evt, *allsp, sp_hits, *sp2hit);
292  }
293  spEnd = allsp->size();
294 
295  if (spEnd > spStart) util::CreateAssn(*this, evt, *tracks, *allsp, *trk2sp, spStart, spEnd);
296 
297  // if there is a PFParticle collection then recover PFParticle and add info to map
298  if (result[trkIndex].Key() > -1)
299  {
300  size_t trackIdx = tracks->size() - 1;
301  art::ProductID trackId = getProductID< std::vector<recob::Track> >();
302  art::Ptr<recob::Track> trackPtr(trackId, trackIdx, evt.productGetter(trackId));
303  pfPartToTrackVecMap[result[trkIndex].Key()].push_back(trackPtr);
304  }
305  }
306 
307  auto vid = getProductID< std::vector<recob::Vertex> >();
308  auto kid = getProductID< std::vector<recob::Vertex> >(kKinksName);
309  auto const* kinkGetter = evt.productGetter(kid);
310 
311  auto tid = getProductID< std::vector<recob::Track> >();
312  auto const* trkGetter = evt.productGetter(tid);
313 
314  auto vsel = pmalgFitter.getVertices(fSaveOnlyBranchingVtx); // vtx pos's with vector of connected track idxs
315  auto ksel = pmalgFitter.getKinks(); // pairs of kink position - associated track idx
316  std::map< size_t, art::Ptr<recob::Vertex> > frontVtxs; // front vertex ptr for each track index
317 
318  if (fPmaFitterConfig.RunVertexing()) // save vertices and vtx-trk assns
319  {
320  double xyz[3];
321  for (auto const & v : vsel)
322  {
323  xyz[0] = v.first.X(); xyz[1] = v.first.Y(); xyz[2] = v.first.Z();
324  mf::LogVerbatim("Summary")
325  << " vtx:" << xyz[0] << ":" << xyz[1] << ":" << xyz[2]
326  << " (" << v.second.size() << " tracks)";
327 
328  size_t vidx = vtxs->size();
329  vtxs->push_back(recob::Vertex(xyz, vidx));
330 
331  art::Ptr<recob::Vertex> vptr(vid, vidx, evt.productGetter(vid));
332  if (vptr.isNull()) mf::LogWarning("PMAlgTrajFitter") << "Vertex ptr is null.";
333  if (!v.second.empty())
334  {
335  for (const auto & vEntry : v.second)
336  {
337  size_t tidx = vEntry.first;
338  bool isFront = vEntry.second;
339 
340  if (isFront) frontVtxs[tidx] = vptr; // keep ptr of the front vtx
341 
342  art::Ptr<recob::Track> tptr(tid, tidx, trkGetter);
343  vtx2trk->addSingle(vptr, tptr);
344  }
345  }
346  else mf::LogWarning("PMAlgTrajFitter") << "No tracks found at this vertex.";
347  }
348  mf::LogVerbatim("Summary") << vtxs->size() << " vertices ready";
349 
350  for (auto const & k : ksel)
351  {
352  xyz[0] = k.first.X(); xyz[1] = k.first.Y(); xyz[2] = k.first.Z();
353  mf::LogVerbatim("Summary") << " kink:" << xyz[0] << ":" << xyz[1] << ":" << xyz[2];
354 
355  size_t kidx = kinks->size();
356  size_t tidx = k.second; // track idx on which this kink was found
357 
358  kinks->push_back(recob::Vertex(xyz, tidx)); // save index of track (will have color of trk in evd)
359 
360  art::Ptr<recob::Track> tptr(tid, tidx, trkGetter);
361  art::Ptr<recob::Vertex> kptr(kid, kidx, kinkGetter);
362  trk2kink->addSingle(tptr, kptr);
363  }
364  mf::LogVerbatim("Summary") << ksel.size() << " kinks ready";
365  }
366 
367  if (fSavePmaNodes)
368  {
369  double xyz[3];
370  for (size_t t = 0; t < result.size(); ++t)
371  {
372  auto const & trk = *(result[t].Track());
373  for (auto const * node : trk.Nodes())
374  {
375  xyz[0] = node->Point3D().X(); xyz[1] = node->Point3D().Y(); xyz[2] = node->Point3D().Z();
376  nodes->push_back(recob::Vertex(xyz, t));
377  }
378  }
379  }
380 
381  for (const auto & pfParticleItr : pfPartToTrackVecMap)
382  {
383  art::Ptr<recob::PFParticle> pfParticle(pfparticleHandle, pfParticleItr.first);
384  mf::LogVerbatim("PMAlgTrajFitter") << "PFParticle key: " << pfParticle.key()
385  << ", self: " << pfParticle->Self() << ", #tracks: " << pfParticleItr.second.size();
386 
387  if (!pfParticle.isNull()) util::CreateAssn(*this, evt, pfParticle, pfParticleItr.second, *pfp2trk);
388  else mf::LogError("PMAlgTrajFitter") << "Error in PFParticle lookup, pfparticle index: "
389  << pfParticleItr.first << ", key: " << pfParticle.key();
390  }
391  }
392 
393  evt.put(std::move(tracks));
394  evt.put(std::move(allsp));
395  evt.put(std::move(vtxs));
396  evt.put(std::move(kinks), kKinksName);
397  evt.put(std::move(nodes), kNodesName);
398 
399  evt.put(std::move(trk2hit_oldway)); // ****** REMEMBER to remove when FindMany improved ******
400  evt.put(std::move(trk2hit));
401  evt.put(std::move(trk2sp));
402 
403  evt.put(std::move(sp2hit));
404  evt.put(std::move(vtx2trk));
405  evt.put(std::move(trk2kink), kKinksName);
406 
407  evt.put(std::move(pfp2trk));
408 }
409 // ------------------------------------------------------
410 // ------------------------------------------------------
411 // ------------------------------------------------------
412 
414 
415 } // namespace trkf
416 
fhicl::Table< pma::ProjectionMatchingAlg::Config > ProjectionMatchingAlg
key_type key() const
Definition: Ptr.h:356
bool SelectHits(float fraction=1.0F)
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool HasPlane(unsigned int iplane) const
Returns whether a plane with index iplane is present in this TPC.
Definition: TPCGeo.h:155
size_t Self() const
Returns the index of this particle.
Definition: PFParticle.h:92
recob::Track convertFrom(const pma::Track3D &src, unsigned int tidx, int pdg=0)
unsigned int FrontTPC(void) const
Definition: PmaTrack3D.h:104
Planes which measure V.
Definition: geo_types.h:77
bool IsEnabled(void) const
Definition: PmaHit3D.h:82
Declaration of signal hit object.
Class to keep data related to recob::Hit associated with recob::Track.
Planes which measure Z direction.
Definition: geo_types.h:79
art::ServiceHandle< geo::Geometry > fGeom
Data related to recob::Hit associated with recob::Track.The purpose is to collect several variables t...
Definition: TrackHitMeta.h:43
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
EDProductGetter const * productGetter(ProductID const) const
Definition: Event.cc:64
art::Ptr< recob::Hit > const & Hit2DPtr(void) const
Definition: PmaHit3D.h:46
Definition of vertex object for LArSoft.
Definition: Vertex.h:35
void produce(art::Event &e) override
#define nodes
ProductID put(std::unique_ptr< PROD > &&product)
Definition: Event.h:102
Planes which measure U.
Definition: geo_types.h:76
fhicl::Table< pma::PMAlgFitter::Config > PMAlgFitting
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:42
void push_back(Ptr< U > const &p)
Definition: PtrVector.h:441
fhicl::Atom< bool > RunVertexing
size_t CompleteMissingWires(unsigned int view)
bool CreateAssn(PRODUCER const &prod, art::Event &evt, std::vector< T > const &a, art::Ptr< U > const &b, art::Assns< U, T > &assn, std::string a_instance, size_t indx=UINT_MAX)
Creates a single one-to-one association.
fhicl::Table< pma::PMAlgVertexing::Config > PMAlgVertexing
Declaration of cluster object.
Provides recob::Track data product.
unsigned int FrontCryo(void) const
Definition: PmaTrack3D.h:105
size_type size() const
Definition: PtrVector.h:308
Encapsulate the geometry of a wire.
TVector3 const & Point3D(void) const
Definition: PmaHit3D.h:48
pma::PMAlgVertexing::Config fPmaVtxConfig
Implementation of the Projection Matching Algorithm.
static const std::string kNodesName
Encapsulate the construction of a single detector plane.
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
Definition: DataViewImpl.h:344
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
pma::ProjectionMatchingAlg::Config fPmaConfig
double Dx(void) const
Definition: PmaHit3D.h:67
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
bool isNull() const
Definition: Ptr.h:328
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:464
Float_t e
Definition: plot.C:34
size_t size() const
Definition: PmaTrack3D.h:76
PMAlgTrajFitter(Parameters const &config)
static const std::string kKinksName
fhicl::Atom< art::InputTag > HitModuleLabel
void clear()
Definition: PtrVector.h:537
PMAlgTrajFitter & operator=(PMAlgTrajFitter const &)=delete
art framework interface to geometry description
pma::PMAlgFitter::Config fPmaFitterConfig
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
Encapsulate the construction of a single detector plane.
fhicl::Atom< art::InputTag > PfpModuleLabel