Go to the documentation of this file.00001 #include "msm_ellipsoid_limiter.h"
00002
00003
00004
00005
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_ellipsoid_limiter::msm_ellipsoid_limiter()
00017 : M_max_(3.0),accept_prop_(0.98)
00018 {
00019 }
00020
00021
00022 void msm_ellipsoid_limiter::set_n_sds(double n_sds)
00023 {
00024 M_max_ = n_sds*n_sds;
00025 }
00026
00027
00028 void msm_ellipsoid_limiter::set_param_var(const vnl_vector<double>& v)
00029 {
00030 mode_var_=v;
00031 set_acceptance(accept_prop_);
00032 }
00033
00034
00035
00036
00037
00038
00039 void msm_ellipsoid_limiter::set_acceptance(double prop,
00040 unsigned n_modes)
00041 {
00042 assert(prop>=0 && prop<=1.0);
00043 accept_prop_ = prop;
00044 if (n_modes==0) n_modes=mode_var_.size();
00045 M_max_ = msm_chi2_for_cum_prob(prop,n_modes);
00046 }
00047
00048
00049 double msm_ellipsoid_limiter::mahalanobis(const vnl_vector<double>& b) const
00050 {
00051
00052 double M=0.0;
00053 for (unsigned i=0;i<b.size();++i)
00054 M += b[i]*b[i]/mode_var_[i];
00055 return M;
00056 }
00057
00058
00059
00060
00061 double msm_ellipsoid_limiter::slide_closer(vnl_vector<double>& b,
00062 const vnl_vector<double>& y) const
00063 {
00064 unsigned n=b.size();
00065 vnl_vector<double> u(n);
00066 for (unsigned i=0;i<n;++i) u[i]=b[i]/mode_var_[i];
00067
00068 double s = (dot_product(u,y)-M_max_)/u.squared_magnitude();
00069
00070
00071 vnl_vector<double> b1 = y-s*u;
00072
00073
00074 b1 *= vcl_sqrt(M_max_/mahalanobis(b1));
00075
00076 double d2=vnl_vector_ssd(b,b1)/n;
00077
00078 b=b1;
00079 return d2/mode_var_[n-1];
00080 }
00081
00082
00083
00084 void msm_ellipsoid_limiter::apply_limit(vnl_vector<double>& b) const
00085 {
00086
00087 double M=mahalanobis(b);
00088
00089 if (M<M_max_) return;
00090
00091
00092
00093
00094 vnl_vector<double> b0=b;
00095
00096
00097 b*=vcl_sqrt(M_max_/M);
00098
00099
00100
00101
00102
00103 unsigned n_its=0;
00104 while (slide_closer(b,b0)>1e-6 && n_its<10) { n_its++; };
00105 }
00106
00107
00108
00109 void msm_ellipsoid_limiter::print_summary(vcl_ostream& os) const
00110 {
00111 os<<" { M_max: "<<M_max_ <<" accept_prop: "<<accept_prop_<<" } ";
00112 }
00113
00114 const static short version_no = 1;
00115
00116
00117 void msm_ellipsoid_limiter::b_write(vsl_b_ostream& bfs) const
00118 {
00119 vsl_b_write(bfs,version_no);
00120 vsl_b_write(bfs,mode_var_);
00121 vsl_b_write(bfs,accept_prop_);
00122 vsl_b_write(bfs,M_max_);
00123 }
00124
00125
00126
00127 void msm_ellipsoid_limiter::b_read(vsl_b_istream& bfs)
00128 {
00129 short version;
00130 vsl_b_read(bfs,version);
00131 switch (version)
00132 {
00133 case (1):
00134 vsl_b_read(bfs,mode_var_);
00135 vsl_b_read(bfs,accept_prop_);
00136 vsl_b_read(bfs,M_max_);
00137 break;
00138 default:
00139 vcl_cerr << "msm_ellipsoid_limiter::b_read() :\n"
00140 << "Unexpected version number " << version << '\n';
00141 bfs.is().clear(vcl_ios::badbit);
00142 return;
00143 }
00144 }
00145
00146 vcl_string msm_ellipsoid_limiter::is_a() const
00147 {
00148 return vcl_string("msm_ellipsoid_limiter");
00149 }
00150
00151
00152 msm_param_limiter* msm_ellipsoid_limiter::clone() const
00153 {
00154 return new msm_ellipsoid_limiter(*this);
00155 }
00156
00157
00158
00159
00160 void msm_ellipsoid_limiter::config_from_stream(vcl_istream &is)
00161 {
00162 vcl_string s = mbl_parse_block(is);
00163
00164 vcl_istringstream ss(s);
00165 mbl_read_props_type props = mbl_read_props_ws(ss);
00166
00167 accept_prop_=vul_string_atof(props.get_optional_property("accept_prop","0.98"));
00168
00169 mbl_read_props_look_for_unused_props(
00170 "msm_ellipsoid_limiter::config_from_stream", props, mbl_read_props_type());
00171 }
00172