All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PDFastSimPAR_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: PDFastSimPAR
3 // Plugin Type: producer
4 // File: PDFastSimPAR_module.cc
5 // Description:
6 // - acts on sim::SimEnergyDeposit from LArG4Main,
7 // - simulate (fast, photon visibility service) the OpDet response to optical
8 // photons Input: 'sim::SimEnergyDeposit' Output: 'sim::OpDetBacktrackerRecord'
9 // Fast simulation of propagating the photons created from SimEnergyDeposits.
10 
11 // This module does a fast simulation of propagating the photons created from
12 // SimEnergyDeposits, This simulation is done using the Semi-Analytical model, which
13 // stores the visibilities of each optical channel with respect to each optical
14 // voxel in the TPC volume, to avoid propagating single photons using Geant4. At
15 // the end of this module a collection of the propagated photons either as
16 //'sim::OpDetBacktrackerRecord' are placed into the art event.
17 
18 // The steps this module takes are:
19 // - to take number of photon and the vertex information from
20 // 'sim::SimEnergyDeposits',
21 // - use the Semi-Analytical model (visibilities) to determine the amount of visible
22 // photons at each optical channel,
23 // - visible photons: the number of photons times the visibility at the middle
24 // of the Geant4 step for a given optical channel.
25 // - other photon information is got from 'sim::SimEnergyDeposits'
26 // - add 'sim::OpDetBacktrackerRecord' to event
27 // Aug. 19 by Mu Wei
28 // Restructured Nov. 21 by P. Green
29 ////////////////////////////////////////////////////////////////////////
30 
31 // LArSoft libraries
46 
47 #include "nurandom/RandomUtils/NuRandomService.h"
48 
49 // Art libraries
50 #include "art/Framework/Core/EDProducer.h"
51 #include "art/Framework/Core/ModuleMacros.h"
52 #include "art/Framework/Principal/Event.h"
53 #include "art/Framework/Principal/Handle.h"
54 #include "art/Framework/Services/Registry/ServiceHandle.h"
55 #include "art/Utilities/make_tool.h"
56 #include "canvas/Utilities/Exception.h"
57 #include "canvas/Utilities/InputTag.h"
58 #include "messagefacility/MessageLogger/MessageLogger.h"
59 #include "fhiclcpp/ParameterSet.h"
60 #include "fhiclcpp/types/Atom.h"
61 #include "fhiclcpp/types/Comment.h"
62 #include "fhiclcpp/types/DelegatedParameter.h"
63 #include "fhiclcpp/types/Name.h"
64 #include "fhiclcpp/types/OptionalDelegatedParameter.h"
65 #include "cetlib_except/exception.h"
66 
67 // Random numbers
68 #include "CLHEP/Random/RandPoissonQ.h"
69 
70 #include <cmath>
71 #include <ctime>
72 #include <map>
73 #include <memory>
74 #include <vector>
75 
76 namespace phot {
77  class PDFastSimPAR : public art::EDProducer {
78  public:
79 
80  // Define the fhicl configuration
81  struct Config {
82  using Name = fhicl::Name;
83  using Comment = fhicl::Comment;
84  using DP = fhicl::DelegatedParameter;
85  using ODP = fhicl::OptionalDelegatedParameter;
86 
87  fhicl::Atom<art::InputTag> SimulationLabel { Name("SimulationLabel"), Comment("SimEnergyDeposit label.") };
88  fhicl::Atom<bool> DoFastComponent { Name("DoFastComponent"), Comment("Simulate slow scintillation light, default true"), true };
89  fhicl::Atom<bool> DoSlowComponent { Name("DoSlowComponent"), Comment("Simulate slow scintillation light") };
90  fhicl::Atom<bool> DoReflectedLight { Name("DoReflectedLight"), Comment("Simulate reflected visible light") };
91  fhicl::Atom<bool> IncludeAnodeReflections { Name("IncludeAnodeReflections"), Comment("Simulate anode reflections, default false"), false };
92  fhicl::Atom<bool> IncludePropTime { Name("IncludePropTime"), Comment("Simulate light propagation time") };
93  fhicl::Atom<bool> GeoPropTimeOnly { Name("GeoPropTimeOnly"), Comment("Simulate light propagation time geometric approximation, default false"), false };
94  fhicl::Atom<bool> UseLitePhotons { Name("UseLitePhotons"), Comment("Store SimPhotonsLite/OpDetBTRs instead of SimPhotons") };
95  fhicl::Atom<bool> OpaqueCathode { Name("OpaqueCathode"), Comment("Photons cannot cross the cathode") };
96  fhicl::Atom<bool> OnlyActiveVolume { Name("OnlyActiveVolume"), Comment("PAR fast sim usually only for active volume, default true"), true };
97  fhicl::Atom<bool> OnlyOneCryostat { Name("OnlyOneCryostat"), Comment("Set to true if light is only supported in C:1") };
98  DP ScintTimeTool { Name("ScintTimeTool"), Comment("Tool describing scintillation time structure")};
99  ODP VUVTiming { Name("VUVTiming"), Comment("Configuration for UV timing parameterization")};
100  ODP VISTiming { Name("VISTiming"), Comment("Configuration for visible timing parameterization")};
101  DP VUVHits { Name("VUVHits"), Comment("Configuration for UV visibility parameterization")};
102  ODP VISHits { Name("VISHits"), Comment("Configuration for visibile visibility parameterization")};
103  };
104  using Parameters = art::EDProducer::Table<Config>;
105 
106  explicit PDFastSimPAR(Parameters const & config);
107  void produce(art::Event&) override;
108 
109  private:
110 
111  void Initialization();
112 
113  void detectedNumPhotons(std::vector<int>& DetectedNumPhotons,
114  const std::vector<double>& OpDetVisibilities,
115  const int NumPhotons) const;
116 
117  void AddOpDetBTR(std::vector< sim::OpDetBacktrackerRecord > & opbtr,
118  std::vector<int> & ChannelMap,
119  const sim::OpDetBacktrackerRecord & btr) const;
120 
121 
122  bool isOpDetInSameTPC(geo::Point_t const& ScintPoint,
123  geo::Point_t const& OpDetPoint) const;
124 
125  // ISTPC
127 
128  // semi-analytical model
129  std::unique_ptr<SemiAnalyticalModel> fVisibilityModel;
130 
131  // propagation time model
132  std::unique_ptr<PropagationTimeModel> fPropTimeModel;
133 
134  // random numbers
135  CLHEP::HepRandomEngine& fPhotonEngine;
136  std::unique_ptr<CLHEP::RandPoissonQ> fRandPoissPhot;
137  CLHEP::HepRandomEngine& fScintTimeEngine;
138 
139  size_t fNOpChannels; // Pulled from geom during Initialization()
140 
141  // geometry properties
142  std::vector<geo::BoxBoundedGeo> fActiveVolumes;
143  int fNTPC;
144 
145  // optical detector properties
146  std::vector<geo::Point_t> fOpDetCenter;
147 
148  //////////////////////
149  // Input Parameters //
150  //////////////////////
151 
152  // Module behavior
153  const art::InputTag simTag;
154  const bool fDoFastComponent;
155  const bool fDoSlowComponent;
156  const bool fDoReflectedLight;
158  const bool fIncludePropTime;
159  const bool fGeoPropTimeOnly;
160  const bool fUseLitePhotons;
161  const bool fOpaqueCathode;
162  const bool fOnlyActiveVolume;
163  const bool fOnlyOneCryostat;
164  std::unique_ptr<ScintTime> fScintTime; // Tool to retrive timinig of scintillation
165 
166  // Parameterized Simulation
167  fhicl::ParameterSet fVUVTimingParams;
168  fhicl::ParameterSet fVISTimingParams;
169  fhicl::ParameterSet fVUVHitsParams;
170  fhicl::ParameterSet fVISHitsParams;
171 
172  };
173 
174  //......................................................................
176  : art::EDProducer{config}
177  , fISTPC{*(lar::providerFrom<geo::Geometry>())}
178  , fPhotonEngine(art::ServiceHandle<rndm::NuRandomService>()->createEngine(
179  *this, "HepJamesRandom", "photon", config.get_PSet(), "SeedPhoton"))
180  , fScintTimeEngine(art::ServiceHandle<rndm::NuRandomService>()->createEngine(
181  *this, "HepJamesRandom", "scinttime", config.get_PSet(), "SeedScintTime"))
182  , simTag(config().SimulationLabel())
183  , fDoFastComponent(config().DoFastComponent())
184  , fDoSlowComponent(config().DoSlowComponent())
185  , fDoReflectedLight(config().DoReflectedLight())
186  , fIncludeAnodeReflections(config().IncludeAnodeReflections())
187  , fIncludePropTime(config().IncludePropTime())
188  , fGeoPropTimeOnly(config().GeoPropTimeOnly())
189  , fUseLitePhotons(config().UseLitePhotons())
190  , fOpaqueCathode(config().OpaqueCathode())
191  , fOnlyActiveVolume(config().OnlyActiveVolume())
192  , fOnlyOneCryostat(config().OnlyOneCryostat())
193  , fScintTime{art::make_tool<phot::ScintTime>(config().ScintTimeTool.get<fhicl::ParameterSet>())}
194  , fVUVHitsParams(config().VUVHits.get<fhicl::ParameterSet>())
195  {
196  // Validate configuration options
197  if(fIncludePropTime && !config().VUVTiming.get_if_present<fhicl::ParameterSet>(fVUVTimingParams)) {
198  throw art::Exception(art::errors::Configuration)
199  << "Propagation time simulation requested, but VUVTiming not specified." << "\n";
200  }
201 
202  if(fDoReflectedLight && !config().VISHits.get_if_present<fhicl::ParameterSet>(fVISHitsParams)) {
203  throw art::Exception(art::errors::Configuration)
204  << "Reflected light simulation requested, but VisHits not specified." << "\n";
205  }
206 
207  if (fDoReflectedLight && fIncludePropTime && !config().VISTiming.get_if_present<fhicl::ParameterSet>(fVISTimingParams)) {
208  throw art::Exception(art::errors::Configuration)
209  << "Reflected light propagation time simulation requested, but VISTiming not specified." << "\n";
210  }
211 
212  if(fIncludeAnodeReflections && !config().VISHits.get_if_present<fhicl::ParameterSet>(fVISHitsParams)) {
213  throw art::Exception(art::errors::Configuration)
214  << "Anode reflections light simulation requested, but VisHits not specified." << "\n";
215  }
216 
217  Initialization();
218 
219  if (fUseLitePhotons) {
220  mf::LogInfo("PDFastSimPAR") << "Using Lite Photons";
221  produces< std::vector<sim::SimPhotonsLite> >();
222  produces< std::vector<sim::OpDetBacktrackerRecord> >();
223  if(fDoReflectedLight) {
224  mf::LogInfo("PDFastSimPAR") << "Storing Reflected Photons";
225  produces< std::vector<sim::SimPhotonsLite> >("Reflected");
226  produces< std::vector<sim::OpDetBacktrackerRecord> >("Reflected");
227  }
228  }
229  else {
230  mf::LogInfo("PDFastSimPAR") << "Using Sim Photons";
231  produces< std::vector<sim::SimPhotons> >();
232  if(fDoReflectedLight) {
233  mf::LogInfo("PDFastSimPAR") << "Storing Reflected Photons";
234  produces< std::vector<sim::SimPhotons> >("Reflected");
235  }
236  }
237  }
238 
239  //......................................................................
240  void
241  PDFastSimPAR::produce(art::Event& event)
242  {
243  mf::LogTrace("PDFastSimPAR") << "PDFastSimPAR Module Producer"
244  << "EventID: " << event.event();
245 
246  std::vector<int> PDChannelToSOCMapDirect(fNOpChannels, -1); // Where each OpChan is.
247  std::vector<int> PDChannelToSOCMapReflect(fNOpChannels, -1); // Where each OpChan is.
248 
249  // SimPhotonsLite
250  auto phlit = std::make_unique<std::vector<sim::SimPhotonsLite>>();
251  auto opbtr = std::make_unique<std::vector<sim::OpDetBacktrackerRecord>>();
252  auto phlit_ref = std::make_unique<std::vector<sim::SimPhotonsLite>>();
253  auto opbtr_ref = std::make_unique<std::vector<sim::OpDetBacktrackerRecord>>();
254  auto& dir_phlitcol(*phlit);
255  auto& ref_phlitcol(*phlit_ref);
256  // SimPhotons
257  auto phot = std::make_unique<std::vector<sim::SimPhotons>>();
258  auto phot_ref = std::make_unique<std::vector<sim::SimPhotons>>();
259  auto& dir_photcol(*phot);
260  auto& ref_photcol(*phot_ref);
261  if(fUseLitePhotons){
262  dir_phlitcol.resize(fNOpChannels);
263  ref_phlitcol.resize(fNOpChannels);
264  for (unsigned int i = 0; i < fNOpChannels; i ++) {
265  dir_phlitcol[i].OpChannel = i;
266  ref_phlitcol[i].OpChannel = i;
267  }
268  }
269  else{ // SimPhotons
270  dir_photcol.resize(fNOpChannels);
271  ref_photcol.resize(fNOpChannels);
272  for (unsigned int i = 0; i < fNOpChannels; i ++) {
273  dir_photcol[i].fOpChannel = i;
274  ref_photcol[i].fOpChannel = i;
275  }
276  }
277 
278  art::Handle<std::vector<sim::SimEnergyDeposit>> edepHandle;
279  if (!event.getByLabel(simTag, edepHandle)) {
280  mf::LogError("PDFastSimPAR") << "PDFastSimPAR Module Cannot getByLabel: " << simTag;
281  return;
282  }
283 
284  auto const& edeps = edepHandle;
285 
286  int num_points = 0;
287  int num_fastph = 0;
288  int num_slowph = 0;
289  int num_fastdp = 0;
290  int num_slowdp = 0;
291 
292  for (auto const& edepi : *edeps) {
293  num_points++;
294 
295  int nphot_fast = edepi.NumFPhotons();
296  int nphot_slow = edepi.NumSPhotons();
297 
298  num_fastph += nphot_fast;
299  num_slowph += nphot_slow;
300 
301  if(!((nphot_fast > 0 && fDoFastComponent) ||
302  (nphot_slow > 0 && fDoSlowComponent))) continue;
303 
304  int trackID = edepi.TrackID();
305  int nphot = edepi.NumPhotons();
306  double edeposit = edepi.Energy() / nphot;
307  double pos[3] = {edepi.MidPointX(), edepi.MidPointY(), edepi.MidPointZ()};
308  geo::Point_t const ScintPoint = {pos[0], pos[1], pos[2]};
309 
310  if (fOnlyActiveVolume && !fISTPC.isScintInActiveVolume(ScintPoint)) continue;
311 
312  // direct light
313  std::vector<int> DetectedNumFast(fNOpChannels);
314  std::vector<int> DetectedNumSlow(fNOpChannels);
315 
316  std::vector<double> OpDetVisibilities;
317  fVisibilityModel->detectedDirectVisibilities(OpDetVisibilities, ScintPoint);
318  detectedNumPhotons(DetectedNumFast, OpDetVisibilities, nphot_fast);
319  detectedNumPhotons(DetectedNumSlow, OpDetVisibilities, nphot_slow);
320 
322  std::vector<int> AnodeDetectedNumFast(fNOpChannels);
323  std::vector<int> AnodeDetectedNumSlow(fNOpChannels);
324 
325  std::vector<double> OpDetVisibilitiesAnode;
326  fVisibilityModel->detectedReflectedVisibilities(OpDetVisibilitiesAnode, ScintPoint, true);
327  detectedNumPhotons(AnodeDetectedNumFast, OpDetVisibilitiesAnode, nphot_fast);
328  detectedNumPhotons(AnodeDetectedNumSlow, OpDetVisibilitiesAnode, nphot_slow);
329 
330  // add to existing count
331  for (size_t i=0; i<AnodeDetectedNumFast.size(); ++i) {DetectedNumFast[i] += AnodeDetectedNumFast[i];}
332  for (size_t i=0; i<AnodeDetectedNumSlow.size(); ++i) {DetectedNumSlow[i] += AnodeDetectedNumSlow[i];}
333  }
334 
335  // reflected light, if enabled
336  std::vector<int> ReflDetectedNumFast(fNOpChannels);
337  std::vector<int> ReflDetectedNumSlow(fNOpChannels);
338  if (fDoReflectedLight) {
339  std::vector<double> OpDetVisibilitiesRefl;
340  fVisibilityModel->detectedReflectedVisibilities(OpDetVisibilitiesRefl, ScintPoint, false);
341  detectedNumPhotons(ReflDetectedNumFast, OpDetVisibilitiesRefl, nphot_fast);
342  detectedNumPhotons(ReflDetectedNumSlow, OpDetVisibilitiesRefl, nphot_slow);
343  }
344 
345  // loop through direct photons then reflected photons cases
346  size_t DoReflected = (fDoReflectedLight) ? 1 : 0;
347  for (size_t Reflected = 0; Reflected <= DoReflected; ++Reflected) {
348  for (size_t channel = 0; channel < fNOpChannels; channel++) {
349 
350  if (fOpaqueCathode && !isOpDetInSameTPC(ScintPoint, fOpDetCenter[channel])) continue;
351 
352  int ndetected_fast = DetectedNumFast[channel];
353  int ndetected_slow = DetectedNumSlow[channel];
354  if (Reflected) {
355  ndetected_fast = ReflDetectedNumFast[channel];
356  ndetected_slow = ReflDetectedNumSlow[channel];
357  }
358  if(!((ndetected_fast > 0 && fDoFastComponent) ||
359  (ndetected_slow > 0 && fDoSlowComponent))) continue;
360 
361  // calculate propagation time, does not matter whether fast or slow photon
362  std::vector<double> transport_time;
363  if (fIncludePropTime) {
364  transport_time.resize(ndetected_fast + ndetected_slow);
365  fPropTimeModel->propagationTime(transport_time, ScintPoint, channel, Reflected);
366  }
367 
368  // SimPhotonsLite case
369  if (fUseLitePhotons) {
370  sim::OpDetBacktrackerRecord tmpbtr(channel);
371  if (ndetected_fast > 0 && fDoFastComponent) {
372  int n = ndetected_fast;
373  num_fastdp += n;
374  for (int i = 0; i < n; ++i) {
375  // calculates the time at which the photon was produced
376  fScintTime->GenScintTime(true, fScintTimeEngine);
377  int time;
378  if (fIncludePropTime) time = static_cast<int>(edepi.StartT() + fScintTime->GetScintTime() + transport_time[i]);
379  else time = static_cast<int>(edepi.StartT() + fScintTime->GetScintTime());
380  if (Reflected) ++ref_phlitcol[channel].DetectedPhotons[time];
381  else ++dir_phlitcol[channel].DetectedPhotons[time];
382  tmpbtr.AddScintillationPhotons(trackID, time, 1, pos, edeposit);
383  }
384  }
385  if (ndetected_slow > 0 && fDoSlowComponent) {
386  int n = ndetected_slow;
387  num_slowdp += n;
388  for (int i = 0; i < n; ++i) {
389  fScintTime->GenScintTime(false, fScintTimeEngine);
390  int time;
391  if (fIncludePropTime) time = static_cast<int>(edepi.StartT() + fScintTime->GetScintTime() + transport_time[ndetected_fast + i]);
392  else time = static_cast<int>(edepi.StartT() + fScintTime->GetScintTime());
393  if (Reflected) ++ref_phlitcol[channel].DetectedPhotons[time];
394  else ++dir_phlitcol[channel].DetectedPhotons[time];
395  tmpbtr.AddScintillationPhotons(trackID, time, 1, pos, edeposit);
396  }
397  }
398  if (Reflected) AddOpDetBTR(*opbtr_ref, PDChannelToSOCMapReflect, tmpbtr);
399  else AddOpDetBTR(*opbtr, PDChannelToSOCMapDirect, tmpbtr);
400  }
401  // SimPhotons case
402  else {
404  photon.SetInSD = false;
405  photon.InitialPosition = edepi.End();
406  if (Reflected) photon.Energy = 2.9 * CLHEP::eV; // 430 nm
407  else photon.Energy = 9.7 * CLHEP::eV; // 128 nm
408  if (ndetected_fast > 0 && fDoFastComponent) {
409  int n = ndetected_fast;
410  num_fastdp += n;
411  for (int i = 0; i < n; ++i) {
412  // calculates the time at which the photon was produced
413  fScintTime->GenScintTime(true, fScintTimeEngine);
414  int time;
415  if (fIncludePropTime) time = static_cast<int>(edepi.StartT() + fScintTime->GetScintTime() + transport_time[i]);
416  else time = static_cast<int>(edepi.StartT() + fScintTime->GetScintTime());
417  photon.Time = time;
418  if(Reflected) ref_photcol[channel].insert(ref_photcol[channel].end(), 1, photon);
419  else dir_photcol[channel].insert(dir_photcol[channel].end(), 1, photon);
420  }
421  }
422  if (ndetected_slow > 0 && fDoSlowComponent) {
423  int n = ndetected_slow;
424  num_slowdp += n;
425  for (int i = 0; i < n; ++i) {
426  fScintTime->GenScintTime(false, fScintTimeEngine);
427  int time;
428  if (fIncludePropTime) time = static_cast<int>(edepi.StartT() + fScintTime->GetScintTime() + transport_time[ndetected_fast + i]);
429  else time = static_cast<int>(edepi.StartT() + fScintTime->GetScintTime());
430  photon.Time = time;
431  if(Reflected) ref_photcol[channel].insert(ref_photcol[channel].end(), 1, photon);
432  else dir_photcol[channel].insert(dir_photcol[channel].end(), 1, photon);
433  }
434  }
435  }
436  }
437  }
438  }
439 
440  mf::LogTrace("PDFastSimPAR") << "Total points: " << num_points
441  << ", total fast photons: " << num_fastph
442  << ", total slow photons: " << num_slowph
443  << "\ndetected fast photons: " << num_fastdp
444  << ", detected slow photons: " << num_slowdp;
445 
446  if (fUseLitePhotons) {
447  event.put(move(phlit));
448  event.put(move(opbtr));
449  if (fDoReflectedLight) {
450  event.put(move(phlit_ref), "Reflected");
451  event.put(move(opbtr_ref), "Reflected");
452  }
453  }
454  else {
455  event.put(move(phot));
456  if (fDoReflectedLight) {
457  event.put(move(phot_ref), "Reflected");
458  }
459  }
460 
461  return;
462  }
463 
464  //......................................................................
465  void PDFastSimPAR::AddOpDetBTR(std::vector< sim::OpDetBacktrackerRecord > & opbtr,
466  std::vector<int> & ChannelMap,
467  const sim::OpDetBacktrackerRecord & btr) const
468  {
469  int iChan = btr.OpDetNum();
470  if (ChannelMap[iChan] < 0) {
471  ChannelMap[iChan] = opbtr.size();
472  opbtr.emplace_back(std::move(btr));
473  }
474  else {
475  size_t idtest = ChannelMap[iChan];
476  auto const& timePDclockSDPsMap = btr.timePDclockSDPsMap();
477  for(auto const& timePDclockSDP : timePDclockSDPsMap) {
478  for(auto const& sdp : timePDclockSDP.second) {
479  double xyz[3] = {sdp.x, sdp.y, sdp.z};
480  opbtr.at(idtest).AddScintillationPhotons(sdp.trackID,
481  timePDclockSDP.first,
482  sdp.numPhotons,
483  xyz,
484  sdp.energy);
485  }
486  }
487  }
488  }
489 
490  //......................................................................
491  void
493  {
494  std::cout << "PDFastSimPAR Initialization" << std::endl;
495  std::cout << "Initializing the geometry of the detector." << std::endl;
496  std::cout << "Simulate using semi-analytic model for number of hits." << std::endl;
497 
498  fRandPoissPhot = std::make_unique<CLHEP::RandPoissonQ>(fPhotonEngine);
499  geo::GeometryCore const& geom = *(lar::providerFrom<geo::Geometry>());
500 
501  // photo-detector visibility model (semi-analytical model)
503 
504  // propagation time model
506 
507  // Store info from the Geometry service
508  fNOpChannels = geom.NOpDets();
510  fNTPC = geom.NTPC();
511 
512  {
513  auto log = mf::LogTrace("PDFastSimPAR") << "PDFastSimPAR: active volume boundaries from "
514  << fActiveVolumes.size() << " volumes:";
515  for (auto const& [iCryo, box] : util::enumerate(fActiveVolumes)) {
516  log << "\n - C:" << iCryo << ": " << box.Min() << " -- " << box.Max() << " cm";
517  }
518  } // local scope
519 
520  if (geom.Ncryostats() > 1U) {
521  if (fOnlyOneCryostat) {
522  mf::LogWarning("PDFastSimPAR")
523  << std::string(80, '=') << "\nA detector with " << geom.Ncryostats()
524  << " cryostats is configured"
525  << " , and semi-analytic model is requested for scintillation photon propagation."
526  << " THIS CONFIGURATION IS NOT SUPPORTED and it is open to bugs"
527  << " (e.g. scintillation may be detected only in cryostat #0)."
528  << "\nThis would be normally a fatal error, but it has been forcibly overridden."
529  << "\n"
530  << std::string(80, '=');
531  }
532  else {
533  throw art::Exception(art::errors::Configuration)
534  << "Photon propagation via semi-analytic model is not supported yet"
535  << " on detectors with more than one cryostat.";
536  }
537  }
538 
539  for (size_t const i : util::counter(fNOpChannels)) {
540  geo::OpDetGeo const& opDet = geom.OpDetGeoFromOpDet(i);
541  fOpDetCenter.push_back(opDet.GetCenter());
542  }
543  }
544 
545  //......................................................................
546  // calculates number of photons detected given visibility and emitted number of photons
547  void
548  PDFastSimPAR::detectedNumPhotons(std::vector<int>& DetectedNumPhotons, const std::vector<double>& OpDetVisibilities, const int NumPhotons) const
549  {
550  for (size_t i=0; i<OpDetVisibilities.size(); ++i){
551  DetectedNumPhotons[i] = fRandPoissPhot->fire(OpDetVisibilities[i] * NumPhotons);
552  }
553  }
554 
555  //......................................................................
556  // checks whether photo-detector is able to see the emitted light scintillation
557  bool
559  geo::Point_t const& OpDetPoint) const
560  {
561  // check optical channel is in same TPC as scintillation light, if not doesn't see light
562  // temporary method working for SBND, uBooNE, DUNE 1x2x6; to be replaced to work in full DUNE geometry
563  // check x coordinate has same sign or is close to zero
564  if (((ScintPoint.X() < 0.) != (OpDetPoint.X() < 0.)) &&
565  std::abs(OpDetPoint.X()) > 10. && fNTPC == 2) { // TODO: replace with geometry service method
566  return false;
567  }
568  return true;
569  }
570 
571  // ---------------------------------------------------------------------------
572 
573 } // namespace phot
574 
575 DEFINE_ART_MODULE(phot::PDFastSimPAR)
fhicl::OptionalDelegatedParameter ODP
std::vector< geo::Point_t > fOpDetCenter
fhicl::ParameterSet fVISHitsParams
bool isOpDetInSameTPC(geo::Point_t const &ScintPoint, geo::Point_t const &OpDetPoint) const
process_name can override from command line with o or output photon
Definition: runPID.fcl:28
void AddOpDetBTR(std::vector< sim::OpDetBacktrackerRecord > &opbtr, std::vector< int > &ChannelMap, const sim::OpDetBacktrackerRecord &btr) const
static std::vector< geo::BoxBoundedGeo > extractActiveLArVolume(geo::GeometryCore const &geom)
Definition: ISTPC.cxx:51
Utilities related to art service access.
Definition of util::enumerate().
std::unique_ptr< PropagationTimeModel > fPropTimeModel
fhicl::Atom< bool > DoSlowComponent
PDFastSimPAR(Parameters const &config)
All information of a photon entering the sensitive optical detector volume.
Definition: SimPhotons.h:64
std::vector< geo::BoxBoundedGeo > fActiveVolumes
fhicl::Atom< bool > DoReflectedLight
void GetCenter(double *xyz, double localz=0.0) const
Definition: OpDetGeo.cxx:40
std::unique_ptr< ScintTime > fScintTime
Energy deposited on a readout Optical Detector by simulated tracks.
fhicl::DelegatedParameter DP
geo::Point_t InitialPosition
Scintillation position in world coordinates [cm].
Definition: SimPhotons.h:67
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
Definition: enumerate.h:69
fhicl::Atom< bool > UseLitePhotons
std::unique_ptr< CLHEP::RandPoissonQ > fRandPoissPhot
T abs(T value)
CLHEP::HepRandomEngine & fScintTimeEngine
Simulation objects for optical detectors.
fhicl::ParameterSet fVISTimingParams
int OpDetNum() const
Returns the readout Optical Detector this object describes.
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
Definition: counter.h:285
Definitions of geometry vector data types.
std::unique_ptr< SemiAnalyticalModel > fVisibilityModel
fhicl::Atom< bool > OpaqueCathode
fhicl::ParameterSet fVUVTimingParams
fhicl::Atom< bool > IncludeAnodeReflections
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
void produce(art::Event &) override
BEGIN_PROLOG vertical distance to the surface Name
Test of util::counter and support utilities.
Description of geometry of one entire detector.
Provides a base class aware of world box coordinates.
void AddScintillationPhotons(TrackID_t trackID, timePDclock_t timePDclock, double numberPhotons, double const *xyz, double energy)
Add scintillation photons and energy to this OpticalDetector.
Encapsulate the geometry of an optical detector.
fhicl::Atom< bool > GeoPropTimeOnly
CLHEP::HepRandomEngine & fPhotonEngine
bool SetInSD
Whether the photon reaches the sensitive detector.
Definition: SimPhotons.h:88
const art::InputTag simTag
contains information for a single step in the detector simulation
void detectedNumPhotons(std::vector< int > &DetectedNumPhotons, const std::vector< double > &OpDetVisibilities, const int NumPhotons) const
fhicl::Atom< art::InputTag > SimulationLabel
art::EDProducer::Table< Config > Parameters
fhicl::Atom< bool > IncludePropTime
float Energy
Scintillation photon energy [GeV].
Definition: SimPhotons.h:82
fhicl::Atom< bool > OnlyActiveVolume
bool isScintInActiveVolume(geo::Point_t const &ScintPoint)
Definition: ISTPC.cxx:43
const bool fIncludeAnodeReflections
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
timePDclockSDPs_t const & timePDclockSDPsMap() const
Returns all the deposited energy information as stored.
fhicl::Atom< bool > OnlyOneCryostat
art framework interface to geometry description
BEGIN_PROLOG could also be cout
fhicl::Atom< bool > DoFastComponent
services LArG4Parameters UseLitePhotons
createEngine fScintTimeEngine(art::ServiceHandle< rndm::NuRandomService >() ->createEngine(*this,"HepJamesRandom","scinttime", p,"SeedScintTime"))
fhicl::ParameterSet fVUVHitsParams