LArSoft  v10_06_00
Liquid Argon Software toolkit - https://larsoft.org/
BackTracker.cc
Go to the documentation of this file.
1 //
3 //
4 // \file BackTracker.cc
5 // \brief The functions needed for the BackTracker class needed by the BackTracker service
6 // in order to connect truth information with reconstruction.
7 // \author jason.stock@mines.sdsmt.edu
8 //
9 // Based on the original BackTracker by brebel@fnal.gov
10 //
11 //
13 
15 
16 #include "BackTracker.h"
18 
23 
24 namespace cheat {
25 
26  //-----------------------------------------------------------------------
28  const cheat::ParticleInventory* partInv,
29  geo::GeometryCore const* geom,
30  geo::WireReadoutGeom const* wireReadoutGeom)
31  : fPartInv(partInv)
32  , fWireReadoutGeom(wireReadoutGeom)
33  , fG4ModuleLabel(config.G4ModuleLabel())
34  , fSimChannelModuleLabel(config.SimChannelModuleLabel())
35  , fHitLabel(config.DefaultHitModuleLabel())
36  , fMinHitEnergyFraction(config.MinHitEnergyFraction())
37  , fOverrideRealData(config.OverrideRealData())
38  , fHitTimeRMS(config.HitTimeRMS())
39  {}
40 
41  //-----------------------------------------------------------------------
43  const cheat::ParticleInventory* partInv,
44  geo::GeometryCore const* geom,
45  geo::WireReadoutGeom const* wireReadoutGeom)
46  : fPartInv(partInv)
47  , fWireReadoutGeom(wireReadoutGeom)
48  , fG4ModuleLabel(pSet.get<art::InputTag>("G4ModuleLabel", "largeant"))
49  , fSimChannelModuleLabel(pSet.get<art::InputTag>("SimChannelModuleLabel", fG4ModuleLabel))
50  , // -- D.R. if not provided, default behavior is to use the G4ModuleLabel
51  fHitLabel(pSet.get<art::InputTag>("DefaultHitModuleLabel", "hitfd"))
52  , fMinHitEnergyFraction(pSet.get<double>("MinHitEnergyFraction", 0.010))
53  , fOverrideRealData(pSet.get<bool>("OverrideRealData", false))
54  , fHitTimeRMS(pSet.get<double>("HitTimeRMS", 1.0))
55  {}
56 
57  //-----------------------------------------------------------------------
59  {
60  fSimChannels.clear();
61  // fAllHitList.clear();
62  }
63 
64  //-----------------------------------------------------------------------
65  std::vector<const sim::IDE*> BackTracker::TrackIdToSimIDEs_Ps(int const& id) const
66  {
67  std::vector<const sim::IDE*> ideps;
68  for (size_t sc = 0; sc < fSimChannels.size(); ++sc) {
69  const auto& tdcidemap = fSimChannels[sc]->TDCIDEMap(); // This returns a reference.
70  for (auto mapitr = tdcidemap.begin(); mapitr != tdcidemap.end(); mapitr++) {
71  // loop over the vector of IDE objects.
72  const std::vector<sim::IDE>& idevec =
73  (*mapitr).second; // note, mapitr.second returns the actual data from
74  // the map, not a copy
75  for (size_t iv = 0; iv < idevec.size(); ++iv) {
76  if (abs(idevec[iv].trackID) == id) ideps.push_back(&(idevec[iv]));
77  } // end for index in idevec
78  } // end loop over map from sim::SimChannel
79  } // end loop over sim::SimChannels
80  return ideps;
81  }
82 
83  //-----------------------------------------------------------------------
84  std::vector<const sim::IDE*> BackTracker::TrackIdToSimIDEs_Ps(int const& id,
85  const geo::View_t view) const
86  {
87  std::vector<const sim::IDE*> ide_Ps;
89  if (fWireReadoutGeom->View(sc->Channel()) != view) continue;
90 
91  for (const auto& item : sc->TDCIDEMap()) {
92 
93  // loop over the vector of IDE objects.
94  for (const sim::IDE& ide : item.second) {
95  if (abs(ide.trackID) == id) ide_Ps.push_back(&ide);
96  }
97  } // end loop over map from sim::SimChannel
98  } // end loop over sim::SimChannels
99 
100  return ide_Ps;
101  }
102 
103  //-----------------------------------------------------------------------
105  {
106  auto ilb = std::lower_bound(fSimChannels.begin(),
107  fSimChannels.end(),
108  channel,
109  [](art::Ptr<sim::SimChannel> const& a, raw::ChannelID_t channel) {
110  return (a->Channel() < channel);
111  });
112  return ((ilb != fSimChannels.end()) && ((*ilb)->Channel() == channel)) ?
113  *ilb :
115  }
116 
117  //-----------------------------------------------------------------------
119  {
120  if (auto const chan = FindSimChannelPtr(channel)) return chan;
121  throw cet::exception("BackTracker") << "No sim::SimChannel corresponding "
122  << "to channel: " << channel << "\n";
123  }
124 
125  //-----------------------------------------------------------------------
126  std::vector<sim::TrackIDE> BackTracker::ChannelToTrackIDEs(
127  detinfo::DetectorClocksData const& clockData,
128  raw::ChannelID_t channel,
129  const double hit_start_time,
130  const double hit_end_time) const
131  {
132  art::Ptr<sim::SimChannel> schannel = FindSimChannelPtr(channel);
133  if (!schannel) return {};
134 
135  std::vector<sim::TrackIDE> trackIDEs;
136  double totalE = 0.;
137 
138  // loop over the electrons in the channel and grab those that are in time with the
139  // identified hit start and stop times
140  int start_tdc = clockData.TPCTick2TDC(hit_start_time);
141  int end_tdc = clockData.TPCTick2TDC(hit_end_time);
142  if (start_tdc < 0) start_tdc = 0;
143  if (end_tdc < 0) end_tdc = 0;
144  std::vector<sim::IDE> simides = schannel->TrackIDsAndEnergies(start_tdc, end_tdc);
145 
146  // first get the total energy represented by all track ids for this channel and range
147  // of tdc values
148  for (size_t e = 0; e < simides.size(); ++e)
149  totalE += simides[e].energy;
150 
151  // protect against a divide by zero below
152  if (totalE < 1.e-5) totalE = 1.;
153 
154  // loop over the entries in the map and fill the input vectors
155  for (size_t e = 0; e < simides.size(); ++e) {
156 
157  if (simides[e].trackID == sim::NoParticleId) continue;
158 
159  sim::TrackIDE info;
160  info.trackID = simides[e].trackID;
161  info.energyFrac = simides[e].energy / totalE;
162  info.energy = simides[e].energy;
163  info.numElectrons = simides[e].numElectrons;
164 
165  trackIDEs.push_back(info);
166  }
167 
168  return trackIDEs;
169  }
170 
171  //-----------------------------------------------------------------------
172  std::vector<sim::TrackIDE> BackTracker::HitToTrackIDEs(
173  detinfo::DetectorClocksData const& clockData,
174  recob::Hit const& hit) const
175  {
176  const double start = hit.PeakTimeMinusRMS(fHitTimeRMS);
177  const double end = hit.PeakTimePlusRMS(fHitTimeRMS);
178  return ChannelToTrackIDEs(clockData, hit.Channel(), start, end);
179  }
180 
181  //-----------------------------------------------------------------------
182  std::vector<int> BackTracker::HitToTrackIds(detinfo::DetectorClocksData const& clockData,
183  recob::Hit const& hit) const
184  {
185  std::vector<int> retVec;
186  for (auto const trackIDE : HitToTrackIDEs(clockData, hit)) {
187  retVec.push_back(trackIDE.trackID);
188  }
189  return retVec;
190  }
191 
192  // These don't exist in the event. They are generated on the fly.
193  //----------------------------------------------------------------------------
194  std::vector<sim::TrackIDE> BackTracker::HitToEveTrackIDEs(
195  detinfo::DetectorClocksData const& clockData,
196  recob::Hit const& hit) const
197  {
198  std::vector<sim::TrackIDE> eveIDEs;
199  std::vector<sim::TrackIDE> trackIDEs = HitToTrackIDEs(clockData, hit);
200  std::map<int, std::pair<double, double>> eveToEMap;
201  double totalE = 0.0;
202  for (const auto& trackIDE : trackIDEs) {
203  auto check = eveToEMap.emplace(fPartInv->TrackIdToEveTrackId(trackIDE.trackID),
204  std::make_pair(trackIDE.energy, trackIDE.numElectrons));
205  if (check.second == false) {
206  check.first->second.first += trackIDE.energy;
207  check.first->second.second += trackIDE.numElectrons;
208  }
209  totalE += trackIDE.energy;
210  } // End for trackIDEs
211  eveIDEs.reserve(eveToEMap.size());
212  for (const auto& eveToE : eveToEMap) {
213  sim::TrackIDE eveTrackIDE_tmp;
214 
215  eveTrackIDE_tmp.trackID = eveToE.first;
216  eveTrackIDE_tmp.energy = eveToE.second.first;
217  eveTrackIDE_tmp.energyFrac = (eveTrackIDE_tmp.energy) / (totalE);
218  eveTrackIDE_tmp.numElectrons = eveToE.second.second;
219 
220  eveIDEs.push_back(eveTrackIDE_tmp);
221  } // END eveToEMap loop
222  return eveIDEs;
223  }
224 
225  //-----------------------------------------------------------------------
226  std::vector<art::Ptr<recob::Hit>> BackTracker::TrackIdToHits_Ps(
227  detinfo::DetectorClocksData const& clockData,
228  const int tkId,
229  std::vector<art::Ptr<recob::Hit>> const& hitsIn) const
230  {
231  // returns a subset of the hits in the hitsIn collection that are matched to the given
232  // track
233 
234  // temporary vector of TrackIds and Ptrs to hits so only one loop through the
235  // (possibly large) hitsIn collection is needed
236  std::vector<art::Ptr<recob::Hit>> hitList;
237  std::vector<sim::TrackIDE> trackIDE;
238  for (auto itr = hitsIn.begin(); itr != hitsIn.end(); ++itr) {
239  trackIDE.clear();
240  art::Ptr<recob::Hit> const& hit = *itr;
241  trackIDE = ChannelToTrackIDEs(clockData,
242  hit->Channel(),
245  for (auto itr_trakIDE = trackIDE.begin(); itr_trakIDE != trackIDE.end(); ++itr_trakIDE) {
246  if (itr_trakIDE->trackID == tkId && itr_trakIDE->energyFrac > fMinHitEnergyFraction)
247  hitList.push_back(hit);
248  } // itr_trakIDE
249  } // itr
250  return hitList;
251  }
252 
253  //-----------------------------------------------------------------------
254  // This function could clearly be made by calling TrackIdToHits for each trackId, but
255  // that would be significantly slower because we would loop through all hits many times.
256  std::vector<std::vector<art::Ptr<recob::Hit>>> BackTracker::TrackIdsToHits_Ps(
257  detinfo::DetectorClocksData const& clockData,
258  std::vector<int> const& tkIds,
259  std::vector<art::Ptr<recob::Hit>> const& hitsIn) const
260  {
261  // returns a subset of the hits in the hitsIn collection that are matched to MC
262  // particles listed in tkIds
263 
264  // temporary vector of TrackIds and Ptrs to hits so only one loop through the
265  // (possibly large) hitsIn collection is needed
266  std::vector<std::pair<int, art::Ptr<recob::Hit>>> hitList;
267  std::vector<sim::TrackIDE> tids;
268  for (auto itr = hitsIn.begin(); itr != hitsIn.end(); ++itr) {
269  tids.clear();
270  art::Ptr<recob::Hit> const& hit = *itr;
271  tids = ChannelToTrackIDEs(clockData,
272  hit->Channel(),
275  for (auto itid = tids.begin(); itid != tids.end(); ++itid) {
276  for (auto itkid = tkIds.begin(); itkid != tkIds.end(); ++itkid) {
277  if (itid->trackID == *itkid) {
278  if (itid->energyFrac > fMinHitEnergyFraction)
279  hitList.push_back(std::make_pair(*itkid, hit));
280  }
281  } // itkid
282  } // itid
283  } // itr
284 
285  // now build the truHits vector that will be returned to the caller
286  std::vector<std::vector<art::Ptr<recob::Hit>>> truHits;
287  // temporary vector containing hits assigned to one MC particle
288  std::vector<art::Ptr<recob::Hit>> tmpHits;
289  for (auto itkid = tkIds.begin(); itkid != tkIds.end(); ++itkid) {
290  tmpHits.clear();
291  for (auto itr = hitList.begin(); itr != hitList.end(); ++itr) {
292  if (*itkid == (*itr).first) tmpHits.push_back((*itr).second);
293  }
294  truHits.push_back(tmpHits);
295  }
296  return truHits;
297  }
298 
299  //-----------------------------------------------------------------------
300  //Cannot be returned as a reference, as these IDEs do not exist in the event. They are constructed on the fly.
301  std::vector<sim::IDE> BackTracker::HitToAvgSimIDEs(detinfo::DetectorClocksData const& clockData,
302  recob::Hit const& hit) const
303  {
304  int start_tdc = clockData.TPCTick2TDC(hit.PeakTimeMinusRMS(fHitTimeRMS));
305  int end_tdc = clockData.TPCTick2TDC(hit.PeakTimePlusRMS(fHitTimeRMS));
306  if (start_tdc < 0) start_tdc = 0;
307  if (end_tdc < 0) end_tdc = 0;
308 
309  return FindSimChannel(hit.Channel())->TrackIDsAndEnergies(start_tdc, end_tdc);
310  }
311 
312  //-----------------------------------------------------------------------
313  std::vector<const sim::IDE*> BackTracker::HitToSimIDEs_Ps(
314  detinfo::DetectorClocksData const& clockData,
315  recob::Hit const& hit) const
316  {
317  std::vector<const sim::IDE*> retVec;
318  int start_tdc = clockData.TPCTick2TDC(hit.PeakTimeMinusRMS(fHitTimeRMS));
319  int end_tdc = clockData.TPCTick2TDC(hit.PeakTimePlusRMS(fHitTimeRMS));
320  if (start_tdc < 0) start_tdc = 0;
321  if (end_tdc < 0) end_tdc = 0;
322 
323  if (start_tdc > end_tdc) { throw; }
324 
325  // The following does not return a std::map. It returns a vector... with no guarantee
326  // that it is sorted...
327  auto const& tdcIDEMap = FindSimChannel(hit.Channel())->TDCIDEMap();
328  std::vector<const std::pair<unsigned short, std::vector<sim::IDE>>*> tdcIDEMap_SortedPointers;
329  for (auto& pair : tdcIDEMap) {
330  tdcIDEMap_SortedPointers.push_back(&pair);
331  }
332 
333  // This is a bunch of extra steps, due to needing a vector we can sort, and needing
334  // those items in the sorted vector to be the items from the sim channels (so a
335  // pointer to the IDEs inside the sim channels can be made). The work around is to
336  // make a vector of pointers to IDEs inside the TDCIDEMap (which is a constant
337  // reference to the fTDCIDEs in the SimChannel.)
338  auto pairSort = [](auto& a, auto& b) { return a->first < b->first; };
339  if (!std::is_sorted(
340  tdcIDEMap_SortedPointers.begin(), tdcIDEMap_SortedPointers.end(), pairSort)) {
341  std::sort(tdcIDEMap_SortedPointers.begin(), tdcIDEMap_SortedPointers.end(), pairSort);
342  }
343 
344  std::vector<sim::IDE> dummyVec; // I need something to stick in a pair to compare
345  // pair<tdcVal, IDE>. This is an otherwise useless
346  // "hack".
347  std::pair<double, std::vector<sim::IDE>> start_tdcPair =
348  std::make_pair(start_tdc, dummyVec); // This pair is a "hack" to make my comparison
349  // work for lower and upper bound.
350  std::pair<double, std::vector<sim::IDE>> end_tdcPair = std::make_pair(end_tdc, dummyVec);
351  auto start_tdcPair_P = &start_tdcPair;
352  auto end_tdcPair_P = &end_tdcPair;
353  auto mapFirst = std::lower_bound(
354  tdcIDEMap_SortedPointers.begin(), tdcIDEMap_SortedPointers.end(), start_tdcPair_P, pairSort);
355 
356  // iterator to just after the last interesting IDE
357  auto mapLast = std::upper_bound(
358  tdcIDEMap_SortedPointers.begin(), tdcIDEMap_SortedPointers.end(), end_tdcPair_P, pairSort);
359  for (auto& mapitr = mapFirst; mapitr != mapLast; ++mapitr) {
360  for (auto& ide : (*mapitr)->second) {
361  retVec.push_back(&ide);
362  } // Add all interesting IDEs to the retVec
363  }
364  return retVec;
365  }
366 
367  //------------------------------------------------------------------------------
368  std::vector<double> BackTracker::SimIDEsToXYZ(std::vector<sim::IDE> const& ides) const
369  {
370  std::vector<double> xyz(3, 0.0);
371  double w = 0.0;
372  for (auto const& ide : ides) {
373  double weight = ide.numElectrons;
374  w += weight;
375  xyz[0] += (weight * ide.x);
376  xyz[1] += (weight * ide.y);
377  xyz[2] += (weight * ide.z);
378  }
379  if (w < 1.e-5)
380  throw cet::exception("BackTracker") << "No sim::IDEs providing non-zero number of electrons"
381  << " can't determine originating location from truth\n";
382  xyz[0] = xyz[0] / w;
383  xyz[1] = xyz[1] / w;
384  xyz[2] = xyz[2] / w;
385  return xyz;
386  }
387 
388  //-------------------------------------------------------------------------------
389  std::vector<double> BackTracker::SimIDEsToXYZ(std::vector<const sim::IDE*> const& ide_Ps) const
390  {
391  std::vector<sim::IDE> ides;
392  for (auto ide_P : ide_Ps) {
393  ides.push_back(*ide_P);
394  }
395  return SimIDEsToXYZ(ides);
396  }
397 
398  //--------------------------------------------------------------------------------
399  std::vector<double> BackTracker::HitToXYZ(detinfo::DetectorClocksData const& clockData,
400  const recob::Hit& hit) const
401  {
402  return SimIDEsToXYZ(HitToSimIDEs_Ps(clockData, hit));
403  }
404 
405  //-----------------------------------------------------------------------------------
407  std::set<int> const& trackIds,
408  std::vector<art::Ptr<recob::Hit>> const& hits) const
409  {
410  int desired = 0;
411  for (const auto& hit : hits) {
412  std::vector<sim::TrackIDE> hitTrackIDEs = HitToTrackIDEs(clockData, hit);
413  for (const auto& tIDE : hitTrackIDEs) {
414  if (trackIds.find(tIDE.trackID) != trackIds.end()) {
415  ++desired;
416  break;
417  } // End if TID Found
418  } // END for trackIDE in TrackIDEs
419  } // End for hit in hits
420  if (hits.size() > 0) { return double(double(desired) / double(hits.size())); }
421  return 0;
422  }
423 
424  //-----------------------------------------------------------------------------------
426  std::set<int> const& trackIds,
427  std::vector<art::Ptr<recob::Hit>> const& hits) const
428  {
429  double totalCharge = 0., desired = 0.;
430  for (const auto& hit : hits) {
431  totalCharge += hit->Integral();
432  std::vector<sim::TrackIDE> trackIDEs = HitToTrackIDEs(clockData, hit);
433  for (const auto& trackIDE : trackIDEs) {
434  if (trackIds.find(trackIDE.trackID) != trackIds.end()) {
435  desired += hit->Integral();
436  break;
437  } // End if trackId in trackIds.
438  } // End for trackIDE in trackIDEs
439  } // End for Hit in Hits
440  if (totalCharge > 0.0) { return (desired / totalCharge); }
441  return 0.0;
442  }
443 
444  //-----------------------------------------------------------------------------------
446  std::set<int> const& trackIds,
448  std::vector<art::Ptr<recob::Hit>> const& allHits,
449  geo::View_t const& view) const
450  {
451 
452  int desired = 0, total = 0;
453 
454  for (const auto& hit : hits) {
455  std::vector<sim::TrackIDE> hitTrackIDEs = HitToTrackIDEs(clockData, hit);
456  for (const auto& trackIDE : hitTrackIDEs) {
457  if (trackIds.find(trackIDE.trackID) != trackIds.end() &&
458  trackIDE.energyFrac >= fMinHitEnergyFraction) {
459  ++desired;
460  break;
461  } // End if trackID in trackIds.
462  } // end for trackIDE in TrackIDEs
463  } // end for hit in hits
464 
465  for (const auto& hit : allHits) {
466  if (hit->View() != view && view != geo::k3D) {
467  continue;
468  } // End if hit.view = view or view = geo::k3D
469  std::vector<sim::TrackIDE> hitTrackIDEs = HitToTrackIDEs(clockData, hit);
470  for (const auto& hitIDE : hitTrackIDEs) {
471  if (trackIds.find(hitIDE.trackID) != trackIds.end() &&
472  hitIDE.energyFrac >= fMinHitEnergyFraction) {
473  ++total;
474  break;
475  }
476  } // END for all IDEs in HitTrackIDEs.
477  } // end for hit in allHits.
478  if (total >= 0) { return double(double(desired) / double(total)); }
479  return 0.;
480  }
481 
482  //-----------------------------------------------------------------------------------
484  detinfo::DetectorClocksData const& clockData,
485  std::set<int> const& trackIds,
487  std::vector<art::Ptr<recob::Hit>> const& allHits,
488  geo::View_t const& view) const
489  {
490  double desired = 0., total = 0.;
491  for (const auto& hit : hits) {
492  std::vector<sim::TrackIDE> hitTrackIDEs = HitToTrackIDEs(clockData, hit);
493  for (const auto& hitIDE : hitTrackIDEs) {
494  if (trackIds.find(hitIDE.trackID) != trackIds.end() &&
495  hitIDE.energyFrac >= fMinHitEnergyFraction) {
496  desired += hit->Integral();
497  break;
498  } // end if hit id matches and energy sufficient.
499  } // End for IDE in HitTrackIDEs.
500  } // End for hit in hits.
501 
502  for (const auto& hit : allHits) {
503  if (hit->View() != view && view != geo::k3D) { continue; }
504  std::vector<sim::TrackIDE> hitTrackIDEs = HitToTrackIDEs(clockData, hit);
505  for (const auto& hitIDE : hitTrackIDEs) {
506  if (trackIds.find(hitIDE.trackID) != trackIds.end() &&
507  hitIDE.energyFrac >= fMinHitEnergyFraction) {
508  total += hit->Integral();
509  break;
510  } // end if hit matches
511  } // end for ide in ides
512  } // End for hit in allHits
513 
514  if (total > 0.) { return desired / total; }
515  return 0.;
516  }
517 
518  //-----------------------------------------------------------------------------------
520  std::vector<art::Ptr<recob::Hit>> const& hits) const
521  {
522  std::set<int> tids;
523  for (const auto& hit : hits) {
524  const double start = hit->PeakTimeMinusRMS(fHitTimeRMS);
525  const double end = hit->PeakTimePlusRMS(fHitTimeRMS);
526  std::vector<sim::TrackIDE> trackIDEs =
527  ChannelToTrackIDEs(clockData, hit->Channel(), start, end);
528  for (const auto& ide : trackIDEs) {
529  tids.insert(ide.trackID);
530  } // End for TrackIDEs
531  } // End for hits
532  return tids;
533  } // End GetSetOfTrackIds
534 
535  //-----------------------------------------------------------------------------------
537  std::vector<art::Ptr<recob::Hit>> const& hits) const
538  {
539  std::set<int> eveIds;
540  for (const auto& hit : hits) {
541  const std::vector<sim::TrackIDE> ides = HitToEveTrackIDEs(clockData, hit);
542  for (const auto& ide : ides) {
543  eveIds.insert(ide.trackID);
544  } // end ides
545  } // End for hits
546  return eveIds;
547  }
548 
549  // This function definitely needs a new implementation. There must be a better way than
550  // so many loops.
552  detinfo::DetectorClocksData const& clockData,
553  std::vector<art::Ptr<recob::Hit>> const& hits) const
554  {
555  std::vector<std::vector<std::vector<int>>> numHits(fGeom->Ncryostats());
556  std::vector<std::vector<std::vector<double>>> hitWeight(fGeom->Ncryostats());
557  std::vector<std::vector<std::vector<std::vector<double>>>> hitPos(fGeom->Ncryostats());
558  // Do we need to resize everything...
559  for (size_t c = 0; c < numHits.size(); ++c) {
560  geo::CryostatID const cid(c);
561  numHits[c].resize(fGeom->NTPC(cid));
562  hitWeight[c].resize(fGeom->NTPC(cid));
563  hitPos[c].resize(fGeom->NTPC(cid));
564  for (size_t t = 0; t < numHits[c].size(); ++t) {
565  geo::TPCID const tpcid(cid, t);
566  numHits[c][t].resize(fWireReadoutGeom->Nplanes(tpcid));
567  hitWeight[c][t].resize(fWireReadoutGeom->Nplanes(tpcid));
568  hitPos[c][t].resize(fWireReadoutGeom->Nplanes(tpcid));
569  }
570  }
571 
572  for (auto const& hit_ptr : hits) {
573  const recob::Hit& hit = *hit_ptr;
574 
575  // use the HitToXYZ and Geometry::PositionToTPC to figure out which drift volume the
576  // hit originates from
577  std::vector<double> hitOrigin = HitToXYZ(clockData, hit_ptr);
578  geo::Point_t const worldLoc{hitOrigin[0], hitOrigin[1], hitOrigin[2]};
579  auto const tpcid = fGeom->PositionToTPCID(worldLoc);
580 
581  auto const [cstat, tpc] = std::make_tuple(tpcid.Cryostat, tpcid.TPC);
582 
583  if (hit.WireID().Cryostat == cstat && hit.WireID().TPC == tpc) {
584  ++numHits[cstat][tpc][hit.WireID().Plane];
585  hitWeight[cstat][tpc][hit.WireID().Plane] = hit.Integral();
586  hitPos[cstat][tpc][hit.WireID().Plane] = hitOrigin;
587  }
588  }
589 
590  // loop over the vectors we made and find the average position for the hits
591  // in the future we might take a weighted average
592  int nhits = 0;
593  std::vector<double> xyz(3);
594  for (size_t c = 0; c < numHits.size(); ++c) {
595  for (size_t t = 0; t < numHits[c].size(); ++t) {
596  for (size_t p = 0; p < numHits[c][t].size(); ++p) {
597 
598  if (numHits[c][t][p] == 1) {
599  ++nhits;
600  xyz[0] += hitPos[c][t][p][0];
601  xyz[1] += hitPos[c][t][p][1];
602  xyz[2] += hitPos[c][t][p][2];
603  }
604 
605  } // end loop over planes
606  } // end loop over tpcs
607  } // end loop over cryostats
608 
609  // get the average position
610  if (nhits < 1)
611  throw cet::exception("BackTracker")
612  << "No hits to determine originating location from truth\n";
613 
614  xyz[0] /= nhits;
615  xyz[1] /= nhits;
616  xyz[2] /= nhits;
617 
618  // Done.
619  return xyz;
620  }
621 
622 } // End namespace cheat
TrackID_t trackID
Geant4 supplied track ID.
Definition: SimChannel.h:107
const art::InputTag fHitLabel
Definition: BackTracker.h:239
const geo::GeometryCore * fGeom
Definition: BackTracker.h:235
std::vector< art::Ptr< sim::SimChannel > > fSimChannels
Definition: BackTracker.h:244
std::vector< std::vector< art::Ptr< recob::Hit > > > TrackIdsToHits_Ps(detinfo::DetectorClocksData const &clockData, std::vector< int > const &tkIds, std::vector< art::Ptr< recob::Hit >> const &hitsIn) const
Definition: BackTracker.cc:256
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
art::Ptr< sim::SimChannel > FindSimChannelPtr(raw::ChannelID_t channel) const
Returns the cached sim::SimChannel on the specified channel.
Definition: BackTracker.cc:104
std::vector< sim::TrackIDE > HitToEveTrackIDEs(detinfo::DetectorClocksData const &clockData, recob::Hit const &hit) const
Definition: BackTracker.cc:194
unsigned int NTPC(CryostatID const &cryoid=details::cryostat_zero) const
Returns the total number of TPCs in the specified cryostat.
Definition: GeometryCore.h:416
const art::InputTag fSimChannelModuleLabel
Definition: BackTracker.h:238
float numElectrons
number of electrons from the particle detected on the wires
Definition: SimChannel.h:30
constexpr auto abs(T v)
Returns the absolute value of the argument.
const double fMinHitEnergyFraction
Definition: BackTracker.h:240
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:195
float Integral() const
Integral under the calibrated signal waveform of the hit, in tick x ADC units.
Definition: Hit.h:254
geo::WireID const & WireID() const
Initial tdc tick for hit.
Definition: Hit.h:290
float energy
energy from the particle with this trackID [MeV]
Definition: SimChannel.h:29
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
Definition: GeometryCore.h:303
pure virtual base interface for detector clocks
std::vector< sim::TrackIDE > HitToTrackIDEs(detinfo::DetectorClocksData const &clockData, recob::Hit const &hit) const
Definition: BackTracker.cc:172
3-dimensional objects, potentially hits, clusters, prongs, etc.
Definition: geo_types.h:137
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
Access the description of the physical detector geometry.
const geo::WireReadoutGeom * fWireReadoutGeom
Definition: BackTracker.h:236
void hits()
Definition: readHits.C:15
std::vector< double > HitToXYZ(detinfo::DetectorClocksData const &clockData, const recob::Hit &hit) const
Definition: BackTracker.cc:399
Ionization at a point of the TPC sensitive volume.
Definition: SimChannel.h:85
static const int NoParticleId
Definition: sim.h:21
Interface for a class providing readout channel mapping to geometry.
art::Ptr< sim::SimChannel > FindSimChannel(raw::ChannelID_t channel) const
Returns the cached sim::SimChannel on the specified channel.
Definition: BackTracker.cc:118
std::vector< art::Ptr< recob::Hit > > TrackIdToHits_Ps(detinfo::DetectorClocksData const &clockData, int tkId, std::vector< art::Ptr< recob::Hit >> const &hitsIn) const
Definition: BackTracker.cc:226
std::set< int > GetSetOfTrackIds() const
Definition: BackTracker.h:221
double HitCollectionPurity(detinfo::DetectorClocksData const &clockData, std::set< int > const &trackIds, std::vector< art::Ptr< recob::Hit >> const &hits) const
Definition: BackTracker.cc:406
double energy
Definition: plottest35.C:25
float energyFrac
fraction of hit energy from the particle with this trackID
Definition: SimChannel.h:28
const cheat::ParticleInventory * fPartInv
Definition: BackTracker.h:234
const double fHitTimeRMS
Definition: BackTracker.h:242
The data type to uniquely identify a TPC.
Definition: geo_types.h:306
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
Description of the physical geometry of one entire detector.
Definition: GeometryCore.h:91
Definition of data types for geometry description.
float PeakTimeMinusRMS(float sigmas=+1.) const
Returns a time sigmas RMS away from the peak time.
Definition: Hit.h:300
Detector simulation of raw signals on wires.
unsigned int Nplanes(TPCID const &tpcid=details::tpc_zero) const
Returns the total number of planes in the specified TPC.
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:180
std::vector< sim::TrackIDE > ChannelToTrackIDEs(detinfo::DetectorClocksData const &clockData, raw::ChannelID_t channel, const double hit_start_time, const double hit_end_time) const
Definition: BackTracker.cc:126
double weight
Definition: plottest35.C:25
std::set< int > GetSetOfEveIds() const
Definition: BackTracker.h:222
double HitChargeCollectionPurity(detinfo::DetectorClocksData const &clockData, std::set< int > const &trackIds, std::vector< art::Ptr< recob::Hit >> const &hits) const
Definition: BackTracker.cc:425
decltype(auto) get(T &&obj)
ADL-aware version of std::to_string.
Definition: StdUtils.h:120
code to link reconstructed objects back to the MC truth information
Definition: BackTracker.cc:24
int trackID
Geant4 supplied trackID.
Definition: SimChannel.h:27
const bool fOverrideRealData
Definition: BackTracker.h:241
BackTracker(const fhiclConfig &config, const cheat::ParticleInventory *partInv, geo::GeometryCore const *geom, geo::WireReadoutGeom const *wireReadoutGeom)
Definition: BackTracker.cc:27
Contains all timing reference information for the detector.
View_t View(raw::ChannelID_t const channel) const
Returns the view (wire orientation) on the specified TPC channel.
std::vector< sim::IDE > TrackIDsAndEnergies(TDC_t startTDC, TDC_t endTDC) const
Return all the recorded energy deposition within a time interval.
Definition: SimChannel.cxx:153
std::vector< int > HitToTrackIds(detinfo::DetectorClocksData const &clockData, recob::Hit const &hit) const
Definition: BackTracker.cc:182
Float_t sc
Definition: plot.C:23
double HitCollectionEfficiency(detinfo::DetectorClocksData const &clockData, std::set< int > const &trackIds, std::vector< art::Ptr< recob::Hit >> const &hits, std::vector< art::Ptr< recob::Hit >> const &allhits, geo::View_t const &view) const
Definition: BackTracker.cc:445
std::vector< const sim::IDE * > TrackIdToSimIDEs_Ps(int const &id) const
Definition: BackTracker.cc:65
const art::InputTag fG4ModuleLabel
Definition: BackTracker.h:237
Definition: MVAAlg.h:12
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:46
float PeakTimePlusRMS(float sigmas=+1.) const
Returns a time sigmas RMS away from the peak time.
Definition: Hit.h:295
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:315
std::vector< sim::IDE > HitToAvgSimIDEs(detinfo::DetectorClocksData const &clockData, recob::Hit const &hit) const
Definition: BackTracker.cc:301
Float_t e
Definition: plot.C:35
int TrackIdToEveTrackId(const int &tid) const
Float_t w
Definition: plot.C:20
Ionization energy from a Geant4 track.
Definition: SimChannel.h:26
raw::ChannelID_t Channel() const
ID of the readout channel the hit was extracted from.
Definition: Hit.h:278
std::vector< double > SimIDEsToXYZ(std::vector< sim::IDE > const &ides) const
Definition: BackTracker.cc:368
double HitChargeCollectionEfficiency(detinfo::DetectorClocksData const &clockData, std::set< int > const &trackIds, std::vector< art::Ptr< recob::Hit >> const &hits, std::vector< art::Ptr< recob::Hit >> const &allhits, geo::View_t const &view) const
Definition: BackTracker.cc:483
double TPCTick2TDC(double const tick) const
Tools and modules for checking out the basics of the Monte Carlo.
TPCID PositionToTPCID(Point_t const &point) const
Returns the ID of the TPC at specified location.
Interface to geometry for wire readouts .
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
The data type to uniquely identify a cryostat.
Definition: geo_types.h:187
std::vector< const sim::IDE * > HitToSimIDEs_Ps(detinfo::DetectorClocksData const &clockData, recob::Hit const &hit) const
Definition: BackTracker.cc:313
std::vector< double > SpacePointHitsToWeightedXYZ(detinfo::DetectorClocksData const &clockData, std::vector< art::Ptr< recob::Hit >> const &hits) const
Definition: BackTracker.cc:551