ExponentialFitter.h
Go to the documentation of this file.
1 #ifndef _utl_ExponentialFitter_h_
2 #define _utl_ExponentialFitter_h_
3 
4 #include <utl/ExponentialFitData.h>
5 #include <utl/AugerException.h>
6 
7 
8 namespace utl {
9 
17  template<class Histogram>
18  class ExponentialFitter {
19  public:
20  ExponentialFitter(const Histogram& histogram,
21  const int startBin, const int stopBin)
22  : fStartBin(startBin), fStopBin(stopBin), fHistogram(histogram)
23  {
24  if (fStartBin < 0 || fStopBin >= histogram.GetNBins())
25  throw OutOfBoundException("start, stop bins out of bound");
26  if (fStopBin - fStartBin < 2)
27  throw OutOfBoundException("too few data points to fit exponential");
28  }
29 
30  ExponentialFitter(const Histogram& histogram,
31  const double xStart, const double xStop)
32  : fStartBin(histogram.GetBinIndex(xStart)),
33  fStopBin(histogram.GetBinIndex(xStop)),
34  fHistogram(histogram)
35  {
36  if (fStartBin < 0)
37  throw OutOfBoundException("range start error");
38  if (fStopBin - fStartBin < 2)
39  throw OutOfBoundException("range order mismatch");
40  }
41 
42  double
43  GetSlope(double& slopeError, const double offset = 0)
44  {
45  // assumes sigma(y) = sqrt(y) without offset
46  // z = log(y)
47  fSum1 = 0;
48  fSumx = 0;
49  fSumx2 = 0;
50  fSumxz = 0;
51  fSumz = 0;
52  fN = 0;
53  for (int i = fStartBin; i < fStopBin; ++i) {
54  const double counts = fHistogram.GetBin(i);
55  if (counts > 0) {
56  const double width = fHistogram.GetBinSize(i);
57  const double y = (counts - offset) / width;
58  if (y > 0) {
59  const double invSigmaz2 = counts;
60  const double z = log(y);
61  const double x = fHistogram.GetBinCenter(i);
62  fSum1 += invSigmaz2;
63  const double s2x = invSigmaz2 * x;
64  fSumx += s2x;
65  fSumx2 += s2x * x;
66  fSumxz += s2x * z;
67  fSumz += invSigmaz2 * z;
68  ++fN;
69  }
70  }
71  }
72 
73  if (fN > 1) {
74  fDet = fSum1*fSumx2 - Sqr(fSumx);
75  if (fDet) {
76  slopeError = fSum1 / fDet;
77  return (fSum1*fSumxz - fSumx*fSumz) / fDet;
78  }
79  }
80 
81  fDet = slopeError = 0;
82  return 0;
83  }
84 
85  void
86  GetFit(double& amplitude, double& amplitudeError,
87  double& slope, double& slopeError,
88  const double offset = 0)
89  {
90  slope = GetSlope(slopeError, offset);
91  if (fDet) {
92  amplitude = exp((fSumx2*fSumz - fSumx*fSumxz) / fDet);
93  amplitudeError = amplitude * (fSumx2 / fDet);
94  } else {
95  amplitude = 0;
96  amplitudeError = 0;
97  }
98  }
99 
100  void
101  GetFit(double& amplitude, double& amplitudeError,
102  double& slope, double& slopeError,
103  double& chi2, int& ndof,
104  const double offset = 0)
105  {
106  GetFit(amplitude, amplitudeError, slope, slopeError, offset);
107  if (fDet) {
108  const double linOffset = log(amplitude);
109  chi2 = Sqr(linOffset)*fSum1 + Sqr(slope)*fSumx2 + 2*(slope*linOffset*fSumx - linOffset*fSumz - slope*fSumxz);
110  ndof = fN - 2;
111  } else {
112  chi2 = 0;
113  ndof = 0;
114  }
115  }
116 
117  void
118  GetFit(ExponentialFitData& ef, const double offset = 0)
119  {
122  GetFit(ef.fAmplitude, ef.fAmplitudeError, ef.fSlope, ef.fSlopeError, ef.fChi2, ef.fNdof, offset);
123  ef.fOffset = offset;
124  }
125 
126  private:
127  const int fStartBin;
128  const int fStopBin;
130 
131  double fSum1;
132  double fSumx;
133  double fSumx2;
134  double fSumxz;
135  double fSumz;
136  double fDet;
137  int fN;
138  };
139 
140 
141  template<class Histogram, typename T>
142  inline
145  const T& start, const T& stop)
146  {
147  return ExponentialFitter<Histogram>(histogram, start, stop);
148  }
149 
150 
151  template<class Histogram, typename T>
152  inline
153  ExponentialFitter<Histogram>
155  const std::pair<T, T>& startStop)
156  {
157  return ExponentialFitter<Histogram>(histogram, startStop.first, startStop.second);
158  }
159 
160 }
161 
162 #endif
void GetFit(double &amplitude, double &amplitudeError, double &slope, double &slopeError, double &chi2, int &ndof, const double offset=0)
ExponentialFitter(const Histogram &histogram, const int startBin, const int stopBin)
Histogram.
Definition: Histogram.h:151
constexpr T Sqr(const T &x)
Fit exponential function.
Exception for reporting variable out of valid range.
ExponentialFitter(const Histogram &histogram, const double xStart, const double xStop)
const BinType & GetBin(const size_t i) const
Definition: Histogram.h:222
ExponentialFitter< Histogram > MakeExponentialFitter(const Histogram &histogram, const T &start, const T &stop)
void GetFit(ExponentialFitData &ef, const double offset=0)
double GetSlope(double &slopeError, const double offset=0)
const Histogram & fHistogram
void GetFit(double &amplitude, double &amplitudeError, double &slope, double &slopeError, const double offset=0)
double GetBinCenter(const size_t bin) const
Definition: Histogram.h:227

, generated on Tue Sep 26 2023.