Isis 3 Programmer Reference
QuickFilter.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "QuickFilter.h"
8#include "IException.h"
9#include <float.h>
10
11using namespace std;
12namespace Isis {
13
27 QuickFilter::QuickFilter(const int ns, const int width,
28 const int height) {
29 // Error checks
30 if(ns <= 0) {
31 string msg = "Invalid value for [ns] in QuickFilter constructor";
32 throw IException(IException::Programmer, msg, _FILEINFO_);
33 }
34
35 if(width < 1) {
36 string m = "[Width] must be must be greater than or equal to one in ";
37 m += "QuickFilter constructor";
38 throw IException(IException::Programmer, m, _FILEINFO_);
39 }
40 else if((width % 2) == 0) {
41 string m = "[Width] must be must be odd in ";
42 m += "QuickFilter constructor";
43 throw IException(IException::Programmer, m, _FILEINFO_);
44 }
45
46 if(height < 1) {
47 string m = "[Height] must be must be greater than or equal to one in ";
48 m += "QuickFilter constructor";
49 throw IException(IException::Programmer, m, _FILEINFO_);
50 }
51 else if((height % 2) == 0) {
52 string m = "[Height] must be must be odd in ";
53 m += "QuickFilter constructor";
54 throw IException(IException::Programmer, m, _FILEINFO_);
55 }
56
57 // Create buffers
58 p_sums = new double[ns];
59 p_sumsqrs = new double[ns];
60 p_counts = new int[ns];
61 p_ns = ns;
62
63 // Set defaults for min/max and valid pixels
64 p_minimum = -DBL_MAX;
65 p_maximum = DBL_MAX;
67
68 // Set the boxcar size and compute half the size
69 p_width = width;
70 p_halfWidth = width / 2;
71
72 p_height = height;
73 p_halfHeight = height / 2;
74
75 Reset();
76 }
77
80 // Initialize buffers
81 for(int i = 0; i < p_ns; i++) {
82 p_sums[i] = 0.0;
83 p_sumsqrs[i] = 0.0;
84 p_counts[i] = 0;
85
86 }
87
88 // Initialize sums for the last time Average/Variance/Count were called
89 p_lastSum = 0.0;
90 p_lastSumsqr = 0.0;
91 p_lastCount = 0;
92 p_lastIndex = -100;
93 p_linesAdded = 0;
94 }
95
98 delete [] p_sums;
99 delete [] p_counts;
100 delete [] p_sumsqrs;
101 }
102
118 void QuickFilter::SetMinMax(const double minimum, const double maximum) {
119 if(minimum >= maximum) {
120 string m = "Minimum must be less than maximum in [QuickFilter::SetMinMax]";
121 throw IException(IException::Programmer, m, _FILEINFO_);
122 }
123
124 p_minimum = minimum;
125 p_maximum = maximum;
126 p_lastIndex = -100;
127 }
128
139 void QuickFilter::SetMinimumPixels(const int pixels) {
140 if(pixels < 0) {
141 string m = "Pixels must be greater than or equal to zero in ";
142 m += "[QuickFilter::SetMinimumPixels]";
143 throw IException(IException::Programmer, m, _FILEINFO_);
144 }
145 p_minimumPixels = pixels;
148 }
149 }
150
162 void QuickFilter::AddLine(const double *buf) {
163 // Check for adding too many lines
164 p_linesAdded++;
165 if(p_linesAdded > p_height) {
166 string m = "Number of lines added exceeds boxcar height ... ";
167 m += "use RemoveLine before AddLine";
168 throw IException(IException::Programmer, m, _FILEINFO_);
169 }
170
171 for(int i = 0; i < p_ns; i++) {
172 if(Isis::IsValidPixel(buf[i])) {
173 if(buf[i] < p_minimum) continue;
174 if(buf[i] > p_maximum) continue;
175 p_sums[i] += buf[i];
176 p_sumsqrs[i] += buf[i] * buf[i];
177 p_counts[i]++;
178 p_lastIndex = -100;
179 }
180 }
181 }
182
188 void QuickFilter::RemoveLine(const double *buf) {
189 for(int i = 0; i < p_ns; i++) {
190 if(Isis::IsValidPixel(buf[i])) {
191 if(buf[i] < p_minimum) continue;
192 if(buf[i] > p_maximum) continue;
193 p_sums[i] -= buf[i];
194 p_sumsqrs[i] -= buf[i] * buf[i];
195 p_counts[i]--;
196 p_lastIndex = -100;
197 }
198 }
199 p_linesAdded--;
200 }
201
213 double QuickFilter::Average(const int index) {
214 // Move the boxcar if necessary
215 Compute(index);
216
217 // Return NULL8 if we have invalid conditions
218 if(p_lastCount < p_minimumPixels) return Isis::NULL8;
219 if(p_lastCount <= 0) return Isis::NULL8;
220
221 // Return the average
222 return p_lastSum / (double) p_lastCount;
223 }
224
236 double QuickFilter::Variance(const int index) {
237 // Move the boxcar if necessary
238 Compute(index);
239
240 // Return NULL8 if we have invalid conditions
241 if(p_lastCount < p_minimumPixels) return Isis::NULL8;
242 if(p_lastCount <= 1) return Isis::NULL8;
243
244 // Return the variance
245 double temp = p_lastCount * p_lastSumsqr - p_lastSum * p_lastSum;
246 if(temp < 0.0) temp = 0.0; // This shouldn't happen unless roundoff occurs
247 return temp / ((double)(p_lastCount - 1) * (double) p_lastCount);
248 }
249
260 int QuickFilter::Count(const int index) {
261 // Move the boxcar if necessary
262 Compute(index);
263
264 // Return the valid count
265 return p_lastCount;
266 }
267
273 int QuickFilter::Width() const {
274 return p_width;
275 }
276
284 return p_halfWidth;
285 }
286
293 return p_height;
294 }
295
303 return p_halfHeight;
304 }
305
312 return p_ns;
313 }
314
320 double QuickFilter::Low() const {
321 return p_minimum;
322 }
323
329 double QuickFilter::High() const {
330 return p_maximum;
331 }
332
341 return p_minimumPixels;
342 }
343
352 void QuickFilter::Compute(const int index) {
353 // If the index hasn't changed just return
354 if(index == p_lastIndex) return;
355
356 // Determine start and stop indeces
357 int start = index - p_halfWidth;
358 int stop = index + p_halfWidth;
359
360 // See if the index has increased by one
361 if(index == p_lastIndex + 1) {
362 // Remove one column
363 start--;
364 if(start < 0) start = -1 * start;
365 p_lastSum -= p_sums[start];
366 p_lastSumsqr -= p_sumsqrs[start];
367 p_lastCount -= p_counts[start];
368
369 // Add another column
370 if(stop >= p_ns) stop = p_ns - (stop - p_ns + 2);
371 p_lastSum += p_sums[stop];
372 p_lastSumsqr += p_sumsqrs[stop];
373 p_lastCount += p_counts[stop];
374 }
375
376 // Recompute everything
377 else {
378 p_lastSum = 0.0;
379 p_lastCount = 0;
380 p_lastSumsqr = 0.0;
381 int j;
382 for(int i = start; i <= stop; i++) {
383 j = i;
384 if(i < 0) {
385 j = -1 * i;
386 }
387 else if(i >= p_ns) {
388 j = p_ns - (i - p_ns + 2);
389 }
390
391 p_lastSum += p_sums[j];
393 p_lastCount += p_counts[j];
394 }
395 }
396
397 // Save the current index
398 p_lastIndex = index;
399 }
400} // end namespace isis
Isis exception class.
Definition IException.h:91
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
double Variance(const int index)
Computes and returns the boxcar variance at pixel index (zero based).
int p_halfHeight
This is half the height of the boxcar rounded down to the next integer since the boxcar is always odd...
double High() const
Returns the highest pixel value included in filtering computations.
void AddLine(const double *buf)
Add an array of doubles to the accumulators and counters.
double * p_sums
Sum accumulator for each column/sample.
Definition QuickFilter.h:52
int p_lastCount
See p_lastSum.
~QuickFilter()
Destroys the QuickFilter object.
double * p_sumsqrs
This is identical to p_sums with the exception that the pixel values are squared before summing occur...
Definition QuickFilter.h:62
int p_ns
This value is initialized in the constructor.
Definition QuickFilter.h:74
int Count(const int index)
Computes and returns the number of valid pixels in the boxcar at pixel index (zero based).
double p_minimum
Minimum valid pixel value.
Definition QuickFilter.h:80
int p_width
This is the width of the boxcar.
void SetMinMax(const double minimum, const double maximum)
This method is used to set the minimum/maximum valid values.
int * p_counts
This is identical to p_sums with the exception that it keeps count of the number of valid pixels in p...
Definition QuickFilter.h:66
void SetMinimumPixels(const int minimumValid)
This method is used to set the minimum number of valid pixels in the boxcar.
QuickFilter(const int ns, const int width, const int height)
Constructs a QuickFilter object with accumulators and counters set to zero.
int p_minimumPixels
The minimum number of pixels in the boxcar which must be valid (not special and inside p_minimum/p_ma...
Definition QuickFilter.h:94
int p_lastIndex
This is used to keep track of the last index passed into the Average, Variance and/or count method.
double Low() const
Returns the lowest pixel value included in filtering computations.
int p_linesAdded
This is used to keep track of the number of lines added.
int p_halfWidth
This is half the width of the boxcar rounded down to the next integer since the boxcar is always odd.
int MinimumPixels() const
Returns the minimum number of pixels which need to be valid inside the boxcar.
double p_lastSumsqr
See p_lastSum.
double Average(const int index)
Computes and returns the boxcar average at pixel index (zero based).
void Compute(const int index)
Computes the moving boxcar sums and counts for the Average, Variance, and count methods.
int Width() const
Returns the width of the boxcar.
int HalfHeight() const
Returns the half the height of the boxcar rounded down because the boxcar size is odd.
double p_maximum
Maximum valid pixel value.
Definition QuickFilter.h:87
int p_height
This is the height of the boxcar.
int HalfWidth() const
Returns the half the width of the boxcar rounded down because the boxcar size is odd.
void RemoveLine(const double *buf)
Remove an array of doubles from the accumulators and counters.
int Samples() const
Returns the number of samples in a line.
void Reset()
Reset all accumulators and counters to zero.
int Height() const
Returns the height of the boxcar.
double p_lastSum
The last sum of a full boxcar.
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.
Namespace for the standard library.