LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
OpMCDigi_module.cc
Go to the documentation of this file.
1 // \file OpMCDigi.h
2 // \author Ben Jones and Christie Chiu, MIT, Sept 2012
3 // bjpjones@mit.edu, cschiu@mit.edu
4 //
5 // This module starts from MC truth sim::OnePhoton objects
6 // and produces a digitized waveform.
7 //
8 // It is assumed that the electronics response is linear,
9 // and the 1PE waveform can be described by a discreate
10 // response shape. The many PE response is then the linear
11 // superposition of the relevant function at the appropriate
12 // arrival times.
13 //
14 
15 
19 //#include "Geometry/Geometry.h"
22 
23 
24 #include "CLHEP/Random/RandFlat.h"
25 #include "CLHEP/Random/RandGaussQ.h"
26 #include "CLHEP/Random/RandPoisson.h"
27 
28 
29 // ROOT includes.
30 #include <Rtypes.h>
31 #ifndef OpMCDigi_h
32 #define OpMCDigi_h 1
33 
34 
35 
36 namespace opdet {
37 
38  class OpMCDigi : public art::EDProducer{
39  public:
40 
42  virtual ~OpMCDigi();
43 
44  void produce(art::Event&);
45 
46  void beginJob();
47 
48 
49  private:
50 
51  // The parameters we'll read from the .fcl file.
52  std::string fInputModule; // Input tag for OpDet collection
53  float fSampleFreq; // in MHz
54  float fTimeBegin; // in us
55  float fTimeEnd; // in us
56  //float fQE; // quantum efficiency of opdet
57  float fSaturationScale; // adc count w/ saturation occurs
58 
59  float fDarkRate; // Noise rate in Hz
60 
61  std::vector<double> fSinglePEWaveform;
62 
63  CLHEP::RandFlat * fFlatRandom;
64  CLHEP::RandPoisson * fPoissonRandom;
65 
66 
67 
68  void AddTimedWaveform (int time, std::vector<double>& OldPulse, std::vector<double>& NewPulse);
69 
70  };
71 }
72 
73 #endif
74 
75 
76 
82 // Framework includes
84 
85 namespace opdet{
86 
88 
89 }//end namespace opdet
91 
92 // \file OpMCDigi.cxx
93 // \author Ben Jones and Christie Chiu, MIT 2010
94 //
95 //
96 
97 // FMWK includes
99 #include "fhiclcpp/ParameterSet.h"
107 
108 // art extensions
110 
111 // LArSoft includes
116 
117 // ROOT includes
118 #include <TH1D.h>
119 #include <TF1.h>
120 #include <TTree.h>
121 #include <TRandom.h>
122 
123 // C++ language includes
124 #include <iostream>
125 #include <sstream>
126 #include <cstring>
127 #include <vector>
128 
129 
130 // Debug flag; only used during code development.
131 // const bool debug = true;
132 
133 namespace opdet {
134 
135 
137  {
138  // Infrastructure piece
139  produces<std::vector< raw::OpDetPulse> >();
140 
141 
142  // Input Module and histogram parameters come from .fcl
143  fInputModule = pset.get<std::string>("InputModule");
144 
146  fTimeBegin = odp->TimeBegin();
147  fTimeEnd = odp->TimeEnd();
148  fSampleFreq = odp->SampleFreq();
149 
150  //fQE = pset.get<double>("QE");
151  fDarkRate = pset.get<double>("DarkRate");
152  fSaturationScale = pset.get<double>("SaturationScale");
153 
154  // Initialize toy waveform vector fSinglePEWaveform
155  fSinglePEWaveform = odp->SinglePEWaveform();
156 
157 
158 
159  // create a default random engine; obtain the random seed from NuRandomService,
160  // unless overridden in configuration with key "Seed"
162  ->createEngine(*this, pset, "Seed");
163 
164  // Sample a random fraction of detected photons
166  CLHEP::HepRandomEngine &engine = rng->getEngine();
167  fFlatRandom = new CLHEP::RandFlat(engine);
168  fPoissonRandom = new CLHEP::RandPoisson(rng->getEngine());
169 
170 
171 
172 
173  }
174 
175  //-------------------------------------------------
176 
177 
179  {
180  }
181 
182 
183  //-------------------------------------------------
184 
186  {
187  }
188 
189 
190  //-------------------------------------------------
191 
192 
193  void OpMCDigi::AddTimedWaveform (int binTime, std::vector<double>& OldPulse, std::vector<double>& NewPulse)
194  {
195 
196  if( (binTime + NewPulse.size() ) > OldPulse.size())
197  OldPulse.resize(binTime + NewPulse.size());
198 
199  // Add shifted NewWaveform to Waveform at pointer
200  for(size_t i = 0; i!=NewPulse.size(); ++i)
201  {
202  OldPulse.at(binTime+i) += NewPulse.at(i);
203  }
204  }
205 
206 
207 
208 
209  //-------------------------------------------------
210 
212  {
213  // Infrastructure piece
214  std::unique_ptr<std::vector< raw::OpDetPulse > > StoragePtr (new std::vector<raw::OpDetPulse>);
215 
216 
218  bool fUseLitePhotons = lgp->UseLitePhotons();
219 
220  // Service for determining opdet responses
222 
223 
224 
225  double TimeBegin_ns = fTimeBegin * 1000;
226  double TimeEnd_ns = fTimeEnd * 1000;
227  double SampleFreq_ns = fSampleFreq / 1000;
228 
229  int nSamples = ( TimeEnd_ns-TimeBegin_ns)*SampleFreq_ns;
230 
231  int NOpChannels = odresponse->NOpChannels();
232 
233 
234  // This vector will store all the waveforms we will make
235  std::vector<std::vector<double> > PulsesFromDetPhotons(NOpChannels,std::vector<double>(nSamples,0.0));
236 
237  if(!fUseLitePhotons)
238  {
239  // Read in the Sim Photons
241  // For every OpDet:
242  for(sim::SimPhotonsCollection::const_iterator itOpDet=ThePhotCollection.begin(); itOpDet!=ThePhotCollection.end(); itOpDet++)
243  {
244  const sim::SimPhotons& ThePhot=itOpDet->second;
245 
246  int Ch = ThePhot.OpChannel();
247  int readoutCh;
248 
249  // For every photon in the hit:
250  for(const sim::OnePhoton& Phot: ThePhot)
251  {
252  // Sample a random subset according to QE
253  if(odresponse->detected(Ch, Phot, readoutCh))
254  {
255 
256  // Convert photon arrival time to the appropriate bin, dictated by fSampleFreq. Photon arrival time is in ns, beginning time in us, and sample frequency in MHz. Notice that we have to accommodate for the beginning time
257  if((Phot.Time > TimeBegin_ns) && (Phot.Time < TimeEnd_ns))
258  {
259  int binTime = int((Phot.Time - TimeBegin_ns) * SampleFreq_ns);
260 
261  // Call function to add waveforms to our pulse
262  AddTimedWaveform( binTime, PulsesFromDetPhotons[readoutCh], fSinglePEWaveform );
263 
264  }
265  } // random QE cut
266  } // for each Photon in SimPhotons
267 
268  }
269  }
270  else
271  {
273  evt.getByLabel("largeant", photonHandle);
274  // For every OpDet:
275  for ( auto const& photon : (*photonHandle) )
276  {
277  int Ch=photon.OpChannel;
278  int readoutCh;
279 
280  std::map<int, int> PhotonsMap = photon.DetectedPhotons;
281 
282  // For every photon in the hit:
283  for(auto it = PhotonsMap.begin(); it!= PhotonsMap.end(); it++)
284  {
285  for(int i = 0; i < it->second; i++)
286  {
287  // Sample a random subset according to QE
288  if(odresponse->detectedLite(Ch, readoutCh))
289  {
290  // Convert photon arrival time to the appropriate bin, dictated by fSampleFreq.
291  // Photon arrival time is in ns, beginning time in us, and sample frequency in MHz.
292  // Notice that we have to accommodate for the beginning time
293  if((it->first > TimeBegin_ns) && (it->first < TimeEnd_ns))
294  {
295  int binTime = int((it->first - TimeBegin_ns) * SampleFreq_ns);
296 
297  // Call function to add waveforms to our pulse
298  AddTimedWaveform( binTime, PulsesFromDetPhotons[readoutCh], fSinglePEWaveform );
299  }
300  } // random QE cut
301  }
302  } // for each Photon in SimPhotons
303  }
304  }
305 
307 
308 
309  // Create vector of output objects, add dark noise and apply
310  // saturation
311 
312  std::vector<raw::OpDetPulse*> ThePulses(NOpChannels);
313  for(int iCh=0; iCh!=NOpChannels; ++iCh)
314  {
315  PulsesFromDetPhotons[iCh].resize((TimeEnd_ns - TimeBegin_ns) * SampleFreq_ns);
316 
317  // Add dark noise
318  double MeanDarkPulses = fDarkRate * (fTimeEnd-fTimeBegin) / 1000000;
319 
320  unsigned int NumberOfPulses = fPoissonRandom->fire(MeanDarkPulses);
321 
322  for(size_t i=0; i!=NumberOfPulses; ++i)
323  {
324  double PulseTime = (fTimeEnd-fTimeBegin)*fFlatRandom->fire(1.0);
325  int binTime = int(PulseTime * fSampleFreq);
326 
327  AddTimedWaveform( binTime, PulsesFromDetPhotons[iCh], fSinglePEWaveform );
328  }
329 
330  // Apply saturation for large signals
331  for(size_t i=0; i!=PulsesFromDetPhotons[iCh].size(); ++i)
332  {
333  if(PulsesFromDetPhotons[iCh].at(i)>fSaturationScale) PulsesFromDetPhotons[iCh].at(i) = fSaturationScale;
334  }
335 
336  // Produce ADC pulse of integers rather than doubles
337 
338  std::vector<short> shortvec;
339 
340  for(size_t i=0; i!=PulsesFromDetPhotons[iCh].size(); ++i)
341  {
342  // Throw randoms to fairly sample +ve and -ve side of doubles
343  int ThisSample = PulsesFromDetPhotons[iCh].at(i);
344  if(ThisSample>0)
345  {
346  if(fFlatRandom->fire(1.0) > (ThisSample - int(ThisSample)))
347  shortvec.push_back(int(ThisSample));
348  else
349  shortvec.push_back(int(ThisSample)+1);
350  }
351  else
352  {
353  if(fFlatRandom->fire(1.0) > (int(ThisSample)-ThisSample))
354  shortvec.push_back(int(ThisSample));
355  else
356  shortvec.push_back(int(ThisSample)-1);
357  }
358  }
359 
360 
361  StoragePtr->push_back( raw::OpDetPulse( iCh, shortvec ,0, fTimeBegin) );
362 
363  } // for each OpDet in SimPhotonsCollection
364 
365 
366  evt.put(std::move(StoragePtr));
367  }
368 }
369 
Store parameters for running LArG4.
CLHEP::RandFlat * fFlatRandom
int OpChannel() const
Definition: SimPhotons.h:161
void AddTimedWaveform(int time, std::vector< double > &OldPulse, std::vector< double > &NewPulse)
virtual bool detected(int OpChannel, const sim::OnePhoton &Phot, int &newOpChannel) const
OpMCDigi(const fhicl::ParameterSet &)
ProductID put(std::unique_ptr< PROD > &&product)
Definition: Event.h:102
base_engine_t & getEngine() const
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
void produce(art::Event &)
An art service to assist in the distribution of guaranteed unique seeds to all engines within an art ...
virtual bool detectedLite(int OpChannel, int &newOpChannel) const
std::string fInputModule
CLHEP::RandPoisson * fPoissonRandom
static art::ServiceHandle< art::RandomNumberGenerator > & rng()
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
Definition: DataViewImpl.h:344
std::vector< double > fSinglePEWaveform
list_type::const_iterator const_iterator
Definition: SimPhotons.h:134
TCEvent evt
Definition: DataStructs.cxx:5
Tools and modules for checking out the basics of the Monte Carlo.
static sim::SimPhotonsCollection GetSimPhotonsCollection(const art::Event &evt, std::string moduleLabel)
bool UseLitePhotons() const