contrib/mul/pdf1d/pdf1d_gaussian.cxx
Go to the documentation of this file.
00001 // This is mul/pdf1d/pdf1d_gaussian.cxx
00002 
00003 //:
00004 // \file
00005 // \brief Univariate Gaussian PDF.
00006 // \author Tim Cootes
00007 
00008 #include "pdf1d_gaussian.h"
00009 
00010 #include <vcl_cassert.h>
00011 #include <vcl_string.h>
00012 #include <vcl_cmath.h>
00013 
00014 #include <vnl/vnl_math.h>
00015 #include <pdf1d/pdf1d_gaussian_sampler.h>
00016 #include <pdf1d/pdf1d_sampler.h>
00017 #include <pdf1d/pdf1d_prob_chi2.h>
00018 #include <vnl/vnl_erf.h>
00019 
00020 
00021 //=======================================================================
00022 
00023 pdf1d_gaussian::pdf1d_gaussian()
00024 {
00025   set(0,1);
00026 }
00027 
00028 pdf1d_gaussian::pdf1d_gaussian(double mean, double variance)
00029 {
00030   set(mean,variance);
00031 }
00032 
00033 //=======================================================================
00034 
00035 pdf1d_gaussian::~pdf1d_gaussian()
00036 {
00037 }
00038 
00039 //=======================================================================
00040 
00041 void pdf1d_gaussian::calc_log_k()
00042 {
00043   k_ = 1.0/vcl_sqrt(2*vnl_math::pi*variance());
00044   log_k_ = vcl_log(k_);
00045 }
00046 
00047 //: Initialise with mean and variance (NOT standard deviation)
00048 void pdf1d_gaussian::set(double mean, double var)
00049 {
00050   pdf1d_pdf::set_mean(mean);
00051   pdf1d_pdf::set_variance(var);
00052   sd_ = vcl_sqrt(var);
00053   calc_log_k();
00054 }
00055 
00056 //: Modify just the mean of the distribution
00057 // This functions should only be used by builders.
00058 void pdf1d_gaussian::set_mean(double mean)
00059 {
00060   pdf1d_pdf::set_mean(mean);
00061 }
00062 
00063 
00064 //=======================================================================
00065 
00066 
00067 pdf1d_sampler* pdf1d_gaussian::new_sampler() const
00068 {
00069   pdf1d_gaussian_sampler *i = new pdf1d_gaussian_sampler;
00070   i->set_model(*this);
00071   return i;
00072 }
00073 
00074 //=======================================================================
00075 
00076 
00077   // Probability densities:
00078 double pdf1d_gaussian::log_p(double x) const
00079 {
00080   double v = variance();
00081   assert(v>0);
00082 
00083   double dx = x-mean();
00084   return log_k_ - 0.5*dx*dx/v;
00085 }
00086 
00087 //: Cumulative Probability (P(x'<x) for x' drawn from the distribution)
00088 double pdf1d_gaussian::cdf(double x) const
00089 {
00090   double dx = (x-mean())/(vnl_math::sqrt2*sd_);
00091   return 0.5*(vnl_erfc(-dx));
00092 }
00093 
00094 //: Return true if cdf() uses an analytic implementation
00095 bool pdf1d_gaussian::cdf_is_analytic() const
00096 {
00097   return true;
00098 }
00099 
00100 
00101 //=======================================================================
00102 
00103 
00104 double pdf1d_gaussian::gradient(double x,
00105                                 double& p) const
00106 {
00107   double v = variance();
00108   assert(v>0);
00109 
00110   double dx = x-mean();
00111   p = k_ * vcl_exp( -0.5*dx*dx/v);
00112 
00113   return -1.0*dx*p/v;
00114 }
00115 
00116 // ====================================================================
00117 
00118 
00119 double pdf1d_gaussian::log_prob_thresh(double pass_proportion) const
00120 {
00121   // The Mahalanobis distance of n-D Gaussian is distributed as Chi^2(n),
00122   // by definition, Chi^2 is the sum of independent Normal RVs.
00123   return log_k() - 0.5 * pdf1d_chi2_for_cum_prob (pass_proportion, 1);
00124 }
00125 
00126 //=======================================================================
00127 
00128 double pdf1d_gaussian::nearest_plausible(double x, double log_p_min) const
00129 {
00130   // calculate radius of plausible region in standard deviations.
00131   log_p_min -= log_k();
00132   assert(log_p_min <0); // Check sd_limit is positive and real.
00133   const double sd_limit = vcl_sqrt(-2.0*log_p_min);
00134 
00135   double dx = x-mean();
00136 
00137   double limit = sd_limit * sd_;
00138   double lo = -1.0 * limit;
00139   double hi = limit;
00140 
00141   if (dx<lo) dx=lo;
00142   else
00143     if (dx>hi) dx=hi;
00144 
00145   return mean()+dx;
00146 }
00147 
00148 //=======================================================================
00149 // Method: is_a
00150 //=======================================================================
00151 
00152 vcl_string pdf1d_gaussian::is_a() const
00153 {
00154   static vcl_string class_name_ = "pdf1d_gaussian";
00155   return class_name_;
00156 }
00157 
00158 //=======================================================================
00159 // Method: is_class
00160 //=======================================================================
00161 
00162 bool pdf1d_gaussian::is_class(vcl_string const& s) const
00163 {
00164   return pdf1d_pdf::is_class(s) || s==pdf1d_gaussian::is_a();
00165 }
00166 
00167 //=======================================================================
00168 // Method: version_no
00169 //=======================================================================
00170 
00171 short pdf1d_gaussian::version_no() const
00172 {
00173   return 1;
00174 }
00175 
00176 //=======================================================================
00177 // Method: clone
00178 //=======================================================================
00179 
00180 pdf1d_pdf* pdf1d_gaussian::clone() const
00181 {
00182   return new pdf1d_gaussian(*this);
00183 }
00184 
00185 //=======================================================================
00186 // Method: print
00187 //=======================================================================
00188 
00189 
00190 void pdf1d_gaussian::print_summary(vcl_ostream& os) const
00191 {
00192   pdf1d_pdf::print_summary(os);
00193   os << '\n';
00194 }
00195 
00196 //=======================================================================
00197 // Method: save
00198 //=======================================================================
00199 
00200 void pdf1d_gaussian::b_write(vsl_b_ostream& bfs) const
00201 {
00202   vsl_b_write(bfs,is_a());
00203   vsl_b_write(bfs,version_no());
00204   pdf1d_pdf::b_write(bfs);
00205   vsl_b_write(bfs,log_k_);
00206 }
00207 
00208 //=======================================================================
00209 // Method: load
00210 //=======================================================================
00211 
00212 void pdf1d_gaussian::b_read(vsl_b_istream& bfs)
00213 {
00214   if (!bfs) return;
00215 
00216   vcl_string name;
00217   vsl_b_read(bfs,name);
00218   if (name != is_a())
00219   {
00220     vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, pdf1d_gaussian &)\n";
00221     vcl_cerr << "           Attempted to load object of type ";
00222     vcl_cerr << name <<" into object of type " << is_a() << vcl_endl;
00223     bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00224     return;
00225   }
00226 
00227   short version;
00228   vsl_b_read(bfs,version);
00229   switch (version)
00230   {
00231     case (1):
00232       pdf1d_pdf::b_read(bfs);
00233       vsl_b_read(bfs,log_k_);
00234       break;
00235     default:
00236       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, pdf1d_gaussian &)\n";
00237       vcl_cerr << "           Unknown version number "<< version << vcl_endl;
00238       bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00239       return;
00240   }
00241 
00242   k_ = vcl_exp(log_k_);
00243   sd_ = vcl_sqrt(variance());
00244 }
00245 
00246 //==================< end of pdf1d_gaussian.cxx >====================