Isis 3 Programmer Reference
HistogramTool.cpp
1 #include "HistogramTool.h"
2 
3 #include <geos/geom/Point.h>
4 
5 #include <QDebug>
6 #include <QDockWidget>
7 #include <QHBoxLayout>
8 #include <QLabel>
9 #include <QMessageBox>
10 #include <QVBoxLayout>
11 
12 #include "Brick.h"
13 #include "CubePlotCurve.h"
14 #include "ImageHistogram.h"
15 #include "Histogram.h"
16 #include "HistogramItem.h"
17 #include "HistogramPlotWindow.h"
18 #include "MdiCubeViewport.h"
19 #include "PolygonTools.h"
20 #include "RubberBandComboBox.h"
21 #include "ToolPad.h"
22 
23 
24 namespace Isis {
25 
32  m_action = new QAction(this);
33  m_action->setText("Histogram Tool");
34  m_action->setIcon(QPixmap(toolIconDir() + "/histogram.png"));
35  }
36 
37 
38 
46  if(m_rubberBandCombo) {
47  m_rubberBandCombo->reset();
48  m_rubberBandCombo->setEnabled(true);
49  rubberBandTool()->setDrawActiveViewportOnly(true);
50  }
51  }
52 
61  QAction *action = new QAction(toolpad);
62  action->setIcon(QPixmap(toolIconDir() + "/histogram.png"));
63  action->setToolTip("Histogram (H)");
64  action->setShortcut(Qt::Key_H);
65 
66  QString text =
67  "<b>Function:</b> Plot histogram in active viewport \
68  <p><b>Shortcut:</b> H</p> ";
69  action->setWhatsThis(text);
70  return action;
71  }
72 
73 
82  QWidget *HistogramTool::createToolBarWidget(QStackedWidget *parent) {
83  QWidget *wrapper = new QWidget;
84 
89  );
90 
91  QWidget *abstractToolWidgets =
93 
94  QHBoxLayout *layout = new QHBoxLayout(wrapper);
95  layout->setMargin(0);
96  layout->addWidget(m_rubberBandCombo);
97  layout->addWidget(abstractToolWidgets);
98  layout->addStretch(1);
99  wrapper->setLayout(layout);
100 
101  return wrapper;
102  }
103 
104 
109  m_frequencyItem = NULL;
110  m_percentageCurve = NULL;
111  }
112 
113 
120  }
121 
122 
128  PlotWindow *window = new HistogramPlotWindow(
129  "Histogram " + PlotWindow::defaultWindowTitle(),
130  qobject_cast<QWidget *>(parent()));
131  return window;
132  }
133 
134 
142  if (selectedWindow()) {
143  selectedWindow()->raise();
144  }
145 
146  if(rubberBandTool()->isValid()) {
147  if (cubeViewport()->isGray()) {
148  refreshPlot();
149  }
150  else {
151  QMessageBox::information(NULL, "Error",
152  "Cannot create histogram on colored viewport",
153  QMessageBox::Ok);
154  }
155  }
156  else {
157  QMessageBox::information(NULL, "Error",
158  "The selected Area contains no valid pixels",
159  QMessageBox::Ok);
160  }
161  }
162 
163 
168  MdiCubeViewport *activeViewport = cubeViewport();
169 
170  if (activeViewport && rubberBandTool()->isValid()) {
171  HistogramPlotWindow *targetWindow = qobject_cast<HistogramPlotWindow *>(
172  selectedWindow(true));
173 
174  QList<QPoint> vertices;
175 
176  if(rubberBandTool()->currentMode() == RubberBandTool::CircleMode) {
177  geos::geom::Geometry *p = rubberBandTool()->geometry();
178  geos::geom::CoordinateSequence *c = p->getCoordinates();
179  for(int i = 0; i < (int)c->getSize(); i++) {
180  QPoint point((int)(c->getX(i) + 0.5), (int)(c->getY(i) + 0.5));
181  vertices.append(point);
182  }
183  delete p;
184  }
185  else {
186  vertices = rubberBandTool()->vertices();
187  }
188 
189  if(vertices.size() < 1) return;
190 
191  Cube *cube = activeViewport->cube();
192  int band = activeViewport->grayBand();
193  ImageHistogram hist(*cube, band);
194 
195  //If the rubber band is a line
196  if (rubberBandTool()->currentMode() == RubberBandTool::LineMode) {
197  double ssamp, sline, esamp, eline;
198  activeViewport->viewportToCube(vertices[0].rx(), vertices[0].ry(),
199  ssamp, sline);
200 
201  activeViewport->viewportToCube(vertices[1].rx(), vertices[1].ry(),
202  esamp, eline);
203 
204  QLine line((int)ssamp, (int)sline, (int)esamp, (int)eline);
205 
206  double slope;
207  int i;
208  int x, y, xinc, yinc;
209  int xsize, ysize;
210 
211  //Get all of the points out of the line
212  QList<QPoint *> *linePts = new QList<QPoint *>;
213 
214  int sx = line.p1().x();
215  int ex = line.p2().x();
216  int sy = line.p1().y();
217  int ey = line.p2().y();
218  if(sx > ex) {
219  xsize = sx - ex + 1;
220  xinc = -1;
221  }
222  else {
223  xsize = ex - sx + 1;
224  xinc = 1;
225  }
226 
227  if(sy > ey) {
228  ysize = sy - ey + 1;
229  yinc = -1;
230  }
231  else {
232  ysize = ey - sy + 1;
233  yinc = 1;
234  }
235 
236  if(ysize > xsize) {
237  slope = (double)(ex - sx) / (double)(ey - sy);
238  y = sy;
239  for(i = 0; i < ysize; i++) {
240  x = (int)(slope * (double)(y - sy) + (double) sx + 0.5);
241 
242  QPoint *pt = new QPoint;
243  pt->setX(x);
244  pt->setY(y);
245  linePts->push_back(pt);
246  y += yinc;
247  }
248  }
249  else if(xsize == 1) {
250  QPoint *pt = new QPoint;
251  pt->setX(sx);
252  pt->setY(sy);
253  linePts->push_back(pt);
254  }
255  else {
256  slope = (double)(ey - sy) / (double)(ex - sx);
257  x = sx;
258  for(i = 0; i < xsize; i++) {
259  y = (int)(slope * (double)(x - sx) + (double) sy + 0.5);
260 
261  QPoint *pt = new QPoint;
262  pt->setX(x);
263  pt->setY(y);
264  linePts->push_back(pt);
265  x += xinc;
266  }
267  }
268 
269  if(linePts->empty()) {
270  QMessageBox::information((QWidget *)parent(),
271  "Error", "No points in edit line");
272  return;
273  }
274 
275  Brick *brick = new Brick(*cube, 1, 1, 1);
276 
277  //For each point read that value from the cube and add it to the histogram
278  for(int i = 0; linePts && i < (int)linePts->size(); i++) {
279  QPoint *pt = (*linePts)[i];
280  int is = pt->x();
281  int il = pt->y();
282  brick->SetBasePosition(is, il, band);
283  cube->read(*brick);
284  hist.AddData(brick->DoubleBuffer(), 1);
285  }
286  delete brick;
287 
288  delete linePts;
289 
290  }
291  //If rubber band is a rectangle
292  else if(rubberBandTool()->currentMode() == RubberBandTool::RectangleMode) {
293  double ssamp, sline, esamp, eline;
294 
295  // Convert vertices to line sample values
296  activeViewport->viewportToCube(vertices[0].x(), vertices[0].y(),
297  ssamp, sline);
298 
299  activeViewport->viewportToCube(vertices[2].x(), vertices[2].y(),
300  esamp, eline);
301 
302  ssamp = round(ssamp);
303  sline = round(sline);
304  esamp = round(esamp);
305  eline = round(eline);
306 
307  int nsamps = (int)(std::fabs(esamp - ssamp) + 1);
308 
309  Brick *brick = new Brick(*cube, nsamps, 1, 1);
310 
311  //For each line read nsamps and add it to the histogram
312  for(int line = (int)std::min(sline, eline); line <= (int)std::max(sline, eline); line++) {
313  int isamp = std::min(ssamp,esamp);
314  brick->SetBasePosition(isamp, line, band);
315  cube->read(*brick);
316  hist.AddData(brick->DoubleBuffer(), nsamps);
317  }
318  delete brick;
319  }
320  //If rubber band is a polygon or circle
321  else {
322  geos::geom::Geometry *polygon = rubberBandTool()->geometry();
323 
324  std::vector <int> x_contained, y_contained;
325  if(polygon != NULL) {
326  const geos::geom::Envelope *envelope = polygon->getEnvelopeInternal();
327  double ssamp, esamp, sline, eline;
328  activeViewport->viewportToCube((int)floor(envelope->getMinX()),
329  (int)floor(envelope->getMinY()),
330  ssamp, sline);
331  activeViewport->viewportToCube((int)ceil(envelope->getMaxX()),
332  (int)ceil(envelope->getMaxY()),
333  esamp, eline);
334 
335 
336  for(int y = (int)sline; y <= (int)eline; y++) {
337  for(int x = (int)ssamp; x <= (int)esamp; x++) {
338  int x1, y1;
339  activeViewport->cubeToViewport(x, y, x1, y1);
340  geos::geom::Coordinate c(x1, y1);
341  geos::geom::Point *p = globalFactory->createPoint(c);
342  bool contains = p->within(polygon);
343  delete p;
344 
345  if(contains) {
346  x_contained.push_back(x);
347  y_contained.push_back(y);
348  }
349  }
350  }
351 
352  delete polygon;
353 
354  Brick *brick = new Brick(*cube, 1, 1, 1);
355 
356  //Read each point from the cube and add it to the histogram
357  for(unsigned int j = 0; j < x_contained.size(); j++) {
358  brick->SetBasePosition(x_contained[j], y_contained[j], band);
359  cube->read(*brick);
360  hist.AddData(brick->DoubleBuffer(), 1);
361  }
362  delete brick;
363  }
364  }
365 
366 
367  //Transfer data from histogram to the plotcurve
368  QVector<QPointF> binCountData;
369  QVector<QPointF> cumPctData;
370  double cumpct = 0.0;
371  for(int i = 0; i < hist.Bins(); i++) {
372  if(hist.BinCount(i) > 0) {
373  binCountData.append(QPointF(hist.BinMiddle(i), hist.BinCount(i)));
374 
375  double pct = (double)hist.BinCount(i) / hist.ValidPixels() * 100.;
376  cumpct += pct;
377  cumPctData.append(QPointF(hist.BinMiddle(i), cumpct));
378  }
379  }
380 
381  //p_histCurve->setData(&xarray[0],&yarray[0],xarray.size());
382 
383 
384  //These are all variables needed in the following for loop.
385  //----------------------------------------------
386  QVector<QwtIntervalSample> intervals(binCountData.size());
387  double maxYValue = DBL_MIN;
388  double minYValue = DBL_MAX;
389  // ---------------------------------------------
390 
391  for(int y = 0; y < binCountData.size(); y++) {
392  intervals[y].interval = QwtInterval(binCountData[y].x(), binCountData[y].x() + hist.BinSize());
393 
394  intervals[y].value = binCountData[y].y();
395  if(binCountData[y].y() > maxYValue) maxYValue = binCountData[y].y();
396  if(binCountData[y].y() < minYValue) minYValue = binCountData[y].y();
397  }
398 
399  if (binCountData.size()) {
401  m_frequencyItem->setData(QwtIntervalSeriesData(intervals));
402 // m_frequencyItem->setSource(activeViewport, vertices);
403  m_percentageCurve->setData(new QwtPointSeriesData(cumPctData));
404  m_percentageCurve->setSource(activeViewport, vertices);
405  }
406 
407 
408  QLabel *label = new QLabel(" Average = " + QString::number(hist.Average()) + '\n' +
409  "\n Minimum = " + QString::number(hist.Minimum()) + '\n' +
410  "\n Maximum = " + QString::number(hist.Maximum()) + '\n' +
411  "\n Stand. Dev.= " + QString::number(hist.StandardDeviation()) + '\n' +
412  "\n Variance = " + QString::number(hist.Variance()) + '\n' +
413  "\n Median = " + QString::number(hist.Median()) + '\n' +
414  "\n Mode = " + QString::number(hist.Mode()) + '\n' +
415  "\n Skew = " + QString::number(hist.Skew()), targetWindow);
416 
417 
418  QVBoxLayout *dockLayout = new QVBoxLayout;
419  dockLayout->addWidget(label);
420  dockLayout->addStretch();
421 
422  QWidget *dockContents = new QWidget;
423  dockContents->setLayout(dockLayout);
424  targetWindow->getDockWidget()->setWidget(dockContents);
425  targetWindow->replot();
426  }
427  }
428 
429 
438  HistogramPlotWindow *targetWindow = qobject_cast<HistogramPlotWindow *>(
439  selectedWindow());
440 
441  if (targetWindow) {
442  if (!m_frequencyItem) {
444  m_frequencyItem->setYAxis(QwtPlot::yRight);
445  m_frequencyItem->setColor(Qt::darkCyan);
446  m_frequencyItem->setTitle("Frequency");
447  targetWindow->add(m_frequencyItem);
448  }
449 
450  QPen percentagePen(Qt::red);
451  percentagePen.setWidth(2);
452 
453  if (!m_percentageCurve) {
454  m_percentageCurve = createCurve("Percentage", percentagePen,
456  m_percentageCurve->setMarkerSymbol(QwtSymbol::NoSymbol);
457  targetWindow->add(m_percentageCurve);
458  }
459  }
460  }
461 }
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::AbstractPlotTool::updateTool
virtual void updateTool()
This forwards all update calls to the plot windows.
Definition: AbstractPlotTool.cpp:118
Isis::HistogramTool::HistogramTool
HistogramTool(QWidget *parent)
Constructor creates a new HistogramTool object.
Definition: HistogramTool.cpp:31
Isis::MdiCubeViewport
Cube display widget for certain Isis MDI applications.
Definition: MdiCubeViewport.h:39
QWidget
Isis::PlotCurve::CubeDN
@ CubeDN
The data is a Cube DN value.
Definition: PlotCurve.h:67
Isis::RubberBandComboBox
Combo box for choosing a rubber band type.
Definition: RubberBandComboBox.h:26
Isis::ImageHistogram::AddData
virtual void AddData(const double *data, const unsigned int count)
Add an array of doubles to the histogram counters.
Definition: ImageHistogram.cpp:228
Isis::RubberBandTool::setDrawActiveViewportOnly
void setDrawActiveViewportOnly(bool activeOnly=false)
This called to set whether rubber band is drawn on active viewport only rather than all linked viewpo...
Definition: RubberBandTool.cpp:333
Isis::AbstractPlotTool::createCurve
static CubePlotCurve * createCurve(QString name, QPen pen, PlotCurve::Units xUnits, PlotCurve::Units yUnits)
This is a helper method for children.
Definition: AbstractPlotTool.cpp:233
QList< QPoint >
Isis::HistogramPlotWindow::add
void add(HistogramItem *)
Add a HistogramItem to the plot.
Definition: HistogramPlotWindow.cpp:60
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::Histogram::BinSize
double BinSize() const
Returns the size of an individual bin.
Definition: Histogram.cpp:470
Isis::Buffer::DoubleBuffer
double * DoubleBuffer() const
Returns the value of the shape buffer.
Definition: Buffer.h:138
Isis::HistogramPlotWindow
Definition: HistogramPlotWindow.h:16
Isis::Tool::toolIconDir
QString toolIconDir() const
returns the path to the icon directory.
Definition: Tool.h:113
Isis::HistogramTool::m_action
QAction * m_action
This is the action that activates this tool.
Definition: HistogramTool.h:70
Isis::HistogramTool::validatePlotCurves
void validatePlotCurves()
This method sets up the names, line style, and color of the all the plot items that will be used in t...
Definition: HistogramTool.cpp:437
Isis::Statistics::Maximum
double Maximum() const
Returns the absolute maximum double found in all data passed through the AddData method.
Definition: Statistics.cpp:403
Isis::Histogram::BinMiddle
double BinMiddle(const int index) const
Returns the value represented by a bin.
Definition: Histogram.cpp:449
Isis::Histogram::Skew
double Skew() const
Computes and returns the skew.
Definition: Histogram.cpp:384
Isis::HistogramTool::m_rubberBandCombo
QPointer< RubberBandComboBox > m_rubberBandCombo
This combo box is for various rubber band selection types.
Definition: HistogramTool.h:72
Isis::RubberBandComboBox::Line
@ Line
Line.
Definition: RubberBandComboBox.h:42
Isis::RubberBandComboBox::Rectangle
@ Rectangle
Rectangle.
Definition: RubberBandComboBox.h:39
Isis::HistogramTool::toolPadAction
QAction * toolPadAction(ToolPad *pad)
This method adds the histogram tool to the tool pad.
Definition: HistogramTool.cpp:60
Isis::PlotWindow::defaultWindowTitle
static QString defaultWindowTitle()
This is the typical suffix for plot windows, it's here in case we want to update all plot windows to ...
Definition: PlotWindow.cpp:1810
Isis::AbstractPlotTool::selectedWindow
PlotWindow * selectedWindow(bool createIfNeeded=true)
Get the 'active' plot window (the window selected by the user to contain new curves).
Definition: AbstractPlotTool.cpp:256
Isis::Statistics::ValidPixels
BigInt ValidPixels() const
Returns the total number of valid pixels processed.
Definition: Statistics.cpp:433
Isis::Brick
Buffer for containing a three dimensional section of an image.
Definition: Brick.h:45
Isis::HistogramTool::updateTool
void updateTool()
This method updates the histogram tool.
Definition: HistogramTool.cpp:118
Isis::HistogramItem
This is the (qwt) plot item for a histogram.
Definition: HistogramItem.h:24
Isis::Histogram::BinCount
BigInt BinCount(const int index) const
Returns the count at a bin position in the histogram.
Definition: Histogram.cpp:403
Isis::Statistics::Variance
double Variance() const
Computes and returns the variance.
Definition: Statistics.cpp:328
Isis::CubeViewport::cubeToViewport
void cubeToViewport(double sample, double line, int &x, int &y) const
Turns a cube into a viewport.
Definition: CubeViewport.cpp:852
Isis::CubeViewport::grayBand
int grayBand() const
Definition: CubeViewport.h:194
Isis::HistogramTool::createToolBarWidget
QWidget * createToolBarWidget(QStackedWidget *parent)
This method creates the widgets for the tool bar.
Definition: HistogramTool.cpp:82
Isis::PlotCurve::Percentage
@ Percentage
The data is a percentage (0-100).
Definition: PlotCurve.h:75
Isis::HistogramTool::rubberBandComplete
void rubberBandComplete()
Called when the user has finished drawing with the rubber band.
Definition: HistogramTool.cpp:141
Isis::Statistics::StandardDeviation
double StandardDeviation() const
Computes and returns the standard deviation.
Definition: Statistics.cpp:312
Isis::Statistics::Minimum
double Minimum() const
Returns the absolute minimum double found in all data passed through the AddData method.
Definition: Statistics.cpp:382
Isis::Histogram::Mode
double Mode() const
Returns the mode.
Definition: Histogram.cpp:328
Isis::ImageHistogram
Container of a cube histogram.
Definition: ImageHistogram.h:40
Isis::HistogramTool::m_percentageCurve
QPointer< CubePlotCurve > m_percentageCurve
This plot curve indicates the data percentage over the histogram.
Definition: HistogramTool.h:68
Isis::HistogramTool::createWindow
PlotWindow * createWindow()
This method creates the default histogram plot window.
Definition: HistogramTool.cpp:127
Isis::HistogramTool::detachCurves
void detachCurves()
Forget the frequency histogram item and the percentage curve.
Definition: HistogramTool.cpp:108
Isis::Cube
IO Handler for Isis Cubes.
Definition: Cube.h:167
Isis::AbstractPlotTool
Parent class for plotting tools which provides common functionality.
Definition: AbstractPlotTool.h:43
Isis::Statistics::Average
double Average() const
Computes and returns the average.
Definition: Statistics.cpp:300
Isis::ToolPad
Definition: ToolPad.h:14
Isis::Histogram::Bins
int Bins() const
Returns the number of bins in the histogram.
Definition: Histogram.cpp:483
Isis::Histogram::Median
double Median() const
Returns the median.
Definition: Histogram.cpp:319
Isis::RubberBandTool::geometry
geos::geom::Geometry * geometry()
Definition: RubberBandTool.cpp:823
Isis::CubeViewport::viewportToCube
void viewportToCube(int x, int y, double &sample, double &line) const
Turns a viewport into a cube.
Definition: CubeViewport.cpp:815
Isis::HistogramTool::m_frequencyItem
QPointer< HistogramItem > m_frequencyItem
This is the qwt plot item which draws the histogram frequency bars.
Definition: HistogramTool.h:66
QVector
This is free and unencumbered software released into the public domain.
Definition: Calculator.h:18
Isis::PlotWindow::replot
void replot()
Reset the scale of the plot, replot it and emit plot changed.
Definition: PlotWindow.cpp:1797
Isis::HistogramTool::refreshPlot
void refreshPlot()
This method plots the selected data in a histogram window.
Definition: HistogramTool.cpp:167
Isis::PlotWindow
Definition: PlotWindow.h:88
Isis::HistogramTool::enableRubberBandTool
void enableRubberBandTool()
This method is called when the tool is activated by the parent, or when the plot mode is changed.
Definition: HistogramTool.cpp:45
QAction
Isis::CubeViewport::cube
Cube * cube() const
Definition: CubeViewport.h:338
Isis::AbstractPlotTool::createToolBarWidget
QWidget * createToolBarWidget(QStackedWidget *parent)
This provides the standard plot tool options, such as selecting an active plot window.
Definition: AbstractPlotTool.cpp:103
Isis::Tool::cubeViewport
MdiCubeViewport * cubeViewport() const
Return the current cubeviewport.
Definition: Tool.h:197
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::RubberBandTool::vertices
QList< QPoint > vertices()
This method returns the vertices.
Definition: RubberBandTool.cpp:672