All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SimPhotonCounter_module.cc
Go to the documentation of this file.
1 // \file SimPhotonCounter.h
2 // \author Ben Jones, MIT 2010
3 //
4 // Module to determine how many phots have been detected at each OpDet
5 //
6 // This analyzer takes the SimPhotonsCollection generated by LArG4's sensitive detectors
7 // and fills up to four trees in the histograms file. The four trees are:
8 //
9 // OpDetEvents - count how many phots hit the OpDet face / were detected across all OpDet's per event
10 // OpDets - count how many phots hit the OpDet face / were detected in each OpDet individually for each event
11 // AllPhotons - wavelength information for each phot hitting the OpDet face
12 // DetectedPhotons - wavelength information for each phot detected
13 //
14 // The user may supply a quantum efficiency and sensitive wavelength range for the OpDet's.
15 // with a QE < 1 and a finite wavelength range, a "detected" phot is one which is
16 // in the relevant wavelength range and passes the random sampling condition imposed by
17 // the quantum efficiency of the OpDet
18 //
19 // PARAMETERS REQUIRED:
20 // int32 Verbosity - whether to write to screen a well as to file. levels 0 to 3 specify different levels of detail to display
21 // string InputModule - the module which produced the SimPhotonsCollection
22 // bool MakeAllPhotonsTree - whether to build and store each tree (performance can be enhanced by switching off those not required)
23 // bool MakeDetectedPhotonsTree
24 // bool MakeOpDetsTree
25 // bool MakeOpDetEventsTree
26 // double QantumEfficiency - Quantum efficiency of OpDet
27 // double WavelengthCutLow - Sensitive wavelength range of OpDet
28 // double WavelengthCutHigh
29 
30 // FMWK includes
31 #include "art/Framework/Core/EDAnalyzer.h"
32 #include "art/Framework/Core/ModuleMacros.h"
33 #include "art/Framework/Principal/Event.h"
34 #include "fhiclcpp/ParameterSet.h"
35 #include "art/Framework/Principal/Handle.h"
36 #include "art/Framework/Services/Registry/ServiceHandle.h"
37 #include "art_root_io/TFileService.h"
38 #include "messagefacility/MessageLogger/MessageLogger.h"
39 
40 // LArSoft includes
52 
53 #include "nug4/ParticleNavigation/ParticleList.h"
54 #include "nusimdata/SimulationBase/MCParticle.h"
55 
56 // ROOT includes
57 #include "RtypesCore.h"
58 #include "TH1D.h"
59 #include "TTree.h"
60 #include "TLorentzVector.h"
61 #include "TVector3.h"
62 
63 // C++ language includes
64 #include <iostream>
65 #include <cstring>
66 #include <cassert>
67 
68 namespace opdet {
69 
70  class SimPhotonCounter : public art::EDAnalyzer{
71  public:
72 
73  SimPhotonCounter(const fhicl::ParameterSet&);
74 
75  void analyze(art::Event const&);
76 
77  void beginJob();
78  void endJob();
79 
80  private:
81 
82  /// Threshold used to resolve between visible and ultraviolet light.
83  static constexpr double kVisibleThreshold = 200.0; // nm
84 
85  /// Value used when a typical visible light wavelength is needed.
86  static constexpr double kVisibleWavelength = 450.0; // nm
87 
88  /// Value used when a typical ultraviolet light wavelength is needed.
89  static constexpr double kVUVWavelength = 128.0; // nm
90 
91  // Trees to output
92 
95  TTree * fTheOpDetTree;
96  TTree * fTheEventTree;
97 
98 
99  // Parameters to read in
100 
101  std::vector<std::string> fInputModule; // Input tag for OpDet collection
102 
103  int fVerbosity; // Level of output to write to std::out
104 
107  bool fMakeOpDetsTree; // Switches to turn on or off each output
109 
110  // float fQE; // Quantum efficiency of tube
111 
112  // float fWavelengthCutLow; // Sensitive wavelength range
113  // float fWavelengthCutHigh; //
114 
117 
118 
119  // Data to store in trees
120 
121  Float_t fWavelength;
122  Float_t fTime;
123  // Int_t fCount;
127  Float_t fT0_vis;
128 
131  // Int_t fCountEventDetectedwithRefl;
132 
133  Int_t fEventID;
134  Int_t fOpChannel;
135 
136  //for the analysis tree of the light (gamez)
138  std::vector<std::vector<std::vector<double> > > fSignals_vuv;
139  std::vector<std::vector<std::vector<double> > > fSignals_vis;
140 
141  TTree * fLightAnalysisTree = nullptr;
143  double fEnergy, fdEdx;
144  std::vector<double> fPosition0;
145  std::vector<std::vector<double> > fstepPositions;
146  std::vector<double> fstepTimes;
147  std::vector<std::vector<double> > fSignalsvuv;
148  std::vector<std::vector<double> > fSignalsvis;
149  std::string fProcess;
150 
153 
154  bool const fUseLitePhotons;
155 
156  void storeVisibility(
157  int channel, int nDirectPhotons, int nReflectedPhotons,
158  double reflectedT0 = 0.0
159  ) const;
160 
161 
162  /// Returns if we label as "visibile" a photon with specified wavelength [nm].
163  bool isVisible(double wavelength) const
164  { return fWavelength < kVisibleThreshold; }
165 
166 
167  };
168 }
169 
170 namespace opdet {
171 
172 
173  SimPhotonCounter::SimPhotonCounter(fhicl::ParameterSet const& pset)
174  : EDAnalyzer(pset)
175  , fPVS(art::ServiceHandle<phot::PhotonVisibilityService const>().get())
176  , fUseLitePhotons(art::ServiceHandle<sim::LArG4Parameters const>()->UseLitePhotons())
177  {
178  fVerbosity= pset.get<int>("Verbosity");
179  try
180  {
181  fInputModule = pset.get<std::vector<std::string>>("InputModule",{"largeant"});
182  }
183  catch(...)
184  {
185  fInputModule.push_back(pset.get<std::string>("InputModule","largeant"));
186  }
187  fMakeAllPhotonsTree= pset.get<bool>("MakeAllPhotonsTree");
188  fMakeDetectedPhotonsTree= pset.get<bool>("MakeDetectedPhotonsTree");
189  fMakeOpDetsTree= pset.get<bool>("MakeOpDetsTree");
190  fMakeOpDetEventsTree= pset.get<bool>("MakeOpDetEventsTree");
191  fMakeLightAnalysisTree= pset.get<bool>("MakeLightAnalysisTree", false);
192  //fQE= pset.get<double>("QuantumEfficiency");
193  //fWavelengthCutLow= pset.get<double>("WavelengthCutLow");
194  //fWavelengthCutHigh= pset.get<double>("WavelengthCutHigh");
195 
196 
198  throw art::Exception(art::errors::Configuration)
199  << "Building a library with reflected light time is not supported when using SimPhotonsLite.\n";
200  }
201 
202  }
203 
204 
206  {
207  // Get file service to store trees
208  art::ServiceHandle<art::TFileService const> tfs;
209  art::ServiceHandle<geo::Geometry const> geo;
210 
211  std::cout<<"Optical Channels positions: "<<geo->Cryostat(0).NOpDet()<<std::endl;
212  for(int ch=0; ch!=int(geo->Cryostat(0).NOpDet()); ch++) {
213  double OpDetCenter[3];
214  geo->OpDetGeoFromOpDet(ch).GetCenter(OpDetCenter);
215  std::cout<<ch<<" "<<OpDetCenter[0]<<" "<<OpDetCenter[1]<<" "<<OpDetCenter[2]<<std::endl;
216  }
217 
218  double CryoBounds[6];
219  geo->CryostatBoundaries(CryoBounds);
220  std::cout<<"Cryo Boundaries"<<std::endl;
221  std::cout<<"Xmin: "<<CryoBounds[0]<<" Xmax: "<<CryoBounds[1]<<" Ymin: "<<CryoBounds[2]
222  <<" Ymax: "<<CryoBounds[3]<<" Zmin: "<<CryoBounds[4]<<" Zmax: "<<CryoBounds[5]<<std::endl;
223 
224  try {
225  pi_serv = &*(art::ServiceHandle<cheat::ParticleInventoryService const>());
226  }
227  catch (art::Exception const& e) {
228  if (e.categoryCode() != art::errors::ServiceNotFound) throw;
229  mf::LogError("SimPhotonCounter")
230  << "ParticleInventoryService service is not configured!"
231  " Please add it in the job configuration."
232  " In the meanwhile, some checks to particles will be skipped."
233  ;
234  }
235 
236  // Create and assign branch addresses to required tree
238  {
239  fThePhotonTreeAll = tfs->make<TTree>("AllPhotons","AllPhotons");
240  fThePhotonTreeAll->Branch("EventID", &fEventID, "EventID/I");
241  fThePhotonTreeAll->Branch("Wavelength", &fWavelength, "Wavelength/F");
242  fThePhotonTreeAll->Branch("OpChannel", &fOpChannel, "OpChannel/I");
243  fThePhotonTreeAll->Branch("Time", &fTime, "Time/F");
244  }
245 
247  {
248  fThePhotonTreeDetected = tfs->make<TTree>("DetectedPhotons","DetectedPhotons");
249  fThePhotonTreeDetected->Branch("EventID", &fEventID, "EventID/I");
250  fThePhotonTreeDetected->Branch("Wavelength", &fWavelength, "Wavelength/F");
251  fThePhotonTreeDetected->Branch("OpChannel", &fOpChannel, "OpChannel/I");
252  fThePhotonTreeDetected->Branch("Time", &fTime, "Time/F");
253  }
254 
255  if(fMakeOpDetsTree)
256  {
257  fTheOpDetTree = tfs->make<TTree>("OpDets","OpDets");
258  fTheOpDetTree->Branch("EventID", &fEventID, "EventID/I");
259  fTheOpDetTree->Branch("OpChannel", &fOpChannel, "OpChannel/I");
260  fTheOpDetTree->Branch("CountAll", &fCountOpDetAll, "CountAll/I");
261  fTheOpDetTree->Branch("CountDetected", &fCountOpDetDetected, "CountDetected/I");
262  if(fPVS->StoreReflected())
263  fTheOpDetTree->Branch("CountReflDetected", &fCountOpDetReflDetected, "CountReflDetected/I");
264  fTheOpDetTree->Branch("Time", &fTime, "Time/F");
265  }
266 
268  {
269  fTheEventTree = tfs->make<TTree>("OpDetEvents","OpDetEvents");
270  fTheEventTree->Branch("EventID", &fEventID, "EventID/I");
271  fTheEventTree->Branch("CountAll", &fCountEventAll, "CountAll/I");
272  fTheEventTree->Branch("CountDetected",&fCountEventDetected,"CountDetected/I");
273  if(fPVS->StoreReflected())
274  fTheOpDetTree->Branch("CountReflDetected", &fCountOpDetReflDetected, "CountReflDetected/I");
275 
276  }
277 
278  //generating the tree for the light analysis:
280  {
281  fLightAnalysisTree = tfs->make<TTree>("LightAnalysis","LightAnalysis");
282  fLightAnalysisTree->Branch("RunNumber",&fRun);
283  fLightAnalysisTree->Branch("EventID",&fEventID);
284  fLightAnalysisTree->Branch("TrackID",&fTrackID);
285  fLightAnalysisTree->Branch("PdgCode",&fpdg);
286  fLightAnalysisTree->Branch("MotherTrackID",&fmotherTrackID);
287  fLightAnalysisTree->Branch("Energy",&fEnergy);
288  fLightAnalysisTree->Branch("dEdx",&fdEdx);
289  fLightAnalysisTree->Branch("StepPositions",&fstepPositions);
290  fLightAnalysisTree->Branch("StepTimes",&fstepTimes);
291  fLightAnalysisTree->Branch("SignalsVUV",&fSignalsvuv);
292  fLightAnalysisTree->Branch("SignalsVisible",&fSignalsvis);
293  fLightAnalysisTree->Branch("Process",&fProcess);
294  }
295 
296  }
297 
298 
300  {
301  if(fPVS->IsBuildJob())
302  {
303  art::ServiceHandle<phot::PhotonVisibilityService>()->StoreLibrary();
304  }
305  }
306 
307  void SimPhotonCounter::analyze(art::Event const& evt)
308  {
309 
310  // Lookup event ID from event
311  art::EventNumber_t event = evt.id().event();
312  fEventID=Int_t(event);
313 
314  // Service for determining opdet responses
315  art::ServiceHandle<opdet::OpDetResponseInterface const> odresponse;
316 
317  // get the geometry to be able to figure out signal types and chan -> plane mappings
318  art::ServiceHandle<geo::Geometry const> geo;
319 
320  // GEANT4 info on the particles (only used if making light analysis tree)
321  std::vector<simb::MCParticle> const* mcpartVec = nullptr;
322 
323  //-------------------------initializing light tree vectors------------------------
324  std::vector<double> totalEnergy_track;
325  fstepPositions.clear();
326  fstepTimes.clear();
328  //mcpartVec = evt.getPointerByLabel<std::vector<simb::MCParticle>>("largeant");
329  mcpartVec = evt.getHandle<std::vector<simb::MCParticle>>("largeant").product();
330 
331  size_t maxNtracks = 1000U; // mcpartVec->size(); --- { to be fixed soon! ]
332  fSignals_vuv.clear();
333  fSignals_vuv.resize(maxNtracks);
334  fSignals_vis.clear();
335  fSignals_vis.resize(maxNtracks);
336  for(size_t itrack=0; itrack!=maxNtracks; itrack++) {
337  fSignals_vuv[itrack].resize(geo->NOpChannels());
338  fSignals_vis[itrack].resize(geo->NOpChannels());
339  }
340  totalEnergy_track.resize(maxNtracks, 0.);
341  //-------------------------stimation of dedx per trackID----------------------
342  //get the list of particles from this event
343  const sim::ParticleList* plist = pi_serv? &(pi_serv->ParticleList()): nullptr;
344 
345  // loop over all sim::SimChannels in the event and make sure there are no
346  // sim::IDEs with trackID values that are not in the sim::ParticleList
347  std::vector<const sim::SimChannel*> sccol;
348  //evt.getView(fG4ModuleLabel, sccol);
349  for(auto const& mod : fInputModule){
350  evt.getView(mod, sccol);
351  double totalCharge=0.0;
352  double totalEnergy=0.0;
353  //loop over the sim channels collection
354  for(size_t sc = 0; sc < sccol.size(); ++sc){
355  double numIDEs=0.0;
356  double scCharge=0.0;
357  double scEnergy=0.0;
358  const auto & tdcidemap = sccol[sc]->TDCIDEMap();
359  //loop over all of the tdc IDE map objects
360  for(auto mapitr = tdcidemap.begin(); mapitr != tdcidemap.end(); mapitr++){
361  const std::vector<sim::IDE> idevec = (*mapitr).second;
362  numIDEs += idevec.size();
363  //go over all of the IDEs in a given simchannel
364  for(size_t iv = 0; iv < idevec.size(); ++iv){
365  if (plist) {
366  if(plist->find( idevec[iv].trackID ) == plist->end()
367  && idevec[iv].trackID != sim::NoParticleId)
368  {
369  mf::LogWarning("LArG4Ana") << idevec[iv].trackID << " is not in particle list";
370  }
371  }
372  if(idevec[iv].trackID < 0) continue;
373  totalCharge +=idevec[iv].numElectrons;
374  scCharge += idevec[iv].numElectrons;
375  totalEnergy +=idevec[iv].energy;
376  scEnergy += idevec[iv].energy;
377 
378  totalEnergy_track[idevec[iv].trackID] += idevec[iv].energy/3.;
379  }
380  }
381  }
382  }
383  }//End of if(fMakeLightAnalysisTree)
384 
385 
386  if(!fUseLitePhotons)
387  {
388 
389  //Reset counters
390  fCountEventAll=0;
392 
393  //Get *ALL* SimPhotonsCollection from Event
394  //std::vector< art::Handle< std::vector< sim::SimPhotons > > > photon_handles;
395  //evt.getManyByType(photon_handles);
396  auto photon_handles = evt.getMany<std::vector<sim::SimPhotons>>();
397  if (photon_handles.size() == 0)
398  throw art::Exception(art::errors::ProductNotFound)<<"sim SimPhotons retrieved and you requested them.";
399 
400  for(auto const& mod : fInputModule){
401  // sim::SimPhotonsCollection TheHitCollection = sim::SimListUtils::GetSimPhotonsCollection(evt,mod);
402  //switching off to add reading in of labelled collections: Andrzej, 02/26/19
403 
404  for (auto const& ph_handle: photon_handles) {
405  // Do some checking before we proceed
406  if (!ph_handle.isValid()) continue;
407  if (ph_handle.provenance()->moduleLabel() != mod) continue; //not the most efficient way of doing this, but preserves the logic of the module. Andrzej
408 
409  bool Reflected = (ph_handle.provenance()->productInstanceName() == "Reflected");
410 
411  if((*ph_handle).size()>0)
412  {
414  //resetting the signalt to save in the analysis tree per event
415  const int maxNtracks = 1000;
416  for(size_t itrack=0; itrack!=maxNtracks; itrack++) {
417  for(size_t pmt_i=0; pmt_i!=geo->NOpChannels(); pmt_i++) {
418  fSignals_vuv[itrack][pmt_i].clear();
419  fSignals_vis[itrack][pmt_i].clear();
420  }
421  }
422  }
423  }
424 
425 
426  // if(fVerbosity > 0) std::cout<<"Found OpDet hit collection of size "<< TheHitCollection.size()<<std::endl;
427  if(fVerbosity > 0) std::cout<<"Found OpDet hit collection of size "<< (*ph_handle).size()<<std::endl;
428 
429  if((*ph_handle).size()>0)
430  {
431  // for(sim::SimPhotonsCollection::const_iterator itOpDet=TheHitCollection.begin(); itOpDet!=TheHitCollection.end(); itOpDet++)
432  for(auto const& itOpDet: (*ph_handle) )
433  {
434  //Reset Counters
435  fCountOpDetAll=0;
438  //Reset t0 for visible light
439  fT0_vis = 999.;
440 
441  //Get data from HitCollection entry
442  fOpChannel=itOpDet.OpChannel();
443  const sim::SimPhotons& TheHit=itOpDet;
444 
445  //std::cout<<"OpDet " << fOpChannel << " has size " << TheHit.size()<<std::endl;
446 
447  // Loop through OpDet phots.
448  // Note we make the screen output decision outside the loop
449  // in order to avoid evaluating large numbers of unnecessary
450  // if conditions.
451 
452 
453  for(const sim::OnePhoton& Phot: TheHit)
454  {
455  // Calculate wavelength in nm
456  fWavelength= odresponse->wavelength(Phot.Energy);
457 
458  //Get arrival time from phot
459  fTime= Phot.Time;
460 
461  // special case for LibraryBuildJob: no working "Reflected" handle and all photons stored in single object - must sort using wavelength instead
462  if(fPVS->IsBuildJob() && !Reflected) {
463  // all photons contained in object with Reflected = false flag
464  // Increment per OpDet counters and fill per phot trees
465  fCountOpDetAll++;
468  fThePhotonTreeAll->Fill();
469  }
470  }
471 
472  if(odresponse->detected(fOpChannel, Phot))
473  {
475  //only store direct direct light
476  if(!isVisible(fWavelength))
478  // reflected and shifted light is in visible range
479  else if(fPVS->StoreReflected()) {
481  // find the first visible arrival time
482  if(fPVS->StoreReflT0() && fTime < fT0_vis)
483  fT0_vis = fTime;
484  }
485  if(fVerbosity > 3)
486  std::cout<<"OpDetResponseInterface PerPhoton : Event "<<fEventID<<" OpChannel " <<fOpChannel << " Wavelength " << fWavelength << " Detected 1 "<<std::endl;
487  }
488  else {
489  if(fVerbosity > 3)
490  std::cout<<"OpDetResponseInterface PerPhoton : Event "<<fEventID<<" OpChannel " <<fOpChannel << " Wavelength " << fWavelength << " Detected 0 "<<std::endl;
491  }
492 
493  } // if build library and not reflected
494 
495  else {
496  // store in appropriate trees using "Reflected" handle and fPVS->StoreReflected() flag
497  // Increment per OpDet counters and fill per phot trees
498  fCountOpDetAll++;
500  if (!Reflected || (fPVS->StoreReflected() && Reflected)) {
501  fThePhotonTreeAll->Fill();
502  }
503  }
504 
505  if(odresponse->detected(fOpChannel, Phot))
506  {
508  //only store direct direct light
509  if(!Reflected)
511  // reflected and shifted light is in visible range
512  else if(fPVS->StoreReflected() && Reflected ) {
514  // find the first visible arrival time
515  if(fPVS->StoreReflT0() && fTime < fT0_vis)
516  fT0_vis = fTime;
517  }
518  if(fVerbosity > 3)
519  std::cout<<"OpDetResponseInterface PerPhoton : Event "<<fEventID<<" OpChannel " <<fOpChannel << " Wavelength " << fWavelength << " Detected 1 "<<std::endl;
520  }
521  else {
522  if(fVerbosity > 3)
523  std::cout<<"OpDetResponseInterface PerPhoton : Event "<<fEventID<<" OpChannel " <<fOpChannel << " Wavelength " << fWavelength << " Detected 0 "<<std::endl;
524  }
525  }
526  } // for each photon in collection
527 
528 
529 
530  // If this is a library building job, fill relevant entry
531  if(fPVS->IsBuildJob() && !Reflected) // for library build job, both componenents stored in first object with Reflected = false
532  {
534  }
535 
536  // Incremenent per event and fill Per OpDet trees
537  if(fMakeOpDetsTree) fTheOpDetTree->Fill();
540 
541  // Give per OpDet output
542  if(fVerbosity >2) std::cout<<"OpDetResponseInterface PerOpDet : Event "<<fEventID<<" OpDet " << fOpChannel << " All " << fCountOpDetAll << " Det " <<fCountOpDetDetected<<std::endl;
543  }
544 
545  // Fill per event tree
547 
548  // Give per event output
549  if(fVerbosity >1) std::cout<<"OpDetResponseInterface PerEvent : Event "<<fEventID<<" All " << fCountOpDetAll << " Det " <<fCountOpDetDetected<<std::endl;
550 
551  }
552  else
553  {
554  // if empty OpDet hit collection,
555  // add an empty record to the per event tree
557  }
559  assert(mcpartVec);
560  assert(fLightAnalysisTree);
561 
562  std::cout<<"Filling the analysis tree"<<std::endl;
563  //---------------Filling the analysis tree-----------:
564  fRun = evt.run();
565  std::vector<double> this_xyz;
566 
567  //loop over the particles
568  for(simb::MCParticle const& pPart: *mcpartVec){
569 
570  if(pPart.Process() == "primary")
571  fEnergy = pPart.E();
572 
573  //resetting the vectors
574  fstepPositions.clear();
575  fstepTimes.clear();
576  fSignalsvuv.clear();
577  fSignalsvis.clear();
578  fdEdx = -1.;
579  //filling the tree fields
580  fTrackID = pPart.TrackId();
581  fpdg = pPart.PdgCode();
582  fmotherTrackID = pPart.Mother();
583  fdEdx = totalEnergy_track[fTrackID];
586  fProcess = pPart.Process();
587  //filling the center positions of each step
588  for(size_t i_s=1; i_s < pPart.NumberTrajectoryPoints(); i_s++){
589  this_xyz.clear();
590  this_xyz.resize(3);
591  this_xyz[0] = pPart.Position(i_s).X();
592  this_xyz[1] = pPart.Position(i_s).Y();
593  this_xyz[2] = pPart.Position(i_s).Z();
594  fstepPositions.push_back(this_xyz);
595  fstepTimes.push_back(pPart.Position(i_s).T());
596  }
597  //filling the tree per track
598  fLightAnalysisTree->Fill();
599  }
600  } // if fMakeLightAnalysisTree
601  }
602  }
603  }
604  if (fUseLitePhotons)
605  {
606 
607  //Get *ALL* SimPhotonsCollection from Event
608  //std::vector< art::Handle< std::vector< sim::SimPhotonsLite > > > photon_handles;
609  //evt.getManyByType(photon_handles);
610  auto photon_handles = evt.getMany<std::vector<sim::SimPhotonsLite>>();
611  if (photon_handles.size() == 0)
612  throw art::Exception(art::errors::ProductNotFound)<<"sim SimPhotons retrieved and you requested them.";
613 
614  //Get SimPhotonsLite from Event
615  for(auto const& mod : fInputModule){
616  //art::Handle< std::vector<sim::SimPhotonsLite> > photonHandle;
617  //evt.getByLabel(mod, photonHandle);
618 
619  // Loop over direct/reflected photons
620  for (auto const& ph_handle: photon_handles) {
621  // Do some checking before we proceed
622  if (!ph_handle.isValid()) continue;
623  if (ph_handle.provenance()->moduleLabel() != mod) continue; //not the most efficient way of doing this, but preserves the logic of the module. Andrzej
624 
625  bool Reflected = (ph_handle.provenance()->productInstanceName() == "Reflected");
626 
627  //Reset counters
628  fCountEventAll=0;
630 
631  if(fVerbosity > 0) std::cout<<"Found OpDet hit collection of size "<< (*ph_handle).size()<<std::endl;
632 
633 
634  if((*ph_handle).size()>0)
635  {
636 
637  for ( auto const& photon : (*ph_handle) )
638  {
639  //Get data from HitCollection entry
640  fOpChannel=photon.OpChannel;
641  std::map<int, int> PhotonsMap = photon.DetectedPhotons;
642 
643  //Reset Counters
644  fCountOpDetAll=0;
647 
648  for(auto it = PhotonsMap.begin(); it!= PhotonsMap.end(); it++)
649  {
650  // Calculate wavelength in nm
651  if (Reflected) {
653  }
654  else {
655  fWavelength= kVUVWavelength; // original
656  }
657 
658  //Get arrival time from phot
659  fTime= it->first;
660  //std::cout<<"Arrival time: " << fTime<<std::endl;
661 
662  for(int i = 0; i < it->second ; i++)
663  {
664  // Increment per OpDet counters and fill per phot trees
665  fCountOpDetAll++;
667 
668  if(odresponse->detectedLite(fOpChannel))
669  {
671  // direct light
672  if (!Reflected){
674  }
675  else if (Reflected) {
677  }
678  if(fVerbosity > 3)
679  std::cout<<"OpDetResponseInterface PerPhoton : Event "<<fEventID<<" OpChannel " <<fOpChannel << " Wavelength " << fWavelength << " Detected 1 "<<std::endl;
680  }
681  else
682  if(fVerbosity > 3)
683  {
684  std::cout<<"OpDetResponseInterface PerPhoton : Event "<<fEventID<<" OpChannel " <<fOpChannel << " Wavelength " << fWavelength << " Detected 0 "<<std::endl;
685  }
686  }
687  }
688 
689 
690 
691  // Incremenent per event and fill Per OpDet trees
692  if(fMakeOpDetsTree) fTheOpDetTree->Fill();
695 
696  if (fPVS->IsBuildJob())
698 
699 
700  // Give per OpDet output
701  if(fVerbosity >2) std::cout<<"OpDetResponseInterface PerOpDet : Event "<<fEventID<<" OpDet " << fOpChannel << " All " << fCountOpDetAll << " Det " <<fCountOpDetDetected<<std::endl;
702  }
703  // Fill per event tree
705 
706  // Give per event output
707  if(fVerbosity >1) std::cout<<"OpDetResponseInterface PerEvent : Event "<<fEventID<<" All " << fCountOpDetAll << " Det " <<fCountOpDetDetected<<std::endl;
708 
709  }
710  else
711  {
712  // if empty OpDet hit collection,
713  // add an empty record to the per event tree
715  }
716  }
717  }
718  }
719  } // SimPhotonCounter::analyze()
720 
721 
722  // ---------------------------------------------------------------------------
724  int channel, int nDirectPhotons, int nReflectedPhotons,
725  double reflectedT0 /* = 0.0 */
726  ) const
727  {
729  = *(art::ServiceHandle<phot::PhotonVisibilityService>());
730 
731  // ask PhotonVisibilityService which voxel was being served,
732  // and how many photons where there generated (yikes!!);
733  // this value was put there by LightSource (yikes!!)
734  int VoxID;
735  double NProd;
736  fPVS->RetrieveLightProd(VoxID, NProd);
737 
738  pvs.SetLibraryEntry(VoxID, channel, double(nDirectPhotons)/NProd);
739 
740  //store reflected light
741  if(fPVS->StoreReflected()) {
742  pvs.SetLibraryEntry(VoxID, channel, double(nReflectedPhotons)/NProd, true);
743 
744  //store reflected first arrival time
745  if (fPVS->StoreReflT0())
746  pvs.SetLibraryReflT0Entry(VoxID, channel, reflectedT0);
747 
748  } // if reflected
749 
750  } // SimPhotonCounter::storeVisibility()
751 
752  // ---------------------------------------------------------------------------
753 
754 }
755 namespace opdet{
756 
757  DEFINE_ART_MODULE(SimPhotonCounter)
758 
759 }//end namespace opdet
Store parameters for running LArG4.
std::vector< std::vector< double > > fstepPositions
process_name can override from command line with o or output photon
Definition: runPID.fcl:28
void RetrieveLightProd(int &VoxID, double &N) const
Encapsulate the construction of a single cyostat.
void storeVisibility(int channel, int nDirectPhotons, int nReflectedPhotons, double reflectedT0=0.0) const
std::vector< double > fPosition0
All information of a photon entering the sensitive optical detector volume.
Definition: SimPhotons.h:64
phot::PhotonVisibilityService const * fPVS
std::vector< std::vector< double > > fSignalsvuv
static constexpr double kVUVWavelength
Value used when a typical ultraviolet light wavelength is needed.
std::vector< double > fstepTimes
std::vector< std::string > fInputModule
Simulation objects for optical detectors.
bool isVisible(double wavelength) const
Returns if we label as &quot;visibile&quot; a photon with specified wavelength [nm].
void analyze(art::Event const &)
static const int NoParticleId
Definition: sim.h:21
static constexpr double kVisibleWavelength
Value used when a typical visible light wavelength is needed.
void SetLibraryReflT0Entry(int VoxID, int OpChannel, float value)
Class def header for mctrack data container.
const sim::ParticleList & ParticleList() const
Encapsulate the geometry of an optical detector.
Collection of photons which recorded on one channel.
Definition: SimPhotons.h:136
void SetLibraryEntry(int VoxID, OpDetID_t libOpChannel, float N, bool wantReflected=false)
std::vector< std::vector< std::vector< double > > > fSignals_vis
object containing MC truth information necessary for making RawDigits and doing back tracking ...
do i e
static constexpr double kVisibleThreshold
Threshold used to resolve between visible and ultraviolet light.
std::vector< std::vector< double > > fSignalsvis
art::ServiceHandle< art::TFileService > tfs
TCEvent evt
Definition: DataStructs.cxx:8
std::vector< std::vector< std::vector< double > > > fSignals_vuv
Tools and modules for checking out the basics of the Monte Carlo.
art framework interface to geometry description
BEGIN_PROLOG could also be cout
services LArG4Parameters UseLitePhotons
cheat::ParticleInventoryService const * pi_serv