USGS

Isis 3.0 Object Programmers' Reference

Home

ScatterPlotData.cpp

00001 #include "IsisDebug.h"
00002 #include "ScatterPlotData.h"
00003 
00004 #include <algorithm>
00005 
00006 #include <qwt_double_range.h>
00007 
00008 #include <QtCore>
00009 
00010 #include "Brick.h"
00011 #include "SpecialPixel.h"
00012 
00013 namespace Isis {
00028   ScatterPlotData::ScatterPlotData(
00029       Cube *xCube, int xCubeBand, int xBinCount,
00030       Cube *yCube, int yCubeBand, int yBinCount,
00031       QwtInterval sampleRange, QwtInterval lineRange) : QwtRasterData(),
00032       m_xDnToBinStretch(new Stretch), m_yDnToBinStretch(new Stretch),
00033       m_counts(
00034         new QVector< QVector<int> >(yBinCount, QVector<int>(xBinCount))),
00035       m_alarmedBins(new QMap<int, bool>) {
00036     int startLine = qRound(lineRange.minValue());
00037     int endLine = qRound(lineRange.maxValue());
00038     ASSERT(xCube->lineCount() == yCube->lineCount());
00039 
00040     Histogram *xCubeHist = new Histogram(*xCube, xCubeBand, NULL,
00041         sampleRange.minValue(), lineRange.minValue(),
00042         sampleRange.maxValue(), lineRange.maxValue(),
00043         xBinCount, true);
00044     m_xCubeMin = xCubeHist->Minimum();
00045     m_xCubeMax = xCubeHist->Maximum();
00046 
00047 
00048     Histogram *yCubeHist = new Histogram(*yCube, yCubeBand, NULL,
00049         sampleRange.minValue(), lineRange.minValue(),
00050         sampleRange.maxValue(), lineRange.maxValue(),
00051         yBinCount, true);
00052     m_yCubeMin = yCubeHist->Minimum();
00053     m_yCubeMax = yCubeHist->Maximum();
00054 
00055 
00056     m_xDnToBinStretch->AddPair(m_xCubeMin, 0);
00057     m_xDnToBinStretch->AddPair(m_xCubeMax, xBinCount - 1);
00058 
00059     m_yDnToBinStretch->AddPair(m_yCubeMin, 0);
00060     m_yDnToBinStretch->AddPair(m_yCubeMax, yBinCount - 1);
00061 
00062     m_maxCount = 0;
00063 
00064     Brick brick1((int)(sampleRange.maxValue() - sampleRange.minValue() + 1),
00065                  1, 1, xCube->pixelType());
00066     Brick brick2((int)(sampleRange.maxValue() - sampleRange.minValue() + 1),
00067                  1, 1, yCube->pixelType());
00068     ASSERT(xCube->sampleCount() == yCube->sampleCount());
00069     ASSERT(brick1.size() == brick2.size());
00070 
00071     for (int line = startLine; line <= endLine; line++) {
00072       brick1.SetBasePosition(qRound(sampleRange.minValue()), line, xCubeBand);
00073       xCube->read(brick1);
00074 
00075       brick2.SetBasePosition(qRound(sampleRange.minValue()), line, yCubeBand);
00076       yCube->read(brick2);
00077 
00078       for (int i = 0; i < brick1.size(); i++) {
00079         double xDn = brick1[i];
00080         double yDn = brick2[i];
00081 
00082         if (!IsSpecial(xDn) && !IsSpecial(yDn)) {
00083           double x = m_xDnToBinStretch->Map(xDn);
00084           double y = m_yDnToBinStretch->Map(yDn);
00085 
00086           if (!IsSpecial(x) && !IsSpecial(y)) {
00087             int roundedX = qRound(x);
00088             int roundedY = qRound(y);
00089 
00090             if (roundedX >= 0 && roundedX < xBinCount &&
00091                 roundedY >= 0 && roundedY < yBinCount) {
00092               int value = (*m_counts)[roundedY][roundedX] + 1;
00093               (*m_counts)[roundedY][roundedX] = value;
00094 
00095               m_maxCount = qMax(m_maxCount, value);
00096             }
00097           }
00098         }
00099       }
00100     }
00101 
00102     setInterval(Qt::XAxis, QwtInterval(m_xCubeMin, m_xCubeMax));
00103     setInterval(Qt::YAxis, QwtInterval(m_yCubeMin, m_yCubeMax));
00104     setInterval(Qt::ZAxis, QwtInterval(0, m_maxCount));
00105   }
00106 
00107 
00114   ScatterPlotData::ScatterPlotData(const ScatterPlotData &other) {
00115     m_xDnToBinStretch.reset(new Stretch(*other.m_xDnToBinStretch));
00116     m_yDnToBinStretch.reset(new Stretch(*other.m_yDnToBinStretch));
00117     m_counts.reset(new QVector< QVector<int> >(*other.m_counts));
00118     m_alarmedBins.reset(new QMap< int, bool>(*other.m_alarmedBins));
00119     m_maxCount = other.m_maxCount;
00120     m_xCubeMin = other.m_xCubeMin;
00121     m_xCubeMax = other.m_xCubeMax;
00122     m_yCubeMin = other.m_yCubeMin;
00123     m_yCubeMax = other.m_yCubeMax;
00124   }
00125 
00126 
00131   ScatterPlotData::~ScatterPlotData() {
00132   }
00133 
00134 
00140   QwtRasterData *ScatterPlotData::copy() const {
00141     return new ScatterPlotData(*this);
00142   }
00143 
00144 
00154   double ScatterPlotData::value(double x, double y) const {
00155     double value = 0;
00156 
00157     QPair<int, int> indices = binXYIndices(x, y);
00158     int index = binIndex(indices.first, indices.second);
00159 
00160     if (index != -1 && (*m_alarmedBins)[index])
00161       value = m_maxCount;
00162     else
00163       value = binCount(indices.first, indices.second);
00164 
00165     return value;
00166   }
00167 
00168 
00174   double ScatterPlotData::xCubeMin() const {
00175     return m_xCubeMin;
00176   }
00177 
00178 
00184   double ScatterPlotData::xCubeMax() const {
00185     return m_xCubeMax;
00186   }
00187 
00188 
00194   double ScatterPlotData::yCubeMin() const {
00195     return m_yCubeMin;
00196   }
00197 
00198 
00204   double ScatterPlotData::yCubeMax() const {
00205     return m_yCubeMax;
00206   }
00207 
00208 
00214   void ScatterPlotData::swap(ScatterPlotData &other) {
00215     m_xDnToBinStretch.swap(other.m_xDnToBinStretch);
00216     m_yDnToBinStretch.swap(other.m_yDnToBinStretch);
00217     m_counts.swap(other.m_counts);
00218     m_alarmedBins.swap(other.m_alarmedBins);
00219     std::swap(m_maxCount, other.m_maxCount);
00220     std::swap(m_xCubeMin, other.m_xCubeMin);
00221     std::swap(m_xCubeMax, other.m_xCubeMax);
00222     std::swap(m_yCubeMin, other.m_yCubeMin);
00223     std::swap(m_yCubeMax, other.m_yCubeMax);
00224   }
00225 
00226 
00234   QPair<double, double> ScatterPlotData::binXY(int index) const {
00235     QPair<int, int> indices = binXYIndices(index);
00236     int xIndex = indices.first;
00237     int yIndex = indices.second;
00238 
00239     if (xIndex != -1 && yIndex != -1) {
00240       int xSize = 0;
00241       int ySize = m_counts->size();
00242 
00243       // Assume square 2D structurs
00244       if (ySize > 0)
00245         xSize = (*m_counts)[0].size();
00246 
00247       double percentAcrossXRange = ((double)xIndex / (double)xSize);
00248       double xDnValue = m_xCubeMin +
00249           percentAcrossXRange * (m_xCubeMax - m_xCubeMin);
00250 
00251       double percentAcrossYRange = ((double)yIndex / (double)ySize);
00252       double yDnValue = m_yCubeMin +
00253           percentAcrossYRange * (m_yCubeMax - m_yCubeMin);
00254 
00255       return QPair<double, double>(xDnValue, yDnValue);
00256     }
00257 
00258 
00259     IString msg = "Bin at index [" + IString(index) + "] not found. "
00260                   "There are [" + IString(numberOfBins()) + "] bins";
00261     throw IException(IException::Programmer, msg, _FILEINFO_);
00262   }
00263 
00264 
00271   int ScatterPlotData::binCount(int binIndex) const {
00272     QPair<int, int> indices = binXYIndices(binIndex);
00273     return binCount(indices.first, indices.second);
00274   }
00275 
00276 
00282   int ScatterPlotData::numberOfBins() const {
00283     int xSize = 0;
00284     int ySize = m_counts->size();
00285 
00286     // Assume square 2D structurs
00287     if (ySize > 0)
00288       xSize = (*m_counts)[0].size();
00289 
00290     return xSize * ySize;
00291   }
00292 
00293 
00299   QVector<double> ScatterPlotData::discreteXValues() const {
00300     QVector<double> xValues;
00301 
00302     int ySize = m_counts->size();
00303     if (ySize) {
00304       int xSize = (*m_counts)[0].size();
00305       xValues.resize(xSize);
00306 
00307       for (int xIndex = 0; xIndex < xSize; xIndex++) {
00308         double percentAcrossXRange = ((double)xIndex / (double)xSize);
00309         xValues[xIndex] = m_xCubeMin +
00310             percentAcrossXRange * (m_xCubeMax - m_xCubeMin);
00311       }
00312     }
00313 
00314     return xValues;
00315   }
00316 
00317 
00325   void ScatterPlotData::alarm(double x, double y) {
00326     int binToAlarm = binIndex(x, y);
00327     if (binToAlarm != -1)
00328       (*m_alarmedBins)[binToAlarm] = true;
00329   }
00330 
00331 
00335   void ScatterPlotData::clearAlarms() {
00336     m_alarmedBins->clear();
00337   }
00338 
00339 
00346   QRectF ScatterPlotData::pixelHint(const QRectF &area) const {
00347     QRectF hint;
00348 
00349     if (m_xDnToBinStretch->Pairs() > 1 && m_yDnToBinStretch->Pairs() > 1) {
00350       hint = QRectF(
00351           QPointF(m_xCubeMin, m_yCubeMin),
00352           QSizeF(m_xDnToBinStretch->Input(1) - m_xDnToBinStretch->Input(0),
00353                  m_yDnToBinStretch->Input(1) - m_yDnToBinStretch->Input(1)));
00354     }
00355 
00356     return hint;
00357   }
00358 
00359 
00367   ScatterPlotData &ScatterPlotData::operator=(const ScatterPlotData &other) {
00368     ScatterPlotData tmp(other);
00369 
00370     swap(tmp);
00371 
00372     return *this;
00373   }
00374 
00375 
00383   int ScatterPlotData::binCount(int xIndex, int yIndex) const {
00384     int count = 0;
00385 
00386     if (yIndex >= 0 && yIndex < m_counts->size()) {
00387       if (xIndex >= 0 && xIndex < (*m_counts)[yIndex].size()) {
00388         count = (*m_counts)[yIndex][xIndex];
00389       }
00390     }
00391 
00392     return count;
00393   }
00394 
00395 
00404   int ScatterPlotData::binIndex(int xIndex, int yIndex) const {
00405     int xSize = 0;
00406     int ySize = m_counts->size();
00407 
00408     // Assume square 2D structurs
00409     if (ySize > 0)
00410       xSize = (*m_counts)[0].size();
00411 
00412     int index = -1;
00413     if ((xIndex >= 0 && xIndex < xSize) && (yIndex >= 0 && yIndex < ySize))
00414       index = xSize * yIndex + xIndex;
00415 
00416     return index;
00417   }
00418 
00419 
00427   int ScatterPlotData::binIndex(double x, double y) const {
00428     QPair<int, int> indices = binXYIndices(x, y);
00429     return binIndex(indices.first, indices.second);
00430   }
00431 
00432 
00439   QPair<int, int> ScatterPlotData::binXYIndices(int binIndex) const {
00440     int xSize = 0;
00441     int ySize = m_counts->size();
00442 
00443     // Assume square 2D structurs
00444     if (ySize > 0)
00445       xSize = (*m_counts)[0].size();
00446 
00447     int yIndex = (binIndex / xSize);
00448     binIndex -= yIndex * xSize;
00449 
00450     int xIndex = binIndex;
00451 
00452     if (xIndex < 0 || yIndex < 0 || xIndex >= xSize || yIndex >= ySize) {
00453       IString msg = "Bin at index [" + IString(binIndex) + "] not found. "
00454                     "There are [" + IString(numberOfBins()) + "] bins";
00455       throw IException(IException::Programmer, msg, _FILEINFO_);
00456     }
00457 
00458     return QPair<int, int>(xIndex, yIndex);
00459   }
00460 
00461 
00469   QPair<int, int> ScatterPlotData::binXYIndices(double x, double y) const {
00470     QPair<int, int> indices(-1, -1);
00471 
00472     if (m_counts->size() && m_counts->at(0).size()) {
00473       double xBinPosition = m_xDnToBinStretch->Map(x);
00474       double yBinPosition = m_yDnToBinStretch->Map(y);
00475 
00476       if (!IsSpecial(xBinPosition) && !IsSpecial(yBinPosition)) {
00477         int discreteXBin = qRound(xBinPosition);
00478         int discreteYBin = qRound(yBinPosition);
00479 
00480         if (discreteXBin >= 0 && discreteXBin < m_counts->at(0).size() &&
00481             discreteYBin >= 0 && discreteYBin < m_counts->size()) {
00482           indices = QPair<int, int>(discreteXBin, discreteYBin);
00483         }
00484       }
00485     }
00486 
00487     return indices;
00488   }
00489 }
00490