contrib/mul/vpdfl/vpdfl_axis_gaussian_builder.cxx
Go to the documentation of this file.
00001 // This is mul/vpdfl/vpdfl_axis_gaussian_builder.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 //  \file
00007 
00008 #include "vpdfl_axis_gaussian_builder.h"
00009 //
00010 #include <vcl_cassert.h>
00011 #include <vcl_string.h>
00012 #include <vcl_sstream.h>
00013 #include <vcl_cstdlib.h> // vcl_abort()
00014 
00015 #include <mbl/mbl_data_wrapper.h>
00016 #include <vpdfl/vpdfl_axis_gaussian.h>
00017 
00018 #include <mbl/mbl_parse_block.h>
00019 #include <mbl/mbl_read_props.h>
00020 #include <vul/vul_string.h>
00021 #include <mbl/mbl_exception.h>
00022 
00023 //=======================================================================
00024 // Dflt ctor
00025 //=======================================================================
00026 
00027 vpdfl_axis_gaussian_builder::vpdfl_axis_gaussian_builder()
00028     : min_var_(1.0e-6)
00029 {
00030 }
00031 
00032 //=======================================================================
00033 // Destructor
00034 //=======================================================================
00035 
00036 vpdfl_axis_gaussian_builder::~vpdfl_axis_gaussian_builder()
00037 {
00038 }
00039 
00040 //=======================================================================
00041 
00042 vpdfl_axis_gaussian& vpdfl_axis_gaussian_builder::gaussian(vpdfl_pdf_base& model) const
00043 {
00044   // require a vpdfl_axis_gaussian
00045   assert(model.is_class("vpdfl_axis_gaussian"));
00046   return static_cast<vpdfl_axis_gaussian&>(model);
00047 }
00048 
00049 vpdfl_pdf_base* vpdfl_axis_gaussian_builder::new_model() const
00050 {
00051   return new vpdfl_axis_gaussian;
00052 }
00053 
00054 //=======================================================================
00055 //: Define lower threshold on variance for built models
00056 //=======================================================================
00057 void vpdfl_axis_gaussian_builder::set_min_var(double min_var)
00058 {
00059   min_var_ = min_var;
00060 }
00061 
00062 //=======================================================================
00063 //: Get lower threshold on variance for built models
00064 //=======================================================================
00065 double vpdfl_axis_gaussian_builder::min_var() const
00066 {
00067   return min_var_;
00068 }
00069 
00070 void vpdfl_axis_gaussian_builder::build(vpdfl_pdf_base& model,
00071                                         const vnl_vector<double>& mean) const
00072 {
00073   vpdfl_axis_gaussian& g = gaussian(model);
00074 
00075   vnl_vector<double> var(mean.size());
00076   for (unsigned int i=0;i<mean.size();i++)
00077     var(i)=min_var_;
00078 
00079   g.set(mean,var);
00080 }
00081 
00082 void vpdfl_axis_gaussian_builder::build(vpdfl_pdf_base& model,
00083                                         mbl_data_wrapper<vnl_vector<double> >& data) const
00084 {
00085   vpdfl_axis_gaussian& g = gaussian(model);
00086 
00087   unsigned long n_samples = data.size();
00088 
00089   if (n_samples<1L)
00090   {
00091     vcl_cerr<<"vpdfl_axis_gaussian_builder::build() Too few examples available.\n";
00092     vcl_abort();
00093   }
00094 
00095   data.reset();
00096   if (n_samples==1)
00097   {
00098     // Build using the single example as mean
00099     build(model,data.current());
00100     return;
00101   }
00102 
00103   unsigned long n_dims = data.current().size();
00104   vnl_vector<double> sum(n_dims),sum_sq(n_dims),var(n_dims);
00105 
00106   double* var_data = var.data_block();
00107   double* sum_data = sum.data_block();
00108   double* sum_sq_data = sum_sq.data_block();
00109   for (unsigned long j=0;j<n_dims;j++)
00110   {
00111     sum_data[j]=0.0;
00112     sum_sq_data[j]=0.0;
00113   }
00114 
00115   data.reset();
00116   for (unsigned long i=0;i<n_samples;i++)
00117   {
00118     const double *v = data.current().data_block();
00119     for (unsigned long j=0;j<n_dims;j++)
00120     {
00121       sum_data[j] += v[j];
00122       sum_sq_data[j] += v[j]*v[j];
00123     }
00124 
00125     data.next();
00126   }
00127 
00128   sum/=n_samples;
00129   for (unsigned long j=0;j<n_dims;j++)
00130   {
00131     var_data[j] = sum_sq_data[j]/n_samples - sum_data[j]*sum_data[j];
00132     if (var_data[j]<min_var_) var_data[j]=min_var_;
00133   }
00134 
00135   g.set(sum,var);
00136 }
00137 
00138 void vpdfl_axis_gaussian_builder::weighted_build(vpdfl_pdf_base& model,
00139                                                  mbl_data_wrapper<vnl_vector<double> >& data,
00140                                                  const vcl_vector<double>& wts) const
00141 {
00142   vpdfl_axis_gaussian& g = gaussian(model);
00143 
00144   unsigned long n_samples = data.size();
00145 
00146   if (n_samples<2L)
00147   {
00148     vcl_cerr<<"vpdfl_axis_gaussian_builder::build() Too few examples available.\n";
00149     vcl_abort();
00150   }
00151 
00152   if (wts.size()!=n_samples)
00153   {
00154     vcl_cerr<<"vpdfl_axis_gaussian_builder::build() Weight array must contain "
00155             <<n_samples<<" not "<<wts.size()<<vcl_endl;
00156     vcl_abort();
00157   }
00158   data.reset();
00159   unsigned long n_dims = data.current().size();
00160 
00161   double w_sum = wts[0];
00162   vnl_vector<double> sum = data.current(); sum *= w_sum;
00163 
00164   for (unsigned long i=1;i<n_samples;i++)
00165   {
00166     data.next();
00167     double wt = wts[i];
00168     sum += wt * data.current();
00169     w_sum += wts[i];
00170   }
00171 
00172   vnl_vector<double> mean = sum/w_sum;
00173 
00174 
00175   vnl_vector<double> sum_sq(n_dims), var(n_dims);
00176   double* var_data = var.data_block();
00177   double* m_data = mean.data_block();
00178   double* sum_sq_data = sum_sq.data_block();
00179   for (unsigned long j=0;j<n_dims;j++)
00180   {
00181     sum_sq_data[j]=0.0;
00182   }
00183 
00184   data.reset();
00185   for (unsigned long i=0;i<n_samples;i++)
00186   {
00187     const double *v = data.current().data_block();
00188     double w = wts[i];
00189     for (unsigned long j=0;j<n_dims;j++)
00190     {
00191       double dx = v[j]-m_data[j];
00192       sum_sq_data[j] += w * dx*dx;
00193     }
00194 
00195     data.next();
00196   }
00197 
00198   for (unsigned long j=0;j<n_dims;j++)
00199   {
00200     var_data[j] = sum_sq_data[j]/w_sum;
00201     if (var_data[j]<min_var_) var_data[j]=min_var_;
00202   }
00203 
00204   g.set(mean,var);
00205 }
00206 //=======================================================================
00207 // Method: is_a
00208 //=======================================================================
00209 
00210 vcl_string vpdfl_axis_gaussian_builder::is_a() const
00211 {
00212   return vcl_string("vpdfl_axis_gaussian_builder");
00213 }
00214 
00215 //=======================================================================
00216 // Method: is_class
00217 //=======================================================================
00218 
00219 bool vpdfl_axis_gaussian_builder::is_class(vcl_string const& s) const
00220 {
00221   return vpdfl_builder_base::is_class(s) || s==vpdfl_axis_gaussian_builder::is_a();
00222 }
00223 
00224 //=======================================================================
00225 // Method: version_no
00226 //=======================================================================
00227 
00228 short vpdfl_axis_gaussian_builder::version_no() const
00229 {
00230   return 1;
00231 }
00232 
00233 //=======================================================================
00234 // Method: clone
00235 //=======================================================================
00236 
00237 vpdfl_builder_base* vpdfl_axis_gaussian_builder::clone() const
00238 {
00239   return new vpdfl_axis_gaussian_builder(*this);
00240 }
00241 
00242 //=======================================================================
00243 // Method: print
00244 //=======================================================================
00245 
00246 void vpdfl_axis_gaussian_builder::print_summary(vcl_ostream& os) const
00247 {
00248   os << "Min. var.: "<< min_var_;
00249 }
00250 
00251 //=======================================================================
00252 // Method: save
00253 //=======================================================================
00254 
00255 void vpdfl_axis_gaussian_builder::b_write(vsl_b_ostream& bfs) const
00256 {
00257   vsl_b_write(bfs,version_no());
00258   vsl_b_write(bfs,min_var_);
00259 }
00260 
00261 //=======================================================================
00262 // Method: load
00263 //=======================================================================
00264 
00265 void vpdfl_axis_gaussian_builder::b_read(vsl_b_istream& bfs)
00266 {
00267   if (!bfs) return;
00268 
00269   short version;
00270   vsl_b_read(bfs,version);
00271   switch (version)
00272   {
00273     case (1):
00274       vsl_b_read(bfs,min_var_);
00275       break;
00276     default:
00277       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, vpdfl_axis_gaussian_builder &)\n"
00278                << "           Unknown version number "<< version << vcl_endl;
00279       bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00280       return;
00281   }
00282 }
00283 
00284 //: Read initialisation settings from a stream.
00285 // Parameters:
00286 // \verbatim
00287 // {
00288 //   min_var: 1.0e-6
00289 // }
00290 // \endverbatim
00291 // \throw mbl_exception_parse_error if the parse fails.
00292 void vpdfl_axis_gaussian_builder::config_from_stream(vcl_istream & is)
00293 {
00294   vcl_string s = mbl_parse_block(is);
00295 
00296   vcl_istringstream ss(s);
00297   mbl_read_props_type props = mbl_read_props_ws(ss);
00298 
00299   double mv=1.0e-6;
00300 
00301   if (props.find("min_var")!=props.end())
00302   {
00303     mv=vul_string_atof(props["min_var"]);
00304     props.erase("min_var");
00305   }
00306   set_min_var(mv);
00307 
00308   try
00309   {
00310     mbl_read_props_look_for_unused_props(
00311         "vpdfl_axis_gaussian_builder::config_from_stream", props);
00312   }
00313   catch(mbl_exception_unused_props &e)
00314   {
00315     throw mbl_exception_parse_error(e.what());
00316   }
00317 }
00318