All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PDFastSimPVS_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: PDFastSimPVS
3 // Plugin Type: producer
4 // File: PDFastSimPVS_module.cc
5 // Description:
6 // - acts on sim::SimEnergyDeposit from LArG4Main,
7 // - simulate (fast, photon visibility service) the OpDet response to optical photons
8 // Input: 'sim::SimEnergyDeposit'
9 // Output: 'sim::OpDetBacktrackerRecord'
10 //Fast simulation of propagating the photons created from SimEnergyDeposits.
11 
12 //This module does a fast simulation of propagating the photons created from SimEnergyDeposits,
13 //This simulation is done using the PhotonLibrary, which stores the visibilities of each optical channel
14 //with respect to each optical voxel in the TPC volume, to avoid propagating single photons using Geant4.
15 //At 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 'sim::SimEnergyDeposits',
20 // - use the PhotonLibrary (visibilities) to determine the amount of visible photons at each optical channel,
21 // - visible photons: the number of photons times the visibility at the middle of the Geant4 step for a given optical channel.
22 // - other photon information is got from 'sim::SimEnergyDeposits'
23 // - add 'sim::OpDetBacktrackerRecord' to event
24 // Aug. 19 by Mu Wei
25 // Restructured Nov. 21 by P. Green
26 ////////////////////////////////////////////////////////////////////////
27 
28 // LArSoft libraries
37 
38 #include "nurandom/RandomUtils/NuRandomService.h"
39 
40 // Art libraries
41 #include "art/Framework/Core/EDProducer.h"
42 #include "art/Framework/Core/ModuleMacros.h"
43 #include "art/Framework/Principal/Event.h"
44 #include "art/Framework/Principal/Handle.h"
45 #include "art/Framework/Services/Registry/ServiceHandle.h"
46 #include "art/Utilities/make_tool.h"
47 #include "canvas/Utilities/Exception.h"
48 #include "canvas/Utilities/InputTag.h"
49 #include "messagefacility/MessageLogger/MessageLogger.h"
50 #include "fhiclcpp/ParameterSet.h"
51 
52 #include "CLHEP/Random/RandPoissonQ.h"
53 #include "CLHEP/Units/SystemOfUnits.h"
54 
55 #include <iostream>
56 #include <memory>
57 #include <utility>
58 #include <vector>
59 
60 namespace phot
61 {
62  class PDFastSimPVS : public art::EDProducer
63  {
64  public:
65  explicit PDFastSimPVS(fhicl::ParameterSet const&);
66  void produce(art::Event&) override;
67  void AddOpDetBTR(std::vector< sim::OpDetBacktrackerRecord > & opbtr,
68  std::vector<int> & ChannelMap,
69  const sim::OpDetBacktrackerRecord & btr) const;
70 
71  private:
72  art::ServiceHandle<PhotonVisibilityService const> fPVS;
73  const bool fDoFastComponent;
74  const bool fDoSlowComponent;
75  const bool fIncludePropTime;
76  const bool fUseLitePhotons;
77  const bool fStoreReflected;
78  const size_t fNOpChannels;
79  const art::InputTag simTag;
80  CLHEP::HepRandomEngine& fScintTimeEngine;
81  std::unique_ptr<ScintTime> fScintTime; // Tool to retrive timing of scintillation
82  CLHEP::HepRandomEngine& fPhotonEngine;
83  std::unique_ptr<CLHEP::RandPoissonQ> fRandPoissPhot;
84 
85  std::unique_ptr<PropagationTimeModel> fPropTimeModel;
86 
87  fhicl::ParameterSet fVUVTimingParams;
88  fhicl::ParameterSet fVISTimingParams;
89  };
90 
91  //......................................................................
92  PDFastSimPVS::PDFastSimPVS(fhicl::ParameterSet const& pset)
93  : art::EDProducer{pset}
94  , fPVS(art::ServiceHandle<PhotonVisibilityService const>())
95  , fDoFastComponent(pset.get<bool>("DoFastComponent", true))
96  , fDoSlowComponent(pset.get<bool>("DoSlowComponent", true))
97  , fIncludePropTime(pset.get<bool>("IncludePropTime", false))
98  , fUseLitePhotons(art::ServiceHandle<sim::LArG4Parameters const>()->UseLitePhotons())
99  , fStoreReflected(fPVS->StoreReflected())
100  , fNOpChannels(fPVS->NOpChannels())
101  , simTag{pset.get<art::InputTag>("SimulationLabel")}
102  , fScintTimeEngine(art::ServiceHandle<rndm::NuRandomService>()->createEngine(*this, "HepJamesRandom", "scinttime", pset, "SeedScintTime"))
103  , fScintTime{art::make_tool<phot::ScintTime>(pset.get<fhicl::ParameterSet>("ScintTimeTool"))}
104  , fPhotonEngine(art::ServiceHandle<rndm::NuRandomService>{}->createEngine(*this, "HepJamesRandom", "photon", pset, "SeedPhoton"))
105  , fRandPoissPhot(std::make_unique<CLHEP::RandPoissonQ>(fPhotonEngine))
106  {
107  mf::LogInfo("PDFastSimPVS") << "PDFastSimPVS Module Construct";
108 
109  if (fUseLitePhotons) {
110  mf::LogInfo("PDFastSimPVS") << "Use Lite Photon." << std::endl;
111  produces< std::vector<sim::SimPhotonsLite> >();
112  produces< std::vector<sim::OpDetBacktrackerRecord> >();
113 
114  if(fStoreReflected) {
115  mf::LogInfo("PDFastSimPVS") << "Store Reflected Photons";
116  produces< std::vector<sim::SimPhotonsLite> >("Reflected");
117  produces< std::vector<sim::OpDetBacktrackerRecord> >("Reflected");
118  }
119  }
120  else {
121  mf::LogInfo("PDFastSimPVS") << "Use Sim Photon.";
122  produces< std::vector<sim::SimPhotons> >();
123  if(fStoreReflected)
124  {
125  mf::LogInfo("PDFastSimPVS") << "Store Reflected Photons";
126  produces< std::vector<sim::SimPhotons> >("Reflected");
127  }
128  }
129 
130  // Propagation times
131  // validate configuration
132  if(fIncludePropTime &&
133  !pset.get_if_present<fhicl::ParameterSet>("VUVTiming", fVUVTimingParams)) {
134  throw art::Exception(art::errors::Configuration)
135  << "Propagation time simulation requested, but VUVTiming not specified." << "\n";
136  }
137 
138  if (fIncludePropTime && fStoreReflected &&
139  !pset.get_if_present<fhicl::ParameterSet>("VISTiming", fVISTimingParams)) {
140  throw art::Exception(art::errors::Configuration)
141  << "Reflected light propagation time simulation requested, but VISTiming not specified." << "\n";
142  }
143 
144  // construct propagation time class
145  if (fIncludePropTime) fPropTimeModel = std::make_unique<PropagationTimeModel>(fVUVTimingParams, fVISTimingParams, fScintTimeEngine, fStoreReflected);
146  }
147 
148  //......................................................................
149  void PDFastSimPVS::produce(art::Event& event)
150  {
151  std::vector<int> PDChannelToSOCMapDirect(fNOpChannels, -1); // Where each OpChan is.
152  std::vector<int> PDChannelToSOCMapReflect(fNOpChannels, -1); // Where each OpChan is.
153 
154  // SimPhotonsLite
155  auto phlit = std::make_unique<std::vector<sim::SimPhotonsLite>>();
156  auto opbtr = std::make_unique<std::vector<sim::OpDetBacktrackerRecord>>();
157  auto phlit_ref = std::make_unique<std::vector<sim::SimPhotonsLite>>();
158  auto opbtr_ref = std::make_unique<std::vector<sim::OpDetBacktrackerRecord>>();
159  auto& dir_phlitcol(*phlit);
160  auto& ref_phlitcol(*phlit_ref);
161  // SimPhotons
162  auto phot = std::make_unique<std::vector<sim::SimPhotons>>();
163  auto phot_ref = std::make_unique<std::vector<sim::SimPhotons>>();
164  auto& dir_photcol(*phot);
165  auto& ref_photcol(*phot_ref);
166  if(fUseLitePhotons){
167  dir_phlitcol.resize(fNOpChannels);
168  ref_phlitcol.resize(fNOpChannels);
169  for (unsigned int i = 0; i < fNOpChannels; i ++) {
170  dir_phlitcol[i].OpChannel = i;
171  ref_phlitcol[i].OpChannel = i;
172  }
173  }
174  else{ // SimPhotons
175  dir_photcol.resize(fNOpChannels);
176  ref_photcol.resize(fNOpChannels);
177  for (unsigned int i = 0; i < fNOpChannels; i ++) {
178  dir_photcol[i].fOpChannel = i;
179  ref_photcol[i].fOpChannel = i;
180  }
181  }
182 
183  art::Handle< std::vector<sim::SimEnergyDeposit> > edepHandle;
184  if (!event.getByLabel(simTag, edepHandle)) {
185  mf::LogWarning("PDFastSimPVS") << "PDFastSimPVS Module Cannot getByLabel: " << simTag;
186  return;
187  }
188 
189  int num_points = 0;
190  auto const& edeps = edepHandle;
191  for (auto const& edepi: *edeps) {
192  num_points ++;
193 
194  int nphot_fast = edepi.NumFPhotons();
195  int nphot_slow = edepi.NumSPhotons();
196  if(!((nphot_fast > 0 && fDoFastComponent) ||
197  (nphot_slow > 0 && fDoSlowComponent))) continue;
198 
199  auto const& prt = edepi.MidPoint();
200 
201  MappedCounts_t Visibilities = fPVS->GetAllVisibilities(prt);
202  MappedCounts_t Visibilities_Ref;
203  if(fStoreReflected) {
204  Visibilities_Ref = fPVS->GetAllVisibilities(prt, true);
205  if(!Visibilities_Ref) mf::LogWarning("PDFastSimPVS") << "Fail to get visibilities for reflected photons.";
206  }
207 
208  if(!Visibilities) {
209  //throw cet::exception("PDFastSimPVS")
210  mf::LogWarning("PDFastSimPVS")
211  << "There is no entry in the PhotonLibrary for this position in space. Position: " << edepi.MidPoint()
212  << "\n Move to next point";
213  continue;
214  }
215 
216  int trackID = edepi.TrackID();
217  int nphot = edepi.NumPhotons();
218  double edeposit = edepi.Energy()/nphot;
219  double pos[3] = {edepi.MidPointX(), edepi.MidPointY(), edepi.MidPointZ()};
220 
221  geo::Point_t const ScintPoint = {pos[0], pos[1], pos[2]};
222 
223  // loop through direct photons then reflected photons cases
224  size_t DoReflected = (fStoreReflected) ? 1 : 0;
225  for (size_t Reflected = 0; Reflected <= DoReflected; ++Reflected) {
226  for (unsigned int channel = 0; channel < fNOpChannels; ++ channel) {
227 
228  double visibleFraction = (Reflected) ? Visibilities_Ref[channel] : Visibilities[channel];
229  if (visibleFraction < 1e-9) continue; // voxel is not visible at this optical channel
230 
231  // number of detected photons
232  int ndetected_fast = (nphot_fast > 0) ? fRandPoissPhot->fire(nphot_fast * visibleFraction) : 0;
233  int ndetected_slow = (nphot_slow > 0) ? fRandPoissPhot->fire(nphot_slow * visibleFraction) : 0;
234  if(!((ndetected_fast > 0 && fDoFastComponent) ||
235  (ndetected_slow > 0 && fDoSlowComponent))) continue;
236 
237  // calculate propagation times if included, does not matter whether fast or slow photon
238  std::vector<double> transport_time;
239  if (fIncludePropTime) {
240  transport_time.resize(ndetected_fast + ndetected_slow);
241  fPropTimeModel->propagationTime(transport_time, ScintPoint, channel, Reflected);
242  }
243 
244  // SimPhotonsLite case
245  if (fUseLitePhotons) {
246  sim::OpDetBacktrackerRecord tmpbtr(channel);
247  if (ndetected_fast > 0 && fDoFastComponent) {
248  for (int i = 0; i < ndetected_fast; ++i) {
249  // calculate the time at which each photon is seen
250  fScintTime->GenScintTime(true, fScintTimeEngine);
251  int time;
252  if (fIncludePropTime) time = static_cast<int>(edepi.StartT() + fScintTime->GetScintTime() + transport_time[i]);
253  else time = static_cast<int>(edepi.StartT() + fScintTime->GetScintTime());
254  if (Reflected) ++ref_phlitcol[channel].DetectedPhotons[time];
255  else ++dir_phlitcol[channel].DetectedPhotons[time];
256  tmpbtr.AddScintillationPhotons(trackID, time, 1, pos, edeposit);
257  }
258  }
259  if ((ndetected_slow > 0) && fDoSlowComponent) {
260  for (int i = 0; i < ndetected_slow; ++i) {
261  // calculate the time at which each photon is seen
262  fScintTime->GenScintTime(false, fScintTimeEngine);
263  int time;
264  if (fIncludePropTime) time = static_cast<int>(edepi.StartT() + fScintTime->GetScintTime() + transport_time[ndetected_fast + i]);
265  else time = static_cast<int>(edepi.StartT() + fScintTime->GetScintTime());
266  if (Reflected) ++ref_phlitcol[channel].DetectedPhotons[time];
267  else ++dir_phlitcol[channel].DetectedPhotons[time];
268  tmpbtr.AddScintillationPhotons(trackID, time, 1, pos, edeposit);
269  }
270  }
271  if (Reflected) AddOpDetBTR(*opbtr_ref, PDChannelToSOCMapReflect, tmpbtr);
272  else AddOpDetBTR(*opbtr, PDChannelToSOCMapDirect, tmpbtr);
273  }
274 
275  // SimPhotons case
276  else {
278  photon.SetInSD = false;
279  photon.InitialPosition = edepi.End();
280  if (Reflected) photon.Energy = 2.9 * CLHEP::eV; // 430 nm
281  else photon.Energy = 9.7 * CLHEP::eV; // 128 nm
282  if (ndetected_fast > 0 && fDoFastComponent) {
283  for (int i = 0; i < ndetected_fast; ++i) {
284  // calculates the time at which the photon was produced
285  fScintTime->GenScintTime(true, fScintTimeEngine);
286  int time;
287  if (fIncludePropTime) time = static_cast<int>(edepi.StartT() + fScintTime->GetScintTime() + transport_time[i]);
288  else time = static_cast<int>(edepi.StartT() + fScintTime->GetScintTime());
289  photon.Time = time;
290  if(Reflected) ref_photcol[channel].insert(ref_photcol[channel].end(), 1, photon);
291  else dir_photcol[channel].insert(dir_photcol[channel].end(), 1, photon);
292  }
293  }
294  if (ndetected_slow > 0 && fDoSlowComponent) {
295  for (int i = 0; i < ndetected_slow; ++i) {
296  fScintTime->GenScintTime(false, fScintTimeEngine);
297  int time;
298  if (fIncludePropTime) time = static_cast<int>(edepi.StartT() + fScintTime->GetScintTime() + transport_time[ndetected_fast + i]);
299  else time = static_cast<int>(edepi.StartT() + fScintTime->GetScintTime());
300  photon.Time = time;
301  if(Reflected) ref_photcol[channel].insert(ref_photcol[channel].end(), 1, photon);
302  else dir_photcol[channel].insert(dir_photcol[channel].end(), 1, photon);
303  }
304  }
305  }
306  }
307  }
308  }
309 
310  if (fUseLitePhotons) {
311  event.put(move(phlit));
312  event.put(move(opbtr));
313  if (fStoreReflected) {
314  event.put(move(phlit_ref), "Reflected");
315  event.put(move(opbtr_ref), "Reflected");
316  }
317  }
318  else {
319  event.put(move(phot));
320  if (fStoreReflected) {
321  event.put(move(phot_ref), "Reflected");
322  }
323  }
324 
325  return;
326  }
327 
328  //......................................................................
329  void PDFastSimPVS::AddOpDetBTR(std::vector< sim::OpDetBacktrackerRecord > & opbtr,
330  std::vector<int> & ChannelMap,
331  const sim::OpDetBacktrackerRecord & btr) const
332  {
333  int iChan = btr.OpDetNum();
334  if (ChannelMap[iChan] < 0) {
335  ChannelMap[iChan] = opbtr.size();
336  opbtr.emplace_back(std::move(btr));
337  }
338  else {
339  size_t idtest = ChannelMap[iChan];
340  auto const& timePDclockSDPsMap = btr.timePDclockSDPsMap();
341  for(auto const& timePDclockSDP : timePDclockSDPsMap) {
342  for(auto const& sdp : timePDclockSDP.second) {
343  double xyz[3] = {sdp.x, sdp.y, sdp.z};
344  opbtr.at(idtest).AddScintillationPhotons(sdp.trackID,
345  timePDclockSDP.first,
346  sdp.numPhotons,
347  xyz,
348  sdp.energy);
349  }
350  }
351  }
352  }
353 
354 } // namespace
355 
356 DEFINE_ART_MODULE(phot::PDFastSimPVS)
Store parameters for running LArG4.
process_name can override from command line with o or output photon
Definition: runPID.fcl:28
CLHEP::HepRandomEngine & fPhotonEngine
std::unique_ptr< ScintTime > fScintTime
void AddOpDetBTR(std::vector< sim::OpDetBacktrackerRecord > &opbtr, std::vector< int > &ChannelMap, const sim::OpDetBacktrackerRecord &btr) const
art::ServiceHandle< PhotonVisibilityService const > fPVS
All information of a photon entering the sensitive optical detector volume.
Definition: SimPhotons.h:64
std::unique_ptr< CLHEP::RandPoissonQ > fRandPoissPhot
fhicl::ParameterSet fVISTimingParams
Energy deposited on a readout Optical Detector by simulated tracks.
geo::Point_t InitialPosition
Scintillation position in world coordinates [cm].
Definition: SimPhotons.h:67
Simulation objects for optical detectors.
int OpDetNum() const
Returns the readout Optical Detector this object describes.
createEngine fRandPoissPhot(std::make_unique< CLHEP::RandPoissonQ >(fPhotonEngine))
fhicl::ParameterSet fVUVTimingParams
PDFastSimPVS(fhicl::ParameterSet const &)
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
void AddScintillationPhotons(TrackID_t trackID, timePDclock_t timePDclock, double numberPhotons, double const *xyz, double energy)
Add scintillation photons and energy to this OpticalDetector.
const art::InputTag simTag
A container for photon visibility mapping data.
bool SetInSD
Whether the photon reaches the sensitive detector.
Definition: SimPhotons.h:88
contains information for a single step in the detector simulation
do i e
float Energy
Scintillation photon energy [GeV].
Definition: SimPhotons.h:82
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
std::unique_ptr< PropagationTimeModel > fPropTimeModel
void produce(art::Event &) override
timePDclockSDPs_t const & timePDclockSDPsMap() const
Returns all the deposited energy information as stored.
CLHEP::HepRandomEngine & fScintTimeEngine
services LArG4Parameters UseLitePhotons
createEngine fScintTimeEngine(art::ServiceHandle< rndm::NuRandomService >() ->createEngine(*this,"HepJamesRandom","scinttime", p,"SeedScintTime"))