LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
OpDigiProperties_service.cc
Go to the documentation of this file.
1 //
3 // \file OpDigiProperties_service.cc
4 //
6 
7 // LArSoft includes
11 
12 // Framework includes
14 
15 // CLHEP includes
16 #include "CLHEP/Random/RandGaussQ.h"
17 
18 // C++ includes
19 #include <fstream>
20 
21 namespace opdet{
22 
23  //--------------------------------------------------------------------
25  art::ActivityRegistry &/*reg*/)
26  : fAnalyticalSPE(0)
27  {
28  this->reconfigure(pset);
29  }
30 
31  //--------------------------------------------------------------------
33  {
34 
35  }
36 
37 
38  //--------------------------------------------------------------------
40  {
41  double SPEArea=0;
42  for(size_t i=0; i!=fWaveform.size(); ++i)
43  SPEArea+=fWaveform.at(i);
44  return SPEArea;
45  }
46 
47  //--------------------------------------------------------------------
49  {
50  double AmpSoFar=0;
51  for(size_t i=0; i!=fWaveform.size(); ++i)
52  if(fWaveform.at(i)>AmpSoFar) AmpSoFar=fWaveform.at(i);
53  return AmpSoFar;
54  }
55 
56  //--------------------------------------------------------------------
58  {
59  double Cumulative=0, SPEArea=0;
60  for(size_t i=0; i!=fWaveform.size(); ++i)
61  {
62  Cumulative += fWaveform.at(i);
63  SPEArea += Cumulative;
64  }
65  return SPEArea;
66  }
67 
68  //--------------------------------------------------------------------
70  {
71  double AmpSoFar=0, Cumulative=0;
72  for(size_t i=0; i!=fWaveform.size(); ++i)
73  {
74  Cumulative += fWaveform.at(i);
75  if(Cumulative>AmpSoFar) AmpSoFar=Cumulative;
76  }
77  return AmpSoFar;
78  }
79 
80 
81  //--------------------------------------------------------------------
82 
84  {
85  return fLowGainArray[ch];
86  }
87 
88  //--------------------------------------------------------------------
90  {
91  return fHighGainArray[ch];
92  }
93  //--------------------------------------------------------------------
95  {
96  return CLHEP::RandGauss::shoot(fLowGainArray[ch],fGainSpreadArray[ch]*fLowGainArray[ch]);
97  }
98  //--------------------------------------------------------------------
100  {
101  return CLHEP::RandGauss::shoot(fHighGainArray[ch],fGainSpreadArray[ch]*fHighGainArray[ch]);
102  }
103  //--------------------------------------------------------------------
105  {
107 
108  else return optdata::TimeSlice_t((time_ns/1.e3-fTimeBegin)*fSampleFreq);
109  }
110 
111 
112  //--------------------------------------------------------------------
114  {
115  fSampleFreq = p.get< double >("SampleFreq" );
116  fTimeBegin = p.get< double >("TimeBegin" );
117  fTimeEnd = p.get< double >("TimeEnd" );
118  fWaveformFile = p.get< std::string >("WaveformFile" );
119  fPERescale = p.get< double >("PERescale" );
120 
121  // PMT properties
122  fQE = p.get<double>("QE");
123  fDarkRate = p.get<double>("DarkRate");
124  fSaturationScale = p.get<optdata::ADC_Count_t>("SaturationScale");
125 
126  // Shaper properties
127  fUseEmpiricalGain= p.get<bool >("UseEmpiricalGain");
128  fHighGainFile = p.get<std::string >("HighGainFile");
129  fLowGainFile = p.get<std::string >("LowGainFile");
130  fGainSpreadFile = p.get<std::string >("GainSpreadFile");
131 
132  fHighGainMean = p.get<double >("HighGainMean");
133  fLowGainMean = p.get<double >("LowGainMean");
134  fGainSpread = p.get<double >("GainSpread");
135  fGainSpread_PMT2PMT = p.get<double >("GainSpread_PMT2PMT");
136 
137  // Digitization ped fluc
138  fPedFlucRate = p.get<double>("PedFlucRate");
139  fPedFlucAmp = p.get<optdata::ADC_Count_t>("PedFlucAmp");
140  fADCBaseline = p.get<optdata::ADC_Count_t>("ADCBaseline");
141  fADCBaseSpread = p.get<double>("ADCBaseSpread");
142 
143  // WF related stuff
144  fUseEmpiricalShape = p.get< bool >("UseEmpiricalShape");
145  fWFLength = p.get< double >("WFLength" );
146 
147  fWaveformFile = p.get< std::string >("WaveformFile" );
148  fChargeNormalized = p.get< bool >("WaveformChargeNormalized", false);
149 
150  // Option 2: WF from analytical function
151  fWFPowerFactor = p.get< double >("WFPowerFactor" );
152  fWFTimeConstant = p.get< double >("WFTimeConstant" );
153  fVoltageAmpForSPE = p.get< double >("VoltageAmpForSPE" );
154 
155  // Generate the SPE waveform (i.e. fWaveform)
157 
158  // Fill gain array
159  FillGainArray();
160 
161  // Fill baseline mean
163 
164  // Report
165  std::string msg(Form("%-10s ... %-10s ... %-10s ... %-10s\n","Ch. Number","Pedestal","High Gain","Low Gain"));
166  for(unsigned int i=0;i<fGeometry->NOpChannels();++i) {
167  msg+=Form("%-10d ... %-10d ... %-10g ... %-10g\n",i,fPedMeanArray[i],fHighGainArray[i],fLowGainArray[i]);
168  }
169  mf::LogInfo(__FUNCTION__)<<msg.c_str();
170 
171  return;
172  }
173 
174  //
175  // As far as Kazu is concerned, this function is deprecated.
176  // Any comment? --Kazu 08/05/2013
177  //
178  std::vector<double> OpDigiProperties::WaveformInit(std::string fWaveformFile)
179  {
180  // Read in waveform vector from text file
181  std::ifstream WaveformFile (fWaveformFile.c_str());
182  std::string line;
183 
184  mf::LogInfo("OpDigiProperties")<<"OpDigiProperties opening OpDet waveform at " << fWaveformFile.c_str();
185 
186  // Read in each line and place into waveform vector
187  std::vector<double> PEWaveform;
188  if (WaveformFile.is_open())
189  {
190  while ( WaveformFile.good() )
191  {
192  getline (WaveformFile, line);
193  PEWaveform.push_back( fPERescale * strtod( line.c_str(), NULL ) );
194  }
195  }
196  else throw cet::exception("OpDigiProperties") << "No Waveform File: Unable to open file\n";
197 
198  WaveformFile.close();
199  return(PEWaveform);
200  }
201 
202  // Fill the array of pedestal mean
204  for(unsigned int i=0;i<fGeometry->NOpChannels();++i)
205  fPedMeanArray.push_back((optdata::ADC_Count_t)(CLHEP::RandGauss::shoot((double)fADCBaseline,fADCBaseSpread)+0.5));
206  }
207 
208  // Fill arrays (std::vector<double>) for PMT gain mean & spread information.
211  {
212  // Fill fron user's text files.
213  mf::LogWarning("OpDigiProperties")<<"Using empirical table of gain for each PMT...";
214  std::string FullPath;
215  cet::search_path sp("FW_SEARCH_PATH");
216 
217  if( !sp.find_file(fHighGainFile, FullPath) )
218  throw cet::exception("OpDigiProperties") << "Unable to find high gain spread file in " << sp.to_string() << "\n";
219 
220  mf::LogWarning("OpDigiProperties")<<"OpDigiProperties opening high gain spread file at " << FullPath.c_str();
221  std::ifstream HighGainFile(FullPath.c_str());
222  if(HighGainFile.is_open()) {
223  std::string line;
224  while ( HighGainFile.good() ){
225  getline(HighGainFile, line);
226  fHighGainArray.push_back(strtod(line.c_str(),NULL));
227  }
228  }else throw cet::exception("OpDigiProperties")<<"Unable to open file!\n";
229 
230  FullPath="";
231  if( !sp.find_file(fLowGainFile, FullPath) )
232  throw cet::exception("OpDigiProperties") << "Unable to find low gain spread file in " << sp.to_string() << "\n";
233 
234  mf::LogWarning("OpDigiProperties")<<"OpDigiProperties opening low gain spread file at " << FullPath.c_str();
235  std::ifstream LowGainFile(FullPath.c_str());
236  if(LowGainFile.is_open()) {
237  std::string line;
238  while ( LowGainFile.good() ){
239  getline(LowGainFile, line);
240  fLowGainArray.push_back(strtod(line.c_str(),NULL));
241  }
242  }else throw cet::exception("OpDigiProperties")<<"Unable to open file!\n";
243 
244  FullPath="";
245  if( !sp.find_file(fGainSpreadFile, FullPath) )
246  throw cet::exception("OpDigiProperties") << "Unable to find low gain spread file in " << sp.to_string() << "\n";
247 
248  mf::LogWarning("OpDigiProperties")<<"OpDigiProperties opening low gain spread file at " << FullPath.c_str();
249  std::ifstream GainSpreadFile(FullPath.c_str());
250  if(GainSpreadFile.is_open()) {
251  std::string line;
252  while ( GainSpreadFile.good() ){
253  getline(GainSpreadFile, line);
254  fGainSpreadArray.push_back(strtod(line.c_str(),NULL));
255  }
256  }else throw cet::exception("OpDigiProperties")<<"Unable to open file!\n";
257 
258  }
259  else{
260  // Generate a set of gake gain mean & spread.
261  std::string txt;
262  txt+= " Generating gain for each pmt.\n";
263  txt+=Form(" High gain mean: %g ADC/p.e.\n", fHighGainMean);
264  txt+=Form(" Low gain mean: %g ADC/p.e.\n", fLowGainMean);
265  txt+=Form(" PMT-to-PMT gain spread : %g \n", fGainSpread_PMT2PMT);
266  txt+=Form(" Intrinsic gain spread : %g \n", fGainSpread);
267  mf::LogWarning("OpDigiProperties")<<txt.c_str();
268  for(unsigned int i=0;i<fGeometry->NOpChannels();++i) {
269  fLowGainArray.push_back(CLHEP::RandGauss::shoot(fLowGainMean,fLowGainMean*fGainSpread_PMT2PMT));
270  fHighGainArray.push_back(CLHEP::RandGauss::shoot(fHighGainMean,fHighGainMean*fGainSpread_PMT2PMT));
271  fGainSpreadArray.push_back(fGainSpread);
272  }
273  }
274 
275  //
276  // Note:
277  // Check for # entries. These exceptions ensures we have enough # of elements.
278  // When a user access the elements by a channel number using LowGainMean(Channel_t ch) etc.,
279  // those functions do not check if the given channel number is valid or not to keep a high
280  // performance of the code. If there's an invalid memory access error in run-time, then
281  // it must mean the user provided an invalid channel number and not due to insufficient
282  // vector elements filled in this function.
283  //
284  if(fLowGainArray.size()<fGeometry->NOpChannels())
285  throw cet::exception("OpDigiProperties")<<"Low gain missing for some channels!\n";
286  if(fHighGainArray.size()<fGeometry->NOpChannels())
287  throw cet::exception("OpDigiProperties")<<"High gain missing for some channels!\n";
288  if(fGainSpreadArray.size()<fGeometry->NOpChannels())
289  throw cet::exception("OpDigiProperties")<<"Gain spread missing for some channels!\n";
290  }
291 
293  {
294  std::string FullPath;
295 
296  if(fUseEmpiricalShape){
297  cet::search_path sp("FW_SEARCH_PATH");
298  if( !sp.find_file(fWaveformFile, FullPath) )
299 
300  throw cet::exception("OpDigiProperties") << "Unable to find PMT waveform file in " << sp.to_string() << "\n";
301 
302  fWaveform = GenEmpiricalWF(FullPath);
303 
304  }else fWaveform = GenAnalyticalWF();
305  }
306 
307  std::vector<double> OpDigiProperties::GenEmpiricalWF(std::string fWaveformFile)
308  {
309  // Read in waveform vector from text file
310  std::ifstream WaveformFile (fWaveformFile.c_str());
311  std::string line;
312 
313  mf::LogWarning("OpDigiProperties")<<"OpDigiProperties opening OpDet waveform at " << fWaveformFile.c_str();
314 
315  // Read in each line and place into waveform vector
316  std::vector<double> PEWaveform;
317  if (WaveformFile.is_open())
318  {
319  double MaxAmp=0;
320  double Charge=0;
321  int NSample=0;
322  while ( WaveformFile.good() && NSample<int(fWFLength*fSampleFreq))
323  {
324  getline (WaveformFile, line);
325  double Amp=strtod(line.c_str(),NULL);
326  PEWaveform.push_back(Amp);
327  if(Amp>MaxAmp) MaxAmp=Amp;
328  NSample++;
329  Charge+=Amp;
330  }
331  // rescale
332  if(MaxAmp<=0) throw cet::exception("OpDigiProperties_module")<<"Waveform amplitude <=0!\n";
333  if(!fChargeNormalized)for(unsigned short i=0; i<PEWaveform.size(); i++){ PEWaveform[i]=PEWaveform[i]/MaxAmp; }
334  else for(unsigned short i=0; i<PEWaveform.size(); i++){ PEWaveform[i]=PEWaveform[i]/Charge; }
335  }
336  else throw cet::exception("No Waveform File") << "Unable to open file\n";
337 
338  WaveformFile.close();
339  return(PEWaveform);
340  }
341 
342  std::vector<double> OpDigiProperties::GenAnalyticalWF(){
343  mf::LogWarning("OpDigiProperties")<<" OpDigiProperties using analytical function for WF generation.";
344  //
345  // Generate waveform from analytical form
346  //
347  if(!fAnalyticalSPE) {// Create analytical function if not yet created
348  fAnalyticalSPE = new TF1("_analyticalSPE",
349  "10^(22)*x^[1]*[0]*exp(-x/[2])/TMath::Factorial([1])",
350  0,fWFLength*2); // x is time in micro-seconds
351  fAnalyticalSPE->SetParameter(0,fVoltageAmpForSPE); // voltage amplitude for s.p.e.
352  fAnalyticalSPE->SetParameter(1,fWFPowerFactor); // power factor (no unit)
353  fAnalyticalSPE->SetParameter(2,fWFTimeConstant); // time constant in us
354  }
355  //
356  // Define a waveform vector
357  //
358  // Size of WF = time width [us] * frequency [MHz]
359  std::vector<double> PEWaveform(int( fWFLength * fSampleFreq), 0.0);
360  double SamplingDuration = 1./fSampleFreq; // in micro seconds
361  double MaxAmp=0;
362  double Charge=0;
363  for(unsigned short i = 0; i<PEWaveform.size(); ++i){
364  double Value=fAnalyticalSPE->Integral( i * SamplingDuration,
365  (i+1) * SamplingDuration) / SamplingDuration;
366  PEWaveform[i]=Value;
367  if(PEWaveform[i]>MaxAmp) MaxAmp=PEWaveform[i];
368  Charge+=Value;
369  }
370 
371  // rescale
372  if(MaxAmp<=0) throw cet::exception("OpDigiProperties_module")<<"Waveform amplitude <=0!\n";
373 
374  if(!fChargeNormalized) {
375  for(unsigned short i=0; i<PEWaveform.size(); i++) {
376  PEWaveform[i]=PEWaveform[i]/MaxAmp;
377  if(PEWaveform[i]<1.e-4) PEWaveform[i]=0;
378  }
379  }
380  else for(unsigned short i=0; i<PEWaveform.size(); i++){ PEWaveform[i]=PEWaveform[i]/Charge; }
381 
382  return PEWaveform;
383  }
384 
385 } // namespace
386 
387 namespace opdet{
388 
390 
391 } // namespace util
double HighGainMean() const
Returns set mean gain value for HIGH gain.
std::vector< double > fHighGainArray
void reconfigure(fhicl::ParameterSet const &p)
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
#define DEFINE_ART_SERVICE(svc)
Definition: ServiceMacros.h:93
art::ServiceHandle< geo::Geometry > fGeometry
std::vector< double > GenAnalyticalWF()
double GetSPEAmplitude()
Utility function ... To be verified (Kazu 08/05/13)
std::vector< double > fLowGainArray
unsigned int NOpChannels() const
Number of electronics channels for all the optical detectors.
double LowGainMean() const
Returns set mean gain value for LOW gain.
double GetSPECumulativeArea()
Utility function ... To be verified (Kazu 08/05/13)
uint16_t ADC_Count_t
Definition: OpticalTypes.h:16
std::vector< double > WaveformInit(std::string WaveformFile)
Int_t max
Definition: plot.C:27
double GetSPECumulativeAmplitude()
Utility function ... To be verified (Kazu 08/05/13)
std::vector< double > GenEmpiricalWF(std::string WaveformFile)
T get(std::string const &key) const
Definition: ParameterSet.h:231
OpDigiProperties(fhicl::ParameterSet const &pset, art::ActivityRegistry &reg)
std::vector< double > fWaveform
optdata::ADC_Count_t fPedFlucAmp
unsigned int TimeSlice_t
Definition: OpticalTypes.h:20
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
double LowGain(optdata::Channel_t ch) const
Generate & return LOW gain value for an input channel using mean & spread for this channel...
double HighGain(optdata::Channel_t ch) const
Generate & return HIGH gain value for an input channel using mean & spread for this channel...
std::vector< optdata::ADC_Count_t > fPedMeanArray
optdata::TimeSlice_t GetTimeSlice(double time_ns)
std::vector< double > fGainSpreadArray
Float_t e
Definition: plot.C:34
optdata::ADC_Count_t fADCBaseline
double GetSPEArea()
Utility function ... To be verified (Kazu 08/05/13)
unsigned int Channel_t
Definition: OpticalTypes.h:19
art framework interface to geometry description
optdata::ADC_Count_t fSaturationScale
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33