contrib/brl/bbas/bsta/bsta_joint_histogram.txx
Go to the documentation of this file.
00001 #ifndef bsta_joint_histogram_txx_
00002 #define bsta_joint_histogram_txx_
00003 //:
00004 // \file
00005 #include "bsta_joint_histogram.h"
00006 
00007 #include <vcl_cmath.h> // for log()
00008 #include <vcl_iostream.h>
00009 #include "bsta_gauss.h"
00010 #include <vnl/vnl_math.h> // for log2e == 1/vcl_log(2.0)
00011 template <class T>
00012 bsta_joint_histogram<T>::bsta_joint_histogram()
00013   : volume_valid_(false), volume_(0),
00014     nbins_a_(1), nbins_b_(1),
00015     range_a_(0), range_b_(0),
00016     delta_a_(0), delta_b_(0),
00017     min_a_(0), max_a_(0),
00018     min_b_(0), max_b_(0),
00019     min_prob_(0),
00020     counts_(1, 1, T(0))
00021 {
00022   bsta_joint_histogram_base::type_ = bsta_joint_histogram_traits<T>::type();
00023 }
00024 
00025 template <class T>
00026 bsta_joint_histogram<T>::bsta_joint_histogram(const T range,
00027                                               const unsigned int nbins,
00028                                               const T min_prob)
00029   : volume_valid_(false), volume_(0), nbins_a_(nbins), nbins_b_(nbins),
00030     range_a_(range), range_b_(range),delta_a_(0),delta_b_(0), min_a_(0),
00031     max_a_(range), min_b_(0), max_b_(range), min_prob_(min_prob),
00032     counts_(nbins, nbins, T(0))
00033 {
00034   bsta_joint_histogram_base::type_ = bsta_joint_histogram_traits<T>::type();
00035   if (nbins_a_>0&&nbins_b_>0)
00036   {
00037     delta_a_ = range_a_/nbins_a_;
00038     delta_b_ = range_b_/nbins_b_;
00039   }
00040 }
00041 
00042 template <class T>
00043 bsta_joint_histogram<T>::bsta_joint_histogram(const T range_a,
00044                                               const unsigned int nbins_a,
00045                                               const T range_b,
00046                                               const unsigned int nbins_b,
00047                                               const T min_prob)
00048   : volume_valid_(false), volume_(0), nbins_a_(nbins_a), nbins_b_(nbins_b),
00049     range_a_(range_a), range_b_(range_b),delta_a_(0),delta_b_(0),min_a_(0),
00050     max_a_(range_a), min_b_(0), max_b_(range_b), min_prob_(min_prob),
00051     counts_(nbins_a, nbins_b, T(0))
00052 {
00053   bsta_joint_histogram_base::type_ = bsta_joint_histogram_traits<T>::type();
00054   if (nbins_a_>0&&nbins_b_>0)
00055   {
00056     delta_a_ = range_a_/nbins_a_;
00057     delta_b_ = range_b_/nbins_b_;
00058   }
00059 }
00060 
00061 template <class T>
00062 bsta_joint_histogram<T>::bsta_joint_histogram(const T min_a, const T max_a,
00063                                               const unsigned int nbins_a,
00064                                               const T min_b, const T max_b,
00065                                               const unsigned int nbins_b,
00066                                               const T min_prob)
00067   : volume_valid_(false), volume_(0), nbins_a_(nbins_a), nbins_b_(nbins_b),
00068     min_a_(min_a), max_a_(max_a), min_b_(min_b), max_b_(max_b),
00069     min_prob_(min_prob), counts_(nbins_a, nbins_b, T(0))
00070 {
00071   bsta_joint_histogram_base::type_ = bsta_joint_histogram_traits<T>::type();
00072   if (nbins_a>0) {
00073     range_a_ = max_a-min_a;
00074     delta_a_ = range_a_/nbins_a;
00075   }
00076   else {
00077     range_a_ = 0;
00078     delta_a_ = 0;
00079   }
00080   if (nbins_b>0) {
00081     range_b_ = max_b-min_b;
00082     delta_b_ = range_b_/nbins_b;
00083   }
00084   else {
00085     range_b_ = 0;
00086     delta_b_ = 0;
00087   }
00088 }
00089 
00090 template <class T>
00091 void bsta_joint_histogram<T>::upcount(T a, T mag_a,
00092                                       T b, T mag_b)
00093 {
00094   if (a<min_a_||a>max_a_)
00095     return;
00096   if (b<min_b_||b>max_b_)
00097     return;
00098   int bin_a =-1, bin_b = -1;
00099   for (unsigned int i = 0; i<nbins_a_; i++)
00100     if ((i+1)*delta_a_>=(a-min_a_))
00101     {
00102       bin_a = i;
00103       break;
00104     }
00105   for (unsigned int i = 0; i<nbins_b_; i++)
00106     if ((i+1)*delta_b_>=(b-min_b_))
00107     {
00108       bin_b = i;
00109       break;
00110     }
00111   if (bin_a<0||bin_b<0) return;
00112   T v = counts_[bin_a][bin_b]+ mag_a + mag_b;
00113   counts_.put(bin_a, bin_b, v);
00114   volume_valid_ = false;
00115 }
00116 
00117 template <class T>
00118 void bsta_joint_histogram<T>::compute_volume() const
00119 {
00120   volume_=0;
00121   for (unsigned int a = 0; a<nbins_a_; a++)
00122     for (unsigned int b =0; b<nbins_b_; b++)
00123       volume_ += counts_[a][b];
00124   volume_valid_ = true;
00125 }
00126 
00127 template <class T>
00128 T bsta_joint_histogram<T>::p(unsigned int a, unsigned int b) const
00129 {
00130   if (a>=nbins_a_)
00131     return 0;
00132   if (b>=nbins_b_)
00133     return 0;
00134   if (!volume_valid_)
00135     compute_volume();
00136   if (volume_ == T(0))
00137     return 0;
00138   else
00139     return counts_[a][b]/volume_;
00140 }
00141 
00142 template <class T>
00143 T bsta_joint_histogram<T>::p(T a, T b) const
00144 {
00145   if (a<min_a_||a>max_a_)
00146     return 0;
00147   if (b<min_b_||b>max_b_)
00148     return 0;
00149   if (!volume_valid_)
00150     compute_volume();
00151   if (volume_ == T(0))
00152     return 0;
00153   unsigned r = 0, c = 0;
00154   bool found = false;
00155   for (unsigned ia = 0; (ia<nbins_a_)&&!found; ++ia)
00156     if ((ia+1)*delta_a_>=(a-min_a_)) {
00157       r = ia;
00158       found = true;
00159     }
00160   if (!found)
00161     return 0;
00162   found = false;
00163   for (unsigned ib = 0; (ib<nbins_b_)&&!found; ++ib)
00164     if ((ib+1)*delta_b_>=(b-min_b_)) {
00165       c = ib;
00166       found = true;
00167     }
00168   if (!found)
00169     return false;
00170   return counts_[r][c]/volume_;
00171 }
00172 
00173 //: The average and variance bin value for row a using counts to compute probs
00174 //  T avg_and_variance_bin_for_row_a(const unsigned int a) const;
00175 template <class T>
00176 bool bsta_joint_histogram<T>::avg_and_variance_bin_for_row_a(const unsigned int a, T & avg, T & var) const
00177 {
00178   if (a >= nbins_a_)
00179     return false;
00180 
00181   T sum = 0;
00182   for (unsigned int b =0; b<nbins_b_; b++)
00183     sum += counts_[a][b];
00184 
00185   if (sum <= 0)
00186     return false;
00187 
00188   avg = 0;
00189   for (unsigned int b =0; b<nbins_b_; b++)
00190     avg += ((b+1)*delta_b_/2)*(counts_[a][b]/sum);
00191 
00192   var = 0;
00193   for (unsigned int b =0; b<nbins_b_; b++) {
00194     T dif = (b+1)*delta_b_/2-avg;
00195     var += vcl_pow(dif, T(2.0))*(counts_[a][b]/sum);
00196   }
00197 
00198   return true;
00199 }
00200 
00201 template <class T>
00202 T bsta_joint_histogram<T>::volume() const
00203 {
00204   if (!volume_valid_)
00205     compute_volume();
00206   return volume_;
00207 }
00208 
00209 template <class T>
00210 T bsta_joint_histogram<T>::entropy() const
00211 {
00212   T ent = 0;
00213   for (unsigned int i = 0; i<nbins_a_; ++i)
00214     for (unsigned int j = 0; j<nbins_b_; ++j)
00215     {
00216       T pij = this->p(i,j);
00217       if (pij>min_prob_)
00218         ent -= pij*T(vcl_log(pij));
00219     }
00220   ent *= (T)vnl_math::log2e;
00221   return ent;
00222 }
00223 
00224 template <class T>
00225 T bsta_joint_histogram<T>::mutual_information() const
00226 {
00227   T mutual_information = T(0);
00228 
00229   //calculate marginal distributions
00230   vcl_vector<T> pa(nbins_a_,T(0)),pb(nbins_b_,T(0));
00231   for (unsigned a = 0; a < nbins_a_; ++a)
00232     for (unsigned b = 0; b < nbins_b_; ++b)
00233     {
00234       pa[a] += this->p(a,b);
00235       pb[b] += this->p(a,b);
00236     }
00237 
00238   //calculate mutual information in base 10
00239   for (unsigned a = 0; a < nbins_a_; ++a)
00240     for (unsigned b = 0; b < nbins_b_; ++b)
00241       if (p(a,b) != 0 && pa[a] != 0 && pb[b] != 0)
00242         mutual_information+=this->p(a,b)*(vcl_log(this->p(a,b)) - (vcl_log(pa[a]) + vcl_log(pb[b])) );
00243 
00244   //convert mutual information to base 2
00245   mutual_information *= (T)vnl_math::log2e;
00246 
00247   return mutual_information;
00248 }
00249 
00250 template <class T>
00251 T bsta_joint_histogram<T>::renyi_entropy() const
00252 {
00253   T ent = 0, sum = 0;
00254   for (unsigned int i = 0; i<nbins_a_; ++i)
00255     for (unsigned int j = 0; j<nbins_b_; ++j)
00256     {
00257       T pij = this->p(i,j);
00258       sum += pij*pij;
00259     }
00260   if (sum>min_prob_)
00261     ent = - T(vcl_log(sum))*(T)vnl_math::log2e;
00262   return ent;
00263 }
00264 
00265 template <class T>
00266 T bsta_joint_histogram<T>::entropy_marginal_a() const
00267 {
00268   T ent = 0;
00269   vcl_vector<T> counts_a(nbins_a_, T(0));
00270   T count_a_sum = T(0);
00271   for (unsigned int i = 0; i<nbins_a_; ++i)
00272     for (unsigned int j = 0; j <nbins_b_; ++j)
00273     {
00274       counts_a[i] += this->get_count(i,j);
00275       count_a_sum += this->get_count(i,j);
00276     }
00277 
00278   for (unsigned int i = 0; i <nbins_a_; ++i) {
00279     T pi = counts_a[i]/count_a_sum;
00280     if (pi>min_prob_)
00281       ent -= pi*T(vcl_log(pi));
00282   }
00283   ent *= (T)vnl_math::log2e;
00284   return ent;
00285 }
00286 
00287 template <class T>
00288 void bsta_joint_histogram<T>::parzen(const T sigma)
00289 {
00290   if (sigma<=0)
00291     return;
00292   double sd = (double)sigma;
00293   vbl_array_2d<double> in(nbins_a_, nbins_b_), out;
00294   for (unsigned int row = 0; row<nbins_a_; row++)
00295     for (unsigned int col = 0; col<nbins_b_; col++)
00296       in[row][col] = (double)counts_[row][col];
00297 
00298   bsta_gauss::bsta_2d_gaussian(sd, in, out);
00299 
00300   for (unsigned int row = 0; row<nbins_a_; row++)
00301     for (unsigned int col = 0; col<nbins_b_; col++)
00302       counts_[row][col] = (T)out[row][col];
00303 }
00304 
00305 template <class T>
00306 T bsta_joint_histogram<T>::get_count(T a, T b) const
00307 {
00308   T pv = this->p(a,b);
00309   if (volume_valid_)
00310     return pv*volume_;
00311   return pv*this->volume();
00312 }
00313 
00314 template <class T>
00315 void bsta_joint_histogram<T>::clear()
00316 {
00317   volume_valid_ = false;
00318   volume_ = 0;
00319   counts_.fill(T(0));
00320 }
00321 
00322 template <class T>
00323 void bsta_joint_histogram<T>::print(vcl_ostream& os) const
00324 {
00325   for (unsigned int a = 0; a<nbins_a_; a++)
00326     for (unsigned int b = 0; b<nbins_b_; b++)
00327       if (p(a,b) > 0)
00328         os << "p[" << a << "][" << b << "]=" << p(a,b) << '\n';
00329 }
00330 
00331 template <class T>
00332 void bsta_joint_histogram<T>::print_to_vrml(vcl_ostream& os) const
00333 {
00334   // we need to scale the display, find magnitude of largest value
00335   T max = (T)0;
00336   for (unsigned int a = 0; a<nbins_a_; a++)
00337     for (unsigned int b = 0; b<nbins_b_; b++)
00338       if (p(a,b) > max)
00339         max = p(a,b);
00340   float avg = static_cast<float>(0.5*(nbins_a_ + nbins_b_));
00341   os << "#VRML V2.0 utf8\n"
00342      << "Group { children [\n";
00343 
00344   for (unsigned int a = 0; a<nbins_a_; a++)
00345   {
00346     for (unsigned int b = 0; b<nbins_b_; b++)
00347     {
00348       float height = (max > 0) ? float((p(a,b)/max)*avg) : 0.0f;
00349       os << "Transform {\n"
00350          << "  translation " << a << ' ' << b << ' ' << height << '\n'
00351          << "  children Shape {\n"
00352          << "    geometry Sphere { radius 0.2 }\n"
00353          << "    appearance DEF A1 Appearance {"
00354          << "      material Material {\n"
00355          << "        diffuseColor 1 0 0\n"
00356          << "        emissiveColor .3 0 0\n"
00357          << "      }\n"
00358          << "    }\n"
00359          << "  }\n"
00360          << "}\n"
00361          << "Transform {\n"
00362          << "  translation " << a << ' ' << b << ' ' << height/2.0 << '\n'
00363          << "  rotation 1 0 0 " << vnl_math::pi/2.0 << '\n'
00364          << "  children Shape {\n"
00365          << "    appearance USE A1\n"
00366          << "    geometry Cylinder { radius 0.05 height " << height << " }\n"
00367          << "  }\n"
00368          << "}\n";
00369     }
00370   }
00371   os << "Transform {\n"
00372      << "  translation " << (nbins_a_-1)/2.0f << ' ' << (nbins_b_-1)/2.0f << " 0\n"
00373      << "  children Shape {\n"
00374      << "    geometry Box { size " << nbins_a_-1 << ' ' << nbins_b_-1 << " 0.3 }\n"
00375      << "    appearance Appearance {\n"
00376      << "      material Material { diffuseColor 0.8 0.8 0.8 }\n"
00377      << "    }\n"
00378      << "  }\n"
00379      << "}\n"
00380   // draw a green box to designate the origin of the histogram
00381      << "Transform {\n"
00382      << "  translation 0.0 0.0 0.0\n"
00383      << "  children Shape {\n"
00384      << "    geometry Box { size " << "1.0 1.0 1.0 }\n"
00385      << "    appearance Appearance {\n"
00386      << "      material Material { diffuseColor 0.0 1.0 0.0 }\n"
00387      << "    }\n"
00388      << "  }\n"
00389      << "}\n"
00390   // draw a red box to designate the "a" axis  of the histogram
00391      << "Transform {\n"
00392      << "  translation " << (nbins_a_-1)/2.0f << " 0 0\n"
00393      << "  children Shape {\n"
00394      << "    geometry Box { size " << (nbins_a_-1) << " 0.5 0.5 }\n"
00395      << "    appearance Appearance {\n"
00396      << "      material Material { diffuseColor 1.0 0.0 0.0 }\n"
00397      << "    }\n"
00398      << "  }\n"
00399      << "}\n"
00400   // draw a cyan box to designate the "b" axis  of the histogram
00401      << "Transform {\n"
00402      << "  translation 0 " << (nbins_b_-1)/2.0f << " 0\n"
00403      << "  children Shape {\n"
00404      << "    geometry Box { size " << 0.5 << ' ' << (nbins_b_-1) << " 0.5 }\n"
00405      << "    appearance Appearance {\n"
00406      << "      material Material { diffuseColor 0.0 0.8 0.8 }\n"
00407      << "    }\n"
00408      << "  }\n"
00409      << "}\n"
00410   // draw background
00411      << "Background { skyColor 1 1 1 }\n"
00412      << "NavigationInfo { type \"EXAMINE\" }\n"
00413      << "] }\n";
00414 }
00415 
00416 template <class T>
00417 void bsta_joint_histogram<T>::print_to_m(vcl_ostream& os) const
00418 {
00419   os << "y = zeros(" << nbins_a_ << ", " << nbins_b_ << ");\n";
00420   for (unsigned int a = 0; a<nbins_a_; a++) {
00421     for (unsigned int b = 0; b<nbins_b_; b++) {
00422       if (p(a,b) > 0) {
00423         os << "y(" << a+1 << ", " << b+1 << ") = " << p(a,b) << "; ";
00424       //os << "y(" << a+1 << ", " << b+1 << ") = " << counts_[a][b] << "; ";
00425       }
00426     }
00427     //os << '\n';
00428   }
00429   //os << '\n';
00430   os << "bar3(y,'detached');\n";
00431 }
00432 
00433 template <class T>
00434 void bsta_joint_histogram<T>::print_to_text(vcl_ostream& os) const
00435 {
00436   os << nbins_a_ << '\t' << nbins_b_ << '\n';
00437   for (unsigned int a = 0; a<nbins_a_; a++)
00438   {
00439     for (unsigned int b = 0; b<nbins_b_; b++)
00440     {
00441       os << get_count(a,b) << '\t';
00442     }
00443     os << '\n';
00444   }
00445   os << "\n probs:\n";
00446   for (unsigned int a = 0; a<nbins_a_; a++)
00447   {
00448     for (unsigned int b = 0; b<nbins_b_; b++)
00449     {
00450       os << p(a,b) << '\t';
00451     }
00452     os << '\n';
00453   }
00454 }
00455 
00456 #undef BSTA_JOINT_HISTOGRAM_INSTANTIATE
00457 #define BSTA_JOINT_HISTOGRAM_INSTANTIATE(T) \
00458 template class bsta_joint_histogram<T >
00459 
00460 #endif // bsta_joint_histogram_txx_