Orfeo Toolbox  3.16
itkGaussianDistribution.cxx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkGaussianDistribution.cxx,v $
5  Language: C++
6  Date: $Date: 2009-08-07 15:27:37 $
7  Version: $Revision: 1.4 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  This software is distributed WITHOUT ANY WARRANTY; without even
13  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
17 
19 #include "itkNumericTraits.h"
20 #include "vnl/vnl_math.h"
21 #include "vnl/vnl_erf.h"
22 
23 namespace itk {
24 namespace Statistics {
25 
28 {
29  m_Parameters = ParametersType(2);
30  m_Parameters[0] = 0.0;
31  m_Parameters[1] = 1.0;
32 }
33 
34 
35 double
37 ::GetMean() const
38 {
39  if (m_Parameters.GetSize() == 2)
40  {
41  return m_Parameters[0];
42  }
43  else
44  {
45  InvalidArgumentError excep(__FILE__, __LINE__);
46  ::itk::OStringStream message;
47  message << "itk::ERROR: " << this->GetNameOfClass()
48  << "(" << this << "): "
49  << "Invalid number of parameters to describe distribution.";
50  excep.SetDescription(message.str());
51  excep.SetLocation(ITK_LOCATION);
52  throw excep;
53  return 0.0;
54  }
55 }
56 
57 void
59 ::SetMean(double mean)
60 {
61  bool modified=false;
62 
63  if (m_Parameters.GetSize() > 0)
64  {
65  if (m_Parameters[0] != mean)
66  {
67  modified = true;
68  }
69  }
70 
71  if (m_Parameters.GetSize() != 2)
72  {
73  bool cache = false;
74  double t = 1.0;
75 
76  // cache current variance if there is one
77  if (m_Parameters.GetSize() > 1)
78  {
79  t = m_Parameters[1];
80  cache = true;
81  }
82 
83  // create a parameters array of the right length
84  m_Parameters = ParametersType(2);
85 
86  // reapply variance if there was one, otherwise use a default value
87  if (cache)
88  {
89  m_Parameters[1] = t;
90  }
91  else
92  {
93  m_Parameters[1] = 1.0;
94  }
95 
96  modified = true;
97  }
98 
99  m_Parameters[0] = mean;
100 
101  if (modified)
102  {
103  this->Modified();
104  }
105 }
106 
107 double
110 {
111  if (m_Parameters.GetSize() == 2)
112  {
113  return m_Parameters[1];
114  }
115  else
116  {
117  InvalidArgumentError excep(__FILE__, __LINE__);
118  ::itk::OStringStream message;
119  message << "itk::ERROR: " << this->GetNameOfClass()
120  << "(" << this << "): "
121  << "Invalid number of parameters to describe distribution.";
122  excep.SetDescription(message.str());
123  excep.SetLocation(ITK_LOCATION);
124  throw excep;
125  return 0.0;
126  }
127 }
128 
129 void
131 ::SetVariance(double variance)
132 {
133  bool modified = false;
134 
135  if (m_Parameters.GetSize() > 1)
136  {
137  if (m_Parameters[1] != variance)
138  {
139  modified = true;
140  }
141  }
142 
143  if (m_Parameters.GetSize() != 2)
144  {
145  bool cache = false;
146  double t = 0.0;
147 
148  // cache current mean if there is one
149  if (m_Parameters.GetSize() > 0)
150  {
151  t = m_Parameters[0];
152  cache = true;
153  }
154 
155  // create a parameters array of the right length
156  m_Parameters = ParametersType(2);
157 
158  // reapply mean if there was one, otherwise use a default value
159  if (cache)
160  {
161  m_Parameters[0] = t;
162  }
163  else
164  {
165  m_Parameters[0] = 0.0;
166  }
167 
168  modified = true;
169  }
170 
171  m_Parameters[1] = variance;
172 
173  if (modified)
174  {
175  this->Modified();
176  }
177 }
178 
179 
180 double
182 ::PDF(double x)
183 {
184  return vnl_math::one_over_sqrt2pi * vcl_exp(-0.5*x*x);
185 }
186 
187 double
189 ::PDF(double x, double mean, double variance)
190 {
191  double xminusmean = x - mean;
192 
193  return (vnl_math::one_over_sqrt2pi / vcl_sqrt(variance))
194  * vcl_exp(-0.5*xminusmean*xminusmean / variance);
195 }
196 
197 double
199 ::PDF(double x, const ParametersType& p)
200 {
201  // verify the parameter vector length
202  if (p.GetSize() == 2)
203  {
204  return PDF(x, p[0], p[1]);
205  }
206  else
207  {
208  InvalidArgumentError excep(__FILE__, __LINE__);
209  ::itk::OStringStream message;
210  message << "itk::ERROR: "
211  << "GaussianDistribution: "
212  << "Invalid number of parameters to describe distribution.";
213  excep.SetDescription(message.str());
214  excep.SetLocation(ITK_LOCATION);
215  throw excep;
216  return 0.0;
217  }
218 }
219 
220 double
222 ::CDF(double x)
223 {
224  return 0.5 * (vnl_erf(vnl_math::sqrt1_2 * x) + 1.0);
225 }
226 
227 
228 double
230 ::CDF(double x, double mean, double variance)
231 {
232  // convert to zero mean unit variance
233  double u = (x - mean) / vcl_sqrt(variance);
234 
235  return 0.5 * (vnl_erf(vnl_math::sqrt1_2 * u) + 1.0);
236 }
237 
238 
239 double
241 ::CDF(double x, const ParametersType& p)
242 {
243  // verify the parameter vector length
244  if (p.GetSize() == 2)
245  {
246  return GaussianDistribution::CDF(x, p[0], p[1]);
247  }
248  else
249  {
250  InvalidArgumentError excep(__FILE__, __LINE__);
251  ::itk::OStringStream message;
252  message << "itk::ERROR: "
253  << "GaussianDistribution: "
254  << "Invalid number of parameters to describe distribution.";
255  excep.SetDescription(message.str());
256  excep.SetLocation(ITK_LOCATION);
257  throw excep;
258  return 0.0;
259  }
260 }
261 
262 double
264 ::InverseCDF(double p)
265 {
266  double dp , dx , dt , ddq , dq;
267  int newt;
268 
269  dp = (p <= 0.5) ? (p) : (1.0-p); /* make between 0 and 0.5 */
270 
271  // if original value is invalid, return +infinity or -infinity
272  // changed from original code to reflect the fact that the
273  // the inverse of P(x) not Q(x) is desired.
274  //
275  // Original line: used for inverse of Q(x)
276  // if( dp <= 0.0 ){ dx = 13.0; return ( (p <= 0.5) ? (dx) : (-dx) ); }
277 
278  // replaced with this if construct for the inverse of P(x)
279  if (p <= 0.0)
280  {
281  return itk::NumericTraits<double>::NonpositiveMin();
282  }
283  else if (p >= 1.0)
284  {
285  return itk::NumericTraits<double>::max();
286  }
287 
288 
291  dt = vcl_sqrt( -2.0 * vcl_log(dp) );
292  dx = dt
293  - ((.010328e+0*dt + .802853e+0)*dt + 2.515517e+0)
294  /(((.001308e+0*dt + .189269e+0)*dt + 1.432788e+0)*dt + 1.e+0);
295 
298  for( newt=0; newt < 3; newt++ )
299  {
300  dq = 0.5e+0 * vnl_erfc( dx * vnl_math::sqrt1_2 ) - dp;
301  ddq = vcl_exp( -0.5e+0 * dx * dx ) / 2.506628274631000e+0;
302  dx = dx + dq / ddq;
303  }
304 
305  // original line when computing the inverse of Q(x)
306  // return ( (p <= 0.5) ? (dx) : (-dx) ); /* return with correct sign */
307  //
308  // Note that P(-x) = Q(x), so whatever x was calculated for Q(x) = p,
309  // we simply need to return the negative of x to get P(xp) = p.
310  //
311  dx = ( (p <= 0.5) ? (-dx) : (dx) ); // return with correct sign
312 
313  return dx;
314 }
315 
316 
317 double
319 ::InverseCDF(double p, double mean, double variance)
320 {
321  double x = GaussianDistribution::InverseCDF(p);
322 
323  // apply the mean and variance to provide the value for the
324  // prescribed Gaussian
325  x = x*vcl_sqrt(variance) + mean;
326 
327  return x;
328 }
329 
330 double
332 ::InverseCDF(double p, const ParametersType& params)
333 {
334  // verify the parameter vector length
335  if (params.GetSize() == 2)
336  {
337  return GaussianDistribution::InverseCDF(p, params[0], params[1]);
338  }
339  else
340  {
341  InvalidArgumentError excep(__FILE__, __LINE__);
342  ::itk::OStringStream message;
343  message << "itk::ERROR: "
344  << "GaussianDistribution: "
345  << "Invalid number of parameters to describe distribution.";
346  excep.SetDescription(message.str());
347  excep.SetLocation(ITK_LOCATION);
348  throw excep;
349  return 0.0;
350  }
351 }
352 
353 double
355 ::EvaluatePDF(double x) const
356 {
357  if (m_Parameters.GetSize() == 2)
358  {
359  if (m_Parameters[0] == 0.0 && m_Parameters[1] == 1.0)
360  {
361  return GaussianDistribution::PDF(x);
362  }
363 
364  return GaussianDistribution::PDF(x, m_Parameters[0], m_Parameters[1]);
365  }
366  else
367  {
368  InvalidArgumentError excep(__FILE__, __LINE__);
369  ::itk::OStringStream message;
370  message << "itk::ERROR: " << this->GetNameOfClass()
371  << "(" << this << "): "
372  << "Invalid number of parameters to describe distribution.";
373  excep.SetDescription(message.str());
374  excep.SetLocation(ITK_LOCATION);
375  throw excep;
376  return 0.0;
377  }
378 }
379 
380 double
382 ::EvaluatePDF(double x, const ParametersType&p) const
383 {
384  if (p.GetSize() == 2)
385  {
386  if (p[0] == 0.0 && p[1] == 1.0)
387  {
388  return GaussianDistribution::PDF(x);
389  }
390 
391  return GaussianDistribution::PDF(x, p[0], p[1]);
392  }
393  else
394  {
395  InvalidArgumentError excep(__FILE__, __LINE__);
396  ::itk::OStringStream message;
397  message << "itk::ERROR: " << this->GetNameOfClass()
398  << "(" << this << "): "
399  << "Invalid number of parameters to describe distribution.";
400  excep.SetDescription(message.str());
401  excep.SetLocation(ITK_LOCATION);
402  throw excep;
403  return 0.0;
404  }
405 }
406 
407 double
409 ::EvaluatePDF(double x, double mean, double variance) const
410 {
411  if (mean == 0.0 && variance == 1.0)
412  {
413  return GaussianDistribution::PDF(x);
414  }
415 
416  return GaussianDistribution::PDF(x, mean, variance);
417 }
418 
419 
420 double
422 ::EvaluateCDF(double x) const
423 {
424  if (m_Parameters.GetSize() == 2)
425  {
426  if (m_Parameters[0] == 0.0 && m_Parameters[1] == 1.0)
427  {
428  return GaussianDistribution::CDF(x);
429  }
430 
431  return GaussianDistribution::CDF(x, m_Parameters[0], m_Parameters[1]);
432  }
433  else
434  {
435  InvalidArgumentError excep(__FILE__, __LINE__);
436  ::itk::OStringStream message;
437  message << "itk::ERROR: " << this->GetNameOfClass()
438  << "(" << this << "): "
439  << "Invalid number of parameters to describe distribution.";
440  excep.SetDescription(message.str());
441  excep.SetLocation(ITK_LOCATION);
442  throw excep;
443  return 0.0;
444  }
445 }
446 
447 double
449 ::EvaluateCDF(double x, const ParametersType& p) const
450 {
451  if (p.GetSize() == 2)
452  {
453  if (p[0] == 0.0 && p[1] == 1.0)
454  {
455  return GaussianDistribution::CDF(x);
456  }
457 
458  return GaussianDistribution::CDF(x, p[0], p[1]);
459  }
460  else
461  {
462  InvalidArgumentError excep(__FILE__, __LINE__);
463  ::itk::OStringStream message;
464  message << "itk::ERROR: " << this->GetNameOfClass()
465  << "(" << this << "): "
466  << "Invalid number of parameters to describe distribution.";
467  excep.SetDescription(message.str());
468  excep.SetLocation(ITK_LOCATION);
469  throw excep;
470  return 0.0;
471  }
472 }
473 
474 double
476 ::EvaluateCDF(double x, double mean, double variance) const
477 {
478  if (mean == 0.0 && variance == 1.0)
479  {
480  return GaussianDistribution::CDF(x);
481  }
482 
483  return GaussianDistribution::CDF(x, mean, variance);
484 }
485 
486 
487 double
489 ::EvaluateInverseCDF(double p) const
490 {
491  if (m_Parameters.GetSize() == 2)
492  {
493  if (m_Parameters[0] == 0.0 && m_Parameters[1] == 1.0)
494  {
496  }
497 
498  return GaussianDistribution::InverseCDF(p,m_Parameters[0],m_Parameters[1]);
499  }
500  else
501  {
502  InvalidArgumentError excep(__FILE__, __LINE__);
503  ::itk::OStringStream message;
504  message << "itk::ERROR: " << this->GetNameOfClass()
505  << "(" << this << "): "
506  << "Invalid number of parameters to describe distribution.";
507  excep.SetDescription(message.str());
508  excep.SetLocation(ITK_LOCATION);
509  throw excep;
510  return 0.0;
511  }
512 }
513 
514 double
516 ::EvaluateInverseCDF(double p, const ParametersType& params) const
517 {
518  if (params.GetSize() == 2)
519  {
520  if (params[0] == 0.0 && params[1] == 1.0)
521  {
523  }
524 
525  return GaussianDistribution::InverseCDF(p,params[0],params[1]);
526  }
527  else
528  {
529  InvalidArgumentError excep(__FILE__, __LINE__);
530  ::itk::OStringStream message;
531  message << "itk::ERROR: " << this->GetNameOfClass()
532  << "(" << this << "): "
533  << "Invalid number of parameters to describe distribution.";
534  excep.SetDescription(message.str());
535  excep.SetLocation(ITK_LOCATION);
536  throw excep;
537  return 0.0;
538  }
539 }
540 
541 double
543 ::EvaluateInverseCDF(double p, double mean, double variance) const
544 {
545  if (mean == 0.0 && variance == 1.0)
546  {
548  }
549 
550  return GaussianDistribution::InverseCDF(p,mean,variance);
551 }
552 
553 void
555 ::PrintSelf(std::ostream& os, Indent indent) const
556 {
557  Superclass::PrintSelf(os,indent);
558 
559  if (m_Parameters.GetSize() > 0)
560  {
561  os << indent << "Mean: " << m_Parameters[0] << std::endl;
562  }
563  else
564  {
565  os << indent << "Mean: (unknown)" << std::endl;
566  }
567 
568  if (m_Parameters.GetSize() > 1)
569  {
570  os << indent << "Variance: " << m_Parameters[1] << std::endl;
571  }
572  else
573  {
574  os << indent << "Variance: (unknown)" << std::endl;
575  }
576 }
577 
578 } // end of namespace Statistics
579 } // end namespace itk

Generated at Sat Feb 2 2013 23:38:54 for Orfeo Toolbox with doxygen 1.8.1.1