contrib/brl/bbas/bsta/bsta_histogram.txx
Go to the documentation of this file.
00001 #ifndef bsta_histogram_txx_
00002 #define bsta_histogram_txx_
00003 //:
00004 // \file
00005 #include "bsta_histogram.h"
00006 
00007 #include <vcl_cmath.h> // for log()
00008 #include <vcl_iostream.h>
00009 #include <vcl_cassert.h>
00010 #include "bsta_gauss.h"
00011 #include <vnl/vnl_math.h> // for log2e == 1/vcl_log(2.0)
00012 
00013 template <class T>
00014 bsta_histogram<T>::bsta_histogram()
00015   : area_valid_(false), area_(0), nbins_(0), range_(0),
00016     delta_(0),min_prob_(0), min_(0), max_(0)
00017 {
00018   bsta_histogram_base::type_ = bsta_histogram_traits<T>::type();
00019 }
00020 
00021 template <class T>
00022 bsta_histogram<T>::bsta_histogram(const T range, const unsigned int nbins,
00023                                   const T min_prob)
00024   : area_valid_(false), area_(0), nbins_(nbins), range_(range),
00025     delta_(0),min_prob_(min_prob), min_(0), max_(range)
00026 {
00027   bsta_histogram_base::type_ = bsta_histogram_traits<T>::type();
00028   if (nbins>0)
00029   {
00030     delta_ = range_/nbins;
00031     counts_.resize(nbins, T(0));
00032   }
00033 }
00034 
00035 template <class T>
00036 bsta_histogram<T>::bsta_histogram(const T min, const T max,
00037                                   const unsigned int nbins,
00038                                   const T min_prob)
00039   : area_valid_(false), area_(0), nbins_(nbins), delta_(0),
00040     min_prob_(min_prob), min_(min), max_(max)
00041 {
00042   bsta_histogram_base::type_ = bsta_histogram_traits<T>::type();
00043   if (nbins>0)
00044   {
00045     range_ = max-min;
00046     delta_ = range_/nbins;
00047     counts_.resize(nbins, T(0));
00048   }
00049   else
00050   {
00051     range_ = 0;
00052     delta_ = 0;
00053   }
00054 }
00055 
00056 template <class T>
00057 bsta_histogram<T>::bsta_histogram(const unsigned int nbins, const T min, const T delta,
00058                                   const T min_prob)
00059  : area_valid_(false), area_(0), nbins_(nbins), delta_(delta),
00060     min_prob_(min_prob), min_(min), max_(min+nbins*delta)
00061 {
00062   bsta_histogram_base::type_ = bsta_histogram_traits<T>::type();
00063   if (nbins>0)
00064   {
00065     range_ = max_-min_;
00066     counts_.resize(nbins, T(0));
00067   }
00068   else
00069    range_ = 0;
00070 }
00071 
00072 template <class T>
00073 bsta_histogram<T>::bsta_histogram(const T min, const T max,
00074                                   vcl_vector<T> const& data, const T min_prob)
00075   : area_valid_(false), area_(0), delta_(0), min_prob_(min_prob),
00076     min_(min), max_(max), counts_(data)
00077 {
00078   bsta_histogram_base::type_ = bsta_histogram_traits<T>::type();
00079   nbins_ = data.size();
00080   range_ = max-min;
00081   if (nbins_>0)
00082     delta_ = range_/nbins_;
00083   else
00084     delta_ = 0;
00085 }
00086 
00087 template <class T>
00088 void bsta_histogram<T>::upcount(T x, T mag)
00089 {
00090   if (x<min_||x>max_)
00091     return;
00092   for (unsigned int i = 0; i<nbins_; ++i)
00093     if (T((i+1)*delta_) + min_ >= x)
00094     {
00095       counts_[i] += mag;
00096       break;
00097     }
00098   area_valid_ = false;
00099 }
00100 
00101 template <class T>
00102 
00103 int bsta_histogram<T>::bin_at_val(T x)
00104 {
00105   if (x<min_||x>max_)
00106     return -1;
00107   for (unsigned int i = 0; i<nbins_; ++i)
00108     if (T((i+1)*delta_) + min_ >= x)
00109     {
00110       return i;
00111     }
00112   return -1;
00113 }
00114 
00115 template <class T>
00116 void bsta_histogram<T>::compute_area() const
00117 {
00118   area_ =0;
00119   for (unsigned int i = 0; i<nbins_; ++i)
00120     area_ += counts_[i];
00121   area_valid_ = true;
00122 }
00123 
00124 template <class T>
00125 T bsta_histogram<T>::cumulative_area(unsigned bin) const
00126 {
00127   T area =0;
00128   for (unsigned int i = 0; i<bin; ++i)
00129     area += counts_[i];
00130   return area;
00131 }
00132 
00133 template <class T>
00134 T bsta_histogram<T>::p(unsigned int bin) const
00135 {
00136   if (bin>=nbins_)
00137     return 0;
00138   if (!area_valid_)
00139     compute_area();
00140   if (area_ == T(0))
00141     return 0;
00142   else
00143     return counts_[bin]/area_;
00144 }
00145 
00146 template <class T>
00147 T bsta_histogram<T>::p(const T val) const
00148 {
00149   if (val<min_||val>max_)
00150     return 0;
00151   if (!area_valid_)
00152     compute_area();
00153   if (area_ == T(0))
00154     return 0;
00155   else
00156     for (unsigned int i = 0; i<nbins_; ++i)
00157       if (T((i+1)*delta_) + min_ >= val)
00158         return counts_[i]/area_;
00159   return 0;
00160 }
00161 
00162 template <class T>
00163 T bsta_histogram<T>::area() const
00164 {
00165   if (!area_valid_)
00166     compute_area();
00167   return area_;
00168 }
00169 
00170 //: Mean of distribution
00171 template <class T>
00172 T bsta_histogram<T>::mean() const
00173 {
00174   return mean(0, nbins_-1);
00175 }
00176 
00177   //: Mean of distribution between bin indices
00178 template <class T>
00179 T bsta_histogram<T>::mean(const unsigned int lowbin, const unsigned int highbin) const
00180 {
00181   assert(lowbin<=highbin);
00182   assert(highbin<nbins_);
00183   T sum = 0;
00184   T sumx = 0;
00185   for (unsigned i = lowbin; i<=highbin; ++i)
00186   {
00187     sum += counts_[i];
00188     sumx += (i*delta_ + min_)*counts_[i];
00189   }
00190   if (sum==0)
00191     return 0;
00192   T result = sumx/sum;
00193   return result;
00194 }
00195 
00196 template <class T>
00197 T bsta_histogram<T>::mean_vals(const T low, const T high) const
00198 {
00199   //find bin indices
00200   T tlow=low, thigh=high;
00201   if (tlow<min_) tlow = min_;
00202   if (thigh>max_) thigh = max_;
00203   unsigned low_bin=0, high_bin = 0;
00204   for (unsigned int i = 0; i<nbins_; ++i)
00205     if (T((i+1)*delta_) + min_ >= tlow) {
00206       low_bin = i;
00207       break;
00208     }
00209   for (unsigned int i = 0; i<nbins_; ++i)
00210     if (T((i+1)*delta_) + min_ >= thigh) {
00211       high_bin = i;
00212       break;
00213     }
00214   return this->mean(low_bin, high_bin);
00215 }
00216 
00217   //: Variance of distribution
00218 template <class T>
00219 T bsta_histogram<T>::variance() const
00220 {
00221   return variance(0, nbins_-1);
00222 }
00223 
00224   //: Variance of distribution between bin indices
00225 template <class T>
00226 T bsta_histogram<T>::
00227 variance(const unsigned int lowbin, const unsigned int highbin) const
00228 {
00229   assert(lowbin<=highbin);
00230   assert(highbin<nbins_);
00231   T mean = this->mean(lowbin, highbin);
00232   mean -= min_;
00233   T sum = 0;
00234   T sumx2 = 0;
00235   for (unsigned i = lowbin; i<=highbin; ++i)
00236   {
00237     sum += counts_[i];
00238     sumx2 += (i*delta_-mean)*(i*delta_-mean)*counts_[i];
00239   }
00240   if (sum==0)
00241     return 0;
00242   else
00243     return sumx2/sum;
00244 }
00245 
00246 template <class T>
00247 T bsta_histogram<T>::
00248 variance_vals(const T low, const T high) const
00249 {
00250   //find bin indices
00251   T tlow=low, thigh=high;
00252   if (tlow<min_) tlow = min_;
00253   if (thigh>max_) thigh = max_;
00254   unsigned low_bin=0, high_bin = 0;
00255   for (unsigned int i = 0; i<nbins_; ++i)
00256     if (T((i+1)*delta_) + min_ >= tlow) {
00257       low_bin = i;
00258       break;
00259     }
00260   for (unsigned int i = 0; i<nbins_; ++i)
00261     if (T((i+1)*delta_) + min_ >= thigh) {
00262       high_bin = i;
00263       break;
00264     }
00265   return this->variance(low_bin, high_bin);
00266 }
00267 
00268 template <class T>
00269 T bsta_histogram<T>::entropy() const
00270 {
00271   double ent = 0;
00272   for (unsigned int i = 0; i<nbins_; ++i)
00273   {
00274     double pi = this->p(i);
00275     if (pi>min_prob_)
00276       ent -= pi*vcl_log(pi);
00277   }
00278   ent *= vnl_math::log2e;
00279   return T(ent);
00280 }
00281 
00282 template <class T>
00283 T bsta_histogram<T>::renyi_entropy() const
00284 {
00285   double sum = 0, ent = 0;
00286   for (unsigned int i = 0; i<nbins_; ++i)
00287   {
00288     double pi = this->p(i);
00289     sum += pi*pi;
00290   }
00291   if (sum>min_prob_)
00292     ent = - vcl_log(sum)*vnl_math::log2e;
00293   return T(ent);
00294 }
00295 
00296 template <class T>
00297 void bsta_histogram<T>::parzen(const T sigma)
00298 {
00299   if (sigma<=0)
00300     return;
00301   double sd = (double)sigma;
00302   vcl_vector<double> in(nbins_), out(nbins_);
00303   for (unsigned int i=0; i<nbins_; ++i)
00304     in[i]=counts_[i];
00305   bsta_gauss::bsta_1d_gaussian(sd, in, out);
00306   for (unsigned int i=0; i<nbins_; ++i)
00307     counts_[i]=(T)out[i];
00308 }
00309 
00310 //The first non-zero bin starting at index = 0
00311 template <class T>
00312 unsigned bsta_histogram<T>::low_bin()
00313 {
00314   unsigned lowbin=0;
00315   for (; lowbin<nbins_&&counts_[lowbin]==0; ++lowbin) /*nothing*/;
00316   return lowbin;
00317 }
00318 
00319 //The first non-zero bin starting at index = nbins-1
00320 template <class T>
00321 unsigned bsta_histogram<T>::high_bin()
00322 {
00323   unsigned highbin=nbins_-1;
00324   for (; highbin>0&&counts_[highbin]==0; --highbin) /*nothing*/;
00325   return highbin;
00326 }
00327 
00328 // Fraction of area less than value
00329 template <class T>
00330 T bsta_histogram<T>::fraction_below(const T value) const
00331 {
00332  if (value<min_||value>max_)
00333     return 0;
00334   if (!area_valid_)
00335     compute_area();
00336   if (area_ == T(0))
00337     return 0;
00338   T sum = 0, limit=(value-min_);
00339   for (unsigned int i = 0; i<nbins_; ++i)
00340     if (T((i+1)*delta_)<limit)
00341       sum+=counts_[i];
00342     else
00343       return sum/area_;
00344   return 0;
00345 }
00346 
00347 // Fraction of area greater than value
00348 template <class T>
00349 T bsta_histogram<T>::fraction_above(const T value) const
00350 {
00351  if (value<min_||value>max_)
00352     return 0;
00353   if (!area_valid_)
00354     compute_area();
00355   if (area_ == T(0))
00356     return 0;
00357   T sum = 0, limit=(value-min_);
00358   for (unsigned int i = 0; i<nbins_; ++i)
00359     if (T((i+1)*delta_)>limit)
00360       sum+=counts_[i];
00361   return sum/area_;
00362 }
00363 
00364 // Value for area fraction below value
00365 template <class T>
00366 T bsta_histogram<T>::value_with_area_below(const T area_fraction) const
00367 {
00368   if (area_fraction>T(1))
00369     return 0;
00370   if (!area_valid_)
00371     compute_area();
00372   if (area_ == T(0))
00373     return 0;
00374   T sum = 0;
00375   for (unsigned int i=0; i<nbins_; ++i)
00376   {
00377     sum += counts_[i];
00378     if (sum>=area_fraction*area_)
00379       return (i+1)*delta_+min_;
00380   }
00381   return 0;
00382 }
00383 
00384 // Value for area fraction above value
00385 template <class T>
00386 T  bsta_histogram<T>::value_with_area_above(const T area_fraction) const
00387 {
00388   if (area_fraction>T(1))
00389     return 0;
00390   if (!area_valid_)
00391     compute_area();
00392   if (area_ == T(0))
00393     return 0;
00394   T sum = 0;
00395   for (unsigned int i=nbins_-1; i!=0; i--)
00396   {
00397     sum += counts_[i];
00398     if (sum>area_fraction*area_)
00399       return (i+1)*delta_+min_;
00400   }
00401   return 0;
00402 }
00403 
00404 //function to erase all bin counts
00405 template <class T>
00406 void bsta_histogram<T>::clear()
00407 {
00408     area_valid_ = false;
00409     area_ = T(0);
00410     counts_.assign(nbins_,T(0));
00411 }
00412 
00413 template <class T>
00414 void bsta_histogram<T>::print(vcl_ostream& os) const
00415 {
00416   for (unsigned int i=0; i<nbins_; ++i)
00417     if (p(i) > 0)
00418       os << "p[" << i << "]=" << p(i) << '\n';
00419 }
00420 
00421 template <class T>
00422 void bsta_histogram<T>::pretty_print(vcl_ostream& os) const
00423 {
00424   os << "area valid: " << area_valid_ << '\n'
00425      << "area: " << area_ << '\n'
00426      << "number of bins: " <<  nbins_ << '\n'
00427      << "range: " << range_ << '\n'
00428      << "delta: " << delta_ << '\n'
00429      << "min_prob: " << min_prob_ << '\n'
00430      << "min: " << min_ << '\n'
00431      << "max: " << max_ << '\n'
00432      << "counts: ";
00433   for (unsigned i = 0; i < counts_.size() ; ++i)
00434     os << counts_[i] << ' ';
00435   os << '\n';
00436 }
00437 
00438 //: print as a matlab plot command
00439 template <class T>
00440 void bsta_histogram<T>::print_to_m(vcl_ostream& os) const
00441 {
00442   os << "x = [" << min_;
00443   for (unsigned int i=1; i<nbins_; ++i)
00444     os << ", " << min_ + i*delta_;
00445   os << "];\n"
00446      << "y = [" << p((unsigned int)0);
00447   for (unsigned int i=1; i<nbins_; ++i)
00448     os << ", " << p(i);
00449   os << "];\n"
00450      << "bar(x,y,'r')\n";
00451 }
00452 
00453 //: print x and y arrays
00454 template <class T>
00455 void bsta_histogram<T>::print_to_arrays(vcl_ostream& os) const
00456 {
00457   os << min_;
00458   for (unsigned int i=1; i<nbins_; ++i)
00459     os << ", " << min_ + i*delta_;
00460   os << '\n'
00461      << p((unsigned int)0);
00462   for (unsigned int i=1; i<nbins_; ++i)
00463     os << ", " << p(i);
00464   os << '\n';
00465 }
00466 
00467 template <class T>
00468 void bsta_histogram<T>::print_vals_prob(vcl_ostream& os) const
00469 {
00470   for (unsigned i = 0; i<nbins_; ++i)
00471     os << avg_bin_value(i) << ' ' << p(i) << '\n';
00472 }
00473 
00474 template <class T>
00475 vcl_ostream& bsta_histogram<T>::write(vcl_ostream& s) const
00476 {
00477   s << area_valid_ << ' '
00478     << area_ << ' '
00479     << nbins_ << ' '
00480     << range_ << ' '
00481     << delta_ << ' '
00482     << min_prob_ << ' '
00483     << min_ << ' '
00484     << max_ << ' ';
00485   for (unsigned i = 0; i < counts_.size() ; ++i)
00486     s << counts_[i] << ' ';
00487 
00488   return  s << '\n';
00489 }
00490 
00491 template <class T>
00492 vcl_istream& bsta_histogram<T>::read(vcl_istream& s)
00493 {
00494   s >> area_valid_
00495     >> area_
00496     >> nbins_
00497     >> range_
00498     >> delta_
00499     >> min_prob_
00500     >> min_
00501     >> max_;
00502   counts_.resize(nbins_);
00503   for (unsigned i = 0; i < counts_.size() ; ++i)
00504     s >> counts_[i] ;
00505   return  s;
00506 }
00507 
00508 //: Write to stream
00509 template <class T>
00510 vcl_ostream& operator<<(vcl_ostream& s, bsta_histogram<T> const& h)
00511 {
00512   return h.write(s);
00513 }
00514 
00515 //: Read from stream
00516 template <class T>
00517 vcl_istream& operator>>(vcl_istream& is, bsta_histogram<T>& h)
00518 {
00519   return h.read(is);
00520 }
00521 
00522 
00523 #undef BSTA_HISTOGRAM_INSTANTIATE
00524 #define BSTA_HISTOGRAM_INSTANTIATE(T) \
00525 template class bsta_histogram<T >;\
00526 template vcl_istream& operator>>(vcl_istream&, bsta_histogram<T >&);\
00527 template vcl_ostream& operator<<(vcl_ostream&, bsta_histogram<T > const&)
00528 
00529 #endif // bsta_histogram_txx_