contrib/mul/pdf1d/pdf1d_exponential_builder.cxx
Go to the documentation of this file.
00001 // This is mul/pdf1d/pdf1d_exponential_builder.cxx
00002 
00003 //:
00004 // \file
00005 
00006 #include "pdf1d_exponential_builder.h"
00007 
00008 #include <vcl_cassert.h>
00009 #include <vcl_string.h>
00010 #include <vcl_cstdlib.h> // vcl_abort()
00011 #include <vcl_cmath.h>
00012 
00013 #include <mbl/mbl_data_wrapper.h>
00014 #include <mbl/mbl_data_array_wrapper.h>
00015 #include <pdf1d/pdf1d_exponential.h>
00016 #include <pdf1d/pdf1d_calc_mean_var.h>
00017 
00018 //=======================================================================
00019 // Dflt ctor
00020 //=======================================================================
00021 
00022 pdf1d_exponential_builder::pdf1d_exponential_builder()
00023     : min_var_(1.0e-6)
00024 {
00025 }
00026 
00027 //=======================================================================
00028 // Destructor
00029 //=======================================================================
00030 
00031 pdf1d_exponential_builder::~pdf1d_exponential_builder()
00032 {
00033 }
00034 
00035 //=======================================================================
00036 
00037 pdf1d_exponential& pdf1d_exponential_builder::exponential(pdf1d_pdf& model) const
00038 {
00039   // require a pdf1d_exponential
00040   assert(model.is_class("pdf1d_exponential"));
00041   return static_cast<pdf1d_exponential&>(model);
00042 }
00043 
00044 pdf1d_pdf* pdf1d_exponential_builder::new_model() const
00045 {
00046   return new pdf1d_exponential;
00047 }
00048 
00049 vcl_string pdf1d_exponential_builder::new_model_type() const
00050 {
00051   return vcl_string("pdf1d_exponential");
00052 }
00053 
00054 
00055 //=======================================================================
00056 //: Define lower threshold on variance for built models
00057 //=======================================================================
00058 void pdf1d_exponential_builder::set_min_var(double min_var)
00059 {
00060   min_var_ = min_var;
00061 }
00062 
00063 //=======================================================================
00064 //: Get lower threshold on variance for built models
00065 //=======================================================================
00066 double pdf1d_exponential_builder::min_var() const
00067 {
00068   return min_var_;
00069 }
00070 
00071 void pdf1d_exponential_builder::build(pdf1d_pdf& model, double mean) const
00072 {
00073   pdf1d_exponential& g = exponential(model);
00074   g.set_lambda(1.0/mean);
00075 }
00076 
00077 //: Build exponential from n elements in data[i]
00078 void pdf1d_exponential_builder::build_from_array(pdf1d_pdf& model, const double* data, int n) const
00079 {
00080   if (n<2)
00081   {
00082     vcl_cerr<<"pdf1d_exponential_builder::build_from_array()"
00083             <<" Too few examples available.\n";
00084     vcl_abort();
00085   }
00086 
00087   double m,v;
00088   pdf1d_calc_mean_var(m,v,data,n);
00089 
00090   double min_m = vcl_sqrt(min_var_);
00091   if (m<min_m) m=min_m;
00092 
00093   pdf1d_exponential& g = exponential(model);
00094   g.set_lambda(1.0/m);
00095 }
00096 
00097 void pdf1d_exponential_builder::build(pdf1d_pdf& model, mbl_data_wrapper<double>& data) const
00098 {
00099   int n_samples = data.size();
00100 
00101   if (n_samples<2)
00102   {
00103     vcl_cerr<<"pdf1d_exponential_builder::build() Too few examples available.\n";
00104     vcl_abort();
00105   }
00106 
00107   if (data.is_class("mbl_data_array_wrapper<T>"))
00108   {
00109     // Use more efficient build_from_array algorithm
00110     mbl_data_array_wrapper<double>& data_array =
00111                      static_cast<mbl_data_array_wrapper<double>&>(data);
00112     build_from_array(model,data_array.data(),n_samples);
00113     return;
00114   }
00115 
00116   double sum = 0;
00117 
00118   data.reset();
00119   for (int i=0;i<n_samples;i++)
00120   {
00121     double x = data.current();
00122     sum += x;
00123     data.next();
00124   }
00125 
00126   double m = sum/n_samples;
00127   double min_m = vcl_sqrt(min_var_);
00128   if (m<min_m) m=min_m;
00129 
00130   pdf1d_exponential& g = exponential(model);
00131   g.set_lambda(1.0/m);
00132 }
00133 
00134 void pdf1d_exponential_builder::weighted_build(pdf1d_pdf& model,
00135                                                mbl_data_wrapper<double>& data,
00136                                                const vcl_vector<double>& wts) const
00137 {
00138   int n_samples = data.size();
00139 
00140   if (n_samples<2)
00141   {
00142     vcl_cerr<<"pdf1d_exponential_builder::build() Too few examples available.\n";
00143     vcl_abort();
00144   }
00145 
00146   double sum = 0;
00147   double w_sum = 0;
00148   const double* w = &(wts.front()); // cannot use wts.begin() since that's an iterator, not a pointer
00149 
00150 
00151   // Inefficient to go through twice.
00152   // Fix this one day.
00153 
00154   data.reset();
00155   for (int i=0;i<n_samples;i++)
00156   {
00157     double x = data.current();
00158     double wi = w[i];
00159     sum += wi*x;
00160     w_sum += wi;
00161     data.next();
00162   }
00163 
00164   double m = sum/w_sum;
00165   double min_m = vcl_sqrt(min_var_);
00166   if (m<min_m) m=min_m;
00167 
00168   pdf1d_exponential& g = exponential(model);
00169   g.set_lambda(1.0/m);
00170 }
00171 //=======================================================================
00172 // Method: is_a
00173 //=======================================================================
00174 
00175 vcl_string pdf1d_exponential_builder::is_a() const
00176 {
00177   return vcl_string("pdf1d_exponential_builder");
00178 }
00179 
00180 //=======================================================================
00181 // Method: is_class
00182 //=======================================================================
00183 
00184 bool pdf1d_exponential_builder::is_class(vcl_string const& s) const
00185 {
00186   return pdf1d_builder::is_class(s) || s==pdf1d_exponential_builder::is_a();
00187 }
00188 
00189 //=======================================================================
00190 // Method: version_no
00191 //=======================================================================
00192 
00193 short pdf1d_exponential_builder::version_no() const
00194 {
00195   return 1;
00196 }
00197 
00198 //=======================================================================
00199 // Method: clone
00200 //=======================================================================
00201 
00202 pdf1d_builder* pdf1d_exponential_builder::clone() const
00203 {
00204   return new pdf1d_exponential_builder(*this);
00205 }
00206 
00207 //=======================================================================
00208 // Method: print
00209 //=======================================================================
00210 
00211 void pdf1d_exponential_builder::print_summary(vcl_ostream& os) const
00212 {
00213   os << "Min. var.: "<< min_var_;
00214 }
00215 
00216 //=======================================================================
00217 // Method: save
00218 //=======================================================================
00219 
00220 void pdf1d_exponential_builder::b_write(vsl_b_ostream& bfs) const
00221 {
00222   vsl_b_write(bfs,version_no());
00223   vsl_b_write(bfs,min_var_);
00224 }
00225 
00226 //=======================================================================
00227 // Method: load
00228 //=======================================================================
00229 
00230 void pdf1d_exponential_builder::b_read(vsl_b_istream& bfs)
00231 {
00232   if (!bfs) return;
00233 
00234   short version;
00235   vsl_b_read(bfs,version);
00236   switch (version)
00237   {
00238     case (1):
00239       vsl_b_read(bfs,min_var_);
00240       break;
00241     default:
00242       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, pdf1d_exponential_builder &)\n"
00243                << "           Unknown version number "<< version << vcl_endl;
00244       bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00245       return;
00246   }
00247 }
00248