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