Histogram1D.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2008-2015 Imperial College London
5  * Copyright 2008-2015 Daniel Rueckert, Julia Schnabel
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_Histogram1D_H
21 #define MIRTK_Histogram1D_H
22 
23 #include "mirtk/Object.h"
24 #include "mirtk/Memory.h"
25 #include "mirtk/Math.h"
26 
27 
28 namespace mirtk {
29 
30 
31 /**
32  * Class for 1D histograms.
33  */
34 template <class HistogramType>
35 class Histogram1D : public Object
36 {
37  mirtkObjectMacro(Histogram1D);
38 
39 protected:
40 
41  /// Number of bins
42  int _nbins;
43 
44  /// Number of samples
45  HistogramType _nsamp;
46 
47  /// Min. value for samples, everything below is ignored
48  double _min;
49 
50  /// Max. value for samples, everything below is ignored
51  double _max;
52 
53  /// Width of bins
54  double _width;
55 
56  /// Dynamic memory for bins
57  HistogramType *_bins;
58 
59 public:
60 
61  /// Construct a histogram from another histogram
62  Histogram1D(const Histogram1D &);
63 
64  /// Construct a histogram with 256 bins and samples ranging from 0 to 255
65  Histogram1D(int nbins = 256);
66 
67  /// Construct a histogram for samples ranging from min to max and width
68  Histogram1D(double min, double max, double width);
69 
70  /// Read constructor
71  Histogram1D(const char *);
72 
73  /// Assignment operator
75 
76  /// Destructor
77  ~Histogram1D();
78 
79  /// Get raw pointer to histogram bins
80  HistogramType *RawPointer();
81 
82  /// Get raw pointer to histogram bins
83  const HistogramType *RawPointer() const;
84 
85  /// Clear and reset histogram
86  void Reset();
87 
88  /// Get number of bins in histogram
89  int NumberOfBins() const;
90 
91  /// Put number of bins in histogram
92  /// \note Unlike PutNumberOfBins, this function does not reset the histogram.
93  void NumberOfBins(int);
94 
95  /// Put number of bins in histogram
96  void PutNumberOfBins(int);
97 
98  /// Get minimum value in histogram
99  double Min() const;
100 
101  /// Set minimum value in histogram
102  /// \note Unlike PutMin, this function does not reset the histogram.
103  void Min(double);
104 
105  /// Get maximum value in histogram
106  double Max() const;
107 
108  /// Set maximum value in histogram
109  /// \note Unlike PutMax, this function does not reset the histogram.
110  void Max(double);
111 
112  /// Get minimum value in histogram
113  double GetMin() const;
114 
115  /// Put minimum value in histogram
116  void PutMin(double);
117 
118  /// Get maximum value in histogram
119  double GetMax() const;
120 
121  /// Put maximum value in histogram
122  void PutMax(double);
123 
124  /// Get width of bins in histogram
125  double GetWidth() const;
126 
127  /// Put width of bins in histogram
128  void PutWidth(double);
129 
130  /// Get number of samples in histogram
131  HistogramType NumberOfSamples() const;
132 
133  /// Set number of samples in histogram
134  void NumberOfSamples(HistogramType);
135 
136  /// Get number of samples in bin(i)
137  HistogramType &operator()(int);
138 
139  /// Get number of samples in bin(i)
140  const HistogramType &operator()(int) const;
141 
142  /// Add counts to bin
143  void Add(int, HistogramType = 1);
144 
145  /// Delete counts from bin
146  void Delete(int, HistogramType = 1);
147 
148  /// Add sample to bin
149  void AddSample(double, HistogramType = 1);
150 
151  /// Delete sample from bin
152  void DelSample(double, HistogramType = 1);
153 
154  /// Convert sample value to continuous bin index
155  double ValToRange(double val) const;
156 
157  /// Convert sample value to bin index
158  int ValToBin(double val) const;
159 
160  /// Convert bin index to sample value
161  double BinToVal(int bin) const;
162 
163  /// Convert bin into probability density distributions
164  double BinToPDF(int bin) const;
165 
166  /// Convert sample value into probability density distributions
167  double ValToPDF(double val) const;
168 
169  /// Convert bin into cumulative density distributions
170  double BinToCDF(int bin) const;
171 
172  /// Convert sample value into cumulative density distributions
173  double ValToCDF(double val) const;
174 
175  /// Convert cumulative density distributions to bin value
176  int CDFToBin(double p) const;
177 
178  /// Convert cumulative density distributions to sample value
179  double CDFToVal(double p) const;
180 
181  /// Log transform histogram
182  void Log();
183 
184  /// Smooth histogram
185  void Smooth();
186 
187  /// Return smallest modal value
188  double Mode() const;
189 
190  /// Return sorted modal values
191  Array<double> Modes() const;
192 
193  /// Calculate mean
194  double Mean() const;
195 
196  /// Calculate variance
197  double Variance() const;
198 
199  /// Calculate standard deviation
200  double StandardDeviation() const;
201 
202  /// Calculate entropy
203  double Entropy() const;
204 
205  /// Read histogram
206  void Read(const char *);
207 
208  /// Wrirte histogram
209  void Write(const char *) const;
210 
211  /// Print histogram
212  void Print() const;
213 };
214 
215 ////////////////////////////////////////////////////////////////////////////////
216 // Inline definitions
217 ////////////////////////////////////////////////////////////////////////////////
218 
219 // -----------------------------------------------------------------------------
220 template <class HistogramType>
222 {
223  return _bins;
224 }
225 
226 // -----------------------------------------------------------------------------
227 template <class HistogramType>
228 inline const HistogramType *Histogram1D<HistogramType>::RawPointer() const
229 {
230  return _bins;
231 }
232 
233 // -----------------------------------------------------------------------------
234 template <class HistogramType>
236 {
237  return _nbins;
238 }
239 
240 // -----------------------------------------------------------------------------
241 template <class HistogramType>
243 {
244  if (_nbins != nbins) {
245  Deallocate(_bins);
246  Allocate(_bins, nbins);
247  _nbins = nbins;
248  _width = (_max - _min) / _nbins;
249  _nsamp = 0;
250  }
251 }
252 
253 // -----------------------------------------------------------------------------
254 template <class HistogramType>
255 inline double Histogram1D<HistogramType>::Min() const
256 {
257  return _min;
258 }
259 
260 // -----------------------------------------------------------------------------
261 template <class HistogramType>
262 inline void Histogram1D<HistogramType>::Min(double min)
263 {
264  _min = min;
265  _width = (_max - _min) / _nbins;
266 }
267 
268 // -----------------------------------------------------------------------------
269 template <class HistogramType>
271 {
272  return _min;
273 }
274 
275 // -----------------------------------------------------------------------------
276 template <class HistogramType>
277 inline double Histogram1D<HistogramType>::Max() const
278 {
279  return _max;
280 }
281 
282 // -----------------------------------------------------------------------------
283 template <class HistogramType>
284 inline void Histogram1D<HistogramType>::Max(double max)
285 {
286  _max = max;
287  _width = (_max - _min) / _nbins;
288 }
289 
290 // -----------------------------------------------------------------------------
291 template <class HistogramType>
293 {
294  return _max;
295 }
296 
297 // -----------------------------------------------------------------------------
298 template <class HistogramType>
300 {
301  return _width;
302 }
303 
304 // -----------------------------------------------------------------------------
305 template <class HistogramType>
307 {
308  return _nsamp;
309 }
310 
311 // -----------------------------------------------------------------------------
312 template <class HistogramType>
314 {
315  _nsamp = n;
316 }
317 
318 // -----------------------------------------------------------------------------
319 template <class HistogramType>
320 inline HistogramType &Histogram1D<HistogramType>::operator()(int i)
321 {
322  return _bins[i];
323 }
324 
325 // -----------------------------------------------------------------------------
326 template <class HistogramType>
327 inline const HistogramType &Histogram1D<HistogramType>::operator()(int i) const
328 {
329  return _bins[i];
330 }
331 
332 // -----------------------------------------------------------------------------
333 template <class HistogramType>
334 inline void Histogram1D<HistogramType>::Add(int i, HistogramType n)
335 {
336  _bins[i] += n;
337  _nsamp += n;
338 }
339 
340 // -----------------------------------------------------------------------------
341 template <class HistogramType>
342 inline void Histogram1D<HistogramType>::Delete(int i, HistogramType n)
343 {
344  _bins[i] -= n;
345  _nsamp -= n;
346 }
347 
348 // -----------------------------------------------------------------------------
349 template <class HistogramType>
350 inline void Histogram1D<HistogramType>::AddSample(double x, HistogramType n)
351 {
352  if (x < _min || x > _max) return;
353  int index = iround(_nbins * (x - _min - 0.5*_width) / (_max - _min));
354  if (index < 0 ) index = 0;
355  if (index >= _nbins) index = _nbins - 1;
356  _bins[index] += n;
357  _nsamp += n;
358 }
359 
360 // -----------------------------------------------------------------------------
361 template <class HistogramType>
362 inline void Histogram1D<HistogramType>::DelSample(double x, HistogramType n)
363 {
364  if (x < _min || x > _max) return;
365  int index = iround(_nbins * (x - _min - 0.5*_width) / (_max - _min));
366  if (index < 0 ) index = 0;
367  if (index >= _nbins) index = _nbins - 1;
368  _bins[index] -= n;
369  _nsamp -= n;
370 }
371 
372 // -----------------------------------------------------------------------------
373 template <class HistogramType>
374 inline double Histogram1D<HistogramType>::ValToRange(double val) const
375 {
376  return _nbins * (val - _min - 0.5 * _width) / (_max - _min);
377 }
378 
379 // -----------------------------------------------------------------------------
380 template <class HistogramType>
381 inline int Histogram1D<HistogramType>::ValToBin(double val) const
382 {
383  const int index = iround(ValToRange(val));
384  return (index < 0 ? 0 : (index >= _nbins ? _nbins - 1 : index));
385 }
386 
387 // -----------------------------------------------------------------------------
388 template <class HistogramType>
389 inline double Histogram1D<HistogramType>::BinToVal(int i) const
390 {
391  return (i*(_max - _min)/_nbins + _min) + _width/2.0;
392 }
393 
394 // -----------------------------------------------------------------------------
395 template <class HistogramType>
396 inline double Histogram1D<HistogramType>::BinToPDF(int i) const
397 {
398  return ((_nsamp == .0) ? .0 : _bins[i] / _nsamp);
399 }
400 
401 // -----------------------------------------------------------------------------
402 template <class HistogramType>
403 inline double Histogram1D<HistogramType>::ValToPDF(double val) const
404 {
405  return BinToPDF(ValToBin(val));
406 }
407 
408 // -----------------------------------------------------------------------------
409 template <class HistogramType>
410 inline double Histogram1D<HistogramType>::BinToCDF(int i) const
411 {
412  if (_nsamp == .0) return .0;
413  double s = .0;
414  for (int j = 0; j <= i; ++j) {
415  s += _bins[j];
416  }
417  return s / _nsamp;
418 }
419 
420 // -----------------------------------------------------------------------------
421 template <class HistogramType>
422 inline double Histogram1D<HistogramType>::ValToCDF(double val) const
423 {
424  return BinToCDF(ValToBin(val));
425 }
426 
427 // -----------------------------------------------------------------------------
428 template <class HistogramType>
429 inline int Histogram1D<HistogramType>::CDFToBin(double p) const
430 {
431  if (p < .0 || p > 1.0) {
432  cerr << "Histogram1D<HistogramType>::CDFToBin: Must be between 0 and 1" << endl;
433  exit(1);
434  }
435  int i;
436  double sum = .0;
437  for (i = 0; i < _nbins; ++i) {
438  sum += static_cast<double>(_bins[i]);
439  if (sum / _nsamp >= p) return i;
440  }
441  return _nbins - 1;
442 }
443 
444 // -----------------------------------------------------------------------------
445 template <class HistogramType>
446 inline double Histogram1D<HistogramType>::CDFToVal(double p) const
447 {
448  return BinToVal(CDFToBin(p));
449 }
450 
451 
452 } // namespace mirtk
453 
454 #endif // MIRTK_Histogram1D_H
void Log()
Log transform histogram.
Array< double > Modes() const
Return sorted modal values.
void Delete(int, HistogramType=1)
Delete counts from bin.
Definition: Histogram1D.h:342
double GetMax() const
Get maximum value in histogram.
Definition: Histogram1D.h:292
int NumberOfBins() const
Get number of bins in histogram.
Definition: Histogram1D.h:235
int _nbins
Number of bins.
Definition: Histogram1D.h:42
HistogramType & operator()(int)
Get number of samples in bin(i)
Definition: Histogram1D.h:320
double Mean() const
Calculate mean.
void Print() const
Print histogram.
double _width
Width of bins.
Definition: Histogram1D.h:54
HistogramType * RawPointer()
Get raw pointer to histogram bins.
Definition: Histogram1D.h:221
void PutWidth(double)
Put width of bins in histogram.
double GetWidth() const
Get width of bins in histogram.
Definition: Histogram1D.h:299
void Allocate(Type *&matrix, int n)
Allocate 1D array.
Definition: Allocate.h:62
HistogramType _nsamp
Number of samples.
Definition: Histogram1D.h:45
void Read(const char *)
Read histogram.
void Add(int, HistogramType=1)
Add counts to bin.
Definition: Histogram1D.h:334
Definition: IOConfig.h:41
double _min
Min. value for samples, everything below is ignored.
Definition: Histogram1D.h:48
double BinToPDF(int bin) const
Convert bin into probability density distributions.
Definition: Histogram1D.h:396
double ValToPDF(double val) const
Convert sample value into probability density distributions.
Definition: Histogram1D.h:403
void Deallocate(Type *&p)
Deallocate 1D array.
Definition: Deallocate.h:36
void DelSample(double, HistogramType=1)
Delete sample from bin.
Definition: Histogram1D.h:362
void PutMin(double)
Put minimum value in histogram.
void PutMax(double)
Put maximum value in histogram.
double GetMin() const
Get minimum value in histogram.
Definition: Histogram1D.h:270
void Smooth()
Smooth histogram.
Histogram1D & operator=(const Histogram1D &)
Assignment operator.
double Min() const
Get minimum value in histogram.
Definition: Histogram1D.h:255
double Variance() const
Calculate variance.
void Reset()
Clear and reset histogram.
double ValToRange(double val) const
Convert sample value to continuous bin index.
Definition: Histogram1D.h:374
void Write(const char *) const
Wrirte histogram.
double Mode() const
Return smallest modal value.
HistogramType NumberOfSamples() const
Get number of samples in histogram.
Definition: Histogram1D.h:306
double ValToCDF(double val) const
Convert sample value into cumulative density distributions.
Definition: Histogram1D.h:422
double CDFToVal(double p) const
Convert cumulative density distributions to sample value.
Definition: Histogram1D.h:446
~Histogram1D()
Destructor.
MIRTKCU_API int iround(T x)
Round floating-point value and cast to int.
Definition: Math.h:170
double _max
Max. value for samples, everything below is ignored.
Definition: Histogram1D.h:51
Histogram1D(const Histogram1D &)
Construct a histogram from another histogram.
int CDFToBin(double p) const
Convert cumulative density distributions to bin value.
Definition: Histogram1D.h:429
double StandardDeviation() const
Calculate standard deviation.
double BinToCDF(int bin) const
Convert bin into cumulative density distributions.
Definition: Histogram1D.h:410
void AddSample(double, HistogramType=1)
Add sample to bin.
Definition: Histogram1D.h:350
double Entropy() const
Calculate entropy.
HistogramType * _bins
Dynamic memory for bins.
Definition: Histogram1D.h:57
double BinToVal(int bin) const
Convert bin index to sample value.
Definition: Histogram1D.h:389
double Max() const
Get maximum value in histogram.
Definition: Histogram1D.h:277
int ValToBin(double val) const
Convert sample value to bin index.
Definition: Histogram1D.h:381
void PutNumberOfBins(int)
Put number of bins in histogram.