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