PhotonLibraryPropagationS2_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: PhotonLibraryPropagationS2
3 // Plugin Type: producer (art v2_05_00)
4 // File: PhotonLibraryPropagationS2_module.cc
5 ////////////////////////////////////////////////////////////////////////
6 
14 #include "fhiclcpp/ParameterSet.h"
16 #include "nurandom/RandomUtils/NuRandomService.h"
17 
18 
19 #include <memory>
20 #include <iostream>
21 
22 // A GEANT4 include to make the macos debug build happy
23 // might need to move this include to larsim/LArG4/OpDetSensitiveDetector.h
24 // though the real issue is why just the mac build cannot find the
25 // symbols in it while other builds an
26 
27 #include "Geant4/G4VUserTrackInformation.hh"
28 
40 
41 #include "CLHEP/Random/RandFlat.h"
42 #include "CLHEP/Random/RandPoissonQ.h"
43 
48 
53 // ROOT Includes
54 #include "TGeoManager.h"
55 
56 namespace phot {
58 }
59 
60 
62 public:
64  // The compiler-generated destructor is fine for non-base
65  // classes without bare pointers or other resource use.
66 
67  // Plugins should not be copied or assigned.
72 
73 private:
74  // Required functions.
75  void produce(art::Event & e) override;
76 
77  void Print(std::map<int, std::map<int, int>>* StepPhotonTable);
78 
80 
82  double fGain;//Number of photons created per drifted electron.
83  CLHEP::HepRandomEngine& fPhotonEngine;
84  CLHEP::HepRandomEngine& fScintTimeEngine;
85 };
86 
87 
89  : EDProducer{p}
90  , fDriftEModuleLabel{p.get< std::string >("DriftEModuleLabel")}
91  , fGain{p.get<double>("Gain",500)}
92  , fPhotonEngine(art::ServiceHandle<rndm::NuRandomService>()->createEngine(*this, "HepJamesRandom", "photon", p, "SeedPhoton"))
93  , fScintTimeEngine(art::ServiceHandle<rndm::NuRandomService>()->createEngine(*this, "HepJamesRandom", "scinttime", p, "SeedScintTime"))
94 {
96 
98  if(fUseLitePhotons)
99  {
100  produces< std::vector<sim::OpDetBacktrackerRecord> >();
101  produces< std::vector<sim::SimPhotonsLite> >();
102  }
103  else produces< std::vector<sim::SimPhotons> >();
104 }
105 
106 
108 {
109 
110  mf::LogInfo("PhotonLibraryPropagationS2") << "Producing S2 photons."<<std::endl;
111 
112 
114 
115 
116  if (!pvs->IncludeParPropTime()) mf::LogInfo("PhotonLibraryPropagationS2") << "Parametrized Propagation Time is not set up for S2. The propagation of S2 light will be instantaneous."<<std::endl;
117 
119  // const detinfo::LArProperties* larp = lar::providerFrom<detinfo::LArPropertiesService>();
120 
121  CLHEP::RandPoissonQ randpoisphot(fPhotonEngine);
122  CLHEP::RandFlat randflatscinttime(fScintTimeEngine);
123 
124 
126 
127  // Get the pointer to the fast scintillation table
128  // larg4::OpDetPhotonTable * fst = larg4::OpDetPhotonTable::Instance();
130 
131  const size_t NOpChannels = pvs->NOpChannels();
132  double nphot;
133 
134 // std::unique_ptr< std::vector<sim::SimPhotons> > PhotonCol (new std::vector<sim::SimPhotons>);
135  std::unique_ptr< std::vector<sim::SimPhotonsLite> > LitePhotonCol (new std::vector<sim::SimPhotonsLite>);
136  std::unique_ptr< std::vector< sim::OpDetBacktrackerRecord > > cOpDetBacktrackerRecordCol (new std::vector<sim::OpDetBacktrackerRecord>);
137 
138  art::ValidHandle< std::vector<sim::SimDriftedElectronCluster> > ElectronClusters_handle = e.getValidHandle<std::vector<sim::SimDriftedElectronCluster>>(fDriftEModuleLabel);
139 
140  //std::cout << "... GETTING ELECTRON CLUSTER HANDLE"<<std::endl;
141 
142 
143  // int counter=0;
144 
145  if(fUseLitePhotons) mf::LogDebug("PhotonLibraryPropagationS2") << "Creating S2 photons as a SimPhotonsLite data product."<<std::endl;
146  else mf::LogError("PhotonLibraryPropagationS2") << "Error creating S2 light, SimPhotons data product is not supported."<<std::endl;
147 
148  int counter=0;
149 
150  for (sim::SimDriftedElectronCluster const& ElectronCluster: *ElectronClusters_handle)
151  {
152  //std::cout << "reading a cluster " << counter <<std::endl; //counter ++;
153  int detectedcounter=0;
154 
155  double const xyz[3] = { ElectronCluster.FinalPositionX(), ElectronCluster.FinalPositionY(), ElectronCluster.FinalPositionZ() };
156  float const* Visibilities = pvs->GetAllVisibilities(xyz);
157  if(!Visibilities)
158  continue;
159 
160  TF1 *ParPropTimeTF1 = nullptr;
161 
162  if(pvs->IncludeParPropTime())
163  {
164  ParPropTimeTF1 = pvs->GetTimingTF1(xyz);
165  }
166 
167  //std::cout <<"\tPosition> " <<ElectronCluster.FinalPositionX()<<" " << ElectronCluster.FinalPositionY()<<" " <<ElectronCluster.FinalPositionZ() <<std::endl;
168  //std::cout <<"\tTiming> " <<ElectronCluster.getTime()<<std::endl;
169  //std::cout <<"\tEnergy> " <<ElectronCluster.getEnergy()<<std::endl;
170  //std::cout <<"\telectrons> " <<ElectronCluster.getNumberOfElectrons()<<std::endl;
171  //std::cout <<"\tTrack> " <<ElectronCluster.getTrackID()<<std::endl;
172 
173  nphot =ElectronCluster.NumberOfElectrons()*fGain; // # photons generated in the Gas Ar phase
174  //mf::LogInfo("PhotonLibraryPropagationS2") << ElectronCluster.getNumberOfElectrons() <<" electron arrives."<< std::endl;
175  //mf::LogInfo("PhotonLibraryPropagationS2") << nphot <<" S2 photons have been created in " << ElectronCluster.FinalPositionX() << " " << ElectronCluster.FinalPositionY() << " "<< ElectronCluster.FinalPositionZ()<< " at time " << ElectronCluster.getTime() << std::endl;
176 
177  //std::cout << ElectronCluster.getNumberOfElectrons() << " electrons." << std::endl;
178 
179  if(!Visibilities)
180  {
181  }
182  else
183  {
184  //std::cout <<"\t\tVisibilities loaded. Let's calculate the number of detected photons. OpChannels: " <<NOpChannels<<std::endl;
185 
186  std::map<int, int> DetectedNum;
187 
188  for(size_t OpDet=0; OpDet!=NOpChannels; OpDet++)
189  {
190  G4int DetThisPMT = G4int(randpoisphot.fire(Visibilities[OpDet] * nphot));
191  //mf::LogDebug("PhotonLibraryPropagationS2") << DetThisPMT <<" photons arrive to OpChannel " << OpDet<<std::endl;
192  //std::cout <<"\t\tVisibilities loaded. Let's calculate the number of detected photons. OpChannels: " <<Visibilities[OpDet] << " "<< nphot << " " << Visibilities[OpDet] * nphot << std::endl;
193  if(DetThisPMT>0)
194  {
195  DetectedNum[OpDet]=DetThisPMT;
196  //std::cout <<"\t\t\t#photons per pmt"<<OpDet<<": "<<DetThisPMT<<std::endl;
197  }
198  }
199  // Now we run through each PMT figuring out num of detected photons
200  if(fUseLitePhotons)
201  {
202  //std::cout << "\t\tLet's create our StepPhotonTable Map." << std::endl;
203 
204  std::map<int, std::map<int, int>> StepPhotonTable;
205  // And then add these to the total collection for the event
206  Print(&StepPhotonTable);
207 
208  for(std::map<int,int>::const_iterator itdetphot = DetectedNum.begin();
209  itdetphot!=DetectedNum.end(); ++itdetphot)
210  {
211 
212  //std::cout << "... iterating! over " <<itdetphot->second <<" photons. "<< std::endl;
213  std::map<int, int> StepPhotons;
214 
215 /*
216  float maxarrivaltimerange=0.0;
217 
218  if(pvs->IncludeParPropTime()) maxarrivaltimerange+=static_cast<int>(10*PropParameters[itdetphot->first][0]);
219 
220  if(pvs->IncludeParPropTime()&&!pvs->IncludeMCParPropTime()&&itdetphot->second>50)
221  {
222 
223  G4double deltaTime = ElectronCluster.getTime();
224  //just normalizing the TF1 by the number of photons
225  double integral=0;
226  int ccounter=0;
227 
228  if(pvs->GetfParPropTime_nonanalyticalfunction())
229  {
230  for(size_t i=1; i<pvs->ParPropTimeNpar();i++)
231  {
232  ParPropTimeFunctionTF1->SetParameter(i, PropParameters[itdetphot->first][i]);
233  }
234  ParPropTimeFunctionTF1->SetRange(PropParameters[itdetphot->first][0],maxarrivaltimerange);
235 
236  integral=ParPropTimeFunctionTF1->Integral(PropParameters[itdetphot->first][0],PropParameters[itdetphot->first][0]+maxarrivaltimerange);
237  }
238  else
239  {
240  integral=pvs->GetParPropTimeFunctionIntegral(PropParameters[itdetphot->first],PropParameters[itdetphot->first][0]+maxarrivaltimerange);
241  }
242 
243  float leftovers=0;
244  for (int binnumber=0; binnumber < maxarrivaltimerange; binnumber++)
245  {
246  int ticks=static_cast<int> (deltaTime + binnumber);
247  if(pvs->GetfParPropTime_nonanalyticalfunction())
248  {
249  StepPhotons[ticks] = static_cast<int>(std::round(itdetphot->second*ParPropTimeFunctionTF1->Eval(binnumber+0.5+PropParameters[itdetphot->first][0])/integral));
250  leftovers+=itdetphot->second*ParPropTimeFunctionTF1->Eval(binnumber+0.5+PropParameters[itdetphot->first][0])/integral-StepPhotons[ticks];
251  }
252  else
253  {
254  StepPhotons[ticks] = static_cast<int>(std::round(itdetphot->second*ParPropTimeFunction(PropParameters[itdetphot->first],binnumber+0.5+PropParameters[itdetphot->first][0])/integral));
255  leftovers+=itdetphot->second*ParPropTimeFunction(PropParameters[itdetphot->first],binnumber+0.5+PropParameters[itdetphot->first][0])/integral-StepPhotons[ticks];
256  }
257  if (leftovers>1.0){leftovers--;StepPhotons[ticks]++;}
258  else if (leftovers<-1.0){leftovers++;StepPhotons[ticks]--;}
259  ccounter+=StepPhotons[ticks];
260 
261  }
262  //std::cout << "CHECK COUNTER!!! " << ccounter << " =? " << itdetphot->second << " if they are not equal we have problems!"<<std::endl;
263  //Print(&StepPhotonTable);
264 
265  }
266  else
267  {
268 */
269  for (G4int i = 0; i < itdetphot->second; ++i)
270  {
271  G4double deltaTime = ElectronCluster.Time();
272  //standard propagation time, montecarlo simulation photon per photon
273  if(pvs->IncludeParPropTime())
274  {
275  deltaTime += ParPropTimeTF1[itdetphot->first].GetRandom();
276  }
277  G4double aSecondaryTime = deltaTime;
278  float Time = aSecondaryTime;
279  int ticks = static_cast<int>(Time);
280  StepPhotons[ticks]++;detectedcounter++;
281  }
282  //std::cout <<"itdetphot->first " << itdetphot->first << std::endl;
283  //std::cout <<"ElectronCluster.getTrackID() " << ElectronCluster.getTrackID() <<", ElectronCluster.getEnergy()/CLHEP::MeV "<< ElectronCluster.getEnergy()/CLHEP::MeV<< std::endl;
284  StepPhotonTable[itdetphot->first] = StepPhotons;
285  //Iterate over Step Photon Table to add photons to OpDetBacktrackerRecords.
286 
287  sim::OpDetBacktrackerRecord tmpOpDetBTRecord(itdetphot->first);
288  //int thisG4TrackID = (aStep.GetTrack())->GetTrackID();
289  int thisG4TrackID = ElectronCluster.TrackID();
290  double xO = ( ElectronCluster.FinalPositionX() / CLHEP::cm );
291  double yO = ( ElectronCluster.FinalPositionY() / CLHEP::cm );
292  double zO = ( ElectronCluster.FinalPositionZ() / CLHEP::cm );
293  double const xyzPos[3] = {xO,yO,zO};
294  // double energy = ( aStep.GetTotalEnergyDeposit() / CLHEP::MeV );
295  double energy = ElectronCluster.Energy()/CLHEP::MeV;
296  //Loop over StepPhotons to get number of photons detected at each time for this channel and G4Step.
297 
298  for(std::map<int,int>::iterator stepPhotonsIt = StepPhotons.begin(); stepPhotonsIt != StepPhotons.end(); ++stepPhotonsIt)
299  {
300  int photonTime = stepPhotonsIt->first;
301  int numPhotons = stepPhotonsIt->second;
302  tmpOpDetBTRecord.AddScintillationPhotons(thisG4TrackID, photonTime, numPhotons, xyzPos, energy);
303  }
304  litefst->AddOpDetBacktrackerRecord(tmpOpDetBTRecord);
305  }//endloop per optdet
306  //Print(&StepPhotonTable);
307  litefst->AddPhoton(&StepPhotonTable);
308  }//endif litephotons
309  else
310  {
311  mf::LogError("PhotonLibraryPropagationS2") << "Error creating S2 light, SimPhotons data product is not supported."<<std::endl;
312  }
313  }//endif visibilities
314 
315  mf::LogInfo("PhotonLibraryPropagationS2") << counter <<" electron clusters processed. "<< ElectronCluster.NumberOfElectrons() <<" electron arrives. "<< nphot <<" S2 photons have been created in " << ElectronCluster.FinalPositionX() << " " << ElectronCluster.FinalPositionY() << " "<< ElectronCluster.FinalPositionZ()<< " at time " << ElectronCluster.Time() << std::endl;counter++;
316 
317 // OpDetSensitiveDetector *theOpDetDet = dynamic_cast<OpDetSensitiveDetector*>(sdManager->FindSensitiveDetector("OpDetSensitiveDetector"));
318 // if (OpDetSensitiveDetector)
319 // {
320 
321  }// endif electroncluster loop
322 
323  if(!fUseLitePhotons)
324  {
325  mf::LogError("PhotonLibraryPropagationS2") << "Error creating S2 light, SimPhotons data product is not supported."<<std::endl;
326  //std::cout << "SIMPHOTONS NOT SUPPORTED!!! "<< std::endl;
327  /*
328  MF_LOG_DEBUG("Optical") << "Storing OpDet Hit Collection in Event";
329  std::vector<sim::SimPhotons>& ThePhotons = larg4::OpDetPhotonTable::Instance()->GetPhotons();
330  PhotonCol->reserve(ThePhotons.size());
331  for(auto& it : ThePhotons)
332  PhotonCol->push_back(std::move(it));*/
333  }
334  else
335  {
336  mf::LogDebug("PhotonLibraryPropagationS2") << "Converting Photon Map in SimPhotonLite data product";
337  std::map<int, std::map<int, int> > ThePhotons = litefst->GetLitePhotons();
338  if(ThePhotons.size() > 0)
339  {
340  LitePhotonCol->reserve(ThePhotons.size());
341 
342  for(auto const& it : ThePhotons)
343  {
344 
346  ph.OpChannel = it.first;
347  ph.DetectedPhotons = it.second;
348  LitePhotonCol->push_back(ph);
349  //std::cout << "... \t" << it.first << std::endl;
350  }
351  }
352  //*cOpDetBacktrackerRecordCol = larg4::OpDetPhotonTable::Instance()->YieldOpDetBacktrackerRecords();
353  *cOpDetBacktrackerRecordCol = litefst->YieldOpDetBacktrackerRecords();
354  }
355 
356  if(!fUseLitePhotons)
357  {
358  mf::LogError("PhotonLibraryPropagationS2") << "Error creating S2 light, SimPhotons data product is not supported."<<std::endl;
359  //e.put(std::move(PhotonCol));
360  }
361  else
362  {
363  mf::LogDebug("PhotonLibraryPropagationS2") << "Storing S2 Photon Collection in event " ;
364  e.put(std::move(LitePhotonCol));
365  e.put(std::move(cOpDetBacktrackerRecordCol));
366  }
367 
368 }
369 
370 void phot::PhotonLibraryPropagationS2::Print(std::map<int, std::map<int, int>>* StepPhotonTable)
371 {
372  for(auto it = StepPhotonTable->begin(); it!=StepPhotonTable->end(); it++)
373  {
374  for(auto in_it = it->second.begin(); in_it!=it->second.end(); in_it++)
375  {
376  std::cout << in_it->second << " ";
377  }
378  std::cout << std::endl;
379  }
380 }
381 
382 
static constexpr double cm
Definition: Units.h:68
Definitions of voxel data structures.
intermediate_table::iterator iterator
Store parameters for running LArG4.
Encapsulate the construction of a single cyostat.
contains objects relating to SimDriftedElectronCluster
std::string string
Definition: nybbler.cc:12
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.h:20
PhotonLibraryPropagationS2 & operator=(PhotonLibraryPropagationS2 const &)=delete
void Print(std::map< int, std::map< int, int >> *StepPhotonTable)
intermediate_table::const_iterator const_iterator
static constexpr double MeV
Definition: Units.h:129
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
tick ticks
Alias for common language habits.
Definition: electronics.h:78
Energy deposited on a readout Optical Detector by simulated tracks.
art framework interface to geometry description
std::map< int, int > DetectedPhotons
Number of photons detected at each given time: time tick -> photons.
Definition: SimPhotons.h:117
Simulation objects for optical detectors.
const double e
void AddPhoton(size_t opchannel, sim::OnePhoton &&photon, bool Reflected=false)
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
PhotonLibraryPropagationS2(fhicl::ParameterSet const &p)
def move(depos, offset)
Definition: depos.py:107
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:441
int OpChannel
Optical detector channel associated to this data.
Definition: SimPhotons.h:114
p
Definition: test.py:223
void AddOpDetBacktrackerRecord(sim::OpDetBacktrackerRecord soc, bool Reflected=false)
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: DataViewImpl.h:686
unsigned int NOpDets() const
Number of OpDets in the whole detector.
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.
static OpDetPhotonTable * Instance(bool LitePhotons=false)
Index NOpChannels(Index)
General LArSoft Utilities.
Compact representation of photons on a channel.
Definition: SimPhotons.h:103
std::vector< sim::OpDetBacktrackerRecord > YieldOpDetBacktrackerRecords()
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
contains information for a single step in the detector simulation
std::map< int, std::map< int, int > > GetLitePhotons(bool Reflected=false)
void ClearTable(size_t nch=0)
bool UseLitePhotons() const
QTextStream & endl(QTextStream &s)