LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
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
36 #include "art_root_io/TFileService.h"
37 #include "fhiclcpp/ParameterSet.h"
39 
40 // LArSoft includes
52 
55 
56 // ROOT includes
57 #include "RtypesCore.h"
58 #include "TH1D.h"
59 #include "TLorentzVector.h"
60 #include "TTree.h"
61 #include "TVector3.h"
62 
63 // C++ language includes
64 #include <cassert>
65 #include <cstring>
66 #include <iostream>
67 
68 namespace opdet {
69 
70  class SimPhotonCounter : public art::EDAnalyzer {
71  public:
73 
74  void analyze(art::Event const&);
75 
76  void beginJob();
77  void endJob();
78 
79  private:
81  static constexpr double kVisibleThreshold = 200.0; // nm
82 
84  static constexpr double kVisibleWavelength = 450.0; // nm
85 
87  static constexpr double kVUVWavelength = 128.0; // nm
88 
89  // Trees to output
90 
93  TTree* fTheOpDetTree;
94  TTree* fTheEventTree;
95 
96  // Parameters to read in
97 
98  std::vector<std::string> fInputModule; // Input tag for OpDet collection
99 
100  int fVerbosity; // Level of output to write to std::out
101 
104  bool fMakeOpDetsTree; // Switches to turn on or off each output
107 
108  // float fQE; // Quantum efficiency of tube
109 
110  // float fWavelengthCutLow; // Sensitive wavelength range
111  // float fWavelengthCutHigh; //
112 
115 
116  // Data to store in trees
117 
118  Float_t fWavelength;
119  Float_t fTime;
120  Float_t foriginX;
121  Float_t foriginY;
122  Float_t foriginZ;
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(int channel,
157  int nDirectPhotons,
158  int nReflectedPhotons,
159  double reflectedT0 = 0.0) const;
160 
162  bool isVisible(double wavelength) const { return fWavelength < kVisibleThreshold; }
163  };
164 }
165 
166 namespace opdet {
167 
169  : EDAnalyzer(pset)
172  {
173  fVerbosity = pset.get<int>("Verbosity");
174  try {
175  fInputModule = pset.get<std::vector<std::string>>("InputModule", {"largeant"});
176  }
177  catch (...) {
178  fInputModule.push_back(pset.get<std::string>("InputModule", "largeant"));
179  }
180  fMakeAllPhotonsTree = pset.get<bool>("MakeAllPhotonsTree");
181  fMakeDetectedPhotonsTree = pset.get<bool>("MakeDetectedPhotonsTree");
182  fSavePhotonOrigins = pset.get<bool>("SavePhotonOrigins", false);
183  fMakeOpDetsTree = pset.get<bool>("MakeOpDetsTree");
184  fMakeOpDetEventsTree = pset.get<bool>("MakeOpDetEventsTree");
185  fMakeLightAnalysisTree = pset.get<bool>("MakeLightAnalysisTree", false);
186  //fQE= pset.get<double>("QuantumEfficiency");
187  //fWavelengthCutLow= pset.get<double>("WavelengthCutLow");
188  //fWavelengthCutHigh= pset.get<double>("WavelengthCutHigh");
189 
192  << "Building a library with reflected light time is not supported when using "
193  "SimPhotonsLite.\n";
194  }
195  }
196 
198  {
199  // Get file service to store trees
202 
203  std::cout << "Optical Channels positions: " << geo->Cryostat().NOpDet() << std::endl;
204  for (int ch = 0; ch != int(geo->Cryostat().NOpDet()); ch++) {
205  auto const OpDetCenter = geo->OpDetGeoFromOpDet(ch).GetCenter();
206  std::cout << ch << " " << OpDetCenter.X() << " " << OpDetCenter.Y() << " "
207  << OpDetCenter.Z() << std::endl;
208  }
209 
210  auto const CryoBounds = geo->Cryostat().Boundaries();
211  std::cout << "Cryo Boundaries" << std::endl;
212  std::cout << "Xmin: " << CryoBounds.MinX() << " Xmax: " << CryoBounds.MaxX()
213  << " Ymin: " << CryoBounds.MinY() << " Ymax: " << CryoBounds.MaxY()
214  << " Zmin: " << CryoBounds.MinZ() << " Zmax: " << CryoBounds.MaxZ() << std::endl;
215 
216  try {
218  }
219  catch (art::Exception const& e) {
220  if (e.categoryCode() != art::errors::ServiceNotFound) throw;
221  mf::LogError("SimPhotonCounter")
222  << "ParticleInventoryService service is not configured!"
223  " Please add it in the job configuration."
224  " In the meanwhile, some checks to particles will be skipped.";
225  }
226 
227  // Create and assign branch addresses to required tree
228  if (fMakeAllPhotonsTree) {
229  fThePhotonTreeAll = tfs->make<TTree>("AllPhotons", "AllPhotons");
230  fThePhotonTreeAll->Branch("EventID", &fEventID, "EventID/I");
231  fThePhotonTreeAll->Branch("Wavelength", &fWavelength, "Wavelength/F");
232  fThePhotonTreeAll->Branch("OpChannel", &fOpChannel, "OpChannel/I");
233  fThePhotonTreeAll->Branch("Time", &fTime, "Time/F");
234  if (fSavePhotonOrigins) {
235  fThePhotonTreeAll->Branch("originX", &foriginX, "originX/F");
236  fThePhotonTreeAll->Branch("originY", &foriginY, "originY/F");
237  fThePhotonTreeAll->Branch("originZ", &foriginZ, "originZ/F");
238  }
239  }
240 
242  fThePhotonTreeDetected = tfs->make<TTree>("DetectedPhotons", "DetectedPhotons");
243  fThePhotonTreeDetected->Branch("EventID", &fEventID, "EventID/I");
244  fThePhotonTreeDetected->Branch("Wavelength", &fWavelength, "Wavelength/F");
245  fThePhotonTreeDetected->Branch("OpChannel", &fOpChannel, "OpChannel/I");
246  fThePhotonTreeDetected->Branch("Time", &fTime, "Time/F");
247  if (fSavePhotonOrigins) {
248  fThePhotonTreeDetected->Branch("originX", &foriginX, "originX/F");
249  fThePhotonTreeDetected->Branch("originY", &foriginY, "originY/F");
250  fThePhotonTreeDetected->Branch("originZ", &foriginZ, "originZ/F");
251  }
252  }
253 
254  if (fMakeOpDetsTree) {
255  fTheOpDetTree = tfs->make<TTree>("OpDets", "OpDets");
256  fTheOpDetTree->Branch("EventID", &fEventID, "EventID/I");
257  fTheOpDetTree->Branch("OpChannel", &fOpChannel, "OpChannel/I");
258  fTheOpDetTree->Branch("CountAll", &fCountOpDetAll, "CountAll/I");
259  fTheOpDetTree->Branch("CountDetected", &fCountOpDetDetected, "CountDetected/I");
260  if (fPVS->StoreReflected())
261  fTheOpDetTree->Branch("CountReflDetected", &fCountOpDetReflDetected, "CountReflDetected/I");
262  fTheOpDetTree->Branch("Time", &fTime, "Time/F");
263  }
264 
265  if (fMakeOpDetEventsTree) {
266  fTheEventTree = tfs->make<TTree>("OpDetEvents", "OpDetEvents");
267  fTheEventTree->Branch("EventID", &fEventID, "EventID/I");
268  fTheEventTree->Branch("CountAll", &fCountEventAll, "CountAll/I");
269  fTheEventTree->Branch("CountDetected", &fCountEventDetected, "CountDetected/I");
270  if (fPVS->StoreReflected())
271  fTheOpDetTree->Branch("CountReflDetected", &fCountOpDetReflDetected, "CountReflDetected/I");
272  }
273 
274  //generating the tree for the light analysis:
276  fLightAnalysisTree = tfs->make<TTree>("LightAnalysis", "LightAnalysis");
277  fLightAnalysisTree->Branch("RunNumber", &fRun);
278  fLightAnalysisTree->Branch("EventID", &fEventID);
279  fLightAnalysisTree->Branch("TrackID", &fTrackID);
280  fLightAnalysisTree->Branch("PdgCode", &fpdg);
281  fLightAnalysisTree->Branch("MotherTrackID", &fmotherTrackID);
282  fLightAnalysisTree->Branch("Energy", &fEnergy);
283  fLightAnalysisTree->Branch("dEdx", &fdEdx);
284  fLightAnalysisTree->Branch("StepPositions", &fstepPositions);
285  fLightAnalysisTree->Branch("StepTimes", &fstepTimes);
286  fLightAnalysisTree->Branch("SignalsVUV", &fSignalsvuv);
287  fLightAnalysisTree->Branch("SignalsVisible", &fSignalsvis);
288  fLightAnalysisTree->Branch("Process", &fProcess);
289  }
290  }
291 
293  {
295  }
296 
298  {
299 
300  // Lookup event ID from event
301  art::EventNumber_t event = evt.id().event();
302  fEventID = Int_t(event);
303 
304  // Service for determining opdet responses
306 
307  // get the geometry to be able to figure out signal types and chan -> plane mappings
309 
310  // GEANT4 info on the particles (only used if making light analysis tree)
311  std::vector<simb::MCParticle> const* mcpartVec = nullptr;
312 
313  //-------------------------initializing light tree vectors------------------------
314  std::vector<double> totalEnergy_track;
315  fstepPositions.clear();
316  fstepTimes.clear();
318  //mcpartVec = evt.getPointerByLabel<std::vector<simb::MCParticle>>("largeant");
319  mcpartVec = evt.getHandle<std::vector<simb::MCParticle>>("largeant").product();
320 
321  size_t maxNtracks = 1000U; // mcpartVec->size(); --- { to be fixed soon! ]
322  fSignals_vuv.clear();
323  fSignals_vuv.resize(maxNtracks);
324  fSignals_vis.clear();
325  fSignals_vis.resize(maxNtracks);
326  for (size_t itrack = 0; itrack != maxNtracks; itrack++) {
327  fSignals_vuv[itrack].resize(geo->NOpChannels());
328  fSignals_vis[itrack].resize(geo->NOpChannels());
329  }
330  totalEnergy_track.resize(maxNtracks, 0.);
331  //-------------------------stimation of dedx per trackID----------------------
332  //get the list of particles from this event
333  const sim::ParticleList* plist = pi_serv ? &(pi_serv->ParticleList()) : nullptr;
334 
335  // loop over all sim::SimChannels in the event and make sure there are no
336  // sim::IDEs with trackID values that are not in the sim::ParticleList
337  std::vector<const sim::SimChannel*> sccol;
338  //evt.getView(fG4ModuleLabel, sccol);
339  for (auto const& mod : fInputModule) {
340  evt.getView(mod, sccol);
341  //loop over the sim channels collection
342  for (size_t sc = 0; sc < sccol.size(); ++sc) {
343  const auto& tdcidemap = sccol[sc]->TDCIDEMap();
344  //loop over all of the tdc IDE map objects
345  for (auto mapitr = tdcidemap.begin(); mapitr != tdcidemap.end(); mapitr++) {
346  const std::vector<sim::IDE> idevec = (*mapitr).second;
347  //go over all of the IDEs in a given simchannel
348  for (size_t iv = 0; iv < idevec.size(); ++iv) {
349  if (plist) {
350  if (plist->find(idevec[iv].trackID) == plist->end() &&
351  idevec[iv].trackID != sim::NoParticleId) {
352  mf::LogWarning("LArG4Ana") << idevec[iv].trackID << " is not in particle list";
353  }
354  }
355  if (idevec[iv].trackID < 0) continue;
356 
357  totalEnergy_track[idevec[iv].trackID] += idevec[iv].energy / 3.;
358  }
359  }
360  }
361  }
362  } //End of if(fMakeLightAnalysisTree)
363 
364  if (!fUseLitePhotons) {
365 
366  //Reset counters
367  fCountEventAll = 0;
369 
370  //Get *ALL* SimPhotonsCollection from Event
371  //std::vector< art::Handle< std::vector< sim::SimPhotons > > > photon_handles;
372  //evt.getManyByType(photon_handles);
373  auto photon_handles = evt.getMany<std::vector<sim::SimPhotons>>();
374  if (photon_handles.size() == 0)
376  << "sim SimPhotons retrieved and you requested them.";
377 
378  for (auto const& mod : fInputModule) {
379  // sim::SimPhotonsCollection TheHitCollection = sim::SimListUtils::GetSimPhotonsCollection(evt,mod);
380  //switching off to add reading in of labelled collections: Andrzej, 02/26/19
381 
382  for (auto const& ph_handle : photon_handles) {
383  // Do some checking before we proceed
384  if (!ph_handle.isValid()) continue;
385  if (ph_handle.provenance()->moduleLabel() != mod)
386  continue; //not the most efficient way of doing this, but preserves the logic of the module. Andrzej
387 
388  bool Reflected = (ph_handle.provenance()->productInstanceName() == "Reflected");
389 
390  if ((*ph_handle).size() > 0) {
392  //resetting the signalt to save in the analysis tree per event
393  const int maxNtracks = 1000;
394  for (size_t itrack = 0; itrack != maxNtracks; itrack++) {
395  for (size_t pmt_i = 0; pmt_i != geo->NOpChannels(); pmt_i++) {
396  fSignals_vuv[itrack][pmt_i].clear();
397  fSignals_vis[itrack][pmt_i].clear();
398  }
399  }
400  }
401  }
402 
403  // if(fVerbosity > 0) std::cout<<"Found OpDet hit collection of size "<< TheHitCollection.size()<<std::endl;
404  if (fVerbosity > 0)
405  std::cout << "Found OpDet hit collection of size " << (*ph_handle).size() << std::endl;
406 
407  if ((*ph_handle).size() > 0) {
408  // for(sim::SimPhotonsCollection::const_iterator itOpDet=TheHitCollection.begin(); itOpDet!=TheHitCollection.end(); itOpDet++)
409  for (auto const& itOpDet : (*ph_handle)) {
410  //Reset Counters
411  fCountOpDetAll = 0;
414  //Reset t0 for visible light
415  fT0_vis = 999.;
416 
417  //Get data from HitCollection entry
418  fOpChannel = itOpDet.OpChannel();
419  const sim::SimPhotons& TheHit = itOpDet;
420 
421  //std::cout<<"OpDet " << fOpChannel << " has size " << TheHit.size()<<std::endl;
422 
423  // Loop through OpDet phots.
424  // Note we make the screen output decision outside the loop
425  // in order to avoid evaluating large numbers of unnecessary
426  // if conditions.
427 
428  for (const sim::OnePhoton& Phot : TheHit) {
429  // Calculate wavelength in nm
430  fWavelength = odresponse->wavelength(Phot.Energy);
431 
432  //Get arrival time from phot
433  fTime = Phot.Time;
434  foriginX = Phot.InitialPosition.X();
435  foriginY = Phot.InitialPosition.Y();
436  foriginZ = Phot.InitialPosition.Z();
437 
438  // special case for LibraryBuildJob: no working "Reflected" handle and all photons stored in single object - must sort using wavelength instead
439  if (fPVS->IsBuildJob() && !Reflected) {
440  // all photons contained in object with Reflected = false flag
441  // Increment per OpDet counters and fill per phot trees
442  fCountOpDetAll++;
443  if (fMakeAllPhotonsTree) {
445  fThePhotonTreeAll->Fill();
446  }
447  }
448 
449  if (odresponse->detected(fOpChannel, Phot)) {
451  //only store direct direct light
453  // reflected and shifted light is in visible range
454  else if (fPVS->StoreReflected()) {
456  // find the first visible arrival time
457  if (fPVS->StoreReflT0() && fTime < fT0_vis) fT0_vis = fTime;
458  }
459  if (fVerbosity > 3)
460  std::cout << "OpDetResponseInterface PerPhoton : Event " << fEventID
461  << " OpChannel " << fOpChannel << " Wavelength " << fWavelength
462  << " Detected 1 " << std::endl;
463  }
464  else {
465  if (fVerbosity > 3)
466  std::cout << "OpDetResponseInterface PerPhoton : Event " << fEventID
467  << " OpChannel " << fOpChannel << " Wavelength " << fWavelength
468  << " Detected 0 " << std::endl;
469  }
470 
471  } // if build library and not reflected
472 
473  else {
474  // store in appropriate trees using "Reflected" handle and fPVS->StoreReflected() flag
475  // Increment per OpDet counters and fill per phot trees
476  fCountOpDetAll++;
477  if (fMakeAllPhotonsTree) {
478  if (!Reflected || (fPVS->StoreReflected() && Reflected)) {
479  fThePhotonTreeAll->Fill();
480  }
481  }
482 
483  if (odresponse->detected(fOpChannel, Phot)) {
485  //only store direct direct light
486  if (!Reflected) fCountOpDetDetected++;
487  // reflected and shifted light is in visible range
488  else if (fPVS->StoreReflected() && Reflected) {
490  // find the first visible arrival time
491  if (fPVS->StoreReflT0() && fTime < fT0_vis) fT0_vis = fTime;
492  }
493  if (fVerbosity > 3)
494  std::cout << "OpDetResponseInterface PerPhoton : Event " << fEventID
495  << " OpChannel " << fOpChannel << " Wavelength " << fWavelength
496  << " Detected 1 " << std::endl;
497  }
498  else {
499  if (fVerbosity > 3)
500  std::cout << "OpDetResponseInterface PerPhoton : Event " << fEventID
501  << " OpChannel " << fOpChannel << " Wavelength " << fWavelength
502  << " Detected 0 " << std::endl;
503  }
504  }
505  } // for each photon in collection
506 
507  // If this is a library building job, fill relevant entry
508  if (
509  fPVS->IsBuildJob() &&
510  !Reflected) // for library build job, both componenents stored in first object with Reflected = false
511  {
513  }
514 
515  // Incremenent per event and fill Per OpDet trees
516  if (fMakeOpDetsTree) fTheOpDetTree->Fill();
519 
520  // Give per OpDet output
521  if (fVerbosity > 2)
522  std::cout << "OpDetResponseInterface PerOpDet : Event " << fEventID << " OpDet "
523  << fOpChannel << " All " << fCountOpDetAll << " Det "
524  << fCountOpDetDetected << std::endl;
525  }
526 
527  // Fill per event tree
528  if (fMakeOpDetEventsTree) fTheEventTree->Fill();
529 
530  // Give per event output
531  if (fVerbosity > 1)
532  std::cout << "OpDetResponseInterface PerEvent : Event " << fEventID << " All "
533  << fCountOpDetAll << " Det " << fCountOpDetDetected << std::endl;
534  }
535  else {
536  // if empty OpDet hit collection,
537  // add an empty record to the per event tree
538  if (fMakeOpDetEventsTree) fTheEventTree->Fill();
539  }
541  assert(mcpartVec);
542  assert(fLightAnalysisTree);
543 
544  std::cout << "Filling the analysis tree" << std::endl;
545  //---------------Filling the analysis tree-----------:
546  fRun = evt.run();
547  std::vector<double> this_xyz;
548 
549  //loop over the particles
550  for (simb::MCParticle const& pPart : *mcpartVec) {
551 
552  if (pPart.Process() == "primary") fEnergy = pPart.E();
553 
554  //resetting the vectors
555  fstepPositions.clear();
556  fstepTimes.clear();
557  fSignalsvuv.clear();
558  fSignalsvis.clear();
559  fdEdx = -1.;
560  //filling the tree fields
561  fTrackID = pPart.TrackId();
562  fpdg = pPart.PdgCode();
563  fmotherTrackID = pPart.Mother();
564  fdEdx = totalEnergy_track[fTrackID];
567  fProcess = pPart.Process();
568  //filling the center positions of each step
569  for (size_t i_s = 1; i_s < pPart.NumberTrajectoryPoints(); i_s++) {
570  this_xyz.clear();
571  this_xyz.resize(3);
572  this_xyz[0] = pPart.Position(i_s).X();
573  this_xyz[1] = pPart.Position(i_s).Y();
574  this_xyz[2] = pPart.Position(i_s).Z();
575  fstepPositions.push_back(this_xyz);
576  fstepTimes.push_back(pPart.Position(i_s).T());
577  }
578  //filling the tree per track
579  fLightAnalysisTree->Fill();
580  }
581  } // if fMakeLightAnalysisTree
582  }
583  }
584  }
585  if (fUseLitePhotons) {
586 
587  //Get *ALL* SimPhotonsCollection from Event
588  //std::vector< art::Handle< std::vector< sim::SimPhotonsLite > > > photon_handles;
589  //evt.getManyByType(photon_handles);
590  auto photon_handles = evt.getMany<std::vector<sim::SimPhotonsLite>>();
591  if (photon_handles.size() == 0)
593  << "sim SimPhotons retrieved and you requested them.";
594 
595  //Get SimPhotonsLite from Event
596  for (auto const& mod : fInputModule) {
597  //art::Handle< std::vector<sim::SimPhotonsLite> > photonHandle;
598  //evt.getByLabel(mod, photonHandle);
599 
600  // Loop over direct/reflected photons
601  for (auto const& ph_handle : photon_handles) {
602  // Do some checking before we proceed
603  if (!ph_handle.isValid()) continue;
604  if (ph_handle.provenance()->moduleLabel() != mod)
605  continue; //not the most efficient way of doing this, but preserves the logic of the module. Andrzej
606 
607  bool Reflected = (ph_handle.provenance()->productInstanceName() == "Reflected");
608 
609  //Reset counters
610  fCountEventAll = 0;
612 
613  if (fVerbosity > 0)
614  std::cout << "Found OpDet hit collection of size " << (*ph_handle).size() << std::endl;
615 
616  if ((*ph_handle).size() > 0) {
617 
618  for (auto const& photon : (*ph_handle)) {
619  //Get data from HitCollection entry
620  fOpChannel = photon.OpChannel;
621  std::map<int, int> PhotonsMap = photon.DetectedPhotons;
622 
623  //Reset Counters
624  fCountOpDetAll = 0;
627 
628  for (auto it = PhotonsMap.begin(); it != PhotonsMap.end(); it++) {
629  // Calculate wavelength in nm
630  if (Reflected) { fWavelength = kVisibleThreshold; }
631  else {
632  fWavelength = kVUVWavelength; // original
633  }
634 
635  //Get arrival time from phot
636  fTime = it->first;
637  //std::cout<<"Arrival time: " << fTime<<std::endl;
638 
639  for (int i = 0; i < it->second; i++) {
640  // Increment per OpDet counters and fill per phot trees
641  fCountOpDetAll++;
643 
644  if (odresponse->detectedLite(fOpChannel)) {
646  // direct light
647  if (!Reflected) { fCountOpDetDetected++; }
648  else if (Reflected) {
650  }
651  if (fVerbosity > 3)
652  std::cout << "OpDetResponseInterface PerPhoton : Event " << fEventID
653  << " OpChannel " << fOpChannel << " Wavelength " << fWavelength
654  << " Detected 1 " << std::endl;
655  }
656  else if (fVerbosity > 3) {
657  std::cout << "OpDetResponseInterface PerPhoton : Event " << fEventID
658  << " OpChannel " << fOpChannel << " Wavelength " << fWavelength
659  << " Detected 0 " << std::endl;
660  }
661  }
662  }
663 
664  // Incremenent per event and fill Per OpDet trees
665  if (fMakeOpDetsTree) fTheOpDetTree->Fill();
668 
669  if (fPVS->IsBuildJob())
671 
672  // Give per OpDet output
673  if (fVerbosity > 2)
674  std::cout << "OpDetResponseInterface PerOpDet : Event " << fEventID << " OpDet "
675  << fOpChannel << " All " << fCountOpDetAll << " Det "
676  << fCountOpDetDetected << std::endl;
677  }
678  // Fill per event tree
679  if (fMakeOpDetEventsTree) fTheEventTree->Fill();
680 
681  // Give per event output
682  if (fVerbosity > 1)
683  std::cout << "OpDetResponseInterface PerEvent : Event " << fEventID << " All "
684  << fCountOpDetAll << " Det " << fCountOpDetDetected << std::endl;
685  }
686  else {
687  // if empty OpDet hit collection,
688  // add an empty record to the per event tree
689  if (fMakeOpDetEventsTree) fTheEventTree->Fill();
690  }
691  }
692  }
693  }
694  } // SimPhotonCounter::analyze()
695 
696  // ---------------------------------------------------------------------------
698  int nDirectPhotons,
699  int nReflectedPhotons,
700  double reflectedT0 /* = 0.0 */
701  ) const
702  {
704 
705  // ask PhotonVisibilityService which voxel was being served,
706  // and how many photons where there generated (yikes!!);
707  // this value was put there by LightSource (yikes!!)
708  int VoxID;
709  double NProd;
710  fPVS->RetrieveLightProd(VoxID, NProd);
711 
712  pvs.SetLibraryEntry(VoxID, channel, double(nDirectPhotons) / NProd);
713 
714  //store reflected light
715  if (fPVS->StoreReflected()) {
716  pvs.SetLibraryEntry(VoxID, channel, double(nReflectedPhotons) / NProd, true);
717 
718  //store reflected first arrival time
719  if (fPVS->StoreReflT0()) pvs.SetLibraryReflT0Entry(VoxID, channel, reflectedT0);
720 
721  } // if reflected
722 
723  } // SimPhotonCounter::storeVisibility()
724 
725  // ---------------------------------------------------------------------------
726 
727 }
728 namespace opdet {
729 
731 
732 } //end namespace opdet
Store parameters for running LArG4.
std::vector< std::vector< double > > fstepPositions
OpDetGeo const & OpDetGeoFromOpDet(unsigned int OpDet) const
Returns the geo::OpDetGeo object for the given detector number.
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
double MinX() const
Returns the world x coordinate of the start of the box.
Definition: BoxBoundedGeo.h:90
std::vector< double > fPosition0
All information of a photon entering the sensitive optical detector volume.
Definition: SimPhotons.h:60
phot::PhotonVisibilityService const * fPVS
std::vector< std::vector< double > > fSignalsvuv
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
virtual bool detected(int OpChannel, const sim::OnePhoton &Phot, int &newOpChannel) const
EDAnalyzer(fhicl::ParameterSet const &pset)
Definition: EDAnalyzer.cc:6
static constexpr double kVUVWavelength
Value used when a typical ultraviolet light wavelength is needed.
CryostatGeo const & Cryostat(CryostatID const &cryoid=cryostat_zero) const
Returns the specified cryostat.
Particle class.
unsigned int NOpChannels() const
Number of electronics channels for all the optical detectors.
std::vector< double > fstepTimes
iterator find(const key_type &key)
Definition: ParticleList.h:318
std::vector< std::string > fInputModule
Simulation objects for optical detectors.
bool isVisible(double wavelength) const
Returns if we label as "visibile" a photon with specified wavelength [nm].
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
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)
T get(std::string const &key) const
Definition: ParameterSet.h:314
Class def header for mctrack data container.
virtual bool detectedLite(int OpChannel, int &newOpChannel) const
const sim::ParticleList & ParticleList() const
std::size_t getView(std::string const &moduleLabel, std::string const &productInstanceName, std::string const &processName, std::vector< ELEMENT const * > &result) const
Encapsulate the geometry of an optical detector.
geo::Point_t const & GetCenter() const
Definition: OpDetGeo.h:72
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
Collection of photons which recorded on one channel.
Definition: SimPhotons.h:127
Handle< PROD > getHandle(SelectorBase const &) const
void SetLibraryEntry(int VoxID, OpDetID_t libOpChannel, float N, bool wantReflected=false)
unsigned int NOpDet() const
Number of optical detectors in this TPC.
Definition: CryostatGeo.h:321
Float_t sc
Definition: plot.C:23
std::vector< std::vector< std::vector< double > > > fSignals_vis
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
object containing MC truth information necessary for making RawDigits and doing back tracking ...
IDNumber_t< Level::Event > EventNumber_t
Definition: IDNumber.h:118
EventNumber_t event() const
Definition: EventID.h:116
static constexpr double kVisibleThreshold
Threshold used to resolve between visible and ultraviolet light.
std::vector< std::vector< double > > fSignalsvis
geo::BoxBoundedGeo const & Boundaries() const
Returns boundaries of the cryostat (in centimetres).
Definition: CryostatGeo.h:114
TCEvent evt
Definition: DataStructs.cxx:8
Particle list in DetSim contains Monte Carlo particle information.
Float_t e
Definition: plot.C:35
RunNumber_t run() const
Definition: Event.cc:29
virtual float wavelength(double energy) const
Namespace collecting geometry-related classes utilities.
std::vector< std::vector< std::vector< double > > > fSignals_vuv
Tools and modules for checking out the basics of the Monte Carlo.
EventID id() const
Definition: Event.cc:23
art framework interface to geometry description
Event finding and building.
std::vector< Handle< PROD > > getMany(SelectorBase const &selector=MatchAllSelector{}) const
cheat::ParticleInventoryService const * pi_serv