contrib/mul/pdf1d/pdf1d_compare_to_pdf_bhat.cxx
Go to the documentation of this file.
00001 // This is mul/pdf1d/pdf1d_compare_to_pdf_bhat.cxx
00002 
00003 //:
00004 // \file
00005 // \author Tim Cootes
00006 // \brief Test if data from a given distribution using Bhattacharyya overlap
00007 
00008 #include "pdf1d_compare_to_pdf_bhat.h"
00009 
00010 #include <vcl_string.h>
00011 
00012 #include <pdf1d/pdf1d_gaussian.h>
00013 #include <pdf1d/pdf1d_gaussian_kernel_pdf_builder.h>
00014 #include <pdf1d/pdf1d_calc_mean_var.h>
00015 #include <pdf1d/pdf1d_bhat_overlap.h>
00016 #include <pdf1d/pdf1d_sampler.h>
00017 #include <pdf1d/pdf1d_resample.h>
00018 
00019 //:
00020 //  When true, if model_pdf is gaussian, use integration over the gaussian ([-3,3]sd)
00021 //  to estimate overlap,  rather than resampling from data distribution
00022 bool use_integration_for_gaussian=true;
00023 
00024 //=======================================================================
00025 // Dflt ctor
00026 //=======================================================================
00027 
00028 pdf1d_compare_to_pdf_bhat::pdf1d_compare_to_pdf_bhat()
00029   : n_per_point_(3)
00030 {
00031   pdf1d_gaussian_kernel_pdf_builder *gk_builder = new pdf1d_gaussian_kernel_pdf_builder;
00032   gk_builder->set_use_width_from_separation();
00033   builder_ = gk_builder;
00034 }
00035 
00036 //: Construct and define method of building pdf from data
00037 pdf1d_compare_to_pdf_bhat::pdf1d_compare_to_pdf_bhat(const pdf1d_builder& builder,
00038                                                      int n_per_point)
00039   : n_per_point_(n_per_point)
00040 {
00041   builder_ = builder;
00042 }
00043 
00044 
00045 //=======================================================================
00046 // Destructor
00047 //=======================================================================
00048 
00049 pdf1d_compare_to_pdf_bhat::~pdf1d_compare_to_pdf_bhat()
00050 {
00051 }
00052 
00053 //: Define method of building pdf from data
00054 void pdf1d_compare_to_pdf_bhat::set_builder(const pdf1d_builder& b)
00055 {
00056   builder_ = b;
00057 }
00058 
00059 //: Number of samples per data-point used in estimating overlap
00060 void pdf1d_compare_to_pdf_bhat::set_n_per_point(int n)
00061 {
00062   n_per_point_ = n;
00063 }
00064 
00065 //=======================================================================
00066 
00067 //: Test whether data came from the given distribution
00068 double pdf1d_compare_to_pdf_bhat::compare(const double* data, int n,
00069                                           const pdf1d_pdf& model_pdf)
00070 {
00071   if (!pdf_.isDefined() || pdf_->is_a()!=builder().new_model_type())
00072     pdf_ = builder().new_model();
00073 
00074   builder().build_from_array(pdf_,data,n);
00075 
00076    // For clarity and to avoid compiler warnings
00077   const pdf1d_pdf* built_pdf = pdf_.ptr();
00078 
00079   // Use integral overlap
00080   if (use_integration_for_gaussian && model_pdf.is_class("pdf1d_gaussian"))
00081     return pdf1d_bhat_overlap_gaussian_with_pdf(model_pdf,*built_pdf);
00082 
00083   return pdf1d_bhat_overlap(*built_pdf,model_pdf,n_per_point_*n);
00084 }
00085 
00086 //=======================================================================
00087 
00088 //: Test whether data has form of the given distribution
00089 double pdf1d_compare_to_pdf_bhat::bootstrap_compare_form(vnl_vector<double>& B,
00090                                                          const double* data, int n,
00091                                                          const pdf1d_builder& builder2, int n_trials)
00092 {
00093   // Fit a general PDF (typically a kernel pdf) to the data and
00094   // sample from it to get samples x and associated prob.s p
00095   if (!pdf_.isDefined() || pdf_->is_a()!=builder().new_model_type())
00096     pdf_ = builder().new_model();
00097   builder().build_from_array(pdf_,data,n);
00098 
00099   bool use_gauss_integration = (use_integration_for_gaussian
00100                                 && builder2.new_model_type()=="pdf1d_gaussian");
00101 
00102    // For clarity and to avoid compiler warnings
00103   const pdf1d_pdf* data_pdf = pdf_.ptr();
00104 
00105   int n_samples = n*n_per_point_;
00106   vnl_vector<double> x(n_samples),p(n_samples);
00107 
00108   if (!use_gauss_integration)
00109   {
00110     pdf1d_sampler* sampler = data_pdf->new_sampler();
00111     sampler->regular_samples_and_prob(x,p);
00112     delete sampler;
00113   }
00114 
00115   vnl_vector<double> sample(n);
00116 
00117   pdf1d_pdf* pdf = builder2.new_model();
00118 
00119   B.set_size(n_trials);
00120 
00121   double sum = 0;
00122   double b;
00123   for (int i=0;i<n_trials;++i)
00124   {
00125     // Build pdf from resampled data.
00126     // Check resampled data is not all identical
00127     double s_mean,s_var=0;
00128     while (s_var<1e-9)
00129     {
00130       pdf1d_resample(sample,data,n);
00131       pdf1d_calc_mean_var(s_mean,s_var,sample);
00132     }
00133 
00134     builder2.build_from_array(*pdf,sample.data_block(),n);
00135 
00136     // Test overlap of pdf with pdf around original data
00137     if (use_gauss_integration)
00138       b = pdf1d_bhat_overlap_gaussian_with_pdf(*pdf,*data_pdf);
00139     else
00140       b = pdf1d_bhat_overlap(*pdf,x.data_block(),p.data_block(),n_samples);
00141 
00142     B[i] = b;
00143     sum+=b;
00144   }
00145 
00146   delete pdf;
00147 
00148   return sum/n_trials;
00149 }
00150 
00151 //=======================================================================
00152 // Method: is_a
00153 //=======================================================================
00154 
00155 vcl_string pdf1d_compare_to_pdf_bhat::is_a() const
00156 {
00157   return vcl_string("pdf1d_compare_to_pdf_bhat");
00158 }
00159 
00160 //=======================================================================
00161 // Method: is_class
00162 //=======================================================================
00163 
00164 bool pdf1d_compare_to_pdf_bhat::is_class(vcl_string const& s) const
00165 {
00166   return pdf1d_compare_to_pdf::is_class(s) || s==pdf1d_compare_to_pdf_bhat::is_a();
00167 }
00168 
00169 //=======================================================================
00170 // Method: version_no
00171 //=======================================================================
00172 
00173 short pdf1d_compare_to_pdf_bhat::version_no() const
00174 {
00175   return 1;
00176 }
00177 
00178 //=======================================================================
00179 // Method: clone
00180 //=======================================================================
00181 
00182 pdf1d_compare_to_pdf* pdf1d_compare_to_pdf_bhat::clone() const
00183 {
00184   return new pdf1d_compare_to_pdf_bhat(*this);
00185 }
00186 
00187 //=======================================================================
00188 // Method: print
00189 //=======================================================================
00190 
00191 void pdf1d_compare_to_pdf_bhat::print_summary(vcl_ostream& os) const
00192 {
00193   os << "Builder: "<<builder_<<'\n';
00194 }
00195 
00196 //=======================================================================
00197 // Method: save
00198 //=======================================================================
00199 
00200 void pdf1d_compare_to_pdf_bhat::b_write(vsl_b_ostream& bfs) const
00201 {
00202   vsl_b_write(bfs,version_no());
00203   vsl_b_write(bfs,builder_);
00204   vsl_b_write(bfs,n_per_point_);
00205 }
00206 
00207 //=======================================================================
00208 // Method: load
00209 //=======================================================================
00210 
00211 void pdf1d_compare_to_pdf_bhat::b_read(vsl_b_istream& bfs)
00212 {
00213   if (!bfs) return;
00214 
00215   short version;
00216   vsl_b_read(bfs,version);
00217   switch (version)
00218   {
00219     case (1):
00220       vsl_b_read(bfs,builder_);
00221       vsl_b_read(bfs,n_per_point_);
00222       break;
00223     default:
00224       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, pdf1d_compare_to_pdf_bhat &)\n"
00225                << "           Unknown version number "<< version << vcl_endl;
00226       bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00227       return;
00228   }
00229 }
00230