contrib/mul/pdf1d/pdf1d_gaussian_kernel_pdf.cxx
Go to the documentation of this file.
00001 // This is mul/pdf1d/pdf1d_gaussian_kernel_pdf.cxx
00002 
00003 //:
00004 // \file
00005 // \brief Univariate gaussian_kernel_pdf kernel PDF
00006 // \author Tim Cootes
00007 
00008 #include "pdf1d_gaussian_kernel_pdf.h"
00009 
00010 #include <vcl_cstdlib.h>
00011 #include <vcl_string.h>
00012 #include <vcl_cmath.h>
00013 
00014 #include <vnl/vnl_math.h>
00015 #include <vnl/vnl_erf.h>
00016 #include <pdf1d/pdf1d_gaussian_kernel_pdf_sampler.h>
00017 #include <pdf1d/pdf1d_sampler.h>
00018 #include <mbl/mbl_index_sort.h>
00019 
00020 //=======================================================================
00021 
00022 pdf1d_gaussian_kernel_pdf::pdf1d_gaussian_kernel_pdf()
00023 {
00024 }
00025 
00026 //: Define n kernels centred at i*sep (i=0..n-1)
00027 pdf1d_gaussian_kernel_pdf::pdf1d_gaussian_kernel_pdf(
00028                             int n, double sep, double width)
00029 {
00030   vnl_vector<double> x(n);
00031   for (int i=0;i<n;++i) x[i]=i*sep;
00032   set_centres(x,width);
00033 }
00034 
00035 //=======================================================================
00036 
00037 pdf1d_gaussian_kernel_pdf::~pdf1d_gaussian_kernel_pdf()
00038 {
00039 }
00040 
00041 //=======================================================================
00042 
00043 
00044 pdf1d_sampler* pdf1d_gaussian_kernel_pdf::new_sampler() const
00045 {
00046   pdf1d_gaussian_kernel_pdf_sampler *i = new pdf1d_gaussian_kernel_pdf_sampler;
00047   i->set_model(*this);
00048   return i;
00049 }
00050 
00051 //=======================================================================
00052 //: Probability density at x
00053 double pdf1d_gaussian_kernel_pdf::operator()(double x0) const
00054 {
00055   double p;
00056   const double* x = x_.data_block();
00057   const double* w = width_.data_block();
00058   int n = x_.size();
00059   double k = 1.0/(n*vcl_sqrt(2*vnl_math::pi));
00060   double sum = 0;
00061 
00062   for (int i=0;i<n;++i)
00063   {
00064     double dx = (x[i]-x0)/w[i];
00065     sum += vcl_exp(-0.5*dx*dx)/w[i];
00066   }
00067 
00068   p = k*sum;
00069 
00070   return p;
00071 }
00072 
00073   // Probability densities:
00074 double pdf1d_gaussian_kernel_pdf::log_p(double x) const
00075 {
00076   return vcl_log(pdf1d_gaussian_kernel_pdf::operator()(x));
00077 }
00078 
00079 //: Cumulative Probability (P(x'<x) for x' drawn from the distribution)
00080 double pdf1d_gaussian_kernel_pdf::cdf(double x0) const
00081 {
00082   const double* x = x_.data_block();
00083   const double* w = width_.data_block();
00084   int n = x_.size();
00085   double sum = 0;
00086 #if 1
00087 
00088   for (int i=0;i<n;++i)
00089     sum += vnl_erfc( (x[i]-x0)/(vnl_math::sqrt2*w[i]) );
00090     // CDF for gaussian = 0.5*(erfc(-x/sqrt2))
00091 
00092   return 0.5*(sum/n);
00093 
00094 #else // a slower but clearer and easier to debug version of above
00095 
00096   if (index_.empty())
00097     mbl_index_sort(x_.data_block(), x_.size(), index_);
00098   for (int i=0;i<n;++i)
00099     sum += 0.5 * (vnl_erfc( -(x0-x[index_[i]])/(vnl_math::sqrt2*w[index_[i]]) ) )/n;
00100 
00101   return sum;
00102 #endif
00103 }
00104 
00105 //: Return true if cdf() uses an analytic implementation
00106 bool pdf1d_gaussian_kernel_pdf::cdf_is_analytic() const
00107 {
00108   return true;
00109 }
00110 
00111 //=======================================================================
00112 
00113 
00114 double pdf1d_gaussian_kernel_pdf::gradient(double x0,
00115                                            double& p) const
00116 {
00117   const double* x = x_.data_block();
00118   const double* w = width_.data_block();
00119   int n = x_.size();
00120   double k = 1.0/(n*vcl_sqrt(2*vnl_math::pi));
00121   double sum_p = 0;
00122   double sum_g = 0;
00123 
00124   for (int i=0;i<n;++i)
00125   {
00126     double wi = w[i];
00127     double dx = (x[i]-x0)/wi;
00128     double p_i = vcl_exp(-0.5*dx*dx)/wi;
00129     sum_p += p_i;
00130     sum_g -= p_i*dx/wi;
00131   }
00132 
00133   p = k*sum_p;
00134 
00135   return k*sum_g;
00136 }
00137 
00138 //=======================================================================
00139 
00140 double pdf1d_gaussian_kernel_pdf::nearest_plausible(double /*x*/, double /*log_p_min*/) const
00141 {
00142   vcl_cerr<<"pdf1d_gaussian_kernel_pdf::nearest_plausible() not yet implemented.\n";
00143   vcl_abort();
00144   return 0.0;
00145 }
00146 
00147 //=======================================================================
00148 
00149 vcl_string pdf1d_gaussian_kernel_pdf::is_a() const
00150 {
00151   static vcl_string class_name_ = "pdf1d_gaussian_kernel_pdf";
00152   return class_name_;
00153 }
00154 
00155 //=======================================================================
00156 
00157 bool pdf1d_gaussian_kernel_pdf::is_class(vcl_string const& s) const
00158 {
00159   return pdf1d_kernel_pdf::is_class(s) || s==pdf1d_gaussian_kernel_pdf::is_a();
00160 }
00161 
00162 //=======================================================================
00163 
00164 short pdf1d_gaussian_kernel_pdf::version_no() const
00165 {
00166   return 1;
00167 }
00168 
00169 //=======================================================================
00170 
00171 pdf1d_pdf* pdf1d_gaussian_kernel_pdf::clone() const
00172 {
00173   return new pdf1d_gaussian_kernel_pdf(*this);
00174 }
00175 
00176 //=======================================================================
00177 
00178 void pdf1d_gaussian_kernel_pdf::print_summary(vcl_ostream& os) const
00179 {
00180   pdf1d_pdf::print_summary(os);
00181   os << '\n';
00182 }
00183 
00184 //=======================================================================
00185 
00186 void pdf1d_gaussian_kernel_pdf::b_write(vsl_b_ostream& bfs) const
00187 {
00188   vsl_b_write(bfs,is_a());
00189   vsl_b_write(bfs,version_no());
00190   pdf1d_kernel_pdf::b_write(bfs);
00191 }
00192 
00193 //=======================================================================
00194 
00195 void pdf1d_gaussian_kernel_pdf::b_read(vsl_b_istream& bfs)
00196 {
00197   if (!bfs) return;
00198 
00199   vcl_string name;
00200   vsl_b_read(bfs,name);
00201   if (name != is_a())
00202   {
00203     vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, pdf1d_gaussian_kernel_pdf &)\n"
00204              << "           Attempted to load object of type "
00205              << name <<" into object of type " << is_a() << vcl_endl;
00206     bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00207     return;
00208   }
00209 
00210   short version;
00211   vsl_b_read(bfs,version);
00212   switch (version)
00213   {
00214     case (1):
00215       pdf1d_kernel_pdf::b_read(bfs);
00216       break;
00217     default:
00218       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, pdf1d_gaussian_kernel_pdf &)\n"
00219                << "           Unknown version number "<< version << vcl_endl;
00220       bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00221       return;
00222   }
00223 }
00224