1 // This is mul/mbl/mbl_histogram.cxx
2 #include <iostream>
3 #include <cmath>
4 #include "mbl_histogram.h"
5 //:
6 // \file
7 // \brief Simple object to build histogram from supplied data.
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_histogram()16 mbl_histogram::mbl_histogram()
17 {
18 clear();
19 }
20
21 // Construct with given number of bins over given range
mbl_histogram(double x_lo,double x_hi,int n_bins)22 mbl_histogram::mbl_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_histogram::set_bins(double xlo, double xhi, int n_bins)
29 {
30 assert(n_bins>0);
31 assert(xhi>xlo);
32
33 bins_.resize(n_bins+1);
34 freq_.resize(n_bins);
35
36 double dx = (xhi-xlo)/n_bins;
37 for (int i=0;i<=n_bins;++i) bins_[i]=xlo+i*dx;
38 clear();
39 }
40
clear()41 void mbl_histogram::clear()
42 {
43 n_obs_ = 0;
44 n_below_ = 0;
45 n_above_ = 0;
46 for (int & i : freq_) i=0;
47 }
48
obs(double v)49 void mbl_histogram::obs(double v)
50 {
51 n_obs_++;
52 if (v<bins_[0])
53 {
54 n_below_++;
55 return;
56 }
57
58 int n = freq_.size();
59
60 for (int i=1;i<=n;++i)
61 {
62 if (v<bins_[i])
63 {
64 freq_[i-1]++;
65 return;
66 }
67 }
68
69 // Not in any bin
70 n_above_++;
71 }
72
73
74 const double MAX_ERROR = 1.0e-8;
75
76 //: Test for equality
operator ==(const mbl_histogram & s) const77 bool mbl_histogram::operator==(const mbl_histogram& s) const
78 {
79 if (s.n_bins()!=n_bins()) return false;
80 if (s.n_obs_ != n_obs_) return false;
81 if (s.n_below_!=n_below_) return false;
82 if (s.n_above_!=n_above_) return false;
83
84 int n = n_bins();
85 for (int i=0;i<n;++i)
86 if (s.freq_[i]!=freq_[i]) return false;
87 for (int i=0;i<=n;++i)
88 if (std::fabs(s.bins_[i]-bins_[i])>MAX_ERROR) return false;
89
90 return true;
91 }
92
93 //: Version number for I/O
version_no() const94 short mbl_histogram::version_no() const
95 {
96 return 1;
97 }
98
b_write(vsl_b_ostream & bfs) const99 void mbl_histogram::b_write(vsl_b_ostream& bfs) const
100 {
101 vsl_b_write(bfs,version_no());
102 vsl_b_write(bfs,n_obs_);
103 vsl_b_write(bfs,n_below_);
104 vsl_b_write(bfs,n_above_);
105 vsl_b_write(bfs,bins_);
106 vsl_b_write(bfs,freq_);
107 }
108
b_read(vsl_b_istream & bfs)109 void mbl_histogram::b_read(vsl_b_istream& bfs)
110 {
111 if (!bfs) return;
112
113 short file_version_no;
114 vsl_b_read(bfs,file_version_no);
115
116 switch (file_version_no)
117 {
118 case 1:
119 vsl_b_read(bfs,n_obs_);
120 vsl_b_read(bfs,n_below_);
121 vsl_b_read(bfs,n_above_);
122 vsl_b_read(bfs,bins_);
123 vsl_b_read(bfs,freq_);
124 break;
125 default:
126 std::cerr << "I/O ERROR: mbl_histogram::b_read(vsl_b_istream&)\n"
127 << " Unknown version number "<< file_version_no << '\n';
128 bfs.is().clear(std::ios::badbit); // Set an unrecoverable IO error on stream
129 return;
130 }
131 }
132
print_summary(std::ostream & os) const133 void mbl_histogram::print_summary(std::ostream& os) const
134 {
135 os << "mbl_histogram: ";
136 if (n_bins()==0) { os<< "No bins defined."; return; }
137
138 int n = n_bins();
139
140 if (n_obs_==0)
141 os << "No samples.";
142 else
143 {
144 os << n_obs_ << " observations.\n"
145 << " < "<<bins_[0]<<" "<<n_below_<<'\n';
146 for (int i=0;i<n;++i)
147 os<<" ["<<bins_[i]<<','<<bins_[i+1]<<") "<<freq_[i]<<'\n';
148 os << " >= "<<bins_[n]<<" "<<n_above_<<'\n';
149 }
150 }
151
152 //: Write out histogram probabilities to a named file
153 // Format: (bin-centre) prob (one per line)
154 // \return true if successful
write_probabilities(const char * path)155 bool mbl_histogram::write_probabilities(const char* path)
156 {
157 int n = n_bins();
158 if (n==0) return false;
159
160 std::ofstream ofs(path);
161 if (!ofs) return false;
162 for (int i=0;i<n_bins();++i)
163 {
164 double dx=std::fabs(bins_[i+1]-bins_[i]);
165 ofs<<0.5*(bins_[i]+bins_[i+1])<<" "<<double(freq_[i])/(dx*n_obs_)<<'\n';
166 }
167 ofs.close();
168 return true;
169 }
170
171 //: Write out cumulative probability distribution to a named file
172 // Format: (bin-centre) sum_prob (one per line)
173 // \return true if successful
write_cdf(const char * path)174 bool mbl_histogram::write_cdf(const char* path)
175 {
176 int n = n_bins();
177 if (n==0) return false;
178
179 std::ofstream ofs(path);
180 if (!ofs) return false;
181 int sum=n_below_;
182 for (int i=0;i<n_bins();++i)
183 {
184 sum+=freq_[i];
185 ofs<<0.5*(bins_[i]+bins_[i+1])<<" "<<double(sum)/n_obs_<<'\n';
186 }
187 ofs.close();
188 return true;
189 }
190
operator <<(std::ostream & os,const mbl_histogram & histo)191 std::ostream& operator<<(std::ostream& os, const mbl_histogram& histo)
192 {
193 histo.print_summary(os);
194 return os;
195 }
196
197 //: Stream output operator for class reference
vsl_print_summary(std::ostream & os,const mbl_histogram & histo)198 void vsl_print_summary(std::ostream& os,const mbl_histogram& histo)
199 {
200 histo.print_summary(os);
201 }
202
203 //: Binary file stream output operator for class reference
vsl_b_write(vsl_b_ostream & bfs,const mbl_histogram & h)204 void vsl_b_write(vsl_b_ostream& bfs, const mbl_histogram& h)
205 {
206 h.b_write(bfs);
207 }
208
209 //: Binary file stream input operator for class reference
vsl_b_read(vsl_b_istream & bfs,mbl_histogram & h)210 void vsl_b_read(vsl_b_istream& bfs, mbl_histogram& h)
211 {
212 h.b_read(bfs);
213 }
214