1 """!@brief Interface between qgisForm and function_historical_map.py
2 ./***************************************************************************
5 Mapping old landcover (specially forest) from historical maps
9 copyright : (C) 2016 by Karasiak & Lomellini
10 email : karasiak.nicolas@gmail.com
11 ***************************************************************************/
13 /***************************************************************************
15 * This program is free software; you can redistribute it and/or modify *
16 * it under the terms of the GNU General Public License as published by *
17 * the Free Software Foundation; either version 2 of the License, or *
18 * (at your option) any later version. *
20 ***************************************************************************/
23 from PyQt4
import QtGui
24 from PyQt4.QtGui
import QAction, QIcon, QFileDialog, QDialog
25 from PyQt4.QtCore
import QSettings, QTranslator, qVersion, QCoreApplication
27 import function_historical_map
as fhm
31 from historical_map_dialog
import HistoricalMapDialog
34 from qgis.core
import QgsMessageLog
38 """!@brief QGIS Plugin Implementation."""
41 """!@brief Constructor.
43 param iface: An interface instance that will be passed to this class
44 which provides the hook by which you can manipulate the QGIS
45 application at run time.
46 type iface: QgsInterface
48 declare all fields to fill, such as output raster, columns to find from a shp...
50 QDialog.__init__(self)
51 sender = self.sender()
55 legendInterface = self.iface.legendInterface()
60 locale = QSettings().value(
'locale/userLocale')[0:2]
61 locale_path = os.path.join(
64 'HistoricalMap_{}.qm'.format(locale))
66 if os.path.exists(locale_path):
68 self.translator.load(locale_path)
70 if qVersion() >
'4.3.3':
71 QCoreApplication.installTranslator(self.
translator)
74 self.
dlg = HistoricalMapDialog()
77 self.
menu = self.
tr(
u'&Historical Map')
79 self.
toolbar = self.iface.addToolBar(
u'HistoricalMap')
80 self.toolbar.setObjectName(
u'HistoricalMap')
84 self.dlg.outRaster.clear()
86 self.dlg.outModel.clear()
88 self.dlg.outMatrix.clear()
91 self.dlg.btnFilter.clicked.connect(self.
runFilter)
92 self.dlg.btnTrain.clicked.connect(self.
runTrain)
93 self.dlg.btnClassify.clicked.connect(self.
runClassify)
94 self.dlg.inModel.clear()
96 self.dlg.outShp.clear()
102 self.dlg.inTraining.currentIndexChanged[int].connect(self.
onChangedLayer)
106 self.dlg.inField.clear()
107 if self.dlg.inField.currentText() ==
'' and self.dlg.inTraining.currentLayer()
and self.dlg.inTraining.currentLayer()!=
'NoneType':
108 activeLayer = self.dlg.inTraining.currentLayer()
109 provider = activeLayer.dataProvider()
110 fields = provider.fields()
111 listFieldNames = [field.name()
for field
in fields]
112 self.dlg.inField.addItems(listFieldNames)
116 """!@brief If active layer is changed, change column combobox"""
118 self.dlg.inField.clear()
120 if self.dlg.inField.currentText() ==
'' and self.dlg.inTraining.currentLayer()
and self.dlg.inTraining.currentLayer()!=
'NoneType':
121 activeLayer = self.dlg.inTraining.currentLayer()
122 provider = activeLayer.dataProvider()
123 fields = provider.fields()
124 listFieldNames = [field.name()
for field
in fields]
125 self.dlg.inField.addItems(listFieldNames)
130 def tr(self, message):
131 """!@brief Get the translation for a string using Qt translation API.
133 We implement this ourselves since we do not inherit QObject.
135 :param message: String for translation.
136 :type message: str, QString
138 :returns: Translated version of message.
142 return QCoreApplication.translate(
'HistoricalMap', message)
156 """Add a toolbar icon to the toolbar.
158 :param icon_path: Path to the icon for this action. Can be a resource
159 path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
162 :param text: Text that should be shown in menu items for this action.
165 :param callback: Function to be called when the action is triggered.
166 :type callback: function
168 :param enabled_flag: A flag indicating if the action should be enabled
169 by default. Defaults to True.
170 :type enabled_flag: bool
172 :param add_to_menu: Flag indicating whether the action should also
173 be added to the menu. Defaults to True.
174 :type add_to_menu: bool
176 :param add_to_toolbar: Flag indicating whether the action should also
177 be added to the toolbar. Defaults to True.
178 :type add_to_toolbar: bool
180 :param status_tip: Optional text to show in a popup when mouse pointer
181 hovers over the action.
182 :type status_tip: str
184 :param parent: Parent widget for the new action. Defaults None.
185 :type parent: QWidget
187 :param whats_this: Optional text to show in the status bar when the
188 mouse pointer hovers over the action.
190 :returns: The action that was created. Note that the action is also
191 added to self.actions list.
195 icon = QIcon(icon_path)
196 action = QAction(icon, text, parent)
197 action.triggered.connect(callback)
198 action.setEnabled(enabled_flag)
200 if status_tip
is not None:
201 afilenamection.setStatusTip(status_tip)
203 if whats_this
is not None:
204 action.setWhatsThis(whats_this)
207 self.toolbar.addAction(action)
210 self.iface.addPluginToRasterMenu(
214 self.actions.append(action)
219 """!@brief Create the menu entries and toolbar icons inside the QGIS GUI."""
221 icon_path =
':/plugins/HistoricalMap/icon.png'
224 text=self.
tr(
u'Select historical map'),
226 parent=self.iface.mainWindow())
230 """!@brief Removes the plugin menu item and icon from QGIS GUI."""
232 self.iface.removePluginRasterMenu(
233 self.
tr(
u'&Historical Map'),
235 self.iface.removeToolBarIcon(action)
240 """!@brief Select file to save, and gives the right extension if the user don't put it"""
241 sender = self.sender()
243 fileName = QFileDialog.getSaveFileName(self.
dlg,
"Select output file")
250 fileName,fileExtension=os.path.splitext(fileName)
251 if sender == self.dlg.selectRaster:
252 if fileExtension!=
'.tif':
253 self.dlg.outRaster.setText(fileName+
'.tif')
255 self.dlg.outRaster.setText(fileName+fileExtension)
256 elif sender == self.dlg.selectModel:
257 self.dlg.outModel.setText(fileName+fileExtension)
258 elif sender == self.dlg.selectMatrix:
259 if fileExtension!=
'.csv':
260 self.dlg.outMatrix.setText(fileName+
'.csv')
262 self.dlg.outMatrix.setText(fileName+fileExtension)
263 elif sender == self.dlg.selectOutShp:
264 if fileExtension!=
'.shp':
265 self.dlg.outShp.setText(fileName+
'.shp')
267 self.dlg.outShp.setText(fileName+fileExtension)
268 elif sender == self.dlg.selectModelStep3:
269 self.dlg.inModel.setText(fileName)
272 """!@brief Select file to load in the field"""
274 fileName = QFileDialog.getOpenFileName(self.
dlg,
"Select your file",
"")
277 if sender == self.dlg.selectModelStep3:
278 self.dlg.inModel.setText(fileName)
283 """!@brief Performs the filtering of the map by calling function_historical_map.py
285 First step is validating the form, then if all is ok, proceed to the filtering.
289 inRaster=self.dlg.inRaster.currentLayer()
290 inRaster=inRaster.dataProvider().dataSourceUri()
291 rasterName,rasterExt=os.path.splitext(inRaster)
292 if not rasterExt ==
'.tif' or rasterExt ==
'.tiff':
293 message =
"You have to specify a tif in image to filter. You tried to had a "+rasterExt
296 message=
"Impossible to load raster"
297 if self.dlg.outRaster.text()==
'':
298 message =
"Sorry, you have to specify as output raster"
301 QtGui.QMessageBox.warning(self,
'Information missing or invalid', message, QtGui.QMessageBox.Ok)
310 inShapeGrey=self.dlg.inShapeGrey.value()
311 inShapeMedian=self.dlg.inShapeMedian.value()
312 outRaster=self.dlg.outRaster.text()
313 iterMedian=self.dlg.inShapeMedianIter.value()
317 fhm.historicalFilter(inRaster,outRaster,inShapeGrey,inShapeMedian,iterMedian)
320 self.iface.messageBar().pushMessage(
"New image",
"Filter with "+str(inShapeGrey)+
' closing size and '+str(inShapeMedian)+
' median size', 3, 10)
321 self.iface.addRasterLayer(outRaster)
325 """!@brief Performs the training by calling function_historical_map.py
327 First step is validating the form, then if all is ok, proceed to the training.
328 Tell the user who don't have sklearn they can't use classifier except GMM.
333 Open a popup to show where the matrix or the model is saved
337 if self.dlg.outModel.text()==
'':
338 message =
"Sorry, you have to specify as model name"
339 if self.dlg.outMatrix.text()==
'':
340 message =
"Sorry, you have to specify as matrix name"
341 if not self.dlg.inClassifier.currentText()==
'GMM':
345 message =
"It seems you don't have Scitkit-Learn on your computer. You can only use GMM classifier. Please consult the documentation for more information"
348 QtGui.QMessageBox.warning(self,
'Information missing or invalid', message, QtGui.QMessageBox.Ok)
353 inFiltered=self.dlg.inFiltered.currentLayer()
354 inFiltered=inFiltered.dataProvider().dataSourceUri()
355 inTraining=self.dlg.inTraining.currentLayer()
358 inTraining=inTraining.dataProvider().dataSourceUri().split(
'|')[0]
361 inClassifier=self.dlg.inClassifier.currentText()
362 outModel=self.dlg.outModel.text()
363 outMatrix=self.dlg.outMatrix.text()
365 inField=self.dlg.inField.currentText()
366 inSeed=self.dlg.inSeed.value()
368 inSplit=self.dlg.inSplit.value()
371 self.dlg.inModel.setText(outModel)
373 fhm.learnModel(inFiltered,inTraining,inField,inSplit,inSeed,outModel,outMatrix,inClassifier)
376 if self.dlg.outMatrix.text()!=
'':
377 QtGui.QMessageBox.information(self,
"Information",
"Training is done!<br>Confusion matrix saved at "+str(outMatrix)+
".")
379 QtGui.QMessageBox.information(self,
"Information",
"Model is done!<br>Model saved at "+str(outModel)+
", and matrix at"+str(outMatrix)+
".")
383 """!@brief Performs the classification by calling function_historical_map.py
384 Method that performs the classification
386 First step is validating the form, then if all is ok, proceed to the classification.
389 if self.dlg.inModel.text()==
'':
390 message =
"Sorry, you have to specify a model"
391 if self.dlg.outShp.text()==
'':
392 message =
"Sorry, you have to specify a vector field to save the results"
393 if not os.path.splitext(self.dlg.outShp.text())[1]==
'.shp':
394 message =
"Sorry, you have to specify a *.shp type in output"
396 QtGui.QMessageBox.warning(self,
'Information missing or invalid', message, QtGui.QMessageBox.Ok)
401 inFilteredStep3=self.dlg.inFilteredStep3.currentLayer()
402 inFilteredStep3=str(inFilteredStep3.dataProvider().dataSourceUri())
405 inModel=str(self.dlg.inModel.text())
410 inMinSize=int(self.dlg.inMinSize.value()*10000)
412 outShp=str(self.dlg.outShp.text())
413 inClassForest=int(self.dlg.inClassForest.value())
417 classify=fhm.classifyImage()
418 classifyProgress=fhm.progressBar(
'Classifying image...',3)
422 temp=classify.initPredict(inFilteredStep3,inModel)
424 QgsMessageLog.logMessage(
"Problem while predicting image")
426 classifyProgress.addStep()
430 temp=classify.rasterMod(temp,int(inClassForest))
432 QgsMessageLog.logMessage(
"Problem while rastering filtering")
434 classifyProgress.addStep()
438 temp=classify.vectorMod(temp,inMinSize,outShp)
440 QgsMessageLog.logMessage(
"Problem while vectorizing filtering")
442 classifyProgress.addStep()
445 layerName=os.path.basename(os.path.splitext(temp)[0])
446 self.iface.addVectorLayer(temp,layerName,
'ogr')
447 self.iface.messageBar().pushMessage(
"New vector : ",outShp, 3, duration=10)
448 classifyProgress.reset()
451 QgsMessageLog.logMessage(
"Problem while classifying "+inFilteredStep3+
" with model "+inModel)
452 QtGui.QMessageBox.warning(self,
'Problem while classifying',
'Something went wrong, please show log. If your system is Windows, we\'re working on it', QtGui.QMessageBox.Ok)
453 classifyProgress.reset()
QGIS Plugin Implementation.
def onChangedLayer
If active layer is changed, change column combobox.
def runClassify
Performs the classification by calling function_historical_map.py Method that performs the classifica...
def runTrain
Performs the training by calling function_historical_map.py.
def unload
Removes the plugin menu item and icon from QGIS GUI.
def initGui
Create the menu entries and toolbar icons inside the QGIS GUI.
def select_load_file
Select file to load in the field.
def tr
Get the translation for a string using Qt translation API.
def runFilter
Performs the filtering of the map by calling function_historical_map.py.
def select_output_file
Select file to save, and gives the right extension if the user don't put it.