contrib/mul/mbl/mbl_sample_stats_1d.cxx
Go to the documentation of this file.
00001 #include "mbl_sample_stats_1d.h"
00002 //:
00003 // \file
00004 #include <vsl/vsl_vector_io.h>
00005 #include <vcl_cassert.h>
00006 #include <vcl_cmath.h>
00007 #include <vcl_limits.h>
00008 #include <vcl_algorithm.h>
00009 
00010 
00011 //=========================================================================
00012 mbl_sample_stats_1d::mbl_sample_stats_1d(const vcl_vector<double> &samples)
00013 {
00014   clear();
00015   for (unsigned i=0, n=samples.size(); i<n; ++i)
00016   {
00017     add_sample(samples[i]);
00018   }
00019 }
00020 
00021 
00022 //=========================================================================
00023 mbl_sample_stats_1d::mbl_sample_stats_1d(const vnl_vector<double> &samples)
00024 {
00025   clear();
00026   for (unsigned i=0, n=samples.size(); i<n; ++i)
00027   {
00028     add_sample(samples[i]);
00029   }
00030 }
00031 
00032 
00033 //=========================================================================
00034 mbl_sample_stats_1d::mbl_sample_stats_1d()
00035 {
00036   clear();
00037 }
00038 
00039 
00040 //=========================================================================
00041 mbl_sample_stats_1d::~mbl_sample_stats_1d()
00042 {
00043 }
00044 
00045 
00046 //=========================================================================
00047 void mbl_sample_stats_1d::clear()
00048 {
00049   samples_.resize(0);
00050   stats_1d_.clear();
00051   use_mvue_=true;
00052 }
00053 
00054 
00055 //=========================================================================
00056 void mbl_sample_stats_1d::add_sample(double v)
00057 {
00058   stats_1d_.obs(v);
00059   samples_.push_back(v);
00060   return;
00061 }
00062 
00063 
00064 //=========================================================================
00065 unsigned mbl_sample_stats_1d::n_samples() const
00066 {
00067   return samples_.size();
00068 }
00069 
00070 
00071 //=========================================================================
00072 double mbl_sample_stats_1d::mean() const
00073 {
00074   return stats_1d_.mean();
00075 }
00076 
00077 
00078 //=========================================================================
00079 double mbl_sample_stats_1d::mean_of_absolutes() const
00080 {
00081   double abs_sum = 0;
00082   for (unsigned i=0, n=samples_.size(); i<n; ++i)
00083     abs_sum+=vcl_fabs(samples_[i]);
00084   return abs_sum/samples_.size();
00085 }
00086 
00087 
00088 //=========================================================================
00089 double mbl_sample_stats_1d::median() const
00090 {
00091   //     return nth_percentile(50);
00092   double ret;
00093 
00094   if (samples_.size()>0)
00095   {
00096     if ( samples_.size() % 2 == 0 )
00097     {
00098       unsigned index = samples_.size() / 2 - 1;
00099 
00100       vcl_vector<double> tmp=samples_;
00101       vcl_vector<double>::iterator index_it0 = tmp.begin() + index;
00102       vcl_nth_element(tmp.begin(),index_it0,tmp.end(),vcl_less<double>());
00103       vcl_vector<double>::iterator index_it1 = tmp.begin() + index + 1;
00104       vcl_nth_element(tmp.begin(),index_it1,tmp.end(),vcl_less<double>());
00105 
00106       ret = (*index_it0 + *index_it1);
00107       ret /= 2.0;
00108     }
00109     else
00110     {
00111       unsigned index = (samples_.size() - 1) / 2;
00112 
00113       vcl_vector<double> tmp=samples_;
00114       vcl_vector<double>::iterator index_it = tmp.begin() + index;
00115       vcl_nth_element(tmp.begin(),index_it,tmp.end(),vcl_less<double>());
00116 
00117       ret = *index_it;
00118     }
00119   }
00120   else // crazy value if  no samples
00121   {
00122     ret = vcl_numeric_limits<double>::max();
00123   }
00124   return ret;
00125 }
00126 
00127 
00128 //=========================================================================
00129 double mbl_sample_stats_1d::quantile(double q) const
00130 {
00131   const unsigned n = samples_.size();
00132 
00133   // These checks are only asserts because client code is responsible for avoiding these errors.
00134   assert(q>=0.0 && q<=1.0);
00135   assert(n>0);
00136 
00137   // Map the specified quantile to a real-valued "index", i.e. a float lying between 2 integer indices
00138   double float_index = (n-1)*q;
00139 
00140   // Get the integer index immediately below (and enforce the bounds)
00141   double f0 = vcl_floor(float_index);
00142   f0 = f0<0.0 ? 0.0 : f0>n-1.0 ? n-1.0 : f0;
00143   unsigned i0 = static_cast<unsigned>(f0);
00144 
00145   // Get the integer index immediately above (and enforce the bounds)
00146   double f1 = vcl_ceil(float_index);
00147   f1 = f1<0.0 ? 0.0 : f1>n-1.0 ? n-1.0 : f1;
00148   unsigned i1 = static_cast<unsigned>(f1);
00149 
00150   // Get the 2 values bracketing the specified quantile position
00151   vcl_vector<double> tmp = samples_;
00152   vcl_vector<double>::iterator index_it0 = tmp.begin() + i0;
00153   vcl_nth_element(tmp.begin(), index_it0, tmp.end(), vcl_less<double>());
00154   vcl_vector<double>::iterator index_it1 = tmp.begin() + i1;
00155   vcl_nth_element(tmp.begin(), index_it1, tmp.end(), vcl_less<double>());
00156 
00157   // Linearly interpolate between the 2 values
00158   double f = float_index - f0;
00159   double ret = (1.0-f)*(*index_it0) + (f)*(*index_it1);
00160   return ret;
00161 }
00162 
00163 
00164 //=========================================================================
00165 double mbl_sample_stats_1d::nth_percentile(int n) const
00166 {
00167   if (samples_.size()==0)
00168     return vcl_numeric_limits<double>::max();
00169 
00170   double fact = double(n)/100.0;
00171   int index=int(fact*(samples_.size()-1));
00172   vcl_vector<double> tmp=samples_;
00173   vcl_vector<double>::iterator index_it = tmp.begin() + index;
00174   vcl_nth_element(tmp.begin(),index_it,tmp.end(),vcl_less<double>());
00175   double ret = *index_it;
00176   return ret;
00177 }
00178 
00179 
00180 //=========================================================================
00181 double mbl_sample_stats_1d::variance() const
00182 {
00183   double v=0;
00184 
00185   if (samples_.size()>1)
00186   {
00187     double mean_v = mean();
00188     double sum_sq = sum_squares();
00189     v = sum_sq - samples_.size()*(mean_v * mean_v);
00190 
00191     if (use_mvue_)
00192     {
00193       v /= (samples_.size()-1);
00194     }
00195     else
00196     {
00197       v /= samples_.size();
00198     }
00199   }
00200 
00201   return v;
00202 }
00203 
00204 
00205 //=========================================================================
00206 double mbl_sample_stats_1d::sd() const
00207 {
00208   return vcl_sqrt(variance());
00209 }
00210 
00211 
00212 //=========================================================================
00213 double mbl_sample_stats_1d::stdError() const
00214 {
00215   double se = variance();
00216   if (use_mvue_)
00217   {
00218     se /= samples_.size()-1;
00219   }
00220   else
00221   {
00222     se /= samples_.size();
00223   }
00224 
00225   return vcl_sqrt(se);
00226 }
00227 
00228 
00229 //=========================================================================
00230 double mbl_sample_stats_1d::skewness() const
00231 {
00232   double skew = 0;
00233 
00234   // skew
00235   // calculated as
00236   // ( Sum_i (Y_i-MEAN)^3 ) / ((N-1)*sigma^3)
00237   // where N is the number of samples
00238   // sigma is the standard deviation
00239 
00240   if (samples_.size()>1)
00241   {
00242     double s=sd();
00243     double m=mean();
00244 
00245     for (unsigned i=0, n=samples_.size(); i<n; ++i)
00246     {
00247       double tmp=samples_[i]-m;
00248       skew += (tmp*tmp*tmp) ;
00249     }
00250 
00251     skew /= ( (samples_.size()-1) * s * s * s );
00252   }
00253 
00254   return skew;
00255 }
00256 
00257 
00258 //=========================================================================
00259 double mbl_sample_stats_1d::kurtosis() const
00260 {
00261   double kurt = 0;
00262 
00263   // kurtosis
00264   // calculated as
00265   // -3 + ( Sum_i (Y_i-MEAN)^4 ) / ((N-1)*sigma^4)
00266   // where N is the number of samples
00267   // sigma is the standard deviation
00268 
00269   if (samples_.size()>1)
00270   {
00271     double s=sd();
00272     double m=mean();
00273 
00274     for (unsigned i=0, n=samples_.size(); i<n; ++i)
00275     {
00276       double tmp=samples_[i]-m;
00277       kurt += (tmp*tmp*tmp*tmp) ;
00278     }
00279 
00280     kurt /= ( (samples_.size()-1) * s * s * s *s);
00281     kurt -= 3;
00282   }
00283   return kurt;
00284 }
00285 
00286 
00287 //=========================================================================
00288 double mbl_sample_stats_1d::min() const
00289 {
00290   if (samples_.size()==0) return vcl_numeric_limits<double>::max();
00291   else return stats_1d_.min();
00292 }
00293 
00294 
00295 //=========================================================================
00296 double mbl_sample_stats_1d::max() const
00297 {
00298   if (samples_.size()==0) return vcl_numeric_limits<double>::min();
00299   else return stats_1d_.max();
00300 }
00301 
00302 
00303 //=========================================================================
00304 double mbl_sample_stats_1d::sum() const
00305 {
00306   return stats_1d_.sum();
00307 }
00308 
00309 
00310 //=========================================================================
00311 double mbl_sample_stats_1d::sum_squares() const
00312 {
00313   return stats_1d_.sumSq();
00314 }
00315 
00316 
00317 //=========================================================================
00318 double mbl_sample_stats_1d::rms() const
00319 {
00320   double ms=sum_squares()/stats_1d_.nObs();
00321   return vcl_sqrt( ms );
00322 }
00323 
00324 
00325 //=========================================================================
00326 mbl_sample_stats_1d& mbl_sample_stats_1d::operator+=(const mbl_sample_stats_1d& s1)
00327 {
00328   // add new samples
00329   for (unsigned i=0;i<s1.samples().size();++i)
00330   {
00331     add_sample(s1.samples()[i]);
00332   }
00333 
00334   return *this ;
00335 }
00336 
00337 
00338 //=========================================================================
00339 // Test for equality
00340 bool mbl_sample_stats_1d::operator==(const mbl_sample_stats_1d& s) const
00341 {
00342   return samples_==s.samples_ && use_mvue_==s.use_mvue_;
00343 }
00344 
00345 // =============================================
00346 short mbl_sample_stats_1d::version_no() const
00347 {
00348   return 1;
00349 }
00350 
00351 
00352 //=========================================================================
00353 void mbl_sample_stats_1d::b_write(vsl_b_ostream& bfs) const
00354 {
00355   vsl_b_write(bfs,version_no());
00356   vsl_b_write(bfs,samples_);
00357   vsl_b_write(bfs,stats_1d_);
00358   vsl_b_write(bfs,use_mvue_);
00359 }
00360 
00361 
00362 //=========================================================================
00363 void mbl_sample_stats_1d::b_read(vsl_b_istream& bfs)
00364 {
00365   if (!bfs) return;
00366 
00367   short file_version_no;
00368   vsl_b_read(bfs,file_version_no);
00369 
00370   switch (file_version_no)
00371   {
00372   case 1:
00373     vsl_b_read(bfs,samples_);
00374     vsl_b_read(bfs,stats_1d_);
00375     vsl_b_read(bfs,use_mvue_);
00376     break;
00377   default :
00378     vcl_cerr << "I/O ERROR: mbl_sample_stats_1d::b_read(vsl_b_istream&)\n"
00379              << "           Unknown version number "<< file_version_no << '\n';
00380     bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00381     return;
00382   }
00383 }
00384 
00385 
00386 //=========================================================================
00387 void mbl_sample_stats_1d::print_summary(vcl_ostream& os) const
00388 {
00389   os << "mbl_sample_stats_1d: ";
00390   if (samples_.size()==0)
00391   {
00392     os << "No samples.";
00393   }
00394   else
00395   {
00396     os << "mean: "<< mean()
00397        << " use MVUE: "<< use_mvue_
00398        << " sd: "<< sd()
00399        << " ["<<stats_1d_.min()<<','<<stats_1d_.max()<<"] N:"<<samples_.size();
00400   }
00401 }
00402 
00403 
00404 //=========================================================================
00405 // Print all data
00406 void mbl_sample_stats_1d::print_all(vcl_ostream& os,
00407                                     const vcl_string& delim/*="\n"*/) const
00408 {
00409   unsigned nSamples = samples_.size();
00410   for (unsigned i=0; i<nSamples; ++i)
00411   {
00412     os << samples_[i] << delim;
00413   }
00414 }
00415 
00416 
00417 //=========================================================================
00418 vcl_ostream& operator<<(vcl_ostream& os, const mbl_sample_stats_1d& stats)
00419 {
00420   stats.print_summary(os);
00421   return os;
00422 }
00423 
00424 
00425 //=========================================================================
00426 // Stream output operator for class reference
00427 void vsl_print_summary(vcl_ostream& os,const mbl_sample_stats_1d& stats)
00428 {
00429   stats.print_summary(os);
00430 }
00431 
00432 
00433 //=========================================================================
00434 // Print all data
00435 void vsl_print_all(vcl_ostream& os, const mbl_sample_stats_1d& stats)
00436 {
00437   stats.print_all(os);
00438 }
00439 
00440 
00441 //=========================================================================
00442 mbl_sample_stats_1d operator+(const mbl_sample_stats_1d& s1, const mbl_sample_stats_1d& s2)
00443 {
00444   mbl_sample_stats_1d r = s1;
00445   r+=s2;
00446 
00447   return r;
00448 }
00449 
00450 
00451 //=========================================================================
00452 // Binary file stream output operator for class reference
00453 void vsl_b_write(vsl_b_ostream& bfs, const mbl_sample_stats_1d& b)
00454 {
00455   b.b_write(bfs);
00456 }
00457 
00458 
00459 //=========================================================================
00460 // Binary file stream input operator for class reference
00461 void vsl_b_read(vsl_b_istream& bfs, mbl_sample_stats_1d& b)
00462 {
00463   b.b_read(bfs);
00464 }
00465