contrib/mul/msm/msm_param_limiter.cxx
Go to the documentation of this file.
00001 #include "msm_param_limiter.h"
00002 //:
00003 // \file
00004 // \author Tim Cootes
00005 // \brief Base for objects with apply limits to parameters
00006 
00007 #include <vsl/vsl_indent.h>
00008 #include <vsl/vsl_binary_loader.h>
00009 #include <mbl/mbl_cloneables_factory.h>
00010 #include <mbl/mbl_parse_block.h>
00011 #include <mbl/mbl_exception.h>
00012 #include <vnl/vnl_gamma.h>
00013 
00014 
00015 //=======================================================================
00016 
00017 void vsl_add_to_binary_loader(const msm_param_limiter& b)
00018 {
00019   vsl_binary_loader<msm_param_limiter>::instance().add(b);
00020 }
00021 
00022 //=======================================================================
00023 
00024 void vsl_b_write(vsl_b_ostream& bfs, const msm_param_limiter& b)
00025 {
00026   b.b_write(bfs);
00027 }
00028 
00029 //=======================================================================
00030 //: Initialise from a text stream.
00031 // The default implementation is for attribute-less normalisers,
00032 // and throws if it finds any data in the stream.
00033 void msm_param_limiter::config_from_stream(vcl_istream &is)
00034 {
00035   vcl_string s = mbl_parse_block(is);
00036   if (s.empty() || s=="{}") return;
00037 
00038   mbl_exception_parse_error x(
00039     this->is_a() + " expects no properties in initialisation,\n"
00040     "But the following properties were given:\n" + s);
00041   mbl_exception_error(x);
00042 }
00043 
00044 
00045 //=======================================================================
00046 //: Create a concrete msm_param_limiter-derived object, from a text specification.
00047 vcl_auto_ptr<msm_param_limiter> msm_param_limiter::create_from_stream(vcl_istream &is)
00048 {
00049   vcl_string name;
00050   is >> name;
00051 
00052   vcl_auto_ptr<msm_param_limiter> ps =
00053     mbl_cloneables_factory<msm_param_limiter>::get_clone(name);
00054 
00055   ps -> config_from_stream(is);
00056   return ps;
00057 }
00058 
00059 //=======================================================================
00060 
00061 void vsl_b_read(vsl_b_istream& bfs, msm_param_limiter& b)
00062 {
00063   b.b_read(bfs);
00064 }
00065 
00066 //=======================================================================
00067 
00068 vcl_ostream& operator<<(vcl_ostream& os,const msm_param_limiter& b)
00069 {
00070   os << b.is_a() << ": ";
00071   vsl_indent_inc(os);
00072   b.print_summary(os);
00073   vsl_indent_dec(os);
00074   return os;
00075 }
00076 
00077 //=======================================================================
00078 
00079 vcl_ostream& operator<<(vcl_ostream& os,const msm_param_limiter* b)
00080 {
00081   if (b)
00082     return os << *b;
00083   else
00084     return os << "No msm_param_limiter defined.";
00085 }
00086 
00087 //=======================================================================
00088 //: Stream output operator for class reference
00089 void vsl_print_summary(vcl_ostream& os,const msm_param_limiter& b)
00090 {
00091   os << b;
00092 }
00093 
00094 //=======================================================================
00095 //: Stream output operator for class reference
00096 void vsl_print_summary(vcl_ostream& os,const msm_param_limiter* b)
00097 {
00098   if (b)
00099     os << *b;
00100   else
00101     os << vsl_indent() << "No msm_param_limiter defined.";
00102 }
00103 
00104 //: Returns X such that P(chi<X | dof==n)==p
00105 double msm_chi2_for_cum_prob(double p, int n_dof, double tol)
00106 {
00107   if ((p<0) | (p>=1.0))
00108     mbl_exception_error(mbl_exception_abort("msm_chi2_for_cum_prob:"
00109       "Illegal value for probability. (Outside range [0,1) )"));
00110 
00111   if (p==0) return 0;
00112 
00113   double d_step = n_dof; // prob = 50% ish
00114   double low_chi = 0;
00115   double high_chi = d_step;
00116 
00117   double p_high = vnl_cum_prob_chi2(n_dof,high_chi);
00118 
00119   // Perform binary search for solution
00120 
00121   // First step along till p_high >= p
00122   while (p_high<p)
00123   {
00124     low_chi = high_chi;
00125     high_chi += d_step;
00126     p_high = vnl_cum_prob_chi2(n_dof,high_chi);
00127   }
00128 
00129   // p_low and p_high now straddle answer
00130   double mid_chi = 0.5 * (low_chi+high_chi);
00131   double p_mid;
00132 
00133   while ((mid_chi-low_chi)>tol)
00134   {
00135     p_mid = vnl_cum_prob_chi2(n_dof,mid_chi);
00136     if (p_mid>p)
00137     {
00138       // Use low & mid as limits
00139       high_chi = mid_chi;
00140     }
00141     else
00142     {
00143       // Use mid and high as limits
00144       low_chi = mid_chi;
00145     }
00146 
00147     mid_chi = 0.5 * (low_chi+high_chi);
00148   }
00149 
00150   return mid_chi;
00151 }