LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
PMAlgTrackMaker_module.cc
Go to the documentation of this file.
1 // Class: PMAlgTrackMaker
3 // Module Type: producer
4 // File: PMAlgTrackMaker_module.cc
5 // Authors D.Stefan (Dorota.Stefan@ncbj.gov.pl), from DUNE, CERN/NCBJ, since May 2015
6 // R.Sulej (Robert.Sulej@cern.ch), from DUNE, FNAL/NCBJ, since May 2015
7 // L.Whitehead (leigh.howard.whitehead@cern.ch), from DUNE, CERN, since Jan 2017
8 //
9 // Creates 3D tracks and vertices using Projection Matching Algorithm,
10 // please see RecoAlg/ProjectionMatchingAlg.h for basics of the PMA algorithm and its settings.
11 //
12 // Progress:
13 // May-June 2015: track finding and validation, growing tracks by iterative merging of matching
14 // clusters, no attempts to build multi-track structures, however cosmic tracking
15 // works fine as they are sets of independent tracks
16 // June-July 2015: merging track parts within a single tpc and stitching tracks across tpc's
17 // August 2015: optimization of track-vertex structures (so 3D vertices are also produced)
18 // November 2015: use track-shower splitting at 2D level, then tag low-E EM cascades in 3D
19 // note: the splitter is not finished and not as good as we want it
20 // January 2016: output of track-vertex finding as a tree of PFParticles, refined vertexing
21 // code, put vertex at front of each track, flip whole track structures to
22 // selected, direction (beam/down/dQdx), use any pattern reco stored in
23 // PFParticles as a source of associated clusters
24 // Mar-Apr 2016: kinks finding, EM shower direction reconstructed for PFPaarticles tagged as
25 // electrons
26 // July 2016: redesign module: extract trajectory fitting-only to separate module, move
27 // tracking functionality to algorithm classes
28 // ~Jan-May 2017: track stitching on APA and CPA, cosmics tagging
29 // July 2017: validation on 2D ADC image
30 //
32 
38 #include "art_root_io/TFileService.h"
40 #include "fhiclcpp/types/Atom.h"
41 #include "fhiclcpp/types/Table.h"
43 
44 // LArSoft includes
64 
65 #include <memory>
66 
67 #include "TH1F.h"
68 
69 namespace trkf {
70 
72  public:
73  struct Config {
74  using Name = fhicl::Name;
76 
78  Name("ProjectionMatchingAlg")};
79 
81 
83 
85 
87 
89  Name("SaveOnlyBranchingVtx"),
90  Comment("use true to save only vertices interconnecting many tracks, otherwise vertex is "
91  "added to the front of each track")};
92 
94  Name("SavePmaNodes"),
95  Comment("save track nodes (only for algorithm development purposes)")};
96 
98  Name("HitModuleLabel"),
99  Comment("tag of unclustered hits, which were used to validate tracks")};
100 
102  Comment("tag of recob::Wire producer.")};
103 
105  Name("ClusterModuleLabel"),
106  Comment("tag of cluster collection, these clusters are used for track building")};
107 
109  Name("EmClusterModuleLabel"),
110  Comment("EM-like clusters, will be excluded from tracking if provided")};
111  };
113 
114  explicit PMAlgTrackMaker(Parameters const& config);
115 
116  PMAlgTrackMaker(PMAlgTrackMaker const&) = delete;
117  PMAlgTrackMaker(PMAlgTrackMaker&&) = delete;
118  PMAlgTrackMaker& operator=(PMAlgTrackMaker const&) = delete;
120 
121  private:
122  void produce(art::Event& e) override;
123 
124  // will try to get EM- and track-like values from various lenght MVA vectors
125  template <size_t N>
126  bool init(const art::Event& evt, pma::PMAlgTracker& pmalgTracker) const;
127 
128  // calculate EM/track value for hits in track, in its best 2D projection
129  // (tracks are built starting from track-like cluster, some electrons
130  // still may look track-like)
131  template <size_t N>
132  int getPdgFromCnnOnHits(const art::Event& evt, const pma::Track3D& trk) const;
133 
134  // convert to a vector of LArSoft's cosmic tags
135  std::vector<anab::CosmicTagID_t> getCosmicTag(const pma::Track3D::ETag pmaTag) const;
136 
137  // ******************** fcl parameters **********************
138  art::InputTag fHitModuleLabel; // tag for hits collection (used for trk validation)
139  art::InputTag fWireModuleLabel; // tag for recob::Wire collection (used for trk validation)
140  art::InputTag fCluModuleLabel; // tag for input cluster collection
141  art::InputTag fEmModuleLabel; // tag for em-like cluster collection
142 
148 
149  bool fSaveOnlyBranchingVtx; // for debugging, save only vertices which connect many tracks
150  bool fSavePmaNodes; // for debugging, save only track nodes
151 
152  // ********** instance names (collections, assns) ************
153  static const std::string kKinksName; // kinks on tracks
154  static const std::string kNodesName; // pma nodes
155 
156  // *********************** geometry **************************
158 
159  // histograms created only for the calibration of the ADC-based track validation mode
161  };
162  // -------------------------------------------------------------
163  const std::string PMAlgTrackMaker::kKinksName = "kink";
164  const std::string PMAlgTrackMaker::kNodesName = "node";
165  // -------------------------------------------------------------
166 
168  : EDProducer{config}
169  , fHitModuleLabel(config().HitModuleLabel())
170  , fWireModuleLabel(config().WireModuleLabel())
171  , fCluModuleLabel(config().ClusterModuleLabel())
172  , fEmModuleLabel(config().EmClusterModuleLabel())
173  , fPmaConfig(config().ProjectionMatchingAlg())
174  , fPmaTrackerConfig(config().PMAlgTracking())
175  , fPmaTaggingConfig(config().PMAlgCosmicTagging())
176  , fPmaVtxConfig(config().PMAlgVertexing())
177  , fPmaStitchConfig(config().PMAlgStitching())
178  , fSaveOnlyBranchingVtx(config().SaveOnlyBranchingVtx())
179  , fSavePmaNodes(config().SavePmaNodes())
181  {
182  produces<std::vector<recob::Track>>();
183  produces<std::vector<recob::SpacePoint>>();
184  produces<std::vector<recob::Vertex>>(); // no instance name for interaction vertices
185  produces<std::vector<recob::Vertex>>(kKinksName); // collection of kinks on tracks
186  produces<std::vector<recob::Vertex>>(kNodesName); // collection of pma nodes
187  produces<std::vector<anab::T0>>();
188  produces<std::vector<anab::CosmicTag>>(); // Cosmic ray tags
189 
191  recob::Hit>>(); // ****** REMEMBER to remove when FindMany improved ******
192  produces<art::Assns<recob::Track, recob::Hit, recob::TrackHitMeta>>();
193 
194  produces<art::Assns<recob::Track, recob::SpacePoint>>();
195  produces<art::Assns<recob::SpacePoint, recob::Hit>>();
196  produces<
198  recob::Track>>(); // no instance name for assns of tracks to interaction vertices
199  produces<art::Assns<recob::Track, recob::Vertex>>(kKinksName); // assns of kinks to tracks
200  produces<art::Assns<recob::Track, anab::T0>>();
201  produces<art::Assns<recob::Track, anab::CosmicTag>>(); // Cosmic ray tags associated to tracks
202 
203  produces<std::vector<recob::PFParticle>>();
204  produces<art::Assns<recob::PFParticle, recob::Cluster>>();
205  produces<art::Assns<recob::PFParticle, recob::Vertex>>();
206  produces<art::Assns<recob::PFParticle, recob::Track>>();
207 
208  if (fPmaTrackerConfig.Validation() == "calib") // create histograms only in the calibration mode
209  {
211  for (size_t p = 0; p < fGeom->MaxPlanes(); ++p) {
212  std::ostringstream ss1;
213  ss1 << "adc_plane_" << p;
214  fAdcInPassingPoints.push_back(tfs->make<TH1F>(
215  (ss1.str() + "_passing").c_str(), "max adc around the point on track", 100., 0., 5.));
216  fAdcInRejectedPoints.push_back(tfs->make<TH1F>(
217  (ss1.str() + "_rejected").c_str(), "max adc around spurious point ", 100., 0., 5.));
218  }
219  }
220  }
221  // ------------------------------------------------------
222 
223  template <size_t N>
225  {
226  int pdg = 0;
229  if (hitResults) {
230  int trkLikeIdx = hitResults->getIndex("track");
231  int emLikeIdx = hitResults->getIndex("em");
232  if ((trkLikeIdx < 0) || (emLikeIdx < 0)) {
233  throw cet::exception("PMAlgTrackMaker")
234  << "No em/track labeled columns in MVA data products." << std::endl;
235  }
236 
237  size_t nh[3] = {0, 0, 0};
238  for (size_t hidx = 0; hidx < trk.size(); ++hidx) {
239  ++nh[trk[hidx]->View2D()];
240  }
241 
242  size_t best_view = 2; // collection
243  if ((nh[0] >= nh[1]) && (nh[0] > 1.25 * nh[2])) best_view = 0; // ind1
244  if ((nh[1] >= nh[0]) && (nh[1] > 1.25 * nh[2])) best_view = 1; // ind2
245 
246  std::vector<art::Ptr<recob::Hit>> trkHitPtrList;
247  trkHitPtrList.reserve(nh[best_view]);
248  for (size_t hidx = 0; hidx < trk.size(); ++hidx) {
249  if (trk[hidx]->View2D() == best_view) {
250  trkHitPtrList.emplace_back(trk[hidx]->Hit2DPtr());
251  }
252  }
253  auto vout = hitResults->getOutput(trkHitPtrList);
254  double trk_like = -1, trk_or_em = vout[trkLikeIdx] + vout[emLikeIdx];
255  if (trk_or_em > 0) {
256  trk_like = vout[trkLikeIdx] / trk_or_em;
257  if (trk_like < fPmaTrackerConfig.TrackLikeThreshold()) pdg = 11; // tag if EM-like
258  // (don't set pdg for track-like, for the moment don't like the idea of using "13")
259  }
260  //std::cout << "trk:" << best_view << ":" << trk.size() << ":" << trkHitPtrList.size() << " p=" << trk_like << std::endl;
261  }
262  }
263  return pdg;
264  }
265 
266  template <size_t N>
267  bool PMAlgTrackMaker::init(const art::Event& evt, pma::PMAlgTracker& pmalgTracker) const
268  {
270  if (!cluResults) { return false; }
271 
272  int trkLikeIdx = cluResults->getIndex("track");
273  int emLikeIdx = cluResults->getIndex("em");
274  if ((trkLikeIdx < 0) || (emLikeIdx < 0)) { return false; }
275 
276  const art::FindManyP<recob::Hit> hitsFromClusters(
277  cluResults->dataHandle(), evt, cluResults->dataTag());
278  const auto& cnnOuts = cluResults->outputs();
279  std::vector<float> trackLike(cnnOuts.size());
280  for (size_t i = 0; i < cnnOuts.size(); ++i) {
281  double trkOrEm = cnnOuts[i][trkLikeIdx] + cnnOuts[i][emLikeIdx];
282  if (trkOrEm > 0) { trackLike[i] = cnnOuts[i][trkLikeIdx] / trkOrEm; }
283  else {
284  trackLike[i] = 0;
285  }
286  }
287  pmalgTracker.init(hitsFromClusters, trackLike);
288  return true;
289  }
290 
291  std::vector<anab::CosmicTagID_t> PMAlgTrackMaker::getCosmicTag(
292  const pma::Track3D::ETag pmaTag) const
293  {
294  std::vector<anab::CosmicTagID_t> anabTags;
295 
297  anabTags.push_back(anab::CosmicTagID_t::kOutsideDrift_Partial);
298  }
301  }
302  if (pmaTag & pma::Track3D::kBeamIncompatible) {
304  }
305  if (pmaTag & pma::Track3D::kGeometry_XX) {
306  anabTags.push_back(anab::CosmicTagID_t::kGeometry_XX);
307  }
308  if (pmaTag & pma::Track3D::kGeometry_YY) {
309  anabTags.push_back(anab::CosmicTagID_t::kGeometry_YY);
310  }
311  if (pmaTag & pma::Track3D::kGeometry_ZZ) {
312  anabTags.push_back(anab::CosmicTagID_t::kGeometry_ZZ);
313  }
314  if (pmaTag & pma::Track3D::kGeometry_YZ) {
315  anabTags.push_back(anab::CosmicTagID_t::kGeometry_YZ);
316  }
317  if (pmaTag & pma::Track3D::kGeometry_Y) {
318  anabTags.push_back(anab::CosmicTagID_t::kGeometry_Y);
319  }
320 
321  if (anabTags.empty()) { anabTags.push_back(anab::CosmicTagID_t::kUnknown); }
322 
323  return anabTags;
324  }
325 
327  {
328  // ---------------- Create data products --------------------------
329  auto tracks = std::make_unique<std::vector<recob::Track>>();
330  auto allsp = std::make_unique<std::vector<recob::SpacePoint>>();
331  auto vtxs = std::make_unique<std::vector<recob::Vertex>>(); // interaction vertices
332  auto kinks = std::make_unique<
333  std::vector<recob::Vertex>>(); // kinks on tracks (no new particles start in kinks)
334  auto nodes = std::make_unique<std::vector<recob::Vertex>>(); // pma nodes
335  auto t0s = std::make_unique<std::vector<anab::T0>>();
336  auto cosmicTags = std::make_unique<std::vector<anab::CosmicTag>>();
337 
338  auto trk2hit_oldway = std::make_unique<
340  recob::Hit>>(); // ****** REMEMBER to remove when FindMany improved ******
341  auto trk2hit = std::make_unique<art::Assns<recob::Track, recob::Hit, recob::TrackHitMeta>>();
342 
343  auto trk2sp = std::make_unique<art::Assns<recob::Track, recob::SpacePoint>>();
344  auto trk2t0 = std::make_unique<art::Assns<recob::Track, anab::T0>>();
345  auto trk2ct = std::make_unique<art::Assns<recob::Track, anab::CosmicTag>>();
346 
347  auto sp2hit = std::make_unique<art::Assns<recob::SpacePoint, recob::Hit>>();
348  auto vtx2trk = std::make_unique<
350  recob::Track>>(); // one or more tracks (particles) start in the vertex
351  auto trk2kink =
352  std::make_unique<art::Assns<recob::Track, recob::Vertex>>(); // one or more kinks on the track
353 
354  auto pfps = std::make_unique<std::vector<recob::PFParticle>>();
355 
356  auto pfp2clu = std::make_unique<art::Assns<recob::PFParticle, recob::Cluster>>();
357  auto pfp2vtx = std::make_unique<art::Assns<recob::PFParticle, recob::Vertex>>();
358  auto pfp2trk = std::make_unique<art::Assns<recob::PFParticle, recob::Track>>();
359 
360  // --------------------- Wires & Hits -----------------------------
361  auto wireHandle = evt.getValidHandle<std::vector<recob::Wire>>(fWireModuleLabel);
362  auto allHitListHandle = evt.getValidHandle<std::vector<recob::Hit>>(fHitModuleLabel);
363  std::vector<art::Ptr<recob::Hit>> allhitlist;
364  art::fill_ptr_vector(allhitlist, allHitListHandle);
365 
366  // -------------- PMA Tracker for this event ----------------------
367  auto pmalgTracker = pma::PMAlgTracker(allhitlist,
368  *wireHandle,
369  fPmaConfig,
376 
377  size_t mvaLength = 0;
378  if (fEmModuleLabel != "") // ----------- Exclude EM parts ---------
379  {
380  auto cluListHandle = evt.getValidHandle<std::vector<recob::Cluster>>(fCluModuleLabel);
381  auto splitCluHandle = evt.getValidHandle<std::vector<recob::Cluster>>(fEmModuleLabel);
382 
383  art::FindManyP<recob::Hit> hitsFromClusters(cluListHandle, evt, fCluModuleLabel);
384  art::FindManyP<recob::Hit> hitsFromEmParts(splitCluHandle, evt, fEmModuleLabel);
385  pmalgTracker.init(hitsFromClusters, hitsFromEmParts);
386  }
387  else if (fPmaTrackerConfig.TrackLikeThreshold() > 0) // --- CNN EM/trk separation ----
388  {
389  // try to dig out 4- or 3-output MVA data product
390  if (init<4>(evt, pmalgTracker)) { mvaLength = 4; } // e.g.: EM / track / Michel / none
391  else if (init<3>(evt, pmalgTracker)) {
392  mvaLength = 3;
393  } // e.g.: EM / track / none
394  else if (init<2>(evt, pmalgTracker)) {
395  mvaLength = 2;
396  } // just EM / track (LArIAT starts with this style)
397  else {
398  throw cet::exception("PMAlgTrackMaker") << "No EM/track MVA data products." << std::endl;
399  }
400  }
401  else // ------------------------ Use ALL clusters -----------------
402  {
403  auto cluListHandle = evt.getValidHandle<std::vector<recob::Cluster>>(fCluModuleLabel);
404  art::FindManyP<recob::Hit> hitsFromClusters(cluListHandle, evt, fCluModuleLabel);
405  pmalgTracker.init(hitsFromClusters);
406  }
407 
408  // ------------------ Do the job here: ----------------------------
409  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
410  auto const detProp =
412  int retCode = pmalgTracker.build(clockData, detProp);
413  // ----------------------------------------------------------------
414  switch (retCode) {
415  case -2: mf::LogError("Summary") << "problem"; break;
416  case -1: mf::LogWarning("Summary") << "no input"; break;
417  case 0: mf::LogVerbatim("Summary") << "no tracks done"; break;
418  default:
419  if (retCode < 0)
420  mf::LogVerbatim("Summary") << "unknown result";
421  else if (retCode == 1)
422  mf::LogVerbatim("Summary") << retCode << " track ready";
423  else
424  mf::LogVerbatim("Summary") << retCode << " tracks ready";
425  break;
426  }
427 
428  // ---------- Translate output to data products: ------------------
429  auto const& result = pmalgTracker.result();
430  if (!result.empty()) // ok, there is something to save
431  {
432  size_t spStart = 0, spEnd = 0;
433  double sp_pos[3], sp_err[6];
434  for (size_t i = 0; i < 3; ++i)
435  sp_pos[i] = 0.0;
436  for (size_t i = 0; i < 6; ++i)
437  sp_err[i] = 1.0;
438 
439  auto const make_pfpptr = art::PtrMaker<recob::PFParticle>(evt);
440  auto const make_trkptr = art::PtrMaker<recob::Track>(evt); // PtrMaker Step #1
441  auto const make_vtxptr = art::PtrMaker<recob::Vertex>(evt);
442  auto const make_kinkptr = art::PtrMaker<recob::Vertex>(evt, kKinksName);
443  auto const make_t0ptr = art::PtrMaker<anab::T0>(evt);
444  auto const make_ctptr = art::PtrMaker<anab::CosmicTag>(evt);
445 
446  tracks->reserve(result.size());
447  for (size_t trkIndex = 0; trkIndex < result.size(); ++trkIndex) {
448  pma::Track3D* trk = result[trkIndex].Track();
449 
450  trk->SelectHits(); // just in case, set all to enabled
451  unsigned int itpc = trk->FrontTPC(), icryo = trk->FrontCryo();
452  pma::dedx_map dedx_tmp;
453  auto const& tpc = fGeom->TPC(geo::TPCID(icryo, itpc));
454  if (tpc.HasPlane(geo::kU)) {
455  trk->CompleteMissingWires(detProp, geo::kU);
456  trk->GetRawdEdxSequence(dedx_tmp, geo::kU, 1);
457  }
458  if (tpc.HasPlane(geo::kV)) {
459  trk->CompleteMissingWires(detProp, geo::kV);
460  trk->GetRawdEdxSequence(dedx_tmp, geo::kV, 1);
461  }
462  if (tpc.HasPlane(geo::kX)) {
463  trk->CompleteMissingWires(detProp, geo::kX);
464  trk->GetRawdEdxSequence(dedx_tmp, geo::kX, 1);
465  }
466  if (tpc.HasPlane(geo::kY)) {
467  trk->CompleteMissingWires(detProp, geo::kY);
468  trk->GetRawdEdxSequence(dedx_tmp, geo::kY, 1);
469  }
470  if (tpc.HasPlane(geo::kZ)) {
471  trk->CompleteMissingWires(detProp, geo::kZ);
472  trk->GetRawdEdxSequence(dedx_tmp, geo::kZ, 1);
473  }
474 
475  //gc: make sure no tracks are created with less than 2 points
476  if (trk->size() < 2) continue;
477 
478  int pdg = 0;
479  if (mvaLength == 4)
480  pdg = getPdgFromCnnOnHits<4>(evt, *(result[trkIndex].Track()));
481  else if (mvaLength == 3)
482  pdg = getPdgFromCnnOnHits<3>(evt, *(result[trkIndex].Track()));
483  else if (mvaLength == 2)
484  pdg = getPdgFromCnnOnHits<2>(evt, *(result[trkIndex].Track()));
485  //else mf::LogInfo("PMAlgTrackMaker") << "Not using PID from CNN.";
486 
487  tracks->push_back(pma::convertFrom(*trk, trkIndex, pdg));
488 
489  auto const trkPtr = make_trkptr(tracks->size() - 1); // PtrMaker Step #2
490 
491  if (trk->HasT0()) {
492  // TriggBits=3 means from 3d reco (0,1,2 mean something else)
493  t0s->push_back(anab::T0(trk->GetT0(), 0, 3, tracks->back().ID()));
494 
495  auto const t0Ptr = make_t0ptr(t0s->size() - 1); // PtrMaker Step #3
496  trk2t0->addSingle(trkPtr, t0Ptr);
497  }
498 
499  // Check if this is a cosmic ray and create an association if it is.
500  if (trk->HasTagFlag(pma::Track3D::kCosmic)) {
501  // Get the track end points
502  std::vector<float> trkEnd0;
503  std::vector<float> trkEnd1;
504  // Get the drift direction, but don't care about the sign
505  // Also need to subtract 1 due to the definition.
506  int driftDir = abs(tpc.DetectDriftDirection()) - 1;
507 
508  for (int i = 0; i < 3; ++i) {
509  // Get the drift direction and apply the opposite of the drift shift in order to
510  // give the CosmicTag the drift coordinate assuming T0 = T_beam as it requests.
511  double shift = 0.0;
512  if (i == driftDir) { shift = trk->Nodes()[0]->GetDriftShift(); }
513  trkEnd0.push_back(trk->Nodes()[0]->Point3D()[i] - shift);
514  trkEnd1.push_back(trk->Nodes()[trk->Nodes().size() - 1]->Point3D()[i] - shift);
515  }
516  // Make the tag object. For now, let's say this is very likely a cosmic (3rd argument = 1).
517  // Set the type of cosmic to the value saved in pma::Track.
518  auto tags = getCosmicTag(trk->GetTag());
519  for (const auto t : tags) {
520  cosmicTags->emplace_back(trkEnd0, trkEnd1, 1, t);
521  auto const cosmicPtr = make_ctptr(cosmicTags->size() - 1);
522  trk2ct->addSingle(trkPtr, cosmicPtr);
523  }
524  }
525 
526  //gc: save associated hits in the same order as trajectory points
527  for (size_t h = 0, cnt = 0; h < trk->size(); h++) {
528  pma::Hit3D* h3d = (*trk)[h];
529  if (!h3d->IsEnabled()) continue;
530 
531  recob::TrackHitMeta metadata(cnt++, h3d->Dx());
532  trk2hit->addSingle(trkPtr, h3d->Hit2DPtr(), metadata);
533  trk2hit_oldway->addSingle(
534  trkPtr, h3d->Hit2DPtr()); // ****** REMEMBER to remove when FindMany improved ******
535  }
536 
538  spStart = allsp->size();
539  //rs: so make also associations to space points in the order of trajectory points
540  for (size_t h = 0; h < trk->size(); ++h) {
541  pma::Hit3D* h3d = (*trk)[h];
542  if (!h3d->IsEnabled()) continue;
543 
544  double hx = h3d->Point3D().X();
545  double hy = h3d->Point3D().Y();
546  double hz = h3d->Point3D().Z();
547 
548  if ((h == 0) || (std::fabs(sp_pos[0] - hx) > 1.0e-5) ||
549  (std::fabs(sp_pos[1] - hy) > 1.0e-5) || (std::fabs(sp_pos[2] - hz) > 1.0e-5)) {
550  if (sp_hits.size()) // hits assigned to the previous sp
551  {
552  util::CreateAssn(evt, *allsp, sp_hits, *sp2hit);
553  sp_hits.clear();
554  }
555  sp_pos[0] = hx;
556  sp_pos[1] = hy;
557  sp_pos[2] = hz;
558  allsp->push_back(recob::SpacePoint(sp_pos, sp_err, 1.0));
559  }
560  sp_hits.push_back(h3d->Hit2DPtr());
561  }
562 
563  if (sp_hits.size()) // hits assigned to the last sp
564  {
565  util::CreateAssn(evt, *allsp, sp_hits, *sp2hit);
566  }
567  spEnd = allsp->size();
568 
569  if (spEnd > spStart) util::CreateAssn(evt, *tracks, *allsp, *trk2sp, spStart, spEnd);
570  }
571 
572  auto vsel = pmalgTracker.getVertices(
573  fSaveOnlyBranchingVtx); // vtx pos's with vector of connected track idxs
574  auto ksel = pmalgTracker.getKinks(); // pairs of kink position - associated track idx
575  std::map<size_t, art::Ptr<recob::Vertex>> frontVtxs; // front vertex ptr for each track index
576 
577  if (fPmaTrackerConfig.RunVertexing()) // save vertices and vtx-trk assns
578  {
579  double xyz[3];
580  for (auto const& v : vsel) {
581  xyz[0] = v.first.X();
582  xyz[1] = v.first.Y();
583  xyz[2] = v.first.Z();
584  mf::LogVerbatim("Summary") << " vtx:" << xyz[0] << ":" << xyz[1] << ":" << xyz[2]
585  << " (" << v.second.size() << " tracks)";
586 
587  size_t vidx = vtxs->size();
588  vtxs->push_back(recob::Vertex(xyz, vidx));
589 
590  auto const vptr = make_vtxptr(vidx);
591  if (!v.second.empty()) {
592  for (const auto& vEntry : v.second) {
593  size_t tidx = vEntry.first;
594  bool isFront = vEntry.second;
595 
596  if (isFront) frontVtxs[tidx] = vptr; // keep ptr of the front vtx
597 
598  auto const tptr = make_trkptr(tidx);
599  vtx2trk->addSingle(vptr, tptr);
600  }
601  }
602  else
603  mf::LogWarning("PMAlgTrackMaker") << "No tracks found at this vertex.";
604  }
605  mf::LogVerbatim("Summary") << vtxs->size() << " vertices ready";
606 
607  for (auto const& k : ksel) {
608  xyz[0] = k.first.X();
609  xyz[1] = k.first.Y();
610  xyz[2] = k.first.Z();
611  mf::LogVerbatim("Summary") << " kink:" << xyz[0] << ":" << xyz[1] << ":" << xyz[2];
612 
613  size_t kidx = kinks->size();
614  size_t tidx = k.second; // track idx on which this kink was found
615 
616  kinks->push_back(
617  recob::Vertex(xyz, tidx)); // save index of track (will have color of trk in evd)
618 
619  auto const tptr = make_trkptr(tidx);
620  auto const kptr = make_kinkptr(kidx);
621  trk2kink->addSingle(tptr, kptr);
622  }
623  mf::LogVerbatim("Summary") << ksel.size() << " kinks ready";
624  }
625 
626  if (fSavePmaNodes) {
627  double xyz[3];
628  for (size_t t = 0; t < result.size(); ++t) {
629  auto const& trk = *(result[t].Track());
630  for (auto const* node : trk.Nodes()) {
631  xyz[0] = node->Point3D().X();
632  xyz[1] = node->Point3D().Y();
633  xyz[2] = node->Point3D().Z();
634  nodes->push_back(recob::Vertex(xyz, t));
635  }
636  }
637  }
638 
639  for (size_t t = 0; t < result.size(); ++t) {
640  size_t parentIdx = recob::PFParticle::kPFParticlePrimary;
641  if (result[t].Parent() >= 0) parentIdx = (size_t)result[t].Parent();
642 
643  std::vector<size_t> daughterIdxs;
644  for (size_t idx : result[t].Daughters()) {
645  daughterIdxs.push_back(idx);
646  }
647 
648  size_t pfpidx = pfps->size();
649  pfps->emplace_back((*tracks)[t].ParticleId(), pfpidx, parentIdx, daughterIdxs);
650 
651  auto const pfpptr = make_pfpptr(pfpidx);
652  auto const tptr = make_trkptr(t);
653  pfp2trk->addSingle(pfpptr, tptr);
654 
655  // add assns to FRONT vertex of each particle
657  art::Ptr<recob::Vertex> vptr = frontVtxs[t];
658  if (!vptr.isNull())
659  pfp2vtx->addSingle(pfpptr, vptr);
660  else
661  mf::LogWarning("PMAlgTrackMaker") << "Front vertex for PFParticle is missing.";
662  }
663  }
664  mf::LogVerbatim("Summary") << pfps->size()
665  << " PFParticles created for reconstructed tracks.";
666  mf::LogVerbatim("Summary") << "Adding " << result.parents().size() << " primary PFParticles.";
667  for (size_t t = 0; t < result.parents().size(); ++t) {
668  std::vector<size_t> daughterIdxs;
669  for (size_t idx : result.parents()[t].Daughters()) {
670  daughterIdxs.push_back(idx);
671  }
672 
673  size_t pfpidx = pfps->size();
674  size_t parentIdx = recob::PFParticle::kPFParticlePrimary;
675  pfps->emplace_back(0, pfpidx, parentIdx, daughterIdxs);
676 
677  // add assns to END vertex of primary
678  if (fPmaTrackerConfig.RunVertexing() && !daughterIdxs.empty()) {
679  auto const pfpptr = make_pfpptr(pfpidx);
681  frontVtxs[daughterIdxs.front()]; // same vertex for all daughters
682  if (!vptr.isNull())
683  pfp2vtx->addSingle(pfpptr, vptr);
684  else
685  mf::LogWarning("PMAlgTrackMaker") << "Front vertex for PFParticle is missing.";
686  }
687  }
688  mf::LogVerbatim("Summary") << pfps->size() << " PFParticles created in total.";
689  }
690 
691  // for (const auto & ct : *cosmicTags) { std::cout << "Cosmic tag: " << ct << std::endl; }
692 
693  evt.put(std::move(tracks));
694  evt.put(std::move(allsp));
695  evt.put(std::move(vtxs));
696  evt.put(std::move(kinks), kKinksName);
697  evt.put(std::move(nodes), kNodesName);
698  evt.put(std::move(t0s));
699  evt.put(std::move(cosmicTags));
700 
701  evt.put(std::move(trk2hit_oldway)); // ****** REMEMBER to remove when FindMany improved ******
702  evt.put(std::move(trk2hit));
703  evt.put(std::move(trk2sp));
704  evt.put(std::move(trk2t0));
705  evt.put(std::move(trk2ct));
706 
707  evt.put(std::move(sp2hit));
708  evt.put(std::move(vtx2trk));
709  evt.put(std::move(trk2kink), kKinksName);
710 
711  evt.put(std::move(pfps));
712  evt.put(std::move(pfp2clu));
713  evt.put(std::move(pfp2vtx));
714  evt.put(std::move(pfp2trk));
715  }
716  // ------------------------------------------------------
717  // ------------------------------------------------------
718  // ------------------------------------------------------
719 
721 
722 } // namespace trkf
PMAlgTrackMaker & operator=(PMAlgTrackMaker const &)=delete
bool SelectHits(float fraction=1.0F)
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
static const std::string kKinksName
void produce(art::Event &e) override
recob::Track convertFrom(const pma::Track3D &src, unsigned int tidx, int pdg=0)
fhicl::Atom< art::InputTag > EmClusterModuleLabel
static constexpr size_t kPFParticlePrimary
Define index to signify primary particle.
Definition: PFParticle.h:57
Planes which measure V.
Definition: geo_types.h:136
Unknown view.
Definition: geo_types.h:142
Declaration of signal hit object.
fhicl::Atom< art::InputTag > WireModuleLabel
bool IsEnabled() const noexcept
Definition: PmaHit3D.h:86
fhicl::Atom< art::InputTag > HitModuleLabel
fhicl::Table< pma::PMAlgVertexing::Config > PMAlgVertexing
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.cc:6
Planes which measure X direction.
Definition: geo_types.h:140
fhicl::Table< pma::PMAlgCosmicTagger::Config > PMAlgCosmicTagging
fhicl::Table< pma::ProjectionMatchingAlg::Config > ProjectionMatchingAlg
void produces(std::string const &instanceName={}, Persistable const persistable=Persistable::Yes)
fhicl::Atom< std::string > Validation
fhicl::Atom< art::InputTag > ClusterModuleLabel
constexpr auto abs(T v)
Returns the absolute value of the argument.
Class to keep data related to recob::Hit associated with recob::Track.
TVector3 const & Point3D() const
Definition: PmaHit3D.h:50
Planes which measure Z direction.
Definition: geo_types.h:138
Data related to recob::Hit associated with recob::Track.The purpose is to collect several variables t...
Definition: TrackHitMeta.h:43
fhicl::Atom< bool > RunVertexing
Definition: T0.h:16
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
Planes which measure Y direction.
Definition: geo_types.h:139
std::vector< anab::CosmicTagID_t > getCosmicTag(const pma::Track3D::ETag pmaTag) const
geo::GeometryCore const * fGeom
TPCGeo const & TPC(TPCID const &tpcid=tpc_zero) const
Returns the specified TPC.
Definition: GeometryCore.h:722
PutHandle< PROD > put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: Event.h:77
Planes which measure U.
Definition: geo_types.h:135
double GetT0() const
Definition: PmaTrack3D.h:257
pma::PMAlgStitching::Config fPmaStitchConfig
unsigned int MaxPlanes() const
Returns the largest number of planes among all TPCs in this detector.
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
pma::ProjectionMatchingAlg::Config fPmaConfig
void push_back(Ptr< U > const &p)
Definition: PtrVector.h:435
bool HasTagFlag(ETag value) const noexcept
Definition: PmaTrack3D.h:67
pma::PMAlgVertexing::Config fPmaVtxConfig
int getPdgFromCnnOnHits(const art::Event &evt, const pma::Track3D &trk) const
bool isNull() const noexcept
Definition: Ptr.h:211
Provides recob::Track data product.
unsigned int FrontTPC() const
Definition: PmaTrack3D.h:118
unsigned int FrontCryo() const
Definition: PmaTrack3D.h:119
The data type to uniquely identify a TPC.
Definition: geo_types.h:381
pma::PMAlgCosmicTagger::Config fPmaTaggingConfig
Description of geometry of one entire detector.
Definition: GeometryCore.h:119
Declaration of cluster object.
ETag GetTag() const noexcept
Definition: PmaTrack3D.h:66
size_type size() const
Definition: PtrVector.h:302
size_t CompleteMissingWires(detinfo::DetectorPropertiesData const &detProp, unsigned int view)
bool CreateAssn(art::Event &evt, std::vector< T > const &a, art::Ptr< U > const &b, art::Assns< U, T > &assn, std::string a_instance, size_t index=UINT_MAX)
Creates a single one-to-one association.
std::map< size_t, std::vector< double > > dedx_map
Definition: Utilities.h:36
fhicl::Atom< float > TrackLikeThreshold
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
double GetRawdEdxSequence(std::map< size_t, std::vector< double >> &dedx, unsigned int view=geo::kZ, unsigned int skip=0, bool inclDisabled=false) const
Utility object to perform functions of association.
void init(const art::FindManyP< recob::Hit > &hitsFromClusters)
double Dx() const noexcept
Definition: PmaHit3D.h:69
bool HasT0() const noexcept
Definition: PmaTrack3D.h:260
fhicl::Table< pma::PMAlgTracker::Config > PMAlgTracking
bool init(const art::Event &evt, pma::PMAlgTracker &pmalgTracker) const
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
fhicl::Table< pma::PMAlgStitching::Config > PMAlgStitching
art::Ptr< recob::Hit > const & Hit2DPtr() const
Definition: PmaHit3D.h:48
std::vector< TH1F * > fAdcInRejectedPoints
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
Definition: ModuleGraph.h:25
TrackCollectionProxyElement< TrackCollProxy > Track
Proxy to an element of a proxy collection of recob::Track objects.
Definition: Track.h:992
std::vector< pma::Node3D * > const & Nodes() const noexcept
Definition: PmaTrack3D.h:274
pma::PMAlgTracker::Config fPmaTrackerConfig
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:46
TCEvent evt
Definition: DataStructs.cxx:8
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:306
Float_t e
Definition: plot.C:35
size_t size() const
Definition: PmaTrack3D.h:89
void clear()
Definition: PtrVector.h:533
PMAlgTrackMaker(Parameters const &config)
Definition: fwd.h:26
static std::unique_ptr< MVAReader > create(const art::Event &evt, const art::InputTag &tag)
Definition: MVAReader.h:108
art framework interface to geometry description
std::vector< TH1F * > fAdcInPassingPoints
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
Encapsulate the construction of a single detector plane.
static const std::string kNodesName