Isis 3 Programmer Reference
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 "PvlGroup.h"
37 #include "PvlKeyword.h"
38 #include "PvlObject.h"
39 
40 using namespace std;
41 namespace Isis {
42 
48  OverlapStatistics::OverlapStatistics(const PvlObject &inStats) {
49  init();
50  fromPvl(inStats);
51  }
52 
67  OverlapStatistics::OverlapStatistics(Isis::Cube &x, Isis::Cube &y,
68  QString progressMsg, double sampPercent) {
69 
70  init();
71 
72  // Test to ensure sampling percent in bound
73  if (sampPercent <= 0.0 || sampPercent > 100.0) {
74  string msg = "The sampling percent must be a decimal (0.0, 100.0]";
75  throw IException(IException::Programmer, msg, _FILEINFO_);
76  }
77 
78  p_sampPercent = sampPercent;
79 
80  // Extract filenames and band number from cubes
81  p_xFile = x.fileName();
82  p_yFile = y.fileName();
83 
84  // Make sure number of bands match
85  if (x.bandCount() != y.bandCount()) {
86  QString msg = "Number of bands do not match between cubes [" +
87  p_xFile.name() + "] and [" + p_yFile.name() + "]";
88  throw IException(IException::User, msg, _FILEINFO_);
89  }
90  p_bands = x.bandCount();
91  p_stats.resize(p_bands);
92 
93  //Create projection from each cube
94  Projection *projX = x.projection();
95  Projection *projY = y.projection();
96 
97  // Test to make sure projection parameters match
98  if (*projX != *projY) {
99  QString msg = "Mapping groups do not match between cubes [" +
100  p_xFile.name() + "] and [" + p_yFile.name() + "]";
101  throw IException(IException::Programmer, msg, _FILEINFO_);
102  }
103 
104  // Figure out the x/y range for both images to find the overlap
105  double Xmin1 = projX->ToProjectionX(0.5);
106  double Ymax1 = projX->ToProjectionY(0.5);
107  double Xmax1 = projX->ToProjectionX(x.sampleCount() + 0.5);
108  double Ymin1 = projX->ToProjectionY(x.lineCount() + 0.5);
109 
110  double Xmin2 = projY->ToProjectionX(0.5);
111  double Ymax2 = projY->ToProjectionY(0.5);
112  double Xmax2 = projY->ToProjectionX(y.sampleCount() + 0.5);
113  double Ymin2 = projY->ToProjectionY(y.lineCount() + 0.5);
114 
115  // Find overlap
116  if ((Xmin1 < Xmax2) && (Xmax1 > Xmin2) && (Ymin1 < Ymax2) && (Ymax1 > Ymin2)) {
117  double minX = Xmin1 > Xmin2 ? Xmin1 : Xmin2;
118  double minY = Ymin1 > Ymin2 ? Ymin1 : Ymin2;
119  double maxX = Xmax1 < Xmax2 ? Xmax1 : Xmax2;
120  double maxY = Ymax1 < Ymax2 ? Ymax1 : Ymax2;
121 
122  // Find Sample range of the overlap
123  p_minSampX = (int)(projX->ToWorldX(minX) + 0.5);
124  p_maxSampX = (int)(projX->ToWorldX(maxX) + 0.5);
125  p_minSampY = (int)(projY->ToWorldX(minX) + 0.5);
126  p_maxSampY = (int)(projY->ToWorldX(maxX) + 0.5);
127  p_sampRange = p_maxSampX - p_minSampX + 1;
128 
129  // Test to see if there was only sub-pixel overlap
130  if (p_sampRange <= 0) return;
131 
132  // Find Line range of overlap
133  p_minLineX = (int)(projX->ToWorldY(maxY) + 0.5);
134  p_maxLineX = (int)(projX->ToWorldY(minY) + 0.5);
135  p_minLineY = (int)(projY->ToWorldY(maxY) + 0.5);
136  p_maxLineY = (int)(projY->ToWorldY(minY) + 0.5);
137  p_lineRange = p_maxLineX - p_minLineX + 1;
138 
139  // Print percent processed
140  Progress progress;
141  progress.SetText(progressMsg);
142 
143  int linc = (int)(100.0 / sampPercent + 0.5); // Calculate our line increment
144 
145  // Define the maximum number of steps to be our line range divided by the
146  // line increment, but if they do not divide evenly, then because of
147  // rounding, we need to do an additional step for each band
148  int maxSteps = (int)(p_lineRange / linc + 0.5);
149 
150  if (p_lineRange % linc != 0) maxSteps += 1;
151  maxSteps *= p_bands;
152 
153 
154  progress.SetMaximumSteps(maxSteps);
155  progress.CheckStatus();
156 
157  // Collect and store off the overlap statistics
158  for (int band = 1; band <= p_bands; band++) {
159  Brick b1(p_sampRange, 1, 1, x.pixelType());
160  Brick b2(p_sampRange, 1, 1, y.pixelType());
161 
162  int i = 0;
163  while(i < p_lineRange) {
164  b1.SetBasePosition(p_minSampX, (i + p_minLineX), band);
165  b2.SetBasePosition(p_minSampY, (i + p_minLineY), band);
166  x.read(b1);
167  y.read(b2);
168  p_stats[band-1].AddData(b1.DoubleBuffer(), b2.DoubleBuffer(), p_sampRange);
169 
170  // Make sure we consider the last line
171  if (i + linc > p_lineRange - 1 && i != p_lineRange - 1) {
172  i = p_lineRange - 1;
173  progress.AddSteps(1);
174  }
175  else i += linc; // Increment the current line by our incrementer
176 
177  progress.CheckStatus();
178  }
179  }
180  }
181  }
182 
183 
191  bool OverlapStatistics::HasOverlap() const {
192  for (int b = 0; b < p_bands; b++) {
193  if (p_stats[b].ValidPixels() > 0) return true;
194  }
195  return false;
196  }
197 
198 
208  PvlObject OverlapStatistics::toPvl(QString name) const {
209  try {
210  // Empty strings are set to default value as well
211  if (name.isEmpty()) {
212  name = "OverlapStatistics";
213  }
214 
215  // Add keywords for OverlapStatistics data
216  PvlObject o(name);
217  o += PvlKeyword("File1", FileNameX().name());
218  o += PvlKeyword("File2", FileNameY().name());
219  o += PvlKeyword("Width", toString(Samples()));
220  o += PvlKeyword("Height", toString(Lines()));
221  o += PvlKeyword("Bands", toString(Bands()));
222  o += PvlKeyword("SamplingPercent", toString(SampPercent()));
223  o += PvlKeyword("MinCount", toString(MinCount())); // Do we need this if EqInfo has this?
224 
225  // Create group for first file of overlap
226  PvlGroup gX("File1");
227  PvlKeyword stsX("StartSample", toString(StartSampleX()));
228  PvlKeyword ensX("EndSample", toString(EndSampleX()));
229  PvlKeyword stlX("StartLine", toString(StartLineX()));
230  PvlKeyword enlX("EndLine", toString(EndLineX()));
231  PvlKeyword avgX("Average");
232  PvlKeyword stdX("StandardDeviation");
233  PvlKeyword varX("Variance");
234  for (int band = 1; band <= Bands(); band++) {
235  if (HasOverlap(band)) {
236  avgX += toString(GetMStats(band).X().Average());
237  stdX += toString(GetMStats(band).X().StandardDeviation());
238  varX += toString(GetMStats(band).X().Variance());
239  }
240  }
241  gX += stsX;
242  gX += ensX;
243  gX += stlX;
244  gX += enlX;
245  gX += avgX;
246  gX += stdX;
247  gX += varX;
248 
249  // Create group for second file of overlap
250  PvlGroup gY("File2");
251  PvlKeyword stsY("StartSample", toString(StartSampleY()));
252  PvlKeyword ensY("EndSample", toString(EndSampleY()));
253  PvlKeyword stlY("StartLine", toString(StartLineY()));
254  PvlKeyword enlY("EndLine", toString(EndLineY()));
255  PvlKeyword avgY("Average");
256  PvlKeyword stdY("StandardDeviation");
257  PvlKeyword varY("Variance");
258  for (int band = 1; band <= Bands(); band++) {
259  if (HasOverlap(band)) {
260  avgY += toString(GetMStats(band).Y().Average());
261  stdY += toString(GetMStats(band).Y().StandardDeviation());
262  varY += toString(GetMStats(band).Y().Variance());
263  }
264  }
265  gY += stsY;
266  gY += ensY;
267  gY += stlY;
268  gY += enlY;
269  gY += avgY;
270  gY += stdY;
271  gY += varY;
272 
273  o.addGroup(gX);
274  o.addGroup(gY);
275 
276  bool isValid = false;
277  // Unserialize the MultivariateStatistics
278  for (int band = 1; band <= Bands(); band++) {
279  PvlKeyword validBand("ValidOverlap", "false");
280 
281  if (HasOverlap(band)) {
282  if (IsValid(band)) {
283  validBand.setValue("true");
284  isValid = true;
285  }
286  }
287 
288  QString mStatsName = "MultivariateStatistics" + toString(band);
289  PvlObject mStats(GetMStats(band).toPvl(mStatsName));
290  mStats += validBand;
291  o.addObject(mStats);
292  }
293  PvlKeyword valid("Valid", (isValid) ? "true" : "false");
294  o += valid;
295  return o;
296  }
297 
298  catch (IException &e) {
299  QString msg = "Trivial overlap between [" + FileNameX().name();
300  msg += "] and [" + FileNameY().name() + "]";
301  throw IException(IException::User, msg, _FILEINFO_);
302  }
303  }
304 
305 
311  void OverlapStatistics::fromPvl(const PvlObject &inStats) {
312  init();
313 
314  const PvlGroup &fileX = inStats.findGroup("File1");
315  const PvlGroup &fileY = inStats.findGroup("File2");
316  p_xFile = inStats["File1"][0];
317  p_yFile = inStats["File2"][0];
318  p_sampRange = inStats["Width"];
319  p_lineRange = inStats["Height"];
320  p_bands = inStats["Bands"];
321  p_sampPercent = inStats["SamplingPercent"];
322 
323  p_minSampX = fileX["StartSample"];
324  p_maxSampX = fileX["EndSample"];
325  p_minLineX = fileX["StartLine"];
326  p_maxLineX = fileX["EndLine"];
327 
328  p_minSampY = fileY["StartSample"];
329  p_maxSampY = fileY["EndSample"];
330  p_minLineY = fileY["StartLine"];
331  p_maxLineY = fileY["EndLine"];
332 
333  p_mincnt = inStats["MinCount"];
334 
335  // unserialize the MStats
336  for (int band = 1; band <= Bands(); band++) {
337  QString name = "MultivariateStatistics" + toString(band);
338  const PvlObject &mStats = inStats.findObject(name);
339  p_stats.push_back(MultivariateStatistics(mStats));
340  }
341 
342  }
343 
344 
348  void OverlapStatistics::init() {
349  p_sampPercent = 0.0;
350  p_bands = 0;
351  p_sampRange = 0;
352  p_lineRange = 0;
353  p_minSampX = 0;
354  p_maxSampX = 0;
355  p_minSampY = 0;
356  p_maxSampY = 0;
357  p_minLineX = 0;
358  p_maxLineX = 0;
359  p_minLineY = 0;
360  p_maxLineY = 0;
361  p_mincnt = 0;
362  }
363 
364 
373  std::ostream &operator<<(std::ostream &os, Isis::OverlapStatistics &stats) {
374  PvlObject p = stats.toPvl();
375  os << p << endl;
376  return os;
377  }
378 
379 }
380 
void SetMaximumSteps(const int steps)
This sets the maximum number of steps in the process.
Definition: Progress.cpp:101
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition: PvlObject.h:141
PvlObject toPvl(QString name="OverlapStatistics") const
Creates a Pvl containing the following Overlap Statistics information File1 File2 Width Height Bands ...
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
Definition: PvlObject.h:286
int sampleCount() const
Definition: Cube.cpp:1452
void addGroup(const Isis::PvlGroup &group)
Add a group to the object.
Definition: PvlObject.h:198
Buffer for containing a three dimensional section of an image.
Definition: Brick.h:61
double ToProjectionX(const double worldX) const
This method converts a world x value to a projection x value.
Definition: Projection.cpp:637
Namespace for the standard library.
void SetBasePosition(const int start_sample, const int start_line, const int start_band)
This method is used to set the base position of the shape buffer.
Definition: Brick.h:136
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
Projection * projection()
Definition: Cube.cpp:1439
void CheckStatus()
Checks and updates the status.
Definition: Progress.cpp:121
void addObject(const PvlObject &object)
Add a PvlObject.
Definition: PvlObject.h:319
QString name() const
Returns the container name.
Definition: PvlContainer.h:77
std::ostream & operator<<(std::ostream &os, Isis::OverlapStatistics &stats)
Creates a pvl of various useful data obtained by the overlap statistics class.
double ToWorldX(const double projectionX) const
This method converts a projection x value to a world x value.
Definition: Projection.cpp:581
Base class for Map Projections.
Definition: Projection.h:171
Program progress reporter.
Definition: Progress.h:58
Container of multivariate statistics.
void AddSteps(const int steps)
If the initial step size was a guess, it can be modified using this method.
Definition: Progress.cpp:215
void SetText(const QString &text)
Changes the value of the text string reported just before 0% processed.
Definition: Progress.cpp:77
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
double ToProjectionY(const double worldY) const
This method converts a world y value to a projection y value.
Definition: Projection.cpp:665
A single keyword-value pair.
Definition: PvlKeyword.h:98
void read(Blob &blob) const
This method will read data from the specified Blob object.
Definition: Cube.cpp:724
PixelType pixelType() const
Definition: Cube.cpp:1403
Calculates statistics in the area of overlap between two projected cubes.
virtual QString fileName() const
Returns the opened cube&#39;s filename.
Definition: Cube.cpp:1208
int lineCount() const
Definition: Cube.cpp:1379
Isis exception class.
Definition: IException.h:107
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
virtual int bandCount() const
Returns the number of virtual bands for the cube.
Definition: Cube.cpp:1125
double ToWorldY(const double projectionY) const
This method converts a projection y value to a world y value.
Definition: Projection.cpp:609
void setValue(QString value, QString unit="")
Sets new values.
Definition: PvlKeyword.cpp:171
Contains Pvl Groups and Pvl Objects.
Definition: PvlObject.h:74
Functor for reduce using average functionality.
Definition: Reduce.h:102
IO Handler for Isis Cubes.
Definition: Cube.h:170