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