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