All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TrackSplitter_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: TrackSplitter
3 // Plugin Type: producer (art v3_02_06)
4 // File: TrackSplitter_module.cc
5 //
6 // Generated at Wed Feb 19 17:38:21 2020 by Gray Putnam using cetskelgen
7 // from cetlib version v3_07_02.
8 ////////////////////////////////////////////////////////////////////////
9 
10 #include "art/Framework/Core/EDProducer.h"
11 #include "art/Framework/Core/ModuleMacros.h"
12 #include "art/Framework/Principal/Event.h"
13 #include "art/Framework/Principal/Handle.h"
14 #include "art/Framework/Principal/Run.h"
15 #include "art/Framework/Principal/SubRun.h"
16 #include "canvas/Utilities/InputTag.h"
17 #include "fhiclcpp/ParameterSet.h"
18 #include "messagefacility/MessageLogger/MessageLogger.h"
23 
36 
37 #include <memory>
38 #include <optional>
40 
41 namespace sbn {
42  class TrackSplitter;
43 }
44 
45 
46 class sbn::TrackSplitter : public art::EDProducer {
47 public:
48  explicit TrackSplitter(fhicl::ParameterSet const& p);
49  // The compiler-generated destructor is fine for non-base
50  // classes without bare pointers or other resource use.
51 
52  // Plugins should not be copied or assigned.
53  TrackSplitter(TrackSplitter const&) = delete;
54  TrackSplitter(TrackSplitter&&) = delete;
55  TrackSplitter& operator=(TrackSplitter const&) = delete;
57 
58  // Required functions.
59  void produce(art::Event& e) override;
60 
61 private:
62 
63  // input labels
64  art::InputTag fTrackLabel;
65  art::InputTag fMergedPFPLabel;
66 
67  // service holders
69  std::optional<detinfo::DetectorPropertiesData> fDetProp;
70  std::optional<detinfo::DetectorClocksData> fDetClock;
71 
72  // helper functions
73  std::pair<int, float> ClosestTrajectoryPoint(const detinfo::DetectorPropertiesData &dprop, const recob::Track &trk, const recob::Hit &hit);
74  std::vector<art::Ptr<recob::Hit>> SplitTrunkHits(
75  const detinfo::DetectorPropertiesData &dprop,
76  const std::vector<art::Ptr<recob::Hit>> &trunk_hits,
77  unsigned main_hit_ind,
78  const std::vector<const recob::TrackHitMeta *> &trunk_hmetas,
79  const recob::Track &trunk_trk,
80  const recob::Track &branch_trk);
81 
82  std::pair<std::vector<art::Ptr<recob::Hit>>, std::vector<const recob::TrackHitMeta *>> OrganizeHits(
83  const recob::Track &trk, const std::vector<art::Ptr<recob::Hit>> &hits, const std::vector<const recob::TrackHitMeta *> &thm, unsigned plane);
84 
85  // Setup struct for ret for the DeMergeHits thingy
86  struct PairedHits {
87  std::vector<recob::Hit> trunk_hits;
88  std::vector<recob::Hit> branch_hits;
89  std::vector<recob::TrackHitMeta> trunk_hmetas;
90  std::vector<recob::TrackHitMeta> branch_hmetas;
91  };
92 
95  const recob::Track &trunk_trk,
96  const recob::Track &new_branch_trk,
97  const recob::Track &old_branch_trk,
98  const std::vector<art::Ptr<recob::Hit>> &trunk_hits,
99  const std::vector<art::Ptr<recob::Hit>> &branch_hits,
100  const std::vector<const recob::TrackHitMeta *> &trunk_hmeta,
101  const std::vector<const recob::TrackHitMeta *> &branch_hmeta,
102  const sbn::MergedTrackInfo &info,
103  unsigned plane);
104 
106  const detinfo::DetectorPropertiesData &dprop,
107  const recob::Track &trunk_trk,
108  const recob::Track &new_branch_trk,
109  const recob::Track &old_branch_trk,
110  const std::vector<art::Ptr<recob::Hit>> &trunk_hits,
111  const std::vector<art::Ptr<recob::Hit>> &branch_hits,
112  const std::vector<const recob::TrackHitMeta *> &trunk_hmetas,
113  const std::vector<const recob::TrackHitMeta *> &branch_hmetas,
114  const sbn::MergedTrackInfo &info);
115 
116  recob::Track DeMergeTrack(const recob::Track &trunk, const recob::Track &branch, const sbn::MergedTrackInfo &info);
117 };
118 
119 sbn::TrackSplitter::TrackSplitter(fhicl::ParameterSet const& p)
120  : EDProducer{p},
121  fTrackLabel(p.get<art::InputTag>("TrackLabel", "pandoraTrack")),
122  fMergedPFPLabel(p.get<art::InputTag>("MergedPFPLabel", "mergeIdent"))
123 {
124  produces<std::vector<recob::Track>>();
125  produces<std::vector<recob::Hit>>();
126  produces<art::Assns<recob::Track, recob::Hit, recob::TrackHitMeta>>();
127  produces<art::Assns<recob::PFParticle, recob::Track>>();
128 }
129 
131  float hit_x = dprop.ConvertTicksToX(hit.PeakTime(), hit.WireID());
132  float hit_w = hit.WireID().Wire * fGeo->WirePitch();
133 
134  // std::cout << "Hit time: " << hit.PeakTime() << std::endl;
135  // std::cout << "Hit X: " << hit_x << std::endl;
136  // std::cout << "Hit W: " << hit_w << std::endl;
137 
138  float dist = -1000.;
139  int ret = -1;
140 
141  for (unsigned i_tp = trk.FirstValidPoint(); i_tp < trk.NumberTrajectoryPoints(); i_tp = trk.NextValidPoint(i_tp+1)) {
142  TVector3 pos = trk.LocationAtPoint<TVector3>(i_tp);
143  float pos_x = pos.X();
144  float pos_w = fGeo->WireCoordinate(trk.LocationAtPoint<geo::Point_t>(i_tp), hit.WireID()) * fGeo->WirePitch();
145  float this_dist = sqrt((pos_x - hit_x) *(pos_x - hit_x) + (pos_w - hit_w) *(pos_w - hit_w));
146  if (ret < 0 || this_dist < dist) {
147  dist = this_dist;
148  ret = i_tp;
149  }
150  }
151 
152  // if (ret == -1) std::cout << "No SP :(\n";
153  // else {
154  // TVector3 pos = trk.LocationAtPoint<TVector3>(ret);
155  // std::cout << "Closest TP X: " << pos.X() << std::endl;
156  // std::cout << "Closest TP W: " << fGeo->WireCoordinate(pos.Y(), pos.Z(), hit.WireID()) * fGeo->WirePitch() << std::endl;
157  // }
158 
159  return {ret, dist};
160 }
161 
162 std::vector<art::Ptr<recob::Hit>> sbn::TrackSplitter::SplitTrunkHits(
163  const detinfo::DetectorPropertiesData &dprop,
164  const std::vector<art::Ptr<recob::Hit>> &trunk_hits,
165  unsigned main_hit_ind,
166  const std::vector<const recob::TrackHitMeta *> &trunk_hmetas,
167  const recob::Track &trunk_trk,
168  const recob::Track &branch_trk) {
169 
170  std::vector<art::Ptr<recob::Hit>> split_trunk_hits;
171 
172  geo::WireID wire = trunk_hits[main_hit_ind]->WireID();
173 
174  for (unsigned i = 0; i < trunk_hits.size(); i++) {
175  art::Ptr<recob::Hit> h = trunk_hits[i];
176  const recob::TrackHitMeta *hmeta = trunk_hmetas[i];
177  if (i != main_hit_ind // different hit
178  && (hmeta->Index() == std::numeric_limits<unsigned int>::max() || !trunk_trk.HasValidPoint(hmeta->Index())) // not used in trunk traj.
179  && h->WireID() == wire) { // on same wire
180 
181  // Found a hit! So there are two hits on the trunk on this wire
182  // and one may belong on the branch
183  //
184  // We'll say this hit "belongs" to the branch if it closer to the projection
185  // of the branch on the plane
186 
187  // std::cout << "TRUNK\n";
188  std::pair<int, float> trunk_dist = ClosestTrajectoryPoint(dprop, trunk_trk, *h);
189  // std::cout << "BRANCH\n";
190  std::pair<int, float> branch_dist = ClosestTrajectoryPoint(dprop, branch_trk, *h);
191 
192  // std::cout << "Possible split trunk hit on wire: " << h->WireID().Wire << ". Trunk dist: " << trunk_dist.second << " branch dist: " << branch_dist.second << std::endl;
193 
194  if (trunk_dist.first >= 0 && branch_dist.first > 0 && branch_dist.second < trunk_dist.second) {
195  split_trunk_hits.push_back(h);
196  }
197  }
198  }
199 
200  return split_trunk_hits;
201 }
202 
204  const detinfo::DetectorPropertiesData &dprop,
205  const recob::Track &trunk_trk,
206  const recob::Track &new_branch_trk,
207  const recob::Track &old_branch_trk,
208  const std::vector<art::Ptr<recob::Hit>> &trunk_hits,
209  const std::vector<art::Ptr<recob::Hit>> &branch_hits,
210  const std::vector<const recob::TrackHitMeta *> &trunk_hmeta,
211  const std::vector<const recob::TrackHitMeta *> &branch_hmeta,
212  const sbn::MergedTrackInfo &info,
213  unsigned plane) {
214 
216 
217  unsigned n_new_branch_trajpoints = new_branch_trk.NumberTrajectoryPoints();
218  unsigned n_old_branch_trajpoints = old_branch_trk.NumberTrajectoryPoints();
219  unsigned n_new_points = n_new_branch_trajpoints - n_old_branch_trajpoints;
220 
221  unsigned n_hits = trunk_hits.size();
222 
223  // std::cout << "De-merging plane: " << plane << std::endl;
224 
225  // std::cout << "Branch start: " << info.branch_start << std::endl;
226 
227  // consider the energy depositions in the trunk before the branch starts
228  // Consider the hits in the trunk before the branch starts
229  unsigned i_hit_trunk = 0;
230  for (; i_hit_trunk < n_hits; i_hit_trunk++) {
231  const recob::Hit &hit = *trunk_hits[i_hit_trunk];
232  const recob::TrackHitMeta *thm = trunk_hmeta[i_hit_trunk];
233 
234  // ignore hits not used in the trunk trajectory
235  if (thm->Index() == std::numeric_limits<unsigned int>::max() || !trunk_trk.HasValidPoint(thm->Index())) continue;
236 
237  // Are we past the track start?
238  TVector3 loc = trunk_trk.LocationAtPoint<TVector3>(thm->Index());
239  bool this_point_past_branch_start = (loc - info.vertex).Dot(info.direction) > info.branch_start;
240  // bool this_point_past_branch_start = info.trunk_wire_direction_is_ascending[plane] ?
241  // (int)hit.WireID().Wire >= info.branch_wire_start[plane] :
242  // (int)hit.WireID().Wire <= info.branch_wire_start[plane];
243 
244  // std::cout << "This wire: " << hit.WireID().Wire << std::endl;
245  // std::cout << "This point: " << (loc - info.vertex).Dot(info.direction) << std::endl;
246 
247  // lookup if the branch has a hit on this wire
248  std::vector<art::Ptr<recob::Hit>> branch_wire_hits;
249  std::vector<const recob::TrackHitMeta *> branch_wire_hmetas;
250  for (unsigned i_hit_branch = 0; i_hit_branch < branch_hits.size(); i_hit_branch++) {
251  art::Ptr<recob::Hit> b_hit = branch_hits[i_hit_branch];
252  if (b_hit->WireID() == hit.WireID()) {
253  branch_wire_hits.push_back(b_hit);
254  branch_wire_hmetas.push_back(branch_hmeta[i_hit_branch]);
255  }
256  }
257 
258  // std::cout << "Number of branch hits on this wire: " << branch_wire_hits.size() << std::endl;
259 
260  bool valid_tp = false;
261  unsigned i_hit_branch = 0;
262  if (branch_wire_hits.size()) {
263  // Check any hits on the branch already have a valid trajectory point.
264  for (; i_hit_branch < branch_wire_hits.size(); i_hit_branch++) {
265  if (branch_wire_hmetas[i_hit_branch]->Index() != std::numeric_limits<unsigned int>::max() &&
266  old_branch_trk.HasValidPoint(branch_wire_hmetas[i_hit_branch]->Index())) {
267  valid_tp = true;
268  break;
269  }
270  }
271  }
272 
273  // std::cout << "Valid traj-point: " << valid_tp << std::endl;
274 
275  // Past the start of the branch track! We should be all set now
276  if (this_point_past_branch_start && valid_tp) {
277  ret.trunk_hits.push_back(hit);
278  ret.trunk_hmetas.push_back(*thm);
279  break;
280  }
281 
282  // No hit lurking on the branch -- we'll have to split the trunk
283  // First see if we can find a stray hit on the trunk
284  if (!branch_wire_hits.size()) {
285  branch_wire_hits = SplitTrunkHits(dprop, trunk_hits, i_hit_trunk, trunk_hmeta, trunk_trk, new_branch_trk);
286  }
287 
288  // std::cout << "Number split trunk hits: " << branch_wire_hits.size() << std::endl;
289 
290  // Ok! Now we have all the information we need to determine what hit to assign
291  // to the branch on this wire. There are three possiblities:
292  //
293  // 1. The branch has a valid hit/traj-point on this wire.
294  // 2. There is a spare hit on the branch or trunk we can associate to the branch trajectory
295  // 3. There are no spare hits on the branch and we need to split the trunk hit.
296  //
297  // These three possibilties are handled in order below:
298  if (valid_tp) {
299  // Valid hit on this wire! Save it and go onto the next trunk hit
300  //
301  // Make a new TrackHitMeta that updates the traj point to the new correct place
302  recob::TrackHitMeta new_branch_meta(branch_wire_hmetas[i_hit_branch]->Index() + n_new_points);
303  ret.branch_hits.push_back(*branch_wire_hits[i_hit_branch]);
304  ret.branch_hmetas.push_back(new_branch_meta);
305 
306  ret.trunk_hits.push_back(hit);
307  ret.trunk_hmetas.push_back(*thm);
308  }
309  // Found a stray hit! We can work with that one
310  else if (branch_wire_hits.size()) {
311  art::Ptr<recob::Hit> new_branch_hit = *std::max_element(branch_wire_hits.begin(), branch_wire_hits.end(),
312  [this, dprop, new_branch_trk](auto const &lhs, auto const &rhs) {
313  return ClosestTrajectoryPoint(dprop, new_branch_trk, *lhs).second < ClosestTrajectoryPoint(dprop, new_branch_trk, *rhs).second;
314  });
315  unsigned i_tp = (unsigned)ClosestTrajectoryPoint(dprop, new_branch_trk, *new_branch_hit).first;
316 
317  recob::TrackHitMeta new_meta(i_tp);
318 
319  // save this hit
320  ret.branch_hits.push_back(*new_branch_hit);
321  ret.branch_hmetas.push_back(new_meta);
322 
323  // save the main hit for the trunk
324  ret.trunk_hits.push_back(hit);
325  ret.trunk_hmetas.push_back(*thm);
326  }
327  // No stray hit -- we'll have to split the tracks single hit on this wire in 2
328  else {
329  recob::Hit halfhit(hit.Channel(), hit.StartTick(), hit.EndTick(), hit.PeakTime(),
330  hit.SigmaPeakTime(), hit.RMS(),
331  hit.PeakAmplitude() / 2., hit.SigmaPeakAmplitude() / 2., hit.SummedADC() / 2.,
332  hit.Integral() / 2., hit.SigmaIntegral() / 2.,
333  hit.Multiplicity(), hit.LocalIndex(), hit.GoodnessOfFit(), hit.DegreesOfFreedom(), hit.View(),
334  hit.SignalType(), hit.WireID());
335 
336  unsigned branch_tp = ClosestTrajectoryPoint(dprop, new_branch_trk, halfhit).first;
337  recob::TrackHitMeta branch_meta(branch_tp);
338 
339  // save the half-hit for the branch and the trunk
340  ret.branch_hits.push_back(halfhit);
341  ret.branch_hmetas.push_back(branch_meta);
342 
343  ret.trunk_hits.push_back(halfhit);
344  ret.trunk_hmetas.push_back(*thm);
345  }
346  }
347 
348  // fill in the rest of the trunk hits
349  for (; i_hit_trunk < n_hits; i_hit_trunk++) {
350  const recob::Hit &hit = *trunk_hits[i_hit_trunk];
351  const recob::TrackHitMeta *thm = trunk_hmeta[i_hit_trunk];
352 
353  // ignore hits not used in the trunk trajectory
354  if (thm->Index() == std::numeric_limits<unsigned int>::max() || !trunk_trk.HasValidPoint(thm->Index())) continue;
355 
356  ret.trunk_hits.push_back(hit);
357  ret.trunk_hmetas.push_back(*thm);
358  }
359 
360  // fill in the rest of the branch hits
361  unsigned n_split_hits = ret.branch_hits.size();
362  for (unsigned i_hit_branch = 0; i_hit_branch < branch_hits.size(); i_hit_branch++) {
363 
364  // don't save invalid hits
365  if (branch_hmeta[i_hit_branch]->Index() == std::numeric_limits<unsigned int>::max() ||
366  !old_branch_trk.HasValidPoint(branch_hmeta[i_hit_branch]->Index())) {
367  continue;
368  }
369 
370  // don't save hits that were already added to the track
371  bool found = false;
372  for (unsigned j_hit_branch = 0; j_hit_branch < n_split_hits; j_hit_branch++) {
373  if (ret.branch_hits[j_hit_branch].WireID() == branch_hits[i_hit_branch]->WireID()) {
374  found = true;
375  break;
376  }
377  }
378  if (found) continue;
379 
380  // Make a new TrackHitMeta that updates the traj point to the new correct place
381  recob::TrackHitMeta new_branch_meta(branch_hmeta[i_hit_branch]->Index() + n_new_points);
382  ret.branch_hits.push_back(*branch_hits[i_hit_branch]);
383  ret.branch_hmetas.push_back(new_branch_meta);
384  }
385 
386  return ret;
387 }
388 
389 std::pair<std::vector<art::Ptr<recob::Hit>>, std::vector<const recob::TrackHitMeta *>> sbn::TrackSplitter::OrganizeHits(
390  const recob::Track &trk, const std::vector<art::Ptr<recob::Hit>> &hits, const std::vector<const recob::TrackHitMeta *> &thm, unsigned plane) {
391 
392  std::pair<std::vector<art::Ptr<recob::Hit>>, std::vector<const recob::TrackHitMeta *>> ret;
393 
394  // Collect the hits on the provided plane
395  for (unsigned i_hit = 0; i_hit < hits.size(); i_hit++) {
396  if (hits[i_hit]->WireID().Plane == plane) {
397  ret.first.push_back(hits[i_hit]);
398  ret.second.push_back(thm[i_hit]);
399  }
400  }
401 
402  // Now decide if the hit order needs to be reversed
403  //
404  // DeMergePlaneHits will assume hits are ordered start -> end
405 
406  int first_valid_hit = -1;
407  int last_valid_hit = -1;
408 
409  for (unsigned i_hit = 0; i_hit < ret.first.size(); i_hit++) {
410  if (ret.second[i_hit]->Index() != std::numeric_limits<unsigned int>::max() && trk.HasValidPoint(ret.second[i_hit]->Index())) {
411  first_valid_hit = i_hit;
412  break;
413  }
414  }
415 
416  for (int i_hit = ret.first.size()-1; i_hit >= 0; i_hit--) {
417  if (ret.second[i_hit]->Index() != std::numeric_limits<unsigned int>::max() && trk.HasValidPoint(ret.second[i_hit]->Index())) {
418  last_valid_hit = i_hit;
419  break;
420  }
421  }
422 
423  bool reverse_hits = false;
424 
425  // If there are two valid hits/traj-point's, then we can decide to re-order using which
426  // is closer to the start
427  if (first_valid_hit >= 0 && last_valid_hit >= 0 && first_valid_hit != last_valid_hit) {
428  reverse_hits = \
429  (trk.LocationAtPoint<TVector3>(ret.second[first_valid_hit]->Index()) - trk.Start<TVector3>()).Mag() >
430  (trk.LocationAtPoint<TVector3>(ret.second[last_valid_hit]->Index()) - trk.Start<TVector3>()).Mag();
431  }
432  // Otherwise, try to see if we can at least determine whether wires and traj-points are ascending or descending
433  //
434  // If not enough info, assume the order is correct
435  else if (ret.first.size() && trk.NumberTrajectoryPoints() >= 2) {
436  TVector3 start = trk.Start<TVector3>();
437  TVector3 start_p1 = trk.LocationAtPoint<TVector3>(trk.NextValidPoint(trk.FirstValidPoint()+1));
438 
439  geo::PlaneID thisplane(0, 0, plane);
440  bool trk_is_ascending = fGeo->WireCoordinate(trk.Start<geo::Point_t>(), thisplane) <
441  fGeo->WireCoordinate(trk.LocationAtPoint<geo::Point_t>(trk.NextValidPoint(trk.FirstValidPoint()+1)), thisplane);
442  int wire0 = ret.first[0]->WireID().Wire;
443  int wire1 = -1;
444  for (unsigned i_hit = 1; i_hit < ret.first.size(); i_hit++) {
445  if ((int)ret.first[i_hit]->WireID().Wire != wire0) {
446  wire1 = ret.first[i_hit]->WireID().Wire;
447  break;
448  }
449  }
450  bool wire_is_ascending = (wire1 >= 0) ? wire1 > wire0 : trk_is_ascending;
451 
452  reverse_hits = trk_is_ascending != wire_is_ascending;
453  }
454 
455  if (reverse_hits) {
456  std::reverse(ret.first.begin(), ret.first.end());
457  std::reverse(ret.second.begin(), ret.second.end());
458  }
459 
460  return ret;
461 }
462 
464  const detinfo::DetectorPropertiesData &dprop,
465  const recob::Track &trunk_trk,
466  const recob::Track &new_branch_trk,
467  const recob::Track &old_branch_trk,
468  const std::vector<art::Ptr<recob::Hit>> &trunk_hits,
469  const std::vector<art::Ptr<recob::Hit>> &branch_hits,
470  const std::vector<const recob::TrackHitMeta *> &trunk_hmetas,
471  const std::vector<const recob::TrackHitMeta *> &branch_hmetas,
472  const sbn::MergedTrackInfo &info) {
473 
475 
476  for (unsigned plane = 0; plane < 3; plane++) {
477  // collect the valid hits on each plane
478  std::pair<std::vector<art::Ptr<recob::Hit>>, std::vector<const recob::TrackHitMeta *>> trunkPlaneHits = \
479  OrganizeHits(trunk_trk, trunk_hits, trunk_hmetas, plane);
480 
481  std::pair<std::vector<art::Ptr<recob::Hit>>, std::vector<const recob::TrackHitMeta *>> branchPlaneHits = \
482  OrganizeHits(old_branch_trk, branch_hits, branch_hmetas, plane);
483 
484  // Split
485  sbn::TrackSplitter::PairedHits paired_hits = DeMergePlaneHits(dprop, trunk_trk, new_branch_trk, old_branch_trk, trunkPlaneHits.first, branchPlaneHits.first,
486  trunkPlaneHits.second, branchPlaneHits.second, info, plane);
487 
488  // Save
489  ret.trunk_hits.insert(ret.trunk_hits.end(), paired_hits.trunk_hits.begin(), paired_hits.trunk_hits.end());
490  ret.trunk_hmetas.insert(ret.trunk_hmetas.end(), paired_hits.trunk_hmetas.begin(), paired_hits.trunk_hmetas.end());
491  ret.branch_hits.insert(ret.branch_hits.end(), paired_hits.branch_hits.begin(), paired_hits.branch_hits.end());
492  ret.branch_hmetas.insert(ret.branch_hmetas.end(), paired_hits.branch_hmetas.begin(), paired_hits.branch_hmetas.end());
493  }
494 
495  return ret;
496 
497 }
498 
500  // add points from the trunk-track
501  std::vector<TVector3> add_p;
502  std::vector<TVector3> add_m;
503  std::vector<recob::TrajectoryPointFlags> add_f;
504 
505  for (unsigned i = 0; i < trunk.NumberTrajectoryPoints(); i++) {
506  if (!trunk.HasValidPoint(i)) continue;
507 
508  TVector3 p = trunk.LocationAtPoint<TVector3>(i);
509  float p_proj = (p - info.vertex).Dot(info.direction);
510 
511  if (p_proj >= info.branch_start) break;
512 
513  add_p.push_back(p);
514  add_m.push_back(trunk.DirectionAtPoint<TVector3>(i));
515  add_f.push_back(trunk.FlagsAtPoint(i));
516  }
517 
518  // smooth the addded points to avoid big jump between trunk and branch
519  if (add_p.size() >= 2) {
520  std::vector<TVector3> add_p_old = add_p;
521 
522  float dist = info.branch_start;
523  TVector3 diff = branch.Start<TVector3>() - add_p_old[add_p_old.size()-1];
524 
525  for (unsigned i = 1; i < add_p_old.size(); i++) {
526  float this_dist = (add_p_old[i] - info.vertex).Dot(info.direction);
527  add_p[i] = add_p_old[i] + diff * (this_dist / dist);
528  }
529 
530  for (int i = 0; i < (int)add_m.size() - 1; i++) {
531  add_m[i] = (add_p[i+1] - add_p[i]).Unit();
532  if (i > 0) add_m[i] = (add_m[i] + (add_p[i] - add_p[i-1]).Unit()).Unit();
533  }
534  add_m[add_p.size()-1] = ((branch.Start<TVector3>() - add_p[add_p.size()-1]).Unit() +
535  (add_p[add_p.size()-1] - add_p[add_p.size()-2])).Unit();
536 
537  // TODO: fix what the initial direction gets set to
538  add_m[0] = (branch.Start<TVector3>() - add_p[0]).Unit();
539  }
540 
541  /*
542  TVector3 p = trunk.Start<TVector3>();
543  float p_proj = (p - info.vertex).Dot(info.direction);
544 
545  if (p_proj < info.branch_start) {
546  add_p.push_back(p);
547  add_m.push_back((branch.Start<TVector3>() - p).Unit());
548  add_f.push_back(trunk.FlagsAtPoint(trunk.FirstValidPoint()));
549  }
550  */
551 
552  // Save the new points
553  recob::Track::Positions_t positions;
554  recob::Track::Momenta_t momenta;
555  recob::Track::Flags_t flags = std::move(add_f);
556 
557  for (unsigned i = 0; i < add_p.size(); i++) {
558  positions.emplace_back(add_p[i].X(), add_p[i].Y(), add_p[i].Z());
559  momenta.emplace_back(add_m[i].X(), add_m[i].Y(), add_m[i].Z());
560  }
561 
562  // copy the starting info from the branch-track
563  for (unsigned i_tp = 0; i_tp < branch.NumberTrajectoryPoints(); i_tp += 1) {
564  positions.push_back(branch.LocationAtPoint(i_tp));
565  momenta.push_back(branch.DirectionAtPoint(i_tp));
566  flags.push_back(branch.FlagsAtPoint(i_tp));
567  }
568 
569  recob::Track::SMatrixSym55 cov_start = trunk.StartCovariance();
570  recob::Track::SMatrixSym55 cov_end = branch.EndCovariance();
571  return recob::Track(std::move(positions), std::move(momenta), std::move(flags),
572  branch.HasMomentum(), branch.ParticleId(), branch.Chi2(), branch.Ndof(), std::move(cov_start), std::move(cov_end), branch.ID());
573 }
574 
576 {
577  // update services
578  fGeo = lar::providerFrom<geo::Geometry>();
579 
580  auto const &dclock = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(e);
581  auto const &dprop = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(e, dclock);
582 
583  // output data products
584  std::unique_ptr<art::Assns<recob::PFParticle, recob::Track>> trkAssn(new art::Assns<recob::PFParticle, recob::Track>);
585  std::unique_ptr<art::Assns<recob::Track, recob::Hit, recob::TrackHitMeta>> hitAssn(new art::Assns<recob::Track, recob::Hit, recob::TrackHitMeta>);
586  std::unique_ptr<std::vector<recob::Track>> outTracks(new std::vector<recob::Track>);
587  std::unique_ptr<std::vector<recob::Hit>> outHits(new std::vector<recob::Hit>);
588 
589  art::PtrMaker<recob::Track> trkPtrMaker{e};
590  art::PtrMaker<recob::Hit> hitPtrMaker{e};
591 
592  // input data
593  art::Handle<std::vector<sbn::MergedTrackInfo>> mergedtrack_handle;
594  e.getByLabel(fMergedPFPLabel, mergedtrack_handle);
595 
596  std::vector<art::Ptr<sbn::MergedTrackInfo>> mergedtracks;
597  art::fill_ptr_vector(mergedtracks, mergedtrack_handle);
598 
599  art::FindManyP<recob::PFParticle> mergedPFPs(mergedtracks, e, fMergedPFPLabel);
600 
601  for (unsigned i_mrg = 0; i_mrg < mergedtracks.size(); i_mrg++) {
602  const sbn::MergedTrackInfo &merge_info = *mergedtracks[i_mrg];
603  const std::vector<art::Ptr<recob::PFParticle>> pfps = mergedPFPs.at(i_mrg);
604  art::FindManyP<recob::Track> fmTracks(pfps, e, fTrackLabel);
605 
606  assert(pfps.size() == 2);
607 
608  art::Ptr<recob::PFParticle> trunk_pfp;
609  art::Ptr<recob::PFParticle> branch_pfp;
610  art::Ptr<recob::Track> trunk_trk;
611  art::Ptr<recob::Track> branch_trk;
612  if ((unsigned)merge_info.trunk == pfps[0]->Self()) {
613  trunk_pfp = pfps[0];
614  trunk_trk = fmTracks.at(0).at(0);
615  branch_pfp = pfps[1];
616  branch_trk = fmTracks.at(1).at(0);
617  }
618  else {
619  trunk_pfp = pfps[1];
620  trunk_trk = fmTracks.at(1).at(0);
621  branch_pfp = pfps[0];
622  branch_trk = fmTracks.at(0).at(0);
623  }
624 
625  // std::cout << "Splitting branch: " << branch_pfp->Self() << " from trunk: " << trunk_pfp->Self() << std::endl;
626 
627  // De-merge with the provided match
628  recob::Track demerge = DeMergeTrack(*trunk_trk, *branch_trk, merge_info);
629 
630  // look-up the track hits
631  art::FindManyP<recob::Hit, recob::TrackHitMeta> hits({trunk_trk, branch_trk}, e, fTrackLabel);
632 
633  sbn::TrackSplitter::PairedHits demerged_hits = DeMergeHits(dprop,
634  *trunk_trk, demerge, *branch_trk,
635  hits.at(0), hits.at(1), hits.data(0), hits.data(1),
636  merge_info);
637 
638  // Save
639  outTracks->push_back(demerge);
640  art::Ptr<recob::Track> branchTrackPtr = trkPtrMaker(outTracks->size()-1);
641  trkAssn->addSingle(branch_pfp, branchTrackPtr);
642 
643  for (unsigned i_hit = 0; i_hit < demerged_hits.branch_hits.size(); i_hit++) {
644  outHits->push_back(demerged_hits.branch_hits[i_hit]);
645  art::Ptr<recob::Hit> thisHitPtr = hitPtrMaker(outHits->size()-1);
646  hitAssn->addSingle(branchTrackPtr, thisHitPtr, demerged_hits.branch_hmetas[i_hit]);
647  }
648 
649  // Also make a new track for the trunk
650  recob::Track trunk_copy = *trunk_trk;
651  outTracks->push_back(trunk_copy);
652  art::Ptr<recob::Track> trunkTrackPtr = trkPtrMaker(outTracks->size()-1);
653  trkAssn->addSingle(trunk_pfp, trunkTrackPtr);
654 
655  for (unsigned i_hit = 0; i_hit < demerged_hits.trunk_hits.size(); i_hit++) {
656  outHits->push_back(demerged_hits.trunk_hits[i_hit]);
657  art::Ptr<recob::Hit> thisHitPtr = hitPtrMaker(outHits->size()-1);
658  hitAssn->addSingle(trunkTrackPtr, thisHitPtr, demerged_hits.trunk_hmetas[i_hit]);
659  }
660 
661  } // end iterate over merged PFParticles
662 
663  // Save into event
664  e.put(std::move(outTracks));
665  e.put(std::move(trkAssn));
666  e.put(std::move(outHits));
667  e.put(std::move(hitAssn));
668 }
669 
670 DEFINE_ART_MODULE(sbn::TrackSplitter)
short int LocalIndex() const
How well do we believe we know this hit?
Definition: Hit.h:227
Data product for reconstructed trajectory in space.
geo::SigType_t SignalType() const
Signal type for the plane of the hit.
Definition: Hit.h:231
Utilities related to art service access.
tracking::Momenta_t Momenta_t
std::optional< detinfo::DetectorPropertiesData > fDetProp
geo::WireID WireID() const
Definition: Hit.h:233
float RMS() const
RMS of the hit shape, in tick units.
Definition: Hit.h:220
Declaration of signal hit object.
Point_t const & LocationAtPoint(size_t i) const
pdgs p
Definition: selectors.fcl:22
std::vector< recob::TrackHitMeta > trunk_hmetas
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
PairedHits DeMergeHits(const detinfo::DetectorPropertiesData &dprop, const recob::Track &trunk_trk, const recob::Track &new_branch_trk, const recob::Track &old_branch_trk, const std::vector< art::Ptr< recob::Hit >> &trunk_hits, const std::vector< art::Ptr< recob::Hit >> &branch_hits, const std::vector< const recob::TrackHitMeta * > &trunk_hmetas, const std::vector< const recob::TrackHitMeta * > &branch_hmetas, const sbn::MergedTrackInfo &info)
float SigmaPeakAmplitude() const
Uncertainty on estimated amplitude of the hit at its peak, in ADC units.
Definition: Hit.h:222
TrackTrajectory::Flags_t Flags_t
float SigmaIntegral() const
Definition: Hit.h:225
bool HasValidPoint(size_t i) const
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.
int DegreesOfFreedom() const
Definition: Hit.h:229
float Integral() const
Integral under the calibrated signal waveform of the hit, in tick x ADC units.
Definition: Hit.h:224
geo::View_t View() const
View for the plane of the hit.
Definition: Hit.h:232
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:580
Data related to recob::Hit associated with recob::Track.The purpose is to collect several variables t...
Definition: TrackHitMeta.h:43
process_name hit
Definition: cheaterreco.fcl:51
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 see the discussion of warn common echo in *Note Linker such as a global int variable echo as opposed to a large global array echo echo I echo The symbol is an indirect reference to another symbol This echo is a GNU extension to the a out object file format which is echo rarely used echo echo N echo The symbol is a debugging symbol echo echo R echo The symbol is in a read only data section echo echo S echo The symbol is in an uninitialized data section for small echo objects echo echo T echo The symbol is in the the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo W echo The symbol is a weak symbol that has not been specifically echo tagged as a weak object symbol When a weak defined symbol echo is linked with a normal defined the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo echo The symbol is a stabs symbol in an a out object file In echo this the next values printed are the stabs other echo the stabs desc and the stab type Stabs symbols are echo used to hold debugging information For more echo see *Note or object file format specific echo echo For Mac OS X
float GoodnessOfFit() const
Degrees of freedom in the determination of the hit signal shape (-1 by default)
Definition: Hit.h:228
std::vector< recob::TrackHitMeta > branch_hmetas
short int Multiplicity() const
How many hits could this one be shared with.
Definition: Hit.h:226
std::pair< int, float > ClosestTrajectoryPoint(const detinfo::DetectorPropertiesData &dprop, const recob::Track &trk, const recob::Hit &hit)
float PeakAmplitude() const
The estimated amplitude of the hit at its peak, in ADC units.
Definition: Hit.h:221
std::optional< detinfo::DetectorClocksData > fDetClock
std::vector< recob::Hit > trunk_hits
std::pair< std::vector< art::Ptr< recob::Hit > >, std::vector< const recob::TrackHitMeta * > > OrganizeHits(const recob::Track &trk, const std::vector< art::Ptr< recob::Hit >> &hits, const std::vector< const recob::TrackHitMeta * > &thm, unsigned plane)
while getopts h
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
Access the description of detector geometry.
const SMatrixSym55 & EndCovariance() const
Collection of exceptions for Geometry system.
tracking::Positions_t Positions_t
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
void produce(art::Event &e) override
Point_t const & Start() const
Access to track position at different points.
std::vector< art::Ptr< recob::Hit > > SplitTrunkHits(const detinfo::DetectorPropertiesData &dprop, const std::vector< art::Ptr< recob::Hit >> &trunk_hits, unsigned main_hit_ind, const std::vector< const recob::TrackHitMeta * > &trunk_hmetas, const recob::Track &trunk_trk, const recob::Track &branch_trk)
Data product for reconstructed trajectory in space.
Description of geometry of one entire detector.
raw::TDCtick_t StartTick() const
Initial tdc tick for hit.
Definition: Hit.h:216
const geo::GeometryCore * fGeo
Provides recob::Track data product.
double ConvertTicksToX(double ticks, int p, int t, int c) const
tracking::SMatrixSym55 SMatrixSym55
raw::TDCtick_t EndTick() const
Final tdc tick for hit.
Definition: Hit.h:217
size_t FirstValidPoint() const
float PeakTime() const
Time of the signal peak, in tick units.
Definition: Hit.h:218
size_t NextValidPoint(size_t index) const
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
TrackSplitter & operator=(TrackSplitter const &)=delete
art::InputTag fMergedPFPLabel
do i e
float SummedADC() const
The sum of calibrated ADC counts of the hit (0. by default)
Definition: Hit.h:223
unsigned int Index() const
Hit index along the track trajectory.
Definition: TrackHitMeta.h:55
PairedHits DeMergePlaneHits(const detinfo::DetectorPropertiesData &dprop, const recob::Track &trunk_trk, const recob::Track &new_branch_trk, const recob::Track &old_branch_trk, const std::vector< art::Ptr< recob::Hit >> &trunk_hits, const std::vector< art::Ptr< recob::Hit >> &branch_hits, const std::vector< const recob::TrackHitMeta * > &trunk_hmeta, const std::vector< const recob::TrackHitMeta * > &branch_hmeta, const sbn::MergedTrackInfo &info, unsigned plane)
PointFlags_t const & FlagsAtPoint(size_t i) const
recob::Track DeMergeTrack(const recob::Track &trunk, const recob::Track &branch, const sbn::MergedTrackInfo &info)
constexpr WireID()=default
Default constructor: an invalid TPC ID.
Declaration of basic channel signal object.
Vector_t DirectionAtPoint(size_t i) const
TrackCollectionProxyElement< TrackCollProxy > Track
Proxy to an element of a proxy collection of recob::Track objects.
float SigmaPeakTime() const
Uncertainty for the signal peak, in tick units.
Definition: Hit.h:219
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:48
Class defining a sparse vector (holes are zeroes)
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
raw::ChannelID_t Channel() const
ID of the readout channel the hit was extracted from.
Definition: Hit.h:230
art framework interface to geometry description
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::vector< recob::Hit > branch_hits
TrackSplitter(fhicl::ParameterSet const &p)
const SMatrixSym55 & StartCovariance() const
Access to covariance matrices.