1 // This is mul/mbl/mbl_wt_histogram.cxx
2 #include <iostream>
3 #include <cmath>
4 #include "mbl_wt_histogram.h"
5 //:
6 // \file
7 // \brief Simple object to build histogram from supplied data, with weights
8 // \author Tim Cootes
9 
10 #ifdef _MSC_VER
11 #  include "vcl_msvc_warnings.h"
12 #endif
13 #include <cassert>
14 #include "vsl/vsl_vector_io.h"
15 
mbl_wt_histogram()16 mbl_wt_histogram::mbl_wt_histogram()
17 {
18   clear();
19 }
20 
21 // Construct with given number of bins over given range
mbl_wt_histogram(double x_lo,double x_hi,int n_bins)22 mbl_wt_histogram::mbl_wt_histogram(double x_lo, double x_hi, int n_bins)
23 {
24   set_bins(x_lo,x_hi,n_bins);
25 }
26 
27 //: Define number and size of bins
set_bins(double xlo,double xhi,int n_bins)28 void mbl_wt_histogram::set_bins(double xlo, double xhi, int n_bins)
29 {
30   assert(n_bins>0);
31   assert(xhi>xlo);
32 
33   wt_sum_.resize(n_bins);
34 
35   dx_ = (xhi-xlo)/n_bins;
36   xlo_ = xlo;
37   clear();
38 }
39 
clear()40 void mbl_wt_histogram::clear()
41 {
42   n_obs_ = 0;
43   total_wt_=0.0;
44   wt_below_ = 0;
45   wt_above_ = 0;
46   for (double & i : wt_sum_) i=0;
47 }
48 
obs(double v,double wt)49 void mbl_wt_histogram::obs(double v, double wt)
50 {
51   n_obs_++;
52   total_wt_ += wt;
53   if (v<xlo_)
54   {
55     wt_below_+=wt;
56     return;
57   }
58 
59   // v-xlo_ >= 0
60   auto i = (unsigned int)((v-xlo_)/dx_);
61 
62   if (i<wt_sum_.size()) wt_sum_[i]+=wt;
63   else                  wt_above_+=wt;
64 }
65 
66 
67 const double MAX_ERROR = 1.0e-8;
68 
69 //: Test for equality
operator ==(const mbl_wt_histogram & s) const70 bool mbl_wt_histogram::operator==(const mbl_wt_histogram& s) const
71 {
72   if (s.n_bins()!=n_bins()) return false;
73   if (s.n_obs_ != n_obs_) return false;
74   if (std::fabs(s.wt_below_-wt_below_)>MAX_ERROR) return false;
75   if (std::fabs(s.wt_above_-wt_above_)>MAX_ERROR) return false;
76   if (std::fabs(s.xlo_-xlo_)>MAX_ERROR) return false;
77   if (std::fabs(s.dx_-dx_)>MAX_ERROR) return false;
78 
79   int n = n_bins();
80   for (int i=0;i<n;++i)
81     if (std::fabs(s.wt_sum_[i]-wt_sum_[i])>MAX_ERROR) return false;
82 
83   return true;
84 }
85 
86 //: Version number for I/O
version_no() const87 short mbl_wt_histogram::version_no() const
88 {
89   return 1;
90 }
91 
b_write(vsl_b_ostream & bfs) const92 void mbl_wt_histogram::b_write(vsl_b_ostream& bfs) const
93 {
94   vsl_b_write(bfs,version_no());
95   vsl_b_write(bfs,n_obs_);
96   vsl_b_write(bfs,total_wt_);
97   vsl_b_write(bfs,wt_below_);
98   vsl_b_write(bfs,wt_above_);
99   vsl_b_write(bfs,xlo_);
100   vsl_b_write(bfs,dx_);
101   vsl_b_write(bfs,wt_sum_);
102 }
103 
b_read(vsl_b_istream & bfs)104 void mbl_wt_histogram::b_read(vsl_b_istream& bfs)
105 {
106   if (!bfs) return;
107 
108   short file_version_no;
109   vsl_b_read(bfs,file_version_no);
110 
111   switch (file_version_no)
112   {
113    case 1:
114     vsl_b_read(bfs,n_obs_);
115     vsl_b_read(bfs,total_wt_);
116     vsl_b_read(bfs,wt_below_);
117     vsl_b_read(bfs,wt_above_);
118     vsl_b_read(bfs,xlo_);
119     vsl_b_read(bfs,dx_);
120     vsl_b_read(bfs,wt_sum_);
121     break;
122    default:
123     std::cerr << "I/O ERROR: mbl_wt_histogram::b_read(vsl_b_istream&)\n"
124              << "           Unknown version number "<< file_version_no << '\n';
125     bfs.is().clear(std::ios::badbit); // Set an unrecoverable IO error on stream
126     return;
127   }
128 }
129 
print_summary(std::ostream & os) const130 void mbl_wt_histogram::print_summary(std::ostream& os) const
131 {
132   os << "mbl_wt_histogram: ";
133   if (n_bins()==0) { os<< "No bins defined."; return; }
134 
135   int n = n_bins();
136 
137   if (n_obs_==0)
138     os << "No samples.";
139   else
140   {
141     os << n_obs_ << " observations.\n"
142        << "    < "<<xlo_<<"   "<<wt_below_<<'\n';
143     for (int i=0;i<n;++i)
144       os<<"  ["<<xlo_+i*dx_<<','<<xlo_+(i+1)*dx_<<")  "<<wt_sum_[i]<<'\n';
145     os << "   >= "<<xlo_+n*dx_<<"   "<<wt_above_<<'\n';
146   }
147 }
148 
149 //: Write out histogram probabilities to a named file
150 //  Format: (bin-centre) prob     (one per line)
151 // \return true if successful
write_probabilities(const char * path)152 bool mbl_wt_histogram::write_probabilities(const char* path)
153 {
154   int n = n_bins();
155   if (n==0) return false;
156 
157   std::ofstream ofs(path);
158   if (!ofs) return false;
159   for (int i=0;i<n;++i)
160   {
161     ofs<<xlo_+(i+0.5)*dx_<<"  "<<double(wt_sum_[i])/total_wt_<<'\n';
162   }
163   ofs.close();
164   return true;
165 }
166 
operator <<(std::ostream & os,const mbl_wt_histogram & histo)167 std::ostream& operator<<(std::ostream& os, const mbl_wt_histogram& histo)
168 {
169   histo.print_summary(os);
170   return os;
171 }
172 
173   //: Stream output operator for class reference
vsl_print_summary(std::ostream & os,const mbl_wt_histogram & histo)174 void vsl_print_summary(std::ostream& os,const mbl_wt_histogram& histo)
175 {
176   histo.print_summary(os);
177 }
178 
179   //: Binary file stream output operator for class reference
vsl_b_write(vsl_b_ostream & bfs,const mbl_wt_histogram & h)180 void vsl_b_write(vsl_b_ostream& bfs, const mbl_wt_histogram& h)
181 {
182   h.b_write(bfs);
183 }
184 
185   //: Binary file stream input operator for class reference
vsl_b_read(vsl_b_istream & bfs,mbl_wt_histogram & h)186 void vsl_b_read(vsl_b_istream& bfs, mbl_wt_histogram& h)
187 {
188   h.b_read(bfs);
189 }
190