USGS

Isis 3.0 Object Programmers' Reference

Home

OverlapStatistics.cpp
Go to the documentation of this file.
1 
23 #include "OverlapStatistics.h"
24 
25 #include <cfloat>
26 #include <iomanip>
27 
28 #include "Brick.h"
29 #include "Cube.h"
30 #include "FileName.h"
31 #include "IException.h"
32 #include "MultivariateStatistics.h"
33 #include "Progress.h"
34 #include "Projection.h"
35 #include "ProjectionFactory.h"
36 #include "PvlObject.h"
37 
38 using namespace std;
39 namespace Isis {
40 
55  OverlapStatistics::OverlapStatistics(Isis::Cube &x, Isis::Cube &y,
56  QString progressMsg, double sampPercent) {
57  // Test to ensure sampling percent in bound
58  if (sampPercent <= 0.0 || sampPercent > 100.0) {
59  string msg = "The sampling percent must be a decimal (0.0, 100.0]";
60  throw IException(IException::Programmer, msg, _FILEINFO_);
61  }
62 
63  p_sampPercent = sampPercent;
64 
65  // Extract filenames and band number from cubes
66  p_xFile = x.fileName();
67  p_yFile = y.fileName();
68 
69  // Make sure number of bands match
70  if (x.bandCount() != y.bandCount()) {
71  QString msg = "Number of bands do not match between cubes [" +
72  p_xFile.name() + "] and [" + p_yFile.name() + "]";
73  throw IException(IException::User, msg, _FILEINFO_);
74  }
75  p_bands = x.bandCount();
76  p_stats.resize(p_bands);
77 
78  //Create projection from each cube
79  Projection *projX = x.projection();
80  Projection *projY = y.projection();
81 
82  // Test to make sure projection parameters match
83  if (*projX != *projY) {
84  QString msg = "Mapping groups do not match between cubes [" +
85  p_xFile.name() + "] and [" + p_yFile.name() + "]";
86  throw IException(IException::Programmer, msg, _FILEINFO_);
87  }
88 
89  // Figure out the x/y range for both images to find the overlap
90  double Xmin1 = projX->ToProjectionX(0.5);
91  double Ymax1 = projX->ToProjectionY(0.5);
92  double Xmax1 = projX->ToProjectionX(x.sampleCount() + 0.5);
93  double Ymin1 = projX->ToProjectionY(x.lineCount() + 0.5);
94 
95  double Xmin2 = projY->ToProjectionX(0.5);
96  double Ymax2 = projY->ToProjectionY(0.5);
97  double Xmax2 = projY->ToProjectionX(y.sampleCount() + 0.5);
98  double Ymin2 = projY->ToProjectionY(y.lineCount() + 0.5);
99 
100  // Find overlap
101  if ((Xmin1 < Xmax2) && (Xmax1 > Xmin2) && (Ymin1 < Ymax2) && (Ymax1 > Ymin2)) {
102  double minX = Xmin1 > Xmin2 ? Xmin1 : Xmin2;
103  double minY = Ymin1 > Ymin2 ? Ymin1 : Ymin2;
104  double maxX = Xmax1 < Xmax2 ? Xmax1 : Xmax2;
105  double maxY = Ymax1 < Ymax2 ? Ymax1 : Ymax2;
106 
107  // Find Sample range of the overlap
108  p_minSampX = (int)(projX->ToWorldX(minX) + 0.5);
109  p_maxSampX = (int)(projX->ToWorldX(maxX) + 0.5);
110  p_minSampY = (int)(projY->ToWorldX(minX) + 0.5);
111  p_maxSampY = (int)(projY->ToWorldX(maxX) + 0.5);
112  p_sampRange = p_maxSampX - p_minSampX + 1;
113 
114  // Test to see if there was only sub-pixel overlap
115  if (p_sampRange <= 0) return;
116 
117  // Find Line range of overlap
118  p_minLineX = (int)(projX->ToWorldY(maxY) + 0.5);
119  p_maxLineX = (int)(projX->ToWorldY(minY) + 0.5);
120  p_minLineY = (int)(projY->ToWorldY(maxY) + 0.5);
121  p_maxLineY = (int)(projY->ToWorldY(minY) + 0.5);
122  p_lineRange = p_maxLineX - p_minLineX + 1;
123 
124  // Print percent processed
125  Progress progress;
126  progress.SetText(progressMsg);
127 
128  int linc = (int)(100.0 / sampPercent + 0.5); // Calculate our line increment
129 
130  // Define the maximum number of steps to be our line range divided by the
131  // line increment, but if they do not divide evenly, then because of
132  // rounding, we need to do an additional step for each band
133  int maxSteps = (int)(p_lineRange / linc + 0.5);
134 
135  if (p_lineRange % linc != 0) maxSteps += 1;
136  maxSteps *= p_bands;
137 
138 
139  progress.SetMaximumSteps(maxSteps);
140  progress.CheckStatus();
141 
142  // Collect and store off the overlap statistics
143  for (int band = 1; band <= p_bands; band++) {
144  Brick b1(p_sampRange, 1, 1, x.pixelType());
145  Brick b2(p_sampRange, 1, 1, y.pixelType());
146 
147  int i = 0;
148  while(i < p_lineRange) {
149  b1.SetBasePosition(p_minSampX, (i + p_minLineX), band);
150  b2.SetBasePosition(p_minSampY, (i + p_minLineY), band);
151  x.read(b1);
152  y.read(b2);
153  p_stats[band-1].AddData(b1.DoubleBuffer(), b2.DoubleBuffer(), p_sampRange);
154 
155  // Make sure we consider the last line
156  if (i + linc > p_lineRange - 1 && i != p_lineRange - 1) {
157  i = p_lineRange - 1;
158  progress.AddSteps(1);
159  }
160  else i += linc; // Increment the current line by our incrementer
161 
162  progress.CheckStatus();
163  }
164  }
165  }
166  }
167 
175  bool OverlapStatistics::HasOverlap() const {
176  for (int b = 0; b < p_bands; b++) {
177  if (p_stats[b].ValidPixels() > 0) return true;
178  }
179  return false;
180  }
181 
182 
183  PvlObject OverlapStatistics::toPvl() const {
184  // Output the private variables
185  try {
186  PvlObject o("OverlapStatistics");
187  PvlGroup gX("File1");
188  PvlKeyword stsX("StartSample", toString(StartSampleX()));
189  PvlKeyword ensX("EndSample", toString(EndSampleX()));
190  PvlKeyword stlX("StartLine", toString(StartLineX()));
191  PvlKeyword enlX("EndLine", toString(EndLineX()));
192  PvlKeyword avgX("Average");
193  PvlKeyword stdX("StandardDeviation");
194  PvlKeyword varX("Variance");
195  for (int band = 1; band <= Bands(); band++) {
196  if (HasOverlap(band)) {
197  avgX += toString(GetMStats(band).X().Average());
198  stdX += toString(GetMStats(band).X().StandardDeviation());
199  varX += toString(GetMStats(band).X().Variance());
200  }
201  }
202  gX += stsX;
203  gX += ensX;
204  gX += stlX;
205  gX += enlX;
206  gX += avgX;
207  gX += stdX;
208  gX += varX;
209 
210  PvlGroup gY("File2");
211  PvlKeyword stsY("StartSample", toString(StartSampleY()));
212  PvlKeyword ensY("EndSample", toString(EndSampleY()));
213  PvlKeyword stlY("StartLine", toString(StartLineY()));
214  PvlKeyword enlY("EndLine", toString(EndLineY()));
215  PvlKeyword avgY("Average");
216  PvlKeyword stdY("StandardDeviation");
217  PvlKeyword varY("Variance");
218  for (int band = 1; band <= Bands(); band++) {
219  if (HasOverlap(band)) {
220  avgY += toString(GetMStats(band).Y().Average());
221  stdY += toString(GetMStats(band).Y().StandardDeviation());
222  varY += toString(GetMStats(band).Y().Variance());
223  }
224  }
225  gY += stsY;
226  gY += ensY;
227  gY += stlY;
228  gY += enlY;
229  gY += avgY;
230  gY += stdY;
231  gY += varY;
232 
233  o += PvlKeyword("File1", FileNameX().name());
234  o += PvlKeyword("File2", FileNameY().name());
235  o += PvlKeyword("Width", toString(Samples()));
236  o += PvlKeyword("Height", toString(Lines()));
237  o += PvlKeyword("SamplingPercent", toString(SampPercent()));
238  o.addGroup(gX);
239  o.addGroup(gY);
240 
241  PvlKeyword cov("Covariance");
242  PvlKeyword cor("Correlation");
243 
244  PvlKeyword valid("ValidOverlap");
245  PvlKeyword val("ValidPixels");
246  PvlKeyword inv("InvalidPixels");
247  PvlKeyword tot("TotalPixels");
248  for (int band = 1; band <= Bands(); band++) {
249  if (HasOverlap(band)) {
250  QString validStr = "false";
251  if (IsValid(band)) validStr = "true";
252  valid += validStr;
253  cov += toString(GetMStats(band).Covariance());
254  cor += toString(GetMStats(band).Correlation());
255  val += toString(GetMStats(band).ValidPixels());
256  inv += toString(GetMStats(band).InvalidPixels());
257  tot += toString(GetMStats(band).TotalPixels());
258  }
259  }
260  o += valid;
261  o += cov;
262  o += cor;
263  o += val;
264  o += inv;
265  o += tot;
266 
267  for (int band = 1; band <= Bands(); band++) {
268  if (HasOverlap(band)) {
269  QString bandStr = "LinearRegression" + toString(band);
270  PvlKeyword LinReg(bandStr);
271  double a, b;
272  try {
273  GetMStats(band).LinearRegression(a, b);
274  LinReg += toString(a);
275  LinReg += toString(b);
276  }
277  catch (IException &e) {
278  // It is possible one of the overlaps was constant and therefore
279  // the regression would be a vertical line (x=c instead of y=ax+b)
280  }
281  o += LinReg;
282  }
283  }
284 
285  return o;
286  }
287  catch (IException &e) {
288  QString msg = "Trivial overlap between [" + FileNameX().name();
289  msg += "] and [" + FileNameY().name() + "]";
290  throw IException(IException::User, msg, _FILEINFO_);
291  }
292  }
293 
294 
303  std::ostream &operator<<(std::ostream &os, Isis::OverlapStatistics &stats) {
304  PvlObject p = stats.toPvl();
305  os << p << endl;
306  return os;
307  }
308 
309 
310 }
311