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