TraceAlgorithm.cc
Go to the documentation of this file.
1 #include <utl/Trace.h>
2 #include <utl/TraceAlgorithm.h>
3 #include <utl/ErrorLogger.h>
4 #include <utl/AugerUnits.h>
5 #include <utl/Deprecator.h>
6 #include <cmath>
7 #include <vector>
8 #include <algorithm>
9 #include <numeric>
10 #include <sstream>
11 
12 using namespace utl;
13 using namespace std;
14 
15 
16 template<typename T>
17 double
19  const unsigned int bin1, const unsigned int bin2)
20 {
21  if (!TraceAlgorithm::BoundsOk(trace, bin1, bin2))
23 
24  return *min_element(&trace[bin1], &trace[bin2] + 1);
25 }
26 
27 
28 template<typename T>
29 double
31  const unsigned int bin1, const unsigned int bin2)
32 {
33  if (!TraceAlgorithm::BoundsOk(trace, bin1, bin2))
35 
36  return *max_element(&trace[bin1], &trace[bin2] + 1);
37 }
38 
39 
40 template<typename T>
41 double
43  const unsigned int bin1, const unsigned int bin2)
44 {
45  if (!TraceAlgorithm::BoundsOk(trace, bin1, bin2))
47 
48  return Sum(trace, bin1, bin2) / (bin2 + 1 - bin1);
49 }
50 
51 
52 template<typename T>
53 inline
54 double
55 TraceAlgorithm::Mean(const vector<T>& v)
56 {
57  return accumulate(v.begin(), v.end(), T(0)) / double(v.size());
58 }
59 
60 
61 template<typename T>
62 double
64  const unsigned int bin1, const unsigned int bin2,
65  const unsigned int sortAlgorithmLimit)
66 {
67  if (!TraceAlgorithm::BoundsOk(trace, bin1, bin2))
69 
70  // work only on trace between bin1 and bin2
71  vector<T> workingSet(&trace[bin1], &trace[bin2+1]);
72 
73  // Calculate median by sorting if the number of elements is small enough
74  if (bin2 - bin1 <= sortAlgorithmLimit) {
75  const size_t half = workingSet.size() / 2;
76  // partially sort trace up to one element furhter than the middle
77  partial_sort(workingSet.begin(), workingSet.begin() + half + 1, workingSet.end());
78 
79  // for odd sizes return the element in the middle
80  // for even sizes return the mean of the two elements in the middle
81  if (workingSet.size() & 1)
82  return workingSet[half];
83  else
84  return 0.5*(workingSet[half - 1] + workingSet[half]);
85  }
86 
87  // calculate starting values
88  double mean = Mean(workingSet);
89  // delta is the number of elements lower than the mean
90  // which have to be eliminated
91  double delta = 0.5 * workingSet.size();
92 
93  double median = 0;
94 
95  vector<T> lowerSet;
96  vector<T> upperSet;
97  do {
98  // devide trace into subset of values lower and higher than the mean
99  for (const auto& value : workingSet) {
100  if (value < mean)
101  lowerSet.push_back(value);
102  else
103  upperSet.push_back(value);
104  }
105 
106  // choose the bigger set for the next round and look if the median is already found
107  if (delta < lowerSet.size()) {
108  // the elements of the upper set must be larger than the median
109  // and are thus not considered anymore
110  swap(workingSet, lowerSet);
111  mean = Mean(workingSet);
112  // Median is found if mean value is the maximum
113  if (mean == *max_element(workingSet.begin(), workingSet.end())) {
114  median = mean; // as mean == max
115  break;
116  }
117  } else {
118  // the elements of the lower set must be smaller than the median
119  // and are thus eliminated for further searching
120  delta -= lowerSet.size();
121  swap(workingSet, upperSet);
122  mean = Mean(workingSet);
123 
124  // Median is found if no values are left to eliminate
125  // in this case, delta is 1/2 or 0
126  // if delta = 0, the trace length was even and the median is taken
127  // as the mean of the two median values.
128  if (delta < 0.1) { // if delta == 0
129  median = 0.5*(*min_element(workingSet.begin(), workingSet.end()) +
130  *max_element(lowerSet.begin(), lowerSet.end()));
131  break;
132  }
133  // Median is also found if mean value is the minimum or delta is 1/2
134  if (mean == *min_element(workingSet.begin(), workingSet.end()) ||
135  delta < 0.9) { // if delta == 1/2
136  median = *min_element(workingSet.begin(), workingSet.end());
137  break;
138  }
139  }
140 
141  lowerSet.clear();
142  upperSet.clear();
143 
144  } while (delta > 0); // should not exit here, but when median is found
145 
146  return median;
147 }
148 
149 
150 template<typename T>
151 double
153  const unsigned int bin1, const unsigned int bin2)
154 {
155  utl::Deprecator::GetInstance().Deprecated(
156  "TraceAlgorithm::RMS()",
157  "v2r8",
158  "use TraceAlgorithm::RootMeanSquare() or TraceAlgorithm::StandardDeviation() "
159  "depending on what you actually want"
160  );
161 
162  if (!TraceAlgorithm::BoundsOk(trace, bin1, bin2))
164 
165  const double mean = Mean(trace, bin1, bin2);
166  double squares = 0;
167  for (unsigned int i = bin1; i <= bin2; ++i) {
168  const double diff = trace[i] - mean;
169  squares += diff * diff;
170  }
171 
172  return sqrt(squares / (bin2 - bin1 + 1U));
173 }
174 
175 
176 template<typename T>
177 double
179  const unsigned int bin1, const unsigned int bin2)
180 {
181  if (!TraceAlgorithm::BoundsOk(trace, bin1, bin2))
183 
184  double squares = 0;
185  for (unsigned int i = bin1; i <= bin2; ++i) {
186  squares += trace[i]*trace[i];
187  }
188 
189  return sqrt(squares / (bin2 - bin1 + 1U));
190 }
191 
192 
193 template<typename T>
194 double
196  const unsigned int bin1, const unsigned int bin2)
197 {
198  if (!TraceAlgorithm::BoundsOk(trace, bin1, bin2))
200 
201  const double mean = Mean(trace, bin1, bin2);
202  double squares = 0;
203  for (unsigned int i = bin1; i <= bin2; ++i) {
204  const double diff = trace[i] - mean;
205  squares += diff * diff;
206  }
207 
208  return sqrt(squares / (bin2 - bin1 + 1U));
209 }
210 
211 
212 template<typename T>
213 double
215  const unsigned int bin1, const unsigned int bin2)
216 {
217  if (!TraceAlgorithm::BoundsOk(trace, bin1, bin2))
219 
220  return accumulate(&trace[bin1], &trace[bin2] + 1, T(0));
221 }
222 
223 
224 template<typename T>
225 double
227  const unsigned int bin1, const unsigned int bin2)
228 {
229  if (!TraceAlgorithm::BoundsOk(trace, bin1, bin2))
231 
232  double sum = 0;
233  double moment = 0;
234 
235  for (unsigned int i = bin1; i <= bin2; ++i) {
236  const double value = trace[i];
237  sum += value;
238  moment += value * (i + 0.5);
239  }
240 
241  return moment / sum;
242 }
243 
244 
245 template<typename T>
246 bool
248  const unsigned int bin1, const unsigned int bin2)
249 {
250  if (bin2 >= trace.GetSize()) {
251  ostringstream errorMsg;
252  errorMsg << " Trace stops at " << trace.GetStop()
253  << " while evaluation requested between " << bin1
254  << " and " << bin2;
255  ERROR(errorMsg);
256  return false;
257  }
258 
259  if (bin1 > bin2) {
260  ostringstream errorMsg;
261  errorMsg << "second bin specified can not be smaller than first: bin1 = "
262  << bin1 << ", bin2 = " << bin2;
263  ERROR(errorMsg);
264  return false;
265  }
266 
267  return true;
268 }
269 
270 
271 template<typename T>
272 double
274  const unsigned int bin1, const unsigned int bin2)
275 {
276  // Definition see e.g. GAP Note 2003-076 by J. Cronin
277 
278  if (!TraceAlgorithm::BoundsOk(trace, bin1, bin2))
280 
281  const double binSize = trace.GetBinning();
282  const double shapeParameterTime = 600 * nanosecond;
283  const unsigned int shapeParameterBin =
284  bin1 + (unsigned int)(shapeParameterTime / binSize);
285 
286  if (shapeParameterBin < bin2) {
287  const double sumLate = Sum(trace, shapeParameterBin, bin2);
288  const double sumEarly = Sum(trace, bin1, shapeParameterBin);
289  return sumLate / sumEarly;
290  }
291 
292  return 0;
293 }
294 
295 
302 template<typename T>
303 double
305  const unsigned int bin1, const unsigned int bin2,
306  const double percent)
307 {
308  if (!TraceAlgorithm::BoundsOk(trace, bin1, bin2))
310 
311  const double sum = Sum(trace, bin1, bin2);
312  if (sum < 0) {
313  cerr << "Pmt trace seems wrong, signal negative (" << sum
314  << ")..." << endl;
315  return 0;
316  }
317 
318  const double signal = sum * percent / 100.;
319 
320  double sumContent = 0;
321  double sumContentPrev = 0;
322  unsigned int i;
323  for (i = bin1; i <= bin2; ++i) {
324  sumContentPrev = sumContent;
325  sumContent += trace[i];
326  if (sumContent >= signal)
327  break;
328  }
329 
330  return ((signal - sumContent) / (sumContent - sumContentPrev) + i + 0.5) *
331  trace.GetBinning();
332 }
333 
334 
335 template<typename T>
336 double
338  const unsigned int bin1, const unsigned int bin2)
339 {
340  if (!TraceAlgorithm::BoundsOk(trace, bin1, bin2))
342 
343  return
344  TimeAtRelativeSignalX(trace, bin1, bin2, 50.) -
345  TimeAtRelativeSignalX(trace, bin1, bin2, 10.);
346 }
347 
348 
349 template<typename T>
350 double
352  const unsigned int bin1, const unsigned int bin2)
353 {
354  if (!TraceAlgorithm::BoundsOk(trace, bin1, bin2))
356 
357  return
358  TimeAtRelativeSignalX(trace, bin1, bin2, 90.) -
359  TimeAtRelativeSignalX(trace, bin1, bin2, 50.);
360 }
361 
362 
363 // explicit instantiations
364 
365 template
366 double
367 TraceAlgorithm::Min(const Trace<int>& trace,
368  const unsigned int bin1, const unsigned int bin2);
369 
370 template
371 double
372 TraceAlgorithm::Max(const Trace<int>& trace,
373  const unsigned int bin1, const unsigned int bin2);
374 
375 template
376 double
377 TraceAlgorithm::Mean(const Trace<int>& trace,
378  const unsigned int bin1, const unsigned int bin2);
379 
380 template
381 double
383  const unsigned int bin1, const unsigned int bin2,
384  const unsigned int SortAlgorithmLimit);
385 
386 template
387 double
388 TraceAlgorithm::RMS(const Trace<int>& trace,
389  const unsigned int bin1, const unsigned int bin2);
390 
391 template
392 double
394  const unsigned int bin1, const unsigned int bin2);
395 
396 template
397 double
399  const unsigned int bin1, const unsigned int bin2);
400 
401 template
402 double
404  const unsigned int bin1, const unsigned int bin2);
405 
406 template
407 double
408 TraceAlgorithm::Sum(const Trace<int>& trace,
409  const unsigned int bin1, const unsigned int bin2);
410 
411 template
412 double
414  const unsigned int bin1, const unsigned int bin2);
415 
416 template
417 double
419  const unsigned int bin1, const unsigned int bin2,
420  const double percent);
421 
422 template
423 double
425  const unsigned int bin1, const unsigned int bin2);
426 
427 template
428 double
430  const unsigned int bin1, const unsigned int bin2);
431 
432 template
433 double
435  const unsigned int bin1, const unsigned int bin2);
436 
437 template
438 double
440  const unsigned int bin1, const unsigned int bin2);
441 
442 template
443 double
445  const unsigned int bin1, const unsigned int bin2);
446 
447 template
448 double
450  const unsigned int bin1, const unsigned int bin2,
451  const unsigned int sortAlgorithmLimit);
452 
453 template
454 double
456  const unsigned int bin1, const unsigned int bin2);
457 
458 template
459 double
461  const unsigned int bin1, const unsigned int bin2);
462 
463 template
464 double
466  const unsigned int bin1, const unsigned int bin2);
467 
468 template
469 double
471  const unsigned int bin1, const unsigned int bin2);
472 
473 template
474 double
476  const unsigned int bin1, const unsigned int bin2);
477 
478 template
479 double
481  const unsigned int bin1, const unsigned int bin2);
482 
483 template
484 double
486  const unsigned int bin1, const unsigned int bin2,
487  const double percent);
488 
489 template
490 double
492  const unsigned int bin1, const unsigned int bin2);
493 
494 template
495 double
497  const unsigned int bin1, const unsigned int bin2);
static double Max(const Trace< T > &trace, const unsigned int bin1, const unsigned int bin2)
Evaluate the maximum of trace between bin1 and bin2.
static double ShapeParameter(const Trace< T > &trace, const unsigned int bin1, const unsigned int bin2)
Evaluate the shape parameter between bin1 and bin2.
SizeType GetStop() const
Get valid data stop bin.
Definition: Trace.h:148
void swap(utl::TabulatedFunction &t1, utl::TabulatedFunction &t2)
static double Mean(const Trace< T > &trace, const unsigned int bin1, const unsigned int bin2)
Evaluate the mean of trace between bin1 and bin2.
static double FallTime(const Trace< T > &trace, unsigned int bin1, unsigned int bin2)
double GetBinning() const
size of one slot
Definition: Trace.h:138
constexpr double percent
Definition: AugerUnits.h:283
static double Median(const Trace< T > &trace, const unsigned int bin1, const unsigned int bin2, const unsigned int sortAlgorithmLimit=40)
Evaluate the median of trace between bin1 and bin2.
#define U
static bool BoundsOk(const Trace< T > &trace, const unsigned int bin1, const unsigned int bin2)
constexpr double nanosecond
Definition: AugerUnits.h:143
static double RMS(const Trace< T > &trace, const unsigned int bin1, const unsigned int bin2)
SizeType GetSize() const
Definition: Trace.h:156
static double RootMeanSquare(const Trace< T > &trace, const unsigned int bin1, const unsigned int bin2)
Evaluate the RootMeanSquare of trace between bin1 and bin2.
static double Centroid(const Trace< T > &trace, const unsigned int bin1, const unsigned int bin2)
static double StandardDeviation(const Trace< T > &trace, const unsigned int bin1, const unsigned int bin2)
Evaluate the StandardDeviation of trace between bin1 and bin2.
Template class for a FADC data or calibrated data container. Use the typedefs (TraceD, TraceI, etc.) defined in Trace-fwd.h.
Definition: Trace-fwd.h:19
Exception thrown when trying to access invalid bounds in Trace.
static double RiseTime(const Trace< T > &trace, const unsigned int bin1, const unsigned int bin2)
double Mean(const std::vector< double > &v)
Definition: Functions.h:31
static double Min(const Trace< T > &trace, const unsigned int bin1, const unsigned int bin2)
Evaluate the minimum of trace between bin1 and bin2.
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
static double Sum(const Trace< T > &trace, const unsigned int bin1, const unsigned int bin2)
Evaluate the sum of bins bin1 thru bin2.
static double TimeAtRelativeSignalX(const Trace< T > &trace, const unsigned int bin1, const unsigned int bin2, const double percent)

, generated on Tue Sep 26 2023.