Isis 3 Programmer Reference
ScatterPlotData.cpp
1 #include "IsisDebug.h"
2 #include "ScatterPlotData.h"
3 
4 #include <algorithm>
5 
6 #include <QtCore>
7 
8 #include "Brick.h"
9 #include "SpecialPixel.h"
10 
11 namespace Isis {
27  Cube *xCube, int xCubeBand, int xBinCount,
28  Cube *yCube, int yCubeBand, int yBinCount,
29  QwtInterval sampleRange, QwtInterval lineRange) : QwtRasterData(),
30  m_xDnToBinStretch(new Stretch), m_yDnToBinStretch(new Stretch),
31  m_counts(
32  new QVector< QVector<int> >(yBinCount, QVector<int>(xBinCount))),
33  m_alarmedBins(new QMap<int, bool>) {
34  int startLine = qRound(lineRange.minValue());
35  int endLine = qRound(lineRange.maxValue());
36  ASSERT(xCube->lineCount() == yCube->lineCount());
37 
38  Histogram *xCubeHist = new Histogram(*xCube, xCubeBand, NULL,
39  sampleRange.minValue(), lineRange.minValue(),
40  sampleRange.maxValue(), lineRange.maxValue(),
41  xBinCount, true);
42  m_xCubeMin = xCubeHist->Minimum();
43  m_xCubeMax = xCubeHist->Maximum();
44 
45 
46  Histogram *yCubeHist = new Histogram(*yCube, yCubeBand, NULL,
47  sampleRange.minValue(), lineRange.minValue(),
48  sampleRange.maxValue(), lineRange.maxValue(),
49  yBinCount, true);
50  m_yCubeMin = yCubeHist->Minimum();
51  m_yCubeMax = yCubeHist->Maximum();
52 
53 
54  m_xDnToBinStretch->AddPair(m_xCubeMin, 0);
55  m_xDnToBinStretch->AddPair(m_xCubeMax, xBinCount - 1);
56 
57  m_yDnToBinStretch->AddPair(m_yCubeMin, 0);
58  m_yDnToBinStretch->AddPair(m_yCubeMax, yBinCount - 1);
59 
60  m_maxCount = 0;
61 
62  Brick brick1((int)(sampleRange.maxValue() - sampleRange.minValue() + 1),
63  1, 1, xCube->pixelType());
64  Brick brick2((int)(sampleRange.maxValue() - sampleRange.minValue() + 1),
65  1, 1, yCube->pixelType());
66  ASSERT(xCube->sampleCount() == yCube->sampleCount());
67  ASSERT(brick1.size() == brick2.size());
68 
69  for (int line = startLine; line <= endLine; line++) {
70  brick1.SetBasePosition(qRound(sampleRange.minValue()), line, xCubeBand);
71  xCube->read(brick1);
72 
73  brick2.SetBasePosition(qRound(sampleRange.minValue()), line, yCubeBand);
74  yCube->read(brick2);
75 
76  for (int i = 0; i < brick1.size(); i++) {
77  double xDn = brick1[i];
78  double yDn = brick2[i];
79 
80  if (!IsSpecial(xDn) && !IsSpecial(yDn)) {
81  double x = m_xDnToBinStretch->Map(xDn);
82  double y = m_yDnToBinStretch->Map(yDn);
83 
84  if (!IsSpecial(x) && !IsSpecial(y)) {
85  int roundedX = qRound(x);
86  int roundedY = qRound(y);
87 
88  if (roundedX >= 0 && roundedX < xBinCount &&
89  roundedY >= 0 && roundedY < yBinCount) {
90  int value = (*m_counts)[roundedY][roundedX] + 1;
91  (*m_counts)[roundedY][roundedX] = value;
92 
93  m_maxCount = qMax(m_maxCount, value);
94  }
95  }
96  }
97  }
98  }
99 
100  setInterval(Qt::XAxis, QwtInterval(m_xCubeMin, m_xCubeMax));
101  setInterval(Qt::YAxis, QwtInterval(m_yCubeMin, m_yCubeMax));
102  setInterval(Qt::ZAxis, QwtInterval(0, m_maxCount));
103  }
104 
105 
113  m_xDnToBinStretch.reset(new Stretch(*other.m_xDnToBinStretch));
114  m_yDnToBinStretch.reset(new Stretch(*other.m_yDnToBinStretch));
115  m_counts.reset(new QVector< QVector<int> >(*other.m_counts));
116  m_alarmedBins.reset(new QMap< int, bool>(*other.m_alarmedBins));
117  m_maxCount = other.m_maxCount;
118  m_xCubeMin = other.m_xCubeMin;
119  m_xCubeMax = other.m_xCubeMax;
120  m_yCubeMin = other.m_yCubeMin;
121  m_yCubeMax = other.m_yCubeMax;
122  }
123 
124 
130  }
131 
132 
139  return new ScatterPlotData(*this);
140  }
141 
142 
152  double ScatterPlotData::value(double x, double y) const {
153  double value = 0;
154 
155  QPair<int, int> indices = binXYIndices(x, y);
156  int index = binIndex(indices.first, indices.second);
157 
158  if (index != -1 && (*m_alarmedBins)[index])
159  value = m_maxCount;
160  else
161  value = binCount(indices.first, indices.second);
162 
163  return value;
164  }
165 
166 
172  double ScatterPlotData::xCubeMin() const {
173  return m_xCubeMin;
174  }
175 
176 
182  double ScatterPlotData::xCubeMax() const {
183  return m_xCubeMax;
184  }
185 
186 
192  double ScatterPlotData::yCubeMin() const {
193  return m_yCubeMin;
194  }
195 
196 
202  double ScatterPlotData::yCubeMax() const {
203  return m_yCubeMax;
204  }
205 
206 
215  m_counts.swap(other.m_counts);
216  m_alarmedBins.swap(other.m_alarmedBins);
217  std::swap(m_maxCount, other.m_maxCount);
218  std::swap(m_xCubeMin, other.m_xCubeMin);
219  std::swap(m_xCubeMax, other.m_xCubeMax);
220  std::swap(m_yCubeMin, other.m_yCubeMin);
221  std::swap(m_yCubeMax, other.m_yCubeMax);
222  }
223 
224 
233  QPair<int, int> indices = binXYIndices(index);
234  int xIndex = indices.first;
235  int yIndex = indices.second;
236 
237  if (xIndex != -1 && yIndex != -1) {
238  int xSize = 0;
239  int ySize = m_counts->size();
240 
241  // Assume square 2D structurs
242  if (ySize > 0)
243  xSize = (*m_counts)[0].size();
244 
245  double percentAcrossXRange = ((double)xIndex / (double)xSize);
246  double xDnValue = m_xCubeMin +
247  percentAcrossXRange * (m_xCubeMax - m_xCubeMin);
248 
249  double percentAcrossYRange = ((double)yIndex / (double)ySize);
250  double yDnValue = m_yCubeMin +
251  percentAcrossYRange * (m_yCubeMax - m_yCubeMin);
252 
253  return QPair<double, double>(xDnValue, yDnValue);
254  }
255 
256 
257  QString msg = "Bin at index [" + QString::number(index) + "] not found. "
258  "There are [" + QString::number(numberOfBins()) + "] bins";
260  }
261 
262 
269  int ScatterPlotData::binCount(int binIndex) const {
271  return binCount(indices.first, indices.second);
272  }
273 
274 
281  int xSize = 0;
282  int ySize = m_counts->size();
283 
284  // Assume square 2D structurs
285  if (ySize > 0)
286  xSize = (*m_counts)[0].size();
287 
288  return xSize * ySize;
289  }
290 
291 
298  QVector<double> xValues;
299 
300  int ySize = m_counts->size();
301  if (ySize) {
302  int xSize = (*m_counts)[0].size();
303  xValues.resize(xSize);
304 
305  for (int xIndex = 0; xIndex < xSize; xIndex++) {
306  double percentAcrossXRange = ((double)xIndex / (double)xSize);
307  xValues[xIndex] = m_xCubeMin +
308  percentAcrossXRange * (m_xCubeMax - m_xCubeMin);
309  }
310  }
311 
312  return xValues;
313  }
314 
315 
323  void ScatterPlotData::alarm(double x, double y) {
324  int binToAlarm = binIndex(x, y);
325  if (binToAlarm != -1)
326  (*m_alarmedBins)[binToAlarm] = true;
327  }
328 
329 
334  m_alarmedBins->clear();
335  }
336 
337 
344  QRectF ScatterPlotData::pixelHint(const QRectF &area) const {
345  QRectF hint;
346 
347  if (m_xDnToBinStretch->Pairs() > 1 && m_yDnToBinStretch->Pairs() > 1) {
348  hint = QRectF(
349  QPointF(m_xCubeMin, m_yCubeMin),
350  QSizeF(m_xDnToBinStretch->Input(1) - m_xDnToBinStretch->Input(0),
351  m_yDnToBinStretch->Input(1) - m_yDnToBinStretch->Input(1)));
352  }
353 
354  return hint;
355  }
356 
357 
366  ScatterPlotData tmp(other);
367 
368  swap(tmp);
369 
370  return *this;
371  }
372 
373 
381  int ScatterPlotData::binCount(int xIndex, int yIndex) const {
382  int count = 0;
383 
384  if (yIndex >= 0 && yIndex < m_counts->size()) {
385  if (xIndex >= 0 && xIndex < (*m_counts)[yIndex].size()) {
386  count = (*m_counts)[yIndex][xIndex];
387  }
388  }
389 
390  return count;
391  }
392 
393 
402  int ScatterPlotData::binIndex(int xIndex, int yIndex) const {
403  int xSize = 0;
404  int ySize = m_counts->size();
405 
406  // Assume square 2D structurs
407  if (ySize > 0)
408  xSize = (*m_counts)[0].size();
409 
410  int index = -1;
411  if ((xIndex >= 0 && xIndex < xSize) && (yIndex >= 0 && yIndex < ySize))
412  index = xSize * yIndex + xIndex;
413 
414  return index;
415  }
416 
417 
425  int ScatterPlotData::binIndex(double x, double y) const {
426  QPair<int, int> indices = binXYIndices(x, y);
427  return binIndex(indices.first, indices.second);
428  }
429 
430 
438  int xSize = 0;
439  int ySize = m_counts->size();
440 
441  // Assume square 2D structurs
442  if (ySize > 0)
443  xSize = (*m_counts)[0].size();
444 
445  int yIndex = (binIndex / xSize);
446  binIndex -= yIndex * xSize;
447 
448  int xIndex = binIndex;
449 
450  if (xIndex < 0 || yIndex < 0 || xIndex >= xSize || yIndex >= ySize) {
451  QString msg = "Bin at index [" + QString::number(binIndex) + "] not found. "
452  "There are [" + QString::number(numberOfBins()) + "] bins";
454  }
455 
456  return QPair<int, int>(xIndex, yIndex);
457  }
458 
459 
467  QPair<int, int> ScatterPlotData::binXYIndices(double x, double y) const {
468  QPair<int, int> indices(-1, -1);
469 
470  if (m_counts->size() && m_counts->at(0).size()) {
471  double xBinPosition = m_xDnToBinStretch->Map(x);
472  double yBinPosition = m_yDnToBinStretch->Map(y);
473 
474  if (!IsSpecial(xBinPosition) && !IsSpecial(yBinPosition)) {
475  int discreteXBin = qRound(xBinPosition);
476  int discreteYBin = qRound(yBinPosition);
477 
478  if (discreteXBin >= 0 && discreteXBin < m_counts->at(0).size() &&
479  discreteYBin >= 0 && discreteYBin < m_counts->size()) {
480  indices = QPair<int, int>(discreteXBin, discreteYBin);
481  }
482  }
483  }
484 
485  return indices;
486  }
487 }
488 
int m_maxCount
The maximum value in m_counts, stored for efficiency.
ScatterPlotData(Cube *xCube, int xCubeBand, int xBinCount, Cube *yCube, int yCubeBand, int yBinCount, QwtInterval sampleRange, QwtInterval lineRange)
ScatterPlotDataConstructor.
double yCubeMax() const
Return the max DN value for the y-axis cube&#39;s data range.
double m_xCubeMax
The maximum DN value for the x cube.
double Minimum() const
Returns the absolute minimum double found in all data passed through the AddData method.
Definition: Statistics.cpp:395
double m_yCubeMin
The minimum DN value for the y cube.
int sampleCount() const
Definition: Cube.cpp:1452
Buffer for containing a three dimensional section of an image.
Definition: Brick.h:61
QPair< double, double > binXY(int binIndex) const
Get the center X/Y Dn values for the bin at index.
int binCount(int binIndex) const
Get the count (number of values) which fall into the bin at index.
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
double yCubeMin() const
Return the min DN value for the y-axis cube&#39;s data range.
~ScatterPlotData()
Destructor.
double Maximum() const
Returns the absolute maximum double found in all data passed through the AddData method.
Definition: Statistics.cpp:416
QRectF pixelHint(const QRectF &area) const
This is a hint given to qwt for how to render a pixel in the spectrogram.
double xCubeMin() const
Return the min DN value for the x-axis cube&#39;s data range.
Container of a cube histogram.
Definition: Histogram.h:86
Pixel value mapper.
Definition: Stretch.h:72
void alarm(double x, double y)
Alarm the bin (highlight it) at the given x/y DN value.
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
void read(Blob &blob) const
This method will read data from the specified Blob object.
Definition: Cube.cpp:724
bool IsSpecial(const double d)
Returns if the input pixel is special.
Definition: SpecialPixel.h:212
double m_yCubeMax
The maximum DN value for the y cube.
QScopedPointer< Stretch > m_xDnToBinStretch
Stretch 1.
PixelType pixelType() const
Definition: Cube.cpp:1403
QScopedPointer< QVector< QVector< int > > > m_counts
The bin counts stored by 2D (x/y) index position.
This is the QwtRasterData for a scatter plot.
double xCubeMax() const
Return the max DN value for the y-axis cube&#39;s data range.
ScatterPlotData & operator=(const ScatterPlotData &other)
Take the data from other and copy it into this.
QVector< double > discreteXValues() const
Get a list of all of the x-bin center values for this scatter plot.
int numberOfBins() const
Get the total number of bins (bin count in x * bin count in y).
virtual double value(double x, double y) const
This gets called every time the scatter plot is re-drawn.
void clearAlarms()
Forget all alarmed bins (viewport->plot).
QScopedPointer< QMap< int, bool > > m_alarmedBins
map from bin index to alarm state (true for alarmed)
void swap(ScatterPlotData &other)
This is part of the copy-and-swap paradigm.
int lineCount() const
Definition: Cube.cpp:1379
QScopedPointer< Stretch > m_yDnToBinStretch
Stretch 2.
Isis exception class.
Definition: IException.h:107
QPair< int, int > binXYIndices(int binIndex) const
Get the 2D index index position given a 1D (flat) index position.
virtual QwtRasterData * copy() const
Returns a copy of the ScatterPlotData object.
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
int binIndex(int xIndex, int yIndex) const
Get the single-index position given an x/y index position.
IO Handler for Isis Cubes.
Definition: Cube.h:170
double m_xCubeMin
The minimum DN value for the x cube.