MixtureModelWizard.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 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/MixtureModelWizard.cpp
22 
23  \brief A Qt dialog that allows users to run a mixture model operation defined by RP module.
24 */
25 
26 // TerraLib
27 #include "../../../dataaccess/dataset/DataSet.h"
28 #include "../../../dataaccess/utils/Utils.h"
29 #include "../../../raster/Raster.h"
30 #include "../../../maptools/RasterContrast.h"
31 #include "../../../maptools/Utils.h"
32 #include "../../../rp/Contrast.h"
33 #include "../../../rp/Functions.h"
34 #include "../../../rp/MixtureModel.h"
35 #include "../../../rp/Module.h"
36 #include "../help/HelpPushButton.h"
37 #include "../layer/search/LayerSearchWidget.h"
38 #include "../layer/search/LayerSearchWizardPage.h"
39 #include "../raster/RasterInfoWidget.h"
40 #include "MixtureModelWizard.h"
41 #include "MixtureModelWizardPage.h"
42 #include "RasterInfoWizardPage.h"
43 #include "Utils.h"
44 
45 // STL
46 #include <cassert>
47 
48 // Qt
49 #include <QApplication>
50 #include <QMessageBox>
51 #include <QActionGroup>
52 
53 //STL
54 #include <memory>
55 
56 
58  : QWizard(parent)
59 {
60  //configure the wizard
61  this->setWizardStyle(QWizard::ModernStyle);
62  this->setWindowTitle(tr("Mixture Model"));
63 
64  this->setOption(QWizard::HaveHelpButton, true);
65  this->setOption(QWizard::HelpButtonOnRight, false);
66 
68 
69  this->setButton(QWizard::HelpButton, helpButton);
70 
71  helpButton->setPageReference("plugins/rp/rp_mixture.html");
72 
73  connect(this, SIGNAL(currentIdChanged(int)), SLOT(onPageChanged(int)));
74 
75  addPages();
76 }
77 
79 {
80  m_mixtureModelPage->clearCanvas();
81 }
82 
84 {
85  if(currentPage() == m_layerSearchPage.get())
86  {
87  std::list<te::map::AbstractLayerPtr> list = m_layerSearchPage->getSearchWidget()->getSelecteds();
88 
89  if(list.empty() == false)
90  {
91  m_mixtureModelPage->set(list);
92  }
93 
94  return m_layerSearchPage->isComplete();
95  }
96  else if(currentPage() == m_mixtureModelPage.get())
97  {
98  return m_mixtureModelPage->isComplete();
99  }
100  else if(currentPage() == m_rasterInfoPage.get())
101  {
102  return execute();
103  }
104 
105  return true;
106 }
107 
108 std::list<te::map::AbstractLayerPtr> te::qt::widgets::MixtureModelWizard::getOutputLayers()
109 {
110  return m_outputLayerList;
111 }
112 
113 void te::qt::widgets::MixtureModelWizard::setList(std::list<te::map::AbstractLayerPtr>& layerList)
114 {
115  m_layerSearchPage->getSearchWidget()->setList(layerList);
116  m_layerSearchPage->getSearchWidget()->filterOnlyByRaster();
117 }
118 
120 {
121  m_mixtureModelPage->setMapDisplay(mapDisplay);
122 }
123 
125 {
126  m_mixtureModelPage->setActionGroup(actionGroup);
127 }
128 
129 void te::qt::widgets::MixtureModelWizard::setLayer(std::list<te::map::AbstractLayerPtr> layers)
130 {
131  removePage(m_layerSearchId);
132 
133  m_mixtureModelPage->set(layers);
134 }
135 
137 {
138  m_mixtureModelPage->onMapDisplayExtentChanged();
139 }
140 
142 {
146 
147  m_layerSearchId = addPage(m_layerSearchPage.get());
148  addPage(m_mixtureModelPage.get());
149  addPage(m_rasterInfoPage.get());
150 
151  //for contrast only one layer can be selected
152  m_layerSearchPage->getSearchWidget()->enableMultiSelection(false);
153 }
154 
156 {
157  std::vector<unsigned int> inputRasterBands;
158  unsigned int nbands = 0;
159 
160  //get output parameters
161  std::string outputDataSetNamePath = m_rasterInfoPage->getWidget()->getPath();
162  std::string outputDataSetNamePrefix = m_rasterInfoPage->getWidget()->getShortName();
163  std::string outputDataSetNameExt = m_rasterInfoPage->getWidget()->getExtension();
164  std::string type = m_rasterInfoPage->getWidget()->getType();
165  std::vector< std::map<std::string, std::string> > outputRastersInfos;
166 
167  //set output names
168  std::vector<std::string> outputDataSetNames;
169  std::map<std::string, std::vector<double> >::iterator it;
170  for (it = algoInputParams.m_components.begin(); it != algoInputParams.m_components.end(); it++)
171  {
172  std::string name = outputDataSetNamePrefix;
173  name += "_";
174  name += it->first;
175  name += outputDataSetNameExt;
176 
177  outputDataSetNames.push_back(name);
178 
179  std::map<std::string, std::string> rinfo;
180 
181  std::string fileName =
182  outputDataSetNamePath
183  + std::string("/")
184  + name;
185  rinfo["URI"] = fileName;
186 
187  outputRastersInfos.push_back(rinfo);
188  inputRasterBands.push_back(nbands++);
189  }
190  if (algoOutputParams.m_createErrorRaster)
191  {
192  for (it = algoInputParams.m_components.begin(); it != algoInputParams.m_components.end(); it++)
193  {
194  std::string name = outputDataSetNamePrefix;
195  name += "_error_";
196  name += it->first;
197  name += outputDataSetNameExt;
198 
199  outputDataSetNames.push_back(name);
200  std::map<std::string, std::string> rinfo;
201 
202  std::string fileName =
203  outputDataSetNamePath
204  + std::string("/")
205  + name;
206  rinfo["URI"] = fileName;
207 
208  outputRastersInfos.push_back(rinfo);
209  inputRasterBands.push_back(nbands++);
210  }
211  }
212 
213  std::vector< boost::shared_ptr< te::rst::Raster > > outputRastersPtrs;
214 
215  bool res = false;
216 
217  try
218  {
219  res = te::rp::DecomposeBands(*algoOutputParams.m_outputRasterPtr, inputRasterBands, outputRastersInfos, type, outputRastersPtrs);
220  }
221  catch (const std::exception& e)
222  {
223  QMessageBox::warning(this, tr("Mixture Model - Decompose"), e.what());
224  QApplication::restoreOverrideCursor();
225  outputRastersPtrs.clear();
226  return false;
227  }
228  catch (...)
229  {
230  QMessageBox::warning(this, tr("Mixture Model - Decompose"), tr("An exception has occurred!"));
231  QApplication::restoreOverrideCursor();
232  outputRastersPtrs.clear();
233  return false;
234  }
235 
236  QApplication::restoreOverrideCursor();
237 
238  //create layer
239  if (res)
240  {
241  outputRastersPtrs.clear();
242  std::string type = m_rasterInfoPage->getWidget()->getType();
243 
244  for (std::size_t t = 0; t < outputRastersInfos.size(); ++t)
245  {
246  std::map<std::string, std::string> rinfo = outputRastersInfos[t];
248  m_outputLayerList.push_back(layer);
249  }
250  }
251  return res;
252 }
253 
255 {
256  if(m_rasterInfoPage->getWidget()->fileExists())
257  {
258  QMessageBox::warning(this, tr("Mixture Model"), tr("File already exists."));
259  return false;
260  }
261 
262  //get layer
263  std::list<te::map::AbstractLayerPtr> l = m_mixtureModelPage->get();
264  std::list<te::map::AbstractLayerPtr> ::iterator it_l;
265  for (it_l = l.begin(); it_l != l.end(); it_l++)
266  {
267  std::unique_ptr<te::rst::Raster> inputRst(te::map::GetRaster(it_l->get()));
268 
269  //run mixture
270  te::rp::MixtureModel algorithmInstance;
271 
272  te::rp::MixtureModel::InputParameters algoInputParams = m_mixtureModelPage->getInputParams();
273 
274  if( algoInputParams.m_inputRasterBands.size() != algoInputParams.m_components.size() )
275  {
276  QMessageBox::critical(this, tr("Mixture Model"), tr("The number of components must be the same as the number of selected bands"));
277  return false;
278  }
279 
280  algoInputParams.m_inputRasterPtr = inputRst.get();
281  std::map<std::string, std::string> error_rinfo;
282  te::rp::MixtureModel::OutputParameters algoOutputParams = m_mixtureModelPage->getOutputParams();
283  algoOutputParams.m_rInfo = m_rasterInfoPage->getWidget()->getInfo();
284  if (algoOutputParams.m_createErrorRaster)
285  {
286  std::string name_out = algoOutputParams.m_rInfo["URI"];
287  std::size_t pos = name_out.find_last_of('.');
288  name_out.insert(pos, "_Error");
289  error_rinfo.insert(std::pair<std::string, std::string>("URI", name_out));
290  algoOutputParams.m_rInfoError = error_rinfo;
291  }
292  algoOutputParams.m_rType = m_rasterInfoPage->getWidget()->getType();
293  algoInputParams.m_transfMatrix = m_mixtureModelPage->getTransfMatrix();
294 
295  std::vector<double> min;
296  std::vector<double> max;
297 
298  QApplication::setOverrideCursor(Qt::WaitCursor);
299 
300  if(algorithmInstance.initialize(algoInputParams))
301  {
302  if(algorithmInstance.execute(algoOutputParams))
303  {
304  min = algoOutputParams.m_min;
305  max = algoOutputParams.m_max;
306  if (error_rinfo.size())
307  {
308  for (size_t i = 0; i < algoOutputParams.m_minerror.size(); ++i)
309  {
310  min.push_back(algoOutputParams.m_minerror[i]);
311  max.push_back(algoOutputParams.m_maxerror[i]);
312  }
313  }
314 
315  //set output layer
316  if (m_mixtureModelPage->isDecompose())
317  {
318  decompose(algoInputParams, algoOutputParams);
319  }
320  else
321  {
322  algoOutputParams.reset();
323  m_outputLayerList.push_back(te::qt::widgets::createLayer(m_rasterInfoPage->getWidget()->getType(),
324  m_rasterInfoPage->getWidget()->getInfo()));
325  if (error_rinfo.size())
326  m_outputLayerList.push_back(te::qt::widgets::createLayer(m_rasterInfoPage->getWidget()->getType(),
327  error_rinfo));
328  }
329 
330  QApplication::restoreOverrideCursor();
331 
332  int addOutPutLayer = QMessageBox::question(this, tr("Mixture Model"), tr("Would you like to add layer on active project?"),
333  QMessageBox::Yes | QMessageBox::No);
334 
335  if (addOutPutLayer == QMessageBox::Yes)
336  {
337  std::list<te::map::AbstractLayerPtr>::iterator itl;
338  size_t nlayer = 0;
339  for (itl = m_outputLayerList.begin(); itl != m_outputLayerList.end(); ++itl, ++nlayer)
340  {
341  te::map::AbstractLayerPtr outputlayer = *itl;
342 
343  te::qt::widgets::applyRasterMultiResolution(tr("Mixture Model"), te::map::GetRaster(outputlayer.get()));
344 
346 
347  (outputlayer.get())->setRasterContrast(contrast);
348  for (size_t b = 0; b < te::map::GetRaster(outputlayer.get())->getNumberOfBands(); ++b)
349  {
350  double gain, offset1, offset2;
351  if (te::rp::Contrast::getGainAndOffset(te::rp::Contrast::InputParameters::LinearContrastT, min[b + nlayer], max[b + nlayer], 0., 255., gain, offset1, offset2))
352  {
353  contrast->setValues(gain, offset1, offset2, min[b], max[b], b);
354  }
355  }
356 
357  emit addLayer(outputlayer);
358  }
359  }
360  }
361  else
362  {
363  QApplication::restoreOverrideCursor();
364 
365  QMessageBox::critical(this, tr("Mixture Model"), tr("Mixture Model execution error.") +
366  ( " " + algorithmInstance.getErrorMessage() ).c_str() );
367 
368  return false;
369  }
370  }
371  else
372  {
373  QApplication::restoreOverrideCursor();
374  QMessageBox::critical(this, tr("Mixture Model"), tr( "Mixture Model initialization error." ) +
375  ( " " + algorithmInstance.getErrorMessage() ).c_str() );
376 
377  return false;
378  }
379  }
380 
381  QApplication::restoreOverrideCursor();
382 
383  return true;
384 }
385 
387 {
388  this->adjustSize();
389 }
const std::string & getErrorMessage() const
Return the current error message if there is any.
std::vector< double > m_min
Minimun value calculeted in output raster.
Definition: MixtureModel.h:163
std::unique_ptr< te::qt::widgets::LayerSearchWizardPage > m_layerSearchPage
void setValues(const double &gain, const double &offset1, const double &offset2, const double &min, const double &max, const std::size_t &band)
It set the transformation values for contranst of one band.
This file defines a class for a MixtureModel Wizard page.
Raster decomposition using mixture model.
Definition: MixtureModel.h:62
void addLayer(te::map::AbstractLayerPtr layer)
std::map< std::string, std::string > m_rInfoError
The necessary information to create the error raster (as described in te::raster::RasterFactory).
Definition: MixtureModel.h:158
std::string m_rType
Output raster data source type (as described in te::raster::RasterFactory ).
Definition: MixtureModel.h:154
std::list< te::map::AbstractLayerPtr > getOutputLayers()
void setPageReference(const QString &ref)
Sets the documentation page reference.
static bool getGainAndOffset(const InputParameters::ContrastType &type, const double &inRangeMin, const double &inRangeMax, const double &outRangeMin, const double &outRangeMax, double &gain, double &offset1, double &offset2)
Returns gain and offset values for contrast types (when applicable).
void setList(std::list< te::map::AbstractLayerPtr > &layerList)
A widget to control the display of a set of layers.
void setMapDisplay(te::qt::widgets::MapDisplay *mapDisplay)
bool DecomposeBands(const te::rst::Raster &inputRaster, const std::vector< unsigned int > &inputRasterBands, const std::vector< std::map< std::string, std::string > > &outputRastersInfos, const std::string &outputDataSourceType, std::vector< boost::shared_ptr< te::rst::Raster > > &outputRastersPtrs)
Decompose a multi-band raster into a set of one-band rasters.
This file defines a class for a Raster Info Wizard page.
This class is GUI used to define the mixture model parameters for the RP constast operation...
void setActionGroup(QActionGroup *actionGroup)
A Qt dialog that allows users to run a mixture model operation defined by RP module.
bool decompose(te::rp::MixtureModel::InputParameters &algoInputParams, te::rp::MixtureModel::OutputParameters &algoOutputParams)
std::map< std::string, std::string > m_rInfo
The necessary information to create the output raster (as described in te::raster::RasterFactory).
Definition: MixtureModel.h:155
MixtureModel input parameters.
Definition: MixtureModel.h:72
int b
Definition: TsRtree.cpp:32
std::unique_ptr< te::qt::widgets::MixtureModelWizardPage > m_mixtureModelPage
std::vector< double > m_max
Maximum value calculeted in output raster.
Definition: MixtureModel.h:164
std::vector< double > m_minerror
Minimun value calculeted in output raster.
Definition: MixtureModel.h:165
This class is GUI used to define the raster info parameters for raster factory.
std::vector< double > m_maxerror
Maximum value calculeted in output raster.
Definition: MixtureModel.h:166
Utility functions for the data access module.
This class contains the parameters needed to apply dynamic contrast over a raster.
TEMAPEXPORT te::rst::Raster * GetRaster(AbstractLayer *layer)
It gets the raster referenced by the given data set layer.
std::map< std::string, std::vector< double > > m_components
A set of endmembers and its radiances.
Definition: MixtureModel.h:114
MixtureModel output parameters.
Definition: MixtureModel.h:127
TEQTWIDGETSEXPORT te::map::AbstractLayerPtr createLayer(const std::string &driverName, const te::core::URI &connInfo)
Push button that uses te::qt::widgets::HelpManager on its mouse pressed implementation.
bool execute(AlgorithmOutputParameters &outputParams)
Executes the mixing model using the parameters defined in inputParams and outputParams.
std::unique_ptr< te::rst::Raster > m_outputRasterPtr
A pointer to the generated output raster, one band per component plus one error band per component (w...
Definition: MixtureModel.h:156
std::unique_ptr< te::qt::widgets::RasterInfoWizardPage > m_rasterInfoPage
boost::numeric::ublas::matrix< double > m_transfMatrix
Used transformation matrix (when applicable).
Definition: MixtureModel.h:117
void setLayer(std::list< te::map::AbstractLayerPtr > layers)
te::rst::Raster const * m_inputRasterPtr
Input raster.
Definition: MixtureModel.h:111
bool m_createErrorRaster
A flag to indicate that output raster will include the error bands.
Definition: MixtureModel.h:162
bool initialize(const AlgorithmInputParameters &inputParams)
Initializes model with paramters defined in inputParams.
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
std::vector< unsigned int > m_inputRasterBands
Bands to be processed from the input raster.
Definition: MixtureModel.h:112
TEQTWIDGETSEXPORT void applyRasterMultiResolution(const QString &toolName, te::rst::Raster *raster)
std::list< te::map::AbstractLayerPtr > m_outputLayerList