LArSoft  v06_85_00
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  // Option 2: WF from analytical function
149  fWFPowerFactor = p.get< double >("WFPowerFactor" );
150  fWFTimeConstant = p.get< double >("WFTimeConstant" );
151  fVoltageAmpForSPE = p.get< double >("VoltageAmpForSPE" );
152 
153  // Generate the SPE waveform (i.e. fWaveform)
155 
156  // Fill gain array
157  FillGainArray();
158 
159  // Fill baseline mean
161 
162  // Report
163  std::string msg(Form("%-10s ... %-10s ... %-10s ... %-10s\n","Ch. Number","Pedestal","High Gain","Low Gain"));
164  for(unsigned int i=0;i<fGeometry->NOpChannels();++i) {
165  msg+=Form("%-10d ... %-10d ... %-10g ... %-10g\n",i,fPedMeanArray[i],fHighGainArray[i],fLowGainArray[i]);
166  }
167  mf::LogInfo(__FUNCTION__)<<msg.c_str();
168 
169  return;
170  }
171 
172  //
173  // As far as Kazu is concerned, this function is deprecated.
174  // Any comment? --Kazu 08/05/2013
175  //
176  std::vector<double> OpDigiProperties::WaveformInit(std::string fWaveformFile)
177  {
178  // Read in waveform vector from text file
179  std::ifstream WaveformFile (fWaveformFile.c_str());
180  std::string line;
181 
182  mf::LogInfo("OpDigiProperties")<<"OpDigiProperties opening OpDet waveform at " << fWaveformFile.c_str();
183 
184  // Read in each line and place into waveform vector
185  std::vector<double> PEWaveform;
186  if (WaveformFile.is_open())
187  {
188  while ( WaveformFile.good() )
189  {
190  getline (WaveformFile, line);
191  PEWaveform.push_back( fPERescale * strtod( line.c_str(), NULL ) );
192  }
193  }
194  else throw cet::exception("OpDigiProperties") << "No Waveform File: Unable to open file\n";
195 
196  WaveformFile.close();
197  return(PEWaveform);
198  }
199 
200  // Fill the array of pedestal mean
202  for(unsigned int i=0;i<fGeometry->NOpChannels();++i)
203  fPedMeanArray.push_back((optdata::ADC_Count_t)(CLHEP::RandGauss::shoot((double)fADCBaseline,fADCBaseSpread)+0.5));
204  }
205 
206  // Fill arrays (std::vector<double>) for PMT gain mean & spread information.
209  {
210  // Fill fron user's text files.
211  mf::LogWarning("OpDigiProperties")<<"Using empirical table of gain for each PMT...";
212  std::string FullPath;
213  cet::search_path sp("FW_SEARCH_PATH");
214 
215  if( !sp.find_file(fHighGainFile, FullPath) )
216  throw cet::exception("OpDigiProperties") << "Unable to find high gain spread file in " << sp.to_string() << "\n";
217 
218  mf::LogWarning("OpDigiProperties")<<"OpDigiProperties opening high gain spread file at " << FullPath.c_str();
219  std::ifstream HighGainFile(FullPath.c_str());
220  if(HighGainFile.is_open()) {
221  std::string line;
222  while ( HighGainFile.good() ){
223  getline(HighGainFile, line);
224  fHighGainArray.push_back(strtod(line.c_str(),NULL));
225  }
226  }else throw cet::exception("OpDigiProperties")<<"Unable to open file!\n";
227 
228  FullPath="";
229  if( !sp.find_file(fLowGainFile, FullPath) )
230  throw cet::exception("OpDigiProperties") << "Unable to find low gain spread file in " << sp.to_string() << "\n";
231 
232  mf::LogWarning("OpDigiProperties")<<"OpDigiProperties opening low gain spread file at " << FullPath.c_str();
233  std::ifstream LowGainFile(FullPath.c_str());
234  if(LowGainFile.is_open()) {
235  std::string line;
236  while ( LowGainFile.good() ){
237  getline(LowGainFile, line);
238  fLowGainArray.push_back(strtod(line.c_str(),NULL));
239  }
240  }else throw cet::exception("OpDigiProperties")<<"Unable to open file!\n";
241 
242  FullPath="";
243  if( !sp.find_file(fGainSpreadFile, FullPath) )
244  throw cet::exception("OpDigiProperties") << "Unable to find low gain spread file in " << sp.to_string() << "\n";
245 
246  mf::LogWarning("OpDigiProperties")<<"OpDigiProperties opening low gain spread file at " << FullPath.c_str();
247  std::ifstream GainSpreadFile(FullPath.c_str());
248  if(GainSpreadFile.is_open()) {
249  std::string line;
250  while ( GainSpreadFile.good() ){
251  getline(GainSpreadFile, line);
252  fGainSpreadArray.push_back(strtod(line.c_str(),NULL));
253  }
254  }else throw cet::exception("OpDigiProperties")<<"Unable to open file!\n";
255 
256  }
257  else{
258  // Generate a set of gake gain mean & spread.
259  std::string txt;
260  txt+= " Generating gain for each pmt.\n";
261  txt+=Form(" High gain mean: %g ADC/p.e.\n", fHighGainMean);
262  txt+=Form(" Low gain mean: %g ADC/p.e.\n", fLowGainMean);
263  txt+=Form(" PMT-to-PMT gain spread : %g \n", fGainSpread_PMT2PMT);
264  txt+=Form(" Intrinsic gain spread : %g \n", fGainSpread);
265  mf::LogWarning("OpDigiProperties")<<txt.c_str();
266  for(unsigned int i=0;i<fGeometry->NOpChannels();++i) {
267  fLowGainArray.push_back(CLHEP::RandGauss::shoot(fLowGainMean,fLowGainMean*fGainSpread_PMT2PMT));
268  fHighGainArray.push_back(CLHEP::RandGauss::shoot(fHighGainMean,fHighGainMean*fGainSpread_PMT2PMT));
269  fGainSpreadArray.push_back(fGainSpread);
270  }
271  }
272 
273  //
274  // Note:
275  // Check for # entries. These exceptions ensures we have enough # of elements.
276  // When a user access the elements by a channel number using LowGainMean(Channel_t ch) etc.,
277  // those functions do not check if the given channel number is valid or not to keep a high
278  // performance of the code. If there's an invalid memory access error in run-time, then
279  // it must mean the user provided an invalid channel number and not due to insufficient
280  // vector elements filled in this function.
281  //
282  if(fLowGainArray.size()<fGeometry->NOpChannels())
283  throw cet::exception("OpDigiProperties")<<"Low gain missing for some channels!\n";
284  if(fHighGainArray.size()<fGeometry->NOpChannels())
285  throw cet::exception("OpDigiProperties")<<"High gain missing for some channels!\n";
286  if(fGainSpreadArray.size()<fGeometry->NOpChannels())
287  throw cet::exception("OpDigiProperties")<<"Gain spread missing for some channels!\n";
288  }
289 
291  {
292  std::string FullPath;
293 
294  if(fUseEmpiricalShape){
295  cet::search_path sp("FW_SEARCH_PATH");
296  if( !sp.find_file(fWaveformFile, FullPath) )
297 
298  throw cet::exception("OpDigiProperties") << "Unable to find PMT waveform file in " << sp.to_string() << "\n";
299 
300  fWaveform = GenEmpiricalWF(FullPath);
301 
302  }else fWaveform = GenAnalyticalWF();
303  }
304 
305  std::vector<double> OpDigiProperties::GenEmpiricalWF(std::string fWaveformFile)
306  {
307  // Read in waveform vector from text file
308  std::ifstream WaveformFile (fWaveformFile.c_str());
309  std::string line;
310 
311  mf::LogWarning("OpDigiProperties")<<"OpDigiProperties opening OpDet waveform at " << fWaveformFile.c_str();
312 
313  // Read in each line and place into waveform vector
314  std::vector<double> PEWaveform;
315  if (WaveformFile.is_open())
316  {
317  double MaxAmp=0;
318  int NSample=0;
319  while ( WaveformFile.good() && NSample<int(fWFLength*fSampleFreq))
320  {
321  getline (WaveformFile, line);
322  double Amp=strtod(line.c_str(),NULL);
323  PEWaveform.push_back(Amp);
324  if(Amp>MaxAmp) MaxAmp=Amp;
325  NSample++;
326  }
327  // rescale
328  if(MaxAmp<=0) throw cet::exception("OpDigiProperties_module")<<"Waveform amplitude <=0!\n";
329  for(unsigned short i=0; i<PEWaveform.size(); i++){ PEWaveform[i]=PEWaveform[i]/MaxAmp; }
330  }
331  else throw cet::exception("No Waveform File") << "Unable to open file\n";
332 
333  WaveformFile.close();
334  return(PEWaveform);
335  }
336 
337  std::vector<double> OpDigiProperties::GenAnalyticalWF(){
338  mf::LogWarning("OpDigiProperties")<<" OpDigiProperties using analytical function for WF generation.";
339  //
340  // Generate waveform from analytical form
341  //
342  if(!fAnalyticalSPE) {// Create analytical function if not yet created
343  fAnalyticalSPE = new TF1("_analyticalSPE",
344  "10^(22)*x^[1]*[0]*exp(-x/[2])/TMath::Factorial([1])",
345  0,fWFLength*2); // x is time in micro-seconds
346  fAnalyticalSPE->SetParameter(0,fVoltageAmpForSPE); // voltage amplitude for s.p.e.
347  fAnalyticalSPE->SetParameter(1,fWFPowerFactor); // power factor (no unit)
348  fAnalyticalSPE->SetParameter(2,fWFTimeConstant); // time constant in us
349  }
350  //
351  // Define a waveform vector
352  //
353  // Size of WF = time width [us] * frequency [MHz]
354  std::vector<double> PEWaveform(int( fWFLength * fSampleFreq), 0.0);
355  double SamplingDuration = 1./fSampleFreq; // in micro seconds
356  double MaxAmp=0;
357  for(unsigned short i = 0; i<PEWaveform.size(); ++i){
358  double Value=fAnalyticalSPE->Integral( i * SamplingDuration,
359  (i+1) * SamplingDuration) / SamplingDuration;
360  PEWaveform[i]=Value;
361  if(PEWaveform[i]>MaxAmp) MaxAmp=PEWaveform[i];
362  }
363 
364  // rescale
365  if(MaxAmp<=0) throw cet::exception("OpDigiProperties_module")<<"Waveform amplitude <=0!\n";
366  for(unsigned short i=0; i<PEWaveform.size(); i++) {
367  PEWaveform[i]=PEWaveform[i]/MaxAmp;
368  if(PEWaveform[i]<1.e-4) PEWaveform[i]=0;
369  }
370 
371  return PEWaveform;
372  }
373 
374 } // namespace
375 
376 namespace opdet{
377 
379 
380 } // 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