LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
old.PhotonBackTracker_service.cc
Go to the documentation of this file.
1 //
3 //
4 // \file: PhotonBackTracker_service.cc
5 //
6 //jason.stock@mines.sdsmt.edu
7 //Based on the BackTracker_service by Brian Rebel
8 //
10 #include <map>
11 
12 // Framework includes
16 
17 // LArSoft includes
29 
30 namespace cheat {
31 
32  //----------------------------------------------------------------------
34  {
35  reconfigure(pset);
36 
38  }
39 
40  //----------------------------------------------------------------------
42 
43  //----------------------------------------------------------------------
45  {
46  fG4ModuleLabel = pset.get<std::string>("G4ModuleLabel", "largeant");
47  fMinOpHitEnergyFraction = pset.get<double>("MinimumOpHitEnergyFraction", 0.1);
48  fDelay = pset.get<double>("Delay");
49  have_complained = false;
50  }
51 
52  //----------------------------------------------------------------------
54  {
55  // do nothing if this is data
56  if (evt.isRealData()) return;
57 
58  // get the particles from the event
60  evt.getByLabel(fG4ModuleLabel, pHandle);
61 
62  // first check to see if we got called to early, that is the particles are
63  // and sim channels are not made yet in a MC production job
64  // if that is the case, we'll take care of it later
65  if (pHandle.failedToGet()) {
66  mf::LogWarning("PhotonBackTracker")
67  << "failed to get handle to simb::MCParticle from " << fG4ModuleLabel << ", return";
68  return;
69  }
70 
71  // Clear out anything remaining from previous calls to Rebuild
73  fMCTruthList.clear();
75  //fVoxelList .clear();
76 
78 
79  if (fo.isValid()) {
80  for (size_t p = 0; p < pHandle->size(); ++p) {
81 
82  simb::MCParticle* part = new simb::MCParticle(pHandle->at(p));
83  fParticleList.Add(part);
84 
85  // get the simb::MCTruth associated to this sim::ParticleList
86  try {
87  art::Ptr<simb::MCTruth> mct = fo.at(p);
88  if (fMCTruthList.size() < 1)
89  fMCTruthList.push_back(mct);
90  else {
91  // check that we are not adding a simb::MCTruth twice to the collection
92  // we know that all the particles for a given simb::MCTruth are put into the
93  // collection of particles at the same time, so we can just check that the
94  // current art::Ptr has a different id than the last one put
95  if (!(mct == fMCTruthList.back())) fMCTruthList.push_back(mct);
96  }
97  // fill the track id to mctruth index map
98  fTrackIDToMCTruthIndex[pHandle->at(p).TrackId()] = fMCTruthList.size() - 1;
99  }
100  catch (cet::exception& ex) {
101  mf::LogWarning("PhotonBackTracker") << "unable to find MCTruth from ParticleList "
102  << "created in " << fG4ModuleLabel << " "
103  << "any attempt to get the MCTruth objects from "
104  << "the photon backtracker will fail\n"
105  << "message from caught exception:\n"
106  << ex;
107  }
108  } // end loop over particles to get MCTruthList
109  } // end if fo.isValid()
110 
111  // grab the sim::OpDetBacktrackerRecords for this event
112 
113  /*
114  try{evt.getView(fG4ModuleLabel, cOpDetBacktrackerRecords);}
115  catch(art::Exception const& e){
116  if(e.categoryCode() != art::errors::ProductNotFound) throw;
117  if(have_complained==false){
118  }
119  }
120  */
121 
123  // std::vector< art::Ptr< sim::OpDetBacktrackerRecords > > cOpDetBacktrackerRecords;
124  evt.getByLabel(fG4ModuleLabel, cPBTRHandle);
125  if (
126  cPBTRHandle
127  .failedToGet()) { //Failed to get products. Prepare for controlled freak out. Assuming this is because there is no OpDetBacktrackerRecords, we will not cause things to fail, but will prepare to fail if a user tries to call backtracker functionality.
128  auto failMode = cPBTRHandle.whyFailed();
129  if (failMode->categoryCode() != art::errors::ProductNotFound)
130  throw;
131  else if (have_complained == false) {
132  std::cout << "FAILED BECAUSE " << (*failMode) << "\n";
133  have_complained = true;
134  mf::LogWarning("PhotonBackTracker")
135  << "Failed to get BackTrackerRecords from this event. All calls to the PhotonBackTracker "
136  "will fail.\n"
137  << "This message will be generated only once per lar invokation. If this is event one, "
138  "be aware the PhotonBackTracker may not work on any events from this file.\n"
139  << "Please change the log level to debug if you need more information for each event.\n"
140  << "Failed with :" << (*failMode) << "\n";
141  mf::LogDebug("PhotonBackTracker") << "Failed to get BackTrackerRecords from this event.\n";
142  }
143  else {
144  mf::LogDebug("PhotonBackTracker") << "Failed to get BackTrackerRecords from this event.\n";
145  }
146  }
147  else { //Did not fail to get products. All is well. Run as expected.
149  }
150 
151  // grab the voxel list for this event
152  //fVoxelList = sim::SimListUtils::GetLArVoxelList(evt, fG4ModuleLabel);
153 
155 
156  MF_LOG_DEBUG("PhotonBackTracker")
157  << "PhotonBackTracker has " << cOpDetBacktrackerRecords.size()
158  << " sim::OpDetBacktrackerRecords and " << GetSetOfTrackIDs().size()
159  << " tracks. The particles are:\n"
160  << fParticleList << "\n the MCTruth information is\n";
161  for (size_t mc = 0; mc < fMCTruthList.size(); ++mc)
162  MF_LOG_DEBUG("PhotonBackTracker") << *(fMCTruthList.at(mc).get());
163 
164  return;
165  }
166 
167  //----------------------------------------------------------------------
169  {
170  //I need to revisit this and see if this check is too aggressive, as it only takes one failed event to set have_complained to true for the rest of the file.
171  //I currently do believe this is okay, as have_complained only flips on ProductNotFound errors, and if that happens in one event of a file,
172  // it should happen in all events of the file.
173  if (have_complained == true) {
174  throw cet::exception("PhotonBackTracker1")
175  << "PhotonBackTracker methods called on a file without OpDetPhotonBacktrackerRecords. "
176  "Backtracked information is not available.";
177  }
178  }
179 
180  //----------------------------------------------------------------------
182  {
183  shouldThisFail();
185 
186  if (part_it == fParticleList.end()) {
187  mf::LogWarning("PhotonBackTracker")
188  << "can't find particle with track id " << id << " in sim::ParticleList"
189  << " returning null pointer";
190  return 0;
191  }
192 
193  return part_it->second;
194  }
195 
196  //----------------------------------------------------------------------
198  {
199  shouldThisFail();
200  // get the mother id from the particle navigator
201  // the EveId was adopted in the Rebuild method
202 
203  return this->TrackIDToParticle(fParticleList.EveId(abs(id)));
204  }
205 
206  //----------------------------------------------------------------------
208  {
209  shouldThisFail();
210  // find the entry in the MCTruth collection for this track id
211  size_t mct = fTrackIDToMCTruthIndex.find(abs(id))->second;
212 
213  if (/* mct < 0 || */ mct > fMCTruthList.size())
214  throw cet::exception("PhotonBackTracker")
215  << "attempting to find MCTruth index for "
216  << "out of range value: " << mct << "/" << fMCTruthList.size() << "\n";
217 
218  return fMCTruthList[mct];
219  }
220 
221  //----------------------------------------------------------------------
222  std::vector<sim::SDP> PhotonBackTracker::TrackIDToSimSDP(int const& id) const
223  {
224  shouldThisFail();
225  std::vector<sim::SDP> sdps;
226 
227  // loop over all sim::OpDetBacktrackerRecords and fill a vector
228  // of sim::SDP objects for the given track id
229  for (size_t sc = 0; sc < cOpDetBacktrackerRecords.size(); ++sc) {
230  const auto& pdTimeSDPmap = cOpDetBacktrackerRecords[sc]->timePDclockSDPsMap();
231 
232  // loop over the SDPMAP
233  for (auto mapitr = pdTimeSDPmap.begin(); mapitr != pdTimeSDPmap.end(); mapitr++) {
234 
235  // loop over the vector of SDP objects.
236  const std::vector<sim::SDP>& sdpvec = (*mapitr).second;
237  for (size_t iv = 0; iv < sdpvec.size(); ++iv) {
238  if (abs(sdpvec[iv].trackID) == id) sdps.push_back(sdpvec[iv]);
239  }
240 
241  } // end loop over map from sim::OpDetBacktrackerRecord
242  } // end loop over sim::OpDetBacktrackerRecords
243 
244  return sdps;
245  }
246 
247  //----------------------------------------------------------------------
249  const simb::MCParticle* p) const
250  {
251  shouldThisFail();
252  return this->TrackIDToMCTruth(p->TrackId());
253  }
254 
255  //----------------------------------------------------------------------
256  std::vector<const simb::MCParticle*> PhotonBackTracker::MCTruthToParticles(
257  art::Ptr<simb::MCTruth> const& mct) const
258  {
259  shouldThisFail();
260  std::vector<const simb::MCParticle*> ret;
261 
262  // sim::ParticleList::value_type is a pair (track ID, particle pointer)
263  for (const sim::ParticleList::value_type& TrackIDpair : fParticleList) {
264  if (TrackIDToMCTruth(TrackIDpair.first) == mct) ret.push_back(TrackIDpair.second);
265  }
266 
267  return ret;
268  }
269 
270  //----------------------------------------------------------------------
271  std::vector<sim::TrackSDP> PhotonBackTracker::OpHitToTrackSDPs(
272  art::Ptr<recob::OpHit> const& opHit)
273  {
274  shouldThisFail();
275  std::vector<sim::TrackSDP> trackSDPs;
276  const double pTime = opHit->PeakTime();
277  const double pWidth = opHit->Width();
278  const double start = (pTime - pWidth) * 1000 - fDelay;
279  const double end = (pTime + pWidth) * 1000 - fDelay;
280 
281  this->ChannelToTrackSDPs(trackSDPs, opHit->OpChannel(), start, end);
282 
283  return trackSDPs;
284  }
285 
286  //----------------------------------------------------------------------
287  const std::vector<std::vector<art::Ptr<recob::OpHit>>> PhotonBackTracker::TrackIDsToOpHits(
288  std::vector<art::Ptr<recob::OpHit>> const& allOpHits,
289  std::vector<int> const& tkIDs)
290  {
291  shouldThisFail();
292  // returns a subset of the opHits in the allOpHits collection that are matched
293  // to MC particles listed in tkIDs
294 
295  // temporary vector of TrackIDs and Ptrs to opHits so only one
296  // loop through the (possibly large) allOpHits collection is needed
297  std::vector<std::pair<int, art::Ptr<recob::OpHit>>> opHitList;
298  std::vector<sim::TrackSDP> tids;
299  for (auto itr = allOpHits.begin(); itr != allOpHits.end(); ++itr) {
300  tids.clear();
301  art::Ptr<recob::OpHit> const& opHit = *itr;
302  const double pTime = opHit->PeakTime(), pWidth = opHit->Width();
303  const double start = (pTime - pWidth) * 1000.0 - fDelay,
304  end = (pTime + pWidth) * 1000.0 - fDelay;
305  this->ChannelToTrackSDPs(tids, opHit->OpChannel(), start, end);
306  for (auto itid = tids.begin(); itid != tids.end(); ++itid) {
307  for (auto itkid = tkIDs.begin(); itkid != tkIDs.end(); ++itkid) {
308  if (itid->trackID == *itkid) {
309  if (itid->energyFrac > fMinOpHitEnergyFraction)
310  opHitList.push_back(std::make_pair(*itkid, opHit));
311  }
312  } // itkid
313  } // itid
314  } // itr
315 
316  // now build the truOpHits vector that will be returned to the caller
317  std::vector<std::vector<art::Ptr<recob::OpHit>>> truOpHits;
318  // temporary vector containing opHits assigned to one MC particle
319  std::vector<art::Ptr<recob::OpHit>> tmpOpHits;
320  for (auto itkid = tkIDs.begin(); itkid != tkIDs.end(); ++itkid) {
321  tmpOpHits.clear();
322  for (auto itr = opHitList.begin(); itr != opHitList.end(); ++itr) {
323  if (*itkid == (*itr).first) tmpOpHits.push_back((*itr).second);
324  }
325  truOpHits.push_back(tmpOpHits);
326  }
327 
328  return truOpHits;
329  }
330 
331  //----------------------------------------------------------------------
332 
333  std::vector<sim::TrackSDP> PhotonBackTracker::OpHitToEveSDPs(art::Ptr<recob::OpHit> const& opHit)
334  {
335  shouldThisFail();
336  std::vector<sim::TrackSDP> trackSDPs = this->OpHitToTrackSDPs(opHit);
337 
338  // make a map of evd ID values and fraction of energy represented by
339  // that eve id in this opHit
340  std::map<int, float> eveIDtoEfrac;
341 
342  double totalE = 0.;
343  for (size_t t = 0; t < trackSDPs.size(); ++t) {
344  eveIDtoEfrac[fParticleList.EveId(trackSDPs[t].trackID)] += trackSDPs[t].energy;
345  totalE += trackSDPs[t].energy;
346  }
347 
348  // now fill the eveSDPs vector from the map
349  std::vector<sim::TrackSDP> eveSDPs;
350  eveSDPs.reserve(eveIDtoEfrac.size());
351  for (auto itr = eveIDtoEfrac.begin(); itr != eveIDtoEfrac.end(); itr++) {
352  sim::TrackSDP temp;
353  temp.trackID = (*itr).first;
354  temp.energyFrac = (*itr).second / totalE;
355  temp.energy = (*itr).second;
356  eveSDPs.push_back(std::move(temp));
357  }
358 
359  return eveSDPs;
360  }
361  std::vector<sim::TrackSDP> PhotonBackTracker::OpHitToEveID(art::Ptr<recob::OpHit> const& opHit)
362  {
363  mf::LogWarning("PhotonBackTracker")
364  << "PhotonBackTracker::OpHitToEveID is being replaced with "
365  "PhotonBackTracker::OpHitToEveSDPs. Please \n update your code accordingly.\n ";
366  std::vector<sim::TrackSDP> eveSDPs = OpHitToEveSDPs(opHit);
367  return eveSDPs;
368  }
369 
370  //----------------------------------------------------------------------
372  {
373  shouldThisFail();
374  std::set<int> eveIDs;
375 
377  while (plitr != fParticleList.end()) {
378  int eveID = fParticleList.EveId((*plitr).first);
379  // look to see if this eveID is already in the set
380  if (eveIDs.find(eveID) == eveIDs.end()) eveIDs.insert(eveID);
381  plitr++;
382  }
383 
384  return eveIDs;
385  }
386 
387  //----------------------------------------------------------------------
389  {
390  shouldThisFail();
391  // fParticleList::value_type is a pair (track, particle pointer)
392  std::set<int> trackIDs;
394  trackIDs.insert(pl.first);
395 
396  return trackIDs;
397  }
398 
399  //----------------------------------------------------------------------
401  {
402  shouldThisFail();
403  std::set<int> eveIDs;
404 
405  std::vector<art::Ptr<recob::OpHit>>::const_iterator itr = opHits.begin();
406  while (itr != opHits.end()) {
407 
408  // get the eve ids corresponding to this opHit
409  const std::vector<sim::TrackSDP> sdps = OpHitToEveID(*itr);
410 
411  // loop over the sdps and extract the track ids
412  for (size_t i = 0; i < sdps.size(); ++i)
413  eveIDs.insert(sdps[i].trackID);
414 
415  itr++;
416  }
417 
418  return eveIDs;
419  }
420 
421  //----------------------------------------------------------------------
423  std::vector<art::Ptr<recob::OpHit>> const& opHits)
424  {
425  shouldThisFail();
426  std::set<int> trackIDs;
427 
428  std::vector<art::Ptr<recob::OpHit>>::const_iterator itr = opHits.begin();
429  while (itr != opHits.end()) {
430 
431  std::vector<sim::TrackSDP> trackSDPs;
432 
433  // get the track ids corresponding to this opHit
434  const double pTime = (*itr)->PeakTime();
435  const double pWidth = (*itr)->Width();
436  const double start = (pTime - pWidth) * 1000.0 - fDelay;
437  const double end = (pTime + pWidth) * 1000.0 - fDelay;
438  // const double start = (*itr)->PeakTimeMinusRMS();
439  // const double end = (*itr)->PeakTimePlusRMS();
440 
441  this->ChannelToTrackSDPs(trackSDPs, (*itr)->OpChannel(), start, end);
442 
443  // loop over the sdps and extract the track ids
444  for (size_t i = 0; i < trackSDPs.size(); ++i) {
445  trackIDs.insert(trackSDPs[i].trackID);
446  }
447 
448  itr++;
449  }
450 
451  return trackIDs;
452  }
453 
454  //----------------------------------------------------------------------
455  double PhotonBackTracker::OpHitCollectionPurity(std::set<int> trackIds,
456  std::vector<art::Ptr<recob::OpHit>> const& opHits)
457  {
458  shouldThisFail();
459  // get the list of EveIDs that correspond to the opHits in this collection
460  // if the EveID shows up in the input list of trackIDs, then it counts
461  float total = 1. * opHits.size();
462  ;
463  float desired = 0.;
464  for (size_t h = 0; h < opHits.size(); ++h) {
465  art::Ptr<recob::OpHit> opHit = opHits[h];
466  std::vector<sim::TrackSDP> opHitTrackSDPs = this->OpHitToTrackSDPs(opHit);
467  // don't double count if this opHit has more than one of the
468  // desired track IDs associated with it
469  for (size_t e = 0; e < opHitTrackSDPs.size(); ++e) {
470  if (trackIds.find(opHitTrackSDPs[e].trackID) != trackIds.end()) {
471  desired += 1.;
472  break;
473  }
474  }
475  } // end loop over opHits
476  double purity = 0.;
477  if (total > 0) purity = desired / total;
478  return purity;
479  }
480 
481  //----------------------------------------------------------------------
483  std::set<int> trackIDs,
484  std::vector<art::Ptr<recob::OpHit>> const& opHits)
485  {
486  shouldThisFail();
487  // get the list of EveIDs that correspond to the opHits in this collection
488  // if the EveID shows up in the input list of trackIDs, then it counts
489  float total = 0;
490  float desired = 0.;
491  // don't have to check the view in the opHits collection because
492  // those are assumed to be from the object we are testing and will
493  // the correct view by definition then.
494  for (size_t h = 0; h < opHits.size(); ++h) {
495  art::Ptr<recob::OpHit> opHit = opHits[h];
496  std::vector<sim::TrackSDP> opHitTrackIDs = this->OpHitToTrackSDPs(opHit);
497  total += opHit->Area(); // sum up the charge in the cluster
498  // don't double count if this opHit has more than one of the
499  // desired track IDs associated with it
500  for (size_t e = 0; e < opHitTrackIDs.size(); ++e) {
501  if (trackIDs.find(opHitTrackIDs[e].trackID) != trackIDs.end()) {
502  desired += opHit->Area();
503  break;
504  }
505  }
506  } // end loop over opHits
507  double purity = 0.;
508  if (total > 0) purity = desired / total;
509  return purity;
510  }
511 
512  //----------------------------------------------------------------------
514  std::set<int> trackIDs,
515  std::vector<art::Ptr<recob::OpHit>> const& opHits,
516  std::vector<art::Ptr<recob::OpHit>> const& allOpHits,
517  geo::View_t const& view)
518  {
519  throw cet::exception("PhotonBackTracker")
520  << "This function is not supported. OpHits do not have type View.\n";
521  }
522 
524  std::set<int> trackIds,
525  std::vector<art::Ptr<recob::OpHit>> const& opHits,
526  std::vector<art::Ptr<recob::OpHit>> const& allOpHits)
527  {
528  shouldThisFail();
529  float desired = 0.;
530  float total = 0.;
531  for (size_t h = 0; h < opHits.size(); ++h) {
532  art::Ptr<recob::OpHit> opHit = opHits[h];
533  std::vector<sim::TrackSDP> opHitTrackSDPs = this->OpHitToTrackSDPs(opHit);
534  // also don't double count if this opHit has more than one of the
535  // desired track IDs associated with it
536  for (size_t e = 0; e < opHitTrackSDP.size(); ++e) {
537  if (trackIDs.find(opHitTrackSDPs[e].trackID) != trackIDs.end() &&
538  opHitTrackSDPs[e].energyFrac >= fMinOpHitEnergyFraction) {
539  desired += 1.;
540  break;
541  }
542  }
543  } // end loop over opHits
544  // now figure out how many opHits in the whole collection are associated with this id
545  for (size_t h = 0; h < allOpHits.size(); ++h) {
546  art::Ptr<recob::OpHit> opHit = allOpHits[h];
547  std::vector<sim::TrackSDP> opHitTrackSDPs = this->OpHitToTrackSDPs(opHit);
548  for (size_t e = 0; e < opHitTrackSDPs.size(); ++e) {
549  // don't worry about opHits where the energy fraction for the chosen
550  // trackID is < 0.1
551  // also don't double count if this opHit has more than one of the
552  // desired track IDs associated with it
553  if (trackIDs.find(opHitTrackSDPs[e].trackID) != trackIDs.end() &&
554  opHitTrackIDs[e].energyFrac >= fMinOpHitEnergyFraction) {
555  total += 1.;
556  break;
557  }
558  }
559  } // end loop over all opHits
560  double efficiency = 0.;
561  if (total > 0.) efficiency = desired / total;
562  return efficiency;
563  }
564 
565  //----------------------------------------------------------------------
567  std::set<int> trackIDs,
568  std::vector<art::Ptr<recob::OpHit>> const& opHits,
569  std::vector<art::Ptr<recob::OpHit>> const& allOpHits,
570  geo::View_t const& view)
571  {
572  throw cet::exception("PhotonBackTracker")
573  << "This function is not supported. OpHits do not have type View.\n";
574  }
576  std::set<int> trackIDs,
577  std::vector<art::Ptr<recob::OpHit>> const& opHits,
578  std::vector<art::Ptr<recob::OpHit>> const& allOpHits)
579  {
580  shouldThisFail();
581  // get the list of EveIDs that correspond to the opHits in this collection
582  // and the energy associated with the desired trackID
583  float desired = 0.;
584  float total = 0.;
585 
586  // don't have to check the view in the opHits collection because
587  // those are assumed to be from the object we are testing and will
588  // the correct view by definition then.
589  for (size_t h = 0; h < opHits.size(); ++h) {
590 
591  art::Ptr<recob::OpHit> opHit = opHits[h];
592  std::vector<sim::TrackSDP> opHitTrackIDs = this->OpHitToTrackSDPs(opHit);
593 
594  // don't worry about opHits where the energy fraction for the chosen
595  // trackID is < 0.1
596  // also don't double count if this opHit has more than one of the
597  // desired track IDs associated with it
598  for (size_t e = 0; e < opHitTrackIDs.size(); ++e) {
599  if (trackIDs.find(opHitTrackIDs[e].trackID) != trackIDs.end() &&
600  opHitTrackIDs[e].energyFrac >= fMinOpHitEnergyFraction) {
601  desired += opHit->Area();
602  break;
603  }
604  }
605  } // end loop over opHits
606 
607  // now figure out how many opHits in the whole collection are associated with this id
608  for (size_t h = 0; h < allOpHits.size(); ++h) {
609 
610  art::Ptr<recob::OpHit> opHit = allOpHits[h];
611 
612  // check that we are looking at the appropriate view here
613  // in the case of 3D objects we take all opHits
614  //if(opHit->View() != view && view != geo::k3D ) continue;
615 
616  std::vector<sim::TrackSDP> opHitTrackIDs = this->OpHitToTrackSDPs(opHit);
617 
618  for (size_t e = 0; e < opHitTrackIDs.size(); ++e) {
619  // don't worry about opHits where the energy fraction for the chosen
620  // trackID is < 0.1
621  // also don't double count if this opHit has more than one of the
622  // desired track IDs associated with it
623  if (trackIDs.find(opHitTrackIDs[e].trackID) != trackIDs.end() &&
624  opHitTrackIDs[e].energyFrac >= fMinOpHitEnergyFraction) {
625  total += opHit->Area();
626  break;
627  }
628  }
629 
630  } // end loop over all opHits
631 
632  double efficiency = 0.;
633  if (total > 0.) efficiency = desired / total;
634 
635  return efficiency;
636  }
637 
638  //----------------------------------------------------------------------
640  int opDetNum) const
641  {
642  shouldThisFail();
644 
645  for (size_t sc = 0; sc < cOpDetBacktrackerRecords.size(); ++sc) {
646  //This could become a bug. What if it occurs twice (shouldn't happen in correct recorts, but still, no error handeling included for the situation
647  if (cOpDetBacktrackerRecords[sc]->OpDetNum() == opDetNum)
648  opDet = cOpDetBacktrackerRecords[sc];
649  }
650 
651  if (!opDet) {
652  throw cet::exception("PhotonBackTracker2") << "No sim::OpDetBacktrackerRecord corresponding "
653  << "to opDetNum: " << opDetNum << "\n";
654  }
655 
656  return opDet;
657  }
658 
659  //----------------------------------------------------------------------
660  void PhotonBackTracker::ChannelToTrackSDPs(std::vector<sim::TrackSDP>& trackSDPs,
661  int channel,
662  const double opHit_start_time,
663  const double opHit_end_time)
664  {
665  shouldThisFail();
666  trackSDPs.clear();
667 
668  double totalE = 0.;
669 
670  try {
673 
674  // loop over the photons in the channel and grab those that are in time
675  // with the identified opHit start and stop times
676  //const detinfo::DetectorClocks* ts = lar::providerFrom<detinfo::DetectorClocksService>();
677  //int start_tdc = ts->OpticalG4Time2TDC( opHit_start_time );
678  //int end_tdc = ts->OpticalG4Time2TDC( opHit_end_time );
679  // if(start_tdc<0) start_tdc = 0;
680  // if(end_tdc<0) end_tdc = 0;
681  std::vector<sim::SDP> simSDPs =
682  schannel->TrackIDsAndEnergies(opHit_start_time, opHit_end_time);
683 
684  // first get the total energy represented by all track ids for
685  // this channel and range of tdc values
686  for (size_t e = 0; e < simSDPs.size(); ++e)
687  totalE += simSDPs[e].energy;
688 
689  // protect against a divide by zero below
690  if (totalE < 1.e-5) totalE = 1.;
691 
692  // loop over the entries in the map and fill the input vectors
693 
694  for (size_t e = 0; e < simSDPs.size(); ++e) {
695 
696  if (simSDPs[e].trackID == sim::NoParticleId) continue;
697 
698  sim::TrackSDP info;
699  info.trackID = simSDPs[e].trackID;
700  info.energyFrac = simSDPs[e].energy / totalE;
701  info.energy = simSDPs[e].energy;
702 
703  trackSDPs.push_back(info);
704  }
705  } // end try
706  catch (cet::exception e) {
707  mf::LogWarning("PhotonBackTracker") << "caught exception \n" << e;
708  }
709 
710  return;
711  }
712 
713  //----------------------------------------------------------------------
714  void PhotonBackTracker::OpHitToSDPs(recob::OpHit const& opHit, std::vector<sim::SDP>& sdps) const
715  {
716  shouldThisFail();
717  // Get services.
718  //const detinfo::DetectorClocks* ts = lar::providerFrom<detinfo::DetectorClocksService>();
719 
720  double fPeakTime = opHit.PeakTime();
721  double fWidth = opHit.Width();
723  ((fPeakTime - fWidth) * 1000.0) - fDelay;
724  sim::OpDetBacktrackerRecord::timePDclock_t end_time = ((fPeakTime + fWidth) * 1000.0) - fDelay;
725 
727  ->TrackIDsAndEnergies(start_time, end_time);
728  }
729 
730  //----------------------------------------------------------------------
731  std::vector<double> PhotonBackTracker::SimSDPsToXYZ(std::vector<sim::SDP> const& sdps)
732  {
733  shouldThisFail();
734  std::vector<double> xyz(3, -999.);
735 
736  double x = 0.;
737  double y = 0.;
738  double z = 0.;
739  double w = 0.;
740 
741  // loop over photons.
742 
743  for (auto const& sdp : sdps) {
744 
745  double weight = sdp.numPhotons;
746 
747  w += weight;
748  x += weight * sdp.x;
749  y += weight * sdp.y;
750  z += weight * sdp.z;
751 
752  } // end loop over sim::SDPs
753 
754  //If the sum of the weights is still zero, then fail to return a value.
755  //A hit with no contributing photons does't make sense.
756  if (w < 1.e-5)
757  throw cet::exception("PhotonBackTracker")
758  << "No sim::SDPs providing non-zero number of photons"
759  << " can't determine originating location from truth\n";
760 
761  xyz[0] = x / w;
762  xyz[1] = y / w;
763  xyz[2] = z / w;
764 
765  return xyz;
766  }
767 
768  //----------------------------------------------------------------------
769  std::vector<double> PhotonBackTracker::OpHitToXYZ(art::Ptr<recob::OpHit> const& opHit)
770  {
771  shouldThisFail();
772  std::vector<sim::SDP> sdps;
773  OpHitToSDPs(opHit, sdps);
774  return SimSDPsToXYZ(sdps);
775  }
776 
777 } // namespace
778 
779 namespace cheat {
781 }
Float_t x
Definition: compare.C:6
const simb::MCParticle * TrackIDToParticle(int const &id) const
std::vector< const simb::MCParticle * > MCTruthToParticles(art::Ptr< simb::MCTruth > const &mct) const
std::map< int, int > fTrackIDToMCTruthIndex
map of track ids to MCTruthList entry
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
list_type::value_type value_type
Definition: ParticleList.h:130
Float_t y
Definition: compare.C:6
std::vector< sim::SDP > TrackIDToSimSDP(int const &id) const
list_type::const_iterator const_iterator
Definition: ParticleList.h:132
Double_t z
Definition: plot.C:276
std::vector< double > SimSDPsToXYZ(std::vector< sim::SDP > const &sdps)
constexpr auto abs(T v)
Returns the absolute value of the argument.
void Add(simb::MCParticle *value)
Definition: ParticleList.h:315
double PeakTime() const
Definition: OpHit.h:94
bool isRealData() const
Definition: Event.cc:53
double OpHitChargeCollectionPurity(std::set< int > trackIDs, std::vector< art::Ptr< recob::OpHit >> const &hits)
int EveId(const int trackID) const
Particle class.
const art::Ptr< simb::MCTruth > & ParticleToMCTruth(const simb::MCParticle *p) const
std::string fG4ModuleLabel
label for geant4 module
std::vector< double > OpHitToXYZ(art::Ptr< recob::OpHit > const &hit)
int TrackId() const
Definition: MCParticle.h:211
unsigned int OpDetFromOpChannel(int opChannel) const
Convert unique channel to detector number.
iterator find(const key_type &key)
Definition: ParticleList.h:318
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 detector geometry.
TString part[npart]
Definition: Style.C:32
void OpHitToSDPs(recob::OpHit const &hit, std::vector< sim::SDP > &sdps) const
double Width() const
Definition: OpHit.h:110
void reconfigure(fhicl::ParameterSet const &pset)
int trackID
Geant4 supplied trackID.
std::vector< sim::TrackSDP > OpHitToEveSDPs(art::Ptr< recob::OpHit > const &hit)
static const int NoParticleId
Definition: sim.h:21
T get(std::string const &key) const
Definition: ParameterSet.h:314
void ChannelToTrackSDPs(std::vector< sim::TrackSDP > &trackSDPs, int channel, const double hit_start_time, const double hit_end_time)
float energyFrac
fraction of OpHit energy from the particle with this trackID
double timePDclock_t
Type for iTimePDclock tick used in the interface.
double energy
Definition: plottest35.C:25
iterator begin()
Definition: ParticleList.h:305
back track the reconstruction to the simulation
const simb::MCParticle * TrackIDToMotherParticle(int const &id) const
void Rebuild(const art::Event &evt)
GlobalSignal< detail::SignalResponseType::FIFO, void(Event const &, ScheduleContext)> sPreProcessEvent
Ionization photons from a Geant4 track.
#define DEFINE_ART_SERVICE(svc)
double weight
Definition: plottest35.C:25
std::vector< sim::TrackSDP > OpHitToTrackSDPs(art::Ptr< recob::OpHit > const &hit)
std::vector< sim::TrackSDP > OpHitToEveID(art::Ptr< recob::OpHit > const &hit)
PhotonBackTracker(fhicl::ParameterSet const &pset, art::ActivityRegistry &reg)
code to link reconstructed objects back to the MC truth information
Definition: BackTracker.cc:22
const art::Ptr< sim::OpDetBacktrackerRecord > FindOpDetBacktrackerRecord(int channel) const
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
Utility object to perform functions of association.
geo::GeometryCore const * geom
Example routine for calculating the "ultimate e-m mother" of a particle in a simulated event...
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
Float_t sc
Definition: plot.C:23
double OpHitCollectionEfficiency(std::set< int > trackIDs, std::vector< art::Ptr< recob::OpHit >> const &hits, std::vector< art::Ptr< recob::OpHit >> const &allhits)
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
#define MF_LOG_DEBUG(id)
double OpHitCollectionPurity(std::set< int > trackIDs, std::vector< art::Ptr< recob::OpHit >> const &hits)
double fMinOpHitEnergyFraction
minimum fraction of energy a track id has to
double Area() const
Definition: OpHit.h:114
std::shared_ptr< art::Exception const > whyFailed() const
Definition: Handle.h:231
std::vector< sim::SDP > TrackIDsAndEnergies(timePDclock_t startTimePDclock, timePDclock_t endTimePDclock) const
Return all the recorded energy deposition within a time interval.
TCEvent evt
Definition: DataStructs.cxx:8
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:306
float energy
energy from the particle with this trackID [MeV]
std::vector< art::Ptr< sim::OpDetBacktrackerRecord > > cOpDetBacktrackerRecords
all the OpDetBacktrackerRecords for the event
Float_t e
Definition: plot.C:35
std::vector< art::Ptr< simb::MCTruth > > fMCTruthList
all the MCTruths for the event
static void AdoptEveIdCalculator(EveIdCalculator *)
double OpHitChargeCollectionEfficiency(std::set< int > trackIDs, std::vector< art::Ptr< recob::OpHit >> const &hits, std::vector< art::Ptr< recob::OpHit >> const &allhits)
Float_t w
Definition: plot.C:20
int OpChannel() const
Definition: OpHit.h:86
Tools and modules for checking out the basics of the Monte Carlo.
const std::vector< std::vector< art::Ptr< recob::OpHit > > > TrackIDsToOpHits(std::vector< art::Ptr< recob::OpHit >> const &allhits, std::vector< int > const &tkIDs)
sim::ParticleList fParticleList
ParticleList to map track ID to sim::Particle.
art framework interface to geometry description
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
bool failedToGet() const
Definition: Handle.h:210
const art::Ptr< simb::MCTruth > & TrackIDToMCTruth(int const &id) const