PCAWizard.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 #include "PCAWizard.h"
21 
22 //Terralib
23 #include "../../../dataaccess/utils/Utils.h"
24 #include "../../../rp/Functions.h"
25 #include "../../../common/StringUtils.h"
26 #include "../../../raster/Band.h"
27 #include "../../../raster/BandProperty.h"
28 #include "../../../raster/RasterFactory.h"
29 #include "../../../raster/Grid.h"
30 #include "../help/HelpPushButton.h"
31 #include "../layer/search/LayerSearchWidget.h"
32 #include "../layer/search/LayerSearchWizardPage.h"
33 #include "../progress/ProgressViewerDialog.h"
34 #include "../utils/ScopedCursor.h"
35 #include "PCAWizardPage.h"
36 #include "../raster/RasterInfoWidget.h"
37 #include "RasterInfoWizardPage.h"
38 #include "Utils.h"
39 
40 #include <boost/lexical_cast.hpp>
41 
42 // Qt
43 #include <QApplication>
44 #include <QMessageBox>
45 
46 #include <fstream>
47 #include <cstdio>
48 #include <cmath>
49 
51 QWizard(parent)
52 {
53  this->setWizardStyle(QWizard::ModernStyle);
54  this->setWindowTitle(tr("Raster Slicing"));
55 
56  this->setOption(QWizard::HaveHelpButton, true);
57  this->setOption(QWizard::HelpButtonOnRight, false);
58 
60 
61  this->setButton(QWizard::HelpButton, helpButton);
62 
63  helpButton->setPageReference("plugins/rp/rp_pca.html");
64 
65  connect(this, SIGNAL(currentIdChanged(int)), SLOT(onPageChanged(int)));
66 
67  addPages();
68 }
69 
71 
73 {
74  if(currentPage() == m_layerSearchPage.get())
75  {
76  te::qt::widgets::ScopedCursor cursor(Qt::WaitCursor);
77  std::list<te::map::AbstractLayerPtr> list = m_layerSearchPage->getSearchWidget()->getSelecteds();
78 
79  if(list.empty() == false)
80  {
81  te::map::AbstractLayerPtr layerPtr = *list.begin();
82 
83  if( layerPtr.get() != nullptr )
84  m_wizardPage->setLayer(layerPtr);
85  }
86 
87  return m_layerSearchPage->isComplete();
88  }
89  else if(currentPage() == m_wizardPage.get())
90  {
91  return m_wizardPage->isComplete();
92  }
93  else if(currentPage() == m_rasterInfoPage.get())
94  {
95  return execute();
96  }
97 
98  return true;
99 }
100 
101 void te::qt::widgets::PCAWizard::setList(std::list<te::map::AbstractLayerPtr> &layerList)
102 {
103  m_layerSearchPage->getSearchWidget()->setList(layerList);
104  m_layerSearchPage->getSearchWidget()->filterOnlyByRaster();
105 }
106 
108 {
109  return m_outputLayer;
110 }
111 
113 {
114  m_layerSearchPage.reset(new LayerSearchWizardPage(this));
115  m_layerSearchPage->getSearchWidget()->enableMultiSelection(false);
116  addPage(m_layerSearchPage.get());
117 
118  m_wizardPage.reset(new PCAWizardPage(this));
119  addPage(m_wizardPage.get());
120 
122  addPage(m_rasterInfoPage.get());
123 
124  this->resize(m_wizardPage->sizeHint());
125 }
126 
128 {
129  m_wizardPage->setLayer( layer );
130 }
131 
133 {
134  if(m_rasterInfoPage->getWidget()->fileExists())
135  {
136  QMessageBox::warning(this, tr("PCA"), tr("File already exists."));
137  return false;
138  }
139 
140  //get layer
141 
142  std::list<te::map::AbstractLayerPtr> list = m_layerSearchPage->getSearchWidget()->getSelecteds();
143  te::map::AbstractLayerPtr l = *list.begin();
144 
145  // input raster
146 
147  std::unique_ptr<te::rst::Raster> inputRst;
148 
149  {
150  //get input raster
151  std::unique_ptr<te::da::DataSet> ds = l->getData();
152 
153  if (ds.get() == nullptr )
154  {
155  QMessageBox::critical(this, tr("PCA"), tr("Invalid layer.") );
156  return false;
157  }
158 
159  std::size_t rpos = te::da::GetFirstPropertyPos(ds.get(), te::dt::RASTER_TYPE);
160 
161  inputRst = ds->getRaster(rpos);
162  }
163 
164  const std::vector< unsigned int > inputRasterBands = m_wizardPage->getSelectedBands();
165 
166  if( inputRasterBands.empty() )
167  {
168  QMessageBox::critical(this, tr("PCA"), tr("No selected bands.") );
169  return false;
170  }
171 
172  // matrix
173 
174  const std::string matrixFileName = m_wizardPage->getMatrixFileName();
175 
176  if( m_wizardPage->inversePCASelected() && matrixFileName.empty() )
177  {
178  QMessageBox::critical(this, tr("PCA"), tr("Invalid matrix file name.") );
179  return false;
180  }
181 
182  std::fstream matrixFile;
183  boost::numeric::ublas::matrix< double > matrix;
184 
185  if( m_wizardPage->inversePCASelected() )
186  {
187  matrixFile.open( matrixFileName.c_str(), std::fstream::in );
188  if( !matrixFile.good() )
189  {
190  QMessageBox::critical(this, tr("PCA"), tr("Invalid matrix file.") );
191  return false;
192  }
193 
194  matrixFile.seekg( 0 );
195 
196  std::string lineStr;
197  std::getline( matrixFile, lineStr );
198 
199  std::vector< std::string > tokens;
200  te::common::Tokenize( lineStr, tokens, ";" );
201 
202  const std::size_t matrixSize = (std::size_t)std::sqrt( tokens.size() );
203  std::size_t tokensIdx = 0;
204 
205  matrix.resize( matrixSize, matrixSize );
206 
207  for( std::size_t row = 0 ; row < matrixSize ; ++row )
208  {
209  for( std::size_t col = 0 ; col < matrixSize ; ++col )
210  {
211  if( tokensIdx >= tokens.size() )
212  {
213  QMessageBox::critical(this, tr("PCA"), tr("Invalid matrix file.") );
214  return false;
215  }
216 
217  matrix( row, col ) = boost::lexical_cast< double >( tokens[ tokensIdx ] );
218  ++tokensIdx;
219  }
220  }
221  }
222  else
223  {
224  if( ! matrixFileName.empty() )
225  {
226  matrixFile.open( matrixFileName.c_str(), std::fstream::out | std::fstream::trunc );
227 
228  if( !matrixFile.good() )
229  {
230  QMessageBox::critical(this, tr("PCA"), tr("Invalid matrix file.") );
231  return false;
232  }
233  }
234  }
235 
236  // output raster
237 
238  std::unique_ptr<te::rst::Raster> outputRasterPtr;
239  std::vector< unsigned int > outputRasterBands;
240 
241  {
242  std::vector< te::rst::BandProperty * > bandProps;
243 
244  for( unsigned int bandIdx = 0 ; bandIdx < inputRasterBands.size() ;
245  ++bandIdx )
246  {
247  bandProps.push_back( new te::rst::BandProperty(
248  *( inputRst->getBand( inputRasterBands[ bandIdx ] )->getProperty() ) ) );
249  bandProps.back()->m_type = m_wizardPage->getOutputRasterDataType();
250  bandProps.back()->m_blkh = bandProps.front()->m_blkh;
251  bandProps.back()->m_blkw = bandProps.front()->m_blkw;
252  bandProps.back()->m_nblocksx = bandProps.front()->m_nblocksx;
253  bandProps.back()->m_nblocksy = bandProps.front()->m_nblocksy;
254 
255  outputRasterBands.push_back( bandIdx );
256  }
257 
258  try
259  {
260  outputRasterPtr.reset( te::rst::RasterFactory::make(
261  m_rasterInfoPage->getWidget()->getType(),
262  new te::rst::Grid( *( inputRst->getGrid() ) ), bandProps,
263  m_rasterInfoPage->getWidget()->getInfo(), nullptr, nullptr ) );
264  }
265  catch(...)
266  {
267  outputRasterPtr.reset();
268  }
269 
270  if( outputRasterPtr.get() == nullptr )
271  {
272  QMessageBox::critical(this, tr("PCA"), tr("Output raster creation error.") );
273  return false;
274  }
275  }
276 
277  // Execute
278 
279  QApplication::setOverrideCursor(Qt::WaitCursor);
280 
281  if( m_wizardPage->inversePCASelected() )
282  {
283  // inverse PCA
284 
285  if( ! te::rp::InversePrincipalComponents( *inputRst, matrix, *outputRasterPtr,
286  outputRasterBands, 0 ) )
287  {
288  QMessageBox::critical(this, tr("PCA"), tr("PCA processing error.") );
289 
290  QApplication::restoreOverrideCursor();
291 
292  return false;
293  }
294  }
295  else
296  {
297  // direct PCA
298 
299  if( ! te::rp::DirectPrincipalComponents( *inputRst, inputRasterBands, matrix,
300  *outputRasterPtr, outputRasterBands, 0 ) )
301  {
302  QMessageBox::critical(this, tr("PCA"), tr("PCA processing error.") );
303 
304  QApplication::restoreOverrideCursor();
305 
306  return false;
307  }
308 
309  for( std::size_t row = 0 ; row < matrix.size1() ; ++row )
310  {
311  for( std::size_t col = 0 ; col < matrix.size2() ; ++col )
312  {
313  matrixFile << boost::lexical_cast< std::string >( matrix( row, col ) );
314  matrixFile << ";";
315  }
316  }
317  }
318 
319  QApplication::restoreOverrideCursor();
320 
321  //set output layer
322 
323  outputRasterPtr.reset();
324 
326  m_rasterInfoPage->getWidget()->getInfo());
327 
328  QMessageBox::information(this, tr("PCA"), tr("PCA ended sucessfully"));
329 
330  return true;
331 }
332 
334 {
335  this->adjustSize();
336 }
PCAWizard(QWidget *parent=0)
Constructor.
Definition: PCAWizard.cpp:50
A raster band description.
Definition: BandProperty.h:61
void setPageReference(const QString &ref)
Sets the documentation page reference.
std::unique_ptr< te::qt::widgets::LayerSearchWizardPage > m_layerSearchPage
The wizard page used to select an input layer.
Definition: PCAWizard.h:104
static te::dt::Date ds(2010, 01, 01)
bool DirectPrincipalComponents(const te::rst::Raster &inputRaster, const std::vector< unsigned int > &inputRasterBands, boost::numeric::ublas::matrix< double > &pcaMatrix, te::rst::Raster &pcaRaster, const std::vector< unsigned int > &pcaRasterBands, const unsigned int maxThreads)
Generate all principal components from the given input raster.
This file defines a class for a Raster Info Wizard page.
void Tokenize(const std::string &str, std::vector< std::string > &tokens, const std::string &delimiters=" ")
It tokenizes a given string with a delimiter of your own choice.
Definition: StringUtils.h:221
This class is GUI used to define the raster info parameters for raster factory.
te::map::AbstractLayerPtr m_outputLayer
Definition: PCAWizard.h:108
void setList(std::list< te::map::AbstractLayerPtr > &layerList)
This function sets the list of layers from which the raster that will be sliced will come from...
Definition: PCAWizard.cpp:101
bool validateCurrentPage()
Overridden function that checks if the current page&#39;s configuration is done in order to proceed to th...
Definition: PCAWizard.cpp:72
Utility functions for the data access module.
void onPageChanged(int index)
Definition: PCAWizard.cpp:333
std::unique_ptr< te::qt::widgets::RasterInfoWizardPage > m_rasterInfoPage
The wizard page used to define the output layer parameters.
Definition: PCAWizard.h:105
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.
static Raster * make()
It creates and returns an empty raster with default raster driver.
te::map::AbstractLayerPtr getOutputLayer()
This function returns the layer that has been created by the wizard with the sliced raster...
Definition: PCAWizard.cpp:107
bool InversePrincipalComponents(const te::rst::Raster &pcaRaster, const boost::numeric::ublas::matrix< double > &pcaMatrix, te::rst::Raster &outputRaster, const std::vector< unsigned int > &outputRasterBands, const unsigned int maxThreads)
Regenerate the original raster from its principal components.
void setLayer(te::map::AbstractLayerPtr layer)
This function sets the layer that contains the raster that will be sliced.
Definition: PCAWizard.cpp:127
std::unique_ptr< te::qt::widgets::PCAWizardPage > m_wizardPage
The wizard page used to define the PCA parameters.
Definition: PCAWizard.h:103
TEDATAACCESSEXPORT std::size_t GetFirstPropertyPos(const te::da::DataSet *dataset, int datatype)
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
unsigned int col
An object that when created shows a cursor during its scope.
Definition: ScopedCursor.h:48