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