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