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