All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
MixtureModelWizardPage.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2011-2012 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/qt/widgets/rp/MixtureModelWizardPage.cpp
22 
23  \brief This file defines a class for a Mixture Model Wizard page.
24 */
25 
26 // TerraLib
27 #include "../../../common/STLUtils.h"
28 #include "../../../dataaccess/dataset/DataSet.h"
29 #include "../../../dataaccess/utils/Utils.h"
30 #include "../../../geometry/Point.h"
31 #include "../../../maptools/MarkRendererManager.h"
32 #include "../../../raster/Raster.h"
33 #include "../../../rp/MixtureModel.h"
34 #include "../../../rp/MixtureModelLinearStrategy.h"
35 #include "../../../rp/MixtureModelPCAStrategy.h"
36 #include "../../../rp/Functions.h"
37 #include "../../../se/Fill.h"
38 #include "../../../se/Mark.h"
39 #include "../../../se/Stroke.h"
40 #include "../../../se/Utils.h"
41 #include "../canvas/Canvas.h"
42 #include "../canvas/MapDisplay.h"
43 #include "MixtureModelWizardPage.h"
44 #include "RasterNavigatorWidget.h"
45 #include "RasterNavigatorDialog.h"
46 #include "ui_MixtureModelWizardPageForm.h"
47 
48 // Qt
49 #include <QGridLayout>
50 
51 // Boost
52 #include <boost/uuid/random_generator.hpp>
53 #include <boost/uuid/uuid_io.hpp>
54 
55 //STL
56 #include <memory>
57 
58 #define PATTERN_SIZE 12
59 
61  : QWizardPage(parent),
62  m_ui(new Ui::MixtureModelWizardPageForm),
63  m_countComponents(0),
64  m_layer(0)
65 {
66 // setup controls
67  m_ui->setupUi(this);
68 
70 
71 //define mark
72  te::se::Stroke* stroke = te::se::CreateStroke("#000000", "1");
73  te::se::Fill* fill = te::se::CreateFill("#FF0000", "1.0");
74  m_mark = te::se::CreateMark("cross", stroke, fill);
75 
77 
78 //connects
79  connect(m_ui->m_tableWidget, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(onItemChanged(QTableWidgetItem*)));
80  connect(m_ui->m_removeToolButton, SIGNAL(clicked()), this, SLOT(onRemoveToolButtonClicked()));
81  connect(m_ui->m_acquireToolButton, SIGNAL(toggled(bool)), this, SLOT(showNavigator(bool)));
82 
83 
84  //configure raster navigator
85  m_navigatorDlg.reset(new te::qt::widgets::RasterNavigatorDialog(this, Qt::Tool));
86  m_navigatorDlg->setWindowTitle(tr("Display"));
87  m_navigatorDlg->setMinimumSize(550, 400);
88  m_navigatorDlg->getWidget()->hideGeomTool(true);
89  m_navigatorDlg->getWidget()->hideInfoTool(true);
90  m_navigatorDlg->getWidget()->hideBoxTool(true);
91 
92  //connects
93  connect(m_navigatorDlg.get(), SIGNAL(navigatorClosed()), this, SLOT(onNavigatorClosed()));
94  connect(m_navigatorDlg->getWidget(), SIGNAL(mapDisplayExtentChanged()), this, SLOT(onMapDisplayExtentChanged()));
95  connect(m_navigatorDlg->getWidget(), SIGNAL(pointPicked(double, double)), this, SLOT(onPointPicked(double, double)));
96 
97 // configure page
98  this->setTitle(tr("Mixture Model"));
99  this->setSubTitle(tr("Select the type of mixture model and set their specific parameters."));
100 
101  m_ui->m_removeToolButton->setIcon(QIcon::fromTheme("list-remove"));
102  m_ui->m_acquireToolButton->setIcon(QIcon::fromTheme("wand"));
103 }
104 
106 {
107  m_components.clear();
108 
109  te::common::Free(m_rgbaMark, PATTERN_SIZE);
110 
111  delete m_mark;
112 }
113 
115 {
116  if(m_ui->m_tableWidget->rowCount() == 0)
117  return false;
118 
119  int nBands = m_ui->m_bandTableWidget->rowCount();
120 
121  bool isChecked = false;
122  for(int i = 0; i < nBands; ++i)
123  {
124  QCheckBox* checkBox = (QCheckBox*)m_ui->m_bandTableWidget->cellWidget(i, 0);
125 
126  if(checkBox->isChecked())
127  {
128  isChecked = true;
129  break;
130  }
131  }
132 
133  if(!isChecked)
134  return false;
135 
136  return true;
137 }
138 
140 {
141  m_layer = layer;
142 
143  m_navigatorDlg->set(m_layer);
144 
145  listBands();
146 }
147 
149 {
150  return m_layer;
151 }
152 
154 {
155  int idx = m_ui->m_typeComboBox->currentIndex();
156  int type = m_ui->m_typeComboBox->itemData(idx).toInt();
157 
159 
160  if(type == MIXMODEL_LINEAR)
161  {
162  algoInputParams.m_strategyName = "linear";
163 
165  algoInputParams.setMixtureModelStrategyParams(specificParameters);
166  }
167  else if(type == MIXMODEL_PCA)
168  {
169  algoInputParams.m_strategyName = "pca";
170 
172  algoInputParams.setMixtureModelStrategyParams(specificParameters);
173  }
174 
175 // insert selected bands
176  unsigned selectedBands = 0;
177  std::vector<bool> selectedBandsVector;
178 
179  for (int i = 0; i < m_ui->m_bandTableWidget->rowCount(); ++i)
180  {
181  QCheckBox* bandCheckBox = (QCheckBox*) m_ui->m_bandTableWidget->cellWidget(i, 0);
182 
183  if (bandCheckBox->isChecked())
184  {
185  selectedBandsVector.push_back(true);
186  selectedBands++;
187 
188  algoInputParams.m_inputRasterBands.push_back(i);
189 
190  QComboBox *sensorComboBox = (QComboBox*) m_ui->m_bandTableWidget->cellWidget(i, 1);
191  algoInputParams.m_inputSensorBands.push_back(std::string(sensorComboBox->currentText().toStdString()));
192  }
193  else
194  selectedBandsVector.push_back(false);
195  }
196 
197 // insert mixture components
198  std::map<std::string, MixModelComponent>::iterator it = m_components.begin();
199  std::vector<double> components;
200 
201  while(it != m_components.end())
202  {
203  components.clear();
204 
205  for (unsigned int i = 0; i < selectedBandsVector.size(); i++)
206  if (selectedBandsVector[i])
207  components.push_back(it->second.m_values[i]);
208 
209  algoInputParams.m_components[it->second.m_name] = components;
210 
211  ++it;
212  }
213 
214 
215  return algoInputParams;
216 }
217 
219 {
221 
222  algoOutputParams.m_normalizeOutput = m_ui->m_normalizeOutputCheckBox->isChecked();
223  algoOutputParams.m_createErrorRaster = m_ui->m_createErrorRasterCheckBox->isChecked();
224 
225  return algoOutputParams;
226 }
227 
229 {
230  if(m_components.empty() == false)
231  drawMarks();
232 }
233 
235 {
236  assert(m_layer.get());
237 
238  //get input raster
239  std::auto_ptr<te::da::DataSet> ds = m_layer->getData();
240 
241  if(ds.get())
242  {
243  std::size_t rpos = te::da::GetFirstPropertyPos(ds.get(), te::dt::RASTER_TYPE);
244  std::auto_ptr<te::rst::Raster> inputRst = ds->getRaster(rpos);
245 
246  if(inputRst.get())
247  {
248  te::gm::Coord2D pixelLocation = inputRst->getGrid()->geoToGrid(x, y);
249 
250  int currentColumn = pixelLocation.x;
251  int currentRow = pixelLocation.y;
252 
253  if (currentColumn < 0 || currentColumn >= (int) inputRst->getNumberOfColumns())
254  return;
255  if (currentRow < 0 || currentRow >= (int) inputRst->getNumberOfRows())
256  return;
257 
258  //component id
259  static boost::uuids::basic_random_generator<boost::mt19937> gen;
260  boost::uuids::uuid u = gen();
261  std::string id = boost::uuids::to_string(u);
262 
263  //component name
264  QString className = QString(tr("Component ") + QString::number(m_countComponents++));
265 
266  //component values
267  std::vector<double> componentsVector;
268 
269  double value;
270  for(unsigned b = 0 ; b < inputRst->getNumberOfBands(); b++)
271  {
272  inputRst->getValue(currentColumn, currentRow, value, b);
273 
274  componentsVector.push_back(value);
275  }
276 
277  //component coordinate
278  te::gm::Coord2D coordinateGrid(currentColumn, currentRow);
279  te::gm::Coord2D coordinateGeo(x, y);
280 
281  MixModelComponent mmc;
282  mmc.m_id = id;
283  mmc.m_name = className.toStdString();
284  mmc.m_values = componentsVector;
285  mmc.m_coordGrid = coordinateGrid;
286  mmc.m_coordGeo = coordinateGeo;
287 
288  m_components.insert(std::map<std::string, MixModelComponent >::value_type(id, mmc));
289 
290  updateComponents();
291  }
292  }
293 }
294 
296 {
297  std::string id = item->data(Qt::UserRole).toString().toStdString();
298 
299  std::string name = item->text().toStdString();
300 
301  std::map<std::string, MixModelComponent >::iterator it = m_components.find(id);
302 
303  bool update = false;
304 
305  if(it != m_components.end())
306  {
307  if(it->second.m_name != name)
308  {
309  it->second.m_name = name;
310  update = true;
311  }
312  }
313 
314  if(update)
315  updateComponents();
316 }
317 
319 {
320  if(m_ui->m_tableWidget->currentRow() == -1)
321  return;
322 
323  std::string id = m_ui->m_tableWidget->item(m_ui->m_tableWidget->currentRow(), 0)->data(Qt::UserRole).toString().toStdString();
324 
325  std::map<std::string, MixModelComponent >::iterator it = m_components.find(id);
326 
327  if(it != m_components.end())
328  {
329  m_components.erase(it);
330 
331  if(m_components.empty())
332  m_countComponents = 0;
333 
334  updateComponents();
335  }
336 }
337 
339 {
340  if(show)
341  m_navigatorDlg->show();
342  else
343  m_navigatorDlg->hide();
344 }
345 
347 {
348  m_ui->m_acquireToolButton->setChecked(false);
349 }
350 
352 {
353  m_ui->m_typeComboBox->clear();
354 
355  m_ui->m_typeComboBox->addItem(tr("Linear"), MIXMODEL_LINEAR);
356  m_ui->m_typeComboBox->addItem(tr("PCA - Principal Component Analysis"), MIXMODEL_PCA);
357 }
358 
360 {
361  assert(m_layer.get());
362 
363  //get input raster
364  std::auto_ptr<te::da::DataSet> ds = m_layer->getData();
365 
366  if(ds.get())
367  {
368  std::size_t rpos = te::da::GetFirstPropertyPos(ds.get(), te::dt::RASTER_TYPE);
369  std::auto_ptr<te::rst::Raster> inputRst = ds->getRaster(rpos);
370 
371  if(inputRst.get())
372  {
373  // define sensor information
374  QStringList sensorsDescriptions;
375  std::vector<std::string> bandNames = te::rp::GetBandNames();
376 
377  for(unsigned int i = 0; i < bandNames.size(); i++)
378  sensorsDescriptions.append(bandNames[i].c_str());
379 
380  m_ui->m_bandTableWidget->setRowCount(0);
381 
382  // initializing the list of bands
383  for(unsigned b = 0 ; b < inputRst->getNumberOfBands(); b++)
384  {
385  int newrow = m_ui->m_bandTableWidget->rowCount();
386  m_ui->m_bandTableWidget->insertRow(newrow);
387 
388  QString bName(tr("Band "));
389  bName.append(QString::number(b));
390 
391  QCheckBox* bandCheckBox = new QCheckBox(bName, this);
392 
393  //if(inputRst->getNumberOfBands() == 1)
394  bandCheckBox->setChecked(true);
395 
396  QComboBox* sensorDescriptionComboBox = new QComboBox(this);
397  sensorDescriptionComboBox->addItems(sensorsDescriptions);
398 
399  m_ui->m_bandTableWidget->setCellWidget(newrow, 0, bandCheckBox);
400  m_ui->m_bandTableWidget->setCellWidget(newrow, 1, sensorDescriptionComboBox);
401  }
402 
403  m_ui->m_bandTableWidget->resizeColumnToContents(0);
404  }
405  }
406 }
407 
409 {
410  te::qt::widgets::MapDisplay* mapDisplay = m_navigatorDlg->getWidget()->getDisplay();
411 
412  mapDisplay->getDraftPixmap()->fill(QColor(0, 0, 0, 0));
413 
414  const te::gm::Envelope& mapExt = mapDisplay->getExtent();
415 
416  te::qt::widgets::Canvas canvasInstance(mapDisplay->getDraftPixmap());
417  canvasInstance.setWindow(mapExt.m_llx, mapExt.m_lly, mapExt.m_urx, mapExt.m_ury);
418 
419  canvasInstance.setPointPattern(m_rgbaMark, PATTERN_SIZE, PATTERN_SIZE);
420 
421  std::map<std::string, MixModelComponent>::iterator it = m_components.begin();
422 
423  while(it != m_components.end())
424  {
425  te::gm::Coord2D cGeo = it->second.m_coordGeo;
426 
427  te::gm::Point point;
428  point.setX(cGeo.x);
429  point.setY(cGeo.y);
430 
431  canvasInstance.draw(&point);
432 
433  ++it;
434  }
435 
436  mapDisplay->repaint();
437 }
438 
440 {
441  m_ui->m_tableWidget->setRowCount(0);
442 
443  std::map<std::string, MixModelComponent>::iterator it = m_components.begin();
444 
445  while(it != m_components.end())
446  {
447  int newrow = m_ui->m_tableWidget->rowCount();
448  m_ui->m_tableWidget->insertRow(newrow);
449 
450  //name
451  QTableWidgetItem* itemName = new QTableWidgetItem(QString::fromStdString(it->second.m_name));
452  itemName->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable);
453  itemName->setData(Qt::UserRole, QVariant(it->second.m_id.c_str()));
454  m_ui->m_tableWidget->setItem(newrow, 0, itemName);
455 
456  //values
457  QComboBox* combo = new QComboBox(m_ui->m_tableWidget);
458 
459  for(size_t t = 0; t < it->second.m_values.size(); ++t)
460  {
461  combo->addItem(QString::number(it->second.m_values[t]));
462  }
463 
464  m_ui->m_tableWidget->setCellWidget(newrow, 1, combo);
465 
466  ////coord x
467  //QTableWidgetItem* itemCoordX = new QTableWidgetItem(QString::number(it->second.m_coordGeo.x));
468  //itemCoordX->setFlags(Qt::ItemIsEnabled);
469  //m_ui->m_tableWidget->setItem(newrow, 2, itemCoordX);
470 
471  ////coord y
472  //QTableWidgetItem* itemCoordY = new QTableWidgetItem(QString::number(it->second.m_coordGeo.y));
473  //itemCoordY->setFlags(Qt::ItemIsEnabled);
474  //m_ui->m_tableWidget->setItem(newrow, 3, itemCoordY);
475 
476  ////coord x
477  //QTableWidgetItem* itemCoordC = new QTableWidgetItem(QString::number(it->second.m_coordGrid.x));
478  //itemCoordC->setFlags(Qt::ItemIsEnabled);
479  //m_ui->m_tableWidget->setItem(newrow, 4, itemCoordC);
480 
481  ////coord y
482  //QTableWidgetItem* itemCoordL = new QTableWidgetItem(QString::number(it->second.m_coordGrid.y));
483  //itemCoordL->setFlags(Qt::ItemIsEnabled);
484  //m_ui->m_tableWidget->setItem(newrow, 5, itemCoordL);
485 
486  ++it;
487  }
488 
489  m_ui->m_tableWidget->sortByColumn(0, Qt::AscendingOrder);
490 
491  drawMarks();
492 
493  emit completeChanged();
494 }
This file defines a class for a MixtureModel Wizard page.
double y
y-coordinate.
Definition: Coord2D.h:87
This class is a dialog for the RasterNavigator widget.
double x
x-coordinate.
Definition: Coord2D.h:86
te::rp::MixtureModel::InputParameters getInputParams()
std::auto_ptr< te::qt::widgets::RasterNavigatorDialog > m_navigatorDlg
std::vector< std::string > GetBandNames()
Returns a vector os with band's names.
Definition: Functions.cpp:557
double m_urx
Upper right corner x-coordinate.
Definition: Envelope.h:346
std::vector< std::string > m_inputSensorBands
The names of the sensor/bands.
Definition: MixtureModel.h:110
A widget to control the display of a set of layers.
Definition: MapDisplay.h:65
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
std::string m_strategyName
The mixture model strategy name see each te::rp::MixtureModelStrategyFactory inherited classes docume...
Definition: MixtureModel.h:112
This file defines a class for a Raster Navigator Dialog.
MixtureModel input parameters.
Definition: MixtureModel.h:69
void Free(std::vector< T * > *v)
This function can be applied to a pointer to a vector of pointers.
Definition: STLUtils.h:131
void setWindow(const double &llx, const double &lly, const double &urx, const double &ury)
It sets the world (or window) coordinates area (supposing a cartesian reference system).
Definition: Canvas.cpp:147
double m_llx
Lower left corner x-coordinate.
Definition: Envelope.h:344
static MarkRendererManager & getInstance()
It returns a reference to the singleton instance.
bool m_normalizeOutput
A flag to indicate that output raster will be normalized, by default [0, 255].
Definition: MixtureModel.h:153
A point with x and y coordinate values.
Definition: Point.h:50
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:51
std::auto_ptr< Ui::MixtureModelWizardPageForm > m_ui
virtual const te::gm::Envelope & getExtent() const
It returns the world extent showned by the MapDisplay.
Definition: MapDisplay.cpp:63
void set(te::map::AbstractLayerPtr layer)
This method is used to set the selected layer for mixture model operation.
A Fill specifies the pattern for filling an area geometry.
Definition: Fill.h:59
TESEEXPORT Mark * CreateMark(const std::string &wellKnownName, Stroke *stroke, Fill *fill)
Creates a mark.
Definition: Utils.cpp:130
double m_lly
Lower left corner y-coordinate.
Definition: Envelope.h:345
TESEEXPORT Stroke * CreateStroke(const std::string &color, const std::string &width)
Creates a stroke.
Definition: Utils.cpp:54
A canvas built on top of Qt.
Definition: Canvas.h:54
te::rp::MixtureModel::OutputParameters getOutputParams()
std::map< std::string, std::vector< double > > m_components
A set of endmembers and its radiances.
Definition: MixtureModel.h:111
MixtureModel output parameters.
Definition: MixtureModel.h:123
void setX(const double &x)
It sets the Point x-coordinate value.
Definition: Point.h:143
virtual QPixmap * getDraftPixmap() const
It returns the map display draft pixmap.
Definition: MapDisplay.cpp:226
double m_ury
Upper right corner y-coordinate.
Definition: Envelope.h:347
A Stroke specifies the appearance of a linear geometry.
Definition: Stroke.h:67
#define PATTERN_SIZE
void setMixtureModelStrategyParams(const StrategyParameters &p)
Set specific mixture model strategy parameters.
This file has the RasterNavigatorWidget class.
TEDATAACCESSEXPORT std::size_t GetFirstPropertyPos(const te::da::DataSet *dataset, int datatype)
Definition: Utils.cpp:432
void setY(const double &y)
It sets the Point y-coordinate value.
Definition: Point.h:157
bool m_createErrorRaster
A flag to indicate that output raster will include the error bands.
Definition: MixtureModel.h:154
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
std::vector< unsigned int > m_inputRasterBands
Bands to be processed from the input raster.
Definition: MixtureModel.h:109
TESEEXPORT Fill * CreateFill(const std::string &color, const std::string &opacity)
Creates a fill.
Definition: Utils.cpp:109