LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
PhotonLibraryPropagation_module.cc
Go to the documentation of this file.
1 
14 
16 
23 #include "cetlib_except/exception.h"
24 #include "fhiclcpp/ParameterSet.h"
25 
26 #include "CLHEP/Random/RandFlat.h"
27 #include "CLHEP/Random/RandPoissonQ.h"
28 
29 #include <cmath>
30 #include <memory>
31 
32 using namespace std;
33 
34 namespace {
35 
36  double single_exp(double t, double tau2)
37  {
38  return exp((-1.0 * t) / tau2) / tau2;
39  }
40 
41  double bi_exp(double t, double tau1, double tau2)
42  {
43  return (((exp((-1.0 * t) / tau2) * (1.0 - exp((-1.0 * t) / tau1))) / tau2) / tau2) *
44  (tau1 + tau2);
45  }
46 
47  // Returns the time within the time distribution of the scintillation process, when the photon was created.
48  // Scintillation light has an exponential decay which here is given by the decay time, tau2,
49  // and an exponential increase, which here is given by the rise time, tau1.
50  // randflatscinttime is passed to use the saved seed from the RandomNumberSaver in order to be able to reproduce the same results.
51  double GetScintTime(double tau1, double tau2, CLHEP::RandFlat& randflatscinttime)
52  {
53  // tau1: rise time (originally defaulted to -1) and tau2: decay time
54  //ran1, ran2 = random numbers for the algorithm
55  if ((tau1 == 0.0) || (tau1 == -1.0)) { return -tau2 * log(randflatscinttime()); }
56  while (1) {
57  auto ran1 = randflatscinttime();
58  auto ran2 = randflatscinttime();
59  auto d = (tau1 + tau2) / tau2;
60  auto t = -tau2 * log(1 - ran1);
61  auto g = d * single_exp(t, tau2);
62  if (ran2 <= bi_exp(t, tau1, tau2) / g) { return t; }
63  }
64  }
65 
66  double GetScintYield(sim::SimEnergyDeposit const& edep, detinfo::LArProperties const& larp)
67  {
68  if (!larp.ScintByParticleType()) { return larp.ScintYieldRatio(); }
69  switch (edep.PdgCode()) {
70  case 2212: return larp.ProtonScintYieldRatio();
71  case 13:
72  case -13: return larp.MuonScintYieldRatio();
73  case 211:
74  case -211: return larp.PionScintYieldRatio();
75  case 321:
76  case -321: return larp.KaonScintYieldRatio();
77  case 1000020040: return larp.AlphaScintYieldRatio();
78  case 11:
79  case -11:
80  case 22: return larp.ElectronScintYieldRatio();
81  default: return larp.ElectronScintYieldRatio();
82  }
83  }
84 
85 } // unnamed namespace
86 
87 namespace phot {
88 
142  private:
146  vector<art::InputTag> fEDepTags;
148  CLHEP::HepRandomEngine& fPhotonEngine;
149  CLHEP::HepRandomEngine& fScintTimeEngine;
150 
151  void produce(art::Event&) override;
152 
153  public:
157  PhotonLibraryPropagation& operator=(PhotonLibraryPropagation const&) = delete;
158  PhotonLibraryPropagation& operator=(PhotonLibraryPropagation&&) = delete;
159  };
160 
161  PhotonLibraryPropagation::PhotonLibraryPropagation(fhicl::ParameterSet const& p)
162  : art::EDProducer{p}
163  , fRiseTimeFast{p.get<double>("RiseTimeFast", 0.0)}
164  , fRiseTimeSlow{p.get<double>("RiseTimeSlow", 0.0)}
165  , fDoSlowComponent{p.get<bool>("DoSlowComponent")}
166  , fEDepTags{p.get<vector<art::InputTag>>("EDepModuleLabels")}
167  , fPhotonEngine(art::ServiceHandle<rndm::NuRandomService>()->registerAndSeedEngine(
168  createEngine(0, "HepJamesRandom", "photon"),
169  "HepJamesRandom",
170  "photon",
171  p,
172  "SeedPhoton"))
174  createEngine(0, "HepJamesRandom", "scinttime"),
175  "HepJamesRandom",
176  "scinttime",
177  p,
178  "SeedScintTime"))
179  {
180  if (art::ServiceHandle<sim::LArG4Parameters const> {} -> UseLitePhotons()) {
181  produces<vector<sim::SimPhotonsLite>>();
182  }
183  else {
184  produces<vector<sim::SimPhotons>>();
185  }
186  }
187 
189  {
192  auto const* larp = lar::providerFrom<detinfo::LArPropertiesService>();
193  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(e);
194  CLHEP::RandPoissonQ randpoisphot{fPhotonEngine};
195  CLHEP::RandFlat randflatscinttime{fScintTimeEngine};
196  auto const nOpChannels = pvs->NOpChannels();
197  unique_ptr<vector<sim::SimPhotons>> photCol{new vector<sim::SimPhotons>{}};
198  auto& photonCollection{*photCol};
199  photonCollection.resize(nOpChannels);
200  unique_ptr<vector<sim::SimPhotonsLite>> photLiteCol{new vector<sim::SimPhotonsLite>{}};
201  auto& photonLiteCollection{*photLiteCol};
202  photonLiteCollection.resize(nOpChannels);
203  for (unsigned int i = 0; i < nOpChannels; ++i) {
204  photonLiteCollection[i].OpChannel = i;
205  photonCollection[i].SetChannel(i);
206  }
207  vector<vector<sim::SimEnergyDeposit> const*> edep_vecs;
208  for (auto label : fEDepTags) {
209  auto const& edep_handle = e.getValidHandle<vector<sim::SimEnergyDeposit>>(label);
210  edep_vecs.push_back(edep_handle);
211  }
212  for (auto const& edeps : edep_vecs) { //loop over modules
213  for (auto const& edep : *edeps) { //loop over energy deposits: one per step
214  //int count_onePhot =0; // unused
215  auto const& p = edep.MidPoint();
216  auto const& Visibilities = pvs->GetAllVisibilities(p);
217  if (!Visibilities) {
218  throw cet::exception("PhotonLibraryPropagation")
219  << "There is no entry in the PhotonLibrary for this position in space. "
220  "Position: "
221  << edep.MidPoint();
222  }
223  auto const isCalcData = fISAlg.CalcIonAndScint(detProp, edep);
224  //total amount of scintillation photons
225  double nphot = static_cast<int>(isCalcData.numPhotons);
226  //amount of scintillated photons created via the fast scintillation process
227  double nphot_fast = static_cast<int>(GetScintYield(edep, *larp) * nphot);
228  //amount of scintillated photons created via the slow scintillation process
229  double nphot_slow = nphot - nphot_fast;
230  for (unsigned int channel = 0; channel < nOpChannels; ++channel) {
231  auto visibleFraction = Visibilities[channel];
232  if (visibleFraction == 0.0) {
233  // Voxel is not visible at this optical channel, skip doing anything for this channel.
234  continue;
235  }
236  if (lgp->UseLitePhotons()) {
237  if (nphot_fast > 0) {
238  //throwing a random number from a poisson distribution with a mean of the amount of photons visible at this channel
239  auto n = static_cast<int>(randpoisphot.fire(nphot_fast * visibleFraction));
240  for (long i = 0; i < n; ++i) {
241  //calculates the time at which the photon was produced
242  auto time = static_cast<int>(edep.T0() + GetScintTime(fRiseTimeFast,
243  larp->ScintFastTimeConst(),
244  randflatscinttime));
245  ++photonLiteCollection[channel].DetectedPhotons[time];
246  }
247  }
248  if ((nphot_slow > 0) && fDoSlowComponent) {
249  //throwing a random number from a poisson distribution with a mean of the amount of photons visible at this channel
250  auto n = randpoisphot.fire(nphot_slow * visibleFraction);
251  for (long i = 0; i < n; ++i) {
252  //calculates the time at which the photon was produced
253  auto time = static_cast<int>(edep.T0() + GetScintTime(fRiseTimeSlow,
254  larp->ScintSlowTimeConst(),
255  randflatscinttime));
256  ++photonLiteCollection[channel].DetectedPhotons[time];
257  }
258  }
259  }
260  else {
261  sim::OnePhoton photon;
262  photon.SetInSD = false;
263  photon.InitialPosition = edep.End();
264  photon.Energy = 9.7e-6;
265  if (nphot_fast > 0) {
266  //throwing a random number from a poisson distribution with a mean of the amount of photons visible at this channel
267  auto n = randpoisphot.fire(nphot_fast * visibleFraction);
268  if (n > 0) {
269  //calculates the time at which the photon was produced
270  photon.Time =
271  edep.T0() +
272  GetScintTime(fRiseTimeFast, larp->ScintFastTimeConst(), randflatscinttime);
273  // add n copies of sim::OnePhoton photon to the photon collection for a given OpChannel
274  photonCollection[channel].insert(photonCollection[channel].end(), n, photon);
275  }
276  }
277  if ((nphot_slow > 0) && fDoSlowComponent) {
278  //throwing a random number from a poisson distribution with a mean of the amount of photons visible at this channel
279  auto n = randpoisphot.fire(nphot_slow * visibleFraction);
280  if (n > 0) {
281  //calculates the time at which the photon was produced
282  photon.Time =
283  edep.T0() +
284  GetScintTime(fRiseTimeSlow, larp->ScintSlowTimeConst(), randflatscinttime);
285  // add n copies of sim::OnePhoton photon to the photon collection for a given OpChannel
286  photonCollection[channel].insert(photonCollection[channel].end(), n, photon);
287  }
288  }
289  }
290  }
291  }
292  }
293  if (lgp->UseLitePhotons()) {
294  // put the photon collection of LitePhotons into the art event
295  e.put(move(photLiteCol));
296  }
297  else {
298  //put the photon collection of SimPhotons into the art event
299  e.put(move(photCol));
300  }
301  }
302 
303 } // namespace phot
304 
base_engine_t & createEngine(seed_t seed)
virtual double ElectronScintYieldRatio() const =0
Store parameters for running LArG4.
virtual double ScintYieldRatio() const =0
Utilities related to art service access.
virtual double AlphaScintYieldRatio() const =0
virtual double ScintSlowTimeConst() const =0
All information of a photon entering the sensitive optical detector volume.
Definition: SimPhotons.h:60
virtual double ScintFastTimeConst() const =0
STL namespace.
ISCalcData CalcIonAndScint(detinfo::DetectorPropertiesData const &detProp, sim::SimEnergyDeposit const &edep) override
virtual double ProtonScintYieldRatio() const =0
geo::Point_t InitialPosition
Scintillation position in world coordinates [cm].
Definition: SimPhotons.h:63
PutHandle< PROD > put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: Event.h:77
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
virtual double PionScintYieldRatio() const =0
Simulation objects for optical detectors.
geo::Point_t End() const
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
Fast simulation of propagating the photons created from SimEnergyDeposits.
Float_t d
Definition: plot.C:235
geo::Point_t MidPoint() const
Double_t edep
Definition: macro.C:13
An art service to assist in the distribution of guaranteed unique seeds to all engines within an art ...
General LArSoft Utilities.
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
bool SetInSD
Whether the photon reaches the sensitive detector.
Definition: SimPhotons.h:84
contains information for a single step in the detector simulation
Energy deposition in the active material.
virtual double MuonScintYieldRatio() const =0
Definition: MVAAlg.h:12
Char_t n[5]
float Energy
Scintillation photon energy [GeV].
Definition: SimPhotons.h:78
virtual double KaonScintYieldRatio() const =0
Float_t e
Definition: plot.C:35
virtual bool ScintByParticleType() const =0
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
bool UseLitePhotons() const