Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "pdf1d_kernel_pdf.h"
00013 #include <vcl_cstdlib.h>
00014 #include <vcl_cassert.h>
00015 #include <vcl_string.h>
00016 #include <vnl/vnl_math.h>
00017 #include <vnl/io/vnl_io_vector.h>
00018 #include <mbl/mbl_index_sort.h>
00019 #include <pdf1d/pdf1d_calc_mean_var.h>
00020
00021
00022
00023 pdf1d_kernel_pdf::pdf1d_kernel_pdf()
00024 {
00025 }
00026
00027
00028
00029 pdf1d_kernel_pdf::~pdf1d_kernel_pdf()
00030 {
00031 }
00032
00033
00034
00035 void pdf1d_kernel_pdf::set_centres(const vnl_vector<double>& x, double width)
00036 {
00037 x_ = x;
00038 width_.set_size(x.size());
00039 width_.fill(width);
00040 all_same_width_ = true;
00041
00042 double m,v;
00043 pdf1d_calc_mean_var(m,v,x);
00044 set_mean(m);
00045 set_variance(v+width*width);
00046 }
00047
00048
00049
00050 void pdf1d_kernel_pdf::set_centres(const vnl_vector<double>& x,
00051 const vnl_vector<double>& width)
00052 {
00053 assert(x.size()==width.size());
00054 x_ = x;
00055 width_= width;
00056 all_same_width_ = false;
00057
00058 double m,v;
00059 pdf1d_calc_mean_var(m,v,x);
00060 double w_sd = width.rms();
00061 set_mean(m);
00062 set_variance(v+w_sd*w_sd);
00063 index_.clear();
00064 }
00065
00066
00067
00068
00069 double pdf1d_kernel_pdf::inverse_cdf(double P) const
00070 {
00071 assert (cdf_is_analytic());
00072 assert (0.0 < P && P < 1.0);
00073
00074 if (index_.empty())
00075 mbl_index_sort(x_.data_block(), x_.size(), index_);
00076
00077
00078 double x_init=x_(index_[int(P * x_.size())]);
00079
00080 double f_init = cdf(x_init);
00081
00082
00083 double step = width_(index_[int(P * x_.size())]);
00084
00085 double x_above, x_below;
00086 if (f_init > P)
00087 {
00088 x_above = x_init;
00089 while (true)
00090 {
00091 x_below = x_above - step;
00092 double f_below = cdf(x_below);
00093 if (f_below < P) break;
00094 x_above = x_below;
00095 step *= 2.0;
00096 }
00097 }
00098 else
00099 {
00100 x_below = x_init;
00101 while (true)
00102 {
00103 x_above = x_below + step;
00104 double f_above = cdf(x_above);
00105 if (f_above > P) break;
00106 x_below = x_above;
00107 step *= 2.0;
00108 }
00109 }
00110 #if 0
00111 double x_middle = (x_above + x_below) / 2;
00112 while (x_above - x_below > vnl_math::sqrteps)
00113 {
00114 double f_middle = pdf.cdf(x_middle) - P;
00115 if (f_middle < 0) x_below=x_middle;
00116 else x_above = x_middle;
00117 }
00118 return (x_above + x_below) / 2;
00119 #endif
00120
00121
00122
00123 double x_middle=0.5*(x_above+x_below);
00124 double dxold= x_above-x_below;
00125 double dx=dxold;
00126 double f_middle = cdf(x_middle)-P;
00127 double df_middle = operator() (x_middle);
00128 for (unsigned j=100;j>0;j--)
00129 {
00130 if ( !((x_above - x_middle)*df_middle + f_middle > 0.0 &&
00131 (x_below - x_middle)*df_middle + f_middle < 0.0 ) ||
00132 (vnl_math_abs((2.0*f_middle)) > vnl_math_abs(dxold*df_middle)))
00133 {
00134 x_middle=0.5*(x_above+x_below);
00135 dxold=dx;
00136 dx=x_above-x_middle;
00137 } else
00138 {
00139 dxold=dx;
00140 dx=f_middle/df_middle;
00141 x_middle -= dx;
00142 assert (x_below <= x_middle && x_middle <= x_above);
00143 }
00144
00145 if (vnl_math_abs(dx) < vnl_math_abs(x_middle * vnl_math::sqrteps))
00146 {
00147 return x_middle;
00148 }
00149
00150 f_middle = cdf(x_middle)-P;
00151 df_middle = operator()(x_middle);
00152
00153 if (f_middle < 0)
00154 x_below=x_middle;
00155 else
00156 x_above=x_middle;
00157 }
00158 vcl_cerr << "ERROR: pdf1d_kernel_pdf::inverse_cdf() failed to converge.\n";
00159 vcl_abort();
00160 return 0.0;
00161 }
00162
00163
00164
00165 vcl_string pdf1d_kernel_pdf::is_a() const
00166 {
00167 static vcl_string class_name_ = "pdf1d_kernel_pdf";
00168 return class_name_;
00169 }
00170
00171
00172
00173 bool pdf1d_kernel_pdf::is_class(vcl_string const& s) const
00174 {
00175 return pdf1d_pdf::is_class(s) || s==pdf1d_kernel_pdf::is_a();
00176 }
00177
00178
00179
00180 short pdf1d_kernel_pdf::version_no() const
00181 {
00182 return 1;
00183 }
00184
00185
00186
00187 void pdf1d_kernel_pdf::print_summary(vcl_ostream& os) const
00188 {
00189 pdf1d_pdf::print_summary(os);
00190 os << '\n';
00191 }
00192
00193
00194
00195 void pdf1d_kernel_pdf::b_write(vsl_b_ostream& bfs) const
00196 {
00197 vsl_b_write(bfs,is_a());
00198 vsl_b_write(bfs,version_no());
00199 pdf1d_pdf::b_write(bfs);
00200 vsl_b_write(bfs,x_);
00201 vsl_b_write(bfs,width_);
00202 }
00203
00204
00205
00206 void pdf1d_kernel_pdf::b_read(vsl_b_istream& bfs)
00207 {
00208 if (!bfs) return;
00209
00210 vcl_string name;
00211 vsl_b_read(bfs,name);
00212 if (name != is_a())
00213 {
00214 vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, pdf1d_kernel_pdf &)\n"
00215 << " Attempted to load object of type "
00216 << name <<" into object of type " << is_a() << '\n';
00217 bfs.is().clear(vcl_ios::badbit);
00218 return;
00219 }
00220
00221 short version;
00222 vsl_b_read(bfs,version);
00223 switch (version)
00224 {
00225 case (1):
00226 pdf1d_pdf::b_read(bfs);
00227 vsl_b_read(bfs,x_);
00228 vsl_b_read(bfs,width_);
00229 break;
00230 default:
00231 vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, pdf1d_kernel_pdf &)\n"
00232 << " Unknown version number "<< version << '\n';
00233 bfs.is().clear(vcl_ios::badbit);
00234 return;
00235 }
00236 }
00237