Isis 3 Programmer Reference
Histogram.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include "Histogram.h"
8 
9 #include "ControlMeasure.h"
10 #include "ControlNet.h"
11 #include "ControlPoint.h"
12 #include "LineManager.h"
13 #include "Message.h"
14 #include "SpecialPixel.h"
15 
16 #include <iostream>
17 #include <math.h>
18 #include <stdio.h>
19 #include <string>
20 
21 using namespace std;
22 
23 namespace Isis {
24 
33  Histogram::Histogram(double minimum, double maximum, int nbins) {
34 
35  SetValidRange(minimum, maximum);
36  SetBins(nbins);
37  }
38 
39 
49  Histogram::Histogram(ControlNet &net, double(ControlMeasure::*statFunc)() const, int bins) {
50 
51  //check to make sure we have a reasonable number of bins
52  if (bins < 1) {
53  string msg = "The number of Histogram Bins must be greater than 0";
54  throw IException(IException::Programmer, msg, _FILEINFO_);
55  }
56  SetBins(bins);
57 
58  //set the ranges
59  rangesFromNet(net,statFunc);
60  //add all the data to the now setup histogram
61  addMeasureDataFromNet(net, statFunc);
62  }
63 
64 
74  Histogram::Histogram(ControlNet &net, double(ControlMeasure::*statFunc)() const,
75  double binWidth) {
76 
77  //check to make sure we have a reasonable number of bins
78  if (binWidth <= 0 ) {
79  string msg = "The width of Histogram Bins must be greater than 0";
80  throw IException(IException::Programmer, msg, _FILEINFO_);
81  }
82 
83  //get the range of the data
84  rangesFromNet(net,statFunc);
85 
86  //Keep an eye on this to see if it breaks anything. Also, I need to create
87  //a dataset to give this constructor for the unit test.
88 
89  //from the domain of the data and the requested bin width calculate the number of bins
90  double domain = this->ValidMaximum() - this->ValidMinimum();
91  int nBins = int ( ceil(domain/binWidth) ) - 1;
92  SetBins(nBins);
93  //add all the data to the now setup histogram
94  addMeasureDataFromNet(net, statFunc);
95  }
96 
97 
105  void Histogram::addMeasureDataFromNet(ControlNet &net,
106  double(ControlMeasure::*statFunc)() const) {
107 
108  //get the number of object points
109  int nObjPts = net.GetNumPoints();
110  for (int i=0; i<nObjPts; i++) { //for each Object point
111  const ControlPoint *point = net.GetPoint(i);
112  if (point->IsIgnored() ) continue; //if the point is ignored then continue
113 
114  //get the number of measures
115  int nObs = point->GetNumMeasures();
116  for (int j=0; j<nObs; j++) { //for every measure
117 
118  const ControlMeasure *measure = point->GetMeasure(j);
119 
120  if (measure->IsIgnored()) continue;
121  this->AddData((measure->*statFunc)());
122  }
123  }
124  }
125 
126 
135  void Histogram::rangesFromNet(ControlNet &net, double(ControlMeasure::*statFunc)() const) {
136  double min,max,temp;
137  min = DBL_MAX;
138  max = -DBL_MAX;
139 
140  //get the number of object points
141  int nObjPts = net.GetNumPoints();
142  for (int i=0; i<nObjPts; i++) { //for each Object point
143 
144  const ControlPoint *point = net.GetPoint(i);
145  if (point->IsIgnored()) continue; //if the point is ignored then continue
146 
147  //get the number of measures
148  int nObs = point->GetNumMeasures();
149 
150  for (int j=0; j<nObs; j++) { //for every measure
151 
152  const ControlMeasure *measure = point->GetMeasure(j);
153  if (measure->IsIgnored()) continue;
154 
155  temp = (measure->*statFunc)(); //get the data using the passed ControlMeasure acessor function pointer
156  if ( !IsSpecial(temp) && temp > max ) max = temp;
157  if ( !IsSpecial(temp) && temp < min ) min = temp;
158  }
159  }
160 
161  //if DBL_MAX's weren't changed there's a problem
162  if (max <= min) {
163  string msg = "The net file appears to have 1 or fewer measures with residual data, "
164  "thus no histogram for this net file can be created;";
165  throw IException(IException::User, msg, _FILEINFO_);
166  }
167 
168  //set up the histogram ranges
169 
170  SetValidRange(min, max);
171  }
172 
173 
175  Histogram::~Histogram() {
176  }
177 
178  //2015-08-24, Tyler Wilson: Added Statistics::SetValidRange call to SetValidRange
179  //So the two functions do not have to be called together when setting
180  //up a histogram
181 
192  void Histogram::SetValidRange(double binStart, double binEnd) {
193  if (binEnd < binStart) {
194  string msg = "The binning range start [" + IString(binStart) + "]"
195  " must be less than the end [" + IString(binEnd) + "].";
196  throw IException(IException::Programmer, msg, _FILEINFO_);
197  }
198 
199  //(tjw): Flush the data buffers. Since we are setting
200  //the statistical range for the data, any data loaded
201  //before this call is useless.
202  Reset();
203  Isis::Statistics::SetValidRange(binStart,binEnd);
204  p_binRangeStart = binStart;
205  p_binRangeEnd = binEnd;
206  }
207 
208 
210  void Histogram::Reset() {
211  Statistics::Reset();
212  for (int i = 0; i < (int)p_bins.size(); i++) {
213  p_bins[i] = 0;
214  }
215  }
216 
217 
219  void Histogram::SetBins(const int nbins) {
220  p_bins.resize(nbins);
221  Histogram::Reset();
222  }
223 
232  void Histogram::AddData(const double *data,
233  const unsigned int count) {
234  Statistics::AddData(data, count);
235 
236  int nbins = p_bins.size();
237  int index;
238  for (unsigned int i = 0; i < count; i++) {
239  if (IsValidPixel(data[i]) && InRange(data[i]) ) {
240  if (BinRangeStart() == BinRangeEnd() ) {
241  index = 0;
242  }
243  else {
244  index = (int) floor( ((double) nbins / (BinRangeEnd() - BinRangeStart())) *
245  (data[i] - BinRangeStart()) );
246  }
247  if (index < 0) index = 0;
248  if (index >= nbins) index = nbins - 1;
249  p_bins[index] += 1;
250  }
251  }
252  }
253 
254 
262  void Histogram::AddData(const double data) {
263  Statistics::AddData(data);
264 
265  int nbins = p_bins.size();
266  int index;
267  if (IsValidPixel(data) && InRange(data) ) {
268  if (BinRangeStart() == BinRangeEnd() ) {
269  index = 0;
270  }
271  else {
272  index = (int) floor( ((double) nbins / (BinRangeEnd() - BinRangeStart())) *
273  (data - BinRangeStart()) );
274  }
275  if (index < 0) index = 0;
276  if (index >= nbins) index = nbins - 1;
277  p_bins[index] += 1;
278  }
279  }
280 
281 
291  void Histogram::RemoveData(const double *data,
292  const unsigned int count) {
293  Statistics::RemoveData(data, count);
294 
295  int nbins = p_bins.size();
296  int index;
297  for (unsigned int i = 0; i < count; i++) {
298  if (IsValidPixel(data[i]) ) {
299 
300  if (BinRangeStart() == BinRangeEnd() ) {
301  index = 0;
302  }
303  else {
304  index = (int) floor( ((double) nbins / (BinRangeEnd() - BinRangeStart())) *
305  (data[i] - BinRangeStart()) );
306  }
307  if (index < 0) index = 0;
308  if (index >= nbins) index = nbins - 1;
309  p_bins[index] -= 1;
310  }
311  }
312  }
313 
319  double Histogram::Median() const {
320  return Percent(50.0);
321  }
322 
328  double Histogram::Mode() const {
329  int mode = 0;
330  for (int i = 0; i < (int)p_bins.size(); i++) {
331 
332  if (p_bins[i] > p_bins[mode]) mode = i;
333  }
334 
335  if (p_bins[mode] < 1) return NULL8;
336 
337  return BinMiddle(mode);
338  }
339 
340 
351  double Histogram::Percent(double percent) const {
352  if ( (percent < 0.0) || (percent > 100.0) ) {
353  string m = "Argument percent outside of the range 0 to 100 in";
354  m += " [Histogram::Percent]";
355  throw IException(IException::Programmer, m, _FILEINFO_);
356  }
357 
358  if (ValidPixels() < 1) return NULL8;
359 
360  BigInt currentPixels = 0;
361  double currentPercent;
362 
363  for (int i = 0; i < (int)p_bins.size(); i++) {
364 
365  currentPixels += p_bins[i];
366  currentPercent = (double) currentPixels / (double) ValidPixels() * 100.0;
367 
368  if (currentPercent >= percent) {
369  return BinMiddle(i);
370  }
371  }
372 
373  return BinMiddle( (int) p_bins.size() - 1);
374  }
375 
376 
384  double Histogram::Skew() const {
385 
386  if (ValidPixels() < 1) return NULL8;
387 
388  double sdev = StandardDeviation();
389 
390  if (sdev == 0.0) return 0.0;
391 
392  return 3.0 * (Average() - Median()) / sdev;
393  }
394 
395 
403  BigInt Histogram::BinCount(const int index) const {
404 
405  if ( (index < 0) || (index >= (int)p_bins.size() ) ) {
406 
407  QString message = Message::ArraySubscriptNotInRange(index);
408 
409  throw IException(IException::Programmer, message, _FILEINFO_);
410  }
411 
412  return p_bins[index];
413  }
414 
415 
427  void Histogram::BinRange(const int index,
428  double &low, double &high) const {
429  if ( (index < 0) || (index >= (int)p_bins.size() ) ) {
430 
431  QString message = Message::ArraySubscriptNotInRange(index);
432  throw IException(IException::Programmer, message, _FILEINFO_);
433  }
434 
435  double binSize = (BinRangeEnd() - BinRangeStart()) / (double) p_bins.size();
436  low = BinRangeStart() + binSize * (double) index;
437  high = low + binSize;
438  }
439 
440 
449  double Histogram::BinMiddle(const int index) const {
450  if ( (index < 0) || (index >= (int)p_bins.size() ) ) {
451 
452  QString message = Message::ArraySubscriptNotInRange(index);
453 
454  throw IException(IException::Programmer, message, _FILEINFO_);
455  }
456 
457  double low, high;
458  BinRange(index, low, high);
459  return (low + high) / 2.0;
460  }
461 
462 
470  double Histogram::BinSize() const {
471 
472  double low, high;
473  BinRange(0, low, high);
474  return high - low;
475  }
476 
477 
483  int Histogram::Bins() const {
484  return (int)p_bins.size();
485  }
486 
487 
493  BigInt Histogram::MaxBinCount() const {
494 
495  BigInt maxBinCount = 0;
496  for (int i = 0; i < (int)p_bins.size(); i++) {
497  if (p_bins[i] > maxBinCount) maxBinCount = p_bins[i];
498  }
499 
500  return maxBinCount;
501  }
502 }
Isis::ValidMaximum
const double ValidMaximum
The maximum valid double value for Isis pixels.
Definition: SpecialPixel.h:122
Isis::Average
Functor for reduce using average functionality.
Definition: Reduce.h:107
Isis::ControlPoint::GetMeasure
const ControlMeasure * GetMeasure(QString serialNumber) const
Get a control measure based on its cube's serial number.
Definition: ControlPoint.cpp:416
Isis::IsSpecial
bool IsSpecial(const double d)
Returns if the input pixel is special.
Definition: SpecialPixel.h:197
Isis::ControlPoint
A single control point.
Definition: ControlPoint.h:354
Isis::ControlNet::GetNumPoints
int GetNumPoints() const
Return the number of control points in the network.
Definition: ControlNet.cpp:1465
Isis::BigInt
long long int BigInt
Big int.
Definition: Constants.h:49
Isis::ControlNet
a control network
Definition: ControlNet.h:257
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::ValidMinimum
const double ValidMinimum
The minimum valid double value for Isis pixels.
Definition: SpecialPixel.h:87
std
Namespace for the standard library.
Isis::IsValidPixel
bool IsValidPixel(const double d)
Returns if the input pixel is valid.
Definition: SpecialPixel.h:223
Isis::IString
Adds specific functionality to C++ strings.
Definition: IString.h:165
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::ControlMeasure
a control measurement
Definition: ControlMeasure.h:175