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
21using namespace std;
22
23namespace 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
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
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
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);
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) {
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
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}
a control measurement
a control network
Definition ControlNet.h:258
A single control point.
const ControlMeasure * GetMeasure(QString serialNumber) const
Get a control measure based on its cube's serial number.
void SetBins(const int bins)
Change the number of bins in the histogram and reset counters.
double BinSize() const
Returns the size of an individual bin.
BigInt BinCount(const int index) const
Returns the count at a bin position in the histogram.
std::vector< BigInt > p_bins
The array of counts.
Definition Histogram.h:121
void addMeasureDataFromNet(ControlNet &net, double(ControlMeasure::*statFunc)() const)
Iterates through all the measures in a network adding them to the histogram.
double BinMiddle(const int index) const
Returns the value represented by a bin.
void SetValidRange(const double minimum=Isis::ValidMinimum, const double maximum=Isis::ValidMaximum)
Changes the range of the bins.
double Median() const
Returns the median.
int Bins() const
Returns the number of bins in the histogram.
virtual void RemoveData(const double *data, const unsigned int count)
Remove an array of doubles from the histogram counters.
double Percent(const double percent) const
Computes and returns the value at X percent of the histogram.
double Mode() const
Returns the mode.
BigInt MaxBinCount() const
Returns the highest bin count.
~Histogram()
Destructs a histogram object.
virtual void AddData(const double *data, const unsigned int count)
Add an array of doubles to the histogram counters.
void Reset()
Resets histogram counters to zero.
double Skew() const
Computes and returns the skew.
void rangesFromNet(ControlNet &net, double(ControlMeasure::*statFunc)() const)
Iterates through all the measures in a network in order to find the domain of the data.
virtual void BinRange(const int index, double &low, double &high) const
Returns the left edge and right edge values of a bin.
Isis exception class.
Definition IException.h:91
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition IException.h:126
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
Adds specific functionality to C++ strings.
Definition IString.h:165
double Average() const
Computes and returns the average.
BigInt ValidPixels() const
Returns the total number of valid pixels processed.
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the accumulators and counters.
void RemoveData(const double *data, const unsigned int count)
Remove an array of doubles from the accumulators and counters.
double StandardDeviation() const
Computes and returns the standard deviation.
void Reset()
Reset all accumulators and counters to zero.
QString ArraySubscriptNotInRange(int index)
This error should be used when an Isis object or application is checking array bounds and the legal r...
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
bool IsValidPixel(const double d)
Returns if the input pixel is valid.
long long int BigInt
Big int.
Definition Constants.h:49
bool IsSpecial(const double d)
Returns if the input pixel is special.
Namespace for the standard library.