contrib/mul/msm/msm_box_limiter.cxx
Go to the documentation of this file.
00001 #include "msm_box_limiter.h"
00002 //:
00003 // \file
00004 // \author Tim Cootes
00005 // \brief Apply limits to each parameter independently
00006 
00007 #include <vnl/io/vnl_io_vector.h>
00008 #include <vsl/vsl_binary_loader.h>
00009 #include <mbl/mbl_parse_block.h>
00010 #include <mbl/mbl_read_props.h>
00011 #include <vul/vul_string.h>
00012 #include <vcl_sstream.h>
00013 #include <vcl_cassert.h>
00014 
00015 //=======================================================================
00016 msm_box_limiter::msm_box_limiter()
00017   : n_sds_(3.0),accept_prop_(0.98)
00018 {
00019 }
00020 
00021 //: Define number of SDs to limit at
00022 void msm_box_limiter::set_n_sds(double n_sds)
00023 {
00024   n_sds_=n_sds;
00025 }
00026 
00027 //: Define variance on each parameter
00028 void msm_box_limiter::set_param_var(const vnl_vector<double>& v)
00029 {
00030   mode_sd_.set_size(v.size());
00031   for (unsigned i=0;i<v.size();++i) mode_sd_[i]=vcl_sqrt(v[i]);
00032   set_acceptance(accept_prop_);
00033 }
00034 
00035 //: Set the limits so that a given proportion pass
00036 void msm_box_limiter::set_acceptance(double prop, unsigned n_modes)
00037 {
00038   assert(prop>=0 && prop<=1.0);
00039   accept_prop_ = prop;
00040   if (n_modes==0) n_modes=mode_sd_.size();
00041 
00042   if (n_modes==0) return;
00043 
00044   // Assume independence and estimate proportion,p, to pass in each
00045   // dimension, thus prop = p^n;
00046   double p = vcl_pow(prop,1.0/n_modes);
00047 
00048   // In each dimension x^2 is distributed as chi-squared with one d.o.f.
00049   double t = msm_chi2_for_cum_prob(p,1);
00050 
00051   set_n_sds(vcl_sqrt(t));
00052 }
00053 
00054 
00055 //: Apply limit to parameter vector b
00056 void msm_box_limiter::apply_limit(vnl_vector<double>& b) const
00057 {
00058   for (unsigned i=0;i<b.size();++i)
00059   {
00060     double m = mode_sd_[i]*n_sds_;
00061     if (b[i]>m) b[i]=m;
00062     else
00063     if (b[i]<-m) b[i]=-m;
00064   }
00065 }
00066 
00067 //=======================================================================
00068 //: Print class to os
00069 void msm_box_limiter::print_summary(vcl_ostream& os) const
00070 {
00071   os<<"{ n_sds: "<<n_sds_
00072     <<" accept_prop: "<<accept_prop_<<" } ";
00073 }
00074 
00075 const static short version_no = 1;
00076 
00077 //: Save class to binary file stream
00078 void msm_box_limiter::b_write(vsl_b_ostream& bfs) const
00079 {
00080   vsl_b_write(bfs,version_no);
00081   vsl_b_write(bfs,mode_sd_);
00082   vsl_b_write(bfs,accept_prop_);
00083   vsl_b_write(bfs,n_sds_);
00084 }
00085 
00086 
00087 //: Load class from binary file stream
00088 void msm_box_limiter::b_read(vsl_b_istream& bfs)
00089 {
00090   short version;
00091   vsl_b_read(bfs,version);
00092   switch (version)
00093   {
00094     case (1):
00095       vsl_b_read(bfs,mode_sd_);
00096       vsl_b_read(bfs,accept_prop_);
00097       vsl_b_read(bfs,n_sds_);
00098       break;
00099     default:
00100       vcl_cerr << "msm_box_limiter::b_read() :\n"
00101                << "Unexpected version number " << version << '\n';
00102       bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00103       return;
00104   }
00105 }
00106 
00107 vcl_string msm_box_limiter::is_a() const
00108 {
00109   return vcl_string("msm_box_limiter");
00110 }
00111 
00112 //: Create a copy on the heap and return base class pointer
00113 msm_param_limiter* msm_box_limiter::clone() const
00114 {
00115   return new msm_box_limiter(*this);
00116 }
00117 
00118 
00119 //: Initialise from a text stream.
00120 // The default implementation is for attribute-less normalisers,
00121 // and throws if it finds any data in the stream.
00122 void msm_box_limiter::config_from_stream(vcl_istream &is)
00123 {
00124   vcl_string s = mbl_parse_block(is);
00125 
00126   vcl_istringstream ss(s);
00127   mbl_read_props_type props = mbl_read_props_ws(ss);
00128 
00129   accept_prop_=vul_string_atof(props.get_optional_property("accept_prop","0.98"));
00130 
00131   mbl_read_props_look_for_unused_props(
00132       "msm_ellipsoid_limiter::config_from_stream", props, mbl_read_props_type());
00133 }