LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
PhotonLibraryPropagation_module.cc
Go to the documentation of this file.
1 
50 #include "CLHEP/Random/RandFlat.h"
51 #include "CLHEP/Random/RandPoissonQ.h"
58 #include "cetlib_except/exception.h"
59 #include "fhiclcpp/ParameterSet.h"
69 
70 #include <cmath>
71 #include <map>
72 #include <memory>
73 #include <vector>
74 
75 using namespace std;
76 
77 namespace {
78 
79 double single_exp(double t, double tau2)
80 {
81  return exp((-1.0 * t) / tau2) / tau2;
82 }
83 
84 double bi_exp(double t, double tau1, double tau2)
85 {
86  return (((exp((-1.0 * t) / tau2) * (1.0 - exp((-1.0 * t) / tau1))) / tau2) / tau2) * (tau1 + tau2);
87 }
88 
89 
90 // Returns the time within the time distribution of the scintillation process, when the photon was created.
91 // Scintillation light has an exponential decay which here is given by the decay time, tau2,
92 // and an exponential increase, which here is given by the rise time, tau1.
93 // randflatscinttime is passed to use the saved seed from the RandomNumberSaver in order to be able to reproduce the same results.
94 double GetScintTime(double tau1, double tau2, CLHEP::RandFlat& randflatscinttime)
95 {
96  // tau1: rise time (originally defaulted to -1) and tau2: decay time
97  //ran1, ran2 = random numbers for the algorithm
98  if ((tau1 == 0.0) || (tau1 == -1.0)) {
99  return -tau2 * log(randflatscinttime());
100  }
101  while (1) {
102  auto ran1 = randflatscinttime();
103  auto ran2 = randflatscinttime();
104  auto d = (tau1 + tau2) / tau2;
105  auto t = -tau2 * log(1 - ran1);
106  auto g = d * single_exp(t, tau2);
107  if (ran2 <= bi_exp(t, tau1, tau2) / g) {
108  return t;
109  }
110  }
111 }
112 
113 double GetScintYield(sim::SimEnergyDeposit const& edep, detinfo::LArProperties const& larp)
114 {
115  if (!larp.ScintByParticleType()) {
116  return larp.ScintYieldRatio();
117  }
118  switch (edep.PdgCode()) {
119  case 2212:
120  return larp.ProtonScintYieldRatio();
121  case 13:
122  case -13:
123  return larp.MuonScintYieldRatio();
124  case 211:
125  case -211:
126  return larp.PionScintYieldRatio();
127  case 321:
128  case -321:
129  return larp.KaonScintYieldRatio();
130  case 1000020040:
131  return larp.AlphaScintYieldRatio();
132  case 11:
133  case -11:
134  case 22:
135  return larp.ElectronScintYieldRatio();
136  default:
137  return larp.ElectronScintYieldRatio();
138  }
139 }
140 
141 } // unnamed namespace
142 
143 namespace phot {
144 
146 
147 private:
148 
152  vector<art::InputTag> fEDepTags;
154 
155 public:
156 
161  PhotonLibraryPropagation& operator=(PhotonLibraryPropagation const&) = delete;
162  PhotonLibraryPropagation& operator=(PhotonLibraryPropagation&&) = delete;
163 
164 public:
165 
166  void produce(art::Event&) override;
167 
168 };
169 
170 PhotonLibraryPropagation::~PhotonLibraryPropagation()
171 {
172 }
173 
174 PhotonLibraryPropagation::PhotonLibraryPropagation(fhicl::ParameterSet const& p)
175  : fRiseTimeFast{p.get<double>("RiseTimeFast", 0.0)}
176  , fRiseTimeSlow{p.get<double>("RiseTimeSlow", 0.0)}
177  , fDoSlowComponent{p.get<bool>("DoSlowComponent")}
178  , fEDepTags{p.get<vector<art::InputTag>>("EDepModuleLabels")}
179 {
180  art::ServiceHandle<rndm::NuRandomService>()->createEngine(*this, "HepJamesRandom", "photon", p, "SeedPhoton");
181  art::ServiceHandle<rndm::NuRandomService>()->createEngine(*this, "HepJamesRandom", "scinttime", p, "SeedScintTime");
183  if (lgp->UseLitePhotons()) {
184  produces<vector<sim::SimPhotonsLite>>();
185  }
186  else {
187  produces<vector<sim::SimPhotons>>();
188  }
189 }
190 
192 {
195  auto const* larp = lar::providerFrom<detinfo::LArPropertiesService>();
197  auto& engine_photon = rng->getEngine("photon");
198  CLHEP::RandPoissonQ randpoisphot{engine_photon};
199  auto& engine_scinttime = rng->getEngine("scinttime");
200  CLHEP::RandFlat randflatscinttime{engine_scinttime};
201  auto const nOpChannels = static_cast<int>(pvs->NOpChannels());
202  fISAlg.Initialize(larp, lar::providerFrom<detinfo::DetectorPropertiesService>(), &*lgp, lar::providerFrom<spacecharge::SpaceChargeService>());
203  unique_ptr<vector<sim::SimPhotons>> photCol{new vector<sim::SimPhotons>{}};
204  auto& photonCollection{*photCol};
205  photonCollection.resize(nOpChannels);
206  unique_ptr<vector<sim::SimPhotonsLite>> photLiteCol{new vector<sim::SimPhotonsLite>{}};
207  auto& photonLiteCollection{*photLiteCol};
208  photonLiteCollection.resize(nOpChannels);
209  for (int i = 0; i < nOpChannels; ++i) {
210  photonLiteCollection[i].OpChannel = i;
211  photonCollection[i].fOpChannel = i;
212  }
213  vector<vector<sim::SimEnergyDeposit> const*> edep_vecs;
214  for (auto label : fEDepTags) {
215  auto const& edep_handle = e.getValidHandle<vector<sim::SimEnergyDeposit>>(label);
216  edep_vecs.push_back(edep_handle);
217  }
218  for (auto const& edeps : edep_vecs) { //loop over modules
219  for (auto const& edep : *edeps) { //loop over energy deposits: one per step
220  //int count_onePhot =0; // unused
221  double const xyz[3] = {edep.X(), edep.Y(), edep.Z()};
222  float const* Visibilities = pvs->GetAllVisibilities(xyz);
223  if (Visibilities == nullptr) {
224  throw cet::exception("PhotonLibraryPropagation")
225  << "There is no entry in the PhotonLibrary for this position in space. "
226  "Position x: "<< xyz[0] << "y: " << xyz[1] << "z: " << xyz[2];
227  }
228  fISAlg.Reset();
230  //total amount of scintillation photons
231  double nphot = static_cast<int>(fISAlg.NumberScintillationPhotons());
232  //amount of scintillated photons created via the fast scintillation process
233  double nphot_fast = static_cast<int>(GetScintYield(edep, *larp) * nphot);
234  //amount of scintillated photons created via the slow scintillation process
235  double nphot_slow = nphot - nphot_fast;
236  for (int channel = 0; channel < nOpChannels; ++channel) {
237  auto visibleFraction = Visibilities[channel];
238  if (visibleFraction == 0.0) {
239  // Voxel is not visible at this optical channel, skip doing anything for this channel.
240  continue;
241  }
242  if (lgp->UseLitePhotons()) {
243  if (nphot_fast > 0) {
244  //throwing a random number from a poisson distribution with a mean of the amount of photons visible at this channel
245  auto n = static_cast<int>(randpoisphot.fire(nphot_fast * visibleFraction));
246  for (long i = 0; i < n; ++i) {
247  //calculates the time at which the photon was produced
248  auto time = static_cast<int>(edep.T0() + GetScintTime(fRiseTimeFast, larp->ScintFastTimeConst(), randflatscinttime));
249  ++photonLiteCollection[channel].DetectedPhotons[time];
250  }
251  }
252  if ((nphot_slow > 0) && fDoSlowComponent) {
253  //throwing a random number from a poisson distribution with a mean of the amount of photons visible at this channel
254  auto n = randpoisphot.fire(nphot_slow * visibleFraction);
255  for (long i = 0; i < n; ++i) {
256  //calculates the time at which the photon was produced
257  auto time = static_cast<int>(edep.T0() + GetScintTime(fRiseTimeSlow, larp->ScintSlowTimeConst(), randflatscinttime));
258  ++photonLiteCollection[channel].DetectedPhotons[time];
259  }
260  }
261  }
262  else {
263  sim::OnePhoton photon;
264  photon.SetInSD = false;
265  photon.InitialPosition = TVector3{edep.X(), edep.Y(), edep.Z()};
266  photon.Energy = 9.7e-6;
267  if (nphot_fast > 0) {
268  //throwing a random number from a poisson distribution with a mean of the amount of photons visible at this channel
269  auto n = randpoisphot.fire(nphot_fast * visibleFraction);
270  if (n > 0) {
271  //calculates the time at which the photon was produced
272  photon.Time = edep.T0() + 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 = edep.T0() + GetScintTime(fRiseTimeSlow, larp->ScintSlowTimeConst(), randflatscinttime);
283  // add n copies of sim::OnePhoton photon to the photon collection for a given OpChannel
284  photonCollection[channel].insert(photonCollection[channel].end(), n, photon);
285  }
286  }
287  }
288  }
289  }
290  }
291  if (lgp->UseLitePhotons()) {
292  // put the photon collection of LitePhotons into the art event
293  e.put(move(photLiteCol));
294  }
295  else {
296  //put the photon collection of SimPhotons into the art event
297  e.put(move(photCol));
298  }
299 }
300 
301 } // namespace phot
302 
virtual double ElectronScintYieldRatio() const =0
Store parameters for running LArG4.
virtual double ScintYieldRatio() const =0
void Initialize(const detinfo::LArProperties *larp, const detinfo::DetectorProperties *detp, const sim::LArG4Parameters *lgp, const spacecharge::SpaceCharge *sce)
void CalculateIonizationAndScintillation(sim::SimEnergyDeposit const &edep)
geo::Length_t Y() const
virtual double AlphaScintYieldRatio() const =0
virtual double ScintSlowTimeConst() const =0
virtual double ScintFastTimeConst() const =0
STL namespace.
virtual double ProtonScintYieldRatio() const =0
ProductID put(std::unique_ptr< PROD > &&product)
Definition: Event.h:102
geo::Length_t Z() const
double NumberScintillationPhotons() const
virtual double PionScintYieldRatio() const =0
contains objects relating to OpDet hits
base_engine_t & createEngine(seed_t seed)
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:42
T get(std::string const &key) const
Definition: ParameterSet.h:231
Float_t d
Definition: plot.C:237
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.
TVector3 InitialPosition
Definition: SimPhotons.h:49
static art::ServiceHandle< art::RandomNumberGenerator > & rng()
contains information for a single step in the detector simulation
virtual double MuonScintYieldRatio() const =0
Char_t n[5]
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
virtual double KaonScintYieldRatio() const =0
Float_t e
Definition: plot.C:34
virtual bool ScintByParticleType() const =0
geo::Length_t X() const
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
bool UseLitePhotons() const