USGS

Isis 3.0 Object Programmers' Reference

Home

QuickFilter.cpp
Go to the documentation of this file.
1 
23 #include "QuickFilter.h"
24 #include "IException.h"
25 #include <float.h>
26 
27 using namespace std;
28 namespace Isis {
29 
43  QuickFilter::QuickFilter(const int ns, const int width,
44  const int height) {
45  // Error checks
46  if(ns <= 0) {
47  string msg = "Invalid value for [ns] in QuickFilter constructor";
48  throw IException(IException::Programmer, msg, _FILEINFO_);
49  }
50 
51  if(width < 1) {
52  string m = "[Width] must be must be greater than or equal to one in ";
53  m += "QuickFilter constructor";
54  throw IException(IException::Programmer, m, _FILEINFO_);
55  }
56  else if((width % 2) == 0) {
57  string m = "[Width] must be must be odd in ";
58  m += "QuickFilter constructor";
59  throw IException(IException::Programmer, m, _FILEINFO_);
60  }
61 
62  if(height < 1) {
63  string m = "[Height] must be must be greater than or equal to one in ";
64  m += "QuickFilter constructor";
65  throw IException(IException::Programmer, m, _FILEINFO_);
66  }
67  else if((height % 2) == 0) {
68  string m = "[Height] must be must be odd in ";
69  m += "QuickFilter constructor";
70  throw IException(IException::Programmer, m, _FILEINFO_);
71  }
72 
73  // Create buffers
74  p_sums = new double[ns];
75  p_sumsqrs = new double[ns];
76  p_counts = new int[ns];
77  p_ns = ns;
78 
79  // Set defaults for min/max and valid pixels
80  p_minimum = -DBL_MAX;
81  p_maximum = DBL_MAX;
82  p_minimumPixels = 0;
83 
84  // Set the boxcar size and compute half the size
85  p_width = width;
86  p_halfWidth = width / 2;
87 
88  p_height = height;
89  p_halfHeight = height / 2;
90 
91  Reset();
92  }
93 
95  void QuickFilter::Reset() {
96  // Initialize buffers
97  for(int i = 0; i < p_ns; i++) {
98  p_sums[i] = 0.0;
99  p_sumsqrs[i] = 0.0;
100  p_counts[i] = 0;
101 
102  }
103 
104  // Initialize sums for the last time Average/Variance/Count were called
105  p_lastSum = 0.0;
106  p_lastSumsqr = 0.0;
107  p_lastCount = 0;
108  p_lastIndex = -100;
109  p_linesAdded = 0;
110  }
111 
113  QuickFilter::~QuickFilter() {
114  delete [] p_sums;
115  delete [] p_counts;
116  delete [] p_sumsqrs;
117  }
118 
134  void QuickFilter::SetMinMax(const double minimum, const double maximum) {
135  if(minimum >= maximum) {
136  string m = "Minimum must be less than maximum in [QuickFilter::SetMinMax]";
137  throw IException(IException::Programmer, m, _FILEINFO_);
138  }
139 
140  p_minimum = minimum;
141  p_maximum = maximum;
142  p_lastIndex = -100;
143  }
144 
155  void QuickFilter::SetMinimumPixels(const int pixels) {
156  if(pixels < 0) {
157  string m = "Pixels must be greater than or equal to zero in ";
158  m += "[QuickFilter::SetMinimumPixels]";
159  throw IException(IException::Programmer, m, _FILEINFO_);
160  }
161  p_minimumPixels = pixels;
162  if(p_minimumPixels > p_width * p_height) {
163  p_minimumPixels = p_width * p_height;
164  }
165  }
166 
178  void QuickFilter::AddLine(const double *buf) {
179  // Check for adding too many lines
180  p_linesAdded++;
181  if(p_linesAdded > p_height) {
182  string m = "Number of lines added exceeds boxcar height ... ";
183  m += "use RemoveLine before AddLine";
184  throw IException(IException::Programmer, m, _FILEINFO_);
185  }
186 
187  for(int i = 0; i < p_ns; i++) {
188  if(Isis::IsValidPixel(buf[i])) {
189  if(buf[i] < p_minimum) continue;
190  if(buf[i] > p_maximum) continue;
191  p_sums[i] += buf[i];
192  p_sumsqrs[i] += buf[i] * buf[i];
193  p_counts[i]++;
194  p_lastIndex = -100;
195  }
196  }
197  }
198 
204  void QuickFilter::RemoveLine(const double *buf) {
205  for(int i = 0; i < p_ns; i++) {
206  if(Isis::IsValidPixel(buf[i])) {
207  if(buf[i] < p_minimum) continue;
208  if(buf[i] > p_maximum) continue;
209  p_sums[i] -= buf[i];
210  p_sumsqrs[i] -= buf[i] * buf[i];
211  p_counts[i]--;
212  p_lastIndex = -100;
213  }
214  }
215  p_linesAdded--;
216  }
217 
229  double QuickFilter::Average(const int index) {
230  // Move the boxcar if necessary
231  Compute(index);
232 
233  // Return NULL8 if we have invalid conditions
234  if(p_lastCount < p_minimumPixels) return Isis::NULL8;
235  if(p_lastCount <= 0) return Isis::NULL8;
236 
237  // Return the average
238  return p_lastSum / (double) p_lastCount;
239  }
240 
252  double QuickFilter::Variance(const int index) {
253  // Move the boxcar if necessary
254  Compute(index);
255 
256  // Return NULL8 if we have invalid conditions
257  if(p_lastCount < p_minimumPixels) return Isis::NULL8;
258  if(p_lastCount <= 1) return Isis::NULL8;
259 
260  // Return the variance
261  double temp = p_lastCount * p_lastSumsqr - p_lastSum * p_lastSum;
262  if(temp < 0.0) temp = 0.0; // This shouldn't happen unless roundoff occurs
263  return temp / ((double)(p_lastCount - 1) * (double) p_lastCount);
264  }
265 
276  int QuickFilter::Count(const int index) {
277  // Move the boxcar if necessary
278  Compute(index);
279 
280  // Return the valid count
281  return p_lastCount;
282  }
283 
289  int QuickFilter::Width() const {
290  return p_width;
291  }
292 
299  int QuickFilter::HalfWidth() const {
300  return p_halfWidth;
301  }
302 
308  int QuickFilter::Height() const {
309  return p_height;
310  }
311 
318  int QuickFilter::HalfHeight() const {
319  return p_halfHeight;
320  }
321 
327  int QuickFilter::Samples() const {
328  return p_ns;
329  }
330 
336  double QuickFilter::Low() const {
337  return p_minimum;
338  }
339 
345  double QuickFilter::High() const {
346  return p_maximum;
347  }
348 
356  int QuickFilter::MinimumPixels() const {
357  return p_minimumPixels;
358  }
359 
368  void QuickFilter::Compute(const int index) {
369  // If the index hasn't changed just return
370  if(index == p_lastIndex) return;
371 
372  // Determine start and stop indeces
373  int start = index - p_halfWidth;
374  int stop = index + p_halfWidth;
375 
376  // See if the index has increased by one
377  if(index == p_lastIndex + 1) {
378  // Remove one column
379  start--;
380  if(start < 0) start = -1 * start;
381  p_lastSum -= p_sums[start];
382  p_lastSumsqr -= p_sumsqrs[start];
383  p_lastCount -= p_counts[start];
384 
385  // Add another column
386  if(stop >= p_ns) stop = p_ns - (stop - p_ns + 2);
387  p_lastSum += p_sums[stop];
388  p_lastSumsqr += p_sumsqrs[stop];
389  p_lastCount += p_counts[stop];
390  }
391 
392  // Recompute everything
393  else {
394  p_lastSum = 0.0;
395  p_lastCount = 0;
396  p_lastSumsqr = 0.0;
397  int j;
398  for(int i = start; i <= stop; i++) {
399  j = i;
400  if(i < 0) {
401  j = -1 * i;
402  }
403  else if(i >= p_ns) {
404  j = p_ns - (i - p_ns + 2);
405  }
406 
407  p_lastSum += p_sums[j];
408  p_lastSumsqr += p_sumsqrs[j];
409  p_lastCount += p_counts[j];
410  }
411  }
412 
413  // Save the current index
414  p_lastIndex = index;
415  }
416 } // end namespace isis