LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
PedAlgoRollingMean.cxx
Go to the documentation of this file.
1 //
3 // PedAlgoRollingMean source
4 //
6 
7 #ifndef larana_OPTICALDETECTOR_PEDALGOROLLINGMEAN_CXX
8 #define larana_OPTICALDETECTOR_PEDALGOROLLINGMEAN_CXX
9 
10 #include "PedAlgoRollingMean.h"
11 #include "UtilFunc.h"
12 
13 //#include <ctime>
14 #include <iostream>
15 namespace pmtana{
16 
17  //*****************************************************************
19  : PMTPedestalBase(name)
20  //*****************************************************************
21  {
22  srand(static_cast<unsigned int>(time(0)));
23  }
24 
25  //**************************************************************************
27  //PedAlgoRollingMean::PedAlgoRollingMean(const ::fcllite::PSet &pset,
28  const std::string name)
29  : PMTPedestalBase(name)
30  //############################################################
31  {
32 
33  _sample_size = pset.get<size_t>("SampleSize");
34  _max_sigma = pset.get<float> ("MaxSigma");
35  _ped_range_max = pset.get<float> ("PedRangeMax");
36  _ped_range_min = pset.get<float> ("PedRangeMin");
37 
38  // _range = pset.get<int> ("RandomRange");
39  // _divisions = pset.get<double>("RandomRangeDivisions");
40  _threshold = pset.get<double>("Threshold");
41  _diff_threshold = pset.get<double>("DiffBetweenGapsThreshold");
42  _diff_adc_count = pset.get<double>("DiffADCCounts");
43 
44  _n_presamples = pset.get<int>("NPrePostSamples");
45 
46  //_random_shift = pset.get<double>("RandomRangeShift");
47  // Random seed number generator
48  //srand(static_cast<unsigned int>(time(0)));
49  }
50 
51  //*******************************************
53  //*******************************************
54  {}
55 
56  //****************************************************************************
58  pmtana::PedestalMean_t& mean_v,
59  pmtana::PedestalSigma_t& sigma_v)
60  //****************************************************************************
61  {
62 
63  // parameters
64  if(wf.size()<=(_sample_size * 2))
65  return false;
66 
67  const size_t window_size = _sample_size*2;
68 
69  // middle mean
70  for(size_t i=0; i< wf.size(); ++i) {
71 
72  mean_v[i] = 0;
73  sigma_v[i] = 0;
74 
75  if( i < _sample_size || i >= (wf.size() - _sample_size) ) continue;
76 
77  mean_v[i] = mean (wf,i - _sample_size,window_size);
78  sigma_v[i] = std (wf,mean_v[i],i - _sample_size,window_size);
79  }
80 
81  // front mean
82  for(size_t i=0; i<_sample_size; ++i) {
83 
84  mean_v[i] = mean_v [_sample_size];
85  sigma_v[i] = sigma_v[_sample_size];
86 
87  }
88  // tail mean
89  for(size_t i=(wf.size() - _sample_size); i<wf.size(); ++i) {
90 
91  mean_v[i] = mean_v [wf.size() - _sample_size -1];
92  sigma_v[i] = sigma_v[wf.size() - _sample_size -1];
93 
94  }
95 
96  float best_sigma = 1.1e9;
97  size_t best_sigma_index = 0;
98  size_t num_good_adc = 0;
99 
100  for(size_t i=0; i<sigma_v.size(); ++i) {
101  // Only consider adcs which mean is in the allowed range
102  auto const& mean = mean_v[i];
103 
104  if( mean < _ped_range_min || mean > _ped_range_max ) continue;
105 
106  auto const& sigma = sigma_v[i];
107  if(sigma < best_sigma) {
108  best_sigma = sigma;
109  best_sigma_index = i;
110  }
111 
112  if(sigma < _max_sigma) num_good_adc += 1;
113  }
114 
115 
116  if( num_good_adc < 1 ) {
117  std::cerr << "\033[93m<<" << __FUNCTION__ << ">>\033[00m Could not find good pedestal at all..." << std::endl;
118  return false;
119  }
120 
121  // If not enough # of good mean indices, use the best guess within this waveform
122  if(best_sigma > _max_sigma || num_good_adc < 3) {
123  for(size_t i=0; i<mean_v.size(); ++i) {
124  mean_v[i] = mean_v.at ( best_sigma_index );
125  sigma_v[i] = sigma_v.at ( best_sigma_index );
126  }
127 
128  return true;
129  }
130 
131 
132  // Else do extrapolation, or random seed depending on what we find...
133 
134  unsigned nbins = 1000;
135 
137  const auto mode_mean = BinnedMaxOccurrence(mean_v ,nbins);
138  const auto mode_sigma = BinnedMaxOccurrence(sigma_v,nbins);
139 
140  //auto mode_mean = BinnedMaxTH1D(mean_v ,nbins);
141  //auto mode_sigma = BinnedMaxTH1D(sigma_v,nbins);
142 
143  //std::cout<<mode_mean<<" +/- "<<mode_sigma<<std::endl;
144 
145  _diff_threshold *= mode_sigma;
146 
148 
149  int last_good_index = -1;
150 
151  for(size_t i=0; i < wf.size(); ++i) {
152 
153  auto const mean = mean_v[i];
154  auto const sigma = sigma_v[i];
155 
156  // if(sigma <= _max_sigma && mean < _ped_range_max && mean > _ped_range_min) {
157  // not sure if this works well for basline that is "linear" seen by David K
158 
159  if(sigma <= _threshold * mode_sigma && fabs(mean - mode_mean) <= _threshold * mode_sigma) {
160 
161  if(last_good_index<0) {
162  last_good_index = (int)i;
163  continue;
164  }
165 
166  if( ( last_good_index + 1 ) < (int) i ) {
167 
168  auto diff = fabs(mean_v.at(last_good_index) - mean);
169 
170  if ( diff > diff_cutoff) {
171  //this should become generic interpolation function, for now lets leave.
172  float slope = (mean - mean_v.at(last_good_index)) / (float(i - last_good_index));
173 
174  for(size_t j = last_good_index + 1; j < i; ++j) {
175  mean_v.at(j) = slope * ( float(j - last_good_index) ) + mean_v.at(last_good_index);
176  sigma_v.at(j) = mode_sigma;
177  }
178  }
179  else {
180  //difference roughly the same lets fill with constant baseline
181 
182  auto presample_mean = edge_aware_mean(wf,last_good_index - _n_presamples, last_good_index);
183  auto postsample_mean = edge_aware_mean(wf,i, _n_presamples);
184 
185  auto diff_pre = fabs(presample_mean - mode_mean);
186  auto diff_post = fabs(postsample_mean - mode_mean);
187 
188  auto constant_mean = diff_pre <= diff_post ? presample_mean : postsample_mean;
189 
190  for(size_t j = last_good_index + 1; j < i; ++j) {
191  //mean_v.at(j) = floor( mean_v.at(last_good_index) ) + _random_shift + (double) ( rand() % _range) / _divisions;
192  mean_v.at(j) = constant_mean;
193  sigma_v.at(j) = mode_sigma;
194  }
195  }
196  }
197  last_good_index = (int)i;
198  }
199  }
200 
201 
202  // Next do extrapolation to the first and end (if needed)
203  // vic: for now we leave this i'm not sure if this really needs
204  // to be tuned until I can make unit test
205  // update: yes this needs work...
206 
207  if(sigma_v.front() > mode_sigma) {
208 
209  int first_index = -1;
210  int second_index = -1;
211 
212  for(size_t i=0; i < wf.size(); ++i) {
213  if( sigma_v.at(i) < mode_sigma ) {
214  if( first_index < 0 ) first_index = (int)i;
215  else if( second_index < 0 ) {
216  second_index = (int)i;
217  break;
218  }
219  }
220  }
221 
222  if(first_index < 0 || second_index < 0) {
223  std::cerr <<"\033[93m<<" << __FUNCTION__ << ">>\033[00m Could not find good pedestal for CDF"
224  << "\n"
225  << "first_index: " << first_index << "\n"
226  << "second_index: " << second_index << "\n"
227  << "If one of these is less than zero, this means there is pulse\n"
228  << "on first sample and baseline never went back down. Returning false here.";
229  return false;
230  }
231 
232 
233  auto diff = fabs(mean_v.at(first_index) - mean_v.at(second_index));
234 
235  if ( diff > diff_cutoff) {
236 
237  float slope = (mean_v.at(second_index) - mean_v.at(first_index)) / (float(second_index - first_index));
238 
239  for(int j=0; j < first_index; ++j) {
240  mean_v.at(j) = mean_v.at(first_index) - slope * (first_index - j);
241  sigma_v.at(j) = _max_sigma;
242  }
243 
244  } else {
245 
246  auto postsample_mean = edge_aware_mean(wf,first_index, first_index + _n_presamples);
247 
248  for(int j=0; j < first_index; ++j) {
249  //mean_v.at(j) = floor( mean_v.at(second_index) ) + _random_shift + (double) ( rand() % _range) / _divisions;
250  mean_v.at(j) = postsample_mean;
251  sigma_v.at(j) = mode_sigma;
252  }
253  }
254 
255  }
256 
257 
258  if(sigma_v.back() > mode_sigma) {
259 
260  int first_index = -1;
261  int second_index = -1;
262 
263  for(int i = wf.size()-1; i >= 0; --i) {
264  if(sigma_v.at(i) < mode_sigma) {
265  if( second_index < 0 ) second_index = (int)i;
266  else if( first_index < 0 ) {
267  first_index = (int)i;
268  break;
269  }
270  }
271  }
272 
273  if(first_index < 0 || second_index < 0) {
274  std::cerr <<"\033[93m<<" << __FUNCTION__ << ">>\033[00m Could not find good pedestal for CDF"
275  << "\n"
276  << "first_index: " << first_index << "\n"
277  << "second_index: " << second_index << "\n"
278  << "If one of these is less than zero, this means there is pulse\n"
279  << "on the last sample and baseline never went back down. Returning false here.";
280  return false;
281  }
282 
283 
284  auto diff = fabs(mean_v.at(second_index) - mean_v.at(first_index) );
285 
286  if ( diff > diff_cutoff) {
287 
288  float slope = (mean_v.at(second_index) - mean_v.at(first_index)) / (float(second_index - first_index));
289  for(int j = second_index+1; j < int(wf.size()); ++j) {
290  mean_v.at(j) = mean_v.at(second_index) + slope * (j-second_index);
291  sigma_v.at(j) = _max_sigma;
292  }
293 
294  }
295  else {
296 
297  auto presample_mean = edge_aware_mean(wf,first_index - _n_presamples, second_index);
298 
299  for(int j = second_index+1; j < int(wf.size()); ++j) {
300  //mean_v.at(j) = floor( mean_v.at(first_index) ) + _random_shift + (double) ( rand() % _range) / _divisions;
301  mean_v.at(j) = presample_mean;
302  sigma_v.at(j) = mode_sigma;
303  }
304  }
305  }
306 
307 
308  return true;
309 
310  }
311 
312 }
313 
314 #endif
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
Definition: UtilFunc.cxx:44
double BinnedMaxOccurrence(const PedestalMean_t &mean_v, const size_t nbins)
Definition: UtilFunc.cxx:61
std::vector< double > PedestalSigma_t
bool ComputePedestal(const pmtana::Waveform_t &wf, pmtana::PedestalMean_t &mean_v, pmtana::PedestalSigma_t &sigma_v)
Method to compute a pedestal of the input waveform using "nsample" ADC samples from "start" index...
double edge_aware_mean(const std::vector< short > &wf, int start, int end)
Definition: UtilFunc.cxx:27
Class definition file of PedAlgoRollingMean.
T get(std::string const &key) const
Definition: ParameterSet.h:231
std::vector< short > Waveform_t
double mean(const std::vector< short > &wf, size_t start, size_t nsample)
Definition: UtilFunc.cxx:15
PedAlgoRollingMean(const std::string name="PedRollingMean")
Default constructor.
std::vector< double > PedestalMean_t
virtual ~PedAlgoRollingMean()
Default destructor.