All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
OpDigiProperties.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // \file OpDigiProperties_service.cc
4 //
5 ////////////////////////////////////////////////////////////////////////
6 
7 // LArSoft includes
9 
10 // Framework includes
11 #include "messagefacility/MessageLogger/MessageLogger.h"
12 
13 // CLHEP includes
14 #include "CLHEP/Random/RandGauss.h"
15 
16 // ROOT includes
17 #include "TF1.h"
18 
19 // C++ includes
20 #include <fstream>
21 
22 namespace opdet{
23 
24  //--------------------------------------------------------------------
25  OpDigiProperties::OpDigiProperties(fhicl::ParameterSet const& p)
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  {
153  if( time_ns/1.e3 > (fTimeEnd-fTimeBegin)) return std::numeric_limits<optdata::TimeSlice_t>::max();
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  //
162  std::vector<double> OpDigiProperties::WaveformInit(std::string fWaveformFile)
163  {
164  // Read in waveform vector from text file
165  std::ifstream WaveformFile (fWaveformFile.c_str());
166  std::string line;
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()) {
207  std::string line;
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()) {
221  std::string line;
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()) {
235  std::string line;
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";
272  if(fGainSpreadArray.size()<fGeometry->NOpChannels())
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 
291  std::vector<double> OpDigiProperties::GenEmpiricalWF(std::string fWaveformFile)
292  {
293  // Read in waveform vector from text file
294  std::ifstream WaveformFile (fWaveformFile.c_str());
295  std::string line;
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
std::vector< double > fHighGainArray
art::ServiceHandle< geo::Geometry const > fGeometry
OpDigiProperties(fhicl::ParameterSet const &pset)
pdgs p
Definition: selectors.fcl:22
std::vector< double > GenAnalyticalWF()
double GetSPEAmplitude()
Utility function ... To be verified (Kazu 08/05/13)
std::vector< double > fLowGainArray
BEGIN_PROLOG xarapuca_vuv SBNDDecoOpHitFinderXArapuca SPEArea
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)
double GetSPECumulativeAmplitude()
Utility function ... To be verified (Kazu 08/05/13)
std::vector< double > GenEmpiricalWF(std::string WaveformFile)
std::vector< double > fWaveform
optdata::ADC_Count_t fPedFlucAmp
double HighGainMean() const noexcept
Returns set mean gain value for HIGH gain.
unsigned int TimeSlice_t
Definition: OpticalTypes.h:20
double LowGain(optdata::Channel_t ch) const
Generate &amp; return LOW gain value for an input channel using mean &amp; spread for this channel...
do i e
double HighGain(optdata::Channel_t ch) const
Generate &amp; return HIGH gain value for an input channel using mean &amp; 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)
double LowGainMean() const noexcept
Returns set mean gain value for LOW gain.
unsigned int Channel_t
Definition: OpticalTypes.h:19
optdata::ADC_Count_t fSaturationScale