QuadraticFitter.h
Go to the documentation of this file.
1 #ifndef _utl_QuadraticFitter_h_
2 #define _utl_QuadraticFitter_h_
3 
4 #include <cmath>
5 
6 #include <utl/Math.h>
7 #include <utl/Histogram.h>
8 #include <utl/AugerException.h>
9 #include <utl/QuadraticFitData.h>
10 
11 
12 namespace utl {
13 
15  public:
16  static double GetError(const double& value)
17  { return std::sqrt(value); }
18 
19  static double GetError2(const double& value)
20  { return value; }
21  };
22 
23 
24  class FlatErrors {
25  public:
26  static double GetError(const double& /*value*/) { return 1; }
27  static double GetError2(const double& /*value*/) { return 1; }
28  };
29 
30 
38  template<class Histogram, class ErrorPolicy /*= utl::PoissonianErrors*/>
39  class QuadraticFitter {
40  public:
42  : fStartBin(0), fStopBin(h.GetNBins()), fHistogram(h) { }
43 
45  const int startBin, const int stopBin)
46  : fStartBin(startBin), fStopBin(stopBin), fHistogram(h)
47  {
48  if (startBin < 0 || stopBin - startBin < 3 || stopBin >= int(h.GetNBins()))
49  throw utl::OutOfBoundException("start, stop bin out of bounds of histogram");
50  }
51 
53  const double xStart, const double xStop)
54  : fHistogram(h)
55  {
56  int start = h.GetBinIndex(xStart);
57  if (start == Histogram::eUnderflow)
58  start = 0;
59  fStartBin = start;
60  int stop = h.GetBinIndex(xStop);
61  if (stop == Histogram::eOverflow)
62  stop = h.GetNBins() - 1;
63  fStopBin = stop;
64  if (start < 0 || stop < 0 || stop - start < 3)
65  throw utl::OutOfBoundException("illegal start or stop, or not enough bins to fit");
66  }
67 
68  double
70  {
71  MakeSums();
72  NeedsCoeficient<1>();
73  NeedsCoeficient<2>();
74  return fMeanX - fK[1] / (2 * fK[2]);
75  }
76 
77  double
78  GetExtremePosition(double& posError, int& ndof)
79  {
80  const double pos = GetExtremePosition(); // delivers: 1, 2
81 
82  const double sigma2k1 = Sqr(fX2Sum) - fX0Sum * fX4Sum; // /det
83  const double sigma2k2 = Sqr(fX1Sum) - fX0Sum * fX2Sum; // /det
84  const double covk1k2 = fX0Sum * fX3Sum - fX1Sum * fX2Sum; // /det
85  const double k22 = Sqr(fK[2]); // /det^2
86 
88 
89  posError =
90  0.5 * sqrt(fDet*(sigma2k1 + (pos - fMeanX)*covk1k2 + sigma2k2*Sqr(fK[1])/k22) / k22);
91 
92  ndof = fN - 3;
93 
94  return pos;
95  }
96 
97  double
98  GetExtremePosition(double& posError, double& chi2, int& ndof)
99  {
100  const double pos = GetExtremePosition(posError, ndof); // delivers: det, 1, 2
101 
102  NeedsCoeficient<0>();
103 
104  chi2 = ((Sqr(fK[0]) * fX0Sum + 2*fK[0]*fK[1] * fX1Sum + (Sqr(fK[1]) + 2*fK[0]*fK[2]) * fX2Sum
105  + 2*fK[1]*fK[2] * fX3Sum + Sqr(fK[2]) * fX4Sum) / Sqr(fDet)
106  - 2 * (fK[0] * fX0YSum + fK[1] * fX1YSum + fK[2] * fX2YSum) / fDet + fX0Y2Sum);
107 
108  return pos;
109  }
110 
111  double
112  GetExtremePosition(double& posError, double& chi2, int& ndof, double polynomialCoeff[3])
113  {
114  const double pos = GetExtremePosition(posError, chi2, ndof); // delivers: det, 0, 1, 2
115  // this gives expansion around the fMeanX
116  for (int i = 0; i < 3; ++i)
117  polynomialCoeff[i] = fK[i] / fDet;
118  // polynomial coefficient are exported as expansion around the position of the extreme
119  polynomialCoeff[0] +=
120  fMeanY -
121  polynomialCoeff[1] * fMeanX +
122  polynomialCoeff[2] * (Sqr(fMeanX) - Sqr(pos));
123  polynomialCoeff[1] = 0;
124  // polynomialCoeff[2] is the same
125  return pos;
126  }
127 
128  void
130  {
133  fit.fExtremePosition =
135  }
136 
137  private:
138  void
140  {
141  fN = fStopBin - fStartBin;
142 
143  fMeanX = fMeanY = 0;
144  for (unsigned int i = fStartBin; i < fStopBin; ++i) {
147  }
148  fMeanX /= fN;
149  fMeanY /= fN;
150 
151  fX0Sum = fX1Sum = fX2Sum = fX3Sum = fX4Sum =
152  fX0YSum = fX1YSum = fX2YSum = fX0Y2Sum = 0;
153 
154  for (unsigned int i = fStartBin; i < fStopBin; ++i) {
155  const double x = fHistogram.GetBinCenter(i) - fMeanX;
156  const double raw = fHistogram.GetBin(i);
157  const double invSigma2 = Sqr(fHistogram.GetBinSize(i)) / ErrorPolicy::GetError2(raw);
158  const double y = fHistogram.GetBinAverage(i) - fMeanY;
159  fX0Sum += invSigma2;
160  const double xs = x * invSigma2;
161  fX1Sum += xs;
162  const double ys = y * invSigma2;
163  fX0YSum += ys;
164  fX0Y2Sum += y * ys;
165  fX1YSum += x * ys;
166  const double x2s = x * xs;
167  fX2Sum += x2s;
168  fX2YSum += y * x2s;
169  const double x3s = x * x2s;
170  fX3Sum += x3s;
171  fX4Sum += x * x3s;
172  }
173  }
174 
175  void
177  {
178  if (!fDet)
179  fDet = Sqr(fX2Sum) * fX2Sum + fX0Sum * Sqr(fX3Sum)
180  + Sqr(fX1Sum) * fX4Sum
181  - fX2Sum * (2 * fX1Sum * fX3Sum + fX0Sum * fX4Sum);
182  }
183 
184  template<unsigned int index>
185  void
187  {
188  switch (index) {
189  case 0:
190  if (!fK[0])
191  fK[0] = Sqr(fX3Sum) * fX0YSum + fX4Sum * (fX1Sum * fX1YSum - fX2Sum * fX0YSum)
192  + Sqr(fX2Sum) * fX2YSum - fX3Sum * (fX2Sum * fX1YSum + fX1Sum * fX2YSum); // /det
193  break;
194  case 1:
195  if (!fK[1])
196  fK[1] = fX4Sum * (fX1Sum * fX0YSum - fX0Sum * fX1YSum) + Sqr(fX2Sum) * fX1YSum
197  + fX0Sum * fX3Sum * fX2YSum - fX2Sum * (fX3Sum * fX0YSum + fX1Sum * fX2YSum); // /det
198  break;
199  case 2:
200  if (!fK[2])
201  fK[2] = Sqr(fX2Sum) * fX0YSum + fX3Sum * (fX0Sum * fX1YSum - fX1Sum * fX0YSum)
202  + Sqr(fX1Sum) * fX2YSum - fX2Sum * (fX1Sum * fX1YSum + fX0Sum * fX2YSum); // /det
203  break;
204  }
205  }
206 
207  unsigned int fStartBin = 0;
208  unsigned int fStopBin = 0;
210 
211  double fMeanX = 0;
212  double fMeanY = 0;
213  double fX0Sum = 0;
214  double fX1Sum = 0;
215  double fX2Sum = 0;
216  double fX3Sum = 0;
217  double fX4Sum = 0;
218  double fX0YSum = 0;
219  double fX1YSum = 0;
220  double fX2YSum = 0;
221  double fX0Y2Sum = 0;
222  int fN = 0;
223  double fDet = 0;
224  double fK[3] = { 0 };
225  };
226 
227 
228  // convinience makers
229  template<class Histogram, class ErrorPolicy>
230  inline
231  QuadraticFitter<Histogram, ErrorPolicy>
232  MakeQuadraticFitter(const Histogram& h, const ErrorPolicy /*ep*/)
233  {
235  }
236 
237  template<class Histogram>
238  inline
239  QuadraticFitter<Histogram>
241  {
242  return QuadraticFitter<Histogram>(h);
243  }
244 
245 
246  template<class Histogram, typename Type, class ErrorPolicy>
247  inline
248  QuadraticFitter<Histogram, ErrorPolicy>
250  const Type xStart, const Type xStop,
251  [[maybe_unused]] const ErrorPolicy ep)
252  {
253  return QuadraticFitter<Histogram, ErrorPolicy>(h, xStart, xStop);
254  }
255 
256  template<class Histogram, typename Type>
257  inline
258  QuadraticFitter<Histogram>
260  const Type xStart, const Type xStop)
261  {
262  return QuadraticFitter<Histogram>(h, xStart, xStop);
263  }
264 
265 }
266 
267 
268 #endif
Histogram.
Definition: Histogram.h:151
int raw
Definition: dump1090.h:270
constexpr T Sqr(const T &x)
Holds result of the quadratic fit.
double GetExtremePosition(double &posError, double &chi2, int &ndof)
QuadraticFitter(const Histogram &h)
const Histogram & fHistogram
double GetBinAverage(const size_t i) const
Definition: Histogram.h:224
static double GetError2(const double &)
Exception for reporting variable out of valid range.
QuadraticFitter(const Histogram &h, const double xStart, const double xStop)
const BinType & GetBin(const size_t i) const
Definition: Histogram.h:222
double GetExtremePosition(double &posError, double &chi2, int &ndof, double polynomialCoeff[3])
static double GetError2(const double &value)
QuadraticFitter< Histogram, ErrorPolicy > MakeQuadraticFitter(const Histogram &h, const ErrorPolicy)
static double GetError(const double &value)
double GetExtremePosition(double &posError, int &ndof)
Type
The type of file that we are acutally opening.
Definition: IoCodes.h:33
static double GetError(const double &)
QuadraticFitter(const Histogram &h, const int startBin, const int stopBin)
void GetFitData(QuadraticFitData &fit)
double GetBinCenter(const size_t bin) const
Definition: Histogram.h:227

, generated on Tue Sep 26 2023.