TabulatedPDF.cc
Go to the documentation of this file.
1 #include "TabulatedPDF.h"
2 
3 #include <utl/AugerException.h>
4 #include <utl/ErrorLogger.h>
5 
6 #include <sstream>
7 #include <cmath>
8 #include <cfloat>
9 #include <algorithm>
10 
11 using namespace std;
12 using namespace utl;
13 using namespace tls;
14 
16 
17 TabulatedPDF::TabulatedPDF()
18 {
19 }
20 
21 TabulatedPDF::TabulatedPDF(const TabulatedPDF& src)
22 { *this = src; }
23 
24 TabulatedPDF::TabulatedPDF(
25  double xmin, double xstep, const std::vector< double > &yValues)
26 {
27  FillTable(xmin, xstep, yValues);
28 }
29 
31 TabulatedPDF::operator=(const TabulatedPDF& src)
32 {
33  fXMin = src.fXMin;
34  fXStep = src.fXStep;
35  fY = src.fY;
36  fYSum = src.fYSum;
37  return *this;
38 }
39 
40 void
41 TabulatedPDF::FillTable(
42  double xmin, double xstep, const Array& yValues)
43 {
44  const unsigned int size = yValues.size();
45 
46  Clear();
47 
48  fXMin = xmin;
49  fXStep = xstep;
50  for (unsigned int i=0;i<size;++i) PushBack(yValues[i]);
51  Normalise();
52 }
53 
54 void
55 TabulatedPDF::PushBack(double y)
56 {
57  const unsigned int size = fY.size();
58 
59  if (y < 0.0) {
60  ostringstream msg;
61  msg << "Value " << y << " at x = " << fXMin+(size-1)*fXStep << " is not a valid probability!";
62  ERROR(msg);
63  y = 0.0;
64  }
65 
66  if (size==0)
67  fYSum.push_back(0.5*y*fXStep);
68  else {
69  const double ysum = fYSum.back() + 0.5*(y+fY.back())*fXStep;
70  fYSum.push_back(ysum);
71  }
72 
73  fY.push_back(y);
74 }
75 
76 void
77 TabulatedPDF::Clear()
78 {
79  fXMin = 0.0;
80  fXStep = 0.0;
81  Array().swap(fY);
82  Array().swap(fYSum);
83 }
84 
85 void
86 TabulatedPDF::Normalise()
87 {
88  if (fYSum.back()==1.0) return;
89 
90  const double factor = 1./fYSum.back();
91 
92  for (unsigned int i=0;i<fY.size();++i) {
93  fY[i] *= factor;
94  fYSum[i] *= factor;
95  }
96 }
97 
100 double
101 TabulatedPDF::Density(double x)
102  const
103 {
104  const unsigned int size = fY.size();
105 
106  if (!size) throw NonExistentComponentException("No points in table.");
107 
108  if (size == 1)
109  return fY[0];
110 
111  if (x < fXMin-fXStep/2)
112  return 0.0;
113  if (x < fXMin)
114  return fY[0];
115  else if (x > fXMin + (size-1)*fXStep)
116  return 0.0;
117 
118  unsigned int index = static_cast<unsigned int>((x-fXMin)/fXStep);
119  const double x1 = fXMin+index*fXStep;
120  const double& dx = fXStep;
121  const double y1 = fY[index];
122  if (x1 == x) return y1;
123  ++index;
124  const double y2 = fY[index];
125 
126  double prob = y1 + (y2 - y1)*(x - x1)/dx;
127  return prob;
128 }
129 
132 double
133 TabulatedPDF::Integral(double xmin, double xmax)
134  const
135 {
136  const unsigned int size = fY.size();
137 
138  if (!size) throw NonExistentComponentException("No points in table.");
139 
140  if (size == 1)
141  return fY[0];
142 
143  // primitive out of bounds handling
144  if (xmin > fXMin + (size-1)*fXStep)
145  return 0.0;
146  if (xmax < fXMin)
147  return 0.0;
148  if (xmin < fXMin)
149  xmin = fXMin;
150  if (xmax > fXMin + (size-1)*fXStep)
151  xmax = fXMin + (size-2)*fXStep;
152 
153  const unsigned int iBegin = static_cast<unsigned int>((xmin-fXMin)/fXStep);
154  const unsigned int iEnd = static_cast<unsigned int>((xmax-fXMin)/fXStep)-1;
155  const double& dx = fXStep;
156  const double x1l = fXMin + iBegin*fXStep;
157  const double y1l = fYSum[iBegin];
158  const double y1u = fYSum[iBegin+1];
159 
160  const double x2l = fXMin + iEnd*fXStep;
161  const double y2l = fYSum[iEnd];
162  const double y2u = fYSum[iEnd+1];
163 
164  const double p1 = y1l + (y1u - y1l)*(xmin - x1l)/dx;
165  const double p2 = y2l + (y2u - y2l)*(xmax - x2l)/dx;
166  return p2-p1;
167 }
168 
169 double
170 TabulatedPDF::Moment(unsigned short order, double xmin, double xmax)
171  const
172 {
173  const unsigned int size = fY.size();
174 
175  if (!size) throw NonExistentComponentException("No points in table.");
176 
177  if (size==1)
178  return fY[0]*pow(fXMin,order);
179 
180  // primitive out of bounds handling
181  if (xmin < fXMin)
182  xmin = fXMin;
183  else if (xmin > fXMin + (size-1)*fXStep)
184  return 0.0;
185  if (xmax < fXMin)
186  return 0.0;
187  else if (xmax > fXMin + (size-1)*fXStep)
188  xmax = fXMin + (size-1)*fXStep;
189 
190  const unsigned int iBegin = static_cast<unsigned int>((xmin-fXMin)/fXStep);
191  const unsigned int iEnd = static_cast<unsigned int>((xmax-fXMin)/fXStep);
192 
193  // simpson's rule for integration
194  // formula R = h ( I0 + 4 I1 + 2 I2 + 4 I3 + ... + 2 In-2 + 4 In-1 + In) / 3
195  double mom = 0;
196  double sum = 0;
197 
198  // first term
199  const double& h = fXStep;
200  mom = h*fY[iBegin]*pow(fXMin+iBegin*fXStep,order);
201  sum = h*fY[iBegin];
202 
203  // intermediate terms
204  bool iloop = true;
205  for (unsigned int i=iBegin+1;i<iEnd;++i)
206  {
207  const int weight = iloop ? 4:2 ;
208  iloop=!iloop;
209  mom += weight*h*fY[i]*pow(fXMin+i*fXStep,order);
210  sum += weight*h*fY[i];
211  }
212 
213  // last term
214  mom += h*fY[iEnd-1]*pow(fXMin+iEnd*fXStep,order);
215  sum += h*fY[iEnd-1];
216 
217  return mom/sum;
218 }
219 
220 double
221 TabulatedPDF::Variance(double xmin, double xmax)
222  const
223 {
224  const unsigned int size = fY.size();
225 
226  if (!size) throw NonExistentComponentException("No points in table.");
227 
228  if (size==1)
229  return 0;
230 
231  // primitive out of bounds handling
232  if (xmin < fXMin)
233  xmin = fXMin;
234  else if (xmin > fXMin + (size-1)*fXStep)
235  return 0.0;
236  if (xmax < fXMin)
237  return 0.0;
238  else if (xmax > fXMin + (size-1)*fXStep)
239  xmax = fXMin + (size-1)*fXStep;
240 
241  const unsigned int iBegin = static_cast<unsigned int>((xmin-fXMin)/fXStep);
242  const unsigned int iEnd = static_cast<unsigned int>((xmax-fXMin)/fXStep);
243 
244  // simpson's rule for integration
245  // formula R = h ( I0 + 4 I1 + 2 I2 + 4 I3 + ... + 2 In-2 + 4 In-1 + In) / 3
246  double mom1 = 0;
247  double mom2 = 0;
248  double sum = 0;
249 
250  // first term
251  const double& h = fXStep;
252  mom1 = h*fY[iBegin]*(fXMin+iBegin*fXStep);
253  mom2 = h*fY[iBegin]*(fXMin+iBegin*fXStep)*(fXMin+iBegin*fXStep);
254  sum = h*fY[iBegin];
255 
256  // intermediate terms
257  bool iloop = true;
258  for (unsigned int i=iBegin+1;i<iEnd;++i)
259  {
260  const int weight = iloop ? 4:2 ;
261  iloop=!iloop;
262  mom1 += weight*h*fY[i]*(fXMin+i*fXStep);
263  mom2 += weight*h*fY[i]*(fXMin+i*fXStep)*(fXMin+i*fXStep);
264  sum += weight*h*fY[i];
265  }
266 
267  // last term
268  mom1 += h*fY[iEnd]*(fXMin+iEnd*fXStep);
269  mom2 += h*fY[iEnd]*(fXMin+iEnd*fXStep)*(fXMin+iEnd*fXStep);
270  sum += h*fY[iEnd];
271 
272  return mom2/sum-pow(mom1/sum,2);
273 }
274 
275 double
276 TabulatedPDF::Quantile(const double psum)
277  const
278 {
279  const unsigned int size = fY.size();
280 
281  if (!size) throw NonExistentComponentException("No points in table.");
282 
283  int index = 0;
284  for (unsigned int i=0;i<size-1;++i)
285  if (fYSum[i] < psum && fYSum[i+1] > psum)
286  { index = i; break; }
287  const double x0 = fXMin+index*fXStep;
288  const double& dx = fXStep;
289  const double& y0 = fYSum[index];
290  const double& y1 = fYSum[index+1];
291  const double quantile = (psum - y0)/(y1-y0)*dx+x0;
292  return quantile;
293 }
Base class for exceptions trying to access non-existing components.
double pow(const double x, const unsigned int i)
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
TabulatedPDF::Array Array
Definition: TabulatedPDF.cc:15
std::vector< double > Array
Definition: TabulatedPDF.h:11

, generated on Tue Sep 26 2023.