contrib/mul/pdf1d/pdf1d_gaussian_kernel_pdf_sampler.cxx
Go to the documentation of this file.
00001 // This is mul/pdf1d/pdf1d_gaussian_kernel_pdf_sampler.cxx
00002 #include "pdf1d_gaussian_kernel_pdf_sampler.h"
00003 //:
00004 // \file
00005 // \brief Implements sampling for a gaussian_kernel_pdf model pdf sampler
00006 // \author Tim Cootes and Ian Scott
00007 //
00008 //=======================================================================
00009 
00010 #include <vcl_string.h>
00011 #include <vnl/vnl_vector.h>
00012 #include <pdf1d/pdf1d_sampler.h>
00013 
00014 //=======================================================================
00015 
00016 pdf1d_gaussian_kernel_pdf_sampler::pdf1d_gaussian_kernel_pdf_sampler():
00017   rng_(9667566ul)
00018 {
00019 }
00020 
00021 pdf1d_gaussian_kernel_pdf_sampler::~pdf1d_gaussian_kernel_pdf_sampler()
00022 {
00023 }
00024 
00025 //=======================================================================
00026 
00027 const pdf1d_gaussian_kernel_pdf& pdf1d_gaussian_kernel_pdf_sampler::gaussian_kernel_pdf() const
00028 {
00029   return static_cast<const pdf1d_gaussian_kernel_pdf&>(model());
00030 }
00031 
00032 
00033 // ====================================================================
00034 
00035 //: For generating plausible examples
00036 double pdf1d_gaussian_kernel_pdf_sampler::sample()
00037 {
00038   const pdf1d_gaussian_kernel_pdf& kpdf = gaussian_kernel_pdf();
00039 
00040   int n = kpdf.centre().size();
00041 
00042   int i = 0;
00043   if (n>1) i=rng_.lrand32(0,n-1);
00044 
00045   double x = rng_.normal();
00046 
00047   x*=kpdf.width()[i];
00048   x+=kpdf.centre()[i];
00049 
00050   return x;
00051 }
00052 
00053 //: Fill x with samples possibly chosen so as to represent the distribution
00054 //  Samples equal numbers from each kernel.
00055 void pdf1d_gaussian_kernel_pdf_sampler::regular_samples(vnl_vector<double>& x)
00056 {
00057   const pdf1d_gaussian_kernel_pdf& kpdf = gaussian_kernel_pdf();
00058   int n = x.size();
00059   double* x_data = x.data_block();
00060   int nk = kpdf.centre().size();
00061   int n_per_k = n/nk;
00062   double lim = (n_per_k-1)/2.0;
00063 
00064   const double* c = kpdf.centre().data_block();
00065   const double* w = kpdf.width().data_block();
00066 
00067   for (int i=0;i<n;++i)
00068   {
00069     // Select components in order
00070     int j = i%nk;
00071 
00072     if (n_per_k>5)
00073     {
00074        x_data[i] = c[j]+rng_.normal()*w[j];
00075     }
00076     else
00077     {
00078       // Spread points about
00079       // Note that this isn't quite right - should be equally spaced in CDF space
00080       int a = j/nk;
00081       double f = double(a)/(n_per_k-1);  // in [0,1]
00082       x_data[i] = c[j] + lim*(2*f-1)*w[j];
00083     }
00084   }
00085 }
00086 
00087 //=======================================================================
00088 
00089 //: Reseeds the static random number generator (one per derived class)
00090 void pdf1d_gaussian_kernel_pdf_sampler::reseed(unsigned long seed)
00091 {
00092   rng_.reseed(seed);
00093 }
00094 
00095 
00096 //=======================================================================
00097 
00098 vcl_string pdf1d_gaussian_kernel_pdf_sampler::is_a() const
00099 {
00100   return vcl_string("pdf1d_gaussian_kernel_pdf_sampler");
00101 }
00102 
00103 //=======================================================================
00104 
00105 bool pdf1d_gaussian_kernel_pdf_sampler::is_class(vcl_string const& s) const
00106 {
00107   return pdf1d_sampler::is_class(s) || s==pdf1d_gaussian_kernel_pdf_sampler::is_a();
00108 }
00109 
00110 //=======================================================================
00111 
00112 short pdf1d_gaussian_kernel_pdf_sampler::version_no() const
00113 {
00114   return 1;
00115 }
00116 
00117 //=======================================================================
00118 
00119 pdf1d_sampler* pdf1d_gaussian_kernel_pdf_sampler::clone() const
00120 {
00121   return new pdf1d_gaussian_kernel_pdf_sampler(*this);
00122 }
00123 
00124